From 641f3d83c2b5a4c402cdc8bc3ed1baa5336d404d 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.0b7@4306 a1ca3aef-8c08-0410-bb20-df032aa958be --- LICENSE.html | 386 +++ Makedefs.in | 138 + Makefile | 76 + README.txt | 195 ++ backend/Makefile | 119 + backend/ipp.c | 399 +++ backend/lpd.c | 393 +++ backend/parallel.c | 179 ++ backend/serial.c | 297 +++ backend/smb.sh | 88 + backend/socket.c | 232 ++ berkeley/Makefile | 95 + berkeley/lpc.c | 458 ++++ berkeley/lpq.c | 369 +++ berkeley/lpr.c | 252 ++ berkeley/lprm.c | 205 ++ cgi-bin/Makefile | 83 + cgi-bin/classes.c | 484 ++++ cgi-bin/jobs.c | 584 +++++ cgi-bin/printers.c | 486 ++++ conf/Makefile | 68 + conf/classes.conf | 72 + conf/cupsd.conf | 369 +++ conf/cupsd.conf-personal | 250 ++ conf/cupsd.conf-professional | 313 +++ conf/mime.convs | 62 + conf/mime.types | 122 + conf/printers.conf | 89 + config.h.in | 101 + configure.in | 316 +++ cups.dsw | 113 + cups.sh | 112 + cups/Makefile | 150 ++ cups/cups.dsp | 176 ++ cups/cups.h | 143 ++ cups/cups_C.h | 123 + cups/debug.h | 57 + cups/emit.c | 301 +++ cups/filter.c | 297 +++ cups/http.c | 1446 +++++++++++ cups/http.h | 291 +++ cups/ipp.c | 1459 +++++++++++ cups/ipp.h | 343 +++ cups/language.c | 373 +++ cups/language.h | 195 ++ cups/mark.c | 412 +++ cups/mime.c | 617 +++++ cups/mime.h | 137 + cups/options.c | 378 +++ cups/page.c | 189 ++ cups/ppd.c | 1769 +++++++++++++ cups/ppd.h | 239 ++ cups/raster.c | 252 ++ cups/raster.h | 233 ++ 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/usersys.c | 175 ++ cups/util.c | 986 +++++++ data/Makefile | 56 + doc/Makefile | 109 + doc/cmp.html | 651 +++++ doc/cmp.pdf | 963 +++++++ doc/cmp.shtml | 717 ++++++ doc/cups.css | 4 + doc/cupsdoc.css | 9 + doc/documentation.html | 70 + doc/figures.sc | Bin 0 -> 51020 bytes doc/idd.html | 746 ++++++ doc/idd.pdf | 1577 ++++++++++++ doc/idd.shtml | 1219 +++++++++ doc/images/classes.gif | Bin 0 -> 591 bytes 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 -> 18985 bytes doc/sam.html | 873 +++++++ doc/sam.pdf | 1114 ++++++++ doc/sam.shtml | 1038 ++++++++ doc/sdd.html | 473 ++++ doc/sdd.pdf | 989 +++++++ doc/sdd.shtml | 567 ++++ doc/ssr.html | 221 ++ doc/ssr.pdf | 446 ++++ doc/ssr.shtml | 252 ++ doc/stp.html | 145 ++ doc/stp.pdf | Bin 0 -> 22085 bytes doc/stp.shtml | 169 ++ doc/sum.html | 511 ++++ doc/sum.pdf | 949 +++++++ doc/sum.shtml | 562 ++++ doc/svd.html | 149 ++ doc/svd.pdf | Bin 0 -> 21933 bytes doc/svd.shtml | 167 ++ filter/Makefile | 150 ++ filter/common.c | 252 ++ 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.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 | 743 ++++++ filter/image.h | 223 ++ filter/imagetops.c | 494 ++++ filter/imagetoraster.c | 3839 ++++++++++++++++++++++++++++ filter/pstops.c | 804 ++++++ filter/rastertohp.c | 493 ++++ filter/textcommon.c | 745 ++++++ filter/textcommon.h | 89 + filter/texttops.c | 568 ++++ fonts/AvantGarde-Book | Bin 0 -> 25994 bytes fonts/AvantGarde-BookOblique | Bin 0 -> 26882 bytes fonts/AvantGarde-Demi | Bin 0 -> 26980 bytes fonts/AvantGarde-DemiOblique | Bin 0 -> 27530 bytes fonts/Bookman-Demi | Bin 0 -> 35453 bytes fonts/Bookman-DemiItalic | Bin 0 -> 35218 bytes fonts/Bookman-Light | Bin 0 -> 35522 bytes fonts/Bookman-LightItalic | Bin 0 -> 34617 bytes fonts/Courier | Bin 0 -> 35719 bytes fonts/Courier-Bold | Bin 0 -> 38284 bytes fonts/Courier-BoldOblique | Bin 0 -> 40686 bytes fonts/Courier-Oblique | Bin 0 -> 34677 bytes fonts/Helvetica | Bin 0 -> 27505 bytes fonts/Helvetica-Bold | Bin 0 -> 26762 bytes fonts/Helvetica-BoldOblique | Bin 0 -> 28971 bytes fonts/Helvetica-Narrow | Bin 0 -> 27406 bytes fonts/Helvetica-Narrow-Bold | Bin 0 -> 27960 bytes fonts/Helvetica-Narrow-BoldOblique | Bin 0 -> 29384 bytes fonts/Helvetica-Narrow-Oblique | Bin 0 -> 28298 bytes fonts/Helvetica-Oblique | Bin 0 -> 28397 bytes fonts/Makefile | 68 + fonts/NewCenturySchlbk-Bold | Bin 0 -> 38763 bytes fonts/NewCenturySchlbk-BoldItalic | Bin 0 -> 38742 bytes fonts/NewCenturySchlbk-Italic | Bin 0 -> 38413 bytes fonts/NewCenturySchlbk-Roman | Bin 0 -> 37561 bytes fonts/Palatino-Bold | Bin 0 -> 41591 bytes fonts/Palatino-BoldItalic | Bin 0 -> 40387 bytes fonts/Palatino-Italic | Bin 0 -> 39917 bytes fonts/Palatino-Roman | Bin 0 -> 42328 bytes fonts/Symbol | Bin 0 -> 32213 bytes fonts/Times-Bold | Bin 0 -> 34996 bytes fonts/Times-BoldItalic | Bin 0 -> 36325 bytes fonts/Times-Italic | Bin 0 -> 37139 bytes fonts/Times-Roman | Bin 0 -> 35161 bytes fonts/Utopia-Bold | Bin 0 -> 36580 bytes fonts/Utopia-BoldItalic | Bin 0 -> 37836 bytes fonts/Utopia-Italic | Bin 0 -> 37599 bytes fonts/Utopia-Regular | Bin 0 -> 36350 bytes fonts/ZapfChancery-MediumItalic | Bin 0 -> 38422 bytes fonts/ZapfDingbats | Bin 0 -> 44537 bytes locale/C/cups_C | 123 + locale/Makefile | 73 + locale/de/cups_de | 123 + locale/en/cups_en | 123 + locale/es/cups_es | 123 + locale/fr/cups_fr | 123 + locale/it/cups_it | 123 + locale/locale.txt | 32 + locale/translate.c | 259 ++ man/Makefile | 78 + man/accept.8 | 57 + man/accept.z | Bin 0 -> 905 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 | 64 + man/enable.z | Bin 0 -> 940 bytes man/filter.1 | 95 + man/filter.z | Bin 0 -> 1683 bytes man/lp.1 | 71 + man/lp.z | Bin 0 -> 836 bytes man/lpadmin.8 | 124 + man/lpadmin.z | Bin 0 -> 2514 bytes man/lpc.8 | 79 + man/lpc.z | Bin 0 -> 1264 bytes man/lpr.1 | 96 + man/lpr.z | Bin 0 -> 1451 bytes man/lprm.1 | 40 + man/lprm.z | Bin 0 -> 414 bytes man/lpstat.1 | 115 + man/lpstat.z | Bin 0 -> 1983 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 ppd/Makefile | 55 + ppd/deskjet.ppd | 186 ++ ppd/laserjet.ppd | 172 ++ pstoraster/Fontmap | 98 + pstoraster/Makefile | 167 ++ 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 | 196 ++ pstoraster/gconfigv.h | 3 + pstoraster/gdebug.h | 117 + pstoraster/gdevabuf.c | 355 +++ pstoraster/gdevcups.c | 2459 ++++++++++++++++++ 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 | 1271 +++++++++ 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 | 644 +++++ 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 | 1523 +++++++++++ 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 | 347 +++ 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 | 476 ++++ 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 | 1034 ++++++++ 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 | 320 +++ pstoraster/pdf_font.ps | 374 +++ pstoraster/pdf_main.ps | 478 ++++ pstoraster/pdf_sec.ps | 58 + pstoraster/pfbtogs.ps | 117 + pstoraster/pstoraster.c | 196 ++ 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 | 41 + pstoraster/sdctd.c | 282 ++ pstoraster/sdcte.c | 173 ++ 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 | 274 ++ pstoraster/sjpegd.c | 91 + pstoraster/sjpege.c | 107 + pstoraster/sjpegerr.c | 97 + 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 | 48 + pstoraster/szlibd.c | 90 + pstoraster/szlibe.c | 90 + 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 | 372 +++ pstoraster/zfdctd.c | 103 + pstoraster/zfdcte.c | 270 ++ 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 | 101 + 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 | 82 + scheduler/auth.c | 602 +++++ scheduler/auth.h | 108 + scheduler/classes.c | 522 ++++ scheduler/classes.h | 43 + scheduler/client.c | 1507 +++++++++++ scheduler/client.h | 94 + scheduler/conf.c | 1189 +++++++++ scheduler/conf.h | 112 + scheduler/cupsd.h | 161 ++ scheduler/dirsvc.c | 544 ++++ scheduler/dirsvc.h | 58 + scheduler/ipp.c | 2421 ++++++++++++++++++ scheduler/job.c | 971 +++++++ scheduler/job.h | 75 + scheduler/listen.c | 142 + scheduler/main.c | 422 +++ scheduler/printers.c | 1035 ++++++++ scheduler/printers.h | 81 + scheduler/testspeed.c | 126 + systemv/Makefile | 114 + systemv/accept.c | 218 ++ systemv/cancel.c | 220 ++ systemv/lp.c | 246 ++ systemv/lpadmin.c | 1147 +++++++++ systemv/lpstat.c | 1268 +++++++++ 737 files changed, 193960 insertions(+) create mode 100644 LICENSE.html create mode 100644 Makedefs.in create mode 100644 Makefile create mode 100644 README.txt create mode 100644 backend/Makefile create mode 100644 backend/ipp.c create mode 100644 backend/lpd.c create mode 100644 backend/parallel.c create mode 100644 backend/serial.c create mode 100755 backend/smb.sh create mode 100644 backend/socket.c create mode 100644 berkeley/Makefile create mode 100644 berkeley/lpc.c create mode 100644 berkeley/lpq.c create mode 100644 berkeley/lpr.c create mode 100644 berkeley/lprm.c create mode 100644 cgi-bin/Makefile create mode 100644 cgi-bin/classes.c create mode 100644 cgi-bin/jobs.c 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/cupsd.conf-personal create mode 100644 conf/cupsd.conf-professional 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 100755 cups.sh create mode 100644 cups/Makefile create mode 100644 cups/cups.dsp create mode 100644 cups/cups.h create mode 100644 cups/cups_C.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/usersys.c create mode 100644 cups/util.c create mode 100644 data/Makefile 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/cupsdoc.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/classes.gif 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.pdf 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.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/rastertohp.c create mode 100644 filter/textcommon.c create mode 100644 filter/textcommon.h create mode 100644 filter/texttops.c create mode 100644 fonts/AvantGarde-Book create mode 100644 fonts/AvantGarde-BookOblique create mode 100644 fonts/AvantGarde-Demi create mode 100644 fonts/AvantGarde-DemiOblique create mode 100644 fonts/Bookman-Demi create mode 100644 fonts/Bookman-DemiItalic create mode 100644 fonts/Bookman-Light create mode 100644 fonts/Bookman-LightItalic create mode 100644 fonts/Courier create mode 100644 fonts/Courier-Bold create mode 100644 fonts/Courier-BoldOblique create mode 100644 fonts/Courier-Oblique create mode 100644 fonts/Helvetica create mode 100644 fonts/Helvetica-Bold create mode 100644 fonts/Helvetica-BoldOblique create mode 100644 fonts/Helvetica-Narrow create mode 100644 fonts/Helvetica-Narrow-Bold create mode 100644 fonts/Helvetica-Narrow-BoldOblique create mode 100644 fonts/Helvetica-Narrow-Oblique create mode 100644 fonts/Helvetica-Oblique create mode 100644 fonts/Makefile create mode 100644 fonts/NewCenturySchlbk-Bold create mode 100644 fonts/NewCenturySchlbk-BoldItalic create mode 100644 fonts/NewCenturySchlbk-Italic create mode 100644 fonts/NewCenturySchlbk-Roman create mode 100644 fonts/Palatino-Bold create mode 100644 fonts/Palatino-BoldItalic create mode 100644 fonts/Palatino-Italic create mode 100644 fonts/Palatino-Roman create mode 100644 fonts/Symbol create mode 100644 fonts/Times-Bold create mode 100644 fonts/Times-BoldItalic create mode 100644 fonts/Times-Italic create mode 100644 fonts/Times-Roman create mode 100644 fonts/Utopia-Bold create mode 100644 fonts/Utopia-BoldItalic create mode 100644 fonts/Utopia-Italic create mode 100644 fonts/Utopia-Regular create mode 100644 fonts/ZapfChancery-MediumItalic create mode 100644 fonts/ZapfDingbats 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 locale/translate.c 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 ppd/Makefile create mode 100644 ppd/deskjet.ppd create mode 100644 ppd/laserjet.ppd create mode 100644 pstoraster/Fontmap 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/listen.c create mode 100644 scheduler/main.c create mode 100644 scheduler/printers.c create mode 100644 scheduler/printers.h create mode 100644 scheduler/testspeed.c 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/lpadmin.c create mode 100644 systemv/lpstat.c diff --git a/LICENSE.html b/LICENSE.html new file mode 100644 index 0000000000..7a25722a6e --- /dev/null +++ b/LICENSE.html @@ -0,0 +1,386 @@ + + + Software License Agreement - Common UNIX Printing System + + + + +

Common UNIX Printing System License Agreement

+ +

Copyright 1997-1999 by Easy Software Products
+44141 AIRPORT VIEW DR STE 204
+HOLLYWOOD, MARYLAND 20636-3111 USA
+
+Voice: +1.301.373.9603
+Email: cups-info@cups.org
+WWW: http://www.cups.org + +

Introduction

+ +

The Common UNIX Printing SystemTM, or CUPSTM, +is provided under the GNU General Public License, Version 2. A copy of +this license follows this introduction. + +

For those not familiar with the GNU General Public License, the license +basically allows you to: + +

+ +

What this license does not allow you to do is make changes or +add features to CUPS and then sell a binary distribution without source +code. You have to provide source for any new drivers, changes, or +additions to the software, and all code must be provided under the GPL. + +

Also, since we have trademarked the Common UNIX Printing System, CUPS, +and CUPS logo, you may not release a derivative product using those names +without permission from Easy Software Products. + +

Binary Distribution Rights

+ +

Easy Software Products also sells rights to the CUPS source code +under a binary distribution license for vendors that are unable to +release source code for their drivers or additions and modifications to +CUPS under the GPL. For pricing information please contact us at the +address shown above. + +

The Common UNIX Printing System utilizes GNU GhostScript 4.03 to +convert PostScript files into a stream of raster images. For binary +distribution licensing of this software, please contact: + +

Miles Jones
+Director of Marketing
+Artifex Software Inc.
+454 Las Gallinas Ave., Suite 108
+San Rafael, CA 94903 USA
+Voice: +1.415.492.9861
+Fax: +1.415.492.9862
+EMail: info@arsoft.com +
+ +

Support

+ +

Easy Software Products sells software support for distributors and +resellers of CUPS. Support for users of CUPS is available from Easy +Software Products through our ESP Print software. + +

Trademarks

+ +

The Common UNIX Printing System, CUPS, and the CUPS logo are the +trademark property of Easy Software Products. Any derivative of this +software may not use any of these trademarks without the expressed +written consent of Easy Software Products. + +

GNU General Public License

+ +

Version 2, June 1991
+
+Copyright 1989, 1991 Free Software Foundation, Inc.
+59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +

Everyone is permitted to copy and distribute verbatim +copies of this license document, but changing it is not allowed. + +

Preamble

+ +

The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + +

When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + +

To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + +

For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + +

We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + +

Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + +

Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + +

The precise terms and conditions for copying, distribution and +modification follow. + +

GNU GENERAL PUBLIC LICENSE
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

+ +
    + +
  1. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +

    Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + +

  2. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +

    You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + +

  3. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + +
      + +
    1. You must cause the modified files to carry prominent notices +stating that you changed the files and the date of any change. + +
    2. You must cause any work that you distribute or publish, that in +whole or in part contains or is derived from the Program or any +part thereof, to be licensed as a whole at no charge to all third +parties under the terms of this License. + +
    3. if the modified program normally reads commands interactively +when run, you must cause it, when started running for such +interactive use in the most ordinary way, 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) and that users may redistribute the program under +these conditions, and telling the user how to view a copy of this +License. (Exception: if the Program itself is interactive but +does not normally print such an announcement, your work based on +the Program is not required to print an announcement.) + +
    + +

    These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +

    Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +

    In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + +

  4. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + +
      + +
    1. Accompany it with the complete corresponding machine-readable +source code, which must be distributed under the terms of Sections +1 and 2 above on a medium customarily used for software interchange; or, + +
    2. Accompany it with a written offer, valid for at least three +years, to give any third party, for a charge no more than your +cost of physically performing source distribution, a complete +machine-readable copy of the corresponding source code, to be +distributed under the terms of Sections 1 and 2 above on a medium +customarily used for software interchange; or, + +
    3. Accompany it with the information you received as to the offer +to distribute corresponding source code. (This alternative is +allowed only for noncommercial distribution and only if you +received the program in object code or executable form with such +an offer, in accord with Subsection b above.) + +
    + +

    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. However, as a +special exception, the source code distributed need not include +anything 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, unless that component +itself accompanies the executable. + +

    If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access 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 along with the object code. + +

  5. 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. + +
  6. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, 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. + +
  7. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + +
  8. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +

    If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +

    It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +

    This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + +

  9. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +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. + +
  10. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +

    Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + +

  11. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + +
+ +

NO WARRANTY

+ +
    + +
  1. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 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. + +
  2. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, 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. + +
+ +

END OF TERMS AND CONDITIONS

+ + + diff --git a/Makedefs.in b/Makedefs.in new file mode 100644 index 0000000000..19b96ea12d --- /dev/null +++ b/Makedefs.in @@ -0,0 +1,138 @@ +# +# "$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 +# 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 +# + +# +# Programs... +# + +AR = @AR@ +AWK = @AWK@ +CC = @CC@ +CHMOD = @CHMOD@ +CP = @CP@ +DSO = @DSO@ +HTMLDOC = @HTMLDOC@ +LN = /bin/ln -sf +MKDIR = @MKDIR@ -p +NROFF = @NROFF@ +PACK = @PACK@ +RANLIB = @RANLIB@ +RM = @RM@ -f +SED = @SED@ +SHELL = /bin/sh +SMBCLIENT = @SMBCLIENT@ + +# +# Libraries... +# + +LIBCUPS = @LIBCUPS@ +LIBCUPSIMAGE = @LIBCUPSIMAGE@ +LIBJPEG = @LIBJPEG@ +LIBPNG = @LIBPNG@ +LIBTIFF = @LIBTIFF@ +LIBZ = @LIBZ@ + +# +# 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) +DSOLIBS = @DSOLIBS@ +IMGLIBS = @IMGLIBS@ -lm +LDFLAGS = @LDFLAGS@ $(OPTIM) +LIBS = -L../cups -lcups $(NETLIBS) @LIBS@ +NETLIBS = @NETLIBS@ +OPTIM = @OPTIM@ +OPTIONS = + +# +# Formatted man page extension... +# + +CAT = @CAT@ + +# +# 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) +LIBDIR = $(libdir) +LOCALEDIR = @CUPS_LOCALEDIR@ +MANDIR = @mandir@ +SBINDIR = @sbindir@ +SERVERROOT = @CUPS_SERVERROOT@ + +# +# Rules... +# + +.SILENT: +.SUFFIXES: .a .c .gz .h .o .z .1 .5 .8 +.c.o: + echo Compiling $<... + $(CC) $(CFLAGS) -c $< +.1.z .5.z .8.z .1.gz .5.gz .8.gz: + echo Formatting $<... + $(NROFF) -man $< >t + $(PACK) t + -mv t.$(CAT) $@ + +# +# End of "$Id$" +# diff --git a/Makefile b/Makefile new file mode 100644 index 0000000000..934bf137c8 --- /dev/null +++ b/Makefile @@ -0,0 +1,76 @@ +# +# "$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 +# 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 + +# +# Directories to make... +# + +DIRS = cups backend berkeley cgi-bin filter man pstoraster \ + scheduler systemv + +# +# Make all targets... +# + +all: + for dir in $(DIRS); do\ + echo Making all in $$dir... ;\ + (cd $$dir; make);\ + done + +# +# Remove object and target files... +# + +clean: + for dir in $(DIRS); do\ + echo Cleaning in $$dir... ;\ + (cd $$dir; make clean);\ + done + +# +# Install object and target files... +# + +install: + for dir in $(DIRS); do\ + echo Installing in $$dir... ;\ + (cd $$dir; make install);\ + done + echo Installing in conf... + (cd conf; make install) + echo Installing in data... + (cd data; make install) + echo Installing in doc... + (cd doc; make install) + echo Installing in fonts... + (cd fonts; make install) + echo Installing in ppd... + (cd ppd; make install) + +# +# End of "$Id$". +# diff --git a/README.txt b/README.txt new file mode 100644 index 0000000000..b12e30a94b --- /dev/null +++ b/README.txt @@ -0,0 +1,195 @@ +README - CUPS v1.0b6 - 07/30/1999 +--------------------------------- + +BETA SOFTWARE BETA SOFTWARE BETA SOFTWARE BETA SOFTWARE BETA SOFTWARE + + WARNING - This is a BETA release of CUPS, which means that it may + contain "bugs" that could prevent you from printing. If + you are concerned that this may cause you lost time or + money, please STOP and do not install this software! + +BETA SOFTWARE BETA SOFTWARE BETA SOFTWARE BETA SOFTWARE BETA SOFTWARE + + +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. + +CUPS is Copyright 1993-1999 by Easy Software Products, All Rights +Reserved. CUPS is currently licensed under the terms of the GNU +General Public License. Please see the license file for details. + + +SYSTEM REQUIREMENTS + +Binary distributions require a minimum of 10MB of free disk space. We +do not recommend using CUPS on a workstation with less than 32MB of RAM +or a PC with less than 16MB of RAM. + +If you are installing from source you'll need an ANSI C compiler and +optionally one or more image file support libraries. Complete source +installation instructions can be found in the CUPS System +Administrator's Manual in the files "doc/sam.html" or "doc/sam.pdf". + + +SOFTWARE REQUIREMENTS + +The following operating system software is required to install one of +the binary distributions from Easy Software Products: + + - Digital UNIX (aka OSF1 aka Compaq Tru64 UNIX) 4.0 or higher + - HP-UX 10.20 or higher + - IRIX 5.3 or higher + - Linux 2.0.36 with glibc2 or higher (tested with RedHat 5.2) + - Solaris 2.5 or higher (SPARC or Intel) + + +INSTALLING CUPS + +We are currently distributing CUPS binary distributions in TAR format +with installation and removal scripts generated by our ESP Package +Manager (EPM) software, which is also included with the source +distribution. + +WARNING: Installing CUPS will overwrite your existing printing system. +Backup files are made by the installation script and restored by the +removal script, so if you experience problems you should be able to +remove the CUPS software to restore your previous configuration. +However, Easy Software Products makes no warranty for this and will not +be liable for any lost revenues, etc. + +To install the CUPS software you will need to be logged in as root +(doing an "su" is good enough). Once you are the root user, run the +installation script with: + + ./cups.install ENTER + +After asking you a few yes/no questions the CUPS software will be +installed and the scheduler will be started automatically. + + +SETTING UP PRINTER QUEUES + +CUPS works best with PPD (PostScript Printer Description) files. In a +pinch you can also use System V style printer interface scripts. + +Two sample PPD files are provided with this distribution that utilize +the PostScript and image file RIPs and the sample HP printer driver. +To add the sample DeskJet driver to the system for a printer connected +to the parallel port, use one of the following commands: + + Digital UNIX: + + /usr/lib/lpadmin -p DeskJet -m deskjet.ppd -v parallel:/dev/lp0 -E + + HP-UX: + + /usr/lib/lpadmin -p DeskJet -m deskjet.ppd -v parallel:/dev/c2t0d0_lp -E + + IRIX: + + /usr/lib/lpadmin -p DeskJet -m deskjet.ppd -v parallel:/dev/plp -E + + Linux: + + /usr/lib/lpadmin -p DeskJet -m deskjet.ppd -v parallel:/dev/par0 -E + /usr/lib/lpadmin -p DeskJet -m deskjet.ppd -v parallel:/dev/par1 -E + /usr/lib/lpadmin -p DeskJet -m deskjet.ppd -v parallel:/dev/par2 -E + + Solaris: + + /usr/lib/lpadmin -p DeskJet -m deskjet.ppd -v parallel:/dev/bpp0 -E + /usr/lib/lpadmin -p DeskJet -m deskjet.ppd -v parallel:/dev/ecpp0 -E + +Similarly, for the sample LaserJet driver you can use "LaserJet" and +"laserjet.ppd". + +For other printers and interfaces see the CUPS System Administator's +Manual included with this software. + + +PRINTING FILES + +CUPS provides both the System V "lp" and Berkeley "lpr" commands for +printing: + + lp filename + lpr filename + +Both the "lp" and "lpr" commands support printing options for the +driver: + + lp -omedia=A4 -oresolution=600dpi filename + lpr -omedia=A4 -oresolution=600dpi filename + +CUPS recognizes many types of images files as well as PostScript, HP-GL/2, +and text files, so you can print those files directly rather than through +an application. + +If you have an application that generates output specifically for your +printer then you need to use the "-oraw" or "-l" options: + + lp -oraw filename + lpr -l filename + +This will prevent the filters from misinterpreting your print file. + + +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 GNU General Public License +which is located in the files "LICENSE.html" and "LICENSE.txt" (or the +file "cups.license" for a binary distribution.) 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 Pro software at: + + http://www.easysw.com/printpro diff --git a/backend/Makefile b/backend/Makefile new file mode 100644 index 0000000000..b4915aa5c2 --- /dev/null +++ b/backend/Makefile @@ -0,0 +1,119 @@ +# +# "$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 +# 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 + +TARGETS = ipp lpd parallel serial smb socket +OBJS = ipp.o lpd.o parallel.o serial.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 + -$(LN) ipp $(SERVERROOT)/backend/http + $(CHMOD) u+s $(SERVERROOT)/backend/lpd + +# +# ipp +# + +ipp: ipp.o ../cups/$(LIBCUPS) + echo Linking $@... + $(CC) $(LDFLAGS) -o ipp ipp.o $(LIBS) + -$(LN) ipp http + +ipp.o: ../cups/cups.h ../Makedefs + +# +# lpd +# + +lpd: lpd.o ../cups/$(LIBCUPS) + echo Linking $@... + $(CC) $(LDFLAGS) -o lpd lpd.o $(LIBS) + +lpd.o: ../cups/cups.h ../Makedefs + +# +# parallel +# + +parallel: parallel.o ../cups/$(LIBCUPS) + echo Linking $@... + $(CC) $(LDFLAGS) -o parallel parallel.o $(LIBS) + +parallel.o: ../cups/cups.h ../Makedefs + +# +# serial +# + +serial: serial.o ../cups/$(LIBCUPS) + echo Linking $@... + $(CC) $(LDFLAGS) -o serial serial.o $(LIBS) + +serial.o: ../cups/cups.h ../Makedefs + +# +# smb +# +# Note: reading through these commands is a good way to get a headache... :) +# + +smb: smb.sh ../Makedefs + echo Generating $@... + $(RM) smb + sedcmd="1,\$$s/^SMBCLIENT=.\*/SMBCLIENT=`echo $(SMBCLIENT) | sed -e '1,$$s/\\//\\\\\\//g'`/" ;\ + $(SED) -e "$$sedcmd" smb + $(CHMOD) +x smb + +# +# socket +# + +socket: socket.o ../cups/$(LIBCUPS) + echo Linking $@... + $(CC) $(LDFLAGS) -o socket socket.o $(LIBS) + +socket.o: ../cups/cups.h ../Makedefs + +# +# End of "$Id$". +# diff --git a/backend/ipp.c b/backend/ipp.c new file mode 100644 index 0000000000..297ad393b6 --- /dev/null +++ b/backend/ipp.c @@ -0,0 +1,399 @@ +/* + * "$Id$" + * + * IPP 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 + + +/* + * '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 */ +{ + int i; /* Looping var */ + int n, n2; /* Attribute values */ + char *option, /* Name of option */ + *val, /* Pointer to option value */ + *s; /* Pointer into option value */ + int num_options; /* Number of printer options */ + cups_option_t *options; /* Printer options */ + char method[255], /* Method in URI */ + hostname[1024], /* Hostname */ + username[255], /* Username info */ + resource[1024], /* Resource info (printer name) */ + filename[1024]; /* File to print */ + int port; /* Port number (not used) */ + char password[255], /* Password info */ + uri[HTTP_MAX_URI];/* Updated URI without user/pass */ + http_status_t status; /* Status of HTTP job */ + FILE *fp; /* File to print */ + http_t *http; /* HTTP connection */ + ipp_t *request, /* IPP request */ + *response; /* IPP response */ + ipp_attribute_t *job_id; /* job-id attribute */ + cups_lang_t *language; /* Default language */ + struct stat fileinfo; /* File statistics */ + size_t nbytes, /* Number of bytes written */ + tbytes; /* Total bytes written */ + char buffer[8192]; /* Output buffer */ + + + 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, print stdin... + */ + + if (argc == 6) + fp = stdin; + else if ((fp = fopen(argv[6], "rb")) == NULL) + { + perror("ERROR: Unable to open print file"); + return (1); + } + else + stat(argv[6], &fileinfo); + + /* + * Extract the hostname and printer name from the URI... + */ + + httpSeparate(argv[0], method, username, hostname, &port, resource); + + /* + * Try connecting to the remote server... + */ + + fprintf(stderr, "INFO: Connecting to %s...\n", hostname); + + if ((http = httpConnect(hostname, port)) == NULL) + { + perror("ERROR: Unable to connect to IPP host"); + + if (fp != stdin) + fclose(fp); + return (1); + } + + /* + * Build a URI for the printer and fill the standard IPP attributes for + * an IPP_PRINT_FILE request. We can't use the URI in argv[0] because it + * might contain username:password information... + */ + + request = ippNew(); + request->request.op.operation_id = IPP_PRINT_JOB; + request->request.op.request_id = 1; + + sprintf(uri, "%s://%s:%d%s", method, hostname, port, resource); + + 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); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", + NULL, argv[2]); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL, argv[3]); + + /* + * Handle options on the command-line... + */ + + options = NULL; + num_options = cupsParseOptions(argv[5], 0, &options); + + if (cupsGetOption("raw", num_options, options)) + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format", + NULL, "application/vnd.cups-raw"); + else + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format", + NULL, "application/octet-stream"); + + ippAddInteger(request, IPP_TAG_JOB, IPP_TAG_INTEGER, "copies", atoi(argv[4])); + + 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)... + */ + 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); + } + 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); + } + else + ippAddInteger(request, IPP_TAG_JOB, IPP_TAG_INTEGER, option, n); + } + else + /* + * Boolean value... + */ + ippAddBoolean(request, IPP_TAG_JOB, option, (char)n); + } + + /* + * Now fill in the HTTP request stuff... + */ + + httpClearFields(http); + httpSetField(http, HTTP_FIELD_CONTENT_TYPE, "application/ipp"); + httpEncode64(password, username); + httpSetField(http, HTTP_FIELD_AUTHORIZATION, password); + + if (fp != stdin) + { + sprintf(buffer, "%u", ippLength(request) + (size_t)fileinfo.st_size); + httpSetField(http, HTTP_FIELD_CONTENT_LENGTH, buffer); + } + else + httpSetField(http, HTTP_FIELD_TRANSFER_ENCODING, "chunked"); + + /* + * Do the request... + */ + + for (;;) + { + /* + * POST the request, retrying as needed... + */ + + if (httpPost(http, resource)) + { + fputs("INFO: Unable to POST print request; retrying...\n", stderr); + sleep(10); + httpReconnect(http); + continue; + } + + fputs("INFO: POST successful, sending IPP request...\n", stderr); + + /* + * Send the IPP request... + */ + + request->state = IPP_IDLE; + + if (ippWrite(http, request) == IPP_ERROR) + { + fputs("ERROR: Unable to send IPP request!\n", stderr); + status = HTTP_ERROR; + break; + } + + fputs("INFO: IPP request sent, sending print file...\n", stderr); + + /* + * Then send the file... + */ + + tbytes = 0; + while ((nbytes = fread(buffer, 1, sizeof(buffer), fp)) > 0) + { + tbytes += nbytes; + fprintf(stderr, "INFO: Sending print file, %uk...\n", tbytes / 1024); + + if (httpWrite(http, buffer, nbytes) < nbytes) + { + perror("ERROR: Unable to send print file to printer"); + status = HTTP_ERROR; + break; + } + } + + fputs("INFO: Print file sent; checking status...\n", stderr); + + /* + * Finally, check the status from the HTTP server... + */ + + while ((status = httpUpdate(http)) == HTTP_CONTINUE); + + if (status == HTTP_OK) + { + response = ippNew(); + ippRead(http, response); + + if (response->request.status.status_code > IPP_OK_CONFLICT) + fprintf(stderr, "ERROR: Print file was not accepted (%04x)!\n", + response->request.status.status_code); + else if ((job_id = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER)) == NULL) + fputs("INFO: Print file accepted - job ID unknown.\n", stderr); + else + fprintf(stderr, "INFO: Print file accepted - job ID %d.\n", + job_id->values[0].integer); + } + else + { + response = NULL; + httpFlush(http); + + fprintf(stderr, "ERROR: Print request was not accepted (%d)!\n", status); + } + + break; + } + + /* + * Free memory... + */ + + httpClose(http); + if (request != NULL) + ippDelete(request); + if (response != NULL) + ippDelete(response); + + /* + * Close the print file as needed... + */ + + if (fp != stdin) + fclose(fp); + + /* + * Return the queue status... + */ + + return (status != HTTP_OK); +} + + +/* + * End of "$Id$". + */ diff --git a/backend/lpd.c b/backend/lpd.c new file mode 100644 index 0000000000..3fa4175642 --- /dev/null +++ b/backend/lpd.c @@ -0,0 +1,393 @@ +/* + * "$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 + * 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. + * 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(cupsTempFile(filename, sizeof(filename)), "w")) == NULL) + { + perror("ERROR: unable to create temporary file"); + return (1); + } + + while ((bytes = fread(buffer, 1, sizeof(buffer), stdin)) > 0) + if (fwrite(buffer, 1, bytes, fp) < bytes) + { + perror("ERROR: 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, "DEBUG: 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, "DEBUG: 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("ERROR: unable to stat print file"); + return (1); + } + + if ((fp = fopen(filename, "rb")) == NULL) + { + perror("ERROR: 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)); + localhost[31] = '\0'; /* RFC 1179, Section 7.2 - host name < 32 chars */ + + 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, "DEBUG: Control file is:\n%s", control); + + lpd_command(fd, "\002%d cfA%03.3d%s\n", strlen(control), getpid() % 1000, + localhost); + + fprintf(stderr, "INFO: 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("INFO: Control file sent successfully\n", stderr); + + lpd_command(fd, "\003%u dfA%03.3d%s\n", (unsigned)filestats.st_size, + getpid() % 1000, localhost); + + fprintf(stderr, "INFO: 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("INFO: 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..df74637e62 --- /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 + * 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 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..d9edfe2a2f --- /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 + * 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 + +#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.sh b/backend/smb.sh new file mode 100755 index 0000000000..a0c67aecb3 --- /dev/null +++ b/backend/smb.sh @@ -0,0 +1,88 @@ +#!/bin/sh +# +# "$Id$" +# +# SMB printing script for the Common UNIX Printing System (CUPS). +# +# Copyright 1993-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 +# + +SMBCLIENT=/usr/local/samba/bin/smbclient + +# +# Usage: +# +# printer job user title copies options [filename] +# + +if [ $# -lt 5 -o $# -gt 6 ]; then + # Too few or too many arguments + echo 'Usage: smb job-id user title copies options [file]' >&2 + exit 1 +fi + +# +# If "filename" is not on the command-line, then we read the print +# data from stdin and write it to a temporary file. +# + +if [ $# = 5 ]; then + # Collect all print data and put it in a temporary file... + if [ "$TMPDIR" = "" ]; then + TMPDIR=/var/tmp + fi + + filename="$TMPDIR/$$.smb" + cat >$filename +else + # Use the file on the command-line... + filename="$6" +fi + +# +# Take apart the URI in $0... +# + +uri="$0" +host=`echo $uri | awk -F/ '{print substr($3, index($3, "@") + 1)}'` +user=`echo $uri | awk -F/ '{print substr($3, 0, index($3, "@") - 1)}'` +if [ "$user" != "" ]; then + user="-U $user" +fi +printer=`echo $uri | awk -F/ '{print $4}'` + +# +# Send the file to the remote system... +# + +$SMBCLIENT //$host/$printer $user -P -N < +#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..5ffc54ab2a --- /dev/null +++ b/berkeley/Makefile @@ -0,0 +1,95 @@ +# +# "$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 +# 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 + +TARGETS = lpc lpq lpr lprm +OBJS = lpc.o lpq.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) lpq lpr lprm $(BINDIR) + $(CP) lpc $(SBINDIR) + +# +# lpc +# + +lpc: lpc.o ../cups/$(LIBCUPS) + echo Linking $@... + $(CC) $(LDFLAGS) -o lpc lpc.o $(LIBS) + +lpc.o: ../cups/cups.h ../Makedefs + +# +# lpq +# + +lpq: lpq.o ../cups/$(LIBCUPS) + echo Linking $@... + $(CC) $(LDFLAGS) -o lpq lpq.o $(LIBS) + +lpq.o: ../cups/cups.h ../Makedefs + +# +# lpr +# + +lpr: lpr.o ../cups/$(LIBCUPS) + echo Linking $@... + $(CC) $(LDFLAGS) -o lpr lpr.o $(LIBS) + +lpr.o: ../cups/cups.h ../Makedefs + +# +# lprm +# + +lprm: lprm.o ../cups/$(LIBCUPS) + echo Linking $@... + $(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..cf2fc33423 --- /dev/null +++ b/berkeley/lpc.c @@ -0,0 +1,458 @@ +/* + * "$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(cupsServer(), 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 (fgets(line, sizeof(line), stdin) != NULL) + { + /* + * Strip the trailing newline... + */ + + line[strlen(line) - 1] = '\0'; + + /* + * 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_status(%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_status: 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(); + + 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(printer_uri, "ipp://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/lpq.c b/berkeley/lpq.c new file mode 100644 index 0000000000..55bf7ed6a4 --- /dev/null +++ b/berkeley/lpq.c @@ -0,0 +1,369 @@ +/* + * "$Id$" + * + * "lpq" 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. + * show_jobs() - Show jobs. + */ + +/* + * Include necessary headers... + */ + +/* + * Include necessary headers... + */ + +#include +#include +#include +#include +#include +#include + + +/* + * Local functions... + */ + +static int show_jobs(http_t *, const char *, const char *, const int, + const int); + + +/* + * '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 */ + const char *dest, /* Desired printer */ + *user; /* Desired user */ + int id, /* Desired job ID */ + interval, /* Reporting interval */ + longstatus; /* Show file details */ + + /* + * Connect to the scheduler... + */ + + http = httpConnect(cupsServer(), ippPort()); + + /* + * Check for command-line options... + */ + + dest = cupsGetDefault(); + user = NULL; + id = 0; + interval = 0; + longstatus = 0; + + for (i = 1; i < argc; i ++) + if (argv[i][0] == '+') + interval = atoi(argv[i] + 1); + else if (argv[i][0] == '-') + { + switch (argv[i][1]) + { + case 'P' : /* Printer */ + if (argv[i][2]) + dest = argv[i] + 2; + else + { + i ++; + dest = argv[i]; + } + break; + + case 'l' : /* Long status */ + longstatus = 1; + break; + + default : + fputs("Usage: lpq [-P dest] [-l] [+interval]\n", stderr); + return (1); + } + } + else if (isdigit(argv[i][0])) + id = atoi(argv[i]); + else + user = argv[i]; + + /* + * Show the status in a loop... + */ + + for (;;) + { + i = show_jobs(http, dest, user, id, longstatus); + + if (i && interval) + sleep(interval); + else + break; + } + + /* + * Close the connection to the server and return... + */ + + httpClose(http); + + return (0); +} + + +/* + * 'show_jobs()' - Show jobs. + */ + +static int /* O - Number of jobs in queue */ +show_jobs(http_t *http, /* I - HTTP connection to server */ + const char *dest, /* I - Destination */ + const char *user, /* I - User */ + const int id, /* I - Job ID */ + const int longstatus)/* I - 1 if long report desired */ +{ + ipp_t *request, /* IPP Request */ + *response; /* IPP Response */ + ipp_attribute_t *attr; /* Current attribute */ + cups_lang_t *language; /* Default language */ + const char *jobdest, /* Pointer into job-printer-uri */ + *jobuser, /* Pointer to job-originating-user-name */ + *jobname; /* Pointer to job-name */ + ipp_jstate_t jobstate; /* job-state */ + int jobid, /* job-id */ + jobsize, /* job-k-octets */ + jobpriority, /* job-priority */ + jobcount, /* Number of jobs */ + rank; /* Rank of job */ + char resource[1024]; /* Resource string */ + static const char *ranks[10] =/* Ranking strings */ + { + "th", + "st", + "nd", + "rd", + "th", + "th", + "th", + "th", + "th", + "th" + }; + + + DEBUG_printf(("show_jobs(%08x, %08x, %08x, %d, %d)\n", http, dest, user, id, + longstatus)); + + if (http == NULL) + return (0); + + /* + * Build an IPP_GET_JOBS or IPP_GET_JOB_ATTRIBUTES request, which requires + * the following attributes: + * + * attributes-charset + * attributes-natural-language + * job-uri or printer-uri + * [ + */ + + request = ippNew(); + + request->request.op.operation_id = id ? IPP_GET_JOB_ATTRIBUTES : 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); + + if (dest == NULL) + { + if (id) + sprintf(resource, "ipp://localhost/jobs/%d", id); + else + strcpy(resource, "ipp://localhost/jobs"); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", + NULL, resource); + } + else + { + sprintf(resource, "ipp://localhost/printers/%s", dest); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", + NULL, resource); + } + + if (user) + { + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, + "requesting-user-name", NULL, user); + ippAddBoolean(request, IPP_TAG_OPERATION, "my-jobs", 1); + } + + /* + * Do the request and get back a response... + */ + + if (!longstatus) + puts("Rank\tPri Owner Job Files Total Size"); + + jobcount = 0; + + if ((response = cupsDoRequest(http, request, "/jobs/")) != NULL) + { + rank = 1; + + /* + * Loop through the job list and display them... + */ + + 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_JOB) + attr = attr->next; + + if (attr == NULL) + break; + + /* + * Pull the needed attributes from this job... + */ + + jobid = 0; + jobsize = 0; + jobpriority = 50; + jobstate = IPP_JOB_PENDING; + jobname = "untitled"; + jobuser = NULL; + jobdest = 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) + jobsize = attr->values[0].integer * 1024; + + if (strcmp(attr->name, "job-priority") == 0 && + attr->value_tag == IPP_TAG_INTEGER) + jobpriority = attr->values[0].integer; + + if (strcmp(attr->name, "job-state") == 0 && + attr->value_tag == IPP_TAG_ENUM) + jobstate = (ipp_jstate_t)attr->values[0].integer; + + if (strcmp(attr->name, "job-printer-uri") == 0 && + attr->value_tag == IPP_TAG_URI) + if ((jobdest = strrchr(attr->values[0].string.text, '/')) != NULL) + jobdest ++; + + if (strcmp(attr->name, "job-originating-user-name") == 0 && + attr->value_tag == IPP_TAG_NAME) + jobuser = attr->values[0].string.text; + + if (strcmp(attr->name, "job-name") == 0 && + attr->value_tag == IPP_TAG_NAME) + jobname = attr->values[0].string.text; + + attr = attr->next; + } + + /* + * See if we have everything needed... + */ + + if (jobdest == NULL || jobid == 0) + { + if (attr == NULL) + break; + else + continue; + } + + jobcount ++; + + /* + * Display the job... + */ + + if (longstatus) + { + puts(""); + + if (jobstate == IPP_JOB_PROCESSING) + printf("%s: active\t\t\t\t ", jobuser); + else + { + printf("%s: %d%s\t\t\t\t ", jobuser, rank, ranks[rank % 10]); + rank ++; + } + + printf("[job %03dlocalhost]\n", jobid); + printf("\t%-33s%d bytes\n", jobname, jobsize); + } + else + { + if (jobstate == IPP_JOB_PROCESSING) + printf("active\t"); + else + { + printf("%d%s\t", rank, ranks[rank % 10]); + rank ++; + } + + printf(" %-5d%-7.7s%-7d%-19s%d bytes\n", jobpriority, jobuser, jobid, + jobname, jobsize); + } + if (attr == NULL) + break; + } + + ippDelete(response); + } + + return (jobcount); +} + + +/* + * End of "$Id$". + */ diff --git a/berkeley/lpr.c b/berkeley/lpr.c new file mode 100644 index 0000000000..f209efee6d --- /dev/null +++ b/berkeley/lpr.c @@ -0,0 +1,252 @@ +/* + * "$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 */ + const char *dest; /* Destination printer */ + const 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? */ + deletefile; /* Delete file after print? */ + char tempfile[1024]; /* Temporary file for printing from stdin */ + char buffer[8192]; /* Copy buffer */ + FILE *temp; /* Temporary file pointer */ + + + silent = 0; + deletefile = 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 'o' : /* Option */ + if (argv[i][2] != '\0') + num_options = cupsParseOptions(argv[i] + 2, num_options, &options); + else + { + i ++; + num_options = cupsParseOptions(argv[i], num_options, &options); + } + 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 'r' : /* Remove file after printing */ + deletefile = 1; + 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); + } + else if (deletefile) + unlink(argv[i]); + } + + /* + * 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(cupsTempFile(tempfile, sizeof(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: standard input 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); + + unlink(tempfile); + + if (job_id < 1) + { + fputs("lpr: unable to print standard input.\n", stderr); + return (1); + } + } + + return (0); +} + + +/* + * End of "$Id$". + */ diff --git a/berkeley/lprm.c b/berkeley/lprm.c new file mode 100644 index 0000000000..2df9530c69 --- /dev/null +++ b/berkeley/lprm.c @@ -0,0 +1,205 @@ +/* + * "$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 + * 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 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 */ + const 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(cupsServer(), 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, "ipp://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, "ipp://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) + { + if (response->request.status.status_code == IPP_NOT_FOUND) + fputs("lprm: Job or printer not found!\n", stderr); + else if (response->request.status.status_code > IPP_OK_CONFLICT) + fputs("lprm: Unable to cancel job(s)!\n", stderr); + + 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..feffe13c71 --- /dev/null +++ b/cgi-bin/Makefile @@ -0,0 +1,83 @@ +# +# "$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 +# 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 + +TARGETS = classes.cgi jobs.cgi 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: + -$(MKDIR) $(SERVERROOT)/cgi-bin + $(CP) $(TARGETS) $(SERVERROOT)/cgi-bin + +# +# classes.cgi +# + +classes.cgi: classes.o ../Makedefs ../cups/$(LIBCUPS) + echo Linking $@... + $(CC) $(LDFLAGS) -o $@ classes.o $(LIBS) + +$(OBJS): ../Makedefs ../cups/cups.h ../cups/ipp.h ../cups/language.h + +# +# jobs.cgi +# + +jobs.cgi: jobs.o ../Makedefs ../cups/$(LIBCUPS) + echo Linking $@... + $(CC) $(LDFLAGS) -o $@ jobs.o $(LIBS) + +$(OBJS): ../Makedefs ../cups/cups.h ../cups/ipp.h ../cups/language.h + +# +# printers.cgi +# + +printers.cgi: printers.o ../Makedefs ../cups/$(LIBCUPS) + echo Linking $@... + $(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/classes.c b/cgi-bin/classes.c new file mode 100644 index 0000000000..53a39e064f --- /dev/null +++ b/cgi-bin/classes.c @@ -0,0 +1,484 @@ +/* + * "$Id$" + * + * Class 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_class_list() - Show a list of classes... + * show_class_info() - Show class information. + */ + +/* + * Include necessary headers... + */ + +#include +#include +#include +#include +#include +#include + + +/* + * Local functions... + */ + +static void show_class_list(http_t *http, cups_lang_t *language); +static void show_class_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 *name; /* Class name */ + http_t *http; /* Connection to the server */ + + + /* + * 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 classes or the status of a + * single class... + */ + + name = argv[0]; + if (strcmp(name, "/") == 0 || strcmp(name, "classes.cgi") == 0) + name = NULL; + + /* + * Print the standard header... + */ + + puts(""); + puts(""); + if (name) + puts(""); + else + puts(""); + printf("%s on %s - Common UNIX Printing System\n", + name == NULL ? "Classes" : name, getenv("SERVER_NAME")); + puts(""); + puts(""); + puts("\"Current"); + puts("\"Current"); + puts("\"Current"); + puts("\"Read"); +#ifdef ESPPRINTPRO + puts("\"Download"); + puts("\"Get"); +#else + puts("\"Download"); +#endif /* ESPPRINTPRO */ + puts(""); + puts(""); + puts(""); + puts("

"); + puts(""); + puts("\"Easy"); +#ifdef ESPPRINTPRO + puts(""); +#else + puts(""); +#endif /* ESPPRINTPRO */ + + printf("

%s on %s

\n", name == NULL ? "Classes" : name, + getenv("SERVER_NAME")); + fflush(stdout); + + puts("
"); + puts(""); + puts(""); + puts(""); + puts(""); + puts(""); + puts(""); + + /* + * Show the information... + */ + + if (name == NULL) + show_class_list(http, language); + else + show_class_info(http, language, name); + + /* + * 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_class_list()' - Show a list of classes... + */ + +static void +show_class_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_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; + + + 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(http, request, "/classes/")) != NULL) + { + /* + * Loop through the classes 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 class status for each class... + */ + + while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) + { + if (strcmp(attr->name, "printer-name") == 0 && + attr->value_tag == IPP_TAG_NAME) + show_class_info(http, language, attr->values[0].string.text); + + attr = attr->next; + } + + if (attr == NULL) + break; + } + + ippDelete(response); + } +} + + +/* + * 'show_class_info()' - Show class information. + */ + +static void +show_class_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[HTTP_MAX_URI];/* 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/classes/%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) + { + puts("

Unable to communicate with CUPS server!"); + return; + } + + if (response->request.status.status_code == IPP_NOT_FOUND) + { + puts("

Class does not exist."); + ippDelete(response); + return; + } + + /* + * Grab the needed class 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; + + if ((attr = ippFindAttribute(response, "printer-uri-supported", IPP_TAG_URI)) != NULL) + { + strcpy(uri, "http:"); + strcpy(uri + 5, strchr(attr->values[0].string.text, '/')); + } + + /* + * Display the class entry... + */ + + puts(""); + + printf("%s\n", uri, name); + + puts(""); + + 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; + + 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); + + 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 class... + */ + + 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/cgi-bin/jobs.c b/cgi-bin/jobs.c new file mode 100644 index 0000000000..a0bb945bc2 --- /dev/null +++ b/cgi-bin/jobs.c @@ -0,0 +1,584 @@ +/* + * "$Id$" + * + * Job 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_job_list() - Show a list of jobs... + * show_job_info() - Show job information. + */ + +/* + * Include necessary headers... + */ + +#include +#include +#include +#include +#include +#include + + +/* + * Local functions... + */ + +static void show_job_list(http_t *http, cups_lang_t *language); +static void show_job_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 *job; /* Job name */ + http_t *http; /* Connection to the server */ + + + /* + * 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 jobs or the status of a + * single job... + */ + + job = argv[0]; + if (strcmp(job, "/") == 0 || strcmp(job, "jobs.cgi") == 0) + job = NULL; + + /* + * Print the standard header... + */ + + puts(""); + puts(""); + if (job) + puts(""); + else + puts(""); + printf("%s on %s - Common UNIX Printing System\n", + job == NULL ? "Jobs" : job, getenv("SERVER_NAME")); + puts(""); + puts(""); + puts("\"Current"); + puts("\"Current"); + puts("\"Current"); + puts("\"Read"); +#ifdef ESPPRINTPRO + puts("\"Download"); + puts("\"Get"); +#else + puts("\"Download"); +#endif /* ESPPRINTPRO */ + puts(""); + puts(""); + puts(""); + puts("

"); + puts(""); + puts("\"Easy"); +#ifdef ESPPRINTPRO + puts(""); +#else + puts(""); +#endif /* ESPPRINTPRO */ + + fflush(stdout); + + /* + * Show the information... + */ + + if (job == NULL) + show_job_list(http, language); + else + show_job_info(http, language, job); + + /* + * Write a standard trailer... + */ + + 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_job_list()' - Show a list of jobs... + */ + +static void +show_job_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 */ + char *job_uri, /* job-uri */ + *printer_uri, /* job-printer-uri */ + *job_name, /* job-name */ + *job_user; /* job-originating-user-name */ + int job_id, /* job-id */ + job_priority, /* job-priority */ + job_k_octets, /* job-k-octets */ + copies; /* copies */ + ipp_jstate_t job_state; /* job-state */ + + + printf("

Jobs on %s

\n", getenv("SERVER_NAME")); + + /* + * Build an IPP_GET_JOBS request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * job-uri + */ + + request = ippNew(); + + request->request.op.operation_id = IPP_GET_JOBS; + 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); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", + NULL, "ipp://localhost/jobs/"); + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoRequest(http, request, "/jobs/")) != NULL) + { + /* + * Do a table for the jobs... + */ + + puts("
"); + puts(""); + puts(""); + printf("\n", cupsLangString(language, CUPS_MSG_PRINT_JOBS)); + printf("\n", cupsLangString(language, CUPS_MSG_JOB_STATE)); + printf("\n", cupsLangString(language, CUPS_MSG_JOB_NAME)); + printf("\n", cupsLangString(language, CUPS_MSG_USER_NAME)); + printf("\n", cupsLangString(language, CUPS_MSG_PRIORITY)); + printf("\n", cupsLangString(language, CUPS_MSG_COPIES)); + printf("\n", cupsLangString(language, CUPS_MSG_FILE_SIZE)); + puts(""); + + /* + * Loop through the jobs 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_JOB) + attr = attr->next; + + if (attr == NULL) + break; + + /* + * Show the job status for each job... + */ + + job_uri = NULL; + printer_uri = NULL; + job_name = "unknown"; + job_user = "unknown"; + job_id = 0; + job_priority = 50; + job_k_octets = 0; + copies = 1; + job_state = IPP_JOB_PENDING; + + while (attr != NULL && attr->group_tag == IPP_TAG_JOB) + { + if (strcmp(attr->name, "job-uri") == 0 && + attr->value_tag == IPP_TAG_URI) + job_uri = attr->values[0].string.text; + + if (strcmp(attr->name, "job-printer-uri") == 0 && + attr->value_tag == IPP_TAG_URI) + printer_uri = attr->values[0].string.text; + + if (strcmp(attr->name, "job-name") == 0 && + attr->value_tag == IPP_TAG_NAME) + job_name = attr->values[0].string.text; + + if (strcmp(attr->name, "job-originating-user-name") == 0 && + attr->value_tag == IPP_TAG_NAME) + job_user = attr->values[0].string.text; + + if (strcmp(attr->name, "job-id") == 0 && + attr->value_tag == IPP_TAG_INTEGER) + job_id = attr->values[0].integer; + + if (strcmp(attr->name, "job-priority") == 0 && + attr->value_tag == IPP_TAG_INTEGER) + job_priority = attr->values[0].integer; + + if (strcmp(attr->name, "job-k-octets") == 0 && + attr->value_tag == IPP_TAG_INTEGER) + job_k_octets = attr->values[0].integer; + + if (strcmp(attr->name, "copies") == 0 && + attr->value_tag == IPP_TAG_INTEGER) + copies = attr->values[0].integer; + + if (strcmp(attr->name, "job-state") == 0 && + attr->value_tag == IPP_TAG_ENUM) + job_state = (ipp_jstate_t)attr->values[0].integer; + + attr = attr->next; + } + + /* + * See if we have everything needed... + */ + + if (job_id && job_uri != NULL && printer_uri != NULL) + { + puts(""); + printf("\n", + getenv("SERVER_NAME"), getenv("SERVER_PORT"), job_id, + strrchr(printer_uri, '/') + 1, job_id); + printf("\n", job_state == IPP_JOB_PROCESSING ? + cupsLangString(language, CUPS_MSG_PROCESSING) : + cupsLangString(language, CUPS_MSG_PENDING)); + printf("\n", job_name); + printf("\n", job_user); + printf("\n", job_priority); + printf("\n", copies); + printf("\n", job_k_octets); + puts(""); + } + + if (attr == NULL) + break; + } + + ippDelete(response); + + puts("
%s%s%s%s%s%s%s
%s-%d%s%s%s%d%d%dk
"); + puts("
"); + } + else + puts("

No jobs found."); +} + + +/* + * 'show_job_info()' - Show job information. + */ + +static void +show_job_info(http_t *http, /* I - Server connection */ + cups_lang_t *language, /* I - Language */ + char *name) /* I - Job "name" */ +{ + int i; /* Looping var */ + ipp_t *request, /* IPP request */ + *response; /* IPP response */ + ipp_attribute_t *attr; /* IPP attribute */ + char uri[HTTP_MAX_URI];/* Real URI */ + char *job_uri, /* job-uri */ + *printer_uri, /* job-printer-uri */ + *job_name, /* job-name */ + *job_user; /* job-originating-user-name */ + int job_id, /* job-id */ + job_priority, /* job-priority */ + job_k_octets; /* job-k-octets */ + ipp_jstate_t job_state; /* job-state */ + + + /* + * Build an IPP_GET_JOB_ATTRIBUTES request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * job-uri + */ + + request = ippNew(); + + request->request.op.operation_id = IPP_GET_JOB_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/jobs/%s", name); + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri); + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoRequest(http, request, uri + 15)) == NULL) + { + puts("

Unable to communicate with CUPS server!"); + return; + } + + if (response->request.status.status_code == IPP_NOT_FOUND) + { + puts("

Job does not exist or has completed."); + ippDelete(response); + return; + } + + /* + * Get the job status for this job... + */ + + if ((attr = ippFindAttribute(response, "job-uri", IPP_TAG_URI)) != NULL) + job_uri = attr->values[0].string.text; + else + { + puts("

Missing job-uri attribute!"); + ippDelete(request); + return; + } + + if ((attr = ippFindAttribute(response, "job-printer-uri", IPP_TAG_URI)) != NULL) + printer_uri = attr->values[0].string.text; + else + { + puts("

Missing job-printer-uri attribute!"); + ippDelete(request); + return; + } + + if ((attr = ippFindAttribute(response, "job-name", IPP_TAG_NAME)) != NULL) + job_name = attr->values[0].string.text; + else + job_name = "unknown"; + + if ((attr = ippFindAttribute(response, "job-originating-user-name", + IPP_TAG_NAME)) != NULL) + job_user = attr->values[0].string.text; + else + job_user = "unknown"; + + if ((attr = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER)) != NULL) + job_id = attr->values[0].integer; + else + { + puts("

Missing job-id attribute!"); + ippDelete(request); + return; + } + + if ((attr = ippFindAttribute(response, "job-priority", IPP_TAG_INTEGER)) != NULL) + job_priority = attr->values[0].integer; + else + job_priority = 50; + + if ((attr = ippFindAttribute(response, "job-k-octets", IPP_TAG_INTEGER)) != NULL) + job_k_octets = attr->values[0].integer; + else + job_k_octets = 0; + + if ((attr = ippFindAttribute(response, "job-state", IPP_TAG_ENUM)) != NULL) + job_state = (ipp_jstate_t)attr->values[0].integer; + else + job_state = IPP_JOB_PENDING; + + /* + * Do a table for the job... + */ + + printf("

%s-%d

\n", + getenv("SERVER_NAME"), getenv("SERVER_PORT"), + strrchr(printer_uri, '/') + 1, strrchr(printer_uri, '/') + 1, job_id); + + puts("
"); + puts(""); + + puts(""); + printf("\n", cupsLangString(language, CUPS_MSG_JOB_STATE)); + printf("\n", job_state == IPP_JOB_PROCESSING ? + cupsLangString(language, CUPS_MSG_PROCESSING) : + cupsLangString(language, CUPS_MSG_PENDING)); + puts(""); + + puts(""); + printf("\n", cupsLangString(language, CUPS_MSG_JOB_NAME)); + printf("\n", job_name); + puts(""); + + puts(""); + printf("\n", cupsLangString(language, CUPS_MSG_USER_NAME)); + printf("\n", job_user); + puts(""); + + puts(""); + printf("\n", cupsLangString(language, CUPS_MSG_PRIORITY)); + printf("\n", job_priority); + puts(""); + + puts(""); + printf("\n", cupsLangString(language, CUPS_MSG_FILE_SIZE)); + printf("\n", job_k_octets); + puts(""); + + puts(""); + printf("\n", cupsLangString(language, CUPS_MSG_OPTIONS)); + puts(""); + puts(""); + puts("
%s%s
%s%s
%s%s
%s%d
%s%dk
%s"); + + for (attr = response->attrs; attr != NULL; attr = attr->next) + { + if (attr->group_tag != IPP_TAG_JOB && + attr->group_tag != IPP_TAG_EXTENSION) + continue; + + if (strcmp(attr->name, "job-uri") == 0 || + strcmp(attr->name, "job-printer-uri") == 0 || + strcmp(attr->name, "job-name") == 0 || + strcmp(attr->name, "job-originating-user-name") == 0 || + strcmp(attr->name, "job-id") == 0 || + strcmp(attr->name, "job-priority") == 0 || + strcmp(attr->name, "job-k-octets") == 0 || + strcmp(attr->name, "job-state") == 0) + continue; + + if (attr->value_tag != IPP_TAG_BOOLEAN) + printf("%s=", attr->name); + + for (i = 0; i < attr->num_values; i ++) + { + if (i) + putchar(','); + + switch (attr->value_tag) + { + case IPP_TAG_INTEGER : + case IPP_TAG_ENUM : + printf("%d", attr->values[i].integer); + break; + + case IPP_TAG_BOOLEAN : + if (!attr->values[i].boolean) + printf("no"); + + case IPP_TAG_NOVALUE : + fputs(attr->name, stdout); + break; + + case IPP_TAG_RANGE : + printf("%d-%d", attr->values[i].range.lower, + attr->values[i].range.upper); + break; + + case IPP_TAG_RESOLUTION : + printf("%dx%d%s", attr->values[i].resolution.xres, + attr->values[i].resolution.yres, + attr->values[i].resolution.units == IPP_RES_PER_INCH ? + "dpi" : "dpc"); + break; + + case IPP_TAG_STRING : + case IPP_TAG_TEXT : + case IPP_TAG_NAME : + case IPP_TAG_KEYWORD : + case IPP_TAG_CHARSET : + case IPP_TAG_LANGUAGE : + case IPP_TAG_MIMETYPE : + case IPP_TAG_URI : + printf("\"%s\"", attr->values[i].string.text); + break; + } + } + + puts("
"); + } + + puts("
"); + + ippDelete(response); +} + + +/* + * End of "$Id$". + */ diff --git a/cgi-bin/printers.c b/cgi-bin/printers.c new file mode 100644 index 0000000000..7756161ed5 --- /dev/null +++ b/cgi-bin/printers.c @@ -0,0 +1,486 @@ +/* + * "$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 */ + + + /* + * 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"); +#ifdef ESPPRINTPRO + puts("\"Download"); + puts("\"Get"); +#else + puts("\"Download"); +#endif /* ESPPRINTPRO */ + puts(""); + puts(""); + puts(""); + puts("

"); + puts(""); + puts("\"Easy"); +#ifdef ESPPRINTPRO + puts(""); +#else + puts(""); +#endif /* ESPPRINTPRO */ + + 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; + + + 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(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[HTTP_MAX_URI];/* 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) + { + puts("

Unable to communicate with CUPS server!"); + return; + } + + if (response->request.status.status_code == IPP_NOT_FOUND) + { + puts("

Printer does not exist."); + ippDelete(response); + return; + } + + /* + * 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; + + if ((attr = ippFindAttribute(response, "printer-uri-supported", IPP_TAG_URI)) != NULL) + { + strcpy(uri, "http:"); + strcpy(uri + 5, strchr(attr->values[0].string.text, '/')); + } + + /* + * Display the printer entry... + */ + + puts(""); + + printf("%s\n", uri, 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; + + 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); + + 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..2859b7064d --- /dev/null +++ b/conf/Makefile @@ -0,0 +1,68 @@ +# +# "$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... +# + +KEEP = classes.conf cupsd.conf printers.conf +REPLACE = mime.convs mime.types + +# +# Make everything... +# + +all: + +# +# Clean all config and object files... +# + +clean: + +# +# Install files... +# + +install: + -$(MKDIR) $(SERVERROOT)/conf + for file in $(KEEP); do \ + if test -e $(SERVERROOT)/conf/$$file ; then \ + $(CP) $$file $(SERVERROOT)/conf/$$file.N ; \ + else \ + $(CP) $$file $(SERVERROOT)/conf ; \ + fi ; \ + done + for file in $(REPLACE); do \ + if test -e $(SERVERROOT)/conf/$$file ; then \ + $(MV) $(SERVERROOT)/conf/$$file $(SERVERROOT)/conf/$$file.O ; \ + fi ; \ + $(CP) $$file $(SERVERROOT)/conf ; \ + done + +# +# End of "$Id$". +# diff --git a/conf/classes.conf b/conf/classes.conf new file mode 100644 index 0000000000..cb6a341e80 --- /dev/null +++ b/conf/classes.conf @@ -0,0 +1,72 @@ +# +# "$Id: classes.conf 333 1999-05-17 18:03:40Z 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 +#Printer sample@host2 +# + +# +# End of "$Id: classes.conf 333 1999-05-17 18:03:40Z mike $". +# diff --git a/conf/cupsd.conf b/conf/cupsd.conf new file mode 100644 index 0000000000..cb54f7ff19 --- /dev/null +++ b/conf/cupsd.conf @@ -0,0 +1,369 @@ +# +# "$Id: cupsd.conf 628 1999-08-23 15:24:48Z 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 + +# +# MaxClients: controls the maximum number of simultaneous clients that +# will be handled. Defaults to 100. +# + +#MaxClients 100 + +# +# 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. The default varies depending on the operating system, but +# will be "sys", "system", or "root" (checked for in that order.) +# + +#SystemGroup sys + +# +# ServerName: the hostname of your server, as advertised to the world. +# By default CUPS will use the hostname of the system. +# +# This is also the name used by clients when connecting to the local +# server, so you can use this to configure a client machine without +# a local server running. +# + +#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/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 + +# +# PageLog: the page log file; if this does not start with a leading / +# then it is assumed to be relative to ServerRoot. By default set to +# "logs/page_log" +# + +#PageLog logs/page_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 info + +# +# 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 "8m" (8 megabytes). +# + +#RIPCache 8m + +# +# TempDir: the directory to put temporary files in. This directory must be +# writable by the user defined above! Defaults to "/var/tmp" or the value +# of the TMPDIR environment variable. +# + +#TempDir /var/tmp + +# +# 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 SystemGroup), 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. +# +# Both "Allow" and "Deny" accept the following notations for addresses: +# +# All +# None +# *.domain.com +# .domain.com +# host.domain.com +# nnn.* +# nnn.nnn.* +# nnn.nnn.nnn.* +# nnn.nnn.nnn.nnn +# nnn.nnn.nnn.nnn/mm +# nnn.nnn.nnn.nnn/mmm.mmm.mmm.mmm +# +# The host and domain address require that you enable hostname lookups +# with "HostNameLookups On" above. +# + + + + + +# +# 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 the system group 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 628 1999-08-23 15:24:48Z mike $". +# diff --git a/conf/cupsd.conf-personal b/conf/cupsd.conf-personal new file mode 100644 index 0000000000..b82b66d976 --- /dev/null +++ b/conf/cupsd.conf-personal @@ -0,0 +1,250 @@ +# +# "$Id: cupsd.conf-personal 407 1999-06-17 20:02:43Z mike $" +# +# Scheduler configuration file for ESP Print Personal. +# + +######################################################################## +# # +# 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 Listen lines to listen to more than one +# port: +# +# Listen 127.0.0.1:80 +# Listen 127.0.0.1:631 +# +# For ESP Print Personal, we can only listen on the local host... +# + +#Listen 127.0.0.1:80 +Listen 127.0.0.1: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/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 + +# +# PageLog: the page log file; if this does not start with a leading / +# then it is assumed to be relative to ServerRoot. By default set to +# "logs/page_log" +# + +#PageLog logs/page_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 info + +# +# 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 + +# +# Browsing: not available in ESP Print Personal. +# + +Browsing Off + +# +# 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 SystemGroup), 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-personal 407 1999-06-17 20:02:43Z mike $". +# diff --git a/conf/cupsd.conf-professional b/conf/cupsd.conf-professional new file mode 100644 index 0000000000..c7bd3324bf --- /dev/null +++ b/conf/cupsd.conf-professional @@ -0,0 +1,313 @@ +# +# "$Id: cupsd.conf-professional 407 1999-06-17 20:02:43Z mike $" +# +# Scheduler configuration file for ESP Print Professional. +# + +######################################################################## +# # +# 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/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 + +# +# PageLog: the page log file; if this does not start with a leading / +# then it is assumed to be relative to ServerRoot. By default set to +# "logs/page_log" +# + +#PageLog logs/page_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 info + +# +# 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 SystemGroup), 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-professional 407 1999-06-17 20:02:43Z mike $". +# diff --git a/conf/mime.convs b/conf/mime.convs new file mode 100644 index 0000000000..72230bd4b4 --- /dev/null +++ b/conf/mime.convs @@ -0,0 +1,62 @@ +# +# "$Id: mime.convs 575 1999-07-30 13:57:16Z 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 575 1999-07-30 13:57:16Z mike $". +# diff --git a/conf/mime.types b/conf/mime.types new file mode 100644 index 0000000000..e44dbcfa9b --- /dev/null +++ b/conf/mime.types @@ -0,0 +1,122 @@ +# +# "$Id: mime.types 575 1999-07-30 13:57:16Z 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 +image/x-sun-raster ras + +# TODO: Add Alias, SoftImage, GIMP??? files +#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,"%-12345X) +application/vnd.cups-raster string(0,"RaSt") string(0,"tSaR") +application/vnd.cups-raw + +# +# End of "$Id: mime.types 575 1999-07-30 13:57:16Z mike $". +# diff --git a/conf/printers.conf b/conf/printers.conf new file mode 100644 index 0000000000..b9e33c87a5 --- /dev/null +++ b/conf/printers.conf @@ -0,0 +1,89 @@ +# +# "$Id: printers.conf 334 1999-05-17 18:11:26Z mike $" +# +# Sample printer 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 printer configuration file. This file is included # +# from the main configuration file (cups.conf) and lists all of the # +# printers known to the system. # +# # +######################################################################## + +# +# Each printer starts with a 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 + +# +# 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 334 1999-05-17 18:11:26Z mike $". +# diff --git a/config.h.in b/config.h.in new file mode 100644 index 0000000000..e8c7440bd9 --- /dev/null +++ b/config.h.in @@ -0,0 +1,101 @@ +/* + * "$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 + * 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 + */ + +/* + * 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 ? + */ + +#undef HAVE_CRYPT_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..1b4c98ab30 --- /dev/null +++ b/configure.in @@ -0,0 +1,316 @@ +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 44141 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 Get the operating system and version number... + +uname=`uname` +uversion=`uname -r | sed -e '1,$s/\.//g'` +if test "$uname" = "IRIX64"; then + uname="IRIX" +fi + +dnl Clear the debugging and non-shared library options unless the user asks +dnl for them... + +OPTIM="" +AC_SUBST(OPTIM) +PICFLAG=1 +CFLAGS="${CFLAGS:=}" + +AC_ARG_ENABLE(debug, [ --enable-debug turn on debugging [default=no]],[if eval "test x$enable_debug = xyes"; then + OPTIM="-g " +fi]) +AC_ARG_ENABLE(shared, [ --disable-shared turn off shared libraries [default=no]]) +if test "$disable_shared" != "yes"; then + case "$uname" in + SunOS* | UNIX_S*) + LIBCUPS="libcups.so.1" + LIBCUPSIMAGE="libcupsimage.so.1" + DSO="\$(CC) -Wl,-h,\$@ -G \$(OPTIM) -o" + ;; + HP-UX*) + LIBCUPS="libcups.sl.1" + LIBCUPSIMAGE="libcupsimage.sl.1" + DSO="ld -b -z +h \$@ -o" + ;; + OSF1* | Linux* | FreeBSD*) + LIBCUPS="libcups.so.1" + LIBCUPSIMAGE="libcupsimage.so.1" + DSO="\$(CC) -Wl,-soname,\$@ -shared \$(OPTIM) -o" + ;; + IRIX*) + LIBCUPS="libcups.so.1" + LIBCUPSIMAGE="libcupsimage.so.1" + DSO="\$(CC) -soname \$@ -shared \$(OPTIM) -o" + ;; + *) + echo "Warning: shared libraries may not be supported. Trying -shared" + echo " option with compiler." + LIBCUPS="libcups.so.1" + LIBCUPSIMAGE="libcupsimage.so.1" + DSO="\$(CC) -Wl,-soname,\$@ -shared \$(OPTIM) -o" + ;; + esac +else + PICFLAG=0 + LIBCUPS="libcups.a" + LIBCUPSIMAGE="libcupsimage.a" + DSO=":" +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(CHMOD,chmod) +AC_PATH_PROG(CP,cp) +AC_PATH_PROG(NROFF,nroff) +if test "$NROFF" = ""; then + AC_PATH_PROG(GROFF,groff) + if test "$GROFF" = ""; then + NROFF="echo" + else + NROFF="$GROFF -T ascii" + fi +fi +AC_PATH_PROG(HTMLDOC,htmldoc) +AC_PATH_PROG(MKDIR,mkdir) +AC_PATH_PROG(PACK,pack) +if test "$PACK" = ""; then + AC_PATH_PROG(PACK,gzip) + if test "$PACK" = ""; then + PACK="echo" + CAT="dummy" + else + PACK="$PACK -fv9" + CAT="gz" + fi +else + PACK="$PACK -f" + CAT="z" +fi +AC_SUBST(CAT) +AC_PATH_PROG(RM,rm) +AC_PATH_PROG(SED,sed) +AC_PATH_PROG(SMBCLIENT,smbclient) +if test "$SMBCLIENT" = ""; then + echo "Looking for smbclient in standard locations..." + AC_PATH_PROG(SMBCLIENT,smbclient,samba_not_detected, + /usr/samba/bin:/usr/local/samba/bin:/usr/freeware/samba/bin:/opt/samba/bin) +fi + +dnl Architecture checks... +AC_C_BIGENDIAN + +dnl Check for libraries... +AC_CHECK_LIB(c,crypt,LIBS="$LIBS",AC_CHECK_LIB(crypt,crypt)) +AC_CHECK_HEADER(crypt.h, AC_DEFINE(HAVE_CRYPT_H)) +AC_CHECK_LIB(sec,getspent) + +NETLIBS="" +AC_SUBST(NETLIBS) +AC_CHECK_LIB(socket,socket, +if test "$uname" != "IRIX"; then + NETLIBS="-lsocket" +else + echo "Not using -lsocket since you are running IRIX." +fi) +AC_CHECK_LIB(nsl,gethostbyaddr, +if test "$uname" != "IRIX"; then + NETLIBS="$NETLIBS -lnsl" +else + echo "Not using -lnsl since you are running IRIX." +fi) + +LIBJPEG="" +LIBPNG="" +LIBTIFF="" +LIBZ="" + +AC_SUBST(LIBJPEG) +AC_SUBST(LIBPNG) +AC_SUBST(LIBTIFF) +AC_SUBST(LIBZ) + +AC_CHECK_HEADER(jpeglib.h, + AC_DEFINE(HAVE_LIBJPEG) + LIBJPEG="-ljpeg") +AC_CHECK_HEADER(png.h, + AC_DEFINE(HAVE_LIBPNG) + LIBPNG="-lpng") +AC_CHECK_HEADER(tiff.h, + AC_DEFINE(HAVE_LIBTIFF) + LIBTIFF="-ltiff") +AC_CHECK_HEADER(zlib.h, + AC_DEFINE(HAVE_LIBZ) + LIBZ="-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 Update compiler options... +if test -n "$GXX"; then + if test -z "$OPTIM"; then + OPTIM="-O2" + fi + if test $PICFLAG = 1; then + OPTIM="-fPIC $OPTIM" + fi +else + case $uname in + IRIX*) + if test -z "$OPTIM"; then + OPTIM="-O2" + fi + if test $uversion -ge 62; then + OPTIM="$OPTIM -n32 -mips3" + fi + ;; + HP-UX*) + if test -z "$OPTIM"; then + OPTIM="+O2" + fi + OPTIM="-Ae $OPTIM" + ;; + SunOS*) + # Solaris + if test -z "$OPTIM"; then + OPTIM="-O" + fi + if test $PICFLAG = 1; then + OPTIM="-KPIC $OPTIM" + fi + ;; + *) + # Running some other operating system; inform the user they + # should contribute the necessary options to + # cups-support@cups.org... + echo "Building CUPS with default compiler optimizations; contact" + echo "cups-support@cups.org with uname and compiler options needed" + echo "for your platform, or set the CFLAGS environment variable" + echo "before running configure." + ;; + esac +fi + +if test "$DSO" != ":"; then + # When using DSOs the image libraries are linked to libcupsimage.so + # rather than to the executables. This makes things smaller if you + # are using any static libraries, and it also allows us to distribute + # a single DSO rather than a bunch... + DSOLIBS="\$(LIBJPEG) \$(LIBPNG) \$(LIBTIFF) \$(LIBZ)" + IMGLIBS="" + + # The HP-UX and Solaris run-time linkers are EXTREMELY stupid when + # it comes to deciding where to find a DSO. Add linker options to + # tell them where to find the DSO (usually in /usr/lib... duh!) + case $uname in + HP-UX*) + LDFLAGS="$LDFLAGS -Wl,+b,$libdir,+fb" + ;; + SunOS*) + # Solaris + LDFLAGS="-R$libdir" + ;; + esac +else + DSOLIBS="" + IMGLIBS="\$(LIBJPEG) \$(LIBPNG) \$(LIBTIFF) \$(LIBZ)" +fi + +AC_SUBST(DSO) +AC_SUBST(DSOLIBS) +AC_SUBST(IMGLIBS) +AC_SUBST(LIBCUPS) +AC_SUBST(LIBCUPSIMAGE) + +dnl Fix "prefix" variable if it hasn't been specified... +if test "$prefix" = "NONE"; then + prefix="/usr" +fi + +dnl Fix "libdir" variable for IRIX 6.x... +if test "$uname" = "IRIX" -a $uversion -ge 62; then + libdir="/usr/lib32" +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... +case "$uname" in + Linux) + CUPS_LOCALEDIR="$prefix/share/locale" + ;; + + OSF1) + CUPS_LOCALEDIR="$prefix/lib/nls/msg" + ;; + + *) + # This is the standard System V location... + CUPS_LOCALEDIR="$prefix/lib/locale" + ;; +esac + +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.sh b/cups.sh new file mode 100755 index 0000000000..16c6d3fade --- /dev/null +++ b/cups.sh @@ -0,0 +1,112 @@ +#!/bin/sh +# +# "$Id$" +# +# Startup/shutdown script for the Common UNIX Printing System (CUPS). +# +# Linux chkconfig stuff: +# +# chkconfig: 2345 60 60 +# description: Startup/shutdown script 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 +# + +# See what program to use for configuration stuff... +case "`uname`" in + IRIX*) + IS_ON=/sbin/chkconfig + ;; + + *) + IS_ON=/bin/true + ;; +esac + +# The verbose flag controls the printing of the names of +# daemons as they are started. +if $IS_ON verbose; then + ECHO=echo +else + ECHO=: +fi + +# See if the CUPS server is running... +case "`uname`" in + IRIX* | HP-UX | SunOS) + pid=`ps -e | awk '{print $1,$4}' | grep cupsd | awk '{print $1}'` + ;; + OSF1) + pid=`ps -e | awk '{print $1,$5}' | grep cupsd | awk '{print $1}'` + ;; + Linux) + pid=`ps ax | awk '{print $1,$5}' | grep cupsd | awk '{print $1}'` + ;; + *) + pid="" + ;; +esac + +# Start or stop the CUPS server based upon the first argument to the script. +case $1 in + start | restart | reload) + if test "$pid" != ""; then + if $IS_ON cups; then + kill -HUP $pid + $ECHO "cups: scheduler restarted." + else + kill $pid + $ECHO "cups: scheduler stopped." + fi + else + if $IS_ON cups; then + /usr/sbin/cupsd 2>&1 >/dev/null & + $ECHO "cups: scheduler started." + fi + fi + ;; + + stop) + if test "$pid" != ""; then + kill $pid + $ECHO "cups: scheduler stopped." + fi + ;; + + status) + if test "$pid" != ""; then + echo "cups: Scheduler is running." + else + echo "cups: Scheduler is not running." + fi + ;; + + *) + echo "Usage: cups {reload|restart|start|status|stop}" + exit 1 + ;; +esac + +exit 0 + + +# +# End of "$Id$". +# diff --git a/cups/Makefile b/cups/Makefile new file mode 100644 index 0000000000..14fe89b7f5 --- /dev/null +++ b/cups/Makefile @@ -0,0 +1,150 @@ +# +# "$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 +# 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 + +# +# Object files... +# + +LIBOBJS = 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 usersys.o \ + util.o +OBJS = $(LIBOBJS) testhttp.o testmime.o testppd.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) testhttp testmime testppd + +# +# Make all targets... +# + +all: $(TARGETS) + +# +# Remove object and target files... +# + +clean: + rm -f $(OBJS) $(TARGETS) + +# +# Install object and target files... +# + +install: all + -$(MKDIR) $(INCLUDEDIR)/cups + $(CP) $(HEADERS) $(INCLUDEDIR)/cups + -$(MKDIR) $(LIBDIR) + $(CP) $(LIBCUPS) $(LIBDIR) + if test $(LIBCUPS) != "libcups.a"; then \ + $(LN) $(LIBCUPS) `basename $(LIBCUPS) .1`; \ + fi + +# +# libcups.so.1, libcups.sl.1 +# + +libcups.so.1 libcups.sl.1: $(LIBOBJS) ../Makedefs + echo Linking $@... + $(DSO) $@ $(LIBOBJS) + -$(LN) $@ `basename $@ .1` + +# +# libcups.a +# + +libcups.a: $(LIBOBJS) + echo Archiving $@... + $(RM) $@ + $(AR) $(ARFLAGS) $@ $(LIBOBJS) + $(RANLIB) $@ + +# +# cups_C.h - the default POSIX locale that is compiled in. +# + +cups_C.h: ../locale/C/cups_C + echo Generating $@... + $(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: language.h 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 +usersys.o: cups.h ../config.h ../Makedefs +util.o: cups.h http.h ipp.h ../config.h ../Makedefs + +# +# testhttp (dependency on static CUPS library is intentional) +# + +testhttp: testhttp.o libcups.a + echo Linking $@... + $(CC) $(LDFLAGS) -o $@ testhttp.o libcups.a $(NETLIBS) + +testhttp.o: http.h ../Makedefs + +# +# testmime (dependency on static CUPS library is intentional) +# + +testmime: testmime.o libcups.a + echo Linking $@... + $(CC) $(LDFLAGS) -o $@ testmime.o libcups.a + +testmime.o: mime.h ../Makedefs + +# +# testppd (dependency on static CUPS library is intentional) +# + +testppd: testppd.o libcups.a + echo Linking $@... + $(CC) $(LDFLAGS) -o $@ testppd.o libcups.a $(NETLIBS) + +testppd.o: ppd.h ../Makedefs + +# +# End of "$Id$". +# diff --git a/cups/cups.dsp b/cups/cups.dsp new file mode 100644 index 0000000000..304345558a --- /dev/null +++ b/cups/cups.dsp @@ -0,0 +1,176 @@ +# Microsoft Developer Studio Project File - Name="cups" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=cups - 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 "cups.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 "cups.mak" CFG="cups - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "cups - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "cups - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "cups - 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 Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\visualc" /I ".." /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /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 +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"cups.lib" + +!ELSEIF "$(CFG)" == "cups - 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 Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\visualc" /I ".." /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /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 +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"cupsd.lib" + +!ENDIF + +# Begin Target + +# Name "cups - Win32 Release" +# Name "cups - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\emit.c +# End Source File +# Begin Source File + +SOURCE=.\filter.c +# End Source File +# Begin Source File + +SOURCE=.\http.c +# End Source File +# Begin Source File + +SOURCE=.\ipp.c +# End Source File +# Begin Source File + +SOURCE=.\language.c +# End Source File +# Begin Source File + +SOURCE=.\mark.c +# End Source File +# Begin Source File + +SOURCE=.\mime.c +# End Source File +# Begin Source File + +SOURCE=.\options.c +# End Source File +# Begin Source File + +SOURCE=.\page.c +# End Source File +# Begin Source File + +SOURCE=.\ppd.c +# End Source File +# Begin Source File + +SOURCE=.\raster.c +# End Source File +# Begin Source File + +SOURCE=.\string.c +# End Source File +# Begin Source File + +SOURCE=.\type.c +# End Source File +# Begin Source File + +SOURCE=.\util.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\cups.h +# End Source File +# Begin Source File + +SOURCE=.\http.h +# End Source File +# Begin Source File + +SOURCE=.\ipp.h +# End Source File +# Begin Source File + +SOURCE=.\language.h +# End Source File +# Begin Source File + +SOURCE=.\mime.h +# End Source File +# Begin Source File + +SOURCE=.\ppd.h +# End Source File +# Begin Source File + +SOURCE=.\raster.h +# End Source File +# End Group +# End Target +# End Project diff --git a/cups/cups.h b/cups/cups.h new file mode 100644 index 0000000000..9219f6606c --- /dev/null +++ b/cups/cups.h @@ -0,0 +1,143 @@ +/* + * "$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 */ + CUPS_PRINTER_IMPLICIT = 0x10000, /* Implicit class */ + CUPS_PRINTER_OPTIONS = 0xfffc /* ~(CLASS | REMOTE | IMPLICIT) */ +}; + + +/* + * 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(const char *printer, int job); +#define cupsDoRequest(http,request,resource) cupsDoFileRequest((http),(request),(resource),NULL) +extern ipp_t *cupsDoFileRequest(http_t *http, ipp_t *request, + const char *resource, const char *filename); +extern int cupsGetClasses(char ***classes); +extern const char *cupsGetDefault(void); +extern const char *cupsGetPPD(const char *printer); +extern int cupsGetPrinters(char ***printers); +extern int cupsPrintFile(const char *printer, const char *filename, + const char *title, int num_options, + cups_option_t *options); +extern char *cupsTempFile(char *filename, int len); +extern int cupsAddOption(const char *name, const char *value, + int num_options, cups_option_t **options); +extern void cupsFreeOptions(int num_options, cups_option_t *options); +extern const char *cupsGetOption(const char *name, int num_options, + cups_option_t *options); +extern int cupsParseOptions(const char *arg, int num_options, + cups_option_t **options); +extern int cupsMarkOptions(ppd_file_t *ppd, int num_options, + cups_option_t *options); + +extern const char *cupsGetPassword(const char *prompt); +extern const char *cupsServer(void); +extern const char *cupsUser(void); + +# ifdef __cplusplus +} +# endif /* __cplusplus */ + +#endif /* !_CUPS_CUPS_H_ */ + +/* + * End of "$Id$". + */ diff --git a/cups/cups_C.h b/cups/cups_C.h new file mode 100644 index 0000000000..ede3c9ab77 --- /dev/null +++ b/cups/cups_C.h @@ -0,0 +1,123 @@ +"us-ascii", +"OK", +"Cancel", +"Help", +"Quit", +"Close", +"Yes", +"No", +"On", +"Off", +"Save", +"Discard", +"Default", +"Options", +"More Info", +"Black", +"Color", +"Cyan", +"Magenta", +"Yellow", +"Copyright 1993-1999 by Easy Software Products, All Rights Reserved.", +"General", +"Printer", +"Image Options", +"HP-GL/2 Options", +"Extra", +"Document", +"Other", +"Print Pages: ", +"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: ", +"Color Saturation: ", +"Color Hue: ", +"Fit to Page: ", +"Shading: ", +"Pen Width: ", +"Gamma Correction: ", +"Brightness: ", +"Add", +"Delete", +"Modify", +"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", +"All", +"Odd", +"Even Pages", +"Darker Lighter", +"Media Size", +"Media Type", +"Media Source", +"Orientation: ", +"Portrait", +"Landscape", +"Job State", +"Job Name", +"User Name", +"Priority", +"Copies", +"File Size", +"Pending", +"Output Mode", +"Resolution", +"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/cups/debug.h b/cups/debug.h new file mode 100644 index 0000000000..415fb5f85c --- /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 + * 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_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..39e17091b1 --- /dev/null +++ b/cups/filter.c @@ -0,0 +1,297 @@ +/* + * "$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 + * 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: + * + * 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... + */ + +/* + * 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 */ + const 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. + */ + +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, j, /* Looping vars */ + num_temp, /* Number of temporary filters */ + num_mintemp, /* Number of filters in the minimum */ + cost, /* Current cost */ + mincost; /* 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... + */ + + mincost = 9999999; + 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...) + */ + + for (j = 0, cost = 0; j < num_temp; j ++) + cost += temp->cost; + + if (cost < mincost) + { + if (mintemp != NULL) + free(mintemp); + + mincost = cost; + mintemp = temp; + num_mintemp = num_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..b61ce6ffa3 --- /dev/null +++ b/cups/http.c @@ -0,0 +1,1446 @@ +/* + * "$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 + * 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: + * + * httpInitialize() - Initialize the HTTP interface library and set the + * default HTTP proxy (if any). + * httpCheck() - Check to see if there is a pending response from + * the server. + * 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 + +#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(const char *name); +static int http_send(http_t *http, http_state_t request, + const char *uri); + + +/* + * Local globals... + */ + +static const char *http_fields[] = + { + "Accept-Language", + "Accept-Ranges", + "Authorization", + "Connection", + "Content-Encoding", + "Content-Language", + "Content-Length", + "Content-Location", + "Content-MD5", + "Content-Range", + "Content-Type", + "Content-Version", + "Date", + "Host", + "If-Modified-Since", + "If-Unmodified-since", + "Keep-Alive", + "Last-Modified", + "Link", + "Location", + "Range", + "Referer", + "Retry-After", + "Transfer-Encoding", + "Upgrade", + "User-Agent", + "WWW-Authenticate" + }; +static const char *days[7] = + { + "Sun", + "Mon", + "Tue", + "Wed", + "Thu", + "Fri", + "Sat" + }; +static const 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__ */ +} + + +/* + * 'httpCheck()' - Check to see if there is a pending response from the server. + */ + +int /* O - 0 = no data, 1 = data available */ +httpCheck(http_t *http) /* I - HTTP connection */ +{ + fd_set input; /* Input set for select() */ + struct timeval timeout; /* Timeout */ + + + /* + * First see if there is data in the buffer... + */ + + if (http == NULL) + return (0); + + if (http->used) + return (1); + + /* + * Then try doing a select() to poll the socket... + */ + + FD_ZERO(&input); + FD_SET(http->fd, &input); + + timeout.tv_sec = 0; + timeout.tv_usec = 0; + + return (select(http->fd + 1, &input, NULL, NULL, &timeout) > 0); +} + + +/* + * '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(const 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(const 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, (char **)&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 if (strcasecmp(method, "socket") == 0) /* Not registered yet... */ + *port = 9100; + 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 */ + const 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 */ + const 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 */ + const 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 */ + const 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 */ + const 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 */ + const 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 */ + const 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 */ + const 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 */ + const 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) + { + 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 */ + int lasterror; /* Last error received */ + + + 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... + */ + + lasterror = 0; + errno = 0; + + 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)) < 0) + { + /* + * Nope, can't get a line this time... + */ + + if (errno != lasterror && errno != ECONNRESET && + errno != ECONNABORTED && errno != ENETRESET) + { + lasterror = errno; + continue; + } + + DEBUG_printf(("httpGets(): recv() error %d!\n", errno)); + + return (NULL); + } + else if (bytes == 0) + return (NULL); + + /* + * 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); + + DEBUG_printf(("httpGets(): Returning \"%s\"\n", line)); + return (line); + } + else if (*bufptr == 0x0d) + bufptr ++; + else + *lineptr++ = *bufptr++; + } + + DEBUG_puts("httpGets(): No new line available!"); + + 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 */ + nbytes, /* Number of bytes written */ + tbytes; /* Number of bytes all together */ + char buf[HTTP_MAX_BUFFER], /* Buffer for formatted string */ + *bufptr; /* Pointer into buffer */ + va_list ap; /* Variable argument pointer */ + + + va_start(ap, format); + bytes = vsprintf(buf, format, ap); + va_end(ap); + + DEBUG_printf(("httpPrintf: %s", buf)); + + for (tbytes = 0, bufptr = buf; tbytes < bytes; tbytes += nbytes, bufptr += nbytes) + if ((nbytes = send(http->fd, bufptr, bytes - tbytes, 0)) < 0) + return (-1); + + return (bytes); +} + + +/* + * 'httpStatus()' - Return a short string describing a HTTP status code. + */ + +const 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. + */ + +const 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(const 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... + * + * If we get status 100 (HTTP_CONTINUE), then we *don't* change states. + * Instead, we just return HTTP_CONTINUE to the caller and keep on + * tryin'... + */ + + if (http->status == HTTP_CONTINUE) + return (http->status); + + 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); + } + + /* + * See if there was an error... + */ + + if (errno) + 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 */ + const 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 */ + const 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 /* O - Content length */ +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(const 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 */ + const char *uri) /* I - URI */ +{ + int i; /* Looping var */ + char *ptr, /* Pointer in buffer */ + buf[1024]; /* Encoded URI buffer */ + static const char *codes[] = /* Request code strings */ + { + NULL, + "OPTIONS", + "GET", + NULL, + "HEAD", + "POST", + NULL, + NULL, + "PUT", + NULL, + "DELETE", + "TRACE", + "CLOSE" + }; + static const 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 ++; + + http->status = HTTP_CONTINUE; + + if (httpPrintf(http, "%s %s HTTP/1.1\r\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\r\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\r\n", http_fields[i], http->fields[i]) < 1) + return (-1); + } + + if (httpPrintf(http, "\r\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..c5f2d1ac99 --- /dev/null +++ b/cups/http.h @@ -0,0 +1,291 @@ +/* + * "$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 + * 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_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 2048 /* 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 = 100, /* 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_LANGUAGE, + HTTP_FIELD_ACCEPT_RANGES, + HTTP_FIELD_AUTHORIZATION, + HTTP_FIELD_CONNECTION, + 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_HOST, + HTTP_FIELD_IF_MODIFIED_SINCE, + HTTP_FIELD_IF_UNMODIFIED_SINCE, + HTTP_FIELD_KEEP_ALIVE, + HTTP_FIELD_LAST_MODIFIED, + HTTP_FIELD_LINK, + HTTP_FIELD_LOCATION, + HTTP_FIELD_RANGE, + HTTP_FIELD_REFERER, + HTTP_FIELD_RETRY_AFTER, + HTTP_FIELD_TRANSFER_ENCODING, + HTTP_FIELD_UPGRADE, + HTTP_FIELD_USER_AGENT, + 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) +extern int httpCheck(http_t *http); +# 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(const char *host, int port); +extern int httpDelete(http_t *http, const char *uri); +extern void httpFlush(http_t *http); +extern int httpGet(http_t *http, const char *uri); +extern char *httpGets(char *line, int length, http_t *http); +extern const char *httpGetDateString(time_t t); +extern time_t httpGetDateTime(const char *s); +# define httpGetField(http,field) (http)->fields[field] +extern int httpHead(http_t *http, const char *uri); +extern void httpInitialize(void); +extern int httpOptions(http_t *http, const char *uri); +extern int httpPost(http_t *http, const char *uri); +extern int httpPrintf(http_t *http, const char *format, ...); +extern int httpPut(http_t *http, const char *uri); +extern int httpRead(http_t *http, char *buffer, int length); +extern int httpReconnect(http_t *http); +extern void httpSeparate(const char *uri, char *method, char *username, + char *host, int *port, char *resource); +extern void httpSetField(http_t *http, http_field_t field, const char *value); +extern const char *httpStatus(http_status_t status); +extern int httpTrace(http_t *http, const char *uri); +extern http_status_t httpUpdate(http_t *http); +extern int httpWrite(http_t *http, const char *buffer, int length); +extern char *httpEncode64(char *out, const char *in); +extern char *httpDecode64(char *out, const 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..37aab1d981 --- /dev/null +++ b/cups/ipp.c @@ -0,0 +1,1459 @@ +/* + * "$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, unsigned 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 */ + const 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 */ + const char *name, /* I - Name of attribute */ + int num_values, /* I - Number of values */ + const 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 */ + const char *name, /* I - Name of attribute */ + const 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 */ + const 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 */ + const char *name, /* I - Name of attribute */ + int num_values, /* I - Number of values */ + const 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 */ + const char *name, /* I - Name of attribute */ + const char *charset, /* I - Character set */ + const 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 */ + const char *name, /* I - Name of attribute */ + int num_values, /* I - Number of values */ + const char *charset, /* I - Character set */ + const 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 */ + const 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 */ + const char *name, /* I - Name of attribute */ + int num_values, /* I - Number of values */ + const int *lower, /* I - Lower values */ + const 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 */ + const 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 */ + const char *name, /* I - Name of attribute */ + int num_values,/* I - Number of values */ + ipp_res_t units, /* I - Units for resolution */ + const int *xres, /* I - X resolutions */ + const 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(const 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; + + t -= timezone; + + 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 */ + const 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 */ + unsigned 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((char *)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((char *)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((char *)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((char *)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. + */ + +const 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 */ + unsigned 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, (char *)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, (char *)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, (char *)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) +{ + const char *server_port; /* SERVER_PORT environment variable */ + struct servent *port; /* Port number info */ + + + if ((server_port = getenv("IPP_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 */ + unsigned 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, (char *)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..0b343f5610 --- /dev/null +++ b/cups/ipp.h @@ -0,0 +1,343 @@ +/* + * "$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_COLLECTION, + IPP_TAG_TEXTLANG, + IPP_TAG_NAMELANG, + IPP_TAG_TEXT = 0x41, + IPP_TAG_NAME, + IPP_TAG_KEYWORD = 0x44, + 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, + CUPS_SET_DEFAULT +} 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(const ipp_uchar_t *date); +extern ipp_attribute_t *ippAddBoolean(ipp_t *ipp, ipp_tag_t group, const char *name, char value); +extern ipp_attribute_t *ippAddBooleans(ipp_t *ipp, ipp_tag_t group, const char *name, int num_values, const char *values); +extern ipp_attribute_t *ippAddDate(ipp_t *ipp, ipp_tag_t group, const char *name, const ipp_uchar_t *value); +extern ipp_attribute_t *ippAddInteger(ipp_t *ipp, ipp_tag_t group, ipp_tag_t type, const char *name, int value); +extern ipp_attribute_t *ippAddIntegers(ipp_t *ipp, ipp_tag_t group, ipp_tag_t type, const char *name, int num_values, const int *values); +extern ipp_attribute_t *ippAddRange(ipp_t *ipp, ipp_tag_t group, const char *name, int lower, int upper); +extern ipp_attribute_t *ippAddRanges(ipp_t *ipp, ipp_tag_t group, const char *name, int num_values, const int *lower, const int *upper); +extern ipp_attribute_t *ippAddResolution(ipp_t *ipp, ipp_tag_t group, const char *name, ipp_res_t units, int xres, int yres); +extern ipp_attribute_t *ippAddResolutions(ipp_t *ipp, ipp_tag_t group, const char *name, int num_values, ipp_res_t units, const int *xres, const 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, const char *name, const char *charset, const char *value); +extern ipp_attribute_t *ippAddStrings(ipp_t *ipp, ipp_tag_t group, ipp_tag_t type, const char *name, int num_values, const char *charset, const char **values); +extern void ippDelete(ipp_t *ipp); +extern ipp_attribute_t *ippFindAttribute(ipp_t *ipp, const 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 const 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..575344e904 --- /dev/null +++ b/cups/language.c @@ -0,0 +1,373 @@ +/* + * "$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 + * 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: + * + * 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(const char *language) /* I - Language or locale */ +{ + int i, count; /* Looping vars */ + char langname[16], /* Requested language name */ + 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') + strcpy(langname, "C"); + else + strcpy(langname, language); + + if (strlen(langname) < 2) + strcpy(real, "C"); + else + { + real[0] = tolower(langname[0]); + real[1] = tolower(langname[1]); + + if (langname[2] == '_' || langname[2] == '-') + { + real[2] = '_'; + real[3] = toupper(langname[3]); + real[4] = toupper(langname[4]); + real[5] = '\0'; + langname[5] = '\0'; + } + else + { + langname[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, langname) == 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, langname); + + 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..6bdff5a2c0 --- /dev/null +++ b/cups/language.h @@ -0,0 +1,195 @@ +/* + * "$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 + * 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_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_ON, + CUPS_MSG_OFF, + CUPS_MSG_SAVE, + CUPS_MSG_DISCARD, + CUPS_MSG_DEFAULT, + 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_GENERAL, + CUPS_MSG_PRINTER, + CUPS_MSG_IMAGE, + CUPS_MSG_HPGL2, + CUPS_MSG_EXTRA, + CUPS_MSG_DOCUMENT, + CUPS_MSG_OTHER, + CUPS_MSG_PRINT_PAGES, + 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_COLOR_SATURATION, + CUPS_MSG_COLOR_HUE, + CUPS_MSG_FIT_TO_PAGE, + CUPS_MSG_SHADING, + CUPS_MSG_DEFAULT_PEN_WIDTH, + CUPS_MSG_GAMMA_CORRECTION, + CUPS_MSG_BRIGHTNESS, + CUPS_MSG_ADD, + CUPS_MSG_DELETE, + CUPS_MSG_MODIFY, + 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_ALL, + CUPS_MSG_ODD, + CUPS_MSG_EVEN_PAGES, + CUPS_MSG_DARKER_LIGHTER, + CUPS_MSG_MEDIA_SIZE, + CUPS_MSG_MEDIA_TYPE, + CUPS_MSG_MEDIA_SOURCE, + CUPS_MSG_ORIENTATION, + CUPS_MSG_PORTRAIT, + CUPS_MSG_LANDSCAPE, + CUPS_MSG_JOB_STATE, + CUPS_MSG_JOB_NAME, + CUPS_MSG_USER_NAME, + CUPS_MSG_PRIORITY, + CUPS_MSG_COPIES, + CUPS_MSG_FILE_SIZE, + CUPS_MSG_PENDING, + CUPS_MSG_OUTPUT_MODE, + CUPS_MSG_RESOLUTION, + 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, "")) +extern char *cupsLangEncoding(cups_lang_t *lang); +extern void cupsLangFlush(void); +extern void cupsLangFree(cups_lang_t *lang); +extern cups_lang_t *cupsLangGet(const 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..8061766bb5 --- /dev/null +++ b/cups/mark.c @@ -0,0 +1,412 @@ +/* + * "$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. + */ + +/* + * Include necessary headers... + */ + +#include "ppd.h" +#include "string.h" + + +/* + * Local functions... + */ + +static void ppd_defaults(ppd_file_t *ppd, ppd_group_t *g); + + +/* + * '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, k, /* Looping variables */ + conflicts; /* Number of conflicts */ + ppd_const_t *c; /* Current constraint */ + ppd_group_t *g, *sg; /* Groups */ + ppd_option_t *o1, *o2; /* Options */ + ppd_choice_t *c1, *c2; /* Choices */ + + + if (ppd == NULL) + return (0); + + /* + * Clear all conflicts... + */ + + conflicts = 0; + + for (i = ppd->num_groups, g = ppd->groups; i > 0; i --, g ++) + { + for (j = g->num_options, o1 = g->options; j > 0; j --, o1 ++) + o1->conflicted = 0; + + for (j = g->num_subgroups, sg = g->subgroups; j > 0; j --, sg ++) + for (k = sg->num_options, o1 = sg->options; k > 0; k --, o1 ++) + o1->conflicted = 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; + } + } + + /* + * 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 */ + const 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 */ + const 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 */ + const 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 */ + const char *option, /* I - Option/Keyword name */ + const 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(ppd, g); +} + + +/* + * '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 */ + const char *option, /* I - Keyword */ + const 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) + break; + + if (i) + { + /* + * Option found; mark it and then handle unmarking any other options. + */ + + c->marked = 1; + + if (o->ui != PPD_UI_PICKMANY) + for (i = o->num_choices, c = o->choices; i > 0; i --, c ++) + if (strcmp(c->choice, choice) != 0) + 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_file_t *ppd, /* I - PPD file */ + 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) + ppdMarkOption(ppd, o->keyword, o->defchoice); + + for (i = g->num_subgroups, sg = g->subgroups; i > 0; i --, sg ++) + ppd_defaults(ppd, sg); +} + + +/* + * End of "$Id$". + */ diff --git a/cups/mime.c b/cups/mime.c new file mode 100644 index 0000000000..555d50cd01 --- /dev/null +++ b/cups/mime.c @@ -0,0 +1,617 @@ +/* + * "$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 + * 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: + * + * 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.14 1999/07/12 16:09:38 mike + * Fixed all constant arrays to use "const" modifier. + * + * Revision 1.13 1999/06/18 18:36:10 mike + * Fixed address to 44141 Airport View Drive... + * + * 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 */ + const 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..a7625d82fb --- /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 + * 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 _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, const char *pathname); +extern mime_t *mimeNew(void); + +extern mime_type_t *mimeAddType(mime_t *mime, const char *super, const char *type); +extern int mimeAddTypeRule(mime_type_t *mt, const char *rule); +extern mime_type_t *mimeFileType(mime_t *mime, const char *pathname); +extern mime_type_t *mimeType(mime_t *mime, const char *super, const char *type); + +extern mime_filter_t *mimeAddFilter(mime_t *mime, mime_type_t *src, mime_type_t *dst, + int cost, const 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..d5d222ce96 --- /dev/null +++ b/cups/options.c @@ -0,0 +1,378 @@ +/* + * "$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(const char *name, /* I - Name of option */ + const 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. + */ + +const char * /* O - Option value or NULL */ +cupsGetOption(const 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(const 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 *val, /* Pointer into value */ + *ptr, /* Pointer into string */ + s[255]; /* Temporary string */ + + + conflict = 0; + + for (i = num_options; i > 0; i --, options ++) + if (strcmp(options->name, "media") == 0) + { + /* + * Loop through the option string, separating it at commas and + * marking each individual option. + */ + + for (val = options->value; *val;) + { + /* + * Extract the sub-option from the string... + */ + + for (ptr = s; *val && *val != ',' && (ptr - s) < (sizeof(s) - 1);) + *ptr++ = *val++; + *ptr++ = '\0'; + + if (*val == ',') + val ++; + + /* + * Mark it... + */ + + if (ppdMarkOption(ppd, "PageSize", s)) + conflict = 1; + if (ppdMarkOption(ppd, "InputSlot", s)) + conflict = 1; + if (ppdMarkOption(ppd, "MediaType", s)) + conflict = 1; + if (ppdMarkOption(ppd, "EFMediaQualityMode", s)) /* EFI */ + conflict = 1; + if (strcasecmp(s, "manual") == 0) + if (ppdMarkOption(ppd, "ManualFeed", "True")) + conflict = 1; + } + } + else if (strcmp(options->name, "sides") == 0) + { + if (strcmp(options->value, "one-sided") == 0) + { + if (ppdMarkOption(ppd, "Duplex", "None")) + conflict = 1; + if (ppdMarkOption(ppd, "EFDuplex", "None")) /* EFI */ + conflict = 1; + if (ppdMarkOption(ppd, "KD03Duplex", "None")) /* Kodak */ + conflict = 1; + } + else if (strcmp(options->value, "two-sided-long-edge") == 0) + { + if (ppdMarkOption(ppd, "Duplex", "DuplexNoTumble")) + conflict = 1; + if (ppdMarkOption(ppd, "EFDuplex", "DuplexNoTumble")) /* EFI */ + conflict = 1; + if (ppdMarkOption(ppd, "KD03Duplex", "DuplexNoTumble")) /* Kodak */ + conflict = 1; + } + else if (strcmp(options->value, "two-sided-short-edge") == 0) + { + if (ppdMarkOption(ppd, "Duplex", "DuplexTumble")) + conflict = 1; + if (ppdMarkOption(ppd, "EFDuplex", "DuplexTumble")) /* EFI */ + conflict = 1; + if (ppdMarkOption(ppd, "KD03Duplex", "DuplexTumble")) /* Kodak */ + conflict = 1; + } + } + else if (strcmp(options->name, "resolution") == 0) + { + if (ppdMarkOption(ppd, "Resolution", options->value)) + conflict = 1; + if (ppdMarkOption(ppd, "SetResolution", options->value)) + /* Calcomp, Linotype, QMS, Summagraphics, Tektronix, Varityper */ + conflict = 1; + if (ppdMarkOption(ppd, "JCLResolution", options->value)) /* HP */ + conflict = 1; + if (ppdMarkOption(ppd, "CNRes_PGP", options->value)) /* Canon */ + 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..89c88926d1 --- /dev/null +++ b/cups/page.c @@ -0,0 +1,189 @@ +/* + * "$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 */ + const 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 && ppd->variable_sizes) + { + /* + * Find the custom page size... + */ + + for (i = 0; i < ppd->num_sizes; i ++) + if (strcmp("Custom", ppd->sizes[i].name) == 0) + break; + + if (i == ppd->num_sizes) + return (NULL); + + /* + * 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[i].width = w * 72.0; + ppd->sizes[i].length = l * 72.0; + ppd->sizes[i].left = ppd->custom_margins[0]; + ppd->sizes[i].bottom = ppd->custom_margins[1]; + ppd->sizes[i].right = w * 72.0 - ppd->custom_margins[2]; + ppd->sizes[i].top = l * 72.0 - ppd->custom_margins[3]; + } + else if (strcasecmp(units, "cm") == 0) + { + ppd->sizes[i].width = w * 2.54 * 72.0; + ppd->sizes[i].length = l * 2.54 * 72.0; + ppd->sizes[i].left = ppd->custom_margins[0]; + ppd->sizes[i].bottom = ppd->custom_margins[1]; + ppd->sizes[i].right = w * 2.54 * 72.0 - ppd->custom_margins[2]; + ppd->sizes[i].top = l * 2.54 * 72.0 - ppd->custom_margins[3]; + } + else if (strcasecmp(units, "mm") == 0) + { + ppd->sizes[i].width = w * 25.4 * 72.0; + ppd->sizes[i].length = l * 25.4 * 72.0; + ppd->sizes[i].left = ppd->custom_margins[0]; + ppd->sizes[i].bottom = ppd->custom_margins[1]; + ppd->sizes[i].right = w * 25.4 * 72.0 - ppd->custom_margins[2]; + ppd->sizes[i].top = l * 25.4 * 72.0 - ppd->custom_margins[3]; + } + else + { + ppd->sizes[i].width = w; + ppd->sizes[i].length = l; + ppd->sizes[i].left = ppd->custom_margins[0]; + ppd->sizes[i].bottom = ppd->custom_margins[1]; + ppd->sizes[i].right = w - ppd->custom_margins[2]; + ppd->sizes[i].top = l - ppd->custom_margins[3]; + } + + return (ppd->sizes + i); + } + 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 */ + const 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 */ + const 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..d4d2d587f5 --- /dev/null +++ b/cups/ppd.c @@ -0,0 +1,1769 @@ +/* + * "$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. + * compare_strings() - Compare two strings. + * compare_groups() - Compare two groups. + * compare_options() - Compare two options. + * compare_choices() - Compare two choices. + */ + +/* + * Include necessary headers. + */ + +#include "ppd.h" +#include +#include +#include "string.h" +#include "language.h" +#include "debug.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 safe_free(p) if (p) free(p) /* Safe free macro */ + +#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 compare_strings(char *s, char *t); +static int compare_groups(ppd_group_t *g0, ppd_group_t *g1); +static int compare_options(ppd_option_t *o0, ppd_option_t *o1); +static int compare_choices(ppd_choice_t *c0, ppd_choice_t *c1); +static int ppd_read(FILE *fp, char *keyword, char *option, + char *text, char **string); +static void ppd_decode(char *string); +static void ppd_fix(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... + */ + + safe_free(ppd->lang_encoding); + safe_free(ppd->lang_version); + safe_free(ppd->modelname); + safe_free(ppd->ttrasterizer); + safe_free(ppd->manufacturer); + safe_free(ppd->product); + safe_free(ppd->nickname); + safe_free(ppd->shortnickname); + + /* + * Free any emulations... + */ + + if (ppd->num_emulations > 0) + { + for (i = ppd->num_emulations, emul = ppd->emulations; i > 0; i --, emul ++) + { + safe_free(emul->start); + safe_free(emul->stop); + } + + safe_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); + + safe_free(ppd->groups); + } + + /* + * Free any page sizes... + */ + + if (ppd->num_sizes > 0) + safe_free(ppd->sizes); + + /* + * Free any constraints... + */ + + if (ppd->num_consts > 0) + safe_free(ppd->consts); + + /* + * Free any fonts... + */ + + if (ppd->num_fonts > 0) + { + for (i = ppd->num_fonts, font = ppd->fonts; i > 0; i --, font ++) + safe_free(*font); + + safe_free(ppd->fonts); + } + + /* + * Free any profiles... + */ + + if (ppd->num_profiles > 0) + safe_free(ppd->profiles); + + /* + * Free the whole record... + */ + + safe_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); + + safe_free(group->options); + } + + if (group->num_subgroups > 0) + { + for (i = group->num_subgroups, subgroup = group->subgroups; + i > 0; + i --, subgroup ++) + ppd_free_group(subgroup); + + safe_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 ++) + safe_free(choice->code); + + safe_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)); + strncpy(group->text, name, sizeof(group->text) - 1); + } + + 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)); + strncpy(option->keyword, name, sizeof(option->keyword) - 1); + } + + 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)); + strncpy(choice->choice, name, sizeof(choice->choice) - 1); + + 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)); + strncpy(size->name, name, sizeof(size->name) - 1); + + 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 */ + char **filter; /* Pointer to filter */ + cups_lang_t *language; /* Default language */ + + + /* + * Get the default language for the user... + */ + + language = cupsLangDefault(); + + /* + * 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. + */ + + safe_free(string); + + return (NULL); + } + + safe_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)); + strncpy(profile->resolution, name, sizeof(profile->resolution) - 1); + strncpy(profile->media_type, text, sizeof(profile->media_type) - 1); + sscanf(string, "%f%f%f%f%f%f%f%f%f%f%f", &(profile->density), + &(profile->gamma), + 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, "cupsFilter") == 0) + { + if (ppd->num_filters == 0) + filter = malloc(sizeof(char *)); + else + filter = realloc(ppd->filters, sizeof(char *) * (ppd->num_filters + 1)); + + ppd->filters = filter; + filter += ppd->num_filters; + ppd->num_filters ++; + + /* + * Copy filter string and prevent it from being freed below... + */ + + *filter = string; + string = NULL; + } + 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, + cupsLangString(language, + CUPS_MSG_GENERAL))) == NULL) + { + ppdClose(ppd); + safe_free(string); + return (NULL); + } + + if ((option = ppd_get_option(group, "PageSize")) == NULL) + { + ppdClose(ppd); + safe_free(string); + return (NULL); + } + + if ((choice = ppd_add_choice(option, "Custom")) == NULL) + { + ppdClose(ppd); + safe_free(string); + return (NULL); + } + + strncpy(choice->text, cupsLangString(language, CUPS_MSG_VARIABLE), + sizeof(choice->text) - 1); + 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); + safe_free(string); + return (NULL); + } + + if ((choice = ppdFindChoice(option, "Custom")) == NULL) + { + ppdClose(ppd); + safe_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, cupsLangString(language, CUPS_MSG_EXTRA)); + else + group = ppd_get_group(ppd, cupsLangString(language, CUPS_MSG_GENERAL)); + + if (group == NULL) + { + ppdClose(ppd); + safe_free(string); + return (NULL); + } + + option = ppd_get_option(group, name); + group = NULL; + } + else + option = ppd_get_option(group, name); + + if (option == NULL) + { + ppdClose(ppd); + safe_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; + + if (text[0]) + { + strncpy(option->text, text, sizeof(option->text) - 1); + ppd_fix(option->text); + } + else + { + if (strcmp(name, "PageSize") == 0) + strncpy(option->text, cupsLangString(language, CUPS_MSG_MEDIA_SIZE), + sizeof(option->text) - 1); + else if (strcmp(name, "MediaType") == 0) + strncpy(option->text, cupsLangString(language, CUPS_MSG_MEDIA_TYPE), + sizeof(option->text) - 1); + else if (strcmp(name, "InputSlot") == 0) + strncpy(option->text, cupsLangString(language, CUPS_MSG_MEDIA_SOURCE), + sizeof(option->text) - 1); + else if (strcmp(name, "ColorModel") == 0) + strncpy(option->text, cupsLangString(language, CUPS_MSG_OUTPUT_MODE), + sizeof(option->text) - 1); + else if (strcmp(name, "Resolution") == 0) + strncpy(option->text, cupsLangString(language, CUPS_MSG_RESOLUTION), + sizeof(option->text) - 1); + else + strncpy(option->text, name, sizeof(option->text) - 1); + } + + option->section = PPD_ORDER_ANY; + } + else if (strcmp(keyword, "JCLOpenUI") == 0) + { + /* + * Find the JCL group, and add if needed... + */ + + group = ppd_get_group(ppd, "JCL"); + + if (group == NULL) + { + ppdClose(ppd); + safe_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); + safe_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; + + strncpy(option->text, text, sizeof(option->text) - 1); + + 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); + safe_free(string); + return (NULL); + } + + if (strchr(string, '/') != NULL) /* Just show human readable text */ + strcpy(string, strchr(string, '/') + 1); + + ppd_decode(string); + ppd_fix(string); + 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); + safe_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); + safe_free(string); + return (NULL); + } + + group->subgroups = subgroup; + subgroup += group->num_subgroups; + group->num_subgroups ++; + + memset(subgroup, 0, sizeof(ppd_group_t)); + ppd_decode(string); + ppd_fix(string); + strncpy(subgroup->text, string, sizeof(subgroup->text) - 1); + } + 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); + safe_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 (string == NULL) + continue; + + 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) + { + strncpy(group->options[i].defchoice, string, + sizeof(group->options[i].defchoice) - 1); + break; + } + + group = NULL; + } + else + strncpy(option->defchoice, string, sizeof(option->defchoice) - 1); + } + 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); + safe_free(string); + return (NULL); + } + + ppd->consts = constraint; + constraint += ppd->num_consts; + ppd->num_consts ++; + + switch (sscanf(string, "%40s%40s%40s%40s", constraint->option1, + constraint->choice1, constraint->option2, + constraint->choice2)) + { + case 0 : /* Error */ + case 1 : /* Error */ + ppdClose(ppd); + safe_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->choice2, constraint->option2); + 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) + { + strncpy(choice->text, text, sizeof(choice->text) - 1); + ppd_fix(choice->text); + } + else if (strcmp(name, "True") == 0) + strcpy(choice->text, "Yes"); + else if (strcmp(name, "False") == 0) + strcpy(choice->text, "No"); + else + strncpy(choice->text, name, sizeof(choice->text) - 1); + + if (strncmp(keyword, "JCL", 3) == 0) + ppd_decode(string); /* Decode quoted string */ + + choice->code = string; + string = NULL; /* Don't free this string below */ + } + + safe_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... + */ + + qsort(ppd->groups, ppd->num_groups, sizeof(ppd_group_t), + (int (*)(const void *, const void *))compare_groups); + + for (i = ppd->num_groups, group = ppd->groups; + i > 0; + i --, group ++) + { + qsort(group->options, group->num_options, sizeof(ppd_option_t), + (int (*)(const void *, const void *))compare_options); + + for (j = group->num_options, option = group->options; + j > 0; + j --, option ++) + { + qsort(option->choices, option->num_choices, sizeof(ppd_choice_t), + (int (*)(const void *, const void *))compare_choices); + + for (k = 0; k < option->num_choices; k ++) + option->choices[k].option = (void *)option; + } + + qsort(group->subgroups, group->num_subgroups, sizeof(ppd_group_t), + (int (*)(const void *, const void *))compare_groups); + + for (j = group->num_subgroups, subgroup = group->subgroups; + j > 0; + j --, subgroup ++) + { + qsort(subgroup->options, subgroup->num_options, sizeof(ppd_option_t), + (int (*)(const void *, const void *))compare_options); + + for (k = group->num_options, option = group->options; + k > 0; + k --, option ++) + { + qsort(option->choices, option->num_choices, sizeof(ppd_choice_t), + (int (*)(const void *, const void *))compare_choices); + + 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); + + safe_free(fp); + } + else + ppd = NULL; + + return (ppd); +} + + +/* + * 'ppdOpenFile()' - Read a PPD file into memory. + */ + +ppd_file_t * /* O - PPD file record */ +ppdOpenFile(const 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); +} + + +/* + * 'compare_strings()' - Compare two strings. + */ + +int /* O - Result of comparison */ +compare_strings(char *s, /* I - First string */ + char *t) /* I - Second string */ +{ + int diff, /* Difference between digits */ + digits; /* Number of digits */ + + + /* + * Loop through both strings, returning only when a difference is + * seen. Also, compare whole numbers rather than just characters, too! + */ + + while (*s && *t) + { + if (isdigit(*s) && isdigit(*t)) + { + /* + * Got a number; start by skipping leading 0's... + */ + + while (*s == '0') + s ++; + while (*t == '0') + t ++; + + /* + * Skip equal digits... + */ + + while (isdigit(*s) && *s == *t) + { + s ++; + t ++; + } + + /* + * Bounce out if *s and *t aren't both digits... + */ + + if (isdigit(*s) && !isdigit(*t)) + return (1); + else if (!isdigit(*s) && isdigit(*t)) + return (-1); + else if (!isdigit(*s) || !isdigit(*t)) + continue; + + if (*s < *t) + diff = -1; + else + diff = 1; + + /* + * Figure out how many more digits there are... + */ + + digits = 0; + + while (isdigit(*s)) + { + digits ++; + s ++; + } + + while (isdigit(*t)) + { + digits --; + t ++; + } + + /* + * Return if the number or value of the digits is different... + */ + + if (digits < 0) + return (-1); + else if (digits > 0) + return (1); + else + return (diff); + } + else if (tolower(*s) < tolower(*t)) + return (-1); + else if (tolower(*s) > tolower(*t)) + return (1); + else + { + s ++; + t ++; + } + } + + /* + * Return the results of the final comparison... + */ + + if (*s) + return (1); + else if (*t) + return (-1); + else + return (0); +} + + +/* + * 'compare_groups()' - Compare two groups. + */ + +static int /* O - Result of comparison */ +compare_groups(ppd_group_t *g0, /* I - First group */ + ppd_group_t *g1) /* I - Second group */ +{ + return (compare_strings(g0->text, g1->text)); +} + + +/* + * 'compare_options()' - Compare two options. + */ + +static int /* O - Result of comparison */ +compare_options(ppd_option_t *o0,/* I - First option */ + ppd_option_t *o1)/* I - Second option */ +{ + return (compare_strings(o0->text, o1->text)); +} + + +/* + * 'compare_choices()' - Compare two choices. + */ + +static int /* O - Result of comparison */ +compare_choices(ppd_choice_t *c0,/* I - First choice */ + ppd_choice_t *c1)/* I - Second choice */ +{ + return (compare_strings(c0->text, c1->text)); +} + + +/* + * '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'; +} + + +/* + * 'ppd_fix()' - Fix WinANSI characters in the range 0x80 to 0x9f to be + * valid ISO-8859-1 characters... + */ + +static void +ppd_fix(char *string) /* IO - String to fix */ +{ + unsigned char *p; /* Pointer into string */ + static unsigned char lut[32] =/* Lookup table for characters */ + { + 0x20, + 0x20, + 0x20, + 0x20, + 0x20, + 0x20, + 0x20, + 0x20, + 0x20, + 0x20, + 0x20, + 0x20, + 0x20, + 0x20, + 0x20, + 0x20, + 'l', + '`', + '\'', + '^', + '~', + 0x20, /* bar */ + 0x20, /* circumflex */ + 0x20, /* dot */ + 0x20, /* double dot */ + 0x20, + 0x20, /* circle */ + 0x20, /* ??? */ + 0x20, + '\"', /* should be right quotes */ + 0x20, /* ??? */ + 0x20 /* accent */ + }; + + + for (p = (unsigned char *)string; *p; p ++) + if (*p >= 0x80 && *p < 0xa0) + *p = lut[*p - 0x80]; +} + + +/* + * End of "$Id$". + */ diff --git a/cups/ppd.h b/cups/ppd.h new file mode 100644 index 0000000000..75000fe270 --- /dev/null +++ b/cups/ppd.h @@ -0,0 +1,239 @@ +/* + * "$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 */ + gamma, /* Gamma correction 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 */ + int num_filters; /* Number of filters */ + char **filters; /* Filter strings... */ +} 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, const char *keyword, + const char *option); +extern void ppdMarkDefaults(ppd_file_t *ppd); +extern int ppdMarkOption(ppd_file_t *ppd, const char *keyword, + const char *option); +extern ppd_choice_t *ppdFindChoice(ppd_option_t *o, const char *option); +extern ppd_choice_t *ppdFindMarkedChoice(ppd_file_t *ppd, const char *keyword); +extern ppd_option_t *ppdFindOption(ppd_file_t *ppd, const char *keyword); +extern ppd_file_t *ppdOpen(FILE *fp); +extern ppd_file_t *ppdOpenFd(int fd); +extern ppd_file_t *ppdOpenFile(const char *filename); +extern float ppdPageLength(ppd_file_t *ppd, const char *name); +extern ppd_size_t *ppdPageSize(ppd_file_t *ppd, const char *name); +extern float ppdPageWidth(ppd_file_t *ppd, const 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..a435af3ac9 --- /dev/null +++ b/cups/raster.h @@ -0,0 +1,233 @@ +/* + * "$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_GMCK, /* Gold, magenta, yellow, black */ + CUPS_CSPACE_GMCS, /* Gold, magenta, yellow, silver */ + CUPS_CSPACE_WHITE, /* White ink (as black) */ + CUPS_CSPACE_GOLD, /* Gold foil */ + CUPS_CSPACE_SILVER /* Silver foil */ +} 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..4b64cbb4a7 --- /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 + * 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: + * + * 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..a5d130d0e9 --- /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 + * 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_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..b29c3eb2c5 --- /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 + * 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. + */ + +/* + * 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..4724ab524c --- /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 + * 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 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..b2c7bd7e94 --- /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 + * 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: + * + * 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 */ + const 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..23b110a490 --- /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 + * 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: + * + * 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(const char *, FILE *, mime_magic_t *); +static int patmatch(const char *, const 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 */ + const char *super, /* I - Super-type name */ + const 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 */ + const 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 */ + const char *pathname) /* I - Name of file to check */ +{ + int i; /* Looping var */ + FILE *fp; /* File pointer */ + mime_type_t **types; /* File types */ + const 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 */ + const char *super, /* I - Super-type name */ + const 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(const 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 <= 13) || + *bufptr == 26 || *bufptr == 27) + { + 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 <= 13) || + *bufptr == 26 || *bufptr == 27) + { + 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(const char *s, /* I - String to match against */ + const 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/usersys.c b/cups/usersys.c new file mode 100644 index 0000000000..d837f2e9ea --- /dev/null +++ b/cups/usersys.c @@ -0,0 +1,175 @@ +/* + * "$Id$" + * + * User, system, and password 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: + * + */ + +/* + * Include necessary headers... + */ + +#include "cups.h" +#include +#include +#include + + +#if defined(WIN32) || defined(__EMX__) +/* + * WIN32 and OS/2 username and password stuff... + */ + +/* + * 'cupsUser()' - Return the current user's name. + */ + +const char * /* O - User name */ +cupsUser(void) +{ + return ("WindowsUser"); +} + + +/* + * 'cupsGetPassword()' - Get a password from the user... + */ + +const char * /* O - Password */ +cupsGetPassword(const char *prompt) /* I - Prompt string */ +{ + return (NULL); +} +#else +/* + * UNIX username and password stuff... + */ + +# include + +/* + * 'cupsUser()' - Return the current user's name. + */ + +const char * /* O - User name */ +cupsUser(void) +{ + struct passwd *pwd; /* User/password entry */ + + + /* + * Rewind the password file... + */ + + setpwent(); + + /* + * Lookup the password entry for the current user. + */ + + if ((pwd = getpwuid(getuid())) == NULL) + return ("unknown"); /* Unknown user! */ + + /* + * Rewind the password file again and return the username... + */ + + setpwent(); + + return (pwd->pw_name); +} + + +/* + * 'cupsGetPassword()' - Get a password from the user... + */ + +const char * /* O - Password */ +cupsGetPassword(const char *prompt) /* I - Prompt string */ +{ + return (getpass(prompt)); +} +#endif /* WIN32 || __EMX__ */ + + +/* + * 'cupsServer()' - Return the hostname of the default server... + */ + +const char * /* O - Server name */ +cupsServer(void) +{ + FILE *fp; /* cupsd.conf file */ + char *server; /* Pointer to server name */ + static char line[1024]; /* Line from file */ + + + /* + * First see if the CUPS_SERVER environment variable is set... + */ + + if ((server = getenv("CUPS_SERVER")) != NULL) + return (server); + + /* + * Next check to see if we have a cupsd.conf file... + */ + + if ((fp = fopen(CUPS_SERVERROOT "/conf/cupsd.conf", "r")) == NULL) + return ("localhost"); + + /* + * Read the cupsd.conf file and look for a ServerName line... + */ + + while (fgets(line, sizeof(line), fp) != NULL) + if (strncmp(line, "ServerName ", 11) == 0) + { + /* + * Got it! Drop any trailing newline and find the name... + */ + + server = line + strlen(line) - 1; + if (*server == '\n') + *server = '\0'; + + for (server = line + 11; isspace(*server); server ++); + + if (*server) + return (server); + } + + /* + * Didn't see a ServerName line, so return "localhost"... + */ + + fclose(fp); + + return ("localhost"); +} + + +/* + * End of "$Id$". + */ diff --git a/cups/util.c b/cups/util.c new file mode 100644 index 0000000000..e298499cff --- /dev/null +++ b/cups/util.c @@ -0,0 +1,986 @@ +/* + * "$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 + * 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: + * + * cupsCancelJob() - Cancel a print job. + * cupsDoFileRequest() - 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(const char *name, char *printer, char *hostname); + + +/* + * 'cupsCancelJob()' - Cancel a print job. + */ + +int /* O - 1 on success, 0 on failure */ +cupsCancelJob(const 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_OPERATION, IPP_TAG_INTEGER, "job-id", job); + + /* + * Do the request... + */ + + if ((response = cupsDoRequest(cups_server, request, "/jobs/")) == NULL) + return (0); + + ippDelete(response); + return (1); +} + + +/* + * 'cupsDoFileRequest()' - Do an IPP request... + */ + +ipp_t * /* O - Response data */ +cupsDoFileRequest(http_t *http, /* I - HTTP connection to server */ + ipp_t *request, /* I - IPP request */ + const char *resource, /* I - HTTP resource for POST */ + const char *filename) /* I - File to send or NULL */ +{ + ipp_t *response; /* IPP response data */ + char length[255]; /* Content-Length field */ + http_status_t status; /* Status of HTTP request */ + FILE *file; /* File to send */ + struct stat fileinfo; /* File information */ + int bytes; /* Number of bytes read/written */ + char buffer[8192]; /* Output buffer */ + const char *password; /* Password string */ + char plain[255], /* Plaintext username:password */ + encode[255]; /* Encoded username:password */ + static char authstring[255] = ""; + /* Authorization string */ + + + DEBUG_printf(("cupsDoFileRequest(%08x, %08s, \'%s\', \'%s\')\n", + http, request, resource, filename ? filename : "(null)")); + + /* + * See if we have a file to send... + */ + + if (filename != NULL) + { + if (stat(filename, &fileinfo)) + { + /* + * Can't get file information! + */ + + ippDelete(request); + return (NULL); + } + + if ((file = fopen(filename, "rb")) == NULL) + { + /* + * Can't open file! + */ + + ippDelete(request); + return (NULL); + } + } + + /* + * Loop until we can send the request without authorization problems. + */ + + response = NULL; + + while (response == NULL) + { + DEBUG_puts("cupsDoFileRequest: setup..."); + + /* + * Setup the HTTP variables needed... + */ + + if (filename != NULL) + sprintf(length, "%u", ippLength(request) + (size_t)fileinfo.st_size); + else + sprintf(length, "%u", 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... + */ + + DEBUG_puts("cupsDoFileRequest: post..."); + + if (httpPost(http, resource)) + { + httpReconnect(http); + continue; + } + + /* + * Send the IPP data and wait for the response... + */ + + DEBUG_puts("cupsDoFileRequest: ipp write..."); + + request->state = IPP_IDLE; + if (ippWrite(http, request) != IPP_ERROR) + if (filename != NULL) + { + DEBUG_puts("cupsDoFileRequest: file write..."); + + /* + * Send the file... + */ + + rewind(file); + + while ((bytes = fread(buffer, 1, sizeof(buffer), file)) > 0) + if (httpWrite(http, buffer, bytes) < bytes) + break; + } + + /* + * Get the server's return status... + */ + + DEBUG_puts("cupsDoFileRequest: update..."); + + while ((status = httpUpdate(http)) == HTTP_CONTINUE); + + if (status == HTTP_UNAUTHORIZED) + { + DEBUG_puts("cupsDoFileRequest: unauthorized..."); + + /* + * Flush any error message... + */ + + httpFlush(http); + + if ((password = cupsGetPassword("Password:")) != NULL) + { + /* + * Got a password; send it to the server... + */ + + if (!password[0]) + break; + sprintf(plain, "%s:%s", cupsUser(), password); + httpEncode64(encode, plain); + sprintf(authstring, "Basic %s", encode); + + continue; + } + else + break; + } + + if (status != HTTP_OK) + { + DEBUG_printf(("cupsDoFileRequest: error %d...\n", status)); + + /* + * Flush any error message... + */ + + httpFlush(http); + break; + } + else + { + /* + * Read the response... + */ + + DEBUG_puts("cupsDoFileRequest: response..."); + + response = ippNew(); + + if (ippRead(http, response) == IPP_ERROR) + { + /* + * Delete the response... + */ + + ippDelete(response); + response = NULL; + + /* + * Flush any remaining data... + */ + + httpFlush(http); + break; + } + } + } + + /* + * Close the file if needed... + */ + + if (filename != NULL) + fclose(file); + + /* + * 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. + */ + +const 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. + */ + +const char * /* O - Filename for PPD file */ +cupsGetPPD(const 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 */ + + + /* + * 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"; + + sprintf(filename, "%s/%s.ppd", tempdir, printer); +#else + if ((tempdir = getenv("TMPDIR")) == NULL) + tempdir = "/tmp"; + + sprintf(filename, "%s/%d.%s.ppd", tempdir, getuid(), printer); +#endif /* WIN32 || __EMX__ */ + + /* + * And send a request to the HTTP server... + */ + + sprintf(resource, "/printers/%s.ppd", printer); + + httpClearFields(cups_server); + httpSetField(cups_server, HTTP_FIELD_HOST, hostname); + httpGet(cups_server, resource); + + switch (httpUpdate(cups_server)) + { + case HTTP_OK : /* New file - get it! */ + break; + 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(const char *name, /* I - Printer or class name */ + const char *filename, /* I - File to print */ + const 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 */ + 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); + + /* + * Setup a connection and request data... + */ + + if ((request = ippNew()) == NULL) + return (0); + + if (!cups_connect(name, printer, hostname)) + { + DEBUG_printf(("cupsPrintFile: Unable to open connection - %s.\n", + strerror(errno))); + 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_OPERATION, IPP_TAG_MIMETYPE, "document-format", + NULL, "application/vnd.cups-raw"); + else + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format", + NULL, "application/octet-stream"); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", + NULL, cupsUser()); + + if (title) + ippAddString(request, IPP_TAG_OPERATION, 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(("cupsPrintFile: 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(("cupsPrintFile: 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(("cupsPrintFile: Adding resolution option \'%s\' with value %s...\n", + option, val)); + } + else + { + ippAddInteger(request, IPP_TAG_JOB, IPP_TAG_INTEGER, option, n); + + DEBUG_printf(("cupsPrintFile: Adding integer option \'%s\' with value %d...\n", + option, n)); + } + } + else + { + /* + * Boolean value... + */ + + DEBUG_printf(("cupsPrintFile: Adding boolean option \'%s\' with value %d...\n", + option, n)); + ippAddBoolean(request, IPP_TAG_JOB, option, (char)n); + } + } + + /* + * Try printing the file... + */ + + sprintf(uri, "/printers/%s", printer); + + if ((response = cupsDoFileRequest(cups_server, request, uri, filename)) == NULL) + 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; + + if (response != NULL) + ippDelete(response); + + return (jobid); +} + + +/* + * 'cupsTempFile()' - Generate a temporary filename. + */ + +char * /* O - Filename */ +cupsTempFile(char *filename, /* I - Pointer to buffer */ + int len) /* I - Size of buffer */ +{ + char *tmpdir; /* TMPDIR environment var */ + static char buf[1024] = ""; /* Buffer if you pass in NULL and 0 */ + + + /* + * See if a filename was specified... + */ + + if (filename == NULL) + { + filename = buf; + len = sizeof(buf); + } + + /* + * See if TMPDIR is defined... + */ + + if ((tmpdir = getenv("TMPDIR")) == NULL) + tmpdir = "/var/tmp"; + + if ((strlen(tmpdir) + 8) > len) + { + /* + * The specified directory exceeds the size of the buffer; default it... + */ + + strcpy(buf, "/var/tmp/XXXXXX"); + return (mktemp(buf)); + } + else + { + /* + * Make the temporary name using the specified directory... + */ + + sprintf(filename, "%s/XXXXXX", tmpdir); + return (mktemp(filename)); + } +} + + +/* + * 'cups_connect()' - Connect to the specified host... + */ + +static char * /* I - Printer name or NULL */ +cups_connect(const 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, cupsServer()); + + 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/Makefile b/data/Makefile new file mode 100644 index 0000000000..b4c96b0e5d --- /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)/data + $(CP) $(FILES) $(DATADIR)/data + +# +# End of "$Id$". +# diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 0000000000..7a59f9bcc0 --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,109 @@ +# +# "$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: + echo Formatting $@... + htmldoc --title images/cups-large.gif --numbered -f $@ $< +.shtml.pdf: + echo Formatting $@... + 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/cups-block-diagram.gif images/cups-large.gif \ + images/cups-medium.gif images/cups-small.gif +WEBPAGES = cups.css cupsdoc.css index.html documentation.html +WEBIMAGES = images/classes.gif images/logo.gif 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) $(DATADIR)/doc + $(CP) $(WEBPAGES) $(DATADIR)/doc + $(CP) overview.html overview.pdf $(DATADIR)/doc + $(CP) $(DOCUMENTS:.shtml=.html) $(DATADIR)/doc + $(CP) $(DOCUMENTS:.shtml=.pdf) $(DATADIR)/doc + -$(MKDIR) $(DATADIR)/doc/images + $(CP) $(WEBIMAGES) $(DATADIR)/doc/images + $(CP) $(DOCIMAGES) $(DATADIR)/doc/images + +# +# The overview, admin guide, and user's guide get special attention... +# + +overview.pdf: overview.html + echo Formatting $@... + htmldoc --duplex --compression=9 --jpeg --webpage -f $@ $< + +sam.html: sam.shtml + echo Formatting $@... + htmldoc --title images/cups-large.gif -f $@ $< +sam.pdf: sam.shtml + echo Formatting $@... + htmldoc --title images/cups-large.gif --duplex --compression=9 \ + --jpeg -f $@ $< + +sum.html: sum.shtml + echo Formatting $@... + htmldoc --title images/cups-large.gif -f $@ $< +sum.pdf: sum.shtml + echo Formatting $@... + htmldoc --title images/cups-large.gif --duplex --compression=9 \ + --jpeg -f $@ $< + +# +# End of Makefile. +# diff --git a/doc/cmp.html b/doc/cmp.html new file mode 100644 index 0000000000..2ed695324d --- /dev/null +++ b/doc/cmp.html @@ -0,0 +1,651 @@ + + +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.

+

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.

+

1.3 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
  • +
+

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 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: +
    +
    +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
    +
    +
+

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.3 1999/05/21 20:54:04 mike Exp $" tag: +
    +
    +/*
    + * "$Id$"
    + *
    + *   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,v 1.3 1999/05/21 20:54:04 +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: +
    +
    +/*
    + * End of "$Id$".
    + */
    +
    +
+

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: +
    +
    +/*
    + * '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);
    +}
    +
    +
+

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: +
    +
    +/*
    + * '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);
    +}
    +
    +
+

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: +
    +
    +int this_variable;   /* The current state of this */
    +int that_variable;   /* The current state of that */
    +
    +
+

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: +
    +
    +/*
    + * This type is for CUPS foobar options.
    + */
    +typedef int cups_this_type_t;
    +
    +
+

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: +
    +
    +/*
    + * 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 */
    +};
    +
    +
+

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: +
    +
    +/*
    + * 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 */
    +};
    +
    +
+

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: +
    +
    +enum
    +{
    +  CUPS_THIS_TRAY,   /* This tray */
    +  CUPS_THAT_TRAY    /* That tray */
    +};
    +
    +
+

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: +
    +
    +/*
    + * 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])));
    +
    +
+

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: +
    +
    +{
    +  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;
    +}
    +
    +
+

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": +
    +
    +return (STATE_IDLE);
    +
    +
+

B.9.2.d 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;
    +
    +
+

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..95d7b965d0 --- /dev/null +++ b/doc/cmp.pdf @@ -0,0 +1,963 @@ +%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"9½ó+J9%ÒЛB`oC¾„4™aŒöÀŸ«Á·«c»Aì¯ß²» E‹¢Hi»ªÞ{õʕ·V +×ü“Âmº}Ek4oýñ8„tóœoú·=˜g—)Ì$•x5ÿUßÞ$ƒú¾}3Hêˆ$…q†Æ«\Iá™:¸iڄvúuè|­H2¹ZU6†B!ŒXaÁéPja #YÕ_–6*C~°ªøO­ æd!à j*cœ0QÆó¯0ò€Ï¨i7éÔPàŽŠ‚Ñ^¾ÿ†‰åheV0Û9,./î^&³‹ÅüDë«4¹G¹ß +‹É íÝá^{g_åÇíFáöñŸÓx, $ëÅR#Ÿ51ZìÐFí!wѹé»zȗ.p Œ=¬…;’¿D4ûŽaË<·ƒY#yPVIύ¦À¡ LÁyn¬°Ù‚#]EË ¡u­bƒ&#ë‚ G¸•ãf&Zû»™ÞŸÑºÚWÔ¸ã±(x²vpm.$º¤©ºïb,Ç¥ëRãgКÉj_]¸ß/´ÿ± >ێƒÈ®„‰ÍaG;'­iß)ÆépÖ@²ê Xø;Ö¢Ó¿…ß™ðªo\öòÀpß´SY\¦˜#ÛÀÏõ¬Ô.§>†Ö?¿Ë<+¿ÇùsKUؔSŒ&ñógaÌϪt¤ïâ”÷ÓyZ¾r…'Müìíî¬Ä'ÞQœ›â[¥lìC>h¢Úµ{éà:9þ¯Üã³!ƒ„Óðý0oýÕú‰ßksendstream +endobj +200 0 obj +869 +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[<•2‡™6Ós Iò"luj[®$Cø÷]I†˜[Ò)0ƒlíõÛÝOúUó _úð{¦µ›y­u7oó%îôúÌ£«‹ˆg+øý*¸d)Ë´ú8ÿeð<'Ûìôˆ•žÇL1†¬h@.ŚG "¦)OX<[ +™RÍEøS¢!ƒ%îÛÐÆÍ"ˆDX#N6™Æbb@ϞO:¯žWúHxƨ˜& ,Ð|kѼ@Q͐zLGœ»c84©ômB7æ)_icªÀ$Öª(´aêèÔb¥‹¡þu:žÜÏ&D¿è:lbn¦3E9VX0fؒ†#ïsébW»™€éòõÑ4{ʕ.œÒˆ¦t…Fò„Qåš ÷ÔÜ%´ôðÝJšÏHëlhOøºîéëž×:ïô¼lxAFùGjxäl·’¯‘;f× ç&8¯øH’íFˆ¨ߨÜ&¦jvÏï5}Ef£?ÊðQ`^Cx¾òÛÞóGðû~sÐkûû†÷ó"WMCD_̊¹:/ðôô4„Xë|Øjm6rAþX}\ÎøûEÚ«÷|…Ñ7Ã#—å;gä;oÈûgäýcùÖá™Õ4üY=µBk‘þÑÁ¥¥¹y½yráŒî¶ö¬tjüÅàŽ¢\ò›êõ\,'x}Á­ŸÖ/ÞÃ-êò¾®œÕÝòBuéFô¼¨µŒg›m2¯ý[û DÝAYendstream +endobj +236 0 obj +1069 +endobj +237 0 obj<>>>>>endobj +238 0 obj<>stream +xÚÕVQ“Ú6~çWì0™ÉqÆÂ9Hó’ËÝÌ=$½Nè3!¯±ZYr%ù€vúß»² Î¥×´O†ÑZÚOß÷iWð[ALoÉ,|DÑ{¿ìï¦À,3š™]O£kX¦ÎTV dRá[øÁ[N¡預ÎI½éCTŠÖŠVä܃0)Bά5(ãÇW㠃I¼¸š.â)QþávW«~Ô74æÀ®‚ú FH2¦aþ=ñ¹«´ðÒhw\™4Œ ez]µë"ŸxAÆ4ËN¾Ž&³ì[ésà°QfÍ8aJ—s¥È7¼”ž+ù;¦°ºè0Ë\ºþê÷Íè³)Ðç´Û­rHÐ‹h5€%™k´ÚD¶~âN`¶oèèØl¥žlÎäæç‡Ï µG›q:}%זÛ=d'Ò¹9|O©"J‹™ÜÁÖØ”Ò;+³E+¸Ã DT¥;©9Dµ¢†~›üM¿”_ە¢PܒW}繗¢œÊƒ&N{×é•NÑR®ÅP~ +4vÊD45_|˲6¦ÓÐ\ÿ‚Om¦0’I4;Æ>Q¨?£¿Y·œü=ø}øÄjaŠ€9rÒBʝ°rzqš¯î¬CzjÐ ëGÇ•º¬<l!ý×¢©Ï¹Þ¯ÃÚ¾³fóð[F“õ/љÜT¶AüÈ5ß`­ÿAñÚÛ¾¡¬Ñ›I’Ø4>>>>>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 +0000026140 00000 n +0000026161 00000 n +0000026274 00000 n +0000026462 00000 n +0000026483 00000 n +0000026623 00000 n +0000027216 00000 n +0000027237 00000 n +0000027350 00000 n +0000027543 00000 n +0000027564 00000 n +0000027695 00000 n +0000028308 00000 n +0000028329 00000 n +0000028442 00000 n +0000028631 00000 n +0000028652 00000 n +0000028783 00000 n +0000029727 00000 n +0000029748 00000 n +0000029879 00000 n +0000030166 00000 n +0000030187 00000 n +0000030327 00000 n +0000031243 00000 n +0000031264 00000 n +0000031395 00000 n +0000031753 00000 n +0000031774 00000 n +0000031914 00000 n +0000032410 00000 n +0000032431 00000 n +0000032562 00000 n +0000033014 00000 n +0000033035 00000 n +0000033175 00000 n +0000034315 00000 n +0000034337 00000 n +0000034477 00000 n +0000035383 00000 n +0000035404 00000 n +0000035544 00000 n +0000036470 00000 n +0000036491 00000 n +0000036631 00000 n +0000037277 00000 n +0000037298 00000 n +0000037438 00000 n +0000038258 00000 n +0000038279 00000 n +0000038419 00000 n +0000039346 00000 n +0000039367 00000 n +0000039507 00000 n +0000039911 00000 n +0000039932 00000 n +0000040045 00000 n +0000040251 00000 n +0000040272 00000 n +0000040427 00000 n +0000042482 00000 n +0000042504 00000 n +0000042659 00000 n +0000043440 00000 n +0000043461 00000 n +0000043516 00000 n +0000043621 00000 n +0000043765 00000 n +0000043871 00000 n +0000043991 00000 n +0000044100 00000 n +0000044249 00000 n +0000044359 00000 n +0000044466 00000 n +0000044620 00000 n +0000044731 00000 n +0000044848 00000 n +0000044964 00000 n +0000045128 00000 n +0000045234 00000 n +0000045353 00000 n +0000045468 00000 n +0000045572 00000 n +0000045728 00000 n +0000045837 00000 n +0000045952 00000 n +0000046064 00000 n +0000046163 00000 n +0000046310 00000 n +0000046407 00000 n +0000046507 00000 n +0000046665 00000 n +0000046805 00000 n +0000046905 00000 n +0000047012 00000 n +0000047162 00000 n +0000047262 00000 n +0000047369 00000 n +0000047517 00000 n +0000047617 00000 n +0000047724 00000 n +0000047874 00000 n +0000047974 00000 n +0000048081 00000 n +0000048227 00000 n +0000048327 00000 n +0000048434 00000 n +0000048585 00000 n +0000048685 00000 n +0000048792 00000 n +0000048940 00000 n +0000049040 00000 n +0000049147 00000 n +0000049297 00000 n +0000049397 00000 n +0000049504 00000 n +0000049636 00000 n +0000049743 00000 n +0000049842 00000 n +0000049960 00000 n +trailer +<> +startxref +50146 +%%EOF diff --git a/doc/cmp.shtml b/doc/cmp.shtml new file mode 100644 index 0000000000..cc6315d3f1 --- /dev/null +++ b/doc/cmp.shtml @@ -0,0 +1,717 @@ + + + + + + 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. + +

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. + +

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 351 1999-05-21 20:54:09Z mike $" tag: + +
    +
    +/*
    + * "$Id: cmp.shtml 351 1999-05-21 20:54:09Z 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 351 1999-05-21 20:54:09Z 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 351 1999-05-21 20:54:09Z 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..d5f37fa431 --- /dev/null +++ b/doc/cups.css @@ -0,0 +1,4 @@ +BODY { background-color: #cccc99 } +H1 { font-family: sans-serif; } +H2 { font-family: sans-serif; } +TH { background-color: #999966 } diff --git a/doc/cupsdoc.css b/doc/cupsdoc.css new file mode 100644 index 0000000000..333f20144d --- /dev/null +++ b/doc/cupsdoc.css @@ -0,0 +1,9 @@ +H1 { font-family: sans-serif } +H2 { font-family: sans-serif } +H3 { font-family: sans-serif } +H4 { font-family: sans-serif } +H5 { font-family: sans-serif } +H6 { font-family: sans-serif } +SUP { font-family: sans-serif; font-size: 6pt } +PRE { margin-left: 2em } +CODE { font-weight: bold } diff --git a/doc/documentation.html b/doc/documentation.html new file mode 100644 index 0000000000..e8803fcb5c --- /dev/null +++ b/doc/documentation.html @@ -0,0 +1,70 @@ + + + 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 for CUPS is available on this server: + +
    + +
  • Whitepaper - An Overview of the Common UNIX Printing System ( + HTML | + PDF ) + +
  • Software Users Manual ( + HTML | + PDF ) + +
  • Software Administrators Manual ( + HTML | + PDF ) + +
  • 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 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 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 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..d003eeb5db --- /dev/null +++ b/doc/idd.html @@ -0,0 +1,746 @@ + + +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 5 - Directories +
+
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.

+

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.

+

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 - Directories
  • +
  • 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

+

The character set files define a mapping between 8-bit characters +and the Unicode character set. They are named using the ISO standard +number defined for the character set. Each file consists of up to 256 +lines of ASCII text. Each line consists of two hexadecimal numbers; the +first number is the character number in the character set (0x00 to +0xff), and the second number is the Unicode character number (0x0000 to +0xffff).

+

3.2 Language Files

+

The language files define the default character set and a collection +of text messages in that language. They are named by prefixing the +string "cups_" to the front of the language specifier (e.g. "cups_en", +"cups_fr", etc.) Each file consists of two or more lines of ASCII text.

+

The first line identifies the character set to be used for the +messages. The currently recognized values are:

+
    +
  • us-ascii
  • +
  • utf-8
  • +
  • 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
  • +
  • iso-8859-14
  • +
  • iso-8859-15
  • +
+

The second and succeeding lines define text messages. If the message +text is preceded by a number, then the current message number is +updated and the text after the number is used.

+

3.3 MIME Files

+

CUPS uses two MIME files in its standard configuration.

+

3.3.1 mime.types

+

The mime.types file defines the recognized file types and consists +of 1 or more lines of ASCII text. Comment lines start with the pound +("#") character. The backslash ("\") character can be used at the end +of a line to continue that line to the next.

+

Each non-blank line starts with a MIME type identifier +("super/type") as registered with the IANA. All text following the MIME +type is treated as a series of type recognition rules:

+
    +
    +mime-type := super "/" type { SP rule }*
    +super := { "a-z" | "A-Z" }*
    +type := { "a-z" | "A-Z" | "-" | "." | "0-9" }*
    +rule := { extension | match | operator | "(" rule ")" }*
    +extension := { "a-z" | "A-Z" | "0-9" }*
    +match := "match(" regexp ")" |
    +         "ascii(" offset "," length ")" |
    +	 "printable(" offset "," length ")" |
    +	 "string(" offset "," string ")" |
    +	 "char(" offset "," value ")" |
    +	 "short(" offset "," value ")" |
    +	 "int(" offset "," value ")" |
    +	 "locale(" string ")"
    +operator := "+" |	[ logical AND ]
    +            "," | SP    [ logical OR ]
    +	    "!"         [ unary NOT ]
    +
    +
+

The int and short rules match look for +integers in network byte order (a.k.a. big-endian) with the +most-significant byte first.

+

3.3.2 mime.convs

+

The mime.types file defines the recognized file filters and consists +of 1 or more lines of ASCII text. Comment lines start with the pound +("#") character.

+

Each non-blank line starts with two MIME type identifiers +("super/type") representing the source and destination types. Following +the MIME types are a cost value (0 to 100) and the filter program to +use. If the filter program is not specified using the full path then it +must reside in the CUPS filter directory.

+

3.4 PostScript Printer Description Files

+

The PostScript Printer Description (PPD) file format is described in +Adobe TechNote #5003: PostScript Printer Description File Format +Specification Version 4.3.

+

3.4.1 CUPS Extensions to PPD Files

+

CUPS adds several new attributes that are described below.

+

3.4.1.1 cupsFilter

+

This string attribute provides a conversion rule of the form:

+
    +
    +source/type cost program
    +
    +
+

The destination type is assumed to the printer's type. If a printer +supports the source type directly the special filter program "-" may be +specified.

+

3.4.1.2 cupsManualCopies

+

This boolean attribute notifies the RIP filters that the destination +printer does not support copy generation in hardware. The default value +is false.

+

3.4.1.3 cupsModelNumber

+

This integer attribute specifies a printer-specific model number. +This number can be used by a filter program to adjust the output for a +specific model of printer.

+

3.4.1.4 cupsProfile

+

This string attribute specifies a color profile of the form:

+
    +
    +resolution/type density gamma m00 m01 m02 m10 m11 m12 m20 m21 m22
    +
    +
+

The resolution and type values may be "-" to act as a +wildcard. Otherwise they must match one of the Resolution + or MediaType attributes defined in the PPD file.

+

The density and gamma values define gamma and density +adjustment function such that:

+
    +
    +f(x) = density * xgamma
    +
    +
+

The m00 through m22 values define a 3x3 transformation +matrix for the CMY color values. The density function is applied +after the CMY transformation.

+

3.4.1.5 cupsVersion

+

This required attribute describes which version of the CUPS IDD was +used for the PPD file extensions. Currently it must be the string +"1.0".

+

3.5 Scheduler Configuration Files

+

The scheduler reads three configuration files that define the +available printers, classes, and services:

+
+
classes.conf
+
This file defines all of the printer classes known to the system.
+
cupsd.conf
+
This file defines the files, directories, passwords, etc. used by +the scheduler.
+
printers.conf
+
This file defines all of the printers known to the system.
+
+

3.5.1 classes.conf

+

The classes.conf file consists of 1 or more lines of ASCII text. + Comment lines start with the pound ("#") character.

+

Each non-blank line starts with the name of a configuration +directive followed by its value. The following directives are +understood: +

+ + + + + + + + +
DirectiveDescription
<Class name> +
</Class>
<DefaultClass name> +
</Class>
Info
Location
MoreInfo
Printer
+
+

+

3.5.2 cupsd.conf

+

The cupsd.conf file consists of 1 or more lines of ASCII text. + Comment lines start with the pound ("#") character.

+

Each non-blank line starts with the name of a configuration +directive followed by its value. The following directives are +understood: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DirectiveDefaultDescription
AccessLogSpecifies the location of the access log +file (default "logs/access_log").
Allow
AuthClass
AuthType
BrowseAddress
BrowseInterval
BrowsePort
BrowseTimeout
Browsing
DefaultCharset
DefaultLanguage
Deny
DocumentRoot
ErrorLog
Group
HostNameLookups
ImplicitClasses
KeepAlive
KeepAliveTimeout
<Location path> +
</Location>
LogLevel
MaxClients
MaxLogSize
MaxRequestSize
Order
PageLog
Port
RIPCache
ServerAdmin
ServerName
ServerRoot
SystemGroup
TempDir
Timeout
User
+
+

+

3.5.3 printers.conf

+

The printers.conf file consists of 1 or more lines of ASCII text. + Comment lines start with the pound ("#") character.

+

Each non-blank line starts with the name of a configuration +directive followed by its value. The following directives are +understood: +

+ + + + + + + + + +
DirectiveDescription
<DefaultPrinter name> +
</Printer>
DeviceURI
Info
Location
MoreInfo
<Printer name> +
</Printer>
State
+
+

+

4 External Interfaces

+

4.1 AppSocket Protocol

+

The AppSocket protocol is an 8-bit clean TCP/IP socket connection. +The default IP service port is 9100.

+

4.2 CUPS Browsing Protocol

+

The CUPS Browsing Protocol is a UDP/IP-based broadcast service. By +default this service operates on IP service port 631.

+

Each broadcast packet describes the state of a single printer or +class and is an ASCII text string of up to 1450 bytes ending with a +newline (0x0a). The string is formatted as follows:

+
    +
    +type SP state SP uri NL
    +
    +
+

The state and uri values correspond to the IPP +printer-state and printer-uri-supported attributes.

+

The type value is a hexadecimal number string representing +capability/type bits: +

+ + + + + + + + + + + + + + + + + + +
BitDescription
00 = printer +
1 = class
10 = local +
1 = remote +
(always 1)
21 = can print B
31 = can print color
41 = can duplex
51 = can staple
61 = can do fast copies
71 = can do fast collating
81 = can punch holes
91 = can cover
101 = can bind
111 = can sort
121 = can print up to 9x14 inches
131 = can print up to 18x24 inches
141 = can print up to 36x48 inches
151 = can print variable sizes
+
+

+

4.3 CUPS PostScript File

+

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

+

The MIME type for CUPS PostScript files is +application/vnd.cups-postscript.

+

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 +points
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 +points
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 points
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-339NegativePrint0 = Do not invert prints +
1 = Invert prints
340-343NumCopies1 to 232 - 1
344-347Orientation0 = Do not rotate page +
1 = Rotate page counter-clockwise +
2 = Turn page upside down +
3 = Rotate page clockwise
348-351OutputFaceUp0 = Output face down +
1 = Output face up
352-359PageSizeWidth and length in points
360-363Separations0 = Print composite image +
1 = Print color separations
364-367TraySwitch0 = Do not change trays if +selected tray is empty +
1 = Change trays if selected tray is empty
368-371Tumble0 = Do not rotate even pages +when duplexing +
1 = Rotate even pages when duplexing
372-375cupsWidthWidth of page image in pixels
376-379cupsHeightHeight of page image in +pixels
380-383cupsMediaTypeDriver-specific 0 to 2 +32 - 1
384-387cupsBitsPerColor1, 2, 4, 8 bits
388-391cupsBitsPerPixel1 to 32 bits
392-395cupsBytesPerLine1 to 232 - +1 bytes
396-399cupsColorOrder0 = chunky pixels (CMYK +CMYK CMYK) +
1 = banded pixels (CCC MMM YYY KKK) +
2 = planar pixels (CCC... MMM... YYY... KKK...)
400-403cupsColorSpace0 = white +
1 = RGB +
2 = RGBA +
3 = black +
4 = CMY +
5 = YMC +
6 = CMYK +
7 = YMCK +
8 = KCMY +
9 = KCMYcm
404-407cupsCompressionDriver-specific 0 to 2 +32 - 1
408-411cupsRowCountDriver-specific 0 to 2 +32 - 1
412-415cupsRowFeedDriver-specific 0 to 2 +32 - 1
416-419cupsRowStepDriver-specific 0 to 2 +32 - 1
+
+

+

The MIME type for CUPS Raster files is +application/vnd.cups-raster.

+

4.5 CUPS Raw Files

+

Raw files are printer-dependent print files that are in a format +suitable to the destination printer (e.g. HP-PCL, HP-RTL, etc.) The +MIME type for CUPS Raw files is application/vnd.cups-raw.

+

4.6 File Transfer Protocol

+

The File Transfer Protocol (FTP) is described by +RFC 959: File Transfer Protocol.

+

4.7 Internet Printing Protocol

+

The Internet Printing Protocol is described by the following RFCs:

+ +

CUPS defines the following extension operations to IPP.

+

4.7.1 Get Default Destination (CUPS_GET_DEFAULT = +0x4001)

+

The get default destination operation returns the printer attributes +for the system default printer or class. The only required attributes +are attributes-charset and +attributes-natural-language.

+

Get default destination will only return ipp-ok.

+

4.7.2 Get Printers (CUPS_GET_PRINTERS = 0x4002)

+

The get printers operation returns the printer attributes for all +printers known to the system. The only required attributes are +attributes-charset and attributes-natural-language.

+

Get printers will only return ipp-ok.

+

4.7.3 Add Printer (CUPS_ADD_PRINTER = 0x4003)

+

The add printer operation adds or replaces the specified printer. +The attributes-charset, attributes-natural-language + and printer-uri attributes are required.

+

The printer-location, printer-info, +printer-more-info, and device-uri attributes are +required when initially adding a printer and optional when modifying a +printer.

+

A PPD file or System V interface script may follow the IPP request +body. If a valid interface script or PPD file is not provided then the +printer is treated as a generic PostScript device.

+

Add printer will return ipp-ok, ipp-not-authorized +, ipp-bad-request, or ipp-attributes.

+

4.7.4 Delete Printer (CUPS_DELETE_PRINTER = 0x4004) +

+

The delete printer operation removes the specified printer. The only +required attributes are attributes-charset, +attributes-natural-language, and printer-uri.

+

Delete printer will return ipp-ok, ipp-not-found +, or ipp-not-authorized.

+

4.7.5 Get Classes (CUPS_GET_CLASSES = 0x4005)

+

The get classes operation returns the printer attributes for all +classes known to the system. The only required attributes are +attributes-charset and attributes-natural-language.

+

Get classes will only return ipp-ok.

+

4.7.6 Add Class (CUPS_ADD_CLASS = 0x4006)

+

The add class operation adds or replaces the specified class. The +attributes-charset, attributes-natural-language, +and printer-uri attributes are required.

+

The printer-location, printer-info, +printer-more-info, and member-uris attributes are +required when initially adding a printer and optional when modifying a +printer.

+

Add class will return ipp-ok, ipp-not-authorized +, ipp-bad-request, or ipp-attributes.

+

4.7.7 Delete Class (CUPS_DELETE_CLASS = 0x4007)

+

The delete class operation removes the specified class. The only +required attributes are attributes-charset, +attributes-natural-language, and printer-uri.

+

Delete class will return ipp-ok, ipp-not-found +, or ipp-not-authorized.

+

4.7.8 Accept Jobs (CUPS_ACCEPT_JOBS = 0x4008)

+

The accept jobs operation allows jobs to be accepted by the +specified destination. The only required attributes are +attributes-charset, attributes-natural-language, +and printer-uri.

+

Accept jobs will return ipp-ok, ipp-not-found +, or ipp-not-authorized.

+

4.7.9 Reject Jobs (CUPS_REJECT_JOBS = 0x4009)

+

The reject jobs operation prevents jobs from being accepted by the +specified destination. The only required attributes are +attributes-charset, attributes-natural-language, +and printer-uri.

+

Reject jobs will return ipp-ok, ipp-not-found +, or ipp-not-authorized.

+

4.7.10 Set Default Destination (CUPS_SET_DEFAULT = +0x400A)

+

The set default destination operation returns the printer attributes +for the system default printer or class. The only required attributes +are attributes-charset, attributes-natural-language +, and printer-uri.

+

Set default destination will return ipp-ok, +ipp-not-authorized, ipp-bad-request, or +ipp-not-found.

+

4.8 Line Printer Daemon Protocol

+

The Line Printer Daemon (LPD) protocol is described by +RFC 1179: Line Printer Daemon Protocol.

+

4.9 Server Message Block Protocol

+

The Server Message Block (SMB) and related Common Internet File +System (CIFS) protocols are described at +http://anu.samba.org/cifs.

+

4.10 Trivial File Transfer Protocol

+

The Trivial File Transfer Protocol (TFTP) is described by +RFC 1350: The TFTP Protocol (Revision 2).

+

5 5 - Directories

+
+
/usr/bin
+
The cancel, lp, lpq, +lpr, lprm, and lpstat commands reside +here.
+
/usr/lib
+
The accept, disable, enable, +lpadmin, and reject commands reside here.
+
/usr/sbin
+
The lpc and cupsd commands resize here.
+
/usr/share/cups
+
This is the root directory of the CUPS static data.
+
/usr/share/cups/data
+
The character set and filter data files reside here.
+
/usr/share/cups/fonts
+
The pstoraster font files reside here.
+
/usr/share/cups/model
+
The sample PPD files reside here.
+
/usr/share/cups/pstoraster
+
The pstoraster data files reside here.
+
/var/cups
+
This is the root directory of the CUPS scheduler.
+
/var/cups/backend
+
The backend filters reside here.
+
/var/cups/cgi-bin
+
The CGI programs reside here.
+
/var/cups/conf
+
The scheduler configuration and MIME files reside here.
+
/var/cups/doc
+
The scheduler documentation files reside here.
+
/var/cups/filter
+
The file filters reside here.
+
/var/cups/interfaces
+
System V interface scripts reside here.
+
/var/cups/logs
+
The access_log, error_log, and +page_log files reside here.
+
/var/cups/ppd
+
This directory contains PPD files for each printer.
+
/var/cups/requests
+
This directory contains pending print job files.
+
+

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..00c4bcb26c --- /dev/null +++ b/doc/idd.pdf @@ -0,0 +1,1577 @@ +%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[11 0 R +13 0 R +15 0 R +17 0 R +19 0 R +21 0 R +23 0 R +25 0 R +27 0 R +29 0 R +31 0 R +]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[34 0 R +36 0 R +38 0 R +40 0 R +42 0 R +44 0 R +46 0 R +]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<>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[49 0 R +51 0 R +53 0 R +55 0 R +57 0 R +59 0 R +61 0 R +63 0 R +65 0 R +67 0 R +69 0 R +71 0 R +73 0 R +75 0 R +77 0 R +79 0 R +81 0 R +83 0 R +85 0 R +87 0 R +89 0 R +91 0 R +93 0 R +95 0 R +97 0 R +99 0 R +101 0 R +103 0 R +105 0 R +107 0 R +109 0 R +111 0 R +113 0 R +115 0 R +117 0 R +119 0 R +121 0 R +123 0 R +125 0 R +127 0 R +129 0 R +131 0 R +133 0 R +135 0 R +137 0 R +139 0 R +141 0 R +143 0 R +145 0 R +147 0 R +149 0 R +151 0 R +153 0 R +155 0 R +]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[158 0 R +160 0 R +162 0 R +164 0 R +166 0 R +168 0 R +170 0 R +172 0 R +174 0 R +176 0 R +178 0 R +180 0 R +182 0 R +184 0 R +]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<>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<>endobj +248 0 obj<>endobj +249 0 obj<>endobj +250 0 obj<>endobj +251 0 obj<>endobj +252 0 obj<>endobj +253 0 obj<>endobj +254 0 obj<>endobj +255 0 obj<>endobj +256 0 obj<>endobj +257 0 obj<>endobj +258 0 obj<>endobj +259 0 obj<>endobj +260 0 obj<>endobj +261 0 obj<>endobj +262 0 obj<>endobj +263 0 obj<>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<>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<>endobj +335 0 obj<>endobj +336 0 obj<>endobj +337 0 obj<>endobj +338 0 obj<>endobj +339 0 obj<>endobj +340 0 obj<>endobj +341 0 obj<>endobj +342 0 obj<>endobj +343 0 obj<>endobj +344 0 obj<>endobj +345 0 obj<>endobj +346 0 obj<>endobj +347 0 obj<>endobj +348 0 obj<>endobj +349 0 obj<>endobj +350 0 obj<>endobj +351 0 obj<>endobj +352 0 obj<>endobj +353 0 obj<>endobj +354 0 obj<>endobj +355 0 obj[186 0 R +187 0 R +188 0 R +189 0 R +190 0 R +191 0 R +192 0 R +193 0 R +194 0 R +195 0 R +196 0 R +197 0 R +198 0 R +199 0 R +200 0 R +201 0 R +202 0 R +203 0 R +204 0 R +205 0 R +206 0 R +207 0 R +208 0 R +209 0 R +210 0 R +211 0 R +212 0 R +213 0 R +214 0 R +215 0 R +216 0 R +217 0 R +218 0 R +219 0 R +220 0 R +221 0 R +222 0 R +223 0 R +224 0 R +225 0 R +226 0 R +227 0 R +228 0 R +229 0 R +230 0 R +231 0 R +232 0 R +233 0 R +234 0 R +235 0 R +236 0 R +237 0 R +238 0 R +239 0 R +240 0 R +241 0 R +242 0 R +243 0 R +244 0 R +245 0 R +246 0 R +247 0 R +248 0 R +249 0 R +250 0 R +251 0 R +252 0 R +253 0 R +254 0 R +255 0 R +256 0 R +257 0 R +258 0 R +259 0 R +260 0 R +261 0 R +262 0 R +263 0 R +264 0 R +265 0 R +266 0 R +267 0 R +268 0 R +269 0 R +270 0 R +271 0 R +272 0 R +273 0 R +274 0 R +275 0 R +276 0 R +277 0 R +278 0 R +279 0 R +280 0 R +281 0 R +282 0 R +283 0 R +284 0 R +285 0 R +286 0 R +287 0 R +288 0 R +289 0 R +290 0 R +291 0 R +292 0 R +293 0 R +294 0 R +295 0 R +296 0 R +297 0 R +298 0 R +299 0 R +300 0 R +301 0 R +302 0 R +303 0 R +304 0 R +305 0 R +306 0 R +307 0 R +308 0 R +309 0 R +310 0 R +311 0 R +312 0 R +313 0 R +314 0 R +315 0 R +316 0 R +317 0 R +318 0 R +319 0 R +320 0 R +321 0 R +322 0 R +323 0 R +324 0 R +325 0 R +326 0 R +327 0 R +328 0 R +329 0 R +330 0 R +331 0 R +332 0 R +333 0 R +334 0 R +335 0 R +336 0 R +337 0 R +338 0 R +339 0 R +340 0 R +341 0 R +342 0 R +343 0 R +344 0 R +345 0 R +346 0 R +347 0 R +348 0 R +349 0 R +350 0 R +351 0 R +352 0 R +353 0 R +354 0 R +]endobj +356 0 obj<>endobj +357 0 obj<>endobj +358 0 obj<>endobj +359 0 obj<>endobj +360 0 obj[356 0 R +357 0 R +358 0 R +359 0 R +]endobj +361 0 obj<>endobj +362 0 obj<>endobj +363 0 obj<>endobj +364 0 obj<>endobj +365 0 obj<>endobj +366 0 obj<>endobj +367 0 obj<>endobj +368 0 obj<>endobj +369 0 obj<>endobj +370 0 obj<>endobj +371 0 obj<>endobj +372 0 obj<>endobj +373 0 obj<>endobj +374 0 obj<>endobj +375 0 obj<>endobj +376 0 obj<>endobj +377 0 obj<>endobj +378 0 obj<>endobj +379 0 obj<>endobj +380 0 obj<>endobj +381 0 obj<>endobj +382 0 obj<>endobj +383 0 obj<>endobj +384 0 obj<>endobj +385 0 obj<>endobj +386 0 obj<>endobj +387 0 obj<>endobj +388 0 obj<>endobj +389 0 obj<>endobj +390 0 obj<>endobj +391 0 obj<>endobj +392 0 obj<>endobj +393 0 obj<>endobj +394 0 obj<>endobj +395 0 obj<>endobj +396 0 obj<>endobj +397 0 obj<>endobj +398 0 obj<>endobj +399 0 obj<>endobj +400 0 obj<>endobj +401 0 obj<>endobj +402 0 obj<>endobj +403 0 obj<>endobj +404 0 obj<>endobj +405 0 obj<>endobj +406 0 obj<>endobj +407 0 obj<>endobj +408 0 obj<>endobj +409 0 obj<>>>>>endobj +410 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 +411 0 obj +6325 +endobj +412 0 obj<>>>>>endobj +413 0 obj<>stream +xÚ+ä2T0BCc3JÎår +ár á +äHÉHendstream +endobj +414 0 obj +31 +endobj +415 0 obj<>>>>>endobj +416 0 obj<>stream +xÚ¥U[OA~çWœø¤‰l]nBßTԐ¨Ý +š>ð2ÌÎÂèìžufJ}ÏÌ,B©5š†DâœÛ÷}çÂK#†úÄpڂvxÞ8Ÿ4¾\ À$#Kï´“ô0†1ÇRMž‚µõƒ½ÙíGÁ#Ša”ŠÂÊLrf%Á¹q\»¶QϹNҀ,¬ÐãRaä¼p_\ËÒEBмÊ)”—’,dµL*‘BF!C3kŽ!ưùÎ+R4×,wõ©j܎Z®*Çbéàaaœ;؅€ Ìs*÷p7ú‰&H²˜Ãxm¬ÈazxpñŒ¦Gð(´q°âè$zCâUKÐÚ[ +½”bõŽïW%ΠDmٌX—ÅÖB{.vÚêö€š£™7ŸÀD0²°`fO…™Nê¥P‘Âl —̬aŒ™]1-¦·,: 9ZAŒ%]™N· ªÊ·Ê¡`J$pŠÚ¸.ìÕ­ iStË͵ æûè;w.ô³Pb œ¤¡‡¦’…ØŽŠ‰ê¬­^Pܧ£Ô!ÕÈùÂnÅ$69*jæèrrÕ% µ“÷32Œ•bsçïéÁÎ<x©DEEšµGçÆáòe¨C&\§‡7Éðî¯.âøt0=:†1 Ùoë!=WȟÉm|{ÂYYŽéQøI÷P©2µ)ƒ{%MUºI ¦­¤]€Ô'·UÁ]#˜’vý¦>,M ,+Ôρ!aši\GÙ¡HÐØ±_¾-§m¤MH’!-B“$;C€eX'û¬’) º*V–ª> ª"axßFLì©ë\Uaxe,æòÕ^Ö«ˆ\ß=Àõb }zÈ+­iÅÕPÌþöêD'íéÑ^'+@æþ–¸ s?JhH˜Nï3á†,u;±aV`Ñܑ­–Õ¼Ú0ܶˆIrD=g…ˆBЏw†JáÊïªðb¾†b¼.ÖêùWá§­Þ)ü‰†®~s÷îó-ʍpoEQR¸™ VÐÊ~*´M¡a‹inF¯kÿ©Êqùóÿrt)ÇPjÒ µüdìÅ^+¤•×ë`êצfP<îîÿ¤vú'рòºW÷ÿå¤ñ½ñ…KZendstream +endobj +417 0 obj +837 +endobj +418 0 obj<>>>>>endobj +419 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 +420 0 obj +120 +endobj +421 0 obj<>>>>>endobj +422 0 obj<>stream +xÚ­•AsÚ0…ïüŠ=’™ØÁ†`Íé0S&69qQ­5¨cKT“òï+!C ¥âf|°Á«ï­´ïÁ÷Vs…ÐíC^µ>e­‡§È +ó¦õ £íX Dž£ºË¾¹’G?vEÞcì»2?€ñ2Ia"ò]…\Íw zuywà÷my¶A(DYŠ7Æ×n!=_L<êRøº½1_k†œ×à0öCð¾keö#¸Tn[o>>>>>endobj +425 0 obj<>stream +xÚ-‹Á +Â0DïûsÔC´›”êµZ Þ´® q#ŒšöÿшÌÀ03¼71ª¯®)öÚ-û5˜!ìV¶‚\gÝÐöƒíùpÂ>MšÃÅ+:ã-•ð9¾¦øLs¹“) ù“uYjˋ¿n1hЬÉëX®Ð‘>H.#ùendstream +endobj +426 0 obj +123 +endobj +427 0 obj<>>>>>endobj +428 0 obj<>stream +xڝVÑn›0}ÏW\õ©• + $!d{ÚªVŠ´j›Bß"MޱO`˜m¶t_¿k „ШÝP_\¸çÜ˹ǧý9 `Š?,C˜E@óɧdòîaÁ +Žo¢å’ôzki˜’$sN(Ó7ÉW»ðcWí-bßÕû܈"‹aà <ˆ¬EÌ!šúÙʏl}r`@»zõÜÖCʸ ä¤,…ÜΙߌIˆ½0'ˆ"S0Èò$-Ò›ØàˆbvìÌüÐö•$g)TÚR[ôzó´A.¢RU¾C¼›!^¨ºfÀ|O衞h!µÐFCÁ¡*Á."Èl :ÜÜ­×`ر¥°ugæwv$)£"GáÝ8úC=J›vB¡ƒµÏ¥}>h|.óözzœNí¬Ó#çۛÛNHÍp˜tÐ⥺Í{Çsb²\þƒàƒ„ð™È}Eö켑µ¥g¶°á‘T™¸Ç~A5³ŒQ# +Yë‰ZCδFí´!¦c~Ã"»g(v=¶NÑFÙã­JýýÊ~v½UHS7ë­K\!µLÌßû ŠÉ«ÛæÈ™¡þöfÐþ²½¬7Ўy¡Xg0èYª! #§vÒ9¦v™H™4v ýÒÐöKv ¯DÏñ­hµF@+¥Ÿ=ƒB‹ì¥øƒ¥¿HV!Ê÷Þ-’6‹ cüŽnm-á|Óוöˆ¦Bœãz\îÅÿ…ºðâx±ò‚q°pl66[ŒƒEã`Ëq°‘{[\÷H)ƒZKÏù·ŸEM0ڈÑ¥Œ¥6Ü-lƒ©5>¬yÿ¹·¨(”¥.\H¤·¶òbl»[בœr¹*SbXÚwMO¸½Ïö×^!Þé×3yëÇû7òøîéëÆré:…j€KeŒTñÔýýD™¸ØWŠØnÇ'¾8~õ?‹y<õWX‡5õ&î“É·É__ˆ–endstream +endobj +429 0 obj +717 +endobj +430 0 obj<>>>/Annots 32 0 R>>endobj +431 0 obj<>stream +xÚ­WËrÛ6Ýû+n™Ò†4)Éòc¦ 5¶;^Äqcµ‹Æ]@$(¡& …€ì8qÿ½ç”E1²2îTö"qîëà> O{ ÅøKh0âÿ´Üûe²·~LÉ êÓ$ÇÚè(á¯Yo ¢„JUÊÈ>,¤y=ùÐ!%‰†ƒãhÄÀÉ\¶`”«BR&sUáÁb­–©žUê‹Ìüš‡‰*£TWFkHçðI×TêZRá$ñj|ýö€ül#z«ËRV–€iïnÖóPcEmé^Ù¹³·ÐKè¾é¯‚›×”ÎE-R+ëˆØÑ©HoM!̜77JEESIKW…uÊ$TÁá¼"«; «ª%Væh0N°b·t }&Ò9Uº +§…¨n=Ü9o¼÷‚Þ]¼;s‘Ê®Ê܂§f¹õ>/°Ç€Ô˜“5<} +üb|9Žh\޳ާ¹. +}¯ª™ƒ¶ì`“j),‡Œ]!#kåéwËÍæY¥+ª—…4'>b:öƒ4z²±2™ð§DètœüLÎ +ö¯õ+]_9uôϏB¯ˆðK@ŒÃ?ƒ.n¥· Ã=t×È]ãðøQg։‚$‰DdT +‹½y$ ûÂ"! Þ½“àü5káínl3퍸oN¿œÉÏ oáqL«O Lªƒuži)xP!«¶}§Ü¢V•ÓBþYc!<ëú—»¹š:bw¢XÊëÚ¾\ ñ½\¨Ð©ðœ´âÙÀ>%oÕO¼þó‘ +=S¦ñå)ýµ]?›xÃ2Hñ ™÷v‰ü<}ÿHËJÔtù~â%Öm7ärk7ÞU5úåžò-r-Ðs¶ƒrlwq®º›:(´¾¥@´6ø‚Žfïu}KÓ+Ѭ3יDt‰ˆ¦j¢U*Q¡=­R§•ÚØÐ(t“|TÖ+ÊUm|£ÜœCá ï£ä9Ô÷Ýöîÿ›C¸Xíe“¨T3—èE“è…c´o æÛÉPËE- šFoô²N%ÇØq<“ á»#,¢óí#  ŽŒmêë¦óœK☧bdÏ'-j=«EÉë¤]ä[r¡ƒÅª´%³)G–AråF¾Ä<[ÏhEÊR¹„ˆDpZ2èíïW×+û™ÂF£xÖIu­seè“jHWˆç:­ÕÂÒwJȞJã^0)çÈ—lg“½8ŠqnâK—¿Ò Ž‘u T©¤’õ°y*èڟªÖ)š$ÍNsŠ~ÇìMïêê¬úÕ5 +’éÉd +jòó^µü€W‡G|íÕ| QÒ0éãÄ· ßFp 7£îˆÔ³'¢Æ™Æ k"Óù¥Fõ¿:ˆãÁI‹“gCÃò­Ï­€|”îᙸր’ŽFãt Pâ>bwÀÛà‡|^މo!JêãïÄ·À#evã[àÐ0[xÞ<6u÷\¢£ö]¦]û +L}_ø=†ïÃhàê÷ÉtÜlnowã"Y\iž­K†Û|]][[¹Y†Ž*ï0‹ Ÿ{É1¯§Këú9œå¶´®‹©Dójü9jT&ƒ~ÐGnܞ~ŸO(ô]0 ¹@k˜ImFXGÈ¢áa?fÉ¿:ãç~!iÛû¥ÿ·ùendstream +endobj +432 0 obj +1236 +endobj +433 0 obj<>>>>>endobj +434 0 obj<>stream +xڝVߏÚF~ç¯ÝKI%;Øæàˆ”‡äÈI÷p-½ÒJ•ò²ØkØÈÞuöÇÿ}gvmNr¤B¬½3»ß|óÍ _G Lð“À<…ly=ú¸½}X@’ÀºÄÙÝ4¾ƒu1ÎâiœÄ ä®1¢²\¿YAÓioe‹xF¦ë0`¬r ÌâïÆYV/¢àäJ¾pm„’ ]ÅA•`wJ¥ëwáÔ ,┎EPQ’ѺÓ^C÷c£œÎù[{l8žg,¿Õ¬¾D‘ÿ `…d–îö¾•ãj^€UFƒÀ1¼_Œ7ˆá±DÈíK0®i”¶Æ[ áœBhžÛê6ž Vu€[ü¥§­ +7Ñ Ôì›Ö¾¼ˆüÿQ:‹§'þSÏÿ“ŽU÷ªܼž…Rgò, RYº)ðü¸‚€Šž™õ/Ï)êÂ.z k?RÞaË%×ÁPÈA°;¦‹=ÓÈ_ ½d®²ðÂ*ç9/Yeøµh³­*xõ›«7×$GP·ölÇ«9e0jßåPÓ¹ ýÁ„O#c˜gP›#ú^fn)ʆ_œ ì)ggIËè7¸ uÞ¢¸ùÔG¾Ò +oæÿ±Ð΃ÎU¥êÿä„é:½›Ä‹ ¿9=Zþý ®æÂÊendstream +endobj +435 0 obj +916 +endobj +436 0 obj<>>>>>endobj +437 0 obj<>stream +xÚí–ßoÚ0Çßù+NÝK+•4ŽCSU©£í„´I]ÉÞúâ&Nñlhÿûíñ«Ú'Pdì;?¾»œùÝ"â‡Mì7·¾d­‹»NЅ¬Äµ$Mƒ²â”æ#^L+^C_ÉRo-1 x\DÇ襊¦ò;Mø’cצ¡Ç½YxY£÷J1¾vžë¼‹eWn³V„Ø –‡¯ÅA”tQŸÇQˆCÔn1&q¸´¦]³vme‘Þ(:¶Ë¾M­‹ÖÕÆa//ÜÚÕ~¶¨c£òl”â÷²yk϶²F6$ŠÒÐWÜå /Ù´2Ö!A|<š³ÞFS/<¥: JÉrå­·äʊ’ÔJ~S9;\"!ø>>>>>endobj +440 0 obj<>stream +xڕ˜]oÛ6†ïý+ˆ^µQÄQ"Ppݦ –m©íÝ™¶µÉ–+Ééº_?Jç$) +ÆÓšh™òéiŒ +Ç(r¦µtãtÎóª²}×îFc‘ç0’ÕÉVõ¶¶=ö–5mUŽƒbívü{$SvÅ¥»¸cËé +Ú±mÝXöåõæ¹:?p¯Ñ_ý—ûüê˛$P&9–ʤ´ó½\& §_¢±L^ڕi,ϧÒ4Mû-`ÈÇóÉ7hêôÒ`˜ t~ö‹¦ìû˞™I#&ÒDO?ž¹Æiæ<×ßO6 ™é#kMÕôÒ¨™éDšï»ö[oç›Mgƒ%ÍÒDÑ]¦ºzit•ò®·ÇÁve•éS’²@Se½4Êrý¬zßvC@“§qBšªé¥AS™ â¢ëú`ÛsÀU&"RH]ý4ºæYò\Ôú¸ hj)¤©š^5³ "…¯Êžìzª©2™Bš*ë¥QVf)”½+»s¹ <­”0¡Bšjë¥Ñ–gàzüLMDœ¦ +zi”Fáò©­Î{–m¸ó²("҄4QÕO£j® M»®íptASiBšªé¥Q3S¦O]{>U"¤©Ž^¥‚ýÒöÃïåÁÞµí?çSà5*E"¤©¶^mùTÏÛé©«z˜ÖP6äšyBšêê¥ÁUlG~µö4o°yÙS1íÒDO?ž96Ož¤7©ÐyD¨¦êziÔÍ$„êíÝcƒs*‡ý»Ÿú–·×_¿ Œc +ŒCŽ—¾< '³K4ŽÃKã8ÄÔ³¹‡×}°• à*b#M-¶—In ÌáßÊMí^ +°ñiÒSE‘&ŠúiÍ Lb'êJºªÿ ¤O³ž, +4UÔK£hf`ú:Ñ¥ýz¶ý@æ0s€‰Š^[ÒR³rm³íæ›CجËDLŸ/bÚ|ñòbª€¸€å¸š +-£¢VQQ‹(`®o +ÜNt™r‡ÐåüfÍ®ØâÏû›¶&¶eeÙÛ×»#ûiôj<ñ +Ï”ÉØ‚Un½¸Iªö¸U¤‰ IƒÃÿ<û›iš7endstream +endobj +441 0 obj +1023 +endobj +442 0 obj<>>>>>endobj +443 0 obj<>stream +xÚ­•ßOÛ0ÇßûWœØ <4øG~uBHŒª´I¬ o¼˜Ô¡Þ’¸KÜ2þ{Îqh7H*M­¢ÈþÞÝÇç»Ë¯‚? +<´ÿ´}IF§×>P +I,‚0æ^ Éòx!«­¬æZ›“äÇè* íî1¿æ{Â(BJC|gÄcPIXtˆ©Oöêö¨9¡ïªق†Ü ÐçÚÈâ¦Ò›ui¡Å`R§JÚ©nI}îù–4‘ÅzªªJyþpJ§JÙ©n)ÇK© +©7}·N#T¦tꡔê–’pËxW˞4“ŸC[õ@ÀnuÓI M3ì²À§–•{Ça]©ÒȪöR]f}ßuÆ|âj9YÉ¿•©\¾Õª65è {WWPh ™«R6K‹ËÙ Œüm<¸ÔE!KÓnÖFTž”Y±®õ¦\Âýñѧ£û ¡i{íéJT"ÅÀ^»ÁBWµW"]A©ËñC.ʟcç·Þ;.E!-‰°¨™zÜTÂ(]ÂRU25j+!Óy®ŸäžA¡éVäé=°ÛRå㢝q ‹è˜£õò³Ë_Ðæ/$˜¼1'wújeE }E˜`».ë´Rk‹õqåø”PÚNͱyþ©…?¦*Ÿ43õl*3±ÉÍ­»â&mçoN}vÚɣx7w¹0b:µÃÜ«]OñÐwÕ7•[•Ê»ù¬'r0Gº#A6²ï»K›•™î ÊãÆ¢S¿ý5™þªSÑ_œÆ”ƒS¿˜4gý†½Û^6‰˜_NÝ–½~ÑÏþGÙ±¦X†–Sw— ڎ]adOÔ¦Pg£QwödÜö$å"æÃüâ:1\ÞÝ.`fS‰TÎ õX›±1¶†ã֒»ä“ç;yõ Òͺ^îæ<êûè-$/Šendstream +endobj +444 0 obj +695 +endobj +445 0 obj<>>>>>endobj +446 0 obj<>stream +xڍ–Ár£8†ï~Š>:I` [µ‡q&³åª­-ïÄsËE€¼f#VˆÄ~ûmIàØTª\ýêþôwKâ¿‚V üÒãl½›=~‹Æ°ÛãH¸ +`—Íx>i¡J^À¦Ä‡=OEý°û×i—^äԋeä9½GáKU½Èô§Ð°URËTnB”¶r?öB#ßĕ¼jå×ÀKˆI®!->›-ÔN˜Ê²©Îeé ‘‰=o + F!Ô[ž +¨¤Ò&NL ñz€‘ fðôcûk%ßë¼ügtÿ ?¾ÖEÂk‘A¢$ÏR^ëŽÌƒõù¬8£C–•P\‹d‰+1é1)õ“Þ¬+ô©×Ž³Ð­ã™§‡«d·Fe¢NUž`LÐµÆð ÷Èh° Œ¦rSU +}æµ±=kÝÿòò´Ù€'$×ʬ'6h 4X’;¼älÀE™á{®˜£ïE^ +x“ᯮVm0L²—êȵF“¸y) +tó7ç:ØÄݛ޼äèRRó¢Ï•€—m»&|hTýy[´…™~]67¶Ãs;ùvÊÜZp§ÃØ÷ª7^4¸âT*%êJâ4Ƙ¼Ùn¡[D+n]^ ¥»•_¹ÚMÄü‹º©LíEöKŽ& úß=+6¶õ.ŵîAœx&Òüˆû½lŽ ¶F[/%*\¨(µyIyœ¼ÈõùÑÖ÷iW¹e–.͎!dk3ºZy>.ÿñÕöeev°xÞ͈Gð@ºü|ÿ»,ôø$ÀŒá##èŠÂb÷‰Ãè"¦+ÿFmO¶n¹4ˆÅÄùk»˜1ÇDà÷n?Ü57Å»=FXيš_Ãêûò)«;Ö5²ZÂehN*L}OXȔ=|J¥k®«×9/Þù¹úú0ÆÎ.>ã{8ÂÎ>|þPwì´u—]³[ñX±ÃzŒ†˜syb՝¸§ê††Æ6½?̂ç¶T#<4 +ºÊŽó8ñO»Ê}DYSâ4úb*ŒÁíÙ¸ìƒÁã +iÆ`CL…±â!Ö^Éa¯3öæbKe•‹±H™?ýÐpâ!(»f^}UܜŒc\ğÞÖN<Àņ#êíê¦ÄOƒ,FmŠüéMmµ0(°-÷á¤òMŒm¯Moh« "×Δô‘$¹»j? Øôf¶ÚÖ~SÚ»±ð=ާ7°Õö^zÑ哂|ú1¬4•|#Ùß³ÿåþcendstream +endobj +447 0 obj +935 +endobj +448 0 obj<>>>/Annots 47 0 R>>endobj +449 0 obj<>stream +xÚ­XKoÛ8¾çW zJJ©§èÁI“E€¦›u¼{ꅖh›…,i)ʎûëwHʎ,?¢C éÓÌ÷͋#ÿwEÀÃ/~¤¿ÓÕÕíôêæ!B`:Œ J|7ivMèçé¯+J¯ÿƒ¯²*) +Mª„Ñ+ @é’×z?½ò\íïLþD“‘ëAÇh”Rü“z.Éáå8Jö`ûh$jèE¾Bþ{ôHòJ‡ò c´:”ŸŸãøn`ïñó£× ÈϏÑêP~|ŽõñŠfžç·fR°YΡ¿ßçFb´8”›Ÿàvó0êʛ#£0 lׇ»ž_๬ÕK*E¥àAä\sz«[dË¢ž#¸†n2¾)w2^ñ"ã¨rœ•3ÞÅV²\H¶²Ï¸0]ÜÍY±h؂ƒ8ŽiEÆi‡ž‡\V@¼À Ûÿr«•yÄÍxvg<à +…®ÎíÚA«!=°zßA ~”àï‹øb4ÝÑE|ø$t½Ëøb>¡˜öKø.ñApÀÿö(Dr±‹{Ú£Ä~ߥnÂç\ò"åðĊ†å_0ÉBfpŸ %ÊB§ W¹hüÚÕ×ãá‘-L]OO÷ ¶‡y)átå‰l­zm­^³ªÊEÊ´¿›u‘¹iSÕN…ÏÕæ¹Ãʶ¾›C×zہõ:aµâr@cH ¼Ð-B¬t¸,N-™‚´,ÃJe £AÖd"Ւ˜Üš(‚CÚAÊì²¹5ñã,]Z‹mCdeÚ¬l:±æÖMmƒTIVԘÑÖ\Ïqƃ¹,WÆZ‡¶fô&&Ïµ¶vDï¢Õ·¬¹TÆVËÞ8ÀYϱ¢f~¢®Sn{W;ãn`Æ¢¨a#Ô£;/ ³­ÂٻœA–…ømj6¥Ìþï5¤ ý8€Ÿ×Ÿ&ìE}úùÙÄo&8řL—BñT5Ҏï^:¼×8}4CµõÂ&;#¹P*ç'íØ¸‘B3/çÝ@‘ç:3æFœ×ÜpîùÇ+\~1908Ët!ÔøW]•E-Ú¸a:´gQ,0*’cìuÒµA0&¬Sm¦Þ`KiœH çÏܞgMßtÁc¤ç ‹ö»˜I¬Ø½Ž¦0E\C…ÌRDf»ËÀUb>±{ó|ÛÏêC™çåFóкNeÏÔ.ƒšK<1„­[]ôÞû}ԊIµ/‰N—õ+|ßs°´q4¥Œ }¶¬VS©x¾Å𯎳©ní£5a;;Âčq|xVÝ­Ž­DzȚá·«œ$¡8¡ÌYÞ\ؽ P¢çz¿³6ŒÂ=–xá;`ЧÄMýäxÇØÍŐ¬Qæ9‘Y%ƒØ’Ò»ËYm S{ùG“;·•ÀÒÆÀŽ_î1QØê‹ËBÉHÏéaB-v¨P‹>!å‘ij5¡ñ±À2/å Œt5P ÁhÐgFvq¥‰CFäHߏ咇»¨7TžÁ–gÐgäá¹m_ÃFÔ¡aØøW£ªF} B_¿ò Th°ƒô…¤ÝLh¡ÂQWá8[3ÜÒ¾ œ„Ez(ÓÓG.Ýí9úU š†.Z´ íÓÃ%(Ái¯¾U‰§ó;Éðp²ØÁ1èÓµ{<>>>>>endobj +452 0 obj<>stream +xڍ˜Ks£8…÷ùZÎT5n$ñòb“¤=®N:“¸+kbËD=Ñ<ҏ_?Wº@ æ¡JUl£Ì9\]ùû%.üQ2²;^\n/Þo§’ēøPz©Pìœú¦ž?‡JQ ïÊãDÌ»í¯iëvÈáߜÛÈ¢Ûs0º4ºýF£Û~6n‡ ÜöOݾ®óTü<óú¾YEJ™%©pJ¹û»Ú«úùšQïGp²]­!k[kH×šï5Ú‡EüTûǧQª´®¤Êz|T…ü­²*†'›í ”]%wð¡èp"3^•N. +Gf»—Õ‚tskF:sáVg¥¥ÏÁtC£ô7º‘Îڐ‰ dÖëSñ7Ç8Ç{©êlo^ûE°Qu"+‘ˆ¢$‰|†T/‚¤âP½#ϪªÔñ)dòµK•Ê5’«Rj³J¢æ\=AàTüFxóSۘ+øš…”ò]û”BÖºrÜé”òÖMJq×u¸Û«›¬„ªx| ½És9- ёÇE\)MöÍ49í‰Rëل¬­'HOxâ‡èˆŽôV­O*w61~Lú§vl>³‡Øxh©&µg<¤äý5L•Y ‹ÎÁ‡†Fßhô¯ÃæžÝÈá´·ú}±žöÉùú¿U90@d >e5â烞³”¶óÒLßYLûùæú94m'÷»åmÑNdmíDzÂNÞ,oœ2°³—r·q)Wö¬4ªtbaˆ{`tFÉ£(ËL⼫ÅHGÖ6ґtNÛÚaIŒ÷Åfuœn®Ãc‘t4Dú‹šl£nÇ©i+غ[Ý£YÛ(Bz<ŠXÛBsaÄzad:Èûfýé¹q“åе•)¸Ñ®OäP@¸°‚‘»¡ÐIE–ÏYÛgŽôø3g‡â7B!/8=ú$ô¬ïÉ4ÇÉ3 +:)âcI [çi¢ñ{K óÃv>/Ë5¬µ\COÈõx3Ÿ9ÌgÞkWoeQ¨Â4ž“5n’íV÷p|F?ó¬—Xd­ëÚÐuM]T€ú^šÝ‰$®ä«˜Õ/3ݯN뿎Oë§ÐE–ú‘µÕô¸~M¹{q^/âîêãU·«íÔS=u™>¤÷غ²`“Íü\«©¤n7àX‚#Ä!tÁ„еžÈÚN¤Ç'õƒæÖ=7¯n_ +)`srm'EP¨JÿÐîH‡MÂÛ(ÙA;àìRµûï‡,Ǻ¯m]dH×¹ÞçÁÖçG6Ò/ô®{z½wiWb‹-²¶-Òã-ú«0T¿¨_ê +ˆM¼_ó3wq`tÌ:@ê|^¼Ù—ÛM/ƒÚÎ.OüòÒ>.²Õï¥Ë=<¶Gù»ßw>É}õbº¥Td ¼µÝ±…mr.ïwÃ.8-¶»a—›Ã)ãq#,€Ðz¡ñˆû*½ø¡c§Ž¦ØNþÖ±S©Þõ¯7³~pëø4¨õêÁÇÃóý&jŽrNB†¿ð<ü½ÙBÌ]}½„ð‡¹njóZ”2ÉôË®y›%Ž>ÑiÎôàÒæ¬‡¸Ô=æٛy¡ߏÉËþ½ø×Àþ[endstream +endobj +453 0 obj +1348 +endobj +454 0 obj<>>>>>endobj +455 0 obj<>stream +xÚŗMsâ8†ïüŠ>fªbdÉ_‡=LÈdf*Cm–°µEÕ\#@;`¼¶ÿߖÚ$ x÷’JʆæmÙïÓrKþ§ÇáÙÿ|Ù»õ>ÞIàFS9D‰ðM®D$=ÅF÷dŒ9UÙöq£M>·QÎB +3ø nWP¬ äó¬˜)0(¬AO¡V •5qÐ5¨ei¶6›Ç…Ø|ŽùýΉŸG=æ3tñr~™ø ¢HúÈ? +áK¨<¶hÓðE‹.ˆÆ^ԁHöԈÎ °Ä1ß¶^>-Ô)XÕÊdFzV”ÙLÕ°™ãÇɺ\¨_º˜µ`vH9Hpª# §í È©Oâ±Ãˆ'|‹'_—õ_zbö§“‹Àjê ‚^º#ÚÕ¿Ô¢¾`s<:ƒÃ:kÐiÉà9qcЩÉ૚ †iÔ<2q„ÓC‹_•žÍ͞G +ý?“aÊðrÝL’¶«IRŸ0GøX“ óD"MÔDg£m¹?Ûo+ý¬*¯.U®§:Ç YA`%¶éÄvÄ) ¾xó½üH)ÁùO¿€ü˜˜ížÿË`œ¶3§>&Œš[O°a&ñ!˜mêUõW‹UµÇ†_Cp ò=>¡æ‚7×e:zsÚÎޜú„7Qï ö¶”Ÿðö`gí¾7[gt1&Ø®']6洝9õ cœærŠ=)=êI7[£¬¯ïºPǶ§oú¼Ûô…';ðœuna¤íÌéÛyHZXŠ-,=janöþ^MTu´˜åóuñsÛt.øqÕŒïáåðãCË*ö”\Ú_Sú} 0áþþ8'Àœr‘Yµ—ãû¾M³'Ì´'LÆåŸF,#±{–¤mjç“–ŸbRâWuƒX¦äF2æI&Z?–Y~¼_ØÌµQm»/7-¤0úé ,,ôE–ÿ<ˆK»óŒ¢!FǃþA4"íýA8&ña8ÁðýñÐiΗçK$¹+)ÏՈÄT£³j*É©HoäT%ÁÙ®J«WiYVª®õªx¿…N0Ù¹g’¶k u{RF`Oò£¥`¸ÚôW뼕 ‘;'i»R!õ *QJSò¹„-\¼#–HtÞ.’¶3§>»]DX"Ƕ`y4ª|G,RtÞ,’¶3§nÁ‚.m^®GsƒoƒÏ`pÇ ÓUý?a˜ÕFU0Õ |³Ã—^²Ç{WYY.tžl>Ÿ‹‰oAz•ËÙqåÓw$åÖõ)²ÄeØH?Ü]mwöRûÉ$uų +º™ M”•.ðRÞD• +ðÂP¤Q˜yfœ _c2ki‰ßëµ6¾ÛJô>>>/Annots 156 0 R>>endobj +458 0 obj<>stream +xÚ͘ÛnÛF†ïýsé!Ã3E½p#Û0ª¥ôÊ@@“+› ÅUH*ŽòôYžF2µt€´( X ôíìîüÿì_Ïl°ðφÐ7€dsöûêìÝu¶oÎ`µÆß‚04X¥ç~\g¹€UÕZ”°(e-™¿Yý}vµ:³L ƒÑ?›þÝ݀c‡¦šlÀñlÓnŸrX6]y`ÛmGY=‰ÝÀýùõjqÿ² +RQ%eö RxØÃéþYØàšë„gò3×tô<#6à:S<'¬>;m>Žš”} +Unî®ßCäG†Váܤ﹨FÔp#œ­R6„Û¢e!j –uV<Då:Q³ Sêt³*Ո¯ežËgÂp*ÕE:iC;3LŽáÍ î <­¬`Ò|ׯ‘lÀp6ÍÃxÞ°YhºZš°oçò31N Éç«ã9A&ž>'ÈÄC¦N™˜çÒEBƏšr°.¾ë4~ w:~à_h\ñC\ÀU‘È”¾Ž‹´±ñV–õ¸}!Ú×°©„^é{†™ëü¡tþhéF~ ̀Þœ½?t<#zhxN ï»f¤ç|85N ?péÿ +Øí2Óú#˜öÇG™Š\™c)61IõëÍaùÈvæP:s´t£½†f™ÃžÀ9¼Qru<#ÈLô©å|H²iyF 9pÇЏŸùôÉäò‘…ª ü+ÌdÂ­™Â ˜‹*{,àFÆy…L‰¾™ØÍ~©¼ÈQ»¹²Ió ñQG+›èh n¸ÄêqNhZžä#¯ŸÉ)yl®Žâ¹JÇs‚|MÄçò.9BË3‚6Å«BË3‚6E"Ÿœ MqŠçòž;1׳pîy*Ÿœ@>ò¦xFlÀ›ôwà/ #ÞÀO×¥¹¬*gpי,â\¨’¤³ß².wI½+ȵúbXåû3cÇþ—õ‹+Þ¬¯_õ «ß–nÊSC3€öˆªMƒs‚ê1"wëxF JMÄgÕ£«¼ŽçÕ£ÕgêT=Z,—NHÇǁ…Bšÿà ¼ã|Œ·[RþAÔÏBða1Wf¹],z7œ8±¿¦¼ÿ´XâMd¢:º„ˆïµ(*ô)È­(•c‘ÔÅpiRVj.>Nw¦b¼A{ÎÅ:ÞåôY¡KU¼¥RŸo®VŸçWחŸ>¬à7°¾{–eß¿Ñ^¦1bÚFLYÄ~pP +, ¢™Æ–Joq]ãkW‹ª/Ÿj_ÕbÓÇêHü5Éãª2{S™*EùÃÝe%^×XÌ ¶µÕŽú|øÕHžâ²õá´Î•N§á´veœy\<îâGqÔÚl‡ÖÝoN¤å9ËshÇMi9î1Ûn ùe,¸FWGéºh2Vq1w·¬®î–šÎ+ÔÜvq~JÂçÕ·üRÈç‚L9«ôƒŎÔüßé×Oç_ͅË4íDë4»œÏ;Í:ÉÜ ÉbŒÒK¯~[Qí”b›ÇI»ˆT[‘dëLô Q~6ÓoŒJ8•ï1µÚA»2{Az£sбj#³é‚æ2Q™9žË)>+ÖòµìF–b¼ÁÈ,Sñ-KÄô$ª£_枟p_Ɋ¬Î°äö$´z)1Ô%v)·ÍA¦72ÍÖûê8q—°ÀjMoèÐ4Ëf)þ »Fÿ½ÛÖ°‰÷íVÔyp[£á2ݛp»ÆN¾Åy–¾lŒ‘±—£y©>³ + +I'¿e)α¦aóŁºqMËÍt~wy½ÔÑá¶Ï}{Ӝ‹F„¶ jj„Ž5ý’Ü =<å(ÐöÛcéŸgÿýnÛ¼endstream +endobj +459 0 obj +1470 +endobj +460 0 obj<>>>>>endobj +461 0 obj<>stream +xÚݗ_oÚ0Àßù÷H¥†&@<ì!…´jUm ²·JÈ$¸MìÔ1cìÓÏÆIIBZè†:m îÎ÷çwwá¹a)_tlõöãÆ•×¸¸€ÕiµÁ åovßR_ƒf·Õkua„#,0Œ9¡sxh¿§³‘{ïzîl<¹ýì¹ø揮ivÎμGi¯ –¥­AËVÖ¼%†@ÛJ2[,Á Â(p³ï8!…Òû$$8ÈåZ t6RîyE¸ü ÁÉ|%¤âXjîÕÑ͝˜á/O±(û×<‡²nQƒ"±â(2"D+´À{ªˆUõÌecÅIE¼¥®¥km[&Uº6*çbM¢H†'O¤U›$I ötÈq%E™0B¶¢Áž0ã¯É£•X2N~â Îá2F§­‹©Ð¸„,`¡4•Uȸ¸q½ÙðޙNÝiÅå(ҊŸY)¡R¡‰ÈsT(z(B2c¹âek +‚i‚6©Àq 6Y öéP½AB=;uõ?Ÿ*7…4laÈP+$-l,TJÞK_'ò÷šx+®kñÞŸÓ×§íÒÊ`y!§Z­špr£ó·‰9Ô°¹<¡!;V6f×+ÔDãx®ƒL_²Ú…˜a½Ä%‚ÈVÛ¨Bº´ëGy&KT¬(ÒÂ1 H¸)IU3ç¼ t²‘÷ê«Õ˜£ÀP!âT9&ËÙzGËõòíYêºlw–¯wÜæ¬ö^ýÞ,´Üº5O ЇíÌ>8¾wl¾›Âá;öfw_®^pèšÃÚÊ£²R˜ÄQÄÖ©¾+Wá<—“•Ÿo*ŒB·zo“R3 Þ=Çÿ.N!Oÿ-˜àGì—i™¸wî°LËà-\[©Ð’püS‘ñrKb¶£û7¡9íÓÕCsqÝÏ®­N쁙͛‰sí*õp« „òGŽõ”,¨úð9Iòmo(U£×6•¦e«[Ö` ™ôwÊõ_¿²bÿendstream +endobj +462 0 obj +771 +endobj +463 0 obj<>>>/Annots 185 0 R>>endobj +464 0 obj<>stream +xÚ­VËnâ0ÝówI¥Ip$¤Ò,ÊkÔªÕ0î* uê8é|ý\ãBI ‹Q¥7ç¾Î=×ö[Ë‚ø68D›V?luÆ.X„+üâõ\³á²=e/,’ð’.2øÍ㓹Hà*|AR´ùvk¤¯úŸ¥—ö·:T’Jc•æÉòœŠ&<Íås*ø_öÙÈÔë,Ç´uæ†c›žÊÜ5}Ó"0c†lEóX½3É*yšÀ¼=xœÌžf£ði8ß<އðÈ—›ùÕqå4ÐNÃgz\—é– ýKs”DôVðD2TJÁ¹d¬°Rõ)ûÈ$Ûì}•HüÅ4ËLÀh*Œ¯ë[¶Ó$þ@÷o9lYõIûÌÞá«=Si_êOÅkʍ˜&뜮ى)-;H,•Y•¹àu C¤í™®BθüoRk”N­Å‚. Å.fR#ÏÆzÏéú Ñ®š¨RM®–hîyÂ`R´~HÙ«ŸˆT¦Q+ÓQØ"&ÁiUK=¦?Àîºf\ÏCUnÀö{&)V1Ì>ϲëùñօ›·ï'Ãù +P‡ž©fD¨Ùâšó¨DހCT‰‡ý“’ÅzO}Áét<@¢ýàúb#®HáêT†ö^H€˜xG,Ëp¡§Ñë‘ãƍªÖrޞ=ô±Ù8¿8`1•ØâAºQÙÞªÔœÈ1ÑZïN¸Oގguè½f¯FmXÉt|×tZË&¦U¬JjqÙÅ%&K%3T’Ý~–r{ÝéÐ$73ºYP3ëNÄWÙW=š6<BÁß9u‰¡ I¶Bо0p¶Âº»jìÁ.éUÍÀف§ëRM8é ÇáéýúÌU‚«™ëáûJÝÌzæ¬óø +ñ]5 gñ⃋ø Šw]ûB>Uâ»ÖQ½ 3ª»U´a7£N—\î!Èw•ÿ){ç™:sl}î7«ªWtذlý»øô•ÿáôf‚êB¡‡hE#¦n|¨vu«Ž5å  ß&å%€âŽu§îXŵd:º §»ŸýYy- tz®¯Nµå"ùÕú%Œ$endstream +endobj +465 0 obj +864 +endobj +466 0 obj<>>>>>endobj +467 0 obj<>stream +xÚ-ŒÁ +‚@„ïûsԃ¶«’z萺B^*ý½ RÛ +i©‡¿6b>øæÅø7þÖT=XBl“GÔAø>BƒnVVîs‚ƒ´>U8Œ«ž»‹ÒÈôÒßG3jîŸk?6 Ì1¢ó7EdçEnˆÜЍQêA«Åt]ÐXæ¶-e!Sj‹cRaþ8ÛØ’Ø™}ý^- +endstream +endobj +468 0 obj +154 +endobj +469 0 obj<>>>>>endobj +470 0 obj<>stream +xÚ­•ÍnÂ0 Çï} +™´RÊÊ×uÀ&HLë $.„¥MI¤íé—ÓD–jmýKlÿm7k/„–½Bèµá© 4õžc/x@8€8±–n/‚˜5:ÐF\!5RqÔñÊr]CÇÙ¥~»ÛÜ¢ÁF«`㝠â%ÂÎÚÚ[”dÅá’Æc‘y5±®FÔHzЌsÚS Ê4µ°…š3„%*lêå &ø¼–`„RÌMU"Œk2X…av %rÂÒb]O £peå.Â躭$rZt|"BºÉ5+ ðçҗDaàö+ “k°·±á*) °ý$}ƒL¶_‡³wpÝÄ)0bH ·ãË%¢&Ô f+G…{uKÝ3Ö,Ê¿óDfF×*©ˆ¶î‹ú»½n‹&•¬ø)F£Iš „Ùlt›«si\ýµø"êNG—È6ÕEî‚9¡Ÿ˜±òÄ÷оÕê'Ð÷+§ø:\Ʌ"é5.d–T´ËŸ2àX¾Ø(;£2ÛÑt2Ÿ­Xÿϳ=Zý¨Õ<ŽF½¨Ù·g­µ‡÷a{oÞ/½endstream +endobj +471 0 obj +433 +endobj +472 0 obj<>>>>>endobj +473 0 obj<>stream +xڝ“ßOÂ0Çß÷WÜ#&î'£òªNßP¦¯f¶·­ÚÒv&ü÷¶l‚$JÖdÉõ{ßÏ]{Ý)$îKaLü¢ëà® â4…²ö!2Í£)”lT:¦21“ôª\:Y~…‰r/+[C[dÝ +58i·Fa+Ë¥€š¯Ð€FÃB‹£Þç ~7:ð\šE}é­¡^@àÂåÕEó;e±5×ð +{±ëSse/à­dcÎ÷Óï&Ã®6óæò~¦®•¨µÔ'…•`ÇbU5xB{éE)ÅÎuÅ 0®‘Z©·@¥› +. ÌçÅÀ«¥¬h JïÎøoP›5ÿ'+Œ‹¦ÇÁR¾÷u ØéàDÜãÈ&ñNÅóí¬„î_æ xÜÏAáªþ·7êÞ"LÇco²Ägf‰å qF»À&Ψªâýä=”ÁSð o|ìendstream +endobj +474 0 obj +338 +endobj +475 0 obj<>>>>>endobj +476 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(LòðbÕ$?“¿ÇA8Qendstream +endobj +477 0 obj +425 +endobj +478 0 obj<>>>>>endobj +479 0 obj<>stream +xڝ’ÝRƒ0…ïyŠ½Ô °PŠxÙÛ)c”ø1M1 iýyzªíԙÆêÀ՞ÙosÎî‹BÏ|!ôûÓÆaï"O /m)Iã ¼8»F>ÏÏñ“Ñã½îGIw:{­™Ö>"tEԐâB3c)´’5̉¨Ö¤b[Â÷ÿaFÌþ1b&NÁO3œ‡O-J0 ™¨¸`̰+À¤]A.ur:Û=Ö2‘’ZRY»ˆåÍoD¢¹¤†R±0a´p£*"øG'8Øs49Ξç»X'„5NT1-²ã¬b]kÞ°'° ¡ ¼†ì>šm¹"u^2kþËY!—c$[]RşõÞ7k»‚;Dz§–Lm ©`mk;ª%]9X8ǎŠo¸YuÎkXÑ. ûðŒÒ¯¾$„Az$¶or7Ì1ø0¾GåvKB™µÇ+ñÓ¥öûà_F=ÛE¶‡i0€®0 "R%Å{ÓZ)ÃÞ­÷ š¶' endstream +endobj +480 0 obj +376 +endobj +481 0 obj<>>>/Annots 355 0 R>>endobj +482 0 obj<>stream +xÚ՜Ks7€ïúsÜÌ Þ3‡d‰rÙe¯µsK•‹¡F2‘Ô’”ÿûàÑ=Ffc\[\»Jª‡èFwãAþ÷„UµýÏ*Ã+¡«Åêäåìä狶bm5»­˜^i£ìÏÙÍ¿fóßï»js[mÖûn½ßý4ûãd:;©'µ¥¸Ìý¸zå•í¶ªÜÏð÷}uíøõí]õó…ªs¯èºµáÕXu‘«J¨I“óƒ(׋ÍCç@‘Rëre_ΪLŽþ;8B»‘æÊþ\UŠO4ˆ¡–0ÔÖޚk?Òb¬èÊödn´Ó—¹½¾±^±¼].æûåfýõQWfbŽiÜKcëß1Ž­o[7¢Œ[ ?¦¼4¦@nÌDçdéúËnß­ˆÉû[ Ö?4N‡ ÚûOÝöÓ²ûüuãH6iÂ8«¨¶±o +¬”UTÛNÀÓEÁ*Hfµ›ä€:ß,WÖÝóR„J9‘9€X0 ·õ̦adÀW†÷?ü=*à+#B¨ætÀG¼rÕñƒ(WÝm·í֋nw`ÛãŠ?_ù' +ÎoG ÷¡1.Ü+íß7/†{|…ƍì‚8pÎ~½¼&LûZçWµ3ZJ +ò@¹D¤ ­Ÿ×h%›HÓDhIêŽy1M ¹©mìÊÈ ÒûýÇnK˜#vwY¢v±(…`hÃsˆÅt@b­}›üßãw£cߜ($ÀÛÑP9ßK‘òÚÖÊÛõüþ0,¬ªViAœánç‡ãÛñE7U˜;µÝû³oŒŒgµ 1_”#¼†M¿uþ ÒÙÇùv¾ØS3)A¸‚Xº0–Û&â®;ª>Húº9é~g$TØÅòþÑ­sÄ,Z¶"&®Ð ‚¤lÃ,,†HäúÚ*ã‚ØsÞÎ×wó»Ž´¬îaŒ×ý#÷–ôOEÃÎÝöhæ`É$¦y+4H“Ø4Ñ£” +i$7nó #1’Þ½~7%âlìíjrí ²‚Y´QôqÆÃ–±µ­µŒÖ~Ýк”-cìhVÖ2T4LpnMb†plµ\u“ý—‡îx ]F%0­6Ð ‡QIÈý2î$¸PÝòr€ùa\l֟ £zæAԅ !똠Cƒ ’aZ–¥ dV×C4Èu¹Ùí¯Ûå¹Þ®S¤p̐¨€ÌírMfúayžw;ÿˆvC@ÌÊ&nŸS2((°bÖg?rö•æ7!{Ç÷ ržqH#²¬€Ìüï ò¦¼M;[”i†(«€¤é_ûn½³Fܼ„à\£µù0ç™þÉöÊbOë Œ?ဂ']^žF¥-ʺ¦ÉQ¨PN•ßÛ©Jñ†‰¤(ñ 2Þø2Ù{“*Å ·næddézñ±»y¼'—±ò%&‚€g›õíòîq;/‡„ãÜJÙّQQA îj¢UšB¨ë¤¦ñ 2HÔ kUÀfÒUzä[ÜÏw»nçòñíq¦ãÂ( +› ú’&4¨QMƒ%*–4Èv»Õ&‡ƒ`‹Ç‡Ý 1†ÒmcT øÓùôít6áR ÐúA͇xT<•É’Î.%6C3¡ ¼KÉïàR¬pˆï›û“¥Ð ‰µu_4ғ´ˆõvhž¤û¨dJ~¤ñ¶¯K>är|rëaþÄ6ƒ¡‚ãFIw6”›Ø äÓ´Vò¤fэ¢Q¡’®aÉ PˆÑÈ|?O*úlcµ¤ÿ¨:VÛMɃ€vÅ3x#ìt±èÊç&=N‰þÁ³s“ž÷fó;éD"yã¡üÍiJDÆ¢³³éåìÛ÷/¯KµvOöÕpFdkmD…Z;GDy?j¾o­]r%‘\Ë ҕ„‰µv[r%`»í:ÃA°«în±§7uÄI÷„ ‡ +À+¸RÒߥŸvøp¨`²BûjúfzVt¦„¶‚m錍 +¦Xe§]Áî.Øä(P0I•Ý~ÏM€QþÄá¹_„éP\ƚ›ÕÔÉNº:©u:Å£ð +UŠÝûü–Á@`#¶5#"܂ (ôÀQۚ³òÚŠ +2«å¯ÇmkFš[ñá ‚,Öòig‹2õð1QA&µü)õ¾éL•ú…±ä²hP(î! jo +(H6~…Ɔwý{ÒÛåš:‹½Ý¬iœÛ¥,¾ãŸ\¨|ÂC¼ã?ïVä ^™ñš'ïú<²Ó¶’´&^yhMáÆC eT[p €Úš±Î A®dwÛOäœe|8Æ]ðOAÌ»n·#?˜ô ‘.Ø³^ÞoÒ1.’Z607#¼@ý๒4p?¿Á¿)h$ÓTºŠ,[[¹:7媦§Ì¶ËOKêžgì¼òOg¤ MnÏS9¯ïŒ_`’@Ü?Vñ^¥¸Æ-,2œJqŨðƒo»¾ù#~Îތþ˜=Ü$W¥¯ý€Sm÷1m3øŒ}û¹ÒuÀB€¼ ªÔ1îW + B€œ/·¶2ßl—‡nÉ(v¬_?ÂZúž7 qÌßÝcTÜwWYý‚—ʺHñ™„gÄ gí÷®·_̃ö8nQÿ¸¿úóE~߸ONë&|ËÆÕéŬzQùÛ^ý•óÊֺ˻u•|šÐ!„r ä…áþ /ahÿsò73&Ï·endstream +endobj +483 0 obj +3110 +endobj +484 0 obj<>>>/Annots 360 0 R>>endobj +485 0 obj<>stream +xÚ͒Mnƒ0F÷>Å,›Æcƒeš”ª»6qPˆˆ‚i6½}ÇàôOBÙÐ ËöûÆOþ`‚^¥ýWuìÞ°¸, 0  V\‚ÎRªæíÎìö§úV½j;œæÈ \ÅôeóH,.@«œöu&¼ƒl}¿ îq™¢Ï¤6´*¦À%G˜Íø…í W߁!#L’©]7¶ûÃ!Zf<'´ˆßÔ#ñŠ^™R½è³z½T©'¥òšÒÀE!HÌp˜Ÿ@•ëíçœÔ$á궤N:ã2¿Ü3E§+ßâz³, D°z}ÞÂ]m×ìªÖõ¹=Xÿ«\û>´½õ„•‚(“ãáÚ6¸|a_þZ°aendstream +endobj +486 0 obj +273 +endobj +487 0 obj<>endobj +488 0 obj<>endobj +489 0 obj<>endobj +490 0 obj<>endobj +491 0 obj<>endobj +492 0 obj<>endobj +493 0 obj<>endobj +494 0 obj<>endobj +495 0 obj<>endobj +496 0 obj<>endobj +497 0 obj<>endobj +498 0 obj<>endobj +499 0 obj<>endobj +500 0 obj<>endobj +501 0 obj<>endobj +502 0 obj<>endobj +503 0 obj<>endobj +504 0 obj<>endobj +505 0 obj<>endobj +506 0 obj<>endobj +507 0 obj<>endobj +508 0 obj<>endobj +509 0 obj<>endobj +510 0 obj<>endobj +511 0 obj<>endobj +512 0 obj<>endobj +513 0 obj<>endobj +514 0 obj<>endobj +515 0 obj<>endobj +516 0 obj<>endobj +517 0 obj<>endobj +518 0 obj<>endobj +519 0 obj<>endobj +520 0 obj<>endobj +521 0 obj<>endobj +522 0 obj<>endobj +523 0 obj<>endobj +524 0 obj<>endobj +525 0 obj<>endobj +526 0 obj<>endobj +527 0 obj<>endobj +528 0 obj<>endobj +529 0 obj<>endobj +530 0 obj<>endobj +531 0 obj<>endobj +532 0 obj<>endobj +533 0 obj<>/Outlines 487 0 R/PageMode/UseOutlines/OpenAction[415 0 R/XYZ null null null]>>endobj +xref +0 534 +0000000000 65535 f +0000000015 00000 n +0000000225 00000 n +0000000286 00000 n +0000000360 00000 n +0000000438 00000 n +0000000515 00000 n +0000000594 00000 n +0000000670 00000 n +0000000751 00000 n +0000000809 00000 n +0000000924 00000 n +0000001009 00000 n +0000001124 00000 n +0000001209 00000 n +0000001324 00000 n +0000001409 00000 n +0000001524 00000 n +0000001609 00000 n +0000001724 00000 n +0000001807 00000 n +0000001922 00000 n +0000002006 00000 n +0000002121 00000 n +0000002206 00000 n +0000002321 00000 n +0000002406 00000 n +0000002521 00000 n +0000002606 00000 n +0000002721 00000 n +0000002806 00000 n +0000002921 00000 n +0000003006 00000 n +0000003100 00000 n +0000003201 00000 n +0000003286 00000 n +0000003387 00000 n +0000003472 00000 n +0000003573 00000 n +0000003658 00000 n +0000003759 00000 n +0000003844 00000 n +0000003945 00000 n +0000004030 00000 n +0000004131 00000 n +0000004216 00000 n +0000004317 00000 n +0000004402 00000 n +0000004468 00000 n +0000004533 00000 n +0000004618 00000 n +0000004683 00000 n +0000004768 00000 n +0000004833 00000 n +0000004918 00000 n +0000004983 00000 n +0000005068 00000 n +0000005133 00000 n +0000005218 00000 n +0000005284 00000 n +0000005369 00000 n +0000005435 00000 n +0000005520 00000 n +0000005586 00000 n +0000005671 00000 n +0000005737 00000 n +0000005822 00000 n +0000005888 00000 n +0000005973 00000 n +0000006039 00000 n +0000006124 00000 n +0000006190 00000 n +0000006275 00000 n +0000006341 00000 n +0000006426 00000 n +0000006492 00000 n +0000006577 00000 n +0000006643 00000 n +0000006728 00000 n +0000006794 00000 n +0000006879 00000 n +0000006945 00000 n +0000007030 00000 n +0000007096 00000 n +0000007181 00000 n +0000007247 00000 n +0000007332 00000 n +0000007398 00000 n +0000007483 00000 n +0000007549 00000 n +0000007634 00000 n +0000007700 00000 n +0000007785 00000 n +0000007851 00000 n +0000007936 00000 n +0000008002 00000 n +0000008087 00000 n +0000008153 00000 n +0000008238 00000 n +0000008304 00000 n +0000008389 00000 n +0000008456 00000 n +0000008543 00000 n +0000008610 00000 n +0000008697 00000 n +0000008764 00000 n +0000008851 00000 n +0000008918 00000 n +0000009005 00000 n +0000009072 00000 n +0000009159 00000 n +0000009226 00000 n +0000009313 00000 n +0000009380 00000 n +0000009467 00000 n +0000009534 00000 n +0000009621 00000 n +0000009688 00000 n +0000009775 00000 n +0000009842 00000 n +0000009929 00000 n +0000009996 00000 n +0000010083 00000 n +0000010150 00000 n +0000010237 00000 n +0000010304 00000 n +0000010391 00000 n +0000010458 00000 n +0000010545 00000 n +0000010612 00000 n +0000010699 00000 n +0000010766 00000 n +0000010853 00000 n +0000010920 00000 n +0000011007 00000 n +0000011074 00000 n +0000011161 00000 n +0000011228 00000 n +0000011315 00000 n +0000011382 00000 n +0000011469 00000 n +0000011536 00000 n +0000011623 00000 n +0000011690 00000 n +0000011777 00000 n +0000011844 00000 n +0000011931 00000 n +0000011998 00000 n +0000012085 00000 n +0000012152 00000 n +0000012239 00000 n +0000012306 00000 n +0000012393 00000 n +0000012460 00000 n +0000012547 00000 n +0000012614 00000 n +0000012701 00000 n +0000013125 00000 n +0000013192 00000 n +0000013279 00000 n +0000013346 00000 n +0000013433 00000 n +0000013500 00000 n +0000013587 00000 n +0000013654 00000 n +0000013741 00000 n +0000013808 00000 n +0000013895 00000 n +0000013962 00000 n +0000014049 00000 n +0000014106 00000 n +0000014192 00000 n +0000014259 00000 n +0000014346 00000 n +0000014413 00000 n +0000014500 00000 n +0000014567 00000 n +0000014654 00000 n +0000014721 00000 n +0000014808 00000 n +0000014875 00000 n +0000014962 00000 n +0000015029 00000 n +0000015116 00000 n +0000015183 00000 n +0000015270 00000 n +0000015400 00000 n +0000015504 00000 n +0000015609 00000 n +0000015715 00000 n +0000015821 00000 n +0000015927 00000 n +0000016033 00000 n +0000016139 00000 n +0000016245 00000 n +0000016351 00000 n +0000016457 00000 n +0000016561 00000 n +0000016666 00000 n +0000016772 00000 n +0000016878 00000 n +0000016984 00000 n +0000017090 00000 n +0000017196 00000 n +0000017302 00000 n +0000017406 00000 n +0000017511 00000 n +0000017617 00000 n +0000017723 00000 n +0000017829 00000 n +0000017935 00000 n +0000018041 00000 n +0000018147 00000 n +0000018253 00000 n +0000018359 00000 n +0000018465 00000 n +0000018571 00000 n +0000018677 00000 n +0000018783 00000 n +0000018889 00000 n +0000018995 00000 n +0000019101 00000 n +0000019207 00000 n +0000019313 00000 n +0000019419 00000 n +0000019525 00000 n +0000019631 00000 n +0000019737 00000 n +0000019843 00000 n +0000019949 00000 n +0000020055 00000 n +0000020161 00000 n +0000020267 00000 n +0000020373 00000 n +0000020479 00000 n +0000020585 00000 n +0000020691 00000 n +0000020797 00000 n +0000020903 00000 n +0000021009 00000 n +0000021115 00000 n +0000021221 00000 n +0000021327 00000 n +0000021431 00000 n +0000021536 00000 n +0000021642 00000 n +0000021748 00000 n +0000021854 00000 n +0000021960 00000 n +0000022066 00000 n +0000022172 00000 n +0000022278 00000 n +0000022384 00000 n +0000022490 00000 n +0000022596 00000 n +0000022702 00000 n +0000022808 00000 n +0000022914 00000 n +0000023020 00000 n +0000023126 00000 n +0000023232 00000 n +0000023338 00000 n +0000023444 00000 n +0000023550 00000 n +0000023656 00000 n +0000023762 00000 n +0000023868 00000 n +0000023974 00000 n +0000024080 00000 n +0000024186 00000 n +0000024292 00000 n +0000024398 00000 n +0000024504 00000 n +0000024610 00000 n +0000024716 00000 n +0000024822 00000 n +0000024928 00000 n +0000025034 00000 n +0000025140 00000 n +0000025246 00000 n +0000025352 00000 n +0000025458 00000 n +0000025564 00000 n +0000025670 00000 n +0000025776 00000 n +0000025882 00000 n +0000025988 00000 n +0000026094 00000 n +0000026200 00000 n +0000026306 00000 n +0000026412 00000 n +0000026518 00000 n +0000026624 00000 n +0000026730 00000 n +0000026836 00000 n +0000026942 00000 n +0000027048 00000 n +0000027154 00000 n +0000027260 00000 n +0000027366 00000 n +0000027472 00000 n +0000027578 00000 n +0000027684 00000 n +0000027790 00000 n +0000027896 00000 n +0000028002 00000 n +0000028108 00000 n +0000028214 00000 n +0000028320 00000 n +0000028426 00000 n +0000028532 00000 n +0000028638 00000 n +0000028744 00000 n +0000028850 00000 n +0000028956 00000 n +0000029062 00000 n +0000029168 00000 n +0000029274 00000 n +0000029380 00000 n +0000029486 00000 n +0000029592 00000 n +0000029698 00000 n +0000029804 00000 n +0000029910 00000 n +0000030016 00000 n +0000030122 00000 n +0000030228 00000 n +0000030334 00000 n +0000030440 00000 n +0000030546 00000 n +0000030652 00000 n +0000030758 00000 n +0000030864 00000 n +0000030970 00000 n +0000031076 00000 n +0000031182 00000 n +0000031288 00000 n +0000031394 00000 n +0000031500 00000 n +0000031606 00000 n +0000031712 00000 n +0000031818 00000 n +0000031924 00000 n +0000032030 00000 n +0000032136 00000 n +0000032242 00000 n +0000032348 00000 n +0000032454 00000 n +0000032560 00000 n +0000032666 00000 n +0000032769 00000 n +0000032872 00000 n +0000032975 00000 n +0000033079 00000 n +0000033181 00000 n +0000033284 00000 n +0000034654 00000 n +0000034758 00000 n +0000034863 00000 n +0000034967 00000 n +0000035072 00000 n +0000035122 00000 n +0000035156 00000 n +0000035190 00000 n +0000035785 00000 n +0000035834 00000 n +0000035883 00000 n +0000035932 00000 n +0000035981 00000 n +0000036030 00000 n +0000036079 00000 n +0000036128 00000 n +0000036177 00000 n +0000036226 00000 n +0000036275 00000 n +0000036324 00000 n +0000036373 00000 n +0000036422 00000 n +0000036471 00000 n +0000036520 00000 n +0000036569 00000 n +0000036618 00000 n +0000036667 00000 n +0000036716 00000 n +0000036765 00000 n +0000036814 00000 n +0000036863 00000 n +0000036912 00000 n +0000036961 00000 n +0000037010 00000 n +0000037059 00000 n +0000037108 00000 n +0000037157 00000 n +0000037206 00000 n +0000037255 00000 n +0000037304 00000 n +0000037353 00000 n +0000037402 00000 n +0000037451 00000 n +0000037500 00000 n +0000037549 00000 n +0000037598 00000 n +0000037647 00000 n +0000037696 00000 n +0000037745 00000 n +0000037794 00000 n +0000037843 00000 n +0000037892 00000 n +0000037941 00000 n +0000038218 00000 n +0000038370 00000 n +0000044766 00000 n +0000044788 00000 n +0000044901 00000 n +0000045003 00000 n +0000045023 00000 n +0000045163 00000 n +0000046071 00000 n +0000046092 00000 n +0000046205 00000 n +0000046396 00000 n +0000046417 00000 n +0000046557 00000 n +0000047157 00000 n +0000047178 00000 n +0000047291 00000 n +0000047485 00000 n +0000047506 00000 n +0000047646 00000 n +0000048434 00000 n +0000048455 00000 n +0000048609 00000 n +0000049916 00000 n +0000049938 00000 n +0000050087 00000 n +0000051074 00000 n +0000051095 00000 n +0000051244 00000 n +0000052056 00000 n +0000052077 00000 n +0000052208 00000 n +0000053302 00000 n +0000053324 00000 n +0000053464 00000 n +0000054230 00000 n +0000054251 00000 n +0000054409 00000 n +0000055415 00000 n +0000055436 00000 n +0000055599 00000 n +0000057077 00000 n +0000057099 00000 n +0000057221 00000 n +0000058640 00000 n +0000058662 00000 n +0000058802 00000 n +0000060010 00000 n +0000060032 00000 n +0000060196 00000 n +0000061737 00000 n +0000061759 00000 n +0000061899 00000 n +0000062741 00000 n +0000062762 00000 n +0000062917 00000 n +0000063852 00000 n +0000063873 00000 n +0000063986 00000 n +0000064211 00000 n +0000064232 00000 n +0000064381 00000 n +0000064885 00000 n +0000064906 00000 n +0000065046 00000 n +0000065455 00000 n +0000065476 00000 n +0000065616 00000 n +0000066112 00000 n +0000066133 00000 n +0000066264 00000 n +0000066711 00000 n +0000066732 00000 n +0000066887 00000 n +0000070068 00000 n +0000070090 00000 n +0000070236 00000 n +0000070580 00000 n +0000070601 00000 n +0000070656 00000 n +0000070761 00000 n +0000070905 00000 n +0000071011 00000 n +0000071131 00000 n +0000071240 00000 n +0000071389 00000 n +0000071499 00000 n +0000071606 00000 n +0000071764 00000 n +0000071875 00000 n +0000071994 00000 n +0000072145 00000 n +0000072249 00000 n +0000072353 00000 n +0000072530 00000 n +0000072639 00000 n +0000072796 00000 n +0000072902 00000 n +0000073019 00000 n +0000073126 00000 n +0000073285 00000 n +0000073395 00000 n +0000073522 00000 n +0000073647 00000 n +0000073768 00000 n +0000073887 00000 n +0000074014 00000 n +0000074182 00000 n +0000074329 00000 n +0000074479 00000 n +0000074627 00000 n +0000074781 00000 n +0000074929 00000 n +0000075073 00000 n +0000075223 00000 n +0000075371 00000 n +0000075519 00000 n +0000075667 00000 n +0000075800 00000 n +0000075934 00000 n +0000076057 00000 n +0000076175 00000 n +0000076309 00000 n +0000076406 00000 n +0000076506 00000 n +trailer +<> +startxref +76692 +%%EOF diff --git a/doc/idd.shtml b/doc/idd.shtml new file mode 100644 index 0000000000..4da9a9e298 --- /dev/null +++ b/doc/idd.shtml @@ -0,0 +1,1219 @@ + + + + + + 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. + +

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. + +

Document Overview

+ +

This interface design description document is organized into the following +sections: + +

    +
  • 1 - Scope +
  • 2 - References +
  • 3 - Internal Interfaces +
  • 4 - External Interfaces +
  • 5 - Directories +
  • 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

+ +

The character set files define a mapping between 8-bit characters +and the Unicode character set. They are named using the ISO standard +number defined for the character set. Each file consists of up to 256 +lines of ASCII text. Each line consists of two hexadecimal numbers; the +first number is the character number in the character set (0x00 to +0xff), and the second number is the Unicode character number (0x0000 to +0xffff). + +

Language Files

+ +

The language files define the default character set and a collection of +text messages in that language. They are named by prefixing the string "cups_" +to the front of the language specifier (e.g. "cups_en", "cups_fr", etc.) Each +file consists of two or more lines of ASCII text. + +

The first line identifies the character set to be used for the messages. +The currently recognized values are: + +

    +
  • us-ascii +
  • utf-8 +
  • 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 +
  • iso-8859-14 +
  • iso-8859-15 +
+ +

The second and succeeding lines define text messages. If the message text +is preceded by a number, then the current message number is updated and the +text after the number is used. + +

MIME Files

+ +

CUPS uses two MIME files in its standard configuration. + +

mime.types

+ +

The mime.types file defines the recognized file types and consists +of 1 or more lines of ASCII text. Comment lines start with the pound +("#") character. The backslash ("\") character can be used at the end +of a line to continue that line to the next. + +

Each non-blank line starts with a MIME type identifier ("super/type") +as registered with the IANA. All text following the MIME type is treated as +a series of type recognition rules: + +

    +mime-type := super "/" type { SP rule }*
    +super := { "a-z" | "A-Z" }*
    +type := { "a-z" | "A-Z" | "-" | "." | "0-9" }*
    +rule := { extension | match | operator | "(" rule ")" }*
    +extension := { "a-z" | "A-Z" | "0-9" }*
    +match := "match(" regexp ")" |
    +         "ascii(" offset "," length ")" |
    +	 "printable(" offset "," length ")" |
    +	 "string(" offset "," string ")" |
    +	 "char(" offset "," value ")" |
    +	 "short(" offset "," value ")" |
    +	 "int(" offset "," value ")" |
    +	 "locale(" string ")"
    +operator := "+" |	[ logical AND ]
    +            "," | SP    [ logical OR ]
    +	    "!"         [ unary NOT ]
    +
+ +

The int and short rules match look for integers +in network byte order (a.k.a. big-endian) with the most-significant byte first. + +

mime.convs

+ +

The mime.types file defines the recognized file filters and consists +of 1 or more lines of ASCII text. Comment lines start with the pound +("#") character. + +

Each non-blank line starts with two MIME type identifiers ("super/type") +representing the source and destination types. Following the MIME types are +a cost value (0 to 100) and the filter program to use. If the filter program +is not specified using the full path then it must reside in the CUPS filter +directory. + +

PostScript Printer Description Files

+ +

The PostScript Printer Description (PPD) file format is described in + +Adobe TechNote #5003: PostScript Printer Description File Format +Specification Version 4.3. + +

CUPS Extensions to PPD Files

+ +

CUPS adds several new attributes that are described below. + +

cupsFilter

+ +

This string attribute provides a conversion rule of the form: + +

    +source/type cost program
    +
+ +

The destination type is assumed to the printer's type. If a printer +supports the source type directly the special filter program "-" may be +specified. + +

cupsManualCopies

+ +

This boolean attribute notifies the RIP filters that the destination printer +does not support copy generation in hardware. The default value is false. + +

cupsModelNumber

+ +

This integer attribute specifies a printer-specific model number. This number +can be used by a filter program to adjust the output for a specific model of +printer. + +

cupsProfile

+ +

This string attribute specifies a color profile of the form: + +

    +resolution/type density gamma m00 m01 m02 m10 m11 m12 m20 m21 m22
    +
+ +

The resolution and type values may be "-" to act as a +wildcard. Otherwise they must match one of the Resolution or +MediaType attributes defined in the PPD file. + +

The density and gamma values define gamma and density +adjustment function such that: + +

    +f(x) = density * xgamma
    +
+ +

The m00 through m22 values define a 3x3 transformation +matrix for the CMY color values. The density function is applied after +the CMY transformation. + +

cupsVersion

+ +

This required attribute describes which version of the CUPS IDD was used +for the PPD file extensions. Currently it must be the string "1.0". + +

Scheduler Configuration Files

+ +

The scheduler reads three configuration files that define the available +printers, classes, and services: + +

+ +
classes.conf +
This file defines all of the printer classes known to the + system. + +
cupsd.conf +
This file defines the files, directories, passwords, etc. + used by the scheduler. + +
printers.conf +
This file defines all of the printers known to the system. + +
+ +

classes.conf

+ +

The classes.conf file consists of 1 or more lines of ASCII text. +Comment lines start with the pound ("#") character. + +

Each non-blank line starts with the name of a configuration directive +followed by its value. The following directives are understood: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DirectiveDescription
<Class name>
+ </Class>
<DefaultClass name>
+ </Class>
Info
Location
MoreInfo
Printer
+ +

cupsd.conf

+ +

The cupsd.conf file consists of 1 or more lines of ASCII text. +Comment lines start with the pound ("#") character. + +

Each non-blank line starts with the name of a configuration directive +followed by its value. The following directives are understood: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DirectiveDefaultDescription
AccessLogSpecifies the location of the access log file (default + "logs/access_log").
Allow
AuthClass
AuthType
BrowseAddress
BrowseInterval
BrowsePort
BrowseTimeout
Browsing
DefaultCharset
DefaultLanguage
Deny
DocumentRoot
ErrorLog
Group
HostNameLookups
ImplicitClasses
KeepAlive
KeepAliveTimeout
<Location path>
+ </Location>
LogLevel
MaxClients
MaxLogSize
MaxRequestSize
Order
PageLog
Port
RIPCache
ServerAdmin
ServerName
ServerRoot
SystemGroup
TempDir
Timeout
User
+ +

printers.conf

+ +

The printers.conf file consists of 1 or more lines of ASCII text. +Comment lines start with the pound ("#") character. + +

Each non-blank line starts with the name of a configuration directive +followed by its value. The following directives are understood: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DirectiveDescription
<DefaultPrinter name>
+ </Printer>
DeviceURI
Info
Location
MoreInfo
<Printer name>
+ </Printer>
State
+ +

External Interfaces

+ +

AppSocket Protocol

+ +

The AppSocket protocol is an 8-bit clean TCP/IP socket connection. +The default IP service port is 9100. + +

CUPS Browsing Protocol

+ +

The CUPS Browsing Protocol is a UDP/IP-based broadcast service. By default +this service operates on IP service port 631. + +

Each broadcast packet describes the state of a single printer or class and +is an ASCII text string of up to 1450 bytes ending with a newline (0x0a). The +string is formatted as follows: + +

    +type SP state SP uri NL
    +
+ +

The state and uri values correspond to the IPP +printer-state and printer-uri-supported attributes. + +

The type value is a hexadecimal number string representing +capability/type bits: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BitDescription
00 = printer
+ 1 = class
10 = local
+ 1 = remote
+ (always 1)
21 = can print B&W
31 = can print color
41 = can duplex
51 = can staple
61 = can do fast copies
71 = can do fast collating
81 = can punch holes
91 = can cover
101 = can bind
111 = can sort
121 = can print up to 9x14 inches
131 = can print up to 18x24 inches
141 = can print up to 36x48 inches
151 = can print variable sizes
+ +

CUPS PostScript File

+ +

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

The MIME type for CUPS PostScript files is +application/vnd.cups-postscript. + +

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 points
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 points
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 points
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-339NegativePrint0 = Do not invert prints
+ 1 = Invert prints
340-343NumCopies1 to 232 - 1
344-347Orientation0 = Do not rotate page
+ 1 = Rotate page counter-clockwise
+ 2 = Turn page upside down
+ 3 = Rotate page clockwise
348-351OutputFaceUp0 = Output face down
+ 1 = Output face up
352-359PageSizeWidth and length in points
360-363Separations0 = Print composite image
+ 1 = Print color separations
364-367TraySwitch0 = Do not change trays if selected tray is empty
+ 1 = Change trays if selected tray is empty
368-371Tumble0 = Do not rotate even pages when duplexing
+ 1 = Rotate even pages when duplexing
372-375cupsWidthWidth of page image in pixels
376-379cupsHeightHeight of page image in pixels
380-383cupsMediaTypeDriver-specific 0 to 232 - 1
384-387cupsBitsPerColor1, 2, 4, 8 bits
388-391cupsBitsPerPixel1 to 32 bits
392-395cupsBytesPerLine1 to 232 - 1 bytes
396-399cupsColorOrder0 = chunky pixels (CMYK CMYK CMYK)
+ 1 = banded pixels (CCC MMM YYY KKK)
+ 2 = planar pixels (CCC... MMM... YYY... KKK...)
400-403cupsColorSpace0 = white
+ 1 = RGB
+ 2 = RGBA
+ 3 = black
+ 4 = CMY
+ 5 = YMC
+ 6 = CMYK
+ 7 = YMCK
+ 8 = KCMY
+ 9 = KCMYcm
404-407cupsCompressionDriver-specific 0 to 232 - 1
408-411cupsRowCountDriver-specific 0 to 232 - 1
412-415cupsRowFeedDriver-specific 0 to 232 - 1
416-419cupsRowStepDriver-specific 0 to 232 - 1
+ +

The MIME type for CUPS Raster files is +application/vnd.cups-raster. + +

CUPS Raw Files

+ +

Raw files are printer-dependent print files that are in a format suitable +to the destination printer (e.g. HP-PCL, HP-RTL, etc.) The MIME type for CUPS +Raw files is application/vnd.cups-raw. + +

File Transfer Protocol

+ +

The File Transfer Protocol (FTP) is described by +RFC 959: File Transfer +Protocol. + +

Internet Printing Protocol

+ +

The Internet Printing Protocol is described by the following RFCs: + +

+ +

CUPS defines the following extension operations to IPP. + +

Get Default Destination (CUPS_GET_DEFAULT = 0x4001)

+ +

The get default destination operation returns the printer attributes +for the system default printer or class. The only required attributes +are attributes-charset and +attributes-natural-language. + +

Get default destination will only return ipp-ok. + +

Get Printers (CUPS_GET_PRINTERS = 0x4002)

+ +

The get printers operation returns the printer attributes for all +printers known to the system. The only required attributes are +attributes-charset and +attributes-natural-language. + +

Get printers will only return ipp-ok. + +

Add Printer (CUPS_ADD_PRINTER = 0x4003)

+ +

The add printer operation adds or replaces the specified printer. The +attributes-charset, +attributes-natural-language and printer-uri +attributes are required. + +

The printer-location, printer-info, +printer-more-info, and device-uri attributes +are required when initially adding a printer and optional when modifying +a printer. + +

A PPD file or System V interface script may follow the IPP request +body. If a valid interface script or PPD file is not provided then the +printer is treated as a generic PostScript device. + +

Add printer will return ipp-ok, ipp-not-authorized, +ipp-bad-request, or ipp-attributes. + +

Delete Printer (CUPS_DELETE_PRINTER = 0x4004)

+ +

The delete printer operation removes the specified printer. The only +required attributes are attributes-charset, +attributes-natural-language, and printer-uri. + +

Delete printer will return ipp-ok, ipp-not-found, +or ipp-not-authorized. + +

Get Classes (CUPS_GET_CLASSES = 0x4005)

+ +

The get classes operation returns the printer attributes for all +classes known to the system. The only required attributes are +attributes-charset and +attributes-natural-language. + +

Get classes will only return ipp-ok. + +

Add Class (CUPS_ADD_CLASS = 0x4006)

+ +

The add class operation adds or replaces the specified class. The +attributes-charset, +attributes-natural-language, and printer-uri +attributes are required. + +

The printer-location, printer-info, +printer-more-info, and member-uris attributes +are required when initially adding a printer and optional when modifying +a printer. + +

Add class will return ipp-ok, ipp-not-authorized, +ipp-bad-request, or ipp-attributes. + +

Delete Class (CUPS_DELETE_CLASS = 0x4007)

+ +

The delete class operation removes the specified class. The only +required attributes are attributes-charset, +attributes-natural-language, and printer-uri. + +

Delete class will return ipp-ok, ipp-not-found, +or ipp-not-authorized. + +

Accept Jobs (CUPS_ACCEPT_JOBS = 0x4008)

+ +

The accept jobs operation allows jobs to be accepted by the +specified destination. The only required attributes are +attributes-charset, +attributes-natural-language, and +printer-uri. + +

Accept jobs will return ipp-ok, ipp-not-found, +or ipp-not-authorized. + +

Reject Jobs (CUPS_REJECT_JOBS = 0x4009)

+ +

The reject jobs operation prevents jobs from being accepted by the +specified destination. The only required attributes are +attributes-charset, +attributes-natural-language, and +printer-uri. + +

Reject jobs will return ipp-ok, ipp-not-found, +or ipp-not-authorized. + +

Set Default Destination (CUPS_SET_DEFAULT = 0x400A)

+ +

The set default destination operation returns the printer attributes +for the system default printer or class. The only required attributes +are attributes-charset, +attributes-natural-language, and printer-uri. + +

Set default destination will return ipp-ok, +ipp-not-authorized, ipp-bad-request, or +ipp-not-found. + +

Line Printer Daemon Protocol

+ +

The Line Printer Daemon (LPD) protocol is described by +RFC 1179: Line Printer Daemon +Protocol. + +

Server Message Block Protocol

+ +

The Server Message Block (SMB) and related Common Internet File +System (CIFS) protocols are described at +http://anu.samba.org/cifs. + +

Trivial File Transfer Protocol

+ +

The Trivial File Transfer Protocol (TFTP) is described by +RFC 1350: The TFTP Protocol +(Revision 2). + +

5 - Directories

+ +
+ +
/usr/bin +
The cancel, lp, lpq, + lpr, lprm, and lpstat commands + reside here. + +
/usr/lib +
The accept, disable, enable, + lpadmin, and reject commands reside here. + +
/usr/sbin +
The lpc and cupsd commands resize here. + +
/usr/share/cups +
This is the root directory of the CUPS static data. + +
/usr/share/cups/data +
The character set and filter data files reside here. + +
/usr/share/cups/fonts +
The pstoraster font files reside here. + +
/usr/share/cups/model +
The sample PPD files reside here. + +
/usr/share/cups/pstoraster +
The pstoraster data files reside here. + +
/var/cups +
This is the root directory of the CUPS scheduler. + +
/var/cups/backend +
The backend filters reside here. + +
/var/cups/cgi-bin +
The CGI programs reside here. + +
/var/cups/conf +
The scheduler configuration and MIME files reside here. + +
/var/cups/doc +
The scheduler documentation files reside here. + +
/var/cups/filter +
The file filters reside here. + +
/var/cups/interfaces +
System V interface scripts reside here. + +
/var/cups/logs +
The access_log, error_log, and + page_log files reside here. + +
/var/cups/ppd +
This directory contains PPD files for each printer. + +
/var/cups/requests +
This directory contains pending print job files. + +
+ +

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/classes.gif b/doc/images/classes.gif new file mode 100644 index 0000000000000000000000000000000000000000..ace15df98035c8ff3e41036b0be59f2664f7d0d3 GIT binary patch literal 591 zc-jF^08~U*5-X9+fD*emQ%-t<0(_wQriGZ zZZazx6{;H!rfZ&NF^DjR%UP$gL12(v1z%TG%JvI>t<>1d$R6}E?QFaBuG=p#CYq`w ziZLKnI#?fMDjR}LReukMU5I;WPjg%#kve@k4n}f;gCRUfWn^cOf{Z>uD@%zdL!5^? zZErJON@0|Ace@NlyuZK^mQ+k1!FGr)XqH-AsBeLx4HT-7rY(4&t$Tq1JGN%5Vb2<> zecNi2Y_Y^HEYhh!)TfI?l!TXqlgPG)&Q*(hvyg$SQ4d$HfyWfAV+V3h%sVe{>bzsg*v?&fS|wvO z;ipJR`P$Vo+Q`t9b~&`r2nMgIIb~O{sU$>Hj3ZL$G-e2z&tV~XEGM?mG=|~0JOR9Q zx~ivQkCoAuorL9KVzjCZsL7LY2n_~8V(13pGyvmhOX_!0g^}SfQhCYc7E-lJ z<8mqB@6klgfj#Q`%u%b%(iC7vD_0O};S&#LvOb}>9YnB~>XIW%d3BaYhzM(>GRB~0 zFrl4c{!(`{Okt{tJ(sb!5}DI%@Dx;B@|5J*;qU$?8QeVQ>viyE2Cb&1&70FFgU_{d d<`(xg{4v$bVfLjbU) 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 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 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 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 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..99ff5b0b60 --- /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..34e13ba325f0b3645c0a52018ff307138ba73af3 GIT binary patch literal 18985 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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

+
+
Preface + +1 - Printing System Overview + +2 - Building and Installing CUPS + +3 - Printer Queue Management + +4 - Printing System Management + +5 - Printer Accounting + +
+

Preface

+ This software administrators manual provides printer administration +information for the Common UNIX Printing System ("CUPS") Version 1.0.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.

+

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.

+

Document Overview

+

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

+
    +
  • 1 - Printing System Overview
  • +
  • 2 - Building and Installing CUPS
  • +
  • 3 - Printer Queue Management
  • +
  • 4 - Printing System Management
  • +
  • 5 - Printer Accounting
  • +
+

1 - Printing System Overview

+

This chapter provides an overview of how the Common UNIX Printing +System works.

+

The Printing Problem

+

For years the printing problem has plagued UNIX®. Unlike +Microsoft® Windows® or MacOS, UNIX has no standard interface or system +in place for supporting printers. Among the solutions previously +available, the Berkeley and System V printing systems are the most +prevalent.

+

These printing systems support line printers (text only) or +PostScript printers (text and graphics), and with some coaxing they can +be made to support a full range of printers and file formats. However, +because each varient of the UNIX operating system uses a different +printing system than the next, developing printer drivers for a wide +range of printers is extremely difficult. That combined with the +limited volume of customers for each UNIX varient has forced most +printer vendors to give up supporting UNIX entirely.

+

The Common UNIX Printing System, or CUPS, is designed to eliminate +the printing problem. One common printing system can be used by all +UNIX varients to support the printing needs of users. Printer vendors +can use its modular filter interface to develop a single driver program +that supports a wide range of file formats with little or no effort. + Since CUPS provides both the System V and Berkeley printing commands, +users (and applications) can reap the benefits of this new technology +with no changes.

+

The Technology

+

CUPS is based upon an emerging Internet standard called the Internet +Printing Protocol, or IPP. IPP has been embraced by dozens of printer +and printer server manufacturers, and will be supported by the next +Microsoft Windows operating system.

+

IPP defines a standard protocol for printing as well as managing +print jobs and printer options like media size, resolution, and so +forth. Like all IP-based protocols, IPP can be used locally or over the +Internet to printers hundreds or thousands of miles away. Unlike other +protocols, however, IPP also supports access control, authentication, +and encryption, making it a much more secure printing solution than +older ones.

+

IPP is layered on top of the Hyper-Text Transport Protocol, or HTTP, +which is the basis of web servers on the Internet. This allows the user +to view documentation and status information on a printer or server +using their web browser.

+

CUPS provides a complete IPP/1.0-based printing system that provides +Basic authentication and domain or IP-based access control. Digest +authentication and TLS encryption will be available in future versions +of CUPS.

+

Jobs

+

Each file that is submitted for printing is called a job. + Jobs are identified by a unique number starting at 1 and are assigned +to a particular destination (usually a printer). Jobs can also have +options associated with them such as media size, number of copies, and +priority.

+

Classes

+

CUPS supports collections of printers known as classes. Jobs +sent to a class are forwarded to the first available printer in the +class.

+

Filters

+

Filters allow a user or application to print many types of files +without extra effort. Print jobs sent to a CUPS server are filtered +before sending them to a printer. Some filters convert job files to +different formats that the printer can understand. Others perform page +selection and ordering tasks. Backend filters perform the most +important task of all - they send the filtered print data to the +printer.

+

CUPS provides filters for printing many types of image files, +HP-GL/2 files, PDF files, and text files. CUPS also supplies PostScript +and image file Raster Image Processors, or RIPs, that convert +PostScript or image files into bitmaps that can be sent to a raster +printer.

+

CUPS provides backends for printing over parallel and serial ports, +and over the network via the JetDirect (AppSocket), Server Message +Block, and Line Printer Daemon protocols.

+

Printer Drivers

+

Printer drivers in CUPS consist of one of more filters specific to a +printer. CUPS includes a sample printer driver for Hewlett-Packard +LaserJet and DeskJet printers. While this driver does not generate +optimal output for different printer models, it does demonstrate how +you can write your own printer drivers and incorporate them into CUPS.

+

Networking

+

Printers and classes on the local system are automatically shared +with other systems on the network. This allows you to setup one system +to print to a printer and use this system as a printer server or spool +host for all of the others. If there is only one occurrence of a +printer on a network, then that printer can be accessed using its name +alone. If more than one printer exists with the same name, users must +select the printer by specifying which server to use (e.g. +"printer@host1" or "printer@host2".)

+

CUPS also provides implicit classes, which are collections of +printers and/or classes with the same name. This allows you to setup +multiple servers pointing to the same physical network printer, for +example, so that you aren't relying on a single system for printing. +Because this also works with printer classes, you can setup multiple +servers and printers and never worry about a "single point of failure" +unless all of the printers and servers goes down!

+

2 - Building and Installing CUPS

+

This chapter shows how to build and install the Common UNIX Printing +System. If you are installing a binary distribution from the CUPS web +site, proceed to the section titled, Installing a +Binary Distribution.

+

Installing a Source Distribution

+

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 and PostScript RIP, you'll need the JPEG, +PNG, TIFF, and ZLIB libraries. CUPS will build without these, but with +reduced functionality. Easy Software Products maintains a mirror of the +current versions of these libraries at:

+ +

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

+ +

The documentation is formatted using the HTMLDOC software. If you +need to make changes you can get the HTMLDOC software from:

+ +

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
    +
    +
+

If the PNG, JPEG, TIFF, and ZLIB libraries are not installed in a +system default location (typically /usr/include and +/usr/lib) you'll need to set the CFLAGS and +LDFLAGS environment variables prior to running configure:

+
    +
    +% setenv CFLAGS "-I/some/directory"
    +% setenv LDFLAGS "-L/some/directory"
    +% ./configure ... 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
    +
    +
+

Running the Software

+ Once you have installed the software you can start the CUPS daemon by +typing: +
    +
    +% /usr/sbin/cupsd & ENTER
    +
    +
+

Installing a Binary Distribution

+

We are currently distributing CUPS binary distributions in TAR +format with installation and removal scripts.

+
    WARNING: +

    Installing CUPS will overwrite your existing printing system. If +you experience difficulties with the CUPS software and need to go back +to your old printing system, you will need to remove the CUPS software +with the provided script and reinstall the printing system from your +operating system CDs.

    +
+

To install the CUPS software you will need to be logged in as root +(doing an "su" is good enough). Once you are the root user, run the +installation script with:

+
    +
    +./cups.install ENTER
    +
    +
+

After asking you a few yes/no questions the CUPS software will be +installed and the scheduler will be started automatically.

+

3 - Printer Queue Management

+

This chapter discusses how to add, modify, and delete print queues +on your system.

+

The lpadmin Command

+

The lpadmin command allows you to perform most printer +administration tasks from the command-line. Since lpadmin + is also a System V printing system command, it is located in the +/usr/lib directory instead of a more common one like +/usr/bin or /usr/sbin.

+

Adding and Modifying Printers

+

To add a printer to CUPS you simply run the lpadmin + command with the "-p" option:

+
    +
    +% /usr/lib/lpadmin -pprinter -E -vdevice -Pppd ENTER
    +
    +
+

Spaces between the option letter and value are optional.

+

The printer name can be up to 127 letters, digits, hyphens, +and underscores. Unlike other printing systems, the printer name in +CUPS is not case-sensitive, so you can't add two printers named +LaserJet and laserjet.

+

The device argument specifies the device URI or filename for +the printer. The following devices are supported in a basic +installation of CUPS:

+
+
file:/dev/filename
+
/dev/filename
+
Sends all output to the specified file.
+
http://[username:password@]hostname[:port]/resource
+
ipp://[username:password@]hostname[:port]/resource
+
Sends all output to the specified IPP printer or server. The +port parameters defaults to 631.
+
lpd://hostname/queue
+
Sends all output to the specified LPD printer queue.
+
parallel:/dev/filename
+
Sends all output to the specified parallel port device.
+
serial:/dev/filename[?options]
+
Sends all output to the specified serial port device. The +options can be any of the following separated by the plus (+) +character: +
    +
  • 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://[username:password@]hostname/queue
+
Sends all output to the specified SMB (Windows) printer queue + using the SAMBA software.
+
socket://hostname[:port]
+
Sends all output to the specified printer using the AppSocket +protocol. The port parameter defaults to 9100.
+
+

The ppd argument specifies the PostScript Printer Description +file to use for this printer. Many options (such as media size, etc.) +will not be available if you omit this part of the lpadmin + command.

+

Using Standard Printer Drivers

+

The lpadmin command allows you to use "standard" PPD +files and interface scripts located in the /usr/share/cups/model + directory with the "-m" option:

+
    +
    +% /usr/lib/lpadmin -pprinter -E -vdevice -mmodel ENTER
    +
    +
+

The model argument specifies the name of the PPD file or +interface script. For example, to add a printer using the sample HP +DeskJet series driver connected to parallel port 1 under Linux you +would use:

+
    +
    +% /usr/lib/lpadmin -pDeskJet -E -vparallel:/dev/par1 -mdeskjet.ppd ENTER
    +
    +
+

Removing Printers

+

To remove a printer to CUPS you simply run the lpadmin + command with the "-x" option:

+
    +
    +% /usr/lib/lpadmin -xprinter ENTER
    +
    +
+

Printer Classes

+

CUPS allows you to group similar printers in a printer class. +When a user sends a print job to a class, the job will be processed by +the first available printer in that class.

+

To add a printer to a class you simply run the lpadmin + command with the "-p" and "-c" options:

+
    +
    +% /usr/lib/lpadmin -pprinter -cclass ENTER
    +
    +
+

The class is created automatically if it doesn't exist. To +remove a class just use the "-x" option:

+
    +
    +% /usr/lib/lpadmin -xclass ENTER
    +
    +
+

Setting the Default Printer

+

To set the default printer or class simply run the lpadmin + command with the "-d" option:

+
    +
    +% /usr/lib/lpadmin -ddestination ENTER
    +
    +
+

The destination argument is the name of the printer or class.

+

Starting and Stopping Printers

+

The enable and disable commands start and +stop printer queues, respectively:

+
    +
    +% /usr/bin/enable printer ENTER
    +% /usr/bin/disable printer ENTER
    +
    +
+

Printers that are disabled may still accept jobs for printing, but +won't actually print any files until they are restarted. This is useful +if the printer malfunctions and you need time to correct the problem. +Any queues jobs are printed after the printer is enabled (started).

+

Accepting and Rejecting Print Jobs

+

The accept and reject commands accept and +reject print jobs for the named printer, respectively:

+
    +
    +% /usr/lib/accept printer ENTER
    +% /usr/lib/reject printer ENTER
    +
    +
+

As noted above, a printer can be stopped but accepting new print +jobs. A printer can also be rejecting new print jobs while it finishes +those that have been queued. This is useful for when you must perform +maintenance on the printer and will not have it available to users for +a long period of time.

+

4 - Printing System Management

+

This chapter shows how you can configure the CUPS server.

+

Changing the Configuration Files

+

All of the server configuration files are located in the +/var/cups/conf directory. Once you have made a change to a file +you need to restart the CUPS server by sending it a HUP signal or using +the supplied script "cups.sh":

+
    +
    +% ./cups.sh restart ENTER
    +
    +
+

The binary distribution installs the script in the init.d + directory with the name lp or lpd depending +on the vendor-supplied printing system.

+

Temporary Files

+

Normally CUPS puts all of its temporary files in /var/tmp +. If you'd like to change this directory you'll need to edit the +/var/cups/conf/cupsd.conf file.

+

Start by creating the new temporary directory and setting the +appropriate permissions:

+
    +
    +% mkdir /foo/bar/tmp ENTER
    +% chmod a+rwxt /foo/bar/tmp ENTER
    +
    +
+

Then change the line containing the TempDir directive +in the cupsd.conf to the directory that you've created:

+
    +
    +TempDir /foo/bar/tmp
    +
    +
+

Finally, restart the server as outlined in the first section of this +chapter.

+

Network Configuration

+

The default configuration of the CUPS server listens for connections +from all network interfaces on port 631 (the standard IPP port). +Administration functions are limited to local connections with the +appropriate username and password.

+

If you'd like to limit access to your system you'll need to edit the +/var/cups/conf/cupsd.conf file.

+

Port

+

The Port directive specifies a port to listen on for +all interfaces. Besides the standard IPP port (631) you can also setup +your server to listen on the HTTP port (80) to use your CUPS server as +a standard web server as well.

+

Listen

+

The Listen directive specifies a listening address and +port, extending the functionality of the Port directive. +If you want to allow connections only from the local machine you can +use:

+
    +
    +Listen 127.0.0.1:631
    +
    +
+

instead of the Port directive.

+

If you want to limit access to a specific network/subnet, make sure +you specify only the network address and not your system's network +address!

+

BrowsePort

+

The BrowsePort directive controls which port is +monitored for remote printers. By default it is set to the IPP port +(631), however you can change it as needed.

+
    NOTE: +

    You must set the BrowsePort to the same value on all +of the systems that you want to see.

    +
+

BrowseAddress

+

The BrowseAddress directive specifies a broadcast +address to use when sending printer status updates over the network. +The default browse address is 255.255.255.255 which will +send printer information to all subnets.

+
    NOTE: +

    If you are using HP-UX 10.20 and a subnet that is not 24, 16, or 8 +bits, printer browsing (and in fact all broadcast reception) will not +work. This problem appears to be fixed in HP-UX 11.0.

    +
+

Printer Security

+

CUPS provides IP and domain-name based access control and Basic +authentication for authentication.

+

Location

+

The Location directive defines access control for a +specific HTTP directory. The following pseudo directories are provided +by the CUPS server:

+
    +
  • /admin - This is the URI that must be referenced to + do printer administation commands.
  • +
  • /classes - This is the URI that must be referenced to + access printer classes.
  • +
  • /jobs - This is the URI that must be referenced to + access jobs.
  • +
  • /printers - This is the URI that must be referenced to + access printers.
  • +
+

All other directories are taken from the /usr/share/cups/doc + directory.

+

The Location directive surrounds the other access +control directives described below. The default server configuration +uses:

+
    +
    +<Location /admin>
    +AuthType Basic
    +AuthClass System
    +
    +Order Deny,Allow
    +Deny From All
    +Allow From 127.0.0.1
    +</Location>
    +
    +
+

Order

+

The Order directive defines the default access control. +The following values are supported:

+
    +
  • Order Allow,Deny - Allow requests from all systems +except for those listed in a Deny directive.
  • +
  • Order Deny,Allow - Allow requests only from those +listed in an Allow directive.
  • +
+

The Order directive must appear inside a Location + directive.

+

Allow

+

The Allow directive specifies a hostname, IP address, +or network that is allowed access to the server:

+
    +
    +Allow from All
    +Allow from None
    +Allow from *.domain.com
    +Allow from .domain.com
    +Allow from host.domain.com
    +Allow from nnn.*
    +Allow from nnn.nnn.*
    +Allow from nnn.nnn.nnn.*
    +Allow from nnn.nnn.nnn.nnn
    +Allow from nnn.nnn.nnn.nnn/mm
    +Allow from nnn.nnn.nnn.nnn/mmm.mmm.mmm.mmm
    +
    +
+

Allow directives are cummulative, so multiple +Allow directives can be used to allow access for multiple hosts +or networks. The /mm notation specifies a CIDR netmask: +

+ + + + + + + + + + +
mmnetmask
00.0.0.0
1128.0.0.0
2192.0.0.0
......
8255.0.0.0
16255.255.0.0
24255.255.255.0
32255.255.255.255
+
+

+

The Allow directive must appear inside a Location + directive.

+

Deny

+

The Deny directive specifies a hostname, IP address, or +network that is allowed access to the server:

+
    +
    +Deny from All
    +Deny from None
    +Deny from *.domain.com
    +Deny from .domain.com
    +Deny from host.domain.com
    +Deny from nnn.*
    +Deny from nnn.nnn.*
    +Deny from nnn.nnn.nnn.*
    +Deny from nnn.nnn.nnn.nnn
    +Deny from nnn.nnn.nnn.nnn/mm
    +Deny from nnn.nnn.nnn.nnn/mmm.mmm.mmm.mmm
    +
    +
+

Deny directives are cummulative, so multiple Deny + directives can be used to allow access for multiple hosts or networks. + The /mm notation specifies a CIDR netmask: +

+ + + + + + + + + + +
mmnetmask
00.0.0.0
1128.0.0.0
2192.0.0.0
......
8255.0.0.0
16255.255.0.0
24255.255.255.0
32255.255.255.255
+
+

+

The Deny directive must appear inside a Location + directive.

+

AuthType

+

The AuthType directive defines the type of +authentication to perform:

+
    +
  • None - No authentication should be performed + (default.)
  • +
  • Basic - Basic authentication should be performed +using the UNIX password and group files.
  • +
+

The AuthType directive must appear inside a +Location directive.

+

AuthClass

+

The AuthClass directive defines what level of +Basic access is required:

+
    +
  • Anonymous - No authentication should be performed + (default.)
  • +
  • User - A valid username and password is required.
  • +
  • System - A valid username and password is required, +and the username must belong to the "sys" group (this can be changed +using the SystemGroup directive, below.
  • +
  • Group - A valid username and password is required, +and the username must belong to the group named by the +AuthGroupName directive.
  • +
+

The AuthClass directive must appear inside a +Location directive.

+

AuthGroupName

+

The AuthGroupName directive sets the group to use for +Group authentication.

+

The AuthGroupName directive must appear inside a +Location directive.

+

SystemGroup

+

The SystemGroup directive sets the administration group +used when authenticating the System type. It defaults to +the "sys" group.

+

File Formats

+

CUPS provides a MIME-based file typing and filtering mechanism to +convert files to a printable format for each printer. The +mime.types and mime.convs files define the file +type and filters that are available on the system.

+

mime.types

+

The mime.types defines the known file types. Each line +of the file starts with the MIME type and may be followed by one or +more file type recognition rules. For example, the text/html + file type is defined as:

+
    +
    +text/html html htm \
    +          printable(0,1024) + (string(0,"<HTML>") string(0,"<!DOCTYPE"))
    +
    +
+

The first two rules say that any file with an extension of ".html" +or ".htm" is a HTML file. The third rules says that any file whose +first 1024 characters are printable text and starts with the strings +"<HTML>" or "<!DOCTYPE" is a HTML file as well.

+

The first two rules deal solely with the name of the file being +typed. This is useful when the original filename is known, however for +print files the server doesn't always have a filename to work with. The +third rule takes care of this possibility and automatically figures out +the file type based upon the contents of the file instead.

+

The available tests are:

+
    +
  • ( 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 (network or "big-endian" byte order)
  • +
  • int(offset,value) - True if 32-bit integer is + identical (network or "big-endian" byte order)
  • +
  • locale("string") - True if current locale matches +string
  • +
+

mime.convs

+

The mime.convs file defines all of the filter programs +that are known to the system. Each line consists of:

+
    +
    +source destination cost program
    +
    +text/plain application/postscript 50 texttops
    +application/vnd.cups-postscript application/vnd.cups-raster 50 pstoraster
    +image/* application/vnd.cups-postscript 50 imagetops
    +image/* application/vnd.cups-raster 50 imagetoraster
    +
    +
+

The source field is a MIME type, optionally using a wildcard +for the super-type or sub-type (e.g. "text/plain", "image/*", +"*/postscript").

+

The destination field is a MIME type defined in the +mime.types file.

+

The cost field defines a relative cost for the filtering +operation from 1 to 100. The cost is used to choose between two +different sets of filters when converting a file. For example, to +convert from image/jpeg to +application/vnd.cups-raster, you could use the imagetops + and pstoraster filters for a total cost of 100, or the +imagetoraster filter for a total cost of 50.

+

The program field defines the filter program to run; the +special program "-" can be used to make two file types equivalent. The +program must accept the standard filter arguments and environment +variables described in the CUPS Interface Design Document:

+
    +
    +program job user title options [filename]
    +
    +
+

If specified, the filename argument defines a file to read +when filtering, otherwise the filter must read from the standard input. +All filtered output must go to the standard output.

+

5 - Printer Accounting

+ This chapter describes the CUPS log files. +

Where to Find the Log Files

+

The log files are normally stored in the /var/cups/logs + directory. You can change this by editing the +/var/cups/conf/cupsd.conf configuration file.

+

The access_log File

+

The access_log file lists each HTTP resource that is +accessed by a web browser or CUPS/IPP client. Each line is in the +so-called "Common Log Format" used by many web servers and web +reporting tools:

+
    +
    +host group user date-time \"method resource version\" status bytes
    +
    +127.0.0.1 - - [20/May/1999:19:20:29 +0000] "POST /admin/ HTTP/1.1" 401 0
    +127.0.0.1 - mike [20/May/1999:19:20:31 +0000] "POST /admin/ HTTP/1.1" 200 0
    +
    +
+

The host field will normally only be an IP address unless you +have changed the HostnameLookups directive on in the +cupsd.conf file.

+

The group field always contains "-".

+

The user field is the authenticated username of the +requesting user. If no username and password is supplied for the +request then this field contains "-".

+

The date-time field is the date and time of the request in +Greenwich Mean Time (a.k.a. ZULU) and is in the format:

+
    +
    +[DD/MON/YYYY:HH:MM:SS +0000]
    +
    +
+

The method field is the HTTP method used ("GET", "PUT", +"POST", etc.)

+

The resource field is the filename of the requested resource.

+

The version field is the HTTP specification version used by +the client. For CUPS clients this will always be "HTTP/1.1".

+

The status field contains the HTTP result status of the +request. Usually it is "200", but other HTTP status codes are possible. +For example, 401 is the "unauthorized access" status in the example +above.

+

The bytes field contains the number of bytes in the request. +For POST requests the bytes field contains the number of bytes +of non-IPP data that is received from the client.

+

The error_log File

+

The error_log file lists messages from the scheduler +(errors, warnings, etc.):

+
    +
    +level date-time message
    +
    +I [20/May/1999:19:18:28 +0000] Job 1 queued on 'DeskJet' by 'mike'.
    +I [20/May/1999:19:21:02 +0000] Job 2 queued on 'DeskJet' by 'mike'.
    +I [20/May/1999:19:22:24 +0000] Job 2 was cancelled by 'mike'.
    +
    +
+

The level field contains the type of message:

+
    +
  • E - An error occurred.
  • +
  • W - The server was unable to perform some action.
  • +
  • I - Informational message.
  • +
  • D - Debugging message.
  • +
+

The date-time field contains the date and time of when the +page started printing. The format of this field is identical to the +data-time field in the access_log file.

+

The message fields contains a free-form textual message.

+

The page_log File

+

The page_log file lists each page that is sent to a +printer. Each line contains the following information:

+
    +
    +printer user job-id date-time page-number num-copies
    +
    +DeskJet root 2 [20/May/1999:19:21:05 +0000] 1 0
    +
    +
+

The printer field contains the name of the printer that +printed the page. If you send a job to a printer class, this field will +contain the name of the printer that was assigned the job.

+

The user field contains the name of the user (the IPP +requesting-user-name attribute) that submitted this file for +printing.

+

The job-id field contains the job number of the page being +printed. Job numbers are reset to 1 whenever the CUPS server is +started, so don't depend on this number being unique!

+

The date-time field contains the date and time of when the +page started printing. The format of this field is identical to the +data-time field in the access_log file.

+

The page-number and num-pages fields contain the page +number and number of copies being printed of that page. For printer +that can not produce copies on their own, the num-pages field +will always be 1.

+ + diff --git a/doc/sam.pdf b/doc/sam.pdf new file mode 100644 index 0000000000..244562c0d4 --- /dev/null +++ b/doc/sam.pdf @@ -0,0 +1,1114 @@ +%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[11 0 R +12 0 R +13 0 R +14 0 R +16 0 R +]endobj +18 0 obj<>endobj +19 0 obj<>endobj +20 0 obj<>endobj +21 0 obj<>endobj +22 0 obj[19 0 R +21 0 R +]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<>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[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 +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 +]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[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 +149 0 R +150 0 R +]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<>stream +xÚíßÜ8rÇ¥nõ‹Ÿ4³îwNH€ØîOÛg 4?´‰(IòäÁ¸õå6Ø»ÍÙÞ÷ß§M·~RU‘’¨¹á Ï ÕâG,~«HÕ}q%V›ÿ®Ä‡kñî½øÃŸ_Üɱ|ñWñnõ»7v|÷þý›•øÝÇ7×âúúêÍ֧ͮ·÷Ù¼ýô6ý×;±þçÕ®¼Û•÷»òqWîwåÇ]ù—ÿ|ûI|ÿúۗ·ÿ.nÞ]½ý7±¾ºz{÷âF|zx‘?ÍÏ\fE>\/‹‹³mÙücqó0v.y¿8 =U9;¿|'—¼¾P#à7#ã’×mLåü2 ê€v3®û \üEì8×]èñÊùÚa®k.•MsgúÊnŸY溞yù!vŒ+»ð¬ÿÒ)®kÏZ™¬á’³Y.á2Ö »]f‰K^x֋ÿjp®,ôº(? ÌuçuT&ñ\W^gÅ_ÆeY-ÛX›òj.zž‹`खËËÞ¹zÁbÁ°8`0,8-|ñ€q`yÞ²'®Îý–™ƒfsõŒµ‹ûàZy½—I\·ÞeÚ9Wê R^v̕…ÃpDÜWx–vÀ¤¡0Í 1:Wæ ZÖ]q…Ãr!‡ŒÀ!s¼ŒÃs‘ÅžÈ%‡Çòü¸„\^`+õœ(kË\2tƒkb™kå9RæV¹Rϙ[ärÅ +QNŒÀy•µ5®Ì%¬Vé€ñ‰*ꀊ&ê€QEx­Çr%®aµtŒOãQ#ÔxŒsÆqI±ãz£Æ#FŒÏ%£Fô×]gç‹Å«‡m¹Û|è¶Ã —îòÏ_ÕùöDgÝw—ߐô/ï/ºé0躻Î[§JwhK®U7]U쵅õ°:ì.Bú±äæ¯Ù\ìPƒ–.Î$›r¹¸¡==7cMb&³»XéԜ. ˜\¬@ž› Éè2ŸÇ•t£í»lÉâ +û²Á£7 ­H=Ø_Õ0I{ç$¬\¢·¡Åϼ +è\ÙXd0ŸÎEyßÎIa¬Í\aÁ¦T®d#ä˜bLäCaÁæ4®ÌЇ䂅F. ìM¼^æVKjdˆ`-’·ŒE:}5§p%£²2¸9XR ?¶ÏEhAŒç’æAšiÉø†¨ç‚A׾ܲ ¬ÌP&yGEp lÈl'ƒ‹6æX®h(‡Ìå –‹`†Ó¼Ã"x†æf؝R4q‰ãZ9a…„–8.´&>Š+Ø#3lá«aw^p6Ãp…nˆEë'®”˜ ×aq;WäŠhP:lÙÎ:¢ñ¤ö­\©[݅ì°I+WäXw!}XÜÆ:Ö]È'=oáʜqÉ´&-\‰s݅‹'-\±х–²¸‘K:Ø]¸1¿läJì.Ü2RÐȅTy¿W,”M¹B‡"C¢r4qaU¾g,ÔðX7p!U>è›+'ÙpU~Ý;§ \¬­± q¢çJ]y´ ÅZ.pQäÑh©åŽªΔf:.éªjà†þTǕÒBò';ýT1öÇßÃá™&%UN±~~…o°‚¨9Šk®å’¥‡5%´]k¬á´X£‘kªå:ܦ¨sÇ!ñ8Ã+Àqyz.(¨W†7ڒ€3¼–H®¥–++<Àš!f”j. :¯f®@˵·½É©&–”~¢æDçÕÌ5Ñs´BRf=ègŒàp‰åz4.×IÛS¼b”>VqeÔª…k®å:‰`DY+I°ès¯Ï5ÕsE(¤L¾3¬ y®] +å[¸<=Wzø¬Œb†ˆ¨¸B¢¶r-µ\û{Íö¿Â/Ùµ +ÛTÁ%©fØÊè¹V{ QßC5Znó\)Õ [¹|=×þfÄéAŠD {åË5=ÖVríãŒºrŒŒê•'9–k>ʓ’« R”YªÀÙPecŽçŠƒš+aÍR[CÄY+#›a3WZ©qIÖbI‚Ó5 ÊÆ$ÇsÉG³PsMŠ´X’áZĹr@àÚ5<Ðs%¬5;œÐQ6–.8ÜFÃ%Ykv­­¬q1Ò›¹²ƒ(h¸M$®ÙE¨&M6&9…+?(½Ž 8N ʤ€&3×Aéu\§¿R”'šl,i\¥×q…œñ%Qϸ‚(®ƒÒk¸RÞFˆ‘l E"×Aé5\o±¿íùOË\’1¼Z¹öJ¯á +y›3æáI6–T®½Ò«¹2æ.F‚qÌ@ZÛÈ©\{¥WsÞ Ì"©2WÄ^í\;¥Ws fæŽÄ8f DQkgݑ~^¹`b›À­K\¬Mårl¥àÚµ^¨¸öv/!‡@4(QT¬~tqÑ@ü2שU.±×dA7Ä"àVA™kY|4U.Ðp=va7» 3+r!Öl¦“˜uRáÊ4\Ɂ'£b‚ Èá\cÓúÕõÏ:×êñ! w+ў¶Ä%8²QÚ–_TàŠ”\ò؂Ù%®€jM"(,«\©’+9VNè±/BNô¾ûJ›«¢fÖüT•kuÔIÏ· +ñ\Ç+Ÿn៕áqE™«ð‰‚ûŠöðÑáãKfu®DÁULE‰È†¸j0€—Ã5F›â:W¦à*êMJž„žkŒšMLó:×ÁVK\aqÀ’'aò¡¹¸K6ªóxzO1/.r•3¢Vd4=U¬RnUN±ŽQäŠJ†túh9ÔNþNï5y•+¹d+,Y^ÖAª& £^½d»Ÿúç=!¥r%L9|,ûÁêW{4ïç£*€•ùÉ(¹/Šrž+äEQ®sI9t˜+3”CW¹Rntè8WòÔäðÀ±£C·¹VüèÐi.ñÔdþÀ>59 Wí"-W£ +m8|Eã=¯TçÃpÕ.*V?ÝŵΠç_sekÇù0\µ‹´\À£ruÇhVUkM<ˆ6«z‘WŽæ +T¿õcM«ÇùP\Ջ´\‘E®µºcu«ÇùP\Ջ´\+~x˜« N³¼_kbõ8Š«zQXIS=r k\~¬á*„ª¥&VŽóá¸*ñ¹&H.YøíÁ/–=æê&VŽóá¸*‰‚b—¸B;\…üÃb¼±_öÔM¬çÃqU.ªÅQ –+Èqó”\ÅUx?”¢‰;Ѧr•/ZU#¢èÀåu˕6q•ó!¹g‹M\a¹fF\™.ž?•‚ÈU¾(©•pÏ%;撚SŠã|H®òEiE²¥‡åšqå\Àá*]$+¡yâWÆá*_–˜8pµç.;ä*çÃr•/ŠÉø®tX®ˆÃUº(9í*ŸyçJ9\¥‹d±•é1Þ0™VZà’®òEâ´ÿuç¸â.¹ŠÇùÐ\勒Ú~¥ \ ‡«|Q%;.“é2Š+læÊ8\å‹Ê3ã`åWá8ž«rQ©Ãâ¨G®µ¾‰‡«|Q9v\­Ë¾!—ðŠK´3uÀOåª\t[œ,&ýpß i¢äpU/º+,EXàr§Üïò8½¾•k,9°²xfڗÙF—Û»çÏ\Ï\càš>Q®`œ\á3×3×3×3×3ŽköÌõÌÕ=—gε™ù Ï•RêËu·{‡™‰i.¥îÀ\Õãkå— Þ0§¨«Þ PïTyŠƒRÚÖs‰ZúF9O¿¸=U¯ËàZ—C;⺭ÏhÊ/óÊN›·˜U­\Ëòí†K*v”Ê/4LŽKüuò¨•kÞ¨¦Ö¢8À*镺 ®Y^šÝp…ª­2(Žƒ°”&S­Ëà +Ê–Ò Wö¸ñtV¬[|uíi·^Y—Á5)ݺ®ä¸Q(¯ +7-Hà)»BY—Ï•vÉv¬W'ïRpY§äsM]Õ2¿ú®å흤K.QyU' ,¼YS—Æå·O7ƒxÒWX\†¥?OÜP—Æ59>ލË$ž/ýNjq`i9I[U—Ä5=>ŽÍ“ úáJN?S` œ¤­ªKâ +ŠnfÆÕ’~xüsv¶)ó‚XŅ3Rúº$®íù¯ãcšwÊ5ÑýaËSH*nZêÇs‰Ã Ýáeg\¡.ç°§œ`†Ô<×êðyÛO^wƵך¸qRFÚº$®è C[K;ã:ìuž¯ÕÖ.“âQεuI\pÊ~õóθŽ!z­µû/~ ¾X_WÉUOìÜQ$‡ñºu_ÝqòA*­½ÍÑëëR¸Òƒ¬¶lÆÕ´¯W¬Wz/qRÏ¢ÕÖ¥pe‡·nِ«i6Ržã(MŽãÖº.é_ˆ>kæ2Ú_–ÚÌRQËjÑ×%påǼûmw\•,Z?®õd€¨KáÚ;æ[ð¢­2…êKætu)\{ǜî||—\ak¹TªdÓÆº8®½cNwõ͸Zó¾îBÕ¨ʇ¢®‹÷Ë;7oÿï·pÙÈg»¿¨OjÍ$GU—À•ì,p疻ç:µvZ ¥Ö¨º®½cÞ¹å>¸Ea¢4Mu \{Ǽsˆ\Øw‹¦ÍbÐT—À%½Ø¬/®Sâu;W¥.kï˜÷"ÙÈe’½}•̲습\Mu)\œd§õÓN¸ÊîZ;uu)\ÉðÓ½c4äŠqë‡-\Mu)\۞N¼ã‹ê:㚔lËoäÒÕ¥pÁþ0¬ßÆerîF”þ,u¾©.…+ٟ¬™˜s-›§_óâÁÀ×ðû8ž¹àZ=ÁÀ÷=>ËQrÁåJž`€hø½fC•¶—½Î ¿‡n¨ÒÖä%î{ ¤;\ÎRmR~/çP%Bq…£ 8ÚB ì÷Þºpˆ6ûB~O±k+ma› ¿WÚµ€ÃCqÁØÙêo‘ßoîXÀ‘â¸F÷}ôIk7&ÚrÎ1Cë°Œ¹:ç˜W­2yq΁‰V·wàœ [{Pü®9°ö°Pöê˜ËÚÕPúâØÌ2mWo@ùÇXÒÞX@=ÇXÔn\€2XÇf`«ö¨Pq¤cL´‹à„Ó-¡G´pŽÎ)¡Ï¶¸žuJèS„Naœz@逫ê”ÐGˆ¦²k]z0-@E—"ú°Ý}=rÉ ½ÄH7äX¡ŸF—.1AL0#!—C‚ar¬Ð{c‘C¿È•ŽGQ†9Zè‰3TÄ9Z胑Èá¬È…zG„Pv9ZèŽJ­ž®Gˆ˜}¸’‘DR­B°ßJ€/ôÁ(dcRæBýd²”¹K7þ(dcVá㎧€NDùðo¸NGŠô²@¸Âሐm„œ ˆ,f·ªÀ´Ê…D<3v¹rŠ ÎÜ^ËW4‚†> +„õBzôYkÈIÂ1ôC¿£r’p <ÀÚýTÁ%œ`øÄ; ïÐl…(Ó„c؆€ä`)~*¤XyàFØ}’Š"vÁ!' +ǀŒ²I´~tFÙCâ…C.rD„ÆQG‡\ä ,µq`¨ôe±§TzҊ4P/Né¥i@UÒÁVÛ$IӀ:43D„-Mµ\+w ‘¶ü9}€Í5Ãb,d—>!&4Cò g C\ў7ЭxC”ÄÐÈSœa 1!>nÈl€Q‡äœ¸h†¥™pLÿ“•„ú°!ç °Þg͂ªf³XÏI–)Ùû@Î`=»°ˆ<6€Õå=+‡¤·XC´gå`D­À™n÷súÈÎòHÏ1GÊ0 à Ò^¥~ÅðÀ|<=J½äWÂâòüjg1,¾)hãbv˜çÇwVóܨ•+ò¸ÿ¥ó÷‚5Œs.éñË9ʳ Þ§/¸ :l;Î.ÛÌñžIÕ2}hç2é°=ڃþ³¯CöçÎ ¹¨Ó0¥A^>ÔúMÞ/B“Ç•›režrv¾X,^=lÊýbq~ÚܘËF‡Y/mù.é ×Ü—™$Ò]8.÷:li…˹k_úÂqɱu’‹°kÓGA,è!¹òÐ%®µ=®t\݅æb­tt¤ñ±M®Ì®yn“Ë­Çmoà¹d8§qq—p —ҁÝï¥pÉÑX!ËKDo’¸·D|֍+‰R¹Ž ØD®A-‘’ûBåÒ;S¶Ÿ¨\ö¤¤92×`CŒ–öBçhˆË\à 1âÞ.ƒk!FÍ2àpQ҇Р6WïÚAO•ãqõ¬Œ @&—îJ¡ WŸ¢ÈJærõÆË$cs1Ò~zq\Æ\=MƘ' ¸úðÏ>÷ … W÷¦ÈÏÒ4âêÌ ùԌ«[U4I6äêÒAå@›ruf–ŒoÌEΡîhbbŸ«‹i‹aºº.û²h~n +W.íÚâ¥y‹ìpmlÑ^—MÖ¹;\¹¼p§³lrYê²óuîW.¯e𕭶Øäâ§V¨.íµÄ.—Az5"u{H..™]ª.¸8dç¯l·¡ .b^¼¿èà=ÝpmÊ.;Þ?¿éäöqíz­Å Ï]Ý»K®]·]/ÎÔýtùÐå}»æÚwÜö„Ãââl[΋ˇ‡ÎoÙ ×âO/’wòÅÛ?Š«BþQ\¯ß|7«77BþôéíR¼÷9d"ûõßÿïó×/âö§?ÿü—Ÿ¿}ÿúùû¯_¿‰ßþËoŸùGùߛO¹WWÛO¹ú°¯¯Þ½¹Þ~Êöê×Ùíï__½Y½Ym+¾þ¸¹Éëë÷û»ÄŸ¿ýíôéðõן~ûÃ÷o»z7ïÞ¼/|Яÿó·¯?ÿן¾oÚúñÃëÍÿ>þ“¸ýå‘nùM¤_¾}ùú¿_~Ú^Ë ÙÿbNô+endstream +endobj +210 0 obj +6321 +endobj +211 0 obj<>>>>>endobj +212 0 obj<>stream +xÚ+ä2T0BCc3JÎår +ár á +äHÉHendstream +endobj +213 0 obj +31 +endobj +214 0 obj<>>>>>endobj +215 0 obj<>stream +xÚmTMoâ0½ó+F=T²(”ãÒ/!µÝl“V{àb’IqëØ©í€Ø_¿3I +”­rqìç™÷ÞÌø£€¾¦CM -:ó¤óãvá ’Æá8˜Âd:†$ëFs‘b/y#ĐýÒ §ÁQÉZ:p&÷[aDVH-·Âë º +Jk62CG ©=Úc˜4¤Î-š5­À¯®LQÐïóãâ3@?5#"õ+Ä;籀e÷ìê9ŠÏ–=xAë8H èk˜“¶‹à’¹SŒÑ,¨µµWmÐn$n¿j$ÜpÒà’¯Là4÷^™€ÒX/V +‘ŒQbGZYß]/&`JdÍtèê.€…‡µp'Wˆ2Ü ¢¬vp#ÜâOŸ#k²*õ¼a…ñä=8/t&lv àŒªö¶ +¥Ô—‡Ð'y+GÀ~´q9Z½/|æhßQáR²†6úJj„º´Ü1.h£~ºX‡£ÐM¨ã4úƒ™¤Æ›Ô(*åâ&¹í/¢ˆŠ)øJ8ê0æO©Ä+ãkyðfVµø¨°¢¤@Å:‘sϼ¢¶é®r—Ýûèúžn¯Âp:[öÎ!¦& ótN¼"̕Iß ?Ìù”3ü,˘6‰sÙR¥ÌÜîʙ“”®*¹¨h[é×`‘êD?y¥S.„PÒï¾õGd™²ekìû~PVÖlKf‘q>N­,ýAºzCÖÂÎ¢èšÆ O–áQ˜úœ{å{®D’†”òª DY*™ŠæB¥3lš÷{Ƥžªžªª™€´rÞò/åÞ´ƒhr¸{|†»õú²›VÖ¢öj Q“ÿƒÑ²w—Mô\\¦\Ò¬=-"já!¥ýr“e<ŸÊ´Ñý#ÛZ[]û4\>´/ÃÑ«7¾3:¤Ýÿo’ÎïÎ?ÅÁ´yendstream +endobj +216 0 obj +698 +endobj +217 0 obj<>>>>>endobj +218 0 obj<>stream +xڝ’AOà †ïýßqZ íhçms.ñ°¸Y¼y!”u˜"Ð-úë…u‹Î¸Ã \€—ç}?>Þ#©2&n@㤺ñg¤(´Í5ï;¡<í„ÙI±¿¡o^›Bƒ2Î&ƒ’n¥«7nόVwRIë sÚXè˜êY ^¡MÔü5Hå4¸­€n[½—ª+¸“ZÙ»Á…]p™`ˆ1Iò`ôŠIç1FbXO ”êÃ:ÑýJÌ¿£Ìã.€¼ÌzÙÖÄT Ê:Ö¶ayÿ²ª®‚e§TÂÀº½€%S¬áA¯å”÷OÔøG¦)çº?@QyM ‚Æüyº þN(ªS{§çí]Ú 1ÂyhVÓp‡½¬,!½ø™h´Ž¾ †ºendstream +endobj +219 0 obj +307 +endobj +220 0 obj<>>>>>endobj +221 0 obj<>stream +xڝUMsÛ6½ëWìў‘}8Šul2É´‡ÔêXnsð"—"b`PŠþ}߂ÔG¨L2ÓÑE$w÷½}ûøw4¥ ~Sz7£ù‚òzô~=zóiIÓ%­KšMٜïîi]ÜLéŽV^ۨ햞!rM;ö;ÍûÛõW¤ÝÓt*iw]ÞÝü~’¥Ôu¥å•j"{j¼Ûé‚)K®Ï'WRåö+¦®®¥ç?ÿør…·wþ5dH¾Ío¨å‰ÏI+ï6†ëïÉuÁ þä<Xù@]È¢¹ͱJó£*7T©@Qۖ‹Äõeöv‘ѳ5ú•é³Î½ ®Œò–þѶpûþò³ÊŸÆ]ƒRÅ:© ^Óy6^!*[(_°/UΒ: ´X¼*å]Û4Î÷4StÈè7È·MRgÚ¨SÏ;íÚ`¤vJ…–Æ3€~Ïþ• #ÊGÑÿ>kÑqÀè<'€Ú…˜j+Ã6f}±Ùâ4ŒÀ×É=i2Úò‰6½ÜDþÉYsx¹•~W¨ý”{ÝÄ« !·õª©t^nÇéy¯c5ÔÑÕL¹Sßt§ÇrxnÚªwb¢¨l!¯ì–ÅŠ'<)\j“Ä®U„¸¿»=ôc”ÉU‹öXåCܝòrH%) Ú5ìՅ „\Ô§B—%{‰è„T•|‹–ÇTÖ¸æbÔÔÂëp_(ȁ¯Â¢šçšáÁÖykbFëJEHUo0“NËmt­#^ì`¤Z* 0ó6DˆÜ£Š]·GÄÞø’£Do•ăvŒ@f°kj›K+§H×,`ªŸc±Î‡ç ½â˜Ñ[é@,ÍXùl{FV¬$° †cë-†ñ´ÁÁW—’„Kß}‡l™‹ ÃBª¬ñj  + Å~kW´Fyqª$œO @õ¶#@àäÎ&Ò'6(¹,ù„+ß\zž>>>>>endobj +224 0 obj<>stream +xڍWÁRÜ8½ó}$UŒa äBX HílÆ©½pÑÈ2£Œ-9’ŒwòõûZ²=ŒC¨­Pa<’ZÝï½~m~Ìéÿæôþœd}p•ß| ùÙ%å%ÖÎ/.²sʋÃ|­(WrmleŸ¶ïòïØxFóyÚ6{ÿ!mûôm±$íi%¼*¨m¬!aHÕÊ=ióDw&(gT „)„+HŠªÂ΀ðãâÂixûÂÙ`¥­ŽÈ:º[,2þÖñ•2œ®ž¿ÏNùjU¯œˆµÚRa*ãɖÔp,åE1~öÊ=ãW-L[ +Z§œ?Š;:]UˆM¾mëB +ƹõo /Z:ëm&7ÿ£Ma;\×('bâ~냪³~ßéyvÆû8ùB•Ú(ObAÓWI%ªl†ÚQd§ ~#QዋôÝ®ü^=¶ Ú¢ÜJoÕªÐb’ ×?Õ9åmÕòÖT¬·|cXgôÀAà%憜€ g-A"`iy©²Ìٖ)± ãuÁN®îsô´nMáTáù\XÛÖ#…ÈP­+Æ£ی¾™XƒEL÷2‡µíîJɈ +™÷ ᠔ÊûɭҚàX7¢E(*Å®ne¤Û6é¹VR·rMµu _IˆbÇŀ¶*t°øÁ%¶ +¥° ×ÈÝn!YÎBʝ0žÓßWømž/ލ[kä0|lèˆR§V½nñ8•þK +2Ê×8ŠX’¼Ö¹¥g­:t†lk ñH2Àç֓6C¾æ•ºÆ†i=Àøõjíbv+‡ •›bT>ë"Ê^Úº©TPLåñ<;7`[‡‘»cW€ANȌɶ »IZ£“<¨DF×úIùðZ¨üaùB£ˆg¡+±ª¢²e· f!vœ-'÷rµYrǗ6ÊþѸGïþÖÚ!Ìa?þaF÷Ñ07°D€R'_Ôý£…¹µõŠm1—¬'`&’ImAx¯Ÿ ¶e‰ðÙVÂÁ×<Î&4[ßFUôø®Oƒ$6ðZ<«Ñ¹ÖJ-¸ÐN‡5˶žzw'›!û%GëG{HÛh՛8®´N‡í[<|ªp¥òoϱÑcР•’¡§œFOÛÛNjB‚|-ú@„ ¾¸-v;Œ‚„+÷l©ŸŽ™‡ÖÔ&nŽqÞªöFWœïo«íדi°.|ê{Ñ4ÕÐ"H,L#ÌD˜YÄ¢ŒîͤÙ6ÌÍ R%ϕ,Íñ4®vE3²Sj“½D b&¬OU&'6K’Ñk.՞ÑÒÖÃþØß/ëSÂæB—%‚áædm>õb½>¤¢81¦gsFñòßæûgÔK!j͂4~㳩®„ܨÔH/„0f=fkû áºfù FÑmžÑ3Þ¾ÈôRé!Kô"ˆAEVoZòÌžÃ쓬k®<âzD·‹ÙŸǧÃãâúføÈ€žoñ9{êqvWhWZ æ¥tº ñìîú*<r¿Ád·ü–†$¿Þ-ð!R9Ðþ"6Ä8“‹“(P¥•µhz1ôo6;}ºtóÿ‚n•è`ߊ`ìÐU±Ðˆ¨(šI‚i|sÂÄî¬Û`8‹ø|¯ÂµvPØ$ÿÇÏM³´¸/<¾;¢ej™/€…ºÂKÙ&E~Àëeê<¬_ UC©ã›To—½ç§gˆ~~y™làúëǛúŠE.ñžÛqK~,jm´Gc0@_ðÖ,*Ž3KÇg§'|úŒ¿;;¹Ìø¯ŠWÿbøœü}ðmPendstream +endobj +225 0 obj +1372 +endobj +226 0 obj<>>>>>endobj +227 0 obj<>stream +xڅUMsÓ0½çW,¹PfÓ$%mo|` + Ã¥U–kQY2’ŒÉ¿ç­d‡4…azh-íîÛ}ï­úc² cü,ètI«5Éfòr3yúæœϊ3ÚT¸[ŸžkڔG—^Û¨<]xýSùðdó‘'´Xä¸ùêü~\™ãH[zõõòФ³A‡H®"gÿjœWTi9,´JêJKŠŽµ¹H‘Sµ•¦+UÀEMkÔxÏMz±*– !©ržÞªÞ¨ç—BÞ _Ò”¯" [҅ +wü÷P%ô­Ö¨k†¾©tÀ³.Ò­²Ê‹ˆŽÛ¨aÈu±íâ4c–ºª”WvW–Ê„é˜ë•ª 1•«]O[ב–z¯q‚/O®·»ô‘Bî8ß:N=€Žµjp ޘ¬" ³/!Ks‘ŸT읿ÓööêeLiDhÛYP£È8‰ñÃ6D +h'ºè5ŽÍ–B³’zkrˆ÷Cè.ßfø‚6àù`Tp}H„` b×&› h8K¤ÜsGê± ƒnc_a/š³–Ð&´Îp²T€;h~äSã0Ä»ô‰5·é’g¥ì<–ɾ`0Ÿ§›qÏ+þ؀%¾]R*ðÉ=ìá뻉QP©´(døXLýÂ…L3w8‰3gÌ”k: ”Q2¦€1ñf;,Ùö!z_kYtcfõúH·M‡üçLÞbÊdÞ;ZN‹ë'C¹å:-m­0Us?5¯nvÜzpܑÆk‰½>>>>>endobj +230 0 obj<>stream +xÚ-‹A‚0D÷=Å,uQäWnQdg‚RÐHIj¤Äߪ×ת™Ừ¼» äŸÖeêe[-VíDÐ#H™B¥rèaќêVCbwîzôó_†-êarޅÈ&Îp0þanK}ò'Ë¿]&VP™UøîŽ–Ѱ{ZéÝkqoµ-']endstream +endobj +231 0 obj +131 +endobj +232 0 obj<>>>/Annots 17 0 R>>endobj +233 0 obj<>stream +xڍUÛrÚ0}ç+ö­é ›;y iÈÐi34éeú"lÔX’#ÉaøûîJ†8iÒv4±Ù=:g÷ìæ¡•@ŒŸÆ=è •­ÙºÕO!™Â:‡d<ކ0`õ ³J™P[`*ƒ…²Ž=^Þ-Wï׿0uIB©Ûéâȧ¯wÂBºc¥ãìNï-àNÆ@=¢ˆàv.µ”ZÁÝÍâ,PŽîY¬ã2‚E]3ü˜ãI…«u+ŽbTEGBÇí5ô{ýh +ýdŠ\$*D½ú©€iŽ1¤&ºŠ™dÂ:#6•È"7ZV(ö|V8ކÒè”óŒTЯ–§>Ü Wð¬ oói0@>ãa4iðy%¾!aO°´‹oF`ü(‰Æ/ô>O1Ûc‰ŽUh4—Á,”äC£$$í $®A΢à4&ÜNú +îJW&åàúü>ócè H ¦Þò‡J.¹rö¹Ùb?¢ ïºz‡RÔ¦àâfµ€KHµ,EÆ;ÙÍ7[…6B;Ö¶º° œÅ$úJ–…à¶"Ñ»·b«|³½x´¸ç˜™J9ÀÛU—Ü0ï×Ü&§óGºþh!ô379Cñ…Ø*.ù_jë@ç>,†Xÿ~ÃÒ{®2ûâ^[•Ä1ƒ½p»€‹ƒUÑ0VѪT†×~©ÑVçîgo8‚¯Be8~ôwT#öF¡;s8 +ɶžÂsKä·J(Ü.–m*ީؔöqyu݆å ëÅ|ÞöI?>-fµJ¬gtÚ !{(¡/$EWŽà,š"¨3<«R¼&¯”Ÿ1VwˆàŠÙÚ(w{ÚK£1 +;(¿H¤0e…²¾¸8­ŒA;öÆ"¨­£," ̝·Å0 žÄMyBøËˆG1LȺz ¹Ó?¼=0 FÏ]yÞíâq”g÷Ú·[V›î‰ÔëӗLúxM|¤ÕXƁÀiHêõ)Ù=§•¬¶(³^a‡¦dô¢ÙÜë›;؝瀕dJc¤E/:…@ ŠIQ#P¼t+{d¢`²nÓÕ´;ŸÉÓO¸D†ÿûOh0‰qãø2Œëö|iýíû=endstream +endobj +234 0 obj +831 +endobj +235 0 obj<>>>/Annots 22 0 R>>endobj +236 0 obj<>stream +xڝU]sÓ:}ϯØa†¹a¦–í´ 3÷¡´M JiÍË^[N¶d©!ÿž]9n\ÓޓŒ[ûuέ¾bˆðÃñ˜¾Y5x›.ÓAÄ"|OKLËíî²Æ ­ÄI̒ÝS wäÔó0K§LØ҂B“אæÃ®߄!®l©Óf®Ý"\]¯Ò¯(Ñ.J|rŠ©"ò%ƒpzqL1ƒ¦ˆàxÂÆ´›®ä:s•P–[©È +m*n­ÈÁÕR-Á¢Ñ»ôÃüâã9Ôº°nƒY[í@ ´³*þM@¶âj)j¿‘qKaÉÛ‰¹ X>ìǂÂèêMShýƒmý¿Ñ¤áw2BPÍÓ³ü©±'fe=«›Í† ^oë Ët®lU"!ÏÐz:Æ Z'ДHÄúìÁñ¨!ö\WkY{çŸoî7!ÚóO›È2Rvuý¸³:Óª >éW.²Cô»…,ю«‰s&C¶u.¨YD·„`EÅ íú¶É;ì÷Àn×âùäÓÃK`á>úåuzyÛ¹>R—(¸+-HU[^–È6²,aí¼8|{-Hå_¶5Q‡¡«ÍãDCÏDßìžÿb–K#2«Dò0uúlV2[õøñµé{a6FZY¶ ~ÈÚR/×F*ÿ¥Raþ~DÏþéÓØ¸ÒøÞôr–:kˆA)<?Öûÿ£M¯Éë/»×ý—È ©„ò`GñÐSy7×WGðþæ×t6ù^ü7Ÿ½…R. ÷\`ÛҁS‚à·ªkeñ€üË…(±†rû|‡&_¨TYérñ;jð¸ä¢gúåµììP;»êfLõýϧ󳫻ßH4¿xÒR¨{i´¢Ù +(LÉx€{GEáyÄŒSªQÖ®?ÐU¬sAS/¼fa­+¶Êß¾xÚ~W6:Ì8teÃ;(“ +Ç]+~/öìb¬à««íŸNÃʌL.œ,sßχ˪?­£ý ž5òlï¹»Ë³»wÀÎö߀iu@%»ŒI‚nãQÌ&dq{6M!hÆI["œå•T8™ ǞÕð+ÇK +Ä£t^ü]•л“8a§ÍÝu+¾;ì4é²Þ]­Ÿ?´Nendstream +endobj +237 0 obj +858 +endobj +238 0 obj<>>>>>endobj +239 0 obj<>stream +xڍTIo1¾ó+>EjE¤0¬aɍlUM[2U.¹xÆp3ØÄ dþ}¼Ì jUqñð–oy~~kõÑs¿>& ÇÈ×­ë´Õ½Ÿ¡?LH OûþHÛ +K˜Ó,̎(vžþqé#ôû1¹3'#ŸüCä •´X‘-ڐ²d4ëº8Äs"à‚Ê„ÐÍïŸO „­¥@VÁT‡xQz˜ENŽh'ò£mr°Ÿ¶¿ kµêꌋnn7šâ+îÓ»ElàT]&Sß¡ã[ g‘êC$ç¥\sAT…[®â™5\ŠO]áØ>3x¹UŠ SV û*×+HÉb;zÐN;7Î(¤Zƒ7«Æ â@…rlI +¾1:‰$.kž~ãôó|ñøðøíꯣ8Ð8íxYBn™Ú)nÂØ»cè36Š‹pЕ6là¡cbï¦8óS¥¼(xnKَìÝäš9Ôc @û9{A‚ùéK,%2’¿úc@–%=½ˆfSì`û+r‚¶jظŽrË©«þՖÖ.×G˜(”\׌œRrº¹þ7·& ?•8lw,øÿŒ¡”Ë¥ûpÃ'JJƒ—6•áÖ œi{®;’‚ i—«—ó͝èõ4t±š© (+Â_G©ï]ùïJÂæ$¶ƒõi®Ö‘ óÂ0å½z!^6AÁv¨˜î +‰7Ët¼óŸ= +þd‡oƒRxò£¶t}›œð@0zjƒ5ÒmÏ]yUoÈ´&ÙŒ\Òp2‰;p»˜ß§èD +Íã…9]sáW“©4¾aI&Ë;“Aï_/ßhÚKf)3ÿ}—¶~µ>ùq°endstream +endobj +240 0 obj +640 +endobj +241 0 obj<>>>>>endobj +242 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS042Ñ3R072PIÑp rt QÐUp VÎO+)O,JUpLÉÍÌË,.)J,É/*VðMÌ+MÌÑ Éâ҅hօê64 [ÅÀA¥yy™yé +%©pÓ@J\C¸¹§ü)Nendstream +endobj +243 0 obj +132 +endobj +244 0 obj<>>>>>endobj +245 0 obj<>stream +xڍUaoÚ0ýί8UšÖIHÈ ìÛV±Ó:ёî»›â6±SŸâßïlǰ†n*QûÝ{÷îûy`±•å–5É%–-¢@Øê=X Œó!ԚËÍaLqà¢V@ã¨àÙ!hÝÀZQiü8ºr„b[D2UÃx-\뺦Š/Ņ»³x7NºÃËúr e¨¬ªô'½f£MMêѽԠÇK´†YI²-Ã'„Ñ5X¢ë +%•T·ArÒé(srÖR•ÿ+ˆe’{°ö–À¯ @ª‡Î¤H5iÝõJ—Ì +ä‹=ï{Ü¢Wò¾ÏÃ¥¥ÕæÐÓ*q0zCjmBgÔ¯Vä¿|zàþ¼m^½‰çWÿ5õϜ»Î݈n|”Ü·.¬ø÷ùûôQqv4Óë»ÕÚÏeÝT0í«~½‘“½´[»Hš Ѝ‹Â§Xbá,ܸm;ÚÝMݗw§1ŽINšÎ"8%dN½ÐõN|¿úœLòç,!ÙõðÓ,¹ØÉRôÑÇcHV}ê}æ†÷p§3Xþ(–?{ïBv•SÝ£ÿ놕´Ü÷Âî…6«€^¿KdåŽUôÔ0ÏX÷&›V>Íâ ^xrb5•)¢„¶qãN³yG†C +ûƒ´ô¹=4[¡0>>>>>endobj +248 0 obj<>stream +xÚ­VßoÚ0~ç¯8í‰jãGQŠ4mtݤI«Äª=´}0±S¼9vÛEì¯ß]ⴐ֍  —»ï»ï~Ø?ZôñÁpLß$k/Z½#ˆ"X¤hOFÝ ,x{±p²ø†Æq0¶¹¸—‰¨Öm`ŝτv`s‘ÈT + }«—áêËG0¤R Í2)þ!s^HíDÑÂIRf-õ]ð²´ÄéC'vÄÇú<7…¤Kfe‚?­cJ1'“»«y<ÝeYvãîˆb‹i1z5ŸR¿ð›í1Ñí8±Ð9*Æ»Ü;p¦LªV€—ùvw‰t¶#¬œË§½Þµ·¢ ¬iά]›‚¿½]ëèÑõ”ò½íÂ_$Mª2ÿ—ÿšÏÇù¼.•Aïëâ5š„0›-’³ù ¯Å§Ì+g b<Œi¤rŽÖÙô~xáÊáÓüâ!‡2Ø!p¢¬”PÓÿÖuD …B£b€KÖÀ¿~crêu{{ “*ò§* šÅL˜†¥¦74qn{|›#+(gÙå¦zå-Ü´_ޜ@²BS‚¥˜Øþà +zð_2Ï_WÖA OñšŒ: WmrzçaÑÔ îG‘Î6QN©É'p´Ï–4 +)pæpaŒ(ƒt›&ˆ¸z™ òB¥DòÅýëø†ó=áÑrttmô…XøBÛfl”)=ØéÙò«ìøá/ϱó¾JÍÍÚbÿí,ð–h’G<»<Ÿ5©[ãtµI¾ ·µ¡Â¾=jGV|fy—@h3Î$FýýÖmŒåö +>‹úý2ÉÎéÓ;ëŽ÷œýyΟyðÏQŽ8)dî`Ò¹¶|@§4­2BÆj‡•öñ6pY®•jñ`½¬OV öÌB&¸d`åOñ +„KºXεDUµqåfºgR±%ÂÈ6ƃɤ 8 W^ØZ»ýާ ã™üm “eLóÐgPÑ(çc8¨Ôº*‹;|ü1éBâÙXŸý§D~&êlÞ2¥ à P_ÀO7ÒLÓ )¤ /`•ò”IX¸=aöÄ$@Dƒf5žL*‰/¾Ì>,p˜é6q˜5inWƒ9VÊ3U¶NåŽÔ'ïh@‡£~wåƒç$Ѻ4\¦úT*åy¿h}ný•÷4endstream +endobj +249 0 obj +883 +endobj +250 0 obj<>>>>>endobj +251 0 obj<>stream +xÚÅVQoÛ6~÷¯8š•dɎl÷­­ Ã6x‰Š>Óâ)a*‘*IÙñ¿ß‘’°ª.ñ-XŒs`Ѝò¶g #Äíi¼ü±5š/"ÅGí‚s-vä—+)‰oän˚iV–XB­´%E5’“É_B6pP ìUSr +…?&ƒ>Ïió]D$F4Љ-N÷húæCV_8) ."Q0wA®±R;:>lZ0Ì·ØOd)ÐÎÈѹ?~ÚÜøAh@7Òҟ²ã°;Á˜Ù\U“|X/¯R/?P/§Q‹—‹N»¸/øX2cðiØ<>ĒÚAv«US;¼DÉt¥!Ù²£rèÎ]”x!|¾CçC¢Ò$MÉMO Ü«­×yëøÖCKs#‘ïEYÂÉGåH§à°=xÓBhcíe¸-ñÈ·pÜ2Ûîv»%i‹H6®«ÿxUÔgàf΂¼WŠùu­5²9({asœM)îsÍñ” +@È52׆XcUŬÈIo \¡‘o,µ?a¨«¸¥æ¾!ªIB?«ü^ŠË°ôi‡ŒÚ ZëZ–KxkJÛ·¯çº—¡¶é\xçÒËTuåõjå¯!Bjñs!F.VÇ{û¤Ä¦K‚ô9‰=ÚúÄ-,_¿c,Ã1‡Ó}–iϟƒíƪº~Ùý󘔮;=ʓ¶raNYvÜó.%ïh(Ÿãi¾6Ø uOîáaéÒ/ßËéVȨÍF„®}«øžiÙs9O䫤 ½¾~•AÐ^Ç7ª°{zªÂ{'%ª{ÍèUjào&æ_WAœÌÝm¶H|€OîD\Lóž Xûwާd¾˜÷ÙÄ37q™MþüKŽ0Àendstream +endobj +252 0 obj +915 +endobj +253 0 obj<>>>>>endobj +254 0 obj<>stream +xÚ­TMoÚ@½ó+æR•HÁØ@ ôF[r¨Ô* î-—µ=®­wÉîÄ¿ïŒ×|¹½Tª@Bx>ޛ7óü>H ¦OÓ9ózð9ŒŸbXFHK~6\@Z ?À¸qvœI=.¤™B¸K·”;9å&ñ$šS3JÞY©=ڐpi¶ˆCÖ?ÒõkÏ I8:Jóh£é’ºPÎsèáÀWƒ°nµ8‚óR)yŽ;[“9(…Xê_÷5F¤ÒÜ7B©c‚ÐG(¥B ¥*jGnÏlbb1e²ÅТóÂz,"H+逾Ã²Q K®nF"£ÊFç^í¨yGӀF¢éeà äÆZÌ}Weh„:‚Ñxo°!̾‡Îã€DÉ0אÄuâmØÑ|»‹‚žKHHgR4nŜq¿U« Ó2|Å-ñá­Èð­#pYF|ÙCZ6wÁaPý¶bØvî%Ú¨Ÿ˜›º¦dwÚ†ÌnEçuòÐZÔ4g7ú=%º“ߣ:~êØü¢àIÐäêx•ÌÆfïv— úýÇÓ%¨‡¿t“ü€o$—¬hÓ^Fföxâ|¹Ð!yÃìvgˆóæ5®ô¥ ¼)Ê®µçÛ üÞU^mçP‘…@z²’–®B¶©qÌZ‰=R/ÔáÂÿ´ïöPQœ½R7Ž–Ö=ÀZ0A-tŽ`ôøhü + ) ‘{!Uûn"Û– g$@ˆ0¤)À”­3;»>>>>>endobj +257 0 obj<>stream +xڅT]Ú0|çW¬NªJ88ú֞8µ½Ò’û&qˆÛÄvm”ß];É݅û2agvg<›£fø‰a=‡Å +Òjô5Mï6o É!^/`µ^B’—0Ò y„}c¯à“ìÈ+.ݧä–Ç›n²XÎ"M +a!-˜v܀-ÔÙ~A£jH™„TÉ\kÃÁnv{°Üœ¸‰+sÝï I7ó¶`òH£xLËÀœPîDÉíópEÀ/e *÷°Ð¥ïÐ9¡á4¥J™ãé«ã¬eOOÌLÓZÛ)៷C& O2M?eʽւ8T,ãÀ¨gŠќfJI ÊWÀ|_.9öÆG†[njš‡O2#„C෇Xq” õ¨mgŽ­µ.rÙÔí­¯²HQd‹ž«Ï]ن`9e¥§ècúñ¢iËÑO¾½O¶¿ !‚îJœò $3 úf‡Ú_…ˆ/Kdøé_¹ !…‹²W/ÎÂ'Yu.õˆþ]Ô\²sÝÚ¯äÀTêtÂ?•™ôîënw¬ß·²ðJ+Cv¼å{e*ô§ ±ÐµÃ܆t <ºž%D{)®ʏà{N ü˜A)þúXv¥E~t•jÊr ½‹-τ{oü)‹^Z!š:jÉç«àÌÞç “ŸÎ\—pÉÏOÔ>ÎÇ$†ž»¾ŽimÞn5hn*a-ÆÌ¶Ù¾ybð<üþ;o¹^âõͨ8¾¦Ûdôkô9åšõendstream +endobj +258 0 obj +587 +endobj +259 0 obj<>>>>>endobj +260 0 obj<>stream +xÚ¥VÛrÛ6}×Wl2‘§/’BÉy‹kš™4ã&ì›_`´P“ €fô÷ÝH]ÙS·#ÍH{9çì‚ORHð“Â"£oQO®óI¼Ià*šC^ÒZ¶^AΧù_“fiJo ~äÒ-ƛù`½\àoBq©u|ÏLìê&í]fËhŒàæk~ó¶gi²>ø.¶µæÀ~5Ý7±NÿS€x³r_b”uŠû³ÅU”‘M¾ +#2õ ÀmTR (´rL*©üÚ x˜æ¢n>Isêw +ˆ(œ| Õ¹cEÛX¡ër|Òioh³Ã'æ`§Û·ObÀ Åt #˜üý¨fäiorÂTŸëÿdj áryp#«ªÝ%a3Ηb…y˜Ý:‚” ”ÒX‡ûˆ”V K\”–hœ0Qté; ¡gIq¾ +×ió@ùÐFNKNh.JÖVŽØ<œ!|üóöûf%­ÊB© «>]ª-&Y²B`] +Õf‹tDÑÝÔ#à˜âÌpø|{ë-ï."øÀkT•u}*e«úH̐òj‰Ô’*]°ê$•Nº­Ï›5Ñ‘¨‚QÜ«Q¬FÅ¡aÖbÊ<êæY@ñséuÅ1Ú£ð¡(*°k²ôŒ»ì©½¥¯>d%¸tç„?¡|HÝ1!?¯óRVâ@ñ"¨ŒH›Òn¦þÙþ¸ m# +YJ䊪|µÄ4‘G\µJ#¸Vr´?ËÜM‘ë» B +¦Fè³Êjԓk› ­“˜ä÷·<ßû['è-¹pèX”ŒòÞgщûÃÆ(t'ªê%X¿ø^ì¹ÏAÊ£QÉ87¤"¯?¬ðÄÜâÃäÎ*év}ž>*êEn#:†Ž)Ï+2©»“†ÑªÚ…öSÝ7T͊-÷žAÂý_Ò ¤óU”à'}ß7þÑX¤³¨R¡9ãôypÏ·ì¾ÔqòbS±mïñï%֋=n[*f»€ %5Lµ#ÞFÊRÚ„·v|æ—dwmtgÅk{ú¹SÇò£ëÙè +§âVÛÐMx‰ÔZI¼>qXQsQk'G%u8u÷n#HoÝÚ_½£²Ç- [Ý ê½A9ý aý|¼ïÀuŸo:_¢³l•E rùéۇM³Ðáßué:ùG÷6~gªeUx!òÇg«¹¿ӌ—É*z.dºÖµaøª°Á™êÂM>ùcò3Rò‚endstream +endobj +261 0 obj +955 +endobj +262 0 obj<>>>>>endobj +263 0 obj<>stream +xÚ­VQoÛ8 ~ϯàc4Nì¤I:¤ÛЏ[s« 쀾Ȳ¼h³%O’›åß)Ùiífz7“"?’ßGùû(†~bX%0_¯F—éhzuq iA–ëE´†4¼Iß¿~•~Eó¢5Ï`’,£YÿÑ Tu`…·ÖèA•+áöÚ|‹€ æ¢`Mé(b;f‘v>9?ž|‡ð÷;Éw°—Ø`Bu„$U¡MŜÄî;=€Dã°M†€lÛò' 9rà× ¹.üô˜ØjƇíäî3ij(™C$¬M&…)í YœA¼<m` ™töìˆØw‚ݏé¸TP0îN œ NNÔTâý«ÐJÑõ3ÖFg¥¨€Õµ`ÆÏ0PÈÂÇoÇÑì‘x礎Žx¡Ôm‹ðVðÆHwø)÷ÞÞmo)éƒÌ‘E×[߇\WLª‰"AdÌbjÆ9͚kåŒ.½Ó%³’k'ÊI憤é¶=¤Í!0¼Ðe©÷^&V4ùƒ·×’¨m[ÙÁ«Å÷Ò +ƒêiIÈ[xÉ#yxŸ,Wò¦,¯ä³¢&ÒúøwŸ®3ýšCZQ#Gȓ\‰éƒIÒ8 …ëªÂ‰uÂá}î*;‰ˆ—ÌZaÿ¦v®6ä |ÕÙoAAq^˜ºþ;› L%:¢oè¶ÁP†$sì®ïÂèêÔ¥6m¬™Ú:NySÛi®ùiaÇ[:w4üOⲍ1ºA2y4ò@hGg‹R´ÜȌ$"PYý{$(e 1 RÈ/ ÌÅë˾î0^„ýAk®óîÇôç=1½éY7¸•ÒC-ÂÞzfzK̄[Ó÷Œ½?7&Çzß u8ÛЪèé1\Ñ ÐÖO@¾Á'+Üݳ(îCŸvØß„j×më×Ēå|… Ÿ6W)rÏ/š[]¸=1dӊ{¦ñÆø‹©†ùü“8YÉVx½_Fº ÅŠÞª¼!^у÷éèïÑ¿ÀÛ×endstream +endobj +264 0 obj +922 +endobj +265 0 obj<>>>>>endobj +266 0 obj<>stream +xÚ­–Ks›0Çïþ{L3† ñ0ä–&M§3}¤‰{ëE¹¡ÉA"n¾}W\ccw:6Ì>ôÛÕ_BÏ~ø‘ù¦åäí|rq›ñ] +óÚ¢˜˜ÛììK•ñêÍüÚ ÄZ?q#c?r°F¯5œA–W<Õù ‡Œ/rÁèÇæžÕ…–¦\)H¥Ð•,\0Y²(ä*?á…5°Šƒª—KYiž]ÚÒv#¬C#70Pßi4¤‚+“szÃÅë6 cmPñgL+XT²V ^•æ¥jF]ÿò¥ÞN³V&‡"ǰ r¬2scpl£³³!”u¯Ü~‘N/r‘&ç´©æh‘R¯¶Òh±|0cŸÕ±óðïâ(k…jX.9«B嶝â£L™Î¥8Ö¶M5;>µHEVóáªA-yš/r#OÀjÁJ>…wÀ²¬BMO!¸^Éê {Ì4äʨJ®°Í­ìµlƒâÕ ¯.»ñˎËs=寄´†¢­ÄÎÞî3}–‚ﳝ»™,Y.ÜT–û|F¸˜²G¸ !ÜóCÆQ£ðévQ–ã=KwãêKÅ1SÕ)é°lìf–ÖeYÌ<˜‚’(þBçËâD ⶉkõ‡Z¡¤PKº:m™ý¨ËÛUÙªÉ̛ڐ§²ûîÖà]™‡R7 °'þë7÷&SÉÔS«á° ~d6.ß³»³MHâzæAež¾›O<×ÃwÓúçþ=±ë }ì,I"sïaØÀ‡gÞaÏ»yÉuu„(ÎVƒä5DIdy0•ùáñ}ŒÍÓzïð +’Ø != +‚{éŽf:Gs´ÞC$I̸´O‘Ð1$ñ›ßq÷ Å,F]àÈ®ëöHÚÿf#G3´Þƒ alWqÜ# a8ª!=A©÷ ‡[}’h¤…9‚‚¯½ñ"í¼QHlEJƒA”ç ¡'(µó‚Iøt/ ^‡YŒªG£´Î;$Ô6åôsÃÿ<èÄÝ>Kĉf3»€nî¯nçxä»þv÷r¡Wæ¥s••¹ÀS^Å´¬|b¢fÍéÁ±áΌڅßh?À•Øþ®OnØÕ¯“?í9"bendstream +endobj +267 0 obj +841 +endobj +268 0 obj<>>>>>endobj +269 0 obj<>stream +xÚ­–]o›0†ïó+Îe[ +†ð±»´]§JÛÔµ©´‹Þx`V°†Vý÷;Ʀ Iˆ6EDÀyíóØ~±ÏŸ™ þ\ x$åì|9;»ŠÁõlË cAäªÛôè’ñ×ãåo ûàº:hy±¨àrÅ@ÑAš×,iòg²bIžåL…• §%;…ë iZ3)OAÔÀYó"ê'hV´¥E!^X +4IPÀvÅêgVêÓǚ‡céQ¤G*„°ŠB²Z”°(Š-‘-¡;%͹ˆr‹d¿Bx¿ŠsnŸìˆM‰OÕà5MuV–“…¥½v ía©õéݳÓ*¸ì5ƒ¤-˶ êÅ)HøÐäUq˜ë$$”Ã/­D¡}:CõvÊÐqoݪ’ý@Þ)mqüY?È÷Ô\4È,øÀïח·ª§’Ê'cÛ¹iázáÄ8¶¯2êÝÈǗŽzaZ©·Ÿ—3Çvðó}û»ý~d;à»»q€÷ÄÁ[œ¿»1ñý5õ| îö~s|§r:ž8Ð4ؑúí¦ñbõ?•¦WoÐ ƒy8˜×P¸$šÄ†Øz2‡Qržö-rÄdÇ<Ä֓9Œz”Ã÷´Mlې˜ç ^ˆ-'3õ(1G4 óù¤¹pÜګG9¯[ƒ`àì!qx€I{õ‰ˆ6)ñGQ:œ=0ap€S{õ(L@´S=²¯=8óàÃöê õè©9¸Z([Ù­*FkȹÌS†Ûè‡¾Š¤Ûj·öbëÈzqcyf~m³Z¾Vìg¼Í:vʲœã–¯ª”• 2 ØŠñ&×°êªXGOiN‚ÄôCÔ®l‘@á$?æï‹”õÜ–.Sȕh‹T{&ž}GÈFñ°³އy×뱤çTæÉfÖîõ”Ä­Ìùc7!÷߯BE¥ÄK:žÂc-Ú +²¼`²[+KÏÁ?-ÁÿtNÔÒÄG® ðMõr»¸Zâ\ÜßÜÁÈšU°,Ò2ç¹ljڈZÂ7Ê[ڕ›–nn…ÄY¯}üðíwcóAþ˜ý­¦õÞendstream +endobj +270 0 obj +816 +endobj +271 0 obj<>>>>>endobj +272 0 obj<>stream +xÚµVÛrÛ6}×WlõdOMF¤YÎd:ã8v“™8Mkå¡3zIHD  +JÑßwM‰””4ÛcËÀb÷œ³àS/~'0ÓOVö^M{Ïî® Æ)Lç¸7ž$ô1?»®\q#™µçÓÐfI,¢áU<&‹iÁ!l¶›ÇA. ϜXqÈù\(na]0’¯¸=oûyŬÈÚ>X–qkAX0üS…óÁ$ۚ¤„¥ãxDðféø²ƒOiµ)uÕÁÁ{ ÑsåDƜР+l¡+™Ã#‡%7smJžÃì ñ³Jºxv¾… *ŽüÑrÓ z +&Eî*Vr`*‡%ê·Ö&ßeÿ¯`ëxùá.üªÑ˜–•u¨…ÔjNû½¾ÝØ>E¹Œ'  …ÑÕ…r:̘"³‚©§À‚Žw ' þŽ- ~ݒ"Ú ~Hƒ^¸‹:ʲÆÚâLÍâ±½G££¬=Ý»õ;ûÎCfË%g„²"GÂm7ït(ýÓ`öF4L¬t¾<4¾¬Xîl£4Ɏéì˯Ê÷~o{ƒfV|;ªŸ.ëÑÎ8-ê×4T#)ËK¡„u&L¾ 0Ê›ã˜æjO¼Sýێä6KÃ[·U»nŠíµ{s$m”xŽmôÄÒ'éNHw8‡™;~)Ý|üðK£W˜ ‹©¸{=2¢2§ó‰(PGãÿŽú¯ä4 „- Q¦ÕŠçÍ=D†þ„rìQúrÃðô§Å‰³¬vÜÄp !¥(yL‚tz”°2& ã€*\¢^¼šßáDIE”Ìà⊠顇úہL§­ÏÛ©ú;†ûtùg[ßÿý_¥×ªa`c¸%%qÃGÁ=ë˜ÁrY WøEJjùdœÅ-rs-ñ®³W“;¥6»raè…¾àM%):ðϬ\J¼lT¹ãŸÝ³Â•òPV‚WQ''f_Ô篂¬4Åk€5Þħ¢v õ/˜Íö,àéë©ggƒ‹dŽfçð+޷ؽXË´Øùfzÿî·>nì.þòú›éßnq½~¼Ô :÷Ë\œkn­ƒ4`Ùf[SjØúdàíŽÈ9Î=3֏ ŸÔöû¤‚ãO…ÎÀ—Þ°Þq+kƶãÚÖxˆ-½% Ë|•S7½I"ú‚h—KÁB­ tºwGœbÌ"¬¹”Û™lKÒžOÆñs:ÿú¯ë»)¾)üôyÐs·&h×ÍTՈöž©Šù҉Âñè2Ðét@‹£á8¾‚Açí};íýÙû#²v}endstream +endobj +273 0 obj +974 +endobj +274 0 obj<>>>>>endobj +275 0 obj<>stream +xڝWKSã8¾ó+z}Ù ›„$„³'CU3 ÙÓfŠ-Û[òHr2ù÷Ó-%Æ1’)8Äv«ûëî¯úq0„þ átÇóƒËéÁÑ͆C˜Æøer6îŸÁ4êLS±ÐƂ]*ÐeÆ Dœe`TƳ,…MÁ¢d9»ß±È8̹ ØUÁ£>LSaÿKÃã2ƒeÊ¥“TZ$B¢::B*>MŸÐ÷GdEŠù§–-ÙÊ@ÊX¥¬‚¥ÒÏ2!Â7©Ð‘s +,{æ¦aҎœè+Xï*x1¿>ü‚à%£=Šòk&Lª¢w±~ÍžET# înᄌ-¨ ª nW* -† ÷°,Â+r{‡c@YpÝs[¾1åÜÿžux?é7v³à%_A‚µ³ôó°–3,¶¥ªáG,»8³¦8¾ö+][}\k}ì‡øÚŽ£ª-Ð>>>>>endobj +278 0 obj<>stream +xÚUNKnƒ0ÝsŠ·¤Rp€ ʖ~"uQ©mè,<&®°Ú¦\¿8NÕÌêý¿³ +åvmüQgC¶?6¨* rcÚ®a‘¿Hø J*;„3ánøÚ¤íMšK5“ášü—ƒ»iÑdIeȃ#J,qõL&"œ2ÓvËv«òt-IôâC’Kgu¬(QTVÇiQç7‚;e.K`èçùæ%»„ L!“Íÿ,‰fixw^Õ͖Þt¬‰Oýq@ÇÏ·NV†•;B/´2Êǃu¯Ü,|Ž1Er÷uÝuÁ¦îØW@+Ml´æÇGâyÈÞ³_\ãw›endstream +endobj +279 0 obj +257 +endobj +280 0 obj<>>>>>endobj +281 0 obj<>stream +xڅTaoÚ0ýί8åS§‰$ ¾mU«Vê4¦fš¦ušŒcˆWÇf¶Ó*ÿ~w mZJY,…8ðÞó½»Ç߃ƒy“ˆzô©%9°Š5dóIÌ`6ŸBQž|€1,2A:ø(„mLPf󮸃€)0F€qO²yœ¨¨”Qñ-¡Jé…S+é!Tξ-o@Û ¬•–>î‰PùC|JT)²äq§ü½’NB°p¡LÙa¯vA°—ò=fÖ Ë8âu5׺¬“%(ÓQõ éŽá$¹ç.ÍÖ'ˆÞ£?R9)ÞÆðÃ6 ¸¡âÌOG…®Z¥"[ˆú%3žMzS aͺ{*czܗ£wjÓ8”5])Çl¢’¹ÒûßzçÏQ{ö* ûÇ aÐÊ’‹ +.‹b NzÛ8A•óX|GcÑr+g<öݺ®ÙÉÕr B+iB çHD:ÏlÑÊH"Ú5ÆÛ±À~!atfë èºN] 4;¥š›¶C¡{éð8"´wrk]ß +kµ_ÅëDË/7$¼¬•I:ϳ¦)†öMÒZÝÉC¼ö?Þ,M{Þgq&—^Ììq2È«×Ã"5v@i=$μ­p: \-—%è¡1š>Z RÅïå.IåÑè\¢¢áµ¼¶öcs8Ÿ +Ép\üí´=å õ²Ù©½¢»Ù8\5×¼õÛÀ•ñ£]`O‡R²ÙñÓé|ŠÑNéGل^œ£¯£d ¢endstream +endobj +282 0 obj +652 +endobj +283 0 obj<>>>>>endobj +284 0 obj<>stream +xÚ¥VmSã6þίØÉ`JÛ¤¹$ßh7M+f:íÑé(öTl)'ÉäÒ_»VlòäڐIˆ¼oϳ«GúrAHœöø?%‹.D$SzÒëwƒ>$ÙQò€pœüC{ˇG¥Eã—jû#˜JÌ3ً’>•“©p˜›+Q èiõÔà—­“ê¾zÀÕ”~6*ƒ™°v®Mі³Y.1ã”!´£Ó æÂ¦Ú¬†ãÿ}ƒ¯%ÕÊ ©,´Ú­`é÷‚î  2ªµíd¯"c«ª@¶ÜRÁ{ƒ¨æ2}€1 + [݉à1üyûËíÝqåNá$W‹Û  +ᆾ†¼:å5µCÄ?>FñÇ_;Ðkxy9‡77ðCH¯¿Öq´9Æé 轿@÷ ³W±_&É5x;nVFÀZïÏ“Ö ´®oý×ÇþF—wÇoSnÐêÒ¤¯3>•9î˜J_»ïÑÜ'4Vjõ6<;ÃTNypÉ–nídQ™¥4ŠÊpAã÷óíõÍrÁúћË<‘ÏÅÂÂd³¹-Nщ‚hŸy´N¸Òí¦nâ¢Ìx§ ª¸µ¥ÈóHÇ`[qR—&¥Mff‰¼É·Rqª3´ ÂL[+'9zàøU³O F5­Rñ¾×FþKl‰4Ek[uE~Øk?ý´Oß& ‡ûp ÊbB@wåQ§kàšy8ëïõߒmP´™Z³˜©öÕõ5‹… Q±n0EùDÌL.V'Ég@ô# .k/ïӆ4F›¿s}´ÖË wmé°®½ñÜÆD-È%ÓPP“Ä=•ÝTeÓÌʜ ÝùöæÂ(’k[oí½õ)Ç'Ì¡‘Ö:ݚÍڏ+ø‡±Xt¢Á`0ŒèÝÆý¥¤Á=¡3‹ZX‘´1Gh? ;äÝyXÈG< ވGÃ0^ÿÏxñ0î®Ç› ©P)æ¹×•Hû+rÅݳï³J—Ü.{“.]â>µ¥ÙbwqïÝæ˜œoæhÙòc:MKc0 փ®Œÿ®ˆ¿oGd|t¾“ VìT–€Ó0CÃgXÍ'ʲû}É®¶“])ŒR,‘×¼|_ÔÑvÔNÊû{¾µ¬Fl{‚_é㋵^n]/æþRCúK YL Ÿ|3#ߟ‚ŠW֋~sû‘›R.3#˙u·³LñÚýG­854y•IcöøAØÊiŸ¹¤OˆíjR~uåV_ûKß(îÞ^<à„£ßÎ.j]uNß詛óQv–R‘úáHÝ`,…«zéÛï␽ã./žöYäºþgčŸ'Ÿ¾‰AH`endstream +endobj +285 0 obj +1010 +endobj +286 0 obj<>>>>>endobj +287 0 obj<>stream +xڕUQo›@ ~ϯðž–j…I“’·nm¤VªÔ­ìi¦ Éu—»”;†òïks švY"ˆ}öçϟÍó „¿!L#M ]>'ƒ³y á¹I޶ÉtêO ɆɊÆ-ù/©—0’Ÿ$Oè;†0tžÞ(Þ{:cЇíÁî™!ä¤0ÖgéªNvÅ,†+ VƒM!”å…×ä$…âje™P½9äZJ] µ¡r]¬™ZÍZ ±Q6,Ð GtŸ Ʉˆ F6l¢CiðçI/<‘AÆ,÷¬X»š=U®hċ—êà¦ ópÅÍï[n¡ÐÚB?¢àìŽmÏÂ8Žga<‹ÂYpŸüüDâƒ.#|ÍãdÇ£ƒúšF.³.%Š!v×÷m5±î!s¬Í‡›¶º$º3ä 萩dƜ¶56Ú6È¥­„”mî÷SWÌÆKÕäÇ\~8šøã7Ц¾ügÅu+‡t{sßWcÁŸKn,êÅ#GNö0k ±(-¢,§´# +£Ž4lY¥1Yp|ÓNnw^HrÁ¡à†×ãBµâŠÿ©»À{è¿|¿ÀÎd¥‘³¬Àh§`4dZ}´ñ éBSkÑ¡Áár—J ‘þ]ênšŽ¨–|aÊzú°`B¿¯ºA¸'’zÐÐ;zv¦W¬Èp£ˆ”I¢Å„ÉށÙÈ»'&–¦Ü˜·–Û:økÁ¼!ÒÐó¦D'ÌAŒ¦3ˆ5aMÇ(Ô^Dn‰u%äØc¶GšÛóVÛí,§LÒ´NtV¦¼Xë„ LR©ÓC¿ß-&+¶%túÎí¢q £1¢ᆬټúv9OÀƒZÅ:·)ÿ2[ …YÃpÇTÉ$ÅñÜqoo¾ÑÆÓ1¾új{tN\'ƒ¯ƒÑ*Jendstream +endobj +288 0 obj +709 +endobj +289 0 obj<>>>>>endobj +290 0 obj<>stream +xÚ-‹=‚0„÷þŠu¨ÒbPFüèf¢ò:› +Öªãßת¹[î¹<&|"f±UÇÖÄæj!@ „\Ì$–2Փí©PŽÍùP¢ôÍøÒÁ ¨;ÛÛa zôaÀ^÷Oí¦tcü'ó¿-³Ó<ÇwÒÕà®[sq¾…²ÎÄwGìÈÞÛN'pendstream +endobj +291 0 obj +133 +endobj +292 0 obj<>>>/Annots 126 0 R>>endobj +293 0 obj<>stream +xÚÕ[ÛrÛ6¾÷S𲽈BxÀ¥ãԝþÓ´©­>#Ñ[‘t)*¿ýÅ.DÀ ö&bE; | v=qõÏKRý%ODžìÚ«wÛ«··*a*Ù>$,žäE¦?·û¶Õ§CôÉMߍu7ÜþuõÓö*ݤ>|Üý D’‹ROk‘m$‡äx5~xLÞÞf c°$ÌS¸ÜÇ¡~¨v5,2ÍHi†¡ëa›Õÿ±Y9‰Å3ýÙ&Û0"‚’$(­®œç €û—ãX·Éì"n«'ËMæ¯B|ƒõû—zøÒÔÏߺdµ"¡ÇäÊØ¦Ô[.å&'bV® MÆõ½·÷ýîÔêã=/QQK”Z*>ñ /"S®Oû*dʃ×9+ákiêÇÅï‹nsVæz¨Þ ˆó ©¥Yè{íá#—PÞÌ£83Û$SúL{0Ä&œCӍM÷8ç ´‰Êô¥ñàˆMp±+èÌ×[”é¦ðшOh‘“]ü¸ˆðÅË +n,–鋁Ä2ƒ–‚<Íç: ™ VkF‚Ü5ˆ-¬‰)ÚAк މ‹Gü3^¯`;ã”@¥k¸Ë1éӛždˆeÌòt¡R—¥¥„Œ|ªwŸ»þÐ?¾|[ŒÓæsM¾]FÄ)3ã ôs"‚â”9:†ÿõŸŽß–SënbB\K£Mru&‚Bѝ‰@nÕñX碾K%&­T0ÿ¹±'† +„§è n›ÃX3ѱG¶êƒJš»›—à JZ8f½æí‘öˆ½†'>Á½š/³2éÊ̑þËÂb•JC\–úx «Tæ¤ýVÏýð·ö–3vy5¡êRa@à*óÜ"ˆ#ñû¢ÀUæ$\-¼‰/=|äJ,pµ09Üz†Ø„óîÔöÁxÆAЛNµÛõàˆMpU·loš iÎW$>AýÒÇêp>› ¢!³â¬»YîIíæÏ÷3†ï¢W²ˆ\¿L`®”‚ê ±,–™D£¿D˜º^ +’Po)b`À™¦‚š(ÀB>Ý÷§aW‡T<À­€iœ@xï›ã84ŸNcÓw³fç2n^Ë:?ÐZÖyæ B{t¤fÕ\è-K†Þæ®þçÔ ukKh_o9O×ÿÅ$À Œ÷9? +J€›¸÷¦oŸš˜¡˜!c†xØÃ·ʘ™¸tیˆ ¬"±¶h¨ ™Ääa‘¹u@áœrˆÜ%ìÂCž;.6> °ûþa|®†¹úmy©X"¦4EçÄ eA*¨”¡¯º;u]D"úÓÒÇ·0¬ gºËM çÑ‹hC],²SaW*´÷9»R$B‘¬(Ëé@Ï €—ó v¹ÌZÆA >ò è]ÓUÃKH³Ü3¸aœPþ z#¨‚¹È&)Nßæ"7NT„Ãr n¢g¹|IPnAt¬òꉽ,u¦›s–ùXÄ6XœêSÁé¨Õ™×\}_ºlìUÆíƒ!4Ê"C't½§®žÖ $ª8±³©«3õÁ}(âԇ~ß<¼„·ƒaÓÑ H2 +ÇU½½èÕÄ>BՒêe– +Å>‚sôAÃÂsð@àñ•W®¿ ki+`‘7g\a…)#(WùòjµÅÆjµNü/HVW«ŽJ´Ä6Š\éC€DP¢%uUÜ×cø½®¨/@¾a>:±ù‚ÌיŒµŽWJ|Û>R?T§Ã®mLOÆ2øßóNÏLC]TáQíæ%F +ðv‰ vsEéêX aõ:ˆ:V€b„Olµ$V˜&C‘"5Šøç'럞ÂÞ΁ÀÔ\ù€v€Zq¨°@µ5É3TmFÝ-×»]ý4Ɯ˄ÏR¨Šx ”r‚ ªÖ ¤G’@`wõ_õnŒ‚ÄÆV{4Àí4 +E€†S”ùp4€à=åw>(LÓ{ÎÕ9½Çï‹Ò{.Ìd8½·à&÷Ð 1bé½1½\²ea«˜3­\²lQ£ØysYñZvÈG¬ þåzXä 5gØ3SÂC"±,»çŒºgn>WÝc،LØZ/\#w!bç "g2Xtã\(âÛ'뻇æñ4TP’ œAG£–Æc¹¨vÁÞ6‡z¾_è»GQ §ØT»\$‚þ!¥ mÝ>õC°Dê@‚PçÕ¦2˜–Ûªš#"e%¶`‰”)j!¢ÆŽ@05B¤ÎkÙhÊð-œw¾g_`^¼/‰åáj+°;HA‰P±ƒ¶÷¨f,.Ëר •CŽÍBJi!”CnÁ¯ödÝlWÚÊ䕁T”ÝA-© ²ò»¡>ÖóGBªµˆ"*A]9N¤‚"¶%Ɉàz¿êã\?CyqsÀ"=; yi+;Hm+— k‹ 8+í=xâÛöšzwšq¦3Z@¥aE‹ED£¿1B*x¦µÈüÚïÞE”kjŽ Aa‹‰U¬EFáO††ýlÁG®®ã—EZ*Jl1þ¥Œ5¸”Ô>r}8ôÏÿ÷‘@m +‚û"ÖQRPËÆûº›1¦÷ieqSadÔÏÀÀ¯dEäÍRFÍ ×§ñóöåi¦mE +}¥V"‡Øþ¥$Ko… ì*¢ŸÜÂþMÁV«9<¼\´]  ZÁ"vPœ·ÿóПž~«Ú™3P\öW¸ë··%U(ޘ»™—ø*àîúv›¼I ?1±XÉ5´@ÓN5öÃ1ùPu§ê(Âôf¿)¸ÙPCâüãêÿ“b~›endstream +endobj +294 0 obj +2304 +endobj +295 0 obj<>>>/Annots 151 0 R>>endobj +296 0 obj<>stream +xÚ͖MÚ0†ïü +Û^ÄNr¤Û²—VÚ.YõX¥!@*’Ð$´ÚߙØCà EXö<¶ßמɯ ' ¾œH¿¬œ|H&ó˜ð˜$+µ¤‚èPÁ3Y¾KÒۜÔ+òXW]^uíûäçäS2a”/O$”-#ˆ+ —‚*ÛڒNqѬÉÃ< œã¤!Ì(c3ãâ­íòò©©÷;œëÆl˜f0áPzÏ`£JHJϒ(EcÛlÐBãŽæ¨= +vX%‰ù9ØvPݔ©që_¥¢üö +^/¨9ZœÓ–‡Ö¨¢x ¸€°Ç²(sÚ½íò5‚˜ÊûPã’*ލî%Pp»LË'Šcªduõ{D%îBÁG÷Ïpû &L*æ¿'µ(›Z0LšÌ¢ÆoÖ ê†pNø¦×R¦ã'.~p¾LÛm9ÏMµñÜöÀ]‹ + ×=p—5˲z_uEµ±XÞË)7VKúT*Ž U™Æu©Òý&¿mòƓIlI˜§s˜nCêêqŒ‰ ô×å˜~ÙÕÒstœ`@ñ/¸‹²ìš6ž½¹ÁX‰ãƒœÊ 0¨Ïõڃr‚•÷L(pÜßv,à +™øFgïâA T_Vúâi¾:­mªJ²¹T¨2gsѶߢÒ,ËÛöûÖë„1508E,Ýø¿\ÝI±»d ¼Bêƒ1}ÃkŒ”¦Ö]aŒ%CuT§dÛmIyÓԍ߁·VÓðhû-ÐcЦâ^²³.Ã1« Æô ¯1³ÆuÆX2¼Øœ‘M÷@Ú¥ëü‚/‘ƒC_Ø)Ïô<¯/ÑÝø¢póÈ»χ7¼/³yB¦äñõyAõªû“Bý›-Ë¢*Ú®I»ºiɗ´Ú§[¤L¹À·‡i(úÍ…Uòëä/ +KáŠendstream +endobj +297 0 obj +714 +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<>endobj +335 0 obj<>endobj +336 0 obj<>endobj +337 0 obj<>endobj +338 0 obj<>endobj +339 0 obj<>endobj +340 0 obj<>endobj +341 0 obj<>endobj +342 0 obj<>endobj +343 0 obj<>endobj +344 0 obj<>endobj +345 0 obj<>endobj +346 0 obj<>endobj +347 0 obj<>endobj +348 0 obj<>endobj +349 0 obj<>endobj +350 0 obj<>endobj +351 0 obj<>endobj +352 0 obj<>/Outlines 298 0 R/PageMode/UseOutlines/OpenAction[214 0 R/XYZ null null null]>>endobj +xref +0 353 +0000000000 65535 f +0000000015 00000 n +0000000227 00000 n +0000000288 00000 n +0000000362 00000 n +0000000444 00000 n +0000000522 00000 n +0000000599 00000 n +0000000678 00000 n +0000000754 00000 n +0000000835 00000 n +0000000894 00000 n +0000000999 00000 n +0000001104 00000 n +0000001209 00000 n +0000001314 00000 n +0000001379 00000 n +0000001464 00000 n +0000001516 00000 n +0000001574 00000 n +0000001658 00000 n +0000001718 00000 n +0000001802 00000 n +0000001833 00000 n +0000001937 00000 n +0000002042 00000 n +0000002147 00000 n +0000002252 00000 n +0000002357 00000 n +0000002460 00000 n +0000002563 00000 n +0000002667 00000 n +0000002772 00000 n +0000002877 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 +0000004135 00000 n +0000004238 00000 n +0000004342 00000 n +0000004447 00000 n +0000004552 00000 n +0000004657 00000 n +0000004762 00000 n +0000004867 00000 n +0000004972 00000 n +0000005077 00000 n +0000005182 00000 n +0000005287 00000 n +0000005392 00000 n +0000005497 00000 n +0000005602 00000 n +0000005707 00000 n +0000005812 00000 n +0000005917 00000 n +0000006022 00000 n +0000006127 00000 n +0000006232 00000 n +0000006337 00000 n +0000006442 00000 n +0000006545 00000 n +0000006648 00000 n +0000006752 00000 n +0000006857 00000 n +0000006962 00000 n +0000007067 00000 n +0000007172 00000 n +0000007277 00000 n +0000007382 00000 n +0000007487 00000 n +0000007592 00000 n +0000007697 00000 n +0000007802 00000 n +0000007907 00000 n +0000008012 00000 n +0000008117 00000 n +0000008222 00000 n +0000008327 00000 n +0000008432 00000 n +0000008537 00000 n +0000008642 00000 n +0000008747 00000 n +0000008852 00000 n +0000008957 00000 n +0000009062 00000 n +0000009167 00000 n +0000009272 00000 n +0000009377 00000 n +0000009482 00000 n +0000009587 00000 n +0000009692 00000 n +0000009797 00000 n +0000009902 00000 n +0000010006 00000 n +0000010110 00000 n +0000010215 00000 n +0000010321 00000 n +0000010427 00000 n +0000010533 00000 n +0000010639 00000 n +0000010745 00000 n +0000010851 00000 n +0000010957 00000 n +0000011063 00000 n +0000011169 00000 n +0000011275 00000 n +0000011381 00000 n +0000011487 00000 n +0000011593 00000 n +0000011699 00000 n +0000011805 00000 n +0000011911 00000 n +0000012017 00000 n +0000012123 00000 n +0000012229 00000 n +0000012335 00000 n +0000012440 00000 n +0000012544 00000 n +0000012648 00000 n +0000013413 00000 n +0000013519 00000 n +0000013623 00000 n +0000013728 00000 n +0000013834 00000 n +0000013940 00000 n +0000014044 00000 n +0000014148 00000 n +0000014252 00000 n +0000014357 00000 n +0000014462 00000 n +0000014568 00000 n +0000014674 00000 n +0000014780 00000 n +0000014886 00000 n +0000014992 00000 n +0000015096 00000 n +0000015201 00000 n +0000015307 00000 n +0000015411 00000 n +0000015516 00000 n +0000015622 00000 n +0000015726 00000 n +0000015831 00000 n +0000015937 00000 n +0000016147 00000 n +0000016181 00000 n +0000016215 00000 n +0000016916 00000 n +0000016965 00000 n +0000017014 00000 n +0000017063 00000 n +0000017112 00000 n +0000017161 00000 n +0000017210 00000 n +0000017259 00000 n +0000017308 00000 n +0000017357 00000 n +0000017406 00000 n +0000017455 00000 n +0000017504 00000 n +0000017553 00000 n +0000017602 00000 n +0000017651 00000 n +0000017700 00000 n +0000017749 00000 n +0000017798 00000 n +0000017847 00000 n +0000017896 00000 n +0000017945 00000 n +0000017994 00000 n +0000018043 00000 n +0000018092 00000 n +0000018141 00000 n +0000018190 00000 n +0000018239 00000 n +0000018288 00000 n +0000018337 00000 n +0000018386 00000 n +0000018435 00000 n +0000018484 00000 n +0000018533 00000 n +0000018582 00000 n +0000018631 00000 n +0000018680 00000 n +0000018729 00000 n +0000018778 00000 n +0000018827 00000 n +0000018876 00000 n +0000018925 00000 n +0000018974 00000 n +0000019023 00000 n +0000019072 00000 n +0000019121 00000 n +0000019170 00000 n +0000019219 00000 n +0000019268 00000 n +0000019317 00000 n +0000019366 00000 n +0000019415 00000 n +0000019464 00000 n +0000019773 00000 n +0000019925 00000 n +0000026317 00000 n +0000026339 00000 n +0000026452 00000 n +0000026554 00000 n +0000026574 00000 n +0000026705 00000 n +0000027474 00000 n +0000027495 00000 n +0000027636 00000 n +0000028014 00000 n +0000028035 00000 n +0000028175 00000 n +0000029089 00000 n +0000029110 00000 n +0000029250 00000 n +0000030693 00000 n +0000030715 00000 n +0000030855 00000 n +0000031753 00000 n +0000031774 00000 n +0000031887 00000 n +0000032089 00000 n +0000032110 00000 n +0000032264 00000 n +0000033166 00000 n +0000033187 00000 n +0000033341 00000 n +0000034270 00000 n +0000034291 00000 n +0000034440 00000 n +0000035151 00000 n +0000035172 00000 n +0000035285 00000 n +0000035488 00000 n +0000035509 00000 n +0000035667 00000 n +0000036420 00000 n +0000036441 00000 n +0000036599 00000 n +0000037553 00000 n +0000037574 00000 n +0000037732 00000 n +0000038718 00000 n +0000038739 00000 n +0000038888 00000 n +0000039611 00000 n +0000039632 00000 n +0000039772 00000 n +0000040430 00000 n +0000040451 00000 n +0000040600 00000 n +0000041626 00000 n +0000041647 00000 n +0000041806 00000 n +0000042799 00000 n +0000042820 00000 n +0000042988 00000 n +0000043900 00000 n +0000043921 00000 n +0000044080 00000 n +0000044967 00000 n +0000044988 00000 n +0000045138 00000 n +0000046183 00000 n +0000046204 00000 n +0000046363 00000 n +0000047816 00000 n +0000047838 00000 n +0000047969 00000 n +0000048297 00000 n +0000048318 00000 n +0000048467 00000 n +0000049190 00000 n +0000049211 00000 n +0000049370 00000 n +0000050451 00000 n +0000050473 00000 n +0000050622 00000 n +0000051402 00000 n +0000051423 00000 n +0000051536 00000 n +0000051740 00000 n +0000051761 00000 n +0000051916 00000 n +0000054291 00000 n +0000054313 00000 n +0000054468 00000 n +0000055253 00000 n +0000055274 00000 n +0000055329 00000 n +0000055434 00000 n +0000055578 00000 n +0000055681 00000 n +0000055786 00000 n +0000055951 00000 n +0000056059 00000 n +0000056174 00000 n +0000056279 00000 n +0000056387 00000 n +0000056495 00000 n +0000056611 00000 n +0000056709 00000 n +0000056878 00000 n +0000057034 00000 n +0000057134 00000 n +0000057249 00000 n +0000057373 00000 n +0000057481 00000 n +0000057601 00000 n +0000057766 00000 n +0000057873 00000 n +0000058039 00000 n +0000058144 00000 n +0000058262 00000 n +0000058378 00000 n +0000058506 00000 n +0000058637 00000 n +0000058759 00000 n +0000058926 00000 n +0000059046 00000 n +0000059162 00000 n +0000059320 00000 n +0000059412 00000 n +0000059519 00000 n +0000059630 00000 n +0000059731 00000 n +0000059884 00000 n +0000059980 00000 n +0000060086 00000 n +0000060192 00000 n +0000060297 00000 n +0000060406 00000 n +0000060516 00000 n +0000060630 00000 n +0000060729 00000 n +0000060865 00000 n +0000060963 00000 n +0000061061 00000 n +0000061207 00000 n +0000061322 00000 n +0000061442 00000 n +0000061561 00000 n +0000061666 00000 n +trailer +<> +startxref +61852 +%%EOF diff --git a/doc/sam.shtml b/doc/sam.shtml new file mode 100644 index 0000000000..bffb8c2a8a --- /dev/null +++ b/doc/sam.shtml @@ -0,0 +1,1038 @@ + + + + + + DRAFT - CUPS Software Administrators Manual + + + +

Preface

+ +This software administrators manual provides printer administration +information for the Common UNIX Printing System ("CUPS") Version 1.0.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. + +

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. + +

Document Overview

+ +

This software administrators manual is organized into the following sections:

+ +
    +
  • 1 - Printing System Overview
  • +
  • 2 - Building and Installing CUPS
  • +
  • 3 - Printer Queue Management
  • +
  • 4 - Printing System Management
  • +
  • 5 - Printer Accounting
  • +
+ +

1 - Printing System Overview

+ +

This chapter provides an overview of how the Common UNIX Printing System +works. + +

The Printing Problem

+ +

For years the printing problem has plagued UNIX®. Unlike +Microsoft® Windows® or MacOS, UNIX has no standard interface or +system in place for supporting printers. Among the solutions previously +available, the Berkeley and System V printing systems are the most +prevalent. + +

These printing systems support line printers (text only) or +PostScript printers (text and graphics), and with some coaxing they can +be made to support a full range of printers and file formats. However, +because each varient of the UNIX operating system uses a different +printing system than the next, developing printer drivers for a wide +range of printers is extremely difficult. That combined with the +limited volume of customers for each UNIX varient has forced most +printer vendors to give up supporting UNIX entirely. + +

The Common UNIX Printing System, or CUPS, is designed to eliminate +the printing problem. One common printing system can be used by +all UNIX varients to support the printing needs of users. Printer +vendors can use its modular filter interface to develop a single driver +program that supports a wide range of file formats with little or no +effort. Since CUPS provides both the System V and Berkeley printing +commands, users (and applications) can reap the benefits of this new +technology with no changes. + +

The Technology

+ +

CUPS is based upon an emerging Internet standard called the Internet +Printing Protocol, or IPP. IPP has been embraced by dozens of printer +and printer server manufacturers, and will be supported by the next +Microsoft Windows operating system. + +

IPP defines a standard protocol for printing as well as managing print +jobs and printer options like media size, resolution, and so forth. Like all +IP-based protocols, IPP can be used locally or over the Internet to printers +hundreds or thousands of miles away. Unlike other protocols, however, IPP +also supports access control, authentication, and encryption, making it a +much more secure printing solution than older ones. + +

IPP is layered on top of the Hyper-Text Transport Protocol, or HTTP, +which is the basis of web servers on the Internet. This allows the user to +view documentation and status information on a printer or server using their +web browser. + +

CUPS provides a complete IPP/1.0-based printing system that provides Basic +authentication and domain or IP-based access control. Digest authentication +and TLS encryption will be available in future versions of CUPS. + +

Jobs

+ +

Each file that is submitted for printing is called a job. +Jobs are identified by a unique number starting at 1 and are assigned +to a particular destination (usually a printer). Jobs can also have +options associated with them such as media size, number of copies, and +priority. + +

Classes

+ +

CUPS supports collections of printers known as classes. Jobs sent +to a class are forwarded to the first available printer in the class. + +

Filters

+ +

Filters allow a user or application to print many types of files +without extra effort. Print jobs sent to a CUPS server are filtered +before sending them to a printer. Some filters convert job files to +different formats that the printer can understand. Others perform page +selection and ordering tasks. Backend filters perform the most +important task of all - they send the filtered print data to the +printer. + +

CUPS provides filters for printing many types of image files, +HP-GL/2 files, PDF files, and text files. CUPS also supplies +PostScript and image file Raster Image Processors, or RIPs, that +convert PostScript or image files into bitmaps that can be sent to a +raster printer. + +

CUPS provides backends for printing over parallel and serial ports, +and over the network via the JetDirect (AppSocket), Server Message +Block, and Line Printer Daemon protocols. + +

Printer Drivers

+ +

Printer drivers in CUPS consist of one of more filters specific to a +printer. CUPS includes a sample printer driver for Hewlett-Packard +LaserJet and DeskJet printers. While this driver does not generate +optimal output for different printer models, it does demonstrate how +you can write your own printer drivers and incorporate them into CUPS. + +

Networking

+ +

Printers and classes on the local system are automatically shared with +other systems on the network. This allows you to setup one system to print +to a printer and use this system as a printer server or spool host for all +of the others. If there is only one occurrence of a printer on a network, +then that printer can be accessed using its name alone. If more than one +printer exists with the same name, users must select the printer by specifying +which server to use (e.g. "printer@host1" or "printer@host2".) + +

CUPS also provides implicit classes, which are collections of +printers and/or classes with the same name. This allows you to setup multiple +servers pointing to the same physical network printer, for example, so that +you aren't relying on a single system for printing. Because this also works +with printer classes, you can setup multiple servers and printers and never +worry about a "single point of failure" unless all of the printers and servers +goes down! + +

2 - Building and Installing CUPS

+ +

This chapter shows how to build and install the Common UNIX Printing System. +If you are installing a binary distribution from the CUPS web site, proceed to +the section titled, Installing a Binary Distribution. + +

Installing a Source Distribution

+ +

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 and PostScript RIP, you'll need the JPEG, +PNG, TIFF, and ZLIB libraries. CUPS will build without these, but with +reduced functionality. Easy Software Products maintains a mirror of the +current versions of these libraries at: + +

+ +

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

+ +

The documentation is formatted using the HTMLDOC software. If you need to +make changes you can get the HTMLDOC software from: + +

+ +

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
    +
+ +

If the PNG, JPEG, TIFF, and ZLIB libraries are not installed in a +system default location (typically /usr/include and +/usr/lib) you'll need to set the CFLAGS and +LDFLAGS environment variables prior to running configure: + +

    +% setenv CFLAGS "-I/some/directory"
    +% setenv LDFLAGS "-L/some/directory"
    +% ./configure ... 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
    +
+ +

Running the Software

+ +Once you have installed the software you can start the CUPS daemon by +typing: + +
    +% /usr/sbin/cupsd & ENTER
    +
+ +

Installing a Binary Distribution

+ +

We are currently distributing CUPS binary distributions in TAR format +with installation and removal scripts. + +

    + WARNING: + +

    Installing CUPS will overwrite your existing printing + system. If you experience difficulties with the CUPS software + and need to go back to your old printing system, you will need + to remove the CUPS software with the provided script and + reinstall the printing system from your operating system CDs. +

+ +

To install the CUPS software you will need to be logged in as root +(doing an "su" is good enough). Once you are the root user, run the +installation script with: + +

    +./cups.install ENTER
    +
+ +

After asking you a few yes/no questions the CUPS software will be +installed and the scheduler will be started automatically. + +

3 - Printer Queue Management

+ +

This chapter discusses how to add, modify, and delete print queues +on your system. + +

The lpadmin Command

+ +

The lpadmin command allows you to perform most printer +administration tasks from the command-line. Since lpadmin +is also a System V printing system command, it is located in the +/usr/lib directory instead of a more common one like +/usr/bin or /usr/sbin. + +

Adding and Modifying Printers

+ +

To add a printer to CUPS you simply run the lpadmin command +with the "-p" option: + +

    +% /usr/lib/lpadmin -pprinter -E -vdevice -Pppd ENTER
    +
+ +

Spaces between the option letter and value are optional. + +

The printer name can be up to 127 letters, digits, hyphens, +and underscores. Unlike other printing systems, the printer name in +CUPS is not case-sensitive, so you can't add two printers named +LaserJet and laserjet. + +

The device argument specifies the device URI or filename for the +printer. The following devices are supported in a basic installation of +CUPS: + +

+ +
file:/dev/filename +
/dev/filename +
Sends all output to the specified file. + +
http://[username:password@]hostname[:port]/resource +
ipp://[username:password@]hostname[:port]/resource +
Sends all output to the specified IPP printer or server. + The port parameters defaults to 631. + +
lpd://hostname/queue +
Sends all output to the specified LPD printer queue. + +
parallel:/dev/filename +
Sends all output to the specified parallel port device. + +
serial:/dev/filename[?options] +
Sends all output to the specified serial port device. The + options can be any of the following separated by the + plus (+) character: +
    +
  • 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://[username:password@]hostname/queue +
Sends all output to the specified SMB (Windows) printer queue + using the SAMBA software. + +
socket://hostname[:port] +
Sends all output to the specified printer using the + AppSocket protocol. The port parameter defaults to 9100. + +
+ +

The ppd argument specifies the PostScript Printer Description file +to use for this printer. Many options (such as media size, etc.) will not +be available if you omit this part of the lpadmin command. + +

Using Standard Printer Drivers

+ +

The lpadmin command allows you to use "standard" PPD files +and interface scripts located in the /usr/share/cups/model +directory with the "-m" option: + +

    +% /usr/lib/lpadmin -pprinter -E -vdevice -mmodel ENTER
    +
+ +

The model argument specifies the name of the PPD file or interface +script. For example, to add a printer using the sample HP DeskJet series +driver connected to parallel port 1 under Linux you would use: + +

    +% /usr/lib/lpadmin -pDeskJet -E -vparallel:/dev/par1 -mdeskjet.ppd ENTER
    +
+ +

Removing Printers

+ +

To remove a printer to CUPS you simply run the lpadmin command +with the "-x" option: + +

    +% /usr/lib/lpadmin -xprinter ENTER
    +
+ +

Printer Classes

+ +

CUPS allows you to group similar printers in a printer class. When +a user sends a print job to a class, the job will be processed by the first +available printer in that class. + +

To add a printer to a class you simply run the lpadmin command +with the "-p" and "-c" options: + +

    +% /usr/lib/lpadmin -pprinter -cclass ENTER
    +
+ +

The class is created automatically if it doesn't exist. To remove a +class just use the "-x" option: + +

    +% /usr/lib/lpadmin -xclass ENTER
    +
+ +

Setting the Default Printer

+ +

To set the default printer or class simply run the lpadmin +command with the "-d" option: + +

    +% /usr/lib/lpadmin -ddestination ENTER
    +
+ +

The destination argument is the name of the printer or class. + +

Starting and Stopping Printers

+ +

The enable and disable commands start and stop +printer queues, respectively: + +

    +% /usr/bin/enable printer ENTER
    +% /usr/bin/disable printer ENTER
    +
+ +

Printers that are disabled may still accept jobs for printing, but won't +actually print any files until they are restarted. This is useful if the +printer malfunctions and you need time to correct the problem. Any queues +jobs are printed after the printer is enabled (started). + +

Accepting and Rejecting Print Jobs

+ +

The accept and reject commands accept and reject +print jobs for the named printer, respectively: + +

    +% /usr/lib/accept printer ENTER
    +% /usr/lib/reject printer ENTER
    +
+ +

As noted above, a printer can be stopped but accepting new print +jobs. A printer can also be rejecting new print jobs while it finishes +those that have been queued. This is useful for when you must perform +maintenance on the printer and will not have it available to users for +a long period of time. + +

4 - Printing System Management

+ +

This chapter shows how you can configure the CUPS server. + +

Changing the Configuration Files

+ +

All of the server configuration files are located in the +/var/cups/conf directory. Once you have made a change to a +file you need to restart the CUPS server by sending it a HUP signal or +using the supplied script "cups.sh": + +

    +% ./cups.sh restart ENTER
    +
+ +

The binary distribution installs the script in the +init.d directory with the name lp or +lpd depending on the vendor-supplied printing system. + +

Temporary Files

+ +

Normally CUPS puts all of its temporary files in /var/tmp. +If you'd like to change this directory you'll need to edit the +/var/cups/conf/cupsd.conf file. + +

Start by creating the new temporary directory and setting the appropriate +permissions: + +

    +% mkdir /foo/bar/tmp ENTER
    +% chmod a+rwxt /foo/bar/tmp ENTER
    +
+ +

Then change the line containing the TempDir directive in +the cupsd.conf to the directory that you've created: + +

    +TempDir /foo/bar/tmp
    +
+ +

Finally, restart the server as outlined in the first section of this +chapter. + +

Network Configuration

+ +

The default configuration of the CUPS server listens for connections from +all network interfaces on port 631 (the standard IPP port). Administration +functions are limited to local connections with the appropriate username and +password. + +

If you'd like to limit access to your system you'll need to edit the +/var/cups/conf/cupsd.conf file. + +

Port

+ +

The Port directive specifies a port to listen on for +all interfaces. Besides the standard IPP port (631) you can also setup +your server to listen on the HTTP port (80) to use your CUPS server as +a standard web server as well. + +

Listen

+ +

The Listen directive specifies a listening address and port, +extending the functionality of the Port directive. If you want +to allow connections only from the local machine you can use: + +

    +Listen 127.0.0.1:631
    +
+ +

instead of the Port directive. + +

If you want to limit access to a specific network/subnet, make sure you +specify only the network address and not your system's network address! + +

BrowsePort

+ +

The BrowsePort directive controls which port is monitored for +remote printers. By default it is set to the IPP port (631), however you can +change it as needed. + +

    + + NOTE: + +

    You must set the BrowsePort to the same value + on all of the systems that you want to see. + +

+ +

BrowseAddress

+ +

The BrowseAddress directive specifies a broadcast address to +use when sending printer status updates over the network. The default +browse address is 255.255.255.255 which will send printer +information to all subnets. + +

    + + NOTE: + +

    If you are using HP-UX 10.20 and a subnet that is not 24, + 16, or 8 bits, printer browsing (and in fact all broadcast + reception) will not work. This problem appears to be fixed in + HP-UX 11.0. + +

+ +

Printer Security

+ +

CUPS provides IP and domain-name based access control and Basic +authentication for authentication. + +

Location

+ +

The Location directive defines access control for a +specific HTTP directory. The following pseudo directories are provided +by the CUPS server: + +

    + +
  • /admin - This is the URI that must be referenced to + do printer administation commands. + +
  • /classes - This is the URI that must be referenced to + access printer classes. + +
  • /jobs - This is the URI that must be referenced to + access jobs. + +
  • /printers - This is the URI that must be referenced to + access printers. + +
+ +

All other directories are taken from the +/usr/share/cups/doc directory. + +

The Location directive surrounds the other access control +directives described below. The default server configuration uses: + +

    +<Location /admin>
    +AuthType Basic
    +AuthClass System
    +
    +Order Deny,Allow
    +Deny From All
    +Allow From 127.0.0.1
    +</Location>
    +
+ +

Order

+ +

The Order directive defines the default access control. +The following values are supported: + +

    + +
  • Order Allow,Deny - Allow requests from all + systems except for those listed in a Deny + directive. + +
  • Order Deny,Allow - Allow requests only from + those listed in an Allow directive. + +
+ +

The Order directive must appear inside a +Location directive. + +

Allow

+ +

The Allow directive specifies a hostname, IP address, or +network that is allowed access to the server: + +

    +Allow from All
    +Allow from None
    +Allow from *.domain.com
    +Allow from .domain.com
    +Allow from host.domain.com
    +Allow from nnn.*
    +Allow from nnn.nnn.*
    +Allow from nnn.nnn.nnn.*
    +Allow from nnn.nnn.nnn.nnn
    +Allow from nnn.nnn.nnn.nnn/mm
    +Allow from nnn.nnn.nnn.nnn/mmm.mmm.mmm.mmm
    +
+ +

Allow directives are cummulative, so multiple Allow +directives can be used to allow access for multiple hosts or networks. The +/mm notation specifies a CIDR netmask: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
mmnetmask
00.0.0.0
1128.0.0.0
2192.0.0.0
......
8255.0.0.0
16255.255.0.0
24255.255.255.0
32255.255.255.255
+ +

The Allow directive must appear inside a +Location directive. + +

Deny

+ +

The Deny directive specifies a hostname, IP address, or +network that is allowed access to the server: + +

    +Deny from All
    +Deny from None
    +Deny from *.domain.com
    +Deny from .domain.com
    +Deny from host.domain.com
    +Deny from nnn.*
    +Deny from nnn.nnn.*
    +Deny from nnn.nnn.nnn.*
    +Deny from nnn.nnn.nnn.nnn
    +Deny from nnn.nnn.nnn.nnn/mm
    +Deny from nnn.nnn.nnn.nnn/mmm.mmm.mmm.mmm
    +
+ +

Deny directives are cummulative, so multiple Deny +directives can be used to allow access for multiple hosts or networks. The +/mm notation specifies a CIDR netmask: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
mmnetmask
00.0.0.0
1128.0.0.0
2192.0.0.0
......
8255.0.0.0
16255.255.0.0
24255.255.255.0
32255.255.255.255
+ +

The Deny directive must appear inside a +Location directive. + +

AuthType

+ +

The AuthType directive defines the type of authentication to +perform: + +

    + +
  • None - No authentication should be performed + (default.) + +
  • Basic - Basic authentication should be + performed using the UNIX password and group files. + +
+ +

The AuthType directive must appear inside a +Location directive. + +

AuthClass

+ +

The AuthClass directive defines what level of Basic +access is required: + +

    + +
  • Anonymous - No authentication should be performed + (default.) + +
  • User - A valid username and password is required. + +
  • System - A valid username and password is + required, and the username must belong to the "sys" group (this + can be changed using the SystemGroup directive, + below. + +
  • Group - A valid username and password is + required, and the username must belong to the group named by + the AuthGroupName directive. + +
+ +

The AuthClass directive must appear inside a +Location directive. + +

AuthGroupName

+ +

The AuthGroupName directive sets the group to use for +Group authentication. + +

The AuthGroupName directive must appear inside a +Location directive. + +

SystemGroup

+ +

The SystemGroup directive sets the administration group used +when authenticating the System type. It defaults to the "sys" +group. + +

File Formats

+ +

CUPS provides a MIME-based file typing and filtering mechanism to +convert files to a printable format for each printer. The +mime.types and mime.convs files define the +file type and filters that are available on the system. + +

mime.types

+ +

The mime.types defines the known file types. Each line +of the file starts with the MIME type and may be followed by one or +more file type recognition rules. For example, the +text/html file type is defined as: + +

    +text/html html htm \
    +          printable(0,1024) + (string(0,"<HTML>") string(0,"<!DOCTYPE"))
    +
+ +

The first two rules say that any file with an extension of ".html" or +".htm" is a HTML file. The third rules says that any file whose first +1024 characters are printable text and starts with the strings "<HTML>" +or "<!DOCTYPE" is a HTML file as well. + +

The first two rules deal solely with the name of the file being +typed. This is useful when the original filename is known, however for +print files the server doesn't always have a filename to work with. The +third rule takes care of this possibility and automatically figures out +the file type based upon the contents of the file instead. + +

The available tests are: + +

    + +
  • ( 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 (network or "big-endian" byte order) + +
  • int(offset,value) - True if 32-bit integer is + identical (network or "big-endian" byte order) + +
  • locale("string") - True if current locale + matches string + +
+ +

mime.convs

+ +

The mime.convs file defines all of the filter programs that +are known to the system. Each line consists of: + +

    +source destination cost program
    +
    +text/plain application/postscript 50 texttops
    +application/vnd.cups-postscript application/vnd.cups-raster 50 pstoraster
    +image/* application/vnd.cups-postscript 50 imagetops
    +image/* application/vnd.cups-raster 50 imagetoraster
    +
+ +

The source field is a MIME type, optionally using a wildcard for +the super-type or sub-type (e.g. "text/plain", "image/*", "*/postscript"). + +

The destination field is a MIME type defined in the +mime.types file. + +

The cost field defines a relative cost for the filtering +operation from 1 to 100. The cost is used to choose between two +different sets of filters when converting a file. For example, to convert +from image/jpeg to application/vnd.cups-raster, +you could use the imagetops and pstoraster +filters for a total cost of 100, or the imagetoraster filter +for a total cost of 50. + +

The program field defines the filter program to run; the +special program "-" can be used to make two file types equivalent. The +program must accept the standard filter arguments and environment +variables described in the CUPS Interface Design Document: + +

    +program job user title options [filename]
    +
+ +

If specified, the filename argument defines a file to read +when filtering, otherwise the filter must read from the standard input. +All filtered output must go to the standard output. + +

5 - Printer Accounting

+ +This chapter describes the CUPS log files. + +

Where to Find the Log Files

+ +

The log files are normally stored in the /var/cups/logs +directory. You can change this by editing the +/var/cups/conf/cupsd.conf configuration file. + +

The access_log File

+ +

The access_log file lists each HTTP resource that is accessed +by a web browser or CUPS/IPP client. Each line is in the so-called "Common +Log Format" used by many web servers and web reporting tools: + +

    +host group user date-time \"method resource version\" status bytes
    +
    +127.0.0.1 - - [20/May/1999:19:20:29 +0000] "POST /admin/ HTTP/1.1" 401 0
    +127.0.0.1 - mike [20/May/1999:19:20:31 +0000] "POST /admin/ HTTP/1.1" 200 0
    +
+ +

The host field will normally only be an IP address unless you +have changed the HostnameLookups directive on in the +cupsd.conf file. + +

The group field always contains "-". + +

The user field is the authenticated username of the requesting user. +If no username and password is supplied for the request then this field +contains "-". + +

The date-time field is the date and time of the request in Greenwich +Mean Time (a.k.a. ZULU) and is in the format: + +

    +[DD/MON/YYYY:HH:MM:SS +0000]
    +
+ +

The method field is the HTTP method used ("GET", "PUT", "POST", etc.) + +

The resource field is the filename of the requested resource. + +

The version field is the HTTP specification version used by the +client. For CUPS clients this will always be "HTTP/1.1". + +

The status field contains the HTTP result status of the +request. Usually it is "200", but other HTTP status codes are possible. +For example, 401 is the "unauthorized access" status in the example +above. + +

The bytes field contains the number of bytes in the request. +For POST requests the bytes field contains the number of bytes +of non-IPP data that is received from the client. + +

The error_log File

+ +

The error_log file lists messages from the scheduler (errors, +warnings, etc.): + +

    +level date-time message
    +
    +I [20/May/1999:19:18:28 +0000] Job 1 queued on 'DeskJet' by 'mike'.
    +I [20/May/1999:19:21:02 +0000] Job 2 queued on 'DeskJet' by 'mike'.
    +I [20/May/1999:19:22:24 +0000] Job 2 was cancelled by 'mike'.
    +
+ +

The level field contains the type of message: + +

    + +
  • E - An error occurred. + +
  • W - The server was unable to perform some action. + +
  • I - Informational message. + +
  • D - Debugging message. + +
+ +

The date-time field contains the date and time of when the page +started printing. The format of this field is identical to the data-time +field in the access_log file. + +

The message fields contains a free-form textual message. + +

The page_log File

+ +

The page_log file lists each page that is sent to a printer. +Each line contains the following information: + +

    +printer user job-id date-time page-number num-copies
    +
    +DeskJet root 2 [20/May/1999:19:21:05 +0000] 1 0
    +
+ +

The printer field contains the name of the printer that +printed the page. If you send a job to a printer class, this field will +contain the name of the printer that was assigned the job. + +

The user field contains the name of the user (the IPP +requesting-user-name attribute) that submitted this file for +printing. + +

The job-id field contains the job number of the page being printed. +Job numbers are reset to 1 whenever the CUPS server is started, so don't depend +on this number being unique! + +

The date-time field contains the date and time of when the page +started printing. The format of this field is identical to the data-time +field in the access_log file. + +

The page-number and num-pages fields contain the page number +and number of copies being printed of that page. For printer that can not +produce copies on their own, the num-pages field will always be 1. + + + diff --git a/doc/sdd.html b/doc/sdd.html new file mode 100644 index 0000000000..5c99b58e1a --- /dev/null +++ b/doc/sdd.html @@ -0,0 +1,473 @@ + + +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.

+

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.

+

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..d3f575b0c3 --- /dev/null +++ b/doc/sdd.pdf @@ -0,0 +1,989 @@ +%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ڕU]OA}çWÜø¤IÙ²€}«¢†DíV°é/Ãì]˜:»w;3 ¡¿¾wfQJŒ$†¹_çœûÁïV þ‹á¢ ½ȼu9k}¾A<‚YƖÁEféi SI%žÍ~ÕÖóhXÛÛçèöˆb˜¤X8•))œ¢¢vîC7®ÝAí:[) –2·!E«–…ÿ'*} ¤$«œSAih­ØÂV'”ÆT‘‘ÉC~à[!#WÊ¡tgE +’RU,2€ëƽ¨ëëzç+ÊsŽ{z˜ü„Ä(†ËžÓ­u˜Ãüôäê)™žÌÏàëKÄQ':Bº7ڑî­Ñ¬nÞaý~õ®J2N,4ò[ã£Å 0õ;ÛaD0ڐÀF0q°ö€õÑ«»FÍ),¶p-ì¦;ýCi%GCNŽUëXIaÒ=Kº +²{BëšÅ‹”ŒõºÔ­,kWtÏÍ· áû#ôêÍ3jÜrÓòœÚZÈ]vh2!ÑFM֝Š!§®SM¼_n/&³q$Is3'׳›ö$I¸¢v_˓çñs)±ôþü¢E ¿+¬¸(p³èÜy\¡ 7b,Ð÷q~z—Œ?ÁãÍU_ŒægŸ`ÊCÀö{´V,.5Égv›Þ_z«¯ðµ,§üˆa¸T®ìW[:(i«ÒO7m£Ü + rŸøKVÒ7Bhå¶Gõijeِy®2¦…¡õ”=Š„¬›†}Ûszµ€¼ I2æEh³døj(Øý¬ÇÊ …®«Se©›S`¡*R¬‡÷8bfÏ]—ºª7@VÖQ®þpíu³Š”ÁíÃÜ®öÐç§²2†…ÞB ”²½úQ§7?;ÀëE¨Ü·)ãӏ“„‡D8ü¾@?d©ß‰³‚Šö+ÙYíûç¡ãÝ-ûÀøèYd?2KQ}…éÎHkڄUÅ0 öK]K6µºCæþRnÞ\À[0|æÛ¯½ÜƒÜév,Š“Â#fȝàý¯Ð‡Žk¦oõù`|?Ä7¿ u¢ÿŠÿÊñ·šx[Ͷ6 S»Q«3ðm}ó Øv¢gö¯þûõ¬õ½õ'(B‘endstream +endobj +221 0 obj +825 +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 +0000028169 00000 n +0000028190 00000 n +0000028303 00000 n +0000028495 00000 n +0000028516 00000 n +0000028657 00000 n +0000029250 00000 n +0000029271 00000 n +0000029384 00000 n +0000029580 00000 n +0000029601 00000 n +0000029751 00000 n +0000030764 00000 n +0000030785 00000 n +0000030944 00000 n +0000032099 00000 n +0000032121 00000 n +0000032252 00000 n +0000033131 00000 n +0000033152 00000 n +0000033293 00000 n +0000034403 00000 n +0000034425 00000 n +0000034556 00000 n +0000035538 00000 n +0000035559 00000 n +0000035699 00000 n +0000036690 00000 n +0000036711 00000 n +0000036842 00000 n +0000037514 00000 n +0000037535 00000 n +0000037648 00000 n +0000037845 00000 n +0000037866 00000 n +0000037988 00000 n +0000038153 00000 n +0000038173 00000 n +0000038286 00000 n +0000038483 00000 n +0000038504 00000 n +0000038644 00000 n +0000039140 00000 n +0000039161 00000 n +0000039292 00000 n +0000039743 00000 n +0000039764 00000 n +0000039919 00000 n +0000042160 00000 n +0000042182 00000 n +0000042337 00000 n +0000043245 00000 n +0000043266 00000 n +0000043321 00000 n +0000043426 00000 n +0000043570 00000 n +0000043676 00000 n +0000043796 00000 n +0000043905 00000 n +0000044054 00000 n +0000044164 00000 n +0000044271 00000 n +0000044425 00000 n +0000044561 00000 n +0000044658 00000 n +0000044768 00000 n +0000044883 00000 n +0000044996 00000 n +0000045106 00000 n +0000045206 00000 n +0000045364 00000 n +0000045461 00000 n +0000045571 00000 n +0000045669 00000 n +0000045813 00000 n +0000045914 00000 n +0000046025 00000 n +0000046127 00000 n +0000046290 00000 n +0000046405 00000 n +0000046526 00000 n +0000046646 00000 n +0000046771 00000 n +0000046892 00000 n +0000047012 00000 n +0000047122 00000 n +0000047270 00000 n +0000047372 00000 n +0000047488 00000 n +0000047601 00000 n +0000047703 00000 n +0000047853 00000 n +0000047960 00000 n +0000048074 00000 n +0000048187 00000 n +0000048307 00000 n +0000048432 00000 n +0000048542 00000 n +0000048653 00000 n +0000048764 00000 n +0000048866 00000 n +0000049011 00000 n +0000049111 00000 n +0000049224 00000 n +0000049338 00000 n +0000049451 00000 n +0000049560 00000 n +0000049674 00000 n +0000049787 00000 n +0000049887 00000 n +0000050005 00000 n +0000050139 00000 n +0000050236 00000 n +0000050336 00000 n +trailer +<> +startxref +50522 +%%EOF diff --git a/doc/sdd.shtml b/doc/sdd.shtml new file mode 100644 index 0000000000..9d8d59d30a --- /dev/null +++ b/doc/sdd.shtml @@ -0,0 +1,567 @@ + + + + + + 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. + +

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. + +

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..51be5b88e5 --- /dev/null +++ b/doc/ssr.html @@ -0,0 +1,221 @@ + + +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 Local Access Risks + +4 Remote Access Risks + +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.

+

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.

+

1.3 Document Overview

+

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

+
    +
  • 1 - Scope
  • +
  • 2 - References
  • +
  • 3 - Local Access Risks
  • +
  • 4 - Remote Access Risks
  • +
  • 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 Access Risks

+

Local access risks are those that can be exploited only with a local +user account. This section does not address issues related to +dissemination of the root password or other security issues associated +with the UNIX operating system.

+

3.1 Security Breaches

+

Since the default installation creates a world-readable request +directory, it is possible for local users to read the contents of print +files before they are printed.

+

This problem can be alleviated by making the request directory +readable only by the user specified in the CUPS configuration file.

+

4 Remote Access Risks

+

Remote access risks are those that can be exploited without a local +user account and/or from a remote system. This section does not address +issues related to network or firewall security.

+

4.1 Denial of Service Attacks

+

Like all internet services, the CUPS server is vulnerable to denial +of service attacks, including:

+
    +
  1. Establishing multiple connections to the server until the server + will accept no more. +

    This cannot be protected against by the current software. It is +possible that future versions of the CUPS software could be configured +to limit the number of connections allowed from a single host, however +that still would not prevent a determined attack.

    +
  2. +
  3. Repeatedly opening and closing connections to the server as fast + as possible. +

    There is no easy way of protecting against this in the CUPS + software. If the attack is coming from outside the local network it +might be possible to filter such an attack, however once the +connection request has been received by the server it must at least +accept the connection to find out who is connecting.

    +
  4. +
  5. Flooding the network with broadcast packets on port 631. +

    It might be possible to disable browsing if this condition is +detected by the CUPS software, however if there are large numbers of +printers available on the network such an algorithm might think that +an attack was occurring when instead a valid update was being +received.

    +
  6. +
  7. Sending partial IPP requests; specifically, sending part of an + attribute value and then stopping transmission. +

    The current code is structured to read and write the IPP request +data on-the-fly, so there is no easy way to protect against this for +large attribute values.

    +
  8. +
  9. Sending large/long print jobs to printers, preventing other users + from printing. +

    There are limited facilities for protecting against large print + jobs (the MaxRequestSize attribute), however this will + not protect printers from malicious users and print files that + generate hundreds or thousands of pages. In general, we recommend + restricting printer access to known hosts or networks, and adding + user-level access control as needed for expensive printers.

    +
  10. +
+

4.2 Security Breaches

+

The current CUPS server only supports Basic authentication with +usernames and passwords. This essentially places the clear text of the +username and password on the network. Since CUPS uses the UNIX username +and password account information, the authentication information could +be used to gain access to accounts (possibly priviledged accounts) on +the server.

+

The default CUPS configuration disables remote administration. We do +not recommend that remote administration be enabled for all hosts, +however if you have a trusted network or subnet access can be +restricted accordingly.

+

The next minor release of CUPS will support Digest authentication of +the entire message body using separate MD5-based username and password +files. This will protect password information and prevent unauthorized +access due to compromised account passwords.

+

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..8ae80cf93e --- /dev/null +++ b/doc/ssr.pdf @@ -0,0 +1,446 @@ +%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[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 +]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<>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 +75 0 obj +6308 +endobj +76 0 obj<>>>>>endobj +77 0 obj<>stream +xÚ+ä2T0BCc3JÎår +ár á +äHÉHendstream +endobj +78 0 obj +31 +endobj +79 0 obj<>>>>>endobj +80 0 obj<>stream +xڝUKo1¾ó+F9%RÙfè-o!¥í6ª.Æ;œx=[Û ¢¿¾c/Bi«TpÁóú¾o|o¥pʟÎ;Ðíƒ,[—“ÖûÛ!¤C˜léŸ÷`’§0–TáÉä¹±ž%ƒÆÞ>$G’Â(GãU¡¤ðŠLã܃4]»vúëd®8*üRX‡²¶Ê¯ÀbEÖCei¡rt …^9ö¦*rNÍôN€$#ÑYðs„+*K2ðøiô-ç’i7鄒™UŒÌ<Áxå<–0=>ºzÌÆGÓøŠÖ1ZH“Óä¿îpï³ þ¼@»P¸ü ÁWX`¿ú–"Ê"°ª6>Z¬ÐFJ!vÚ9ë+oE4º˜À%0ò0nå Ñ@Ž Ô‘Ãl7­`¼‘:³”×Ò;ð0”ä‘!8/L.l¾…àHסƒ…кa±@““ }É÷ê֎5L (ºå²æû5ÄÀ%ÚÔúV–üÐÖÊ pI´…è’u֍Š1§nR‚ŸA¿“Ùx’¤¹™£›Ém{”eÜNѸÏD›€ŸK‰§àéÁ3Í"ø^cÍE›µGç>àŠe¸×C§Ç÷Ùõ;x¸½JÓóáôäŒyØþO—šä »?^k¨pQUc~Ä8Ó*Wæ6íh¯¤««0 Ü´¥òs^îÿ(j#C#„æy?¨Ès,˒ìKÐ1Í,-] PdäüXZUù-'tñAEbGYv͋ÐfÉpg(ÚìÆÊ …®«sU¥×[ï 696Ã{1³ç®K]7 kç©T?¸öb½Š¼íwŸán¾…>=楷|^ô + TüîÕKN»Ó“=¼A¾%ª m*ïÚÃ(ã!$¿Ï0 YvbÃ̐iïȶ–Õýý>>>>>endobj +83 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS041T072PIÑp rt QÐUp VÎO+)O,JUNM.-Ê,©TJ-È/*Ñ ÉâÒi҅ê2‰˜˜˜é™)€ù† +ÁÉù© Q×®@.ü7 £endstream +endobj +84 0 obj +118 +endobj +85 0 obj<>>>>>endobj +86 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 +87 0 obj +522 +endobj +88 0 obj<>>>>>endobj +89 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 +90 0 obj +121 +endobj +91 0 obj<>>>>>endobj +92 0 obj<>stream +xÚuRÛjÜ0}÷WÌcïnöòؔ +¥´]úª•ÆY%²ÆÑÈMý÷‘³]Xƒå3ç6z®¸‘§Í–k°}u×V¾ì ÙAÛɟõf­{·„odM€Ö"3üòüÄWí£@WÐ43ôz¹«× +ž¡f†&…‚IùH¬o“Ášü;òP ¼ø|¡ŒŒI9hŒ¹†öèmöÁ2DÊj@d›e½PYã\REÏ< + a0J œaï£)ãԉ „D”a0Ì/”Ä@’Ó¤"còy:Ñ€¬/LşŽÞÿúûBœLB€'ÎØ×s;Räm½=÷3—Y7°?ÉÜ%4öˆo·¹÷Ñb‘uؙ1d𑳠aNce>«OÁ]˧3‡ ùðYüg Ÿ¤7JÓ{ð2Ë0³WD'¡Ïe³6¥ÓÉTÙRÌ3kwCò1C烈P8马¸üCW¿R,Ösಽ!‘ˆö§ÝKü3÷z˜ 7OÚ]ÙË¥oø©ÜA+¬ÜÐúÎ ‡zzaýÓý½zïüØæºÔ÷ën¶ç®W›õ<ñÖ=_moê r«ßŸÛêgõiã #endstream +endobj +93 0 obj +447 +endobj +94 0 obj<>>>>>endobj +95 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS041T072PIÑp rt QÐUp VÎO+)O,JUNM.-Ê,©TJ-È/*Ñ ÉâÒi҅ê2‰[ëìò|ò“s““S‹‹‚2‹³‹AJ\C¸¹Ñ€%3endstream +endobj +96 0 obj +131 +endobj +97 0 obj<>>>>>endobj +98 0 obj<>stream +xÚ}WKo7¾ûWÌÑ$ْßí©nÀ@[¤¶‚öà Å¥$Æ\rCr½V~}¿!¹z¬í @‘¬È™ù3œ~?šÒþLézFçW$룻ùÑéç[šÞÒ|‰_®®/h^_Ѓª]Tô›”*zÐá9œÌ¿áìM§ùìøüvrŧËY‘Ïz>KÂ+Škø¿"’–ŠÔkcœŽª¢Nã×6’ ã¤0Ôå9‚k->ÚêÔyZzWã€ÏáÃ&DUO¸ +䞞Ofœ{¾Ö‚’Q;K•S¬C€ªò\‹¡Å'¯Œà¤Ñ‘U±sþ™8¼öªÆðõÖ븙d„`ãrr³Ã˜™Lée5JuKzTþEKУ?aæOý ^BÛ¨2ÞÆ… ZöȲ-\ƒä!à¸<Ð;3VâOk*N `K½Âõ$²ÑµŽ)³mëÀ Ô>t(â:- àEÀ­q4H·Æ9f#"sÒ¥œ ¹ñøí +© o­-CO%ªÆÌUiV„yPb3š ¹ +C؝¤q\ÆO–œŠoï¢ÀŠæ& %†:±aðE™”¬HY;m÷l¸'_p4éj¾Êt øA ]©t>7rß` Ö«u6ÆVg‡®3àŠB+×^’Œ¨'ÚY™£íˆ¤ôê;z:ÒD,”²èn©ô ¨/nëû ´ÌW$£qÙ̇ÁsI€‡Q·v€;Èןµ«·¢žQ?縳ç +<âhᝨ$§o€SEØÚ‚éê|úF¿ûH«tHSѺd½Ì¢¸J'ø»0µ_!â@Ö-Åx)»†ûÉ¿ê›&dã¤É…–yÚ¤œ=@¹Ò¬†èº.Pž}Î}#†guPÐI ©[CK¶¦è"zFWÔ6š%\(>ՋýV‹‹¢Å£²IŠFøÈóóþË*ž ¿Rh”ÔK §šÍVٝe¸Ù^/Z$E­J͹´]Óàp¯YŸ7zaC—*ô¯Ó^?n‡ŸtUjÍ}+c?ª|B‹ÈËÎß+˜€^€ñ1¾—©bWäÚ5ù€\ny.-ØïK<{YãÌð–ÏËŸéÞ©qL»‚¾¹Eș²GFý@äӎ«L¯zÈc6ê›èíÌJîã±ÍcYHmàj• ~gxe {e<3sù>+ïðñ_âõ!󸍍ÃGúxÇÀÓÉÇSœ¥‡0ûÌè¶'®>•Úµ¡€e-sa˜t@:`¥ø]ÙëÖb3©àûaò:p9·XAº·å¦Q§Øû®®!þéÌI)§_¿ ȳuMÏçé;5 Qr¥X”8—>6Àlú0,Ñ;ïUªbU +û›²ý·%áÍÎ4Æ^¹·5Ͱ+åíŠîàu¹VoKûݲ¿9‹Ç2´ Í@w"hI¢å¦Œhä4ýÒ¬eVÔªˆ Bî +<¦=¨ø7þ€ˆÆ™”Bz<Ð]½Æ²~lƒÄ Á =j~·RѸc}ýûþ¿ƒëô}°~íÕ× P^ ÷~ßm>H wƞJÌácöt\ž• +ø‡V+µ­ <ôÈ2õïͳJ-öÉ ¶ß»rQå™ +ýÊ.*ì VM?Oè_Üv©—vVNý‘ÏgcÜìŒ1»ÎÆøðG.nÎ&·8‰3×üïOó£ŽþúYU»endstream +endobj +99 0 obj +1404 +endobj +100 0 obj<>>>>>endobj +101 0 obj<>stream +xÚ]Q]o›0}çWœÇU4NXš=®Ëò6ikØ0æ܁Í|ífÙ¯ßuˆZ©Âºæ|ÝßBa%Âf›™ŠÇ¦¸?ÔP +M/_¶»ºÚ¡é>èn²Îr :ZïÐÈév¤½ÐãˆÁsäò:Ó ØŸ0è‚F ‰£€ų¿!N­LÐÆ3ŒÎ¢wÍs±B©6Õ:›Ck2Q`>t֝ÆKuC­·UQÍ@¢û7BŠn ‘4|¯¿~q¶ŽÓ<û±·'фNq ­Y¶¨ÌÈ70I}"´¾» ±x‚iÖ²ùû|ß÷ŸÊV¼:Qpz’U]‡Y3˖R‰+4ƒå%Æ|$ßÖI}ӒâJ Rž‹H.GôÁþ£îé­°.¢‡ñ“ˆN–o%÷¦Îצî»ÛïTµ‚Z©EfÿôåР\::ú>žµì~$“‚>>>>>endobj +104 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 +105 0 obj +426 +endobj +106 0 obj<>>>>>endobj +107 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 +108 0 obj +383 +endobj +109 0 obj<>>>/Annots 53 0 R>>endobj +110 0 obj<>stream +xÚ՘ÍnÔ0Çïû>4þNŽ…R„„ì.°/,4ÈPߌ»jìܶRkâßÄ3žÿ8ýµÁ¨ÔI‚¨@M»y¹ß\ÝÖ×hDXЂ !¹¾î¿<Û>ß)ÔÑ«î<¨ópy¾ÿ¾y½ß”E©)æ‚ÍeûÆ  •žÖ"su÷whgøï¿¢«[Ž06Í´ÚyÃh?![DyQÅ|gÊ®é~*š(%x%\»Ó«ÿáÙHPa"M¸¾¶ˆ“‚à j¡ÖùDØH‰XÐVÏÄ&Ú¡ °[ÐÛ/zWœŽ§æ0œºóãQ粐kŠ{.¶vÅ>¶v0[QLô6¦$S W²1Ì@ÚÝ_Õ&Šaš¯DñøÒ¾œhïÿ¨þÏIý}<9 õ*’“É +¯+½(Ȋ¤²Â뺀N3Yñd\šªˆÐ`ÔM×ünõvŸç… d¬`1Ð?ÄLjˆÞQOœœ|.É(øî~‘àsIT“´à{<7áŠøÎ +”­:ª^u™‰c½.ýyäG3›_G`”{7X&÷\Øu“¬Ü{•Èƒ3;ΫOv‰”Msõæç¥IZHrvGòµ”hBÀ ¤u>¥8˜o5óÁ ƒ`Ý1QÒ"x+WÒ ì@ڙÃ~“؈!Aó„iÖÏ?Àëa84s;ˆ>™œçv +§¶Y¹œÙAêàÄ8s͋eNžl•4"ƒH µÚã ê!ìÀûO´Z¦µšHwp/õג,kâ”1õU<mÖIŒ³¥¼¹ë.—C?ɺÀëÿ^Ùþ˜ºïf¶,JÌ  %…rÂj¡¤£C_Î ¤½êÛ¹$×ր–Æ·,]#²+µƒ¤¼”Ä4)/ÌTˆéßìÕôÝù~.²Œ­ï¤mczu[ÁncX—$ŕ“·›íõí½@öëׇ¿‡^¡QD·êg×@Õx!‰]Ý ¢ùqóã×ï>>>>>endobj +113 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS041T072PIÑp rt QÐUp VÎO+)O,JUNM.-Ê,©TJ-È/*Ñ ÉâÒi҅êÊÌ ¹†pr‡Âµendstream +endobj +114 0 obj +103 +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<>/Outlines 115 0 R/PageMode/UseOutlines/OpenAction[79 0 R/XYZ null null null]>>endobj +xref +0 133 +0000000000 65535 f +0000000015 00000 n +0000000221 00000 n +0000000282 00000 n +0000000356 00000 n +0000000434 00000 n +0000000511 00000 n +0000000590 00000 n +0000000666 00000 n +0000000747 00000 n +0000000805 00000 n +0000000907 00000 n +0000001010 00000 n +0000001114 00000 n +0000001218 00000 n +0000001322 00000 n +0000001426 00000 n +0000001530 00000 n +0000001634 00000 n +0000001738 00000 n +0000001842 00000 n +0000001944 00000 n +0000002047 00000 n +0000002151 00000 n +0000002255 00000 n +0000002359 00000 n +0000002463 00000 n +0000002567 00000 n +0000002671 00000 n +0000002773 00000 n +0000002876 00000 n +0000002980 00000 n +0000003084 00000 n +0000003188 00000 n +0000003292 00000 n +0000003396 00000 n +0000003498 00000 n +0000003601 00000 n +0000003705 00000 n +0000003809 00000 n +0000003913 00000 n +0000004017 00000 n +0000004121 00000 n +0000004225 00000 n +0000004329 00000 n +0000004433 00000 n +0000004537 00000 n +0000004641 00000 n +0000004744 00000 n +0000004848 00000 n +0000004953 00000 n +0000005058 00000 n +0000005163 00000 n +0000005268 00000 n +0000005586 00000 n +0000005618 00000 n +0000005650 00000 n +0000005849 00000 n +0000005896 00000 n +0000005943 00000 n +0000005990 00000 n +0000006037 00000 n +0000006084 00000 n +0000006131 00000 n +0000006178 00000 n +0000006225 00000 n +0000006272 00000 n +0000006319 00000 n +0000006366 00000 n +0000006413 00000 n +0000006461 00000 n +0000006509 00000 n +0000006557 00000 n +0000006728 00000 n +0000006877 00000 n +0000013254 00000 n +0000013275 00000 n +0000013385 00000 n +0000013485 00000 n +0000013504 00000 n +0000013641 00000 n +0000014534 00000 n +0000014554 00000 n +0000014664 00000 n +0000014851 00000 n +0000014871 00000 n +0000015008 00000 n +0000015599 00000 n +0000015619 00000 n +0000015729 00000 n +0000015919 00000 n +0000015939 00000 n +0000016067 00000 n +0000016583 00000 n +0000016603 00000 n +0000016713 00000 n +0000016913 00000 n +0000016933 00000 n +0000017070 00000 n +0000018543 00000 n +0000018564 00000 n +0000018685 00000 n +0000019137 00000 n +0000019158 00000 n +0000019297 00000 n +0000019794 00000 n +0000019815 00000 n +0000019945 00000 n +0000020399 00000 n +0000020420 00000 n +0000020573 00000 n +0000021671 00000 n +0000021693 00000 n +0000021805 00000 n +0000021979 00000 n +0000022000 00000 n +0000022055 00000 n +0000022160 00000 n +0000022303 00000 n +0000022408 00000 n +0000022527 00000 n +0000022635 00000 n +0000022783 00000 n +0000022892 00000 n +0000022998 00000 n +0000023154 00000 n +0000023249 00000 n +0000023406 00000 n +0000023522 00000 n +0000023630 00000 n +0000023764 00000 n +0000023861 00000 n +0000023961 00000 n +trailer +<> +startxref +24144 +%%EOF diff --git a/doc/ssr.shtml b/doc/ssr.shtml new file mode 100644 index 0000000000..91ece988ed --- /dev/null +++ b/doc/ssr.shtml @@ -0,0 +1,252 @@ + + + + + + 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. + +

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. + +

Document Overview

+ +

This software security report is organized into the following sections:

+ +
    +
  • 1 - Scope
  • +
  • 2 - References
  • +
  • 3 - Local Access Risks
  • +
  • 4 - Remote Access Risks
  • +
  • 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 Access Risks

+ +

Local access risks are those that can be exploited only with a local user +account. This section does not address issues related to dissemination of the +root password or other security issues associated with the UNIX operating +system. + +

Security Breaches

+ +

Since the default installation creates a world-readable request directory, +it is possible for local users to read the contents of print files before they +are printed. + +

This problem can be alleviated by making the request directory readable only +by the user specified in the CUPS configuration file. + +

Remote Access Risks

+ +

Remote access risks are those that can be exploited without a local user +account and/or from a remote system. This section does not address issues +related to network or firewall security. + +

Denial of Service Attacks

+ +

Like all internet services, the CUPS server is vulnerable to denial of +service attacks, including: + +

    + +
  1. Establishing multiple connections to the server until the server + will accept no more. + +

    This cannot be protected against by the current software. It + is possible that future versions of the CUPS software could be + configured to limit the number of connections allowed from a + single host, however that still would not prevent a determined + attack. + +

  2. Repeatedly opening and closing connections to the server as fast + as possible. + +

    There is no easy way of protecting against this in the CUPS + software. If the attack is coming from outside the local + network it might be possible to filter such an attack, however + once the connection request has been received by the server it + must at least accept the connection to find out who is + connecting. + +

  3. Flooding the network with broadcast packets on port 631. + +

    It might be possible to disable browsing if this condition + is detected by the CUPS software, however if there are large + numbers of printers available on the network such an algorithm + might think that an attack was occurring when instead a valid + update was being received. + +

  4. Sending partial IPP requests; specifically, sending part of an + attribute value and then stopping transmission. + +

    The current code is structured to read and write the IPP + request data on-the-fly, so there is no easy way to protect + against this for large attribute values. + +

  5. Sending large/long print jobs to printers, preventing other users + from printing. + +

    There are limited facilities for protecting against large print + jobs (the MaxRequestSize attribute), however this will + not protect printers from malicious users and print files that + generate hundreds or thousands of pages. In general, we recommend + restricting printer access to known hosts or networks, and adding + user-level access control as needed for expensive printers. + +

+ +

Security Breaches

+ +

The current CUPS server only supports Basic authentication with +usernames and passwords. This essentially places the clear text of the +username and password on the network. Since CUPS uses the UNIX username +and password account information, the authentication information could +be used to gain access to accounts (possibly priviledged accounts) on +the server. + +

The default CUPS configuration disables remote administration. We do +not recommend that remote administration be enabled for all hosts, +however if you have a trusted network or subnet access can be +restricted accordingly. + +

The next minor release of CUPS will support Digest authentication of +the entire message body using separate MD5-based username and password +files. This will protect password information and prevent unauthorized +access due to compromised account passwords. + +

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..ec2a16f929 --- /dev/null +++ b/doc/stp.html @@ -0,0 +1,145 @@ + + +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.

+

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.

+

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.pdf b/doc/stp.pdf new file mode 100644 index 0000000000000000000000000000000000000000..7d51055f8ac6739daf6ddde74786295f08351e78 GIT binary patch literal 22085 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 + + + + + + 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. + +

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. + +

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..21f2d24814 --- /dev/null +++ b/doc/sum.html @@ -0,0 +1,511 @@ + + +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

+
+
Preface + +1 - Printing System Overview + +2 - Using the Printing System + +3 - Standard Printer Options + +
+

Preface

+ This software users manual describes how to use the Common UNIX +Printing System ("CUPS") Version 1.0.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.

+

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.

+

Document Overview

+

This software users manual is organized into the following sections:

+
    +
  • 1 - Printing System Overview
  • +
  • 2 - Using the Printing System
  • +
  • 3 - Standard Printer Options
  • +
  • 4 - Checking the Status Via the Web
  • +
+

1 - Printing System Overview

+

This chapter provides an overview of how the Common UNIX Printing +System works.

+

The Printing Problem

+

For years the printing problem has plagued UNIX®. Unlike +Microsoft® Windows® or MacOS, UNIX has no standard interface or system +in place for supporting printers. Among the solutions previously +available, the Berkeley and System V printing systems are the most +prevalent.

+

These printing systems support line printers (text only) or +PostScript printers (text and graphics), and with some coaxing they can +be made to support a full range of printers and file formats. However, +because each varient of the UNIX operating system uses a different +printing system than the next, developing printer drivers for a wide +range of printers is extremely difficult. That combined with the +limited volume of customers for each UNIX varient has forced most +printer vendors to give up supporting UNIX entirely.

+

The Common UNIX Printing System, or CUPS, is designed to eliminate +the printing problem. One common printing system can be used by all +UNIX varients to support the printing needs of users. Printer vendors +can use its modular filter interface to develop a single driver program +that supports a wide range of file formats with little or no effort. + Since CUPS provides both the System V and Berkeley printing commands, +users (and applications) can reap the benefits of this new technology +with no changes.

+

The Technology

+

CUPS is based upon an emerging Internet standard called the Internet +Printing Protocol, or IPP. IPP has been embraced by dozens of printer +and printer server manufacturers, and will be supported by the next +Microsoft Windows operating system.

+

IPP defines a standard protocol for printing as well as managing +print jobs and printer options like media size, resolution, and so +forth. Like all IP-based protocols, IPP can be used locally or over the +Internet to printers hundreds or thousands of miles away. Unlike other +protocols, however, IPP also supports access control, authentication, +and encryption, making it a much more secure printing solution than +older ones.

+

IPP is layered on top of the Hyper-Text Transport Protocol, or HTTP, +which is the basis of web servers on the Internet. This allows the user +to view documentation and status information on a printer or server +using their web browser.

+

CUPS provides a complete IPP/1.0-based printing system that provides +Basic authentication and domain or IP-based access control. Digest +authentication and TLS encryption will be available in future versions +of CUPS.

+

Jobs

+

Each file that is submitted for printing is called a job. + Jobs are identified by a unique number starting at 1 and are assigned +to a particular destination (usually a printer). Jobs can also have +options associated with them such as media size, number of copies, and +priority.

+

Classes

+

CUPS supports collections of printers known as classes. Jobs +sent to a class are forwarded to the first available printer in the +class.

+

Filters

+

Filters allow a user or application to print many types of files +without extra effort. Print jobs sent to a CUPS server are filtered +before sending them to a printer. Some filters convert job files to +different formats that the printer can understand. Others perform page +selection and ordering tasks. Backend filters perform the most +important task of all - they send the filtered print data to the +printer.

+

CUPS provides filters for printing many types of image files, +HP-GL/2 files, PDF files, and text files. CUPS also supplies PostScript +and image file Raster Image Processors, or RIPs, that convert +PostScript or image files into bitmaps that can be sent to a raster +printer.

+

CUPS provides backends for printing over parallel and serial ports, +and over the network via the JetDirect (AppSocket), Server Message +Block, and Line Printer Daemon protocols.

+

Printer Drivers

+

Printer drivers in CUPS consist of one of more filters specific to a +printer. CUPS includes a sample printer driver for Hewlett-Packard +LaserJet and DeskJet printers. While this driver does not generate +optimal output for different printer models, it does demonstrate how +you can write your own printer drivers and incorporate them into CUPS.

+

Networking

+

Printers and classes on the local system are automatically shared +with other systems on the network. This allows you to setup one system +to print to a printer and use this system as a printer server or spool +host for all of the others. If there is only one occurrence of a +printer on a network, then that printer can be accessed using its name +alone. If more than one printer exists with the same name, users must +select the printer by specifying which server to use (e.g. +"printer@host1" or "printer@host2".)

+

CUPS also provides implicit classes, which are collections of +printers and/or classes with the same name. This allows you to setup +multiple servers pointing to the same physical network printer, for +example, so that you aren't relying on a single system for printing. +Because this also works with printer classes, you can setup multiple +servers and printers and never worry about a "single point of failure" +unless all of the printers and servers goes down!

+

2 - Using the Printing System

+

This chapter shows you how to submit, query, and cancel print jobs +to different printers.

+

Submitting Files for Printing

+

CUPS provides both the System V (lp) and Berkeley ( +lpr) printing commands. To print a file to the default printer +on the system (or your only printer if you have only one) you just need +to type:

+
    +
    +% lp filename ENTER
    +
    +
+

or:

+
    +
    +% lpr filename ENTER
    +
    +
+

CUPS understands many different types of files directly, including +PostScript and image files. This allows you to print from inside your +applications or at the command-line, whichever is most convenient!

+

Choosing a Printer

+

Many systems will have more than one printer available to the user. +These printers can be attached to the local system via a parallel or +serial port, or available over the network.

+

To see a list of available printers, use the lpstat + command:

+
    +
    +% lpstat -p -d ENTER
    +
    +
+

The "-p" option specifies that you want to see a list of printers, +and the "-d" option reports the current system default printer or +class.

+

To print to a specific printer, use the "-d" option to the lp + command:

+
    +
    +% lp -d printer filename ENTER
    +
    +
+

or the "-P" option to the lpr command:

+
    +
    +% lpr -P printer filename ENTER
    +
    +
+

Setting Printer Options

+

For many types of files, the default printer options may be +sufficient for your needs. However, there may be times when you need to +change the options for a particular file you are printing.

+

The lp command allows you to pass printer options using +the "-o" option:

+
    +
    +% lp -o landscape -o scaling=75 -o media=A4 filename.jpg
    +
    +
+

The lpr command has no command-line option for printer +options.

+

The available printer options vary depending on the printer. The +standard options are described in Chapter 3.

+

Printing Multiple Copies

+

Both the lp and lpr commands have options +for printing more than one copy of a file:

+
    +
    +% lp -n num-copies filename ENTER
    +% lpr -#num-copies filename ENTER
    +
    +
+

Copies are normally not collated for you. To get collated +copies use the lp command with the "-o Collate=True" +option:

+
    +
    +% lp -n num-copies -o Collate=True filename ENTER
    +
    +
+

Checking the Printer Status from the Command-Line

+

The lpstat command can be used to check for jobs that +you have submitted for printing:

+
    +
    +% lpstat ENTER
    +Printer-1 johndoe 4427776
    +Printer-2 johndoe 15786
    +Printer-3 johndoe 372842
    +
    +
+

The jobs are listed in the order they will be printed. To see which +files and printers are active, use the "-p" option:

+
    +
    +% lpstat -p ENTER
    +printer DeskJet now printing DeskJet-1.
    +
    +
+

Or to show the jobs and the printers, use the "-o" and "-p" options:

+
    +
    +% lpstat -o -p ENTER
    +Printer-1 johndoe 4427776
    +Printer-2 johndoe 15786
    +Printer-3 johndoe 372842
    +printer DeskJet now printing DeskJet-1.
    +
    +
+

Checking the Printer Status from the Web

+

Since CUPS uses the Internet Printing Protocol, it is also a +full-featured web server. To use your web browser to monitor the +printers on your system, open the URL " +http://localhost:631". From there you can view the status of +classes, jobs, and printers with the click of a button!

+

Canceling a Print Job

+

The cancel command cancels a print job:

+
    +
    +% cancel job-id ENTER
    +
    +
+

The job-id is a number that was reported to you by the +lp or lpstat commands.

+

3 - Standard Printer Options

+

This chapter describes the standard printer options that are +available when printing with the lp command.

+

General Options

+

The following options apply when printing all types of files.

+

Selecting the Media Size, Type, and Source

+

The "-o media=xyz" option sets the media size, type, and/or source:

+
    +
    +% lp -o media=Letter filename ENTER
    +% lp -o media=Letter,MultiPurpose filename ENTER
    +% lp -o media=Letter,Transparency filename ENTER
    +% lp -o media=Letter,MultiPurpose,Transparency filename ENTER
    +
    +
+

The available media sizes, types, and sources depend on the printer, +but most support the following options (case is significant):

+
    +
  • Letter - US Letter (8.5x11 inches, or 216x279mm)
  • +
  • Legal - US Legal (8.5x14 inches, or 216x356mm)
  • +
  • A4 - ISO A4 (8.27x11.69 inches, or 210x297mm)
  • +
  • COM10 - US #10 Envelope (9.5x4.125 inches, or + 241x105mm)
  • +
  • DL - ISO DL Envelope (8.66x4.33 inches, or 220x110mm)
  • +
  • Transparency - Transparency media type or source
  • +
  • Upper - Upper paper tray
  • +
  • Lower - Lower paper tray
  • +
  • MultiPurpose - Multi-purpose paper tray
  • +
  • LargeCapacity - Large capacity paper tray
  • +
+

The actual options supported are defined in the printer's PPD file +in the PageSize, InputSlot, and +MediaType options.

+

Setting the Orientation

+

The "-o landscape" option will rotate the page 90 degrees to print +in landscape orientation:

+
    +
    +% lp -o landscape filename ENTER
    +
    +
+

Printing On Both Sides of the Paper

+

The "-o sides=two-sided-short" and "-o sides=two-sided-long" options +will enable duplexing on the printer (if the printer supports it.) The +"two-sided-short" option is suitable for landscape pages, while the +"two-sided-long" option is suitable for portrait pages:

+
    +
    +% lp -o sides=two-sided-short filename ENTER
    +% lp -o sides=two-sided-long filename ENTER
    +
    +
+

Selecting a Range of Pages

+

The "-o page-ranges=pages" option selects a range of pages for +printing:

+
    +
    +% lp -o page-ranges=1 filename ENTER
    +% lp -o page-ranges=1-4 filename ENTER
    +% lp -o page-ranges=1-4,7,9-12 filename ENTER
    +
    +
+

As shown above, the pages value can be a single page, a range +of pages, or a collection of page numbers and ranges separated by +commas. The pages will always be printed in ascending order, regardless +of the order of the pages in the "page-range" option.

+

To select the even or odd pages, use the "-o page-set=set" option:

+
    +
    +% lp -o page-set=odd filename ENTER
    +% lp -o page-set=even filename ENTER
    +
    +
+

Setting the Brightness

+

You can control the overall brightness of the printed output using +the "-o brightness=percent" option:

+
    +
    +% lp -o brightness=120 filename ENTER
    +
    +
+

Values greater than 100 will lighten the print, while values less +than 100 will darken it.

+

Setting the Gamma Correction

+

You can control the overall gamma correction of the printed output +using the "-o gamma=value" option:

+
    +
    +% lp -o gamma=1700 filename ENTER
    +
    +
+

Values greater than 1000 will lighten the print, while values less +than 1000 will darken it.

+

Text Options

+

The following options apply when printing text files.

+

Setting the Number of Characters Per Inch

+

The "-o cpi=value" option sets the number of characters per inch:

+
    +
    +% lp -o cpi=12 filename ENTER
    +
    +
+

Setting the Number of Lines Per Inch

+

The "-o lpi=value" option sets the number of lines per inch:

+
    +
    +% lp -o lpi=8 filename ENTER
    +
    +
+

Setting the Number of Columns

+

The "-o columns=value" option sets the number of text columns:

+
    +
    +% lp -o columns=2 filename ENTER
    +
    +
+

Setting the Page Margins

+

Normally the page margins are set to the hard limits of the printer. +To adjust the page margins use the "-o page-left=value", "-o +page-right=value", "-o page-top=value", and "-o page-bottom=value" +options:

+
    +
    +% lp -o page-left=value filename ENTER
    +% lp -o page-right=value filename ENTER
    +% lp -o page-top=value filename ENTER
    +% lp -o page-bottom=value filename ENTER
    +
    +
+

The value argument is the margin in points; each point is +1/72 inch or 0.35mm.

+

Pretty Printing

+

The "-o prettyprint" option puts a header at the top of each page +with the page number, job title (usually the filename), and the date. +Also, C and C++ keywords are highlighted, and comment lines are +italicized:

+
    +
    +% lp -o prettyprint filename ENTER
    +
    +
+

Image Options

+

The following options apply when printing image files.

+

Scaling the Image

+

The "-o scaling=percent" and "-o ppi=value" options change the size +of a printed image:

+
    +
    +% lp -o scaling=percent filename ENTER
    +% lp -o ppi=value filename ENTER
    +
    +
+

The scaling percent is a number from 1 to 800 specifying the +size in relation to the page (not the image.) A scaling of 100 +percent will fill the page as completely as the image aspect ratio +allows. A scaling of 200 percent will print on up to 4 pages.

+

The ppi value is a number from 1 to 1200 specifying the +resolution of the image in pixels per inch. An image that is 3000x2400 +pixels will print 10x8 inches at 300 pixels per inch, for example. If +the specified resolution makes the image larger than the page, multiple +pages will be printed to satisfy the request.

+

Adjusting the Hue (Tint) of an Image

+

The "-o hue=value" option will adjust the hue of the printed image, +much like the tint control on your television:

+
    +
    +% lp -o hue=value filename ENTER
    +
    +
+

The value argument is a number from -360 to 360 and +represents the color hue rotation. The following table summarizes the +change you'll see with different colors: +

+ + + + + + + + +
Originalhue=-45hue=45
RedPurpleYellow-orange
GreenYellow-greenBlue-green
YellowOrangeGreen-yellow
BlueSky-bluePurple
MagentaIndigoCrimson
CyanBlue-greenLight-navy-blue
+
+

+

Adjusting the Saturation (Color) of an Image

+

The "-o saturation=percent" option adjusts the saturation of the +colors in an image, much like the color knob on your television:

+
    +
    +% lp -o saturation=percent filename ENTER
    +
    +
+

The percent argument specifies the color saturation from 0 to +200. A color saturation of 0 produces a black-and-white print, while a +value of 200 will make the colors extremely intense.

+ + diff --git a/doc/sum.pdf b/doc/sum.pdf new file mode 100644 index 0000000000..c2d34fef56 --- /dev/null +++ b/doc/sum.pdf @@ -0,0 +1,949 @@ +%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[10 0 R +11 0 R +]endobj +13 0 obj<>endobj +14 0 obj<>endobj +15 0 obj[14 0 R +]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<>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[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 +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 +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 +149 0 R +150 0 R +151 0 R +152 0 R +153 0 R +154 0 R +155 0 R +]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<>stream +xÚíßoä8rÇ¥nõË<ÉÞíwº= $@Æ#{ܳ;@hlk“}8 $QÈC‡ÍíÞ%Áæön$¸ÿ>ýËÝúAJUEJ¢|懛tó#¿U$‹ê¿¼¹Ñö·â«;ñá£øýÿ¼yoùæ/âCôõÍWû_~øøñ&_º¹ww·7÷ûZß¾Ìÿíý·ï³~›Œöåþ|ܗOûò¸/ßìË?ýûûoů?ÿöÃû÷nßÿ‹ØÜÞ¾€Gq/¾}zS¼Ì¯\fE>Ý­V««‹]ÙþÇêþiê\òquzªrqyý4M.yw¥F*Á­î'Æ%ﺘžËåu2.<Ôí~ +\W¹ø«Äq®‡Ðã•ˍÃ\w\*›æΌ•Ý1³Ìõ(<óòEâW~åY)þµS\wžµ2Û8Ã%…g³\;Âe¬v‡Ì—¼ò¬ÿíè\yèõQ¾™ëÁë©Ì’1¹n½ÞŠ¿Ë²Z·±¶åí(\2ô<ÁÀI!¬–/ç‹Àâ€Á°`à´dðŦåy끸z÷[fšÍ50Ö,‚+ò/³¸>{#”yï\™7Jù²g®<‡‹ Šà¾Â³´¦ … 퀉huŠÑ¹roÔ²é‹+— 9Å`™ãÅ`ž‹,öD.9>–ç÷À%àòë\™çDÙX撡\3Ë\‘çHYZåʏ+íGÛ-ٚÅeƒ'oZ‘z°¿«a’öÎI6Ø0¸Ä`S‹Ÿyйò°È`>‹,ò¾+’ÂX9Ú¹FÂ"‚Í©\éFÈ1ńÈ%ÆÂ"‚-i\¹É \Ø[x}YX-™‘!‚µHÞ2éöՒ•ZgŒJdðá`I5üÄ>¡ žKši¦%碞 F\‡ò™mˆ`e…2+z*‚kˆ`Cf{™\´É°ÄrÅc9dž(ϰ\3œ=Á3D07Ãþ¬¢‰kWä„zà¸ÐBštø(®ldÌP° † ¯†AÑ{ÁIØÃº!­Ÿ!¸2~`6ހ%Ý\±+¢A°u7WèˆÆ“útren rÀf\±cÅôaIWèØp!Ÿô²ƒ+wÆ%Óºtp¥Î .Jœup ÇfZʒV.éàpáæüº•+sp¸pÛHA+RåýA±PV4kå +Š ‰ÊÑÆ…Uù±PÓcÓ…Tù`h®‚dCÀUùÍà\Cœ·p9°·Æ6ęž+sQäт–h¹ÀE‘G; µ–K8ª8SZ踤«ª›úsWF «žìü¯š±?ÿŽÏ4­¨r†õó¾cÀ +¢–(®¥–KVnܖÐJt­‰†KÐbV®¹–ëø1eÃ8‰Ÿ À™^ŽËÓsAI½r|¸)ЖœéµFr­µ\yéùÖ 1³$PsÑyµsZ®ƒíÍ΃0³¤ô35— :¯v®™žë¬’²êA?s`‡k,׳q)¸ÎڞáÍ£ô‰Š+§ÆP\K-×YcÊ^IŠ}è@_{x®¹ž+~~D!eñcÈkíJ(ßÁåé¹²ãßÊ)fˆ˜(Š+$ša'×ZËuø¬ÅáGø-»Na›+¸$Õ ;¹=WtÍ3T£í6_Á•QͰ“Ë×s>쉸<Ȑ‚d¯œ`¹æ§ÚJ®ƒq\PwŽ‘"P½ò¬Àr-ÂgyRr•DвJ8{ªl,ñ\ñócPs¥¬Ujgˆ¸hpåd3lçÊ*8 .ÉÚ,IqºD٘x.ùlj®“I‘6Kr\¸V\ûŽz®”µg‡z ÊÆšÂǏÑpI֞]g/\ŒôÅv®ü( +®c‰{v1ª‹@“YAá*ŽJ¯ã΁SŠ2) ÉƂÆuTzW̯ 剀&k×Qéu\!g~IÔ³î Šë¨ô®Œw†b$HÑÆŒÈuTz WÌÛìïzþó*—dL¯N®ƒÒk¸BÞáLŒyø@’5•ë ôj®œyŠ‘b3ö6 +*×AéÕ\ 7³HªÊ3¦W7×^éÕ\‚™¹#1Ž(QT@çÚ[w¬_W®†Ø%p› +ëP¹[)¸ö½*®ƒÝKFÈ!ÝJ•¨]R6¿ÊuîDK4YÐ 1BÀÊ"¨r­Ë¦Î®ç"œ¦`·ae.ĞÍ\c˲¢Îj\¹†+=òätCL29\jLbÞüG}ÿ³É=?ôi%ÚÓV¸G6*Gòä‹J\±’Kžz‘ Q"ì +Ñ¡Ö$‚ÀºÎ•)¹ÒSå”û"tðÑáLïûw¯´¹-kfÃOÕ¹¢“ÆHz¾UˆçÊ9^ùüþE^WT¹JQc_Ñ >:\b|ɢɕ*¸Ê©(1Ù£î x9Ü`´)irå +®²ÞdäEà¹"–l4lb^4¹Ž¶Zá +Ë–¼“Oí¥Ä%X²QŸ˜§Û{Šuq™«šõÑôT±Zù¬òpŠ}Œ2W\1촇Ô?@Ë¡vñw~¯ÉÛBÉ%\aÅòòR5õêí$ß¿øÔ¿à +)•+eÊás9LV÷¸º£y¿˜T¬ÌÏ&É%xQ”ó\!/ŠrKšÈ¡Ã\¹¡ºÊ•q£Cǹҗ&‡G®˜ºÍñ£C§¹ÄK“ù#WøÒäðÈÅٚŸ—|q2àÊ^œÌc¹&!óåE àܲûѼ<|[Éå¦Ä³e¾\çr£ú©wq]Ùö;ïö6®ó)£í®FšMÀ¹å5‚ë¼oSŸœ‰’kÉáZª¹Ê3éË—`»/5¾Fuj]œs¸æJ®\}¾²Ý—@cƵ.z.OÉ%ÔçüMµ½êrSk]\s¸Ö +®´©r€rË3,×\¾¬U\‡+Pp…ÍÇh™ë`°ºÜ¹Zg®Y“ëY4ü‹ðd÷€rËšk­æòU\õë|(®ÆÀ“œïüÉcx4×¢•kÿ_Â«ô`Qu,‰Šk©tEÕxѨìdžÛn,»¹Ž/Ÿ7N>{•ëå.Î9\FYÅ?P›ØkW)-¥:Äçܞz=W£QõÐé˜Ç¨0jƒá:§)²äÊ.®9\õF¢˜ïi(—gÛ¹¤†+Ös®z£ÚLٛå PaTá:ÿC‘ý¯æò9\µFõ‹§Ïå÷Á¥¸Î×Í¥h”Õìj[®Î̹šº¡¸Î×Í¥»¨Ö˞.©áŠÔ:¯¸Î‡àj6Š•0aTP˜èaxʹ­v±yÁÕl$”Žŵ@qejÿ•iâ(Åu>W³‘–+³Ä+ãÇsRëbó:‚«Ù(T:"×Ã%½†"·®S×ù0\FZ®”F•úpüŠÆ5z]©¸Î‡áj4*W?"ŠkS®¿–Ê.6®óa¸´\À£ +õÀhvU]<Š6«ÞȀ«@sªŸú‰¦‹õë|(®z#-Wl‘k£ÅDÝÅúu>W½‘–+⇇…Úà4Ûû.Ö¯ó¡¸êÂZšê‰KXãò W)T­t±vÇUkÄçš!¹üué§G¿|ÜöXª»X»Î‡ãª5%Å®p…v¸Jù‡åxã°í¨»X»Î‡ãª5jÄQ)–+(pë”BÅUz?”¢‹{ѦrUEõˆ(>ryýrem\Õë|H.ÅÀr#,׈+×Åó§ R¹ªÒúT \²g.©¹Å¡¸Î‡äª6Êj’-=,×҈«håW¥‘¬…æ©\9‡«Ú(¬N0qäêÎ=\÷ÈU¹Î‡åª6ŠÉø[®l\®˜ÃUi”žO•Ï›¼£se®J#YîevŠ7L–•¸$‡«ÚHœÏ¿<WÒ'Wù:š«Ú(mœWºÀ•r¸ªj‘ Øs™,—Q\a;WÎáª6ª®ŒƒÈ ®Òu>è{¥”ºãr=ìßaæ_cºK©;2×UýúZõeC¥7Ì)êªOÔ'Užâ¢”¶wÆ\¢‘¾QÍÓ/O5ë2¸6ÕÍО¸>7W4՗yåçÎϘU\ëêí‡K*N”ª/4LO[üuó¨“k9¨–Ö¢<Áj鵺 ®EQ™šýp…ª£2(σ°’&S¯Ëà +ª–Ò Wþ|ðtQ®[~uíù´^Y—Á5«|t?\éé Pޖ>´$çì +e]>WÖ'W\:±ŽÎÞ¥ä²ÎÉ皺ªm~õ§VwÒ>¹DI äyV5°ôBfM]—:>ÝNâYo\ayNԔþlÔZk¹ÚêvÄó•·mÉê© ײóö|©_,¶Õ¥p•Þ ÛWܲV«sµÔ%q —ѽ켥j«¥.ƒ+1çZàÒmê¡#VÑ×%qōŸôÀ•ë¦Á•s÷£ªpz*­\FïߨîÅ|Y´ré뒸tïgµËUêìuÑÁ¥­KâÊN>½Ëh#{獮BíA‰I]£bøÞžc¡|½Þ0_Ågøž%g‹á{±^¹†çê~Ýò4¹â¿Y®d’\Ý›Ir™,˜_¹†ç2ZXNšk1I.ù7ËL’«{6¡\³ir…/0ð5ü>ŽW®¸¢øâ¾Çg=I.x¡\é  ¿×l¬Òõ²×¥á÷ЍUºº¼Æ}o sTj‡Ë¹@ªKêÃïå«Ä(®prGW(ýÞ[×Ñe_Èï)vm§-ìÒä÷J»px(.˜ZÀ!;ý-òûÍ 82×侏>íÀD[Î9fèœ6€1WçsÔ)s€‘ç˜ètK€qÎ9°°sÅïšëûe¯Ž9°¼[ ¥/Ž­,³nõ”?ṕ¥ÝÔṕÅÝÆ(ƒuluG}€Š#s`¢[ä'œn =¢¯€stN }ް-À¬SBŸ!´p +ã”Ð"H\U§„>FtCë’Ð „ir*ºчÝîë™KNHè%Fº¡À +ýb2r¸.q‰ébŠ™1€ ¹Ä£pP`…Þ›Šúe®l:‚ˆ2,(ÐBïH„˜£">(ÐBLDe.„Ð;"€²+(ÐBïˆpD(´zº"!bõUâJ'Iu +Áá( +¼Ð“Y• !ô³IÈFPåBlÝø“EKLC8Bœ +þA8qHäüá:!ÒË¡… Â#ûAØÌîTy !ˆxfìvA\¸?½Ö ®x }û!„ôè»ÖP„cì †~G$áy‚u?ú¹‚K8?Áð‰w@2Þ±'X„ž(PЄcÜ †€äFž`~)¤Xyä F8}’ŠŽ"NÁ¡ +LjŒrH´qu F9CbÃ179bB瀨£cnrP¶Ú81GTúœ2I€8Ò#*=iG¨MÇSzAéP•t´Ý6IÒ4 NÍÑ aKs-Wä®!Ò¶_  O°¥£fXŽ…€ìÒG2ĔfH@^áŒdˆíy݊G1DI ]¼ÄÇSâㆂ1ÁFˆqz@Á™`‹fXYiçÁ ¿XI© +Î|Õ,¨jk‚ œd™‘½¬ 6° ‹ÉsXC>°rHz€5EVFÔ +œåöÐ1‡ Ï àl sd Þ$Tê#ƄæãPê%ç1÷ï $ÆÇÜi:܀±¦;peu°ÃõfàB*ý@²ž1ðÿÔ0Æ €?S‡°ÖÛ3`)ә_‚ :S¢ÀqEX°µÃ5GreŽ ˜ ¹A8F†Xûª¥qB Õ* +3Cìuá,ùV…™!öªõا»Dsá ±GéÈ l +SCô“‘5^)^`&°}Zâgo†Z.ém‰¹‘tAalˆ=i¢0ò¡`±É•;õ,lr9£õ¸ã <— §¢ñ4.î΢AãrB:°ç½.9+¤q9`‰è£C×薈Ï: qå±B*×Èñ/á›È5ª%Rr_¨\czgÊñ•kÄÀž”4GæmŠÑÒ^è\#M1bbƒkœ)F<Ûep2ŨY.JzàšÁæ\;è©r<®µƒ‘Èä’Â])4áRY©Ã\®áÀx™dl.FÚÏ ŽË˜k ÅóƁ×þÙç^¤0áêßùYšF\}ƒ$Ÿšqõ«Š&Ɇ\}:h£hS®þÀ̒ñ¹È9Ô=-Lìsõ±l1LW·Ãe_ÍïMXá*¤][¼6ï‘®­-Ú²Ù¦p‡«Wî –M.KCv¹)\ã*䝱 ¾µÕ›\üÔê#Õµ½žØå2H¯F¤nÉÅ%³KÕ‡ìò­í>ôÁE̋÷W=¼ç¢®myÂeÇû—÷½||o\ûQë0ȋÕS_ŸÝ'×~ØîVêqº~êósûæ: Üî†ÃêêbW.W«ë§§Þ?r® +$ß¾Iß<È7ï¿ù$n? ùññãÍ×â>º¹òû¿{Ê>#Å;ñX@.òŸþðëÿ}÷ó¢øå‡Ÿ¿ûîO¿}÷ãßËÿÞ6¾··»Æ·w_ß|ïn?ÜÜíšïš½Ë‹ß½»½‰n¢ÿ¸ÝU~w¿ýÝ»»‡H¾ûå¯ç? ?ÿôýo¿ÿõ—C½7Kê§?ÿõçÿúãþºí槯ÞmÿïÓ?ˆÏ?þ(²ÝÙÛNýïßïš&r õÿɄñkendstream +endobj +200 0 obj +6310 +endobj +201 0 obj<>>>>>endobj +202 0 obj<>stream +xÚ+ä2T0BCc3JÎår +ár á +äHÉHendstream +endobj +203 0 obj +31 +endobj +204 0 obj<>>>>>endobj +205 0 obj<>stream +xڅTKoâ0¾ó+F=Ôd P(Ç¥/!µÝl“V{ÈÅI&Å­c§¶býŽ ºl¥UN±?{¾ÇŒ?Œé‹`1éŠz°Jßn—-!­`ÍÂÌ3HËa¬±bŽÒ7BÌ Š"è Át²'•n¸£*»c¡5¨ ÔL¶L@‰¦Ð>>>>>endobj +208 0 obj<>stream +xڕÑÍRƒ0à=Oq–u6€@ÝùםÓ*¡nÜDHÛhI4 íèӛ@;Žé¢6Iîýr™óŒÝ"H2ÿÕmpKƒËéä**@—î.Ëó(mF÷ªîZ.-f[®·‚ï.軫MAÈP&“¡’®…QK»cš£3\´Lvlw¡ôŠIñÃiìšc©6µrÃk+”4×^ïñ¸ˆb„q¥Þ³ÿ_„˜k'z¥ü6–·GƒÖƒ’Äq' ÷*ã?Ùy–”8©´L6L7Ä5fŸýÿ¥º[óúã0•Smg°¬ß¾ð·¡£Øw’E9HZô¹=ßL©ªy‰òJÕ§òاâ›C’¦Ña}Sìϒ¢Àødô4x +~aT¡¯endstream +endobj +209 0 obj +296 +endobj +210 0 obj<>>>>>endobj +211 0 obj<>stream +xڝUMsÛ6½ëWìў‘}8Šul2É´‡ÔêXnsð"—"b`PŠþ}߂ÔG¨L2ÓÑE$w÷½}ûøw4¥ ~Sz7£ù‚òzô~=zóiIÓ%­KšMٜïîi]ÜLéŽV^ۨ햞!rM;ö;ÍûÛõW¤ÝÓt*iw]ÞÝü~’¥Ôu¥å•j"{j¼Ûé‚)K®Ï'WRåö+¦®®¥ç?ÿør…·wþ5dH¾Ío¨å‰ÏI+ï6†ëïÉuÁ þä<Xù@]È¢¹ͱJó£*7T©@Qۖ‹Äõeöv‘ѳ5ú•é³Î½ ®Œò–þѶpûþò³ÊŸÆ]ƒRÅ:© ^Óy6^!*[(_°/UΒ: ´X¼*å]Û4Î÷4StÈè7È·MRgÚ¨SÏ;íÚ`¤vJ…–Æ3€~Ïþ• #ÊGÑÿ>kÑqÀè<'€Ú…˜j+Ã6f}±Ùâ4ŒÀ×É=i2Úò‰6½ÜDþÉYsx¹•~W¨ý”{ÝÄ« !·õª©t^nÇéy¯c5ÔÑÕL¹Sßt§ÇrxnÚªwb¢¨l!¯ì–ÅŠ'<)\j“Ä®U„¸¿»=ôc”ÉU‹öXåCܝòrH%) Ú5ìՅ „\Ô§B—%{‰è„T•|‹–ÇTÖ¸æbÔÔÂëp_(ȁ¯Â¢šçšáÁÖykbFëJEHUo0“NËmt­#^ì`¤Z* 0ó6DˆÜ£Š]·GÄÞø’£Do•ăvŒ@f°kj›K+§H×,`ªŸc±Î‡ç ½â˜Ñ[é@,ÍXùl{FV¬$° †cë-†ñ´ÁÁW—’„Kß}‡l™‹ ÃBª¬ñj  + Å~kW´Fyqª$œO @õ¶#@àäÎ&Ò'6(¹,ù„+ß\zž>>>>>endobj +214 0 obj<>stream +xڍWÁRÜ8½ó}$UŒa€r !,¤HílÆ©½pÑÈ2£Œ-9’ŒwòõûZ²=ŒC¨­Pa<’ZÝï½~m~ÌéÿætvÁ?²>¸ÎŽoßÓüìŠòk——ÙåÅa¾V”+¹6¶²OÛwùwl<§ù~[,I{Z ¯ +jkHRµrOÚ<ѽ ÊÈa +á +’¢ª°3 ü¸¸pÚÞ¾p6Xi«#²Žî‹Œÿ£µ@|¥ '«çgÙ)_­ê•±V[*ìOe<ْŽ¥²(ÆÏ^¹güª…iK!Cë”óGqG§« +±É·Mc]HÁ87£þ ôEKg½-Ãäæ´)l‡ëåDLÜo}PuÖï;½ÈÎy'_¨RåIì hú*©D•ÍP;Šì²Áo$*"|q‘¾Û•ß«Ç6A[”[鍢ZZLôú§:"§¼­ZޚŠõ–o ëŒø ˆ¼³Äܐpá¬%H,-/U–9Û2%–aÜ£.ØÉÕ}ŽžÖ­)œ*<Ÿ kÛz¤ªuÅxtb›Ñ7k°ˆé^æ°¶Â])Q!óž!”Ry?¹UZëF´@¥ØÕ­ŒtÛ&=×bÃÀêBêV®©¶ô+ Qì¸pCâÂVƒ_#â¯ÄV¡Tâ¶á£»-ä1ËYH¹Æsúû +¿ËóÅuk<† QêÔª×-§ÒIAFùG@K’WÀ ·ô¬U‡Îm D"IøÜzÒb¨Ó×¼²Sר0­¿^­]Ìnåp¡rSL¢#€Êg]DÙK[7• +Š©<žg'£à¬cë0Òawì0È ™1ùÂÖB#a7Ikr’õ‚ÈèF?)^ •?,_Hc´ñ,t%V•BT¶ìÄ,Ď³åä^®6KîøÒFÙ#ŸÑ»¿5ÏOėh‡T=XôíªÖ}hϰÒû¦ í¢vs؏˜ÑçhÈX"@©“¯ jþÑÂÜÚzŶ„KÖ0ɤ6Ž ¼×O† Û²Dø€l+áàkgš‡­o£GŒ*z|×§ÁNx-žÕè\k¥\h§Ãše[O=Œ»“͐ý’£õ‰£=¤m´êMWZ§Ãö->V¸Rù·çØè1hÐJÉÐSN£§mŒí '5!A¾} ƒƒ_܉»FA•{¶ÔÎOÇÌN‰Ckj7Ç8oU{«+Î÷·ÕöëÉ4X>õ½hšjh$–Ʀf"Ì,bQF÷fÒlææ©’çJ–æxW»¢Ù)µÉ^"1Ö§*“›‚%ɂè5—jÏhiëaìo„ˆ—õ)as¡ËÁps²6Ÿú +±^RQœSȳ9£¿xy‚osÈý‰3ꥵfAš‹ +¿ñÙT×BnTj¤B³3‰µý…p]³ü#‡èŒ6ÏèoßFdz©ô%z +Ä ¢«7-yHfÏaöIÖ5Wq=¢»ÅìχãÓáqqs;|d@Ï·øœ½Fõ8»+´+-PóR:݄xvw }ž ¹ß`H²‰[~KC’_ïø©hbœÉÅI¨ÎÒJ‡Z4½ú7›>]ºùA·JôN°‹oE°Fvè*XhDTÍ$Á4¾9abwÖm0œE|þ¬ÂvPØ$ÿÇÃM³´¸/<¾;¢ej™/€…ºÆKÙ&E~Àëeê<¬ßUC©ã›ToW½çççÙ{º¸ºJ6póõÃm}Å"—xÏí¸%¿yVǼ,‹ŠÏÒ©Ùåé :çïÎO®2þcâÕ?>åü$ŸQendstream +endobj +215 0 obj +1367 +endobj +216 0 obj<>>>>>endobj +217 0 obj<>stream +xڅUÁRÛ0½ç+¶¹4Ì$'![K)Óvh‡–0½p²«È’+ɘü}w%Û$¦°´»o÷½·â÷(…üIa=‡Å +x9ºØŒŽ¯Î!=MÎ`“ãÝj½NV°É&7Vj/,\Zù$¬;ÚüÂÈ%¤iŒ›-Îã²RÇ»›[àF;é<˜Œô«4V@.•§0W .sÉÁ`PÅ"IL•š«:/++%º{j¡ÓE2'è ¹±ðI4Jx?»aü‘Ù ®™ö‹ðÀt—Â=Òßm—ÀÏBbU_H×ö ™A>>>>>endobj +220 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS041ѳT072PIÑp rt QÐUp VÎO+)O,JU-N-*VðMÌ+MÌÑ Éâ҅èхj2‰™šé™+€ùE™y%©E +.E™e@ Y×®@.s#­endstream +endobj +221 0 obj +124 +endobj +222 0 obj<>>>>>endobj +223 0 obj<>stream +xڕSÁrÚ0½óÛCgÈ ¸6PÀ=¦CŽZœž¸{‹Ê’#Édü÷ݕpÒ¤i;\¬•Þ¾·ï-“ Rúe°YÀr e;¹-&îrÈr(jX¤«$ƒõfE5]ÀîÔà„½•Úóá08íMq&Ü +²Œqóœ/Wi°E#”èßïÔÞ\dE“ñM7N ßá8Ðô +ªîu¯éñ&Lp‹ö*þ„°¿CºÑÏÒ´-á]…¹Î/ ¦Ø–Ra-zå¹éΖɂu_£Ã#õ§439Íu5Œ¶¬£ýâ‚ñÂh$ \;÷΃F¬ÝÐá§Q}ÎD5¯É3é¨!ãÃ{P]ªE‹°ûRì¾½Ù +†Ž>û_í¿w öº¢õðl$Ã/»ÃC90uèèèÂbéíÔ¥ê+Î`oœ?”Vv>D)[ñ€ñ9¥Â«,”¢~ÛçÇÌjkZêèhb¢ë”,…—F;}ê÷\I3xjdÙà…#"ݤ‚îõµ$áïâÌۗÍÒ4Žü׿æj›&9Aèí†Ï»bòuòž5Ùendstream +endobj +224 0 obj +504 +endobj +225 0 obj<>>>/Annots 12 0 R>>endobj +226 0 obj<>stream +xÚ­VmoÓ0þÞ_qB* ÍÚõi lð([ø^â4ǶӪÿž;;I·ve›„6uss/Ï=÷Ü9 Œð'ñ”~³jð1¼»^@rÏ!-ðÙt6‹§æÃe©µj VF(Ç͛ôO I‚i4^Ó¯LíÀî¬ã•…­J¶áPiÃÁ•LVê؆ Éî$>Òø”Cc¹‰!-¹í,dèuǁ9Dz’ç­-!À¼É8>§¼RgL¶‰a#B­™aRr ÚÆø¼Öƽ¥ó>³Þ Ê­¸Ûjó;nŸOã N5:cvÂ:ÐÅ=×á[ÂícZF--CY[ÇÜC®†éªb*ß/¨‚‚šÐWÓ—Ðá5„8Õåpõ-½ºy3"߮ȜEõèÚ ­ÀÖ<…à–øw°Ó l™rDãÃÂöå :_ÎY”÷a 'ò¬ÿ>kŒá"Ð}Љœ¬‘®o2²Ifí#ÄzÂ:”Yç¶çô>ˆV&G4ÿЉÛs!$W¬âO’­M‹qõ$Fó?@ˆVÿD¹Ÿß§'û–;G܎/|÷XíÉ1¾ÆÂ*e·«Q9¨J†Ò ÒŽ:‚¡ÃŽÕ66R@ + ƒ‚38\<·1|Ñ[¾¡æb\Áá@?NT˜q[råµJžÄi†ËcÑå£è~̝ÈÉ!މ™v:±æ#ݽ@@€ Do­‰j”ñQՍߌAºSÁ •§Ab6›±šÓÿ‘ôrvA§Šç‚]~˜ôýŽÕë'À³Õ‡ëقÒÝ1¼Ážßƒj=™Wé`ðö „>n>Ãd|Žé“Å ‹¬`2áßp’pKw š.æBx´F{B7ÌìPc5W91K#UöVþv\‡*g&ï}¨á9·™w(¡à4Î{ÈçE<;ÀùÐŬûÒZô˒ՄwìÙ[Zëa|4‰!@?Œ«V™ð§HÔHÁR׸ ONãGíÊç->êè³{oÃÝ|œº¡9¸°3]ïüÝç5øBq+PMe¾ÄGvÖá~{õOëšz(m*Û]Ëô«ZéGnb)™CÁ´{ +Å¥aÍÝþA‹ãäý~jª¶¢íý¶ ±/SÓðƒu1oã$“I¼€é|NúɇŸn>\§Áòçênuá¶TçOK/Gø¾Õ0IîQðŠfç#ršÓwãÅ~5:ý‡#òcð7?òäendstream +endobj +227 0 obj +916 +endobj +228 0 obj<>>>/Annots 15 0 R>>endobj +229 0 obj<>stream +xÚ½UmoÓ:þÞ_qî$¤^©É’4kÚI|àŽ xk&>;©C Žk;«öï9ÇNË: +Ò@B•¢ÚçýyÎ9þ’B‚¿Š æ ¨»Éåäô*UœAÙÐÝbY@¹™þ[~™$¥)žì!R †.ªu/¸…HŖ’9þ¼4‡FH®XÇáò}yyCÖ§W+HÏâ%ùÐq4_Å9y»hyýU¨ÏàZ×F(Ç ¬sƒ…ÆèÎß_è®cj½Šo9P2 ¦Ožä©DÅ LFáTö=ZL¡Þ f +*ƒåpjÊmà‹®,Æeîõ-»ã`‡ªΡ&)ô”'&}¾‹÷±(Óÿ#˜Q*ßًƚ£öj£9äyVÅâ¨V¶×Jϊåqù^g^dË<;¬‡þ3_-3¤°T Psm6Èþ»‡­’òeóM ¥Ë9l[Q·žlt€€¹ ÞXíÄŸ¼ÞßIԟìÒ!Ò½Z=Ĩ?‚ã^rûõ w ôvÏÓî2Jã_€ñÁPØ Ý,‹»ÒÖ£O¼˜ +ƒPŠýZôñrþN[üz2ʟxõÓ ^ Uã°ß^¯ eëõ_“…]ï²¹6ÚéZË)’Vƒf2j8F3ØÄ[^a‹š;n|·i8ˆî)üe9Iâ·}Rúܼ‚l™Æ+Èά­CêŠøl>>>>>endobj +232 0 obj<>stream +xÚ-‹A‚0÷=Å[ê¢Ø/(ºT” J9@£ÅÔԂ´ÄëkÕ¼·šÌ<A|FH×ñ—ÛK¶(7 ‚ì@Y–l‘/äuv8ïJ Ž¢­4}^jÔh½=*å&eçòÎø¯áÿˆD„iNÉ +_PÆãn¨&Ì`5Š~0ÚGí(ى½5'-endstream +endobj +233 0 obj +133 +endobj +234 0 obj<>>>>>endobj +235 0 obj<>stream +xÚ¥TMÓ0½÷WŒVBJ¥&Û|4m‘¸ .,,$Üzq·1rlc»´Ý_Ï8N¶Ý²° ”S<3ï½y3ö÷Q Süb˜'æPµ£·åèöÝâ%”[HâY”B>Ï ¬ƒB(,5Ñ5Ük&,ÕðIY&…—ß°,ƒ8ve¡¯ Ólu¥eà T Q®¤¦¦ÒlC ؆‚U(="‰¢)„q²á >‰˜m:O>íÉ®žª  ’m‹,‘?ÇæfÑÂE¦(qé¾§‚jŸïÇçå¾ +[ɹ<8 ƒV¢?]É#œƒ=)lSnaË85gþ4JÜÄã”Óª«sÝњ(؝@‰@ùPȽ®è¥Ý„ZWüæxz¸éõ¡Ö›Ý…Àt¸vÀ½•LýzpréõáF„^k¸’9Ö:x\Á#ÕjÝà\‚´VË՗ó'w{nÙý^+iè?—š£p=Duú/旐.¶ÚÙqiöy1Ͼo¬ñó¶\yEñGá¦Ðoú6{ ­4Ì^)©mýe»†~úA¬ƒŠ ax¡ Û ¶ev=îgWõb“f‡Iî·{äóëk⽸¾*!|- è:XD³#F˜¨×.JçÇd¾lÛõø)á¥ÂgÙv„ÿ† #Wv͕Îò3×âñ}éºÃ»³ø›‡)›g˜8u©qìVåèóè'½G{®endstream +endobj +236 0 obj +539 +endobj +237 0 obj<>>>>>endobj +238 0 obj<>stream +xڝV]oë6 }ϯ 2 kØ³×Iô¡·í.ЮYí¾õE±•ă#y’Ü$ûõ#e;7‰=ܛ¢HE‘‡<<"ûÏÀ¿|Gôn_’Áï_Sð}H–LÝ¢ièN!ɮރh×ÉßxÁk.\݅õAØ€ß⸠áý +½';ßw£ä"]s=© ð½]0›l6ï×µo‹æãð î_ž}¯‹öÃ/¾âƒ²ä;sov¡ë7'¨¡¿ó½›‹Qžú |x:†œºQ„˜ãñ dàaõÞՉbB—Lq‘î»àÇVØð,g`ö˜jY©”_„õV–\õJÇP2úmÛ_óInûbÚãÏÆ|® +“Ï+UJÍ»¡­Õ)kó§ÓfjÅïYÉÒÜôðn͐6ö3Ǿg>>>>>endobj +241 0 obj<>stream +xÚ¥U[o›0~çWUª”Iƒa`„LêÚ¥Ó¤­k:i.˜ÀflfL³ýûÛi.R›¦©òás¾«IþxBüG§P´Þyî½»˜‰ƒò +ÏҌ˜¯åhδnÄtÍà\5‹Z Ö÷oò_¸!n܏'AjÆÊ +* B+É횼gŠrwëu•=éT#4+Aº4 ýӉ/·ÆÏ:¦ +&ô ÈN7R|pô!Lœ\ôà;éåÈ¡#¬ï`ŠD!T g‚¶ f—ùìf׋oÀÜü |`=,£š)T†ÎH²A;Ü`2±1ò–5"ýÛâÆèîJIÕoÜhtàH·÷ãȑn'þ™¶-…©TŠÆùQ¹/,H±9(}»tf­»Ã ãðõ‘“ùÓ¡¿²M~‰¡ÍÙ_ ߭ͧ/wެ•ä\.MR.”h×ñ(9¬$›¢3žûC›¾Ú;ô‹ÕLkªhæ{¸Â'_DQïUdÚ*ºf·+è™î-°X`|¡ AàWjˆHôh‹®Ð½&¿6ø6îâ[Ì£­ŽìõΦ’í3—ÈVææž·eïÒjúå}­X¯,[É#aL MR'ñÓÍNj|˜Þ^Ía.+½¤ŠÁmonÎ7*ÊͺO’·ü1þ¢îý£HÆ ¾ovˆÄæÁ,÷®½ÿMÚòendstream +endobj +242 0 obj +521 +endobj +243 0 obj<>>>>>endobj +244 0 obj<>stream +xڕVÁrÛ8 ½û+0éŒ3µTÉv§;=dÓtÚC»ÙF½åÂX°Å„U’ªã~}R²%M±I RHè—ÂdÆÏ¢ü› Þ~<…t![ÒÞlžòß|x…ÎÉj®@¸+„/¬de²[2™BšƒhrÏØà«6¥Pjã-j¶(ƒƒ`сÓ~¯&%Ké,èe8ndåÐĐiùmcÝc/E¿ø*Ҍ"ÔùE +—îýO¡|5â3Þ82rU<±ìt½]U¾Û¸ÑÎé²Ý];©+û.äœÀi`‰¨ÛÆî ¤üòT « XJ…•(.¾fßþl²‡ö`›m*[ìçø„Ñ®¸'ڕ7#êÃö¬ÝzM†TìUSbå@Z_®P> §ÖTdû Xá…ϤoOÆ´KKÚ@OŽË2>÷eMÆÆ¥!]nà’Còü£³ RŸ÷úêê uCÊP ÈрZ#Yën-]±SaՔ7hFp«oÀI§®‡m:Á÷Ù±z}ôÅnrá0†3eõÎýêù›7p‡›µ6yh’‚ê¯X˜»….=—JVŽH'”\È_˜¿\•;*ž,;ñ}Ï÷ ?eóÏ%çÿ_h…gù^j¥ôš‡FÛ8 êšøYX…ç=éý1û\¡¯”h;<„¿–Ú‹÷5šr¹·]Ë^GâÕ*ÌKdråE;…ò€ðÅôöÂԎ°—µa©ßŽmà~CJÖz/,.iüÓ ž' Ør¹éXöDPŸTÂ÷I;¯½þ¯‡½h•~‰{îâë#8ëµDš˜N)vÇÒZ*ÅÙ«](aY÷µB‡$aw~é… ;0Œ«ÍRKÁžïq’ô¿û‘‚ú)·¦æô¦>bÐ!™ŒgAòL2Õæ y÷4½éø1¿­Vg¶ý셤x4Ê{T–Iñ£rªÂf/W?4'I’܏§Ìc°ÜK.MîçÞ O ÇGûîGÔ©ð^0É1|`ZIúßí…/Åî—CÑl'Ÿ„ªÚ–oe£œ$ρÛí·ÝEìXªŸ]nZV~4hÝs£àÌß:?5¬ÆŒœ‘ʸo«çCÑàÃ1 íÝ7èÄÃI; 8'ú,(yF†cžºrF+ÓF7¦_)TøSZŠÒ’y ,NãSºfÍã>÷áÛÙÇ "8ÿ~yWzéÖ<å¿[4–n\}`Ø< +VÑÉ8a£tʋ“Ù$>†äo—µ‹lðÿà7öEÝendstream +endobj +245 0 obj +959 +endobj +246 0 obj<>>>>>endobj +247 0 obj<>stream +xÚ¥VQoÚ0~çWœ&M£R“:i0©m×v•ÖµƒôaR_ \‚Û$fNRÆ~ýÎq¡0iB +äøüù¾óٟu`ôq ï©Ó¤stN® m‚PÇüA‚Y÷(xî0°G¿|„x–„yg¯<.BcÊ„«ïÁÕHƒO®=Ðè,b±N‡¶¯‡só·_ýÝ-¶‡t«¨H0ÍAdÀ!-’ *•L4ƒ\‚þâé .fÍ 'ò©Œ¥Ò™’9υLmГ†2ŽåR¤ä|ãZÏ©:ëfE’p%þ`E2çi„°’ŧ8† –"ŸÃL„!*U9KöÙdÝ«²v<ÇÖR™íiÎ{%"‘òXƒºÌÓ³¼^êÙÎ&hbWA‡ÙŒ°õctŽëØ zßÀ@ÿt%­Æ{À.s7`öxÐ{[à²ÖËá¸ôú®YÁÎÊô«ä +µ0å\kü‰ºÒ–Tº†ï©ò}bm«Ê€[ª2àU¥–žk–èF!¦M5UîQ¯4]P‹n¢‡y>Q·dÀ-ð~A§®éc“SÑ}½ k-¥hkU#©q}âm«Æ€[ª1àýjw]ó¦’ñËʚ¬cìm÷RÁ|z¶UaÀ-Uð^ÞСmE9ÞñˆŽ ޔr›ÎD$›B.•H2ù^wyth´>*p;%x¿’¾c¶þåŠoí–í]±–òMDóÜJùëf¹Iò{íO€ +ÜR’ï9׆`ÎýöXåLç³ç"ËKƒ ó¼P¥}ÀS÷RŸöOG Cr¸MxôƯضÁ} oÌj‚³ª)uÀ‹’—3§ÙÀ4{m`ˆTÏ%ô\ǐÓ9Äâ÷’ÊÉ#²,9Æø*2"­ªiè5z¯¥ï¦ý_Þ^qüÓݳNE(°éݍ’”†_º½Ë˜ 绩‹¿PrVL‰„¿)È$æÓ‹n Ör.r$ Hóc —éZaî.DAìäðdõ oÖ8ü+L0^Ñzä˜fh)ƒÚò={žÇÌ|_Fç×Xpùø0†± ó%§®{̐¨îxZ˜Ë€eFY}—í6ÞWÊè©Ðt» çõ=Ú¤å g}_øÑù 3ü}µendstream +endobj +248 0 obj +839 +endobj +249 0 obj<>>>>>endobj +250 0 obj<>stream +xÚ-Ë»‚@„á~ŸbJ(À=BPJ¼-LTÍF„Èa‰¯¯¨™©þä{ +‚üŒDóoØ°X¤k+Pú1VK .Ý5I¶ù9CÖWö¥|Ôȓ2“z¸Ü +ïg¼?¢hŽI?À7$e;¶15ì]ã0i7Æ.ú +ÊàØ©ZÏhÏâ"Þɉ*ëendstream +endobj +251 0 obj +143 +endobj +252 0 obj<>>>/Annots 156 0 R>>endobj +253 0 obj<>stream +xÚ͛QsÜ6€ßý+ôØÎœ7")JâcãÔ¹v.­/v¦/y‘mÙÞvµòiw“Ëýú#HP"•dfj{Ó7Ÿ,AùÏ ËrýË*ž‰2»éN^_¼:WSÙÕ]ÆJ±âYYIýóêö‡«æzÓfý]vÖo÷ív¿ûñêϓŸ¯NòU®)ðƒÁ÷oa•¢Öj]&äªÀÁ&»„Ìä‡ûìչ̃G‚ž²»ڻ榅‡L9j±ZX‹­Žþ[´“(ÁP\êŸ]V±Ãa¨ ¥ÝUò pùe·o»lñ!·ÓÊÅJ†OÁyÃúýS;|Z·Ÿ¿mô‚­Ô=fWÆVµ~åºX•8X´+X“q-¡ßíMsètx/[Ô#j‹òJ[%àã<ò"6å:ڏ¦œüœe ß±¶¦þuíߓ¾fY—ZT¿#Ì9"µ5+ý]|;‹”ÓeЧÙeRé˜08œ‹a½Ý¯·÷Ë8ÐeJê&Àá4âbŸ §¯_±ÈWUHÃy¤EF¾x¸úÓ7™_JýaØAZB“•À•æ¡%<3aµg +ðƒÿ œn‰9Ú#hßaâóp~äõzì%pé1|Ë1éèÍG™•e™':¹,¯µ!°GP{ó°í7ýý—o›Q2>im/"æ,¤Y ô;–8 ÍY”vaøµ¿Þ}ÛLu3ŠàÚ]Vªq@Et¦9Û4»]»[ªúŽØ*1ƒh§Bú/M>1Ò <·«Áùz³o‡ƒèÚCu ÄŒ’—&ï–5,‰f@%¯¼´ÞËùÈB>bs<Î#îͰþ´hc‘Y:Ò$mÖB “ˆëZ‡‡Pf-”‰´ßÚýç~øK¯– yùhJÕTc@áZ”¥IDPGÚ¿'®EYلÄéÂÕáM}ðí,Rb…«ÃèµA…œF·YÌxê&ÓÌ~%œF֞ZÐ=eø€Ê¹õpQñ2ËG@¥ô¾' + Ñ–Ô _äQUä”Ân˜*iì ­ +.d»ŠÃu·ÞÓfõè°¹‡Mhð,œ/Ƶ¤Ý>òôíÆ¶iNqw=‘}u +ùüWsE¸%[,­Ù‹¹<æi½¡ƒe¦Îáë22ÛÌ®:g}OÎÑ$ó2Äã4â‚3©B”˜U!Ùy,® ‡:¢PqŒŽ°ÜÖ  +¤c¸)Ë/ÛÈ7çá 5BiÀq¾N*T|}ȋPÐ4'`{Iûu¿]*TøQl?cNaÂ얪Ò½NaŪN[b<¢mtÖ!ç‘÷î°Ù¯7-•'´m`wÏúÇõÒ΅×/còÜJ&«˜阜áŽí¡½ù+!!^U:“xœf U‰§ ”)"|Î3¯*!?> y6eÏ ðrßìÔê4¯†=mÈCäÝ =Ñ5ôõ5M}õ¶N År¾z§÷|ô¸ƒ©àUÏú®k¶·§ÿZoŽ`ªüïhE‡¨¨+[SAÄØ¢¢®mm‘¢o¢(Àã4ââ!êH6~Î×^Õёgâ'à9¦…èÈ3òPy)!:ÒÔWoëR,ç«ëå¹^ +C˜ +^õöz!ÙæÏÓ‰E«Ypt´BÑkd´ºsÖ³f{Ónèp:\Ùø0®vZF CO–L(²bƄ*µZNÚPÈäó—vˆûµ_ð+ޤ‹®È¾‚(*{¼¨_Çþ=©¯ ŠÚV ‚î+8¼Ùþ|;‹”X_Áaôv=186¶·ÍpK6¦—†ŽÚŒW-¡êe>MÔó—ÔŽ®z¡›þÂáÂ"GÑBfÙ­L24ƒ´^€Ò.ÇoÛm;4¢øÐî&xÎ#޶¨8®cþeãš*Fp†Ý¹ªp´h]¸èÂ9.•í¦½‰t­<¦=TáœOYßôê«ßKÌp(€¸«/Îhœ‰©ç§ÓóÔ5¬„;,! Ü«ö‡añæPþgkÑ Ík<Š€ƒP;"ƒ4Ç[PÑn„O„‚“Ã"ëóéõÔa큎C„ý>¬Û­®8u2Y¸­P¿L«–qÚ\¹ûPг#Ê\¥ö¹= ¸îtx'`óð–òŤ •?µ!  éu¿ ªþIü +{…v›»¾%ÛĞ:$5Ús,-¬€õwTÎQž/x.ç¾ÐŽCÆ­¯ +Ù¾ñ䬛ÇÅöæÓß+Œ†fËÌÒbGdhÖxÑ,y=Ÿ`Þ6x‚@$µüxÊžPé‡(@Ôûf{Oe‹c àPqdXyÚ°+…ÿ‡,@ÖEs¿Ø·{îZ(e%du;"££TØ»J[HF¾Iôß ¨”v“§î„õ"„¡Â^ëû‡ý¶Ýí–n½½PMÊDÄoõYãH©>¹twýáøÖ^>ß ”)µ§§nÛHÕ †{Ût]Cw‘ªÇóò+ + î¬ÈM‹eÂómâXär/ðöb Æ-x¤kà wg±ý/Ññh]¦à !@ã4¢èÝYñòûÝïþH¸»h"–«Xµ%òïùD݆°OG‹Kù@ªÌç¿( +XÔo‡îšìoxú¶Ž®g4+`iäZæéBSC’°¤³‡fhnà¾Q+y M,òÑA®V²–xA½¦¯¬QRÍ9-à@¿lo~pë ":•Lb3Ë “±B‹•«ú{âÒñmäø|'€À”Èt08 –›ŽgÃ'à¡@™PiyÚ°ä£YÃèt,8M¢BÓ@zÿN L0:4=eØTóßÌ ŒÏ'¾Œ Ӝû_Îc_.¾¯âs|F>ß ˆôŠÏÁl 0@Xb˜:ž£€‡ÈKSdqfò[ÀBw ¹ßºÅX=Ó5ÈX`Àîy*=íˆ + ¦òï*=G¾q\ÀGLŒVÀ5¿f vcÍӇ柿: +8Ú»f¸_/ºR>ÿõiVD¼ZM—–݈ôj5މÖný;sñºØ•!Î\<yïåOèXäj9üãUsù˄C»ÍJ.¿tdôy0ë!¢q¾H8c9®>•…ÂZ é숌J™c­tÓl"¹f"ږ” +ù(à€‘\3©Ã6ŽB˜p0ãî…ÎÏ ï³¢x•Z—Ï G¤GÞ¬þéöÏÃ.Ö&œ˜*à®wð'r“ÜWŸ@— „¡Âþy ۄ“º½¾RÏ`(€°?\é<öñGú +K=ô?C" +T u†§ å0ìêC + «ÙRµð¤ l97›@ÊO}y:«Ü]P7aÃE¬Ráx)<=VÝl,ñàÒº(’Žh'u[]Ìa(à®è7ûÃ`Ž¿¨ãÓn;B& + ó#”Ÿý@Ŭé̎{†tˆ¤bÖ×îLWJÎX(P¸ƒZª0iÃ%Ã|ôýذȢb¶úûw]ÌüK¡Wç5^°8e&ÉK…·"Þ¼ÿéü*;ÍÎ>\\f—ýÝþs3´Ù‡´SÞ5ÛC³}! ÍqZqóÛ­Ñÿ>ù?7±½endstream +endobj +254 0 obj +2716 +endobj +255 0 obj<>>>>>endobj +256 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS041ѳT072PIÑp rt QÐUp VÎO+)O,JU-N-*VðMÌ+MÌÑ Éâ҅èхjÊÌ º†pr¿%endstream +endobj +257 0 obj +102 +endobj +258 0 obj<>endobj +259 0 obj<>endobj +260 0 obj<>endobj +261 0 obj<>endobj +262 0 obj<>endobj +263 0 obj<>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<>/Outlines 258 0 R/PageMode/UseOutlines/OpenAction[204 0 R/XYZ null null null]>>endobj +xref +0 298 +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 +0000000907 00000 n +0000001012 00000 n +0000001043 00000 n +0000001094 00000 n +0000001179 00000 n +0000001203 00000 n +0000001307 00000 n +0000001412 00000 n +0000001517 00000 n +0000001622 00000 n +0000001727 00000 n +0000001830 00000 n +0000001933 00000 n +0000002037 00000 n +0000002142 00000 n +0000002247 00000 n +0000002352 00000 n +0000002457 00000 n +0000002562 00000 n +0000002667 00000 n +0000002772 00000 n +0000002877 00000 n +0000002982 00000 n +0000003087 00000 n +0000003192 00000 n +0000003297 00000 n +0000003402 00000 n +0000003505 00000 n +0000003608 00000 n +0000003712 00000 n +0000003817 00000 n +0000003922 00000 n +0000004027 00000 n +0000004132 00000 n +0000004237 00000 n +0000004342 00000 n +0000004447 00000 n +0000004552 00000 n +0000004657 00000 n +0000004762 00000 n +0000004867 00000 n +0000004972 00000 n +0000005077 00000 n +0000005182 00000 n +0000005287 00000 n +0000005392 00000 n +0000005497 00000 n +0000005602 00000 n +0000005707 00000 n +0000005812 00000 n +0000005917 00000 n +0000006022 00000 n +0000006127 00000 n +0000006232 00000 n +0000006337 00000 n +0000006442 00000 n +0000006547 00000 n +0000006652 00000 n +0000006757 00000 n +0000006862 00000 n +0000006967 00000 n +0000007072 00000 n +0000007177 00000 n +0000007282 00000 n +0000007385 00000 n +0000007488 00000 n +0000007592 00000 n +0000007697 00000 n +0000007802 00000 n +0000007907 00000 n +0000008012 00000 n +0000008117 00000 n +0000008222 00000 n +0000008327 00000 n +0000008432 00000 n +0000008537 00000 n +0000008642 00000 n +0000008747 00000 n +0000008852 00000 n +0000008957 00000 n +0000009062 00000 n +0000009167 00000 n +0000009272 00000 n +0000009377 00000 n +0000009482 00000 n +0000009587 00000 n +0000009692 00000 n +0000009797 00000 n +0000009902 00000 n +0000010007 00000 n +0000010113 00000 n +0000010219 00000 n +0000010325 00000 n +0000010431 00000 n +0000010537 00000 n +0000010643 00000 n +0000010749 00000 n +0000010855 00000 n +0000010961 00000 n +0000011067 00000 n +0000011173 00000 n +0000011279 00000 n +0000011385 00000 n +0000011491 00000 n +0000011597 00000 n +0000011703 00000 n +0000011809 00000 n +0000011915 00000 n +0000012021 00000 n +0000012127 00000 n +0000012233 00000 n +0000012339 00000 n +0000012445 00000 n +0000012551 00000 n +0000012657 00000 n +0000012763 00000 n +0000012869 00000 n +0000012975 00000 n +0000013081 00000 n +0000013187 00000 n +0000013293 00000 n +0000013399 00000 n +0000013505 00000 n +0000013611 00000 n +0000013717 00000 n +0000013823 00000 n +0000013929 00000 n +0000014035 00000 n +0000014141 00000 n +0000014247 00000 n +0000014353 00000 n +0000014459 00000 n +0000014565 00000 n +0000014671 00000 n +0000014777 00000 n +0000014883 00000 n +0000014989 00000 n +0000015095 00000 n +0000015201 00000 n +0000015307 00000 n +0000015413 00000 n +0000015519 00000 n +0000015625 00000 n +0000015731 00000 n +0000015837 00000 n +0000015943 00000 n +0000016997 00000 n +0000017031 00000 n +0000017065 00000 n +0000017576 00000 n +0000017625 00000 n +0000017674 00000 n +0000017723 00000 n +0000017772 00000 n +0000017821 00000 n +0000017870 00000 n +0000017919 00000 n +0000017968 00000 n +0000018017 00000 n +0000018066 00000 n +0000018115 00000 n +0000018164 00000 n +0000018213 00000 n +0000018262 00000 n +0000018311 00000 n +0000018360 00000 n +0000018409 00000 n +0000018458 00000 n +0000018507 00000 n +0000018556 00000 n +0000018605 00000 n +0000018654 00000 n +0000018703 00000 n +0000018752 00000 n +0000018801 00000 n +0000018850 00000 n +0000018899 00000 n +0000018948 00000 n +0000018997 00000 n +0000019046 00000 n +0000019095 00000 n +0000019144 00000 n +0000019193 00000 n +0000019242 00000 n +0000019291 00000 n +0000019340 00000 n +0000019389 00000 n +0000019618 00000 n +0000019770 00000 n +0000026151 00000 n +0000026173 00000 n +0000026286 00000 n +0000026388 00000 n +0000026408 00000 n +0000026539 00000 n +0000027300 00000 n +0000027321 00000 n +0000027461 00000 n +0000027828 00000 n +0000027849 00000 n +0000027989 00000 n +0000028903 00000 n +0000028924 00000 n +0000029064 00000 n +0000030502 00000 n +0000030524 00000 n +0000030664 00000 n +0000031556 00000 n +0000031577 00000 n +0000031690 00000 n +0000031885 00000 n +0000031906 00000 n +0000032046 00000 n +0000032621 00000 n +0000032642 00000 n +0000032805 00000 n +0000033792 00000 n +0000033813 00000 n +0000033976 00000 n +0000034861 00000 n +0000034882 00000 n +0000034995 00000 n +0000035199 00000 n +0000035220 00000 n +0000035369 00000 n +0000035979 00000 n +0000036000 00000 n +0000036158 00000 n +0000037202 00000 n +0000037223 00000 n +0000037363 00000 n +0000037955 00000 n +0000037976 00000 n +0000038125 00000 n +0000039155 00000 n +0000039176 00000 n +0000039334 00000 n +0000040244 00000 n +0000040265 00000 n +0000040378 00000 n +0000040592 00000 n +0000040613 00000 n +0000040768 00000 n +0000043555 00000 n +0000043577 00000 n +0000043690 00000 n +0000043863 00000 n +0000043884 00000 n +0000043939 00000 n +0000044044 00000 n +0000044188 00000 n +0000044291 00000 n +0000044396 00000 n +0000044561 00000 n +0000044669 00000 n +0000044784 00000 n +0000044889 00000 n +0000044997 00000 n +0000045105 00000 n +0000045221 00000 n +0000045319 00000 n +0000045485 00000 n +0000045602 00000 n +0000045721 00000 n +0000045845 00000 n +0000045970 00000 n +0000046120 00000 n +0000046261 00000 n +0000046370 00000 n +0000046522 00000 n +0000046661 00000 n +0000046791 00000 n +0000046915 00000 n +0000047051 00000 n +0000047178 00000 n +0000047301 00000 n +0000047417 00000 n +0000047566 00000 n +0000047695 00000 n +0000047832 00000 n +0000047962 00000 n +0000048087 00000 n +0000048190 00000 n +0000048327 00000 n +0000048432 00000 n +0000048571 00000 n +0000048705 00000 n +trailer +<> +startxref +48891 +%%EOF diff --git a/doc/sum.shtml b/doc/sum.shtml new file mode 100644 index 0000000000..4883760bf6 --- /dev/null +++ b/doc/sum.shtml @@ -0,0 +1,562 @@ + + + + + + + DRAFT - CUPS Software Users Manual + + + +

Preface

+ +This software users manual describes how to use the Common UNIX Printing +System ("CUPS") Version 1.0.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. + +

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. + +

Document Overview

+ +

This software users manual is organized into the following sections:

+ +
    +
  • 1 - Printing System Overview
  • +
  • 2 - Using the Printing System
  • +
  • 3 - Standard Printer Options
  • +
  • 4 - Checking the Status Via the Web
  • +
+ +

1 - Printing System Overview

+ +

This chapter provides an overview of how the Common UNIX Printing System +works. + +

The Printing Problem

+ +

For years the printing problem has plagued UNIX®. Unlike +Microsoft® Windows® or MacOS, UNIX has no standard interface or +system in place for supporting printers. Among the solutions previously +available, the Berkeley and System V printing systems are the most +prevalent. + +

These printing systems support line printers (text only) or +PostScript printers (text and graphics), and with some coaxing they can +be made to support a full range of printers and file formats. However, +because each varient of the UNIX operating system uses a different +printing system than the next, developing printer drivers for a wide +range of printers is extremely difficult. That combined with the +limited volume of customers for each UNIX varient has forced most +printer vendors to give up supporting UNIX entirely. + +

The Common UNIX Printing System, or CUPS, is designed to eliminate +the printing problem. One common printing system can be used by +all UNIX varients to support the printing needs of users. Printer +vendors can use its modular filter interface to develop a single driver +program that supports a wide range of file formats with little or no +effort. Since CUPS provides both the System V and Berkeley printing +commands, users (and applications) can reap the benefits of this new +technology with no changes. + +

The Technology

+ +

CUPS is based upon an emerging Internet standard called the Internet +Printing Protocol, or IPP. IPP has been embraced by dozens of printer +and printer server manufacturers, and will be supported by the next +Microsoft Windows operating system. + +

IPP defines a standard protocol for printing as well as managing print +jobs and printer options like media size, resolution, and so forth. Like all +IP-based protocols, IPP can be used locally or over the Internet to printers +hundreds or thousands of miles away. Unlike other protocols, however, IPP +also supports access control, authentication, and encryption, making it a +much more secure printing solution than older ones. + +

IPP is layered on top of the Hyper-Text Transport Protocol, or HTTP, +which is the basis of web servers on the Internet. This allows the user to +view documentation and status information on a printer or server using their +web browser. + +

CUPS provides a complete IPP/1.0-based printing system that provides Basic +authentication and domain or IP-based access control. Digest authentication +and TLS encryption will be available in future versions of CUPS. + +

Jobs

+ +

Each file that is submitted for printing is called a job. +Jobs are identified by a unique number starting at 1 and are assigned +to a particular destination (usually a printer). Jobs can also have +options associated with them such as media size, number of copies, and +priority. + +

Classes

+ +

CUPS supports collections of printers known as classes. Jobs sent +to a class are forwarded to the first available printer in the class. + +

Filters

+ +

Filters allow a user or application to print many types of files +without extra effort. Print jobs sent to a CUPS server are filtered +before sending them to a printer. Some filters convert job files to +different formats that the printer can understand. Others perform page +selection and ordering tasks. Backend filters perform the most +important task of all - they send the filtered print data to the +printer. + +

CUPS provides filters for printing many types of image files, +HP-GL/2 files, PDF files, and text files. CUPS also supplies +PostScript and image file Raster Image Processors, or RIPs, that +convert PostScript or image files into bitmaps that can be sent to a +raster printer. + +

CUPS provides backends for printing over parallel and serial ports, +and over the network via the JetDirect (AppSocket), Server Message +Block, and Line Printer Daemon protocols. + +

Printer Drivers

+ +

Printer drivers in CUPS consist of one of more filters specific to a +printer. CUPS includes a sample printer driver for Hewlett-Packard +LaserJet and DeskJet printers. While this driver does not generate +optimal output for different printer models, it does demonstrate how +you can write your own printer drivers and incorporate them into CUPS. + +

Networking

+ +

Printers and classes on the local system are automatically shared with +other systems on the network. This allows you to setup one system to print +to a printer and use this system as a printer server or spool host for all +of the others. If there is only one occurrence of a printer on a network, +then that printer can be accessed using its name alone. If more than one +printer exists with the same name, users must select the printer by specifying +which server to use (e.g. "printer@host1" or "printer@host2".) + +

CUPS also provides implicit classes, which are collections of +printers and/or classes with the same name. This allows you to setup multiple +servers pointing to the same physical network printer, for example, so that +you aren't relying on a single system for printing. Because this also works +with printer classes, you can setup multiple servers and printers and never +worry about a "single point of failure" unless all of the printers and servers +goes down! + +

2 - Using the Printing System

+ +

This chapter shows you how to submit, query, and cancel print jobs to +different printers. + +

Submitting Files for Printing

+ +

CUPS provides both the System V (lp) and Berkeley +(lpr) printing commands. To print a file to the default printer +on the system (or your only printer if you have only one) you just need to +type: + +

    +% lp filename ENTER
    +
+ +

or: + +

    +% lpr filename ENTER
    +
+ +

CUPS understands many different types of files directly, including PostScript +and image files. This allows you to print from inside your applications or at +the command-line, whichever is most convenient! + +

Choosing a Printer

+ +

Many systems will have more than one printer available to the user. These +printers can be attached to the local system via a parallel or serial port, +or available over the network. + +

To see a list of available printers, use the lpstat command: + +

    +% lpstat -p -d ENTER
    +
+ +

The "-p" option specifies that you want to see a list of printers, and the +"-d" option reports the current system default printer or class. + +

To print to a specific printer, use the "-d" option to the lp +command: + +

    +% lp -d printer filename ENTER
    +
+ +

or the "-P" option to the lpr command: + +

    +% lpr -P printer filename ENTER
    +
+ +

Setting Printer Options

+ +

For many types of files, the default printer options may be sufficient for +your needs. However, there may be times when you need to change the options +for a particular file you are printing. + +

The lp command allows you to pass printer options using the +"-o" option: + +

    +% lp -o landscape -o scaling=75 -o media=A4 filename.jpg
    +
+ +

The lpr command has no command-line option for printer options. + +

The available printer options vary depending on the printer. The standard +options are described in Chapter 3. + +

Printing Multiple Copies

+ +

Both the lp and lpr commands have options for +printing more than one copy of a file: + +

    +% lp -n num-copies filename ENTER
    +% lpr -#num-copies filename ENTER
    +
+ +

Copies are normally not collated for you. To get collated copies +use the lp command with the "-o Collate=True" option: + +

    +% lp -n num-copies -o Collate=True filename ENTER
    +
+ +

Checking the Printer Status from the Command-Line

+ +

The lpstat command can be used to check for jobs that you +have submitted for printing: + +

    +% lpstat ENTER
    +Printer-1 johndoe 4427776
    +Printer-2 johndoe 15786
    +Printer-3 johndoe 372842
    +
+ +

The jobs are listed in the order they will be printed. To see which files +and printers are active, use the "-p" option: + +

    +% lpstat -p ENTER
    +printer DeskJet now printing DeskJet-1.
    +
+ +

Or to show the jobs and the printers, use the "-o" and "-p" options: + +

    +% lpstat -o -p ENTER
    +Printer-1 johndoe 4427776
    +Printer-2 johndoe 15786
    +Printer-3 johndoe 372842
    +printer DeskJet now printing DeskJet-1.
    +
+ +

Checking the Printer Status from the Web

+ +

Since CUPS uses the Internet Printing Protocol, it is also a +full-featured web server. To use your web browser to monitor the +printers on your system, open the URL +"http://localhost:631". From there +you can view the status of classes, jobs, and printers with the click +of a button! + +

Canceling a Print Job

+ +

The cancel command cancels a print job: + +

    +% cancel job-id ENTER
    +
+ +

The job-id is a number that was reported to you by the +lp or lpstat commands. + +

3 - Standard Printer Options

+ +

This chapter describes the standard printer options that are available +when printing with the lp command. + +

General Options

+ +

The following options apply when printing all types of files. + +

Selecting the Media Size, Type, and Source

+ +

The "-o media=xyz" option sets the media size, type, and/or source: + +

    +% lp -o media=Letter filename ENTER
    +% lp -o media=Letter,MultiPurpose filename ENTER
    +% lp -o media=Letter,Transparency filename ENTER
    +% lp -o media=Letter,MultiPurpose,Transparency filename ENTER
    +
+ +

The available media sizes, types, and sources depend on the printer, but +most support the following options (case is significant): + +

    + +
  • Letter - US Letter (8.5x11 inches, or 216x279mm) + +
  • Legal - US Legal (8.5x14 inches, or 216x356mm) + +
  • A4 - ISO A4 (8.27x11.69 inches, or 210x297mm) + +
  • COM10 - US #10 Envelope (9.5x4.125 inches, or + 241x105mm) + +
  • DL - ISO DL Envelope (8.66x4.33 inches, or 220x110mm) + +
  • Transparency - Transparency media type or source + +
  • Upper - Upper paper tray + +
  • Lower - Lower paper tray + +
  • MultiPurpose - Multi-purpose paper tray + +
  • LargeCapacity - Large capacity paper tray + +
+ +

The actual options supported are defined in the printer's PPD file in the +PageSize, InputSlot, and MediaType +options. + +

Setting the Orientation

+ +

The "-o landscape" option will rotate the page 90 degrees to print in +landscape orientation: + +

    +% lp -o landscape filename ENTER
    +
+ +

Printing On Both Sides of the Paper

+ +

The "-o sides=two-sided-short" and "-o sides=two-sided-long" options will +enable duplexing on the printer (if the printer supports it.) The "two-sided-short" +option is suitable for landscape pages, while the "two-sided-long" option is +suitable for portrait pages: + +

    +% lp -o sides=two-sided-short filename ENTER
    +% lp -o sides=two-sided-long filename ENTER
    +
+ +

Selecting a Range of Pages

+ +

The "-o page-ranges=pages" option selects a range of pages for printing: + +

    +% lp -o page-ranges=1 filename ENTER
    +% lp -o page-ranges=1-4 filename ENTER
    +% lp -o page-ranges=1-4,7,9-12 filename ENTER
    +
+ +

As shown above, the pages value can be a single page, a range of +pages, or a collection of page numbers and ranges separated by commas. The +pages will always be printed in ascending order, regardless of the order of +the pages in the "page-range" option. + +

To select the even or odd pages, use the "-o page-set=set" option: + +

    +% lp -o page-set=odd filename ENTER
    +% lp -o page-set=even filename ENTER
    +
+ +

Setting the Brightness

+ +

You can control the overall brightness of the printed output using the +"-o brightness=percent" option: + +

    +% lp -o brightness=120 filename ENTER
    +
+ +

Values greater than 100 will lighten the print, while values less than +100 will darken it. + +

Setting the Gamma Correction

+ +

You can control the overall gamma correction of the printed output +using the "-o gamma=value" option: + +

    +% lp -o gamma=1700 filename ENTER
    +
+ +

Values greater than 1000 will lighten the print, while values less +than 1000 will darken it. + +

Text Options

+ +

The following options apply when printing text files. + +

Setting the Number of Characters Per Inch

+ +

The "-o cpi=value" option sets the number of characters per inch: + +

    +% lp -o cpi=12 filename ENTER
    +
+ +

Setting the Number of Lines Per Inch

+ +

The "-o lpi=value" option sets the number of lines per inch: + +

    +% lp -o lpi=8 filename ENTER
    +
+ +

Setting the Number of Columns

+ +

The "-o columns=value" option sets the number of text columns: + +

    +% lp -o columns=2 filename ENTER
    +
+ +

Setting the Page Margins

+ +

Normally the page margins are set to the hard limits of the printer. To +adjust the page margins use the "-o page-left=value", "-o page-right=value", +"-o page-top=value", and "-o page-bottom=value" options: + +

    +% lp -o page-left=value filename ENTER
    +% lp -o page-right=value filename ENTER
    +% lp -o page-top=value filename ENTER
    +% lp -o page-bottom=value filename ENTER
    +
+ +

The value argument is the margin in points; each point is 1/72 inch +or 0.35mm. + +

Pretty Printing

+ +

The "-o prettyprint" option puts a header at the top of each page with the +page number, job title (usually the filename), and the date. Also, C and C++ +keywords are highlighted, and comment lines are italicized: + +

    +% lp -o prettyprint filename ENTER
    +
+ +

Image Options

+ +

The following options apply when printing image files. + +

Scaling the Image

+ +

The "-o scaling=percent" and "-o ppi=value" options change the size of a +printed image: + +

    +% lp -o scaling=percent filename ENTER
    +% lp -o ppi=value filename ENTER
    +
+ +

The scaling percent is a number from 1 to 800 specifying the size +in relation to the page (not the image.) A scaling of 100 percent will +fill the page as completely as the image aspect ratio allows. A scaling of +200 percent will print on up to 4 pages. + +

The ppi value is a number from 1 to 1200 specifying the resolution +of the image in pixels per inch. An image that is 3000x2400 pixels will print +10x8 inches at 300 pixels per inch, for example. If the specified resolution +makes the image larger than the page, multiple pages will be printed to +satisfy the request. + +

Adjusting the Hue (Tint) of an Image

+ +

The "-o hue=value" option will adjust the hue of the printed image, much +like the tint control on your television: + +

    +% lp -o hue=value filename ENTER
    +
+ +

The value argument is a number from -360 to 360 and represents the +color hue rotation. The following table summarizes the change you'll see with +different colors: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Originalhue=-45hue=45
RedPurpleYellow-orange
GreenYellow-greenBlue-green
YellowOrangeGreen-yellow
BlueSky-bluePurple
MagentaIndigoCrimson
CyanBlue-greenLight-navy-blue
+ +

Adjusting the Saturation (Color) of an Image

+ +

The "-o saturation=percent" option adjusts the saturation of the colors in +an image, much like the color knob on your television: + +

    +% lp -o saturation=percent filename ENTER
    +
+ +

The percent argument specifies the color saturation from 0 to 200. +A color saturation of 0 produces a black-and-white print, while a value of 200 +will make the colors extremely intense. + + + diff --git a/doc/svd.html b/doc/svd.html new file mode 100644 index 0000000000..780f843022 --- /dev/null +++ b/doc/svd.html @@ -0,0 +1,149 @@ + + +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.

+

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.

+

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..4491433eae8bdcd80fc3593ab16ba75c5c490d14 GIT binary patch literal 21933 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 A=l}o! literal 0 Hc-jL100001 diff --git a/doc/svd.shtml b/doc/svd.shtml new file mode 100644 index 0000000000..1f9c34c2a2 --- /dev/null +++ b/doc/svd.shtml @@ -0,0 +1,167 @@ + + + + + + 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. + +

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. + +

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..bdf5892d29 --- /dev/null +++ b/filter/Makefile @@ -0,0 +1,150 @@ +# +# "$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 +# 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 + +TARGETS = hpgltops texttops pstops imagetops imagetoraster \ + rastertohp + +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 rastertohp.o texttops.o textcommon.o + +# +# Make all targets... +# + +all: $(TARGETS) + +# +# Clean all object files... +# + +clean: + rm -f $(OBJS) $(TARGETS) $(LIBCUPSIMAGE) + +# +# Install all targets... +# + +install: + -$(MKDIR) $(SERVERROOT)/filter + $(CP) $(TARGETS) $(SERVERROOT)/filter + -$(MKDIR) $(LIBDIR) + $(CP) $(LIBCUPSIMAGE) $(LIBDIR) + -if test $(LIBCUPSIMAGE) != "libcupsimage.a"; then \ + $(LN) $(LIBCUPSIMAGE) `basename $(LIBCUPSIMAGE) .1`; \ + fi + +# +# hpgltops +# + +hpgltops: $(HPGLOBJS) common.o ../Makedefs ../cups/$(LIBCUPS) + echo Linking $@... + $(CC) $(LDFLAGS) -o $@ $(HPGLOBJS) common.o $(LIBS) -lm +$(HPGLOBJS): hpgltops.h + +# +# libcupsimage.so.1, libcupsimage.sl.1 +# + +libcupsimage.so.1 libcupsimage.sl.1: $(IMAGEOBJS) ../Makedefs + echo Linking $@... + $(DSO) $@ $(IMAGEOBJS) $(DSOLIBS) -lm + -$(LN) $@ `basename $@ .1` + +# +# libcupsimage.a +# + +libcupsimage.a: $(IMAGEOBJS) ../Makedefs + echo Archiving $@... + $(RM) $@ + $(AR) $(ARFLAGS) $@ $(IMAGEOBJS) + $(RANLIB) $@ + +$(IMAGEOBJS): image.h + +# +# imagetops +# + +imagetops: imagetops.o common.o $(LIBCUPSIMAGE) ../Makedefs \ + ../cups/$(LIBCUPS) + echo Linking $@... + $(CC) $(LDFLAGS) -o $@ imagetops.o common.o -L. -lcupsimage \ + $(IMGLIBS) $(LIBS) +imagetops: common.h image.h + +# +# imagetoraster +# + +imagetoraster: imagetoraster.o common.o $(LIBCUPSIMAGE) ../Makedefs \ + ../cups/$(LIBCUPS) + echo Linking $@... + $(CC) $(LDFLAGS) -o $@ imagetoraster.o common.o -L. -lcupsimage \ + $(IMGLIBS) $(LIBS) +imagetoraster: common.h image.h + +# +# pstops +# + +pstops: pstops.o common.o ../Makedefs ../cups/$(LIBCUPS) + echo Linking $@... + $(CC) $(LDFLAGS) -o $@ pstops.o common.o $(LIBS) +pstops.o: common.h + +# +# rastertohp +# + +rastertohp: rastertohp.o ../Makedefs ../cups/$(LIBCUPS) + echo Linking $@... + $(CC) $(LDFLAGS) -o $@ rastertohp.o $(LIBS) +rastertohp.o: ../cups/raster.h + +# +# texttops +# + +texttops: texttops.o textcommon.o common.o ../Makedefs \ + ../cups/$(LIBCUPS) + echo Linking $@... + $(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..65ddc529e6 --- /dev/null +++ b/filter/common.c @@ -0,0 +1,252 @@ +/* + * "$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 */ + const 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; + else if ((val = cupsGetOption("Duplex", num_options, options)) != NULL && + strcmp(val, "DuplexNoTumble") == 0) + Duplex = 1; + else if (ppdIsMarked(ppd, "Duplex", "DuplexNoTumble") || + ppdIsMarked(ppd, "Duplex", "DuplexTumble")) + 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..9c460985f5 --- /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 */ + const 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..0d8aac7045 --- /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 "/data/HPGLprolog", "r")) == NULL) + { + perror("ERROR: Unable to open HPGL prolog \"" CUPS_DATADIR "/data/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.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..af9d4cd0af --- /dev/null +++ b/filter/image.c @@ -0,0 +1,743 @@ +/* + * "$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 d, /* I - Ink/marker density */ + float g, /* I - Ink/marker gamma */ + float matrix[3][3]) /* I - Color transform matrix */ +{ + int i, j, k; /* Looping vars */ + + + 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); + + for (k = 0; k < 256; k ++) + ImageDensity[k] = 255.0 * d * 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) + { + cupsTempFile(img->cachename, sizeof(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..eb1192dae3 --- /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 d, float g, 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..e6c28eca00 --- /dev/null +++ b/filter/imagetops.c @@ -0,0 +1,494 @@ +/* + * "$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 */ + const 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 */ + int realcopies; /* Real copies being printed */ + + + 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; + + Copies = atoi(argv[4]); + + 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("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("%!"); + + if (ppd != NULL && ppd->patches != NULL) + puts(ppd->patches); + + 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 dup 0 lt { pop 1 } { %.3f exp neg 1 add } " + "ifelse %.3f mul } bind settransfer\n", g, b); + + if (Copies > 1 && !slowcollate) + { + printf("/#copies %d def\n", Copies); + realcopies = Copies; + Copies = 1; + } + else + realcopies = 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, "PAGE: %d %d\n", page, realcopies); + 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..47aa6c5057 --- /dev/null +++ b/filter/imagetoraster.c @@ -0,0 +1,3839 @@ +/* + * "$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, 4, 4, 1, 1, 1 }; + + +/* + * 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 */ + const 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; + + Copies = atoi(argv[4]); + + 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("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 : + case CUPS_CSPACE_WHITE : + case CUPS_CSPACE_GOLD : + case CUPS_CSPACE_SILVER : + 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) + ImageSetProfile(profile->density, profile->gamma, 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; + } + else + header.NumCopies = 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 : + case CUPS_CSPACE_WHITE : + case CUPS_CSPACE_GOLD : + case CUPS_CSPACE_SILVER : + 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 : + case CUPS_CSPACE_GMCK : + case CUPS_CSPACE_GMCS : + 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++ ^= 17; /* Blue (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) + { + *cptr ^= bitmask; /* Blue (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[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[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..f93d76f26a --- /dev/null +++ b/filter/pstops.c @@ -0,0 +1,804 @@ +/* + * "$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 */ +const char *PageRanges = NULL; /* Range of pages selected */ +const 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 */ + const 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 */ + int level; /* Nesting level for embedded files */ + int nbytes, /* Number of bytes read */ + tbytes; /* Total bytes to read for binary data */ + int page; /* Current page sequence number */ + + + 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; + + Copies = atoi(argv[4]); + + 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("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(cupsTempFile(tempfile, sizeof(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); + + if (ppd != NULL && ppd->patches != NULL) + puts(ppd->patches); + + 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 dup 0 lt { pop 1 } { %.3f exp neg 1 add } " + "ifelse %.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... + */ + + level = 0; + + while (psgets(line, sizeof(line), fp) != NULL) + if (strncmp(line, "%%BeginDocument:", 16) == 0 || + strncmp(line, "%%BeginDocument ", 16) == 0) /* Adobe Acrobat BUG */ + level ++; + else if (strcmp(line, "%%EndDocument") == 0 && level > 0) + level --; + else if (strncmp(line, "%%Page:", 7) == 0 && level == 0) + break; + else if (strncmp(line, "%%BeginBinary:", 14) == 0 || + (strncmp(line, "%%BeginData:", 12) == 0 && + strstr(line, "Binary") != NULL)) + { + /* + * Copy binary data... + */ + + tbytes = atoi(strchr(line, ':') + 1); + while (tbytes > 0) + { + nbytes = fread(line, 1, sizeof(line), fp); + fwrite(line, 1, nbytes, stdout); + tbytes -= nbytes; + } + } + else + puts(line); + + /* + * Then read all of the pages, filtering as needed... + */ + + for (page = 1;;) + { + if (strncmp(line, "%%BeginDocument:", 16) == 0 || + strncmp(line, "%%BeginDocument ", 16) == 0) /* Adobe Acrobat BUG */ + level ++; + else if (strcmp(line, "%%EndDocument") == 0 && level > 0) + level --; + else if (strncmp(line, "%%Page:", 7) == 0 && level == 0) + { + if (sscanf(line, "%*s%*s%d", &number) == 1) + { + if (!check_range(number)) + { + while (psgets(line, sizeof(line), fp) != NULL) + if (strncmp(line, "%%BeginDocument:", 16) == 0 || + strncmp(line, "%%BeginDocument ", 16) == 0) /* Adobe Acrobat BUG */ + level ++; + else if (strcmp(line, "%%EndDocument") == 0 && level > 0) + level --; + else if (strncmp(line, "%%Page:", 7) == 0 && level == 0) + break; + + continue; + } + + if (!sloworder && NumPages > 0) + end_nup(NumPages - 1); + + if (slowcollate || sloworder) + Pages[NumPages] = ftell(temp); + + if (!sloworder) + { + if ((NumPages % NUp) == 0) + { + if (ppd == NULL || ppd->num_filters == 0) + fprintf(stderr, "PAGE: %d %d\n", page, Copies); + + printf("%%%%Page: %d %d\n", page, page); + page ++; + ppdEmit(ppd, stdout, PPD_ORDER_PAGE); + } + + start_nup(NumPages); + } + + NumPages ++; + } + } + else if (strncmp(line, "%%BeginBinary:", 14) == 0 || + (strncmp(line, "%%BeginData:", 12) == 0 && + strstr(line, "Binary") != NULL)) + { + /* + * Copy binary data... + */ + + tbytes = atoi(strchr(line, ':') + 1); + while (tbytes > 0) + { + nbytes = fread(line, 1, sizeof(line), fp); + + if (!sloworder) + fwrite(line, 1, nbytes, stdout); + + if (slowcollate || sloworder) + fwrite(line, 1, nbytes, stdout); + + tbytes -= nbytes; + } + } + 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); + page = 1; + + if (!sloworder) + { + while (Copies > 0) + { + rewind(temp); + + for (number = 0; number < NumPages; number ++) + { + if ((number % NUp) == 0) + { + if (ppd == NULL || ppd->num_filters == 0) + fprintf(stderr, "PAGE: %d 1\n", page); + + printf("%%%%Page: %d %d\n", page, page); + page ++; + ppdEmit(ppd, stdout, PPD_ORDER_PAGE); + } + + start_nup(number); + copy_bytes(temp, Pages[number + 1] - Pages[number]); + end_nup(number); + } + + Copies --; + } + } + else + { + do + { + for (number = NumPages - 1; number >= 0; number --) + { + if ((number % NUp) == 0) + { + if (ppd == NULL || ppd->num_filters == 0) + fprintf(stderr, "PAGE: %d %d\n", page, + slowcollate ? 1 : Copies); + + printf("%%%%Page: %d %d\n", page, page); + page ++; + 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 --; + } + while (Copies > 0 || !slowcollate); + } + } + } + else + { + /* + * No DSC comments - write any page commands and then the rest of the file... + */ + + if (ppd == NULL || ppd->num_filters == 0) + fprintf(stderr, "PAGE: 1 %d\n", slowcollate ? 1 : Copies); + + 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) + { + if (ppd == NULL || ppd->num_filters == 0) + fputs("PAGE: 1 1\n", stderr); + + 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 */ +{ + const 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, (char **)&range, 10); + } + else + { + lower = strtol(range, (char **)&range, 10); + + if (*range == '-') + { + range ++; + if (!isdigit(*range)) + upper = 65535; + else + upper = strtol(range, (char **)&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 */ +{ + if (Flip || Orientation || NUp > 1) + puts("grestoreall"); + + 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 */ + + + if (Flip || Orientation || NUp > 1) + 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/rastertohp.c b/filter/rastertohp.c new file mode 100644 index 0000000000..85de33ed0d --- /dev/null +++ b/filter/rastertohp.c @@ -0,0 +1,493 @@ +/* + * "$Id$" + * + * Hewlett-Packard Page Control Language and Raster Transfer Language + * filter for ESP Print. + * + * Copyright 1993-1999 by Easy Software Products + * + * These coded instructions, statements, and computer programs contain + * unpublished proprietary information of Easy Software Products, and + * are protected by Federal copyright law. They may not be disclosed + * to third parties or copied or duplicated in any form, in whole or + * in part, without the prior written consent of Easy Software Products. + * + * Contents: + * + */ + +/* + * Include necessary headers... + */ + +#include +#include +#include +#include +#include +#include + + +/* + * Globals... + */ + +unsigned char *Planes[4], /* Output buffers */ + *CompBuffer; /* Compression buffer */ +int NumPlanes, /* Number of color planes */ + Feed; /* Number of lines to skip */ + + +/* + * Prototypes... + */ + +void Setup(void); +void StartPage(cups_page_header_t *header); +void EndPage(cups_page_header_t *header); +void Shutdown(void); + +void CompressData(unsigned char *line, int length, int plane, int type); +void OutputLine(cups_page_header_t *header); + + +/* + * 'Setup()' - Prepare the printer for printing. + */ + +void +Setup(void) +{ + /* + * Send a PCL reset sequence. + */ + + putchar(0x1b); + putchar('E'); +} + + +/* + * 'StartPage()' - Start a page of graphics. + */ + +void +StartPage(cups_page_header_t *header) /* I - Page header */ +{ + int plane; /* Looping var */ + + + /* + * Set the media type, position, and size... + */ + + printf("\033&l6D\033&k12H"); /* Set 6 LPI, 10 CPI */ + printf("\033&l%.2fP", /* Set page length */ + header->PageSize[1] / 12.0); + printf("\033&l%dX", header->NumCopies); /* Set number copies */ + if (header->MediaPosition) + printf("\033&l%dH", header->MediaPosition); /* Set media position */ + if (header->cupsMediaType) + printf("\033&l%dM", /* Set media type */ + header->cupsMediaType); + + /* + * Set graphics mode... + */ + + if (header->cupsColorSpace == CUPS_CSPACE_KCMY) + { + NumPlanes = 4; + printf("\033*r-4U"); /* Set KCMY graphics */ + } + else + NumPlanes = 1; + + printf("\033*t%dR", header->HWResolution[0]); /* Set resolution */ + printf("\033*r%dS", header->cupsWidth); /* Set width */ + printf("\033*r%dT", header->cupsHeight); /* Set height */ + printf("\033&a0H\033&a0V"); /* Set top-of-page */ + printf("\033*r1A"); /* Start graphics */ + + if (header->cupsCompression) + printf("\033*b%dM", /* Set compression */ + header->cupsCompression); + + Feed = 0; /* No blank lines yet */ + + /* + * Allocate memory for a line of graphics... + */ + + Planes[0] = malloc(header->cupsBytesPerLine); + for (plane = 1; plane < NumPlanes; plane ++) + Planes[plane] = Planes[0] + plane * header->cupsBytesPerLine / NumPlanes; + + if (header->cupsCompression) + CompBuffer = malloc(header->cupsBytesPerLine * 2); +} + + +/* + * 'EndPage()' - Finish a page of graphics. + */ + +void +EndPage(cups_page_header_t *header) /* I - Page header */ +{ + /* + * Eject the current page... + */ + + if (NumPlanes > 1) + { + printf("\033*rC"); /* End color GFX */ + printf("\033&l0H"); /* Eject current page */ + } + else + { + printf("\033*r0B"); /* End GFX */ + printf("\014"); /* Eject currnet page */ + } + + /* + * Free memory... + */ + + free(Planes[0]); + + if (header->cupsCompression) + free(CompBuffer); +} + + +/* + * 'Shutdown()' - Shutdown the printer. + */ + +void +Shutdown(void) +{ + /* + * Send a PCL reset sequence. + */ + + putchar(0x1b); + putchar('E'); +} + + +/* + * 'CompressData()' - Compress a line of graphics. + */ + +void +CompressData(unsigned char *line, /* I - Data to compress */ + int length, /* I - Number of bytes */ + int plane, /* I - Color plane */ + int type) /* I - Type of compression */ +{ + unsigned char *line_ptr, /* Current byte pointer */ + *line_end, /* End-of-line byte pointer */ + *comp_ptr, /* Pointer into compression buffer */ + *start; /* Start of compression sequence */ + int count; /* Count of bytes for output */ + + + switch (type) + { + case 0 : + /* + * Do no compression... + */ + + line_ptr = line; + line_end = line + length; + break; + + case 1 : + /* + * Do run-length encoding... + */ + + line_end = line + length; + for (line_ptr = line, comp_ptr = CompBuffer; + line_ptr < line_end; + comp_ptr += 2, line_ptr += count) + { + for (count = 1; + (line_ptr + count) < line_end && + line_ptr[0] == line_ptr[count] && + count < 256; + count ++); + + comp_ptr[0] = count - 1; + comp_ptr[1] = line_ptr[0]; + } + + line_ptr = CompBuffer; + line_end = comp_ptr; + break; + + case 2 : + /* + * Do TIFF pack-bits encoding... + */ + + line_ptr = line; + line_end = line + length; + comp_ptr = CompBuffer; + + while (line_ptr < line_end) + { + if ((line_ptr + 1) >= line_end) + { + /* + * Single byte on the end... + */ + + *comp_ptr++ = 0x00; + *comp_ptr++ = *line_ptr++; + } + else if (line_ptr[0] == line_ptr[1]) + { + /* + * Repeated sequence... + */ + + line_ptr ++; + count = 2; + + while (line_ptr < (line_end - 1) && + line_ptr[0] == line_ptr[1] && + count < 127) + { + line_ptr ++; + count ++; + } + + *comp_ptr++ = 257 - count; + *comp_ptr++ = *line_ptr++; + } + else + { + /* + * Non-repeated sequence... + */ + + start = line_ptr; + line_ptr ++; + count = 1; + + while (line_ptr < (line_end - 1) && + line_ptr[0] != line_ptr[1] && + count < 127) + { + line_ptr ++; + count ++; + } + + *comp_ptr++ = count - 1; + + memcpy(comp_ptr, start, count); + comp_ptr += count; + } + } + + line_ptr = CompBuffer; + line_end = comp_ptr; + break; + } + + /* + * Set the length of the data and write a raster plane... + */ + + printf("\033*b%d%c", line_end - line_ptr, plane); + fwrite(line_ptr, line_end - line_ptr, 1, stdout); +} + + +/* + * 'OutputLine()' - Output a line of graphics. + */ + +void +OutputLine(cups_page_header_t *header) /* I - Page header */ +{ + int plane; /* Current plane */ + + + /* + * Output whitespace as needed... + */ + + if (Feed > 0) + { + printf("\033*b%dY", Feed); + Feed = 0; + } + + /* + * Write bitmap data as needed... + */ + + for (plane = 0; plane < NumPlanes; plane ++) + CompressData(Planes[plane], header->cupsBytesPerLine / NumPlanes, + plane < (NumPlanes - 1) ? 'V' : 'W', + header->cupsCompression); +} + + +/* + * 'main()' - Main entry and processing of driver. + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line arguments */ + char *argv[]) /* I - Command-line arguments */ +{ + int fd; /* File descriptor */ + cups_raster_t *ras; /* Raster stream for printing */ + cups_page_header_t header; /* Page header from file */ + int page; /* Current page */ + int y; /* Current line */ + + + /* + * Check for valid arguments... + */ + + if (argc < 6 || argc > 7) + { + /* + * We don't have the correct number of arguments; write an error message + * and then sleep for 1 second to give the scheduler a chance to read + * the message. + */ + + fputs("ERROR: rastertopcl job-id user title copies options [file]\n", stderr); + sleep(1); + return (1); + } + + /* + * Open the page stream... + */ + + if (argc == 7) + { + if ((fd = open(argv[6], O_RDONLY)) == -1) + { + perror("ERROR: Unable to open raster file - "); + sleep(1); + return (1); + } + } + else + fd = 0; + + ras = cupsRasterOpen(fd, CUPS_RASTER_READ); + + /* + * Initialize the print device... + */ + + Setup(); + + /* + * Process pages as needed... + */ + + page = 0; + + while (cupsRasterReadHeader(ras, &header)) + { + /* + * Write a status message with the page number and number of copies. + */ + + page ++; + + fprintf(stderr, "PAGE: %d %d\n", page, header.NumCopies); + + /* + * Start the page... + */ + + StartPage(&header); + + /* + * Loop for each line on the page... + */ + + for (y = 0; y < header.cupsHeight; y ++) + { + /* + * Let the user know how far we have progressed... + */ + + if ((y & 127) == 0) + fprintf(stderr, "INFO: Printing page %d, %d%% complete...\n", page, + 100 * y / header.cupsHeight); + + /* + * Read a line of graphics... + */ + + if (cupsRasterReadPixels(ras, Planes[0], header.cupsBytesPerLine) < 1) + break; + + /* + * See if the line is blank; if not, write it to the printer... + */ + + if (Planes[0][0] || + memcmp(Planes[0], Planes[0] + 1, header.cupsBytesPerLine - 1)) + OutputLine(&header); + else + Feed ++; + } + + /* + * Eject the page... + */ + + EndPage(&header); + } + + /* + * Shutdown the printer... + */ + + Shutdown(); + + /* + * Close the raster stream... + */ + + cupsRasterClose(ras); + if (fd != 0) + close(fd); + + /* + * If no pages were printed, send an error message... + */ + + if (page == 0) + fputs("ERROR: No pages found!\n", stderr); + else + fputs("INFO: Ready to print.\n", stderr); + + /* + * Sleep for 1 second and return... + */ + + sleep(1); + return (page == 0); +} + + +/* + * End of "$Id$". + */ diff --git a/filter/textcommon.c b/filter/textcommon.c new file mode 100644 index 0000000000..2558905a44 --- /dev/null +++ b/filter/textcommon.c @@ -0,0 +1,745 @@ +/* + * "$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 = 1, /* 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 */ + Copies = 1; /* Number of copies */ +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... */ + { + "and", + "and_eq", + "asm", + "auto", + "bitand", + "bitor", + "bool", + "break", + "case", + "catch", + "char", + "class", + "compl", + "const", + "continue", + "default", + "delete", + "do", + "double", + "else", + "enum", + "explicit", + "extern", + "false", + "float", + "for", + "friend", + "goto", + "if", + "inline", + "int", + "long", + "mutable", + "namespace", + "new", + "not", + "not_eq", + "operator", + "or", + "or_eq", + "private", + "protected", + "public", + "register", + "return", + "short", + "signed", + "sizeof", + "static", + "struct", + "switch", + "template", + "this", + "throw", + "true", + "try", + "typedef", + "typename", + "union", + "unsigned", + "virtual", + "void", + "volatile", + "while", + "xor", + "xor_eq" + }; + + +/* + * 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 */ + const 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 ((val = cupsGetOption("prettyprint", num_options, options)) != NULL) + { + PrettyPrint = 1; + PageLeft = 72.0f; + PageRight = PageWidth - 36.0f; + PageBottom = PageBottom > 36.0f ? PageBottom : 36.0f; + PageTop = PageLength - 36.0f; + CharsPerInch = 12; + LinesPerInch = 8; + } + + if ((ppd = SetCommonOptions(num_options, options, 1)) != NULL) + ppdClose(ppd); + + WrapLines = cupsGetOption("nowrap", 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) + PageTop -= 216.0f / LinesPerInch; + + Copies = atoi(argv[4]); + + WriteProlog(argv[3], argv[2], ppd); + + /* + * 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 (!(isalnum(ch) || 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 ((isalnum(ch) || 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..cffd4db731 --- /dev/null +++ b/filter/textcommon.h @@ -0,0 +1,89 @@ +/* + * "$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 */ + Copies; /* Number of copies to produce */ +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, ppd_file_t *ppd); + + +/* + * End of "$Id$". + */ diff --git a/filter/texttops.c b/filter/texttops.c new file mode 100644 index 0000000000..b8757bf9c3 --- /dev/null +++ b/filter/texttops.c @@ -0,0 +1,568 @@ +/* + * "$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 */ + ppd_file_t *ppd) /* I - PPD file info */ +{ + 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("\tFB 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, + (0.5f + 0.157f) * 72.0f / LinesPerInch); + printf("\t\t%.1f %.1f } ifelse\n", 36.0f / LinesPerInch, + (0.5f + 0.157f) * 72.0f / LinesPerInch); + } + else + printf("\t%.1f %.1f\n", 36.0f / LinesPerInch, + (0.5f + 0.157f) * 72.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, + (0.5f + 0.157f) * 72.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, + (0.5f + 0.157f) * 72.0f / LinesPerInch); + printf("\t\tdup stringwidth pop neg %.1f add %.1f } ifelse\n", + PageRight - PageLeft - 36.0f / LinesPerInch, + (0.5f + 0.157f) * 72.0f / LinesPerInch); + } + else + printf("\tP cvs dup stringwidth pop neg %.1f add %.1f\n", + PageRight - PageLeft - 36.0f / LinesPerInch, + (0.5f + 0.157f) * 72.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.0f / (float)CharsPerInch; + y -= (float)(row + 0.843) * 72.0f / (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('>'); + } + 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 (PrettyPrint) + { + if (attr & ATTR_RED) + puts("r"); + else if (attr & ATTR_GREEN) + puts("g"); + else if (attr & ATTR_BLUE) + puts("b"); + else + puts("S"); + } + else + puts("S"); +} + + +/* + * End of "$Id$". + */ diff --git a/fonts/AvantGarde-Book b/fonts/AvantGarde-Book new file mode 100644 index 0000000000000000000000000000000000000000..ff3b81847e96f619f08fcbd708ccb742704f2f56 GIT binary patch literal 25994 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 literal 0 Hc-jL100001 diff --git a/fonts/AvantGarde-Demi b/fonts/AvantGarde-Demi new file mode 100644 index 0000000000000000000000000000000000000000..e0df0c709564e1ff1c0c55493267de6747082122 GIT binary patch literal 26980 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
2_R@ zOsyMpYO=MLu7?PW^JrVA2O#Z(RIsb>V#_Nb;MI#DhAXM>kx@JSAai(hy(nsOyTwM) zT>=GyzeQJP(;dl414XfRn(pt_v?UAXe-JrG^Ta1hVp z&o8(W{-V`aZIX2i2~fCYnmt=bW d!J+*x5&U29pAdMUz1%P%fe+j;{(@0le*+})hEo6l literal 0 Hc-jL100001 diff --git a/fonts/Bookman-Light b/fonts/Bookman-Light new file mode 100644 index 0000000000000000000000000000000000000000..4416dbf312ca5414e817b179c9eb7f7b1037c7ac GIT binary patch literal 35522 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 SoRgYZRFa>YSd`7xzzhItFD_C5 literal 0 Hc-jL100001 diff --git a/fonts/Courier b/fonts/Courier new file mode 100644 index 0000000000000000000000000000000000000000..54fe52724bbb3c243fd616a0329e075c6976b320 GIT binary patch literal 35719 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 literal 0 Hc-jL100001 diff --git a/fonts/Courier-Bold b/fonts/Courier-Bold new file mode 100644 index 0000000000000000000000000000000000000000..7b31de35f3135bdbf792ab7b0a665d28fd8ec0fe GIT binary patch literal 38284 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 QD-SPM7b_1Z;t<^b05wus?EnA( literal 0 Hc-jL100001 diff --git a/fonts/Courier-BoldOblique b/fonts/Courier-BoldOblique new file mode 100644 index 0000000000000000000000000000000000000000..45b11a12f77fd52c4fb0e4606cf5171728b04cb9 GIT binary patch literal 40686 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%0A(4sOjcj8Y3Py;iJ>yMjZ)eK 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 Z|Bv8*1%bJPrKy{Tv!kh-J!&xg{{W?;%F6%% literal 0 Hc-jL100001 diff --git a/fonts/Courier-Oblique b/fonts/Courier-Oblique new file mode 100644 index 0000000000000000000000000000000000000000..bbd2f05345469c07f2b1838d72667e1ccec3cc94 GIT binary patch literal 34677 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 literal 0 Hc-jL100001 diff --git a/fonts/Helvetica b/fonts/Helvetica new file mode 100644 index 0000000000000000000000000000000000000000..5f20a5aade37ce33e120c93c2db56ff8141cce7e GIT binary patch literal 27505 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 VCj_Q;=Eg3rj`qebwlIO9{{aafGARH6 literal 0 Hc-jL100001 diff --git a/fonts/Helvetica-BoldOblique b/fonts/Helvetica-BoldOblique new file mode 100644 index 0000000000000000000000000000000000000000..48c34c1ca2fc617d4631f21c0d9e0be659a4cb4f GIT binary patch literal 28971 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 literal 0 Hc-jL100001 diff --git a/fonts/Helvetica-Narrow b/fonts/Helvetica-Narrow new file mode 100644 index 0000000000000000000000000000000000000000..e81691b52c032272dc8db6e127278462366a60b5 GIT binary patch literal 27406 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 z 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�D*3 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�S={MYA^(*AS6s#TVRJ$i(i<(N1*H8;*CLJnPuH}QniV(6~gH9rNvx6TTU6eve1kZ zfR(Z!^MBn98tS|7Qsi8@8$Q8txQ3}Rl^lY%Gs>4MU5J{WZYGQGKoH_6QDw&Dr%^u3 zwD?0P^D4)5a*laO>H z5Y5_43eqhz&-JYi0|NZ689M;v22t}Kx|us#sfwd?U{J4gGKqx*WLC`%I3XREsd{aB zwC^NQDNv$p+LC>(ALL%b(?Dc=t+^#SW4F~e_Vi7iIs@|Y@sAn_Tn$9+S0A~no6UV> zGXi9Dsw*OEOyp{7Tq9J4025Ftrv%qD3;F4rnKD(RYIz{*H#CV(oJ;lNgQD>6S-Wfb zw@Ue{Ye=_-iui%KIr)kyAo%1VA_3|>{K*p_zPTb?&f~^y**vzI%@PQb~RXqFdxDL#13x!8&*qNcQ zr!<#Mt#WB-7D($hr5Wc;Ts!zq{b{zLtSQ;?3ooV^hkE`TXMYOIIFSx5-B*W#DIlsg z_f9WoM1mWu3p3opRYag#Iv$i;M|bbn-l|y$o*yBl;0M!dVK-?l_;y!XeUM5cmKAiO zzz0uHMez+*RtZC8MI0r=K5*H!Jb?!=pD+Fy#4VFa<=y^bU7-03~r$cCX)1O>g>QY%+G{M8dyEkUOiBdH)K2eraYxdm;xndtl>pNJUe=( zdjkt((6)~fNzDC)Vvm7s=q=cbve&hSus*cw^XUFu39P~;Mjh)B$^NjXb{lu7|5&A9 zlwOv2dU~}QXmLs69;yN3eOJy}Hm)tga{@_PV2yVZpb3H$=n>?QY|w4J?4m*m4QdXp zn|*TViO-mVPM>~>`O!J;hbFB#dpg;t{E;YdkOfUkQdw~yCYR9!+K2l5)Yd=i1zF1V zZA%ltxmSQ_S{q%$WjC;~VL&78GV44WN!i!ue5zYW^gG;7xw)Bv1Au`>d^n%E(J|-N z)wg+>wp`a6h{FQ+Hl*>z{S zoe{V>tCR_fLT-&jO=XH?()9)2p2!E3nN9_oi5h*N7BNssS0rQ@%_o~;B>EMKTk6W^*n`5M zzLbn^0LuNY{k)&;+^J3_9jW59YDgYDwb3ci2dg#e>}ey^-S z7(d91`B@2_o!0_s8NMut9)2xB(-0GGJ@><{Tf_yE^R?bbBIheezU8;v#D*izCqTIw z&bHTuZpAvcVB;D)nSUsphvxyNe$D(I+0nfc#+P84M;6)nn5ef!n@{zpPQf|g&RYU$ zx+}HdJNVYIEdsR6qs<@qH;);)BB=VaQx|6s%R^AoPX38j6p&9O{;i-ZEfK}E(Ryd0 zA5ds$E-h{RnjHDBGo)s={cqA+&i>-gZ3bENlh+g4rIhXOHEI?O6~h

6HJ^rnXoNRLmA_kDp&hZnS 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

YqLw7Xhbt5P`d1Va<~6Rm zkMV#1(TCk*Yc1;n;duqh;l(5GR|zRS**{K6S}i$VaLc$2;IFsbmcau~;iL2LZZ$0G znS4s_1df^9$#DE6rqh5|YTr!kZT^XSZ92(}&h_jB;%>nenWtTXkv*@k_qwh{F6or( z_@*(7afwuThwp!SoT|N}t2sVl$*Y@YVh(MTgD0lY2f7By_01b2rY*Y)x-4#l0$K#B zKRY6U&Z9Di4PDye?X?rI&Ov|Vjf28$!v@hhg0VW2%Az30~Y)Q26}>LE@+I$ zE7qHS{WP)`AFp?Eny~NfmoEI${cKfjvsdNg&67Dz(Xki6 z-xA>Ucw0wq*R2bG_wwr&o>Rg+EM_O8i_HE!Qv#px z$fX-;+>m4+Oe@;`KkcEKsj@aT~n*;|;nx;r_TxZ1%5f&UNkI|5q( literal 0 Hc-jL100001 diff --git a/fonts/Makefile b/fonts/Makefile new file mode 100644 index 0000000000..f287800b1d --- /dev/null +++ b/fonts/Makefile @@ -0,0 +1,68 @@ +# +# "$Id$" +# +# Fonts 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 + +# +# Font files... +# + +FONTS = AvantGarde-Book AvantGarde-BookOblique AvantGarde-Demi \ + AvantGarde-DemiOblique Bookman-Demi Bookman-DemiItalic \ + Bookman-Light Bookman-LightItalic Courier Courier-Bold \ + Courier-BoldOblique Courier-Oblique Helvetica \ + Helvetica-Bold Helvetica-BoldOblique Helvetica-Narrow \ + Helvetica-Narrow-Bold Helvetica-Narrow-BoldOblique \ + Helvetica-Narrow-Oblique Helvetica-Oblique \ + NewCenturySchlbk-Bold NewCenturySchlbk-BoldItalic \ + NewCenturySchlbk-Italic NewCenturySchlbk-Roman \ + Palatino-Bold Palatino-BoldItalic Palatino-Italic \ + Palatino-Roman Symbol Times-Bold Times-BoldItalic \ + Times-Italic Times-Roman Utopia-Bold Utopia-BoldItalic \ + Utopia-Italic Utopia-Regular ZapfChancery-MediumItalic \ + ZapfDingbats + +# +# Make everything... +# + +all: + +# +# Clean all config and object files... +# + +clean: + +# +# Install files... +# + +install: + -$(MKDIR) $(DATADIR)/fonts + $(CP) $(FONTS) $(DATADIR)/fonts + +# +# End of "$Id$". +# diff --git a/fonts/NewCenturySchlbk-Bold b/fonts/NewCenturySchlbk-Bold new file mode 100644 index 0000000000000000000000000000000000000000..41876dcd2e896c5a0a33c804ef97aad1bfbb7415 GIT binary patch literal 38763 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 SK5i~SA^yHDLEaScg#QC_-4pZx literal 0 Hc-jL100001 diff --git a/fonts/NewCenturySchlbk-BoldItalic b/fonts/NewCenturySchlbk-BoldItalic new file mode 100644 index 0000000000000000000000000000000000000000..8ed9fdf522825a8bfcfc532a3d126c34d870d0e5 GIT binary patch literal 38742 zc-oY?Q?M}Iwk)`8+qP}nwr$(C*SBna%eHOXwr%&n_qnG}$L`w^w;!q^26B#(l^OLi z0|2{#0RTt|6_jZOP3(Ix3~dM)82+g- zutJfN3Okt^x>(xVi5R+=auJ9*SrUku8WAuu5-@UdvOtj%2-`b&I$4@qxDco+sS_yM zo4L3fI+@b^Kl1--Brx*)SN)&<|FbS-Q&R#L3sV9!OB+)HVR;2jNjY%>3UN7A0&!D2 zQ>TA6RB$!2u{0)-u{1Wdb2gk`mM(~er_VzYL_V(5UG6et9kKkVdS{nbq zkcPIFHlF|A*#GQTH~p`5|8?Yl*8XdPpq=?Y;?Od((lPv3+R|Cf(!LPlBu1^e^U5IyMGg) z|KED{-#rS3mUb>Go(`r24F3cAcg*-dv5=6x2Z1*&BRc~DEfW*dKW=7aB;e%a@crKm zlr?m5vh*O(X86Yuj0FF@|NHr$NcTTrqISmiCYE;Q1j;Ukb|!{SCjWQhe^It{bTyR} zAz)=-Vqj$XFSf?6PEP-j`nM(jVgBFozx{7&>S1aO6#(Rv2mo*%3%P1gG(dBY`MzbD zNi?Xf&3bKB$eJ{2t1{84mrVV-vK?}7CLL*+?b775lNV?EPWm$R0CIjm!r8Q09&t@I zg!xNNyI%}tQB$dmPPy|9!USJCZK$&BQN2UD(tEoHghXNTn6S%heru3V=<%Nx{8Doiz zdjp^?r~z7F8->KS^PYGynzq##!z&r%;;(vvO(xY{TiiE25|XwW)ctDS0bVFd5ARCL zoGR>ga<32&wL5V=aU#6tE_Z~1Or(KJ&A8a6N4msRQ_a-?gvyF+N*k~$JxTAC6;N>-ovB^Kcs*4>cJh}JjS z2C{XFdQG(n#Er{x|9^sz_VrWr0Yh@V`a4>Pjww=y|3 zw=-O61Uu9~oels=nKT_e8$ouHIveXQsdio&B*kzKWK;jjqS3k!CMQ*uMi3t7E61kt zWrB1Qpb*X0{j2Z{< zLN;|e8LaE_h;H{|*yq3CzNK+go{ zp?LPy#`W*1w3zqlI{8D4PD^V!4v;A@tRdF`ly-mU6t~3POQmj@QDY1)hL~TS%Q_av zNF}E}LmY7X`|U~mX(X^mMSGp8nLQ2m#b9RyAiHqYK8WTUsZX?~WqTbKN=`1AFXm?k zW=x%{-pID{aqqy#mA`)>KiSKnu&RE+-7;{r_1r)X8>F0lZqBRtE3M@!OBKrR2Zkkc zNe}%?AHQUdpKuXyQo*nEl5IBQG$AJq|EyTqu?a?Ff=M_!dUJDEPTam3P+A1IE^Wf- zM?|2F`iG|yDxP=5Tr?oTr?G98sYti%g+dOqYeRZTtD?RD3 zb+o7_v+Yus-Etdg~_yO#9eV_*(zR;#)hCm6PqNycNDM^Czf2k#h=a5%txhOfzsMXrK?qve64+=w?gBjmt5B@rTF9A)YB>4pe_gR;HzO+8Au*cO)3f9oQrVj}Az1g>42#U~XcY+jw2X|3TP zj;OF}qJxmQbSdiebZ|8Qf_=Vkk-2Ig#S{x7+N+0NFD+soX29Dhc0pmAquMhM}@~9eJy|@oeR<4aRM{1PA`L&4Rg*`5l;xfuS6pu;I0hTsV6;Lib*sI1orV# z>B%WDsetyqb#160X34%>#mBlfkIo#l>{Z}T)!qI*JK;PYa1JBd#?6cHGKta^w*Ifp zB%6&&TVYQlUn~cT7#=Q41jO#xd;-{&M%3C6z(?8eWYc$tIY ziTo3PAmf<8h|OJ$(7PqC1OZT;9Gn){XP%pkt)P}9@}Gm)B4UChS-^=df9|WYcTF@q zFZ!{jBBQ`<>4xFtAD`4rfnS;s%*E7BDSCz% z`$*x@Bm$~@DfUIqAFM^mW*a>%h2;eiN&&jPk^#BNNKv>f@;gZRK4fox8F@8~X9R^Q z)u@GO5oT?wT#~~EE^m!+{kge6?a<~?fIQko=4OD_@}yj}P+qUSC>Zstui31Z-P7;x z!(x)lYzG`zkTd6818cI}$3EZ29^#+$PC^#Z9Xob5k+r7HFRP&GY%FHj4B4(jjCQ^Y zQ7)tPFdPZp{i_BNEHpe|H4a2jbT80zqw$!W0~&6;L0#i{e95CmLv;R}#fno3HIg?` z)7_Fp_oZh9+9w;FhJ3%6M=Zu#P-BwlRw zKO|drY}#v#vBpRAMk-?1cK8Pd;`U6u#hDutG67jj3N!y1OY)hyQXnjyQR9*aQ1$E~Ck?CX z*>a9yR&7<*%%(<@;ajtQVRosyRo%fNlw^-ZwyGn3AB>qHOABBVtpsy4-!XVN*k6`Yey86{~V=6oV^3UMI>Nzhbkv3v!^w#pgbG4-GA#T^U^K)|I1m<=zRSZd zl;BX(8p!5GeE}qDZXdjI`@cku6Cjp&fypxJ85JHVc8KuNQu_@n6*BMFV3x4Yxcxd* zU!o+vtsFB8Ik~5&Cyhu};tCst5n!c?)dyFr_N)z16vAUdYBs=FRFNIWO?GgNMb4i5 zU}`N)f)>TcTT36862VPz62R5sdhGkR?_JCu^0O~MGo(>ENw$uJzYOhT*3>;FN{A{k zH%Hj$w&#ZooKf-L-hj#OEaAau4AgSL=6Z#fdo9wQ0-PN<>>&OzsfiK7*nwv?wM<>7m6n0D7+ivz=v=W#jUA{YX~rpV<4X<@WsUP6PYKSleXh`Iof zi)BHL^UoXFQrO)(9U2Hwj7b)@mlYA;wXRL@bJ_>Fh`eA^Ark)ILB1f1OL_W?bynt> zh!WaTV`f~ux=UQ_%7l507`n890FwxXe~rqpmzsiw&&rhER~&EJW%^v(xC0M|^vjdI z-*W?II?qh~vPV|?42B98!#wzEO%wQ}`2$l2Ym=G>N6R=t?qKW#DapXync(?MY zD43cU2iz>Ze>J7N$q&7Cy{*lf_%RS5@s^!eIl+w_A=;57R!7Kcjhvy*59ZE1k@l|e zuY2y5D&SK|*34tqNOToSnDxqF3x;_huX3-z8 zl&E{K(9daYgII?KG{!Mu#XbSSu+Ttqu~2MdX@G^i^0|FD=VA`1cf;5Ahh$oWwkEGY zI*jgS)Pl)ff1Z$wu650*Bd`!Z$_YIi4$=A{{AuEWmxxeb2ONDp*7p2o>JUmNrz9dO z@)2yV?(%ANpl?chx(&hvQXfa3WzXWd%}sX&?;o24++vS1W2jEiS4ule!n9%|L_?q= z_BB{Mw{vhFQ9^_ImYBrjr6u;!2`o>rj;uP^Zt3<{8I@C-Y=qirRiMVpebE8 z-S5=YoUSe9J*A(J)xLM7O(qN!#UKZFKJ15ckq7qXi>!1UNk<^xVw)Us78z6^EbU=D zaP)G0YlVF6&d#D~mVw$G9I-8x646jXj|?=z1@QUD*w|)~aZ|p+GwM9`UZ!#=?*|yT z78}B_E}HF09h6f)pfylac5s&W1hi|zPXTRml-UEyzqW*FX)%#qRI1cTR{HK5V}RMp z)IhkN*?*SSqC>=6pf(r#Xm0xTsfW9sl$IsJYHq^FmCpHMw%B*M4@Y@7&1V8}ahtEB zPHq{wN2qh7Jd#(Pp_r!K1GWVQ_IsXP#0MtmOvi(jeWBUs_F&w(WT9@j7z@AZqP1J{ z=JV3(j`Q@K<>)o0_nZY}2-@E(mHr@STrzNxSxd{^=!eL|+D_=Jpr8#M z?0eTmd#J8FwI9>Fg)YJoQJ5SEs}ceXkAe?APYU|`iSSS-w^3xH==4^{?c5;YT{Z+Be)p%@lh7uN zpVn#I;k8}8+fq{~;d0qmr0e4(qnYFYW*><<5$BI!zF?GPz8fi4paea05!Sx`%~z@0m3cu(1r-iC6;L%?K7(9pN{MiiFgPoUbk@1bWuoP z3|`T>;t;{Qp5wna8!peK<|5wkKoyG=#u4SHm@7Sw_eJ4BU2o^?ip!QrOGB|?;vILa z$*PHK|Ax_aY&|uH(7eDueWh6{<%N)=TKa8l8Gwtu;vS6+^#+&|2Qi z-7YD3dSNI)j1k&5BTzP7=XROflfdJviA-Z{B^;GgH;5vfj$sLuIypDiLb$bQmI@;{ zb@;4d`UE|HA_pl83MUGD&MV+j=)|Gl3S>%}G{gKQFKv0am*`wuk^FSj1z8yF9-!;I zNtY~h7aKC+-+?ZHz50ewH|WS`ZiS>%BXmwH#edw3v#UyJU6ssSNnW}#E(l3CC#me$ zO~}2rlJP~XM$vQH8$9-$#}aLzStBGg%PIhf$YudeT3^yWp0cj|G4J44%I=GWOX$a# zpS6?N%ySVFK3)(pk6p*0EwC_LMM2;r;*)|y6H}c>l?}5+&dM3$6gbkS4lP|D4yLds zNu-st>05cJmlNEU4>YTqQVOYx=9%c;rj5{QB5L$4fpRv%0pz;QACGViQR=*5rT?cO zpMwsf=3TewHm1AJEOpTVS{u$gn84ZT5bu$g$^NPAk)Cy6T?)5SZuFjzIR`@fos4CZ`(d5Kk;K%3F^oQJ-QK-3 zPX(1JP@K8|QL33N50|DIGG_&`r!cC|$ePd^AsyX+x=8 zKrd3?UGr`Og~aCN$gpc^8x_xZo3SV=H|ZkIMD{B`4!A0-B%4)`Dr`u zBXBP%arb!Z*00m=XSB4dxZJZIf76RTV$WLPElNQShj2uVFwS4uG?3qHe$Obf7hn!A zLN+gC(Fw7?V69Ph9(M1nl)#H`5lT($<){<|WGN96crTj(pPIP2$ zR~TgbUZW=ysegENm!}wk@2pY50zn!Ci-dG5LNzwD@)6tUum_0;%Xr2mUWK@N#Rsh( z2FvlO)Riz~wGymw0lhU_6A-$6P|C0^$TrqkHx?IHaa*fSmufuS%4qZGc-K%bVT* zG|t~1YU6ElRja97BW3*udXl6umT^BfNxj+{Xr6BPYQn+-0}N_TM^#&X7+P{iGQ%!+ zkG!?d_@{UbPM2+4?dH{Iuc=XO-YbRmdriHXi09r4g&!dA%%M_Qh7A1gGv_pGqgFdM z(p#l>7&Jvk@z@_dYY~MNR2CD|V|3Am3X?0zNjhm>4h?l0Ov_UN2PgA8txi-}WyiE9 z%o8VC0LZpv#AC&a5oF7@DY|8Pa;=y>W5B&!gzwB`3B=Budw#e=5$WS%?TWfZ%*qX6 zKJ3F-Dr7g4cML};DnP)J&;I9_s0Cgxuq~5Ft)l2|4nN_T4xrCusRy8GF^L$*i}YmC zriSX%U^eI!C9-hKK+RjhRxxcL`U;-~J6$)}kU8F-^Bun7dYp`g;|s6-439fb2f0W0 zTcSnhBI06os0|*7;~)Cms(n$|MOoK$G|i`+w-mCI!B`z?=vB68dt#%c%g$RAv%J&!F+aQwM&5K0X%3wKL%clm=jXAWV~xTeCV8*ox!|UJP~qciqIxzp%TX#AY^{Oz;Hp2@&0LzZjX#ZXGOSH^Y7fRN#o<+74f0=c>vu4R&ew@ zg&3Ao_ReV2xywj&8~253FuyfdcseyAsWNHu5NpKGp!AyVm>VIy)XU4A`TI}oXF|y7 z0}FSu*P;{6Pf26Xt(G`*11D=?vS-Xb18UqKt*c^BL3I8X=!BlyX4lP8J?aQx)MLk$ z>|05hQw+(D4UwuTY+VR{2Uw-HG9D~Wk?-tXx0-40OmE01Lb6PYevO4TMt`HE$Gyhw zas1aSmMp|H0_v!7pq0^N;!pYfycrmykP=XIF(CKiT-lN^s#txDIYsHeiyfd^Von(b z%z;kgy}w-P8OkX{s^+3!PXmI_*d2G&ixP-rxC>|^Z5u$go>9Q8+;xJAM1)yBRS4fW zMaoFBZYKJLd+6oQ+#1+a{4EeMi61kwLbf7BT~Z@~j8Va&E08e|Y%>KAyr3i3zhqX; zC~^FG-;Ochmrb}6RI+Z>of>Jy1iIw1IR54uaPUOzP&0Bm(?^#;AeK};MuzJbSo zWd&BZkO7v`ykJVq1dQ@PE*iOvTONoac6_PVg;0A(xsAU=&4Z=ncCNQM6ntO@VoivP z;*2Hc{MrkcU-JkX2FcTNBs!+6&BkcnxTHs5b-uB^T_G<3cEMO0v~dmYIen68t*w^; z;^h0tAhw}dWXk4&7AZL+6beX!JQV=C_@13;{l#cQXjhBi#x_O30dQhP* zI~Ts~qg$J-1=ql{S+k9~qH}2m6KLC32{bs4F(xm`8x~wOw6py=f5Xxk!8MCD1L(5> z(^Mpl3>F=kWzJz{)~|BoDBjFRhv`qT$lv=Q>R0>7HXd&N=RZOHW&kq2RLY+26-zLr zsEyMSjo7y*^EAJqmG>s^Q4>Q}`l5Wp*U6E%9w%2QCp!}lu>QppNV6R2ABJB{P%0_M z|FuenS&0M3)q{wDhX3`kK3V?4a_*MPFM(nToy`6tG_=i+R-YJu9!`%e(7BIL1U*** zZs8gxG?iNxTB(%h(e1n#FzkeS<23zMv@Bnp{{6G;_uI*{E-(JP$0EVT`jNKhTLksf zO7t`Aa5cTGmQfji%ffU7Cl*>Sg|saPHF_&%<8Wb-LBCX3=8;i9BFfe%Gm4J^##ykd z^^GE5U}c`JBhyGy2jJ~#Db^Oek|Ckx2YiaFiY%u1^0&GQrfkSNMgVd7Q&^CcHa$HB z$?Kh-dJt4b10nzbsL7?WuA0timvSFjFlNu9{lC94$rE^c! zLh;KQi$aWAZCHmX%7n$L<@3yv+Woxb-m^QseiK}E`=yTpN+QaIE*&~i`6iaIm$Fi! z-NvNPO?rc=mprYy@Wip7N28Cxx9C^Y5Sg~m{ZH8pnl|h$&g^7f`l$&O4r|NR;|apd zUJ#DO=Z)S(4$i}rWMsY_<_rEj50%(pDRC%>n}O3&^i^x7Evr1sNH*k4L-99#U1P}N zQW#!U*vJj>?Nvy+q09;aItEp*-m~rF1C?^Fwk0^U(sRX<$W!VD(#OYDNhtB6pm@Sf z-RW-NNs3eYGFy_a4Lw`!TYMhJ<$P3jliVZJ023a=H)poDwE_{^O$ap(@f3X9Kuh3i z383-}<`y6H&eKp1@aXa2EEq*x^|dKUzvi9qVI+8SEDBaLcImZ-tJl2s%HoX4%}EbG zWZb&`va%{lVM7$+n@=el16?QBKsm2u230Ui^u%ddnHQQ`A!Mc!ZbnWt12s-I_72Rm-&*Krn(-T zV_bwW%p)@#4ElWG2rHog{w;NFmXQJ(nKEbce!YQb0-d&DE3bdfW-~&~ zQ-BS%(S5jZ3nYfmEntV?(vW^UPPE$A;5AHQ^99~y85?5IYw4K| zx{1?_J8H5i$%oEfwBo}=3KYgWSn!|gc;^(1>TVJv;db0u_kdRoR+jY+3z%E{kjM%K z6GB2ybe~I1Q+AO6QUp$0GD%j*`SX`DRT&_%rjzppzURc>TvOtM8H{zc@-z&hu;EO; zs9p}5tIedCVS!GaqBc=&a$Z=1{1;|H@?LnSQa&(DatT;8{)rzPv&gpr-)=`Xs>&o} z0RloDIPl5tnebV{BbT-t$-2$|aaU23+SRv-B`wx!EL+zXu~rwHqsP_?EG38PTXPOs z?;xdsPGt4bIO$^V9M1n$4k`PMy7WVX4&bC>t&-$c;q-xgQ`^Lv=*J z-9jyib-!v=24dKjiS8r5uAS2W}5f`@=zvMm2~v8Hq@j0i6Uo~2IXF5c|j=cTlR)eTWnG^;}A zL()&(ptvG(+0LyI!+Srh=AFIIvU`a{Za|)-9){hsU=dj17}&`-JwYCnO5rwyxSb#k zCf4~cU26i91%OqS^#54 z@Z!`|MUvW3t%q3<1T-MNQBSNeaEHrh{5rGwFD?Or+O?@CBGpIcYUyW2kN1xiHx)PL z-0s)SzQ^UDXSZgEBGKdT_EKirZH>Z!ygYyUw7-SM%G)2=;YfP54(dhh!K|(m#WyAR zOFSv&hG;n{g?jU6;JcfnR~w%E%8?EXVye%p^>Vo|giO$cw~7j8)C+{b`je!gsb+FP z3^4VqFru@5s#mM9JMl=ptT36P)=&v#sJwVV6*sIQauBm?YWTqw z)izNi+3}0x>y++sG$PrC$O!qn%r+QTrjv_hhILl1f3yr|rvQ zf7k3-Afj7s%EXFA`4%cdJ8^_^XE#XxxZBfY(xiOKr|dAzC}~a#h0|G;h7LNGKJT&( zHyI4gQXA2x2>e}T#Rs$4G{=a3)v$wWnIqO)oJAZF89&kOOq{1mG# zf7w}@?sBCrsoMm2tjwj($nJbNt(5aYNQ9ADwK*c^Q8diLLYA%OA^mGMu-ybVof+;T z8lG&Su)M?rkwjYy&F`^-p;e+=*q*6iEzDI=_mQ~L+z)PB&*iB&y_^%r!qi-3-;K0O zGxRWlNrh-oTSp$8`FyeozPCwMSj!3XHZ~9~L0am?|5Te+Fb7++rSALoR8QJ>f3$K@ zhb^#GbNxGt`w0Y8vMG`ZgRP&qf8AW%>Qo=#%ko zPiyv=T>Dhw`-^oYmH6&Ic{|`CvA=54^&W7DZMN3GdbTn99K8z{TvRCr-E5Y+!2L&? zkL}RWwbzuXrc|Y3JiEUGJN(@xrgedQ*-{TXR`^p069MHdpAqj#7P5+>0NC*bAceW! zmDsI%lKTYQJ1D7{#Uf4n3}jf1_lpP45InjaeFD#uV~ z%lAWm3nZ|gm{gk;coPsql>>xlubv091W-PP5HxABIPP3+qZzN-BW@59rot*>JRVCN zvInDi`38GQbdefOLDlOvx6o7tPM(#m@%0rHGw?C?zeLIvl#U-PI=gZn8I|XbQ zZBb6?2G?{%{rhb|lX_Mrb$ILCqpfwaZi7ePR|;ze9V{eHHXZ()x1lo^2%7_{w?5I@A|rzvGaD#s0X$rIgqIZ$;?N+&uf1%_Sx=T+@kjhHf0 zHWE|iNCPw#&H_p_0M$)5%}iR(uVtex_TAGYhUo=fL-}5Gi_sijMW@dM1@>3g!@>tA zA>QW?GA!V+8sso2Fa4F%fYYX2ix&&A3vVvCn=(`)35WaXCBsbW1b&$2tPx7gqGeT_ zOws+>KG27R3+!I$dc~~y?!u|vPKL=u)Mrtk3ZKn?Q?_IdaY4hGBK`{VqK>lZX!j8x zAO(}Xqy{+%`Q5HR^Nd;n{vpJbN59m9G)|o`s$L;?Icx%}iI0|_dxgHW8?xE2`|fG1 zgOaiRd@J8S>+##Dn)f89^C<|+FsmdUPdb2PJhwcfogg)FZ>D>IbrSXLQqUOgX8?7j zF6Lg$_Feh!OZWT+az@!yYxO4fH)T6iqxa?Vo$da={y@HMdZRmd@4cfI#T`QU97L{n z1=zEvoTT0+)Qa4@vxdiVu!7e+=YIl-Zor8*95yYc`eBeZ2m{GdY|2|~mGS><604o< zt?ER`Js_OBpf>e%7TxcBDwZml9+FCb8zrIlrB{x#vFbL9_-fwji@e7C%AmM^gY*2k zWTCu4w9Z`Qxw${L^A=UM+%6{Bd*=8*3LwSHhI#02yXWA{6Q@ zlHe&#{%a&u2-%DlkjncQ8+K@w`@P+BgDy>ljtl}Oy z){B?IUCvY8rxp|Y9G+*hr}bd|^U-Qa1lCaXIVaq$eU3SEj~OatPbWm$_+l;pCC&pN z-bLzD5Rz0S4+9jkm+Oqn|1)`d( z3K?skJ9y{2IZF>Lnh$6stIjL^AdPSGN_3-2F_1Uk<>+)kv=1`uG@$`ia2xcB0iE2G zxa5VdG&f34EUgv{Hh}PTBs6FRM;67NxJX>CdCt-^Mk>xPuooI)Ir9lKHlfN_6lA^* z;XRzRv$^o>7N_5`FMlWW9J&qr{D>7VwgutwS;Dv3O)z#QRdvysAM_NhUkviBRAA&0 zDC|=QaEioI*U?nvT(bx7>dVC`s-Hk$XWF>)vJW#kTW@M%tgbIuQUSxPe^N4?jz_%p zzNqn#Aq5l80lF$@VasN%`Kt>Pm>+?@=$$qbx=X>=*4xBE<6lqR5GO8J>x}fE{G4U- zX-}PW%pbOldDyQ7<*QM-)@GIBd;D`HR=BEtg z)+=Qgui*`4axT|{dV-TC5R^QrEs1nM8|(&HOcV1TQ^P6xKS3*MUYrAQe`X;!t?;*N zzAaiy@jE^#xb9>EZQ-F-y7($k(BG}|BM)`AG|xt0vpE%>`n)nS5qQ;c#4z1EBjfj4 zXPb_OK}{@_NR1Mfm#_A)$gR|^pk^9Pwc;ArI|;4?HSu|&Xp=tUrj~v}(ZX0ulKXU3 z>Rh$WjVQYRsz5Yes+LNVs2q`~!L=y_Hq$SGl~-&KZy(iR!7ur6#C;c4;>r#P1bTpV zwBfI~fykVuNmIVIe>+lTMa(Hjvgpq&pK~Ma;YMR6nvD^`_+;+|{>{&J4V;5I4=pf$ zT}l!xf&uB61OZnQpzS`jIX=y*PjEgzL*QUS?&dq1OTVtPsLP>NTOl zaJ5kI`7$^T@8}nq$tH!zRe^*Usiit7V*Y+Gp3kAOFY5GTWbj>%e{Jg#r~Iz?q7fy;^5rn4!Aodz$&y8>Me$b&cUPmu9exH*p}01ixnJ_c1~S_z}C{xn1-`s68iQ4Xj7GucK3uyeM=<)%Ysc zT*UzDhUkM6UMjtKud0SM!_(bti4iMc!HXnxSoxqjl`$HZ+Dh!j8s9cvxRgx(SZvmG zaNnrc2cEu!O}-43_*A0Fx_tY$S3OuwBczeTxHPxHC&st!wNVF7GKrncp52hQ)@MR5 zyIiRa;(euf3SJ=*bz149gp&S8fn{I}k|W~vVh5f9M!o&FU~&8bEWvh4+uaK?SsfV< z@uc?%A4EwZvHhb^IG82t?eo(3`~&9!zzWpc;1n349-N<=b%D z$yxH#*!QA{aoWHH^;c5|Nxbu9e z)XJw#@s|&o6T8+Eri6vhv|qD^<%7j2b1?bOAzp|a1d+NZ?4PL7BOz1>rykWqF3dOW zHHs{%8=f6V5pCQr=A4E8L2lRARU9=v@FD#Nr;*(3>@H8)$Ie`k8k-ACmW`tVA+blg zHGAtdxu&6>A-kGB;^YlL_`L3!;hVij&|9#49}zF<>YySj@i%&OY4)fvJI!6Al3|CS z-l)B_BSGvBdoJWY7IlE4#fUOo4-P4QI2H!RvM3##IUVVSmzdsCwt54klV{PM0^w#e z(qgixq7p2-wLS*wTZVu>_4&;WSiqHq?6y3K3HD^l&^6Of`H4qo)C6bb(3h`>t3ZHp zMrl>S7{Oh~ii2^Y#9(SmDG6m8$R}&l3lsUfK3_{c`94%Zvgv~+v(o-T9)*5D`|@ku zY0;ji^3+!!0Y6+)x11q`U`+C_Bb^6e3Vlx%q9#{_pE$~iMK~58h?sSgVWIRx+`EJ| zqTZF(AnJy{$lCWgLO}L7=R$VKRX4}lmU??|ns~!mylb71ML6^{%l0jm5WUe+#S+@L zH#!D;`z=(8Q)gfXqcFL>IExirMh`vKxkl`U3o_6fIYB-YXg6__n^XL6K+xCj63gl) z7ww*CysE+QWdMIukBQYn+>{)AXI?O!dJDeCuzkPX6x&@Q-qtR1oRtz^Bxj9QTc%3d z!W22mb%aqTxxiw^(vO=>JMN4vEXX4yP_@e^RtCfOd84yJo_H0aZflen%+d{Ca5C^lo)TK zw&at&>+0|E-cMrgke1bE;(v(Yr9#>N3T=cFP0YOwwDhbHK0!t9?d(W7%^u>WN6Nn< zCZ0dYahg_*vpDNw!2K1;94!8Ui1UAODTypj%mU$S4B%{q6CcJR<}sqVwD?LGXeDj1 zt>Vg_uveI{t@S;bTyHNGcg`7Oy>4Wg1~I3K^}r58Mpf2!jM*$iM@-4m{BS|%*?}H8 z2Bn3{4mZxnzv1;{-l1|CJ>#0%fOXdv0!h5bojGX5$ z<$5B;A@w6p(XpmFtl!&3-l#&8kV<+hmZ+Uv0Ppy2gttzDADzGdb+CofxRdrYi@6Q& z_UKqBvp$cSavr)pn$US0Q9KcW)|kN}`XoC9MKP7v(9-S%CaFw&XyJ50+`9lF=)MLg zgd1zw%>@#_~j==|Zq6--)pH%VG1TXnqLLjOAgN4iT2|=<^j56fy5K^w*TO| zqiFoAc}0n-!zZQ@K0}-MMOk3G$V|_*eTXj&dguU&_UF5u;}*JUUY{n3&t<{Y4#=YF zAq6X#7F#NSI@b#E9_4@-Nj$TKXbiY+y&MT6)%Og$dD0B>1-!ogu1@|kLaOn4{HXV& z!cJkY^fSuYEnRpjLQo8Cn-cv+qYoM%aftZGr!~oLc!NhAj zM%T2$z6x0LHa>Sj%v(`RT|d2>XfuP8SGr}&BD(419V{!)$78cMqjlnZm4h;)p;Gv= zETDHE^Kqoz_fA?KN+FT5ZZS|5t`#e1MP``%#(&g*pWZAmizlr%|11p& zH&Vc~+2oxfCXhw%7yT)@9755Z9~7;@@C?u~rjAT}vpw0b^MO=N^y6Q8WAe)to)xyY zX8~M~pEE7jWdvx>k9QE|w@r5%QN4U1y zh8SF~bid2Hb`(j2V#Y|076b*-*!!TedHeH@Vae7uDqqH637H4PB?oei*|1g2yKUuu z=NoGbsm1tn!R-7B22MZGx1I;f;|*V&@y+*mbdHMU*fZx5Z=eIRi-$HD{$p2BhI7-ttUxp)b9M%8Of9G<=MY7@0uX zCig(+vkAtdn+zT)f+nC|F}Q4?Ai|ksX4Q{XGHuE|1bH3XPieH#vH(l_WLQ(PT^Gkg zNA60ix!GR!?o1WKz3%7n5mqg;o|k+T88ahQ7D!r+5jz4qLhOD3)?p2YSvuIN>A`z6 zXVO=|Z=(dJ_qMijSF6}~Z()R(vLM?57-1l72hYwB)gS&5)6?d?E1-)kQ&1ng(HF$7 z#80_W+29TR7)&?q4P3Tkz)4hC?fvC+7Sm|KnJNe+j^6p5bCpW|fo%fA3`fsH>mYa@ zTp${Z30N{JHX)wD;dOMd;Nv(3DS`3^T4nOfP031osWSjUBWbo#p*lzY-hD#edM5rg zV~s}4+s5R6(!-ngH}DuV?9Dk!@&w#oMvkg27X;TRr>!c?*cYVH0e{PZ6EG>5)y2cG z*DgPnEV$jEg=CaAjFD;tZU5Ex7YwYx-wqVr>UHJjV3tbsU-BY({qqIx!@vm#%Q1aoErMq}D) zP@L(lEx?QnjB0P6_=2o(A1{Z)uf-~abIo1Y*H72@{1fmzTjHAjbBQdAS}+ikBKj{8+(#J(laymN zPBY=7Pu|cwXMTZ!M8A&wMgO&;yN!rQ*g`VG6~Sw}5D~@d{v&W+62Oh7u0aI0*%}+z z0q?6&!u^$<*TXoL%{OZaDX6_CpG3yok4J`#W_6ysGutMXtAx2;hb8uR-hQ%)EHLdT zTy6%4>$aBv@5?8SLcWtN2z{bDy@%Sol!V1xT|s$Y^2fGAxb2VFn&qJDeHu>Zy|^eJ z$<~zhNfi-f(}6KU0A2{9GCQ=a!#myY94o-Js7n?H{;woC<@;+zn)JB(7L7_8yik!* z_6Ll~?}d1DsMnk!S_EZy!h+0v5cp27hb+Zb6;Y-AgUc*v`DOb{|79Id zyD^w$w>EEj|1vt!TFZCE#%nf_^CjPf&QXxMUJv)gU^B^a2W?$UyVa`7vH$rjcHw?t z)f(yr@>!+iU%R=1rrJjJgX{y4C$qDKUwPPgkb*QC z^WKw|L$!5uxBP(}D^z7qPq3aF0ue~!lfC9a3FJ8h9b1Z!G*tv7&vRm1C z0fL^^65gPqekR=+t7byHp!2wvW3bBRojA&J!##y}~Z+N7nOb zX#$NAp^tux0sKXYM$05-fvE^pzsAeI<^_kBC5baR)WKe0r-eV>N@{h_YGd)+Du7-< zd}EY=eaLU4`r%cJPBXvCN`V~kgN-t~uYQ)YYS6DyLeSDca@5R4`irwr@HWQBq0nM= z7Vwx?G)@;P7Kf$VCw%qdAru7*w^!_IwoEh$nXbDx#$O7Yqg!=E6y z@?fLB1h$So{Eu7M6z}IRllA}#YX|aJhqqC>EQy+3vwd2u8rpaZKn12WNU^o7&wn!D zDRK8H%K7<8m2H?VIClQ^sIlgZ>@6vAoYyXzKI?a*%s~`2*#7z_6YpXJe5EAo1*b?F@b=6dm3hn~ zwE5W|bE(HH=9`pqNLVC9A#m8eu!IW#KZ=H7Y4flbT>soYi}QEa#p5X<@9;QR;HFryu3qTT~zz7M8~-{~L^PT?VI(Xt)ZM~7}P4637k^$g`e zA}JX9&0hXunJ5`x*+>R6EChC#a|E0kpatv4hz7J!gcpAd{Z%carN-h-|@rO2$<3vdkIA zy^dqnJ*(kiK5GgYh?0!P;Y;8E93x(?idCZiXA|VX^ioQ~G9-SG2_>suY-`Z;o2kus z6Jy$sTu))kUg6Or;rQNcFnadidk(HExrl~((*m7SIl;H0J`Gwok_fsazBg06wf>+m zrfo#Sai`o2G_d^hlk@608^ds`$xV`C7xo$;^#9(3jF^)M=@PYtFNJB*TE{vN2TvVQ zLtzS52!WR^fOwr_K_rcFalQCd=%cjGK z-Bq3T$)9yeiGC$tTM(2;gmy(&@J4~1qS5sI7Jm_%j9gatD@l066W-9WpYO=^2zL4#<66%uQ+|v&SBQ$y-B{ zdW>pIX_7q1aUpwT&?efYK^{ezVe=37*=-b!Nc7|mP@cCVZl>y;%&biFsZp^M2gP-4 z(PImNO*2)+CH*kF#|&agHN_L8-+~nmBS(*TUm!kDD@xiiGC*)us9Ki)XmC(j(2YEFAlY$$=)7J) zce6S|r)FO~`2OB{Fj*Og3O|}ilTdf;b&}X%al;e$0Uy@_q!6ybVQ)4FYl&EHvG;1t zWp*MpfF)oo4*ctXCnOn2a3q=Xzv=;K97$Hv2YB@L3`8pb7D<{ei~8@`EaEayxs=~C zWMYemk_nBF``6dC7m_t3(x=CYbVo^f6+57z%I6;$$t0dl@*c^hX<+G{_=JB!=peJD z1<6xu9^p55?t8yO`lg>6Uk_^(H4vseh<+YDk*ReA{AkRKfbJ}Z0+uxv`r*7=`Zs-^ zrsds-TrY`)#HXmx2(pYe)^km{Fk>8w(tU+vQ`%Ss?wphjPCf#G$d7;joD)Tb^nAB(p z>NHjTs;3VX@pPq4G;}C>AGFB4DDK9eJtUY=mM&zTBC7{QW*cd#3}*zS0IDLQ*TGXl zCf&mYj1|E&;DeEH_`ry3my`{mYOefKv7_w*GG$Vt3Y3riUJpN98;7SKEl;_V+2*uG zFiA!GvSrUZgvUtF`89uRvAR4doX zO7?o~E~W_?0rF?OK$D}ag64o&EZmk<`haKjMy|r+(U?J1B(A)}wH=ODZAj`+LlfYa zhb3c3xO&m;P{TOC2d7fMX%7!BAZf zRD&Y27~X9Gjy^2@IaYAoX3a1ks=(pK1WANid2R-Gk1{M+ZN(3QV%L(-9;`{w+)vw1 zzS{1YHntHxIYR7`4>x6mS-kuUAi3{mRLa10z1{ja?{H|%7)9$suq4}JTYSpi{tx|} z8RBYF^`#v3526keRCw_I22=JAuccCF#P?Nz;pUdKT3}!{FM}fJT2~0PI>U@$S+s&? zgN|$J%;v>V8PjRmFxf{}uEBEcj zzY(Bb9IV@UEU_Fs1)JV)IRoAtwRr~C8m<}owEcsX7_d>}At4^%N)KOQ8h}v#^oc%Z zcXKi@JZp5OAmbWytjQ^&OyaJ94%|M&IWj5h(zGSjpS1;8k`~zP?(HdiRxfApSd2bmw09FkFb|} zo%9>A-2}lxIL~vpElc%);>pVQ*AtThZ{#|XnZFRR)uayM)X;ti+D$=#3o5|j0uj%Q zv}jM4r&&K_Bg}+npgh*$VMABQq*^Lc0#EzeJ7w{C)n>}bv&NhAWN1V&Zv8nqHG+^l zw>1%*K(m@JE|jI@@K!Kf{pX01hX)DOz$kug1~0x6ha}EbMY?-!ywkX9kH4@GnVdK} zZ7(JsZ-YPWk*ts_BKr==z`B1@nr}UW|HqJs<5sqNB9Nh#Hs?RJ${C~3YL z{@wfVm1-HbE*SRJdLXZWO=!e@jP21Qy?emOyPlYkU$-M6rjr?G>F31y6pKFpkPc0P z9gL*k<5s7dIAS+N{QK7}PXIwuJ!?=Gm$^*n>S4`yPFJ|aWU7V1HBj#&Z|;8{?AHJ-;$%VRpS^NT>UEN)G<=C!aeOXV z0k*toUMwbq!m3^7L|$cf!z)NUO3~36$;cH!HT)KfGJv`f$l&mSU43!p0e=VL?@^r` zz%y3&IPNVA5@)qua81Y6_)II!2D#Ae5oICB`VA@jzmC%x!EZ1B^{Mq-x20@2=3jRr z21eD@lC{c?jE);Nj@*@~6Dx8jljPgF(<{U@eZ9}km5cqFxwE{!(IT%Sq7KV@H7YHJ zhdW09TC@|X2(L@|=KAu*Bh2&Q2HklcrYk5mZHr;MEl*xdkqCXUGzvx}k$yLaVYP?x zQ7A^E0q*p!VgE%t>&I|bk2KDXnqb*QE}mHL+Whm$(*gh7regzqq5aEnBVP14nfKD)j$C_wu}*p5!#lSWxcL z6OYM!un}5)L~ml?#Pm3elfgsWDz%ed7%^8Jf!arB(ka`bYl#sZ^Wi1?S45|suioLKSkICo-<1n&s(OmG?RjEs_AK9$6q*1N!Njs$l^w4W-;b15_wkv-K{VG#p}b~nD&%7qfg4AL5oEZ z*2W(`)O?uO?J{L(oGx8$JL)m6Mtl++yF9!*&P*aVcXc?fLa-h4m%sS8y0cx>Ed<7a z#4Q!r5?3lYAEzI~ACyue2E)W8cxQ$Loh%>y`i{eBZWs*NuFQJLWCI7cf+^As!(%tn z-fL_pW5UV|l2BZxS-{kbUC$?Ei_e*K8&-lgp;MefM4_&d>1SrS?wp4e^jk`kKan1` z+_+*`v*~{uAp9n`H%&tq?m6oS3I%1Pe(7!>os$0yF|4>w-vFC{(sAZ*i zv1xKxxEhXr^r94iYlKN#wEIi=+Ch6j+{hB_ZcUO3Iodt8LYRgobga{GPVwfRQs-9n z4v&;Ka^AS30Tv^mg3s(T-F)NGTGmR%lGbZ)H}W1yb;0@Gq5sYcv}-6ULR~|RVLzb% zU-P>=N2Y+(CiSws!%*qTfUUAKyq`#Ps^DmE4%Gp)3dS$a+imMVPcqHe%}u9tQ5`QE zUPj7#bsFmic!LOcpgK-0MWQ7dvr;gbJt0Tiqj#Xd`82e`Kyu))4oqHPt{$wbYb#nY z;BTr2j?Hpu9t6VA_Sw66)-XEYm{*3E1mpbnAG>s=kqHZGu?@1_7w#Z(+@N#Wp<7M4 zc;y3GI;25$6Dh5!uMsM2? zC44i)&kr;{z?g_RuG7!{H}LPSld=R4x#iviUbM9m)LS@{S#rUnftw||ah!I33Xgwx+KTW#-ejhl6aJL9EHZhQN2Q^vQ_`dy0a z!+@+c^^VAqy?Bj}CK+NmJ9M$^VsjE24)1?271qi;0EKL1?4bIL-~^~{8*SN!t?c^2 zZ})Ppy@1AXEPp9>m#+-H29BcqeUnJnCJl7lK*vd>wIN|x5l5s0TbB<;&>PiqkG-a{ zr%V=a z@Q=1y>7`|9DM0kRsYD36=W=M^L)_Q*xYVbkYTH2vGF6I#UhZaUS5Z=yf}YZwHI zkpwGg#tMZNY6Rv@SLEPS&bNvC&BpLjM~~nUsL0{GP*2-qOsf>gWdBpO<#&K;)JJuo zJJI*KmCM;O5_TvshZ5#C+axVHF4X@t=D-Z+=ZP*rCYv2IftVAY_hMuMj&DX1dG2vb zowxVCt)>A&7k&&_)>imiLZt1x(JVGtzYyBAauWS2SUuf)UbaBT`-`F{1wZo5Ro(L~ zzrB8I@MbhSk?6<{B_A+KU2No zoV({emw$iHi>JHv;yTZ{M#sUaIDEN!X)eysBg`{(N!p_Ha@ zpL_BJo5@eeOn(j2A@2$N8PQ2X@o|8tC_w7Jzik`s=5`lv`BpwM5Jrkajm7Fl;QDhFdVMR%ZYR-AWGU@gq0d!BR2l_7 z*OW^M#rKzC3ut91u|+8{~-Fzcu2g&t7Td9Z_SW(P-UgIv5&N4cb=Bu2%g@+kcJ0Okq zqMssCUFmHjkutf10CQ?zOqgC-;d=SoE;pE^^B7ETv19?F;@DpHdV)^QK(*CgyHb;% zqh0TP!E$CzHhv-!GJ9e}6$y`#To$TrY|y)j8Rw??ZyD1b+EZkhy`TgK-={Xi2&oh~wokU89MF(s9RA`2GURxPqv{ZkDUB!1oFdvN(Ho0WLrNO< zDCYiJ?n$3@m*LXI5iMBL$M z5N}@4KG9D)vV8sRv`O#b1dFhCJZ7k@idHX8s>yMV6>CvT3km zKtjv|7S~BX#k4LotCm{}ZV5zXA#ptaB$w7t^IAdeXeJKBz<2q&`(a9lQ8t@7byb=L zKuLuk+eu5pZ4iz#I=NW_-t#i>^JB^9LJEu7d*J?oUkMm7X8#pznb`J49;?B)=O#)v zcT}<+)c8{)-w&So#U(T&`PlJpxR7@AGDWo0rp}5rL&wsy*>tUsA$jJ$8_zcWNR~i#QZk3r&IU1{oev7B0Smm`^82` zuCq!SNN)~|xxjXdQ<%ruP&;wT(PrR}6WQe&XdXktdn6bcUp=_uC*QS}`@zNxGoGjC zFm$mJytc_2F3=Sktbo|ygfk)P-Hm`nhkBB3c>@z(631Tpa7f&m!3 zE1a)>5*vEh92vK1wBJ|9E1Qf(qV>mF`^B8!)Z5I`K1XU&`nn=7 z`}MEbTKn6KV9WQ=+jwxYG@R7i?>*&_c+&&aMkd^1P%$)dQM!E4Jq9gDHPyuZsODu= zREOC2L#Bo-5`Z-BmB3A^bK1?d)1T8^Hm2#RDXVL=Ir zJlc3lTe321Y+&3gD?(q`Z9MJ@PKG3MD8B~#rw)JVaNilWQZ3Rwz)_p{(GSpT;P+>r zaW4sdahwFGEk%HKd}4{>cU4r7-H`1wzznhBcP9&Ul6Hl3=VNi0595J3=T1eg(Lg^i z?9>@KROoaC_%7U#6;aO^Lr;Ep`hV}JK@Io9HyjP7wG4SZeREa3COtFHC3VRwGseGU zbq{_}d~>%UKJ-x*A+sbi5(psaj=%_Y!I*IrllNO$8-;WNy>wIc`)-AEFc*80Tmi|3 z$^|%yU1{iFEwXb%X^4dq+i%*ykJgGu^$Tb;E=fdPPnY6SQX`x=T#2!fg1?TGw=393 z7B|Kro>d3+j?(+kP_t|{nY5BoF{j5em#@I&^6GPz4!ze4~ zn-Lp+8DPg&rmNCgX%G5(bP@!gJ&`UYfq;vHa`BBRHwLZ3nIYZ(>;P_m(X`=~4gn~Y zcSU#i2UDBqf{Omnp5axFvghpqcW7xy#4)5J%eX2-ZjmKW7=-RF3l136bC~BuKm4(% z^$Lcz!(3Y(JhU#?>0dJwS%F`ZhPWOZV_#tD3ll&yk~7u0I%so=zL(@5;5c&*xl)N! zko6kC(s=%Y_48-Mb6QZuJ4qd6BhG=)ri4j}94y8B4E%Qiv@E{Zrejmx`kaRnUYt7j zc_Oy&f%{U%fh&!41}i9V^*AjtsaNeLUhS8^_dByA>GcT+5NA`9tz^|HTc}Swly`y! z%Go5~SffGCG$)`ohD%bd%L=k-!7zIJwuYR}RAmxdME&=TOfiwFaSEHCF66BYK|YMD zS^uQKwMEiYu=&AwbA;ve$}lgvQLuq*vQ*=aP#g@fw$)4G4bn<#jhQF-C-GjFmW*L$ z+kR{FVCBSOGiHvA@25`#8UuOz%Y10yV*VIBJ}3N@iDSUgf|#)ec92qSh97~U(U9dR zW*>k@dlO`DF}>DS48}obl1gp1mVtv54Q6@Z7P{$%`F5yK6rYSdzc;lrBj2kb@|Np1 zvLs1W%mIFJvY79CH27AEM>{Uf(<2N|)C)gyWR3TAL-OV=ETKBk#R&V1oQ=|gt;E3s z(?ZH53L_b~)ChLMmW(vFm_Q*y|IXQIZfXN>0yx}zDI*x=H(^{*n0 zJXq+t8hV)kZwpwtzkKjS3_tS>Np!#b)08ziuumScud+wf6Avw|Y<=SZcmmd&Z0928zPI(t9wo>LVBVm+Ye%dA z%v+Y2h=ePksCbxkfv8uJzJgsIccBOQMNjP&eEhr!afJR+FXpT49AY=~`JOw4Vcqv< z53NT<3*r~rgrGY}|M)6z35$|AwoD-h*f4!ltM$$1tK(2PHnBdRB&nMB2SfkVFqReV z_AV1|K=I8`G2ZaNUUaq>o_zv1>@lBnYV4fTtz-%%zjP{edJc4|QQ+{uu%mtn!PkDN zYEo>=sj6X^S|8~s1=D6IIsiUT(x?}XwyLf<4`I1(c8Y}9g3OUu1T}=TWTpEZDO8@M z|BLO)c1AeX(x3FT6GQ_!NuRp?8B_%$i23Uc-}3q(&qh5Rr>V67Y9cNe{4>G8q5DcN zFiE5i$y#>>Zv-e;6GOm;p%_NzG7*#y5d?i#0&iQ3WYqbb?x{fB%KY9`MT|~k=j7Lx zdORv}z2;K31W2bbO5;uKh!eeWqh9f#vRx^0r#$YJc5oqP*E*`y1rL&^zm&9D$9~dR|>EP~rph4wzCTr7{i= z_$?*oGam}sM)z83y^((_sdA{^1<&7C?9lwcFIAkSO#?fU+VyCxMMtz2PM*ZPXlFQz zgPsonv*K-@_Rbm+9#yaMF5mq4I?gV@4MH@1*Peli?y2c83Hc6#&$2f8cHoF|J`Yp{ zMZN+n`$$O5rlYCshKak{5e059Rk>;AWu!*$k@Zm*+aoOWEB#-(Xh?SKo9GSgWQ)3{b&;uo;bb&tKN! z+*6?H)Vl=T=ipL#^TB&s$xIL;e`sc5<5u>wGOCj6H6jo%q5;9Vr+s+wWWIXD#^XFTepx5aEm!X8w87{Xsja>l{ zpe-)xZv@cOI23l=Nf+U2j-`SY654%7o)f;n`%VOe=uJCAO!gYKb`*wuZ{3EPILr6(HIa2K za3}wdU18(i>~20!^@{eSjEk$~z+GL5jzS=k(WrEdi?YOLX`8q>Qu$<)(NR?cxD!5F zCOT9MF5hONCYfUHuc>RXY$OjJ(uw4+ejHFwB@5`=Ig-ADjADp-m!{~mJez|M*fR3H zJX_wzgEA7MguFJEcSlLekq7(d^IhW>3H#DhLNqxb;t5p@h4`WXV$|1EG?f@y3BTw% zxgf!VcHU0*?NK(gm1LbwjfAC1W(43&|L6ygeCcM~%=p2+sepXSd-xfDFh}f7KZpGj zWmh3pyGvWfd}-#<`jxG}AcL@(z_FrW6KaO;FMeu8D7JJi9DTU1vfhb}r;P5hwW-U3I zt-{fQI0<+&p_eyL3+N@RqVf7w)b8ztiR4}PN#PZ<_3>c0~F!H6){duY{K4fMx^@Q zF9$r^)o1f^6lShI-~WFRd^(^GEfzD#P&z}a@y6AdwM+3H6?EP-yG1c#+d6r|{s04w zD?xHVY#~}X5cJ#iptG!gtWx20L+F$`Z&^BHtY{SKTH?}8J#VC8CrzmK1M0UV2PLC} zC}G)$d(Lbv<%l+4jKNG6i##7KT0r9oxK z763CY3&>o4_XVw!$4cN|6PwYxvtNj9`v=s!!#~i0EpC6|+r}PQ3+Kx{Pge(_BIO8u zI0-TQ!c-%r)1{DZAqd|ws+meGSQNC&;8=T4S0&m1OFxElHYQjgyx*mJVaLZ-K|+!` z_U-kwY%lJiDGx=w=GIQkg5vJu9g8ZHyStCGxKQ^qT&kJ6Kc|?Z#Y{hyF@(MPwRI?< z(cXo}Y=tGv$j*9A1pr_U`BZgR@GgI*hIIh}Z;Ly8Q}|ewI0|fbMMLlXi6WM3J_b== zr-dM;Kb+adZ85mH)%6*49v^LlPxAT1{ag>0^iIKshFFQVyBLHp_s3Q~Fl$EGdR7ad zfkM}$0|dyXhi{@G606}l+#1#fM39b(MT={2jGH$+5q)hB3fg-tpd&3iMKrwYTr||k zHB7?}m4-2YJ1fuOxIWgdj_EZR;QY^Ry&k>{p*<_X>v+o(L@`u`tfWS7K;q`P%zuUL zi)uMo)YS3IJk(-ID1gD_RqAluv$aW3H^kFL#R(v(#kWHBN~1S>iUJ!#z8a?}gn1^a zbkk+j$->D$o7;u-y1zbEHis?{D$ufWTJU!)&a{ zO>s2s$-sFLW@ zcz%rywNxR(PaE^h_renl#26YOU?gzcE^ z+=sj`h1fl9y(wHR16C!!Iqf;MKDwu;abEK@>;YV%$RZXxZ)| zzlPcGup0tTc8lC?y-XGsNP&?edK1zBZLQSMV=CNa1UCGjwn$19KF>!!7G1g2|@ox?2XbcvgiZ^hZ)SoT# zxAlTu*8XkepoY_n`w4(QEhp<3&$xfz+TqFJoOmPyLPX^Q3hTZnG$u$&?a-+6d(H|2 zj+$2|F=f!}o!5&=BLJIPle!}jaZ*H(!^f}|V)Nq4zaC6^Py3?(AR0ORO2QeYpzEe{ z2p$C&Vk)onteCJpanzdcuowDRQ;$Nw+f{fF2Xlw<8hJJ|wiJlCSVHB11AP1lUf@7= zgq%}~Lv3EISusL3%ipFP{Oa5m%&zE@Anj%(=X>AMGj1!(xg0uWJEJgEqzBetZ`<>P zqlaWA@C?Q3|4XW9+>&BsA5RQX+#8=q=apMTRk~AT1Bst_Eqvw;`KVzG|G#m-)=rHa z*fiy4?2{vl`C(YZ02X>DYo&H8t@&Y-D(wTYKNHDlI>?u5YQMD!S~72TP&K$`0U5uI z_+=@9Ib7C?)={7nn#KJ!_gmA>asqOVCk4+m!@lXOtfW_nJVwe}_^Q`A_kY&GqO=kE zSPEK;a>Vl12CLyNj6H?9-12+O3RbPb?aH6oQ@r4`G_IQ>lfSU72xFO@IalKYa_?YH z(1?U)Nt2KtvX&A?N~!p?63n7RPiblX(5zb>*UKc7Pkg_bA=Q!!x+T7l0H_n>(>iLu zi7ZpJd(DN3Wb@$yrj!!Nr_30}Z6Mi0HFF+<<{l53=?_%AIiD_U|z!rXUu9LuA;v5`r zlpDLEnhb$W^nqnn&H-!a{6`le6l&0F%v6`6S;9lRiSLF*BjzzC&grtOgIw;rItwYQ z*d8dGSYFn>&Yt~W#^l4c+jO$!W>9rPydtH0pHUR>m39N79>HjQ&(er1$;>OkcZb9h z=O;b0L!(d+K%C`(e@|%Gev*K;mAXmCuF3cW7uM*~lXZvOr?`@%aN$1cm7tt^Wb`T$ zUR#d@d+cBfK7~oEg2{4qP(1B~jV$fqJKRMlv!ZK$2zBIUhhSuzfo_ZlTOf`}&5I5} z>nf}C2%y{t?xc0Oq<2x!_yez1f^neB3N09<18LJ?!x$!XK5tl)Ju0l8YiVoOSaziR zwu9>OMp}|ma?5PBNGfUSYx~ZVgU_9~@gtdh{m+Xu3pcG?lsK$y=wElx+Jdy74coEYZM=BtAL!Y53ks9?icm@Y{UOlxb8lA_UV*o;g0y^ zG#wTmdW0I>;6|l8=;gtNyxsVV?f!XP%n3C|PR&~Gv%4V`J$$kvfB?s-&AW_(GuBoN z4FQb-|37{OYd2x)5C=}FQ6#k)(man9cjcMo$C`tIJ9-3Y_hz3ZqVZy5KfG69}is_{mg@Z(d;^s(f%c zGx>$ozw`T=KFgIG`axua6`Gw{C?4dl0I#7hF0A!D$S{uD!kq^lyLeUW!Lop{E<0>Lfc9@M7UUsIN#C8d#OaN6|^Vn-H6 zc5`652eBhBe}c6s*|u{0#j4r~K=|3lLb#5o>P1`Ya$Bsgc14hQA1|Ma5GoX#lhGEx zopBGA62_22pc%KJgmH^FM`8F$5x&K^PxWBnV)8svtA7EHUe zGmZumJe62UJJB66PHZaI=zh#CJSdlz?_{15gxhO(yK~Jl_yP10;fET6Xcs^&ActCY z2PK95J&Dzj)UweL($*6w6O)Q1H^Z~e8k6H1RtGjOViL!aTYWVPOXKi!VW+Qy{)fPn zVrROh0w$_H?h0<#zAAcZx*H%L#gxCq1s)K^4>(W~QS98oHG=247lQV4xlI*JMqYHo z>oB_nyvGe;U-ly=!_fxd8#`6JSua$I89(v~Qs_;rYZg-BjKI`L?ytI@H2fl|XyLM* z#j5%1A{l?r>^R?+O**`DKq{Vk`vLUJkls_hK*?%OMs8C-bL<&{J}@Cgr=3GVE@ zaA5Q{r8~v}{RVXBneK9jIq0w;Kcb~POQJEsH9$+DZ9^uxz}@nHo023 zP#D5%L0M&6*-3n4zeZ735^)7G=g#Rnswxv&rSP;oje*yJYz85k6kSSHH8?l@g{G z-zFX81a`MYTm+1IMs#$vE#-@1n7zvcQw{bdJ~Vt-qaR~FFg~LlT$#xe1`P*8kl^Df zBvfWMZ+O+y7FrUEhzVz@Z*9I6z77UY1I_fIc)_dTA{?&jqBf$pQKaZJS|bCf-2e3I z_MH{vTpD}Aqzzlw)~ufRkFTZKv>e%5FLIdbF8kll(QR?Dt8h~nIshCxX^e1d%ELh@ z#%!*=H4_w2JpcUV%uvQ*P30?rT<=CKN^hMCeMu$r=kxzp=>|xv1X5GhvB8R!cd%Oz zN1Helq)Y*lq}>+h=wo_JEYkLiCa#KO8?F8hirTfIH4SpljujEWssCB+%H%5SI-W*! zDU^)M;P&auFcyc2&i>h}WU%E^u8UPhG?#y@==|{oq2!zGq9iWZ+s%--0Zx93oVm=w zVD9T36x5=Too*U!$1g}L2ggAbT=|4G1=P&lyuBdJwl5>6^J)5djP!n1V+n3GSa^#r zS!*V-cMgdQXF<136*oMF=hd|BNR7#O4JYBz1M|87w`EE)UXU02;~3hH@hGq;H41BJ zhk>ae#NYV=vGaxJDyREX30CK!ARn}(GoLsa^esZwfzY%0KG&LtDl+mb7R9u!H%rd^ zt+_Rba8UwHj|32#F&EC*`sI|ky*yePLgYuuD&xWn3vD|fh{=ACwz#iiC zj}w$Ui-AA+-l3}mK=InhU}Pf=j#vz*CXpD7-e1Xf7zK2RUE?Jq`@NjAA*G~Pd$=~R z+sNivV^|_EO_VgK9?x1Loh$OpI#T}uG?0F;dd&h~<3-r@?1B`v7X?X{fYO@tc0bCk z*=mww$&b`+;Rcs0GvvD`xK!MI8~4qy`smHVN?}SsTy-M_pnCB$-ew=|IW)1XQ7ktZ z%P+UYv75$+EOm6E{kN~&^K^S@XZiEl;$v)^5Ts|RZFbUP~J7%ZwQ&1k#SQY&-jn#h_w6-453#bk4M+s%uo#3^4Ie_RGpC>kp1c z_Z6yCNvA+=I%{Gkyz)YGtQi;oBK27H-}xo(Oi48_kPx`GoJ*dSR6Vqr4N8mhXIy75 zbrlj1rY>&DaVQmUm9|_iT&BR!9hCvkms7m?dM$c+fsJT)!aU2_Q2wo9i7mtN3TKS< zk$sj0)8{pL#9{YLE*jk;W#2!Y&$2CcWM}U!5MA=71gEs~c;=i00#~c2K(fQRF>j`0 z72J32frSc!2xY2K$|&b6Er_MV5EqThLyjtT)I0reL7_5@uU(g2o+y zcd9XlR9#X}?Y(I&PG|q4yWbY|KWNHvNQL+mPD1*TesJs=8egdYsq=xzxcNjlywoC- zhH7wwP_}2zYS^0D_y7KzgZpwRo8U9fa*6a z`@v@EI85`}lXD|l7Hg#nsrYjc1~ls|5g6x(8s)ACSw4}=?Vu5Wmg^{DOU)+y&~xjrbbQz^s*~~Hewt# z>(t&kGv2?DmubMiFjg!`oHc|Foo?n!yf8P;YSPxcESO?Y%z3vo_E>wEj~% zm7mIx1FQltvv|;Q9sohRJ=`(ORApjSb#S=h8=K89-@UP*WGRE$Z~ygKalE#^z#0o6 z$lLL1Gt~!XI|q4pElEvm^ftZzl>E83M;!%!qa+`3b|*jcI9r&8Q8e-{xM(gK*U~RU zf}zk_RuY?9TI78?)*`D(0RG33Hsok7*?L>)^#62fz#56luurJVG7~IesQ;A+C58H< zz7Gi&#z4_&Car&E%ZUS^-JF=lym>shx&R>F2C~cP)ATLx^3^=q}FL1DXOrr zsiuApHo=`}^TTy~ZRlqKt4JHf17a0T(xGITL*lcR*enij5Izv-M8Ke`=WlfuSBYjV00 z3LXOsVlgc*SV~A!RFx-<=>wt#;e|@nHiU>vYgR|xLbIl7P1|Gv;RP>eTOxHWa)Eyjc8ZXi1ntuGKO7F= z_;ERXXWDdanlY0zhv}R)X1crM&FPNQ-QC^J)SYI!o6}BBj?edh`2O~Jd|rRR^QYJ7 zVO9KMH}YoI5zszIQ2t)F3A1X<;T~BKoqTG2-`>_av%rxAX%sRTZ)$l@bAA-^iX~N& zOIeaqipwfQIao{uV2I8rE@{(#dqaZth@P`qt0^5TL3KPPC2$!wrMX=*tEzNH{nO#2 z5br`{GbWfNT-V>qiht}`w6zgH>zz{_uh*KoJmquyX()%eXrT)=$`xG~3*$J9Lkc!F z7t<5!;4%5KMk_dW$C@p^7vkzJrdEyQAR*^y6e=eph7mv zgJLh&pu}_dqrxPPfS}79vFjF5nq|0AzSvDDZL$uTh}rd(?}s*NeN%o$Eb{SU7mb5( z#wH3fNz~AgPabKzz!CraG^PBHxH}S7EnzTkvqOtmo`aSP7_Fcx+=vagUGvP4J~<`b zFkqS3q5WVVycLY2hTvVX6fWKpG2Ef~t#+Af`>;H83NJHMgeWT+H1Cx4Lu zGv3td`mVB@#5Y$yjF;o*x>Y`Gcxff)OF9bC(N#~<{>oUHmF$sMN@7LgF?2D!Twp76 z<0dU%y{>+|@hP(As_z$aUky3bTL~!_eDcz>z|+fp=Y|z`$d}tnC44#bDC)Xg?@`l+ zZk4a&M*5PG;Sn`t4JfOa6DaY*Lmid(kqSBywDH?o(~V#(dLqRUfwm~F^mcs3xkoeC zgP#a4OigfAj`Fx0xP0@u_-ZPEg8tiwiA|VYad4fZ(l;diF7vExc=s_jXFp}$O<-K$ zdV5LyQXq$`Mcj<6p8|FjoUcaZj&MPSX@b~E<(El7U%)_!Sey5#20)Ys>}?flY`Mqds#mrjT70CAAbf7Id#}PHc~iK zj}xAQ+E6Q`s9^iq)0A6jk0~imjSR^78mC0aTO`l*ZlX`yn*i1hE+VEWp}bAw=S@us z7o{3ocT9iu4XZojQo-r8P*yA?#@e_#w-hUvdKOqky)He{CA#|3IU#Gufy1|x?pJZ) z0HuD4g_pjPpn3JAM4TA%ANW~clN)!WLCNI&5y(s!Ggmp>Vv{M(`x`9vdnhT~&NiKs zMd78d9jmqiaN2s_HUL$8&3mG9Q|181GPLOA)RSu1j#J4B+4~L->s&k}p&01%uxG7X zi%Dr2aE!foEh1GRmpo@O@a~P4bPkm8a%|uC_pgyCy8G^Qb?B&x=O?-2kCAGw<+LxG zMogJY)${bXw0#!PhOt7;_88FDyFrgq0Nq5XX9=VE+9jzm;s%TTTtfU$N```}ybIzAau)`VdMl&Ok?UVjr54gZIG(1^B>aP z%J^&u`6GOJmg;GIDP|A9U2Nr}L!lFtk&KdOZ;IuhZUSS-1o`~k@+>4YWkEUscgag7 z>d*Kq3+`V3V%V69d&i_<3i}hq8TGAnN89LG8919q`ZI`eG}}EC{z%lvD{7!eq-Fi? zOMJ_p^~rRZcRX|>e}iiu!dNR{0bw571K?L9cF4hccD6aD87c@>p zLFS0C3CQAp8{rC4;sOUsq9P3{n;JJwbukHEeY8Jx=9RzqXlXs8u&;mwahD6wGqbt1Uwd?C<$$eZKL&YF_etUErTV5yN+LW+gYS=sr1u5w~*38KfeBhfBqI@r1E?V#GD4bOdU z5IWn^#oNiWD%E24(;u$2XLv{3lV~iX+vji0o9<(~HW~Yz{dJox`HM`EZL%CSd3ry! zG07mk8K33WtT$rE{(h13GHvMN*Q&qs=#uBO>5{?Sx~J4D$(XDEI*`sbRfoz@R z#NWR!>9W^;4Pc}%uI*x|PK~7a1!9x)9cS}mIp7*O%nO2q3}vljo}?11!xR+`6q>1GExY9-cQ8PKoq>z^fvr|e z0I7ND?D8!Y zzWS0x_B@xCTG)t-sr&)wo?ZcIAH z5Wj(r8fRSgIMne4jnDn^J|Xky*fGh_2V2SJyJB24R*rYdw8yWHj}7QBd zHnd$B3b2-DLa+NPY)g>D(&ehBonFh}zAFBQu7up5+(6xvvQ;Ova}=Txx7=h=*Il2t z|JCAofZ9uThj|mq*Fp##lFH-+%+X4^41FP~9yB)6fU@cf6-|n|TO7US7Fr|4ANaLo zn89hR2gD~U)dA`VMTfFH2}7^%gv6lau7)lJK9mlgrEVGRqsYYHpE#tR$4HHB;tgkz zp9fQD(+H!~ZrXAu>lS5E6pjq(#Fx}3m>%If?GEShS!MNR!B#v2+#XIP8H`8`KAa_$ zD;b)8-1Q&W=pY&If^V8+bC|p_!+E~x@8YfIeBETQ;SQus+nQ40r8J+zraO791)KH}+R=!@dE;%Gr zmg@b^eMX#nrS{Bj8|eKLfAqiE{buZYY3^+qJ~6&hJiBEC|8hHUxkaOd-huA+S!j5s zFp!0*>^AfEcs~y`;uIu5)}4uVn)xJtq8Q01jQYUX60Nvz@0^Y>#@Ot> zddW&)oo%D%o#&}mtwCHv;lc5H0z*^mx@iFkD}d*wnoX+GzzrR6@91{Tn;IP%XbVLA zN_qENK1pVdf3sl}0cMT7xNVjHmhRa)%904z23Z}v%tLB)eg=l5$@97T1v~g)9|&3{ zT?2k_K+`3Ebuq3l!oUP5)L*a5OiU6E8wF%`NuEAv%Re_t-E^^wc8$F@GNLPF`Y(EC zvvFaNBU}qDPyO$&l~Fd~z5NNm>0W~w`^~xnSG$-~zhlBkXDNX6k!nm}sFN{X#oIDj zuPH0ydU?HM=uP6dGK^!!H#@3Dxm3D0Si~q&4(slz>)pYvv(ehXhpb&ngsdZ0EZxnq zwb5jJ(*3fzrAU|G!h%tWZ?08Ggum{vi7y;=(O^d1iHezrLyCC(-3K{!w z=Wat>x$vLa5o5{wb)}hB$>ARbLphEbk&P;Se2XQrwLWYI=lkqV#W0+XD8;2ch+nBp znMkCybHyU|afA2k09Gj=ueOL1@pDtquv)WAHK}$qLICexQgr}+<_2B17iAzT$`TIw zer`zFwtY_93I;M<8UeR6%*wJfXUfSx=RGG_jIwiQ+>Qeq8o$iRHS8!dMpJr^%A6mZ zGp=fMMbc-QX>;=7_+F~IF7++!_brQ;IC;Mi~;ud}- zUC8I33JYEN3Ri{C7n{C1+HVtXY7BLMCK?#OIdNSuFnv21fwe(Gy~I?U34V>u$h?lt zVUQ>CWid=Ff1tO}*P6_?qQh5)|D{~CfK)!&pS#cPV=jOr-+cZU-2I+iz9%FejWye!<+oy?uv;uAdDb2K85V`SiTMiaYOA^t`8-9Uh=0aO1|;T;?xSTx<~`=`N{jbC#xO3I zL9k!L*f?#PIau>d7xUUHIL}gKW@oc^jTTcgPfn-C?ELo=XEI-l^=Q=@VlxP6&tIKu z-YLxPaj4*fBJuuIl3eVtZE0F^EJorHkIaE7waYoq1gEvYBpm0T7sUj8&2q(7eB|f$ z;DWo|WpZl1Zsco6oZlAF4vwxv`8id!hZp{Y?Hkoyxe?i)l1Y$()VeQh(ghX|#wQD_l^@a!q~RUTE4O*%bVa2NimjNE z>j4N-n0Z@_FDK_;clsFbna>I=jCh*RW9s=Ha`TMHb3mC(`h&b{jcKE&hq=tNLD$>5p7V z>(b-d>{g;$1(Qu6K z$BPilr`*dP{7_|Cy%|!5Bc{!GC=Q#B{-n;w4FH6)9%&?_#=5Y|nB{@mbTF&*E>nD! znkozRzIQYdIv%jA1hn|K%-Iqp_&fc+_&&1@E@1xTRl4*9E!dsO$A?>FipF>_=@vur zG2Sl+4Pp^0_HphXDs!hfzuV;SxzE#oR;>BOS-J_2x(%f^k&pa2>dKE6@S`lJI! hB|$?$;r;&%_y2(Z6@aOoxv`6zqrI_q+qP}n#*S_8*fw@-JGuXUyZiPX@407;b3Uv!M$M}E zJT=#>532%z8$p49$cPk_>4Z$|jZDSu?Of=X=oz^IBBpjOu1=oH#uhSkk}ife07k}t za7H#5GBOb-Q$rU^dpl7>7gKJ4xRWJ7+|&rb!~|gC;$np%1Blo=csf~{TetvJmDB;s z_GT{bhEArm{~!E63IRr*|B?Tv{{O5>+0+!^Vqpp}v$Qb;f<{HMg{b zVfYWtl6GeH04B!$fs{yXPp>g4Zt(#Xg9I9v+)F&n3};b$l1I6a{++z z|3JdOQ~#%k^8f0C{rfrMt~NGuhPMAS@n4n!{_)J--p0t@-WnhS_z&+ajsF*tp{=Ej z=l`De@Ac}Y|JkXMsky6-q0_&o|ML6u|gDgnz|M{}T%f+j{`K>6qBr0d&kvT>ne~6DNR+o!$5U=Q3GC z7bi;(fHvblv%m!S=l$Q$|3td~Mia9$wl}e~GY2TU7}}W_I+^^xz<nSQ3DM&SIfg4T=Y8@37ytEVGD* zw6)o;tcuu@|JbTbbm^tgysT`8+?h#7TIRSkJMHAh*}joI58s2G-HmcJZ&pTJQ4eGP z(9rA{XvZCr%Wazp(a95yN{tZreEO(@ybV1ZY0~fjk{5Zi->(*y@*=A`E0_-iAm|f| z6qprru`B}ZM4R_q+*5)0JQ=BS?Fgu~zu`4?$NkWtBWD8FR$rBVa<;s1aW!KsQSq;V zw1qUl3vHuN*mu4&jq-FKhB}+x0xqAEsr>?fg4wK0OBf)sti{5$eoBM9x@0GAuKm#D z^9Z(b#tP$(>CiPVu&sjo#z^I|c3vo~N4KSh1BrN^sh34{@e!e2IO-E{ zEKMZH>O`rN@I}NQ(RW$dJ3fL|lQTj;_~U@NYqr((v^=G-u+V_(t87lnyK!!^=-CT4 zFG4jYlgeCR(8OdrHna7M0v9RlR<$e9lBe--&ZG(7@03`k;sX#dqsXCEv8!L3fI-nc z@j11hJ4$)K$$n=JYBTWSeKKiZT??EeY*FK=sQl91cPFqQfXLt9vO9xh3kv5!F{Fj$ zDtpDvJ;%;SA~G1dY|v?(&>FEh>E3V>p0HO}H;m=p;C(>_r)=C?)8(Sjt4uD}*P@2( za3kyL*h1*WVpj^3?Vo!MShw>JnHb;Q$^}pf*_&JE>N!hJ;hBJ_w5!W9EVLL*!P1Z; zsy!00buM5#20NHHZo~HaLvxWuzX%o*L0X!s#kTm?7*a-#vva+ZrufzLmy)15fE@c-L#7 z3{B9f$Cuun$Ikhyv8K1hdoB#TsCaw0?T~ z9rq24C$;Crmb$q@3w{1Ob=`T6EFvw)Ik3Y(uru0;2-6fU-f!6r_<_Qa(|yX?jdS`a zkGo{7*{1|V)jrq~BxW-8cIgR2$@0%d1$${UluXRZFC^mgyy|5HZq=(d5Joe}FZ9)x zL}7SA1Gg`HUts$t-V%RAlHf8R_TX9HD^l=lNstr+cT{F=sx8`rRp~hg`uGr#q}`|Z z9I%-8{;Ms=cRvYjUnO>>ZG;Q^Tg3aDnt*u4#Y-Q^3^sPC9&DPtY@(RKX;N#t-7B;L zX>!gwd<`$Y-#1HFePj?~>BzXQ>#1d9Qi@jq*fhKejIt3wmHsWVZUxZ#q~nBKsceFR z<^0o%*JbNOzGvuW>DR}3P{jmCv){Ok@jKf!IJ@k_ zx7|s>+!tf=waylT+h_r#A4F|lZUcP?6@F-c<%tKExzmWPte{7RX$jayl)_=>(xG7Q zO@=|mnp3TQLQz&zF-4(|W7jj1G@j7ZFWPq@2S$S5JT!;GUGHdemu|bN6**V_R##`v zj9|p)o)JN|T!B~Of{c_r?M*<#t>~q}wxQIUEe`_vOtcruk87yssgs2IH_VTE`x__l z6T3-q9EQmSV1-%ml;f4oP>nb<(hDUr_Y_GqvLvdoZSfpFo$NkpPzeb};Kc3FP z|Ne3e;@zCyBdzNVVc)>ebKwPocqL%HbhJ_+L)wpneMh4HKIqwa&tP5Mah0RvO)#!! zjs)e~)%f(@dog)rCU?1#s&);N*EwHrA7@2O}#~x z%=T!S^hj{EdH+E6Vsf8T>#eG<8HXivz_ujPB0!s>(%}d87t=KMz;qYmU@{MucvcUm z0_B<^h-|;jK6=usAVVe86Up!Rvzbl*d`AQsx>vRxgMhr+R$@L|m_-xk7(_cDG}45a zXjwZ|Ck96ev-qfP4cxm;v8bL1Yu{Ob(FS$$C$MY{m zMiqgJMlWLKygo;pa`)OYcf%rH{W>$1CaO)tp!F=aw3MsaMEWheBfn z3Cg+HZ3p&=fa~CFL+J^rhTb#KDr~FF4P&Pt5^{|&gws|x}qAyaLV)IUgysictUq2vp7*>}NZ9PLt~ zBP@1(a@XiFIYG#QnK-PD?L>`xLB+%VuED?;0n4|Z8wi$xY`Hn^dec!X83SCvML!Zl zIxCIoD!C|d9K;;8TGb-~=^I13@*HqIYaW>Dicl-)wKZr2dn5-Ws_rmu2P#A4=jsNw zMx@A&sw(S#=i`9LG@9bn^>wU;uMHQ~5QL}74aO$Y4^jgLN*j(PKsw^?b=?@m{tse* zeRTMCUFeEJhbJoCkUz0++zLz4(@=wi2DW^HB5ihu zKR@9EmPh{GFCR-~LR_#$RJ4=lv3(pgr74B8ykmJ@^9wSsx7h;AJEDSY!zm&czznhDS zL}Bk@)kkFIY>SdvkEYDtD^wXUWwOBv^?l_A`8twf5=QnVF4x=;Sw~C>nIJsHz`7;q z5x+Sq8FhCBIE@Dy_}hc@Cw~o}MR<@H=xSfhNptUMq1-Mo1!YkR^3m5YWT(6ncVjp+ zJ7N}dxSB0cjAg1#AEv1(>Yovyv6Na#UuejL?NqoN_kH0gW00EU=EKZfD=hA~-#Ccb zQ=+l;USNVZWn}*raCoFLT#U>?-yXgd2$Y=j#(^`nqFtelb!oYv%VPBchLMR(Xj;&B z`^=&;%QQ_MAGZ%0=w zu3%P->b?uq*bg{VoC_m=S?hZDVaW4uinyr6Fh;Z*c@UDbWcLh%n%owI5ehPe2pdgevbQ(VfZ$%YPGT_n+!kttYmEkCnZbSv@pDGpL|XsivUoziWf(WHegoK zOqR-Sags;jvbw!)IM#=PY&7phh=;Gy{%XesiV5(+j_1F|J@m}`-Z4r-JmvO3M8rPxVLj_wiOuuZ1XDa3< zsTT7twYl>@{^jxEi=MDQwt8m=Lu`CD(Q+X^eGSG-D88b*y7CEurVRmxmD2zoM-`c3 za}@7b*ydr3x1``L6eKp;{HY~I_TXdQwlWQ<+JZfs3*@4lN8K0*UYqfN{fldr)c%CY zWoIXK^f(-t8#<_2Z0yZb}*(HMMKzJR}9Gvi( zG}&_ZwJacg%rG11;;cCUnbT$=neFZCI7%sRfV3s-;~7~sZKqli>Nh=q=mXX3rIF=T zR{)-xyDi0=R#D@8^S8#N@&&y_J^~y8b-B)aZeh>QY9#_mLB<1S3!UD0GU`)Ht zGya}TUj8#^ApxdDJOIhGS(8qBI7)5i>R3iz?%6i@`gW#8^L}sqD0C{Pzmi*q>BBrY zV%d6y9=33IiA6x{6WCx^Qe`qyZQs{6+rf~FJ!kiha|ok_JdNE+uq|Djp?p{X3!>f2 zFrQ^}LLq#8PZV0jg)p8+=#ggyqH{3RM-JPTv64}`_F;-!l@{pcFvX^VqrN~zI<^aO zAqj;kznm#`PSM?FH>>r17Q?zZ#5;%_FyJuL+&^ppikk6DouzHcY%}_(zxEQ!JqGCa zuUuf46Vwj35N$uoD0{cYiEuQUD+#A)Rt^hu0q=>i^f_7=aEvby#{7YwGjmgH{DlVo z>Sss^;0x7^nvSScUK8(>=3T z3G&*_ZLNCLt0$elnt0^*GC#H_v# zWI}_uaBJ$I8f)+Qs)kmr0a!J$cY2z&J99lKk01;e`>=wr$@q#c7g0P3dgYm1ER%x^ zPcFP@8BV#JZ5JfD&?e|j=a^O{C1nTDn!anFK64WVDu{x)Y_h-HIIqMnDYdwYyuW^R z*~wq7jReP!y`3RX(8<(lk@E@D=<@_2#E*IN(k1Fk{S^fpbFi%HXh78^1)s=q70mGp znws4!uc+~?)1Q(*Nq)8?yJpf;1M9Ky&Z&*-W$mo%U?u1Qt4iCOW~BQ8<2ZZ)_G$y{q7r9MD&MU@2QA2??w8 zRIt3RwRkHx=N-ebM7mTQ;hrR`+ib-KYKA6P%v2FL%yX&Lc<)vZgjd4t8$ZK!7!1fv zu_SYbK$tXYp%R~>7VWNN^1w(%Xfq-B+T;e!-ggdxus-J z+EDi=tHg<~)z-xR)*eeP5NLT|=_NXFzskH;vbWvYsbp@zP^O+R3fx1;gPR(j&+i^~ z2}HyHM_WF&)EqC2VcWyPDDEyEZuQy|WLq(=u+k6_fix6xL9ZaqDOBegKqPbacYgy> z$l8+mMl=LiLuS^1LjyigNbd}Dg+3u9V)h7foexN2Bi^-`K|8R4XV=f25Oi-XiWM%{ zv`)$|Y;eJRB?ztQSEr&?t!4kPE0}Lhs=}8H!CxnE!&{z#V+YV8V#R^CN^uXzN0?%) zw9y@%(;#>>DDFfm&@g}TDhjBk1uXAzh>IeaRi1$2fw*A>K7lg2a4zn=ny-ncKQ9>w z+dA)ba%|*o)b(G%phg26)2yjeKgH*cUk46v7aqbEzPh9)vk| zOWp+L$)e-uj`BbKh<$VE$>q5@`4oYoSjWn#BY5-`?#vr#tu9fm+T=72#Sl~IA3AXE zF^Si0Z7Ub$s!>U=dzsY}-F{O*CXS)Y>_>X;?;-LRr`C9eziElC+FGJMmI($}t(x(I z)ye6T;`oHsi!{?K^llr~aL{rWRG*(rn#+`xHlE~=N;7<qy$Tk?M#W(JJ8<&H`&}nG6?x6&kEh))cNt>og*w|E+1>TG43ZaIzM`83$ zoO3{%qU?3Du82b7AvLRZ&kmTfS!Y<$DR|LJudX!UTMT56w;`FUhVw^Shwb=DWkUK> z9Z@qcSrRHJwV*T_;QK`;xWa%b17;G!^H3n3>-c)20alPMov?O@D0H-XQ`*nzJsRKh|(4GScGt{U%pUJ5~Eztz^#}aO^n? za4Yw_Uo4s9ge5gB&8hy-EH?A(2%RWB&vG$@c563SiNq67FF=(sKH4=Vf@%vwzJu+F zXLcra+We+r3DoCm;B;Zfz<{nLKp0nV7IM$%(D*s z6h<5W9V+46#gqd{S3wgtctQ*%Ctt9!FXcjUC~5|?x0iQ=s|DItj(MPxIew>fU2#pi zGyySf-FVisPd5V-_B*sCaHqG%m}krQFW-}C^+-mM>^8*+C*mY3-ud>NFV?yq4$aS8 z7aYUq+ITZze7<@(2e`c_yY=ljV(M^v$9XjA!6cCWDO&x2r7{Yjd5yWXA~;b4ipasR6H+ z&{Y?PpZE338d|&NZ-|#aqbK;8Ow~9f6|_{tq#fe!=k#n!Q+PC*y%s;@t?4FIwV{tL`%H7bHSfP9dq&g%bhD^ooi^>MX zzbL%UT9c7<9Kx=Q>vp!axZ^c8ixLb^s z1_ht?k?!$bYmCR{&XoSZ|?G6Y>;hXvu-dh^()V@{T)*j?hOR45fU#y>d2I+=pk2 zly%{U_`Fr8qm_{30fcGsi`OWHeOnxXjRC~?^6wu!3+c?{A{$9odeK(39BuC`9z_`k z#4f5`hK2y)dj)6uQCsQyifAR;ut>-EI)4fB17KDc#=`a_Rq#hi+nEHLqCHTeL&4k> zQ4pfW5*ig)rs%ePt?7$dlVPOn zL7NSU zZO;e-7`c*8&Kx7}x-}|Nsrzm{Zu^Ksbo?ny9bmJS?pT&-%IR)(x)rtwCs@C$s2c>x z++5<2H{1eXoR-1z4h)$5&~4ED&7W74l_M#Ov_2*aGs&xd2+!eT;9$Zk8y=%k6p&sp z34?59@ewt%V~-?Me*$boTy@-5@Nya)VY6>GwgBykl&L=3^^i9`J;1>e5 zUo>aRc7la(WD%OI43Yd%oVl=jG>R$7y}bkvckp zv^3DgtM@p#0tx{BXAKESeVd*=1sM?T5KV#()_$$!_L21Reb<(uDwcfmIe4>->p&jW z==I}zC5?^iHtAEN92r-gy%<6t_Z1vF)AE?##9T47%XJ$?* zCPTt?7w{Lb6&m}1p@9}o?W>R37p`50DsEv6&`YLl%0JsijszCv^~U}aEEmX^?7x1t z!+?%(bDA+e@?B{;n=(V9<6$g$oD}yw^PxVkPN9H~+EjdXjT+5HLs)P9ghVZCaJH^0^6*Q;9Xz5ycf@6^$Qwi2R#fkr3oZ< zbA>`8tY3{ye5rD#LO3(7-^ET3#v8nS-kvvJt7@l}U z5n?00E7E2qdaQ=Bfn^^fIn2J-nRo?Ob~H?EVy}_ct|-G2=ERBCEl%Fv_wmp#?91&~ zj-5dvOIvj7FGOmx>qx3;oun!8(rt*MHmtOTj~23Bv~|y!_1e-oWeo2`BpKiQ)*XGo zinI8zy4gIVwCJ-8&nUNDClLI}@uRePs=aR9A202Q=b)%WAoCk-iAEtK zb;x^zYdA7;G_@{eZSD@qbrB4EM$~&pF71z@(E<8r8|gzmdD~UG&Ixg~ZoMxUeFxSu zuO7>-uWzmODzvBQ(NlBFJ&x8Afi^6&XpYECo&@Wyc^>2J1Ty*^%MM->d_ijq1)fz|MVSHZxo+S^h^V;NydC45@GxyG=3sWEc<5Bl zmRk7G+NrkNM*~oOeoNU)?zn!m`De3+0z-A*nrwY|YeoXzgxt+UH|ZZp=JAlBj7^VXLN$Eu_-BTr!xyCv7n8$a< z2}mJ^Ls$2bhV$OlR5|ZdS=dyXvTQm_AJ-Wg!$7Zanr9`;1h$35wU{P-w&Qe4+Mc@g z=JKhf7)K6$JO9-?6Wp8#w}Joule77X;)iW^b=PhvhtBJ(&u;{NztmE?HR7s5X_)<- zG{BnBhsu<=35yyI@b>~KJD9~vLJaZ(A{oLXoJ0M)#0^q~D(fw%vMql_z;o&nqC%l} z(?j=ojTIWi>=ybm7gaLh9iUyz!C<@Bc!LytF|Hb=3po z$8kZ&#lLY1xTmF#S6UKV!3ACO=TF#0(QF&_V*(pggCMsKNvTOgTA)Wf})l$n2) za!lc`H4!l@oVy*=joHqZlKU6%(9WX7FGfZ3fxVjOdc;9)7tn0c_H&28;vttRY~AOk zTz05Xo&)*b=uz!_@P!_$Zu9q|@kGRHM0q#GlLxPF;V^H&_fgHV7!hgxGKnkMdzv3V zRsKAT`weq>v$YzygujYzqqipYt#_kPC_elfWeCk&>`M#XDjZZI_#*oVwBJ&T_6N9L> z+5KpTJ?3NkPN{08&3Al?tKRkKAQgv5JZx3g|V2eV7>ID*MHzy%y z2O42;=eMyDv{)kzt9{TY_|D>=e#({g7@0inaBd1;xYLoSGu}OIYQ#Zv?clSSXY3yd zm;Im{+@Xwcbc+%d6W=D!KW;t0g(M>kwy~~zoX(`egQiq-gUw#@I~)8foEr42s+q_2 z{j3D%_;fi|1BLOqz*|>*>aEd(m~t4sYQtva>&B?$Lb`G;w^NNTlv?nZ@+tfg#jSw+ zkgWMlRj)G4!ox;*u(5I1YBXzAZ(kM+cF(+&Qt{R}xf^A!eG4?#B5H1HjFso~*muRV`ut#WvP-&G10#XMz>Djs+} zdT9g?ihlkqzjxXXV)+HuZivvaHP!^#xg^RE%r|meI9{)9gG<;xqG=!EPhSMgQ>U$! z{i3c!GV$FV3k!U%YA1D14%W%+V=b`>lM?0cN)#b=8K@>oQhcsThKu?6at81{!QOO} zXBIUKzE@YXd_J`*ZS+we*6+fhT2-MH891+w;VR}PIW|+aOziT{NR6F-Lg?sDFMUcD zUjL40d{+QGjV@ZJK`#V9Kd)!ML`$4ZyiN9ACvYBl|;!$ zq&L!QFoMhNHI$WpkM^zd)qcM|kju5q=bYut~s}Rc+wQ}u?3m6Oa zEcWYjimK%=Vz06{9R|@~^cX0lqnFNccVl6x@Zosmoi?U50*XTv4N8!xBpb_W_yUki zpBH9@|4f<*J5TDhIGVD7F-621&!fJn6WD+cxu=y$JI6d~qxkT~fY-c+%CU2xeX6&a zWcsKHOAg8Gsgt|7o74vHAphLW@$&wjNMCbt*zZeC6@rC}%8$D}AC*EJI<=NLU2UyN z3%SzyqXq=*$gcWl?*sBJgVl%Oqho;dMr+PyRd+xZdamOSKcN!KT)K#OQPGM_Eh!=c zPna#*VKCK;QL19mulMDR-c!BP-fHo1TLuA%CIQb%mo$5qjXKK@(-BN8SPwLc zUz5b6Ok%2^uC=m!9{RV{jE*BN*An;qTXU!3z2c|5HJ-DF#j#ZB@)p=G6CE z4Q^UhYtm$}vz@e|nVJ6A^v9ULMVy3--&gTx<=>qIH4Blw4$7uG9jN+GmQ& zr(lyi6OQEF1n%bH@xP|rB0OHBA^=Hb1?8xdFC`^2i;EEKO`(jhTf&)f6evlThQp0V zb3Xuv$y{DAhL8MkV3)`FzIu_B=)%859<*XD7#Ii4?jd4?xabTRL_fcQ;Qa|Ajj`4z z#zi!R?LlXMbuk87m&e{z#YKdx=O}-JS&@JxmMc@F9Sb%)2J^PLP0GSv&(g6R9Sj+4 zz$1BfuFclt_KipTOG_yiv%cQW@EA-F=9iPZG&@5}7`p?vtI8byp-kLH zHzv>K&UH>>0VX%h*A)>=^&8-J&~04y$5VP*P{enoCWSj%!sXep5=DplDby&Q+DnN? zZUDlwc6E$uqd36laq;iH0`|AB%Fo8k_gQz;gH92UhfbO$dB$9V&&G$gG3%BlSik?u z-SFywha$Zw_>|Ps><^+DxC)?*E+ad%X&73*WRS6&HBrcIzvo6u&3HvT%xu8TxCNeq z>n~%1|4Yi&`W@i>eD{>)DH_&QJ8>V9=NoTQQj7ha61mhU19 zSE2H$bYnN7KGwQLG#%j*9a{ywmZ}^RTRlI)<{V?+-FMv_cdl#zyTJ1ktxT1tUT^Sg z3U#Dm-jO_-^C6~GMBm`HhuOMC^^GMJ&%ccqD?-l^9#_3!O7leU(yX1u@w{cff}^f}Iunes#}0$v8?U~;hY zDgYf?31~1WWzl^VJS#_1TcLoY3QTrvIg&7W-*pi6u+-kP{gdc>7_peRTRbveHYylH znCN$F+>BwQ#UZOG{zc*q%Z+Hg@1WA7tjDifCri(r&`7jOjS;zJ^J&-eCx^lyhn>yB zlncfTF14WI4Ds{UTjN;n&=AU;w9)d;AU2MEXTudLgm+* zp)8qVtc?&M%OE`BX*T%J(mj^o>+oL|syDaRl(U)+_$Ahrr8u2_DRSU@Yb2LPerdK- zog*VWw*M@iQujrw-O)jd=FtoMG1aVV+_rDS&hr%xZI|nhZghIABd>b}s{iX?cffLPE#=!jx)n=y_ruxiP_@~8PbD73L+gHh>=uE(HszfG+}`E5r^6OgQu;ba;cHvpgoAIQ2+^IRrL zXAdSjX=!gQ9+2>bgr2NgOz zA4_6I$@E)GSN})xqkka531$kNgm=^^=AK*N|j$E@my#I<1*-j*dmY z`tOt75r`hIiIF;NTl+Lt6fq(hWSeRpF$E5gGZHo~@_PHE?QA?R0o2f<_)m+FDQ6Um z5frIB(RT=cDo504@`-MJ8Mn>sCu3mlExK|+IakHTj$5jNd5{gg#+6Yv2`8Awcb~62 zf%81sc~3Mo7(?~XuT}*rVt?r9dT4Yt+&1zpLZnubhd6qaa}R*%hyv$TD9d^xX9Gp_ zVwBQ@B+1EW{h;?$(2`v|ddlN2yXf>Y3?)oC=d%t$#(YzW-;^B??wBB#^-8iFS_D(A zPvEmE=|G|Z(;PZbtsxpmF%q>wUsj&%GJjQ_=q>TP&F==A2$pLSk)Ol`V$WpT+WTU=X$(sLCiLCH5Ga1S?qY1a2m8_a8WH<2%Y=E!NuXRc5@h3 zhi<^Xgp$*TjDB@StC0-Xz45zfiW^mF$EH342Y4FD!&1^^qe>Kg%CQ zeLhSG@!$tQ)z^Kt?KZJ-PT)qA`)NxpxkR}|0{U@(6pFkoYrdRu;^#&55&n_37wwfLwY+(*Tuz6F(#2 zd$qHO9T4?jNfLp#*rgM$Fdlr^CEc9_SJRE)f&xB8Gz2!fg6IT9QRq?pJf*|ig(BFO zDMUsc*;Ak-obcrmvzYU3x1LhXox*eK*8G4KY6CMrvSzrWR|m{iB=N=5$nOHxE3t3W z2&nvyp+nbnGZE_DF_{bgr$)Bgh%7oFy>@N>`~7Wn4sp!2jSn`fh7wrStwPT6h%Z-} z$L)Er0kP#0a>J1PBqW}l_xcaAzZjQ^(KeEh=jC&Y{A-^u;#&I zU3HXzCKgugQH%)h5UU1DkpgEgx3S4Rjmok838vHV)*bUI7A*1J72Y2V&9NzKDE%UL z!zjvJ;?BzZF}i-IgvKHp+;N_KeMk;CnI(4Iu7vC9K}m%P?p=<*&&HK&28*pA24Q;N z0Hj9!61|d#n!8QA=LC%eX$s7g@s#4XAWz2b#ot*En^*hK{#(?i-LeqFz zS+PP;>tlw@p1C-H$Nh@PqNe|yXAhjZXJrQruz_wybNmV(_x&9Zkj3Ee4G$7&I>@jW zZUtH#uanrwQwdee<8ZfTei<739bCwW8<4FaNP)pU_b!iGcb)0%7~6Azu(Ps;hVoI8 zSWcg8U~yXQ+A1*nxWR(f)xrf3gi|3jc{l-Gfd!rhShFfGT#3T0M#cHp4=4LN3x1w6 zgxxobFl?^iHMR#jFP7i7y*~W@X8@i@))A=v68%vf-(THPYw>Ay*{k{oOZQxpSc>t| z31^r2f%`R#n7jkBR*Z2tTJC$Q5BoSsBhCjp0GqjQH;TvyWwyl7jpRCIyZL2l9NR@n zi~Bet@-R9q-jvrzZNqRiNTqw^^yq;l35Lya!cNH!Y2?^$=XJsxwB=C+r`Yu0xNc1D zQ~+HHJt!$aS5elXk9w7$8G@S!MXS;YH?rbR>Ut?;gjXy_tJ-wOc+Eil+8B zb{MW;;hK9_)dLt5i-U>S)x30;Xm_6R?3W$@yoQ#NYz(JdiJ$yv3S>$=wgB?O-wSpq zF?ucPOK#+&D(Iu-xZhnuL7G5sXQ&UATyJcJIx*H2@!8>=b8T>_5fK9iHH$HJy;=ikyk=r{~fQ##!K5^;K zBibuC3f6ZuKre!Tjv?4KF>ua8Vvc2xK#uxPTGhGX>RjY((KVU)LbK{~y6vk~GYG%P zPQ6+>=zXIhl-NwBklbXo?t>z+VO)q?rPYl6dS*cTxpjbV+1S?99A8mzo-m>w^_G*CxC$ znLW>)ch7q?w`j0!{)%7)UbO7hlg@%0;?`9X%Zy`Nv-l=-HZHp(yYadRjz zWhK?xv>8722%jSC&~>X{csrorxN_{G-eb-{g$@DV&WhKpU_W>KW2)bULqs;NxIh6E^Q4`$-McbA1(wsS@>s|3! zvg<8RoVO@=h`%8}x9!;fR(O@^VcQ0N(8M^Y*6U_DP`7#mD z74-u?(Zs73j@70~q~3QWTMFp0c2ynRnwm zCA$7`HlZr0qs7yvfT|svDzs~w@bI)l7aCQ(lRTO0e`q{Fzn!NG%*TV9Zwc~MG7imC zEO`B3{u~15TbKwJL~ZldBfcwBEGNjFLO&zw9tKb;$$jl0dUpxb&Y3W5Rm0iXRtC*d zCQ51ZD})lY1r0Vsg))QNJO6rvgnOx$x^$)A8GZMcm{lc_Bhr&*>xbtYLh(pj`_dX< z0KK(jE);MGv6j}y#IUbYtfYt0X_N~b%dvK(;)Uq+8_b%duxp4`fnsbLo09hNndT9a zrkjD*J>_5SIgb+i_B2y-=4D2xa)ogVdv%}-Q>z;}b+iP9!(Y?$`YzD()GQVmf}s!I zdC-v}a1FZ&Vo(L{*0=1y3(;@uuS&ToPsgu*Po@k{x_{^~MUbQ~2d)0WRr9e~)sonn z<@*E-I=4R&B;3__us8`K0zC-G!ym92rU;o3E+r;(CP*xouw;KP#Cs68#G-`ycXgx` z`706D3f>4;#Pd+`nCA?)XF43rM8d4#EB$UR+_t?*HreX#_-Zpm2pNIxRtNKj*)!|g zu}DZz?kRno>fF_~6C%Mjkp5CC(rkyh`eX`P$oVKr*9s@6QF3z&COGxD^cT$uCH8eF zbHmvdEOl^2GpeCpBDtlRR^JuKc@OC;49rw4W)AORLQ55INl{&kp=S(iE6Ef=H+lb- zJ(9jk6qN1QazfJ4871aAyV{}3V_yHWxp)udT)!21;$kM5x(?S&3BO+WR!`!3FZ1`_ zY?%SPw{qm7ENV(uk+ar>&QHF*OUfxU#z zzaY$y?%^++uYDzTv+lQQk%HlO0Jq}3K|1155S8+LpZjA$SMH;~56%9XjAs=+TdbFj zJR3tyzula{5N{%64Kbo`nCn`7noH==<=m3>bg9K%JV7^8xSWMIF3xf9G;=o%BN)fKn}+){IY;lN`mIbZcq#X=mVt!d17O{rTk? zWAzbmEH5G84UTO*&HXgdvnG|z#g;wZu!5x1JbH^ILYK!rH@ODPo!0 zYXw2e=3DntvwNJtfr6>7u6z5s+wc2RS1Zmwx5yk^Q`~qD{vIpHU_gvY$Z-1S+-;Ou zFff?0sSFPEqwlW0H0$icZ<;6rW-DV#!#{p|R5=U9nGlOkGUW|Or3EX8j!zl_3Kj!f zM#iG*l`GCEVoywzw2AvDo-z#=+I(MhkTg3rJFONPoyINTna^MeG`iF6oeDUus2T?v zFgK?j5jpB^^SkBbG^kZJRoXL-W6<|GY_ktbj>A(h2Lom|ix+|3GGD5%NpL9A2F1fg z74I(iHQB_GQ;eg#Rd}MBqD&P~RnGRu24JO3Y(=lv##N(V?it)Y-^QfKh4x$9H4;Pl zs?!NuZBW@)jPC9z^Kukn!#@;;N1(d zaX51VCpEHf;RS9+YI}e#L27^)D!v1mo2*^H!pvMSl^R>an)SHto|)cy9J-cuG4rXP z!U>tiwu_JfqU;2?WQ0>%aN1{5X(9OVig||su8t)lme;Zd=_{p<09Xf`^riffl2zWPO4c-O>3z^R z9bRmx6lFttlMwE*j}}6z7yfZIpt)!nW4)0zvs>uHT-Oq$vu9!qP8&zR`q_6yMkv;= zwg3_Dx*>ZG)jznR=#D$xYF>)Y4(isrS$bVr@I!zjF(tw7f{%v#H3q@;WZMO*JDRA* z@DZk~8n_=zEY0dPaWq?Mhtj+1s!i%QJgxy^OG!;f93)uyew{2b&9qyw_(bBLYvbL_ zwLhzjQP9(LbwDDD6eD`^RXz%1ZL+CY$!hqZ6Eshc-E&3Gty_>Cbt@t*ncb@;WK0dS z54Vfm>IXyu{vxb8D;8iE4BagXA#;?y6sexTR`@8(>8BFksLj?paerls!yhjXl?x$} zrBsROf5*v?$U$DfDT^+&m#>j2tL1eQ*jH;bJ? z=jER_ASH|NwY-0}upzn`t*%88Q)8JG^t+@)H40mV5^STPJ{QXIKsQyVVUxgUelZhX z=0h<{Y7tL4>XOMGqC?q(4*vW<00%($zkZ1~M^)s`#JL*)yC(wO2t!9oP11S5?LHyC z>pm0O>u|BCyM_-*#%igxZw#ytyM{|O6V!s@KUQ$6&Whq-#w(};sTBwbTLI1%`v&(5 zDfRRq&h4~6j6Bn}QGviY-s6GN%>_*3NRHDZ0*yx(SP+AW>9eaY5;00-J;e8e>G$dl zm7W;@8y(8?pO1iYeDoNKA}4|G{<+2X)oApAISx-rg`Wh?C(&O5Ih?zeH8A6A3NBoG zhJjnk|MR<*(4f_Hw!TFdnwl9U|i^LuFfPeNr7ak~}}pA)JoM0zZsJc?$GJa|H)mmXa}Y8sY#dy$|ClfRBzUQXQE&5ZMfe?`B}#zLKmWLkSMr~b z;lkKRJ`+dTY}~TT$u|edov21D>!?l>%t&j$yc?!s8v)0jOT!2*WMgl4^q|gSbTRA% z>e=Dwu6dwqLmG7Og<`K$PI?4ZN{~@UE;Xs?jBuu%AWV%6icA!^dS>fajjzd5{ZWgpr+C#Jhm32FvoLA@OQ# zJ5X7lP7+*TAlU@A#+pMX`o0ljz}Vo;Y(hZRv$VcKYI0mC%b0=FHOOT zbXA1>=Nbx3J9q_$C3kiRstg)GG+x#@Y8`i5k}DGp5oJV5&?GilN?D_++%H~|*#*XZ zOv+VW#0GPAi!{=$gD`C5hTUUHsGI4|0a(?RhBTB^53;fxVmQopZy4NvD0@x7-AOlw zNK~tJr^v@>8CgC%dR&FhGn^QgL5Ix?3iNj8poStaD16L=(H74ds+Ypkf)xJ*NZXmBt5xieYq-M5y88c0` zdZyZsf9iy=V>Dob8|AND=-ERvGij?c!EFs|OB9!5wsro&xqD2N4|xqdK|J112%U=| zg7u$iQ{pb6vl1yM3w)RE&W7f_7#6SY9ZMNMZuC*G9Y7tvfe>v90sDhWKrX1!i84Nm z>OHh$cw9(M&~9{GkRjG>MIR$8qxs+tv#*}!P$xlA=g-5)V-f69LV>taMn{}%QiTp` zXB=BP6!}+0lB_+>+Ur_h1Nv>V@3|ly9T#{^tTzA6_O9IMR?OTox_$xS`|G}b z_jy0p$NGxBm!%4_G*sUpmx%j&-s*E0Dsbfof7B{=uV1hz=fRY>OQ|kW5O^}N!!%fo z`^&oM;bkDA$HrKQktpD93r!4A)xM@x?y6Jdp^pciHxFfNJRgfV@sj{O{N(Oa&B8vS zQhBq`jOlh^Wn`{xnnO(gb>*OG?vX?u>`Y{906W*uDz%I7QYJt7F>Hx!zY=iKn5)e( z2dC%Sn8krUj`|ZsF;te|QB` zf@X^rx*X=C*P&Cjj$<#wJ#^~Up1+zb)NZ#g9BHuc<%!SX!hWcF>-IsF)q*uI znFvc!+NL{%IBBQ9?SsrF;PVc+7An_JSeT};hEL7D_9Ur-1H~T`L8^-YqlK;-x05yqk+{car$b zSU356C5Eyo4LBV0`;{P)j~ZsmT<^A65a2DTsp&2b7kVQ@J~4 zXf3c~vZip4iT+Z^IUWTMwF^gOmtF@cPBDvS^Q2%BlE>`=*kD)~626$^Xyqj_TCf-e z4K$8cx5OC!$0qahF7T2~zWe1=_j$#agFafhI_iIH5t&WQB^w-7bP|0IpT@|l7Mt9W z+vxwYq^5vQ0)Q=Q@^H zppbH)Fg<_7J>+jkIKRsD#AjQ-7yHcoskCnHA2eiDp_+4aT4sAH9XKK*3SWSul6l4Y z>iNFac;lE9ZDwRKl}mMliAVMGCBXNy4&wEPytG`BsFrMi-P6^bD1OScdg=k{z7oM8 zhi|g8_z4R=YVR;XJA$2#ePvjc9QtVsm{=rQI;x7Ds6chA+(2y0kUWbAgPB04L@3aD zwboY|PTX1O&7JZiZ!EX5dk6_IYO^CRn|IpA)f-~|!KfDPQpInAIQt5ah3@#G>}=|y zxq#5Q%o;$+iq}3wTMlIaY+D!+wZF%;hph;z$-v%BbjD12x3AHiGgVhf91!{<+;?T|77razYE5`W;apdes{9`^urVzLXc&+i`8vBe^ zPW-GJEF-ZFQ&&FVrG4q(3sE3Zr3q=$w5?c9)&%q5lc=dHY7fMmgWExSXrwwFvUTb% zcdC-4KhTy#e}oeX?vFn zY{AI66@5fau=@ z>*1?R)qmA49KIkO{v>=xVmF$lWl)4#aTtrh%cFMx6w9n$a&btU)4!Gk+Bft6RnvuU zNb;C64>D?-caN?P)V0vq$aaveaVJEQPJrSIveJw~DiNNHYqb2u{T!3ZdjxOHq6_>g zcBM&f!SIL!#3@Y?CUWZi@j#!p1fq6r)TFM=O_1}5xb7|TDpO@9dTA5%~nN76Zc zcHM)JqgDS}+)r%w53pT;Ct}v?tLqMk*`w3V+DYuFR{N3F4y26kNS;pwEm@?E!FiSe z|HF`q;F~9gisk%7bcGzW7h&><;7}pJYf>7z?2$p0(Ap9twa?xLA2)lBdkm#6OsLz( z&G77@Ier!LnfXW_+#aRdqN772qfPkS!?)?G*DaLwSRi0<$A9SjP~dDXV0-u~$sxlt z`1b|gVG~=US1{*ub_lt=l)}RC$2w_13iioER~c&l0I9 z+0Cc#JKz1G3q3Xu;!ydPtNo}^%*$mYW>5=u=_i`9otrFn(cqnDv8!SI4k(x;PVZz| zI<;OnRgFq%c2&QHos4_TGj>5)blr*^)=vu z3?z+NF<3BfZf3F*>|s?Fp(LtWXUZjQ1VTNXcV})&f3M*{6SOdB2J!aD23`+I!4%`8 zYq)wUI0g6+;mn!ZCFL~)$8d>3D#H{EaH}n>s{OcZm6dFmKv2YlX2dlt>y-yMD}2wa z2jkWa1z7G@!F-((v0Op?WdA7f%5Bspfs&PCQEr@yPc~l0Dd3muJkb<#F^nX7nZZR_ z(^AD(0x~wQSJgnKry*sxtd^r|;n$8HG?|_f|7`O%<|WmgjMq^J&DBIZ2xWdD!D2?1 z&`{Z_R#J@Jp6IS{|CpVwJmcRtL7UY-M7&n&&`RmCY&P5nBuEMO(1)yYm1_hg^7>Ba zO;N_$PmWXg?+yM6F@q<}X?S2)`oB~19jXab>2|KaSG9IijSCZO*q}JIs(h)8@4~oE z(G%B>0y}Ce3ogiv2y6P8@tfq1IAFxH$u#QeFmSnV2GrXu$B!@BdotDP+4f%Nu`6GP zKLLHGyYSanLuJ9pXtWShW_ql{$jP{%k|`{d_e30G$?;5gvEo8Sgj1r>&mz$Sf}~Tg zd$t3#e;lPyrc^|Gr|Uo~r(#S&zJ4kNrc?9M9qCJqvi@hBP^9*2;g?%BO2AKrJeHGi zvD*kkSran2CEUKjxB~cCYp-_)a&0Rj{_9iDL-Ls`|fx( zX8Fo?XJ;eM09(((IBf!R<>2w>T@oUm_)*JBt1Y0f=J(h-V&D2uX@A%W?l^*6@;bt7iTXVT45&*TQHYFi6{DApCNMG1>wE$cqZ4 z532qZISFg}*)$-#oVZ&@zRAWZXz6xif;j7yL7}CU2t-H+8 zZ0Xtk8Hj8<^9Y}~%DCvPI?@{J9aXpFPs!k#d@mOiE_+(So6%0#1E3v-$6hEbts@XZ zeojGV_F%39&p6%;=Qx!E1)$Kdeiw)pW6`{e9uQ%_oY2~d=Kv8@THpAog__7nH@=!W z72*4OsRGa{j|B9o^=kN&n3`)s%i8nz#}fdQsXJ$gj6iKAUcrlWkwW<{EycLK`odtG zY;(?>+R`i@KXZb{zI3n}4TM3-lYXiHuZ#x>BDF>7f^N>b`1T5E>6)x5#giq@t za3%-I z$b{Eh>20X_6}2_HH2w<~L>cO{FCqaVL5fPJ)sPUD4So*~+XpOWlibfFewCdpGJT%! zyh@^_bUfBwKQszA*vs5>TE9)%$?90*3|*K-*4~Q=jEiECcbOMMwTlN&QTiqFK7l%# zYCLZ_8pS^03EUE+t|KKvRm78XZtG*Q6wJfVSRJ_5k!5ixkFB0BQ+h-DG(PFXO`I?| zn$=ya&|RxMN`MtZHP|qM^iy6%K^h6+X?>r-=SdhY4pl>ed7jAdRXrhPidlr`2nYnD z%gfA^B{-L&)B(~l79AEE550OGY00@%oNCFB^5g+h%E^!aS%M&_n$+bj)FT$#6U4}s2` zs9x~^?fDQ+asU8(hPwFiGU{{ozQ8bn({5y9O4pK74^~l1qL{4+cEUexYC)eXxsb)@ zHSlS}u?=@MA0HW1u#7{#skb}&rV1wyHXh_{o;JImgE5xd9Jrc+b?kU3@*@NI$Nm>P z*;yfELv+{PYmzNy932BYdTTASyU@0c38WPmmtn<;;}fAqe-pRaKZ?J!DT+YavH5fn zdda1h@iFp-xA#BK5Z*P`RRF#y2>;Mt3&SzWPK0*Zn{O#9qB@QMV02UviN-u@5yocE-ry| zq$)6-A3j9yD9!v}`;z}MSRx{s=t@E9<E3-HaFyr1W1!bY+sFN?qT_=UU@h5 z5|RT2PVMFp?;ux&M>bbb+ z59)y3x}U%j5%~gQ{i5a>uGCX>6(}Kou!PZ!W{uh1BU}tk8h=vpPQo%iEtShm+@*>p zZoAoOd;Uv`&9@KeZ;U=`i3qY!@`>Ae1RX!G(QkOZIJ_vzH299nH(f=Qe2l8y^SOOA z^~P&CF9jC7*{}n%s+`Q(Lgp*;#=HVrfD!0RC? zQtyIe3*liz8PtoiP~zQMUuJ#`gyUnZ4;=K^3!?|y63?2PyIFbb4jwcdPOtGtJQFTV zI)iB*|GBQ-8ha6?VUnzi$^=3$6dr9`1^BxhUez(KtaND z=&o+}(~v?bExVJzEP-)VY#!;^dO!<*1&|kJ1WIpsGp=IntkqvMctTv}RrEY9I_DA- zxn9hQ8jen}IW?DC^40M?05n`Gl+RhGc+`80$Esqr9$fcpSR@2O4OpM>9W@&VU>1Aq%kQ6Wo>zkDz=KFly z)FhYd`D*%Rk@@oGoJD`Cw!x9elNkX<-cdb87hIzU-LvRuXc2>3V~IHiUlkLYSiv8C zK&%rqN+ko=KW-4L?*;&@{-HEu9V>{a$-u0X#bLb${9b&DvBAEveiIFu%3pGY9qr1M zUGVoiz{}hc6SMC|sW1IdgxCf0=w3t!uoBc;g~ha=*|XI2gHh{mve~yxa3)$jt9YeN zZVz5b%JT0r5bsVCm2}G0>8tgk(aTRzw&~VnWAlpN``=Z1 zxFa4q^sHrGE8aO{$3X+RVfGTL7d247uEl_GoR8d4~5=U#@wCG zHIJ?d+G=dq5?cfuITJ}8KN__7MQSH&oUm&;vH`;;FiIST;F;DNmYah+0r_2el!B$V z(nJGn%4iC_2>Vuim^V@v1DQax2vw5AR(M-nmzML-wNi?&!LPj~BDTMhPZJm+61~=^ zF*iNX*rl-9ZmT40cq9YRt?CgkQi~+^(TfK=cwhnJz^34vF~10GueL%nHd|RKatZLi z>@HGkpsp_zyX)^KN z0?ui1XLJfv{56$D(33>|g>&p}4TXx9KuruquI9)nPaz>?JtJBS{~_e zoAE_^w5QZO`^X+M7J!#b_XYt3YDUg~(4rOSSdLtHq$*Y0m8Kq$|)HeU+m z{Sg2?xOtA&vBHEIw-nx)s$ABVeqrDoaD?Na7P*^!G@sJy*jenyPZbB(Xk`8M|4_Xi zlR7*X8Xf975)lRJVA9@`*PjhZ;>n|nilnOGDDFPuZ(BA?f*3j0tbe0r1&D&V%!1mW z-&YV%w%M=9|AH7c*Jneysrqb%{$Ne|-MIx%bz$PDKnH(%*3R>WAE+F7F>hd`fGi>j zwdp=ak~y_Q3AnXq5CY>Im*fUY1tR;i`fnkhCD%%qsv1R&k26726u^4kKVNxI>7Ok^ zYID5^tZ91Qgizt@B)u$A%FZp08IirDoMJ7Q2PpHjY&5B*0d(4RT&~pkl5a!3rp;m~ zEKx78w@><4!-!8!tgo;KzJe^>;t#S)4J%!FT3SQlJ%~^_iLl`?Wb(YGtQUXT?87SC z%w)~~**dQX*(+T#*#;Ue2044Sqi_bhc&WHupk%9?f;HBw0-Tog-iC0!YbGnfopWk5 zzQrZ;;b^>&cvBb*nbXsk^QJ??bWIPMk}s*@cKzbv2>7@b8RFx8rpL&J7J*zz&HfA1 z$i!*3>640=k?|#!_nagKdduO1>jevl(HWh}8X;Q-B@(95;2ZJ)Sk4Qwr=3W&n#*&GWedfj}dmnFad$=hI3=6()&NtkIkEtzXq~AwJX!lf7qv4BqF9}nMg-;; zqgKnDSb98Bqwf5Lr2I*m+c5P-HwyWXM|6WyeYjGiqCZV2!2Bk}DL*PEc!>;5D-C* zW_(jqVQK>u*&yf+YFH&JQv3|ZGcGV$qF~3!JJrvY^VZO}mdpH#qHPTXGnSh4IRHk0 zxAT(T1%_HA6+~{&p{+&Ii9Trb-cH!+?$^ zKW#J4S7i>19_7aY>Xa>fkDz=&L18(EnJRDv2dukO#YDL!>F!%_!9RO|+GCutr#t$x z-y)v<5HhtA zOY4US4GwxVBi>8?WM=FcP9!Iw{iR~(V^+6xxxK{={h7|t0gKMh96ib~A^FjraPp5dw1@%2WXyI2nKVG+n;n*X9}guMmgD*i}RoyLl3q3qJT- zj8Z4Bk%EHA*vT>l!&z31m%*gc&ZU_?u4hSa(AvD3OwS~#L-9=Q85AdE5P2cZk?@uC zXYkO=!&j%QZ3w7hCOW6~LZoB%;2ifX*f-GJR+V=en9F>Xq>WTyts3*f4&_lv z7fzKn&OTjoL*=b>?dwnG0p5xp%{;y0XTIC8cH#G5K3flzUC?@ov14M4W02-;H;4Fs zi0W?myQ3hfLhZX8D%w~>gIW=4p+CXdBs~bR>n^o&0w6vT_nw^C0fd$o;bA@%@pc0^ z-)+l7H@tBaw`Y-<3ih=JuR&vXFkl>LlhR^@n z?owT8DPoLEHUrKj^PAzYKqpEem+SN`(%00Cq;U>gG+NIM!i8i>X`a=SC5+6_;njQLq_fd4O* zrdDD6gz#z<_eU&9Ig;U|nH5xh0vLbZX?5j^)2SLSscDEEA84iBlUAze{%@7w7}$9$ z>)9!RJmZn&OZ>0x|9PRa=K;A-n#V4$nqLIiK`G@bMMb2h)Q_6x!@fOLQ1}ztF4T`_ zKt~)`pLc`ZIAk7Zctlz#9_>j%?d>jc)kDNee{ zG^opllVTk!#9{XmZ{vF)#Xy7L_3En({-knm&ty^9cL&DU<-X`9Oi-mvK*-dIMX7B3 z5E#*ggAdl?BHLFI&8fiamy;=U)qX_!~WWJ7ej%v**JscNKLeY z;mvXh;x6aK0%^*=SN8bt8SEka+S!a0h*A7ZHX$}{H_W$=mr8X9pzNLNYH$A*!dvN? zhMqJ!*r+Nt`ioDzSGhD!p&+1f4GiLsg4WlN;Sd{877pMb*M(2VZc-12AfJv{!k!x? zo0%Iu9-M}rd>4?5#n7IZDaWstQRv*9OtTfkWno`iVXTjA>b;Di#Aj}laQ>BjBKQpb zOiB3Ka`Z*Y*moQtQ5@WmFMF%HtPR_P{K*d}x44f$9b{Q8Pa(i!uOZiaN1_J{AA2`9}!d^df>%*1$&UuRZ__l0`f~ z6u+yKVN*Z_^5y*Aj@My9+m1pA+_LZpWaeT;pZ18VUxEXwqC#ap=?Q<* zPbX^6pCj|A$^>P_GA7R2az9%GTJS2gR6PW0d)7|Jt(Eu{<#JbMmm=^0paZP~m&7Ed zVJQOFc>uv3@|cSdB4GBLg5;33ecmZZI?^<0e#G>jd@)15;ApkCfLi0Ft#uHn+Ya4> z8N7Qw?VrqMG!HlhtV(~UK2{;9YFa23k2`HBRGzoCd~J2E&&P>4zfhy3EqwnM#_RpKLN8k2`dX z5Ig#=z9;39eacAMv#z->j;RUW8Z_iQI9hd0tCAga!|;tpE%}$6mEMsh0(Q;UBu@Vz zEOyVhLiRIe&;~AAJM0nn-~{H&67S4xjz{kE{Y)Apg>M{tGl1O%(-E_tcpTR|=sxwe z(u53MyU@6nmsxFS3;pwYN@+G#c~>3gSf+SvjD%88H;E37$Q8N>gQM)5{7-Q3=PUo{ zAxO{z^9YacGXZ=rHc;3;>Xm>Pv~2 z-&RFm*yGT?WTeVCu+`VdH28Q)4@0nOvE5_U1{RqmYLG%UV7?%JN$7~`P@_Q2E|F;V zCx?UXRMgo2{knhuM13x%Uq-O5^{vbdl|_{PR&3N0JIstI7e=jaSejm?a3Me=ZVXe@~^d2U>zi}^*z&`SiC(PQ1vacX!2zltp%M6yFi)&o<+*T)A zWKwu$BdRiXV(f@aEc(#pHnVtbVe9$wo@V$AWlln;3AkYNL=LrCwsofld~M3$gXIn$^-hxuf+ekKbi9mpqg3FQ8gkKnPHxU z3|AZEe#vS;ND8+d)ADX|nY$$W_{JU`gh}abp5`Nd<1lYi=1_JQswQSQZ_gs&vpKK7@;vn|HmddhW88InO&J*J@KjS|_kOng>Zb{Vy=EgH1$5z_Txw z&H!xCO8qT%0bt@1@^}q zYKJA}lhUB&h+srW1zmwSFVZ1xi}_gR@Et*6F3Lu1X^9S~VF6ciS0Ih}(S6VO0>j$O8yeE+gaq^=@7DBMs?o@UQl5Dm5>A(gsWXkeS3CWhLU*bPgY8_^Y2 zyKZVxR|5afwh7ms`OE*r$6aH^Xu)5aIXr&s2vs{%#Iw0iUM1(FhNaM8z;1*~S%}Oh3VCO(`)?Um z&)BnvO?b?aZSZb8eBRld8iqoA0pfr58*Sj@5A=%aQavESOlxhGwl+L0t_hOwul}kF zMn3)WlQ(@0Pic%_pmmOGGLBBXy-D3^%xnq_CQC&XF<&P___dcm2I(e8N>%WB3X}Ln4DpAAT%C`gbr3x=g%q3jJo@31 za%qgf=eFq13NgnJfa3XEugO;Jjpw_*0^GNo_+TjdQ2c$hvV*LzBF%x{;C91p_FjH9 z`br~<*+-^gh<#wi`^S&T$g<6xtXX!B z{wbmDT*0u?pdR{;xHW|AbfNRqDBrWxB5JEyMqn>$>!pS9HjMYUQ1wkU%pqZbZ`lN= z)z}a2myn1WyZAQv>=S@qgzu=ZaGn2d;pUQw!yIaSqxnwZM|v68Fxuq(b}u1kxkM*F zkOPWlKR(T2PL6Tz&>F9n9bmJW)t8@WGRdnh8RW7w%fC{nxSxi!_UkW29XuCo8WjSx zR8j}pwxP|nFh~8zCnoE zG3jOP`9iW9d&8D^U6qkxenzfhWjQnT!C@9uV>7-jcT-d_|I@lT#6%@O`-!n4B5xD| ze#o;1Sup2(W@vDjMCLg>tDSaeE_Efb0v@-f$u(U<__`sGC?EtPVWd@TOvST$?$GGs zpF+k)n&mL-d#v@hSPGAC=hkGo3aHxDA9vfzs8I%IdcAwb8nYkx6W7Eon&6Ozp3lal z-q$P+6wix>vmDu@((Awx`uz+&)aYxrM_Y?p>K*zC!sG8`62ngUDtmTFT;qrtj?z>0 z@*&Nt83fmwHy}qZRt@O`Go2RwB2!p2(ff5VMT%JlV5Iy6wiB|8)MM?tP%Ns7zL$}v zl$7)O!I@o7FBL?>;moVoIs`9(pnZl%a5;D+;u+9v>)! zqx0tNt$_EaZ0DyQ8y%Bed(|i_NNLd`A}Lmz5KLWUGv&)Of5X`KX`?3UTp9One)*R%%wN z96-c!0-3_TmAWp|wkHjCf$fe+Gc7!{Ot1rPDts||3+-B(Drq(KYP|?FbXV8bVl=ZM z)A^#>Mu2F zoPfw_-pM-dhtNl3jfX|N-fLXS4Xi^~PcghNB zc{;4s{d<;B6?o9>EMzs9L(WQE_GmM0CT z?ng1$$6emS08|1H7PAbN$y26wzL^*=P7{;YcxlQ$^_+?Nn+&H&kQBxaVY86-h~|OR z(Iy9Qqp@9fO3drr{CFW0rh}0NxNmdu~;O$55e%jL9;C zYJZm_nMYZLh3yP@v~fg5Xr>^CGF{w+eZIe3mo^6R3$$s!iU0^`WJ{}9dVK|pf(~lL zRNh|El_fp&VBmjYv}V*Zj2)Ws3UEF~SB$NuS-MbV8565`Xc~F1WLe^ryw@y!GP-N% zfrt2+Rf3u5Zm&2>Iu1QgaHE_jU%_Nc%EL_Yx`g!exYTii0;pwa@B|EF;`_`duK}>- zyYNAxVN%XR9Qi*tH%{jg43j0ipJI+c-(XMOnK9Zaw0kzTeZ zF{2~Cw#-7)$XIG?^i7D(l{uI!)&A9N<}WQwdW#x~EfaOAzwQ6twoOgw05-xjnuNcz zpI3tjm%!X~)qia_Us;7oKQ6`vpWEsS$ytLKwAepQ$Zy)TUjL~JZREO^HnV)o^TiYC z4(!P=S^b9di;sxqe6K>5QhTWoNTiHy3g5TXt}WpxkNBs;K=sSg=h}D0n=UEj%+YPa z4+6$LN-(ua9x zG8pG&F;7;R|WY3Bf{;b9aJh%69q6@G(t>CE9< z56b748kQB=b}bbE-V|Cz&Yr>svL+IWr-9!Q08uZ?5AU6uznou&n_k%~^%Dva?>)9i z5G^V5ofEIkmr>;rkRNoF3eJtmPX*iz&am^2^p2?!8f|hWd@?_<-HHuDqa>+u&(%Z84=-GcPgc2T<+Z0L*gPX2Hn*@)9YW50vE?_YCYBO2ozF&jQBdM8^PRUCP( zS$2;friHKwB5;qhpt;KP^Rp%^p7xap3@kcSgPgfix_uV>Lm>>ph-ixbTYHeoWr+H8 zl-VG2KMlua-p(Vw@1^~rc_4N3^H9s>!3S$SYOR?t*u96qPFxKeyzBA?Stp3x3t;Uv z&RiEE=n|H$Pe>)p{0XSSvm&S0v;kd)HM}|^uK9Nx0VhPa z)vsdSGf~g_JXSexEUw7!TP{zc~9cMoeC)BpL(lsOapVf?FHQZ+tq)p+dsSWS7h zF-YIS!fY8i`Bd43SNqKSLNoJtbvc_%X^@nvYX9eWp-cuuI_ke3O^c@GJ1u8l&&S+tGT> zehPDK+7Djb5TL_AJL#X&fU~|9dbL(EkRL8i=lK{Z8SlMEo1u*y!-_RsIWVYA1Jj+NYsvu4 ziP$oH$R3``+lg$tVB(2|?sBoLbOu-Aj5sk~r+*gbH-Tew`sOj|nb(%wk(G?+y(AZI zRqIy}91>NV8NT>K3X0N0|L#B_-zPWJy3r*Ne|g?HaWi3Q&v$2JlLcALSwluAzzzNN zAD{}D4ZSqDTq5A5u9Pbg6_4~2)=a>G1=Q)(eWcW$U;h}nx=pYf`x-B)qqH%`h8D&- z$^Z)~Jrd=S8r6EtfvWIBuZPW8*9bIrAig3%*BJJjc`s-&vyXQ;o;I8`<3}Cu_lfY< zx(x1huZnOJ#{92D2zq2k5BMqWniJrQJOjVI9 zWI3#7#moLLdZ4G1$S|a9^JDwWl@^WCH08Etsz>XW)3QlhREtnWi$B+Jc)N=POGA5$ zdI(p$ex(ucP(Wsv<#Fp)phFh_?Fyo8yun{T_45tn#_wO(obMfMRkQIzfrd9o{Tdpn zzUc^9BAAH}kl|CYhlJ@o(%Fb}HBz49oz85eBnX!(BYIoyML2FDgN0*fkqoIoLo_8v zr?}7$^@AN!5<712)Iz42T!G)<+dunFAfig25b)!+WI8+V(CaUyfR#Au9j4Jc5igMLuO5kv?VaUX69B_Nh0!6k(SmeI zNesz}#6UVmHv@nEz=Bh?_dPMWb7vIFHZq52d?imhc^4Eyr%!9@X zgRb~5$gd%rZdeFw zV=M@#CY5JF;=HomWjyMPyV|Nz5shA)ES$p}`=r^em6@5mV|ih^XEotYAX@|X7EZ!U zP!AAlxF3o+mgxqx+k=HtoC2izViR3j=A>W0;N~S^A{-odp1WYOj}5@9k=>FWiG9So zdmGO>N?j^$=OawS&!Y5zefTuZ}dKd^}9 z3`oZpel3z|zZy9`5Y?b<$L0o1otM_ao{4Q=)&b(;&Z0Gf>lRDiq1)m+V;2LF(XP3^Bjq@I>CCt<6c^v#D(nR zQLCHCbv%=8e9dg00w@ugDDSiYx1TgD6&dYMSLLODV!*EA6oD$Nv{BAs>XQghgs$9=`R-j2JC*vHik({*5=fZnyzgFL6|5Fr-XcBL@ zegXt_D5c1jF{O=IPgWf6QofUz423B_Y7VfcEdy`a2-BP!xlQc>c}<|{dYvqG>(3JcJ~C*91P3oYvVbd@TF>1 zPyQllTPY!q`y1;d20A0?E;P%NVUQ}^%T^x4DT|v3TibC6j$-!(b@2|Uf*8g2EM9uC1CheVq0kJ4JqhUl+^QAzO85KRw{iM7?njZ_3t{Lf-b52&GA;nMXNyn_+s zoo2I!ifJ>C_IS~?b_hIfGToLGWyY=X@yhyE6Bmq`hnED&jfy4R|FJJ(GJkd(OSx}l zWBgvzV&|O^gZg6X;)RUFEWG`Bl+$XGtJ8LVU$gbp_X(UuAtI#Z+Wy-fQQJou03@8& zFi`C}$r`w$uLW(hO}M3vxv$BK?cJr|?PKYs%k&1!dp}ZLv7%0_DgGE<;fLZi7xRxm z+Keq;8aPon;4}(1ZwW@`D2-;|owPUlA5dTv+uD+p@icC2?*W}66%L-fR z$+87cV?Dl}@~Gy>8LRXt5G9=^uP|Z%>YyN=L(!xsy$->42}bL{AWJj{zo;>ae3JG` zdLe^J!Ev1$N)r)(Q5=4_5CTv#&K((4fbtD1U@Qfk8YkSY?(C5i^?z=7LOc^`lgR=TQ>)SvR246v88e@ zY9R3jlYUJ9yKXj${%bO-8%)#I5XLhd2n$Ipwx(x!VdmvMURvHN--b&N1n~3g+dt4Yh=}%T6Ws09T?tF8t{Q15^$Z9|6quK17LeWO8o0T3m=jbYz-6-xu5>c%SpQ9-;du$5R z(k!jF06@FkQGt7jS*+uuUmGZ9r{##chi>Cxa@nzGXPm#MA$Qn>q9(?~@wxNMIj)B# zxwV3+(<$L3I01|{6rVcF$S&!Y@l(@18HHy01?nc8(h-m{Vk*4l6lW$kgQK4{Ft`q_ zz9*`*g6}!mIsl$|Syeh`_a>q3e{N@75{YmOpGIZVU3{U-SQ-GHZmY(rz>-@X`%apK zrOj9k=zS5olc>{4ER*5z?m+BjGN;;Z|C*FuIO&H#D@-2nRQK)W#7Z_; zC7ZdYKy)4!0x-Tdk+V|0Uy~jEel^MLjVL6+@GS1lOJT&nLjO#(MMO9$T41CC;@TzE zT1^F?`FYR~;n~iv_6|*y^}qE?Er3Q)Ex5LY{=V}}7p^PybAZ}JvADeJ;9WFXzOn;9 zSjER{yfyUO?LDsQzq(@GK3Ze0qlGMcC6`%X-`(`Qj?N-`PBt?7-jyS!-f095Nj(`4`+fid<&9}H$6&VgYZ^pz*uPcoDQHaEk8V}G-$8y z>m#RPZB{!|wH-oMoGZ;w)-+G^wE@^^NgHDoin7tvCmN-WzAnDE!#GU}>IY=@+d{ly z19eqBqfaLYsSG-bksnKQhXc=n#RA4yPUQ+;$b%qwzqm^T25%mR3LI++zA)Q*uicb& z{vLETdC1ktz^qt&y3P=|8e=208IGGuqpfCl`gOU$t~RxP%{k|va|C4r7R%i>Y9|lE zZsyFt6O-F!yr8g5Gv0V(AqhuHYw+{K@s&W5x2OMqZ?2m0FxtnUTF@O^QpX zjwNdGtr|W(KFaD;){-SQ=a$0@W&O|}D(4~j0Ut~0%|MOdpV|zsWB5O^G4eY(A$-Xp z_F3wPr{ssaXAG(Lbf79bXM5z?T7#qT0cMS`rZpsN$7NBWy?TM97KTM3?3&( z&@)3jqg4I#$9%1h)TN$Uh4%Tsywq%aLS^8_s1~LzjH-A8vTzz;G${H~6JGJ3po9Hg!qI zJnLBE;AM>i367s;ufzMYCVyoziA1UWqd{# zgj1gWmS;xJx1#h9P0MQ6MK<@UI@42+2huy12XR3 zpm2bLxw{Id+qpx`phAnpoaN-cLBw;y1;6EBm;Uy8Ug_0A47sJ4w;4tEHeh|bD{7do zo>-!D4G31GsXO=$-0~xFe8WmDHQPb~Dokg?-R}c!VBWctu9KeAn7F{y_>#~pKNkDh zhU$R0C5gOn4Y}Qjab~~5?}f7fljbl9m7p{h5DbDsZ@cm-s=a);xlhi8qxqAF_@R+_ zpJ6k7kqgug>+wcW3Xe)mg1ghy0gGthD-oyh1R3&sK~Kv!b?gVElvh!nwnVKKLFamk zs#zz~Aca4!RbMg2eOESYNMLRtSl_}PVI%;lg5uj$(zb2cOo>tpC ziMR11E2LA%G!>#m-2Lw*)@r?8+9l5NQmth2dn$rVEU;S2$3H03LKD^(ppu`tD=|DJ=OEM{+zPee}2Xy4)fxp0Tc z7xRV4+B$VlVzm2XPHZR5_lHYAtJ+(smMv-5G_g6Azx;AudTWzh3Xn1sv%E^s77_!a zlpXhyKG8=u2u0!7_OS4kcE5fa7>=;J4xZoj_4EO3^+PN~?qY2ODe;)7AE1mhLcxIt z@o&PM^WUd&*RhDJo9q-)W3b@xcPR=8aTK~5yh@RnDIHO2>S8EB3I?^fhcA5BIz=P8 z5sJ_5mz(iU?Z;9SyL20fN4?wTpPgJ-eyuWFpx5K&hxv*LRx%;xX0;}ROUt;f5{2%Xtit5BulMaa>?s;JmZe98j25@-KcOm@0Xp zl~_P#U1)N2pnYwhnhQHA0_&>st@hWoebj>jA0#^f)Y1P>&AmBb22#|0p(_NUo_))x z8(gBPN6Y2mEAa2d=m0kibI2SK|0Rr0>mM0L$>ooL@^wX9-O=vchYGtDHE#iwq3)Sd zyv2EGn&#I7vY9C=I4$vGo`a99+tWqy-%JT=+UeX;M*@thGx|@kZ>uAEHTBxo*q2J) z=NsGem*(tAV|U~VZbWV8SklNo8aFrX>=rYP^G&aArRtx*!~-yZn9rUG{68W1pWwej TVC4X}aCUY4WZ`U25CHf;15t-> literal 0 Hc-jL100001 diff --git a/fonts/NewCenturySchlbk-Roman b/fonts/NewCenturySchlbk-Roman new file mode 100644 index 0000000000000000000000000000000000000000..46df4a4d9f72f76d583a07aad57194c3adecb4d5 GIT binary patch literal 37561 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%0DZY%=3x~Tv8%vkfr%6+*$Gwdm^P$Mnon! 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 F{{v;C|JVQk literal 0 Hc-jL100001 diff --git a/fonts/Palatino-Bold b/fonts/Palatino-Bold new file mode 100644 index 0000000000000000000000000000000000000000..8f8ef3649e8874d81a6e905c8be3eb65522e99ac GIT binary patch literal 41591 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 TjkBGVJNS!>l{*MC1o?jeXX`kJ literal 0 Hc-jL100001 diff --git a/fonts/Palatino-Italic b/fonts/Palatino-Italic new file mode 100644 index 0000000000000000000000000000000000000000..c8d447a64c233b22cb4049a8cc0801b71550955c GIT binary patch literal 39917 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 Vguuqd&dSTj-POv=8RskN{{RN#KUM$$ literal 0 Hc-jL100001 diff --git a/fonts/Palatino-Roman b/fonts/Palatino-Roman new file mode 100644 index 0000000000000000000000000000000000000000..ba252bdcb5fdd946447fdbb74fe4be490eb3e6d4 GIT binary patch literal 42328 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 literal 0 Hc-jL100001 diff --git a/fonts/Symbol b/fonts/Symbol new file mode 100644 index 0000000000000000000000000000000000000000..e96e6e0452df3c74b3f8f0363d9cdff05fd0b33e GIT binary patch literal 32213 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 literal 0 Hc-jL100001 diff --git a/fonts/Times-Bold b/fonts/Times-Bold new file mode 100644 index 0000000000000000000000000000000000000000..b03ed85d48cb5970d4ddb7782737351ef9ee7c7c GIT binary patch literal 34996 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

Y(hIHTwq_m*Nl_CL06= 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 L7UlH{7)J3gcvKEe literal 0 Hc-jL100001 diff --git a/fonts/Times-Italic b/fonts/Times-Italic new file mode 100644 index 0000000000000000000000000000000000000000..b4b018a8d9c648970e3e5df3eb8031137f964b7a GIT binary patch literal 37139 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 n{X|*acrf|~3pp7XAvqB=XQ_L_rvp{s^+Y! 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 B5Q6{! literal 0 Hc-jL100001 diff --git a/fonts/Utopia-Bold b/fonts/Utopia-Bold new file mode 100644 index 0000000000000000000000000000000000000000..06b91085a442ec590833e3a4f65d40311b8be842 GIT binary patch literal 36580 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

ptlb%C1VA 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 literal 0 Hc-jL100001 diff --git a/fonts/Helvetica-Narrow-Oblique b/fonts/Helvetica-Narrow-Oblique new file mode 100644 index 0000000000000000000000000000000000000000..04045ae3f4f7e8992059eed00427c57f2e01a8d5 GIT binary patch literal 28298 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 literal 0 Hc-jL100001 diff --git a/fonts/Helvetica-Oblique b/fonts/Helvetica-Oblique new file mode 100644 index 0000000000000000000000000000000000000000..0653f80bf599b0d49c1573b0198a9fe1c9eeac6f GIT binary patch literal 28397 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

d(A>0GW|SZx_`nCI2yl7&7Q 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 literal 0 Hc-jL100001 diff --git a/fonts/Utopia-BoldItalic b/fonts/Utopia-BoldItalic new file mode 100644 index 0000000000000000000000000000000000000000..c36689694d2810d66dce3b4c5d2b64b6ac816a16 GIT binary patch literal 37836 zc-o}6W3VpWvNgEuy=*>v*|u%lwynKv+qP}n#$L8QBuaBS(&$ zGozxa{D7@Mfq+PU%PY|c7~2_|h}zjY(=gD|a{^SH?d&ZKXaw!7jU}87tSyWH^z{D# z^b9a0BtniR2F@0Cw!#L^CY%5@6Jvm!kuw0m2w-66WM<)HVFNI5aQus?D&yj0VD=A( ziJ6&^1HjC{#Q3l9e~AMuoB##@M-wv(CubAKe^i_u4UA1}3>>WhcBX)T`vE9<{Davz z0VHgV>>Taw9RI0kObf%n05G=rr=;OOxwbHL|8gy1Yib8zp#M+Y*v0<8F;^2ur+=&h z$p6be#XkiNjO}c#JpjfgrZ9A}cFqp!lyWCxD`flZm72Khgi6&HZnKqAu3fvIaK)So|;He;opR@b7VY>fw;{Ht#`Db&C zEo{vIO3nth#s-eY|99Zuu)KkVt+TR+y$OK+e+2)%X851AjDfSGg*!lt{$CUD5AmPt zzwdPZmmd{d3kMey31I*eD+@F0|40Z5+PVLsVPIwe&@lef3)%*XIZRFzU zXkzR9?-~53)&E|bTKu!4CMNDCMlgOL95FyZZ}Yr=huN=HC*Z<8j?sj&n?pDi6OP=W zOjKN`Z-t1OT~UlLg?QEM5F>GZtX1cpj2OC*g$4;O(u23txL}!p4s%9 zu76hT!Ci|{vpC!J<0*k13cN$OZ%;uesz<2KybMGZYj-D=R#jy{BvA$|SN30t-28rg zczVVI0%3+E=|F35giTLy#<0HyTr$KehbZjcS$Zl8Hf?Kz~kKU~(`+NZJ}X$?iG zT#UVtWaq%~UhX9rma-(yx;UJb+CP?e504NWQ^bB)_;ING_gM zHY8>~HlIJ{EX+`_NH^@A5_2Yu>8`6IplG5OlJO&A!kKSr7_}AJX&ebv8kTnnw#~_V z8eK+EfbB=?wBIeeNKadQpoDc?tW*>ixM8hNJE&1d&MJ`w(sQ$faNWF7J4wM?Xcr$? ze@K`tm%l^A{?n13OsFtM**tflI~{TB;dEU)$qTDT$z>g;cn(RG8v2o>-8$t-In$F+ zEE3~gsav3eZBQ(4z5>E!kT@!TKmziOj~5dy;jHxYm^e|h$}IqY0}e+&auCQ7h=zfP z1Nn)z^vrBu9>Udo4F?2bp=uEaQwoFmQs#>T8z>>oF*ptrhynouHlM7tzifU!T0z$oM)&iP!VgDf1*9D#;r4V znW;eKt=hN)R%JL1j{MfZ*u`MGv<^Zjh4vJ@LkkmgG?hv*Ia1RZ1mZw7=3#!IXrD%| z2c}I#;Ut^qxR~|LG~fKKrpJ40f0Ok0;qCkvXH%)J?U+Q75rQ1b6I9?G9%H@OY za;0NZ?IyYp{JIpDa3~C2dQAl37>)xT{`Hr59CVu<6lAOj;z*DcMvdc`_b?t9(^Xaz z0+x5{!N85ct(!Ow50+#hxr{Q9IU?|`5{h^`ZoArGiYih?y;Qo_(kke+Z#j=P< zSg+BL8xl2pm0IMl4a|?1+rI+rLyj0ipWu@>UV|e+jL|Pco&BC)aX}s5^{eZj;ys#f)jLe^v2pJ3j_U!0Em9AymZ zeVhm)-k%x%C(&`aknquByChVOb39-<%gk9Wl)&u($AYovVVF}LOJ$4e^@iQzds}(x z7fM%q+lg9F4Pfx^mfQX($^cM{Z>~5ls7rmymM~iU0z^n*USj?I?2}K(cgNoFevvw< zBb~=6n4=DysWGWu7@A}G?IpZU;$PJR?+*oE2xZQ>u=s4$YPoR=;`X-ja7${@5M#hG ze6MX0&p_15nW5$1R0Mvq$qD$coaBhRXa{IZ$|=_a-RQfm_%iljI~|n~IwrWnq6b0; z0RdpoCruL_9hO&y5`uBmCgCY)tLhWP-`4R(cu>B}Vn=X_!9WsY*g9*%ZU&8oP&>|` z?{Xm)JFGUmNTTGy(HI@(<#bnK{ps^Bf6>Mmbm$wCF#ezu6onFMv+uUAjaCxb#+{KG z$mMo7c0u7M1!7&YJAAQW@j-=O-VeD8^qE?b5s`N;_`hIb;>gNp0nhl=?#3DlU-tI1 zzFt+$da!cj7#*e2kbSKGR6^O}Lr4crr~bWu)2QGSp@mSzd~TLF_;!Ts+6lhI!Z4tQ z4q$CZma)SH{WE7`=C*U4uA_sjV-{OlrJb&VcBY6WmjX~rM880QS<;}d3V3&8(CDx7 zm4c*$=(qvBh8*CVlw5@*0Ts=NkzJR*6B;dvChNRKH}9)_Oa^i5PkzVka7-;YHKNGD z(l!mc&vO;@(JXj?`uxD_$3yKJD=JPwx`_Pjopw4iTFwgiT+>au|UGiH_8#*V2#tWDOh`m#K0DLMSGyRWn|{Cj z4V2f&jdEL3=!OB6+YsrczW(Tb>UP-G%A?$GVVpHgeOO&!LnHT3wX?(Lr>Qp064|&1hsmUM z{8_DZohyVAH+;TO*+&UXD=GJZw50)A1u`WnvvILp`$2ooRzKLX%dTQ1dmc*+CSTf( z3IhxRpj*6)k&6OoVUvCFsQ|-nmWdWZVNRT*ffysq!-rNBM3J^<*L^5EFvcgWz)`t# zl4;Fq$kd`qZ4*!n#e|i#Q56gXm_0T#84{Pw?(kW;-FP3y^h`;xLKEFGhemk9x@(U6 zTo1H&o{qjbT$Lha$1n?d6qYw19^!h>)^l=qDZ8i~SjWa#sW6Sq2=|rhWDS)=Jhx*};l&10c0D8A}aBU3g z^9rL*n-N;%>o!kWu?WdW6AhJ#Ac-_A0ngX>rY z$F>W-F3I4#vrV3^W%w(^)B{;gfoU0^^gAI#jgh;>V~zSxA&*8!Jf=bFlAL;@%ED4ZEG!+DMxhooIy)q%;xyN?_-CKn~|$EFQg zkjmQY8$uETM{an}l^^JDsloh^YfW>8$V-b<{+J;bDpCAOHnLPO#QB@->lb{KfI;8rTPtVXFzwtrYl>k60TI0TbS>o(JIS~!1B!-rsE)IgT4!jl4O?xoqR8JP3t=KKMQgI8GnRNKw<+rE{mJFt+jUs-@UiW>k>XgeAaK3l0p;1xRt^a* z&f@(R>H&T+9~_0laz)gbd?pff*>F>sVcMANQZY5ZtnEVaRdeHz5ygMNI~~6#0OR<4BrXd>3@a!T{!50X6lp0 zm-_KMEAdg{eTq1+M@V<6R`OF|r|)IKVntm)xtl;Sk=En_^9H!+v&M_rn$!E8H$#Xi zI?LK+eNWOZX;eh>*TFm;nlhZslg^g4dCU%R$mx{k!} z5c;L}Z970#AZRHvLaSMW@GkJ?l!JNW-T1p4p>^Z$F`@e+Bz%TC0pg`jkMkrwY&Cz@ z2xwtHaKzU12_sYCYM_W4>GVm!CXsU~-k6Tq^9TkQuGhC<&sB(KB&WHHmym0I{&vS# z_l1ca0d76>oi=Uori(`lU~oG*vOSS3q!z|C7L;wY=i6IrJH&Xsa={V?{x)49gDpQZ z6)~)G`E%(GU-k&Jj8y^g^_YC`sS~up(MeknSs;TErJ*+<=zO`@};N zA5w{o`LcIE^%Q;$qX=z@#yNaIZX#^*@WT9|0l&b=k(+BXyL0ja(sUJ&BP_WbT)#W# zDu_{oDl7R)qWu0mhtd=1Z`m$sg`oi+Z*|TM&bJc{$}2wOW9h{Hb+MB*CuS)9`Ot%% z&tw6A1;tCAmu!7I%Sr>u9-;ZTTV{Q5jz=Oh|O+2#iyJLRzBN+ zT_SKjvrwA_pDx_Bs3I(ff4^mDleDaj57Yp4Yqz3k=M?|vyL(qDJm_i^>_fGjPB52> zdzy$i!4&+beb@TnO-RkXJe8_{O#uft2bep7aklIov<=ec#9w${ByfEOr5}<5MoQB3 z^AQhZ^qf8X^I5z*6F}*9{p+GVRAjt~xFY-&#Gm53jDk=2X6HO*!ew5R3=Qf})di-! z0daK@*HiNay|Agq@BR~{8iSQ{H!`QUT+eHp6N2d|ZR!kJ9Zdp|j*Phj>^?J=q%bN8 zyy&S+FPX?!h#>9OlRD*Hr*^hnyFV^wAsBKyBz1n(x09kGTd{jhlS*z_TAgEIyP0oM z0Y^k0QiJmE2>HY)8$W#zCDvj?Ag%t!UkS|Z@5j!JFXe)~C#u=JRt@hXeL-41F~ltLB6 zzrEMn!SiOVl@yE22Q3%6p;uFBl%J{IYE#1cMWoE`rL=oE&iX8tn*}r4PaBZDV4*L3 zL%mHs?`x$Ym=fp*_U8f~!dHOoBCBp;XI@(r%kE0|5l`MHk8>m8E(UO{n>A)~ZDMf1 zMMHnN@fooQT3NX3_nz&K%+3Ss?%v5JHn!A<23TW~_x`LqP|IE5hmUZJ^i4UgkBQ7f ziSb8&dN0PE!^wX<08?T63(p-e4KH75>qB{K~d7P6mY{FM%TDD z4WN4Z`jb|g?sP_l(*#F|zqaVM=`f!N-N9B zwQK~unEM4X7DdawUWAQF`@nVPfMSp0DuwdoIZq29Z_+p2d!cjxGID6t0e9HwZ$nT3 z9{(jKa^?<=D;-Jo9Z|s3l$w!?%F|&DhT+(|RRHM`{H;?)v9_%frJW6ep=Ywsoa|yt zRpLn?x@y?zTJ%6aV!284M9;-M0dKEIUhYE{fT*Owx$U6M=X1_+2wdypNYTw86=t)p z@`%}3;;J^EK0Venr>W&x%ht?`s|NY4th|IguG|vl#;{;$oIW*e>sLRU$$;)Jjo=2p z#KliHbk;)uhcF4R0(ou3TmoG;dKVuSFvx`?&uuxHt|PS`xbC=pQ18Z`Ee~X{XKiyi zr?nW5PlG|$EM!?Mzt=6V8$Sd8d2YD&Sg7_1sb@HmHxO!sD5rMz zuOCo0_Gpd83I_aG_NGxjw)5uCyLTW7=mTC%%F?3_NDVhsXzX{ViKzuAv7lJwXX3`d zX)6oO=5ooV%_q=d0}7V@hMaaC0sSg+oDsok{Wr^`*Lmma*5_OVR)%kX@QcuyDEA<5 z@0>5T34&TBpDdG-<9XqOu6~7rT~sHs84rJ6SQHC z;|~eeg=w?f9`;{#w|3 z79L1ns;Y>D?*#^#?mu*Q!^oXK8c9wT*FNQ$kKsg@PSww0CqvZ*dO^#7wjKv!H1SrV+$L?`h>X-rueOFi&Z*O+ux6@ zseD{WnNo-D#d=Nvrk}#vXaT9`&1jg4o79Z-W=X9*FnUA-bgr+`esLM}JT?@oP$dv; zeNH(RD`;*Jr$T*9U1Jd1r)Em30LRst% z`E39>@e`0zRiw4)WID^`6!i#VCQVIyn=C#3GP(omW{jWvj+}4es6E=1pSKv@(QOgX za5uy#B7yax9%|>VeCfd33%+{-JddIm-bnDCB)~`iLPEA3N{p$J1vyscqWYl{+3iMJ zk@b=O7u$PdZ0Yc|;vNF4VP_NbiXk&OQXM(OM^9Mr(+ol7CGzwVmv;`K(7Ic3xL-%4 zc+^dFTeD(g#{Pl=d@z+}%ZHi}wg|;j(=y+^*5u3No`i!F3d>$?X^Y<{izpOCP$OQ# z&dV#_MJWA;>r6Y@UXFAd?k%Ho*xe#2)6rLZg-)0}E;9M9&0~PowhIFL?~VD?-#4`> zR}Go4jdNe|Hq>&dlN{=c$8B#qE4mWDj!K1;ddA_@U!dy1yT9#a5d)arM;}kk@SsZ~!5*-H|9m}g*Q(zHTVhv0CN7eVV-pge5M}))Kt`-YnrMOpW4egP~W}OS&vR9{+7F3y*3M2R~QL?O>H#z%}`Kx)j66WEL^qXsdP#7SIhur z?Kj}Xp5~!1Sy$bD?`j{V`D*s4k6(qo+Xfq=LZz&>l&_7FV&tN{y7jjh52WfKzFQG6 z4dQysk>5C6#W5Ujahd3g2rFdfN?dB3MxwP(XijT7_(97bzN+JH7(iKVFCz2KqskpU zv#)Z?O9-VK9n6>LgFcGHX*O;x*qlc6<8-|-76fWVnIovVN*^_M0-GdPt+GEC? z(Mla)L(-fd0cR|?QxBzayhm>wcfVN8M;u#q|bj_=|kN%@htM&bz$mDR1WQec(|o{$xt!8r30OPelzD~Y9RW#dwuaBg~dwxpIc?8Ok?$-YWfo%p4J2Nl| zXMxO#RHjSt87$+RK#}6Rhc^vm#j=9YrlqTTo05e*ohiox-0f5O`ougyzniy zzKC}sT>ZR+F&H1ZyqTnSw3jZ68*joqA~o#buW3-d7xmPJN?psxa$5bXhK=Kos~=&L zc5=d%c9buEVk`a(B1f?4o?&C$$XX76%=-pya7|M7iN<`ss_8Xjnp_3=;MGWS=_7L} z*Sh8637&l(0$aK8tYB@sQZ@DfV`dyf&KHroWZ3AhhD+M_8^y@C5Lho zOpWE9#!Q+sJ&wxM!a{(>+90=1ZHiiC7Od(q3~cyexL!(?nTm#ViW@yjuNya8Eg|1U zGkYD2z5D?8n`yQmV|`K}(DvI#X9Kz=Dad62+sg+wh#jCRTcI_?vxF>@ir3JiHOZ%w28O7iJ; zczq?`$G?wQ(BsE!909i)vhN5RotX17F7se@>2;CD>!79+V($WjS9r}=tnMGH)4Rc;3Qyl|L@I=Jlz;k)={syja-&1875d@%ZvXAZ=k)r&mZ zK+$4F^GX@OX3~Vra)6D`9QEX#cL4TTMkNeO`RK=gD<;3PgL(0$lZS{S5XBDIGw4Ch zVAj|hOjSRH;Fk$|`VZ*)krTufVJ z&b|1xe7FU0j~JDI$`fIDNOnevY9fueV@I>}*YSm!l9xSXWE)iX5}k}x`r~5Z%Dd#X zV?#55BG4E$rIP!vF!Nu2!wrt*!P6F)kr&SPdf-ADbI%5;pnZEGWUI&PJ;VFSb1?9b z$J{j>9exXYsrKcZf(UDXF*jervv^~GQ)OFslB~~q@81I`dDX{;+#Z4--F}8`{dWU@ z%80r}Ge$@H9M8aDuS<4DMUo?*z!t931S?2 z>8#if4=Pm2cMkE zx45o26;%uN6w=bi@pA+BD^dDh+5$zD#}lA2WH#7Gs7d5tHHwq4Rl&}l7Hn}u!ps*I zz4=p`p0!ay>y&Y(lMJ09N6c&Nv^dYaK*K>8nk$VX=omj6&R9&MXv!|1w>)RxKe*l< zoQvhh@jw_0%&WZyhl#gk6dCa&d1R6XQEpoJn;ZEX#boN1 z%yro0v}HFR~)gAkfzo(kOU^})`BwKr~>^-YhvBn{R_>Oz@6n-&C561 zn2l>suF$k~Dr@2E5xDe%7(VzW*%MRbl;HQv3FuMHHYu$L(9HH@K}2w1%m_W4C9dqy zFk6;!34R1iS?7QK>9==Z7wbmKFg79~;U;1LYD8>#$Fe_2gk#+EOQ+F2qa+XL-e;S5 zvOiH&#o5F^TIz9#+!iVb0rc0_18lv^DQZATclXj5Co492+qtT8IfRvV)Mu=Ykl(}+ z#BvGlZM8UlAT8A0pS9jl=bR^=;7H1x^R|^9ACk;F#GwNQ9@{c6>;qH&@WWbv{YB;v zZhG+TU-E3f3Bn@!)-=}VibGm(e{I$EWGNtuTql##olMzmyJWz-wQZZiX(a{R=P zZizsHV)77Up%(pXBb3N4{e3@vcDB6gcE{!?jK2aOQnO2fejVDY>aO-&`@5!vq>7jR z11FTLA%s$^WVGbrR|o2Mp?eV?JCY&lczUI%>0#7vybJCLkYRU@7z=)q`hm)B48y4*k1?X9nrt~oP&>0yslf!~{{M9;~#+G>g zk#O&;(~(jUd@-?Ko1h(rCB!E*clIrMwO5Slf#3DrA_pPzLY+X-^eTN3ywb@|GR+8S zeB8$^ABkp&vO`iSW3Y5TLgX4|rk=bzivlz1e}2;D0Mc7iiDYK;{riPPH**_5!dRo*4EA%L%e@D41 zAkve{DQZwakDa^{DBm@DQHjSw#RR7dv5w}sxMiXT8Go>yzCh{4_FS8Pm`~(3q**G3 z1}U#l@>auY(JnzMM*LV7a}fplE#DsHq!aKbEXM$V`;ON{+7MCkcyKzM!9^F{YcmVK zzhs1;Ctf0*MPT5Gz!-{$Y&`}D2VK1c7~>{$T{_NnaJorKF;6FZR8R$41n+>I&R{As zsh8<$=(l>^Y@?W!^Ff0efKG6aUxk3NlmNRq>zoD!TcCdLDR4vroZH>Ezww6r2ZQ@XoJ z_2Znl@_j^za=m_i2q^W4U!Tp0WT=kxPfAuRWT}aRmTA0sp8D< z#`ob03549ApBm@F)`XEBq>^n(A#iYk5dPY?8Lh)M-88iaZ%pab@W!vHP-!xO_$wxy zl)8}SD6Yi-@DcrW-!@$DFOoSDX>Jg3*Rp3^MuL^ayDyEioWEHlKY`7+ZBIiR-fI(? zb~tpe7}R1mGwSNr6DN9gD4gHU#Ra-ydH$M_=aMy6;fq)>)M#fU?yJ$ed{6+QM>;4P zom|r_&!8@kRRTQf#*jMtQNfafda#7%JxNz`a#s@r>UO2?@?l z0#J@fa!y4;l?g=J(P_lGgaPHF(UvyK)O;k7sPFnpt}WI`V$Uiou`(VA2E6_rgOWVk z9A5^3DXD+s*)?W}(G`^qgX+GmQbwc+xadJz5$1Y&Xw4{a?`jS_U1%v=EDS-xF-N&1A}x<^xkGkR)k{o} z7A(bDROPMH&iTHLMuz7~u!uGe&C8VIE@onHdW5yxz)JsjG>%Ibr_nSO=iU5H*>v{ z^Iw}`eZSnP`kc_0@9mzN8T`ISB#`#ZlA-PFdGJl0xR%An1TYY%U3)Ho3~Bg$A^+SW zjV%Bto>&(0qN65KI@I$w_XQme9(SI*-zA?oM&B>-JOdCG+Q)5Xev7Oxi=XP9`F8jX zK~Pz(7_K3@LNE3uBNe%5t(0VQj}~^*BgKzITw}v_<}EPgt=trOl}_H2OdzA3g)WNh zCl#8Q4f7Ty2&Ye|hrG@d692H%U;_@ki>}rZdM={{puqqpTwYQL+(u zrPM(YJt|&|fmW`@VBrN7vf0%^n%B(~DpvXPw)YC(gPKGWKjwOlN5yu>7g+Lj4n>XJ z=pkU$#PNj%Me<2DHkiv*+7=Y+1#rp&jM(1@L;)B1`YyfLBc{Y0Ft4P-8hsJTL=z3~Vs>GoMTn(;DrOL-MEP19{Bq^Zk+naw02VHFP@M47HMz=g zOXhhD7K{PX3@7_6PVGMG<)IOh69`1$8=Kh46?yVY-8)CShVyc^Nkx=%`w=v1(zZ?5 z(+4XdAy@C^_4vVC5^2d_oAN*}ZqYuLmlEAVX)SI(;2IB$d_Mutg{?BtGjUY z`^8a9oS?T7f1uGGmW$1AM%Mw|NW~|Vg~4&K7rv|mw8UDTNuLgRI^u#`dv3RKSv%2s zWzFeyabP6k-hlSws=nwSh_ z-)CxcXobjLu@3C?=uRH0jPy!DXF2`2SO1`(GA|0UZES6agFXo&#~s((r7lib`wxad zQpVL5umuuG9k4rETAQx~@0w~eP{S(95^Sl&Iez!d)d7OY?t5RwabOLUr;&D{umCP; z!RDMKl#~vJ^LPJ?y+@*vPCN(v|boO8gS%(Ev{Ws zvn50aTr8gk`|`5|V-P4N{w}j6L#K+9QCUfr6NN$`!)U&msTZqE6NVhpI2O+d;{d9! z?xIU4mM)<7Eb;?oMqySX9b|xo4p~1PB^^i+AvMY2TYP;JIGn6SPf%b#kQg@i?yX*j zpyx4N$7tZlDv2N$zZZ^(P1V^g9I0kardwmhh+wd+WGYct_s0B-8VvE-{Lk^7aLA$mJ zNgV5>zCADV3nxt%^LXpbHL0_u0DR+~DwP<3g&mV5=+%m-o3mU2|S4;+(lBC$4Y)4Pkr$88`VDutN~ z15(P)T1bJCIdjv-HHFB)l`B9Ky#4EjWxVMS+b;lcyu8btqA^$%#TOzcN<-mU&JCo3tSM-ncauTwQPfJW|6?WMkj3*&K^$`^1T%%3 zMgH2(ry^$>btlJBO1{!C3#7;>z7*=^5KUfTLq)PzcjMbt+8vtTS#<6S>)np)9SemN z1fd*)FnMDZZ#2hK2^I^EB|+R0#MEj;UsC0#&wQrb2CL~6qUexO#%2E{B)e@WVU+i? zuT}p-B{nA$$6HtdrqmZZ4 z8E2l0)Y~>CZ_*ys9yu{O%D+}`W{Jr8R49*cA#t&0ufWjyfPl!zIRFIrm%Q#y+1(tS&> z3;#LT$;Zvr^Xq|cIQZ!A**jjauoVs$FVmnEG0DNc2BTSds(5+ z<~7}?v8Ep#+6KaCqaFOgjapn#riKube}O9xVZCI)1(q|N^?W3AA546lM^mp&Y#kB9 z_!CHLt|NMqWZ$HxvVZx?f#+NlYR*BO85AfYrOT7~_#%?iYkB2m=t-v+8Ug_?@kGCd zt7m0QfIX2EW|)1`x!H}#H{M@rhHD^Ups4Op-4L|U)5zwGq}9q&3jqQM*pzs2Ym$oh zWb0$o^2vtM&VB6b$278~i%7_*COE74B;x4@Lkcfh8OLU59AxM-70Y3c4SyC94_FE< zV7CGZ6sy9>G8hJh@nYaCoe2!I-EW}eDIa9~C-J*MYe5P>N3Bf7Z;DorT%^5)ieixTq%lk!kUS&U5=Liu^(X z19YRqCE`MQ0%JPb4GrOWn#lo%qK&x+E2%13>)mgTIPB(fnK*r?>l zRkJHqXxPaY{eAZ$-)a<3vs*gEMXoSK-fOF|aOAoCo`s-wfLgn4d86h@P*|BWh$kpn z)ctGf$`|l#(fFg&KRtZ8fJ0n_Auv~ba-dbG8)D9s@=XoKq&z=OmwVQi_L*(dK@TRey41fPT-d8R(IsU>L{hqa6!P_Iy!$4x8{UhSU)2c>wqi@PCC@znrc_yQ&lr$(fG1Dmdo zBH1d%wHdR*X5n|DBOZ|bZbe|l1hjvJ0qM{_B>#gbTdHAdY_Lp;ZYCkWB;zN!uhT=q zA8zZJdt?uBQ-E#znL;nlx}lPY_0693rhh9?w3f$e@H_u}QJ%5(Z%g`ykD+4ac!_sr zce0&s`Zi(Sgm_JAG<6JcxjqJl8F*R?XY}AGs)iw{)wuNm^ zFG0TW0_p<&F}4*es=TEkf1g~l^F;Aw4VQNobA|FFYpkx_n}}Kt@K$d0^E0@v)&2|V znCu|9RiZLuRK9g>?&d#5*Db@{x{&2C`d0O)YdE>@WxdVGRq&i zvYf!C6vL)403ReJzNZ(085xNP(&I7N<#JEj{iu$`4I)ZWVUAz|H#X+*Sdzwhl&=x? z`{8l5nDesmBa*9$)LL>v!T>RaGWxJr28HWJeTHV8m5@+kPKmmm#ZMNy@f{7qY7OpK z=q6TJw3ldEG6DIC-A?*azsiUjKHC}W!k(UwWf+!sY)dnJ5xS+7ReI-Nk3yvu17Rvs zNaJyk)5lpmx_c60$5y4Ub0VOn<-HdlQ3)BFJ|#}KPaq#hmU!3P^W-?|444r;u(J2I z_dVu%LT89hUg38@8CzC7L-cP3JttT|sF8^bS;oseQF|=q@t>uJmjvL@i9{=r)`R(V zBnzcG0c+7Byabxpr6hdp5Gap6MG*Mii`JM*U1-+&u{qi%2wbFrX~eW6(|o^U?yjg= z`#g$Rk?P*LjU>uWV*4(fEbg>t9PZN4xmTib5C)-)q2bq`QE+FAhGebGbCk`sK%Hn1 z1P$KbZC+zN6D=f!`SqLIrm6a;^gY^Kt@SjQ6EyC+__f2!oje=DUbGg!^<2gNo{$ub zh&fyR8GYKxW(Z#<%GodI-Cl53#_aisz7b_+;@6XsCJRU&8>r4X$QHUO0HA=Gv$J@?{pEC;I+UpZ3h)h$m zn)siaLS>V53;Tpug^_(7nx9YOGf?X_AVd)vU?!|cNyu|dM0dne)OYzeo4n; z!}f)6(R-Ns!z?Co&jD&_?#ILGjf_o9jIELrZQNoK5opAQyLQ%^z))N8OfHF2+@6cs zedV?R9%PY7+vClzJ^H>#D8l-#SNJj_WaOcL8VN5CEXjdua!*YBa#dYey5(5dc{D3l zy3wcUp|avTkG5fIC$7FDN(x4zrWLVTEgVn6|Kp82$U682Zu5ko2}8|%M^68W%|w+( z(*U-BslnwZYOtfZgF5o#ATRw^^8O~SkI##OH3mVCQxLB=sR4*8bU&$WuD%97ME9y9 zIn7^30TnPDu3r}K)%SNU3;@3g^fMbuV!$+}>|b)^ovK?pFd?*i9F%PLy0p%k{NvPz zTQ(eg8E3@o!grw5eGLuc(XAS%bKQ2xAPP8wE@L-4$HmGwN#DG^UwAk_ijJI)E+@^e zO>YAC+RwK8x+E^$z($o_`>t6pBx$)&=Uw#x9^%Vo=uB1R{0^bt0jio=Thoz>!b1?- zrF3Xc?EM!!S2>&^-TL_RAKcBFO zPh&ULWHR$sjM@c!JV!9jBfvvK?U^E-Fy}S=!mO~Fd>xYCZ*IQLW*nDB(#z1r2XkEU?a}{(_~yF(~Mj-rK)Xo+3(~IIvhdffxTaQ zfF*a6N3qv<`0iGQ1o9MCj$7e4imosH$Zj%xZm|o^#COJ{z=%olu;m7Xj_A%SGabn0 z^pVOM`e|T{CakU(n8yWZ4<<0089LI$>kw&y0=?=T8X222=ySj1;+~?O%xM3~%`2Tq zcC6gAG&qp{hKauLVD5WvEF}w1J{?_p{B9GTBWi6CcH+6HjtVstd>h>e!ie*T{cY+b z-Wb#Pgjs-{ocuVJ-_ne`hFpnIm^^{tdko45UP9ZrQW{cuI+*d#m+$yZva4XpB8YlZ z`$A@)1_zZ7-y(;mttNb({@cb}HWEU0cLW3u{%IJT!7jm!;)ucCeDlkcNc&ACxnFrt zLAUYgB_=CleQ9}0N9oNy7v@yO$XFyM%Y_S;^FksV0gIf1(>SRGW+-jz=&!hE0hBwc zkmLKyy!|X0X}~+_j`*L<14iEG?dbQ#S6ok`qC|wn{E?p;m}I&bNI3*h8JT`t1a2fz zPPG|0)Q>U|Cl>P>_*hYFpd}TkT^PR}rB%$uh$%ToilVw)Joy zn$<%8*m&k2n@`hGR5EsS&tdaOnS8v?2ceoux~(x%hEHEzUagujwI4RMZEoP()D31K zTbrz1Co|@%aa>_Xw~o6V$l=PGKUV@c4WM9raOh~d?9VhM-aqbdQa`dWr?wylhC!hq zai@(SZ%MfNc@j<)7b`#1a&yD)%crU&3HZi1PTlblZMswPDvH9ic$grfK*Z&XPefn) z^C+oI-^wR4{fyMV%t%q=SY#Ir_w^Ce%(K<`5YD?ZUg+~9E?fA>FIb5!S1G>A!}SflfMd>HuMxr ztkQk#W4fr!>lZPx;N3WUD}H{$*N^$I0!rjYpmu|O5nT6wgn4kKKU#Bmb@-?GHUqwg)%Y0IQe|I60%mLuQ^QfRSIq-Z(cphfQ{X1Qlj{eoDD}5lWtJ9XYw<3{9?*z z*jwXLJB~lL{bWWB$Hv@Mf`o30yTke6B$s}d{=lT7ctiKGGL#+xeZktZWId8nJJZ^ud`wTgaekiFRhC;=c zyP+n+lm%B<&jYZA}?~RMj{`jcrYKqMoL-qv%Da5jwZUU zTWJLX2*oGx%ASwc@%ZWC{sXmTlh>fX*E=2o)BwWtNiDo5~llgR&sDy(+j+Mh$yOHZ7emsdZRkpREy9$<%)~MzFv@_?%<|>jVorE6Wo(hGIgh9Mk7bl!jjeRL038 zPqM=;RP`}}$Z3#TilWtG4UZyu#l zZ`DN^vq#o`Rior%RBqOOvy@4)?(S;sZ=S{T<3CBxSAP@6)IHD>iKlb7pIMjM2PUvIlp}*(yNa^6Up*n5)#3Tor$cy@~wG5@|1G!Ec z9_yt^WE?08(21aq#X&XIva!90{x1LqK>5FJ#lK=zV+-j^_7a9)_x;ihd%;IFBlr+9vUi{+qBay?HltJR`k2oF)-HWLeYVz4FaR);SqL}+j2 zm7mocK<3dHcJ>?DO~lH-aFlHR%oIw8 z+u6r5Sw&HqK`*ZAqhw4VB1oDsHYGk3m%B7rzDauhOpr;$rWK(Af}Dlvq*rb=4iwlo zH!DjPW7HMPu4+1!NPrPb6QRNswjQQgK_}&OE0~0rc!@SKwsdK(^_vxum~yAj(p8ZU z7sWMp@HKG=8P%RF8b;9GrcbBfI%6ejj%5UTAO26{WS7z?8)~SW;p~GP&SBnT!P;z! zR&v5#T3UPZ3V)M3{lr}NyXhf9*kW5ctam%F+{P3_U#-R_ncfJ86t^akp+t2C>7#lH zI+g;56SP8sW(^$=s zjs3}BJ2L#fs2w}ulLJe{Sd<%jK{-dESx!c@tefBIL2M^j2c$42l=rzRB5RD6HX1mZ zoB1k7vW`$12H72K)lbsWaD3$|^1^u}#_3r|sW!CW&ZAsw#xC0*R9Yyjb}qa;DzwDI zrf~ff&0`<6`@(Fs9qlqk9ciMtELdzn%@{%YJEwr#t$3QurX46_iQ457l@uP*au?eK ze(EwuID?SEQ^GHlmO{8+hxr*aA*&wGYqX zJDg6KgYeD7cQ%Hz>%fa0y)NM|!|{qJz6KD)zM|h1L#{X4y@nnv8f8&ki`~-{_>`Mj zL9C~8AO|~C9G>J?;!K7of%vyp`e|{T{OUGJ4VXEJ&eNNs$q@X)S^!`h13=i;2tQPF z)l64#690&m&<2trn9J00jxyE#{8kh=7?2ug4QJsAakh0skc5r0Uj>(Bsh9!mxS!DT zjYi1Yo&f3jiefjL7zl)9<>He} zbc|%yn?EX&*cu)W_!==#0X#Qk$^n!S4|b8mqPT#W0IMb_CC>LmfiKeaR%n#EAB`eV z*^7y&Xg_mpOIlg=A1*U2j?i@wiRr}~k+H>1n!tPp;jJS9l?rW*2@(ZRDk*E98U_ zdJGZP>fY4rupng@cdgPzH`qIEVYCO|4`9tS?o%q0L-n*H88?HPTQd#!l_@{_D<@JN z6d+~o?(f8p$@v9X%Ht;782W2LQ>cX4_Z#ayaIGn%cvq;7Gj zpcvP9E0UR_XdIGwh(LoVX`Q9G%fwo;a8Nk782k&|q}3>v1%41*i-np}XJ<76A_%8y zzCTkt0V*Qet*rg>n(x?eXUc>M6m#6xQ1Co4Un9J3*eF_^7nX)9hy@x>#}BK9m$gh& zCJwPK+_~j5>!$g^W{+H#3EVJ`HMu9rbo(6)SaooQcMcbHNM3b+8+U!NT4+}s2v10} z+F=6BdpO*Q_o(AE5!d5XG<6QVnA*5QpU#;#_p@HT?{iKoMEdjGX#HI_==y^C&XE*s zroZ8_aSZxkrWcHe?-4f#Nmj;u_#OaK*ASiS@dOFiQsehx$*AUId2h_fv_D_Cd8{J?dRHs#)@dRI?O`DD<{EXRh%@CJZM@&Faxs6?am3AEk3 zmGUBHQlD7pj=5Hgq)fyVQ&4rYgOhz5GZSBT$a<2Vcllh~4RN7>e-V@KAnd`!m*0*E zb0q~RkJ8M?J9pg8i26;mJCqQw6(q1YWMnTy-qb{9waW99DdNG7V@Na+y`@Y0XNS%6 zfeJq^6%-wPzX`6zxCV9BTI?)l=mB?2)8r_&(GlehZ!T+HO_4xom6*{-M>|)i8nA$X z(|sy`D~YZzSxD;<^MHjyxUYPo7dz8FwG+mFD7)*2VtUXC|MR!23@z&xX#0{TNxsCr z=Y&YVaB$#z5D-;ZO#m*Ff@*jf7V+Y&eJ3v(F<}@rbA4229iQgqxkd{WHJtU`7im|iFglEr)mLBd4y#DKq7{l9OAN&0$4)Jj11kk`xj zw%O1Wr8BtvVsU<~eg>SrZaOVu;72RnBk=9?ASz@$kLTR;e?$S_6x8mX|?w1M_3;Vp8*?j(g6QM;_AFh#ORBj6>0n2tm;sO*F| zX79dVMG--c{=^YRFr0c<)@9iLO_$w;SB>o91g2P;wcaSl)8bu>547KI2+)4 zy}Mka?~*~S4s=!@pIQ|v=*?&k=mf5@_ddE%ZKbNWfYbXV_7|0Zcs0ZZ!tfUx&fi0E zUVi~a4?Ep3$sLi#PF3nssQy$V)k$TpzeRMh>B!`4c(-r3ee+2aK&QUkbgycbIxRFv zYk}IU-%s#2QkhZWy2IRst}3Xapj0{llhUnvha+i4jkAG>qej0&)pGgbyf1hT#|m3z z*-EWJABc-pl8H^Bi!$&-7jK2~@2ejQ52WKS@mao4Qz$WOW-{srV_O>}- z%PYJ3iPy$zM6%CWY3`VXOzJ)avV0lz$B|bt6BxXgTimR0REo}R%;eV|P;O7pF0mCb znnXnRYiuVF7oaIq(CP{#NUDP_iK_^eyv)NC`vR7X_f+jO2l2&|2J3e{e`EK!Q}C{F z2|cG4w!pZnMw}yY!fb^ZKJjt3!Ssw(kw(#&n(=TAoe1OB5B>E>)z5l|631O6txd#5 z^ANTr#GnocdAV99nHZeEi28jjKhcrNV-`!(W0{O0UV$O}JVd7bPC|<$N{=iEv#?kq z3)84R%u5m^v69%ABrs_`mXe@F-*1e_;7BQYapXaOe*y#N;?`mCSVJ4H}@}>y28Q0gcN$+n>r71@G&#o2xp#?$=mfxrz7`owBha zzxW9R1jI}7+7yzemqkbfxL<@_AOc25fFV+Pi?hs0Qi^1fEDwZyn@s;3St6W zcxS_paAVv+5~q~`Zsgey6vG z(lV|jv;Wf-6s?IHdiN0~Jy&?~K`pmSg95R6`iKxT4+s343d|?KY>{6ZMco}uBaQ%h zZIgRNIjA^lLe|$mX1=D_ah(NyRL{zyg2eD+Ho#Ja^)_dZ?yd+WKCqOkf{?@t&NUCnhfiJ@Q;r*W>?y}R)U>|pWb{%MOB}ZNz*qT`b71M!)m0H*`Q)eUex-NR|D>8 zUFL3Re<$Jif+!{)xW%L@Y@0CaMIv}~^e?8awr;>38x#ulHL>E2Vp|wV(veKMWkqsv zCHFbJ(b^k*AEdId=G$k*N#Nq;DO1flBn>{SzhW>$(u)z1laf4?p!uPv1?rNT zKR&oFD#7cS<;Lt~sn04-3p|}wfoFN`^jt!lN%d3k?;jjVmTH12AR`SLP1e9(EN5qc zt$J+JB|^EE_6MQD za9@ySK!GIXP*#_j7%-u- zMA&V;%NtiolQPZ>d@E@uT?9T`;FQ=k?J!vW@Hf#Xal&oOvf4%S%l3~UpAaiqCLjkU zu2rHG#U^_WqjcUu#A9~Pw!C}*U&YLTI3k!KGsXlaA39UV@c{cnV}X@lO;k;p<0)_K zEoHg$#0ECY_VyxPVo8G_pcIYj7ZpZs#H6NTY%OW6{RDwxsW%iV(F>b4)IGl)na6f9zn!EesWqCEmk;UgG}_g(w6<`O6fw z=F-dZ15s17o2P?nH!3VjL384^Kd3pQXsmda&*0<8u`$d;g*SY(&PTgX#SVm`O7l}f z%`;Z9DV;(d_tA1^m=@Q(j>10Yc*ky8&-ekL8?5SM^krzyU)zD@{UQ1EHespwfnD-g z;_2Q?BKwOah|RMDdsijv-FBr8ziR$A>Z%7StG>MqYTI;1gO#&OgjRg|LOU7Ww7h5B z{Dw4K+M1tH9_Tcoexx*&gzV^hPr2$6ag1OJ5hB3}VUK{zZ54F&>BKp;i>n&~B);`18+$SnpfbMoCWgn4&&N=;u7sznko`lYxlr9$& z!5nOdtkJVUTotSfG{Q~I{8_BurEOV&@4mVb8ctS|!$J6AJ%h8Lf{jS(07!mSqJHGQ zdy~Tp?o$rEE6~IqC=X!j_Uc4Pl;TSDUIfR9Ey#uq8Qazm6?He_fQ>I!8~AAyKK$6H zex~tg!I1uC^0&L33DIXLMZ>^%0iz^{b&PS zFLP#l@KFIZ*=YaxT=>Nnpq%y#-R$a*h?_oRySD4n?|jP*unzU9CzP>b$S6kl{PX6U z#+7VdV|QeN#soX}JeY4E7{;sPEOGIqr%x&A{o2|wUtY)LvyKuau9CVv{YOU5bin{h zd>{wBI+f78rtaFTz)*PXI&L!lH@36w!MaA;UbwrM7-zOb1b|)4k+ikowI{H?Q|FbI zr`uOP-G7gfFoNK^73WPvx>@*}44p>%G{W&E&MlUFkUi_Y_HaP2i`wRn;IZK7oq6fL z!G$?YlV$1c#7k4Vo zl9(%5+gLC5nm_iyNpuB`tQ2sGz&u31^Q>^@g_EAt!3lZ{w!5FRnZ>}B4`zv7+3;L_ zCLm#fKFWaTek>KDX7#>82bR%EKl4<5w-06}R682t*7`#nRwEe`ClQQZxU(_Lst*~D z1}ss}yO-6^n1*nIR%xlZ*m9rMSSu1b@zdRggsuSQ|r>*78?_2RRKDUSi z5r&=xQ;|U`p9!{h>}Sc8cs&c}Ov-R}LQAcGEP(Ja!rcD*Z!C^AEiXaf5a0LHeb%r% z{UCf}2-Gw((>fpgl(#}iwcA7RM0QGsT=J%88?pJCehv9r#uVCYN{ug%ukSClHHyBt z&oF)paSBZ~aNc#`@stoSVgquKp+mqkb>_kR$|n)t5~}*m)xdGB@+^kjBn;x!7$*U( z;7W=da}+=l;<$}XRw3tVCf!sR@p1U=%^mJLzCCI+dv&50qz-vhQ4{(u;ab4zDwMdZ z+=Az1RhF>W-U()DJ0loB!$Tytx5L$q%{!WJ?k)GVnd}4o+zPB?BL#PC2`qg@$mUI- zOihzQ`c?UNe!i3%#~Qr4sY(x#?Af{%ow}y0L5v&RHGp!51?PgcC6sueHs5j8Y}A1s zR(b3{<&-kkNf$|}Wj>eK8gQ9HRfYdDGjWK)?>vzn=eFp zW-N*`TLAwVP6{cL6;h@_Q46`SjmeRCrZX}08+w5{$7BnqeR_h~`GP-nz!7!Soh>zc zE94-!6MQ%!@?i7Y$CwzW(6rcXC3^S1#s1S@6>uc@mzDcxBhfqD4?&^PY_g&<)K@oZ z%nmazzFRglPrb4%sMqCY3WoELF9fZQ7KNFJh`On?;G)1}(zZOi-g%KvJ&#fao1-dU zR3Gh;t7*2H)jb4PRVM>Q)6SU|NRM^AgXhi!8qqeGB+j;K}s*4w%v%^7MHmQj2cd^K!X2)BK)6i*8&P1&@=} zyACL#wVnH0StQFKx@x4Q<)I^PGDiT3=;!xkZ0GL`=Y^ee<1*icV1 zGHO2+mc~C7CoCj{IAuhf>EwCU-!c@*8=m0$l-el+X%eQf^0?wasS-M9RM<)g_D8zW zNGYziS~_pYx6D&=JDDxHsZD@a!#p;dKpNK_+wupC*sCx*IgkQi4PNR^#A#DiV&UfH z17>oBLH#W?&36=)|DkE^OxnO7n2vnq$I_3T&K68V`e(`#{U5Oet2$hIaBm$(kq0vHpRSa+yigSz^%V1DCG$)GaAlzb`;o^r|8zuiE*dPcm*d({+4S z)sWxB8d@V0?>a^aGUpr?BAOK{How|}jh$$u5!Op2gXbHOtWJ&MBT}pguktVFf))U;4H_n!#cE}X_hkWxR9YYMxLtF}X&I7t zr)|7n5=N${24^6)BM>qa5x$0BtJn;>QC(7}c7N9mJJ7>*5)}dfwAJX@B}lzLIV>L* zrCQ;k5c(^|>#W5mZfS#k?aE@G`PfnzQZ89mX_2fVrG&3gwiQ@&0WM-bWWe2<0+mL` zGibdUk)bwPFoL%gbB!%W3rw8Ad5WD0bzxU@xV8Qd*ob5%4m$C&%K`JtVIzY|Mvu=O z;qmPGMYj8HF03Vs4rj}*86^&~?2>z|-YFeKB-o`>d#~Ip>M#yJvg=_=l_wYaHFTZH z3TQJ~+(K=T8&5!Y5Xw@YZ4e3+Ji{hMhTQkAwyquuIL?0h3(PL7sW-eGl1yRzP7)OK zAM7xqbnO8{Y_ z$G!c-(%8Ge-p?e1g5sMr?2}A8=~|>sdeRWm^n93Ww@Vf(i)3O(=Q*9fLgz%?qN+#~ z@r1sfTR?U#!chX?HiJJR@G8dvywZB#*CRg9fq29~V{)lPvajYxIljd6`*3*E>*Wb=w@#0Gg{JiQ&G;Yr8Oc;tL2Apxgv(RegD)NjbQ+^^m6XXG_; z&#VaI!l_F$$RrnGS-l1l%dHBz$bN?G$L9Rt;F`v?DySUs(iX~Jr;A=)_Ub2^gl2*) z73sxr$Aa7K{VFR*E!9<39exIESSUmmo=^Fb@MAAJU4+oBm*wEdba8P{hy4QgM+)%v zNFXUH@k%M?04Y4xKAH_YE=mwMX%nE0I_rUh2SvWVWgRob+&`K&D=Au^?yk_HX%<=d zXhz%lZ>K#J#-Fw+G~?)j?P|cCxr@Zqh0dE94H~O3;kztvtRy7`#*T^CmdgF;8C;-} zFXI&{UY11EuGX~jpdpupvy(e`6z?ToH=_ydu>hv2NJn__mGQWiAm^lNahX&5@gAiF zS6D)w?$N~A+3x?un2sH{AqTDrhc$*JVQAnFbnnOmBwvtmkp+uzxFhgtS18oGEW;_W zYZfB!2M_detJwa{!@rA396|26xFD%7b{92 zcTKu}n7q~|w)9`|S3>);SZr7tMC@^w0iG%K0$cY)afQE>62rdpDuve4Gshj62=QwG$zjsR74_5?n1;*eeJ+% zsXXq6{&WZO_{$N|?AI7l>bz{fCC+BlcWtH*O|I+wucAO=4x1($k}vyb4O0Mm)>*Cc zUNgdDQUS4A`fSaCvL)Hop7)M#fSm*Ln`@Sh>iFZeE6g07#{W&_4FjE+(6eWA%p(C) z`a_S8wBC>5@T1vOj`IhKy2+|^yGft0Z|uj7uq*yZ+(Z=+qm%Z4RulE7Vm5(7%$ptI z7CY``FY!Wu3xR`eLc9%7=M5=@VHNi>nZCwI>ZPx#V6itqac5`AEPjQ+GGXb)oyP>|VDj^qI*uq&)`J^{61KJhKd z+#>bE1|M8Gqm+xgM#2y1Z%D#Gi~OC7jcdLDu}ipMaNl#?NzzTTSP(c znl}$|@;XA&t7q7!uo-7TZT`t33_$E+1K@LzG~%7=0O3%rSlVL?uvY_O7RV8zZ_(V8 zTdVo6XKx$E_Ii5s|37ErMt8-<0WIeg$iVw*($2fg$3KFw%u7=1nI~3J+wyiI1!y_D zNfvbXV=Pst?`N_}^gYxJUWR8Zw6=D9-z1;b;&FCf2r|!wTdh2jpT@-fgunOe3xS%1w1FqEP$;HNX zKLq`UyAvWc4sEmTjindela1_a@6I5oR91Zt&l)q4Nj8!-h?*U6^Bb*fN5thXYc6$* zqBD|p^@ueuzB>iGu6uj$G=;EMLF>54m4SPZTKbn9&} zfj*!5)&-7!g#$PqQ?0r2@I8ej#H!F-n5#Hq*4N9u&3!F<*&(C`lajE!ic=ck0JeO7 zi|f|8Oe}fzFg#PRMWlP=QKRt+`uujHgJ3sJU)qS3x1Ar9Ra`KZZd%x-^^H`r+)PY4 ztPvc4@Ns!X`J(ghVSQ)VrQEAB8!-$ zSmp49HN44z<&I3;F%MVBRCwiU7;0t9j?slqiW@MjK|xZ=yz+NCDr_lliT$PU%QiG9 zf{_9)vE~TZ(5R$ugsSz4Dfr!Rm&$`gJm())MNpE`dm@2jdFup8FvVm^#2Mpxcz|y^ zLg{`IdFkkvqo)bl&DGd_4R=f7MslR@61q!Ckz97v)pXQPK9r&jksY@v*>g2+kzh+j z=IbTA4b#$vF&omb8X{Gn9uzoynQc=TnAQ6H>!i92Ylo`!_~~Ge)l5ONX>KJDYG7i)4U|>_<3Y)_4;}Vn3W#isZzniEDS>_)Dx)UMh2%Q>6K|!C z!cEr$#5+cmv;(0>5L3_bPrsWqR(npW3zn_wI$c7G-;1BX6`o4VSKh3Rhgo}0shSZkM0%@4g$h?|X`)oA&##8p%^VXA#=#gB6}Ot#1MrYP zuB6E4V|A4q1Gyx@2c7k-Re&o~%QO)`{lyc40m1u|c7EP~=WP4xF9)m-mGV$&fAA)J zAZxb-iiRt96?7PPr0iT#Sn@036|EV62$4w`^(?qgNWx{ z_>BbLX6sYWK7OoU>J|S48pFtgLsln`F;RZ;(+yML+pVhvy>RlZ84NY&Cp|@=C6i-7 z+#U-67pLzw#K>l!De@JO5QW_ECW@O!j> za|2_~c+USe|17C?$!W`UtF!knX)~5lj-MXD`nI({qcrSv8w4;#;~LI#hM2&Y)L7he zKc`A#)*n;-Per+`7=X~N&yn8{-mi5Pc1TfBp^bSS13tw z+#ep!^_!Aa2`SvfDlur+_1|3>61znoUwEtX2sYO6i;`4Zc4RBplhox1O5q^Nfvg`N(0srHvAB;P0Zo$X<{FZ16` z;PjWp4_26wC!3ay1!vKGnaa;>2iiAlm|~eiI^2+i)cEN=>e818SF*)oBu|NoS(#f~ zq+|$uv*Iz1|4DUFd8zD)e8k;b?E>f^VVlA2%T_pE58g~GqJOm-K7hWOAr`+UrKBz@ za7b}?(W{4x{fRVn6U9!sD!a&iP|k2ZEhBM<%!YrSo4T% zQZj-Dt-hnnHX$w8InrlUtQKP`ayL|o3dq@}S)FetWAe$lAlWUa$8)aB;LLlK4q=<6 z>l(afeA86a7nxmd?i&u|KU>KL8;O1gd9Wku`L5DVrOv_#AW+FJ4>008rxW%s;Z2!W z+Riy21?V>ml~F=H*K4&6!Wh^6+rJ}MQ{nydUUSsA9xsc|1{6`E#Xgk*T6^am@_0wK zD8G$6Xe&<+qk;8fU)?K?N#!)D#MKTiIgzK;)ELQD7x(G@1V*NlQ%RUE_0~KGKHdA^yIvo)S@Ly1kolTT$wB zJ~8pmDPK(#O@^Xt$f~^1LZp>C$<`Z?;?(}Ds~BX9p>CtDne{uDA4tv_g}|UE1M$WQ zx6F6dQT(B%+pe0|(%gHd8eVUUa+}v;J)CpXKk2R{nmc!9G~o@@k|N8*a9Z|GCMtEm zUSP6GtoGCcSoP}H{4ka@E}~uM1CX2P2jgT46BVIYo%2|?>fbp{OEpz-fSVqM4VLuL zIBT7PcDP+{@KNH3J}a-uz^qAaLYtm!ydllpyy9IWVekJ=k27Us+T zhgC4`l*FElXOb@91CbmE@)li}*rAVN&_L!(HMK<7K)pcNaZm-_RB6!$q`iPZ`cuyL zP$+d^Lpf!}Wn~DQ+!=>bV!|i5$~a8fa7WU4B2E*$jIx07jut%{&Z^(km}+gcroF8M z(TJ%hwzsIl8`gW>LJ;hsZT;^Me1a$qaxIEGwGb=~&bnT8rPzZ`k0m?Bxs#1hnTI|Y zNU+j&1PTHTXL~DKPksWO^+r&z(Ljs17$oomBP?Ezq|8!{qVZcy`Y+gb4i5KPdV<+6 z;tKQC6D=w)*K3E z8;b**8+La?i3T~EYmck#`LbQWB%nA~O?Mg0Muwy}CB`JsdIw;t#y>}KBlq;LjITk5 zKt}tPKCeyd0(%Bg-{y}ZN>(xM#xx>W_ZzN2Q_D#lY&X4}ObHb#WIUizP`FMbLLgKX zzJ*rKdoLpE&gy6gbJ}3>q3`CGYn8Hp-Ln5DT!#u=L>3bIq;oJ|^XhD>Z2c%q zBT1~DT^L*I9__o}dyFbN)OKM)z$7#TC1@8b4L5Zni9o{dP0nW{MJSATmU z$3Wy@h}*>BeUmezfHss7T)XGKhSh_v&Fg~{bZ5ht40kQEn3Dm_gEut`;q_dFX3PSHm-3-Mk$gLP zi5I2kz90$Prw*kPv<0}5W-(SO3Xl6s?p7ra*TF~iwH2uG10`g(y7E?@kv?`{35{~< z^@gAait;hkSzTw$40HOgL}UJJsQF5YsQD8i2HIHETfewIS5I~z9M$gy)P1S~02+x! zD_V=r^3Astu)kb3$7NT3F1M<2(1qSwPhaoUvMwcsOd+W0=tc@AhT4Bk(vod8GxPmE z@Yl~LZ>!Ak!QBDs^DTIarr;fc2NS<7BWi<8XY|IOsVEdt$%6;i=9>Ecg&&0iLL5SN z1{>DHc>pP2a`CKPcveipAuuf2c!@v@GC0OsEVv-QBLHFu#$6+uLW`lL`Dtclzu%Bo z)@&bUn1rVp2rDfkh|^_%7DuL z=Vyl5E#8zs+lD=6Ml*%f01|brxVzD+1%-S4KApErS0N#FwvSX3d7jr?$97Z#^ zc>fX?6}|TA?~qtQ%L#90RDA=ksMyAB$F>8THB0eNJKJ;^LzD0g)r1Zsu!d96Me%`E z36IL}s`$1nRF6t^X_WXvb(pM=XxA`K<8cRbjC8=U$q_khed20AGu%*soR=IqO(;en ziJ85*yW&#LXU%={L!|KG2x2;edKlyJnwE*UBkkvJcq>NJV_jh6`)1dsa=CNU(L!R} zZUqT1$CX5~*ee5|iRdv*O4z1EnDM-6pIDeY98iats#Z8)xHG)R#E`J-g)J_}?wy(f z$r|D5N>5spXoQjlydCr8oMUK4GXuyTy`I2yDuZ<0ygAw%sO23V2TlbWGZFf=+N%lP zV!V}rx}DQE_{T5hSFVxD^}9S7GPOhm>uOckn3DGcG3P4FaFer+b0@<#`)f*WZ2Iwj zsd(@NwTldj1hB|}XF;pcXh=2vS{i%emS@)!|7Y>-pm4C^}1JC^! z{+p7tvn)`KQ}4EjgWy7ci)3p29UNJCLg$eY)p5R@>{1~(KVNGD89oe-?%hx(8=qI@ zl(&_`$MlmaZkmgs^iXexi-iJYop*##Khjgh>7Ot`^0dvJw-s`a9%(A&2jVo~=%c9i z$1*`XkQZ%8=@6^Q7|i`JqdbQ%p8hnbluv0dUv~@weW|+B_E=^rzUx(`eZf3&zqcIk zD27ElL)n%Qa&k3RW0pd$C>elI`+n$9WfwT6i{?TO@2+^!q6io5mf!RfWoxvlXr~Oh z{n6>YvcTcpT{7w$P|Qeu;q_Dp>f7?O`u1Zg?79ev>PH9^9)i-W=cqx6 zY4zT$S1Y)aw52aX~xWe{kXJI7Q&kfngXPcZ+8(^NwtHz zM0Ai3Y3WBV@p$AKGlVX9w05Z^!AKMt8ew7%IgaDBj=KLFHZ|?EiqUOJdoyCnpW}jr z;U*JAvrYPqM&vUjv(vI4F%)k3Tr7MD0-hjuWOVvsEngH~=4$VB4E)RqiklE z!ev__gT_^v0jTyezOLv&QC+2#Zn!Hn9Y%x0a8S;fjq#L#W-Wd#3A8Y<*OWmiTP<0e z%UPq$yYn+QMdb;QGyum-FyF_0sbOm&vS_e>Wu&7mhmY*3g(`T|J~SSQGB~2Lz|S5% z{dHL@x$#_1hEv^citY<{DPgJQMwX&xP-^ECX-DwtH;d8jBD0ZsTfSE}nM?U~Y@-36 zLZC83Uz92C-z`C3@_qVRtYV}XW_UxbIhANY7{RgLPNs-R<8~+*<+u(FTfLpwW_2|; z?R%)~6kSQ*F#L@vJ!#_zG6{7`OF~uT!>CEEY9Y91ap^^ee6sBK zMG|4Pls^I`CK$|fOwirUvl6RvpEZJPiTacv`x@5q0w(89p1uK;g@U;1EjqDy)wJzQcYs0s7ts+{)g~;ES0DEV37lI7 z69f`T2s63GCVFvW|9%}s$dFLhNqq@;CiSvw;ZWW2?nrGTE@*y5F&6N)x5+SMAaWB_ z47=EkRGW0$>RA_Sw%7M@E!CJ(R;edCqb(N!rn35=+HD~o=DrJzEB-`$rQ<<>FQNLdOU^XGSPwL|Rsrw@;i%Wpk113--8=u~It(IhQBQ212QUeB* z2vX%K{6^S6?oDs%6$NbcFR!{Dgo4{>aP$#}z>s8w=$U6YwJMZqqfM>>eHr?ojE00- zg{4Cv+SK#_FJ>jUN*hanMtu-0XNV)VcHbn)%786ajLgkpSXlmL7p_*;G3%*qrnepr z4tsH}nv{da6?Eb}N59FSIZI2}U*sG*i?$Bv#`lN;eyI-L3UJSY@jzCxN^Cz^gq>kO z2<$%M9hnWp{$?G|OFI0H(@w(O(s|Fq&f&N5lAgO{r!vjE~vEp2! zoa{-6uh~GsG941j)ef`~qMBu8doF+GLcNTT%;844(iXS)dZ9J{xyOXx`FST;I;@g3@@mv(%mp^N)s@>(y12g9unp2vCRs)ZRZq9}G=CaUN?u|%dWP`c| zPl{$Kk;vCh-+rZ9${3gCft4s{k+Le^O! z)j^AvVO$dut9?#=>l(U=gyW`m+{)3rl{IOTAB-mVuSN`3i9sev&9{I*9FyHeDvrTy zjy_?K)mV|6g+G0COM>TXGZ)y%@vc>G6p-Md-6wXv+iLJ*V!z{(G6XBY`{tpOI$MP44i*jn_UCgl=*9(@UbJg`3)A5zA#Z&SLIAE zo(DV@z(t2PJRY0W_%z=^G@%dwz_peNgT(h)d7(?Yy;9WFwd-||AJPgoVK^oYIlwjZ z6hndgZBDA0l{YqFO&Ui01^58&X3Ar+#_tekK2NT~D2n^_%H}J7YPiS_mdMM;wr1<+ zj%d+@*j!B5xhmTwI`0>)q1?0U7?lKjlNK;grt`t3nt3&$B1F2(7D{*zMBAjqGWiqr zwnn zR~)48ih3fydsM?)IIgN?NWO}20(q2!OQO|VNRy+-4V^^I_RF0eYm%=5dJm`q@(0sQ z5ctHZIxMzNh!?eZK#bV=gl3Rl#fpvg&jt-^p>j3cWs&0R@L~0*@xPjOkl!#p|HXs3 zj)!HJe29K`XcUQ?MgFkx%Em&GElYvr99raz4BwC>%a-&Z(YLNewa%SE+0$Gr06}bv zoC7bic7Vb7!R1|YZMK8{-@)a#MM-_9* zs4%6-4zTKT!N(RKdm*&TeLhw4o;KgA3COcqFW9fUWUbyr*k(~f>+$oip{47gXkfVL z^)A{PXOq5S?uuwC9n%YBf}^rMA=DQAfKE#3{a-pOWdit^sMNAdu+7pOjj5l(1CLjE&g z;HGGR^QeCiFy5_*>!=0I&bazZ5e?08_aNCl=fLO^DhUW1oY566yQT0!7bxwA0*WD= z!)$WA&2!_;QG1$l5YHbxah`r7Q5z2oCoSfgQQ*wNWH@<9xm!Qi*VsvvaTnq7OY9KR z*BCcWu$MG&oTd)P1AKfuT^pB|x#Yz;b3eA9<{ZUo_iHAXfc~1jNq5T0+kFi*&C z0(+~rG5Iwnz9<4O2Cq>j&kAYB-iqviL$CFue`A*kdyUwIIJ+~Lf4$ITRgQKvVJnL) zA~_E=xCw8tXHV83gxCEQ*^46jwcQ!{(jub7(pNjJw{5sMJan{~Y_MppNLI6;8jnJ~ zpimm8!xzGJ;83A6-w6w1bosuquZQ@wk9z}TyH1mHX_qKDM2*B*+q7fo-;v<_f4K?u zq$BE@>n|e>B(i(ADFbomvee$lsL;RiUk@qzxh=A*K=WHV`I z#;pHZE-&IYq}IS?#8q-nYFjF-HYmX40?CIkS-kRd{a*%g`+!kl! zOv9Pl8sbm4C{mpE5XM<8`2p;jdL0Z>?>IoIm|@zogc7rL8wVg`k*ZvtrIKM*N^d2qw3R_|HR;kzEf z^gdYwIYY#9F#N4DSRp;R!gz;x#=&=DYUK?fR(e^j_a5k}*(rGS6VA)>hkhnaSE+Be zNzIgHk;o}Cr|?QWHKT+SxDeT-yhT!jt#NcT&!zI7hN^X8c!7H@JZOP-+ry39GsQH7 z{-=e$w3X=9pn!R8Kzj|^$3_J*g0r4e9iNfQ>?PHiOkC|65+BDRN{TR?JRg?im0#xdQR z#M%2{@1e?Zp|XYSvIMXTFla?{`Y-mW+AC%>IvUIeMuE+ z*a}9O$8Gm(R`DFS@aX~Bt}CDT9-JZf!d8=8s3~(}5|ypC>S7)XQ$O#SY_%~LSOeML z>*i(K`5%-HQ2M8nRxjYCgEDQvuFLSD6!F}tEZr!t=6Jd54;$CW*_m&R>M~DiCY|&s z_%fU;-;v@%aw5QHZ@|0FBMYq>uHFtayybh8br;TRvYb~A66Vzeg}=0&nCJ_^Insps zgW^AqRQhE4MHLAQ3o&Hn^E5rv)wq0ac&r-$1i!1CQw$NPfcH%PWPPCo6YFX8dUfjd zLPch9l1nU=t)RY+;B_#ujzZ2M27GVTKYzCnE(AEUePm{d)^!|ekV=~6 z(cjoP!5fxOq^q|<&)SGx{|5NzTY!Qk5rt}N@0_6?W*Tz2Gh-y?{DEuh4_I=SZ zIJEleQP^Q#FvTL?>3uX0%5C%8SZO0le$&?Vb++DFtQlY=Mc71xFJ`8<)2(r3V?03=3P4wDy1%EyGx{2 z`fI#qdsGE!C|469eop9DS*lUWk)88n=!z8cMm=TJk*p@6&L6pIkN#{2i5H6fOmft7 z(l&2SEHERFDXjZauWCykD3~xAdNQm@uQ74R-sFN7?Mo64YoSYhCgy$R3=UZizIeIa zocsRJ=|P{q2+f~knJ*C$8*1rnSM6ysX|5#94zhxWdISP60F4W$nk7!1M(5+E>N0J* ztG$CVJ$x>;?C1}f~nL{^6_O}l~`;l5%fZs1^%sJVQO>i zmA4zE%l)9}WbgWjzKp?zR)3@@u*77L=tdVE z7WB3{G#@*|-;X>H@=@ZO9ny5MlBKbz`MNlf9nx(##{GbtU6SqRZ^Dz<%YuV!%d2*` z(_HCYW!-d+X>Z3(Irlr`>h``w)talSMYFM?lMYmBf?Jy4{l%*=+e*g(>hC%fo!IiB}=^3w+bV$Ep6jzRzobPUZTl% z$bI*0V4G-Lfi0oVD$EFd{4P7J?t8WW&X###`sbx;WJg`GbH7aa-{G|N|2T;VsBB0d z%M%pQ6SDP;_g4OD#c2nPO9O1sO#5Yx=mO?{#*9?yS`rD|-BBo;kVbWOXfa>6sqdYr zzC6=2hhiT~G5I8AnsxHEo^j>b6bsC8=&;s0c7KlKT+IMRAh9@0aP)7Dtt1N#y*Sgxs;C=Eg?SeRGEhlXT+93WATN{i}oXBvbdOYDUnqg{uHSI*4D^X>Rfs^V|wROj_DlKT;*5ZdjffEM6B9CCVhTyZzb~qtBoYaR(v|1qzsrreHd1qGoHI z>nA&eA(vK>>kICeWotVIXuH=bczv`EAiwyel{zdCL z&cZFf_&b~xQnjz`VH7>%8UK>YFSQ({7*{ek@7ku9FaD1? zAYeHkhhuQ2W-tKA?YU?Bs{9?(ZODBh7Tj$b2xW1NC()&` zcei6NFIbXly2;JcnvE7~48XJxjl%ePhM*&$_1DL5J{>&~IPQW|+}sP<7^@HuzV$6C z=Z1<6!i9D4(vY6+a9Co7%4Z(oc|vl5o${!_thpcw&G{A6VSke0*9==sTv~}I;qeYH z=5-PXjtGJ zH~E9`C&|b()B%P!`R%lY6?I$heI8jpNlT^S$PrwW>a}drJzVW`L~@$^Gv)@0Yl&cU zm%lCDv@w)MwL9v(@Av?IK)2ILu4Ar0RdWD7GX_+Yi{t|r17>d|spQf>w?;dyW6ro< z-&jJ6K)B5eLPb|aa5=xwH~kD+CHdy$k8-q0M#A|HsX{lmLM&_SiVr6}aU=p?MnzJA zHv|a6W?S|6H8XpoI+{keJTbj-l=EU8;bjA~s$J>(=$bCFZR97@n(jf`;=2aasUU*S z+iQx`timIPL5HhXNt-)q1-rq&f8FaR&JYRy2`6-kC)!N@vOif7KCjR5EN_jF*Aiz8 zoGI9A`4_k0W+Pj9z9r91jODx=KUU{oHc)@dh?7zjPi#!NeW+>O&(QO1q{b%Erq;}@K8MAn{Fev3FCl)LBH10>(2IE)^nj|= zt@LJ_wOVLVESs9tIZ_Jmu;J%;#AMMdVO^wflf#P9zPSM5WrOlRW=1YR(wN81JA|T< zd~yedF48`Zy=yPW9bIhH%N4QaV0~ZQep`W0uNCgLohx^qz$@O4UtF0iyd~2UWjf~Y zOJf={k%?&q)&>NVQanx^KBovFR{u3WYOs5vy52Xia`C0-A0a`oFDG$VjWqbs2&%u%G}l*Q8C0;+0BSE4e8w>DQJlM(Y>!u^$;|S`!p} zsiTjtsym9YLtpRbz_S4nt4q*%=dmtO6@#bQSu>US)_ZCV^WBhx&dF4`gdEA-hG6>BeZNGkC$eN*`#HnrQ3;$yfWMxe$_hBr$>oG$9LfSoB zEsV~-i1y+Gtxhsk@R$_8ZnL?LvOzah<@(bNsh|3ZzJe1tq0nYT4qq&;ChzZF1lP%4 z(!JiQjNkRS1y&ZuLi6{<3USytw1Zv8vgZ*~SPsr=`YqBv ze=_W6{mtImWMs9H4DNE;dW^e`H3bd8H!T84x%?FAKp*_~@mHd?x8`YIDcE9UMucVv zzLdfIP|1@Yn4=CoJ`J1k_tX)i7i5ig-CNPyKE%2Vc2-+YO}apvXvbGu{hh+eHoFrF zZ)lgBKs+f?T!-q`u+pOxe4Dh3@*OK#;Z+g%KvJwao{CkIFV;pp?tQQdhvV%uwrY@_ zGwKI7NIg_*QEI)OY3V@wzgBVJoGmUu@g%*tXL#JMK6g+qP}JKIh!??z`uW@&3HA|LmG` zt-0o^s$I1ML5;ydKqyF*R2hWL987=`4)(4LER4*&0CiUfM=N6nX;))gD^mb7^FNT8 z1&)G3)EQ{(YUN-rX6y>&1!w}z0E(ur001k1g`1ayo0o+fz{11xAAuV3ZZ5_a|6@3VI?Em2ZB@D1~0T=_EffiOSu0ZF1Dz47PW)`7n*7VPhhzE=$I|xZ4gePB|H94O9RHhh2Rgg_vkIX8 zU-oJK6*M+;u($OBm;uee z))t`hA6YH{6`%{y+5I2-|FgOOX;8w=)>gsT?w`f~CH!B@@&5`lwzIPJ`hN!g&j?N6 zf3>Fqv~aUEcK)CAf5{5lTi5~t3@mK_1zNdCSa|}?l&oA$Edl1nwl2W`!qx4~fX=p7 z_CO^E7pwo+3jb1=ng0i;W@%+=V-Iw30dV{m1++K&pRWI{+<$sz`ak#Df0E+=rp3(4 z-U6WNYHV+2>}>Xb1OG`Y8C%)As(CpA0nGnf>_5jW|9dQN?CNag3D9N!kG207`0x4e zH~s(NMcv-Y$qgti24LglVCVVY5+WiFo<0mLoSXm#)_;w#urhN1xOtfU{*P=^H)m&{ zz3YGOzJG20_t@O(-)sVboAr+2tAR|MhNgOl!ix5<8R;FO&j;WaC%pLC4I%Gh{Ro(rT`5Y%G(RSb*e_I3Zc3od4_ zp+-&V1Ckrj>1Q*DEYY0NkbO(a+rb8%C)`n~fu>fuon8{_1gdLIKAlRz^JI4Gya>F{ zQr|Jfln<;ln$#E&Lj9sV3C%J05b>e+caE7gapwHtZjR5}-bo+U5AW)RTOx`B8RP;jQj_4JCe^$$4a6sz44e-FfPYxQZMdzOP@#?1im z_{eN4#{=A`XAgJ0v)}3!W08wz$su)%-g3X)AMi8a-#Jg#(LtWE=@S^n^9|uU_<#4K z^|H8+2QqB+s5?lYfDsovB1&4*?Uh*{4QqYErFP+`(bRx{DR>xuzU4<0xqc?dA-43? zQp9K7q2Fn))9p~|rpZ_m56*=ds%m^hXxfGPHM)MS{?%3WLHh+xe31cM$g!) zTMHdnZP@wyd41T+isjf_6b}8f&%6^SwW0Wig0~Ag+l@aS47qly4Q`^8UU3FBShu*E zbt=cd-?TY6Ha%NYD@JOI1SIUx{v3p1Y9h@y^$yoL40U372nQR@0Pl1Dpt4CXPF)$Q zfHDCFMnpCF4dqPMK^*<24#JPsE>MDjvwviU4Nb2avKx_Et2H0BaMpp0U6()oKXQKBACGaD8YS4pwzcCCf-Jvbn^!zRISnme7N-o+(9|0WkQQ^P>d z4}IzM+S#5&-^iYeT!G`CQLbm|p#!F)4$na`(G>;Pg0L$>B7J&3z*( zKcRFzW3nIiW2d6KQtq;*uW{LcmMSis&0&r`Bsy_RLlPq2)KvysJz&%k{OVhdTI666KU-SQvQtP%806x3ux#mN&S?fMaQ zF6;xJA1a3=D=-}I&rHMD4m6T|m}waua>P}O^NIqabmmw!>)~%2#s(rJHr2SH{7XAH zb@9Yui?Uz2@B64H84!EK2#6w4Iohh{Rc{*Fv&Wb( z&(iPlG$HoIC)!3B2&hdxKi>W}e}Y!o z%yEdJf5`Z9!+G-wy^nE_J)WMPIo5^&BC8ZaSNr+Vb($J4as{)tBdv>Xk6|mFtu4!C zixejF%#iwp{H-o@F8Lv#XNHy(T8cD2Y;~6h2X@b8K~-yr zmn^hGzWLL=6njnVY%&sHI!Z2phHW($n13TnL^dyqw*_5{i1;gErzySL!~s zMdu0_qf|{FRPA?UU!}s$R5M|e>K0V8lXn`$Mo=WKWrAIPRR1g?uBWX|1GQ30@z|jQ zJwbRgsB1ryN(L%&1$p7NOTqG_>iQhyVyu_Q!CK4=%+5Y5Q$4%vi_!(omWV>^qys1N zpplJ(!K7Qsj8j%sPz15PvMqOhig|_C78*>q1wK1@g{!(@{X0v;r5dc2qYT+<{w7~Zl%Z~2|xS`q4_am*fjI|=dA9}&by z8TFf-8Ez{ie?{y!FPDJ8ASaaLMM6^elCy-FYU*Bo`%g0-^4eAuDMk?*A~e zWZbXV!@TH}qF_C}*{%%B29-oD^vq3fuY!RsWQ%7wIE>Eu;p}7o?j{A*KhBvkL;P9x zEn7$BUFx``BEJojQ9!TsbJ$YmK<`o%HaR#ZD0%V*7N6nMF9?I2Q!JtV2)asT+Db>* z%aOn6EEir|)6qGJ`W5XniJB9hBabFJQoIko;hpv`UiSxqCOm}fehOLw$Lg+M? z!^EViYoN>zZg{D(7D%Z2M|$P$vW1+Gv7(ADPGhcVZXpg;lm=4`BZttIHII(*10D+NV*DNqP%FsJQk|yeOR{)EfnqI&#!tdt z?3{Ca9G~jzyzzcWnW?=hEYZD z6v|L2(?lK`Mu1T4IOps3$a8=v5WN#p!Bjg7^|o2@WA;kP@AESnh>lr& z3;Fl0BCmyW%f>4VxdhF1F!LwI3G>$oH7H2SWu<%wAk_4jBar$rV@3LK0U5Q)7 z{l1M!E48d!*s*%9mtv`G0gqop881-h=dd0Q4>S%999&SW)Y!^}GfHxtdLw=&y7m4|NH} z0ej3dWZ}-k=R5$+ke@~GW)0Qx3lF_kbwSsOmd)|*C{XziH#+Jh`x;8x@kA_r9O%#Q z2yqj_P?b-i%c}J}eZ{C%I^~y3Y{Z^Q)Qee}0lH)TskNa!TM`EDoRmomG@Fdcw>EQ- z&*giE798{pzbfvI`gD1wmtBk&nhHN0e|>vT#&|^oPJ8_l_Q2*Zpj-oX8HzV7o;o_2p1FRw+#KQYc??m#A(Y z#z2-&_5bQ5jz0)VY%#IA#QMm`j z*>*o|zBB5UR@X97H!iK$PpYb5^qt6;Fe)a5b?BsN7Ttn+fvw~SjX7(ue|f=Q^tPXz z$rxATLQsO__rS}ZE8_)p$Igpv7;^*BF#mp6Al3#Zfno#3no8c=msp2Ok%c}XZo_7t zl`S{8*S34G$d+0qGuw!!7=FNZ34}!uY(2P~tfa>`YfgVW$#B~ua3f1#*Dbpnr74h}fzN=2m>urB7 zDmEPj-qk!s$3uUTIM;mU-kdDJt@9uyRDhe)Tufk-XSl9v25L(JVexi`S=>St)LAIXYTh{h6k zcmVxzO8;y-XSXE&qVd|30KSNS@&14l-ekV|$tR&|zt`g!FGEE|RbW^EI@;Xn0Zy%$ zQ2Ahu3063gLALJ7!PGZtqbfqv-c7lS_LoY=6VPkoKNjK%&n^sKvx?)j&Cin@R z$jm&~5xx*-`o6Bd>tp@88QYkDYI!8Y`HI@lTz+gebF z>BTCDtUN1(Hu~rl-;B%sxm>|DaPT6uyDWKuKaUrTO`;N%fI7ra5Wui?@n%trLN}?4 zrb_ql!yaE*mntzPYJfrhA&2+fp3fIKj3BtcCO4p`R| z;rF`z-W3i1KyDIESrRI>8-Rl#|5uJ;t=dr5@S-Dbn0y6X+uet*d1ENZltzi=8~XdW zjc<;I`ibA9|4?HPcc3cmXCa?Yi#DzcPl#H=-5-5-Y|V&>sYV0PX?}ljd?RnN^s?Y} zS(yVEaz7As>uyFN5{JJpQYU!OH~QnFOivN&kuLr49!C50R34r) zt3si!q4r6r7A%;A7TyCH~SJh_q!*bkERNjq^f?e=Rzx^-KHyI z9pqjyMNrV;7FkudZh~Y=xAeRj64aawZ4cW5iZ_B7J+_5py|JQkIy69eU2?L98NTw@zC`>;%ZUrb*3% zKK8{F-~3?Kw=AK|{H{jpb-3BGJc`k@F&F4>62+UJ?jivh3`oDPHe>G4OmNe+8tXkc z`od4kHbt9Z!+tL~DO6-DQrQ@zPg!t}R65 znU=7ulwUw#JtQC3MJKUFZ%X$d(9Ju)`t)9vA{_k1Oa{q_LmmV%jxbe!=k=D?fD0;L z+`_GzEfe7UM&d*Q#2x2{w~;R0m`KNoq+GxzHsQ<$J95b%l91y(%IIK&6lRkZ6OJ?t z_Ih;6DK^@XQYh;Bn&W_G$$qWB}2j1R{n`!3mOz6rGio_r&%1TTL6!h`R1?e)7APMZo z6X;#LUO*2B8!}uuk0=u~dmYE}BBoUZU~shKs6^u|OPMO$5Lm|S9`Z2TQzB0Q z1hRE*`fT|j-nLXPQD7|?+%|jJw0JBn`$-K_jI<#WioI8xjE5p9Oe#@C$~ab3@l0T1 z(S=`?Gr?cu*s^eK73kyaS41btKYJQLZ?XrKt$jbl)mY(@ac&``-g8j~wRs@n)KL}E z^W|10d7mgmQTHDajdSyvGo6oq;o{S*tN-1+i|NSeQs56V6#u7^+8p1i3$d$foHpBO)3Sa9{-y(6gqcAFQkJ(m~ z{~fc6b%-BtryE3{H{0*o+%YTnCzEu_2}L?&k6Ph0vyWf+WrRBe2cfLlODf2Ea}>*! z2^7;Gf^Tc=C%dac`+kqq!gWk$$wHY2Fmpfb+CmJIrYzzC?8>I#%N2A15*l6D^rREy z5HG=}c(a#?xtzn{7)y#wNd zCg@3DK=BdU6y$u9eg%#U37qz+Akus5k9m83VNM-*rEt;%Nx(U`R9-{zV_{`?s|pl& zmY?hpN2voMPGS|;|IiepM$*Kfn-WF0%c2d?)2$l#4?&-DoX1~1bC1}}GCCSZ! zPz=f2MI<%9sfa^`j?V0|R7um;mwfflyb{X>Eeor*?45S~C9%bq?)ql;)hwq104$Lp zkXjb^B$Hs5cf#D^+#%Eyk?_^Qc7o_brAFbe0xb`=&HQcVo<~gZc_X) z37cOGM?~jUdSv&1c4f~NiCl3_565@}ViK%34n)Zn4VP-X8_ceHR82<%lRNWK36|`A{9;xviiH9;#b*dLti-B&e`j|s8qsaUQGiKq zdUHK+=cW8%r!%mf%={&9qOF_Qpk}gO18CKK{0ymB36~o?HUy2Su2}wRUq6g6-++S> z(yhqjDcdLp!y=As6)qR?uB2Sxo_=gOFlElNovZ$;pejY1VWGYtX627gO3IRPFdfPG zf_M4SJ|Ay5FqUHwD3}VG)*Fqs3ucqQ;~(=}t@L7^I(oE#3h?Fjn3QOBp2Z5(#T1nR z&6E5pm3~d3V(rG{>Q~%g!iNrg9&5Vx54D1-p7RLa!;=Zsn1qW2b-nHxHn4BBsFcZr zZ|!dVGng6cM)rMCdPzEI6y34#qKO#z9n-4&H>f_9vzD|V$zT{T-R|c2i#HCp`cA7Z z8CCEDrV9Gz+RhC_XvMY3lsHv60!Qby%GQN= z@N67*VJLt%is(LnbkUaPk}m92vy$Z$drmnT292V!tkJTOmOG*t0Xu$ zeuKP+=&F0da?y7<55)Oo%52f6vm?78H-~NwOR&9 z$3xooa=ai~!YGA1VWxJwJ9J=gZ#YOQ%vZB)3@pHv+xXwbSxswRX~R9X0xiB(u5?UK zJAxUbQ8zl@T=nWi1)f~qXO2eZ;&WMz_8OOUBZGoCO|H)%rAi+9&rn#njDvUSI5Prh z-?sre_oUhW5smORY>Fqw`shu=LUX!$!L+1~sDx<>a^Il$b_{nQ4>-;=+&LJ*L+&E< znDM>jkoy~m5z8iAPv-XaQG+%i)LB_h;o)EIZXT9#VdRnuDs-h^f+nQ3z$~;dT^fC% zpMC`p^k6UnZ}og4bd}8=qXW4xMjGT`_8f*sWYi1WG5T4i`=~!RtqMhi8AR_8$yO64 zT9BTs%B}MUl4Q)@S37w=%RzM)TkP1uF!7HD$q|<%(SJ^nI{0^HJM-}g*zi%w7tE6D ze~I(0o*7PZUd{I91;PW)0rrB}!OI916%3Im;so^Dkc>~@C4@@95#KONPc4RPeUx-j zIp4Z6GWsC&P(rX49utk9hGoDcA;7a2MI{|}07U^YC3n&&X*Q!Y;B=&>$6K`|PR_^^;ZU?P z`j$-WvS_aYwcsv2ezvP{kK-r$RNO1ou}JmQNAMFZ;_|u>1xCPHj*bv=iZ1*xn`b0U+M98kCXhK`p(C=G0YkN09Va2GRfh zc^uRi_)?7_hC?I+KMF0Z3hwxk;qQM*F^SKx->s**GyQ3Cr)a3VXU_1(>Gwoa)-QAvCXujG}$_^Y|-*06e1AtXoO|1)4ae$9VV#T?`(Hi&c(P8 zZazeKm++kSj+QHi{|)(MTu8PytDyUHJ|rJ;k5R0~V}iyUoCetipR6pk*-$qbF4m6U zB1FQ3@(m8~4L36OByfh3g}sKjZGf(^$Iqn_;eNhmUSC?x)mHV3hNu>_YTH*`N3qR= zw6Bz^r5qI}jygpw<(JlDj9sqnpLO6^O-cMINv)AL4G`TiJw-Z!D(X=r6zhT}lnT z(+x*CuWIaS$W^OYW*{UNO_eZ|(-)Xuj_S}P%9kLIx4jJ?-nCB1F|4HUAAW{%vi!Pt zn3eI{ljluX3L>}DUD9XSX!A0p&$pYuk(p<%<}!8oy=F*d#pjMbZelra+k^f@J>IRN zd1oe@eTr}OOb-5v(bEQ<$ut4vOZ)O6JDVVu7@+6{6Y)$biYtn9m7=8xdkm2KODp{$ z$>-8IA$h)oaU7q!V!0`2nj~lrhbW{5YI zu7rKB*sdf36E5FmP$XoFyBc+5poWd2zX|(gvN=U6v-aJNhntxVp}i&{{{uyu&g2gR zjG<`Idtyua9ZuT^QJ?U?+i!U8o&GOXc*F0~@x{w)SUMfvH^`Yhd+l;$Fm#D)KoIH5 z=u zplPIqz!&2;PkEU(TWA9L-9zL7MK?ehjoERn3wD{aq0V$$E5%OMX#Up$_0oyAA4inp zZAr7f;YTtU5_^ePCUV{A*&)y2^JEmC1zn)_P;2n!$qas z=|E!+JU zg0cpX=mVbM-tkFh83dHk>8wSi4;ZJLp&GNZdP5_xK#9fot&*1oe?ea`#`N~l*62Y? zTcz3GKP1oDn)~ufMKaEo{GIc0Gevncgl=%NSfF9DO1|h1f103CTLLS~ozg0%Wia9G z0BZMYyZ?cAtif?XOJ&@f0`_L*?Y>W0*S=h9=*Oi`iEsoeS{#L5vJ=KlT#Gw3GY372 z@QGN&mziHFDHPArhqMUcAcYg~CX+jQMI;Q3TeSi z2Zi@@d30!>{=_c9h($O!UD#kUi9l?BNmIMGXL2|a%QKBjR&N#0Y#L_2pZxb79n_r7 zY^RDvewzV#6qvW~i{(_ng;wmfTJn=7BAHOpvT+#|IoRo3E|{7X%?#s+aLJ=wN|DZ= zjfnO;7=QUBH`b-PG3|h27W2boQ~;=uEat8iF$nEjMadWP3V2ObbBEb?&sWi}b!P2N z2zWBc%z)#vPtSFG$^Ec8`nM37SN?DOd5<49c1+9y52-K|O9Spx8BQ;*v_pM2|<17GT-Obo?xSziWZwZRsa5c1UoRmK=I^>8j2Hduc>OQWd zGYX15v;x$q@Gn;yDXaOjIk}s6A6nVa;I89jXrlI#^hV{JgDeyrquTH%A)ih#Y$O7y*dg4r)NN+u_#R)E&8dtyL{ofU!nT|qL#m*m(Urr|lDB*%U@M*;F;v?8%87 zn9V5A$r?Xh?bVk23>b7p^txXXA?yESHBVKtlxp5BFGPamS6J#0cxpcWe0rjdaXQ;= zPm%ZB&Pd-p`e_n-=V<3$)6=+6(x!ofvhci{5p41-0TrsL%YDl)5je0xA?Ll=t9u8M ziWugmaV1R8)=Uj}7OLTl4oRwkg1j|P+Uv9Nyi}v2IhxNbPzmM?e-VfgM1sGbI~LMY z*_{dbBajr*0xuIHB5i^}77simPt>r*`C)i(fqGP#*PO48bG^3X%5JeSz$h=5^c{Qn zGAxbBAcbN=jT)ebg*@6#Z`H8LsmkR{B|@(~2^rPvNbMu#k-2SP6`t|%jovGPGt5ti z1cIblHNSSCyLQ^yto^C3CB?IeV<=Uw5mAB5#A`Z74JCETN(c7aL|N>}*C_Djs?*mM z*V4tds_u{SU}fPS9z&K^f=UpDrYz5_{10+(^2|gOyQkeDMxg^$LF85#Z*3U(N8Q`> zT8=;|#{^KC)kmMy3H@U({WXP6CXor(VzJ0To!vZ+s zpZNEy9niaNrTyn{6SJPXeb{l222&lP#gLf=k^vSJO4`dsW~>GQJcVVK5qZ|~Ai>ZQ=?{58WUua~om$yz&DS>R$lAnd!5 zFP8qfZIjQdMPsG85>Mi%C-I=?%PT7Q-$%1LU+v}~>H&PdLF%M^zRB8gvg*)oyX%vM z&rtGQQGpKuA0RcYy59ff84b-sMzyI7;;~LmdVT7JS(JBjI@CaH#p}a3|1@dw=`0&z z^Mm}0RKT0Vw|>!spc}1MDU4VMUOG>`_J#J_xFxu2Tj7;U%My30uSrIbZy=SR) z|IBHZk~wHW_NP6p*)K|P?ulD=slFR-X-_0GG8MxwXCpM`McaJU~Mf;=*f1bm?i?U_*Qp`^i?ESyr>@C|Nj_1-&3{@kJLX>~`C} z1d;dzXNt^F)AQ|_ut;*M`$dbMSURusEu6{63n)Nfc6UeFk zQjB$Vf~zA>FM(VZ{F{g3ox}i_ccyK3{7m#HTu|B|{2ac$iDUeNrTi%LLIK(I6;j0t z<=227#8hrve%}}((o6Kn;%WoV%KAQIjaJYOmq(^a{AUhFCJcGvoQ?Py+Kw0e0S>INmosffif*#9-ykUdC}yT^mj&!tZko0{hPMkvvf!l|mnQnV5f9 zIQuO^hm-(nj zd|AR|rCfS){>rv+bsvxsq2h!Q;wL(9hY^_Pei7B+*-MLNn8WMQ+`G9`hg+N1DKg!a zKYQLl$}jg_TNkBlgUkiRLMYB(rZ0;Ui|56|UFB`u3v5B`b8WdRqE@U+SEPG5yn4{( zOp+p(AB?l8;vX-SooX!HDUR9Ha~R(rgTJwN2BI3Zk?x`Q&wG(XG!ajdS!1V9i2S#D zo!jGYOEvdyxUY$0D28K~`?yFQ{5qO!p9OZ{lRE4_d$aP8WxNx^*isq`03Lv3rJ`0s zNvC`6W1b;ydg$Gd@coR&6zeTHK{&B*2eu#TNagDw5^7cR6e60$=l26>P80fAUhcy} zzHW}Fy6=J^5uhzUSs~H}a{j#dw^^zN~8pIJachZ#jUHvVGiPw5#b4+_ADE#;W)$|5=b#OjP_BOR2*3}LI@!$S0Q{kA~4k95xHt-gpzbM-t6p3RlbDP_himT9Fs7NJVxI1 zeat*aW{G>R_r4adAZFl1#o;dJY$lB&(4bFdhTLGvED_fn^E_Bx6Q1822u6|-`l7Dr zw;b2zF@lUozQF13X8|jhf)3F|6I*-f%yLsr!}U1R@k5H%e*768lUo<8C-+xA^x@t$ zw6!;euvE?fCYQh2#iKH>19$%f4}I=NyPrm-YUWLmS3X!W8mcgnFP>pm_}Kk(;fMQ2 zF7MxOHr71HNOFrV zh)Yu8v!+B=Ee7Wna0VILd^c^-5yb`Hqe|Ss1*>7#mUi>(6 ze@}S5RS(Q*@Yk|{G5wG^USHF~l`=0c%AHrlE?I4R&hQ5DY%WX9j{>ieGPlxeR7}F6S?J>o10&LW1*s2XQ~|omydwn?Bz>$=ngM9Y%7-EoYkXLFXK#fWh>MdBc)y@rfw0 z8Ret1*uvGZ`QOJN+Up{VRV`jZXBEixmw%|)sKr#mFWVtSbsk?bn8{(}4GZGf52TtH zo9^XdGJA`Y!;x3moQ6H6nd^pC6AnuQVp{hn=8sY#4_M{2Llu?niB-6`F4)ch@tR@{ zn8^&GrPoCYSxPd zitn72Q_3*SvFlMOOXuis`5@P$7iEq=cvhATf_@)=U2H*jbx!8;>bfRU%l znQ(@`EDdHc=g&#u+?k^d1f>b1{P36%x?p;qJ_a$=CqTJWKJ;^81RGB51#cvLPU|%? zxl>$w_?I>tlXh;enW)8H{50sAKs;N6VtfcBLk`>>6b7(fTPI0S+=5E(x)ofw!%JYq zUq2=wtuwNfBXMQ?vLsw&bC{(NbG+P2(M-wK)7hzFY--1BwGOW-XO`r-@S7lrK7scV z4-wsq01|HxzmiVB+28qi352)_lcP8cz_=NtBh>Xf+5Z{$c@nUXyhirPVdg%^xYQ4I ztJhc_zb?+5ZTrSQ5IMOX9BC7G*_|R;5-FC1r@SzZn?&$K`VH@D&;gN%1KCL)QXQsI2E}R(}lD>fpl|!WW2% zi_LB~&w_dq7-AiKZsPS478$MeB~4BiD0du$QL}x2;b>x;>F%xe)IXk37S)?2v0Tq8`-vyVeqWi842N!HvvqFnXpmV@}Ee z51VgD-J~lr?+Wg1prnCmae`J82B~#F5{Zb0`MuZQoMw=^5KP;=*>AmgA=34v`4{Ls zi`G51(F$$kl~E6Q8B`F&9mWtG8C$SC=IZXfKQdD>ZGNYCbjAuUR`?9YkMB zE=GL+$t5wf@gbZwxMoh)tWQIGw3(Xn@$413xz?+i!QbY4vux{cNIfsI;-LAG!c`dpbl=pEd^%I?(&UGkxk}-kF>Juqt;7Q9^hGm_;5l z4DWU<4@6yUYD|ho;X>EcIR_YifBv@l?$F_oRroA8Ab?DLfhI16xme%eYUD*#bI1Ph zfV+Rfl=$L+TN_~WK=15JWQloY*!3}f73MgVAE8fo7@#aBNrABP8c;43Y!RD1)7yyPW)c8H0?h-j=H0WeQZS>i zou@548wlf>kvX8)ojg#BMc|;bgqJ35ZH5kWAnJ7xD66$RPa#Z{S2APhb$z3aeQFKf zSrp_W`7S5bMKR#WmzD|&*+`kJBlND2UWp9N@8)|7+yujoR`+)gw>)R+d?TCYeePPe z653_WhUh8WU5j-JLqfe;K{Yl**?V4x)U29YWZ9js3qz+Vj!SDuTC65_XrqdJ&4Zp} z%6=NqomJvoM?Nw&1IiT*$jcOpi=4Huda+t9XwhwO)bVgz$)zvoG3{@IzM*=sOmnWzFzM04f`?4TVxeYEG~B{>Se zla$A3XgR2Z-DvH^X6t+B<3CV3iL5WtA)ocpGHNY|A~>D~n5`9d32m1q=wRwUl@SmC z${=F>-;&pt4)-q24)~~%uXY7ZKjBiC51kg)=7?%DHs)eE>)wX0%s{ERX0BCA1b^tzb+^V88|?5kK_Pyt7vLOG=H z(dLrE^6)Noho=sUC=Pjg86oI2sxVy4&jvJ-op5lAu`bi_$S)89DjQC*k4_B^p zjG1h=cck}G?VSF976Ay3&kuoKAL?1=Cf5OmCIkv19x_Pj(Tn^Q61LmJ_C&Sz zrQ5qyWaqf(`CJ64z^kyLm8;>M!RS%VD@vm&^mDy-EG)B3)kD=i z!Tyi;*XWRG0R7WN05{g@GMr*K50NsfKZFbBlWKyEG`DOHRDO4(Z>S1h)s^cZvwD>8 z`m9BH%RFEFIeFdv9-V$}Nt#9E)GV&(9_;2k6LVM<^<68=p?Pv~LZNHRL;~HCH$9K` z#)=Hg%QwSx@3*1b-ZkjhyKy4+XZnjJZRpK04kxAdHUkV(#i~dkO1X(8H?oSJ3~SP4 zRgR>(+9ejj+#s8JU9!@^`>)^47yuVVM(LYWX4R&vQGgwi$Ynn zg4xnfP++GvUj!fd7hkmY9b>VR5LvLY&<-%ZUg>0TpCRm&zHjd8s_q7XgTD_Vq{hj_ zmAe#PzUHXDilAzQ|3pFyKP(DG$`VjRlE7A32vZ97W?u#$6E=IH7i7(b;&<-Gmm>iJl?~`^TRX zlfu>~b>%fb{A;s+q}2RiBcc-uF>=`WF$xB`7Cc|Eq@@-0Z`rV#`o==<>vvSEppky( zI!T`^#13U-+beB|%N3q=6#mlyW?ORQR}gd#(OsYj_XvO|Nui9H2MpYlnu+|?>Zz~_ z<(eVSx2sNdY=Rh;!qh3DPJE=wg~;z0GA!X7qyF0OimeK7Fsns&f!7xrKXhJjcdy|P z+4Bft9t*X*4V|b$69RN+(x}TzoWQZLoV`kyToAr?*JsJ<{c7svOlC`jQvUO@_0TGT zb}Ja>>)TA{c_yxN`)X)1$@oZAstR#VE+LBY;PP?uSEMMq=l0(vGGrcJgOfd~6!S;E zv&6ThKXa|7(rAGx;T`7Ejke>#0+)OB&+WY6k`SenzP>B$lxlt8H!I$2YyafjI(Ep@*u;YeG<%e`N5q zgErn^M*qzS;qwYLwaVmcE-uHcYdtS5B6C-1@H1lQBB93b`P;S)3}VbK&GvlSe*>ARO2Ehs=H!5zshBM1XaiMMXbs*ZHI5X(<S%Wx$J=X>nVokM^x%Wj&}zq>Z)xu!|o4M;=3^>vrI4wLcH1CO zp`_;s3mv8G^|m;W60re&?a|WsQpL$bnv@GEMCB`1jXY(kz>1{c9e^|b$YpR$q$OtP z&R~klTRdHR6oxd4>ooF5%V(3xPa0ZercSB2Gf5Ru2seJ$+==bn5i4BjXYV>D*dqNWv^36aiD7qlXj&L$|a^i zLZxxD4yoR1Aq$H>W#ZGv)K69v&#g0HaHfB-B%~uVO-1ea#}T23pQMd?qWI&L5T~4U zE&5e=3X&5)r8tjY zm*+ILYxIc}CTcdhcxg7rsaXIBofnSPWA>lAY{o*6H-<$H;saZ3>4(=jHvmqq_AI3^ z*u2XLFwL-Y!+vzw$ih^|LUU~A9`f{s(ew4sBjaq|n|G0ig#l%|MnbU^Jd-CT81H=- zY>u94rRO24Fw4+^!9M(u61aOxbkm=wstJR`4o()7%G);0g9Tlcs@$Q29#6HDG0*+P z4V0ck3bKML*We5S{0yAR-3fXcjAnu&E5x1KL0QzJ1R1U6* zM@afR`I`cHjMn@I#AfXs50<7fRbT6n0hPJgo8+iZ`C_|*35wDHAsY8- zUP-|_AE4UXom&4zoXVH>yhO)K!yDW?I(4>ny=^Q-U7aGy&x$bMB=6+y`*DB@?9t)| zCjrhXCSzGCr4yEWPKHm^)|6uPh2s|Q`mZnH~? zTv=&sieV^)H!{AWf?OIwL%?}tU%x!ahow8|Iq=5tL4&$5)P!HI!Sp(|b&3!vDhRAO zuoH2}I-}qu+3uq~77PaG5ph=ts91k9MH<+k*{@ewMh_QdU+)-j#oTrkev_4`j%X97+`;=|D>h#g5mhtAgbp2ld4?yt0E(gUbZ?hOK02~4t7RpJJWPgk0bp>N< zb>aa#cpNU~Rgq~x3GuGX0hKhJNY{YdEu!3vU_k;k<-^CcR48-C3Hc$WDN}X_S=bwK zg#h|Ru$)j&od1_REpbJ6J28~UmJ?4PmSF3X|pjQ_A;6(iVdfrsIt zQfwd=V-&k(&%$QV8@*O6dGHK55A+N|4tTIl~F4Ph+647?#u)QJE;|>SHWSx zPSUL^CD5*9DqI19Na;q9)u^Q6Xbx6)c1!GNN}^ij?VUv&BlTbg0$5)Q%tg_ z$RAE z6;K9FLtVwNxTQBTse0)gGkd?fjvj~7&T_O@e1vqM?>5adqut^TWe&OpqCy5+jUVI3 z0^iOre%N4uzg`agC*fl2#77r!8GI9~gNa4VE%6Pm;Z2Yq;A6Uwlwz&s91{(B5yv~@ z)JXGWRqZgs8@wea(DGZX`vzz*otZbLX{uU#K2n;kTe*L?lIy8{aQ~chUV4bx|%q zZB!A@!VI`q9`!61t;PpBl|tH-bxe~UbZ|<>Is0j{C+ud_L}D?!R%enj9imLbQ4NW; zoBusze)U`8g;nV@7}@KHjxwwJD*|?{l!LB|)V5zLICj94_~IZ|xuR{op|G0_=*{{F zT!;e|9qAZ-Tw_3Ohrka!;Dx!q$CSC7BV|xda&)iw98fabkq$A)^7qC^rI;5QPKz1P zTUvMV2RxwF^^U&sz7fXrkguGBUyz$}Wr@k>R)^i2qdV)0LbbbN2Wni>%lo}UNr^PJ ze{D5YYOfX2=?ICtob~@7D z`}qPWqdDoN>6S7hj+wD!OJ%@_S$KU|n2fo$x00$um>e#;aW?)J$@)rX7-Z9%#Lggt zSLES%q`>UpH1HW!8J#%V(z)sL#C+$*QlTkFXF|J@8Bs-3p}(5CTKGyeFm!KSBza$b zd7+Yj5@t@GG2+;3=2~P%J+lXYyG@ItPgi=`ome6a3DI42c&>9`|vGx|PK zaT7|clT^})=jKgad*nkpV!P!@0RE#aYqy3y-hjyzq}2`)+h=O>OuS)XaW2y2u8$3L z2go>yqva%qqt~(I|0Z^*06Ekley;w!1yAfiSNO52;^8j=E6@a%b=0(ftCvqG)q52i zu+I{Zul4#R-7M1*T!(TBT zznO3=RM>Z>cdTvj9OM1POj3MQJv;pwCSS#Q#QSKAsqwcXJ}IsPRpqHqDkcB>N{_vC z_IZqkIxjJcOyI~S_c&osS0*Yg%=6W-56Bb?6+bo&{H?=ibFn0#HFz5Pe$*e+)kb+) zjZiSCW)=fRUb3uuVO%vg|CUv4-Ux3N1PL|ZN*yx%sU>XXaO$DDLbWh5zNmmic}f0r z{uVQ(QZ#In59$IAl-Tkw5nCBu4UW3EpnTeaNqd4z*_In-2sUt@44S9r7GkhyPLf_t z*H6iNXIpt^N~8ACZkD0QZ`~|x#}XR=kZVnF!m@Lat%M0;!mg!Nf-C7vYDV2!3DEBr z(?&Ap;@MU`5Oymj2JKTVWh;3}s}b+xgUt&4Dw2RnnBa9;s1ytVu1im}>f*siMoh;P z1H1b|&l~$L0Fx)up4esnuQUFWz=2kYNyCDGZ$@4hfkN3|rGj8?R%y2fz{|+@pTHJ`*=)6Ip8ipM)=x_XF>JwU}JQyRS;nb>&r3ao}^zY6wi)}whYdBMP z>*ia@7V$O-&ZH#y#4d>;_g7G+!3=B@tY3;-VxQX<&JZ9DsQ4u)3K3n_LCx`YKS!*s zmypQ@SMP&f;m|KVE+iX$XGzKAHxd?;7>9R_=5k&Ny(Oi5?EZ{nSA}X9f>JDm>E~P>?9r zHWO2&{>AXA5C;U4eX|8wf=`1d}tIp%pvV15}6O# zOM2%1bB)s`C68>@1`i}X`IV!umuPx;?$jqAJ;e8((T(bwglSB zvD{g&Vj=>l|8gbjW*q_5Hw#l-GwMPDw(+CvWhJF<9;X%&NgqeOA!< z$pCibhR&Yh3y$RFg{S{zXD8(@+vHSTHLw1LhfZ{|NnC# zFCt%Q?#D?%H%Yx_Id$YlfXU~2rl$DAm9 zlNHL)I7HB-Wvt`qKG#u#`fcDAZq$-xosNetUoyi4I|W`uxgO)b;fHs!foa;@b9MbC z>Srj7ig_9PYmnur1*3{U@$1ySyY}L1U0(5yI2mxh2UEjc;!9#v`O->v?L{*6>n}!5 zlxwT%Z2KfoR5n%p)w&%v)uJaOr;5o+|f9hbC{+JaTRFtYS!zPP2@m0 z{4xi~TIf^E_CRR{y#Tqd7W3;OM$@j9_LNWan`A{hTA5Xnt94L*z0{}m?N)y8TB2!w zmp+xX5>%b384a(a^S!IF81<+e+93m~!im00)!h14YsDRlqSdjRd$SryOwo#j#oXh^ zW#6L&Bc4kg6SUiWkDA~{iON({!6o#YQPJ2%-CrJK47O0P%Q%g0+X36<*kUR@UYxIVE`4q))?w$1O z#9jr5S*TICsz)sp!v*$155&+~%o`E3G5SM_U#s>>7bOuQ>}|*vUnZ{y09!4ls>`>?;+f5StZp(< zyMZcT5BnMdjW*6T8!{HB(mEMhn*QTP8bB420r9AtiqqPE%{q?WbA^G8=UJWp05`E~4A!4;4l-JJBe;WhEumgyQpfg`mIMK)HXK!~<4qkmUj zr8+7?yk(U@ymg$X@=Mn#1TfpxKHWTEFD>lF)xzTi=*iAjVsGVH8sql-n^0o=X}5lL z*WiGUm`i#FBZJaWOATl)p(Pmu*rSNi$;yUxGneiV}uHKbB?Xx!jlIMe)#{xf(ONNV4ao{*t ztP0q0$lOB4>)XtIQPD_GlMrvbd8T*ieY8Q4%0zha#^dcR)qc1MhnVy6V<-x4(5QY_ zSRdA7k#=-4jMCA@_aM5A0r;zV)cSk~@j-f;p6&g-ZG42gd2c)BDdcumS~Q4V`+PxU z=pj;@>DQ1Vw&5m>_ECBd!iG*uagRV4bV-DwH)?_{|4ai!W{vU6@M}22DcZbRk5Rf3 z3se7+k-3vVhV7| zN{z-V!*~PTamHi!%JLYB3;w?t&}ljD^Bj>6Qtg14f3dq{ZeoTk|Qq;|J#hc90P z3V=L&9~=aOscdh(L#cBD;d@>VDC*3pd*K0Hk@pU}7Q$>%sMqh$P|d1Md^Ab16HGAC zfs-uFlk66>Ns}_0M5e=Iiz8AV@7;OlAOa{tRAsQk-v@?>7|r!PnMJ2S%+f(SjZ?KR zKWjr@mH~6Hw9oS8Eb4ppPEZ2URPD#@k7@hl`inO;_nNCsb&A@DiIvu!I&uILNwV`Fq-5hIyhr=3)&;~4NX*(6-W^8B<3XG1n> z8*ZpTMju6|K`HMm;L)oBhJmXTPiXKes7%$rf=>q5>*$SD&KO>u@1mPkSuZ%2`4=c3 z@`9pLyq*nqer$Dx?(*4Dk@DjHw95R0=-F>C|>ivwu>@>Yq- zT|XKfzubu&?b$89BA_>-^94wk?zG+T9UIz6(d(ygR6#XNG$~`+3!6WNuycxxSoG(Z z{mlf3EE+!;2VOC=Ja|%{PU8Az@SpUFZ}A5`ON&S5$Yokg;B9=c-oE0$Dx8=Vmd(+_(Il-DGTfxd)UU#59ljU*+4S)+08Sv+Z|&suq9q1(oRa;Ju)kO^rvDMm-KCP2S^Vux?m@7A?lLLSBp-_kJDV3*;ikvr6%nu#Hhit4XV- z3;+}dbVB8`k#H<*CR-(<75rcN2a9Da`Gh(_C($;gVWnJtKQ*R)Gr=;+6QaxX|p>#vX`OBB&TCQr__j-%}V z*~*DOM4{CXOl+J^W3kTJ;1#*_6=@ApZ~qJD?Rt|_Twj7Z$5Y$~O`NRMqy4}*dH5k} zi76z^X=@!NZw-HsB!vyO0^PY;5hkhzb3@hFGay?FtJ>jn2eRh(`FOikA)8j1mz}rH&lk5L{(! zOf)?K_q$p(;f-?)IcLSN=Mey(6jx1@e)cA`?K3;7l{c*l*VMaRuGO!Z1DOl&AUaZ> zF%Dnua;jpS`>x(w-Wz&T$IJN|7k|^F5C4iDvK6XY$?Uo!i-kQ^)lO0c(9nKB^ zrQe0zZ6m$=uU2L4_nu`S2B;$Tx!eYluT-TNV7_!`iyT++VnB=-sPDBEn18|Vbs{27 z%|b;D)S;EcF&BtkW`zo&_W@L|gHGZI|01*0mS@dmv5KneRoE9 zhVN#ta+Z!ZG9e|hD6n1haZ1O^ubW z^qFxuR?D=@(`iLpse2MW&F4yziu?oO;Sx2l$2T&QyuM+RsAiM(+iYs71>IAe8Kvn{ zA}$e+C1EfyJF^=}2+npsf{p68iyOy^;Oy_K4GX~$F^6c-X z_^4>53 zG*=E|UQ8|Dqf0@ib8NRjWFBW_Rv0aqx8)30_`O#G4^drnhJWFrP6>)-XfrqioOarU zlacoU-Haqu6Kfwp?U#tg^ za8GZzaz+$B3R6cVlNE7*VRv#E0dvr>>S;;b#F{^k{67Ob(+2NLYLEfbO$Fzuq5uJE z`mbtfwV@7g!xmkWLAEQraGJP6ON7!{WrI&Abqf0CG-$Vx%c$SXGPD(p>?!CGE^xgg zd>R-H2Y_(K{;IouHT4#BN99c9#`X_Y+4+3v@u63*Ye`mm7Q5myGv+oqYen zl(V~45fk25(q1gWDlnGnXdF4^l)5HNZ+j2vMEc6+OpyheuI>Hk5cr72+cV z=pE|(=HcJU38<*aK6*s9y6(~<)6L9Uixy$IsC2=-hZ;=If0ky@u9S0Mqf=T$k_~4- z)#lv;a&tTDykI?v%E(0x^b6r>*}IVANDnqy@{e0Bj4WDAwXt{w2_@AOTqAjR!(YG zN_InhYt%7+&+W8!Q}L13#FwJyh;lnro%Et4aKp{ zmp6(o+o%$efmP^EcqV?u=RYh9y~$<-DN8?u4b#^ZnVJ41vc~e4t^Xi&t`MmRej*~T zd-{`#AXrV#4q=6)lexinxFd@2nZ0v<;}66GfrCD32p4ZWu%J*vaIS850i=3z9dOD} znWDvBl~^(Yh2&UHWY#%W4L4AkJ_lE!L7wjJVfYwtgp&hJqnUnS05wbS;C+;e{fO}M7*bB|KxE4zkw@bqPN0sR<28obH!ND_tuvj-eAI4-e!o?i_N8-HO$&W z4e(#GUn)Fx(|6d5A0q2Ua~pd$_}T3JtkdxypS!`dSaCtbv$?R)soA>39QMX~nN*S0 zEooYzO6|MkjY$%2RkE%_&{SOm9t9mzU?c&?jY0h(+ove-dYU>B(K zpC-1z$7K*j)~o33EbK zo2=M8X_-J*ad?t8k&!!R(Pf0LRbBoX zqb*B7(L~L;SWLxteI77Ep9$dnC9TMM^PM3wjmm5>zBU~rg0jK{HR4sq^8rrvMMe&Rt49O6Dd}eJyuY3{dx^TT0$^0gH5RTI~QF?^6E7=QT8< z-V#==rHZ0%Tfo`aNXXEq^ew%9%CvoJ;oot$V=JZo{3!a+pR1Sr-#e!%mpwV9&;8E8 z(HA@C=g@_vnneU*d4WP5$zTgBW&9E?H102}RzQh9H0@CJFgFk*FxMFO!n=E)P|=1% z;7aw#U?E>}5howA2VMbE*j~gysWYg3AfRV{qH%k!#9oDXpm%^)701+)+i@~kl%E5V z&5=j|Sp}W{g9{|$=HgvTor2hK{w zdF5~v)e%aNRQb=Jx*Fzd4};-z^AmXbbm*{$Nejva_kE{?EpcbqmQBTwiR&US8Z(wQ zBB`N#HA2~x3$INZjcCnHQSoZeG4hdD4eyd+wtcB0D$DDl8gDk|cDZc(OQnMzI zD*L=@SHTdy{ivnH&Wz83WBc~jBfM&eMcz_4dc?$lD=I|TAr;DHegTcQe+ zPpKFRya|AAC3?Fe1RH~Dv$sE9sNEgd%~m088~*92x_H<=Ebx<6hQQ5pK+IWy<;qEk z7fjS|+S`UXi@eHp$yfsrLN94361&)`76MNwq@6X&9Dvov$GCa%O#^)Cj0@q8@4Tq2 z%VjVl5wNY;lEOickhBy0ujMz(L*|u=W-`@^s*_NX#VvW~vrh z1V^<2gmmS+AnSLia5if@rFW+EgzuNe2G4QvRB(`6;(M%bq&HS6_zbwN_?3HwYQ9g1 zTt}?gN_sM~*c`RY>Sd)PD1rn8^}A6j;}!B(_8D&fyR?L^e209Zc%kry=Wz)s71MQQ zcoFz?#u&_M5pxhIbAtZOU#%PSWpAB9#vJ)TQ{W{tCgvnt4+XuR^M(;zo4k(*!c#N_}-lyx_7hj z9lv`Xxd)?x`Xz2Ils#zYb48qbA}%*+m7C+isfVAu)W>H+B1(dfnXo0U|N0tW1yR_DZnM~WUw zOul>km&eI(5tk<9T_dwM;5DrpJMg48$wtF5O($#9X}k_?(nh zlSAGNOaJlq5(b3+*kvjQ8)b*{dZ}==zCML?k&BnhqjG`ljuxpu(Gk~{+*mWWZ$C0r zp}{8pDB%OnVW8`Y?~IZH@NNW@mI6Z>T=jaC3OMP_E$5K0A@Uk0I$RHi>SrF(t44HbpzFGGi(*%;H2+DPjv=RdR)yRhn99et+9iEdd1>QqAiQ7;c`WnA+ShOgzN)1W0XS1V^k!AtO({3U+OnjEx zuu5I%?hq5~eT5aN>!4gg-txGwd#+}YtF2MBi%6S0AoC|^c)d~%Zg8mpUgph~Q5l|b zCYqhe;k3;p&>c5KizVtb*5K@t984Jmx5VDLI$UZDb81i==d)foY6e^%UGX-^yNM7# z>&LmX-j8(PP*1&o_X5SoB@2iigGrvtZGf}++0lCKgcPRdBVas-VxvHxXJ)=~Yr=W= z1U02<4hdojBOhA~6HD8ArprCKiB}-a0=e7-cFK^)sqHua3pfKv_HBg&eww_MNu2hh z0BS(Phfll2@4S<;Va?_l$@pqQ1KhSk<(ye?o&2p06(dq){COiHaFogrP#LkkAmqR0 z^XiV$2D!e816okc`u7eo<*5i$t9L8XeG=p6*Jb!uDjjQzvy1KW$Qs z4tyQof0A>H9>K{2aSxS4aV!BdvIwcWudJY@>`DlF9$n!W{iO>_d8SzBIt1!fZsNI# z5_sekm`$VHZF8LIQO^aAE7zT87`W2#F$3nG-KGCr;W6M0Q9t6K)ekvJlA8wF-Ub+=8n6t9Lf1_ByOB0G|tcT zqk-Kgfldd{9`ALggLvsKR{uzCud%zKB+Rk$>EGW&#rnJhHrVnv`N+VgR>x@^XG{Pw z>_suQ=dJ&yonuUz^b`I8OtwZ#OQ>X=_rD8n`2i-=62oEp^kIotd5C%0XGv<~PR-Rh zg}xikpnv(F8K=KJty{w$89^2vV7ZEacrk00+lC_*y(PqCbf@LZ;!ITaPog_1nE}is zh)4}3jj~r0+?T5kOIp@z!4n?)a+dP#zilUTOw?8b&s-h}72e`mmfwX9`Y{vYJaQ`U zNv$jA9k-OoX(qus)^8WsxZWyDX4x4U{6s5GmD0@w&m%Wa7b+M#qt>nXviTYDOG>wt z^))f74X64IUZ(WJ4kX)CWDQXyjPU>-b1*1u7HFp>4LS`p_)2=t&nbMa!WoNJ>l>0| zx>FWd&}u!I0>jB*G|zeT1BxhF$>eZ|?O-L*R5C0QV?hI)J3ql%6Mw$pVuyMw8YkPr%aOUb&dSq8%K+6G zz)|#V@%dsT=~hPIElT%umN>r^IAFY{-;eAO%hL-8X0>5mh<*j_Dp+yb^(R?cpqW-YC z)vsOpQ)l|Cdp<7^P5-spiERM5kakOhR6lUgOY!?w{qUuSKHNbhSyvR$}XVg1H>ZnJv|t~ZNe{t6~_}sb|`h!hE5>C z2lWk`LY6wB7+tkf<_h-4rm2W-(~C$2D-6yaTR$&dmX}yb?(h?tRWw7=axWjgf@Z3> zxWU$*=8|k5k!)hz=c1EXo)8ofbK?tFknx9O@z~)OjI0HSE$5iOHX9zo0m=3JmkwLH za#3E-J>Sa|rq(Yw&c*;w%8tif3o7CKi^)w(tP)I@w{Ufthtx7E;el1hq1V9E08@qT zu2{IBd{u4KIktARmS`z4GH@~0k3-s~G2in*xKkRB9Noe91|6^1feE*XSk)@a^jO_K z;-UQKiauJ3*`+Z=WTiHla2(-%`=a4?>8uYl;b|fyl51gjFK_zP#wUt0vAwrE_PDb3 zWNp5t-Z8QVjICOS+}Q-`PGDdkbw|NeONKk6gYK2iw4^NPo`F|D;H&u42z+CDDd1#X z=JM^(C(YGvi&c%iCh1rqhP_)yl28dI__AFM(~NrY&JHb^lq&$4b#XxX-@Q>xIOEY? zP%XQ|Ob=n>CN4<$3&XbgI>oB1kesYLcVLvlp#iY(T!|hi&S{>@yKwrNak{aZno8uK zlNPtz-_|=r+nS(c-$0Vi%qu|eR_AdZ<51iiq2r+fVPEcjX*nw;(WPsR0Wk^?DUqZ^C#r>=U?>_ zGy<|a4vb%X_ssD&PrQwr%ari*@ED?yFJaCuNs^`AA>u(@TzfR)n^^nx*hxIWyUFC-lGxvzyeP{! zgsHUy9uvVXr+#DSMFjh13A9G)g^&!`H5gOp8@jER?~D}4X&$7Zvz(N-|Jim0d2Vqf z>RN91%VQqV*MLz~_T1J^XLG9~YfPT%y{<3blAWfghbk4bw%EXSorGxmnGyY|{)b$DMKaROWF3Gc zv9vwm+58Of-BklOcAMd#+G_eju`G){A?ig9^hX(P(lBxC##4pQaS_lZv((d;{4e$R z6#RQ6n~1;?c3oybDm?in<93xI#!zB2Wni)|(1ue`$5lby?BboKMzJ^4XRe~LP7I2j z08Pmh;p1XQ@DSCk-@s~GhDURf=C$98`T_yH77P~c)G8Jc*jAmm(v;Rr*Kd(BmkyR1 zSIfyqkE3-5^g)-`G>|%Kp>S;u3qcj*#=YCr&r9Hk{*2w@sMln&nf$K%@j5R^4wHqd zow3w4jO@9Uj`v{p-4sQiDwDk}N#j(vrgDyJ)L$3k#@J;N@8CV-wCIQTl=8HnSr zpT^QjhHwX%cV5u#{&95>@<`MDXrFLeP6;*r>PKo?>Ze`w2l`IG7#&&_rLBDh zVe9au=oMv&%Y_v#; ze*vQ~HvA+w$*=5KGGS0|9O*cTMntcT6t%C50uKOTP%LO&DH+wezss>@fC8emw)Oso zHuSCA`F+R2j=4SFPm_Zjxvt34)AkoX7SzKU7JC<3If+BmM_(1ZT z_)|SI zAB^s-?P%dEe=O;&WZ%XR38ti#nIvT&aai1(CG+M3Vw{(ntXwdUwR%PmLMiNKJ%~}} zlzhYnc;CftgmUm9(7b*EzcWe81NtF~dXs*Ew9c&7-JX zb6c}oC}5Db1zTc(i`khdmt)!FGtwn<`acGrK&nOGM9rQT=tJp*7%0(;5b`owueQi? z;$(*Tz*$FXP^6<}PN=S)e{Z)*YD$Q3RDqI{&*zS~EaNNM^um$)?wbLiOr=-L3FZ{g zR*O&3>kO@`Fchw^GG4ZZ2Jm==r6W#M=Wh1dcAJ3aK*5V4sPNbia48~;a7xA3NA1K_ zNk22_M5DA&^I<_jdQt{=`qkHgD`jK>6ZqQk#9FKYFIaaO(r$$4`Hb7i_`-7y+)jH*=Tzra3~-_wTitri3*J^MH2R|KyWZ55Y{o@& zdap;F-%@E91SohOmh)Jew0rf}awSv2;H&dbV1GjW8Y1tJ$i>vyPu~ zb7c|@)dEjFq6}Qr_7GH%)oT-9f~FF-tsY2cbhPxcgawh0>UZN zC082b(Vj z=BXoU-K~Vs{7SXcKs!Ro+vp7uo#TaG8y886oGyZYN{fYaV{zk~z#n~m6haai(KgY7 zct2flimk1K5T9GVWzJAXH8y;yvTQ)%0*L$GrPO6IGal-z&DH9Ye-$@*Z$rnU|8YK| z$Z9V#TF(aWk`f~7s*;LLyp^e^Aic`6b8~)oQz=eDsH-|B+TGDG?{Hry0&p)m$W7?w z-kFb3d&Np=-iTr!8ECu{ThUBB;wHZOW!T{t$J*9{&TZH^#6#saiyi#CjInc9(I&7V zqq%!AKT2BGYqZYU37I+*^JQQ}GOI$n+LGBl6D>iMrbidXU2EU1X?{K|8!2Kq zEkn=SAjR!!VMt3eA`}Ya0F^q*|3wFN1#lmH79S9ckS8>NKa;lTnk=_u1BfJ!EG98E z@Z9;Ex1^Wv-E0zoBM2)ZK%QId5h;Z`$)1|G4 zgzQXMHS(&gYF~ffj}_s&UnnVWYWMj5&Re380}F^=Fw#ZsncITE)@iI0Q;@G&11)Pr zvrP0o__yOjOYG~1l&tYM+vGh0jBERwC-P|nB=P|@E~-yDBvJ42TgSM8aEerYQwT`f$sN)0;3zL4pLk~(}Db}CwzWdoq>ZKBAJ$kTz z1yYPsokddZAn*>0{#0@t*;&lIr}e>w0cc%XwrQiPyY|#Eq$z1)bl*9jJo9!6O36h% zKzkt@E77tS?O4mJG0f5HGlIXm?$Qg}cr z#m%2C9?e>vx|Tbd&j{Cy#q2Y`Tw)7vRUpfF8c6a-6^NP3G<%nP)+|)Y)@*)k`rbo6 zTj~Fb_5!`k>=oLoLl(#=nIX}ifSe%akIE}?+k)RK_VBBnkhy~mIh})rNB+v#L9ll+X6b(CR3qWC$7J~~YQVI6~^&x?MhRmQzE$B;-E{e^t|^r^F+U)9W27FFGKU@Ai@ z2YzKeFqZ4z={^j6f7=dHtN}%(g?(GZZLG|lo4`oTZdMw?^~%9*Q+mAe4gNf8x>WQ4 zS3RP7cpb~m;=1KswqzLi@B^!*HD)R-i4btEnS+~756$)en{omFgS*M4)1JFw-b4#y z(2wYAyHVm%rd0v>tmU4;kbDwo#yJ5gbnw`~o2%NbVGS$>QFLg3q1S`j)>eNT$pvdp ze~@`<;51T~HM=Y(_>pF|bA`aO>WlBM4Ln^SA;sxmGbUN}d?0&tz*zoqFQ0FFx+?l4 z*&>0JkmCKSdqm>5qyhTW(vJnJGXiL2^Ofviwpi3Bgi|GP?3YV%Rmlc=79d zFslSQyg~ql{1aj>9_lnW*>h}8qbQLt;q`~qB`vzbn&|X?6>D*W!MBh!yV^0}h8g@2 zZ}h8lJNUWSzt5?NABG|U0SZ1nqwBdvaB=m&$PtF0-=OM;IuHCu*lT7xvoM>^ zMtXtP_gD5R8DD&9Vy7v2MrLDNhXdOlEpe`A)!e${%k{ZP>aHGse&l$d0my2)jR@5Uf8vJbuV^DeY?@flvN^- z6nLu7NO8m5N~sGFz=KiN2%s$%idlI3sP4N+?2~0Wju(wY+PdT}!!)j-g+!no)p2w4l{WqXMFZ>6=B&Z(oo7EA zjsk`4y@FD^)T$Mu_N+Z4)F`FI-c@Rgs=b05p=uM#pH{4vn58xqs#Xwt*A6w(d+%qs z@9yuO5Ad9~&#QC#tmM1ajsXe~!%K6{@DEf!A&Dm*>xregv$;L)ZuGC3WqDsoe}|lF zB7t$MvFHm-QiPhqACi@7`H<~Ss8Z`L&klYD_VrxC$Ti;AStV$5`1DOVRirFXa%y5B zAp>$ts(*Tv-cfu17NxCNZxap_Pd;duxz8O!`yw@Y-nM5LDgSY#YvHD;oSdB`?z_o1 zqlyM%W=s2N!Gui7wAjLiW9$<`mYL4IU<^opuGrjZgq7dkMv7T<&%7@p52f$pnN}j|3N<)sV`tgPjJv+HZ96 zEu^(%pV&>Jl9=V(Fe%|n>Lex0%aWI&4saNXu6#N5xD-}?Jglb>4_AIg56902aT;Se zOmji{&I0<$WZy>yZs^Z9eJ=vtN{EHMhLE$&D~;Os{9_v)(^$%` zKf;wUlhYEez}@XCOuUGqKMC%zyG)SU#z219e+mBa$?oK?@2YDRbT^qAD>AG$OKB8k zT`HQ;YYm##L93M%?{W;6{B@#l*WlV65VU1)g(Kds+N#-GVP4Sa>JneEVa2k zXAh#*tUZxo`ty~wj+gLMtjzaS{!r@v3+V$m4rC!hVODMB(h#`BLJSJ7@9~s!aNy6n z$%`+t`2l=cQAMiqS%azn{IzEribZalFq}r+K67YZKL?_0mTU_+iz<=2%dd#&Htxl8 zTRgCYIAVGQI)e+{_P2Dpmq4|JPk%E1lV?5Tn7~~J4u^wdfq zYo%hfBJ0@AZHa67&z*>Jgp$g}nt>xF?`7;k2Gc(mwG}M{vB~|uhyboWk_+Fc`4SC5 zlSp|Oyb4|8I41E#B>q-OOmE`GVrMSDx6KrLQEX^( zRADgr=imvOEuWgnFyUF1|I81LuXNS{bmQ`V3>96o^CKSwNk6hlIfv0oI7?ScCA<2d zFX9aRUMk-+Z!li+GyA9j8~LsJBQ1$s(Cl~NPmszV1y%w7{k9xb3`Y-$J>=o4-@ipT zZQ|=^=wfRfGa{WC)FJ=2aQAdOjXK@I<4_-AUaZ$RUp>?G7S)}gBn5j_(7zQr#*lT% z+cF}oMT>69Bhbnm5qXRN1)}E=R=viiB!`PsE0ro+2i8M(`A6X$Vn|A}FGNl`_q^kw&4z?F-C;{{!S-c?>5F|zWuU=!~+h|oC06%0UTuW~xD!B8Y1Auel=L;jzj4sU=VDK09?itM0G;}35MBo%7@@G_nnFZw z9HGrcoKCYwaBG2y(Sbui{i@*;8qKb(e#IXKwJDW@4KizCw~zPySC|(o;^b01 z+K*(uG%|qW(P8! z@aG`f*f=LCP5@w<5petDix-?NY6d4j+UXQ^t38~CVw?lM_YAbpFqOmR9dQo0J!&Hy zhd!l!ZO(Ntu*?ckyeiNiQ?tdUM0pYxDrrF!uTVJ zVw}5p0(KU%B>5ROD!k)tM+zUtB?^BGap$>66npDzrn8$)YTq68*HOfHJ~?5dK(H^! zC`HideT(X{QonX;wU;IBr4@uyJMNR9N@@>8$~>8t6Yn@JxlOubgY| zoJi?-#%~HrhhX(=1+Voe6?mJU*=uYG$EavlKCh>7*9>1@u9A!Job`BMNpsc~LrtRY zX zXInCaY`QyEg+kX*MAjGBAG;jKC}c=>_V;hi%iw+i1#Ky?ZT7^u3KLedSH${vt(g8K zkzB#V;Q~jf+mP$fu~r8NJjXw^&PdXk#%@Abm4xDzsXUVZ`V7yt_GTshY0O5&*+VSL zs#z)*Vnv7yIqMy;Xme-%bWQn*q@%wpt!L(#L_`Il3Gfa(x9*Ek-Fg>sc0@d6n*Mq5 z8alx#NshAaOQ3h%eaAF9VjVAJ5mtHj$) zX548&vjeg&j3}(Xy=|Dqm>fp?&q4gMuInm*tVC|=*fwnbT?Mn+kwc%t$)W4^5rB|v1)6_i- zFZgg8Aba@~O3v;?(YiOnA?g#UwIOTxuq~qUpca~a^F_&MA*r9NrtD@ufzkX}`C)vY zS)?>G00>Vbgte}(FURQi*w>t|l($TtjsyF~h6pSY+IrDlt2@1>*CEI>BEx))twL)9 z)_RT*us!w2g?T3+xL37w6WpJyz}>g-Zr^0A>htXZFWm%o=pE0rLL0`0mNnU@1ilnX zN{qUPb%uTATtD@`Z{6qba2T3f7~4)>Y;Z?M(Nsm7@Z>KUQ~qU`L4u4n6H{%yy~Re; z-4Tdpi%|K&Nu+lK#}8)VLi2IUhJLH6_l{@49>Vko%>1iI|1Qf( z(_^s?4g*}@2pFRHM!}vcX)YS@8a}dO3I6;k$xb#Cv76|Gqmy8sa-1~&~1{h5^?XQXCkkXMY>+|POos)d#!OwlY zuLvriKI%rDjV#oMJ@FpbyXq}G&?{o=2(*g8`&zzInzPlE2_Og(3Mu^VIpM!KesexN&4ddfhcAeB&VA~byh@z*Nl1U z$rcj#QJjg8vk9Hup)q5JP*fF_{vM7xRHDY7!Xp2Y6zdmsJZi+KgeOoM5Ik$_&)Q@9GTm>6Q ziS9hH-RryoUQXJ- z{^(Pr5oe(_CTDD<_5$W{N7CJ$7~sGm4S0F9oTBTfOT6@?b^iXvi}9{UXM|8$*qEVe z?flD5Kg?<=v&pz}9XZ-L+aW%hgj&-p=kY@LLoJK7K%4--+|CHa?w z!*F+!dxlX>n%#*dgC!9I{Yhn(*NavwmP$P>7CtLVERp7^eh8cc9np|;wZh+aV?+AZ z@X!Rxjy*rHj^4nQ&rh8?v0%)yzgyUmIJo4Ej+5bSK8Q+Pv~d+JXG9F+H3kUMl@{E1 zu$wNIt)!Gmc4N~=$+_QP0)}aOk<4>!vRT+KRg`$L#v#%`!ra#>M99SAt#$BVY$QXb zvlEObc)gg~bc(TYf!rJ9bW}7k1ffYfZ*VH@P4`W}l>2=o!Y#eB zh3d2HYY}6oU7)?rf?3MC#~ohyRvIPzn4)Yd=D8K_xsV5dMb?QcBri!Ey%=OKh?1Zu zMt+>5&lFR1RP?vy)!fE4U#ar&hI^cSzOmTet>q%+Uu|zuP|%7OUx75%`+J@J zqWp-ydh%x%Ey_Wkb=Dj~JK5ntlHe-bgHvt7{}b$Dw=8umtp0TnaQhgnn|DoflQxS4 zvx?nj|1xYXTi_V>1#=nHC60NKEV9V=Jp zX?HmLe9PBD$PTtVia{+^n%cbZ_VB{t01*=xTo>!Z>6xr-=H=?zcA_I65(G6UN$)0# zNnDV3i}W#FY}_4rzkr^EEHzHzM`nm9Q1ZdQ}PmSo9vhHe5qt0MHBxE2E_3+ literal 0 Hc-jL100001 diff --git a/fonts/Utopia-Regular b/fonts/Utopia-Regular new file mode 100644 index 0000000000000000000000000000000000000000..1772a3a0b7d0ea0bc4546cba06f453f8c230f246 GIT binary patch literal 36350 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 literal 0 Hc-jL100001 diff --git a/fonts/ZapfDingbats b/fonts/ZapfDingbats new file mode 100644 index 0000000000000000000000000000000000000000..eaf7105c80006dabb937a99bdf2074b23cad8c0c GIT binary patch literal 44537 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 literal 0 Hc-jL100001 diff --git a/locale/C/cups_C b/locale/C/cups_C new file mode 100644 index 0000000000..dc69f651ca --- /dev/null +++ b/locale/C/cups_C @@ -0,0 +1,123 @@ +us-ascii +OK +Cancel +Help +Quit +Close +Yes +No +On +Off +Save +Discard +Default +Options +More Info +Black +Color +Cyan +Magenta +Yellow +Copyright 1993-1999 by Easy Software Products, All Rights Reserved. +General +Printer +Image Options +HP-GL/2 Options +Extra +Document +Other +Print Pages: +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: +Color Saturation: +Color Hue: +Fit to Page: +Shading: +Pen Width: +Gamma Correction: +Brightness: +Add +Delete +Modify +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 +All +Odd +Even Pages +Darker Lighter +Media Size +Media Type +Media Source +Orientation: +Portrait +Landscape +Job State +Job Name +User Name +Priority +Copies +File Size +Pending +Output Mode +Resolution +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..06ab0ab1f3 --- /dev/null +++ b/locale/Makefile @@ -0,0 +1,73 @@ +# +# "$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: translate + +# +# 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 + +# +# translate - a simple utility to use Bablefish to translate the POSIX message +# file to one of several languages. +# +# translate outfile language +# + +translate: translate.o ../cups/libcups.a + echo Linking $<... + $(CC) $(LDFLAGS) -o translate translate.o $(LIBS) + +translate.o: ../cups/http.h + +# +# End of "$Id$". +# diff --git a/locale/de/cups_de b/locale/de/cups_de new file mode 100644 index 0000000000..7a387cec7a --- /dev/null +++ b/locale/de/cups_de @@ -0,0 +1,123 @@ +iso-8859-1 +OK +Löschen +Hilfe +Beendet +Nah +Ja +Nein +Auf +Weg von +Außer +Ausschuß +Rückstellung +Optionen +Mehr INFO +Schwarzes +Farbe +Cyan-blau +Magenta +Gelb +Copyright 1993-1999 durch Easy Software Products, alle Rechte vorbehalten. +General +Drucker +BildOptionen +HP-GL/2 Optionen +Extrakosten +Dokument +Anderes +DruckSeiten: +Gesamtes Dokument +Seitenbereich: +RückOrdnung: +Seite Format: + 1-Up + 2-Up + 4-Up +BildScaling: +Natürliche BildGröße Des Gebrauches +Zoom durch Percent +Zoom durch PPI +SpiegelBild: +Farbe Sättigung: +Farbe Farbe: +Passen Sie, um zu paginieren: +Schattierend: +FederBreite: +Gamma Korrektur: +Helligkeit: +Fügen Sie hinzu +Löschung +ändern Sie +DruckerURI +DruckerName +DruckerStandort +Drucker-cInfo +Drucker bilden und formen +EinheitURI +Formatierung Seite +Seite Druckend +InitialisierenDrucker +DruckerZustand +Jobs Annehmend +Jobs Nicht, Annehmend +Druckjobs +Kategorie +Lokal +Entfernte Station +Duplexing +Heftend +Schnelle Plattenkopierprogramme +Gemischte Exemplare +Bohrung Lochen +Bedeckung +Binden +Sortierend +Klein (bis 9.5x1în) +Medium (9.5x1în bis 13x19in) +Groß (13x19in und größeres) +Kundenspezifische Größe +Leerlauf +Verarbeitend +Gestoppt +Alles +Ungerade +Gleichmäßige Seiten +Dunkleres Heller +MediaGröße +MediaArt +MediaQuelle +Lagebestimmung: +Portrait +Landschaft +Job State +Job Name +User Name +Priority +Copies +File Size +Pending +Output Mode +Resolution +400 Ihre Datenbanksuchroutine sendete einen Antrag, den dieser Server nicht verstehen könnte. +Dieser Server könnte nicht überprüfen, daß Sie autorisiert sind, das Hilfsmittel zuzugreifen. +Sie müssen zahlen, diesen Server zuzugreifen. +Sie haben nicht Erlaubnis, das Hilfsmittel auf diesem Server zuzugreifen. +Das erbetene Hilfsmittel wurde nicht auf diesem Server gefunden. +Die erbetene Methode wird nicht mit dem Hilfsmittel erlaubt. +Eine passende Darstellung für das Hilfsmittel wurde nicht auf diesem Server gefunden. +Sie haben nicht Erlaubnis, diesen Server als Proxyhauptrechner zu benutzen. +Der Antrag hat zu lang genommen, um durchzuführen und ist abgebrochen worden. +Das erbetene Hilfsmittel hat mehr als einen Wert. +Das erbetene Hilfsmittel wird gegangen und ist nicht ersetzt worden. +Die erbetene Methode benötigt ein gültiges Content-Length. +Die Vorbedingung auf dem Antrag wertete zu falschem aus. +Der Antrag ist zu groß, damit dieser Server verarbeitet. +Der AntragcUri ist zu groß, damit dieser Server verarbeitet. +Das Antragformat wird nicht durch diesen Server verstanden. +500 Der Server hat einen unrecoverable Fehler ermittelt und nicht Ihren Antrag verarbeiten kann. +Die erbetene Methode wird nicht durch diesen Server eingeführt. +Das proxy server empfing eine unzulässige Antwort von einem aufwärts gerichteten Server. +Das erbetene Hilfsmittel ist aktuell auf diesem Server nicht erreichbar. +Das proxy server hat zu lang genommen, um auf diesen Server zu reagieren. +Dieser Server unterstützt nicht die HTTP-Version, die durch Ihre Datenbanksuchroutine angefordert wird. diff --git a/locale/en/cups_en b/locale/en/cups_en new file mode 100644 index 0000000000..de5472dbb9 --- /dev/null +++ b/locale/en/cups_en @@ -0,0 +1,123 @@ +iso-8859-1 +OK +Cancel +Help +Quit +Close +Yes +No +On +Off +Save +Discard +Default +Options +More Info +Black +Colour +Cyan +Magenta +Yellow +Copyright 1993-1999 by Easy Software Products, All Rights Reserved. +General +Printer +Image Options +HP-GL/2 Options +Extra +Document +Other +Print Pages: +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: +Colour Saturation: +Colour Hue: +Fit to Page: +Shading: +Pen Width: +Gamma Correction: +Brightness: +Add +Delete +Modify +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 +All +Odd +Even Pages +Darker Lighter +Media Size +Media Type +Media Source +Orientation: +Portrait +Landscape +Job State +Job Name +User Name +Priority +Copies +File Size +Pending +Output Mode +Resolution +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..0971aa5524 --- /dev/null +++ b/locale/es/cups_es @@ -0,0 +1,123 @@ +iso-8859-1 +OK +Cancelación +Ayuda +Salido +Cercano +Sí +No +En +De +Excepto +Descarte +Valor por defecto +Opciones +Más Info +Negro +Color +Ciánico +Magenta +Amarillo +El copyright 1993-1999 por Easy Software Products, todos endereza reservado. +General +Impresora +Opciones De la Imagen +Opciones De HP-GL/2 +Suplemento +Documento +Otro +Paginaciones De la Impresión: +Entero Documento +Rango De Paginación: +Orden Reversa: +Formato De la Paginación: + 1-Up + 2-Up + 4-Up +Escalamiento De la Imagen: +Talla Natural De la Imagen Del Uso +Zoom de Percent +Zoom de PPI +Imagen Del Espejo: +Saturación Del Color: +Tonalidad Del Color: +Quepa para paginar: +Sombreando: +Anchura De la Pluma: +Corrección Gamma: +Brillo: +Agregue +Cancelación +Modifiqúese +URI De la Impresora +Nombre De la Impresora +Localización De la Impresora +Impresora Info +La impresora hace y modela +URI Del Dispositivo +Paginación Del Formato +Imprimiendo La Paginación +De Incialización Impresora +Estado De la Impresora +Validando Trabajos +No validando Trabajos +Trabajos De Impresión +Clase +Local +Telecontrol +Duplexing +Sujetando con grapa +Rápidas Copias +Clasificadas Copias +Perforación Del Agujero +Cubierta +Atando +Clasificando +Pequeño (los hasta 9.5x14in) +Media (los 9.5x14in a el 13x19in) +Grande (el 13x19in y más grande) +De encargo Talla +Marcha lenta +Procesando +Parado +Todo +Impar +Uniformes Paginaciones +Más Oscuro Más Brillante +Talla De Media +Tipo De Media +Fuente De los Media +Orientación: +Retrato +Paisaje +Job State +Job Name +User Name +Priority +Copies +File Size +Pending +Output Mode +Resolution +400 Su browser envió una petición que este servidor no podría entender. +Este servidor no podría verificar que le autoricen a tener acceso al recurso. +Usted debe pagar tener acceso a este servidor. +Usted no tiene permiso de tener acceso al recurso en este servidor. +El recurso solicitado no fue encontrado en este servidor. +El método solicitado no se permite con el recurso. +Una representación apropiada para el recurso no fue encontrada en este servidor. +Usted no tiene permiso de utilizar este servidor como ordenador principal del poder. +La petición ha durado demasiado para terminar y se ha abortado. +El recurso solicitado tiene más de un valor. +Se va y no se ha substituido el recurso solicitado. +El método solicitado requiere un Content-Length válido. +La condición previa en la petición evaluó a falso. +La petición es demasiado grande para que este servidor procese. +El URI de la petición es demasiado grande para que este servidor procese. +El formato de la petición no es entendido por este servidor. +500 El servidor ha detectado un error irrecuperable y no puede procesar su petición. +El método solicitado no es puesto en ejecución por este servidor. +El proxy server recibió una respuesta inválida de un servidor por aguas arriba. +El recurso solicitado es actualmente inasequible en este servidor. +El proxy server ha durado demasiado para responder a este servidor. +Este servidor no utiliza la versión del HTTP requerida por su browser. diff --git a/locale/fr/cups_fr b/locale/fr/cups_fr new file mode 100644 index 0000000000..fa5c05924f --- /dev/null +++ b/locale/fr/cups_fr @@ -0,0 +1,123 @@ +iso-8859-1 +OK +Annulation +Aide +Quitté +Étroit +Oui +Non +Sur +Outre de +Économiser +Écart +Défaut +Options +Plus D'Information +Noir +Couleur +Cyan +Magenta +Jaune +Copyright 1993-1999 par Easy Software Products, tous droits réservés. +Général +Imprimante +Options D'Image +Options D'HP-GL/2 +Frais supplémentaires +Document +Autre +Pages D'Impression: +Entier Document +Chaîne De Page +Commande D'Inversion: +Format De Page: + 1-Up + 2-Up + 4-Up +Graduation D'Image: +Taille Normale D'Image D'Utilisation +Zoom par Percent +Zoom par PPI +Image De Miroir: +Saturation De Couleur: +Tonalité De Couleur: +Adaptez pour paginer: +Ombrageant: +Largeur De Crayon lecteur: +Gamma Correction: +Éclat: +Ajoutez +Effacement +Modifiez +URI D'Imprimante +Nom D'Imprimante +Emplacement D'Imprimante +Information D'Imprimante +L'imprimante font et modèlent +URI De Dispositif +Page De Formatage +Imprimant La Page +D' Initialisation Imprimante +État D'Imprimante +Recevant Les Travaux +Ne recevant pas Les Travaux +Tirages +Classe +Local +Périphérique +Duplexage +Agrafant +Rapides Copies +Assemblées Copies +Poinçon De Trou +Bâche +Liant +Triant +Petit (jusqu'à 9.5x1în) +Support (9.5x1în à 13x19in) +Grand (13x19in et plus grand) +Faite sur commande Taille +Ralenti +Traitant +Arrêté +Tout +Impair +Même Pages +Plus foncé Plus Lumineux +Taille De Medias +Type De Supports +Source De Medias +Orientation: +Verticale +Horizontal +Job State +Job Name +User Name +Priority +Copies +File Size +Pending +Output Mode +Resolution +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. +Vous devez payer pour accéder à ce serveur. +Vous n'avez pas la permission d'accéder à la ressource sur ce serveur. +La ressource demandée n'a pas été trouvée sur ce serveur. +On ne permet pas la méthode demandée avec la ressource. +Une représentation appropriée pour la ressource n'a pas été trouvée sur ce serveur. +Vous n'avez pas la permission d'utiliser ce serveur comme centre serveur de procuration. +La demande a pris trop longtemps pour se terminer et a été interrompue. +La ressource demandée a plus d'une valeur. +La ressource demandée est allée et n'a pas été substituée. +La méthode demandée exige un Content-Length valide. +La condition préalable sur la demande a évalué à faux. +La demande est trop grande pour que ce serveur traite. +L'cUri de demande est trop grand pour que ce serveur traite. +Le format de demande n'est pas compris par ce serveur. +500 Le serveur a détecté une erreur irrémédiable et ne peut pas traiter votre demande. +La méthode demandée n'est pas appliquée par ce serveur. +Le proxy server a reçu une réponse incorrecte d'un serveur ascendant. +La ressource demandée est actuel indisponible sur ce serveur. +Le proxy server a pris trop longtemps pour répondre à ce serveur. +Ce serveur ne supporte pas la version de HTTP exigée par votre browser. diff --git a/locale/it/cups_it b/locale/it/cups_it new file mode 100644 index 0000000000..228c6a8357 --- /dev/null +++ b/locale/it/cups_it @@ -0,0 +1,123 @@ +iso-8859-1 +GIUSTO +Annullamento +Aiuto +Rinunciato +Vicino +Sì +No +Su +Fuori di +Risparmi +Scarto +Difetto +Opzioni +Più Info +Nero +Colore +Ciano +Fucsina +Colore giallo +Copyright 1993-1999 da di Easy Software Products, tutti radrizza riservato. +Generalità +Stampante +Opzioni Di Immagine +Opzioni Di HP-GL/2 +Supplemento +Documento +Altro +Pagine Della Stampa: +Intero Documento +Gamma Di Pagina: +Ordine D'inversione: +Formato Della Pagina: + 1-Up + 2-Up + 4-Up +Scaling Di Immagine: +Formato Naturale Di Immagine Di Uso +Zoom da Percent +Zoom da PPI +Immagine Dello Specchio: +Saturazione Di Colore: +Tonalità Di Colore: +Adattare per paginare: +Proteggendo: +Larghezza Della Penna: +Correzione Gamma: +Luminosità: +Aggiungere +Cancellazione +Modificare +URI Della Stampante +Nome Della Stampante +Posizione Della Stampante +Stampante Info +Stampante fa e modella +URI Del Dispositivo +Pagina Di Formattazione +Stampando Pagina +D' Inizializzazione Stampante +Condizione Della Stampante +Accettando I Lavori +Non accettando I Lavori +Lavori Di Stampa +Codice categoria +Locale +Periferico +Utilizzazione per due usi +Cucendo con punti metallici +Veloci Copie +Fascicolate Copie +Perforazione Del Foro +Covering +Legandosi +Ordinando +Piccolo (fino a 9.5x1în) +Media (9.5x1în - 13x19in) +Grande (13x19in e più grande) +Su ordinazione Formato +Idle +Elaborando +Arrestato +Tutto +Dispari +Anche Pagine +Più Scuro Più Luminoso +Formato Di Media +Tipo Di Media +Sorgente Di Media +Orientamento: +Portrait +Paesaggio +Job State +Job Name +User Name +Priority +Copies +File Size +Pending +Output Mode +Resolution +400 Il vostro browser ha trasmesso una richiesta che questo server non potrebbe capire. +Questo server non potrebbe verificare che siete autorizzati ad accedere alla risorsa. +Dovete pagare accedere a questo server. +Non avete permesso accedere alla risorsa su questo server. +La risorsa chiesta non è stata trovata su questo server. +Il metodo chiesto non è permesso con la risorsa. +Una rappresentazione adatta per la risorsa non è stata trovata su questo server. +Non avete permesso utilizzare questo server come calcolatore centrale di procura. +La richiesta ha preso troppo lungamente per completare ed è stata abbandonata. +La risorsa chiesta ha più di un valore. +La risorsa chiesta è andata e non è stata sostituita. +Il metodo chiesto richiede un Content-Length valido. +Il presupposto sulla richiesta ha valutato a falso. +La richiesta è troppo grande affinchè questo server elabori. +Il URI di richiesta è troppo grande affinchè questo server elabori. +Il formato di richiesta non è capito da questo server. +500 Il server ha rilevato un errore unrecoverable e non può elaborare la vostra richiesta. +Il metodo chiesto non è effettuato da questo server. +Il proxy server ha ricevuto una risposta non valida da un server verso l'alto. +La risorsa chiesta è attualmente non disponibile su questo server. +Il proxy server ha preso troppo lungamente per rispondere a questo server. +Questo server non sostiene la versione del HTTP richiesta dal vostro 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/locale/translate.c b/locale/translate.c new file mode 100644 index 0000000000..e56690be62 --- /dev/null +++ b/locale/translate.c @@ -0,0 +1,259 @@ +/* + * "$Id$" + * + * HTTP-based translation program for the Common UNIX Printing System (CUPS). + * + * This program uses AltaVista's "babelfish" page to translate the POSIX + * message file (C/cups_C) to several different languages. The translation + * isn't perfect, but it's a good start (better than working from scratch.) + * + * 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 +#include +#include + +#include + + +/* + * 'main()' - Main entry. + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line arguments */ + char *argv[]) /* I - Command-line arguments */ +{ + http_t *http; /* HTTP connection */ + http_status_t status; /* Status of GET command */ + char line[1024], /* Line from file */ + *lineptr, /* Pointer into line */ + buffer[2048], /* Input/output buffer */ + *bufptr, /* Pointer into buffer */ + length[16]; /* Content length */ + int bytes; /* Number of bytes read */ + FILE *in, /* Input file */ + *out; /* Output file */ + + + if (argc != 3) + { + fputs("Usage: translate outfile language\n", stderr); + return (1); + } + + if ((in = fopen("C/cups_C", "r")) == NULL) + { + perror("translate: Unable to open input file"); + return (1); + } + + if ((out = fopen(argv[1], "w")) == NULL) + { + perror("translate: Unable to create output file"); + fclose(in); + return (1); + } + + /* + * Do character set... + */ + + fgets(line, sizeof(line), in); + fputs("iso-8859-1\n", out); /* Right now that's all that Babelfish does */ + + /* + * Then strings... + */ + + while (fgets(line, sizeof(line), in) != NULL) + { + /* + * Strip trailing newline if necessary... + */ + + lineptr = line + strlen(line) - 1; + if (*lineptr == '\n') + *lineptr = '\0'; + + /* + * Skip leading numbers and whitespace... + */ + + lineptr = line; + while (isdigit(*lineptr)) + putc(*lineptr++, out); + + while (isspace(*lineptr)) + putc(*lineptr++, out); + + if (*lineptr == '\0') + { + putc('\n', out); + continue; + } + + /* + * Encode the line into the buffer... + */ + + sprintf(buffer, "doit=done&lp=en_%s&urltext=[", argv[2]); + bufptr = buffer + strlen(buffer); + + while (*lineptr) + { + if (*lineptr == ' ') + *bufptr++ = '+'; + else if (*lineptr < ' ' || *lineptr == '%') + { + sprintf(bufptr, "%%%02X", *lineptr & 255); + bufptr += 3; + } + else + *bufptr++ = *lineptr; + + lineptr ++; + } + + *bufptr++ = '&'; + *bufptr = '\0'; + + sprintf(length, "%d", bufptr - buffer); + + /* + * Send the request... + */ + + if ((http = httpConnect("dns.easysw.com", 80)) == NULL) + { + perror("translate: Unable to contact proxy server"); + fclose(in); + fclose(out); + return (1); + } + + lineptr = line; + while (isdigit(*lineptr)) + lineptr ++; + while (isspace(*lineptr)) + lineptr ++; + + printf("%s = ", lineptr); + fflush(stdout); + + http->version = HTTP_1_0; + httpClearFields(http); + httpSetField(http, HTTP_FIELD_CONTENT_TYPE, + "application/x-www-form-urlencoded"); + httpSetField(http, HTTP_FIELD_CONTENT_LENGTH, length); + if (httpPost(http, "http://babelfish.altavista.digital.com/cgi-bin/translate?")) + httpPost(http, "http://babelfish.altavista.digital.com/cgi-bin/translate?"); + + httpWrite(http, buffer, bufptr - buffer); + + while ((status = httpUpdate(http)) == HTTP_CONTINUE); + + if (status == HTTP_OK) + { + int sawparen = 0; + int skipws = 1; + int sawbracket = 0; + + while ((bytes = httpRead(http, buffer, sizeof(buffer))) > 0) + { + buffer[bytes] = '\0'; + + for (bufptr = buffer; *bufptr; bufptr ++) + { + if (*bufptr == '>') + sawbracket = 0; + else if (*bufptr == '<') + { + sawbracket = 1; + if (sawparen) + break; + } + else if (*bufptr == '[' && !sawbracket) + sawparen = 1; + else if (sawparen) + { + if (skipws) + { + if (!isspace(*bufptr)) + { + skipws = 0; + *bufptr = toupper(*bufptr); + } + } + + if (!skipws) + { + if (*bufptr == '\n') + { + putc(' ', out); + putchar(' '); + } + else + { + putc(*bufptr, out); + putchar(*bufptr); + } + } + } + } + + if (sawparen && sawbracket) + break; + } + + httpFlush(http); + putc('\n', out); + putchar('\n'); + } + else + { + printf("HTTP error %d\n", status); + + fprintf(out, "%s\n", lineptr); + httpFlush(http); + } + + httpClose(http); + } + + fclose(in); + fclose(out); + + return (0); +} + + +/* + * End of "$Id$". + */ diff --git a/man/Makefile b/man/Makefile new file mode 100644 index 0000000000..55c2fbe9fd --- /dev/null +++ b/man/Makefile @@ -0,0 +1,78 @@ +# +# "$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 + +CAT1 = $(MAN1:.1=.$(CAT)) +CAT5 = $(MAN5:.5=.$(CAT)) +CAT8 = $(MAN8:.8=.$(CAT)) + +# +# Make everything... +# + +all: $(CAT1) $(CAT5) $(CAT8) + +# +# 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.$(CAT) $(MANDIR)/cat1/cancel.$(CAT) + -$(MKDIR) $(MANDIR)/cat5 + $(CP) $(CAT5) $(MANDIR)/cat5 + -$(MKDIR) $(MANDIR)/cat8 + $(CP) $(CAT8) $(MANDIR)/cat8 + $(LN) accept.$(CAT) $(MANDIR)/cat8/reject.$(CAT) + $(LN) enable.$(CAT) $(MANDIR)/cat8/disable.$(CAT) + +# +# End of "$Id$". +# diff --git a/man/accept.8 b/man/accept.8 new file mode 100644 index 0000000000..fa379027fb --- /dev/null +++ b/man/accept.8 @@ -0,0 +1,57 @@ +.\" +.\" "$Id: accept.8 380 1999-06-10 16:15:04Z 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 +[ -h +.I server +] [ -r [ +.I 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 380 1999-06-10 16:15:04Z mike $". +.\" diff --git a/man/accept.z b/man/accept.z new file mode 100644 index 0000000000000000000000000000000000000000..6ec1f4f6c884ac0e9bdb3a751ce217d2f7c3395f GIT binary patch literal 905 zc-oVfV_;w{l4=NN*>X=>Px!`@PRTH(A@U z^y;Kyf0Nbq|Ns9AS><-5m22jN6Fkz)P7icy_~-w>v^2|XMReY+r zRB?tm+w;qBb9~pX5&9UcP{G{a_}uaEf`S~j2~8{uCR(UDaR@dkPLQh|KIr;VP7)6wRYJ<+?0GM zt^R+B)uQf$Rb3%kkG^jF_SkFtx7LiEIa@bu`<%ba_;z_ju_jmk1WlnX=3s2L*O;tFp8m zxK!ZNBEak*(IUX=pwS|r&T@ExRsDap)`|y_%6pvVeBIjrZR%yt5Y2#9U2cLq_UhOp zyzyDneCY%IjIhivFaQ5p9lLZ^$g1iuLEk&J9)Etxhkn{>RlkMRd zVb8XG_FrChuc0b%^|}kouPvKtG)?Zq%*hKLez2+GKX%|k2vc8k$3e;ee?5~{9GIBY z_~+|h#b+8G0SoGvsn{IlwSy*{Np@fnbC%XeU2{3f9FeM22ai0JGcvk0jolWA8j`1)wvGzz9 z^P8h4>k2!QgFU9H6SklK|8UE%f>t?UV-%otz(!Z?V=^1h|NkE|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 zc-oVfV_;wk=3-!EWZ>ZA<78n{;NnP5&C4$;F441ecJ&MhPE1M5%q=L@(9|(Bb@cV~ z4+=@osnm6G_wWggEGt(xNy;#`h}gEZbjd{D=F2=9_W%E78L2O1c_!8qJ6}R&ce?)n zZ|k;9(%ev$*vh`GH{oKAm|-(-;&zy5g}l0p=Ed9W%NB}0>bcVV<%-H%3-_$oUKiY$ zqz(rpu^AkEBUj94+dd(Yc}BrAKBGrfV&LbJl;DIfhq?Ha4HUlE za;O_@NqR3fX_c*~pT;>sM(<-vUoWaC{r{KX_#)jduPbBg4do>Z#UJ!dPFi$1h=0p5 z3CrgG#D_YZatEIqJP2cIHjrrMi2r}4>Bysn0y=*@QyUnPymj_)_?t=!UuY`kcGElG zBNV%NLQkYp#8-~SbnX8?zI$HeDsqj^-F6!VEpn(h;`zv1XaE1t3ad8M379Ih_0ITr-|NozeEA8B1moW9{ z&WVjDHx&UzZp;d@a1imm+Zqt?N=DdGMWglqzay6>-dH=qRl?r)9Ya)L@w4ZXpM(Wx zS)R@^sJ*!*BbTi;AW%vvRU%g^RxDS#{{N;KbJeD*YE4_k_%&c@uxYSpK&Wj<)yh+g zvKD$RzUmjMuqtmAgLtBdfK!LGTmQm`C1SB+sS;kD;;s`HDTau`4VZYPd{?|t?~_Bl zmL}3NKip@!J$}$-P$wZ0!8=pjF0az&(k7tdvn#q!&wCQ&xMJ()X?rzxel9-wNn3NP zjAc>gtxU&1r_6Of=eWlIf1mT`1W4}Z#Fhsq6u2M0?U~E|<6wegUF7eF2Q_!`PusEW z|Nlw8$^FHC5B{Y}Z{k?AeU2u(?VeMnKqD-duQgGB(|o?r|1VdYqxYtkU)jYeL*x$E-EGzlJq2;u9NM-QGnyJ`RbYoB+h+*p^_ z{6zosye+D{Czdn^WHmK_^n!9)H}TszSWJiqCy;1`&qtU$ zS^xhPSGt(feE5lijEC<3f87%^c24!&B*3R4?xk0ATar6PuA-q(VaJEVyk{Ffv#irS zF4H~lrJpu1(#{DoENxl)axFtlMPl32eYu^llMC8T9=YFQ=F>fC_JZFVzu5E&8ujol zxUh>`ubcUT4C?}ssY3hzA3vzHvCwGpFlYLm9b2yC6Iy2FoYR zBO$L&ST3Jp`5h?Y6S(5SgvMYaNyf$i5pl-kgq;8Xs@}RScG&rPt5k2&@9JO%v#*xF z@}lMa_WIacipE|&Go7{Fp&*5gzwwDeV?o3VnHX{V|5t()yIQ5$7IRz)tBt;P)HXL^ zwy6F8`Rwb&3$q~N;q5;*?{Vfox^SjgO5lXY3PM2g4UoT^|4h52NQ%aZ&5FyM4SAgH z*1k?^J^%lGbcEVbpN0#}yp2l_CMzW5u=O<_QD~GUI zUoN`wtMqMIk=E|jY%~A=`C(hIyE{bVhN*uknl_5a1**c-_Jy|Gy7OxsMJBkDlqyJ~-5Snsv&ir?1QEl*c|sZ-j%a4*-} zx4u^P+gEh?>`|9_rsm~?VV(Y$RNq(5os{rNgc)o;Jbv!#2vPHX2c z*}&P9d2QRK=l?&7h!sh%;MUk4_C>om>d(^4+qW;^br-44cUrf3)+DdQZ@fk^VrFc; zjXOeE86WV)h}p59|NqM3mG2`bR;Hh)60dYjD0JArXa<;^)$f@jB%mSwC3ySFM~+9C z&i{Y6K&`K0LZicu1CC6eZh1b^Dou1>vQ6*aQ`>b6;;k!NMS4!0kg#K)(8PE_Mw)T) zf&zX93qb})31$2LJz1$Sn=4f+c~6 z!+hEA{QoB%?#FWR!DVAOFydqQuvHYO*Qx&hF;kUUX9OfHn4ZXNv&~VT7IxpW9++)@ J*qmu70002IwnYE{ literal 0 Hc-jL100001 diff --git a/man/filter.1 b/man/filter.1 new file mode 100644 index 0000000000..51d494d987 --- /dev/null +++ b/man/filter.1 @@ -0,0 +1,95 @@ +.\" +.\" "$Id: filter.1 327 1999-05-14 17:03:06Z mike $" +.\" +.\" filter 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 filter 1 "Common UNIX Printing System" "14 May 1999" "Easy Software Products" +.SH NAME +filter \- file conversion filter interfaces +.SH SYNOPSIS +.B filter +job user title num-copies options +.I [ filename ] +.SH DESCRIPTION +The CUPS filter interface provides a standard method for adding support for +new document types to CUPS. Each filter is capable of converting from one +or more input formats to another format that can either be printed directly +or piped into another filter to get it to a printable format. +.LP +Filters 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 file +format. +.LP +The command name (argv[0]) is set to the name of the destination printer. +.SH ENVIRONMENT VARIABLES +The following environment variables are defined by the CUPS server when +executing each filter: +.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 filter. +.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 filter (typically root). +.SH COMPATIBILITY +While the filter interface is compatible with System V interface +scripts, it will only work with the System V interface script as the +only filter. Typically the interface script will be provided via the +\fBlpadmin(8)\fR command using the \fI-i\fR option. +.SH SEE ALSO +backend(1), cupsd(8), +CUPS Software Administrator's Manual, +CUPS Interface Design Description +.SH COPYRIGHT +Copyright 1993-1999 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: filter.1 327 1999-05-14 17:03:06Z mike $". +.\" diff --git a/man/filter.z b/man/filter.z new file mode 100644 index 0000000000000000000000000000000000000000..44203947c5d439ff1d54a7683203cfcc9e09a88f GIT binary patch literal 1683 zc-n1LeLT~79N)~t{Fssqbb-(|9ug~}O`Mf{xhtDb)g@VTQQD_tf zt80LTwDnNt&^O;=qZ3oo(zEt50ywd838@)5@4O=@lDp4_ zLiP0a@n^C3+ijtTMI>+9?BM7U91@z8nY-?E<aMHv_;#;KE3p#-oy&bN?YsI}09&dkOp0=lBstjQ9 zQ-X(-7;~H??jiSqPjBIF`-aqp7eQJy^rm$ug|zmto>IEjbj)WOI|7M z9CzS?v@gmVLXs+QLD3Bw7q)NE6fzzXqPq1h&RSMcq(om&J~>m%5EjpY4_4Ma+Qj&p zp5JMl%c9(SP2_FP{J`wjQrTqZ%!)Rc%NuhCjT5KF&-m3iAR>J1&>I|y4KXD=g)4)m3kaOy!_AE?DXQ2u`p6a*g&39MDNuBFuivM zD&{>A%(gAhxwP-$Mu=b8?5CeS_;~MX`bfY+S3dAP#vEChu6jOfqW{imYUR)CgIgC5 z-XPnnT2mVrgkGHTQn^{iSi!1DwP=^s5~+P%XHZOK$4b zbS!Pob9ge(qsoRyvz~B!tyrCpnth!p^=8hcGjrhMV%_e%<(ltSbrmpK)Y88CVUwC3 z6$0;N-~f19-uT;D!6)MQS%a51XqPZrH&{5+iXmMk zpk7~)HZS7{4p5xSc@_1Md|Q3Clj1-|o^lVji{)rg zIG-5C5pavt>HDJfE8a_=ixmRX?VcJ6VrU6b99!j+#n&KUN#f3Kj1D<-4PJ-5(j64U znhq~guOq|YrHixYmuEK!->0k{zV#?U4JRW7d|oPq?>LN?6}Inzd#>`TYvA|jgYX^N z3^ZpfeBg#$u%T%Q{8RF=D>1>BUBzLeiaF!}LT`NQZn0EImRf#eV38}wmfjw+x4t!` zdOGd5%ph99C3Pd|Q97=%lG;p?1Qju-CMnb-XoU`5?3O&}mFAKUtcjHR1l9^sfzlzD z)hi3^6WApc3mK!KMTZIc_H;w0F8EY^Pvb=|Ru`{5=Xc)t2>N#6bwroAZHvpot%+GS zdo42}ZlchnjcEvk{w7fhQsn%YjZvjWRhK|pH5JHW?XC|k33i8$63@!}b&Qxs{UnG% zCW_c=@U@`F)#^#t(LHzq0oA2JJ#?rw@xOu`H6yA%5DC-?cTgcwU?gJ!4*&D5Hg_Yo ky($-pn!)QbujL*3Fa?9SzMXO*Ci9v%qB7_t+%3TV17SrchX4Qo literal 0 Hc-jL100001 diff --git a/man/lp.1 b/man/lp.1 new file mode 100644 index 0000000000..57dfb52e80 --- /dev/null +++ b/man/lp.1 @@ -0,0 +1,71 @@ +.\" +.\" "$Id: lp.1 491 1999-07-07 14:03:48Z 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 lp +[ \-c ] [ \-d +.I destination +] [ \-m ] [ \-n +.I num-copies +[ \-o +.I option +] [ \-p/q +.I priority +] [ \-s ] [ \-t +.I title +] [ +.I file(s) +] +.br +.B cancel +[ \-a ] [ -h +.I server +] [ +.I id +] [ +.I destination +] [ +.I destination-id +] +.SH DESCRIPTION +\fBlp\fR submits files for printing. +.LP +\fBcancel\fR cancels existing print jobs. The \fI-a\fR option will remove +all jobs from the specified destination. +.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 491 1999-07-07 14:03:48Z mike $". +.\" diff --git a/man/lp.z b/man/lp.z new file mode 100644 index 0000000000000000000000000000000000000000..1d45c15750bc8715997259da6c3c09523d3e69df GIT binary patch literal 836 zc-oVfV_;wv=4N1IWMXIImufTRHXrP94#b^FCv(KIx3+SxwX6SkuqprkjI-q{+{~7^3y}}ZwQMm^ak$Ace^o5**|}70Rra!(^8e4)Ts@m}1w`6qr_D4i z_DXrg@P*H;*KC$i56{Bp6^}$3rCds7?E1ME7XJUOEwCa_h+k*>Zmn&aH-j%;aLui{ zr64Hy|L2t_SGH|=RkUhmBq)rm15ER(ZYeJ4y7fn_qPoeZqibL0F|mt|_$qM5Fiue0Jd-x3rs>XCPE4Ok@7uuG>`$*PYz zz~GgIsH5|WMDS-s~gwlSCpM#pXI$OE!Bh)YO0+|@~Zlm~Lz z#Qy)cCY>t#{JB5-(zchGwJc%Rm)Lfl6ZF!weB~Zs@>Jo^C8lG%U$!i%|K}1Rp)7V> zjuou!(xsVayytFJo$^*=b#CUD@7JHJo-#a@J?(3=h#)ZLbEV9Bk6uhz#bq|juD}2P zjpljNo4c483mcd4p0!zhzV?rH-e&6rn&GeX21AEli`(&q%(Wqfi4b~3!YML z_WvcSST9C2bboYIRFG_Ha&jv8^yA8oeVI?=)TV?^aQW2aZhIgmTJmAHfME6F{~wN8 ydNhj!D4_vXh8aQLkARx%{~wc!*!cFa({YBKKrgOcB)Rm?S20i`{}?F1-~a&r@rd^T literal 0 Hc-jL100001 diff --git a/man/lpadmin.8 b/man/lpadmin.8 new file mode 100644 index 0000000000..fc492b1f88 --- /dev/null +++ b/man/lpadmin.8 @@ -0,0 +1,124 @@ +.\" +.\" "$Id: lpadmin.8 461 1999-06-24 17:44:19Z 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" "22 June 1999" "Easy Software Products" +.SH NAME +lpadmin \- configure cups printers and classes +.SH SYNOPSIS +.B lpadmin +[ -h +.I server +] \-d +.I destination +.br +.B lpadmin +[ -h +.I server +] \-p +.I printer +.I option(s) +.br +.B lpadmin +[ -h +.I server +] \-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 +\-m \fImodel\fR +.br +Sets a standard System V interface script or PPD file from the model +directory. +.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 +\-D \fIinfo\fR +.br +Provides a textual description of the printer. +.TP 5 +\-E +.br +Enables the printer; this is the same as running the \fIaccept(8)\fR and +\fIenable(8)\fR programs on the printer. +.TP 5 +\-L \fIlocation\fR +.br +Provides a textual location of the printer. +.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. Finally, 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. +.SH LIMITATIONS +The CUPS version of \fBlpadmin\fR does not support all of the System V or +Solaris 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 461 1999-06-24 17:44:19Z mike $". +.\" diff --git a/man/lpadmin.z b/man/lpadmin.z new file mode 100644 index 0000000000000000000000000000000000000000..c7b0c61cb48b0c0d86e2e90324dbb18e8f526218 GIT binary patch literal 2514 zc-n=Qc~sKr8pmP+F-*-&C2!-NxeOs%E@hiTwy1%UnpUpC zXqNkOymL()%_S=|ld?urb9BtIMeAt(?)z)%o_o&ycZ zb{7bz?EiqE`!u{MTU$L9i$w888gw)pZSCZq(C3>a#WLTDY-zIrrmG8+6su%61q-AV zVz0p-k5hdV%qU_KrN^7Aw2e(S8PlSSrz}V2C0)D1a`)_uqiuYA%D0#jFYk54wimuK z%~^BaN=P&de5S|yh>{BA!!*}QQzo?Z#CCzUNt9olKb^R@T(#;)-fLk_yla|kucP(m zRVk=sN9?qz$AX^q%;*zTGEF|+Zzn*Ez*)1x$Echnp)^h|LuxdV z?Boo}Naso|3MKgBx-mxMT)H()F3+c$LwT>RO_nP5X2lllVaFv{c?y1T5&c2SDwiaB z`>&M>^-B@bT z=Fqk7eLZ$HxPiK&hZ#_3?)HE!4U&4(ir;$kv-A1hKFa#}kO@`we(;*2BTDCvTp+|t-qh!7NMf{>nyunMu3)kuM6$bpLjXEos|8zuA`!;Z)b$s zLUq^F1S`t8wCtrIqDk{X*j|2V1Dm55$bjwx-(i?Sg{7rbx@(ZAFf9^gEtQg#}c|>|?k}@qg+dg_hCM1Ys2HVqrhbL1UcG+d2a{ zs~V$3KkB<88J!v#t`twW#bjM(Ld#Q!+yCr8qOG(fvDu2ET4}l_$+gDl_%_^`wZs}G ztjTK!WK_&)w`87H@;z!XTjXlPPE`5HqbePgR&49Zq%(K>P&&M-S*PHOdc3!jDEY8c z8|7J{gOwFvMB1`7hLXW?WdlZKc ziVKSmdHb@kqZop|0K0sdk8ZRy+tX{Ml~)y&fMQ8~IG}kSf$`LNjtR1$MYYt`*zfdW zq369S{j$0ZCAKgc#f`CrPf*@Y@;sn>u0OiJUQr}!t7_-+ns$)$6$az8Da!;mc%HNuPNQ=YgsV|>)65TlOI)-$ z0dr<3l=1^#p}ncdc-O(J^&Y2m3PR^Y;Cl7yVsSYC9T3#9MxL!_{nFzjYPXa8ybz1J zmpIkT|5NGZe(iSI6gHB&ZD&b8^RtylNeTp|xou*<253hHDq{j@>t6NTTQNe=99jEq zp*gayfF;PEbh}rJMbZ(@Mu?Er6wIm>8Y#;rHR=9$j`3QxFNG4P=#-b_CP$DNbQek2 zKf5lG?T}@ty#lOt-I!yNfV5KarJ!yMrvZZA?_n{#PP<^4a1nJz!62NF--4O&ts)Y+ zH=B@3^{d%reAaQrV|c6p-+W<;JPw1@+wddM{;<#h*rX!IM*^X9X*r)&k=blAcVxaKUn!+v9}8CO?l(; zGBY5DH_ZTH21)GmlBrp`y^F=Gimc~k|DKty2cg7?(_kk2t~>fbxE(D$0+bI>@4SNz z>g=)&a1)IAJVOJFJAfSzGgJ0L+r|7oI<9LWeVwt%`qEt+pt;eXtXoKf6?*WPv;BHGPO}uxNd@ku&9C3! z$(K3V_LXN#0BtH$EL#O8rN$CIC(UiWn@{!o1O3Avn%VsHSlN_&#rS2#Lmj0!GpdFR zu7fEb5lhlQBOl5e^6|b-1g_l*fNK%}I(AosWdaQ4asV^>@y;IF@u_fw~d zF7HsM39U1=(RaaYONUnDu~;GM$USH&LHvtaM|ykdrP6Z0gvyB7!~i^%K^^#T)5mL~ z`AQPgEKzwv%=vg_KBO3$`&!Sx!l+@TS;K&rtPQn5NSFVGLc^6DKVP}Atr{PSMA(o0skr4+RQed8akBcNAY8L$?Dsm4k0v02BfDsbTu@%+dCQ`o;j=1 zhcX#M2vreAC$Y0MbLbb+J5r(1W_8t5&Z-3c6&k8ls+7b240QDjhm;>_?5P@kBbn5n zY)ZG_dP1KZxFkbSY9ZXM*zX@F_0?O~YPcgcR8JiQ;l?BtW@u~GU_W-VM><@8xWC^T JAe|A;{{|^h!Oj2x 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..ad563e3ebc --- /dev/null +++ b/man/lpr.1 @@ -0,0 +1,96 @@ +.\" +.\" "$Id: lpr.1 491 1999-07-07 14:03:48Z 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 +[ \-P +.I destination +] [ \-# +.I num-copies +[ \-l ] [ \-o +.I option +] [ \-p] [ \-r ] [ \-C/J/T +.I title +] [ +.I file(s) +] +.SH DESCRIPTION +\fBlpr\fR submits files for printing. Files named on the command line are sent +to the named printer (or the system default destination if no destination is +specified). If no files are listed on the command-line \fBlpr\fR reads the +print file from the standard input. +.SH OPTIONS +The following options are recognized by \fBlpr\fR: +.TP 5 +\-P \fIdestination\fR +.br +Prints files to the named printer. +.TP 5 +\-# \fIcopies\fR +.br +Sets the number of copies to print from 1 to 100. +.TP 5 +\-C \fIname\fR +.br +Sets the job name. +.TP 5 +\-J \fIname\fR +.br +Sets the job name. +.TP 5 +\-T \fIname\fR +.br +Sets the job name. +.TP 5 +\-l +.br +Specifies that the print file is already formatted for the destination and +should be sent without filtering. This option is equivalent to "-oraw". +.TP 5 +\-o \fIoption\fR +.br +Sets the job name. +.TP 5 +\-p +.br +Specifies that the print file should be formatted with a shaded header with +the date, time, job name, and page number. This option is equivalent to +"-oprettyprint" and is only useful when printing text files. +.TP 5 +\-r +.br +Specifies that the named print files should be deleted after printing them. +.SH COMPATIBILITY +The "c", "d", "f", "g", "i", "m", "n", "t", "v", and "w" 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 491 1999-07-07 14:03:48Z mike $". +.\" diff --git a/man/lpr.z b/man/lpr.z new file mode 100644 index 0000000000000000000000000000000000000000..0a611435cac569a06692fc1a1fdec25673cb6302 GIT binary patch literal 1451 zc-nPTX;70_6itYb5D+PZAc&Bp$_@rdEHXma4e6&SU|1qHi9lF_L>2`)Kx9)0o25dq z!xC`9P(Z}kj0i2VL{X5XKvZlM9jQRkTEkct;q{C9qvK59k2`P9%)RfNbMLzr<_Ls# zxh?{U*n&oH)j?y?2m%Hho%#(Y?qpJON^n$6EI&~|vUhNF3OF3XJ;6)Mu(sLf<>PlK zkQI3bIv8{`JpS|^GR52X0G$zb>Pu%AH~;iZtD4FQf$MlV0N{;c{}tB3P9wL@*Kq~f zEEoaq#;8(EO~u2lSYd;&28!UE14G>9WAfwiW6dMgnz^(19Z1QznFqRBv+S&*F9oc= z$s~&;Pb@?hQe7yBvmk;T$b+-FQ)bnMTQ=m1*)rw5vAl`= zNWI?~P8+omj;uXY-W1qOxO9%kTo2X_E>R9L!tPeg>sg?NypZFrZm2vq<%VMpAf&}y zSIv;*hBKw@ZQ0Gt#a+Mh!_ZC6yHjSDImSN1U1Q++orOF@oH&y^sRKEYFDs;YaXhCI zfKB(|=w2#s@;_1pck6*dxRV?}p6a(LklK(};r=?dZ`87|1pnIWzf~TIq{-*I_&pD( zx=D$*g$>r~gaWu*II)*gFkCZ|weEKH1brz8=gb3tvyY3poPc~oBN_m6)4j4*ElQb! z=wq1!@IGoT{o2L#0K8p%`e-`O^Z>U)Qb_|Mj~oDo{fq3UC)f9dKALWvy9T!;^Xa1d zR10L1Io5>HM7|*%h_`Px& zYYoM)H*H#|ete2FGlwZMaRHx=(&zk2;0jfx2H~yE?~*%Yt$xGNtF0bCzobb1$S_q! zyf8ZB9|*uo@zP(RJ#!}hyr7b1uAQvgO=gs8_mjl?qXo9GlBofABf}1kFJ`hZ162jo zWR#$R(%AQ-M@`OS9;}2eZ(QuQ6;%xzwiG60E6qc#*C>*eqN)4F4pnl)*Fx$T0Px#& zYC}(|?V4!(nwkn^7jt-_o%ADhaHe`@pQJF%c^6t>+Ro*zP1GH!uRi22EqX=`9n(DL zDIg(Hv*{t4`njkE!8U~Jyct>u2XBnVtT7E#xb*}ONj(9%e%ylwb_Ni=jWJj}*szPa z8%Fr_Hadmg4!IbRU~6CrooltM9pBy~i6T>Z7wn#~C39MynbTE|Tv_13sOGBQ#pI(s`G_6QW(%q7nxo^P2hPl2o% zPhn(r{)Sns?+Dl=H9PUGB!QVlN?CGwlNMC1S?I}*(&8M(p@sVdVX5dq@Z$UakaXAa zv*Gi3r5K|+(JQ7Ng}}sP&5wWBR9Ax+ZXw?5OL0e3L;-#$a$q*y@#7A-1tAF`NMAxe z*u+mUx}rvVO$`hX3N`Pcivzf~U5R@KLl*CJNpZWAj0()NwZmQ7Rba)k{*cy0o@LDc q9Dm_MqTeYAkw^p261}u!np$Njr`Ie8zE#!Hf9PttD;hNw$bSKINVqlt literal 0 Hc-jL100001 diff --git a/man/lprm.1 b/man/lprm.1 new file mode 100644 index 0000000000..03b06eb3a5 --- /dev/null +++ b/man/lprm.1 @@ -0,0 +1,40 @@ +.\" +.\" "$Id: lprm.1 327 1999-05-14 17:03:06Z mike $" +.\" +.\" lprm 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 lprm 1 "Common UNIX Printing System" "14 May 1999" "Easy Software Products" +.SH NAME +lprm \- cancel print jobs +.SH SYNOPSIS +.B lprm +.SH DESCRIPTION +\fBlpstat\fR +.SH COMPATIBILITY +SOMETHING +.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: lprm.1 327 1999-05-14 17:03:06Z mike $". +.\" diff --git a/man/lprm.z b/man/lprm.z new file mode 100644 index 0000000000000000000000000000000000000000..40f8c05b5d993b28c55fd14b51dc5762f93f80b4 GIT binary patch literal 414 zc-oVfV_;zN;bLH9Vqg~F;bCV`;NbEME-|!pcJ=cQ2uV!M$;~e)D%Q}{arE&GicHST ztJHOJarX#KN=ZvEEmzkwHi^i{D%-YVH&=&-|NsC0pDj6Qdz#J0R!#UqV#0<;{OLfk zE3vIEB5JovEMmmWc+I5i{|A(HlM5qFbbxrFlyVCmg&`oE*@hESQt|;qyX>^v#}qwi=TkzcrGmvB{BYaflJ? zaoxCJgXqS^3dfEu7L;ed|Nl}YD~x)M8m$wwe(hEVf%9f=QLX83canlb1+4pNbsG;Jo2om`7Ujhq!rA$obWNOO)}~X(}+ySx((ybT9O)R-p}WKpZoKCpXdFGj6!V>!=uos zEwZu%IawJThJy2tj*;{B2?`63GV=A~g+zR_TTkE6*wOho*E1mW+xUIvw)PAb=j*`O zV}E12o(zsOIbe6xU3dQ>ha=1raTacTCi{#U{}$z8D*y}Pfl~buQW;(ejdI6)XTv@Z=yLTFUMVBbA2a0M4D*IMFGqLRj7*FF@*<9krtq*bZSFIg zRUw4J z7>dRS+u?AF3it6gbTC4TrAyuqCp@)P;7D<57Mw z4Vu*3s}VS+&WMqhL)WT;kpe{op5bU@$=Bsonb7D>5>%F3vVyMGa_o(7o8#}nkON)8 zsW80I{@Ir-RKTjw>UQVk@;7NTlB6Dq2{X32k;BkO<)SfVdS?~3334sbooxgCW+vFJ zZT)xUu{IjkKqOm^Kg8G+b`)FH4{akFQq?~Mw=X#zk9z@!J00N z)BmYHc_80Udf;XttCGEVbw{AndKXu7j0NU{(kns)nB!oT-$hg8(48OIyAr?Dq{^@c z;AL+l^OHqlfQBBIq_x6tk~-PWhxROZm}K=o4l=4?0r0zmZqu(V;Uc;)iq~-sEIsa`;W=c9M}<%oc0|aa$tXd)kINlBo5v`Ok)mW@uknvlwX-M$foK11>v(0It-(+y;NMZeX>W+DyrDjJc5gX!Pmo~-= zC;bNac+Xy!f(S%^JeNa4k~Kn_B9G9L4#$d2v_c=IM~=SeHahs?+SVcY!!D&y=4WTO z?MwZEI{k!8f@8B+fh%yJU^w9O>zDS72a1wQc6$6`?O;}USjQR^q}l$7m;doTL(gtX zJTn%aZxJ$kzG-9Fd-R`f+$os+(z7%X^;HRMbVFx4zVq_fzmPW04XyrechraK_#^aC zCvNVu-u(LC4o!#vSbS|J_9qlucsG6WO#Dyv>%s@b`fP%FKG^Wo1z;_{SKkZ4Febx< zAMcVt@|h{>OplFuf1<{5x?86r@fy?_z3%H463v)f9(8-CgP?hnd+d{iJJ8i`_n(Cs zAi-z68j5eyg$Wrvq!fP8gHpqD&DYc)NsC}A%YO8WIOzi z?8Mqr_Nt&DJGh{El>R4+v+*8Hx`OOYI%6O*nGbET>2sF9sa7MGfd$^4G_M&ioE{q) z4>f=rKSVk^t=V{^=gJc1X#O6u8AaP*Xz)1rc-n@rA7@pv2LTCU0FOky-*kOTY`Z7n z?)^tkudv7bYpswqO4Bk+?p11%_btBN(7dw354s+Icd0&#h2ELlU|y+wX~B|)NiH+M z2?V=QNeh<7m_e|b8FV==*T-(TUm36GrHs?GCQqJl2`^D%FUYv7g)#!gyY?#YK>LdD2fRRoqJ2^73lubCTBg25#C2 MZfi13HtO`h0k$vHHvj+t literal 0 Hc-jL100001 diff --git a/man/mime.convs.5 b/man/mime.convs.5 new file mode 100644 index 0000000000..93e530312f --- /dev/null +++ b/man/mime.convs.5 @@ -0,0 +1,36 @@ +.\" +.\" "$Id: mime.convs.5 327 1999-05-14 17:03:06Z mike $" +.\" +.\" mime.convs 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 mime.convs 5 "Common UNIX Printing System" "14 May 1999" "Easy Software Products" +.SH NAME +mime.convs \- mime type conversion file for cups +.SH DESCRIPTION +.SH SEE ALSO +classes.conf(5), cupsd(8), cupsd.conf(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: mime.convs.5 327 1999-05-14 17:03:06Z mike $". +.\" diff --git a/man/mime.convs.z b/man/mime.convs.z new file mode 100644 index 0000000000000000000000000000000000000000..27c4895c70d3cefe447fd41f3eaa2278fb8a9367 GIT binary patch literal 432 zc-jH50Z;xP9smFWQwjh90RRXM5D5hUAPNX&X>M<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>setpagedevice" +*PageSize Legal/Legal: "<>setpagedevice" +*PageSize Executive/Executive: "<>setpagedevice" +*PageSize A4/A4: "<>setpagedevice" +*PageSize A5/A5: "<>setpagedevice" +*PageSize B5/B5 (JIS): "<>setpagedevice" +*PageSize EnvISOB5/Envelope B5: "<>setpagedevice" +*PageSize Env10/Envelope #10: "<>setpagedevice" +*PageSize EnvC5/Envelope C5: "<>setpagedevice" +*PageSize EnvDL/Envelope DL: "<>setpagedevice" +*PageSize EnvMonarch/Envelope Monarch: "<>setpagedevice" +*CloseUI: *PageSize + +*OpenUI *PageRegion: PickOne +*OrderDependency: 10 AnySetup *PageRegion +*DefaultPageRegion: Letter +*PageRegion Letter/Letter: "<>setpagedevice" +*PageRegion Legal/Legal: "<>setpagedevice" +*PageRegion Executive/Executive: "<>setpagedevice" +*PageRegion A4/A4: "<>setpagedevice" +*PageRegion A5/A5: "<>setpagedevice" +*PageRegion B5/B5 (JIS): "<>setpagedevice" +*PageRegion EnvISOB5/Envelope B5: "<>setpagedevice" +*PageRegion Env10/Envelope #10: "<>setpagedevice" +*PageRegion EnvC5/Envelope C5: "<>setpagedevice" +*PageRegion EnvDL/Envelope DL: "<>setpagedevice" +*PageRegion EnvMonarch/Envelope Monarch: "<>setpagedevice" +*CloseUI: *PageRegion + +*DefaultImageableArea: Letter +*ImageableArea Letter/US Letter: "18 36 594 756" +*ImageableArea Legal/US Legal: "18 36 594 972" +*ImageableArea Executive/Executive: "18 36 504 684" +*ImageableArea A4/A4: "18 36 577 806" +*ImageableArea A5/A5: "18 36 403 559" +*ImageableArea B5/JIS B5: "18 36 498 693" +*ImageableArea EnvISOB5/B5 (ISO): "18 36 463 673" +*ImageableArea Env10/Com-10: "18 36 279 648" +*ImageableArea EnvC5/EnvC5: "18 36 441 613" +*ImageableArea EnvDL/EnvDL: "18 36 294 588" +*ImageableArea EnvMonarch/Envelope Monarch: "18 36 261 504" + +*DefaultPaperDimension: Letter +*PaperDimension Letter/Letter: "612 792" +*PaperDimension Legal/Legal: "612 1008" +*PaperDimension Executive/Executive: "522 756" +*PaperDimension A4/A4: "595 842" +*PaperDimension A5/A5: "421 595" +*PaperDimension B5/B5 (JIS): "516 729" +*PaperDimension EnvISOB5/Envelope B5: "499 709" +*PaperDimension Env10/Envelope #10: "297 684" +*PaperDimension EnvC5/Envelope C5: "459 649" +*PaperDimension EnvDL/Envelope DL: "312 624" +*PaperDimension EnvMonarch/Envelope Monarch: "279 540" + +*OpenUI *MediaType/Media Type: PickOne +*OrderDependency: 10 AnySetup *MediaType +*DefaultMediaType: Plain +*MediaType Plain/Plain Paper: "<>setpagedevice" +*MediaType Bond/Bond Paper: "<>setpagedevice" +*MediaType Special/Special Paper: "<>setpagedevice" +*MediaType Transparency/Transparency: "<>setpagedevice" +*MediaType Glossy/Glossy Paper: "<>setpagedevice" +*CloseUI: *MediaType + +*OpenUI *InputSlot/Media Source: PickOne +*OrderDependency: 10 AnySetup *InputSlot +*DefaultInputSlot: Tray +*InputSlot Tray/Tray: "<>setpagedevice" +*InputSlot Manual/Manual Feed: "<>setpagedevice" +*InputSlot Envelope/Envelope Feed: "<>setpagedevice" +*CloseUI: *InputSlot + +*OpenUI *Resolution/Output Resolution: PickOne +*OrderDependency: 20 AnySetup *Resolution +*DefaultResolution: 300dpi +*Resolution 150dpi/150 DPI: "<>setpagedevice" +*Resolution 300dpi/300 DPI: "<>setpagedevice" +*Resolution 600dpi/600 DPI: "<>setpagedevice" +*CloseUI: *Resolution + +*OpenUI *ColorModel/Output Mode: PickOne +*OrderDependency: 10 AnySetup *ColorModel +*DefaultColorModel: CMYK +*ColorModel CMYK/Color: "<>setpagedevice" +*ColorModel Gray/Grayscale: "<>setpagedevice" +*CloseUI: *ColorModel + +*DefaultFont: Courier +*Font AvantGarde-Book: Standard "(001.006S)" Standard ROM +*Font AvantGarde-BookOblique: Standard "(001.006S)" Standard ROM +*Font AvantGarde-Demi: Standard "(001.007S)" Standard ROM +*Font AvantGarde-DemiOblique: Standard "(001.007S)" Standard ROM +*Font Bookman-Demi: Standard "(001.004S)" Standard ROM +*Font Bookman-DemiItalic: Standard "(001.004S)" Standard ROM +*Font Bookman-Light: Standard "(001.004S)" Standard ROM +*Font Bookman-LightItalic: Standard "(001.004S)" Standard ROM +*Font Courier: Standard "(002.004S)" Standard ROM +*Font Courier-Bold: Standard "(002.004S)" Standard ROM +*Font Courier-BoldOblique: Standard "(002.004S)" Standard ROM +*Font Courier-Oblique: Standard "(002.004S)" Standard ROM +*Font Helvetica: Standard "(001.006S)" Standard ROM +*Font Helvetica-Bold: Standard "(001.007S)" Standard ROM +*Font Helvetica-BoldOblique: Standard "(001.007S)" Standard ROM +*Font Helvetica-Narrow: Standard "(001.006S)" Standard ROM +*Font Helvetica-Narrow-Bold: Standard "(001.007S)" Standard ROM +*Font Helvetica-Narrow-BoldOblique: Standard "(001.007S)" Standard ROM +*Font Helvetica-Narrow-Oblique: Standard "(001.006S)" Standard ROM +*Font Helvetica-Oblique: Standard "(001.006S)" Standard ROM +*Font NewCenturySchlbk-Bold: Standard "(001.009S)" Standard ROM +*Font NewCenturySchlbk-BoldItalic: Standard "(001.007S)" Standard ROM +*Font NewCenturySchlbk-Italic: Standard "(001.006S)" Standard ROM +*Font NewCenturySchlbk-Roman: Standard "(001.007S)" Standard ROM +*Font Palatino-Bold: Standard "(001.005S)" Standard ROM +*Font Palatino-BoldItalic: Standard "(001.005S)" Standard ROM +*Font Palatino-Italic: Standard "(001.005S)" Standard ROM +*Font Palatino-Roman: Standard "(001.005S)" Standard ROM +*Font Symbol: Special "(001.007S)" Special ROM +*Font Times-Bold: Standard "(001.007S)" Standard ROM +*Font Times-BoldItalic: Standard "(001.009S)" Standard ROM +*Font Times-Italic: Standard "(001.007S)" Standard ROM +*Font Times-Roman: Standard "(001.007S)" Standard ROM +*Font ZapfChancery-MediumItalic: Standard "(001.007S)" Standard ROM +*Font ZapfDingbats: Special "(001.004S)" Standard ROM +*% +*% End of "$Id$". +*% diff --git a/ppd/laserjet.ppd b/ppd/laserjet.ppd new file mode 100644 index 0000000000..20e0b9d78a --- /dev/null +++ b/ppd/laserjet.ppd @@ -0,0 +1,172 @@ +*PPD-Adobe: "4.3" +*% +*% "$Id$" +*% +*% Sample HP LaserJet driver PPD 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 +*% 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 +*% +*FormatVersion: "4.3" +*FileVersion: "1.0" +*LanguageVersion: English +*LanguageEncoding: ISOLatin1 +*PCFileName: "LASERJET.PPD" +*Manufacturer: "ESP" +*Product: "(CUPS v1.0)" +*cupsVersion: 1.0 +*cupsManualCopies: False +*cupsFilter: "application/vnd.cups-raster 0 rastertohp" +*ModelName: "HP LaserJet Series" +*ShortNickName: "HP LaserJet Series" +*NickName: "HP LaserJet Series CUPS v1.0" +*PSVersion: "(2017.000) 0" +*LanguageLevel: "2" +*ColorDevice: False +*DefaultColorSpace: Gray +*FileSystem: False +*Throughput: "8" +*LandscapeOrientation: Plus90 +*VariablePaperSize: False +*TTRasterizer: Type42 + +*UIConstraints: *PageSize Executive *InputSlot Envelope +*UIConstraints: *PageSize Letter *InputSlot Envelope +*UIConstraints: *PageSize Legal *InputSlot Envelope +*UIConstraints: *PageSize A4 *InputSlot Envelope +*UIConstraints: *PageSize A5 *InputSlot Envelope +*UIConstraints: *PageSize B5 *InputSlot Envelope + +*OpenUI *PageSize/Media Size: PickOne +*OrderDependency: 10 AnySetup *PageSize +*DefaultPageSize: Letter +*PageSize Letter/Letter: "<>setpagedevice" +*PageSize Legal/Legal: "<>setpagedevice" +*PageSize Executive/Executive: "<>setpagedevice" +*PageSize A4/A4: "<>setpagedevice" +*PageSize A5/A5: "<>setpagedevice" +*PageSize B5/B5 (JIS): "<>setpagedevice" +*PageSize EnvISOB5/Envelope B5: "<>setpagedevice" +*PageSize Env10/Envelope #10: "<>setpagedevice" +*PageSize EnvC5/Envelope C5: "<>setpagedevice" +*PageSize EnvDL/Envelope DL: "<>setpagedevice" +*PageSize EnvMonarch/Envelope Monarch: "<>setpagedevice" +*CloseUI: *PageSize + +*OpenUI *PageRegion: PickOne +*OrderDependency: 10 AnySetup *PageRegion +*DefaultPageRegion: Letter +*PageRegion Letter/Letter: "<>setpagedevice" +*PageRegion Legal/Legal: "<>setpagedevice" +*PageRegion Executive/Executive: "<>setpagedevice" +*PageRegion A4/A4: "<>setpagedevice" +*PageRegion A5/A5: "<>setpagedevice" +*PageRegion B5/B5 (JIS): "<>setpagedevice" +*PageRegion EnvISOB5/Envelope B5: "<>setpagedevice" +*PageRegion Env10/Envelope #10: "<>setpagedevice" +*PageRegion EnvC5/Envelope C5: "<>setpagedevice" +*PageRegion EnvDL/Envelope DL: "<>setpagedevice" +*PageRegion EnvMonarch/Envelope Monarch: "<>setpagedevice" +*CloseUI: *PageRegion + +*DefaultImageableArea: Letter +*ImageableArea Letter/US Letter: "18 36 594 756" +*ImageableArea Legal/US Legal: "18 36 594 972" +*ImageableArea Executive/Executive: "18 36 504 684" +*ImageableArea A4/A4: "18 36 577 806" +*ImageableArea A5/A5: "18 36 403 559" +*ImageableArea B5/JIS B5: "18 36 498 693" +*ImageableArea EnvISOB5/B5 (ISO): "18 36 463 673" +*ImageableArea Env10/Com-10: "18 36 279 648" +*ImageableArea EnvC5/EnvC5: "18 36 441 613" +*ImageableArea EnvDL/EnvDL: "18 36 294 588" +*ImageableArea EnvMonarch/Envelope Monarch: "18 36 261 504" + +*DefaultPaperDimension: Letter +*PaperDimension Letter/Letter: "612 792" +*PaperDimension Legal/Legal: "612 1008" +*PaperDimension Executive/Executive: "522 756" +*PaperDimension A4/A4: "595 842" +*PaperDimension A5/A5: "421 595" +*PaperDimension B5/B5 (JIS): "516 729" +*PaperDimension EnvISOB5/Envelope B5: "499 709" +*PaperDimension Env10/Envelope #10: "297 684" +*PaperDimension EnvC5/Envelope C5: "459 649" +*PaperDimension EnvDL/Envelope DL: "312 624" +*PaperDimension EnvMonarch/Envelope Monarch: "279 540" + +*OpenUI *InputSlot/Media Source: PickOne +*OrderDependency: 10 AnySetup *InputSlot +*DefaultInputSlot: Default +*InputSlot Default/Default: "<>setpagedevice" +*InputSlot Tray1/Tray 1: "<>setpagedevice" +*InputSlot Tray2/Tray 2: "<>setpagedevice" +*InputSlot Tray3/Tray 3: "<>setpagedevice" +*InputSlot Tray4/Tray 4: "<>setpagedevice" +*InputSlot Manual/Manual Feed: "<>setpagedevice" +*InputSlot Envelope/Envelope Feed: "<>setpagedevice" +*CloseUI: *InputSlot + +*OpenUI *Resolution/Output Resolution: PickOne +*OrderDependency: 20 AnySetup *Resolution +*DefaultResolution: 300dpi +*Resolution 150dpi/150 DPI: "<>setpagedevice" +*Resolution 300dpi/300 DPI: "<>setpagedevice" +*Resolution 600dpi/600 DPI: "<>setpagedevice" +*CloseUI: *Resolution + +*DefaultFont: Courier +*Font AvantGarde-Book: Standard "(001.006S)" Standard ROM +*Font AvantGarde-BookOblique: Standard "(001.006S)" Standard ROM +*Font AvantGarde-Demi: Standard "(001.007S)" Standard ROM +*Font AvantGarde-DemiOblique: Standard "(001.007S)" Standard ROM +*Font Bookman-Demi: Standard "(001.004S)" Standard ROM +*Font Bookman-DemiItalic: Standard "(001.004S)" Standard ROM +*Font Bookman-Light: Standard "(001.004S)" Standard ROM +*Font Bookman-LightItalic: Standard "(001.004S)" Standard ROM +*Font Courier: Standard "(002.004S)" Standard ROM +*Font Courier-Bold: Standard "(002.004S)" Standard ROM +*Font Courier-BoldOblique: Standard "(002.004S)" Standard ROM +*Font Courier-Oblique: Standard "(002.004S)" Standard ROM +*Font Helvetica: Standard "(001.006S)" Standard ROM +*Font Helvetica-Bold: Standard "(001.007S)" Standard ROM +*Font Helvetica-BoldOblique: Standard "(001.007S)" Standard ROM +*Font Helvetica-Narrow: Standard "(001.006S)" Standard ROM +*Font Helvetica-Narrow-Bold: Standard "(001.007S)" Standard ROM +*Font Helvetica-Narrow-BoldOblique: Standard "(001.007S)" Standard ROM +*Font Helvetica-Narrow-Oblique: Standard "(001.006S)" Standard ROM +*Font Helvetica-Oblique: Standard "(001.006S)" Standard ROM +*Font NewCenturySchlbk-Bold: Standard "(001.009S)" Standard ROM +*Font NewCenturySchlbk-BoldItalic: Standard "(001.007S)" Standard ROM +*Font NewCenturySchlbk-Italic: Standard "(001.006S)" Standard ROM +*Font NewCenturySchlbk-Roman: Standard "(001.007S)" Standard ROM +*Font Palatino-Bold: Standard "(001.005S)" Standard ROM +*Font Palatino-BoldItalic: Standard "(001.005S)" Standard ROM +*Font Palatino-Italic: Standard "(001.005S)" Standard ROM +*Font Palatino-Roman: Standard "(001.005S)" Standard ROM +*Font Symbol: Special "(001.007S)" Special ROM +*Font Times-Bold: Standard "(001.007S)" Standard ROM +*Font Times-BoldItalic: Standard "(001.009S)" Standard ROM +*Font Times-Italic: Standard "(001.007S)" Standard ROM +*Font Times-Roman: Standard "(001.007S)" Standard ROM +*Font ZapfChancery-MediumItalic: Standard "(001.007S)" Standard ROM +*Font ZapfDingbats: Special "(001.004S)" Standard ROM +*% +*% End of "$Id$". +*% diff --git a/pstoraster/Fontmap b/pstoraster/Fontmap new file mode 100644 index 0000000000..42797fe18d --- /dev/null +++ b/pstoraster/Fontmap @@ -0,0 +1,98 @@ +% +% "$Id: Fontmap 569 1999-07-30 12:57:12Z mike $" +% +% Fontmap file 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 +% + +% +% The Fontmap file takes lines in the following formats: +% +% /FontName /RealFontName [for aliases] +% /FontName (FileName) [for actual font files] +% +% All Type1 fonts in the "fonts" directory (usually /usr/share/cups/fonts) +% are automagically added with the names in the font files (that is, the +% font filename doesn't matter, it looks at the file header instead). +% + +% +% The standard fonts included with ESP Print are the free GhostScript fonts, +% which don't use the standard names. These aliases map the standard 39 +% fonts to the free fonts. +% + +/Bookman-Demi /URWBookmanL-DemiBold ; +/Bookman-DemiItalic /URWBookmanL-DemiBoldItal ; +/Bookman-Light /URWBookmanL-Ligh ; +/Bookman-LightItalic /URWBookmanL-LighItal ; + +/Courier /NimbusMonL-Regu ; +/Courier-Oblique /NimbusMonL-ReguObli ; +/Courier-Bold /NimbusMonL-Bold ; +/Courier-BoldOblique /NimbusMonL-BoldObli ; + +/AvantGarde-Book /URWGothicL-Book ; +/AvantGarde-BookOblique /URWGothicL-BookObli ; +/AvantGarde-Demi /URWGothicL-Demi ; +/AvantGarde-DemiOblique /URWGothicL-DemiObli ; + +/Helvetica /NimbusSanL-Regu ; +/Helvetica-Oblique /NimbusSanL-ReguItal ; +/Helvetica-Bold /NimbusSanL-Bold ; +/Helvetica-BoldOblique /NimbusSanL-BoldItal ; + +/Helvetica-Narrow /NimbusSanL-ReguCond ; +/Helvetica-Narrow-Oblique /NimbusSanL-ReguCondItal ; +/Helvetica-Narrow-Bold /NimbusSanL-BoldCond ; +/Helvetica-Narrow-BoldOblique /NimbusSanL-BoldCondItal ; + +/Palatino-Roman /URWPalladioL-Roma ; +/Palatino-Italic /URWPalladioL-Ital ; +/Palatino-Bold /URWPalladioL-Bold ; +/Palatino-BoldItalic /URWPalladioL-BoldItal ; + +/NewCenturySchlbk-Roman /CenturySchL-Roma ; +/NewCenturySchlbk-Italic /CenturySchL-Ital ; +/NewCenturySchlbk-Bold /CenturySchL-Bold ; +/NewCenturySchlbk-BoldItalic /CenturySchL-BoldItal ; + +/Times-Roman /NimbusRomNo9L-Regu ; +/Times-Italic /NimbusRomNo9L-ReguItal ; +/Times-Bold /NimbusRomNo9L-Medi ; +/Times-BoldItalic /NimbusRomNo9L-MediItal ; + +/Symbol /StandardSymL ; + +/ZapfChancery-MediumItalic /URWChanceryL-MediItal ; + +/ZapfDingbats /Dingbats ; + +% +% This alias is for less-intelligent PC programs like Quark and +% Freehand which insist on using "Times" as the name for the +% "Times-Roman" font. Go figure. +% + +/Times /Times-Roman ; + +% +% End of "$Id: Fontmap 569 1999-07-30 12:57:12Z mike $". +% diff --git a/pstoraster/Makefile b/pstoraster/Makefile new file mode 100644 index 0000000000..518d0121b1 --- /dev/null +++ b/pstoraster/Makefile @@ -0,0 +1,167 @@ +# +# "$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... +# + +LIBOBJS = 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 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 +OBJS = $(LIBOBJS) genarch.o pstoraster.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 libgs.a 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 + -$(LN) pstoraster $(SERVERROOT)/filter/pdftops + -$(MKDIR) $(DATADIR)/pstoraster + $(CP) $(DFILES) $(DATADIR)/pstoraster + +# +# genarch - generate the architecture configuration file. +# + +genarch: genarch.o + echo Linking $@... + $(CC) $(LDFLAGS) -o genarch genarch.o +arch.h: genarch + echo Generating $@... + ./genarch arch.h + +# +# libgs.a - GhostScript interpreter library... +# + +libgs.a: $(LIBOBJS) ../Makedefs + echo Archiving $@... + $(RM) $@ + $(AR) $(ARFLAGS) $@ $(LIBOBJS) + $(RANLIB) $@ + +gdevcups.o: ../cups/raster.h +gconf.o iconf.o gscdef.o: gconfig.h +$(LIBOBJS): arch.h ../config.h ../Makedefs + + +# +# pstoraster - PostScript RIP filter. +# + +pstoraster: pstoraster.o libgs.a ../Makedefs ../cups/$(LIBCUPS) + echo Linking $@... + $(CC) $(LDFLAGS) -o pstoraster pstoraster.o libgs.a \ + $(LIBJPEG) $(LIBZ) $(LIBS) -lm +pstoraster.o: arch.h ../config.h ../Makedefs + +# +# 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..4988155ff2 --- /dev/null +++ b/pstoraster/gconfig.h @@ -0,0 +1,196 @@ +/* + * "$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_ +# ifdef HAVE_LIBZ +oper_(zfzlib_op_defs) +# endif /* HAVE_LIBZ */ +oper_(zcie_l2_op_defs) +oper_(zcrd_l2_op_defs) +oper_(zfont0_op_defs) +oper_(zchar2_op_defs) +# ifdef HAVE_LIBJPEG +oper_(zfdcte_op_defs) +oper_(zfdctd_op_defs) +# endif /* HAVE_LIBJPEG */ +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..1d4b8f202f --- /dev/null +++ b/pstoraster/gdevcups.c @@ -0,0 +1,2459 @@ +/* + * "$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 *); +private dev_proc_sync_output(cups_sync_output); + +/* + * 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, + cups_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_K, /* 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 : + case CUPS_CSPACE_WHITE : + case CUPS_CSPACE_GOLD : + case CUPS_CSPACE_SILVER : + 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 : + case CUPS_CSPACE_GMCK : + case CUPS_CSPACE_GMCS : + 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 : + case CUPS_CSPACE_WHITE : + case CUPS_CSPACE_GOLD : + case CUPS_CSPACE_SILVER : + 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 : + case CUPS_CSPACE_GMCK : + case CUPS_CSPACE_GMCS : + 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 = 17; + 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); + +#ifdef DEBUG + fprintf(stderr, "DEBUG: cupsBitsPerPixel = %d, cupsWidth = %d, cupsBytesPerLine = %d, srcbytes = %d\n", + cups->header.cupsBitsPerPixel, cups->header.cupsWidth, + cups->header.cupsBytesPerLine, srcbytes); +#endif /* DEBUG */ + + 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 (num_copies < 1) + num_copies = 1; + + 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 : + case CUPS_CSPACE_WHITE : + case CUPS_CSPACE_GOLD : + case CUPS_CSPACE_SILVER : + 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 = 4; + cups->color_info.num_components = 4; + break; + } + + case CUPS_CSPACE_CMYK : + case CUPS_CSPACE_YMCK : + case CUPS_CSPACE_KCMY : + case CUPS_CSPACE_GMCK : + case CUPS_CSPACE_GMCS : + 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->color_info.num_components > 1) + { + 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 = profile->gamma; + + 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_sync_output()' - Keep the user informed of our status... + */ + +private int /* O - Error status */ +cups_sync_output(gx_device *pdev) /* I - Device info */ +{ + fprintf(stderr, "INFO: Processing page %d...\n", cups->page); + + return (0); +} + + +/* + * '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..b9a0c1b57c --- /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 = (gs_rop3_t)(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 = (gs_rop3_t)(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 = (gs_rop3_t)rop3_know_S_0(rop); break; + case 1: rop = (gs_rop3_t)rop3_invert_S(rop); break; + case 2: break; + case 3: rop = (gs_rop3_t)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 = (gs_rop3_t)rop3_know_T_0(rop); break; + case 1: rop = (gs_rop3_t)rop3_invert_T(rop); break; + case 2: break; + case 3: rop = (gs_rop3_t)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 = (gs_rop3_t)(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 = (gs_rop3_t)rop3_know_S_0(rop); + else if ( const_source == all_ones ) + rop = (gs_rop3_t)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 = (gs_rop3_t)rop3_know_T_0(rop); + else if ( const_texture == all_ones ) + rop = (gs_rop3_t)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 = (gs_rop3_t)(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 = + (gs_rop3_t)(source_transparent ? + (pattern_transparent ? So & Po : So) : + (pattern_transparent ? ~So | Po : rop3_1)); + return (gs_rop3_t)((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..98229dbc69 --- /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 "ctype_.h" +#include "gdevprn.h" +#include "gp.h" +#include "gsparam.h" +#include "gxclio.h" +#include + +/* ---------------- 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..b2251519f2 --- /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("TMPDIR")) == NULL ) + strcpy(fname, "/var/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..1a81a6c868 --- /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 { (%stderr) (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..452e9f6790 --- /dev/null +++ b/pstoraster/gs_init.ps @@ -0,0 +1,1271 @@ +% 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 + { (%stderr) (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 { (%stderr) (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 { (%stderr) (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 { (%stderr) (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 +% Set a null transfer function... +{} bind settransfer +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 %

B7r#)^99QbWWn!O?1PG-%v-kjB3fgAK^9WP}_}ZGE zqSrh$ZFUe71|LVvj|gcQ>-H`ITc=Yos)T%0`P4=F+AuwZOR57?Jp6z@7?>ahwfK#= z03M6juu5t3k740fvn|AXB=u;e8tuFR*voV?;aYirRRiM$#LM>6#8}mLn>dEvgiM^O zr_DEvPKQlo}+Z|B60=OYAT; zvXobx)OuX;|B>=@Uiq7qm`dib&GPL5J9=I%EN=mzj$i$4(t#c`Ef0;)jyLD7r>y0? z|E^nU+t)94Oh`r)YZ9-9Gv+vFO6UlbPjO#J#?^513T2Z0(SDs{;g|w(yC!TZ-*c8`I=^BpwkZCySm zOmr@^$ul#e+rQ{zlT>IRCW~1A~{)NElA=gjXm15B>kfOnHK$5`Xci0CAYCFBX}uQP43LH6MAY_ z`^*)2(~^K3ZA(ax;`%R}<6%6#2{55*0!sFrA%Q~Q0npgqs3_wTKI`EH_!Cp++` z_AIX@r~&P$eX5t{I8Xp}C{VpNuzWBfEWWli*f|)ZW(?;ZMjdT|gv3Q{chcDVB->DD z!UeW9EZ?yNJv!_ooX#I~cdvw)4PRP}5#_15;FECLH8gvT+N@~%vvqW{>|7LaBZ5@j znEoBCLK6~I05@WvLa-~iEk-m|AB-Lne2IM3SHbHGHy~%9W!(2zBwEG`m9HKD%SaBCdNs7`1J}zA82ch|| zD|lzvi&xRy_kaTuS9X|L1T*g$>0S!HEnlc+ml4-aK>_WnhEkzZ#|i0{88d8OzsGKI zj6K&yQ=rn0J+S21K29ly&6hWRCHLs{&#MMq_Yw1X^$5zrUqHPPN_{%=@ZO{o ze%YFDj`n8GFq>8o5c743((r(QwvGK>OlI8R+3Lsi$wTNcjMc)e=`fbuWQbujp?@!muS+6^9N>99OU|M^(tO6jrfa%& z|E5X1YBt=@mxi_H+S5HzLHB0ZeV>%hS8&UNF}kJff1y?HS2lZnE}~bQGWV~K*uqG_w{kKx|IvN}UtlnrLkQuS)G7U%5Fv+O3i1u8{pjrs z+R}g#zhdW*3QP5ZrPx>LwS`5}O<9mC`#TmojJrrGRHVl}Z9~pS2B;YdhxgG!FNtZV z)_Joh7IQtfI^}Kdk(LVye^lxERj@f*?ePuXMne>>yhhs$&@6GpeH~Ig-8ly9G{~ z=8}S}E?^__oJB}V+(XQA|jLn1Qw-UtB zN%AsUa*hB09hB=dNnNZ<68^hZmo__Hd+Hh)1I{qJ^9wZek=&P*hH>>?rA#o3x5F;= z2>aC*9l18%fi3A>Z=?@1hg|nmuppd_t{SC#-+kj^Kw&h4Tt`jM{i@hAj7evg7ufiu zxY`Yi0??96**NaaC8CBtD04{AviBaBm1X)6F~(UwCi#7ZH0C481XD*)9Ba+N%`$`D zPkFx8L$x1LzoL`bIQHly#xQOl6btYP|XUdonLLP+E@N03F)0{LyIRkCP-pcp;g%SIhS@BNLt*eHoYNM zI~~h+i0EN~@C`RsP#Ob##)Wyox{oJ(UU8*y)|?0=q_S)er^VPXsq7D!U(XO&?mLmG=;8wS>?0=_Ob*XaI`qD@{x)X6`sik2 za6PgRsizps?n`E;qgL#MRzd86ezgV1{}{uvn7l|j1rx{_K+pU3&~Ve4sCGV`+EA+g zGx%zvDH5jMwukNrcm%m5#r@xLGqQL=!EeKyYpNzeh^k_w9V<*(D4ithaUar#A@Mmpe% zQjLV<-|Uq<_E%Uvy;{ZQ3!T;(glXpv7^ZPc}_Y zwiM5Rd(q5*?RC*W*6Sa1Hl02?BMr(b6dWGD%V2kHM2A-W?4Q7T>S)5byE#*p>l7pC ztS}6N_NXim`+_S@28svX@*N_XV@up^=o-b_u z2hQGawxxA%4766m$TQAfk&eDz7uo!BnFuu{08*FvoCEf@wJt=BZKWmnIZ{e5-lwVj z4unASAko!g=~)LPGdm=gv`3=I%APgg(Jk-sWd3QbPBZeLkXOdY0dcztEQMNXd+bpF zalZTSAXNb_@std!24*FKBOz75yGTVIVI*EbqsoRt_mm-Yn~L4*0KU8rzz^GWX~5!(-lRK!DDa7vv?uaO&3t~ctMADYLg8vc7UT0f3ljMc zL8-H5t$rdHu1d2f_!W(`G{ilq4GxQPU&ziaKs~W4kg4b7It1jnE-GZd{i7%;3wbKz zcSmvP&FPJICz+)0JC!as`)PX|iG7v%A@t^iW)U6&KBttbd38vBq7Cb6FPttAitaMa zh4YcZXoM`-8H(Jd7Dc4huDj+yMpg;T0%AG38zUsv(!}q6 sCQ$;JMTmc@#~lISm=IuK%>Pdi{u}s@2$%xR0nV-tb^vEvgaF9@0Rg&nd;kCd literal 0 Hc-jL100001 diff --git a/fonts/Bookman-Demi b/fonts/Bookman-Demi new file mode 100644 index 0000000000000000000000000000000000000000..da92e614cd697c8c181328027059fdf91d773f0a GIT binary patch literal 35453 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 literal 0 Hc-jL100001 diff --git a/fonts/Bookman-DemiItalic b/fonts/Bookman-DemiItalic new file mode 100644 index 0000000000000000000000000000000000000000..59072a526fb2189f07d315296a830be9bb8d7756 GIT binary patch literal 35218 zc-oY?V~{TGmMvPgtyT4wZQHhO+qP}nwr$(?D%VIx z3~c}m4FA*_SYb#>g`G?dT`cYGL=0U_xd38LmH;tRBLE{CfRU4v4TcmTZ13RdWNB{U z@~>e4WqUIhcS9#rn*Ue+UyT4G&wthb>Hoj$QZ_XOxLBA1%q(q80mAYMnv!zj019zA zRe-puovG753>93BY%GldGM2`scFv}h05f|hfX#md0AqVQ6U%>*cBX@2WCWO48oL0D zOwBFrVCes)UDD3X9>B=(A9)j3hySX%nL0WD0|HR|r+P}jKiW;~?QA>&CZ=XE^m6tt z{~Q3I_`i_wKcWBKMDhRYf&I@pVy-qea)!45N#Z}f1IPgWWgg&P?g9Q~pQZ8t2WMz& zY2*37LH^H1b<_V~`L9|3v-TgO1?|lL@r0Ije@{HJV7M^{rx5dbR# zBPTn@fABPRb#gMbbNTl+{-gfC;(xEcsi}vlF-!nReJ~KvMJ)8XLGcjH9roLfWfsw} zwl?dPRS|3QxUI@mw_XbM%i3cH9w}+^(4*tvunF)F@H!r;jSg+wjAQCN(!8d6_5s{c33?FS4qug6TIu1YKg0 z0+V7cmPMeQNXvnXdnypGCj(`!9X^%zH@v3qq#qh|aS}c zZ9xt2Lfc5&_foV{S#m{=!W||n#$9~70Rsa|@#p6XK>>$~kS2WKx1|`44<)(D9r{NV zi}s8F{oWRmts{eq=qMPAKR~_|X?Zu~2(SYvfHgoO3Ad79hwmC345Bq5HY>Ps)!Jz= zAqf1~>MUzrkW^HP*c1YGsBJR}zz8Z5rd6RV_)z?u6-JqsxKjau0sy7REMqTJ0W(h> zzUbYL&HHRF5QOO%o6#k1Kx=rlyNuWKRBOUGMVT$uL#$NT^1jThrHlfY*%&6<7-?oe z8b_*Dv!qM~tBH(dEflJDnhS5GAw3(v9_;0hYY4N_S#X{#dBAz*dlkRlBnNzN}VgX+<_tW$f1YTBe_^b%n#ymnxou#d517a z7dbJS^%#HOCWUJd?S$3S+b0Df>qCAV;r=6;r-Nsf7epMWNi^K0eP)6u!Y0aJ@8pKp zT{WblpLzjOaMB*JXi%sF#84lzUyN2F^*69GIG@<~Ty*!xe{LOGIJH4v9=w&j03mXc z%f?D{ZGPVAme#bVyN7Jg&4T8gaD9D3duwz**<0u5oO?)QV8f-u0VFG%x*iEezycIz z*_VUwvlLMAWsztdO*DPk>^9Y`*0NF`d|n(ds8tNjMvo{Mr;6$WBu<7ejVUULR&@E| z5VcGB8gqaZNu(S349cG`RS3^f=6;8!I2q8jF?g3RNh`?O;(Up=hbjyPK75Bbv}_(s zgp$}TMZ{|nFwnuws746^zl#ask>(Z;go^rr(7U_0Hh~x42xcR@qek`$Z6B8{RY#vS zBV*r>&+Ym}IL_MGOyZ8MvM)?OKQ4Za(H>^m<<8eYlL041!yp01pCcQ;rHDIkybs$S z%l-F{W3=RbB~O{wD!pTGe>!qe*nRN?Qb&-@G2FLe0q;I+Ulqmqw4%z@s*@U2NOc}- zK9KoW6LjMnhw6?1alW?}QpL{f-oECiw$tOi0J^?e6+$T3EOrZDvq;3`vd1YYTft4@ z%X4b|CwfWm%eq#Ph-W29;2}7ht)@MYoz75<=XKEwa)T>9JvN-p z9jSWkEw+1Z)I*+-YyfzO`D-GE`!~T-%x=qm9P>;Nj4%B%hz8&Aj$;(m$IYA|d5Y91 zkh$Pryrbq_h=>P)WQOskoFo2hFZM^V$@kl9zZ1{;C#-E;JnZI8;H?sX*VRjZ4P}|T zgBh}U2eVz>W}!%!di^9cg_Nvthq!eUU?eVgC6$ZhCZUx?ZGUUewK{p<=*@3>?}ZKg z`hp1tldRm{*tjpG97%H@z;tloN7LJ^*M4s%4+aa_t;TO7t&9-osw$E3;UIShY+Rsa zq=$2(>_c`Bs~`S>lcQ`*J3hYs6VmAGGG5d@CM`S}g~#h=ErEi&|JI4c`R%#*eV$z~~_je#JhK!Y-M?=EL;alCe|Cu%sKxKycWDQ|V-FSgB#PmueaTW65sm1*@WA2d{`C;w- zdjz`4F;C5AzcuXdaCOZ3cRyBR+Xx7d)0jHORf>$PO`)UE`%DN}tIH;q{VECwy?(iK z90z_4iA(+bn67s>-0#wHu?~I-=OmdItU7P@2rWZ<%7s#iJU7V}*Qcflm!Yg&JP|e6 zV={mk1JIYMFZ;t4n_BZ5)d>DT6%?ih2^n6%38~M5-T7DbI#Eh>bH^jEYu}isxkp1{ z4B;iWS`r3%888eoY%|iQM{~j@;UJcPB8cN~`I7gG9B3$g4v-MG2JQ8nm?%sumgdno zEcaB{fk2Mk_x?+&)#H$y!m;{D2$ee&2Fh@q2?iZiynE-Rl;`9?e6N-g{o@blPBX) z+Wy6W2J006oqk0K5V5YkKzJ+yk+Ed@VKauPQi1KP4zSJUI+b^vv3~UVPVn~Dmx5-d zY9Xd$uV~+)Nex#2#IxTTtvC>5(=GQqMhwZX%##!jg&5<6dZ-Y~3fYTAfD)SSLgJBqc?uZ@iZ zW=af{&$1*A4q3#&<&Z>4Hv@#QVE5zacQ6rC%s!bbyX^4jHw@ua7AcwPU*!HWBq?s$ z!fuQLBtA{%=M0!&mFxb+7RR;|aXdtAO?kuUQa0!e^0ONez?4GhS*|m-Fp_4LnO6T5 zIO6bh;;6^L83UsyFb9Q9q(#1EcALGQD2_;=AlB~Z4jVl7LV1DMa$9tc0kjzZC`%2Y zxoSoxg_{D(V!`IwU|Pj5e5C7|GUwZ=(Q0h{L&;KvALzM+wE8h}8@6q>MD6~R`7msm zWTxu4+=HunTX*=w*REs-);ZNvGtKQl{|tRa?vz9xShexIN7?cyB>-XIRt`qV8C-C9 zl-W)7wAa8@1}|gRr=2~(wzf6T*`{;1n%&NtItOL3xyf-u5iOs z=Y50&;i+I~x-TD-&X`^U<{T(Ju^a>JD^EXtJ zeD`&6f!=NrE5#vN*D^Y1$-IyefB#DdTefA)z8(R z?J5i0>GK=*Q_8Sc6wUW0q2{@7cnso^d@iLC@nX)O+dsDXdY=+d`^va$q0=z?Nn}1hxV|E5| zw+bOo^Fslf*Pk*Ybf?9fxqg=#{ifAmC0Do~!M)O0h6|^Zz*(RR-NbPR;Auod&IYBH zQ-W4+L8shRIN~|qe84J5hIv(>x6SxEl`iN4a~dpjv<1^&C@2W;=A|_xlVR||{?b0R34M#;grG|0Gr@f7 zr4zCdj$}H`U+=`Fy!Ku+VYw&%9Kx~cbAS9f)ne`!*lD&7p+K(E%(yjBV&xQ?iIms6 zK^85rO8r8*n(#KE?3YsVWljfkXuQCbYwepXiTrX?u(fkDM30u%jAnV-TnIWxBw-`xIZ? z-E$VH^2`{Vi4i-Mau%Cs0(VrncKSxKO{qTF85A47!nL}NPPf)kb!pU^sTON;uyEO8 z3W5bbKRX5nVF6dop30*1SmDPRSntL9yCuStpDO2VTl{bARjmd}a_d4Y_$75Aej9@F zkD{QAKM~QjwpeudeEt@(yP_qN8rK#`Bm{{f9nJum1_94Td9a4DS0esPZkv*Y5|9>d zE)ox=F11x-UuDm4PES-C@8Ky-klskmk1wT*92XouIAlcV%1Fpaq=$77WFnsZd#K6I zWc}@t3E!-)Ai-e*<#3VQcppAr4!JFH?V%=h;qL412*KefEOFtQHeIPxq+sKHZR8J# z?k7x&I&+f#LY>#o$b)S;n1Ab7L5{2g@u8~J`C zp5S|)eIPnvNEvb-GZa$ zKsZUAF-IODLQ2hoKPWefK6k{&YW}_QPuI(o*xvX;+&tmB$^C`*th%<+dg2TlKh!HE zW*XhaU>7{Cq{o4W<&@Gxf)qA;~mGnrI7k8RrRoLMnrA zM41Q7cdvDcG}Hvq=k;NZ+*U(`ULeY1=kqZ1vq>(oChr`c?YJ-@7OMG*iJ>Evba*?w z#Qh2`s7I%|C~5Rm1eon zZ>(hmEqCw9+ChbXN5D&WLXf|=Drf;iVMg)oaNv@wa!_3JeY(%1>j0d0MR*W*B$m@? zD$Zj!*D?*RWz}|D(L*Ed^IO~?Z~H1&>^L8 z)yL=`(l+A>l|%8O(fzmyERveKk2+E&MDf(wvD<(|0GAhB-{d(ga4bFX+;A zcCf3HOjl%|7S6-GTwb_uIC2X!U!jpu_9?cq<7zcO!S5(8$}`UDJheY7t8e4?J-_L^ zU5@Xs+KWoBh`|!-%~ur^XJFsM^P;~t30K?UJCVsK7k>a)RZ{ELfoEHd3{F8tc(juQ zz)nd1Ccp-ba@bo-QPwj`Fot(m#NkHqVd`ws5hgNr8mxqN+T5=K6zR_=+BUz2+Dcq6 zoL?wR!xs0vm?yNDqqlUe{9Jn{@oS~o!5kd8=Fy*P z^FkMgc*0oi(`3V2*AOUtsyu%ilCiupTJXqc?=n3xcmxT%QFqP)@H0S}e3pTvJ1a<# zoDi*&P8e?StYEc?F1pF%ep`H&P?5GK9-uhEsCA^c6uL@2$dgeCDR7V^ACS7T98pUR zZ# zBk;C$Cl-`2T5F#{K3Yd z9M3E{U6l6dw+i`DZ&D%57WE!&*FApYF-B|gr4r+3p4e)24z+%-MV|f+?AFJOrj7s^ zlL^KxTwOg(lCRF!Zj~Yj5gs0((A#N5s$lCayA(ysIj_7EO+MIYAUIovM*uH1 zy+@YJ%kZ;Hj{XV!fOWwyH!2kg#&4V!mXOcsZ!2V5tuTBmnCo@tlM#-%To z%#dVPrxfH1DnI8fkCDsrGQCD{nTzavSBBIOU(57MT+NsrYSApG3O)*MSUiI6bQxCs z>K?W@eIjz~E1^O%X?Y-5(cf-A5O&{ck=ks*ll`1_F~vF(#GMh_Mk@2`5b&b2j}|za z^(l9VpzH<5A$1jd?^NE63}ErC)mse+>O{YbPB^S@4BN#=z;Pxg%BqEA!#A>H&gbMJ1UQp_`;_kWc)a4#lz)?{Ik?Tf zNw7gZ%E~qhsoDuGYcq71CniF?ye8+j$zYRoR#>XV2p*IO6rYkx&>d?ouVfk>nP4Ko zCk~gZ)bdRw_L$f}V^97>^4-ai+P?xh-S`0^6Iu)FxG_bTOb(I6dj3?>583`&a03=P z);SFlS3@qW-H=1kAg!CfQ@Eu1{i6mfgwH8&F01&lI-43bX}BFm{8gOWuxd#!uX!?G zxADWSP%*OCkgl+fMqvO_9?>3Iv+%7&ZyGM;=irtZ4|=`(C^}a z6|5e`LW%`_6O*Rw>6uz-1l~pd1E%Jq%}hL+@=hae);hO_nE5rFy8bXNai{Ncmkfmbtv9=|PF++}sTla@A2t?1fW8s<0W3{4KgIRq zX-CEt5bEPENlbJLjlz$!iv!~H6Vps=?t`fMi)ao>nLd4*sJm~>%fwn3WZb~4Od6?y zc&46C{Vj!^rLPVtNi(Q|GHm$xLWN!v{ZS4NDy;XcjG&%;wK)ef@k!Zzoo!>{jFr~C zp+b+a20Qs+o5JhYLOLVkIhrsI4kl7oSQ9TY4=}i7sdi+!hBaAFXd`Bur%~4mnK}bt zRZ$QhT~q=@W9;TU>8PzY|L{1kDj_p4tDi6U@?RPH zpk~=BHptJ1NNntVO1}v$wd#p-)o$uoZaC!| z{%E^rEKvDAKC7!;-7y5|bA7uRxIwjTr<|0zP_!oi8IAGsl_{YjvuOkgA=4ErHfY#s zY)yB!->bEek&Epzr%zl);;j%!o^g3m{>Bf34}ZaI>xvjUtp9Puk8W=azIx3C%AV>5 zPI!1*n$rq34UdTS!YvU{c%e!26U2ed=>2}T8CQXA-f?LpVFlmNNl|C|)5)~im(YTD z+%%hSlzeU|X|_<8*zhiT_!#jytU2>A8C5J#h41*95f7OYFln^9-uvhK6BYKY=5PYT z`*S?P>in=gg0a|N(>|$)HHGs02L8~1jOm3zRMn$(4qT5wRJ7?q{7?y>?iX^G;G6vHewP2XU zw01sm3ProZ_`q_8?#8~nTJ6CO&inHq+gOqpkPp`GF*W{K$``- zb>sXLx@IGpN?%DV#ZexHtwc~!hN?9CKwW@C{~nzTv!a4zQeXFtNgN3?mV{6%h3 z*?q>Sc+@svFO~NuZ%2;6K> z7=K{;=LjHy=7Jc1{{DHYg*Nm|!h2hOTzMh%FxC$8%iFV3`s)layJ&ZStj@eN#0+5% z{QA+WZ!q@-J&tDkmhVkTsd;OL*4_u@hN0zNAm1^Q2(W;i5z1op1JBgNI3nfgw=pdq z@#ZuJlEnN))`aVd5^!li_-@;OmiT(7DpnlngLIg(*&cyX)@~{JV3yQx=6_^4Olpm^ z);U~YYnpWvYR@a`5p2EEo^)bxb)HH6c;#sAcY}WaOvf~<8`J-QXrH7?L&@HVX_?sRIe}z zEEmik0dpu60yFzeawTahIp*=aZJ);!K^jaUHN%s7+ z?ZA;A_UMi*R=v7D^ds=u!NB6V8)4_ulmbG>3L|^s!^14OC5w-7?yZ&|zHj))^RLJ| zo;bak*%zh8(_${gmgGzzo2QRE%%yW&Kd-puK^9nyiKwnr=y?lxn9^rrSccu|=!4jy z(@z|K8l|yr!d1{N%`GSFC9~^GIfDCLwIkh>>f>>cnJ0Du8Z&)6KQg<~UJhx0)B&ty z>5~{&2F4EJ;g)BQ9T0SjAU?hcRE;_~Nd~)ZCeyYmX)xis+SjiRRc&iM_bC(%%vjL( z$-_+|OfO5>t&peS+E^8hG=?>09I2X_FC=EForSA9hE;&tA7%xImcW^sv9i3O1j;?m zhvYNyrmx#&YW1WO(E87ExH3xdvOJ>ShZG{91@)9M3giSEz9P6@hwFV*W$~c)&PSzx zR!y)Rg24_uSA^x*O1K{jws$TK>3Jh{fsa)al7~8|`Ahqq<;AFX>jNKgLN0lP)nmS> zg!&`>ZJFM`1M&`lOnDSoHuR*kpeg@Pji7x~9|I8T<&Xlx{z+vWO$8^2Yr9R z<~FP7uB>I#zP)>cK`+eLYy(xfO%D_2+ZM@pP+lSl=%(@y169%F`i zS3=K+B!@2ZxqI*Bf%1w-0Zf_9oIzM*@ht(^KG7J+)68kA?YZzgk36$e>rr~l#eek* zVo__t7kn(tbaB1i(Jm+wehZK*H2WqAeVlEo7%Gpwh(!dWke3>6{W#qK!BQ(8SK=~Whqr$8g$>WDC|1I5oe=h!3 z!B-#2iLg@xAtOrHStbn+^8PHGSq#cLe@9UpoJw&xF6wW20u&pN+2 z4>lb;w8z@}8F}eRhJ{7odECRmuTe=2ht`8-iQ$S+nJ#$=5#G!i0%&y?kMEZ*v$d?H zgh}I;M0?jc)2}q^9dcE5gCgkD8#NJ#sHIfMu*V(Bd4-~bak@hw5z@%`r#cmsg+rrN zvcLFLvk1+{uvQE@`VH%6$uR?!)J=&EKEy7bzlZpYx0Ahwm- zw&j^9;&t`;gNMo%6~W+3&VPhl@OR1EQ8`xYyslk<_I~*>ii0HQs`L4w*NtA99Q&9* zkhPC(v({MXXo0kW=v`!-5MrH8zpmbHZF(i_%A`|U4g@mx8czGMalGH4&ek?hvj+kwxfn0#(tg9^4u^(c&j%k`m>3dx>{0 zc)>Kjs41owk1Z}19+oN>XnK^eIn14Wb4w~|Ty;2-6XCcy1p<*J>=&DKV_ON)y?m1Q zd~$7Tcxo=_8|G&5>sR~zE}S$&ksPv0&|}z$pjJ|7X4k%ZuwVq=zG6A8rJ*!R?z>*K ztoq?WvpAQS@VK3Pufdt$lS9%Y!s#nSsvtFMGwELFetJE(R{%8J&r+a|l^|}#DTYYN z%pXrm4w8-EWw18uWYvoiun|~y){MC@pxRNL z=sS8cea1%M&g+TYHR?49S!wXE2m#Y&^Ob2uP01Z*gMhO?T&{d!mC8%F?s1LW@|b8` zidC?KMI=ZieSG)F0`n1x#DE@%jn-qCP}zrYrK?#rVOTzGl#X`qKf9XUyu{FEfL?Bc zsl6aa_p{9y&UpOPUbRkx2Kw@4=i566xuB~mW3kpMlDW$N=-?iVgbtJ+Ae!(AXviw8 zR)I&V*E-z(jB&uc!k24Lu{N$!)+%RQFqe-+u zZkdb~rXm)@pgpN1RQX+dc@ZoyLe`^8V=p%O^<`GIf4&lvnZN3~s=qvV9Xi||5M!Cp zgdI(I#x9GJRg*>C-GDY`w5JFd9R;`|f})1NCotGfwHs*wVqN@=px_DhIoXlH;`)sSXX`h zF0*UFv7RcT*?7`68{k*mi3Ac4d$ia*!DYIFLltwm2i>|XV0{BC?#!r2E@)0io@^I=1tv9%!ir-9X=lF~1F4!d89y0-7d z>O%&^ARyqLjR|7t&(NX7esibrrl8^0jMaEhVqwW-ak6g**c*yi8rC*F8Q4lqApdX+79~n$`=!Hx@;sxcD(4!s)nd_u z?l-2fwq63=1$_c@r(4dv6Mo(96uFH|a;~Z`Xa*bDr@1GyqN+@if}tQ#a`(RmMh|JL z!0`@)5J5oTgD4OTzNev4BdFSMq{JX~x3=1v`uM|_x0<^0?RQKjOhQG2$3(|{R6bkx zS#`DOLAmZ45XblC@n5S0Y4Db(xIGV^urvk;kK0&m^SqsCzv1IKZ#krBXB%t8$@z%| zxW$$D%G7V$%zQ?b{RyZ-;?6zaNV%E`l(i7~!69BSmg5*imdcDYXqvMLOq_=LhM<+$ zx^rqhv5X(zt{;9egib>FTbE>iDT#RVQsJ8q?{2Iec23FHvz)M@6i!S~p*7`DvQp@} zkI^jWApxI5Y>E4Tc6^*It-kuPU7}EE-E9U3ACalHvC5dqaJ0w;n<rNtKiG7wQ;S})Q}2%{8ssb$dZfT@^%3y! z`e4PmWZt%B;R^rPT}S*EjT#P^FhW~oP!zS50fvj3vzCkCW%(WPW(^$1Be5TYIj93? z8qW(15;-nVgJ_%kBf7xxD+#D$ZD!CtNr(|x)E2^th`VCgUuDcBQ#Y?HS53t}|EJ){ z@Ip6WT~?8M5L%-bbqs!tU0Qd`(~&}+%bdU9?z+laG}^B>eCNF*gr!FLc_$5UJ2>uE zRn(Vpyo__w3$bg7YI|{6z-#HkK0q!V#M$lGC*IDBXhaaX_4&A2h`4K7w@+qu*jAa$WvKwVajocX+oEL5jlh;LVo= z?>G%+vMU~$Q$nn&IPr7+BE<31GE)1An7?MaR22C5YQX3Q<3UL5lRa#P?a^l(Mz}A% zUx&`=z8eza3E38|(g)@?2Idu3B$;%>pgxvOvwA+U#oqmZYDB|6NTQ!O9Tpdi?q~OM zeY~|J(xduY&`|sO3Yxd7@*1`B*9}#Zu>_YJ!{i$3Llw--6#X%rfzjp}jc1^-LxPkP z)T<4i>Dm+alK2<9@n1&N5?h14{|<=j7R`wmF7cr;KBy zX1j3hIby-WU8@b2G6Op;#ZLtOY0OSk=z|x(?xHtL8V7#@#*Ke7OCdOVYV~LiK)~uJ zE=^dVWn{=*NXSI$JxZ!X3u-eh;qfjzo=#|+6SX`43?l4IdLX8}G| z2NJmxfm23*o34G94GG+e8`DH{8oggt-QFe}zCCxv-<9_2JD@=t8b2fApmKAH5Icc} z?Z!R$qZ*f|?G>)4Dn#0VS;gh-h!Esd$1N6==P=5J&uXPD9Y_2x6WtvIO^l zsnc%rA$=_)hUDWf3H!yerI#}*0>U`qL3^Hkxn2vur(ziS{gzm^DuvAjbxwdBcjK~* zLeyh+{4u09=r5UfE4deL#`t{K!f4wmXEoml8wl1+?1!uf+WporoUL}aBpLD5!IJ4b z(tKz#qTWg}f==GeRPG|H11X}dR}jkDEmp!^qsp9;$e2(e6QJu8niUa8SW)bbb&Pb5 zGY7pjhr^;NW*%9}x`Bx*G8Ppc!%ltR(obs0&!OIC<#P)qpxSbS?ORf{c@c_6lF`?k zlQ>}Er;J^~NiUOy+U42kDHFE4aWE0N-G`BO1n_@e6l*8PP|DEW+cHD?2aIjOQ1wC` z5Y9Wg2x~k*&+V$7dJXr(5^>h=?O*O1iGf!NICN7^954bh;2T4&f(f~$#w%DgIwu;>0 zs{T9=q83o_pC#WX_+lUFzN_IK8#SKC4wtTtsb%#`tAD;Ti%1;hq%mz(ByWxXCFwI# zPndg~w921Yj$^71;z9MAARiI$-YB}2jN@lQ#ubdea(=&C39Yh-aeNL-T`Bm(EmRnJ zv$)sxz3BIRqqf#zg7KCkpYZ~JZNk>t{)tw!h0c>rRP`gSwfr%DneK_wqgENwXFHf! z{GnxPA4V%Q%$Aea!rE=h%4e9glyNW$U)6pm5-FUQLXvhiBtuBtrgEf*i^0d4=3?J< zEeneyoETr7VUxsRc!rI}G+uJ~L0NbukUr4?cpwfmigcR3P2Zocu-A;o$}nQHhZpIQ z^bdG>Mv?T~k7{Rrq%-LRb8it!2~GA!!~?ZjoEMCEQ=ruW*}C=F9~xwzxxt1kBhMqC zksKi~mel0))|i3;>wa<8Sd&;rU;JeJZ5U_>JQ_pzA`Pn@NEbsQ|KYP9KY8yf;`nf_ zNx$D5v}6M9_#DfB--Cilenh3fbO7m2R{v}eSU113!(Gis$q1uoCYu5`44c#7>9=K9 z2KA}viVW7B=J7ymb4DtBqD<@6BO_*j7I$ANf3`l^6J*e_ROmML=S1Dzbi~>IX#$Lp zQESaDJGD~xa!+Vm#^oU}Hng2`6EvTZL(O}p+X1P(>yJzg)VPC&d(apz3Fv4(COi!v zbA8330GE`cRWV8O&tEqXdoR?KI zCWn?;Q7s|<+jI;m!@uAZs51WID-Ql0$nAZM*3Wq6z8;1U@n{99QqBLntGY@j20rmp zQJ}d9C3VfCY3}y>ceT+Nq@(1~rO02!;&-7iw7&+J4;>-6K1|?9;}Ih3Y|-f@fknKYAPT_u%&$pZov%+pph!PnK>n;oq-2)jnNq?E12G4@mW zpP|GpoQ*!!<=V4nx{8%iU|y2ASfNd&zVEWCF=0qMlCm)&7(tQdGUnBU^52tv)hUS9 z8md4cGyNH`G&K7W`@OqYky{_^Woh4b#;0Q8Q7fDdZiZcf|L8T?>F|&mjAOQIh`uS9 zB=`IIdpE1TBnMwXPbKIxi`#02vScf7c9fBsVyGPiT!3!^YZb;8Ap69Op5ufNDoPcj z3zOt96NFp&iHiKFxHuK5$;vN_`GzgvIpk(~i>t_7mV?~wBnD;vQI$?XUd0ZplGPb* zN%8=3LXdWg?!gnih5xVvLS*S=(#t*HE>;Ppx%~-DBaCy39NX5jPcoWnSh4fDlh2%{ zvJjx#98t|gKKw2;XeABS?l7K;ln89I;pkD&U2hqS;`bCAMo>Yg*Dq#~6=C$33Oa0o z`)w9Tq4$C*=0t%zp0$B3!QexkTG1vEG;lo~Bo}V=x2+7=Nk^noU*|a4TxJnPjWVT( z@_vKe&6*wr8WFjnc|Nr~W>P1d{auIJ>K-Z1zIDtlgl&FN6L-EI_N;bs!S_w$erH&- zQ*IptxY^iA^4!w*C1^*It3j?MX<^F zDZF9nkM`odKtT~65A{Oe4R1FRiO=;W7Hk51X9VoG5EA$j=`vBQShcF*6}=JVpO!DU zEl|)o%lcI7wGfvHeED`qZp5asD9Jg!vzXCZJoc^idO2P*^*fRBt`v+tWhI^k5bOt3 zCO)|wo=nJZQ&OuY2iX9XR-ao^8mrDe+5t=z!%i3z*j7~|ARHO?S3te`FoGXzUO`iw z(d>A$Fc;7ISdFcra`$gl$SKG~kt6nN_M|kJzZME2B~Qrt%s}NNt*EDo!JH|TmeK8S z3@&3UX+*C$(b#Ei_OQSP?mlK7=!R+VUxDVnp)kpHL=o|~#S;fpZ&&W7^Z7w=4KMjA z@Z`MR>I~au6teJ4NpM;Ltd;%0ieDE%E7ZDeLv`k>K<~I@O5eL)>IPk*V@;rOD}k{v zj~nOK@PJDbb`1pjrjyG&t|f<_cn^7pY~D7Q6kR;@h-Xd!|sq_pF5M40$_0AcM@qv-savCOLAoVWrfykkS<)3AZC}| zB$sEL!#2kN<@;NrdLKHTW&Zq4^OM6GVVB{-9x1rm2km91KU5H9%+4&PA8k@ljp*6- zgF+{<^byU9pz&wDkH>nEkx-38b1(YxvZBEDEqPYV0dy5;q_NQO!nN7R-)im6T;LpPz3YC!6V;lc@RX&E zscg9(4G8&FV_-ZzLKb?>r%}Q>T3D}+-R4UVlZaIrul1XeoRLt;nDW7wOmClxN$058 z5=>;^Uv`CcHux77e(~4cw1m-Z)(eGoz`QA+X81D1;VTiuKeRmn9;AAeBVVQ?t|r}Z z1Fqr(8NI7F#o;%KPG^BK{W+7p7$O{(c0R40akw*E7tGD`nwG(5{S1HF1|PIW3PSh+ z>v6QeL!`3KolZGR#74@JyM(99Z8k6Wi=`q7=o2Q05?s*GSK9*LJ!;W9n(e0xE>+$u zOW5t9sF;ReG{!5hldov|A0I!}Q`XE7nL#F30-VA|xOpcAy*O|=+58gwDi5k-1r8x@ zdh!jhO)3;)=JlXiOh`j}c8FF>1Qvncf0nsbw)=7Kmh{EHF;oj5gS^^DT>k#oAAs0> z)!Sk{k`YgkG8|qgl~r$vLeak^hn;M$_s|`=gpXDoHP@*I)(Wx2nYs6$p6s3Ecb&pw zXjjA47iZyMvn3%{8|)}j_?)=OP+yyXZSL$;jZWMn+ZL8maSE5;6d-GT*r<))S9&wD0hfHS zdWVEDpD@QNBoUs@@?lo)VlH;obUFidVeMSw3i_V5*7ziMp60=n6et*rJ*|!xrU$T zeVKHk-0NupFUq0XmxT=~{hD4O((;m(vnCI0{p2d_yZ(wRIvR`o3Z)s(4Q9bgRN$2k z`W=aoio|`wIRpro&3diA!_@4(bJBuUko`U+HH%t43eNDBg@+5cH*<0rpwIeNKzISc zY2qt`fs(_JN*Y9U{I)$W#+EzUY2kO(BaB>UlNayJ$@oWC_Jp^zD)-9zg^Q(7A0Y?7 zawoa>Z_)>ey}3+6dS*2gg0Q1qq^ykr#v}li@+BfVlwBgx4QN`k^pHBBRy+5G-7pJ^ zb7~VD=h#x?HW}Z+VpeiIaZ zRTtqEQRsH^O0;OeDFq8IhMV2`=ujL)Y>+tqhzYR9EMb*rd_#X6X&-lQ`)rYm;XFL_ z3>^IktzH(6)87Mhj0*{Bq>{{Tr&Jo6FmEdBHzRkCYrnUGSJ|8;Cb<_*G&SATtQX8RHq#xU{(aMb78&JVKOX=Ku zqe{pK*iOqYG!EAHjpKb~v(F*mvt2+dBMF#y#?kFJ{Y$i&qQ?Rr9f5i;8@L-cRh~jK zv~1-&c=QCac&f;YQ|{;G?j`UUt~{VcQlQ?xxQr=;EYD6J(7x0Z7JlVXC%c?!8lr88 zhmP+&8i2LeBK^R)$INW30gJvN2L_YVH2Fq9xGJjBJ-1RiifN-Wzd*|8V6-?`2yb}t zg`NG1H8sFDp=#vHCk&o!uuR4DmD_7e0Je;bBMRGP1u1Fi*P5UfqSi_Pt&+%+h z%{01*+-CsMuLR;qROHfcq}uJuDx9(Z1qVR*zXF4?<`a#>Owr5dsR#FI*|G8v}?yW~u6({I2!6S+Gv0bKCiMZ7LprmFMVxDfp1YZ%1R=x2FGy-$qQNhlKZ2 z27*gmBL*$}9r~2D5Y(i2PIRPCpqz$J!(@29UhA%e5Xqe-J+E|7sU6L+AVDfq#KI&cRV2Mk z>LDM$Y0B@{GB+Lrwp7Sm5kxKC`=}!;a40NU1!y)J%PF1lH^KLA`SY5iOXuHWp^4n- zLZ}?vBteopbhs52vzTX|7a5YDd&V1~J`tsmVVGDXcB(tPE=jYj_^p`JL35Ca z$x`}T7p6wVL3|QBpQp%3O^jj?Y^>g%a~KE*SQ^*W43Kd87$Ns(*l1B(zY<&eOS0HN z!!Do0>tbv(@0OaKj%m^+e}%R~G}8Yl6d62Cxx^aMobak-X=sn?;05yC?(E&bIq?Ol zL<20mJW$mk90n&KygbDNY8>u?t2fK^Laq2tN!cIL#B>K3>Qp6LPRl2d*bkoG4I!u2 zI1pVZ@wN2)`%cghbgTY`;>-SGP*`OKZAf8mE=DS$AaZzbfOz06T-`0kNCxREw&xTO zt~p|t^1+NDHa@C2^DDrUVDi%Xs%y^F-Jwk?kCKVGDY9#W92k~)?5W^v+doyI8vI&n z#Q%{&Y#Lqg_SHP`Tq4gislRpdhLbnNI(Swd#k(EK3ing;-is(ZRvwFmHo4hk<7| zL!dIaW`xkB$#k)-Ip&0uj_DtXwWPM6D@GgfETZL6;oB=Q0P~Nk+%}FmeuP;3J8Rbl z*X_WLAk;E%k4W{MWPt@J_sf?&0&4*vu;q14C+Z}X{4SC5*^{mQKJL4hdkk{{bn6m$ zRk(zdF%MoAOix&_eJQS)O@OW+X{e@KrM-VovvrYq&ZIoZ5n85>(QJl8+vdP5wWcbX3Rqd0HKkewU-^H6f;6YjyTG z-qtB%Mv|utK$4Tbp<`RrFvHG?h5Q zV_m$B-9QD7e1{3~(Esca+yD`RbQ_`LtEJ;GGoD@kdE^;Qw>0yyaAVw%nem5B!1xRT!rW$X2OfB&0y<6v?{PtI z%aQ~G`Rav2kGrDc3dG9r5N9&PWJss?IsE0#;k911s_@78Qz}rHohkBT)|u=)c3@=qF(4t-g&2rS;wvf^64;mZ5DS{<@J= z{=(f;c|b=BSXbvet7vUG*o*TBgKqswz2y-a3G(+3Z?pk~Z8D#2L7DGRu-F$B>fBk>*9hx3y_2>~g$jDFs7g%7~a6XOEqb1DiGW+EhrxkGt{dDU<1kYr-*s z7RcsoQq3($PX%t$1;ywyq)vm4KSY~^ZK1bN~p?ckMakiMdi znZ1JHCm)}7fLwC`UV2lq?FT`(i)-TYOf95 z=mW0KM~q`~+GcSYQ_b?53j;^r*Sga}Z_j+jI6ItHJu34*g-TV|?4`WdtdNhQ{#yZ~ z$QY?ZHXTFlC@AQ%tt}ljp#ojC2(rn$2~(=fz~#)oqi5j(wfVLv_k`EG1(R>R7`vky zEYh~P;xR5K%`y4pJjIgh-5<3|IlE2f+ew)UljFw-9in)3srJc!4J+R5R$547teG5cd1aXyCmP}#rJ z@duq)L|S#=9J=Wzi>lF;*EzDS_k9=Fn<-8jrB(!&N{(lkHx0PB`|xm|BZphqe(ld7 zDADU1>BkN8M%4i$+NTUQ5#@p~Zb+HNBs$35AK~x6^xx)dP+&4PBzKO&ex(bzptN4o zz^$zy>$wpvJ?=)FqQ#SOcSni58ZyXm%u$@%1AbV8X%$>pe}RFvM?$z>w<;7sXX>lUVOvx^Mx$5m52b;W~I*)skhIB zJW`O30nOEHuYLR}#R0aY*KetVwn#WklkaMU~?^S^HYtReBdcQPC!AthF4JMGZOxebum2)_&4H{&9t;*Fhq zAKlRhgdkXMcKZ0;5CnXLv!=jzB(C^xSW(~YsSL)#mIdVMVj24EfiyY#M&`M3)%3VCw)WT< zgi7{Qm*B!L4Hy>2oS)h@nwpgbLeF9}xL~V~^x*wc3!>sWyX@M@-myB>ls_tlD6u1{ z-z7%|2KwzjoO^<&WMDGY86i5#bh6)JiPqtDkz3#@m>YSf!v{ns<<(jJJ)|#Q=VlJ_m29^&TOveCc5OlYsrh<5fW9pW^e3;i(J z@ZoT$?7*T?aTRp$*S~@s!rh)58}y3Mwj866Zpu~VG5aqnKzg3K);YDFT&q#+O49;b}TO_Z;kiNALWguR9G_84uLtFvT2ep;pPSSv4a{6G4TiUsS6VsM!n@m zU|mC8&&-zzgKQ9Lq_e1ljfPY1=l1=0LnOmKaloG0hXLnYtKxPF!$t%nwW27f+WFpG zqsLvw`IR}e9XUP#oRM5Kc)(`HqH=vlnWc+RCvR4GvH#Y3UA48x&K%>3_m_Upp2TjA);%=3 z2V@p_zLR!UKhD=-$7mUTHIVuia2t9mj=?N+pc#PjPXlBAjVmZ=WMG97E4rp)(LMM_ zA`MMK!HkEXD(w&pkRfGJ^?dbO)s01RXV&uPzl0b}4iCn@W&#>N8su#3L1 z9SJA|;3)9drs7_!(dge(9Or4QwM<_vUm4ZNOQRv*ezCX~ZxXlwnV_)2c6)Qeo>=)5 zzPY}SaAe9y+bWL)V(2}kwvRhQvA##$HJizdjdr&$r>Oa14fW&rM=LR_99xmV$i3XLKQI~-e{gW-xaJR=)x|r z!zS0SrI)cp;=Hf*9tH|w-G4eQr#4jGYCi2n(5L1#e?qgYIgp;3x|uM={d>S&LOlXtElgR+w=S*bntZ{#mtJb^ z!WNEaP`~QTNI`VmP2&se)8|_qLw}url6czI;fW|F21{#wS|?s;0jJ+=J6ogH1L|yb z1y5l~EU@p{n*7aTcv9&3#^4}Dn)>YZw-Ejm|6=uy2`m?=EPcTBB#T@C0&1IX7d(ty zjpvtc4K)GR+qsy&_O;0|FdUpLP!Jf^bcJa8{u-j5q-_yKI0%w&4!1YQFOMD@gAfn5 z_Dsr0VW%K*K9zdNbTN|aN-eU-k405pH9D&3?m!}{~e6x&Pm8s!46rBwUy z*Xjkf2~((P?{DB+>v~Q6&$h+I$F#k4ePG|suPe=Olf=b?Nhv_{)o~v1wyq~LDKgZ2WoJ;1CrhFukL-R|YUQ3LodyQq3s#!Q_HB%ziXDrnswelG=CFks_Rrk>O zuEo8iv{@{8$|5Gottv}3f?gp$2s9j-1iQBa5BKd<&VQ$nNwjNDp;u(HKXC55=BmXM z#2&cSrq~m>wyzB{>1R z@E?y8znvAPG+=7frb+5(m3e!hXDy>DN669Y4h!oQ^YBvE6SD;F3|U-D#RlO$I1L%+ z@^+e?V3bUmP!#FQZ=W^r_=)TKAz`T)$r{F?PQSbarC;9Us>M_2_c56BAdbxwI6FvM z_Vi6=Vm9OKn$#T6*_E+|^w>IIDY)CTV>+DVw+k*`tL1VdLe_J6=qsskg(AuXFHE-= z2ZOzMf)aW@d?ILlUMjz}igYuN>6?is4Z64)n-JbIG?xzAs|%XR7GlRzbM~@;R1TqH z1Q(GMRM!mxKXKtE76zCcOlQ>IAQfK19anFzxap{uvX>@q&dvZG-x1G(?pkvbX!CQX zc$0>uk3gs1+TJYAD5}2Dx+~@-G3}p+_G^#&jR9AC7N0l|7K)nuYJDj?OIma|8wUFi zSEH1yBn$MfPvp=ZOwPc6di^r7s*}0N5)Ml}_-!^>${TZQw7a_~H7Y2E6^Ue$p{plR zIcp*@|80X+815a*>%c)uF3S$+f8^zE z2VP)ZQ}#~;)mc<*oIdFV(|!rXidXVWwclf4ILB(ST8b^MTPAOv2ZC8qFYCM6(DMge zd$z?=N1Gl|$FmkOn$oeSAtmOS?D~{_sQwo6-@ztf{~>G)leC;sst|Y>2ZG9F^Tz#k ze?#-1fx&F$`!VTN_dAkFQETqK%Z5lK>xK<^BB-12j@Rn!9-Fp<3C8#cIcJz&f~1;b7Nph!>@=QoZVy$c z#o?L3D-2p=H`|zawT`qJhOL5RF?=EA%qIq9nE{6;3HC47U>u6{Tf-UQCm0B}jf9zl zu$y8o`xodlo|#7Dq|VGRl^Mn^L1y%0h(T{obhHu1{l(bhZX`O&wQzCTF&S z22YKs9T#pro=DFT^y@x%(R%Luv7dw@_Y1K*w--xsA02w{--yGmie2!5VeST%i%E6A zyV=k3qf^%o#xr9gUTpgLGR8XUns`fK3h#N)@Rp$cJs%e=>2+QH-r0z7^A}P*AA$Np z>!%h^)a|IgBK?e@l-`H;i|3;_9vf2OfzFy2gH&jM%$iS_W_mb~dfFd$9}}Wr9l=|x zCDSbtvu~7IY zLcAVwj@>JTCuozbOID(sob_$@&qV~jdS=tIcu}o4Rfu6UN~H+~aUcDgcjgSB7erRJ zOJLj(HsWvK0{h^^>)yk8N<`-%C1 z9sN+`GH-`mS3!MHk&PW#2mtG|W}zsMHd?p}%)zHUjl3tqxJCHl>Y` z_r@iG|IFY~-6o-^a8_6H^Yc_KEG>xms}BlA`kL;}78@p-)3Na7do33wr7s>>H43*W)Qq(^vtL_~g&#$yMEk@~LqT0cWz|ngMI#Lq zD;XYYs92<4XA%qfXDkOfdf?^K{!Q|w)pU@M;U5Q_b%iw;(U9N;O3nvABE$6mN~s8K zcdcJB1~TsW@EKr!0t^SEm7d^=b|)z0B&Q99X7Ocp$Q;o@hG}gF{qiUeeBz1)&$DHY zKlZ^hI?jtA5hzQ!zA28lNY=C>{+h1bC-3B##gF(0Opb=ut#jMZhf&aX+L|s-BhST7 zf4@K=pz>iHZSVsyP`5}lF{xJ^q%MnjPkc>HnV?Z>p@ilcqtj+120ptXw4wi4XjR0g zS9x^qhm#)sK-(|_w%2@iM&B-BLvV*I!ke~2Ckl^aBxMqNA+|niw&Nm6u54>b`oMxu(9hUq@dpj-8AJu@`uKUu7aZ zq?zshX1@QbLLlF^U~L~@I|=u6-){(J73A;?Sk;R$ZeRc*%z)V;x1ku)XGUh%1t8Ns z8+5x2qLSUU;W2P?wX7SqWO!t&Ft1d9Q zFw(QOPxQXRo-^vgPDGxD*Mp*vjB4*K9ie!6<_Z*IOu|wC)A*eQuyXD~=WB->^pxS5 z@H)=|_^67I&>Z2GkklLCrGG}Fivce_M&1vhOcb->Q{wv}FI2C)890XWD7o^_{vtr1 zdo-B(IMTmlh)CyO0(vk>E81+|gBDpT?{2E}Z~L%@hKjRfcTO)1VD{+KD^*)*dJtu{ zLrdr5M)CD9^vKhq#u~I}l>BDIcmtlI)b1ASYmI3TAfqLUkI85tIf5|SBNXQ)K4SQQ z*GrZEeus-Ei{UUU*Y~qN4Q*GexzJYqMp~L=+RqClJr4!ntu~`ZX|b&&^;6ylR5^HI zX0v;HXFKhu~iOIh*fRv4^$R9!)r2_uh zGF7`pm=xUp6tM;m#R6B=+tl0E2m!dG>A`32kCry)7dwfK%|C|k)+=9R>`T*?j}R$@ za}Whru&!Bae08imu`T(TnNq}81I2@W;6`$AilQIBf`w@Kp1Z28ny}NOIK?DtXXKp9 zloIG?3pO36WZPmr9tx#%$RI8~2Y27r#|2C#Zy8DqqoXap zDFL!jLj0#?E-0X|?nJ@Kh7IUg7f^*^4P+2-qMziBD(6Tt?bH$Fs)gka$G$OsQrK5??e>xlL_%QLLh}Q>+Vr!HGqV)Rpm`A{>kX zEw)*g&g;=Uo7eJ!0+27sjHN1z5&`3JmYqaZ1RC7W#?HXt+let*Se0!@2=qje`eK^z zNX)cx-H7Nzm9nLJefNcyOzq%xACh;W#-0mq&h3ECa1o%2t`_s>YPP;$ee zWIs~?Fq(CGA~*%1}*cAQ5;w7{fI3;my2Ww&%v0d5BbiBzEA zv95q=jUbbyoQRalTMdhtylG>F*AeK<@q-tDso~1hFc%M&Q8FDEB*quIvnL##(Q~NOM@btD9I+RL4`9dBVa;+oa13-78E#5e}mnw0A?PCJiMY% zN;^v%tu6}S4nXW)1PG_Z_iNkfGHz(4Lyp+tx0H;{7vm%Ud+e)PHSQMehVHIfQg~`= z2PB{-rG4K!VqW##U2YsPon8xOq7t=~BA3CkHABj$GSw6oYAHJBuh#EeM@=OfW@KmbbzfxFu` zEWbo8E-ZY_+X4PNAcH(^3D=WeNT6awoTD~hG}&p~VY~;5_s)XRFM-Dv|B z_{Yh9a?ddK=|L5PYqooy&uBgx@qldrG|!H{$28(FCLCX*D*x{Z1 zh_jhItE4x;wUgHq4=F!vmjPJcS+5{fpzj4*>U({(i^vC`(1JQ*lPCmb8-4r>k#h|_ z&6toPh))-38Kq9uHOS~~P4P&_MfC|36f>=E@pU4l$uTsEN8~8dIW+?cPuJ*kx2pN& z2+P__kJApn*aP~oxzJ{o?s~;_EKZ7z$s#_Cj40@DOmlk2Sg@XPP`N872vWlWLnle+ zi(&1zCYK98HqEc#_(6rxaWv4>JGyr}q`Ag9jlco(3Y$LapWF+ds20ft96=p7;}J~U zt!zJvfS?f&>s}{77#lAm|9ZCXy6Nf;jz`KrUJAY#helG3TM<=3*7$Q=JNc3e3~_-EMk+UNEa;z=?m8+Pjd7$j>3~kSqwB;r7su zSRT9aPb_H8B3PBx1OLj=8+_vw9L`J9lV+)gqWFXJFT^@FPC3CT@u-@1mk(x#^ntRn z4@7<9x7PVpFymqVohqDxE1$4r<6Tlq>x#;FPhs3cJ9LaJIHve2#l$NX%`c{K5EEI; zIo@4EW{vg4+4On131}B?x9T(lzUoyrI=;@yqnF;rI3Qb6tC3o@#r42?>;JV&TE3w3 zb1Al%)p$3idMw~_2C?~^LO?~giJ7+7M1z(29oY)U^f=6Ww(H5H^IYo9Z2u*A!CRws zl!;aRB71GhfYi@|aNc)Mq9s@u+ULz!iGK z7)tnMZ$O>2iqoRoV;b8}>aYKM&jV63DNq(voiFkzq~fhWy<1*)WP^$MvAX6_EaqJc z3K?0QVL~K~cO8L)4|+7X%O@aTPq(Z>A)?^BA$00#J3r_|G#Rp3mJP&s-MR2ukjl@j z@B3saG!CN-wfrQfiuPBQfuif2*#p5%A1V==VH0vs9C8tOGLWF^2som>iC+&O0_loy zT!N)FNIZ%InUZa&$r&bBrn8JArCZIze7bxTTw1ump`6tHt~8Xy7cH7 z=Of@OfOJ|+J~sD93g9{$c|ecP&zv8pL^;46!;t*v-MwC_o{c)dC=0NKHxtqvHYw~# zEuCXxc-IY7^AJ!Cy~M?Td;rss5xd|z{9rt-D|m}9$^lE-tguegL((VbCC=Kl<*;kQ zC$Cewp(=eZ>M>;eCTLD-o6U}Wu{y+(zNi*L-{EH=JD~J`1!;{+WZ0E!^W**wG0q0c zoiCO+8<*m4TImqMfgkogBgpM#B~aU+>rIbTKy$6sQ`bIMa2x)mNIE-o^@gtB-eDkl zu9!Rb6y$IZ;Ir^;o^vFf+Va$OzK#3M*m@Ze+@VOcg;h7##pC2vyLU-8i$y@61Em0ew=opCRmbd^7ydnJ?chbV#n&Mr#0;P6hupA)+{{?@huX{ivhY?~wn?8+ZLDd&BN?vdA6NpL? zQ5Bzo?lE9lf4SP-%Bziw=1`?uUtBlopI)2zGaR~vWgUQo!E>I?e*zRKys0~r@!ti$ zpd|P9d}5oSaR{s*5dqKsF4P`AKpSI_@(A>NLdz@$Um`l2Sl_7u%OEvgB+R!{_#~+5 zcbzou-9`5T0CdNa=?b)zg_FEX?ru34HdRak1c~#+h2wrIPzx#Z^e)$0nJB@pG%4i! z#($|OM$Tuy(=^1$WL<~0*UlW^m!|%DV>_vd;VaEi#9EaeudulGEUtat6Z_k3(JxR3KQCG1}O!~cWhYn?G8K4JR@11KgEww04h z;NZ=~5FZ*St6g}*qdD7a5n4B+to^j5&yyRdP|LSujqk{Dx*J?H*@vPjUdjj~tHtR( ziH}zZ3U)5-vwxh7Zw07BnBs<_q+cE6iylgTi3p4kGB0YDVYOu0=GEWu+V)u65J=jF zK4We$tI&qeoC#!|DXQ;!jChM==(VC)HKI449kw-))Tm2WGfG(!a%lAoZM?a$rFyUm zT!m!(nvuhr2Z*V9dnTC}?QjuENr zloB9vGzL)@RzV&ziWoPsB2?u-4&xqnc$>!}so1X2iLZC?eHqRg;66iHbkXPvBp<%o zKT3)NwxvhYs0M3ZKuay#cxfz#SR`u{V-G-r)W~M>uLlR*(gJZnzO$;W1;Q3l$yt-j`r8t!meFf5rWy5Ww|M26lzOt# zTEaTaD>H#&TF?-QiTfY;rQ0nc&_S5Lf0;RAP21btap!{Pp?PA_ofl(|oSX6ZyV&aa zQH24Q#Bg@hcptH=*1<^4ovh&yt`7|fJDODG@7g!3lyBQV&MX@GlliMW2Y?`tyFJl| zTZ(Nf3d1IMCg|MRSN&A>*IC3W9p3|k^A!RUF0-$#tpz;E6d0klV2Y8n!I zQ@nswsSRmo^##L<6$+O3m*`5WkOMbJ?w}Cn%;_W`X{)8$6-gtxDVAcREq?BBl5??F z)Uj{9hm+zhV7`f^+q;hsnbzGy(hW;X|v_xoRP$rQFCks+;l=H*+Ok0>e+lX4DjM({JArtjUlg=UI+D{f4&lsA1db)G8I- zDcQvP@ZLH?c*B?3Im*Y_UP*FD53iynTDSSTQ57x@*K21})>P|kRl zYt9p3N1Pze{1I%7{}Ztu8h7WV&KXjtb&8+Kl2EKr*+lf6(#Y-BDcgE^jiCbpK3JRt3^1=*XirbtUaQNr+4oLAzDn~+ z4nB%Jvq_J$n*7WjJAkLZ-U!pCTkJk?f~>A@M-E~4rs?pvMo`Te=84?g6#Zd;s>%U7 zAdc33z}DPfVbp{_Ocu96t0Vvr$yC)ziXkGN>1WjE(LG1~>+wvO{%^n2p?P*PKSO?)=e)Ekx0kN0;nRmLs+Pf@0N1lAKM&qJ9(9gmFdbfz%TVJon8SD4 zXlAW1Sefzu?YWfuG}C#nXpB6SpLZ%?O~2lWmE&jweeB6NQ(q{Z?7D2RDR%zx3A6V~ zi=Se0&wUttpz6uY0-bb94H`su*Bwh}O)6c9dxrccR7p9y5jjafAxtpp*jAfaulzX{ zVTx!{2y~IuXWq8gdDMi0|L#nLsi6;_^E(cz=H6VIeQ8}Q z)_4%hozOF?41b}5wXEUA3{Z;8{j5Uf+3#x~8b>4W5^YCinVpVkocf~W2VWkP* z#EOk*DcUeo2o6dz`uB_pE*+tcdfG>qGLYw}$gz?hbX2`^#~@9e1_y4ZvJg$MzrpRn zs;9$%ZdVDYb07pNHT}C@FwQyy-}7g-BC)%pg~AX5x1H zDvNssOAj`t;PDrVu`i<$sW(Ar}X_5XxRbl8f`p^c2wkUNxn z1-V;2;muqFQW10KM8WV(l2Lf=zZ{n{i@oq##@9mNDvb%X>BZ1wEnZPzrTXG!gD1IK zlfS?)jGBI-J;fj**7fnufo#t z!_%@0!zA^3IZegT#*~t7$RytOOs}G5YiOgTcDk{wOUp|Bd<(1$fO-;AX{y)N`Bb=z zX!UWQRN28QrxPNVy1nX8Qohq3H1e`|zee-}iZZ#sXu~7s7-~WUU>O~QjnGJM>J5SE)n_#z~TwO2p+w1^&GyEdphlv9x6AH?@e6{J#GC#H(c$7^5}l4GRu0)?>m4&J5|8pR>3uJfVlzuIk@r->;8etQ3M-Yil!)MGOoa`pE z)N=f0&+{8O_ZZS>tpZ6t767)Mum2Sm*WH-i*bLUVLg6T+rKg>IN6aS8q5L4`OX)P@ zeP_9eiiY<^w8=*2{3z2GrO|r@FT&iJll^~x_gRLr5z{Efgg5u+w527zOpF(Fhl9B* zv=~=pZosZ9%Gy8LUj+NjiJP+-n=$hZF*ty``)!$)M=!7{wqS7X;tVyQ%}z+DA(PAC zM-&u-PHwg>)8y$lIi2#z>f&nBy2xh^{`GvOem>e)=$**rDo(n5>LrF6OZ_~iyvpj= zH+93MUf~PTqQ+_7^+?+>X|`gYKeg=%Cf^B!L9`HgW`XJ-+F_As*kC`jq{LS|u@Z%n zoUM(UM1sxdpnK`Uojo5_KXdTbiMLr_O&XMB+ml8! z)F{{XnyRD`Gd)(~oU*g{Y${O?;}0-=dWYUa|D-31J^thEid1bA3n4ysBWVTr@cKC! zhO*MgKN018NrFGeQ8|HAU1}~So=S)1uE4@bIecoQIlBMoRloLM;NNFRT!Pa0w@u7y zEjz6paWj#n|Aq62>>AfMBtq&BP}Cs-YU&fw%S6;hfy<*r?g%9@ZG#> zdeuSiw<%|mM_isOHK@#({|=nHTgV2)reiYcNwhH9^MkcjM039F zI;axhlm=A`&#zKh#Doxb{(Dqnzxcyhr{o{u&+r^3LjcQD6p(%UUdMpmy;f$>JLA!M zh-((Jzz|ow1NuorMG5P9C$6vc_80)chI`vCl%Iz55!F}6=7Kp1vnJYu+i3ONdZem1 zXWoNk9Q%m6j^1p#honSmq0UvuC2Ngeq@4A%>qS2QkV$Vv1KnJN)pg#Hi}jAEBLc(j z0edg1c+nKlmQL-9xLJM+RQ8(4MTE3D!yv2d0vIVmZplQ#OJbde-&GugZ`3&8?8krx zZGBLV*|&s$45P5W;2S$e{kyK!@V;4fz@7?>)yYpUC2yy|vPNmr$l|u{&?i8z;wB_( zwa!5kw5psL*C3wm7qKpqz7vmj%l-$@rO3{0=6d+@%onuWE!`Oda+BP9_i)juw6N`R z1HLyf<_%)aY8>*fj*5 zx;dPW0u^OSQiLXU+<=HntzBh>%qT3}*Ju)Sc#!TahtS;8Elai*TUWG*3~v?_YB@GA z?g!dTvqcO%bJv7*Rl(xX3nn7yRW_Le29}524ObxXIw2hfG9;L&TmFD~>KZ(&nT!z^ z+l?NLML+e0qumGK0d6D*_o_1fwBpLGRsXF-mx(69&AC;u5fP0JHKew;2>CXvc#8? zEqT+DvG%H2f|QH`3fZ0c>`5(8>6gh^4ogBla)2LB ziy+BF5C=E=;KASHD(xcS$f!hxBjo#GQpPHCim~KiQ4VF(3lb@C^;k9k>=+0TFfm8Z z+=Tu6dXJ-H{7xUl68Mh@tCf@8BASOTpI8Zuqn=(7!bho`56C2-AWVg8F&^UBg$fDv zS%6975fk!Zu}2G915COAdE$I}r|1mgyQ;m7CIrFhg{X$rdw33kZV;qmql{C0c812f zIKw1GGlT4OdBLTDr=1M{-+*4i)T~Af1r#3%6DupXY+GZcj!;!|T%J^teXtcaM;5F3aTc++a?1a*Zrk zn2#MWi*JI1-KFZuC?`pp*JzO>7?%faPq)Fu(oVeH6wzwerHio5u(om(NdgrwU%XFv zDUr&<>esNh1SxKi7A^|+*JpHY7mp%Uwd+2yt@kqRU31h-;mu0ayoZ$e4S@593X{rW*;s%PNAdCd z;&|~hLvAlvd2UnVpBp5>H(>xwo)y10HAYtywBflA8d=MN2#d3_F9LSV^bu#VsH}UV zQA){?tw)PsK;Wc6=LOh1dD+0|Qinn92i_)66y%@44O%e#=^NEd_4eR%S(@?QnTdpn zW{?%@m%jbCxNxhJcmtl5NVF0Sqn9MTZq1WD#VfQnkxhmcg*eJ1`Fb{J!UIk0(|IQg=-7TaEv{ z`mZg&og^(xShK>g?d@n|F{gZqf>6i8UHJkr8r%M-JwQYx*4MK|g&BXfcu!(nV29;b zCQViu5;g?1q~G^4hlTyF#6{jXl;J1VfpHBfLB=E8Uza}gJUdTSM1%tKaJ{No+vu#2 z+s6ehdho1Ep{cTResWQ`4;1R_A3K${s=>A;GDq^#-v6XS`gY&zp{2bA#oY##i(x;m zhz>n7D-*XwR{~mpwBYyS$;(YIkl=OQi&r-v?q)VCeQZ2ce=hkLCX&^zIFc79sM>uB z8cH~Ieff8AzKeHlwv=spuzd43zni;mqw>}>->f{8(9>`7K{trCzp@g^hQd**FibQ= z4B2}x-%=1`x*L0hl5u<2h(xFvo~?UN;z9;w8cFTy%05b4)P$LvW<_ga)@-|G{<9o2 zX#;KRg_IiY>laaH1QAVsJBld`vYTZ1E6=)?l#^|%STFccHIly(cYyW4 zt1wHjf2$D?OS?mnnSs1Tf(x9D{E-HzZd$;OBsiu%7~_^>@`q~^|65mqMYM0^pONJV z;+BZTD0;V>-!9P`fDe@GTF#}hTlZPC)# zEuUAR93X%@v#o161Fik~ff>T$Y2lo;Vxn*B_)q(=Gj!Vw-e!YPWvScAH9%u_~glnCk zz<+2F?*SlNP#uw*;&5t3k6s{`uyr%&J-fC<3w*G1SKbT7vU!_Imr?Tw)C&A^f(91b zSz;yC$pMoX@Z${U32NllWVL^bRj^0U`I}%kJ`Z_7v613ON%$!0S~N^5R1sp4VnVVc z4ep+J)=J1DafNKuXVUQiyCcMC|6ekgrAZM7kO2!?Hb<_t6e+2E!|zB-dS%qa*&CE% ziFDUKSK9+%L|NalaUiErMCS|YHj2sW?MpdZaSYxhFT?l*qIuD>4VP;QMuMCcPahgf zqyad@8#C~*W$Vmy;B$rc$Y}T?NLgH@Vn?`@%&c@+D|;tdFRAiahZpY!-hk#wxquht zDYallzQ$}-PbeF(`YZ0&9G#KGYl#vx`I}ojB{o>gvQUa|)PmX#^f|?CHG_xeg|sAn zNh_(FcCG&Q_?Cr%@cod>u)*ZxZ&FbgJDk_YyE^Bh2+*KTzviMA zuO3BcWSNpGeM=QW_{6VWRpHs<%;B@_V%naL^GVPXq}EF+J4vI$bJd=R-1cDPW^9rD zS!;}iGH)B&vg{Z3rD0j^WJiNVHI36C{m9@>{^o*R+)O&%@=}*DAT!=(AMb_XDrfc( zWyKfS6npB|{jU8tuNI?rSA;;Ci3+UTDBqvb(XQE^E~a?6 zk$p|*reV-fJ12i-)cqD0=~ykmcTLezM=Q2GQ@5_+NKFEiPVqjpTezTIERw?TtPv>s zxtv(>TmD{s3fotzPd>i95L|kd;v_oI{8^ONpQ~nGmK8YLKGFEv;*Td0oG}JWrNgn* zD_zwe>`BA{Ef!gAPF%a`a zQm_d8F5D+gPd734&H;XIFK%3O&A*?Fko zssD^@QrEAmW8dh=l6<29jByw#A%~E9c;&av(}uez18>&l?TmF%5?nWs4m?GP;#hZe zqn#>&f(twbaxqW&Qo!67a?oNuLN^|U6?Cs8PSu4i71E!Bmn677D~mq;5|O)}UT!$N z!IJ5O# z3Brb+EneAD8@`-w7xgO^Yynax4tm?8a&iwZeS>U#t3T2lz#CQupRcp8mDp6K zcF5j`vtQ-~G2I42+UE#$^W?HzRPT&fwD`ELfek1!`v*F8mAkReR^7`{!kxGG{Ftnk zH%FxZo?>XZZ#+#;`8T>zTGzHOT2rpdM9%f+dH4>4@7i`Mp=>cHAG0quTZwpgFuPIR z#&=pMPAR482_f0ExdItfc1A-7ul7$zk4W3wQaREo7SUTit=`27#?X2P7WV)ahHGGB!zLqu!9x&dds!r)0?vpuuSnmu<(8^_M<$~e$qeptZNC>-Oh zdV=CPEExU6oXlzG<0FmVsT)`LrDXLwzTrlIK!mt5=}uyDJ6J z#x}2?`2#KqKYp|=3DH_j)&o~02ypQ-59GuMSBh7{Bi7S!H_Fc-;0Ewgfb