From f55da0db17575d8f7a81e3dea8033df39d010907 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.0.3@4306 a1ca3aef-8c08-0410-bb20-df032aa958be --- CHANGES.txt | 98 + CREDITS.txt | 25 + LICENSE.html | 386 ++ Makedefs.in | 138 + Makefile | 92 + README.txt | 200 + backend/Makefile | 116 + backend/betest.c | 85 + backend/ipp.c | 652 ++ backend/lpd.c | 409 ++ backend/parallel.c | 196 + backend/serial.c | 314 + backend/socket.c | 254 + berkeley/Makefile | 95 + berkeley/lpc.c | 467 ++ berkeley/lpq.c | 369 ++ berkeley/lpr.c | 294 + berkeley/lprm.c | 221 + cgi-bin/Makefile | 83 + cgi-bin/classes.c | 486 ++ cgi-bin/jobs.c | 584 ++ cgi-bin/printers.c | 488 ++ conf/Makefile | 71 + conf/classes.conf | 79 + conf/cupsd.conf | 369 ++ conf/cupsd.conf-personal | 250 + conf/cupsd.conf-professional | 313 + conf/mime.convs | 62 + conf/mime.types | 122 + conf/printcap | 2 + conf/printers.conf | 96 + config.h.in | 116 + configure.in | 342 ++ cups.dsw | 113 + cups.list | 319 + cups.sh | 117 + cups.spec | 134 + cups/Makefile | 152 + cups/cups.dsp | 176 + cups/cups.h | 144 + cups/cups_C.h | 123 + cups/debug.h | 57 + cups/emit.c | 301 + cups/filter.c | 299 + cups/http.c | 1507 +++++ cups/http.h | 293 + cups/ipp.c | 1457 +++++ cups/ipp.h | 343 ++ cups/language.c | 390 ++ cups/language.h | 200 + cups/mark.c | 412 ++ cups/mime.c | 622 ++ cups/mime.h | 137 + cups/options.c | 378 ++ cups/page.c | 189 + cups/ppd.c | 1814 ++++++ cups/ppd.h | 239 + cups/raster.c | 252 + cups/raster.h | 233 + cups/snprintf.c | 287 + cups/string.c | 125 + cups/string.h | 94 + cups/testhttp.c | 109 + cups/testmime.c | 199 + cups/testmime.dsp | 102 + cups/testppd.c | 183 + cups/testppd.dsp | 102 + cups/type.c | 1014 ++++ cups/usersys.c | 175 + cups/util.c | 1109 ++++ data/Makefile | 56 + doc/Makefile | 118 + doc/cmp.html | 753 +++ doc/cmp.pdf | 941 +++ doc/cmp.shtml | 717 +++ doc/cups.css | 4 + doc/cupsdoc.css | 9 + doc/documentation.html | 72 + doc/figures.sc | Bin 0 -> 51020 bytes doc/idd.html | 901 +++ doc/idd.pdf | 1517 +++++ doc/idd.shtml | 1250 ++++ 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 | 292 + doc/overview.pdf | Bin 0 -> 20469 bytes doc/sam.html | 1022 ++++ doc/sam.pdf | 1216 ++++ doc/sam.shtml | 1088 ++++ doc/sdd.html | 569 ++ doc/sdd.pdf | 962 +++ doc/sdd.shtml | 557 ++ doc/spm.html | 4090 +++++++++++++ doc/spm.pdf | 9119 ++++++++++++++++++++++++++++ doc/spm.shtml | 4555 ++++++++++++++ doc/ssr.html | 338 ++ doc/ssr.pdf | 426 ++ doc/ssr.shtml | 272 + doc/stp.html | 247 + doc/stp.pdf | Bin 0 -> 17648 bytes doc/stp.shtml | 169 + doc/sum.html | 628 ++ doc/sum.pdf | 923 +++ doc/sum.shtml | 578 ++ filter/Makefile | 151 + filter/common.c | 255 + filter/common.h | 67 + filter/hpgl-attr.c | 442 ++ filter/hpgl-char.c | 498 ++ filter/hpgl-config.c | 647 ++ filter/hpgl-input.c | 232 + filter/hpgl-main.c | 255 + filter/hpgl-polygon.c | 380 ++ filter/hpgl-prolog.c | 369 ++ filter/hpgl-vector.c | 707 +++ filter/hpgltops.h | 232 + filter/image-colorspace.c | 883 +++ 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 | 1620 +++++ filter/image-zoom.c | 310 + filter/image.c | 779 +++ filter/image.h | 225 + filter/imagetops.c | 568 ++ filter/imagetoraster.c | 3975 ++++++++++++ filter/pstops.c | 872 +++ 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 | 124 + 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 -> 908 bytes man/backend.1 | 102 + man/backend.z | Bin 0 -> 1569 bytes man/classes.conf.5 | 39 + man/classes.conf.z | Bin 0 -> 578 bytes man/cupsd.8 | 48 + man/cupsd.conf.5 | 37 + man/cupsd.conf.z | Bin 0 -> 504 bytes man/cupsd.z | Bin 0 -> 903 bytes man/enable.8 | 64 + man/enable.z | Bin 0 -> 940 bytes man/filter.1 | 108 + man/filter.z | Bin 0 -> 1862 bytes man/lp.1 | 111 + man/lp.z | Bin 0 -> 1464 bytes man/lpadmin.8 | 124 + man/lpadmin.z | Bin 0 -> 2522 bytes man/lpc.8 | 79 + man/lpc.z | Bin 0 -> 1263 bytes man/lpq.1 | 52 + man/lpq.z | Bin 0 -> 709 bytes man/lpr.1 | 96 + man/lpr.z | Bin 0 -> 1448 bytes man/lprm.1 | 51 + man/lprm.z | Bin 0 -> 748 bytes man/lpstat.1 | 115 + man/lpstat.z | Bin 0 -> 1980 bytes man/mime.convs.5 | 43 + man/mime.convs.z | Bin 0 -> 723 bytes man/mime.types.5 | 40 + man/mime.types.z | Bin 0 -> 621 bytes man/printers.conf.5 | 39 + man/printers.conf.z | Bin 0 -> 575 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 | 2348 +++++++ 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 | 227 + 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 | 723 +++ scheduler/auth.h | 108 + scheduler/classes.c | 544 ++ scheduler/classes.h | 43 + scheduler/client.c | 1537 +++++ scheduler/client.h | 94 + scheduler/conf.c | 945 +++ scheduler/conf.h | 112 + scheduler/cupsd.h | 140 + scheduler/dirsvc.c | 558 ++ scheduler/dirsvc.h | 58 + scheduler/ipp.c | 2625 ++++++++ scheduler/job.c | 982 +++ scheduler/job.h | 75 + scheduler/listen.c | 142 + scheduler/log.c | 372 ++ scheduler/main.c | 443 ++ scheduler/printers.c | 1237 ++++ scheduler/printers.h | 81 + scheduler/testspeed.c | 126 + systemv/Makefile | 114 + systemv/accept.c | 261 + systemv/cancel.c | 247 + systemv/lp.c | 307 + systemv/lpadmin.c | 1154 ++++ systemv/lpstat.c | 1275 ++++ 746 files changed, 215677 insertions(+) create mode 100644 CHANGES.txt create mode 100644 CREDITS.txt 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/betest.c 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 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/printcap create mode 100644 conf/printers.conf create mode 100644 config.h.in create mode 100644 configure.in create mode 100644 cups.dsw create mode 100644 cups.list create mode 100755 cups.sh create mode 100644 cups.spec 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/snprintf.c 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/spm.html create mode 100644 doc/spm.pdf create mode 100644 doc/spm.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 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/lpq.1 create mode 100644 man/lpq.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/log.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/CHANGES.txt b/CHANGES.txt new file mode 100644 index 0000000000..4d9f5fc6c4 --- /dev/null +++ b/CHANGES.txt @@ -0,0 +1,98 @@ +CHANGES.txt - 11/04/1999 +------------------------ + +CHANGES IN CUPS v1.0.2 + + - The HP-GL/2 filter didn't always scale the output + correctly. + - The HP-GL/2 filter now supports changing the page size + automatically when the "fitplot" option is not used. + - The cancel-job operation was expecting a resource name + of the form "/job/#" instead of "/jobs/#"; this + prevented the cancel and lprm commands from working. + - The backends didn't log pages when files were printed + using the "-oraw" option. + - The authorization code did not work with the Slackware + long shadow password package because its crypt() can + return NULL. + - The chunking code didn't work for reading the response + of a POST request. + - cupsGetPPD() now does authentication as needed. + - The N-up code in the PostScript filter didn't work + with some printers (grestoreall would restore the + default blank page and device settings). + - The N-up code in the PostScript filter didn't scale + the pages to fit within the imageable area of the + page. + - Wasn't doing an fchown() on the request files. This + caused problems when the default root account group + and CUPS group were not the same. + + +CHANGES IN CUPS v1.0.1 + + - Documentation updates. + + - Fixed a bunch of possible buffer-overflow conditions. + + - The scheduler now supports authentication using PAM. + + - Updated the Italian message file. + + - httpEncode64() didn't add an extra "=" if there was + only one byte in the last three-byte group. + + - Now drop any trailing character set from the locale + string (e.g. "en_US.ISO_8859-1" becomes "en_US") + + - Fixed "timezone" vs "tm_gmtoff" usage for BSD-based + operating systems. + + - Updated IPP security so that "get" operations can be + done from any resource name; this allows the CGIs to + work with printer authentication enabled so long as + authentication isn't turned on for the whole "site". + + - The IPP code didn't properly handle the "unsupported" + group; this caused problems with the HP JetDirect since + it doesn't seem to support the "copies" attribute. + + - The HTTP chunking code was missing a CR LF pair at the + end of a 0-length chunk. + + - The httpSeparate() function didn't handle embedded + usernames and passwords in the URI properly. + + - Doing "lpadmin -p printer -E" didn't restart printing + if there were pending jobs. + + - The cancel-job operation now requires either a + requesting-user-name attribute or an authenticated + username. + + - The add-printer code did not report errors if the + interface script or PPD file could not be renamed. + + - Request files are now created without world read + permissions. + + - Added a cupsLastError() function to the CUPS API to + retrieve the IPP error code from the last request. + + - Options are now case-insensitive. + + - The lpq command now provides 10 characters for the + username instead of the original (Berkeley standard) + 7. + + - The cancel command needed a local CUPS server to work + (or the appropriate ServerName in cupsd.conf) + + - The cancel and lprm commands didn't report the IPP + error if the job could not be cancelled. + + - The lp and lpr commands didn't intercept SIGTERM to + remove temporary files when printing from stdin. + + - The lp and lpr commands didn't report the IPP error if + the job could not be printed. diff --git a/CREDITS.txt b/CREDITS.txt new file mode 100644 index 0000000000..1b970fb50c --- /dev/null +++ b/CREDITS.txt @@ -0,0 +1,25 @@ +CREDITS.txt - 10/01/1999 +------------------------ + +Few projects are completed by one person, and CUPS is no exception. We'd +like to thank the following individuals for their contributions: + + Nathaniel Barbour - Lots of testing and feedback. + N. Becker - setsid(). + Jean-Eric Cuendet - GhostScript filters for CUPS. + Van Dang - HTTP and IPP policeman. + Dr. ZP Han - setgid()/setuid(). + Guy Harris - *BSD shared libraries and lots of other fixes. + Wang Jian - CUPS RPM corrections. + Roderick Johnstone - Beta tester of the millenium. + Sergey V. Kovalyov - ESP Print Pro and CUPS beta tester. + Mark Lawrence - Microsoft interoperability testing. + Jason McMullan - Original CUPS RPM distributions. + Wes Morgan - *BSD fixes. + Ulrich Oldendorf - German locale. + Petter Reinholdtsen - HP-UX compiler stuff. + Stuart Stevens - HP JetDirect IPP information. + Kiko - Bug fixes. + +If I've missed someone, please let me know by sending an email to +"mike@easysw.com". 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..adec18f3df --- /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 +MV = @MV@ +NROFF = @NROFF@ +PACK = @PACK@ +RANLIB = @RANLIB@ +RM = @RM@ -f +SED = @SED@ +SHELL = /bin/sh + +# +# 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..94452385c1 --- /dev/null +++ b/Makefile @@ -0,0 +1,92 @@ +# +# "$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) + +# +# Make a software distribution... +# + +epm: + epm -v cups + +rpm: + epm -v -f rpm cups + +deb: + epm -v -f deb cups + +tardist: + epm -v -f tardist cups + +# +# End of "$Id$". +# diff --git a/README.txt b/README.txt new file mode 100644 index 0000000000..0fdae99510 --- /dev/null +++ b/README.txt @@ -0,0 +1,200 @@ +README - CUPS v1.0.3 - 12/15/1999 +--------------------------------- + +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) +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 with glibc2 or higher + - 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 available from: + + http://www.easysw.com/epm + +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. + + +READING THE DOCUMENTATION + +Once you have installed the software you can access the documentation +(and a bunch of other stuff) on-line at: + + http://localhost:631 + +If you're having trouble getting that far, the documentation is located +in the "/usr/share/cups/doc" directory in the binary distributions, and +under the "doc" directory in the source archives. + +Please read the documentation before asking questions. + + +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. + +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 + + +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. If you are running a version +of Linux, be sure to provide the Linux distribution you have, too. + + +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 diff --git a/backend/Makefile b/backend/Makefile new file mode 100644 index 0000000000..a526c45e9a --- /dev/null +++ b/backend/Makefile @@ -0,0 +1,116 @@ +# +# "$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 = betest ipp lpd parallel serial socket +OBJS = betest.o 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 + +# +# betest +# + +betest: betest.o ../cups/$(LIBCUPS) + echo Linking $@... + $(CC) $(LDFLAGS) -o betest betest.o $(LIBS) + +betest.o: ../cups/string.h ../Makedefs + +# +# 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 + +# +# 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/betest.c b/backend/betest.c new file mode 100644 index 0000000000..1ea64c5991 --- /dev/null +++ b/backend/betest.c @@ -0,0 +1,85 @@ +/* + * "$Id$" + * + * Backend 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" 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() - Run the named backend. + */ + +/* + * Include necessary headers. + */ + +#include +#include +#include +#include + + +/* + * 'main()' - Run the named backend. + * + * Usage: + * + * betest device-uri job-id user title copies options [file] + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line arguments (7 or 8) */ + char *argv[]) /* I - Command-line arguments */ +{ + char backend[255]; /* Method in URI */ + + + if (argc < 7 || argc > 8) + { + fputs("Usage: betest device-uri job-id user title copies options [file]\n", + stderr); + return (1); + } + + /* + * Extract the method from the device-uri - that's the program we want to + * execute. + */ + + if (sscanf(argv[1], "%254[^:]", backend) != 1) + { + fputs("betest: Bad device-uri - no colon!\n", stderr); + return (1); + } + + /* + * Execute and return + */ + + execl(backend, argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], + NULL); + + return (1); +} + + +/* + * End of "$Id$". + */ diff --git a/backend/ipp.c b/backend/ipp.c new file mode 100644 index 0000000000..de26c25a22 --- /dev/null +++ b/backend/ipp.c @@ -0,0 +1,652 @@ +/* + * "$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 */ + ipp_status_t ipp_status; /* Status of IPP request */ + 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 */ + ipp_attribute_t *copies_sup; /* copies-supported 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 */ + int copies; /* Number of copies remaining */ + + + 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 + { + strncpy(filename, argv[6], sizeof(filename) - 1); + filename[sizeof(filename) - 1] = '\0'; + } + + /* + * Open the print file... + */ + + if ((fp = fopen(filename, "rb")) == NULL) + { + perror("ERROR: Unable to open print file"); + return (1); + } + else + stat(filename, &fileinfo); + + /* + * Extract the hostname and printer name from the URI... + */ + + httpSeparate(argv[0], method, username, hostname, &port, resource); + + /* + * Try connecting to the remote server... + */ + + do + { + fprintf(stderr, "INFO: Connecting to %s...\n", hostname); + + if ((http = httpConnect(hostname, port)) == NULL) + if (errno == ECONNREFUSED) + { + fprintf(stderr, "INFO: Network host \'%s\' is busy; will retry in 30 seconds...", + hostname); + sleep(30); + } + else + { + perror("ERROR: Unable to connect to IPP host"); + sleep(30); + } + } + while (http == NULL); + + /* + * 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... + */ + + snprintf(uri, sizeof(uri), "%s://%s:%d%s", method, hostname, port, resource); + + /* + * First validate the destination and see if the device supports multiple + * copies. We have to do this because some IPP servers (e.g. HP JetDirect) + * don't support the copies attribute... + */ + + language = cupsLangDefault(); + copies_sup = NULL; + + do + { + /* + * Build the IPP request... + */ + + 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 != NULL ? language->language : "C"); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", + NULL, uri); + + /* + * Now fill in the HTTP request stuff... + */ + + httpClearFields(http); + httpSetField(http, HTTP_FIELD_CONTENT_TYPE, "application/ipp"); + if (username[0]) + { + httpEncode64(password, username); + httpSetField(http, HTTP_FIELD_AUTHORIZATION, password); + } + + sprintf(buffer, "%u", ippLength(request)); + httpSetField(http, HTTP_FIELD_CONTENT_LENGTH, buffer); + + /* + * Do the request... + */ + + for (;;) + { + /* + * POST the request, retrying as needed... + */ + + if (httpPost(http, resource)) + { + fputs("INFO: Unable to POST get-printer-attributes 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, getting 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); + + ipp_status = response->request.status.status_code; + + if (ipp_status > IPP_OK_CONFLICT) + { + if (ipp_status == IPP_PRINTER_BUSY || + ipp_status == IPP_SERVICE_UNAVAILABLE) + { + fputs("INFO: Printer busy; will retry in 10 seconds...\n", stderr); + sleep(10); + } + else + { + fprintf(stderr, "ERROR: Printer will not accept print file (%x)!\n", + ipp_status); + status = HTTP_ERROR; + } + } + else if ((copies_sup = ippFindAttribute(response, "copies-supported", + IPP_TAG_RANGE)) != NULL) + { + /* + * Has the "copies-supported" attribute - does it have an upper + * bound > 1? + */ + + if (copies_sup->values[0].range.upper <= 1) + copies_sup = NULL; /* No */ + } + + ippDelete(response); + } + else + { + if (status == HTTP_ERROR) + { + fprintf(stderr, "WARNING: Did not receive the IPP response (%d)\n", + errno); + status = HTTP_OK; + ipp_status = IPP_PRINTER_BUSY; + } + else + fprintf(stderr, "ERROR: Validate request was not accepted (%d)!\n", status); + } + + httpFlush(http); + + break; + } + + if (status != HTTP_OK) + { + if (fp != stdin) + fclose(fp); + + httpClose(http); + + return (1); + } + } + while (ipp_status > IPP_OK_CONFLICT); + + /* + * See if the printer supports multiple copies... + */ + + if (copies_sup) + copies = 1; + else + copies = atoi(argv[4]); + + /* + * Then issue the print-job request... + */ + + while (copies > 0) + { + /* + * Build the IPP request... + */ + + request = ippNew(); + request->request.op.operation_id = IPP_PRINT_JOB; + 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 != NULL ? language->language : "C"); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", + NULL, uri); + + fprintf(stderr, "DEBUG: printer-uri = \"%s\"\n", uri); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", + NULL, argv[2]); + + fprintf(stderr, "DEBUG: requesting-user-name = \"%s\"\n", argv[2]); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL, + argv[3]); + + fprintf(stderr, "DEBUG: job-name = \"%s\"\n", 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"); + + if (copies_sup) + 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 (strcasecmp(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 (strncasecmp(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 (strcasecmp(s, "dpc") == 0) + ippAddResolution(request, IPP_TAG_JOB, option, IPP_RES_PER_CM, n, n2); + else if (strcasecmp(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"); + if (username[0]) + { + httpEncode64(password, username); + httpSetField(http, HTTP_FIELD_AUTHORIZATION, password); + } + + sprintf(buffer, "%u", ippLength(request) + (size_t)fileinfo.st_size); + httpSetField(http, HTTP_FIELD_CONTENT_LENGTH, buffer); + + /* + * Do the request... + */ + + for (;;) + { + /* + * POST the request, retrying as needed... + */ + + httpReconnect(http); + + if (httpPost(http, resource)) + { + fputs("INFO: Unable to POST print request; retrying...\n", stderr); + sleep(10); + 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... + */ + + rewind(fp); + + 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 ((ipp_status = response->request.status.status_code) > IPP_OK_CONFLICT) + { + if (ipp_status == IPP_SERVICE_UNAVAILABLE || + ipp_status == IPP_PRINTER_BUSY) + { + fputs("INFO: Printer is busy; retrying print job...\n", stderr); + sleep(10); + } + else + 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; + ipp_status = IPP_PRINTER_BUSY; + + if (status == HTTP_ERROR) + { + fprintf(stderr, "WARNING: Did not receive the IPP response (%d)\n", + errno); + status = HTTP_OK; + } + else + fprintf(stderr, "ERROR: Print request was not accepted (%d)!\n", status); + } + + httpFlush(http); + + break; + } + + if (request != NULL) + ippDelete(request); + if (response != NULL) + ippDelete(response); + + if (ipp_status <= IPP_OK_CONFLICT) + { + fprintf(stderr, "PAGE: 1 %d\n", copies_sup ? atoi(argv[4]) : 1); + copies --; + } + } + + /* + * Free memory... + */ + + httpClose(http); + + /* + * Close and remove the temporary file if necessary... + */ + + fclose(fp); + + if (argc < 7) + unlink(filename); + + /* + * 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..12cd63050e --- /dev/null +++ b/backend/lpd.c @@ -0,0 +1,409 @@ +/* + * "$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 + { + strncpy(filename, argv[6], sizeof(filename) - 1); + filename[sizeof(filename) - 1] = '\0'; + } + + /* + * Extract the hostname and printer name from the URI... + */ + + httpSeparate(argv[0], method, username, hostname, &port, resource); + + /* + * Queue the job... + */ + + if (argc > 6) + { + status = lpd_queue(hostname, resource + 1, filename, + argv[2] /* user */, atoi(argv[4]) /* copies */); + + if (!status) + fprintf(stderr, "PAGE: 1 %d\n", atoi(argv[4])); + } + else + status = lpd_queue(hostname, resource + 1, filename, + argv[2] /* user */, 1); + + /* + * 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 = vsnprintf(buf, sizeof(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 reserve port"); + sleep(30); + continue; + } + + 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"); + sleep(30); + } + } + 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 */ + + snprintf(control, sizeof(control), "H%s\nP%s\n", localhost, user); + cptr = control + strlen(control); + + while (copies > 0) + { + + snprintf(cptr, sizeof(control) - (cptr - control), "ldfA%03.3d%s\n", + getpid() % 1000, localhost); + cptr += strlen(cptr); + copies --; + } + + snprintf(cptr, sizeof(control) - (cptr - control), + "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..1506b3f6e2 --- /dev/null +++ b/backend/parallel.c @@ -0,0 +1,196 @@ +/* + * "$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 copies; /* Number of copies to print */ + 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; + copies = 1; + } + else + { + /* + * Try to open the print file... + */ + + if ((fp = fopen(argv[6], "rb")) == NULL) + { + perror("ERROR: unable to open print file"); + return (1); + } + + copies = atoi(argv[4]); + } + + /* + * 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... + */ + + while (copies > 0) + { + copies --; + + if (fp != stdin) + { + fputs("PAGE: 1 1\n", stderr); + rewind(fp); + } + + 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..cfe86df4b8 --- /dev/null +++ b/backend/serial.c @@ -0,0 +1,314 @@ +/* + * "$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 copies; /* Number of copies to print */ + 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; + copies = 1; + } + else + { + /* + * Try to open the print file... + */ + + if ((fp = fopen(argv[6], "rb")) == NULL) + { + perror("ERROR: unable to open print file"); + return (1); + } + + copies = atoi(argv[4]); + } + + /* + * 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... + */ + + while (copies > 0) + { + copies --; + + if (fp != stdin) + { + fputs("PAGE: 1 1\n", stderr); + rewind(fp); + } + + 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/socket.c b/backend/socket.c new file mode 100644 index 0000000000..8ccdade963 --- /dev/null +++ b/backend/socket.c @@ -0,0 +1,254 @@ +/* + * "$Id$" + * + * AppSocket backend for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-1999 by Easy Software Products, all rights reserved. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * main() - Send a file to the printer or server. + */ + +/* + * Include necessary headers. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(WIN32) || defined(__EMX__) +# include +#else +# include +# include +# include +# include +#endif /* WIN32 || __EMX__ */ + + +/* + * 'main()' - Send a file to the printer or server. + * + * Usage: + * + * printer-uri job-id user title copies options [file] + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line arguments (6 or 7) */ + char *argv[]) /* I - Command-line arguments */ +{ + char method[255], /* Method in URI */ + hostname[1024], /* Hostname */ + username[255], /* Username info (not used) */ + resource[1024]; /* Resource info (not used) */ + FILE *fp; /* Print file */ + int copies; /* Number of copies to print */ + 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; + copies = 1; + } + else + { + /* + * Try to open the print file... + */ + + if ((fp = fopen(argv[6], "rb")) == NULL) + { + perror("ERROR: unable to open print file"); + return (1); + } + + copies = atoi(argv[4]); + } + + /* + * 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); + + while (copies > 0) + { + for (;;) + { + if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) + { + perror("ERROR: Unable to create socket"); + 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"); + sleep(30); + } + } + else + break; + } + + /* + * Finally, send the print file... + */ + + copies --; + + if (fp != stdin) + { + fputs("PAGE: 1 1\n", stderr); + rewind(fp); + } + + 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... + */ + + close(fd); + } + + /* + * Close the input file and return... + */ + + 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..06aed77eb1 --- /dev/null +++ b/berkeley/lpc.c @@ -0,0 +1,467 @@ +/* + * "$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); + + snprintf(printer_uri, sizeof(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 + { + /* + * Just show the method... + */ + + *strchr(device, ':') = '\0'; + 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..7762e18793 --- /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 + { + snprintf(resource, sizeof(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%-32.32s %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(" %-4d %-10.10s %-6d %-18.18s %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..98592ed6df --- /dev/null +++ b/berkeley/lpr.c @@ -0,0 +1,294 @@ +/* + * "$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. + * sighandler() - Signal catcher for when we print from stdin... + */ + +/* + * Include necessary headers... + */ + +#include +#include +#include + + +#ifndef WIN32 +# include + + +/* + * Local functions. + */ + +void sighandler(void); +#endif /* !WIN32 */ + + +/* + * Globals... + */ + +char tempfile[1024]; /* Temporary file for printing from stdin */ + + +/* + * '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 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\' - error code %x.\n", + argv[i], cupsLastError()); + 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); + } + +#ifndef WIN32 + signal(SIGTERM, sighandler); +#endif /* !WIN32 */ + + 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) + { + fprintf(stderr, "lpr: unable to print standard input - error code %x.\n", + cupsLastError()); + return (1); + } + } + + return (0); +} + + +#ifndef WIN32 +/* + * 'sighandler()' - Signal catcher for when we print from stdin... + */ + +void +sighandler(void) +{ + /* + * Remove the temporary file we're using to print from stdin... + */ + + unlink(tempfile); +} +#endif /* !WIN32 */ + + +/* + * End of "$Id$". + */ diff --git a/berkeley/lprm.c b/berkeley/lprm.c new file mode 100644 index 0000000000..1d9bce5497 --- /dev/null +++ b/berkeley/lprm.c @@ -0,0 +1,221 @@ +/* + * "$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; + http = 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) + { + snprintf(uri, sizeof(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); + } + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, + "requesting-user-name", NULL, cupsUser()); + + /* + * 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) + { + switch (response->request.status.status_code) + { + case IPP_NOT_FOUND : + fputs("lprm: Job or printer not found!\n", stderr); + break; + case IPP_NOT_AUTHORIZED : + fputs("lprm: Not authorized to lprm job(s)!\n", stderr); + break; + case IPP_FORBIDDEN : + fprintf(stderr, "lprm: You don't own job ID %d!\n", job_id); + break; + default : + if (response->request.status.status_code > IPP_OK_CONFLICT) + fputs("lprm: Unable to lprm job(s)!\n", stderr); + break; + } + + 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..0d996ef7ad --- /dev/null +++ b/cgi-bin/classes.c @@ -0,0 +1,486 @@ +/* + * "$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 +#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 - " CUPS_SVERSION "\n", + name == NULL ? "Classes" : name, getenv("SERVER_NAME")); + puts(""); + puts(""); +#ifdef ESPPRINTPRO + puts("\"Current"); + puts("\"Current"); + puts("\"Current"); + puts("\"Read"); + puts("\"Download"); + puts("\"Get"); +#else + puts("\"Current"); + puts("\"Current"); + puts("\"Current"); + puts("\"Read"); + puts("\"Download"); +#endif /* ESPPRINTPRO */ + puts(""); + puts(""); + puts(""); + puts("

"); + puts(""); + puts("\"Easy"); + puts(""); + + 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, "/")) != 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); + + snprintf(uri, sizeof(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, "/")) == 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:"); + strncpy(uri + 5, strchr(attr->values[0].string.text, '/'), sizeof(uri) - 6); + uri[sizeof(uri) - 1] = '\0'; + } + + /* + * 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); + + snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", name); + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, + "printer-uri", NULL, uri); + + jobs = cupsDoRequest(http, request, "/"); + } + 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..7258b80a12 --- /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 +#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 - " CUPS_SVERSION "\n", + job == NULL ? "Jobs" : job, getenv("SERVER_NAME")); + puts(""); + puts(""); +#ifdef ESPPRINTPRO + puts("\"Current"); + puts("\"Current"); + puts("\"Current"); + puts("\"Read"); + puts("\"Download"); + puts("\"Get"); +#else + puts("\"Current"); + puts("\"Current"); + puts("\"Current"); + puts("\"Read"); + puts("\"Download"); +#endif /* ESPPRINTPRO */ + puts(""); + puts(""); + puts(""); + puts("

"); + puts(""); + puts("\"Easy"); + puts(""); + + 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, "/")) != 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); + + snprintf(uri, sizeof(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, "/")) == 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) + 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..6ec17513f1 --- /dev/null +++ b/cgi-bin/printers.c @@ -0,0 +1,488 @@ +/* + * "$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 +#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 - " CUPS_SVERSION "\n", + printer == NULL ? "Printers" : printer, getenv("SERVER_NAME")); + puts(""); + puts(""); +#ifdef ESPPRINTPRO + puts("\"Current"); + puts("\"Current"); + puts("\"Current"); + puts("\"Read"); + puts("\"Download"); + puts("\"Get"); +#else + puts("\"Current"); + puts("\"Current"); + puts("\"Current"); + puts("\"Read"); + puts("\"Download"); +#endif /* ESPPRINTPRO */ + puts(""); + puts(""); + puts(""); + puts("

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

%s on %s

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

The Common UNIX Printing System, CUPS, and the CUPS logo are the"); + puts("trademark property of Easy Software"); + puts("Products. CUPS is copyright 1997-1999 by Easy Software Products,"); + puts("All Rights Reserved."); + + puts(""); + puts(""); + + /* + * Close the HTTP server connection... + */ + + httpClose(http); + cupsLangFree(language); + + /* + * Return with no errors... + */ + + return (0); +} + + +/* + * 'show_printer_list()' - Show a list of printers... + */ + +static void +show_printer_list(http_t *http, /* I - HTTP connection */ + cups_lang_t *language)/* I - Client's language */ +{ + ipp_t *request, /* IPP request */ + *response; /* IPP response */ + ipp_attribute_t *attr; /* IPP attribute */ + + + /* + * Build a CUPS_GET_PRINTERS request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + */ + + request = ippNew(); + + request->request.op.operation_id = CUPS_GET_PRINTERS; + request->request.op.request_id = 1; + + + 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, "/")) != 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); + + snprintf(uri, sizeof(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, "/")) == 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:"); + strncpy(uri + 5, strchr(attr->values[0].string.text, '/'), sizeof(uri) - 6); + uri[sizeof(uri) - 1] = '\0'; + } + + /* + * 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); + + snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", name); + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, + "printer-uri", NULL, uri); + + jobs = cupsDoRequest(http, request, "/"); + } + 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..f9b8484d1f --- /dev/null +++ b/conf/Makefile @@ -0,0 +1,71 @@ +# +# "$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 -r $(SERVERROOT)/conf/$$file ; then \ + $(CP) $$file $(SERVERROOT)/conf/$$file.N ; \ + else \ + $(CP) $$file $(SERVERROOT)/conf ; \ + fi ; \ + done + for file in $(REPLACE); do \ + if test -r $(SERVERROOT)/conf/$$file ; then \ + $(MV) $(SERVERROOT)/conf/$$file $(SERVERROOT)/conf/$$file.O ; \ + fi ; \ + $(CP) $$file $(SERVERROOT)/conf ; \ + done + if test -r /etc/printcap -a ! -r /etc/printcap.O; then \ + $(CP) /etc/printcap /etc/printcap.O ; \ + fi + +# +# End of "$Id$". +# diff --git a/conf/classes.conf b/conf/classes.conf new file mode 100644 index 0000000000..42e97dbed0 --- /dev/null +++ b/conf/classes.conf @@ -0,0 +1,79 @@ +# +# "$Id: classes.conf 678 1999-09-22 18:10:55Z 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 + +# +# Accepting: is the class accepting jobs? +# +#Accepting Yes +#Accepting No +# + +# +# Printer: adds a printer to the class. +# + +#Printer sample +#Printer sample@host2 +# + +# +# End of "$Id: classes.conf 678 1999-09-22 18:10:55Z 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/printcap b/conf/printcap new file mode 100644 index 0000000000..230c3017d6 --- /dev/null +++ b/conf/printcap @@ -0,0 +1,2 @@ +# This is a dummy printcap file that is automatically generated by the +# CUPS software for old applications that rely on it. diff --git a/conf/printers.conf b/conf/printers.conf new file mode 100644 index 0000000000..54f43322a4 --- /dev/null +++ b/conf/printers.conf @@ -0,0 +1,96 @@ +# +# "$Id: printers.conf 678 1999-09-22 18:10:55Z 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 print new jobs. +# Stopped - Printer is disabled but accepting new jobs. +# + +#State Idle + +# +# Accepting: is the printer accepting jobs? +# +#Accepting Yes +#Accepting No + +# + +# +# End of "$Id: printers.conf 678 1999-09-22 18:10:55Z mike $". +# diff --git a/config.h.in b/config.h.in new file mode 100644 index 0000000000..775db42c6c --- /dev/null +++ b/config.h.in @@ -0,0 +1,116 @@ +/* + * "$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.3" + +/* + * 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 PAM stuff? + */ + +#ifndef HAVE_LIBPAM +#define HAVE_LIBPAM 0 +#endif /* !HAVE_LIBPAM */ + +/* + * 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 + +/* + * Do we have the (v)snprintf() functions? + */ + +#undef HAVE_SNPRINTF +#undef HAVE_VSNPRINTF + +/* + * 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..815bcfc192 --- /dev/null +++ b/configure.in @@ -0,0 +1,342 @@ +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, [ --enable-shared turn on shared libraries [default=yes]]) +if test "$enable_shared" != "no"; 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" + ;; + FreeBSD* | NetBSD* | OpenBSD*) + LIBCUPS="libcups.so.1" + LIBCUPSIMAGE="libcupsimage.so.1" + DSO="\$(CC) -Wl,-soname,\$@ -shared \$(OPTIM) -o" + ;; + OSF1* | Linux*) + 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 + +AC_ARG_ENABLE(pam, [ --enable-pam turn on PAM support [default=yes]]) + +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(MV,mv) +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) + +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) +if test "$enable_pam" != "no"; then + AC_CHECK_LIB(dl,dlopen) + AC_CHECK_LIB(pam,pam_start) +fi + +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) + +dnl Save the current libraries since we don't want the image libraries +dnl included with every program... +SAVELIBS="$LIBS" + +dnl Check for image libraries... +LIBJPEG="" +LIBPNG="" +LIBTIFF="" +LIBZ="" + +AC_SUBST(LIBJPEG) +AC_SUBST(LIBPNG) +AC_SUBST(LIBTIFF) +AC_SUBST(LIBZ) + +AC_CHECK_LIB(jpeg, jpeg_destroy_decompress, + AC_DEFINE(HAVE_LIBJPEG) + LIBJPEG="-ljpeg" + LIBS="$LIBS -ljpeg") + +AC_CHECK_LIB(z, deflate, + AC_DEFINE(HAVE_LIBZ) + LIBZ="-lz" + LIBS="$LIBS -lz") + +dnl PNG library uses math library functions... +AC_CHECK_LIB(m, pow) + +dnl AC_CHECK_HEADER(png.h, +AC_CHECK_LIB(png, png_read_info, + AC_DEFINE(HAVE_LIBPNG) + LIBPNG="-lpng") + +dnl AC_CHECK_HEADER(tiff.h, +AC_CHECK_LIB(tiff, TIFFReadScanline, + AC_DEFINE(HAVE_LIBTIFF) + LIBTIFF="-ltiff") + +dnl Restore original LIBS settings... +LIBS="$SAVELIBS" + +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) +AC_CHECK_FUNCS(snprintf) +AC_CHECK_FUNCS(vsnprintf) + +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" -o $uname = Linux; 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 65; 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.list b/cups.list new file mode 100644 index 0000000000..1706d5e056 --- /dev/null +++ b/cups.list @@ -0,0 +1,319 @@ +# +# "$Id: cups.list 823 1999-12-15 21:16:02Z mike $" +# +# ESP Package Manager (EPM) file list for the Common UNIX Printing +# System (CUPS). +# +# EPM can be found in the "epm" subdirectory of this distribution. +# Please report problems and fixes to "epm@easysw.com". +# +# 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 +# + +%product Common UNIX Printing System +%copyright 1993-1999 by Easy Software Products, All Rights Reserved. +%vendor Easy Software Products +%license LICENSE.cups +%readme README.cups +%version 1.0.3 +%incompat printpro + +%system all +# Server files +f 0555 root sys /var/cups/backend/ipp backend/ipp +l 0555 root sys /var/cups/backend/http ipp +f 4550 root sys /var/cups/backend/lpd backend/lpd +f 0555 root sys /var/cups/backend/parallel backend/parallel +f 0555 root sys /var/cups/backend/serial backend/serial +f 0555 root sys /var/cups/backend/socket backend/socket +f 0500 root sys /usr/sbin/cupsd scheduler/cupsd +f 0555 root sys /var/cups/cgi-bin/classes.cgi cgi-bin/classes.cgi +f 0555 root sys /var/cups/cgi-bin/jobs.cgi cgi-bin/jobs.cgi +f 0555 root sys /var/cups/cgi-bin/printers.cgi cgi-bin/printers.cgi +f 0555 root sys /var/cups/filter/pstoraster pstoraster/pstoraster +l 0555 root sys /var/cups/filter/pdftops pstoraster +f 0555 root sys /var/cups/filter/imagetops filter/imagetops +f 0555 root sys /var/cups/filter/pstops filter/pstops +f 0555 root sys /var/cups/filter/texttops filter/texttops +f 0555 root sys /var/cups/filter/rastertohp filter/rastertohp +f 0555 root sys /var/cups/filter/hpgltops filter/hpgltops +f 0555 root sys /var/cups/filter/imagetoraster filter/imagetoraster + +# Admin commands +l 0555 root sys /usr/bin/disable /usr/sbin/accept +l 0555 root sys /usr/bin/enable /usr/sbin/accept +l 0555 root sys /usr/lib/accept /usr/sbin/accept +l 0555 root sys /usr/lib/lpadmin /usr/sbin/lpadmin +l 0555 root sys /usr/lib/reject accept +f 0555 root sys /usr/sbin/accept systemv/accept +f 0555 root sys /usr/sbin/esplicense license/esplicense +f 0555 root sys /usr/sbin/lpadmin systemv/lpadmin +f 0555 root sys /usr/sbin/lpc berkeley/lpc +l 0555 root sys /usr/sbin/reject accept + +# User commands +f 0555 root sys /usr/bin/cancel systemv/cancel +f 0555 root sys /usr/bin/lp systemv/lp +f 0555 root sys /usr/bin/lpq berkeley/lpq +f 0555 root sys /usr/bin/lpr berkeley/lpr +f 0555 root sys /usr/bin/lprm berkeley/lprm +f 0555 root sys /usr/bin/lpstat systemv/lpstat +f 0555 root sys /usr/bin/lpwin gui/lpwin + +# DSOs +%system hpux +f 0555 root sys /usr/lib/libcups.sl.1 cups/libcups.sl.1 +l 0555 root sys /usr/lib/libcups.sl libcups.sl.1 +f 0555 root sys /usr/lib/libcupsimage.sl.1 filter/libcupsimage.sl.1 +l 0555 root sys /usr/lib/libcupsimage.sl libcupsimage.sl.1 +%system irix-6.5 +f 0555 root sys /usr/lib32/libcups.so.1 cups/libcups.so.1 +l 0555 root sys /usr/lib32/libcups.so libcups.so.1 +f 0555 root sys /usr/lib32/libcupsimage.so.1 filter/libcupsimage.so.1 +l 0555 root sys /usr/lib32/libcupsimage.so libcupsimage.so.1 +%system !irix-6.5 !hpux +f 0555 root sys /usr/lib/libcups.so.1 cups/libcups.so.1 +l 0555 root sys /usr/lib/libcups.so libcups.so.1 +f 0555 root sys /usr/lib/libcupsimage.so.1 filter/libcupsimage.so.1 +l 0555 root sys /usr/lib/libcupsimage.so libcupsimage.so.1 +%system all + +# Directories +d 0755 root sys /var/cups/interfaces +d 0755 root sys /var/cups/logs +d 0755 root sys /var/cups/ppd +d 0755 root sys /var/cups/requests + +# Data files +f 0444 root sys /usr/lib/locale/C/cups_C locale/C/cups_C +f 0444 root sys /usr/lib/locale/de/cups_de locale/de/cups_de +f 0444 root sys /usr/lib/locale/en/cups_en locale/en/cups_en +f 0444 root sys /usr/lib/locale/es/cups_es locale/es/cups_es +f 0444 root sys /usr/lib/locale/fr/cups_fr locale/fr/cups_fr +f 0444 root sys /usr/lib/locale/it/cups_it locale/it/cups_it +f 0444 root sys /usr/share/cups/data/8859-1 data/8859-1 +f 0444 root sys /usr/share/cups/data/8859-14 data/8859-14 +f 0444 root sys /usr/share/cups/data/8859-15 data/8859-15 +f 0444 root sys /usr/share/cups/data/8859-2 data/8859-2 +f 0444 root sys /usr/share/cups/data/8859-3 data/8859-3 +f 0444 root sys /usr/share/cups/data/8859-4 data/8859-4 +f 0444 root sys /usr/share/cups/data/8859-5 data/8859-5 +f 0444 root sys /usr/share/cups/data/8859-6 data/8859-6 +f 0444 root sys /usr/share/cups/data/8859-7 data/8859-7 +f 0444 root sys /usr/share/cups/data/8859-8 data/8859-8 +f 0444 root sys /usr/share/cups/data/8859-9 data/8859-9 +f 0444 root sys /usr/share/cups/data/HPGLprolog data/HPGLprolog +f 0444 root sys /usr/share/cups/data/psglyphs data/psglyphs +f 0444 root sys /usr/share/cups/fonts/AvantGarde-Book fonts/AvantGarde-Book +f 0444 root sys /usr/share/cups/fonts/AvantGarde-BookOblique fonts/AvantGarde-BookOblique +f 0444 root sys /usr/share/cups/fonts/AvantGarde-Demi fonts/AvantGarde-Demi +f 0444 root sys /usr/share/cups/fonts/AvantGarde-DemiOblique fonts/AvantGarde-DemiOblique +f 0444 root sys /usr/share/cups/fonts/Bookman-Demi fonts/Bookman-Demi +f 0444 root sys /usr/share/cups/fonts/Bookman-DemiItalic fonts/Bookman-DemiItalic +f 0444 root sys /usr/share/cups/fonts/Bookman-Light fonts/Bookman-Light +f 0444 root sys /usr/share/cups/fonts/Bookman-LightItalic fonts/Bookman-LightItalic +f 0444 root sys /usr/share/cups/fonts/Courier fonts/Courier +f 0444 root sys /usr/share/cups/fonts/Courier-Bold fonts/Courier-Bold +f 0444 root sys /usr/share/cups/fonts/Courier-BoldOblique fonts/Courier-BoldOblique +f 0444 root sys /usr/share/cups/fonts/Courier-Oblique fonts/Courier-Oblique +f 0444 root sys /usr/share/cups/fonts/Helvetica fonts/Helvetica +f 0444 root sys /usr/share/cups/fonts/Helvetica-Bold fonts/Helvetica-Bold +f 0444 root sys /usr/share/cups/fonts/Helvetica-BoldOblique fonts/Helvetica-BoldOblique +f 0444 root sys /usr/share/cups/fonts/Helvetica-Narrow fonts/Helvetica-Narrow +f 0444 root sys /usr/share/cups/fonts/Helvetica-Narrow-Bold fonts/Helvetica-Narrow-Bold +f 0444 root sys /usr/share/cups/fonts/Helvetica-Narrow-BoldOblique fonts/Helvetica-Narrow-BoldOblique +f 0444 root sys /usr/share/cups/fonts/Helvetica-Narrow-Oblique fonts/Helvetica-Narrow-Oblique +f 0444 root sys /usr/share/cups/fonts/Helvetica-Oblique fonts/Helvetica-Oblique +f 0444 root sys /usr/share/cups/fonts/NewCenturySchlbk-Bold fonts/NewCenturySchlbk-Bold +f 0444 root sys /usr/share/cups/fonts/NewCenturySchlbk-BoldItalic fonts/NewCenturySchlbk-BoldItalic +f 0444 root sys /usr/share/cups/fonts/NewCenturySchlbk-Italic fonts/NewCenturySchlbk-Italic +f 0444 root sys /usr/share/cups/fonts/NewCenturySchlbk-Roman fonts/NewCenturySchlbk-Roman +f 0444 root sys /usr/share/cups/fonts/Palatino-Bold fonts/Palatino-Bold +f 0444 root sys /usr/share/cups/fonts/Palatino-BoldItalic fonts/Palatino-BoldItalic +f 0444 root sys /usr/share/cups/fonts/Palatino-Italic fonts/Palatino-Italic +f 0444 root sys /usr/share/cups/fonts/Palatino-Roman fonts/Palatino-Roman +f 0444 root sys /usr/share/cups/fonts/Symbol fonts/Symbol +f 0444 root sys /usr/share/cups/fonts/Times-Bold fonts/Times-Bold +f 0444 root sys /usr/share/cups/fonts/Times-BoldItalic fonts/Times-BoldItalic +f 0444 root sys /usr/share/cups/fonts/Times-Italic fonts/Times-Italic +f 0444 root sys /usr/share/cups/fonts/Times-Roman fonts/Times-Roman +f 0444 root sys /usr/share/cups/fonts/Utopia-Bold fonts/Utopia-Bold +f 0444 root sys /usr/share/cups/fonts/Utopia-BoldItalic fonts/Utopia-BoldItalic +f 0444 root sys /usr/share/cups/fonts/Utopia-Italic fonts/Utopia-Italic +f 0444 root sys /usr/share/cups/fonts/Utopia-Regular fonts/Utopia-Regular +f 0444 root sys /usr/share/cups/fonts/ZapfChancery-MediumItalic fonts/ZapfChancery-MediumItalic +f 0444 root sys /usr/share/cups/fonts/ZapfDingbats fonts/ZapfDingbats +f 0444 root sys /usr/share/cups/pstoraster/Fontmap pstoraster/Fontmap +f 0444 root sys /usr/share/cups/pstoraster/gs_l2img.ps pstoraster/gs_l2img.ps +f 0444 root sys /usr/share/cups/pstoraster/gs_pfile.ps pstoraster/gs_pfile.ps +f 0444 root sys /usr/share/cups/pstoraster/pfbtogs.ps pstoraster/pfbtogs.ps +f 0444 root sys /usr/share/cups/pstoraster/gs_wl1_e.ps pstoraster/gs_wl1_e.ps +f 0444 root sys /usr/share/cups/pstoraster/gs_wl2_e.ps pstoraster/gs_wl2_e.ps +f 0444 root sys /usr/share/cups/pstoraster/gs_wl5_e.ps pstoraster/gs_wl5_e.ps +f 0444 root sys /usr/share/cups/pstoraster/gs_wan_e.ps pstoraster/gs_wan_e.ps +f 0444 root sys /usr/share/cups/pstoraster/gs_pdf_e.ps pstoraster/gs_pdf_e.ps +f 0444 root sys /usr/share/cups/pstoraster/gs_sym_e.ps pstoraster/gs_sym_e.ps +f 0444 root sys /usr/share/cups/pstoraster/gs_std_e.ps pstoraster/gs_std_e.ps +f 0444 root sys /usr/share/cups/pstoraster/gs_dbt_e.ps pstoraster/gs_dbt_e.ps +f 0444 root sys /usr/share/cups/pstoraster/gs_mex_e.ps pstoraster/gs_mex_e.ps +f 0444 root sys /usr/share/cups/pstoraster/gs_mro_e.ps pstoraster/gs_mro_e.ps +f 0444 root sys /usr/share/cups/pstoraster/gs_iso_e.ps pstoraster/gs_iso_e.ps +f 0444 root sys /usr/share/cups/pstoraster/gs_ksb_e.ps pstoraster/gs_ksb_e.ps +f 0444 root sys /usr/share/cups/pstoraster/gs_ttf.ps pstoraster/gs_ttf.ps +f 0444 root sys /usr/share/cups/pstoraster/gs_pdf.ps pstoraster/gs_pdf.ps +f 0444 root sys /usr/share/cups/pstoraster/gs_ccfnt.ps pstoraster/gs_ccfnt.ps +f 0444 root sys /usr/share/cups/pstoraster/pdf_sec.ps pstoraster/pdf_sec.ps +f 0444 root sys /usr/share/cups/pstoraster/gs_res.ps pstoraster/gs_res.ps +f 0444 root sys /usr/share/cups/pstoraster/pdf_base.ps pstoraster/pdf_base.ps +f 0444 root sys /usr/share/cups/pstoraster/gs_btokn.ps pstoraster/gs_btokn.ps +f 0444 root sys /usr/share/cups/pstoraster/gs_diskf.ps pstoraster/gs_diskf.ps +f 0444 root sys /usr/share/cups/pstoraster/pdf_2ps.ps pstoraster/pdf_2ps.ps +f 0444 root sys /usr/share/cups/pstoraster/gs_init.ps pstoraster/gs_init.ps +f 0444 root sys /usr/share/cups/pstoraster/gs_kanji.ps pstoraster/gs_kanji.ps +f 0444 root sys /usr/share/cups/pstoraster/pdf_draw.ps pstoraster/pdf_draw.ps +f 0444 root sys /usr/share/cups/pstoraster/pdf_font.ps pstoraster/pdf_font.ps +f 0444 root sys /usr/share/cups/pstoraster/gs_type1.ps pstoraster/gs_type1.ps +f 0444 root sys /usr/share/cups/pstoraster/gs_fonts.ps pstoraster/gs_fonts.ps +f 0444 root sys /usr/share/cups/pstoraster/gs_statd.ps pstoraster/gs_statd.ps +f 0444 root sys /usr/share/cups/pstoraster/gs_lev2.ps pstoraster/gs_lev2.ps +f 0444 root sys /usr/share/cups/pstoraster/gs_typ42.ps pstoraster/gs_typ42.ps +f 0444 root sys /usr/share/cups/pstoraster/gs_pdfwr.ps pstoraster/gs_pdfwr.ps +f 0444 root sys /usr/share/cups/pstoraster/gs_cidfn.ps pstoraster/gs_cidfn.ps +f 0444 root sys /usr/share/cups/pstoraster/gs_cmdl.ps pstoraster/gs_cmdl.ps +f 0444 root sys /usr/share/cups/pstoraster/gs_dps1.ps pstoraster/gs_dps1.ps +f 0444 root sys /usr/share/cups/pstoraster/gs_setpd.ps pstoraster/gs_setpd.ps +f 0444 root sys /usr/share/cups/pstoraster/gs_cmap.ps pstoraster/gs_cmap.ps +f 0444 root sys /usr/share/cups/pstoraster/gs_fform.ps pstoraster/gs_fform.ps +f 0444 root sys /usr/share/cups/pstoraster/pdf_main.ps pstoraster/pdf_main.ps +f 0444 root sys /usr/share/cups/model/deskjet.ppd ppd/deskjet.ppd +f 0444 root sys /usr/share/cups/model/laserjet.ppd ppd/laserjet.ppd + +# Config files +c 0644 root sys /var/cups/conf/classes.conf conf/classes.conf +c 0644 root sys /var/cups/conf/cupsd.conf conf/cupsd.conf +f 0644 root sys /var/cups/conf/mime.convs conf/mime.convs +f 0644 root sys /var/cups/conf/mime.types conf/mime.types +c 0644 root sys /var/cups/conf/printers.conf conf/printers.conf + +# Dummy printcap file for Digital UNIX and Linux... +%system dunix linux +%format !rpm +f 0644 root sys /etc/printcap conf/printcap +%system all +%format all + +# Developer files +f 0444 root sys /usr/include/cups/cups.h cups/cups.h +f 0444 root sys /usr/include/cups/http.h cups/http.h +f 0444 root sys /usr/include/cups/ipp.h cups/ipp.h +f 0444 root sys /usr/include/cups/language.h cups/language.h +f 0444 root sys /usr/include/cups/mime.h cups/mime.h +f 0444 root sys /usr/include/cups/ppd.h cups/ppd.h +f 0444 root sys /usr/include/cups/raster.h cups/raster.h + +%system irix-6.5 +f 0444 root sys /usr/lib32/libcups.a cups/libcups.a +%system !irix-6.5 +f 0444 root sys /usr/lib/libcups.a cups/libcups.a +%system all + +# Documentation files +f 0444 root sys /usr/share/cups/doc/cmp.html doc/cmp.html +f 0444 root sys /usr/share/cups/doc/cmp.pdf doc/cmp.pdf +f 0444 root sys /usr/share/cups/doc/cupsdoc.css doc/cupsdoc.css +f 0444 root sys /usr/share/cups/doc/cups.css doc/cups.css +f 0444 root sys /usr/share/cups/doc/documentation.html doc/documentation.html +f 0444 root sys /usr/share/cups/doc/idd.html doc/idd.html +f 0444 root sys /usr/share/cups/doc/idd.pdf doc/idd.pdf +f 0444 root sys /usr/share/cups/doc/images/classes.gif doc/images/classes.gif +f 0444 root sys /usr/share/cups/doc/images/cups-bar.gif doc/images/cups-bar.gif +f 0444 root sys /usr/share/cups/doc/images/cups-block-diagram.gif doc/images/cups-block-diagram.gif +f 0444 root sys /usr/share/cups/doc/images/cups-large.gif doc/images/cups-large.gif +f 0444 root sys /usr/share/cups/doc/images/cups-medium.gif doc/images/cups-medium.gif +f 0444 root sys /usr/share/cups/doc/images/cups-small.gif doc/images/cups-small.gif +f 0444 root sys /usr/share/cups/doc/images/logo.gif doc/images/logo.gif +f 0444 root sys /usr/share/cups/doc/images/navbar.gif doc/images/navbar.gif +f 0444 root sys /usr/share/cups/doc/images/printer-idle.gif doc/images/printer-idle.gif +f 0444 root sys /usr/share/cups/doc/images/printer-processing.gif doc/images/printer-processing.gif +f 0444 root sys /usr/share/cups/doc/images/printer-stopped.gif doc/images/printer-stopped.gif +f 0444 root sys /usr/share/cups/doc/index.html doc/index.html +f 0444 root sys /usr/share/cups/doc/overview.html doc/overview.html +f 0444 root sys /usr/share/cups/doc/overview.pdf doc/overview.pdf +f 0444 root sys /usr/share/cups/doc/sam.html doc/sam.html +f 0444 root sys /usr/share/cups/doc/sam.pdf doc/sam.pdf +f 0444 root sys /usr/share/cups/doc/sdd.html doc/sdd.html +f 0444 root sys /usr/share/cups/doc/sdd.pdf doc/sdd.pdf +f 0444 root sys /usr/share/cups/doc/spm.html doc/spm.html +f 0444 root sys /usr/share/cups/doc/spm.pdf doc/spm.pdf +f 0444 root sys /usr/share/cups/doc/ssr.html doc/ssr.html +f 0444 root sys /usr/share/cups/doc/ssr.pdf doc/ssr.pdf +f 0444 root sys /usr/share/cups/doc/sum.html doc/sum.html +f 0444 root sys /usr/share/cups/doc/sum.pdf doc/sum.pdf + +# Man pages +%system irix +f 0444 root sys /usr/share/catman/a_man/cat1/accept.z man/accept.z +l 0444 root sys /usr/share/catman/a_man/cat1/reject.z accept.z +f 0444 root sys /usr/share/catman/u_man/cat1/backend.z man/backend.z +f 0444 root sys /usr/share/catman/u_man/cat5/classes.conf.z man/classes.conf.z +f 0444 root sys /usr/share/catman/u_man/cat5/cupsd.conf.z man/cupsd.conf.z +f 0444 root sys /usr/share/catman/a_man/cat1/cupsd.z man/cupsd.z +f 0444 root sys /usr/share/catman/a_man/cat1/enable.z man/enable.z +l 0444 root sys /usr/share/catman/a_man/cat1/disable.z enable.z +f 0444 root sys /usr/share/catman/u_man/cat1/filter.z man/filter.z +f 0444 root sys /usr/share/catman/a_man/cat1/lpadmin.z man/lpadmin.z +f 0444 root sys /usr/share/catman/a_man/cat1/lpc.z man/lpc.z +f 0444 root sys /usr/share/catman/u_man/cat1/lpq.z man/lpq.z +f 0444 root sys /usr/share/catman/u_man/cat1/lprm.z man/lprm.z +f 0444 root sys /usr/share/catman/u_man/cat1/lpr.z man/lpr.z +f 0444 root sys /usr/share/catman/u_man/cat1/lpstat.z man/lpstat.z +f 0444 root sys /usr/share/catman/u_man/cat1/lp.z man/lp.z +l 0444 root sys /usr/share/catman/u_man/cat1/cancel.z lp.z +f 0444 root sys /usr/share/catman/u_man/cat5/mime.convs.z man/mime.convs.z +f 0444 root sys /usr/share/catman/u_man/cat5/mime.types.z man/mime.types.z +f 0444 root sys /usr/share/catman/u_man/cat5/printers.conf.z man/printers.conf.z +%system !irix +f 0444 root sys /usr/man/man8/accept.8 man/accept.8 +l 0444 root sys /usr/man/man8/reject.8 accept.8 +f 0444 root sys /usr/man/man1/backend.1 man/backend.1 +f 0444 root sys /usr/man/man1/classes.conf.5 man/classes.conf.5 +f 0444 root sys /usr/man/man8/cupsd.8 man/cupsd.8 +f 0444 root sys /usr/man/man5/cupsd.conf.5 man/cupsd.conf.5 +f 0444 root sys /usr/man/man8/enable.8 man/enable.8 +l 0444 root sys /usr/man/man8/disable.8 enable.8 +f 0444 root sys /usr/man/man1/filter.1 man/filter.1 +f 0444 root sys /usr/man/man8/lpadmin.8 man/lpadmin.8 +f 0444 root sys /usr/man/man8/lpc.8 man/lpc.8 +f 0444 root sys /usr/man/man1/lpq.1 man/lpq.1 +f 0444 root sys /usr/man/man1/lprm.1 man/lprm.1 +f 0444 root sys /usr/man/man1/lpr.1 man/lpr.1 +f 0444 root sys /usr/man/man1/lpstat.1 man/lpstat.1 +f 0444 root sys /usr/man/man1/lp.1 man/lp.1 +l 0444 root sys /usr/man/man1/cancel.1 lp.1 +f 0444 root sys /usr/man/man5/mime.convs.5 man/mime.convs.5 +f 0444 root sys /usr/man/man5/mime.types.5 man/mime.types.5 +f 0444 root sys /usr/man/man5/printers.conf.5 man/printers.conf.5 + +# Startup script +%system all +i 0555 root sys cups cups.sh + +# +# End of "$Id: cups.list 823 1999-12-15 21:16:02Z mike $". +# diff --git a/cups.sh b/cups.sh new file mode 100755 index 0000000000..c7f7814215 --- /dev/null +++ b/cups.sh @@ -0,0 +1,117 @@ +#!/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 + +# Change to the root directory first, in case we are being run from a +# CD-ROM installation script... + +cd / + +# 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.spec b/cups.spec new file mode 100644 index 0000000000..70063767d0 --- /dev/null +++ b/cups.spec @@ -0,0 +1,134 @@ +# +# "$Id: cups.spec 775 1999-11-04 13:35:01Z mike $" +# +# RPM "spec" file for the Common UNIX Printing System (CUPS). +# +# Original version by Jason McMullan . +# +# Copyright 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 +# + +Summary: Common Unix Printing System +Name: cups +Version: 1.0.2 +Release: 0 +Copyright: GPL +Group: System Environment/Daemons +Source: ftp://ftp.easysw.com/pub/cups/1.0.2/cups-1.0.2-source.tar.gz +Url: http://www.cups.org +Packager: Michael Sweet +Vendor: Easy Software Products +# use buildroot so as not to disturb the version already installed +BuildRoot: /tmp/rpmbuild +Conflicts: lpr + +%package devel +Summary: Common Unix Printing System - development environment +Group: Development/Libraries + +%description +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. + +%description devel +The Common UNIX Printing System provides a portable printing layer for +UNIX® operating systems. This is the development package for creating +additional printer drivers, and other CUPS services. + +%prep +%setup + +%build +./configure + +# If we got this far, all prerequisite libraries must be here. +make + +%install +# these lines just make sure the directory structure in the +# RPM_BUILD_ROOT exists +rm -rf $RPM_BUILD_ROOT +mkdir -p $RPM_BUILD_ROOT/etc +mkdir -p $RPM_BUILD_ROOT/etc/rc.d +mkdir -p $RPM_BUILD_ROOT/etc/rc.d/init.d +mkdir -p $RPM_BUILD_ROOT/usr +mkdir -p $RPM_BUILD_ROOT/usr/bin +mkdir -p $RPM_BUILD_ROOT/usr/lib +mkdir -p $RPM_BUILD_ROOT/usr/man +mkdir -p $RPM_BUILD_ROOT/usr/man/man1 +mkdir -p $RPM_BUILD_ROOT/usr/man/man5 +mkdir -p $RPM_BUILD_ROOT/usr/man/man8 +mkdir -p $RPM_BUILD_ROOT/usr/share/locale +mkdir -p $RPM_BUILD_ROOT/var/cups +mkdir -p $RPM_BUILD_ROOT/var/cups/conf +mkdir -p $RPM_BUILD_ROOT/var/cups/logs +mkdir -p $RPM_BUILD_ROOT/var/log + +ln -sf /var/cups/logs $RPM_BUILD_ROOT/var/log/cups +ln -sf /var/cups/conf $RPM_BUILD_ROOT/etc/cups + +make prefix=$RPM_BUILD_ROOT/usr DATADIR=$RPM_BUILD_ROOT/usr/share/cups LOCALEDIR=$RPM_BUILD_ROOT/usr/share/locale SERVERROOT=$RPM_BUILD_ROOT/var/cups install + +install -m 755 -o root -g root cups.sh $RPM_BUILD_ROOT/etc/rc.d/init.d/cups + +ln -sf /usr/sbin/accept $RPM_BUILD_ROOT/usr/bin/disable +ln -sf /usr/sbin/accept $RPM_BUILD_ROOT/usr/bin/enable +ln -sf /usr/sbin/accept $RPM_BUILD_ROOT/usr/lib/accept +ln -sf /usr/sbin/accept $RPM_BUILD_ROOT/usr/lib/reject +ln -sf /usr/sbin/accept $RPM_BUILD_ROOT/usr/sbin/reject +ln -sf /usr/sbin/lpadmin $RPM_BUILD_ROOT/usr/lib/lpadmin + +%post +/sbin/chkconfig --add cups + +%preun +/sbin/chkconfig --del cups + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +/etc/rc.d/init.d/cups +%config /var/cups/conf/* +/usr/bin/* +/usr/lib/* +/usr/man/* +/usr/sbin/* +%dir /usr/share/cups +/usr/share/cups/* +%dir /var/cups +/var/cups/backend/* +/var/cups/cgi-bin/* +/var/cups/filter/* +%dir /var/cups/interfaces +%dir /var/cups/logs +%dir /var/cups/ppd +%dir /var/cups/requests +%dir /etc/cups +%dir /var/log/cups + +%files devel +%dir /usr/include/cups +/usr/include/cups/* + +# +# End of "$Id: cups.spec 775 1999-11-04 13:35:01Z mike $". +# diff --git a/cups/Makefile b/cups/Makefile new file mode 100644 index 0000000000..c9123926d8 --- /dev/null +++ b/cups/Makefile @@ -0,0 +1,152 @@ +# +# "$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 snprintf.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 \ + $(RM) `basename $(LIBCUPS) .1`; \ + $(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 +snprintf.o: string.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..5f6b881f98 --- /dev/null +++ b/cups/cups.h @@ -0,0 +1,144 @@ +/* + * "$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 ipp_status_t cupsLastError(void); +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..ce63211af0 --- /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 (strcasecmp(((ppd_option_t *)choices[i]->option)->keyword, "PageSize") == 0 && + strcasecmp(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..da68ba3de0 --- /dev/null +++ b/cups/filter.c @@ -0,0 +1,299 @@ +/* + * "$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; + strncpy(temp->filter, filter, sizeof(temp->filter) - 1); + temp->filter[sizeof(temp->filter) - 1] = '\0'; + } + } + 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; + strncpy(temp->filter, filter, sizeof(temp->filter) - 1); + temp->filter[sizeof(temp->filter) - 1] = '\0'; + + 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..d2dc4a79a4 --- /dev/null +++ b/cups/http.c @@ -0,0 +1,1507 @@ +/* + * "$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"... + */ + + strncpy(http->hostname, host, sizeof(http->hostname) - 1); + 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) + { + http->error = errno; + http->status = HTTP_ERROR; + 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) + { + http->error = errno; + http->status = HTTP_ERROR; + +#ifdef WIN32 + closesocket(http->fd); +#else + close(http->fd); +#endif + + return (-1); + } + + http->error = 0; + http->status = HTTP_CONTINUE; + + return (0); +} + + +/* + * 'httpSeparate()' - Separate a Universal Resource Identifier into its + * components. + */ + +void +httpSeparate(const char *uri, /* I - Universal Resource Identifier */ + char *method, /* O - Method [32] (http, https, etc.) */ + char *username, /* O - Username [32] */ + char *host, /* O - Hostname [32] */ + int *port, /* O - Port number to use */ + char *resource) /* O - Resource/filename [1024] */ +{ + 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) + { + strncpy(resource, ptr, HTTP_MAX_URI - 1); + resource[HTTP_MAX_URI - 1] = '\0'; + *ptr = '\0'; + } + else + resource[0] = '\0'; + + if (isdigit(*uri)) + { + /* + * OK, we have "hostname:port[/resource]"... + */ + + *port = strtol(uri, (char **)&uri, 10); + + if (*uri == '/') + { + strncpy(resource, uri, HTTP_MAX_URI - 1); + resource[HTTP_MAX_URI - 1] = '\0'; + } + } + else + *port = 0; + + strcpy(method, "http"); + username[0] = '\0'; + return; + } + else + { + strncpy(method, host, 31); + method[31] = '\0'; + } + + /* + * If the method starts with less than 2 slashes then it is a local resource... + */ + + if (strncmp(uri, "//", 2) != 0) + { + strncpy(resource, uri, 1023); + resource[1023] = '\0'; + + username[0] = '\0'; + host[0] = '\0'; + *port = 0; + return; + } + + /* + * Grab the hostname... + */ + + while (*uri == '/') + uri ++; + + ptr = host; + while (!(*uri == ':' && isdigit(uri[1])) && *uri != '@' && *uri != '/' && *uri != '\0') + *ptr ++ = *uri ++; + + *ptr = '\0'; + + if (*uri == '@') + { + /* + * Got a username... + */ + + strncpy(username, host, 31); + username[31] = '\0'; + + ptr = host; + uri ++; + 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... + */ + + strncpy(resource, uri, HTTP_MAX_URI - 1); + resource[HTTP_MAX_URI - 1] = '\0'; +} + + +/* + * '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) + { + DEBUG_puts("httpRead: Getting chunk length..."); + + if (httpGets(len, sizeof(len), http) == NULL) + { + DEBUG_puts("httpRead: Could not get length!"); + 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->data_encoding == HTTP_ENCODE_CHUNKED) + httpGets(len, sizeof(len), http); + + 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; + else if (bytes < 0) + http->error = errno; + + if (http->data_remaining == 0) + { + if (http->data_encoding == HTTP_ENCODE_CHUNKED) + httpGets(len, sizeof(len), http); + + if (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) + { + if (httpPrintf(http, "%x\r\n", length) < 0) + return (-1); + + if (length == 0) + { + /* + * A zero-length chunk ends a transfer; unless we are sending POST + * data, go idle... + */ + + DEBUG_puts("httpWrite: changing states..."); + + if (http->state == HTTP_POST_RECV) + http->state ++; + else + http->state = HTTP_WAITING; + + if (httpPrintf(http, "\r\n") < 0) + return (-1); + + 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_encoding == HTTP_ENCODE_CHUNKED) + if (httpPrintf(http, "\r\n") < 0) + return (-1); + + if (http->data_remaining == 0 && http->data_encoding == HTTP_ENCODE_LENGTH) + { + /* + * Finished with the transfer; unless we are sending POST data, go idle... + */ + + DEBUG_puts("httpWrite: changing states..."); + + if (http->state == HTTP_POST_RECV) + http->state ++; + else + http->state = HTTP_WAITING; + } + + DEBUG_printf(("httpWrite: wrote %d bytes...\n", tbytes)); + + return (tbytes); +} + + +/* + * 'httpGets()' - Get a line of text from a HTTP connection. + */ + +char * /* O - Line or NULL */ +httpGets(char *line, /* I - Line to read into */ + int length, /* I - Max length of buffer */ + http_t *http) /* I - HTTP data */ +{ + char *lineptr, /* Pointer into line */ + *bufptr, /* Pointer into input buffer */ + *bufend; /* Pointer to end of buffer */ + int bytes; /* Number of bytes read */ + + + DEBUG_printf(("httpGets(%08x, %d, %08x)\n", line, length, http)); + + if (http == NULL || line == NULL) + return (NULL); + + /* + * Pre-scan the buffer and see if there is a newline in there... + */ + + 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 != http->error) + { + http->error = errno; + continue; + } + + DEBUG_printf(("httpGets(): recv() error %d!\n", errno)); + + return (NULL); + } + else if (bytes == 0) + { + if (http->blocking) + http->error = EPIPE; + + 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 = vsnprintf(buf, sizeof(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%15s%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 + { + http->status = HTTP_ERROR; + return (HTTP_ERROR); + } + } + + /* + * See if there was an error... + */ + + if (http->error) + { + http->status = HTTP_ERROR; + 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') + { + *outptr ++ = '='; + 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 */ +{ + DEBUG_printf(("httpGetLength(%08x)\n", http)); + + if (strcasecmp(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked") == 0) + { + DEBUG_puts("httpGetLength: chunked request!"); + + 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]); + + DEBUG_printf(("httpGetLength: content_length = %d\n", http->data_remaining)); + } + + 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'; + + /* + * See if we had an error the last time around; if so, reconnect... + */ + + if (http->status == HTTP_ERROR || http->status >= HTTP_BAD_REQUEST) + httpReconnect(http); + + /* + * 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) + { + http->status = HTTP_ERROR; + 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) + { + http->status = HTTP_ERROR; + return (-1); + } + } + + if (httpPrintf(http, "\r\n") < 1) + { + http->status = HTTP_ERROR; + 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..74c8938820 --- /dev/null +++ b/cups/http.h @@ -0,0 +1,293 @@ +/* + * "$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 */ + int error; /* Last error on read */ + 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); +# define httpError(http) ((http)->error) +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..052e23d34f --- /dev/null +++ b/cups/ipp.c @@ -0,0 +1,1457 @@ +/* + * "$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; + + 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 && strcasecmp(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_VALUE) + { + /* + * 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..d15f3c4b3b --- /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_UNSUPPORTED_GROUP, + IPP_TAG_UNSUPPORTED_VALUE = 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..86eadabb24 --- /dev/null +++ b/cups/language.c @@ -0,0 +1,390 @@ +/* + * "$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. Any trailing character set specification is + * dropped. + */ + + if (language == NULL || language[0] == '\0' || + strcmp(language, "POSIX") == 0) + strcpy(langname, "C"); + else + { + /* + * Copy the locale string over safely... + */ + + strncpy(langname, language, sizeof(langname) - 1); + langname[sizeof(langname) - 1] = '\0'; + + /* + * Strip charset from "locale.charset"... + */ + + if ((text = strchr(langname, '.')) != NULL) + *text = '\0'; + } + + 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; + + snprintf(filename, sizeof(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'; + snprintf(filename, sizeof(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..a54424d82c --- /dev/null +++ b/cups/language.h @@ -0,0 +1,200 @@ +/* + * "$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... + */ + +# ifdef WIN32 +# define cupsLangDefault() cupsLangGet(setlocale(LC_ALL, "")) +# else /* This fix works around bugs in the Linux and HP-UX setlocale() */ +# define cupsLangDefault() cupsLangGet(getenv("LANG")) +# endif /* WIN32 */ + +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..e74b5354d5 --- /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 || strcasecmp(c1->choice, "None") == 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 || strcasecmp(c2->choice, "None") == 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 (strcasecmp(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 (strcasecmp(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 (strcasecmp(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 (strcasecmp(option, "PageSize") == 0 && strncasecmp(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 (strcasecmp(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 (strcasecmp(c->choice, choice) != 0) + c->marked = 0; + + if (strcasecmp(option, "PageSize") == 0 || strcasecmp(option, "PageRegion") == 0) + { + /* + * Mark current page size... + */ + + for (i = 0; i < ppd->num_sizes; i ++) + ppd->sizes[i].marked = strcasecmp(ppd->sizes[i].name, choice) == 0; + + /* + * Unmark the current PageSize or PageRegion setting, as appropriate... + */ + + if (strcasecmp(option, "PageSize") == 0) + { + if ((o = ppdFindOption(ppd, "PageRegion")) != NULL) + for (i = 0; i < o->num_choices; i ++) + o->choices[i].marked = 0; + } + else + { + if ((o = ppdFindOption(ppd, "PageSize")) != NULL) + 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 (strcasecmp(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..e1b160ed76 --- /dev/null +++ b/cups/mime.c @@ -0,0 +1,622 @@ +/* + * "$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.15 1999/10/10 15:40:23 mike + * Scanf, strcpy, and sprintf security changes. + * + * 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); + + strncpy(filename, pathname, sizeof(filename) - 1); + filename[sizeof(filename) - 1] = '\0'; + + 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... + */ + + snprintf(filename, sizeof(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... + */ + + snprintf(filename, sizeof(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..f135e9620f --- /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 (strcasecmp(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 (strcasecmp(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 (strcasecmp(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 (strcasecmp(options->name, "sides") == 0) + { + if (strcasecmp(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 (strcasecmp(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 (strcasecmp(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 (strcasecmp(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..65dd283ce4 --- /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%254s", &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..91a0e0211e --- /dev/null +++ b/cups/ppd.c @@ -0,0 +1,1814 @@ +/* + * "$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); + } + + DEBUG_printf(("ppdOpen: keyword = %s, string = %08x\n", keyword, string)); + + 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) + { + 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) + { + if (!ppd->variable_sizes) + { + 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; + } + + 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%40s%40s", &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/snprintf.c b/cups/snprintf.c new file mode 100644 index 0000000000..c3d1a655cf --- /dev/null +++ b/cups/snprintf.c @@ -0,0 +1,287 @@ +/* + * "$Id$" + * + * snprintf 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: + * + * vsnprintf() - Format a string into a fixed size buffer. + * snprintf() - Format a string into a fixed size buffer. + */ + +/* + * Include necessary headers... + */ + +#include +#include +#include "string.h" + + +#ifndef HAVE_VSNPRINTF +/* + * 'vsnprintf()' - Format a string into a fixed size buffer. + */ + +int /* O - Number of bytes formatted */ +vsnprintf(char *buffer, /* O - Output buffer */ + size_t bufsize, /* O - Size of output buffer */ + const char *format, /* I - printf-style format string */ + va_list ap) /* I - Pointer to additional arguments */ +{ + char *bufptr, /* Pointer to position in buffer */ + *bufend, /* Pointer to end of buffer */ + sign, /* Sign of format width */ + size, /* Size character (h, l, L) */ + type; /* Format type character */ + const char *bufformat; /* Start of format */ + int width, /* Width of field */ + prec; /* Number of characters of precision */ + char tformat[100], /* Temporary format string for sprintf() */ + temp[1024]; /* Buffer for formatted numbers */ + int *chars; /* Pointer to integer for %p */ + char *s; /* Pointer to string */ + int slen; /* Length of string */ + + + /* + * Loop through the format string, formatting as needed... + */ + + bufptr = buffer; + bufend = buffer + bufsize - 1; + + while (*format && bufptr < bufend) + { + if (*format == '%') + { + bufformat = format; + format ++; + + if (*format == '%') + { + *bufptr++ = *format++; + continue; + } + else if (strchr(" -+#\'", *format)) + sign = *format++; + else + sign = 0; + + width = 0; + while (isdigit(*format)) + width = width * 10 + *format++ - '0'; + + if (*format == '.') + { + format ++; + prec = 0; + + while (isdigit(*format)) + prec = prec * 10 + *format++ - '0'; + } + else + prec = -1; + + if (*format == 'l' && format[1] == 'l') + { + size = 'L'; + format += 2; + } + else if (*format == 'h' || *format == 'l' || *format == 'L') + size = *format++; + + if (!*format) + break; + + type = *format++; + + switch (type) + { + case 'E' : /* Floating point formats */ + case 'G' : + case 'e' : + case 'f' : + case 'g' : + if ((format - bufformat + 1) > sizeof(tformat) || + (width + 2) > sizeof(temp)) + break; + + strncpy(tformat, bufformat, format - bufformat); + tformat[format - bufformat] = '\0'; + + sprintf(temp, tformat, va_arg(ap, double)); + + if ((bufptr + strlen(temp)) > bufend) + { + strncpy(bufptr, temp, bufend - bufptr); + bufptr = bufend; + break; + } + else + { + strcpy(bufptr, temp); + bufptr += strlen(temp); + } + break; + + case 'B' : /* Integer formats */ + case 'X' : + case 'b' : + case 'd' : + case 'i' : + case 'o' : + case 'u' : + case 'x' : + if ((format - bufformat + 1) > sizeof(tformat) || + (width + 2) > sizeof(temp)) + break; + + strncpy(tformat, bufformat, format - bufformat); + tformat[format - bufformat] = '\0'; + + sprintf(temp, tformat, va_arg(ap, int)); + + if ((bufptr + strlen(temp)) > bufend) + { + strncpy(bufptr, temp, bufend - bufptr); + bufptr = bufend; + break; + } + else + { + strcpy(bufptr, temp); + bufptr += strlen(temp); + } + break; + + case 'p' : /* Pointer value */ + if ((chars = va_arg(ap, int *)) != NULL) + *chars = bufptr - buffer; + break; + + case 'c' : /* Character or character array */ + if (width <= 1) + *bufptr++ = va_arg(ap, int); + else + { + if ((bufptr + width) > bufend) + width = bufend - bufptr; + + memcpy(bufptr, va_arg(ap, char *), width); + bufptr += width; + } + break; + + case 's' : /* String */ + if ((s = va_arg(ap, char *)) == NULL) + s = "(null)"; + + slen = strlen(s); + if (slen > width && prec != width) + width = slen; + + if ((bufptr + width) > bufend) + width = bufend - bufptr; + + if (slen > width) + slen = width; + + if (sign == '-') + { + strncpy(bufptr, s, slen); + memset(bufptr + slen, ' ', width - slen); + } + else + { + memset(bufptr, ' ', width - slen); + strncpy(bufptr + width - slen, s, slen); + } + + bufptr += width; + break; + + case 'n' : /* Output number of chars so far */ + if ((format - bufformat + 1) > sizeof(tformat) || + (width + 2) > sizeof(temp)) + break; + + strncpy(tformat, bufformat, format - bufformat); + tformat[format - bufformat] = '\0'; + + sprintf(temp, tformat, va_arg(ap, int)); + + if ((bufptr + strlen(temp)) > bufend) + { + strncpy(bufptr, temp, bufend - bufptr); + bufptr = bufend; + break; + } + else + { + strcpy(bufptr, temp); + bufptr += strlen(temp); + } + break; + } + } + else + *bufptr++ = *format++; + } + + /* + * Nul-terminate the string and return the number of characters in it. + */ + + *bufptr = '\0'; + return (bufptr - buffer); +} +#endif /* !HAVE_VSNPRINT */ + + +#ifndef HAVE_SNPRINTF +/* + * 'snprintf()' - Format a string into a fixed size buffer. + */ + +int /* O - Number of bytes formatted */ +snprintf(char *buffer, /* O - Output buffer */ + size_t bufsize, /* O - Size of output buffer */ + const char *format, /* I - printf-style format string */ + ...) /* I - Additional arguments as needed */ +{ + int bytes; /* Number of bytes formatted */ + va_list ap; /* Pointer to additional arguments */ + + + va_start(ap, format); + bytes = vsnprintf(buffer, bufsize, format, ap); + va_end(ap); + + return (bytes); +} +#endif /* !HAVE_SNPRINTF */ + + +/* + * 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..9ac80e1e26 --- /dev/null +++ b/cups/string.h @@ -0,0 +1,94 @@ +/* + * "$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 +# include +# include + + +/* + * Stuff for WIN32 and OS/2... + */ + +# if defined(WIN32) || defined(__EMX__) +# define strcasecmp stricmp +# define strncasecmp strnicmp +# endif /* WIN32 || __EMX__ */ + + +/* + * C++ magic... + */ + +# ifdef __cplusplus +extern "C" { +# endif /* __cplusplus */ + + +/* + * 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 */ + +# ifndef HAVE_SNPRINTF +extern int snprintf(char *, size_t, const char *, ...); +# endif /* !HAVE_SNPRINTF */ + +# ifndef HAVE_VSNPRINTF +extern int vsnprintf(char *, size_t, const char *, va_list); +# endif /* !HAVE_VSNPRINTF */ + + +/* + * C++ magic... + */ + +# ifdef __cplusplus +} +# endif /* __cplusplus */ + +#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..3223785539 --- /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], "%15[^/]/31%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..1b4b5fe7b9 --- /dev/null +++ b/cups/type.c @@ -0,0 +1,1014 @@ +/* + * "$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; + strncpy(temp->super, super, sizeof(temp->super) - 1); + strncpy(temp->type, type, sizeof(temp->type) - 1); + + 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... + */ + + snprintf(value[0], sizeof(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... + */ + + strncpy(key.super, super, sizeof(key.super) - 1); + key.super[sizeof(key.super) - 1] = '\0'; + strncpy(key.type, type, sizeof(key.type) - 1); + key.type[sizeof(key.type) - 1] = '\0'; + + 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..f52475515f --- /dev/null +++ b/cups/util.c @@ -0,0 +1,1109 @@ +/* + * "$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; /* Current server connection */ +static ipp_status_t last_error = IPP_OK; /* Last IPP error */ +static char authstring[255] = ""; /* Authorization string */ + + +/* + * 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 + * [requesting-user-name] + */ + + 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"); + + snprintf(uri, sizeof(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); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", + NULL, cupsUser()); + + /* + * Do the request... + */ + + if ((response = cupsDoRequest(cups_server, request, "/jobs/")) == NULL) + { + last_error = IPP_BAD_REQUEST; + return (0); + } + else + { + last_error = response->request.status.status_code; + 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 */ + + + 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)) + 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); + + printf("Authentication required for %s on %s...\n", cupsUser(), + http->hostname); + + if ((password = cupsGetPassword("UNIX Password: ")) != NULL) + { + /* + * Got a password; send it to the server... + */ + + if (!password[0]) + break; + snprintf(plain, sizeof(plain), "%s:%s", cupsUser(), password); + httpEncode64(encode, plain); + snprintf(authstring, sizeof(authstring), "Basic %s", encode); + + continue; + } + else + break; + } + else if (status == HTTP_ERROR) + { + if (http->error != ENETDOWN && http->error != ENETUNREACH) + continue; + else + break; + } + else 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 */ + char **temp; /* Temporary pointer */ + + + /* + * 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, "/")) != NULL) + { + last_error = response->request.status.status_code; + + for (attr = response->attrs; attr != NULL; attr = attr->next) + if (attr->name != NULL && + strcasecmp(attr->name, "printer-name") == 0 && + attr->value_tag == IPP_TAG_NAME) + { + if (n == 0) + temp = malloc(sizeof(char *)); + else + temp = realloc(*classes, sizeof(char *) * (n + 1)); + + if (temp == NULL) + { + /* + * Ran out of memory! + */ + + while (n > 0) + { + n --; + free((*classes)[n]); + } + + free(*classes); + ippDelete(response); + return (0); + } + + *classes = temp; + temp[n] = strdup(attr->values[0].string.text); + n ++; + } + + ippDelete(response); + } + else + last_error = IPP_BAD_REQUEST; + + 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, "/")) != NULL) + { + last_error = response->request.status.status_code; + + if ((attr = ippFindAttribute(response, "printer-name", IPP_TAG_NAME)) != NULL) + { + strncpy(def_printer, attr->values[0].string.text, sizeof(def_printer) - 1); + def_printer[sizeof(def_printer) - 1] = '\0'; + ippDelete(response); + return (def_printer); + } + + ippDelete(response); + } + else + last_error = IPP_BAD_REQUEST; + + 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 */ + char *tempdir; /* Temporary file directory */ + const char *password; /* Password string */ + char plain[255], /* Plaintext username:password */ + encode[255]; /* Encoded username:password */ + http_status_t status; /* HTTP status from server */ + static char filename[HTTP_MAX_URI]; /* Local filename */ + + + /* + * 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"; + + snprintf(filename, sizeof(filename), "%s/%s.ppd", tempdir, printer); +#else + if ((tempdir = getenv("TMPDIR")) == NULL) + tempdir = "/tmp"; + + snprintf(filename, sizeof(filename), "%s/%d.%s.ppd", tempdir, getuid(), printer); +#endif /* WIN32 || __EMX__ */ + + /* + * And send a request to the HTTP server... + */ + + snprintf(resource, sizeof(resource), "/printers/%s.ppd", printer); + + do + { + httpClearFields(cups_server); + httpSetField(cups_server, HTTP_FIELD_HOST, hostname); + httpSetField(cups_server, HTTP_FIELD_AUTHORIZATION, authstring); + + if (httpGet(cups_server, resource)) + { + status = HTTP_UNAUTHORIZED; + continue; + } + + while ((status = httpUpdate(cups_server)) == HTTP_CONTINUE); + + if (status == HTTP_UNAUTHORIZED) + { + DEBUG_puts("cupsGetPPD: unauthorized..."); + + /* + * Flush any error message... + */ + + httpFlush(cups_server); + + printf("Authentication required for %s on %s...\n", cupsUser(), + cups_server->hostname); + + if ((password = cupsGetPassword("UNIX Password: ")) != NULL) + { + /* + * Got a password; send it to the server... + */ + + if (!password[0]) + break; + snprintf(plain, sizeof(plain), "%s:%s", cupsUser(), password); + httpEncode64(encode, plain); + snprintf(authstring, sizeof(authstring), "Basic %s", encode); + + continue; + } + else + break; + } + } + while (status == HTTP_UNAUTHORIZED); + + /* + * 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 */ + char **temp; /* Temporary pointer */ + + + /* + * 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, "/")) != NULL) + { + last_error = response->request.status.status_code; + + for (attr = response->attrs; attr != NULL; attr = attr->next) + if (attr->name != NULL && + strcasecmp(attr->name, "printer-name") == 0 && + attr->value_tag == IPP_TAG_NAME) + { + if (n == 0) + temp = malloc(sizeof(char *)); + else + temp = realloc(*printers, sizeof(char *) * (n + 1)); + + if (temp == NULL) + { + /* + * Ran out of memory! + */ + + while (n > 0) + { + n --; + free((*printers)[n]); + } + + free(*printers); + ippDelete(response); + return (0); + } + + *printers = temp; + temp[n] = strdup(attr->values[0].string.text); + n ++; + } + + ippDelete(response); + } + else + last_error = IPP_BAD_REQUEST; + + return (n); +} + + +/* + * 'cupsLastError()' - Return the last IPP error that occurred. + */ + +ipp_status_t /* O - IPP error code */ +cupsLastError(void) +{ + return (last_error); +} + + +/* + * '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; + + snprintf(uri, sizeof(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 (strcasecmp(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 (strncasecmp(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 (strcasecmp(s, "dpc") == 0) + ippAddResolution(request, IPP_TAG_JOB, option, IPP_RES_PER_CM, n, n2); + else if (strcasecmp(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... + */ + + snprintf(uri, sizeof(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 [HTTP_MAX_URI] */ + char *hostname) /* O - Hostname [HTTP_MAX_URI] */ +{ + char hostbuf[HTTP_MAX_URI]; + /* Name of host */ + static char printerbuf[HTTP_MAX_URI]; + /* Name of printer or class */ + + + if (name == NULL) + { + last_error = IPP_BAD_REQUEST; + return (NULL); + } + + if (sscanf(name, "%1023[^@]@%1023s", printerbuf, hostbuf) == 1) + { + strncpy(hostbuf, cupsServer(), sizeof(hostbuf) - 1); + hostbuf[sizeof(hostbuf) - 1] = '\0'; + } + + if (hostname != NULL) + { + strncpy(hostname, hostbuf, HTTP_MAX_URI - 1); + hostname[HTTP_MAX_URI - 1] = '\0'; + } + else + hostname = hostbuf; + + if (printer != NULL) + { + strncpy(printer, printerbuf, HTTP_MAX_URI - 1); + printer[HTTP_MAX_URI - 1] = '\0'; + } + 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) + { + last_error = IPP_SERVICE_UNAVAILABLE; + 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..7c59236e20 --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,118 @@ +# +# "$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 spm.shtml \ + ssr.shtml stp.shtml sum.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 manual, programmers manual, and users manual get +# special attention... +# + +overview.pdf: overview.html + echo Formatting $@... + htmldoc --duplex --compression=9 --jpeg --webpage -f overview.pdf overview.html + +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 $@ $< + +spm.html: spm.shtml + echo Formatting $@... + htmldoc --title images/cups-large.gif -f $@ $< +spm.pdf: spm.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..8748f3a5b4 --- /dev/null +++ b/doc/cmp.html @@ -0,0 +1,753 @@ + + + +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
+GIF89a¯ÿòÌÌ̙™™fff333ÿÿÿÿÿÿÿÿÿ!ù,¯ÿBþXºÜþ0ÊI«½8ëÍ»ÿ`(Ždižhª2€0p,Ïtmßx®ï + + +;±Ýíˆndý !¸ ž³wà…MƒƒY~¿{,gÚ\‚äé +Œ×Ø(tÙî!Ï=Ñ.ûz¯áџ:ì;Ã9qöíÉë]/¿ºÉ¤Et/†'Îþt9Àؖž_ÙÇ\|W•wArö¸Ý2Ô× +tN°0Tï}¡û‰$!‚yMxî)ˆš‰Ôø@nB°U½ÊwE„§!ŠF H L8B +c‰;ždŠ-æDVWdг€h±äړP¶%#(4Fiå•Ï\hŠ:Re!\ÒėX^¦%€¥À-$E€Ö/úHŽšlââöÌQX + + +¸1Nô¯b"œŠüjåÁÂE0…È8ö5GkZ|ÒÁwt„C»ÔQSÇo6Ôِ[W„$²*Ž+4Pb-8¹P1þ'8"‘ФÄ$ Cyê‘„)>ãŠtè`Ð3‡‹¾z"«rE'Âqfä°Ë +‘qÂ\|€„Ž¡ôö»%É(.—bڽȀíÉ`{¬EÇ1w’ »[Hß`(B6ö“  +†')ÊRŽÎa[ÃrbC!T尌 +2Q·ÈHZê#–®üË/àô¯FÝê(Û²% ºXË9öÀbÁ4f.ù-oý™XËB…IÎÒ7¹*@ÃӎÍT€hà‘ÌW␙Ã$f:µyžn†ó†r„'téKv` +Ç+dª– œ79sò|'=×¢Ìx¶òœÿ„¦œˆeÎ;*à$þ” IÝÆaÏ{–3ŽÅÁ +P“ÍS[ÙL¨3©òQ7éÆò#ãûô0F×ðsE°t§@‘ØQÜ´´ ©:3ÓRíd ¥*MITnŒ£¨H]ØQÁd +@òþ—¬rMœŽaO + +rë^yÀ·(¸îéêû$uDòrã/a,I.°ÙUÀœb hˆ`¾B ë" +Ü`HØxȸo1þ[á\8f^æ|\ý‚¢¢zø0(ˆ\ {ƒÄgäÞõ€çâ§Á˜0*\³n¼‹m¶/Äeª±ÿ†ì +Ç,½DN2€œº+ùÉ|í0L¡Le*ð¸Ã>­2ëf,eIPOËÅàr—±”80SAŸcFªatç»ãy¤¸ršçÌ¡5ïoõËsžï|¿8˙Φ¬þ,ï¼èà)ÁÌ;øk¡—†dDpÑòø2¢qfHã!˓~ٟ-í +'g:,æ4y?ýäP‹Z›ž#ÏÕ´Î5AK‰k]ûš›ÒKõ¯‡më€õzØÈƫ؎Ý>B{PЪ.6hf]º?©ÌIŽuO„íM‚ÌÇÜcµ3˜ +61‹NÒ[†W£ ¦m¿­{ÂPâvζKnUˆ[ ònĽ±÷n?l:Áž3ušë¬sP[ÿnn¾çP…WõÔFj[Â÷ +¹vÏ™à‰˜xú'ˆ£ÀÀ†p¸4.êãKÇ¿ÂÁ±o§¢ü"Á|Nk`îʘ + + +jl©ÌuˆËi™0pmC´«+‰÷6¤2­éÏe`(ŽJ]¥iõð3ƒØí"p|ª!:qøFس 6£ +@­,þŠqüぐoÌÇ®žÖüV“¶QǛEvî¹²É8ÙªS"æÀç‡x± àþ‡>—Iãg +ïÝ>Y‰çN80æ§ ±¾GLLìÕµ…(1Þ¼!8}þ¬“*…ª‰Ùì:e»´œ +ª¿ên_6ÂÃSÀ`eG;Ö„CƒCcˆ¿‡4¸yeî¯Í)oøByRm½0?íLîÅ`QÿjÓÙ/ºôÓN|Ý + + +þÙAÜŒÁ¸D5©D aævx ?жx°DM@•!h‰àȀާ® +• á×B`ð¤ªE?›“”Þdƒ"8$Ý`Ki0…OðƒnΓ±µvtžè€I([,¹Ndɨh\'6X +P㗊‰Éøt ¢‘¥˜¬è €ˆ†Ky™FˆŒë`š”yƒ„¨š €š‰ƒM©‡øFQhY„ +9¶X¯×–í4š¤™Y\)"¹AN]‰xéz÷Gq07)©ñ™•Y€r°ŒŽi‹ z ™ÇäFÍÉT–ù› +ËŽC œwI›üX]‹¹\ëY]þf lïYbj8ŸÈuœbŸÍÅtú©fÞןfBI—“*øé:ÛØUj Ò +ˆõ¹ Õp $(~ ¡Ú ¡gù{îpZI?¡ƒîÀv:“a¦˜6¢§Ô]Ý‘(ªê)!ŸÚ¢: +jwµ¡4ÚvíHÛǘ9ºXhó•üù£¥Á¢VÉ{Dº2š‰(°¤3š¤a÷ +У¥“p¢þò4Vº—  +E´¥è¤k°7ºhT*€¿èw`ڞiÄ …S¦Ʀmê Nêƒ#ú¢f€ xê†ý +8z©7uÚp{Ú=~]7`«h‡ÚsÚg:…zd˜ó§ÎA-vþAñr¦'–AÚ)9–š¢âSi;£…š 1ªo"ª +¦J;“º rº8Ui|é>¡Úœú + +“ë¥Dfný2»ƒ–0j«®»ºK;zë¢Íö»—!µ—S»³r>K+6ˆ‹¨XÒ»; CÈ +8Ê;¢»ÃÛ/Œ‹¥ž!¬s½VR½óõϋOâ[/çK¨þ˜Ñ:͋\Ý+ Sc:ï˞’º¶ë9Æ» + +ô 8ly$ +8©ÙÅmX2Ùh>—?¯!šHüÁ^LsP,Ÿ«Y‹âá¿ÿtšì‚£Y +r¦Éš¥9ÇjžÄ8-ÆÇŒ¶iêPÂbA˜ù‰Ã¸š»³7RœCWRoìŠå MŒŠ”åt™ Œ›réÉq + + +å>}Lê}ÎǨ 5:àŒ|"þÇwÐsøæNΰ¹#R>~-N‰®èƒ ßcðÞÚÎÑ¥®åGÎâ툉Ýè*‚¸ +=‚ž ºëⅭëÀ>Û·žën^žmèÊëð¼ã>å×Λ«}êØ÷ +“Œ¬ËIÁ·AÔNÍëv>]t.âÚLЫþíï¾ñnäÖÜæs¹¿±â°+† +¬UØïî•.ç¬ÎìÍ.è´ÞŠG=ðù‚§ž¯”ë^äÛ®êh-‹êê!i!ÕvMíiªîþ¾òîá/þÑ-OÖGð,oñº!å’gOâ POìOôBþÈàhâ+?ï>ßÊVHÀsaõ™€õ$óSîõ—»ó8.žß¹ +~áßÈ©ö»]ò3ëÆt_÷[ïôb¯ç‚Ü÷Õ«@u™ð;zܘ‘Ü@óŽ2’?ùƒ¸ÙlùF ¶™¯ù›N ž0œú£¶¤ÿ0#9:ß§½ž©Ÿ\#ÃÙæó2é+û‚ÀÓ¸_äM/ÓtaÚý3”]Ù«¿¸iîaF>ª}ŒØvÍïMÍ÷Ðëä©îr܌öqñ_ÀüªrâF®ò +ýþ¸—hT_ã4sx”ýÝî)ç.QgûàŸÏ%ì‹}i´ASû|þð@QÜ +$J9€»-̱÷ÜôMؑhZ˜¦:°œ*ÏlßxÒ|ϼ¡ÅLÀ ¬Áfù9BÑdìÁ|«VV„¢“énKv + + +kB_ƒg 3ʳ8#Þ¬L=0;J¤äÈ@¤F|'i~±© žaʊÆg;d*3²”©bPÏ¢TäHô¦?[† +ÄäƒhN6ZM¢D:c*BR!$±ckƒ’V­-uÛ@[øp„Ÿ]¼8ö-1{TήWÏ2ñ Šp=¸q«Ñ½es.‰„4+#Ëe¦¥W5µekxr䛓/X͚5Iǃ=kÝúµì˰ûN–2qÅ¦yZ£QŽ›ÇޝtxŠäcK—Ííɹ +iþ¡9¼m1oñ¢©/²8îìSté4l’Wm¾9óéÖÛÐãã{{üzÞ¿çøêöÞzà}œàL¨ "˜ +ÄÐsà¶PGLUúå`MÞ  ¡†9¬§Û{pX¸¡wÚw߇¡¨ ‰í "MUXNx + ++l´á¦ +j²F:Á.êÆÛj¤³Búî ¼Ê«/£Ö’[н#í+ð¥ænJÞ¸«æ;ð©õ‹¨ _ËðĊһ*º? +ƒÂwœÃyzh±°Øzl2,#oZ2țr|ò˂°¼$Ç)ë +óÍÙÔ,éfs€1Î@/øîÏPõÌiÐH·ðÃBkLtÒP¯bôS;NÝWÔXÏ +ó’dlÍtÖ`°tžOc óÅa§}Aě²1vËjÇmþu+`ÍÍÁ·qwü6˜‚ì½sÞXŸ¨Ë$xM6àP³-iÉSÚ½Aوïë84–ø=xä8^!ä*L>ޘƒk¹Œ({Iè^!ḘN$ê +«®ç!ºû‚ÿÝ ë¯ßoî—Oü¨¾ÿî9í]ñÞ{ñÙÊ®ãlhŽ(èÌÃê¼~ÔS¢|ö՟zýw¬Ë§|øÝ—*½ŒÈ×­|úåwzþæ“)Nrû¾Ê?*ô¥ +¿*÷ô7ú½~Múúú÷ª÷Ɉ•S3x*ûíP”ùH£°°àó(è¾í-Jƒú™ +åAF{#\”g…Áœ)!),Ô #ÓÂǼjþ1œŒþh©²K„9$ƒYè)Ž ˆA È +—‡)#1‰Óp"˜ð'Ã%n‰P´‡Ù¨-‹1³¢^\%ƈÔp„CLÖ5à + +
+

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
  • +
  • RFC 1179, Line Printer Daemon Protocol
  • +
  • RFC 2565, IPP/1.0: Encoding and Transport
  • +
  • RFC 2566, IPP/1.0: Model and Semantics
  • +
  • RFC 2639, IPP/1.0: Implementers Guide
  • +
+

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.4 1999/09/22 20:06:18 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.4 1999/09/22 20:06:18 +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..3bc2940ad9 --- /dev/null +++ b/doc/cmp.pdf @@ -0,0 +1,941 @@ +%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<>endobj +194 0 obj<>>>>>endobj +195 0 obj<>stream +xÚEŽÁŠÂ0„ïyŠ9º`bÿ6mÉÑ-zº Ø´Vj²›FÅ·ßVY–9 ó óÃÉ$B™"+pº²OÍV[…4n‘+Q +¥ÐÍ¢:ÖTÞµ}w &öÞagœéìÕºˆz0îC_&Z‚h¦Iæ"§L¤8¯v5'‘ÌENRxZ¼×7f|âàÛø0Á¢¾¹âø*Êlºñ¿ã¿Ÿ¡ïΤTÉ'SK¬‡û9±·£ wÛÌèF³/ö õº>nendstream +endobj +196 0 obj +188 +endobj +197 0 obj<>>>endobj +198 0 obj<>stream +xÚ+ä2T0BCc3JÎår +ár á +äHÉHendstream +endobj +199 0 obj +31 +endobj +200 0 obj<>>>>>endobj +201 0 obj<>stream +xڕT[o;~çWŒò”He ’¾•܄Դ ÕyàÅxgÁ×³±½ úëÏØ»„„FQQ„”µçò]ÆóÜJ¡Ã) »Ð€,Z£y럻+èv`žóÍ`؇yvžÂLR‰ó_ñ6Ö·íAštã}’Â8CãU®¤ðŠLڇ4mB»ƒ$–š¯•I&W«ÊÆP(„+,8J- d$«úËÒFeèÀ¯Vÿ«•áϜ,d¸AMeŒ&ã"Êxþ #(ý¹kÚ«†×TÜíñûø?˜XŽVf³óXÀâüìúq2;[\ÀO´. J“8ÊýVXLþ`Þï$—5óî¾Æ ڍÂíÔ?ñBW@I֋¥F>kb´Ø¡ÌCî¢ûyìHP/],à{X wD~‰hözaËÜ +·ƒYCŽqPVIÏ2SÀPG†à<Ë*lv€àHWѰ€Bh]³Ø ÉȺ`ÂQßʱ” aßZÙðý¡}B;Š‚'!k[¢Í…D—4U÷*Ær\º.5qýALfãI’fOÇ·ó»öx2aWE¾NÕó‡.ÄGzð‹–‘çÏ-UaON1ZďŸQ„!?©Òç@}¿§¼x”Nãò•+ÜkâGow'%Ž8ñš²àÜŸ+e£MóË&ª]»—ûÍ`Œê_v’+nNÃ÷í¼õoëòj6endstream +endobj +202 0 obj +868 +endobj +203 0 obj<>>>>>endobj +204 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 +205 0 obj +117 +endobj +206 0 obj<>>>>>endobj +207 0 obj<>stream +xÚ­•]“š0†ïýçҝ– êU·ãL¥‚{åM +AӁÄ&q¶þû&¬¶îL±;\€rò¼çã=ú£‡ÀÓ‚ȇaYÕû”öŸÇà{úMæ}Ö¤ ‚°ŒÈ‡ô{‚"â„Èõë Ál'0çÙ±"LaE9³á Ԅû¡[3Ó=‚—%£lg旁J­jßN öú«6fbÁYöG:‰3{ë‡\+÷‚3[År½‰Õ›qVÐÝQX½fxG â³k¾N mï—óù<9IE*X2ED3s"鎙[&èáwoºH$ӕ‘p¶"¼PoX˜æeT*] ÒÔrÄåüëZú‡¤¯n¡cÁwW•1ÁÝY'ë[è„dGAÕI›÷À…ºƒ›Æ·¸)‘÷Z$Ù¼3¿$ÿ3¶×ùm쫦oÿ5¹v»8çŽìûð¢öDœ—Xþã3Μ«%–`øÈ ^. @ÃQäƒv½.|¯k›h;Q¦L>Û~.p¡¶º¹ŒãÇzâÓ<§†ˆKx9œˆ•‘àhs)@Øëç™~ŒÆøB±™šFcRé é=P<ãeg¤ÿ> àœø‚e<7 À,‡T`&;{¿¡†ÔÏIY#RaÝáLvG†ÃñrYÊú×Öÿó‘æÄž5ggúã ±æÿAÁÈsÇZW¿šÏ‹´÷µ÷ dÃßÎendstream +endobj +208 0 obj +541 +endobj +209 0 obj<>>>>>endobj +210 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 +211 0 obj +122 +endobj +212 0 obj<>>>>>endobj +213 0 obj<>stream +xڍ“ÍnÛ0„ï~Š…N ਖìÚNoMœ>´h+ÕÈ!šZIl)RáOä黤”pš¢°&´ËÙýfô0É`F¿ V9̗À»ÉU9yw{ ù ʚÞ,W («³9Ü +‰ð‰)Ö`‡Ê—?b]¶ê.–YšÇÊ4ƒ0ȝ6OP8ã¹ó‡údÙXŸ/Óxó ã-Xí G¨ƒ†m™”°Gè%ãXë÷՟+¹6m¯U%TNƒk©I×îÀ ÆZûdv Ý"µj,U}RÍæÃ”÷g‰å-V^¢I¦H±ç¾·ôOïÏ¡Ô`°cB‘^×3'ö4ÚA¸´¬ÐÀ÷ÏÛ»8ï f§pœP±í¸‡ÒîD9ÒZÑn™aÜ¡±@:UãÚôØÅ,]`s(NÁ û&ÑâÓiVšû`\ ª*¨µé˜‹' ZnĞ4ÇǾGbûWS¸Öò7|ð´]h·ÿpN ª7L«WqùïaGë½ +¨ƒ¿\+g´]Ç#ÉpO1Pv„´,ƒëäìõ®HÈ—L¤#¶N$Šÿ$ƒÑ’I©&ä‹t™ƒŽ€Ô‚Çõ,p¦B«#©3^VیÄôÄÉwÅ1¬"Ï¥¯H6J†ŠC+ö¬GC¹ åÛíøBI‘¥x~ã'mð彚ÉhÓúH|¾ÊGŸþö-/Ö³ô’Êèýûp¾)'_'¿{žMCendstream +endobj +214 0 obj +544 +endobj +215 0 obj<>>>>>endobj +216 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 +217 0 obj +118 +endobj +218 0 obj<>>>>>endobj +219 0 obj<>stream +xڍVMsÓ0½çWìpJg¨iÒÐn¥À '  Ã%Å^×bdÉHrBÿ=oe'i\\˜~%Îêí¾·oWý5™Ñ¾ft9§ó ÊëÉûåäͧkšŸÑ²Ä'— ZSüò®]¦;nœôÕ»œCÐöádù'4›u'NçY:sC÷®Œ[åyxx5}u¿¼{µ:¡P)chÍÚu­cä‚xÃþ‘¢®™µ=9O¶þðf‹Ôø°ñ µ€´³ól.i·:V+¦Ûï_ï)ô%dû|ªçQW­´øAZmX¨¨Ö*0%g™\™°JgŒÛ‚-…¨"‡w’tþö@v–‘<š‚é@¹q  &wuc8JæàLµ³ƒ’磇]ǏSyÔÄ,Žcè(,VSË[’‡PU…xe Bé|­ä©ÒFA²Õ‰@œ>¥;sßǦóÊoÅÏÄã&dc®ivÙ;fq–]uÅÎèÖ(تԹÚ1þ«¹~T, ‹GuCÏ9C44R݆(Eå=&žªø÷¶ØÎŒ·õ޵ °RLh+ÖlãH?¸¼•;Ù{çGZ÷݊À„ƒÁ¨Ôf¬‡Ã`¼PÝKâ¿ÃÇ·1ÏÛ -B0ýh¡¯®5PÍ'B°±¯Ó¼¨f á\:ØX«¼Â‰1Ë?µ„>>>>>endobj +222 0 obj<>stream +xÚuASà …ïüŠw´‡`ˆ ¤W;õ¦SGü4'%i«ÿÞ%ñêÀ°3û¾·oùb5Un7²GÃƓ¢´æ +¦¿“\â%ÍÁ‡ÎÎ!ōù PBˆ¬Eæìp™\FʸºØS âbu=ng1ãÃwìՆÁWøàé3'jŒ¸Ù ¥a=Ž?ëP—sÊ| oÿ…Լ…jé¡üÝûá »}8]ò²*žm´'7º8ã0Øeõj5Uº©‹©-=)$oPÿ÷Û½a¯ì¤ŠYƒendstream +endobj +223 0 obj +214 +endobj +224 0 obj<>>>>>endobj +225 0 obj<>stream +xڕVMSÛ0½çWìpjg°k›HoÀ@§—NJ WF–׉[r%šߕdÇÄùh‰­Ý·oß~ˆ_“"ú‹á*‹ðzr›N¾<Ì!‰ -èdv5…4ÿt KY˜w¦±B¦QN_e|å-ƒY&Î6Œá•.¥€m¡*ÅÊ[O!Ž;ëd:ä»§ÅZÂf­ƒ†)o€p ‘Þ2ƒ9dhQ挅BÂ/BÍ^¥:‡ºö‹‰føš¬eˁ"Çž§‡Ö_=µæ–‰$Ž˜ Vè`z÷(¼¶çq…ÑnZóî»EÃÚôá)C’¯9Ñ-‹ÒçšEN¹*4†²½…BV•|÷&ö kË*ïÄøg™ó:D;‹O¿»ç%hÁ½–J +èÕ/¤¤Úl £ôœÄE)XÕçèÞ¸jZÖ£"R©8æÛ¤Fåèr?{;s ï¥Y;yYS„F–Âh[ñŠqҒ–JsI-pL”·ø%zéòý ‚}B„{F}Ã×L¬X0…èÛ¦k+ÒEÐOÝO…n³@o´Áš¸Â-Y˧;)Bø^·ÇéÀŠÂű¾[øu¹ póBgÂw¼­öœ¤«*ªÏ@„Ô²’î±98`ÊØáŠMš€Ëº¡aµ! ÏóaìþƒÄ(¬ÏaoZ; ýÏ±"w= ôy(MœkÎQ’;ýŸXÛ%rIQÿf 07Jæ-7¶©{Ä{T¨nîà±‡_ìwŠ$ëŒc¿ÆÆ§#ì;%å$ã¤_ycãS’aOö—…›´ipI]ðÍ/ò,ÓGw)ž»Õé÷’¤c­©T´½»d¯‡Df—áìÄ?Óë(œ“YÌíó}:ù9ùƒ’±endstream +endobj +226 0 obj +848 +endobj +227 0 obj<>>>>>endobj +228 0 obj<>stream +xÚmP½R„0îyŠ«´8$¶Þh§sz¨õ,Gœ`6̍oï,,œ¤Úý~÷+QÉS°+ãoÇä¾Inï@UÐô²)«*-¡é®nÓ^É2]7Ÿ‚)@©³ÍKY +æc 8h{†N$ƒÖ“¡@ðܶÄÜÏÆ|‚¥ tšƒ×§9hgAx&Ð ­'Œ„Þ»Â@ÐÎޓ °?Š^·DcµKóh¼a‹.lRxv0y×Íí"é×ÈÀ#TP[`ׇ zm KRëLÈ,¦Ñ'ј¼–ÀҌӵ}ýÛ^UZC½¤Ø¿ްw¶×çÙãbÿ„V*1úÁ ÜíJÙVyI*‹Ã"¯Ódÿú¡I^’Zƒµendstream +endobj +229 0 obj +285 +endobj +230 0 obj<>>>>>endobj +231 0 obj<>stream +xڝ”ÁŽ›0†ï<ÅÛlLÙS”d#­¶T°R¯³fºÁ6µFyûÚЕºR°Ô +„€¾ùϘŸ ƒ•?¬søT—É—6¹Û}†|íÑGÊum÷aûA[‹æú±ý1%°õœ–,˧”ŒAKFÚ9£ÆB†§¦y™M”j7BàZŽgGTý{ÊރҿÓG48 4,RP=h†8‰_á¡C‡ µ!p¯¨¼íáý NÈxA1RL½V”^ð\ȳÐÊ÷e ðBîB¤À]4ŒF÷¥•³dþ—»ðd5?‘‹¹òr'WÊË׿´à.{?©Ÿ¥´Xe÷óTä°áF«kl06Mu8D„H¿Ü7¬q¨:4Tº#8z÷å¯rÒãïýøM=E\WÏu³\ªò=êùéðj#” Û\­#an›ê®^†nëæëÓ ñS26BÞµîN ­AehÚi®‡í¡N÷Ë¼º ä\Z#?¡{ƒã«àÿlÉùÓû7ôÔèÿ‡b]øî¯B€±ðbÛ&ߒß07endstream +endobj +232 0 obj +423 +endobj +233 0 obj<>>>>>endobj +234 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 +235 0 obj +381 +endobj +236 0 obj<>>>>>endobj +237 0 obj<>stream +xڝV[sÚ:~çWì0}H[0¾O‡2‡™6Ós Éyȋ°Ö©m¹’ áßw%â$6Ã4aaíõÛÝoý«ã‹ÿŒ|†e¯«Îàv ¾ « Þ G!¬â«¯0ã1Ë·ð/ýU2A3š+ùqõ?ʆàyV¶ï#½J¨¤Y QӀBð‹)ÄT–ÒX¾á"#Šñð#y)" +¼{¡´ ’Çó¨ÔF¬lÄs…?zöÇñ¼-ÑGÊr*A&$MaMEÊС⠟̌ÍÙçÏu—§øbØ3•ÀìþÇÒ±YŽÁUY†®sm0qüη+æEsY +{V Hk–2u°‰ð4¦îïÿ½Á˸:HE3铱î5À„åýM™Gôc4 Ù!ž9Ðg,4•Û@׉ººd0½[.*xñYQاˆô×õdÐés•`”]–GiÓnÈYŸI×y{8Ã#ì>ÜÔÛæ\Ç"‚…6JI”¼êC@…H(ÑhnÙNƒƒ1›RiU}Ö*=s*JQpìFÌ>'JWƊ´ã`õ"^Û&Ê`˜²H'Œžr®ðÜ3O§SYªØÌ8‚p`Ul|¨öƳ ;f ¬!« Áú`¬Í–Ðý°ˆ'È…#•¥½xˆœ7îxàûHw8ñ®!c?)̟ øÐE¶‹¹ c 9rLß7ˆ>£©Æ >ý™“wfÞÛ¸¡2¬PUãT* +‘ÎEf§ª`<£¾Jã3'ò€ƒ³Q{‚þ!x\FJö ÇqÙdL K‰/s}¢SS`©DiëÞ‰mm™Õ¶…ý B—p+H&£j2iúSð‚ +¤¤9 cS?@QE‘ytK4™»¥8$­µnJöÂÎ0Z¶. îÚX‰‰XXŒ]^*MÓq“ÍZ+C÷Ûb6¿[Îõ¬º°O˜ф—il‰aM©îbÖ»›“Ææ¶£‹ÍËOÝó“fÈpXc’‘-š)RJ¤mdÝ&ƒm¨©ÉEuÕS¥ò‰Y4ðí4鋗ylÓkvÝ&†^ø¦ I(x`t7‚íL–%Sç*lSý›§éaÏy܃ïDR]EßÃ~à!Þ/§çúÀ1à <]®÷ô‚QÐÝ 5ÅïøŠ€tP²¯ê/}r¸Ø¶)<>>N Qª˜ ûýÞiÕxobV±Áe¥;r¯÷t…™ô_ñ‹çœÓð4ü³AƒFð^cðz¹õ ÕÖÖۚ+ų‹6œúåììŠÃI>^ÖÛõòËÂî¬B° [íeV³Š|ËÁ«ŸÆ/ÅNÄ+bó¾®-õ‘  õ¥5…ˆš«e<Ó~óUçŸÎoÌLHendstream +endobj +238 0 obj +1066 +endobj +239 0 obj<>>>>>endobj +240 0 obj<>stream +xÚÍU]oÛ6}÷¯¸0 +4lY²<'vח¦.‡vê½(hêÊâF‘IÅv‡ý÷]вYK»ìiŽaðëž{Îá½Ìï½búK ù//{ïV½ñ‡)$ ¬rڙÝN£[XeWV׆#äBâ9¸ÁFSÂB)¬j ÂùY¥i¶‘t¢`¸Î +faƒ¨@jë@!3 ª t@óЋÁêWÊÃܧ'F£ÉÔg_ûFIèÀ5,ChÿÕ}¶ æUd WÊá#$ñŸÏçãx>žL`/âÙ"¹%Ž¿!,÷¼êG¸qÈ<‡äƧùÜÓv÷]4µâNheOç¦Á¡Ñq4mOE |b%ùmMfáÐ vÂÀ`+õ†I°\W¶`R’MÀY%“â+f°¾ê¿×«BØþšsaôY—è +ʶ”i ÖX‘—ZÉÃQbJì)3î9V>58M~Ó-™Z>Ié¯àî—‡Ï ”C“3ºl)6†™äg҅à”ì@[¡Ž"*ƒ¹ØÃN›ŒÂ/K½CÙE¯„ו=«9ÎE~ü¬_Ró®]rÉ yÕ·Ž9ÁûÀ¨8h㜻 ¯U††b úbt;_ž´½ LD3ýŵ,›a0†öèú|j{§,Ò4šËbï5¯KTžVÏVǒ‘»G·OòžÍuéQ @FJH·åFl|ãí|§5mt Ï4Úa³tjG¡ªÚѵ–Âu%SS3uX†y‹ÓµóLÖäÜåQ‚­ º¡rmÊF%59f˜½¤¥_·®¯¯Öƒ×0‚;]R^„¼…°¾_º½Ûú¤Ú(­ð™V²r1 %¹Ôä¨ÿŒ¯á'"s¯©x¼+TSÁ‹!ÄQ ?¾%‚ô“и~Rðˆ¿Ç»'¼‡3YÚí[ :ցúãRIuÄtµQ„G·óæbóÏo>q)|¤ºÖÙ·¸ôû\ rîM¡þuÂKúîòyû^¦/ë²Ññ{° þuàm«4™ÞНûìÚæÍ¿Ó*Ûڄ°L±-6"$kŒ…¨ÑÍ$öAÉÔ/¦„‘BüMþÉßåª÷sï/™Ýkendstream +endobj +241 0 obj +821 +endobj +242 0 obj<>>>>>endobj +243 0 obj<>stream +xڕUMsÛ6½ëWìèËQ¢>m§9$Nœñ!©;Q{Ҍ—`P¶Úéï‚õAZi+ÍHvñvßîÃòG'†!}c˜`<žwÞ/:ƒ»!\Ã"ó;³«y4‚Ez1¸ì-¾u†Ð‡Ñ•߀KxÅ%³öæ&Տn-ìòbÙ{}¸ÕyQ:„-¼…°ÿ¼ìE­ãm¼/Ú¡½¥¶ÝÆ2“š9h—ð+åt¯6h,B¡ŸÐÀ†É_Ã0Â/o)Oú‰é¹£É/!6öž`p°¼Øá=ïðÈ­…øW“Wµ¨t¥Q„·]öÞ4Œûõàîâ¹ïPŸZԟìlï£ üÁŒ`‰D»÷›x?B˜É¼¢¾°\¨Upš@ïœF³à´‡'áÖÀ`%uÂ$X® »fRB‚ÀY!“âOL)ÝTŸì¾Z3wºö«c6ÑñhÙ«YŽƒØk­äð™cá„Vàt¥%0¥5ãî“5XHÊ0…d Y©¸çՈÍ̪ÌQ9Ÿ-*$͒b­TËäl‹¤æíI/PÎHù•W©Rº\:– {B¤2h“ZÏÓ×÷q³'ÔHÌÌ™k¾ïÔvú„²9岤¢3°º4Ô§L72EºkþLג@ïF-ÇѬð>h^UŠÕU|Qǵ¼Îë…hºJ fH•$…ÀTzpyŽ© i1ÓÒW³¢Å€ë܇‡„¸o”*EˍHè‚U­ã߄4õ?ª’$íÂIí߄¹åo/ña|UèNdá´ÆJ€8êÏÏ!hˆˆ³“d +‹mñÓ)2ý÷)òŽŠèˏ/Â¥ïE÷Ñu’WÆ-“€Ý¨­e›NÓu­j³_f΁MÿŸÀ*ŽÝšm°©Ž%˜Ñ*s,Åìœ,^zãú1ÂÑ?…á—i9t5)í™Wçàîj—~Çd™]‚½‚¸Õ*«ÒTlá3Sl…ƒÉ*öýx2'ÿþ|4 5¿T£É|BN•G<õß:ÿN÷‚¢endstream +endobj +244 0 obj +849 +endobj +245 0 obj<>>>>>endobj +246 0 obj<>stream +xÚÕSÑn›0}ÏW婍Bº>­Y÷¶©SÙ[¥È'°f`EÓþ}×6Iºdm×Mš4¾¾çúžs¿|xôøBýòrpÆï<\"^êH8‹Ü âôLmk‘Š%òJwu»PYNŠ.ÔÕyü™P—ð# sçL=w¦q×nˆ;Õt\uh÷‰SèÁ¹ðÜiŸæúøÀʼZÙ¤)|¿Oš„6éMQ ÝÕBÅJÑ¢ÍEBnDÃY+°ÉU†®JEÓrI‡Ò®ÚQa#›´«R TgVׂòR( • Ðr©ut²Xöú,ܟ iۂ©ð +bêçPܽ??¡$EOu‚·’w¥¨S¹¬e|Ãxö€²%›±µ—¥.€¤ü rZ¤9S¢Øß%ñ6Œ,ÖpºV)ÊD4{Վh¦}S¤H^q’/eï%ÕõÖ¬ÉYRõiT¨e‘ó-X"×âµ¥q031$Æ£Ý1½'0BLB> F jóO·wô#Ö@ÖZ™Ö=ÁŽ"=Ń)Ã8Êüv\˸Ù`¬.WÆ#Ì»¦Ñʶ4aÓ9§'ïðd€gñLâ¿?}q"Ì Ö¶Oޚè÷n ׅþøÆìŒoªì=¿[=k÷èev·½¾Üê÷˜Óqðö‘éÿ…Ómoãr[á`r³þOü=ë'íû>m„4m³mt˜Ëj™¯ºÆïYÅVÂÌú¶`Æ(Ž?(߉&žù¡³©À³þºø•¿nâÁÇÁûŒendstream +endobj +247 0 obj +573 +endobj +248 0 obj<>>>>>endobj +249 0 obj<>stream +xÚµUÛnÓ@}ÏW }JÚÆ‰“4n(}HC• j„©ªµ=Ž—Ú^³»&Ä¿3k;ܤ$”§ë™3sœ/ ºô³ÁéA~Ò8s#°pCò Ç‚4Ϭc˜ˆTi–jÕr?—Qƒ2ª}ÔµU”eÃ%Kx:+ƒ`ÛUPoXãüª¤,A*bdôò,Cé3…0ç:‚< P*_H È«çˆ)̅ L›{îˋëÛɛËkw|éîš~ÔÅî[=ӅÜcwà ¨}kÚZ†<¥Â¡ #„Éû«kà©F2!æždrI®45Ÿñ´ÄÄÒ5ÊZÏLRÉo›©u[Kë6\U¥%Gî"#d˜æ J¦9aÞàH‘kaŠ_QB&”â^Œ P€˜—óP>øúw´ ðŀ¾H2£´îí¯ß_m™&y.|ê›ê¢ñÎ5NDb‚À‹…·„ÇÉp¦1^Ž2?ZíûiY® #SN®Ý+Š™I—dvéÔÈô£öX“ê¾<€Î>¸W %[À~gWn2`™ÁôŽŒŸ'+j +´ ÂAå<³Ft=>pý#ºþ?cψ@‰\úf-VôåšÇü;–œš}™Bª¸;:¿0Oýòh×*_r:³Y‘­ÎÄC³qzÓ$F6‹Ú‘2˜I‘g B •h,ZìÚKg¿Îé>Lbd¥bŠ|`Òpé!5$Ùb©˲îeÖÙ®=ÍÝN›N¡{žÑC"œ6‹$Þ,-¿y>uo¦­iËd¬´´>ƒ2ˆßPiR{~{ñüÕùÉÃh¶Mþq]È«܏X:Cõ£âÑcÿlð–±DʓMV¶ÆxÙÝ#ŒUu òéƒ`7Anm§bÄlÚ´i†º>é»G_°¿ïRéú¸¢mÛTpx4*%Q|ùé!ä³¼Ô¼f)›ڀ«˜:nÛ‡²ÚN¯»õqà ÈTølÇÎÝÆÛÆ/¡ûîendstream +endobj +250 0 obj +746 +endobj +251 0 obj<>>>>>endobj +252 0 obj<>stream +xڕV]oÓ0}ﯸÊ$MÚª[ 1Hƒx`¹ÉMkæÚÅv ´ÿ坮´Y˜èª&±ï÷9>ÙÏ^)ýe0»o¾êÏzý7ÈF0+ig|š%˜Î“ ÝLíÀ£Ù`“›x8IÆw6 ƒ·²@i™åJÛÑÎv0NFÎö¥«a.T~me.”Áæ70×,¿FkÀ,™ÍqÁ%ÔÜ.Á.Ô%— oEOH¬Ap‰ ÌÈÀ‡%K ¥BÕÆA©³ahÅX¦­‹°ç ¬´¨}†™É¸Â`Ö´nš$Tí® +²ó ׂžŠýÀÙCMÎÕnke64¦95ÊD“ÒÏïi` +7?‚(øñýÞFM“S÷ ädŸAÿÞ)µvñ7LÃqÿÀðЯ܊t —ZQ£†æ§ædÃD…ô¤ÕŠ ´ +&“I’$mLJ’Q@ W8<‡ô 8<ƒ,MýÝãÇWG-ëv“…ún—ÜP«£³®}f;öoVn÷ùû7 Ò ƞD‹+ÅÀ¿¨PшPtWêÍ]xI¿Ž;Q½ä£;·™Ì@B$9GB•ܱ)2tòeÎË=AGwA=‘åKˆrFµ…j +,Y%ln­‹V! AÄ´f7_ù·*mL\<˜Î^Î.¾¿}ýîžÞƒÊø=„œûÌ5²ëöVÓYwb©(µ\üoäÛ}¡Û#Gº9Liæº[æ* ^;õ†€«•.hâ8 ižÚ<¹:òñq+„ÔG€œ<äs´5¢cGYÉ|+·I²UÐ1'/L/ª@a"Ԛiº]¢á&iéù~“9|D[i Ÿ½ t¶z¹ ÙÔk*­UEéÑ>î•dW5T^J£°u‘3lÓ¨vdkðü'H…ÄpㆎL®ä†^-ÔçA]¨J´^ÑR¡jY3‚Šôïjå®|µÖjƒ@¿ ÍV°FM*°b2ï>>>>>endobj +255 0 obj<>stream +xÚí“ÁOƒ0ÅïüßQEZØ*p3΁gRYQ PüÖiøïmÇt ,fޅKï×Çû}·(8ú¦à3p—P¶Ömn]¥!0ò +¨Ø–¾ùæâ2Y©OŽr”»çFÀZô¤ÛËüMƒ  Ô€Ä÷lˆËB›6Ûµ-Çd+”m¯GÀ;Ô mó-Z[œyMcE¨?\ k5Lìö⃍Öiæ½£yw䋂E±,w­èWµìH‚(q.s£§Žk+¢$YaÝ)ÂIZëÙ̔ÞL©|\Š;/æ;+rÓ4ÓI's—²“Ð{åOè{^¾Ö“ô¡¨Sv/$¶Jã&×܊.;>>>>>endobj +258 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 +259 0 obj +135 +endobj +260 0 obj<>>>/Annots 106 0 R>>endobj +261 0 obj<>stream +xÚ՛MsÛ6†ïþ<¶‡2Ä óQgzh’ÆjîŠB;êXbBIÉøßw]€Fr3ìÌØ‚W|,¾Ä¾ b™ïW¬éàkވ¾Ùì®^­®^\›†wÍê¶aÊ4ý ›Õ—ßVëÏ÷c3Ý6¯§ýqÜ¿¯þ»úsuÕµì7f¿}|kM/T«›]£[N¯ï›Ë>{û|×¼¸V cö¯ÙÃzx+ü5Ö<ŠÈ]ã~$|Œåf3}-ˆ+€Ã/Úê¿Ø£ç 'qÞöp⊷Štâ/®%É×±ç"VÇ6£dÙÁ±Ìj#)N¨¿¾ÀUßÞn7ëãvÚ[¨àˆŠt-iיV.Ú¹¨UŒu­DÅxI1âè„I8ö¤›‡ÃqÜe&r8älùˆ~*»¸§½ÿ1Î?¶ãO‹“¬5U_P\™Ô$ÅqWf€±S\÷ÖÙùœ€(N¨7Óæ´ƒiú8/FPJP7ú71‘ÃïžXv–µ]՛ÅvñõâÁdÕС=ò¼Éz˜20š‹zÊÇñvœÇýftAšv¨ÜkEaÒª>X,.Y¬Rú"/Z¬'jŠ%D +éõ¿n2—$ Wuö¢Ä,ŠËgÂbÖ}ÿ´—¥¤ºÁœqY…KS§uɜ=Gwà* ‡ÂDzü:αÃá֛­'0Š̋í3€W‘"ol€ïdîõ%«`.ÅEÁ(Å5ä~¨c\oaùø(&:t×'wÌ¡°ý½Þ¯ïF+·[ƒ˜¶Êµ*L÷N ·ºIéM¦“h²¢l2D„Â%S"…‰ôf;›ã4?<΋vòVûHqÞçÓæxšÝB[XûyúËQP_š.X<‚ÙHÃÐBEÑld—_ÀnÈuVøGq½;í>s(èl6•¤—*8,"Ô(x©&yŽÝ ”)ˆâ„z;îÇy]³Å–<²X7ˆ}Qk’çÀíÓ‡ÂDZ‡#Í(!ªÜ¼, ƌ[ ãi¹A$ïP®bE"ŠîmAŠ)Fyaµb±.[¸¡vW'‰ƒ åˆjz½Ìu‚S^¤8 +çíýt8¬ç'›iYííHVèìðzi*'.Õ®©{õ2[OfŸXð~ö¹°'­Æyç +1¯³—¥ë©)æN«O›b¼§¾ÓËl=‡Ú™l1 ˆâµ™§ýŠ&em‹G–ïhqM(fW8¸”¯’šQ¯²ùʬÎpöœ×Ó¨™ýŒ!‚ÙÛê3ÆåÒ"û~ÚÎãÒ"èU[ÏÖ+tf8§~˜:8¸˜êœ:O¯ +©.¢kp'D +¿¸mŽ·Ä,6n /´hÛ´­iã4£?ÜÀ)1ìB»&ƝßÀaL-(P=§{t0nšu)Šâ{·Þ-ë¡VØE‰ºÎY!ž…Du }ÐJÄK‰õv1 (ÎÒ' ¢þêS)UJ`¦±­æ’ ¡à0¾Y(7b¡{ϕP(Œ]¾ÓÞmîjy^â\+™ŸIl .š½Ø83ɶ¼ZÅdó$L¶Eq‚U—l%‰zìSáYôQ›ÊJÔ3_x1Ù< “-AQœ=ú0Ó%›,$›üÂXÐ J6©½[‹RºÇØ-¨„Caߎ_§/¸3ÕWøèMq6 ¬ÑlÊ[·('‘(ábÅ öìŽc¯ ςG­.+_*¦q(ÝbÅùsK¶Ž:e.%º¨­e“­ÓÞ­e)وcl77áP˜HŸÖóÖ>} ÛxY[º1•ŸJFë62qn£¼qËbª3-æ`”HÕåYAÍÂ:[³d™­¹÷mYL3Â`–ÅŒòô‘±²¬ðÜF¯ý~…À×ÑSÓÆû³*¤A´]>Ç fõð s‹«JŸ"-Í!¥‚U»×a)J/UL/‚`zÅŒ>Ëä’,¬«%K–Õ’{ŸVÅä" &WÌÁ(‘žQrqm®èäyn¼#÷¥ ímÝ$ fyN¯Ú{³Þ~°pŠÝò„4m3)æÌ‚v‚ÝãÒé3^áá¬æÃýzéa¯ýv/¶$ä?Wÿýž¡endstream +endobj +262 0 obj +1953 +endobj +263 0 obj<>>>/Annots 134 0 R>>endobj +264 0 obj<>stream +xÚ՗ÁŽ›0†ï<…í!Ä66¶¯›6=µÚnèÐ]¥ +¡%DUß¾c{L¤Äí)Éî +ivàƒù=ÿ~eŒPøe¤(íßk›=UÙ|i§¤Z& )• ÕÛ»ªþ¾kH·&‹n?4ûáð¾ú‘}¬2šS س‡—ODñœ’²¹&-1:/1ؑ•¥Ÿ]ÐoÈ|)cö~ŠÃ¹%œ 7|ʘ‘‹w‰À-a…8Ýoƒy„}©Ûí~caE‘+¨þ—ßð‡• ù8‡Çò¹ë²ñb”ˆ§$B+Ë\LQ˜G؇îõØÂÂÖöÛ[&\p#¥®¨ +êPµ´DмÀK‚.ͅWG]Ö&º´%Zs|:»úph\Ç ¿yûüw?Ic;ûÉc?I£ öŠ%-HÞræöh–“º€cÈ‘D:´TÒpã 7a^<˜Ýdiܔu¦ðÁh7©h˜×:a·ÀQSŽOì0‡¡Æ-Fð»3S‰N’å8¼}u’Taxë´Ù„f‹Q˜GØÝ™-%‘(ÜäõU¸ ’Hˆ0ÁuÚnHB»Å(Ì#ìž §†+¨›±Þ.ˆ ç¶ §ŽI9ÊvɄƒi$-º·Æ’àåÀÜáæö/ýÄT4¼]õÃe҆CvS ¼~œ^òÊÐb|÷A¤ ùI›¤ÓÄ¸m› +ó[ v®Ÿ˜¹›~búbqqS„Â:úK›/%~œØ³4¾^–*"€%è2Áa9«n=ü®û抏G¬¡}ٚà0¸ªïŽö+íò:Ž»©ðSåa}q/ÍÏ®®”'õùÓÁ #mÙõ­2òf-ÁŒ}€±zúÕ¸Æ3k.˜ßUߞWö{w½Ý{çuò¹ÞכÆzŸ<ïjçý +¦¸«k»EÁ¾fˆvrendstream +endobj +265 0 obj +700 +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<>1<>2<>4<>]>>>>endobj +xref +0 322 +0000000000 65535 f +0000000015 00000 n +0000000227 00000 n +0000001784 00000 n +0000001858 00000 n +0000001936 00000 n +0000002013 00000 n +0000002092 00000 n +0000002168 00000 n +0000002249 00000 n +0000002307 00000 n +0000002410 00000 n +0000002514 00000 n +0000002619 00000 n +0000002724 00000 n +0000002829 00000 n +0000002934 00000 n +0000003039 00000 n +0000003144 00000 n +0000003249 00000 n +0000003354 00000 n +0000003457 00000 n +0000003561 00000 n +0000003666 00000 n +0000003771 00000 n +0000003876 00000 n +0000003981 00000 n +0000004086 00000 n +0000004191 00000 n +0000004294 00000 n +0000004398 00000 n +0000004503 00000 n +0000004608 00000 n +0000004713 00000 n +0000004818 00000 n +0000004923 00000 n +0000005028 00000 n +0000005133 00000 n +0000005238 00000 n +0000005343 00000 n +0000005448 00000 n +0000005551 00000 n +0000005655 00000 n +0000005760 00000 n +0000005865 00000 n +0000005970 00000 n +0000006075 00000 n +0000006180 00000 n +0000006285 00000 n +0000006390 00000 n +0000006495 00000 n +0000006600 00000 n +0000006705 00000 n +0000006808 00000 n +0000006912 00000 n +0000007017 00000 n +0000007122 00000 n +0000007227 00000 n +0000007332 00000 n +0000007437 00000 n +0000007542 00000 n +0000007647 00000 n +0000007752 00000 n +0000007857 00000 n +0000007962 00000 n +0000008065 00000 n +0000008169 00000 n +0000008274 00000 n +0000008379 00000 n +0000008484 00000 n +0000008589 00000 n +0000008692 00000 n +0000008796 00000 n +0000008901 00000 n +0000009006 00000 n +0000009111 00000 n +0000009216 00000 n +0000009321 00000 n +0000009426 00000 n +0000009531 00000 n +0000009636 00000 n +0000009741 00000 n +0000009846 00000 n +0000009951 00000 n +0000010056 00000 n +0000010161 00000 n +0000010266 00000 n +0000010371 00000 n +0000010476 00000 n +0000010581 00000 n +0000010686 00000 n +0000010791 00000 n +0000010896 00000 n +0000011001 00000 n +0000011106 00000 n +0000011211 00000 n +0000011316 00000 n +0000011421 00000 n +0000011526 00000 n +0000011631 00000 n +0000011736 00000 n +0000011841 00000 n +0000011946 00000 n +0000012050 00000 n +0000012154 00000 n +0000012258 00000 n +0000012362 00000 n +0000013058 00000 n +0000013164 00000 n +0000013270 00000 n +0000013376 00000 n +0000013482 00000 n +0000013586 00000 n +0000013691 00000 n +0000013797 00000 n +0000013903 00000 n +0000014009 00000 n +0000014115 00000 n +0000014219 00000 n +0000014324 00000 n +0000014430 00000 n +0000014536 00000 n +0000014642 00000 n +0000014748 00000 n +0000014852 00000 n +0000014957 00000 n +0000015063 00000 n +0000015169 00000 n +0000015275 00000 n +0000015381 00000 n +0000015485 00000 n +0000015589 00000 n +0000015694 00000 n +0000015800 00000 n +0000015906 00000 n +0000016140 00000 n +0000016174 00000 n +0000016208 00000 n +0000016961 00000 n +0000017010 00000 n +0000017059 00000 n +0000017108 00000 n +0000017157 00000 n +0000017206 00000 n +0000017255 00000 n +0000017304 00000 n +0000017353 00000 n +0000017402 00000 n +0000017451 00000 n +0000017500 00000 n +0000017549 00000 n +0000017598 00000 n +0000017647 00000 n +0000017696 00000 n +0000017745 00000 n +0000017794 00000 n +0000017843 00000 n +0000017892 00000 n +0000017941 00000 n +0000017990 00000 n +0000018039 00000 n +0000018088 00000 n +0000018137 00000 n +0000018186 00000 n +0000018235 00000 n +0000018284 00000 n +0000018333 00000 n +0000018382 00000 n +0000018431 00000 n +0000018480 00000 n +0000018529 00000 n +0000018578 00000 n +0000018627 00000 n +0000018676 00000 n +0000018725 00000 n +0000018774 00000 n +0000018823 00000 n +0000018872 00000 n +0000018921 00000 n +0000018970 00000 n +0000019019 00000 n +0000019068 00000 n +0000019117 00000 n +0000019166 00000 n +0000019215 00000 n +0000019264 00000 n +0000019313 00000 n +0000019362 00000 n +0000019411 00000 n +0000019460 00000 n +0000019509 00000 n +0000019558 00000 n +0000019607 00000 n +0000019656 00000 n +0000019917 00000 n +0000020048 00000 n +0000020307 00000 n +0000020328 00000 n +0000020423 00000 n +0000020525 00000 n +0000020545 00000 n +0000020685 00000 n +0000021624 00000 n +0000021645 00000 n +0000021758 00000 n +0000021946 00000 n +0000021967 00000 n +0000022107 00000 n +0000022719 00000 n +0000022740 00000 n +0000022853 00000 n +0000023046 00000 n +0000023067 00000 n +0000023198 00000 n +0000023813 00000 n +0000023834 00000 n +0000023947 00000 n +0000024136 00000 n +0000024157 00000 n +0000024288 00000 n +0000025229 00000 n +0000025250 00000 n +0000025381 00000 n +0000025666 00000 n +0000025687 00000 n +0000025827 00000 n +0000026746 00000 n +0000026767 00000 n +0000026898 00000 n +0000027254 00000 n +0000027275 00000 n +0000027415 00000 n +0000027909 00000 n +0000027930 00000 n +0000028061 00000 n +0000028513 00000 n +0000028534 00000 n +0000028674 00000 n +0000029811 00000 n +0000029833 00000 n +0000029973 00000 n +0000030865 00000 n +0000030886 00000 n +0000031026 00000 n +0000031946 00000 n +0000031967 00000 n +0000032107 00000 n +0000032751 00000 n +0000032772 00000 n +0000032912 00000 n +0000033729 00000 n +0000033750 00000 n +0000033890 00000 n +0000034818 00000 n +0000034839 00000 n +0000034979 00000 n +0000035381 00000 n +0000035402 00000 n +0000035515 00000 n +0000035721 00000 n +0000035742 00000 n +0000035897 00000 n +0000037921 00000 n +0000037943 00000 n +0000038098 00000 n +0000038869 00000 n +0000038890 00000 n +0000038945 00000 n +0000039050 00000 n +0000039194 00000 n +0000039300 00000 n +0000039420 00000 n +0000039529 00000 n +0000039678 00000 n +0000039788 00000 n +0000039895 00000 n +0000040049 00000 n +0000040160 00000 n +0000040277 00000 n +0000040393 00000 n +0000040557 00000 n +0000040663 00000 n +0000040782 00000 n +0000040897 00000 n +0000041001 00000 n +0000041157 00000 n +0000041266 00000 n +0000041381 00000 n +0000041493 00000 n +0000041592 00000 n +0000041739 00000 n +0000041836 00000 n +0000041936 00000 n +0000042094 00000 n +0000042234 00000 n +0000042334 00000 n +0000042441 00000 n +0000042591 00000 n +0000042691 00000 n +0000042798 00000 n +0000042946 00000 n +0000043046 00000 n +0000043153 00000 n +0000043303 00000 n +0000043403 00000 n +0000043510 00000 n +0000043656 00000 n +0000043756 00000 n +0000043863 00000 n +0000044014 00000 n +0000044114 00000 n +0000044221 00000 n +0000044369 00000 n +0000044469 00000 n +0000044576 00000 n +0000044726 00000 n +0000044826 00000 n +0000044933 00000 n +0000045065 00000 n +0000045172 00000 n +0000045271 00000 n +0000045389 00000 n +trailer +<> +startxref +45617 +%%EOF diff --git a/doc/cmp.shtml b/doc/cmp.shtml new file mode 100644 index 0000000000..7ab49b83cc --- /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 +
  • RFC 1179, Line Printer Daemon Protocol +
  • RFC 2565, IPP/1.0: Encoding and Transport +
  • RFC 2566, IPP/1.0: Model and Semantics +
  • RFC 2639, IPP/1.0: Implementers Guide +
+ +

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 679 1999-09-22 20:06:27Z mike $" tag: + +
    +
    +/*
    + * "$Id: cmp.shtml 679 1999-09-22 20:06:27Z 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 679 1999-09-22 20:06:27Z 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 679 1999-09-22 20:06:27Z 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..6f9bd0fd0b --- /dev/null +++ b/doc/documentation.html @@ -0,0 +1,72 @@ + + + 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 ) + +
  • Software Programmers 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 ) + +
+ +
+ +

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..8a7cf49329 --- /dev/null +++ b/doc/idd.html @@ -0,0 +1,901 @@ + + + +CUPS Interface Design Description + + + + + + + +

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 + +
+GIF89a¯ÿòÌÌ̙™™fff333ÿÿÿÿÿÿÿÿÿ!ù,¯ÿBþXºÜþ0ÊI«½8ëÍ»ÿ`(Ždižhª2€0p,Ïtmßx®ï + + +;±Ýíˆndý !¸ ž³wà…MƒƒY~¿{,gÚ\‚äé +Œ×Ø(tÙî!Ï=Ñ.ûz¯áџ:ì;Ã9qöíÉë]/¿ºÉ¤Et/†'Îþt9Àؖž_ÙÇ\|W•wArö¸Ý2Ô× +tN°0Tï}¡û‰$!‚yMxî)ˆš‰Ôø@nB°U½ÊwE„§!ŠF H L8B +c‰;ždŠ-æDVWdг€h±äړP¶%#(4Fiå•Ï\hŠ:Re!\ÒėX^¦%€¥À-$E€Ö/úHŽšlââöÌQX + + +¸1Nô¯b"œŠüjåÁÂE0…È8ö5GkZ|ÒÁwt„C»ÔQSÇo6Ôِ[W„$²*Ž+4Pb-8¹P1þ'8"‘ФÄ$ Cyê‘„)>ãŠtè`Ð3‡‹¾z"«rE'Âqfä°Ë +‘qÂ\|€„Ž¡ôö»%É(.—bڽȀíÉ`{¬EÇ1w’ »[Hß`(B6ö“  +†')ÊRŽÎa[ÃrbC!T尌 +2Q·ÈHZê#–®üË/àô¯FÝê(Û²% ºXË9öÀbÁ4f.ù-oý™XËB…IÎÒ7¹*@ÃӎÍT€hà‘ÌW␙Ã$f:µyžn†ó†r„'téKv` +Ç+dª– œ79sò|'=×¢Ìx¶òœÿ„¦œˆeÎ;*à$þ” IÝÆaÏ{–3ŽÅÁ +P“ÍS[ÙL¨3©òQ7éÆò#ãûô0F×ðsE°t§@‘ØQÜ´´ ©:3ÓRíd ¥*MITnŒ£¨H]ØQÁd +@òþ—¬rMœŽaO + +rë^yÀ·(¸îéêû$uDòrã/a,I.°ÙUÀœb hˆ`¾B ë" +Ü`HØxȸo1þ[á\8f^æ|\ý‚¢¢zø0(ˆ\ {ƒÄgäÞõ€çâ§Á˜0*\³n¼‹m¶/Äeª±ÿ†ì +Ç,½DN2€œº+ùÉ|í0L¡Le*ð¸Ã>­2ëf,eIPOËÅàr—±”80SAŸcFªatç»ãy¤¸ršçÌ¡5ïoõËsžï|¿8˙Φ¬þ,ï¼èà)ÁÌ;øk¡—†dDpÑòø2¢qfHã!˓~ٟ-í +'g:,æ4y?ýäP‹Z›ž#ÏÕ´Î5AK‰k]ûš›ÒKõ¯‡më€õzØÈƫ؎Ý>B{PЪ.6hf]º?©ÌIŽuO„íM‚ÌÇÜcµ3˜ +61‹NÒ[†W£ ¦m¿­{ÂPâvζKnUˆ[ ònĽ±÷n?l:Áž3ušë¬sP[ÿnn¾çP…WõÔFj[Â÷ +¹vÏ™à‰˜xú'ˆ£ÀÀ†p¸4.êãKÇ¿ÂÁ±o§¢ü"Á|Nk`îʘ + + +jl©ÌuˆËi™0pmC´«+‰÷6¤2­éÏe`(ŽJ]¥iõð3ƒØí"p|ª!:qøFس 6£ +@­,þŠqüぐoÌÇ®žÖüV“¶QǛEvî¹²É8ÙªS"æÀç‡x± àþ‡>—Iãg +ïÝ>Y‰çN80æ§ ±¾GLLìÕµ…(1Þ¼!8}þ¬“*…ª‰Ùì:e»´œ +ª¿ên_6ÂÃSÀ`eG;Ö„CƒCcˆ¿‡4¸yeî¯Í)oøByRm½0?íLîÅ`QÿjÓÙ/ºôÓN|Ý + + +þÙAÜŒÁ¸D5©D aævx ?жx°DM@•!h‰àȀާ® +• á×B`ð¤ªE?›“”Þdƒ"8$Ý`Ki0…OðƒnΓ±µvtžè€I([,¹Ndɨh\'6X +P㗊‰Éøt ¢‘¥˜¬è €ˆ†Ky™FˆŒë`š”yƒ„¨š €š‰ƒM©‡øFQhY„ +9¶X¯×–í4š¤™Y\)"¹AN]‰xéz÷Gq07)©ñ™•Y€r°ŒŽi‹ z ™ÇäFÍÉT–ù› +ËŽC œwI›üX]‹¹\ëY]þf lïYbj8ŸÈuœbŸÍÅtú©fÞןfBI—“*øé:ÛØUj Ò +ˆõ¹ Õp $(~ ¡Ú ¡gù{îpZI?¡ƒîÀv:“a¦˜6¢§Ô]Ý‘(ªê)!ŸÚ¢: +jwµ¡4ÚvíHÛǘ9ºXhó•üù£¥Á¢VÉ{Dº2š‰(°¤3š¤a÷ +У¥“p¢þò4Vº—  +E´¥è¤k°7ºhT*€¿èw`ڞiÄ …S¦Ʀmê Nêƒ#ú¢f€ xê†ý +8z©7uÚp{Ú=~]7`«h‡ÚsÚg:…zd˜ó§ÎA-vþAñr¦'–AÚ)9–š¢âSi;£…š 1ªo"ª +¦J;“º rº8Ui|é>¡Úœú + +“ë¥Dfný2»ƒ–0j«®»ºK;zë¢Íö»—!µ—S»³r>K+6ˆ‹¨XÒ»; CÈ +8Ê;¢»ÃÛ/Œ‹¥ž!¬s½VR½óõϋOâ[/çK¨þ˜Ñ:͋\Ý+ Sc:ï˞’º¶ë9Æ» + +ô 8ly$ +8©ÙÅmX2Ùh>—?¯!šHüÁ^LsP,Ÿ«Y‹âá¿ÿtšì‚£Y +r¦Éš¥9ÇjžÄ8-ÆÇŒ¶iêPÂbA˜ù‰Ã¸š»³7RœCWRoìŠå MŒŠ”åt™ Œ›réÉq + + +å>}Lê}ÎǨ 5:àŒ|"þÇwÐsøæNΰ¹#R>~-N‰®èƒ ßcðÞÚÎÑ¥®åGÎâ툉Ýè*‚¸ +=‚ž ºëⅭëÀ>Û·žën^žmèÊëð¼ã>å×Λ«}êØ÷ +“Œ¬ËIÁ·AÔNÍëv>]t.âÚLЫþíï¾ñnäÖÜæs¹¿±â°+† +¬UØïî•.ç¬ÎìÍ.è´ÞŠG=ðù‚§ž¯”ë^äÛ®êh-‹êê!i!ÕvMíiªîþ¾òîá/þÑ-OÖGð,oñº!å’gOâ POìOôBþÈàhâ+?ï>ßÊVHÀsaõ™€õ$óSîõ—»ó8.žß¹ +~áßÈ©ö»]ò3ëÆt_÷[ïôb¯ç‚Ü÷Õ«@u™ð;zܘ‘Ü@óŽ2’?ùƒ¸ÙlùF ¶™¯ù›N ž0œú£¶¤ÿ0#9:ß§½ž©Ÿ\#ÃÙæó2é+û‚ÀÓ¸_äM/ÓtaÚý3”]Ù«¿¸iîaF>ª}ŒØvÍïMÍ÷Ðëä©îr܌öqñ_ÀüªrâF®ò +ýþ¸—hT_ã4sx”ýÝî)ç.QgûàŸÏ%ì‹}i´ASû|þð@QÜ +$J9€»-̱÷ÜôMؑhZ˜¦:°œ*ÏlßxÒ|ϼ¡ÅLÀ ¬Áfù9BÑdìÁ|«VV„¢“énKv + + +kB_ƒg 3ʳ8#Þ¬L=0;J¤äÈ@¤F|'i~±© žaʊÆg;d*3²”©bPÏ¢TäHô¦?[† +ÄäƒhN6ZM¢D:c*BR!$±ckƒ’V­-uÛ@[øp„Ÿ]¼8ö-1{TήWÏ2ñ Šp=¸q«Ñ½es.‰„4+#Ëe¦¥W5µekxr䛓/X͚5Iǃ=kÝúµì˰ûN–2qÅ¦yZ£QŽ›ÇޝtxŠäcK—Ííɹ +iþ¡9¼m1oñ¢©/²8îìSté4l’Wm¾9óéÖÛÐãã{{üzÞ¿çøêöÞzà}œàL¨ "˜ +ÄÐsà¶PGLUúå`MÞ  ¡†9¬§Û{pX¸¡wÚw߇¡¨ ‰í "MUXNx + ++l´á¦ +j²F:Á.êÆÛj¤³Búî ¼Ê«/£Ö’[н#í+ð¥ænJÞ¸«æ;ð©õ‹¨ _ËðĊһ*º? +ƒÂwœÃyzh±°Øzl2,#oZ2țr|ò˂°¼$Ç)ë +óÍÙÔ,éfs€1Î@/øîÏPõÌiÐH·ðÃBkLtÒP¯bôS;NÝWÔXÏ +ó’dlÍtÖ`°tžOc óÅa§}Aě²1vËjÇmþu+`ÍÍÁ·qwü6˜‚ì½sÞXŸ¨Ë$xM6àP³-iÉSÚ½Aوïë84–ø=xä8^!ä*L>ޘƒk¹Œ({Iè^!ḘN$ê +«®ç!ºû‚ÿÝ ë¯ßoî—Oü¨¾ÿî9í]ñÞ{ñÙÊ®ãlhŽ(èÌÃê¼~ÔS¢|ö՟zýw¬Ë§|øÝ—*½ŒÈ×­|úåwzþæ“)Nrû¾Ê?*ô¥ +¿*÷ô7ú½~Múúú÷ª÷Ɉ•S3x*ûíP”ùH£°°àó(è¾í-Jƒú™ +åAF{#\”g…Áœ)!),Ô #ÓÂǼjþ1œŒþh©²K„9$ƒYè)Ž ˆA È +—‡)#1‰Óp"˜ð'Ã%n‰P´‡Ù¨-‹1³¢^\%ƈÔp„CLÖ5à + +
+

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
  • +
  • RFC 1179, Line Printer Daemon Protocol
  • +
  • RFC 2565, IPP/1.0: Encoding and Transport
  • +
  • RFC 2566, IPP/1.0: Model and Semantics
  • +
  • RFC 2639, IPP/1.0: Implementers Guide
  • +
+

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>
Surrounds a class definition.
<DefaultClass name> +
</Class>
Surrounds a class definition for the default +destination.
AcceptingSpecifies whether the class is accepting new +jobs. May be the names "Yes" or "No".
InfoA textual description of the class.
LocationA textual location of the class.
MoreInfoA URL pointing to additional information on +the class.
PrinterSpecifies a printer that is a member of the +class.
+
+

+

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
AccessLoglogs/access_logSpecifies the +location of the access log file.
Allow-Allows connections from the specified +host, network, or domain.
AuthClass-Specifies what level of +authentication is required; may be either "User", "System", or "Group".
AuthTypeNoneSpecifies the type of +authentication to perform; may be either "None" or "Basic".
BrowseAddress255.255.255.255Specifies a +broadcast address to send CUPS browsing packets to.
BrowseInterval30Specifies the number of +seconds between browsing updates.
BrowsePort631Specifies the UDP port number to +use for browse packets.
BrowseTimeout300Specifies the number of +seconds to wait until remote destinations are removed from the local +destination list.
BrowsingOnSpecifies whether or not printer +and class browsing is enabled; can be "On" or "Off".
DefaultCharsetiso-8859-1Specifies the default +character set.
DefaultLanguagecurrent localeSpecifies the +default language.
Deny-Refuses connections from the specified +host, network, or domain.
DocumentRoot/usr/share/cups/docSpecifies the +document data root directory.
ErrorLoglogs/error_logSpecifies the error log +file location.
Grouproot, sys, systemSpecifies the group +name or ID that is used when running external programs.
HostNameLookupsOffSpecifies whether or not to +perform reverse IP address lookups to get the actual hostname; may be +"On" or "Off". Hostname lookups can significantly degrade the +performance of the CUPS server if one or more DNS servers is not +functioning properly.
ImplicitClassesOnSpecifies whether or not to +automatically create printer classes when more than one printer or +class of the same name is detected on the network; may be "On" or +"Off".
KeepAliveOnSpecifies whether or not to use +the HTTP Keep-Alive feature; may be "On" or "Off".
KeepAliveTimeout30Specifies the amount of +time to keep the HTTP connection alive before closing it.
<Location path> +
</Location>
-Specifies a location to restrict +access to.
LogLevelinfoControls the amount of +information that is logged in the error log file. Can be one of +"debug", "info", "warn", "error", or "none", in decreasing order or +verbosity.
MaxClients100Specifies the maximum number of +simultaneous active clients. This value is internally limited to 1/3 +of the total number of availabel file descriptors.
MaxLogSize0Specifies the maximum size of the +access, error, and page log files in bytes. If set to 0 then no +maximum size is set. Log files are rotated automatically when this +size is exceeded.
MaxRequestSize0Specifies the maximum size of +HTTP requests in bytes. If set to 0 then there is no maximum.
OrderAllow,DenySpecifies the order of Allow +and Deny directive processing; can be "Deny,Allow" to implicitly deny +hosts unless they are allowed by an Allow line, or "Allow,Deny" to +implicitly allow hosts unless they are denied by a Deny line.
PageLoglogs/page_logSpecifies the location of +the page log file.
Port631Specifies a port number to listen to +for HTTP connections.
RIPCache8mSpecifies the size of the memory +cache in bytes that is used by RIP filters.
ServerAdminroot@ServerNameSpecifies the +person to contact with problems.
ServerNamehostnameSpecifies the hostname that +is supplied to HTTP clients. This is also used to determine the +default CUPS server for the CUPS IPP client applications.
ServerRoot/var/cupsSpecifies the root +directory for server data files.
SystemGrouproot, sys, systemSpecifies the +group name used for System class authentication.
TempDir/var/tmpSpecifies the temporary +directory to use.
Timeout300The timeout in seconds before +client connections are closed in the middle of a request.
UserlpSpecifies the user that is used when +running external programs.
+
+

+

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
AcceptingSpecifies whether the printer is accepting +new jobs. May be the names "Yes" or "No".
<DefaultPrinter name> +
</Printer>
Surrounds the printer definition for a default +destination.
DeviceURISpecifies the device-uri attribute for the +printer.
InfoA textual description of the printer.
LocationA textual location of the printer.
MoreInfoA URL pointing to additional information on +the printer.
<Printer name> +
</Printer>
Surrounds the printer definition.
StateSpecifies the initial state of the printer; can +be "Idle" or "Stopped".
+
+

+

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. The URI method name is "socket".

+

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 Internet Printing Protocol

+

The Internet Printing Protocol is described by the following RFCs:

+ +

The URI method name for IPP is "ipp".

+

CUPS defines the following extension operations to IPP.

+

4.6.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.6.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.6.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.6.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.6.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.6.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.6.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.6.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.6.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.6.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.7 Line Printer Daemon Protocol

+

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

+

The URI method name for LPD is "lpd".

+

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

+

The URI method name for SMB is "smb".

+

5 5 - Directories

+
+
/usr/bin
+
The cancel, lp, lpq, +lpr, lprm, and lpstat commands reside +here.
+
/usr/sbin
+
The accept, cupsd, lpadmin, +lpc, and reject commands reside 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..bf1a445ad8 --- /dev/null +++ b/doc/idd.pdf @@ -0,0 +1,1517 @@ +%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[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 +]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[100 0 R +102 0 R +104 0 R +106 0 R +108 0 R +110 0 R +112 0 R +114 0 R +116 0 R +118 0 R +120 0 R +122 0 R +124 0 R +126 0 R +128 0 R +130 0 R +132 0 R +134 0 R +136 0 R +138 0 R +140 0 R +142 0 R +144 0 R +146 0 R +]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[149 0 R +151 0 R +153 0 R +155 0 R +157 0 R +159 0 R +]endobj +161 0 obj<>endobj +162 0 obj<>endobj +163 0 obj[162 0 R +]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<>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[164 0 R +165 0 R +166 0 R +167 0 R +168 0 R +169 0 R +170 0 R +171 0 R +172 0 R +173 0 R +174 0 R +175 0 R +176 0 R +177 0 R +178 0 R +179 0 R +180 0 R +181 0 R +182 0 R +183 0 R +184 0 R +185 0 R +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 +]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<>endobj +356 0 obj<>endobj +357 0 obj<>endobj +358 0 obj<>endobj +359 0 obj<>endobj +360 0 obj<>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<>stream +xÚMŒÍjÃ0Ãï~ +7¨½üãc·´[Úx§Ké’Öv7úö[C ÐOFH”DZ ûfm5d3@)‘!UÙâ¦ùø¬TS°nh;‹Òúñ0ÅèÜxã<½šãg Š0I-rpJ…ü£yU–œD‡œr¡Áeñ<ß´þ†fÂoë,j7÷×.øÇ0KEñïg>ßÜxø + ­_L¯°>°¥ÇÞzë~lэa;v“s=÷endstream +endobj +379 0 obj +186 +endobj +380 0 obj<>>>endobj +381 0 obj<>stream +xÚ+ä2T0BCc3JÎår +ár á +äHÉHendstream +endobj +382 0 obj +31 +endobj +383 0 obj<>>>>>endobj +384 0 obj<>stream +xÚ¥UßO"1~篘ܓ&²ÇޛŠõöÍ=ðRº]¨vwÖ¶ Çýõ7máÐ3š ‰Äίo¾ofxnÄТO ý6tzÀóÆÙ¤ñõòÚ-˜ddéõ»0Ibs,ÅáäÑ[ã~°6{qÔöö(†Q* ++3ə•X×.ÄqíÚîE>Õd! È +1. FÎ ÷ŵ,]$¤È«œrA©q)ÉBVˤ)dô2Ô9³æra ›ï<°"uAsÍrWŸªÆc±tð°0ÎìBÀ9æ9•»¿ý„D$YÌa¼6Vä0=ør~ŸŒ¿LáAhã`ÅQ+zE@· íMè÷¥ÐK)Vï0ð~헶”¨-›QÏåÆG±µÐ¾;m÷€„Ñ̍O`"YX0³ÇÁLGôR(ŠHa¶† fÖ0ÆÌ®˜„ӊ[†­ Æ«L§[Uå…r(˜R¡ ¢7Emœ{u+C FàøÜöæ¨û}𺝠ý$”X'jè¡©d!¶ƒb¢:ë†EŸŽR‡T#çW»%“º±ÈQ‘”£‹Ées”$$& î3fd*ÅæÎß·8ó-Às%** +$Ö^;×—/CB ™p:N®“áÜ]žÇqÿdzxc²ßÔ#z¦?‘ÛøæÌY]…Ó²Ó£ðsî¡Re’)ƒ{%MUºI ÑVÒ.@ ÒÉmCUp'SÒ®ß䇥©¢e…ú)tH˜fWƵìP$hìØ¯Þ¶§]¤=H’!­A“(;C€eX&û¬’) º*V–ª> ª"axßFLݓê\Uaxe,æò7Õ^֋ˆ\ÝÞÃÕb }zÀ+­iÁÕPÌ^{u£Vgz¸‡×‘À +¹¿$î¾ÜfÓûL¸!KÝNl:+°hîÐVÓjÞ;nŽÚÎÇ$9¢ž³ÂÓC!è‡;C¥på7Uøù0ßB1^k¨õ—zÓv¯£¡{ßܽø|‹rCÛ[Q”îD&HZØO…v(4ì0MÍèeé?•£K9.~ý_ŽcÊ1”šxC-?{J±W +iáõ:˜µ©ƒ½ÓP^÷êþ¿˜4~4þùºXµendstream +endobj +385 0 obj +836 +endobj +386 0 obj<>>>>>endobj +387 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS045×3S072PIÑp VðÌ+I-JKLNUpI-ÎLÏQÉE™%™ùyš!Y\º-ºP=F 13 ˜o¨œœ_ +u á +ä, ëendstream +endobj +388 0 obj +113 +endobj +389 0 obj<>>>>>endobj +390 0 obj<>stream +xÚ­•]“š0†ïýçҝ– êU·ãL¥‚{åM +AӁÄ&q¶þû&¬¶îL±;\€rò¼çã=ú£‡ÀÓ‚ȇaYÕû”öŸÇà{úMæ}Ö¤ ‚°ŒÈ‡ô{‚"â„Èõë Ál'0çÙ±"LaE9³á Ԅû¡[3Ó=‚—%£lg旁J­jßN öú«6fbÁYöG:‰3{ë‡\+÷‚3[År½‰Õ›qVÐÝQX½fxG â³k¾N mï—óù<9IE*X2ED3s"鎙[&èáwoºH$ӕ‘p¶"¼PoX˜æeT*] ÒÔrÄåüëZú‡¤¯n¡cÁwW•1ÁÝY'ë[è„dGAÕI›÷À…ºƒ›Æ·¸)‘÷Z$Ù¼3¿$ÿ3¶×ùm쫦oÿ5¹v»8çŽìûð¢öDœ—Xþã3Μ«%–`øÈ ^. @ÃQäƒv½.|¯k›h;Q¦L>Û~.p¡¶º¹ŒãÇzâÓ<§†ˆKx9œˆ•‘àhs)@Øëç™~ŒÆøB±™šFcRé é=P<ãeg¤ÿ> àœø‚e<7 À,‡T`&;{¿¡†ÔÏIY#RaÝáLvG†ÃñrYÊú×Öÿó‘æÄž5ggúã ±æÿAÁÈsÇZW¿šÏ‹´÷µ÷ dÃßÎendstream +endobj +391 0 obj +541 +endobj +392 0 obj<>>>>>endobj +393 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS045×3S072PIÑp VðÌ+I-JKLNUpI-ÎLÏQÉE™%™ùyš!Y\º-ºP=& 1#C ˜o¤”š–Z”š—œZ ’r á +äÍÃ"ïendstream +endobj +394 0 obj +118 +endobj +395 0 obj<>>>>>endobj +396 0 obj<>stream +xڝVßoÚ0~ç¯8±*•” +t{bU+!í§Jߐ&ã\Àkâd¶³Òýõ;Û!„´j·¨/nüÝwçïΟùÕ aD!Ì"Og½«ÞÅíD#X%´3M`ư”•d©_$Œ£>[ýtØpæ±ÃiD„p½cŠq‚¸é?0¬ðÑ4p쫯ñšð‰ÅCŒ‰ 2VBnaƒæQÂ|¸æ¢É ±ÜKÁó¸Å%x¦ÐV@yñ¯S² c(µ¥¶ÑË»¯  q1ƒ,³ ÅûbHrå0-æÆw®Zà¹ÔB ye&‡èr +)ÛO­Ì‹»ëå îwBasØážÅÈEF²ûrôWD"”6‡ +…nvø.í÷VâS™×ƒÑ~4²µŽöI²>;¯…ÔHÅÄ­ÏÕ­ö=ϑÉrÏÆc2 +æ~<"øÄä¶d[ü‡ÉHГ¡°õВ•©i͎=#-Ó¹¹tj’Ґ¡ÖÄ£½2ÌÔÌo Èæ +EY÷‡9ÑFÙeŸ—…þÑ·‡vMQ¹4.Y³h]PáDÂ`TQ(ûçÕ2Q´DÃõY+ýËÃe'ƒ†1ËÖ㍁ªHšúyq3&b”ƤŸ³=ÉéB4æý šÓx©ŧO h@¶Rü!èo––DGò½÷äU#£9£.dMgpÚéA©‡Ls!Nã¼d’áü¿"„·óùåÕ0ìu w ›t »ì6í6ëÖ±oWÛÝQÊÐi9<ßÕÑ­Åè’sÄØ¿…cjZMˤyü.Ù) +ÇØ› «lôÜ"_4mëj’£+—EÌ Æµm;z–ØûlÿméN¿æÈcø¼ü|ó†_ß»³LÚy ðžL†*Ȝ귓DJĶTÌúï1í¤âƒi•–~)d"ÃÀ<o<G˜·D/·w±†¹=³¢43|Õ6á:Ï2R¹¥½‡ÒɔGav._‘—Ľôßõ×gGõ¹aüA§Lï,`½>Ag²¶Xz,•¼?›¼Ý|zU„,±z²<Æw÷·wO†ÌåpC/Ѓ‡»âµ¯žù¶YŽO}›úº,P]Ø [1Ó$ꖔCE•Ö_.¾,X¤©ÓÌ÷kÞèW¼þsq2W„$Œ»b7«Þ÷Þ_"æyendstream +endobj +397 0 obj +888 +endobj +398 0 obj<>>>/Annots 32 0 R>>endobj +399 0 obj<>stream +xڝVËRãFÝó7šEL2’e›GU„GŠÅ0dp²ÈE[jIíQ·a˜!ÿžs»%[(ÆTa(ÙRŸs_}ïi}ى(Ä_Dñ„ÿ“rç×éÎÞùˆ¢ˆ¦V&£à€¦é SE¡òjNæV҇‹gd’rM¦–ÂȔ„&AZÖ¹Ô¤2·\ËDÍ«Ü䪢zYH}´;ýB:dðéGl¿ÌKé[ÊÑ/¤— Y“·ç9#ßéúʲéߟ˜’….,‡å;yÂÿæÑyÇþ_Þÿ‘­í>ß¾½öú‡ÈÖ¹%˯FVšÓy¢R˜äß +1£jæß <ªw³»ÁК¾9”Íî#0<ûËúsùuá¼<õàÔ~<¡“ïQÝÃרɭ¨{Ä{Q,å«.oUmÞBDžo¡*®:¼zèUcðÖýÌì>Ÿ©Pó|:¾<¥¿_òÁnÞ3 íÿŒõñÓvÒÞê÷gZV¢~¤ËSÇYO·o§oØù›bªÛÑtËæ9a@¢Jû([÷>Ύz3…Rw”¡°‡¦­5~P%̓ªïhöh$©:Åß Dpˆ€fùܗUš‹êf—rt$§M7†v"”6¾Î!-*Rg(ËkmÌ!E#§a~&ųYi‚DU÷úyÔáóbX‹††YÌs*³¼Â Ë_£jß zv Éqy`YçÚX Œ•ª–TX._Ÿ\\½”NTYJdâ ÚˆÚ¬²§…ZÂ6ºíڌxFD—­6ð3‚Wªòg…¨î¬)gI7¦TW»SøC9t˜¶ZºÇ+죖‹Zj4š¯Õ²N$çØ <• a5Þ, óͧ*„ZÔH›fÊn!EQÂ'׏ ®ž´¨Õ¼%¯/µ è"ÛÐ =,ΣJÒ ™pf)˜mÙ²(h!\E+Ê •Kā,QnJüquÝúOsl4Æ÷qÝRûM§Œš±‹Q÷+dsÔùÂЫ&˜§RÛ\’stˆmµ³éN„8oùñåÓo‡!šs8!•Çã`ÜÜtÝ?‡“I۞¯8½\]¢¢®=UQäÒ¤2CYîË1ÅÃ`Óþr]Ç´ßA”4ІA´ßE?ÞGŸåÜ£ÔóU™lþÇ©šIšÊäöRaêߍÃ0>êTäÅÄpCÃq„`‘–ÍÑÞ¼ÕPÒÁ„3܂îJtó„£Ýï"€Ehæ­ø¢¤a8\e²ßEr[mÃwÀ!•;m$ï•C½¯Î,Bëe‰„QI{¸¸ ýQ[€ÕYÑ>äwñ…â¤sX;N‹G·À{.ŠíÚÌ/Ú¥xD×úܔû  ?‚Lh2jÀîâǑ øEÇáÈï6³}Gò÷‡!s&ülra{êGã¼Q‡ßwþô—,endstream +endobj +400 0 obj +1240 +endobj +401 0 obj<>>>>>endobj +402 0 obj<>stream +xÚ­UߏÚF~ç¯Ý©‚ƒ \¤¾”K¤<\KZ)R^{ ›Ú»Îþ8à¿ïׇ̮}9ÒHB¬ñÎÌ7ß|3óm”Â?),3˜- ¯G¿mGoÞßAšÂ¶Ä7‹Õ’ͅ[?þÆyýLŒÃ¹ ù7'4¢yš 8Ùs<"ǃÀª>?q.¬ÿÚ|‚÷÷pÄæñÃ/ +üd‰%M2àaí´FÝTg6´×Î÷ZœO7i2½yJoÙBžOãz»…Où®ÂA»V²{×î–÷ùڞݥ欠]¦9Ç^z!üí–k¥@èØ#Ûajíd6¯!¯˜1Ô†ëG‘só¶_ÔKÁ¶÷Š×‡Ù—5­="1„G¹TU¤>îÙÖü#ÕQÒ(ó žåuÒÐkEñÓñý. V^CJɭ҂ÄpTºÀ#·yÒíA{Éô58‘Êÿ‘kT¬ZŸ«Ûd‹Ù*()¨˜lK–s¸çFì%ý ô›8Ã'éí&K\\±¹‚þßu +§˜$üN~óÕ4¹o°¤çwÛџ£8_ô endstream +endobj +403 0 obj +952 +endobj +404 0 obj<>>>>>endobj +405 0 obj<>stream +xÚíX[oÛ6~ϯ ´—ˆQ_¶b€“^ -ºÚyP` ¥£˜Dº$•,ÿ~‡¤ì¤ªmÉØ‡$N@~<úÎÇsS¾ŸQá%ÉØ~çõÙåòìâýŒÐ”,KÜOi“eñ* ³’¼bZƒs)Ê×ËoM ¥:ŠÇaj¡Ë5ü$%¯pE +͵ÑD–ø<©H-Š pKóÅÕõ51ð· ɕ¬k¦ÝԆ)C¹Yƒ–7²ùú*ø%øúÚrÀ'ÓēÌ×L±Ü€ +ۍ-¥w,_!ÅhU1qï {»úÙ°`5X&ÌR-ù]£˜áR‚+È Rʪ’PÕáxôU „Äúë·¸¸ë0Úք¡»H”6R¿zù²V¾qNÉ(‰<Ý·ÛS£­õµë sÅ7––Ýy·<‹Â/p÷ñå‰S´‘³pŒ¦íg!|öb˜&³pÖ¢“8'/Ð.¶×O¬ÕŒz~o®ìõ:Å~ï8üæÂí¹eÿüí΢QÊޝ¶ +»ó”\pëMØãN£ o.Ipá¸;íÝyF£;Þ :u<ßBɚÊüמ`$(N…·¿µá‚ ð2M1†zéч¼L§)ZA®ó< ˜Þ¶ ¥År^rŒËÇ5 _OÚ{Ãѱí1"à‘|“+’ì‰¬`—+º£Wð'èÀ&vðI}®bÄ¥Ã]u胮fm‰º¥ìx9w¥a•½†mêØ$ß9ÛG4Ív‘ןH½'‘<фZN72gÛ ÞKµj'ñŒ³0ÎÓ¡ò¤¶!¥X¡÷Šzûåë0.@Œ$¬(\ð#yŽxU·üÅpþQº‹ýüúÿdùØÿ¬"¨ƒ‘ÏÈÆ#&3.ìI õ +N>q©6”ºGï­µÏ]7A?ÆÛ®“¼Ùèb@ÏÝÁþï¸ÿªãÒh‚·Óv\WÅÝ*֙ñ‰}8¦ñ iéÑ3jÿ<ŽºljuãXÓ¦³‰ÏfÛ ´¾‘ÝNPÉ;}ÁÜæ_•ßu:Éb/¬[™ü)\¾sד(ÍÏq(†ïÃK0iÓinC¦ãþèG‡Dۀ6 0…H©díÜÕ­YKmÎ;'Àm #Ù')àXê<²G3lžP¶eöHfíûéê’iž÷é4£»žÔ/“TÉa‰4™øjz©0‡`^ +~Š­8ÖöüsH3FVJ²"gÚØñ²biÀVtuûyÑQkeŸh§‘ ËïÁXlß;Åô”W + ¨ÃR(}¡Ïµ=°£uJ¢cq$ší|¢‹¾ƒ¬°îˆC‚4›‚èbâô„W¨†ÃîQãâý´íR4³Õy;gíÕ'LÉr Øhù ~;òGF황]Kf­\ûÿQžÿqö¾‰bÞendstream +endobj +406 0 obj +1167 +endobj +407 0 obj<>>>>>endobj +408 0 obj<>stream +xÚ¥XYoÜ6~÷¯ìS xwuì‰;‡Q7qãÍsÁ•¨5k‰Ü’”þúÕڌu8…ٖ¾r¾9ÉNbˆð'†eé²êäýædúqq ›’åd‹U:YÁ&ÿå½÷Š^ ©Ýü}ÇóÉeñÃ"Í›uZãÕ$ò´Îøè¦Õ¢­•]`O«;Zè†Öèi˜1¾ ýÊÛ½¿¡h<²) {ɸÆ Ï!+‰R![¯˜Êɶ¤ùȇ-…ÑW>2zF_‹bÔÃÔ|õštèèÀm8_ú<§©K}vC¤¢a2%Æ«Õ|=îÌÍÜ©€ uÌІšú _˜§[*‰ÔnÃ-Ú®ßö†[°3üˆn ŸG΅ÞðKÂw5ÙÑÀò¬–’rí²±¾ôŠú ŸÍpýÁ†[ôPÃ-¸Õð4rfóÇÀÖñsó¾ÑK«¬)œf®R4ÕAyÛs¸JŸiÁ©¾òöԄ.*Âx±Ùìàø·è¡ñoÁmñ?[›âaøY]¡§¿ Fÿ´Vrª0¨é4«÷jš‹¬3¼&ȉ& QäL"ƒB>öÐ0[GMè +‡Ü³å•R +y)‚YŠšRóí¯Ò}l³Þ‚0]vP°Òu:}†Û24Øp‹j¸·>_¸ý$E½¬6¾;õ¨ìCÓªËðQœTÔDýÅ9¾$ÚôL¢ÜôvâšsÓ:è–JNJl6b'IÕ7¬ÌÒeÓUûsš抷æJ’¸®úSþ z)Ä-&DØ\‹b`wÅ9eO%În.tG±ñÀÅUÀÉsI•Â@²k™Ֆqì15Òf +¡ý Tä1ìÏa†ÏÝ(Än)¶ã¸_ü ËG¬ë蔜Úýn Ϩ™·ðU zöý껞Dc€ ¸ †J ç__”‰ +îÊÌÙ¢æ¶Êš˜ÀPÀµÊ¾z‘ΏesµèK‡¶~é»Pp` +Gô!Òԗ͋j_²Œé33Qõ³sz•Ô;…FÚKd=“”è†y?en1›TŽ\Ì5nÙ>@„ d­Œw(6 +Ð9ÕXœ1Gq¨ýÑ£¾•ÙàzíT— å‡L¯‘ÈN÷8´%« ìÜãÀÎ=GôÁ= –s›©¿Sºÿ­dwô8Ɯ¯ iŸ7›09ú±Õú«–ôçxš/_1ý:ôÀŠæÀm-™¥®í5<µÀº*?©ž´ll¡´¡ìÕµqv§€Xæ¶´0!œ•$úFæ$9NŽØJšÉq[Éqr|­ØÿöÒ÷tØ}ó.0ïíôðùݑÄÃÇq¤ }Xðµd™Æ +Ÿ™Ú¯E%ñú5ã£C¤ÄÛ(‰—¾âÈt‰-¬ N¼Ïm>\KQ†‘c€²ò øÁ‡¨Í~a̚À™;sچSÀ(§Ûz7 +Çò‘Yet +£{"¹ùmµŒì˜>â(‹¢þœšê{86?‘2w•›Ø£U÷õ§8}MtèÐÛ +`ûøy8+NãakŠ»/U*òÀªºzz¹‚ÿ—šp,á-"&‘3·Ð67è½;RÖ¶¿Ø†ÄmW+YÅL§Ñ"ÐOÓCoÒBãPs\—ÜV’--­§¼É$ÛãÑ¢oj\ÆMÑè÷„t„Ŷùa¾ôNÀü¸fÿ†mh ÊÈqáԅÞæ’f'ï&- ÷°}Ô}ra®Çl?‹Œ&ŽÝ-¶úÍ\^Àe£Ê^’¡o´KÉ®ú|¼ôZ÷Ídìî¼Ö}#™Åú+¯õ“‰lúqåïXcÛí–IÔÌ¢&ø +‚óê95s­ùe# 1cìDÆ^&ÌQ±9åælTvŸ­¢ƒƒÖÞò?Oþ3H¨Öendstream +endobj +409 0 obj +1589 +endobj +410 0 obj<>>>>>endobj +411 0 obj<>stream +xڕX[oÛ6~ϯ ¼—HdÝìØ[Q,KÚÎÀÚy±û0 À@K´ÍN"]‘JâýúÃ#Y‰KÈ~$Ïùø ýã,`>ü,ã’Ÿý¶<~ŒY°åš…QìMÙxx¶LßðÒêœ[™ð,Û³û­PÌn¥aFþ'¼Š‡DˆT¤ÞÛå÷³Ë3ßóaõÃãö c/fãˬ#oÌÂÐ Y!ØâpMqw‡žð¶ FÁF>>hð)¼ÄÇl Ž|æ·âG)Œ]€éh-Yã㠏ŸÝ~îãb'¹–€¯‚åüAæeN.ë5û}¹œÃ&n-ä¹>»"Ø&¯öVÍÖÌˬ†%-Ñ& +G™Òõ’}¤Å¡W¤E¼í&Í¡]àŠ4&Òô´pB¾üY¤¢hqu•eúþüF¨}ig"[θJNa©,Dbåh±¶+t"Œ‘jó K¸b+Á8áÜÍ 2ße2‘6۷榸ðVãi”*ƒUЂ=ãàÇÙ"e+ø¨È–ÖäL*qæ²AãXk;Z…vhÍnï¦Èj;ò—ï9æÑxz8æËÈ󻏙Ўö.03é˜t}̣ш¼˜óøCoZéî`蟌Ǝu¦ÈZáqãgœ_nØZf½ÎÇS°¡J ~_b 4%¿/1¸J ~;1Œ¢‘s]¶å÷8 +ŽyËÙðL•ù +Ô "ɤ±ۚ­AB˜ZI´R(x­LA“"û£Ð'F;EûȯRäíl~͓m;9Nò®Ã¯³¢Ë”"×ÅâÄÈ\*lb·Üb, Å lŠ:±¢è#(ž¼&úD‚|Œ x\¥Ã…(îDq•æ”ôqThm¥á/<]„íÀSí$Ú°<±ì^Ú-ƒ¸ÊDÞKÂ8|E¼úÄx!ð±x‰ãICAíã#0;ª×k «E`Ê$Y°ñRðÀ˜²PL—ØrÀ?ό&åÀ„T€hà(„[;k^f¶µÂõ×ùê0Úì"‘î»Ù|ÎhyÆÑÊ`½ì;Éëx nönJÜWìӑ:öô}ˆÑ¸áÿäÖâxNjaRîL× L«ŒŠŒTä¤Ür—¯û(ˆ¦£Cö Ð' +ÀÇAKJQ¸‡œ›*t¹{! +ϙÙ÷P\€99:E!´4ƒ›vނFº8[ ¥$%ÿäTEèS¥ª(¾¤¾})òݍ,^‰Íw]¼Päx±$뢮Ïé8hzü~e8ô©Êpà£Ê€§+`K™ ]¶##ò[íý½$(V)# §ZN€¨³Â£ÂÝV‚iԌTT÷dšf® +òúbÐǕ?yE-#ô©qàc §1yñÕ<ëì³N]€ +ö¤z»Û`Q*]{‹#ñ¹Yñ ËÚ¦à½e-„KÜéCèù ð | ?NY㝆5‘7ò"°Y*׏€Öhws;Ã1ebTѤKŸ¨#ñ*jð^‘£¨ðྺZ\ÏfcÖc×:ÏQj4h,/ª^Àµ º„;Ó·7ƒŸßÞ¶ëâ–Ð8ˆÂ«j›>@ç÷Ku±Ê¸ú×-Lëšfa—ñœTÑh¹) jÞ73ȄͭIÂÔ;ž•‹p=ôü¼“»éÀŠÕ:ý™øUüñ.à,œ¹7/ƒ!¬‘ðn„I +¹C³ºeøá+Š¡£0ô.Ÿf‘G¿~`ŒLªvï*I¡Ú£&. ðZOFZpmJ=‘)qϾë´0Ÿù/µõ ´“ÊàoaîúEú~˜¾"V˜|~¡õ©Z¼»¡îi^ù€¾oYønX¾oè¨ÇeQ ^Í& %“J:qaqåu¯Ø9©6ýÖ iÒÁž»:ü8©Ž7a¥¸ ýCo8CK×<p]7r£XK{4墚¸RûãZª˜1B†}WzHàÎ_gÿžendstream +endobj +412 0 obj +1502 +endobj +413 0 obj<>>>>>endobj +414 0 obj<>stream +xڕ”]kÛ0†ïý+¹Ú.¢X’?V +ÛºŽ@]ìüז;Dòdyìçïè#m)I›`Az¥÷y}tü'¡âC¡dÀ h÷ɗ:YÜf@)Ô=°’dP,9YBÝ}¸e+¶›õÇúwBiN +܊óÕ ZÙK1‚ý% óªùd$4Öù0Y½6~q0RYaˆ;á[¤$Eû§aóXæËƒK # :"¦|EVQÍ#å 5æôÇSr­zý +ü3XñÏNÍ¡ÇÖÈÁJ­@÷— æ%žv6ªWŸDÍ8ŽÈu§ÛÆ¡œÄÝEÁ…¬Ü¹œÍêÕ'YÇ)„ú¡8úi·›;4rIõVCÓuÒ1#¾D½ÙÇê’´D׳xõñŠ”;Ыûà ªÙ‹kgŸÂœÆpW‹¸zýï°VMÆèIuãK~¼H½T>ç;QrßUáHîêþf” QžÕ‡bäÅ*ÜñÊ6V¼ÙK0:å«ëó ÚFÁƒ€ÙºÛ‰`ÏÎ*«‡At³÷Òø.;·0A}¤0‹ÛeüóPß)%ó¾nï+X;ľi܈Q>*÷:ô¬ƒ›‡-󸇓‹“¤Õªwª¬ÌðCz¥1ÓÏä?³‚CÜendstream +endobj +415 0 obj +462 +endobj +416 0 obj<>>>>>endobj +417 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS045×3S072PIÑp VðÌ+I-JKLNUpI-ÎLÏQÉE™%™ùyš!Y\º-ºP=†F AcKK0×XÏTÏX¡ (dJ±^r~^HÞ5„+ §($Öendstream +endobj +418 0 obj +123 +endobj +419 0 obj<>>>>>endobj +420 0 obj<>stream +xڕ—Moã6†ïþƒ=9+¤>­{Xg³…¢p7Î-J¢kµ²¨RTbÿûI)±ÉÒ€!‡/‡Ï _•ÿf~(D.x!¤‡Ùj;»ÿƒK`»Ã‘0òa›Í}x<*.KVÀºÄ‡Ky}·ýÇhidµ‹:®Q;¾UՓHÿå +6R(‘ŠÂÊ} ´•»¡c‚o÷üL^µrÈk`%,I® -8>o6÷ë ÔV˜Š²ä©ÊE逑ñk +ZÁåkžr¨„T:NL 1"̀+Sς>ÿ\Á«½È d®¥_lô/Χì|â,mv.<ßzàq;#Áfõþõów´Uˆ1vú–KE•󱊷Õô†bÅÃ`xñƒGc`EÁtïcsƒéV·âa6J­Õ—VoJ|E؋b¼b$˜nu+¤ŠÛ·È¸*¯|ìä-ƒé>7ÚA˜ˆšµI?K’Û»ùJL÷¸Ñ¢íû'¥g/ÿߟîk£„Á ÆÕôfß¶/ñ‘ú£•Fmäú¿ÐÆý~kßÿX¾¿'‘›ÿ»ø‘NÑb{-Ù_³ÿ”5îendstream +endobj +421 0 obj +985 +endobj +422 0 obj<>>>/Annots 47 0 R>>endobj +423 0 obj<>stream +xÚ­XËnÛ8Ýç+.ºJJ‘¨§è"I“A€¦“I<³ê†–h‡…,i(*~ý\^JŽ,ۊA‹$.ϹOÒÿøàá?‚ØüÏÖ'ó“³ë|æKðÙëCœn +óüÔ>ϝžkÞ2Ÿá+d¼„ZÉRC[ƒ®ÀO_X²ÌEcÐWóÏõp“͏û?Ñnlì& Ú%sÌs(ûÀIŒ‹ìÇ¡› ÐȶãnLœÂ÷9ñK˜É1JÐî± |˜c¸!qЦ8>q%ù¢ÐÈßïó ´y,?ïáwv=Cˆ‰¸Qà +² +Ý.ÿ¹{€»ªÑ™’µ†kYÃè-E¨3în',ŠQçl[çyþÄñìöMb‡,³±XÏ c֟€RSì,Â+‰o-lûp”b#µ+ààݳ®pj¿Ó¸ü(9ºqYìÑ^!ôA¯„]Çg±‡'ØëÊõ—|…fx· P8FcÄ\üÎËÀ—ýT!Ù~ä¯j1ûÐ#`¸hæÑt(Ò°Þ½ÉHÔ:e +kA`‡7p‡ÄëÃbF=ÛiU¶'yeeސÀßµÜ9—Ñí{pX?òéÚm`*fJ?A-¥)¬ÕO`«ÿ ÜëbÛkYœ:,õÚËVO§`ÖjX÷ˆ‰IÂ6ƒdöNd ڕØì½È¸«°Ù ²g×iÿE}s’0osaz;*âyG®J{ûŠÓ½Ó}íƽxsÊ CªznÌáðNUºÂ@w>øûä +wë“endstream +endobj +424 0 obj +1497 +endobj +425 0 obj<>>>>>endobj +426 0 obj<>stream +xڍ˜]s›:†ïó+tyÎLqõ_œ›$Íi:M›“¸ÓkŠe[=QMÓ_ߕ;‰Â‡&3Ž@zÙ}wŏ3F(ü1²äD¤¤8œ¯ÏÞ^ń1²ÞNÅB4c‹Œ¬71ò¹èZbtY’|ÛJC¶ª”¯¿ŸQ1±à–⯩ïú›‰×P#[Š_Cu¾s÷{·>£ +s?}ÜýKâl±$©HáìØ~¤vÞF’ûv/V=Ëh²ˆ'aN©ÕÁÑ\d úŒÁfïËqõKñebçèæ@íÁË®.å/{ ïåRXÝ­QUKUíJ5j#7žìmt÷í94¡å09ww!àn“ +8g5÷ +8x¢ +$Y¶HQƒ4â™x©Áû¯w²Ñe×*]yJ¼×FýÖU›ÃS®6ä§4­*à‡9@T´MTK©ªØ/¦%H2Sq7ç>¦$@§3£H£OôI‚4ƒ«X ²8â«ÕK ®ùõ¹îªûï‡Ä•î ,µ•;i²S?"í^’RnÛ7ä›n[}xCŒÚíá§ÕªÕµ1µn”•¬!zëε)§â=áË/+f­á6͌ˆñê˜I³q„lh!=G"qAi$¨E×UÑq¿—h^:]jRéÖg!0”:7y«ÁZ,ß ¤Öõ89¡ K‚ó Ù`]=ª e˜_‚Æ Ìò¥2ônLðߝ ƒ! >ǦÝdž-ݧzO×2NRX«[E²šqkdqS0j‰4jùDµŒã¾¦ šE‚±—Z~”¹M–w,6ž¦k] CD5 –iÚUïlŠNRVÔs—Г˜Uõ#dÿkh\T±:•ÀYQ‘ é1QE†Sf$õ¼ï&7à}'§[™õ1´6…(ë\ê`m+ЩÄòE³vl¨Ý#=f÷"=F¯âÂ_rÕåå•Äz=lUǔd 9ȍÊ¢éf˜š$>Õ¿Y‹B6Ô¢³(Áûú'8X÷,êÆNü¶¯Ož&×U ^S‚&Ç +F¶B‚B#Ÿf–Ë9\'ðù;6øù;zôùÓ¬ÏR."ØÀr¿JëÞbÝypC6Æw&?4zx¶Î6t¹™kó4ccI=cY›üñþAµÅ~ÜWŠ}^Ar·€6Dma¹¥,Zè"í»Ÿ‡º}Ðè"øÄ‰% N‡7¡Ép’¼½ÊúšÁEKî䏸r{ÕLÓe÷¥lÔ®²ÿ +£ê£-GxJԟÃeÝywyc[²«~[/cˆ],cI¿úÿÎþUD!endstream +endobj +427 0 obj +1361 +endobj +428 0 obj<>>>/Annots 98 0 R>>endobj +429 0 obj<>stream +xÚŘßoœ8ÇßóWÌc* +¶ùé.›¦­ÒUsɞN‘úBÀ›åʤÛü÷7¶aaYðÒÓIQ+`‡ç;㱝Îl°ðŸ Ôÿ£íÙÕêìý ۆÕÛôÀõ©éÃ*>§®oPÏ~·úûŒ¹&Ávh\½lŸR.l¶å˜L-ø ®sÈòʼküÏ Ÿy» >Æ/EÊ&Ù³hiaSì[ÚØò~F“«3Ë´pìûËýG`¾®ËLä)Å•F؀™Aêë`bY&mhB}ÓêÑ(˜’ɱÐ$dòÊäʽÕ_I\oJIäké($[yE·“Ÿ<­N8Êö"?A,¼h•¬ú®n•´r´£÷ŽRKŊz.:;ú‰'ϛzà©2þGW Ãþgº*ÙÙ®JzÒU[ú–A}zìè’ÇI¸z-†ù]&?xiT’u¡±ÎHÌ-_L­ÀűÚMÆì_©içã|PoÀû„4áϔF²³¥‘ô”4Ž4UÁg(Žw,ÎURWw¼\äi^ô±/€\»@OŸÒ{èÈú3ÏCÅÎõPѓºNwé!Ö½ÀžôðNdðÐCqJæ¸çÒ¶^vO²³Ý“ô¤{,h²/ÀzŒÔ««×š ÿ¾$sï0¡‰cÚóžDÇ'TatvqSìlU$=© + šâ`q FŠ›Ìç¯eÌˑE/Ú¼dß_›šßÎËÇ[Ø_¾½YížÂ,æq¯ÉbËåáöö¸ Á6EfayÐÆ4MÑLܰ¥¸ac¼©öÓB3,DÍì‹«Z±Êe¬„V´º£[¡™OÔìb–e0‹NýP„ÑØîb·Ij>¶wøx5¢Z˜©> £ï;C;Æj`uÐú¸\ ¬®bofOÁC³æÛ㮃Æmõ¢Ž×ʦjª‹”‚•fZZ…Já*T=¼e´ÃXyc±Ú%¯ª$ÏÞn)¤Ô›]I;·f(zªfPBÕ™åÌY(îóÝ"Éê7ÔÆöf×SÅÎÖFғÚXí¼² jãŒjsÃyüvҐÀ›½¹Tì\i=% ñ©ÆEa‚Qaj^¼¡0ž7{k©ØÙÂHzDüI<•0« ‡åçå¨q 뼄şwpV5/a¤x.L*PîY{çaQ¤IÖXˆÞÿÈbSi”²Í¡ç¦úJyâ7Vdf©-3ö[;¸:lŠ(q•ˆ‚PC х¢L2üó‚㢞ÕÊÒõ&¬%†‡žP8´ÅßÕKR‡x€Q¬Ñã˜Wu’Éñ·ÝáúÎÍgs°l|º3î_.ï÷+¼ó:µ&UÛýªd»_Ð˅Ïb¤¯áN 鸐×y”§“Ú‰¡N7E1¢2yÂÝÑÓ«Tg§i¾ØýÍ¢ºT]GM×ÄGeö½#®Gùm7iH]Ì<‡`ƒ-Å®P<§)Û²N€ùа¾§g»÷[°ñh©…{Ò8 GKwÀg A75t@Ú=1쀴¿g‚ö{êQ"·ë-}u¤vù ]ø© N“ÀA<3¸Î¥& Þc—ð!‹òX˜q§ «2̪"/åZ:¨/òSm:bK³Ÿ.3ÒAî{štÏšthXn Û½oÓA÷€6tt´é ¡{Ò‚@KwÒމ‘ô€­Ü x}:˜ÕK÷t2,ó˜§2ø6D"ªþ÷LÀ£¬ßf‚|ÖdBÃÊHkØî½È[÷¤ñœîiéyãœè»ö|±^kèÀL°OôÝT–9ZºÄb²§Oç qÕâÓdŽw ×¼Jž3ø˜‡x&+_˜X–Æ’Æo>!bà‚4Y#WQÙÛ¤í·®åUÔͱǰqN0<¢þHâ +#õmœL–Z(ÙÁ&Fì-šLüãì_Òíjéendstream +endobj +430 0 obj +1452 +endobj +431 0 obj<>>>/Annots 147 0 R>>endobj +432 0 obj<>stream +xÚݗÛnâH†ïyŠÒ\e¤Øñ FڋL RfÄÙ«H£ŽÝ&½c»=v“ ûô[íö ­VH à«ê®ª¿ªÛ?&ø2Á³ÀvÁŸWƒ›{LV!X#Ýwäè#XWϖëÁÇÕïƒéj`èÊ7S¾-Ð\7µ‘Áµt»úÁò=ëÆy=´Ä`Ú}ÎUyÇÃÏN^!w&’¼BÄ`žnvò*¼9îñ¯ÈÛâ +¼B ﺺ×Í+ò£aO>U"ÛêãUyÇîُíúxÇûò©ȏ>^!bpzõãìéÇqǺ«ðŸԟ­áæÞ©zÆvw³¸¿kèŽ>Á‚ÆQyâ•ÂRd_l2 +<,~øÂI˜g\pŸG ;KÍ*ð––¬D¶ãn7F³›ºƒ5©lÍ´Qgv°g`´u_º:¸¢Ëí ;ÌË~ëÀUBväX껋WäÇVŸ…iêN'¯²#&S§:ÒPriy¦TPß¡ Âb§ ñ'øBÒTVþ…ŠwJxœO +±ÌæóF ùq9hèQ³\Œ=®POO‹ÄT¼ò—š”~XXš~Ð ?;›»§ù²„æ… CEü]n‡þ4ÉQÛÀSš*G„Kw…—›û1ÎWú³í2*Gw±!PÐ’M$?sÔuaÏÅzߦ«o“éýíÓã +~ã§cæóÇÒg*c?®5z *â±Ùd[.)ƒHe3Ñ ˆ{ÙŒ­n¸|› 7¾jÿõ#’ç:àjUŽêÞâI´E÷?6,£ê“`‹—»6ª]_íþÕüW’åTì‡uUTö´†µÉH¤E$YoȚ¶¬Ûå{8‘–wEPí[¦¥½"JAãߏ9?YU«¨ê¼ÌW®–r¾˜}]M˺–ÖµLk?`Tå÷„¿'R»²Ճ½zµjùŸ«^οP2nƒ .Y]±Ûɤ®X]0»§`½4ÒÔ Íeßd4ˆ_<¥> m ʒ\šçë}ƒ£ìËö±ZU›Ò6; ÷•Që§]³#ÑÔN#î™iÇrŠgIÈÏecžÑãG¢ èói­ÞhFÜû+žB,a‚aÃme¡åy@v]‰Kò´¼ö”pÌn÷¨vânaŽçZÈ𢄢Y–cø7(Øõ¹Ÿ±T@L¶Õ!T^ðð’Ãá/<Øê0 q‘7±àÐ=ã*­¸Š5ñL¸l7þÆŒQÈm«£‘Q"äˆÇìà”JhÆ|˜ó\,Kïe^Sº£hâ ú÷ú…ûÔÈÏðŒýQ°>‹hU’pLÉ‹.š(ç´=T&ÓÇéjڞ+NÏ\ J_‡£%£1ëž(]‡ò9ÃãÄÜùëÃýú²yÓVÑd?ÿ˜B¾I‚3EÑ)¼na ‹ÛÁ¼BѽËÁÝãír9mîÃ3î~ååâ«Amøÿ¸ÔÑü‹Á¨únâsµ|ö)·þY3<ñŠÎ։ü(æ\u„i¥‘æYFU垧UǓÇlzճ诃?£ ÿendstream +endobj +433 0 obj +1190 +endobj +434 0 obj<>>>/Annots 160 0 R>>endobj +435 0 obj<>stream +xÚ՗ßoâ8Çßù+FûD¥K. 4¤'ÝzÚ +i{¾UªLâP÷;ë˜ívÿúã@~·Zí^Õ +”ð±gæ3ãäsÏÿ\øú?Êz×aï÷›+p‡&ø‹¸¶aÜÚ¾íÃ8Ža’’¢€‡þäþnù8žN'óñr ‚óuè8þÃÅEøŒ>†àºÆ‡åùöPûŸ(ôm=ˆœJ¢˜àú^J4OID P(,r±„ÑRnƒ¶6®ÒuŸ(%Ùj£haEODT5×îÿÖ4À½¸O͔µ‘$µRÂײ¦m@xÜ^9—Œ+*­d-9TžHŠA}Þ0Ic[ëZÉ8â4Ñ61o6rDÏx"ÎÕfBÒâÌh¶2AÇ£,ãÚ'¶3¼ÇbEbK‡H‹7¼iŒX4³U3°ÍuÕpÖ`€}V6ܦ4¥Š6{n:›ÏÂY³íF'Ú.6~ڝ'i&¾t5œàX¶}9›hŸÓ[GÚ²£‘l7¶Ù™ÖóðÃðIĆÇg¢Ð‰[7Œ£ˆæ +nۚÀ“Éì.|¼ýt½‡!85ƒ—gí¥6…ÓT¼æ®°Úé°î«×!1¢ÏøÖ®›“Ãá?Ïð_˸–§÷ÆÊ,è3š¬,f·³I“•«¬Hã¥ÅJ.éÊUIK"E†¼l‡öw"Óæ¤y†¾dµt½7d\–TᑓMª¿÷Ûñ³œ…xú܌ïç᎟ñ ~°8Xz㱆@ã Ò2gÐþ¹ ª‚qnIz-Íö¾vJüµ:®Zu^?©£§åùp-äòùt4Þ.ª+@G¥ÕÐÁco èæŒS¸+ ?%øìÂñR(‰TΞc;øB£?\ý±ø ¼Ë¡} ‡œgàÛ1),ÍËNnP6ƒæöÐZýùÝôáÙ3k+t"ÄÀL¼ã›¨ÖÍ`à\bLûM¼Uרö ½K] Pí»ÈJ—ºd0tÜ]n«kT;¹~¨\ï²]&rq3Á䎮þ8YºÊ“Sz2,XÆac¤Ü/>BF‘Ô8ÉèvB`at5>¤yü¡„((ëê^Žp7¾ïô ƒz ¾kê)ÇÖ\aóÝ[—eŒ¬‘çh7Ð7½a`ÀùŽ·adâïÞ¿ž}Zendstream +endobj +436 0 obj +927 +endobj +437 0 obj<>>>/Annots 163 0 R>>endobj +438 0 obj<>stream +xڍ‘1oÂ0„÷üŠ 86Ð:BKŀDIØXLòÒÆ1µÝJý÷µ Zu¨,=Ëö}Ͼó[$ÀýH'˜&(T´Ì£x½€H‘Wþ$IS– /‡36GFæƒ ¶d­¬ ËV¯Øít¡ÛQþâÉ„èÉñ$a³@ægú›<³íò8‚ìJj¥£+­”î°é™ŽÖMëéOëHyýj³Î>>>>>endobj +441 0 obj<>stream +xÚ-‹Ë +Â0D÷ùŠYê¢5Iíc]àB¨4~@‰·%ZM‚߯Q™Ãœ'àŸUª¾³V±Õ¾P#DYçjÉ¡.‹Í¹ëq°‘ü8h–‚™líÍ#g—êʲŸ’ýÉ,D™K|Á:oГ‘Ç‘B&B;;}Cç]tÚÍé¿SìÄÞ+E*Zendstream +endobj +442 0 obj +137 +endobj +443 0 obj<>>>>>endobj +444 0 obj<>stream +xÚ­•Ënƒ0E÷|Å,S©Ä!%nÛ¦U‘R•~€c‰[Œ‰m*õïkç±y@H ðs=wÆxDÐsW£>< Éà) Èë#ô{¤.2Őð΋ÐȬÒÍ]òå¸!D‘çÜÔ°?ìnPRM"ßñ "Y!l£½]´ÃhÎ0;œÒ¹¯RYQO¬ëݑG Íù1g,µ˜’ÒÁ4ÁV¨±{èWxd˜¹Ö1ʶ.V†×§K¹¬ÊŸÂXS4~¹&ùSVT#ñ9\²Fp·ui¥,ð]“þ‚J7£ÏŸóð… 8µô +YâùËea¦Ì¢ƒvãG*2ÿê§úgl›3IUnÍUMáúQijœ|Õÿ­ÛV#¯îÐêj •E†0Ÿ¿Ü&u.ÖÙ·¨ÅÕÿÔyl…¼ÌP7’# ʾ1ç—ßA»V»>)–"¬ýã<¿M¡Ðj©©l#¡ò´¦]ö΀gŲÔnª|³‰fÓÙ¤eÅW¬©°CK‰¹Ý +ŸÓïõÜ)ƽîù#1Åݱ;6]¼ùI¼Ï 2endstream +endobj +445 0 obj +421 +endobj +446 0 obj<>>>>>endobj +447 0 obj<>stream +xڝ’MOÃ0 †ïý>‰~Òv=Ã@â6´Âe©ÛfڒÌéöïIÚ²Á4&˜%’ó¼ymË[/†È®îr·ùÆ»/½ð)‡8†²v¡¼HƒÊj~0 +ùN›°ëé¦\Y2=’~’©#ËÁ2ýaA„FT-ƒìËÀÿ®;:iu5ãh~wYìM‡xƒ †“ÐÝ~k՘Ëõ ¯Ñø:aÜæfÞ­î§lr{J"‘¢³ “Õ)¬Yƒgؾ›W”¥uu©*a „¼S´®dDŽ40ŸÏF¿Z ã-hê{ü7SÂíMgþï¬QVB6ƒ¬ÔrÈc´-ƟŠ,È!™&ÃT>¼Îð|˜€™mQ#ÝՏ‚P҉ý8›Z‘?M"§IL£ÜÆú@ø03ÃÔ=–Þ‹÷ Õ»â[endstream +endobj +448 0 obj +310 +endobj +449 0 obj<>>>>>endobj +450 0 obj<>stream +xڝ”M›0†ïüŠ9¶ØÀ"²=¦(ÉFZm©`¥^½fºñµFù÷C+u¥`©3<ó¾ž1?’Vtä°.ྮ’Ï]r·ûÅ +º#Eªu ]ÿa{iœcöú±û>%äë9!­ò¬˜R²:´ÊÍäyÈ jZTÙD©çPy#´nÔxöhA2=œÙ€Ù{PúwúÈ,“å2°EÝ =€±`‘£øzæ(cüÓdûUx`t‚*^PŒSo4¦v .ÔY μ0Ú§2%¼¢¿ jð£5ƒeÊÅÊ9´‚ý—»ðä ?¡¹"¹“+Mò=-¸ËÞÏDJ³”–«ìažŠ6Ü} Ʀ­‡ˆEËÁ©a­gºg¶‡ÚôGrÐtU“º§ñ šŒ¸®_šv¹TM õò|øڇ…m¯Î£Š0·m}×,C·Mûåù†ø©Z!ïºw'$Bg™vG 4ã 72B{lÒýÓ2ï/½OÆOAèÞ²ñMpO¿·äüéÃôÔèÿ‡r]R÷W!P܇Û.ùšü0®7endstream +endobj +451 0 obj +424 +endobj +452 0 obj<>>>>>endobj +453 0 obj<>stream +xڝ’ÛRÂ0†ïû{©­K©—Ú¦â4>@ ¡FÚDӀ‡§7) +ƒ3DtšéÅþÙo³ÿî‹BÏ|!\ÇöÐÆcï*‹! ¯l(N¢ ¼¼¸E>šä—øÉèÑA÷ûqu:{­™Ö>"tMԐâB3)´’5äDTR±Ể„0%æÿ(1—çàg)ÎNÃg%˜†TT\0fØ`Ò®!“Š:¹ík™HI-©¬]Ärñ‘h.©¡ÔD,-,TEÿè;GÓÓìÜt¾·uJXãD³"=Í*6µæ [r{ +ÂkHß裙–ËRç¦!3濬ruŒd«Kªø³>ôÍÚ.àö±,Ƨ©%S[C*XÛÚǎkI×ΰc…°â[nFñšVD´+Ã>^£ä+/1 ’ó7™“{TîÌ_Êlc¼?ûóÃÁÐ\÷‡ýžÍéG6…I0€.0 +ú0¢JŠ÷¦µRн;ïü&endstream +endobj +454 0 obj +374 +endobj +455 0 obj<>>>/Annots 328 0 R>>endobj +456 0 obj<>stream +xÚ͜Ks7€ïúsÜB^Ì!Y¢]vÙk­ÈÜRåb¨‘Ì„-IÙñ¿_<º‘ÐmȤÊ܍Ï3ݍFã1þï«jû?«4¯DSÍWg¯§g¯Þ´¯«émÅT[5ZVӛMg¿/»js[]lÖûn½ßý4ýãl<=«Gµ%¸_˜ûåú­kTP#S­*3âðó²š8ö@}{W½z£*ÆÜßæº5VÕþm¬z‘«Êÿ–ðƒ(“ùæ¾s ®,ÜþÁèäÿcϾ·})k ÎG}qÅG +ðâ¯ÞH0£õcŕ8;Ž2–$•í˜-)ä€zwc½¾¸]ÌgûÅfí JÛ'dגíêv${Ûù¼¨³«G2XŒ—,£­aN#iò}·ïV™@Žý­ùëCÙˑöék·ýºè¾9œd£ö$ _°¸jkM°xhD‹«VÛ¶·¸(X9¬vñœ€@¨ËÍüaeÃôyEX ”Öº €˜˜Û?;²ÙY6íª¦íÓnø¹Ï1É*]‡ôÈóIaªµq˜Ð¼)×Ým·íÖóÎϲéϵ¢´ª‰)64žJ±Jéy1Å"Ñpk±„b ]üz5ɸ$ö¶«jçÊ9°p$ôɺiŽë–’Õ¥ˆÉ94HªðÃÔÛº”œ‘cj›Uˆôiÿ¥ÛfŒ»»Üìrp9ÀÐØ8øIŒ‘OLÛ_!UøŸŸJÌqQH€²o®RVzÆ;[5n׳åó(Ò}Uٔ<`8Âng˜sN/ã¨B´×"¤V“¾ñdŽ©eȱ¢œc€ØšŸÄ=’.¾Ì¶³ù>ûáÊB×1¶&â&]n®%}Ý(r³lBB€½Y,ƒCy}C¨àDÙÖq¢˜²dËB"Ŕ…k÷&å€Hf뻇Ù]—õ\Óã¯û‡ì=7"O֛›µ'RNbt­ã<Äèڄ„,Š%%rŒ²þI8 ÒÇwǙì{»êÔÍÆ äÀ¢oN+e=ou͝ÕéëåÖ-¬CÞPÛ÷kT¨•­ÕsyŠtv•·¢@°ÕbՍößïû²RÙb%)†—1‘ê ÄKŽ«ðx +y4Ï|³þêÍ£Žœ.›Â :Nw¡A­08ÉÉÒ «ë!䀺Úìö“ùvqŸ] Ö)œk$* s»XgçMа@£A€—ÝÎ?¢-Ð3P‚YU¼ö<‚‚Ì¡ìŸ,C›ÂØà2Ìp>€}ƒŒ ®p¦”åô$ÆuÏMFÂòk)ÚÝ´¬BdÿÚwëuÓ.C$ ç|—¯R¢&O·ßä<ûZ3þˆ +Àººº|F»[˜ @ÂPA=ª þßÁSÊŒ‘‰Þ7HΰO ½*å à´n<$i2ÿÒÝ<,³…qDX7ޖr^lÖ·‹»‡í¬0À Ç޲c ¡¢¼>Âî«ÎtњX'„FèÂÛ'8­8БĤ«•È6_Îv»nçæÂÛS˜ +MÁBÖÁ}™ÄB¦Aû”Êä¸L‚@îQó‡ûÝMoéÕG®;KöÑ,¬cýKø±æX*¨\…O:»BŠ; QÈv&vBò¨ç¬ÎnÜ©ÂÊÅÆHøù‰a]íӅÌoÝ L¹…„¤@q3`~ó†|®­Sˆ7ؾ‘§¶±Ân¥<l„ÆSû7Â|Î Åý$²Úé&Hêüþ~²™ÿ™Ýw! —!Üd’QWÛÍ~3ß,P8×Eã³Ö§¾`߈•àu0xi×)~Û<¡qà°% ƍÍI )Èéõvóm·XßåŠÒpõ…+É(^â´#m€=U«¸î â©Néeq³9Áž”b â-@¹=}²@ÞüÀ’@–F›"Q¡‰‹3_\«#ïf0™woÉ5ƒÐˆŽã-ܐÅ;r¼iˆÅÁ'_ˆbÌõIX Öõl—_¦ÆA‚C—Dà´SØ%-ºN“[¡A\gà6,®›Œ«‡·zÒ!®³CC§¬ GÖõì[nV‹½ÃKY €°¸Prú'P_°ÂŠ—7ä¶DhÏ5K‰¦ä9à˜vÈ1Â‰\® „`qò@®±Œ°uta†‹7ÃI;¢ *è' +“ã嬰½Å•ˆkºÐˆk®`À5Å5/rs•s¹G½ÍŸ¹Å¾níãb?!¡B8¸îngËŽÜö£‹¾ +€ÛÙ(lxPÈÊV3¬· nI‚GþæÌç·ãéçËñ›ó_?LŸ'S–%‹zH¶ +Èý%ƒ!-¦i†ïlSÿ%ëšýöS((>Ya/…‹6®„CƒD•¬±xjŠ{H×ST#ìÈB–âC( öËs{¦„aƒK»“Ê”HbáêúÝ¿§ãëÌÌCq+?Q ࠀð_r¨– s ZŠòAÁ!(äß߆/F +oâözhH᫵¦¸g‚$ÆÜ‘e‚9ÀÎonr‘{÷9ˆ²P`å“‚°¾lü<ŸA€(痗(çš‹9d£°³q" J0w±1E |œL/°$( + š‚/¹Ïä…ÉQ?UÉR É-IyŠ9^ê–ݾË/zyÄ5µ+ (€WŽ‚Xù*~ð|¨@ˆ•Ëñ‡ñt|@¸ õq͇xT|nž!Ýte†NA@ùp‘;\ŠAR×q?4HÔ¬/CsKÒ¹Ÿw( +ä;dÞAV锅 +»Ål@Þ¸µP +’içâÃùd2ÎÍ:„沉²QØÙl"J°zøÞ¨(ªŸu^ X.EŠ;zîëÞЈ‘ÂL_Ÿ4…8AN˜È́sNO’ª¾dď‘ Œt·^”æL*D‘¹ÆGGÆ¡„c©J©V©¹¸ W°M‘b”FŒ‰æ%c"£pŠÃ´ˆµkhÈÐ2Ö®º@ +Ó@‚¹ÄÛ‡L4=Οñ$8TÀ‹’…!7ЕŠ)dR»Â4SŠ‚³p#‡pTåڕt«-6@‚$µ«~©ˆ)ÆISÇÊ54Hœ4,V®¦'@ +ûy +ä;ŸÏ»òžnó뾇 +À{¿ù=&‚¼f(%Sš‘…¹äâb|5ýüþÓëI©níɾ²LȨÀ¬[êÖ +ŒÔ­æ%ëÖR˜HëÖÐ a"M¬[ÛR˜‰ùï³Õád‚ÍoÙ3ÎâQthÄ-{Æ!ÒtaÃ)Ú­c +ˆ=çÃb)oH_ûƅ%œ¶†&ýW~8h¨‚kÖ­²7ÜdB3ÞNá2BÑã5¹ÊÄãµÁÊ֔|[}Õ)Ä?°Ù~Í~¨&ÉC1î32¥Y»Ý.ûýíòԀ† +|½ÜÌÿÌg)‚kÙÐd¨Ðß°&®Wÿðqk³·® ë/]öô+74UþʕÁû£ÖåeeDìç +…#òs®&ˆÿ½ +…!@.[[m¶‹p–ªØ©~ÞË _FÃuIW»+rYÒ}3í—¹lˆ}ü°Iÿ ôˆ·Ë_Ûï>|ÛÓ8sÎZL”n`‡LçNi%{æE —(ϳ7Üz„Aјï¼0Ón» +‡ö'öoKj4nÂÅ´m÷f`š½›Öw Ÿ¹˜„¤È™o7ëï+¼C)NË\ÁPñëþŸ{1=Ê­š–Þ#é/†V¶b]Ü­+òŒVÜp?ëpnVüÏÙÿ½²d+endstream +endobj +457 0 obj +3024 +endobj +458 0 obj<>>>>>endobj +459 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS045×3S072PIÑp VðÌ+I-JKLNUpI-ÎLÏQÉE™%™ùyš!Y\º-ºP=™™ A×®@. Àýendstream +endobj +460 0 obj +98 +endobj +461 0 obj<>endobj +462 0 obj<>endobj +463 0 obj<>endobj +464 0 obj<>endobj +465 0 obj<>endobj +466 0 obj<>endobj +467 0 obj<>endobj +468 0 obj<>endobj +469 0 obj<>endobj +470 0 obj<>endobj +471 0 obj<>endobj +472 0 obj<>endobj +473 0 obj<>endobj +474 0 obj<>endobj +475 0 obj<>endobj +476 0 obj<>endobj +477 0 obj<>endobj +478 0 obj<>endobj +479 0 obj<>endobj +480 0 obj<>endobj +481 0 obj<>endobj +482 0 obj<>endobj +483 0 obj<>endobj +484 0 obj<>endobj +485 0 obj<>endobj +486 0 obj<>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<>1<>2<>4<>]>>>>endobj +xref +0 506 +0000000000 65535 f +0000000015 00000 n +0000000226 00000 n +0000001783 00000 n +0000001857 00000 n +0000001935 00000 n +0000002012 00000 n +0000002091 00000 n +0000002167 00000 n +0000002248 00000 n +0000002306 00000 n +0000002421 00000 n +0000002506 00000 n +0000002621 00000 n +0000002706 00000 n +0000002821 00000 n +0000002906 00000 n +0000003021 00000 n +0000003106 00000 n +0000003221 00000 n +0000003304 00000 n +0000003419 00000 n +0000003503 00000 n +0000003618 00000 n +0000003703 00000 n +0000003818 00000 n +0000003903 00000 n +0000004018 00000 n +0000004103 00000 n +0000004218 00000 n +0000004303 00000 n +0000004418 00000 n +0000004503 00000 n +0000004597 00000 n +0000004698 00000 n +0000004783 00000 n +0000004884 00000 n +0000004969 00000 n +0000005070 00000 n +0000005155 00000 n +0000005256 00000 n +0000005341 00000 n +0000005442 00000 n +0000005527 00000 n +0000005628 00000 n +0000005713 00000 n +0000005814 00000 n +0000005899 00000 n +0000005965 00000 n +0000006031 00000 n +0000006113 00000 n +0000006179 00000 n +0000006262 00000 n +0000006328 00000 n +0000006412 00000 n +0000006478 00000 n +0000006562 00000 n +0000006628 00000 n +0000006712 00000 n +0000006778 00000 n +0000006862 00000 n +0000006928 00000 n +0000007012 00000 n +0000007078 00000 n +0000007162 00000 n +0000007228 00000 n +0000007309 00000 n +0000007375 00000 n +0000007457 00000 n +0000007523 00000 n +0000007606 00000 n +0000007672 00000 n +0000007755 00000 n +0000007821 00000 n +0000007904 00000 n +0000007970 00000 n +0000008053 00000 n +0000008119 00000 n +0000008202 00000 n +0000008268 00000 n +0000008351 00000 n +0000008417 00000 n +0000008498 00000 n +0000008564 00000 n +0000008646 00000 n +0000008712 00000 n +0000008795 00000 n +0000008861 00000 n +0000008944 00000 n +0000009010 00000 n +0000009093 00000 n +0000009159 00000 n +0000009242 00000 n +0000009308 00000 n +0000009391 00000 n +0000009457 00000 n +0000009540 00000 n +0000009606 00000 n +0000009689 00000 n +0000009881 00000 n +0000009947 00000 n +0000010033 00000 n +0000010100 00000 n +0000010187 00000 n +0000010254 00000 n +0000010341 00000 n +0000010408 00000 n +0000010495 00000 n +0000010562 00000 n +0000010649 00000 n +0000010716 00000 n +0000010803 00000 n +0000010870 00000 n +0000010957 00000 n +0000011024 00000 n +0000011111 00000 n +0000011178 00000 n +0000011265 00000 n +0000011332 00000 n +0000011419 00000 n +0000011486 00000 n +0000011573 00000 n +0000011640 00000 n +0000011727 00000 n +0000011794 00000 n +0000011881 00000 n +0000011948 00000 n +0000012035 00000 n +0000012102 00000 n +0000012189 00000 n +0000012256 00000 n +0000012343 00000 n +0000012410 00000 n +0000012497 00000 n +0000012564 00000 n +0000012651 00000 n +0000012718 00000 n +0000012805 00000 n +0000012872 00000 n +0000012959 00000 n +0000013026 00000 n +0000013113 00000 n +0000013180 00000 n +0000013267 00000 n +0000013334 00000 n +0000013421 00000 n +0000013488 00000 n +0000013575 00000 n +0000013785 00000 n +0000013852 00000 n +0000013939 00000 n +0000014006 00000 n +0000014093 00000 n +0000014160 00000 n +0000014247 00000 n +0000014314 00000 n +0000014401 00000 n +0000014468 00000 n +0000014555 00000 n +0000014622 00000 n +0000014709 00000 n +0000014775 00000 n +0000014832 00000 n +0000014918 00000 n +0000014944 00000 n +0000015048 00000 n +0000015153 00000 n +0000015259 00000 n +0000015365 00000 n +0000015471 00000 n +0000015577 00000 n +0000015683 00000 n +0000015789 00000 n +0000015895 00000 n +0000016001 00000 n +0000016105 00000 n +0000016210 00000 n +0000016316 00000 n +0000016422 00000 n +0000016528 00000 n +0000016634 00000 n +0000016740 00000 n +0000016846 00000 n +0000016950 00000 n +0000017055 00000 n +0000017161 00000 n +0000017267 00000 n +0000017373 00000 n +0000017479 00000 n +0000017585 00000 n +0000017691 00000 n +0000017797 00000 n +0000017903 00000 n +0000018009 00000 n +0000018115 00000 n +0000018221 00000 n +0000018327 00000 n +0000018433 00000 n +0000018539 00000 n +0000018645 00000 n +0000018751 00000 n +0000018857 00000 n +0000018963 00000 n +0000019069 00000 n +0000019175 00000 n +0000019281 00000 n +0000019387 00000 n +0000019493 00000 n +0000019599 00000 n +0000019705 00000 n +0000019811 00000 n +0000019917 00000 n +0000020023 00000 n +0000020129 00000 n +0000020235 00000 n +0000020341 00000 n +0000020447 00000 n +0000020553 00000 n +0000020659 00000 n +0000020765 00000 n +0000020871 00000 n +0000020975 00000 n +0000021080 00000 n +0000021186 00000 n +0000021292 00000 n +0000021398 00000 n +0000021504 00000 n +0000021610 00000 n +0000021716 00000 n +0000021822 00000 n +0000021928 00000 n +0000022034 00000 n +0000022140 00000 n +0000022246 00000 n +0000022352 00000 n +0000022458 00000 n +0000022564 00000 n +0000022670 00000 n +0000022776 00000 n +0000022882 00000 n +0000022988 00000 n +0000023094 00000 n +0000023200 00000 n +0000023306 00000 n +0000023412 00000 n +0000023518 00000 n +0000023624 00000 n +0000023730 00000 n +0000023836 00000 n +0000023942 00000 n +0000024048 00000 n +0000024154 00000 n +0000024260 00000 n +0000024366 00000 n +0000024472 00000 n +0000024578 00000 n +0000024684 00000 n +0000024790 00000 n +0000024896 00000 n +0000025002 00000 n +0000025108 00000 n +0000025214 00000 n +0000025320 00000 n +0000025426 00000 n +0000025532 00000 n +0000025638 00000 n +0000025744 00000 n +0000025850 00000 n +0000025956 00000 n +0000026062 00000 n +0000026168 00000 n +0000026274 00000 n +0000026380 00000 n +0000026486 00000 n +0000026592 00000 n +0000026698 00000 n +0000026804 00000 n +0000026910 00000 n +0000027016 00000 n +0000027122 00000 n +0000027228 00000 n +0000027334 00000 n +0000027440 00000 n +0000027546 00000 n +0000027652 00000 n +0000027758 00000 n +0000027864 00000 n +0000027970 00000 n +0000028076 00000 n +0000028182 00000 n +0000028288 00000 n +0000028394 00000 n +0000028500 00000 n +0000028606 00000 n +0000028712 00000 n +0000028818 00000 n +0000028924 00000 n +0000029030 00000 n +0000029136 00000 n +0000029242 00000 n +0000029348 00000 n +0000029454 00000 n +0000029560 00000 n +0000029666 00000 n +0000029772 00000 n +0000029878 00000 n +0000029984 00000 n +0000030090 00000 n +0000030196 00000 n +0000030302 00000 n +0000030408 00000 n +0000030514 00000 n +0000030620 00000 n +0000030726 00000 n +0000030832 00000 n +0000030938 00000 n +0000031044 00000 n +0000031150 00000 n +0000031256 00000 n +0000031360 00000 n +0000031464 00000 n +0000031568 00000 n +0000031673 00000 n +0000031776 00000 n +0000031880 00000 n +0000031984 00000 n +0000032088 00000 n +0000032192 00000 n +0000032296 00000 n +0000033626 00000 n +0000033660 00000 n +0000033694 00000 n +0000034311 00000 n +0000034360 00000 n +0000034409 00000 n +0000034458 00000 n +0000034507 00000 n +0000034556 00000 n +0000034605 00000 n +0000034654 00000 n +0000034703 00000 n +0000034752 00000 n +0000034801 00000 n +0000034850 00000 n +0000034899 00000 n +0000034948 00000 n +0000034997 00000 n +0000035046 00000 n +0000035095 00000 n +0000035144 00000 n +0000035193 00000 n +0000035242 00000 n +0000035291 00000 n +0000035340 00000 n +0000035389 00000 n +0000035438 00000 n +0000035487 00000 n +0000035536 00000 n +0000035585 00000 n +0000035634 00000 n +0000035683 00000 n +0000035732 00000 n +0000035781 00000 n +0000035830 00000 n +0000035879 00000 n +0000035928 00000 n +0000035977 00000 n +0000036026 00000 n +0000036075 00000 n +0000036124 00000 n +0000036173 00000 n +0000036222 00000 n +0000036271 00000 n +0000036320 00000 n +0000036369 00000 n +0000036418 00000 n +0000036467 00000 n +0000036760 00000 n +0000036891 00000 n +0000037148 00000 n +0000037169 00000 n +0000037264 00000 n +0000037366 00000 n +0000037386 00000 n +0000037526 00000 n +0000038433 00000 n +0000038454 00000 n +0000038567 00000 n +0000038751 00000 n +0000038772 00000 n +0000038912 00000 n +0000039524 00000 n +0000039545 00000 n +0000039658 00000 n +0000039847 00000 n +0000039868 00000 n +0000040008 00000 n +0000040967 00000 n +0000040988 00000 n +0000041142 00000 n +0000042453 00000 n +0000042475 00000 n +0000042624 00000 n +0000043647 00000 n +0000043668 00000 n +0000043808 00000 n +0000045046 00000 n +0000045068 00000 n +0000045190 00000 n +0000046850 00000 n +0000046872 00000 n +0000047012 00000 n +0000048585 00000 n +0000048607 00000 n +0000048729 00000 n +0000049262 00000 n +0000049283 00000 n +0000049396 00000 n +0000049590 00000 n +0000049611 00000 n +0000049769 00000 n +0000050825 00000 n +0000050846 00000 n +0000051009 00000 n +0000052577 00000 n +0000052599 00000 n +0000052721 00000 n +0000054153 00000 n +0000054175 00000 n +0000054338 00000 n +0000055861 00000 n +0000055883 00000 n +0000056047 00000 n +0000057308 00000 n +0000057330 00000 n +0000057485 00000 n +0000058483 00000 n +0000058504 00000 n +0000058650 00000 n +0000059042 00000 n +0000059063 00000 n +0000059176 00000 n +0000059384 00000 n +0000059405 00000 n +0000059554 00000 n +0000060046 00000 n +0000060067 00000 n +0000060207 00000 n +0000060588 00000 n +0000060609 00000 n +0000060749 00000 n +0000061244 00000 n +0000061265 00000 n +0000061396 00000 n +0000061841 00000 n +0000061862 00000 n +0000062017 00000 n +0000065112 00000 n +0000065134 00000 n +0000065247 00000 n +0000065416 00000 n +0000065436 00000 n +0000065491 00000 n +0000065596 00000 n +0000065740 00000 n +0000065846 00000 n +0000065966 00000 n +0000066075 00000 n +0000066224 00000 n +0000066334 00000 n +0000066441 00000 n +0000066599 00000 n +0000066710 00000 n +0000066829 00000 n +0000066980 00000 n +0000067084 00000 n +0000067188 00000 n +0000067365 00000 n +0000067474 00000 n +0000067631 00000 n +0000067737 00000 n +0000067854 00000 n +0000067961 00000 n +0000068119 00000 n +0000068229 00000 n +0000068356 00000 n +0000068481 00000 n +0000068602 00000 n +0000068721 00000 n +0000068889 00000 n +0000069036 00000 n +0000069186 00000 n +0000069334 00000 n +0000069488 00000 n +0000069636 00000 n +0000069780 00000 n +0000069930 00000 n +0000070078 00000 n +0000070226 00000 n +0000070374 00000 n +0000070507 00000 n +0000070628 00000 n +0000070746 00000 n +0000070880 00000 n +0000070977 00000 n +0000071077 00000 n +trailer +<> +startxref +71305 +%%EOF diff --git a/doc/idd.shtml b/doc/idd.shtml new file mode 100644 index 0000000000..219d6a3f1e --- /dev/null +++ b/doc/idd.shtml @@ -0,0 +1,1250 @@ + + + + + + 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 +
  • RFC 1179, Line Printer Daemon Protocol +
  • RFC 2565, IPP/1.0: Encoding and Transport +
  • RFC 2566, IPP/1.0: Model and Semantics +
  • RFC 2639, IPP/1.0: Implementers Guide +
+ +

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>
Surrounds a class definition.
<DefaultClass name>
+ </Class>
Surrounds a class definition for the default destination.
AcceptingSpecifies whether the class is accepting new jobs. May be + the names "Yes" or "No".
InfoA textual description of the class.
LocationA textual location of the class.
MoreInfoA URL pointing to additional information on the class.
PrinterSpecifies a printer that is a member of the class.
+ +

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
AccessLoglogs/access_logSpecifies the location of the access log file.
Allow-Allows connections from the specified host, network, or + domain.
AuthClass-Specifies what level of authentication is required; may be either + "User", "System", or "Group".
AuthTypeNoneSpecifies the type of authentication to perform; may be either + "None" or "Basic".
BrowseAddress255.255.255.255Specifies a broadcast address to send CUPS browsing packets to.
BrowseInterval30Specifies the number of seconds between browsing updates.
BrowsePort631Specifies the UDP port number to use for browse packets.
BrowseTimeout300Specifies the number of seconds to wait until remote destinations + are removed from the local destination list.
BrowsingOnSpecifies whether or not printer and class browsing is enabled; can + be "On" or "Off".
DefaultCharsetiso-8859-1Specifies the default character set.
DefaultLanguagecurrent localeSpecifies the default language.
Deny-Refuses connections from the specified host, network, or + domain.
DocumentRoot/usr/share/cups/docSpecifies the document data root directory.
ErrorLoglogs/error_logSpecifies the error log file location.
Grouproot, sys, systemSpecifies the group name or ID that is used when running + external programs.
HostNameLookupsOffSpecifies whether or not to perform reverse IP address lookups to + get the actual hostname; may be "On" or "Off". Hostname lookups can + significantly degrade the performance of the CUPS server if one or + more DNS servers is not functioning properly.
ImplicitClassesOnSpecifies whether or not to automatically create printer classes + when more than one printer or class of the same name is detected on + the network; may be "On" or "Off".
KeepAliveOnSpecifies whether or not to use the HTTP Keep-Alive feature; may + be "On" or "Off".
KeepAliveTimeout30Specifies the amount of time to keep the HTTP connection alive + before closing it.
<Location path>
+ </Location>
-Specifies a location to restrict access to.
LogLevelinfoControls the amount of information that is logged in the + error log file. Can be one of "debug", "info", "warn", "error", + or "none", in decreasing order or verbosity.
MaxClients100Specifies the maximum number of simultaneous active clients. + This value is internally limited to 1/3 of the total number of + availabel file descriptors.
MaxLogSize0Specifies the maximum size of the access, error, and page + log files in bytes. If set to 0 then no maximum size is set. + Log files are rotated automatically when this size is + exceeded.
MaxRequestSize0Specifies the maximum size of HTTP requests in bytes. If set to 0 + then there is no maximum.
OrderAllow,DenySpecifies the order of Allow and Deny directive processing; can + be "Deny,Allow" to implicitly deny hosts unless they are allowed by + an Allow line, or "Allow,Deny" to implicitly allow hosts unless they + are denied by a Deny line.
PageLoglogs/page_logSpecifies the location of the page log file.
Port631Specifies a port number to listen to for HTTP connections.
RIPCache8mSpecifies the size of the memory cache in bytes that is used by + RIP filters.
ServerAdminroot@ServerNameSpecifies the person to contact with problems.
ServerNamehostnameSpecifies the hostname that is supplied to HTTP clients. This + is also used to determine the default CUPS server for the CUPS IPP + client applications.
ServerRoot/var/cupsSpecifies the root directory for server data files.
SystemGrouproot, sys, systemSpecifies the group name used for System class authentication.
TempDir/var/tmpSpecifies the temporary directory to use.
Timeout300The timeout in seconds before client connections are closed + in the middle of a request.
UserlpSpecifies the user that is used when running external programs.
+ +

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
AcceptingSpecifies whether the printer is accepting new jobs. May be + the names "Yes" or "No".
<DefaultPrinter name>
+ </Printer>
Surrounds the printer definition for a default destination.
DeviceURISpecifies the device-uri attribute for the printer.
InfoA textual description of the printer.
LocationA textual location of the printer.
MoreInfoA URL pointing to additional information on the printer.
<Printer name>
+ </Printer>
Surrounds the printer definition.
StateSpecifies the initial state of the printer; can be "Idle" or + "Stopped".
+ +

External Interfaces

+ +

AppSocket Protocol

+ +

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

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

Internet Printing Protocol

+ +

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

+ +

The URI method name for IPP is "ipp". + +

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

The URI method name for LPD is "lpd". + +

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

The URI method name for SMB is "smb". + +

5 - Directories

+ +
+ +
/usr/bin +
The cancel, lp, lpq, + lpr, lprm, and lpstat commands + reside here. + +
/usr/sbin +
The accept, cupsd, + lpadmin, lpc, and reject + commands reside 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..8a711ba042 --- /dev/null +++ b/doc/overview.html @@ -0,0 +1,292 @@ + + + + An Overview of the Common UNIX Printing System + + + + + + + + +

An Overview of the
+ Common UNIX Printing System

+ +

October 4, 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. Printer classes are collections of printers. Jobs +sent to a class are forwarded to the first available printer in the +class, round-robin fashion. + +

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 cupsFilter entries in the printer PPD +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. +Each filter has a relative cost associated with it, and the filtering +algorithm chooses the set of filters that will convert the file to the +needed format with the lowest total "cost". + +

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, +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 GNU General Public License +which means that it is basically free except for binary-only +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..856b4821660ae2173f9b1fcc7b0c5a9159e191bf GIT binary patch literal 20469 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

e|o2c@d8qB-g88-`V9WwDBHWv)HejR|3=D${@fG z0L+U4d1Gk1=ZPPgWe0!m?@avs+Q2x-cR?09)1vZFZRFJz%#5HiBGtx!_UdEr36_s| z10wfktlwASqIz}(#a>5%)2ISJjP}vVJ2Bf9mln-2aQm?E6>bIuqHKTSMhsi+#HIC# zg_-CrZ$9wW@R@By@KBuFCvfR?eSe^rcxQJ1K(43wBJ1SXbFRT5Y4@y}ckDuO+K$#F zX%PURifuf~G6P8J;S7^&b?q7C!fiy}1?-o|V{9&YfGN~KsvmPbGnh7eg!blEYM|PA z27zslFo4k2x%;a*@jGo>LDW78+PPX1%q7vYSEUzzSWL!s+~3(sE^yYx1n{oB@~sO% zhs=*2z9R(CeRuD^(Wt7MYdQC9nIUe*^&yTG-t2r%~?J({$ywM~j?%o(l{h zWBYSGYaiP6f_L<5J=;Fh#-wMwdPRdVZ;M#H=U6ev@3j|Bh$+WOsuD5T9nmW_UR+5Y z%{gG45(ggKi)LVU@g*~F4U8ByKoaTzWdd!&pN!g0_=EH<^F=3vxTo_ zvFm|4r7w;oUEbot?GO~@#z%>tUe`Y2_NFZ>3^RVq9@mxRXe*{h=)3Jp!xMfq&sbQK zm@n3r{j82kth9RU_7o5)@XpI}yaTRQxQ$g?0aa_=#E1jN^H_gSI?x7MUoaQhjU~dU zl?vly!d|m-8Q0Gj#2_tegOw+uzmLQrmsgXj(d#bW9sSFn0^O#12e`cY=^o3yhg2pW zEW~~Wttm$8S{FHdpU6aI1=LQ6**3d;&&;)pp1)Zxhs|3A)xrH9fScuo%&{7PO~QBf ziC_uR1%1piw)j$N^nw*INqfH!nHxO^0@j4Lb7D1Hb;O39>%%5-KhmbzymjpMQGvY1~5UNW=6=U)7|9j)+7o+`Wm3#)qen4g!vA1vHH$0Q!- z<~6BqdpR6WxW~*h?s7~Yq3{C3BgY9w2!-(13y<(SV&Uh7KeI^@rCwIYGuY3P7Df#b z@!llwye;l5ekS=1!OQ2xT`T0g!BqG0i#jvTeZ(j3yiMyodp5a&@a5Uj^c*>b=EU35 zWn+TKTNmG#-DT-9ua|!HaX*}4xtZ3ZjoWnUT8X- zXBEZNVvX^az7qiwg!U-0YTO-q!XbxiJqD;y3|a&3ejwsty7gS(=vsv5C&Q~}pj%|B zQlO@lqDE7pD@h=dhGkwntC|n_(Fw6C3rfU+&xwaMAb_R;-5TOyi=FDP5MuQ(W4wC# z2sRFi+X1_`B*)n9=BW8wvQ-c(N|89RW^oZaoJk*6qqW$=Qr)4y<a%p=YN|!sYPye#U&;xZ}fXzigq&@DxQTHtw{s!^Hl2oYPmdX8u*pV0a}lZ zUlE#cWq4HSCWw(gGe$`$s|@vObyQLgQo%-nA9{I)xD7-A^cHftlH`RFMYf2x`>Kw_B;A4ZT!d23D{$iw!z;76s2J z8Li$EqzCjrGVUj{8X!oQYJ1LolND-t(cOX0EMbwbEG)obp6VM5o?Db&F;mPlTB(k; z0>`*Va-z3hTmyM^8j6w;``$wv6-)igSxUHySDe7Pw;0+7Lu3^%!|2mQ-D-?#>hMoDS*c7y)n@2>Zm`K&v zEW2y4Ykn>jw1qcX>iq|PY`l-nt-MuPx&vxfapt=|H4}-oE&t@f$|rTd`g85j#p#gi z{N}0*!f7LlJ;lkLT-gumRh;GV>SGgM6I{fGP@Yp?m=b=%(X~n*61{!CbUrOI*YnCp zJfhd6%tdA9%|w#iX8{966b(>|AHHWEeFCD#+U&IiYfWw!@vfcS_Tb=Rk|!e!A8{&T zaVkz6g-*TSv@Hp7iPlv+c#_=J@61&8Q!*o`o%6tvA^;QBOxrB~ETp+?w_K{eshO#a z_m$8!%7NXH)>c!Mu{(#o-xnW=$6jXyP;YbywKJs4OxR9ZdRdYUjmo~3d@w6|ue~fl z7&S~bbbd|su!>c5dve?YX_#iO6;cy?IVRnA!dW7|sB+$wLvnt>=k<8dO+TUT(KT!5 z?}HKpU;tsKpUAwtL$%5+Fe4GzCrPTqbGrI1V_C*U%oJf~%~t5_1#L#a6}st<&QW)U zJ}4tAEj7SIH^5uZ!$`ZDN0z@l-N@C(aMNRSSCa(jOWrXfrm!k6X=3xeysA8%smK}3 zsd{f;ThH~3Y_?#J6*!}bBD2Ls%5`#SVJ#rjE$WFd)P&l~1h;H05d7i@*4ROk!|u zL{UFw)=RgTIfhJuJFT@bMTrr^r<#~@wR8R*nq3hA|~i{K(L)p+wK5(j>%P@^x_U! zE>$RXc?DiQ){%Wsd!7ee;^`K>vwaQOxaAuCIZRNxV%oEE2Jol>*)|Vtg;RP!!6m*G zsSOCskC~+C$5w%PuWk%ptO8$J?vMDmCXKCjf)@mMdbPsqu%AOH0S-0+HCtaYN#((% z^XJl-Stoyf`MNPt9hc)Q+?u`?UE00f=FRl--CC^wqtCVhK^O$4ufBHNb7*3`CS`PO z`{#V~p1R&!apl{GL}$(%9?l@Q=1Atwo;hmAT1+BFG^m2QZAID}`BLhe6?S{%a$)}F ze6`5ig*=sk7N5?&6t|iDd^LG*bv@mh(H)9ODZDZ@{s7_p=DYKld35w5BJbmRkArH+ z1lz+8(6M|~fA4#Jd+IQjl(9sc#L-rl=u*0IDHc`7mF@6=1v5m|)qKj}HwWp?YV&&Y zZV%T>?p>GL-|tG8xi7S{mjk_fJ*Rc@=3}Ya`Dm|JeynEBB+7u+c_TNHuoIzp0|P zCA{}5%R8dQ$9sc0FZU8l^?VtqIeDJC@eM=ySs{6(4|OW$ zl`l6m;E&0pQ`c@-QUgJqL9RdEa@iagR4qypyvU+ir5l{{XI1 zZW!s2?B(=Q~tp?P%uTNNJ6@S_wCc(>)+xw7oi$mR*cE&KXgurtk@i?7E4TJ3MuMv6yyZf>=8@H+WwZQK{_ zWbPOvd~43}{iWKQuNBsJCk$OFN?sYma|(Y#E@cfT>ZK413mNeDW1sf^7@GlJs?Er| z_rCn&R^pqah4jw3%+IEuWiSmk>ld5-gsx~4G8_bLGhEYt%rY_7vf=w9^lTQ_xM0wA z--{-;BybL5)5J&>IE13#L2b4=g-D7A;O5D=!FxWflObbkIcPhfR7OlWhQn0)=c~to z%OBL%uiWD)Z6u)TLlZ4`4fY1tDIw1V3p~G=7RlRm!Fu7oe*?)EQ-$o6FNzz(tfL)w zy(`}83~Nuf#SpRG_pCOp7w0uDIKRmBa5{nCzSogC;GtPP!=0_%(I^uiy)Rk$&q4Ey zpCrW{=Aqj`6Upl#8~TX#&!0Unetf6%mA-?cWG<2sMX$A;8o1cYtn@9Kon*Ur0ln zrt->E+D&~499J)&UFr|RFMAQOM5P>C@=#FFL~k%!!MJ$mek$ps>`-d#d;wbQf-?O6 z_Q3@7Yv?+in*4LQq32(CE|)4kmKxTe)CO~`^<^9yMj`5*@hH!|+KXeu-yX1gso(xK zK0KL@@K#7{iqe{!54_p@$yj9osNj7CJ6~*r2QP_Uve_HEGY6|VlTsW%S61+qDk_8& zD-5XLeGj>pPLpnUlb`Zkodg`3SCZ}s;RAQndwvyIZPkMGzPS=xO?IxbiY6|;aMt{K zIfAiTX|F#enSOxY(14cCr^x28H4$X4kqar0Exh)1x6GDno(1`S4uK9VqNKPItZ8(G z@oh^(ryN{d=gY@39)3IRVu-F}_uag1lM=Hew|<{2Qu#!gD>>dxT}!Tb!|f(`_kWoG zFq~0WnJ0zey;RRoj3co>AdvPj{0S;r+tg^ayUvhFVj+D%L1%=Rlg|a!pdEIn9__4- zv%nv@cz!_>sv6o|Bsu#*W9kz4d}Eo{nOcl&gbC_0Wi3C0x&Fnr12@R$(3b-l%9jEW zo1c@U9yhHhexUZiJ`LBlAE)@f;qI@ zk)f7C@YrIV8q9F%`s2G%d{piG3Us!Nbqt@R3$$}?yj;7Z5B@3EH2!+oo`F2EL;b+B${F$O>+cT!gdj|) zha}PMa5K8+I7(x)%|f|Ep)NEJC0rCL^{e+3%Vzn9uuWu&GYKhN5_ih)c6M28>BXhUBAl5D@Mm|L=HCv}n~Bu1bA@?(l@HwImG`z?-?x66P1Z3l^@w20Vmq3C~c zzhCVC-TnT5b({as8~b9XZtRQyZ*J^&-5AlhP|sKlM&4;0+w;EpuBsRZ{CnoksHEtYa}F+U3mtysCfcdQbYHs&{^ z)9tQ(vkk5e4n(3_7|DYUBVGV7?_JIJ-|V$8puc}W5#C<&D(dr652?Q_>-FdWGDn!& zE!4e$FF7^&$tHd;XZpj|+1JU&+R_)Zi9hlr`;esE~O9Tg)rKQ(-mt=O2 zs|SrstUF;1qOZ!!)jrFxFW7TQ4}KYt-}tzt!?8cOF-5O?_IWJBJ4=L4_rVI<<1^8d zqIqxS{@t9_jryP0rYI33H}((4y^Boe*Y?t9iwdD;tDhHVi;6aHysMM1Dfzl%z4M|= zcaZY))l5;c!Z9&;p#?tFZwxx1SKiCoH9M-$lW!U{`3hU`HTWSbB5SJ7>&r9`{n$+X z-3AZROOxX-cY#%`c1~hbbry1EDW-=VYgTpBFIPA6x?ChZOJftdXtSl=zJzgX_FbuH z;Vb5&+fdJU**p7lquH{ip^s0&Eautl_MWi+7>ZDWZg0P5WoSSBqHH|fstkU<{0eH4 z!qdFEvEGYF?#ri9Yod1P;E|z6FpW3SpF$SHtBeXZAYI?JEF0~+mn|&Ri;X>^dWWO8 z%7x0pTz1CmQ@LZp7^_yMbvwjT0FKwM2AAi4*q6WgSuz;OSlw6ub{r8fH=5avZ=Twc zxbe_ySfkiY*SO%>*{kkTMQf%X(wrQx3HXM&hPb%Zm%!-;!!9RYy;g;9dbp7^->jXQ z;qqE$r9sPXXS@EfLgcHkH$C1gtRCHAgeuX2LtV?>`_*c_#iOreAe^)4ma} zjPjbC3e*`Z;jeg?pR8y{-?=7Kto9}HQ(xd$L1>#vvxN#~RbV#ELcVMbGhVX6 zxCkS#uWLAP`EuU=B1rD_#65A(pUM3N!b02i@Ad|5eK%LKefVByiWV=_*o0_of6g|e z3p7}r`|&xLr{rQp?Ee0`H+xq{QM@@Ta5ZgfHF|gbc@XCu>!Cbsqn>e?=Wu?}W$Pa6 zcUW!E*M^z}ml{Y7{9eMTAEpXnF1He==R&PT%!w9tKXaV7pX)LpcT(RuF|*xN!)LJJ ztxM=F1iUa8%PV$hSE7h%(Rocj>t!Iez}V6*wH@99qNkVZebR8B*EHUlNi}5u1Fujh z-hiQoUQW*auwBk1uCk8vFHkcjzfNUW?!GM#uh!I`i7uZ6Gn!PwfE+0ebKzw$@EU||QJ;6RN zgTs}A{QCtTgw1m|_(jO=FDDUx>bOs6F)-ajW%%t`!5vjpr$h_qYQu+mmQ+m!!!bL4 z_}tx=c0)02zFl#%+&TH@`VF5|w)wDGgz;Gj+L9q z%2|dsarj+}2GC?W+fNN0x99P*vqofgtm5swrNo;0r?6?NxzkKk)&rEI3`k&XDf`7HU z(KX1JSLz2SoxpGh09vnKAPCdh?U)(azNZ!mjZrturrs(u{CJ;Qk|Hil>c?9-)!zG` zj49$iBEyPuU-~rS(0VizS>;;!Pp#=(bPm;Vo2DQ5H*m;jjylI^(4J=<*1m6s?ZP zvQ5B_Sd(qLn6IH2J?sn}nt^+aSWYS=)aI_S1I7DU=`2INw6KV5*TY#NK4HKmq`g@4 z{V)*cH<2qzbfZ-H@bj=Qt;Qy7=V5190n%+RUuZHc0ig!XH6Q9{F>g)I`rqNTI-diD zGSb=@W^z2x?KNPE_KV2&{TUS~pgqS&&-r1GHg@K&2d}=Np#wjhn3XST_aWV=0&k>j zE=SHeW9qxjUdr2i_9~G-Xn5K8Xr!(DE=%~RE8EcNC~=n0MG)HT@vo<r2s zKYbhhUB*qIPg?M#v)n^kSSGBs6dYMMRVDMwd3Nk21KJV#u;P967fK>U#}_>B?wNNW zH5itB^WoED z^Ah*hTx7PB$!)$>yWiBDh^dPFA)S}_r6h7sE$15N>WhpA0YqZl7?TRo6hX3^qX@^Y zlI>&uST|*@X|3FT2*vTL{GI^8C`C5x2EU3U5L#he7os4R$6=TbJ?5Oxt82JdXBJ|Q zYwED_ZJC<@ThZrfm9S4*0)H?P*7xBu>7wgJdF1q2-O7@_Gu98_P|IFnGKn<8=+ya; zu-(3II<8E09z4~U{xMaf+b4#_Go z9=8B9MK1)Q&?V}jAn3C^WdSd$9=jDz=bXVPR#Q(NF{d@99J1_Z!bCBw3=bpo+7vbL zU0lze1*q;Maz5+c&Uuz6peoj7cUjetx`=$4d>CwDb|>soGkKdesbdR0`8*%JPi#hyfuTTj zbylQYvvA7~no#Ss4(@BAk%9Pm?LPB-f<`E9^#wQjX}m}ION2f2^4vTOXf^$l8bw3r zzJBg~pV=|lbD%A{*gfADXz|w({cCu)PHywsCS$fgR02-~Lzl=UWVn*sM!zv$iOEw9 zX+D4c$F~Ed#~S)hKXl3KN3tBJ7c%5-PX#n4m!c~#3;6!yScF=Q=>b=+?gh2J9Q#jq z2*nsT+f~lyX_3c5dDEHo>BaAN7BpHdIz7A2cmV=+cfvV6LLzD2+7c0XHt z=2sg2_cU$7H1bWwR317#66PmuGpV3m^*~%w6}L>&2&LgGF;eAxukYkq3hNCX0@vAK z!y&KoJ{fZN>h*lcgDweXi}V5dva=#_glW{#uO-$V#=HwrpBBWFlNUQXyz>L_LZGLsIQv+V#lnU z>i!aStcLA8N8zZZztbDPvvy&IXqQDkh8~Meg+ovG#y`3(aW13o{VBy2REvA@9=urws_C4hGY4aZ0STE0@ z(d}mm43sOa73BWv&+nXI$q%CGuOg~lmbs&H=k;JfD8#XYIS5+0Y;x1EMi;;eXItcT zy@D_PpsR_)zMKJO3gyCTlFC}}jUv1;5p;`7XXxXNjasy|-}yKzR&GbGW?&roh(W^Qz zBFOJ2l8KV%xlEI^ie@0_71n+sa2PuCU9up9-Pu-|aqO_4>AQ;(lf_Q++~C|r3qZ~M z>2unzzgou~*u*7&3nl)GbDHFTKBxURe}WBEb7Ye|eMpl$bx4!?&xf=O^9JOo1Xb;x zfUumjXp(yy=F>OscRo2fV}*{8JR(~*s-%QlXYg+sZS4e-CUB^>eXh8t?Cx-5V|#71 z`N!gLg7x%d!g$=!*8Rx+PeDOG-@hf2BZdMZ?`@2G3Oj6mnz<*gUCGZ(+0L;2wBj4< z!leDp#;``GQPx-@NhcXwZElKBX-@i+HD7NJ&zH8Do4m=90YASH%p8jtw*L}+eoyvs z_x&_D=Xm5)NaL+DqBVN;`l{*Dkh3$M_e8R=JA(JLAtoVPba522{=VT$rb#g z=Cy8q7RLO2NYnZDgmFcWU> zJEiaEj_q(VyI5sH@gxq9?_zw8OT6^;hsEoklpavr<=Sx@3yw-ubIkY_Xh}10?$%Jc zFYlGsx<*JA7Idv8T1kL<^+se=_|vB>_Y}$4IA@k+7X`T9%lK;46@Y8VB-9CRpItYI zQP6o{+CFlXiP}Y0oD<&;$f=r3RMrd_siZysmN%j!i~Xt&xv(6Zk}UJg${uR2fB6EK z+xyZq^DEo^ZK?GUqa@~{?)ZD*mrs6`iS)_Qz z{irunIo8&)S7^hvzG=_p`qs!;#wOnv!{3e=2Imrqa40XS;BSVpSU;4TxSr+v%sWS^ z7diAo=}WbZW%%r)$jVAFsy>A{4{+j*CJ8$aTEc)7P3>*I?*!%V*(UTJSB@uThmeC` zpw9XQX*uqZWS2vggp6#@+k6S_<$uF;X3(E8otiwDZc@zcp@J7kBfAJx%rfmmb<-e5yTgCF_a*A!iuL>h&jlKvAM4%x7RUfi=M@nzw>8G1izGp zdA8ow!TGUg*>~SqZTY3QX_@#e*+YBm0$`aXSveUY3KCL@L;A`06W~dYeVBT?v#<_@2L;YqQmrz~b-G`!(a8%ZPdNG} z>TJ^pFi;zY*DUao*9iTP*E980DsYkgQZem>%z0w`0pT=cwG*P^&i6>(^qmgG!{`PZ^RvTfG31V9vjeJ$~Rd@)af5;39vzaTyQ~+r5oSD zQHO+o#t^bvR#fLrvM#y=XCB~RTfP=`dQtfG%n*r)C`jbDQ2KwrD2NIFzg-mm_FRtm z-yfJ2{^!adCi0(GhFCLQ)Tk6$?V`C|fR>ASp_9zZd&Yg3^e&yM)!2+q7GxF|uY+c(8+>^TwPr2MR3Le$@ZcC}=I*snwbJodWCRc}IuH>oL2z#8AlQ z+d)9sx!cm2eWpFV=4VFor!E%zisD8&2^l zPo-A$cCI+%yJ=0LXU#_TELD3qItBHrTLlWZ-d%~6i)!P5)LHRG`aQV=kLKBa9k2U9 zhxZG&=jxq0?s?|Q(y|xI735DP)x0uQ$a7ol8B1Q`jald~8HL=+R83Uhe@c|nmguF- zb=KePdh|%u$2)uzyzjdi+}yR6Ta|4DD!g*CLw2+6FX#`s+FWG!*(+?9vQ6dSLLMG$ z+uj!;>HB!0hVBWm{pd@BECrd8b3q}Mc5h$QlWLp!<~hOwhTC!tb~y?v*rP|XVo3xH z7hOk9>L0vCRNuY1YhGE$A-0VkBV?|~$zvNZd_6KVVZy&$RhIaMAgV32Gp^4!V*~-> zw5>Q?yTnb{WTnw;6lQfXJZp}|sIo|GETAr&@gr0-;f25E)CXVnp=6LimQuM(1-q$K zltJPLlIZcf8(fVkln_fT-FeElA&*oA(!>{O8}TxRrr0yl8wfc^q?hnXz$j^N zsGW0!Z(GeXf9!+;L6pYRFNG&fJ)L!JTrxGjn7b>yKz4Um?))fJlwsd&T`tY=mLLyb z77lfTVP~flX9$0mA$5(jQ(3YelgSVUGdREoH%7{t4#On0XsJ0M>6P%~U4Dt}WfL)Kp4xj|%$GE}^jzH~Vy(uRE}~>I^xF2E zm?-s|y=w|QB3JvoXc}~=&Nmh*3rwn^$mo@u>9$-nGfz3^sHFQx(>tHV z6Ku;<^U%#bz0(sxG48zaKH}b`gV9eI(@B}e+5s_bEya{8m#3rigJuKowvt*$sT_{)%)gDvr8hT-tIqhWs35fiYI)T~;UbLIillx#Q_LX!#x8HwNTz zO_)J-aA^+)D>EWBLBIcrPpj{|Uqs8n6|^PPmc)a&ZEwQu8Tjzg0a3ep_l;ANoS4WT zlbo;!=(iB`UrchM|Nl*L$4{RAWs(y;HOYzn=SeOlxdAyMOck~s6m^YTw7k4tBCje{ zsZj?yHr4qpA=(u&rM9NQ3-1N zAVV?1t+jlJ#ImDnPc2!f$RNij5M#3lp6c`k>!uBSu3}s+}>xCufNa{r5xmL z`1mEQE_cQDOR#62kpH#=za~(`Tic|4N;Hcf@a-Z0hSAwCfz@4`?)7J#xrjE;mzC3g zftBs^q9rx=wA`zI};&gye`6KG?@-QloSr^G?T1X9q!7Cy``pm z)|`03bn^Xl%qnN`+z8Vr86}|`p*@N&mjfh7!p6%6#Wj+Qg4aJcX}mG*^_R1fjuJRW z;vF4Yur0Pibh~|-d;x|CEf>3{Q9xzwvYBjszx+41zEi@n!!c){{2 zFnXOQH>r0HHoErke>&(qIXyCd-4P=Z7Z?346aOy;hQxm}Fn$e#za96)Bu?>N@;~!k zNT-YBtuX!TVEx1#7K!WmFU)Dr0e_l(k*jkJeL0j8iC8a8qS8?MdgXkNa(1C8qdKW> zPUW5C4|(RMdLoRZORILD%U7j*Qf-L|m)~0uF5Y?P_Zn-*TB1KN>FHk;Ic^~TYWl);H4&2gN4T6kX#Gbi zkDu&j1D(tdM^|+0{Se-0pz-lHLmk&%-xC5?JpM+WUyok@`BeAs7wcnNU0jubrYMNM zH~Q!sa8SP-IzZfydPdLN19e^a_z`>+IXUaUbb>Du;!GmUCML~BBK-S@O#(*>aW>~a zWk>t5<16srGSCsCzsp1z8#}E}c zjZYMGx_+V{DTz}uQPIxVu_*7qtNC``yiYp~@iq9fa zI3k>qNuADDN?PQUOj;OpS_T4vPRqppB10qXVeSwl$ + + +CUPS Software Administrators Manual + + + + + + + +

CUPS Software Administrators Manual


+CUPS-SAM-1.0.3
+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 + +A - Using CUPS with SAMBA + +
+GIF89a¯ÿòÌÌ̙™™fff333ÿÿÿÿÿÿÿÿÿ!ù,¯ÿBþXºÜþ0ÊI«½8ëÍ»ÿ`(Ždižhª2€0p,Ïtmßx®ï + + +;±Ýíˆndý !¸ ž³wà…MƒƒY~¿{,gÚ\‚äé +Œ×Ø(tÙî!Ï=Ñ.ûz¯áџ:ì;Ã9qöíÉë]/¿ºÉ¤Et/†'Îþt9Àؖž_ÙÇ\|W•wArö¸Ý2Ô× +tN°0Tï}¡û‰$!‚yMxî)ˆš‰Ôø@nB°U½ÊwE„§!ŠF H L8B +c‰;ždŠ-æDVWdг€h±äړP¶%#(4Fiå•Ï\hŠ:Re!\ÒėX^¦%€¥À-$E€Ö/úHŽšlââöÌQX + + +¸1Nô¯b"œŠüjåÁÂE0…È8ö5GkZ|ÒÁwt„C»ÔQSÇo6Ôِ[W„$²*Ž+4Pb-8¹P1þ'8"‘ФÄ$ Cyê‘„)>ãŠtè`Ð3‡‹¾z"«rE'Âqfä°Ë +‘qÂ\|€„Ž¡ôö»%É(.—bڽȀíÉ`{¬EÇ1w’ »[Hß`(B6ö“  +†')ÊRŽÎa[ÃrbC!T尌 +2Q·ÈHZê#–®üË/àô¯FÝê(Û²% ºXË9öÀbÁ4f.ù-oý™XËB…IÎÒ7¹*@ÃӎÍT€hà‘ÌW␙Ã$f:µyžn†ó†r„'téKv` +Ç+dª– œ79sò|'=×¢Ìx¶òœÿ„¦œˆeÎ;*à$þ” IÝÆaÏ{–3ŽÅÁ +P“ÍS[ÙL¨3©òQ7éÆò#ãûô0F×ðsE°t§@‘ØQÜ´´ ©:3ÓRíd ¥*MITnŒ£¨H]ØQÁd +@òþ—¬rMœŽaO + +rë^yÀ·(¸îéêû$uDòrã/a,I.°ÙUÀœb hˆ`¾B ë" +Ü`HØxȸo1þ[á\8f^æ|\ý‚¢¢zø0(ˆ\ {ƒÄgäÞõ€çâ§Á˜0*\³n¼‹m¶/Äeª±ÿ†ì +Ç,½DN2€œº+ùÉ|í0L¡Le*ð¸Ã>­2ëf,eIPOËÅàr—±”80SAŸcFªatç»ãy¤¸ršçÌ¡5ïoõËsžï|¿8˙Φ¬þ,ï¼èà)ÁÌ;øk¡—†dDpÑòø2¢qfHã!˓~ٟ-í +'g:,æ4y?ýäP‹Z›ž#ÏÕ´Î5AK‰k]ûš›ÒKõ¯‡më€õzØÈƫ؎Ý>B{PЪ.6hf]º?©ÌIŽuO„íM‚ÌÇÜcµ3˜ +61‹NÒ[†W£ ¦m¿­{ÂPâvζKnUˆ[ ònĽ±÷n?l:Áž3ušë¬sP[ÿnn¾çP…WõÔFj[Â÷ +¹vÏ™à‰˜xú'ˆ£ÀÀ†p¸4.êãKÇ¿ÂÁ±o§¢ü"Á|Nk`îʘ + + +jl©ÌuˆËi™0pmC´«+‰÷6¤2­éÏe`(ŽJ]¥iõð3ƒØí"p|ª!:qøFس 6£ +@­,þŠqüぐoÌÇ®žÖüV“¶QǛEvî¹²É8ÙªS"æÀç‡x± àþ‡>—Iãg +ïÝ>Y‰çN80æ§ ±¾GLLìÕµ…(1Þ¼!8}þ¬“*…ª‰Ùì:e»´œ +ª¿ên_6ÂÃSÀ`eG;Ö„CƒCcˆ¿‡4¸yeî¯Í)oøByRm½0?íLîÅ`QÿjÓÙ/ºôÓN|Ý + + +þÙAÜŒÁ¸D5©D aævx ?жx°DM@•!h‰àȀާ® +• á×B`ð¤ªE?›“”Þdƒ"8$Ý`Ki0…OðƒnΓ±µvtžè€I([,¹Ndɨh\'6X +P㗊‰Éøt ¢‘¥˜¬è €ˆ†Ky™FˆŒë`š”yƒ„¨š €š‰ƒM©‡øFQhY„ +9¶X¯×–í4š¤™Y\)"¹AN]‰xéz÷Gq07)©ñ™•Y€r°ŒŽi‹ z ™ÇäFÍÉT–ù› +ËŽC œwI›üX]‹¹\ëY]þf lïYbj8ŸÈuœbŸÍÅtú©fÞןfBI—“*øé:ÛØUj Ò +ˆõ¹ Õp $(~ ¡Ú ¡gù{îpZI?¡ƒîÀv:“a¦˜6¢§Ô]Ý‘(ªê)!ŸÚ¢: +jwµ¡4ÚvíHÛǘ9ºXhó•üù£¥Á¢VÉ{Dº2š‰(°¤3š¤a÷ +У¥“p¢þò4Vº—  +E´¥è¤k°7ºhT*€¿èw`ڞiÄ …S¦Ʀmê Nêƒ#ú¢f€ xê†ý +8z©7uÚp{Ú=~]7`«h‡ÚsÚg:…zd˜ó§ÎA-vþAñr¦'–AÚ)9–š¢âSi;£…š 1ªo"ª +¦J;“º rº8Ui|é>¡Úœú + +“ë¥Dfný2»ƒ–0j«®»ºK;zë¢Íö»—!µ—S»³r>K+6ˆ‹¨XÒ»; CÈ +8Ê;¢»ÃÛ/Œ‹¥ž!¬s½VR½óõϋOâ[/çK¨þ˜Ñ:͋\Ý+ Sc:ï˞’º¶ë9Æ» + +ô 8ly$ +8©ÙÅmX2Ùh>—?¯!šHüÁ^LsP,Ÿ«Y‹âá¿ÿtšì‚£Y +r¦Éš¥9ÇjžÄ8-ÆÇŒ¶iêPÂbA˜ù‰Ã¸š»³7RœCWRoìŠå MŒŠ”åt™ Œ›réÉq + + +å>}Lê}ÎǨ 5:àŒ|"þÇwÐsøæNΰ¹#R>~-N‰®èƒ ßcðÞÚÎÑ¥®åGÎâ툉Ýè*‚¸ +=‚ž ºëⅭëÀ>Û·žën^žmèÊëð¼ã>å×Λ«}êØ÷ +“Œ¬ËIÁ·AÔNÍëv>]t.âÚLЫþíï¾ñnäÖÜæs¹¿±â°+† +¬UØïî•.ç¬ÎìÍ.è´ÞŠG=ðù‚§ž¯”ë^äÛ®êh-‹êê!i!ÕvMíiªîþ¾òîá/þÑ-OÖGð,oñº!å’gOâ POìOôBþÈàhâ+?ï>ßÊVHÀsaõ™€õ$óSîõ—»ó8.žß¹ +~áßÈ©ö»]ò3ëÆt_÷[ïôb¯ç‚Ü÷Õ«@u™ð;zܘ‘Ü@óŽ2’?ùƒ¸ÙlùF ¶™¯ù›N ž0œú£¶¤ÿ0#9:ß§½ž©Ÿ\#ÃÙæó2é+û‚ÀÓ¸_äM/ÓtaÚý3”]Ù«¿¸iîaF>ª}ŒØvÍïMÍ÷Ðëä©îr܌öqñ_ÀüªrâF®ò +ýþ¸—hT_ã4sx”ýÝî)ç.QgûàŸÏ%ì‹}i´ASû|þð@QÜ +$J9€»-̱÷ÜôMؑhZ˜¦:°œ*ÏlßxÒ|ϼ¡ÅLÀ ¬Áfù9BÑdìÁ|«VV„¢“énKv + + +kB_ƒg 3ʳ8#Þ¬L=0;J¤äÈ@¤F|'i~±© žaʊÆg;d*3²”©bPÏ¢TäHô¦?[† +ÄäƒhN6ZM¢D:c*BR!$±ckƒ’V­-uÛ@[øp„Ÿ]¼8ö-1{TήWÏ2ñ Šp=¸q«Ñ½es.‰„4+#Ëe¦¥W5µekxr䛓/X͚5Iǃ=kÝúµì˰ûN–2qÅ¦yZ£QŽ›ÇޝtxŠäcK—Ííɹ +iþ¡9¼m1oñ¢©/²8îìSté4l’Wm¾9óéÖÛÐãã{{üzÞ¿çøêöÞzà}œàL¨ "˜ +ÄÐsà¶PGLUúå`MÞ  ¡†9¬§Û{pX¸¡wÚw߇¡¨ ‰í "MUXNx + ++l´á¦ +j²F:Á.êÆÛj¤³Búî ¼Ê«/£Ö’[н#í+ð¥ænJÞ¸«æ;ð©õ‹¨ _ËðĊһ*º? +ƒÂwœÃyzh±°Øzl2,#oZ2țr|ò˂°¼$Ç)ë +óÍÙÔ,éfs€1Î@/øîÏPõÌiÐH·ðÃBkLtÒP¯bôS;NÝWÔXÏ +ó’dlÍtÖ`°tžOc óÅa§}Aě²1vËjÇmþu+`ÍÍÁ·qwü6˜‚ì½sÞXŸ¨Ë$xM6àP³-iÉSÚ½Aوïë84–ø=xä8^!ä*L>ޘƒk¹Œ({Iè^!ḘN$ê +«®ç!ºû‚ÿÝ ë¯ßoî—Oü¨¾ÿî9í]ñÞ{ñÙÊ®ãlhŽ(èÌÃê¼~ÔS¢|ö՟zýw¬Ë§|øÝ—*½ŒÈ×­|úåwzþæ“)Nrû¾Ê?*ô¥ +¿*÷ô7ú½~Múúú÷ª÷Ɉ•S3x*ûíP”ùH£°°àó(è¾í-Jƒú™ +åAF{#\”g…Áœ)!),Ô #ÓÂǼjþ1œŒþh©²K„9$ƒYè)Ž ˆA È +—‡)#1‰Óp"˜ð'Ã%n‰P´‡Ù¨-‹1³¢^\%ƈÔp„CLÖ5à + +
+

Preface

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

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
  • +
  • A - Using CUPS with SAMBA
  • +
+

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
+
smb://[username:password@]workgroup/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.

+

A - Using CUPS with SAMBA

+

This appendix describes how to use CUPS with SAMBA.

+

What is SAMBA?

+

In case you haven't heard of SAMBA, it is basically a software +package that allows you to configure your UNIX system as a Windows file +and printer server. It also allows you to access files and printers on +a Windows system. Like CUPS, SAMBA is free software.

+

SAMBA version 2.0.6 is the first release of SAMBA that supports +CUPS. You can download SAMBA from:

+

http://www.samba.org +

+

How Do I Configure SAMBA for CUPS?

+

To configure SAMBA for CUPS, edit the smb.conf file and +replace the existing printing commands and options with the line:

+
    +
    +printing = cups
    +
    +
+

That's all there is to it! Remote users will now be able to browse +and print to printers on your system.

+

How Do I Configure CUPS for SAMBA?

+

To configure CUPS for SAMBA, run the following command:

+
    +
    +% ln -s `which smbspool` /var/cups/backend/smb ENTER
    +
    +
+

The smbspool program is provided with SAMBA starting +with SAMBA 2.0.6. Once you have made the link you can use the smb + method in the device URI for your printers:

+
    +
    +% lpadmin -p printer -v smb://hostname/printer ... ENTER
    +% lpadmin -p printer -v smb://workgroup/hostname/printer ... ENTER
    +
    +
+

The second form only needs to be used if the Windows system is in a +different workgroup.

+ + diff --git a/doc/sam.pdf b/doc/sam.pdf new file mode 100644 index 0000000000..b4176f74e8 --- /dev/null +++ b/doc/sam.pdf @@ -0,0 +1,1216 @@ +%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[11 0 R +12 0 R +13 0 R +14 0 R +16 0 R +18 0 R +]endobj +20 0 obj<>endobj +21 0 obj<>endobj +22 0 obj[21 0 R +]endobj +23 0 obj<>endobj +24 0 obj<>endobj +25 0 obj[24 0 R +]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[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 +]endobj +130 0 obj<>endobj +131 0 obj<>endobj +132 0 obj<>endobj +133 0 obj<>endobj +134 0 obj<>endobj +135 0 obj<>endobj +136 0 obj<>endobj +137 0 obj<>endobj +138 0 obj<>endobj +139 0 obj<>endobj +140 0 obj<>endobj +141 0 obj<>endobj +142 0 obj<>endobj +143 0 obj<>endobj +144 0 obj<>endobj +145 0 obj<>endobj +146 0 obj<>endobj +147 0 obj<>endobj +148 0 obj<>endobj +149 0 obj<>endobj +150 0 obj<>endobj +151 0 obj<>endobj +152 0 obj<>endobj +153 0 obj<>endobj +154 0 obj<>endobj +155 0 obj<>endobj +156 0 obj<>endobj +157 0 obj<>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[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 +156 0 R +157 0 R +158 0 R +159 0 R +160 0 R +161 0 R +162 0 R +163 0 R +164 0 R +165 0 R +166 0 R +167 0 R +168 0 R +169 0 R +170 0 R +171 0 R +172 0 R +173 0 R +174 0 R +175 0 R +176 0 R +]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<>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<>stream +xÚEŽA +Â0D÷9Å,LìobK–UêNPlÕJm5‰Š··UD>Ìb˜÷ø7Fˆú#¤1d‚ý…Í ›.5â怙 dª„‚)G‹Ýº@ÑÂÓº +Yy©ÛÚgCçàendstream +endobj +242 0 obj +181 +endobj +243 0 obj<>>>endobj +244 0 obj<>stream +xÚ+ä2T0BCc3JÎår +ár á +äHÉHendstream +endobj +245 0 obj +31 +endobj +246 0 obj<>>>>>endobj +247 0 obj<>stream +xÚmTMoÛ0 ½çW=%@ãى—ãÒ/h7¯I‹rQlºQ+K®$'È~ýHÛmZ¯ðE–žÈ÷I½ö"é‹`:‚ñÒ¢·X÷¾]ÏaÂ:‡8Šƒ)L¦1¬³~b1)Öτˆ!Š1l ÃñhŒµÞIÎäþ ,‚È +©¥óVxcBWBAiÍ^fèh!µGû&©sc‹fM+ð;„ Sôûðsù‡„0ŒÆMƄƒHý«£óXÀ¦vñ¬Î6xDë8H„Á8h˜Ï!š2sЇÁŒ#´íÑî%>+$Ühč¶O< ›ù]—€ÒX/¶ +‰ŒQâHJYß݌¾OÀ”ÈŠéÐÕ\K;á: +·ˆ2Ü£¢lp%ÜVo.'ÖdUêxà +ãÉyp^èLØìDÁU½›*”jTìQg\BwòVŽü €Ýç^ùš+‘¤¥¼*Q–J¦¢¹Pé ›æýš1©§ª§ªj& ­œ7…üK¹÷íšn~>ÀÍîD}ÓO+kQ{u„†¨ÉÿGÅA8Þ :|ÙAEÁeÊ%ÍÚý2¡&RÚß"7YÆ3ñ¦L=ü`[k«k†Ùià£pÖyñâYÌéˆv#þ¿Z÷~÷þò5³©endstream +endobj +248 0 obj +699 +endobj +249 0 obj<>>>>>endobj +250 0 obj<>stream +xڝ’½nƒ0…wžâŽéņíFú#uˆš²u±Œ!®ÀVmÔ>}mJR5C*{±}îw¯Î§‡ ´ A”¸M;oYz·/÷€R(kû’¤i@Y-ž$í;& ¼í™Ús6ܔVB“ÒÇI;e¹ã´¬Í@Ru\pm1RièˆèI V!UCÿfpa$˜ƒZ¶­¸h@3j¸úaêB]pàc£wœ¤pncÀ‡µ²DG)¾´aÝ/ÇôèEwdûÀ²çmå@DTð*´!m뎏Ûuq,š]1›žõ VD†¹^ŠÿøÞ?Qw'žrJe?B¯Bä±ÕóD`àfE¾Zæ“.;èm†P‚&Ò¨-æ|äçùXùpõ>г ?Å¡«Âî.Ê2/¦ñ¹ô6ÞÔAÉ­endstream +endobj +251 0 obj +315 +endobj +252 0 obj<>>>>>endobj +253 0 obj<>stream +xڝUMÛ6½ûWÌqð*þŠw÷Ø ÚC².֛ô°ZÙìR¤JRrüïû†’?"-P0,™3ï͛7ÿGSšà3¥û͗”W£ëÑ»O4›ÐºÄ÷2›Óò~AëâfJw´òÚFm·ô|‘+zjÙ·š÷·ë¿¶ éTÂ»ùì>›Ièz§å;UGöT{×ê‚)K®'WÒÎí)î˜>ºªr–^¾üþçÞÞù·uh4½´ Ý-&ÙC‡Ã琕wÃՏÔpx¶ÌR=Ÿœ§+¨;²ìÜ‰ú˜¥þY–Ú©@µQۆ‹Äôuö~™Ñ‹5úé³Î½ ®Œò–¾i[¸}H¿ùYåOÏã®>>>>>endobj +256 0 obj<>stream +xڍWÑRÛ8}ç+î#!†Ð °¥´ Í6îì /Š,5¶äJ2Þôë÷\Évˆ 2%ޤ«{Ï9÷\óãhNgø7§÷ü#ë£ëüèôó4¿¤¼ÄÊÅåevAyqœoåJnŒ­ìÓî]þÛ4Ÿ§m³ó‹lÁÛ>~[®H{Z ¯ +jkHRµrOÚ<ѝ ÊÈa +á +’¢ª°3 ü¸¸tÚÞ¾t6Xi«²Žî–ËŒÿ£@|¥ '«çï³s¾ZÕk'$b­wT؟Êx²%5K9dQŒŸ½rÏøU ӖB†Ö)çOâŽNWb“o›Æº‚qnFý苖Îz[†ÉÍÿhSØ×5ʉ˜¸ßù ê¬ß7€ÃɪÔFy{š¾J*Qe3Ԏ";…lð‰Š_\¤ïvíê±MÐåVz«¨V…“½þ©NÈ)o«–·¦b½åÃ&£>"ï,17ä\8k KËK•eÎvL‰e¨ vruŸ£§Mk +§ +ÏçÂÆ¶)D†j]1ØeôÍÄ,bº—9ll§pWJFTȼg¥TÞOn•ÖǺ-BP)öu+#Ý®IϵØ2°:€º•ª­ýJB{.ܐ8€°UÁ ƒÅ׆ø+±S(•ø€m¸FÆèvyÌrRî„ñœþ¡Âoó|yBÝF#„áC`CG”:µîu‹Ç©ô_RQ¾ÁPĒä°È-=kÕ¡3d[‘ˆG’>·ž´êô5¯ìÕ56LëƯWk³[;\¨Ü“è òYQöÒÖM¥‚b*OçÙÙ(¸ëØ:ŒtØ» rBfL¾°µÐHØMÒ…œäA½ 2ºÑOʇ×Bå«Ò­@< ]‰u¥€•-»1 ±ãl9¹—«Í’;îMt¶8Ë®xõû¦u~ ½D3¤ÚÁ¡o×µìB΀•Þ5¥h}´cXÃaüãŒî£] k ‰¥N®&¨5úG kkë5›b.OÀ< “Ê8‚ð^?¶kËá²­„ƒ«yœMX>·¾1jèñ]ŸûHlߍxV£o!¬•Zp¡m=u0îM¶Bv7J~Ö'Žæ¶Ñª·p\i»·YøXáBå?ÃFAsVJ†žnýlklg8¥ òµè  $ðâ¶H ¸í0ªÜ¯¥v~:bö*ÚR›¸9Æy»ÖϺâl߬µ_OvÁšð©ãEÓTCs ­4x0‡0 ac‰2ú6fÛ@°5'H•åGý¸´endstream +endobj +257 0 obj +1361 +endobj +258 0 obj<>>>>>endobj +259 0 obj<>stream +xڅUÁrÓ0½ç+–\Hg7NCÒÞ `Ê4 —^TYŽEeÉH2nþž]IvS†É!±¼»o÷½·Ê¯IKüä°]ÁÙx=¹ÜMNß_@¾…]‰o6Ûm¶]1»¶R{aáÊÊߺ“ÝOŒ[CžÇ¸Åj“­ãŠRÃÛï×7ÀvÒy0%-è«6V@)•§0×.KÉÁ`ÐÄ"YL•š«¶_8V7Jôï© „ÎϲAGH(…¢SÂûÅ5ã÷Ìð™9a? Lp%Ü=ýNU\?*‰U}%]ê +ƒxÚxØ -,óØqãe͘Ö7­Af!ËRX¡‡Â8a!”›ƒô±^!jdÁ‡r•éà`ZàLCg%žà“Óé!½§zFŒm ¥Ž }%j|¼YYæQÀÅz™SÜWá;cï¥ÞÿO»ˆÈs›6‰  ÇáÝÁy„c¨k½©™—x¬à*<+ “¾ƒñ6…ù:Âg°C–G#`Ó¹@Žá„o›`’„†g’'Þ=¶.©Ö÷åŽPqR•q1 +Gû‘P7jÝH=†ÆÑÃ#Î(©}œ.8–óÖ¢¼<˜÷çcýtsÊ£yÙ£ Hà;¤‹s|RÏI‚#|éÑl¬Æ(…P¡°XHð¾˜xÀr‘fêØQeΉ T®nqH'”à>ô‰w‡´b‡çè]%yÕӅ«·3‘í3˜¦ü×D^>%2Ÿ­¦ÙíI*×»(ì,SŽT3¿%-ntÜ&9n&q‰%Ç­H{jÈÙbGä2nÍ"qoˆöæÈ¡§ØLoÒç„d£!Évð7£Õ­ò’.•H€ƒÆ ²D!Cɦ:8²z¯tßÉ<8J<„{iÎñG؄‡Ãè—¬P¤@t 9A 6§B¡*žfp)8ìØ$Ø4éà­8þ|¸IÂH#ôgÒæ‰3‘òX߀ÝᇽMSs ¢¾dRµVL¡Õ +L\Bڛãb#ðsî?¼Ý^D±Ï“Øùú¯§³eú— Þ¹1¥ïHü7E-µ ¦Á_˜nYXÝEL[lWËü7­Ï—Ù„·¯èùÝnòmòH·P|endstream +endobj +260 0 obj +820 +endobj +261 0 obj<>>>>>endobj +262 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS04±Ð³P072PIÑp VÎO+)O,JUpLÉÍÌË,.)J,É/*VðMÌ+MÌÑ Éâ҅h҅ê2‰™šé™+€ùE™y%©E +.E™e©EÅ Y×®@.º^%—endstream +endobj +263 0 obj +126 +endobj +264 0 obj<>>>/Annots 19 0 R>>endobj +265 0 obj<>stream +xڕUÛrÛ6}×Wì[Ó‰âEÖ%o±c¹ê$ŽjÑÓËô"A + 0þ¾»-Ój¦£F öröìÙå—Q1~X¤Í¡£ë|4]¯ !¯ Y,¢+˜/f—oR˜Àu'šR¨˜*a£¬cMCכÇíîÇü/tA’ë$øN²t¥äž„…âÀZÇ Øƒ>ZÀœ†=õEˆîÀáFK©<Þo~ƒ­ÊQžÝÉ:.#ØTpÒ0ß|<(‚p›â(ƪèHèx¸ƒ,Í¢dYÍAb¥KÄn ì¨æ¯^è^(fNP +ëŒØwN ŠÊhPa¡pä{°Âñ1´Fœ—Týkyá͝p /Çð:žij¸Š–<ÿb?°0‹—Hí·ì‡h?O¢ÅE½/]L}¦¨gaÐ\ׁ’÷J¨´ç qäMT°Béx„¨“YŒð/£îtg +þ¨Þ{FÞ1L®âȋïé„á’+g_ + Òy0ú]w? zu„)xw¿ÛÀ Z¶¢Aѝ¥æ›ˆmB ¡{I½³ œÅ$jJ¶àv,Q·%·¢V¾Ñ¾p”wdm:E¡¨û^ªºå†y­†ÀcR9ÿJéŸäƒZæ¦bXz#ö†ˆ%íKmèʛU¢AëŸïYñ™«Ò^äµ]KK8 +wqq¨:¤Æj X*1íGQmuåþL¯æð«P%ŽýŽúˆOì­uÀ($«=„—8¶ˆoWÑ:xØlÇDޙlrûy{{7†í=ùf½{§?>l®û*‘Ïè¼'…F }¡Rtç(œÅáBI„ê /»ÓTòóÅáNÜ2{BUîH{`k4Za%C‚ñ‹°A +c°¬@ëEâ¢3娋Amoeù3``îí7f8ÂK’ ²%¤É +ç&Ü^±é:†i6#Ó4ŒDåÚ·Ó)žÇzì1B½NÛn?=£xeÔ.ö-Æ<·²_’}æ´rU¥ô+Jâ`´Œ xwÿµÑUÈS- (z0iiQ„è Å¥"ÙW&¶'Ùà¶üÞf´ÿ$$K"Ì_¾‹µÙ*äz&­V]¤MíóÀþ?[9ÒRꢣåÂüþƉ¯´‘Ì9䦳4ÍÄÝOùÇï?݀í5w~©þð‚pú£@¶kîžÔ7]/[«À÷¼WgË×hL拞Ø_F)è@endstream +endobj +266 0 obj +905 +endobj +267 0 obj<>>>/Annots 22 0 R>>endobj +268 0 obj<>stream +xڍV]Ú8}çW\UږJ“„0 …‘ú0_°¬(eRUZõÅ$Îà6±Sہɿßk'‚@3bJâ{Ï9÷㸿;>ôðLJë¡ù ÓÎ}Ðñ&ð}b|3 ÜQ÷ïàËüñë(ë-‘b)ÒۏÁÏÎSÐé¹=Lc>|ó±œb2ƒoÆœ‚?î»Ãê[/£!_Á›ô`l@‘ÇpØ+Q×Zg·ž·Ýn]JT¡¶n(Ro­Ó$¡ßçéUyºæ±7ƒ?0ÙLç\_#>¦{iÆÆ_ááÛóKyp¯Õé݁=†/!WTÁtñ H®E(x Z€ùË^s”¯×Rò‹Æ,Ás„GX™\†DX!¡À5M]š±58Bú×nß@¶@½- îËâô-½¿ÀõöɞÁÓòPŠÕ\‹ hDc’'Wš$ ÑLpز$,×VŠ•¼ë-ãöa_fíz¹’‡@]+¼}lCþ81IC-$ÃZ!tCél×,\·Êa¹‰ •[É4E”èSÚ´.“ŒÛà(¤ˆßÎh‹])=®pÏe 3aYìü1ùŽ“Il÷[[›ÈLÔeͪs|6µô br¶³Ø²y^L¯àŸç'ü f“É•-ýóÙ=$l%‰-­Ñ‡Újõ4²j뙪§`'ôGnj!‡¤8ÔÚ¨Š%Êx˜ä½¤ùV[µŽþøh:ôÂ)²ÂMRT+òÃd~7}¹hþxô$å&O)׀sÈÈ +׳Õh Ü6ä sÎËAªúsº‰HSCIÞ93O‰”zõ\ïjŒÊ¸vO ™Ÿ iNŠëºg'ã+G¿ÁºÂšlè^Öw²Ôü̕>c%ÆÃÎa­V9K"Û±z“ÜC£íímvVŽŸ)­ x©Númk_w«zó:®¡à¨ó/«V_Äç°®ûe: gއ„¾” MqµV…aˆ§ùÛUQ+ƽ0ÏTï[">íD ª iԕÀ=ãDðˆ®(Ù*7 }RÐwj­!Ì¥ÄÅH +ôã:ªº aU¦‹é”qànin³”h¼0ôúð +1{)QïmL…’eZUSqS‘hNÑ÷»åb¶˜Þž¤ÙÐg9µnëñ^µë£OšžÐ·Œ¢šF,ŽYˆ–g¼Ñ²Ç6•è£ +Ý÷ûXÛá¸yó×ówQʸ)Á}Uð…ðœ$&Þñ# s>õ{&jdž ü‘{öû’þÎqˍ ©êHÿvþ®YÉïendstream +endobj +269 0 obj +939 +endobj +270 0 obj<>>>>>endobj +271 0 obj<>stream +xÚmRKo£0¾ó+F=µRq€²iÒ[©´‡}–½õâ`C¼õ£ÿ~=&DM·â‚á{Îø5É! O×\-¡î“»*Y<–çP5ôi¹*Ù +*q~ÿççXlܞ \ ÐR +p-–×/ô:¢7€€Á(í”nÁŽÖÉþ’þÀ^uݑedoÜNI_T“ ÒüŠäv4Ú+·‹ Áà›kk£©´u<¨NˆOh ö‡Dƒ4üý¯ûËÈ1 ÓbÉJò¬Þ˝þ/ÿVB‡mJ·`<Ÿ $®áÌú3P6LH¾Ý=_0ø¡ë(ö¡/YiTñVšK0^ÇO‡L!?깫}dSÈÕ!d^®ÂÅË¿äly¼~O³õ­è•Vօ­¢±ðkÏ»¸Ð‰–^±¾NÑâJàNinFx žÚzªE”r•±5DøšÎ›*ù•üÂjþ™endstream +endobj +272 0 obj +433 +endobj +273 0 obj<>>>>>endobj +274 0 obj<>stream +xÚ-M +Â0„÷ï³ÔEkÒíÖú.¥ñOk%’&˜¤ˆ··A™Y óͼHBL’(—É·E‹} )¡zȪÎk¬ +ÕÍ6—S‹ÖõñÍþŽu7h«Cô8²ÙÌՓ²”ý))RXVEž®¦à`Cdc´}€ÑhËþƒmÒ×1jgS}§èL_§<,endstream +endobj +275 0 obj +140 +endobj +276 0 obj<>>>>>endobj +277 0 obj<>stream +xڍUQoÚ0~çWœ*Mc”½m“6­S[èÞMì€ÛÄvmĿߝ¬%´jÅCE}wßwß}w<õRã'…y“äUïûº7ú±€l ëÒÅfó)¬y ÜX©¼°p[‹ZÀ5Sl+*¡ü—õ&M!M))¡¬d’͇%®wÒA¾c†2¹tyíœp°Óðç¨4—ÅqLqà¢^€!(x" ZÁQ×ÜÑyQ #ÜÒ9Á!™Ž‡—J@i¯¤‚+]UXï”Æf³á´ãæ±ß¤ž¦ô!•€•¥>8bB谅¶rw>²ÅöB¾tÞ2/‘´gîÑAauášBI)•M tUZI•”êÉJ‡ÚÁ*#©¶D-Ô¤§ðRçÌ ¨‹?ï{T;;*妋å¹×öØá*b0º@ +•¶±3ìW+Ô_>¾°9oDÛW#ÝyèÛ3ÿÆ9õMº6¢oQÝÛÓÎCúíäp¢W÷7«0]'+SÁÖ¯ªõŽKÒïBÚEb.@2Â׶Ăbqϒ,°ø­ô£Ö¶‰‰±YŒí7üN +ô!YB²? äb/sэ»éT3¼±ü³^Þuö7l„Z–ãn„?õˆ=®i°<ö¼g%ÞfÛ7V¶ö>ß¶Y«ØIgÏ:*V¡Ÿ˜BH¨ Í%Íæ ˜ '·ÒãßÝÑì„rñfԊãcŽNtC¸WÁ‚©Úî^¸AÇÊÔOk€L—ƒ|€KÓá«´?›9s"qHCz¹À$ÿ ûÏ>øËt[ޅú¼ë¦ßXÂþg¥ÿŸ®ñ³y[Ò%å<œå|@ó—&ye·5qpF䲐8oÒ%ÃýÝOZÔB–"(„W^È6Â)4G:f9rCGkW£ms†l˜“9Ð-ÁÃï%¿Y—ËçΧM‰÷~„¦ó)^…1…¦)ýc¹îÝöþi£ +Ïendstream +endobj +278 0 obj +729 +endobj +279 0 obj<>>>>>endobj +280 0 obj<>stream +xÚ­VÛn7}×W pÐj/’ ÈŠVn @\¨]}pü@‘\‹õî’áE‚úõr©ÛÚV“8°aÈäðœ3ÙC}îåáOñÿ¥uïzÑKߏ!ÏaQú¥ñd”L`Á.KQñiÊø:õŸRó7‹zôãdäžì¥ïGœ}XÁf€THg•³`%Ø£8¥à Šã5&c¯çc¸ªÂbÑ쐲øÄvÜ7{®Ä_¨À÷ ¶nH(–ïÂDÖ ˜ããè+‹í…¡ABI(¶V¨»JÒàä¢ñ¹¿è©3:5èí<¥N™´–ŒW]ALhN­Ô[¬º]…Z^ôë‹xmÓøÕ¾ýCÂ?@¯Ä2‰B_íLéªí±¶v'èJ7Ð_Ÿ¶B7®> :Ò¾¹ùcqóW»6‰ùäù¿]Ž'ãö;æoçqüaæu +cñI’øí»Ó‘€ÙÏG<€S“ùSùÀ/GY2„°0cÌ·…¿Œ[ÉD¹õÿÅÞMq³èýÙû§]KÀendstream +endobj +281 0 obj +917 +endobj +282 0 obj<>>>>>endobj +283 0 obj<>stream +xÚ­V]oÛ6}÷¯¸0Ì"Ùr ;í[Û¤†­p{é -^%Ì(R%);þ÷½—”2miÖÀ~°%Þ¯sùmPÀ˜>Ì'p1ƒ²¼[F¦P°¬èÍìrš_ÂR—w¯–÷ôrÖ½ÖV¢NÏú€!wÛÖhøKU)ô(ԈÁVñ÷bq•Òô߁2]%J_:Մ>ÐS|u£ñ‚!%h\\ ­Wæ–kŽ!+.ò ·Æ9} €ßp…þïߑê£ãâÒ©5ŕÖ,JNÙ'´F u†o¤%(Ó>ÀÖ¶°±­–T +ߤéÆðš‡#€²É”+þ£Ö»‘V«‘n„¬•¬é gא­ûoF×#úW@VKZq!o ×—ןSú×PÌ9Ʀã„÷g¬íšf…EšÜïMãOfylfiÁñb܁‰†|ÿeq§ñŠ Ù‚kMD¿©#¬ëÿÆÒÖµ06*ÜŰ³ìá l”5ÏAå!­¤µÃ®¿½Ã'±è €÷ZxÿŽD™`·''nm†@iázx<ɎÀ:s]ÉUðÈá¯;ä…#ié{´áÞ®¢NSàyD‹žˆt£´†RŒ-‘¦°ÚÆ¥•r>€X êp¥ñ‘BÅt‰²æ]¶Î÷÷Å? ¼(çÍ𓳬ìÉ÷ÏÚ?Â~Vî¯ÚÁÿ”Bú~£Bñ8v§S4‚òP:ì¢ ¶A•$˜-¨ +Tiћ_ùòdE»;+a{ßW¤ÜOŒ{rCÜ`ì ÜÅV¢Õ¡÷‰ÿ² OîÄ!² éÅc;Ñ¿˜läÿÁEîãBfI3 +Îòób8JvâÀRÇ'Õ!@ù>'ãF‚p‘Fâ&ئù1ï>F ÛÀQ—”ö`¡TþÔʎ"“[Ёžúyœå[‹-’M9ä:Ð騷OдRf”Ú‚gÙ9Û_‡ÏN¦®oxæÉp’êàd•‘¶Sv µØÒà캢,±‰>í¡²Ý)@ôœÃª tØóŽeh£$Of¯(žî”ƒÅ°åô¦N2È(É+îH?ô%s¨ZÍ~²+ Zèª5e4ÐH ›´A¾Ž(’¹wi#:º(K#Ô9¼¥6_±ûƒêKaÙ|2æ¨/|'#ÑÓ\ÂÉ^ôpo^±ééœo‘qqqÁ®—ƒOƒïu›(endstream +endobj +284 0 obj +950 +endobj +285 0 obj<>>>>>endobj +286 0 obj<>stream +xڕS͎›0¾ós©D¥…`’&ÙÞÒ*=TjµÝ¥``X›µMо}Ç6i79uBÂ3ßÏ|/ ƒ‚.ë­¿›!ùR%«o÷ÀvPuTÙîvùª6=4 ŽN¨gઅG/žýÖg!¥" +’~æBòšœ9íµLü8HM‘†Ð-èœ0 ÙfO;cŸ–Œ¿þ~x‚'ݹ™„C;ø1áNç®&.=>‹°lWÅ6þpÍ>>>>>endobj +289 0 obj<>stream +xڝTێÚ0}ç+F+­JUåJÊ¥oí +Ô>tKKöLâwÛµ(¿c'aÙ°´U…„L2gæœã3üEâ'‚Y “)dõèS: +V ˆCH ˆf˜ÎHóq¬ã†ñlŽÚоNv´¦Ü¼M",(²0Ïâ¼I<óc MK¦!+‰4T.ÅA~ÁQ4™àÛ5Š‚))Ü=¬7 ©ÚSå·]HÃv ÁKBn;ޕ„ï,‡èðÄ0ÁaÅ*ª_ÒA`<õŠU¢p°vÆiz‹.,r©DF ́qWÝv »Žã`OT5RÿrÜr¦hf„:úðgÔ)-ɞBMr +Ė#§hÒړY1(^qó]9§8)ª Qfh lxâ¹õ€~~Xƒf;NPŸ‚F÷æèFʊa/)&Í`ôÍ@–Uäër çæC_¶°¿1'^ìܼ?è '¢Ëûtùc‡èn ER[Ɖ:¢MÚ(¶mœóŒ#¾ªtËڑ½â=ãÌøùUÏáÀLépœÔàJh×EÍew*;·xh'íñ¥PÞÉlÙ/Šv‹r=È)­¥P֌?çö^¨Ý9¶Á¶Qfx4§.m~Ñ·×òjê¡x¾6nor¨Ø£Ë`ŸF»³ÏžÚšª(ï3Jsfþ¾$î”û¯í‹eíwÍ{Å—&Œy¦(1}œ9=œ©}æG8&œšS‘R ¼\aTÕLk ™¾äú›uâöõ8(„¶çÆuÀñsÊ­Ý]Þ¢wµÈ¼S‡ßæ?z«ùùÆ$óûßMf mqôÞ>X¦£ï£'ß?¾bendstream +endobj +290 0 obj +622 +endobj +291 0 obj<>>>>>endobj +292 0 obj<>stream +xڕVQoÛ6~÷¯¸=ÕbY²ÇÍ[Ó5X­ËPía@^h‘йJ¤FRVýïwGR¶¬Ú'€-Ýñî¾ï»;þ7É ÅOË5ýõä1ŸÌŸVe—øf½Y%Èù4ß Ŏ©Wn' ’J@¡•cRIõêŸÝäÿ¢s§¹¨›_¥ Oû#§À¥…“{R]r+ÚÆò.ǞN{ûp€6üÅtûn/È6…Y¶L”nas‚?ôg¿§°ÂÙbå« ©ÅЋðz:/µžo™™»º9sœžg2ó­ԓT¬ª·`„uÌ8Ÿ¢f/ 0 ºuï‹-¥±ß#Z.ñ¡´lã„IBœ÷Ýøg«4ÀÿE¸N›oða‘¯­aä~žUzÊ)'”DÉÚÊG'PÀÇ¿Ÿ¿öIVÒ:¡,”ڐ± +©áo£kÀÒ@ÅØRaŠ%+V¥ ÑXëz™€™úúSœŸŸŸ½åËMxZ±.¦R¶*Fb†ôTK$Œ8®tÁª³T:év>oÖ4F7F"·£¸-V£X&ŠCìŔyz\>—^-£}>EV`M–~ã[ö€€ÔÞÒW²\ºKrïQ0¤Ù9!=¿®ÞRVâDð*R¶\&kJíAú)Ÿ£°?Ú;Ë6¢¥D¦X Ê×J<uÄ4{"4Ga%Gû‹ìÁË™~¹!L `j„=«¬F5¹¶‰aÅ¤sËóãy›C ä-8 %É(ïcØž^ŒBw¢ª®ƒú»ÿX/y\6GÏqnHA^{Xß-ˆïøŠ÷ƒ±—:«¤;Ä<<(é§Ì&4 SžUäQwgÍ¢UuÍëç´o¦š;ؑ?BýÚh @¶¸ORüd±Ç¯Œ?©Ðœñ~°¼E¥—»óXÙ¸7Y~ÑO¤¹m·øõËÃv¶­ ³C‚’ê؀¦‘Œ”vÃÞgÇ>¿\ÕØ£Ñomßk^C­Ñv5ºÂñ·“Å.4îŠZ+‰Û§õ±µvp&R3S#Ž£_z{l̸9GE»ûvºÔf½Lâ¾'¬„‚Çf»‹ù¥ðåÏüÓÃUþÁ3ëÖヒsô:"qí[šî{Vµ‚æ ͯ¨¹À™=ÞŽ +²b哿&ÿçRjendstream +endobj +293 0 obj +1028 +endobj +294 0 obj<>>>>>endobj +295 0 obj<>stream +xÚ­V]oÛ: }ϯàcw;±›%é0 Hw7¬À>²[¸}QlyÑf[ž$7Ë¿)ÉÙ¬&‚ ÍKM‰<¤ù}”ÀÿX¤p9‡¼]g£ÉÛç$•ôi¾œÅKȊ‹Ÿ²7/že_Ñ<óæ)Dé<ž‘õ¦„½ì€)Íx·Žîþ‡d§S`M t·i¸³e„†FHgcHæc +–°F¡U¢1\ÁFɝutA×E%Ë ÅǨÉeœRTVUt9ÓÏyk„lîŸÁN ‰Bì¤úC¶Åˆ­’›Š×Àږ3¥ÁHØp(Åný{ÄI<]šW,(ÍËͦ® kï–çf²"¯ïÖ·òA\ÃÍÚV¡5MÔ°šÃ†i Ìòœk ¹lŒ’•=tʹȁufË#rF)A‰5~ú…ræC_^Æs +ý^º'±e[Î8õÆw. XV#8¼ ¦ ¶À@·<%Â~—ekIª=UK,«Jîè1[Í»B¯ØŸä ä‹VÀflá`+©¹zàÊ0÷ðÒ%z8duŸÎaZVÔâQR‘#þÈÿÝ7Ž•u‡,BJ(^rś! G +y ¥u&´qO’˺Æ÷ÒñÔo™E”WLk®ÿ“ƒ—wy&¯róWPŸ3C{à³B4¤Ä +U@¢+!É ûƱ«”¬m¨`§ÕDoñà$ïZ=)d~¼1ˆãžÎÔ\ºSJvH&‹ÆAípXc+ê\‰ µÇÎr]†ýÉºÊøN z ”âK§s;$ˋã•Wú(µð_ö`ÁõΫޓÀŠP¶o¹“©#Æ×DF¸ÝkÃëÀüûI˜æ¿¼ÙW¤™ ð–^­a :ïŒIº@ɞÆIpäå¤ÏäÕP)­ž÷Zi1œ#”G.SIóۋ 2ÔÄVuž”ºk[© /ÎÖ9WJ[•1Õíqc¹Š)þƒí˜OóSۇÒÞἿÁÐ0 ݐ؛­Ô*”A77ÙÊ« Ý1(‡Zš nžNrȗ'“”Mµï{<݄Ώzb Äå|rXsë‚Ð8äptž«§çþ‘žæòÓ9÷CÈ X?CkËØ®2E¡Ñvqݎv¬Ã^ÇÈç¯ÅušZa0¾iŽ{¶ò©V·Æ²á§­ÿÄn½Šq0»@KŸT’¤xz~•¸:مâV–fGM·òCµQâVø5³¢d¶$J.p…Å[×´‘ò•Kì³­ÆÖ–,èÛlôyôLXendstream +endobj +296 0 obj +968 +endobj +297 0 obj<>>>>>endobj +298 0 obj<>stream +xÚՖÛr›0†ïý{™fbYãÜ¥IÓÉLÛI÷T'4¹'Ó·¯à,z×±ñŒ¥_«O«ewO`ý!Dæ›ä“ËÉìÖ+3ÅsDa™^ܬ×òV¥Ì¥2çY™Xþš`˜Œâ–èEªÊKXºžö”ŒéÇ[8Ëó1ÚkŽ¹ßº•†–¨H²UfŽ·wOÆRÎÕëµ[Ö+ ´s°sŒ3Gb†Lpêzý´œ`„uÈî~ž>‹Ñ D(ÒWD±æ×î{îS¢°VSJÔ6ö›S„ÄX¥ÄAaËd­[&mÎ|Î0齘?“Uw09LÜ¥ ¡± [„z½/‹S÷±°˜˜i›dA½Hæ!Âþ$VÝKÕ¯$B¨ES p„Lk½9¬º—ƒaOz׸EAÃÐË'½NÝËBë‰D05ÐÂF®S÷â`ì—²‹4 ,؈èuê>  ¶»tG?g€ælD;u†€2瞎Ì:œÖuÖVðÍFð²Be©ÐY¶eâ‹Ll&ÜÌ33:û å;Qü9^†÷Õ«ƒöT{X L])x®kÚÃ#ð4-uº:¨3P½ð +2å +•®Yu©Ò¥«Òû*Q¾‰òºÙ¾iU¦”5Ø®6k÷µ +÷~î›,Dïäeã²ùh†› ½®«s9žõSø«N ^Ýiÿ3$õm£e\÷sƔoócoKµZ ÿ¤ù‰FdG+>ßú0úÏ}OÉQwjœÝǍƒ´ÑæÔÜþx|†g¹ªÞMˆÜ¤yVdª*y%K_y±åö¥ŸºEÓz±uÙt swŽ]jÕ§ø>ù xKìendstream +endobj +299 0 obj +751 +endobj +300 0 obj<>>>>>endobj +301 0 obj<>stream +xÚ½W]oÚ0}çW\í‰J%MòѽÑn­*mÕ6¨´^ÜÄ@¦àÐØ)âßïÚФ „µ«ˆØ÷Þs||®å<õ°ñã@@Àõ!Zö®&½‹›!8Lfà9V~èZ!Lâ¾s6ùÓs|ŸlýLBËV5þuÒÃXl÷ó놡ÊÌ0yĶä Æ ÁÄñ,¯Œ&„T¢‘•á⻖¯°IË%éÄÅ 0¿3ÝÊeèZC…mYVM9r€‡`ng:º•qqQà ây4qÌïÌEG·r±]½~•’Îa2Þe`ٝɘè62^HŒqɰ…ަt„PàŸà^ÝJÈ'ƽ.9@¿G(yþ &6Ñ ”lðlß4Y0P˜7vÙùý/ŒoÌÐö0èCœä,’É3ƒe!$ÐՊÑ.’˜­Wø–ET&o­b™™Kp†jƆ[v÷¨‹ÉfŪ©@|Ór „›s^’ŽÙ,áL€Äd‰‘Í€bã21TAf°bù,˗ŸM¨¬ƒGÙÃO‰Ôñï3þ +{÷YB,²"á‘m‘X Ó>r£E*­éY×ì”íÝzEE½FÕÃ]€ ‘ð¹äáþî7¬¨ë,òæyV¬`–¤LèT5ø§-øß\§¸ˆSÓÔäœõ‚JHÙ3K•wºì"&$Ûî©À‚ñÉÆñŒo–Y!>Ü]‚å¯AGðLÓDy‡åœ.™6ËÎ9/Vj6Þɖo€;×3ÊË»Pm·G–fÊ䙞û$6â“BQ׌!ãõi_.°`D¹0ZP>¯ôH#ã[•Újs ¿®I1¨€7©ÑXõÝŘoQ*|T4ZhÓ´fÕ,šÛ=îÐ^(ߨwp\´,æø‘q\LнÎJtÜ À®ì´ÛÕÎÖ«xVÿYÔÖ®8L¾K3í¥ñ2ቐ¹9õŒ¾(nŒG4ãéõnIÝ +,¸“¥Öۆ(OQ9C h©CX–pð‚êw­ÅõÏ1Œ³™\S¼uö¤³\ÀwÊ šêN1iƒ€èËàöê5 †ûכòJø³÷–Ÿ’endstream +endobj +302 0 obj +805 +endobj +303 0 obj<>>>>>endobj +304 0 obj<>stream +xڝWßSÛ8~ç¯ØæåÒ66± !½¹¹JaÊL)\É=ÜL^[Žuµ%Ÿ$“æ¿¿])?cJRÈlk÷ûöÛÕjýßICüàlLŸ¤<ù8=9½ùÑL3|2¾¸Ç0Mû7¢àp£tɬy;ý Šü¢ ‡#Ztõ÷Ã#TZ=‰”`pw{w̙á)ddoW• `Ò][®éªäIΤ0%X‰’O\[·ÜÐ †þ„´lŽæ™ƒ§?Äq£³0&\Βܯã:„iÎÁS®)öKQòÑy‹{ßqéZLDž-ö¬Rž ‰Á Ì&*ވ içȒi¼ùÄDá¨+Ù¢LÖfe,/C‚šÖržyÍ_bÝPü¨X=q㘗j)wüM×$bA‘©lœ±L[Kasw“Rº‹¸d+˜óVh™* +µÄœÏW7ºÓP*ÝKóD-¤°BIÐuAèXZÀ°²*øÀµ¢²ü‡=ÍmYtåÄ{›Ô¤ÀÌïû´ k;ˆ`[?°ù‚ÙlÀ0œÐØþlkoÖ¢a<š½…÷0ëK¥K7{|žÞ}ù³‡š7ß|º¿šþóp÷go÷)ŽL#™ÐƂ]*¯՗\ùðœúL¢@–KCªaŠz!EÐ#yÝ¿=€ÑqV~#Ø\èÔ;n¥ aL'WfÇ¢ܙš%®¨©žw[‘dtЮ/‚.ðl³6Äi1Æ´Á’E¸¶ø™H)gUðbµ—¬Ü¯Þ9§CՑ’‡ŸÚð¬.0X.ÝJ¥ÅBHtG&ä¢EMÜn@Žeí‰:×bÓ§(p®éQª¸‘¿¡6ŒôÍÙ†µõLm©ôwG¹ °ìû³,%¤» iTÊ1…°+'>«­ÂŽ(V”ÂE­‘ªm«9ù\WÊŒ½ ë³Ö”JHlF,íÒ~ׯ,7֕Âz{%뚎'Èvk3‹Çíý;ëcõVÚ»¡< C‰D †˜¹>Pa®ÎZÕtfìÃ5ôéÂzÿâ‹ZJpùõÓQ®mWHo™ Ô¡b o8¾ÿv”ß7/Süz?=Ê@’Ïú½ŠYܨ²×­°{n-6å½R?iÛ~è½ ·Ë{G¡0“1ë«,3ܐæÂæ]1MuU›á)c¹oOO¬i£I]>^ÝÞb·¾ú6€¯_0½ü8€8‹ƒ(oœÈ«qü·«I0ÖuVÓÁ|]à1´¥â¹ ƒø|Ô&ì-îâ½9–Ö¤{þºwmä¤ë/Ô¹¼åQ¢Q˜[hÌOÍ_Ã¥½E= +ËäJÛÃÁ¢±K  lÜMX̋äÖ5j:]çbp™ +&{Žâ³)r}|fúpºX¿H:é½"f¡Ð1–ú!å’Ôš8xßhŽi”Ëfº üI±7ávŒÚL¸/èÛ1ÅÆ ‡í‰^Mš• ݏÁXۍy¼1 #Jî¤|i 4ªÖ ‹C„i…£Ê«5Z¶.Ý4ZLH`UU`2ÉÁ)žóÖ$ZT·nÖ²ª2-Û¦Á“Lä®Lаì|®™!!Ðke¬òW-¿¢d ~ú^ó>ÜÒj?u±£°6ß±8½™¬SE1ºOFËG•Ù%%í2-¾0ZÍÐØÀ“µoA4šÐ¦»ˆ‡déæ(>?À°ë%özzò×Éÿ¥Ã|âendstream +endobj +305 0 obj +1277 +endobj +306 0 obj<>>>>>endobj +307 0 obj<>stream +xڍUMSÛ0½çWìä˜Ø‰CHÒöD Ìp`¦ÒSéA±×FT–„$'ðﻒ씘”arÉh¿Þ¾·»~d0¥_Ëœ- ¯_׃Éõ² Ö%Y«yº‚u1Z? œ¬ɸh#«“c|ì"FPrp non¯À½hƒÒŽ+ɄxÆrY‘uÇE‘3S@© 8Jo&ñþ@/¶ÙÄÿ÷#L«Ô—™B’¥3gèðÙM´`\Ç0ä5«prêÿžN´²Îæ†k7¼?ég‹tþŸ> +´ŽKæ~¤(°äéYØ1fÚÅÔ¼ÆÔûÙ·É~NNðãˆ…=ƒ‚ðn¼óž@*àÐxv1‚Ò¨šôu +²é4_/ÄPO¥&Ȑ?(e±GðÝ‘:Ü)(xY¢AéÀ¢³ Ê¶’…ݹäJnѸ¨jh® >³Z Òޗˆ.M°¨Ý£ÆªßµS‡®¯à1­ÏC‹“­,Ò¼Ñ61̪^–1¼¨†4D u|L²€À)ýF1&‹¾¯¶N­³çÄ«Ázl:嘈Ä{¤ÄZ͎Cy¯B,‡)ϧ˜,mTeXýþpý$hý½€¦‘_â’jÌ9îlÃd9“°Áý<Õ솹ñ³Ð'Â/àS÷LÐDʼnì’Õ uÃòµ‹Å)NDÄLÕÔeƒ2(·Ü(é`Ë gA¹i›i÷7Xô*·Ûúíç÷;¸‘”­d9Â%Z^I¸TyHü¹“ã“§†.b2 dvÕÆ·IÒq'°½j~ùN%«ñ÷!·IÈÐ +rSFòˆîbüJû½<]’7SØvýjÿ½kY—p¿û4Y”Ûìx;ë-uÚàîw°¯Êk®¹Ô ér!DKªªÆÑcLR)_ù $šÓ|ÕÏæ+útÌΗ±F þN•nÇ ÂEQsÉ­£+¥hgn™l˜ðñI K–³© +×Ô_°›ó¥ÿÃ,óWëÁÁ_•&ßendstream +endobj +308 0 obj +741 +endobj +309 0 obj<>>>>>endobj +310 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS04±Ð³P072PIÑp VÎO+)O,JUpLÉÍÌË,.)J,É/*VðMÌ+MÌÑ Éâ҅h҅ê22 šYè+€r3sSõ’óóʊA®!\\r#àendstream +endobj +311 0 obj +122 +endobj +312 0 obj<>>>>>endobj +313 0 obj<>stream +xڍU]oÚ0}çW\ñÔiÊ' Þ¶ª¨•:-S3MÓ:MÆ1ÄkbSÛ)ʿ߽”R:"A¾î¹>çžc Äx$0Ma4Þ >ƒhžAC±„t: +˜LÇP”g €ÜH儁œëV9©VïŠ?X0†$¡‚ ¯Fé4L©¨¨¤^±5U•Âr#‚«\|Ëo¡Ö+XÊZذÊ ™P Á8Ï â{%Œ§a.Ué+o°hNEϛcM: Ç}[±ƒ†õJ›†ÕuÖi#JÊCõñá,zd&âíÚFX}¥4‚cyÂÝgЍ©®Žh.:¥$Qú92®-õ’ìzp­–þ¬ éô°ݓ«Ö0'µòT^‰3΅µ¿ë­:'Å9à½+=\µ…ZZgA0^ÁUQä`„Õ­áě9@ê}=ʊ0؈,ŒÞXœ¹6~ÐÑuž¯¥P.„K¢>{¢ÔR ڎÅê€ã´px¡›éû™Ó ÝÚm§†©Î7ÃFÂà2Ð tmÄZ›~Z×vöÄ6#Nèó õBTÚ:XÝ® ýɜœlÜÝ á*]î¨Rœ>A 1×Ò¼]oAⱝÃÁe‚9ˆñÀHàñ3£Ï¬‹’,ËfI6KãYšÁû?¿`˜¹- be#UäeŽ’0Â8ƌž€mä½8†>>>>>endobj +316 0 obj<>stream +xÚ¥VQsÚ8~ϯØá%É\ll‡#À[ï’4é”+7!ssWnn„½5B¢’J}W–M Bz„Y»ßî·«Oûõ(†ˆþb8o»o:;úmxÔ¼nAÃpBoڝV؁av2|@8~¡—íòåIÆ,–ÏЯWF'0á(2à,¹]Àdn'¨I±¨ñkŽÆ—ð^#ÊO LÂÐ흰ð1d!üsÿñ~tZ˜“;ÚMÆ-‚ >ØDé³=C]¥$-÷öóåe³ÿéæßôéÝÜôúýÞÝüÑçßõ°ƒÂ¨¶vd;Cû ²½©Þ ‡ðû 7˜Q÷WÃÆ4÷þñéÎ=Ѧáè´Ld¦F£rî'xÂJ¶Å-ÁWæáëHO¨ WòõôÌS>á)³´J3ŸíxYlKGiC¸V~¿ܕ Î9Zp!€‰[oÖ²á šq7ÙXfsórÄ©’–qY‹›¸È…o´AU÷&gB,[—l#‰"ªÒ8· h›.3_áÕ"NU†˜F˜+cøX O¿±Ù\à´¢¸â¯‘K–SshþØbiŠÆ4ªˆ|oWvÀÆê鐺—á@æ³1%By܊³kÎjÅ[ýØE›ÐôT2¸ œ60²`ëSäOÄÌD«Y½“<¬Õrk„X< ×¯9:Õk.-E¼úd½Ò“ºT7ن8ñŒ†n3áX·/†ÉöÍ8²f´¢ÉKû.i9@Õk°…iž¹a$KˆAÑ)¿Ù|«®;DÓÑöSšYî‘Ld4Êu©„ÝŎ^æ+„:„+·Ip‰ë…ž(!ÔÂ5nÖ]jZ:s³‡†/j𬦭.‚ ¼zè¤jÎÑì—ÚRè@+eI°^RÉ_+M£ÁùmÂU†{È]]æª$ .ýlÕù!ÜN`©rÇ0 Ž„5žéeƜm´|í8ÃX‰½ÚÉùâSYâVÙc2—¸Õ!۝®‡)F¿;5± 7½Ëf\Rhféʄ>“Ô¬…Rx³à"‰œUÒr‹ç…“¨bòù<­öjxôçÑ%!·$endstream +endobj +317 0 obj +1088 +endobj +318 0 obj<>>>>>endobj +319 0 obj<>stream +xڍTMo›@½ó+¦§:R †PÛ×¶ª¥Vªä*ô©ZØÁÞvv(ê¿ï qŠqA»ïͼ÷fà!ˆaÉO ënVPÔÁç,ø°M!Ž!+ùfµI£ dz‘®²{¾\—‹Öc3Mø”+ …³¤Œõ@̲ªFpeÿ.¸[Èë·Ýn,¸œØ >´èÉØ}(ÀP˜óЍ1yKxwŁoóÚ¡äÂø&JD0Œg9Bé86ÆJáhD%«(}ÆÖ½ËC£ß`Œ`Û:gK£½£Ú#äÈ}††¨#øþˆò „=ãлZüÃtæÎÔùµ»Î@nه'Õpµkð´³ï 4Ñjpz££Ž¡wk ùîu«Z†dÎS¾àV° ¸¥àۨ?¹ž‚éÇÑ×<£>ž~RÖø™Y£‘9…ª$º(S½ ÓØ'¤ÇeREÞÿ®ÜþœUáö@l…C®gKÈ1ÌÐ …á/jôS–§ÀƉI©ÓîhÐÿ¿BCzŠf¡I‘¶Ón÷[ÄQʂućN·Nû=AÃM:{})ã—õCgª +TÕ©¿¢âh€mFXœnø7¯ÖO¶÷֕ÔÉÆÒµ±ÆS£ÈñGðCÙVUÂZ¸N–Ó D‚Ì ¶<$Á¤kùõ÷ÉG9øš?ƒåÆlsendstream +endobj +320 0 obj +507 +endobj +321 0 obj<>>>>>endobj +322 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS04±Ð³P072PIÑp VÎO+)O,JUpLÉÍÌË,.)J,É/*VðMÌ+MÌÑ Éâ҅h҅ê22 [Z*€¹!© +‰é©ñ9ùé +n™9© Y×®@.Þ¹%ªendstream +endobj +323 0 obj +127 +endobj +324 0 obj<>>>/Annots 25 0 R>>endobj +325 0 obj<>stream +xڅTmkÛ0þž_qûÔÅvB\Æh»·@7¶Ö¥ÛGٖc­¶äIJÝþûÝIÎKcDbßór§çògC„ŸÒæK(»ÉU>™}Ê ‰ ¯ñ>>>>>endobj +328 0 obj<>stream +xÚ­SˎÓ0Ý÷+ΩHÄy´JÛÙ ÎPÄ,†Ç4#¶ãÆNcšØÁvõïÇNZ h„’Edßó¸'÷~ŸÄˆÜc–ú7¯'×Ù$|¿B¼@V¸›t± )26ý z¼S¸Å’…Ø·šãæáó…ÒØ®ï®×o_gßtŽ8¡A’’¹‡f +ù@o [ [rwTUªrïjëšJv5òEXy:g.H¶W¨$ƒÇ¾y SïL£Tõˆ°£:ÌÛÆ„;š¸d¡»Ãæc¶¹¿´ dgsNû¬4^Oϔ—¨)­öšÖÆv‚q†^ØrlÆRm}¿œ%$")Á'™sU‹’v5eÜ÷ìù]LñŒ$ÞI%äa(Ê©Dk†’g¬ýîªæ¶T bŒ‘ñN8­‡ûÛ!dG§Y!-׿…DÊjÇ4'Ád¬™ž À)‚ÎÇ~†—Å¥2VҚ‡Ï£!?ÿ†ï;"Ëÿ)ß+}ØkÕ6á¿ya, wcË|Ž5”¬Žœ3«°ãþ¹Ð‹!ô¯B2Õ˜£±|˜× EÁ5—?¬‘Qry’ŒçK—A¼š;6ìÆV¶§nSÖ>a¬¦Viƒ;*[:Ìd0‚EyT²ô‡‰#Y"úûUÝd“/“'y(µendstream +endobj +329 0 obj +475 +endobj +330 0 obj<>>>/Annots 129 0 R>>endobj +331 0 obj<>stream +xÚÕ[ÝrÛ¶¾÷S𲽨B€\:öq§þ%V@‘h‡=¢èRT<~ûb± p,@=O2ãx³ØÏÚ°¿ðßW¬(í_VÔ¼¨T±î®Þ/¯Þݙ‚—Åò¡`ÒªÅróÝrõiÛýCqÓïÆf7î¿_þuõŸåU¹(-|aðåã@ª’ ]t…ýG±-îüÕúá±xw' Æàǁœ²KíûchVë~HU-*˲ÿ¹˜ývÒ*V1«ç eÍR³#‚ÌòîNì6(^YŽUøþe?6]q4À鬸XÈ•ø„öû—føÒ6Ï'ØÂÌȨ9»•Æž£®ÐÂj‚iÖbåÂÑÛ~}èìÑÁÝí²Ÿ=Mjnö“i“ S:7§µÝz$&“ ÃÐÇý֌Ïýð_Yœãóô2™’ { 8¥døý)™PO'eÌeOr %—–y©nClÂyh·›d\¬Š¥ P± nµÛ$ԛ„!9ÿÊ\Ä'¨ŸvûqµÝ&?[b!e}Ü ¯,¬vóç÷Î]ô2ՙ‹c#}‰¶®ˆx+Éòl3HŠ¢–ظ ”I¶âY ƒ|s߆u“Ú¸IÎ:d˜_àÐnÛý8´ŸcÛï.ê&Nï\Ía窚²ßÊFE¤|¡n•©4úõÍ߇vh:ßdQ僆R“±+cÐç<ìvKOò—tŒæ`Úҁ¸SüÄ`´€À"K›‹ùI•–SHBbÊå*­þU :‚A¼ˆÀˆ­Î D…qÈ,cä;˜÷ín5¼¤ök‡›Éx樁è2I'ÒJjL½íyÂïßHH+iлVé„Ôƒ¹¼1BC.¡äR#ÅëElÂÉÖP€;C2F#6¡}84‡&y’䤠0¯?ñ ì×Õnõ趋Úì²Q›eZꕐ¾ÿbˆx+¬„BŸŸo\yD#l•!›¶O«M×Âúˆ ZßàlBÑÙº;´öz^6Sʚ½âÎõאÁ ¸J›:·½I]´µ7”X±«3Š®@mÍc(âÔ¯ý¦}xI‡Ëçî¢_@t¡÷œô%ö 3 fÐý—ìH™wŸøÏ}Ú,,"C„dx¨ûÑnÙjؤŒ<Ƀ‘!ŽÑpâe}fмÔ_Áá„‹ûNß*À1ž¹X%NœÝ‰àb•Ê×V]ÿ%ƒLò;ºl,D#¾ŠZzþôÎe¤Ê2³ +npdìŠHLÆâ¦:3Öâ¾_ŸàÂÖöìú•Y‹Õ84VÆn2Å4MŒï›1= ÄíQU c!Û£%+‰@kîW ùê¶yX¶cºæž>“A"’¨áþ"1™‹i ÀiÉ$ Ʉ9âú¼ùú«3I£¥‹¿»`*]}cÓÕµ9*"¦âú XˆõƒónLÍåæ¿ÒQáccì~ è¨è1Ä/­ +;z/33-³Út+¨’‘ +TÝÛû¡Þ7~3…™‹šYõ*zc ÑB*P¯òÏ)œzכÍÐìq¶«/~ª¡—â8…wÅ<—âüüNGb%4s#(âcÁÓ¬C;ºWT±3:è,3g%ø¼¼G*8%øé×G|¹êÿ¢ Á¡¼ËuL<â74Žÿ}ØPc@ÌîU_N=#pç‡u<ž×4ü¾Þnûç™:áŒv +ÇÎڙ*ž‡+8ß6;wñÜ ‹™ÅQ–™øKšÒ2¨„¤ŒºôÒÍëÃøyùòäÆé¢²Gx&2“{8B^ü‰#—5èS@7×b%åôÿ‹rÜÏW!à:ò)œf« ÜCxúmչݫ/û;¨Ó¤Pyü]6MU*ìŠ2Ô-…J…ËQ\Ãøž +¬Æ~ض>>>/Annots 177 0 R>>endobj +334 0 obj<>stream +xÚ՘ßoÛ6ÇßýWðq{ˆBRü!>nÖtV «]ô±ÐÙVaY™¬,è¿#y’(µ¦Ü—ÆK‚ đó¾<Þóς +ߌ¤ÊþlªÅëõâöÞNÉzK˜4DiAÖ¿¬ó¿©·ä®>¶Å±=ýºþ²x³^ЄÁþböׇ·Dó„•Ê$#a)O$Ždeñ“͎ÜÞ Â˜ý@Ía®‚¹ð‰«¯§¶¨Þ6õÓ£ý,E[Cò‚_̜õö ~sž(ð[ÊÄàÝyOa ܗ åYP°¶"†MAhîPuSåþ4@döò +M¾8 jaêFè¨ F~UYIûõ±pž +“¤×áéœ{Ò([랄{àGƒ{Òhwîmêã¿Î=ɯ¹ˆoÔº¦Œ»â¸àÿFÇnï%^g˜¤©¿Íò|¼ÐIÃɎhÎÚQnÎS‚•pýÄtSÞÜqÞ7%d±&rE¸)šõþv—P„ÛZn6õÓ±-;w|éµD§?Æ4ž²¤T.Ó¨ ҇ôÙåeH^RjŸq>í‹&’½LE´½Î#&š‘ÕÖçAÁZ{ܞ_HB»îRêñ!Ár€±Ì^ÆÖMèöµx.·Îô"v0œ€°?ë],˜¢SÁ`BèåÁg@n#ï…bl6 DêRº+T~0Ô@)„Ïèëý\ ì8Œ*{6!íˆÊ7›âtú|ˆê@|µcd7™Vi còJ +͜è)u…Æ+ãè)óuæёcŒ ᐃf$MS7qÉ„½s*Ñc ÚØ ®~-ٓ‹Ñ¡ªÐ^t7Dgم’#ÅdS +šç1ß3zgÌêMÇ4´gµ³ÿÚ¶ß†b)€@òƒï4f—*—±\Ðg¦84#'Ör˜€#l9sLÈùx‚öà<+X-•Íî#š‘u÷ñý*ÒO «­Zbº/´#ë¹l÷1©D°/ّMÅáÎVËw¯—î1bƒíE‹ëøåZ»Z ìÛʾ×÷ùŠðiŸ·‘¶g T¶õ×c$šUžHìÙ {Ïš#ڑäô~åÞDéõ¼þf¥WÂèv†¼)”ôá÷ú9¢÷°ô¶¥{ÄA3’~‹µ™ÃZ¸xNÜ„fý¹uÃRÛ~ãÚtW·åî)ÖH‡ û0â½p}g8r҅Bì}ÄåY¦¡øŽqð íaÛ:ò8 +W„Cž3N蜅tåb4¥?!BgƒO2W!}ˆ¸A|òÒÐCŠ‚æ 1>:B š/ ;¤`D„´ÿ`Ðu<÷ñº |¾…«mÛffÌ D\°¸¸ +'ðIR´eé'„\f?lØ6íÿ±™a!¹w¯&\e½l«zÛ>çpˇª<–§¶ÉÛº9‘wùñ)?XÞ Tê͝e‰òüµø ©jxendstream +endobj +335 0 obj +1081 +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<>endobj +356 0 obj<>endobj +357 0 obj<>endobj +358 0 obj<>endobj +359 0 obj<>endobj +360 0 obj<>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<>1<>2<>4<>]>>>>endobj +xref +0 395 +0000000000 65535 f +0000000015 00000 n +0000000228 00000 n +0000001785 00000 n +0000001859 00000 n +0000001941 00000 n +0000002019 00000 n +0000002096 00000 n +0000002175 00000 n +0000002251 00000 n +0000002332 00000 n +0000002391 00000 n +0000002496 00000 n +0000002601 00000 n +0000002706 00000 n +0000002811 00000 n +0000002876 00000 n +0000002961 00000 n +0000003019 00000 n +0000003102 00000 n +0000003161 00000 n +0000003221 00000 n +0000003305 00000 n +0000003329 00000 n +0000003380 00000 n +0000003465 00000 n +0000003489 00000 n +0000003593 00000 n +0000003698 00000 n +0000003803 00000 n +0000003908 00000 n +0000004013 00000 n +0000004116 00000 n +0000004219 00000 n +0000004323 00000 n +0000004428 00000 n +0000004533 00000 n +0000004638 00000 n +0000004743 00000 n +0000004848 00000 n +0000004953 00000 n +0000005058 00000 n +0000005163 00000 n +0000005268 00000 n +0000005373 00000 n +0000005478 00000 n +0000005583 00000 n +0000005688 00000 n +0000005791 00000 n +0000005894 00000 n +0000005998 00000 n +0000006103 00000 n +0000006208 00000 n +0000006313 00000 n +0000006418 00000 n +0000006523 00000 n +0000006628 00000 n +0000006733 00000 n +0000006838 00000 n +0000006943 00000 n +0000007048 00000 n +0000007153 00000 n +0000007258 00000 n +0000007363 00000 n +0000007468 00000 n +0000007573 00000 n +0000007678 00000 n +0000007783 00000 n +0000007888 00000 n +0000007993 00000 n +0000008098 00000 n +0000008201 00000 n +0000008304 00000 n +0000008408 00000 n +0000008513 00000 n +0000008618 00000 n +0000008723 00000 n +0000008828 00000 n +0000008933 00000 n +0000009038 00000 n +0000009143 00000 n +0000009248 00000 n +0000009353 00000 n +0000009458 00000 n +0000009563 00000 n +0000009668 00000 n +0000009773 00000 n +0000009878 00000 n +0000009983 00000 n +0000010088 00000 n +0000010193 00000 n +0000010298 00000 n +0000010403 00000 n +0000010508 00000 n +0000010613 00000 n +0000010718 00000 n +0000010823 00000 n +0000010928 00000 n +0000011033 00000 n +0000011138 00000 n +0000011243 00000 n +0000011349 00000 n +0000011455 00000 n +0000011561 00000 n +0000011665 00000 n +0000011769 00000 n +0000011874 00000 n +0000011980 00000 n +0000012086 00000 n +0000012192 00000 n +0000012298 00000 n +0000012404 00000 n +0000012510 00000 n +0000012616 00000 n +0000012722 00000 n +0000012828 00000 n +0000012934 00000 n +0000013040 00000 n +0000013146 00000 n +0000013252 00000 n +0000013358 00000 n +0000013464 00000 n +0000013570 00000 n +0000013676 00000 n +0000013782 00000 n +0000013888 00000 n +0000013994 00000 n +0000014099 00000 n +0000014203 00000 n +0000014307 00000 n +0000015075 00000 n +0000015181 00000 n +0000015285 00000 n +0000015390 00000 n +0000015496 00000 n +0000015602 00000 n +0000015706 00000 n +0000015810 00000 n +0000015914 00000 n +0000016019 00000 n +0000016124 00000 n +0000016230 00000 n +0000016336 00000 n +0000016442 00000 n +0000016548 00000 n +0000016654 00000 n +0000016758 00000 n +0000016863 00000 n +0000016969 00000 n +0000017073 00000 n +0000017178 00000 n +0000017284 00000 n +0000017388 00000 n +0000017493 00000 n +0000017599 00000 n +0000017703 00000 n +0000017807 00000 n +0000017911 00000 n +0000018016 00000 n +0000018122 00000 n +0000018228 00000 n +0000018332 00000 n +0000018437 00000 n +0000018543 00000 n +0000018647 00000 n +0000018752 00000 n +0000018858 00000 n +0000018964 00000 n +0000019070 00000 n +0000019176 00000 n +0000019282 00000 n +0000019386 00000 n +0000019491 00000 n +0000019597 00000 n +0000019703 00000 n +0000019809 00000 n +0000019915 00000 n +0000020021 00000 n +0000020415 00000 n +0000020449 00000 n +0000020483 00000 n +0000021274 00000 n +0000021323 00000 n +0000021372 00000 n +0000021421 00000 n +0000021470 00000 n +0000021519 00000 n +0000021568 00000 n +0000021617 00000 n +0000021666 00000 n +0000021715 00000 n +0000021764 00000 n +0000021813 00000 n +0000021862 00000 n +0000021911 00000 n +0000021960 00000 n +0000022009 00000 n +0000022058 00000 n +0000022107 00000 n +0000022156 00000 n +0000022205 00000 n +0000022254 00000 n +0000022303 00000 n +0000022352 00000 n +0000022401 00000 n +0000022450 00000 n +0000022499 00000 n +0000022548 00000 n +0000022597 00000 n +0000022646 00000 n +0000022695 00000 n +0000022744 00000 n +0000022793 00000 n +0000022842 00000 n +0000022891 00000 n +0000022940 00000 n +0000022989 00000 n +0000023038 00000 n +0000023087 00000 n +0000023136 00000 n +0000023185 00000 n +0000023234 00000 n +0000023283 00000 n +0000023332 00000 n +0000023381 00000 n +0000023430 00000 n +0000023479 00000 n +0000023528 00000 n +0000023577 00000 n +0000023626 00000 n +0000023675 00000 n +0000023724 00000 n +0000023773 00000 n +0000023822 00000 n +0000023871 00000 n +0000023920 00000 n +0000023969 00000 n +0000024018 00000 n +0000024067 00000 n +0000024116 00000 n +0000024441 00000 n +0000024572 00000 n +0000024824 00000 n +0000024845 00000 n +0000024940 00000 n +0000025042 00000 n +0000025062 00000 n +0000025193 00000 n +0000025963 00000 n +0000025984 00000 n +0000026125 00000 n +0000026511 00000 n +0000026532 00000 n +0000026672 00000 n +0000027590 00000 n +0000027611 00000 n +0000027751 00000 n +0000029183 00000 n +0000029205 00000 n +0000029345 00000 n +0000030236 00000 n +0000030257 00000 n +0000030370 00000 n +0000030567 00000 n +0000030588 00000 n +0000030742 00000 n +0000031718 00000 n +0000031739 00000 n +0000031902 00000 n +0000032912 00000 n +0000032933 00000 n +0000033064 00000 n +0000033568 00000 n +0000033589 00000 n +0000033702 00000 n +0000033913 00000 n +0000033934 00000 n +0000034092 00000 n +0000034892 00000 n +0000034913 00000 n +0000035071 00000 n +0000036059 00000 n +0000036080 00000 n +0000036238 00000 n +0000037259 00000 n +0000037280 00000 n +0000037429 00000 n +0000037952 00000 n +0000037973 00000 n +0000038122 00000 n +0000038815 00000 n +0000038836 00000 n +0000038994 00000 n +0000040093 00000 n +0000040115 00000 n +0000040283 00000 n +0000041322 00000 n +0000041343 00000 n +0000041492 00000 n +0000042314 00000 n +0000042335 00000 n +0000042485 00000 n +0000043361 00000 n +0000043382 00000 n +0000043532 00000 n +0000044880 00000 n +0000044902 00000 n +0000045042 00000 n +0000045854 00000 n +0000045875 00000 n +0000045988 00000 n +0000046181 00000 n +0000046202 00000 n +0000046351 00000 n +0000047140 00000 n +0000047161 00000 n +0000047320 00000 n +0000048479 00000 n +0000048501 00000 n +0000048641 00000 n +0000049219 00000 n +0000049240 00000 n +0000049353 00000 n +0000049551 00000 n +0000049572 00000 n +0000049726 00000 n +0000050419 00000 n +0000050440 00000 n +0000050589 00000 n +0000051135 00000 n +0000051156 00000 n +0000051311 00000 n +0000053634 00000 n +0000053656 00000 n +0000053811 00000 n +0000054963 00000 n +0000054985 00000 n +0000055040 00000 n +0000055145 00000 n +0000055289 00000 n +0000055392 00000 n +0000055497 00000 n +0000055662 00000 n +0000055770 00000 n +0000055885 00000 n +0000055990 00000 n +0000056098 00000 n +0000056206 00000 n +0000056322 00000 n +0000056420 00000 n +0000056589 00000 n +0000056745 00000 n +0000056845 00000 n +0000056960 00000 n +0000057084 00000 n +0000057192 00000 n +0000057312 00000 n +0000057477 00000 n +0000057584 00000 n +0000057750 00000 n +0000057855 00000 n +0000057973 00000 n +0000058089 00000 n +0000058217 00000 n +0000058348 00000 n +0000058470 00000 n +0000058637 00000 n +0000058757 00000 n +0000058873 00000 n +0000059031 00000 n +0000059123 00000 n +0000059230 00000 n +0000059341 00000 n +0000059442 00000 n +0000059595 00000 n +0000059691 00000 n +0000059797 00000 n +0000059903 00000 n +0000060008 00000 n +0000060117 00000 n +0000060227 00000 n +0000060341 00000 n +0000060440 00000 n +0000060576 00000 n +0000060674 00000 n +0000060772 00000 n +0000060931 00000 n +0000061046 00000 n +0000061166 00000 n +0000061285 00000 n +0000061390 00000 n +0000061539 00000 n +0000061641 00000 n +0000061776 00000 n +0000061898 00000 n +trailer +<> +startxref +62126 +%%EOF diff --git a/doc/sam.shtml b/doc/sam.shtml new file mode 100644 index 0000000000..56f4d1a00a --- /dev/null +++ b/doc/sam.shtml @@ -0,0 +1,1088 @@ + + + + + + CUPS Software Administrators Manual + + + +

Preface

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

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
  • +
  • A - Using CUPS with SAMBA
  • +
+ +

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 +
smb://[username:password@]workgroup/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. + +

A - Using CUPS with SAMBA

+ +

This appendix describes how to use CUPS with SAMBA. + +

What is SAMBA?

+ +

In case you haven't heard of SAMBA, it is basically a software package +that allows you to configure your UNIX system as a Windows file and printer +server. It also allows you to access files and printers on a Windows system. +Like CUPS, SAMBA is free software. + +

SAMBA version 2.0.6 is the first release of SAMBA that supports CUPS. +You can download SAMBA from: + +

http://www.samba.org

+ +

How Do I Configure SAMBA for CUPS?

+ +

To configure SAMBA for CUPS, edit the smb.conf file and +replace the existing printing commands and options with the line: + +

    +printing = cups
    +
+ +

That's all there is to it! Remote users will now be able to browse and +print to printers on your system. + +

How Do I Configure CUPS for SAMBA?

+ +

To configure CUPS for SAMBA, run the following command: + +

    +% ln -s `which smbspool` /var/cups/backend/smb ENTER
    +
+ +

The smbspool program is provided with SAMBA starting with +SAMBA 2.0.6. Once you have made the link you can use the smb +method in the device URI for your printers: + +

    +% lpadmin -p printer -v smb://hostname/printer ... ENTER
    +% lpadmin -p printer -v smb://workgroup/hostname/printer ... ENTER
    +
+ +

The second form only needs to be used if the Windows system is in a +different workgroup. + + + diff --git a/doc/sdd.html b/doc/sdd.html new file mode 100644 index 0000000000..e73dce1012 --- /dev/null +++ b/doc/sdd.html @@ -0,0 +1,569 @@ + + + +CUPS Software Design Description + + + + + + + +

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 + +A Glossary + +
+GIF89a¯ÿòÌÌ̙™™fff333ÿÿÿÿÿÿÿÿÿ!ù,¯ÿBþXºÜþ0ÊI«½8ëÍ»ÿ`(Ždižhª2€0p,Ïtmßx®ï + + +;±Ýíˆndý !¸ ž³wà…MƒƒY~¿{,gÚ\‚äé +Œ×Ø(tÙî!Ï=Ñ.ûz¯áџ:ì;Ã9qöíÉë]/¿ºÉ¤Et/†'Îþt9Àؖž_ÙÇ\|W•wArö¸Ý2Ô× +tN°0Tï}¡û‰$!‚yMxî)ˆš‰Ôø@nB°U½ÊwE„§!ŠF H L8B +c‰;ždŠ-æDVWdг€h±äړP¶%#(4Fiå•Ï\hŠ:Re!\ÒėX^¦%€¥À-$E€Ö/úHŽšlââöÌQX + + +¸1Nô¯b"œŠüjåÁÂE0…È8ö5GkZ|ÒÁwt„C»ÔQSÇo6Ôِ[W„$²*Ž+4Pb-8¹P1þ'8"‘ФÄ$ Cyê‘„)>ãŠtè`Ð3‡‹¾z"«rE'Âqfä°Ë +‘qÂ\|€„Ž¡ôö»%É(.—bڽȀíÉ`{¬EÇ1w’ »[Hß`(B6ö“  +†')ÊRŽÎa[ÃrbC!T尌 +2Q·ÈHZê#–®üË/àô¯FÝê(Û²% ºXË9öÀbÁ4f.ù-oý™XËB…IÎÒ7¹*@ÃӎÍT€hà‘ÌW␙Ã$f:µyžn†ó†r„'téKv` +Ç+dª– œ79sò|'=×¢Ìx¶òœÿ„¦œˆeÎ;*à$þ” IÝÆaÏ{–3ŽÅÁ +P“ÍS[ÙL¨3©òQ7éÆò#ãûô0F×ðsE°t§@‘ØQÜ´´ ©:3ÓRíd ¥*MITnŒ£¨H]ØQÁd +@òþ—¬rMœŽaO + +rë^yÀ·(¸îéêû$uDòrã/a,I.°ÙUÀœb hˆ`¾B ë" +Ü`HØxȸo1þ[á\8f^æ|\ý‚¢¢zø0(ˆ\ {ƒÄgäÞõ€çâ§Á˜0*\³n¼‹m¶/Äeª±ÿ†ì +Ç,½DN2€œº+ùÉ|í0L¡Le*ð¸Ã>­2ëf,eIPOËÅàr—±”80SAŸcFªatç»ãy¤¸ršçÌ¡5ïoõËsžï|¿8˙Φ¬þ,ï¼èà)ÁÌ;øk¡—†dDpÑòø2¢qfHã!˓~ٟ-í +'g:,æ4y?ýäP‹Z›ž#ÏÕ´Î5AK‰k]ûš›ÒKõ¯‡më€õzØÈƫ؎Ý>B{PЪ.6hf]º?©ÌIŽuO„íM‚ÌÇÜcµ3˜ +61‹NÒ[†W£ ¦m¿­{ÂPâvζKnUˆ[ ònĽ±÷n?l:Áž3ušë¬sP[ÿnn¾çP…WõÔFj[Â÷ +¹vÏ™à‰˜xú'ˆ£ÀÀ†p¸4.êãKÇ¿ÂÁ±o§¢ü"Á|Nk`îʘ + + +jl©ÌuˆËi™0pmC´«+‰÷6¤2­éÏe`(ŽJ]¥iõð3ƒØí"p|ª!:qøFس 6£ +@­,þŠqüぐoÌÇ®žÖüV“¶QǛEvî¹²É8ÙªS"æÀç‡x± àþ‡>—Iãg +ïÝ>Y‰çN80æ§ ±¾GLLìÕµ…(1Þ¼!8}þ¬“*…ª‰Ùì:e»´œ +ª¿ên_6ÂÃSÀ`eG;Ö„CƒCcˆ¿‡4¸yeî¯Í)oøByRm½0?íLîÅ`QÿjÓÙ/ºôÓN|Ý + + +þÙAÜŒÁ¸D5©D aævx ?жx°DM@•!h‰àȀާ® +• á×B`ð¤ªE?›“”Þdƒ"8$Ý`Ki0…OðƒnΓ±µvtžè€I([,¹Ndɨh\'6X +P㗊‰Éøt ¢‘¥˜¬è €ˆ†Ky™FˆŒë`š”yƒ„¨š €š‰ƒM©‡øFQhY„ +9¶X¯×–í4š¤™Y\)"¹AN]‰xéz÷Gq07)©ñ™•Y€r°ŒŽi‹ z ™ÇäFÍÉT–ù› +ËŽC œwI›üX]‹¹\ëY]þf lïYbj8ŸÈuœbŸÍÅtú©fÞןfBI—“*øé:ÛØUj Ò +ˆõ¹ Õp $(~ ¡Ú ¡gù{îpZI?¡ƒîÀv:“a¦˜6¢§Ô]Ý‘(ªê)!ŸÚ¢: +jwµ¡4ÚvíHÛǘ9ºXhó•üù£¥Á¢VÉ{Dº2š‰(°¤3š¤a÷ +У¥“p¢þò4Vº—  +E´¥è¤k°7ºhT*€¿èw`ڞiÄ …S¦Ʀmê Nêƒ#ú¢f€ xê†ý +8z©7uÚp{Ú=~]7`«h‡ÚsÚg:…zd˜ó§ÎA-vþAñr¦'–AÚ)9–š¢âSi;£…š 1ªo"ª +¦J;“º rº8Ui|é>¡Úœú + +“ë¥Dfný2»ƒ–0j«®»ºK;zë¢Íö»—!µ—S»³r>K+6ˆ‹¨XÒ»; CÈ +8Ê;¢»ÃÛ/Œ‹¥ž!¬s½VR½óõϋOâ[/çK¨þ˜Ñ:͋\Ý+ Sc:ï˞’º¶ë9Æ» + +ô 8ly$ +8©ÙÅmX2Ùh>—?¯!šHüÁ^LsP,Ÿ«Y‹âá¿ÿtšì‚£Y +r¦Éš¥9ÇjžÄ8-ÆÇŒ¶iêPÂbA˜ù‰Ã¸š»³7RœCWRoìŠå MŒŠ”åt™ Œ›réÉq + + +å>}Lê}ÎǨ 5:àŒ|"þÇwÐsøæNΰ¹#R>~-N‰®èƒ ßcðÞÚÎÑ¥®åGÎâ툉Ýè*‚¸ +=‚ž ºëⅭëÀ>Û·žën^žmèÊëð¼ã>å×Λ«}êØ÷ +“Œ¬ËIÁ·AÔNÍëv>]t.âÚLЫþíï¾ñnäÖÜæs¹¿±â°+† +¬UØïî•.ç¬ÎìÍ.è´ÞŠG=ðù‚§ž¯”ë^äÛ®êh-‹êê!i!ÕvMíiªîþ¾òîá/þÑ-OÖGð,oñº!å’gOâ POìOôBþÈàhâ+?ï>ßÊVHÀsaõ™€õ$óSîõ—»ó8.žß¹ +~áßÈ©ö»]ò3ëÆt_÷[ïôb¯ç‚Ü÷Õ«@u™ð;zܘ‘Ü@óŽ2’?ùƒ¸ÙlùF ¶™¯ù›N ž0œú£¶¤ÿ0#9:ß§½ž©Ÿ\#ÃÙæó2é+û‚ÀÓ¸_äM/ÓtaÚý3”]Ù«¿¸iîaF>ª}ŒØvÍïMÍ÷Ðëä©îr܌öqñ_ÀüªrâF®ò +ýþ¸—hT_ã4sx”ýÝî)ç.QgûàŸÏ%ì‹}i´ASû|þð@QÜ +$J9€»-̱÷ÜôMؑhZ˜¦:°œ*ÏlßxÒ|ϼ¡ÅLÀ ¬Áfù9BÑdìÁ|«VV„¢“énKv + + +kB_ƒg 3ʳ8#Þ¬L=0;J¤äÈ@¤F|'i~±© žaʊÆg;d*3²”©bPÏ¢TäHô¦?[† +ÄäƒhN6ZM¢D:c*BR!$±ckƒ’V­-uÛ@[øp„Ÿ]¼8ö-1{TήWÏ2ñ Šp=¸q«Ñ½es.‰„4+#Ëe¦¥W5µekxr䛓/X͚5Iǃ=kÝúµì˰ûN–2qÅ¦yZ£QŽ›ÇޝtxŠäcK—Ííɹ +iþ¡9¼m1oñ¢©/²8îìSté4l’Wm¾9óéÖÛÐãã{{üzÞ¿çøêöÞzà}œàL¨ "˜ +ÄÐsà¶PGLUúå`MÞ  ¡†9¬§Û{pX¸¡wÚw߇¡¨ ‰í "MUXNx + ++l´á¦ +j²F:Á.êÆÛj¤³Búî ¼Ê«/£Ö’[н#í+ð¥ænJÞ¸«æ;ð©õ‹¨ _ËðĊһ*º? +ƒÂwœÃyzh±°Øzl2,#oZ2țr|ò˂°¼$Ç)ë +óÍÙÔ,éfs€1Î@/øîÏPõÌiÐH·ðÃBkLtÒP¯bôS;NÝWÔXÏ +ó’dlÍtÖ`°tžOc óÅa§}Aě²1vËjÇmþu+`ÍÍÁ·qwü6˜‚ì½sÞXŸ¨Ë$xM6àP³-iÉSÚ½Aوïë84–ø=xä8^!ä*L>ޘƒk¹Œ({Iè^!ḘN$ê +«®ç!ºû‚ÿÝ ë¯ßoî—Oü¨¾ÿî9í]ñÞ{ñÙÊ®ãlhŽ(èÌÃê¼~ÔS¢|ö՟zýw¬Ë§|øÝ—*½ŒÈ×­|úåwzþæ“)Nrû¾Ê?*ô¥ +¿*÷ô7ú½~Múúú÷ª÷Ɉ•S3x*ûíP”ùH£°°àó(è¾í-Jƒú™ +åAF{#\”g…Áœ)!),Ô #ÓÂǼjþ1œŒþh©²K„9$ƒYè)Ž ˆA È +—‡)#1‰Óp"˜ð'Ã%n‰P´‡Ù¨-‹1³¢^\%ƈÔp„CLÖ5à + +
+

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
  • +
  • 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
  • +
  • RFC 1179, Line Printer Daemon Protocol
  • +
  • RFC 2565, IPP/1.0: Encoding and Transport
  • +
  • RFC 2566, IPP/1.0: Model and Semantics
  • +
  • RFC 2639, IPP/1.0: Implementers Guide
  • +
+

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

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: +
    +
  • quit - Quits the lpc command.
  • +
  • status - Shows the status of printers and jobs in the queue.
  • +
+

3.2.2 lpr

+ The lpr command submits a job for printing. The CUPS version of lpr +silently ignores the "i", "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.cgi

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

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

+ 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, get a list +of available classes, get the default printer or class, get the default +server name, get the local username, and get a password string. +

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 imagetoraster

+ The imagetoraster filter converts image files into CUPS raster data. +

3.5.4 pstops

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

3.5.5 pstoraster

+ The pstoraster filter converts PostScript program data into CUPS +raster data. +

3.5.6 rastertohp

+ The rastertohp filter handles converting CUPS raster data to HP PCL +and supports both color and black-and-white printers. +

3.5.7 texttops

+ The texttops filter converts text files into PostScript. +

3.6 Scheduler

+ The scheduler is a fully-functional HTTP/1.1 and IPP/1.0 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 Logging

+ The logging module manages the access, error, and page log files that +are generated by the scheduler. +

3.6.9 Main

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

3.6.10 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 printers and 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), "F" (filter), and "E" (enable and accept) 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. +

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..f1bf1f5cac --- /dev/null +++ b/doc/sdd.pdf @@ -0,0 +1,962 @@ +%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<>endobj +150 0 obj<>endobj +151 0 obj<>endobj +152 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 +149 0 R +150 0 R +151 0 R +]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<>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<>stream +xÚMŒÑÁ0…ïûç’Dk׬z‰qÕÈVL0Ú!ÞÞJ„œä?ɟó}WFHº´Dš¡<±‰eùL`·Ð™!ÕJ(ت7]/ +Ͷ}l¼CîB½;Ç*}}iëæÜ·‡ŽU Š,ɑ0à” +ù…y‘çœD‡œ”Ðà2û¸g›ðü¹¾©neÞC•ŠìÏÓ\ž¾Þí[1šwÇ 0>±ŠÏ€• Îß]љeKö^†=¾endstream +endobj +222 0 obj +176 +endobj +223 0 obj<>>>endobj +224 0 obj<>stream +xÚ+ä2T0BCc3JÎår +ár á +äHÉHendstream +endobj +225 0 obj +31 +endobj +226 0 obj<>>>>>endobj +227 0 obj<>stream +xڕUMO"A½ó+*{ÒDf`A÷¦¢†DÝYA³.MO ´öLÝ=ö×ouÏ ŠÆ¸Á„ÐõõÞ«Ÿ[1tøð ½ȼu6m}¿<n¦[Ã>LӃ&’J<œ>k<¬­íAuƒ=ŠaœbáT¦¤pŠŠÚµqܸvQH5]* –2·!E«…ÿ’F•>R’UΩ 4´Rla«Jc +ªÈÈä!?ðŸ["#—Ê¡tgE +’RU,€2€ëƽ¢w>§<ç¸ûÛñHŒb¸ì9ÙX‡9̾ß'“o³Cx@c}‰8êDï(÷;ÑqM¹» ýµB³R¸þ„óçµ_˜ +(É81×Èo4ÀÄCì¬ûcÜ +#‚ц6‚±ƒ¥°{œçˆ^ÛjŽHa¾ a70ÙªŸJ+é,8òrr¬!XÇ: +“î XÒUÝ£Z×,VX¤d¬W}¯neYÁ¼ž;n¾ ߇Щ34O¨qÃ-Ës~hkU ÷ءɄD5Y·*†tœºN5ö~º˜ÌƑ$Í­_L/Ûã$áfŠÚ}.,ϝÇÏ¥ÄÂûzðHó@ž+¬¸(p³öè\{\¡ 7b$Ð÷qvpŒŽàîò<އ'³Ã#˜ð°ý­ „3Mò‰Ý&7gÞê+œ–å„1Œv€Ê•ýØjK{%mUúIভ•[‚AîÿȪBúF­ÜæC}DšZ`YÖdžj†Œinhm=e"!ë&aÛvœ^­ïA’Œx Ú,¾ +v?+ceB×Õ)ˆ²ÔÍ!°P)ÖÃû1bfÏ]—ºª7@VÖQ®þríU³ˆ”ÁÕí=\-wÐg²2†Ï„Þ@ ”²÷^ý¨Ó›îáõ"ˆTî۔ña»qÂC"H~Ÿ£²ÔïĖYAEû•l¬ö³ãЃÑöŽ}á<|õ$²™…(‚: ‚Âlg¤5­Ã¢bû³®%›ZÝcfþRnÖ á->ðí×'^î@nUû(Š“ÂfÈ}à}ý¯Ð‡Žj¦oõùbü)Ç_iâ]3›ÚtÜ˜Ú Û¸íÿïêw¢Îì_ýï‹iëwë¾î12endstream +endobj +228 0 obj +813 +endobj +229 0 obj<>>>>>endobj +230 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS045×3V072PIÑp VÎO+)O,JUpI-ÎLÏQÉE™%™ùyš!Y\ººP-F 13=30ßP!89¿ $êÂÈøÅ Ÿendstream +endobj +231 0 obj +113 +endobj +232 0 obj<>>>>>endobj +233 0 obj<>stream +xÚ­•]“š0†ïýçҝ– êU·ãL¥‚{åM +AӁÄ&q¶þû&¬¶îL±;\€rò¼çã=ú£‡ÀÓ‚ȇaYÕû”öŸÇà{úMæ}Ö¤ ‚°ŒÈ‡ô{‚"â„Èõë Ál'0çÙ±"LaE9³á Ԅû¡[3Ó=‚—%£lg旁J­jßN öú«6fbÁYöG:‰3{ë‡\+÷‚3[År½‰Õ›qVÐÝQX½fxG â³k¾N mï—óù<9IE*X2ED3s"鎙[&èáwoºH$ӕ‘p¶"¼PoX˜æeT*] ÒÔrÄåüëZú‡¤¯n¡cÁwW•1ÁÝY'ë[è„dGAÕI›÷À…ºƒ›Æ·¸)‘÷Z$Ù¼3¿$ÿ3¶×ùm쫦oÿ5¹v»8çŽìûð¢öDœ—Xþã3Μ«%–`øÈ ^. @ÃQäƒv½.|¯k›h;Q¦L>Û~.p¡¶º¹ŒãÇzâÓ<§†ˆKx9œˆ•‘àhs)@Øëç™~ŒÆøB±™šFcRé é=P<ãeg¤ÿ> àœø‚e<7 À,‡T`&;{¿¡†ÔÏIY#RaÝáLvG†ÃñrYÊú×Öÿó‘æÄž5ggúã ±æÿAÁÈsÇZW¿šÏ‹´÷µ÷ dÃßÎendstream +endobj +234 0 obj +541 +endobj +235 0 obj<>>>>>endobj +236 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS045×3V072PIÑp VÎO+)O,JUpI-ÎLÏQÉE™%™ùyš!Y\ººP-& 1#C=30ßH!(5-µ(5/9µ$åÂÈ©ï"£endstream +endobj +237 0 obj +118 +endobj +238 0 obj<>>>>>endobj +239 0 obj<>stream +xÚµVMoÛ8½ûW rr€Hþ\;ɞšd»ð¢hÓÔéÉZÙl$Q!©ù÷!%GR·n·ð…"çë=>Îø±7‚!ýF0ÃdQÖ»Zöo/`<„eB'³ù–q7hä&‡O¨Ÿ$îN—_Èn +£‘· ƳÐY^ßß~i RY¡ Æ ˜ƒQ‰Ý `Êu`žÅÌ€Ý + ª@-,‚U´[Ô´ÚJ”Î8F¦r(´Ì­Ì7`…y0—>uT¥Ÿ‡ã—ì«ñlíÚúW"zÀ<6m?*y4!×לP?`ŠÏpM5ˆc½¯ÿ]gϤ-rK¸E„ðN®µÐÏG…x+Sr?®ÌOÑã2E}œ—»>øÜ¡æFs>üL‡á¹SN8‚ö |G4Ë-º2™)f˜[wÿe.#a¥Ê (ÒÈËlM ÒU,“5[ʚ;›4} ƚ‹Dš’wÒn¹‚>>>>>endobj +242 0 obj<>stream +xÚµVQoÛ8 ~ϯ òÔa³;i’8 ·Ý ··íš>u{mzÑbK®$'Ë¿?R²³ÔëÒØ¡EŒH$?ò#ù9÷£¦ô—ÀlÁÿy=z³MÞ]A2‡uI7‹U§°..fqÏÁ¢‘¢z±þJFsH’`¥ º#£õ;ÈD¾EUÐWUXp|Ñ`.K‰|Õ8 *“ic¤rh ×JaîÈ`'ÅÀ¥‹Úhã ÀÌ1BãL?™…$oÿ}҂.½w©M}rÂ§J%F©Ï4Ä»žP¬I)+|­'µº{ž/ã8þü°ÌÈ;Ÿ,-äBA† ԁ*¨3©ŸO¢ªô^ª/]&y.]QÊÇxŸÒÅúTƒÁE&Úâp–ögF8|˜ÖDpƒ.PÌ.À6\»?é¸zˆ}ÂØ£ÀÒÙ!ð(àê ´jëŒzHU à¿†Ú#Ýaˆ‹;T?Aå+^o0ßÉ¿RÅOéæÿTZ=ÒÔukh¸pÄoÙAö;…IšÍâE¿§—`5mŸ;¿§Þäy{ªÐíµÙÂF[­åDØòϦ¹ Q£ÎuÅPkUÈ +‹Ávfø÷:} Ta +ZšÖ¸uF+ù­ëW~a™}ד ç§Dw×,O-p¥h+D¥›_¼J¦Óï/;êæÓxøMá š-Vx€·T-•`Ï}´Î;kfk' ’ °²n*ìo¢J*ÏA)rdîßÞ~¸á§m³Z:ÏÉ$ñÕÉ&÷(,Ú Ñï×Ñ¡^ ¡!]ÊdÅ㴗nøMZÇ­´ºt{ao#¼ç†[“kö%hê¤ïÀu qz:„iœ@Õäg‰¡û>VIËXÆú*EQKE ’ši:¢<ü„ uµö2î[l±ŸE"Ps$ÅSàÙµmÃ`Êõ±Êçêöqwï[jTébžÔù,¹8Fêê$õÙ09'¥ÓRôËâià) Áñ&ž„§D"¥¯Ucžè9ö'́yQà‰òø¬€žmÏdG9gǾ–Þ«Ê‘È/J ŒåøŒÔü±¿´ˆáÆvÜ¿_ÏOٌ‘ê§Ê¨Á`­w”I-¿ÉjÊg¸@“w«.@r¹¤À‹K¿ð¾²›~EþBKÕð#7Ò'È®Qðˆ–é”]|6Ÿq=ÓÇ~;ý½}ýÜÏ[endstream +endobj +243 0 obj +890 +endobj +244 0 obj<>>>>>endobj +245 0 obj<>stream +xÚ­Vßo›0~Ï_q­”°Xh_—þX¤UÊT¦½ôÅÀA݁b“(ÿýÎ6F»¤“¦H Øßïûî󵝿ôñ!Z@°„´š|‰'Ÿî®Á ÎigEÞâì"ðXݯ/ãÚÁ÷Ýþl±ôB³?#¬dUI÷Lãž`-4Ö9Kž.(ôé¶µ,jV)ó°ãƒ=&³„)Ì@i¦¼Ò(ײMÙݾ)€ŽõoaŽ•9å²!j +iɔBz`"ƒ™(ϕKt妆 èéx~à¥?I¬Å äJ+[Û1^²¤Ä®„gÎgâ[…­ò–‡y`ò6Ê1Ak<ýRŒØq +'Vö©I”’W\ÛTWے”6çu)ÜaSˆDï­v§åX8ÉÎiaÓÿ)Äkƒ 5Ъàö¹YgDÎõGÖ\ee)'èˆP`rè$(?Ÿq,†îkY«+Ì9”s W_ °²´¿r«¹Ԝº³Ó’½¹ÎÊÒÏzĊuÆ"-öŸMÒñ\Ò΀Y8÷®œ$!¬~l7ûOjVNr¼Ö¥ éf€‚ԍTŠ +Ž"Å)|ãÍÖú*™(VÐâÃúáv +›Í»á5S”s¤FވÔõ¹QÎZº+AÉ\ï©û§zÒTX ».Ý_ÑÇÍÉZ‚™•¹IL;¨‹Ä j$(=%õ Z³æ¼$’ÔéKZ¤ŽL¡@ +r—Fæ#ªo¼¥FøûúÑhÖ˜³¦ÔËg1od¿«p:ª ƒ–2%÷£Z”펫dK)÷4 +È[tPqZú…mû47®²Ð£àÝ_”ã +©N–˜jóhᎠ+qäJ5صÞkddL3ÈkYQÝ9ækxíi–¡ÃRÚyšX`»þ1^ّxŸUÅ]‡¡‘\9v¤hÒ9i4v¤Jm)–®šc7bÕr…#»AjõË«¶rÿsDԖ~èÆƒ½dí%ƒT¼æ'­¹½&xæbfÑb>ú¯"¼š{×`W#ó~O¾O~T®¹Qendstream +endobj +246 0 obj +792 +endobj +247 0 obj<>>>>>endobj +248 0 obj<>stream +xÚµVÛrÛ6}×Wì£<#Ò¦înŸ_ZuâF‰ä7½@ÀRBJ :ñßw­´ŠÓNÆî圃Å.?÷2¸¢¿ FSÿãeïíºwy ÙÖ9½™Î³tkÑ¥ãt ï˜ÚÕl‡p_+î¤Vöbý‰ƐeÑ!NɎÖ{„¢5Ï[s¨Œ~’uL fHåÐ䌓™6`ЉORí€ë²Ô +~u5+ Dk)˜ f *fœäuÁŒÇ@™³Q„ZhÎ +Ê ¤Ð¥T>š#@\ƒÜ*®…ßÜô1Ý¥ð¸‚7«›Åb‹Õûd>Ÿ\'ÙÐñts%IF£tÚJ2‡ÅÃÝ+åx¨ 'K’ÁÂsVèàÉî¾ò=IÕÕ©dÊ Çb|÷\EB\«'4–L@0ǶÌ"cîD[W•6ޤ’¤y{®Ûg %Qï&=ºAx(Y—pm]t¢ÑûåF—þ¼tm茜¦µ@ë¤bj°>Iïá¦gu›ÂryûJٖ„iō¬,M(¸E6BþSÍ|dÊÀbá[Kzæ{ä…ú‰[^‚¼ÜÙ Â ,¥kB hƒP¹¾(%mšódgð‘´%دãk¢ñ7¼¬3ÈJ :‡›Ç媵óu@u,‚$[-ÀÅáZ‘Zr§àVóº¤óÞ\@mñ”,U‡Ò*éˆ]5b #}Í9ÎÐã«t9Nà>”Ëyb±¤HÁ²*Ð#‰•Ö©i‹æIòæŠ{’)¼)Šƒ#3d͊‚H~‘nO…Ø´K7Iç'Œ˜Ù¾ö—ˆŠ7¨†sz¶Ngðv¿-3ÅJ„$¨–¤¼_w«¿iÓtFte6é˔Tÿ”ï½…… ¨2—+füD›ò¸éq{iÃþ¦ï³îÐüh¦GRþ<Òªý3³VsÉ\+k'Íÿ µ–®hÓ8¿¾¤IøsÞèJRé4çU—[¢F'Æã¶Áϵ4”ñ?k÷¾i1AÛÎp±•¿}iR±ciØÙMO7 ƒ:›~ Ä +ºÉLló:V㯠ó£IH+¥©“UÈ}-‰Aëã ·¬©ãScaSªªv‡–>£û}Àƀ·é n2$úx8ܨûÎmeBqBæÃ(;™`º@Ç®@7r?îÍsÇÁÆQ¤þÛРӉ¸îÏ·äIšÁ¾ÚNWç;VkԊ±Ð\ý}™üöîrçŒÿ‚ѝ1u>õ˜R;ÿnîƒÕ7ÉÛ³©çMÈl2KG0]ù ah¬tî¾ø“i‡Âq’†ƒŒÉl\æ~o4¹¦:¸úÞWàݺ÷¡÷7¤‘66endstream +endobj +249 0 obj +982 +endobj +250 0 obj<>>>>>endobj +251 0 obj<>stream +xڝVÛrÛ8 }÷Wà±;S)–íØÉãnÚÝffg֝¸@SÍ®Dª$ÕÔýú¼ØŽ“*Ž$‘qppúˤ‚)ý*XÍ`¾ÙMþÚL®þ¾…j›†v–7U9ƒMýf^^—sPØ¡7V8öÍg²]@UEÛb¶,l»ÙãSKhTËiôW´ÞÅ]^Ez×ÞÀݧõ$ãZxQÆÃO@Šù¼\f è7½EMrh¥]ˆÜ[Ї¶p=JÕ(I˜ºNèš ­é`½~—`Ñôhc;òJpÉSé¿ HpkÆ@‘«yäi{OÁŠ6žÃuø LžÌžÑ¸6Î?H«zOy™] ïw(]&Soöý(œ“Y†³'ª˜±‹ ºŒ „çÃÖwÿ^ÝÐ÷†Ø¿'¿ÖX^¿¤²òÿ‚֋ǽò˜KçÆYÇoþUud£gœòƹ2OŸâ®Ò‹iyã.áAî±ÚWŠé²(’4CÛŠfÐÒ+£E 6›õUUV¦û5¿O´DØHWÂi•´è‚È2!oA¶Â9¤vûl¶î‚J¥ƒƒ;PEºî=ˆÖ™cå8Õõ-ÂÖQKª[±k¨•EIò; JÒ&â°Ø™\ VbË\ÄM¸@ + [!%:>×[¡]/,jßbç1¾ÖHâ ¡©ò’úsð{cÕwÁ̍r.Î-¡3Ì?ÓoÑõF;µ¥OjóÜí¡ÁP…·¦ ¬ò)WÉx ;ˆ6ì…Ä©tyD8@æÆY F³›Á]$n4¯LîÏ3 +báÀI)G— =¼r÷¢,©#[ ’Ó\dkD_Q€spg ¸‚Ò,Š:ÎÔGK½õ{T‡ÑÚ 61K½7NϜèQDê+ì°É9Çê%K¾êëB“äþhñ¤™HÂ琹y6ø¡ I>}„”šŽL¦ †æ4_=^}ÍɞYoì 4áà—-K(6¶C]ÓÖEàd’cb¹AÃ£o.Ê9¡&/p‚ßP>K•&!ZžJwÿÜ_M׍ã«P#ÖÜÓ&ÏuxÄm IiBç8/üÀÑŠÆ ,S€\Âÿ´>>>>>endobj +254 0 obj<>stream +xڍVMs"7½ûWôÑ©†ûº&‰ÚT‘ï]h£ÍŒ4+i ä×çµ$0œ²«€Q¼×ýº5?nF4Ä߈ÆSþ—õÍçÕÍÏ¿>ÐhB« N¦÷£Á­ŠÛñ`:˜Ð£5½mښŸVßa;¡Ñ(ÙöïØ¶«R‘<·¤Úm¥H{rÊ7Öx½ÆÏuø- +m¶àóø²Xv7v¤ZTúŸlÌɑr4NðDÓ8Û8-‚¢BA>¸V†é¢ûNT­òºMTÞÂÉ6>ÁðÊí´„÷Z¦:ÇÙI}02á‚gšÄ&(I¾c^ +N£LL2He}mAŒÚ[ð‰æÚ)¬;Ð2C¼Ú‡âd~b”{e +Ÿ¡J­v8A ãrÔQ0¯N»ÃcAkgE!…ä­üK…}Uµ ݒä8)º¬„÷ÜTQ´ÁrD)ªê@¢(TAÁRÔAmœ­c* £¢S ª´GQQ1£Ü9õÿã,¨¤Î”?fìÑt8¾ÌÔXzTÚ½â#º:@ì×ú€UÝVA7,‡¢€|–"‡é¸Øï)=/WŒó#»á+dáGNý€àCJ)$‘Ò:ÖpuÐË×gž ]$²Ì8r\ô¡TNõ¥@ݵ2ï±m,ˆr²8q`,Ì!FFDn!W•Ú—Z–Tëm Ùè¨Tρeá‰ÎV¬è£D.è#õ`óμ=­V‹úzífô»]_ŸŽï08V¯FlCOz”GSzáZ@÷ÜEgeê)o±XUô¢um±¶¬ó +¬¶‰ ¦Ì¢·^åTþ<—¿Nóž¾Øí}½Ê´J6]²¯mè‘rκ„»Á!»ÄýÄV"ÄùÝ*£°¹ õ!µX–Š~ЊúCèëF ƒ+÷DÐ5÷mˆ ídÉÏ´iòSœòW¶O¢emìˆ Ëÿ9D•wš±ç8¹ÚHó$¨Ã õvùüÛÓKgocÊ·†O_æ]K¯·©{ UaCøóñx{!œm‡ØŽà㘃}ubê^ҍú[‡D3Ò"/é«]9mò˝‰Râšýgë/óÌEçepÀÜ×éîDíÞ弉ø*L‘öN‡¬Ô“ßۚ½Òe“!F#ҝÑ2&§ox©·¸Núd-³5y‡Í…eèìºõáxÒ¯´ák 6B*^ñ퟾]×:Éò¸àš³ŠŸó… /Lá>ƒ}š Æ4FX1êÒnžÇp®XPü!nŽïbýäÑŸÝ Ùe4ä‡ã‡É€_ò.¿Âý²ºùóæ_<™;Lendstream +endobj +255 0 obj +984 +endobj +256 0 obj<>>>>>endobj +257 0 obj<>stream +xÚ­•MoÛ0 †ïù„O-xu>»c·¶X2ÄÝ.½(6¨“%WRZäߏ”â,m{†LB½2~H~dpAŸ c˜Ì¡¨ŸòÁ‡ÛM!¯he~™¥cÈ˳IºH3E?ÏI4…,‹¢ÑxžNY”oñ ÂÔµÐ%xTʁ§Wl±Ü)´àM«Òøfí 2\ƒ…¬d•Ú£ui ô›f4™¤ó–f …ЪNš(é£9¨ŒF ŽÚXŒT~+<ú÷´Ã–2ÀI½é†›@)X+ì¤;húðœ7Í1n$3:ÊbÉíïj6Ô½TQÒ%¬ÿ?T3PM'‘jŽ4n·®¥wÇïJ*t¯÷ZɟQ»œý÷l~° •Plj6†cãÛ*ì^WAOÍoc©¸Q·H+¡àðp¶\^‡f<œ¿‹Ëë´FÙÑj qÃ¾ÃØ³#ÞNç!`cͳ,i˜ù¢0º’›yyFFÇ«BáÉËcIc ´o¢‡:ýLG‚h!bôœŽ5‰ÆØ÷ô‘%Ç6*éü±‰nØö.¦Ž*1Z¤îÒ©(a½ã¹sh»Y.iÓ#Ý,QÒypÿñ-py–ÍøvÍ²“³º2•á^]££ÃÁ_…•a"xó(î-Æz•MSJ,,e;nòÁ·Á/,W%Hendstream +endobj +258 0 obj +664 +endobj +259 0 obj<>>>>>endobj +260 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS045×3V072PIÑp VÎO+)O,JUpI-ÎLÏQÉE™%™ùyš!Y\ººP-†F A#s==@c=3199µ $åÂȼm"endstream +endobj +261 0 obj +117 +endobj +262 0 obj<>>>>>endobj +263 0 obj<>stream +xڝ”M›0†ïüŠ9¶ØÀ"²=¦(ÉFZm©`¥^g̈́uãj;òïkC+u¥`©3<ó¾ž1?’VþÈa]À}L&Ÿ»än÷ ŠtG©Ö%tý‡ 셶Íõc÷}JÈ×sBZåY1¥d9td¤3*Èóá©iQe¥žCåÐ˜–ãّj8ã@Ù{Púwúˆ… ± lIõ\   bƇ‚Ô†À½¡ò¶_¹ô'8.ãùH1õZQzÁkp!ϊ3t\+ ̗Q$à•Ü…H»h J+gÉpü/wÿàÉjv"sååN®”—¯ÍiÁ]ö~&R?Ki¹Êæ©(`ÌVר`lÚúpˆ‘~9˜oXëPõhz¨uOpôîÊ_å¤Çßûñ šЏ®_šv¹TízÔËóá4†+¶½ZG2Âܶõ]³ Ý6í—çâ§dl„¼ë"ܝAehÚi¦E„öؤû§eÞ#]9—6ÈNAèÞàøÆ™…§ß[rþôázjôÿC¹.}÷W!ß‡Û.ùšü0£7endstream +endobj +264 0 obj +424 +endobj +265 0 obj<>>>>>endobj +266 0 obj<>stream +xڝ’ÝRƒ0…ïyŠ½Ô °´@ñ²?0¶Ó8Ĉ4ÅXH4¤­úô&¨íÔâÏÀ՞ÙosÎî³ãÃ@>Œ"ó—3ÅÎUïޘR^ x}qƒ\4Ë.ñ£Öƒ“î#/ètz¨©R."å–È5 ɸ¢f‚+)jȯv¤¢„¯ îBXþcÄRÜÿ¿HpÚ_§ +^1N©fW€I»…TÈÒÊEèØî±†‰¤P¢µX¬~"Å'5Šðµ£…•¬go`aghÞÏδóc¬sB+*_äI?+ßՊ5tÍCÈ «!y)ô¶l‘Z/ é5ÿ嬐Í1­*JɞÔÉ7m»‚=Ç"ŸöS *÷š”Ó¶5Ö¢ÜZX8Ŗ’í™^uÊj +XÞn4ûüŒâϾ8ôFÆ×^d:gw¨€BlԁHj|±Š·çúáX÷¸ãáÀ´ø)~ì…Ð&Þ&¥üµi”`çÖyë}%¶endstream +endobj +267 0 obj +374 +endobj +268 0 obj<>>>/Annots 117 0 R>>endobj +269 0 obj<>stream +xÚ՛ÛRÜF†ïy +]&YÏùpƒq¨²+Äl`½½§h;äé3‡ÍÌÔ΍W¶«€¦¥é×èï֌ö¯3Ú÷Ÿ6š5\5ËõÙëùÙ«KÛ0ÒÌï*m£´hæ·?ÍWm³½kη›C»9ìž:{3?#3âþ õ_>¼õA£¸œ™fݘƒŸW͍gmÞß7¯.eC©ÿk~7å6u6/â3r݄o?fr³ÜîZbÒÁÝ/f“ÿG_Ñ~ÿÒö_ºö«Ç :³“Q\ZåÔÅc—V»8(ÎŇ?ž+äu±]>®Ý0}™W"P§nL±’¹ßXv:j»RÙÁvãσ;d“•šD{dã&›`ÒºqXÑB6Q>´wmßn–m¨ÂÎôĽ–#ƒVªl±1xÎb¥ÔÑj±‰h˜S¬"BHç^ߌ\’¼·¸’ø‹R² ¬t' f­Ôi/ ¦ºàٜcPXE¸MƒÖ˜9'Ž!ÎU*¤ôûá¡íGÄλ{oö\Á °$vºØ$î>nT»¯`áç笂†[œ#F(F`ɊÙÀ¸h÷ÝýæeP±³;(3! mžñäiúDÆ;áÑ\è Á³.CDtYŽ» ­ôC³$BH¯ËÏíæv›žz/K§™“NX<Ðú.?p¢î!FX Ð 6&Y±³ï}É1 +òëv;O¢|6© L(­ƒÅs A!”6Ѽ¼P  +H T‰‚<ÀV»ÛQ(%B;Ï%…PJÆVÐ Å1¡€D™ïƒ*ä¶[ô‹Õª]yŸŠ‡a2IÜ9žI +™ä ’ÀDeþ†«@¨}Ûw‹ £zÐTˆH\Gg‚B$n;ww"(îq¯BA`û­sôCJOÆÏÕxý.;¹ßL&Çú½ÄqUÔHéuÛnWíӈæ²8,*¤«Ï´óíz½H5Ô8W8±æØ˜¤´(!(Æ$e©0¼bÉV£ ÏR!X†B@&֞!Jqkr%ˆAVŠ[›*CKf"Qbn©Ô[íúR)#s1ˆA¡”I·/Z1‡ºn_Ö È+Pid²Ó ±8®inñc-Žk–*6û•8ÚßlÒ@:{R³)ÏvkdXI“›ûÃ*LEEÑP«J$*|3Z¡ °åj±ß·ûÙò¾ ~>ý0‘\uü<…HîD u) ùég^£ °OۏƒBœM¤Ãdâ¬0ó2qžÌœã&$G…‚<Àv}·9´}L§Ÿ ҈KQü7zI +—b$J$0J˜„¬(19ß0Á™@4´^)æ#éÊ«|·X¶#3ýÁO˜êclïºý¢‚á-NxͰAMd~¾ˆA1¨‰JUEà $*•{¾¨PØùvó¥Ýt~ŽDnñ¤3mÐËÇÍÒÏM§y¨ïÚC#3ËrŠA֘YžŠ@ý5‘(Ó·Ôx€ý6Ÿ_e]Õ~>º‚¹ 2ëHڍeLcms ‹A¡±!©† Ԝ‰R_½*TÌ'ØÕõ˜ÄÅÞþž0LJ$ØñøUÓµ ¦T®ƒ1(¤V:ÕAÎÜ$ÌÝË +ò{·ØÜ?.îÇü¢@8 Qî:WÀ´O¯·AT–šçbƒB=¬ºK´ýL$^Æ©PhÔ«ƒ÷'O:”,"‘*ÖÙcPH¤†uv‰¶‰W²*ä¶Û§14¡•,L&Q¬²Ç I «ìíü‰º&BÖ(ÈÌ˔‡Ñɞðþ‡F¼X`A¡—Ù³±Ö-‘¨ðë% +ò‹ú¶;°¤Ó¯®`"±by=…HlkºÇÏéªù€:´†¢6•];Þ0Q¢ó’J rÃDɰ¸®†)q¬:æ@Ú¤<´·«tŸMñe)dPY‘=܊ÊÂí°È®ÐV 0~ÕVœ˜Ò¯‡‡mßý“_:%']G´1Ū¸©ÅͰ&®Ð 0þ‰ºæÄ,Îã*Ór·}T±®ê¥p5¬„+´A $QÇëà‰t¾êÚM|‰ELçÑQHkà²^—ý…uGñS޲¢Ä,¼p²¹ëîûòÎ:Q‚½oR¼Eë7 †eo…¿1Ô}×'ftÑõíÒõCOcsÁOÿ:Uƒ4ðnüËÅði†ð`øÝUÆäeÅ93G‹ÙÓÑY0X§~™ÿ¬LÀǾ®¯§÷FgT(Ÿ>KhàÝi×>>>/Annots 152 0 R>>endobj +272 0 obj<>stream +xÚ՘Ïo›0€ïù+|Ü¥þ‰áØuk¥i“¶%۝QÈiê¿gûLµÆ»…¶U¢'㏾/æù9¿7ŒPøeD¤æ¯l6v›ë»œpJv„©œ¤Z’ÝþÝ®x8V¤{$·];Ví8¼ß=m>í64¡@0/̼ü¸'š'”¤B%iHžÂ› Ždkè/&ôr}' cæ~šÃµfÜP$i¢É«w À ÌN±¼ Ž#ìs÷`ÿa–C¶'ÿa4"ó$Ú33’8Øñ’²˜$$1!'îB’‡}釺=˜T—7uDóDNŽl8b4‘ÞQs„$ÆéÄ]8ò°¯EÝg°8×±”b–dÀMn”û‹fM*×£&F_÷N7‹)…²€ù ÷­¯¡Pôö±^ÚÖO xʼ6Dq“™ 03¨Œ*õt¦$’é$]RpØr¶ÏÃX5¯£‚Ù°¼3(n [Ô¯3K{žŸ˜Ì^æ…ãsÛ5MÑîíÇ%õ…wtI§ù¼»¸ XњúD',òà{ãò%ʍ{XQ–Õi´¾kkxô‹XR鼅¸ °¤´ßḆ„$´¢paeіÕñmY’bÞD\X’Òo"&Ÿˆ%$1È=_¢paûz0ݔ­Œt ’¢ŽµUߥaƒÀ‘`~ѐ_Ä’7Æ…ã«Z¯èí¬$¦]½¶‰Ø °Ä¦š¤bŽÃ¨2õ9á¸EO“­¥¡ý/CTuہ!*纝Æ!‰ÙÖbÂq„Ožq=ÛJšÚˆ#™Ó¹j»`v$s6WíØéȓLS›.Q8ްãi‹qmmm̓ÖsÝvAàIgsݎ<‰qS{(GX_=U¥÷”­ß“9ËHۘÀ'ëÌíúNá±Û\e‹î͹öšo[d±„ᰥܻa(úgûÌå [S…ú§Aqþ` …¶µFIØÖ]0)ôß\ÀAŠÌ•œ›s]gC‚˜ðþà†‘´«úfÀ=0[£Æ¨:hÓI æ3•„ uÂxLr5íø„ãUö]ûì¤A»%Ö%Íéšs¤Ó7`®#•Áâá96Š·?¿mɶ{ÿ}E>VC}hÍ[Ù×§±îì®vŔi®4·©Ö5šü¾ù hòeendstream +endobj +273 0 obj +868 +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<>1<>2<>4<>]>>>>endobj +xref +0 338 +0000000000 65535 f +0000000015 00000 n +0000000225 00000 n +0000001782 00000 n +0000001856 00000 n +0000001938 00000 n +0000002016 00000 n +0000002093 00000 n +0000002172 00000 n +0000002248 00000 n +0000002329 00000 n +0000002388 00000 n +0000002491 00000 n +0000002595 00000 n +0000002700 00000 n +0000002805 00000 n +0000002910 00000 n +0000003015 00000 n +0000003120 00000 n +0000003225 00000 n +0000003330 00000 n +0000003435 00000 n +0000003538 00000 n +0000003642 00000 n +0000003747 00000 n +0000003852 00000 n +0000003957 00000 n +0000004062 00000 n +0000004167 00000 n +0000004272 00000 n +0000004375 00000 n +0000004479 00000 n +0000004584 00000 n +0000004689 00000 n +0000004794 00000 n +0000004899 00000 n +0000005004 00000 n +0000005109 00000 n +0000005214 00000 n +0000005319 00000 n +0000005424 00000 n +0000005529 00000 n +0000005634 00000 n +0000005739 00000 n +0000005844 00000 n +0000005949 00000 n +0000006054 00000 n +0000006159 00000 n +0000006264 00000 n +0000006369 00000 n +0000006474 00000 n +0000006579 00000 n +0000006684 00000 n +0000006789 00000 n +0000006894 00000 n +0000006999 00000 n +0000007104 00000 n +0000007209 00000 n +0000007314 00000 n +0000007419 00000 n +0000007524 00000 n +0000007629 00000 n +0000007734 00000 n +0000007839 00000 n +0000007944 00000 n +0000008049 00000 n +0000008154 00000 n +0000008259 00000 n +0000008364 00000 n +0000008469 00000 n +0000008574 00000 n +0000008679 00000 n +0000008784 00000 n +0000008889 00000 n +0000008994 00000 n +0000009099 00000 n +0000009204 00000 n +0000009309 00000 n +0000009414 00000 n +0000009519 00000 n +0000009624 00000 n +0000009729 00000 n +0000009834 00000 n +0000009939 00000 n +0000010044 00000 n +0000010149 00000 n +0000010254 00000 n +0000010359 00000 n +0000010464 00000 n +0000010569 00000 n +0000010674 00000 n +0000010779 00000 n +0000010884 00000 n +0000010989 00000 n +0000011094 00000 n +0000011199 00000 n +0000011304 00000 n +0000011409 00000 n +0000011514 00000 n +0000011619 00000 n +0000011724 00000 n +0000011830 00000 n +0000011936 00000 n +0000012042 00000 n +0000012148 00000 n +0000012254 00000 n +0000012360 00000 n +0000012466 00000 n +0000012572 00000 n +0000012678 00000 n +0000012784 00000 n +0000012889 00000 n +0000012994 00000 n +0000013098 00000 n +0000013202 00000 n +0000013306 00000 n +0000013410 00000 n +0000013514 00000 n +0000014291 00000 n +0000014397 00000 n +0000014503 00000 n +0000014609 00000 n +0000014715 00000 n +0000014821 00000 n +0000014927 00000 n +0000015033 00000 n +0000015139 00000 n +0000015243 00000 n +0000015348 00000 n +0000015454 00000 n +0000015560 00000 n +0000015666 00000 n +0000015772 00000 n +0000015878 00000 n +0000015984 00000 n +0000016090 00000 n +0000016196 00000 n +0000016302 00000 n +0000016408 00000 n +0000016514 00000 n +0000016620 00000 n +0000016726 00000 n +0000016832 00000 n +0000016938 00000 n +0000017044 00000 n +0000017150 00000 n +0000017256 00000 n +0000017360 00000 n +0000017464 00000 n +0000017568 00000 n +0000017673 00000 n +0000017777 00000 n +0000017882 00000 n +0000018172 00000 n +0000018206 00000 n +0000018240 00000 n +0000019143 00000 n +0000019192 00000 n +0000019241 00000 n +0000019290 00000 n +0000019339 00000 n +0000019388 00000 n +0000019437 00000 n +0000019486 00000 n +0000019535 00000 n +0000019584 00000 n +0000019633 00000 n +0000019682 00000 n +0000019731 00000 n +0000019780 00000 n +0000019829 00000 n +0000019878 00000 n +0000019927 00000 n +0000019976 00000 n +0000020025 00000 n +0000020074 00000 n +0000020123 00000 n +0000020172 00000 n +0000020221 00000 n +0000020270 00000 n +0000020319 00000 n +0000020368 00000 n +0000020417 00000 n +0000020466 00000 n +0000020515 00000 n +0000020564 00000 n +0000020613 00000 n +0000020662 00000 n +0000020711 00000 n +0000020760 00000 n +0000020809 00000 n +0000020858 00000 n +0000020907 00000 n +0000020956 00000 n +0000021005 00000 n +0000021054 00000 n +0000021103 00000 n +0000021152 00000 n +0000021201 00000 n +0000021250 00000 n +0000021299 00000 n +0000021348 00000 n +0000021397 00000 n +0000021446 00000 n +0000021495 00000 n +0000021544 00000 n +0000021593 00000 n +0000021642 00000 n +0000021691 00000 n +0000021740 00000 n +0000021789 00000 n +0000021838 00000 n +0000021887 00000 n +0000021936 00000 n +0000021985 00000 n +0000022034 00000 n +0000022083 00000 n +0000022132 00000 n +0000022181 00000 n +0000022230 00000 n +0000022443 00000 n +0000022574 00000 n +0000022821 00000 n +0000022842 00000 n +0000022937 00000 n +0000023039 00000 n +0000023059 00000 n +0000023200 00000 n +0000024084 00000 n +0000024105 00000 n +0000024218 00000 n +0000024402 00000 n +0000024423 00000 n +0000024564 00000 n +0000025176 00000 n +0000025197 00000 n +0000025310 00000 n +0000025499 00000 n +0000025520 00000 n +0000025670 00000 n +0000026679 00000 n +0000026700 00000 n +0000026859 00000 n +0000027820 00000 n +0000027841 00000 n +0000027972 00000 n +0000028835 00000 n +0000028856 00000 n +0000028997 00000 n +0000030050 00000 n +0000030071 00000 n +0000030202 00000 n +0000031176 00000 n +0000031197 00000 n +0000031337 00000 n +0000032392 00000 n +0000032413 00000 n +0000032544 00000 n +0000033279 00000 n +0000033300 00000 n +0000033413 00000 n +0000033601 00000 n +0000033622 00000 n +0000033762 00000 n +0000034257 00000 n +0000034278 00000 n +0000034409 00000 n +0000034854 00000 n +0000034875 00000 n +0000035030 00000 n +0000037235 00000 n +0000037257 00000 n +0000037412 00000 n +0000038351 00000 n +0000038372 00000 n +0000038427 00000 n +0000038532 00000 n +0000038676 00000 n +0000038782 00000 n +0000038902 00000 n +0000039011 00000 n +0000039160 00000 n +0000039270 00000 n +0000039377 00000 n +0000039531 00000 n +0000039667 00000 n +0000039764 00000 n +0000039874 00000 n +0000039989 00000 n +0000040102 00000 n +0000040202 00000 n +0000040360 00000 n +0000040457 00000 n +0000040567 00000 n +0000040665 00000 n +0000040809 00000 n +0000040914 00000 n +0000041029 00000 n +0000041135 00000 n +0000041298 00000 n +0000041413 00000 n +0000041534 00000 n +0000041654 00000 n +0000041779 00000 n +0000041900 00000 n +0000042020 00000 n +0000042130 00000 n +0000042278 00000 n +0000042380 00000 n +0000042496 00000 n +0000042616 00000 n +0000042729 00000 n +0000042846 00000 n +0000042963 00000 n +0000043065 00000 n +0000043216 00000 n +0000043323 00000 n +0000043437 00000 n +0000043550 00000 n +0000043670 00000 n +0000043795 00000 n +0000043905 00000 n +0000044016 00000 n +0000044130 00000 n +0000044241 00000 n +0000044344 00000 n +0000044489 00000 n +0000044589 00000 n +0000044702 00000 n +0000044816 00000 n +0000044929 00000 n +0000045038 00000 n +0000045152 00000 n +0000045265 00000 n +0000045365 00000 n +0000045499 00000 n +0000045596 00000 n +0000045696 00000 n +trailer +<> +startxref +45924 +%%EOF diff --git a/doc/sdd.shtml b/doc/sdd.shtml new file mode 100644 index 0000000000..07c691849a --- /dev/null +++ b/doc/sdd.shtml @@ -0,0 +1,557 @@ + + + + + + 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 + +
  • 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 +
  • RFC 1179, Line Printer Daemon Protocol +
  • RFC 2565, IPP/1.0: Encoding and Transport +
  • RFC 2566, IPP/1.0: Model and Semantics +
  • RFC 2639, IPP/1.0: Implementers Guide +
+ +

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

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

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: + +
    + +
  • quit - Quits the lpc command. + +
  • status - Shows the status of printers and jobs in the queue. + +
+ +

lpr

+ +The lpr command submits a job for printing. The CUPS version of lpr silently +ignores the "i", "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.cgi

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

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

+ +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, get a list of available +classes, get the default printer or class, get the default server name, get +the local username, and get a password string. + +

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

imagetoraster

+ +The imagetoraster filter converts image files into CUPS raster data. + +

pstops

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

pstoraster

+ +The pstoraster filter converts PostScript program data into CUPS raster data. + +

rastertohp

+ +The rastertohp filter handles converting CUPS raster data to HP PCL and +supports both color and black-and-white printers. + +

texttops

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

Scheduler

+ +The scheduler is a fully-functional HTTP/1.1 and IPP/1.0 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. + +

Logging

+ +The logging module manages the access, error, and page log files that are +generated by the scheduler. + +

Main

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

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 printers and 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), "F" (filter), and "E" (enable and accept) 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. + +

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/spm.html b/doc/spm.html new file mode 100644 index 0000000000..69e85087bd --- /dev/null +++ b/doc/spm.html @@ -0,0 +1,4090 @@ + + + +DRAFT - CUPS Software Programmers Manual + + + + + + + +

DRAFT - CUPS Software Programmers Manual


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

Table of Contents

+
+
Preface + +1 - Printing System Overview + +2 - The CUPS API + +3 - Writing Filters + +4 - Writing Printer Drivers + +5 - Writing Backends + +A - Constants + +B - Structures + +C - Functions + +
+GIF89a¯ÿòÌÌ̙™™fff333ÿÿÿÿÿÿÿÿÿ!ù,¯ÿBþXºÜþ0ÊI«½8ëÍ»ÿ`(Ždižhª2€0p,Ïtmßx®ï + + +;±Ýíˆndý !¸ ž³wà…MƒƒY~¿{,gÚ\‚äé +Œ×Ø(tÙî!Ï=Ñ.ûz¯áџ:ì;Ã9qöíÉë]/¿ºÉ¤Et/†'Îþt9Àؖž_ÙÇ\|W•wArö¸Ý2Ô× +tN°0Tï}¡û‰$!‚yMxî)ˆš‰Ôø@nB°U½ÊwE„§!ŠF H L8B +c‰;ždŠ-æDVWdг€h±äړP¶%#(4Fiå•Ï\hŠ:Re!\ÒėX^¦%€¥À-$E€Ö/úHŽšlââöÌQX + + +¸1Nô¯b"œŠüjåÁÂE0…È8ö5GkZ|ÒÁwt„C»ÔQSÇo6Ôِ[W„$²*Ž+4Pb-8¹P1þ'8"‘ФÄ$ Cyê‘„)>ãŠtè`Ð3‡‹¾z"«rE'Âqfä°Ë +‘qÂ\|€„Ž¡ôö»%É(.—bڽȀíÉ`{¬EÇ1w’ »[Hß`(B6ö“  +†')ÊRŽÎa[ÃrbC!T尌 +2Q·ÈHZê#–®üË/àô¯FÝê(Û²% ºXË9öÀbÁ4f.ù-oý™XËB…IÎÒ7¹*@ÃӎÍT€hà‘ÌW␙Ã$f:µyžn†ó†r„'téKv` +Ç+dª– œ79sò|'=×¢Ìx¶òœÿ„¦œˆeÎ;*à$þ” IÝÆaÏ{–3ŽÅÁ +P“ÍS[ÙL¨3©òQ7éÆò#ãûô0F×ðsE°t§@‘ØQÜ´´ ©:3ÓRíd ¥*MITnŒ£¨H]ØQÁd +@òþ—¬rMœŽaO + +rë^yÀ·(¸îéêû$uDòrã/a,I.°ÙUÀœb hˆ`¾B ë" +Ü`HØxȸo1þ[á\8f^æ|\ý‚¢¢zø0(ˆ\ {ƒÄgäÞõ€çâ§Á˜0*\³n¼‹m¶/Äeª±ÿ†ì +Ç,½DN2€œº+ùÉ|í0L¡Le*ð¸Ã>­2ëf,eIPOËÅàr—±”80SAŸcFªatç»ãy¤¸ršçÌ¡5ïoõËsžï|¿8˙Φ¬þ,ï¼èà)ÁÌ;øk¡—†dDpÑòø2¢qfHã!˓~ٟ-í +'g:,æ4y?ýäP‹Z›ž#ÏÕ´Î5AK‰k]ûš›ÒKõ¯‡më€õzØÈƫ؎Ý>B{PЪ.6hf]º?©ÌIŽuO„íM‚ÌÇÜcµ3˜ +61‹NÒ[†W£ ¦m¿­{ÂPâvζKnUˆ[ ònĽ±÷n?l:Áž3ušë¬sP[ÿnn¾çP…WõÔFj[Â÷ +¹vÏ™à‰˜xú'ˆ£ÀÀ†p¸4.êãKÇ¿ÂÁ±o§¢ü"Á|Nk`îʘ + + +jl©ÌuˆËi™0pmC´«+‰÷6¤2­éÏe`(ŽJ]¥iõð3ƒØí"p|ª!:qøFس 6£ +@­,þŠqüぐoÌÇ®žÖüV“¶QǛEvî¹²É8ÙªS"æÀç‡x± àþ‡>—Iãg +ïÝ>Y‰çN80æ§ ±¾GLLìÕµ…(1Þ¼!8}þ¬“*…ª‰Ùì:e»´œ +ª¿ên_6ÂÃSÀ`eG;Ö„CƒCcˆ¿‡4¸yeî¯Í)oøByRm½0?íLîÅ`QÿjÓÙ/ºôÓN|Ý + + +þÙAÜŒÁ¸D5©D aævx ?жx°DM@•!h‰àȀާ® +• á×B`ð¤ªE?›“”Þdƒ"8$Ý`Ki0…OðƒnΓ±µvtžè€I([,¹Ndɨh\'6X +P㗊‰Éøt ¢‘¥˜¬è €ˆ†Ky™FˆŒë`š”yƒ„¨š €š‰ƒM©‡øFQhY„ +9¶X¯×–í4š¤™Y\)"¹AN]‰xéz÷Gq07)©ñ™•Y€r°ŒŽi‹ z ™ÇäFÍÉT–ù› +ËŽC œwI›üX]‹¹\ëY]þf lïYbj8ŸÈuœbŸÍÅtú©fÞןfBI—“*øé:ÛØUj Ò +ˆõ¹ Õp $(~ ¡Ú ¡gù{îpZI?¡ƒîÀv:“a¦˜6¢§Ô]Ý‘(ªê)!ŸÚ¢: +jwµ¡4ÚvíHÛǘ9ºXhó•üù£¥Á¢VÉ{Dº2š‰(°¤3š¤a÷ +У¥“p¢þò4Vº—  +E´¥è¤k°7ºhT*€¿èw`ڞiÄ …S¦Ʀmê Nêƒ#ú¢f€ xê†ý +8z©7uÚp{Ú=~]7`«h‡ÚsÚg:…zd˜ó§ÎA-vþAñr¦'–AÚ)9–š¢âSi;£…š 1ªo"ª +¦J;“º rº8Ui|é>¡Úœú + +“ë¥Dfný2»ƒ–0j«®»ºK;zë¢Íö»—!µ—S»³r>K+6ˆ‹¨XÒ»; CÈ +8Ê;¢»ÃÛ/Œ‹¥ž!¬s½VR½óõϋOâ[/çK¨þ˜Ñ:͋\Ý+ Sc:ï˞’º¶ë9Æ» + +ô 8ly$ +8©ÙÅmX2Ùh>—?¯!šHüÁ^LsP,Ÿ«Y‹âá¿ÿtšì‚£Y +r¦Éš¥9ÇjžÄ8-ÆÇŒ¶iêPÂbA˜ù‰Ã¸š»³7RœCWRoìŠå MŒŠ”åt™ Œ›réÉq + + +å>}Lê}ÎǨ 5:àŒ|"þÇwÐsøæNΰ¹#R>~-N‰®èƒ ßcðÞÚÎÑ¥®åGÎâ툉Ýè*‚¸ +=‚ž ºëⅭëÀ>Û·žën^žmèÊëð¼ã>å×Λ«}êØ÷ +“Œ¬ËIÁ·AÔNÍëv>]t.âÚLЫþíï¾ñnäÖÜæs¹¿±â°+† +¬UØïî•.ç¬ÎìÍ.è´ÞŠG=ðù‚§ž¯”ë^äÛ®êh-‹êê!i!ÕvMíiªîþ¾òîá/þÑ-OÖGð,oñº!å’gOâ POìOôBþÈàhâ+?ï>ßÊVHÀsaõ™€õ$óSîõ—»ó8.žß¹ +~áßÈ©ö»]ò3ëÆt_÷[ïôb¯ç‚Ü÷Õ«@u™ð;zܘ‘Ü@óŽ2’?ùƒ¸ÙlùF ¶™¯ù›N ž0œú£¶¤ÿ0#9:ß§½ž©Ÿ\#ÃÙæó2é+û‚ÀÓ¸_äM/ÓtaÚý3”]Ù«¿¸iîaF>ª}ŒØvÍïMÍ÷Ðëä©îr܌öqñ_ÀüªrâF®ò +ýþ¸—hT_ã4sx”ýÝî)ç.QgûàŸÏ%ì‹}i´ASû|þð@QÜ +$J9€»-̱÷ÜôMؑhZ˜¦:°œ*ÏlßxÒ|ϼ¡ÅLÀ ¬Áfù9BÑdìÁ|«VV„¢“énKv + + +kB_ƒg 3ʳ8#Þ¬L=0;J¤äÈ@¤F|'i~±© žaʊÆg;d*3²”©bPÏ¢TäHô¦?[† +ÄäƒhN6ZM¢D:c*BR!$±ckƒ’V­-uÛ@[øp„Ÿ]¼8ö-1{TήWÏ2ñ Šp=¸q«Ñ½es.‰„4+#Ëe¦¥W5µekxr䛓/X͚5Iǃ=kÝúµì˰ûN–2qÅ¦yZ£QŽ›ÇޝtxŠäcK—Ííɹ +iþ¡9¼m1oñ¢©/²8îìSté4l’Wm¾9óéÖÛÐãã{{üzÞ¿çøêöÞzà}œàL¨ "˜ +ÄÐsà¶PGLUúå`MÞ  ¡†9¬§Û{pX¸¡wÚw߇¡¨ ‰í "MUXNx + ++l´á¦ +j²F:Á.êÆÛj¤³Búî ¼Ê«/£Ö’[н#í+ð¥ænJÞ¸«æ;ð©õ‹¨ _ËðĊһ*º? +ƒÂwœÃyzh±°Øzl2,#oZ2țr|ò˂°¼$Ç)ë +óÍÙÔ,éfs€1Î@/øîÏPõÌiÐH·ðÃBkLtÒP¯bôS;NÝWÔXÏ +ó’dlÍtÖ`°tžOc óÅa§}Aě²1vËjÇmþu+`ÍÍÁ·qwü6˜‚ì½sÞXŸ¨Ë$xM6àP³-iÉSÚ½Aوïë84–ø=xä8^!ä*L>ޘƒk¹Œ({Iè^!ḘN$ê +«®ç!ºû‚ÿÝ ë¯ßoî—Oü¨¾ÿî9í]ñÞ{ñÙÊ®ãlhŽ(èÌÃê¼~ÔS¢|ö՟zýw¬Ë§|øÝ—*½ŒÈ×­|úåwzþæ“)Nrû¾Ê?*ô¥ +¿*÷ô7ú½~Múúú÷ª÷Ɉ•S3x*ûíP”ùH£°°àó(è¾í-Jƒú™ +åAF{#\”g…Áœ)!),Ô #ÓÂǼjþ1œŒþh©²K„9$ƒYè)Ž ˆA È +—‡)#1‰Óp"˜ð'Ã%n‰P´‡Ù¨-‹1³¢^\%ƈÔp„CLÖ5à + +
+

Preface

+ This software programmers manual provides software programming +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 software administrators manual is organized into the following +sections:

+
    +
  • 1 - Printing System Overview
  • +
  • 2 - The CUPS API
  • +
  • 3 - Writing Filters
  • +
  • 4 - Writing Printer Drivers
  • +
  • 5 - Writing Backends
  • +
  • A - Constants
  • +
  • B - Structures
  • +
  • C - Functions
  • +
+

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 - The CUPS API

+

This chapter describes the CUPS Application Programmers Interface +("API").

+

The CUPS Library

+

Detecting the CUPS Library in Autoconf

+

Basic Services

+

Include Files

+

Getting the Available Printers and Classes

+

Printing Files

+

Setting Printer Options

+

Cancelling Jobs

+

HTTP Services

+

Include Files

+

Connecting to a Server

+

Setting Request Fields

+

Issuing a Request

+

Getting the Request Status

+

Sending Request Data

+

Reading Request Data

+

IPP Services

+

Include Files

+

Creating an IPP Request

+

Adding Attributes

+

Sending an IPP Request

+

Reading an IPP Response

+

Finding Attributes

+

Looping Through Attributes

+

IPP Standard Operations

+

IPP Extension Operations

+

CUPS Extension Operations

+

Language Services

+

Include Files

+

Getting the Default Language

+

Getting the Language Encoding

+

Getting a Language String

+

MIME Services

+

Include Files

+

Loading a MIME Database

+

Finding a Specific MIME Type

+

Finding the MIME Type of a File

+

Filters

+

PPD Services

+

Include Files

+

Loading a PPD File

+

Options and Groups

+

Finding an Option

+

Finding a Page Size

+

Marking Options

+

Checking for Conflicts

+

Sending Options

+

3 - Writing Filters

+

This chapter describes how to write a file filter for CUPS.

+

Overview

+

Security Considerations

+ Users and Groups +

Temporary Files

+

Page Accounting

+

Command-Line Arguments

+

Copy Generation

+

Environment Variables

+

Writing a HTML Filter

+

4 - Writing Printer Drivers

+

This chapter discusses how to write a printer driver, which is a +special filter program that converts CUPS raster data into the +appropriate commands and data required for a printer.

+

Overview

+

Page Accounting

+

Color Management

+

Raster Functions

+

cupsRasterOpen()

+

cupsRasterReadHeader()

+

cupsRasterReadPixels()

+

cupsRasterClose()

+

Writing a HP-PCL Driver

+

5 - Writing Backends

+

This chapter describes how to write a backend for CUPS. Backends +communicate directly with printers and allow printer drivers and +filters to send data using any type of connection transparently.

+

Overview

+

Security Considerations

+ Users and Groups +

Temporary Files

+

Page Accounting

+

Retries

+

Command-Line Arguments

+

Copy Generation

+

Environment Variables

+

Writing a Serial Port Backend

+

A - Constants

+

This appendix lists all of the constants that are defined by the +CUPS API.

+

CUPS Constants

+

HTTP Constants

+

IPP Constants

+

Language Constants

+

MIME Constants

+

PPD Constants

+

Raster Constants

+

B - Structures

+

This appendix describes all of the structures that are defined by +the CUPS API.

+

+

C - Functions

+

This appendix provides a reference for all of the CUPS API +functions. + +

+

cupsAddOption()

+

Usage

+
+int
+cupsAddOption(const char *name,
+              const char *value,
+              int num_options,
+	      cups_option_t **options);
+
+

Arguments

+
+ + + + + + + +
ArgumentDescription
nameThe name of the option.
valueThe value of the option.
num_optionsNumber of options currently in the array.
optionsPointer to the options array.
+
+

Returns

+

The new number of options.

+

Description

+

cupsAddOption() adds an option to the specified array.

+

Example

+
+#include <cups.h>
+
+...
+
+/* Declare the options array */
+int           num_options;
+cups_option_t *options;
+
+/* Initialize the options array */
+num_options = 0;
+options     = (cups_option_t *)0;
+
+/* Add options using cupsAddOption() */
+num_options = cupsAddOption("media", "letter", num_options, &options);
+num_options = cupsAddOption("resolution", "300dpi", num_options, &options);
+
+

See Also

+cupsFreeOptions(), +cupsGetOption(), +cupsParseOptions() + + +

cupsCancelJob()

+

Usage

+
+int
+cupsCancelJob(const char *dest,
+              int job);
+
+

Arguments

+
+ + + + +
ArgumentDescription
destPrinter or class name
jobJob ID
+
+

Returns

+

1 on success, 0 on failure. On failure the error can be found by +calling cupsLastError().

+

Description

+

cupsCancelJob() cancels the specifies job.

+

Example

+
+#include <cups.h>
+
+cupsCancelJob("LaserJet", 1);
+
+

See Also

+

cupsLastError(), +cupsPrintFile() + +

+

cupsDoFileRequest()

+

Usage

+
+ipp_t *
+cupsDoFileRequest(http_t *http,
+                  ipp_t *request,
+                  const char *resource,
+		  const char *filename);
+
+

Arguments

+
+ + + + + + +
ArgumentDescription
httpHTTP connection to server.
requestIPP request data.
resourceHTTP resource name for POST.
filenameFile to send with POST request (NULL + pointer if none.)
+
+

Returns

+

IPP response data or NULL if the request fails. On +failure the error can be found by calling +cupsLastError().

+

Description

+

cupsDoFileRequest() does a HTTP POST request and +provides the IPP request and optionally the contents of a file to the +IPP server. It also handles resubmitting the request and performing +password authentication as needed.

+

Example

+
+#include <cups.h>
+
+http_t      *http;
+cups_lang_t *language;
+ipp_t       *request;
+ipp_t       *response;
+
+...
+
+/* Get the default language */
+language = cupsLangDefault();
+
+/* Create a new IPP request */
+request  = ippNew();
+
+request->request.op.operation_id = IPP_PRINT_FILE;
+request->request.op.request_id   = 1;
+
+/* Add required attributes */
+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, "ipp://hostname/resource");
+
+ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
+             NULL, cupsUser());
+
+/* Do the request... */
+response = cupsDoFileRequest(http, request, "/resource", "filename.txt");
+
+

See Also

+

cupsLangDefault(), +cupsLangEncoding(), +cupsUser(), httpConnect() +, ippAddString(), +ippNew() + +

+

cupsDoRequest()

+

Usage

+
+ipp_t *
+cupsDoRequest(http_t *http,
+              ipp_t *request,
+              const char *resource);
+
+

Arguments

+
+ + + + + +
ArgumentDescription
httpHTTP connection to server.
requestIPP request data.
resourceHTTP resource name for POST.
+
+

Returns

+

IPP response data or NULL if the request fails. On +failure the error can be found by calling +cupsLastError().

+

Description

+

cupsDoRequest() does a HTTP POST request and provides +the IPP request to the IPP server. It also handles resubmitting the +request and performing password authentication as needed.

+

Example

+
+#include <cups.h>
+
+http_t      *http;
+cups_lang_t *language;
+ipp_t       *request;
+ipp_t       *response;
+
+...
+
+/* Get the default language */
+language = cupsLangDefault();
+
+/* Create a new IPP request */
+request  = ippNew();
+
+request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
+request->request.op.request_id   = 1;
+
+/* Add required attributes */
+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, "ipp://hostname/resource");
+
+/* Do the request... */
+response = cupsDoRequest(http, request, "/resource");
+
+

See Also

+

cupsLangDefault(), +cupsLangEncoding(), +cupsUser(), httpConnect() +, ippAddString(), +ippNew() + +

+

cupsFreeOptions()

+

Usage

+
+void
+cupsFreeOptions(int num_options,
+                cups_option_t *options);
+
+
+

Arguments

+
+ + + + +
ArgumentDescription
num_optionsNumber of options in array.
optionsPointer to options array.
+
+

Description

+

cupsFreeOptions() frees all memory associated with the +option array specified.

+

Example

+
+#include <cups/cups.h>
+
+int           num_options;
+cups_option_t *options;
+
+...
+
+cupsFreeOptions(num_options, options);
+
+

See Also

+

cupsAddOption(), +cupsGetOption(), cupsMarkOptions(), cupsParseOptions() + +

+

cupsGetClasses()

+

Usage

+
+int
+cupsGetClasses(char ***classes);
+
+

Arguments

+
+ + + +
ArgumentDescription
classesPointer to character pointer array.
+
+

Returns

+

The number of printer classes available.

+

Description

+

cupsGetClasses() gets a list of the available printer +classes. The returned array should be freed using the free() + when it is no longer needed.

+

Example

+
+#include <cups/cups.h>
+
+int  i;
+int  num_classes;
+char **classes;
+
+...
+
+num_classes = cupsGetClasses(;
+
+...
+
+if (num_classes > 0)
+{
+  for (i = 0; i num_classes; i ++)
+    free(classes[i]);
+
+  free(classes);
+}
+
+

See Also

+

cupsGetDefault(), +cupsGetPrinters() + +

+

cupsGetDefault()

+

Usage

+
+const char *
+cupsGetDefault(void);
+
+

Returns

+

A pointer to the default destination.

+

Description

+

cupsGetDefault() gets the default destination printer +or class. The default destination is stored in a static string and will +be overwritten (usually with the same value) after each call.

+

Example

+
+#include <cups/cups.h>
+
+printf("The default destination is %s\n", cupsGetDefault());
+
+

See Also

+

cupsGetClasses(), +cupsGetPrinters() + +

+

cupsGetOption()

+

Usage

+
+const char *
+cupsGetOption(const char *name,
+              int num_options,
+              cups_option_t *options);
+
+

Arguments

+
+ + + + + +
ArgumentDescription
nameThe name of the option.
num_optionsThe number of options in the array.
optionsThe options array.
+
+

Returns

+

A pointer to the option values or NULL if the option is +not defined.

+

Description

+

cupsGetOption() returns the first occurrence of the +named option. If the option is not included in the options array then a +NULL pointer is returned.

+
+#include <cups/cups.h>
+
+int           num_options;
+cups_option_t *options;
+const char    *media;
+
+...
+
+media = cupsGetOption("media", num_options, options);
+
+

See Also

+

cupsAddOption(), +cupsFreeOptions(), cupsMarkOptions() +, cupsParseOptions() + +

+

cupsGetPassword()

+

Usage

+
+const char *
+cupsGetPassword(const char *prompt);
+
+

Arguments

+
+ + + +
ArgumentDescription
promptThe prompt to display to the user.
+
+

Returns

+

A pointer to the password that was entered or NULL if +no password was entered.

+

Description

+

cupsGetPassword() displays the prompt string and asks +the user for a password. The password text is not echoed to the user.

+

Example

+
+#include <cups/cups.h>
+
+char *password;
+
+...
+
+password = cupsGetPassword("Please enter a password:");
+
+

See Also

+

cupsServer(), +cupsUser() + +

+

cupsGetPPD()

+

Usage

+
+const char *
+cupsGetPPD(const char *printer);
+
+

Arguments

+
+ + + +
ArgumentDescription
printerThe name of the printer.
+
+

Returns

+

The name of a temporary file containing the PPD file or NULL + if the printer cannot be located or does not have a PPD file.

+

Description

+

cupsGetPPD() gets a copy of the PPD file for the named +printer. The printer name can be of the form "printer" or +"printer@hostname".

+

You should remove (unlink) the PPD file after you are done using it. +The filename is stored in a static buffer and will be overwritten with +each call to cupsGetPPD().

+

Example

+
+#include <cups/cups.h>
+
+char *ppd;
+
+...
+
+ppd = cupsGetPPD("printer@hostname");
+
+...
+
+unlink(ppd);
+
+ + +

cupsGetPrinters()

+

Usage

+
+int
+cupsGetPrinters(char ***printers);
+
+

Arguments

+
+ + + +
ArgumentDescription
printersPointer to character pointer array.
+
+

Returns

+

The number of printer printers available.

+

Description

+

cupsGetPrinters() gets a list of the available +printers. The returned array should be freed using the free() + when it is no longer needed.

+

Example

+
+#include <cups/cups.h>
+
+int  i;
+int  num_printers;
+char **printers;
+
+...
+
+num_printers = cupsGetPrinters(;
+
+...
+
+if (num_printers > 0)
+{
+  for (i = 0; i num_printers; i ++)
+    free(printers[i]);
+
+  free(printers);
+}
+
+

See Also

+

cupsGetClasses(), +cupsGetDefault() + +

+

cupsLangDefault()

+

Usage

+
+const char *
+cupsLangDefault(void);
+
+

Returns

+

A pointer to the default language structure.

+

Description

+

cupsLangDefault() returns a language structure for the +default language. The default language is defined by the LANG + environment variable. If the specified language cannot be located then +the POSIX (English) locale is used.

+

Call cupsLangFree() to free any memory associated with +the language structure when you are done.

+

Example

+
+#include <cups/language.h>
+
+cups_lang_t *language;
+...
+
+language = cupsLangDefault();
+
+...
+
+cupsLangFree(language);
+
+

See Also

+

cupsLangEncoding(), +cupsLangFlush(), cupsLangFree(), +cupsLangGet(), cupsLangString() + +

+

cupsLangEncoding()

+

Usage

+
+char *
+cupsLangEncoding(cups_lang_t *language);
+
+

Arguments

+
+ + + +
ArgumentDescription
languageThe language structure.
+
+

Returns

+

A pointer to the encoding string.

+

Description

+

cupsLangEncoding() returns the language encoding used +for the specified language, e.g. "iso-8859-1", "utf-8", etc.

+

Example

+
+#include <cups/language.h>
+
+cups_lang_t *language;
+char        *encoding;
+...
+
+language = cupsLangDefault();
+encoding = cupsLangEncoding(language);
+...
+
+cupsLangFree(language);
+
+

See Also

+

cupsLangDefault(), +cupsLangFlush(), cupsLangFree(), +cupsLangGet(), cupsLangString() + +

+

cupsLangFlush()

+

Usage

+
+void
+cupsLangFlush(void);
+
+

Description

+

cupsLangFlush() frees all language structures that have +been allocated.

+

Example

+
+#include <cups/language.h>
+
+...
+
+cupsLangFlush();
+
+

See Also

+

cupsLangDefault(), +cupsLangEncoding(), cupsLangFree(), +cupsLangGet(), cupsLangString() + +

+

cupsLangFree()

+

Usage

+
+void
+cupsLangFree(cups_lang_t *language);
+
+

Arguments

+
+ + + +
ArgumentDescription
languageThe language structure to free.
+
+

Description

+

cupsLangFree() frees the specified language structure.

+

Example

+
+#include <cups/language.h>
+
+cups_lang_t *language;
+...
+
+cupsLangFree(language);
+
+

See Also

+

cupsLangDefault(), +cupsLangEncoding(), cupsLangFlush(), +cupsLangGet(), cupsLangString() + +

+

cupsLangGet()

+

Usage

+
+cups_lang_t *
+cupsLangGet(const char *name);
+
+

Arguments

+
+ + + +
ArgumentDescription
nameThe name of the locale.
+
+

Returns

+

A pointer to a language structure.

+

Description

+

cupsLangGet() returns a language structure for the +specified locale. If the locale is not defined then the POSIX (English) +locale is substituted.

+

Example

+
+#include <cups/language.h>
+
+cups_lang_t *language;
+
+...
+
+language = cupsLangGet("fr");
+
+...
+
+cupsLangFree(language);
+
+

See Also

+

cupsLangDefault(), +cupsLangEncoding(), cupsLangFlush(), +cupsLangFree(), cupsLangString() + +

+

cupsLangString()

+

Usage

+
+char *
+cupsLangString(cups_lang_t *language,
+               int         message);
+
+

Arguments

+
+ + + + +
ArgumentDescription
languageThe language to query.
messageThe message number.
+
+

Returns

+

A pointer to the message string or NULL if the message +is not defined.

+

Description

+

cupsLangString() returns a pointer to the specified +message string in the specified language.

+

Example

+
+#include <cups/language.h>
+
+cups_lang_t *language;
+char        *s;
+...
+
+language = cupsLangGet("fr");
+
+s = cupsLangString(language, CUPS_MSG_YES);
+
+...
+
+cupsLangFree(language);
+
+

See Also

+

cupsLangDefault(), +cupsLangEncoding(), cupsLangFlush(), +cupsLangFree(), cupsLangGet() + +

+

cupsLastError()

+

Usage

+
+ipp_status_t
+cupsLastError(void);
+
+

Returns

+

An enumeration containing the last IPP error.

+

Description

+

cupsLastError() returns the last IPP error that +occurred. If no error occurred then it will return IPP_OK + or IPP_OK_CONFLICT.

+

Example

+
+#include <cups/cups.h>
+
+ipp_status_t status;
+
+...
+
+status = cupsLastError();
+
+

See Also

+

cupsCancelJob(), +cupsPrintFile() + +

+

cupsMarkOptions()

+

Usage

+
+int
+cupsMarkOptions(ppd_file_t *ppd,
+                int num_options,
+                cups_option_t *options);
+
+

Arguments

+
+ + + + + + +
ArgumentDescription
ppdThe PPD file to mark.
num_optionsThe number of options in the options array.
optionsA pointer to the options array.
+
+

Returns

+

The number of conflicts found.

+

Description

+

cupsMarkOptions() marks options in the PPD file. It +also handles mapping of IPP option names and values to PPD option +names.

+

Example

+
+#include <cups/cups.h>
+
+int           num_options;
+cups_option_t *options;
+ppd_file_t    *ppd;
+
+...
+
+cupsMarkOptions(ppd, num_options, options);
+
+

See Also

+

cupsAddOption(), +cupsFreeOptions(), cupsGetOption(), +cupsParseOptions() + +

+

cupsParseOptions()

+

Usage

+
+int
+cupsParseOptions(const char *arg,
+                 int num_options,
+                 cups_option_t **options);
+
+

Arguments

+
+ + + + + + +
ArgumentDescription
argThe string containing one or more options.
num_optionsThe number of options in the options array.
optionsA pointer to the options array pointer.
+
+

Returns

+

The new number of options in the array.

+

Description

+

cupsParseOptions() parses the specifies string for one +or more options of the form "name=value", "name", or "noname". It can +be called multiple times to combine the options from several strings.

+

Example

+
+#include <cups/cups.h>
+
+int           num_options;
+cups_option_t *options;
+
+...
+
+num_options = 0;
+options     = (cups_option_t *)0;
+num_options = cupsParseOptions(argv[5], num_options, &options);
+
+

See Also

+

cupsAddOption(), +cupsFreeOptions(), cupsGetOption(), +cupsMarkOptions() + +

+

cupsPrintFile()

+

Usage

+
+int
+cupsPrintFile(const char *printer,
+              const char *filename,
+              const char *title,
+	      int num_options,
+	      cups_option_t *options);
+
+

Arguments

+
+ + + + + + + + +
ArgumentDescription
printerThe printer or class to print to.
filenameThe file to print.
titleThe job title.
num_optionsThe number of options in the options array.
optionsA pointer to the options array.
+
+

Returns

+

The new job ID number or 0 on error.

+

Description

+

cupsPrintFile() sends a file to the specified printer +or class for printing. If the job cannot be printed the error code can +be found by calling cupsLastError().

+

Example

+
+#include <cups/cups.h>
+
+int           num_options;
+cups_option_t *options;
+
+...
+
+cupsPrintFile("printer@hostname", "filename.ps", "Job Title", num_options,
+              options);
+
+

See Also

+

cupsCancelJob(), +cupsLastError() + +

+

cupsRasterClose()

+

Usage

+
+void
+cupsRasterClose(cups_raster_t *ras);
+
+

Arguments

+
+ + + +
ArgumentDescription
rasThe raster stream to close.
+
+

Description

+

cupsRasterClose() closes the specified raster stream.

+

Example

+
+#include <cups/raster.h>
+
+cups_raster_t *ras;
+
+...
+
+cupsRasterClose(ras);
+
+

See Also

+

cupsRasterOpen(), +cupsRasterReadHeader(), +cupsRasterReadPixels(), +cupsRasterWriteHeader(), +cupsRasterWritePixels() + +

+

cupsRasterOpen()

+

Usage

+
+cups_raster_t *
+cupsRasterOpen(int fd,
+               cups_mode_t mode);
+
+

Arguments

+
+ + + + +
ArgumentDescription
fdThe file descriptor to use.
modeThe mode to use; CUPS_RASTER_READ or +CUPS_RASTER_WRITE.
+
+

Returns

+

A pointer to a raster stream or NULL if there was an +error.

+

Description

+

cupsRasterOpen() opens a raster stream for reading or +writing.

+

Example

+
+#include <cups/raster.h>
+
+cups_raster_t *ras;
+
+...
+
+ras = cupsRasterOpen(0, CUPS_RASTER_READ);
+
+

See Also

+

cupsRasterClose(), +cupsRasterReadHeader(), +cupsRasterReadPixels(), +cupsRasterWriteHeader(), +cupsRasterWritePixels() + +

+

cupsRasterReadHeader()

+

Usage

+
+unsigned
+cupsRasterReadHeader(cups_raster_t *ras,
+                     cups_page_header_t *header);
+
+

Arguments

+
+ + + + +
ArgumentDescription
rasThe raster stream to read from.
headerA pointer to a page header structure to read +into.
+
+

Returns

+

1 on success, 0 on EOF or error.

+

Description

+

cupsRasterReadHeader() reads a page header from the +specified raster stream.

+

Example

+
+#include <cups/raster.h>
+
+int                  line;
+cups_raster_t        *ras;
+cups_raster_header_t header;
+unsigned char        pixels[8192];
+...
+
+while (cupsRasterReadHeader(ras, &header))
+{
+  ...
+
+  for (line = 0; line < header.cupsHeight; line ++)
+  {
+    cupsRasterReadPixels(ras, pixels, header.cupsBytesPerLine);
+
+    ...
+  }
+}
+
+

See Also

+

cupsRasterClose(), +cupsRasterOpen(), +cupsRasterReadPixels(), +cupsRasterWriteHeader(), +cupsRasterWritePixels() + +

+

cupsRasterReadPixels()

+

Usage

+
+unsigned
+cupsRasterReadPixels(cups_raster_t *ras,
+                     unsigned char *pixels,
+		     unsigned length);
+
+

Arguments

+
+ + + + + +
ArgumentDescription
rasThe raster stream to read from.
pixelsThe pointer to a pixel buffer.
lengthThe number of bytes of pixel data to read.
+
+

Returns

+

The number of bytes read or 0 on EOF or error.

+

Description

+

cupsRasterReadPixels() reads pixel data from the +specified raster stream.

+

Example

+
+#include <cups/raster.h>
+
+int                  line;
+cups_raster_t        *ras;
+cups_raster_header_t header;
+unsigned char        pixels[8192];
+...
+
+while (cupsRasterReadHeader(ras, &header))
+{
+  ...
+
+  for (line = 0; line < header.cupsHeight; line ++)
+  {
+    cupsRasterReadPixels(ras, pixels, header.cupsBytesPerLine);
+
+    ...
+  }
+}
+
+

See Also

+

cupsRasterClose(), +cupsRasterOpen(), +cupsRasterReadHeader(), +cupsRasterWriteHeader(), +cupsRasterWritePixels() + +

+

cupsRasterWriteHeader()

+

Usage

+
+unsigned
+cupsRasterWriteHeader(cups_raster_t *ras,
+                      cups_page_header_t *header);
+
+

Arguments

+
+ + + + +
ArgumentDescription
rasThe raster stream to write to.
headerA pointer to the page header to write.
+
+

Returns

+

1 on success, 0 on error.

+

Description

+

cupsRasterWriteHeader() writes the specified page +header to a raster stream.

+

Example

+
+#include <cups/raster.h>
+
+int                  line;
+cups_raster_t        *ras;
+cups_raster_header_t header;
+unsigned char        pixels[8192];
+...
+
+cupsRasterWriteHeader(ras, &header);
+
+for (line = 0; line < header.cupsHeight; line ++)
+{
+  ...
+
+  cupsRasterWritePixels(ras, pixels, header.cupsBytesPerLine);
+}
+
+

See Also

+

cupsRasterClose(), +cupsRasterOpen(), +cupsRasterReadHeader(), +cupsRasterReadPixels(), +cupsRasterWritePixels() + +

+

cupsRasterWritePixels()

+

Usage

+
+unsigned
+cupsRasterWritePixels(cups_raster_t *ras,
+                      unsigned char *pixels,
+		      unsigned length);
+
+

Arguments

+
+ + + + + +
ArgumentDescription
rasThe raster stream to write to.
pixelsThe pixel data to write.
lengthThe number of bytes to write.
+
+

Returns

+

The number of bytes written.

+

Description

+

cupsRasterWritePixels() writes the specified pixel data +to a raster stream.

+

Example

+
+#include <cups/raster.h>
+
+int                  line;
+cups_raster_t        *ras;
+cups_raster_header_t header;
+unsigned char        pixels[8192];
+...
+
+cupsRasterWriteHeader(ras, &header);
+
+for (line = 0; line < header.cupsHeight; line ++)
+{
+  ...
+
+  cupsRasterWritePixels(ras, pixels, header.cupsBytesPerLine);
+}
+
+

See Also

+

cupsRasterClose(), +cupsRasterOpen(), +cupsRasterReadHeader(), +cupsRasterReadPixels(), +cupsRasterWriteHeader() + +

+

cupsServer()

+

Usage

+
+const char *
+cupsServer(void);
+
+

Returns

+

A pointer to the default server name.

+

Description

+

cupsServer() returns a pointer to the default server +name. The server name is stored in a static location and will be +overwritten with every call to cupsServer()

+

The default server is determined from the following locations:

+
    +
  1. The CUPS_SERVER environment variable,
  2. +
  3. The ServerName directive in the cupsd.conf + file,
  4. +
  5. The default host, "localhost".
  6. +
+

Example

+
+#include <cups/cups.h>
+
+const char *server;
+
+server = cupsServer();
+
+

See Also

+

cupsGetPassword(), +cupsUser() + +

+

cupsTempFile()

+

Usage

+
+char *
+cupsTempFile(char *filename,
+             int length);
+
+

Arguments

+
+ + + + +
ArgumentDescription
filenameThe character string to hold the temporary +filename.
lengthThe size of the filename string in bytes.
+
+

Returns

+

A pointer to filename.

+

Description

+

cupsTempFile() generates a temporary filename for the +/var/tmp directory or the directory specified by the TMPDIR + environment variable.

+

Example

+
+#include <cups/cups.h>
+
+char filename[256];
+
+cupsTempFile(filename, sizeof(filename));
+
+ + +

cupsUser()

+

Usage

+
+const char *
+cupsUser(void);
+
+

Returns

+

A pointer to the current username or NULL if the user +ID is undefined.

+

Description

+

cupsUser() returns the name associated with the current +user ID as reported by the getuid() system call.

+

Example

+
+#include <cups/cups.h>
+
+const char *user;
+
+user = cupsUser();
+
+

See Also

+

cupsGetPassword(), +cupsServer() + +

+

httpBlocking()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

httpCheck()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

httpClearFields()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

httpClose()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

httpConnect()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

httpDecode64()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

httpDelete()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

httpEncode64()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

httpError()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

httpFlush()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

httpGet()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

httpGets()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

httpGetDateString()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

httpGetDateTime()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

httpGetField()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

httpGetLength()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

httpHead()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

httpInitialize()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

httpOptions()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

httpPost()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

httpPrintf()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

httpPut()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

httpRead()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

httpReconnect()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

httpSeparate()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

httpSetField()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

httpTrace()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

httpUpdate()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

httpWrite()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

ippAddBoolean()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

ippAddBooleans()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

ippAddDate()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

ippAddInteger()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

ippAddIntegers()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

ippAddRange()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

ippAddRanges()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

ippAddResolution()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

ippAddResolutions()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

ippAddSeparator()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

ippAddString()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

ippAddStrings()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

ippDateToTime()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

ippDelete()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

ippFindAttribute()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

ippLength()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

ippNew()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

ippPort()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

ippRead()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

ippTimeToDate()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

ippWrite()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

mimeAddFilter()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

mimeAddType()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

mimeAddTypeRule()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

mimeDelete()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

mimeFileType()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

mimeFilter()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

mimeLoad()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

mimeMerge()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

mimeNew()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

mimeType()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

ppdClose()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

ppdConflicts()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

pddEmitFd()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

ppdEmit()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

ppdFindChoice()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

ppdFindMarkedChoice()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

ppdFindOption()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

ppdIsMarked()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

ppdMarkDefaults()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

ppdMarkOption()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

ppdOpenFd()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

ppdOpenFile()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

ppdOpen()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

ppdPageLength()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

ppdPageSize()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + +

ppdPageWidth()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + diff --git a/doc/spm.pdf b/doc/spm.pdf new file mode 100644 index 0000000000..26d2680c06 --- /dev/null +++ b/doc/spm.pdf @@ -0,0 +1,9119 @@ +%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[11 0 R +12 0 R +13 0 R +]endobj +15 0 obj<>endobj +16 0 obj<>endobj +17 0 obj<>endobj +18 0 obj[15 0 R +16 0 R +17 0 R +]endobj +19 0 obj<>endobj +20 0 obj<>endobj +21 0 obj<>endobj +22 0 obj[19 0 R +20 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[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 +]endobj +33 0 obj<>endobj +34 0 obj<>endobj +35 0 obj<>endobj +36 0 obj[33 0 R +34 0 R +35 0 R +]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[37 0 R +38 0 R +39 0 R +40 0 R +41 0 R +42 0 R +43 0 R +44 0 R +]endobj +46 0 obj<>endobj +47 0 obj<>endobj +48 0 obj<>endobj +49 0 obj<>endobj +50 0 obj[46 0 R +47 0 R +48 0 R +49 0 R +]endobj +51 0 obj<>endobj +52 0 obj<>endobj +53 0 obj<>endobj +54 0 obj[51 0 R +52 0 R +53 0 R +]endobj +55 0 obj<>endobj +56 0 obj<>endobj +57 0 obj<>endobj +58 0 obj[55 0 R +56 0 R +57 0 R +]endobj +59 0 obj<>endobj +60 0 obj<>endobj +61 0 obj<>endobj +62 0 obj<>endobj +63 0 obj[59 0 R +60 0 R +61 0 R +62 0 R +]endobj +64 0 obj<>endobj +65 0 obj[64 0 R +]endobj +66 0 obj<>endobj +67 0 obj<>endobj +68 0 obj<>endobj +69 0 obj[66 0 R +67 0 R +68 0 R +]endobj +70 0 obj<>endobj +71 0 obj<>endobj +72 0 obj<>endobj +73 0 obj<>endobj +74 0 obj<>endobj +75 0 obj[70 0 R +71 0 R +72 0 R +73 0 R +74 0 R +]endobj +76 0 obj<>endobj +77 0 obj<>endobj +78 0 obj<>endobj +79 0 obj<>endobj +80 0 obj<>endobj +81 0 obj[76 0 R +77 0 R +78 0 R +79 0 R +80 0 R +]endobj +82 0 obj<>endobj +83 0 obj<>endobj +84 0 obj<>endobj +85 0 obj<>endobj +86 0 obj<>endobj +87 0 obj[82 0 R +83 0 R +84 0 R +85 0 R +86 0 R +]endobj +88 0 obj<>endobj +89 0 obj<>endobj +90 0 obj<>endobj +91 0 obj<>endobj +92 0 obj<>endobj +93 0 obj[88 0 R +89 0 R +90 0 R +91 0 R +92 0 R +]endobj +94 0 obj<>endobj +95 0 obj<>endobj +96 0 obj<>endobj +97 0 obj<>endobj +98 0 obj<>endobj +99 0 obj[94 0 R +95 0 R +96 0 R +97 0 R +98 0 R +]endobj +100 0 obj<>endobj +101 0 obj<>endobj +102 0 obj<>endobj +103 0 obj<>endobj +104 0 obj<>endobj +105 0 obj[100 0 R +101 0 R +102 0 R +103 0 R +104 0 R +]endobj +106 0 obj<>endobj +107 0 obj<>endobj +108 0 obj[106 0 R +107 0 R +]endobj +109 0 obj<>endobj +110 0 obj<>endobj +111 0 obj<>endobj +112 0 obj<>endobj +113 0 obj[109 0 R +110 0 R +111 0 R +112 0 R +]endobj +114 0 obj<>endobj +115 0 obj<>endobj +116 0 obj<>endobj +117 0 obj<>endobj +118 0 obj[114 0 R +115 0 R +116 0 R +117 0 R +]endobj +119 0 obj<>endobj +120 0 obj<>endobj +121 0 obj[119 0 R +120 0 R +]endobj +122 0 obj<>endobj +123 0 obj<>endobj +124 0 obj<>endobj +125 0 obj<>endobj +126 0 obj<>endobj +127 0 obj[122 0 R +123 0 R +124 0 R +125 0 R +126 0 R +]endobj +128 0 obj<>endobj +129 0 obj<>endobj +130 0 obj<>endobj +131 0 obj<>endobj +132 0 obj<>endobj +133 0 obj[128 0 R +129 0 R +130 0 R +131 0 R +132 0 R +]endobj +134 0 obj<>endobj +135 0 obj<>endobj +136 0 obj<>endobj +137 0 obj<>endobj +138 0 obj<>endobj +139 0 obj[134 0 R +135 0 R +136 0 R +137 0 R +138 0 R +]endobj +140 0 obj<>endobj +141 0 obj<>endobj +142 0 obj<>endobj +143 0 obj<>endobj +144 0 obj<>endobj +145 0 obj[140 0 R +141 0 R +142 0 R +143 0 R +144 0 R +]endobj +146 0 obj<>endobj +147 0 obj<>endobj +148 0 obj<>endobj +149 0 obj<>endobj +150 0 obj<>endobj +151 0 obj[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[152 0 R +153 0 R +154 0 R +155 0 R +156 0 R +]endobj +158 0 obj<>endobj +159 0 obj<>endobj +160 0 obj[158 0 R +159 0 R +]endobj +161 0 obj<>endobj +162 0 obj<>endobj +163 0 obj[161 0 R +162 0 R +]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<>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[164 0 R +165 0 R +166 0 R +167 0 R +168 0 R +169 0 R +170 0 R +171 0 R +172 0 R +173 0 R +174 0 R +175 0 R +176 0 R +177 0 R +178 0 R +179 0 R +180 0 R +181 0 R +182 0 R +183 0 R +184 0 R +185 0 R +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 +]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<>endobj +356 0 obj<>endobj +357 0 obj<>endobj +358 0 obj<>endobj +359 0 obj<>endobj +360 0 obj<>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[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 +355 0 R +356 0 R +357 0 R +358 0 R +359 0 R +360 0 R +361 0 R +362 0 R +363 0 R +364 0 R +365 0 R +366 0 R +367 0 R +368 0 R +369 0 R +370 0 R +371 0 R +372 0 R +373 0 R +374 0 R +375 0 R +376 0 R +377 0 R +378 0 R +379 0 R +380 0 R +381 0 R +382 0 R +383 0 R +384 0 R +385 0 R +386 0 R +387 0 R +388 0 R +389 0 R +390 0 R +391 0 R +392 0 R +393 0 R +394 0 R +395 0 R +396 0 R +397 0 R +398 0 R +]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<>endobj +411 0 obj<>endobj +412 0 obj<>endobj +413 0 obj<>endobj +414 0 obj<>endobj +415 0 obj<>endobj +416 0 obj<>endobj +417 0 obj<>endobj +418 0 obj<>endobj +419 0 obj<>endobj +420 0 obj<>endobj +421 0 obj<>endobj +422 0 obj<>endobj +423 0 obj<>endobj +424 0 obj<>endobj +425 0 obj<>endobj +426 0 obj<>endobj +427 0 obj<>endobj +428 0 obj<>endobj +429 0 obj<>endobj +430 0 obj<>endobj +431 0 obj<>endobj +432 0 obj<>endobj +433 0 obj<>endobj +434 0 obj<>endobj +435 0 obj<>endobj +436 0 obj<>endobj +437 0 obj<>endobj +438 0 obj<>endobj +439 0 obj<>endobj +440 0 obj<>endobj +441 0 obj<>endobj +442 0 obj<>endobj +443 0 obj<>endobj +444 0 obj<>endobj +445 0 obj<>endobj +446 0 obj<>endobj +447 0 obj<>endobj +448 0 obj<>endobj +449 0 obj<>endobj +450 0 obj<>endobj +451 0 obj<>endobj +452 0 obj<>endobj +453 0 obj<>endobj +454 0 obj<>endobj +455 0 obj<>endobj +456 0 obj<>endobj +457 0 obj<>endobj +458 0 obj<>endobj +459 0 obj<>endobj +460 0 obj<>endobj +461 0 obj<>endobj +462 0 obj<>endobj +463 0 obj[400 0 R +401 0 R +402 0 R +403 0 R +404 0 R +405 0 R +406 0 R +407 0 R +408 0 R +409 0 R +410 0 R +411 0 R +412 0 R +413 0 R +414 0 R +415 0 R +416 0 R +417 0 R +418 0 R +419 0 R +420 0 R +421 0 R +422 0 R +423 0 R +424 0 R +425 0 R +426 0 R +427 0 R +428 0 R +429 0 R +430 0 R +431 0 R +432 0 R +433 0 R +434 0 R +435 0 R +436 0 R +437 0 R +438 0 R +439 0 R +440 0 R +441 0 R +442 0 R +443 0 R +444 0 R +445 0 R +446 0 R +447 0 R +448 0 R +449 0 R +450 0 R +451 0 R +452 0 R +453 0 R +454 0 R +455 0 R +456 0 R +457 0 R +458 0 R +459 0 R +460 0 R +461 0 R +462 0 R +]endobj +464 0 obj<>endobj +465 0 obj<>endobj +466 0 obj<>endobj +467 0 obj<>endobj +468 0 obj<>endobj +469 0 obj<>endobj +470 0 obj<>endobj +471 0 obj<>endobj +472 0 obj<>endobj +473 0 obj<>endobj +474 0 obj<>endobj +475 0 obj<>endobj +476 0 obj<>endobj +477 0 obj<>endobj +478 0 obj<>endobj +479 0 obj<>endobj +480 0 obj<>endobj +481 0 obj<>endobj +482 0 obj<>endobj +483 0 obj<>endobj +484 0 obj<>endobj +485 0 obj<>endobj +486 0 obj<>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[464 0 R +465 0 R +466 0 R +467 0 R +468 0 R +469 0 R +470 0 R +471 0 R +472 0 R +473 0 R +474 0 R +475 0 R +476 0 R +477 0 R +478 0 R +479 0 R +480 0 R +481 0 R +482 0 R +483 0 R +484 0 R +485 0 R +486 0 R +487 0 R +488 0 R +489 0 R +490 0 R +491 0 R +492 0 R +493 0 R +494 0 R +495 0 R +496 0 R +497 0 R +498 0 R +499 0 R +500 0 R +501 0 R +502 0 R +503 0 R +504 0 R +505 0 R +506 0 R +507 0 R +508 0 R +509 0 R +510 0 R +511 0 R +512 0 R +513 0 R +514 0 R +515 0 R +516 0 R +]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<>endobj +534 0 obj<>endobj +535 0 obj<>endobj +536 0 obj<>endobj +537 0 obj<>endobj +538 0 obj<>endobj +539 0 obj<>endobj +540 0 obj<>endobj +541 0 obj<>endobj +542 0 obj<>endobj +543 0 obj<>endobj +544 0 obj<>endobj +545 0 obj<>endobj +546 0 obj<>endobj +547 0 obj<>endobj +548 0 obj<>endobj +549 0 obj<>endobj +550 0 obj<>endobj +551 0 obj<>endobj +552 0 obj<>endobj +553 0 obj<>endobj +554 0 obj<>endobj +555 0 obj<>endobj +556 0 obj<>endobj +557 0 obj<>endobj +558 0 obj<>endobj +559 0 obj<>endobj +560 0 obj<>endobj +561 0 obj<>endobj +562 0 obj<>endobj +563 0 obj<>endobj +564 0 obj<>endobj +565 0 obj<>endobj +566 0 obj<>endobj +567 0 obj<>endobj +568 0 obj<>endobj +569 0 obj<>endobj +570 0 obj<>endobj +571 0 obj<>endobj +572 0 obj[518 0 R +519 0 R +520 0 R +521 0 R +522 0 R +523 0 R +524 0 R +525 0 R +526 0 R +527 0 R +528 0 R +529 0 R +530 0 R +531 0 R +532 0 R +533 0 R +534 0 R +535 0 R +536 0 R +537 0 R +538 0 R +539 0 R +540 0 R +541 0 R +542 0 R +543 0 R +544 0 R +545 0 R +546 0 R +547 0 R +548 0 R +549 0 R +550 0 R +551 0 R +552 0 R +553 0 R +554 0 R +555 0 R +556 0 R +557 0 R +558 0 R +559 0 R +560 0 R +561 0 R +562 0 R +563 0 R +564 0 R +565 0 R +566 0 R +567 0 R +568 0 R +569 0 R +570 0 R +571 0 R +]endobj +573 0 obj<>endobj +574 0 obj<>endobj +575 0 obj<>endobj +576 0 obj<>endobj +577 0 obj<>endobj +578 0 obj<>endobj +579 0 obj<>endobj +580 0 obj<>endobj +581 0 obj<>endobj +582 0 obj<>endobj +583 0 obj<>endobj +584 0 obj<>endobj +585 0 obj<>endobj +586 0 obj<>endobj +587 0 obj<>endobj +588 0 obj<>endobj +589 0 obj<>endobj +590 0 obj<>endobj +591 0 obj<>endobj +592 0 obj<>endobj +593 0 obj<>endobj +594 0 obj<>endobj +595 0 obj<>endobj +596 0 obj<>endobj +597 0 obj<>endobj +598 0 obj<>endobj +599 0 obj<>endobj +600 0 obj<>endobj +601 0 obj<>endobj +602 0 obj<>endobj +603 0 obj<>endobj +604 0 obj<>endobj +605 0 obj<>endobj +606 0 obj<>endobj +607 0 obj<>endobj +608 0 obj<>endobj +609 0 obj<>endobj +610 0 obj<>endobj +611 0 obj<>endobj +612 0 obj<>endobj +613 0 obj<>endobj +614 0 obj<>endobj +615 0 obj<>endobj +616 0 obj<>endobj +617 0 obj<>endobj +618 0 obj<>endobj +619 0 obj<>endobj +620 0 obj<>endobj +621 0 obj<>endobj +622 0 obj<>endobj +623 0 obj<>endobj +624 0 obj<>endobj +625 0 obj<>endobj +626 0 obj<>endobj +627 0 obj[573 0 R +574 0 R +575 0 R +576 0 R +577 0 R +578 0 R +579 0 R +580 0 R +581 0 R +582 0 R +583 0 R +584 0 R +585 0 R +586 0 R +587 0 R +588 0 R +589 0 R +590 0 R +591 0 R +592 0 R +593 0 R +594 0 R +595 0 R +596 0 R +597 0 R +598 0 R +599 0 R +600 0 R +601 0 R +602 0 R +603 0 R +604 0 R +605 0 R +606 0 R +607 0 R +608 0 R +609 0 R +610 0 R +611 0 R +612 0 R +613 0 R +614 0 R +615 0 R +616 0 R +617 0 R +618 0 R +619 0 R +620 0 R +621 0 R +622 0 R +623 0 R +624 0 R +625 0 R +626 0 R +]endobj +628 0 obj<>endobj +629 0 obj<>endobj +630 0 obj<>endobj +631 0 obj<>endobj +632 0 obj<>endobj +633 0 obj<>endobj +634 0 obj<>endobj +635 0 obj<>endobj +636 0 obj<>endobj +637 0 obj<>endobj +638 0 obj<>endobj +639 0 obj<>endobj +640 0 obj<>endobj +641 0 obj<>endobj +642 0 obj<>endobj +643 0 obj<>endobj +644 0 obj<>endobj +645 0 obj<>endobj +646 0 obj<>endobj +647 0 obj<>endobj +648 0 obj<>endobj +649 0 obj<>endobj +650 0 obj<>endobj +651 0 obj<>endobj +652 0 obj<>endobj +653 0 obj<>endobj +654 0 obj<>endobj +655 0 obj<>endobj +656 0 obj<>endobj +657 0 obj<>endobj +658 0 obj<>endobj +659 0 obj<>endobj +660 0 obj<>endobj +661 0 obj<>endobj +662 0 obj<>endobj +663 0 obj<>endobj +664 0 obj<>endobj +665 0 obj<>endobj +666 0 obj<>endobj +667 0 obj<>endobj +668 0 obj<>endobj +669 0 obj<>endobj +670 0 obj<>endobj +671 0 obj<>endobj +672 0 obj<>endobj +673 0 obj<>endobj +674 0 obj<>endobj +675 0 obj<>endobj +676 0 obj<>endobj +677 0 obj<>endobj +678 0 obj<>endobj +679 0 obj<>endobj +680 0 obj<>endobj +681 0 obj[628 0 R +629 0 R +630 0 R +631 0 R +632 0 R +633 0 R +634 0 R +635 0 R +636 0 R +637 0 R +638 0 R +639 0 R +640 0 R +641 0 R +642 0 R +643 0 R +644 0 R +645 0 R +646 0 R +647 0 R +648 0 R +649 0 R +650 0 R +651 0 R +652 0 R +653 0 R +654 0 R +655 0 R +656 0 R +657 0 R +658 0 R +659 0 R +660 0 R +661 0 R +662 0 R +663 0 R +664 0 R +665 0 R +666 0 R +667 0 R +668 0 R +669 0 R +670 0 R +671 0 R +672 0 R +673 0 R +674 0 R +675 0 R +676 0 R +677 0 R +678 0 R +679 0 R +680 0 R +]endobj +682 0 obj<>endobj +683 0 obj<>endobj +684 0 obj<>endobj +685 0 obj<>endobj +686 0 obj<>endobj +687 0 obj<>endobj +688 0 obj<>endobj +689 0 obj<>endobj +690 0 obj<>endobj +691 0 obj<>endobj +692 0 obj<>endobj +693 0 obj<>endobj +694 0 obj<>endobj +695 0 obj<>endobj +696 0 obj<>endobj +697 0 obj<>endobj +698 0 obj<>endobj +699 0 obj<>endobj +700 0 obj<>endobj +701 0 obj<>endobj +702 0 obj<>endobj +703 0 obj<>endobj +704 0 obj<>endobj +705 0 obj<>endobj +706 0 obj<>endobj +707 0 obj<>endobj +708 0 obj<>endobj +709 0 obj<>endobj +710 0 obj<>endobj +711 0 obj<>endobj +712 0 obj<>endobj +713 0 obj<>endobj +714 0 obj<>endobj +715 0 obj<>endobj +716 0 obj<>endobj +717 0 obj<>endobj +718 0 obj<>endobj +719 0 obj<>endobj +720 0 obj<>endobj +721 0 obj<>endobj +722 0 obj<>endobj +723 0 obj<>endobj +724 0 obj<>endobj +725 0 obj<>endobj +726 0 obj<>endobj +727 0 obj<>endobj +728 0 obj<>endobj +729 0 obj<>endobj +730 0 obj<>endobj +731 0 obj<>endobj +732 0 obj<>endobj +733 0 obj<>endobj +734 0 obj<>endobj +735 0 obj<>endobj +736 0 obj[682 0 R +683 0 R +684 0 R +685 0 R +686 0 R +687 0 R +688 0 R +689 0 R +690 0 R +691 0 R +692 0 R +693 0 R +694 0 R +695 0 R +696 0 R +697 0 R +698 0 R +699 0 R +700 0 R +701 0 R +702 0 R +703 0 R +704 0 R +705 0 R +706 0 R +707 0 R +708 0 R +709 0 R +710 0 R +711 0 R +712 0 R +713 0 R +714 0 R +715 0 R +716 0 R +717 0 R +718 0 R +719 0 R +720 0 R +721 0 R +722 0 R +723 0 R +724 0 R +725 0 R +726 0 R +727 0 R +728 0 R +729 0 R +730 0 R +731 0 R +732 0 R +733 0 R +734 0 R +735 0 R +]endobj +737 0 obj<>endobj +738 0 obj<>endobj +739 0 obj<>endobj +740 0 obj<>endobj +741 0 obj<>endobj +742 0 obj<>endobj +743 0 obj<>endobj +744 0 obj<>endobj +745 0 obj<>endobj +746 0 obj<>endobj +747 0 obj<>endobj +748 0 obj<>endobj +749 0 obj<>endobj +750 0 obj<>endobj +751 0 obj<>endobj +752 0 obj<>endobj +753 0 obj<>endobj +754 0 obj<>endobj +755 0 obj<>endobj +756 0 obj<>endobj +757 0 obj<>endobj +758 0 obj<>endobj +759 0 obj<>endobj +760 0 obj<>endobj +761 0 obj<>endobj +762 0 obj<>endobj +763 0 obj<>endobj +764 0 obj<>endobj +765 0 obj<>endobj +766 0 obj<>endobj +767 0 obj<>endobj +768 0 obj<>endobj +769 0 obj<>endobj +770 0 obj<>endobj +771 0 obj<>endobj +772 0 obj<>endobj +773 0 obj<>endobj +774 0 obj<>endobj +775 0 obj<>endobj +776 0 obj<>endobj +777 0 obj<>endobj +778 0 obj<>endobj +779 0 obj<>endobj +780 0 obj<>endobj +781 0 obj<>endobj +782 0 obj<>endobj +783 0 obj<>endobj +784 0 obj<>endobj +785 0 obj<>endobj +786 0 obj<>endobj +787 0 obj<>endobj +788 0 obj<>endobj +789 0 obj<>endobj +790 0 obj<>endobj +791 0 obj[737 0 R +738 0 R +739 0 R +740 0 R +741 0 R +742 0 R +743 0 R +744 0 R +745 0 R +746 0 R +747 0 R +748 0 R +749 0 R +750 0 R +751 0 R +752 0 R +753 0 R +754 0 R +755 0 R +756 0 R +757 0 R +758 0 R +759 0 R +760 0 R +761 0 R +762 0 R +763 0 R +764 0 R +765 0 R +766 0 R +767 0 R +768 0 R +769 0 R +770 0 R +771 0 R +772 0 R +773 0 R +774 0 R +775 0 R +776 0 R +777 0 R +778 0 R +779 0 R +780 0 R +781 0 R +782 0 R +783 0 R +784 0 R +785 0 R +786 0 R +787 0 R +788 0 R +789 0 R +790 0 R +]endobj +792 0 obj<>endobj +793 0 obj<>endobj +794 0 obj<>endobj +795 0 obj<>endobj +796 0 obj<>endobj +797 0 obj<>endobj +798 0 obj<>endobj +799 0 obj<>endobj +800 0 obj<>endobj +801 0 obj<>endobj +802 0 obj<>endobj +803 0 obj<>endobj +804 0 obj<>endobj +805 0 obj<>endobj +806 0 obj<>endobj +807 0 obj<>endobj +808 0 obj<>endobj +809 0 obj<>endobj +810 0 obj<>endobj +811 0 obj<>endobj +812 0 obj<>endobj +813 0 obj<>endobj +814 0 obj<>endobj +815 0 obj<>endobj +816 0 obj<>endobj +817 0 obj<>endobj +818 0 obj<>endobj +819 0 obj<>endobj +820 0 obj<>endobj +821 0 obj<>endobj +822 0 obj<>endobj +823 0 obj<>endobj +824 0 obj<>endobj +825 0 obj<>endobj +826 0 obj<>endobj +827 0 obj<>endobj +828 0 obj<>endobj +829 0 obj<>endobj +830 0 obj<>endobj +831 0 obj<>endobj +832 0 obj<>endobj +833 0 obj<>endobj +834 0 obj<>endobj +835 0 obj<>endobj +836 0 obj<>endobj +837 0 obj<>endobj +838 0 obj<>endobj +839 0 obj<>endobj +840 0 obj<>endobj +841 0 obj<>endobj +842 0 obj<>endobj +843 0 obj<>endobj +844 0 obj<>endobj +845 0 obj[792 0 R +793 0 R +794 0 R +795 0 R +796 0 R +797 0 R +798 0 R +799 0 R +800 0 R +801 0 R +802 0 R +803 0 R +804 0 R +805 0 R +806 0 R +807 0 R +808 0 R +809 0 R +810 0 R +811 0 R +812 0 R +813 0 R +814 0 R +815 0 R +816 0 R +817 0 R +818 0 R +819 0 R +820 0 R +821 0 R +822 0 R +823 0 R +824 0 R +825 0 R +826 0 R +827 0 R +828 0 R +829 0 R +830 0 R +831 0 R +832 0 R +833 0 R +834 0 R +835 0 R +836 0 R +837 0 R +838 0 R +839 0 R +840 0 R +841 0 R +842 0 R +843 0 R +844 0 R +]endobj +846 0 obj<>endobj +847 0 obj<>endobj +848 0 obj<>endobj +849 0 obj<>endobj +850 0 obj<>endobj +851 0 obj<>endobj +852 0 obj<>endobj +853 0 obj<>endobj +854 0 obj<>endobj +855 0 obj<>endobj +856 0 obj<>endobj +857 0 obj<>endobj +858 0 obj<>endobj +859 0 obj<>endobj +860 0 obj<>endobj +861 0 obj<>endobj +862 0 obj<>endobj +863 0 obj<>endobj +864 0 obj<>endobj +865 0 obj<>endobj +866 0 obj<>endobj +867 0 obj<>endobj +868 0 obj<>endobj +869 0 obj<>endobj +870 0 obj<>endobj +871 0 obj<>endobj +872 0 obj<>endobj +873 0 obj<>endobj +874 0 obj<>endobj +875 0 obj<>endobj +876 0 obj<>endobj +877 0 obj<>endobj +878 0 obj<>endobj +879 0 obj<>endobj +880 0 obj<>endobj +881 0 obj<>endobj +882 0 obj<>endobj +883 0 obj<>endobj +884 0 obj<>endobj +885 0 obj<>endobj +886 0 obj<>endobj +887 0 obj<>endobj +888 0 obj<>endobj +889 0 obj<>endobj +890 0 obj<>endobj +891 0 obj<>endobj +892 0 obj<>endobj +893 0 obj<>endobj +894 0 obj<>endobj +895 0 obj<>endobj +896 0 obj<>endobj +897 0 obj<>endobj +898 0 obj<>endobj +899 0 obj<>endobj +900 0 obj[846 0 R +847 0 R +848 0 R +849 0 R +850 0 R +851 0 R +852 0 R +853 0 R +854 0 R +855 0 R +856 0 R +857 0 R +858 0 R +859 0 R +860 0 R +861 0 R +862 0 R +863 0 R +864 0 R +865 0 R +866 0 R +867 0 R +868 0 R +869 0 R +870 0 R +871 0 R +872 0 R +873 0 R +874 0 R +875 0 R +876 0 R +877 0 R +878 0 R +879 0 R +880 0 R +881 0 R +882 0 R +883 0 R +884 0 R +885 0 R +886 0 R +887 0 R +888 0 R +889 0 R +890 0 R +891 0 R +892 0 R +893 0 R +894 0 R +895 0 R +896 0 R +897 0 R +898 0 R +899 0 R +]endobj +901 0 obj<>endobj +902 0 obj<>endobj +903 0 obj<>endobj +904 0 obj<>endobj +905 0 obj<>endobj +906 0 obj<>endobj +907 0 obj<>endobj +908 0 obj<>endobj +909 0 obj<>endobj +910 0 obj<>endobj +911 0 obj<>endobj +912 0 obj<>endobj +913 0 obj<>endobj +914 0 obj<>endobj +915 0 obj<>endobj +916 0 obj<>endobj +917 0 obj<>endobj +918 0 obj<>endobj +919 0 obj<>endobj +920 0 obj<>endobj +921 0 obj<>endobj +922 0 obj<>endobj +923 0 obj<>endobj +924 0 obj<>endobj +925 0 obj<>endobj +926 0 obj<>endobj +927 0 obj<>endobj +928 0 obj<>endobj +929 0 obj<>endobj +930 0 obj<>endobj +931 0 obj<>endobj +932 0 obj<>endobj +933 0 obj<>endobj +934 0 obj<>endobj +935 0 obj<>endobj +936 0 obj<>endobj +937 0 obj<>endobj +938 0 obj<>endobj +939 0 obj<>endobj +940 0 obj<>endobj +941 0 obj<>endobj +942 0 obj<>endobj +943 0 obj<>endobj +944 0 obj<>endobj +945 0 obj<>endobj +946 0 obj<>endobj +947 0 obj<>endobj +948 0 obj<>endobj +949 0 obj<>endobj +950 0 obj<>endobj +951 0 obj<>endobj +952 0 obj<>endobj +953 0 obj<>endobj +954 0 obj<>endobj +955 0 obj[901 0 R +902 0 R +903 0 R +904 0 R +905 0 R +906 0 R +907 0 R +908 0 R +909 0 R +910 0 R +911 0 R +912 0 R +913 0 R +914 0 R +915 0 R +916 0 R +917 0 R +918 0 R +919 0 R +920 0 R +921 0 R +922 0 R +923 0 R +924 0 R +925 0 R +926 0 R +927 0 R +928 0 R +929 0 R +930 0 R +931 0 R +932 0 R +933 0 R +934 0 R +935 0 R +936 0 R +937 0 R +938 0 R +939 0 R +940 0 R +941 0 R +942 0 R +943 0 R +944 0 R +945 0 R +946 0 R +947 0 R +948 0 R +949 0 R +950 0 R +951 0 R +952 0 R +953 0 R +954 0 R +]endobj +956 0 obj<>endobj +957 0 obj<>endobj +958 0 obj<>endobj +959 0 obj<>endobj +960 0 obj<>endobj +961 0 obj<>endobj +962 0 obj<>endobj +963 0 obj<>endobj +964 0 obj<>endobj +965 0 obj<>endobj +966 0 obj<>endobj +967 0 obj<>endobj +968 0 obj<>endobj +969 0 obj<>endobj +970 0 obj<>endobj +971 0 obj<>endobj +972 0 obj<>endobj +973 0 obj<>endobj +974 0 obj<>endobj +975 0 obj<>endobj +976 0 obj<>endobj +977 0 obj<>endobj +978 0 obj<>endobj +979 0 obj<>endobj +980 0 obj<>endobj +981 0 obj<>endobj +982 0 obj<>endobj +983 0 obj<>endobj +984 0 obj<>endobj +985 0 obj<>endobj +986 0 obj<>endobj +987 0 obj<>endobj +988 0 obj<>endobj +989 0 obj<>endobj +990 0 obj<>endobj +991 0 obj<>endobj +992 0 obj<>endobj +993 0 obj<>endobj +994 0 obj<>endobj +995 0 obj<>endobj +996 0 obj<>endobj +997 0 obj<>endobj +998 0 obj<>endobj +999 0 obj<>endobj +1000 0 obj<>endobj +1001 0 obj<>endobj +1002 0 obj<>endobj +1003 0 obj<>endobj +1004 0 obj<>endobj +1005 0 obj<>endobj +1006 0 obj<>endobj +1007 0 obj<>endobj +1008 0 obj<>endobj +1009 0 obj<>endobj +1010 0 obj[956 0 R +957 0 R +958 0 R +959 0 R +960 0 R +961 0 R +962 0 R +963 0 R +964 0 R +965 0 R +966 0 R +967 0 R +968 0 R +969 0 R +970 0 R +971 0 R +972 0 R +973 0 R +974 0 R +975 0 R +976 0 R +977 0 R +978 0 R +979 0 R +980 0 R +981 0 R +982 0 R +983 0 R +984 0 R +985 0 R +986 0 R +987 0 R +988 0 R +989 0 R +990 0 R +991 0 R +992 0 R +993 0 R +994 0 R +995 0 R +996 0 R +997 0 R +998 0 R +999 0 R +1000 0 R +1001 0 R +1002 0 R +1003 0 R +1004 0 R +1005 0 R +1006 0 R +1007 0 R +1008 0 R +1009 0 R +]endobj +1011 0 obj<>endobj +1012 0 obj<>endobj +1013 0 obj<>endobj +1014 0 obj<>endobj +1015 0 obj<>endobj +1016 0 obj<>endobj +1017 0 obj<>endobj +1018 0 obj<>endobj +1019 0 obj<>endobj +1020 0 obj<>endobj +1021 0 obj<>endobj +1022 0 obj<>endobj +1023 0 obj<>endobj +1024 0 obj<>endobj +1025 0 obj<>endobj +1026 0 obj<>endobj +1027 0 obj<>endobj +1028 0 obj<>endobj +1029 0 obj<>endobj +1030 0 obj<>endobj +1031 0 obj<>endobj +1032 0 obj<>endobj +1033 0 obj<>endobj +1034 0 obj<>endobj +1035 0 obj<>endobj +1036 0 obj<>endobj +1037 0 obj<>endobj +1038 0 obj<>endobj +1039 0 obj<>endobj +1040 0 obj<>endobj +1041 0 obj<>endobj +1042 0 obj<>endobj +1043 0 obj<>endobj +1044 0 obj<>endobj +1045 0 obj<>endobj +1046 0 obj<>endobj +1047 0 obj<>endobj +1048 0 obj<>endobj +1049 0 obj<>endobj +1050 0 obj<>endobj +1051 0 obj<>endobj +1052 0 obj<>endobj +1053 0 obj<>endobj +1054 0 obj<>endobj +1055 0 obj<>endobj +1056 0 obj<>endobj +1057 0 obj<>endobj +1058 0 obj<>endobj +1059 0 obj<>endobj +1060 0 obj<>endobj +1061 0 obj<>endobj +1062 0 obj<>endobj +1063 0 obj<>endobj +1064 0 obj[1011 0 R +1012 0 R +1013 0 R +1014 0 R +1015 0 R +1016 0 R +1017 0 R +1018 0 R +1019 0 R +1020 0 R +1021 0 R +1022 0 R +1023 0 R +1024 0 R +1025 0 R +1026 0 R +1027 0 R +1028 0 R +1029 0 R +1030 0 R +1031 0 R +1032 0 R +1033 0 R +1034 0 R +1035 0 R +1036 0 R +1037 0 R +1038 0 R +1039 0 R +1040 0 R +1041 0 R +1042 0 R +1043 0 R +1044 0 R +1045 0 R +1046 0 R +1047 0 R +1048 0 R +1049 0 R +1050 0 R +1051 0 R +1052 0 R +1053 0 R +1054 0 R +1055 0 R +1056 0 R +1057 0 R +1058 0 R +1059 0 R +1060 0 R +1061 0 R +1062 0 R +1063 0 R +]endobj +1065 0 obj<>endobj +1066 0 obj<>endobj +1067 0 obj<>endobj +1068 0 obj<>endobj +1069 0 obj<>endobj +1070 0 obj<>endobj +1071 0 obj<>endobj +1072 0 obj<>endobj +1073 0 obj<>endobj +1074 0 obj<>endobj +1075 0 obj<>endobj +1076 0 obj<>endobj +1077 0 obj<>endobj +1078 0 obj<>endobj +1079 0 obj<>endobj +1080 0 obj<>endobj +1081 0 obj<>endobj +1082 0 obj<>endobj +1083 0 obj<>endobj +1084 0 obj<>endobj +1085 0 obj<>endobj +1086 0 obj<>endobj +1087 0 obj<>endobj +1088 0 obj<>endobj +1089 0 obj<>endobj +1090 0 obj<>endobj +1091 0 obj<>endobj +1092 0 obj<>endobj +1093 0 obj<>endobj +1094 0 obj<>endobj +1095 0 obj<>endobj +1096 0 obj<>endobj +1097 0 obj<>endobj +1098 0 obj<>endobj +1099 0 obj<>endobj +1100 0 obj<>endobj +1101 0 obj<>endobj +1102 0 obj<>endobj +1103 0 obj<>endobj +1104 0 obj<>endobj +1105 0 obj<>endobj +1106 0 obj<>endobj +1107 0 obj<>endobj +1108 0 obj<>endobj +1109 0 obj<>endobj +1110 0 obj<>endobj +1111 0 obj<>endobj +1112 0 obj<>endobj +1113 0 obj<>endobj +1114 0 obj<>endobj +1115 0 obj<>endobj +1116 0 obj<>endobj +1117 0 obj<>endobj +1118 0 obj<>endobj +1119 0 obj[1065 0 R +1066 0 R +1067 0 R +1068 0 R +1069 0 R +1070 0 R +1071 0 R +1072 0 R +1073 0 R +1074 0 R +1075 0 R +1076 0 R +1077 0 R +1078 0 R +1079 0 R +1080 0 R +1081 0 R +1082 0 R +1083 0 R +1084 0 R +1085 0 R +1086 0 R +1087 0 R +1088 0 R +1089 0 R +1090 0 R +1091 0 R +1092 0 R +1093 0 R +1094 0 R +1095 0 R +1096 0 R +1097 0 R +1098 0 R +1099 0 R +1100 0 R +1101 0 R +1102 0 R +1103 0 R +1104 0 R +1105 0 R +1106 0 R +1107 0 R +1108 0 R +1109 0 R +1110 0 R +1111 0 R +1112 0 R +1113 0 R +1114 0 R +1115 0 R +1116 0 R +1117 0 R +1118 0 R +]endobj +1120 0 obj<>endobj +1121 0 obj<>endobj +1122 0 obj<>endobj +1123 0 obj<>endobj +1124 0 obj<>endobj +1125 0 obj<>endobj +1126 0 obj<>endobj +1127 0 obj<>endobj +1128 0 obj<>endobj +1129 0 obj<>endobj +1130 0 obj<>endobj +1131 0 obj<>endobj +1132 0 obj<>endobj +1133 0 obj<>endobj +1134 0 obj<>endobj +1135 0 obj<>endobj +1136 0 obj<>endobj +1137 0 obj<>endobj +1138 0 obj<>endobj +1139 0 obj<>endobj +1140 0 obj<>endobj +1141 0 obj<>endobj +1142 0 obj<>endobj +1143 0 obj<>endobj +1144 0 obj<>endobj +1145 0 obj<>endobj +1146 0 obj<>endobj +1147 0 obj<>endobj +1148 0 obj<>endobj +1149 0 obj<>endobj +1150 0 obj<>endobj +1151 0 obj<>endobj +1152 0 obj<>endobj +1153 0 obj<>endobj +1154 0 obj<>endobj +1155 0 obj<>endobj +1156 0 obj<>endobj +1157 0 obj<>endobj +1158 0 obj<>endobj +1159 0 obj<>endobj +1160 0 obj<>endobj +1161 0 obj<>endobj +1162 0 obj<>endobj +1163 0 obj<>endobj +1164 0 obj<>endobj +1165 0 obj<>endobj +1166 0 obj<>endobj +1167 0 obj<>endobj +1168 0 obj<>endobj +1169 0 obj<>endobj +1170 0 obj<>endobj +1171 0 obj<>endobj +1172 0 obj<>endobj +1173 0 obj<>endobj +1174 0 obj[1120 0 R +1121 0 R +1122 0 R +1123 0 R +1124 0 R +1125 0 R +1126 0 R +1127 0 R +1128 0 R +1129 0 R +1130 0 R +1131 0 R +1132 0 R +1133 0 R +1134 0 R +1135 0 R +1136 0 R +1137 0 R +1138 0 R +1139 0 R +1140 0 R +1141 0 R +1142 0 R +1143 0 R +1144 0 R +1145 0 R +1146 0 R +1147 0 R +1148 0 R +1149 0 R +1150 0 R +1151 0 R +1152 0 R +1153 0 R +1154 0 R +1155 0 R +1156 0 R +1157 0 R +1158 0 R +1159 0 R +1160 0 R +1161 0 R +1162 0 R +1163 0 R +1164 0 R +1165 0 R +1166 0 R +1167 0 R +1168 0 R +1169 0 R +1170 0 R +1171 0 R +1172 0 R +1173 0 R +]endobj +1175 0 obj<>endobj +1176 0 obj<>endobj +1177 0 obj<>endobj +1178 0 obj<>endobj +1179 0 obj<>endobj +1180 0 obj<>endobj +1181 0 obj<>endobj +1182 0 obj<>endobj +1183 0 obj<>endobj +1184 0 obj<>endobj +1185 0 obj<>endobj +1186 0 obj<>endobj +1187 0 obj<>endobj +1188 0 obj<>endobj +1189 0 obj<>endobj +1190 0 obj<>endobj +1191 0 obj<>endobj +1192 0 obj<>endobj +1193 0 obj<>endobj +1194 0 obj<>endobj +1195 0 obj<>endobj +1196 0 obj<>endobj +1197 0 obj<>endobj +1198 0 obj<>endobj +1199 0 obj<>endobj +1200 0 obj<>endobj +1201 0 obj<>endobj +1202 0 obj<>endobj +1203 0 obj<>endobj +1204 0 obj<>endobj +1205 0 obj<>endobj +1206 0 obj<>endobj +1207 0 obj<>endobj +1208 0 obj<>endobj +1209 0 obj<>endobj +1210 0 obj<>endobj +1211 0 obj<>endobj +1212 0 obj<>endobj +1213 0 obj<>endobj +1214 0 obj<>endobj +1215 0 obj<>endobj +1216 0 obj<>endobj +1217 0 obj<>endobj +1218 0 obj<>endobj +1219 0 obj<>endobj +1220 0 obj<>endobj +1221 0 obj<>endobj +1222 0 obj<>endobj +1223 0 obj<>endobj +1224 0 obj<>endobj +1225 0 obj<>endobj +1226 0 obj<>endobj +1227 0 obj<>endobj +1228 0 obj[1175 0 R +1176 0 R +1177 0 R +1178 0 R +1179 0 R +1180 0 R +1181 0 R +1182 0 R +1183 0 R +1184 0 R +1185 0 R +1186 0 R +1187 0 R +1188 0 R +1189 0 R +1190 0 R +1191 0 R +1192 0 R +1193 0 R +1194 0 R +1195 0 R +1196 0 R +1197 0 R +1198 0 R +1199 0 R +1200 0 R +1201 0 R +1202 0 R +1203 0 R +1204 0 R +1205 0 R +1206 0 R +1207 0 R +1208 0 R +1209 0 R +1210 0 R +1211 0 R +1212 0 R +1213 0 R +1214 0 R +1215 0 R +1216 0 R +1217 0 R +1218 0 R +1219 0 R +1220 0 R +1221 0 R +1222 0 R +1223 0 R +1224 0 R +1225 0 R +1226 0 R +1227 0 R +]endobj +1229 0 obj<>endobj +1230 0 obj<>endobj +1231 0 obj<>endobj +1232 0 obj<>endobj +1233 0 obj<>endobj +1234 0 obj<>endobj +1235 0 obj<>endobj +1236 0 obj<>endobj +1237 0 obj<>endobj +1238 0 obj<>endobj +1239 0 obj<>endobj +1240 0 obj<>endobj +1241 0 obj<>endobj +1242 0 obj<>endobj +1243 0 obj<>endobj +1244 0 obj<>endobj +1245 0 obj<>endobj +1246 0 obj<>endobj +1247 0 obj<>endobj +1248 0 obj<>endobj +1249 0 obj<>endobj +1250 0 obj<>endobj +1251 0 obj<>endobj +1252 0 obj<>endobj +1253 0 obj<>endobj +1254 0 obj<>endobj +1255 0 obj<>endobj +1256 0 obj<>endobj +1257 0 obj<>endobj +1258 0 obj<>endobj +1259 0 obj<>endobj +1260 0 obj<>endobj +1261 0 obj<>endobj +1262 0 obj<>endobj +1263 0 obj<>endobj +1264 0 obj<>endobj +1265 0 obj<>endobj +1266 0 obj<>endobj +1267 0 obj<>endobj +1268 0 obj<>endobj +1269 0 obj<>endobj +1270 0 obj<>endobj +1271 0 obj[1229 0 R +1230 0 R +1231 0 R +1232 0 R +1233 0 R +1234 0 R +1235 0 R +1236 0 R +1237 0 R +1238 0 R +1239 0 R +1240 0 R +1241 0 R +1242 0 R +1243 0 R +1244 0 R +1245 0 R +1246 0 R +1247 0 R +1248 0 R +1249 0 R +1250 0 R +1251 0 R +1252 0 R +1253 0 R +1254 0 R +1255 0 R +1256 0 R +1257 0 R +1258 0 R +1259 0 R +1260 0 R +1261 0 R +1262 0 R +1263 0 R +1264 0 R +1265 0 R +1266 0 R +1267 0 R +1268 0 R +1269 0 R +1270 0 R +]endobj +1272 0 obj<>endobj +1273 0 obj<>endobj +1274 0 obj<>endobj +1275 0 obj<>endobj +1276 0 obj<>endobj +1277 0 obj<>endobj +1278 0 obj<>endobj +1279 0 obj<>endobj +1280 0 obj<>endobj +1281 0 obj<>endobj +1282 0 obj<>endobj +1283 0 obj<>endobj +1284 0 obj<>endobj +1285 0 obj<>endobj +1286 0 obj<>endobj +1287 0 obj<>endobj +1288 0 obj<>endobj +1289 0 obj<>endobj +1290 0 obj<>endobj +1291 0 obj<>endobj +1292 0 obj<>endobj +1293 0 obj<>endobj +1294 0 obj<>endobj +1295 0 obj<>endobj +1296 0 obj<>endobj +1297 0 obj<>endobj +1298 0 obj<>endobj +1299 0 obj<>endobj +1300 0 obj<>endobj +1301 0 obj<>endobj +1302 0 obj<>endobj +1303 0 obj<>endobj +1304 0 obj<>endobj +1305 0 obj<>endobj +1306 0 obj<>endobj +1307 0 obj<>endobj +1308 0 obj<>endobj +1309 0 obj<>endobj +1310 0 obj<>endobj +1311 0 obj<>endobj +1312 0 obj<>endobj +1313 0 obj<>endobj +1314 0 obj<>endobj +1315 0 obj<>endobj +1316 0 obj<>endobj +1317 0 obj<>endobj +1318 0 obj<>endobj +1319 0 obj<>endobj +1320 0 obj<>endobj +1321 0 obj<>endobj +1322 0 obj<>endobj +1323 0 obj<>endobj +1324 0 obj<>endobj +1325 0 obj<>endobj +1326 0 obj<>endobj +1327 0 obj<>endobj +1328 0 obj<>endobj +1329 0 obj<>endobj +1330 0 obj<>endobj +1331 0 obj<>endobj +1332 0 obj<>endobj +1333 0 obj<>endobj +1334 0 obj<>endobj +1335 0 obj<>endobj +1336 0 obj<>endobj +1337 0 obj<>endobj +1338 0 obj<>endobj +1339 0 obj<>endobj +1340 0 obj<>endobj +1341 0 obj<>endobj +1342 0 obj<>endobj +1343 0 obj<>endobj +1344 0 obj<>endobj +1345 0 obj<>endobj +1346 0 obj<>endobj +1347 0 obj<>endobj +1348 0 obj<>endobj +1349 0 obj<>endobj +1350 0 obj<>endobj +1351 0 obj<>endobj +1352 0 obj<>endobj +1353 0 obj<>endobj +1354 0 obj<>endobj +1355 0 obj<>endobj +1356 0 obj<>endobj +1357 0 obj<>endobj +1358 0 obj<>endobj +1359 0 obj<>endobj +1360 0 obj<>endobj +1361 0 obj<>endobj +1362 0 obj<>endobj +1363 0 obj<>endobj +1364 0 obj<>endobj +1365 0 obj<>endobj +1366 0 obj<>endobj +1367 0 obj<>endobj +1368 0 obj<>endobj +1369 0 obj<>endobj +1370 0 obj<>endobj +1371 0 obj<>endobj +1372 0 obj<>endobj +1373 0 obj<>endobj +1374 0 obj<>endobj +1375 0 obj<>endobj +1376 0 obj<>endobj +1377 0 obj<>endobj +1378 0 obj<>endobj +1379 0 obj<>endobj +1380 0 obj<>endobj +1381 0 obj<>endobj +1382 0 obj<>endobj +1383 0 obj<>endobj +1384 0 obj<>endobj +1385 0 obj<>endobj +1386 0 obj<>endobj +1387 0 obj<>endobj +1388 0 obj<>endobj +1389 0 obj<>endobj +1390 0 obj<>endobj +1391 0 obj<>endobj +1392 0 obj<>endobj +1393 0 obj<>endobj +1394 0 obj<>endobj +1395 0 obj<>endobj +1396 0 obj<>endobj +1397 0 obj<>endobj +1398 0 obj<>endobj +1399 0 obj<>endobj +1400 0 obj<>endobj +1401 0 obj<>endobj +1402 0 obj<>endobj +1403 0 obj<>endobj +1404 0 obj<>endobj +1405 0 obj<>endobj +1406 0 obj<>endobj +1407 0 obj<>endobj +1408 0 obj<>endobj +1409 0 obj<>endobj +1410 0 obj<>endobj +1411 0 obj<>endobj +1412 0 obj<>endobj +1413 0 obj<>endobj +1414 0 obj<>endobj +1415 0 obj<>endobj +1416 0 obj<>endobj +1417 0 obj<>endobj +1418 0 obj<>endobj +1419 0 obj<>endobj +1420 0 obj<>endobj +1421 0 obj<>endobj +1422 0 obj<>endobj +1423 0 obj<>endobj +1424 0 obj<>endobj +1425 0 obj<>endobj +1426 0 obj<>endobj +1427 0 obj<>endobj +1428 0 obj<>endobj +1429 0 obj<>endobj +1430 0 obj<>endobj +1431 0 obj<>endobj +1432 0 obj<>endobj +1433 0 obj<>endobj +1434 0 obj<>endobj +1435 0 obj<>endobj +1436 0 obj<>endobj +1437 0 obj<>endobj +1438 0 obj<>endobj +1439 0 obj<>endobj +1440 0 obj<>endobj +1441 0 obj<>endobj +1442 0 obj<>endobj +1443 0 obj<>endobj +1444 0 obj<>endobj +1445 0 obj<>endobj +1446 0 obj<>endobj +1447 0 obj<>endobj +1448 0 obj<>endobj +1449 0 obj<>endobj +1450 0 obj<>endobj +1451 0 obj<>endobj +1452 0 obj<>endobj +1453 0 obj<>endobj +1454 0 obj<>endobj +1455 0 obj<>endobj +1456 0 obj<>endobj +1457 0 obj<>endobj +1458 0 obj<>endobj +1459 0 obj<>endobj +1460 0 obj<>endobj +1461 0 obj<>endobj +1462 0 obj<>endobj +1463 0 obj<>endobj +1464 0 obj<>endobj +1465 0 obj<>endobj +1466 0 obj<>endobj +1467 0 obj<>endobj +1468 0 obj<>endobj +1469 0 obj<>endobj +1470 0 obj<>endobj +1471 0 obj<>endobj +1472 0 obj<>endobj +1473 0 obj<>endobj +1474 0 obj<>endobj +1475 0 obj<>endobj +1476 0 obj<>endobj +1477 0 obj<>endobj +1478 0 obj<>endobj +1479 0 obj<>endobj +1480 0 obj<>endobj +1481 0 obj<>endobj +1482 0 obj<>endobj +1483 0 obj<>endobj +1484 0 obj<>endobj +1485 0 obj<>endobj +1486 0 obj<>endobj +1487 0 obj<>endobj +1488 0 obj<>endobj +1489 0 obj<>endobj +1490 0 obj<>endobj +1491 0 obj<>endobj +1492 0 obj<>endobj +1493 0 obj<>endobj +1494 0 obj<>endobj +1495 0 obj<>endobj +1496 0 obj<>endobj +1497 0 obj<>endobj +1498 0 obj<>endobj +1499 0 obj<>endobj +1500 0 obj<>endobj +1501 0 obj<>endobj +1502 0 obj<>endobj +1503 0 obj<>endobj +1504 0 obj<>endobj +1505 0 obj<>endobj +1506 0 obj<>endobj +1507 0 obj<>endobj +1508 0 obj<>endobj +1509 0 obj<>endobj +1510 0 obj<>endobj +1511 0 obj<>endobj +1512 0 obj<>endobj +1513 0 obj<>endobj +1514 0 obj<>endobj +1515 0 obj<>endobj +1516 0 obj<>endobj +1517 0 obj<>endobj +1518 0 obj<>endobj +1519 0 obj<>endobj +1520 0 obj<>endobj +1521 0 obj<>endobj +1522 0 obj<>endobj +1523 0 obj<>endobj +1524 0 obj<>endobj +1525 0 obj<>endobj +1526 0 obj<>endobj +1527 0 obj<>endobj +1528 0 obj<>endobj +1529 0 obj<>endobj +1530 0 obj<>endobj +1531 0 obj<>endobj +1532 0 obj<>endobj +1533 0 obj<>endobj +1534 0 obj<>endobj +1535 0 obj<>endobj +1536 0 obj<>endobj +1537 0 obj<>endobj +1538 0 obj<>endobj +1539 0 obj<>endobj +1540 0 obj<>endobj +1541 0 obj<>endobj +1542 0 obj<>endobj +1543 0 obj<>endobj +1544 0 obj<>endobj +1545 0 obj<>endobj +1546 0 obj<>endobj +1547 0 obj<>endobj +1548 0 obj<>endobj +1549 0 obj<>endobj +1550 0 obj<>endobj +1551 0 obj<>endobj +1552 0 obj<>endobj +1553 0 obj<>endobj +1554 0 obj<>endobj +1555 0 obj<>endobj +1556 0 obj<>endobj +1557 0 obj<>endobj +1558 0 obj<>endobj +1559 0 obj<>endobj +1560 0 obj<>endobj +1561 0 obj<>endobj +1562 0 obj<>endobj +1563 0 obj<>endobj +1564 0 obj<>endobj +1565 0 obj<>endobj +1566 0 obj<>endobj +1567 0 obj<>endobj +1568 0 obj<>endobj +1569 0 obj<>endobj +1570 0 obj<>endobj +1571 0 obj<>endobj +1572 0 obj<>endobj +1573 0 obj<>endobj +1574 0 obj<>endobj +1575 0 obj<>endobj +1576 0 obj<>endobj +1577 0 obj<>endobj +1578 0 obj<>endobj +1579 0 obj<>endobj +1580 0 obj<>endobj +1581 0 obj<>endobj +1582 0 obj<>endobj +1583 0 obj<>endobj +1584 0 obj<>endobj +1585 0 obj<>endobj +1586 0 obj<>endobj +1587 0 obj<>endobj +1588 0 obj<>endobj +1589 0 obj<>endobj +1590 0 obj<>endobj +1591 0 obj<>endobj +1592 0 obj<>endobj +1593 0 obj<>endobj +1594 0 obj<>endobj +1595 0 obj<>endobj +1596 0 obj<>endobj +1597 0 obj<>endobj +1598 0 obj<>endobj +1599 0 obj<>endobj +1600 0 obj<>endobj +1601 0 obj<>endobj +1602 0 obj<>endobj +1603 0 obj<>endobj +1604 0 obj<>endobj +1605 0 obj<>endobj +1606 0 obj<>endobj +1607 0 obj<>endobj +1608 0 obj<>endobj +1609 0 obj<>endobj +1610 0 obj<>endobj +1611 0 obj<>endobj +1612 0 obj<>endobj +1613 0 obj<>endobj +1614 0 obj<>endobj +1615 0 obj<>endobj +1616 0 obj<>endobj +1617 0 obj<>endobj +1618 0 obj<>endobj +1619 0 obj<>endobj +1620 0 obj<>endobj +1621 0 obj<>endobj +1622 0 obj<>endobj +1623 0 obj<>endobj +1624 0 obj<>endobj +1625 0 obj<>endobj +1626 0 obj<>endobj +1627 0 obj<>endobj +1628 0 obj<>endobj +1629 0 obj<>endobj +1630 0 obj<>endobj +1631 0 obj<>endobj +1632 0 obj<>endobj +1633 0 obj<>endobj +1634 0 obj<>endobj +1635 0 obj<>endobj +1636 0 obj<>endobj +1637 0 obj<>endobj +1638 0 obj<>endobj +1639 0 obj<>endobj +1640 0 obj<>endobj +1641 0 obj<>endobj +1642 0 obj<>endobj +1643 0 obj<>endobj +1644 0 obj<>endobj +1645 0 obj<>endobj +1646 0 obj<>endobj +1647 0 obj<>endobj +1648 0 obj<>endobj +1649 0 obj<>endobj +1650 0 obj<>endobj +1651 0 obj<>endobj +1652 0 obj<>endobj +1653 0 obj<>endobj +1654 0 obj<>endobj +1655 0 obj<>endobj +1656 0 obj<>endobj +1657 0 obj<>endobj +1658 0 obj<>endobj +1659 0 obj<>endobj +1660 0 obj<>endobj +1661 0 obj<>endobj +1662 0 obj<>endobj +1663 0 obj<>endobj +1664 0 obj<>endobj +1665 0 obj<>endobj +1666 0 obj<>endobj +1667 0 obj<>endobj +1668 0 obj<>endobj +1669 0 obj<>endobj +1670 0 obj<>endobj +1671 0 obj<>endobj +1672 0 obj<>endobj +1673 0 obj<>endobj +1674 0 obj<>endobj +1675 0 obj<>endobj +1676 0 obj<>endobj +1677 0 obj<>endobj +1678 0 obj<>endobj +1679 0 obj<>endobj +1680 0 obj<>endobj +1681 0 obj<>endobj +1682 0 obj<>endobj +1683 0 obj<>endobj +1684 0 obj<>endobj +1685 0 obj<>endobj +1686 0 obj<>endobj +1687 0 obj<>endobj +1688 0 obj<>endobj +1689 0 obj<>endobj +1690 0 obj<>endobj +1691 0 obj<>endobj +1692 0 obj<>endobj +1693 0 obj<>endobj +1694 0 obj<>endobj +1695 0 obj<>endobj +1696 0 obj<>endobj +1697 0 obj<>endobj +1698 0 obj<>endobj +1699 0 obj<>endobj +1700 0 obj<>endobj +1701 0 obj<>endobj +1702 0 obj<>endobj +1703 0 obj<>endobj +1704 0 obj<>endobj +1705 0 obj<>endobj +1706 0 obj<>endobj +1707 0 obj<>endobj +1708 0 obj<>endobj +1709 0 obj<>endobj +1710 0 obj<>endobj +1711 0 obj<>endobj +1712 0 obj<>endobj +1713 0 obj<>endobj +1714 0 obj<>endobj +1715 0 obj<>endobj +1716 0 obj<>endobj +1717 0 obj<>endobj +1718 0 obj<>endobj +1719 0 obj<>endobj +1720 0 obj<>endobj +1721 0 obj<>endobj +1722 0 obj<>endobj +1723 0 obj<>endobj +1724 0 obj<>endobj +1725 0 obj<>endobj +1726 0 obj<>endobj +1727 0 obj<>endobj +1728 0 obj<>endobj +1729 0 obj<>endobj +1730 0 obj<>endobj +1731 0 obj<>endobj +1732 0 obj<>endobj +1733 0 obj<>endobj +1734 0 obj<>endobj +1735 0 obj<>endobj +1736 0 obj<>endobj +1737 0 obj<>endobj +1738 0 obj<>endobj +1739 0 obj<>endobj +1740 0 obj<>endobj +1741 0 obj<>endobj +1742 0 obj<>endobj +1743 0 obj<>endobj +1744 0 obj<>endobj +1745 0 obj<>endobj +1746 0 obj<>endobj +1747 0 obj<>endobj +1748 0 obj<>endobj +1749 0 obj<>endobj +1750 0 obj<>endobj +1751 0 obj<>endobj +1752 0 obj<>endobj +1753 0 obj<>endobj +1754 0 obj<>endobj +1755 0 obj<>endobj +1756 0 obj<>endobj +1757 0 obj<>endobj +1758 0 obj<>endobj +1759 0 obj<>endobj +1760 0 obj<>endobj +1761 0 obj<>endobj +1762 0 obj<>endobj +1763 0 obj<>endobj +1764 0 obj<>endobj +1765 0 obj<>endobj +1766 0 obj<>endobj +1767 0 obj<>endobj +1768 0 obj<>endobj +1769 0 obj<>endobj +1770 0 obj<>endobj +1771 0 obj<>endobj +1772 0 obj<>endobj +1773 0 obj<>endobj +1774 0 obj<>endobj +1775 0 obj<>endobj +1776 0 obj<>endobj +1777 0 obj<>endobj +1778 0 obj<>endobj +1779 0 obj<>endobj +1780 0 obj<>endobj +1781 0 obj<>endobj +1782 0 obj<>endobj +1783 0 obj<>endobj +1784 0 obj<>endobj +1785 0 obj<>endobj +1786 0 obj<>endobj +1787 0 obj<>endobj +1788 0 obj<>endobj +1789 0 obj<>endobj +1790 0 obj<>endobj +1791 0 obj<>endobj +1792 0 obj<>endobj +1793 0 obj<>endobj +1794 0 obj<>endobj +1795 0 obj<>endobj +1796 0 obj<>endobj +1797 0 obj<>endobj +1798 0 obj<>endobj +1799 0 obj<>endobj +1800 0 obj<>endobj +1801 0 obj<>endobj +1802 0 obj<>endobj +1803 0 obj<>endobj +1804 0 obj<>endobj +1805 0 obj<>endobj +1806 0 obj<>endobj +1807 0 obj<>endobj +1808 0 obj<>endobj +1809 0 obj<>endobj +1810 0 obj<>endobj +1811 0 obj<>endobj +1812 0 obj<>endobj +1813 0 obj<>endobj +1814 0 obj<>endobj +1815 0 obj<>endobj +1816 0 obj<>endobj +1817 0 obj<>endobj +1818 0 obj<>endobj +1819 0 obj<>endobj +1820 0 obj<>endobj +1821 0 obj<>endobj +1822 0 obj<>endobj +1823 0 obj<>endobj +1824 0 obj<>endobj +1825 0 obj<>endobj +1826 0 obj<>endobj +1827 0 obj<>endobj +1828 0 obj<>endobj +1829 0 obj<>endobj +1830 0 obj<>endobj +1831 0 obj<>endobj +1832 0 obj<>endobj +1833 0 obj<>endobj +1834 0 obj<>endobj +1835 0 obj<>endobj +1836 0 obj<>endobj +1837 0 obj<>endobj +1838 0 obj<>endobj +1839 0 obj<>endobj +1840 0 obj<>endobj +1841 0 obj<>endobj +1842 0 obj<>endobj +1843 0 obj<>endobj +1844 0 obj<>endobj +1845 0 obj<>endobj +1846 0 obj<>endobj +1847 0 obj<>endobj +1848 0 obj<>endobj +1849 0 obj<>endobj +1850 0 obj<>endobj +1851 0 obj<>endobj +1852 0 obj<>endobj +1853 0 obj<>endobj +1854 0 obj<>endobj +1855 0 obj<>endobj +1856 0 obj<>endobj +1857 0 obj<>endobj +1858 0 obj<>endobj +1859 0 obj<>endobj +1860 0 obj<>endobj +1861 0 obj<>endobj +1862 0 obj<>endobj +1863 0 obj<>endobj +1864 0 obj<>endobj +1865 0 obj<>endobj +1866 0 obj<>endobj +1867 0 obj<>endobj +1868 0 obj<>endobj +1869 0 obj<>endobj +1870 0 obj<>endobj +1871 0 obj<>endobj +1872 0 obj<>endobj +1873 0 obj<>endobj +1874 0 obj<>endobj +1875 0 obj<>endobj +1876 0 obj<>endobj +1877 0 obj<>endobj +1878 0 obj<>endobj +1879 0 obj<>endobj +1880 0 obj<>endobj +1881 0 obj<>endobj +1882 0 obj<>endobj +1883 0 obj<>endobj +1884 0 obj<>endobj +1885 0 obj<>endobj +1886 0 obj<>endobj +1887 0 obj<>endobj +1888 0 obj<>endobj +1889 0 obj<>endobj +1890 0 obj<>endobj +1891 0 obj<>endobj +1892 0 obj<>endobj +1893 0 obj<>endobj +1894 0 obj<>endobj +1895 0 obj<>endobj +1896 0 obj<>endobj +1897 0 obj<>endobj +1898 0 obj<>endobj +1899 0 obj<>endobj +1900 0 obj<>endobj +1901 0 obj<>endobj +1902 0 obj<>endobj +1903 0 obj<>endobj +1904 0 obj<>endobj +1905 0 obj<>endobj +1906 0 obj<>endobj +1907 0 obj<>endobj +1908 0 obj<>endobj +1909 0 obj<>endobj +1910 0 obj<>endobj +1911 0 obj<>endobj +1912 0 obj<>endobj +1913 0 obj<>endobj +1914 0 obj<>endobj +1915 0 obj<>endobj +1916 0 obj<>endobj +1917 0 obj<>endobj +1918 0 obj<>endobj +1919 0 obj<>endobj +1920 0 obj<>endobj +1921 0 obj<>endobj +1922 0 obj<>endobj +1923 0 obj<>endobj +1924 0 obj<>endobj +1925 0 obj<>endobj +1926 0 obj<>endobj +1927 0 obj<>endobj +1928 0 obj<>endobj +1929 0 obj<>endobj +1930 0 obj<>endobj +1931 0 obj<>endobj +1932 0 obj<>endobj +1933 0 obj<>endobj +1934 0 obj<>endobj +1935 0 obj<>endobj +1936 0 obj<>endobj +1937 0 obj<>endobj +1938 0 obj<>endobj +1939 0 obj<>endobj +1940 0 obj<>endobj +1941 0 obj<>endobj +1942 0 obj<>endobj +1943 0 obj<>endobj +1944 0 obj<>endobj +1945 0 obj<>endobj +1946 0 obj<>endobj +1947 0 obj<>endobj +1948 0 obj<>endobj +1949 0 obj<>endobj +1950 0 obj<>endobj +1951 0 obj<>endobj +1952 0 obj<>endobj +1953 0 obj<>endobj +1954 0 obj<>endobj +1955 0 obj<>endobj +1956 0 obj<>endobj +1957 0 obj<>endobj +1958 0 obj<>endobj +1959 0 obj<>endobj +1960 0 obj<>endobj +1961 0 obj<>endobj +1962 0 obj<>endobj +1963 0 obj<>endobj +1964 0 obj<>endobj +1965 0 obj<>endobj +1966 0 obj<>endobj +1967 0 obj<>endobj +1968 0 obj<>endobj +1969 0 obj<>endobj +1970 0 obj<>endobj +1971 0 obj<>endobj +1972 0 obj<>endobj +1973 0 obj<>endobj +1974 0 obj<>endobj +1975 0 obj<>endobj +1976 0 obj<>endobj +1977 0 obj<>endobj +1978 0 obj<>endobj +1979 0 obj<>endobj +1980 0 obj<>endobj +1981 0 obj<>endobj +1982 0 obj<>endobj +1983 0 obj<>endobj +1984 0 obj<>endobj +1985 0 obj<>endobj +1986 0 obj<>endobj +1987 0 obj<>endobj +1988 0 obj<>endobj +1989 0 obj<>endobj +1990 0 obj<>endobj +1991 0 obj<>endobj +1992 0 obj<>endobj +1993 0 obj<>endobj +1994 0 obj<>endobj +1995 0 obj<>endobj +1996 0 obj<>endobj +1997 0 obj<>endobj +1998 0 obj<>endobj +1999 0 obj<>endobj +2000 0 obj<>endobj +2001 0 obj<>endobj +2002 0 obj<>endobj +2003 0 obj<>endobj +2004 0 obj<>endobj +2005 0 obj<>endobj +2006 0 obj<>endobj +2007 0 obj<>endobj +2008 0 obj<>endobj +2009 0 obj<>endobj +2010 0 obj<>endobj +2011 0 obj<>endobj +2012 0 obj<>endobj +2013 0 obj<>endobj +2014 0 obj<>endobj +2015 0 obj<>endobj +2016 0 obj<>endobj +2017 0 obj<>endobj +2018 0 obj<>endobj +2019 0 obj<>endobj +2020 0 obj<>endobj +2021 0 obj<>endobj +2022 0 obj<>endobj +2023 0 obj<>endobj +2024 0 obj<>endobj +2025 0 obj<>endobj +2026 0 obj<>endobj +2027 0 obj<>endobj +2028 0 obj<>endobj +2029 0 obj<>endobj +2030 0 obj<>endobj +2031 0 obj<>endobj +2032 0 obj<>endobj +2033 0 obj<>endobj +2034 0 obj<>endobj +2035 0 obj<>endobj +2036 0 obj<>endobj +2037 0 obj<>endobj +2038 0 obj<>endobj +2039 0 obj<>endobj +2040 0 obj<>endobj +2041 0 obj<>endobj +2042 0 obj<>endobj +2043 0 obj<>endobj +2044 0 obj<>endobj +2045 0 obj<>endobj +2046 0 obj<>endobj +2047 0 obj<>endobj +2048 0 obj<>endobj +2049 0 obj<>endobj +2050 0 obj<>endobj +2051 0 obj<>endobj +2052 0 obj<>endobj +2053 0 obj<>endobj +2054 0 obj<>endobj +2055 0 obj<>endobj +2056 0 obj<>endobj +2057 0 obj<>endobj +2058 0 obj<>endobj +2059 0 obj<>endobj +2060 0 obj<>endobj +2061 0 obj<>endobj +2062 0 obj<>endobj +2063 0 obj<>endobj +2064 0 obj<>endobj +2065 0 obj<>endobj +2066 0 obj<>endobj +2067 0 obj<>endobj +2068 0 obj<>endobj +2069 0 obj<>endobj +2070 0 obj<>endobj +2071 0 obj<>endobj +2072 0 obj<>endobj +2073 0 obj<>endobj +2074 0 obj<>endobj +2075 0 obj<>endobj +2076 0 obj<>endobj +2077 0 obj<>endobj +2078 0 obj<>endobj +2079 0 obj<>endobj +2080 0 obj<>endobj +2081 0 obj<>endobj +2082 0 obj<>endobj +2083 0 obj<>endobj +2084 0 obj<>endobj +2085 0 obj<>endobj +2086 0 obj<>endobj +2087 0 obj<>endobj +2088 0 obj<>endobj +2089 0 obj<>endobj +2090 0 obj<>endobj +2091 0 obj<>endobj +2092 0 obj<>endobj +2093 0 obj<>endobj +2094 0 obj<>endobj +2095 0 obj<>endobj +2096 0 obj<>endobj +2097 0 obj<>endobj +2098 0 obj<>endobj +2099 0 obj<>endobj +2100 0 obj<>endobj +2101 0 obj<>endobj +2102 0 obj<>endobj +2103 0 obj<>endobj +2104 0 obj<>endobj +2105 0 obj<>endobj +2106 0 obj<>>>>>endobj +2107 0 obj<>stream +xÚUËnÂ0E÷þŠ»,6™8Jð(ìÒÄýCÌK )vÒ*_6­F:‹™{Ï<! C(RÈǎ­5[ìÒú(2È" ÔÍÛ{µÚipl>Ëu~Œ³(]v¦ë¬ó؛ûhڙ¾G¢è B‰%8I‘FI,óºÜsɁb”«páiþz²5~ú'oÆãàŸ¹LŠü¨ÿšÜõ|@J<@ͱj[TqéQYoÝ·mbu«Ùû^2@endstream +endobj +2108 0 obj +187 +endobj +2109 0 obj<>>>endobj +2110 0 obj<>stream +xÚ+ä2T0BCc3JÎår +ár á +äHÉHendstream +endobj +2111 0 obj +31 +endobj +2112 0 obj<>>>>>endobj +2113 0 obj<>stream +xÚmTMsÚ0½ó+vr‚™àÚàòq,ùf’Ö $Óa¯A‰,9’ C}wm'$”á‚V»zïíÛõ['‚~Œ0AZtfËηÛ) BXæGq0†Ñ8†eÖM,æ"ÅÞò…2bˆ"Îè7)ýá` 8k¹•œÉý^X„ÒšEÖA!t%‡v2Ã3IRo@êÜØBxi4Ð?ð[„+St|ú9ÿÃà!ô£a–X©=—-Îc«îÅÕS²¸Xõà™ ù‘(ƒ†ò¢1S¦ú8 &\ߖýÚ¡ÝIÜ•FyƒQ7¢¾°€SÜMJc½X+VÕæ(q@[‹áÚÕàûL‰Vԗ®~À0÷°îDßQC†;TT‘Áú7Â`ñ޹̬J½o˜Ca<ç…΄͎œQÕGK…RŠê̐1”}‚[9ê^ÜË£6¶¢ÕûÌ50CûŠ +Rk(ÐWR#9èÑò ¸ }õ½‹õsôtóԜó4úc3I7©Qdãüfy۟' )šôµp4X̟ Ä†ókyðbÖµx«°"P ³NäÜ3¯†Œ¸È>®º÷Éõ%<Þ^EÑxºê]‚†€îÐ9±A˜)“¾RÚâaÆ·Œð£,$ÎeK•É¡œ9tUɓ@¦í¥ß‚Eò‰y¥S6B(égû#²Ìµeoìk£8­­Ù;–Ì,ãü"µ²ôGMèꀬ…]$É5­@ŸZ†Ÿ†ÀÔ÷<+ç¹IZOÂUˆ²T2MA¥3l†÷ß,;¿;ÿø±'endstream +endobj +2114 0 obj +693 +endobj +2115 0 obj<>>>>>endobj +2116 0 obj<>stream +xڕ’?OÃ0Å÷|ŠːP'%IÙú‡H ˆ@\±°XŽÛ[ØN+øôœ›V-H"{°r÷{÷b¿¯€À$õ›·Áœ·ÅHt•4Ë¢h=ZjÞµB9xÞ ³“bC?°s„ôaœFßI·Ò‚Õk·gF«[©¤u†9m,´Lu¬ìÐfÔü5Hå4¸­€µn½—jVp'µ²÷ý~œçQ|ô§üµ1"BiPÑ«Tß։öŸc~vL”»"„s€¢§Åª¬`V>‚„ߌ<˜(dㄱƒøÉøa`iän¨Î݅ΜñO¡êa3Xà;8¦Ü0rŽdåLÇ]gÄ0thÑ©>}-?Ö¦Y„Çü”É×YA½CÿFÕ)q¥ÑÃÚ/ žqó!‰S³xìÁØIòÆW£ý@ƒ—à=×ãendstream +endobj +2117 0 obj +331 +endobj +2118 0 obj<>>>>>endobj +2119 0 obj<>stream +xڝUMÛ6½ûWÌqð*þŠw÷Ø ÚC².֛ô°ZÙìR¤JRrüïû†’?"-P0,™3ï͛7ÿGSšà3¥û͗”W£ëÑ»O4›ÐºÄ÷2›Óò~AëâfJw´òÚFm·ô|‘+zjÙ·š÷·ë¿¶ éTÂ»ùì>›Ièz§å;UGöT{×ê‚)K®'WÒÎí)î˜>ºªr–^¾üþçÞÞù·uh4½´ Ý-&ÙC‡Ã琕wÃՏÔpx¶ÌR=Ÿœ§+¨;²ìÜ‰ú˜¥þY–Ú©@µQۆ‹Äôuö~™Ñ‹5úé³Î½ ®Œò–¾i[¸}H¿ùYåOÏã®>>>>>endobj +2122 0 obj<>stream +xڍWÁnÛ8½ç+昱§“=6M³M‘b½µŠ½äBK”Íš"U’ŠÖýú}CJr¬&Å¢Ac™äpæ½7o”'s:Ç¿9½[ðOQŸÜä'oïþ ùåVWWقòò4ßJÊe±5VÛÍþMþÛ.i>OÛf‹ì’·}ø¶\‘ò´^–Ô6֐0$ké6ÊlèÞéŒ äƒ0¥p%Bkì ?..2·/ ¶°úŒ¬£ûå2ãÿh+_JÃIàêù»ì‚¯–õډ±Ö{*íOi<يŽ%²(ÇÏ^º'üª…i+Q„ÖIçÏâŽNiØäÛ¦±.¤`œ›‘ÿú¢ +g½­Âäæ”)m‡ëéDLÜï}uÖïÀáäKY)#=‰M_%U¨²jG‘D6øDE„/.Òw»öGõØ&(‹rµÚIªe©Ä$A¯~Ê3rÒ[ÝòÖT¬·|cØfôÀAà%憜€ g]€DÀÒò’¶Ìٞ)± ãuÁN®îsô´mMédéù\ØÚÖ#…ÈP­4ãщ}FßL¬Á"¦{žÃÖvw¥d„Fæ=C8XÒûÉ­…5Á±nD‹P´‡º¥)ܾIϵØ1°*€º-¶T[úeQ¸pCâÂê’A‹/ ñk±—(•ø€m¸FÆèÓò˜å,¤Ü ã9ýc…Êóåu[…<† Qêäº×-§ÒNAFùG@K’WÀ ·ô¤d‡Î(ÚˆD<’ ð¹õ¤ ÄP§¯yå ®±aZ0~½Z¹˜ÝÚáB馘DG•OªŒ²/lÝh$Sùvž‚°Ž­ÃH‡Ã±ÀPLȌɗ¶ + »IZ£“<¨DF·j#}x)Tþ°z&Ñ +ēPZ¬µBTµìÄ,Ď³Õä^®6Kîx0ÑÙåyvÍ«ŸÑ¹¯ZçGÚ+4Cªúv]«À.tä Xé]SPŠ¶è£ÂŽãŸfô9Ú²’P©äj‚Z£~´°¶¶^³)á’ñÌ2©Œ#ïÕÆ°][(Z-\ÍãlÂòñ´õmtˆQCoú4ØGbûnœ} am¡Ú©°eÑÖSãÞd+dw£äg}âhŽÂ6JöŽ+­Saÿ: 4.”þ÷3lô4§–Eèé¦ÑÏvÆv†SšPP¼} Áƒ^Üi·Æ@B•ûµRÎOGÌA…C[*7Ç8¯×z§4gûj­ýz² քO/šF́´ÒàÁÂ4„E$ªèÛL˜mÁ֜ YñDÉÒOƒêP2ã:¥5K„!fÂڔUò`S²Y ½ÞRå­l=쏝ñ²>%l.UU!nN¦æSO!ÖËã) + +y*gôO Opl©o8£^Qg”¹˜ ð;ŸMep#ŠLMôLcÖC`¦°¶¿Ð­jŸ`äÑæé<ãíûˆL/”²DO)‚44`õ[3’9r—c’U͕G\ÏèÓröçÃۋáqy{7|d@O¶øœ½Dõ8µ5Z•–¨yU8Մxöp }ž ¹ß`<²}[~?C’_ï—ø©hbœÉÅI¨ÎÒZ…Z4½úwšƒ>]ºùA·NôN°‹ïC°Evg†+4"4E+I0ïL˜Õu;ŒeŸ?Ëp«6Éÿñô}Ó¬,î oÎh•Zæ `a„nð:¶K‘ðb™:ë·BÖPêøÕ[Äu¯Äùł—çÿöëû»ڊ®ðvÛq;ùuÍúø‚e¡9ÀŒÏÍ®.âÁKþæòü:ã?"^üác~ò÷ÉœÜendstream +endobj +2123 0 obj +1365 +endobj +2124 0 obj<>>>>>endobj +2125 0 obj<>stream +xڅUÁrÓ0½ç+–\3‰›¤!ioPJ` Ã¥U–cQY2’\7Ï®$»© ÃäXÞÝ·ûÞ[å÷hsü,`³„Ó5ðjt±\Ãb»߬7›l »|²µR{aáÒÊ{aÝ«Ý/Œ[ÁbãfËu¶:ŽËcH ï~l¯í¤ó` +0ZÐWe¬€B*Oa®\’ƒ7À ŽE²˜*5WM.¾p¬ª•èÞS½8͖!¡0>ˆV ïg[Æï˜Íá3sÂ~˜ÎáR¸;úª¸ ~–«úRºÔ7äñ´ñ°ZXæ±ãÚˊ)0¯?€&Ì\…°B÷…qÂ\(7éc½\TȂåJÓÂÁ4À™†ÖJ<Á' ¦Õ}zG!õŒ[J@ûRTøy#²²(Ì£€³Õ<;£¸¯Â·ÆÞI½ÿŸv‘+æ6m4#@ŽÃ»ƒóÇP9ÖxS1/ñXÀ•x–C+} ãm +íóu„Ï`‡,FÀ +¦uà ßÔÁ$ Ï%O¼zl\R­ëË â¤$*ãjc2Žö#¡nк‘z £>†GœQRû8]p,çEyy0ï# ÎǺ馔Gó²GÀ·Hçù¤ž“GøÒ£ÙX…Q +¡Ba;°à]1ñ€;ä"ÍÔ±£$ʜ¨\ÕàN(Á}èoiÅÏÑÛRò²£ 9&Vo&"Ûg0Nùoˆ¼Å˜È|r´g7¯R¹ÎEag™r¤š¹—´¸Ñqë三Ä%–·"yì©!'Sˆ‘˸Q4‹Ä½!Úë#‡ž`3IŸ’ †$ÛÁߌV5ÊKºT"jƒÈ…ô%ëòàÈêÒ]'Óà(ñî¥)8Ä`£_z°B‘Ñ5äÕۜ +…ªxšÁ…ଷw`“`Ó¤½·âøÓþ& # П H›sL$ÎDÊc}{v‹ö6NÍ6ˆú‚IÕX1†F+t2q ioŽ‹ À;Ì}¸ÿðv{Å>Kb/–k8§ÿ˜Ëïo¯v0‹·þµ)|KØZ³·¬ª¨Ì¦¶wF™³Írþ?§ÕÙ<;‡ðö5=¿ß¾þc"PAendstream +endobj +2126 0 obj +824 +endobj +2127 0 obj<>>>>>endobj +2128 0 obj<>stream +xÚ-‹Á‚0DïûsÔC•ES¼ªÈͤÊúƒ±WÔߗ3s™7ybdc ›zŽ´šW+0CpnQää2)ëJ`°=¹uß ¯Nû«úƒ>±÷ÝËß§r#“<óm"K¶³¿í´í† (µ}ZzwBú©ð%\endstream +endobj +2129 0 obj +127 +endobj +2130 0 obj<>>>>>endobj +2131 0 obj<>stream +xÚu‘±nÂ0E÷|Å qã$$d ´TH¨p7Ç1ÄUp¨mú÷uš”Vª'ëwÏ{öG@ùC‘ÇH2ˆS°dÁú@ÐœÌ‘å)X=‚5«·íåv3cïMAi†&qNâg² ?;iPK+Œª¤…»%œÏ­Ü©Nckº£á§“4í\H짯™ìgdP y¯Š¦Y ’1íEU†›Ï˜Žà<"ßÃ?J'…Súø;ÀØ¥Q^\':}øçÉè°Ì’[%°“檄´w--ÚK-±Ví@ý©=Kwó—W®Z^µÒo®ú}-¸®±j¹µ?ñ‹ña}D‘ìÞ¤‹ˆò弿?±à5øM +‚Îendstream +endobj +2132 0 obj +282 +endobj +2133 0 obj<>>>>>endobj +2134 0 obj<>stream +xÚu‘ÁRƒ0E÷ùŠ·ÔH(RºT*Š3ŽñRx­8!±!èïK"Vq’UîɽwÞ; +Áx(¬b{ëŽ\3r‘m€FÀö£'ԁ5g…n¥iå²V`Î^IÞeàGV¬Ð8ÍA¨áñÍ´JΩ”Ë…°à½Ú9ÕE­¿¢¼xŠºc¬€ +õ{[ã5:¹å²Cƒ‹}R%%Ö®’QÀêJ—x°7£Šfî”÷ý`!þÍôÛÉļàɨ2Ü G$›ßi[nø )‘/"‹CʋùŒ ÔB4Œ!¦‘ŸXl[^e >>>>>endobj +2137 0 obj<>stream +xڅ‘_Oƒ0Åßù÷Q`‘?8G²dF„ú*½c(¬-êǗâ’e84}jίçܞ{´¸ã!zp@ÙZÔZ¥1è~T‚ˆ8P~³e3p„´nPÝÒwËûÞu|£­%2]‹ +˜€m–AŽÇ•žQ ç†I´–õÛ ¹(ø¿&9²KHõP8£ÒZüµëºÞô »¡:,ƒ&¤ÐLp&9<÷(ǏށW¨Í—F¡Fq[¿fÅ"7µþ´n§ÖwLT« +”u‰gò´Ÿóóý¬Ò1ñ܉z̓”‚ Ó$E·×ŸL"d²«$k[” +ž˜Xc lóÎ=÷ª½¹N “›û†Z/Ö7Ï¬Nendstream +endobj +2138 0 obj +277 +endobj +2139 0 obj<>>>>>endobj +2140 0 obj<>stream +xÚ­’ÁN„0†ï}Š9ê¶dñ¨f“%A©PKÁ(k)ß^º°h֐x0íiæ›þ?™7D€ÚÏ[tKÑ&½­ÆN×Z^Ü c¤ªÁ¼ˆEņÆÀž©z`µ¸¤¯ƒs…Ýà=!(ޕcu…eßdaô̍l'#N8ÉvY…Ð~¡f»‹îNñf(¤²™¨½}ÇÊiçQ+f†=³þ!cj`•p줳õ°$ؖüÀw}À¹„¢ôén°ãendstream +endobj +2141 0 obj +281 +endobj +2142 0 obj<>>>>>endobj +2143 0 obj<>stream +xÚuÁRƒ0†ïyŠÿhÐlD GEé©#J|€ L-Iè8ãÓKZ3½í÷í¿³{b>!¸OÑ ìI²u¹%ÝLҜbÙÞ½'ãìe[l½;ǕÜ3ŽèÇIJc[cûYÀÕ½ÅQ©^£6?zaì”ÿ +Æßª->usÁó(œí¦™–R­¯KþE¬ËDá)ĆÇy0ŸßK‰ÅGU£vÝô­¼Få]ïÕ0h?b§ìYBD&£LðۏH²dνD¡ñ"ÙûÄNdendstream +endobj +2144 0 obj +213 +endobj +2145 0 obj<>>>>>endobj +2146 0 obj<>stream +xÚ-‹A‚0÷ÿo©‹*’Ú­¨¸2¢Ô4Fc[l!^_kÌ{«É̋ÙwŒB¦_-•š–•3tÎ%VyÝζçu¥!°¹Ô ߏo:ÔÁ߂±¶ ã&óœë‰Ô‰ÈyB…R ‰8ãÝ»ãZ샟†˜„¦}@Î&Œendstream +endobj +2147 0 obj +131 +endobj +2148 0 obj<>>>>>endobj +2149 0 obj<>stream +xÚ}QOƒ0…ßùçQ@J+°G%ÎgÆâ3ÂjÅFöïmÇ¢.KL“¦¹ùzî9çËcíaH"ðeç=æÞÝz…(D^ƒ³4ˆ'yuÃáã]ËQö Ör?’6·ù§¥s´¿à>’ r?òV”m1X™RË2hՌQa¶Z„µÜ“»T+l·Ù‹ò +,qÊ!|©Ó|=>HšqîÃàdsKåd•ÈTodEº¥}]Zµ|/üÎØ (ú +ÏZMƒ¹æÜ†ri¨”.ôÑ¥§÷gí¦he©¦Þ5tå?fK'™ê:»Ì‘½åu3uԏç¥é¯»ô¿ÊE"l¡#wƒ§Ü{ó¾-«€äendstream +endobj +2150 0 obj +278 +endobj +2151 0 obj<>>>>>endobj +2152 0 obj<>stream +xÚu1oÂ0…wÿŠ7–!4—DŒ%M`(-fœÈUbÃÅmÅ¿+­Ô¥º›î}ï“î"ñ}iö؋…uÊ ›{’Ïiš@žJw¾b©­f即ù1r³‘‹ò®²_†íµõØ+6ê½ÓC ÿ06ÞØ ++¹~Am:¯y4ÎAŒ”ä _þùí©–ˆPî6[l]ã¿klص¬ú^󀵲Ÿª Š(4£Y‡"eá”Åé´@üÏ•¯âãÅI(endstream +endobj +2153 0 obj +193 +endobj +2154 0 obj<>>>>>endobj +2155 0 obj<>stream +xڅ‘MSÂ0E÷ýw 3¶ö +KEÙ9 ÖqÃ&“‡&%IáïûBª.Çé.=÷w“S”!¥/C•£˜ƒwÑ}Ý®—ÈSÔ{äÅ2©0¯JÔͤDŒw#TlTN<yÆNëJ•È2ŸŠC,.ò*É}²n¥oYï#´|°VX´ú§q¡™ ý8³¹Î¼Á¥•¼%l/¸dGìåѽÑÃ:¸–9p­w«·í«_$EœAl˜½Ndށ†kJ©§<ÉY¹î:¦r¨&`FœiDƒ½6?K%¡áYå’¢L“…WlH~–âò ”#0K“ëµmÙAàŽs=(uã†_WúHž'¦ˆê„r¿<ó,Ty UփâNjeÿôñ¡·ÞôBí&»i@ãëºÑ^´¬Jê˜z2›ùƒÇ:zŽ>ÜF¨{endstream +endobj +2156 0 obj +327 +endobj +2157 0 obj<>>>>>endobj +2158 0 obj<>stream +xڅ±nÂ0†w?Å?ÂàÔà¤c@ Trƒ«.Y¬`Pª„À9)<>qÓN•Zùn¹ûþûä “Ә©PeÞ {X?BÎaÃF¥2Šaö“²?ûÜúÎQîì~3´£bRL§æƒ ð…ˆæ¿1]Ý\íÿIJºõî‡ø2'£™«oó;U]u:Âb£¹Î¶XRõéhäSHx+ÄBDiH,ó§µGö¦wص‡îjÉAS{$Û4Ž<^ì©·u8ÁC’'±A©Âh6˜ˆÿ~½2ì•Ý“X[>endstream +endobj +2159 0 obj +207 +endobj +2160 0 obj<>>>>>endobj +2161 0 obj<>stream +xÚu‘MSÂ0E÷ýw©‹Ö~Aa)Œ¸¥Œëˆ¶IMR˜þ{_hѧ‹Î´'÷¼ûò$ˆéIP¤È¦àM°(ƒ‡ÕiŒrt–G)¦E޲º› Ä»‘NªŒ +UÙûòƒðIâñpàÃ,-èEGÊ£´àGÖ:aP ËÜ ‹£>Ãiœ)L€a7„a¯ –Ûõ&ú‰×MÓ)Ɂ•4‚»ºÇYº#Z#¥Z0Uù)b„I6XY]“`Py9ìe}9Crës õ˜êáúV@ïɪ©¤Vp†)Û2#™£¡îIáë’2£™W¾â$ÅùÈG`G—åmï¨n¥VVVÂ0³?âÓéÀoíuæg£»Öþ βhzY±hZm˜é±’µ°ã*®Ú5;>>>>>endobj +2164 0 obj<>stream +xÚ}±NÃ0†w?ōtpˆÝÆ c[Zqav72Äg¸º ޞ#Ąî¦û¿ÿ“î (§0Wiž­4»Ü^¨A§DÕu¡@÷ëà½Ážß:´°¤áì-ÆÓL?g|‘q^•Å"㯟pcђ‰.à/÷£åJ2q|w0Éàѐ3ûÑ~[ÿ0Oä¢Ã tv"FhEX™Ã‹Å>›"™…T E•{×Ë­ë]ÛAŽñЅ–Â@Æ{K'¸3x6cRðÔäµ,SQ4é4¯dÑ@ùÿóÍîÙ©@\›endstream +endobj +2165 0 obj +221 +endobj +2166 0 obj<>>>>>endobj +2167 0 obj<>stream +xÚu;Â0D{ŸbJ(lÇĤ‰"sC +æ#Áí±ù ÐV»ó´3»'Â@}1HŽ$ÅzOŠtÆ8…*‘t9R) ŠV†Û8m]ÓV;O 0¨(`QÂeÌ©¶U}<[TWÔUã|[×8”p[ƒõ{‰ï´ƒ>¦¬¬)°º=ˆá2_ ŸOã§M&ƒ E$hÜ â#SöôŸ(•ÿ§ùm¦íæ¢7æûÎÞëN2ÎãßïRøl4h, ƒ‘"srIaþendstream +endobj +2168 0 obj +207 +endobj +2169 0 obj<>>>>>endobj +2170 0 obj<>stream +xÚu޽Â0 „÷<…G’Æ¥$e„þH •B ‚ ÑV$A¼>õˆòMþîì{2¹ ÂF‘.#;X–Ô;@ vXˆÒZ(°×Usl*(æ)D7۶w&+)AcÊ¿¬u!öþ'uˆôS¨2‘“µl÷µÅÙtÐÍC|;߃ñóÍ»qì}€ÆM/÷ œ’\§’‚©¤U&·Bƒüݶ²ìÄ>ŸAendstream +endobj +2171 0 obj +165 +endobj +2172 0 obj<>>>>>endobj +2173 0 obj<>stream +xÚmŽË‚0E÷ýŠ»ÔHKCe)Fwêð(¡iIôïmŸ2³š{OæÌƒPDn(Cœ ¾‘L’Í1‹ [Ä< Á!›U†…æÚΓ2kyu ¥ 2ˆ™™‡e§ ÊqTC£Ÿh”©'])õ=î-l§`~·ÜZZ”“r`«Õ z}ý%/°ËOábÛ~m‘÷%áöÿW\pWE¾dÔIÎä 6Ó@òendstream +endobj +2174 0 obj +172 +endobj +2175 0 obj<>>>>>endobj +2176 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS042S072PIÑp rt QÐUp VÎO+)O,JU(ÊO/JÌÍM-*VðMÌ+MÌÑ ÉâÒéӅj42 ™š+€¹N@3‚KŠJ“KJ‹R‹AR®!\\RÏ$6endstream +endobj +2177 0 obj +126 +endobj +2178 0 obj<>>>>>endobj +2179 0 obj<>stream +xÚmŽA‚0E÷=Å_ê,m\*‘ÄÆzm¨Á o º3³˜äÿ—yó h˜OÑÜÉA’M¹£|+b†4íª@„òi›É8;®å-pI2sÑFœeaVvfD= ʶæÁ»—iUHà•V^ÙFA;ºïá4¦N¡¸Vì«ôO/Žüë á¼Hãüï+"¡¡sÇø%9“Ÿy<>endstream +endobj +2180 0 obj +167 +endobj +2181 0 obj<>>>>>endobj +2182 0 obj<>stream +xڕ•[oÚ0ÇßùG4*&΅uÔµeÚÃ6Ö¦oH•—š)æ$íºO¿c;´!„& ûïãŸÏÍ¿ üP°fò$ƒOþ`ºð€ºà¯qfæºd~8 Êm~†ß·E”¥«áj4òi¥­•Ç ¶TÞålÃõ¬^5iRm&J 9…#Ô óÃA–æLÀ8e ?mÈaï©«Y\vÈqwHËä>S›å¶¬RÞ0W‹V£³ƒ£[–>݅ؔ O‹\+ T*æqPTùg'’êQ⢾ây "µ‡œ¹ö108/?7ŸÁž£ÚöL4DMx`ÄÁá¶ELÝ9Riµéx¸òU­¢lWxŽd°QmJét…¦6Phþ9 Ù +ü¯=A:0] öÆTêL ç¨ø¨·°©ñÿƒsLbô‡Sê£p–«Ó§–Y Èoeò“ IXÍcr 9?cN*l&{(îԛZ©RÓª°Û‰—Ö +"YÍ©y?J*k½7¥R·æçkYŽ­aoxQŠ´*¯]þÊö2Óµ¥2•?É"ßw89Z³º“MëÀì‘æ· CtNZí¶óZ¾åA´ŽxXó[+Ãõ–lã£Mó]”qrø AÈÃÇFßj¼BÞLÇpј¡«‚ ãiC-›æëSKò³ƒ< Uh Y\¶‹ÑLÀ•AÕ/±ŽlC/6ò²«ö³×uÉ~â zã:Á›çü’FEÄâèo¯£Öç`4Íï¦äs«aã†XŒn L£Š2Ò $WWcÁIÂȝœÂIÌ ¬YüW¿ãàýþÅÕÛ¬ày—òEÚ¶ #ÜF¶§‹yUԜÁÌ©bzus±ða—wË[¸ÍÖœL½¥È6‚% 9|eiÉbib"WN\Su!ӖC6#¯¸D+‹2 ^Z¦ßÁ?DŽKendstream +endobj +2183 0 obj +716 +endobj +2184 0 obj<>>>/Annots 14 0 R>>endobj +2185 0 obj<>stream +xڕ’ËnÂ0E÷þŠ»© çɒ>ªjJÜ› ¢Ju‚úûµ“J)E­,<¶ïœë±?›Aˆ¼›’ÝK6Kæ rgv˜\¹dJaQÔÕT¾³'ɸˍвaµ´ ÂÀsc” FÕe2[t$Ð{Ì3§øæ¨ÁlΧ:ÑJ½œšCu¬×“õôW"QäFSP8d?˜|`ú=ób±çÞÁbn™l­-UÓ9»iLˆïë—ð|Zóc—{üÏXšëzÜ´k”¸9sÞRºÇ}\- oi†¬Ú5Ÿ¹VHuµ×yY*]ã9?žóÂVuH„p"Áǿ¬åvY}o^ُûendstream +endobj +2186 0 obj +264 +endobj +2187 0 obj<>>>/Annots 18 0 R>>endobj +2188 0 obj<>stream +xڍT]Ú0|çW¬®/PAj;!ÁjU‰\ÕS«RȽ݋ rJj'ºößwЅ(ÂÙñìxwÇ¿;~)ø¡ý%yçKÜùðÀF¯1F‘B¼ê&ÕÎÜ •Èì±X>wŸ{½øÅ!‡ ‰Xä“é¢xdÔѤª´!|C‰7:Cœʔl…†÷+iÊ~ o>H/¸­÷ñDŽï»Œc½©r©JãC Ô"(RD5¢÷( ¢œzRàë‰4‰NweZ(™Æâ¬Øá1ÿ +ÁÑCxXLjz Á‡–°8f”{¼A3:ÂäGt]ú Ñ7´ÎÝ©m%jiu‚ZÚLã᥆BC’ c@‰\^pénéÐgD:iwõÅò·”aáÛä?R"۞›¥Ôè³õ:v< ¡S4—e¥•9@N[?âH”C@øa•µ»@Àç6²R(˜*I¤1} àj-Ò¬Ò҃Ÿ‡ÿPn%H­mW„‚¥„uQ©,ÿâ:ËRµz ßŠÒ°fq9kG|¦œZš½ÕZ¥©wìUv½‹ÓßàcëÉÐÍþkØíI0h곙LÒu*õÝå¼Ó?"ße¯w©J²j%á“Mîm?·\~ýޏÃêHý(Ë»>ÐkÞ_H ãÌGXÓr†uȽ¶_4sp­KêëwÒ¯³é( ¼á!!#þau’ñ´ËœSöo›¢úŽxH3ymŠF͆·k,4™bÀýÓl‹b]¾ +œí™.6Zä¹Ô~U‰Ìr( a±Úû,´¯‚ÀwWA«¿:ÿ¾²”Øendstream +endobj +2189 0 obj +617 +endobj +2190 0 obj<>>>/Annots 22 0 R>>endobj +2191 0 obj<>stream +xڝVmo£Fþî_1R¿8QMX^LPÚJé%¹ž”Þ¹1ù鴁Ŧ‚Å·»œ{ÿ¾³»€cÇ`·‰D2̳3ϼ.ß&\ü%yàÏ!­&¿'“«‡HIŽšy9sH²iÚlä]ýP”ì‰}k˜T/ӗ‹‹äo‹,zºN Ñϒ®˜Õº·JXSÅfóUÁ¥Vã[â:×ÖJ¤þûóÞý´f…=}ŸÖ\*H×TèC²nDÊþÛ©ÉrZ±—‹›w™ð}ì­X5ãJZD„hD¤5óÛtu !1q"´€¯ï˜LE±QE͵æ>™¸Ž‹õêO!¸Ft{hÈô\ÇÁ`yKíς½8râ7hS÷ ejKAtJ¤¡Ó¯ýïˆý‘$  ÎRMT ’‰ïL8'xFš<—§áiم¦@mµ÷é}Z, U@F=Å*ô÷lV<Èʏœ–—m¨#yëT [òZÀâË29ÅÑ'hø\Ž<ȑ´#ݵï>G=¶ <ƒm¡Ö†^ŸÏ—i7Ö¶U¦ŸŸí«®{¦°© ®˜€"^sæØM1Ñ«áÜè øhÿîæÏäSàrŸ¡^Fs;z¶Wäǚ™f,È!bhjÍú´ä´(¥_¸ù¯AJZ˄@k)åðª+Ý`F_ \–_½K iÃD|ೂ8î…ÒFy€+Ø1Õа[¦Tª{M ÛÔ 5'û€œÁ v°…Þzë³8r;ìR–ÕL3{=E1/Q/2è¼½`­¬wLÛ­îv´o×î!¥,Ô9ZÏÛöíÌ´{ >¡¥RÖ°F{%ºÁš7¯U¡Vb¯’† 8—•Vm¨”ÛZdNiƒg¸*Rj •ÀËX6œÆûhµ)/ş +ž–MÆàKgýÛÁM4Ú-$Ô¨ +|½Ù­0Ø-M¬M{¿oöê3wï͸óÀ5­ÆÚ¹Ɯ¤k˜¯%å«aÿ—ZÝàwÄ ÷^Œ%©À‹za̽ïÚš¯…ÑÐûO‰›ƒR؍cwÇ͑z½Ç\]ÂG¦L'f,§M© ‹.¯À½æW̍)Ç<ÀGe*îYa07îæùÜY*Ãdj➙Ã#¡}Œ*†ãÉÙvoºß…Ö)N†æ{¦ëˆëáa<4ßok÷™mÿG$0ƒϋ%,ë\m)îþ…¨W‚Vþ¤¼¡¥±ªOÎ"Ï\³KÆà’VQ€ÖÌk/j£þkò/`éåendstream +endobj +2192 0 obj +963 +endobj +2193 0 obj<>>>/Annots 32 0 R>>endobj +2194 0 obj<>stream +xÚµUÛnÚ@}ç+¦~‚›]Ûœ*©\0‰ +æ ¹°\*ߺ^+ùüîú!±E¤,ãYÏì9sfvøÓÀ€øƒfˆkë7¾;Î Ξ¿0ú=EgפäOBb&?æJñ‹P—Â`sÚÁLæóÍ|1™9›Ñdjm9¿dŒ”~Õù£¾¾Ž¹2;w`ív ¢N”ìÀeŒž~%ŒÄp×¾¶Ó@ +⠉·ÅX`è¿ûü—ï”,E®Wþô ’ÖuwŠ"·äÁ!eRº¢Üµ¹.Òj§Ù;Öxó<·–3yž—?¬ÅÒvÚWéÀåG:'#o. “Ú0[M§m¨LMU±¢ƒ¡©¼F>h¨'²K­ÊìŠ-+ë6‰â©ì`îêòô¸SâȺµn¥e’³ªju)Þm*M­Ùxeí›e +\–Pד j…^uñ…/|yHá[¹$?–/ïAHyžè¦¸ZLÚ E<€*'ô$Ւͪ/qœûNçÆ,p}Ò¡$º%ÿƒàÌz²9bîÊÃä$æLî-T+#U1 «êi£â®QZ•Z„tύºâ\ÖÍu«ªIóÆÌ"k†È0v$P "EÉÇǛiGa>•ò0<²ÈÖÍ#cQJA¥sM¸±çžB0…½²¢F‘ XÏFªÌϞ!0–„€åÅaíäÒ5ÌqͰ8֙U©™Üg0:ŸýË#>${7ñX!àÇuÂ=¥Wbªš¡t«0Q‰©ç˜Å7k‡:’ï¦O-7UW/ôÐP¿´nàV¤ò9n— ÷!' k¥Bœ“i*Úíœx +Ÿb$ºnÙ²êSpÞ¾Ù®o,Üçm胩ò)ž·õ6³ö};]jD2{ŠYÂá.ö1Þû$rv9ä "qV3òR§O¿_C !%ý³.¬‘2 Vó%,Ã={q)9 Ôõ}BcxrƒÄõ² £òùÒS‘TûbI×Å0KìW׏<’Ëñ³ñ—Vendstream +endobj +2195 0 obj +762 +endobj +2196 0 obj<>>>/Annots 36 0 R>>endobj +2197 0 obj<>stream +xÚ¥VÛNãH}ÏW”4/MßbÇÊîH™!0H,“MÌRÔØà•oÓn³¿Õ±ƒ´·ëtõ©S—æçÈ ?6¸>Äùèk4º¸ +Á Ú¡ÅâC”Œã¦ª/Ë5ûÙ°Z<ŒÎ΢4ÒÓÈÉÔ"žDÞ×tϴՂÐ[»I«j+à\šñ­m‘ÙçOB(”üþ|…7?Æ×;‡±qYÔâ'Ê冺lxÌÎæïâp]MuÁ÷MÎ +QkÄl["€Ld‚mAc‡6 о¾duÌÓJ¤e!-Ëhd •îþ¬¯Á›!zj¹ÄÁ³§$ÇÂGÎ`sl‡²ÒhÇsqç Z¥Ì3ô¦’ƒ7 % ©Ÿ"¦Ü+bߣh%•(X,Ɂ(¡füãd˜§7s‰õaž}„§fçÏt~LÚ(Þ¬V`,PAO1óôöaf +ÝË =úš™®cêµ6(hÎ`WrXýØD§Xzzþ0K…>šç—BugSMvÍDà S¦mȞóujAë +ëŸ)E9· ªÑã»ûÛÛ·Ɛî@<±.;šf5…zj’´2ÎÑ[L x”b4Eÿâ:ËÒbÿNۄ‰ pQ rÃn‘é(ð|/L%´H·´KI H‚ª]@¤·ÕÚõõiŠ=ðE®¤d5PP5"+¢Ž¢&/¥ ¤f¯+°}enpKV—í0“-/›Ýdè3Ù<橨ï›ü¨cǂ̥©¢uý\òhƒ¨B¤1UOk(KXÒ/Çò7Í«¬w†J‹8kHMÈӗƒ±;˜u;ÔYw”U/z³.Ñ~;ȶâx‚Í”W—Å|øè™‡Ræ0 åÑj1t4¶—Ó&~›ÑbßÏà\š¼öN\<9'èCOWžºäƒïnÀùA*ôýØaô ˜É׫%!dpq×L¨ÚK؎6™€6~8¿8w–?¡WKÎÞlœÄŽYõªcv„äÕ((ö—šMÿ0«Ð'j÷@tß8£‚a/ìùM³¾‹®5œŒ.ðUéٖìj1þÛå˜Þ±çÿ‘!9ùbHYá/ãjlÓÉcÛëe´]­oî¢åz»ˆ¢õÍ×ûh¹™À™y”®¤öüdý,’D‰šr†Jž>6‡›øâjf¦ªíøà‡¾Þw¹^\E0o÷« lʝx¦x ­x¹ç4ϯá/Z44SŠÈ“ÀQ×ö†1X˜‰êaWÍômî„&gþ¦YËðendstream +endobj +2198 0 obj +958 +endobj +2199 0 obj<>>>/Annots 45 0 R>>endobj +2200 0 obj<>stream +xÚ­TYÚ0~çWLó«v²Õ¶J¹ŠDYJÂÒÊ ¶ÊµN¢ÝŸ_›¥PRVjˆ,ÙÌÌwdÆ/ ˆÿ0–xƒ¨óÅïŒýR? Ëj*6` ,U‡,ST›<‘rÏö M8àï@¤Ù<ÒßvŸÓÔÝn½œ=Çûžÿó$ UYÝM—Ñ—‚f¹ ³åòÉw§OËñÊõg‹ßGïîÊûò±(q>¼>œ>É9Џ"§™Ëh.ɰXÏç2ˆ¼¿ªÔu¬š`Ù}¾F` [=î® +­S,¾rA‘fsïÇqlÛt†<¨ {ºémzE”RVjԜ‰;5ï6—æîbºv§ã›mŠI^0*5µÚ¯¶ü:><ƒáss¤|jþ¼i(U:Ñ”¸^ÍdRžS¦ìYj%[~}‰ãÜkÚ!Éò˜DTc4K +ÐÔî`”@~ P‘SUî´³(^/MâŒÂˆn%«2xÓ=äy*C#Lº€Ö&`³Å0TKÔó(7̒«]+f³Ï{Uô,Æ:¶r×:œ—0}4ø³sGtGА³Ýô®"bl«vƒ©–Ú¿†‰L³Â¬)V¸å8¶‘¼ªVnº©Ÿøapt;·ZÊû¸­3ÊZ9ØhâœG5nçÄ%¼‹‘è²aÇ4h>b[ù®ÜÚX¦c/}GçÊÍM}e:ýË[¿Õ$ÇV÷ï°+x—"*vä &qV úÚæÏ ¶_Œ¡®›åpVîĆë¥^²Ë_ £°dɞ‘(¢,ƒo$.Hx¼Ñ±nbëH$H™¦t<¿‘( ieÇ÷Î/ç˜Õìendstream +endobj +2201 0 obj +628 +endobj +2202 0 obj<>>>/Annots 50 0 R>>endobj +2203 0 obj<>stream +xڍ”[oÚ0ÇßùGÚ LÅØÎ]L“ØZúԍ•ô ©ÊÙraN²®ß~vìMM"âó÷9?Ÿ‹ÿŒ`ñ#àP0lÓÑ4[z@ð·Âb;²ÁÆau(–œ±ï‡2γb3ÞL&þ/¥5•vjadJíS옲bð´‘åèoGÒ&–Fn¯ï8+!«Òç\-Ü´ôÐzä~­}.á£Þµ™Ì[û:À†¡˜|W¥,+ ¥°€© ØDŽPéc5*)"&,—oYò¸Ž)-wþ#,²z|=ރé +µ… DØ@±øË¬{Ä{k5¥Þu]SóY’Át=Iq–®š¯ŽRó}«ÒŸŒC¾m‡8ƒ€óà]ç5]Cp åUê^Ei»ªýŒ«\”\@–ùr¡M…×Á„µº7£§ž0±¥@[e•­¬².{ÙVqq(š +a+Ìâ0I)Ksþ +AQäa”,‚—¸ÜC¹gúÌêÈPXoc¡‹ýz÷/HÉÅûgaRE >IÀ™|¡ýçža8û”#wzκiÞ3¬Ýa›_÷Žº.èdò|üáíD÷¦dÍ,’"ï4 Ñ=€e/»ò6KA\jÍG¢Z ¥ç;8QJÝÓ-¸ˆ"Eٔ»7œK‘uŒG,Ù0bÐqNqn ÎOª¸gåbä ¨˜òAƒ9â!à¿[mߋA-Y Ã0<伇ѰÁX¼h_×ãléêZN ¥Â¹e5Á·‹¥Søú´ZÃ:ߖ/¸V<ßñ M/à!Ȫ ‘~Å^¦Åí~3Stq½l‰£ÿgÚ^endstream +endobj +2204 0 obj +624 +endobj +2205 0 obj<>>>>>endobj +2206 0 obj<>stream +xÚ¥T]Ú0|çW¬Ôà„/ &€hO¢÷õT‰Bî©T• Np•8ÔNzWUýï]ÇæŽ ¤­T@HÞÏÎÎÚþÖñÁïÃÐüâ¼ó>ê\ÞMÁC”`&IѶW{}ÏËëŒiÍõº»îõ¢¯J-t0ò5ÐÍRn³L]2ð-¥IaÄ÷Èäs¼c +úý~ì½ÙI¥áВÍUZå\–Ú"Fàû1 âÄ áO}2Æý¾á:Vb_ŠBšÌmÔñˆ‡V<ÿ-ïN= +(Êôi@¦x$Åaul¸C‡hˆ;_е§Ô‰ #lÞÚj›¬ÕÕ5ju‹mâ +ÊŒ,6‹½ 2¥ØòÕEþV]£Ïª~1Rw–¼¬”t–º2­ãюƒ¬ò J-Ø+«Ú5 +ì;Ûdœ´Nµ1sŠNŠ´ǃž.¤¼Äj ]%ªz®ÝTEÀˆVuc|k½+ªl ‰â­´éáìÑ%”aX_kìð9=;.A” 4ȲB¦X_"1ß¶[qûÄò}Öz™ÞgՖÃ[ãÇ¥ù#»«Æýj,±q1;Å©}qŽ4óîR¶dKBȟG…à4gù¿ì"õ«WàÙy~6ÖI¡pŸ@AÞ D=Öc»¸8áüؑ;Ü'ñÙ=Yí +ñ¿ìÄ'îôøAáaè7Ëù]¸~X¬`U$å#ÃûºPEªXžs¥á“Ë ÅÀ쌃úU&DéÐ>2+Îažé½$;¿™mœÀendstream +endobj +2207 0 obj +592 +endobj +2208 0 obj<>>>/Annots 54 0 R>>endobj +2209 0 obj<>stream +xÚ}PËnƒ0¼û+æ˜H…Ø` ó(9U¢Á½åb¥&j„Ck@ýýÚ­Õ¢6ª,­´ãÙٝy# Ô=†>>>/Annots 58 0 R>>endobj +2212 0 obj<>stream +xÚ}S_oÚ0|çSœ:M +ÓHã$üÓ¦I´´}šÄ }ˋ—’ɱ™íÀúíg×бBP"GÎï|¿óùü»Gه ¹·hzwYïöq +2F¶¶•Ñxސ•AÑnõ3s¶¦-7y÷ûÙ/M=t0ŒÂÔAŸ5Ý0_0=crà‘BUøä0¶D¢pr©ÅNÖeÞÿrÖ'I<Ւ™V íë)9¶y3le- S0¦b(=³ýjS jj)ÂNö9Ӆª·tÜËY‡.SŽbl˜Ñ]½±U^žT(8Õ:Dց¬5´‘Š•¨èÑ·$Œ +m,¨°K·%ö5çøÉ wLíUm ȃV·”ó[5Õ«&M†å-Ëû k'…Ñ¢BaaÝÆ<ü¡Í–wð‡Z¼-¾:wnÝVßÞõ»é«ë<¸¹²ÿ:ÏÅÍgœ{~-#+Æ0ãZ:ÀC֋ÂÈæÝ Ä Ë'7A'VGƒ±;V?áX]ŸLH8½Š>4 Ãi8<ß‰QœÆ8‰Óÿ®Å½KÓnÃo&,|€ô1yÿ£7ÆÉ‘ÄöŠO‡>2óåì1Ã÷ϋVrmöT1,”Ü(Ú4–ß©°iq¤·r0Ž#·0Iݯ4M]°÷Gï/Ay3rendstream +endobj +2213 0 obj +482 +endobj +2214 0 obj<>>>/Annots 63 0 R>>endobj +2215 0 obj<>stream +xڍ–Ûn›@†ïý£ôƉâ Ë¥­ä6uT)iҘÜEŠ(¬Zé­úö=`cÀXBÀþ;óíœäß +þ(x&X.ÄÙäS8¹X@=W¸âzq!L¦qýZ^³êîµJ‹üiútzþTJ[)gŽAl¡|,£5S«zѤÚL‘—Ä/‡3¡Á%jÀC[™G;ïÈaïJó +ò:{.äîò¸XxÒÊç +Îôž§ÓËޙ,KaÏùºÎX^•Já¥B8h~féƒ7"¡¡%ZÀÏW¬Œy*}ˆ•/áÄ F}{{¸ÛGµcXÄDß&qÀ4ð‘3Xˆ…mS«MÛ#´¥–é³5ž#l?"„Lš—`á ñŠTø¬â@ŽCÚ¾EŒÑJ=©Ð\_¥§•¹!Æ:ûÁ¸ Ô̶Ž8þ½Åëšèc4¯TäE‹²³6„£Ðp«;Mªó½+XËwá«jžërmêAô¡«k^ ì kU´’¢MÍJ(84¬¶N¿=ÞÜì[›BÚ®HKȋ +¶Js–ƒ½Ô針ށi³sÍÕù¤ÿUÊqRq\sÎòx[Ï¢¶“¦ªáëlšÇ›:A•ª¨fjˆÎÚ¥Y%S¬ç‰KZt¢8·áèÄwދ3_ˆyùØ_W1ìvW«y.FjÐõT»I‹×-.BŽ ¤øDžÈï'ç{³F à%c0ߔE¯£¨nCL%êá=ÏÛ¾lTtô| í® t­y’ìÝ 3_´l㍺6±¹3´;Ïk¼œË +êI÷ ÎØŽÆ1ê$ؘŽ{øÀ Aƒù6Ämč0]Ú +ƒ…“É{ IG!ÜG¼ì¢oíbáëbËâCvíÕÃ| >?Þ/aY¬ª¿ŽÊ{^¬y”eŒ—påu´6gÔtaæ™F·ÆlÏÆB–Ÿ-GGàûä?™XÌendstream +endobj +2216 0 obj +736 +endobj +2217 0 obj<>>>/Annots 65 0 R>>endobj +2218 0 obj<>stream +xڍTMÚ0½ó+FÛ TÅÄù$ݶí.{ÙV‹E ¤MâÔ6eûïkÇdÃG+P„3yoÞÌøWƒ£>¼P×EïsÒMcÀ$ £…¤ýõ¾OTΈÆÓU5$? Ö7Øaà _c—‚l©‰:Û ‹m"V + ëáðVcT;h|‘£­8+*¹ܟÑzžÉ<áÛ}AK) "Œ5"§@V[Òc© êõkžU2c¥Ž<&=9ʚãcþþX¡×Wb±Q®ƒ\àÀ8ÖAƒvÕ?q ]{ì[yÖ( êL•µ¸š¢—ì(˜Hi&ªœüÑ?¥ +ìåèš_eÿoÍ5ú¢æ“é¾oçbN垗Öò¦&ÝîÐú ËJIy£·²ÝU"á@P¦)0ÍИ4ýoËççיûm d§,­èêdtº{bh ½:à'jë¼0u˜†ɳr ¤LˆŸâØبrÈQ'‚äUíôEB&šù÷”ËJBÉ$ÐõŽ)/ºÍ½XÖã )ªüꦽÉÊu¾O)|еôí>uv®»‚f׬ÎûÛ`„ÐmÀ±ÞpfïÝ,§DPÓ¼–Sïïníø‚R˜ä‚ <¶3¬€ÃH= Bå«9äf„;x¾…öÐâðx -(ÿMy3™B½¸ Æ'â3.ÇrY=5É»zÖÏõÔìKqâ>O3šŽ­ä0V>A=<óÉ4!|Yΰ`y jqgœm9) +Ê|%åžä:ç»! #·¾]¼P¿ò}Ï\6‡¿÷þ=`ž1endstream +endobj +2219 0 obj +608 +endobj +2220 0 obj<>>>>>endobj +2221 0 obj<>stream +xÚ¥TËnÛ0¼û+éÅ.`F/KÒM›Ç%-ÜX9ð…‘(‹­Dª$•4ߥD9ŠóhB€ s‡»3;ëý5ñÁÃLJ$€0†¬ž|J'‡çGà'‰“„ĐæÓ¬mô3«Õéfº™ÍÒ=,êaó…G" »ÖtËú¨G.ø.‡Ú@VRo-C¾G–ûéǰFqa˜Ú̎Ÿ” Ã>ë‰Ú¶5F÷ˆø¾Eø^Œ”æ¡#6 ,È?òI‚)ðø”éLñÆp)lä,xÄÖì^W-½"dêǶhà‘ƒõ3àÀHèÐAo„îz9~ Ëaú;NgÇ®«Ñ±KK‚Ö d¿Šü…ªa‚¦Ú¡Ÿ¥úÐì(rcpÅL«„kõ ÅZ÷m3¦`XÝHEÕ=¼b€ÆÊÛN šÝŸKÃÈô §_¯//טÔȨÒÀ ƒJf԰ܦÉ%ӀÇÃt…¨Y•ô–!¡ yq–öÆáÑHâsÿ„–[f4–Êds?¸¶ÓY Cã”ï̄t¤ªëJ³ºÜu¼Uïé9pð«yøñ±”ÚØûÄÁÆße º”m•£¹µÄ^l¦­¨¸ø¹™=fH KâñÇ —‚A«­_Üô<-ªãÈ5h#êàõjC Ïà¦-Š~ŠGl©ÈáŽWU§é–©;ōaÏL Œf% +ƨ‘ûSðj§_6ñì7­›êÅ-ô†‹¬jsïlþCû"函}´¿žúeÔäǯã!¯0¼‡±°§ö¹e÷Uœ¹¶Úns.‡½İXv°Ó«“óæðùzµ†µ,̝u}¥äVѺfJÃ*ZZÙs{ožÝ^Z3'•–6%vÕuÇaâӷɳ:¼·endstream +endobj +2222 0 obj +664 +endobj +2223 0 obj<>>>>>endobj +2224 0 obj<>stream +xÚ¥TێÚ@ }ç+,õX1› CÑ®´í^ž*QÈ>•ªÂ$L&t’t[Uý÷Ú¹°» i+PÐØÇöñ±'_{ür{ô ½·~ïòn| +~ˆo:eø»~Ó{•-­6™²é¦¿ ü/%V”ØÑÄa‚°©ŒTéu`^9]^&Âxr¡…;lv6u°—†Ãá±¶ ­Zãq™îÚFùA™,-àœs!B>çlŠñh¾Qi`õ1Ӊ!Ï­ßs˜ƒjœ«{3DO\D¹pÙ\‡¹`¬Ï€)·W¡]áa亐UTä&Äa‚íÔ]ôŠ"½eR˜!K€ôŽ•QZ+°¿ÐvøgÚú,í'Յ¨¶a¥²ÜšJóº-²WJîï˜ü°EªIU‡õ +ò›Ô±ÜƊuε1Ú¤V•Ν¬õ!R–ƒX§1ɐשø‰âk‹žÔ®Ò}’Ç;Ø*­BkžjQ‚>F¹áÎqxÜ+:‚I NL„ZÌ©vÝýß~—‡cÜy‹^iÄùNÁká’lÕ¸X#6  ç¬8«ÏµM@u»Ü#cìπç¥à ´fø¿ùu›—E®À)‡ò õ³q‹)9 Ð@þiÈxqÑJø)_?êOÕ «›d3¦ð«œü¬Ú"îzàÕÿY]ßù0‚wË5¬“0{”x[—6‰¬<¨å÷Òä2¦#ŠMÝâ2ž‘I ë4¶ _$z¿F ñendstream +endobj +2225 0 obj +585 +endobj +2226 0 obj<>>>/Annots 69 0 R>>endobj +2227 0 obj<>stream +xÚ}PËjÃ0¼ë+æ˜@íH~Èö1:§B«·\D*‚·’M¿R+šÐ– XØÑììì¼êC•!ç8²dÑ6`DïxÍÒ âuÖ)…¥vÃ\œÉ£ 4¥~0Ê~ð2OkT<-b£ÑýC¾!øÍ]ö Á€•µwt¥¯þ˜±',ÚŒÅÊÂSý ÇéÍmÕ¸ÖÒ9å³ÃüÛ¨^Nz X8ð*Hë(È2î%¿CÙ역@‚õË®C7ôㇴ +;;œ¬4FY‡'y™¤šILªŒþN³¨‚¿/8ob¼Ïäía'endstream +endobj +2228 0 obj +234 +endobj +2229 0 obj<>>>/Annots 75 0 R>>endobj +2230 0 obj<>stream +xڍ•]oÚ0†ïùGÚ T#“”u›ÄZ¨*u[WRiH•›8àɱ™íÐñïgçƒQi•(’9¯ÏûøøØüé!p̓ÀÙ7É{_ãÞù,Bœ™È( Äi?)Öêóå5ÉpÁô¢¿ âߕ6¨´Ã × ¬öQá%©¢.DuÐCu"Á•†d…%œY !×·zlMƒË##߯r=]H®ªx5^£ +dkA¹&´½"V™—Â@‚Ò²HLâœ4¹&*‘t­©à͚ŽŒNV§êƒ¬X·˜C&d+Ÿq5UMå|dzþFA9Iáy[¦yÍÙ¿›|¿9Ä!|C¥à9á6XRǚÛmVÎWk’ÐŒš„;Ës.4<`"ÁڄŒ—êûóÛ_@‹þ”/U«Å œÀ,4ФN­lJw…;nÊ9“„´ÕÒìffB€ùr’ ¹¬”Hh öBõªk)ô‹…ÞŠ°¤‚wìûô/Î×ìd ×í4D‘-Ȫÿ¬®&³†põx?‡¹Èô‹½î¥XJœçD*ø†y™Í;DÞ†¡çډk +ܖð³÷ŸKôtendstream +endobj +2231 0 obj +650 +endobj +2232 0 obj<>>>/Annots 81 0 R>>endobj +2233 0 obj<>stream +xڕ•ooÚ0Æßó)Nì ­;ÿÕmR·–¾Ù¤®¤ï*UQ0!SH˜“hûø=;v@ PQìGw??wgþL(Øø¥0p|H·“oñd¾ˆ€¯qÇâC¼š¥í®þ‘”ÙC™V«¼Ì^g¯WWñïNìvb˳‰+Å/u’ñn׆Ho2ª#m×r©MÂãáåÊ[Ko \Ëg‹1_¯nGI§‹{'²vË˦îP*Ԗ'°fTRD#J Ë÷¼NE¾kòª”;ñÄ&6ZÓÿåeZ´+Ÿå‘æ&=Ù|ÌǑq ÇíP$M®Íɇ"BÈùT½w_ÀØ~Ï×I[4Òõa¸Þà½z_¤Áÿ… ¶œu~É9Üu5šªÛ_€b»‡°…Ð!T¿]×ô"ƒÃ>§j®¸,9™0 å8êŒÔ?“ÒÖ)5–ÎuʔØÞœ¢­7g¨ÈÀœ81Ћ!T…Î00Wæ3 ŽáUõƒ½”ᑟ¯„C=â!býÛIÃy)ÂR]s†bo¾u7Y4”™½Èë.–ûç»E |yZ²Z7¼ŠŸD•‰d»å¢†ŸIÙ&…ŒkQ†ÿm³‡ïT-»TûðkòO?þendstream +endobj +2234 0 obj +666 +endobj +2235 0 obj<>>>/Annots 87 0 R>>endobj +2236 0 obj<>stream +xڕ“Mo£0†ïüŠ‘ö’Hű1¢]UênC/»Rè-/8„Ê@jL۟¿vùhEBÚÈÒx^Ï<~m?Y°þPÏüIaýŒ­E¸âC¼×Ï÷‘q:Kšcý›•Y(šú°›íæóø±Uº­Ò^bäåCÍ2Þf1¬º¤CÚ2ÏUžšœž"g*Ånþý¤<¥m…[^'2?ª¼*û&„ô]¼aÖí”3ØKÎk`B€Ð²FC­d“¨Fêyu` +ì™Ã_ÎK#«¦xŠ&¡Ö¯¬8ŠÉ]ËËD4)‡†lÑ÷D‡ë‘£!tYp²Ñiß"ÎáFԕ¬c #¬OÞ Ä Û;õ—ÚÁŠHˆÌ¥éeï~šu#çoùž5Bõޟmš¬ïH³¥‰–¸kÙau½®à͍°b]&Uš—ÙE +xˆÎÒl˜ÄèY¿ÊêÛv‘ÁñZ Ôñ‡h’AƒþÁ¿|Tߒ÷Ówñ +­>è)¿Š)ùá(Në- »N¶ƒßìpû¿½ c°á×Ã&‚¨Ú«&9ld•IV\Öð‡• ¦®MlßÁf¡ë˜)×¥€Ï¼€{ëyç;‚endstream +endobj +2237 0 obj +453 +endobj +2238 0 obj<>>>/Annots 93 0 R>>endobj +2239 0 obj<>stream +xڍ”ÛŽÚ0†ïyŠ‘zUc|"mU‰؛VÚ.Ù;¤ULH•Í¡íã×vl@$‰ÈžŸ™of~å÷ˆ–s!ÎG_ÃÑtñ ÜɈëyȅp;ŽÛCý=*’U%Äf¼™LÂ_wBg†W·:JDŘ %]–?eºU1yE0òû‰Õé=“Ç÷>ªw+³m&O½rŒuçUÒæ¢hêN1B”"$Ã “) òdy½u\¥‡&- Y†#Œ°œÇñçõ¸/Õ3Ê%,ၬI1¢P XˆIà#fԔËÛ3µ,7x3Å0“#Ð=Ø>5ž.¢ñ½‚º©Ú¸ieª¦„œºƒŒ¹Ìó0²V"ŸfιñÂÅÜÔ¢»¶Ô¦ÝnäÃ~±ýu 54²Åú ât—Ší@³èêޗÿ¢ü]5ڇ´ˆ³v+à³™ÚÌhÿåÂ~nìùïéB„ºŸåÔü#6^ ó¬.{K%fOz3Ò6rð"æukºÐW œf­þGÏ©bµYc·2XÎ÷•L=⫾®Ħ Ò•>Hꈰ,âr›ÉMâ»Òš‚º÷ ,éc«¬­÷7¨«ìl£ÇÓUËù³¸½Ƽc×9pÂïÏÀR>°nª³=ô³MW¾ñ‘C±wµÅ¯óU|{{YúÜ5#ùÍx©Ê¤Šò\T5üˆŠ6ÊTV‡PâK§sO})õ5gf?GÿzŸyendstream +endobj +2240 0 obj +568 +endobj +2241 0 obj<>>>/Annots 99 0 R>>endobj +2242 0 obj<>stream +xÚ¥•]o›0†ïó+Žº›¤Z †u›”­IUiÓº†J»ˆT1b˜Ìu?Ç`h–´Ó”Èüúœç|Á¯ Oÿ£|ð1L–3 SbÜñ¦SâA°FÕ®üŠä†«õp=?ktc×"LëÊ0áÍ®3³iÓg#ZyTp©E¸G-â9ˆ +Q*ˆ¶¡„Kæ|=º:òè8Ñ¹Lªœ U6 +(Õ +jM E•ájUZDg”LÑ>¾æe$ӝJ ¡wÁÀ"¦¤[îo€ù¨vm†œÔs‰ ¶…‹ä°êÛÔ!3£¶qe{ê:·Ìð¹šÁÅèë t5Zí F ¶ôc(bPxQ˜qò¦ÅÐà«1ku/æs¢3-pÏU%…Is†®®gR »"ŠKP„ ë\a3@©dáц½·†eнsd¾·[Œ!¢×t½Ž!.dÃrÇ£4Nù¦Í&Üî'ÒD¡`ÃãT w„^ÚVu0EHr÷uuûÖÅH²´Ü®G{ÇËêG©RU)¾9îâw˜ï²“cò&QVm8¼Ó1OÚxÈöÃÁÌôŒP7^í©«óg!ç]6ßÃ_¸ˆå…Ëÿ°Þš\JÎם¯sã¾âæYYÍ5­7@míçà;øhn²¦³ô2ý^¦õÜîq]ó8¬²®ázú¾9ã‘ú:².-ãÒ`_o¡NÊX±Q±IEr–‚úq: Û³p¾_ÀhY_˱Ì*ìös¶§‡µ…p¯«ÅIˆ–ôÕu§œap%nÇÀ¨ßݝd@Ð X)¹WŒck“¥o +'Úwæ6¯ëûù2€1|z¸[ÁªˆÕSˆ¯¦;Y$2Ìs.KøŠ*Ì´Õ1µ=OíúKÀ˜~ĘÓ|&àÛàœõ'endstream +endobj +2243 0 obj +685 +endobj +2244 0 obj<>>>/Annots 105 0 R>>endobj +2245 0 obj<>stream +xڍ–moÚ0Çßó)NÛZ7Nœ'u›Ô­Ð7íÔ5é‹IH(2%µmûö³c‡‡@‚$w¾ûùü¿ƒ÷K¾1ø68̋Á×xp; û§Òâù>ò ^ çõZ<%lU˜Up­¾kñ¦³ö_«6׊azuwé8šãž/낲Jh0VØòQ(½ÌVZ/å„CŒ|B>~ bγu••LYÆñÀB–,äæãõH ½]L,¯çÉkÛB6p +Q³]™P{Û¶-¶Þ͉Ãç*†ºmi¼&Iƒ¯(´&¨Jx¯)ÿ‡N“’Б1/%ÕÞ=¤šÏu‘Í9ôà °ºøEù96_ÚÅlwo·: ØÓˆ¯´ª93*h«¬ôêÀº”Ò¢\²Ú!V¡äÐJ]¯~{zÚ7„,Ý[› `e šfŒ.ÐQ‘vt¶M²x¬1·É¹Þ"$Ý­ˆ5giFÝMe¬coÕtuü7)ÖùѶÿ˜±y^/(|R¼·›x«/®î™ “à®ë¤fŠy]‹®!t:ǦU>C[ÌGZM‡RþÁŒã‹ÅΪö6 ¾½½D³çèqös u´Í3á”n³œšr¥pŸ‹ò ¿°iy‘J* pÖ׹7_Ân‡î¾þhšÔyÕ +°7[H,“jWýù,“O#™D7M£BmÆl^.vz rZÛ³ä8Í`8/…˜äµX$°=Õ¹†Àq¼öŽʋ uœpFn @äž{@B^ž¾iý0Òí$0’“Aþ»pˆt¯÷“FM¿@T¦ÕŸDNí^.yR” xNXä*êÛŒ|Ûê +œøDžTó˜¸f÷?ÿ[V:†endstream +endobj +2246 0 obj +726 +endobj +2247 0 obj<>>>/Annots 108 0 R>>endobj +2248 0 obj<>stream +xÚ}S]o›0}çW\i/‰´86P ê6)KÔ®,¡o‘"8©'0̘u?v [¡YØ÷Üs÷^ÿt`ýðóf…ó9uæñ%Ò£ŽaˆH“¬©ê[Z«•”¥ÜMvÓiúÃ"}‹œ]`ääcMOÌF1\¶A—X^UûZQÕÔ{e0:D0ŠÎ(ü*ùa7½ÈxžeÚ0ÕHQÛ¸„tJµ±ÀDS0I/d¥P” .N žäZÖĮ¡Q•kVg’W†¢û¥ÒHi:OÖêa}D”YÖHÉÖGeêNMš®à™çyË5ðB<ä/šyÿðµo@³ýŸÑâöˇûøv½L{ ãõXý¦E•¶÷YÞ|0E™›=}ê5º·}=`?®ÞÎ@½ °,𭟧-c°ÈëÒV©ƒÖ7Ã,Ä,›/fn„5º€ÐC^»Éak.M/Oðz*݈ü»FK*2–ߔ߻Y9+Fú_:=âûwAÜ +¶¦Z¥÷/-Úz±H.TÌsÖY²Í㨵á¢|/²Ó~½YÄ)Ì`ù˜la[Õ3• Yž$-ôu«áŽŠ†æ†uFÜf¡‹M¢˜#ß÷Ÿ©÷7çæë4sendstream +endobj +2249 0 obj +480 +endobj +2250 0 obj<>>>/Annots 113 0 R>>endobj +2251 0 obj<>stream +xڕUÛn›@}÷WŒÔ—¤Š7,,7¥ªä6q”‡¨4&o‘¢­Y;´Üº@/ßYvIŒŠ%Ìٙ³3gÎ(Xø£àÛàx°ÎgŸâÙù2êC¼Áˆçûă89Y·U}Ëå/U“–Eýpòpz×X¦±s×"Laïk¾:jAh‚6ՉҢQ!üB-Œ¦®ªäq“fⱁ÷ø|6ÀÃàŒP´ùc©×¿Wå V0«N/ööã8šòBnÛ\M­.Pª‡æŽÙtRRâcü|)êµL»*rÏ,baϟow×ÀD»–Cl 6Ãt¶…RÀjL}‡Pƒ¶=WݟÑÝð˜¡ç*, ìbÇ«ËÞñŠŸDÑ%¨>CSBŽ Ç²À!Öd†=ÂPóò=Á0Äè7!¡Ü€Áà°¡Á@ÿÊ¥äßâíÙXk2ï}7fì41ÎyU‰rDÊØÒÿæÉlÌ=™g‡UÀ‹„ÀÕtïDÓʸWˆ:•žVïëf¯Ëb“¥ë¦†MÙ 9x2êVç}/õAçèiœt⫇#îÕIঞÕ%<ñ"ÉDðªJ‹­bzEf<ÇBúó¯NÖÿų8•q|x_Wx^e=ì]Z¬³6ðAmî\ÝÈÓǁï ^•K½\;²¿±Ã}¢v</e“ÇëBŽÆløì•±Â¯\  ֞ԩQ/¾Zƒð¿ÅßG+X•›æ7G‹d¹•<υ¬á–-ÏTÞ9µ=˜û¶5Ôóæì>3ß´áëì^Î>Þendstream +endobj +2252 0 obj +719 +endobj +2253 0 obj<>>>/Annots 118 0 R>>endobj +2254 0 obj<>stream +xڍ•ÛnÚ@†ïyŠ•ªÁÆë3JS‰6%êEÔ4«REXÀ­tm'íÛwö` ¶ d¼žß3³3ã? +~(8¾üΓΧiçb<Àt‰?ˆÓÅÙ¼ÜäwLäüÛ¦ˆ²4ŸÍz½é/-vµxàYĕ⇜­¸¶Z04F›jOQZHÞ¡ Û}Ïñ\À|Íœ3±ê×€ú>!-“ÇL;8ª—ø±€ósóܬwÙøOŽ£±GbU&<-r­ð€R©} 1p̯DRC‡”èo_ó|."CZ¾L;±0ñÛÓý ¸!ª=Ë!6PÛEw¶…—‚äEL‡P£¶}Ož·jµƒ®Áó$ƒ%&Rq)ïŠkºæ"JW€/X”ÊË,å H2tgCÞÆvC‡X'cku ¶†õC½i{ûقÖ'. [VˆXP¬·ÄÀ„`ÿŽqû6Æ:™[©r£GU(íÌ#ØdX¥ˆ\dMÎÊxŒ×µ1ÆÉ¼JÝZ»úvBOcß󢩩îª|dÛúº´UÒùËáÄïÞÚ?µ“¡ã𐩀Î`#í¹Š˜oøÈ]ÈY¬M¹ÚRÎÄݱ×M—-ãwoPՖ„·{á +¬º»Ê$+˜Õ!f½Æ¯6KÇÛóïgÿՋޟ0Ú'œÃ(γFóQÓO¸€@6Sø>4×±n¦šZ¬`¿}g÷ú-¶*ëÖX¡M¼*õe§·G³L´ ØéƒJYHE ^o«ÖøÔ’a`»&ÿmy +à /NȀí‰S8Žw4†ò‚[&~ײÐôw1Í( еïšu}?OaŸî&0ɖŠÃ1s'²•`IÂE·,-Y,ý¨íà °ÕøwCyËuý6¨UÜ÷Îó)|Ÿendstream +endobj +2255 0 obj +792 +endobj +2256 0 obj<>>>>>endobj +2257 0 obj<>stream +xڕ–aOÛ0†¿÷WœØ@ÔÄIš´bšÖ ˜˜6‰Ñ𠥩Ó%Næ$büûÝ9N mBK‘ªÚ÷úòäì÷Ìß ÿ8ø68DÙà[08¿ž÷!ˆ1âù>ó XGuQÞªDV×I*ŽNN‚§Fé6ÊáÈb.)ïËp)š¨´y“Pg¸ÅƉ£\–D«PÁiAÓBm­€7Ÿ× bL!ÃL¾¢Jªt@ÖÙc^T ®Ü“߯(+85kN.vÊå8ME¦jYgBVe£ç¤{˜~蘚¶"Òð g>fÀéKQF*ÑÏ ÈU0°˜…ºþºûîÕî˜êÏmÓÙ³A ˜uˆ¹ï0nÔ¶7BáF­O†kðFÄàz~ƒg6JÓéghº`%ÀD W¥aYB•7søƒíaö8f:˜Y«;˜R×Ç)djOH*…ÖxûØ\ŽùfÓê^6Û'};°žò9èØ>$´˜u8’V÷"Y^s¸_û4ŒÎioc0ô +Th‡¡RáË>n‹Œt0·V÷q;èmªnæ)ysq›?Ê錭X¨QwZhÓÛô€;QÕJšÐZŒº¦×øK[<ë³ps¹®»BM.A(•+ÖÛ`¶šuåôt÷åJ!X§µI¨ze!¢$NÄb×å1þғ‰\2¸‰µžè£Pʼ‚yÛi;ªÓxT¿vé… 9i㼖 ˜¿à8M1%¼}ÿ+,«+Zفß_œ«aV¤½×Õ§DFi ŸéçôÅV_¶n€­!5·Í畃.:n¾Ý»ââý쌱÷[[ydöæë*/+ê|GgpÔvAV”4ü‰P‹ÁÁÁ7ÝöÕ66Åæ¶žcþk¸¼›^0„ï÷·3˜åqõ¢nU¾Ta– UÂïPÖaJ)†´rèÛÚª3!`š–9\ßE=íNŒIÿ þ(íBäendstream +endobj +2258 0 obj +721 +endobj +2259 0 obj<>>>/Annots 121 0 R>>endobj +2260 0 obj<>stream +xÚuQo …ßùçQ“•B³K–-q–½ùÂj5YZÙ¨f°áËÔ@nrážóÜ/ÂÁÂáe¼í@î É븄مŸRsZÀl'M×aޏnj>ÈÒFYÆÂcY?Æ¥Tc@%¨HM&zþ›÷{äµ牢d ”öô9.ì¡íú'÷¾™l¦7q•Š3KMÕ- KÀ*‘î­/cýFx¶ãqé½óç—ny­S|UÐ*øþ­éa=¯ 2,ÞV ·;~[ßaåÝÞÛaèüˆ{8Ù>šf¼(‘U‹BÅⓔìʺ_Éä“d‹endstream +endobj +2261 0 obj +238 +endobj +2262 0 obj<>>>/Annots 127 0 R>>endobj +2263 0 obj<>stream +xڕ”QoÚ0Çßù'í¦blÇNˆZMbmÙ^¦1Hµ¤*J ͔f‡­¿vœ!Z!¢Äþçîwÿ»øoÖ?Dž(ë} z£©ă`¥w\ÏC.q?ÚmÕÂ@1¢ ,:Ä{{5ÕÉÝ#ui.«ø¸aàÛ"t%÷-Wð"À:ª"Ì È!2ö +œºl÷ýœ¥º“óà4cÕœ˜eÚkk1ýu­Ïg¥®»oËPPèÕVDÉ*q³Xt¶Ù¯a¶MÏN×§d¥»XÀáÙ èåËÉÄu `sÞn/¿€º±á•^“Tå­Þ’ª]Ø´“™eàùÚjûÚnèå~›÷ˆ–6¨~nŦnMg¾1Cþ>!ñO­Œ¸ÊXQU©n t¤ÅuÄ0aü]ÿ…¼HB1ޗ›ƒ9â×Pjޏ±Ì’W‘ª‹,!G}`Ô9߈š¥~?Ëo™¢iL;lÿæò¨PO_uçôWΫ§³³bä'S[24 i3Œ¦ãú¬¥.0¿,ða>™0„û§Ùùªøê3e&óµ ³LH?ÂÍ.LMÈ¡yoèQ|ú 0ÏŸå2'U¡¿zoÀX¨Ÿendstream +endobj +2264 0 obj +574 +endobj +2265 0 obj<>>>/Annots 133 0 R>>endobj +2266 0 obj<>stream +xڕ•kOÛ0†¿÷Wi_ÊÔ;×Fl“:(cÛXĤ*j’)—ÎN?ÇqBÛÜ¥„$~}Îsìׇ¿#˜Žú®ÓÑ×`t~ís!ˆpÄq]â@°¯÷;釲àâ׎gãdz³à–ZZ:µ)±”ô^†[®G)xÕ ÁqV¢ ´*࣒á(£d֕%Î +ˆ6“† +N?eÈ4ßp ¨þ<ž]´ØLS§Ÿ‹í>åY!µÂƔÂ61òÔ¬ +¨EJÃÚ|/[ÀãÍ&ζ +þYÄÞö³,^Ât—ôv†q¶Nöh”O +è\ç"O_‡¿£cõ¼»ž@`ø ÍE¡h:u¨Ï,9‡y"ó–Ye/|ÀY:*…E[ê‡D»«¡[8ö³•Ovî2É%¯·®3áÌÁ9uFæ9h´J©±ê\“ҝm°#Ípƒ¿\ ’TíxbR§¿ú¥â}'Ë]üÂ9Èb2ãhY,Ãz%ëe©€ßÁò€'ƒŸ.L;ìx2ìÓÁkZ¶%»zê5‹’»§)N¤Íp~=«LÆ Õ"Ͳ…øó릥ýa™GÅsˆíçNä[¦)~„Ù>LTÈ©š7u²óۆzeY¦þGÐ8¿GÿxÈendstream +endobj +2267 0 obj +710 +endobj +2268 0 obj<>>>>>endobj +2269 0 obj<>stream +xڍTÛnÚ@}ç+FªT‘&l¼Æ,ÒJ¤¹=´*ç©T‘epå[wm%U”ï¬×N‚1$ ½sfö̙Ë߃¾\†„IïÜï^yÀ]ðWdq\—9à/ûa™ËY 3 –7ôC±è/ŽŽü?ÚÁÒÛ`–r¸•ÁµÕ¯6š\G+S­S\*;sƒö_¢NïDu|WÀ'z:iùA×§rˉÄݦ +¤|õÓâh¼C{8ÔÌ&b]&˜R#là\!ܳ Tçր†{œ¹Ž/P†"ʋ(K•åÒïÌ }Ÿÿf×`ms‹‘ê†KôMƒ™ æ`n;t­F›#¾…® +eÕôlÅÁò<-)T1«âWÌü ‚Vd!0H È(L°„•Èv˜­å )Î{Ùjt[ÍÑõ´Îº-šȳ(U,‰^ªx Šv%k˜0{‹¹«ªúnæºSç—F±¸£˜!±Ië6iê ZÜÑ=Â!KA–aˆRžÞ.\A&…ÈÛہ­.Rã³üð46lú•P²¥¤ª8Ô2Ç0ZE¸ÜnýÌ.‚$÷õ‡( ãr‰p¦èê ló¥5¬­W*ãîìÆQŠãŽåð²êÚ‡€Ï£¯ÚÐfA¸ D30–¿FÜ3·c‡Ó¹ßD1ÂbO…ÔÍÒõzåü¸³×Þ¼`E-µè+Åà3ãJ;8«fŠÇ FëMQ[Žw®xìX¨ÛL+Qê ´B'¯ï8ÿW œ¢øFwÔûõé®ÌžZ'OºÕFu?sÓgè鸘M®|À×ÛéæÙª¸h^§"[‹ IPHø¤e«å9pÍjÉÌaËL,×jv=¬wÉÏÞyÕßðendstream +endobj +2270 0 obj +669 +endobj +2271 0 obj<>>>/Annots 139 0 R>>endobj +2272 0 obj<>stream +xڍ“QOƒ0Çßù÷¸%£ô ´ìqNÑ#Ɨ½­[f`Ì¢ß֔éDÈҦɵwÿÿ/íõÝA z ÜÌuåÜäŽÏä[}Â#$>ä›I&%,ʦžæoÎ]îPBu¡YÐ,é½ €‡‰ ‚ˆaƒ2£ù'_íÀ‹ Z—éTí²>›´hZ©–eÝÈÕd54Œ¸&둇„YRki±¬× ŒtìÄÓQFP Á3„/~!:Òë)RYl’ý§,›Q_?•8³sv&d逯gyUûV>h ©:˜¾ìd6Þ%ŒêÐoF m4Ø&&uÂEs|S\^IŸÂ‹#Û`èsaFä6]Ä9¸°|I2ÈêmûQ( ‰ªwª¨*©x,§¢4š®)t…OMaÈÌcÐþó󳡯Oendstream +endobj +2273 0 obj +320 +endobj +2274 0 obj<>>>>>endobj +2275 0 obj<>stream +xڕUmOÛ0þÞ_qÒ¤©jâ¼We“`Àø°i]>-2­ÓdÊKç$‚ ñßw¶ÓQÒ´tAB®ï¹»çΏϿ{ ü£à™`¹0ÏzAïôzԃ B‹ëyą`џ׫rÊʊ‹)g‹IòÈÓ2쇃AðK;ØÚaèĖ·%[rm5`ÔMª£Õy™,s¾vܦñw'‘»wBmßUp„«“–t}ë0™€£•Šöž)ϗUÆ[UZ–.ä\,ëŒçU©P*¾ƒá‡Vӊ5Hbèˆ#àö%/ç"YUI‘KËUÐ3ˆÇñïßô3Ø>¢Ã"&PÓ$˜.‡Y˜zmº¡hu®vCϑl$Y`;/]ñ +bºÝPV‚³ ªƒ°D¢ÈÈ~®¶oã`®ÝÁU3t}}Júì:h®Š$—<‘ …‚û:Џx‹¥kbäƒY*ôN–QiA«¥ƒe^g÷H²ˆàþOÅK¹Ð\¬bëæ¾ÅØ61ËÁŒºS/"¶P¥Šø”WµÈ ¯5"o««õÛUƒÒC!VäpõíZ®¹…î|ç]ié]΅­TûÇ̚[_¥/7»(¥ -W|žD ÞÞWÞMëê‘e«tç¨z—äó´^p8“ÜNuPl ’ÖO”åö\I“œ;FÞËpk>9ãöc¬^áõ¢ }=ùšOß¡>™?Û„ýå<ÄIÊ!lύÊÊrï5—p kÃùik澙 B=…}Ù1øÆXõΚ‚‰äqÓe\5–ãã­´Oþ[`ª‚æ…ØÌq!µ>áâ æhž}¤»*xní>>>/Annots 145 0 R>>endobj +2278 0 obj<>stream +xڕ“QOÂ0Çß÷)î(½­ëÊ#¢Ó#n3¾ð²@!˜aяïDāf[“kïþÿ_ÛÛ»‡ éA4¿³Ò»É¼A<T-hE>dóNj-ŒŠºêfoÞ]æI!©ä!¹çt%)¢&( eÍùn ƒXbã*J%—ÙnS'y½µn\Tµv¦ÝVC£‰ìàˆ:ºÍR6– VãÕ–>ûñ´±ë‹ ¡À#„O‡%¯AHÿN‘Ø|þ@ŸuY|:ðÈ ^c!à‘¼ºÕ֞¢œ‹vz—{DIÚ?ݘŒwµ6 §#%œ´Æžb²ú´EÝN1ˆMÓ^èkˆŒP,r›Œâ ú0~™¤V‹íGî,L\µtyYZWÃc¾Þåkö¹°ù’ CÍSJ ùž½/iÅÊendstream +endobj +2279 0 obj +318 +endobj +2280 0 obj<>>>/Annots 151 0 R>>endobj +2281 0 obj<>stream +xڕ•YoÚ@Çßù#UªHŽ×·•´Is<´*¢>”*²Ì®Œíî%UÕïÞÙà ø€$´öÎÎüö?¿zLüð-°=ˆ7½ËYïì&âÃl‰;žïÌýx[ðIÄKʾ±¤¤w4ZP6ïÏONf?Õ Gº¦áˆ÷£õE"_M+­[¥}© ‡x +zBË-ËteTҋºöTYÈ3àÛ8¦œpŸ(c93:«­V1¢Y^4_ÅÑWòp)/hœ,º¨Kí—A7ÙõS´)ÒÎ~“dqº]P¸xgÊ©±þPëÌÚ#&·Ù§i’Ñó–QðÒóú#Zÿás›«EÝ´š:¯#Vù,’'šòï ­õ†a¾NGfĄ‚·{£¦ÛÇ2g0ï à=˜çR ¸ÐW0D„;š¬Ö¥Þ9=Uyßñð§1 ‚«á¸ƒ>–2ht¥É`—áò7V֘²OÈмÒßÎ*šR +£”獞%º M1ßD'n 0ÅdëTõ`͚­`·ë\{?WiÎiÕ­±\#ž‹„íÑLMÉ0WníÄÿRÐì`xâƒTñ­€T7_ 0Átí‡V ep+ ;$Ge@Ôÿƒ¨ŠIWjÃap°ì« +3dúÈ):ëÃÖV<†pvèB"–^ F¿ǓÑÍ †pu?žÂ4_–þ!ŒY¾bÑfC‡ÏQ¶Rát(N}ˬ׹ã;È$_»¾¾é×Þ?OCjendstream +endobj +2282 0 obj +776 +endobj +2283 0 obj<>>>>>endobj +2284 0 obj<>stream +xڕT[oÚ0~çWiÒmqãÜHD7‰®·‡MbjcªÜ`’L¹0ÇQ;Mûïó%´%$À BÆç;ǟÏåûÕÃ`ˆ˕ß0ë]½óð‚•°¸£r!XöÃj]ÎHÉ)ûÆN§É3MËE1?µ‡­=†Žléq_’ˆj«~m4±Wåeåt)íâÈÛs‹<~`êüÃ‰Ø5¡umn0& NÖ*ܺ¦4x¼ŒwjYú-UÍy©`,Ø0¨:”a£‘!ޝh²d͓"—–ë g CÔäågv ¶'Ўa!°ƒEPÓ[FaÞƾ/ޥѦå!ç Z×®ù9’ƒíù’…Ȩ⥢+^ALAgJÎ(ɀð$‹"6h?UÛ³q4Un¡ª ºž.“.^ Ke€%áä…â!~®)bÍO¡;ù‰ˆª tŸ´ðË«ìQd±XÁãoNË£IÚ¦|4I…n­÷kÇZž£¹Î(¯X^÷ë¦ätººWÛhKΜæ¨s ,§~'ðÙPéë ‰\ "嚆É*£¸]i²ÝŸÝÄ®ŸI¶N;¥è]’‡iµ¤p!ٝë (þؐ‰Æß$绢‘&9·HÚ«vÕKJØ>`LÉRáõ¦ ÝÖµzéùîaßüÑt@íN£0wêڅԅ3x¯IÔØcU0Xôeàc• ¸¨Ÿ€ä w4‰b^[NOuÙßDø³#͉tô”¢^+þ[—²›§”}vŸôWw‰·ÑpÓ×R–«Ùä&€!|ºŸÎa^¬ø36eEÄH–QVÂ’W$•†Òo82•8ž<²mKKœR˜¤eQOÿ×Þ?Àhù¾endstream +endobj +2285 0 obj +654 +endobj +2286 0 obj<>>>/Annots 157 0 R>>endobj +2287 0 obj<>stream +xڕ’Ao‚@…ïüŠ9j"ëÎ ­-í¥©š^¼] ˆ]0íÏïl³•ˆm›Ì2ûÞ·Ãût8=¡O¢rîrgœÄ€>ä+ú"#dòå S +&eSóç!w8ãtÐ,h–ôÑ EPAÄYh‹2£yѯ×0N|@´.O­ä²Øïš´hZ¥§eݨù`>¼jI";8¢ ˜¼fÉ­¥Å²^#0Ò]°ˆ—Úö2`ˆ ‚†ÅoAHÿN‘ªbùD¯Ò½,‚Y¼o„€ÿM2Û|«²9t5£þˆøœ¸è‡¡`¾­®fÄ´›kœ%ã]oZu>.Å8‰lºPH#ò"‘ût’äàÂôm–AV¯Ú¯B+˜éz­‹ªRºçb»/J£éšƒn(øeúýÐ ìw;ˆí]_“ŠÅ™endstream +endobj +2288 0 obj +317 +endobj +2289 0 obj<>>>/Annots 160 0 R>>endobj +2290 0 obj<>stream +xڍTێÚ0}ç+FÛ¨ äF€n[‰¶°O­(„>!UÞd®›ÚÚ¿¯ › ˪Jd%ž™3gŽgü»ãk‚ȾIÞùw†‹)xcˆ3c‰Æc'‚8í&ǃZ£<¡Üv·½^ü«t K·ÁÈuBë¶Qd‡¥Õ…ieô½ +Cp¥!Ù o­1y®3ißM·½û«AP¬P%W¥=Ï«ÓD%‡å%hzbFŽLƒ*'9:7Ñ¿ J$=h*x]ÇU†—Ĩ‰tA–ü€üˆ¡±TÒBb +”¥‰¦ 0‘š’•-p|K„ðΔ1xDâ,©ÖÈ͞Þš¿c6žój Jãkچ`ЦªœrC2“"/ŠËcâLùîÂU½³°þè Ís +j‹ÏçÍrýs=_ý˜¯Úz"?Q)xŽ\ÉHJö[Bø·‘Ë*¿mÛÀ)•˜hzB+µ¾D’¦F©cº6kGfôšBРPK¶J÷áÎ*Âì÷]«ïVºóæH~`7§ç å ;¦ï-¯¡]œýÇֵǪ1qåñÝ¿PñxÞ·‡q3¦„u˜Ç×qͅbÏ.«û¾˜5‡ÉÈU? Öö®iùË4ÛÐ÷/ãö€zI”: ™Ö ûbº©×ÈçS'¸•ЭV¤ŠLýâ¯I6êiX®a†‹IÅ;t `8-o“ÕlÃl{ÃZdúL$ÂRŠ$yŽRÁW„ÝçG0û® Œ\»†¸/Èü½ó„a’xendstream +endobj +2291 0 obj +592 +endobj +2292 0 obj<>>>>>endobj +2293 0 obj<>stream +xڍTßoÚ0~ç¯8i/0'!!ê4‰2í¡ƒôiìÁ xJìÌ1]»¿~ç86 kA²"ßwwŸ¿ûñ{@ÀÅ?È?„´|N“e $‚$CKENÉn˜Ë*aE¹ä9Û·£QòË O]'0Àۊº7F4QTÁ{cÅKâ:³—¡-$ÃoA ö¡ƒ…§?.4 l¯ÛÑÕ B¾osÎÕþX0¡+‹˜!NŒ †u 2'Âx½`Uªx©¹Ær \ÇEÅNÇú+3DOIࠎ®‹9=×ñ@1Øô€I;~ƒöf±9OèZú ¡75‚8¶Ïnå¨éÕIjzɁÑ‹¦š)¨´âbZÂAæ;ÐhÔ(«TT=BÁùÿ;‚ØÇŒo}‡E÷¼Ã²b[[£îÿË@f5Ֆ`û .àîQ³ê5‘)ó› ×è^áϝÐò^3}T¢é›¶0¦›Ã¦i ”؃(=jÞ¶¼E=«ØÙyè\lÓN«C=IØ?„§à°g‚)Š¢í)=dRÕR[7ÚºMè¢ìFÛqÅR-1Bãw¾¨J–òŒ³Ö¨PåDŽç'-’›ÕâÛºž‰{®¤0SȀӻœ]–çúe~q±¼ã"͏;Fs8‡OåÑÝ;fÓ´âüð¦áÏ«WžÉZQuËì|³öѬy.ñB˜ºÄ–q±ž/×ÛÕ62Ó(öáJɽ¢EÁT7TinBŒç8òê™Ù0ó¼’Æà›ÙQ +I3#ßÿÈö‰Oendstream +endobj +2294 0 obj +598 +endobj +2295 0 obj<>>>/Annots 163 0 R>>endobj +2296 0 obj<>stream +xÚ}S_o›0çSœ´—dZˆ u›”-M5©›²@Þò⁓x›Ù¦i¿ýl +!eÁÝýþÜ È\üÐÞiá|Iœéz8‚ä`"a¹!$Ù(­JµSTîGûñ8ùÝ$MÒd†ÜÀ&í9Ò&Š`Ñ=Ü"®4¤'"á½Í1!ŒÜù5ø“`Ù~|wÃàû ȖêJrÕÄÀøB6 +–P +Æ5• è…´’’r •ç¤  $\6Õ£»ÇÇkÀ°C]m«àÛ +˜‚ŠgôÀ8ÍÜAq+ªRÉJÍ¿¦è¼íã+©lÌÕ̵V¢”HÑ4ƒ3Ó§CVQ¦®Ò&ýz©SzþŽÖtõ Bõ¢4-.Ãð]¯VHò|Øãý3)Ê|pÈïOó*£ðѝÚÃ=}?ýÎbXWwÿO¯‚n#‡÷%¦–¹6á>q‹Ì¾ÛÛcû`_ÀGž±^À|æÎڗbû+ôòåº[ç£Kˌ–ª7f^g!ÿµúMÂî0â 2ÏJÔR¶²Z®õxo…Õ"b*Ÿ^wëjºž·êd@6=]m—ë&ðu·‰!}&’ÂFŠ£$EA¥‚ï„W$·¨ì…0‰>>>>>endobj +2299 0 obj<>stream +xڅ‘½nƒ0FwžâŽÉµÁØ0’6éT)g˂¨Ciù«1j¿v ¨AU+Kî=÷Øþüá`@za`>ŠÆÙqçîfÀ/ºCó(ð—Í«Rý®îŠ÷ª-ϛóvËß,H,è†È#< y)LW×±µD–c#Z5Ø©06SØ73n€n)á{LkuùA …¬zUu­é칃<¤o½lé#HÓ!¡Zd'µÙ) ûö‰9p¦™ÿI[u/jæ¡ÌlÌ <ç:ÅE"ß>:j”í06‡¸zóÎþ+oúzp&$õÐÙ|£%_ +>(º*ÓäÀÁ…ûÓ1ƒ¬»¨Ï\_ì(»RæM#äOy;æµQ¸fÒe>Z» #Úv-Ó`úgçÎ\Žendstream +endobj +2300 0 obj +294 +endobj +2301 0 obj<>>>>>endobj +2302 0 obj<>stream +xڅ‘?oƒ0Åw>ōɀkƒÁ0Ò4éT)²eAÔ!iùWcÔ~üžã€’¨j…Åp÷{ïìwŸŠ?4§lœÇÜyØÄÀäì„Bò·ÅQë~u”åÇ~±_.ówKqK¹%ÜP»¡¨¤ébs[KT56²ÕƒUÀ˜Q1Ïh\ŸÞRb1#m±ü$‡Rz}êZÓYç%¯<ÿÒgàÒÑÈ*ÑÙ%!ûö¸8тÄÒÖڏgkAè?ÎØ8Ïðê%.yöѩԣj‡K`Sˆwo¾ê¬¿‹¦¯ïΤ„¤:›o4ç‹+ÅAÑÙ2M69¸°Úm3Ⱥƒþ*ðb[ÕUªh©x)Ú±¨…k”®ðÎù‡Ü”8÷í:®Gá.^Ò%Œ_endstream +endobj +2303 0 obj +293 +endobj +2304 0 obj<>>>>>endobj +2305 0 obj<>stream +xڅ‘½nƒ0FwžâŽÉµÁ`i:UJÁÙ²X‰C©ø« j¿v ¨EQ+Kî=÷Øþüá`@za >œç‘9Y˜»êND©»lކ¡ßՂˬõE6§í–½[–XÖ ‘G {T¼¦«k„ØZ*˱í ìT›)ì›7@¿)á{TkuùI¨³¬ú¡êZÓÙ3yH_|Ùòg ±¦Ci‘Ôf¤€âìsàLS/ù“¶ê YÔÔCÿ˜'ؘxŽvЋľ}t.†Q¶j +lqõæýoúzp!¤µêl¾ñ’o>(¾)ó4càÂîx( è®Ã'×;È®”¼i„TðÂۑ×FášI—úhí&”hÛ­…Óo¼:ß4|*endstream +endobj +2306 0 obj +295 +endobj +2307 0 obj<>>>>>endobj +2308 0 obj<>stream +xڅ‘?oƒ0Åw>ōÉÅ`lištª”Ù²X©CSñ¯¶Qûñ{Ž J£¨ÃÝï½³ß}zBüÄ̞Cë=VÞÃ&¡:b‡q0¨ÞïÆ «¦×r¿Ø/—Õ‡£¨£ü$ ¨¥vZÔÒv±F©«åª[ÙíT bU$²?S" 8ÚbùIêƒ: æÔw¶³®¼0ñÊó¯xš"P†FN‰Î( å8¢và…æAö'í¬ãl¶æAøó[羄:ÅEÓÈ=ºfTž»„xóæ«Îú[´Csp)%äî]¾éœ/®¥gË"ßTàÃj·-¡ìæKàŶª¯•h[©4¼ˆnµð­ÒçÑ9Æl‰ÒØ­ãzîâÕû +Œyendstream +endobj +2309 0 obj +293 +endobj +2310 0 obj<>>>>>endobj +2311 0 obj<>stream +xڅ‘Aoƒ Çï~Šwl:P=º®ÝiI§ôÖ qÔuQtˆÙ>þ ¨Ù̲…„Ã{¿÷þ¼{YhQUëÝ3ïÀ.¦“P$À^6¯Z÷»NJQéóæ¼Ý²7ÇÇù1 +ˆåN¯…íš!®–«zl…Ôƒ›Šc;…C;ãGè'e!œá€­)?ˆ¡R×^_;i;{桙K/[ñ$5tL#r“Æ‚Pþ‡Ä8Ó4Èþ¤:Ê5 Ð?æ ¶æžcâ"iè]=*9LÍ!®Þü­³ÿäm߬.…€¼:—oºä›@dJoÊ"?0ðaw:–PvýÁÍŎª«o[¡xâräUøvÒ§!Z» %Æv+'túgï üò¸endstream +endobj +2312 0 obj +292 +endobj +2313 0 obj<>>>>>endobj +2314 0 obj<>stream +xڅ‘?oƒ0Åw>ōɀ‹Á`i“tª”Ù²XÄ¡©øWÔ~üžc@iTµÂb¸û½wö»‡‚‡… 2§lœÇÂyØ%@9gìDœ“ŠÓêmú,»“ŒØqu\¯‹w 2 º¡G˜ZTÒt±Æ˜­¥ªÙÚªB Ô¨¨o4nàý¤ DJ8Úby#u©.ýpéZÓÙŽG<¼õò˞ÅH‡,B#«Dg”„üØgfàLs’üI[ë Y¬9ñþqž`ã¼Às®S\,öí£39ŒªÕS`sˆwo¾él¿DÓ×÷çRBZëÎæ/ùâVqP|µÌÒ].<ö9äÝyøx±½ê*%šF* /¢Em,\£t¹Í?ŠM‰±À®ãvîâÕù¥E3endstream +endobj +2315 0 obj +295 +endobj +2316 0 obj<>>>>>endobj +2317 0 obj<>stream +xڅ‘½nà Fw?Å“Á.` öè6I§J©ílYPJÜTþ+`µ_ŽÕZU+$†{Ï=ÀÇ{€مˆœÚྠ+îv`ÕÙvçƒêeõj̰‘4ò¸:®×՛ǨÇÂEÔa-j麶F©¯åª[Ùí§ÀØMaâfÂý¤„3q«µåÔ'uÌ¥ï\g[(BöÎóV<M-PfE~Қ ( å/0¡îÀÍ£ìOÚ«ãlVóýcž`gžá[ªS\4%þх4£êôØ-Äś¿u¶Ÿ¢šeÀ¥”7º÷ù¦s¾ b{PzUù®‚ûÊþl>„½Ø^õµm+•†'э¢qŠÐM†œ ¥›rjm×2˦ßx¾ùüCendstream +endobj +2318 0 obj +292 +endobj +2319 0 obj<>>>>>endobj +2320 0 obj<>stream +xڅ‘?oƒ0Åw>ōɵÁ`iK:UJÁÙ² âÐTü«1j?~Ï1AiµÂb¸û½wö»O‡ÁB™SµÎ£p6 P∝ˆs/qX½k=d]ÕdÄö«ýz->,È,è†Äc܍e-MkŒÙZªê©•­*JŠúFãä7e šP£-–ŸåX©Ó O}g:™pˆGðÖË/#²¬}PŠ;°ÏÌÀ ͽäOÚZÉbÍ=òó ç¾ä:ÇÅbß>:—zRÝ8v ñæÍWì»l‡æ6àBJH›±·ùÆK¾¸UŸ-ót#À…§Ý¶€¢?ê¯/¶U}­Ê¶•j„ײ›ÊÆX¸Férÿœ?'¦ÄX`×q= +wñæü¹@6endstream +endobj +2321 0 obj +295 +endobj +2322 0 obj<>>>>>endobj +2323 0 obj<>stream +xڅ‘Ooƒ ‡ï~Š÷Ød€(zt›ÝiI§öÖ é¨ë⿁fûøƒ¢f3Íïû¼ðãÃ#€Í"À)œï¾ôîv åÙt"ÎQåëæmúL©N7Çí¶|ws”bÄ,uТ’¶kjŒ¹Zªª±‘í ÝT„Ø)BíŒàߔ…HB7ZS~”ú¤.ýpéZÛÉJ#l®¼lù°ØÐ!‹ŒÈM3%¡¸SfœiŽ’?i§’EÍþÇ<ÁÖ¼Às¨S\,¦îѹFÕê)°9Ä՛t²/Ñôõ:àBJHkݹ|ã%ßsP|Uæé®ûŠî<| +s±½ê*%šF* Ï¢Em¾ô9Åk7ãÌØ®eN¦ßxñ¾VŸŒóendstream +endobj +2324 0 obj +291 +endobj +2325 0 obj<>>>>>endobj +2326 0 obj<>stream +xڅ‘?oƒ0Åw>ōÉÅÆ`i:UJÁÙ² Ô!©øWÔ~üžc@iµÂb¸û½wö»O‡€ 2çÐ8ÂyÈ Ä;ç^â}u†>«G}Ú¯öëµø°³”ú3ÔN—•4]¬1fk©ªÆF¶ƒ¶ª1*BÆ üߔHB<޶X~–ú ÎýpîZÓÙÇ÷|¼òòË_€ÅH‡,B#«Dg +JBq¦Ì œiî%ÒÖ:Hkîùÿ8O°q^à9Ô).Sûè\£jõØâ͛¯:›ï²éëۀ )!­ugó—|q¥8(¾Xæi&À…§Ý¶€¢;_%^l«ºJ•M#•†×²ËÚX¸FérzɟSSb,°ë¸…»xs~zŒ‚endstream +endobj +2327 0 obj +293 +endobj +2328 0 obj<>>>>>endobj +2329 0 obj<>stream +xڅ‘½nà Fw?Å“ÁllìÑm“L•R›lYPJÜTþ+`µ_¶ÕFU+$†{Ï=ÀÇ{@ÛE€E§pjƒ{Üms øÙvRÆP +üeõj̰“æ¸:®×üÍ3Ô3a‚uÌA‹Zº®­Qêk…ªÇVvFû©qS$r3aŒR"9AÌjmùQꓺ æÒw®³áFØ^xÙÊÐÌÒ M­ÈOZsJBõ QwàL3”ÿI{uœ/j†ð?æ væž#â¢Yä]J3ªNOÍ!Þ¼ù[gó)Ú¡¹ ¸’ŠF÷>ßlÉ7…Ø”]•e±åÂÃa_A՟͇°Û«¾V¢m¥Òð$ºQ4NºÉEøÖMµ¶k™ÅÓo<_[Œ endstream +endobj +2330 0 obj +289 +endobj +2331 0 obj<>>>>>endobj +2332 0 obj<>stream +xڅ‘?oƒ0Åw>ōɀ‹Á`i›dª”Ù²X©CSñ¯¶Qûñ{Ž J£¨ÃÝï½³ß}zü(D‰=‡Ö{¬¼‡u”CuÄNÂ9I z[¼3l¤ÑûÅ~¹¬>ÄäÇaÚiQKÛÅc®–«zleg´SÅ@©UÑÐjü(øMYˆf”p´Åò³ÔuÌ©ïlgUy ðÆó¯ØK‘ŽY‚FN‰Î!( å8dvà…æ$û“vÖQ6[süã<ÁÖy†/™Nq±4t.¤U§§À.!Þ¼ùª³úíÐÜ\J y£{—o:ç‹ÅAéÙ²È×øð´Û–PöGó%ðb[Õ×J´­T^D7ŠÆZøVéóðœ?g¶ÄXäÖq= +wñêý+ðŒendstream +endobj +2333 0 obj +292 +endobj +2334 0 obj<>>>>>endobj +2335 0 obj<>stream +xڅ‘»nà †w?Å“Á.`lìÑm.S¥Ôv¶,(%®+ß +Xíã‚mµQÔ +‰áœï|Àχ‡™…c8·Þcé=ìRÀ ʋéČ1”¯«7­‡½Ð®E¡eÝU§Õi½.ßMíG( –>*^ Û55J]-“Õ؊N+7Æv +;ã‡è7e!œâ€­)o„:ËzÐußÙζôP€Ì՗-ßM ÑØˆÜ¤1Š;0¡öÀ™fAú'íÔaº¨Y€þ1O°5/ðîMˆ{t.ô(;56‡xóæío‡æ6àBÈÕ»|“%ßBsPrUæÙ®žŽ‡Šþ¢?¹¹ØAö•äm+¤‚gލ¼± +ßNúŒ [7eÔØ®eM¿ñâ}ìendstream +endobj +2336 0 obj +297 +endobj +2337 0 obj<>>>>>endobj +2338 0 obj<>stream +xڅ‘Ënƒ0E÷|Å,“ƒÁ°¤ÍcU)g—•:”ŠWQûùǀҨj…ÅbæÜ;ö‡€06çÜ8ÜyØ¥@ð vbƼøëêMë~/õFhÉ«FžV§õš¿[–Z֍|ö8ˆRš.Ö(µµL•c#[=XU„ ŒÆ ýŸ”HJ<†¶XÞÈᬪ^W]k:[îøž_~ùh‚tDc4²Jt@I(~jÎ4óÒ?ik¦‹5óüœ'Ø8/ðíMûè\êQµÃØâݛo:Û/Ñôõ}À…”ÕCgóM–|q±8(¹ZæÙŽƒ OÇCEwџ/vP]©DÓH5À³hGQ ×(]\óg±)QÚu܎Â]¼8ß㒎±endstream +endobj +2339 0 obj +296 +endobj +2340 0 obj<>>>>>endobj +2341 0 obj<>stream +xڅ‘½nƒ0FwžâŽÉ€kƒa¤mÈT)²eA‰C©ø«1j¿v ¨EQ+Kî=÷ØþüáÀzà¼Îó˜;I„C~՝€s@~Ù¼)Õï…J*Q_N›Óv›¿[YÐõ1b<E)LW׳µX–c#Z5Ø)1S„š×ÿ)‘ˆ ®µºü,†³¬zUu­éìr#¬o½léX¨iŸZd'µ™‚Ý)3Î4Gџ´U{Ñ¢æÿcž`c^à9×).RûèT¨Q¶ÃØâêÍ?:»¯¢éëuÀ™×Cgó —|ðôAáM™ÆI.<dÝU}úbٕ²h!x)Ú±¨Â5“.§xífœiÛ­Ìùô¯Î7¨óendstream +endobj +2342 0 obj +293 +endobj +2343 0 obj<>>>>>endobj +2344 0 obj<>stream +xڅ‘?oƒ0Åw>ōɵÁ`i›di¥œ- J’Š5FíÇï9”DU+,†»ß{g¿ût(ü(‘9‡ÚyÎÃ:ÊA±qîE Þ'­»Ô/²)õi¿Ø/—âÒ̒nH>>>>>endobj +2347 0 obj<>stream +xڅ‘Ooƒ ‡ï~Š÷Øt€(zt[»]–tjo½–º.þ`¶?(jV³l!áð¾Ïû?>< È, Œ@ññîKïn›fPžM'f,ˆ¡<­Þ´îŸ?V‡õº|wu¡€Zh¯x%l×Ô(uµLVC#Z­ÜTÛ)L쌢[ÊB8Å3ZS~ê(/½¾t­ílJÈÜxÞò' ‰¡#‘›4fR@ñ L¨=p¢YþI;u˜Îj Ì#lÍ3>>>>>endobj +2350 0 obj<>stream +xڅ‘?oƒ0Åw>ōɵÁ`i›T*¥@¶,VêP*þÕµê§ï9”FU+,†»ß{g¿{w(ü(‘9ÇÆ¹-œ›m”CqÂNĹAñ²zÕºl+]‰ºú’‡Õa½.Þ,Ê,ê†ÄcÝ¢”¦‹5Æl-UåØÈVV¥FE}£qò“2M¨ÇÑË÷r8ªª×UךΦpˆGðÞË/{#²¬}Pò_`Ÿ™3ͽäOÚZÉbÍ=òóçž“âb±oI=ªv˜›C¼zóEgó)š¾¾8—Òzèl¾ñ’/îÅgË,ÝàÂÝ~—Cޝô‡À‹íTW*Ñ4R ð$ÚQÔÆÂ5J—ûçücbJŒv—£pÏÎ7žbŽ‘endstream +endobj +2351 0 obj +298 +endobj +2352 0 obj<>>>>>endobj +2353 0 obj<>stream +xڅ‘MO„0†ïüŠ9îÀ¶ +GÔ]OÆØÛ^šµ‹kø²-џoK(1’fžy¦}y÷0 óa`Â΍w[z7û0ƒòb:1cA åËæUëþ©××®U§Íi»-ßGçG( –;*^ Û55J]-“ÕЈV+7Æv +;ã‡è'e!œâ€­)ß u–×q³íìJÈ\z9ò ‰¡#‘›4fR@ñ L¨]8Ó,Hÿ¤:L5 Ð?æ ¶æžcâ¢ qÎ…d«¦ÀæWoþÖÙ}ò¦¯×B@V«Îå›,ùÆšEɨ̳} >ÜÝEps±ƒì*ɛFH¼xm¾ôAk7eÔØÆr‚§¿ñì}C’Öendstream +endobj +2354 0 obj +291 +endobj +2355 0 obj<>>>>>endobj +2356 0 obj<>stream +xڅ‘?oƒ0Åw>ōɵÁ0Ò6éT‰Ù² Ô¡©øWÛ¨ýø=Ç¥QÕ +‹áî÷ÞÙï>< +? +alÏ¡óî+ïn›P± ÄP½®ÞŒóA›ýj¿^Wïâò#p ítÝHÛÅ箖©fêdo´SE@©UQf5~H~R¢) ÚbùQêƒ:æ4ô¶³©<¼ñò+ž€'HG>>>>>endobj +2359 0 obj<>stream +xڅ‘Ín„ F÷>Å]Î,´€(º´íLWM¬:»Ù˜)Zÿ +˜öñ ƒšÖLڐ°¸÷Ü||8^?„KçÜÎÝ1Ì ¨t'dÌ ¡xݽ)5¦¢éUuޝ÷ûâÝbÔbn€:ãj½œ[BܼùGçðUvc» 8ç’V6ßhÍ7_]•Yr,À…‡SšC>Tê³ÔKÅP‹²ë¸ð\öSÙ…k&]FÐÖMÕ¶k9òçßxq¾<~_endstream +endobj +2360 0 obj +292 +endobj +2361 0 obj<>>>>>endobj +2362 0 obj<>stream +xڅ‘?oƒ0Åw>ōɀ‹Á`i›tªDlY¬Ô¡©øWÛ¨ýø=Ç¥QÕ +‹áî÷ÞÙï>< +~¢ÄžCçÝ×ÞÝ6Ê¡>b'áœ$P¿®ÞŒ‹ÉìWûõº~w sŒ„Yf§E#mkŒ¹Z®š©“½ÑN¥VEC«ñ£à'e!šQÂÑˏRÔi4§¡·Mí$À /¿ò XŠtÌ4rJtAI¨~Cf^hN²?ige‹5'Á?Î3løéKC÷èRšIõzìâ͛¯:›/эímÀ•”·zpù¦K¾¸P”ž-Ë|[ƒ»¢‚j8šO+ÔÐ(ÑuRixý$Zká[¥ÏÃsþ)³%Æ"·ŽëQ¸‹ïg+‹¼endstream +endobj +2363 0 obj +291 +endobj +2364 0 obj<>>>>>endobj +2365 0 obj<>stream +xڅ‘½nà Fw?Å“ÁllìÑm“N•R›lYPBÜTþ+`µ_ŽÕZU+$†{Ï=ÀÇ{@ÛE€E§plƒ{Üms øÙvRÆP +ü´z5f(¥8V‡õš¿yˆz(L0¢ÚkQK×µ5J}­PõØÊÎh?•!nŠDn&ŒñOÊA$'ˆY­-?J}T—Á\úÎu6<ÀÛÏ[ù4³tBS+ò“ց’PýGÔx£Êÿ¤½:Îg5Cøó;ó ß2â¢Yä]J3ªNOÝB\¼ù[gó)Ú¡Y\I E£{Ÿo6ç›BlʮʲØráa¿« êÏæC؋íT_+ѶRixÝ(§ÝdÈ"¼tSF­íZΒé7^‚/%'Œjendstream +endobj +2366 0 obj +290 +endobj +2367 0 obj<>>>>>endobj +2368 0 obj<>stream +xڅ‘?oƒ0Åw>ōɀ‹Á`i›tª”‚³e±¨CSñ¯Æ¨ýø=Ç¥QÕ +‹áî÷ÞÙï>< +~¢Äžªõî…w·Í€rGì$œ“Äëê͘¡PUßuª2‡Õa½ïŽdŽôã€0KîGY+ÛÅc®–ëzjUgF§ŠR«¢¡ÕøQð“²Í(áh‹åG5Vú4˜SßÙÎFx ðÚ˯x–"³œCÐ +Ê_àÙš“ìOÚYGÙbÍIðó [ç¾;ÇÅÒÐ=ºPfÒÝ8v ñæÍWÍ—l‡æ6àR)ț±wù¦K¾¸V”ž-‹|+À‡‡ý®„²?šO‰Ûé¾Ö²m•áYv“l¬…o•>Ïù§‰-1¹u\Â]¼xߨ"Ž&endstream +endobj +2369 0 obj +295 +endobj +2370 0 obj<>>>>>endobj +2371 0 obj<>stream +xڅ‘½nà Fw?Å“Á06öè¶I§J©M¶,(%n*ÿcµ_ŽÕZQ+$†{Ï=ÀÇG@ÛE€Sˆ86Á½î¶âd; ç(ñºz3¦/U/µ4ê°:¬×â݃̃aŒsà~•r][cÌ×r]jÍà§b ÄMêfÂÿ¦D2‚¸ÕÚò£Žúܛs׺ÎFa{ëy+ž€¥–ŽYbE~Қ)hå ˜2wà•æ(û“öê(›ÕáÌìÌ3|ÍuŠ‹¥Ô?ºPfÔí0v qñæÍ—lúzp©äõÐù|Ó9ß"{PzQùV@û] ew2ŸÒ^l§»J˦Qz€gَ²vŠÐM†œâ¥›qfm—rʧßx ¾绎%endstream +endobj +2372 0 obj +293 +endobj +2373 0 obj<>>>>>endobj +2374 0 obj<>stream +xڅ‘?oƒ0Åw>ōɀ‹Á`3Ò6tª”Ù² Ä¡Tü«1j?~Ï1AiµÂb¸û½wö»O‡‚‡… 2çÐ:…óÆ@9'ìDœ“Šãê]ë!—:­esܯöëuñaAfA7ô3àn,+iºXcÌÖUM­ìôhU!PjTÔ77ð~S¢1%m±ü,ǃª]÷él +Ç#Þzùe/ÀÒ!‹ÐÈ*ÑÙ%!¿ûÌ ¼ÐœÄÒÖ:ˆkN¼œgØ8/ð%×9.&|ûèLêIuãØ%ě7_u6ße;4·çRBҌ½ÍW,ùâVq8[fIZ€ O»myÒ_%^l«úJ•m+Õ¯e7•±pÒåþ9!L‰±À®ãzîâÍùo±—endstream +endobj +2375 0 obj +295 +endobj +2376 0 obj<>>>>>endobj +2377 0 obj<>stream +xڅ‘Ooƒ ‡ï~Š÷Øt€(zt[»Ó’Né­â¨ë⿁fûøƒ¢f3Íïû¼ðãÃÀÌÂÀ„1”wϽ»} +˜?›NÌXݼ Cϕ(åisÚnù»£¨£üÔRG-*i»¦F©«eªÙÚME€±ÂÄÎø!úMY§8`FkʏR—êÒ—®µ÷P€Ì•—-š:¢±¹Ic& $7`Bí3͂ôOÚ©ÃtQ³ýcž`k^à9Ô).š÷è\£jõØâêÍ?:»/Ñôõ:àBJÈjݹ|“%ßBsPrUæÙžƒÇCEw>…¹ØAu•M#•†gю¢¶ +ßNúŒ µ›2jl×r’N¿ñâ}=Œáendstream +endobj +2378 0 obj +291 +endobj +2379 0 obj<>>>>>endobj +2380 0 obj<>stream +xڅ‘Ënƒ0E÷|Å,“ÔƒaIÛ¤«J)]6VâÐT¼jŒÚÏï8”FQ+,3çÞ±ï|:~‚ÈœCã<ÎÃ6Ê¡8a'â܋ 8®ÞµîËþ(´Ü¯öëuña1f17$3X9ˆJš.Ö³µTUc#[=XU”õÆ ÈoÊ@4¡G[,?Ëá Î½>w­él +‡xï¼ü²`1Ò!‹ÐÈ*ÑÙ%!¿ûÌ œiî%ÒÖ:Hk'Ø8/ðœê‹}ûèLêQµÃØâ͛¯:›oÑôõmÀ¹”ÖCgó—|q§8(¾Xfé¶žÊ]ywÒ_/¶S]¥DÓH5À«hGQ ×(]î_òOˆ)1Øu\Â]¼9?ðόãendstream +endobj +2381 0 obj +293 +endobj +2382 0 obj<>>>>>endobj +2383 0 obj<>stream +xڅ‘ÍN„0F÷<Å]Î,À +…%êŒ+“:q3›fì †?Û}|Û)%FÓ¤‹{Ï=m¿¾{YhQçÖ»eÞÍ>L]L'¡4H€½l^µže­ÅisÚnٛ£ˆ£üÄRGÅ+a»¦Fˆ«å²[Ñiå¦bÀØNáÐÎøúIYg8 FkÊ÷Be=èºïlgÇ< såe+€¤†ŽIbDnҘCÊ_àØgšٟ´SGÙ¢¦úÇ<ÁÖ¼Às¨S\$ Ý£ ¡GÙ©)°9Ä՛¿uvŸ¼šuÀ¥7ªwù¦K¾ Dæ ôª,ò=Êþ¢?¸¹ØAö•äm+¤‚Gލ¼± +ßNú4Dk7¡ÄØ®å O¿ñä}YŒöendstream +endobj +2384 0 obj +292 +endobj +2385 0 obj<>>>>>endobj +2386 0 obj<>stream +xڅ‘1oƒ0…w~ōɀ‹Á`I›tª”Ù²XÁAT€©µ?¿ç8 4ŠZa1Ü}ïýîÓ¡àáG!ˆÌ9µÎ¦pžv PÅ;ç$‚¢\Õ}Ÿ–åF©FŠî¸:®×Ň%™%ÝÐ#̐‡ATÒt±Æ˜­¥ºšZٍƒU…@©QQßhÜÀûMˆ&”p´Åò‹NºîÇZu¦³-xxí嗽‹‘Y„FV‰Î>h ùØgfàLs’üI[ë Y¬9ñþq¾ÂÆyç`¯q±Ø·Îä8én¸6‡x÷æ›Îö[´}sp.%¤Í l¾ñ’/®ÅË,ÝàÂóaŸC®Îã—À‹íµª´h[©xÝ$cá¥ËýKþ‰oJŒv·£pïÎõÔendstream +endobj +2387 0 obj +295 +endobj +2388 0 obj<>>>>>endobj +2389 0 obj<>stream +xڅ‘Aoƒ Çï~Šwl:@=Ú­ÝiI§öÖ ©Ô¸¨8ÐlPÔlͲ…„Ã{¿÷þ¼{Y0†KçíJïáfP^M'f,ˆ¡¬6Í0dUµ“²¼×çÍy»-ßJêG( =i^ Û55J]-Sõԉ~Ôn*Œí&vÆÑOÊB8Å3ZS~ú¢šaldo;ûÒC2÷^·ühbèˆÆFä&™€Püj\h¤ÒN¦«šèó [ó +/ÉÎqф¸GçbœT¯çÀ–ïÞü­³ÿäÝÐÞ\Y«¥Ë7Yó!4%7ežJðáñt, ×ñƒ›‹•¬ï:¡4¼ð~â­UøvÒgÝ»)£Æv+§áü¯Þ*®Ž²endstream +endobj +2390 0 obj +294 +endobj +2391 0 obj<>>>>>endobj +2392 0 obj<>stream +xڅ‘?oƒ0Åw>ōɀ‹Á`i“tª”Ù²XÁATü« j?~Ïq@iµÂb¸û½wö»O‡‚‡… 2çÔ:υó´K€r(ÎØ‰8'媆´,7b”ÇÕq½.>,Æ,æ†a;hQIÓÅc¶–ªjje7j« +R£¢¾Ñ¸÷›2M(áh‹åÔ'UcÝw¦³-xxç嗽‹‘Y„FV‰Î>( ùØgfàLs’üI[ë Y¬9ñþq¾ÂÆyçT¯q±Ø·Îä8©N_›C¼{óMgû-Ú¡¹8—ÒF÷6ßxÉwŠƒâ‹e–î +páå°Ï!ïÏã—À‹íU_)ѶRixÝ$cá¥ËýKþ 3%Æ»ŽÛQ¸‹wçD܌”endstream +endobj +2393 0 obj +293 +endobj +2394 0 obj<>>>>>endobj +2395 0 obj<>stream +xڅ‘Ooƒ ‡ï~Š÷Ød€(zt[»ì°¤Szë…Tj\ü7ÔlP¬Ù̲…„Ãû>ïüx÷`³p +AçÆ»ÞÝ>ÂA\L'âE ŠMÕ÷iQ<·£*•>mNÛ­xs$s¤bÄ,yd©l×ÔsµT—S£ÚqpS!b§µ3~€R" AÜhMùQ g]õcÕµ¶³FØ\{Ù²'`±¡C‘›4f +ZAþ L™=ðFs”üI;u,jŽð?æ¶æ¾;ÇÅbꝩqÒí0v qõæoÝ§lúzp®¤õй|ã%ßsP|Ufé^€ÇCyw?¤¹ØAw¥–M£ô/²dm¾ô9Åk7ãÌØ®å$œãÕûLFŽOendstream +endobj +2396 0 obj +295 +endobj +2397 0 obj<>>>>>endobj +2398 0 obj<>stream +xڅ‘?oƒ0Åw>ōɀ‹Á`i›T*¥àlY¬à *þՀڏßsLPE­°î~ïýîÓ¡àáG!ˆÌ96Σp¶ Pℝˆs(VUß§EñڎªTz8¬ëµø°(³¨z„t?ÈR™.Ö³µT—S£Úq°ª(5*êx¿)ф޶X~VÃQWýXu­él„ãï½ü²`1Ò!‹ÐÈ*ÑÙ­ ¿ûÌ ¼Ðœ$ÒÖ:HkN¼œgØ8/ð%Ù9.ûöљ'Ýs`—oÞ|ÕÙ|˦¯oΕ‚´:›o¼ä‹{ÅAñÙ2K·\xÚïrÈ»Óø%ñb;ݕZ6 nÞd;ÉÚX¸Férÿœ™c]Çõ(ÜÅ»ó-ŽYendstream +endobj +2399 0 obj +297 +endobj +2400 0 obj<>>>>>endobj +2401 0 obj<>stream +xڅ‘Ooƒ ‡ï~Š÷Ød€(zt[»Ó’Ní­R©qñß@³}üAQ³5Íïû¼ðãÃ#€Í"À)œ[ï±ðö ÅÅt"ÎQE¹©‡!-ËLt•>>>>>endobj +2404 0 obj<>stream +xڅ‘?oƒ0Åw>ōÉÅ`0Œ´M:UJÁÙ²XÁATü« j?~Ï1 4ªZa1ÜýÞ;û݇CÀǏ@›snGî<ìS ø;1c^ ¼ÜÔЕe.ºJêÓæ´Ýòw R º‘ïQµ¨¤ébR[ËT5µ²µUE@ˆQ‘ÀhÜÐÿIˆ¤Äch‹åg©ÏªƺïLgÇßóñÖë/š э¬PŠ_à€š ͼôOÚZ‡éjÍ<ÿç6Î+¼ä:ÇE“À>:—ã¤:=¶„x÷æ›ÎîK´Csp!%dîm¾Éš/n%WË<Ûspáéx( è/ã§À‹T_)ѶRixÝ$cá¥Ë‚kþibJ”†v·£poÎ70•zendstream +endobj +2405 0 obj +294 +endobj +2406 0 obj<>>>>>endobj +2407 0 obj<>stream +xڅ‘=oƒ0†w~ōɀkƒÁ0Ò6éT)gËbQñUÔþüÚ1 6ŠZ!y¸{î9ûåÃ#€ÍG€Æpn½Gî=ìS øÅtbÆP ¼ÜÔЕe.ußLcÝw§Íi»åï¦ö#Œ¨…ZTÒvMRWËT5µ²µ›Š€;E;ã‡ø7e!’Č֔Ÿ¥>«z°‹mgÇ=Œ°¹ùzä/@CG46"7iÌ( Å8 váB3”þI;u˜®j†ð?æ¶æ^²ã¢IàËqRž[B¼yóÎîK´Csp!%dî]¾Éšo ¡Y”\•y¶çàÃÓñP@Ñ_ÆOa.vP}¥DÛJ¥áUt“h¬Â·“> ð­›2jl×ršÎãÍû\¹endstream +endobj +2408 0 obj +295 +endobj +2409 0 obj<>>>>>endobj +2410 0 obj<>stream +xڅ‘?oƒ0Åw>ōɵÁÁ0Ò6éT)²eAÁA©øWÔ~üÞŀҨj…Åp÷{ïìw†‡ ¤sjœÇÜyØÅÀ%ägì„Rz!äåêÒ÷IY¦Êtõ8\ºÖWÇõ:·´°´»až ú`ŠJQkBØZ¢«±Qí`¬jœ“Šû¤qö“"ˆÇܓh‹ågeNúÒÓdêls‡y ¯¾üÒÒ¢‘U¢³ZAö ì 8Óҋÿ¤­u/ÖÒcÿ8O09/ðî—ˆ|ûèT £nÍØâݛo:Û¯¢éëû€3¥ ©Mgó–|qµ8(ºZ¦É.žû ²î<|x±½î*]4Ò^‹v,j²pIéJÿš?gŒjBv·³poÎ7µžáendstream +endobj +2411 0 obj +297 +endobj +2412 0 obj<>>>>>endobj +2413 0 obj<>stream +xڅ‘Ín„ F÷>Å]Î,¤ º´íLWM¦ÊìfCFÆØøWÔ´_(jZÓ´!aqï¹øxó`³ðBׯ»ÞÝ1ÂAÜL‡qŽˆbWõ}Z¹ê¥–c§/»Ë~/^KëGQ˞Y*Û55J]-ÕåÔ¨vÜT„Ø)Ø?Ä?) ‘„ n´¦ü¨†«®ú±êZÛ9#l.¾nÙÐØÐeFä&9­ ÿ¨=p¡9Jþ¤:LV5Gøó [ó +/ÑÎqÑ8pÎÔ8év˜[Bܼù[çð!›¾Þœ+i=t.ßx͗AhŠ¿”YzàÃÃù”CÞÝÆwi.vÒ]©eÓ(=À³l'Y[…o'}୛²xù‚Éü/Þ'̔Xendstream +endobj +2414 0 obj +294 +endobj +2415 0 obj<>>>>>endobj +2416 0 obj<>stream +xڅ‘?oƒ0Åw>ōɀkƒÁ0Ò6éT)²e±‚ƒ¨øWj?~Ï1 4ªZa1ÜýÞ;û݇ÀâÇÀÍ97Îcî<ìc`ò vB!Hy±©ú>)ŠlÔU[ž6§í6· · P xd©LkœÛZ¢Ë©Qí8XUŒóŒÆõéOÊ@,fD -–ŸÕpÖU?V]k:»Ü¡„â­×_ú>>>>>endobj +2419 0 obj<>stream +xڅ‘Ín„ F÷>Å]Î,´€º´íLWM¦êìfCFÆØøWд_(jZÓ´!aqï¹øxó0 ³0p!ƒkëÝÞÝ1Ì¡¸™ã<`P”»zÒ²ÌGUw•¾ì.û}ñêHêH?BµäY‹JÚ®©Qêj©ª¦Vv£vS`l§0±3~ˆ~R ¸Ñšò£ÔWUcÝw¶s(< síu˞€Æ†Ž(3"7iÌ”„ü˜P{àBó ù“vê0YÕ<@ÿ˜gؚWx vŽ‹ÆÄ=:“ã¤:=¶„¸yó·ÎáC´C³ 8—ÒF÷.ßx͗AhŠ¿”Yz,À‡‡ó)‡¼¿ïÂ\ì¤úJ‰¶•Jóè&ÑX…o'}NÐÖMY¼| Fáü/Þ'­Ž“endstream +endobj +2420 0 obj +293 +endobj +2421 0 obj<>>>>>endobj +2422 0 obj<>stream +xڅ‘1oƒ0…w~ōɵÁ`i“tª”‚³e±RQa Ôþüžã€Ò¨j…Åp÷½wö»ÁB”ØsÒÞ£ðvP⌝„ó ñ¶ªû~#G%:Qku\×kñîHæH?&³äa•²]¬1æj¹©&­Úqpª(µ*Z‘Ÿ”…hF޶XÞ¨ádê~¬»Öv¶Â#Ák/¿âXŠtÌ4rJtÁ((CfÎ4²?ige‹5È?ÎWØ:/ðì5.–†îх'Ó×ÀæïÞ|ÓÙ~IÝ7÷—JAÞ Ë7]òŵâ ôbYä;><ö%”Ýyü”x±½é*#µVf€ÙN²±¾Uú<¼äO ³5Æ"·ÛY¸ŒWï0Žendstream +endobj +2423 0 obj +295 +endobj +2424 0 obj<>>>>>endobj +2425 0 obj<>stream +xڅ‘½nà Fw?Å“Á06öè6I§J©M¶,(%–+ÿlµ_(¶ÕFU+$†{Ï=ÀÇ[@ÛE€Sˆ¸´Á½îâj; ç(ñ²©‡a§5ªóæ¼ÝŠWO1O…1FÌQ'#+庶Ƙ¯åºšZՍÆOÅ@ˆ›"Ô̈́þI9ˆdq«µå2]cÝw®³FØ^y݊G`©¥c–X‘Ÿ´f +ZAù L™;p¡9Êþ¤½:ÊV5Gøó ;ó +/¡Îq±”úGjœtgæÀ–oÞü­³ÿíÐÜ\*yczŸoºæ›@dJ¿”E~ÂÃéXBÙ_Çwi/vÔ}¥eÛ*màIv“lœ"t“!§øÖ͒tù‚ãù;žƒOƒ¢Œõendstream +endobj +2426 0 obj +290 +endobj +2427 0 obj<>>>>>endobj +2428 0 obj<>stream +xڅ‘?oƒ0Åw>ōɵÁ`i:UJÁÙ²ÐÄATü«1j?~Ï1AiµÂb¸û½wö»O‡ÁB™shGá( ÅØgfà…æ^ò'm­ƒd±æùÇy†ó_²ãb±oK=©nœ»„xóæ«Îæ»l‡æ6àBJH›±·ùÆK¾¸YŸ-ó4àÂÓn[@џôW‰Ûª¾ReÛJ5ÂkÙMec,\£t¹Ο’ÈÔ ì>®gá2ޜ©”lendstream +endobj +2429 0 obj +298 +endobj +2430 0 obj<>>>>>endobj +2431 0 obj<>stream +xڅ‘ÍN„0F÷<Å]Î,À¶”–¨3n4¡³›M3vߢok8Ähštqï¹§í×w2 '28×Þ­ðnö `âb:Œó€xٔ]÷¨šbx=mNÛ­xsu”¡€ZêØËBÙ®©Qêj©.ÆZ5Cï¦"ÀØNabgü]S ¸Ñšò½êϺ솲mlg'< såeˀƆŽ(3"7iÌ´‚ü˜P{àLó ù“vê0YÔ<@ÿ˜'ؚxuŠ‹ÆÄ=:Sè›~ +lqõæÝ§¬»jp®¤Uߺ|ã%_¡9(þVfé^€wÇCy{>¤¹ØA·…–u­tO²ee¾ô9Ak7eñü-ñé;ž½/¢öendstream +endobj +2432 0 obj +291 +endobj +2433 0 obj<>>>>>endobj +2434 0 obj<>stream +xڅ‘?oƒ0Åw>ōɀkƒÁ0Ò6éÔ*g˂RQñ¯”~üžc@iµÂb¸û½wö»/‡ŏšs¬Gé>>>>>endobj +2437 0 obj<>stream +xڅ‘Ín„ F÷>Å]Î,¤€(º´íLWM¬2»Ù˜)clü+hÚÇ/5­i¦!aqï¹øx÷`³p +A—Ö»ÞÝ1ÂA\M'âE ^wõ0d½Ï»ó~/ÞÃã‡1˜tYIÛ55Æ\-UÕÔÊnÔn*Bì¡vÆðoÊB$!ˆ­)?J}Qõ0Ö}g;áa„Í…×-:d‘¹Ic¦ $À”Ùš£ä&íÔA²ª9Âÿ˜gؚWx‰tŽ‹ÅÔ=:—ã¤:=¶„¸yóÎá³l‡fp!%¤î]¾ñšo9(þVæéQ€§¬€¢¿Ž¥¹X¦úJ•m+•†ç²›ÊÆ*|;ésŠ·nÅË·œÌßñâ}ŒKendstream +endobj +2438 0 obj +289 +endobj +2439 0 obj<>>>>>endobj +2440 0 obj<>stream +xڅ‘?oƒ0Åw>ōɀkƒÁ0Ò6éT)gËb%¢â_ ¨ýø=Ç¥QÕ +‹áî÷ÞÙï><?alϱñ¥÷°M gìÄBäiUõ}®Õé°:¬×òÝ1Ü1~D ·Ì~P¥¶]¬qîj™)§F·ãàT0fU,°?¤?) ±”¶X~ÖÃÑTýXu­íl¤G Å /¿üx‚tÄc4rJtÀh(~nδ 韴³ÓÅZúó¶Î >>>>>endobj +2443 0 obj<>stream +xڅ‘Aoƒ Çï~Šwl2@=ºµÝiI§ôÖ é¨qu¨Ù>þ`¨Ùše ‡÷~ïüy `»p +Q܋àîá ®¶“pŽ/›ºïE­•èvrTçÍy»¯ždž cŒ˜#Oƒ¬”ëÚc¾–›jÒª?!nŠP7Fø'å ’ĭ֖wj¸˜ºë®u½0ÂöÚëV<K-³ÄŠü¤5S0 +Ê_`Ê܁ ÍQö'íÕQ¶ª9Âÿ˜gؙWx vŽ‹¥Ô?ºPãdÚal ñæÍß:û©ûæ6àR)ț¡óù¦k¾ Dö ôKYä!<œŽ%”Ýu|—öbGÓUFj­ÌO²dã¡› 9Å·n–¤Ë·Bæïx>ÌuŽoendstream +endobj +2444 0 obj +293 +endobj +2445 0 obj<>>>>>endobj +2446 0 obj<>stream +xڅ‘?oƒ0Åw>ōɀ‹Á`i›tª”‚£.YPê *þՀڏ߻˜ 4ªZa1ÜýÞ;û݇ÃÁÏCÑ96νrî¶ p ꄝHJz[U}ÿjªQV‡õZ½[HXÈ =&ÚE©©‹5!l-5åÔèv¬*ÎIÅ}Ò¸÷“"ˆ'œI´Åò£ަêǪk©³QŽÇ<¼ñò˞@ÄH‡"B#«DgŒ†üØ4ðBK–üI[ë Y¬%óþqžar^àK¦s\"öí£3=N¦æÀ.!Þ¼ùª³ù*š¾¾ 8×Òzèl¾ñ’/nÅgË,Ý*páa¿Ë!ïNãgۙ®4EÓh3ÀsÑNEM.)]éŸóçܧšÝÇõ,\Ƌó ·fŒ?endstream +endobj +2447 0 obj +293 +endobj +2448 0 obj<>>>>>endobj +2449 0 obj<>stream +xڅ‘Án„ †ï>ÅwZ@=Úví©ÉVÙÛ^ÌÊÑ-hÚÇ/5­iڐp˜ùæ~Þ< È, Œ@ÃEz÷Ü»ËSÀ øÕtbƂx½“­Y]çm7 +uޝ÷{þêHêH?BµäIW°]S£ÔÕ2ÕLRô£vS`l§0±3~ˆ~RÂ)˜Ñšò£ÐÕÞÆvèmçÀ= síu+ž€&†ŽhlDnҘ (å/0¡öÀ…fAú'íÔaºªY€þ1ϰ5¯ðìMˆ{t!ÆIõzl qóæoÃG%oÝ6àRÈ:=¸|“5ßBsPò¥,²œƒ§c åpß+s±£UI)”†çªŸªÎ*|;é3‚¶n'Ë·`Îßñâ}ÇoŽoendstream +endobj +2450 0 obj +293 +endobj +2451 0 obj<>>>>>endobj +2452 0 obj<>stream +xڅ‘1oƒ0…w~ōɀ‹Á`i›tª”‚³eAÁAT¨µý÷=Ç¥QÔ +‹áî{ïìw? +AdÎQ9ÂyØ&@9ˆv"ÎI¢\©ZÉ´,Åw/«Ãz-Þ-Ç,ç†a†ÛE%MkŒÙZª«IÉv¬*JŠúFãÞoÊ@4¡„£-–ŸåpÔu?Ö]k:áxÄÃK/¿ìXŒtÈ"4²JtöAKÈïÀ>3/4'ɟ´µ’Åšïç6Î |‰uދž}t&ÇI·ÃØ%ě7_u6_…ê›Û€s)!m†Îæ/ùâRqP|¶ÌÒ­žö»òî4~x±î*](%õ¯E;±pÒåþ9J™©1Ø}\ÏÂe¼9?ê@endstream +endobj +2453 0 obj +294 +endobj +2454 0 obj<>>>>>endobj +2455 0 obj<>stream +xڅ‘Aoƒ Çï~Šwl2P=º­ÝiI§ô֋©Ô¸ˆ:Ôlûöƒ¡fkš-$Þû½ðçÍ#€Í"Àœ•w/¼»}„ƒ¸˜ã1åFÕJ¦e)>{™M>>>>>endobj +2458 0 obj<>stream +xڅ‘1oƒ0…w~ōɀ‹Á`i“tª”‚³e±RQaH ¨ýù=ǀҨj…Åp÷½wö»B€…(±ç¤½Gá=ì2 Ä; ç$ñ¶ÒµVÕ¨AWÇõZ¼;Œ9̏Â,vèe¥lkŒ¹ZnªQ«vè*J­Š†VãGÁOÊB4£„£-–7ª?™ú2Ô]k;[á$À;/¿âXŠtÌ4rJtÁ((CfÎ4'ٟ´³Ž²Åš“àç ¶Î <§:ÅÅÒÐ=ºPÃhÚ~ +lñîÍ7í—Ô—æ>àR)ț¾sù¦K¾¸S”^-‹|'À‡§Ã¾„²;Ÿ/¶7]e¤ÖÊôð"ÛQ6Ö·JŸ‡×ü)Ml±Èíãv.ãÕû(MŒêendstream +endobj +2459 0 obj +293 +endobj +2460 0 obj<>>>>>endobj +2461 0 obj<>stream +xڅ‘ÁN„0†ï<Åw` ¥…#êâÉd…îm/ÍÚ% +X êÛÛZ JŒ¦I3ß|mÿ¾zYX…‹òn¹w“§€ð«éPÆ +üy§j%óº‘ü£—çÝy¿ç/$ôc žQIÛ55B\-ÓÕ¤d;n*Œí팡Ÿ”…pŠf´¦|/‡‹®û±îZÛ9pÈÜz݊ ‰¡cBÈMsZBù {àB³ ý“vê(]Õ,@ÿ˜gؚWxÉuŽ‹$¡{t!ÇI·ÃØâæÍß:‡w¡úfp)%dÍй|“5_ +‘9(ùRYÎÁ‡»Ó±„²»ŽoÂ\쨻J ¥¤àQ´“h¬Â·“> ÑÖMh²| ÆlþŽ'ïrŽ&endstream +endobj +2462 0 obj +292 +endobj +2463 0 obj<>>>>>endobj +2464 0 obj<>stream +xڅ‘1oƒ0…w~ōɀkƒÁ0Ò6tª”Ù²X©ƒ¨0¤Ôþüžã€Ò¨J…Åp÷½wö»OŏAÛsÐÞcå=ä)0Õ;±$†ê}¥­ò¦•Ù¯öëuõá0î0?¢„[l7ÈZÙ.Ö8wµÌԓVÝ88UŒY ¬ÆéoÊB,eD -–ŸÕp0ÍilúÎv6•G Å;/¿âx‚tÄc4rJtÀ((ÿ€nδ é]ÚY‡éb-ýÇù[çžS½ÄœÀ=ºPãdºáØâ͛¯:›o©OímÀ¥RµCïòM–|q§8(9[Y^O»m e¿$^lkúÚH­•àUv“l­…o•¾Îù3–Øç¡ÛÇõ,\ƛ÷OäŒÿendstream +endobj +2465 0 obj +293 +endobj +2466 0 obj<>>>>>endobj +2467 0 obj<>stream +xڅ‘Aoƒ Çï~Šwl2@=º­ÝeKºjo½–Ñ4ÛÇ 5›i¶pxï÷~ÀŸ÷€¶‹§%pRÁ}Üm3 ʋí$œ£ÊóJÕJ>wâ|\×ëòÍCÌCaŒsÐÁˆJº®­1æk¹®%ÛÞø©qS„º™0¿)‘Œ nµ¶ü(ÍI××¾îZ×ٔFØÞxÞöOÀRKÇ,±"?iÍ´„âL™;p¢9Êþ¤½:Êf5Gøó;ó O™Žq±”úGïe?è֌M!.Þü£³ùêÚ,.¤„¼1Ï7óM ²¥ßÊ}¾-!„‡Ã®€¢»ôÂ^l§»J ¥¤6ð"ÚA4NºÉS¼t³$¾…lüŽ×à ‡³Œ†endstream +endobj +2468 0 obj +290 +endobj +2469 0 obj<>>>>>endobj +2470 0 obj<>stream +xڅ‘1oƒ0…w~ōɀ‹Á`i›tŠ”‚³eA©ƒ¨0¤6¨ýù=ǀҨj…Åp÷½wö»B€…(±ç¤¼Gá=l3 Ä; ç$ñ¶R’;©ky\×kñî(æ(?³ÔÁTµ´]¬1æj¹®G%»Á8U ”Z ­Æ‚Ÿ”…hF G[,?KsÒÍehúÎv6 H€W^~Å °é˜%hä”è‚–Pþ‡ÌœiN²?ige‹5'Á?ÎlxuŠ‹¥¡{t!‡Qwf +lñîÍ7ÍW¥.í}À¥”·¦wù¦K¾¸R”^-‹|+À‡§Ã¾„²?Ÿ^l¯ûZWJIm`WucÕZ ß*}^óÇ-Ùc‘ÛÇí,\Æ«÷ O>Œ‚endstream +endobj +2471 0 obj +292 +endobj +2472 0 obj<>>>>>endobj +2473 0 obj<>stream +xڅ‘Aoƒ Çï~Šwl2@=º­ÝiKWí­ÒQã"Ú¡¦ûøƒ¡f3ÍïýÞøóÀv"'ÜÁÝ6" 8Ûq(ÞVºÒêE]«ãz]¼{†y&Œ1bŽ9t²T®kkŒùZfÊA«¦ïüT „¸)BÝLáߔƒHJ°Z[~TÝÉT—¾j×ÙFØ^xÞöOÀKnj[‘Ÿ´f +FA~¦Ì8Ñ¥Ò^¥³Z üy„y†§HǸXBý£÷ªLӍM!.Þü£³ù”úR/Ε‚¬îZŸo2çË!²%ßÊ}¶- „‡Ã.‡¼=÷Wi/¶3mi¤ÖÊtð,›AÖNºÉPP¼t3žLßB(¿ã5øÉ·Œ)endstream +endobj +2474 0 obj +289 +endobj +2475 0 obj<>>>>>endobj +2476 0 obj<>stream +xڅ‘1oƒ0…w~ōɵÁ0Ò6éT)g˂RQa Ôöß÷”FU+,†»ï½³ß½{~ÂØž£öî¥w·M +'ìÄB1Èו®µ’_½:¬ëµ|sw‘€[h?”•²]¬qîj™©&­Úqpª(µ*ʬÆÉOÊB4¥@[,?ªáhê~¬»Öv6Ò#Á/¿ü x‚tÄc4rJtf`¿ÀŒÛZ韴³ÓÅZäç¶Î |ÉtŽ‹'Ì=:WãdÚaìâ͛¯:›ÏR÷ÍmÀ…R5CçòM–|q£8(9[æÙV‚û]Ew?J¼ØÎt•)µVf€ç²ÊÆZøVé vΟ2fkœ‡n׳p/Þ7¢ÃŒ6endstream +endobj +2477 0 obj +292 +endobj +2478 0 obj<>>>>>endobj +2479 0 obj<>stream +xڅ‘½nà Fw?Å“Á0{tÓ¤S¥Ôv¶,(!V*ÿlµ_(¶ÕFQ+$†{Ï=ÀÇ{@ÛE@Pˆ8œšà± v)åÅv¸ˆCy^õýySwFWÇõº|óóPcÄt0²R®kkŒùZ¦«±Qí`üT „¸)BÝLáߔƒHJ°Z[~R椯ýpíZ×ٖFØÞxÙòg`‰¥cÆ­ÈOZ3­ ¸SæœiÒ?i¯ŽÒE-þÇ<ÁμÀs¦S\,¡þѹFݚ)°9ě7ÿèl?eÓ×·JAV›Îç›,ùrˆìAÉ·2Ïv%„°9ì (ºËð!íÅöº«´l¥ ¼Èv”µS„n2ߺOæo!4š¾ã5ø¬ÂŒ“endstream +endobj +2480 0 obj +290 +endobj +2481 0 obj<>>>>>endobj +2482 0 obj<>stream +xڅ‘?oƒ0Åw>ōÉÅ`0Œ4M:UJÁÙ² bÿjƒÚßs (¢VX w¿÷Î~÷ipñ#à‡ú­õÌ­§C „/±2æ„À/›a¸ìú®lêbTçÍy»å¤´ס<©¼º‹5JM-‘ÕԊnTF!ZE<­±}÷7¥!‡¡-–_„*d=ŒußéΞ[®ãâ­×_ú +4B: !%:{ d`ê ͜øOÚXûñjÍ÷çÖÎ+¼ä:ÇE#Ï<:ã$;5¶„x÷æ›Îþ;o‡æ>àLH՛|£5_Ü*Š®–irà`ÃîtÌ ëËñ+Nje_ɼm…Tð–wSÞh [+mæ]ó'Õ5J}³ÛY¸Œwë-}×endstream +endobj +2483 0 obj +295 +endobj +2484 0 obj<>>>>>endobj +2485 0 obj<>stream +xڅ‘Ín„ F÷>Å]Î,´€(º´­vÕdªÌn6fdŒMûø…¢¦5M÷ž{€7Ò #à‡píœ{îÜe1`ü¦;!c^¼:ŒU•v͔U—Ãåx䯖¢–räQCUY ÓÕ5Jm-‘õ܉~Rv*ŒÍ&fÆõÑOÊ@8ÆÓZ]~ê*›qj†ÞtRî é+o[þ4Òt@C-²“ÚL@ +(~ 5®4óâ?i«öãMÍ<ôyyƒ×P—¸hDì£s1ͲWK`kˆ»7ë¤e7¶û€ ! iÕ`ó¶|CðõAї2O2.<œOÃmz/õÅNr¨eÙuB*x.û¹lÂ5“.#hï¦a´~ &Áò/Î'*ZŒÌendstream +endobj +2486 0 obj +290 +endobj +2487 0 obj<>>>>>endobj +2488 0 obj<>stream +xڅ‘Ínƒ0„ï<œԃáH[ÒS¥œ[.Vâ *þj@íãwJ£ª¡ÝofíÙ‡Á‡B™÷Ô8ÂyØ%@9ˆ v"νÄyÓ÷笩Æãæ¸ÝŠwË0˸!ñ˜aƒ,•éb1[Ku95ª« +R£¢¾Ñ¸ùIˆ&Ôãh‹åg5œtՏUךN&â<ðúÉ_€ÅH‡,B#«Dg´‚âØgfàBs/ù“¶ÖA²Zsüã<ÃÆy…—Hç¸XìÛKçjœt;́-!ÞÝù¦“}ɦ¯ï.”‚´:›o¼æ‹ ÅAñÕ2Ow\x:ì (ºËø)ñ`{ݕZ6Ò¼Êv’µ±pÒåþ5ü75Æ»ÛY¸Œ7ç¡Ü‹Ãendstream +endobj +2489 0 obj +291 +endobj +2490 0 obj<>>>>>endobj +2491 0 obj<>stream +xڅ‘Ín„ F÷>Å]Î,¤€(º´Ó±«&ÓÑÙ͆(cmü+jÚÇ/5­iڐ°¸÷Ü|¼9°^8/€¼qî3ç.‰€pÈnºpŽȊ]ßIÕ‡—®ÊåuwÝï³WK2Kº>F̐—A”Òtu1[‹U95²;å!fŠP3ãzø'e ĵV—䐫ª«®5cæ`„õµ×íü,Ô´Ï-²“ÚLAIH)3.4Gџ´U{Ѫæÿcžac^á%Ø9.Rûè³'Õs`Kˆ›7ë?DÓ×ۀS)!®‡Îæ®ùàéƒÂ/å9N2páp9¥v·ñ]苝TW*Ñ4R ð$ÚIÔFášI—S¼u³ \¾…P>Ç³ó ¹ˆŽmendstream +endobj +2492 0 obj +294 +endobj +2493 0 obj<>>>>>endobj +2494 0 obj<>stream +xڅ‘?oƒ0Åw>ōÉÅ`0Œ4 "¥@¶,8”–5 öã÷J£ªÃÝï½³ß}lü¸¾:ycàTˆê¡Óùk¾¸\\-“(ÎÀ„Ýé˜BÚ]ÆOŽ;Ê®”¼i„àÀۉ×ÊÂTJ“9×ü‰¨¥®ÞÇí,\Ƌñ ±ÓVendstream +endobj +2495 0 obj +301 +endobj +2496 0 obj<>>>>>endobj +2497 0 obj<>stream +xڅ‘MO„0†ïüŠ9îÀ¶ +GÔœq…îm/ÍÒ%¾,ýù¶[ JŒ†„ÃÌ3Ï´oß H?„KãÜsç.3àWÝ óBàŮj‹—~¬ºö¼;ï÷ü͒Ԓn€>>>>>endobj +2500 0 obj<>stream +xڅ‘?oƒ0Åw>ōɵÁ`i›T"¥@¶,VpPZþÕµ¿ç˜ $ªZa1ÜýÞ;ûݧCàG!ˆÌ94Îcá<¬ Š#v"νŠrÑ÷å«Þõ!Ëýb¿\ï–c–sCâ1Ãí´¨¤éb1[KU56²´U…@©QQßh܀ÜR¢ õ8ÚbùYêƒ:õékMgU8Ä#xéù—½‹‘Y„FV‰Î>( ù/°ÏÌÀ ͽäOÚZÉlÍ=òóç¾Ä:ÅÅbß>:“èZ=v ñîÍWÕ·húú>à\JHkÝÙ|ã9_\*ŠÏ–Yº.À…§Ý6‡¼;_/¶U]¥DÓH¥a#ÚQÔÆÂ5J—ûçüi@L±Àîãz.ãÍùì ?endstream +endobj +2501 0 obj +296 +endobj +2502 0 obj<>>>>>endobj +2503 0 obj<>stream +xڅ‘Ooƒ ‡ï~Š÷Øt€ztk»S“®Ú[/¤EÓÍÍöñCÍfš-$Þ÷yàÇ»‡™…\jï1÷v `ya:Œó€A~]uÝu/ÔÛFb¨z}^×ëüÕ±Ô±~„jٓ¥´]S£ÔÕRUµlzí¦"ÀØNabgüý¦,„p£5åÔuëú[ÛØÎ6÷P€ÌÅçíø 46tD™¹Ic& $dw`Bí̓äOÚ©ÃdVóýcakžá)Ú1.÷è£ìÕè1°)Äśt¶Ÿ¢îªeÀ™”VºuùÆs¾ BsPü­<¦»|x:2ÈÚ¢ÿæbՖJÔµTö¢De¾ô9AK7eñô-8Äãw¼x_ÕP_endstream +endobj +2504 0 obj +295 +endobj +2505 0 obj<>>>>>endobj +2506 0 obj<>stream +xڅ‘?oƒ0Åw>ōɀ‹Á`i›tŠšÙ²X‰ƒÒò¯6¨ýø=c‚’¨j…Åp÷{ïìwŸ? +AdΡv çaåPœ°qN"(Ž‹®;n„úxíúsÛìûå²x·$³¤z„r§E)MkŒÙZªÊ¡–M¯­*JŠúFãÞ-e šPÂÑËÏRÔyl:«Âñˆ‡×žÙ °éEhd•è샒ÿûÌ ¼Ðœ$ÒÖ:HfkN¼œ'Ø8Ïð%Ø).ûöљìÕè)°Kˆwo¾ê¬¾EÝU÷çRBZéÖæÏùâZqP>>>>>endobj +2509 0 obj<>stream +xڅ‘»nƒ0†wžâŒÉõ #mC§ªi [+8(·Ú öñk׀Zµ²äáœï|¶¿{Y8Á¹ñî ï.Ks(.¦qDP”›¾/_zÙfåisÚn‹7G1Gù! +˜¥ŽZTÒvM1WKU56²´› +c;…‰ñ)úMY'8àFkʏRŸÕµ®]k;»ÂC2W^¶Ã°ØÐ!‹ŒÈM3%!¿fœi$ÒNM“EÍôy‚­yçP§¸XLÜ£rU«§ÀæWoþÑÙ}Ц¯×çRBZëÎå/ùF@ÍAñ·òføðpÜçw—áC˜‹íUW)Ñ4Rixí(j«ðí¤Ï Z»YÏ߂)¾ãÕûIٌÚendstream +endobj +2510 0 obj +291 +endobj +2511 0 obj<>>>>>endobj +2512 0 obj<>stream +xڅ‘?oƒ0Åw>ōɵÁ`i:UMlY¬ÄATü« j?~Ï1AiµÂb¸û½wö»O‡ÁB™shÇÒyÈ Êv"νÊãjŽoƒì²º‘ûÕ~½.?,Ç,ç†Äc†ÛiQIÓÅc¶–ªjje7j« +R£¢¾Ñ¸ùMˆ&Ôãh‹åg©ªƺïLgS:Ä#xé嗿‹‘Y„FV‰Î>( ÅØgfà…æ^ò'm­ƒd±æùÇy†ó_bãb±oËqRž»„xóæ«Îæ[´Csp!%¤îm¾ñ’/.ÅgË<ÍJpái·- èOã—À‹mU_)ѶRixÝ$cá¥Ëýsþ4`¦ÆX`÷q= —ñîüðëEendstream +endobj +2513 0 obj +295 +endobj +2514 0 obj<>>>>>endobj +2515 0 obj<>stream +xڅ‘½nà Fw?Å“Á.` öè¶I§ªiL¶,(!V*ÿlµ_(¶ÕZQ+$†{Ï=ÀÇ{€مˆœêà^wÛ 0q±ÆyÄ@œW]w~éTs\×kñæê™0AuÌÁÈR¹®­Qêk¹.‡Z5½ñS `ì¦0q3aŒ~SÂޏÕÚò£2'}íúkÛ¸ÎF(BöÂó¶šZ:¡ÌŠü¤5Ð +Š0¡îÀ‰æQö'íÕq6«y„þ1°3ÏðéM‰ô^õƒnÌØââÍ?:›OYwÕ2àB)È+Óú|Ó9_±=(ýVîó­€»ŠöÒH{±nK-ëZiϲdå¡› 9AK7eéô-8NÆïx ¾ÒEŒ2endstream +endobj +2516 0 obj +290 +endobj +2517 0 obj<>>>>>endobj +2518 0 obj<>stream +xڅ‘?oƒ0Åw>ōÉÅ`0Œ´Mº´gËb%Mſڠöã÷J£ªÃÝï½³ß}8|ü„±9‡Æ¹çÎÝ6€Ÿ°3æÅÀ«¾?梒ϲ­†·ýj¿^ówKRKº‘ïQCî4r¦‹5Jm-SÕØÈvÐV!FE£qCÿ'e ’¡-–¥>¨s?œ»Öt6Üñ=¯½üŠ'  ҍÑÈ*Ñ9%¡ü¨8ÓÌKÿ¤­u˜.ÖÌóÿqž`ã¼Às°S\4 ì£ 9ŒªÕS`sˆ7o¾êl¾DÓ×·—RBVëÎæ›,ùâZqPr±,²-vy ew>^,W]¥DÓH¥áE´£¨…k”. .ù“065JC»ëY¸ŒWç²\Žendstream +endobj +2519 0 obj +296 +endobj +2520 0 obj<>>>>>endobj +2521 0 obj<>stream +xڅ‘Ooƒ ‡ï~Š÷Ød€zt[»ÓWí­ÓRã⿁fË>ý`¨ÙL³…„Ãû>ïüxó`³ +‡sãÝçÞÝ>" ¿šqÈ/›¾¿¤E)³êSž6§í6usœbÄ,wԆ²]ScÌÕUŽlí¦B ÄNjgüÿ¦,Db‚„Ñšò£ÔgUõCÕµ¶³Ë=Œ°¹ô²ž€E†7"7iÌ”„ìL™=p¦Šÿ¤:ˆµ@øó[óϱNq±ˆºGä0ªVOÍ!®Þü£³û(š¾^œI I­;—o´äË!0EßÊC²ÏÁ‡‡cšAÖ]‡÷Â\,U]©Š¦‘JÃsюEm¾ôÅk7ãÑü-$Ów¼x_*yºendstream +endobj +2522 0 obj +292 +endobj +2523 0 obj<>>>>>endobj +2524 0 obj<>stream +xڅ‘?oƒ0Åw>ōÉÅ`0Œ´M:U¢à¨K+8”Š5 öã÷J£ªÃÝï½³ß}X\üø¡>§ÆºçÖÝ>€Ÿ±2æ„À‹Mß©(åkUŒoÇÍq»å老ס< ˆé.Ö(5µD•S#Ûq0ªÑ*âií»?) ‘˜8 m±ü(‡“ªú±êZÝÙqËu\¼õú˞€FH4D#£Dg”„üØ£zàB3'þ“6Ö~¼Z3ÇýÇy†µó +/¹ÎqÑÈ3Îä8©v˜[B¼yóUg÷%š¾¾ 8—’zèL¾Ñš/nEË,Ùs°ááæwçñSàÅRՕJ4T<‹vµ¶°µÒfÞ%âGºF©oöq= —ñb}ۍ´endstream +endobj +2525 0 obj +296 +endobj +2526 0 obj<>>>/Annots 290 0 R>>endobj +2527 0 obj<>stream +xÚ͛AwÛ8€ïù:îêŠIQÇLÚÌv_»Í4Þ ÚJê[êØr»óï— @‘´Q9L¬ô½4 Á/" ÿyŲÜücYɳBe«ÝÕ/Ë«··UÆólù1YeªÙrýeýuÛdÝCvÓµ}Óö‡.¿z¿¼Ê¹!À7ß¾ü +Lr¡³]fþÔØf÷?‘ß?fooeÆü9§Œ¨ùswûæ¡^5ðGŠbQ˜.óËÅì¿Ø³Z13Óã|¡ŒZJ¶`Ô µ¼½¤³ ЦÇLøþ¯Cßì²g¡gg†‹…Œ©ÔO´Ï?šýMóp‚-ª)5¥·¼2v´Ë´03ÁÍ´Åò…5ÑwÝê¸3¦ù¼¾‚ñF_¼4:ˆhØïx‘¾ø‚ÏC_|tãI]˜ïFSæqñçÁÀü.“ÚΏ(jnôTšý±°×2Þ<ÏÆí2YKŒ Ô-p·oÚ~Ó>> Æï²JC`Ô-¦lš`´™œÈeÌ¢þs7€b|›HUY¯+¥1ll<å^d™£“]~kF4î!Fãô±Û‘Ò ŒÖ ‹ò°ßó:nvÖýC™ÃÎK)_*ë†Q1¶á}””%úà *'˵™x¢~‡jVßÚnÛ=þ@ÉÌoç%EB]¢°^ØÌIQ#P—è‚ÿÝ}µ‰«æŸ¤&\äÆmî2cô®LØlÓ»ÙևCsÀ¼gÆ3NMÖxwp¯ÊîjÛ&Ëì¿Ýlûfo§j"±œõò¦¦›Ö¯) ÁÄ6‚éæ"p’Íþùý ‡ýÏNaÔO¸wûÍҟ±&57ýÉq•‰*·nNk³ôØð*C÷Ÿ¦ÿÙíÿ0‘Åú8>O/ GS2a6§” ~"%J¢àãI™ƒÙì)¢a/QRi™Ãc" ug4\ƒ­[Ó1‰º‰tóß»ûË÷£­Iœ ¨›P×wlLÐ3I N¾Ê„á›H»<O%iBòiù‚ãie\mÄ£î êÆÂ9²:%Q¿%}Ü|Ý×{›s|F+ð¼ÚKj/Jt« b ¶Ü)ÙlœB“Smúf5žÉ†He ã”#ž d?¶„áp3FŸŸÀH€`ãëŽ7´ª:{4%<‹VrvgììáH€€›öyV8Ú°$ÜRD,#àI×Ǿ[u탵²êoLR›• ¥TÞÕ6‚(Å%F©_êÃf5âÜü`ë9Gˆ¢~‚ÝÉsE) 컙¹¸Ô>3ëloWòLö‚}Æ8&öÚÕö¸ÛÁx¸«±>)¤9šl²¡£Â<4–ÐSQi ä9ìly=fcYoûkÓ'¼Q0ôTŸќǽQ0¼ì¼F»þQo¶öbxÄ%yˆÙ÷¹2Ë#I€”$FDɒZYzå‰ÙÄ@³ÙDDsœ]6‘ҫЉsxy­@OÜÎá¦kÛäá&€³ƒ×±ŽØwc^Ώ…m 7º1 T€‚¡è.Ù öÞìí¥¢ºTœJ-V.ÃÀ”Ë80åêeÉÑܵF4'@À/ÍŸÇæÐkšy`Ɇ‡ 4Í<ðvÓl×Òµš¥®yE/ÇÍ3Kjy]óŠ^8Ž ]ûñøªÇ4'@À1{òA‹Q$@(Z6ëÀÅ¥ïySê.«áô§©¨[ӛõ‰§šfOp©f€)È¡b +8XzŸÔÕ0óáLcð¾¯û#îùú9JjÉl¾€‡ M­`ÉT‰ñ¾i×Éӄö4Q ìà4¡=p‚7ªÂdzwÀ1PT÷®îë‹씚%Ø; lj–dyuJÉ~ôà;B–“U¬<®ÌOÍ ˆHŗ»xO¤×¼ ð“Øðé5T\ðán$»†î² +ª¤"v;ÒÉ]Ý_G¤Ì’»jȱ˜%§Zƒ‰ ö@³ vDsœ]‚]%ôİ\1ÔØ +ôĨ^áfßÔ©KÀ|]Ç8'@ĺOÖµgÙ48f‘±F ?¾ ӏ`$ ¢(yÁ´$µdyܰb+X²œ*.®×ë)©ˆƒIv +sŽ×÷ûÍ×cæ-Š ¹Jbº®5µ¼’˜Ö/ˆý˦SË è´Iû±xù£NH$ '´ ­‡éúԜáÛÖ,µT%†Ø­`©JáNy“rˆÆ¡j8¢9Ž/— Ë×'1‹ÄbʂùáVËÓi:a¦‡ï]{h¨žùõû©S9ÅÖjh ¦˜ …©ÝŒTœÒŒ€Çø~áʪ”ŽD9ÄU× +t$4›]÷=Všäf G4#àqËoûîøømàEº:ÑϔþºN?¥ä kl•6TV3º7ƒ¡p-V¨ŸPæÀÛ®ëýzìvÐ#`¯Ûð?oöõðD¨‹XuJÍ hPœÅ¡”OU2QXæa¨ß‚Þÿ¯oڃQȘŽ=ýióœÀS./ð2%¥ßœêZr¨ÄV à|Z‰L0Ø]SD('@´)z à,ÊÓ§ƒ‹ŠxaK®ÆOÐV©h¸¿ªâr—Š +T>Öíã±~9 úÑXM&"ö>]í2ŸtÂuXå¢ã"ý²–¸è³ +=×—„†TXߢâòõ²ê·¨³Ú5½´Å‘$Ô­©³ÂGz×<ÔÇíØÅ™@Q ¼’ŠhØM4·a^=OeùøIªü°Z”q‰T/X ²J AÔ­&.ã”9|l@žžúäDÿŒ‡²ExÍÁ°ÛÂÞ·«nMåå¯ö™ÈÔºW¸Êq݊ ¢‰+ãP S"*Z±ÝD}]5 ÝÙS†Œ9ØMœ k㠐“èÓÇÂnW›c²j\._ûL>²Hx׌õ)ö3\G‘’SeʧŸÞ'>íAx{˜Gì­æ_ŠzòÓˇukªfçp3¦*÷)Ý/×·ËìMfÓ´ûî¡ÿYï›ìnß=îëÝ*ÿ>Õí±ÞbÁ +häM‰¯ö7¤Êß®þ¶Ô¾‹endstream +endobj +2528 0 obj +2494 +endobj +2529 0 obj<>>>/Annots 399 0 R>>endobj +2530 0 obj<>stream +xÚ՛KwÛ¶€÷þ\¶ +Ä2uâ¤ç$§ª­{ï¦V¦]¶åRrúøõƒ¼lOOC%[cŸ„`0˜¡?cE©ÿ²¢ªáßz{öÝêìÕ¥*xY¬n &UQ7¢XÝ|³ê~ÞôÅ؍‡~<ì¿]ýzövuV.JM€/ ¾\½+¾(‹º’‹¶Ø¬l I›âðFLwÅ«KQ0oØpÝ·Ö}õ;~?®77}ñÙ7 +Ùú¸Z°øl^›Þ|l¦ôœõ³þaeF…œ/j˜c AM ÔÄ+-ëI|Øu7Ãx—PS0hʱ­š¨»J…L2PoŒRôñûo¬`´f)֋XԁhoºC÷s·ïXµ‹ê‹š0k«RiÂrWN +lÅʅÀ8flŒ[ÕzîMw𸤥üP°” G ì`Q×÷ýz¸Ö){y†&¶-Ø+"bKÌX?¿-¸Ô<¢aK[ýuo,Ïق}ËçL.U½àÎä(y“KÕhùx“;— ÓÀäwø%åƒÁ`ôf¡¡¨ÁrԏƒWO>u ˜(eð*ülJj;Æ4ê@4}Ò|žŒÖ‹§äÚ¿Ç,ê@¬Ä> Ã:TUf;8snÌ:dB/Øf¡VZia 6R°[ò:›C?™“Ã4Nàì;j†úÜÖ3¬•9Þe –1MPÇ+²)ñh_.ß|ÞÆÁÐmalq°Ù’®ûéÓ°Æ8¡úg'¥­#V„¬ñ@5±JÁŠÐ[¶~Apåh&¸Šh¶¿²àJŠŠŽXˆ}P +Ô$;GWž¦; +®0\9”àOQʃ’+> 1^„Á$O“³Y.k®ªt‡mMR`®Š¡wþáþ0ìÆ}ú°­=·à Bší@Àn¼I·~¸†Õåãf;ìÝ´{¸Gdz隱ŒªYCGŠrR jÖ¾$ª±,Ñ}Ä2Q º1¥c?V2Ÿq¨Cëío:%çóCY%—]•“%—bñ"5[š‰é#šQ³Åeï $à4ŒAԁPËî.uxãÑÿ4hԁh×ÃßèêӜ̈́*é —T”¼Í„btëí¦ß2G†ªn´/ˆh¶É©¿QͺªÐQÓ¸›«")ÐQÓâ‰sñK¿Î)É4®â ¤g;ñv7%`Áp k ¢aÔÁ~¼Ýx»֘ãú⹆cU] çB‚ñ°%¬½f;ÈèŒ5ªá3/ǔ’JÐQÕÇ0¾¦9½º””q„N-z¡êóJòX?zAD4l%ÊyBÕ~¤¾Ð<ÁP3qþ7 ‡¤ádHká[D“-¼¶§vDSV鋠àÂ8ÌNvœ1múX_ —ä6?ÁM®ÿ¨‚ͳ‡ÿѬq—›ëƒ½§ ìrÆ)}ׯôzù+wQq8ãý"œíÀÜ7ýÔ¹Ý^ÏrÎ)¨R-Åò'FÉ+¨RŠ’Sýö~7uSJCaólåSAtãÕ?ž× æ”ÔJ?«ZÇÊ(:jë|DŒ´1KÄ¡vCz½^ïFp^fïAJm֘%ãXª†Qô̜äSL•‰̆ØnõuðüÃ0öém %ä™"¤îà™¯§»‡­-¦‰v¾lSvÉÖ8_ßPTèr/v÷‰ýŒuK($Q;±Þõ#9£›fîÀWd‘Æ±šô" +Á5:Õ·ã§aڍ`òäVãŽÇLø©ÿí¦J³{:çê¹Ï¹¬¦tÔ¶©œhªªÐ¹f£Ÿ`¸Ž~àö±šÊ³×Þ` 8k2ÄP;Þ¯>~Hm}? 'b˜íP¹óC‡d&"«æÈfƒHº*¥‹¤ñõ3‘tUR¥]¤#i 3oDÃÖú¸HÚbä 5×/‰¤-M‰Ç4іÓ0j»%ö¯h8obµîÍ4|¢À¼’'˜3™ÞÀ\qˆ£ð\ ÎUõUâ2}òFYÏHð' o©L}DeAxF$l·¬S £r +ª±†ª äA!PPMõӋÝ&•© c›Ç(j·õënÔú†Ó€rÎÚfvÓH,Ô֐µBÁŸz\ƒ_uû¤c ÆbڇÇ$jǚÎøv771wÚðe ©R<Å¥`% *Ô®î÷¨±îûñ§o~ú°M=oÉ6;9NÕÖKÁä8USýä®úîæ½þßOvАóÿâsduf^¬r‰FR0/F¥Æx^ËáÏ~³÷ósٙ•Tß3µ'”‚™•TÜó3»Øìö½[j¾J_zrÆ-± k&šFÁ»%ֶLJâ–d"戤Cq"åqˀDKC¨Ý`Þ/ϗ҉œÖÃ$äö#˜í`ôpLsš¶‚ëˁãëg"pVSÑH¦#p 3rDÃV¢ä"p‹‘O0ÔLœã"p÷¡Jc±'#ÜwÝú·~¼Á³MÌj´gÌØd¶œÀ2” üPx.|f‚ŠQ_IøÜ¤½(«lµ +u”¼e•«V—Çv8“ÇŽp¶ƒ´ç‰ä±s +âÌù¾š¤@AüeYlG3Yìˆf;œ\;§ ²±ð1ý”í1Ï%cí,"Q;±Ní–Qä=!›¤DX**Š]õ‡i ‡˯Êm¶¾F‚TZW³:>Eoy&C߯u0<ü|›ùý,Z™z—Àjea69_ÛÒlŒƒ­:µÌ|›y€Ø•¾8¾®_–”'æäe\ýâD;½||F?KU&ˆqíKðÅ n2‘zÒñ¿å.„À§ÚB¶r÷ˆöÐmrÅYVOƇ,x$΢–»éznȍ…ç;ÛG£fBQPj\k3ÓQ¶ö)Ý/صYž íʟ½¹z}¹*΋‹ÿ,¯‹ëÝíánê‹å´»›ºí¶ŸöÅÇn|è6=g¼.În¦5 ¤³Ïþ©onendstream +endobj +2531 0 obj +2238 +endobj +2532 0 obj<>>>/Annots 463 0 R>>endobj +2533 0 obj<>stream +xÚÕZMoÛ8½ûWðØâð[ä1Mânlš¸·^TG ¼ðGjÙØýù;äŒ%ʈÅ™00¡ô¬7"ç ý{"‡ÿ‚U’)Ëëɗùäræ™älþ̄ñÌVšÍŸ>Íë_«†mŸÙõv³o6ûöóüŸÉí|§‡_CÀ¬2SÇÖLðiEÁŠ=ð“ëw/ìrf˜áëÂ}.…¯»bgñLøú4L8#8>Á±áú!ŽOq€u»¯‰¶¶S žøOø³” äXÊ©Eʊ¢|9Óô&`.X©`$Pÿqÿx>‹ JxÝ1i)&±iSYP³yró&) Ž![0íâ:ùc>¿͖ì€B¶ì ǏX9[Æ*kf4pĠϖñÄ@åÛýH²’[×Ì»”ph˜Nså [ Ù|9ŸkæäTPäËÅùðW½y9Ô/Íù”%wÃü’êԋÆu¹ËæÉz,Ø* Iž*ŽåúîÛÝíÈ*ìï…,‰˜“ ǏX§y²åÌ,É3É26Öeãàíb$ËTX”ïïoFak¨XªùˆÆ«·ê»šŠ¢Va6]ðÄTá=Iº´ÆªüP·ûf7Zã}% –Ë!ë·j|¸ì#Ì®ÐãQa™áaýÄ ë#úŽÎˆ¸ˆ¾Œös¢ó§`4üŽn®GlOP|ò¸ßûîÁœW…ÍÒá;áûÆìBñ¢Ú€Ü“Ÿ=Ús*)Pk1xcöh/¨°döœ?…£aÂÉíŽ8±âøgvØ,öKX»´l]ÁïDªñ²§«Šj•ꢷvºrX³‡×öêééïאŸŸ~~ø•.ibJ}–s%K«±­ôÐ"a@”a'¬­Á¦òG ÝV’Ui«.KÐj9È F Cù]í^림]m–œªÈ^ˆË4F 9å°s{h ÊãUVoA/0ËPj¬g°sV% ¡³eè¦i»e\‡ñz¸¸–Y~BPÍ ¿%ü '•æö¿zýºŠK^êª/Ê;¬/AA0èé)¨:qý=6#{¹äV̓Ñ8A]­Úm€¾¨ Š—å õaæbÔ·ÜÊÙ£Ü\כE³úsû«“Q”'mf>Àóº£Þ`Ì¸Ä•®79‚ÆQÁ +zƒQÂÐx,XÅ*NŽž6äÙÅÁ(¡Lt銓c,;ÅÁ(a¨֙r'Ç*#ŸäeëMŽÇs n†õ…Ó)Æ;ô†pHoR ?Д©7v\o¤§ƒ +ê0F½ÞHOÇAqn¶³åªyh~švTÏËØéÉj|:È +¢Ü`ÐOéè|¡d¹É´–ªUŒ†–NŠ•›=C~”Œz¦x±ÉñSd¾G±Á(á§Éz/Wlrü$æQl0JøI²Ë˕›?övÔ z‚¼í¼ÜqPn@4NP…ʍËÈ ç´{ ûYŒ¹á«Ê͉Ôæ§ùñ !:ïQp0è'„pÅïnrô*Eõ*È F ?xW®h¹ÉѳG3>È F =K¦wɂ“c¨É㎂ƒQÂP“³]®àäø)ÝùD‚¢„Ÿ"C»\ÁÉñ“hgGUÀ ¡'ßé¦QPn04^°—¦2§×‚“).ªP£x5øi„àdб™íšOoÚNn|9gXJŒOÞxÔ?tÆ=ãkMŽ#gÝendstream +endobj +2534 0 obj +1454 +endobj +2535 0 obj<>>>/Annots 517 0 R>>endobj +2536 0 obj<>stream +xÚ՚ËSÛH‡ïþ+æ˜Pæý8²rÉÖ²àÜrñ‚pyËâÇfÿü™Y-ªâæØ ”«Ùm>iüµôC?fJÈü­„ñåçi3ûm>ût—„–bþ"”KÂ+æÏ拿ֽؽˆÏ»í±ßçÏnç3ÙÉÜ¡<¨òððEÝIáë¢Øˆ”:׊µx,Ýß¼`¿Ÿî¬Pª¼_Ðù¹>?7¿á·Ãbٗ7Ñ¡ÓùoÌ¿ê˜|MÀkÝù ¯´ìR«}!Ô&×çz¿è¥°—ì´lZ]¯»ÒJ¥ü[>»Éü/;6ï&çÁRJ¼Z5¼< +œ `©§ÓëáK¼é_§õñû‡ïKÛ`¹¬õŠj‰aM5VFP a-‹óÄ¡aU%C…aqV2E¨( ”\+D¨"o!StҜU£Z…è¤ÑðU2Ág«0›’¡ñlR ZÉCPò¤QÛÞZ1U²½¬dB;³JùĪQÉ6DUSòu¡Ÿ¬Øœ@VTG¬o«±ª’¡@+Â;g%S€N5a•‹¨¡Ó¬/(8ÀWuÞ@…ಜ"÷yCjÛ®áʼ +jžá;q(¾jÐÁȵ@xõ”ð}Fn}š‘q£¶½µbjdwÙÈ&Åv%Xô +Õhd“í¥‘‘ï‡ÃÏÝþyprt\¬eüåå`òŸ*C1.=wSxy:ƳŒ¡B|ù9‘µŽ)<AVUÇP!<—@VœuLZš©:† +æceyë˜âËDŸ/ B|ƀgø^P|Yûr7P <-ß7l†.0l&m`;4b:j<1j$ŠÌ¡@“F¶X|˜4÷7Ðñ†SSIÃåÅ ä㕊q1èÔâqÎㆠ-!¯ã*D[BÎvÜPxÞ£´ *„çÿ´‰"t¥MP!BÇ|ØPt&¡´ *Dg%÷´)\6©ÖC²]TÕ¨R­§Éöý~µ=öûÃ9Há³RM$¤B¹6è8ªÿA®MʖkƒHå4×Ö²åÚlEJà©ØBí*R¨F<ه(_h±vÕ(Tˆ/´X›¯H)>?ÆÑªUˆÏ·0š¯H)>Ɛ +„gã{C¢¡œ·Oµí‘uH”.Ïel»xKe; ‰”qcHôu±]¾ùWjÔl|e%±´S"(ÐzÐÜ#{OâT*Ä'ù§Úa¡všfډ{¤MÁÅ1‰VPŒp±¥ÐlULÁyÈ¡«.}œœùBÓnM@ø lm}xJøÂj·³´+¶Xî@v¹™ÅcÿÞnŸvÏ«írp†gñ!¶Šú—͘Ùi‚m5û›&):Ñ=“:¾É„xß1 l#˜<ßÙ‡;[Ëm°©å>7×wsq%>»»—ãÏž÷ûÝr¿Ølò¥¨ø}±=-Ö¥é•Ò^\6Wÿ´}øçì?©­endstream +endobj +2537 0 obj +1200 +endobj +2538 0 obj<>>>/Annots 572 0 R>>endobj +2539 0 obj<>stream +xÚ՚ËrÛFE÷üŠYÚ Ãó~,e[ò&®("½óQ Z  +@&ùü ¦‡DÃUfsْªXu9`SÓ¼ ^áï…2ÿ*´0^<|Î¥)¼qM[¡¤otU±ËÿðŠ~-ÞßY¡Ôø†a<Öçcó;>t‡c¿+ïctòŸ™ŸlXüXEÐkÝø‘^›ÆTUéGÂü¬a>uÃcÿürxÞïÆz6åƒYP’|25väSªQU!>%›Ò3·ÿµÛ—MWv0æ6`³ƒŸKc×nE’y£@Lx.…¬3ɲëÄO렗Ây²óBu½–ºÙ û±”JùÙ×pšò‡4Ÿ¦hòãˆ'WUÅËfâbi‚ÇãËðK»[ßmŽÃ÷oo¾½kË¥Õ §&ÚÁ§bf)˜E vüêëЮK¯ëÀ©×¯tù(Dèw¿¢ø¬A~ +ñYËݯ(>#‘_ðŒºÚ¯jêW¸P]W¬ýJ~¥ø•t#LQȯTœùUßu'»ò‘Ùõ‡!úAdXE ~–¿a€¶´ãhX²IUM„6)0¬›~}ܞ.V­Ï'ƒ%‰øUñcP/Dð+¾~Lñy{öUâó\†¯S|N£)} á¹+ÝøTÜxV¦®söbsً­ õ ¢>«É‹mÞï™îg36œ® «%ÚAÛâVŎA vÐ̊³S€¥CÏv\"TüŠ­x&E°«f€šðLÞVÍ=° £«)"ŒÌ/ÿ)º Àkʸ…èò1‘÷¸¡ø\§„çø =pNu`àÌ +ÕõZŠéȱ—Gޱ®~ 4g5“ iX,ýón NሎȤOêcÀ°8O +0·žÎ™¨fASÔSÎtßöCÇwÌDâ6°8…L~ŠûÄ?bŠÔM1(aróDÜñþ÷r¤þ]ƒâ%;Oíæ.x:âl)þ-qO– +ÜD&Ï÷ÈÆz¬Í»áSM>=ÜÜ­Ä;ññëýR,÷O‡Û¾÷ý~Ý·Ûm×âK»;¶›²¹‰x ý§žÄßÿí¸ƒendstream +endobj +2540 0 obj +1150 +endobj +2541 0 obj<>>>/Annots 627 0 R>>endobj +2542 0 obj<>stream +xÚ՚IsÛF…ïüs´‚g_޲l%—TŠ®\|adHŤÿüÌL7‰+a릶ºž ý­÷€þ5SBæßJ_þ)ÄË£è•ìêà=¼<ïï†Õöp»Z÷_ß}}_VõŒ8 jº<.ù<Ày"RçPŒáRÈ:Ã|Ù/Ÿê¸ëÀiÜ_M~ÍçRË.¡jc=“×ÃÓËæhÖçCÁƒ‘„ó ¼L–ª üjÞ^†m…3º œN Iè<8Mvƒª!t|æS¿VχÕn[OaÊ;³ $ù¬«©iªá³¬†oâP|F‚¿”XÑàþB'ÎqHœÉB¸—â™8N^N§¸”òùçԘ8NÅcÞ̗ûC?ܬwûSâ„òSτÔ)b¤©†qSE3҂_1Ž +ÐÖi<Æ ¨‘Ð&…×EL‡Ä ìªÚ1¨/D°+¶vLòy{²…ªáóL†­“|NUŸ©s ¢Ás¯4ãã*`Ɠep;g+V—­Øš€÷‡®ÀU5Z±Íçû̌}î·'/æsqå41 +Ú½`±bÍ(hFÅي)À:'+®ª!Tºc}íOá™Áªêµ?¨ÏäÓª™_û“„Ñá­[ P aä}åOÒÕôP º¼ﮉäsqìš@4x.½¶k:®a3Y·'Î]ӅÃTãÆX.eG5ƍÉ_µÓ¸™÷Ëo?ç¿ýp %ßܛ!†!{Ï©fÑ ƒ1ìk&0OÝX3jµd5œtMͪ“ž}ÍDꤛš ÔH¨“a^3‘|!55¨†/Jæ5ÉçýX3hð|xmÍt\Âf²n¬k&{9l´Ã2ÜÖ1pfR3i÷Qs·úÞ¯÷cÔØ7w-çˆY0iì˜@4³`%ÿމÔ¾é˜@5„:0ï˜(<…•xMP žÂJœsÚP„ËlH9mŵÄ*›oÚ|*†S?¤P|*2¿±¡èvØ%@4p;l:kŽë@ÖLÂí¸Ó¬ñ—³FylÂm)…AY£<6ácÚü>¬ýٝ’o +ì1 +êð5 šQ°Ø†sŽ +Ð`^£TCh°g5žÆ"»F ¨O³oÐ(>‰]v P ŸÄ.›oÐ|ɞª!b¤KØ`óÍ.B}]³ NËëˆÝ52¸dL» +l=và<&ÓÂܚl8¾é¿Ë‡´°þ>‹—ó»™·/Î"õùx^WŸ—O pÇþM¤Р9Áó™‰7Y¬¿Ù& Á¦±´†{˜xV'3q–Š7²ÉÓça#~V—›Ÿ°8ú4¿¾]ˆ+qóåî^Üïÿ,‡^Ü »§a¹ÙôÃ^ü²Ü¾,×eÕ+¥½¸ +P‰þ½ÂãøÛì_y±»9endstream +endobj +2543 0 obj +1219 +endobj +2544 0 obj<>>>/Annots 681 0 R>>endobj +2545 0 obj<>stream +xÚ͚KsÛF„ïü{´†÷ý8ʲ™Sª‰ºùÂÐ͘¯€”“ŸŸÝ!0t•¹ºeä*¹Ú†þ€E÷²‰¿gJÈüG‰ …ñbµ›}XÌÞϓÐR,ž…rIø`Åâë›ÅòÏm/Ïâþ°?÷ûóéíâ¯Ù§ÅLv2O(ßTùöð[ÕIáë¢Ø ¥MgPmÅcÿÓo kñ~n…Råóß6¿âÇþ´6Çóæ°/¯eS$ˁîþr±Á®uç »RB…ì…/Ÿ_0>ý»Ü·}™eb§y°½ŠO¦Îf¾$3‚§dWÌcߋ_Î!¿ +çÉ^‚ã—QwÛÓ¡ŒR)ÿ+ŸÓ”~‰——°.ù|UóiÒù/H—ï4—B֙dõr<=öÏ~øòæËÛ2Ñ9>Œøååíá¢Éß3jêŠiE¸X/âÓi¹®‹]N‹ýUx>™ÉrA¾ Á°úó˰¯Æht816 ˪v Šº–Å֒›|֌V£P>kÁhØZr“ÏHðšâ› žQà5mK¾ÌK¾„ÇqOK¾qšÀ’U¨>UndƒŠx²ŠG^ô»ã|³í/žìc¾Å9ÝϪ±¤©Ž†\Y҂aq¶ä ­Ë±–쪉Ð&†u7¬_v—ݪõ—hmâ…~UÁ üŠsâ´½§©‰Šz>Ã7qZ|NÕÔÄEøœæ7궑Zª¿D[.^“Z»ÑIŸNÓÎ6߀ÝÞ¶ÐêÆµÔ¶šMuSäRj^ÃÙM[€5îG»©Š*Íßn„&Eb7 &B“¯,s»iñEGìዼ‡&]P°)1‚À副ÛÞ^æÀööjÇQL··ú¶+aS$Ë;RP“-—À¨¾ÏÇÛÃêûf¿7¸†ËJaMcMX-T1edMä¨aß:´FË*[\P„Ð|'Æu‹ÛÂË÷–3ÁӒ{â´ø$mÀA>ɽånñéD[nPŸNÜ[î&_ -7‚_Ýr_æ@æ\ ‚ã‘uË}ã4ÕÌÑZî³ó€˜"G{l¹KäÜëWßǒ[s˛ +kk‘žYŽ}â´ð öÜ5q@>‹=7ÛÄiái,¹kâ€"xKnΙÓ"TXs×ÌEÖÜ|3§Å'§zZ¡"|Ëi¾™ÓàSúé &<_ù.ç2çj çüÇÞÎÌøN£šG¬¶kàlûå0ßôÛ¯§KìËj9¸Ærðrê@åàÿÞ©h±æ®ŠZ¬¹ÙN Ï`Ç]Á3Øqsœ¡Æ–»(B¨™—j-:F¯Q¨Äš›oÜ4øÖÚÅXÒu«°Ôn§ °¡Sà(Îa6îvØD¨Å£Ë–I)ž“&b'As8ÛÔ9†rxßx¨ úñ5þº÷XŽsßz¾mªäŒ».ÇïOŠ}ë£òh’½nÆ­æÿ`ROGò\’Ž?uLܟJªp™Ÿwø¼«ÍWÃ',€>>ÜÍ❸úü(Ïç–C/>‡õ°Üíúá$~_î_–Ûz]q×wjÒ› žÆ?fÿªÖendstream +endobj +2546 0 obj +1219 +endobj +2547 0 obj<>>>/Annots 736 0 R>>endobj +2548 0 obj<>stream +xÚ՚MsI †ïüŠ>&Oúûãè$vN[•µÉ-Ö;¤øp¼ÉÏßéqÕ"ŽŠí‚z=ƒàéÖ衟 %dþUÂøò÷°]¼_.ÞÝ&¡¥X> +å’ðÁŠå·7ËÕ?›^ìŇýîØïއ·Ë‹›åBv2G(7ªÜÜ}AwRxãº(¶B)Õ)Tq_¿zÄð$ÞÝÚ|by ó¹>Ÿ›Ÿñæ÷jû¼éËó˜Øéü2ó?;?ÞìZw>³'™ï@ zÁÓ&ëLrß÷âã4…5´ó@xC]oûJ¥¬ÿ„eÊ[œ—I¦Œ•—)” ©ér&z%»šwߏÇçœr»þáøõÍ×·%¤—ãƒ ¬á|J¸äsg֔_:ˆ)%\^]p¾VO5ßuà”ïF“os®jÙ%T a¬{y=<½lÇÚa=›]$á|‚b&ËÆjà‚„‚u×_†]…3º œ6$tJM.)UC蚏ýáaX?×û]Ý”OfAIòYSk ب†ÏZ(6|-‡â3êKñ žQP_hËã€åÌáq ÅÔrÂyËq*@•’î¤&Ïq*ŽŽó±Øë½=YN̗8§ë9ù M­Xà7U4ù -,Î~Cښޣ߀šmRøÎˆ«ãPx!@½ªŽªÁ êgÇ¡½…JSTCèÔ¾ŽCñ9¥¦:¨†ÏiÞ~Cљõ¥\w 8¡¾Ð~3Æ¿™Â㊩ßÄó~cµ­U*¦rW1ٍÕŠΦ?ö£Ý8Í­WÚD$EÝD4MR( 5‹³é€&E¬YÅt@M„&%|oÄÕt(¼èðÝQ1P ^ôÜ-‡â +ŠMµP _>'ò¶ŠÏÅS¿H¡jø\‚rÃ×t(>ë ¾gÑàå Í^f:c0Y <Ž¡˜šN:o:Æh¨R²|ª5¹Ž1ªTq›Ý«9žUA’Hˆ¼1r4MBhÉÜnH<‰=t°éæõJbŸœ«ÝPx:a{»Ú ¨ O'ln36’0@‡ TC±ÅÍÖpH>ïOÝ"…ªáóØÖfk8$Ÿƒ¦vu ž»ÐnÆ(`7³0xœ±ÙœY¢j6Ú@k<š|i‚˜¼F[ìŒW¯†ý0õ¼úi'\Ed„†>yuMFhl“sö +Pa£¼z¨†Pa£œ­çPxûÛà9rÞ(×»Ûœ=‡ T[ÜÕs@M„*òþˆCÒӌ€jè‚e>:@òy9€hð¼ºtt`Œž3 „Ççс3ËT]GYhG›‹ˆÉu”ÓèÀíæåð½qÀÒu4‘ÆNÓ š¬0Žýô ¨U3=ª!Ô¬Ûj$œ Íô¨NFöÓa²Íð@²³¢•óÑ +.ªfr ΛÚQ3Ÿ à|œÆü¼íÓ¥CÇÔ⫑1S§ÑÄĴă¯c1óqÓ—7ŸúÓlZÞ~ÇÑb +ª¡¾¾™Fì¼7n5ûŠNÇf^@ÇW½&ÞÓÀ6ÉÓÜlçfókõiì'Ý]ß.ŕøðåó½¸ß?­†^|öOÃj»í‡ƒøkµ{YmJÐ+¥½¸ +Ð+ýw½^ã*þ½ø*ž¶¬endstream +endobj +2549 0 obj +1220 +endobj +2550 0 obj<>>>/Annots 791 0 R>>endobj +2551 0 obj<>stream +xÚ՚KoÛV…÷úw™,ÂÜ÷céÄqZ RKÙeÃ&´¢BW¢Ñ ¿¾—w†ä¥j¼œ8€€#Ê#jx¾p4¯”ùŸA ãÅ×ÃêÝfõö. -ÅæA(—„Vl¾½Ú´î;qzïOǾ;ö—×›¿V6+ÙÈ\axPÃÃýÇ\ª‘Â×DqJúF£Ú‹õPþÙoœ·âíJ o†×úüÚüŽ÷]ÿt>–÷1º ùÏÌO6,~‚!ÜkÝøÁ½6A…î‡ùY?˜¹í._Ï»Ç~w:õlÊ/fá’ô'ScJ5 +UåOɦô̇íáqߕO0æ6`ó Rþ\ºö ’̈ٞK!ëìdÝuâëT¿ +çÉ. áq,u³¿œ†R*åg†Ó”/Ò|š¢É‹—"Нtéï}ÿø±ë/_^}y]šÜrºg«–èŸJž¥Ô8UG ‘õùÒnK»ëÀ©Ý_dÐyŒ,Ù$T•C ²nÎÛ§ÃÿÖç“ÁÃ%iÏH¬Â#P•=k!±83‡rh$dMa¨Ê¡Q4|™CùS¡„ 0TåOEÞÄ¡ÜIùR¢´ˆÊœ´// ÖAâԅð8–bJ{8¶˜šÜNjFŽM +R +¡sÛöݺ?ïŽÛ‘>ÑqiŠà®7„ ¡Vˆ¹!lˆWœCôój¨Ê¡wø?#®À¡ì9qU€ª²ç4wÜPþL€ )¸UùËéyã†ò—ÆO¸UùÓ’†/p(•=¥!_hàŒu8‹BxK1Ž»“â”RÕ “ÓY?Îfwè&Üh>yå¯÷ƒÉh”#o@Ìý`¢çNÊ^PWm@Uþòk"kÚPö\„´*´UÙs Ҋ3o(‡ÖAÎހªæÏÊòæ å/ z⠨ʟ14|yCù˹/Gހ¨ìiù2ڌU€6‹2p +1e'X#afž!“PT¨‘8GÔÜíºý·‘3^²IªÉl¸Þ:Áˆ¼ðÄÜ:ᄜ3q(ƒgä…8 *‡gäl‰CÙó8Ú.ÄUÙó8ØæLÊ¡ƒé6TåÐ1ç åΤiP¤PUî,N´ùò†ò§až]°¢²§qœMg¬ÄYÂããdœ'sÂuæh5ÎÅÐꚋgèh…sq„ÎoÝqÛŸ¨™]Бh r@Ž\ȵÄ9gäUÄyA¨Ù¡Š¼oq(sÁT *sÁòß zYm €ªzÅ}k€ògCµ5ªòg#÷­ʟ±óֈʞq/Ýër…ð¸c½5¯#Gi˜ŒG“/O3q”žæi¿títƒc‡›†{!-!ü6¢j ù¯ “­¶ÒrHžóÂ[TÕÊ@\NÈ£æ¿0@Øó±Úðq‘V>qßHÔ:K½,°œf;æßÜ$ꛛySÀ.çØV¿tO‹ŒßÚ<Ûë0L"îib5YŠ‹ æ_»~×îwÿN_×xÃ¥½ÇŸ(‡¿kö)§Ùˆ³ù†4ä˧I·÷7wñF¼ÿüi-Ö§‡þŸö܉OçÓöÜÝù"~oOí¾t½3ùÚx`dºû'õÕzѺ§endstream +endobj +2552 0 obj +1221 +endobj +2553 0 obj<>>>/Annots 845 0 R>>endobj +2554 0 obj<>stream +xÚ՚ËnÛHE÷úŠ^& 3ý~,=I<«Á8²²ËFqhzx(“ÏOwW“,ˆÊˊm¸¦TÒ!›÷ŠÅúo¥„Ì¿J_þî÷«?6«w7Ih)6B¹$|°bóíÍfûu׋ãƒx<œûÃùôvóïêãf%;™+”UÖŠ ;)¼q]{‘RçšØ‰»Rý§ âݍJ•÷ :?×ççæ7ü|Ú>öåMtètþŒù_“Ÿ( x­;Ÿá•–]jªÑBm²Î8×ÃãË~ܕÖçђē©³Oú|d@!<%»ºbÖýùe8T8£»ÀéR„.²rMgšš ]*+2Ã|èO÷ÃÓóùéx¨‡0å'³ $ù¢É™O©N5…øb=~¿o÷Ï»z +šÈé$é|ï‘ù<à‚¹ë{ñË:襰—ì²lK]ïNÇRJ¥üßßa7eÍ»ÉùêRɕ5^E£ËIà\“úç|~þ».ñӗ7_ޖ’ySäeÈVkšêY5@ 5a-XçÌ¡l–U2"4 +,‹mæPx*€cÕÌ…ðTäž8Ÿ4à58U!>iÁiø&Ág«cމjæ³IÛðÍŠ/ð—á…þBgÎX2gQ¨mo¥˜fŽºœ9ÖÛêR¡|g1gŽõLªdÎíñtÇ*nn<ñjbY8Um«Æ´,œæ:ž ͵Jè€B|ùެC‡ÂÓL«†(„§˜çØ¡«ÍŒ± +* fÃ7v>“"|+ª±jæ3ù´Ô¼c‡â‹ü¥d„ýëBg¬¡³(Ó¶{Ƒ£/GŽ ªzT¦rM̑cò^ŒSä O‡óÃ:‰O-p ±"\„«ºòñA áXçÌ¡­k–U2"ÌñbYg…—#DO™ +áŽÅ9s(ÂìrÊPˆPKމCÑI75TSˆN¶î6ßÄ!øt‚Þv 3žN­µMgÎX2gQ¨m»ä6ÊyƎ½;*B›¼ÞÑ1ǎŠÓ¥Îºß~›.t<¿Û9•Õ]^*˜yÄļ$T°üÇ(@/Ñ(Dèó1 +Ï4F +áÙÈŒ€"4€B„Æq# ø´Bc ŸfÞ[£èd˜Ç@ 8_;F0ցÈYjÛ#ë1w9rÒÜ#O æÄIn"X÷÷Ç῟®v|dv6ûËë!ªy‚ .åQóŸ è|Dã~Ù'÷‰ùðÁæžX6Éû[8žº…ƒ¬ZށÓÜÇ8ÑԀŽ?5›¸Ï T¸™LNó®±Í»*—ךO­ôa}}³WâýçÛ;qw|8ÿ¿zq;‡í~ß'ñ×öð²Ý•ªWJ{q Yú½íÄO«ÇǨ'endstream +endobj +2555 0 obj +1188 +endobj +2556 0 obj<>>>/Annots 900 0 R>>endobj +2557 0 obj<>stream +xÚ͚KoÛFÇïú{Laöý8:÷T µeô’ kÓ® +½JÉh>~ww†â2@4>Ž ø‹Òˆ?îpþÚÑü»RBæ%‚ƋÇÝêÓzõñ6 -ÅúY(—„V¬ŸÞ­û¿¶ƒ8<‹Ï‡ýy؟Oï×ÿ¬¾®W²“9ByPåáî·ª“Â×E±IvÅVܗè?½a|o­Pª|^> o|~mþÀûa¿üŒ&ì.¿Wuvù!xCÝlO‡J¥ü¬,Ït þ¢ÿ%^>ñ| µÎ§›/aì +¤Ë+åµÉ:“ü}>ï‡c?öçáû»ïïKL/;LJ`‘/2å5̰)Ÿ:„-9¡dW“ðáÔ¿ %æEHºäó)çdÕ²K¨fB— +PIÕñåu7Ý^Ö³YG/šü˜ñdÕàź|wÃùuÜW4£»ÀiI>Ÿ ÖäûΠjø‚„Jóe8=Ž›ãysØ×LùÅ,(I>çk±)µT¡jø\€jóõG¿;në-h"§[ä³êK1 žµP_hϙâ€ç,áq ÅÔsÂuÏqFÖ*•Ë‘B1{Ž3 +ŠxÎùv3lŸ8{N$rB…Z³ªç€hrBEîŽCáIƒ%«:NU Ÿ´øåˆ«ãx¶Þo“〚ñlRP±8{EԚê9 Â¡ÒðõŠÏ[øJT=TÃçT¾žCñ9õ¥¤&ˆÏé·9ÎgkÆ~¯û5¡Ö¨èrÝ1ûÍË'¿YýãeƒcËÆŽ—Ùn"2B[ØÒÇÑd„vP²8{X“tòP ¡Òøåˆ«çx&E¨XÕs@Íx&/«æî9a¾åÅs@5„ÑóvŠ.¨KÇH¡jèòk"oÇ¡ø\„úRŒDƒçÔÚs¦8à9‹@xC1utÝuŒu°Ôå.®bv“둝\çáøÔô՜cg:Ia4lèŠã€h2Â(XŒ‡Ì©'/Žª!Ԓ³ßp;Üà7Ò-ë•Äþ6c¿¡u‚&7ø ¨™P'ìr³u’/¤K¿H¡jø"6¶Ù:Éç¡­]mDƒç±«M;ÎgO r–Žså2UÇÑÚãuŸbví.~óç¸9·»œÀq—“‘zåÕs@49a±UÎÙs(@Íòê9 BÍr¶®Cá)ìqW×Õà)ìpsvŠPJü1®ºŽ”˲%±ÏÍ×u>Ã¥g¤PÍ|*òÞåtÁ̳ ¸`ß:?0ÅÏYÂã–óüÀ•ËT=Gyl+sQ³é( òÍñxóôôépØý~²ž`Y%„&†yxD“6² m†@5„Æñ ñ´j†@5xš{Sä“¡ÕðÉÈ|x€âK¶™HË®vrÌ'(¸¨æÁ¸ìgGýÖ± NÓF£šóÌÀ• sjØW¡Ì©ÅÅȀǎøÂdN—I|~ÆI†if–]qÇýWŠÍªfPÀ.›âVó Øtl¦tü©½Ä~Fðf6y™™83«ËfÅ'l$}¹»¹]‹âó÷{qx>ÿ׏ƒø6^Æ~·Ɠø½ß¿öÛÊêL®×ôHlðBþ±ú¿¸oendstream +endobj +2558 0 obj +1222 +endobj +2559 0 obj<>>>/Annots 955 0 R>>endobj +2560 0 obj<>stream +xÚ՚KoY…÷üŠ»LîÜ÷céÄñh#%˜ì²aâ6"âáÖäççÞ[ÕômKC±K%ސ PœCW׏™2ÿ(a|ùÿm;{¿˜½»OBK±xÊ%჋Ç7‹å¿›^ìŸÄ‡ýîÔïNÇ·‹ï³‹™ìd®PnT¹™ÿ%‚î¤ðÆuQl…Ò¦3¨6⡔õ‡•xwo…Rå ƒÎõù±ùïúã·Ãúù´ÞïÊsٔ Ér ûÍÿ’!صî|aWªS¨½ðåWÄŒ?—ÛçM_j™ØilWñÉÔÙ̗dÑà)ÙՆyè{ñ¿uš_…×ÉN Áñ¡Ôíæ¸/¥TÊ÷þ /Sna)\òù]Í/SÈ]éò'Íå{u!Y??ß>>Þ-Oý×7_ߖŠ^vŽ% ÚËá¢É·5å?ÄØ.Ö7ñËq¹ªÍ®§f¿ +Ï'43Ù%T _`X·‡ÕËv°FëÙ¼‹$žóàW²ô(¨Ïð«yz9ì*œÑ]àô’„Ö€ÓÔ4ÕZ >Ã7q(>#«Õ@â€jøŒ¯á›8Ÿ +à/%@4x*^—7CțI<§%ÒFð(ŠWÕč´àQ7ç¯p«þpNœÈìãì.·ƒ­oÆ ˆ±lRàWœ‡ ýª¨†0Dü^Ä5p(™/ xÉ6»i:OŽÿ¦U³(ÕĨ¢æ¾&@ÀùØl øéÛ'î;‰ÚbiV¦ãkwåõ,ûîõzçK5‰ºTƒžËåH5Ù °º] cå|2“ÊYÜoGURßñ㸠㫉ó•„Éäy56âjl>ý ùSг£»ùíýB܈_>=ˆ‡ýÓé¿å¡ŸûÕa¹Ýö‡£øg¹{YnJÕ¥½¸ 0ý¹^ãËøyö ß·+endstream +endobj +2561 0 obj +1207 +endobj +2562 0 obj<>>>/Annots 1010 0 R>>endobj +2563 0 obj<>stream +xÚ՚ˏÚHÆïü}Lqúý8’Çìi¥ì@n¹8rÄkG›?»»Ê¸=Rhn[›HHf +>\|?(×ß+Áxü/˜“LYöã°ú°]½Lr¶}fÂffÛ§7Ûöû¾c§göñt»ãxy»ý¹ú¼]ñ†Ç +éF¤›Ç?b©†3«Lãف ɛ€jÏ6©ü«¿vìýƒfB¤'Œ/Ã*Ÿq=ì^Ó3iۘøBãÝÍûOp^q.ec“sn‰ +'wREmQ¸óùÔmºŽý¶Jñ‡ð&ée<ž ­÷—S*$B¼ïðÅè‰ï ]ÂÇÌ…ÞbDÇ!žúóyýô´éÎíЎ§áۛooS]¨|˜•V06'UÉgE+AõõÒîr›KG§Íïó§Ub¨Â ÖTT9Ss§8äTæ ¨ÂS„9S3(dLæ ¨Â ð¤)S3džL¦LV…9®!dÈR¦bOg + e@Ìît-uÎLu€3‹BxKÑ$¸MíT<ýÕLí<’fúãnŒµ„¢XpYi«sVeҀ(ÚÁˆ*¤©ù3£*‘TaÐHʜ©yS’*sTá-ƒ'ɚA©!c2g@¥„!Kšš½i@ö„„!KšŠ=>>>/Annots 1064 0 R>>endobj +2566 0 obj<>stream +xÚ՚Ër7E÷ü +,í…Æh¼±T,+›$¥Htyã c¦øP†TìÏ€Æp0N™­eGR‘u b“¾3Íþ{B¦_Úå¿/»ÅOËÅ»Û(”Ë'6 +çX>¾Y®þØöâð$Þö§~:¾]þµø°\ÈN¦ùòÃýÏ)N'…Ó¶ b'Bèl[ñ£÷‚a-Þݐß/}—^ònžŸé÷ëӟŸß|~›ß̪N§Ïš†:6? ýçÁ«<Ju.ÍCŒyЍóàUÒ:éôñ¸Z÷9òâÄHóÉØ™ÄJv±ªdWvÏõ°~ٍ»Æ¸4 I:]ZD'ó3ª‰ÎƼZ ã¾?½ û¦Uçù, tzÌ˧ÓáBՆ²x7ýñ˰y>mû²|‘Ç9¤á\,9:¨ªó͇o«Ýó¶?ø?Ï:L-2=¡hè¬ÇÔòÐ÷â‡qš—â4™y :^C]o‡ +bÒÿƒY*Fd. Êç¥EQá’ÙXc0?%³ù­ÿ::^Yx‚ Ėвä«â6(š-¡Óc·¡øÀ×t•ÝU³×PlRc¶B¯)ªa“³c¯!MÉ&£× šMÌ2l݆Â󯄊۠jðRþ1¬Ý†ÂsSK^6 ³˜Zh·ã ÛÌÕñŠ§Û„Ënc,”åm:š(&·1VU¯¹; §Ñlt`’¡þ ‰-¡}ÉXÅmP4["qænCñ)SVvT  ²õ²ˆ©ßPtåŽ~ƒª¡…ùб߀:Ì4ÅoPM€:íZÅÚo(¼`ñZ¨ø ª/8ÖnCÁyÀԒ-EÖþ%¼ÎmÆ8è6³@u¼†âé6ñ²ÛhJ‚ +ò,&·Ñ6b~J~s߯Ùß܀$ö„±%a»AÑ쉔x o»!ùR~Ug»AÕj]¯‹xÚ I—N–<Û ª†NIÞfCâI¬wW³‘vž±d-js5 +OEu®AUžŠµŽÍÕnH<Uìâ (ºP‹Ø´ÝŒqÐnfp| ÅÒn.ÌR±åj5òr£šüF¹Z O~³ÜìúåáfuêG×ñ\sZb/X,‰›AÑìËÝd(:]kâÅdP5x¦ÖŚ E§j)»˜ ª†NÕB6c›¡Aׯ۲͠j¡–³ÙÚ …'å¹8U5x²°ÙÚ Ë×Å PLt^yO3FA“™…©ã|ïh.ÌP±ðX¹ú€brðæÜðiØLæb ÃEì'§ÖÍnpÀ½5€ä3¾i @՚Àº5€¤Ó¦i @ÕÐi˽5€Tд jëâ '}Ó€ª“wk…ÍÔçeëh_ÛPƒ Í´QpÔ2n +¸0?ÅfœoÓŠÉeB-|ïÒ=Ìõããíf{ê‡ómŒá´ 4ћ¦f7¯~»È½€‚³¶í˜¿-çïe(0M€™W¾âÞ@Ñ©Ðô¨ð]‰w²M`òÜ¿jÿªIkáb­ñÜÜ_ß.ŕxÿñîA<žN_WC/î†ÃzXívýp¿®ö/«mzʉ+UÐo›ê$þ¾øb'ž¶endstream +endobj +2567 0 obj +1209 +endobj +2568 0 obj<>>>/Annots 1119 0 R>>endobj +2569 0 obj<>stream +xÚ՚MsÛF †ïú{LQöûãè&q/ÍLj+·\Ԙָ£—’Ûôß\€âÒ3t+jÏHóšÄG á5±øca”†_£’U.ªï»ÅO«ÅûÛ¢¬V«GeBQ1yµzx³Zÿ¶íÔáQ}8ìOÝþt|»ú}ñiµÐK †3<Üý ¡–ZE–Yí”1fiHmÕýþÕ+úzëáÄá á2¢‹p.¼ã§ëÝó¶ÞÇ奅˄?.ÿócƒní2zÑð„‚È:ë@È}שÓ¼?B?DÇ)ÔÍöxB™úð)Áç¤ P<RD‰^Ö´Û=íº›‡‡ÕßÏÝ·7ßÞ1“Y)˜Àé/gC(r²¡ÀU£˜²!”H¾כšé6ÉÉôëø²ƒGXG«aQ5€¹®âM¿yٍEÃG!ëdzłELˆªaK Õ]wzé÷•ÍÙe’³|<`ˆXb ”8R `HX`>vÇïýÓóéé°¯ Xàd<žwXcª ¡jð¼Ç#Öh8<§±´ n€¢¡sK o4c4šY :N¡d¿l4Á$,PÀ•HMFL~e3w/Û³Õ' T˜<Ю–)´˜*š<Ы”`‹aø|ÍÂÑbPM€¾ú7H¨Épt)Ñ?BƒÉ jèRÆ"%Ød8Àè±¼T“AÕÆ€ÅE¬ÉpxÁ`}©&ƒªÁ V´Åpp.ai¾s(6@É×YÌ-fˆŽS(™.[Œ·ïøÒULãmÀú4xÌÇn۝Îöµ ;$L>Ôõ#«AÑ䃱X«[ ÃçJ¦Z5X ª ж•l5]XªªÕ jèrn4^2XdªÑ jðàœ,Úh8¼Ïý CªÁ ˌX«áð|ÀÒ2øІ¾dþ:«ã ÕÌÑq +%Ójâe«qð¬Jç! ªš¼Æ9‡jðšÛ§m'¸o–˜t€eÑ£Ó hÒÁjá>ÃÑij£Ïè0/UšZàR}†¡³…:×ÕgPMt¶PßZ°Óp€‰š×ÕiP5€™š×b†Ã‹ñÜ2¤¼HMk±NÃálYW;@ÑЅ+}fŒ‚>3 CÇ»Lºì2Öaã» ö‚b2ë©ïM&sêúÑb‚¬Û™43¹`±^mE“ –à‚†ã3Ô¯Fƒª4Ô—j4¦Î5ž·À­¦¾µ`£aM¦æu5T É²oh8¸äšT \òÂç8¼¨§9 ]4×ÎŒqÐhfè¸‘</[ñØþ.æ,&«1>Oc¿Ög£±²ê0¢&!œŸFP4 á‚øQŽÏšfUhE·Î86šQT ›ÎâGÀâ›I€âgŪás [6Í@ž7­³>À°Å<ÍÄy»:–k'(MšåWûÿc™þR˜íly×­™æ{ÿçm™Ï]¿¼+c5·+3íÿûy×Û[é»ÿœÍÍæ¿Í¯ZI¢·þmâÒçy×<λ¥Æ2¶‹înnWêúðõ˽º?<žþZ÷úÒ6ýz·ëú£ú¼Þ¿¬·µF­Þ%lƒþø“>Á_ÿ9h©}endstream +endobj +2570 0 obj +1206 +endobj +2571 0 obj<>>>/Annots 1174 0 R>>endobj +2572 0 obj<>stream +xÚ՚MsG†ïüŠ9Ú­çûã¨ÈRNI9¾ùBÄJ!Å;ÿ>3ӽ쬫BëØ‘TT½,jô,­÷e›þk¡„ÌßJ_~ž†ÅOË҇$´Ëg¡\>X±\¿[®~ßöbÿ,îö»s¿;ŸÞ/ÿ\Ü/²“¹B¹QåæóÏ"èN +o\Å ”ôFµ¥ü¿q|¬PªÑ]Èf¾³cð¥´$àµî|×¦3¨¾æ{}aù؟žŽ›Ãy³ß•z6å3€¤ñdêlÁSªS¨<%»Ú1÷ßWÃaÛ××/æ&`òú‘x.•–D’ùe1ѹ²Î }/þ³Nó«pšì¼ÇR·ÛÓ¾”R)ßû?8Kù4Ÿ¥hòí bÊ .ûˆ‹µ†ÍÐÿÚûúîëûRÌi>]0q*¢|ªF–RçP4Ý$x՗Óê¥vº¼i>çÑ«d—P5€.€WÝ_^‡Ñö­Ïç‚$Mg XU!P µ`UŒ£†4L¦F ¨Ð(°¶QCá©P]¢Tƒ§"ë ¡à¤k©iPEÃ&-XË‚ë`д…ð8–â4êzÐØÊÏ’ºˆ)hl¾×Q³üçÐóÎ}½!lÕ­jր˜†fÅ8k(>oѬJրj½Ã÷CL³†¢s +¼ªf ¨†ÎiæICá™.S“Tƒ—7²N +O[xT“Tƒ§ø Û¬¡ðj6`րhè”k¡³f¬Y3+„DZϬÑ׳ƤX *ÚìO ¦¬1)?ë»íþtÉ[̲¦Àšë-a¢«~UÓÄÔ&zæYCÑ…vU²Tƒ—9g Eç"¸UÍP KàVŒÓ†´|¦¦ ¨0¿R–uÚPxF_fC +Uƒg 8 Û´¡ð²ëË1m@4tZ¾-kÆ*5³2p +ñLC$çãåŠT5gà%jö»çíæé|ãÆnVl¯wƒN0¯AbêpÎ8j(¾€óð5 Àˆóp®QCÑycרÕÐyb3Ž +ÐÁ$¢Tèx gÒe6¤P5pç×lƒ†ÂÓ0½®y¢¡Ó8¼¦£f¬Q3+„ÇÇ98˰±×ÃF+˜‚§ò¦Ĕ5Záü°^ß›óÃú2CsÌ®j”vD;H˜†CÒÈù0\K†3N‚OE‡×¤5ªÈú’†b ¦ÙÕ°Ë~+€ô²Ù +ÕzÅ|+€Â³¡Ù +ÕàÙÈ|+€Â3vÚ +ÑÐ÷Ö­€±$ͬwœ·Üõ¤Qfà±X-ˆ)i”Çg%g.Ó3Ëov–A=Ñ2Lk šv‘ýZÁ—l³æÃðäxïhQ5+q> šýBAçc³àã̦|b¾ à©]•v`>°v¼?žñÔÇ3Ó&€ª­~ë?šùa `¬Ã3W,ō¸ûòéQ<îŸÏßVÇ^|:î_Ž«aè'ñËj÷ºÚ–ª7ùŠ›#Ñïoð|þ¶ø\Ê«rendstream +endobj +2573 0 obj +1217 +endobj +2574 0 obj<>>>/Annots 1228 0 R>>endobj +2575 0 obj<>stream +xÚ՚Mo7†ïú<&‡l8üæÑ±£¢‡ ©­ÜrQíµ«V_•ä6?¿$‡«åˆÆ·Nl@À«•(=ÜÙ÷…fçï™þAx%´÷›Ù‡Åìý< +%ÅâQ€Ây#oËß×½Ø=ŠëÝöÔoOÇ·‹?g3ÙÉ´B~€üpûKZª“ÂiÛ±1v¶Šµ¸Ë«¿xÃáI¼Ÿ?/} §]zmúÀ¯ÇåSŸ?DùN¥ï˜žêXüò»RKì d«ªðPé¤ÍÕáéy3ì¤qiŸ8@Òt2v&ÓI—Î ª†dWêå¶?=¶…M«Îó9$ ,Ÿ>ÝéªF@s9&–›þxXíO«Ý¶œÀ˜^Ì’Æ :=&<€ªjðB9{¿/7ûu¹ütàsùÑp.¢íÈt¡hؼDk¹ë{ñÃuš·â&™éBx|Xêj}Üå¥ ¦g‚]JîšvÉ:4(c3]Q•.…€µ j¿˜¯¶Ÿ–‡¿ú‡ë?v«ûþۛoo ®üŸMT *ÁèbS%€P4•` º㐡ø´¬.•CU¨]ŠkÈPtàѤJÈ jè 0 +Oj´Œ˜¢6…jÌjç;eMNš›þqù¼>‡¼ ŠUQ à%hP4Õàjÿ›qÐP|¶vÀñ<Úi\YÖ1C±éÚ¸.1ƒªa3µmÍ8f(@U{×%fP5€ªö®Ù …úÜ‚ª<¨}k¶ACáIìZcÈiÓZÉÚ´~EÐÔujд ÕãCÿ›eÐÀ堁P»ßû`¨Æ š˜yÑ8ãr)ƒV—+¼PŒ•Þp ùœl†P5€XtÆ7C¨:¸€Ú4C¨@myx +š!T žbÝ5#ᤇP4l2¼v`XCf²P=\Ø¥2;ßѦ’f2íyàó¾ßÎÏ=3›·€‘ gL}¹ŒcaÚýŠûçB3à¦ÍoYOPhÖ¶Óηe~S†b3ÐÜý70½£¦xßû§ØThný«ð¢“ÄûÆ?²`ò< ê€*ØTh.ÖNÏÍíÕ|!މë¯_îÄÝîñôïòЋ/‡ÝÓa¹Ùô‡£ø´Ü>/×ÔØ´!ï<öA¿ÿ³ZÕ}ümöÿžÚendstream +endobj +2576 0 obj +1201 +endobj +2577 0 obj<>>>/Annots 1271 0 R>>endobj +2578 0 obj<>stream +xÚ՚ËsA‡ïüsÔCÖy?޾âEËHyñ‚fƒX¼¢–½=Ó½ì`•o¶IŠª_–4|ÌlÐÙ¯%$|+a|þù´ž<›Mž\&¡¥˜Ý å’ðÁŠÙí£ÙüãªÛ;ñ|»9ö›ãáñìËäål"; òÊ7ׯDНÞ¸.еH²óVbš«ÿöû…xri…Rùñ‚†ûz¸/<à´ïÅ£*»†¿U=:N¥ž®Û\J%ø­Ì¿éþù—2ætð¼áÔž-ÐI ˜ˆVÊkHv»Û·»~s¹\õ}xœkzÓi.˜ˆj›E&X@Ø,©sˆ4o%»²oóEŸ éðŸñ¹äáÃRjÙ%J# K™'oÓýâ~=œZÖÃkÁ²M Üæš¹0Ut±,Þu¼ßo +™Ñ]à³|m<Ÿ°ËÀg(UxAbyÑ>헻ãr»)˗àÎ ÛxÎc›&ª(Ux.`›yùc¾Þ­Êég"ŸÓ¯g ¶–, µØZÚ®ê kÎ +Ñq*ÅÓ5öa×8#Kƒ‚s7PUãŒÂþDª4c³]µáÕ5v„ +¥]Ù`¨v„ŠÌUÓ¢“†ºUQMIž´ôŽˆ©jt¶œkƒj0t6)lVŒeÓ ÛL‘ ¦ +0Dl2leÓÂóßÙ`ªð¼ÃFÃV6-<§°µä}‰¡¢súïT3TA՜•¡ãš¯hÜâ±&ÐG6ÙJMcaµ#™æ +:ðë~³8~|,]Ž ¾±´-ªXCµ´ÃFÅØ3-¾²9Ï`ªËò2öLƒÎ¤ˆ}ªxÓHg`Q5sÏ´£ÃS<ƒ©ŒžµeZpAæBŠR÷‰¬-ÓÂs[K–†ŠÎ%l-mÏ uÐ3g…è8•âiÿ°iŒuØ dþ4ƒi4^d+ÓL—?ÏBcC@óуk0TÂlVŒ]Ó⃍'O®ÁTjÉÙ4-6I3l4tç½JÒ›±i€:Ñ»˜Ó¨±Ùº¦…Òi.¤(Ux‘f×l]ÓÂó8¹.BÀPÑy\·]3ÔAל¢ãà œ¥kÂîÑn˜€G871®Ñ®6Íûåmõ‘F1éSˆ›Áà$¼xCµ, Â{¦Å§i^<ƒ©Ô4 +çjš¢ v1 ¦ŠNÑüš±iZ€RÒيi¤>endobj +2581 0 obj<>endobj +2582 0 obj<>endobj +2583 0 obj<>endobj +2584 0 obj<>endobj +2585 0 obj<>endobj +2586 0 obj<>endobj +2587 0 obj<>endobj +2588 0 obj<>endobj +2589 0 obj<>endobj +2590 0 obj<>endobj +2591 0 obj<>endobj +2592 0 obj<>endobj +2593 0 obj<>endobj +2594 0 obj<>endobj +2595 0 obj<>endobj +2596 0 obj<>endobj +2597 0 obj<>endobj +2598 0 obj<>endobj +2599 0 obj<>endobj +2600 0 obj<>endobj +2601 0 obj<>endobj +2602 0 obj<>endobj +2603 0 obj<>endobj +2604 0 obj<>endobj +2605 0 obj<>endobj +2606 0 obj<>endobj +2607 0 obj<>endobj +2608 0 obj<>endobj +2609 0 obj<>endobj +2610 0 obj<>endobj +2611 0 obj<>endobj +2612 0 obj<>endobj +2613 0 obj<>endobj +2614 0 obj<>endobj +2615 0 obj<>endobj +2616 0 obj<>endobj +2617 0 obj<>endobj +2618 0 obj<>endobj +2619 0 obj<>endobj +2620 0 obj<>endobj +2621 0 obj<>endobj +2622 0 obj<>endobj +2623 0 obj<>endobj +2624 0 obj<>endobj +2625 0 obj<>endobj +2626 0 obj<>endobj +2627 0 obj<>endobj +2628 0 obj<>endobj +2629 0 obj<>endobj +2630 0 obj<>endobj +2631 0 obj<>endobj +2632 0 obj<>endobj +2633 0 obj<>endobj +2634 0 obj<>endobj +2635 0 obj<>endobj +2636 0 obj<>endobj +2637 0 obj<>endobj +2638 0 obj<>endobj +2639 0 obj<>endobj +2640 0 obj<>endobj +2641 0 obj<>endobj +2642 0 obj<>endobj +2643 0 obj<>endobj +2644 0 obj<>endobj +2645 0 obj<>endobj +2646 0 obj<>endobj +2647 0 obj<>endobj +2648 0 obj<>endobj +2649 0 obj<>endobj +2650 0 obj<>endobj +2651 0 obj<>endobj +2652 0 obj<>endobj +2653 0 obj<>endobj +2654 0 obj<>endobj +2655 0 obj<>endobj +2656 0 obj<>endobj +2657 0 obj<>endobj +2658 0 obj<>endobj +2659 0 obj<>endobj +2660 0 obj<>endobj +2661 0 obj<>endobj +2662 0 obj<>endobj +2663 0 obj<>endobj +2664 0 obj<>endobj +2665 0 obj<>endobj +2666 0 obj<>endobj +2667 0 obj<>endobj +2668 0 obj<>endobj +2669 0 obj<>endobj +2670 0 obj<>endobj +2671 0 obj<>endobj +2672 0 obj<>endobj +2673 0 obj<>endobj +2674 0 obj<>endobj +2675 0 obj<>endobj +2676 0 obj<>endobj +2677 0 obj<>endobj +2678 0 obj<>endobj +2679 0 obj<>endobj +2680 0 obj<>endobj +2681 0 obj<>endobj +2682 0 obj<>endobj +2683 0 obj<>endobj +2684 0 obj<>endobj +2685 0 obj<>endobj +2686 0 obj<>endobj +2687 0 obj<>endobj +2688 0 obj<>endobj +2689 0 obj<>endobj +2690 0 obj<>endobj +2691 0 obj<>endobj +2692 0 obj<>endobj +2693 0 obj<>endobj +2694 0 obj<>endobj +2695 0 obj<>endobj +2696 0 obj<>endobj +2697 0 obj<>endobj +2698 0 obj<>endobj +2699 0 obj<>endobj +2700 0 obj<>endobj +2701 0 obj<>endobj +2702 0 obj<>endobj +2703 0 obj<>endobj +2704 0 obj<>endobj +2705 0 obj<>endobj +2706 0 obj<>endobj +2707 0 obj<>endobj +2708 0 obj<>endobj +2709 0 obj<>endobj +2710 0 obj<>endobj +2711 0 obj<>endobj +2712 0 obj<>endobj +2713 0 obj<>endobj +2714 0 obj<>endobj +2715 0 obj<>endobj +2716 0 obj<>endobj +2717 0 obj<>endobj +2718 0 obj<>endobj +2719 0 obj<>endobj +2720 0 obj<>endobj +2721 0 obj<>endobj +2722 0 obj<>endobj +2723 0 obj<>endobj +2724 0 obj<>endobj +2725 0 obj<>endobj +2726 0 obj<>endobj +2727 0 obj<>endobj +2728 0 obj<>endobj +2729 0 obj<>endobj +2730 0 obj<>endobj +2731 0 obj<>endobj +2732 0 obj<>endobj +2733 0 obj<>endobj +2734 0 obj<>endobj +2735 0 obj<>endobj +2736 0 obj<>endobj +2737 0 obj<>endobj +2738 0 obj<>endobj +2739 0 obj<>endobj +2740 0 obj<>endobj +2741 0 obj<>endobj +2742 0 obj<>endobj +2743 0 obj<>endobj +2744 0 obj<>endobj +2745 0 obj<>endobj +2746 0 obj<>endobj +2747 0 obj<>endobj +2748 0 obj<>endobj +2749 0 obj<>endobj +2750 0 obj<>endobj +2751 0 obj<>endobj +2752 0 obj<>endobj +2753 0 obj<>endobj +2754 0 obj<>endobj +2755 0 obj<>endobj +2756 0 obj<>endobj +2757 0 obj<>endobj +2758 0 obj<>endobj +2759 0 obj<>endobj +2760 0 obj<>endobj +2761 0 obj<>endobj +2762 0 obj<>endobj +2763 0 obj<>endobj +2764 0 obj<>endobj +2765 0 obj<>endobj +2766 0 obj<>endobj +2767 0 obj<>endobj +2768 0 obj<>endobj +2769 0 obj<>endobj +2770 0 obj<>endobj +2771 0 obj<>endobj +2772 0 obj<>endobj +2773 0 obj<>endobj +2774 0 obj<>endobj +2775 0 obj<>endobj +2776 0 obj<>endobj +2777 0 obj<>endobj +2778 0 obj<>endobj +2779 0 obj<>endobj +2780 0 obj<>endobj +2781 0 obj<>endobj +2782 0 obj<>endobj +2783 0 obj<>endobj +2784 0 obj<>endobj +2785 0 obj<>endobj +2786 0 obj<>endobj +2787 0 obj<>endobj +2788 0 obj<>endobj +2789 0 obj<>endobj +2790 0 obj<>endobj +2791 0 obj<>endobj +2792 0 obj<>endobj +2793 0 obj<>endobj +2794 0 obj<>endobj +2795 0 obj<>endobj +2796 0 obj<>endobj +2797 0 obj<>endobj +2798 0 obj<>endobj +2799 0 obj<>endobj +2800 0 obj<>endobj +2801 0 obj<>endobj +2802 0 obj<>endobj +2803 0 obj<>endobj +2804 0 obj<>endobj +2805 0 obj<>endobj +2806 0 obj<>endobj +2807 0 obj<>endobj +2808 0 obj<>endobj +2809 0 obj<>endobj +2810 0 obj<>endobj +2811 0 obj<>endobj +2812 0 obj<>endobj +2813 0 obj<>endobj +2814 0 obj<>endobj +2815 0 obj<>endobj +2816 0 obj<>endobj +2817 0 obj<>endobj +2818 0 obj<>endobj +2819 0 obj<>endobj +2820 0 obj<>endobj +2821 0 obj<>endobj +2822 0 obj<>endobj +2823 0 obj<>endobj +2824 0 obj<>endobj +2825 0 obj<>endobj +2826 0 obj<>endobj +2827 0 obj<>endobj +2828 0 obj<>endobj +2829 0 obj<>endobj +2830 0 obj<>endobj +2831 0 obj<>endobj +2832 0 obj<>endobj +2833 0 obj<>endobj +2834 0 obj<>endobj +2835 0 obj<>endobj +2836 0 obj<>endobj +2837 0 obj<>endobj +2838 0 obj<>endobj +2839 0 obj<>endobj +2840 0 obj<>endobj +2841 0 obj<>endobj +2842 0 obj<>endobj +2843 0 obj<>endobj +2844 0 obj<>endobj +2845 0 obj<>endobj +2846 0 obj<>endobj +2847 0 obj<>endobj +2848 0 obj<>endobj +2849 0 obj<>endobj +2850 0 obj<>endobj +2851 0 obj<>endobj +2852 0 obj<>endobj +2853 0 obj<>endobj +2854 0 obj<>endobj +2855 0 obj<>endobj +2856 0 obj<>endobj +2857 0 obj<>endobj +2858 0 obj<>endobj +2859 0 obj<>endobj +2860 0 obj<>endobj +2861 0 obj<>endobj +2862 0 obj<>endobj +2863 0 obj<>endobj +2864 0 obj<>endobj +2865 0 obj<>endobj +2866 0 obj<>endobj +2867 0 obj<>endobj +2868 0 obj<>endobj +2869 0 obj<>endobj +2870 0 obj<>endobj +2871 0 obj<>endobj +2872 0 obj<>endobj +2873 0 obj<>endobj +2874 0 obj<>endobj +2875 0 obj<>endobj +2876 0 obj<>endobj +2877 0 obj<>endobj +2878 0 obj<>endobj +2879 0 obj<>endobj +2880 0 obj<>endobj +2881 0 obj<>endobj +2882 0 obj<>endobj +2883 0 obj<>endobj +2884 0 obj<>endobj +2885 0 obj<>endobj +2886 0 obj<>endobj +2887 0 obj<>endobj +2888 0 obj<>endobj +2889 0 obj<>endobj +2890 0 obj<>endobj +2891 0 obj<>endobj +2892 0 obj<>endobj +2893 0 obj<>endobj +2894 0 obj<>endobj +2895 0 obj<>endobj +2896 0 obj<>endobj +2897 0 obj<>endobj +2898 0 obj<>endobj +2899 0 obj<>endobj +2900 0 obj<>endobj +2901 0 obj<>endobj +2902 0 obj<>endobj +2903 0 obj<>endobj +2904 0 obj<>endobj +2905 0 obj<>endobj +2906 0 obj<>endobj +2907 0 obj<>endobj +2908 0 obj<>endobj +2909 0 obj<>endobj +2910 0 obj<>endobj +2911 0 obj<>endobj +2912 0 obj<>endobj +2913 0 obj<>endobj +2914 0 obj<>endobj +2915 0 obj<>endobj +2916 0 obj<>endobj +2917 0 obj<>endobj +2918 0 obj<>endobj +2919 0 obj<>endobj +2920 0 obj<>endobj +2921 0 obj<>endobj +2922 0 obj<>endobj +2923 0 obj<>endobj +2924 0 obj<>endobj +2925 0 obj<>endobj +2926 0 obj<>endobj +2927 0 obj<>endobj +2928 0 obj<>endobj +2929 0 obj<>endobj +2930 0 obj<>endobj +2931 0 obj<>endobj +2932 0 obj<>endobj +2933 0 obj<>endobj +2934 0 obj<>endobj +2935 0 obj<>endobj +2936 0 obj<>endobj +2937 0 obj<>endobj +2938 0 obj<>endobj +2939 0 obj<>endobj +2940 0 obj<>endobj +2941 0 obj<>endobj +2942 0 obj<>endobj +2943 0 obj<>endobj +2944 0 obj<>endobj +2945 0 obj<>endobj +2946 0 obj<>endobj +2947 0 obj<>endobj +2948 0 obj<>endobj +2949 0 obj<>endobj +2950 0 obj<>endobj +2951 0 obj<>endobj +2952 0 obj<>endobj +2953 0 obj<>endobj +2954 0 obj<>endobj +2955 0 obj<>endobj +2956 0 obj<>endobj +2957 0 obj<>endobj +2958 0 obj<>endobj +2959 0 obj<>endobj +2960 0 obj<>endobj +2961 0 obj<>endobj +2962 0 obj<>endobj +2963 0 obj<>endobj +2964 0 obj<>endobj +2965 0 obj<>endobj +2966 0 obj<>endobj +2967 0 obj<>endobj +2968 0 obj<>endobj +2969 0 obj<>endobj +2970 0 obj<>endobj +2971 0 obj<>endobj +2972 0 obj<>endobj +2973 0 obj<>endobj +2974 0 obj<>endobj +2975 0 obj<>endobj +2976 0 obj<>endobj +2977 0 obj<>endobj +2978 0 obj<>endobj +2979 0 obj<>endobj +2980 0 obj<>endobj +2981 0 obj<>endobj +2982 0 obj<>endobj +2983 0 obj<>endobj +2984 0 obj<>endobj +2985 0 obj<>endobj +2986 0 obj<>endobj +2987 0 obj<>endobj +2988 0 obj<>endobj +2989 0 obj<>endobj +2990 0 obj<>endobj +2991 0 obj<>endobj +2992 0 obj<>endobj +2993 0 obj<>endobj +2994 0 obj<>endobj +2995 0 obj<>endobj +2996 0 obj<>endobj +2997 0 obj<>endobj +2998 0 obj<>endobj +2999 0 obj<>endobj +3000 0 obj<>endobj +3001 0 obj<>endobj +3002 0 obj<>endobj +3003 0 obj<>endobj +3004 0 obj<>endobj +3005 0 obj<>endobj +3006 0 obj<>endobj +3007 0 obj<>endobj +3008 0 obj<>endobj +3009 0 obj<>endobj +3010 0 obj<>endobj +3011 0 obj<>endobj +3012 0 obj<>endobj +3013 0 obj<>endobj +3014 0 obj<>endobj +3015 0 obj<>endobj +3016 0 obj<>endobj +3017 0 obj<>endobj +3018 0 obj<>endobj +3019 0 obj<>endobj +3020 0 obj<>endobj +3021 0 obj<>endobj +3022 0 obj<>endobj +3023 0 obj<>endobj +3024 0 obj<>endobj +3025 0 obj<>endobj +3026 0 obj<>endobj +3027 0 obj<>endobj +3028 0 obj<>endobj +3029 0 obj<>endobj +3030 0 obj<>endobj +3031 0 obj<>endobj +3032 0 obj<>endobj +3033 0 obj<>endobj +3034 0 obj<>endobj +3035 0 obj<>endobj +3036 0 obj<>endobj +3037 0 obj<>endobj +3038 0 obj<>endobj +3039 0 obj<>endobj +3040 0 obj<>endobj +3041 0 obj<>endobj +3042 0 obj<>endobj +3043 0 obj<>endobj +3044 0 obj<>endobj +3045 0 obj<>endobj +3046 0 obj<>endobj +3047 0 obj<>endobj +3048 0 obj<>endobj +3049 0 obj<>endobj +3050 0 obj<>endobj +3051 0 obj<>endobj +3052 0 obj<>endobj +3053 0 obj<>endobj +3054 0 obj<>endobj +3055 0 obj<>endobj +3056 0 obj<>endobj +3057 0 obj<>endobj +3058 0 obj<>endobj +3059 0 obj<>endobj +3060 0 obj<>endobj +3061 0 obj<>endobj +3062 0 obj<>endobj +3063 0 obj<>endobj +3064 0 obj<>endobj +3065 0 obj<>endobj +3066 0 obj<>endobj +3067 0 obj<>endobj +3068 0 obj<>endobj +3069 0 obj<>endobj +3070 0 obj<>endobj +3071 0 obj<>endobj +3072 0 obj<>endobj +3073 0 obj<>endobj +3074 0 obj<>endobj +3075 0 obj<>endobj +3076 0 obj<>endobj +3077 0 obj<>endobj +3078 0 obj<>endobj +3079 0 obj<>endobj +3080 0 obj<>endobj +3081 0 obj<>endobj +3082 0 obj<>endobj +3083 0 obj<>endobj +3084 0 obj<>endobj +3085 0 obj<>endobj +3086 0 obj<>endobj +3087 0 obj<>endobj +3088 0 obj<>endobj +3089 0 obj<>endobj +3090 0 obj<>endobj +3091 0 obj<>endobj +3092 0 obj<>endobj +3093 0 obj<>endobj +3094 0 obj<>endobj +3095 0 obj<>endobj +3096 0 obj<>endobj +3097 0 obj<>endobj +3098 0 obj<>endobj +3099 0 obj<>endobj +3100 0 obj<>endobj +3101 0 obj<>endobj +3102 0 obj<>endobj +3103 0 obj<>endobj +3104 0 obj<>endobj +3105 0 obj<>endobj +3106 0 obj<>endobj +3107 0 obj<>endobj +3108 0 obj<>endobj +3109 0 obj<>endobj +3110 0 obj<>endobj +3111 0 obj<>endobj +3112 0 obj<>endobj +3113 0 obj<>endobj +3114 0 obj<>endobj +3115 0 obj<>endobj +3116 0 obj<>endobj +3117 0 obj<>endobj +3118 0 obj<>endobj +3119 0 obj<>endobj +3120 0 obj<>endobj +3121 0 obj<>endobj +3122 0 obj<>endobj +3123 0 obj<>endobj +3124 0 obj<>endobj +3125 0 obj<>endobj +3126 0 obj<>endobj +3127 0 obj<>endobj +3128 0 obj<>endobj +3129 0 obj<>endobj +3130 0 obj<>endobj +3131 0 obj<>endobj +3132 0 obj<>endobj +3133 0 obj<>endobj +3134 0 obj<>endobj +3135 0 obj<>endobj +3136 0 obj<>endobj +3137 0 obj<>endobj +3138 0 obj<>endobj +3139 0 obj<>endobj +3140 0 obj<>endobj +3141 0 obj<>endobj +3142 0 obj<>endobj +3143 0 obj<>endobj +3144 0 obj<>endobj +3145 0 obj<>endobj +3146 0 obj<>endobj +3147 0 obj<>endobj +3148 0 obj<>endobj +3149 0 obj<>endobj +3150 0 obj<>endobj +3151 0 obj<>endobj +3152 0 obj<>endobj +3153 0 obj<>endobj +3154 0 obj<>endobj +3155 0 obj<>endobj +3156 0 obj<>endobj +3157 0 obj<>endobj +3158 0 obj<>endobj +3159 0 obj<>endobj +3160 0 obj<>endobj +3161 0 obj<>endobj +3162 0 obj<>endobj +3163 0 obj<>endobj +3164 0 obj<>endobj +3165 0 obj<>endobj +3166 0 obj<>endobj +3167 0 obj<>endobj +3168 0 obj<>endobj +3169 0 obj<>endobj +3170 0 obj<>endobj +3171 0 obj<>endobj +3172 0 obj<>endobj +3173 0 obj<>endobj +3174 0 obj<>endobj +3175 0 obj<>endobj +3176 0 obj<>endobj +3177 0 obj<>endobj +3178 0 obj<>endobj +3179 0 obj<>endobj +3180 0 obj<>endobj +3181 0 obj<>endobj +3182 0 obj<>endobj +3183 0 obj<>endobj +3184 0 obj<>endobj +3185 0 obj<>endobj +3186 0 obj<>endobj +3187 0 obj<>endobj +3188 0 obj<>endobj +3189 0 obj<>endobj +3190 0 obj<>endobj +3191 0 obj<>endobj +3192 0 obj<>endobj +3193 0 obj<>endobj +3194 0 obj<>endobj +3195 0 obj<>endobj +3196 0 obj<>endobj +3197 0 obj<>endobj +3198 0 obj<>endobj +3199 0 obj<>endobj +3200 0 obj<>endobj +3201 0 obj<>endobj +3202 0 obj<>endobj +3203 0 obj<>endobj +3204 0 obj<>endobj +3205 0 obj<>endobj +3206 0 obj<>endobj +3207 0 obj<>endobj +3208 0 obj<>endobj +3209 0 obj<>endobj +3210 0 obj<>endobj +3211 0 obj<>endobj +3212 0 obj<>endobj +3213 0 obj<>endobj +3214 0 obj<>endobj +3215 0 obj<>endobj +3216 0 obj<>endobj +3217 0 obj<>endobj +3218 0 obj<>endobj +3219 0 obj<>endobj +3220 0 obj<>endobj +3221 0 obj<>endobj +3222 0 obj<>endobj +3223 0 obj<>endobj +3224 0 obj<>endobj +3225 0 obj<>endobj +3226 0 obj<>endobj +3227 0 obj<>endobj +3228 0 obj<>endobj +3229 0 obj<>endobj +3230 0 obj<>endobj +3231 0 obj<>endobj +3232 0 obj<>endobj +3233 0 obj<>endobj +3234 0 obj<>endobj +3235 0 obj<>endobj +3236 0 obj<>endobj +3237 0 obj<>endobj +3238 0 obj<>endobj +3239 0 obj<>endobj +3240 0 obj<>endobj +3241 0 obj<>endobj +3242 0 obj<>endobj +3243 0 obj<>endobj +3244 0 obj<>endobj +3245 0 obj<>endobj +3246 0 obj<>endobj +3247 0 obj<>endobj +3248 0 obj<>endobj +3249 0 obj<>endobj +3250 0 obj<>endobj +3251 0 obj<>endobj +3252 0 obj<>endobj +3253 0 obj<>endobj +3254 0 obj<>endobj +3255 0 obj<>endobj +3256 0 obj<>endobj +3257 0 obj<>endobj +3258 0 obj<>endobj +3259 0 obj<>endobj +3260 0 obj<>endobj +3261 0 obj<>endobj +3262 0 obj<>endobj +3263 0 obj<>endobj +3264 0 obj<>endobj +3265 0 obj<>endobj +3266 0 obj<>endobj +3267 0 obj<>endobj +3268 0 obj<>endobj +3269 0 obj<>endobj +3270 0 obj<>endobj +3271 0 obj<>endobj +3272 0 obj<>endobj +3273 0 obj<>endobj +3274 0 obj<>endobj +3275 0 obj<>endobj +3276 0 obj<>endobj +3277 0 obj<>endobj +3278 0 obj<>endobj +3279 0 obj<>endobj +3280 0 obj<>endobj +3281 0 obj<>endobj +3282 0 obj<>endobj +3283 0 obj<>endobj +3284 0 obj<>endobj +3285 0 obj<>endobj +3286 0 obj<>endobj +3287 0 obj<>endobj +3288 0 obj<>endobj +3289 0 obj<>endobj +3290 0 obj<>endobj +3291 0 obj<>endobj +3292 0 obj<>endobj +3293 0 obj<>endobj +3294 0 obj<>endobj +3295 0 obj<>endobj +3296 0 obj<>endobj +3297 0 obj<>endobj +3298 0 obj<>endobj +3299 0 obj<>endobj +3300 0 obj<>endobj +3301 0 obj<>endobj +3302 0 obj<>endobj +3303 0 obj<>endobj +3304 0 obj<>endobj +3305 0 obj<>endobj +3306 0 obj<>endobj +3307 0 obj<>endobj +3308 0 obj<>endobj +3309 0 obj<>endobj +3310 0 obj<>endobj +3311 0 obj<>endobj +3312 0 obj<>endobj +3313 0 obj<>endobj +3314 0 obj<>endobj +3315 0 obj<>endobj +3316 0 obj<>endobj +3317 0 obj<>endobj +3318 0 obj<>endobj +3319 0 obj<>endobj +3320 0 obj<>endobj +3321 0 obj<>endobj +3322 0 obj<>endobj +3323 0 obj<>endobj +3324 0 obj<>endobj +3325 0 obj<>endobj +3326 0 obj<>endobj +3327 0 obj<>endobj +3328 0 obj<>endobj +3329 0 obj<>endobj +3330 0 obj<>endobj +3331 0 obj<>endobj +3332 0 obj<>endobj +3333 0 obj<>endobj +3334 0 obj<>endobj +3335 0 obj<>endobj +3336 0 obj<>endobj +3337 0 obj<>endobj +3338 0 obj<>endobj +3339 0 obj<>endobj +3340 0 obj<>endobj +3341 0 obj<>endobj +3342 0 obj<>endobj +3343 0 obj<>endobj +3344 0 obj<>endobj +3345 0 obj<>endobj +3346 0 obj<>endobj +3347 0 obj<>endobj +3348 0 obj<>endobj +3349 0 obj<>endobj +3350 0 obj<>endobj +3351 0 obj<>endobj +3352 0 obj<>endobj +3353 0 obj<>endobj +3354 0 obj<>endobj +3355 0 obj<>endobj +3356 0 obj<>endobj +3357 0 obj<>endobj +3358 0 obj<>endobj +3359 0 obj<>endobj +3360 0 obj<>endobj +3361 0 obj<>endobj +3362 0 obj<>endobj +3363 0 obj<>endobj +3364 0 obj<>endobj +3365 0 obj<>endobj +3366 0 obj<>endobj +3367 0 obj<>endobj +3368 0 obj<>endobj +3369 0 obj<>endobj +3370 0 obj<>endobj +3371 0 obj<>endobj +3372 0 obj<>endobj +3373 0 obj<>endobj +3374 0 obj<>endobj +3375 0 obj<>endobj +3376 0 obj<>endobj +3377 0 obj<>endobj +3378 0 obj<>endobj +3379 0 obj<>endobj +3380 0 obj<>endobj +3381 0 obj<>endobj +3382 0 obj<>endobj +3383 0 obj<>endobj +3384 0 obj<>endobj +3385 0 obj<>endobj +3386 0 obj<>endobj +3387 0 obj<>endobj +3388 0 obj<>endobj +3389 0 obj<>endobj +3390 0 obj<>endobj +3391 0 obj<>endobj +3392 0 obj<>endobj +3393 0 obj<>endobj +3394 0 obj<>endobj +3395 0 obj<>endobj +3396 0 obj<>endobj +3397 0 obj<>endobj +3398 0 obj<>endobj +3399 0 obj<>endobj +3400 0 obj<>endobj +3401 0 obj<>endobj +3402 0 obj<>endobj +3403 0 obj<>endobj +3404 0 obj<>endobj +3405 0 obj<>endobj +3406 0 obj<>endobj +3407 0 obj<>endobj +3408 0 obj<>endobj +3409 0 obj<>endobj +3410 0 obj<>1<>2<>20<>]>>>>endobj +xref +0 3411 +0000000000 65535 f +0000000015 00000 n +0000000233 00000 n +0000001790 00000 n +0000001864 00000 n +0000001942 00000 n +0000002019 00000 n +0000002098 00000 n +0000002174 00000 n +0000002255 00000 n +0000002339 00000 n +0000002398 00000 n +0000002503 00000 n +0000002609 00000 n +0000002715 00000 n +0000002753 00000 n +0000002859 00000 n +0000002964 00000 n +0000003070 00000 n +0000003108 00000 n +0000003213 00000 n +0000003318 00000 n +0000003422 00000 n +0000003460 00000 n +0000003565 00000 n +0000003671 00000 n +0000003777 00000 n +0000003882 00000 n +0000003988 00000 n +0000004094 00000 n +0000004200 00000 n +0000004305 00000 n +0000004411 00000 n +0000004491 00000 n +0000004596 00000 n +0000004702 00000 n +0000004808 00000 n +0000004846 00000 n +0000004951 00000 n +0000005057 00000 n +0000005162 00000 n +0000005268 00000 n +0000005374 00000 n +0000005480 00000 n +0000005585 00000 n +0000005691 00000 n +0000005764 00000 n +0000005869 00000 n +0000005975 00000 n +0000006081 00000 n +0000006187 00000 n +0000006232 00000 n +0000006337 00000 n +0000006443 00000 n +0000006549 00000 n +0000006587 00000 n +0000006692 00000 n +0000006798 00000 n +0000006904 00000 n +0000006942 00000 n +0000007047 00000 n +0000007153 00000 n +0000007259 00000 n +0000007365 00000 n +0000007410 00000 n +0000007514 00000 n +0000007538 00000 n +0000007643 00000 n +0000007749 00000 n +0000007855 00000 n +0000007893 00000 n +0000007998 00000 n +0000008104 00000 n +0000008210 00000 n +0000008316 00000 n +0000008422 00000 n +0000008474 00000 n +0000008579 00000 n +0000008685 00000 n +0000008791 00000 n +0000008897 00000 n +0000009003 00000 n +0000009055 00000 n +0000009160 00000 n +0000009266 00000 n +0000009372 00000 n +0000009478 00000 n +0000009584 00000 n +0000009636 00000 n +0000009741 00000 n +0000009847 00000 n +0000009953 00000 n +0000010059 00000 n +0000010165 00000 n +0000010217 00000 n +0000010322 00000 n +0000010428 00000 n +0000010534 00000 n +0000010640 00000 n +0000010746 00000 n +0000010798 00000 n +0000010904 00000 n +0000011011 00000 n +0000011118 00000 n +0000011225 00000 n +0000011332 00000 n +0000011390 00000 n +0000011496 00000 n +0000011603 00000 n +0000011637 00000 n +0000011743 00000 n +0000011850 00000 n +0000011957 00000 n +0000012064 00000 n +0000012114 00000 n +0000012220 00000 n +0000012327 00000 n +0000012434 00000 n +0000012541 00000 n +0000012591 00000 n +0000012697 00000 n +0000012804 00000 n +0000012838 00000 n +0000012944 00000 n +0000013051 00000 n +0000013158 00000 n +0000013265 00000 n +0000013371 00000 n +0000013429 00000 n +0000013535 00000 n +0000013642 00000 n +0000013749 00000 n +0000013856 00000 n +0000013962 00000 n +0000014020 00000 n +0000014126 00000 n +0000014233 00000 n +0000014340 00000 n +0000014447 00000 n +0000014553 00000 n +0000014611 00000 n +0000014717 00000 n +0000014824 00000 n +0000014931 00000 n +0000015038 00000 n +0000015144 00000 n +0000015202 00000 n +0000015307 00000 n +0000015413 00000 n +0000015519 00000 n +0000015625 00000 n +0000015729 00000 n +0000015787 00000 n +0000015893 00000 n +0000016000 00000 n +0000016107 00000 n +0000016214 00000 n +0000016320 00000 n +0000016378 00000 n +0000016484 00000 n +0000016591 00000 n +0000016625 00000 n +0000016731 00000 n +0000016838 00000 n +0000016872 00000 n +0000016978 00000 n +0000017085 00000 n +0000017192 00000 n +0000017299 00000 n +0000017406 00000 n +0000017511 00000 n +0000017616 00000 n +0000017722 00000 n +0000017829 00000 n +0000017936 00000 n +0000018043 00000 n +0000018150 00000 n +0000018257 00000 n +0000018364 00000 n +0000018471 00000 n +0000018578 00000 n +0000018685 00000 n +0000018792 00000 n +0000018899 00000 n +0000019006 00000 n +0000019113 00000 n +0000019218 00000 n +0000019323 00000 n +0000019429 00000 n +0000019536 00000 n +0000019643 00000 n +0000019750 00000 n +0000019857 00000 n +0000019964 00000 n +0000020071 00000 n +0000020178 00000 n +0000020285 00000 n +0000020392 00000 n +0000020499 00000 n +0000020606 00000 n +0000020713 00000 n +0000020820 00000 n +0000020927 00000 n +0000021034 00000 n +0000021141 00000 n +0000021248 00000 n +0000021355 00000 n +0000021462 00000 n +0000021569 00000 n +0000021676 00000 n +0000021783 00000 n +0000021890 00000 n +0000021997 00000 n +0000022104 00000 n +0000022211 00000 n +0000022318 00000 n +0000022425 00000 n +0000022532 00000 n +0000022639 00000 n +0000022746 00000 n +0000022853 00000 n +0000022960 00000 n +0000023067 00000 n +0000023174 00000 n +0000023281 00000 n +0000023388 00000 n +0000023495 00000 n +0000023602 00000 n +0000023709 00000 n +0000023816 00000 n +0000023923 00000 n +0000024030 00000 n +0000024137 00000 n +0000024244 00000 n +0000024351 00000 n +0000024458 00000 n +0000024565 00000 n +0000024672 00000 n +0000024779 00000 n +0000024886 00000 n +0000024993 00000 n +0000025100 00000 n +0000025207 00000 n +0000025314 00000 n +0000025421 00000 n +0000025528 00000 n +0000025635 00000 n +0000025742 00000 n +0000025849 00000 n +0000025956 00000 n +0000026063 00000 n +0000026170 00000 n +0000026277 00000 n +0000026384 00000 n +0000026491 00000 n +0000026598 00000 n +0000026705 00000 n +0000026812 00000 n +0000026919 00000 n +0000027026 00000 n +0000027133 00000 n +0000027240 00000 n +0000027347 00000 n +0000027454 00000 n +0000027561 00000 n +0000027668 00000 n +0000027775 00000 n +0000027882 00000 n +0000027989 00000 n +0000028096 00000 n +0000028203 00000 n +0000028310 00000 n +0000028417 00000 n +0000028524 00000 n +0000028631 00000 n +0000028738 00000 n +0000028845 00000 n +0000028952 00000 n +0000029059 00000 n +0000029166 00000 n +0000029273 00000 n +0000029379 00000 n +0000029485 00000 n +0000029591 00000 n +0000029697 00000 n +0000029802 00000 n +0000029907 00000 n +0000030012 00000 n +0000030117 00000 n +0000030222 00000 n +0000030327 00000 n +0000031353 00000 n +0000031460 00000 n +0000031567 00000 n +0000031674 00000 n +0000031781 00000 n +0000031888 00000 n +0000031995 00000 n +0000032102 00000 n +0000032209 00000 n +0000032316 00000 n +0000032423 00000 n +0000032530 00000 n +0000032637 00000 n +0000032744 00000 n +0000032851 00000 n +0000032958 00000 n +0000033065 00000 n +0000033172 00000 n +0000033279 00000 n +0000033386 00000 n +0000033491 00000 n +0000033597 00000 n +0000033704 00000 n +0000033811 00000 n +0000033918 00000 n +0000034025 00000 n +0000034132 00000 n +0000034239 00000 n +0000034346 00000 n +0000034453 00000 n +0000034560 00000 n +0000034667 00000 n +0000034774 00000 n +0000034881 00000 n +0000034988 00000 n +0000035095 00000 n +0000035202 00000 n +0000035309 00000 n +0000035416 00000 n +0000035523 00000 n +0000035630 00000 n +0000035737 00000 n +0000035844 00000 n +0000035951 00000 n +0000036058 00000 n +0000036163 00000 n +0000036268 00000 n +0000036373 00000 n +0000036479 00000 n +0000036585 00000 n +0000036692 00000 n +0000036799 00000 n +0000036906 00000 n +0000037013 00000 n +0000037120 00000 n +0000037227 00000 n +0000037333 00000 n +0000037440 00000 n +0000037547 00000 n +0000037654 00000 n +0000037760 00000 n +0000037867 00000 n +0000037973 00000 n +0000038080 00000 n +0000038187 00000 n +0000038294 00000 n +0000038399 00000 n +0000038504 00000 n +0000038609 00000 n +0000038715 00000 n +0000038822 00000 n +0000038928 00000 n +0000039035 00000 n +0000039142 00000 n +0000039249 00000 n +0000039356 00000 n +0000039462 00000 n +0000039569 00000 n +0000039676 00000 n +0000039783 00000 n +0000039890 00000 n +0000039997 00000 n +0000040103 00000 n +0000040210 00000 n +0000040317 00000 n +0000040424 00000 n +0000040529 00000 n +0000040634 00000 n +0000040739 00000 n +0000040845 00000 n +0000040951 00000 n +0000041058 00000 n +0000041165 00000 n +0000041272 00000 n +0000041379 00000 n +0000041486 00000 n +0000041593 00000 n +0000041700 00000 n +0000041806 00000 n +0000041913 00000 n +0000042020 00000 n +0000042127 00000 n +0000042232 00000 n +0000042338 00000 n +0000042442 00000 n +0000042547 00000 n +0000042652 00000 n +0000042757 00000 n +0000042862 00000 n +0000043744 00000 n +0000043849 00000 n +0000043954 00000 n +0000044060 00000 n +0000044167 00000 n +0000044274 00000 n +0000044381 00000 n +0000044488 00000 n +0000044595 00000 n +0000044702 00000 n +0000044809 00000 n +0000044916 00000 n +0000045023 00000 n +0000045130 00000 n +0000045237 00000 n +0000045344 00000 n +0000045451 00000 n +0000045558 00000 n +0000045663 00000 n +0000045768 00000 n +0000045874 00000 n +0000045979 00000 n +0000046084 00000 n +0000046190 00000 n +0000046297 00000 n +0000046404 00000 n +0000046511 00000 n +0000046618 00000 n +0000046725 00000 n +0000046832 00000 n +0000046939 00000 n +0000047046 00000 n +0000047153 00000 n +0000047260 00000 n +0000047367 00000 n +0000047474 00000 n +0000047581 00000 n +0000047688 00000 n +0000047795 00000 n +0000047902 00000 n +0000048009 00000 n +0000048116 00000 n +0000048223 00000 n +0000048330 00000 n +0000048437 00000 n +0000048544 00000 n +0000048651 00000 n +0000048758 00000 n +0000048865 00000 n +0000048972 00000 n +0000049079 00000 n +0000049186 00000 n +0000049293 00000 n +0000049400 00000 n +0000049507 00000 n +0000049614 00000 n +0000049721 00000 n +0000049828 00000 n +0000049935 00000 n +0000050042 00000 n +0000050148 00000 n +0000050253 00000 n +0000050358 00000 n +0000050463 00000 n +0000050985 00000 n +0000051092 00000 n +0000051199 00000 n +0000051306 00000 n +0000051413 00000 n +0000051520 00000 n +0000051627 00000 n +0000051734 00000 n +0000051840 00000 n +0000051947 00000 n +0000052054 00000 n +0000052161 00000 n +0000052268 00000 n +0000052375 00000 n +0000052482 00000 n +0000052588 00000 n +0000052695 00000 n +0000052802 00000 n +0000052909 00000 n +0000053016 00000 n +0000053123 00000 n +0000053230 00000 n +0000053336 00000 n +0000053443 00000 n +0000053550 00000 n +0000053657 00000 n +0000053764 00000 n +0000053871 00000 n +0000053978 00000 n +0000054085 00000 n +0000054191 00000 n +0000054298 00000 n +0000054405 00000 n +0000054512 00000 n +0000054619 00000 n +0000054726 00000 n +0000054832 00000 n +0000054939 00000 n +0000055046 00000 n +0000055153 00000 n +0000055260 00000 n +0000055367 00000 n +0000055474 00000 n +0000055581 00000 n +0000055687 00000 n +0000055794 00000 n +0000055901 00000 n +0000056008 00000 n +0000056115 00000 n +0000056222 00000 n +0000056329 00000 n +0000056434 00000 n +0000056539 00000 n +0000056644 00000 n +0000057086 00000 n +0000057193 00000 n +0000057300 00000 n +0000057407 00000 n +0000057514 00000 n +0000057621 00000 n +0000057728 00000 n +0000057835 00000 n +0000057942 00000 n +0000058049 00000 n +0000058156 00000 n +0000058263 00000 n +0000058370 00000 n +0000058477 00000 n +0000058584 00000 n +0000058691 00000 n +0000058798 00000 n +0000058905 00000 n +0000059012 00000 n +0000059119 00000 n +0000059226 00000 n +0000059333 00000 n +0000059440 00000 n +0000059547 00000 n +0000059654 00000 n +0000059761 00000 n +0000059868 00000 n +0000059975 00000 n +0000060082 00000 n +0000060189 00000 n +0000060296 00000 n +0000060403 00000 n +0000060510 00000 n +0000060617 00000 n +0000060724 00000 n +0000060831 00000 n +0000060938 00000 n +0000061045 00000 n +0000061152 00000 n +0000061259 00000 n +0000061366 00000 n +0000061473 00000 n +0000061580 00000 n +0000061687 00000 n +0000061794 00000 n +0000061901 00000 n +0000062008 00000 n +0000062115 00000 n +0000062222 00000 n +0000062329 00000 n +0000062436 00000 n +0000062543 00000 n +0000062649 00000 n +0000062754 00000 n +0000062859 00000 n +0000063309 00000 n +0000063416 00000 n +0000063523 00000 n +0000063630 00000 n +0000063736 00000 n +0000063843 00000 n +0000063950 00000 n +0000064057 00000 n +0000064164 00000 n +0000064271 00000 n +0000064378 00000 n +0000064485 00000 n +0000064591 00000 n +0000064698 00000 n +0000064805 00000 n +0000064912 00000 n +0000065019 00000 n +0000065126 00000 n +0000065233 00000 n +0000065339 00000 n +0000065446 00000 n +0000065553 00000 n +0000065660 00000 n +0000065767 00000 n +0000065874 00000 n +0000065981 00000 n +0000066088 00000 n +0000066194 00000 n +0000066301 00000 n +0000066408 00000 n +0000066515 00000 n +0000066622 00000 n +0000066729 00000 n +0000066836 00000 n +0000066943 00000 n +0000067049 00000 n +0000067156 00000 n +0000067263 00000 n +0000067370 00000 n +0000067477 00000 n +0000067584 00000 n +0000067691 00000 n +0000067798 00000 n +0000067904 00000 n +0000068011 00000 n +0000068118 00000 n +0000068225 00000 n +0000068332 00000 n +0000068439 00000 n +0000068546 00000 n +0000068653 00000 n +0000068759 00000 n +0000068865 00000 n +0000068970 00000 n +0000069075 00000 n +0000069525 00000 n +0000069632 00000 n +0000069739 00000 n +0000069846 00000 n +0000069953 00000 n +0000070060 00000 n +0000070167 00000 n +0000070274 00000 n +0000070381 00000 n +0000070488 00000 n +0000070595 00000 n +0000070702 00000 n +0000070809 00000 n +0000070916 00000 n +0000071023 00000 n +0000071130 00000 n +0000071237 00000 n +0000071344 00000 n +0000071451 00000 n +0000071558 00000 n +0000071665 00000 n +0000071772 00000 n +0000071879 00000 n +0000071986 00000 n +0000072093 00000 n +0000072200 00000 n +0000072307 00000 n +0000072414 00000 n +0000072521 00000 n +0000072628 00000 n +0000072735 00000 n +0000072842 00000 n +0000072949 00000 n +0000073056 00000 n +0000073163 00000 n +0000073270 00000 n +0000073377 00000 n +0000073484 00000 n +0000073591 00000 n +0000073698 00000 n +0000073805 00000 n +0000073912 00000 n +0000074019 00000 n +0000074126 00000 n +0000074233 00000 n +0000074340 00000 n +0000074447 00000 n +0000074554 00000 n +0000074661 00000 n +0000074768 00000 n +0000074875 00000 n +0000074981 00000 n +0000075086 00000 n +0000075191 00000 n +0000075633 00000 n +0000075740 00000 n +0000075847 00000 n +0000075954 00000 n +0000076060 00000 n +0000076167 00000 n +0000076274 00000 n +0000076381 00000 n +0000076488 00000 n +0000076595 00000 n +0000076702 00000 n +0000076809 00000 n +0000076915 00000 n +0000077022 00000 n +0000077129 00000 n +0000077236 00000 n +0000077343 00000 n +0000077450 00000 n +0000077557 00000 n +0000077664 00000 n +0000077770 00000 n +0000077877 00000 n +0000077984 00000 n +0000078091 00000 n +0000078198 00000 n +0000078305 00000 n +0000078412 00000 n +0000078519 00000 n +0000078625 00000 n +0000078732 00000 n +0000078839 00000 n +0000078946 00000 n +0000079053 00000 n +0000079160 00000 n +0000079267 00000 n +0000079374 00000 n +0000079480 00000 n +0000079587 00000 n +0000079694 00000 n +0000079801 00000 n +0000079908 00000 n +0000080015 00000 n +0000080122 00000 n +0000080229 00000 n +0000080335 00000 n +0000080442 00000 n +0000080549 00000 n +0000080656 00000 n +0000080763 00000 n +0000080870 00000 n +0000080977 00000 n +0000081084 00000 n +0000081189 00000 n +0000081294 00000 n +0000081399 00000 n +0000081849 00000 n +0000081956 00000 n +0000082063 00000 n +0000082170 00000 n +0000082277 00000 n +0000082384 00000 n +0000082491 00000 n +0000082598 00000 n +0000082705 00000 n +0000082812 00000 n +0000082919 00000 n +0000083026 00000 n +0000083133 00000 n +0000083240 00000 n +0000083347 00000 n +0000083454 00000 n +0000083561 00000 n +0000083668 00000 n +0000083775 00000 n +0000083882 00000 n +0000083989 00000 n +0000084096 00000 n +0000084203 00000 n +0000084310 00000 n +0000084417 00000 n +0000084524 00000 n +0000084631 00000 n +0000084738 00000 n +0000084845 00000 n +0000084952 00000 n +0000085059 00000 n +0000085166 00000 n +0000085273 00000 n +0000085380 00000 n +0000085487 00000 n +0000085594 00000 n +0000085701 00000 n +0000085808 00000 n +0000085915 00000 n +0000086022 00000 n +0000086129 00000 n +0000086236 00000 n +0000086343 00000 n +0000086450 00000 n +0000086557 00000 n +0000086664 00000 n +0000086771 00000 n +0000086878 00000 n +0000086985 00000 n +0000087092 00000 n +0000087199 00000 n +0000087305 00000 n +0000087410 00000 n +0000087515 00000 n +0000087620 00000 n +0000088070 00000 n +0000088177 00000 n +0000088284 00000 n +0000088391 00000 n +0000088498 00000 n +0000088605 00000 n +0000088712 00000 n +0000088819 00000 n +0000088925 00000 n +0000089032 00000 n +0000089139 00000 n +0000089246 00000 n +0000089353 00000 n +0000089460 00000 n +0000089567 00000 n +0000089674 00000 n +0000089780 00000 n +0000089887 00000 n +0000089994 00000 n +0000090101 00000 n +0000090208 00000 n +0000090315 00000 n +0000090422 00000 n +0000090529 00000 n +0000090635 00000 n +0000090742 00000 n +0000090849 00000 n +0000090956 00000 n +0000091063 00000 n +0000091170 00000 n +0000091277 00000 n +0000091384 00000 n +0000091490 00000 n +0000091597 00000 n +0000091704 00000 n +0000091811 00000 n +0000091918 00000 n +0000092025 00000 n +0000092132 00000 n +0000092239 00000 n +0000092345 00000 n +0000092452 00000 n +0000092559 00000 n +0000092666 00000 n +0000092773 00000 n +0000092880 00000 n +0000092987 00000 n +0000093094 00000 n +0000093200 00000 n +0000093307 00000 n +0000093414 00000 n +0000093520 00000 n +0000093625 00000 n +0000093730 00000 n +0000094172 00000 n +0000094279 00000 n +0000094386 00000 n +0000094493 00000 n +0000094600 00000 n +0000094707 00000 n +0000094814 00000 n +0000094921 00000 n +0000095028 00000 n +0000095135 00000 n +0000095242 00000 n +0000095349 00000 n +0000095456 00000 n +0000095563 00000 n +0000095670 00000 n +0000095777 00000 n +0000095884 00000 n +0000095991 00000 n +0000096098 00000 n +0000096205 00000 n +0000096312 00000 n +0000096419 00000 n +0000096526 00000 n +0000096633 00000 n +0000096740 00000 n +0000096847 00000 n +0000096954 00000 n +0000097061 00000 n +0000097168 00000 n +0000097275 00000 n +0000097382 00000 n +0000097489 00000 n +0000097596 00000 n +0000097703 00000 n +0000097810 00000 n +0000097917 00000 n +0000098024 00000 n +0000098131 00000 n +0000098238 00000 n +0000098345 00000 n +0000098452 00000 n +0000098559 00000 n +0000098666 00000 n +0000098773 00000 n +0000098880 00000 n +0000098987 00000 n +0000099094 00000 n +0000099201 00000 n +0000099308 00000 n +0000099415 00000 n +0000099522 00000 n +0000099629 00000 n +0000099735 00000 n +0000099840 00000 n +0000099945 00000 n +0000100395 00000 n +0000100502 00000 n +0000100609 00000 n +0000100716 00000 n +0000100823 00000 n +0000100929 00000 n +0000101036 00000 n +0000101143 00000 n +0000101250 00000 n +0000101357 00000 n +0000101464 00000 n +0000101571 00000 n +0000101678 00000 n +0000101784 00000 n +0000101891 00000 n +0000101998 00000 n +0000102105 00000 n +0000102212 00000 n +0000102319 00000 n +0000102426 00000 n +0000102533 00000 n +0000102639 00000 n +0000102746 00000 n +0000102853 00000 n +0000102960 00000 n +0000103067 00000 n +0000103174 00000 n +0000103281 00000 n +0000103388 00000 n +0000103494 00000 n +0000103601 00000 n +0000103708 00000 n +0000103815 00000 n +0000103922 00000 n +0000104029 00000 n +0000104136 00000 n +0000104243 00000 n +0000104349 00000 n +0000104456 00000 n +0000104563 00000 n +0000104670 00000 n +0000104777 00000 n +0000104884 00000 n +0000104991 00000 n +0000105098 00000 n +0000105204 00000 n +0000105311 00000 n +0000105418 00000 n +0000105525 00000 n +0000105632 00000 n +0000105739 00000 n +0000105845 00000 n +0000105951 00000 n +0000106055 00000 n +0000106160 00000 n +0000106610 00000 n +0000106717 00000 n +0000106824 00000 n +0000106931 00000 n +0000107038 00000 n +0000107145 00000 n +0000107252 00000 n +0000107359 00000 n +0000107466 00000 n +0000107573 00000 n +0000107680 00000 n +0000107787 00000 n +0000107894 00000 n +0000108001 00000 n +0000108108 00000 n +0000108215 00000 n +0000108322 00000 n +0000108429 00000 n +0000108536 00000 n +0000108643 00000 n +0000108750 00000 n +0000108857 00000 n +0000108964 00000 n +0000109071 00000 n +0000109178 00000 n +0000109285 00000 n +0000109392 00000 n +0000109499 00000 n +0000109606 00000 n +0000109713 00000 n +0000109820 00000 n +0000109927 00000 n +0000110034 00000 n +0000110141 00000 n +0000110248 00000 n +0000110355 00000 n +0000110462 00000 n +0000110569 00000 n +0000110676 00000 n +0000110783 00000 n +0000110890 00000 n +0000110997 00000 n +0000111104 00000 n +0000111211 00000 n +0000111318 00000 n +0000111426 00000 n +0000111534 00000 n +0000111642 00000 n +0000111750 00000 n +0000111858 00000 n +0000111966 00000 n +0000112073 00000 n +0000112179 00000 n +0000112285 00000 n +0000112391 00000 n +0000112852 00000 n +0000112959 00000 n +0000113067 00000 n +0000113175 00000 n +0000113283 00000 n +0000113391 00000 n +0000113499 00000 n +0000113607 00000 n +0000113715 00000 n +0000113822 00000 n +0000113930 00000 n +0000114038 00000 n +0000114146 00000 n +0000114254 00000 n +0000114362 00000 n +0000114470 00000 n +0000114578 00000 n +0000114685 00000 n +0000114793 00000 n +0000114901 00000 n +0000115009 00000 n +0000115117 00000 n +0000115225 00000 n +0000115333 00000 n +0000115441 00000 n +0000115548 00000 n +0000115656 00000 n +0000115764 00000 n +0000115872 00000 n +0000115980 00000 n +0000116088 00000 n +0000116196 00000 n +0000116304 00000 n +0000116411 00000 n +0000116519 00000 n +0000116627 00000 n +0000116735 00000 n +0000116843 00000 n +0000116951 00000 n +0000117059 00000 n +0000117167 00000 n +0000117274 00000 n +0000117382 00000 n +0000117490 00000 n +0000117598 00000 n +0000117706 00000 n +0000117814 00000 n +0000117922 00000 n +0000118030 00000 n +0000118137 00000 n +0000118245 00000 n +0000118352 00000 n +0000118458 00000 n +0000118564 00000 n +0000119060 00000 n +0000119168 00000 n +0000119276 00000 n +0000119384 00000 n +0000119492 00000 n +0000119600 00000 n +0000119708 00000 n +0000119816 00000 n +0000119924 00000 n +0000120032 00000 n +0000120140 00000 n +0000120248 00000 n +0000120356 00000 n +0000120464 00000 n +0000120572 00000 n +0000120680 00000 n +0000120788 00000 n +0000120896 00000 n +0000121004 00000 n +0000121112 00000 n +0000121220 00000 n +0000121328 00000 n +0000121436 00000 n +0000121544 00000 n +0000121652 00000 n +0000121760 00000 n +0000121868 00000 n +0000121976 00000 n +0000122084 00000 n +0000122192 00000 n +0000122300 00000 n +0000122408 00000 n +0000122516 00000 n +0000122624 00000 n +0000122732 00000 n +0000122840 00000 n +0000122948 00000 n +0000123056 00000 n +0000123164 00000 n +0000123272 00000 n +0000123380 00000 n +0000123488 00000 n +0000123596 00000 n +0000123704 00000 n +0000123812 00000 n +0000123920 00000 n +0000124028 00000 n +0000124136 00000 n +0000124244 00000 n +0000124352 00000 n +0000124460 00000 n +0000124568 00000 n +0000124675 00000 n +0000124781 00000 n +0000124887 00000 n +0000125392 00000 n +0000125500 00000 n +0000125608 00000 n +0000125716 00000 n +0000125824 00000 n +0000125932 00000 n +0000126039 00000 n +0000126147 00000 n +0000126255 00000 n +0000126363 00000 n +0000126471 00000 n +0000126579 00000 n +0000126687 00000 n +0000126795 00000 n +0000126902 00000 n +0000127010 00000 n +0000127118 00000 n +0000127226 00000 n +0000127334 00000 n +0000127442 00000 n +0000127550 00000 n +0000127658 00000 n +0000127765 00000 n +0000127873 00000 n +0000127981 00000 n +0000128089 00000 n +0000128197 00000 n +0000128305 00000 n +0000128413 00000 n +0000128521 00000 n +0000128628 00000 n +0000128736 00000 n +0000128844 00000 n +0000128952 00000 n +0000129060 00000 n +0000129168 00000 n +0000129276 00000 n +0000129384 00000 n +0000129491 00000 n +0000129599 00000 n +0000129707 00000 n +0000129815 00000 n +0000129923 00000 n +0000130031 00000 n +0000130139 00000 n +0000130247 00000 n +0000130354 00000 n +0000130462 00000 n +0000130570 00000 n +0000130678 00000 n +0000130786 00000 n +0000130893 00000 n +0000130999 00000 n +0000131105 00000 n +0000131210 00000 n +0000131715 00000 n +0000131823 00000 n +0000131931 00000 n +0000132039 00000 n +0000132147 00000 n +0000132255 00000 n +0000132363 00000 n +0000132471 00000 n +0000132579 00000 n +0000132687 00000 n +0000132795 00000 n +0000132903 00000 n +0000133011 00000 n +0000133119 00000 n +0000133227 00000 n +0000133335 00000 n +0000133443 00000 n +0000133551 00000 n +0000133659 00000 n +0000133767 00000 n +0000133875 00000 n +0000133983 00000 n +0000134091 00000 n +0000134199 00000 n +0000134307 00000 n +0000134415 00000 n +0000134523 00000 n +0000134631 00000 n +0000134739 00000 n +0000134847 00000 n +0000134955 00000 n +0000135063 00000 n +0000135171 00000 n +0000135279 00000 n +0000135387 00000 n +0000135495 00000 n +0000135603 00000 n +0000135711 00000 n +0000135819 00000 n +0000135927 00000 n +0000136035 00000 n +0000136143 00000 n +0000136251 00000 n +0000136359 00000 n +0000136467 00000 n +0000136575 00000 n +0000136683 00000 n +0000136791 00000 n +0000136899 00000 n +0000137007 00000 n +0000137115 00000 n +0000137222 00000 n +0000137328 00000 n +0000137434 00000 n +0000137930 00000 n +0000138038 00000 n +0000138146 00000 n +0000138253 00000 n +0000138361 00000 n +0000138469 00000 n +0000138577 00000 n +0000138685 00000 n +0000138793 00000 n +0000138901 00000 n +0000139009 00000 n +0000139116 00000 n +0000139224 00000 n +0000139332 00000 n +0000139440 00000 n +0000139548 00000 n +0000139656 00000 n +0000139764 00000 n +0000139872 00000 n +0000139979 00000 n +0000140087 00000 n +0000140195 00000 n +0000140303 00000 n +0000140411 00000 n +0000140519 00000 n +0000140627 00000 n +0000140735 00000 n +0000140842 00000 n +0000140950 00000 n +0000141058 00000 n +0000141166 00000 n +0000141274 00000 n +0000141382 00000 n +0000141490 00000 n +0000141598 00000 n +0000141705 00000 n +0000141813 00000 n +0000141921 00000 n +0000142029 00000 n +0000142137 00000 n +0000142245 00000 n +0000142353 00000 n +0000142461 00000 n +0000142858 00000 n +0000142894 00000 n +0000142930 00000 n +0000156700 00000 n +0000156751 00000 n +0000156802 00000 n +0000156853 00000 n +0000156904 00000 n +0000156955 00000 n +0000157006 00000 n +0000157057 00000 n +0000157108 00000 n +0000157159 00000 n +0000157210 00000 n +0000157261 00000 n +0000157312 00000 n +0000157363 00000 n +0000157414 00000 n +0000157465 00000 n +0000157516 00000 n +0000157567 00000 n +0000157618 00000 n +0000157669 00000 n +0000157720 00000 n +0000157771 00000 n +0000157822 00000 n +0000157873 00000 n +0000157924 00000 n +0000157975 00000 n +0000158026 00000 n +0000158077 00000 n +0000158128 00000 n +0000158179 00000 n +0000158230 00000 n +0000158281 00000 n +0000158332 00000 n +0000158383 00000 n +0000158434 00000 n +0000158485 00000 n +0000158536 00000 n +0000158587 00000 n +0000158638 00000 n +0000158689 00000 n +0000158740 00000 n +0000158791 00000 n +0000158842 00000 n +0000158893 00000 n +0000158944 00000 n +0000158995 00000 n +0000159046 00000 n +0000159097 00000 n +0000159148 00000 n +0000159199 00000 n +0000159250 00000 n +0000159301 00000 n +0000159352 00000 n +0000159403 00000 n +0000159454 00000 n +0000159505 00000 n +0000159556 00000 n +0000159607 00000 n +0000159658 00000 n +0000159709 00000 n +0000159760 00000 n +0000159811 00000 n +0000159862 00000 n +0000159913 00000 n +0000159964 00000 n +0000160015 00000 n +0000160066 00000 n +0000160117 00000 n +0000160168 00000 n +0000160219 00000 n +0000160270 00000 n +0000160321 00000 n +0000160372 00000 n +0000160423 00000 n +0000160474 00000 n +0000160525 00000 n +0000160576 00000 n +0000160627 00000 n +0000160678 00000 n +0000160729 00000 n +0000160780 00000 n +0000160831 00000 n +0000160882 00000 n +0000160933 00000 n +0000160984 00000 n +0000161035 00000 n +0000161086 00000 n +0000161137 00000 n +0000161188 00000 n +0000161239 00000 n +0000161290 00000 n +0000161341 00000 n +0000161392 00000 n +0000161443 00000 n +0000161494 00000 n +0000161545 00000 n +0000161596 00000 n +0000161647 00000 n +0000161698 00000 n +0000161749 00000 n +0000161800 00000 n +0000161851 00000 n +0000161902 00000 n +0000161953 00000 n +0000162004 00000 n +0000162055 00000 n +0000162106 00000 n +0000162157 00000 n +0000162208 00000 n +0000162259 00000 n +0000162310 00000 n +0000162361 00000 n +0000162412 00000 n +0000162463 00000 n +0000162514 00000 n +0000162565 00000 n +0000162616 00000 n +0000162667 00000 n +0000162718 00000 n +0000162769 00000 n +0000162820 00000 n +0000162871 00000 n +0000162922 00000 n +0000162973 00000 n +0000163024 00000 n +0000163075 00000 n +0000163126 00000 n +0000163177 00000 n +0000163228 00000 n +0000163279 00000 n +0000163330 00000 n +0000163381 00000 n +0000163432 00000 n +0000163483 00000 n +0000163534 00000 n +0000163585 00000 n +0000163636 00000 n +0000163687 00000 n +0000163738 00000 n +0000163789 00000 n +0000163840 00000 n +0000163891 00000 n +0000163942 00000 n +0000163993 00000 n +0000164044 00000 n +0000164095 00000 n +0000164146 00000 n +0000164197 00000 n +0000164248 00000 n +0000164299 00000 n +0000164350 00000 n +0000164401 00000 n +0000164452 00000 n +0000164503 00000 n +0000164554 00000 n +0000164605 00000 n +0000164656 00000 n +0000164707 00000 n +0000164758 00000 n +0000164809 00000 n +0000164860 00000 n +0000164911 00000 n +0000164962 00000 n +0000165013 00000 n +0000165064 00000 n +0000165115 00000 n +0000165166 00000 n +0000165217 00000 n +0000165268 00000 n +0000165319 00000 n +0000165370 00000 n +0000165421 00000 n +0000165472 00000 n +0000165523 00000 n +0000165574 00000 n +0000165625 00000 n +0000165676 00000 n +0000165727 00000 n +0000165778 00000 n +0000165829 00000 n +0000165880 00000 n +0000165931 00000 n +0000165982 00000 n +0000166033 00000 n +0000166084 00000 n +0000166135 00000 n +0000166186 00000 n +0000166237 00000 n +0000166288 00000 n +0000166339 00000 n +0000166390 00000 n +0000166441 00000 n +0000166492 00000 n +0000166543 00000 n +0000166594 00000 n +0000166645 00000 n +0000166696 00000 n +0000166747 00000 n +0000166798 00000 n +0000166849 00000 n +0000166900 00000 n +0000166951 00000 n +0000167002 00000 n +0000167053 00000 n +0000167104 00000 n +0000167155 00000 n +0000167206 00000 n +0000167257 00000 n +0000167308 00000 n +0000167359 00000 n +0000167410 00000 n +0000167461 00000 n +0000167512 00000 n +0000167563 00000 n +0000167614 00000 n +0000167665 00000 n +0000167716 00000 n +0000167767 00000 n +0000167818 00000 n +0000167869 00000 n +0000167920 00000 n +0000167971 00000 n +0000168022 00000 n +0000168073 00000 n +0000168124 00000 n +0000168175 00000 n +0000168226 00000 n +0000168277 00000 n +0000168328 00000 n +0000168379 00000 n +0000168430 00000 n +0000168481 00000 n +0000168532 00000 n +0000168583 00000 n +0000168634 00000 n +0000168685 00000 n +0000168736 00000 n +0000168787 00000 n +0000168838 00000 n +0000168889 00000 n +0000168940 00000 n +0000168991 00000 n +0000169042 00000 n +0000169093 00000 n +0000169144 00000 n +0000169195 00000 n +0000169246 00000 n +0000169297 00000 n +0000169348 00000 n +0000169399 00000 n +0000169450 00000 n +0000169501 00000 n +0000169552 00000 n +0000169603 00000 n +0000169654 00000 n +0000169705 00000 n +0000169756 00000 n +0000169807 00000 n +0000169858 00000 n +0000169909 00000 n +0000169960 00000 n +0000170011 00000 n +0000170062 00000 n +0000170113 00000 n +0000170164 00000 n +0000170215 00000 n +0000170266 00000 n +0000170317 00000 n +0000170368 00000 n +0000170419 00000 n +0000170470 00000 n +0000170521 00000 n +0000170572 00000 n +0000170623 00000 n +0000170674 00000 n +0000170725 00000 n +0000170776 00000 n +0000170827 00000 n +0000170878 00000 n +0000170929 00000 n +0000170980 00000 n +0000171031 00000 n +0000171082 00000 n +0000171133 00000 n +0000171184 00000 n +0000171235 00000 n +0000171286 00000 n +0000171337 00000 n +0000171388 00000 n +0000171439 00000 n +0000171490 00000 n +0000171541 00000 n +0000171592 00000 n +0000171643 00000 n +0000171694 00000 n +0000171745 00000 n +0000171796 00000 n +0000171847 00000 n +0000171898 00000 n +0000171949 00000 n +0000172000 00000 n +0000172051 00000 n +0000172102 00000 n +0000172153 00000 n +0000172204 00000 n +0000172255 00000 n +0000172306 00000 n +0000172357 00000 n +0000172408 00000 n +0000172459 00000 n +0000172510 00000 n +0000172561 00000 n +0000172612 00000 n +0000172663 00000 n +0000172714 00000 n +0000172765 00000 n +0000172816 00000 n +0000172867 00000 n +0000172918 00000 n +0000172969 00000 n +0000173020 00000 n +0000173071 00000 n +0000173122 00000 n +0000173173 00000 n +0000173224 00000 n +0000173275 00000 n +0000173326 00000 n +0000173377 00000 n +0000173428 00000 n +0000173479 00000 n +0000173530 00000 n +0000173581 00000 n +0000173632 00000 n +0000173683 00000 n +0000173734 00000 n +0000173785 00000 n +0000173836 00000 n +0000173887 00000 n +0000173938 00000 n +0000173989 00000 n +0000174040 00000 n +0000174091 00000 n +0000174142 00000 n +0000174193 00000 n +0000174244 00000 n +0000174295 00000 n +0000174346 00000 n +0000174397 00000 n +0000174448 00000 n +0000174499 00000 n +0000174550 00000 n +0000174601 00000 n +0000174652 00000 n +0000174703 00000 n +0000174754 00000 n +0000174805 00000 n +0000174856 00000 n +0000174907 00000 n +0000174958 00000 n +0000175009 00000 n +0000175060 00000 n +0000175111 00000 n +0000175162 00000 n +0000175213 00000 n +0000175264 00000 n +0000175315 00000 n +0000175366 00000 n +0000175417 00000 n +0000175468 00000 n +0000175519 00000 n +0000175570 00000 n +0000175621 00000 n +0000175672 00000 n +0000175723 00000 n +0000175774 00000 n +0000175825 00000 n +0000175876 00000 n +0000175927 00000 n +0000175978 00000 n +0000176029 00000 n +0000176080 00000 n +0000176131 00000 n +0000176182 00000 n +0000176233 00000 n +0000176284 00000 n +0000176335 00000 n +0000176386 00000 n +0000176437 00000 n +0000176488 00000 n +0000176539 00000 n +0000176590 00000 n +0000176641 00000 n +0000176692 00000 n +0000176743 00000 n +0000176794 00000 n +0000176845 00000 n +0000176896 00000 n +0000176947 00000 n +0000176998 00000 n +0000177049 00000 n +0000177100 00000 n +0000177151 00000 n +0000177202 00000 n +0000177253 00000 n +0000177304 00000 n +0000177355 00000 n +0000177406 00000 n +0000177457 00000 n +0000177508 00000 n +0000177559 00000 n +0000177610 00000 n +0000177661 00000 n +0000177712 00000 n +0000177763 00000 n +0000177814 00000 n +0000177865 00000 n +0000177916 00000 n +0000177967 00000 n +0000178018 00000 n +0000178069 00000 n +0000178120 00000 n +0000178171 00000 n +0000178222 00000 n +0000178273 00000 n +0000178324 00000 n +0000178375 00000 n +0000178426 00000 n +0000178477 00000 n +0000178528 00000 n +0000178579 00000 n +0000178630 00000 n +0000178681 00000 n +0000178732 00000 n +0000178783 00000 n +0000178834 00000 n +0000178885 00000 n +0000178936 00000 n +0000178987 00000 n +0000179038 00000 n +0000179089 00000 n +0000179140 00000 n +0000179191 00000 n +0000179242 00000 n +0000179293 00000 n +0000179344 00000 n +0000179395 00000 n +0000179446 00000 n +0000179497 00000 n +0000179548 00000 n +0000179599 00000 n +0000179650 00000 n +0000179701 00000 n +0000179752 00000 n +0000179803 00000 n +0000179854 00000 n +0000179905 00000 n +0000179956 00000 n +0000180007 00000 n +0000180058 00000 n +0000180109 00000 n +0000180160 00000 n +0000180211 00000 n +0000180262 00000 n +0000180313 00000 n +0000180364 00000 n +0000180415 00000 n +0000180466 00000 n +0000180517 00000 n +0000180568 00000 n +0000180619 00000 n +0000180670 00000 n +0000180721 00000 n +0000180772 00000 n +0000180823 00000 n +0000180874 00000 n +0000180925 00000 n +0000180976 00000 n +0000181027 00000 n +0000181078 00000 n +0000181129 00000 n +0000181180 00000 n +0000181231 00000 n +0000181282 00000 n +0000181333 00000 n +0000181384 00000 n +0000181435 00000 n +0000181486 00000 n +0000181537 00000 n +0000181588 00000 n +0000181639 00000 n +0000181690 00000 n +0000181741 00000 n +0000181792 00000 n +0000181843 00000 n +0000181894 00000 n +0000181945 00000 n +0000181996 00000 n +0000182047 00000 n +0000182098 00000 n +0000182149 00000 n +0000182200 00000 n +0000182251 00000 n +0000182302 00000 n +0000182353 00000 n +0000182404 00000 n +0000182455 00000 n +0000182506 00000 n +0000182557 00000 n +0000182608 00000 n +0000182659 00000 n +0000182710 00000 n +0000182761 00000 n +0000182812 00000 n +0000182863 00000 n +0000182914 00000 n +0000182965 00000 n +0000183016 00000 n +0000183067 00000 n +0000183118 00000 n +0000183169 00000 n +0000183220 00000 n +0000183271 00000 n +0000183322 00000 n +0000183373 00000 n +0000183424 00000 n +0000183475 00000 n +0000183526 00000 n +0000183577 00000 n +0000183628 00000 n +0000183679 00000 n +0000183730 00000 n +0000183781 00000 n +0000183832 00000 n +0000183883 00000 n +0000183934 00000 n +0000183985 00000 n +0000184036 00000 n +0000184087 00000 n +0000184138 00000 n +0000184189 00000 n +0000184240 00000 n +0000184291 00000 n +0000184342 00000 n +0000184393 00000 n +0000184444 00000 n +0000184495 00000 n +0000184546 00000 n +0000184597 00000 n +0000184648 00000 n +0000184699 00000 n +0000184750 00000 n +0000184801 00000 n +0000184852 00000 n +0000184903 00000 n +0000184954 00000 n +0000185005 00000 n +0000185056 00000 n +0000185107 00000 n +0000185158 00000 n +0000185209 00000 n +0000185260 00000 n +0000185311 00000 n +0000185362 00000 n +0000185413 00000 n +0000185464 00000 n +0000185515 00000 n +0000185566 00000 n +0000185617 00000 n +0000185668 00000 n +0000185719 00000 n +0000185770 00000 n +0000185821 00000 n +0000185872 00000 n +0000185923 00000 n +0000185974 00000 n +0000186025 00000 n +0000186076 00000 n +0000186127 00000 n +0000186178 00000 n +0000186229 00000 n +0000186280 00000 n +0000186331 00000 n +0000186382 00000 n +0000186433 00000 n +0000186484 00000 n +0000186535 00000 n +0000186586 00000 n +0000186637 00000 n +0000186688 00000 n +0000186739 00000 n +0000186790 00000 n +0000186841 00000 n +0000186892 00000 n +0000186943 00000 n +0000186994 00000 n +0000187045 00000 n +0000187096 00000 n +0000187147 00000 n +0000187198 00000 n +0000187249 00000 n +0000187300 00000 n +0000187351 00000 n +0000187402 00000 n +0000187453 00000 n +0000187504 00000 n +0000187555 00000 n +0000187606 00000 n +0000187657 00000 n +0000187708 00000 n +0000187759 00000 n +0000187810 00000 n +0000187861 00000 n +0000187912 00000 n +0000187963 00000 n +0000188014 00000 n +0000188065 00000 n +0000188116 00000 n +0000188167 00000 n +0000188218 00000 n +0000188269 00000 n +0000188320 00000 n +0000188371 00000 n +0000188422 00000 n +0000188473 00000 n +0000188524 00000 n +0000188575 00000 n +0000188626 00000 n +0000188677 00000 n +0000188728 00000 n +0000188779 00000 n +0000188830 00000 n +0000188881 00000 n +0000188932 00000 n +0000188983 00000 n +0000189034 00000 n +0000189085 00000 n +0000189136 00000 n +0000189187 00000 n +0000189238 00000 n +0000189289 00000 n +0000189340 00000 n +0000189391 00000 n +0000189442 00000 n +0000189493 00000 n +0000189544 00000 n +0000189595 00000 n +0000189646 00000 n +0000189697 00000 n +0000189748 00000 n +0000189799 00000 n +0000189850 00000 n +0000189901 00000 n +0000189952 00000 n +0000190003 00000 n +0000190054 00000 n +0000190105 00000 n +0000190156 00000 n +0000190207 00000 n +0000190258 00000 n +0000190309 00000 n +0000190360 00000 n +0000190411 00000 n +0000190462 00000 n +0000190513 00000 n +0000190564 00000 n +0000190615 00000 n +0000190666 00000 n +0000190717 00000 n +0000190768 00000 n +0000190819 00000 n +0000190870 00000 n +0000190921 00000 n +0000190972 00000 n +0000191023 00000 n +0000191074 00000 n +0000191125 00000 n +0000191176 00000 n +0000191227 00000 n +0000191278 00000 n +0000191329 00000 n +0000191380 00000 n +0000191431 00000 n +0000191482 00000 n +0000191533 00000 n +0000191584 00000 n +0000191635 00000 n +0000191686 00000 n +0000191737 00000 n +0000191788 00000 n +0000191839 00000 n +0000191890 00000 n +0000191941 00000 n +0000191992 00000 n +0000192043 00000 n +0000192094 00000 n +0000192145 00000 n +0000192196 00000 n +0000192247 00000 n +0000192298 00000 n +0000192349 00000 n +0000192400 00000 n +0000192451 00000 n +0000192502 00000 n +0000192553 00000 n +0000192604 00000 n +0000192655 00000 n +0000192706 00000 n +0000192757 00000 n +0000192808 00000 n +0000192859 00000 n +0000192910 00000 n +0000192961 00000 n +0000193012 00000 n +0000193063 00000 n +0000193114 00000 n +0000193165 00000 n +0000193216 00000 n +0000193267 00000 n +0000193318 00000 n +0000193369 00000 n +0000193420 00000 n +0000193471 00000 n +0000193522 00000 n +0000193573 00000 n +0000193624 00000 n +0000193675 00000 n +0000193726 00000 n +0000193777 00000 n +0000193828 00000 n +0000193879 00000 n +0000193930 00000 n +0000193981 00000 n +0000194032 00000 n +0000194083 00000 n +0000194134 00000 n +0000194185 00000 n +0000194236 00000 n +0000194287 00000 n +0000194338 00000 n +0000194389 00000 n +0000194440 00000 n +0000194491 00000 n +0000194542 00000 n +0000194593 00000 n +0000194644 00000 n +0000194695 00000 n +0000194746 00000 n +0000194797 00000 n +0000194848 00000 n +0000194899 00000 n +0000194950 00000 n +0000195001 00000 n +0000195052 00000 n +0000195103 00000 n +0000195154 00000 n +0000195205 00000 n +0000195256 00000 n +0000195307 00000 n +0000195358 00000 n +0000195409 00000 n +0000195460 00000 n +0000195511 00000 n +0000195562 00000 n +0000195613 00000 n +0000195664 00000 n +0000195715 00000 n +0000195766 00000 n +0000195817 00000 n +0000195868 00000 n +0000195919 00000 n +0000195970 00000 n +0000196021 00000 n +0000196072 00000 n +0000196123 00000 n +0000196174 00000 n +0000196225 00000 n +0000196276 00000 n +0000196327 00000 n +0000196378 00000 n +0000196429 00000 n +0000196480 00000 n +0000196531 00000 n +0000196582 00000 n +0000196633 00000 n +0000196684 00000 n +0000196735 00000 n +0000196786 00000 n +0000196837 00000 n +0000196888 00000 n +0000196939 00000 n +0000196990 00000 n +0000197041 00000 n +0000197092 00000 n +0000197143 00000 n +0000197194 00000 n +0000197245 00000 n +0000197296 00000 n +0000197347 00000 n +0000197398 00000 n +0000197449 00000 n +0000197500 00000 n +0000197551 00000 n +0000197602 00000 n +0000197653 00000 n +0000197704 00000 n +0000197755 00000 n +0000197806 00000 n +0000197857 00000 n +0000197908 00000 n +0000197959 00000 n +0000198010 00000 n +0000198061 00000 n +0000198112 00000 n +0000198163 00000 n +0000198214 00000 n +0000198265 00000 n +0000198316 00000 n +0000198367 00000 n +0000198418 00000 n +0000198469 00000 n +0000198520 00000 n +0000198571 00000 n +0000198622 00000 n +0000198673 00000 n +0000198724 00000 n +0000198775 00000 n +0000198826 00000 n +0000198877 00000 n +0000198928 00000 n +0000198979 00000 n +0000199030 00000 n +0000200523 00000 n +0000200657 00000 n +0000200917 00000 n +0000200939 00000 n +0000201037 00000 n +0000201141 00000 n +0000201162 00000 n +0000201296 00000 n +0000202062 00000 n +0000202084 00000 n +0000202228 00000 n +0000202632 00000 n +0000202654 00000 n +0000202797 00000 n +0000203717 00000 n +0000203739 00000 n +0000203882 00000 n +0000205320 00000 n +0000205343 00000 n +0000205486 00000 n +0000206383 00000 n +0000206405 00000 n +0000206521 00000 n +0000206721 00000 n +0000206743 00000 n +0000206877 00000 n +0000207232 00000 n +0000207254 00000 n +0000207379 00000 n +0000207729 00000 n +0000207751 00000 n +0000207876 00000 n +0000208226 00000 n +0000208248 00000 n +0000208373 00000 n +0000208727 00000 n +0000208749 00000 n +0000208874 00000 n +0000209160 00000 n +0000209182 00000 n +0000209298 00000 n +0000209502 00000 n +0000209524 00000 n +0000209658 00000 n +0000210009 00000 n +0000210031 00000 n +0000210156 00000 n +0000210422 00000 n +0000210444 00000 n +0000210578 00000 n +0000210978 00000 n +0000211000 00000 n +0000211125 00000 n +0000211405 00000 n +0000211427 00000 n +0000211561 00000 n +0000211978 00000 n +0000212000 00000 n +0000212125 00000 n +0000212419 00000 n +0000212441 00000 n +0000212575 00000 n +0000212855 00000 n +0000212877 00000 n +0000213002 00000 n +0000213240 00000 n +0000213262 00000 n +0000213396 00000 n +0000213641 00000 n +0000213663 00000 n +0000213779 00000 n +0000213978 00000 n +0000214000 00000 n +0000214134 00000 n +0000214374 00000 n +0000214396 00000 n +0000214548 00000 n +0000215337 00000 n +0000215359 00000 n +0000215516 00000 n +0000215853 00000 n +0000215875 00000 n +0000216041 00000 n +0000216731 00000 n +0000216753 00000 n +0000216919 00000 n +0000217955 00000 n +0000217977 00000 n +0000218134 00000 n +0000218969 00000 n +0000218991 00000 n +0000219157 00000 n +0000220188 00000 n +0000220210 00000 n +0000220367 00000 n +0000221068 00000 n +0000221090 00000 n +0000221256 00000 n +0000221953 00000 n +0000221975 00000 n +0000222127 00000 n +0000222792 00000 n +0000222814 00000 n +0000222962 00000 n +0000223270 00000 n +0000223292 00000 n +0000223449 00000 n +0000224004 00000 n +0000224026 00000 n +0000224192 00000 n +0000225001 00000 n +0000225023 00000 n +0000225189 00000 n +0000225870 00000 n +0000225892 00000 n +0000226044 00000 n +0000226781 00000 n +0000226803 00000 n +0000226955 00000 n +0000227613 00000 n +0000227635 00000 n +0000227783 00000 n +0000228090 00000 n +0000228112 00000 n +0000228269 00000 n +0000228992 00000 n +0000229014 00000 n +0000229180 00000 n +0000229919 00000 n +0000229941 00000 n +0000230098 00000 n +0000230624 00000 n +0000230646 00000 n +0000230812 00000 n +0000231453 00000 n +0000231475 00000 n +0000231641 00000 n +0000232399 00000 n +0000232421 00000 n +0000232588 00000 n +0000233387 00000 n +0000233409 00000 n +0000233567 00000 n +0000234120 00000 n +0000234142 00000 n +0000234309 00000 n +0000235101 00000 n +0000235123 00000 n +0000235290 00000 n +0000236155 00000 n +0000236177 00000 n +0000236329 00000 n +0000237123 00000 n +0000237145 00000 n +0000237294 00000 n +0000237605 00000 n +0000237627 00000 n +0000237794 00000 n +0000238441 00000 n +0000238463 00000 n +0000238630 00000 n +0000239413 00000 n +0000239435 00000 n +0000239587 00000 n +0000240329 00000 n +0000240351 00000 n +0000240500 00000 n +0000240893 00000 n +0000240915 00000 n +0000241067 00000 n +0000241846 00000 n +0000241868 00000 n +0000242017 00000 n +0000242408 00000 n +0000242430 00000 n +0000242597 00000 n +0000243446 00000 n +0000243468 00000 n +0000243620 00000 n +0000244347 00000 n +0000244369 00000 n +0000244518 00000 n +0000244908 00000 n +0000244930 00000 n +0000245097 00000 n +0000245762 00000 n +0000245784 00000 n +0000245945 00000 n +0000246616 00000 n +0000246638 00000 n +0000246796 00000 n +0000247353 00000 n +0000247375 00000 n +0000247509 00000 n +0000247876 00000 n +0000247898 00000 n +0000248032 00000 n +0000248398 00000 n +0000248420 00000 n +0000248554 00000 n +0000248922 00000 n +0000248944 00000 n +0000249078 00000 n +0000249444 00000 n +0000249466 00000 n +0000249600 00000 n +0000249965 00000 n +0000249987 00000 n +0000250121 00000 n +0000250489 00000 n +0000250511 00000 n +0000250645 00000 n +0000251010 00000 n +0000251032 00000 n +0000251166 00000 n +0000251534 00000 n +0000251556 00000 n +0000251690 00000 n +0000252054 00000 n +0000252076 00000 n +0000252210 00000 n +0000252576 00000 n +0000252598 00000 n +0000252732 00000 n +0000253094 00000 n +0000253116 00000 n +0000253250 00000 n +0000253615 00000 n +0000253637 00000 n +0000253771 00000 n +0000254141 00000 n +0000254163 00000 n +0000254297 00000 n +0000254666 00000 n +0000254688 00000 n +0000254822 00000 n +0000255188 00000 n +0000255210 00000 n +0000255344 00000 n +0000255713 00000 n +0000255735 00000 n +0000255869 00000 n +0000256233 00000 n +0000256255 00000 n +0000256389 00000 n +0000256760 00000 n +0000256782 00000 n +0000256916 00000 n +0000257280 00000 n +0000257302 00000 n +0000257436 00000 n +0000257801 00000 n +0000257823 00000 n +0000257957 00000 n +0000258322 00000 n +0000258344 00000 n +0000258478 00000 n +0000258842 00000 n +0000258864 00000 n +0000258998 00000 n +0000259361 00000 n +0000259383 00000 n +0000259517 00000 n +0000259885 00000 n +0000259907 00000 n +0000260041 00000 n +0000260407 00000 n +0000260429 00000 n +0000260563 00000 n +0000260931 00000 n +0000260953 00000 n +0000261087 00000 n +0000261451 00000 n +0000261473 00000 n +0000261607 00000 n +0000261973 00000 n +0000261995 00000 n +0000262129 00000 n +0000262494 00000 n +0000262516 00000 n +0000262650 00000 n +0000263018 00000 n +0000263040 00000 n +0000263174 00000 n +0000263541 00000 n +0000263563 00000 n +0000263697 00000 n +0000264063 00000 n +0000264085 00000 n +0000264219 00000 n +0000264587 00000 n +0000264609 00000 n +0000264743 00000 n +0000265113 00000 n +0000265135 00000 n +0000265269 00000 n +0000265634 00000 n +0000265656 00000 n +0000265790 00000 n +0000266157 00000 n +0000266179 00000 n +0000266313 00000 n +0000266681 00000 n +0000266703 00000 n +0000266837 00000 n +0000267207 00000 n +0000267229 00000 n +0000267363 00000 n +0000267730 00000 n +0000267752 00000 n +0000267886 00000 n +0000268254 00000 n +0000268276 00000 n +0000268410 00000 n +0000268776 00000 n +0000268798 00000 n +0000268932 00000 n +0000269300 00000 n +0000269322 00000 n +0000269456 00000 n +0000269819 00000 n +0000269841 00000 n +0000269975 00000 n +0000270346 00000 n +0000270368 00000 n +0000270502 00000 n +0000270866 00000 n +0000270888 00000 n +0000271022 00000 n +0000271386 00000 n +0000271408 00000 n +0000271542 00000 n +0000271904 00000 n +0000271926 00000 n +0000272060 00000 n +0000272424 00000 n +0000272446 00000 n +0000272580 00000 n +0000272946 00000 n +0000272968 00000 n +0000273102 00000 n +0000273468 00000 n +0000273490 00000 n +0000273624 00000 n +0000273990 00000 n +0000274012 00000 n +0000274146 00000 n +0000274513 00000 n +0000274535 00000 n +0000274669 00000 n +0000275037 00000 n +0000275059 00000 n +0000275193 00000 n +0000275559 00000 n +0000275581 00000 n +0000275715 00000 n +0000276080 00000 n +0000276102 00000 n +0000276236 00000 n +0000276602 00000 n +0000276624 00000 n +0000276758 00000 n +0000277121 00000 n +0000277143 00000 n +0000277277 00000 n +0000277642 00000 n +0000277664 00000 n +0000277798 00000 n +0000278160 00000 n +0000278182 00000 n +0000278316 00000 n +0000278681 00000 n +0000278703 00000 n +0000278837 00000 n +0000279200 00000 n +0000279222 00000 n +0000279356 00000 n +0000279724 00000 n +0000279746 00000 n +0000279880 00000 n +0000280243 00000 n +0000280265 00000 n +0000280399 00000 n +0000280763 00000 n +0000280785 00000 n +0000280919 00000 n +0000281286 00000 n +0000281308 00000 n +0000281442 00000 n +0000281816 00000 n +0000281838 00000 n +0000281972 00000 n +0000282337 00000 n +0000282359 00000 n +0000282493 00000 n +0000282862 00000 n +0000282884 00000 n +0000283018 00000 n +0000283386 00000 n +0000283408 00000 n +0000283542 00000 n +0000283910 00000 n +0000283932 00000 n +0000284066 00000 n +0000284430 00000 n +0000284452 00000 n +0000284586 00000 n +0000284954 00000 n +0000284976 00000 n +0000285110 00000 n +0000285473 00000 n +0000285495 00000 n +0000285629 00000 n +0000285998 00000 n +0000286020 00000 n +0000286154 00000 n +0000286519 00000 n +0000286541 00000 n +0000286675 00000 n +0000287044 00000 n +0000287066 00000 n +0000287224 00000 n +0000289791 00000 n +0000289814 00000 n +0000289972 00000 n +0000292283 00000 n +0000292306 00000 n +0000292464 00000 n +0000293991 00000 n +0000294014 00000 n +0000294163 00000 n +0000295436 00000 n +0000295459 00000 n +0000295608 00000 n +0000296831 00000 n +0000296854 00000 n +0000297003 00000 n +0000298295 00000 n +0000298318 00000 n +0000298467 00000 n +0000299759 00000 n +0000299782 00000 n +0000299931 00000 n +0000301224 00000 n +0000301247 00000 n +0000301396 00000 n +0000302690 00000 n +0000302713 00000 n +0000302862 00000 n +0000304123 00000 n +0000304146 00000 n +0000304295 00000 n +0000305590 00000 n +0000305613 00000 n +0000305762 00000 n +0000307042 00000 n +0000307065 00000 n +0000307215 00000 n +0000308509 00000 n +0000308532 00000 n +0000308682 00000 n +0000309964 00000 n +0000309987 00000 n +0000310137 00000 n +0000311416 00000 n +0000311439 00000 n +0000311589 00000 n +0000312879 00000 n +0000312902 00000 n +0000313052 00000 n +0000314326 00000 n +0000314349 00000 n +0000314499 00000 n +0000315596 00000 n +0000315619 00000 n +0000315678 00000 n +0000315787 00000 n +0000315938 00000 n +0000316045 00000 n +0000316154 00000 n +0000316326 00000 n +0000316438 00000 n +0000316558 00000 n +0000316668 00000 n +0000316781 00000 n +0000316894 00000 n +0000317015 00000 n +0000317117 00000 n +0000317277 00000 n +0000317423 00000 n +0000317539 00000 n +0000317697 00000 n +0000317802 00000 n +0000317950 00000 n +0000318070 00000 n +0000318199 00000 n +0000318306 00000 n +0000318463 00000 n +0000318568 00000 n +0000318696 00000 n +0000318824 00000 n +0000318947 00000 n +0000319079 00000 n +0000319205 00000 n +0000319317 00000 n +0000319474 00000 n +0000319579 00000 n +0000319708 00000 n +0000319831 00000 n +0000319959 00000 n +0000320088 00000 n +0000320212 00000 n +0000320344 00000 n +0000320473 00000 n +0000320603 00000 n +0000320720 00000 n +0000320881 00000 n +0000320986 00000 n +0000321120 00000 n +0000321255 00000 n +0000321372 00000 n +0000321529 00000 n +0000321634 00000 n +0000321763 00000 n +0000321897 00000 n +0000322034 00000 n +0000322133 00000 n +0000322275 00000 n +0000322380 00000 n +0000322504 00000 n +0000322628 00000 n +0000322751 00000 n +0000322876 00000 n +0000322997 00000 n +0000323125 00000 n +0000323232 00000 n +0000323395 00000 n +0000323533 00000 n +0000323648 00000 n +0000323769 00000 n +0000323876 00000 n +0000324042 00000 n +0000324135 00000 n +0000324262 00000 n +0000324375 00000 n +0000324546 00000 n +0000324684 00000 n +0000324791 00000 n +0000324899 00000 n +0000325059 00000 n +0000325169 00000 n +0000325299 00000 n +0000325429 00000 n +0000325540 00000 n +0000325655 00000 n +0000325819 00000 n +0000325957 00000 n +0000326072 00000 n +0000326193 00000 n +0000326314 00000 n +0000326413 00000 n +0000326579 00000 n +0000326672 00000 n +0000326799 00000 n +0000326920 00000 n +0000327077 00000 n +0000327183 00000 n +0000327303 00000 n +0000327422 00000 n +0000327546 00000 n +0000327666 00000 n +0000327785 00000 n +0000327893 00000 n +0000328051 00000 n +0000328129 00000 n +0000328274 00000 n +0000328421 00000 n +0000328518 00000 n +0000328633 00000 n +0000328746 00000 n +0000328863 00000 n +0000328976 00000 n +0000329076 00000 n +0000329237 00000 n +0000329334 00000 n +0000329449 00000 n +0000329562 00000 n +0000329679 00000 n +0000329792 00000 n +0000329892 00000 n +0000330057 00000 n +0000330154 00000 n +0000330269 00000 n +0000330382 00000 n +0000330499 00000 n +0000330612 00000 n +0000330712 00000 n +0000330873 00000 n +0000330970 00000 n +0000331085 00000 n +0000331198 00000 n +0000331315 00000 n +0000331428 00000 n +0000331528 00000 n +0000331691 00000 n +0000331788 00000 n +0000331903 00000 n +0000332020 00000 n +0000332133 00000 n +0000332233 00000 n +0000332395 00000 n +0000332492 00000 n +0000332607 00000 n +0000332720 00000 n +0000332837 00000 n +0000332950 00000 n +0000333050 00000 n +0000333212 00000 n +0000333309 00000 n +0000333422 00000 n +0000333539 00000 n +0000333652 00000 n +0000333752 00000 n +0000333913 00000 n +0000334010 00000 n +0000334125 00000 n +0000334238 00000 n +0000334355 00000 n +0000334455 00000 n +0000334618 00000 n +0000334715 00000 n +0000334830 00000 n +0000334943 00000 n +0000335060 00000 n +0000335173 00000 n +0000335273 00000 n +0000335431 00000 n +0000335528 00000 n +0000335643 00000 n +0000335756 00000 n +0000335873 00000 n +0000335972 00000 n +0000336135 00000 n +0000336232 00000 n +0000336347 00000 n +0000336460 00000 n +0000336577 00000 n +0000336690 00000 n +0000336790 00000 n +0000336953 00000 n +0000337050 00000 n +0000337163 00000 n +0000337280 00000 n +0000337393 00000 n +0000337493 00000 n +0000337657 00000 n +0000337754 00000 n +0000337869 00000 n +0000337982 00000 n +0000338099 00000 n +0000338212 00000 n +0000338312 00000 n +0000338473 00000 n +0000338570 00000 n +0000338687 00000 n +0000338800 00000 n +0000338900 00000 n +0000339060 00000 n +0000339157 00000 n +0000339272 00000 n +0000339389 00000 n +0000339502 00000 n +0000339602 00000 n +0000339761 00000 n +0000339858 00000 n +0000339973 00000 n +0000340086 00000 n +0000340203 00000 n +0000340316 00000 n +0000340416 00000 n +0000340578 00000 n +0000340675 00000 n +0000340790 00000 n +0000340903 00000 n +0000341020 00000 n +0000341133 00000 n +0000341233 00000 n +0000341394 00000 n +0000341491 00000 n +0000341604 00000 n +0000341721 00000 n +0000341834 00000 n +0000341934 00000 n +0000342097 00000 n +0000342194 00000 n +0000342309 00000 n +0000342422 00000 n +0000342539 00000 n +0000342652 00000 n +0000342752 00000 n +0000342916 00000 n +0000343013 00000 n +0000343128 00000 n +0000343241 00000 n +0000343358 00000 n +0000343471 00000 n +0000343571 00000 n +0000343732 00000 n +0000343829 00000 n +0000343944 00000 n +0000344057 00000 n +0000344174 00000 n +0000344287 00000 n +0000344387 00000 n +0000344550 00000 n +0000344647 00000 n +0000344762 00000 n +0000344879 00000 n +0000344992 00000 n +0000345092 00000 n +0000345254 00000 n +0000345351 00000 n +0000345466 00000 n +0000345579 00000 n +0000345696 00000 n +0000345809 00000 n +0000345909 00000 n +0000346077 00000 n +0000346174 00000 n +0000346289 00000 n +0000346402 00000 n +0000346519 00000 n +0000346632 00000 n +0000346732 00000 n +0000346900 00000 n +0000346997 00000 n +0000347112 00000 n +0000347225 00000 n +0000347342 00000 n +0000347455 00000 n +0000347555 00000 n +0000347724 00000 n +0000347821 00000 n +0000347936 00000 n +0000348049 00000 n +0000348166 00000 n +0000348279 00000 n +0000348379 00000 n +0000348548 00000 n +0000348645 00000 n +0000348760 00000 n +0000348873 00000 n +0000348990 00000 n +0000349103 00000 n +0000349203 00000 n +0000349361 00000 n +0000349458 00000 n +0000349571 00000 n +0000349688 00000 n +0000349801 00000 n +0000349901 00000 n +0000350061 00000 n +0000350158 00000 n +0000350273 00000 n +0000350386 00000 n +0000350503 00000 n +0000350602 00000 n +0000350758 00000 n +0000350855 00000 n +0000350968 00000 n +0000351085 00000 n +0000351198 00000 n +0000351298 00000 n +0000351458 00000 n +0000351555 00000 n +0000351670 00000 n +0000351783 00000 n +0000351900 00000 n +0000352013 00000 n +0000352113 00000 n +0000352270 00000 n +0000352367 00000 n +0000352482 00000 n +0000352595 00000 n +0000352712 00000 n +0000352825 00000 n +0000352925 00000 n +0000353088 00000 n +0000353185 00000 n +0000353300 00000 n +0000353413 00000 n +0000353530 00000 n +0000353643 00000 n +0000353743 00000 n +0000353900 00000 n +0000353997 00000 n +0000354112 00000 n +0000354225 00000 n +0000354342 00000 n +0000354455 00000 n +0000354555 00000 n +0000354714 00000 n +0000354811 00000 n +0000354926 00000 n +0000355039 00000 n +0000355156 00000 n +0000355269 00000 n +0000355369 00000 n +0000355529 00000 n +0000355626 00000 n +0000355741 00000 n +0000355854 00000 n +0000355971 00000 n +0000356084 00000 n +0000356184 00000 n +0000356342 00000 n +0000356439 00000 n +0000356554 00000 n +0000356667 00000 n +0000356784 00000 n +0000356897 00000 n +0000356997 00000 n +0000357157 00000 n +0000357254 00000 n +0000357369 00000 n +0000357482 00000 n +0000357599 00000 n +0000357712 00000 n +0000357812 00000 n +0000357969 00000 n +0000358066 00000 n +0000358181 00000 n +0000358294 00000 n +0000358411 00000 n +0000358524 00000 n +0000358624 00000 n +0000358781 00000 n +0000358878 00000 n +0000358993 00000 n +0000359106 00000 n +0000359223 00000 n +0000359336 00000 n +0000359436 00000 n +0000359591 00000 n +0000359688 00000 n +0000359803 00000 n +0000359916 00000 n +0000360033 00000 n +0000360146 00000 n +0000360246 00000 n +0000360402 00000 n +0000360499 00000 n +0000360614 00000 n +0000360727 00000 n +0000360844 00000 n +0000360957 00000 n +0000361057 00000 n +0000361222 00000 n +0000361319 00000 n +0000361434 00000 n +0000361547 00000 n +0000361664 00000 n +0000361777 00000 n +0000361877 00000 n +0000362040 00000 n +0000362137 00000 n +0000362252 00000 n +0000362365 00000 n +0000362482 00000 n +0000362595 00000 n +0000362695 00000 n +0000362855 00000 n +0000362952 00000 n +0000363067 00000 n +0000363180 00000 n +0000363297 00000 n +0000363410 00000 n +0000363510 00000 n +0000363671 00000 n +0000363768 00000 n +0000363883 00000 n +0000363996 00000 n +0000364113 00000 n +0000364226 00000 n +0000364326 00000 n +0000364482 00000 n +0000364579 00000 n +0000364694 00000 n +0000364807 00000 n +0000364924 00000 n +0000365037 00000 n +0000365137 00000 n +0000365299 00000 n +0000365396 00000 n +0000365511 00000 n +0000365624 00000 n +0000365741 00000 n +0000365854 00000 n +0000365954 00000 n +0000366113 00000 n +0000366210 00000 n +0000366325 00000 n +0000366438 00000 n +0000366555 00000 n +0000366668 00000 n +0000366768 00000 n +0000366924 00000 n +0000367021 00000 n +0000367136 00000 n +0000367249 00000 n +0000367366 00000 n +0000367479 00000 n +0000367579 00000 n +0000367737 00000 n +0000367834 00000 n +0000367949 00000 n +0000368062 00000 n +0000368179 00000 n +0000368292 00000 n +0000368392 00000 n +0000368547 00000 n +0000368644 00000 n +0000368759 00000 n +0000368872 00000 n +0000368989 00000 n +0000369102 00000 n +0000369202 00000 n +0000369358 00000 n +0000369455 00000 n +0000369570 00000 n +0000369683 00000 n +0000369800 00000 n +0000369913 00000 n +0000370013 00000 n +0000370174 00000 n +0000370271 00000 n +0000370386 00000 n +0000370499 00000 n +0000370616 00000 n +0000370729 00000 n +0000370829 00000 n +0000370989 00000 n +0000371086 00000 n +0000371201 00000 n +0000371314 00000 n +0000371431 00000 n +0000371544 00000 n +0000371644 00000 n +0000371804 00000 n +0000371901 00000 n +0000372016 00000 n +0000372129 00000 n +0000372246 00000 n +0000372359 00000 n +0000372459 00000 n +0000372616 00000 n +0000372713 00000 n +0000372828 00000 n +0000372941 00000 n +0000373058 00000 n +0000373171 00000 n +0000373271 00000 n +0000373429 00000 n +0000373526 00000 n +0000373641 00000 n +0000373754 00000 n +0000373871 00000 n +0000373984 00000 n +0000374084 00000 n +0000374241 00000 n +0000374338 00000 n +0000374453 00000 n +0000374566 00000 n +0000374683 00000 n +0000374796 00000 n +0000374896 00000 n +0000375057 00000 n +0000375154 00000 n +0000375269 00000 n +0000375382 00000 n +0000375499 00000 n +0000375612 00000 n +0000375712 00000 n +0000375874 00000 n +0000375971 00000 n +0000376086 00000 n +0000376199 00000 n +0000376316 00000 n +0000376429 00000 n +0000376529 00000 n +0000376687 00000 n +0000376784 00000 n +0000376899 00000 n +0000377012 00000 n +0000377129 00000 n +0000377242 00000 n +0000377342 00000 n +0000377503 00000 n +0000377600 00000 n +0000377715 00000 n +0000377828 00000 n +0000377945 00000 n +0000378058 00000 n +0000378158 00000 n +0000378320 00000 n +0000378417 00000 n +0000378532 00000 n +0000378645 00000 n +0000378762 00000 n +0000378875 00000 n +0000378975 00000 n +0000379134 00000 n +0000379231 00000 n +0000379346 00000 n +0000379459 00000 n +0000379576 00000 n +0000379689 00000 n +0000379789 00000 n +0000379949 00000 n +0000380046 00000 n +0000380161 00000 n +0000380274 00000 n +0000380391 00000 n +0000380504 00000 n +0000380604 00000 n +0000380768 00000 n +0000380865 00000 n +0000380980 00000 n +0000381093 00000 n +0000381210 00000 n +0000381323 00000 n +0000381423 00000 n +0000381588 00000 n +0000381685 00000 n +0000381800 00000 n +0000381913 00000 n +0000382030 00000 n +0000382143 00000 n +0000382243 00000 n +0000382406 00000 n +0000382503 00000 n +0000382618 00000 n +0000382731 00000 n +0000382848 00000 n +0000382961 00000 n +0000383061 00000 n +0000383221 00000 n +0000383318 00000 n +0000383433 00000 n +0000383546 00000 n +0000383663 00000 n +0000383776 00000 n +0000383876 00000 n +0000384037 00000 n +0000384134 00000 n +0000384249 00000 n +0000384362 00000 n +0000384479 00000 n +0000384592 00000 n +0000384692 00000 n +0000384853 00000 n +0000384950 00000 n +0000385065 00000 n +0000385178 00000 n +0000385295 00000 n +0000385408 00000 n +0000385508 00000 n +0000385665 00000 n +0000385762 00000 n +0000385877 00000 n +0000385990 00000 n +0000386107 00000 n +0000386220 00000 n +0000386320 00000 n +0000386484 00000 n +0000386581 00000 n +0000386696 00000 n +0000386809 00000 n +0000386926 00000 n +0000387039 00000 n +0000387139 00000 n +0000387296 00000 n +0000387393 00000 n +0000387508 00000 n +0000387621 00000 n +0000387738 00000 n +0000387851 00000 n +0000387951 00000 n +0000388105 00000 n +0000388202 00000 n +0000388317 00000 n +0000388430 00000 n +0000388547 00000 n +0000388660 00000 n +0000388760 00000 n +0000388915 00000 n +0000389012 00000 n +0000389127 00000 n +0000389240 00000 n +0000389357 00000 n +0000389470 00000 n +0000389570 00000 n +0000389725 00000 n +0000389822 00000 n +0000389937 00000 n +0000390050 00000 n +0000390167 00000 n +0000390280 00000 n +0000390380 00000 n +0000390541 00000 n +0000390638 00000 n +0000390753 00000 n +0000390866 00000 n +0000390983 00000 n +0000391096 00000 n +0000391196 00000 n +0000391352 00000 n +0000391449 00000 n +0000391564 00000 n +0000391677 00000 n +0000391794 00000 n +0000391907 00000 n +0000392007 00000 n +0000392168 00000 n +0000392265 00000 n +0000392380 00000 n +0000392493 00000 n +0000392610 00000 n +0000392723 00000 n +0000392823 00000 n +0000392982 00000 n +0000393079 00000 n +0000393194 00000 n +0000393307 00000 n +0000393424 00000 n +0000393537 00000 n +0000393637 00000 n +0000393800 00000 n +0000393897 00000 n +0000394012 00000 n +0000394125 00000 n +0000394242 00000 n +0000394355 00000 n +0000394455 00000 n +0000394613 00000 n +0000394710 00000 n +0000394825 00000 n +0000394938 00000 n +0000395055 00000 n +0000395168 00000 n +0000395268 00000 n +0000395428 00000 n +0000395525 00000 n +0000395640 00000 n +0000395753 00000 n +0000395870 00000 n +0000395983 00000 n +0000396083 00000 n +0000396241 00000 n +0000396338 00000 n +0000396453 00000 n +0000396566 00000 n +0000396683 00000 n +0000396796 00000 n +0000396896 00000 n +0000397052 00000 n +0000397149 00000 n +0000397264 00000 n +0000397377 00000 n +0000397494 00000 n +0000397607 00000 n +0000397707 00000 n +0000397864 00000 n +0000397961 00000 n +0000398076 00000 n +0000398189 00000 n +0000398306 00000 n +0000398419 00000 n +0000398519 00000 n +0000398674 00000 n +0000398771 00000 n +0000398886 00000 n +0000398999 00000 n +0000399116 00000 n +0000399229 00000 n +0000399329 00000 n +0000399485 00000 n +0000399582 00000 n +0000399697 00000 n +0000399810 00000 n +0000399927 00000 n +0000400040 00000 n +0000400140 00000 n +0000400296 00000 n +0000400393 00000 n +0000400508 00000 n +0000400621 00000 n +0000400738 00000 n +0000400851 00000 n +0000400951 00000 n +0000401111 00000 n +0000401208 00000 n +0000401323 00000 n +0000401436 00000 n +0000401553 00000 n +0000401666 00000 n +0000401766 00000 n +0000401923 00000 n +0000402020 00000 n +0000402135 00000 n +0000402248 00000 n +0000402365 00000 n +0000402478 00000 n +0000402578 00000 n +0000402733 00000 n +0000402830 00000 n +0000402945 00000 n +0000403058 00000 n +0000403175 00000 n +0000403288 00000 n +0000403388 00000 n +0000403549 00000 n +0000403646 00000 n +0000403761 00000 n +0000403874 00000 n +0000403991 00000 n +0000404104 00000 n +0000404204 00000 n +0000404371 00000 n +0000404468 00000 n +0000404583 00000 n +0000404696 00000 n +0000404813 00000 n +0000404926 00000 n +0000405026 00000 n +0000405187 00000 n +0000405284 00000 n +0000405399 00000 n +0000405512 00000 n +0000405629 00000 n +0000405742 00000 n +0000405842 00000 n +0000406001 00000 n +0000406098 00000 n +0000406213 00000 n +0000406326 00000 n +0000406443 00000 n +0000406556 00000 n +0000406656 00000 n +0000406819 00000 n +0000406916 00000 n +0000407031 00000 n +0000407144 00000 n +0000407261 00000 n +0000407374 00000 n +0000407474 00000 n +0000407635 00000 n +0000407732 00000 n +0000407847 00000 n +0000407960 00000 n +0000408077 00000 n +0000408190 00000 n +0000408290 00000 n +0000408447 00000 n +0000408544 00000 n +0000408659 00000 n +0000408772 00000 n +0000408889 00000 n +0000409002 00000 n +0000409102 00000 n +0000409261 00000 n +0000409358 00000 n +0000409473 00000 n +0000409586 00000 n +0000409703 00000 n +0000409816 00000 n +0000409916 00000 n +0000410071 00000 n +0000410168 00000 n +0000410283 00000 n +0000410396 00000 n +0000410513 00000 n +0000410626 00000 n +0000410726 00000 n +0000410887 00000 n +0000410984 00000 n +0000411099 00000 n +0000411212 00000 n +0000411329 00000 n +0000411442 00000 n +0000411542 00000 n +0000411701 00000 n +0000411798 00000 n +0000411913 00000 n +0000412026 00000 n +0000412143 00000 n +0000412256 00000 n +0000412356 00000 n +0000412502 00000 n +0000412599 00000 n +0000412714 00000 n +0000412827 00000 n +0000412944 00000 n +0000413057 00000 n +0000413157 00000 n +trailer +<> +startxref +413391 +%%EOF diff --git a/doc/spm.shtml b/doc/spm.shtml new file mode 100644 index 0000000000..3e5a6b46ac --- /dev/null +++ b/doc/spm.shtml @@ -0,0 +1,4555 @@ + + + + + + DRAFT - CUPS Software Programmers Manual + + + +

Preface

+ +This software programmers manual provides software programming +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 software administrators manual is organized into the following sections:

+ +
    +
  • 1 - Printing System Overview
  • +
  • 2 - The CUPS API
  • +
  • 3 - Writing Filters
  • +
  • 4 - Writing Printer Drivers
  • +
  • 5 - Writing Backends
  • +
  • A - Constants
  • +
  • B - Structures
  • +
  • C - Functions
  • +
+ +

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 - The CUPS API

+ +

This chapter describes the CUPS Application Programmers Interface ("API"). + +

The CUPS Library

+ +

Detecting the CUPS Library in Autoconf

+ + +

Basic Services

+ +

Include Files

+ +

Getting the Available Printers and Classes

+ +

Printing Files

+ +

Setting Printer Options

+ +

Cancelling Jobs

+ + +

HTTP Services

+ +

Include Files

+ +

Connecting to a Server

+ +

Setting Request Fields

+ +

Issuing a Request

+ +

Getting the Request Status

+ +

Sending Request Data

+ +

Reading Request Data

+ + +

IPP Services

+ +

Include Files

+ +

Creating an IPP Request

+ +

Adding Attributes

+ +

Sending an IPP Request

+ +

Reading an IPP Response

+ +

Finding Attributes

+ +

Looping Through Attributes

+ +

IPP Standard Operations

+ +

IPP Extension Operations

+ +

CUPS Extension Operations

+ + +

Language Services

+ +

Include Files

+ +

Getting the Default Language

+ +

Getting the Language Encoding

+ +

Getting a Language String

+ + +

MIME Services

+ +

Include Files

+ +

Loading a MIME Database

+ +

Finding a Specific MIME Type

+ +

Finding the MIME Type of a File

+ +

Filters

+ + +

PPD Services

+ +

Include Files

+ +

Loading a PPD File

+ +

Options and Groups

+ +

Finding an Option

+ +

Finding a Page Size

+ +

Marking Options

+ +

Checking for Conflicts

+ +

Sending Options

+ + +

3 - Writing Filters

+ +

This chapter describes how to write a file filter for CUPS. + +

Overview

+ +

Security Considerations

+ +Users and Groups + +

Temporary Files

+ +

Page Accounting

+ + +

Command-Line Arguments

+ +

Copy Generation

+ + +

Environment Variables

+ + +

Writing a HTML Filter

+ + +

4 - Writing Printer Drivers

+ +

This chapter discusses how to write a printer driver, which is a +special filter program that converts CUPS raster data into the +appropriate commands and data required for a printer. + +

Overview

+ +

Page Accounting

+ +

Color Management

+ + +

Raster Functions

+ +

cupsRasterOpen()

+ +

cupsRasterReadHeader()

+ +

cupsRasterReadPixels()

+ +

cupsRasterClose()

+ + +

Writing a HP-PCL Driver

+ + +

5 - Writing Backends

+ +

This chapter describes how to write a backend for CUPS. Backends +communicate directly with printers and allow printer drivers and +filters to send data using any type of connection transparently. + +

Overview

+ +

Security Considerations

+ +Users and Groups + +

Temporary Files

+ +

Page Accounting

+ +

Retries

+ + +

Command-Line Arguments

+ +

Copy Generation

+ + +

Environment Variables

+ + +

Writing a Serial Port Backend

+ + +

A - Constants

+ +

This appendix lists all of the constants that are defined by the CUPS +API. + +

CUPS Constants

+ +

HTTP Constants

+ +

IPP Constants

+ +

Language Constants

+ +

MIME Constants

+ +

PPD Constants

+ +

Raster Constants

+ + +

B - Structures

+ +

This appendix describes all of the structures that are defined by the CUPS +API. + +

+ + +

C - Functions

+ +

This appendix provides a reference for all of the CUPS API functions. + +

cupsAddOption()

+ +

Usage

+ +
+int
+cupsAddOption(const char *name,
+              const char *value,
+              int num_options,
+	      cups_option_t **options);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + + + + + +
ArgumentDescription
nameThe name of the option.
valueThe value of the option.
num_optionsNumber of options currently in the array.
optionsPointer to the options array.
+ +

Returns

+ +

The new number of options. + +

Description

+ +

cupsAddOption() adds an option to the specified array. + +

Example

+ +
+#include <cups.h>
+
+...
+
+/* Declare the options array */
+int           num_options;
+cups_option_t *options;
+
+/* Initialize the options array */
+num_options = 0;
+options     = (cups_option_t *)0;
+
+/* Add options using cupsAddOption() */
+num_options = cupsAddOption("media", "letter", num_options, &options);
+num_options = cupsAddOption("resolution", "300dpi", num_options, &options);
+
+ +

See Also

+ +cupsFreeOptions(), +cupsGetOption(), +cupsParseOptions() + +

cupsCancelJob()

+ +

Usage

+ +
+int
+cupsCancelJob(const char *dest,
+              int job);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
destPrinter or class name
jobJob ID
+ +

Returns

+ +

1 on success, 0 on failure. On failure the error can be found by calling +cupsLastError(). + +

Description

+ +

cupsCancelJob() cancels the specifies job. + +

Example

+ +
+#include <cups.h>
+
+cupsCancelJob("LaserJet", 1);
+
+ +

See Also

+ +

+cupsLastError(), +cupsPrintFile() + +

cupsDoFileRequest()

+ +

Usage

+ +
+ipp_t *
+cupsDoFileRequest(http_t *http,
+                  ipp_t *request,
+                  const char *resource,
+		  const char *filename);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + + + + + +
ArgumentDescription
httpHTTP connection to server.
requestIPP request data.
resourceHTTP resource name for POST.
filenameFile to send with POST request (NULL pointer if none.)
+ +

Returns

+ +

IPP response data or NULL if the request fails. On failure +the error can be found by calling +cupsLastError(). + +

Description

+ +

cupsDoFileRequest() does a HTTP POST request and provides the +IPP request and optionally the contents of a file to the IPP server. It also +handles resubmitting the request and performing password authentication as +needed. + +

Example

+ +
+#include <cups.h>
+
+http_t      *http;
+cups_lang_t *language;
+ipp_t       *request;
+ipp_t       *response;
+
+...
+
+/* Get the default language */
+language = cupsLangDefault();
+
+/* Create a new IPP request */
+request  = ippNew();
+
+request->request.op.operation_id = IPP_PRINT_FILE;
+request->request.op.request_id   = 1;
+
+/* Add required attributes */
+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, "ipp://hostname/resource");
+
+ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
+             NULL, cupsUser());
+
+/* Do the request... */
+response = cupsDoFileRequest(http, request, "/resource", "filename.txt");
+
+ +

See Also

+ +

+cupsLangDefault(), +cupsLangEncoding(), +cupsUser(), +httpConnect(), +ippAddString(), +ippNew() + +

cupsDoRequest()

+ +

Usage

+ +
+ipp_t *
+cupsDoRequest(http_t *http,
+              ipp_t *request,
+              const char *resource);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + +
ArgumentDescription
httpHTTP connection to server.
requestIPP request data.
resourceHTTP resource name for POST.
+ +

Returns

+ +

IPP response data or NULL if the request fails. On failure +the error can be found by calling +cupsLastError(). + +

Description

+ +

cupsDoRequest() does a HTTP POST request and provides +the IPP request to the IPP server. It also handles resubmitting the +request and performing password authentication as needed. + +

Example

+ +
+#include <cups.h>
+
+http_t      *http;
+cups_lang_t *language;
+ipp_t       *request;
+ipp_t       *response;
+
+...
+
+/* Get the default language */
+language = cupsLangDefault();
+
+/* Create a new IPP request */
+request  = ippNew();
+
+request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
+request->request.op.request_id   = 1;
+
+/* Add required attributes */
+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, "ipp://hostname/resource");
+
+/* Do the request... */
+response = cupsDoRequest(http, request, "/resource");
+
+ +

See Also

+ +

+cupsLangDefault(), +cupsLangEncoding(), +cupsUser(), +httpConnect(), +ippAddString(), +ippNew() + +

cupsFreeOptions()

+ +

Usage

+ +
+void
+cupsFreeOptions(int num_options,
+                cups_option_t *options);
+
+

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
num_optionsNumber of options in array.
optionsPointer to options array.
+ +

Description

+ +

cupsFreeOptions() frees all memory associated with the +option array specified. + +

Example

+ +
+#include <cups/cups.h>
+
+int           num_options;
+cups_option_t *options;
+
+...
+
+cupsFreeOptions(num_options, options);
+
+ +

See Also

+ +

+cupsAddOption(), +cupsGetOption(), +cupsMarkOptions(), +cupsParseOptions() + +

cupsGetClasses()

+ +

Usage

+ +
+int
+cupsGetClasses(char ***classes);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
classesPointer to character pointer array.
+ +

Returns

+ +

The number of printer classes available. + +

Description

+ +

cupsGetClasses() gets a list of the available printer classes. +The returned array should be freed using the free() when it is +no longer needed. + +

Example

+ +
+#include <cups/cups.h>
+
+int  i;
+int  num_classes;
+char **classes;
+
+...
+
+num_classes = cupsGetClasses(&classes);
+
+...
+
+if (num_classes > 0)
+{
+  for (i = 0; i < num_classes; i ++)
+    free(classes[i]);
+
+  free(classes);
+}
+
+ +

See Also

+ +

+cupsGetDefault(), +cupsGetPrinters() + +

cupsGetDefault()

+ +

Usage

+ +
+const char *
+cupsGetDefault(void);
+
+ +

Returns

+ +

A pointer to the default destination. + +

Description

+ +

cupsGetDefault() gets the default destination printer or class. +The default destination is stored in a static string and will be overwritten +(usually with the same value) after each call. + +

Example

+ +
+#include <cups/cups.h>
+
+printf("The default destination is %s\n", cupsGetDefault());
+
+ +

See Also

+ +

+cupsGetClasses(), +cupsGetPrinters() + +

cupsGetOption()

+ +

Usage

+ +
+const char *
+cupsGetOption(const char *name,
+              int num_options,
+              cups_option_t *options);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + +
ArgumentDescription
nameThe name of the option.
num_optionsThe number of options in the array.
optionsThe options array.
+ +

Returns

+ +

A pointer to the option values or NULL if the option is +not defined. + +

Description

+ +

cupsGetOption() returns the first occurrence of the +named option. If the option is not included in the options array then a +NULL pointer is returned. + +

+#include <cups/cups.h>
+
+int           num_options;
+cups_option_t *options;
+const char    *media;
+
+...
+
+media = cupsGetOption("media", num_options, options);
+
+ +

See Also

+ +

+cupsAddOption(), +cupsFreeOptions(), +cupsMarkOptions(), +cupsParseOptions() + +

cupsGetPassword()

+ +

Usage

+ +
+const char *
+cupsGetPassword(const char *prompt);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
promptThe prompt to display to the user.
+ +

Returns

+ +

A pointer to the password that was entered or NULL if no +password was entered. + +

Description

+ +

cupsGetPassword() displays the prompt string and asks the user +for a password. The password text is not echoed to the user. + +

Example

+ +
+#include <cups/cups.h>
+
+char *password;
+
+...
+
+password = cupsGetPassword("Please enter a password:");
+
+ +

See Also

+ +

+cupsServer(), +cupsUser() + +

cupsGetPPD()

+ +

Usage

+ +
+const char *
+cupsGetPPD(const char *printer);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
printerThe name of the printer.
+ +

Returns

+ +

The name of a temporary file containing the PPD file or NULL +if the printer cannot be located or does not have a PPD file. + +

Description

+ +

cupsGetPPD() gets a copy of the PPD file for the named printer. +The printer name can be of the form "printer" or "printer@hostname". + +

You should remove (unlink) the PPD file after you are done using it. The +filename is stored in a static buffer and will be overwritten with each call +to cupsGetPPD(). + +

Example

+ +
+#include <cups/cups.h>
+
+char *ppd;
+
+...
+
+ppd = cupsGetPPD("printer@hostname");
+
+...
+
+unlink(ppd);
+
+ +

cupsGetPrinters()

+ +

Usage

+ +
+int
+cupsGetPrinters(char ***printers);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
printersPointer to character pointer array.
+ +

Returns

+ +

The number of printer printers available. + +

Description

+ +

cupsGetPrinters() gets a list of the available printers. +The returned array should be freed using the free() when it is +no longer needed. + +

Example

+ +
+#include <cups/cups.h>
+
+int  i;
+int  num_printers;
+char **printers;
+
+...
+
+num_printers = cupsGetPrinters(&printers);
+
+...
+
+if (num_printers > 0)
+{
+  for (i = 0; i < num_printers; i ++)
+    free(printers[i]);
+
+  free(printers);
+}
+
+ +

See Also

+ +

+cupsGetClasses(), +cupsGetDefault() + +

cupsLangDefault()

+ +

Usage

+ +
+const char *
+cupsLangDefault(void);
+
+ +

Returns

+ +

A pointer to the default language structure. + +

Description

+ +

cupsLangDefault() returns a language structure for the default +language. The default language is defined by the LANG environment +variable. If the specified language cannot be located then the POSIX (English) +locale is used. + +

Call cupsLangFree() to free any memory associated with the +language structure when you are done. + +

Example

+ +
+#include <cups/language.h>
+
+cups_lang_t *language;
+...
+
+language = cupsLangDefault();
+
+...
+
+cupsLangFree(language);
+
+ +

See Also

+ +

+cupsLangEncoding(), +cupsLangFlush(), +cupsLangFree(), +cupsLangGet(), +cupsLangString() + +

cupsLangEncoding()

+ +

Usage

+ +
+char *
+cupsLangEncoding(cups_lang_t *language);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
languageThe language structure.
+ +

Returns

+ +

A pointer to the encoding string. + +

Description

+ +

cupsLangEncoding() returns the language encoding used for the +specified language, e.g. "iso-8859-1", "utf-8", etc. + +

Example

+ +
+#include <cups/language.h>
+
+cups_lang_t *language;
+char        *encoding;
+...
+
+language = cupsLangDefault();
+encoding = cupsLangEncoding(language);
+...
+
+cupsLangFree(language);
+
+ +

See Also

+ +

+cupsLangDefault(), +cupsLangFlush(), +cupsLangFree(), +cupsLangGet(), +cupsLangString() + +

cupsLangFlush()

+ +

Usage

+ +
+void
+cupsLangFlush(void);
+
+ +

Description

+ +

cupsLangFlush() frees all language structures that have been +allocated. + +

Example

+ +
+#include <cups/language.h>
+
+...
+
+cupsLangFlush();
+
+ +

See Also

+ +

+cupsLangDefault(), +cupsLangEncoding(), +cupsLangFree(), +cupsLangGet(), +cupsLangString() + +

cupsLangFree()

+ +

Usage

+ +
+void
+cupsLangFree(cups_lang_t *language);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
languageThe language structure to free.
+ +

Description

+ +

cupsLangFree() frees the specified language structure. + +

Example

+ +
+#include <cups/language.h>
+
+cups_lang_t *language;
+...
+
+cupsLangFree(language);
+
+ +

See Also

+ +

+cupsLangDefault(), +cupsLangEncoding(), +cupsLangFlush(), +cupsLangGet(), +cupsLangString() + +

cupsLangGet()

+ +

Usage

+ +
+cups_lang_t *
+cupsLangGet(const char *name);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
nameThe name of the locale.
+ +

Returns

+ +

A pointer to a language structure. + +

Description

+ +

cupsLangGet() returns a language structure for the specified +locale. If the locale is not defined then the POSIX (English) locale is +substituted. + +

Example

+ +
+#include <cups/language.h>
+
+cups_lang_t *language;
+
+...
+
+language = cupsLangGet("fr");
+
+...
+
+cupsLangFree(language);
+
+ +

See Also

+ +

+cupsLangDefault(), +cupsLangEncoding(), +cupsLangFlush(), +cupsLangFree(), +cupsLangString() + +

cupsLangString()

+ +

Usage

+ +
+char *
+cupsLangString(cups_lang_t *language,
+               int         message);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
languageThe language to query.
messageThe message number.
+ +

Returns

+ +

A pointer to the message string or NULL if the message is +not defined. + +

Description

+ +

cupsLangString() returns a pointer to the specified message +string in the specified language. + +

Example

+ +
+#include <cups/language.h>
+
+cups_lang_t *language;
+char        *s;
+...
+
+language = cupsLangGet("fr");
+
+s = cupsLangString(language, CUPS_MSG_YES);
+
+...
+
+cupsLangFree(language);
+
+ +

See Also

+ +

+cupsLangDefault(), +cupsLangEncoding(), +cupsLangFlush(), +cupsLangFree(), +cupsLangGet() + +

cupsLastError()

+ +

Usage

+ +
+ipp_status_t
+cupsLastError(void);
+
+ +

Returns

+ +

An enumeration containing the last IPP error. + +

Description

+ +

cupsLastError() returns the last IPP error that occurred. +If no error occurred then it will return IPP_OK or +IPP_OK_CONFLICT. + +

Example

+ +
+#include <cups/cups.h>
+
+ipp_status_t status;
+
+...
+
+status = cupsLastError();
+
+ +

See Also

+ +

+cupsCancelJob(), +cupsPrintFile() + +

cupsMarkOptions()

+ +

Usage

+ +
+int
+cupsMarkOptions(ppd_file_t *ppd,
+                int num_options,
+                cups_option_t *options);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + +
ArgumentDescription
ppdThe PPD file to mark.
num_optionsThe number of options in the options array.
optionsA pointer to the options array.
+ +

Returns

+ +

The number of conflicts found. + +

Description

+ +

cupsMarkOptions() marks options in the PPD file. It also +handles mapping of IPP option names and values to PPD option names. + +

Example

+ +
+#include <cups/cups.h>
+
+int           num_options;
+cups_option_t *options;
+ppd_file_t    *ppd;
+
+...
+
+cupsMarkOptions(ppd, num_options, options);
+
+ +

See Also

+ +

+cupsAddOption(), +cupsFreeOptions(), +cupsGetOption(), +cupsParseOptions() + +

cupsParseOptions()

+ +

Usage

+ +
+int
+cupsParseOptions(const char *arg,
+                 int num_options,
+                 cups_option_t **options);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + +
ArgumentDescription
argThe string containing one or more options.
num_optionsThe number of options in the options array.
optionsA pointer to the options array pointer.
+ +

Returns

+ +

The new number of options in the array. + +

Description

+ +

cupsParseOptions() parses the specifies string for one +or more options of the form "name=value", "name", or "noname". It can +be called multiple times to combine the options from several strings. + +

Example

+ +
+#include <cups/cups.h>
+
+int           num_options;
+cups_option_t *options;
+
+...
+
+num_options = 0;
+options     = (cups_option_t *)0;
+num_options = cupsParseOptions(argv[5], num_options, &options);
+
+ +

See Also

+ +

+cupsAddOption(), +cupsFreeOptions(), +cupsGetOption(), +cupsMarkOptions() + +

cupsPrintFile()

+ +

Usage

+ +
+int
+cupsPrintFile(const char *printer,
+              const char *filename,
+              const char *title,
+	      int num_options,
+	      cups_option_t *options);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + +
ArgumentDescription
printerThe printer or class to print to.
filenameThe file to print.
titleThe job title.
num_optionsThe number of options in the options array.
optionsA pointer to the options array.
+ +

Returns

+ +

The new job ID number or 0 on error. + +

Description

+ +

cupsPrintFile() sends a file to the specified printer or +class for printing. If the job cannot be printed the error code can be +found by calling cupsLastError(). + +

Example

+ +
+#include <cups/cups.h>
+
+int           num_options;
+cups_option_t *options;
+
+...
+
+cupsPrintFile("printer@hostname", "filename.ps", "Job Title", num_options,
+              options);
+
+ +

See Also

+ +

+cupsCancelJob(), +cupsLastError() + +

cupsRasterClose()

+ +

Usage

+ +
+void
+cupsRasterClose(cups_raster_t *ras);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
rasThe raster stream to close.
+ +

Description

+ +

cupsRasterClose() closes the specified raster stream. + +

Example

+ +
+#include <cups/raster.h>
+
+cups_raster_t *ras;
+
+...
+
+cupsRasterClose(ras);
+
+ +

See Also

+ +

+cupsRasterOpen(), +cupsRasterReadHeader(), +cupsRasterReadPixels(), +cupsRasterWriteHeader(), +cupsRasterWritePixels() + + +

cupsRasterOpen()

+ +

Usage

+ +
+cups_raster_t *
+cupsRasterOpen(int fd,
+               cups_mode_t mode);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
fdThe file descriptor to use.
modeThe mode to use; CUPS_RASTER_READ or + CUPS_RASTER_WRITE.
+ +

Returns

+ +

A pointer to a raster stream or NULL if there was an error. + +

Description

+ +

cupsRasterOpen() opens a raster stream for reading or writing. + +

Example

+ +
+#include <cups/raster.h>
+
+cups_raster_t *ras;
+
+...
+
+ras = cupsRasterOpen(0, CUPS_RASTER_READ);
+
+ +

See Also

+ +

+cupsRasterClose(), +cupsRasterReadHeader(), +cupsRasterReadPixels(), +cupsRasterWriteHeader(), +cupsRasterWritePixels() + +

cupsRasterReadHeader()

+ +

Usage

+ +
+unsigned
+cupsRasterReadHeader(cups_raster_t *ras,
+                     cups_page_header_t *header);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
rasThe raster stream to read from.
headerA pointer to a page header structure to read into.
+ +

Returns

+ +

1 on success, 0 on EOF or error. + +

Description

+ +

cupsRasterReadHeader() reads a page header from the specified +raster stream. + +

Example

+ +
+#include <cups/raster.h>
+
+int                  line;
+cups_raster_t        *ras;
+cups_raster_header_t header;
+unsigned char        pixels[8192];
+...
+
+while (cupsRasterReadHeader(ras, &header))
+{
+  ...
+
+  for (line = 0; line < header.cupsHeight; line ++)
+  {
+    cupsRasterReadPixels(ras, pixels, header.cupsBytesPerLine);
+
+    ...
+  }
+}
+
+ +

See Also

+ +

+cupsRasterClose(), +cupsRasterOpen(), +cupsRasterReadPixels(), +cupsRasterWriteHeader(), +cupsRasterWritePixels() + +

cupsRasterReadPixels()

+ +

Usage

+ +
+unsigned
+cupsRasterReadPixels(cups_raster_t *ras,
+                     unsigned char *pixels,
+		     unsigned length);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + +
ArgumentDescription
rasThe raster stream to read from.
pixelsThe pointer to a pixel buffer.
lengthThe number of bytes of pixel data to read.
+ +

Returns

+ +

The number of bytes read or 0 on EOF or error. + +

Description

+ +

cupsRasterReadPixels() reads pixel data from the specified +raster stream. + +

Example

+ +
+#include <cups/raster.h>
+
+int                  line;
+cups_raster_t        *ras;
+cups_raster_header_t header;
+unsigned char        pixels[8192];
+...
+
+while (cupsRasterReadHeader(ras, &header))
+{
+  ...
+
+  for (line = 0; line < header.cupsHeight; line ++)
+  {
+    cupsRasterReadPixels(ras, pixels, header.cupsBytesPerLine);
+
+    ...
+  }
+}
+
+ +

See Also

+ +

+cupsRasterClose(), +cupsRasterOpen(), +cupsRasterReadHeader(), +cupsRasterWriteHeader(), +cupsRasterWritePixels() + +

cupsRasterWriteHeader()

+ +

Usage

+ +
+unsigned
+cupsRasterWriteHeader(cups_raster_t *ras,
+                      cups_page_header_t *header);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
rasThe raster stream to write to.
headerA pointer to the page header to write.
+ +

Returns

+ +

1 on success, 0 on error. + +

Description

+ +

cupsRasterWriteHeader() writes the specified page header to +a raster stream. + +

Example

+ +
+#include <cups/raster.h>
+
+int                  line;
+cups_raster_t        *ras;
+cups_raster_header_t header;
+unsigned char        pixels[8192];
+...
+
+cupsRasterWriteHeader(ras, &header);
+
+for (line = 0; line < header.cupsHeight; line ++)
+{
+  ...
+
+  cupsRasterWritePixels(ras, pixels, header.cupsBytesPerLine);
+}
+
+ +

See Also

+ +

+cupsRasterClose(), +cupsRasterOpen(), +cupsRasterReadHeader(), +cupsRasterReadPixels(), +cupsRasterWritePixels() + +

cupsRasterWritePixels()

+ +

Usage

+ +
+unsigned
+cupsRasterWritePixels(cups_raster_t *ras,
+                      unsigned char *pixels,
+		      unsigned length);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + +
ArgumentDescription
rasThe raster stream to write to.
pixelsThe pixel data to write.
lengthThe number of bytes to write.
+ +

Returns

+ +

The number of bytes written. + +

Description

+ +

cupsRasterWritePixels() writes the specified pixel data to a +raster stream. + +

Example

+ +
+#include <cups/raster.h>
+
+int                  line;
+cups_raster_t        *ras;
+cups_raster_header_t header;
+unsigned char        pixels[8192];
+...
+
+cupsRasterWriteHeader(ras, &header);
+
+for (line = 0; line < header.cupsHeight; line ++)
+{
+  ...
+
+  cupsRasterWritePixels(ras, pixels, header.cupsBytesPerLine);
+}
+
+ +

See Also

+ +

+cupsRasterClose(), +cupsRasterOpen(), +cupsRasterReadHeader(), +cupsRasterReadPixels(), +cupsRasterWriteHeader() + +

cupsServer()

+ +

Usage

+ +
+const char *
+cupsServer(void);
+
+ +

Returns

+ +

A pointer to the default server name. + +

Description

+ +

cupsServer() returns a pointer to the default server name. +The server name is stored in a static location and will be overwritten with +every call to cupsServer() + +

The default server is determined from the following locations: + +

    + +
  1. The CUPS_SERVER environment variable, + +
  2. The ServerName directive in the + cupsd.conf file, + +
  3. The default host, "localhost". + +
+ +

Example

+ +
+#include <cups/cups.h>
+
+const char *server;
+
+server = cupsServer();
+
+ +

See Also

+ +

+cupsGetPassword(), +cupsUser() + +

cupsTempFile()

+ +

Usage

+ +
+char *
+cupsTempFile(char *filename,
+             int length);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
filenameThe character string to hold the temporary filename.
lengthThe size of the filename string in bytes.
+ +

Returns

+ +

A pointer to filename. + +

Description

+ +

cupsTempFile() generates a temporary filename for the +/var/tmp directory or the directory specified by the +TMPDIR environment variable. + +

Example

+ +
+#include <cups/cups.h>
+
+char filename[256];
+
+cupsTempFile(filename, sizeof(filename));
+
+ +

cupsUser()

+ +

Usage

+ +
+const char *
+cupsUser(void);
+
+ +

Returns

+ +

A pointer to the current username or NULL if the user ID is +undefined. + +

Description

+ +

cupsUser() returns the name associated with the current +user ID as reported by the getuid() system call. + +

Example

+ +
+#include <cups/cups.h>
+
+const char *user;
+
+user = cupsUser();
+
+ +

See Also

+ +

+cupsGetPassword(), +cupsServer() + +

httpBlocking()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

httpCheck()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

httpClearFields()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

httpClose()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

httpConnect()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

httpDecode64()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

httpDelete()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

httpEncode64()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

httpError()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

httpFlush()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

httpGet()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

httpGets()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

httpGetDateString()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

httpGetDateTime()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

httpGetField()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

httpGetLength()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

httpHead()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

httpInitialize()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

httpOptions()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

httpPost()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

httpPrintf()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

httpPut()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

httpRead()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

httpReconnect()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

httpSeparate()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

httpSetField()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

httpTrace()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

httpUpdate()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

httpWrite()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

ippAddBoolean()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

ippAddBooleans()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

ippAddDate()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

ippAddInteger()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

ippAddIntegers()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

ippAddRange()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

ippAddRanges()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

ippAddResolution()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

ippAddResolutions()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

ippAddSeparator()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

ippAddString()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

ippAddStrings()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

ippDateToTime()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

ippDelete()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

ippFindAttribute()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

ippLength()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

ippNew()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

ippPort()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

ippRead()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

ippTimeToDate()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

ippWrite()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

mimeAddFilter()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

mimeAddType()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

mimeAddTypeRule()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

mimeDelete()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

mimeFileType()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

mimeFilter()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

mimeLoad()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

mimeMerge()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

mimeNew()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

mimeType()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

ppdClose()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

ppdConflicts()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

pddEmitFd()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

ppdEmit()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

ppdFindChoice()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

ppdFindMarkedChoice()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

ppdFindOption()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

ppdIsMarked()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

ppdMarkDefaults()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

ppdMarkOption()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

ppdOpenFd()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

ppdOpenFile()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

ppdOpen()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

ppdPageLength()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

ppdPageSize()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

ppdPageWidth()

+ +

Usage

+ +
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
+ +

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + + + diff --git a/doc/ssr.html b/doc/ssr.html new file mode 100644 index 0000000000..f5df9f6180 --- /dev/null +++ b/doc/ssr.html @@ -0,0 +1,338 @@ + + + +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 + +
+GIF89a¯ÿòÌÌ̙™™fff333ÿÿÿÿÿÿÿÿÿ!ù,¯ÿBþXºÜþ0ÊI«½8ëÍ»ÿ`(Ždižhª2€0p,Ïtmßx®ï + + +;±Ýíˆndý !¸ ž³wà…MƒƒY~¿{,gÚ\‚äé +Œ×Ø(tÙî!Ï=Ñ.ûz¯áџ:ì;Ã9qöíÉë]/¿ºÉ¤Et/†'Îþt9Àؖž_ÙÇ\|W•wArö¸Ý2Ô× +tN°0Tï}¡û‰$!‚yMxî)ˆš‰Ôø@nB°U½ÊwE„§!ŠF H L8B +c‰;ždŠ-æDVWdг€h±äړP¶%#(4Fiå•Ï\hŠ:Re!\ÒėX^¦%€¥À-$E€Ö/úHŽšlââöÌQX + + +¸1Nô¯b"œŠüjåÁÂE0…È8ö5GkZ|ÒÁwt„C»ÔQSÇo6Ôِ[W„$²*Ž+4Pb-8¹P1þ'8"‘ФÄ$ Cyê‘„)>ãŠtè`Ð3‡‹¾z"«rE'Âqfä°Ë +‘qÂ\|€„Ž¡ôö»%É(.—bڽȀíÉ`{¬EÇ1w’ »[Hß`(B6ö“  +†')ÊRŽÎa[ÃrbC!T尌 +2Q·ÈHZê#–®üË/àô¯FÝê(Û²% ºXË9öÀbÁ4f.ù-oý™XËB…IÎÒ7¹*@ÃӎÍT€hà‘ÌW␙Ã$f:µyžn†ó†r„'téKv` +Ç+dª– œ79sò|'=×¢Ìx¶òœÿ„¦œˆeÎ;*à$þ” IÝÆaÏ{–3ŽÅÁ +P“ÍS[ÙL¨3©òQ7éÆò#ãûô0F×ðsE°t§@‘ØQÜ´´ ©:3ÓRíd ¥*MITnŒ£¨H]ØQÁd +@òþ—¬rMœŽaO + +rë^yÀ·(¸îéêû$uDòrã/a,I.°ÙUÀœb hˆ`¾B ë" +Ü`HØxȸo1þ[á\8f^æ|\ý‚¢¢zø0(ˆ\ {ƒÄgäÞõ€çâ§Á˜0*\³n¼‹m¶/Äeª±ÿ†ì +Ç,½DN2€œº+ùÉ|í0L¡Le*ð¸Ã>­2ëf,eIPOËÅàr—±”80SAŸcFªatç»ãy¤¸ršçÌ¡5ïoõËsžï|¿8˙Φ¬þ,ï¼èà)ÁÌ;øk¡—†dDpÑòø2¢qfHã!˓~ٟ-í +'g:,æ4y?ýäP‹Z›ž#ÏÕ´Î5AK‰k]ûš›ÒKõ¯‡më€õzØÈƫ؎Ý>B{PЪ.6hf]º?©ÌIŽuO„íM‚ÌÇÜcµ3˜ +61‹NÒ[†W£ ¦m¿­{ÂPâvζKnUˆ[ ònĽ±÷n?l:Áž3ušë¬sP[ÿnn¾çP…WõÔFj[Â÷ +¹vÏ™à‰˜xú'ˆ£ÀÀ†p¸4.êãKÇ¿ÂÁ±o§¢ü"Á|Nk`îʘ + + +jl©ÌuˆËi™0pmC´«+‰÷6¤2­éÏe`(ŽJ]¥iõð3ƒØí"p|ª!:qøFس 6£ +@­,þŠqüぐoÌÇ®žÖüV“¶QǛEvî¹²É8ÙªS"æÀç‡x± àþ‡>—Iãg +ïÝ>Y‰çN80æ§ ±¾GLLìÕµ…(1Þ¼!8}þ¬“*…ª‰Ùì:e»´œ +ª¿ên_6ÂÃSÀ`eG;Ö„CƒCcˆ¿‡4¸yeî¯Í)oøByRm½0?íLîÅ`QÿjÓÙ/ºôÓN|Ý + + +þÙAÜŒÁ¸D5©D aævx ?жx°DM@•!h‰àȀާ® +• á×B`ð¤ªE?›“”Þdƒ"8$Ý`Ki0…OðƒnΓ±µvtžè€I([,¹Ndɨh\'6X +P㗊‰Éøt ¢‘¥˜¬è €ˆ†Ky™FˆŒë`š”yƒ„¨š €š‰ƒM©‡øFQhY„ +9¶X¯×–í4š¤™Y\)"¹AN]‰xéz÷Gq07)©ñ™•Y€r°ŒŽi‹ z ™ÇäFÍÉT–ù› +ËŽC œwI›üX]‹¹\ëY]þf lïYbj8ŸÈuœbŸÍÅtú©fÞןfBI—“*øé:ÛØUj Ò +ˆõ¹ Õp $(~ ¡Ú ¡gù{îpZI?¡ƒîÀv:“a¦˜6¢§Ô]Ý‘(ªê)!ŸÚ¢: +jwµ¡4ÚvíHÛǘ9ºXhó•üù£¥Á¢VÉ{Dº2š‰(°¤3š¤a÷ +У¥“p¢þò4Vº—  +E´¥è¤k°7ºhT*€¿èw`ڞiÄ …S¦Ʀmê Nêƒ#ú¢f€ xê†ý +8z©7uÚp{Ú=~]7`«h‡ÚsÚg:…zd˜ó§ÎA-vþAñr¦'–AÚ)9–š¢âSi;£…š 1ªo"ª +¦J;“º rº8Ui|é>¡Úœú + +“ë¥Dfný2»ƒ–0j«®»ºK;zë¢Íö»—!µ—S»³r>K+6ˆ‹¨XÒ»; CÈ +8Ê;¢»ÃÛ/Œ‹¥ž!¬s½VR½óõϋOâ[/çK¨þ˜Ñ:͋\Ý+ Sc:ï˞’º¶ë9Æ» + +ô 8ly$ +8©ÙÅmX2Ùh>—?¯!šHüÁ^LsP,Ÿ«Y‹âá¿ÿtšì‚£Y +r¦Éš¥9ÇjžÄ8-ÆÇŒ¶iêPÂbA˜ù‰Ã¸š»³7RœCWRoìŠå MŒŠ”åt™ Œ›réÉq + + +å>}Lê}ÎǨ 5:àŒ|"þÇwÐsøæNΰ¹#R>~-N‰®èƒ ßcðÞÚÎÑ¥®åGÎâ툉Ýè*‚¸ +=‚ž ºëⅭëÀ>Û·žën^žmèÊëð¼ã>å×Λ«}êØ÷ +“Œ¬ËIÁ·AÔNÍëv>]t.âÚLЫþíï¾ñnäÖÜæs¹¿±â°+† +¬UØïî•.ç¬ÎìÍ.è´ÞŠG=ðù‚§ž¯”ë^äÛ®êh-‹êê!i!ÕvMíiªîþ¾òîá/þÑ-OÖGð,oñº!å’gOâ POìOôBþÈàhâ+?ï>ßÊVHÀsaõ™€õ$óSîõ—»ó8.žß¹ +~áßÈ©ö»]ò3ëÆt_÷[ïôb¯ç‚Ü÷Õ«@u™ð;zܘ‘Ü@óŽ2’?ùƒ¸ÙlùF ¶™¯ù›N ž0œú£¶¤ÿ0#9:ß§½ž©Ÿ\#ÃÙæó2é+û‚ÀÓ¸_äM/ÓtaÚý3”]Ù«¿¸iîaF>ª}ŒØvÍïMÍ÷Ðëä©îr܌öqñ_ÀüªrâF®ò +ýþ¸—hT_ã4sx”ýÝî)ç.QgûàŸÏ%ì‹}i´ASû|þð@QÜ +$J9€»-̱÷ÜôMؑhZ˜¦:°œ*ÏlßxÒ|ϼ¡ÅLÀ ¬Áfù9BÑdìÁ|«VV„¢“énKv + + +kB_ƒg 3ʳ8#Þ¬L=0;J¤äÈ@¤F|'i~±© žaʊÆg;d*3²”©bPÏ¢TäHô¦?[† +ÄäƒhN6ZM¢D:c*BR!$±ckƒ’V­-uÛ@[øp„Ÿ]¼8ö-1{TήWÏ2ñ Šp=¸q«Ñ½es.‰„4+#Ëe¦¥W5µekxr䛓/X͚5Iǃ=kÝúµì˰ûN–2qÅ¦yZ£QŽ›ÇޝtxŠäcK—Ííɹ +iþ¡9¼m1oñ¢©/²8îìSté4l’Wm¾9óéÖÛÐãã{{üzÞ¿çøêöÞzà}œàL¨ "˜ +ÄÐsà¶PGLUúå`MÞ  ¡†9¬§Û{pX¸¡wÚw߇¡¨ ‰í "MUXNx + ++l´á¦ +j²F:Á.êÆÛj¤³Búî ¼Ê«/£Ö’[н#í+ð¥ænJÞ¸«æ;ð©õ‹¨ _ËðĊһ*º? +ƒÂwœÃyzh±°Øzl2,#oZ2țr|ò˂°¼$Ç)ë +óÍÙÔ,éfs€1Î@/øîÏPõÌiÐH·ðÃBkLtÒP¯bôS;NÝWÔXÏ +ó’dlÍtÖ`°tžOc óÅa§}Aě²1vËjÇmþu+`ÍÍÁ·qwü6˜‚ì½sÞXŸ¨Ë$xM6àP³-iÉSÚ½Aوïë84–ø=xä8^!ä*L>ޘƒk¹Œ({Iè^!ḘN$ê +«®ç!ºû‚ÿÝ ë¯ßoî—Oü¨¾ÿî9í]ñÞ{ñÙÊ®ãlhŽ(èÌÃê¼~ÔS¢|ö՟zýw¬Ë§|øÝ—*½ŒÈ×­|úåwzþæ“)Nrû¾Ê?*ô¥ +¿*÷ô7ú½~Múúú÷ª÷Ɉ•S3x*ûíP”ùH£°°àó(è¾í-Jƒú™ +åAF{#\”g…Áœ)!),Ô #ÓÂǼjþ1œŒþh©²K„9$ƒYè)Ž ˆA È +—‡)#1‰Óp"˜ð'Ã%n‰P´‡Ù¨-‹1³¢^\%ƈÔp„CLÖ5à + +
+

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
  • +
  • RFC 1179, Line Printer Daemon Protocol
  • +
  • RFC 2565, IPP/1.0: Encoding and Transport
  • +
  • RFC 2566, IPP/1.0: Model and Semantics
  • +
  • RFC 2639, IPP/1.0: Implementers Guide
  • +
+

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

+

There are two known security vulnerabilities with local access:

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

    +
  2. +
  3. Device URIs are passed to backend filters in argv[0] and in an +environment variable. Since device URIs can contain usernames and +passwords it may be possible for a local user to gain access to a +remote resource. +

    We recommend that any password-protected accounts used for remote +printing have limited access priviledges so that the possible damages +can be minimized.

    +

    The device URI is "sanitized" (the username and password are + removed) when sent to an IPP client so that a remote user cannot +exploit this vulnerability.

    +
  4. +
+

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..c6daab7783 --- /dev/null +++ b/doc/ssr.pdf @@ -0,0 +1,426 @@ +%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<>endobj +75 0 obj<>>>>>endobj +76 0 obj<>stream +xÚMŽ;Â0D{ŸbJ°É&&Á%ßbs”8| +8”ÛcCi‹Ñ̛½3BD(Rd9ª+›6^+¤ L9Á/¤0õ`YÎÖ‹ÝFC·흅¶ÕÝ|ÒÞZç‡æD@“©(À) œ@ˆM®uÉI$1Èi"xšVû®ÿ7®­•ï>A™‰üÓÞzw:=H©‚‡£F˜].(£Ù…W:랶ŽÕ•a[ö3œ>¬endstream +endobj +77 0 obj +183 +endobj +78 0 obj<>>>endobj +79 0 obj<>stream +xÚ+ä2T0BCc3JÎår +ár á +äHÉHendstream +endobj +80 0 obj +31 +endobj +81 0 obj<>>>>>endobj +82 0 obj<>stream +xڝUKo1¾ó+F9%Rز@!é-o!¥í6¨.Æ;œx=[Û ¢¿¾cïRREM<¯ïûæÁN +=þ¤0îÃ`²ìœÏ:®O¡ßƒYÁ–Ñx³ü0…©¤ +fOњŽkw”&ýhOR˜äh¼*”^‘i\‡¦­k”ÄT³¥rà¨ðkaÊÚ*¿‹Y•¥•Êс0üzãØ› +¨È9µÐ/$‰Ö8(Ȃ_"\PY’û/“ï¡8—L ºÌ*FfaºqK˜\ÜgӃù< uŒÒ¤—üÅnØKNvýmè×ڕÂõôþ@ûµw!SµõÑbƒ6 +±óþǰêVD£‹ \Káö8. ä¸BÍ9,6p%ܦ[¡3Ky-½OCI‚óÂäÂæ;ŽtúQ­+49ÙЕ|¯níXÁ‚ž;n¡-߇çhŸQcèZYòCW+ƒÀ%ÑB¢KÚ¬[c:Nݤš?ƒ~'&³ñ$Is+'W³ëî$˸™¢q_ˆ04?—Á?҃'ZD +ð£Æš‹7kÎmÀËp#.†>Îo³Ëc¸»¾HÓñéüè¦<lÿŒÎ‰G„sMò™Ý¦ŸÏƒ5T8«ª)?bœè•+s„v´WÒÕU˜nÚZù%/÷‰µ‘¡B󴿪Ès,˚ìsÐ1-,­] PdäüTZUù'tñAEbYvÉkÐeÉðÅP´‡Yy+ƒ¸®ÎAT•nwÞAmrl†÷uÄ̞».uÝl€¬§RýäÚ«vy×o¾ÜÃÍr}~È+où¸è 4@©øÛk˜ôó£=¼A¾$ª m*ïÚÝ$ã!$¿/0 YvbË̐龐­•Õ½upI².࿜‡·®_¸uöQ˜¨¦8ÏiM븜GÂ}jòË6ÿ„Ùþ.1ïÆð'¾ßݗ\î€m•z-Š“ÂÈÚó޾+tÀ¡·$yJÎ$Ç:¸Sîù})†±z>>>>>endobj +85 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS041T072PIÑp rt QÐUp VÎO+)O,JUNM.-Ê,©TJ-È/*Ñ ÉâÒi҅ê2‰˜˜˜é™)€ù† +ÁÉù© Q×®@.ü7 £endstream +endobj +86 0 obj +118 +endobj +87 0 obj<>>>>>endobj +88 0 obj<>stream +xÚ­•]“š0†ïýçҝ– êU·ãL¥‚{åM +AӁÄ&q¶þû&¬¶îL±;\€rò¼çã=ú£‡ÀÓ‚ȇaYÕû”öŸÇà{úMæ}Ö¤ ‚°ŒÈ‡ô{‚"â„Èõë Ál'0çÙ±"LaE9³á Ԅû¡[3Ó=‚—%£lg旁J­jßN öú«6fbÁYöG:‰3{ë‡\+÷‚3[År½‰Õ›qVÐÝQX½fxG â³k¾N mï—óù<9IE*X2ED3s"鎙[&èáwoºH$ӕ‘p¶"¼PoX˜æeT*] ÒÔrÄåüëZú‡¤¯n¡cÁwW•1ÁÝY'ë[è„dGAÕI›÷À…ºƒ›Æ·¸)‘÷Z$Ù¼3¿$ÿ3¶×ùm쫦oÿ5¹v»8çŽìûð¢öDœ—Xþã3Μ«%–`øÈ ^. @ÃQäƒv½.|¯k›h;Q¦L>Û~.p¡¶º¹ŒãÇzâÓ<§†ˆKx9œˆ•‘àhs)@Øëç™~ŒÆøB±™šFcRé é=P<ãeg¤ÿ> àœø‚e<7 À,‡T`&;{¿¡†ÔÏIY#RaÝáLvG†ÃñrYÊú×Öÿó‘æÄž5ggúã ±æÿAÁÈsÇZW¿šÏ‹´÷µ÷ dÃßÎendstream +endobj +89 0 obj +541 +endobj +90 0 obj<>>>>>endobj +91 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 +92 0 obj +121 +endobj +93 0 obj<>>>>>endobj +94 0 obj<>stream +xÚ}T]oÛ0 |ϯ úÔ‹'iÚîmÝP`ºÖŬ{P$&Ñ"K©$;ó~ýHÙNZc°t"w$ŸF9Lè—ÃÅf å躽þxÓ +ºY\Ì¡P§3øä¤0ðVJ ît؆³â'Açç-t<]d ÜBE õ áâÆþ¤°°DÀ_;ãtDΚö:n@€IÏ«€žc¸ÊÆ ŠPFí,(‡¬‹L€Òæ³lÊi…Rž3ê*x4‚CGŠŽ°ÔV¤çnE$¼sv"„½óDÀƒ£SÏI*¯cӇ!€“:EJüøéÃç›oƒän‡žÂÛ5„&D,³V+È/:uæ“ì2I™åpß'¹ö(äÿ­eAœ°•oï`kÝÞ)֕±”v©Žš¸&‚æ™úo8îôü.πNﵕ˜jQ¸•‰ mˆÂ˜V"I´"$ŽQcúTbiH4|"Q")êÉ ç›W ém€ A3bEJL…QQÈ –RKg#Úؑ×6ÂJʺD +’Ø5©òt‡*ë$?JÃy½£¬eßQTÖ­[ËJ±eG’ÛCâp¨)õ¡–º.ìPꕦÚlfÌ»‡Û{æ¾ÒëÊ·z1ïDoü¼Öi'ö{¢Dj?ÜÝ´ƒÀM×6æRÈ-ZÅï#‰Eù°®¿O~€°*}Z@[kïlIRA-¼fÒ´ªz(rÊĊ°Â‚¢pYV”ì(…í›>°w¥hX¸þ½˜A¢¹æÝ<Ó§ˆâ±t‘%®ò‡>}å+éʒ+Mã/ls 1&#YB‚tÓ8¯JDºÈ©ØÉ¨Œ.u'B.­É µ¦ZƒkÓ±i‡ú”(_v C[Âýþ[wõê²qÜâ'AXš3žÀãiß-,ë U“ÅL¼Fõxû òĒw¬œ…›Û[FÓÁ€yÏVôU'õ‰&mº~S‚ˆ<û¦[4—ÝêÓÏÎÿ[ÚóËIvEK† çüý¡}ý†‚ýíendstream +endobj +95 0 obj +757 +endobj +96 0 obj<>>>>>endobj +97 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 +98 0 obj +131 +endobj +99 0 obj<>>>>>endobj +100 0 obj<>stream +xÚ}WÛnÜ6}÷WÌ£¬×ÞµãKûT· ` -RÛAûà®ÄÝeL‘ +IYÞ|}Ï ©½ÈI`À°¥á\Î93}=šÑ~ft5§óKªš£Ûǣӏ74?£Ç%Þ\^]Ðc}|A÷ºñIÓoU¥c¤{Ÿã»Ç/°½ Ù,۞Ì/§b]lU¶ lK*hJkù·JT)G MúµµÞ$]Soð¶K¤ÈúJYê¢ìÁw]}ê-ƒo`²û¸‰I7SαgçÓ9Ç~\›HQWÉxGµ×‘œ‡ƒºœ‹‰±Ã£ ­â É“Ó©÷á™Ø½ ºWÖòñ.˜´™æ +ohvU*¼8›^ Óý¡A¢~I:¼˜ +तªŸàò§y*pç’ˆŒHr2N€Š¦ß?zG(U¼tÖé Vs¢õ6\9D*‡›q•íjãV¿pèùû]ÄٔøÑñ‡˜àÇÄ5Œ¨él2-¼VÞ¹ŒTäœB‰ЍÝФ̈́¶ €RãƒtPã6˜@bppÛ°T1Ìj¥Œ‹x¸—7h°ý2õÐŔî×ÛúTË +Yv©ƒfÿ}÷ßÁñqØÁÙ°ò„)(/‡£"÷Þïö1Â}±§€âs|•=—KeÃü½@ŸõJo3ˆOï†Ê2ôߛfµ^*l“¹ØaëÊI•K*뺪±5U^Oé_œöÒI;!Kwdû±:N˧ƒc÷Yˆ¼S‹Àw›.²ï°@Š0d#ϒ½m?v ÞÀË÷țÝ"÷U%psØá«àz§ÙóëŸ~#]\ŸMo`›+þÿÃãÑ?Gÿß+‰aendstream +endobj +101 0 obj +1459 +endobj +102 0 obj<>>>>>endobj +103 0 obj<>stream +xÚ]ÁRÂ0†ï}Šÿ¨‡–j©G¹9£ $[§Mj’Šøô&àȌ“\v÷ÿw¿ÝŒ¡ŒaQ§/‡lų٦càm¬ÔMU4àê†wC_ƒ6ÖÁQOÂl‹Ç·—Žºïá§q´.`­äÄ:2AK´5Ic¤Œ# ä½8öV0ymð4 +'Ýò÷¬DÎÅl8òˉv¶ GWߑœœ'l)+Ùóäʗó2¹š”Y,ï‹ +縊Hž•#!;òIóij×ì+e¶endstream +endobj +104 0 obj +303 +endobj +105 0 obj<>>>>>endobj +106 0 obj<>stream +xڝ”ÁŽ›0†ï<ÅÛl IŽ)J²‘V[*X©×Y3aÝ`›ÚN£¼}h¥®,µ2²°føæÿíÁ?¢>>>>>endobj +109 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 +110 0 obj +383 +endobj +111 0 obj<>>>/Annots 53 0 R>>endobj +112 0 obj<>stream +xÚ͘Ûr›0†ïýºl/BÐ ¡ËšLg:“ÖvÀ%rã6˜Ófòö]I+26´W!™Áȋ>£_»?¿”äðO‰b„¤ª—ëÅù&,'ë-¡R“B ²¾·Þ|{4¤Ù’«fߙ}wx¿þ±ø°^äY{ ö°¼µ Rp™•¤&eÆðü‘¬,ûÕåíwr~# ¥ö×l·.…_£ä$~@ÖÄ}$|EʪjžŒ1 pø"›ý=9nÄXVÀÀ%Ë$6pàç7e„y,‡ˆÕ1Q2‚ÔЗZ-c$Æõñf}·ÝU›n×ì-T*è1#]§´Ëu&zí\j£y&¼blJ1ä” +„I8>H«—Cgê‘Dúƒüœö·RÙÅíîiÿì̳КéY?¡¸Ô¨‰ŠûÆ ¸Ô +ÚNq>¡xàÐÜæsÂ8¢®›êw izš#(¨›ÃHLdgðÝËNGmWº·]Þ»Ã`²RåÞٸɘԐ‡ ÍEei¶¦5ûʸ'‚Йš¹×ò‰¤•Å`±¾qÌb¥TÞÙ¤ÅbÉ@±„ˆa$]}ý¼™’¡7$®Ìí¤Ä,Œ#+TBoÖEñ¶Ó2¥ºàƒ9ûFd®LÖSæ8e®’p0Œ¤»îÁ´#bÝ­7[N`GX;T›Eðq«  +Žhîü˜UPWâ|Â(ŕ%fù¨c|jªÍãiNÔ·&о¾) ;ÒE^s8Šz׬]§( {ïÚ~üøs³-9Q29÷þìÛ5ŽU.¼Qói£B¢¶ë‹„ˆa$­Lõ»Ýu/§qÁ֏­Û„‡qä]¶fS=ø·6‡™£å#”ò>#óçGÊG¨Ò„/ ª'GÔS–¦n:suw¨S–Pjª†¢ÞvÙe3é}ùx¸±¾Œø¼vY¦ÆkHbX¡úƱ…ôËA1YCX +«YLÄ0’®Í~7fˆQçb¯nÃmùéR,¢»ò¥˜0ޤ•]îV#I€Wؽw  ð¢ë6•Ïþf;•’º‡…Ÿ!×BâÌO-=Åy[BÁ0ûï 0T3¦aœÍÖ9Õ¸s2ᗰ9ì|ã˜uÂÙ-d/Æör=ÁÍOqFÎícs8lÚ§”Îèü_鉤¥Ô¯˜…M×8j]”¡åZ×ëâ=>$°#imÚÚÛ½š›Ýÿ£v\—Þöí¸|c(x®5Z×hÉ]m.ÛÍpÂx@Um³ñªÁ®avkM§×0ȼ7[b& +ÅÄîù¯—7krF܎uÕl»çMkHomKóÔ´«4aßž)æÆ»C5¿,þì‰òendstream +endobj +113 0 obj +1019 +endobj +114 0 obj<>>>>>endobj +115 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS041T072PIÑp rt QÐUp VÎO+)O,JUNM.-Ê,©TJ-È/*Ñ ÉâÒi҅êÊÌ ¹†pr‡Âµendstream +endobj +116 0 obj +103 +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<>1<>2<>4<>]>>>>endobj +xref +0 135 +0000000000 65535 f +0000000015 00000 n +0000000230 00000 n +0000001787 00000 n +0000001861 00000 n +0000001939 00000 n +0000002016 00000 n +0000002095 00000 n +0000002171 00000 n +0000002252 00000 n +0000002310 00000 n +0000002412 00000 n +0000002515 00000 n +0000002619 00000 n +0000002723 00000 n +0000002827 00000 n +0000002931 00000 n +0000003035 00000 n +0000003139 00000 n +0000003243 00000 n +0000003347 00000 n +0000003449 00000 n +0000003552 00000 n +0000003656 00000 n +0000003760 00000 n +0000003864 00000 n +0000003968 00000 n +0000004072 00000 n +0000004176 00000 n +0000004278 00000 n +0000004381 00000 n +0000004485 00000 n +0000004589 00000 n +0000004693 00000 n +0000004797 00000 n +0000004901 00000 n +0000005003 00000 n +0000005106 00000 n +0000005210 00000 n +0000005314 00000 n +0000005418 00000 n +0000005522 00000 n +0000005626 00000 n +0000005730 00000 n +0000005834 00000 n +0000005938 00000 n +0000006042 00000 n +0000006146 00000 n +0000006249 00000 n +0000006353 00000 n +0000006458 00000 n +0000006563 00000 n +0000006668 00000 n +0000006773 00000 n +0000007091 00000 n +0000007123 00000 n +0000007155 00000 n +0000007399 00000 n +0000007446 00000 n +0000007493 00000 n +0000007540 00000 n +0000007587 00000 n +0000007634 00000 n +0000007681 00000 n +0000007728 00000 n +0000007775 00000 n +0000007822 00000 n +0000007869 00000 n +0000007916 00000 n +0000007963 00000 n +0000008011 00000 n +0000008059 00000 n +0000008107 00000 n +0000008154 00000 n +0000008201 00000 n +0000008372 00000 n +0000008500 00000 n +0000008752 00000 n +0000008772 00000 n +0000008864 00000 n +0000008964 00000 n +0000008983 00000 n +0000009120 00000 n +0000010009 00000 n +0000010029 00000 n +0000010139 00000 n +0000010326 00000 n +0000010346 00000 n +0000010483 00000 n +0000011093 00000 n +0000011113 00000 n +0000011223 00000 n +0000011413 00000 n +0000011433 00000 n +0000011561 00000 n +0000012387 00000 n +0000012407 00000 n +0000012517 00000 n +0000012717 00000 n +0000012737 00000 n +0000012875 00000 n +0000014405 00000 n +0000014427 00000 n +0000014548 00000 n +0000014922 00000 n +0000014943 00000 n +0000015082 00000 n +0000015577 00000 n +0000015598 00000 n +0000015728 00000 n +0000016182 00000 n +0000016203 00000 n +0000016356 00000 n +0000017446 00000 n +0000017468 00000 n +0000017580 00000 n +0000017754 00000 n +0000017775 00000 n +0000017830 00000 n +0000017935 00000 n +0000018078 00000 n +0000018183 00000 n +0000018302 00000 n +0000018410 00000 n +0000018558 00000 n +0000018667 00000 n +0000018773 00000 n +0000018929 00000 n +0000019024 00000 n +0000019181 00000 n +0000019297 00000 n +0000019405 00000 n +0000019539 00000 n +0000019636 00000 n +0000019736 00000 n +trailer +<> +startxref +19961 +%%EOF diff --git a/doc/ssr.shtml b/doc/ssr.shtml new file mode 100644 index 0000000000..19b13864d0 --- /dev/null +++ b/doc/ssr.shtml @@ -0,0 +1,272 @@ + + + + + + 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 +
  • RFC 1179, Line Printer Daemon Protocol +
  • RFC 2565, IPP/1.0: Encoding and Transport +
  • RFC 2566, IPP/1.0: Model and Semantics +
  • RFC 2639, IPP/1.0: Implementers Guide +
+ +

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

+ +

There are two known security vulnerabilities with local access: + +

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

  2. Device URIs are passed to backend filters in argv[0] and in + an environment variable. Since device URIs can contain + usernames and passwords it may be possible for a local user to + gain access to a remote resource. + +

    We recommend that any password-protected accounts used for + remote printing have limited access priviledges so that the + possible damages can be minimized. + +

    The device URI is "sanitized" (the username and password are + removed) when sent to an IPP client so that a remote user + cannot exploit this vulnerability. + +

+ +

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..2cb74f6e63 --- /dev/null +++ b/doc/stp.html @@ -0,0 +1,247 @@ + + + +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 + +
+GIF89a¯ÿòÌÌ̙™™fff333ÿÿÿÿÿÿÿÿÿ!ù,¯ÿBþXºÜþ0ÊI«½8ëÍ»ÿ`(Ždižhª2€0p,Ïtmßx®ï + + +;±Ýíˆndý !¸ ž³wà…MƒƒY~¿{,gÚ\‚äé +Œ×Ø(tÙî!Ï=Ñ.ûz¯áџ:ì;Ã9qöíÉë]/¿ºÉ¤Et/†'Îþt9Àؖž_ÙÇ\|W•wArö¸Ý2Ô× +tN°0Tï}¡û‰$!‚yMxî)ˆš‰Ôø@nB°U½ÊwE„§!ŠF H L8B +c‰;ždŠ-æDVWdг€h±äړP¶%#(4Fiå•Ï\hŠ:Re!\ÒėX^¦%€¥À-$E€Ö/úHŽšlââöÌQX + + +¸1Nô¯b"œŠüjåÁÂE0…È8ö5GkZ|ÒÁwt„C»ÔQSÇo6Ôِ[W„$²*Ž+4Pb-8¹P1þ'8"‘ФÄ$ Cyê‘„)>ãŠtè`Ð3‡‹¾z"«rE'Âqfä°Ë +‘qÂ\|€„Ž¡ôö»%É(.—bڽȀíÉ`{¬EÇ1w’ »[Hß`(B6ö“  +†')ÊRŽÎa[ÃrbC!T尌 +2Q·ÈHZê#–®üË/àô¯FÝê(Û²% ºXË9öÀbÁ4f.ù-oý™XËB…IÎÒ7¹*@ÃӎÍT€hà‘ÌW␙Ã$f:µyžn†ó†r„'téKv` +Ç+dª– œ79sò|'=×¢Ìx¶òœÿ„¦œˆeÎ;*à$þ” IÝÆaÏ{–3ŽÅÁ +P“ÍS[ÙL¨3©òQ7éÆò#ãûô0F×ðsE°t§@‘ØQÜ´´ ©:3ÓRíd ¥*MITnŒ£¨H]ØQÁd +@òþ—¬rMœŽaO + +rë^yÀ·(¸îéêû$uDòrã/a,I.°ÙUÀœb hˆ`¾B ë" +Ü`HØxȸo1þ[á\8f^æ|\ý‚¢¢zø0(ˆ\ {ƒÄgäÞõ€çâ§Á˜0*\³n¼‹m¶/Äeª±ÿ†ì +Ç,½DN2€œº+ùÉ|í0L¡Le*ð¸Ã>­2ëf,eIPOËÅàr—±”80SAŸcFªatç»ãy¤¸ršçÌ¡5ïoõËsžï|¿8˙Φ¬þ,ï¼èà)ÁÌ;øk¡—†dDpÑòø2¢qfHã!˓~ٟ-í +'g:,æ4y?ýäP‹Z›ž#ÏÕ´Î5AK‰k]ûš›ÒKõ¯‡më€õzØÈƫ؎Ý>B{PЪ.6hf]º?©ÌIŽuO„íM‚ÌÇÜcµ3˜ +61‹NÒ[†W£ ¦m¿­{ÂPâvζKnUˆ[ ònĽ±÷n?l:Áž3ušë¬sP[ÿnn¾çP…WõÔFj[Â÷ +¹vÏ™à‰˜xú'ˆ£ÀÀ†p¸4.êãKÇ¿ÂÁ±o§¢ü"Á|Nk`îʘ + + +jl©ÌuˆËi™0pmC´«+‰÷6¤2­éÏe`(ŽJ]¥iõð3ƒØí"p|ª!:qøFس 6£ +@­,þŠqüぐoÌÇ®žÖüV“¶QǛEvî¹²É8ÙªS"æÀç‡x± àþ‡>—Iãg +ïÝ>Y‰çN80æ§ ±¾GLLìÕµ…(1Þ¼!8}þ¬“*…ª‰Ùì:e»´œ +ª¿ên_6ÂÃSÀ`eG;Ö„CƒCcˆ¿‡4¸yeî¯Í)oøByRm½0?íLîÅ`QÿjÓÙ/ºôÓN|Ý + + +þÙAÜŒÁ¸D5©D aævx ?жx°DM@•!h‰àȀާ® +• á×B`ð¤ªE?›“”Þdƒ"8$Ý`Ki0…OðƒnΓ±µvtžè€I([,¹Ndɨh\'6X +P㗊‰Éøt ¢‘¥˜¬è €ˆ†Ky™FˆŒë`š”yƒ„¨š €š‰ƒM©‡øFQhY„ +9¶X¯×–í4š¤™Y\)"¹AN]‰xéz÷Gq07)©ñ™•Y€r°ŒŽi‹ z ™ÇäFÍÉT–ù› +ËŽC œwI›üX]‹¹\ëY]þf lïYbj8ŸÈuœbŸÍÅtú©fÞןfBI—“*øé:ÛØUj Ò +ˆõ¹ Õp $(~ ¡Ú ¡gù{îpZI?¡ƒîÀv:“a¦˜6¢§Ô]Ý‘(ªê)!ŸÚ¢: +jwµ¡4ÚvíHÛǘ9ºXhó•üù£¥Á¢VÉ{Dº2š‰(°¤3š¤a÷ +У¥“p¢þò4Vº—  +E´¥è¤k°7ºhT*€¿èw`ڞiÄ …S¦Ʀmê Nêƒ#ú¢f€ xê†ý +8z©7uÚp{Ú=~]7`«h‡ÚsÚg:…zd˜ó§ÎA-vþAñr¦'–AÚ)9–š¢âSi;£…š 1ªo"ª +¦J;“º rº8Ui|é>¡Úœú + +“ë¥Dfný2»ƒ–0j«®»ºK;zë¢Íö»—!µ—S»³r>K+6ˆ‹¨XÒ»; CÈ +8Ê;¢»ÃÛ/Œ‹¥ž!¬s½VR½óõϋOâ[/çK¨þ˜Ñ:͋\Ý+ Sc:ï˞’º¶ë9Æ» + +ô 8ly$ +8©ÙÅmX2Ùh>—?¯!šHüÁ^LsP,Ÿ«Y‹âá¿ÿtšì‚£Y +r¦Éš¥9ÇjžÄ8-ÆÇŒ¶iêPÂbA˜ù‰Ã¸š»³7RœCWRoìŠå MŒŠ”åt™ Œ›réÉq + + +å>}Lê}ÎǨ 5:àŒ|"þÇwÐsøæNΰ¹#R>~-N‰®èƒ ßcðÞÚÎÑ¥®åGÎâ툉Ýè*‚¸ +=‚ž ºëⅭëÀ>Û·žën^žmèÊëð¼ã>å×Λ«}êØ÷ +“Œ¬ËIÁ·AÔNÍëv>]t.âÚLЫþíï¾ñnäÖÜæs¹¿±â°+† +¬UØïî•.ç¬ÎìÍ.è´ÞŠG=ðù‚§ž¯”ë^äÛ®êh-‹êê!i!ÕvMíiªîþ¾òîá/þÑ-OÖGð,oñº!å’gOâ POìOôBþÈàhâ+?ï>ßÊVHÀsaõ™€õ$óSîõ—»ó8.žß¹ +~áßÈ©ö»]ò3ëÆt_÷[ïôb¯ç‚Ü÷Õ«@u™ð;zܘ‘Ü@óŽ2’?ùƒ¸ÙlùF ¶™¯ù›N ž0œú£¶¤ÿ0#9:ß§½ž©Ÿ\#ÃÙæó2é+û‚ÀÓ¸_äM/ÓtaÚý3”]Ù«¿¸iîaF>ª}ŒØvÍïMÍ÷Ðëä©îr܌öqñ_ÀüªrâF®ò +ýþ¸—hT_ã4sx”ýÝî)ç.QgûàŸÏ%ì‹}i´ASû|þð@QÜ +$J9€»-̱÷ÜôMؑhZ˜¦:°œ*ÏlßxÒ|ϼ¡ÅLÀ ¬Áfù9BÑdìÁ|«VV„¢“énKv + + +kB_ƒg 3ʳ8#Þ¬L=0;J¤äÈ@¤F|'i~±© žaʊÆg;d*3²”©bPÏ¢TäHô¦?[† +ÄäƒhN6ZM¢D:c*BR!$±ckƒ’V­-uÛ@[øp„Ÿ]¼8ö-1{TήWÏ2ñ Šp=¸q«Ñ½es.‰„4+#Ëe¦¥W5µekxr䛓/X͚5Iǃ=kÝúµì˰ûN–2qÅ¦yZ£QŽ›ÇޝtxŠäcK—Ííɹ +iþ¡9¼m1oñ¢©/²8îìSté4l’Wm¾9óéÖÛÐãã{{üzÞ¿çøêöÞzà}œàL¨ "˜ +ÄÐsà¶PGLUúå`MÞ  ¡†9¬§Û{pX¸¡wÚw߇¡¨ ‰í "MUXNx + ++l´á¦ +j²F:Á.êÆÛj¤³Búî ¼Ê«/£Ö’[н#í+ð¥ænJÞ¸«æ;ð©õ‹¨ _ËðĊһ*º? +ƒÂwœÃyzh±°Øzl2,#oZ2țr|ò˂°¼$Ç)ë +óÍÙÔ,éfs€1Î@/øîÏPõÌiÐH·ðÃBkLtÒP¯bôS;NÝWÔXÏ +ó’dlÍtÖ`°tžOc óÅa§}Aě²1vËjÇmþu+`ÍÍÁ·qwü6˜‚ì½sÞXŸ¨Ë$xM6àP³-iÉSÚ½Aوïë84–ø=xä8^!ä*L>ޘƒk¹Œ({Iè^!ḘN$ê +«®ç!ºû‚ÿÝ ë¯ßoî—Oü¨¾ÿî9í]ñÞ{ñÙÊ®ãlhŽ(èÌÃê¼~ÔS¢|ö՟zýw¬Ë§|øÝ—*½ŒÈ×­|úåwzþæ“)Nrû¾Ê?*ô¥ +¿*÷ô7ú½~Múúú÷ª÷Ɉ•S3x*ûíP”ùH£°°àó(è¾í-Jƒú™ +åAF{#\”g…Áœ)!),Ô #ÓÂǼjþ1œŒþh©²K„9$ƒYè)Ž ˆA È +—‡)#1‰Óp"˜ð'Ã%n‰P´‡Ù¨-‹1³¢^\%ƈÔp„CLÖ5à + +
+

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..59f3201c8f54aa27f8044d646ecf14ec0d71e2e3 GIT binary patch literal 17648 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 G2>uTUy;J!B literal 0 Hc-jL100001 diff --git a/doc/stp.shtml b/doc/stp.shtml new file mode 100644 index 0000000000..511764e3d5 --- /dev/null +++ b/doc/stp.shtml @@ -0,0 +1,169 @@ + + + + + + + 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..48dac357bf --- /dev/null +++ b/doc/sum.html @@ -0,0 +1,628 @@ + + + +CUPS Software Users Manual + + + + + + + +

CUPS Software Users Manual


+CUPS-SUM-1.0.3
+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 + +
+GIF89a¯ÿòÌÌ̙™™fff333ÿÿÿÿÿÿÿÿÿ!ù,¯ÿBþXºÜþ0ÊI«½8ëÍ»ÿ`(Ždižhª2€0p,Ïtmßx®ï + + +;±Ýíˆndý !¸ ž³wà…MƒƒY~¿{,gÚ\‚äé +Œ×Ø(tÙî!Ï=Ñ.ûz¯áџ:ì;Ã9qöíÉë]/¿ºÉ¤Et/†'Îþt9Àؖž_ÙÇ\|W•wArö¸Ý2Ô× +tN°0Tï}¡û‰$!‚yMxî)ˆš‰Ôø@nB°U½ÊwE„§!ŠF H L8B +c‰;ždŠ-æDVWdг€h±äړP¶%#(4Fiå•Ï\hŠ:Re!\ÒėX^¦%€¥À-$E€Ö/úHŽšlââöÌQX + + +¸1Nô¯b"œŠüjåÁÂE0…È8ö5GkZ|ÒÁwt„C»ÔQSÇo6Ôِ[W„$²*Ž+4Pb-8¹P1þ'8"‘ФÄ$ Cyê‘„)>ãŠtè`Ð3‡‹¾z"«rE'Âqfä°Ë +‘qÂ\|€„Ž¡ôö»%É(.—bڽȀíÉ`{¬EÇ1w’ »[Hß`(B6ö“  +†')ÊRŽÎa[ÃrbC!T尌 +2Q·ÈHZê#–®üË/àô¯FÝê(Û²% ºXË9öÀbÁ4f.ù-oý™XËB…IÎÒ7¹*@ÃӎÍT€hà‘ÌW␙Ã$f:µyžn†ó†r„'téKv` +Ç+dª– œ79sò|'=×¢Ìx¶òœÿ„¦œˆeÎ;*à$þ” IÝÆaÏ{–3ŽÅÁ +P“ÍS[ÙL¨3©òQ7éÆò#ãûô0F×ðsE°t§@‘ØQÜ´´ ©:3ÓRíd ¥*MITnŒ£¨H]ØQÁd +@òþ—¬rMœŽaO + +rë^yÀ·(¸îéêû$uDòrã/a,I.°ÙUÀœb hˆ`¾B ë" +Ü`HØxȸo1þ[á\8f^æ|\ý‚¢¢zø0(ˆ\ {ƒÄgäÞõ€çâ§Á˜0*\³n¼‹m¶/Äeª±ÿ†ì +Ç,½DN2€œº+ùÉ|í0L¡Le*ð¸Ã>­2ëf,eIPOËÅàr—±”80SAŸcFªatç»ãy¤¸ršçÌ¡5ïoõËsžï|¿8˙Φ¬þ,ï¼èà)ÁÌ;øk¡—†dDpÑòø2¢qfHã!˓~ٟ-í +'g:,æ4y?ýäP‹Z›ž#ÏÕ´Î5AK‰k]ûš›ÒKõ¯‡më€õzØÈƫ؎Ý>B{PЪ.6hf]º?©ÌIŽuO„íM‚ÌÇÜcµ3˜ +61‹NÒ[†W£ ¦m¿­{ÂPâvζKnUˆ[ ònĽ±÷n?l:Áž3ušë¬sP[ÿnn¾çP…WõÔFj[Â÷ +¹vÏ™à‰˜xú'ˆ£ÀÀ†p¸4.êãKÇ¿ÂÁ±o§¢ü"Á|Nk`îʘ + + +jl©ÌuˆËi™0pmC´«+‰÷6¤2­éÏe`(ŽJ]¥iõð3ƒØí"p|ª!:qøFس 6£ +@­,þŠqüぐoÌÇ®žÖüV“¶QǛEvî¹²É8ÙªS"æÀç‡x± àþ‡>—Iãg +ïÝ>Y‰çN80æ§ ±¾GLLìÕµ…(1Þ¼!8}þ¬“*…ª‰Ùì:e»´œ +ª¿ên_6ÂÃSÀ`eG;Ö„CƒCcˆ¿‡4¸yeî¯Í)oøByRm½0?íLîÅ`QÿjÓÙ/ºôÓN|Ý + + +þÙAÜŒÁ¸D5©D aævx ?жx°DM@•!h‰àȀާ® +• á×B`ð¤ªE?›“”Þdƒ"8$Ý`Ki0…OðƒnΓ±µvtžè€I([,¹Ndɨh\'6X +P㗊‰Éøt ¢‘¥˜¬è €ˆ†Ky™FˆŒë`š”yƒ„¨š €š‰ƒM©‡øFQhY„ +9¶X¯×–í4š¤™Y\)"¹AN]‰xéz÷Gq07)©ñ™•Y€r°ŒŽi‹ z ™ÇäFÍÉT–ù› +ËŽC œwI›üX]‹¹\ëY]þf lïYbj8ŸÈuœbŸÍÅtú©fÞןfBI—“*øé:ÛØUj Ò +ˆõ¹ Õp $(~ ¡Ú ¡gù{îpZI?¡ƒîÀv:“a¦˜6¢§Ô]Ý‘(ªê)!ŸÚ¢: +jwµ¡4ÚvíHÛǘ9ºXhó•üù£¥Á¢VÉ{Dº2š‰(°¤3š¤a÷ +У¥“p¢þò4Vº—  +E´¥è¤k°7ºhT*€¿èw`ڞiÄ …S¦Ʀmê Nêƒ#ú¢f€ xê†ý +8z©7uÚp{Ú=~]7`«h‡ÚsÚg:…zd˜ó§ÎA-vþAñr¦'–AÚ)9–š¢âSi;£…š 1ªo"ª +¦J;“º rº8Ui|é>¡Úœú + +“ë¥Dfný2»ƒ–0j«®»ºK;zë¢Íö»—!µ—S»³r>K+6ˆ‹¨XÒ»; CÈ +8Ê;¢»ÃÛ/Œ‹¥ž!¬s½VR½óõϋOâ[/çK¨þ˜Ñ:͋\Ý+ Sc:ï˞’º¶ë9Æ» + +ô 8ly$ +8©ÙÅmX2Ùh>—?¯!šHüÁ^LsP,Ÿ«Y‹âá¿ÿtšì‚£Y +r¦Éš¥9ÇjžÄ8-ÆÇŒ¶iêPÂbA˜ù‰Ã¸š»³7RœCWRoìŠå MŒŠ”åt™ Œ›réÉq + + +å>}Lê}ÎǨ 5:àŒ|"þÇwÐsøæNΰ¹#R>~-N‰®èƒ ßcðÞÚÎÑ¥®åGÎâ툉Ýè*‚¸ +=‚ž ºëⅭëÀ>Û·žën^žmèÊëð¼ã>å×Λ«}êØ÷ +“Œ¬ËIÁ·AÔNÍëv>]t.âÚLЫþíï¾ñnäÖÜæs¹¿±â°+† +¬UØïî•.ç¬ÎìÍ.è´ÞŠG=ðù‚§ž¯”ë^äÛ®êh-‹êê!i!ÕvMíiªîþ¾òîá/þÑ-OÖGð,oñº!å’gOâ POìOôBþÈàhâ+?ï>ßÊVHÀsaõ™€õ$óSîõ—»ó8.žß¹ +~áßÈ©ö»]ò3ëÆt_÷[ïôb¯ç‚Ü÷Õ«@u™ð;zܘ‘Ü@óŽ2’?ùƒ¸ÙlùF ¶™¯ù›N ž0œú£¶¤ÿ0#9:ß§½ž©Ÿ\#ÃÙæó2é+û‚ÀÓ¸_äM/ÓtaÚý3”]Ù«¿¸iîaF>ª}ŒØvÍïMÍ÷Ðëä©îr܌öqñ_ÀüªrâF®ò +ýþ¸—hT_ã4sx”ýÝî)ç.QgûàŸÏ%ì‹}i´ASû|þð@QÜ +$J9€»-̱÷ÜôMؑhZ˜¦:°œ*ÏlßxÒ|ϼ¡ÅLÀ ¬Áfù9BÑdìÁ|«VV„¢“énKv + + +kB_ƒg 3ʳ8#Þ¬L=0;J¤äÈ@¤F|'i~±© žaʊÆg;d*3²”©bPÏ¢TäHô¦?[† +ÄäƒhN6ZM¢D:c*BR!$±ckƒ’V­-uÛ@[øp„Ÿ]¼8ö-1{TήWÏ2ñ Šp=¸q«Ñ½es.‰„4+#Ëe¦¥W5µekxr䛓/X͚5Iǃ=kÝúµì˰ûN–2qÅ¦yZ£QŽ›ÇޝtxŠäcK—Ííɹ +iþ¡9¼m1oñ¢©/²8îìSté4l’Wm¾9óéÖÛÐãã{{üzÞ¿çøêöÞzà}œàL¨ "˜ +ÄÐsà¶PGLUúå`MÞ  ¡†9¬§Û{pX¸¡wÚw߇¡¨ ‰í "MUXNx + ++l´á¦ +j²F:Á.êÆÛj¤³Búî ¼Ê«/£Ö’[н#í+ð¥ænJÞ¸«æ;ð©õ‹¨ _ËðĊһ*º? +ƒÂwœÃyzh±°Øzl2,#oZ2țr|ò˂°¼$Ç)ë +óÍÙÔ,éfs€1Î@/øîÏPõÌiÐH·ðÃBkLtÒP¯bôS;NÝWÔXÏ +ó’dlÍtÖ`°tžOc óÅa§}Aě²1vËjÇmþu+`ÍÍÁ·qwü6˜‚ì½sÞXŸ¨Ë$xM6àP³-iÉSÚ½Aوïë84–ø=xä8^!ä*L>ޘƒk¹Œ({Iè^!ḘN$ê +«®ç!ºû‚ÿÝ ë¯ßoî—Oü¨¾ÿî9í]ñÞ{ñÙÊ®ãlhŽ(èÌÃê¼~ÔS¢|ö՟zýw¬Ë§|øÝ—*½ŒÈ×­|úåwzþæ“)Nrû¾Ê?*ô¥ +¿*÷ô7ú½~Múúú÷ª÷Ɉ•S3x*ûíP”ùH£°°àó(è¾í-Jƒú™ +åAF{#\”g…Áœ)!),Ô #ÓÂǼjþ1œŒþh©²K„9$ƒYè)Ž ˆA È +—‡)#1‰Óp"˜ð'Ã%n‰P´‡Ù¨-‹1³¢^\%ƈÔp„CLÖ5à + +
+

Preface

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

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-edge" and "-o +sides=two-sided-long-edge" 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-edge filename ENTER
    +% lp -o sides=two-sided-long-edge 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
    +
    +
+

N-Up Printing

+

The "-o number-up=value" option selects N-Up printing. N-Up +printing places multiple document pages on a single printed page. CUPS +supports 1-Up, 2-Up, and 4-Up formats:

+
    +
    +% lp -o number-up=1 filename ENTER
    +% lp -o number-up=2 filename ENTER
    +% lp -o number-up=4 filename ENTER
    +
    +
+

The default format is 1-Up.

+

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. The default gamma is 2200 which matches the +sRGB specification.

+

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..309a4a2f17 --- /dev/null +++ b/doc/sum.pdf @@ -0,0 +1,923 @@ +%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<>endobj +157 0 obj<>endobj +158 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 +156 0 R +157 0 R +]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<>stream +xÚMŽË‚0E÷ýŠ»ÔÄVÚš.ÕàŽ¡|‘â#(JAÃßK5F3É,æÞs2wÂLád„ý…¬ Yn5DSƒ‚iH²¦šmŠ4GÞÖý³ì, +g;‡¤¼e37ç Á¹Ç´b +”K&¾͋„r0é›Tû\Dk\ºñgM»¶ö½{÷BÉ¢?Q{»ÓáØƒk­è´ô«¦A揙>zØÊ£±!;ò®^;™endstream +endobj +205 0 obj +175 +endobj +206 0 obj<>>>endobj +207 0 obj<>stream +xÚ+ä2T0BCc3JÎår +ár á +äHÉHendstream +endobj +208 0 obj +31 +endobj +209 0 obj<>>>>>endobj +210 0 obj<>stream +xÚ}TKo£0¾çWŒzJ¤ÂBÂæqÜô¥Hm—-iµ.†Æ­±©mÑ_¿c J7[­8áÏ|¿Bè a1…Ùòj´Þ޾]¯`À¶„(ŒüÌl‹q¬±d9N¶/”Aº ¯OñfӅ?uYÛ7`TiL#4µŠÉ† (Ðäšgh`§`•‹‚Ý!\¨ªRï7¿!Ö\Z.Ÿ!iÅ +ÒñÙÅcœœ¥x¢Z\I /œõ C?ðg~já¡¢pøKÊüÜ£Þs<üžò¦s?êqÿG­Õž`P+mY&Î†ÁZÔP*ÝÝM§ßç jÔ¬ š®€ñacaÇÌ ü Q’2{t£€¬…+fZH>Œµ*šÜ§a¨”E‚`,“ÓÅ‚Q¢±¤N‡‚ ѳأ,9@Ù'};g|pÚ¹93¾Oî¬Q¿¢Àr’†<Á%µDífÁøCÕ»rTº/µqyíQLbcU®Ùº¹Ú^{›8&cYŸž1C³ãðS+öìò;z𢲎¼5ØPS ³NèÜ:\]2⒡ó1߯—çðp}†‹U:9‡„†€âwh {FX •¿RZr·vQ×áG]'tH˜ë*u&˜0ꤥij7 dځÛh$Ÿè§ldîŒ`‚ÛöK}XQ YJ¿ö S¦ÕÁ8ÊE¬ŒMhWj{äÔ-OÝYL;Ǘ´I†Ÿ†@uq7+_c%´‡ÔWÀêZðœõY`?¼_#&öäz.š~òÆXUñwê½ï—T 7÷p³;BOÇy£5J+Z聪ò߬Èfé䯁Ià•³©ä´k›˜†„YÈé<ë^–ÂíÄ3©¤÷I¶AV3< Ëã‡Áòä5‹–¿¢{LÜÿÕvôkô)'¤¶endstream +endobj +211 0 obj +689 +endobj +212 0 obj<>>>>>endobj +213 0 obj<>stream +xڕѱNÃ0à=Oñeˆ©“¤ŒØP‹’ÂÂb·5$6ØN#xzì¤UE¥•½Ø¾ûî¬û(¦nQÄ©ßUܕÁõã 4C¹v/i–‘e=¹WU×ri±Øq½¼¿*?\dJÇÈ0JIâ#Ë­00jm{¦9:õAËdǸ¥7LŠ_^CH«`·kÕ4ªrÃ++”4·#^íñ('ÑÑ‹Ò ÿ«O(B,µ½RüËۓF«c£4vÜÈÕÁÊxÅwvB^$ÅN*,“5ÓõqÅ×𿋠ÄAó-¯>]9Õv/‚ ÇWþ>fäû šPƒÆ ɽ9_- ‡y¬†y< óði!MgäaM}päïâ<ÇôìÐÊà9øÄVŸÅendstream +endobj +214 0 obj +288 +endobj +215 0 obj<>>>>>endobj +216 0 obj<>stream +xڝUMÛ6½ûWÌqð*þŠw÷Ø ÚC².֛ô°ZÙìR¤JRrüïû†’?"-P0,™3ï͛7ÿGSšà3¥û͗”W£ëÑ»O4›ÐºÄ÷2›Óò~AëâfJw´òÚFm·ô|‘+zjÙ·š÷·ë¿¶ éTÂ»ùì>›Ièz§å;UGöT{×ê‚)K®'WÒÎí)î˜>ºªr–^¾üþçÞÞù·uh4½´ Ý-&ÙC‡Ã琕wÃՏÔpx¶ÌR=Ÿœ§+¨;²ìÜ‰ú˜¥þY–Ú©@µQۆ‹Äôuö~™Ñ‹5úé³Î½ ®Œò–¾i[¸}H¿ùYåOÏã®>>>>>endobj +219 0 obj<>stream +xڍWÑRÛ8}ç+î#ÌC(ÚÇ¥”-:›mÜÙ^[&jdɕd¼é×÷\Évˆ 2%ޤ«{Ï9÷\óýhNçø7§7 þ)ê£ëüèìöͯ(¯°²¸ºÊ”—ÇùFR.‹±Ú>îNòoØvIóyÚ6»Xd—¼íý×劔§µð²¤¶±†„!YK÷¨Ì#ݙ ‘|¦®¤BháÇÅ¥S&ðö¥³ÁVŸ’ut·\fümâKi8 \=“]ðÕ²^;Q ÖzG¥ý!'[Qñ¤CåøÙK÷„_µ0m%ŠÐ:éüiÜÑ)­›|Û4օŒs3ò¿@ŸUᬷU˜Üü¯2¥íp]#ˆ‰û²Îú}8œ|)+e¤'±‡ é«¤ +U6Cí(²“È¿‘¨ˆðÅEúf×þ ÛeQ®V[Iµ,•˜$èÕyJNz«[ޚŠõ–o ›Œîù ˆ¼³ÄܐpᬠXZ^Җ9Û1%–a< .ØÉÕ}Žž6­),=Ÿ Ûz¤ª•f<:±Ë諉5XÄtÏsØØN⮔ŒÐȼg‹Bz?¹µ°&8֍h +€b_·4…Û5é¹[VR·Å†jë@¿, Š=nH@X]2è`ñ%‚!~-v¥° ×È}ÜA³œ…”;a<§¨ðy¾<¥n£Âð!°¡"J\÷ºÅãTúÏ)È(ßà(bIò +X䖞”ìÐE[‘ˆG’>·ž”êô5¯ìÕ56LëƯW+³[;\(Ý“è òI•Qö…­-ƒd*ÏæÙù(¸ëØ:ŒtØ» ń̘|ik¡°›¤5 +9ɃzAdt£¥/…ÊïWϤ1ZxJ‹µ–@ˆª–Ý‚˜…Øq¶šÜËÕfÉ÷&:»<ÏÞòê'tî«ÖùA€ö +͐j‡¾]×*° 8Vz×”¢-úhǰ†ÃøÇ}Šv¬$T*¹š Ö¨ï-¬­­×lŠA¸d<ó€L*ãÂ{õhØ®- „­®æq6aùpÜú6:Ĩ¡‡“> ö‘ؾñ$GßBX[(Á…v*lX´õÔÁ¸7Ù +ÙÝ(ùYŸ8š£°’½…ãJëTؽÎÂ{ ¥ÿý ýÍ©ezºiô³­±á”&/Ehð` ·EZÀm‡1På~­”óÓ³WáЖÊÄÍ1ÎëµÞ*ÍÙ¾Zk¿žì‚5áSNj¦ÑCs ­4x0‡0 ac‰*ú6fÛ@°5'HVg/Q=NmV¥%j^N5!žÝ_C_„gBîâ7lߖßϐ䗻%>D*ڟ†grqª³´V¡M/†þf¯O—nþ_Э½ìâûl‘ÝY§á +MÑJLã;fugÝcYÄçO2Ü(…Mò8þ³iV÷…‡“SZ¥–ù X¡k¼ŽmSä{¼X¦ÎÃú5”:¾Cõñ¶Wâ|ñ.ûƒ—çci+¼×v܈_=kâ3^Ž…æC³´wvu7_òw—ço3þÓáÅ? >äGÿýŽUUendstream +endobj +220 0 obj +1356 +endobj +221 0 obj<>>>>>endobj +222 0 obj<>stream +xڅUÁrÓ0½ç+–\hg7NÓ¤½1¥0ÀS¦épéE•åXT–Œ$×Íß³+ÉnêÂ09$–w÷í¾÷Vù=ÉaŸ6K8]¯'—ÛÉÉÇ È7°-ñÍz³ÉÖ°-Ž®­Ô^X¸²òQXw¼ý…q+Èó7_®³Õa\ã@jx{}Üh'S‚Ñ‚¾jc”Ry +sà²”¼M,’ÅT©¹j áð…cu£Dÿžš@èü4[t„„ÒXø$:%¼Ÿ_3þÀl_™ö‹ðÀtWÂ=ÐïTÅeð³’XÕWÒ¥¾¡0ˆ§‡ÐÂ27^ÖLi}Óú4a²,…z(ŒB¹Hë¢F|(W™ö¦Î4tVâ >Y0Ò{ +©gäÀØÆPêÚW¢Æ×È‘•Eažœ¯Ù9Å}¾3öAêÝÿ´‹ˆ\1ç°i£‘ÊpÞíG8†Ê±Ö›šy‰Çj®Â³:é+0oS萯#|[dy4V0 tàNø¶ &Ihx(yáÐcë’j}_î '%Q×£q´ …p£ЍÔchíð9<⌒ÚÇé‚c9o-Ê˃yŸap>ÖO7£<š—=›€¾Gº8È'õœ$8À—ÍÆjŒRہ…t'Ü!i¦Ž%Q挸@åê‡tB îC@Ÿx¿O+¶ÞU’W=]È1±zw$²]ӔÿŽÈ˧D拣å4»;Nåz…eʑjæQÒâFÇ­“ãŽ$.±ä¸Éc/ y4ƒØ¹ŒE³HÜ¢½9pè 6ӛô5!ÙhH²üÍhu«¼¤K%à 1ˆ,QÈP²©öެÞ+Ýw2 ŽOá^š3Aü6áá0ú­+)]CNPƒÍ©P¨Š§\ +Î{6 6M:x+Ž?n’0ÒýՀ´9‡DâL¤<Ö·{`÷xÁaoÓÔ\`ƒ¨/™T­ShµB'—öæ°Ø¼Ç܅ûo·7Qìó$v¾¾ÈÎàt‘þe‚wnLé;ÿ6XúÓ- ;ÑóÍrñ¿¤Õù"»€ðöŒž?l'?&,òLºendstream +endobj +223 0 obj +815 +endobj +224 0 obj<>>>>>endobj +225 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS04³Ô3U072PIÑp VÎO+)O,JU-N-*VðMÌ+MÌÑ Éâ҅¨Õ…*6‰™šé™+€ùE™y%©E +.E™e@ Y×®@. ²!Õendstream +endobj +226 0 obj +116 +endobj +227 0 obj<>>>>>endobj +228 0 obj<>stream +xڍTMoÛ0 ½çWp‡)x±›&͎-ÚۆnqwêE±éZ­,¹’œÀÿ~¤d÷#]‡"@I|äããcž&),è“Â:ƒÓÍä"Ÿ|»Þ@¶€¼¢ïe’Âj½„¼œf0‡['õ=øáÆJíù°íÇæ$ ÜҔqóœŸfë$cl^KE-Z\mzÓýoÀu»FúQ˜O§K½g™€Äê_ù‚);0UÈèèÁbáyJêBu%+|cœßV¶> J6âc8iÎ6J‘?fqü8‘Êš†2:2I”W´­’…ðÒhªNgÆ0 s®¤ÆjYÔ¸çobAïzZñ/úø²6&,ˆîEû¡y°qôR©8âÆXrO-4ÏùÙb/¤»cu-+€î9Èñ©/ˆ{9Äi£L!Ôè¹½Dµ–d¤&1(¯¤÷ÖXZqóº²a1¸¶F0ö1 Ñ +8¤ê $©ES}Ž gÌ;äx·fä´iãD7ž¿h¸>>>/Annots 12 0 R>>endobj +231 0 obj<>stream +xڝVÛnã6}÷W ²(+U’eË.‡®‘mº­wíýZ¢-¥©’T ÿ}g(Rõ%vÜ"É3£3gÎñïQ þÄ0žÒoތ>­G?}Ž`ë-ݙβ0uñøÔ­6Ì@ÐBPÀóëço?®_08…8¦èÃd¦¾.9<íÈÖTR€ny^m+®Á”Xä ;Ø3aÀHМƒºÒäZU ÕþLLeŠ¡Œâ­TFÛûy§Çú  oKA<îá|ËºÚør ä5Ó:tqNهæQæ>í#tš_€ÀPºÕw¹îëö”ŽGÈeÓ`?û@Ïi¤žQ¢ÒCÜV5¬áïr‹½ô–ïBRÿ“‚`yÔâl•FáŒ2WܘJì`éÿ´ÀôéóˆÿŒ] ’˜C‹ªÀÉÓ£pìÔÇÅôúb˜p€ ÝmqH ‹ePL +ç…á7¹ç¯48,£¸K8ӆ©|â¾äÂê2‰À¼db×OÛ?ª3h™2UÞÕ¬§Ã&1,nÑaÏšúâV×r¯mMÄТD/ºî4ۏ\ú‘ßV•„‹ëœµœ.ðŸk-gÍYîž×£(ŒÐˆè#¦o¿B:NB2¥‡Ö@šEø·¿ªaE6ᥛ(!d¯¬ªÙ¦æü½2u@Iµ\D$­K9D…@Éèl¢`ªrh¾×¹ª6¨ŽJÀuœGÈç$ÌÎpž¦¨ÝКC¿(YKxÇVGCtä¢óµëӇÍ[:Â\™ªE²E§½ºzŸ¤)ïs0šçݓ×8ú×ÓÝñT´YL ûèܲ=ÐÆ3«ÀÛJ º&ÈmGo¸­µãÁyׇ›ñW$Þ3f§.¤jp)®ñ©oSHsÙx]3ƒúp.„Z’°ãæß/ÿ¹Ûö•nü™{-úÚOkÕñûÌà„BÜÿã +÷ü¢äù_ވ¼Ë¯ðDÐ!ÏJ6öþÂmýï¸õWõ÷¦ŸÐÙâ9êmYtFH,ç/rst °òÓݦ©ŒŠà-‚ì©æ-A¹&ƒŸSŠBrHÓ$˲镸dˆ‹'ÙìZÔxˆgÉ,MÞ1^Û"é’H½Ù7”*¸=P+uMôô†VXҙj_VyÙ¿Uí"û“•­ÆrS½òãóMûp&´i;x:'x*œ ‘(¾/W°’[³§¢ß5•ÿÂDÇjJ úè K" +žÑ½ñ|Î!ê%¥}µ1¯'g²_Gÿ +endstream +endobj +232 0 obj +972 +endobj +233 0 obj<>>>/Annots 15 0 R>>endobj +234 0 obj<>stream +xÚ¥S]o›0}ϯ¸‹4)“b‚ ’Çeí´ªÛ²†jÏ@œB ¾Ì6úïç’ŒNH“&$$ÛÇ÷Ÿsî¯ _â–Íäc:YÜø°‚ô`v¢$öH÷³÷P·Re +H ×ßÒëûéÓÄB}/1ç­¨¸b>1ù|Ëp<‚Ý«øãi“PÏÜZ܄@©i@tD^h*| d©/ª’Áæ2¾·‹¾ºœC'™Ý™œÚã)i§€­ªËµ+¡O‚pHÇøo]Buã’ï‘AqG#¸àŒ£Wq2†ZžQË8HÂàD[Ï¢…}…MɊgƒ6šô]a§ŸÚI8lìþO–u÷/ªï*^0Ø>>>>>endobj +237 0 obj<>stream +xÚ-‹A‚0÷=Å[êìǸ•èJ å ´Rµ%¶%^_óÞj2óbþa›Ïï,;¶9• ‚Р|ŸîPd¢_UmÝ u|K¯Ðå.ÒMò¹w–,nò—‰Ï0ËÊ´ÀRª{wCjo\TM”q +Ð~´?^ÖJ×'gãÔÜ»²¸p. endstream +endobj +238 0 obj +141 +endobj +239 0 obj<>>>>>endobj +240 0 obj<>stream +xÚ¥U[oÓ0~ï¯8Bê¤&‹4ix¬ ¤Þúâ¥îjäØ&v×v¿;N¯+Lå)¶Ïwó9ɯ‚È>2 q +eÕùPt®>å€#(f€Q?Œ!Í(¦Ý"¦¤žÂ}̈́¡5Œ”aRèËâ§-K!Wøº ÆYˆ]i1gÊ9Q®dJuY³ªÁÌ)è ¢j¥G´›Ä©)'Â8yà–s*ü9&aÉ̼ðäQKÞåêPMJYU–%ôë9 Ì­G$Q8pú>SAkÂO»±çp&Þ…™ä\.€R¢_‰#œƒY+kRÎ`Æ8Õ;ö¤Eã0u¨cÊiÙT97wtÊŒÙ3íAaz`¥ÃX.ê’þUØE ¡rÅïWëç‹Vhj|ÐÍè×lp¯d º~·I1wжÜ ¿®`‹|K»#gHŠÂðk1üî*­Ԇyª¢w·à†Ý/j%5ý‡ò¢&B+Û ¢\ÿ'ûkX{mܤ°—ð®wajŸ¦ö×ä³Ô¶Çµ¯6}ÛÚ=xX¨¤6 JÉÚ4»/jã(öÃ3é–Ćf'H³GÁf¬$ÂL.Û +[±x`OoÕNpšυÏâx6ø1†öZ'ÝAØ_Ù&ʹ³d»£t…³¼ª&—‡„û +O²=þ2»³áJ޹â~z6×uò’èËx×ICƒ3ë)LóCªh…óìlª£;´õE0O”KE-mnÝ%!ÂýÖ­PÔ?›õæö´Á›Û}ÊA˜¦–3Ž(qdÝGgSîOÉKòƒòÃশŸ_2ØþšîŒ‘ç{íO’d‰æÈEÈ- ‹Î·Îo)ê§endstream +endobj +241 0 obj +638 +endobj +242 0 obj<>>>>>endobj +243 0 obj<>stream +xڝVmâ6þί­têž§$Pv©´z×­T©{GöÛ~1‰WÁvmg9úë;c'@€܊=¯Ï<3™{ôñ•Á`DïbÝû4ëýüGY³ä÷i£ûaz³òö%ÝÁÇÙ?(ÐonŸ6ž Û3`ŽÁpúö–o£Dk¶, å7lþ¥7çl†ã÷Ú|ª+/'µ5ډSÓᖙxýî°¹]ŠÏÜðBúí™ðéŠæþÈ H³|”Éül%€¾æhã¥V\mŒ¶^”À­€R,¤ÂßRGYc¥òÂþä`2ù²íÍQŒ¾Sùß1ɱܟÊÔ~Zi"ÈUٕ=@åI”’϶æá&‰4ž!6šƒA:"Í©ð^ªeù«•ByN];ý.@7LC…á8ÄTÜ4>`#« +¬F}¡ÁŒaÜGĖV^G´ 6è½Ï_ÛôÆä›‚åÁå¨ º 8+¾ðøeöø­›#Å6» 9¤ô¾*ø¤ý +¦²ÄPô"D8á'-t&SG*~£ý*™[!˜(—˜:FtV¦Òjو´4 +ð`Ôs¤HY›J|ǸÈùAu‡Tðr+ƒ†Š¤O_>Bˆð(°]9$1Wúào¡ízT—Àf…(à»)7 R$–Kí]*ÞÛ(ž©&Eԏ£ï-ýÂדa**Q6pøÆª"¨/ÝEPŠÌ’Ž{éîPqÁ¨C“¶5"D ý.sh>»Ž +¾K)¹KÆ,ËÏ"؂láø )°Ò|®_Er0çFíÄ1§xÞÂ+¯jšÀ +æ8^±–jYE&'À%8ð°ÐU¨BÜ܀ª×sa];hSÂZn9Mêù ¬×Ü¥¡IbEBòj÷ŽâˆM&9w…P%1CÛRجXr[VÂífE¸À?g&ZoÆþÍã–#i£³#•nXÄ«P”².Ë€ÚÅ ºcžþ?­Á«èD:dózbFˆæêŽúž ´3öbÅú±Ú<>œ´P°Ö¶LÚý ¦â¢¼¦}ÁÐÕE½Æ'Gƒ~|bfϲ¦Ì$—ÂççÉt?F3t‘@¾i”É%6îšû‹mŸÍ•»WÈTax}‹ظ£pĩɄ7%Úì÷V6§¿„3è`¦zá7´å<;j´'®p +[R”fwyŸ„³œó»ô»ƒ•Xv ]'ZI"´S]Û">>>>>endobj +246 0 obj<>stream +xÚ¥VQOÛ0~ï¯8!MÚ$ÒÅiזI¼P14it„I{4ŽÓ˜9vf;tüûÐÒÂÚPÔ7û¾»ïûîÎéŸÆ FÀÊÞYÚûøåÈÒoFÒO ÍÞ_sç„Z€+8œ±(œâÖ~Hï0|„4áQ2ê}ø/]£ +˜VÎh`úž*%Ü®à ópS¡Ï@×®ªÔö±ÒQ¤Ÿ„ŸVÜ0®ÜèÊ ­>7åc8ñՑ”„âï@V°‰$I ¹\ђÃù,=¿Ú¤tKþ'•5·°0œ:n +!q Kì¥ÏÉ՚÷1, Ì ÷ Jz]›Œšßˆ®ß]Û ýѶ½´,)Lµ1œy™™¼IØ*I'«è4éêq!ãøíþbð3‡!EXÆsZKאóDÐ42hYXH++ ¤Ž܆böêâ lřÈ£^üº_ãÖúaܟø,)ÿëà{pèÿKà©äZJ½ô&7~Z U%°<ò òB|:ïŸí6"³º¼E簧ӂÊÐF s<ùªX±“o3«Äf“Ár×x V‰Ù:1®L¼o|^’¼8zÂìVôMàÆv#»ˆ‘!gW>åä­2¦ZÖåžáÍhâök3ÒFïíD›ôÀfÌé‚Ã%5 ±CÀL›_š‡fQ=¢l@ ÷Àép‡ƒ”aJá¶|ƒÛªfwµuϳԖ?>L[+ìÃ"ÉsךvŒ §áÅ~ìtµ:¤*[_Üjçt¹iþ^w·ê¿à±'Û¾ 'ô^Z±æ©°‡`Òv”à|Âï|H1½™_õÎÝÒ÷ðÆúí¿¤ª¦Òƒ"2:ÁØhŒӝ †ã!R +AdàÎÓޏÞ?n•àendstream +endobj +247 0 obj +666 +endobj +248 0 obj<>>>>>endobj +249 0 obj<>stream +xڕWßOã8~ç¯!´4›_ íöEÜÒqpÐ}8‰ÓºÔàÄYÛ¡ôþú›±“¶ ´dEiUçóÌ÷}3ž¤?"ñ/‚$£×4?ø:9øüG +Q“9^ÉFi0‚Éìh²àp’,ç÷Ç'ÀŠ™ 3c–p&:s·zþé<óÕRéòÑâq!ñßò™ß7U¹sRŠ‚{ˆ°LŠ©øÏ~óÚC“t,Ý vÊYB[94|àâïÉÅíÚÜSÚ9 ­ièk|™“Økç“Ùkî\I©–X‚ÚU¤W–hÆrÁÑáº< \óü>r²“í7©ôµƒkû&ïšßhsæo««suZº{Ôõ±oM˜k•ã1¶ +Fa¦äS1_5¶:åx5—̝„­{ûþ¨“­Po2ؙÜÃY§ÝÒhm„¹Ÿ–BJR/7©˜¡ž.%·{…™M\ü‚”-h⌚Ëàq­Øqv·2ùVGmUIòR—Ñ·]§…°6½&ÙûöFñ[57JVÎY$ºECO¼riÈ7äPSá/v´Øsã0 Ãð5NÉG¿sK\¾Ž\š– Ýð'x05ðWF&péÉx¶~C´“>gÏ|»§6ÆDVź|'WÒ +Œì½õÔøú8¡;ëgæ«Ú•7v÷É?›=UÆ6&þYQ/N0öÓ¢ç8XT¼}ê=1梻Јh +Ó:ú¤¾Ï~BXryª +«•¤VZ©JwëÄ%³|47Ö´~nüì=¶Ý¢.¤:ÐMEÍñF`ê‹;UûƒìÐʺQ@{œ[ö »½iªïâ8Cê ~¤¢9¿¢Í†×7˙˜Ï¹æÎAÌbj†5ë(‰Qä ½Ôk-ð±€IÆA‚…ÅUòliqœn/úµ‹ÉA`×oÞn¿áŒpöFi†ïYD8(6Þ,ïޏâ`\ƒñÉ&Ý Ž³SäàÁãQn[OIQLÏH$еõ-ŸYÇÅ ¸©téMu)ÝÚ¿œ(M^~¤ û#ë­Íûjsà·ÚjEQì‹õMs^´5Õü›+e_±a7ëûd…Ôö}e9p_Y¼KÖ8ömí%´e]¯ë±äÔVkôI£ C÷Tä°=9ì.=§qc{[ËÝójðP¯nÔlšqŽ,ÃT=u8lO»KÇ0òÏPW8™ ËÚb.‹™xTm)çZäF}Ôfé°ÿ`p؞Zv—–$ò³à|Å:§}<6bþ¢'ÿAÁ^6EÛ#*öŸÛS”þ7ëFÍ¬ËÆÁ[ÎàûÍÜ©¹]ҏ“ï†kW¬¨üXxì G)-&Y‚k¾?ñJs󿡇Ž+÷SÑÔÒÿ9ø€óþVendstream +endobj +250 0 obj +1238 +endobj +251 0 obj<>>>>>endobj +252 0 obj<>stream +xÚm’Ao›@…ïüЧH•ˆ(‚íJ=¤‘«öЪ­É͗ 썗]º»ÄÍ¿Ï,XSWœØ™ùÞ{£ùåÈøË1+p]¡é¢Ouôþóy‰ºåJ5ÏÓõ&¾Ý<ÎK½…ßVÂVxi4ÖñQÆ®/aZ¯ØÒeýȘy>a’¢Jˀ©yø"1p{² iӏ@1*¹Qçµ-ÐÃKĤZ2h]¡š”ÜÓköÚ<¬_Oòl OŠž¤cè‡Ég†E°É HŠÑå;¨ÿu‰V*Ò¢#,¿×Ë_os&#á$éT®ŽåøÈx;CØíж멑­$w’ãd­5ïÒY–âö¼Ã„]÷Öl††!âŸüJ4ûDèMrØIOÜ(µ¿ÿ(‚À“PÓqJ¡§+u ?ÞRGê™×ïI;J§(óc”¼Z¤7|:£ÚÝýV¦õa ÷ŽðMèA¨0”L½É¬Èίë ûXÇ5‹œ_U9+Ó9Æ¡ü&<,ëègô$4Û endstream +endobj +253 0 obj +399 +endobj +254 0 obj<>>>>>endobj +255 0 obj<>stream +xÚ-‹±‚0E÷~Åaûl¬:ªÑè`¢¡l,´‘i_QsÏtrî“øg!'n=Û*6;¬@eAr/°œs¨:ٕ—Å`ÃK¥7£ÇY»¨©êXök³Lr’‚x.𛺋>´®A¸£A•¨Ö…*Å`¡N½nÌtÚ+veo­ˆ)endstream +endobj +256 0 obj +137 +endobj +257 0 obj<>>>/Annots 158 0 R>>endobj +258 0 obj<>stream +xÚ͛Ýs¹ ÀßýWìãÝL­,¹ß¯I{Ó|ô¬L_ò²–×¶î´Zw%%Mÿú¸ ®mr=s¶”Ì8fü,‚ ~ø?g*Šá¯Š +%y´jÏÞ.ÏÞ¼«"G˛HeU”i´¼þiY_mš¨»‰.ºí¾Ùîw?/?ûÛò,^Ä@À/ +¿üöQžd‹2j#ø'åÆ&ºDøD¾¿Þ¼Ë"¥ðÇ¡^¢ðã>÷ÍM½jð‡$É".øÏÅÉÿQOZÃÓz‘ƒY +µPÜ`³¼y—²`r@ øòÇnߴѓPÁiA=]d.•û™öé[Ó[7ß—ªEuBF Ù-®ÀÚ¨La$ÔࢵT¼0.úK·:´àšOÛK能t6phÔoy޽ôBŸ†½´wáee_ÁRðqéûÁÁÆU–•f|Êc¨AìTÀúsXÔkçO3„^ex¢áî”Vûz»_ooŸ† ý6ª2ptÆÝéœE#´api¼(\÷?tìèø—I–W&êf865 /YS]Þ5‹°xŠö•D궤ð +X=Q8ù’Gý#¯ƒtӚð)äV^ÈøYnÂ0Æ4Æ•eÅà&gŽŠK¸â~‹jVwÛnÓÝþ@`¦àO)K¦s¥‰‰Â0¦œÂ\iJ!ø×îʪ:ý 4à$†°ÙFàô¶! Bãð.6õn×ì¨î9ᇠÑÃknVµiˆÁ*³Æß­7û¦7C…Lœôô††'&®å%&ÓÍS$›þéõ/Ôqý«)Œû÷K¿þÆöoÊOÍ~™ßdi›0W–0õÔM–VŠbÜÇfÿ½ëÿ€Ìbbœ>Í(yK²æ’Œ¾¤$KóŒ€öefª'‡F½L •e“æQ w3çËΛԅºY듏ÄÝÌÚûRŸPF×ϧ¶â~F…Ë ‰Àz+ wœ,ÀD*ÍZ:‰DZV¤{Sæ¨ñX¥—f4¸ÃU»Þû &H¸•Th/Éå~͑»Ùyl/´i›•º,+``7'"Je@åzú±¬€ã\6ª£Mchö’„ø2Æõa"ö%%Å÷‹»®ó/?¡oiqµ‡3ªâܛˆì€¨¿tҘÉÛÕ "„Œ®S“prüÌÔFן¸4u"Ô1Páa‹ã~ÆS¾$`œÂBÈáY~ºß¯»-%}}£2`vXëXç{©!Ì®ôbæ€Ð§£®Ò¥q?ó>6ûõý¦ñ©Ç¸Ët€V€‰Ýýšêr]ßî£'UI%FjŒFOªŠ÷wÍêp€±°ª€ˆêÀ¸»š‘ß…2¦LÇŠû+‘ß½ËFZ<¦†)qxV€—ûzð¥,A^‰'¦.˜wÓwž&©´êÁh­ÀËIõ6҅æ×Â*g¨]ÛÖÛëó®·æø¼ˆÿ|g ¹_™QubüÃ4„û•ùsœQäÅÝùL×cû…qþdz4ò +I³ù3ÜÎÒÈ+ 䳝βªã´ù\—c”Ö1$%U‰Aþ»¹2a1~=|ð½BQ9„'JÔ¾Wh®­êíªÙøÝo€û©mݏºu°¸ª˜¸°,u@•1Æý|9kÔÆb!žÑ +0î×Î̌JOäµòî““ƒiŸLß?²ON`Oiòqâß'[˜ÙÎ:4êeJhŸl1°sŒ] w3úöºî¯½Üqˆx¶3áåéH›Q5*IƒÊ|2Hq²fÄëÕ#»‚ +\ö%‰6©®0áÊ4ÛÛ&IB ï}³múzã)G=Vw°ÜÏ8i­ä´.IŸ6UªâÝ{{ujÙ!‚Ïë˜68›f8;útWS¹4  ?“eÚ¿O> êCs½öDR©ŽÙ²À•ìÀH€ºþ_ó_ºÕ!ÇÁˆ’ Œ¶üqïƒIu€¿q`,@0”PTŽwú.ŠxÝ¡çWñKœ].Îø°¯¦¨%\.æ×Á]µÔÇ"Mc“4+À@¿Ó u̸Ô] 0ìS¿n¶P©Á²7÷¼åq•öÛZWöÞQk´µ®qäXß#iÂÁYûndë³õ¨õ0.‹˜õ¶ÛßùêáQg+s—Æö}ÌúÚ{)0ªÁŠC'Æu7¾xQ‰9Ðq6I^ÿ”Ê-på:(+`g´¾ç㶗 t‚Ϙ@-á„%?™ež›Ãc‹ô%¡ŒNˆGA.Š,ê·z{ë‹€I+Gqp$`q^·Ú¸+ÃbÝe‘€e}®où”éµkàÌç9Px G-1óyAåÓÇó/÷þãÎdD™CfeŠÅc'úG߯”ñ³"“®¨%Œ”¥ÏȆËd+‡eҙ¹p@åxHä¢XÀ ÞöëÛ»ý¶ÙíèÁӑÊ_•¬œT¢ê –°r?«êhd Ic œci Ë* ^Œ,ì}ݶµÿh¨pj•)Ž,î¢ë{ ¹\üÞ>OÞEiÍï¢J4¥vßEi=Ú+ï† P‰^Nx,ÎH±BO+±rY,À¬‹»º¯WøôÈS¢ JkYì2­3?û+ÕëvòA`Dýc»º3§vøØç|7èqÌyÞ¸G»y>æ‡jsýÏÒÈ?$Í +¨9— B}ð?Æ ›é–GâðX€y3üYøo«”h4’fÒÙ¥ÜKqâÂXÀ>쬽ÛI¡§z:P+À´u»æiÊ^ÿ]lpÆò˜ß¾¨¡%f,Wö +¦ìGè +c€A©˜¹0¼Â4±<þe– +¼ViA×FfbMc¬yUZr¦o½~#”ÉÚÊEqùð’çÄÉz¬E•ØgŸx@-áQ‰}¢¹ª70êӉRåÒ¬@6«âÕq;‡/ƒ\ 0ÌL¦9¸9òž#hmmßx–èQZ¹ÉU›Ñüõú÷Ã.t~7ê·Æ4‰K³3l-”ÑÖxÐã¢XÀ þ~ðžÝÊô¢¢œ XÀ ¾þ´„¸òõgÿ«ŠräUx$éòX \& +],qÏê’X@Ó‘¯Bu±¬Ë§æ²Ç|é±AϋǦŠ[Âób~_:ß÷,¼Cò¬@9'Û uÊÏS 0ì²Þzs[äs-˜Tf»L`æW,κÞ牂ÛÜjŠ´Œôù¢ÔÆí­Æäë°XÀ¾öy£ÐÆ÷iñ0ÓÃî–˜5úcñçï2”ùUŒñCÆÃürà\™ P®ì/\}ù|]v7ûïußD_vx,ð¡Þê ý2@t׺füëìÿa'ëÒendstream +endobj +259 0 obj +2689 +endobj +260 0 obj<>>>>>endobj +261 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS04³Ô3U072PIÑp VÎO+)O,JU-N-*VðMÌ+MÌÑ Éâ҅¨Õ…*ÎÌ º†prÇvMendstream +endobj +262 0 obj +94 +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<>1<>2<>4<>]>>>>endobj +xref +0 304 +0000000000 65535 f +0000000015 00000 n +0000000219 00000 n +0000001776 00000 n +0000001850 00000 n +0000001928 00000 n +0000002005 00000 n +0000002084 00000 n +0000002160 00000 n +0000002241 00000 n +0000002299 00000 n +0000002404 00000 n +0000002509 00000 n +0000002540 00000 n +0000002591 00000 n +0000002676 00000 n +0000002700 00000 n +0000002804 00000 n +0000002909 00000 n +0000003014 00000 n +0000003119 00000 n +0000003224 00000 n +0000003327 00000 n +0000003430 00000 n +0000003534 00000 n +0000003639 00000 n +0000003744 00000 n +0000003849 00000 n +0000003954 00000 n +0000004059 00000 n +0000004164 00000 n +0000004269 00000 n +0000004374 00000 n +0000004479 00000 n +0000004584 00000 n +0000004689 00000 n +0000004794 00000 n +0000004899 00000 n +0000005002 00000 n +0000005105 00000 n +0000005209 00000 n +0000005314 00000 n +0000005419 00000 n +0000005524 00000 n +0000005629 00000 n +0000005734 00000 n +0000005839 00000 n +0000005944 00000 n +0000006049 00000 n +0000006154 00000 n +0000006259 00000 n +0000006364 00000 n +0000006469 00000 n +0000006574 00000 n +0000006679 00000 n +0000006784 00000 n +0000006889 00000 n +0000006994 00000 n +0000007099 00000 n +0000007204 00000 n +0000007309 00000 n +0000007414 00000 n +0000007519 00000 n +0000007624 00000 n +0000007729 00000 n +0000007834 00000 n +0000007939 00000 n +0000008044 00000 n +0000008149 00000 n +0000008254 00000 n +0000008359 00000 n +0000008464 00000 n +0000008569 00000 n +0000008674 00000 n +0000008779 00000 n +0000008882 00000 n +0000008985 00000 n +0000009089 00000 n +0000009194 00000 n +0000009299 00000 n +0000009404 00000 n +0000009509 00000 n +0000009614 00000 n +0000009719 00000 n +0000009824 00000 n +0000009929 00000 n +0000010034 00000 n +0000010139 00000 n +0000010244 00000 n +0000010349 00000 n +0000010454 00000 n +0000010559 00000 n +0000010664 00000 n +0000010769 00000 n +0000010874 00000 n +0000010979 00000 n +0000011084 00000 n +0000011189 00000 n +0000011294 00000 n +0000011399 00000 n +0000011504 00000 n +0000011610 00000 n +0000011716 00000 n +0000011822 00000 n +0000011928 00000 n +0000012034 00000 n +0000012140 00000 n +0000012246 00000 n +0000012352 00000 n +0000012458 00000 n +0000012564 00000 n +0000012670 00000 n +0000012776 00000 n +0000012882 00000 n +0000012988 00000 n +0000013094 00000 n +0000013200 00000 n +0000013306 00000 n +0000013412 00000 n +0000013518 00000 n +0000013624 00000 n +0000013730 00000 n +0000013836 00000 n +0000013942 00000 n +0000014048 00000 n +0000014154 00000 n +0000014260 00000 n +0000014366 00000 n +0000014472 00000 n +0000014578 00000 n +0000014684 00000 n +0000014790 00000 n +0000014896 00000 n +0000015002 00000 n +0000015108 00000 n +0000015214 00000 n +0000015320 00000 n +0000015426 00000 n +0000015532 00000 n +0000015638 00000 n +0000015744 00000 n +0000015850 00000 n +0000015956 00000 n +0000016062 00000 n +0000016168 00000 n +0000016274 00000 n +0000016380 00000 n +0000016486 00000 n +0000016592 00000 n +0000016698 00000 n +0000016804 00000 n +0000016910 00000 n +0000017016 00000 n +0000017122 00000 n +0000017228 00000 n +0000017334 00000 n +0000017440 00000 n +0000017546 00000 n +0000017652 00000 n +0000018722 00000 n +0000018756 00000 n +0000018790 00000 n +0000019360 00000 n +0000019409 00000 n +0000019458 00000 n +0000019507 00000 n +0000019556 00000 n +0000019605 00000 n +0000019654 00000 n +0000019703 00000 n +0000019752 00000 n +0000019801 00000 n +0000019850 00000 n +0000019899 00000 n +0000019948 00000 n +0000019997 00000 n +0000020046 00000 n +0000020095 00000 n +0000020144 00000 n +0000020193 00000 n +0000020242 00000 n +0000020291 00000 n +0000020340 00000 n +0000020389 00000 n +0000020438 00000 n +0000020487 00000 n +0000020536 00000 n +0000020585 00000 n +0000020634 00000 n +0000020683 00000 n +0000020732 00000 n +0000020781 00000 n +0000020830 00000 n +0000020879 00000 n +0000020928 00000 n +0000020977 00000 n +0000021026 00000 n +0000021075 00000 n +0000021124 00000 n +0000021173 00000 n +0000021222 00000 n +0000021271 00000 n +0000021320 00000 n +0000021549 00000 n +0000021680 00000 n +0000021926 00000 n +0000021947 00000 n +0000022042 00000 n +0000022144 00000 n +0000022164 00000 n +0000022295 00000 n +0000023055 00000 n +0000023076 00000 n +0000023216 00000 n +0000023575 00000 n +0000023596 00000 n +0000023736 00000 n +0000024654 00000 n +0000024675 00000 n +0000024815 00000 n +0000026242 00000 n +0000026264 00000 n +0000026404 00000 n +0000027290 00000 n +0000027311 00000 n +0000027424 00000 n +0000027611 00000 n +0000027632 00000 n +0000027772 00000 n +0000028480 00000 n +0000028501 00000 n +0000028664 00000 n +0000029707 00000 n +0000029728 00000 n +0000029891 00000 n +0000030604 00000 n +0000030625 00000 n +0000030738 00000 n +0000030950 00000 n +0000030971 00000 n +0000031120 00000 n +0000031829 00000 n +0000031850 00000 n +0000032008 00000 n +0000033022 00000 n +0000033043 00000 n +0000033183 00000 n +0000033920 00000 n +0000033941 00000 n +0000034099 00000 n +0000035408 00000 n +0000035430 00000 n +0000035579 00000 n +0000036049 00000 n +0000036070 00000 n +0000036183 00000 n +0000036391 00000 n +0000036412 00000 n +0000036567 00000 n +0000039327 00000 n +0000039349 00000 n +0000039462 00000 n +0000039627 00000 n +0000039647 00000 n +0000039702 00000 n +0000039807 00000 n +0000039951 00000 n +0000040054 00000 n +0000040159 00000 n +0000040324 00000 n +0000040432 00000 n +0000040547 00000 n +0000040652 00000 n +0000040760 00000 n +0000040868 00000 n +0000040984 00000 n +0000041082 00000 n +0000041248 00000 n +0000041365 00000 n +0000041484 00000 n +0000041608 00000 n +0000041733 00000 n +0000041883 00000 n +0000042024 00000 n +0000042133 00000 n +0000042285 00000 n +0000042424 00000 n +0000042554 00000 n +0000042678 00000 n +0000042814 00000 n +0000042941 00000 n +0000043055 00000 n +0000043178 00000 n +0000043294 00000 n +0000043443 00000 n +0000043572 00000 n +0000043709 00000 n +0000043839 00000 n +0000043964 00000 n +0000044067 00000 n +0000044204 00000 n +0000044309 00000 n +0000044448 00000 n +0000044582 00000 n +trailer +<> +startxref +44810 +%%EOF diff --git a/doc/sum.shtml b/doc/sum.shtml new file mode 100644 index 0000000000..8ed10f2b3d --- /dev/null +++ b/doc/sum.shtml @@ -0,0 +1,578 @@ + + + + + + + CUPS Software Users Manual + + + +

Preface

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

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-edge" and "-o +sides=two-sided-long-edge" 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-edge filename ENTER
    +% lp -o sides=two-sided-long-edge 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
    +
+ +

N-Up Printing

+ +

The "-o number-up=value" option selects N-Up printing. N-Up +printing places multiple document pages on a single printed +page. CUPS supports 1-Up, 2-Up, and 4-Up formats: + +

    +% lp -o number-up=1 filename ENTER
    +% lp -o number-up=2 filename ENTER
    +% lp -o number-up=4 filename ENTER
    +
+ +

The default format is 1-Up. + +

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. The default gamma is 2200 which matches the +sRGB specification. + +

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/filter/Makefile b/filter/Makefile new file mode 100644 index 0000000000..daf4c29148 --- /dev/null +++ b/filter/Makefile @@ -0,0 +1,151 @@ +# +# "$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 \ + $(RM) `basename $(LIBCUPSIMAGE) .1`; \ + $(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..c529ffcc15 --- /dev/null +++ b/filter/common.c @@ -0,0 +1,255 @@ +/* + * "$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; + + fprintf(stderr, "DEBUG: Page = %.0fx%.0f; %.0f,%.0f to %.0f,%.0f\n", + PageWidth, PageLength, PageLeft, PageBottom, PageRight, PageTop); + } + + 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 && + strncasecmp(val, "two-", 4) == 0) + Duplex = 1; + else if ((val = cupsGetOption("Duplex", num_options, options)) != NULL && + strncasecmp(val, "Duplex", 6) == 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..b8850df407 --- /dev/null +++ b/filter/hpgl-attr.c @@ -0,0 +1,442 @@ +/* + * "$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) + { + MiterLimit = 3.0f; + LineCap = 0; + LineJoin = 0; + } + else for (i = 0; i < (num_params - 1); i += 2) + switch ((int)params[i].value.number) + { + case 1 : + LineCap = 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 : + LineJoin = 0; + break; + case 5 : + LineJoin = 2; + break; + default : + LineJoin = 1; + break; + } + break; + case 3 : + MiterLimit = 1.0 + 0.5 * (params[i + 1].value.number - 1.0); + break; + } + + if (PageDirty) + { + printf("%.1f setmiterlimit\n", MiterLimit); + printf("%d setlinecap\n", LineCap); + printf("%d setlinejoin\n", LineJoin); + } +} + + +/* + * '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 && params[0].value.number <= 1024) + PenCount = (int)params[0].value.number; + else + fprintf(stderr, "WARNING: HP-GL/2 \'NP\' command with invalid number of parameters (%d)!\n", + num_params); + + for (i = 0; i <= PenCount; i ++) + Pens[i].width = PenWidth; + + PC_pen_color(0, NULL); +} + + +/* + * '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) + { + Pens[i].rgb[0] = standard_colors[i][0]; + Pens[i].rgb[1] = standard_colors[i][1]; + Pens[i].rgb[2] = standard_colors[i][2]; + } + else + { + Pens[i].rgb[0] = 0.0f; + Pens[i].rgb[1] = 0.0f; + Pens[i].rgb[2] = 0.0f; + } + + if (PageDirty) + printf("%.3f %.3f %.3f %.2f SP\n", Pens[PenNumber].rgb[0], + Pens[PenNumber].rgb[PenNumber], Pens[PenNumber].rgb[2], + Pens[PenNumber].width * PenScaling); + } + else if (num_params == 1 || num_params == 4) + { + i = (int)params[0].value.number; + + if (num_params == 1) + { + Pens[i].rgb[0] = standard_colors[i & 7][0]; + Pens[i].rgb[1] = standard_colors[i & 7][1]; + Pens[i].rgb[2] = standard_colors[i & 7][2]; + } + else + { + Pens[i].rgb[0] = params[1].value.number; + Pens[i].rgb[1] = params[2].value.number; + Pens[i].rgb[2] = params[3].value.number; + } + + if (PageDirty && i == PenNumber) + printf("%.3f %.3f %.3f %.2f SP\n", Pens[PenNumber].rgb[0], + Pens[PenNumber].rgb[PenNumber], Pens[PenNumber].rgb[2], + Pens[PenNumber].width * PenScaling); + } + 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) + { + pen = (int)params[1].value.number; + + Pens[pen].width = w; + + if (PageDirty && pen == PenNumber) + printf("%.3f %.3f %.3f %.2f SP\n", Pens[PenNumber].rgb[0], + Pens[PenNumber].rgb[PenNumber], Pens[PenNumber].rgb[2], + Pens[PenNumber].width * PenScaling); + } + else if (num_params < 2) + { + /* + * Set width for all pens... + */ + + for (pen = 0; pen <= PenCount; pen ++) + Pens[pen].width = w; + + if (PageDirty) + printf("%.3f %.3f %.3f %.2f SP\n", Pens[PenNumber].rgb[0], + Pens[PenNumber].rgb[PenNumber], Pens[PenNumber].rgb[2], + Pens[PenNumber].width * PenScaling); + } + 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); + + if (PageDirty) + printf("%.3f %.3f %.3f %.2f SP\n", Pens[PenNumber].rgb[0], + Pens[PenNumber].rgb[PenNumber], Pens[PenNumber].rgb[2], + Pens[PenNumber].width * PenScaling); +} + + +/* + * '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..5a0536e7ea --- /dev/null +++ b/filter/hpgl-char.c @@ -0,0 +1,498 @@ +/* + * "$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 */ + + + /* + * Set default font attributes... + */ + + AlternateFont.typeface = 48; + AlternateFont.posture = 0; + AlternateFont.weight = 0; + AlternateFont.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 : + AlternateFont.height = params[i + 1].value.number; + break; + case 5 : + AlternateFont.posture = (int)params[i + 1].value.number; + break; + case 6 : + AlternateFont.weight = (int)params[i + 1].value.number; + break; + case 7 : + AlternateFont.typeface = (int)params[i + 1].value.number; + break; + } + + /* + * Define the font... + */ + + if (PageDirty) + printf("/SA {\n" + " /%s%s%s%s findfont\n" + " [ %f %f %f %f 0.0 0.0 ] makefont\n" + " setfont\n" + "} bind def\n", + AlternateFont.typeface == 48 ? "Courier" : "Helvetica", + (AlternateFont.weight != 0 || AlternateFont.posture != 0) ? "-" : "", + AlternateFont.weight != 0 ? "Bold" : "", + AlternateFont.posture != 0 ? "Oblique" : "", + AlternateFont.x * AlternateFont.height, + -AlternateFont.y * AlternateFont.height, + AlternateFont.y * AlternateFont.height, + AlternateFont.x * AlternateFont.height); + + CharHeight[1] = AlternateFont.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 */ +{ + if (CharFont) + { + if (num_params == 2) + { + AlternateFont.x = params[0].value.number; + AlternateFont.y = params[1].value.number; + } + + if (PageDirty) + { + printf("/SA {\n" + " /%s%s%s%s findfont\n" + " [ %f %f %f %f 0.0 0.0 ] makefont\n" + " setfont\n" + "} bind def\n", + AlternateFont.typeface == 48 ? "Courier" : "Helvetica", + (AlternateFont.weight != 0 || AlternateFont.posture != 0) ? "-" : "", + AlternateFont.weight != 0 ? "Bold" : "", + AlternateFont.posture != 0 ? "Oblique" : "", + AlternateFont.x * AlternateFont.height, + -AlternateFont.y * AlternateFont.height, + AlternateFont.y * AlternateFont.height, + AlternateFont.x * AlternateFont.height); + } + } + else + { + if (num_params == 2) + { + StandardFont.x = params[0].value.number; + StandardFont.y = params[1].value.number; + } + + if (PageDirty) + { + printf("/SS {\n" + " /%s%s%s%s findfont\n" + " [ %f %f %f %f 0.0 0.0 ] makefont\n" + " setfont\n" + "} bind def\n", + StandardFont.typeface == 48 ? "Courier" : "Helvetica", + (StandardFont.weight != 0 || StandardFont.posture != 0) ? "-" : "", + StandardFont.weight != 0 ? "Bold" : "", + StandardFont.posture != 0 ? "Oblique" : "", + StandardFont.x * StandardFont.height, + -StandardFont.y * StandardFont.height, + StandardFont.y * StandardFont.height, + StandardFont.x * StandardFont.height); + } + } +} + + +/* + * '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 \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("%.3f %.3f %.3f %.2f SP ST\n", Pens[CharPen].rgb[0], + Pens[CharPen].rgb[CharPen], Pens[CharPen].rgb[2], + Pens[CharPen].width * PenScaling); + Outputf("%.3f %.3f %.3f %.2f SP\n", Pens[PenNumber].rgb[0], + Pens[PenNumber].rgb[PenNumber], Pens[PenNumber].rgb[2], + Pens[PenNumber].width * PenScaling); + } + + 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; + + if (PageDirty) + puts("SA"); + + 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 */ + + + /* + * Set default font attributes... + */ + + StandardFont.typeface = 48; + StandardFont.posture = 0; + StandardFont.weight = 0; + StandardFont.height = 11.5; + StandardFont.x = 1.0; + StandardFont.y = 0.0; + + /* + * Loop through parameter value pairs... + */ + + for (i = 0; i < (num_params - 1); i += 2) + switch ((int)params[i].value.number) + { + case 4 : + StandardFont.height = params[i + 1].value.number; + break; + case 5 : + StandardFont.posture = (int)params[i + 1].value.number; + break; + case 6 : + StandardFont.weight = (int)params[i + 1].value.number; + break; + case 7 : + StandardFont.typeface = (int)params[i + 1].value.number; + break; + } + + /* + * Define the font... + */ + + if (PageDirty) + printf("/SS {\n" + " /%s%s%s%s findfont\n" + " [ %f %f %f %f 0.0 0.0 ] makefont\n" + " setfont\n" + "} bind def\n", + StandardFont.typeface == 48 ? "Courier" : "Helvetica", + (StandardFont.weight != 0 || StandardFont.posture != 0) ? "-" : "", + StandardFont.weight != 0 ? "Bold" : "", + StandardFont.posture != 0 ? "Oblique" : "", + StandardFont.x * StandardFont.height, + -StandardFont.y * StandardFont.height, + StandardFont.y * StandardFont.height, + StandardFont.x * StandardFont.height); + + CharHeight[0] = StandardFont.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; + + if (PageDirty) + puts("SS"); + + 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..b5442fdac8 --- /dev/null +++ b/filter/hpgl-config.c @@ -0,0 +1,647 @@ +/* + * "$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 page_width, /* Actual page width */ + page_height; /* Actual page height */ + float scaling; /* Scaling factor */ + float left, right, /* Scaling window */ + bottom, top; + float width, height; /* Scaling width and height */ + float iw1[2], iw2[2]; /* Clipping window */ + + + /* + * Get the page and input window sizes... + */ + + if (FitPlot) + { + page_width = PageRight - PageLeft; + page_height = PageTop - PageBottom; + } + else + { + page_width = (P2[0] - P1[0]) * 72.0f / 1016.0f; + page_height = (P2[1] - P1[1]) * 72.0f / 1016.0f; + } + + fprintf(stderr, "DEBUG: page_width = %.0f, page_height = %.0f\n", + page_width, page_height); + + if (page_width == 0 || page_height == 0) + return; + + /* + * Set the scaling window... + */ + + switch (ScalingType) + { + case -1 : /* No user scaling */ + left = P1[0]; + bottom = P1[1]; + right = P2[0]; + top = P2[1]; + break; + + case 0 : /* Anisotropic (non-uniform) scaling */ + left = Scaling1[0]; + bottom = Scaling1[1]; + right = Scaling2[0]; + top = Scaling2[1]; + break; + + case 1 : /* Isotropic (uniform) scaling */ + left = Scaling1[0]; + bottom = Scaling1[1]; + right = Scaling2[0]; + top = Scaling2[1]; + + width = right - left; + height = top - bottom; + + if (width == 0 || height == 0) + return; + + if ((width * page_height) != (height * page_width)) + { + scaling = height * page_width / page_height; + if (width < scaling) + { + width = scaling; + left = 0.5f * (left + right - width); + right = left + width; + } + else + { + height = width * page_height / page_width; + bottom = 0.5f * (bottom + top - height); + top = bottom + height; + } + } + break; + + case 2 : + left = Scaling1[0]; + bottom = Scaling1[1]; + right = left + page_width * Scaling2[0]; + top = bottom + page_height * Scaling2[1]; + break; + } + + width = right - left; + height = top - bottom; + + if (width == 0 || height == 0) + return; + + /* + * Rotate the plot as needed... + */ + + if (Rotation == 0 || Rotation == 180) + { + if ((width > height && page_width < page_height) || + (width < height && page_width > page_height)) + { + fputs("DEBUG: Automatically rotating the page...\n", stderr); + Rotation += 90; + } + } + else + { + if ((width > height && page_width > page_height) || + (width < height && page_width < page_height)) + { + fputs("DEBUG: Automatically rotating the page...\n", stderr); + Rotation = (Rotation + 90) % 360; + } + } + + /* + * Scale the plot as needed... + */ + + if (Rotation == 0 || Rotation == 180) + scaling = page_width / width; + else + scaling = page_width / height; + + if (FitPlot) + { + if (Rotation == 0 || Rotation == 180) + scaling *= page_width / PlotSize[1]; + else + scaling *= page_width / PlotSize[0]; + } + + /* + * Offset for the current P1 location... + */ + + if (FitPlot) + { + left = 0; + bottom = 0; + } + else + { + left = P1[0] * 72.0f / 1016.0f; + bottom = P1[1] * 72.0f / 1016.0f; + } + + /* + * Generate a new transformation matrix... + */ + + switch (Rotation) + { + case 0 : + Transform[0][0] = scaling; + Transform[0][1] = 0.0; + Transform[0][2] = -left; + Transform[1][0] = 0.0; + Transform[1][1] = scaling; + Transform[1][2] = -bottom; + break; + + case 90 : + Transform[0][0] = 0.0; + Transform[0][1] = -scaling; + Transform[0][2] = PageLength - left; + Transform[1][0] = scaling; + Transform[1][1] = 0.0; + Transform[1][2] = -bottom; + break; + + case 180 : + Transform[0][0] = -scaling; + Transform[0][1] = 0.0; + Transform[0][2] = PageLength - left; + Transform[1][0] = 0.0; + Transform[1][1] = -scaling; + Transform[1][2] = PageWidth - bottom; + break; + + case 270 : + Transform[0][0] = 0.0; + Transform[0][1] = scaling; + Transform[0][2] = -left; + Transform[1][0] = -scaling; + Transform[1][1] = 0.0; + Transform[1][2] = PageWidth - bottom; + break; + } + + fprintf(stderr, "DEBUG: Transform = [ %.3f %.3f\n" + "DEBUG: %.3f %.3f\n" + "DEBUG: %.3f %.3f ]\n", + Transform[0][0], Transform[1][0], Transform[0][1], + Transform[1][1], Transform[0][2], Transform[1][2]); + + if (FitPlot) + { + if (Rotation == 0 || Rotation == 180) + PenScaling *= page_width / PlotSize[1]; + else + PenScaling *= page_width / PlotSize[0]; + } + else + PenScaling = 1.0; + + if (PenScaling < 0.0) + PenScaling = -PenScaling; + + if (PageDirty) + { + printf("%.2f setlinewidth\n", Pens[PenNumber].width * PenScaling); + + if (IW1[0] != IW2[0] && IW1[1] != IW2[1]) + { + iw1[0] = IW1[0] * 72.0f / 1016.0f; + iw1[1] = IW1[1] * 72.0f / 1016.0f; + iw2[0] = IW2[0] * 72.0f / 1016.0f; + iw2[1] = IW2[1] * 72.0f / 1016.0f; + + printf("initclip MP %.3f %.3f MO %.3f %.3f LI %.3f %.3f LI %.3f %.3f LI CP clip\n", + iw1[0], iw1[1], iw1[0], iw2[1], iw2[0], iw2[1], iw2[0], iw1[1]); + } + } +} + + +/* + * '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); + + PenWidth = 1; + + 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] = 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; + 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]; + + if (ScalingType < 0) + { + Scaling1[0] = P1[0]; + Scaling1[0] = P1[1]; + Scaling2[0] = P2[0]; + Scaling2[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]; + + if (ScalingType < 0) + { + Scaling1[0] = P1[0]; + Scaling1[0] = P1[1]; + Scaling2[0] = P2[0]; + Scaling2[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] = PageLeft / 72.0f * 1016.0f; + IW1[1] = PageBottom / 72.0f * 1016.0f; + IW2[0] = PageRight / 72.0f * 1016.0f; + IW2[1] = PageTop / 72.0f * 1016.0f; + } + else if (num_params == 4) + { + + if (ScalingType < 0) + { + IW1[0] = params[0].value.number; + IW1[1] = params[1].value.number; + IW2[0] = params[2].value.number; + IW2[1] = params[3].value.number; + } + else + { + IW1[0] = (Transform[0][0] * params[0].value.number + + Transform[0][1] * params[1].value.number + + Transform[0][2]) / 72.0f * 1016.0f; + IW1[1] = (Transform[1][0] * params[0].value.number + + Transform[1][1] * params[1].value.number + + Transform[1][2]) / 72.0f * 1016.0f; + IW2[0] = (Transform[0][0] * params[2].value.number + + Transform[0][1] * params[3].value.number + + Transform[0][2]) / 72.0f * 1016.0f; + IW2[1] = (Transform[1][0] * params[2].value.number + + Transform[1][1] * params[3].value.number + + Transform[1][2]) / 72.0f * 1016.0f; + } + + fprintf(stderr, "DEBUG: IW%.0f,%.0f,%.0f,%.0f = [ %.0f %.0f %.0f %.0f ]\n", + params[0].value.number, params[1].value.number, + params[2].value.number, params[3].value.number, + IW1[0], IW1[1], IW2[0], IW2[1]); + } + + + 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] = PageWidth; + PlotSize[1] = PageLength; + } + else + { + PlotSize[0] = PageLength; + PlotSize[1] = PageWidth; + } + 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; + Scaling1[0] = P1[0]; + Scaling1[0] = P1[1]; + Scaling2[0] = P2[0]; + Scaling2[1] = P2[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 = 1; + } + + update_transform(); +} + + +/* + * End of "$Id$". + */ diff --git a/filter/hpgl-input.c b/filter/hpgl-input.c new file mode 100644 index 0000000000..9b4b73ec71 --- /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, "%262143[^\"]\"", 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..dc5998d9f5 --- /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 */ + 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 */ + + + 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); + + PPD = SetCommonOptions(num_options, options, 1); + + PlotSize[0] = PageWidth; + PlotSize[1] = PageLength; + + 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); + + 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..7877c9fbd3 --- /dev/null +++ b/filter/hpgl-prolog.c @@ -0,0 +1,369 @@ +/* + * "$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 */ +{ + 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 */ + float iw1[2], iw2[2]; /* Clipping window */ + int i; /* Looping var */ + ppd_size_t *size; /* Page size */ + ppd_option_t *option; /* Page size option */ + ppd_choice_t *choice; /* Page size choice */ + float width, length; /* Page dimensions */ + int landscape; /* Rotate for landscape orientation? */ + + + /* + * Write the page header as needed... + */ + + if (!PageDirty) + { + PageDirty = 1; + PageCount ++; + + printf("%%%%Page: %d %d\n", PageCount, PageCount); + + if (PPD != NULL && !FitPlot) + { + /* + * Set the page size for this page... + */ + + if (Rotation == 0 || Rotation == 180) + { + width = PlotSize[0]; + length = PlotSize[1]; + } + else + { + width = PlotSize[1]; + length = PlotSize[0]; + } + + landscape = 0; + + /* + * Lookup the closest PageSize and set it... + */ + + for (i = PPD->num_sizes, size = PPD->sizes; i > 0; i --, size ++) + if ((fabs(length - size->length) < 36.0 && size->width >= width) || + (fabs(length - size->width) < 36.0 && size->length >= width)) + break; + + if (i == 0 && PPD->variable_sizes) + { + for (i = PPD->num_sizes, size = PPD->sizes; i > 0; i --, size ++) + if (strcasecmp(size->name, "custom") == 0) + break; + } + + if (i > 0) + { + /* + * Found a matching size... + */ + + option = ppdFindOption(PPD, "PageSize"); + choice = ppdFindChoice(option, size->name); + + puts("%%BeginPageSetup"); + printf("%%%%BeginFeature: PageSize %s\n", size->name); + + if (strcasecmp(size->name, "custom") == 0) + { + PageLeft = PPD->custom_margins[0]; + PageRight = width - PPD->custom_margins[2]; + PageWidth = width; + PageBottom = PPD->custom_margins[1]; + PageTop = length - PPD->custom_margins[3]; + PageLength = length; + + printf("%.0f %.0f 0 0 0\n", width, length); + + if (choice->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... + */ + + puts("pop pop pop"); + puts("<>setpagedevice\n"); + } + else + { + /* + * Use the vendor-supplied command... + */ + + printf("%s\n", choice->code); + } + } + else + { + if (choice->code) + printf("%s\n", choice->code); + + if (fabs(length - size->width) < 36.0) + { + /* + * Do landscape orientation... + */ + + PageLeft = size->bottom; + PageRight = size->top; + PageWidth = size->length; + PageBottom = size->left; + PageTop = size->right; + PageLength = size->width; + + landscape = 1; + } + else + { + /* + * Do portrait orientation... + */ + + PageLeft = size->left; + PageRight = size->right; + PageWidth = size->width; + PageBottom = size->bottom; + PageTop = size->top; + PageLength = size->length; + } + } + + puts("%%EndFeature"); + puts("%%EndSetup"); + } + } + + printf("/PenScaling %.3f def\n", PenScaling); + + printf("/SA {\n" + " /%s%s%s%s findfont\n" + " [ %f %f %f %f 0.0 0.0 ] makefont\n" + " setfont\n" + "} bind def\n", + AlternateFont.typeface == 48 ? "Courier" : "Helvetica", + (AlternateFont.weight != 0 || AlternateFont.posture != 0) ? "-" : "", + AlternateFont.weight != 0 ? "Bold" : "", + AlternateFont.posture != 0 ? "Oblique" : "", + AlternateFont.x * AlternateFont.height, + -AlternateFont.y * AlternateFont.height, + AlternateFont.y * AlternateFont.height, + AlternateFont.x * AlternateFont.height); + + printf("/SS {\n" + " /%s%s%s%s findfont\n" + " [ %f %f %f %f 0.0 0.0 ] makefont\n" + " setfont\n" + "} bind def\n", + StandardFont.typeface == 48 ? "Courier" : "Helvetica", + (StandardFont.weight != 0 || StandardFont.posture != 0) ? "-" : "", + StandardFont.weight != 0 ? "Bold" : "", + StandardFont.posture != 0 ? "Oblique" : "", + StandardFont.x * StandardFont.height, + -StandardFont.y * StandardFont.height, + StandardFont.y * StandardFont.height, + StandardFont.x * StandardFont.height); + + if (CharFont) + puts("SA"); + else + puts("SS"); + + printf("%.1f setmiterlimit\n", MiterLimit); + printf("%d setlinecap\n", LineCap); + printf("%d setlinejoin\n", LineJoin); + + printf("%.3f %.3f %.3f %.2f SP\n", Pens[1].rgb[0], Pens[1].rgb[1], + Pens[1].rgb[2], Pens[1].width * PenScaling); + + puts("gsave"); + + if (Duplex && (PageCount & 1) == 0) + switch ((PageRotation / 90 + landscape) & 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 + landscape) & 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; + } + + if (IW1[0] != IW2[0] && IW1[1] != IW2[1]) + { + iw1[0] = IW1[0] * 72.0f / 1016.0f; + iw1[1] = IW1[1] * 72.0f / 1016.0f; + iw2[0] = IW2[0] * 72.0f / 1016.0f; + iw2[1] = IW2[1] * 72.0f / 1016.0f; + + printf("initclip MP %.3f %.3f MO %.3f %.3f LI %.3f %.3f LI %.3f %.3f LI CP clip\n", + iw1[0], iw1[1], iw1[0], iw2[1], iw2[0], iw2[1], iw2[0], iw1[1]); + } + } + + /* + * 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..7518e25aa6 --- /dev/null +++ b/filter/hpgl-vector.c @@ -0,0 +1,707 @@ +/* + * "$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 ++; + PenNumber = (int)decode_number(&s, base_bits, 1.0); + if (PageDirty) + printf("%.3f %.3f %.3f %.2f SP\n", Pens[PenNumber].rgb[0], + Pens[PenNumber].rgb[PenNumber], Pens[PenNumber].rgb[2], + Pens[PenNumber].width * PenScaling); + 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..4071c63cbb --- /dev/null +++ b/filter/hpgltops.h @@ -0,0 +1,232 @@ +/* + * "$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 + + +/* + * Font information... + */ + +typedef struct +{ + int typeface, /* Typeface number */ + posture, /* Posture number */ + weight; /* Weight number */ + float height; /* Height/size of font */ + float x, y; /* X and Y direction/scaling */ +} font_t; + + +/* + * Pen information... + */ + +typedef struct +{ + float rgb[3]; /* Pen color */ + float width; /* Pen width */ +} pen_t; + + +/* + * 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 ppd_file_t *PPD VALUE(NULL); /* PPD file */ + +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 font_t StandardFont, /* Standard font */ + AlternateFont; /* Alternate font */ +VAR float PenPosition[2] VALUE2(0.0f, 0.0f), + /* Current pen position */ + PenScaling VALUE(1.0f), /* Pen width scaling factor */ + PenWidth VALUE(1.0f); /* Default pen width */ +VAR pen_t Pens[1024]; /* State of each pen */ +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_ */ +; + +VAR int LineCap VALUE(0); /* Line capping */ +VAR int LineJoin VALUE(0); /* Line joining */ +VAR float MiterLimit VALUE(3.0f); /* Miter limit at joints */ + + +/* + * 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); +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..9da8ad7385 --- /dev/null +++ b/filter/image-colorspace.c @@ -0,0 +1,883 @@ +/* + * "$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(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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 */ + km, /* Maximum K value */ + diff; /* Color differences */ + 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)); + + if ((km = max(c, max(m, y))) > k) + k = k * k / km; + + c -= k; + m -= k; + y -= k; + + 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++ = ImageDensity[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 ((km = max(c, max(m, y))) > k) + k = k * k / km; + + c -= k; + m -= k; + y -= k; + + *out++ = c; + *out++ = m; + *out++ = y; + *out++ = k; + + count --; + } +} + + +/* + * 'ImageRGBToWhite()' - Convert RGB colors to luminance. + */ + +void +ImageRGBToWhite(const 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(const 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, /* IO - Input/output pixels */ + int count, /* I - Number of pixels/bytes to adjust */ + const 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, /* IO - 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..26f3185e28 --- /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) */ + const 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 /* O - -1 on error, 0 on success */ +gif_read_cmap(FILE *fp, /* I - File to read from */ + int ncolors, /* I - Number of colors in file */ + gif_cmap_t cmap, /* O - Colormap information */ + int *gray) /* IO - Is the image grayscale? */ +{ + int i; /* Looping var */ + + + /* + * 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..31b0289599 --- /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) */ + const 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..57f1ee0008 --- /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) */ + const 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..98626ac2e2 --- /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) */ + const 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..11af3bd918 --- /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) */ + const 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..cf840c5337 --- /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) */ + const 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..1e7bb5bc46 --- /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) */ + const 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..12faf3f0a4 --- /dev/null +++ b/filter/image-tiff.c @@ -0,0 +1,1620 @@ +/* + * "$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) */ + const 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... + */ + + lseek(fileno(fp), 0, SEEK_SET); /* Work around "feature" in some stdio's */ + + 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 = 128; + img->yppi = 128; + } + } + + /* + * 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..3563203e01 --- /dev/null +++ b/filter/image.c @@ -0,0 +1,779 @@ +/* + * "$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 */ + const 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 */ + + + /* + * Wipe the tile cache file (if any)... + */ + + if (img->cachefile != NULL) + { + fprintf(stderr, "DEBUG: Closing and removing swap file \"%s\"...\n", + img->cachename); + + fclose(img->cachefile); + unlink(img->cachename); + } + + /* + * Free the image cache... + */ + + fputs("DEBUG: Freeing memory...\n", stderr); + + for (current = img->first; current != NULL; current = next) + { + fprintf(stderr, "DEBUG: Freeing cache (%08lx, next = %08lx)...\n", + current, next); + + next = current->next; + free(current); + } + + /* + * Free the rest of memory... + */ + + if (img->tiles != NULL) + { + fprintf(stderr, "DEBUG: Freeing tiles (%08lx)...\n", img->tiles[0]); + + free(img->tiles[0]); + + fprintf(stderr, "DEBUG: Freeing tile pointers (%08lx)...\n", img->tiles); + + 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 or the RIP_CACHE environment variable. + */ + +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%254s", &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; + + fprintf(stderr, "DEBUG: max_ics=%d...\n", img->max_ics); +} + + +/* + * '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 */ + float m; /* Current matrix value */ + int *im; /* Pointer into ImageMatrix */ + + ImageHaveProfile = 1; + + for (i = 0, im = ImageMatrix[0][0]; i < 3; i ++) + for (j = 0; j < 3; j ++) + for (k = 0, m = matrix[i][j]; k < 256; k ++) + *im++ = (int)(k * m + 0.5); + + for (k = 0, im = ImageDensity; k < 256; k ++) + *im++ = 255.0 * d * pow((float)k / 255.0, g) + 0.5; +} + + +/* + * 'ImageGetCol()' - Get a column of pixels from an image. + */ + +int /* O - -1 on error, 0 on success */ +ImageGetCol(image_t *img, /* I - Image */ + int x, /* I - Column */ + int y, /* I - Start row */ + int height, /* I - Column height */ + ib_t *pixels) /* O - Pixel data */ +{ + int bpp, /* Bytes per pixel */ + twidth, /* Tile width */ + count; /* Number of pixels to get */ + const ib_t *ib; /* Pointer into tile */ + + + 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 /* O - -1 on error, 0 on success */ +ImageGetRow(image_t *img, /* I - Image */ + int x, /* I - Start column */ + int y, /* I - Row */ + int width, /* I - Width of row */ + ib_t *pixels) /* O - Pixel data */ +{ + int bpp, /* Bytes per pixel */ + count; /* Number of pixels to get */ + const ib_t *ib; /* Pointer to pixels */ + + + 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 /* O - -1 on error, 0 on success */ +ImagePutCol(image_t *img, /* I - Image */ + int x, /* I - Column */ + int y, /* I - Start row */ + int height, /* I - Column height */ + const ib_t *pixels) /* I - Pixels to put */ +{ + int bpp, /* Bytes per pixel */ + twidth, /* Width of tile */ + count; /* Number of pixels to put */ + int tilex, /* Column within tile */ + tiley; /* Row within tile */ + ib_t *ib; /* Pointer to pixels in tile */ + + + 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 /* O - -1 on error, 0 on success */ +ImagePutRow(image_t *img, /* I - Image */ + int x, /* I - Start column */ + int y, /* I - Row */ + int width, /* I - Row width */ + const ib_t *pixels) /* I - Pixel data */ +{ + int bpp, /* Bytes per pixel */ + count; /* Number of pixels to put */ + int tilex, /* Column within tile */ + tiley; /* Row within tile */ + ib_t *ib; /* Pointer to pixels in tile */ + + + 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 * /* O - Pointer to tile or NULL */ +get_tile(image_t *img, /* I - Image */ + int x, /* I - Column in image */ + int y) /* I - Row in image */ +{ + int bpp, /* Bytes per pixel */ + tilex, /* Column within tile */ + tiley, /* Row within tile */ + xtiles, /* Number of tiles horizontally */ + ytiles; /* Number of tiles vertically */ + ic_t *ic; /* Cache pointer */ + itile_t *tile; /* Tile pointer */ + + + if (x >= img->xsize || y >= img->ysize) + { + fprintf(stderr, "ERROR: Internal image RIP error - %d,%d is outside of %dx%d\n", + x, y, img->xsize, img->ysize); + return (NULL); + } + + if (img->tiles == NULL) + { + xtiles = (img->xsize + TILE_SIZE - 1) / TILE_SIZE; + ytiles = (img->ysize + TILE_SIZE - 1) / TILE_SIZE; + + fprintf(stderr, "DEBUG: Creating tile array (%dx%d)\n", xtiles, ytiles); + + 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) + { + ic = calloc(sizeof(ic_t) + bpp * TILE_SIZE * TILE_SIZE, 1); + ic->pixels = ((ib_t *)ic) + sizeof(ic_t); + + img->num_ics ++; + + fprintf(stderr, "DEBUG: Allocated cache tile %d (%08lx)...\n", + img->num_ics, ic); + } + else + { + fprintf(stderr, "DEBUG: Flushing old cache tile (%08lx)...\n", + img->first); + + flush_tile(img); + ic = img->first; + } + + ic->tile = tile; + tile->ic = ic; + + if (tile->pos >= 0) + { + fprintf(stderr, "DEBUG: Loading cache tile from file position %d...\n", + tile->pos); + + 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 + { + fputs("DEBUG: Clearing cache tile...\n", stderr); + + memset(ic->pixels, 0, bpp * TILE_SIZE * TILE_SIZE); + } + } + + if (ic == img->first) + { + if (ic->next != NULL) + ic->next->prev = NULL; + + img->first = ic->next; + ic->next = NULL; + ic->prev = NULL; + } + else if (img->first == NULL) + img->first = ic; + + if (ic != img->last) + { + /* + * Remove the cache entry from the list... + */ + + if (ic->prev != NULL) + ic->prev->next = ic->next; + if (ic->next != NULL) + ic->next->prev = ic->prev; + + /* + * And add it to the end... + */ + + 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) /* I - Image */ +{ + int bpp; /* Bytes per pixel */ + itile_t *tile; /* Pointer to tile */ + + + + bpp = ImageGetDepth(img); + tile = img->first->tile; + + if (!tile->dirty) + { + tile->ic = NULL; + return; + } + + if (img->cachefile == NULL) + { + cupsTempFile(img->cachename, sizeof(img->cachename)); + + fprintf(stderr, "DEBUG: Creating swap file \"%s\"...\n", img->cachename); + + if ((img->cachefile = fopen(img->cachename, "wb+")) == NULL) + { + perror("ERROR: Unable to create image swap file"); + tile->ic = NULL; + tile->dirty = 0; + return; + } + } + + if (tile->pos >= 0) + { + if (ftell(img->cachefile) != tile->pos) + if (fseek(img->cachefile, tile->pos, SEEK_SET)) + { + perror("ERROR: Unable to seek in swap file"); + tile->ic = NULL; + tile->dirty = 0; + return; + } + } + else + { + if (fseek(img->cachefile, 0, SEEK_END)) + { + perror("ERROR: Unable to append to swap file"); + tile->ic = NULL; + tile->dirty = 0; + return; + } + + tile->pos = ftell(img->cachefile); + } + + + if (fwrite(tile->ic->pixels, bpp, TILE_SIZE * TILE_SIZE, img->cachefile) < 1) + perror("ERROR: Unable to write tile to swap file"); + else + fprintf(stderr, "DEBUG: Wrote tile at position %d...\n", tile->pos); + + 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..b4969e48a9 --- /dev/null +++ b/filter/image.h @@ -0,0 +1,225 @@ +/* + * "$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, const 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, const ib_t *pixels); +extern int ImagePutRow(image_t *img, int x, int y, int width, const ib_t *pixels); + +/* + * File formats... + */ + +extern int ImageReadGIF(image_t *img, FILE *fp, int primary, int secondary, + int saturation, int hue, const ib_t *lut); +extern int ImageReadJPEG(image_t *img, FILE *fp, int primary, int secondary, + int saturation, int hue, const ib_t *lut); +extern int ImageReadPNG(image_t *img, FILE *fp, int primary, int secondary, + int saturation, int hue, const ib_t *lut); +extern int ImageReadPNM(image_t *img, FILE *fp, int primary, int secondary, + int saturation, int hue, const ib_t *lut); +extern int ImageReadPhotoCD(image_t *img, FILE *fp, int primary, + int secondary, int saturation, int hue, + const ib_t *lut); +extern int ImageReadSGI(image_t *img, FILE *fp, int primary, int secondary, + int saturation, int hue, const ib_t *lut); +extern int ImageReadSunRaster(image_t *img, FILE *fp, int primary, + int secondary, int saturation, int hue, + const ib_t *lut); +extern int ImageReadTIFF(image_t *img, FILE *fp, int primary, int secondary, + int saturation, int hue, const ib_t *lut); + +/* + * Colorspace conversions... + */ + +extern void ImageWhiteToWhite(const ib_t *in, ib_t *out, int count); +extern void ImageWhiteToRGB(const ib_t *in, ib_t *out, int count); +extern void ImageWhiteToBlack(const ib_t *in, ib_t *out, int count); +extern void ImageWhiteToCMY(const ib_t *in, ib_t *out, int count); +extern void ImageWhiteToCMYK(const ib_t *in, ib_t *out, int count); + +extern void ImageRGBToWhite(const ib_t *in, ib_t *out, int count); +extern void ImageRGBToRGB(const ib_t *in, ib_t *out, int count); +extern void ImageRGBToBlack(const ib_t *in, ib_t *out, int count); +extern void ImageRGBToCMY(const ib_t *in, ib_t *out, int count); +extern void ImageRGBToCMYK(const 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, const 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..ab9de3e3e8 --- /dev/null +++ b/filter/imagetops.c @@ -0,0 +1,568 @@ +/* + * "$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, + xsize2, + ysize2; + 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 = strcasecmp(val, "separate-documents-collated-copies") != 0; + } + + if ((val = cupsGetOption("Collate", num_options, options)) != NULL && + strcasecmp(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... + */ + + if (zoom == 0.0 && ppi == 0) + ppi = img->xppi; + + xprint = (PageRight - PageLeft) / 72.0; + yprint = (PageTop - PageBottom) / 72.0; + + 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; + + /* + * Rotate the image if it will fit landscape but not portrait... + */ + + if ((xinches > xprint || yinches > yprint) && + xinches <= yprint && yinches <= xprint) + { + /* + * Rotate the image as needed... + */ + + Orientation = (Orientation + 1) & 3; + xsize = yprint; + yprint = xprint; + xprint = xsize; + + xsize = PageLeft; + PageLeft = PageBottom; + PageBottom = PageWidth - PageRight; + PageRight = PageTop; + PageTop = PageLength - xsize; + + xsize = PageWidth; + PageWidth = PageLength; + PageLength = xsize; + } + } + 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; + } + + xsize2 = yprint * zoom; + ysize2 = xsize2 * img->ysize / img->xsize; + + if (ysize2 > (xprint * zoom)) + { + ysize2 = xprint * zoom; + xsize2 = ysize2 * img->xsize / img->ysize; + } + + /* + * Choose the rotation with the largest area, but prefer + * portrait if they are equal... + */ + + if ((xsize * ysize) < (xsize2 * xsize2)) + { + /* + * Do landscape orientation... + */ + + Orientation = 1; + xinches = xsize2; + yinches = ysize2; + xprint = (PageTop - PageBottom) / 72.0; + yprint = (PageRight - PageLeft) / 72.0; + + xsize = PageLeft; + PageLeft = PageBottom; + PageBottom = PageWidth - PageRight; + PageRight = PageTop; + PageTop = PageLength - xsize; + + xsize = PageWidth; + PageWidth = PageLength; + PageLength = xsize; + } + else + { + /* + * Do portrait orientation... + */ + + Orientation = 0; + 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) + { + memset(data + length, 0, 4 - length); + b = (((((data[0] << 8) | data[1]) << 8) | data[2]) << 8) | data[3]; + + 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..c79117a467 --- /dev/null +++ b/filter/imagetoraster.c @@ -0,0 +1,3975 @@ +/* + * "$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, + xsize2, + ysize2; + 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 */ + ppd_profile_t userprofile; /* User-specified 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 = strcasecmp(val, "separate-documents-collated-copies") != 0; + } + + if ((val = cupsGetOption("Collate", num_options, options)) != NULL && + strcasecmp(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, "CutMedia")) != NULL) + exec_choice(&header, choice); + + if ((choice = ppdFindMarkedChoice(ppd, "ESPFinishing")) != 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... + */ + + 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 ((val = cupsGetOption("profile", num_options, options)) != NULL) + { + profile = &userprofile; + sscanf(val, "%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f", + &(userprofile.density), &(userprofile.gamma), + userprofile.matrix[0] + 0, userprofile.matrix[0] + 1, + userprofile.matrix[0] + 2, + userprofile.matrix[1] + 0, userprofile.matrix[1] + 1, + userprofile.matrix[1] + 2, + userprofile.matrix[2] + 0, userprofile.matrix[2] + 1, + userprofile.matrix[2] + 2); + + userprofile.density *= 0.001f; + userprofile.gamma *= 0.001f; + userprofile.matrix[0][0] *= 0.001f; + userprofile.matrix[0][1] *= 0.001f; + userprofile.matrix[0][2] *= 0.001f; + userprofile.matrix[1][0] *= 0.001f; + userprofile.matrix[1][1] *= 0.001f; + userprofile.matrix[1][2] *= 0.001f; + userprofile.matrix[2][0] *= 0.001f; + userprofile.matrix[2][1] *= 0.001f; + userprofile.matrix[2][2] *= 0.001f; + } + else if (ppd != NULL) + { + fprintf(stderr, "DEBUG: Searching for profile \"%s/%s\"...\n", + resolution, media_type); + + for (i = 0, profile = ppd->profiles; i < ppd->num_profiles; i ++, profile ++) + { + fprintf(stderr, "DEBUG: \"%s/%s\" = ", profile->resolution, + profile->media_type); + + if ((strcmp(profile->resolution, resolution) == 0 || + profile->resolution[0] == '-') && + (strcmp(profile->media_type, media_type) == 0 || + profile->media_type[0] == '-')) + { + fputs("MATCH!\n", stderr); + break; + } + else + fputs("no.\n", stderr); + } + + /* + * If we found a color profile, use it! + */ + + if (i >= ppd->num_profiles) + profile = NULL; + } + + if (profile) + 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 (zoom == 0.0 && ppi == 0) + ppi = img->xppi; + + if (ppi > 0) + { + /* + * Scale the image as neccesary to match the desired pixels-per-inch. + */ + + if (Orientation & 1) + { + xprint = (PageTop - PageBottom) / 72.0; + yprint = (PageRight - PageLeft) / 72.0; + } + else + { + xprint = (PageRight - PageLeft) / 72.0; + yprint = (PageTop - PageBottom) / 72.0; + } + + xinches = (float)img->xsize / (float)ppi; + yinches = (float)img->ysize / (float)ppi; + + /* + * Rotate the image if it will fit landscape but not portrait... + */ + + if ((xinches > xprint || yinches > yprint) && + xinches <= yprint && yinches <= xprint) + { + /* + * Rotate the image as needed... + */ + + Orientation = (Orientation + 1) & 3; + xsize = yprint; + yprint = xprint; + xprint = xsize; + } + } + else + { + /* + * Scale percentage of page size... + */ + + xprint = (PageRight - PageLeft) / 72.0; + yprint = (PageTop - PageBottom) / 72.0; + + xsize = xprint * zoom; + ysize = xsize * img->ysize / img->xsize; + + if (ysize > (yprint * zoom)) + { + ysize = yprint * zoom; + xsize = ysize * img->xsize / img->ysize; + } + + xsize2 = yprint * zoom; + ysize2 = xsize2 * img->ysize / img->xsize; + + if (ysize2 > (xprint * zoom)) + { + ysize2 = xprint * zoom; + xsize2 = ysize2 * img->xsize / img->ysize; + } + + /* + * Choose the rotation with the largest area, but prefer + * portrait if they are equal... + */ + + if ((xsize * ysize) < (xsize2 * xsize2)) + { + /* + * Do landscape orientation... + */ + + Orientation = 1; + xinches = xsize2; + yinches = ysize2; + xprint = (PageTop - PageBottom) / 72.0; + yprint = (PageRight - PageLeft) / 72.0; + } + else + { + /* + * Do portrait orientation... + */ + + Orientation = 0; + xinches = xsize; + yinches = ysize; + } + } + + xpages = ceil(xinches / xprint); + ypages = ceil(yinches / yprint); + + /* + * Compute the bitmap size... + */ + + xprint = xinches / xpages; + yprint = yinches / ypages; + + if ((choice = ppdFindMarkedChoice(ppd, "PageSize")) != NULL && + strcasecmp(choice->choice, "Custom") == 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; + } + + header.Margins[0] = PageLeft; + header.Margins[1] = PageBottom; + + switch (Orientation) + { + case 0 : + header.ImagingBoundingBox[0] = PageLeft; + header.ImagingBoundingBox[1] = PageBottom; + header.ImagingBoundingBox[2] = PageLeft + xprint * 72; + header.ImagingBoundingBox[3] = PageBottom + yprint * 72; + break; + case 1 : + header.ImagingBoundingBox[0] = PageRight - yprint * 72; + header.ImagingBoundingBox[1] = PageBottom; + header.ImagingBoundingBox[2] = PageRight; + header.ImagingBoundingBox[3] = PageBottom + xprint * 72; + break; + case 2 : + header.ImagingBoundingBox[0] = PageRight - xprint * 72; + header.ImagingBoundingBox[1] = PageTop - yprint * 72; + header.ImagingBoundingBox[2] = PageRight; + header.ImagingBoundingBox[3] = PageTop; + break; + case 3 : + header.ImagingBoundingBox[0] = PageLeft; + header.ImagingBoundingBox[1] = PageTop - xprint * 72; + header.ImagingBoundingBox[2] = PageLeft + yprint * 72 + 0.5f; + header.ImagingBoundingBox[3] = PageTop; + break; + } + + 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(2 * 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, "CutMedia") == 0) + header->CutMedia = (cups_cut_t)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) + strncpy(header->MediaType, value, sizeof(header->MediaType) - 1); + else if (strcmp(name, "OutputType") == 0) + strncpy(header->OutputType, value, sizeof(header->OutputType) - 1); + } +} + + +/* + * '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 / 3; + + 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..cbeeca1313 --- /dev/null +++ b/filter/pstops.c @@ -0,0 +1,872 @@ +/* + * "$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 */ + int page_count; /* Page count for NUp */ + int subpage; /* Sub-page number */ + int copy; /* Current copy */ + + + 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 = strcasecmp(val, "separate-documents-collated-copies") != 0; + } + + if ((val = cupsGetOption("Collate", num_options, options)) != NULL && + strcasecmp(val, "True") == 0) + Collate = 1; + + if ((val = cupsGetOption("OutputOrder", num_options, options)) != NULL && + strcasecmp(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 - 1)) == 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 (strcmp(line, "%%Trailer") == 0 && level == 0) + break; + 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 - 1); + + if (NumPages & (NUp - 1)) + { + start_nup(NUp - 1); + end_nup(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 - 1)) == 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); + } + + if (NumPages & (NUp - 1)) + { + start_nup(NUp - 1); + end_nup(NUp - 1); + } + + Copies --; + } + } + else + { + page_count = (NumPages + NUp - 1) / NUp; + copy = 0; + + do + { + for (page = page_count - 1; page >= 0; page --) + { + if (ppd == NULL || ppd->num_filters == 0) + fprintf(stderr, "PAGE: %d %d\n", page + 1, + slowcollate ? 1 : Copies); + + if (slowcollate) + printf("%%%%Page: %d %d\n", page + 1, + page_count - page + copy * page_count); + else + printf("%%%%Page: %d %d\n", page + 1, page_count - page); + + ppdEmit(ppd, stdout, PPD_ORDER_PAGE); + + for (subpage = 0, number = page * NUp; + subpage < NUp && number < NumPages; + subpage ++, number ++) + { + start_nup(number); + fseek(temp, Pages[number], SEEK_SET); + copy_bytes(temp, Pages[number + 1] - Pages[number]); + end_nup(number); + } + + if (number & (NUp - 1)) + { + start_nup(NUp - 1); + end_nup(NUp - 1); + } + } + + copy ++; + } + while (copy < Copies && slowcollate); + } + } + + /* + * Copy the trailer, if any... + */ + + while ((nbytes = fread(line, 1, sizeof(line), fp)) > 0) + fwrite(line, 1, nbytes, stdout); + } + 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 (strcasecmp(PageSet, "even") == 0 && (page & 1)) + return (0); + if (strcasecmp(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 (nleft > sizeof(buffer)) + nbytes = sizeof(buffer); + else + nbytes = nleft; + + if ((nbytes = fread(buffer, 1, nbytes, 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("ESPsave restore"); + + 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 */ + float pw, pl; /* Printable width and length of full page */ + + + if (Flip || Orientation || NUp > 1) + puts("/ESPsave save def"); + + if (Flip) + printf("%.0f 0 translate -1 1 scale\n", PageWidth); + + pw = PageRight - PageLeft; + pl = PageTop - PageBottom; + + 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 = pl; + l = w * PageLength / PageWidth; + + if (l > (pw * 0.5)) + { + l = pw * 0.5; + w = l * PageWidth / PageLength; + } + + tx = pw * 0.5 - l; + ty = (pl - w) * 0.5; + } + else + { + l = pw; + w = l * PageWidth / PageLength; + + if (w > (pl * 0.5)) + { + w = pl * 0.5; + l = w * PageLength / PageWidth; + } + + tx = pl * 0.5 - w; + ty = (pw - l) * 0.5; + } + + if (Duplex && (number & 2)) + printf("%.0f %.0f translate\n", PageWidth - PageRight, PageBottom); + else + printf("%.0f %.0f translate\n", PageLeft, PageBottom); + + if (Orientation & 1) + { + printf("0 %.0f translate -90 rotate\n", pl); + printf("%.0f %.0f translate %.3f %.3f scale\n", + ty, tx + l * x, w / pw, l / pl); + } + else + { + printf("%.0f 0 translate 90 rotate\n", pw); + printf("%.0f %.0f translate %.3f %.3f scale\n", + tx + w * x, ty, w / pw, l / pl); + } + + 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 = pw * 0.5; + l = w * PageLength / PageWidth; + + if (l > (pl * 0.5)) + { + l = pl * 0.5; + w = l * PageWidth / PageLength; + } + + if (Duplex && (number & 4)) + printf("%.0f %.0f translate\n", PageWidth - PageRight, PageBottom); + else + printf("%.0f %.0f translate\n", PageLeft, PageBottom); + + printf("%.0f %.0f translate %.3f %.3f scale\n", x * w, y * l, + 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; + } +} + + +/* + * 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..78372c2f41 --- /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%63s", &unicode, glyph) == 2) + Glyphs[unicode] = strdup(glyph); + + fclose(fp); + } + + if (strncmp(charset, "iso-", 4) == 0) + { + memset(chars, 0, sizeof(chars)); + + snprintf(filename, sizeof(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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 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 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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 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 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 zc-oY>Wmr{R7cPu+H;8mg!=}4Kkdg*z*ubV^)6&w7N;e|iB_JT(-CZJ`f;4;^-{*aW z=bRts`vKRr?lI!?CjkgLFN`< za&;9=a#cGsu&a?Hkm(Wr;7D%l{$Pjr|G#;u0)gaU3m~}}$Qnp4p`@%Wt0+TGC!?rN zE(5d$IvQD%D?1xogG|WfK_)<3Cm=n!nVloK^?x47P3&w z4zfjNeMnc<*36C^!1f>9)Y<;OHW#3y6J!xN-9O3GlS5KBwX?N$CpQI}A+svlfgvv- zr~7|M;onRDI??_AD%ii{NIP3wD;n8ANc^{3ceYYyoL8w=ZiK#-F($PH+!3<8^2keeA)0PvWDE= z8SM3ESdkwlkAt0@)ydunGF1@#KL`goD`bVWkuh8E zFtp~je_`&2^&lrO&=w4O?9M~ZY7caTd?4Vz7%w@ik&XRBTuANzhw?!wJN*S9shQZ>*ckmq zAZgivY#;k@|6vZY`%94%l8lqJk<+8dkW@T?j&^?mNEUXsf9uKxNdWBn*Ukl@4z_Rv zKJtLDHnVef{0l(XnnB9`7l5#Jf{e)jo*`VFfG)tl)#rMs{*zj8L8#h-9uwhxNZH!% z(V~Zf18qQ0QEmuf>xa+de*lCr(82jpPq`tC%^&0$_?I*{gtUV*(CN=-_doDYnQhG- zogcTK8$w^q+TP-C@wp-N#ev{Q0EE4S1?cZHguEos`mqOuyp+8Y=rMI32zBL0t9T&H zWsDwonFqpL>QNLP2y0op#{lO;dmvN*e<29n*GBgCkDMTM<&A8NO&>uJ!V1oRA0d1d zA3Z|IDnSbE_=qg;1KGb^c_CcYEFRZ@7s6G=;_u|}Lb$4e%pYaL3n8m!^!GKq5T@$? zstGUm!|Xs-{Y{9M=Yb8-{81nXU9Cr4Aas?T{ysy*j8*3`H9iPgV@D$sD!A>p^-TitS|bBoZVUM!2enJ?Mk;$XU0I)$)GJP^o5V?lT`M;_MV1s02|70N~8S^JI1z>}u z0elh(!X9Mz1mXS@2Ji@hkhXd_z?oBpee}6#_rK(2zbyp3!stXqkJCZ4YFyQKH~VGaFG4q&ehoN(RK%Tkhwqb z)5<-l-5(h8@E7F#2mDv{9%SziZffWHi2j52nF7rpZ(x82@q5@_pYET42N84vnmkGC zK?(oaI{sDH2R*cLwg!XjtshnJK^E;D?d=8)=uogE*Q{XtnFjO-sZ`9W4?A(LnY zesp#KJZP%Q|A|6!bp?VTdJ1+ldbGC#9u(CC`EA+G>F{WjPiv=(xXd;bhhO#w z9k;eKfAECl_6Xt??!r^k zpX&)^<9|Bb9FH$3;72KP03I10edg>O?2in_k2rI1JULZ83C8)v^dubD6VsD`+>bWU zC*gP=8Ein0djD`W`@7^xFus2*k6-?95&Kj9e>L&pCiWl(=8li2^WhryU-U7ZhuheH z@h8!_{^F0R{JEL^@A~&763=7HlUTfuEl;BHJw2X2j`whTdu)3gkqhwD_BiIlo$l|E z9`X}7ei@&-p2y)4im4sX?A*#UfpWil2oE;%~f&cuh1UX9o_xaCn zSdeZ3O^|(|xhhcgG3r_Hh?q^?X6dK10Wgdq&13!?#iEw2F&nV$4buU2>h2O*ik< zp)cEiZD=zJkbf8#Ou5=0n@A5WY{+L{6M<)m%~ocAlSW|SXDeB~0(SibCFIUVpJq$S z@b(T(Td&s}7b$eeZ)W;J9_!kzii})V@?M6-IodnrDs*3Z_u_DY4&nEfrRfZ`_D4g4wXE zu)HX<0)s=SUM2aVm8n%~G z?=g}YUH_z*!)rY>DZGU(CONpL9(WPY6R$7jUY7pmgp~G$u^%=N8bfqJ@_v{gZLf3h zz0Jwe)`|#zkQwIbmBBX5mKmF5k!yGyc z4i@eaoD_XfC?+|~eBXFl@USWu=(mphGAORG7AI1+k9!K4bxh?rJC0cQTWCMmNcCE% zf6zboWVs$OIUVC$JxsbFt0yFGt%8d65x)p%%r=C-)%4ue!AsJT;xXIZ28s9KNxtGC zEMvuE7YXpHo6=mP*$g7n|9z~27E(%!41cp*k+``q_3q?HDnfNr(GqOQGf9BDqL$X( z*Ur+JlJ&%IMAD;8#8+S6BUGFJfIGy;NH=`<@zB@ehn||)a#m?NR9)uV`n^PBu(T2^ zY+do*Wudx_)g>if82oBqJgpQ71B!M9znGCLN;6mR5x@Ouu~i;sn9z4+><_tD!8lj6 z>+rf-dXpL-gCl14?&ss2oPIPO2hgg%M2JKn62Ifb95#~`y}DhCwjNA|UR9$DdPm)` z5a|!!o#6BKMtV-}UPpQ05Sh007GBZSVk-RQ9ObFJg*_JCzLmYB@cXlOy?rjvKVwmA zYg;4M-8Y7*ChNEb1gL~}*3tx6e?0N4XgG;M+!Dd~99&1$RAowPo`nq0pss7VIfO-a zyxXRn)~aW1oahh_l|)mmgJhR|XEm273-2*DeQEU4!rDM~La29CO(!zs*_le6PChuT z!v+_y@wOL7bV@a0+U#X}3+xL998;r8ZxRrGh6EV4v=tWBIN+|dH`F?MIYe^?zqzE1 z@#|6dQFZ*B0L$B}@x;GE&Xedfpy(NP@$11Lhp;W^s zp^F*_BjA7NbVg0uTDYD-UHILo@FrT-|3cpHclvVQ;jw6k=_DuWdJqXyzb!77!?6-I z$L!&Iw^}CDt0i{>R6-SkMO>Q<0~G%RYzxgzMtxjXez9{TE7!oO_IX)`(9t7JSo!r% z&Z)LM_TI-6InFatc^~%-;or2M-2}g<1i71l^a~Sm9cmE-<-S&!8Fx;LIe1{o3%FAQ z$45GTz?{8DyVKWUd}}P2e%%j8(2M0e*LY9?#zJz`(3Vf}@f9oVJd9C#8DJylQ)kN{ z@=@?3cQ!K$Z873`MyG&w1FPZh_ zvVsy>W#(kEicW|5yWGv)%3~uaV_=XIwdnbtWxfRLY{Z-Brb;Y&o}1|zU^}M^=pL&9 z9bHixzDe$EQLiPsAg2qJMhb#Tn!b=!4!f8Ezfy!QI0iYQR`te&GzjY_O(a*0a-MNE z%{6x_1x@Q>uR7^+BfalPnru6Dn0f~@ZE&<(7W>JZr}xutjzthoAnwE`1(r5$IPdJl zV#(OmK_!mp37QdPYYNbEiV(b-=c)hlr?xq|eVLl(vS!lq>)-5`ticqvm54@wN=@)N zr{4PEdqa~Wq4}s=Dn1a`{FZjvxVkA z06)>B<-TDY)UROJySnJO*+<1A6R_uAb6Za4pSBKQ7Bec7zd&=@Jilxa-+7L4LTGb# z*~zJ`*T)*lPT7HfqJJui1{cMmTol z;>hvmVCb~3&Gq(AhPXoldCyNT+p^^XYpCAnw`zq5L{#Z1*@q5vF6V|F#ZiLU!#$=M zF4+{k-;?wIpk2`5+-vd?oeXwO2zQSNjV~d5zeD7aL^8vksu{ZI-t9R;V`Ifap9$E& zA}~dw?ebx+B0CRS13o>$JUK@ z`y70K5tMxx(YLCh#5~|P@jNI=M(fO>jK8K*a3s1YJ`u|Y?u`1gWr8OC&VJJiwWC|8 zD~n~Ta+X$UaFcs{T3~`4)hs{gni`eF@i{s>h4sr<{%k9Q8KkE}NSJnbt_8x_-;F#6 zJj77UoOsyr=6CTsjAu|6ciTpN@_Sy0aH+(&&FD zw2A55tjdV9M0HsmhEA%7BlvyCC!@H^zpD#QGRWjhiPDn#+z!>Uemp6p7V52sE9(=Y zoH^l0Gx^IRQvlVM^Fz5ggXaZl=`_XB z;lwkQ%?Y0u<8@v15pi|)C^?9kcTz6z9GUcRa9*^PhXZ*tQpsN=(kbyos%>n`wWutn zJ|7Hl_$5GAIO;~s8fhrLgVLU;OJmzuUZG#0eT~i(VDwC>FjG<3Q5F8VS14x4j$FfZ zge%wi{Pl&u6+cZV?RR;}=+A|x1cx%kqcqAt-_b0_y)isZHBgY`w4e_BJ^QMb;wVDEX(Ncb1p~bVYj7$)oo>R zLzzyqW)n18*dl6%_K3c_Z}H4`I#Cx@yPsbLxcjWhq@ic4cp4joy?U)#-8XKjJz3R4 z=n3CA{sP*%WMYj!Bg6!%i&z!eS za)*c28>HL|=dQvFd}f;AunJ<&4B@)w@!K5E^A!Rq@%3n(81E$I@uJ&agxFa~!;?LC zDL06@e#5=6tnOB=*8RehU?4`oQMOk7Sx!U-YoSqLGwNI_+VW9)Sz%-s6kkJraLCey z>DF@*YjdHs6y)FY$80;vpE9Oo4oGV5?-R$3svPi^iivNBk&XR6?F8$gPTfzcBCN)5 z5KByALo>Rxp1J{@ft5zr3-lw#7KqApzYk&X79$y88o{xLfl$9jH#t9$hzzr`w{o%J zy`lp3UxFJI;+QH3)ix(t;t2cDb z->D;=Jrc0mnvk+u-W^r80?H69VL}#>T}T23+G}Ked_&CMdR1W1Am?AjDIKYlO^R% zOZu$9pGba^*LuTC1|S#}UceS1bYxcUDoKXCSi(=p(w>}~%_>oItPCpm3jSHYAf18u zgVK^YlA|kFjHup)%g573d<;Nt4N8TsAe;G^2@CWrDxTPu9LPmgr?iR@%0Yft(`6BWULJ3KNfi6=l5f4UehShychjI%EOlDN@?F;WhGom zM!PmQ6Zjq_nR==aQTTm&YYkYGdE`tl5q=$YH;QzKe>bpVJn|xWJbb!b-tx#sqRPPG zNG)nZg;Jrgc7FG}o+~)clsizJN@!u&*JJ&xXX{1t8cYFGO8Y`ow3v%`TLsU%Job&_ z-y|dJ&v(nhgx{Ey4hcnnGOJ2=Wv}}UIMfV$sa~X;_saSBkwlgI zM^aL#CycAN(?PFW>$eS{!}1!|)G{i@$bBMo6S#Y!5t#jr=O_ZTtZ?`Q@o?FpUaL`9 zn*W{M=A10_)Qu&Y?H3e==<+?s4TgD2k}s3)7<$5u+~Kla)2;|GD^PXK{gF-V``8nX zJes2UxWo3wK zA`zsyKHi4yUZC*5oHt9M*>s8N<`p#)=WL8Jg#IwHk7*=visggm8JTaO+y4Rq_-f5H z<1`%0d(q#lW_oN9A)F|P(g znWX|h;v9O~q?-aw5tVxL&D)cZ%8%^;DS2}Juke21F5gdGQx;BEnFEzM#=jtrn@)_v zNP5~)36kX#Wv0)Yq9}yXv`w*vOr&8n+|b6Nc|>J7h+pB{RFJIR#UR-Y7e{>l?f4w? z$7rU&a``*q=zjBT)ObF(WatqsXe+Y@?W6gFHBec9i#u$9E?M&rs_?@xAiDw#J ze9Ro`Dgb4CJHW>>x+J^mjb|#_M@9C=D#e$}Z?$lN|HT0kh+1Ocd`)WR*|C z6+NCFOG#E~#<~6C6*B|5PR}XnKSr^73Jt92?cvp2bcx!%)H~F>PsU(xLvfHK@I2P* zgIiA?qu<01Opu4Krc6$nX7ObOBP`9J23GK-sGHETL?@^<*5frf>8F82?XX7Q^T^gz zW?6Gbon=5LxabK7@^#Z}X}`2yrHXCuT;Bb*a;dw`KRl{+MPpDk?5@B+*ru_P#$E5r z;-R3OmoM1>y~Ei7`q2`UG8=h4UqBJJ1RTI(_p-v*X_hW>EBwN;?_8LFNYu~9&j9Nu4z0j1)o=(ma+bR&707nZ--j=E+ zMMXq2XT$leAbdK(wTG<&bdX2Y)<`+vAafv4!^SJoVJNw39v-A`8e_tN(R z4x+3HK4eJ?#+NOkU??%nqm(3&G=AFAzv5sner+yNs+K$+5h|?t<8?;*1Uxz>azQ`C zurcIZFJDDPdw|*%d`{Run2{1%cCn(4gh4;;pA}3S5HpEvXJf`kmpyx+j+;iNYL+`I zb3}nE1SOlZi>PvrxMBBIIi&iRuC_=KV;FB33+fQ+s3**aZ~R&8iB--uguowE@B-p+ zZvluqpP7ANHc*7VY_8*(aO34?wwE{j!eIqS(^l7TlOFX*#;}cg#WIFnsOdLEFXdVd zqRAg3yux|qx8)q9f3>|qmo$73Gpy{2qa+|l%Pn_Q!xObLCG!k_-5Wjlq{mC^s)L$Q zMJd_4r(`tq)jj~=Y%^cl3kGck8&<>a?kE71f8SI`sIqu1Dpt!EpR(-no(AOGaL_rx zU8!4vspR6({EY57;8vpMNZIEALSm{yvU~*&{0GmIPJ^gRb8sBYE)i~$ESbmfe;0$t z^qY943R1ea*`Ik~F~+UlP)+PGC@KVH#V48S9;5qwv$SVtUaUHM(H6OxGhmY{PK_ru zi!h=N64LBSqQ;)Rx-a85lJUWkCx>&bi~Kss3>dYx8~OmAw#lOM zP$C%SdOMe$YI0GAHLAgu)Pfk(DBf$qL7>HJ8U)Yo4$kg&U&%cz`6O0_#Sv{?oh}DD zD@$%KbStgnMHx0d8!h}A>*RISx8xH^ z+f+1o*Or0{!|h69p~@&T#Q+vk!#8iLI3;}&)-Ns2>N5)Cgl+jj%iquPUsHIF)ZGd9 z4%Xe7`o7kL565QOiS40i+fl#_{pb(fZ(!9DV*q@EMS8jS`dw6|d5c8Y0t+(>eo`Is z0PM>9_DuQhA(kXDcY~=2p8`HpW_TCUS#BVq|2CG!^$|?L*<9T4rx- zFxxG#I1Z0?3BW;KTlPH$Iu0%(tH+2*MCu1*J6{m;AthZIu$aC$RTgr5KOAp7yeJ>O zTcj#qg@8}08bT|5X~v}+C#tczi|?bhitKs6Z!6VcBclkiZEhW5OK3sr){9Gj>e$FF56D5eCNgR867@WldfF znvMvL;qbDN(Kt#J(LHwhWj}`M5Rr5Pra&t_C!z~n6v1GoS^;$vf zaDJ~)rYb(gNkq4tLqe{J9(!5NOJ(zBaH?qCy<5?@D+9QR6p{2p5d>C)${iKs?bXMY z5L&Jly~TiAE}{4e)17@qftdT*@%$@cP1VO2uh6w~&cQ#F!Y4CKAP8-N@)0=n9_?%tWw|^Qc^x^MpDecEM)jsry){pm zpPaK^si1Qqu{D=?h`~}U56(}S1WPe0?Zpm{j7eiwq2J~72CB|dE?~`eYJGIK0x!&G zo!$6`rhtfdJ>T)9iKH_piRI(B8UqJq^WE^7#xuU3NAC|A`9~Je7e>V#Kj%yHd)2}1 zBxtK20JW~V3i>Ds2AP#{=P_7;#Q9Px{CpotHF^@s_@MYo7IC*mzj@`d^KZ9}2E1A- zz1q8V)#iUyyh$#kRReSkb#Az8XcubsyVXsOr3nrE!O|xF+t(-b7LzQi#uP~xrCD90 zkBH`kUNeJbij_o7K{NIix>NP*4qq5!QDCJx>Srdt@O_LQ{o{I{HTUv|TV8zjlcuf$ zd_c%B_TgrTNDTSPU%Vj9NF=k;9PK;XA;x<^@W#O@@wDl)LkIhX2Q&6Fm{t;PGQ*=_ zg{|L`J~BsJ3K`O1p3ULa{%07hzjxZ&ap)bju={*aa(~akwuzl?PS|ksmlE!4qy)WE zJfi+k-tV(>lfte?@0qJlc#1)HB!?)O&UD+ z-tG?T6PS(-TWSn2U1Jdai1Z$w7hDM-ChP4!Z7+s8bx+{l;B^ps_a18(OL#h63QoPa zdVLM9-`XsuH75~GU)BlZLDnBp+CwY{!arv2!L z5|o>NL{19`DRqbf>)pR96b14WvNFT9lCI+aix_vmxITH{n9ru*3#M&ai&1+RI5@5XZz$e zX=`mxO#e9ka>FkKP(>h#;n`M!b!UaTje3niwkp8YL}_C%2N?)xuT6h;$)l)r$80X* zs7#|K@&@v6k*BE+6?Rd%Wmz*-U2``2AM($$Zm0asIJh(WF6^8LB|WgrJvM z9b~lkzEa-YF7f#@DsPjSe>Th`?N2+bInrVhRQElxh%4bnrG!I!w{ix8 zm~-JIHnaG$se)tbIE)&Nowp&9R!E1o*bNiM1_k*XTmo;9q)oK@%=rpP2N_1o?Guc* zN}y(t3qAeQ7)A0ooI_TlT%@hJTFr3}?bsDI{51^TMug+CcP3xzzXmG~L!E5o;m~k3?kC6?_gI}94LfSWzRTf{T$uq$5U51^>(wjrOGdeORsU9$pZj_CU zPVsXs(c5!2)-4{y3dH@W1G|+IaG{X+Dd$Ju-pS=WX2tK=EAgD(4>fIbRMGmLP{R7X zTB)g9EZm57bhtZecY}La3TCDH7FY2(Gc0LBmHR2o2k&F^;03*67F0dC5RX0_%M)oC zPO%_NVoQsxt`b6f3e~9Dou4l)D^w0=+$1{lH-922 zKDr97XhYzS6|3QM#M%YF?4P=$;yRzHLf-4PC=;OM4X5xi`+u~rc*`%Khevm^|D z>GuAr<@g@tf$a7&5e1-T5-vVUqnDHpXZp2v~S{x8S#Wv z4)9;aB#ny%a&O!lm-&Rwp`*)M>!$o#M1YnGWzE4sJC-xuIROp=&@&d>pKEF(9^DWp zSAJoddz0LvQ}Hr2YP-!OD>1^#@4VgZogco?IU=-B2pOhYz%ZfAYaR3vBjRbk0RCPE z231cJS{_lTKa2}e#!My zn~v;VpX5qo^-1|l)9xZD0%`@Qqx2A5@Ql2U={!!@VoG+F#bB9Oo}ouW5B9IMkXgI< zX2m$qH##!LpZv6FGjUjlXOO^b#uU|adtW+(lJ-9g^(?;SPXn zbK2o!<8Dh=Ltsleopq5{w+ip}F7HM+5xPna5&6>q3l9~~d5W~(+wW=_pN0a|sT#U) zYmmxQqrFjTn3K0%5bjhJJN>sqg==g8`k2(qszF_P|AYfid%wt_HAUJ~l! z^7wKA>G_g^$Ad3lkCqF9SO%lFB%hZQrGV2BdC~I<@ z?a(COY5Tt-bkGAQPYjjCO{Tis%Ec-le*<-4W3Kc;36m8%jcL3u|j(@{*XUbmY(zr2b1WgVW_;+GI7zIjIs8&=mn zs>tRMjwRZ3d|M}_7U3?=K2dG9NY?&c*q|H@BYi_m(6!}oFcc~#B1KH<_P}6mt>+;| z49EeSfS#n3h)c9v(J<~szl*NQ%c^*^_unnL40nfqRxB=a^|3cuF)r`LOmDGlqMw?8{89j~%pTujW8Oc*9#I|Z{ksQFA<~Qw9eloW0iE`%d%2b;mt2v@sAwyFgl`&Gjhml9^NaK^_kBIr?^Pdp z%n6CzPcri&_d=s53*q8E4q9Bt^HJbhi~`987rl4M6x&GSV(Ka|HuM; zeH3mi+^>`L8^A+SKMt%!jQEM#Ot>31sV#0^^|`73vo6?g@V;uone4+|m%RE2YV6ny zt<64ZE0c_%{CmP};xc)p!DUY0DGow|-UwtoW?Z~DxBHCZ^|X2G^_0YFn?KIbEbWKrMXGJ)^~N-f?G#s zzxts#?U_L-k;qEzcgx@+lTzU^cvr)>`?Rb+%F&dBF9FSUe(mrTQM9=M1q9=Kt;_gT z7l+O&S!p)3YGZXc8=iwELdg~ZzqWU!Dgt$x6+2=|>t5oM40E61QOox`tLmVxfWF5p zyEIHNN4P`dpzGK2#nYD%I2ao(f1y z!EleOXttTWwtv=RE%=1Lrqy7*D8}=0kOUg98i#^JDL`kVCjtS@5j{6Se6?vKE>Yhp zTc9JuVEYAQblI5I&g4*dt8{}2&ex-8jegFvtP2B1f0)KCcUYA@gS5VnoZY%ml|L}q zMr#J@+&i1S^1aJHv7J~|7P$7ZS%nk}m7@&|z4j^62$Ik}w*|{G*Nf_4)G3CdJZxkzXXMm+V)HtQriX6&&7X7ahs_Hx$hm3)Ca+mZlokzK(JF zVTo8z&TNx%9{Vyhor2=5F6lESdaTbKA^hySLiUz4U3zz=+PuM9<>4(^{(8HvUKt@S z%h$gbzh0jgwpt&aYdv2#*;P4YhgaQhXF#0bq_7PulXbhZ4-!l_Kd`1uClcz|Cp3QvKub01(cWX`_x zzbq*jaha@Xz|@anUmXRRHCa#+2nabuarpHOH#ynC0GtHh)=8+$Pz!%+>AQ}9(+Yob z>n%)Okuux%EK?6D5ncGCA?Dlc<#QCZlM7Tl^kg5k`pF=ZrYzlD$9eWPGs zyC9~+B3d#|JdN1`hN<{Q|5h@Taqe~Q37VfJ4Q6wE+vBGWWPTn)Yt&ygARnN#z~aKeJRE5DLrXpm&h#~AQ?vBaQH1&vG(#W>$GNQ z0WuKvuZ3SB=M~YvXsu3FHV2#xJBr>yTHwcKW_l!dixg_%L-rC(I`W{>ZP1Abmmcnzv5e za%g=lwkW&5%dMrB9h+LRfmkgD>=-MW-gxVb-9k+3KvS^%Mhp{%AMIClz>Dwz*Br~m zNlMAo*Gq}9c|E2V@OJM0#vHe}p=nNAbUfML@JuF52yx`cYG^7mE5_cDF@Cj=x}>b4 zX=v79y4;HIbn#UmreV5-@*NL@b`K?d+l()u_chsReusD9K9!Y@;Umr|yN_`C3)n4_ zZjQbRzJt}|_Rxgn?}iHViR6^sXg2bU#hiBnAImQk-*cnU` zzU@WGK8^z^_R$52MH8eF67U{sQIQM99#e0arEv#Z!j))d{Z-nLH~KY}EH-1C0z_Nt z#-=sR5tGUt7>YIy;cc(vKwh^{2nmLBZZ)jBo^6$xg`Pxwlw;jOP_r-8yz)+q;p&EWd%)*}HLnA@Ym9yUXyM}9)%b^p! z9F9J`-`(={ZE%FC@Ez!sm!ymfLQU!sN)l2{?4o0~_6fgn1QheoG0!ZB zj~dY`W(yp4J$P!WH8pq>Z$%=5*FXM#HjRQ5FSJ{C-?@nwqc4!cGeeGn`U)q8ZA?nI zH!I%?vyw5WRPQrdoe@gqSR35vsPm#aHB9^wh@xGK(39n8-LTfVgnUmTG0Ab&zsB{wmNLd zX)&`eP-gk2DEVh*L_jq4X^2ZL)R<+VS9dy^T;o46UY2u|TBJ9yyWK()fJJp_z3%6T|z~BV1 z7z!a4uDr@TNb<_pL;_+W$8YKyF(EX!n4q#cM^M}c7E#pBp8dQcP=8auyj^j?hS!O# z3)1#MM=EA1;@zj4uyJ|bwd=P3=FYQ9MvNzR7`>EzP+?xLQ1)l#YI<7DPpT$gxnlU2 z`y0n!!bZ7Sz`Un|TkFv4$CwT97(b0afWEtxV=_qSlBjpf_K>55txzPk8h=4cbbQIP zg(>hBHmI0WGg)0*gQ_Xtb$_KBS{`{k!cM_gKY5%EzX_Eu+AKyYGegQE+y2Vj)BpRX zOUI{J4%+q%7tdpMkQ{k#c&^;(yZvjGGnF8(MqCv-HnjrL3VMyt!e!T|cvhLLX`#~*rEMA5&ftOccGzi2@! z?kX0rSQ46bGPt~|*(h{{9h$Kv2z3fsjn5U8)Ul^Vm)J!=Cr3!czv}lp=;W|K3Gc2& zz4;Cs(o%$Cq#{=zhO3(f%nB1wV2cn61%z9T(POrnlheM7^3bD8*{Je4>Be@FR;4ih z1k>||ELiEVBD147-}pV2hJrsXDuV$cXG!UOJd=9Bgj7EAUet2%{fysbU#N=6r@^Im~K!v)&z6=_vt-zqU`g z9cep~>+*WM+ydWNe5uF#;_5Q3-1|v4qv_4=Ns%$luVkeOU1BBu(xh!B>JC>8(yqfd zvc{_!T#brq8V(+{X*$EUaLx_Bd)t7{;e)(|g0~dI#(34e%k_pG2}l6sb z-Z03Ts`IzQluF8pr1f-Pk=5G<&Dlv5a@F^&)6>TN5J47I7Bhq#&=Lu?25P?7vtyCd z-IVyZVjS48v!t)4y3dA|OOKiyETi!>Gnn_^jOL-Pl*CBgR1nrH5SscVFh+IlkOzF?%@g9x7GPvhydObDGSJrsa5O+Lwphg(N^a8fj@=IHw1U)Ue z(NJ|-vEh_Y!eC!@u9m2+FR~|9_!W5O?cTg+E0_!Cr6p}UJKScaJQ_&K_=04=y$Mmu zVe!(t3GW1E=x5q->NnhBYQ0*Q(2wJSOop?;q#^#i@|4fIQkC3dI#mk3npg*|K;4ov z=c3#oIp9)ujk5@*N0{Z(F%G?H27bX@R-oWh>zYjrJzq#-SJhX^D1h=8jQ4Gcc1f!Tp6$5(ia;; zG1GZ2W@)`5KI$qL;S+>AL+nXFp5Fvk z+R0e|eV$i{|FV|1vP%F{ijO=Ft3e4{T^(27;Wv zW7Yl2K{d0@lq~jQ#Gn3JC3tle&@tGC9$73^EK^r6N3icJPn6WcrmB^Vg5kz56GWj* zH-6AK+Z*tJ3QgCYcgcx*{7O6sD9A%r<(m=If^6)6eOa56RME=*U?F(0!H+%{Sr6sT z=YN(s8AgAeN^sI2zaG;|yL6j)FC@5=P!@e1OaqW!N$LzPx{7mhG{V>{w@TSPrij^ejdI!Q5R$b$ z>n^U-TuX1pqrx+^>O?jxs>0kIGIg(Ex70e~nRc(IrDNMQ2{W=hu02MML|Qz#i3)dvcl7dZI6T6wjFo-ys;C2UFmt zq$SN{tn-7wlmi3rx)D_jiAQJ2K}wd`PJ0&&_()iv2W~H1Ytw>#`S5Qu+mpYxjG!Xr zU!&qmmwYkE)R+L^9uORNbkLN`8;}sc;8L4WzrdAkN2snCR;%}FiS1gaUN;dIY7HvN zj0QI@A>A*RCZ3XiYlRK{apaq_A;e)=CXGO1+p9>JdzhW8%Ep-2$N3I1J6n__r7O#w zK0wrJf49K7+wa9KbGlX@xBrw~`po;0vYAC~+sojpB|VHWvrk>(&`Y(>q6+57>G>2$ z;SoRdKA9Xal#GRChmHh2 zitWZ4n##Xl*ez~sW=tJP)q4LnEy9f-dcUN}-q{-zZXkqjjZg3S$q8Md{~yu8jMrvw_FkZRkA_y`Ckjs|NGyfP2^eZ`a&`v9;cJZ!7hr-g{c- z%`!xG&zJSsdVSLAg|fRN4Eq&AT(3b0%)SGFm8Ed`XKQjf*+bJONZAz+J0MZ9QtO9YJP6d*|Iw5rqE5*!v(nsf&#m7mEb5;y=1v# z(TRV4?3{fkNTkbZx1@g5s~0U%W^4PtEXk=d?Y;ST_+}S0`;eL8SmUd=I>TNx3vo_z ze8PNZ6Bz1hbOF4sYdqCy-%Lb*N`9-2!{YB+A-^6ifbHWKo)Rsk;^0fGTT;CPXH$$a)*oaRPAm}b^=CO-h_H2#T5Nq1L$fYxrBfV&>`}{7>IJ2f97e5c>_&LrQ z&LNWM@eIEFE<GE!rtY9TEHtHy8aDx>+@EU4cG70fAxkxeaEg$F5L(=AC^_RbKOKr(1_J`B+G`;FJjkK87#O&+V< zJ}^af9FF*xvpuxo z35gbZ8A;|qR_bmbz&XKgrNi7_#1ksJ4>9`HGGm-^= zXC5}cmY$57MSa!fl{?U)wAO90({YKzF*V4WwB7Xq*@(?=CT#;3?y2z}U>hlFL6qCHmgzl0LN&;WuHD^IW|*u_ z2kfQ>rP9$DH0nNgttXV5R-fy?jD8DYix%qDa-$zb2XlvCyY6{YiINivZC^i`4Tdfx()JfpRQ0vR2)mlA+Y z`m2r$gC{t=MBby*B87792um00@?Fhu0D=x&Y*nq&$H zl2OK<_nUfS0lr&z*oeA(NrVx?AV_ao>*C)E)ggn&E$&EcghTXWI3{~Pf920h3mt^| zYNtQWtM9Jjk`6Th?`^o*v|yHhk9cNxYB zxn{EwPC|X4Tfjv;2$Hx^D?rP(GcjVLvn;*offi*(Z@2ST=1}$2zPcrTHOnhDJ@GN^ z%5x1jGnoUW2P-S1gET(G_1W*^y~#Y9Z$I9aNXf6pN?x74wvRvBkKu}n!4(q_6X)yd z8AC%f9^SZtv-Z>2-KhzYxH|F*$**fmGP9U(+Acz)l;<=S9IuR7rK4BZF3^tsUO9&*B#uE zrEpj^t`EN#T^~4j=d1KTXFXQ^ge)jem7$ZmbDl8KU7eB;Sbf+e)q=RiqoVdb2f*kbX569Z$K&C0JoD4>;7+ZFOwh zwr$(CZ5tiq&)oYAvzu?u1JtTEXH~ko+t8qy%9ET)UW2mtyAB)QP$(s+K$QUJW?(_f ziOsn2SW`HtQT{0Z?nkd>W=}XA5P}#3ipk4w#b`5FJH3(yNmm~Hc=VS5fs0F=a3$l4 zl)(dMvN;86hQdo3$fUE3D*6(%t;)p&@6m-A^oT_Hj1h>@Z&Oxw$JoE|*)6xrbQ;)dxCidwzLS(Tgoh%=o zS@30MyAY>^a;{pGu6V_NN1F;BAFG1-snViqvna?d=fTh(3;hWk7n`=-eb1Y2i8-G@ z45H*q@5O7@Q+i18pWErrX`-%~!HmRB6}cI`rN{HBBHBOXUfi}!JV6`!`Jp97dq%ZKNQuuu21&W5J=WD)cm%g%*QSX z%)bGmXH_+yKxunt)XiE30g*#gtEX2l+9U=Ej- z2<75Z+XugWoGS!XRzZ+4WvVabgX7v^^22TY4vb&V`g1+Gr)=Q2#kyFgY(S-Xqo zWDaJl`4|t`dSzb$Z&e26{E5+U-_HqvuKnQ`d{7W8NRHb-k#CKmg{i_f*J&j4B6-6t zdrF5DOv_bMAF1EeIUj9AE*R-8TWVG3!?MCxf;&oP)()2ax~<d92Y=8f2^9%1qtXpd#Ml#-j|R^p3t2&B*ATc7?QBHOUj-IkMJ zPcs%N5`mu{9i|bp`SVU6=U(=XOXO{`Jt1E;ZJSzI4dH4x1MJpy#E5iIY5BxfK zUyAcSQe-F3lxdfqj9ilyb21gM--*=5iPpNad(v+S;!dLq<3~XIWvT*TEk>S-snQ}w z@cJ}jM|Qxhx4NYlXSXDToiY7}bMf-x`-ji(oEctnAYoHh&65zjRh2dpi7=F{f)|~}DSTzuJiz#)ZTigvj_)ORoLoZm8b&Ep4KuG*GUBD8dJq`~8KxY4fsBS?_n3@vm ze2XlsEWJcMy2m$y_tU7GzkLV-w^rb}h6^Y5QlXma4fAmAQ`EDP9oG$#^8}%vG@lF| zW2GwFQDwdJYulwLUV$|*+G7@}r3kx3Co{A;$kJjISU4wmUwBC#Uqa@l38p`qhzy(0 z1-L{+8OdTPD;37a;>v9N0E*lZXMm0f0SgO)GnrC5Ae+?addaf`Is<5Z_4Qk}bf~Yd zcMqm$=|?CP_KxuS*BrQF6x;d(!gBT)M4hme#{r8zM#I@w^V~@9oQy%!iP2q%FQXKJ zFOI(?FVpJ|$q`&l#Gkf4H98=Ex7uU@(*!CF*3}0!24=v@-)b^VK&eJ=cpGy*0Pg@~ z_~saY9WQLn^S*Pph(~Ax6jIx`GEA;BDh1dmfyLj;wORu-M?BZ2h|(j$ydVZ9<}BXx z-QbyMwh=#yCc1R7z0j_5QM$=WS8wBpu0Cp+X@YU$h z&HRm;BPT;8%+n0d9N7nR80;*h6oTyp7_Pk=y;2((_yO3@$j@o7D3la$GqzL6kz&wd z)XS@yh>^BM<^EiF)A|#(q?>)0T>{*m6ILswMfxg zMTK#Qo35w^3BPG>G_u*iBtN-#|CCLb8U*nQ;c{Np0gitGj3s*Z&QkA4E)L&Nh=LkE0lr4({vt!kH0Nk~cmBp&>m&avc~a+6&k~1yOZTUpn@=Y+~gRXkUrx z*klrzcI2w?uFFbd*+l1HOFO2rFNx$-kd+nQ=s=WXOcK1T(1L?c#62|!_a`hWfau`nq5UNsg?Ch8?z zMv7^={&6YAieU7#Pd`ao_lCB62-m&{JW0L-$g!LuRK}j_ALv;uGhvggZk{OF*-_$~ctkb%!K*?q^>9Q=_x3qGM~mXPndb9K zgx1T}^~T+8IDbxId|QCTP<*0TdV8QCEmK@>x4-Wu{!>6B)Ira)GO&5Mq!8p~aSPvA zolVBLRgq+fk2Y6`bCHQi;CStXp!IsVa4_iAbBKu?Ko0SLGgO91?mGd+115HJs`NxdSNn(dlla4zv9mA+}X+3pG$2*P%s)wY{f2kfRvRUbM2u5 zTTCBu=g_a7Oex&PP4C|87AadPCIUc@5~RvW#%ceg1s{hsMHxBaM9rEhpJ)AOlNK7y z2H|?YK1erp<0!nry7PP#ThO(gg8tDS0-UNo<%ia0zff(`o%l|9=q6@hqdQDMQin{+ z-^Mxrc432(%8Kn;Yf8~ksNHz3;b&uZWc;SMd^((uiZ;rqg?{}SP|NDUdwvnROXpx} z5oC2~gX=P8-C|}6{oWm~k8V|DqEYrCCX65d6*-Af@Dz!d0eN>E#X}kED)AFLos6qd zip|9vx`aiCR5%LJ@_Qjt(p4QAG-4lh=}<03squpnqj;}TuVViAS>`4{ARTN>eM8VFLnH2cN_Rx&_DXoGq9tSSu3!^q)HlBZJD!^z0K7Fl4#Gj!tJwUv=R*hQgoe)fMUmk?#V8G*%p6#?4Ixr^wbi(i( zIg}h+CuMFurk=mn6<_g2*#U7w;)H9!-o0Hr_S$xkw7Wz^y82gE`wuCI!A~pKzoLK}*zb8j~6J zF!{A;SlJKN;79W~z+Vn3i^)9b3FH-k24j7SAf<7nGSHdosR@EZD{|q0b>=kw&M$42 zAakpkUxKp$QloaX^Z`>06J}&;PmwU47Ctu5Lbx~xgD^nXlUIrBdV`*;nx(Lx8vC|j z5KFd33K5~f_QJU`?j3db?32e;=#mtGcgJ_3=iEfNl_zn$dAarI$%m8!O=5(JT6Hls zyHK|2cXoD#0YD5Cx9Sd!&(0 z-$1uW*UrhL)U@cNZ3LkCA{a<{6~{eg*HVh?{@cw&W6TB%CJCT~RAYj`wd6`&N8nWn zaF;Z^0Woj_zw{jd--gVB%g?&G?k-@m53q553sbx*yE8ukHg>@{SE$mUoWs=Y#mpSP zpjR)q5`(tK;c&ULLy4iIL!LLHSiEl_xj`77^!&7jP@f3O{j7>(y0^EQBQ!jF#FL8! zj#Z8abnL;7oSnb6{~iR9vXi#%NQOG{i&o!-z*5zpu?pswXuk!LPy_n87d_NQ-`bfaVB=ZT?f?c#7PE*b_gl2 z@EiV>w6Rp!gpwKZd=Y2r51o_vESQWNC{ZDrMOs#6WsRSU%{%Li2Vo4o4}|?(@n)E% zuI3!Gb0W{y>f?tc>e{iRg=UqMHoIU z!ZCo$r?ws}pNp?bT=cfnTu}@NFYIB<@V=68{@@gx>b&YRGm;Qd;G4{N{%f@qaMhU4 z3-Yd#@GH>wB->vm&Ec5>;sk_b7E)ANsb14DIS`#a^9D+z%-l6$CPTfL#H^({Re)P^ zU_E-AXGF?$!)&Ji?XAAfM`Xf~rqFn*eU@zkikwN?ZyM2U2G@KNjLnn2Am-X9mTM|a zX8UOXo2X$E9Z@W{yRxMl9eNyV(svP@j~vCOq%IrTetSd8fJ!q-g88~!g5l=+I`k+h zT?JN|mov!xL4o{!=G6mnk_&;@!ql^jNL8j6*h)7jBZ5+EY_ zu3L49SR5(xGXtI<=!pVl*1Gi>1%FUso&Pjm@)V*}r~EufLL^#9rx5r5K<$qrps^z2 zcWchgNERq2D^UzbWH0&qS)^vKbcc@c&+@+#VWIn{;@jdc%Y>&HaR(}FZM7zK z>PuojgYV_q?=i5;HW1D}cO>BuKWge5#r@Q0G0S7PIlNl;TTsJjs!J1`CXIg1Iu42iq_rn!0ud2y#fIz?Ln4Y zM*(LR2{>y*h2~mAD42T1$>*)wX+M)p!m3e{)M+b$39? zj4h+BI?{T*c=VL|xmLqbBy6=f56`wm6#y%B+_o0TdmngSTnc+Yh4aq+V=34eAbYltkMEY&Xx`EVb2+$YIAmF?gnUMe(n9h>5Y@s)ralK}8fxpy9mc4A8&S(b<#m)3tOZ^I| z2__G|EAt5=h9TyD`D_`7FS@tI& ziX^~P-C5zY_!xkILIR*MX=e=~b-Xb%H9Lt3q*VnA@ZUfVnNBsj;Bg+Bd?o%yt zs0ji|10VX=qqE;}4cHs6f+Nf);!WZ$GbYgh5BgEwY~jn*#r+8y;|e5@`1DRDrI)bU zD~Wud2SnP(!S|fv)-C66wUDLqzuKJos}8bAzXHoqG9`XOtlcaI#k^d{Dg%|xNFrv^ z*Y2ahU_i_rKhKJO?pqxTEUKkmQJ4GUN%JZ9C>taQ9^+H$lh^r;S&8>z>Y$EWPjabibbir`XP%fq00?X5PZ*i!I=yX3acc< z2LaB5J9lUyy{$n~l`<8B50onV<4U4>GJR$xuZr)&utqCUuF_A>7qxN)hXXX2FIQ56 zfN_iPKb?+P6#h5DG_doM$J%Y3a%CR(+7A6~A>-PT^?k8B);Y9$+3ZZPq{Xx`gRJ0l zr6k!sqx?B2+&!|kEG+|23}Q(IpxS-G{MRW(bII?yDOR4YtFt$cv*$)y+Gj+V`zMv0Q}&u1+yr=^pXT98d675~7XQEk4rhJu>z#D$6|Jv@%#Gu(1FBWD39oJS?F!Pb2Gz5!0Ah*t@Y89HqY5$}_|tHxs%l%2 z)s=?^(htg^hc*fE&2O%Yc5n0(bMq<)jy9? zoUxe0%tVe{${rY!9X7v`fLg*UE7*BP2`Hjibb7BDfnttu?8NCMBGxd-h6}#lI2$?A z-u=GiDuN}mcfLpB&D}}T=lQ3wM@1X#?ZR6cR7AnN`?)P{IKoT4!kPg@3G<4Q+@#v3 zU8(5%mi$C%5U=`AheicS`CQxa2?LwUGOEAl4Y*{nP*7i7QsLg733{+-QRzPr)8`6X zqZY7l$z#9@UF#lpQ2uk~COXrYke6^_zpA$Wt(nedB0Z0U!yX7GFl1UV8iSRqFT`Z^ z633sy%Hv!-;6^_?jIo}5jpi@qtkPo`$7Tc~z%Xi2tF(!fs$hDmRdmaKA9Wl%-sx|b$5Ojq&irNv(Y8Q|$JWV>)gf8;N&xRzm zy(XpXmEhp=w1$At{1)+_Gd*XyYpvM~>A1oC7rGP{0)1*;YV7BsO_=s7V`O&o_!2t0 zy6fq$Cj1Ar*BrMAzDwU=R580rbM;{r8|L2UR1d3G))Ubn`%OK;kk+-!D0mNZJO6P& zO>Xh#S9s_eQiGp(ntTeNN9}Djt&f|w>gq7?0^BT2Yc}g*NNPBLfW?mw+s5AWRS}g- z*|x;qY1cjI)t42=Ppbl#vkp>&4;5}l!+bAHVf%&hxF%Fd7~M)i>o+UwW$+JG?#<_A z0S4!GgAF7|pBZ>8+a(y@8Nqmi5e?~FErvc|Vec5;nRz?7%CmIn@yGG_Ew;d=&*2ZN z&)>ec?Hag4p@O1*gZ>0FGpsZ>s5~I3M06g&$k2nMUa-c5r`1$DJUxl5q4xi79L=rk z?F6ZMsV?^5zJi^LG=i8al`vu*a^;Ozgf zstU5pvHy{cN<(Ym@bSQ-m|RG;#ZA)^1W~2l(PC_6Su|rYO<<^ zZvRjQb1{vWt4!KSKpYl6z|vA6`Sd)vUv13&Z9CCli7o&aNUXIul=CVzH+z4-ulK2@ z>K44D2l7&Cwg4&l=*HMJ%T80eUE+Az@D6JSx4yXmt^`D$NzatP-C5_mnggI@^aNUW z+5w&-@FNDM&Ut*h{8q4T*WA=16@#JRdHL{UInWQhiC6U@Q#6Zn72v4REtry8&oaP` zZgWfRd_SzR!HVwDCK?|gn{;@i7IPc+sFQcgy5xqakvFEKmOU7&OmlDg$+k7G(hf8>{LW)Y0i&Ozs&f!q;*9M&CK5e=Fif3-(IAo#; zI~sT(+sZ;al^aF>Xa~YMot2G+*rO1n1rxtzsfr_lC)p{l=Qd`zN(Q#9)Jr!p~tmZLcy9{=tt zlh%Jgv}0z+m4g2EW>|}jP4M?G_m0(YAH@l}ku;XI?%X06$OgOKre__$y%1j?v2$)Y zn-U@aA4TPJ!|0D5BgKjEj^xG?5i@&jTcLsv7qlP;#Vme%J4CL=&P)8Q>x}m5RYbUo z@8AWx;1ua5Ed#kLSm7XSafg9c&bN`{1q+XI(ZW|At7p)3SPKDg`W`Y*v}I9QqtjT- zZhY9lwodIoGS$bsPD*H$GG}3$UeYt zQM#alwu==j1wsf(^M2#DDzX?IEpU3ydc-fxki-}buhovPg^nj9_3&*Yf&PCYhCPi( z?Vv@h=GTb!6kNM1&2lWII#Yot3W`J~N_MaTI>StE^H3Q42!r8EMI{ab0)f(DMzD=r58hsi-rVHOCXJ)C4bX&>w(H7l{5l8TGxg7BLXBgU zf3)aKZy*%i1lrMt!f0;6c?c=9#>tGFKwLjOhLT3R(S&1U*&x#mc?^^WehrF`Z4>x! z1Z<~0*g{s(rFmh>dZKSb5y+tv+FR|#a&b;}A!BFvCl9IV8(!EZs{D~PU4#>2)EPVB z9(TZ3`bYKr8I}cjRlnEZNGY|~3N!p=AUYcTXn-f-A^gE3pobvLq3UW5InWv4EKdHl zoMOf~_f39tFEktgYpXIp(yjTQPQARiYN{Bqo}bF`(pXb{fZGlOsVtt0F?C@eb$Jd% zykOvx+YS^`;Fak;CrPOI_k*Vu6`Z~CAvNP%IEGWa>x!7vcYPG!r-rBx z%f)jK!RsgU!62~`gCRkIs1jKu#JAFGoHY()WY1gYSB1-PBgk4Sd}MZnv0Yx&-UaTq z5IFq_?_sI*^`v<5(gf5 zYE>#^XDC+Kcr;r|#N)&UQPO;|xksmh#p=A&x4~q1lp+1+iM8M(ld|rIQde?G1!zXB zCfiu&PsUCE4CD3_PCsNPOW(3=bvbN}+G59NNcF%%J<&Ty$jk|T1+AV=U91_O23Px7 ztNT$SK0}@NbLEAemO3PNl=y|?X`8`WU)_@&oe%a})YlJ5TRc-WwPFL;?eJ&KCWQ+? z`~YNiRPFWy)g*&$t1&h%^GpEbN&E8(?OV?I7+G!wsnEfUa4DVTOyaapQg_WtBS*S< zf{FgHwt5_AD~_EzAj07E9{dFuIv2u^utGY4I}G$hkDyWq>4VXz2saU1ZM+`b8G3wR zxB6Pc_O?FhY%IJ7r7zbuuwjRONs9q1S-;Xan5*2x@#=4|eAX%a=8-F*xd0RqJ!c!K z7dJQ-6r&j@*N_mKr84<@<({^A%V*rSW3k4U` z?J7IxR-4!9YVln$ss&GK>w`lb9JR7}H<-%D#(^U=SgO0NZ{}1n19~Q=)5qC=NZ)l7xyjWd40%Y3DP&ZjgGLwuhXoyYocxYiA>fhwF%6K zqU}YSk3SHJUKrtpb$`0)j>MZ0(V8GJYke-iMiX>uy* zzsV}q?sw);hH-2W6!=&3Qrn+sK9Pu>KHX7sMIMnno$Ljhhg9*-8EZsINsM1u z`*f()(D_N8u})5m!N({sJ=fMTcxAXmf#LGay|Qo&A=)bT%|d`3=<_#;yOKE&Kio$) z2;)Qx3|x=lVQ>eW2s?^rx<|H|^Pw)sxHSwq?WQ0I8ukQ!ahE+J-Z$%xS8bXE559e( zn;xIdo_BQ5>pew90lN6=af^{+tVt4>*X0@7wA2v~twUdGa)jx%fwo5f(Q>lylF+r7 zNn|qc5H`w9B%VsOg~GG|94<_w<6nz{B1*Uh7ZFQ%loW%u{WdR)f)Lx=h&1qDeS)XT zKxQsDO7GkvP=CJ|`BMu1*@Vo6{3fm0e_$);?m*Q4z`MuXipDG5twJa4QZPN*ymg-( zVyul;S{3C9g1&{V!G><*q;f(ih>~~dk`V*!(bc@~AfDU=qT7sYf~4{oT|hX|5!o9l zU+d30dgW8HHT#8xGZXOkd6DVsIK;%RFxJl-%uDZ8?}7sp9O~{P*{677 zYEnAsTLl%z%R#}{)hCb&)r1T2E5fex095lHd?^{GJEG<(`{4l}otJkiHN(iVd99D( z?mIY?YgWU#-OXx$C!kW3;hfa4lWf@sc@YO`y8ZG z{*SimbKf|x-SYSsCOAIYdELOA1w~=rQ6fYB97x<09K%h>#r-8|@wIZuv2u%2ICjOV zQ@KI*ia#hreMLhKf8$QvshKP3aK6E2B1kldcnaf--{OE~=e?wUAf|wQHgPxjh~2qd z@w;%*nK+A!$?&+_)G0nxGW z@NZN}GtG1jwV|k zL|gj6DNDd)pT(0V9v6t=)J^`hA@FQrTcR*r#hL}Gx*GgGvnYr~J+`|+p6DJNn0}XJ z*|}jp$|ywZhsN7Y=`apwC47wSkVum#+>sYaZi}7SagS~O!T)wyi@5FVOT~bBQ|}Bj zuA@gnn#USsCmk@=$MKB*rx8IQXwa)7(SpEbh>rx0F&&(@b-mfC-EevO5~(}P`5L0+ zIvx-vhM&Y))RepulfzQf<#oG6R_og0T^ZiHI#Odhq+uJ%#ZvIuLc9wHsuMczf~5&N zCApvy;DRCZ{!QD-}T{EL?buD~q8 z{sKUTfbX@Yn%O5-He{B~eb91%J6zLL98*dvjXGK#BP_X1OXWr-b%sTjhBr@YJey(( zvI61!^V+M>o6p>FIu07|;@x`D5mDuJTHX~%T!)JgDQq|3(3ljCP@Twnu$pv)3tH(8 z>u~lGbR9l=HgSxIPAtNo;_ii#s(^iy)JPjXDDkmfZIF?bL1JeINJb0B=pYsN>Vb2!@dlqeGg3|Qx25PkG9D&#_oIx8qWo-A#n^iMQg zDtzal+{KVU>JuzUk@OHb#0^tMJhpYKgX?;=Yjc5iTP?&uCN$_)o4w(V`X&SADfSuy gfYCsJfSCT5gZY2J{|SJJ?SGq;4*$)g!32Q*4}D^cnE(I) 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 zc-oY?W0WP`wk?{r?Odr!+qSJrS8}Co+qNrh+qP|0+Lbo%xA(s1o!8F0KkoYx(b_;C zF?#edTg=(QAG97E1cZV_NtIsM#LfsPVQ1@1&&-NIHMEtZR{@&2NIM%^ z1DKfp2{Ez5QBa6F0u7xl>}TjsWZb7yx5CTN8_a_3Xp|$IJ{cu`qT97y->J zY~dLH#ai0d)DFPR^dG;8i~WDaT!D^G|9}8g|C>BD;2-KHcDB|Y0281o9HWAr^FI#& zQ2k#}_@B`KPNMq%^}_yV9SIj}YXw7_f13D@Xn=oIa{|Z#{-v9>p(Eg5+F2O?e^7=t z7SfDTcDE@fc-z^fVL+8v;BWG`*-t<|EEd) zcZ!msg{`xihdmI$^xqf}5j%H)7dmifPJc|&JM z3wMAH(?5g24EX2%U)O(IdjF%0xUI3BiG{5hK-JmM*2K`!v$ z((V}O#2)-m*ftfWS0ovc87A%i@Ky(V9lSr%qU8l7E%If({askfiKyr(W7!vkVn`@Z zVp0B$V;*2D*0k&FmIA`>!9@MrmWW2@3sFmN+!q5jVkTg1^+n}7d&?6aUn|-Io$v}o zM_3aw-zE}Gz}8|iWGPCU(tb>MZx$-$A^TStJmw>|6K0vT0{ZxDw27OGf>KF3q%&qg zFY@--Ht3r3k~<#pR`$m3@AC~;LWXAfph-R&-KoTDPox5McflnOm$vjFj)c*r^9_%X zd5LeF{Bc-@Ltbrs z5SCjpcgk0|LwgsPr_9i&Z!~bL%<3N5exu zY#LIfV!^h%YJ=P&@9K8S_X}}`5)BMgNz}D#ESpRRkGd)&zc$nqiyjh|BHM-x{|2XY z#v0W=YbVT|97L190RX!rUNSh(+y`h}_g3VUTO?w{UL&Mr-h81&Ib{he;;h~yM%Zbo z-YVC_tLsG;OCum!_Xc*AT^zAeZ)td}`gq6V%HGG$K z#&kUQ{1e1HZ_#AhR2dsKP~y&k;t4MgS#2J_9uS|L^$Aav7G88b zV($Xj+%j;P2Z-}jI$A!T;a z=jv)KE^DLuFT#@S`=>~4xsri2l1J^(Ic56SZscymN+FlgOymF(na2VObPM)l6@++s zC0%G7ZB~-VJ~ZqRI1$#XWSXXsh?xD6fft@bGA(35Ui7)*#70R#PcI6fv6_OoO z;K1+OUwQ*qx=SA+hh{_+;Zf(Y*>^w;w5qUnO9y)?CVWw@n|Rl}gb54bu^iGc4ehOY z{_@s%NWf{dWT&lR)HSNwGwA(iF{pX0@PNLbRUG&fN{)8!JDviWnx@3N1Dz@K{P#(L z-i#+(%j(2C0(XF*dn`5!YS*TBi~S$q1*R8&qU}=(xOv-zTFFesD12Q}eqG zLwxw6XVE>Ya^%mP##RVe**U|z`s@|kyYeg2DfvzCYq)sM@2^#TW_pAE@Qsk-h1~_Rfzk}H7gdS8%ubU zuEo&#oLJne8bY(jOI3e&W^}1sw%GE*82)NyqGz-niv94{HKSm}3I8Sj!c_Wip0h6! zWF$=$|8PszL|2_4isEEHJC(XG6nbLj4O;Kf8yn7IEek(uu#VGKA)qDn`~Wzw>=-Hr z2V~qhWyORPK|oH9$1k4PHuSQd0;`K_XlcnKvZ`;Q1Fb-;czeli63(qOek75JsCHiCt9rSV-R+Wfv?VrIAFoD45#Mc!r@*(m&|)AElata?CiX3&mUHOT^n4Ssf#*j%0LKIQWFZHE5 z)*gBszj!+ti}};Zl&3f@2jQJ)Dk&mV?Npyf%y;16*Fm5ex+6u4;;~z+DjO#O51HJj zFPmY^NEJPHI+LwA!sdHl>dy@e-z6`$Ib}>$JNYR2!U5+$_&7;@ijATOcP5&}Vc_-d`Op?>d3P$D%T+b($1k4HdL;Mg?<2ZgE*Zx>p1rro^b>1Gx$&3_tq{j`JQ3!Lu zglU>cF`NA3Z5f+I&#$-){1IhP&L!DLfR_oDWrl~FBw`GmGDtkX8=hwfS=^58^E2|D zjk$cBqvQ7R#JWBAVmzB?6mZ1?(ton$xTOn_$^SDj*PfDQS!H3J2R`wo^3D!=o7FimPt9y*581j`!Be9?k*n1Q! zACBEwqzo^`U&Jlw%$@thygLq?UTR%z`k<XTImKzZ(SD=qi69NZ;?tTkz-nmrh?&M+!J2qd$T$}0}$=;HirXdT-^p{p?L@w3oHK8pGgfMpsXFwVw7)92v(wQ10z+_>I9YYTa1YC4+-;D+_vO2u^TTI3RFN=fi%{&}~4QnM%bCvC?OpW;v@_$q5MgctY*M zT9!H1;`Kp$d2Rjb`FoAGYG~Xvg`|kj2eJ|Y!~qq5R0w;ajHZ6vz3C79Pf zsNqJ($Y=tB?5Iu*O4s@`o{gojyjUi%dBu|Zya2v5YT$S5Pn1v2qfxs+e(FUfIOmEm zjPui$97kQI9B(eDt9c3N!GV>5rF!p~gj}9;+fms;)hxGs^TG{mo_HQ^klg)Pxp_e| z5)m@FaEOcL%+4VLy_%xq(TeelaJ`4HBb4-}iibXoI>rwxQnku=OwR<N{< ze0^Y@9w=;qdOB_$G%Q@SQ`o%@)ph6qGiO(?j~H1T;&*h*Dy0VUR{^5*LINMBKOAN; zdrHLj*j32-%Dc;-6ODDmXiC0ZEJgX)HW?HpA9#;#6T0uFrT3GR8w&haY;>bWb>e4s z^klCeF^uR#KCHosRX{bOk2tGMhYC^h7e9Hb^0oRx=j%H>+HI9M%e4tFT^FQfMyDO! zM4d?&6MD~UC-rfs4lyQg*e+n=KvJ=0gg+Blaa4%2Wyq}*LL-fp(ia?%m2dkSRIh9! zfXCX8aJwU9EF|aH-3-xHM)l=&BX(YsWLVyvI_{=6Qxz1wcxYiRbEs{NGVVrpRy9qK zMYcNT@SC-H@%CFw#F(*qer0eODQJL7Lar}V{;dXXQ~hV*O!YXT?aSpAhTL6vY8~PW zRO6B%@7yMh{ZU-cxnD=Y@>>3e8e;T-X4mU{ZFn!nq}Tx0V9yyCK>@t~Yx2N`+HWbx zyCpgN$dD|Wv!$Cu;Kn8NqzUe3CB$&!(>EY<)yWSe9ndmtbUDV;M%xPJZZuQFsIfu1} ze_n}heG8X>N<0zh&bYW}9PRx)yQ-9kMb|h%aA!&_y6@K>n^76;| zHGdq)bW={sKEy&a<$f}`9}02yJydk^3ksu~1(*^J8l;Rjw(LmpkeC?X%Kav{t1)yXl( zNR&P~7A0KZoocL&vXCtA zBFpLO>q8Gid-Qqi4!Qa_k++3)!_lyW1|as;)sFG6)(W<3XOxo|Ci0I>VeQ@+Q}$hl znXJh^c3Ztg`Y&uF`d}IxZ(T3kHz}TE>4YjK^N{s`3MLBEIpl zkg77lbUZc_IDqM9bIG?w<1#Z4T@53Z_H*p@fcT(c@^B}wVUz8tv;2t?-MG+s!}{eK9*cH40$T#oS|DEGS7ra!pBpmbgfuerR+`3a zO5P)aj-g{652BDeB|NJST1y#QTK59@^u=A&YVKP$*q^GC3YLL(l~i)#*fPHR8b)*U zZy?Lia$v#czzX>i!Qed7fwfm>|CQ&(5jn0)tcFEi!3D|WGrHb~>w2rj7LAc>YEf;0 zvZpWGTyvpz^Re{`)H-l3ML%NI#LxVgeuC$gh`zEArMb64^~^o1s6->9r>L1%NR6Vq#D)U(4={PT5x|j; zKOI@u8MVs!SW{ra`w{4YVYeT72m3ZHpaOEC_sH3dZG*1Ojwj`^hiYYzZW=I0O}`SU z^*!$BpQ7gTFstWl*S%uoL&>d}5>Sf7ia(h4G*qlQI4V{{WLUw4?2~?t$4mIEC$CkY z?R`G3eB+Sv+-C8$*R77MqE_XcpDEI%Aw;Z#l-!}BcxwKJxD7lYYJaDlJwV366&p03 zKo4m;1WAdFMy|&wzSgJqJg{C+LiL%0TkgMj`Kwdvs;FK+96JEtUJ)oE)@STJ|M-KK>Po zlN8VxX_q6Qggg*~0yV2rznc)yqa}6@B|-pZuBQxEGu$Ut;kHdnP zaRD_96QtW*_4E>u4ufIUnIz=)Q2mLOHQg@JPPfCS0u?09sIp7_BRUP4>w+j_e)w+J z?3v-E|HMAyi=zeC_ObFMh?FKIwVA)m;i&QA+Oz9%nG@ji{gfN+)|N=j_1SVKS8QrT zfOvu6lYU_~bHMyIbk{ok$ir0xNuXy;$&z80;&>?fQ9v20OaJaiHNgr6mijk-jX``z zc26de%*WHPaTgnzjc{5c&D`6SB|n0HULBQMwRRvl*_P{AO{4JK=c*?V0qid$Rs>$) zic#H11dprbAnwG|s$Pyzw^me_W8jg`JIGgRubi$CWP+LBpShTfjG?4UPEr7p2(>N} zkQ`2^&PYM!4hI%l$HeEl1{n!bK6B>nR=|&T@eLF$FF-nCx^NVCgFZ8u9dT#}?+q4* zOX-2Hp|{aY(C?N_R6-2cv9`tCpCJw|QGIcpBtD#|*12HwtZZVP8$j#cuLB7+{{pG{ zxD~D6sAORx7SWsOG|UL~%e$F+Ycp$LLPyaj5C&A3#={M5)hET;5E_bJsd>CQbooXxV< zG+esKNU#cGpqP=a9PCBV?U3ksI|T9PH%qtg5&d2z^hmU~ zbjQSs%tL9wbZ1K?0X@ivwI>^xcH&|2CKkT$aPPutt@fv5Yi7{yoZuS`u|ogpp`?WqRjPa;8D)-4P0PYLkPknfzWQUUO~=^rna7Pr>5?^)kqN<; zl!|$y(o(4sKHH#(?@y#N@nI27TDzYwD(qgy?WAe`<`v1;ssAswzYLCdh&nV3J1!l3)U_r}g~A}wN906R(C&&0cmpZ#(S--xc2i619PGUlUt&J^N6ZHcohQ>v5kREjKh zUa$6Npf4`kIKXf(MF8#_C!od@Bajy;GX|)fCt`#i68dQqjJ`e?0a6yplHR~aNwg-9 znf>?c;O%HBQZykjPzEtfF&6@Qcpl|SCPQy&hEB-*^RUopxf^?MpU({5_+otZ)YCNt zi%1-SJ>Q;5&47Cj2Z|7sZmPIbbJChuFo~NIYJ9pHQC_mlB=VswjMJT}>zi>cHC-IjW%hd60L|YXj1tCNO|n*rZSA@!#B`2DqE*|H?p5S*nHsG@ zx63*YMm+IRPbY%c_d1Br>-kwqFV)nMfaH=TZXVnFyD;5YL^rP1&Q&wEbf94c8RwEo z+NA{yQPaxV82{2(m7ME9*#!i7ac)}9?o+(jmIbQC^jhpCO@>WZ5ME!lkL1CPq6R|bq%I7cg@B-KNtT=b1JWz|lv z?6z@{Y(mLI^o&9_vITzepS>{_F5u5zG3hxzuWv>+s%ZpbSzsRSF<#AsmnD_^;YP`` zwx*18h_nQUic{}Im`Uvceiw${%puO`Am{!yPIHn$DsKSv1;$Z>W3w%Fl~{ADZHzEx z`q+494y*3FgJv24kO}L5Fwx>BI1*5t+*wyj9lc13D>I#OtYD@Z;({F#_DioOVs|}S z-+_sjn9{vp;e6T{oz_l>4uur`2#^$+J@;2B^w_usYbut#Q%21+pj3Wtn_L}76BS4G z@3Baar)5M|{-RMioXobOi1^l8PYtF2MG#3aO?j?RA5$ZP2J6M=Pp=o5syF@mw#J1k zge4C$1ULc)zptdgVtX>L!g*wU9~L6$Dc#mO7Hb7j5Xdg`>W44Go{kqHzOBI^d*-P` zOPB)BAwKPa;?6bB&{v(M7FNSMG+8J|AbGG_w8rX#T>wgozv?Q#EOk6(;?|T9Wj)yV z?PQ}PV-{>i^FaT2j7!C#+>5;O zcpfQvXvK~c>J5Gn9-Hiw>+Z3-P-eBxQIN6IW`~TG5{i~}db^w|8sk#gv{uTx`dy&e z)?6^$wtCTGVTN4%DqS<*5$}| z2bDc1ki(YkA(K5=v(8^zQLb3iVZ3^-{p+`F$B=5Xffe~2ciRaEwH}O@-3K2i;=((Z z<(4+*qv+#L1jNgQ@LR-dyjJHn0V2q#hwQ>hO7*>*aCKbQF8_{fz z5bVG9zuw`@8>ZDgprfmQDCm&GWEn7oVD8!Z!ebCD)bX25qTTPf_PN)s=+|Wg*&V>| zWM=c4vzSC%eTqsspfudq^ne1)qdMDyc=MYB94<0-V!Li(w)amMu*ML^`F4{Xrl_1s zF43URUt=Ni17aPONVdE~cEB*>3QmMXZ`!4++3Bh~kGWs0F&gN}9eK-E|3etO7`3vy1ai z?&$dhc_2yivNtM|zE;4q8_bXUf}>E-V+)^UR*-KWZptiZwh9B9wm6UZ-j-uj1cXmb z6N+ev(7FeaiBLghyX`S}QpzQ@FqkRBJ0T>haz@1)LyP`S9l6A-lQa3&A2;BVqL4d! zBo&fbI#MrQMT(OmqBW5NKgamN?qe4&Fk;NW+YTlGB~Y>azgM0_NxZHe^aU;g(hcfT zH^ALNY2&BoxPLCnocr|uvp_Q&7t7y<_icWDPt@1bleg_cn&i}!T3P&Zly)#)(Tc-* zgKLC5*Gf-S$&h04dd{dDD#thcq8^FjI8&&iU>V{y+=T`O9hZ|fU)oqbeadTC-WXJS z{23_ho`V92X_q|LGNNq=<+~n4=n11wZ(gI|nW+d+K4V~_fW~k4H0R({Xw_8Yq}5YT zW7B)}l!?L>bxs_dvkA9o4?IAE*&hC#Wc{Hd&oGV-^CZ`sOqF)#3^ABnRT|x)D`ldr z({ZVofG8o)dU7rP&+!f+Z=y6D98w_I$ugSa(10-zm5;;Jpj4X-mgQ+Iwo?~xrpn}= zf)M@yK0?1O>{u{!gzlpqZcDoP!zEs*2-hqejiB}6F;sF9uRq5^ti*t2@~(Rnz9w!g zxN6&ZzTe$y!LwPs@LWGR>-!yODpA;!bSk~3P%D22n+_^sP<-sOY+L;-p}ZTtmD!`b z$BlmT`uSYR61Ic=s_%FN0cm6}Ipth@9IaCxpbzKL#1Uh{*Sbb)?;4|@^oUGE`#6jE zXT#o6G~AAj|AZEFe2>wq4~c6`jU?=zTtY>jB;(rSQ_P!lQ(TYne1fe#H|eAkH@k>C zktitbg~?5fB-etjT6kd+PqoDnOymsZirxiv^P4!z4eE$cCg8Cd%gM!2 z2{I5H<)3f7wA%?3zg&cnrcSrtdd`Rn&syQD=H67;4`$D8oM6khxx{dx=DrItrrsGCn`zeQFLCcAdt{yJEMQP0G3 zF0>!2dDBeYa|L0XRv8LlX+u7DC(s**wJq(I!5P0_t+SLrkR6JhMw}r+VZ#ZskNmrz zC`l)v6XxKz$EZ2biV=q^JqifFT2ZKWpZ|(ZvglRnG54)E|2X%zpMJ(D+3}Wj}iA$(Mf`0<^if`47n$RnAKwI1u z!2Y%n4SdAa_N<#@`0=BDGfQL;+qYkg%!E>ok4apyzECq$(+`6R0zaj`QMCJ-WnPZP zC{3pZW$-{s+x+p5!-qj`g!eLWe0siN1L3-O5L7-k

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 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 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..4486654039 --- /dev/null +++ b/locale/de/cups_de @@ -0,0 +1,124 @@ +iso-8859-1 +Okay +Abbrechen +Hilfe +Beenden +Schließen +Ja +Nein +An +Aus +Speichern +Verwerfen +Default +Optionen +Mehr Info +Schwarz +Farbe +Cyan +Magenta +Gelb +Copyright 1993-1999 durch Easy Software Products, alle Rechte vorbehalten. +Allgemein +Drucker +Bild Optionen +HP-GL/2 Optionen +Speziell +Dokument +Andere +Druckbereich: +Gesamtes Dokument +Seitenbereich: +Umgedrehte Reihenfolge: +Seitenformat: + normal + 2 auf 1 + 4 auf 1 +Bild-Skalierung: +Natürliche Bildgröße +Zoom in Prozent +Zoom in PPI +Gespiegelte Ausgabe: +Farbsättigung: +Farbton: +Auf Seite anpassen: +Schattiert: +Strichstärke: +Gamma-Korrektur: +Helligkeit: +Hinzufügen +Löschen +Ändern +Drucker-URI +Drucker-Name +Drucker-Standort +Drucker-Info +Drucker-Modell +Device-URI +Formatiere Seite +Drucke Seite +Initialisiere Drucker +Drucker-Zustand +Bereit +Nicht bereit +Druckaufträge +Klasse +Lokal +Remote +Duplex +Hefter +Schnellkopien +Sortieren/Gruppieren +Locher +Deckblatt +Bindung +Sortieren +Klein (bis 14x35cm) +Medium (14x35cm bis 33x48cm) +Groß (33x48cm und größer) +Benutzerspezifische Größe +Leerlauf +In Arbeit +Gestoppt +Alles +Ungerade +Gerade Seiten +Dunkler Heller +Medien-Größe +Medium +Medien-Quelle +Ausrichtung: +Hochformat +Querformat +Job-Status +Job-Name +Benutzername +Priorität +Kopien +Dateigröße +In Warteposition +Ausgabe-Modus +Auflösung +400 Der Server versteht die Anfrage Ihres Browsers nicht. +Der Server konnte nicht Ihre Berechtigung überprüfen, diese Ressource zu benutzen. +Sie müssen bezahlen, um auf diesen Server zuzugreifen. +Sie sind nicht berechtigt, auf diese Ressource des Servers zuzugreifen. +Die gewünschte Ressource wurde auf diesem Server nicht gefunden. +Die gewünschte Methode ist mit dieser Ressource nicht erlaubt. +Eine passende Art der Ressource wurde auf diesem Server nicht gefunden. +Sie können diesen Server nicht als Proxy-Server verwenden. +Der Auftrag brauchte zu lang zur Beendigung und wurde abgebrochen. +Die gewünschte Ressource besitzt mehr als einen Wert. +Die gewünschte Ressource existiert nicht mehr und wurde nicht ersetzt. +Die gewünschte Methode benötigt eine gültige Länge des Inhalts. +Die Voraussetzungen für den Auftrag sind nicht erfüllt. +Der Auftrag ist zu groß, um auf diesem Server verarbeitet zu werden. +Die URI des Auftrags ist zu groß, um auf diesem Server verarbeitet zu werden. +Das Format des Auftrags wird von diesem Server nicht verstanden. +500 Der Server hat einen nicht behebbaren Fehler entdeckt und kann Ihren Auftrag nicht verarbeiten. +Die gewünschte Methode ist auf diesen Server nicht implementiert. +Der Proxy-Server empfing eine unzulässige Antwort von einem höheren Server. +Die gewünschte Ressource ist aktuell auf diesem Server nicht verfügbarr. +Der Proxy-Server braucht zu lang, um auf diesen Server zu reagieren. +Dieser Server unterstützt nicht die HTTP-Version, die Ihr Browser benötigt. + 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..7fdc73b674 --- /dev/null +++ b/locale/fr/cups_fr @@ -0,0 +1,123 @@ +iso-8859-1 +OK +Annulation +Aide +Quitté +Fermer +Oui +Non +Oui +Non +Sauver +Quitté +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 +Options supplémentaires +Document +Autre +Pages d'impression: +Entier document +Chaîne de page +Commande d'Inversion: +Pages par feuilles: + 1 + 2 + 4 +Graduation d'image: +Emploi taille normale d'image +Zoom par pourcent +Zoom par PPI +Image de miroir: +Saturation de couleur: +Teinture de couleur: +Correspondre au page: +Ombrageant: +Largeur de crayon lecteur: +Correction de Gamma: +Éclat: +Ajoutez +Éffacer +Modifiez +URI de l'imprimante +Nom de l'imprimante +Emplacement de l'imprimante +Information de l'imprimante +Font et modèlent de l'imprimante +Dispositif de l'URI +Formatage du page +Imprimant la page +Initialisation de l'imprimante +État de l'Imprimante +Recevant les travaux +Ne recevant pas Les Travaux +Tirages +Classe +Local +Distant +Duplexage +Agrafant +Copie Rapides +Copies Assemblées +Poinçon de trou +Bâche +Liant +Triant +Petit (jusqu'à 9.5x1pouce) +Moyen (9.5x1pouce à 13x19pouce) +Grand (13x19pouce et plus grand) +Taille faite sur commande +Arrêter +Traitant +Arrêté +Tout +Impair +Même Pages +Plus foncé Plus Lumineux +Dimension du medias +Sorte de medias +Source du medias +Orientation: +Verticale +Horizontal +État du travail +Nom du travail +Nom de l'utilisateur +Priorité +Copies +Grandeur du fichier +Imminent +Method de sortie +Resolution +400 Votre browser a envoyé une demande que ce serveur ne pouvait pas comprendre. +Ce serveur ne pouvait pas vérifier que vous êtes autoriséz à 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 ce serveur. +L'Uri de demande est trop grand pour ce serveur. +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 actuellement 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..d840a74f3f --- /dev/null +++ b/locale/it/cups_it @@ -0,0 +1,123 @@ +iso-8859-1 +Procedi +Annulla +Aiuto +Esci +Chiudi +Sì +No +Attivo +Inattivo +Salva +Scarta +Standard +Opzioni +Più Informazioni +Nero +Colore +Ciano +Fucsia +Giallo +Copyright 1993-1999 di Easy Software Products, tutti i diritti riservati. +Generale +Stampante +Opzioni per immagini +Opzioni per HP-GL/2 +Extra +Documento +Altro +Stampa delle pagine: +Intero Documento +Stampa intervallo: +Ordine inverso: +Formato della pagina: + 1-Up + 2-Up + 4-Up +Scaling dell'immagine: +Usa formato naturale dell'immagine +Zoom in percentuale +Zoom in PPI +Immagine riflessa: +Saturazione del colore: +Tonalità del colore: +Adatta alla pagina: +Ombreggiatura: +Larghezza della penna: +Correzione Gamma: +Luminosità: +Aggiungi +Cancella +Modifica +URI della stampante +Nome della stampante +Collocazione della stampante +Informazioni sulla stampante +Produttore e modello della stampante +URI Del Dispositivo +Preparazione della pagina +Stampa della Pagina +Inizializzazione Stampante +Condizione della stampante +Sto accettando le richieste di stampa +Non sto accettando le richieste di stampa +Richieste di stampa +Codice categoria +Locale +Remoto +Fronte-retro +Sto cucendo con punti metallici +Copie veloci +Copie fascicolate +Perforazione delle pagine (per fascicolatura) +Inserendo copertina +Applicando fascicolatura +Ordinando +Piccolo (fino a 9.5x1în) +Medio (9.5x1în - 13x19in) +Grande (13x19in e più grande) +Formato personalizzato +Idle +Elaborando +Arrestato +Tutto +Dispari +Pagine pari +Più Scuro Più Luminoso +Formato del supporto +Tipo del supporto +Sorgente del supporto +Orientamento: +Verticale +Orizzontale +Job State +Job Name +User Name +Priorita' +Copie +Dimensioni del file +In attesa +Output Mode +Risoluzione +400 Il vostro browser ha trasmesso una richiesta che questo server non ha capito +Questo server non ha potuto verificare che siete autorizzati ad accedere alla risorsa. +Dovete pagare accedere a questo server. +Non avete il permesso di accedere alla risorsa richiesta su questo server. +La risorsa chiesta non è stata trovata su questo server. +Il metodo richiesto non è consentito con la risorsa desiderata. +Una rappresentazione adatta per la risorsa non è stata trovata su questo server. +Non avete il permesso utilizzare questo server come proxy. +La richiesta ha impiegato troppo tempo per essere completata ed è stata abbandonata. +La risorsa chiesta ha più di un valore. +La risorsa chiesta non e' piu' disponibile e non è stata ancora rimpiazzata. +Il metodo chiesto richiede un campo "Content-Length" valido. +I prerequisiti per la richiesta non sono soddisfatti. +La richiesta è troppo grande per essere elaborata da questo server. +L'URI della richiesta è troppo grande per essere elaborato da questo server. +Il formato della richiesta non è capito da questo server. +500 Il server ha rilevato un errore non recuperabile e non può elaborare la vostra richiesta. +Il metodo chiesto non è implementato da questo server. +Il proxy server ha ricevuto una risposta non valida da un server di livello superiore. +La risorsa chiesta è attualmente non disponibile su questo server. +Il proxy server ha impiegato troppo tempo per rispondere a questo server. +Questo server non supporta la versione 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..db4f6799bc --- /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 lp.1 lpq.1 lprm.1 lpr.1 lpstat.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..071cc9f6fe --- /dev/null +++ b/man/accept.8 @@ -0,0 +1,57 @@ +.\" +.\" "$Id: accept.8 680 1999-09-22 20:06:43Z 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" "22 September 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 +\fIaccept\fR instructs the printing system to accept print jobs to the +specified destinations. +.LP +\fIreject\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 \fIaccept\fR and \fIreject\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 Administrators Manual +.SH COPYRIGHT +Copyright 1993-1999 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: accept.8 680 1999-09-22 20:06:43Z mike $". +.\" diff --git a/man/accept.z b/man/accept.z new file mode 100644 index 0000000000000000000000000000000000000000..1365c3fc11fe89e4660191c909a4f18cb5dde5a4 GIT binary patch literal 908 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 K|0A@jfdc?Xqy*0Z literal 0 Hc-jL100001 diff --git a/man/cupsd.8 b/man/cupsd.8 new file mode 100644 index 0000000000..36db0ce165 --- /dev/null +++ b/man/cupsd.8 @@ -0,0 +1,48 @@ +.\" +.\" "$Id: cupsd.8 814 1999-12-14 20:46:19Z 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" "22 September 1999" "Easy Software Products" +.SH NAME +cupsd \- common unix printing system daemon +.SH SYNOPSIS +.B cupsd +.I [ \-c config-file ] +.SH DESCRIPTION +\fIcupsd\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/cupsd.conf\fR) will be used. +.SH COMPATIBILITY +\fIcupsd\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 +backend(1), classes.conf(5), cupsd.conf(5), filter(1), mime.convs(5), +mime.types(5), printers.conf(5), +CUPS Software Administrators Manual, +CUPS Interface Design Description +.SH COPYRIGHT +Copyright 1993-1999 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: cupsd.8 814 1999-12-14 20:46:19Z mike $". +.\" diff --git a/man/cupsd.conf.5 b/man/cupsd.conf.5 new file mode 100644 index 0000000000..084b2b4ce6 --- /dev/null +++ b/man/cupsd.conf.5 @@ -0,0 +1,37 @@ +.\" +.\" "$Id: cupsd.conf.5 680 1999-09-22 20:06:43Z 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" "22 September 1999" "Easy Software Products" +.SH NAME +cupsd.conf \- server configuration file for cups +.SH DESCRIPTION +The \fIcupsd.conf\fR file configures the CUPS scheduler, \fIcupsd(8)\fR. +.SH SEE ALSO +classes.conf(5), cupsd(8), mime.convs(5), mime.types(5), printers.conf(5), +CUPS Software Administrators Manual, +CUPS Interface Design Description +.SH COPYRIGHT +Copyright 1993-1999 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: cupsd.conf.5 680 1999-09-22 20:06:43Z mike $". +.\" diff --git a/man/cupsd.conf.z b/man/cupsd.conf.z new file mode 100644 index 0000000000000000000000000000000000000000..67a0c61d04356ed7661d9fe3ea95cd40e38b3194 GIT binary patch literal 504 zc-oVfV_;x9!NtJHz{JTd$i~i~z`+%toSK=JUsPP8=j<8~oS2f9TTrT@sbgqr>FDX_ z9~2Uro{>{&uDR<3K|?%@*=X}o)z){=?36RI3t+W!AP>*QMeV9KF@?&8HPp(#)Q z|2rBoNp%yyhsK2KWoB*N3lpyJ}QLg{gXqvu0g#W)&KvN9KE!9sd!MV(k`xDjC#%DWwmm- zQn}JVmqanmckf$x{r_(+MNKnTup1A41A2vviAVl&QLgTU3YVr%FjFrzBnQZp`~N>k zujaO-*a=&OMb7M>Ip);QXIUoH68-3+@A;DDBI+Ec4^F6BA;Mq(e}>EBkNvZgCh_EP z-L#neA?)PDqRA!lWvLQY?XvESFZk@*dloiWF*a&&ICaGTf9B}4u~4b_2$u*0gA134 zHoNw$magXqHCq;nJ$K_+b@GIr&O(2=M=sB`|Np5@xzS=O^bQ+%BOq+M%6Db+Hj755 g*2)RK7WPUe3DQ=2HFrKmK20@S{vQY)>AhhD05W~xng9R* literal 0 Hc-jL100001 diff --git a/man/cupsd.z b/man/cupsd.z new file mode 100644 index 0000000000000000000000000000000000000000..fdc632d784a5023a17dbac615cdab74920d0540e GIT binary patch literal 903 zc-oVfV_;zQpE*aB}yEFpiEbtjONI`D%~{2UF+&|NlSfOssjKZ1Bx> z=f)P6Ixza>?#xRAu$;WN+9qPh6xPctoQilvUDA+HK0Bw!oGbGqqIf|F7$h)!G$U zs(MN8WzA{xiBD%Wtu(VT=r=lh!qMcxADxK}b8di~@mzeu?*IRCebQ3Ct1a^NT|Z}A zmh1W1^TH=q`mTJqW^%yQApU2OJNsuR>HYs-o&M}7NbYQpI`e}G>-ln0Uf3V&VeI)V zc%P5U_d?A!*X{rROv!xbde*u5=d`>UVc&j-D8K5;Y1u$tb70a+|MSfk3qz9*mjC~A zm;INX=RU6p)7 zs6}H$3i&$RF@MW3p*1zzn#=ZR+I z=^lB$F0*FGTjqG`aeUUf-|gTUE4J{NREEaI2K$uf;%uwUPW}I%eBr_3q?5b&C!9B` z7MfxX36UL|=8kW?n|iy|Uf54gum9hB76s?H@Cs@D|L=QpOX7!$k``u8(Pd9=8Kqvy0WnvK+vWDOK@_iPh+LlTDA~RL z|KXcrk1qgiUoPe+I8EsIsw1r_OlPePKj#D{zCCzbU9^txro6ZYF!E+E_`ONQVXm-Q zFVBJltGJAMm@mi(Iy6lQ`u|^%mHX&XZ~tR`G7Q~P76ori_PI{dpUaXacVfGlfn)G< z#fUGH4$TSK^0fYctC?>{ae!nw3MgY?N;mb~YH;m1Q1^R9mdni_Hn}ksCp|xVUVBbl Pa27C6{Qqb6?f?e>f0UnF literal 0 Hc-jL100001 diff --git a/man/enable.8 b/man/enable.8 new file mode 100644 index 0000000000..73cea8f63a --- /dev/null +++ b/man/enable.8 @@ -0,0 +1,64 @@ +.\" +.\" "$Id: enable.8 814 1999-12-14 20:46:19Z mike $" +.\" +.\" enable/disable 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 enable 8 "Common UNIX Printing System" "22 September 1999" "Easy Software Products" +.SH NAME +disable, enable \- stop/start printers and classes +.SH SYNOPSIS +.B disable +[ \-c ] [ -h +.I server +] [ \-r [ +.I reason +] ] destination(s) +.br +.B enable +destination(s) +.SH DESCRIPTION +\fIenable\fR starts the named printers or classes. +.LP +\fIdisable\fR stops the named printers or classes. The following options may +be used: +.TP 5 +\-c +.br +Cancels all jobs on the named destination. +.TP 5 +\-r [ \fIreason\fR ] +.br +Sets the message associated with the stopped state. If no reason is specified +then the message is set to "Reason Unknown". +.SH COMPATIBILITY +The CUPS versions of \fIdisable\fR and \fIenable\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 +accept(8), cancel(1), lp(1), lpadmin(8), lpstat(1), reject(8), +CUPS Software Administrators Manual +.SH COPYRIGHT +Copyright 1993-1999 by Easy Software Products, All Rights Reserved. + +.\" +.\" End of "$Id: enable.8 814 1999-12-14 20:46:19Z mike $". +.\" diff --git a/man/enable.z b/man/enable.z new file mode 100644 index 0000000000000000000000000000000000000000..bffd076d455c9270ea89146f436eb991dcdb2a80 GIT binary patch literal 940 zc-jH115^AT9smFZ!V3Ta00RgJ4-Ewf0w4%wa|&N!X>MtuWN2({a40D)IYC23 zNl#EzW@mMIEG{uPOifNwSzBFpcOo)JNL4dBLPTn7adC816#rGGc04^+q zbl}%Up?e&DaxA;6QjC)WWHc^9$jK5?NXamSkTOhH|L4i=mfYJVhRLYPH8tVhEbkA) zv1n_XT+-$Xkp;~zVTa+^xMAAn3z}T9b8DBbU5DZM^>J&MEnok|uW*|bum9?4(&kGI zlTnmvYd)?mb0XKcO^Q;0Spi4L^CZF2I5I;BNdi(xoRc9W2+0t+3s?W^nq0YZ#mTFb zS2f&O2;USda}uNU;MYc>d*PgmF6zOQum9I4u3EXZ%NHiDQC!z?dUwSN+{CE;I5p9z zUifDs%et^{CWU!NqKm{utN-@6uJq#9y7ZV|HnP`8fNEF&;?7t9|M=!O>PGe=jsrZ~ z-tH(?<|Rkx)y1x4TK5AfU;m4S9j;)xrOOvKxq9W;dcXhw%&6bR3iPV&g==No&TAt_ z;w_3CP_E+i)1&)~BS6ak|NkIUbNEv&?%RE*M>L~o{wPzpp;}dT!nL;hsQg~9|NrnP zWisCE65t)r5pWb4N*yDJ$q=auB_xK((sE3MkO3qFAtVB1B!rMBB*SDiU;mRryl^Cu zo*_`Sz1O^^xjk~#&8}FvHFApPwmAKBOP4NKxixZ%=Cqh!Wq|xpthLk?|M^G5W40W1 zUFovyMesj9lcyfn72fZP73smQi(FUiy~dJP|K~l$8dS6y7QMjVlR>xVw4q9c`A9u3 zC{|&6jU|8_LZNMYtzZ9$pwp1yKtX20xS?Dg_~ovl#r**^acI{RD(gAvB*!0M%2ASF z`5rz;<78+|gqbE0k}CiGhaE}8NI;-pIgUD!5)LRA^ivWJC>QioVd*u(LInc;igy-7 zNI0NXfBy;rsOX6Z6bp_7k~1;oA|l9EH1wM0++fJQ7lkp!n2MA-M-h@Fq>yZehDc!v zAP0~*B0&V?n!o=X^vl7eP>+L*7y%0h7%*mOe0wauW6DHDkgSv*d1IqsxYSX@8dV6| zzyA!Ys0dNu%2Jf2DN0h5r722Ml%*&P2F#@6NgGhX#ta$bo{~>?2@4h! OaiqWh|Ns0QN>BsjgT{CO literal 0 Hc-jL100001 diff --git a/man/filter.1 b/man/filter.1 new file mode 100644 index 0000000000..4928064b52 --- /dev/null +++ b/man/filter.1 @@ -0,0 +1,108 @@ +.\" +.\" "$Id: filter.1 680 1999-09-22 20:06:43Z 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" "22 September 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 +CONTENT_TYPE +.br +The MIME type associated with the file (e.g. application/postscript). +.TP 5 +DEVICE_URI +.br +The device-uri associated with the printer. +.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 +PRINTER +.br +The name of the printer; this is provided for shell scripts which may not be +able to get the passed argv[0] string. +.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. +.TP 5 +USER +.br +The user executing the filter (typically lp). +.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 Administrators Manual, +CUPS Interface Design Description +.SH COPYRIGHT +Copyright 1993-1999 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: filter.1 680 1999-09-22 20:06:43Z mike $". +.\" diff --git a/man/filter.z b/man/filter.z new file mode 100644 index 0000000000000000000000000000000000000000..c26f974a1960100355ad3fa74ee1a4a38817df88 GIT binary patch literal 1862 zc-l==c{tl!8V(U6MJz!Yl3H4#VySIHTM~OquLL)>RRygGu}#x!opK|sHP=!d)RdsN zxmAp!j2oURK^IG1gNs(_&>2nD*7^ulaxlZq`G;W`Oc5#9~r~FYG!f5@!a=}i$9QT z$nM_0!Kv1+o?f9B;;d}#&j*Dhr#qcwSC!Asi;&7n0DvJ&vla0kI?UWqsfITH698Y< zIa3M>ycZ)YY8WAveF!Tom%UjR?KrfDFLxr_HpZh8gl#jl)0d|%`_LmKa3x~WHrk*b zA!@si3n{DxI%BwpoRVGR=yk&^=NT(S z?>lqNNrwv96FXykRBdWk4lTLUL-#84zydp9pp>WW$|c;PAzV#@FDIIQX6 zx$tRDEOjM_>vd5tR1l{2vWfaGrcVp}cg#^>I#_?kS@+K8gu4BA)pQ(pr}}%sVxfvb zP)+2h+v(z-TyQY5+I*~xljvf@q&H`n21gV#K@s+6x((;GoNSLKM@7 zY}up!P~DYfGa*VlzEwAT0sqbh!|8O%GzD9g75KL4uL)T~nv{_FPuvWvuJ@BXeB9Bw z@l1^i`Bh+F2@2pfOT`tJzX9?|t1>w8jzdjHTt?r-FJOPBzF;BAEog0bz!~k;VP4!k zY^fBV;z3fa-YSpE|JYu+vFHL?dpu10ll++bL0r zp z-WFlWkKfAWD*8eG%wy=-kz!)+hP>6Smb}8>csTI^H69hG;d&;2y6haY2?;gWi&}t{ zWhR*P=LeCiYC*p-+_Mm?k9CiS9AC+gp)>TT2!qk&!qLbL!NBjVtNd@oK$(#@u)_|`w2o~eE`ZS>oj>&?x6x_x-EzVA5r7Xpida5mLj9J=(o@e>ZkX7L%l z$L0tbOIxZvyjzQB(WZ!o!w_7DZo0YOu`raBBSwZESI*W2lo%+>id#=Lgf{+4eeT&+ zJEvWe8Q&f;*lMWgw1zdQkH?m{L)G(yb*en9BomswMYW0OE06;zQg~#se#8@7*+>7u zn%>-V?T|)b8Pw9>@x)V2Y7OGufn~mZJJdoeVz9-Tz*BX58SIiaQck+E6(E&zpgLd zGj~3xX%DSQX|mTYe~?Sycv|HqD|nXVk*lgo$VV*8dfY4Alu;dVH% zRW1Om8io<}#-fSynOd)}vCiXiLZpH{C%`M^JTwl=62ey+LKdzvggU3^3yjVR#Rn5D z_VS%79zU0>hKAHYSkg5hudFH0lMd%&w5;et8&1xOE1i>KO0$&QC4P~yEE4QJ<)rxX zu7$vKPW#T#D>seU#sS9ky-tHfjdxGHTTBqu7+PJ&gT zLG-~yCpy2?MYYtWk2aTXh8Ore(&VIOSfHg$EVY9@*&@q4$J6Z2>HX`{dR*29J2m4C zVrjkOr0c`qiYLkO-~iHf`*s+V)0_MO^?LOl)RE#>S?z1jVP^?L@myFw*x$Z=5t6xe zV0QY;@k!pZzptGD6mC5toWg?~_l^SmG@A_RP?|OE8F7|y?{>nYQM##TlA8l)(_&?4{c+vm> literal 0 Hc-jL100001 diff --git a/man/lp.1 b/man/lp.1 new file mode 100644 index 0000000000..d62e5812dc --- /dev/null +++ b/man/lp.1 @@ -0,0 +1,111 @@ +.\" +.\" "$Id: lp.1 814 1999-12-14 20:46:19Z 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" "9 September 1999" "Easy Software Products" +.SH NAME +lp \- print files +.br +cancel \- cancel jobs +.SH SYNOPSIS +.B lp +[ \-c ] [ \-d +.I destination +] [ -h +.I server +] [ \-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 OPTIONS +The following options are recognized by \fBlp\fR: +.TP 5 +\-d \fIdestination\fR +.br +Prints files to the named printer. +.TP 5 +\-h \fIhostname\fR +.br +Specifies the print server hostname. The default is "localhost" or the value +of the CUPS_SERVER environment variable. +.TP 5 +\-m +.br +Send email when the job is completed (ignored in CUPS 1.0.) +.TP 5 +\-n \fIcopies\fR +.br +Sets the number of copies to print from 1 to 100. +.TP 5 +\-o \fIoption\fR +.br +Sets a job option. +.TP 5 +\-p/q \fIpriority\fR +.br +Sets the job priority from 1 (lowest) to 100 (highest). The default priority +is 50. +.TP 5 +\-s +.br +Do not report the resulting job IDs (silent mode.) +.TP 5 +\-t \fIname\fR +.br +Sets the job name. +.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. +.LP +The "m" option is not functional in CUPS 1.0. +.SH SEE ALSO +lpstat(1), +CUPS Software Users Manual +.SH COPYRIGHT +Copyright 1993-1999 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: lp.1 814 1999-12-14 20:46:19Z mike $". +.\" diff --git a/man/lp.z b/man/lp.z new file mode 100644 index 0000000000000000000000000000000000000000..878412447890b61d45ae61169009566d3041124b GIT binary patch literal 1464 zc-nPTe>~G^9G}K)HrwRKUXE}$`4#hPhm)9Oo$wt?mN=6iks-fotFV{G`H@S7NyQY# zsiVb2x=px3s9U{uTxwp@-8x~DQm*fPSNGSwUibX*yq?eVc|Y&Z=kt8t&tq-|gP~4i zU>Yz@1QLhQ*4BbqAa%Y=Oi9nk%Ffvq!8mv*jhX4>;uR3MI}D&j$HXTjv25*#{-NP} zlT&l^j#@gBckT(HI|orBqmCSNb@T9MAFewefiS><&^YZitcs$~Z6zsn8Gveb3EEm! z``o?+4D>ZD1X{WrA^6^IA*DMwpH7)+1yvLDwaO&cnD4{8JnFADlEz*wt{?EujEpov zRB}cn5Smz)*>F~cQ|1Q~e*z+#6kCAzT$)p(qC{%XuSVaW7vdFLsJXfVyr8dmUP&)a zP}0jAKm`FX2de$6wWY3nZ!Rq+;0C=yVGLXfP#6NETs5vRE(kJHA+s1_dZVReIlIh; z-Dmv(9X1ErOQcp*mQO9PpT8F=jq&pcXxC6?gX_zzsVsT2*qb{%N; z-(N1sRY&S8YKN$bY0g{EDs-eV0qvO2R%@I#)!byJ#Om&zPR3-3{zFj z$)?xhYA;1pdOb}fAGekJ2BO~=*<;si-nisjUZpmGGbu!}swxP}2ui##B;p@GCzR47 z_c^4qYqF)orFG`;d;XhaP7St)ngpsM)JZI{34cO@cy)*?@~>o1d^Rk#7Jh<{8xh&G-=tQZv5b)9ui}$-`AL?23}H=pKbuVyiQbea4t8Y9 zQy*3}Hp)KbxMvcCx~+4D5T6l2Xq%R8bh0PeJYkjeb{qqK zgiO{PA1{A!^I3{P&m6a$@NUHV9HCeXtD)2lpKUH)sLftq+af2N7dZpF# z&SA9A&V^b34tulXPob@kYTrVF%soxl1fI!5X^O37?k8{!;KPtfujhjtu?*7FLZ@&j zlqs+5>DMytR8`d(!?ndqydMG9*^Ax+FQjO|qBJNHV{qf3zSCnw;|9X;g2q**28j6 YK;a4K`Lr=^HUIu0SY3}8GhT@N2ZN@^MgRZ+ literal 0 Hc-jL100001 diff --git a/man/lpadmin.8 b/man/lpadmin.8 new file mode 100644 index 0000000000..a6a33904b3 --- /dev/null +++ b/man/lpadmin.8 @@ -0,0 +1,124 @@ +.\" +.\" "$Id: lpadmin.8 680 1999-09-22 20:06:43Z 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 September 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 +\fIlpadmin\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 and accepts jobs; 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 \fIlpadmin\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 \fIlpadmin\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 Administrators Manual +.SH COPYRIGHT +Copyright 1993-1999 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: lpadmin.8 680 1999-09-22 20:06:43Z mike $". +.\" diff --git a/man/lpadmin.z b/man/lpadmin.z new file mode 100644 index 0000000000000000000000000000000000000000..f9cae34fa112a4d9ba631af223f35eeead49b77b GIT binary patch literal 2522 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 VyAr7@bhv!-&*SfT{W=N({RMp3&LjW; literal 0 Hc-jL100001 diff --git a/man/lpc.8 b/man/lpc.8 new file mode 100644 index 0000000000..0280d528ba --- /dev/null +++ b/man/lpc.8 @@ -0,0 +1,79 @@ +.\" +.\" "$Id: lpc.8 680 1999-09-22 20:06:43Z 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" "22 September 1999" "Easy Software Products" +.SH NAME +lpc \- line printer control program +.SH SYNOPSIS +.B lpc +[ +.I command +[ +.I parameter(s) +] ] +.SH DESCRIPTION +\fIlpc\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 \fIlpc\fR program accepts a subset of commands accepted by the Berkeley +\fIlpc\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 \fIlpc\fR is geared towards the Berkeley printing system, it is impossible +to use \fIlpc\fR to configure printer or class queues provided by CUPS. To +configure printer or class queues you must use the \fIlpadmin(8)\fR command +or another CUPS-compatible client with that functionality. +.SH COMPATIBILITY +The CUPS version of \fIlpc\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 Administrators Manual +.SH COPYRIGHT +Copyright 1993-1999 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: lpc.8 680 1999-09-22 20:06:43Z mike $". +.\" diff --git a/man/lpc.z b/man/lpc.z new file mode 100644 index 0000000000000000000000000000000000000000..826de50e1aa4ef20c838cf0aa81ec178fd1a30f7 GIT binary patch literal 1263 zc-jH)1Q7cl9smFb^$P$200ImI4-E$c1Rw}y3SVJkX>4w9aB_2WQ)F#*C@Cy1K|@7J zPf%25XJ~mbI5|X2O-@o-VsUnNEkadWU2AwUM@Ta|KUiu)5ZEk8Ft7jr|MBXPe8-fS zilccbywle?fB*mf*epmeq#*%x7B+^3P*D0FkN?{R;61E$@QWQgj<>pTdw50VVxy3Q zD8Skc3!t(zM3oXUj3Gn}qY?l6X|Sj+mw~j>(@#wtnmIJ2)00NvZ8ZealTl46G;(Uw zQ%zcGDWNH;CWT;p4uk|yK>8kK7&?arP+nryH_dp=)7AS-aiLwd;AuDaL@> z$5_3vULwY|AOD)kL8>pSgkE$fsmAJB?i2OAPYDaOlE z*KnPihZjfx^DTH1;t00ceKge66HDP2m5PquQ<-bzqpxy~umXgC{+hJVB{am;(f|Mc zJQB&vnQPYbj#G`;>D*x(oy1}h|M_cdG|(9|wA0f^CXP)hH005#pgKSQ|H2t4HAUsC zk!QwvYiu*FQc+tNgn#}XdnS+n|MB3KPF%}gx14gEZpTjJ2;A-?5Rd=mHB9+wpfYGZ zG5~4$BX*woChyf@FLWl&=NeUoNiH6W>KmR6L{BRVJo*{9Q z9`AWiO*J(H()`!lw?2CggKX<`^)$pR87E_5Jk4j>v_j1#>iq2Wf(q( zkD>V58WTY#QG{rUKmStKaF~!`Lj7uT?V>?N3;fneLCvus!iE2CP;+cZFrk080zpL! zNB`}FM1qPJ`(YD=f{GXIgr=#91r#siU=r6cAi{X zi{?C}#8n%~MdqHl$X+$A@WvG_IV1n@%az1J%@~9s02l|EaGjhTalt{s!TfX1Iqtxr ZWB?vYEOgl7xrOCBJOBUx|G`j%08sCeYJ30y literal 0 Hc-jL100001 diff --git a/man/lpq.1 b/man/lpq.1 new file mode 100644 index 0000000000..ccbfd3cbbb --- /dev/null +++ b/man/lpq.1 @@ -0,0 +1,52 @@ +.\" +.\" "$Id: lpq.1 797 1999-12-07 19:04:57Z mike $" +.\" +.\" lpq 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 lpq 1 "Common UNIX Printing System" "7 December 1999" "Easy Software Products" +.SH NAME +lpq \- show printer queue status +.SH SYNOPSIS +.B lpq +[ \-P +.I dest +] [ \-l ] [ +.I +interval +] +.SH DESCRIPTION +\fIlpq\fR shows the current print queue status on the named printer. +Jobs queued on the default destination will be shown if no printer or +class is specified on the command-line. +.LP +The \fIinterval\fR option allows you to continuously report the jobs +in the queue until the queue is empty; the list of jobs is show one +every \fIinterval\fR seconds. +.LP +The \fI-l\fR option requests a more verbose reporting format. +.SH SEE ALSO +cancel(1), lp(1), lpr(1), lprm(1), lpstat(1) +.br +CUPS Software Users Manual +.SH COPYRIGHT +Copyright 1993-1999 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: lpq.1 797 1999-12-07 19:04:57Z mike $". +.\" diff --git a/man/lpq.z b/man/lpq.z new file mode 100644 index 0000000000000000000000000000000000000000..c68fbed280b141841a9c15662257c18d8b73de8d GIT binary patch literal 709 zc-jHQ0y_O49smFYI0^s(00RgH6$%9eAP5R&UukS^Z*p^VQ(a|LDDKjl37YM-+yVcAb{o-Y8yL%buGfmbgW2J}Yy4(%8=_ zb^rVjai;pq?RJaS*xUC%D#PIoaNv!VS#{ZM&EkdSTwuZNEGEDIV%uP~U;mRr^-9$( zRK-(jm#R#vPgJvVFh3O}0-ne#Q7@Gk2p?eny?k`{ef!tCW;lT$Q+}rHUyxyr=rK*^!ZBq3~l}YNB zaI&sxXad!L{!I(jB2_Hhj8^9Fw3E0-8Tp4k^EUF1h3~Xn_^qM2cRa!I1*$qu8zV-@ z+!{fEvIRO$AtWpR@~5<|usERrn-LBuKqkaq98iEwh`hjYLIE}-2%iw*gjfIL0!W>l z;_)$+x1CSUJK!oI-fBrGZn|i}gjwo2L1W2J` z#pMm-Pl3GW7m1_ac^9~{Wn%zL8I1Bv4MH%l|H)h}=4`MnRaI40RaI40RaI40RaI40 r09ZYhvjr{qp<>1VjB$ewZW26j8zS|#D`;+UxJJx>|NsB^s;U7%hk#5A literal 0 Hc-jL100001 diff --git a/man/lpr.1 b/man/lpr.1 new file mode 100644 index 0000000000..5d06283ef0 --- /dev/null +++ b/man/lpr.1 @@ -0,0 +1,96 @@ +.\" +.\" "$Id: lpr.1 660 1999-09-09 14:58:01Z 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" "9 September 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 a job option. +.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 Users Manual +.SH COPYRIGHT +Copyright 1993-1999 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: lpr.1 660 1999-09-09 14:58:01Z mike $". +.\" diff --git a/man/lpr.z b/man/lpr.z new file mode 100644 index 0000000000000000000000000000000000000000..f02ebd380a3d8ed368214efc9885b0f052480a56 GIT binary patch literal 1448 zc-oCrX;4#F6lMtt1W<}0EX5eHAW)W|P)kGtktJ$aBOyRg5)lM~q!17osYxVASPG7U z4+dn4$TBQL1mf6Y3jv&>D8>k7X)9_~%n%0&0)poDWzhcXOy7_D?wq;joNqbz?!f8j z82w|m=@ciOYv88UG9WEvq#ujRU>XP$%!w#7AtIr8-qsgYG{6Cxv$!(5`JAPu%J^Sl(CS!~rE9emW6ig3 z2%Bnhyx*~)9PLA3hIRw>c3c=raft4K*wN>!6+lFaL0vCxrv3V-9ICOf@lWu$w1Dro>@Y;=IifcIA(kNT75V z>~JItF%kyA`|OMbUDLr1>^ID_Tz^6*fnd9!`(n}f<84K`!f}#3i|QPDo3?kS zH?RB=qHXG7Wo3hGMrfLZHnl}2+Dc=mXfA=P6qpcLo38mEuL|r0ItweS#jLhoPuu6b zPDmW(G7^zUza$G?zg+z*1{DG|c<)81$8GV%)ARAq$p*=d8&T)W4J|~%V#{g;$3L_K zv!1m`hN6PUL<5X99NAEB4r|1x%-bRc%nkf7L5AbtX?j55J;&@d7_W}YDGDW&5^O>n z&YVdvcABWva{B9Qw9g0g8yDhUfyEHtI@4=N>ezpLg)biMqnNjxAd|`Gj8hH0AV*KG VHGJ37SX2r8NNBmud5-bJ{{hZu+bIA5 literal 0 Hc-jL100001 diff --git a/man/lprm.1 b/man/lprm.1 new file mode 100644 index 0000000000..a8a9ff489d --- /dev/null +++ b/man/lprm.1 @@ -0,0 +1,51 @@ +.\" +.\" "$Id: lprm.1 680 1999-09-22 20:06:43Z 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" "22 September 1999" "Easy Software Products" +.SH NAME +lprm \- cancel print jobs +.SH SYNOPSIS +.B lprm +[ - ] [ -P +.I destination +] [ +.I job ID(s) +] +.SH DESCRIPTION +\fBlprm\fR cancels print jobs that have been queued for printing. The \fI-P\fR +option specifies the destination printer or class. +.LP +If no arguments are supplied, the current job on the default destination is +cancelled. You can specify one or more job ID numbers to cancel those jobs, +or use the \fI\-\fR option to cancel all jobs. +.SH COMPATIBILITY +The CUPS version of \fIlprm\fR is compatible with the standard Berkeley +\fIlprm\fR command. +.SH SEE ALSO +cancel(1), lp(1), lpstat(1), lpr(1), +CUPS Software Users Manual +.SH COPYRIGHT +Copyright 1993-1999 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: lprm.1 680 1999-09-22 20:06:43Z mike $". +.\" diff --git a/man/lprm.z b/man/lprm.z new file mode 100644 index 0000000000000000000000000000000000000000..343996dd9d69187e80115f2d2351750f69fa259f GIT binary patch literal 748 zc-jH%0u%io9smFYZVLbb00RgI6AA_c03ZkoWnW=zZf|mPbV*QCV`*)0C@Cy0F*!j) zMNUstSz=^nXmxomL`+RmRa<9jcQQgpNL_X_SZi^rrY7`*ixL0-|M>O5&U=eQHE+D< zxT%CA5C8xFVsA(|u@zK8NDYyo@(w;n*Z=HI>0-1N)GeBCMX|#iQWZzZEq@OZ-dU!YgT2ysdx!1Gj*7%QLE2sZCP#N?Hy{CA6p|QSx~C9zI9oWN0*l zA19HLHUIhxY8Jra#0mB$99V%q#NidhII#kDCh+3K3C9GSetU~VHE+Bo7Wh~H;Ol9H zvZ!>9BP33fiODdD2sTXuNDvDkQc_C4{~YAZy%4hT#f%sLiWV?n%%Plm;AcI>q8hi} zbKF$I5rCX)8Q}9ssJE%En?yT literal 0 Hc-jL100001 diff --git a/man/lpstat.1 b/man/lpstat.1 new file mode 100644 index 0000000000..cf33579bd8 --- /dev/null +++ b/man/lpstat.1 @@ -0,0 +1,115 @@ +.\" +.\" "$Id: lpstat.1 680 1999-09-22 20:06:43Z mike $" +.\" +.\" lpstat 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 lpstat 1 "Common UNIX Printing System" "22 September 1999" "Easy Software Products" +.SH NAME +lpstat \- print cups status information +.SH SYNOPSIS +.B lpstat +[ -a [ +.I destination(s) +] ] [ -c [ +.I class(es) +] ] [ -d ] [ -h +.I server +] [ -o [ +.I destination(s) +] ] [ -p [ +.I printer(s) +] ] [ -r ] [ -s ] [ -t ] [ -u [ +.I user(s) +] ] [ -v [ +.I printer(s) +] ] +.SH DESCRIPTION +\fBlpstat\fR displays status information about the current classes, jobs, and +printers. When run with no arguments, \fBlpstat\fR will list jobs queued by +the user. Other options include: +.TP 5 +\-a [\fIprinter(s)\fR] +.br +Shows the accepting state of printer queues. If no printers are +specified then all printers are listed. +.TP 5 +\-c [\fIclass(es)\fR] +.br +Shows the printer classes and the printers that belong to them. If no +classes are specified then all classes are listed. +.TP 5 +\-d +.br +Shows the current default destination. +.TP 5 +\-h \fIserver\fR +.br +Specifies the CUPS server to communicate with. +.TP 5 +\-o [\fIdestination(s)\fR] +.br +Shows the jobs queue on the specified destinations. If no destinations are +specified all jobs are shown. +.TP 5 +\-p [\fIprinter(s)\fR] +.br +Shows the printers and whether or not they are enabled for printing. If +no printers are specified then all printers are listed. +.TP 5 +\-r +.br +Shows whether or not the CUPS server is running. +.TP 5 +\-s +.br +Shows a status summary, including the system default destination, a +list of classes and their member printers, and a list of printers and +their associated devices. This is equivalent to using the "-d", "-c", +and "-p" options. +.TP 5 +\-t +.br +Shows all status information. This is equivalent to using the "-r", +"-d", "-c", "-d", "-v", "-a", "-p", and "-o" options. +.TP 5 +\-u [\fIuser(s)\fR] +.br +Shows a list of print jobs queued by the specified users. If no users +are specified, lists the jobs queued by the current user. +.TP 5 +\-v [\fIprinter(s)\fR] +.br +Shows the printers and what device they are attached to. If no printers +are specified then all printers are listed. +.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. +.LP +The "-h" option is not a standard System V option. +.SH SEE ALSO +cancel(1), lp(1), +CUPS Software Users Manual +.SH COPYRIGHT +Copyright 1993-1999 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: lpstat.1 680 1999-09-22 20:06:43Z mike $". +.\" diff --git a/man/lpstat.z b/man/lpstat.z new file mode 100644 index 0000000000000000000000000000000000000000..814cf0871e9361fb168b556e3426e55b3f820565 GIT binary patch literal 1980 zc-nQ9e>_wBAIIm{&?b@}S%ie%}6k0HoMIe5%`_lu5PT>wllPIZ%(GB68bO?Iq%qBZ_J6w3~K62;j z-Zlt=Jl6?Fo$xqHK33&yxh(<~_+KO$nyxs|-Zyx9b4qqa2>mr`bZC8w;TZa9)g6b8 zFi@Bgj*ZdTiZD?_oE?T%=2P`DeGk)LoHXY3h3=rD1Vz3W$H4D>Xb393A~y?z62PgH zax=59dybm$L~x8Q)iH>aOI5>I2az~mobldL$V`XKczrvlluDW|RjbxI5Hg$Ws5$k^ z|JCaG9oizZn7jzdD>QsWNUCcPGl%LKh!j-gy}y3*`&`ZB8wm~U7Yf9AJE)d|>fN=b zf7$pLTKJMB{nwjb-ll~dcUVOJro%?YD&eQp^0*n{QEW{lm)n4Xb6nCPFI|G3;QCjG zw@$nhQ#9+Yrh#mhu^DB)$vxY}rc-fqGm9He%bNMn51vW;2^|LGa>LoW7y^kcB?ydl13g%*|e{S9MQijC=+)0p}F8M7MKY7L!-mGyCpF78fc-IM>Q9uR^*$-T9VlX#(5S(N!E?pXvTDv)kD1_C6b}%!P7N>x(6dP*ZRe>zE&)KKeXbfxYbxn zYR4slxLQiAjB|CpG1jNCrZOqvQ#YdH#@E2Z%YFu`J@SfuSXtjamafy1C;&K>4E3y-SekA7 zzy(3r^kd50_4m}wG6LpiB9}z&54TP|1r|#z9bBS9(TVm)6A->W4Tc3daDY(VBhRfIX`)sVV_TT*buxh z_PQ6mwWdSXx7QD<^!*HI)hR@CYQlON-&mVlQ2=D(VV1S~nmVPBb3Y{^vsZ8B zjGn&!#uq0nefv9M5uDAaWw+5M$lKuTKpE=NFRZqE|9Jx`tZr)i_|k-te_UzwGp0=l zkSxoj&uuc_Vn>E#AMyVFjX^GJyTD=jsz@$}2o~-jTAKsFkK8{@ePOvWwR*xNAJiywz`1SgdglAASTL5on;!v4}qu1FwM=jfSn}!#S+rS8D2N zN_&r32&t?$ypX+p!Y!p!@i?mV~r8+GpZdT>-CjN<^S7)0}-u4mls4fxqERRVs) zE)@$4_mrLg`};G@G)?D@nkNmVLu&ndx{o|L4%n);`{#lW-`Pr-%KqY>mbSL`e9H#Q am*X6#`#R@OZ;pvNrwC9%+c>t`9R4SOSj>O` literal 0 Hc-jL100001 diff --git a/man/mime.convs.5 b/man/mime.convs.5 new file mode 100644 index 0000000000..f047059b04 --- /dev/null +++ b/man/mime.convs.5 @@ -0,0 +1,43 @@ +.\" +.\" "$Id: mime.convs.5 680 1999-09-22 20:06:43Z 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" "22 September 1999" "Easy Software Products" +.SH NAME +mime.convs \- mime type conversion file for cups +.SH DESCRIPTION +The \fImime.convs\fR file defines the filters that are available for +converting files from one format to another. The standard filters +support text, PDF, PostScript, HP-GL/2, and many types of image files. +.LP +Additional filters can be added to the \fImime.convs\fR file or to +other files in the configuration directory (\fB/var/cups/conf\fR) with +the extension ".convs". +.SH SEE ALSO +classes.conf(5), cupsd(8), cupsd.conf(5), mime.types(5), printers.conf(5), +CUPS Software Administrators Manual, +CUPS Interface Design Description +.SH COPYRIGHT +Copyright 1993-1999 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: mime.convs.5 680 1999-09-22 20:06:43Z mike $". +.\" diff --git a/man/mime.convs.z b/man/mime.convs.z new file mode 100644 index 0000000000000000000000000000000000000000..5b73f2c73a1d5de9e0cba82bd428c703b80a236b GIT binary patch literal 723 zc-jHe0xbO>9smFYF$(|z00RgJ5DW$b03ZkoWnp7!Zf|mPbS_h0WM*t_a40D(FEu$q zLq$nYXJ~bHc`Y$AL`P0fQdCu9cOpnkO<8y|I9Nuiq?nbMw=}c_3={wVkW>rixd?}; z_mX>$D!9Y{{U#-5EzKK7lE+Lm7>(!J3~j@SOVDC5x5J4=M^o=nWib^8BX$4!4t}>ZwZ1HAJq9Ci(0h{H z+t72;RCv2nT@se_Fv6F@DrhBt{(7E&pu}Tuhrp_7x$)y*c#6pbfB{)2LME;3P9m@w zAV7d1uwh!7eSiLvnqP@@?i-NUl8N4f5x5yu|M=t2WLV~@9R?#Cd^M@Kb?Q9(Ka04O zyy-~kVbYP)XGw=j&X*l6I!hfe&|)|4eSiNKf4U_t|DeQfAF;p0rT(`y1`{gvMUHRh zvG%yResaC?H@#Nx*`sCwXF}Xx|>>l5=p-k{}*Q>}*)ld8OeSOaK4>|G{dg F0Du(DOO*fs literal 0 Hc-jL100001 diff --git a/man/mime.types.5 b/man/mime.types.5 new file mode 100644 index 0000000000..31a99e4b93 --- /dev/null +++ b/man/mime.types.5 @@ -0,0 +1,40 @@ +.\" +.\" "$Id: mime.types.5 680 1999-09-22 20:06:43Z mike $" +.\" +.\" mime.types 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.types 5 "Common UNIX Printing System" "22 September 1999" "Easy Software Products" +.SH NAME +mime.types \- mime type description file for cups +.SH DESCRIPTION +The \fImime.types\fR file defines the recognized file types. +.LP +Additional file types can be added to \fImime.types\fR or in additional files +in the configuration directory \fB/var/cups/conf\fR with the extension ".types". +.SH SEE ALSO +classes.conf(5), cupsd(8), cupsd.conf(5), mime.convs(5), printers.conf(5), +CUPS Software Administrators Manual, +CUPS Interface Design Description +.SH COPYRIGHT +Copyright 1993-1999 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: mime.types.5 680 1999-09-22 20:06:43Z mike $". +.\" diff --git a/man/mime.types.z b/man/mime.types.z new file mode 100644 index 0000000000000000000000000000000000000000..01088e80e100cd227ceaee5a356a694245bf2135 GIT binary patch literal 621 zc-oVfV_;zJh%X_@O=PNs?6cd!_FR zp@r@Lf93d{?phVY+$|XDC?sI!)_lTpQfmFb*}|J1t(wlmx$MaMu2pfZ2lJCACeL1U zWWDS8YoQ*Y%pQi55;tYMl=1T9pZFxD!>6Tx;uDnymzMDV4^{Q8f~_J-mX+MR6nR;A zY4B3#W#?vOY}CH6CE|9w(DZ%R9_1!*W&j0%<}dVno9a8u@_#7SvpZcQozIkTKR!vDYa_~G;*>dqDCZUJ?me-&gHAv9FT zxASIpv9p3qM5F2dU;W9+`Hk7dfqXg+^JPR_?wg)CV)FfducMjigzod*^ZD6rm->77 z*8j86=-lz`*uBozd!!y5%00M_yIQ1M=GMYX7A+H$RUC~tRaM$gd@yNj_{7dRVb=dY z#ZyAxs0G<^86+^Uuu2%DiLFcg5Dqr`p6fe@RgW1hu1q>t<*Ji@eNHXD>t%m_wb2`G+wpj-mzo%nfZzXcvS5F_r`EP+sVzqr!DCo(y`>;GS_mX@yJu{`U{0%Fw_&uZopt9o?Y+_B?c z^ZYrH7NN`@1~;X0W*NB&O>$mRD5>P<**EcsO2be2`2Ul&tCpI2U)2fO8Z7F&DsE-d zlB1rdrfWs5bO!3KU2yD<#nipxGFwVO?&4Dom(Abx|8Jsqk~XK?nd9y$W;-olKugA9|Pm2Z9G%Ll_zW$wvb7 literal 0 Hc-jL100001 diff --git a/ppd/Makefile b/ppd/Makefile new file mode 100644 index 0000000000..675b199e4c --- /dev/null +++ b/ppd/Makefile @@ -0,0 +1,55 @@ +# +# "$Id$" +# +# PPD 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 + +# +# PPD files... +# + +FILES = deskjet.ppd laserjet.ppd + +# +# Make everything... +# + +all: + +# +# Clean all config and object files... +# + +clean: + +# +# Install files... +# + +install: + -$(MKDIR) $(DATADIR)/model + $(CP) $(FILES) $(DATADIR)/model + +# +# End of "$Id$". +# diff --git a/ppd/deskjet.ppd b/ppd/deskjet.ppd new file mode 100644 index 0000000000..cc712c3551 --- /dev/null +++ b/ppd/deskjet.ppd @@ -0,0 +1,186 @@ +*PPD-Adobe: "4.3" +*% +*% "$Id$" +*% +*% Sample HP DeskJet 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: "DESKJET.PPD" +*Manufacturer: "ESP" +*Product: "(CUPS v1.0)" +*cupsVersion: 1.0 +*cupsManualCopies: True +*cupsFilter: "application/vnd.cups-raster 0 rastertohp" +*ModelName: "HP DeskJet Series" +*ShortNickName: "HP DeskJet Series" +*NickName: "HP DeskJet Series CUPS v1.0" +*PSVersion: "(2017.000) 0" +*LanguageLevel: "2" +*ColorDevice: True +*DefaultColorSpace: RGB +*FileSystem: False +*Throughput: "1" +*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 +*UIConstraints: *Resolution 600dpi *ColorModel CMYK + +*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 *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..33881cabc6 --- /dev/null +++ b/pstoraster/gdevcups.c @@ -0,0 +1,2348 @@ +/* + * "$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 + + +/* + * Globals... + */ + +extern const char *cupsProfile; + + +/* + * 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, mk; /* Integral CMYK values */ + float 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 : + 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]; + + 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 : + 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]; + + 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)); + + mk = max(ic, max(im, iy)); + if (mk > ik) + ik = ik * ik / mk; + + ic = lut_rgb_color[ic - ik]; + im = lut_rgb_color[im - ik]; + iy = lut_rgb_color[iy - ik]; + 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)); + + mk = max(ic, max(im, iy)); + if (mk > ik) + ik = ik * ik / mk; + + ic = lut_rgb_color[ic - ik]; + im = lut_rgb_color[im - ik]; + iy = lut_rgb_color[iy - ik]; + 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)); + + 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)); + + mk = max(ic, max(im, iy)); + if (mk > ik) + ik = ik * ik / mk; + + ic = lut_rgb_color[ic - ik]; + im = lut_rgb_color[im - ik]; + iy = lut_rgb_color[iy - ik]; + 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 */ + float m[3][3]; /* Color correction matrix */ + 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 (cupsProfile && cups->header.cupsBitsPerColor == 8) + { + fprintf(stderr, "DEBUG: Using user-defined profile \"%s\"...\n", cupsProfile); + + if (sscanf(cupsProfile, "%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f", &d, &g, + m[0] + 0, m[0] + 1, m[0] + 2, + m[1] + 0, m[1] + 1, m[1] + 2, + m[2] + 0, m[2] + 1, m[2] + 2) != 11) + fputs("DEBUG: User-defined profile does not contain 11 integers!\n", stderr); + else + { + cupsHaveProfile = 1; + + d *= 0.001f; + g *= 0.001f; + m[0][0] *= 0.001f; + m[0][1] *= 0.001f; + m[0][2] *= 0.001f; + m[1][0] *= 0.001f; + m[1][1] *= 0.001f; + m[1][2] *= 0.001f; + m[2][0] *= 0.001f; + m[2][1] *= 0.001f; + m[2][2] *= 0.001f; + } + } + else 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; + + d = profile->density; + g = profile->gamma; + + memcpy(m, profile->matrix, sizeof(m)); + } + } + + if (cupsHaveProfile) + { + 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 * m[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 */ + } + + + 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..b7932d7239 --- /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%254s", &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 %