From 3624845d7b49c7a9ed2403d57e16ff92fb06c76d 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.1b1@4306 a1ca3aef-8c08-0410-bb20-df032aa958be --- CHANGES.txt | 263 + CREDITS.txt | 26 + LICENSE.html | 386 + Makedefs.in | 132 + Makefile | 94 + README.txt | 245 + backend/Makefile | 137 + backend/betest.c | 85 + backend/ipp.c | 668 + backend/lpd.c | 414 + backend/parallel.c | 515 + backend/serial.c | 657 + backend/socket.c | 259 + backend/usb.c | 303 + berkeley/Makefile | 95 + berkeley/lpc.c | 467 + berkeley/lpq.c | 483 + berkeley/lpr.c | 318 + berkeley/lprm.c | 221 + cgi-bin/Makefile | 117 + cgi-bin/admin.c | 891 ++ cgi-bin/cgi.h | 81 + cgi-bin/classes.c | 221 + cgi-bin/html.c | 89 + cgi-bin/ipp-var.c | 175 + cgi-bin/ipp-var.h | 54 + cgi-bin/jobs.c | 140 + cgi-bin/printers.c | 221 + cgi-bin/template.c | 364 + cgi-bin/var.c | 654 + conf/Makefile | 71 + conf/classes.conf | 79 + conf/cupsd.conf | 369 + conf/mime.convs | 62 + conf/mime.types | 122 + conf/printcap | 2 + conf/printers.conf | 96 + config.h.in | 121 + configure.in | 350 + cups.dsw | 128 + cups.list | 414 + cups.sh | 117 + cups.spec | 116 + cups/Makefile | 141 + cups/cups.dsp | 180 + cups/cups.h | 145 + cups/cups_C.h | 132 + cups/debug.h | 57 + cups/dest.c | 455 + cups/emit.c | 301 + cups/http.c | 1528 +++ cups/http.h | 315 + cups/ipp.c | 1595 +++ cups/ipp.h | 349 + cups/language.c | 390 + cups/language.h | 209 + cups/mark.c | 411 + cups/md5.c | 392 + cups/md5.h | 94 + cups/options.c | 379 + cups/page.c | 189 + cups/ppd.c | 1816 +++ cups/ppd.h | 240 + cups/snprintf.c | 287 + cups/string.c | 125 + cups/string.h | 94 + cups/testhttp.c | 109 + cups/testmime.dsp | 102 + cups/testppd.c | 183 + cups/testppd.dsp | 102 + cups/usersys.c | 175 + cups/util.c | 1230 ++ data/HPGLprolog | 37 + data/Makefile | 86 + data/iso-8859-1 | 251 + data/iso-8859-10 | 251 + data/iso-8859-13 | 251 + data/iso-8859-14 | 251 + data/iso-8859-15 | 251 + data/iso-8859-2 | 253 + data/iso-8859-3 | 244 + data/iso-8859-4 | 251 + data/iso-8859-5 | 251 + data/iso-8859-6 | 206 + data/iso-8859-7 | 245 + data/iso-8859-8 | 213 + data/iso-8859-9 | 251 + data/psglyphs | 1051 ++ data/utf-8 | 38 + doc/Makefile | 148 + doc/cmp.html | 665 + doc/cmp.pdf | 754 ++ doc/cmp.shtml | 717 + doc/cups.css | 4 + doc/cupsdoc.css | 9 + doc/documentation.html | 73 + doc/figures.sc | Bin 0 -> 51020 bytes doc/idd.html | 813 ++ doc/idd.pdf | 881 ++ doc/idd.shtml | 1250 ++ doc/images/accept-jobs.gif | Bin 0 -> 259 bytes doc/images/add-class.gif | Bin 0 -> 242 bytes doc/images/add-printer.gif | Bin 0 -> 252 bytes doc/images/cancel-job.gif | Bin 0 -> 248 bytes doc/images/cancel-jobs.gif | Bin 0 -> 255 bytes doc/images/cancel.gif | Bin 0 -> 210 bytes doc/images/classes.gif | Bin 0 -> 591 bytes doc/images/continue.gif | Bin 0 -> 224 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/delete-class.gif | Bin 0 -> 259 bytes doc/images/delete-printer.gif | Bin 0 -> 267 bytes doc/images/draft.gif | Bin 0 -> 926 bytes doc/images/hold-job.gif | Bin 0 -> 228 bytes doc/images/left.gif | Bin 0 -> 110 bytes doc/images/logo.gif | Bin 0 -> 1958 bytes doc/images/manage-classes.gif | Bin 0 -> 289 bytes doc/images/manage-jobs.gif | Bin 0 -> 266 bytes doc/images/manage-printers.gif | Bin 0 -> 296 bytes doc/images/modify-class.gif | Bin 0 -> 267 bytes doc/images/modify-printer.gif | Bin 0 -> 277 bytes doc/images/navbar.gif | Bin 0 -> 2869 bytes doc/images/navbar.xcf.gz | Bin 0 -> 4253 bytes doc/images/print-test-page.gif | Bin 0 -> 288 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/images/reject-jobs.gif | Bin 0 -> 252 bytes doc/images/release-job.gif | Bin 0 -> 255 bytes doc/images/restart-job.gif | Bin 0 -> 249 bytes doc/images/right.gif | Bin 0 -> 145 bytes doc/images/show-active.gif | Bin 0 -> 303 bytes doc/images/show-completed.gif | Bin 0 -> 337 bytes doc/images/start-class.gif | Bin 0 -> 238 bytes doc/images/start-printer.gif | Bin 0 -> 255 bytes doc/images/stop-class.gif | Bin 0 -> 245 bytes doc/images/stop-printer.gif | Bin 0 -> 252 bytes doc/index.html | 36 + doc/overview.html | 292 + doc/overview.pdf | Bin 0 -> 20446 bytes doc/sam.html | 934 ++ doc/sam.pdf | 963 ++ doc/sam.shtml | 1088 ++ doc/sdd.html | 481 + doc/sdd.pdf | 760 ++ doc/sdd.shtml | 557 + doc/spm.html | 4002 ++++++ doc/spm.pdf | 8337 ++++++++++++ doc/spm.shtml | 4220 ++++++ doc/ssr.html | 243 + doc/ssr.pdf | Bin 0 -> 25053 bytes doc/ssr.shtml | 272 + doc/stp.html | 159 + doc/stp.pdf | Bin 0 -> 21277 bytes doc/stp.shtml | 169 + doc/sum.html | 540 + doc/sum.pdf | 628 + doc/sum.shtml | 578 + doc/svd.shtml | 165 + filter/Makefile | 190 + filter/common.c | 255 + filter/common.h | 67 + filter/form-attr.c | 37 + filter/form-main.c | 37 + filter/form-ps.c | 37 + filter/form-text.c | 37 + filter/form-tree.c | 38 + filter/form.h | 34 + filter/hpgl-attr.c | 442 + filter/hpgl-char.c | 498 + filter/hpgl-config.c | 638 + filter/hpgl-input.c | 232 + filter/hpgl-main.c | 255 + filter/hpgl-polygon.c | 380 + filter/hpgl-prolog.c | 373 + 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 | 565 + filter/imagetoraster.c | 3972 ++++++ filter/pstops.c | 867 ++ filter/raster.c | 252 + filter/raster.h | 233 + filter/rastertoepson.c | 596 + filter/rastertohp.c | 503 + filter/textcommon.c | 745 ++ filter/textcommon.h | 93 + filter/texttops.c | 1132 ++ 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 | 132 + locale/Makefile | 73 + locale/de/cups_de | 133 + locale/en/cups_en | 132 + locale/es/cups_es | 132 + locale/fr/cups_fr | 132 + locale/it/cups_it | 132 + locale/locale.txt | 32 + locale/translate.c | 259 + man/Makefile | 87 + man/accept.8 | 66 + man/accept.man | 57 + man/backend.1 | 132 + man/backend.man | 102 + man/classes.conf.5 | 66 + man/classes.conf.man | 39 + man/cupsd.8 | 66 + man/cupsd.conf.5 | 66 + man/cupsd.conf.man | 37 + man/cupsd.man | 48 + man/enable.8 | 66 + man/enable.man | 64 + man/filter.1 | 132 + man/filter.man | 108 + man/lp.1 | 132 + man/lp.man | 111 + man/lpadmin.8 | 132 + man/lpadmin.man | 124 + man/lpc.8 | 66 + man/lpc.man | 79 + man/lpq.1 | 66 + man/lpq.man | 52 + man/lpr.1 | 132 + man/lpr.man | 96 + man/lprm.1 | 66 + man/lprm.man | 51 + man/lpstat.1 | 132 + man/lpstat.man | 115 + man/mime.convs.5 | 66 + man/mime.convs.man | 43 + man/mime.types.5 | 66 + man/mime.types.man | 40 + man/printers.conf.5 | 66 + man/printers.conf.man | 39 + ppd/Makefile | 55 + ppd/deskjet.ppd | 186 + ppd/laserjet.ppd | 172 + ppd/stcolor.ppd | 131 + ppd/stphoto.ppd | 131 + 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 | 2353 ++++ 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 | 113 + scheduler/auth.c | 738 + scheduler/auth.h | 113 + scheduler/cert.c | 250 + scheduler/cert.h | 60 + scheduler/classes.c | 544 + scheduler/classes.h | 43 + scheduler/client.c | 1682 +++ scheduler/client.h | 98 + scheduler/conf.c | 1023 ++ scheduler/conf.h | 116 + scheduler/cupsd.dsp | 173 + scheduler/cupsd.h | 152 + scheduler/devices.c | 390 + scheduler/dirsvc.c | 546 + scheduler/dirsvc.h | 58 + scheduler/filter.c | 299 + scheduler/ipp.c | 3962 ++++++ scheduler/job.c | 2179 +++ scheduler/job.h | 86 + scheduler/listen.c | 142 + scheduler/log.c | 372 + scheduler/main.c | 486 + scheduler/mime.c | 549 + scheduler/mime.h | 137 + scheduler/ppds.c | 541 + scheduler/printers.c | 1322 ++ scheduler/printers.h | 82 + scheduler/testmime.c | 199 + scheduler/testspeed.c | 126 + scheduler/type.c | 1014 ++ standards/draft-ietf-ipp-model-v11-04.txt | 11876 +++++++++++++++++ standards/draft-ietf-ipp-protocol-v11-03.txt | 2540 ++++ standards/rfc1179.txt | 787 ++ standards/rfc1321.txt | 1179 ++ standards/rfc2565.txt | 2075 +++ standards/rfc2566.txt | 9691 ++++++++++++++ standards/rfc2567.txt | 2411 ++++ standards/rfc2568.txt | 563 + standards/rfc2569.txt | 1571 +++ standards/rfc2616.txt | 9859 ++++++++++++++ standards/rfc2617.txt | 1907 +++ standards/rfc2639.txt | 3587 +++++ systemv/Makefile | 151 + systemv/accept.c | 286 + systemv/cancel.c | 236 + systemv/lp.c | 375 + systemv/lpadmin.c | 1331 ++ systemv/lpoptions.c | 290 + systemv/lppasswd.c | 442 + systemv/lpstat.c | 1494 +++ templates/Makefile | 69 + templates/add-class.tmpl | 62 + templates/add-printer.tmpl | 33 + templates/admin-op.tmpl | 1 + templates/admin.tmpl | 57 + templates/choose-device.tmpl | 32 + templates/choose-make.tmpl | 35 + templates/choose-model.tmpl | 35 + templates/choose-serial.tmpl | 55 + templates/choose-uri.tmpl | 41 + templates/classes.tmpl | 50 + templates/error.tmpl | 3 + templates/header.tmpl | 20 + templates/job-cancel.tmpl | 1 + templates/job-hold.tmpl | 1 + templates/job-release.tmpl | 1 + templates/jobs.tmpl | 55 + templates/modify-class.tmpl | 62 + templates/modify-printer.tmpl | 36 + templates/option-boolean.tmpl | 62 + templates/option-header.tmpl | 62 + templates/option-pickmany.tmpl | 62 + templates/option-pickone.tmpl | 62 + templates/option-trailer.tmpl | 0 templates/printer-accept.tmpl | 1 + templates/printer-added.tmpl | 2 + templates/printer-configured.tmpl | 2 + templates/printer-confirm.tmpl | 6 + templates/printer-deleted.tmpl | 1 + templates/printer-modified.tmpl | 2 + templates/printer-reject.tmpl | 1 + templates/printer-start.tmpl | 1 + templates/printer-stop.tmpl | 1 + templates/printers.tmpl | 54 + templates/test-page.tmpl | 2 + templates/trailer.tmpl | 7 + visualc/config.h | 114 + 864 files changed, 277848 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 backend/usb.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/admin.c create mode 100644 cgi-bin/cgi.h create mode 100644 cgi-bin/classes.c create mode 100644 cgi-bin/html.c create mode 100644 cgi-bin/ipp-var.c create mode 100644 cgi-bin/ipp-var.h create mode 100644 cgi-bin/jobs.c create mode 100644 cgi-bin/printers.c create mode 100644 cgi-bin/template.c create mode 100644 cgi-bin/var.c create mode 100644 conf/Makefile create mode 100644 conf/classes.conf create mode 100644 conf/cupsd.conf create mode 100644 conf/mime.convs create mode 100644 conf/mime.types create mode 100644 conf/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/dest.c create mode 100644 cups/emit.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/md5.c create mode 100644 cups/md5.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/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.dsp create mode 100644 cups/testppd.c create mode 100644 cups/testppd.dsp create mode 100644 cups/usersys.c create mode 100644 cups/util.c create mode 100644 data/HPGLprolog create mode 100644 data/Makefile create mode 100644 data/iso-8859-1 create mode 100644 data/iso-8859-10 create mode 100644 data/iso-8859-13 create mode 100644 data/iso-8859-14 create mode 100644 data/iso-8859-15 create mode 100644 data/iso-8859-2 create mode 100644 data/iso-8859-3 create mode 100644 data/iso-8859-4 create mode 100644 data/iso-8859-5 create mode 100644 data/iso-8859-6 create mode 100644 data/iso-8859-7 create mode 100644 data/iso-8859-8 create mode 100644 data/iso-8859-9 create mode 100644 data/psglyphs create mode 100644 data/utf-8 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/accept-jobs.gif create mode 100644 doc/images/add-class.gif create mode 100644 doc/images/add-printer.gif create mode 100644 doc/images/cancel-job.gif create mode 100644 doc/images/cancel-jobs.gif create mode 100644 doc/images/cancel.gif create mode 100644 doc/images/classes.gif create mode 100644 doc/images/continue.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/delete-class.gif create mode 100644 doc/images/delete-printer.gif create mode 100644 doc/images/draft.gif create mode 100644 doc/images/hold-job.gif create mode 100644 doc/images/left.gif create mode 100644 doc/images/logo.gif create mode 100644 doc/images/manage-classes.gif create mode 100644 doc/images/manage-jobs.gif create mode 100644 doc/images/manage-printers.gif create mode 100644 doc/images/modify-class.gif create mode 100644 doc/images/modify-printer.gif create mode 100644 doc/images/navbar.gif create mode 100644 doc/images/navbar.xcf.gz create mode 100644 doc/images/print-test-page.gif 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/images/reject-jobs.gif create mode 100644 doc/images/release-job.gif create mode 100644 doc/images/restart-job.gif create mode 100644 doc/images/right.gif create mode 100644 doc/images/show-active.gif create mode 100644 doc/images/show-completed.gif create mode 100644 doc/images/start-class.gif create mode 100644 doc/images/start-printer.gif create mode 100644 doc/images/stop-class.gif create mode 100644 doc/images/stop-printer.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 doc/svd.shtml create mode 100644 filter/Makefile create mode 100644 filter/common.c create mode 100644 filter/common.h create mode 100644 filter/form-attr.c create mode 100644 filter/form-main.c create mode 100644 filter/form-ps.c create mode 100644 filter/form-text.c create mode 100644 filter/form-tree.c create mode 100644 filter/form.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/raster.c create mode 100644 filter/raster.h create mode 100644 filter/rastertoepson.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.man create mode 100644 man/backend.1 create mode 100644 man/backend.man create mode 100644 man/classes.conf.5 create mode 100644 man/classes.conf.man create mode 100644 man/cupsd.8 create mode 100644 man/cupsd.conf.5 create mode 100644 man/cupsd.conf.man create mode 100644 man/cupsd.man create mode 100644 man/enable.8 create mode 100644 man/enable.man create mode 100644 man/filter.1 create mode 100644 man/filter.man create mode 100644 man/lp.1 create mode 100644 man/lp.man create mode 100644 man/lpadmin.8 create mode 100644 man/lpadmin.man create mode 100644 man/lpc.8 create mode 100644 man/lpc.man create mode 100644 man/lpq.1 create mode 100644 man/lpq.man create mode 100644 man/lpr.1 create mode 100644 man/lpr.man create mode 100644 man/lprm.1 create mode 100644 man/lprm.man create mode 100644 man/lpstat.1 create mode 100644 man/lpstat.man create mode 100644 man/mime.convs.5 create mode 100644 man/mime.convs.man create mode 100644 man/mime.types.5 create mode 100644 man/mime.types.man create mode 100644 man/printers.conf.5 create mode 100644 man/printers.conf.man create mode 100644 ppd/Makefile create mode 100644 ppd/deskjet.ppd create mode 100644 ppd/laserjet.ppd create mode 100644 ppd/stcolor.ppd create mode 100644 ppd/stphoto.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/cert.c create mode 100644 scheduler/cert.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.dsp create mode 100644 scheduler/cupsd.h create mode 100644 scheduler/devices.c create mode 100644 scheduler/dirsvc.c create mode 100644 scheduler/dirsvc.h create mode 100644 scheduler/filter.c 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/mime.c create mode 100644 scheduler/mime.h create mode 100644 scheduler/ppds.c create mode 100644 scheduler/printers.c create mode 100644 scheduler/printers.h create mode 100644 scheduler/testmime.c create mode 100644 scheduler/testspeed.c create mode 100644 scheduler/type.c create mode 100644 standards/draft-ietf-ipp-model-v11-04.txt create mode 100644 standards/draft-ietf-ipp-protocol-v11-03.txt create mode 100644 standards/rfc1179.txt create mode 100644 standards/rfc1321.txt create mode 100644 standards/rfc2565.txt create mode 100644 standards/rfc2566.txt create mode 100644 standards/rfc2567.txt create mode 100644 standards/rfc2568.txt create mode 100644 standards/rfc2569.txt create mode 100644 standards/rfc2616.txt create mode 100644 standards/rfc2617.txt create mode 100644 standards/rfc2639.txt 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/lpoptions.c create mode 100644 systemv/lppasswd.c create mode 100644 systemv/lpstat.c create mode 100644 templates/Makefile create mode 100644 templates/add-class.tmpl create mode 100644 templates/add-printer.tmpl create mode 100644 templates/admin-op.tmpl create mode 100644 templates/admin.tmpl create mode 100644 templates/choose-device.tmpl create mode 100644 templates/choose-make.tmpl create mode 100644 templates/choose-model.tmpl create mode 100644 templates/choose-serial.tmpl create mode 100644 templates/choose-uri.tmpl create mode 100644 templates/classes.tmpl create mode 100644 templates/error.tmpl create mode 100644 templates/header.tmpl create mode 100644 templates/job-cancel.tmpl create mode 100644 templates/job-hold.tmpl create mode 100644 templates/job-release.tmpl create mode 100644 templates/jobs.tmpl create mode 100644 templates/modify-class.tmpl create mode 100644 templates/modify-printer.tmpl create mode 100644 templates/option-boolean.tmpl create mode 100644 templates/option-header.tmpl create mode 100644 templates/option-pickmany.tmpl create mode 100644 templates/option-pickone.tmpl create mode 100644 templates/option-trailer.tmpl create mode 100644 templates/printer-accept.tmpl create mode 100644 templates/printer-added.tmpl create mode 100644 templates/printer-configured.tmpl create mode 100644 templates/printer-confirm.tmpl create mode 100644 templates/printer-deleted.tmpl create mode 100644 templates/printer-modified.tmpl create mode 100644 templates/printer-reject.tmpl create mode 100644 templates/printer-start.tmpl create mode 100644 templates/printer-stop.tmpl create mode 100644 templates/printers.tmpl create mode 100644 templates/test-page.tmpl create mode 100644 templates/trailer.tmpl create mode 100644 visualc/config.h diff --git a/CHANGES.txt b/CHANGES.txt new file mode 100644 index 0000000000..6568861ad3 --- /dev/null +++ b/CHANGES.txt @@ -0,0 +1,263 @@ +CHANGES.txt - 02/27/2000 +------------------------ + +CHANGES IN CUPS v1.1b1 + + - NEW web-based administration interface. + - NEW EPSON printer drivers. + - NEW user-defined printers and options. + - NEW persistent jobs and job history + - NEW IPP/1.1 support + - NEW template-based web interfaces. + - NEW CUPS-get-devices and CUPS-get-ppds operations. + - NEW support for create-job and send-file operations. + - NEW certificate-based authentication for local + administration. + - NEW USB backend. + - The lpr command now produces human-readable error messages. + - The lpq command now produces BSD standard format output + instead of OSF/1 output. This should resolve the SAMBA + print queue problems that have been reported. + - The IPP backend did not always detect when the "raw" option + was being used. + - The "lpstat -p" command would stop after the first active + printer. + - The "lpstat -v" command would stop before the first remote + printer. + + +CHANGES IN CUPS v1.0.5 + + - The HP-GL/2 filter did not correctly set the pen color + for pens other than #1. + - The scheduler would only accept 26 simultaneous jobs + under some OS releases (mkstemp() limitation.) It now + handles up to 2^32 simultaneous jobs. + - The PostScript filter loaded the printer's PPD file + twice. + - The PAM authentication code now uses pam_strerror() to + provide a textual error message in the error_log file. + - The scheduler now copies PPD and interface script + files instead of moving them; this fixes installations + with a separate requests directory. + - The PostScript RIP did not generate correct 6-color + output. + - Several filters were marking PPD options twice when + they didn't need to. + - The scheduler did not save the printer or class state + after an accept-jobs or reject-jobs operation. + - The cupsGetDefault() function now ignores the PRINTER + environment variable if it is set to "lp". + - New ippErrorString() function to get textual error + messages. + - Better error reporting in the System V commands. + - The lpadmin and lpstat commands always tried to + connect to the default server. + - The text filter didn't load the charset files from the + correct location. + - Wasn't sending a WWW-Authenticate: field to HTTP + clients when authentication was required. + - httpSeparate() didn't always set the default port + number for known methods. + - The HP-GL/2 filter now looks for "PSwidth,length" + instead of (the correct) "PSlength,width" as + documented by HP. It appears that many major CAD + applications are broken and this change allows the + auto-rotation to work with them. + - The IPP "printer-resolution" option was not being + translated. + - The charset files did not include the Microsoft + "standard" characters from 128 to 159 (unused by the + ISO-8859-x charsets) + - The scheduler was chunking the Content-Type field from + CGI programs; this problem was most noticeable with + Microsoft Internet Explorer 5. + - By popular demand, the printers, jobs, and classes + CGIs no longer force a reload of the page every 10/30 + seconds. + - The scheduler incorrectly required that the IPP client + provide a document-format attribute for the + validate-job operation. + - Clients that sent bad IPP requests without the + required attributes-natural-language and + attributes-charset attributes would crash the + scheduler. + + +CHANGES IN CUPS v1.0.4 + + - Documentation updates. + - Jobs would get stuck in the queue and wouldn't print + until you enabled the queue. + - The lp and lpr commands now catch SIGHUP and SIGINTR. + - The lp and lpr commands now use sigaction or sigset + when available. + - CUPS library updates for WIN32/OS-2 + + +CHANGES IN CUPS v1.0.3 + + - Documentation updates. + - The lpq man page was missing. + - The configure script was not properly detecting the + image libraries. + - The top-level makefile was calling "make" instead of + "$(MAKE)". + - PostScript filter fixes for number-up, OutputOrder, + and %Trailer. + - The imagetops filter didn't end the base-85 encoding + properly if the image data was not a multiple of 4 + bytes in length. + - The imagetoraster filter didn't generate good banded + RGB or CMY data (was dividing the line width by 4 + instead of 3...) + - The imagetoraster filter now records the bounding + box of the image on the page. + - The CUPS image library cache code wasn't working as + designed; images larger than the maximum RIP cache + would eventually thrash using the same cache tile. + - The CUPS image library TIFF loading code didn't + handle unknown resolution units properly; the fixed + code uses a default resolution of 128 PPI. + - cupsGetClasses() and cupsGetPrinters() did not free + existing strings if they ran out of memory. + - The scheduler logs incorrectly contained 3 digits for + the timezone offset instead of 4. + - The scheduler now does a lookup for the default user + and group ID; the previous hardcoded values caused + problems with the LPD backend. + - The cancel-job operation now allows any user in the + system group to cancel any job. + - The cancel-job operation stopped the print queue if + the job was being printed. + - Now only stop printers if the backend fails. If the + filter fails then the failure is noted in the + error_log and printing continues with the next file in + the queue. + - Now log whether a filter fails because of a signal + or because it returned a non-zero exit status. + - The root user now always passes the system group test. + - Printers with an interface script and remote printers + and classes didn't have a printer-make-and-model + attribute. + - Added logging of lost/timed-out remote printers. + - The HP-GL/2 filter was scaling the pen width twice. + - Updated the HP-GL/2 filter to use a single SP (Set + Pen) procedure. This makes the output smaller and is + more appropriate since the filter keeps track of the + pen states already. + - The scheduler didn't handle passwords with spaces. + - The IPP backend now does multiple copies and retries + if the destination server requires it (e.g. HP + JetDirect.) + - The disable command didn't implement the "-c" option + (cancel all jobs.) + - Changed the CMYK generation function for the image file + and PostScript RIPs. + - The lp command didn't support the "-h" option as + documented. + - The AppSocket, IPP, and LPD backends now retry on all + network errors. This should prevent stopped queues + caused by a printer being disconnected from the + network or powered off. + - The scheduler now restarts a job if the corresponding + printer is modified. + - The image RIPs now rotate the image if needed to fit + on the page. + + +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..71bad14862 --- /dev/null +++ b/CREDITS.txt @@ -0,0 +1,26 @@ +CREDITS.txt - 01/27/2000 +------------------------ + +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. + L. Peter Deutsch - MD5 code. + +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..f7f31ac86c --- /dev/null +++ b/Makedefs.in @@ -0,0 +1,132 @@ +# +# "$Id$" +# +# Common makefile definitions for the Common UNIX Printing System (CUPS). +# +# Copyright 1997-2000 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@ +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 = + +# +# 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@ +DOCDIR = @CUPS_DOCDIR@ +INCLUDEDIR = $(includedir) +LIBDIR = $(libdir) +LOCALEDIR = @CUPS_LOCALEDIR@ +LOGDIR = @CUPS_LOGDIR@ +MANDIR = @mandir@ +REQUESTS = @CUPS_REQUESTS@ +SBINDIR = @sbindir@ +SERVERBIN = @CUPS_SERVERBIN@ +SERVERROOT = @CUPS_SERVERROOT@ + +# +# Rules... +# + +.SILENT: +.SUFFIXES: .a .c .h .man .o .1 .5 .8 +.c.o: + echo Compiling $<... + $(CC) $(CFLAGS) -c $< +.man.1 .man.5 .man.8: + echo Formatting $<... + $(RM) $@ + $(NROFF) -man $< >$@ + +# +# End of "$Id$" +# diff --git a/Makefile b/Makefile new file mode 100644 index 0000000000..ab767cc640 --- /dev/null +++ b/Makefile @@ -0,0 +1,94 @@ +# +# "$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)) || break;\ + done + +# +# Remove object and target files... +# + +clean: + for dir in $(DIRS); do\ + echo Cleaning in $$dir... ;\ + (cd $$dir; $(MAKE) clean) || break;\ + done + +# +# Install object and target files... +# + +install: + for dir in $(DIRS); do\ + echo Installing in $$dir... ;\ + (cd $$dir; $(MAKE) install) || break;\ + 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) + echo Installing in templates... + (cd templates; $(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..521f8048ec --- /dev/null +++ b/README.txt @@ -0,0 +1,245 @@ +README - CUPS v1.1b1 - 02/27/2000 +--------------------------------- + +************************************************************************ +************************************************************************ +**** **** +**** BETA SOFTWARE BETA SOFTWARE BETA SOFTWARE BETA SOFTWARE **** +**** **** +************************************************************************ +************************************************************************ + +This is an official public beta release for the Common UNIX Printing +System. Since this is a beta release, we do not recommend that you +use this software on a production system. Instead, please use the +current 1.0.x release for your production systems. + +Also, currently we are only providing source code for the beta releases. +As we approach a final production ("gold") release of CUPS 1.1 we will +provide binary distributions as well. + +Please report all problems in the CUPS 1.1 beta releases to +"cups-beta@cups.org" or to the CUPS mailing list. + +Thanks for using CUPS! + + +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-2000 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 USING YOUR WEB BROWSER + +CUPS 1.1 includes a new web-based administration tool that allows you +to manage printers, classes, and jobs on your server. To access the +printer administration tools open the following URL in your browser: + + http://localhost:631/admin + +You will be asked for the administration password (root or any other +user in the sys/system/root group on your system) and then shown a +menu of available functions. + +[note: adding, deleting, and modifying classes has not been implemented in + beta 1] + + +SETTING UP PRINTER QUEUES FROM THE COMMAND-LINE + +CUPS works best with PPD (PostScript Printer Description) files. In a +pinch you can also use System V style printer interface scripts. + +Six sample PPD files are provided with this distribution that utilize +the PostScript and image file RIPs and the sample EPSON and HP printer +drivers. 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/lp0 -E + /usr/lib/lpadmin -p DeskJet -m deskjet.ppd -v parallel:/dev/lp1 -E + /usr/lib/lpadmin -p DeskJet -m deskjet.ppd -v parallel:/dev/lp2 -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 other sample drivers you can use: + + Driver PPD File + -------------------------- ------------ + HP DeskJet Series deskjet.ppd + HP LaserJet Series laserjet.ppd + EPSON Stylus Color Series stcolor.ppd + EPSON Stylus Photo Series stphoto.ppd + EPSON 9-pin Series epson9.ppd [not in beta 1] + EPSON 24-pin Series epson24.ppd [not in beta 1] + +These sample drivers provide basic printing capabilities, but generally +do not exercise the full potential of the printers or CUPS. For +commercial printer drivers 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-2000 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..238813d6cb --- /dev/null +++ b/backend/Makefile @@ -0,0 +1,137 @@ +# +# "$Id$" +# +# Backend makefile for the Common UNIX Printing System (CUPS). +# +# Copyright 1997-2000 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 + +BACKENDS = ipp lpd parallel serial socket usb +TARGETS = betest $(BACKENDS) +OBJS = betest.o ipp.o lpd.o parallel.o serial.o socket.o usb.o + + +# +# Make all targets... +# + +all: $(TARGETS) + + +# +# Clean all object files... +# + +clean: + rm -f $(OBJS) $(TARGETS) + + +# +# Install all targets... +# + +install: + -$(MKDIR) $(SERVERBIN)/backend + $(CP) $(BACKENDS) $(SERVERBIN)/backend + -$(LN) ipp $(SERVERBIN)/backend/http + + +# +# 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 + + +# +# usb +# + +usb: usb.o ../cups/$(LIBCUPS) + echo Linking $@... + $(CC) $(LDFLAGS) -o usb usb.o $(LIBS) + +usb.o: ../cups/cups.h ../Makedefs + + +# +# End of "$Id$". +# diff --git a/backend/betest.c b/backend/betest.c new file mode 100644 index 0000000000..8c68284e1e --- /dev/null +++ b/backend/betest.c @@ -0,0 +1,85 @@ +/* + * "$Id$" + * + * Backend test program for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2000 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..0132e2ee09 --- /dev/null +++ b/backend/ipp.c @@ -0,0 +1,668 @@ +/* + * "$Id$" + * + * IPP backend for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2000 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 */ + const char *content_type; /* CONTENT_TYPE environment variable */ + + + if (argc == 1) + { + if ((s = strrchr(argv[0], '/')) != NULL) + s ++; + else + s = argv[0]; + + printf("network %s \"Unknown\" \"Internet Printing Protocol\"\n", s); + return (0); + } + else 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) || + ((content_type = getenv("CONTENT_TYPE")) != NULL && + strcasecmp(content_type, "application/vnd.cups-raw") == 0)) + 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 --; + } + else if (ipp_status != IPP_SERVICE_UNAVAILABLE && + ipp_status != IPP_PRINTER_BUSY) + break; + } + + /* + * 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..60bd578874 --- /dev/null +++ b/backend/lpd.c @@ -0,0 +1,414 @@ +/* + * "$Id$" + * + * Line Printer Daemon backend for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2000 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 == 1) + { + puts("network lpd \"Unknown\" \"LPD/LPR Host or Printer\""); + return (0); + } + else 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..52ac67251f --- /dev/null +++ b/backend/parallel.c @@ -0,0 +1,515 @@ +/* + * "$Id$" + * + * Parallel port backend for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2000 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. + * list_devices() - List all parallel devices. + */ + +/* + * Include necessary headers. + */ + +#include +#include +#include +#include + +#if defined(WIN32) || defined(__EMX__) +# include +#else +# include +# include +# include +#endif /* WIN32 || __EMX__ */ + +#ifdef __sgi +# include +# ifndef INV_EPP_ECP_PLP +# define INV_EPP_ECP_PLP 6 /* From 6.3/6.4/6.5 sys/invent.h */ +# define INV_ASO_SERIAL 14 /* serial portion of SGI ASO board */ +# define INV_IOC3_DMA 16 /* DMA mode IOC3 serial */ +# define INV_IOC3_PIO 17 /* PIO mode IOC3 serial */ +# define INV_ISA_DMA 19 /* DMA mode ISA serial -- O2 */ +# endif /* !INV_EPP_ECP_PLP */ +#endif /* __sgi */ + + +/* + * Local functions... + */ + +void list_devices(void); + + +/* + * '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 == 1) + { + list_devices(); + return (0); + } + else 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); +} + + +/* + * 'list_devices()' - List all parallel devices. + */ + +void +list_devices(void) +{ + static char *funky_hex = "0123456789abcdefghijklmnopqrstuvwxyz"; + /* Funky hex numbering used for some devices */ + +#ifdef __linux + int i; /* Looping var */ + int fd; /* File descriptor */ + char device[255]; /* Device filename */ + FILE *probe; /* /proc/parport/n/autoprobe file */ + char line[1024], /* Line from file */ + *delim, /* Delimiter in file */ + make[IPP_MAX_NAME], /* Make from file */ + model[IPP_MAX_NAME]; /* Model from file */ + + + for (i = 0; i < 4; i ++) + { + sprintf(device, "/proc/parport/%d/autoprobe", i); + if ((probe = fopen(device, "r")) != NULL) + { + memset(make, 0, sizeof(make)); + memset(model, 0, sizeof(model)); + strcpy(model, "Unknown"); + + while (fgets(line, sizeof(line), probe) != NULL) + { + /* + * Strip trailing ; and/or newline. + */ + + if ((delim = strrchr(line, ';')) != NULL) + *delim = '\0'; + else if ((delim = strrchr(line, '\n')) != NULL) + *delim = '\0'; + + /* + * Look for MODEL and MANUFACTURER lines... + */ + + if (strncmp(line, "MODEL:", 6) == 0 && + strncmp(line, "MODEL:Unknown", 13) != 0) + strncpy(model, line + 6, sizeof(model) - 1); + else if (strncmp(line, "MANUFACTURER:", 13) == 0 && + strncmp(line, "MANUFACTURER:Unknown", 20) != 0) + strncpy(make, line + 13, sizeof(make) - 1); + } + + fclose(probe); + + if (make[0]) + printf("direct parallel:/dev/lp%d \"%s %s\" \"Parallel Port #%d\"\n", + i, make, model, i + 1); + else + printf("direct parallel:/dev/lp%d \"%s\" \"Parallel Port #%d\"\n", + i, model, i + 1); + } + else + { + sprintf(device, "/dev/lp%d", i); + if ((fd = open(device, O_WRONLY)) >= 0) + { + close(fd); + printf("direct parallel:%s \"Unknown\" \"Parallel Port #%d\"\n", device, i + 1); + } + else + { + sprintf(device, "/dev/par%d", i); + if ((fd = open(device, O_WRONLY)) >= 0) + { + close(fd); + printf("direct parallel:%s \"Unknown\" \"Parallel Port #%d\"\n", device, i + 1); + } + } + } + } +#elif defined(__sgi) + int i, j, n; /* Looping vars */ + char device[255]; /* Device filename */ + inventory_t *inv; /* Hardware inventory info */ + + + /* + * IRIX maintains a hardware inventory of most devices... + */ + + setinvent(); + + while ((inv = getinvent()) != NULL) + { + if (inv->inv_class == INV_PARALLEL && + (inv->inv_type == INV_ONBOARD_PLP || + inv->inv_type == INV_EPP_ECP_PLP)) + { + /* + * Standard parallel port... + */ + + puts("direct parallel:/dev/plp \"Unknown\" \"Onboard Parallel Port\""); + } + else if (inv->inv_class == INV_PARALLEL && + inv->inv_type == INV_EPC_PLP) + { + /* + * EPC parallel port... + */ + + printf("direct parallel:/dev/plp%d \"Unknown\" \"Integral EPC parallel port, Ebus slot %d\"\n", + inv->inv_controller, inv->inv_controller); + } + } + + endinvent(); + + /* + * Central Data makes serial and parallel "servers" that can be + * connected in a number of ways. Look for ports... + */ + + for (i = 0; i < 10; i ++) + for (j = 0; j < 8; j ++) + for (n = 0; n < 32; n ++) + { + if (i == 8) /* EtherLite */ + sprintf(device, "/dev/lpn%d%c", j, funky_hex[n]); + else if (i == 9) /* PCI */ + sprintf(device, "/dev/lpp%d%c", j, funky_hex[n]); + else /* SCSI */ + sprintf(device, "/dev/lp%d%d%c", i, j, funky_hex[n]); + + if (access(device, 0) == 0) + { + if (i == 8) + printf("direct parallel:%s \"Unknown\" \"Central Data EtherLite Parallel Port, ID %d, port %d\"\n", + device, j, n); + else if (i == 9) + printf("direct parallel:%s \"Unknown\" \"Central Data PCI Parallel Port, ID %d, port %d\"\n", + device, j, n); + else + printf("direct parallel:%s \"Unknown\" \"Central Data SCSI Parallel Port, logical bus %d, ID %d, port %d\"\n", + device, i, j, n); + } + } +#elif defined(__sun) + int i, j, n; /* Looping vars */ + char device[255]; /* Device filename */ + inventory_t *inv; /* Hardware inventory info */ + + + /* + * Standard parallel ports... + */ + + for (i = 0; i < 10; i ++) + { + sprintf(device, "/dev/ecpp%d", i); + if (access(device, 0) == 0) + printf("direct parallel:%s \"Unknown\" \"Sun IEEE-1284 Parallel Port #%d\"\n", + device, i + 1); + } + + for (i = 0; i < 10; i ++) + { + sprintf(device, "/dev/bpp%d", i); + if (access(device, 0) == 0) + printf("direct parallel:%s \"Unknown\" \"Sun Standard Parallel Port #%d\"\n", + device, i + 1); + } + + for (i = 0; i < 3; i ++) + { + sprintf(device, "/dev/lp%d", i); + + if (access(device, 0) == 0) + printf("direct parallel:%s \"Unknown\" \"PC Parallel Port #%d\"\n", + device, i + 1); + } + + /* + * MAGMA parallel ports... + */ + + for (i = 0; i < 40; i ++) + { + sprintf(device, "/dev/pm%02d", i); + if (access(device, 0) == 0) + printf("direct parallel:%s \"Unknown\" \"MAGMA Parallel Board #%d Port #%d\"\n", + device, (i / 10) + 1, (i % 10) + 1); + } + + /* + * Central Data parallel ports... + */ + + for (i = 0; i < 9; i ++) + for (j = 0; j < 8; j ++) + for (n = 0; n < 32; n ++) + { + if (i == 8) /* EtherLite */ + sprintf(device, "/dev/sts/lpN%d%c", j, funky_hex[n]); + else + sprintf(device, "/dev/sts/lp%c%d%c", i + 'C', j, + funky_hex[n]); + + if (access(device, 0) == 0) + { + if (i == 8) + printf("direct parallel:%s \"Unknown\" \"Central Data EtherLite Parallel Port, ID %d, port %d\"\n", + device, j, n); + else + printf("direct parallel:%s \"Unknown\" \"Central Data SCSI Parallel Port, logical bus %d, ID %d, port %d\"\n", + device, i, j, n); + } + } +#elif defined(__hpux) + int i, j, n; /* Looping vars */ + char device[255]; /* Device filename */ + + + /* + * Standard parallel ports... + */ + + if (access("/dev/rlp", 0) == 0) + puts("direct parallel:/dev/rlp \"Unknown\" \"Standard Parallel Port (/dev/rlp)\""); + + for (i = 0; i < 7; i ++) + for (j = 0; j < 7; j ++) + { + sprintf(device, "/dev/c%dt%dd0_lp", i, j); + if (access(device, 0) == 0) + printf("direct parallel:%s \"Unknown\" \"Parallel Port #%d,%d\"\n", i, j); + } + + /* + * Central Data parallel ports... + */ + + for (i = 0; i < 9; i ++) + for (j = 0; j < 8; j ++) + for (n = 0; n < 32; n ++) + { + if (i == 8) /* EtherLite */ + sprintf(device, "/dev/lpN%d%c", j, funky_hex[n]); + else + sprintf(device, "/dev/lp%c%d%c", i + 'C', j, + funky_hex[n]); + + if (access(device, 0) == 0) + { + if (i == 8) + printf("direct parallel:%s \"Unknown\" \"Central Data EtherLite Parallel Port, ID %d, port %d\"\n", + device, j, n); + else + printf("direct parallel:%s \"Unknown\" \"Central Data SCSI Parallel Port, logical bus %d, ID %d, port %d\"\n", + device, i, j, n); + } + } +#elif defined(__osf__) + int i; /* Looping var */ + char device[255]; /* Device filename */ + + + for (i = 0; i < 3; i ++) + { + sprintf(device, "/dev/lp%d", i); + if ((fd = open(device, O_WRONLY)) >= 0) + { + close(fd); + printf("direct parallel:%s \"Unknown\" \"Parallel Port #%d\"\n", device, i + 1); + } + } +#elif defined(FreeBSD) || defined(OpenBSD) || defined(NetBSD) + int i; /* Looping var */ + char device[255]; /* Device filename */ + + + for (i = 0; i < 3; i ++) + { + sprintf(device, "/dev/lpt%d", i); + if ((fd = open(device, O_WRONLY)) >= 0) + { + close(fd); + printf("direct parallel:%s \"Unknown\" \"Parallel Port #%d\"\n", device, i + 1); + } + } +#endif +} + + +/* + * End of "$Id$". + */ diff --git a/backend/serial.c b/backend/serial.c new file mode 100644 index 0000000000..bee76f1a20 --- /dev/null +++ b/backend/serial.c @@ -0,0 +1,657 @@ +/* + * "$Id$" + * + * Serial port backend for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2000 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__ */ + +#ifdef __sgi +# include +# ifndef INV_EPP_ECP_PLP +# define INV_EPP_ECP_PLP 6 /* From 6.3/6.4/6.5 sys/invent.h */ +# define INV_ASO_SERIAL 14 /* serial portion of SGI ASO board */ +# define INV_IOC3_DMA 16 /* DMA mode IOC3 serial */ +# define INV_IOC3_PIO 17 /* PIO mode IOC3 serial */ +# define INV_ISA_DMA 19 /* DMA mode ISA serial -- O2 */ +# endif /* !INV_EPP_ECP_PLP */ +#endif /* __sgi */ + + +/* + * Local functions... + */ + +void list_devices(void); + + +/* + * '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 == 1) + { + list_devices(); + return (0); + } + else 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 serial port device... + */ + + if ((fd = open(resource, O_WRONLY | O_NOCTTY)) == -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); +} + + +/* + * 'list_devices()' - List all serial devices. + */ + +void +list_devices(void) +{ + static char *funky_hex = "0123456789abcdefghijklmnopqrstuvwxyz"; + /* Funky hex numbering used for some devices */ + +#ifdef __linux + int i; /* Looping var */ + int fd; /* File descriptor */ + char device[255]; /* Device filename */ + + + for (i = 0; i < 4; i ++) + { + sprintf(device, "/dev/ttyS%d", i); + if ((fd = open(device, O_WRONLY | O_NOCTTY)) >= 0) + { + close(fd); + printf("serial serial:%s?baud=115200 \"Unknown\" \"Serial Port #%d\"\n", + device, i + 1); + } + } +#elif defined(__sgi) + int i, j, n; /* Looping vars */ + char device[255]; /* Device filename */ + inventory_t *inv; /* Hardware inventory info */ + + + /* + * IRIX maintains a hardware inventory of most devices... + */ + + setinvent(); + + while ((inv = getinvent()) != NULL) + { + if (inv->inv_class == INV_SERIAL) + { + /* + * Some sort of serial port... + */ + + if (inv->inv_type == INV_CDSIO || inv->inv_type == INV_CDSIO_E) + { + /* + * CDSIO port... + */ + + for (n = 0; n < 6; n ++) + printf("serial serial:/dev/ttyd%d?baud=19200 \"Unknown\" \"CDSIO Board %d Serial Port #%d\"\n", + n + 5 + 8 * inv->inv_controller, inv->inv_controller, n + 1); + } + else if (inv->inv_type == INV_EPC_SERIAL) + { + /* + * Everest serial port... + */ + + if (inv->inv_unit == 0) + i = 1; + else + i = 41 + 4 * inv->inv_controller; + + for (n = 0; n < inv->inv_state; n ++) + printf("serial serial:/dev/ttyd%d?baud=19200 \"Unknown\" \"EPC Serial Port %d, Ebus slot %d\"\n", + n + i, n + 1, inv->inv_controller); + } + else if (inv->inv_state > 1) + { + /* + * Standard serial port under IRIX 6.4 and earlier... + */ + + for (n = 0; n < inv->inv_state; n ++) + printf("serial serial:/dev/ttyd%d?baud=19200 \"Unknown\" \"Onboard Serial Port %d\"\n", + n + inv->inv_unit + 1, n + inv->inv_unit + 1); + } + else + { + /* + * Standard serial port under IRIX 6.5 and beyond... + */ + + printf("serial serial:/dev/ttyd%d?baud=115200 \"Unknown\" \"Onboard Serial Port %d\"\n", + inv->inv_controller, inv->inv_controller); + } + } + } + + endinvent(); + + /* + * Central Data makes serial and parallel "servers" that can be + * connected in a number of ways. Look for ports... + */ + + for (i = 0; i < 10; i ++) + for (j = 0; j < 8; j ++) + for (n = 0; n < 32; n ++) + { + if (i == 8) /* EtherLite */ + sprintf(device, "/dev/ttydn%d%c", j, funky_hex[n]); + else if (i == 9) /* PCI */ + sprintf(device, "/dev/ttydp%d%c", j, funky_hex[n]); + else /* SCSI */ + sprintf(device, "/dev/ttyd%d%d%c", i, j, funky_hex[n]); + + if (access(device, 0) == 0) + { + if (i == 8) + printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data EtherLite Serial Port, ID %d, port %d\"\n", + device, j, n); + else if (i == 9) + printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data PCI Serial Port, ID %d, port %d\"\n", + device, j, n); + else + printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data SCSI Serial Port, logical bus %d, ID %d, port %d\"\n", + device, i, j, n); + } + } +#elif defined(__sun) + int i, j, n; /* Looping vars */ + char device[255]; /* Device filename */ + + + /* + * Standard serial ports... + */ + + for (i = 0; i < 26; i ++) + { + sprintf(device, "/dev/cua/%c", 'a' + i); + if (access(device, 0) == 0) + printf("serial serial:%s?baud=38400 \"Unknown\" \"Serial Port #%d\"\n", + device, i + 1); + } + + /* + * MAGMA serial ports... + */ + + for (i = 0; i < 40; i ++) + { + sprintf(device, "/dev/term/%02d", i); + if (access(device, 0) == 0) + printf("serial serial:%s?baud=38400 \"Unknown\" \"MAGMA Serial Board #%d Port #%d\"\n", + device, (i / 10) + 1, (i % 10) + 1); + } + + /* + * Central Data serial ports... + */ + + for (i = 0; i < 9; i ++) + for (j = 0; j < 8; j ++) + for (n = 0; n < 32; n ++) + { + if (i == 8) /* EtherLite */ + sprintf(device, "/dev/sts/ttyN%d%c", j, funky_hex[n]); + else + sprintf(device, "/dev/sts/tty%c%d%c", i + 'C', j, + funky_hex[n]); + + if (access(device, 0) == 0) + { + if (i == 8) + printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data EtherLite Serial Port, ID %d, port %d\"\n", + device, j, n); + else + printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data SCSI Serial Port, logical bus %d, ID %d, port %d\"\n", + device, i, j, n); + } + } +#elif defined(__hpux) + int i, j, n; /* Looping vars */ + char device[255]; /* Device filename */ + + + /* + * Standard serial ports... + */ + + for (i = 0; i < 10; i ++) + { + sprintf(device, "/dev/tty%dp0", i); + if (access(device, 0) == 0) + printf("serial serial:%s?baud=38400 \"Unknown\" \"Serial Port #%d\"\n", + device, i + 1); + } + + /* + * Central Data serial ports... + */ + + for (i = 0; i < 9; i ++) + for (j = 0; j < 8; j ++) + for (n = 0; n < 32; n ++) + { + if (i == 8) /* EtherLite */ + sprintf(device, "/dev/ttyN%d%c", j, funky_hex[n]); + else + sprintf(device, "/dev/tty%c%d%c", i + 'C', j, + funky_hex[n]); + + if (access(device, 0) == 0) + { + if (i == 8) + printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data EtherLite Serial Port, ID %d, port %d\"\n", + device, j, n); + else + printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data SCSI Serial Port, logical bus %d, ID %d, port %d\"\n", + device, i, j, n); + } + } +#elif defined(__osf__) + int i; /* Looping var */ + char device[255]; /* Device filename */ + + + /* + * Standard serial ports... + */ + + for (i = 0; i < 100; i ++) + { + sprintf(device, "/dev/tty%02d", i); + if (access(device, 0) == 0) + printf("serial serial:%s?baud=38400 \"Unknown\" \"Serial Port #%d\"\n", + device, i + 1); + } +#elif defined(FreeBSD) || defined(OpenBSD) || defined(NetBSD) + int i, j; /* Looping vars */ + int fd; /* File descriptor */ + char device[255]; /* Device filename */ + + + /* + * SIO ports... + */ + + for (i = 0; i < 32; i ++) + { + sprintf(device, "/dev/ttyd%c", funky_hex[i]); + if ((fd = open(device, O_WRONLY | O_NOCTTY)) >= 0) + { + close(fd); + printf("serial serial:%s?baud=115200 \"Unknown\" \"Standard Serial Port #%d\"\n", + device, i + 1); + } + } + + /* + * Cyclades ports... + */ + + for (i = 0; i < 16; i ++) /* Should be up to 65536 boards... */ + for (j = 0; j < 32; j ++) + { + sprintf(device, "/dev/ttyc%d%c", i, funky_hex[j]); + if ((fd = open(device, O_WRONLY | O_NOCTTY)) >= 0) + { + close(fd); + printf("serial serial:%s?baud=115200 \"Unknown\" \"Cyclades #%d Serial Port #%d\"\n", + device, i, j + 1); + } + } + + /* + * Digiboard ports... + */ + + for (i = 0; i < 16; i ++) /* Should be up to 65536 boards... */ + for (j = 0; j < 32; j ++) + { + sprintf(device, "/dev/ttyD%d%c", i, funky_hex[j]); + if ((fd = open(device, O_WRONLY | O_NOCTTY)) >= 0) + { + close(fd); + printf("serial serial:%s?baud=115200 \"Unknown\" \"Digiboard #%d Serial Port #%d\"\n", + device, i, j + 1); + } + } + + /* + * Stallion ports... + */ + + for (i = 0; i < 32; i ++) + { + sprintf(device, "/dev/ttyE%c", funky_hex[i]); + if ((fd = open(device, O_WRONLY | O_NOCTTY)) >= 0) + { + close(fd); + printf("serial serial:%s?baud=115200 \"Unknown\" \"Stallion Serial Port #%d\"\n", + device, i + 1); + } + } + + /* + * SX ports... + */ + + for (i = 0; i < 128; i ++) + { + sprintf(device, "/dev/ttyA%d", i + 1); + if ((fd = open(device, O_WRONLY | O_NOCTTY)) >= 0) + { + close(fd); + printf("serial serial:%s?baud=115200 \"Unknown\" \"SX Serial Port #%d\"\n", + device, i + 1); + } + } +#endif +} + + +/* + * End of "$Id$". + */ diff --git a/backend/socket.c b/backend/socket.c new file mode 100644 index 0000000000..a3b130384b --- /dev/null +++ b/backend/socket.c @@ -0,0 +1,259 @@ +/* + * "$Id$" + * + * AppSocket backend for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2000 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 == 1) + { + puts("network socket \"Unknown\" \"AppSocket/HP JetDirect\""); + return (0); + } + else 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/backend/usb.c b/backend/usb.c new file mode 100644 index 0000000000..468112dea9 --- /dev/null +++ b/backend/usb.c @@ -0,0 +1,303 @@ +/* + * "$Id$" + * + * USB port backend for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2000 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 USB port. + * list_devices() - List all USB devices. + */ + +/* + * Include necessary headers. + */ + +#include +#include +#include +#include + +#if defined(WIN32) || defined(__EMX__) +# include +#else +# include +# include +# include +#endif /* WIN32 || __EMX__ */ + + +/* + * Local functions... + */ + +void list_devices(void); + + +/* + * 'main()' - Send a file to the specified USB 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 == 1) + { + list_devices(); + return (0); + } + else if (argc < 6 || argc > 7) + { + fputs("Usage: USB 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 USB port device... + */ + + if ((fd = open(resource, O_WRONLY)) == -1) + { + perror("ERROR: Unable to open USB 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); +} + + +/* + * 'list_devices()' - List all USB devices. + */ + +void +list_devices(void) +{ +#ifdef __linux + int i; /* Looping var */ + int fd; /* File descriptor */ + char device[255]; /* Device filename */ + FILE *probe; /* /proc/parport/n/autoprobe file */ + char line[1024], /* Line from file */ + *delim, /* Delimiter in file */ + make[IPP_MAX_NAME], /* Make from file */ + model[IPP_MAX_NAME]; /* Model from file */ + + + if ((probe = fopen("/proc/bus/usb/devices", "r")) != NULL) + { + i = 0; + + memset(make, 0, sizeof(make)); + memset(model, 0, sizeof(model)); + + while (fgets(line, sizeof(line), probe) != NULL) + { + /* + * Strip trailing newline. + */ + + if ((delim = strrchr(line, '\n')) != NULL) + *delim = '\0'; + + /* + * See if it is a printer device ("P: ...") + */ + + if (strncmp(line, "S:", 2) == 0) + { + /* + * String attribute... + */ + + if (strncmp(line, "S: Manufacturer=", 17) == 0) + { + strncpy(make, line + 17, sizeof(make) - 1); + if (strcmp(make, "Hewlett-Packard") == 0) + strcpy(make, "HP"); + } + else if (strncmp(line, "S: Product=", 12) == 0) + strncpy(model, line + 12, sizeof(model) - 1); + } + else if (strncmp(line, "I:", 2) == 0 && + strstr(line, "Driver=printer") != NULL && + make[0] && model[0]) + { + /* + * We were processing a printer device; send the info out... + */ + + printf("direct usb:/dev/usb/usblp%d \"%s %s\" \"USB Printer #%d\"\n", + i, make, model, i + 1); + + i ++; + + memset(make, 0, sizeof(make)); + memset(model, 0, sizeof(model)); + } + } + + fclose(probe); + } + else + { + for (i = 0; i < 8; i ++) + { + sprintf(device, "/dev/usb/usblp%d", i); + if ((fd = open(device, O_WRONLY)) >= 0) + { + close(fd); + printf("direct usb:%s \"Unknown\" \"USB Printer #%d\"\n", device, i + 1); + } + } + } +#elif defined(__sgi) +#elif defined(__sun) +#elif defined(__hpux) +#elif defined(__osf) +#elif defined(FreeBSD) || defined(OpenBSD) || defined(NetBSD) +#endif +} + + +/* + * End of "$Id$". + */ diff --git a/berkeley/Makefile b/berkeley/Makefile new file mode 100644 index 0000000000..f924bd9f2a --- /dev/null +++ b/berkeley/Makefile @@ -0,0 +1,95 @@ +# +# "$Id$" +# +# Berkeley commands makefile for the Common UNIX Printing System (CUPS). +# +# Copyright 1997-2000 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) + $(CP) lpq lpr lprm $(BINDIR) + -$(MKDIR) $(SBINDIR) + $(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..dc0132a987 --- /dev/null +++ b/berkeley/lpc.c @@ -0,0 +1,467 @@ +/* + * "$Id$" + * + * "lpc" command for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2000 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..bcf56f2a0d --- /dev/null +++ b/berkeley/lpq.c @@ -0,0 +1,483 @@ +/* + * "$Id$" + * + * "lpq" command for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2000 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); +static void show_printer(http_t *, const 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 */ + 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 (;;) + { + if (dest) + show_printer(http, dest); + + i = show_jobs(http, dest, user, id, longstatus); + + if (i && interval) + { + fflush(stdout); + 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 */ + jobcopies, /* Number of copies */ + rank; /* Rank of job */ + char resource[1024]; /* Resource string */ + char rankstr[255]; /* Rank string */ + char namestr[1024]; /* Job name 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... + */ + + jobcount = 0; + + if ((response = cupsDoRequest(http, request, "/jobs/")) != NULL) + { + if (response->request.status.status_code > IPP_OK_CONFLICT) + { + fprintf(stderr, "lpq: get-jobs failed: %s\n", + ippErrorString(response->request.status.status_code)); + ippDelete(response); + return (0); + } + + 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; + jobcopies = 1; + + 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; + + if (strcmp(attr->name, "copies") == 0 && + attr->value_tag == IPP_TAG_INTEGER) + jobcopies = attr->values[0].integer; + + attr = attr->next; + } + + /* + * See if we have everything needed... + */ + + if (jobdest == NULL || jobid == 0) + { + if (attr == NULL) + break; + else + continue; + } + + if (!longstatus && jobcount == 0) + puts("Rank Owner Job Files Total Size"); + + jobcount ++; + + /* + * Display the job... + */ + + if (jobstate == IPP_JOB_PROCESSING) + strcpy(rankstr, "active"); + else + { + sprintf(rankstr, "%d%s\t", rank, ranks[rank % 10]); + rank ++; + } + + if (longstatus) + { + puts(""); + + if (jobcopies > 1) + sprintf(namestr, "%d copies of %s", jobcopies, jobname); + else + strcpy(namestr, jobname); + + printf("%s: %-31s [job %d localhost]\n", jobuser, rankstr, jobid); + printf(" %-31.31s %d bytes\n", namestr, jobsize); + } + else + printf("%-6s %-10.10s %-15d %-27.27s %d bytes\n", rankstr, jobuser, + jobid, jobname, jobsize); + + if (attr == NULL) + break; + } + + ippDelete(response); + } + else + { + fprintf(stderr, "lpq: get-jobs failed: %s\n", ippErrorString(cupsLastError())); + return (0); + } + + if (jobcount == 0) + puts("no entries"); + + return (jobcount); +} + + +/* + * 'show_printer()' - Show printer status. + */ + +static void +show_printer(http_t *http, /* I - HTTP connection to server */ + const char *dest) /* I - Destination */ +{ + ipp_t *request, /* IPP Request */ + *response; /* IPP Response */ + ipp_attribute_t *attr; /* Current attribute */ + cups_lang_t *language; /* Default language */ + const char *printer, /* Printer name */ + *message; /* Printer device URI */ + ipp_pstate_t state; /* Printer state */ + char uri[HTTP_MAX_URI]; + /* Printer URI */ + + + if (http == NULL) + return; + + /* + * Build an 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; + + language = cupsLangDefault(); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, + "attributes-charset", NULL, cupsLangEncoding(language)); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, + "attributes-natural-language", NULL, language->language); + + sprintf(uri, "ipp://localhost/printers/%s", dest); + 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) + { + if (response->request.status.status_code > IPP_OK_CONFLICT) + { + fprintf(stderr, "lpq: get-printer-attributes failed: %s\n", + ippErrorString(response->request.status.status_code)); + ippDelete(response); + return; + } + + if ((attr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM)) != NULL) + state = (ipp_pstate_t)attr->values[0].integer; + else + state = IPP_PRINTER_STOPPED; + + switch (state) + { + case IPP_PRINTER_IDLE : + printf("%s is ready\n", dest); + break; + case IPP_PRINTER_PROCESSING : + printf("%s is ready and printing\n", dest); + break; + case IPP_PRINTER_STOPPED : + printf("%s is not ready\n", dest); + break; + } + + ippDelete(response); + } + else + fprintf(stderr, "lpq: get-printer-attributes failed: %s\n", + ippErrorString(cupsLastError())); +} + + +/* + * End of "$Id$". + */ diff --git a/berkeley/lpr.c b/berkeley/lpr.c new file mode 100644 index 0000000000..5db54c116d --- /dev/null +++ b/berkeley/lpr.c @@ -0,0 +1,318 @@ +/* + * "$Id$" + * + * "lpr" command for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2000 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(int); +#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 */ +#ifdef HAVE_SIGACTION + struct sigaction action; /* Signal action */ +#endif /* HAVE_SIGACTION */ + + + 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\' - %s.\n", + argv[i], ippErrorString(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 +# if defined(HAVE_SIGSET) + sigset(SIGHUP, sighandler); + sigset(SIGINT, sighandler); + sigset(SIGTERM, sighandler); +# elif defined(HAVE_SIGACTION) + memset(&action, 0, sizeof(action)); + action.sa_handler = sighandler; + + sigaction(SIGHUP, &action, NULL); + sigaction(SIGINT, &action, NULL); + sigaction(SIGTERM, &action, NULL); +# else + signal(SIGHUP, sighandler); + signal(SIGINT, sighandler); + signal(SIGTERM, sighandler); +# endif +#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 - %s.\n", + ippErrorString(cupsLastError())); + return (1); + } + } + + return (0); +} + + +#ifndef WIN32 +/* + * 'sighandler()' - Signal catcher for when we print from stdin... + */ + +void +sighandler(int s) /* I - Signal number */ +{ + /* + * Remove the temporary file we're using to print from stdin... + */ + + unlink(tempfile); + + /* + * Exit... + */ + + exit(s); +} +#endif /* !WIN32 */ + + +/* + * End of "$Id$". + */ diff --git a/berkeley/lprm.c b/berkeley/lprm.c new file mode 100644 index 0000000000..4b931a683b --- /dev/null +++ b/berkeley/lprm.c @@ -0,0 +1,221 @@ +/* + * "$Id$" + * + * "lprm" command for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2000 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..32835f50cd --- /dev/null +++ b/cgi-bin/Makefile @@ -0,0 +1,117 @@ +# +# "$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 = admin.cgi classes.cgi jobs.cgi printers.cgi +LIBOBJS = abort.o email.o html.o ipp-var.o template.o var.o +OBJS = $(LIBOBJS) admin.o classes.o jobs.o printers.o + + +# +# Make all targets... +# + +all: $(TARGETS) + + +# +# Clean all object files... +# + +clean: + rm -f $(OBJS) libcgi.a $(TARGETS) + + +# +# Install all targets... +# + +install: + -$(MKDIR) $(SERVERBIN)/cgi-bin + $(CP) $(TARGETS) $(SERVERBIN)/cgi-bin + + +# +# libcgi.a +# + +libcgi.a: $(LIBOBJS) + echo Archiving $@... + $(RM) $@ + $(AR) $(ARFLAGS) $@ $(LIBOBJS) + $(RANLIB) $@ + +$(LIBOBJS): cgi.h +ipp-var.o: ipp-var.h + + +# +# admin.cgi +# + +admin.cgi: admin.o ../Makedefs ../cups/$(LIBCUPS) libcgi.a + echo Linking $@... + $(CC) $(LDFLAGS) -o $@ admin.o libcgi.a $(LIBS) + +admin.o: cgi.h ipp-var.h ../cups/cups.h ../cups/ipp.h ../cups/language.h + + +# +# classes.cgi +# + +classes.cgi: classes.o ../Makedefs ../cups/$(LIBCUPS) libcgi.a + echo Linking $@... + $(CC) $(LDFLAGS) -o $@ classes.o libcgi.a $(LIBS) + +classes.o: cgi.h ipp-var.h ../cups/cups.h ../cups/ipp.h ../cups/language.h + + +# +# jobs.cgi +# + +jobs.cgi: jobs.o ../Makedefs ../cups/$(LIBCUPS) libcgi.a + echo Linking $@... + $(CC) $(LDFLAGS) -o $@ jobs.o libcgi.a $(LIBS) + +jobs.o: cgi.h ipp-var.h ../cups/cups.h ../cups/ipp.h ../cups/language.h + + +# +# printers.cgi +# + +printers.cgi: printers.o ../Makedefs ../cups/$(LIBCUPS) libcgi.a + echo Linking $@... + $(CC) $(LDFLAGS) -o $@ printers.o libcgi.a $(LIBS) + +printers.o: cgi.h ipp-var.h ../cups/cups.h ../cups/ipp.h ../cups/language.h + +$(OBJS): ../Makedefs + +# +# End of "$Id$". +# diff --git a/cgi-bin/admin.c b/cgi-bin/admin.c new file mode 100644 index 0000000000..4639006e8a --- /dev/null +++ b/cgi-bin/admin.c @@ -0,0 +1,891 @@ +/* + * "$Id$" + * + * Administration CGI for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2000 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 "ipp-var.h" + + +/* + * Local functions... + */ + +static void do_am_class(http_t *http, cups_lang_t *language, int modify); +static void do_am_printer(http_t *http, cups_lang_t *language, int modify); +static void do_delete_class(http_t *http, cups_lang_t *language); +static void do_delete_printer(http_t *http, cups_lang_t *language); +static void do_job_op(http_t *http, cups_lang_t *language, ipp_op_t op); +static void do_printer_op(http_t *http, cups_lang_t *language, ipp_op_t op); +static void do_test_page(http_t *http, cups_lang_t *language); + + +/* + * '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 */ + http_t *http; /* Connection to the server */ + const char *op; /* Operation name */ + + + /* + * Get the request language... + */ + + language = cupsLangDefault(); + + /* + * Send a standard header... + */ + + printf("Content-Type: text/html;charset=%s\n\n", cupsLangEncoding(language)); + + cgiSetVariable("TITLE", "Admin"); + cgiSetVariable("SERVER_NAME", getenv("SERVER_NAME")); + cgiSetVariable("REMOTE_USER", getenv("REMOTE_USER")); + cgiSetVariable("CUPS_VERSION", CUPS_SVERSION); + + cgiCopyTemplateFile(stdout, TEMPLATES "/header.tmpl"); + + /* + * See if we have form data... + */ + + if (!cgiInitialize()) + { + /* + * Nope, send the administration menu... + */ + + cgiCopyTemplateFile(stdout, TEMPLATES "/admin.tmpl"); + } + else if ((op = cgiGetVariable("OP")) != NULL) + { + /* + * Connect to the HTTP server... + */ + + http = httpConnect("localhost", ippPort()); + + /* + * Do the operation... + */ + + if (strcmp(op, "cancel-job") == 0) + do_job_op(http, language, IPP_CANCEL_JOB); + else if (strcmp(op, "hold-job") == 0) + do_job_op(http, language, IPP_HOLD_JOB); + else if (strcmp(op, "release-job") == 0) + do_job_op(http, language, IPP_RELEASE_JOB); + else if (strcmp(op, "restart-job") == 0) + do_job_op(http, language, IPP_RESTART_JOB); + else if (strcmp(op, "start-printer") == 0) + do_printer_op(http, language, IPP_RESUME_PRINTER); + else if (strcmp(op, "stop-printer") == 0) + do_printer_op(http, language, IPP_PAUSE_PRINTER); + else if (strcmp(op, "accept-jobs") == 0) + do_printer_op(http, language, CUPS_ACCEPT_JOBS); + else if (strcmp(op, "reject-jobs") == 0) + do_printer_op(http, language, CUPS_REJECT_JOBS); + else if (strcmp(op, "print-test-page") == 0) + do_test_page(http, language); + else if (strcmp(op, "add-class") == 0) + do_am_class(http, language, 0); + else if (strcmp(op, "add-printer") == 0) + do_am_printer(http, language, 0); + else if (strcmp(op, "modify-class") == 0) + do_am_class(http, language, 1); + else if (strcmp(op, "modify-printer") == 0) + do_am_printer(http, language, 1); + else if (strcmp(op, "delete-class") == 0) + do_delete_class(http, language); + else if (strcmp(op, "delete-printer") == 0) + do_delete_printer(http, language); + else + { + /* + * Bad operation code... Display an error... + */ + + cgiCopyTemplateFile(stdout, TEMPLATES "/admin-op.tmpl"); + } + + /* + * Close the HTTP server connection... + */ + + httpClose(http); + } + else + { + /* + * Form data but no operation code... Display an error... + */ + + cgiCopyTemplateFile(stdout, TEMPLATES "/admin-op.tmpl"); + } + + /* + * Send the standard trailer... + */ + + cgiCopyTemplateFile(stdout, TEMPLATES "/trailer.tmpl"); + + /* + * Free the request language... + */ + + cupsLangFree(language); + + /* + * Return with no errors... + */ + + return (0); +} + + +/* + * 'do_am_class()' - Add or modify a class. + */ + +static void +do_am_class(http_t *http, /* I - HTTP connection */ + cups_lang_t *language, /* I - Client's language */ + int modify) /* I - Modify the printer? */ +{ +} + + +/* + * 'do_am_printer()' - Add or modify a printer. + */ + +static void +do_am_printer(http_t *http, /* I - HTTP connection */ + cups_lang_t *language, /* I - Client's language */ + int modify) /* I - Modify the printer? */ +{ + int i; /* Looping var */ + ipp_t *request, /* IPP request */ + *response; /* IPP response */ + ipp_status_t status; /* Request status */ + ipp_attribute_t *attr; /* Response attribute */ + int num_strings; /* Number of strings */ + char **strings; /* Strings */ + const char *var; /* CGI variable */ + char uri[HTTP_MAX_URI], /* Device or printer URI */ + *uriptr; /* Pointer into URI */ + int maxrate; /* Maximum baud rate */ + char baudrate[255]; /* Baud rate string */ + static int baudrates[] = /* Baud rates */ + { + 1200, + 2400, + 4800, + 9600, + 19200, + 38400, + 57600, + 115200, + 230400, + 460800 + }; + + + if (cgiGetVariable("PRINTER_LOCATION") == NULL) + { + if (modify) + { + /* + * Build an 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", + cgiGetVariable("PRINTER_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) + { + ippSetCGIVars(response); + ippDelete(response); + } + + /* + * Update the location and description of an existing printer... + */ + + cgiCopyTemplateFile(stdout, TEMPLATES "/modify-printer.tmpl"); + } + else + { + /* + * Get the name, location, and description for a new printer... + */ + + cgiCopyTemplateFile(stdout, TEMPLATES "/add-printer.tmpl"); + } + } + else if ((var = cgiGetVariable("DEVICE_URI")) == NULL) + { + /* + * Build a CUPS_GET_DEVICES request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + */ + + request = ippNew(); + + request->request.op.operation_id = CUPS_GET_DEVICES; + 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, "printer-uri", + NULL, "ipp://localhost/printers/"); + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoRequest(http, request, "/")) != NULL) + { + ippSetCGIVars(response); + ippDelete(response); + } + + /* + * Let the user choose... + */ + + cgiCopyTemplateFile(stdout, TEMPLATES "/choose-device.tmpl"); + } + else if (strchr(var, '/') == NULL) + { + /* + * User needs to set the full URI... + */ + + cgiCopyTemplateFile(stdout, TEMPLATES "/choose-uri.tmpl"); + } + else if (strncmp(var, "serial:", 7) == 0 && cgiGetVariable("BAUDRATE") == NULL) + { + /* + * Need baud rate, parity, etc. + */ + + if ((var = strchr(var, '?')) != NULL && + strncmp(var, "?baud=", 6) == 0) + maxrate = atoi(var + 6); + else + maxrate = 19200; + + for (i = 0; i < 10; i ++) + if (baudrates[i] > maxrate) + break; + else + { + sprintf(baudrate, "%d", baudrates[i]); + cgiSetArray("BAUDRATES", i, baudrate); + } + + cgiCopyTemplateFile(stdout, TEMPLATES "/choose-serial.tmpl"); + } + else if ((var = cgiGetVariable("PPD_NAME")) == NULL) + { + /* + * Build a CUPS_GET_PPDS request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + */ + + request = ippNew(); + + request->request.op.operation_id = CUPS_GET_PPDS; + 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, "printer-uri", + NULL, "ipp://localhost/printers/"); + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoRequest(http, request, "/")) != NULL) + { + ippSetCGIVars(response); + ippDelete(response); + } + + /* + * Let the user choose... + */ + + cgiCopyTemplateFile(stdout, TEMPLATES "/choose-model.tmpl"); + } + else + { + /* + * Build a CUPS_ADD_PRINTER request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + * printer-location + * printer-info + * ppd-name + * device-uri + * printer-is-accepting-jobs + * printer-state + */ + + request = ippNew(); + + request->request.op.operation_id = CUPS_ADD_PRINTER; + 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", + cgiGetVariable("PRINTER_NAME")); + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", + NULL, uri); + + ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-location", + NULL, cgiGetVariable("PRINTER_LOCATION")); + + ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-info", + NULL, cgiGetVariable("PRINTER_INFO")); + + ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME, "ppd-name", + NULL, cgiGetVariable("PPD_NAME")); + + strcpy(uri, cgiGetVariable("DEVICE_URI")); + if (strncmp(uri, "serial:", 7) == 0) + { + /* + * Update serial port URI to include baud rate, etc. + */ + + if ((uriptr = strchr(uri, '?')) == NULL) + uriptr = uri + strlen(uri); + + sprintf(uriptr, "?baud=%s+bits=%s+parity=%s+flow=%s", + cgiGetVariable("BAUDRATE"), cgiGetVariable("BITS"), + cgiGetVariable("PARITY"), cgiGetVariable("FLOW")); + } + + ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", + NULL, uri); + + ippAddBoolean(request, IPP_TAG_PRINTER, "printer-is-accepting-jobs", 1); + + ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state", + IPP_PRINTER_IDLE); + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoRequest(http, request, "/admin/")) != NULL) + { + status = response->request.status.status_code; + ippDelete(response); + } + else + status = IPP_NOT_AUTHORIZED; + + if (status > IPP_OK_CONFLICT) + { + cgiSetVariable("ERROR", ippErrorString(status)); + cgiCopyTemplateFile(stdout, TEMPLATES "/error.tmpl"); + } + else if (modify) + cgiCopyTemplateFile(stdout, TEMPLATES "/printer-modified.tmpl"); + else + cgiCopyTemplateFile(stdout, TEMPLATES "/printer-added.tmpl"); + } +} + + +/* + * 'do_delete_class()' - Delete a class... + */ + +static void +do_delete_class(http_t *http, /* I - HTTP connection */ + cups_lang_t *language) /* I - Client's language */ +{ + ipp_t *request, /* IPP request */ + *response; /* IPP response */ + char uri[HTTP_MAX_URI]; /* Job URI */ + const char *pclass; /* Printer class name */ + ipp_status_t status; /* Operation status... */ + + + if (cgiGetVariable("CONFIRM") == NULL) + { + cgiCopyTemplateFile(stdout, TEMPLATES "/class-confirm.tmpl"); + return; + } + + if ((pclass = cgiGetVariable("PRINTER_NAME")) != NULL) + snprintf(uri, sizeof(uri), "ipp://localhost/classes/%s", pclass); + else + { + cgiSetVariable("ERROR", ippErrorString(IPP_NOT_FOUND)); + cgiCopyTemplateFile(stdout, TEMPLATES "/error.tmpl"); + return; + } + + /* + * Build a CUPS_DELETE_CLASS request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + */ + + request = ippNew(); + + request->request.op.operation_id = CUPS_DELETE_CLASS; + 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, "printer-uri", + NULL, uri); + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoRequest(http, request, "/admin/")) != NULL) + { + status = response->request.status.status_code; + + ippDelete(response); + } + else + status = IPP_GONE; + + if (status > IPP_OK_CONFLICT) + { + cgiSetVariable("ERROR", ippErrorString(status)); + cgiCopyTemplateFile(stdout, TEMPLATES "/error.tmpl"); + } + else + cgiCopyTemplateFile(stdout, TEMPLATES "/class-deleted.tmpl"); +} + + +/* + * 'do_delete_printer()' - Delete a printer... + */ + +static void +do_delete_printer(http_t *http, /* I - HTTP connection */ + cups_lang_t *language)/* I - Client's language */ +{ + ipp_t *request, /* IPP request */ + *response; /* IPP response */ + char uri[HTTP_MAX_URI]; /* Job URI */ + const char *printer; /* Printer printer name */ + ipp_status_t status; /* Operation status... */ + + + if (cgiGetVariable("CONFIRM") == NULL) + { + cgiCopyTemplateFile(stdout, TEMPLATES "/printer-confirm.tmpl"); + return; + } + + if ((printer = cgiGetVariable("PRINTER_NAME")) != NULL) + snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", printer); + else + { + cgiSetVariable("ERROR", ippErrorString(IPP_NOT_FOUND)); + cgiCopyTemplateFile(stdout, TEMPLATES "/error.tmpl"); + return; + } + + /* + * Build a CUPS_DELETE_PRINTER request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + */ + + request = ippNew(); + + request->request.op.operation_id = CUPS_DELETE_PRINTER; + 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, "printer-uri", + NULL, uri); + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoRequest(http, request, "/admin/")) != NULL) + { + status = response->request.status.status_code; + + ippDelete(response); + } + else + status = IPP_GONE; + + if (status > IPP_OK_CONFLICT) + { + cgiSetVariable("ERROR", ippErrorString(status)); + cgiCopyTemplateFile(stdout, TEMPLATES "/error.tmpl"); + } + else + cgiCopyTemplateFile(stdout, TEMPLATES "/printer-deleted.tmpl"); +} + + +/* + * 'do_job_op()' - Do a job operation. + */ + +static void +do_job_op(http_t *http, /* I - HTTP connection */ + cups_lang_t *language, /* I - Client's language */ + ipp_op_t op) /* I - Operation to perform */ +{ + ipp_t *request, /* IPP request */ + *response; /* IPP response */ + char uri[HTTP_MAX_URI]; /* Job URI */ + const char *job; /* Job ID */ + const char *printer; /* Printer name (purge-jobs) */ + ipp_status_t status; /* Operation status... */ + + + if ((job = cgiGetVariable("JOB_ID")) != NULL) + snprintf(uri, sizeof(uri), "ipp://localhost/jobs/%s", job); + else if ((printer = cgiGetVariable("PRINTER_NAME")) != NULL) + snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", printer); + else + { + cgiSetVariable("ERROR", ippErrorString(IPP_NOT_FOUND)); + cgiCopyTemplateFile(stdout, TEMPLATES "/error.tmpl"); + return; + } + + /* + * Build a job request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * job-uri or printer-uri (purge-jobs) + * requesting-user-name + */ + + request = ippNew(); + + request->request.op.operation_id = op; + 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); + + if (job) + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", + NULL, uri); + else + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", + NULL, uri); + + if (getenv("REMOTE_USER") != NULL) + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", + NULL, getenv("REMOTE_USER")); + else + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", + NULL, "root"); + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoRequest(http, request, "/jobs")) != NULL) + { + status = response->request.status.status_code; + + ippDelete(response); + } + else + status = IPP_GONE; + + if (status > IPP_OK_CONFLICT) + { + cgiSetVariable("ERROR", ippErrorString(status)); + cgiCopyTemplateFile(stdout, TEMPLATES "/error.tmpl"); + } + else if (op == IPP_CANCEL_JOB) + cgiCopyTemplateFile(stdout, TEMPLATES "/job-cancel.tmpl"); + else if (op == IPP_HOLD_JOB) + cgiCopyTemplateFile(stdout, TEMPLATES "/job-hold.tmpl"); + else if (op == IPP_RELEASE_JOB) + cgiCopyTemplateFile(stdout, TEMPLATES "/job-release.tmpl"); +} + + +/* + * 'do_printer_op()' - Do a printer operation. + */ + +static void +do_printer_op(http_t *http, /* I - HTTP connection */ + cups_lang_t *language, /* I - Client's language */ + ipp_op_t op) /* I - Operation to perform */ +{ + ipp_t *request, /* IPP request */ + *response; /* IPP response */ + char uri[HTTP_MAX_URI]; /* Printer URI */ + const char *printer; /* Printer name (purge-jobs) */ + ipp_status_t status; /* Operation status... */ + + + if ((printer = cgiGetVariable("PRINTER_NAME")) != NULL) + snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", printer); + else + { + cgiSetVariable("ERROR", ippErrorString(IPP_NOT_FOUND)); + cgiCopyTemplateFile(stdout, TEMPLATES "/error.tmpl"); + return; + } + + /* + * Build a printer request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + */ + + request = ippNew(); + + request->request.op.operation_id = op; + 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, "printer-uri", + NULL, uri); + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoRequest(http, request, "/admin/")) != NULL) + { + status = response->request.status.status_code; + + ippDelete(response); + } + else + status = IPP_GONE; + + if (status > IPP_OK_CONFLICT) + { + cgiSetVariable("ERROR", ippErrorString(status)); + cgiCopyTemplateFile(stdout, TEMPLATES "/error.tmpl"); + } + else if (op == IPP_PAUSE_PRINTER) + cgiCopyTemplateFile(stdout, TEMPLATES "/printer-stop.tmpl"); + else if (op == IPP_RESUME_PRINTER) + cgiCopyTemplateFile(stdout, TEMPLATES "/printer-start.tmpl"); + else if (op == CUPS_ACCEPT_JOBS) + cgiCopyTemplateFile(stdout, TEMPLATES "/printer-accept.tmpl"); + else if (op == CUPS_REJECT_JOBS) + cgiCopyTemplateFile(stdout, TEMPLATES "/printer-reject.tmpl"); +} + + +/* + * 'do_test_page()' - Send a test page. + */ + +static void +do_test_page(http_t *http, /* I - HTTP connection */ + cups_lang_t *language) /* I - Client's language */ +{ + ipp_t *request, /* IPP request */ + *response; /* IPP response */ + char uri[HTTP_MAX_URI]; /* Job URI */ + const char *printer; /* Printer name (purge-jobs) */ + ipp_status_t status; /* Operation status... */ + + + if ((printer = cgiGetVariable("PRINTER_NAME")) != NULL) + snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", printer); + else + { + cgiSetVariable("ERROR", ippErrorString(IPP_NOT_FOUND)); + cgiCopyTemplateFile(stdout, TEMPLATES "/error.tmpl"); + return; + } + + /* + * Build an IPP_PRINT_JOB request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + * requesting-user-name + * document-format + */ + + 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->language); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", + NULL, uri); + + if (getenv("REMOTE_USER") != NULL) + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", + NULL, getenv("REMOTE_USER")); + else + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", + NULL, "root"); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", + NULL, "Test Page"); + + ippAddString(request, IPP_TAG_JOB, IPP_TAG_MIMETYPE, "document-format", + NULL, "application/postscript"); + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoFileRequest(http, request, uri + 15, + CUPS_DATADIR "/data/testprint.ps")) != NULL) + { + status = response->request.status.status_code; + ippSetCGIVars(response); + + ippDelete(response); + } + else + status = IPP_GONE; + + if (status > IPP_OK_CONFLICT) + { + cgiSetVariable("ERROR", ippErrorString(status)); + cgiCopyTemplateFile(stdout, TEMPLATES "/error.tmpl"); + } + else + cgiCopyTemplateFile(stdout, TEMPLATES "/test-page.tmpl"); +} + + +/* + * End of "$Id$". + */ diff --git a/cgi-bin/cgi.h b/cgi-bin/cgi.h new file mode 100644 index 0000000000..2217bc298f --- /dev/null +++ b/cgi-bin/cgi.h @@ -0,0 +1,81 @@ +/* + * "$Id$" + * + * CGI support library definitions. + * + * Copyright 1997-2000 by Easy Software Products. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _CGI_H_ +# define _CGI_H_ + +# include +# include +# include +# include + +# ifdef WIN32 +# include +# include +# include +# define strcasecmp(s,t) stricmp((s),(t)) +# define strncasecmp(s,t,n) strnicmp((s),(t),(n)) +# else +# include +# endif /* WIN32 */ + + +/* + * Prototypes... + */ + +extern int cgiInitialize(void); +extern void cgiAbort(const char *title, const char *stylesheet, + const char *format, ...); +extern int cgiCheckVariables(const char *names); +extern const char *cgiGetArray(const char *name, int element); +extern int cgiGetSize(const char *name); +extern void cgiSetSize(const char *name, int size); +extern const char *cgiGetVariable(const char *name); +extern void cgiSetArray(const char *name, int element, + const char *value); +extern void cgiSetVariable(const char *name, const char *value); +extern void cgiCopyTemplateFile(FILE *out, const char *template); + +extern void cgiStartHTML(FILE *out, const char *author, + const char *stylesheet, + const char *keywords, + const char *description, + const char *title, ...); +extern void cgiEndHTML(FILE *out); + +extern FILE *cgiEMailOpen(const char *from, const char *to, + const char *cc, const char *subject, + int multipart); +extern void cgiEMailPart(FILE *mail, const char *type, + const char *charset, const char *encoding); +extern void cgiEMailClose(FILE *mail); + + +# define cgiGetUser() getenv("REMOTE_USER") +# define cgiGetHost() (getenv("REMOTE_HOST") == NULL ? getenv("REMOTE_ADDR") : getenv("REMOTE_HOST")) + +#endif /* !_CGI_H_ */ + +/* + * End of "$Id$". + */ diff --git a/cgi-bin/classes.c b/cgi-bin/classes.c new file mode 100644 index 0000000000..d0531dfb57 --- /dev/null +++ b/cgi-bin/classes.c @@ -0,0 +1,221 @@ +/* + * "$Id$" + * + * Class status CGI for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2000 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. + */ + +/* + * Include necessary headers... + */ + +#include "ipp-var.h" + + +/* + * '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 *pclass; /* Printer class name */ + http_t *http; /* Connection to the server */ + ipp_t *request, /* IPP request */ + *response; /* IPP response */ + char uri[HTTP_MAX_URI]; + /* Printer URI */ + const char *which_jobs; /* Which jobs to show */ + + + /* + * Get any form variables... + */ + + cgiInitialize(); + + /* + * 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... + */ + + pclass = argv[0]; + if (strcmp(pclass, "/") == 0 || strcmp(pclass, "classes.cgi") == 0) + { + pclass = NULL; + cgiSetVariable("TITLE", "Classes"); + } + else + cgiSetVariable("TITLE", pclass); + + /* + * Get the printer info... + */ + + request = ippNew(); + + 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 (pclass == NULL) + { + /* + * Build a CUPS_GET_CLASSES request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + */ + + request->request.op.operation_id = CUPS_GET_CLASSES; + request->request.op.request_id = 1; + } + else + { + /* + * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + */ + + request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES; + request->request.op.request_id = 1; + + snprintf(uri, sizeof(uri), "ipp://%s/classes/%s", getenv("SERVER_NAME"), + pclass); + 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) + { + ippSetCGIVars(response); + ippDelete(response); + } + + /* + * Write the report... + */ + + cgiCopyTemplateFile(stdout, TEMPLATES "/header.tmpl"); + cgiCopyTemplateFile(stdout, TEMPLATES "/classes.tmpl"); + + /* + * Get jobs for the specified class if a class has been chosen... + */ + + if (pclass != NULL) + { + /* + * Build an IPP_GET_JOBS request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + */ + + request = ippNew(); + + 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); + + request->request.op.operation_id = IPP_GET_JOBS; + request->request.op.request_id = 1; + + snprintf(uri, sizeof(uri), "ipp://%s/classes/%s", getenv("SERVER_NAME"), + pclass); + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, + uri); + + if ((which_jobs = cgiGetVariable("which_jobs")) != NULL) + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "which-jobs", + NULL, which_jobs); + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoRequest(http, request, "/")) != NULL) + { + ippSetCGIVars(response); + ippDelete(response); + + cgiCopyTemplateFile(stdout, TEMPLATES "/jobs.tmpl"); + } + } + + cgiCopyTemplateFile(stdout, TEMPLATES "/trailer.tmpl"); + + /* + * Close the HTTP server connection... + */ + + httpClose(http); + cupsLangFree(language); + + /* + * Return with no errors... + */ + + return (0); +} + + +/* + * End of "$Id$". + */ diff --git a/cgi-bin/html.c b/cgi-bin/html.c new file mode 100644 index 0000000000..c2b47c4c05 --- /dev/null +++ b/cgi-bin/html.c @@ -0,0 +1,89 @@ +/* + * "$Id$" + * + * CGI HTML functions. + * + * Copyright 1997-2000 by Easy Software Products. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contents: + * + * cgiStartHTML() - Start an HTML document stream. + * cgiEndHTML() - End an HTML document stream. + */ + +#include "cgi.h" +#include + + +/* + * 'cgiStartHTML()' - Start an HTML document stream. + */ + +void +cgiStartHTML(FILE *out, /* I - Output file to use */ + const char *stylesheet, /* I - Stylesheet to use */ + const char *author, /* I - Author name */ + const char *keywords, /* I - Search keywords */ + const char *description, /* I - Description of document */ + const char *title, /* I - Title for page */ + ...) /* I - Any addition args for title */ +{ + va_list ap; /* Argument pointer */ + + + fputs("Content-type: text/html\n\n", out); + fputs("\n", out); + fputs("\n", out); + fputs("\n", out); + + fputs("\t\n", out); + va_start(ap, title); + vfprintf(out, title, ap); + va_end(ap); + fputs("\n", out); + + if (stylesheet) + fprintf(out, "\t\n", + stylesheet); + if (author) + fprintf(out, "\t\n", author); + if (keywords) + fprintf(out, "\t\n", keywords); + if (description) + fprintf(out, "\t\n", description); + + fputs("\n", out); + fputs("\n", out); +} + + +/* + * 'cgiEndHTML()' - End an HTML document stream. + */ + +void +cgiEndHTML(FILE *out) /* I - Output file to use */ +{ + fputs("\n", out); + fputs("\n", out); +} + + +/* + * End of "$Id$". + */ diff --git a/cgi-bin/ipp-var.c b/cgi-bin/ipp-var.c new file mode 100644 index 0000000000..3c61f3a0ba --- /dev/null +++ b/cgi-bin/ipp-var.c @@ -0,0 +1,175 @@ +/* + * "$Id$" + * + * IPP variable 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: + * + * ippSetCGIVars() - Set CGI variables from an IPP response. + */ + +/* + * Include necessary headers... + */ + +#include "ipp-var.h" + + +/* + * 'ippSetCGIVars()' - Set CGI variables from an IPP response. + */ + +void +ippSetCGIVars(ipp_t *response) /* I - Response data to be copied... */ +{ + int element; /* Element in CGI array */ + ipp_attribute_t *attr; /* Attribute in response... */ + int i; /* Looping var */ + char name[1024], /* Name of attribute */ + value[16384], /* Value(s) */ + *valptr; /* Pointer into value */ + char method[HTTP_MAX_URI], + username[HTTP_MAX_URI], + hostname[HTTP_MAX_URI], + resource[HTTP_MAX_URI], + uri[HTTP_MAX_URI]; + int port; + + + cgiSetVariable("SERVER_NAME", getenv("SERVER_NAME")); + cgiSetVariable("REMOTE_USER", getenv("REMOTE_USER")); + cgiSetVariable("CUPS_VERSION", CUPS_SVERSION); + + for (attr = response->attrs; + attr && attr->group_tag == IPP_TAG_OPERATION; + attr = attr->next); + + for (element = 0; attr != NULL; attr = attr->next, element ++) + { + /* + * Copy attributes to a separator... + */ + +/* puts("
");*/ + + for (; attr != NULL && attr->group_tag != IPP_TAG_ZERO; attr = attr->next) + { + /* + * Copy the attribute name, substituting "_" for "-"... + */ + + if (attr->name == NULL) + continue; + +/* printf("

%s\n", attr->name);*/ + + for (i = 0; attr->name[i]; i ++) + if (attr->name[i] == '-') + name[i] = '_'; + else + name[i] = attr->name[i]; + + name[i] = '\0'; + + /* + * Copy values... + */ + + value[0] = '\0'; + valptr = value; + + for (i = 0; i < attr->num_values; i ++) + { + if (i) + strcat(valptr, ","); + + valptr += strlen(valptr); + + switch (attr->value_tag) + { + case IPP_TAG_INTEGER : + case IPP_TAG_ENUM : + sprintf(valptr, "%d", attr->values[i].integer); + break; + + case IPP_TAG_BOOLEAN : + sprintf(valptr, "%d", attr->values[i].boolean); + break; + + case IPP_TAG_NOVALUE : + strcat(valptr, "novalue"); + break; + + case IPP_TAG_RANGE : + sprintf(valptr, "%d-%d", attr->values[i].range.lower, + attr->values[i].range.upper); + break; + + case IPP_TAG_RESOLUTION : + sprintf(valptr, "%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_URI : + if (strncmp(attr->values[i].string.text, "ipp:", 4) == 0) + { + httpSeparate(attr->values[i].string.text, method, username, + hostname, &port, resource); + if (username[0]) + snprintf(uri, sizeof(uri), "http://%s@%s:%d%s", username, + hostname, port, resource); + else + snprintf(uri, sizeof(uri), "http://%s:%d%s", hostname, port, + resource); + + strcat(valptr, uri); + 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 : + strcat(valptr, attr->values[i].string.text); + break; + } + } + + /* + * Add the element... + */ + + cgiSetArray(name, element, value); + } + + if (attr == NULL) + break; + } +} + + +/* + * End of "$Id$". + */ diff --git a/cgi-bin/ipp-var.h b/cgi-bin/ipp-var.h new file mode 100644 index 0000000000..a657b63344 --- /dev/null +++ b/cgi-bin/ipp-var.h @@ -0,0 +1,54 @@ +/* + * "$Id$" + * + * IPP variable definitions for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2000 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 "cgi.h" + + +/* + * Definitions... + */ + +/*#define TEMPLATES "/home/mike/c/cups/templates"*/ +#define TEMPLATES CUPS_DATADIR "/templates" + + +/* + * Prototype... + */ + +extern void ippSetCGIVars(ipp_t *response); + + +/* + * End of "$Id$". + */ diff --git a/cgi-bin/jobs.c b/cgi-bin/jobs.c new file mode 100644 index 0000000000..fe90bbef6d --- /dev/null +++ b/cgi-bin/jobs.c @@ -0,0 +1,140 @@ +/* + * "$Id$" + * + * Job status CGI for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2000 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. + */ + +/* + * Include necessary headers... + */ + +#include "ipp-var.h" + + +/* + * '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 */ + http_t *http; /* Connection to the server */ + const char *which_jobs; /* Which jobs to show */ + ipp_t *request, /* IPP request */ + *response; /* IPP response */ + + + /* + * Get any form variables... + */ + + cgiInitialize(); + + /* + * 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)); + + cgiSetVariable("TITLE", "Jobs"); + cgiSetVariable("SERVER_NAME", getenv("SERVER_NAME")); + cgiSetVariable("REMOTE_USER", getenv("REMOTE_USER")); + cgiSetVariable("CUPS_VERSION", CUPS_SVERSION); + + cgiCopyTemplateFile(stdout, TEMPLATES "/header.tmpl"); + + /* + * Build an IPP_GET_JOBS request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + */ + + request = ippNew(); + + 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); + + request->request.op.operation_id = IPP_GET_JOBS; + request->request.op.request_id = 1; + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, + "ipp://localhost/jobs"); + + if ((which_jobs = cgiGetVariable("which_jobs")) != NULL) + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "which-jobs", + NULL, which_jobs); + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoRequest(http, request, "/")) != NULL) + { + ippSetCGIVars(response); + ippDelete(response); + + cgiCopyTemplateFile(stdout, TEMPLATES "/jobs.tmpl"); + } + + cgiCopyTemplateFile(stdout, TEMPLATES "/trailer.tmpl"); + + /* + * Close the HTTP server connection... + */ + + httpClose(http); + cupsLangFree(language); + + /* + * Return with no errors... + */ + + return (0); +} + + +/* + * End of "$Id$". + */ diff --git a/cgi-bin/printers.c b/cgi-bin/printers.c new file mode 100644 index 0000000000..5a6d3c131c --- /dev/null +++ b/cgi-bin/printers.c @@ -0,0 +1,221 @@ +/* + * "$Id$" + * + * Printer status CGI for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2000 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. + */ + +/* + * Include necessary headers... + */ + +#include "ipp-var.h" + + +/* + * '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 */ + ipp_t *request, /* IPP request */ + *response; /* IPP response */ + char uri[HTTP_MAX_URI]; + /* Printer URI */ + const char *which_jobs; /* Which jobs to show */ + + + /* + * Get any form variables... + */ + + cgiInitialize(); + + /* + * 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; + cgiSetVariable("TITLE", "Printers"); + } + else + cgiSetVariable("TITLE", printer); + + /* + * Get the printer info... + */ + + request = ippNew(); + + 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 (printer == NULL) + { + /* + * Build a CUPS_GET_PRINTERS request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + */ + + request->request.op.operation_id = CUPS_GET_PRINTERS; + request->request.op.request_id = 1; + } + else + { + /* + * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + */ + + request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES; + request->request.op.request_id = 1; + + snprintf(uri, sizeof(uri), "ipp://%s/printers/%s", getenv("SERVER_NAME"), + printer); + 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) + { + ippSetCGIVars(response); + ippDelete(response); + } + + /* + * Write the report... + */ + + cgiCopyTemplateFile(stdout, TEMPLATES "/header.tmpl"); + cgiCopyTemplateFile(stdout, TEMPLATES "/printers.tmpl"); + + /* + * Get jobs for the specified printer if a printer has been chosen... + */ + + if (printer != NULL) + { + /* + * Build an IPP_GET_JOBS request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + */ + + request = ippNew(); + + 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); + + request->request.op.operation_id = IPP_GET_JOBS; + request->request.op.request_id = 1; + + snprintf(uri, sizeof(uri), "ipp://%s/printers/%s", getenv("SERVER_NAME"), + printer); + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, + uri); + + if ((which_jobs = cgiGetVariable("which_jobs")) != NULL) + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "which-jobs", + NULL, which_jobs); + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoRequest(http, request, "/")) != NULL) + { + ippSetCGIVars(response); + ippDelete(response); + + cgiCopyTemplateFile(stdout, TEMPLATES "/jobs.tmpl"); + } + } + + cgiCopyTemplateFile(stdout, TEMPLATES "/trailer.tmpl"); + + /* + * Close the HTTP server connection... + */ + + httpClose(http); + cupsLangFree(language); + + /* + * Return with no errors... + */ + + return (0); +} + + +/* + * End of "$Id$". + */ diff --git a/cgi-bin/template.c b/cgi-bin/template.c new file mode 100644 index 0000000000..4506305eb2 --- /dev/null +++ b/cgi-bin/template.c @@ -0,0 +1,364 @@ +/* + * "$Id$" + * + * CGI template function. + * + * Copyright 1997-2000 by Easy Software Products. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contents: + * + * cgiCopyTemplateFile() - Copy a template file and replace all the + * '{variable}' strings with the variable value. + * cgi_copy() - Copy the template file, substituting as needed... + * cgi_puts() - Put a string to the output file, quoting as + * needed... + */ + +#include "cgi.h" + + +/* + * Local functions... + */ + +static void cgi_copy(FILE *out, FILE *in, int element, char term); +static void cgi_puts(const char *s, FILE *out); + + +/* + * 'cgiCopyTemplateFile()' - Copy a template file and replace all the + * '{variable}' strings with the variable value. + */ + +void +cgiCopyTemplateFile(FILE *out, /* I - Output file */ + const char *template) /* I - Template file to read */ +{ + FILE *in; /* Input file */ + + + /* + * Open the template file... + */ + + if ((in = fopen(template, "r")) == NULL) + return; + + /* + * Parse the file to the end... + */ + + cgi_copy(out, in, 0, 0); + + /* + * Close the template file and return... + */ + + fclose(in); +} + + +/* + * 'cgi_copy()' - Copy the template file, substituting as needed... + */ + +static void +cgi_copy(FILE *out, /* I - Output file */ + FILE *in, /* I - Input file */ + int element, /* I - Element number (0 to N) */ + char term) /* I - Terminating character */ +{ + int ch; /* Character from file */ + char op; /* Operation */ + char name[255], /* Name of variable */ + innername[255], /* Inner comparison name */ + *innerptr, /* Pointer into inner name */ + *s; /* String pointer */ + const char *value; /* Value of variable */ + const char *innerval; /* Inner value */ + char outval[1024], /* Output string */ + compare[1024]; /* Comparison string */ + int result; /* Result of comparison */ + + + /* + * Parse the file to the end... + */ + + while ((ch = getc(in)) != EOF) + if (ch == term) + break; + else if (ch == '{') + { + /* + * Get a variable name... + */ + + for (s = name; (ch = getc(in)) != EOF;) + if (strchr("}]<>=!", ch)) + break; + else if (s > name && ch == '?') + break; + else + *s++ = ch; + + *s = '\0'; + + /* + * See if it has a value... + */ + + if (name[0] == '?') + { + /* + * Insert value only if it exists... + */ + + if ((value = cgiGetArray(name + 1, element)) != NULL) + strcpy(outval, value); + else + outval[0] = '\0'; + } + else if (name[0] == '#') + { + /* + * Insert count... + */ + + if (name[1]) + sprintf(outval, "%d", cgiGetSize(name + 1)); + else + sprintf(outval, "%d", element + 1); + } + else if (name[0] == '[') + { + /* + * Loop for # of elements... + */ + + int i; /* Looping var */ + long pos; /* File position */ + int count; /* Number of elements */ + + + if (isdigit(name[1])) + count = atoi(name + 1); + else + count = cgiGetSize(name + 1); + + pos = ftell(in); + + if (count > 0) + { + for (i = 0; i < count; i ++) + { + fseek(in, pos, SEEK_SET); + cgi_copy(out, in, i, '}'); + } + } + else + cgi_copy(NULL, in, 0, '}'); + + continue; + } + else + { + /* + * Insert variable or variable name (if element is NULL)... + */ + + if ((value = cgiGetArray(name, element)) == NULL) + sprintf(outval, "{%s}", name); + else + strcpy(outval, value); + } + + /* + * See if the terminating character requires another test... + */ + + if (ch == '}') + { + /* + * End of substitution... + */ + + if (out) + cgi_puts(outval, out); + + continue; + } + + /* + * OK, process one of the following checks: + * + * {name?exist:not-exist} Exists? + * {name=value?true:false} Equal + * {namevalue?true:false} Greater than + * {name!value?true:false} Not equal + */ + + if (ch == '?') + { + /* + * Test for existance... + */ + + result = cgiGetArray(name, element) != NULL && outval[0]; + } + else + { + /* + * Compare to a string... + */ + + op = ch; + + for (s = compare; (ch = getc(in)) != EOF;) + if (ch == '?') + break; + else if (ch == '#') + { + sprintf(s, "%d", element + 1); + s += strlen(s); + } + else if (ch == '{') + { + /* + * Grab the value of a variable... + */ + + innerptr = innername; + while ((ch = getc(in)) != EOF && ch != '}') + *innerptr++ = ch; + *innerptr = '\0'; + + if (innername[0] == '#') + sprintf(s, "%d", cgiGetSize(innername + 1)); + else if ((innerptr = strrchr(innername, '-')) != NULL && + isdigit(innerptr[1])) + { + *innerptr++ = '\0'; + if ((innerval = cgiGetArray(innername, atoi(innerptr))) == NULL) + *s = '\0'; + else + strcpy(s, innerval); + } + else if (innername[0] == '?') + { + if ((innerval = cgiGetArray(innername + 1, element)) == NULL) + *s = '\0'; + else + strcpy(s, innerval); + } + else if ((innerval = cgiGetArray(innername, element)) == NULL) + sprintf(s, "{%s}", innername); + else + strcpy(s, innerval); + + s += strlen(s); + } + else if (ch == '\\') + *s++ = getc(in); + else + *s++ = ch; + + *s = '\0'; + + if (ch != '?') + return; + + /* + * Do the comparison... + */ + + switch (op) + { + case '<' : + result = strcasecmp(outval, compare) < 0; + break; + case '>' : + result = strcasecmp(outval, compare) > 0; + break; + case '=' : + result = strcasecmp(outval, compare) == 0; + break; + case '!' : + result = strcasecmp(outval, compare) != 0; + break; + } + } + + if (result) + { + /* + * Comparison true; output first part and ignore second... + */ + + cgi_copy(out, in, element, ':'); + cgi_copy(NULL, in, element, '}'); + } + else + { + /* + * Comparison false; ignore first part and output second... + */ + + cgi_copy(NULL, in, element, ':'); + cgi_copy(out, in, element, '}'); + } + } + else if (ch == '\\') /* Quoted char */ + { + if (out) + putc(getc(in), out); + else + getc(in); + } + else if (out) + putc(ch, out); +} + + +/* + * 'cgi_puts()' - Put a string to the output file, quoting as needed... + */ + +static void +cgi_puts(const char *s, + FILE *out) +{ + while (*s) + { + if (s[0] == '<' && s[1] != '/' && !isalpha(s[1])) + fputs("<", out); + else if (*s == '\"') + fputs(""", out); + else if (s[0] == '&' && isspace(s[1])) + fputs("&", out); + else + putc(*s, out); + + s ++; + } +} + + +/* + * End of "$Id$". + */ diff --git a/cgi-bin/var.c b/cgi-bin/var.c new file mode 100644 index 0000000000..e3607d0bf5 --- /dev/null +++ b/cgi-bin/var.c @@ -0,0 +1,654 @@ +/* + * "$Id$" + * + * CGI form variable and array functions. + * + * Copyright 1997-2000 by Easy Software Products. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contents: + * + * cgiInitialize() - Initialize the CGI variable "database"... + * cgiCheckVariables() - Check for the presence of "required" variables. + * cgiGetArray() - Get an element from a form array... + * cgiGetSize() - Get the size of a form array value. + * cgiGetVariable() - Get a CGI variable from the database... + * cgiSetArray() - Set array element N to the specified string. + * cgiSetVariable() - Set a CGI variable in the database... + * cgi_add_variable() - Add a form variable. + * cgi_compare_variables() - Compare two variables. + * cgi_find_variable() - Find a variable... + * cgi_initialize_get() - Initialize form variables using the GET method. + * cgi_initialize_post() - Initialize variables using the POST method. + * cgi_initialize_string() - Initialize form variables from a string. + * cgi_sort_variables() - Sort all form variables for faster lookup. + */ + +/*#define DEBUG*/ +#include "cgi.h" + + +/* + * Data structure to hold all the CGI form variables and arrays... + */ + +typedef struct +{ + const char *name; /* Name of variable */ + int nvalues, /* Number of values */ + avalues; /* Number of values allocated */ + const char **values; /* Value(s) of variable */ +} var_t; + + +/* + * Local globals... + */ + +static int form_count = 0, /* Form variable count */ + form_alloc = 0; /* Number of variables allocated */ +static var_t *form_vars = NULL; /* Form variables */ + + +/* + * Local functions... + */ + +static void cgi_add_variable(const char *name, int element, + const char *value); +static int cgi_compare_variables(const var_t *v1, const var_t *v2); +static var_t *cgi_find_variable(const char *name); +static int cgi_initialize_get(void); +static int cgi_initialize_post(void); +static int cgi_initialize_string(const char *data); +static void cgi_sort_variables(void); + + +/* + * 'cgiInitialize()' - Initialize the CGI variable "database"... + */ + +int /* O - Non-zero if there was form data */ +cgiInitialize(void) +{ + char *method; /* Form posting method */ + + +#ifdef DEBUG + setbuf(stdout, NULL); + puts("Content-type: text/plain\n"); +#endif /* DEBUG */ + + method = getenv("REQUEST_METHOD"); + + if (method == NULL) + return (0); + + if (strcasecmp(method, "GET") == 0) + return (cgi_initialize_get()); + else if (strcasecmp(method, "POST") == 0) + return (cgi_initialize_post()); + else + return (0); +} + + +/* + * 'cgiCheckVariables()' - Check for the presence of "required" variables. + * + * Names may be separated by spaces and/or commas. + */ + +int /* O - 1 if all variables present, 0 otherwise */ +cgiCheckVariables(const char *names) /* I - Variables to look for */ +{ + char name[255], /* Current variable name */ + *s; /* Pointer in string */ + const char *val; /* Value of variable */ + int element; /* Array element number */ + + + if (names == NULL) + return (1); + + while (*names != '\0') + { + while (*names == ' ' || *names == ',') + names ++; + + for (s = name; *names != '\0' && *names != ' ' && *names != ','; s ++, names ++) + *s = *names; + + *s = 0; + if (name[0] == '\0') + break; + + if ((s = strrchr(name, '-')) != NULL) + { + *s = '\0'; + element = atoi(s + 1) - 1; + val = cgiGetArray(name, element); + } + else + val = cgiGetVariable(name); + + if (val == NULL) + return (0); + + if (*val == '\0') + return (0); /* Can't be blank, either! */ + } + + return (1); +} + + +/* + * 'cgiGetArray()' - Get an element from a form array... + */ + +const char * /* O - Element value or NULL */ +cgiGetArray(const char *name, /* I - Name of array variable */ + int element) /* I - Element number (0 to N) */ +{ + var_t *var; /* Pointer to variable */ + + + if ((var = cgi_find_variable(name)) == NULL) + return (NULL); + + if (var->nvalues == 1) + return (var->values[0]); + + if (element < 0 || element >= var->nvalues) + return (NULL); + + return (var->values[element]); +} + + +/* + * 'cgiGetSize()' - Get the size of a form array value. + */ + +int /* O - Number of elements */ +cgiGetSize(const char *name) /* I - Name of variable */ +{ + var_t *var; /* Pointer to variable */ + + + if ((var = cgi_find_variable(name)) == NULL) + return (0); + + return (var->nvalues); +} + + +/* + * 'cgiGetVariable()' - Get a CGI variable from the database... + * + * Returns NULL if the variable doesn't exist... If the variable is an + * array of values, returns the last element... + */ + +const char * /* O - Value of variable */ +cgiGetVariable(const char *name)/* I - Name of variable */ +{ + const var_t *var; /* Returned variable */ + + + var = cgi_find_variable(name); + +#ifdef DEBUG + if (var == NULL) + printf("cgiGetVariable(\"%s\") is returning NULL...\n", name); + else + printf("cgiGetVariable(\"%s\") is returning \"%s\"...\n", name, + var->values[var->nvalues - 1]); +#endif /* DEBUG */ + + return ((var == NULL) ? NULL : var->values[var->nvalues - 1]); +} + + +/* + * 'cgiSetArray()' - Set array element N to the specified string. + * + * If the variable array is smaller than (element + 1), the intervening + * elements are set to NULL. + */ + +void +cgiSetArray(const char *name, /* I - Name of variable */ + int element, /* I - Element number (0 to N) */ + const char *value) /* I - Value of variable */ +{ + int i; /* Looping var */ + var_t *var; /* Returned variable */ + + + if (name == NULL || value == NULL || element < 0) + return; + + if ((var = cgi_find_variable(name)) == NULL) + { + cgi_add_variable(name, element, value); + cgi_sort_variables(); + } + else + { + if (element >= var->avalues) + { + var->avalues = element + 16; + var->values = (const char **)realloc((void *)(var->values), + sizeof(char *) * var->avalues); + } + + if (element >= var->nvalues) + { + for (i = var->nvalues; i < element; i ++) + var->values[i] = NULL; + + var->nvalues = element + 1; + } + else if (var->values[element]) + free((char *)var->values[element]); + + var->values[element] = strdup(value); + } +} + + +/* + * 'cgiSetSize()' - Set the array size. + */ + +void +cgiSetSize(const char *name, /* I - Name of variable */ + int size) /* I - Number of elements (0 to N) */ +{ + int i; /* Looping var */ + var_t *var; /* Returned variable */ + + + if (name == NULL || size < 0) + return; + + if ((var = cgi_find_variable(name)) == NULL) + return; + + if (size >= var->avalues) + { + var->avalues = size + 16; + var->values = (const char **)realloc((void *)(var->values), + sizeof(char *) * var->avalues); + } + + if (size > var->nvalues) + { + for (i = var->nvalues; i < size; i ++) + var->values[i] = NULL; + } + else if (size < var->nvalues) + { + for (i = size; i < var->nvalues; i ++) + if (var->values[i]) + free((void *)(var->values[i])); + } + + var->nvalues = size; +} + + +/* + * 'cgiSetVariable()' - Set a CGI variable in the database... + * + * If the variable is an array, this truncates the array to a single element. + */ + +void +cgiSetVariable(const char *name, /* I - Name of variable */ + const char *value) /* I - Value of variable */ +{ + int i; /* Looping var */ + var_t *var; /* Returned variable */ + + + if (name == NULL || value == NULL) + return; + + if ((var = cgi_find_variable(name)) == NULL) + { + cgi_add_variable(name, 0, value); + cgi_sort_variables(); + } + else + { + for (i = 0; i < var->nvalues; i ++) + if (var->values[i]) + free((char *)var->values[i]); + + var->values[0] = strdup(value); + var->nvalues = 1; + } +} + + +/* + * 'cgi_add_variable()' - Add a form variable. + */ + +static void +cgi_add_variable(const char *name, /* I - Variable name */ + int element, /* I - Array element number */ + const char *value) /* I - Variable value */ +{ + var_t *var; /* New variable */ + + + if (name == NULL || value == NULL) + return; + +#ifdef DEBUG + printf("Adding variable \'%s\' with value \'%s\'...\n", name, value); +#endif /* DEBUG */ + + if (form_count >= form_alloc) + { + if (form_alloc == 0) + form_vars = malloc(sizeof(var_t) * 16); + else + form_vars = realloc(form_vars, (form_alloc + 16) * sizeof(var_t)); + + form_alloc += 16; + } + + var = form_vars + form_count; + var->name = strdup(name); + var->nvalues = element + 1; + var->avalues = element + 1; + var->values = calloc(element + 1, sizeof(char *)); + var->values[element] = strdup(value); + + form_count ++; +} + + +/* + * 'cgi_compare_variables()' - Compare two variables. + */ + +static int /* O - Result of comparison */ +cgi_compare_variables(const var_t *v1, /* I - First variable */ + const var_t *v2) /* I - Second variable */ +{ + return (strcasecmp(v1->name, v2->name)); +} + + +/* + * 'cgi_find_variable()' - Find a variable... + */ + +static var_t * /* O - Variable pointer or NULL */ +cgi_find_variable(const char *name) /* I - Name of variable */ +{ + var_t key; /* Search key */ + + + if (form_count < 1 || name == NULL) + return (NULL); + + key.name = name; + + return ((var_t *)bsearch(&key, form_vars, form_count, sizeof(var_t), + (int (*)(const void *, const void *))cgi_compare_variables)); +} + + +/* + * 'cgi_initialize_get()' - Initialize form variables using the GET method. + */ + +static int /* O - 1 if form data read */ +cgi_initialize_get(void) +{ + char *data; /* Pointer to form data string */ + + +#ifdef DEBUG + puts("Initializing variables using GET method..."); +#endif /* DEBUG */ + + /* + * Check to see if there is anything for us to read... + */ + + data = getenv("QUERY_STRING"); + if (data == NULL || strlen(data) == 0) + return (0); + + /* + * Parse it out and return... + */ + + return (cgi_initialize_string(data)); +} + + +/* + * 'cgi_initialize_post()' - Initialize variables using the POST method. + */ + +static int /* O - 1 if form data was read */ +cgi_initialize_post(void) +{ + char *content_length, /* Length of input data (string) */ + *data; /* Pointer to form data string */ + int length, /* Length of input data */ + nbytes, /* Number of bytes read this read() */ + tbytes, /* Total number of bytes read */ + status; /* Return status */ + + +#ifdef DEBUG + puts("Initializing variables using POST method..."); +#endif /* DEBUG */ + + /* + * Check to see if there is anything for us to read... + */ + + content_length = getenv("CONTENT_LENGTH"); + if (content_length == NULL || atoi(content_length) == 0) + return (0); + + /* + * Get the length of the input stream and allocate a buffer for it... + */ + + length = atoi(content_length); + data = malloc(length + 1); + + /* + * Read the data into the buffer... + */ + + for (tbytes = 0; tbytes < length; tbytes += nbytes) + if ((nbytes = read(0, data + tbytes, length - tbytes)) < 0) + { + free(data); + return (0); + } + + data[length] = '\0'; + + /* + * Parse it out... + */ + + status = cgi_initialize_string(data); + + /* + * Free the data and return... + */ + + free(data); + + return (status); +} + + +/* + * 'cgi_initialize_string()' - Initialize form variables from a string. + */ + +static int +cgi_initialize_string(const char *data) /* I - Form data string */ +{ + int done; /* True if we're done reading a form variable */ + char *s, /* Pointer to current form string */ + ch, /* Temporary character */ + name[255], /* Name of form variable */ + value[65536]; /* Variable value... */ + + + /* + * Check input... + */ + + if (data == NULL) + return (0); + + /* + * Loop until we've read all the form data... + */ + + while (*data != '\0') + { + /* + * Get the variable name... + */ + + for (s = name; *data != '\0'; data ++, s ++) + if (*data == '=') + break; + else + *s = *data; + + *s = '\0'; + if (*data == '=') + data ++; + else + return (0); + + /* + * Read the variable value... + */ + + for (s = value, done = 0; !done && *data != '\0'; data ++, s ++) + switch (*data) + { + case '&' : /* End of data... */ + done = 1; + s --; + break; + + case '+' : /* Escaped space character */ + *s = ' '; + break; + + case '%' : /* Escaped control character */ + /* + * Read the hex code from stdin... + */ + + data ++; + ch = *data - '0'; + if (ch > 9) + ch -= 7; + *s = ch << 4; + + data ++; + ch = *data - '0'; + if (ch > 9) + ch -= 7; + *s |= ch; + break; + + default : /* Other characters come straight through */ + *s = *data; + break; + } + + *s = '\0'; /* nul terminate the string */ + + /* + * Remove trailing whitespace... + */ + + s --; + while (s >= value && *s == ' ') + *s-- = '\0'; + + /* + * Add the string to the variable "database"... + */ + + if ((s = strrchr(name, '-')) != NULL && isdigit(s[1])) + { + *s++ = '\0'; + cgiSetArray(name, atoi(s) - 1, value); + } + else + cgiSetVariable(name, value); + } + + return (1); +} + + +/* + * 'cgi_sort_variables()' - Sort all form variables for faster lookup. + */ + +static void +cgi_sort_variables(void) +{ +#ifdef DEBUG + int i; + + + puts("Sorting variables..."); +#endif /* DEBUG */ + + if (form_count < 2) + return; + + qsort(form_vars, form_count, sizeof(var_t), + (int (*)(const void *, const void *))cgi_compare_variables); + +#ifdef DEBUG + puts("New variable list is:"); + for (i = 0; i < form_count; i ++) + printf("%s = %s\n", form_vars[i].name, form_vars[i].value); +#endif /* DEBUG */ +} + + +/* + * End of "$Id$". + */ diff --git a/conf/Makefile b/conf/Makefile new file mode 100644 index 0000000000..8905a107a9 --- /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) + for file in $(KEEP); do \ + if test -r $(SERVERROOT)/$$file ; then \ + $(CP) $$file $(SERVERROOT)/$$file.N ; \ + else \ + $(CP) $$file $(SERVERROOT) ; \ + fi ; \ + done + for file in $(REPLACE); do \ + if test -r $(SERVERROOT)/$$file ; then \ + $(MV) $(SERVERROOT)/$$file $(SERVERROOT)/$$file.O ; \ + fi ; \ + $(CP) $$file $(SERVERROOT) ; \ + 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/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..b2a0199328 --- /dev/null +++ b/config.h.in @@ -0,0 +1,121 @@ +/* + * "$Id$" + * + * Configuration file for the Common UNIX Printing System (CUPS). + * + * @configure_input@ + * + * Copyright 1997-2000 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.1b1" + +/* + * Where are files stored? + */ + +#define CUPS_LOCALEDIR "/usr/share/locale" +#define CUPS_SERVERROOT "/etc/cups" +#define CUPS_SERVERBIN "/usr/lib/cups" +#define CUPS_DOCROOT "/usr/share/doc/cups" +#define CUPS_REQUESTS "/var/spool/cups" +#define CUPS_LOGDIR "/var/logs/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..5f14963126 --- /dev/null +++ b/configure.in @@ -0,0 +1,350 @@ +dnl +dnl "$Id$" +dnl +dnl Configuration script for the Common UNIX Printing System (CUPS). +dnl +dnl Copyright 1997-2000 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/[[^0-9]]//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.2" + LIBCUPSIMAGE="libcupsimage.so.2" + DSO="\$(CC) -Wl,-h,\$@ -G \$(OPTIM) -o" + ;; + HP-UX*) + LIBCUPS="libcups.sl.2" + LIBCUPSIMAGE="libcupsimage.sl.2" + DSO="ld -b -z +h \$@ -o" + ;; + FreeBSD* | NetBSD* | OpenBSD*) + LIBCUPS="libcups.so.2" + LIBCUPSIMAGE="libcupsimage.so.2" + DSO="\$(CC) -Wl,-soname,\$@ -shared \$(OPTIM) -o" + ;; + OSF1* | Linux*) + LIBCUPS="libcups.so.2" + LIBCUPSIMAGE="libcupsimage.so.2" + DSO="\$(CC) -Wl,-soname,\$@ -shared \$(OPTIM) -o" + ;; + IRIX*) + LIBCUPS="libcups.so.2" + LIBCUPSIMAGE="libcupsimage.so.2" + DSO="\$(CC) -soname \$@ -shared \$(OPTIM) -o" + ;; + *) + echo "Warning: shared libraries may not be supported. Trying -shared" + echo " option with compiler." + LIBCUPS="libcups.so.2" + LIBCUPSIMAGE="libcupsimage.so.2" + 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(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) + +AC_CHECK_LIB(png, png_read_info, + AC_DEFINE(HAVE_LIBPNG) + LIBPNG="-lpng") + +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 -g3" + fi + if test $PICFLAG = 1; then + OPTIM="-fPIC $OPTIM" + fi +else + case $uname in + IRIX*) + if test -z "$OPTIM"; then + OPTIM="-O2 -g3" + fi + if test $uversion -ge 62; then + OPTIM="$OPTIM -n32 -mips3" + fi + ;; + HP-UX*) + if test -z "$OPTIM"; then + OPTIM="+O2 -g3" + fi + OPTIM="-Ae $OPTIM" + ;; + SunOS*) + # Solaris + if test -z "$OPTIM"; then + OPTIM="-O -g3" + 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 as needed.. +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="${prefix}/lib32" +fi + +dnl Need special attention for the default location... +if test "$prefix" = "/usr" ; then + CUPS_SERVERROOT="/etc/cups" + CUPS_LOGDIR="/var/log/cups" + CUPS_REQUESTS="/var/spool/cups" + + AC_DEFINE_UNQUOTED(CUPS_SERVERROOT, "$CUPS_SERVERROOT") + AC_DEFINE_UNQUOTED(CUPS_LOGDIR, "$CUPS_LOGDIR") + AC_DEFINE_UNQUOTED(CUPS_REQUESTS, "$CUPS_REQUESTS") +else + CUPS_SERVERROOT='${prefix}/etc/cups' + CUPS_LOGDIR='${prefix}/log/cups' + CUPS_REQUESTS='${prefix}/spool/cups' + + AC_DEFINE_UNQUOTED(CUPS_SERVERROOT, "$prefix/etc/cups") + AC_DEFINE_UNQUOTED(CUPS_LOGDIR, "$prefix/log/cups") + AC_DEFINE_UNQUOTED(CUPS_REQUESTS, "$prefix/spool/cups") +fi + +CUPS_SERVERBIN='${prefix}/lib/cups' +AC_DEFINE_UNQUOTED(CUPS_SERVERBIN, "$prefix/lib/cups") + +AC_SUBST(CUPS_SERVERROOT) +AC_SUBST(CUPS_SERVERBIN) +AC_SUBST(CUPS_LOGDIR) +AC_SUBST(CUPS_REQUESTS) + +dnl Set the CUPS_LOCALE directory... +case "$uname" in + Linux) + CUPS_LOCALEDIR='${prefix}/share/locale' + AC_DEFINE_UNQUOTED(CUPS_LOCALEDIR, "$prefix/share/locale") + ;; + + OSF1) + CUPS_LOCALEDIR='${prefix}/lib/nls/msg' + AC_DEFINE_UNQUOTED(CUPS_LOCALEDIR, "$prefix/lib/nls/msg") + ;; + + *) + # This is the standard System V location... + CUPS_LOCALEDIR='${prefix}/lib/locale' + AC_DEFINE_UNQUOTED(CUPS_LOCALEDIR, "$prefix/lib/locale") + ;; +esac + +AC_SUBST(CUPS_LOCALEDIR) + +dnl Set the CUPS_DATADIR directory... +CUPS_DATADIR='${datadir}/cups' +AC_DEFINE_UNQUOTED(CUPS_DATADIR, "$prefix/share/cups") +AC_SUBST(CUPS_DATADIR) + +dnl Set the CUPS_DOCDIR directory... +CUPS_DOCDIR='${datadir}/doc/cups' +AC_DEFINE_UNQUOTED(CUPS_DOCDIR, "$prefix/share/doc/cups") +AC_SUBST(CUPS_DOCDIR) + +AC_OUTPUT(Makedefs) + +dnl +dnl End of "$Id$". +dnl diff --git a/cups.dsw b/cups.dsw new file mode 100644 index 0000000000..2fc669868f --- /dev/null +++ b/cups.dsw @@ -0,0 +1,128 @@ +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: "cupsd"=.\scheduler\cupsd.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name cups + End Project Dependency +}}} + +############################################################################### + +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..560efb5f4a --- /dev/null +++ b/cups.list @@ -0,0 +1,414 @@ +# +# "$Id: cups.list 937 2000-02-28 19:18:57Z mike $" +# +# ESP Package Manager (EPM) file list for the Common UNIX Printing +# System (CUPS). +# +# Copyright 1997-2000 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-2000 by Easy Software Products, All Rights Reserved. +%vendor Easy Software Products +%license LICENSE.txt +%readme README.txt +%version 1.1b1 +%incompat printpro + +%system all +# Server files +f 0555 root sys /usr/lib/cups/backend/ipp backend/ipp +l 0555 root sys /usr/lib/cups/backend/http ipp +f 0555 root sys /usr/lib/cups/backend/lpd backend/lpd +f 0555 root sys /usr/lib/cups/backend/parallel backend/parallel +f 0555 root sys /usr/lib/cups/backend/serial backend/serial +f 0555 root sys /usr/lib/cups/backend/socket backend/socket +f 0555 root sys /usr/lib/cups/backend/usb backend/usb +f 0500 root sys /usr/sbin/cupsd scheduler/cupsd +f 0555 root sys /usr/lib/cups/cgi-bin/admin.cgi cgi-bin/admin.cgi +f 0555 root sys /usr/lib/cups/cgi-bin/classes.cgi cgi-bin/classes.cgi +f 0555 root sys /usr/lib/cups/cgi-bin/jobs.cgi cgi-bin/jobs.cgi +f 0555 root sys /usr/lib/cups/cgi-bin/printers.cgi cgi-bin/printers.cgi +f 0555 root sys /usr/lib/cups/filter/pstoraster pstoraster/pstoraster +l 0555 root sys /usr/lib/cups/filter/pdftops pstoraster +f 0555 root sys /usr/lib/cups/filter/imagetops filter/imagetops +f 0555 root sys /usr/lib/cups/filter/pstops filter/pstops +f 0555 root sys /usr/lib/cups/filter/texttops filter/texttops +f 0555 root sys /usr/lib/cups/filter/rastertoepson filter/rastertoepson +f 0555 root sys /usr/lib/cups/filter/rastertohp filter/rastertohp +f 0555 root sys /usr/lib/cups/filter/hpgltops filter/hpgltops +f 0555 root sys /usr/lib/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/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/lpoptions systemv/lpoptions +f 4555 root sys /usr/bin/lppasswd systemv/lppasswd +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 + +# DSOs +%system hpux +f 0555 root sys /usr/lib/libcups.sl.2 cups/libcups.sl.2 +l 0555 root sys /usr/lib/libcups.sl libcups.sl.2 +f 0555 root sys /usr/lib/libcupsimage.sl.2 filter/libcupsimage.sl.2 +l 0555 root sys /usr/lib/libcupsimage.sl libcupsimage.sl.2 +%system irix-6.5 +f 0555 root sys /usr/lib32/libcups.so.2 cups/libcups.so.2 +l 0555 root sys /usr/lib32/libcups.so libcups.so.2 +f 0555 root sys /usr/lib32/libcupsimage.so.2 filter/libcupsimage.so.2 +l 0555 root sys /usr/lib32/libcupsimage.so libcupsimage.so.2 +%system !irix-6.5 !hpux +f 0555 root sys /usr/lib/libcups.so.2 cups/libcups.so.2 +l 0555 root sys /usr/lib/libcups.so libcups.so.2 +f 0555 root sys /usr/lib/libcupsimage.so.2 filter/libcupsimage.so.2 +l 0555 root sys /usr/lib/libcupsimage.so libcupsimage.so.2 +%system all + +# Directories +d 0711 root sys /etc/cups/certs +d 0755 root sys /etc/cups/interfaces +d 0755 root sys /etc/cups/ppd +d 0755 root sys /var/log/cups +d 0755 root sys /var/spool/cups + +# Data files +%system linux +f 0444 root sys /usr/share/locale/C/cups_C locale/C/cups_C +f 0444 root sys /usr/share/locale/de/cups_de locale/de/cups_de +f 0444 root sys /usr/share/locale/en/cups_en locale/en/cups_en +f 0444 root sys /usr/share/locale/es/cups_es locale/es/cups_es +f 0444 root sys /usr/share/locale/fr/cups_fr locale/fr/cups_fr +f 0444 root sys /usr/share/locale/it/cups_it locale/it/cups_it + +%system dunix +f 0444 root sys /usr/lib/nls/msg/C/cups_C locale/C/cups_C +f 0444 root sys /usr/lib/nls/msg/de/cups_de locale/de/cups_de +f 0444 root sys /usr/lib/nls/msg/en/cups_en locale/en/cups_en +f 0444 root sys /usr/lib/nls/msg/es/cups_es locale/es/cups_es +f 0444 root sys /usr/lib/nls/msg/fr/cups_fr locale/fr/cups_fr +f 0444 root sys /usr/lib/nls/msg/it/cups_it locale/it/cups_it + +%system !linux dunix +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 + +%system all +f 0444 root sys /usr/share/cups/charsets/cp874 data/cp874 +f 0444 root sys /usr/share/cups/charsets/cp1250 data/cp1250 +f 0444 root sys /usr/share/cups/charsets/cp1251 data/cp1251 +f 0444 root sys /usr/share/cups/charsets/cp1252 data/cp1252 +f 0444 root sys /usr/share/cups/charsets/cp1253 data/cp1253 +f 0444 root sys /usr/share/cups/charsets/cp1254 data/cp1254 +f 0444 root sys /usr/share/cups/charsets/cp1255 data/cp1255 +f 0444 root sys /usr/share/cups/charsets/cp1256 data/cp1256 +f 0444 root sys /usr/share/cups/charsets/cp1257 data/cp1257 +f 0444 root sys /usr/share/cups/charsets/cp1258 data/cp1258 +f 0444 root sys /usr/share/cups/charsets/iso-8859-1 data/iso-8859-1 +f 0444 root sys /usr/share/cups/charsets/iso-8859-14 data/iso-8859-14 +f 0444 root sys /usr/share/cups/charsets/iso-8859-15 data/iso-8859-15 +f 0444 root sys /usr/share/cups/charsets/iso-8859-2 data/iso-8859-2 +f 0444 root sys /usr/share/cups/charsets/iso-8859-3 data/iso-8859-3 +f 0444 root sys /usr/share/cups/charsets/iso-8859-4 data/iso-8859-4 +f 0444 root sys /usr/share/cups/charsets/iso-8859-5 data/iso-8859-5 +f 0444 root sys /usr/share/cups/charsets/iso-8859-6 data/iso-8859-6 +f 0444 root sys /usr/share/cups/charsets/iso-8859-7 data/iso-8859-7 +f 0444 root sys /usr/share/cups/charsets/iso-8859-8 data/iso-8859-8 +f 0444 root sys /usr/share/cups/charsets/iso-8859-9 data/iso-8859-9 +f 0444 root sys /usr/share/cups/charsets/utf-8 data/utf-8 + +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 +f 0444 root sys /usr/share/cups/model/stcolor.ppd ppd/stcolor.ppd +f 0444 root sys /usr/share/cups/model/stphoto.ppd ppd/stphoto.ppd + +f 0444 root sys /usr/share/cups/templates/add-class.tmpl templates/add-class.tmpl +f 0444 root sys /usr/share/cups/templates/add-printer.tmpl templates/add-printer.tmpl +f 0444 root sys /usr/share/cups/templates/admin-op.tmpl templates/admin-op.tmpl +f 0444 root sys /usr/share/cups/templates/admin.tmpl templates/admin.tmpl +f 0444 root sys /usr/share/cups/templates/choose-device.tmpl templates/choose-device.tmpl +f 0444 root sys /usr/share/cups/templates/choose-make.tmpl templates/choose-make.tmpl +f 0444 root sys /usr/share/cups/templates/choose-model.tmpl templates/choose-model.tmpl +f 0444 root sys /usr/share/cups/templates/choose-serial.tmpl templates/choose-serial.tmpl +f 0444 root sys /usr/share/cups/templates/choose-uri.tmpl templates/choose-uri.tmpl +f 0444 root sys /usr/share/cups/templates/classes.tmpl templates/classes.tmpl +f 0444 root sys /usr/share/cups/templates/error.tmpl templates/error.tmpl +f 0444 root sys /usr/share/cups/templates/header.tmpl templates/header.tmpl +f 0444 root sys /usr/share/cups/templates/job-cancel.tmpl templates/job-cancel.tmpl +f 0444 root sys /usr/share/cups/templates/job-hold.tmpl templates/job-hold.tmpl +f 0444 root sys /usr/share/cups/templates/job-release.tmpl templates/job-release.tmpl +f 0444 root sys /usr/share/cups/templates/jobs.tmpl templates/jobs.tmpl +f 0444 root sys /usr/share/cups/templates/modify-class.tmpl templates/modify-class.tmpl +f 0444 root sys /usr/share/cups/templates/modify-printer.tmpl templates/modify-printer.tmpl +f 0444 root sys /usr/share/cups/templates/option-boolean.tmpl templates/option-boolean.tmpl +f 0444 root sys /usr/share/cups/templates/option-header.tmpl templates/option-header.tmpl +f 0444 root sys /usr/share/cups/templates/option-pickmany.tmpl templates/option-pickmany.tmpl +f 0444 root sys /usr/share/cups/templates/option-pickone.tmpl templates/option-pickone.tmpl +f 0444 root sys /usr/share/cups/templates/option-trailer.tmpl templates/option-trailer.tmpl +f 0444 root sys /usr/share/cups/templates/printer-accept.tmpl templates/printer-accept.tmpl +f 0444 root sys /usr/share/cups/templates/printer-reject.tmpl templates/printer-reject.tmpl +f 0444 root sys /usr/share/cups/templates/printer-start.tmpl templates/printer-start.tmpl +f 0444 root sys /usr/share/cups/templates/printer-stop.tmpl templates/printer-stop.tmpl +f 0444 root sys /usr/share/cups/templates/printers.tmpl templates/printers.tmpl +f 0444 root sys /usr/share/cups/templates/test-page.tmpl templates/test-page.tmpl +f 0444 root sys /usr/share/cups/templates/trailer.tmpl templates/trailer.tmpl + +# Config files +c 0644 root sys /etc/cups/classes.conf conf/classes.conf +c 0644 root sys /etc/cups/cupsd.conf conf/cupsd.conf +f 0644 root sys /etc/cups/mime.convs conf/mime.convs +f 0644 root sys /etc/cups/mime.types conf/mime.types +c 0644 root sys /etc/cups/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/image.h filter/image.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/ppd.h cups/ppd.h +f 0444 root sys /usr/include/cups/raster.h filter/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/doc/cups/cups.css doc/cups.css +f 0444 root sys /usr/share/doc/cups/documentation.html doc/documentation.html +f 0444 root sys /usr/share/doc/cups/index.html doc/index.html + +f 0444 root sys /usr/share/doc/cups/images/accept-jobs.gif doc/images/accept-jobs.gif +f 0444 root sys /usr/share/doc/cups/images/add-class.gif doc/images/add-class.gif +f 0444 root sys /usr/share/doc/cups/images/add-printer.gif doc/images/add-printer.gif +f 0444 root sys /usr/share/doc/cups/images/cancel-job.gif doc/images/cancel-job.gif +f 0444 root sys /usr/share/doc/cups/images/cancel-jobs.gif doc/images/cancel-jobs.gif +f 0444 root sys /usr/share/doc/cups/images/cancel.gif doc/images/cancel.gif +f 0444 root sys /usr/share/doc/cups/images/classes.gif doc/images/classes.gif +f 0444 root sys /usr/share/doc/cups/images/continue.gif doc/images/continue.gif +f 0444 root sys /usr/share/doc/cups/images/cups-bar.gif doc/images/cups-bar.gif +f 0444 root sys /usr/share/doc/cups/images/cups-block-diagram.gif doc/images/cups-block-diagram.gif +f 0444 root sys /usr/share/doc/cups/images/cups-large.gif doc/images/cups-large.gif +f 0444 root sys /usr/share/doc/cups/images/cups-medium.gif doc/images/cups-medium.gif +f 0444 root sys /usr/share/doc/cups/images/cups-small.gif doc/images/cups-small.gif +f 0444 root sys /usr/share/doc/cups/images/delete-class.gif doc/images/delete-class.gif +f 0444 root sys /usr/share/doc/cups/images/delete-printer.gif doc/images/delete-printer.gif +f 0444 root sys /usr/share/doc/cups/images/hold-job.gif doc/images/hold-job.gif +f 0444 root sys /usr/share/doc/cups/images/left.gif doc/images/left.gif +f 0444 root sys /usr/share/doc/cups/images/logo.gif doc/images/logo.gif +f 0444 root sys /usr/share/doc/cups/images/manage-classes.gif doc/images/manage-classes.gif +f 0444 root sys /usr/share/doc/cups/images/manage-jobs.gif doc/images/manage-jobs.gif +f 0444 root sys /usr/share/doc/cups/images/manage-printers.gif doc/images/manage-printers.gif +f 0444 root sys /usr/share/doc/cups/images/modify-class.gif doc/images/modify-class.gif +f 0444 root sys /usr/share/doc/cups/images/modify-printer.gif doc/images/modify-printer.gif +f 0444 root sys /usr/share/doc/cups/images/navbar.gif doc/images/navbar.gif +f 0444 root sys /usr/share/doc/cups/images/print-test-page.gif doc/images/print-test-page.gif +f 0444 root sys /usr/share/doc/cups/images/printer-idle.gif doc/images/printer-idle.gif +f 0444 root sys /usr/share/doc/cups/images/printer-processing.gif doc/images/printer-processing.gif +f 0444 root sys /usr/share/doc/cups/images/printer-stopped.gif doc/images/printer-stopped.gif +f 0444 root sys /usr/share/doc/cups/images/reject-jobs.gif doc/images/reject-jobs.gif +f 0444 root sys /usr/share/doc/cups/images/release-job.gif doc/images/release-job.gif +f 0444 root sys /usr/share/doc/cups/images/restart-job.gif doc/images/restart-job.gif +f 0444 root sys /usr/share/doc/cups/images/right.gif doc/images/right.gif +f 0444 root sys /usr/share/doc/cups/images/show-active.gif doc/images/show-active.gif +f 0444 root sys /usr/share/doc/cups/images/show-completed.gif doc/images/show-completed.gif +f 0444 root sys /usr/share/doc/cups/images/start-class.gif doc/images/start-class.gif +f 0444 root sys /usr/share/doc/cups/images/start-printer.gif doc/images/start-printer.gif +f 0444 root sys /usr/share/doc/cups/images/stop-class.gif doc/images/stop-class.gif +f 0444 root sys /usr/share/doc/cups/images/stop-printer.gif doc/images/stop-printer.gif + +f 0444 root sys /usr/share/doc/cups/cmp.html doc/cmp.html +f 0444 root sys /usr/share/doc/cups/cmp.pdf doc/cmp.pdf +f 0444 root sys /usr/share/doc/cups/cupsdoc.css doc/cupsdoc.css +f 0444 root sys /usr/share/doc/cups/idd.html doc/idd.html +f 0444 root sys /usr/share/doc/cups/idd.pdf doc/idd.pdf +f 0444 root sys /usr/share/doc/cups/overview.html doc/overview.html +f 0444 root sys /usr/share/doc/cups/overview.pdf doc/overview.pdf +f 0444 root sys /usr/share/doc/cups/sam.html doc/sam.html +f 0444 root sys /usr/share/doc/cups/sam.pdf doc/sam.pdf +f 0444 root sys /usr/share/doc/cups/sdd.html doc/sdd.html +f 0444 root sys /usr/share/doc/cups/sdd.pdf doc/sdd.pdf +f 0444 root sys /usr/share/doc/cups/spm.html doc/spm.html +f 0444 root sys /usr/share/doc/cups/spm.pdf doc/spm.pdf +f 0444 root sys /usr/share/doc/cups/ssr.html doc/ssr.html +f 0444 root sys /usr/share/doc/cups/ssr.pdf doc/ssr.pdf +f 0444 root sys /usr/share/doc/cups/sum.html doc/sum.html +f 0444 root sys /usr/share/doc/cups/sum.pdf doc/sum.pdf + +# Man pages +%system irix +f 0444 root sys /usr/share/catman/a_man/cat1/accept.1 man/accept.8 +l 0444 root sys /usr/share/catman/a_man/cat1/reject.1 accept.1 +f 0444 root sys /usr/share/catman/u_man/cat1/backend.1 man/backend.1 +f 0444 root sys /usr/share/catman/u_man/cat5/classes.conf.5 man/classes.conf.5 +f 0444 root sys /usr/share/catman/u_man/cat5/cupsd.conf.5 man/cupsd.conf.5 +f 0444 root sys /usr/share/catman/a_man/cat1/cupsd.1 man/cupsd.8 +f 0444 root sys /usr/share/catman/a_man/cat1/enable.1 man/enable.8 +l 0444 root sys /usr/share/catman/a_man/cat1/disable.1 enable.1 +f 0444 root sys /usr/share/catman/u_man/cat1/filter.1 man/filter.1 +f 0444 root sys /usr/share/catman/a_man/cat1/lpadmin.1 man/lpadmin.8 +f 0444 root sys /usr/share/catman/a_man/cat1/lpc.1 man/lpc.8 +f 0444 root sys /usr/share/catman/u_man/cat1/lpq.1 man/lpq.1 +f 0444 root sys /usr/share/catman/u_man/cat1/lprm.1 man/lprm.1 +f 0444 root sys /usr/share/catman/u_man/cat1/lpr.1 man/lpr.1 +f 0444 root sys /usr/share/catman/u_man/cat1/lpstat.1 man/lpstat.1 +f 0444 root sys /usr/share/catman/u_man/cat1/lp.1 man/lp.1 +l 0444 root sys /usr/share/catman/u_man/cat1/cancel.1 lp.1 +f 0444 root sys /usr/share/catman/u_man/cat5/mime.convs.5 man/mime.convs.5 +f 0444 root sys /usr/share/catman/u_man/cat5/mime.types.5 man/mime.types.5 +f 0444 root sys /usr/share/catman/u_man/cat5/printers.conf.5 man/printers.conf.5 +%system !irix +f 0444 root sys /usr/man/man8/accept.8 man/accept.man +l 0444 root sys /usr/man/man8/reject.8 accept.man +f 0444 root sys /usr/man/man1/backend.1 man/backend.man +f 0444 root sys /usr/man/man1/classes.conf.5 man/classes.conf.man +f 0444 root sys /usr/man/man8/cupsd.8 man/cupsd.man +f 0444 root sys /usr/man/man5/cupsd.conf.5 man/cupsd.conf.man +f 0444 root sys /usr/man/man8/enable.8 man/enable.man +f 0444 root sys /usr/man/man8/esplicense.8 man/esplicense.man +l 0444 root sys /usr/man/man8/disable.8 enable.man +f 0444 root sys /usr/man/man1/filter.1 man/filter.man +f 0444 root sys /usr/man/man8/lpadmin.8 man/lpadmin.man +f 0444 root sys /usr/man/man8/lpc.8 man/lpc.man +f 0444 root sys /usr/man/man1/lpq.1 man/lpq.man +f 0444 root sys /usr/man/man1/lprm.1 man/lprm.man +f 0444 root sys /usr/man/man1/lpr.1 man/lpr.man +f 0444 root sys /usr/man/man1/lpstat.1 man/lpstat.man +f 0444 root sys /usr/man/man1/lp.1 man/lp.man +l 0444 root sys /usr/man/man1/cancel.1 lp.man +f 0444 root sys /usr/man/man5/mime.convs.5 man/mime.convs.man +f 0444 root sys /usr/man/man5/mime.types.5 man/mime.types.man +f 0444 root sys /usr/man/man5/printers.conf.5 man/printers.conf.man + +# Startup script +%system all +i 0555 root sys cups cups.sh + +# +# End of "$Id: cups.list 937 2000-02-28 19:18:57Z mike $". +# diff --git a/cups.sh b/cups.sh new file mode 100755 index 0000000000..a79cc0b43d --- /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: 02345 99 00 +# description: Startup/shutdown script for the Common UNIX \ +# Printing System (CUPS). +# +# Copyright 1997-2000 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* | Linux*) + 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..05ba3cd313 --- /dev/null +++ b/cups.spec @@ -0,0 +1,116 @@ +# +# "$Id: cups.spec 904 2000-02-18 17:48:09Z mike $" +# +# RPM "spec" file for the Common UNIX Printing System (CUPS). +# +# Original version by Jason McMullan . +# +# Copyright 1999-2000 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.1a8 +Release: 0 +Copyright: GPL +Group: System Environment/Daemons +Source: ftp://ftp.easysw.com/pub/cups/beta/cups-1.1a8-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/rc.d/init.d + +make prefix=$RPM_BUILD_ROOT/usr LOGDIR=$RPM_BUILD_ROOT/var/log/cups \ + REQUESTS=$RPM_BUILD_ROOT/var/spool/cups \ + SERVERROOT=$RPM_BUILD_ROOT/etc/cups install + +install -m 755 -o root -g root cups.sh $RPM_BUILD_ROOT/etc/rc.d/init.d/cups + +%post +/sbin/chkconfig --add cups + +%preun +/sbin/chkconfig --del cups + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +%defattr(-,root,root) +/etc/rc.d/init.d/cups +%config /etc/cups/* +%dir /etc/cups/certs +%dir /etc/cups/interfaces +%dir /etc/cups/ppd +/usr/bin/* +%%attr(4555,root,root) /usr/bin/lppasswd +/usr/lib/* +/usr/man/* +/usr/sbin/* +%dir /usr/share/cups +/usr/share/cups/* +%dir /usr/share/doc/cups +/usr/share/doc/cups/* +%dir /var/cups +/usr/lib/cups/backend/* +/usr/lib/cups/cgi-bin/* +/usr/lib/cups/filter/* +%dir /var/spool/cups +%dir /var/log/cups + +%files devel +%dir /usr/include/cups +/usr/include/cups/* +/usr/lib/*.a + +# +# End of "$Id: cups.spec 904 2000-02-18 17:48:09Z mike $". +# diff --git a/cups/Makefile b/cups/Makefile new file mode 100644 index 0000000000..d714cd89bf --- /dev/null +++ b/cups/Makefile @@ -0,0 +1,141 @@ +# +# "$Id$" +# +# Support library Makefile for the Common UNIX Printing System (CUPS). +# +# Copyright 1997-2000 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 = dest.o emit.o http.o ipp.o language.o mark.o md5.o options.o \ + page.o ppd.o snprintf.o string.o usersys.o util.o +OBJS = $(LIBOBJS) testhttp.o testppd.o + +# +# Header files to install... +# + +HEADERS = cups.h http.h ipp.h language.h ppd.h + +# +# Targets in this directory... +# + +TARGETS = $(LIBCUPS) testhttp 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) .2`; \ + $(LN) $(LIBCUPS) `basename $(LIBCUPS) .2`; \ + fi + +# +# libcups.so.2, libcups.sl.1 +# + +libcups.so.2 libcups.sl.2: $(LIBOBJS) ../Makedefs + echo Linking $@... + $(DSO) $@ $(LIBOBJS) + -$(LN) $@ `basename $@ .2` + +# +# 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 + +dest.o: cups.h http.h ipp.h language.h string.h +emit.o: ppd.h +http.o: http.h ipp.h md5.h string.h +ipp.o: http.h ipp.h string.h language.h +language.o: cups_C.h language.h string.h +mark.o: ppd.h +md5.o: md5.h +options.o: cups.h +page.o: ppd.h +ppd.o: language.h ppd.h +snprintf.o: string.h +string.o: string.h +usersys.o: cups.h +util.o: cups.h http.h ipp.h + +# +# 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 + +# +# 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 + +$(OBJS): ../Makedefs ../config.h + +# +# End of "$Id$". +# diff --git a/cups/cups.dsp b/cups/cups.dsp new file mode 100644 index 0000000000..cef2887657 --- /dev/null +++ b/cups/cups.dsp @@ -0,0 +1,180 @@ +# 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 ".." /I "../visualc" /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=.\snprintf.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..b717961367 --- /dev/null +++ b/cups/cups.h @@ -0,0 +1,145 @@ +/* + * "$Id$" + * + * API definitions for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2000 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 + + +/* + * 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) */ +}; + +typedef struct /**** Printer Options ****/ +{ + char *name; /* Name of option */ + char *value; /* Value of option */ +} cups_option_t; + +typedef struct /**** Destination ****/ +{ + char *name, /* Printer or class name */ + *instance; /* Local instance name */ + int is_default; /* Is this printer the default? */ + int num_options; /* Number of options */ + cups_option_t *options; /* Options */ +} cups_dest_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 cupsAddDest(const char *name, const char *instance, + int num_dests, cups_dest_t **dests); +extern void cupsFreeDests(int num_dests, cups_dest_t *dests); +extern cups_dest_t *cupsGetDest(const char *name, const char *instance, + int num_dests, cups_dest_t *dests); +extern int cupsGetDests(cups_dest_t **dests); +extern void cupsSetDests(int num_dests, cups_dest_t *dests); + +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..d95beb1ed2 --- /dev/null +++ b/cups/cups_C.h @@ -0,0 +1,132 @@ +"us-ascii", +"OK", +"Cancel", +"Help", +"Quit", +"Close", +"Yes", +"No", +"On", +"Off", +"Save", +"Discard", +"Default", +"Options", +"More Info", +"Black", +"Color", +"Cyan", +"Magenta", +"Yellow", +"Copyright 1993-2000 by Easy Software Products, All Rights Reserved.", +"General", +"Printer", +"Image", +"HP-GL/2", +"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", +"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", +"Text", +"Pretty Print", +"Margins", +"Left", +"Right", +"Bottom", +"Top", +"Filename(s)", +"Print", +"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..c7918b9bf3 --- /dev/null +++ b/cups/debug.h @@ -0,0 +1,57 @@ +/* + * "$Id$" + * + * Debugging macros for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2000 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/dest.c b/cups/dest.c new file mode 100644 index 0000000000..6d3e40493d --- /dev/null +++ b/cups/dest.c @@ -0,0 +1,455 @@ +/* + * "$Id$" + * + * User-defined destination (and option) support for the Common UNIX + * Printing System (CUPS). + * + * Copyright 1997-2000 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: + * + * cupsAddDest() - Add a destination to the list of destinations. + * cupsFreeDests() - Free the memory used by the list of destinations. + * cupsGetDest() - Get the named destination from the list. + * cupsGetDests() - Get the list of destinations. + * cupsSetDests() - Set the list of destinations. + */ + +/* + * Include necessary headers... + */ + +#include "cups.h" +#include "string.h" +#include + + +/* + * Local functions... + */ + +static int cups_get_dests(const char *filename, int num_dests, + cups_dest_t **dests); + + +/* + * 'cupsAddDest()' - Add a destination to the list of destinations. + */ + +int /* O - New number of destinations */ +cupsAddDest(const char *name, /* I - Name of destination */ + const char *instance, /* I - Instance of destination */ + int num_dests, /* I - Number of destinations */ + cups_dest_t **dests) /* IO - Destinations */ +{ + int i; /* Looping var */ + cups_dest_t *dest; /* Destination pointer */ + + + if (name == NULL || dests == NULL) + return (0); + + if ((dest = cupsGetDest(name, instance, num_dests, *dests)) != NULL) + return (num_dests); + + /* + * Add new destination... + */ + + if (num_dests == 0) + dest = malloc(sizeof(cups_dest_t)); + else + dest = realloc(*dests, sizeof(cups_dest_t) * (num_dests + 1)); + + if (dest == NULL) + return (num_dests); + + *dests = dest; + + for (i = num_dests; i > 0; i --, dest ++) + if (strcasecmp(name, dest->name) < 0) + break; + else if (instance == NULL && dest->instance != NULL) + break; + else if (instance != NULL && dest->instance == NULL && + strcasecmp(instance, dest->instance) < 0) + break; + + if (i > 0) + memmove(dest + 1, dest, i * sizeof(cups_dest_t)); + + dest->name = strdup(name); + dest->is_default = 0; + dest->num_options = 0; + dest->options = (cups_option_t *)0; + + if (instance == NULL) + dest->instance = NULL; + else + dest->instance = strdup(instance); + + return (num_dests + 1); +} + + +/* + * 'cupsFreeDests()' - Free the memory used by the list of destinations. + */ + +void +cupsFreeDests(int num_dests, /* I - Number of destinations */ + cups_dest_t *dests) /* I - Destinations */ +{ + int i; /* Looping var */ + cups_dest_t *dest; /* Current destination */ + + + if (num_dests == 0 || dests == NULL) + return; + + for (i = num_dests, dest = dests; i > 0; i --, dest ++) + { + free(dest->name); + + if (dest->instance) + free(dest->instance); + + cupsFreeOptions(dest->num_options, dest->options); + } + + free(dests); +} + + +/* + * 'cupsGetDest()' - Get the named destination from the list. + */ + +cups_dest_t * /* O - Destination pointer or NULL */ +cupsGetDest(const char *name, /* I - Name of destination */ + const char *instance, /* I - Instance of destination */ + int num_dests, /* I - Number of destinations */ + cups_dest_t *dests) /* I - Destinations */ +{ + int comp; /* Result of comparison */ + + + if (name == NULL || num_dests == 0 || dests == NULL) + return (NULL); + + while (num_dests > 0) + { + if ((comp = strcasecmp(name, dests->name)) < 0) + return (NULL); + else if (comp == 0) + { + if ((instance == NULL && dests->instance == NULL) || + (instance != NULL && dests->instance != NULL && + strcasecmp(instance, dests->instance) == 0)) + return (dests); + } + + num_dests --; + dests ++; + } + + return (NULL); +} + + +/* + * 'cupsGetDests()' - Get the list of destinations. + */ + +int /* O - Number of destinations */ +cupsGetDests(cups_dest_t **dests) /* O - Destinations */ +{ + int i; /* Looping var */ + int num_dests; /* Number of destinations */ + int count; /* Number of printers/classes */ + char **names; /* Printer/class names */ + cups_dest_t *dest; /* Destination pointer */ + const char *home; /* HOME environment variable */ + char filename[1024]; /* Local ~/.lpoptions file */ + + + /* + * Initialize destination array... + */ + + num_dests = 0; + *dests = (cups_dest_t *)0; + + /* + * Grab all available printers... + */ + + if ((count = cupsGetPrinters(&names)) > 0) + { + for (i = 0; i < count; i ++) + { + num_dests = cupsAddDest(names[i], NULL, num_dests, dests); + free(names[i]); + } + + free(names); + } + + /* + * Grab all available classes... + */ + + if ((count = cupsGetClasses(&names)) > 0) + { + for (i = 0; i < count; i ++) + { + num_dests = cupsAddDest(names[i], NULL, num_dests, dests); + free(names[i]); + } + + free(names); + } + + /* + * Grab the default destination... + */ + + if ((dest = cupsGetDest(cupsGetDefault(), NULL, num_dests, *dests)) != NULL) + dest->is_default = 1; + + /* + * Load the /etc/cups/lpoptions and ~/.lpoptions files... + */ + + num_dests = cups_get_dests(CUPS_SERVERROOT "/lpoptions", num_dests, dests); + + if ((home = getenv("HOME")) != NULL) + { + snprintf(filename, sizeof(filename), "%s/.lpoptions", home); + num_dests = cups_get_dests(filename, num_dests, dests); + } + + /* + * Return the number of destinations... + */ + + return (num_dests); +} + + +/* + * 'cupsSetDests()' - Set the list of destinations. + */ + +void +cupsSetDests(int num_dests, /* I - Number of destinations */ + cups_dest_t *dests) /* I - Destinations */ +{ + int i, j; /* Looping vars */ + cups_dest_t *dest; /* Current destination */ + cups_option_t *option; /* Current option */ + FILE *fp; /* File pointer */ + const char *home; /* HOME environment variable */ + char filename[1024]; /* lpoptions file */ + + + /* + * Figure out which file to write to... + */ + + if (getuid() == 0) + strcpy(filename, CUPS_SERVERROOT "/lpoptions"); + else if ((home = getenv("HOME")) != NULL) + snprintf(filename, sizeof(filename), "%s/.lpoptions", home); + else + return; + + /* + * Try to open the file... + */ + + if ((fp = fopen(filename, "w")) == NULL) + return; + + /* + * Write each printer; each line looks like: + * + * Dest name[/instance] options + * Default name[/instance] options + */ + + for (i = num_dests, dest = dests; i > 0; i --, dest ++) + if (dest->instance != NULL || dest->num_options != 0 || dest->is_default) + { + fprintf(fp, "%s %s", dest->is_default ? "Default" : "Dest", + dest->name); + if (dest->instance) + fprintf(fp, "/%s", dest->instance); + + for (j = dest->num_options, option = dest->options; j > 0; j --, option ++) + fprintf(fp, " %s=%s", option->name, option->value); + + fputs("\n", fp); + } + + /* + * Close the file and return... + */ + + fclose(fp); +} + + +/* + * 'cups_get_dests()' - Get destinations from a file. + */ + +static int /* O - Number of destinations */ +cups_get_dests(const char *filename, /* I - File to read from */ + int num_dests, /* I - Number of destinations */ + cups_dest_t **dests) /* IO - Destinations */ +{ + int i; /* Looping var */ + cups_dest_t *dest; /* Current destination */ + FILE *fp; /* File pointer */ + char line[8192], /* Line from file */ + *lineptr, /* Pointer into line */ + *name, /* Name of destination/option */ + *instance; /* Instance of destination */ + + + /* + * Try to open the file... + */ + + if ((fp = fopen(filename, "r")) == NULL) + return (num_dests); + + /* + * Read each printer; each line looks like: + * + * Dest name[/instance] options + * Default name[/instance] options + */ + + while (fgets(line, sizeof(line), fp) != NULL) + { + /* + * See what type of line it is... + */ + + if (strncasecmp(line, "dest", 4) == 0 && isspace(line[4])) + lineptr = line + 4; + else if (strncasecmp(line, "default", 7) == 0 && isspace(line[7])) + lineptr = line + 7; + else + continue; + + /* + * Skip leading whitespace... + */ + + while (isspace(*lineptr)) + lineptr ++; + + if (!*lineptr) + continue; + + name = lineptr; + + /* + * Search for an instance... + */ + + while (!isspace(*lineptr) && *lineptr && *lineptr != '/') + lineptr ++; + + if (!*lineptr) + continue; + + if (*lineptr == '/') + { + /* + * Found an instance... + */ + + *lineptr++ = '\0'; + instance = lineptr; + + /* + * Search for an instance... + */ + + while (!isspace(*lineptr) && *lineptr) + lineptr ++; + } + else + instance = NULL; + + *lineptr++ = '\0'; + + /* + * Add the destination... + */ + + num_dests = cupsAddDest(name, instance, num_dests, dests); + + if ((dest = cupsGetDest(name, instance, num_dests, *dests)) == NULL) + { + /* + * Out of memory! + */ + + fclose(fp); + return (num_dests); + } + + /* + * Add options until we hit the end of the line... + */ + + dest->num_options = cupsParseOptions(lineptr, dest->num_options, + &(dest->options)); + + /* + * Set this as default if needed... + */ + + if (strncasecmp(line, "default", 7) == 0) + { + for (i = 0; i < num_dests; i ++) + (*dests)[i].is_default = 0; + + dest->is_default = 1; + } + } + + /* + * Close the file and return... + */ + + fclose(fp); + + return (num_dests); +} + + +/* + * End of "$Id$". + */ diff --git a/cups/emit.c b/cups/emit.c new file mode 100644 index 0000000000..be56f5b97c --- /dev/null +++ b/cups/emit.c @@ -0,0 +1,301 @@ +/* + * "$Id$" + * + * PPD code emission routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2000 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/http.c b/cups/http.c new file mode 100644 index 0000000000..1f0aa2877e --- /dev/null +++ b/cups/http.c @@ -0,0 +1,1528 @@ +/* + * "$Id$" + * + * HTTP routines for the Common UNIX Printing System (CUPS) scheduler. + * + * Copyright 1997-2000 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) + { +#if defined(WIN32) || defined(__EMX__) + http->error = WSAGetLastError(); +#else + http->error = errno; +#endif /* WIN32 || __EMX__ */ + 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) + { +#if defined(WIN32) || defined(__EMX__) + http->error = WSAGetLastError(); +#else + http->error = errno; +#endif /* WIN32 || __EMX__ */ + 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 != ':') + { + 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; + } + else + { + /* + * Parse port number... + */ + + *port = 0; + uri ++; + while (isdigit(*uri)) + { + *port = (*port * 10) + *uri - '0'; + uri ++; + } + } + + if (*uri == '\0') + { + /* + * Hostname but no port or path... + */ + + resource[0] = '/'; + resource[1] = '\0'; + return; + } + + /* + * 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) +#if defined(WIN32) || defined(__EMX__) + http->error = WSAGetLastError(); +#else + http->error = errno; +#endif /* WIN32 || __EMX__ */ + + 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 */ + + + 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... + */ + +#if defined(WIN32) || defined(__EMX__) + WSASetLastError(0); +#else + errno = 0; +#endif /* WIN32 || __EMX__ */ + + 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 defined(WIN32) || defined(__EMX__) + if (WSAGetLastError() != http->error) + { + http->error = WSAGetLastError(); + continue; + } + + DEBUG_printf(("httpGets(): recv() error %d!\n", WSAGetLastError())); +#else + if (errno != http->error) + { + http->error = errno; + continue; + } + + DEBUG_printf(("httpGets(): recv() error %d!\n", errno)); +#endif /* WIN32 || __EMX__ */ + + 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..59206ca8b9 --- /dev/null +++ b/cups/http.h @@ -0,0 +1,315 @@ +/* + * "$Id$" + * + * Hyper-Text Transport Protocol definitions for the Common UNIX Printing + * System (CUPS). + * + * Copyright 1997-2000 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__ */ + +# include "md5.h" + + +/* + * 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 authentication types... + */ + +typedef enum +{ + HTTP_AUTH_NONE, /* No authentication in use */ + HTTP_AUTH_BASIC, /* Basic authentication in use */ + HTTP_AUTH_MD5, /* Digest authentication in use */ + HTTP_AUTH_MD5_SESS, /* MD5-session authentication in use */ + HTTP_AUTH_MD5_INT, /* Digest authentication in use for body */ + HTTP_AUTH_MD5_SESS_INT /* MD5-session authentication in use for body */ +} http_auth_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 */ + int auth_type; /* Authentication in use */ + md5_state_t md5_state; /* MD5 state */ + char nonce[HTTP_MAX_VALUE]; + /* Nonce value */ + int nonce_count; /* Nonce count */ +} 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..2eb3fb03ac --- /dev/null +++ b/cups/ipp.c @@ -0,0 +1,1595 @@ +/* + * "$Id$" + * + * Internet Printing Protocol support functions for the Common UNIX + * Printing System (CUPS). + * + * Copyright 1997-2000 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. + * ippErrorString() - Return a textual message for the given error message. + * 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. + * _ipp_add_attr() - Add a new attribute to the request. + * ipp_read() - Semi-blocking read on a HTTP connection... + */ + +/* + * Include necessary headers... + */ + +#include +#include +#include "string.h" +#include "language.h" + +#include "ipp.h" +#include "debug.h" + + +/* + * Local functions... + */ + +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 = _ipp_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 = _ipp_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 = _ipp_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 = _ipp_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 = _ipp_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 = _ipp_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 = _ipp_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 = _ipp_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 = _ipp_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 = _ipp_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 = _ipp_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 = _ipp_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); +} + + +/* + * 'ippErrorString()' - Return a textual message for the given error message. + */ + +const char * /* O - Text string */ +ippErrorString(ipp_status_t error) /* I - Error status */ +{ + static cups_lang_t *language = 0; /* Language info */ + + + /* + * Load the localized message file as needed... + */ + + if (!language) + language = cupsLangDefault(); + + /* + * Return the appropriate message... + */ + + switch (error) + { + case IPP_OK : + case IPP_OK_SUBST : + case IPP_OK_CONFLICT : + return ("OK"); + + case IPP_BAD_REQUEST : + return (cupsLangString(language, HTTP_BAD_REQUEST)); + + case IPP_FORBIDDEN : + return (cupsLangString(language, HTTP_FORBIDDEN)); + + case IPP_NOT_AUTHENTICATED : + case IPP_NOT_AUTHORIZED : + return (cupsLangString(language, HTTP_UNAUTHORIZED)); + + case IPP_NOT_POSSIBLE : + return (cupsLangString(language, HTTP_METHOD_NOT_ALLOWED)); + + case IPP_TIMEOUT : + return (cupsLangString(language, HTTP_REQUEST_TIMEOUT)); + + case IPP_NOT_FOUND : + return (cupsLangString(language, HTTP_NOT_FOUND)); + + case IPP_GONE : + return (cupsLangString(language, HTTP_GONE)); + + case IPP_DOCUMENT_FORMAT : + return (cupsLangString(language, HTTP_UNSUPPORTED_MEDIATYPE)); + + case IPP_CONFLICT : + return (cupsLangString(language, HTTP_CONFLICT)); + + case IPP_INTERNAL_ERROR : + return (cupsLangString(language, HTTP_SERVER_ERROR)); + + case IPP_OPERATION_NOT_SUPPORTED : + case IPP_VERSION_NOT_SUPPORTED : + return (cupsLangString(language, HTTP_NOT_SUPPORTED)); + + case IPP_SERVICE_UNAVAILABLE : + case IPP_DEVICE_UNAVAILABLE : + case IPP_TEMPORARY_ERROR : + case IPP_PRINTER_BUSY : + return (cupsLangString(language, HTTP_SERVICE_UNAVAILABLE)); + + case IPP_NOT_ACCEPTING : + return (cupsLangString(language, CUPS_MSG_NOT_ACCEPTING_JOBS)); + } + + return ("ERROR"); +} + + +/* + * '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); +} + + +/* + * 'ippNew()' - Allocate a new IPP request. + */ + +ipp_t * /* O - New IPP request */ +ippNew(void) +{ + ipp_t *temp; /* New IPP request */ + + + if ((temp = (ipp_t *)calloc(sizeof(ipp_t), 1)) != NULL) + { + /* + * Default to IPP 1.1... + */ + + temp->request.any.version[0] = 1; + temp->request.any.version[1] = 1; + } + + return (temp); +} + + +/* + * '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 = _ipp_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++ = ipp->request.any.version[0]; + *bufptr++ = ipp->request.any.version[1]; + *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)); + + if ((sizeof(buffer) - (bufptr - buffer)) < (n + 2)) + { + if (httpWrite(http, (char *)buffer, bufptr - buffer) < 0) + { + DEBUG_puts("ippWrite: Could not write IPP attribute..."); + return (IPP_ERROR); + } + + bufptr = buffer; + } + + *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); + + if ((sizeof(buffer) - (bufptr - buffer)) < (n + 2)) + { + if (httpWrite(http, (char *)buffer, bufptr - buffer) < 0) + { + DEBUG_puts("ippWrite: Could not write IPP attribute..."); + return (IPP_ERROR); + } + + bufptr = buffer; + } + + *bufptr++ = n >> 8; + *bufptr++ = n; + memcpy(bufptr, attr->values[i].string.charset, n); + bufptr += n; + + n = strlen(attr->values[i].string.text); + + if ((sizeof(buffer) - (bufptr - buffer)) < (n + 2)) + { + if (httpWrite(http, (char *)buffer, bufptr - buffer) < 0) + { + DEBUG_puts("ippWrite: Could not write IPP attribute..."); + return (IPP_ERROR); + } + + bufptr = buffer; + } + + *bufptr++ = n >> 8; + *bufptr++ = n; + memcpy(bufptr, attr->values[i].string.text, n); + bufptr += n; + } + break; + + case IPP_TAG_UNSUPPORTED_VALUE : + case IPP_TAG_DEFAULT : + case IPP_TAG_UNKNOWN : + case IPP_TAG_NOVALUE : + *bufptr++ = 0; + *bufptr++ = 0; + 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)); +} + + +/* + * '_ipp_add_attr()' - Add a new attribute to the request. + */ + +ipp_attribute_t * /* O - New attribute */ +_ipp_add_attr(ipp_t *ipp, /* I - IPP request */ + int num_values) /* I - Number of values */ +{ + ipp_attribute_t *attr; /* New attribute */ + + + DEBUG_printf(("_ipp_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..0a0cab7708 --- /dev/null +++ b/cups/ipp.h @@ -0,0 +1,349 @@ +/* + * "$Id$" + * + * Internet Printing Protocol definitions for the Common UNIX Printing + * System (CUPS). + * + * Copyright 1997-2000 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_CANCELLED, + 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, + 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, + CUPS_GET_DEVICES, + CUPS_GET_PPDS +} 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 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 time_t ippDateToTime(const ipp_uchar_t *date); +extern void ippDelete(ipp_t *ipp); +extern const char *ippErrorString(ipp_status_t error); +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); + +extern ipp_attribute_t *_ipp_add_attr(ipp_t *, int); + + +/* + * 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..5e8cf71428 --- /dev/null +++ b/cups/language.c @@ -0,0 +1,390 @@ +/* + * "$Id$" + * + * I18N/language support for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2000 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..4f5b769547 --- /dev/null +++ b/cups/language.h @@ -0,0 +1,209 @@ +/* + * "$Id$" + * + * Multi-language support for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2000 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_TEXT, + CUPS_MSG_PRETTYPRINT, + CUPS_MSG_MARGINS, + CUPS_MSG_LEFT, + CUPS_MSG_RIGHT, + CUPS_MSG_BOTTOM, + CUPS_MSG_TOP, + CUPS_MSG_FILENAME, + CUPS_MSG_PRINT, + 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..1967df79d0 --- /dev/null +++ b/cups/mark.c @@ -0,0 +1,411 @@ +/* + * "$Id$" + * + * Option marking routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2000 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 */ + + + 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/md5.c b/cups/md5.c new file mode 100644 index 0000000000..707488479d --- /dev/null +++ b/cups/md5.c @@ -0,0 +1,392 @@ +/* + Copyright (C) 1999 Aladdin Enterprises. All rights reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + L. Peter Deutsch + ghost@aladdin.com + + */ +/*$Id$ */ +/* + Independent implementation of MD5 (RFC 1321). + + This code implements the MD5 Algorithm defined in RFC 1321. + It is derived directly from the text of the RFC and not from the + reference implementation. + + The original and principal author of md5.c is L. Peter Deutsch + . Other authors are noted in the change history + that follows (in reverse chronological order): + + 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. + 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). + 1999-05-03 lpd Original version. + */ + +#include "md5.h" + +#ifdef TEST +/* + * Compile with -DTEST to create a self-contained executable test program. + * The test program should print out the same values as given in section + * A.5 of RFC 1321, reproduced below. + */ +#include +main() +{ + static const char *const test[7] = { + "", /*d41d8cd98f00b204e9800998ecf8427e*/ + "a", /*0cc175b9c0f1b6a831c399e269772661*/ + "abc", /*900150983cd24fb0d6963f7d28e17f72*/ + "message digest", /*f96b697d7cb7938d525a2f31aaf161d0*/ + "abcdefghijklmnopqrstuvwxyz", /*c3fcd3d76192e4007dfb496cca67e13b*/ + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + /*d174ab98d277d9f5a5611c2c9f419d9f*/ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890" /*57edf4a22be3c955ac49da2e2107b67a*/ + }; + int i; + + for (i = 0; i < 7; ++i) { + md5_state_t state; + md5_byte_t digest[16]; + int di; + + md5_init(&state); + md5_append(&state, (const md5_byte_t *)test[i], strlen(test[i])); + md5_finish(&state, digest); + printf("MD5 (\"%s\") = ", test[i]); + for (di = 0; di < 16; ++di) + printf("%02x", digest[di]); + printf("\n"); + } + return 0; +} +#endif /* TEST */ + + +/* + * For reference, here is the program that computed the T values. + */ +#if 0 +#include +main() +{ + int i; + for (i = 1; i <= 64; ++i) { + unsigned long v = (unsigned long)(4294967296.0 * fabs(sin((double)i))); + printf("#define T%d 0x%08lx\n", i, v); + } + return 0; +} +#endif +/* + * End of T computation program. + */ +#define T1 0xd76aa478 +#define T2 0xe8c7b756 +#define T3 0x242070db +#define T4 0xc1bdceee +#define T5 0xf57c0faf +#define T6 0x4787c62a +#define T7 0xa8304613 +#define T8 0xfd469501 +#define T9 0x698098d8 +#define T10 0x8b44f7af +#define T11 0xffff5bb1 +#define T12 0x895cd7be +#define T13 0x6b901122 +#define T14 0xfd987193 +#define T15 0xa679438e +#define T16 0x49b40821 +#define T17 0xf61e2562 +#define T18 0xc040b340 +#define T19 0x265e5a51 +#define T20 0xe9b6c7aa +#define T21 0xd62f105d +#define T22 0x02441453 +#define T23 0xd8a1e681 +#define T24 0xe7d3fbc8 +#define T25 0x21e1cde6 +#define T26 0xc33707d6 +#define T27 0xf4d50d87 +#define T28 0x455a14ed +#define T29 0xa9e3e905 +#define T30 0xfcefa3f8 +#define T31 0x676f02d9 +#define T32 0x8d2a4c8a +#define T33 0xfffa3942 +#define T34 0x8771f681 +#define T35 0x6d9d6122 +#define T36 0xfde5380c +#define T37 0xa4beea44 +#define T38 0x4bdecfa9 +#define T39 0xf6bb4b60 +#define T40 0xbebfbc70 +#define T41 0x289b7ec6 +#define T42 0xeaa127fa +#define T43 0xd4ef3085 +#define T44 0x04881d05 +#define T45 0xd9d4d039 +#define T46 0xe6db99e5 +#define T47 0x1fa27cf8 +#define T48 0xc4ac5665 +#define T49 0xf4292244 +#define T50 0x432aff97 +#define T51 0xab9423a7 +#define T52 0xfc93a039 +#define T53 0x655b59c3 +#define T54 0x8f0ccc92 +#define T55 0xffeff47d +#define T56 0x85845dd1 +#define T57 0x6fa87e4f +#define T58 0xfe2ce6e0 +#define T59 0xa3014314 +#define T60 0x4e0811a1 +#define T61 0xf7537e82 +#define T62 0xbd3af235 +#define T63 0x2ad7d2bb +#define T64 0xeb86d391 + +static void +md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) +{ + md5_word_t + a = pms->abcd[0], b = pms->abcd[1], + c = pms->abcd[2], d = pms->abcd[3]; + md5_word_t t; + +#ifndef ARCH_IS_BIG_ENDIAN +# define ARCH_IS_BIG_ENDIAN 1 /* slower, default implementation */ +#endif +#if ARCH_IS_BIG_ENDIAN + + /* + * On big-endian machines, we must arrange the bytes in the right + * order. (This also works on machines of unknown byte order.) + */ + md5_word_t X[16]; + const md5_byte_t *xp = data; + int i; + + for (i = 0; i < 16; ++i, xp += 4) + X[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); + +#else /* !ARCH_IS_BIG_ENDIAN */ + + /* + * On little-endian machines, we can process properly aligned data + * without copying it. + */ + md5_word_t xbuf[16]; + const md5_word_t *X; + + if (!((data - (const md5_byte_t *)0) & 3)) { + /* data are properly aligned */ + X = (const md5_word_t *)data; + } else { + /* not aligned */ + memcpy(xbuf, data, 64); + X = xbuf; + } +#endif + +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) + + /* Round 1. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ +#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + F(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 0, 7, T1); + SET(d, a, b, c, 1, 12, T2); + SET(c, d, a, b, 2, 17, T3); + SET(b, c, d, a, 3, 22, T4); + SET(a, b, c, d, 4, 7, T5); + SET(d, a, b, c, 5, 12, T6); + SET(c, d, a, b, 6, 17, T7); + SET(b, c, d, a, 7, 22, T8); + SET(a, b, c, d, 8, 7, T9); + SET(d, a, b, c, 9, 12, T10); + SET(c, d, a, b, 10, 17, T11); + SET(b, c, d, a, 11, 22, T12); + SET(a, b, c, d, 12, 7, T13); + SET(d, a, b, c, 13, 12, T14); + SET(c, d, a, b, 14, 17, T15); + SET(b, c, d, a, 15, 22, T16); +#undef SET + + /* Round 2. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ +#define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + G(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 1, 5, T17); + SET(d, a, b, c, 6, 9, T18); + SET(c, d, a, b, 11, 14, T19); + SET(b, c, d, a, 0, 20, T20); + SET(a, b, c, d, 5, 5, T21); + SET(d, a, b, c, 10, 9, T22); + SET(c, d, a, b, 15, 14, T23); + SET(b, c, d, a, 4, 20, T24); + SET(a, b, c, d, 9, 5, T25); + SET(d, a, b, c, 14, 9, T26); + SET(c, d, a, b, 3, 14, T27); + SET(b, c, d, a, 8, 20, T28); + SET(a, b, c, d, 13, 5, T29); + SET(d, a, b, c, 2, 9, T30); + SET(c, d, a, b, 7, 14, T31); + SET(b, c, d, a, 12, 20, T32); +#undef SET + + /* Round 3. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + H(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 5, 4, T33); + SET(d, a, b, c, 8, 11, T34); + SET(c, d, a, b, 11, 16, T35); + SET(b, c, d, a, 14, 23, T36); + SET(a, b, c, d, 1, 4, T37); + SET(d, a, b, c, 4, 11, T38); + SET(c, d, a, b, 7, 16, T39); + SET(b, c, d, a, 10, 23, T40); + SET(a, b, c, d, 13, 4, T41); + SET(d, a, b, c, 0, 11, T42); + SET(c, d, a, b, 3, 16, T43); + SET(b, c, d, a, 6, 23, T44); + SET(a, b, c, d, 9, 4, T45); + SET(d, a, b, c, 12, 11, T46); + SET(c, d, a, b, 15, 16, T47); + SET(b, c, d, a, 2, 23, T48); +#undef SET + + /* Round 4. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ +#define I(x, y, z) ((y) ^ ((x) | ~(z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + I(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 0, 6, T49); + SET(d, a, b, c, 7, 10, T50); + SET(c, d, a, b, 14, 15, T51); + SET(b, c, d, a, 5, 21, T52); + SET(a, b, c, d, 12, 6, T53); + SET(d, a, b, c, 3, 10, T54); + SET(c, d, a, b, 10, 15, T55); + SET(b, c, d, a, 1, 21, T56); + SET(a, b, c, d, 8, 6, T57); + SET(d, a, b, c, 15, 10, T58); + SET(c, d, a, b, 6, 15, T59); + SET(b, c, d, a, 13, 21, T60); + SET(a, b, c, d, 4, 6, T61); + SET(d, a, b, c, 11, 10, T62); + SET(c, d, a, b, 2, 15, T63); + SET(b, c, d, a, 9, 21, T64); +#undef SET + + /* Then perform the following additions. (That is increment each + of the four registers by the value it had before this block + was started.) */ + pms->abcd[0] += a; + pms->abcd[1] += b; + pms->abcd[2] += c; + pms->abcd[3] += d; +} + +void +md5_init(md5_state_t *pms) +{ + pms->count[0] = pms->count[1] = 0; + pms->abcd[0] = 0x67452301; + pms->abcd[1] = 0xefcdab89; + pms->abcd[2] = 0x98badcfe; + pms->abcd[3] = 0x10325476; +} + +void +md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes) +{ + const md5_byte_t *p = data; + int left = nbytes; + int offset = (pms->count[0] >> 3) & 63; + md5_word_t nbits = (md5_word_t)(nbytes << 3); + + if (nbytes <= 0) + return; + + /* Update the message length. */ + pms->count[1] += nbytes >> 29; + pms->count[0] += nbits; + if (pms->count[0] < nbits) + pms->count[1]++; + + /* Process an initial partial block. */ + if (offset) { + int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); + + memcpy(pms->buf + offset, p, copy); + if (offset + copy < 64) + return; + p += copy; + left -= copy; + md5_process(pms, pms->buf); + } + + /* Process full blocks. */ + for (; left >= 64; p += 64, left -= 64) + md5_process(pms, p); + + /* Process a final partial block. */ + if (left) + memcpy(pms->buf, p, left); +} + +void +md5_finish(md5_state_t *pms, md5_byte_t digest[16]) +{ + static const md5_byte_t pad[64] = { + 0x80, 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, 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 + }; + md5_byte_t data[8]; + int i; + + /* Save the length before padding. */ + for (i = 0; i < 8; ++i) + data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); + /* Pad to 56 bytes mod 64. */ + md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); + /* Append the length. */ + md5_append(pms, data, 8); + for (i = 0; i < 16; ++i) + digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); +} diff --git a/cups/md5.h b/cups/md5.h new file mode 100644 index 0000000000..a2d7b34156 --- /dev/null +++ b/cups/md5.h @@ -0,0 +1,94 @@ +/* + Copyright (C) 1999 Aladdin Enterprises. All rights reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + L. Peter Deutsch + ghost@aladdin.com + + */ +/*$Id$ */ +/* + Independent implementation of MD5 (RFC 1321). + + This code implements the MD5 Algorithm defined in RFC 1321. + It is derived directly from the text of the RFC and not from the + reference implementation. + + The original and principal author of md5.h is L. Peter Deutsch + . Other authors are noted in the change history + that follows (in reverse chronological order): + + 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. + 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); + added conditionalization for C++ compilation from Martin + Purschke . + 1999-05-03 lpd Original version. + */ + +#ifndef md5_INCLUDED +# define md5_INCLUDED + +/* + * This code has some adaptations for the Ghostscript environment, but it + * will compile and run correctly in any environment with 8-bit chars and + * 32-bit ints. Specifically, it assumes that if the following are + * defined, they have the same meaning as in Ghostscript: P1, P2, P3, + * ARCH_IS_BIG_ENDIAN. + */ + +typedef unsigned char md5_byte_t; /* 8-bit byte */ +typedef unsigned int md5_word_t; /* 32-bit word */ + +/* Define the state of the MD5 Algorithm. */ +typedef struct md5_state_s { + md5_word_t count[2]; /* message length in bits, lsw first */ + md5_word_t abcd[4]; /* digest buffer */ + md5_byte_t buf[64]; /* accumulate block */ +} md5_state_t; + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Initialize the algorithm. */ +#ifdef P1 +void md5_init(P1(md5_state_t *pms)); +#else +void md5_init(md5_state_t *pms); +#endif + +/* Append a string to the message. */ +#ifdef P3 +void md5_append(P3(md5_state_t *pms, const md5_byte_t *data, int nbytes)); +#else +void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); +#endif + +/* Finish the message and return the digest. */ +#ifdef P2 +void md5_finish(P2(md5_state_t *pms, md5_byte_t digest[16])); +#else +void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); +#endif + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif /* md5_INCLUDED */ diff --git a/cups/options.c b/cups/options.c new file mode 100644 index 0000000000..d8170ca5be --- /dev/null +++ b/cups/options.c @@ -0,0 +1,379 @@ +/* + * "$Id$" + * + * Option routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2000 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 || + strcasecmp(options->name, "printer-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..b9a206948b --- /dev/null +++ b/cups/page.c @@ -0,0 +1,189 @@ +/* + * "$Id$" + * + * Page size functions for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2000 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.0f; + ppd->sizes[i].length = l * 72.0f; + ppd->sizes[i].left = ppd->custom_margins[0]; + ppd->sizes[i].bottom = ppd->custom_margins[1]; + ppd->sizes[i].right = w * 72.0f - ppd->custom_margins[2]; + ppd->sizes[i].top = l * 72.0f - ppd->custom_margins[3]; + } + else if (strcasecmp(units, "cm") == 0) + { + ppd->sizes[i].width = w / 2.54f * 72.0f; + ppd->sizes[i].length = l / 2.54f * 72.0f; + ppd->sizes[i].left = ppd->custom_margins[0]; + ppd->sizes[i].bottom = ppd->custom_margins[1]; + ppd->sizes[i].right = w / 2.54f * 72.0f - ppd->custom_margins[2]; + ppd->sizes[i].top = l / 2.54f * 72.0f - ppd->custom_margins[3]; + } + else if (strcasecmp(units, "mm") == 0) + { + ppd->sizes[i].width = w / 25.4f * 72.0f; + ppd->sizes[i].length = l / 25.4f * 72.0f; + ppd->sizes[i].left = ppd->custom_margins[0]; + ppd->sizes[i].bottom = ppd->custom_margins[1]; + ppd->sizes[i].right = w / 25.4f * 72.0f - ppd->custom_margins[2]; + ppd->sizes[i].top = l / 25.4f * 72.0f - 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..2e84cdbca4 --- /dev/null +++ b/cups/ppd.c @@ -0,0 +1,1816 @@ +/* + * "$Id$" + * + * PPD file routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2000 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, "Throughput") == 0) + ppd->throughput = atoi(string); + 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] = (float)atof(string); + else if (strcmp(keyword, "MaxMediaHeight") == 0) + ppd->custom_max[1] = (float)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..c093e454c8 --- /dev/null +++ b/cups/ppd.h @@ -0,0 +1,240 @@ +/* + * "$Id$" + * + * PostScript Printer Description definitions for the Common UNIX Printing + * System (CUPS). + * + * Copyright 1997-2000 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 */ + throughput; /* Pages per minute */ + 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/snprintf.c b/cups/snprintf.c new file mode 100644 index 0000000000..2cb180ed95 --- /dev/null +++ b/cups/snprintf.c @@ -0,0 +1,287 @@ +/* + * "$Id$" + * + * snprintf functions for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2000 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..b295162c73 --- /dev/null +++ b/cups/string.c @@ -0,0 +1,125 @@ +/* + * "$Id$" + * + * String functions for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2000 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..5c3464ae76 --- /dev/null +++ b/cups/string.h @@ -0,0 +1,94 @@ +/* + * "$Id$" + * + * String definitions for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2000 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..9d1dde6593 --- /dev/null +++ b/cups/testhttp.c @@ -0,0 +1,109 @@ +/* + * "$Id$" + * + * HTTP test program for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2000 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.dsp b/cups/testmime.dsp new file mode 100644 index 0000000000..33fbd301af --- /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 ".." /I "../visualc" /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..f998614a2b --- /dev/null +++ b/cups/testppd.c @@ -0,0 +1,183 @@ +/* + * "$Id$" + * + * PPD test program for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2000 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..27d4f035ce --- /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 ".." /I "../visualc" /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/usersys.c b/cups/usersys.c new file mode 100644 index 0000000000..359f031f2c --- /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-2000 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..ce5732f112 --- /dev/null +++ b/cups/util.c @@ -0,0 +1,1230 @@ +/* + * "$Id$" + * + * Printing utilities for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2000 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... + * cups_local_auth() - Get the local authorization certificate if + * available/applicable... + */ + +/* + * 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); +static int cups_local_auth(http_t *http); + + +/* + * '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)) + { + last_error = IPP_SERVICE_UNAVAILABLE; + 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); + last_error = IPP_NOT_FOUND; + return (NULL); + } + + if ((file = fopen(filename, "rb")) == NULL) + { + /* + * Can't open file! + */ + + ippDelete(request); + last_error = IPP_NOT_FOUND; + 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); + + /* + * See if we can do local authentication... + */ + + if (cups_local_auth(http)) + continue; + + /* + * Nope - get a password from the user... + */ + + 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 defined(WIN32) || defined(__EMX__) + if (http->error != WSAENETDOWN && http->error != WSAENETUNREACH) +#else + if (http->error != ENETDOWN && http->error != ENETUNREACH) +#endif /* WIN32 || __EMX__ */ + 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; + + last_error = IPP_SERVICE_UNAVAILABLE; + + /* + * 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); + + if (response) + last_error = response->request.status.status_code; + else if (status == HTTP_NOT_FOUND) + last_error = IPP_NOT_FOUND; + else if (status == HTTP_UNAUTHORIZED) + last_error = IPP_NOT_AUTHORIZED; + else if (status != HTTP_OK) + last_error = IPP_SERVICE_UNAVAILABLE; + + 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)) + { + last_error = IPP_SERVICE_UNAVAILABLE; + 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 */ + const char *var; /* Environment variable */ + static char def_printer[64];/* Default printer */ + + + /* + * First see if the LPDEST or PRINTER environment variables are + * set... However, if PRINTER is set to "lp", ignore it to work + * around a "feature" in most Linux distributions - the default + * user login scripts set PRINTER to "lp"... + */ + + if ((var = getenv("LPDEST")) != NULL) + return (var); + else if ((var = getenv("PRINTER")) != NULL && strcmp(var, "lp") != 0) + return (var); + + /* + * Try to connect to the server... + */ + + if (!cups_connect("default", NULL, NULL)) + { + last_error = IPP_SERVICE_UNAVAILABLE; + 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)) + { + last_error = IPP_SERVICE_UNAVAILABLE; + 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); + + /* + * See if we can do local authentication... + */ + + if (cups_local_auth(cups_server)) + continue; + + /* + * Nope, get a password from the user... + */ + + 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)) + { + last_error = IPP_SERVICE_UNAVAILABLE; + 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))); + last_error = IPP_SERVICE_UNAVAILABLE; + 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 ((int)(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); +} + + +/* + * 'cups_local_auth()' - Get the local authorization certificate if + * available/applicable... + */ + +static int /* O - 1 if available, 0 if not */ +cups_local_auth(http_t *http) /* I - Connection */ +{ +#if defined(WIN32) || defined(__EMX__) + /* + * Currently WIN32 and OS-2 do not support the CUPS server... + */ + + return (0); +#else + int pid; /* Current process ID */ + FILE *fp; /* Certificate file */ + char filename[1024], /* Certificate filename */ + certificate[33]; /* Certificate string */ + + + /* + * See if we are accessing localhost... + */ + + if (ntohl(http->hostaddr.sin_addr.s_addr) != 0x7f000001 && + strcasecmp(http->hostname, "localhost") != 0) + return (0); + + /* + * Try opening a certificate file for this PID. If that fails, + * try the root certificate... + */ + + pid = getpid(); + sprintf(filename, CUPS_SERVERROOT "/certs/%d", pid); + if ((fp = fopen(filename, "r")) == NULL && pid > 0) + fp = fopen(CUPS_SERVERROOT "/certs/0", "r"); + + if (fp == NULL) + return (0); + + /* + * Read the certificate from the file... + */ + + fgets(certificate, sizeof(certificate), fp); + fclose(fp); + + /* + * Set the authorization string and return... + */ + + sprintf(authstring, "Local %s", certificate); + + return (1); +#endif /* WIN32 || __EMX__ */ +} + + +/* + * End of "$Id$". + */ diff --git a/data/HPGLprolog b/data/HPGLprolog new file mode 100644 index 0000000000..21b244ca23 --- /dev/null +++ b/data/HPGLprolog @@ -0,0 +1,37 @@ +%%BeginResource: procset hpgltops 1.1 0 +% +% "$Id: HPGLprolog 932 2000-02-26 20:01:37Z mike $" +% +% HP-GL/2 filter procset for the Common UNIX Printing System (CUPS). +% +% This procset contains the basic drawing commands that are used to +% reduce output size. Note the 'MP' (make newpath) definition - this +% should be called 'NP' (newpath), but GhostScript uses the 'NP' name +% for 'noaccess put' in some of its font files... +% +% Copyright 1993-2000 Easy Software Products +% +% These coded instructions, statements, and computer programs are the +% property of Easy Software Products and are protected by Federal +% copyright law. Distribution and use rights are outlined in the file +% "LICENSE.txt" which should have been included with this file. If this +% file is missing or damaged please contact Easy Software Products +% at: +% +% Attn: CUPS Licensing Information +% Easy Software Products +% 44141 Airport View Drive, Suite 204 +% Hollywood, Maryland 20636-3111 USA +% +% Voice: (301) 373-9603 +% EMail: cups-info@cups.org +% WWW: http://www.cups.org +% +/MO { moveto } bind def +/LI { lineto } bind def +/FI { fill } bind def +/ST { stroke } bind def +/CP { closepath } bind def +/MP { newpath } bind def +/SP { setlinewidth setrgbcolor } bind def +%%EndResource diff --git a/data/Makefile b/data/Makefile new file mode 100644 index 0000000000..dfa1dbd637 --- /dev/null +++ b/data/Makefile @@ -0,0 +1,86 @@ +# +# "$Id$" +# +# Datafile makefile for the Common UNIX Printing System (CUPS). +# +# Copyright 1993-2000 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... +# + +CHARSETS = cp874 \ + cp1250 \ + cp1251 \ + cp1252 \ + cp1253 \ + cp1254 \ + cp1255 \ + cp1256 \ + cp1257 \ + cp1258 \ + 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-10 \ + iso-8859-13 \ + iso-8859-14 \ + iso-8859-15 \ + utf-8 +DATAFILES = HPGLprolog psglyphs + + +# +# Make everything... +# + +all: + + +# +# Clean all config and object files... +# + +clean: + + +# +# Install files... +# + +install: + -$(MKDIR) $(DATADIR) + -$(MKDIR) $(DATADIR)/data + $(CP) $(DATAFILES) $(DATADIR)/data + -$(MKDIR) $(DATADIR)/charsets + $(CP) $(CHARSETS) $(DATADIR)/charsets + + +# +# End of "$Id$". +# diff --git a/data/iso-8859-1 b/data/iso-8859-1 new file mode 100644 index 0000000000..86b8c90886 --- /dev/null +++ b/data/iso-8859-1 @@ -0,0 +1,251 @@ +charset 8bit + +# +# This file defines the font and character mappings used for ISO-8859-1 +# (Latin1/West European) text printing. +# +# The first line consists of: +# +# direction width normal bold italic bold-italic +# +# Direction is the string "ltor" or "rtol", indicating left-to-right or +# right-to-left text. +# +# Width is the string "single" or "double"; double means that the glyphs +# are twice as wide as ASCII characters in the Courier typeface. +# +# "Normal", "bold", "italic", and "bold-italic" are the typefaces to use +# for each presentation. If characters are only available in a single +# style then only one typeface should be listed (e.g. "Symbol") +# +# Each font that is listed will be used (and downloaded if needed) when +# printing. +# + +ltor single Courier Courier-Bold Courier-Italic Courier-BoldItalic + +# +# The following lines define the mapping from the 8-bit character set to +# the Unicode glyphs for each character: +# +# char glyph +# +# "Char" and "glyph" are hexadecimal values. +# + +20 0020 +21 0021 +22 0022 +23 0023 +24 0024 +25 0025 +26 0026 +27 0027 +28 0028 +29 0029 +2A 002A +2B 002B +2C 002C +2D 002D +2E 002E +2F 002F +30 0030 +31 0031 +32 0032 +33 0033 +34 0034 +35 0035 +36 0036 +37 0037 +38 0038 +39 0039 +3A 003A +3B 003B +3C 003C +3D 003D +3E 003E +3F 003F +40 0040 +41 0041 +42 0042 +43 0043 +44 0044 +45 0045 +46 0046 +47 0047 +48 0048 +49 0049 +4A 004A +4B 004B +4C 004C +4D 004D +4E 004E +4F 004F +50 0050 +51 0051 +52 0052 +53 0053 +54 0054 +55 0055 +56 0056 +57 0057 +58 0058 +59 0059 +5A 005A +5B 005B +5C 005C +5D 005D +5E 005E +5F 005F +60 0060 +61 0061 +62 0062 +63 0063 +64 0064 +65 0065 +66 0066 +67 0067 +68 0068 +69 0069 +6A 006A +6B 006B +6C 006C +6D 006D +6E 006E +6F 006F +70 0070 +71 0071 +72 0072 +73 0073 +74 0074 +75 0075 +76 0076 +77 0077 +78 0078 +79 0079 +7A 007A +7B 007B +7C 007C +7D 007D +7E 007E +80 20AC +82 201A +83 0192 +84 201E +85 2026 +86 2020 +87 2021 +88 02C6 +89 2030 +8A 0160 +8B 2039 +8C 0152 +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +98 02DC +99 2122 +9A 0161 +9B 203A +9C 0153 +9F 0178 +A0 00A0 +A1 00A1 +A2 00A2 +A3 00A3 +A4 00A4 +A5 00A5 +A6 00A6 +A7 00A7 +A8 00A8 +A9 00A9 +AA 00AA +AB 00AB +AC 00AC +AD 00AD +AE 00AE +AF 00AF +B0 00B0 +B1 00B1 +B2 00B2 +B3 00B3 +B4 00B4 +B5 00B5 +B6 00B6 +B7 00B7 +B8 00B8 +B9 00B9 +BA 00BA +BB 00BB +BC 00BC +BD 00BD +BE 00BE +BF 00BF +C0 00C0 +C1 00C1 +C2 00C2 +C3 00C3 +C4 00C4 +C5 00C5 +C6 00C6 +C7 00C7 +C8 00C8 +C9 00C9 +CA 00CA +CB 00CB +CC 00CC +CD 00CD +CE 00CE +CF 00CF +D0 00D0 +D1 00D1 +D2 00D2 +D3 00D3 +D4 00D4 +D5 00D5 +D6 00D6 +D7 00D7 +D8 00D8 +D9 00D9 +DA 00DA +DB 00DB +DC 00DC +DD 00DD +DE 00DE +DF 00DF +E0 00E0 +E1 00E1 +E2 00E2 +E3 00E3 +E4 00E4 +E5 00E5 +E6 00E6 +E7 00E7 +E8 00E8 +E9 00E9 +EA 00EA +EB 00EB +EC 00EC +ED 00ED +EE 00EE +EF 00EF +F0 00F0 +F1 00F1 +F2 00F2 +F3 00F3 +F4 00F4 +F5 00F5 +F6 00F6 +F7 00F7 +F8 00F8 +F9 00F9 +FA 00FA +FB 00FB +FC 00FC +FD 00FD +FE 00FE +FF 00FF diff --git a/data/iso-8859-10 b/data/iso-8859-10 new file mode 100644 index 0000000000..7e1399a6dd --- /dev/null +++ b/data/iso-8859-10 @@ -0,0 +1,251 @@ +charset 8bit + +# +# This file defines the font and character mappings used for ISO-8859-10 +# (Latin6/Nordic) text printing. +# +# The first line consists of: +# +# direction width normal bold italic bold-italic +# +# Direction is the string "ltor" or "rtol", indicating left-to-right or +# right-to-left text. +# +# Width is the string "single" or "double"; double means that the glyphs +# are twice as wide as ASCII characters in the Courier typeface. +# +# "Normal", "bold", "italic", and "bold-italic" are the typefaces to use +# for each presentation. If characters are only available in a single +# style then only one typeface should be listed (e.g. "Symbol") +# +# Each font that is listed will be used (and downloaded if needed) when +# printing. +# + +ltor single Courier Courier-Bold Courier-Italic Courier-BoldItalic + +# +# The following lines define the mapping from the 8-bit character set to +# the Unicode glyphs for each character: +# +# char glyph +# +# "Char" and "glyph" are hexadecimal values. +# + +20 0020 +21 0021 +22 0022 +23 0023 +24 0024 +25 0025 +26 0026 +27 0027 +28 0028 +29 0029 +2A 002A +2B 002B +2C 002C +2D 002D +2E 002E +2F 002F +30 0030 +31 0031 +32 0032 +33 0033 +34 0034 +35 0035 +36 0036 +37 0037 +38 0038 +39 0039 +3A 003A +3B 003B +3C 003C +3D 003D +3E 003E +3F 003F +40 0040 +41 0041 +42 0042 +43 0043 +44 0044 +45 0045 +46 0046 +47 0047 +48 0048 +49 0049 +4A 004A +4B 004B +4C 004C +4D 004D +4E 004E +4F 004F +50 0050 +51 0051 +52 0052 +53 0053 +54 0054 +55 0055 +56 0056 +57 0057 +58 0058 +59 0059 +5A 005A +5B 005B +5C 005C +5D 005D +5E 005E +5F 005F +60 0060 +61 0061 +62 0062 +63 0063 +64 0064 +65 0065 +66 0066 +67 0067 +68 0068 +69 0069 +6A 006A +6B 006B +6C 006C +6D 006D +6E 006E +6F 006F +70 0070 +71 0071 +72 0072 +73 0073 +74 0074 +75 0075 +76 0076 +77 0077 +78 0078 +79 0079 +7A 007A +7B 007B +7C 007C +7D 007D +7E 007E +80 20AC +82 201A +83 0192 +84 201E +85 2026 +86 2020 +87 2021 +88 02C6 +89 2030 +8A 0160 +8B 2039 +8C 0152 +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +98 02DC +99 2122 +9A 0161 +9B 203A +9C 0153 +9F 0178 +A0 00A0 +A1 0104 +A2 0112 +A3 0122 +A4 012A +A5 0128 +A6 0136 +A7 00A7 +A8 013B +A9 0110 +AA 0160 +AB 0166 +AC 017D +AD 00AD +AE 016A +AF 014A +B0 00B0 +B1 0105 +B2 0113 +B3 0123 +B4 012B +B5 0129 +B6 0137 +B7 00B7 +B8 013C +B9 0111 +BA 0161 +BB 0167 +BC 017E +BD 2015 +BE 016B +BF 014B +C0 0100 +C1 00C1 +C2 00C2 +C3 00C3 +C4 00C4 +C5 00C5 +C6 00C6 +C7 012E +C8 010C +C9 00C9 +CA 0118 +CB 00CB +CC 0116 +CD 00CD +CE 00CE +CF 00CF +D0 0110 +D1 0145 +D2 014C +D3 00D3 +D4 00D4 +D5 00D5 +D6 00D6 +D7 0168 +D8 00D8 +D9 0172 +DA 00DA +DB 00DB +DC 00DC +DD 00DD +DE 00DE +DF 00DF +E0 0101 +E1 00E1 +E2 00E2 +E3 00E3 +E4 00E4 +E5 00E5 +E6 00E6 +E7 012F +E8 010D +E9 00E9 +EA 0119 +EB 00EB +EC 0117 +ED 00ED +EE 00EE +EF 00EF +F0 00F0 +F1 0146 +F2 014D +F3 00F3 +F4 00F4 +F5 00F5 +F6 00F6 +F7 0169 +F8 00F8 +F9 0173 +FA 00FA +FB 00FB +FC 00FC +FD 00FD +FE 00FD +FF 0138 diff --git a/data/iso-8859-13 b/data/iso-8859-13 new file mode 100644 index 0000000000..e3b67c693e --- /dev/null +++ b/data/iso-8859-13 @@ -0,0 +1,251 @@ +charset 8bit + +# +# This file defines the font and character mappings used for ISO-8859-13 +# (Latin7/Baltic Rim) text printing. +# +# The first line consists of: +# +# direction width normal bold italic bold-italic +# +# Direction is the string "ltor" or "rtol", indicating left-to-right or +# right-to-left text. +# +# Width is the string "single" or "double"; double means that the glyphs +# are twice as wide as ASCII characters in the Courier typeface. +# +# "Normal", "bold", "italic", and "bold-italic" are the typefaces to use +# for each presentation. If characters are only available in a single +# style then only one typeface should be listed (e.g. "Symbol") +# +# Each font that is listed will be used (and downloaded if needed) when +# printing. +# + +ltor single Courier Courier-Bold Courier-Italic Courier-BoldItalic + +# +# The following lines define the mapping from the 8-bit character set to +# the Unicode glyphs for each character: +# +# char glyph +# +# "Char" and "glyph" are hexadecimal values. +# + +20 0020 +21 0021 +22 0022 +23 0023 +24 0024 +25 0025 +26 0026 +27 0027 +28 0028 +29 0029 +2A 002A +2B 002B +2C 002C +2D 002D +2E 002E +2F 002F +30 0030 +31 0031 +32 0032 +33 0033 +34 0034 +35 0035 +36 0036 +37 0037 +38 0038 +39 0039 +3A 003A +3B 003B +3C 003C +3D 003D +3E 003E +3F 003F +40 0040 +41 0041 +42 0042 +43 0043 +44 0044 +45 0045 +46 0046 +47 0047 +48 0048 +49 0049 +4A 004A +4B 004B +4C 004C +4D 004D +4E 004E +4F 004F +50 0050 +51 0051 +52 0052 +53 0053 +54 0054 +55 0055 +56 0056 +57 0057 +58 0058 +59 0059 +5A 005A +5B 005B +5C 005C +5D 005D +5E 005E +5F 005F +60 0060 +61 0061 +62 0062 +63 0063 +64 0064 +65 0065 +66 0066 +67 0067 +68 0068 +69 0069 +6A 006A +6B 006B +6C 006C +6D 006D +6E 006E +6F 006F +70 0070 +71 0071 +72 0072 +73 0073 +74 0074 +75 0075 +76 0076 +77 0077 +78 0078 +79 0079 +7A 007A +7B 007B +7C 007C +7D 007D +7E 007E +80 20AC +82 201A +83 0192 +84 201E +85 2026 +86 2020 +87 2021 +88 02C6 +89 2030 +8A 0160 +8B 2039 +8C 0152 +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +98 02DC +99 2122 +9A 0161 +9B 203A +9C 0153 +9F 0178 +A0 00A0 +A1 201D +A2 00A2 +A3 00A3 +A4 00A4 +A5 201E +A6 00A6 +A7 00A7 +A8 00D8 +A9 00A9 +AA 0156 +AB 00AB +AC 00AC +AD 00AD +AE 00AE +AF 00C6 +B0 00B0 +B1 00B1 +B2 00B2 +B3 00B3 +B4 201C +B5 00B5 +B6 00B6 +B7 00B7 +B8 00F8 +B9 00B9 +BA 0157 +BB 00BB +BC 00BC +BD 00BD +BE 00BE +BF 00E6 +C0 0104 +C1 012E +C2 0100 +C3 0106 +C4 00C4 +C5 00C5 +C6 0118 +C7 0112 +C8 010C +C9 00C9 +CA 0179 +CB 0116 +CC 0122 +CD 0136 +CE 012A +CF 013B +D0 0160 +D1 0143 +D2 0145 +D3 00D3 +D4 014C +D5 00D5 +D6 00D6 +D7 00D7 +D8 0172 +D9 0141 +DA 015A +DB 016A +DC 00DC +DD 017B +DE 017D +DF 00DF +E0 0105 +E1 012F +E2 0101 +E3 0107 +E4 00E4 +E5 00E5 +E6 0119 +E7 0113 +E8 010D +E9 00E9 +EA 017A +EB 0117 +EC 0123 +ED 0137 +EE 012B +EF 013C +F0 0161 +F1 0144 +F2 0146 +F3 00F3 +F4 014D +F5 00F5 +F6 00F6 +F7 00F7 +F8 0173 +F9 0142 +FA 015B +FB 016B +FC 00FC +FD 017C +FE 017E +FF 2019 diff --git a/data/iso-8859-14 b/data/iso-8859-14 new file mode 100644 index 0000000000..293024b8b8 --- /dev/null +++ b/data/iso-8859-14 @@ -0,0 +1,251 @@ +charset 8bit + +# +# This file defines the font and character mappings used for ISO-8859-14 +# (Latin8/Celtic) text printing. +# +# The first line consists of: +# +# direction width normal bold italic bold-italic +# +# Direction is the string "ltor" or "rtol", indicating left-to-right or +# right-to-left text. +# +# Width is the string "single" or "double"; double means that the glyphs +# are twice as wide as ASCII characters in the Courier typeface. +# +# "Normal", "bold", "italic", and "bold-italic" are the typefaces to use +# for each presentation. If characters are only available in a single +# style then only one typeface should be listed (e.g. "Symbol") +# +# Each font that is listed will be used (and downloaded if needed) when +# printing. +# + +ltor single Courier Courier-Bold Courier-Italic Courier-BoldItalic + +# +# The following lines define the mapping from the 8-bit character set to +# the Unicode glyphs for each character: +# +# char glyph +# +# "Char" and "glyph" are hexadecimal values. +# + +20 0020 +21 0021 +22 0022 +23 0023 +24 0024 +25 0025 +26 0026 +27 0027 +28 0028 +29 0029 +2A 002A +2B 002B +2C 002C +2D 002D +2E 002E +2F 002F +30 0030 +31 0031 +32 0032 +33 0033 +34 0034 +35 0035 +36 0036 +37 0037 +38 0038 +39 0039 +3A 003A +3B 003B +3C 003C +3D 003D +3E 003E +3F 003F +40 0040 +41 0041 +42 0042 +43 0043 +44 0044 +45 0045 +46 0046 +47 0047 +48 0048 +49 0049 +4A 004A +4B 004B +4C 004C +4D 004D +4E 004E +4F 004F +50 0050 +51 0051 +52 0052 +53 0053 +54 0054 +55 0055 +56 0056 +57 0057 +58 0058 +59 0059 +5A 005A +5B 005B +5C 005C +5D 005D +5E 005E +5F 005F +60 0060 +61 0061 +62 0062 +63 0063 +64 0064 +65 0065 +66 0066 +67 0067 +68 0068 +69 0069 +6A 006A +6B 006B +6C 006C +6D 006D +6E 006E +6F 006F +70 0070 +71 0071 +72 0072 +73 0073 +74 0074 +75 0075 +76 0076 +77 0077 +78 0078 +79 0079 +7A 007A +7B 007B +7C 007C +7D 007D +7E 007E +80 20AC +82 201A +83 0192 +84 201E +85 2026 +86 2020 +87 2021 +88 02C6 +89 2030 +8A 0160 +8B 2039 +8C 0152 +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +98 02DC +99 2122 +9A 0161 +9B 203A +9C 0153 +9F 0178 +A0 00A0 +A1 1E02 +A2 1E03 +A3 00A3 +A4 010A +A5 010B +A6 1E0A +A7 00A7 +A8 1E80 +A9 00A9 +AA 1E82 +AB 1E0B +AC 1EF2 +AD 00AD +AE 00AE +AF 0178 +B0 1E1E +B1 1E1F +B2 0120 +B3 0121 +B4 1E40 +B5 1E41 +B6 00B6 +B7 1E56 +B8 1E81 +B9 1E57 +BA 1E83 +BB 1E60 +BC 1EF3 +BD 1E84 +BE 1E85 +BF 1E61 +C0 00C0 +C1 00C1 +C2 00C2 +C3 00C3 +C4 00C4 +C5 00C5 +C6 00C6 +C7 00C7 +C8 00C8 +C9 00C9 +CA 00CA +CB 00CB +CC 00CC +CD 00CD +CE 00CE +CF 00CF +D0 0174 +D1 00D1 +D2 00D2 +D3 00D3 +D4 00D4 +D5 00D5 +D6 00D6 +D7 1E6A +D8 00D8 +D9 00D9 +DA 00DA +DB 00DB +DC 00DC +DD 00DD +DE 0176 +DF 00DF +E0 00E0 +E1 00E1 +E2 00E2 +E3 00E3 +E4 00E4 +E5 00E5 +E6 00E6 +E7 00E7 +E8 00E8 +E9 00E9 +EA 00EA +EB 00EB +EC 00EC +ED 00ED +EE 00EE +EF 00EF +F0 0175 +F1 00F1 +F2 00F2 +F3 00F3 +F4 00F4 +F5 00F5 +F6 00F6 +F7 1E6B +F8 00F8 +F9 00F9 +FA 00FA +FB 00FB +FC 00FC +FD 00FD +FE 0177 +FF 00FF diff --git a/data/iso-8859-15 b/data/iso-8859-15 new file mode 100644 index 0000000000..b306a0c7a9 --- /dev/null +++ b/data/iso-8859-15 @@ -0,0 +1,251 @@ +charset 8bit + +# +# This file defines the font and character mappings used for ISO-8859-15 +# (Latin9/West Europe + Euro) text printing. +# +# The first line consists of: +# +# direction width normal bold italic bold-italic +# +# Direction is the string "ltor" or "rtol", indicating left-to-right or +# right-to-left text. +# +# Width is the string "single" or "double"; double means that the glyphs +# are twice as wide as ASCII characters in the Courier typeface. +# +# "Normal", "bold", "italic", and "bold-italic" are the typefaces to use +# for each presentation. If characters are only available in a single +# style then only one typeface should be listed (e.g. "Symbol") +# +# Each font that is listed will be used (and downloaded if needed) when +# printing. +# + +ltor single Courier Courier-Bold Courier-Italic Courier-BoldItalic + +# +# The following lines define the mapping from the 8-bit character set to +# the Unicode glyphs for each character: +# +# char glyph +# +# "Char" and "glyph" are hexadecimal values. +# + +20 0020 +21 0021 +22 0022 +23 0023 +24 0024 +25 0025 +26 0026 +27 0027 +28 0028 +29 0029 +2A 002A +2B 002B +2C 002C +2D 002D +2E 002E +2F 002F +30 0030 +31 0031 +32 0032 +33 0033 +34 0034 +35 0035 +36 0036 +37 0037 +38 0038 +39 0039 +3A 003A +3B 003B +3C 003C +3D 003D +3E 003E +3F 003F +40 0040 +41 0041 +42 0042 +43 0043 +44 0044 +45 0045 +46 0046 +47 0047 +48 0048 +49 0049 +4A 004A +4B 004B +4C 004C +4D 004D +4E 004E +4F 004F +50 0050 +51 0051 +52 0052 +53 0053 +54 0054 +55 0055 +56 0056 +57 0057 +58 0058 +59 0059 +5A 005A +5B 005B +5C 005C +5D 005D +5E 005E +5F 005F +60 0060 +61 0061 +62 0062 +63 0063 +64 0064 +65 0065 +66 0066 +67 0067 +68 0068 +69 0069 +6A 006A +6B 006B +6C 006C +6D 006D +6E 006E +6F 006F +70 0070 +71 0071 +72 0072 +73 0073 +74 0074 +75 0075 +76 0076 +77 0077 +78 0078 +79 0079 +7A 007A +7B 007B +7C 007C +7D 007D +7E 007E +80 20AC +82 201A +83 0192 +84 201E +85 2026 +86 2020 +87 2021 +88 02C6 +89 2030 +8A 0160 +8B 2039 +8C 0152 +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +98 02DC +99 2122 +9A 0161 +9B 203A +9C 0153 +9F 0178 +A0 00A0 +A1 00A1 +A2 00A2 +A3 00A3 +A4 20AC +A5 00A5 +A6 0160 +A7 00A7 +A8 0161 +A9 00A9 +AA 00AA +AB 00AB +AC 00AC +AD 00AD +AE 00AE +AF 00AF +B0 00B0 +B1 00B1 +B2 00B2 +B3 00B3 +B4 017D +B5 00B5 +B6 00B6 +B7 00B7 +B8 017E +B9 00B9 +BA 00BA +BB 00BB +BC 0152 +BD 0153 +BE 0178 +BF 00BF +C0 00C0 +C1 00C1 +C2 00C2 +C3 00C3 +C4 00C4 +C5 00C5 +C6 00C6 +C7 00C7 +C8 00C8 +C9 00C9 +CA 00CA +CB 00CB +CC 00CC +CD 00CD +CE 00CE +CF 00CF +D0 00D0 +D1 00D1 +D2 00D2 +D3 00D3 +D4 00D4 +D5 00D5 +D6 00D6 +D7 00D7 +D8 00D8 +D9 00D9 +DA 00DA +DB 00DB +DC 00DC +DD 00DD +DE 00DE +DF 00DF +E0 00E0 +E1 00E1 +E2 00E2 +E3 00E3 +E4 00E4 +E5 00E5 +E6 00E6 +E7 00E7 +E8 00E8 +E9 00E9 +EA 00EA +EB 00EB +EC 00EC +ED 00ED +EE 00EE +EF 00EF +F0 00F0 +F1 00F1 +F2 00F2 +F3 00F3 +F4 00F4 +F5 00F5 +F6 00F6 +F7 00F7 +F8 00F8 +F9 00F9 +FA 00FA +FB 00FB +FC 00FC +FD 00FD +FE 00FE +FF 00FF diff --git a/data/iso-8859-2 b/data/iso-8859-2 new file mode 100644 index 0000000000..bad8840bb0 --- /dev/null +++ b/data/iso-8859-2 @@ -0,0 +1,253 @@ +charset 8bit + +# +# This file defines the font and character mappings used for ISO-8859-2 +# (Latin2/East European) text printing. +# +# The first line consists of: +# +# direction width normal bold italic bold-italic +# +# Direction is the string "ltor" or "rtol", indicating left-to-right or +# right-to-left text. +# +# Width is the string "single" or "double"; double means that the glyphs +# are twice as wide as ASCII characters in the Courier typeface. +# +# "Normal", "bold", "italic", and "bold-italic" are the typefaces to use +# for each presentation. If characters are only available in a single +# style then only one typeface should be listed (e.g. "Symbol") +# +# Each font that is listed will be used (and downloaded if needed) when +# printing. +# + +ltor single Courier Courier-Bold Courier-Italic Courier-BoldItalic + +# +# The following lines define the mapping from the 8-bit character set to +# the Unicode glyphs for each character: +# +# char glyph +# +# "Char" and "glyph" are hexadecimal values. +# + +20 0020 +21 0021 +22 0022 +23 0023 +24 0024 +25 0025 +26 0026 +27 0027 +28 0028 +29 0029 +2A 002A +2B 002B +2C 002C +2D 002D +2E 002E +2F 002F +30 0030 +31 0031 +32 0032 +33 0033 +34 0034 +35 0035 +36 0036 +37 0037 +38 0038 +39 0039 +3A 003A +3B 003B +3C 003C +3D 003D +3E 003E +3F 003F +40 0040 +41 0041 +42 0042 +43 0043 +44 0044 +45 0045 +46 0046 +47 0047 +48 0048 +49 0049 +4A 004A +4B 004B +4C 004C +4D 004D +4E 004E +4F 004F +50 0050 +51 0051 +52 0052 +53 0053 +54 0054 +55 0055 +56 0056 +57 0057 +58 0058 +59 0059 +5A 005A +5B 005B +5C 005C +5D 005D +5E 005E +5F 005F +60 0060 +61 0061 +62 0062 +63 0063 +64 0064 +65 0065 +66 0066 +67 0067 +68 0068 +69 0069 +6A 006A +6B 006B +6C 006C +6D 006D +6E 006E +6F 006F +70 0070 +71 0071 +72 0072 +73 0073 +74 0074 +75 0075 +76 0076 +77 0077 +78 0078 +79 0079 +7A 007A +7B 007B +7C 007C +7D 007D +7E 007E +80 20AC +82 201A +84 201E +85 2026 +86 2020 +87 2021 +89 2030 +8A 0160 +8B 2039 +8C 015A +8D 0164 +8E 017D +8F 0179 +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +99 2122 +9A 0161 +9B 203A +8C 015B +8D 0165 +8E 017E +8F 017A +A0 00A0 +A1 0104 +A2 02D8 +A3 0141 +A4 00A4 +A5 013D +A6 015A +A7 00A7 +A8 00A8 +A9 0160 +AA 015E +AB 0164 +AC 0179 +AD 00AD +AE 017D +AF 017B +B0 00B0 +B1 0105 +B2 02DB +B3 0142 +B4 00B4 +B5 013E +B6 015B +B7 02C7 +B8 00B8 +B9 0161 +BA 015F +BB 0165 +BC 017A +BD 02DD +BE 017E +BF 017C +C0 0154 +C1 00C1 +C2 00C2 +C3 0102 +C4 00C4 +C5 0139 +C6 0106 +C7 00C7 +C8 010C +C9 00C9 +CA 0118 +CB 00CB +CC 011A +CD 00CD +CE 00CE +CF 010E +D0 0110 +D1 0143 +D2 0147 +D3 00D3 +D4 00D4 +D5 0150 +D6 00D6 +D7 00D7 +D8 0158 +D9 016E +DA 00DA +DB 0170 +DC 00DC +DD 00DD +DE 0162 +DF 00DF +E0 0155 +E1 00E1 +E2 00E2 +E3 0103 +E4 00E4 +E5 013A +E6 0107 +E7 00E7 +E8 010D +E9 00E9 +EA 0119 +EB 00EB +EC 011B +ED 00ED +EE 00EE +EF 010F +F0 0111 +F1 0144 +F2 0148 +F3 00F3 +F4 00F4 +F5 0151 +F6 00F6 +F7 00F7 +F8 0159 +F9 016F +FA 00FA +FB 0171 +FC 00FC +FD 00FD +FE 0163 +FF 02D9 diff --git a/data/iso-8859-3 b/data/iso-8859-3 new file mode 100644 index 0000000000..306152b840 --- /dev/null +++ b/data/iso-8859-3 @@ -0,0 +1,244 @@ +charset 8bit + +# +# This file defines the font and character mappings used for ISO-8859-3 +# (Latin3/South European) text printing. +# +# The first line consists of: +# +# direction width normal bold italic bold-italic +# +# Direction is the string "ltor" or "rtol", indicating left-to-right or +# right-to-left text. +# +# Width is the string "single" or "double"; double means that the glyphs +# are twice as wide as ASCII characters in the Courier typeface. +# +# "Normal", "bold", "italic", and "bold-italic" are the typefaces to use +# for each presentation. If characters are only available in a single +# style then only one typeface should be listed (e.g. "Symbol") +# +# Each font that is listed will be used (and downloaded if needed) when +# printing. +# + +ltor single Courier Courier-Bold Courier-Italic Courier-BoldItalic + +# +# The following lines define the mapping from the 8-bit character set to +# the Unicode glyphs for each character: +# +# char glyph +# +# "Char" and "glyph" are hexadecimal values. +# + +20 0020 +21 0021 +22 0022 +23 0023 +24 0024 +25 0025 +26 0026 +27 0027 +28 0028 +29 0029 +2A 002A +2B 002B +2C 002C +2D 002D +2E 002E +2F 002F +30 0030 +31 0031 +32 0032 +33 0033 +34 0034 +35 0035 +36 0036 +37 0037 +38 0038 +39 0039 +3A 003A +3B 003B +3C 003C +3D 003D +3E 003E +3F 003F +40 0040 +41 0041 +42 0042 +43 0043 +44 0044 +45 0045 +46 0046 +47 0047 +48 0048 +49 0049 +4A 004A +4B 004B +4C 004C +4D 004D +4E 004E +4F 004F +50 0050 +51 0051 +52 0052 +53 0053 +54 0054 +55 0055 +56 0056 +57 0057 +58 0058 +59 0059 +5A 005A +5B 005B +5C 005C +5D 005D +5E 005E +5F 005F +60 0060 +61 0061 +62 0062 +63 0063 +64 0064 +65 0065 +66 0066 +67 0067 +68 0068 +69 0069 +6A 006A +6B 006B +6C 006C +6D 006D +6E 006E +6F 006F +70 0070 +71 0071 +72 0072 +73 0073 +74 0074 +75 0075 +76 0076 +77 0077 +78 0078 +79 0079 +7A 007A +7B 007B +7C 007C +7D 007D +7E 007E +80 20AC +82 201A +83 0192 +84 201E +85 2026 +86 2020 +87 2021 +88 02C6 +89 2030 +8A 0160 +8B 2039 +8C 0152 +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +98 02DC +99 2122 +9A 0161 +9B 203A +9C 0153 +9F 0178 +A0 00A0 +A1 0126 +A2 02D8 +A3 00A3 +A4 00A4 +A6 0124 +A7 00A7 +A8 00A8 +A9 0130 +AA 015E +AB 011E +AC 0134 +AD 00AD +AF 017B +B0 00B0 +B1 0127 +B2 00B2 +B3 00B3 +B4 00B4 +B5 00B5 +B6 0125 +B7 00B7 +B8 00B8 +B9 0131 +BA 015F +BB 011F +BC 0135 +BD 00BD +BF 017C +C0 00C0 +C1 00C1 +C2 00C2 +C4 00C4 +C5 010A +C6 0108 +C7 00C7 +C8 00C8 +C9 00C9 +CA 00CA +CB 00CB +CC 00CC +CD 00CD +CE 00CE +CF 00CF +D1 00D1 +D2 00D2 +D3 00D3 +D4 00D4 +D5 0120 +D6 00D6 +D7 00D7 +D8 011C +D9 00D9 +DA 00DA +DB 00DB +DC 00DC +DD 016C +DE 015C +DF 00DF +E0 00E0 +E1 00E1 +E2 00E2 +E4 00E4 +E5 010B +E6 0109 +E7 00E7 +E8 00E8 +E9 00E9 +EA 00EA +EB 00EB +EC 00EC +ED 00ED +EE 00EE +EF 00EF +F1 00F1 +F2 00F2 +F3 00F3 +F4 00F4 +F5 0121 +F6 00F6 +F7 00F7 +F8 011D +F9 00F9 +FA 00FA +FB 00FB +FC 00FC +FD 016D +FE 015D +FF 02D9 diff --git a/data/iso-8859-4 b/data/iso-8859-4 new file mode 100644 index 0000000000..1af6ae62d5 --- /dev/null +++ b/data/iso-8859-4 @@ -0,0 +1,251 @@ +charset 8bit + +# +# This file defines the font and character mappings used for ISO-8859-4 +# (Latin4/North European) text printing. +# +# The first line consists of: +# +# direction width normal bold italic bold-italic +# +# Direction is the string "ltor" or "rtol", indicating left-to-right or +# right-to-left text. +# +# Width is the string "single" or "double"; double means that the glyphs +# are twice as wide as ASCII characters in the Courier typeface. +# +# "Normal", "bold", "italic", and "bold-italic" are the typefaces to use +# for each presentation. If characters are only available in a single +# style then only one typeface should be listed (e.g. "Symbol") +# +# Each font that is listed will be used (and downloaded if needed) when +# printing. +# + +ltor single Courier Courier-Bold Courier-Italic Courier-BoldItalic + +# +# The following lines define the mapping from the 8-bit character set to +# the Unicode glyphs for each character: +# +# char glyph +# +# "Char" and "glyph" are hexadecimal values. +# + +20 0020 +21 0021 +22 0022 +23 0023 +24 0024 +25 0025 +26 0026 +27 0027 +28 0028 +29 0029 +2A 002A +2B 002B +2C 002C +2D 002D +2E 002E +2F 002F +30 0030 +31 0031 +32 0032 +33 0033 +34 0034 +35 0035 +36 0036 +37 0037 +38 0038 +39 0039 +3A 003A +3B 003B +3C 003C +3D 003D +3E 003E +3F 003F +40 0040 +41 0041 +42 0042 +43 0043 +44 0044 +45 0045 +46 0046 +47 0047 +48 0048 +49 0049 +4A 004A +4B 004B +4C 004C +4D 004D +4E 004E +4F 004F +50 0050 +51 0051 +52 0052 +53 0053 +54 0054 +55 0055 +56 0056 +57 0057 +58 0058 +59 0059 +5A 005A +5B 005B +5C 005C +5D 005D +5E 005E +5F 005F +60 0060 +61 0061 +62 0062 +63 0063 +64 0064 +65 0065 +66 0066 +67 0067 +68 0068 +69 0069 +6A 006A +6B 006B +6C 006C +6D 006D +6E 006E +6F 006F +70 0070 +71 0071 +72 0072 +73 0073 +74 0074 +75 0075 +76 0076 +77 0077 +78 0078 +79 0079 +7A 007A +7B 007B +7C 007C +7D 007D +7E 007E +80 20AC +82 201A +83 0192 +84 201E +85 2026 +86 2020 +87 2021 +88 02C6 +89 2030 +8A 0160 +8B 2039 +8C 0152 +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +98 02DC +99 2122 +9A 0161 +9B 203A +9C 0153 +9F 0178 +A0 00A0 +A1 0104 +A2 0138 +A3 0156 +A4 00A4 +A5 0128 +A6 013B +A7 00A7 +A8 00A8 +A9 0160 +AA 0112 +AB 0122 +AC 0166 +AD 00AD +AE 017D +AF 00AF +B0 00B0 +B1 0105 +B2 02DB +B3 0157 +B4 00B4 +B5 0129 +B6 013C +B7 02C7 +B8 00B8 +B9 0161 +BA 0113 +BB 0123 +BC 0167 +BD 014A +BE 017E +BF 014B +C0 0100 +C1 00C1 +C2 00C2 +C3 00C3 +C4 00C4 +C5 00C5 +C6 00C6 +C7 012E +C8 010C +C9 00C9 +CA 0118 +CB 00CB +CC 0116 +CD 00CD +CE 00CE +CF 012A +D0 0110 +D1 0145 +D2 014C +D3 0136 +D4 00D4 +D5 00D5 +D6 00D6 +D7 00D7 +D8 00D8 +D9 0172 +DA 00DA +DB 00DB +DC 00DC +DD 0168 +DE 016A +DF 00DF +E0 0101 +E1 00E1 +E2 00E2 +E3 00E3 +E4 00E4 +E5 00E5 +E6 00E6 +E7 012F +E8 010D +E9 00E9 +EA 0119 +EB 00EB +EC 0117 +ED 00ED +EE 00EE +EF 012B +F0 0111 +F1 0146 +F2 014D +F3 0137 +F4 00F4 +F5 00F5 +F6 00F6 +F7 00F7 +F8 00F8 +F9 0173 +FA 00FA +FB 00FB +FC 00FC +FD 0169 +FE 016B +FF 02D9 diff --git a/data/iso-8859-5 b/data/iso-8859-5 new file mode 100644 index 0000000000..2ca78cfead --- /dev/null +++ b/data/iso-8859-5 @@ -0,0 +1,251 @@ +charset 8bit + +# +# This file defines the font and character mappings used for ISO-8859-5 +# (Cyrillic) text printing. +# +# The first line consists of: +# +# direction width normal bold italic bold-italic +# +# Direction is the string "ltor" or "rtol", indicating left-to-right or +# right-to-left text. +# +# Width is the string "single" or "double"; double means that the glyphs +# are twice as wide as ASCII characters in the Courier typeface. +# +# "Normal", "bold", "italic", and "bold-italic" are the typefaces to use +# for each presentation. If characters are only available in a single +# style then only one typeface should be listed (e.g. "Symbol") +# +# Each font that is listed will be used (and downloaded if needed) when +# printing. +# + +ltor single Courier Courier-Bold Courier-Italic Courier-BoldItalic + +# +# The following lines define the mapping from the 8-bit character set to +# the Unicode glyphs for each character: +# +# char glyph +# +# "Char" and "glyph" are hexadecimal values. +# + +20 0020 +21 0021 +22 0022 +23 0023 +24 0024 +25 0025 +26 0026 +27 0027 +28 0028 +29 0029 +2A 002A +2B 002B +2C 002C +2D 002D +2E 002E +2F 002F +30 0030 +31 0031 +32 0032 +33 0033 +34 0034 +35 0035 +36 0036 +37 0037 +38 0038 +39 0039 +3A 003A +3B 003B +3C 003C +3D 003D +3E 003E +3F 003F +40 0040 +41 0041 +42 0042 +43 0043 +44 0044 +45 0045 +46 0046 +47 0047 +48 0048 +49 0049 +4A 004A +4B 004B +4C 004C +4D 004D +4E 004E +4F 004F +50 0050 +51 0051 +52 0052 +53 0053 +54 0054 +55 0055 +56 0056 +57 0057 +58 0058 +59 0059 +5A 005A +5B 005B +5C 005C +5D 005D +5E 005E +5F 005F +60 0060 +61 0061 +62 0062 +63 0063 +64 0064 +65 0065 +66 0066 +67 0067 +68 0068 +69 0069 +6A 006A +6B 006B +6C 006C +6D 006D +6E 006E +6F 006F +70 0070 +71 0071 +72 0072 +73 0073 +74 0074 +75 0075 +76 0076 +77 0077 +78 0078 +79 0079 +7A 007A +7B 007B +7C 007C +7D 007D +7E 007E +80 20AC +82 201A +83 0192 +84 201E +85 2026 +86 2020 +87 2021 +88 02C6 +89 2030 +8A 0160 +8B 2039 +8C 0152 +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +98 02DC +99 2122 +9A 0161 +9B 203A +9C 0153 +9F 0178 +A0 00A0 +A1 0401 +A2 0402 +A3 0403 +A4 0404 +A5 0405 +A6 0406 +A7 0407 +A8 0408 +A9 0409 +AA 040A +AB 040B +AC 040C +AD 00AD +AE 040E +AF 040F +B0 0410 +B1 0411 +B2 0412 +B3 0413 +B4 0414 +B5 0415 +B6 0416 +B7 0417 +B8 0418 +B9 0419 +BA 041A +BB 041B +BC 041C +BD 041D +BE 041E +BF 041F +C0 0420 +C1 0421 +C2 0422 +C3 0423 +C4 0424 +C5 0425 +C6 0426 +C7 0427 +C8 0428 +C9 0429 +CA 042A +CB 042B +CC 042C +CD 042D +CE 042E +CF 042F +D0 0430 +D1 0431 +D2 0432 +D3 0433 +D4 0434 +D5 0435 +D6 0436 +D7 0437 +D8 0438 +D9 0439 +DA 043A +DB 043B +DC 043C +DD 043D +DE 043E +DF 043F +E0 0440 +E1 0441 +E2 0442 +E3 0443 +E4 0444 +E5 0445 +E6 0446 +E7 0447 +E8 0448 +E9 0449 +EA 044A +EB 044B +EC 044C +ED 044D +EE 044E +EF 044F +F0 2116 +F1 0451 +F2 0452 +F3 0453 +F4 0454 +F5 0455 +F6 0456 +F7 0457 +F8 0458 +F9 0459 +FA 045A +FB 045B +FC 045C +FD 00A7 +FE 045E +FF 045F diff --git a/data/iso-8859-6 b/data/iso-8859-6 new file mode 100644 index 0000000000..fd8d7c7bfa --- /dev/null +++ b/data/iso-8859-6 @@ -0,0 +1,206 @@ +charset 8bit + +# +# This file defines the font and character mappings used for ISO-8859-6 +# (Arabic) text printing. +# +# The first line consists of: +# +# direction width normal bold italic bold-italic +# +# Direction is the string "ltor" or "rtol", indicating left-to-right or +# right-to-left text. +# +# Width is the string "single" or "double"; double means that the glyphs +# are twice as wide as ASCII characters in the Courier typeface. +# +# "Normal", "bold", "italic", and "bold-italic" are the typefaces to use +# for each presentation. If characters are only available in a single +# style then only one typeface should be listed (e.g. "Symbol") +# +# Each font that is listed will be used (and downloaded if needed) when +# printing. +# + +rtol single Courier Courier-Bold Courier-Italic Courier-BoldItalic + +# +# The following lines define the mapping from the 8-bit character set to +# the Unicode glyphs for each character: +# +# char glyph +# +# "Char" and "glyph" are hexadecimal values. +# + +20 0020 +21 0021 +22 0022 +23 0023 +24 0024 +25 0025 +26 0026 +27 0027 +28 0028 +29 0029 +2A 002A +2B 002B +2C 002C +2D 002D +2E 002E +2F 002F +30 0660 +31 0661 +32 0662 +33 0663 +34 0664 +35 0665 +36 0666 +37 0667 +38 0668 +39 0669 +3A 003A +3B 003B +3C 003C +3D 003D +3E 003E +3F 003F +40 0040 +41 0041 +42 0042 +43 0043 +44 0044 +45 0045 +46 0046 +47 0047 +48 0048 +49 0049 +4A 004A +4B 004B +4C 004C +4D 004D +4E 004E +4F 004F +50 0050 +51 0051 +52 0052 +53 0053 +54 0054 +55 0055 +56 0056 +57 0057 +58 0058 +59 0059 +5A 005A +5B 005B +5C 005C +5D 005D +5E 005E +5F 005F +60 0060 +61 0061 +62 0062 +63 0063 +64 0064 +65 0065 +66 0066 +67 0067 +68 0068 +69 0069 +6A 006A +6B 006B +6C 006C +6D 006D +6E 006E +6F 006F +70 0070 +71 0071 +72 0072 +73 0073 +74 0074 +75 0075 +76 0076 +77 0077 +78 0078 +79 0079 +7A 007A +7B 007B +7C 007C +7D 007D +7E 007E +80 20AC +82 201A +83 0192 +84 201E +85 2026 +86 2020 +87 2021 +88 02C6 +89 2030 +8A 0160 +8B 2039 +8C 0152 +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +98 02DC +99 2122 +9A 0161 +9B 203A +9C 0153 +9F 0178 +A0 00A0 +A4 00A4 +AC 060C +AD 00AD +BB 061B +BF 061F +C1 0621 +C2 0622 +C3 0623 +C4 0624 +C5 0625 +C6 0626 +C7 0627 +C8 0628 +C9 0629 +CA 062A +CB 062B +CC 062C +CD 062D +CE 062E +CF 062F +D0 0630 +D1 0631 +D2 0632 +D3 0633 +D4 0634 +D5 0635 +D6 0636 +D7 0637 +D8 0638 +D9 0639 +DA 063A +E0 0640 +E1 0641 +E2 0642 +E3 0643 +E4 0644 +E5 0645 +E6 0646 +E7 0647 +E8 0648 +E9 0649 +EA 064A +EB 064B +EC 064C +ED 064D +EE 064E +EF 064F +F0 0650 +F1 0651 +F2 0652 diff --git a/data/iso-8859-7 b/data/iso-8859-7 new file mode 100644 index 0000000000..b121ccd4c2 --- /dev/null +++ b/data/iso-8859-7 @@ -0,0 +1,245 @@ +charset 8bit + +# +# This file defines the font and character mappings used for ISO-8859-7 +# (Greek) text printing. +# +# The first line consists of: +# +# direction width normal bold italic bold-italic +# +# Direction is the string "ltor" or "rtol", indicating left-to-right or +# right-to-left text. +# +# Width is the string "single" or "double"; double means that the glyphs +# are twice as wide as ASCII characters in the Courier typeface. +# +# "Normal", "bold", "italic", and "bold-italic" are the typefaces to use +# for each presentation. If characters are only available in a single +# style then only one typeface should be listed (e.g. "Symbol") +# +# Each font that is listed will be used (and downloaded if needed) when +# printing. +# + +ltor single Courier Courier-Bold Courier-Italic Courier-BoldItalic + +# +# The following lines define the mapping from the 8-bit character set to +# the Unicode glyphs for each character: +# +# char glyph +# +# "Char" and "glyph" are hexadecimal values. +# + +20 0020 +21 0021 +22 0022 +23 0023 +24 0024 +25 0025 +26 0026 +27 0027 +28 0028 +29 0029 +2A 002A +2B 002B +2C 002C +2D 002D +2E 002E +2F 002F +30 0030 +31 0031 +32 0032 +33 0033 +34 0034 +35 0035 +36 0036 +37 0037 +38 0038 +39 0039 +3A 003A +3B 003B +3C 003C +3D 003D +3E 003E +3F 003F +40 0040 +41 0041 +42 0042 +43 0043 +44 0044 +45 0045 +46 0046 +47 0047 +48 0048 +49 0049 +4A 004A +4B 004B +4C 004C +4D 004D +4E 004E +4F 004F +50 0050 +51 0051 +52 0052 +53 0053 +54 0054 +55 0055 +56 0056 +57 0057 +58 0058 +59 0059 +5A 005A +5B 005B +5C 005C +5D 005D +5E 005E +5F 005F +60 0060 +61 0061 +62 0062 +63 0063 +64 0064 +65 0065 +66 0066 +67 0067 +68 0068 +69 0069 +6A 006A +6B 006B +6C 006C +6D 006D +6E 006E +6F 006F +70 0070 +71 0071 +72 0072 +73 0073 +74 0074 +75 0075 +76 0076 +77 0077 +78 0078 +79 0079 +7A 007A +7B 007B +7C 007C +7D 007D +7E 007E +80 20AC +82 201A +83 0192 +84 201E +85 2026 +86 2020 +87 2021 +88 02C6 +89 2030 +8A 0160 +8B 2039 +8C 0152 +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +98 02DC +99 2122 +9A 0161 +9B 203A +9C 0153 +9F 0178 +A0 00A0 +A1 02BD +A2 02BC +A3 00A3 +A6 00A6 +A7 00A7 +A8 00A8 +A9 00A9 +AB 00AB +AC 00AC +AD 00AD +AF 2015 +B0 00B0 +B1 00B1 +B2 00B2 +B3 00B3 +B4 0384 +B5 0385 +B6 0386 +B7 00B7 +B8 0388 +B9 0389 +BA 038A +BB 00BB +BC 038C +BD 00BD +BE 038E +BF 038F +C0 0390 +C1 0391 +C2 0392 +C3 0393 +C4 0394 +C5 0395 +C6 0396 +C7 0397 +C8 0398 +C9 0399 +CA 039A +CB 039B +CC 039C +CD 039D +CE 039E +CF 039F +D0 03A0 +D1 03A1 +D3 03A3 +D4 03A4 +D5 03A5 +D6 03A6 +D7 03A7 +D8 03A8 +D9 03A9 +DA 03AA +DB 03AB +DC 03AC +DD 03AD +DE 03AE +DF 03AF +E0 03B0 +E1 03B1 +E2 03B2 +E3 03B3 +E4 03B4 +E5 03B5 +E6 03B6 +E7 03B7 +E8 03B8 +E9 03B9 +EA 03BA +EB 03BB +EC 03BC +ED 03BD +EE 03BE +EF 03BF +F0 03C0 +F1 03C1 +F2 03C2 +F3 03C3 +F4 03C4 +F5 03C5 +F6 03C6 +F7 03C7 +F8 03C8 +F9 03C9 +FA 03CA +FB 03CB +FC 03CC +FD 03CD +FE 03CE diff --git a/data/iso-8859-8 b/data/iso-8859-8 new file mode 100644 index 0000000000..6d3a7c8c3e --- /dev/null +++ b/data/iso-8859-8 @@ -0,0 +1,213 @@ +charset 8bit + +# +# This file defines the font and character mappings used for ISO-8859-8 +# (Hebrew) text printing. +# +# The first line consists of: +# +# direction width normal bold italic bold-italic +# +# Direction is the string "ltor" or "rtol", indicating left-to-right or +# right-to-left text. +# +# Width is the string "single" or "double"; double means that the glyphs +# are twice as wide as ASCII characters in the Courier typeface. +# +# "Normal", "bold", "italic", and "bold-italic" are the typefaces to use +# for each presentation. If characters are only available in a single +# style then only one typeface should be listed (e.g. "Symbol") +# +# Each font that is listed will be used (and downloaded if needed) when +# printing. +# + +rtol single Courier Courier-Bold Courier-Italic Courier-BoldItalic + +# +# The following lines define the mapping from the 8-bit character set to +# the Unicode glyphs for each character: +# +# char glyph +# +# "Char" and "glyph" are hexadecimal values. +# + +20 0020 +21 0021 +22 0022 +23 0023 +24 0024 +25 0025 +26 0026 +27 0027 +28 0028 +29 0029 +2A 002A +2B 002B +2C 002C +2D 002D +2E 002E +2F 002F +30 0030 +31 0031 +32 0032 +33 0033 +34 0034 +35 0035 +36 0036 +37 0037 +38 0038 +39 0039 +3A 003A +3B 003B +3C 003C +3D 003D +3E 003E +3F 003F +40 0040 +41 0041 +42 0042 +43 0043 +44 0044 +45 0045 +46 0046 +47 0047 +48 0048 +49 0049 +4A 004A +4B 004B +4C 004C +4D 004D +4E 004E +4F 004F +50 0050 +51 0051 +52 0052 +53 0053 +54 0054 +55 0055 +56 0056 +57 0057 +58 0058 +59 0059 +5A 005A +5B 005B +5C 005C +5D 005D +5E 005E +5F 005F +60 0060 +61 0061 +62 0062 +63 0063 +64 0064 +65 0065 +66 0066 +67 0067 +68 0068 +69 0069 +6A 006A +6B 006B +6C 006C +6D 006D +6E 006E +6F 006F +70 0070 +71 0071 +72 0072 +73 0073 +74 0074 +75 0075 +76 0076 +77 0077 +78 0078 +79 0079 +7A 007A +7B 007B +7C 007C +7D 007D +7E 007E +80 20AC +82 201A +83 0192 +84 201E +85 2026 +86 2020 +87 2021 +88 02C6 +89 2030 +8A 0160 +8B 2039 +8C 0152 +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +98 02DC +99 2122 +9A 0161 +9B 203A +9C 0153 +9F 0178 +A0 00A0 +A2 00A2 +A3 00A3 +A4 00A4 +A5 00A5 +A6 00A6 +A7 00A7 +A8 00A8 +A9 00A9 +AA 00D7 +AB 00AB +AC 00AC +AD 00AD +AE 00AE +AF 203E +B0 00B0 +B1 00B1 +B2 00B2 +B3 00B3 +B4 00B4 +B5 00B5 +B6 00B6 +B7 00B7 +B8 00B8 +B9 00B9 +BA 00F7 +BB 00BB +BC 00BC +BD 00BD +BE 00BE +DF 2017 +E0 05D0 +E1 05D1 +E2 05D2 +E3 05D3 +E4 05D4 +E5 05D5 +E6 05D6 +E7 05D7 +E8 05D8 +E9 05D9 +EA 05DA +EB 05DB +EC 05DC +ED 05DD +EE 05DE +EF 05DF +F0 05E0 +F1 05E1 +F2 05E2 +F3 05E3 +F4 05E4 +F5 05E5 +F6 05E6 +F7 05E7 +F8 05E8 +F9 05E9 +FA 05EA diff --git a/data/iso-8859-9 b/data/iso-8859-9 new file mode 100644 index 0000000000..2ccfa65e12 --- /dev/null +++ b/data/iso-8859-9 @@ -0,0 +1,251 @@ +charset 8bit + +# +# This file defines the font and character mappings used for ISO-8859-9 +# (Latin5/Turkish) text printing. +# +# The first line consists of: +# +# direction width normal bold italic bold-italic +# +# Direction is the string "ltor" or "rtol", indicating left-to-right or +# right-to-left text. +# +# Width is the string "single" or "double"; double means that the glyphs +# are twice as wide as ASCII characters in the Courier typeface. +# +# "Normal", "bold", "italic", and "bold-italic" are the typefaces to use +# for each presentation. If characters are only available in a single +# style then only one typeface should be listed (e.g. "Symbol") +# +# Each font that is listed will be used (and downloaded if needed) when +# printing. +# + +ltor single Courier Courier-Bold Courier-Italic Courier-BoldItalic + +# +# The following lines define the mapping from the 8-bit character set to +# the Unicode glyphs for each character: +# +# char glyph +# +# "Char" and "glyph" are hexadecimal values. +# + +20 0020 +21 0021 +22 0022 +23 0023 +24 0024 +25 0025 +26 0026 +27 0027 +28 0028 +29 0029 +2A 002A +2B 002B +2C 002C +2D 002D +2E 002E +2F 002F +30 0030 +31 0031 +32 0032 +33 0033 +34 0034 +35 0035 +36 0036 +37 0037 +38 0038 +39 0039 +3A 003A +3B 003B +3C 003C +3D 003D +3E 003E +3F 003F +40 0040 +41 0041 +42 0042 +43 0043 +44 0044 +45 0045 +46 0046 +47 0047 +48 0048 +49 0049 +4A 004A +4B 004B +4C 004C +4D 004D +4E 004E +4F 004F +50 0050 +51 0051 +52 0052 +53 0053 +54 0054 +55 0055 +56 0056 +57 0057 +58 0058 +59 0059 +5A 005A +5B 005B +5C 005C +5D 005D +5E 005E +5F 005F +60 0060 +61 0061 +62 0062 +63 0063 +64 0064 +65 0065 +66 0066 +67 0067 +68 0068 +69 0069 +6A 006A +6B 006B +6C 006C +6D 006D +6E 006E +6F 006F +70 0070 +71 0071 +72 0072 +73 0073 +74 0074 +75 0075 +76 0076 +77 0077 +78 0078 +79 0079 +7A 007A +7B 007B +7C 007C +7D 007D +7E 007E +80 20AC +82 201A +83 0192 +84 201E +85 2026 +86 2020 +87 2021 +88 02C6 +89 2030 +8A 0160 +8B 2039 +8C 0152 +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +98 02DC +99 2122 +9A 0161 +9B 203A +9C 0153 +9F 0178 +A0 00A0 +A1 00A1 +A2 00A2 +A3 00A3 +A4 00A4 +A5 00A5 +A6 00A6 +A7 00A7 +A8 00A8 +A9 00A9 +AA 00AA +AB 00AB +AC 00AC +AD 00AD +AE 00AE +AF 00AF +B0 00B0 +B1 00B1 +B2 00B2 +B3 00B3 +B4 00B4 +B5 00B5 +B6 00B6 +B7 00B7 +B8 00B8 +B9 00B9 +BA 00BA +BB 00BB +BC 00BC +BD 00BD +BE 00BE +BF 00BF +C0 00C0 +C1 00C1 +C2 00C2 +C3 00C3 +C4 00C4 +C5 00C5 +C6 00C6 +C7 00C7 +C8 00C8 +C9 00C9 +CA 00CA +CB 00CB +CC 00CC +CD 00CD +CE 00CE +CF 00CF +D0 011E +D1 00D1 +D2 00D2 +D3 00D3 +D4 00D4 +D5 00D5 +D6 00D6 +D7 00D7 +D8 00D8 +D9 00D9 +DA 00DA +DB 00DB +DC 00DC +DD 0130 +DE 015E +DF 00DF +E0 00E0 +E1 00E1 +E2 00E2 +E3 00E3 +E4 00E4 +E5 00E5 +E6 00E6 +E7 00E7 +E8 00E8 +E9 00E9 +EA 00EA +EB 00EB +EC 00EC +ED 00ED +EE 00EE +EF 00EF +F0 011F +F1 00F1 +F2 00F2 +F3 00F3 +F4 00F4 +F5 00F5 +F6 00F6 +F7 00F7 +F8 00F8 +F9 00F9 +FA 00FA +FB 00FB +FC 00FC +FD 0131 +FE 015F +FF 00FF diff --git a/data/psglyphs b/data/psglyphs new file mode 100644 index 0000000000..c4a902c66c --- /dev/null +++ b/data/psglyphs @@ -0,0 +1,1051 @@ +0020 space +0021 exclam +0022 quotedbl +0023 numbersign +0024 dollar +0025 percent +0026 ampersand +0027 quotesingle +0028 parenleft +0029 parenright +002a asterisk +002b plus +002c comma +002d minus +002e period +002f slash +0030 zero +0031 one +0032 two +0033 three +0034 four +0035 five +0036 six +0037 seven +0038 eight +0039 nine +003a colon +003b semicolon +003c less +003d equal +003e greater +003f question +0040 at +0041 A +0042 B +0043 C +0044 D +0045 E +0046 F +0047 G +0048 H +0049 I +004a J +004b K +004c L +004d M +004e N +004f O +0050 P +0051 Q +0052 R +0053 S +0054 T +0055 U +0056 V +0057 W +0058 X +0059 Y +005a Z +005b bracketleft +005c backslash +005d bracketright +005e asciicircum +005f underscore +0060 grave +0061 a +0062 b +0063 c +0064 d +0065 e +0066 f +0067 g +0068 h +0069 i +006a j +006b k +006c l +006d m +006e n +006f o +0070 p +0071 q +0072 r +0073 s +0074 t +0075 u +0076 v +0077 w +0078 x +0079 y +007a z +007b braceleft +007c bar +007d braceright +007e asciitilde +00a0 space +00a1 exclamdown +00a2 cent +00a3 sterling +00a4 currency +00a5 yen +00a6 brokenbar +00a7 section +00a8 dieresis +00a9 copyright +00aa ordfeminine +00ab guillemotleft +00ac logicalnot +00ad hyphen +00ae registered +00af macron +00b0 degree +00b1 plusminus +00b2 twosuperior +00b3 threesuperior +00b4 acute +00b5 mu +00b6 paragraph +00b7 periodcentered +00b8 cedilla +00b9 onesuperior +00ba ordmasculine +00bb guillemotright +00bc onequarter +00bd onehalf +00be threequarters +00bf questiondown +00c0 Agrave +00c1 Aacute +00c2 Acircumflex +00c3 Atilde +00c4 Adieresis +00c5 Aring +00c6 AE +00c7 Ccedilla +00c8 Egrave +00c9 Eacute +00ca Ecircumflex +00cb Edieresis +00cc Igrave +00cd Iacute +00ce Icircumflex +00cf Idieresis +00d0 Eth +00d1 Ntilde +00d2 Ograve +00d3 Oacute +00d4 Ocircumflex +00d5 Otilde +00d6 Odieresis +00d7 multiply +00d8 Oslash +00d9 Ugrave +00da Uacute +00db Ucircumflex +00dc Udieresis +00dd Yacute +00de Thorn +00df germandbls +00e0 agrave +00e1 aacute +00e2 acircumflex +00e3 atilde +00e4 adieresis +00e5 aring +00e6 ae +00e7 ccedilla +00e8 egrave +00e9 eacute +00ea ecircumflex +00eb edieresis +00ec igrave +00ed iacute +00ee icircumflex +00ef idieresis +00f0 eth +00f1 ntilde +00f2 ograve +00f3 oacute +00f4 ocircumflex +00f5 otilde +00f6 odieresis +00f7 divide +00f8 oslash +00f9 ugrave +00fa uacute +00fb ucircumflex +00fc udieresis +00fd yacute +00fe thorn +00ff ydieresis +0100 Amacron +0101 amacron +0102 Abreve +0103 abreve +0104 Aogonek +0105 aogonek +0106 Cacute +0107 cacute +0108 Ccircumflex +0109 ccircumflex +010a Cdotaccent +010b cdotaccent +010c Ccaron +010d ccaron +010e Dcaron +010f dcaron +0110 Dcroat +0111 dcroat +0112 Emacron +0113 emacron +0114 Ebreve +0115 ebreve +0116 Edotaccent +0117 edotaccent +0118 Eogonek +0119 eogonek +011a Ecaron +011b ecaron +011c Gcircumflex +011d gcircumflex +011e Gbreve +011f gbreve +0120 Gdotaccent +0121 gdotaccent +0122 Gcommaaccent +0123 gcommaaccent +0124 Hcircumflex +0125 hcircumflex +0126 Hbar +0127 hbar +0128 Itilde +0129 itilde +012a Imacron +012b imacron +012c Ibreve +012d ibreve +012e Iogonek +012f iogonek +0130 Idotaccent +0131 dotlessi +0132 IJ +0133 ij +0134 Jcircumflex +0135 jcircumflex +0136 Kcommaaccent +0137 kcommaaccent +0138 kgreenlandic +0139 Lacute +013a lacute +013b Lcommaaccent +013c lcommaaccent +013d Lcaron +013e lcaron +013f Ldot +0140 ldot +0141 Lslash +0142 lslash +0143 Nacute +0144 nacute +0145 Ncommaaccent +0146 ncommaaccent +0147 Ncaron +0148 ncaron +0149 napostrophe +014a Eng +014b eng +014c Omacron +014d omacron +014e Obreve +014f obreve +0150 Ohungarumlaut +0151 ohungarumlaut +0152 OE +0153 oe +0154 Racute +0155 racute +0156 Rcommaaccent +0157 rcommaaccent +0158 Rcaron +0159 rcaron +015a Sacute +015b sacute +015c Scircumflex +015d scircumflex +015e Scedilla +015f scedilla +0160 Scaron +0161 scaron +0162 Tcommaaccent +0163 tcommaaccent +0164 Tcaron +0165 tcaron +0166 Tbar +0167 tbar +0168 Utilde +0169 utilde +016a Umacron +016b umacron +016c Ubreve +016d ubreve +016e Uring +016f uring +0170 Uhungarumlaut +0171 uhungarumlaut +0172 Uogonek +0173 uogonek +0174 Wcircumflex +0175 wcircumflex +0176 Ycircumflex +0177 ycircumflex +0178 Ydieresis +0179 Zacute +017a zacute +017b Zdotaccent +017c zdotaccent +017d Zcaron +017e zcaron +017f longs +0192 florin +01a0 Ohorn +01a1 ohorn +01af Uhorn +01b0 uhorn +01e6 Gcaron +01e7 gcaron +01fa Aringacute +01fb aringacute +01fc AEacute +01fd aeacute +01fe Oslashacute +01ff oslashacute +0218 Scommaaccent +0219 scommaaccent +021a Tcommaaccent +021b tcommaaccent +02bc afii57929 +02bd afii64937 +02c6 circumflex +02c7 caron +02c9 macron +02d8 breve +02d9 dotaccent +02da ring +02db ogonek +02dc tilde +02dd hungarumlaut +0300 gravecomb +0301 acutecomb +0303 tildecomb +0309 hookabovecomb +0323 dotbelowcomb +0384 tonos +0385 dieresistonos +0386 Alphatonos +0387 anoteleia +0388 Epsilontonos +0389 Etatonos +038a Iotatonos +038c Omicrontonos +038e Upsilontonos +038f Omegatonos +0390 iotadieresistonos +0391 Alpha +0392 Beta +0393 Gamma +0394 Delta +0395 Epsilon +0396 Zeta +0397 Eta +0398 Theta +0399 Iota +039a Kappa +039b Lambda +039c Mu +039d Nu +039e Xi +039f Omicron +03a0 Pi +03a1 Rho +03a3 Sigma +03a4 Tau +03a5 Upsilon +03a6 Phi +03a7 Chi +03a8 Psi +03a9 Omega +03aa Iotadieresis +03ab Upsilondieresis +03ac alphatonos +03ad epsilontonos +03ae etatonos +03af iotatonos +03b0 upsilondieresistonos +03b1 alpha +03b2 beta +03b3 gamma +03b4 delta +03b5 epsilon +03b6 zeta +03b7 eta +03b8 theta +03b9 iota +03ba kappa +03bb lambda +03bc mu +03bd nu +03be xi +03bf omicron +03c0 pi +03c1 rho +03c2 sigma1 +03c3 sigma +03c4 tau +03c5 upsilon +03c6 phi +03c7 chi +03c8 psi +03c9 omega +03ca iotadieresis +03cb upsilondieresis +03cc omicrontonos +03cd upsilontonos +03ce omegatonos +03d1 theta1 +03d2 Upsilon1 +03d5 phi1 +03d6 omega1 +0401 afii10023 +0402 afii10051 +0403 afii10052 +0404 afii10053 +0405 afii10054 +0406 afii10055 +0407 afii10056 +0408 afii10057 +0409 afii10058 +040a afii10059 +040b afii10060 +040c afii10061 +040e afii10062 +040f afii10145 +0410 afii10017 +0411 afii10018 +0412 afii10019 +0413 afii10020 +0414 afii10021 +0415 afii10022 +0416 afii10024 +0417 afii10025 +0418 afii10026 +0419 afii10027 +041a afii10028 +041b afii10029 +041c afii10030 +041d afii10031 +041e afii10032 +041f afii10033 +0420 afii10034 +0421 afii10035 +0422 afii10036 +0423 afii10037 +0424 afii10038 +0425 afii10039 +0426 afii10040 +0427 afii10041 +0428 afii10042 +0429 afii10043 +042a afii10044 +042b afii10045 +042c afii10046 +042d afii10047 +042e afii10048 +042f afii10049 +0430 afii10065 +0431 afii10066 +0432 afii10067 +0433 afii10068 +0434 afii10069 +0435 afii10070 +0436 afii10072 +0437 afii10073 +0438 afii10074 +0439 afii10075 +043a afii10076 +043b afii10077 +043c afii10078 +043d afii10079 +043e afii10080 +043f afii10081 +0440 afii10082 +0441 afii10083 +0442 afii10084 +0443 afii10085 +0444 afii10086 +0445 afii10087 +0446 afii10088 +0447 afii10089 +0448 afii10090 +0449 afii10091 +044a afii10092 +044b afii10093 +044c afii10094 +044d afii10095 +044e afii10096 +044f afii10097 +0451 afii10071 +0452 afii10099 +0453 afii10100 +0454 afii10101 +0455 afii10102 +0456 afii10103 +0457 afii10104 +0458 afii10105 +0459 afii10106 +045a afii10107 +045b afii10108 +045c afii10109 +045e afii10110 +045f afii10193 +0462 afii10146 +0463 afii10194 +0472 afii10147 +0473 afii10195 +0474 afii10148 +0475 afii10196 +0490 afii10050 +0491 afii10098 +04d9 afii10846 +05b0 afii57799 +05b1 afii57801 +05b2 afii57800 +05b3 afii57802 +05b4 afii57793 +05b5 afii57794 +05b6 afii57795 +05b7 afii57798 +05b8 afii57797 +05b9 afii57806 +05bb afii57796 +05bc afii57807 +05bd afii57839 +05be afii57645 +05bf afii57841 +05c0 afii57842 +05c1 afii57804 +05c2 afii57803 +05c3 afii57658 +05d0 afii57664 +05d1 afii57665 +05d2 afii57666 +05d3 afii57667 +05d4 afii57668 +05d5 afii57669 +05d6 afii57670 +05d7 afii57671 +05d8 afii57672 +05d9 afii57673 +05da afii57674 +05db afii57675 +05dc afii57676 +05dd afii57677 +05de afii57678 +05df afii57679 +05e0 afii57680 +05e1 afii57681 +05e2 afii57682 +05e3 afii57683 +05e4 afii57684 +05e5 afii57685 +05e6 afii57686 +05e7 afii57687 +05e8 afii57688 +05e9 afii57689 +05ea afii57690 +05f0 afii57716 +05f1 afii57717 +05f2 afii57718 +060c afii57388 +061b afii57403 +061f afii57407 +0621 afii57409 +0622 afii57410 +0623 afii57411 +0624 afii57412 +0625 afii57413 +0626 afii57414 +0627 afii57415 +0628 afii57416 +0629 afii57417 +062a afii57418 +062b afii57419 +062c afii57420 +062d afii57421 +062e afii57422 +062f afii57423 +0630 afii57424 +0631 afii57425 +0632 afii57426 +0633 afii57427 +0634 afii57428 +0635 afii57429 +0636 afii57430 +0637 afii57431 +0638 afii57432 +0639 afii57433 +063a afii57434 +0640 afii57440 +0641 afii57441 +0642 afii57442 +0643 afii57443 +0644 afii57444 +0645 afii57445 +0646 afii57446 +0647 afii57470 +0648 afii57448 +0649 afii57449 +064a afii57450 +064b afii57451 +064c afii57452 +064d afii57453 +064e afii57454 +064f afii57455 +0650 afii57456 +0651 afii57457 +0652 afii57458 +0660 afii57392 +0661 afii57393 +0662 afii57394 +0663 afii57395 +0664 afii57396 +0665 afii57397 +0666 afii57398 +0667 afii57399 +0668 afii57400 +0669 afii57401 +066a afii57381 +066d afii63167 +0679 afii57511 +067e afii57506 +0686 afii57507 +0688 afii57512 +0691 afii57513 +0698 afii57508 +06a4 afii57505 +06af afii57509 +06ba afii57514 +06d2 afii57519 +06d5 afii57534 +1e80 Wgrave +1e81 wgrave +1e82 Wacute +1e83 wacute +1e84 Wdieresis +1e85 wdieresis +1ef2 Ygrave +1ef3 ygrave +200c afii61664 +200d afii301 +200e afii299 +200f afii300 +2012 figuredash +2013 endash +2014 emdash +2015 afii00208 +2017 underscoredbl +2018 quoteleft +2019 quoteright +201a quotesinglbase +201b quotereversed +201c quotedblleft +201d quotedblright +201e quotedblbase +2020 dagger +2021 daggerdbl +2022 bullet +2024 onedotenleader +2025 twodotenleader +2026 ellipsis +202c afii61573 +202d afii61574 +202e afii61575 +2030 perthousand +2032 minute +2033 second +2039 guilsinglleft +203a guilsinglright +203c exclamdbl +2044 fraction +2070 zerosuperior +2074 foursuperior +2075 fivesuperior +2076 sixsuperior +2077 sevensuperior +2078 eightsuperior +2079 ninesuperior +207d parenleftsuperior +207e parenrightsuperior +207f nsuperior +2080 zeroinferior +2081 oneinferior +2082 twoinferior +2083 threeinferior +2084 fourinferior +2085 fiveinferior +2086 sixinferior +2087 seveninferior +2088 eightinferior +2089 nineinferior +208d parenleftinferior +208e parenrightinferior +20a1 colonmonetary +20a3 franc +20a4 lira +20a7 peseta +20aa afii57636 +20ab dong +20ac Euro +2105 afii61248 +2111 Ifraktur +2113 afii61289 +2116 afii61352 +2118 weierstrass +211c Rfraktur +211e prescription +2122 trademark +2126 Omega +212e estimated +2135 aleph +2153 onethird +2154 twothirds +215b oneeighth +215c threeeighths +215d fiveeighths +215e seveneighths +2190 arrowleft +2191 arrowup +2192 arrowright +2193 arrowdown +2194 arrowboth +2195 arrowupdn +21a8 arrowupdnbse +21b5 carriagereturn +21d0 arrowdblleft +21d1 arrowdblup +21d2 arrowdblright +21d3 arrowdbldown +21d4 arrowdblboth +2200 universal +2202 partialdiff +2203 existential +2205 emptyset +2206 Delta +2207 gradient +2208 element +2209 notelement +220b suchthat +220f product +2211 summation +2212 minus +2215 fraction +2217 asteriskmath +2219 periodcentered +221a radical +221d proportional +221e infinity +221f orthogonal +2220 angle +2227 logicaland +2228 logicalor +2229 intersection +222a union +222b integral +2234 therefore +223c similar +2245 congruent +2248 approxequal +2260 notequal +2261 equivalence +2264 lessequal +2265 greaterequal +2282 propersubset +2283 propersuperset +2284 notsubset +2286 reflexsubset +2287 reflexsuperset +2295 circleplus +2297 circlemultiply +22a5 perpendicular +22c5 dotmath +2302 house +2310 revlogicalnot +2320 integraltp +2321 integralbt +2329 angleleft +232a angleright +2500 SF100000 +2502 SF110000 +250c SF010000 +2510 SF030000 +2514 SF020000 +2518 SF040000 +251c SF080000 +2524 SF090000 +252c SF060000 +2534 SF070000 +253c SF050000 +2550 SF430000 +2551 SF240000 +2552 SF510000 +2553 SF520000 +2554 SF390000 +2555 SF220000 +2556 SF210000 +2557 SF250000 +2558 SF500000 +2559 SF490000 +255a SF380000 +255b SF280000 +255c SF270000 +255d SF260000 +255e SF360000 +255f SF370000 +2560 SF420000 +2561 SF190000 +2562 SF200000 +2563 SF230000 +2564 SF470000 +2565 SF480000 +2566 SF410000 +2567 SF450000 +2568 SF460000 +2569 SF400000 +256a SF540000 +256b SF530000 +256c SF440000 +2580 upblock +2584 dnblock +2588 block +258c lfblock +2590 rtblock +2591 ltshade +2592 shade +2593 dkshade +25a0 filledbox +25a1 H22073 +25aa H18543 +25ab H18551 +25ac filledrect +25b2 triagup +25ba triagrt +25bc triagdn +25c4 triaglf +25ca lozenge +25cb circle +25cf H18533 +25d8 invbullet +25d9 invcircle +25e6 openbullet +263a smileface +263b invsmileface +263c sun +2640 female +2642 male +2660 spade +2663 club +2665 heart +2666 diamond +266a musicalnote +266b musicalnotedbl +f6be dotlessj +f6bf LL +f6c0 ll +f6c1 Scedilla +f6c2 scedilla +f6c3 commaaccent +f6c4 afii10063 +f6c5 afii10064 +f6c6 afii10192 +f6c7 afii10831 +f6c8 afii10832 +f6c9 Acute +f6ca Caron +f6cb Dieresis +f6cc DieresisAcute +f6cd DieresisGrave +f6ce Grave +f6cf Hungarumlaut +f6d0 Macron +f6d1 cyrBreve +f6d2 cyrFlex +f6d3 dblGrave +f6d4 cyrbreve +f6d5 cyrflex +f6d6 dblgrave +f6d7 dieresisacute +f6d8 dieresisgrave +f6d9 copyrightserif +f6da registerserif +f6db trademarkserif +f6dc onefitted +f6dd rupiah +f6de threequartersemdash +f6df centinferior +f6e0 centsuperior +f6e1 commainferior +f6e2 commasuperior +f6e3 dollarinferior +f6e4 dollarsuperior +f6e5 hypheninferior +f6e6 hyphensuperior +f6e7 periodinferior +f6e8 periodsuperior +f6e9 asuperior +f6ea bsuperior +f6eb dsuperior +f6ec esuperior +f6ed isuperior +f6ee lsuperior +f6ef msuperior +f6f0 osuperior +f6f1 rsuperior +f6f2 ssuperior +f6f3 tsuperior +f6f4 Brevesmall +f6f5 Caronsmall +f6f6 Circumflexsmall +f6f7 Dotaccentsmall +f6f8 Hungarumlautsmall +f6f9 Lslashsmall +f6fa OEsmall +f6fb Ogoneksmall +f6fc Ringsmall +f6fd Scaronsmall +f6fe Tildesmall +f6ff Zcaronsmall +f721 exclamsmall +f724 dollaroldstyle +f726 ampersandsmall +f730 zerooldstyle +f731 oneoldstyle +f732 twooldstyle +f733 threeoldstyle +f734 fouroldstyle +f735 fiveoldstyle +f736 sixoldstyle +f737 sevenoldstyle +f738 eightoldstyle +f739 nineoldstyle +f73f questionsmall +f760 Gravesmall +f761 Asmall +f762 Bsmall +f763 Csmall +f764 Dsmall +f765 Esmall +f766 Fsmall +f767 Gsmall +f768 Hsmall +f769 Ismall +f76a Jsmall +f76b Ksmall +f76c Lsmall +f76d Msmall +f76e Nsmall +f76f Osmall +f770 Psmall +f771 Qsmall +f772 Rsmall +f773 Ssmall +f774 Tsmall +f775 Usmall +f776 Vsmall +f777 Wsmall +f778 Xsmall +f779 Ysmall +f77a Zsmall +f7a1 exclamdownsmall +f7a2 centoldstyle +f7a8 Dieresissmall +f7af Macronsmall +f7b4 Acutesmall +f7b8 Cedillasmall +f7bf questiondownsmall +f7e0 Agravesmall +f7e1 Aacutesmall +f7e2 Acircumflexsmall +f7e3 Atildesmall +f7e4 Adieresissmall +f7e5 Aringsmall +f7e6 AEsmall +f7e7 Ccedillasmall +f7e8 Egravesmall +f7e9 Eacutesmall +f7ea Ecircumflexsmall +f7eb Edieresissmall +f7ec Igravesmall +f7ed Iacutesmall +f7ee Icircumflexsmall +f7ef Idieresissmall +f7f0 Ethsmall +f7f1 Ntildesmall +f7f2 Ogravesmall +f7f3 Oacutesmall +f7f4 Ocircumflexsmall +f7f5 Otildesmall +f7f6 Odieresissmall +f7f8 Oslashsmall +f7f9 Ugravesmall +f7fa Uacutesmall +f7fb Ucircumflexsmall +f7fc Udieresissmall +f7fd Yacutesmall +f7fe Thornsmall +f7ff Ydieresissmall +f8e5 radicalex +f8e6 arrowvertex +f8e7 arrowhorizex +f8e8 registersans +f8e9 copyrightsans +f8ea trademarksans +f8eb parenlefttp +f8ec parenleftex +f8ed parenleftbt +f8ee bracketlefttp +f8ef bracketleftex +f8f0 bracketleftbt +f8f1 bracelefttp +f8f2 braceleftmid +f8f3 braceleftbt +f8f4 braceex +f8f5 integralex +f8f6 parenrighttp +f8f7 parenrightex +f8f8 parenrightbt +f8f9 bracketrighttp +f8fa bracketrightex +f8fb bracketrightbt +f8fc bracerighttp +f8fd bracerightmid +f8fe bracerightbt +fb00 ff +fb01 fi +fb02 fl +fb03 ffi +fb04 ffl +fb1f afii57705 +fb2a afii57694 +fb2b afii57695 +fb35 afii57723 +fb4b afii57700 diff --git a/data/utf-8 b/data/utf-8 new file mode 100644 index 0000000000..41459ae14f --- /dev/null +++ b/data/utf-8 @@ -0,0 +1,38 @@ +charset utf8 + +# +# This file defines the font mappings used for Unicode/UTF-8 text printing. +# +# Each line consists of: +# +# first last direction width normal bold italic bold-italic +# +# First and last are the first and last glyphs in the font mapping +# that correspond to that font; a maximum of 256 characters can be +# mapped with each group, which a maximum of 256 mappings (this is a +# PostScript limitation.) The glyph values are hexadecimal. +# +# Direction is the string "ltor" or "rtol", indicating left-to-right or +# right-to-left text. +# +# Width is the string "single" or "double"; double means that the glyphs +# are twice as wide as ASCII characters in the Courier typeface. +# +# "Normal", "bold", "italic", and "bold-italic" are the typefaces to use +# for each presentation. If characters are only available in a single +# style then only one typeface should be listed (e.g. "Symbol") +# +# Each font that is listed will be used (and downloaded if needed) when +# printing. +# + +0000 00FF ltor single Courier Courier-Bold Courier-Italic Courier-Bold-Italic +0100 01FF ltor single Courier Courier-Bold Courier-Italic Courier-Bold-Italic +0200 02FF ltor single Courier Courier-Bold Courier-Italic Courier-Bold-Italic +0300 03FF ltor single Symbol +0400 04FF ltor single Courier-Cyrillic +1E00 1EFF ltor single Courier Courier-Bold Courier-Italic Courier-Bold-Italic +2000 20FF ltor single Courier Courier-Bold Courier-Italic Courier-Bold-Italic +2100 21FF ltor single Courier Courier-Bold Courier-Italic Courier-Bold-Italic +2200 22FF ltor single Symbol +2300 23FF ltor single Symbol diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 0000000000..d46b71cd3e --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,148 @@ +# +# "$Id$" +# +# Documentation makefile for the Common UNIX Printing System (CUPS). +# +# Copyright 1993-2000 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 --titleimage images/cups-large.gif --numbered -f $@ $< +.shtml.pdf: + echo Formatting $@... + htmldoc --titleimage 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/accept-jobs.gif \ + images/add-class.gif \ + images/add-printer.gif \ + images/cancel-job.gif \ + images/cancel-jobs.gif \ + images/cancel.gif \ + images/classes.gif \ + images/continue.gif \ + images/delete-class.gif \ + images/delete-printer.gif \ + images/draft.gif \ + images/hold-job.gif \ + images/left.gif \ + images/logo.gif \ + images/manage-classes.gif \ + images/manage-jobs.gif \ + images/manage-printers.gif \ + images/modify-class.gif \ + images/modify-printer.gif \ + images/navbar.gif \ + images/print-test-page.gif \ + images/printer-idle.gif \ + images/printer-processing.gif \ + images/printer-stopped.gif \ + images/reject-jobs.gif \ + images/release-job.gif \ + images/right.gif \ + images/show-active.gif \ + images/show-completed.gif \ + images/start-class.gif \ + images/start-printer.gif \ + images/stop-class.gif \ + images/stop-printer.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) $(DOCDIR)/doc + $(CP) $(WEBPAGES) $(DOCDIR)/doc + $(CP) overview.html overview.pdf $(DOCDIR)/doc + $(CP) $(DOCUMENTS:.shtml=.html) $(DOCDIR)/doc + $(CP) $(DOCUMENTS:.shtml=.pdf) $(DOCDIR)/doc + -$(MKDIR) $(DOCDIR)/doc/images + $(CP) $(WEBIMAGES) $(DOCDIR)/doc/images + $(CP) $(DOCIMAGES) $(DOCDIR)/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 --titleimage images/cups-large.gif -f $@ $< +sam.pdf: sam.shtml + echo Formatting $@... + htmldoc --titleimage images/cups-large.gif --duplex --compression=9 \ + --jpeg -f $@ $< + +spm.html: spm.shtml + echo Formatting $@... + htmldoc --titleimage images/cups-large.gif -f $@ $< +spm.pdf: spm.shtml + echo Formatting $@... + htmldoc --titleimage images/cups-large.gif --duplex --compression=9 \ + --jpeg -f $@ $< + +sum.html: sum.shtml + echo Formatting $@... + htmldoc --titleimage images/cups-large.gif -f $@ $< +sum.pdf: sum.shtml + echo Formatting $@... + htmldoc --titleimage 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..7ca60fa5a3 --- /dev/null +++ b/doc/cmp.html @@ -0,0 +1,665 @@ + + + +CUPS Configuration Management Plan + + + + + + + +


+

CUPS Configuration Management Plan


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

Table of Contents

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

1 Scope

+

1.1 Identification

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

1.2 System Overview

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

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

+

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

+

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

+

1.3 Document Overview

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

2 References

+

2.1 CUPS Documentation

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

2.2 Other Documents

+ The following non-CUPS documents are referenced by this document: +
    +
  • IEEE 1387.4, System Administration: Printing (draft)
  • +
  • IPP/1.0: Additional Optional Operations - Set 1
  • +
  • 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.5 2000/01/04 13:45:38 mike Exp $" tag: +
    +
    +/*
    + * "$Id$"
    + *
    + *   Description of file contents.
    + *
    + *   Copyright 1997-2000 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.5 2000/01/04 13:45:38 +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..d98093e943 --- /dev/null +++ b/doc/cmp.pdf @@ -0,0 +1,754 @@ +%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[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 +]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[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 +]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<>stream +xÚìÏsë8rÇIŠºÌ‰öŒî´üt§çyšÝ­ÚJñÙfvçÖ$ÁÊ!•S*Ç6•üÿ±~X"H€èn$è5¦jêÙE|ˆÆ·@ƒúÇOßòýÛßò?=å¿ýžÿçÿô,~*ÅOÿÈÛÿù×?þøÛï¿ÿºÏÿü—_Ÿò§§§·kýñõ¥ù÷¯|­ÿöœþº?•ßNå÷SùË©¼œÊ¿žÊ¿üÇ×?òÿýŸÿû¯¯ÿ–ÿíÛ׿ç‡oß¾>ÃKþ=ÿãõ§öcøä²+âõi»Ý>ÜËÛ?¶ß_—Î%^¶wY¤*w÷¯ËäOj¤Üöû¸ē‰é½Ü?–KáÂC]о/ëå!"—x[ÎõœE¼r˜ë‰KåÒ!˜¾rÛg޹^òȾü\ÆÕÊÏ3s=GžJRÎÉõ-òVâÃl\ŽuЄõV¾ÌÂ%²( + ‚B¹ü29×$X,0X –€Åƒ %ƒ/° ¬(ÚMÄåÝoÙ9h6×ÄXo`å\ûhò’LÀõ#𡬼sÕÑ,åÏ\M6A!|…gi,A +Ú Ñ ê£s5Ѭåà‹+›— 9Ä`™ãÅ`ž‹,öD.1?V{àÊàŠRç\uD98æY\‰c®}HÙ8媣`Jé++D91WT蚐°ŒÒË TÔ  LÔ‹Š4ðZåªBÃ2t,OãQ ÔxŒsÆq‰±FãzX¢Æ#F,Ï%£FL×]w÷Ûí—×cy>|ðÛa0IwÅ÷_†ƒüxÂ[‡ÿîŠG’þÅ˃ŸßÝuoœ*=[ í,¸ö~ºªÛk[ça=xì.Bú±àæØ\ìPƒ–.Î$[q¹¸¡==·aMJ&³»XéԜ.K™\¬@ž› É貘ÇUùÑv‡]¶cqeSÙà՛eN¤ܯjؤ½s’  ®|²¡ÅϼJé\Í Xd°˜ÎEùØÍÉÜZ9ƹfÂ"‚­¨\Õ FÈ1ŒȕυEÛи'’ –Y¹0p7ñú¥uZj+Cg‘¼c,Òé« …«rÎX•½ÅÍÁ‘jÄ¥{.B J<—°ÒlKÃ7D=Ì:¸ÎåÛÁÉ %i=•œkˆàBf½ .Ú`Ø`¹Š¹2O”,Á W­Ç’ó ìÍПR4q‡ãÚa…„–¤8®´&1Š«žÙ#3ì€á«aÚz/8 [c¸²0Dƒ¢õ ‚«æfóuXiæ*B J‡íÌ\Y OjOjäªÃê.d‡%F®"°îBú°ÒĕÖ]È'½1p5Á¸dZ“RW\wá¢ÄÄÀ•6ºÐRVŽr‰» 7æw£\u€Ý…[FJG¹*OŠ…²¢d”+ (2$*ÇVå'ÆB ÃRåÓ©¹Z’ Wå“s! q5ÂÀÚÛ=W¢È£­ÔrAˆ"v@;-W¨jàLi­ã¡ªnè¯t\5-4”=Ùí§ž±¿ÿ.Ï´’T¹Æúù=¾aÀ +¢6(®–KH·Kh%ºÖRÕÓbQ®•–ër›®Îa‡Àà ¯Çé¹ £^ >ÜÌіœáµCrí´\MçùÖ 1£$UsÑys¥Z®³í%·NH)}¢æÊ‰Îkœ+ÑsÝ´BPf=ègŒàp‡åz7.×MÛk¼b”¾Tq5ÔÊÀµÑrÝD° ¬•T؇ô¹WŠçZ鹊÷G”Q&ß V<זByW¤çª/ŸÕPÌ1PRWF4C#×NËu¾×úü+ü’QØV +.A5C#WªçڟòáªÕr[¬àª©fhäŠõ\盽§5Rì•K,×êZ[Éu6Ž;êÊ12BªWNZ,×:{—'%WG¤(³ÔgO@• ž«x j®Š5K5†ˆëWC6Ãq®ZÂp ÖbI…Ó5 ÊFÒâ¹Ä»Y¨¹®&EZ,ip-â\9%pžê¹*֚Nè(; +\n£á¬5;c+\ŒôÅq®æ" +®K‰kvª‰@“¤¥pµ¥×qgéB™ÐdcMãº(½Ž«àôWòD@“ë¢ô:®Œ3¾êÙwCÅuQz WÍÛÃÈ0’ ¤h#!r]”^ÃUðûMÏ%s Æð2r•^Õñ6g +ÌÃ’lì¨\g¥Ws5Ì]Œ +㘁´¶ÑR¹ÎJ¯æ½ØER2WÁ^f®“Ò«¹rfæŽÀ8f DQ)ëd݅~^¹e¢IàkSYŽ­\§Öç*®³Ý Fȑ#š ”(ªT?º²k ±ÌukDŸ+?krN7Ä="àVÌµë>š>h¸Þ;а›‚]†Yw¹k6+IlºŠšô¸ Wuáiè†X!dr¸Ñ˜ÄjøCýsȵèÝJ´§•¸rŽlH[âã‹:\…’K\[°'¢@Ø¢C­I¤€]Ÿ«VrU×Ê=öEèà£ÃDïû¯´ùÖṌŸêsí¯#èùVž«áxåÛ-â;^WÈ\OÌɱonn0¾d=äª\ÝT”‚lˆ{ó€¼0ÚT¹WWojò$ ð\{–l lbÕ¹.¶*qeÝKž„‰×ñÒáÊY²Ñ˜×Ó{Šyq—KΈÚ{ÈhzªX¯üPy8Å:F—« »òúh9ÔNþnï5ùÒ*¹Ä€+“,¯ñª è¨Wo'ÍéŧñýGH©\SßËy°†ÇeŽæãvQ°2Ÿ,’+çEQÁse¼(*t.a#‡s5–r*W͍çª>š^¸ +vt6מ͕4™¿peM/\œ¥ùp‰'óg®úÃÉ<–k2ߝÎ-‡͋ó·•Ü:\[æ»uîªßFwÒ²ßmµwpœOm›.Ò,²Î-ï\·u›þà,•\×FÍÕI¿\¹r¶ûRãkT§×ćk¥äjÔûËÛ}©4fÜkbÄኔ\¹z߁¿h£¶W]nj¯‰;×NÁU UPn9Ár­4áËNŕr¸RW6|ŒŽ¹Î«Ëë51áp%C®wшﲫÝÊ-§h®š+Vqõó¡¸g¯r~ô'/ÙÅlp\ëQ®Ó¿^òHjÁZv,¥Šk£tEr<Џ¨ëdÞ7ÛnlÌ\—᯻?"éx@·‰+×à¢Zr—Ûj{‡àꤥÈ]|Ëíé71âp .’7.y<€ +£®[‘"K~­lâŽÃÕ¿(—óM +-áðì8—Ðpz®”ÃÕ¿¨7RNf™*Œj1\·Ùÿj®˜ÃÕ»¨ðTà¹b\Šã|f.ÅEußÁnßÊ#`ÂÃĞk¨Šã|f.ÝÀT5_ŽÜp ×^­óŠã|®áE…ÒÁ&ŒJ[=Ì®9·r‡Çù\Ër¥#Bq­Q\µÚ՚8JqœÁ5¼HËU;â*”ñÆË- é5qxœÁ5¼(S:"×Ã%¢"ÎSÇù0\ƒ‹´\?Œê´áò;ô¼RqœÃ5¸¨[ývGסµœm”MçÃp .Òr?ŒjÕ£YU4ñ"Ú4®þE\-š+Uý6.5MìçCqõ/Òr¹ê^,ÕMìçCqõ/Òríùáa«68Íòþ ‰ýã|(®þEY/Mõʕ;ãŠK W'T•šØ;·ãê]ÄçJ\ñ®óۋ_¾,{lÔMìçÃqõ.Ê;Š-qen¸:ù‡Ýxã¼ì‘ª›Ø;·ãê]4ˆ£*,WÚâæ)­Š«ó~(EO¢Må’/Ú÷#¢âÂùåªÇ¸äã|H.ÅÀn÷X®µW£‹ç¯AeNä’/ªúC%;s Ï\BsŠCqœÉ%_T÷$[DX®W;Ê.é"Ñ Í« ¸—|Q&°üÂeÎ=Üy䒎óa¹ä‹ +E2þW=/WÁá’.ªn»Ê·EÞÙ¹j—t‘è¶²¾Æ6ÓJ\‚Ã%_”ßö¿ž#W铫{œÍ%_T ö+Càª8\òE½H0?qÙL—Q\Ù8WÃá’/’gÆé>®Îq>ès¥”ºór=ŸÞa?bšK©;3×Cÿøšü²¡ÎæuÕ»ꝪHqPJÛ:k®|¾!çéw·§†u\y1Ô׏áŒF~™WsÛìø9QeäÚÉÔ—Pì(É/4¬®KüuòÈȵ™‚ TSë¼;Àz齺 ®u+ M?\™j« ºã “Òdúu\©l)^¸š÷§»nÝî«ko»õʺ ®Dºµ®êºQ(¾unڑÀ[v…².Ÿ«öÉUtv¬÷7ïÒqY·äsM]Õ2¿ú®òöNå“+ª›v^Ȭ©K㊯ۧoƒ8ñƕu—áòžÒߌ§©KãJ®£0qÙÄóҟá¦×VËIÚªº$®Õõq¼=™t®êöÓ5ä$mU]WÚ}tk;.CúáõÏÍÝ[ÙtĪ윑Ò×%qÏ]ÓÆ+W¢ûѧ“T<¶ÔçÊ/ƒô8„wÞ¸2]:ÎeO¹éÀd#©;x®ýåóŽŸ|ðÆuŽš¸1‘†‘¶.‰«¸ÈÐÑÒKo\—½Îûƒ:À:eR¼Ë¹¶.‰ nÙ¯qëë¢Z{þ⇬ã‹õu•\ÃÄÎEu¯G÷叫“Òkmñîm®¾X_—ÂU_ `ü`;®±}½n=é½ÄÕ0‹V[—ÂÕ\~<ºeK®±}ØByŽCš—ƺ.]_ˆ¾ç²Ú_ÚÌÒ|Õ¢¯Kàj/Žùô[\½,Ú¸ôdЍKá:;æ“[öÉÕyіL¡ú’9]] +×Ù1×'ï“ëý ì —J•l:ZÇuvÌõ©¾—1ïë9Sš\ùPÔuñ~ùäËãÿc—‹|¶—‡á¤¦ÒLrTu \ÕÉOnÙ?×­µ«^(u@Õ%póÉ-OÁõ. +‰vЌÕ%póÉ-[raß-Z‹ÁX]—x÷b멸n‰×f®^]×Ù1ŸEr”Ë&ûø*™ìе\cu)\o&˜4·õS/\²{ãb§®.…ëM2âúì-¹JÜú¡k¬.…ëØÓUt}Q7®D²­x”KW—Âçð±‰ËæÜM.ý9Õù±º®ê|²&±çڍO¿6ÝyÈJË5V—ÂUߜº7®ªÛŸûÞmz«Kájn³Q.›sˆçkãï·M­–k¬®!ž—Þ¶%ä]A ®qö¶ ©Ÿ,ŽÕ¥puÞ ë«™«õ¹F꒸r—Õ¹ìf¤jŸk¤.ƒ«´çZãÒmú¡ÿ VÑ×%qƒßxàjô +3àj¸ëQ2\ŸÊ(—Õû7䵘_ÚQ.}]—îý¬n¹:}l \Úº$®úêÓǹ¬²Þè!Ón”ØÔµ*–ïí¹Ê×ëMóU|–ïY +¶X¾ë“kz.ó떗ÉUüÓr•‹ä2/pÉe3aþ䚞Ëjb¹h®õ"¹Ä?-WºH.ólõA¹’ere0ðµü>ŽO®¸ö0ðÅ}Ïn‘\ðA¹ª Z~¯Ù\Åô²×å÷ÐÍULMÞá¾70¸@ªrÃ\ e’ºÒò{9ç*Š+[\Àa +%°ß{ZÀ‘›ì ù=Å¡­´e&=@~¯thG„â‚¥Âèo‘ßoXÀQã¸÷}ô•±mç˜Á8lc®Á9æ½Qæ#/Á9°Üè–ã‚s`™±Åš3‡}€²×ÀXcV@éK`3Ëڬހò9°ÊÜX@=€ÀXa6.@l`3°½9êT˜ËÍ"8á Kèmœ£ Jè„m®gƒú¡€S˜ „A:àª%ô¢©€ìڐ„>G˜ ‡bH}fv_ï\bAB/0Ò -Vè׋‘Ã]‡+_Ž V˜Ȑ+ A,0 +-V裥ÈaÜ媗#ˆ(Â-ôDˆ *âƒ-ôéBäpÝåB} Â(»‚-ôÇ¥€VÏP„#C̾:\ÕB")£œ· Å }ºÙHd.„Ð'‹TæB,Ýċu+_†pd8üƒ"âȇxà B8j¤—Â!Gl#´A `1Û¨«>BðÌØå +h)‚¸xí\Åú,(ÖCéÑg­¡% ÇÜ ýŽhIÂ1ó3?ú•‚+~€áï€d¼s°=z @KŽy>r’s˜y€Õø©bå™a÷H*:sˆH؇–(30Ê&ÐúyÖ9eˆιÈQDs‘ƒ²Ôā9£Ò7”AОQéI+Ò@½t>¥Ï)Mª’ζÚ&HšÔ¡9›!"li¥åڇkˆ´åhél¨vc! »ô™ ±¢g83âžö¼nų¢ †®@žâÌcˆñqCË`3Ĉ9qx@Ë`iˆf(Í4€ó`¦Ÿ¬Tԇ -g€M>kΩj-k€MœdY“½´¬6± +ÈcX]>±rz‹€5D'VFÔ +œéöÔ1GNÀY™8樼A:©ÔgB©œÇ Üϙ.H,8ޏÃtºc wàÊêd†kÍÁ…Tú‰:,c=càÔ4Æ €?R§é°ŒÖÛNÓaә_‚& :C¢Åqí±`»0ºk…äªé0‘qƒph­ ±÷UKó„ªY.´v†èuâ,øV­!zÕzìÓÝ ¹ð†èQ:j ›ÖÖãrfWŠØ ¬OKüñÍPË%¢¹-±±’.h­ ѓ&æV>¬­'BõÊXZ?Þ¹±´°öõ^†˜È,e \<1÷3–½í#×½{&ܸ¥rU¤s©ÍJÉ\"š LdöܹK0‘;¸)82‡i\o\´;¼•Ÿ'–‘P¬.t¬Â^¿¹1p1_uFÃÒÇàd}¡ãNSbé¥ +\EiW°/)áøf08Ô&[õ cœFwžÿf<[l2êR6W›qÀúßtŽ*OôÛø\‹+Š¿S;‹añcq€‰‹ÙaQt_zî¬ñ¹‘‘«ˆ¸ÿ¥ó/9k·6\"â—{”56¼OßYqYtØqœ=šÌñ…Ie˜>˜¹l:ìŒöªÿ짌ý¹K.ê4Li¯ƒ~/ÛÌæqµ¶\Mä¦ÜÝo·Û/¯oåe»}È,?mcÍå¢ÃœSþ#†KȵqÀe'‰³tŽ+¼Û9á +®ÃÌK_8.±´îBrvm¦(ˆ=$W›…ÄupÇU/«»Ð\¬•O_ºäj‚áÚ´.¹‚ÑzÜöžKdKÑxw gÑ q!Øý^ +—XŒÒ¸°DôÖ!‰kvKÄgиš…X!•kæø—°MäšÕ)¹/T®9½3eû‰Ê5c`OJš#sÍ6Ähi/t®™†1±ŒÁ5Ï#îí2¸fbÔ,%=pÍ`sM®ôT9×ÄÚÁÈdr‰<\)´ášRY©Ã\®éÀx™dl.FÚÏ$ŽËšk¢Éóā×þ9椰áòoŠü,M+.ß`ɧv\~UÑ&Yؒ˧ƒ¶Ê¶åòf—ŒoÍEΡö41qÏåcÚb™®î†Ë½,ڟ›pÂÕ +·¶øhß"7\o¶è®Ë’CW+Âé,—\ŽºìþІÆÕŠ'küâª-.¹ø©ÕªGw-qËe‘^Hݞ“‹Kæ–ʇìþ‹ë6øà"æÅÇ[ï¹ðÃõV^qÙññýw/·÷Æuê5ƒAÞm_}ÝÛ'ש۞¶wê~z|õy_ß\çŽ;žpØ>ÜËývûøúêý–“pÍPàÿÿÿârõä +äÿÿEŽÁ‚0Cï|Eš¸É`¨;*ћ âü€Ebp3chø{™‰ñÒCÛ×t'£åA ‰!kd‚® +º¬fù¥8#·¦n›Á)ßZƒ£2ªÑm<ŠN™¹¼O0cf<£KiòÃI~,£q(Æ)IV”‡x¯úg[û·r…³Õpõý·ÈÓéÅÇ>G×67&ĚL"ØvÊ`ö(u¯ÝKWÝËè}ŠÔñèendstream +endobj +125 0 obj +6288 +endobj +126 0 obj<>>>endobj +127 0 obj<>stream +xÚ+ä2T0BCc3JÎår +ár á +äHÉHendstream +endobj +128 0 obj +31 +endobj +129 0 obj<>>>>>endobj +130 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 +131 0 obj +868 +endobj +132 0 obj<>>>>>endobj +133 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 +134 0 obj +117 +endobj +135 0 obj<>>>>>endobj +136 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 +137 0 obj +541 +endobj +138 0 obj<>>>>>endobj +139 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 +140 0 obj +122 +endobj +141 0 obj<>>>>>endobj +142 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 +143 0 obj +544 +endobj +144 0 obj<>>>>>endobj +145 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 +146 0 obj +118 +endobj +147 0 obj<>>>>>endobj +148 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 +151 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 +152 0 obj +214 +endobj +153 0 obj<>>>>>endobj +154 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 +155 0 obj +848 +endobj +156 0 obj<>>>>>endobj +157 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 +158 0 obj +285 +endobj +159 0 obj<>>>>>endobj +160 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 +161 0 obj +423 +endobj +162 0 obj<>>>>>endobj +163 0 obj<>stream +xڝ“MSÂ0†ïý{ÔC‘B)õ(Ð* â4þ€XB„DӀ¿ÞMUďiN»³Ïîûîö9ˆ ‹_ýĽjŒhp‘'E@W.”¤q'º<»!!ÏÏé#æãC>ì%¸ÍóÉ­ «ÖÌ,¡,70ÖÊ-aÎT½e5ÿ$|wØbö3}ÿü4£ùiøÔ¡·©Z(Α]eÍrm*/—_`Ûa“mu¥¥X.~"2+´bJËÔÍh`aj¦Ä{›ð°çdrš=Gå{['Œo¼¨bZd§YÅVZ±áKÁ`oBÁ„„ìµzÀmù,õ^Á5ÿ嬈O1э-+#žìA7oڀßDz¦–ÜìTð¦qΤ®Öͩ焨;«Î…ä@ SÍ +ÙÇg”~Õ ø·ÒËNâ*Çw¤tN­D½5íaàN´á +õJÖ + £xˆUá°×uEQÏã~¿Óƒ6p×R£óæ nƒä&endstream +endobj +164 0 obj +379 +endobj +165 0 obj<>>>>>endobj +166 0 obj<>stream +xڝV]sÚ:}çWì0}H[06v ðTJÈ\fÚLï…$}ȋ°Ö­m¹’ áßw%â›aš0ƒ°öóìîYÿnyàâ¿Ã>øÓÖ×e«w7‚¾ Ë5Þ †,£«¯0åË6ðý]0ASš)ùqù?ÊàyV¶Û8FzSI!´¢¢¹à[Qˆ¨",¡°lÍEJãàGòB„ÖxöBi$‹ âa¡Xِg +8:ôìùNÿÕó¦@ ˨“$’ç C‡Šƒ~256§Ÿ?W]ã‹`ÇT Ӈ Çf9oXf¸ÎÁÄñ`a•ï´òQ0(¯]  +¢è=I1•FÌ&ԛP2’Vã÷°:1$TTHàPF"|øm0V̋f²÷4GV,ajoáID<ÜϾÃ˸ÚKESé’±î5À„eýu‘…ôC41Ù"žÐ,4•[CÛ Ûºd0¹_ÌKxñYžÛ§ˆô;×ÕdÐésc”m–…IÑvÈYŸqÛ9Ý÷Áö>ÜVÛæ\Ç"‚¹6JI¿éC@‰ˆ)ÑhnØVƒƒ1›RiU}Ö*sÊ ‘sìFÌ>#JWƊ4ã`õBžïÛÄÊ`˜°P'Œž2®ðÜ1O§cYÊØÌ8ƒp`Yžl|¨öγ [f ¬!« Ájo¬MÐþ0ÆÈ¹#c•&-xÎ5²„ëö\¯ç"¤þ8¸û7²_f/9|hƒ"›±Å܅‘†9¦Û7ˆ÷>¢)Ç >ý“3§vn© ËUÙ8•’B¤s‘…é±*Þh4ìê 4>3"÷88kµ#Xà‚GE¨dÇpŒ—uƲ”ØÒè2×G:5–J¶îØÖ–Ym[èÑ/ t 7‚¤0ª:“¦?Ï©@Š@@êÓ06õU™G·D¹;ŠA’Jë&dç ì £e«Â஍˜ˆ…ÅØå…Ò4ÕÙ¬´2´¿Í§³ûÅÌQ/ª »˜éy‘D–V”ê.6¼a¹»>iln;0_¿þÔ=Ÿ2i† ‡5")Ù ™<¡DÚ6AÖ­3؄š_TWý7Q*›Eߎ“>Ç&½z×MÒAà×0aHHBÁ#£;¸l‹d²(˜¢8bA“ê?>>>>>endobj +169 0 obj<>stream +xÚÍU]Ó:}ï¯UHlWmš4Ù¯/,EÚ`å­rIcpì`;Ûö^ñß'i»4,°<Ñ­Vþš3sŽç¸_{„ôA|轜÷Ưˆ"˜g´s~™—0OO¬® GȄÄg 2p9‚3Œ¦„…BX+Ô +„ó³RÓl)éDÎp"äÌÂQÔցBfjT)èÍCOóϔ?„+Ÿž*MŸ}|ê7BEaSœÂ¬ í?¹I§TyØÜrxQp“0 Ça4‰J>>>>>endobj +172 0 obj<>stream +xڕUÛrÛ8 }÷W`üÒ8S˖ãK’¶m¶ÙÉöéÔ»OžÉPd³¥H-I9ñîôß Š–/R܋=c‹x€BÿvbÒ7†Ù.¦Àóλygp;„+˜g~gz9‹F0OÏç½ù—Îúñ0ºôp/¸dÖ^_§úÁ­„]œ-z/ 7:/J‡°7öŸ½¨u¼÷A;´× ´Â¶û ±ÓXfR3íÏà>RNwjÆ"ú ¬™,ñ% £!¼~CyÒOLÏ­M~!±ñ°w{¿‡ƒÅÙïi‹Gn-Äÿ›¼¢¨EÕ +"¼Í¢÷ªaüæ×ƒÛ+ˆg¾C}jQ¼µ½‹Æð3‚%íÎoìýa2$sðŠbøÀr¡–Ái q¼uMƒÓ…[ƒ¥Ô “`¹.ìŠI g…pLŠÿ0¥t»s*R}²ûhÍÜñZØÏŽ9<ØDÇ£E¯fyÄ6_!h%7€O '´§+-)åAŽoþ¾ÿ B94ãR$†™MñzÏd%ø +òÒ::¹*P#„FðÂ`&ž ËËÂv=-ÿФöŽè&ðg3î.Yƒ…¤ SH6•Š{^ØÌ,Ë•óÙ¢BÒ,)ÖZA@µLN¶HjÞîô匔_y•*¥kÀµ¡c ºGD*ƒ6©õ<}}Ö;BÔÈÌ܁¹æûVm¶¡(›cž!K*:«KC}ÊÄa#S¤»æÏt- DðnÔðÅE4­<‚?4¯*Åê*>«ã÷ŒZ^çõL4]%„3¤J’ŽB`*Ý;Š<ÇT´˜ié«YÑbÀuîÃCBÜ¿6J•¢åF$tÁ*Öñ¯CšûáÚUI’vá¨ö¯ÂÜò·€—Æø0¾*t'²p Zc%@ôçÇ4ÄÄÉI2ù¦øá™ü|м¥":‚ÅòËðË¢ô½è>¸.°¢@òJÃ@ E`°õ¯µìcÓiº®UmvËýÌ9!°Éï ¬âØ­Ø›ê8RQ‚­2÷ÇRÌNÉâ¹7®C!ýP~™¦‘c@W“Òžxun/·éÇqL–éÕ(Ø+ˆ­2±,MÅþbŠ-±bp/Yžgäߟ†Ï¾kƳ1™+[<ñïçOï3[€‚endstream +endobj +173 0 obj +846 +endobj +174 0 obj<>>>>>endobj +175 0 obj<>stream +xÚÕUÑn›0}ÏW婍Á ƒt}Z³îmS§²·J‘1N`ÌÀ$Цý{¯ Iºdm×Mš4!|}Ïõ=ç+ß = ÓÀüD1¸Šã÷.-M$˜…îQr¦·•LäY©!ÚªYè4£Eúò<úB¨ °ÐÀÂ9¾çÎ îÊ p«ëV趖Í>Ñ7‰œ×žë÷i.ÃG^dåªKòÁXŸ4 º¤·yŽfW %/dƒ&å%rµ‘µàÄ&Ó)Ú2‘u#J»z#e‰ª“¼L0\P!xUIÊK t*A ¨¥ù4=ÐÉlÚ±7gáîlhIw-Ø +¯@!®I-Ü»óªÓ)IÑSàm!KÍu¦ÊG_s‘> Ü‘MùZ‚C¨Â@œ+ñ-’Œk™o‰ï’x[FÖr–¦V!‹XÖ{Վh&}S¤HV‚ ’/á¥è%5õÖ¼Îxœ[õiT¨Tž‰-x¬ÖòMGã`gbIŒG»czO`„ˆ„|@ŒÔ2æŸonéCż†ªŒ2{‚EzŠS†q”ùý¸–u³Åtº\0oëÚ(ÛÐt¤mÌ䜞¼Ã“žÅs}ŠÿñôÅ 1ÏyÓ îÄendstream +endobj +176 0 obj +572 +endobj +177 0 obj<>>>>>endobj +178 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 +179 0 obj +746 +endobj +180 0 obj<>>>>>endobj +181 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 +184 0 obj<>stream +xÚí“ASƒ0…ïüŠ=ê!‘ZÀ™Ԗ›c-xîD¦©Nÿ½ v„ŽSï’K†¼oo—¼; \\ ޲ʹM«8îBš BÊ`øn.î Q¹ùZBªÕ°’Òb¥«Ëô Á 0fAøÔâñ€rË&»ªz*‡¥VˆV×à÷s#j¿µë3Ÿc¡a½aï‰üº0û]+îÝØl/Àž»È{¿^óÙ\e»JÖF˜BÕd¡µÒ­ŒüÐy³§Z 1Š,uQ"H\`sFý‘7¢ÛÊS¥'ã҆ܔå°×áÉä™jä v«üŽ}/²×¢–`³>4RcÎú…$û­AÜ[±IH££×\Q70—ÛLmÔ/3ná?ÍxÜÄîøï‡‡±pÆi`Ç2¥g^U/hØÍ‚EöÅ"u/+@4¼endstream +endobj +185 0 obj +335 +endobj +186 0 obj<>>>>>endobj +187 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 +188 0 obj +135 +endobj +189 0 obj<>>>/Annots 51 0 R>>endobj +190 0 obj<>stream +xÚ՛MsÛ6†ïþ<¶‡2Ä'câԙ𤑒»,ӎ:–˜PR2þ÷° ÐÈ@zìÌØ‚W|,¾Ä¾ b™ïW¤éÌ?Òô´a²Yo¯Þ,¯^Ýè†vÍò¾!B·¤‘=o–w¿-W·C3Þ7×ãî0ìûߗÿ^ý¹¼êÚÎ0ì7b¿}zgd¢UͶQ-Å׏ÍÂÒOÞ>=4¯nDCˆý{ö0iÞjþižÅä¶q?>D‘²Xß ¢ÂÀÍ/Úê¿È³çmNÊDi+͉ Ú +à‰¿ºá(£¹’’2±:¶%#ÈÖK¬–1ãˆúëÎ\õÍýf½:lƝ…ŠÞQ‘®%í:ÝòY;7ÀµŠ‘®å -)†Õa„=iñ´? ÛÌDÇù™?¢ŸÊ.îi~ ӏÍðÓâ8iuÂZ5QqŅîÍØ)Î +Š{éì|N@GÔÛq}ܚiú¾SFìp¸õfëÁ ãóbû  UdË[éÍw´ +÷úœU—â¬`ˆ¢ªíSDãfc–Ïb¢C·vrÇ ;Ðß«Ýêa°r»5ˆn«\ۉÂtïx«›”npÖd:&ËÊ&ƒDS¸xJÄ0’Þn¦a}§§çyÂNþÞj1ŽÀÅa:®ÇÉ-´™µŸË_Ž‚ú\wÁâăkʊfã9Êހ$ #i1§uföGÇÛEŽ]z$4Œ#Íf’s¢ëšù%Õû>X< "Õ{^ʊ«AÏ!Î!ÆeîTï7ÇÉÕÀ̒0âjoM=¡š7è‰ýÈ ÙÈš;d6wx}ÆÜ¹p+\ž7wâÊÜs$,ˆ:Ær·9Ž6ŸŠ›‰œ 0La=ùmœ2+øèhëNܸSú± îX§Ñ¬K÷›Ýƒ«Ìu˜SÛò„õ¡6Àà\màLóbmðDBØÌO2Æ£®WF­ø_vUÕגt”GÆî‘ÅPÊËÆŽØI@/eS¤¤˜9Ã`Ên)F(˜/›2r´>å`˜zOžìúÅâ²¾»Å‚`L«°§ƒ Ó¶ l É æ9¤ÆÁÆõ~<™`´’û‹ùKekëɼ'¯ÏÔ"ÖSp ‘¯F&Ø) ¢HYŒ÷‡Ÿ«)S"€™´Ô”Ÿ„†aê·8‡Õ]¬¯rƒCf­PÁap®¦0·×c/C±¦x¢Y§’”ˆa$}¦}vùì†\g…qGÜûãöv˜BAï/-JÒs‘aä x©&yŽÝ ä)ãˆz7ì†iU³Å–c4²X7ˆc |Qk’ç˜Û§†‘´öœQŒU¹yYŒh·†ÓrƒH0ځ\Ŋ„%mAŠ)zaµb‘.[¨ÆvWgNgÊÕØôzë$̧·È¾7Ó0·¤hëÙº#…Î ¥Ø³SgSbçéM!ÕÙLt áþ·MÃñv‚èùÃÆ ô™m›¶5mœfô7÷æ”t¡´]Ãϯ§fŒ-(£zN÷è`Ø4ëRÆö~µ×C5¬°‹u³B8 7ˆ$êø •ˆ–$B‘v1 0NÒ' ¢þ꥔*%0QÐVsɃPpˆß,”6S´½çJ(†.ßqç6wöµ-ŠÉ…H®˜Q$½ ä¢*Ú\QÉó +T{G–¥ åm]'"f~N¯Ú{3i?X8ÅnþB +·™qf;Áîqéô¯ðpVóñqµƒô°×þºòŸ«ÿËWŸendstream +endobj +191 0 obj +1956 +endobj +192 0 obj<>>>/Annots 64 0 R>>endobj +193 0 obj<>stream +xÚ՗ÁŽ›0†ï<…í!Ä66¶¯›6=µÚnèÐ]¥ +¡%DUß¾c{L¤Äí)Éî +ivàƒù=ÿ~eŒPøe¤(íßk›=UÙ|i§¤Z&MÎH©©ÞÞUõ÷]Cº5Ytû¡Ù‡÷Տìc•ќØ=¼|"Šç””…Ì5i‰Ñy‰Áެ,ÿì‚~CæKA³wTÎ-á\¸áS^ÂÝ/Þ%·„âtO¼ æö¥n·û…E® fø_~ÃV&äã?Èç¬ËJÄ ˆQ"ž’I¬,s1Eaaº×c [Ûno™pÁ”º¢,(¨C ÔÒ)ò, º¸d4^uY›èҖhuÎñé@Zìêáq_0Püæíóßý$íì'Œý$‚Ø+–´\ yËMP˜GØ£YNêŽA"DéÐRIÃŽ7Ü„yñ`v“¥qS֙£ݤ¢a^ë„Ý:DM9>H°Ã†·ÁïÎpL%:I–ãðöAÔIR…á­ÓfCš-Faawg¶”D¢p“×Wá‚H"!Â×i»! í£0°{2œJ® nÆz[¸ 2œÛ‚œ:&e8ä(Û%¦‘´èÞK‚—s‡›Û¿ôSÑðvAÔO ”I9ØM1óúqzÉ+C‹ñEÜ‘2Tä'm’NCã¶m&(Ì#l5üÙ¹~bænú‰é‹ÅA@XÄM +ëè,m¾”øqbÏÒøBxYªˆ– Ë‡i䬺õð»î›+> °†öek‚Ã4⪾;Ú¯´Ëë8ì¦ÂO•‡uôyĽ4?»~¸RjœÔçO'Œ´e×·nÈțµ3öÆBèéTãϬ ¸`~W]|{^ÙïÝõvsì×Éçz_oë}ò¼«÷gL(hü™â®®íûšý>ÇÑendstream +endobj +194 0 obj +701 +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<>1<>2<>4<>]>>>>endobj +xref +0 251 +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 +0000002411 00000 n +0000002516 00000 n +0000002621 00000 n +0000002726 00000 n +0000002830 00000 n +0000002935 00000 n +0000003040 00000 n +0000003144 00000 n +0000003249 00000 n +0000003354 00000 n +0000003459 00000 n +0000003563 00000 n +0000003668 00000 n +0000003773 00000 n +0000003878 00000 n +0000003983 00000 n +0000004087 00000 n +0000004192 00000 n +0000004297 00000 n +0000004402 00000 n +0000004507 00000 n +0000004611 00000 n +0000004716 00000 n +0000004821 00000 n +0000004925 00000 n +0000005030 00000 n +0000005135 00000 n +0000005240 00000 n +0000005345 00000 n +0000005450 00000 n +0000005555 00000 n +0000005660 00000 n +0000005765 00000 n +0000005870 00000 n +0000005975 00000 n +0000006080 00000 n +0000006185 00000 n +0000006290 00000 n +0000006394 00000 n +0000006497 00000 n +0000006600 00000 n +0000006904 00000 n +0000007009 00000 n +0000007114 00000 n +0000007218 00000 n +0000007323 00000 n +0000007428 00000 n +0000007532 00000 n +0000007637 00000 n +0000007742 00000 n +0000007846 00000 n +0000007951 00000 n +0000008056 00000 n +0000008160 00000 n +0000008261 00000 n +0000008293 00000 n +0000008325 00000 n +0000009017 00000 n +0000009065 00000 n +0000009113 00000 n +0000009161 00000 n +0000009209 00000 n +0000009257 00000 n +0000009305 00000 n +0000009353 00000 n +0000009401 00000 n +0000009449 00000 n +0000009497 00000 n +0000009545 00000 n +0000009593 00000 n +0000009641 00000 n +0000009689 00000 n +0000009737 00000 n +0000009785 00000 n +0000009833 00000 n +0000009881 00000 n +0000009929 00000 n +0000009977 00000 n +0000010025 00000 n +0000010073 00000 n +0000010121 00000 n +0000010169 00000 n +0000010217 00000 n +0000010265 00000 n +0000010313 00000 n +0000010361 00000 n +0000010409 00000 n +0000010457 00000 n +0000010505 00000 n +0000010553 00000 n +0000010602 00000 n +0000010651 00000 n +0000010700 00000 n +0000010749 00000 n +0000010798 00000 n +0000010847 00000 n +0000010896 00000 n +0000010945 00000 n +0000010994 00000 n +0000011043 00000 n +0000011092 00000 n +0000011141 00000 n +0000011190 00000 n +0000011239 00000 n +0000011288 00000 n +0000011337 00000 n +0000011386 00000 n +0000011435 00000 n +0000011484 00000 n +0000011533 00000 n +0000011582 00000 n +0000011631 00000 n +0000011892 00000 n +0000012044 00000 n +0000018403 00000 n +0000018425 00000 n +0000018520 00000 n +0000018622 00000 n +0000018642 00000 n +0000018782 00000 n +0000019721 00000 n +0000019742 00000 n +0000019855 00000 n +0000020043 00000 n +0000020064 00000 n +0000020204 00000 n +0000020816 00000 n +0000020837 00000 n +0000020950 00000 n +0000021143 00000 n +0000021164 00000 n +0000021295 00000 n +0000021910 00000 n +0000021931 00000 n +0000022044 00000 n +0000022233 00000 n +0000022254 00000 n +0000022385 00000 n +0000023326 00000 n +0000023347 00000 n +0000023478 00000 n +0000023763 00000 n +0000023784 00000 n +0000023924 00000 n +0000024843 00000 n +0000024864 00000 n +0000024995 00000 n +0000025351 00000 n +0000025372 00000 n +0000025512 00000 n +0000026006 00000 n +0000026027 00000 n +0000026158 00000 n +0000026608 00000 n +0000026629 00000 n +0000026769 00000 n +0000027907 00000 n +0000027929 00000 n +0000028069 00000 n +0000028957 00000 n +0000028978 00000 n +0000029118 00000 n +0000030035 00000 n +0000030056 00000 n +0000030196 00000 n +0000030839 00000 n +0000030860 00000 n +0000031000 00000 n +0000031817 00000 n +0000031838 00000 n +0000031978 00000 n +0000032906 00000 n +0000032927 00000 n +0000033067 00000 n +0000033473 00000 n +0000033494 00000 n +0000033607 00000 n +0000033813 00000 n +0000033834 00000 n +0000033988 00000 n +0000036015 00000 n +0000036037 00000 n +0000036191 00000 n +0000036963 00000 n +0000036984 00000 n +0000037039 00000 n +0000037144 00000 n +0000037288 00000 n +0000037394 00000 n +0000037514 00000 n +0000037623 00000 n +0000037772 00000 n +0000037882 00000 n +0000037989 00000 n +0000038143 00000 n +0000038254 00000 n +0000038371 00000 n +0000038487 00000 n +0000038651 00000 n +0000038757 00000 n +0000038876 00000 n +0000038991 00000 n +0000039095 00000 n +0000039251 00000 n +0000039360 00000 n +0000039475 00000 n +0000039587 00000 n +0000039686 00000 n +0000039833 00000 n +0000039930 00000 n +0000040030 00000 n +0000040188 00000 n +0000040328 00000 n +0000040428 00000 n +0000040535 00000 n +0000040685 00000 n +0000040785 00000 n +0000040892 00000 n +0000041040 00000 n +0000041140 00000 n +0000041247 00000 n +0000041397 00000 n +0000041497 00000 n +0000041604 00000 n +0000041750 00000 n +0000041850 00000 n +0000041957 00000 n +0000042108 00000 n +0000042208 00000 n +0000042315 00000 n +0000042463 00000 n +0000042563 00000 n +0000042670 00000 n +0000042820 00000 n +0000042920 00000 n +0000043027 00000 n +0000043159 00000 n +0000043266 00000 n +0000043365 00000 n +0000043483 00000 n +trailer +<> +startxref +43710 +%%EOF diff --git a/doc/cmp.shtml b/doc/cmp.shtml new file mode 100644 index 0000000000..58d55d1dda --- /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.1 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.1: CUPS Configuration Management Plan +
  • CUPS-IDD-1.1: CUPS System Interface Design Description +
  • CUPS-SAM-1.1.x: CUPS Software Administrators Manual +
  • CUPS-SDD-1.1: CUPS Software Design Description +
  • CUPS-SPM-1.1: CUPS Software Programming Manual +
  • CUPS-SSR-1.1: CUPS Software Security Report +
  • CUPS-STP-1.1: CUPS Software Test Plan +
  • CUPS-SUM-1.1.x: CUPS Software Users Manual +
  • CUPS-SVD-1.1.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.1.0
    +
    +
+ +Beta-test releases are indentified by appending the letter B followed by +the build number: + +
    +
    +major.minor.patchbbuild
    +1.1.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.1.0b1    First beta release
    +1.1.0b2    Second beta release
    +1.1.0      First production release
    +1.1.1b1    First beta of 1.1.1
    +1.1.1      Production release of 1.1.1
    +1.1.1b1    First beta of 1.1.1
    +1.1.1      Production release of 1.1.1
    +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.1. 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 904 2000-02-18 17:48:09Z mike $" tag: + +
    +
    +/*
    + * "$Id: cmp.shtml 904 2000-02-18 17:48:09Z mike $"
    + *
    + *   Description of file contents.
    + *
    + *   Copyright 1997-2000 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:
    + *
    + *   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 904 2000-02-18 17:48:09Z mike $" tag. The primary purpose of this is to +mark the end of a source file; if the trailer is missing it is possible +that code has been lost near the end of the file: + +
    +
    +/*
    + * End of "$Id: cmp.shtml 904 2000-02-18 17:48:09Z mike $".
    + */
    +
    +
+ +

Functions

+ +

Naming

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

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

Documentation

+ +Each function shall begin with a comment header describing what the function +does, the possible input limits (if any), and the possible output values +(if any), and any special information needed: + +
    +
    +/*
    + * 'do_this()' - Compute y = this(x).
    + *
    + * Notes: none.
    + */
    +
    +static float     /* O - Inverse power value, 0.0 <= y <= 1.1 */
    +do_this(float x) /* I - Power value (0.0 <= x <= 1.1) */
    +{
    + ...
    + 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..4d01504f46 --- /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 { text-align: left } 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..b452bc4ba2 --- /dev/null +++ b/doc/documentation.html @@ -0,0 +1,73 @@ + + + Documentation - Common UNIX Printing System + + + Easy Software Products Home Page + Do Administration Tasks + Manage Printer Classes Status + On-Line Help + Manage Jobs + Manage Printers + Download the Current CUPS Software + + + + +
+ +
+ +

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-2000 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..4c987e9613 --- /dev/null +++ b/doc/idd.html @@ -0,0 +1,813 @@ + + + +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 + +
+

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..7fd18ccfb1 --- /dev/null +++ b/doc/idd.pdf @@ -0,0 +1,881 @@ +%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[11 0 R +13 0 R +15 0 R +]endobj +17 0 obj<>endobj +18 0 obj<>endobj +19 0 obj<>endobj +20 0 obj<>endobj +21 0 obj[18 0 R +20 0 R +]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[23 0 R +25 0 R +27 0 R +29 0 R +31 0 R +33 0 R +35 0 R +37 0 R +39 0 R +]endobj +41 0 obj<>endobj +42 0 obj<>endobj +43 0 obj<>endobj +44 0 obj<>endobj +45 0 obj[42 0 R +44 0 R +]endobj +46 0 obj<>endobj +47 0 obj<>endobj +48 0 obj[47 0 R +]endobj +49 0 obj<>endobj +50 0 obj<>endobj +51 0 obj[50 0 R +]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[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 +]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<>stream +xÚìÏsë8rÇIŠºÌ‰öŒî´üt§çyšÝ­ÚJñÙfvçÖ$ÁÊ!•S*Ç6•üÿ±~X"H€èn$è5¦jêÙE|ˆÆ·@ƒúÇOßòýÛßò?=å¿ýžÿçÿô,~*ÅOÿÈÛÿù×?þøÛï¿ÿºÏÿü—_Ÿò§§§·kýñõ¥ù÷¯|­ÿöœþº?•ßNå÷SùË©¼œÊ¿žÊ¿üÇ×?òÿýŸÿû¯¯ÿ–ÿíÛ׿ç‡oß¾>ÃKþ=ÿãõ§öcøä²+âõi»Ý>ÜËÛ?¶ß_—Î%^¶wY¤*w÷¯ËäOj¤Üöû¸ē‰é½Ü?–KáÂC]о/ëå!"—x[ÎõœE¼r˜ë‰KåÒ!˜¾rÛg޹^òȾü\ÆÕÊÏ3s=GžJRÎÉõ-òVâÃl\ŽuЄõV¾ÌÂ%²( + ‚B¹ü29×$X,0X –€Åƒ %ƒ/° ¬(ÚMÄåÝoÙ9h6×ÄXo`å\ûhò’LÀõ#𡬼sÕÑ,åÏ\M6A!|…gi,A +Ú Ñ ê£s5Ѭåà‹+›— 9Ä`™ãÅ`ž‹,öD.1?V{àÊàŠRç\uD98æY\‰c®}HÙ8媣`Jé++D91WT蚐°ŒÒË TÔ  LÔ‹Š4ðZåªBÃ2t,OãQ ÔxŒsÆq‰±FãzX¢Æ#F,Ï%£FL×]w÷Ûí—×cy>|ðÛa0IwÅ÷_†ƒüxÂ[‡ÿîŠG’þÅ˃ŸßÝuoœ*=[ í,¸ö~ºªÛk[ça=xì.Bú±àæØ\ìPƒ–.Î$[q¹¸¡==·aMJ&³»XéԜ.K™\¬@ž› É貘ÇUùÑv‡]¶cqeSÙà՛eN¤ܯjؤ½s’  ®|²¡ÅϼJé\Í Xd°˜ÎEùØÍÉÜZ9ƹfÂ"‚­¨\Õ FÈ1ŒȕυEÛи'’ –Y¹0p7ñú¥uZj+Cg‘¼c,Òé« …«rÎX•½ÅÍÁ‘jÄ¥{.B J<—°ÒlKÃ7D=Ì:¸ÎåÛÁÉ %i=•œkˆàBf½ .Ú`Ø`¹Š¹2O”,Á W­Ç’ó ìÍПR4q‡ãÚa…„–¤8®´&1Š«žÙ#3ì€á«aÚz/8 [c¸²0Dƒ¢õ ‚«æfóuXiæ*B J‡íÌ\Y OjOjäªÃê.d‡%F®"°îBú°ÒĕÖ]È'½1p5Á¸dZ“RW\wá¢ÄÄÀ•6ºÐRVŽr‰» 7æw£\u€Ý…[FJG¹*OŠ…²¢d”+ (2$*ÇVå'ÆB ÃRåÓ©¹Z’ Wå“s! q5ÂÀÚÛ=W¢È£­ÔrAˆ"v@;-W¨jàLi­ã¡ªnè¯t\5-4”=Ùí§ž±¿ÿ.Ï´’T¹Æúù=¾aÀ +¢6(®–KH·Kh%ºÖRÕÓbQ®•–ër›®Îa‡Àà ¯Çé¹ £^ >ÜÌіœáµCrí´\MçùÖ 1£$UsÑys¥Z®³í%·NH)}¢æÊ‰Îkœ+ÑsÝ´BPf=ègŒàp‡åz7.×MÛk¼b”¾Tq5ÔÊÀµÑrÝD° ¬•T؇ô¹WŠçZ鹊÷G”Q&ß V<זByW¤çª/ŸÕPÌ1PRWF4C#×NËu¾×úü+ü’QØV +.A5C#WªçڟòáªÕr[¬àª©fhäŠõ\盽§5Rì•K,×êZ[Éu6Ž;êÊ12BªWNZ,×:{—'%WG¤(³ÔgO@• ž«x j®Š5K5†ˆëWC6Ãq®ZÂp ÖbI…Ó5 ÊFÒâ¹Ä»Y¨¹®&EZ,ip-â\9%pžê¹*֚Nè(; +\n£á¬5;c+\ŒôÅq®æ" +®K‰kvª‰@“¤¥pµ¥×qgéB™ÐdcMãº(½Ž«àôWòD@“ë¢ô:®Œ3¾êÙwCÅuQz WÍÛÃÈ0’ ¤h#!r]”^ÃUðûMÏ%s Æð2r•^Õñ6g +ÌÃ’lì¨\g¥Ws5Ì]Œ +㘁´¶ÑR¹ÎJ¯æ½ØER2WÁ^f®“Ò«¹rfæŽÀ8f DQ)ëd݅~^¹e¢IàkSYŽ­\§Öç*®³Ý Fȑ#š ”(ªT?º²k ±ÌukDŸ+?krN7Ä="àVÌµë>š>h¸Þ;а›‚]†Yw¹k6+IlºŠšô¸ Wuáiè†X!dr¸Ñ˜ÄjøCýsȵèÝJ´§•¸rŽlH[âã‹:\…’K\[°'¢@Ø¢C­I¤€]Ÿ«VrU×Ê=öEèà£ÃDïû¯´ùÖṌŸêsí¯#èùVž«áxåÛ-â;^WÈ\OÌɱonn0¾d=äª\ÝT”‚lˆ{ó€¼0ÚT¹WWojò$ ð\{–l lbÕ¹.¶*qeÝKž„‰×ñÒáÊY²Ñ˜×Ó{Šyq—KΈÚ{ÈhzªX¯üPy8Å:F—« »òúh9ÔNþnï5ùÒ*¹Ä€+“,¯ñª è¨Wo'ÍéŧñýGH©\SßËy°†ÇeŽæãvQ°2Ÿ,’+çEQÁse¼(*t.a#‡s5–r*W͍çª>š^¸ +vt6מ͕4™¿peM/\œ¥ùp‰'óg®úÃÉ<–k2ߝÎ-‡͋ó·•Ü:\[æ»uîªßFwÒ²ßmµwpœOm›.Ò,²Î-ï\·u›þà,•\×FÍÕI¿\¹r¶ûRãkT§×ćk¥äjÔûËÛ}©4fÜkbÄኔ\¹z߁¿h£¶W]nj¯‰;×NÁU UPn9Ár­4áËNŕr¸RW6|ŒŽ¹Î«Ëë51áp%C®wшﲫÝÊ-§h®š+Vqõó¡¸g¯r~ô'/ÙÅlp\ëQ®Ó¿^òHjÁZv,¥Šk£tEr<Џ¨ëdÞ7ÛnlÌ\—᯻?"éx@·‰+×à¢Zr—Ûj{‡àꤥÈ]|Ëíé71âp .’7.y<€ +£®[‘"K~­lâŽÃÕ¿(—óM +-áðì8—Ðpz®”ÃÕ¿¨7RNf™*Œj1\·Ùÿj®˜ÃÕ»¨ðTà¹b\Šã|f.ÅEußÁnßÊ#`ÂÃĞk¨Šã|f.ÝÀT5_ŽÜp ×^­óŠã|®áE…ÒÁ&ŒJ[=Ì®9·r‡Çù\Ër¥#Bq­Q\µÚ՚8JqœÁ5¼HËU;â*”ñÆË- é5qxœÁ5¼(S:"×Ã%¢"ÎSÇù0\ƒ‹´\?Œê´áò;ô¼RqœÃ5¸¨[ývGסµœm”MçÃp .Òr?ŒjÕ£YU4ñ"Ú4®þE\-š+Uý6.5MìçCqõ/Òr¹ê^,ÕMìçCqõ/Òríùáa«68Íòþ ‰ýã|(®þEY/Mõʕ;ãŠK W'T•šØ;·ãê]ÄçJ\ñ®óۋ_¾,{lÔMìçÃqõ.Ê;Š-qen¸:ù‡Ýxã¼ì‘ª›Ø;·ãê]4ˆ£*,WÚâæ)­Š«ó~(EO¢Må’/Ú÷#¢âÂùåªÇ¸äã|H.ÅÀn÷X®µW£‹ç¯AeNä’/ªúC%;s Ï\BsŠCqœÉ%_T÷$[DX®W;Ê.é"Ñ Í« ¸—|Q&°üÂeÎ=Üy䒎óa¹ä‹ +E2þW=/WÁá’.ªn»Ê·EÞÙ¹j—t‘è¶²¾Æ6ÓJ\‚Ã%_”ßö¿ž#W铫{œÍ%_T ö+Càª8\òE½H0?qÙL—Q\Ù8WÃá’/’gÆé>®Îq>ès¥”ºór=ŸÞa?bšK©;3×Cÿøšü²¡ÎæuÕ»ꝪHqPJÛ:k®|¾!çéw·§†u\y1Ô׏áŒF~™WsÛìø9QeäÚÉÔ—Pì(É/4¬®KüuòÈȵ™‚ TSë¼;Àz齺 ®u+ M?\™j« ºã “Òdúu\©l)^¸š÷§»nÝî«ko»õʺ ®Dºµ®êºQ(¾unڑÀ[v…².Ÿ«öÉUtv¬÷7ïÒqY·äsM]Õ2¿ú®òöNå“+ª›v^Ȭ©K㊯ۧoƒ8ñƕu—áòžÒߌ§©KãJ®£0qÙÄóҟá¦×VËIÚªº$®Õõq¼=™t®êöÓ5ä$mU]WÚ}tk;.CúáõÏÍÝ[ÙtĪ윑Ò×%qÏ]ÓÆ+W¢ûѧ“T<¶ÔçÊ/ƒô8„wÞ¸2]:ÎeO¹éÀd#©;x®ýåóŽŸ|ðÆuŽš¸1‘†‘¶.‰«¸ÈÐÑÒKo\—½Îûƒ:À:eR¼Ë¹¶.‰ nÙ¯qëë¢Z{þ⇬ã‹õu•\ÃÄÎEu¯G÷叫“Òkmñîm®¾X_—ÂU_ `ü`;®±}½n=é½ÄÕ0‹V[—ÂÕ\~<ºeK®±}ØByŽCš—ƺ.]_ˆ¾ç²Ú_ÚÌÒ|Õ¢¯Kàj/Žùô[\½,Ú¸ôdЍKá:;æ“[öÉÕyіL¡ú’9]] +×Ù1×'ï“ëý ì —J•l:ZÇuvÌõ©¾—1ïë9Sš\ùPÔuñ~ùäËãÿc—‹|¶—‡á¤¦ÒLrTu \ÕÉOnÙ?×­µ«^(u@Õ%póÉ-OÁõ. +‰vЌÕ%póÉ-[raß-Z‹ÁX]—x÷b멸n‰×f®^]×Ù1ŸEr”Ë&ûø*™ìе\cu)\o&˜4·õS/\²{ãb§®.…ëM2âúì-¹JÜú¡k¬.…ëØÓUt}Q7®D²­x”KW—Âçð±‰ËæÜM.ý9Õù±º®ê|²&±çڍO¿6ÝyÈJË5V—ÂUߜº7®ªÛŸûÞmz«Kájn³Q.›sˆçkãï·M­–k¬®!ž—Þ¶%ä]A ®qö¶ ©Ÿ,ŽÕ¥puÞ ë«™«õ¹F꒸r—Õ¹ìf¤jŸk¤.ƒ«´çZãÒmú¡ÿ VÑ×%qƒßxàjô +3àj¸ëQ2\ŸÊ(—Õû7䵘_ÚQ.}]—îý¬n¹:}l \Úº$®úêÓǹ¬²Þè!Ón”ØÔµ*–ïí¹Ê×ëMóU|–ïY +¶X¾ë“kz.ó떗ÉUüÓr•‹ä2/pÉe3aþ䚞Ëjb¹h®õ"¹Ä?-WºH.ólõA¹’ere0ðµü>ŽO®¸ö0ðÅ}Ïn‘\ðA¹ª Z~¯Ù\Åô²×å÷ÐÍULMÞá¾70¸@ªrÃ\ e’ºÒò{9ç*Š+[\Àa +%°ß{ZÀ‘›ì ù=Å¡­´e&=@~¯thG„â‚¥Âèo‘ßoXÀQã¸÷}ô•±mç˜Á8lc®Á9æ½Qæ#/Á9°Üè–ã‚s`™±Åš3‡}€²×ÀXcV@éK`3Ëڬހò9°ÊÜX@=€ÀXa6.@l`3°½9êT˜ËÍ"8á Kèmœ£ Jè„m®gƒú¡€S˜ „A:àª%ô¢©€ìڐ„>G˜ ‡bH}fv_ï\bAB/0Ò -Vè׋‘Ã]‡+_Ž V˜Ȑ+ A,0 +-V裥ÈaÜ媗#ˆ(Â-ôDˆ *âƒ-ôéBäpÝåB} Â(»‚-ôÇ¥€VÏP„#C̾:\ÕB")£œ· Å }ºÙHd.„Ð'‹TæB,Ýċu+_†pd8üƒ"âȇxà B8j¤—Â!Gl#´A `1Û¨«>BðÌØå +h)‚¸xí\Åú,(ÖCéÑg­¡% ÇÜ ýŽhIÂ1ó3?ú•‚+~€áï€d¼s°=z @KŽy>r’s˜y€Õø©bå™a÷H*:sˆH؇–(30Ê&ÐúyÖ9eˆιÈQDs‘ƒ²Ôā9£Ò7”AОQéI+Ò@½t>¥Ï)Mª’ζÚ&HšÔ¡9›!"li¥åڇkˆ´åhél¨vc! »ô™ ±¢g83âžö¼nų¢ †®@žâÌcˆñqCË`3Ĉ9qx@Ë`iˆf(Í4€ó`¦Ÿ¬Tԇ -g€M>kΩj-k€MœdY“½´¬6± +ÈcX]>±rz‹€5D'VFÔ +œéöÔ1GNÀY™8樼A:©ÔgB©œÇ Üϙ.H,8ޏÃtºc wàÊêd†kÍÁ…Tú‰:,c=càÔ4Æ €?R§é°ŒÖÛNÓaә_‚& :C¢Åqí±`»0ºk…äªé0‘qƒph­ ±÷UKó„ªY.´v†èuâ,øV­!zÕzìÓÝ ¹ð†èQ:j ›ÖÖãrfWŠØ ¬OKüñÍPË%¢¹-±±’.h­ ѓ&æV>¬­'BõÊXZ?Þ¹±´°öõ^†˜È,e \<1÷3–½í#×½{&ܸ¥rU¤s©ÍJÉ\"š LdöܹK0‘;¸)82‡i\o\´;¼•Ÿ'–‘P¬.t¬Â^¿¹1p1_uFÃÒÇàd}¡ãNSbé¥ +\EiW°/)áøf08Ô&[õ cœFwžÿf<[l2êR6W›qÀúßtŽ*OôÛø\‹+Š¿S;‹añcq€‰‹ÙaQt_zî¬ñ¹‘‘«ˆ¸ÿ¥ó/9k·6\"â—{”56¼OßYqYtØqœ=šÌñ…Ie˜>˜¹l:ìŒöªÿ짌ý¹K.ê4Li¯ƒ~/ÛÌæqµ¶\Mä¦ÜÝo·Û/¯oåe»}È,?mcÍå¢ÃœSþ#†KȵqÀe'‰³tŽ+¼Û9á +®ÃÌK_8.±´îBrvm¦(ˆ=$W›…ÄupÇU/«»Ð\¬•O_ºäj‚áÚ´.¹‚ÑzÜöžKdKÑxw gÑ q!Øý^ +—XŒÒ¸°DôÖ!‰kvKÄgиš…X!•kæø—°MäšÕ)¹/T®9½3eû‰Ê5c`OJš#sÍ6Ähi/t®™†1±ŒÁ5Ï#îí2¸fbÔ,%=pÍ`sM®ôT9×ÄÚÁÈdr‰<\)´ášRY©Ã\®éÀx™dl.FÚÏ$ŽËšk¢Éóā×þ9椰áòoŠü,M+.ß`ɧv\~UÑ&Yؒ˧ƒ¶Ê¶åòf—ŒoÍEΡö41qÏåcÚb™®î†Ë½,ڟ›pÂÕ +·¶øhß"7\o¶è®Ë’CW+Âé,—\ŽºìþІÆÕŠ'küâª-.¹ø©ÕªGw-qËe‘^Hݞ“‹Kæ–ʇìþ‹ë6øà"æÅÇ[ï¹ðÃõV^qÙññýw/·÷Æuê5ƒAÞm_}ÝÛ'ש۞¶wê~z|õy_ß\çŽ;žpØ>ÜËývûøúêý–“pÍPàÿÿÿârõä +äÿÿMŒK‚0„÷œâ_jb+myØ¥ +&ìê¬!”´UÃí¥&&nf’™ùæ$‚ý… Aô¦˜ãø¢Ûœoe Åä¤é›VB&­&o­Q³SzڊÇÊF@ˆg å8D¦?Y†ý‘s@4Á‘¯óÆ.PëÞ½#¡4º{¶Î~‡ÃÉߏž£†»ÂyŠVá;8Ž#T>´PI+ÍKvÍEp >tEñpendstream +endobj +144 0 obj +6286 +endobj +145 0 obj<>>>endobj +146 0 obj<>stream +xÚ+ä2T0BCc3JÎår +ár á +äHÉHendstream +endobj +147 0 obj +31 +endobj +148 0 obj<>>>>>endobj +149 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 +150 0 obj +836 +endobj +151 0 obj<>>>>>endobj +152 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 +153 0 obj +113 +endobj +154 0 obj<>>>>>endobj +155 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 +156 0 obj +541 +endobj +157 0 obj<>>>>>endobj +158 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 +159 0 obj +118 +endobj +160 0 obj<>>>>>endobj +161 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 +162 0 obj +888 +endobj +163 0 obj<>>>/Annots 16 0 R>>endobj +164 0 obj<>stream +xڝVËRãFÝó7šEL2’e›GU„GŠÅ0dìd‘!‹¶Ô2 +’Ú£nÃ0Cþ=çv˶PlS…¡dK}Î}õ½§õe/¢Å#þOʽ_'{—Š"šdX ‚#š¤½L…zÌ«™;I®>\yšKÊ5™Z +#SšiYçR“ÊÜr-5«r“«ŠêE!õÉþäxé˜À§ß°ý2/¥o)'¿^ÌeMށçŒ|§ñeÓ¿?1=$? +]X Êwò„ÿÍ£gòNý¿¼ÿ#—¶»@|ûöØkèo [ç–,¿YiNç™Ja’;|+Ä Œª™Ûó\¨ÞíþCkúæP6»wŽÀðì/ëCÎä×¹óò܁Óò㠝ä9ÃU–iiÈ{ïQ!«™¹{9¯óʈi!ßÄÖôY‡ê¾FMîDÝ!>ˆb!_uy§jó"ò| ­P‰pÕiåÕA¯ƒ·îgÞ`÷ùL…šåàÓéõ9ý½Í»yÏ,´ÿ ÖÇO»I?x«ßŸiQ‰ú‰®?Ng=ݾ¾Q`ço‚©^ަ[î¡0/ =UÚEÙºwqvԛù(”º§ E€=4m­ñƒ*iU}OÓ'#IÕ)†ø¶'‚û@4Íg¾¬Ò\T·ûô˜£Û 9Ëtã o'BiãëҒ¡"•q†²¼Ö&pÁS4pæÇq0bR0›•&HTõ _F¾,†…±hh˜Å<§2Ë+ܰü5ªö ¢g×p1œ—–u®•À©Q©jI…åâÑéøìêŠ t è¤t¦ÊR"ÕFÔf•=ÍÕ¶ÑmïÐfÄ3"¸\ÚX~!PðJUþ´Õ½5å,éÆÔ£jkw +( ‡ÓVKx…}Ôr^K̀FóµZԉä;§R$¬ÆÛ‚t¹ù´@…P iÓLÙm/$£( +Cøäú1ÁՓ浚բäõ…–]e:¡ƒÅyT)Cz.Î,sF¶( +š WъrCåq K‚›’Ag܌—þӍñ}Z·ÔaÓ)ƒfìbÔýٌ“:ŸºaÕó\jû€Kr‰±­v1Ù ƒç-_"¾|úâ0DsöGà ¤’âx ›»‚ÆÝÓ¸?-Ûó§·½››sTÔµ§ª1Š\šÔB¦( ÒÝSÜ×1!×uLð-DIƒ¨D;ñmðÃCñEÎJ=[•Éæšª©¤‰LþÝ0 ã“VE¶&†ê#‹´lŽöfKVk@IG#Îpº(ÑÍ#Žv¼~¡™wâ[ˆ’úa•Éf|||Ìmµ ßB?„T¶ð¼%¸í»žßÖä˜zÛgc7{‰S„?¡.ü=b;¹+×a³µ½]‚=@£Ø‘¼X¾8i–4÷z®6J¸%‰4…’ʜŽœGgõta¬Ž#T–£õLL%DkMפñ$‹¹¾´ +±ãÉõò½`å“5êR£­VMaìۢʜD¡‚ÛސþZ}vÚHÞ+‡zWY„Ö‹ £’öpqú£¶«³bùßÅ犐Ö`í8u,žÜï¹(vk3¿h—â u^ësSî£&üb0¢Ñ i»‹WG&à‡#¿ÝxÌöÉ?ì‡Ìñ³AÈn;õ¡¿ïý–—$endstream +endobj +165 0 obj +1237 +endobj +166 0 obj<>>>>>endobj +167 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 +168 0 obj +952 +endobj +169 0 obj<>>>>>endobj +170 0 obj<>stream +xÚíXÙnÛ8}ÏWêK Ċ(ÉÛ´ IH‹Ní<(0 %*f#‘.I%ÍßÏå¥ä¤ªmɘyd…xH{xî’ü8¡$‚J’‰û̪“‹åÉÙû9¡)Y°2™Ñ0&ËüeŽCJ²’ÃM˜)Y¼Z~hJ(õÐQ< S]®ù/@Rˆž(i„±†¨Þ§4©”椒ã£óÅåÕ±ü§ É¥ª*.m³h,Ӗ<»&NÞ¨ZæäÛËàEðí•ão¦‰'™­™f™å:lZJïX¶&RÉѪdòö皧ƒ%«¸cÂÕBÜ֚Y¡$Ʌæ™÷œª,ÕÏÉê‘ØzÏʚ‡ÄÅ뗄¼í0Ún6„A¸@kc•Êÿðòù&Q8ºSO÷m»Ëb8+}Ýsn2-6Ž–[y·<‰Â.pûí˧pÆx2 'pô¾ÇPw/v€i2ç :‰ãpú Nh¯™Ç©ç÷æÒ]/*ög'à7g¸†ýûەE­µ»;ãÆý9/„.š°'œd gøã’Ñ>œ'4„ト)ò|Ë V—ö¿Žœ ÑN¹?~+$eDÁƒ£Dô¾(ÓÙN®çYÆÁ0ޘþl´ÒbÃ3QðåÚ_OÚG# °v‘ü|W+’ì‘¬ø6WŒ;qôL°à+7Ëìà“ +zbMÁréàX=zo¬`K$p% Õ óKJÍJwmî¸,ßFÛG4m­×ŸI½#“<ѳçZe¬MáTËpÏxFÃy"z/O¸Ñ™£ôJôNQo¾\C!bayŽîòðºjøËáü£éÖüø#zÿdžxóÖ@‘ë½Ögdã@“Yô=©xµ‚GHŸ`® ¥îÑ;‹íSÛMÒÈ߀k»1ÉêÉ4Ý-ìÿ–û¯Z.{Mۖ‹eŸŽik¡Á8Ž)=§î×à8¡[pœ¸0u혦m#0æZuA©nÍÃÅ¿K¿Š:©â®«[—ü.x|‹~ëI“8:¦ByôP)¼C +€Î›rvî Ó ôkÀ1ΎÒÙˆZU®iÄÈÉZ{Ú±äöAé»S—g¹ª˜èk÷tšnËF ôh$zìõð`¯Çïý’‚ó½%j»Æç°&ÏG¨’%¿ç%f-l‡š!S@õÔüG y”¿îhSùɁ 4‚ÃupJ‚Å£±¼ +P²àŒT›¾±¦ôˆAУ‡j†à½šÅÓV±åã†wû¤$?”8¶ìP ç†k×._wg©Žbî~´º`Fd½2=k¦dBôP™¼O¦¶ñ^hÈ"~žçšÿæ®x -íékŸnŒ¬´byƌuã…;È f8´¢Ë›Ï‹ŽÅVînÙ°ìŽ[‡íiš1"x DˆÝ§Ð$ò|½BWnø€žÖ‘(‰¹IÖí„b8*ø3dµ‡s¹O’z“3Ë{'0º-Ï&rÚVç~=»C³÷³¦Oѱ›‰¦1ë.— 0Ë8V+n%étܑß2jöÌܳdÞȵûù_'ÿR_c^endstream +endobj +171 0 obj +1174 +endobj +172 0 obj<>>>>>endobj +173 0 obj<>stream +xÚ¥XYoã6~ϯø©bY‡Oìbn²GÐt“&Þ炖(‡Dº$•£¿¾CR–ntd‹J"}j¾ùæÿ9‰ ğ1$sH˓ë“Éç)D¬sˆÁæË$XÂ:û壏Š^ ©]ÿ}E³`ŽkñÁ<‰ÌU¬ÜÛMYΨ}Gáûù5ìpðªÜP Z@¥(äBÂÆš4‹CGI›Õ;’ÞS­sûÓú$ B|Çæróâ©y­ù÷wo‘$xCR¸}%+|-‡¶oØŽ“¨ÇIˆ~ÐȌãcâµácÍJ**Ÿ’$ »(©™9(š +ž)CÊ#a*®Ya–Ž‘´šBF•fœh&¸‚/eî?Ð r)Jk·))<:VAÁ”îã5ZaÍëtŽ—n^-ÚºÙ®yµ`ÇëÝðëŒñ­GéocôñŽ¢óH§.4ì$ãÿ%<ƒ´ Jy„ljûÀPN6ÍÞAJ8l(Œ®øÈØ]åù¨‡©Ùò- +tè +tà6εÏiNªBŸÝ©¨/A¦Äx¹œ­ÆÉ™9¢ ’ÚÐRŸãssu[Å!’Úí¸EÛý»Àµãì? Çg¡ aíø%áۊl©çyZII¹vÙ@‡x_ԆúŸNqÿÁŽ[ôPÇ-¸Õñ$tnógÏ×ñK÷nh޵UNSW)šê jß3¸JŸziÁ©~òþÔÈ?%a¼È¼ì`ý[ôPý[p›þ§+S< "­JŒô¾ú'•’…¢¦“´Ú©I&ÒN!Ԗ #š€D{1‰ +ùÜCÃt6e _=PÜ&ŠébîÊÀ')…¼~Á,ÄVM¨yöWá¶yoA˜.[ÈYẈ‘NŸã¶ vÜ¢‡:nÁ­ŽÏæN²_¤¨vž×&v§ ž•½hZv9¾5€“’Õ_œãM¢M_À$ÊL_á^’ÈŠsÓ:è–JN +l6b+IÙ7­L“EÓUûsš抷æJ»®úSþ:z)Ä=&„ß\ó|`wÅAeG%o%nô@±ñÀŵÇÉ2I•B!ٽ̚-Ֆqì1Òf +¡ý”äÙw~èÃðµ†7±]{{*¶åøÂø@ÏXØ1*µ[Ö¯KxJÍą·ü Ͼ_ßbߓè°·r(2yþmÿD]pWhŽÖæ·uÖ¨ŀ›}#™ +çrޗ8m#Óvbp`'†z/†$© çE¹+XÊô™¨úÙI ãJ*½B#ïҞJJôôî²Ôífóʱ‹éÆ-Ý{ˆ½vM6PFVŠŒj¬Ï˜¦8×¾ÓºY½u²‹Ñ÷}¶ÎVHeg€ÚÒÕvr` z KºÍÖß)ÝýV°ú?Bc>² k_×k?Aù±µ9F¬’ôçxš-Þ0;ôÀªæÀmU-ž&®õ5<µ}†uUR +üܲâÂՆ²{4÷‚³cEf* –º ͍ˆÓB¸Ï‰¾¹9Žããºâf|@W|_¡+²Þ¿¿¬;숾ûàû÷~²þá@ãþḍHҌ †@,ûZ²TcOMТ‡“hõ–!Ò¡râÀmœD‹ºâàt‰¬ð?Ÿx.^ú|&¸–¢ðµc€²¬¨Ç¥¶4ó’ŽñW†­Îܗ§m:9Œ2º©¶#8™]F§0z$’›ßÖÊÈë#ŽkñO´ŸQS÷ÏÇÁ2sÅ;ÙõªûšT”¼¥:ôÀèÀm50Šêøy:+å~ŠºWJòÄʪ<>dÁÿ M8Vÿ0ç“Ê©Û(€õ†ï•í1¶)qÛÚ +V2Óm´ð©&ɾAi¡q¸9lL+Ȇ6ÖþŒªT²~cô‹¨)ý±°à¡°Ø¶HÌu0EnÙ¿~/…ëö츚pê2ÀW¸9­Ùá'x“†}ØnlÏ[Äa3“^ýå×sj\óËJ‹%À-×k’`Dû1+À~e‡úé2ÜÇhUûþçÉÎý«“endstream +endobj +174 0 obj +1597 +endobj +175 0 obj<>>>>>endobj +176 0 obj<>stream +xڕXÛnÛF}÷W,ԗ°hÞ$KmÔµ“T@“ª–üP @±"Wò¦$WÙ]ÚV¿¾3;¤(3)#m‰g/sæÌ-ßÏæÃ¿€EcüIò³ß–gcl¹fa{S6žބ-Ó7¼´*çV&<Ëvìñ^ÌÞKÌüO0ø-ž!R‘zo—ßÎ>,Ï|χÝ÷ÛO,Œ½˜/G°_Œ¼1 C/dZ°Å à šâé= àÏ.p{pùøÜ£Á¦ðp$ò™?݊ï¥0vWÇÛÒm||éãgwžû¸ØŠD®¥0`«`9’y™“ÉjÍ~_.çpˆÛË0YàZŸ ƒΆūÆc³53Â2«`KK´ í(+T½eiqèÅiQv“æÐΈ.pEši zOZ8![þÔ©Ð-®®²L=žßˆb×EšÂ•È–ƒ3^¤ —°Tj‘Xù Z¬mµJ„1²ØüÂ^°•`\pî֐G™o3™H›¹ƒ‡‹SÜù^¡;Ê"ƒmð +;ÆÁ(ŽËEÊVð± Ë´NÎd!Îá¾lÐXÖ:v¡Úg·„»Èê<²÷ïqôh<Ý;ú2òünGÚß&G˜Ý kGF#²bÎ7âµi¹:Ss±…Wÿdô3•@ŽP:?ãørÃÖ2ë5>žÂªÔà÷¥BSjðûR«Ôà·SÃ(9ӕ¶-»ÇQpÌZζ€gE™¯@ß ’L‹Ñ­Ø4„¹¡­Dj^¦Š É’ýOèžÀÇ~äWYòv6¿æÉ};?Nò.ï׉Ñ%K‘+½ƒ†M 72— یØ{n1–†"NE¥X¡ûŠ'¯I‰„>‘!c(W)q!ôƒÐWiN‰ÿ€$­”ý•^á¹èbl –*'‡å‰eÒÞ3H‚«Lä½$ŒÃWD ¡OŒ‹˜8ž4Ô60€ ²è1½Æ°Z¦ÜBž!uøF¼+,Ô%¶ðÃ3£H9°  p…p{§bÍË̶åv}7_@1ÆK» E¨ûn6Ÿ3ڟq¼%±^úÁdv<†G7ý7%rƒ+úɧŽþ½§¢4np zk9àâë‹¤Üš. N«:Œ¡ŠŒTä¤Ür—²û(ˆ¦£}ö+Ð'*ÀÇA_Ja¸ƒ´›Ҫܾ†çÌìŒ{¨‹‹ nÀœ¤ Ú„Ái‰ºahål%”>’ –ü“s¡OÌU>–«¢ø’š÷¥È·7R¿$›o»x Îq½;Šua×gt4~¿2úTe8ðQeÀӕ°¥Ì…*ۑù­‰V딐‰S}'H@ÔYá t·•à@ +5# ª|2M3Wy=ôqåO^QÌ}ª@ø˜@ÂiLVܙÚû¬S ͞•o7ê²( uoq$ž 9<ú¶Ñ¼·®…0ɝ0„>‘¿ÀÇÅÇ) b|áu=öDÞȋàÖ²p- ¨`7o†d02S.F=CºŠÊ1ÐC€ÓE޲ÂYÀ}uµ¸žÍ ʞ¬Ç®Už£Øè¥±\Wí€ëT £Ó×7ƒŸ_ß¶Kã=×Ð;íU/ê;}€î ÆÌb¸Êxñ¯Û˜ö5ÍÆ.ç9±â¥å¦ÔÔÁï4ȅÍì$aéÏJu¸~õ£Ç÷‹›…àêÀŠU*ý™øUüÑC§EXus8†°WDÒ»&Ñr‹×êNpP‘û“N%°0ô.Ÿç‘ƒÿÁ›u¹½J·(ÚãQ8ޓÇH ®U©²B<²ojmÌg¾Ãá¶vA;¯ þfà¦Ñ/jÐ/“¦ ì&£_ø]¹xwCýÓ¼²ï÷¾ÝL½»¨^¿oبß-J­Q¯æЕÉB:qayåu›¿ sJ)'¯˜‹ø˜¥QLUâF<ÈDÜÝΎú”JD K-·VËUiž…¬ìëKj“WHӁ_Tæ¤Rf0Â2wúûÆv†—XóD0ˆ¹)X+l†´dX­ \Œ¦Uz?’êÀž¿ÎþMz:endstream +endobj +177 0 obj +1540 +endobj +178 0 obj<>>>>>endobj +179 0 obj<>stream +xڕ“mKÃ0Çß÷S{¥/–5I6Ág +Óv ¶©F¶¤¦øñ½¤™Ê˜:)¤üïî÷Ï]Þ" +1~r<ƒz]”Ñä&J¡lå$lÊÉÊæh®Z}\¾F”¦$Ã(Ü:+Þí¦ZA#úÚÈÎJ­@·`_tF*+ q1×e“k}.·À—>Ï1ý“Å„PìS>#³ æŒ‘ü›¡ԌcäºÓuåP~Ä]Á?YÓSÌêÕ?²&W„º×Fì½Úåãt¹¤z«¡jé˜_¢Þ¬ƒõÜÕ>؁WïwÀ!c·õt1ÔU­Å™ˆaL·‡“pzöep{VlŒÑÕôßà(µRy§™‰3ÜÝæïf¼z0ó¥Þ¶#Î†)/leÅN/ŠNÔ²•bàôp؄Þ)wèêJÁ“€Ñ¼Y‰h£Âê®Íè7©g‡¶fPïiÍäf^/õó—3oár¹(`îÛªp%zù¬ÜoûjÜx‡NRlsp֓Z«Ö©’<ÁÒ^Aiðô}ãŸðendstream +endobj +180 0 obj +418 +endobj +181 0 obj<>>>>>endobj +182 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 +183 0 obj +123 +endobj +184 0 obj<>>>>>endobj +185 0 obj<>stream +xڍ—MoÛ8†ïþƒžœƒR’õ±Àê4]X,ÜÆ¹åBIt­®,j):±ÿýI)±É +rùrøÌÌˑúߌÁ?"ü²ýl¹™ÝOÀ#°ÙâJ°Éç<—+aUáÖe¼¹Ûü6ZY­R×3j—Â׺~Ù¿\ÁZ +%2QZy”¶r/tMð͎ŸÉëVE¬‚ØI YÉñyó°¾_­¡±ÂLTÏT!*tˆœoÙ¡T \¾‡ZH¥ã$”#Ò x2õ-èóÏì¹Ú‰*¶çZúÅFÿâ~Ê. nl³óàáyýK)ޚ¢ú5-Ãþ-&Kxþ¦sRÖðR)Xž±Fui¸°<½g§v¸£ËOÔ\2Ŧ}•ÜEBŸºízõȲÝÙa53UÍy“É"Ř +¡…áAl‘Qc—MÚ $6…5ºGyÛª¯O«(~Dr%u–¸ñPƒ@ƒ¹ÂKOœW¹¾j‡gTü­,*/sr$ìåÎ6¶ †‡l…Ü3¥°HLÿ(K¬æ¶ê]t4±ã™ôÔ©æð´nSÀ‡ƒ,àŸ¿/{äýY—ìrØ.ÏÍæË-s“ñ•c_«^YyÀ3!%oj{°º¦«õ:æVÜÕ:îR~VÄn#žï4‡Z·šçŸ(,`zÀr_[ 'c]¶ÞT¬SwüÈrž{œÕaŸ¢ÚöH^c¢¼RúGÆj–e¡N÷¦x‡»F-Ú°t¡Ç„ãEeY(½E˜ÑÿðͱÖ÷[/z·KlwŸ8 +qъi¸Ñ™ÚL½.a$:*]¸¡1Æ5Ñ ?»KpåhŠ+æNŒðz‰.¿‰èûøt“׊-ï‡y-¥{íáŸ)K‘13“œ+HÉ÷B]Ï—9+ߨ©úr7–@ð^püŽ$|üCý‘€ß–Ù»LÀ‡Š)5,Lj°«áT XqZ"l¼±¤‹g·cT$é=Êˆ©h²h_®ýTù¡.ùqˆÆ‰¾Ӏ¬x(Zèóý88ɐg 'L\2Lj‡qpœ˜×s8P[ýšËD]ð±JƒxúD±âa0?°ÆÀʒéá9ÆæÅÓ­nÅÃl4°V¬~¨ða'ÊñŠ‘xºÕ­x* ¬Ó“~¨L¼ò±›ÇÓ}n´ƒ0öû—’~–´°/ç(a<ÝãF;ˆ²ð­Ã)¸søö ¢é¾6ÚA|WӛsÛ~ý%G@Vµ~ LãQ¿µï¿ÇïJäæ^‚HÏ ‹í·d?fÿýc6“endstream +endobj +186 0 obj +993 +endobj +187 0 obj<>>>/Annots 21 0 R>>endobj +188 0 obj<>stream +xÚ­XMoÛ8½çW zJJ©O/ÐCš&‹M·›x÷Ô -Ñ YÒRT÷×lY–ŠIm>ÍÌ{3õßø‘þ—n/>//>Þ@,×@‚…K J|7evIü÷˟¾çê§ôgø)+ ’¢PÐT J É+ @é¯5úfyá¹:ÙÿzøíFÚn£]cŽz.Éáq G¸hÁ$ +ܸ‡ÆhÛ#ߍLLÁÛ1úÑkÌŒ1ŒÑîÜ ø|Œï&¦p*Æg&[åjñëíøüm΍πGâûx»@ˆÎ¸aÒF¸>\ÿóý¾—µzL¥¨܊œëˆ%âC#ûÀ¼Fp düY¤ÜÉxŋŒ#Ç«¬\ñ>¶’åF²­}ƅåÓÑjΊMÃ6Ä©¤¥SŒ" (VɈ#=û)·‘YÐÖqÆk´»âÖ(tuÖ(ñ7ñIèzÓøb >¡GªœâûÄÁQüŸO$’›N÷VړÄ~íR÷À×\ò"åpϊ†å0ÉBfp“ %ÊB§`P·hüÒÕß;ÆÇ¾ÎtqÜßÝ߀ÚUÖ¥„ñÊ5ØZõÚZ½dU•‹”iŸ‹ÌM›ªv*|®6ÏW¶õÝßNàY–b|>°Zq9c[H œØ-BlµX§ž˜‚´,Ã:eGÛEƒ¬ ÈDª 1¹3‚C|Ì!:fE6íFîŒzœ¥OÖb»²2m¶6û°æ½¨›7 vP%YQc>[sÇS Ö²Ük½°uD‚ðp÷½ÖÖN‚ÄU´zà™KelµÑø 86 ÔôNäµeÊm×»T\õó+¾E /B=¡ºë²‘°Ú)ì»;<dYˆ_¦R॔Ùཆ4"¡ðãòÝ{Tï~¼7ú­ÄÆÁÀvp&Ó'¡xªi[÷ Þk„>š¡Úˆzd‘\(•óQ;¶¾H¡#/×}! ‘ç:3f¡À˜Ÿ¹‰yà¿áòƒÉ±ÀY¦ ¡ÆÿÕUYÔ¢Õ Ó¡=‹bƒªHŽÚë¤kƒ`LX§ÚLý‚Jã´lX 5œgKSŒ8¾ÒÄ! 2Âr‰ôo#Ipâ˜KÒ`g“4ès$É"jo? êÐ0<¦ùW£ªFýNžd¡‡Œy<-v.O‹>˯æEÃy.Žy^eÏ g·/;d‘Ézú0¦Ý”èÍNC¼’»Õ}z<%ØHí +8x÷¬J<µßh\$öf7.‹­ŠAŸU%lyxàø£ª˜Z?‘ä|Ӈ'0 ‰GÃàÑ¿«Þ2°uwªtù³\™¹‡ôǑ5W“Á8PHÓ¹XÄ]*bE›J…ZU¦°6lqw‰èn¥[*-»iŽÛl$Y E©gHÀ¿•°g¤3HÃ)â¼xnÛ­¯£šÀ@mLSX+€[àN€Ð³ôœ ½öºQÓ%˜6 +¶b@«½‰FL»>зú0Ý·á)lÛ†é¾ Àf€Hº×QæýJL½ýµê0PâT$6 †#Ç>â´Ï´/‡PçöÍËÔ;Tàï‹ÿ&'õ_endstream +endobj +189 0 obj +1499 +endobj +190 0 obj<>>>>>endobj +191 0 obj<>stream +xڍ˜ËrÛ8E÷þ +,gªB…øÒb6±ã‰S±ã‰”Êš– Š`@ÒNòõi ©‡!>P®’%â.»o7øãŠ’þ(Iá Yí¯Þ-¯ÞÞF„R²Üò'IFgY®ÿbärÝ6D«¢ ù¦š|WO/¿_! (Ÿ1CñKª¡Î èªò­0ÔûåU8 aZǏ/ÿ’(›¥$‰æ³ˆD \~'D ²èaçÑlÞ±4ŒÍ#0 C³DK3žÍÂ3´ˆ©¹/qÖ,eKc3K;‹Ð¼i«Bü4Çðnö`ë{Ô²lH-Ëm!‚Z®Åځ¡µjŸÎ¡ hbæhîÎ9ÜmTËâ¬ÆàNK£'ú¨Ax‚4 XÆ_kðáÛQ«¢m¤*%>(-«²Éá9—kò,t#WðCO ²š:¨„d¹ÚÍÆ%ˆç1LÅޜ…ð1&²81%@%8Ñ bȃÄJE›Ï_Kp·Ï·ð¨ß©¶\ÛÿnHܪVÃR±º&[ù iv‚bÓ¼!OªiÔþ Ñr»ƒŸF«FUnrUª–F³š¨=Ùd œ‹7…/?š•‚ûÔ*&ìL“„¬o !=H1Ü}" :tWÖ ‹@Çp2êF‘R5°B«T¹ÎþbøÚÕʤ×Ý0:" ›{ç²ÞÒXzPaŽñ0iÒ×Ò|TÛ!IÀ†·6ê‡ùxë|v# á`¬pvë¬}XÌ(™¿6ˈ簼11‘ÅŽÁ(&Ò(æ‰>ˆÅ1J™œÒ×R~¹I—÷k¬8ޤKUCDÖ –®›Q¿˜,½¤GÔw6©G¯fDýp h á´¦á©zhž +ᥦ|ÞBN¨ê8à}®ÁkGQ»6ãfhpÊPƾäÞx—§]ñìF“¦¬¯é#=dú<Å0b`VŒ» .Û¼¸X³û½jo™âÙFöb-ó>ŸºïÇFôˆEpÒ£õõ(¤‡<ŠG]ä <Š9uo&þØÕ(G”»²‚†¯.@”C# B¡#˅,ñ}ü–õ~ü–|üŒÂUìrÁG8íYî7a¼ÀY¬!/vȄøVçûš@ƒÏÖÚæ6×S½§ñ!ͧmYïE[zpÑÐëašsHsîô»÷Rk¥mß:ö"•>döEÀ»À° ,cÞåYßPGz(ÔY’vå˜' ƒãvb›7òYL!KÓñž­ó¢AqÆGt°;O,뭃¥uàQ—˜`ä˜àC»¿V•®ïS“ÕÌ4ûÉÌn'ã%Ç|: áV3Yp„„NÁ2ï¼@Ö7/Ê ýæEÞ9Þ÷YKۜç; ­€ǽ®ÛUœFÉ +zzpŠ`U¨Õÿ/²}ýŲÕ%âme6°z){ŒW>¿à°È49FÛd¬oôPAãc´ãƎã~n¨"·ùJ|­zTÆa²ñ>)¨ƒ´Õ„vãï—qÈúfÒCGµ +Ä`¿±ã;ð ò·Û¸~“ëfgû¬B”[øêÙWQ¨¡g.!ë›KHåÍ5SISYà~Ílt_¬¬ÔÞöÉÁw++U˜}ßë+ b7ù~Ü¢¾O܃oWÒ.æ0–Ä1–¥Î-^d³Ú ûÊj——Û  5‘Xn!V ´’æˆÙUˆ}ÕüêÑèÚûđíHæ%õ•ÌÂÍ( +&‘:&±l÷O…˜4añ,Ên/û²ƒ¯kû"ö…SÕç˜0Édñ9åK2]{N钜¥ËÛÛ¬«‘4N!†Rf×sýõqÝ”ke7¢–ÛÒü[iYŠP€§Ý9ÜÆž-z³° ¹í^D©yù€¥;îøïêÑ~D endstream +endobj +192 0 obj +1429 +endobj +193 0 obj<>>>/Annots 40 0 R>>endobj +194 0 obj<>stream +xÚŘÑn£8†ïû¾ìH…Á؀©´ÛÌtfԉ¶›fµª47”8 ;X Íôí÷M‚aV#U­€˜ÏÆç÷ϱͿg”8ðG óñ?ޞ]-ÏÞ_sB)Y®‰ë0›_P[å꜒ßÈ"¯£Zù,3RD²"» \®žŠTþH²ÇwËÎ>.Ïہ†÷‡Å'…?ð )îÛ.q]8”’ܝ`Cn‡ KÏæFØu줢]&l§GC4ÅçúÔö1¸ <ì¥ê…ƒ…ñSQý¬ê ëªrUFòµ +”$[u„°“2­FõO8:'1!,ÒÁoÑÁ‡âx3wJxßç«Ñð;9Ÿ“ûû{rss\Dž:EeQùªŽmÛX OPOPNº¾AhG´o|³ÐŠÕ!›àFhEk¡;ºš‡L¿]Üq,î°¡ïŠ(–'„Þm’ZžPsñéê„^PúûA1CéÓ(þŽåVï‡0X¸¥÷óÙA©¯Ù›ƒâ@ÇÅŠoŽ››âxk)æ‡íHQ†—¦¡Ò°ÍHë±Ò¸«Þóx;X+85XÛ¢”U•äÙÛ̈́ ŽSS©f§& M% ƸN¥Ü§'fŠE¾›åOYý†Ú¸brBÕìdm=¨ 庋œº wR›k)Wo( $ª©«KÍN–FÑCҸТN9Ôi“ÒÜÕ²x;i\!&¯-5;UMŸ~r¡_§åF’ù—ùGRÛ¬ó’Ìþº½#‹¨ªeIÖI +[ä":<§ ï<*Š4‰£RÑûçle£V©ê¼âÜÖ¿A©CNæÍ’Û^û¬¹Æ½® +¨ëk‘Ð]‰ „¢L2xµ’…„y=«uICԛ¨Vì{" h ¿«§¤ŽR‰£XCÄ+YÕI¦úß6S¼´탉ãó­u;ûzAà¼XÂYÖ1L÷dPµÝÏJ¶û ½|ò{šÉšÜb§aŸyÇy:¨vu¸vĈËäH/Juž¦ù±Åõ¬ºÔMÇíÇôÔ¾õo®#ÓÆ†Ìç :¾…}8R]§¯,Û²^~hX˜Ùîþ–P—›á4tÃ3Ò°%®ëB˜ºít»-öâ Т§NAG_©]>’nø™O‚fº„„mƒï]LðZ¸$³8_a1,–ɲŒ²ªÈK5›äõ¨ÖV`‹îu™`ÿÔµÁ «†ÛÀv÷[;àÐÚÁDw@kÝ€ö~ 0Ðt0ғv ú:ÐÐãvð›é¨±ƒ?n‡y¾’©òÜF@ÄÕ/÷m¼ ® ^hX5Ö¶»^ f¸ÍCÜ3è@çx#mwЁZþè/Б¶{€ö™g¤;è§“==î.ôp6Î .ÉY%ù”G°1ƹ/ÊF&¦_jØ8­iÔµÁ4 «La`»û0Tl¤á€¦Áî›è@Óð6€!Óð.B× lj¢{š&4·Ý€føÙÑDwÎl¾Úú Ó€3›gV°àÌ6B÷ 93÷„Ár)ÜÓވ‚=hXb›éØ>æÞ÷ ‡Í¿ßÑã¯óz/¸„¥%®£T¯6q•vW—Oqý+Ý|­ +ºŒ½_ݵìÏ¿ž¢é +¦H˜>„êŽZ䪶ÖQ,ÛDðA­‹ºù.aQՇ÷Ú՟1},d°˜zkuzÝïûŸgÿ«Ãéendstream +endobj +195 0 obj +1589 +endobj +196 0 obj<>>>/Annots 45 0 R>>endobj +197 0 obj<>stream +xÚÝWێâF}ç+Jû4+=¶+å`„4‰xöi¤UÝ†ÎÚÝÞv3,ùúTû†1÷d#E’ øÔé®:ÕUåï-,üØÐs í‚·>{­‡‰¶ ^NßtÀíwÌ>xÁÝ«ãöà£÷Gkìµ,ÓBC}±õeþ„榅Ø6bcp³]üˆ`qÝ˜Ý +Ýï]@×1ØÎïçàuâÝAæÅ| øs‰¿†ˆÁ±m³s_G ¾mU‘:¯!ß³M·†ÿ|}¹„‡I§Ð¬íî›OÁ麃Oð+IƗðFՆRϳÀt6ƒ™Jø"Jµ¶;j« 6Ñp\ô½…—ùbªV"Nb +¡KáK’fƳ³y|™-  !ã4µÒQ$6z;ô‡¢¦U±)c-Ùz?3Êüijvě’4~™¦/§ðŒ‡âZl,$=npÄˀ¾3Ÿ^v²q6ª·Yabœ)†n«…Öý€ìN%.)í*‰rp,n÷PÍÀ a†}-dÕI³ÈËðȰ!椾d‰‚˜l‹&”%”n^zcXÜàM[¦!.òN"#3®Òð+[ ú¸‰w Jo»^j $%J—xŒV)N%óa&RµÈÙó¸8V;Ù!¾áüÞCá> ²Æ.ٟy»dñF£ÒCrÄb—7U”¶óˆ*Ú,*£ñóØ7ëJçB] r®ÃÒ"i,ÞÏW”sMùšâq¢îüýâ~[½ifÑh??-‘B±æÁ•Iq6ñÎ'F7›õE÷†ƒÇçáb1®fƒî³_°Ü<”†ÿÉ ôæŸ ýâ·Ýíé÷·›ûšMýÓªxâˆÎ–\ß²:W´0#72zŽõ&ûNO¿÷dLv¯xQý½õH—Gîendstream +endobj +198 0 obj +1004 +endobj +199 0 obj<>>>/Annots 48 0 R>>endobj +200 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 +201 0 obj +927 +endobj +202 0 obj<>>>/Annots 51 0 R>>endobj +203 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 +206 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 +207 0 obj +137 +endobj +208 0 obj<>>>>>endobj +209 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 +210 0 obj +421 +endobj +211 0 obj<>>>>>endobj +212 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 +213 0 obj +310 +endobj +214 0 obj<>>>>>endobj +215 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 +216 0 obj +424 +endobj +217 0 obj<>>>>>endobj +218 0 obj<>stream +xڝ’ÏRÂ0Æï}Š=ꡕ–RëQ U˜vˆÓø±„ ‰¦ÿ<½IQœ!¢ÓL»Ùßæûv_¼zæ ¡ŸØS¯¼!ö.òÂð†’4RÀó³[ä£QqŽŸL>Þçý( â.O_9ÕÚG¤^5¤˜ÐTÁH +­$‡‚ˆfMº%|wð¦Åô-¦òáü$ÃùqøÄ¢Ր‰† J »LÚ%äRÕN.B'`»ÇZ&RRËZr±šýF$šIA8Tšˆ¹1£…™jˆ`]ÂÁ.Ðø8»0Êw¶Ž ]9Qå¤Ì޳Ê5×lEçŒÀ΄’0Ù[ýh¦å²Ô¹iȌù/k…\Š‘luU+ö¬÷ºiÛÜ>Våð8µ¢jcH%m[ûØ!—õÒÁÂ9v¬VlĄ̃sÆ)`ED»0ìÃ5J¿êÒAÀ ½2S9ºGÕÖü©©ÆñSŸ.Íuÿ2êٚ(¶Á¸ß"è×påѡÞm"Ãޝ÷ Ë%¥endstream +endobj +219 0 obj +372 +endobj +220 0 obj<>>>/Annots 94 0 R>>endobj +221 0 obj<>stream +xÚ͜Ks7€ïúsÜB^Ì!Y¢\vÙk­ÈÜRåb¨‘Ì„-IÙñ¿_<º±ÐmH§Ê܍Ï3ݍFã1ùï«jû«4¯DSÍWg¯§g¯®ÚŠ×Õô®bª±ªÑ²šÞþk:û}ÙU›»êb³Þwëýî§égãéY=ª-ÃýÆÜo7o\£j„™jU™‡Ÿ—ÕÄÑêÛûêՕªsÿžëÖXUû¯±êY|D®*ÿGÂR L曇΁¸²pû£“ÿŞ}oûRÖ@œû⊏4àÅ_]I0£õdŕ8;Ž2–$•í˜-)ä€z{k½¾¸[ÌgûÅfí JÛ'dגíêv${Ûù¼¨³«G2XŒ—,£­aN#iòm·ïV™@Žý­ùëCÙˑöñK·ý²è¾:œd£ö$ _°¸jkM°xhD‹«VÛ¶·¸(X9¬vñœ€@¨ËÍüqeÃôyEX ”Öº €˜˜Û¿;²ÙY6íª¦íÓnø¹Ï1É*]‡ôÈóIavhRš—"妻ë¶ÝzÞùA¶§•žø% +A«š˜bCã©«”y‘S, ·¶Iˆ ÒůדŒKbo¸ªvN¡, GBŸ¬›æ¸n)Y]Š˜œCƒ¤ +?L½­KÉ9¦¶Y%á€H÷Ÿ»mÆØ±»ËÍ.'0 #€ŸÄùTÁ´ýR…ÿù©TÁü…D(ûæ*e©g¼µUãv=[>"ÝW•MɈ#ìn†9GŸ\ÆQ…h¯EH­>&}ãÉSːcE9DZ5=>‰{$]|žmgó}.ö •…®clMÄMºÜ\KúºQäfل„ +»Z,ƒCy}C¨àDÙÖq¢˜²dËB"Ŕ…k÷&å€HïgëûÇÙ}—õ\Óã¯û‡ì=7"O֛›µ'RNbt­ã<Äèڄ„,Š%%rŒ²þI8 ҇·ƙì{»êÔÍÆ äÀ¢oN+e=ou͝ÕéëåÖ-¬CÞPÛ÷kT¨•­ÕsyŠtv•·¢@°ÕbՍöߺS™TK&R '. b"Õˆ— WáñòhžùfýśGÙ8MaÐ +§»Ð ƒVœädiЇÕõr@]ovûÉ|»xÈ®kŠÎ5 ¹]¬³ó&EX ]¾‹xÙíü#Ú=%˜UÅkŸÁ((˜ÁÊþÉÓÆ—a†óìdlp…3¥,§ 1®{n2:–_KÑî¦Íf"kü×¾[﬛v"a8ç·Î) Q“§Ûor}­ÇÿŽ +Àº¾¾|F»[˜ @ÂPA}Wü¿ƒ§”3#½oœaŸ&zUÊÀiÝxH8 Òdþ¹»}\f ㈰.n¼-)伨¬ï÷ÛYa€Ž eÇ@BE>("x}„è¢5±N8Ѕ·OpZq #‰IW+%(l¾œívÝÎͅw§0š‚…¬ƒû2!4ˆ…Lƒö)• Èq;˜:Ü£æ»ÛÞ6Ò-ª\w–ì£YXÇú—ð bͱTP¹ +Ÿtv…w¢(ì!Lì$„äQ÷0YÝ¸R…•‹‘ðó7ºڧ ™ßºA˜r' + -HâfÀüæ ø\[§4n°}#Om54b…ÝJ!x<؍§öo„/øœŠû7HdµÓM ÔùÃÃd3ÿ3»ïB.C¸É$!¢ ¯·›ýf¾Y: p.:®3ŠÆg­O}Á.¾+Áë`ðÒ® Rü¶yB âÀ9`KAŒ›“RÒëíæën±¾Ï¥àê W’%8P¼ÄiGÚ-zªVqÝÄS5œÒËâf r‚=)Ä@:Ä[€r{ú:e¼ù%$„-6E¢Bg¾¸v³×1“yÇñ–\3è8ލY\°#Ǜ6á€X|ò…(Æ\Ÿ„r`ÝÌvùe:`$8TqIN;…]Ò¢ë4¹åÄunÈ⺠9Á¸zxË¡'â:@1;4tÊ +rdÝ̾æfµØ;l°” +‹ %w õ+¬xyCnK„ñ\£±”hJžŽi‡)œÈå + B×)äË[Gf¸ˆp3œ´#*¢‚~¢09^QÎ +Û[\‰¸¦ ¸fá +\S\ó"‡1W9' {ԛü™[ìëÖ>.ö*„ƒëînö¸ÌáÀm?ºèKq ¸ €Â†…¬l5Ãz â–(xäo>Á|z3ž~º_ÿú~ú<™²,YÔC²U@î/ éh1M3|g«€˜ú/Y×췟BéüCñÉ +{)\´q%$ªdÅSSÜ+@¸ž¢‚a‡D²²@a°_žÛ3% \ڝT¦Ä €D ×7oÿ=ßdfŠ[ù‰b„ÿ’Cµ%˜³øÕR” +A!ÿþ6|1Rx·×CƒD +×X­5Å=$1æŽ,Èv~{›‹”Ø»ÏA”… ++Ÿ¬„õeãçù +„@9¿¼Ä@É8—Ð\œÈ!€IP‚¹‹) +åãD`òx%A1PX¸Ð|ÉÈ}&(LŽú©J–HnIÊSÈñjT·ìö]~ÑË#®©]I@q¨¼r¬ÄÊWñƒçCB¬\Žß§ã…­k>Ä£àsó éì¦+3t +*ʇ‹üÛáR ’ºŽ{ø¡A‚¤f}š[BÎý¼CQ Ø!ó²ÂH§,TØE8(fòÆ­…R (L;ïÏ'“qnÖ!4—MЍ +ÀÎfAP‚ÕÃ÷F@ùðPý¬óÅr)RÜÑs_÷†FŒfúú¤)Ä r´€@nœsz’Týó%s |Œd`¤»õ¢4ßÁ¤B™k|tdJ8–ªôjš‹ ÒqÛ)FiÄø˜h^2& 2 +§8L‹X»†‰ -cíªK±¤0 $(K¼MqÈDÓãüO‚C¼(Yp]Ù¡˜â@A&µ+L3¥H!8 7rGY®]Iç°Úb(HR»ê—Š˜bœ4u¬\CƒÄIÃbåjJq¤°Ÿ— @°óù¼+ïéö8¿îKp¨¼w›ß³a"Èk†R2¥)Y˜K..Æ×ÓOï>¾ž”ê֞ì+˄Œ +ìÀºQ¡nMQ ÀHÝj^²n-…‰Ô±n &Òĺµ-… ˜¯ÁÈvÓýÑÍ÷ù­¬&⤻B›àPx…0!ýÝÔÐLR´ÞŒß/ЁBh.͐ +¦X±ÒÎ+ÒÁ(P0¤bm_n!|P¬¸`ê‹çÐ"Á"T¬_YÛmŽÝ]e⾄M`¨¼ÂEøØ½Ÿ{(ì€m¹ˆ·Å +=𠍹ˆqSwG¡¨ ’ºxrØÖ\¤¹µZT±.¦-J×ÃÇDEêâó>[ýÐN&Øü–=ã,E‡Fܲg"M6쑢Ý:&¡€ØsÞ/֙ò†ôu±o\8QÈùakhÒå‡ó€† +!¸fÝ*{ÃM&4óÝ[¢Â)\F(z¼&W™Cƒx¼6Xٚ’ρc«¯:倨à6Û/ÙÕ$y(Æ}F¦4##ëC·Ûe¿¡ýCžÐP€¯—›ùŸù,Ep-š úÖÄõê>îamö֕aý¥+Þ¾seà†¦Ê_¹2xÔZƒ¢¼¬Œˆý\¡0`!@~ÎÕâ¿W¡ Èåbkë ÍvÎRéÓü¼—¾Œ†ë’®vW䲤ûfÚ/ rÙûøa/’þAèo–;¾¶ß|ø¶§q朵˜(ÝÀ™ÎÒJöÌ'Š.Qžgo¸õ;‚¢1ßy!`¦Ývíõi~G^27áâŒ?Ú6ƒ{3°ÍÞMë;†Ï\LB RäÌ·›õ·Þ¡§e®`¨ø‚uÿ¿{1=Ê­š–Þ#é/†V¶b]ܯ+òŒVÜp?ëpnVüÏÙÿ©dendstream +endobj +222 0 obj +3029 +endobj +223 0 obj<>>>>>endobj +224 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS045×3S072PIÑp VðÌ+I-JKLNUpI-ÎLÏQÉE™%™ùyš!Y\º-ºP=™™ A×®@. Àýendstream +endobj +225 0 obj +98 +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<>1<>2<>4<>]>>>>endobj +xref +0 271 +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 +0000002905 00000 n +0000002943 00000 n +0000003044 00000 n +0000003129 00000 n +0000003230 00000 n +0000003315 00000 n +0000003346 00000 n +0000003412 00000 n +0000003495 00000 n +0000003561 00000 n +0000003645 00000 n +0000003711 00000 n +0000003793 00000 n +0000003859 00000 n +0000003942 00000 n +0000004008 00000 n +0000004089 00000 n +0000004155 00000 n +0000004237 00000 n +0000004303 00000 n +0000004384 00000 n +0000004450 00000 n +0000004532 00000 n +0000004598 00000 n +0000004681 00000 n +0000004761 00000 n +0000004827 00000 n +0000004912 00000 n +0000004978 00000 n +0000005063 00000 n +0000005094 00000 n +0000005160 00000 n +0000005245 00000 n +0000005269 00000 n +0000005325 00000 n +0000005409 00000 n +0000005433 00000 n +0000005537 00000 n +0000005642 00000 n +0000005747 00000 n +0000005852 00000 n +0000005956 00000 n +0000006061 00000 n +0000006166 00000 n +0000006270 00000 n +0000006375 00000 n +0000006480 00000 n +0000006585 00000 n +0000006690 00000 n +0000006795 00000 n +0000006900 00000 n +0000007005 00000 n +0000007110 00000 n +0000007215 00000 n +0000007320 00000 n +0000007425 00000 n +0000007529 00000 n +0000007634 00000 n +0000007739 00000 n +0000007844 00000 n +0000007949 00000 n +0000008054 00000 n +0000008159 00000 n +0000008264 00000 n +0000008369 00000 n +0000008474 00000 n +0000008579 00000 n +0000008684 00000 n +0000008789 00000 n +0000008894 00000 n +0000008999 00000 n +0000009104 00000 n +0000009209 00000 n +0000009314 00000 n +0000009419 00000 n +0000009523 00000 n +0000009626 00000 n +0000009729 00000 n +0000009832 00000 n +0000010143 00000 n +0000010175 00000 n +0000010207 00000 n +0000010798 00000 n +0000010846 00000 n +0000010894 00000 n +0000010943 00000 n +0000010992 00000 n +0000011041 00000 n +0000011090 00000 n +0000011139 00000 n +0000011188 00000 n +0000011237 00000 n +0000011286 00000 n +0000011335 00000 n +0000011384 00000 n +0000011433 00000 n +0000011482 00000 n +0000011531 00000 n +0000011580 00000 n +0000011629 00000 n +0000011678 00000 n +0000011727 00000 n +0000011776 00000 n +0000011825 00000 n +0000011874 00000 n +0000011923 00000 n +0000011972 00000 n +0000012021 00000 n +0000012070 00000 n +0000012119 00000 n +0000012168 00000 n +0000012217 00000 n +0000012266 00000 n +0000012315 00000 n +0000012364 00000 n +0000012413 00000 n +0000012462 00000 n +0000012511 00000 n +0000012560 00000 n +0000012609 00000 n +0000012658 00000 n +0000012707 00000 n +0000012756 00000 n +0000012805 00000 n +0000012854 00000 n +0000012903 00000 n +0000013196 00000 n +0000013348 00000 n +0000019705 00000 n +0000019727 00000 n +0000019822 00000 n +0000019924 00000 n +0000019944 00000 n +0000020084 00000 n +0000020991 00000 n +0000021012 00000 n +0000021125 00000 n +0000021309 00000 n +0000021330 00000 n +0000021470 00000 n +0000022082 00000 n +0000022103 00000 n +0000022216 00000 n +0000022405 00000 n +0000022426 00000 n +0000022566 00000 n +0000023525 00000 n +0000023546 00000 n +0000023700 00000 n +0000025008 00000 n +0000025030 00000 n +0000025179 00000 n +0000026202 00000 n +0000026223 00000 n +0000026363 00000 n +0000027608 00000 n +0000027630 00000 n +0000027752 00000 n +0000029420 00000 n +0000029442 00000 n +0000029582 00000 n +0000031193 00000 n +0000031215 00000 n +0000031337 00000 n +0000031826 00000 n +0000031847 00000 n +0000031960 00000 n +0000032154 00000 n +0000032175 00000 n +0000032333 00000 n +0000033397 00000 n +0000033418 00000 n +0000033581 00000 n +0000035151 00000 n +0000035173 00000 n +0000035295 00000 n +0000036795 00000 n +0000036817 00000 n +0000036980 00000 n +0000038640 00000 n +0000038662 00000 n +0000038825 00000 n +0000039900 00000 n +0000039922 00000 n +0000040076 00000 n +0000041074 00000 n +0000041095 00000 n +0000041240 00000 n +0000041632 00000 n +0000041653 00000 n +0000041766 00000 n +0000041974 00000 n +0000041995 00000 n +0000042144 00000 n +0000042636 00000 n +0000042657 00000 n +0000042797 00000 n +0000043178 00000 n +0000043199 00000 n +0000043339 00000 n +0000043834 00000 n +0000043855 00000 n +0000043986 00000 n +0000044429 00000 n +0000044450 00000 n +0000044604 00000 n +0000047704 00000 n +0000047726 00000 n +0000047839 00000 n +0000048008 00000 n +0000048028 00000 n +0000048083 00000 n +0000048188 00000 n +0000048332 00000 n +0000048438 00000 n +0000048558 00000 n +0000048667 00000 n +0000048816 00000 n +0000048926 00000 n +0000049033 00000 n +0000049191 00000 n +0000049302 00000 n +0000049421 00000 n +0000049572 00000 n +0000049676 00000 n +0000049780 00000 n +0000049957 00000 n +0000050066 00000 n +0000050223 00000 n +0000050329 00000 n +0000050446 00000 n +0000050553 00000 n +0000050711 00000 n +0000050821 00000 n +0000050948 00000 n +0000051073 00000 n +0000051194 00000 n +0000051313 00000 n +0000051481 00000 n +0000051628 00000 n +0000051778 00000 n +0000051926 00000 n +0000052080 00000 n +0000052228 00000 n +0000052372 00000 n +0000052522 00000 n +0000052670 00000 n +0000052818 00000 n +0000052966 00000 n +0000053099 00000 n +0000053220 00000 n +0000053338 00000 n +0000053472 00000 n +0000053569 00000 n +0000053669 00000 n +trailer +<> +startxref +53896 +%%EOF diff --git a/doc/idd.shtml b/doc/idd.shtml new file mode 100644 index 0000000000..ca48eccc03 --- /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.1. + +

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.1: CUPS Configuration Management Plan +
  • CUPS-IDD-1.1: CUPS System Interface Design Description +
  • CUPS-SAM-1.1.x: CUPS Software Administrators Manual +
  • CUPS-SDD-1.1: CUPS Software Design Description +
  • CUPS-SPM-1.1: CUPS Software Programming Manual +
  • CUPS-SSR-1.1: CUPS Software Security Report +
  • CUPS-STP-1.1: CUPS Software Test Plan +
  • CUPS-SUM-1.1.x: CUPS Software Users Manual +
  • CUPS-SVD-1.1.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.1". + +

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/accept-jobs.gif b/doc/images/accept-jobs.gif new file mode 100644 index 0000000000000000000000000000000000000000..9da7a0dce11b175dafc1f23c698367a584570a0a GIT binary patch literal 259 zc-jF20sQ_)Nk%v~VOana0KxzO%*>glrgMjfRC01ZXJ<5KW;2nIUjP69EC2ui09gPO z000Bf2)ZFdCCW*wy*O)0h6qc@3|ncQs5O8hV5D#?TZZ_~c#hUep#Q)OixH-;FljX}YJw1!H5r;IgHn-{ceE1IM+xKXBDiBI` zcVb9?iiL-PdK(0UYGZX*NR)z(YMGpLeI1O8h?b;&rJAUv6&|6FuBLpBR+Y4}f)yXF zjeDMCyk2Xwyk~X8!xbPzN1MwiPf*Rw(IqS{)2i1OJPSA3-Wl5=0m|Ry1uHG$4wB|a J9UmglrgMjfRC01ZXJ<5KW;2nIUjP69EC2ui089WB z000BO2)ZFdCCW*wy*L*#L|7m*Xk=-c!xsX^>ArAegl%l!*sKJ2?@Ovt=71qmjFp2D ziS!KsykVg^p-wGLqZQZC5UI**By8P^r(sEYY>qgjV>LUDPF}QfG5%b6z|Tx{e1b=I zgKZK75JgLYbdFVbYD<$glrgMjfRC01ZXJ<5KW;2nIUjP69EC2ui08#)H z000BY2)ZFdCCW*wy*OJkL|7m*Xk=-g)bNFXfxd7&8KEoRI7ur(?*En5D09FRDaXlS zxwIrJPt*X=BNn0(tX7G_o*J5Bw3#GBx!3ejyl!6IYK+4gDc9Hcb2guT*Z+Nea25}A zfp&*bOo)PejeuSg1Q14xj*o$tXqb3!On?|1Mo6HYnV_4dom&|lqiAiAtfY{Rs;Cwo zua{#H!Cg9(kD9$Hq+P^)gS@K+1M&9+zyoAKO7z`2>?5A CbZnvk literal 0 Hc-jL100001 diff --git a/doc/images/cancel-job.gif b/doc/images/cancel-job.gif new file mode 100644 index 0000000000000000000000000000000000000000..3cc1e23bc650c00b22adb435e40862516f3b9d66 GIT binary patch literal 248 zc-jH@00;j^Nk%v~VN(DU0KxzO%*>g9fM7yGF&G#U0|Np800384LI3~%EC2ui08;=I z000BU2)ZFdCCW*wy*OVoL|7m*Xk=-g)$oOYfxd7|8KEoRcu6Zk?*Eq62y-YNfRrO~ zsTlxz%!m?Mm|CpKQX^V1N{+>e_ZyaGrsHZAOL1_;U#W5)SDWn@`n}ASJlz+o`iLgkro}5p{IMOgI%g~i4`6iMpj;6b!)U` yp15MVV3-jfLsY~vPEW?5W@?y9E literal 0 Hc-jL100001 diff --git a/doc/images/cancel-jobs.gif b/doc/images/cancel-jobs.gif new file mode 100644 index 0000000000000000000000000000000000000000..2384b903c673223b776c21f76c2ea6a9ad5f9d14 GIT binary patch literal 255 zc-jH~0093-Nk%v~VOana0KxzO%*>g9fM7yGF&G#U0|Np800384LI3~%EC2ui09gPO z000Bb2)ZFdCCW*wy*O)0h6qc@3|ncQs5O8hV5D#?TZZ_~c#hUep#Q)Oi-b8C55Wnt z$V?3YzGh^Zq*|;Ltf?Wb93@DjQVb>+w8}CyY&BaP-Sl+2tb^xx^!>ai+xZs{aaVYN zT5E-bfQEe=1P~W`XJ3ndW0aDNd3%!?9fO6ImYk%arj=P39vN+?h^VlKjd_2g6dxK# zZDL`Zlyt9IZoh0}LI6Zb%0N$0%g;J2F3{94JPS9~+8Ng&0m<9p1uHGy4v^x?9Umh0fMCo*G0Yee%mV_<007KaLI3~%EC2ui06G8^ z000A@2)ZFdCCW*wy^#zNmS+Pdj^s3SA7GShdl}#A&NQq9bUvdYcKiq3C}TH MbhQ>594QF^J97d~lmGw# literal 0 Hc-jL100001 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$bVfLjbUg9reH#cF&J_Z17`vNW&l@_LI3~%EC2ui07L*3 z000B62)ZFdCCW*wy;zbV!urgRjbxb(9tap_>$V2SzI1KHN?`ANk&2ju@bDrQjJ?SK zpbJirC1{e;a9)NIqA-FrYLVdV7UQs1!bdN6oo1uamWP@0&brx0yc%C2K(2syf_r&| zg+pT&8*@)~hI@pOd>9-VP?C>>j$W7+9V3WOiEmnZVvmUy9zavABTG!KvKT2Vv$qmB a3p2Q`x*q|oy*nr>zz%=IB^w?4ZZ&};` literal 0 Hc-jL100001 diff --git a/doc/images/cups-bar.gif b/doc/images/cups-bar.gif new file mode 100644 index 0000000000000000000000000000000000000000..b2bdf4b520db437c310a503ba6b27bd696fe580c GIT binary patch literal 1242 zc-jHl1SR`NNk%w1VMhQ`0P_F) z%*@RH0002Y%*@Qp%*@QpA^8LW000dDEC2ui07n2)07C@+u*pfQy*TU5@nB#mj$~-m;k{Y;ytnIwsiZN&m4v7XswuJ8gOvP;Gl130ww6EH@o#Dg|j9ca1AmkDFj8 zS{XKXAY>9XR*yh;F?nB{3I?LFK|*ykoVOOI8aS=Ez7hkevLz`Ky1x^{C@{=11JBPe z!#)kYEq7h8bV`VXN;m-rY8O>d zV4O-5gpmkfKwlewP0FNM(xAYTdTbgbP$5T20E_-I9Aa?dDMbQn$TDCdW`L3hRp?Su zSefM$3x&#Zmgo{wrj<0&!r?>#rCE;wE@l2gpdhHUX3w^j(xkKlO`R|&P)&)oD+y}t zHUJpLEGj^I5&{Ap`l2TWbE5UJJ5R+JO2wxz2F8>U3ulsNgIVvisq2rrP#;&yS( zbrdkBC76bwM#^&|K|2~%USCfQ3$59c$cZ-)bpQkAh5&@OU=j=j(3+4300C&f#o5S! z@{__U4n#D3nji=rWRA~B#>1_=DqA;MG35)U$TJ{9?g&X>Wysze;W7wKq{oiLFH4F% zg^{lW%l|6;3%EuStFR5&j#?Ks`YsM9$o`O9Df;12N>z%f!#DYgV7OBY^vsFGJ*#emy$DgA^Ui$uZT;BpW~qJjVg@QBm^ zJ{Eu!M@dkCSB@N*GUAddBDq0R1)A_oT}L9R7ma{aV@r-EVrgNHQF{56dz-Xa)Kgdq zsO2LFgt<&v+^GQdFoY=os0k$>s%z?nfpc*hu38 z12|;4#{!gEB*<*>7-K|pWWqAb2g%4&USOq-vW5nS!cahw@<~XCYH{o#4RD`^QyB&b z2*+3^>6Ao`iCQ#4SQ*EAQtp~OoLKq1siTrXA{MkkiG z;fSqcU|Itaq11MWr@$zv2M%Qnm(h4)lsZr%r}C>$0r2J*gbJr5;+vdL^wZm|g{^8D zH?sY<(FYqk zgh>kCxWq2|DxU44`wI^Fm&<5&ru~QwqLPKla&$zaOj)E`ph=@*rp#yWzUW;2h77%` zlobTInG;k~d`?-HIvMrMTmybS0Z^L-!%#B@0MLk8`eg3@ZUk*aN8cJ5-u?#YiwFP! EJKUogO#lD@ literal 0 Hc-jL100001 diff --git a/doc/images/cups-block-diagram.gif b/doc/images/cups-block-diagram.gif new file mode 100644 index 0000000000000000000000000000000000000000..156a2e78ee1f774975bd80528700bc169892e8e8 GIT binary patch literal 3509 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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/delete-class.gif b/doc/images/delete-class.gif new file mode 100644 index 0000000000000000000000000000000000000000..81b1465acdd35559182b55e5b98ade10bb0afcdf GIT binary patch literal 259 zc-jF20sQ_)Nk%v~VOana0KxzO%*>g9fM7yGF&G#U0|Np800384LI3~%EC2ui09gPO z000Bf2)ZFdCCW*wy*O)0h6qc@3|ncQs5O8hV5D#?TZZ_~c#hUep#Q)Oi)1+%jhX{S zX*x0sPu&3EyF{ZE>_ltbM!2)alJY!C%1CJ1ob7(o?=3ju7<-}TuYS)gw~Kptf_;G% z4|aKigMoyKT40ZbiWmeCZi!BfnS4%vo}F=La|IoUe1DOXo@9)ycPav=ey5JKs)d@E zv~wRzprW&CXm4}BXi9xoqaZ{<&dyU*&(lCGF4WjEJPSA3-W%H?0nOj#5-Tm@4wmNA J9Umg9fM7yGF&G#U0|Np800384LI3~%EC2ui0ABzU z000Bn2)ZFdCCW*wy*O)3h6qc@3|ncQXgPo)V5D#?mxlPxc#hXfp#MM=i)1+%jhX{S zxj7;$%%W@n@Li$>EOc4IYLl}DcM?5H%1?9lN%2OM@b~(iX2&m%@mbDimiv2cWORLg zfQ1Ybh&DCpHjZOgv*f^AVfjc))Z7#*W1@DF5KWcJPSAB<|yMK0o3R1 R7Ar044xH}h9Um|NkNW4ozWXWgvHHbZ8()Nlj1yEC2ui00031 z0RRI2jE||y?GK}zwAzca-n{z{hT=$;=82~2%C_zc$MQ_q_KoNI&iDQg3<`(DqVb4K zDwoWr^9hYgr_`$Tip^@b+^+Wv4vWX+viXcotJmzd`wfrF=k&V$j?e4&{J#GW7$`VM zSZH{Nn5ekO*y#8O87VnQS!sERnW?$S+3EQS8Y((UT55WVnyR|W+UoiW8!J0YTWfoZ z+W?T;1mMf7BmGNVZH=8Ry}e_7?TrH-E?z@kZZ3m9 ztq#Nf?EV5C&@Ioht6gt@kMirBfM357&*B9HIFQ7$eGCL9{NQjw#D^K^Jh?ofCY<;rVU zmR-@ecA?_j>oROZt$_CtMru}U+Q4`V&;09Guw%q}88@Cxd9hW=nA`R}xVE!r%bzhD z{zuj+=fd_LGi*M<<1Jrg z9bM+0O};_bTX;Ghh+ka76(^v7H$6z)gRxP#8gdSDHl2k`NoL(^&h52ah{Z{$TRY`F zMxZ+!%7$KaE&c}-ds)o~4S)SDrV@_%eRpDy^`W?pctL{L6p{29x#NiPsi@$JGS2uU zl|{Zc+f@xFCuEmS1{o!iNqXobGE0%ArIOSD*koTG{`97oR(|-Uh_z{WSDZtZ8K#<5 z(l#eWhso)upn5uoXP)y-^=4N%u9c{ZWI|f!gq7~dqG@1~HkhV%TG^;=7KSQng?x&Z zA*rQ087XU_sj4ZXr+T{Qtg)WNrl%27wWY2{_Udb!um=03i*LUA z?#pk#{{9Pazyc3UaKQ#2jBvsVFU)Ym4nGWW#1ch0fMCo*G0Yee%mV_<007KaLI3~%EC2ui07U>4 z000BA2)ZFdCCW*wy?Bx#!urgRjbu3v9tap_>$(QWzI1)XN?`ANl!}%EMR*}jj6n?Y zG63j`LuF+dg_0W5qvXKdZiQ5BglhzcC627OP#(M4=XV?awmg(%a-GOuTjz5Y1Q1qh zfO{Eza()#XYKxG8eu`{}OahOUnwpATRh)*D6&;yno||1^dS7j)79K!7vMx?47M_YOT literal 0 Hc-jL100001 diff --git a/doc/images/left.gif b/doc/images/left.gif new file mode 100644 index 0000000000000000000000000000000000000000..fd7b0410439bdc234c3e56e5c41308dd2834437f GIT binary patch literal 110 zc-jGO0FnPkNk%v~VGsZq0KxzO%*>g@#F4YJfTpH%o}O!&nP#i2c(=ENEC2ui01yBe z0009!2)Yn5q)5q{nV7DV`x2c8aADSz-i2bpnt|>##8X7yIA+uH4b!a~KovXD6eQQD QxKT0!L{Y^7$s_;(JJ*UWq5uE@ literal 0 Hc-jL100001 diff --git a/doc/images/logo.gif b/doc/images/logo.gif new file mode 100644 index 0000000000000000000000000000000000000000..9999795caa725187141a472f5dd1109491286b8c GIT binary patch literal 1958 zc-jG`2U++>Nk%v~VMhQc0QCR>@bK{O@9&O|j*E+not>SVo14DAzPr1-mX?;3l$2gx zURqjOYHDg`W@dJFc5`!c2?+@W1qIX7)6me+&CSiq%F3*)tf{G~!^6YCz`*P4>+0(2 zqobpsprGaD<>ch#`T6aBzr-i0J6(DJdx+ARyr2;N0BY;^N|_rl!cq$W>KU^z`&HGBUBT zu>b%7EC2ui07n2Q07VA=z+G-gEOL%WWM|22b_md@lu)Qz3#+VFi|Be0iEudO3V}lC z$#2d6q1ZbBY~4HjZnj@Wv*~YUe;$H@AB7$tHaLhjjEyHZCnqSA5)%}b4GsXC0c~s| zeHtX5EHfwq0~{V45DWu93MB(L0|_<)IvFi8J|_YtEfNGRE)~WVIvC2z2F(W~3J)59 zeKXdBGan9gJug2HjSb=rEEtfI5|tB{6vrt&${88W2G1lV1V0=;{1z4$7l!PJL1@vU zMvQJKjC3O1oC_4%=|Hv&1HA*!o|P!U&xgN{L^yO1`Gg9W1Y|&{T*(rRO8`80Y?8UD zW&i*I0%*{wQ-l6bKGv?y7*r4k4n{{CK{|(mfrAh+L*Q6L0N@ZCb7cIG;3L8h7kzsC z(BR=3whxC6B~64-;W>2bA|9iNArsF48+_*VV~v1UHUd7V_#q;K3akQbL>OV?0xSs; z7QA_|4Z(;M6f*o!u_HnT4D&KzBte>E#|00DnmvT}gHfbwZA9`)VG;wv5n52#WcbS@o=xDt^i`z)^>>3gOZQUL`zB(qF2SmN~IPDtX_hYP>;;Q==@OqD8^!NLzUm_P#!6+l3P06(;Fn|=`-zzPX9&``n; z{txW%f(0tnV8I9rxF^y;s->ysQL(uN3Ab&$@Yx08`EUei_;gS}4kd7aKn^DGvw{FC z{4>A+IjkUq3-Jy>tw(H1G-jZku&xLYuY~-{1Xxr@MYnJ2{;ST zu~OVcVygtWB16}mp=t!IN5cjrFG*0WfQ1+d*eCVG7t5f6g%@UxVN3u52vtoV+5{q! zd|6YbiT1JvGC~zfl8H-DneYSt4V!%J z04^}d(7_KFRN&Jc3-qucAWHTPVNxruK8daC$oV==JVeX+4*|q*2Lvf>0D}S>)Bpnu z#vZ#Q$Sc0(Gs)}-olKrJ*#QHA1@2@w-hjZ+f(L<+p5|*#Lg}U?l&F$ijPWT9UQ>hflHDp-bRo|?44?o_i0wdp%F7HE*n(ZG zfdnvMK#eeP8yB=7H-O4RaehF72)IB5Fn|mUdLRP`JOBnFNLf5aI2vd;ASXNF$zJ}@ zhZ=lC6%KmA0uJ#58|>gP5U7C-p!0$gydVNP^4AM?aGMEW;0FmP&8PlCMFOMwpoBe1 z5ZS0Ghz-2sFDmeW3PjKW8%#h17Vx47Y+!&9VBiEJNQVPPP=FD%Km;wQ69+~h0us=} zSLZpJM^Mv~891&%R%8KdTqOfG&B`scq7pkOFn}G@X^9uX$kATr1Ay${0ehLCYKBq> zE3%;lY{`cw79fG|rCgU;zpkK@b1{JDeydnE(I) literal 0 Hc-jL100001 diff --git a/doc/images/manage-classes.gif b/doc/images/manage-classes.gif new file mode 100644 index 0000000000000000000000000000000000000000..69d5b0147068125faa07a4a84266a6d81aa269fc GIT binary patch literal 289 zc-jFW0p9*cNk%v~VQ>Hx0KxzO%*>glrgMjfRC01ZXJ<5KW;2nIUjP69EC2ui0B`^l z000B-2)ZFdCCW*wy*TU53mHPNjLguTXsWKoAd-N=&UCFBq-^heFX4)SZ%CZIOqN5k zxH&kL5h$}V00=KmN_L8!K&9MC1GANspXNeYz0OL}6|mRb2G{L!ii509f75JHf`eaw zgL6xLgo}!Aj1~`kj(LWPh>n(&U0R2onVuE|5SvPsPo{KRn5UYFY-f0>uo)kGeTJ)m zxsR@#pNP7)kOIQHjlqnnfWFDdxQEXdA;rsRrPXdx*V=iq*xPkp;TR%FVZG-yRaWWM n?K>|q@2~SUKnptc`YZP%0p|MxW^e(+pMy~X1%3ztBLM(A>uiRu literal 0 Hc-jL100001 diff --git a/doc/images/manage-jobs.gif b/doc/images/manage-jobs.gif new file mode 100644 index 0000000000000000000000000000000000000000..adaff856f0929ebe37519e68994a60a767490353 GIT binary patch literal 266 zc-jF90rmbzNk%v~VP60g0KxzO%*>glrgMjfRC01ZXJ<5KW;2nIUjP69EC2ui0ABzU z000Bm2)ZFdCCW*wy*O)3h6qc@3|ncQXgPo)V5D#?mxlPxc#hXfp#MM=i)1+zgD~So zi5dWWOJ?LCMV6`)Y^i~vQoK`e!6+V=y-cb$D^a)2*>%Lx9lw?7@O00|s;R7(t)h(<9)X*+o~vM! zv9P(V6(6*^Zm6TfdTF4XQkr&WkRU`>SJF*A)WO##EH2qa$=ww^3pe29CgLFh(dO(F QD=p~`mhIggA1w(0J8!smBLDyZ literal 0 Hc-jL100001 diff --git a/doc/images/manage-printers.gif b/doc/images/manage-printers.gif new file mode 100644 index 0000000000000000000000000000000000000000..cd897291dd439440a3c86a2b66cb8ebd6774878e GIT binary patch literal 296 zc-jFd0oVRVNk%v~VQv5v0KxzO%*>glrgMjfRC01ZXJ<5KW;2nIUjP69EC2ui0B!&j z000B^2)ZFdCCW*wy*TT=$q>OJG6QFxXsS{}I0D8h&$Mieajow>bt{3Ma7c5NEC(b} zb7(e|m!xh02u7un=MsZ0bT{8wgZtHb%}MjQ`@}k-5oy{RKgYH2x;#8_aOrw=f_Q>} zdxc?acY|_+S&N1k4}Wfe6ODzBmY9}VPL+V0k^;fQk)g|kna{49%(KuEAjz6*yV-AtZfe=F(~z)id=eo?TN&r; uGE`OW#o_Wr3pw?#`8q%M`~N%oi3p$$pg|KYUJP__>Yzgj9zeWE0028T9*5-s literal 0 Hc-jL100001 diff --git a/doc/images/modify-class.gif b/doc/images/modify-class.gif new file mode 100644 index 0000000000000000000000000000000000000000..58a0ead8297209371b80fcbfd0ca3cfc7513fee7 GIT binary patch literal 267 zc-jFA0rdVyNk%v~VOszc0KxzO%*>glrgMjfRC01ZXJ<5KW;2nIUjP69EC2ui09ybQ z000Bn2)ZFdCCW*wy*O)1h6qc@3|ncQC^mp1V5D#?V}|(7cn;S}p#Q)Pi)1+zOU6P{ zxy&4%%Vur>@Lir1>_#fZG?QIi!^@3oBUmug7_Eer66oa2%s9MobiTb;@8fP)dV_v` z77uuBhKq!Qd2@nUj*}Mz5Rq(+ntz;OZ)Rt7bQK+VaD{-6sCu55sjrk19;T{}g{!BL zntZEo1s}A0Yjc^LvBaTqX=q=*1t3I0Thb|1Rn!{J*cB`;+ehCeJPSAB<|gAI0nz8} R6e}(24wvrV9UmglrgMjfRC01ZXJ<5KW;2nIUjP69EC2ui0AThCh_ApzO&_8KcK^A4i-{v97$Bme+At6qKs literal 0 Hc-jL100001 diff --git a/doc/images/navbar.gif b/doc/images/navbar.gif new file mode 100644 index 0000000000000000000000000000000000000000..c19f634c0d3278ff58e20c19eafe9136c8bbd5e4 GIT binary patch literal 2869 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 Tn1e`|gi81agHQ-67z6-28w6=Z 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/print-test-page.gif b/doc/images/print-test-page.gif new file mode 100644 index 0000000000000000000000000000000000000000..807dca10e6c69e9e2eb439a00057365f748df68b GIT binary patch literal 288 zc-jFV0pI>dNk%v~VP^mo0KxzO%*>glrgMjfRC01ZXJ<5KW;2nIUjP69EC2ui0A~Oc z000B+2)ZFdCCW*wy*TSl$q>OJG6QFxXo?Qu2pDQCuObgu7_tpvQFP}M3~4oKt? zbD$)jrlu1*8~}h9X++E6PP`j17p!YAzuQ7nx@IdY-sIOEM{nPEwM33_ocDQpYHVps zfQ5vDc8G^=g^CpqOjL@Af@F|dmXCXscAAfv1q2XThL??|oqU6bi&Jl)gRB)Ee@>~4 zr;xb3zLlYz7$3KbmYc7#iDIYA$9-74uFtJ-uydWga7vDvcorc>L*q1}kw4_=D6$+a mFY54N-x@v(IPv&2^&$b{`TrbPxZvlY6u^TKJb-YK0027`?SZ-g 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/images/reject-jobs.gif b/doc/images/reject-jobs.gif new file mode 100644 index 0000000000000000000000000000000000000000..6d938e308475bdc9862421d2d21653ff105b4b3a GIT binary patch literal 252 zc-jH{00aL=Nk%v~VN?JV0KxzO%*>glrgMjfRC01ZXJ<5KW;2nIUjP69EC2ui08{`J z000BY2)ZFdCCW*wy*OhsL|7m*Xk=-g*6@XZfxd8D8KEoRxJfHP?*Et7$Z{waGY3=> zvn0X>fZnB9pyI3)tVBy{Fegppc6%f*#Z&XR9AR4=-*HubrrYD;c74uIL8eA|ZG(M# zU`T{~f?N{>e@=;kdy?5_ CZED;A literal 0 Hc-jL100001 diff --git a/doc/images/release-job.gif b/doc/images/release-job.gif new file mode 100644 index 0000000000000000000000000000000000000000..a05cd9cc7178499b395e08d26165b3e4a55adabe GIT binary patch literal 255 zc-jH~0093-Nk%v~VORhZ0KxzO%*>g9xnM%6F&Li`1DOH0N=$Kp;oL*3U;!!G@4w=Q7lH5t>$WadM2+c4lubub=v3ks-8Y)^Y><55f4pA zd4PL=VTy@@h>wgE1Q33ThIe#^XLX!oa)*Z&9deL(SAC_YkeHDZ9;APujkB?|i?x8P za8gCLo|bE4c4%*H#(c#SAVgWsIZ#o~(labB)7LvT*xML9A_2_Y+bb<04TR!Z9UmglrgMjfRC01ZXJ<5KW;2nIUjP69EC2ui08s!G z000BV2)ZFdCCW*wy*O7gL|7m*Xk=-g)9{6Wfxd7o8KEoRxJD~M?*Ek4$Z{waQHN3z zvm}xRfZnB9plYns3|6wOG?$}%f0%g-h|3pUWz71AI9#MaO%EZGi_+&&y0EC~QRoy%)n literal 0 Hc-jL100001 diff --git a/doc/images/right.gif b/doc/images/right.gif new file mode 100644 index 0000000000000000000000000000000000000000..8ae8213ceaa55668ad026fb2b09254c96ab59dfa GIT binary patch literal 145 zc-nLKbhEHb6kw2Gc+9|X=FH3^M<#CG+^}p}@w|E2GiRo)UR|+$dkc_(6)FB?VdP@q zV9;Rz0+1ODEOr|_Jli-FvJG~d+<4a8Zc)`#HtD8S(z^75Lh&ne8~hLZ{XFpC{PoW- eYqsCz@mxK1*18bwZ*%53NM|f8I+>=#U=0BM(LkI4 literal 0 Hc-jL100001 diff --git a/doc/images/show-active.gif b/doc/images/show-active.gif new file mode 100644 index 0000000000000000000000000000000000000000..d232ef9f84342b411b132828eb6cdff279469b68 GIT binary patch literal 303 zc-jFk0nq+ONk%v~VR!%(0KxzO%*>glrgMjfRC01ZXJ<5KW;2nIUjP69EC2ui0C)ft z000C02)ZFdCCW*wy*TU5F&RRzjLguTXsWK*Ad-N=&U9@@1}Wcs?^`)V;72U-UZ%@o zd5|=H&&)GAqf)G#0br<{OrZtrwI`00H4Tiox%9Tf&Ul4=eKXNk%v~VUGY50KxzO%*>glrgMjfRC01ZXJ<5KW;2nIUjP69EC2ui0FM9^ z000C22)ZFdCCW*wy*TU5yO+cu1WU;bU#hNb%MPRo7;bIfxM!Gj?*Bm7P7w$ik4Q`m zbvZZ>5@_xzwN)!uOqQ~Zss?~!b0Y1suI5xaP0p-W4Xp+0B-aboJXd?i`~QA@d3R3{ zg;8{Fh8$+~jPmYWzM&9A(uiCbp0$Hv5fxY)PUlBojI)xx{knA*z2 z?#AHaqwf_Xk*w*B&sc|}?19hv5z?249~xE!Gmv1CBnX>^Ho$~|=#Zk37&9#Tc&Hyy j#gGL(I*J@=;bVya3`wfA2t&q62ftRz^bul&j06BXGu)o0 literal 0 Hc-jL100001 diff --git a/doc/images/start-class.gif b/doc/images/start-class.gif new file mode 100644 index 0000000000000000000000000000000000000000..2b6f43fad34cf9d50e46ca384a87ba7df433d834 GIT binary patch literal 238 zc-jH(01^L3Nk%v~VNL)P0KxzO%*>g9reH#cF&J_Z17`vNW&l@_LI3~%EC2ui08RiD z000BK2)ZFdCCW*wy*NuUL|7m*Xk=-g#qfoIfxd8Tgl=r#+N=b4?^CPMUZuY#1D0c8r05cbQa$7af*)oPV04j;4DR9&bfQRbfVwcddc2bgmg6 oLR`EtP*J_XFDos=#yK>{$`m>w0lUk=Dl8xkebG1^9xMp}JCE94=l}o! literal 0 Hc-jL100001 diff --git a/doc/images/start-printer.gif b/doc/images/start-printer.gif new file mode 100644 index 0000000000000000000000000000000000000000..017bb394aa59c23ee9b7b7058a49ad34c62840f9 GIT binary patch literal 255 zc-jH~0093-Nk%v~VN?JV0KxzO%*>g9xnM%6F&Li`1DOH6HT2X1t~bMr+JEvxO!Xn{FqM=W_b&#yGyxH`0t=@8^ASfq!%< z5E^u3eQjK7i+Y2Mj9?N3hf0rfONvp1o^zTS9Aj*dlYeY}r;(f(9i*R|kDauutFn?8 z9(ajwPH;$hPoI;%xELQpK+8W=Rm{*iD=pF0FFOl1*4r4^AOXtU;wmiP4wvFU93CtQ F06SU!YOeqQ literal 0 Hc-jL100001 diff --git a/doc/images/stop-class.gif b/doc/images/stop-class.gif new file mode 100644 index 0000000000000000000000000000000000000000..5cb7adfd808058a01d565fc69abd5c96e0114cc3 GIT binary patch literal 245 zc-jH=01E#{Nk%v~VNL)P0KxzO%*>h0fMCo*G0Yee%mV_<007KaLI3~%EC2ui08RiD z000BR2)ZFdCCW*wy*NuUL|7m*Xk=-g#qfoIfxd8Tgl=r#+N=b4?^CPM*Ndr@55+lW<*U|+azvpRL;>e)IOgOr`#+u`JyX8T8>;DyXfp>5j z1P~>5OMn!DU}2AHhC*ahcZ-B{Qh1z%o)jHimU(h|qnDYeq!%7;kYiq$Z-K9iUsP9X v5g(L2x>+PoP+7mg87nP6#l{vo3pLEq7|tL8z0%SuEY%K(*ghN{EC~QRBm`$i literal 0 Hc-jL100001 diff --git a/doc/images/stop-printer.gif b/doc/images/stop-printer.gif new file mode 100644 index 0000000000000000000000000000000000000000..b3accf3dfb2a3157d04b30385e2b0e11e6b0cb20 GIT binary patch literal 252 zc-jH{00aL=Nk%v~VN?JV0KxzO%*>h0fMCo*G0Yee%mV_<007KaLI3~%EC2ui08{`J z000BY2)ZFdCCW*wy*OhsL|7m*Xk=-g*6@XZfxd8D8KEoRxJfHP?*Et7=yE6?B*&Ps zXh}9@13-^BNjhKGD@luLV7SIeSX^LMvgD(+Y&DO|@QWj3Mw0LDb5*=%?4* CJ!;zk literal 0 Hc-jL100001 diff --git a/doc/index.html b/doc/index.html new file mode 100644 index 0000000000..b6fd277344 --- /dev/null +++ b/doc/index.html @@ -0,0 +1,36 @@ + + + Common UNIX Printing System + + + Easy Software Products Home Page + Do Administration Tasks + Manage Printer Classes Status + On-Line Help + Manage Jobs + Manage Printers + Download the Current CUPS Software + + + + +
+ +
+ +

Do Administration Tasks

+

Manage Printer Classes

+

On-Line Help

+

Manage Jobs

+

Manage Printers

+

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-2000 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..6986d8dfc8da1a5faac9a72c06c3fd35e1ceeea1 GIT binary patch literal 20446 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 B9{m6S literal 0 Hc-jL100001 diff --git a/doc/sam.html b/doc/sam.html new file mode 100644 index 0000000000..78a63d0bc7 --- /dev/null +++ b/doc/sam.html @@ -0,0 +1,934 @@ + + + +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 + +
+

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..fc7f0ad2e3 --- /dev/null +++ b/doc/sam.pdf @@ -0,0 +1,963 @@ +%PDF-1.2 +%âãÏÓ +1 0 obj<>endobj +2 0 obj<>endobj +3 0 obj<>endobj +4 0 obj<>endobj +5 0 obj<>endobj +6 0 obj<>endobj +7 0 obj<>endobj +8 0 obj<>endobj +9 0 obj<>endobj +10 0 obj<>endobj +11 0 obj<>endobj +12 0 obj<>endobj +13 0 obj<>endobj +14 0 obj<>endobj +15 0 obj<>endobj +16 0 obj[11 0 R +13 0 R +15 0 R +]endobj +17 0 obj<>endobj +18 0 obj<>endobj +19 0 obj[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<>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[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 +]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[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 +]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<>stream +xÚìÏsë8rÇIŠºÌ‰öŒî´üt§çyšÝ­ÚJñÙfvçÖ$ÁÊ!•S*Ç6•üÿ±~X"H€èn$è5¦jêÙE|ˆÆ·@ƒúÇOßòýÛßò?=å¿ýžÿçÿô,~*ÅOÿÈÛÿù×?þøÛï¿ÿºÏÿü—_Ÿò§§§·kýñõ¥ù÷¯|­ÿöœþº?•ßNå÷SùË©¼œÊ¿žÊ¿üÇ×?òÿýŸÿû¯¯ÿ–ÿíÛ׿ç‡oß¾>ÃKþ=ÿãõ§öcøä²+âõi»Ý>ÜËÛ?¶ß_—Î%^¶wY¤*w÷¯ËäOj¤Üöû¸ē‰é½Ü?–KáÂC]о/ëå!"—x[ÎõœE¼r˜ë‰KåÒ!˜¾rÛg޹^òȾü\ÆÕÊÏ3s=GžJRÎÉõ-òVâÃl\ŽuЄõV¾ÌÂ%²( + ‚B¹ü29×$X,0X –€Åƒ %ƒ/° ¬(ÚMÄåÝoÙ9h6×ÄXo`å\ûhò’LÀõ#𡬼sÕÑ,åÏ\M6A!|…gi,A +Ú Ñ ê£s5Ѭåà‹+›— 9Ä`™ãÅ`ž‹,öD.1?V{àÊàŠRç\uD98æY\‰c®}HÙ8媣`Jé++D91WT蚐°ŒÒË TÔ  LÔ‹Š4ðZåªBÃ2t,OãQ ÔxŒsÆq‰±FãzX¢Æ#F,Ï%£FL×]w÷Ûí—×cy>|ðÛa0IwÅ÷_†ƒüxÂ[‡ÿîŠG’þÅ˃ŸßÝuoœ*=[ í,¸ö~ºªÛk[ça=xì.Bú±àæØ\ìPƒ–.Î$[q¹¸¡==·aMJ&³»XéԜ.K™\¬@ž› É貘ÇUùÑv‡]¶cqeSÙà՛eN¤ܯjؤ½s’  ®|²¡ÅϼJé\Í Xd°˜ÎEùØÍÉÜZ9ƹfÂ"‚­¨\Õ FÈ1ŒȕυEÛи'’ –Y¹0p7ñú¥uZj+Cg‘¼c,Òé« …«rÎX•½ÅÍÁ‘jÄ¥{.B J<—°ÒlKÃ7D=Ì:¸ÎåÛÁÉ %i=•œkˆàBf½ .Ú`Ø`¹Š¹2O”,Á W­Ç’ó ìÍПR4q‡ãÚa…„–¤8®´&1Š«žÙ#3ì€á«aÚz/8 [c¸²0Dƒ¢õ ‚«æfóuXiæ*B J‡íÌ\Y OjOjäªÃê.d‡%F®"°îBú°ÒĕÖ]È'½1p5Á¸dZ“RW\wá¢ÄÄÀ•6ºÐRVŽr‰» 7æw£\u€Ý…[FJG¹*OŠ…²¢d”+ (2$*ÇVå'ÆB ÃRåÓ©¹Z’ Wå“s! q5ÂÀÚÛ=W¢È£­ÔrAˆ"v@;-W¨jàLi­ã¡ªnè¯t\5-4”=Ùí§ž±¿ÿ.Ï´’T¹Æúù=¾aÀ +¢6(®–KH·Kh%ºÖRÕÓbQ®•–ër›®Îa‡Àà ¯Çé¹ £^ >ÜÌіœáµCrí´\MçùÖ 1£$UsÑys¥Z®³í%·NH)}¢æÊ‰Îkœ+ÑsÝ´BPf=ègŒàp‡åz7.×MÛk¼b”¾Tq5ÔÊÀµÑrÝD° ¬•T؇ô¹WŠçZ鹊÷G”Q&ß V<זByW¤çª/ŸÕPÌ1PRWF4C#×NËu¾×úü+ü’QØV +.A5C#WªçڟòáªÕr[¬àª©fhäŠõ\盽§5Rì•K,×êZ[Éu6Ž;êÊ12BªWNZ,×:{—'%WG¤(³ÔgO@• ž«x j®Š5K5†ˆëWC6Ãq®ZÂp ÖbI…Ó5 ÊFÒâ¹Ä»Y¨¹®&EZ,ip-â\9%pžê¹*֚Nè(; +\n£á¬5;c+\ŒôÅq®æ" +®K‰kvª‰@“¤¥pµ¥×qgéB™ÐdcMãº(½Ž«àôWòD@“ë¢ô:®Œ3¾êÙwCÅuQz WÍÛÃÈ0’ ¤h#!r]”^ÃUðûMÏ%s Æð2r•^Õñ6g +ÌÃ’lì¨\g¥Ws5Ì]Œ +㘁´¶ÑR¹ÎJ¯æ½ØER2WÁ^f®“Ò«¹rfæŽÀ8f DQ)ëd݅~^¹e¢IàkSYŽ­\§Öç*®³Ý Fȑ#š ”(ªT?º²k ±ÌukDŸ+?krN7Ä="àVÌµë>š>h¸Þ;а›‚]†Yw¹k6+IlºŠšô¸ Wuáiè†X!dr¸Ñ˜ÄjøCýsȵèÝJ´§•¸rŽlH[âã‹:\…’K\[°'¢@Ø¢C­I¤€]Ÿ«VrU×Ê=öEèà£ÃDïû¯´ùÖṌŸêsí¯#èùVž«áxåÛ-â;^WÈ\OÌɱonn0¾d=äª\ÝT”‚lˆ{ó€¼0ÚT¹WWojò$ ð\{–l lbÕ¹.¶*qeÝKž„‰×ñÒáÊY²Ñ˜×Ó{Šyq—KΈÚ{ÈhzªX¯üPy8Å:F—« »òúh9ÔNþnï5ùÒ*¹Ä€+“,¯ñª è¨Wo'ÍéŧñýGH©\SßËy°†ÇeŽæãvQ°2Ÿ,’+çEQÁse¼(*t.a#‡s5–r*W͍çª>š^¸ +vt6מ͕4™¿peM/\œ¥ùp‰'óg®úÃÉ<–k2ߝÎ-‡͋ó·•Ü:\[æ»uîªßFwÒ²ßmµwpœOm›.Ò,²Î-ï\·u›þà,•\×FÍÕI¿\¹r¶ûRãkT§×ćk¥äjÔûËÛ}©4fÜkbÄኔ\¹z߁¿h£¶W]nj¯‰;×NÁU UPn9Ár­4áËNŕr¸RW6|ŒŽ¹Î«Ëë51áp%C®wшﲫÝÊ-§h®š+Vqõó¡¸g¯r~ô'/ÙÅlp\ëQ®Ó¿^òHjÁZv,¥Šk£tEr<Џ¨ëdÞ7ÛnlÌ\—᯻?"éx@·‰+×à¢Zr—Ûj{‡àꤥÈ]|Ëíé71âp .’7.y<€ +£®[‘"K~­lâŽÃÕ¿(—óM +-áðì8—Ðpz®”ÃÕ¿¨7RNf™*Œj1\·Ùÿj®˜ÃÕ»¨ðTà¹b\Šã|f.ÅEußÁnßÊ#`ÂÃĞk¨Šã|f.ÝÀT5_ŽÜp ×^­óŠã|®áE…ÒÁ&ŒJ[=Ì®9·r‡Çù\Ër¥#Bq­Q\µÚ՚8JqœÁ5¼HËU;â*”ñÆË- é5qxœÁ5¼(S:"×Ã%¢"ÎSÇù0\ƒ‹´\?Œê´áò;ô¼RqœÃ5¸¨[ývGסµœm”MçÃp .Òr?ŒjÕ£YU4ñ"Ú4®þE\-š+Uý6.5MìçCqõ/Òr¹ê^,ÕMìçCqõ/Òríùáa«68Íòþ ‰ýã|(®þEY/Mõʕ;ãŠK W'T•šØ;·ãê]ÄçJ\ñ®óۋ_¾,{lÔMìçÃqõ.Ê;Š-qen¸:ù‡Ýxã¼ì‘ª›Ø;·ãê]4ˆ£*,WÚâæ)­Š«ó~(EO¢Må’/Ú÷#¢âÂùåªÇ¸äã|H.ÅÀn÷X®µW£‹ç¯AeNä’/ªúC%;s Ï\BsŠCqœÉ%_T÷$[DX®W;Ê.é"Ñ Í« ¸—|Q&°üÂeÎ=Üy䒎óa¹ä‹ +E2þW=/WÁá’.ªn»Ê·EÞÙ¹j—t‘è¶²¾Æ6ÓJ\‚Ã%_”ßö¿ž#W铫{œÍ%_T ö+Càª8\òE½H0?qÙL—Q\Ù8WÃá’/’gÆé>®Îq>ès¥”ºór=ŸÞa?bšK©;3×Cÿøšü²¡ÎæuÕ»ꝪHqPJÛ:k®|¾!çéw·§†u\y1Ô׏áŒF~™WsÛìø9QeäÚÉÔ—Pì(É/4¬®KüuòÈȵ™‚ TSë¼;Àz齺 ®u+ M?\™j« ºã “Òdúu\©l)^¸š÷§»nÝî«ko»õʺ ®Dºµ®êºQ(¾unڑÀ[v…².Ÿ«öÉUtv¬÷7ïÒqY·äsM]Õ2¿ú®òöNå“+ª›v^Ȭ©K㊯ۧoƒ8ñƕu—áòžÒߌ§©KãJ®£0qÙÄóҟá¦×VËIÚªº$®Õõq¼=™t®êöÓ5ä$mU]WÚ}tk;.CúáõÏÍÝ[ÙtĪ윑Ò×%qÏ]ÓÆ+W¢ûѧ“T<¶ÔçÊ/ƒô8„wÞ¸2]:ÎeO¹éÀd#©;x®ýåóŽŸ|ðÆuŽš¸1‘†‘¶.‰«¸ÈÐÑÒKo\—½Îûƒ:À:eR¼Ë¹¶.‰ nÙ¯qëë¢Z{þ⇬ã‹õu•\ÃÄÎEu¯G÷叫“Òkmñîm®¾X_—ÂU_ `ü`;®±}½n=é½ÄÕ0‹V[—ÂÕ\~<ºeK®±}ØByŽCš—ƺ.]_ˆ¾ç²Ú_ÚÌÒ|Õ¢¯Kàj/Žùô[\½,Ú¸ôdЍKá:;æ“[öÉÕyіL¡ú’9]] +×Ù1×'ï“ëý ì —J•l:ZÇuvÌõ©¾—1ïë9Sš\ùPÔuñ~ùäËãÿc—‹|¶—‡á¤¦ÒLrTu \ÕÉOnÙ?×­µ«^(u@Õ%póÉ-OÁõ. +‰vЌÕ%póÉ-[raß-Z‹ÁX]—x÷b멸n‰×f®^]×Ù1ŸEr”Ë&ûø*™ìе\cu)\o&˜4·õS/\²{ãb§®.…ëM2âúì-¹JÜú¡k¬.…ëØÓUt}Q7®D²­x”KW—Âçð±‰ËæÜM.ý9Õù±º®ê|²&±çڍO¿6ÝyÈJË5V—ÂUߜº7®ªÛŸûÞmz«Kájn³Q.›sˆçkãï·M­–k¬®!ž—Þ¶%ä]A ®qö¶ ©Ÿ,ŽÕ¥puÞ ë«™«õ¹F꒸r—Õ¹ìf¤jŸk¤.ƒ«´çZãÒmú¡ÿ VÑ×%qƒßxàjô +3àj¸ëQ2\ŸÊ(—Õû7䵘_ÚQ.}]—îý¬n¹:}l \Úº$®úêÓǹ¬²Þè!Ón”ØÔµ*–ïí¹Ê×ëMóU|–ïY +¶X¾ë“kz.ó떗ÉUüÓr•‹ä2/pÉe3aþ䚞Ëjb¹h®õ"¹Ä?-WºH.ólõA¹’ere0ðµü>ŽO®¸ö0ðÅ}Ïn‘\ðA¹ª Z~¯Ù\Åô²×å÷ÐÍULMÞá¾70¸@ªrÃ\ e’ºÒò{9ç*Š+[\Àa +%°ß{ZÀ‘›ì ù=Å¡­´e&=@~¯thG„â‚¥Âèo‘ßoXÀQã¸÷}ô•±mç˜Á8lc®Á9æ½Qæ#/Á9°Üè–ã‚s`™±Åš3‡}€²×ÀXcV@éK`3Ëڬހò9°ÊÜX@=€ÀXa6.@l`3°½9êT˜ËÍ"8á Kèmœ£ Jè„m®gƒú¡€S˜ „A:àª%ô¢©€ìڐ„>G˜ ‡bH}fv_ï\bAB/0Ò -Vè׋‘Ã]‡+_Ž V˜Ȑ+ A,0 +-V裥ÈaÜ媗#ˆ(Â-ôDˆ *âƒ-ôéBäpÝåB} Â(»‚-ôÇ¥€VÏP„#C̾:\ÕB")£œ· Å }ºÙHd.„Ð'‹TæB,Ýċu+_†pd8üƒ"âȇxà B8j¤—Â!Gl#´A `1Û¨«>BðÌØå +h)‚¸xí\Åú,(ÖCéÑg­¡% ÇÜ ýŽhIÂ1ó3?ú•‚+~€áï€d¼s°=z @KŽy>r’s˜y€Õø©bå™a÷H*:sˆH؇–(30Ê&ÐúyÖ9eˆιÈQDs‘ƒ²Ôā9£Ò7”AОQéI+Ò@½t>¥Ï)Mª’ζÚ&HšÔ¡9›!"li¥åڇkˆ´åhél¨vc! »ô™ ±¢g83âžö¼nų¢ †®@žâÌcˆñqCË`3Ĉ9qx@Ë`iˆf(Í4€ó`¦Ÿ¬Tԇ -g€M>kΩj-k€MœdY“½´¬6± +ÈcX]>±rz‹€5D'VFÔ +œéöÔ1GNÀY™8樼A:©ÔgB©œÇ Üϙ.H,8ޏÃtºc wàÊêd†kÍÁ…Tú‰:,c=càÔ4Æ €?R§é°ŒÖÛNÓaә_‚& :C¢Åqí±`»0ºk…äªé0‘qƒph­ ±÷UKó„ªY.´v†èuâ,øV­!zÕzìÓÝ ¹ð†èQ:j ›ÖÖãrfWŠØ ¬OKüñÍPË%¢¹-±±’.h­ ѓ&æV>¬­'BõÊXZ?Þ¹±´°öõ^†˜È,e \<1÷3–½í#×½{&ܸ¥rU¤s©ÍJÉ\"š LdöܹK0‘;¸)82‡i\o\´;¼•Ÿ'–‘P¬.t¬Â^¿¹1p1_uFÃÒÇàd}¡ãNSbé¥ +\EiW°/)áøf08Ô&[õ cœFwžÿf<[l2êR6W›qÀúßtŽ*OôÛø\‹+Š¿S;‹añcq€‰‹ÙaQt_zî¬ñ¹‘‘«ˆ¸ÿ¥ó/9k·6\"â—{”56¼OßYqYtØqœ=šÌñ…Ie˜>˜¹l:ìŒöªÿ짌ý¹K.ê4Li¯ƒ~/ÛÌæqµ¶\Mä¦ÜÝo·Û/¯oåe»}È,?mcÍå¢ÃœSþ#†KȵqÀe'‰³tŽ+¼Û9á +®ÃÌK_8.±´îBrvm¦(ˆ=$W›…ÄupÇU/«»Ð\¬•O_ºäj‚áÚ´.¹‚ÑzÜöžKdKÑxw gÑ q!Øý^ +—XŒÒ¸°DôÖ!‰kvKÄgиš…X!•kæø—°MäšÕ)¹/T®9½3eû‰Ê5c`OJš#sÍ6Ähi/t®™†1±ŒÁ5Ï#îí2¸fbÔ,%=pÍ`sM®ôT9×ÄÚÁÈdr‰<\)´ášRY©Ã\®éÀx™dl.FÚÏ$ŽËšk¢Éóā×þ9椰áòoŠü,M+.ß`ɧv\~UÑ&Yؒ˧ƒ¶Ê¶åòf—ŒoÍEΡö41qÏåcÚb™®î†Ë½,ڟ›pÂÕ +·¶øhß"7\o¶è®Ë’CW+Âé,—\ŽºìþІÆÕŠ'küâª-.¹ø©ÕªGw-qËe‘^Hݞ“‹Kæ–ʇìþ‹ë6øà"æÅÇ[ï¹ðÃõV^qÙññýw/·÷Æuê5ƒAÞm_}ÝÛ'ש۞¶wê~z|õy_ß\çŽ;žpØ>ÜËývûøúêý–“pÍPàÿÿÿârõä +äÿÿEޱ‚0„wžâ5±•Ò +vDƒ B}€ÆÅ 5mÑðöRÃrÃÝ}—;ˆh{âÄ ZØqœåxB­Ž—ªÆ´þ#­†\=»¡sÞJo¬ƒR£ì×â1Ó  4a¡8ùÓ¨ÉKDpŒi("Ž3@IŠYÈ é¦e½²FWï~=FçːyM¶»Ý=Î34 ß@Þ÷PÓA­¶o­Zˆè}ÌÅòZendstream +endobj +144 0 obj +6284 +endobj +145 0 obj<>>>endobj +146 0 obj<>stream +xÚ+ä2T0BCc3JÎår +ár á +äHÉHendstream +endobj +147 0 obj +31 +endobj +148 0 obj<>>>>>endobj +149 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 +150 0 obj +699 +endobj +151 0 obj<>>>>>endobj +152 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 +153 0 obj +315 +endobj +154 0 obj<>>>>>endobj +155 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 +158 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 +159 0 obj +1361 +endobj +160 0 obj<>>>>>endobj +161 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 +162 0 obj +820 +endobj +163 0 obj<>>>>>endobj +164 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 +165 0 obj +126 +endobj +166 0 obj<>>>/Annots 16 0 R>>endobj +167 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 +168 0 obj +905 +endobj +169 0 obj<>>>/Annots 19 0 R>>endobj +170 0 obj<>stream +xڍVÛnÚ@}ç+F•Ú)¾B!RrƒRQšW•ª¾,ö:lk¯ÝÝ5ÄßÙµ Ɓ9ÁޙsÎ\ŽùÛñÀÅ®ú7H:w~Ç÷ÁóÀðÉ`Ø·‡à‡ÝOþ—ÙÃ×{i¤6DPˆDšÜ\ø¿;~ǵ]L£/ž¾,&˜ÌÆàë'àzö úóÆhEˆpÆ.Œ4(ò Üu¥Tvã8›ÍƦDrciâ¬T‡i ÁwyÜ*OWßvÆ#ðú:›…鬫+ÄÇt÷i’±˜ñ¸ÿþô\Üiµz»oŽáCÈ%•0™’«4Hy*ý—½ä(_­($äXŒç±2¹( ±8©€?rV4±ÁoÆÖàé]Ù= Ù +Udô¦$¸+‹Õ3ôނíì’=ÎýÇž£¹ã#ѐF$0.‰c¢XÊaÃâ²\)Fò¶·Œ››5~™µëäRìuðö±5ùïXÈ T*Ö +¡J/a³bÁªUÃ-]S±LQD)€¾2©të2Á¸ùG!AüvFSìJéam„§x_´0ã4( ƒ?$ß²2í~mkK3u^³êu-Ÿlà42lžæ“KøüôˆW:_šÒÿœMï fKALiµ>ÔV«§¡Q[ÏT=[¡¿º8f 9ÄžÖFU Qƃ8é9Í7ºØ²uôׅîÐ{l§È +7IRu¨È÷ãÙíäù  ÙÃÁ“”¯™HyB¹œCF–¸ž­Fãá¶!‘s^R՟ãMDº˜Jzðƚ:2M¨SÏuñ¦Æ¨ŒkQñĐÙÉæ¤Ø¶}r2¾rô¬+¬ÈšîT`}W(K^Âï\ªV¢=ì$Öj™³84«7ÉÞ7Zwg³ÓrütiuÀspÔo[ûº]Õ3˜×q Qµú,>ûuÝ-Ó9ý< ð¡hxhHh‚«µ,4{D<Î߬Š\2îy&Cx×ña+¢_MH£®î'¢€tEÁ–¹^裂~Pc A..F\ ×QÕ»–eº°‘Nj÷ðoúm–…/ µÚ…轨w6&Á2%«©¸®H4§èÇíb>OnŽÒlè3œZoãñÿ¿j×GŸÔ=¡¯E3Ô- Y±-O{£am*чºçõ°¶ƒQóÍ_Ï܆ 㺠÷UÂÂsëxËë1ÌúÐsuÔPßë»}ûÜÃ_3ð;Ò·Î?;,Éãendstream +endobj +171 0 obj +930 +endobj +172 0 obj<>>>>>endobj +173 0 obj<>stream +xÚmRKSÛ0¾ûWìp‚¬ØÆ 7 á֖÷ÆE±dG`kdòïÑ*q†PÆKûí÷ØÕ[’C¾® ¸šC3$wu2{(!Ï¡néj^•¬‚Zœßÿ{\ÅÖm¹‘Àµ-¥‡Ð!¬yóJ¿;ô°0¥Ò؝ur¸¤ +lUß»Œð]‚ÛH ê‹ú%É Í¯XAjG¡­r› ¾+zmcÔè¢#•¶ŽÖ=âDZƒÃÁÑ( ÿ\ºÿi)¦!aZÌYIš5ÂgºÓÀÿù_Kè±ëÂAià ¢ƒçs$Ã5œYʆ頩Ñw›ç tɾä% ,ÞJs Æëxuðü£žÂÓTnˆböÁâ°ª´ˆ1جñ£eS”åïzù´‡Nk=I}Û:iB€WòM)9´r ;igáÍKKÂö›‘Äq¬Ã$h'„³ÍF +ßÞ ÆIñ5µw8„`Mhß±½Éê`2/«ððò9›Ÿßj’¾ƒÒʺ°U4~qíyºoK¯‹,vá0ªž’Mo¬¬2¶€X\ÐyY'“Åz÷[endstream +endobj +174 0 obj +423 +endobj +175 0 obj<>>>>>endobj +176 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS04±Ð³P072PIÑp VÎO+)O,JUpLÉÍÌË,.)J,É/*VðMÌ+MÌÑ Éâ҅h҅ê24 š˜è™*@ŒÉÏ-ÈÌÉÌKW’t á +ä®$×endstream +endobj +177 0 obj +124 +endobj +178 0 obj<>>>>>endobj +179 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 +180 0 obj +729 +endobj +181 0 obj<>>>>>endobj +182 0 obj<>stream +xÚ­V]oÛ6}÷¯¸0 Ŧ/ÛplC›¬)0 )¼ÉÅÒ<Ð$s‘D•6Ü_¿KJ²-%ñÒ¦Häå9ç^Þ{¨¯ƒbüI`4q¿´\-ч $ ,3·4™ŽÃ),Ùy&r>ßDüÍòßA ÁpŽ]À£½èÃø€³KyÉ4<iMe  fÍAWœŠLp#¬Z!Á1ÂژjE·Vs叿Ñz+{w·–Ú¸¥Ûy%•¹‹×Ò*êåGZEõ#?šÐŸ‹TJ”†+ +tÃUK ê¦yî8»LçP…zð¬Æ3bs£Åd”œ*R^1̰Í&új¹}Uï÷9x°SäNržó|þÓz¢EW!¬ÃFГ +°Æ‚ôøoßÊÊYê»×(©‘;:žºÉ†ª™””°â@ÊÈÌ#g2ÏåV”÷Í8%£pXgàr6ȸÚùÀ*·¾œÿúå Ð5nQ¼ŠyC·58XË~¯·‡-¿ìK + 宥Âƒª”_i3ìÒ³£û,®Ë§'xJ[¬Ü,dÀˆ!à0NP`„ÙõIø†—ÏP¸-¨Oa©8}Àê~7¾dìxÜy5z)Ë'.biU©ûØX¦ìd««ÿñ²ÃôÇ/9†ÕO´ôæ +{÷Q2¹ÕØÁ+«]žîDzysu ZffKÔé —ô›#kûU.Ó¨:蹬ªÔáž4’Êüû}»7ØÇ&>KâØ'\ BŸ"¨u#Q÷¶à¥Ùë¯gkåH©•E“Î{®ý’\3Þ{3äB·y‡p㍩¶.¼/m麧žh(8´øÆnhˆ×¹XÕRïm"r²B‘ÁNZ…0 AÓl|¯;0ø^VˆGMeQ’50ƒd܌×hNœžÏþªRƒAD±CÊJàÛ³ßø©¿Pël]ŸPS¾3ݰžÁ_GWYl/ õ2B±µ|Ý5ä’z+¥ËýY¯ˆ¬V‘Fsçµ•Ž +ÉxÞĄâÔHµÃª›µ¯åYPœ5×6oÁgûö÷ ÿ<«¨I‚ª5¥YÝcuí:èJ×lºõ£Ð+ºAGÚ÷1ן–××kÓ&Ÿ$â÷åd:©¿2ÿø¼H!mÆ.N¡ >I?°;-ñ˜A2žâœšØJ†nq4ºg¿¬+®—ƒ¿ÿwÁL©endstream +endobj +183 0 obj +908 +endobj +184 0 obj<>>>>>endobj +185 0 obj<>stream +xÚ­V]oÛ6}÷¯¸0Ô"Ùr ;í[Û¤†­ð{é M^%L%R%);þ÷»—”2uiÖÀ~°%Þ¯sùmPÀ˜>Ì'p1YÞ/£S( +X–ôfv9Í/a©†Ë;„×Ë{z9ë^k«°JÏú€!wÛÖhø¥.5zjD`Ëø{±¸‚RWô߁6])$‚—N7!‡ôDÝTxÁ‚P +4.®„ÖksË5ǐù„[ãœ>À¯ ¸Bÿõ7¤ú踸rzMqÒƒ2 â”p¢ª°‚ƺ@÷Fђߵi`k[ØØ¶RT +ߦéÆð†‡#€²É”+þ£Ö»Q¥W£ªªÖ²¦/œ]C¶îK¼)\è_Y­hÅ=†¼i\Z^Néß@1çü˜Žޟ±¶kšir¿4?™å±™¥Njq&òÃ_‹›8×Í\k"úýHa]ÿ‡4J[×Â(ØèpÃβ‡3°MÐÖ<•‡´v’Ö»þö ŸÄ¢ƒ>TÂ{ü>qd‚Ýn|œœP¸u¶m] ×ÃãIvցœ{ì$W9À#‡¿ïcHޤe”ïц{»Š:Mç-zv ҍ®*X!ÅX‰4…‚Õ6.-µóÄZP‡« +)ÔL—)kÞeÛá|_üÛÀ‹rޜ?9ËdO¾֞øö3¹¿jÿS +éû +yÄãØNÑڃt(ØDl-‚–$˜-èteћWüG{²¢Ý•°½o‰+ÒÀ n‰'Æ=¹!n0öîâ +KÑV¡÷‰ÿ² OîÄ!ª éÅc;Ñ¿˜lÔÿÁEíãBfI3 +Îòób8JvâÀÒÇ'Õ!@ù>'ãF‚p‘Fâ&ئù1ï>F ÛÀQ—”ö`¡ÒþÔʎ"“[Ёžúyœå[‹-’M9ä:ÐéXmŸ i¥Í(µϲs¶¿ŸL]ßð̓á$Õ=ÀÉ*…#m§ì +j±¥ÁÙu…”ØDŸöPÚî zÎaÕ:ìyÇ ÚhÉÓ…ÙÆ+Ч»å`1l9ý©† 2*òŠ;Ò}Éʶb?ÙP-ª²52h¤„MÚ _G4ɍÜ[Z爎.ÊÒu嗀ÄWìþ :› +›•ñØ)I½$Î|vm~yÝ)ø²³˜^?³bž2ÆôƖaùßñ¾$#t"X‚øa"ŽÏRX6ŸŒ¿{U™Îùâßüàz9øsð`6#gendstream +endobj +186 0 obj +935 +endobj +187 0 obj<>>>>>endobj +188 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 +191 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 +192 0 obj +622 +endobj +193 0 obj<>>>>>endobj +194 0 obj<>stream +xڕVQoÛ6~÷¯¸=ÕbÙ²ÇÍ[ÓµX­ËPía@^h‘йJ¤FRVýïwGR¶¬Z‚$@lÝñî¾ï»úo’ÂRXmè7¯&Ùdþy i +YO6Ûu²…ŒO³½Pï™zàöJ©äZ9&•T/þ»›ì_L^Ääi&ªúWi·ݑSà҈ÜɃ©®¥åMmy‚GÃL§}|8@›#~bŽºyw»€YºJ–Ônns‚?tg¿§pÂÙrí§ ­ÅÒËðx:/´žï˜™»ª¾Hœ^v2ómÔg©XYoÁë˜q¾E+ÌA`tã*Þ [Hc>G´]à—Ò°µ& uÞCzàŸ­þ¯ÂµÚ|‡‹|i £ôË®çž2BI¬)qtÎ|üûé[×d)­ÊB¡ «Ð~6º T¬-¶X°\àT +j³nVéøç©Ÿß1řáðåéÉG>ß$ðW¨ëb+E£b%fHO•DˆãR笼h¥•nïûfumtm$r;¨Ûà4ŠU¢8ÔÌZl™'1¨ÃåKáÕ±ÚwáKQU`9Îdé3>5`Hå#ýô¡+Á¥»&×ùCšÒóqõ²g‚ב²Õ*ÙPkOÒ«|Êþßß,[‹\™b(?+ñLÔÓDì™Ð…•㯲ÏSdúù†0œ©ö¬´Õäš:„uQ“Îý-ËNçmxF o!©/IF}ŸºhÅîü`Pºe9êï¾ü[`½–1lŽÌqnHA^{8ß-ˆøˆwÆØI•Òã^îô*³  C˔gyÔíŲhUÃòzŸöËT±|O†ù#ÔǬ1 éò>YàOúw|Äþ¤ÂpÆ;cy‹J¯oçi²án²ü¼s¤¹mvøï-އël aÇ5ÕX¦Œ”výÝg‡9¿ŒjìÑè֊·®ïXV_kt»]¢ýíe¾‹ƒwE¥•ÄÛ]‰ö؈J;艴̴ÈǓõK‹oÎÁÐÃí¾…½n­Y'“xß Ö¡àqÙîb¿})|ý3ûô0 +Â?xfÕø»ïªŽ#¯}Kî~`e#ÈOÈ¿¢ægöô6pRCÃõÒ½dîC øíä]MóŠÑŒç ÇïD½¯¥÷*½"²HÖç MÍñ¢ZžöÞz–uýë~ç{;UAþÍ/ïî’Þß°ý µV"¼ÔÕ©%©PmU¸¹þéÀh¿‹6¾¦ë-¾Àl¶ñ5ƛü7]¸–îüÞ 6þ`ªa%åÏBÚì~¹ ¬tC_®î·XmñêÛЧlò×äéÃTúendstream +endobj +195 0 obj +1018 +endobj +196 0 obj<>>>>>endobj +197 0 obj<>stream +xÚ­VMoÛ8½ûWÌ1]X²¥xm§( +¤Ý °m½ØC.EÕl%R%©¸þ÷;ü1v£E|‰†œy3|óf¾O2˜ã_«.—@Ûɛb2{ÿ'dµý´\/Ò5ÕŧÏÅ»—/Нh^s2‡$_¦ k¾©a/{ ŠA¯¹ø6ÉݐÍÓ|DT@@÷¥`̖à„4/¦-§ ¬¡äFO¡S\¦ TrçÝ_Øë\@M¨±0jv™æ6*i{T”hŠQÖ.Åý Øq4Ù;©¾¥Pl1b§dÙ°H×1¢4 %ƒšÿ`Î@œ¥óÔçyÙÊå‰uHs_‡MÀwËh¯¸ÙKò¨"oï6·6䯘†›«B%[ÂE"HË $J™Ö@¥0J6îТ9қ-†SbS‚k4þôå"„¾¼L—6ôßҟ8‰­Ø2ðÆy0ž¸sDzþÀ b5˜J„ØÝ1Êk„ý¡(6á’T{[y,±l¹³ÙiÖW2zÅá4·Î‘@¡h”{d WIÍÔS4ÀË×èáÕ}¾\ÅiÍHÕò'I%žø³þïþ½ñ¬l{dRB±š)&(B@ŽTò@JçŒk㟄ʶÅ÷Òéԣ̎"¢ њé_ÂÞ`À\ž ä«, +ëçÌÐøï,‚‡Œ)q* ѕ‚˜d†|cØUJ¶.T °×j¦·xpFûNÏ*I7†åx ó/5—î•’=’É¡ñ£F;ÖØŠš*^ÚaØY¾Ë°?IߘÐ)Q¡“šé•gndy9`¼ +RŸäþ«,øÞy=x +x"Tì;æeêˆñ­%#ÜîµamdŽþý¬*Ló/&öÓk«‘Ùà½}!´ÆìyoÌòJö<Í¢#¯fC&¯ÇJéô|ÐJ‡á¡>>>>>endobj +200 0 obj<>stream +xÚՖÍr›0Çï~Š=¶™XF_Î-MšNfÚNš¸ ‚<¡1à"’Lß¾+ bí©ƒñŒ¥¿V?­Ö»ûkFÁÇõ'ÉgV³ÅKX­õHG„Á*}w¹Ù”¯°®ÊHZæ"+HRæïW?gÌ©GâŽè±Tµ“°( +r6>í(™ Ã×Y¸Èó)ڜì½z¡v'¥ÚŸst蜅Ä3bçýfþ¤Y%“:{‘ +D%!yÎóçÐç JÀu¶ÝH8´{ÒV" +ø!áYÉê„áI"•‚uY½ÙmÏÉíë;T€ó…¬_ËêIX=m¾h¹Ûº(k„. P[™dëL®n¯ïµ¥\¨§ »"hVPÆÑ1‘uŒ5GcŸèàāfý¸šyÄÐ}ûºÿ~L"xLB aˆWÄ<äG÷=ôˆ HШcjûí)ª­2ßBy†ÉX7LhN?'˜hŒ«™Œº‡É’x¾½Ú!¡,vañ—1®we±ê!?6>a]’%s"‰؝ĨIBnÿ’„M32ÂD¨uæ0êAŸc<á®q‡‚“Ox4!z­z…q³4ìi€NàÐhBàZõ Ž×dæà¤q ¾Œ&D¯Uñ˜ëÝ9ÁÁ÷PMb«îò€ó&íõdÖñ´ŽY[Õ ¶[)*È +•¥³lÇÄç21™xÐ +±3K ¾žÁìϛP¾–ÅïÃeÞ®zõÐë÷a÷+®+…ȱ¦ÝށHÓ +ëÐù^úQԐ)[¨°f5¥ +KWû*Y½Èê¢Ý¾mUæÌo±mmF÷u +÷nîkYÈÁɳáÆe'rь7A;]_çr8ë¦pW7@ƒºãþgLêÚþŒFË´îç„)׿Çܖê´@ÿGó± éڈZŸØzàï:6!]ñp¶þ‡¦‡³)IšõçèÅMÜލÑáêûÝ<”ëúUÇêešgE¦êJÔe¥à‹(ž…É>s»hÞ¬¢¦AðCJ¸=I¼xˆo³?r gendstream +endobj +201 0 obj +764 +endobj +202 0 obj<>>>>>endobj +203 0 obj<>stream +xÚ½W]oÚ0}çW\í‰J%MòѽÑn­*mÕ6¨´^ÜÄ@¦`ÓØ)âßïÚ Ð¤ „µ«ˆØ÷Þs||®1O=l|9p}ˆ–½«IïâfŽ“xŽ€ºV“¸OÎ&zŽï㓭ŸKbÙú¥Ç¿Nzø ‹í>~ÝÂ0ÔùA€E±-ƒqC0q<Ë+£ !•hdUpñ]Ëר–eÕØ”#xxævæa¢[y ]k¨Qà ây4qÌïÌÅD·r!.éýðȔ„ŽÐq,љŽ‰n¥c»{ØBÆ:LÇ» ,»3"ºŽ’½.9@ßG(þ &.¢(Ùà¹A±[“yqc—ÝÖÿÂø¦Ú6`â$c‘Jž,s©€®VŒfp™Ä h½Â7Q•ÞZÅ*f.ÁênÙQ£\-&›«¦bñ «7nÎyI:f³„3 +“F‚˜Å,ÆURP%`Ų™È–Ÿ‹:QY‡„¨Ô~Jü Ž/ø+ì܋:„\ˆ<á‘m‘X Ó>r£yª¬éY×ì”-ÕzEe½F5Ã]€s™ð¹äáþî7¬¨”k‘Å@y óLä+˜%)“f§U þi >À7×).âTã4$59g½  +RöÌRí.{A£ˆI ‰Ä¶{ʱ`|²±F\ðÍRäòÃÝõ YötÏ4M´wXÆé’³ìœób¥ÖI`ãTlù¸s3£½¼ 5v{d©Ð&fî“ÜÈOEÿ´ï^ŸöÕ F”k£åóJ42¾Õ©­Ö97ð뚃 +x“Uß]Œù¥ÂGG£…6MkÖÍb¸ÝcÐáà%î}÷ÇEËbŽÇUɔÜë¬EÇÍìÊN»]íl³ŠwaõŸEmíŠÃä»4Ó^P/žH•§^¡/ŠãÍxEºC½[GÒ· îT©õ¶!ÊãSVΐ´Ô!,K8xA ñF^Þ«®~Œa,fjMñÖ5ړ™„ï”ç45R¤ b×o?Ã`¸ÿ‹S^ öþIŸ…>endstream +endobj +204 0 obj +787 +endobj +205 0 obj<>>>>>endobj +206 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 +207 0 obj +1277 +endobj +208 0 obj<>>>>>endobj +209 0 obj<>stream +xڍUKSÛ0¾çWìä˜Ø‰CHh{¢f80Óé©ô Øk#*KB’ø÷]Ivš˜”arÉHûø»òó ƒ)ý2XÎàly=øºLnæe°*éfq1O/`UŒV'«'º\´—#«“c<ì2FPrp înï®Á½jƒÒŽ+Ʉx…ÆrYÑ햋"g¦€RpTÞ6MâãNl³ŽÿF˜V©o3…$;KgÎÐዛhÁ¸ŽaÈkVáäÔÿ=heÍ ×nøpÒ%Îéü?< +´ŽKæ~„ Xr‰t,ì˜3írj^cêãìÛb?''øÇqÄÆŒAAx7>x' 5ph¼ºŠ” „ 4ª&‚l:MÁ÷ 9Ä©±D‚.òG¥,ö^£Û"킂—%”,: ªl;YØ>RH®ä‹®’pCˆð…ÕZ÷¾E ‰hz‚Eïž4V}ÖN†îÁcZ žŠ“,Ò¼Ñ61̪^•1¼ª†4$ 1>fY@à”~ã“E?V[§ŽöÙiâÝ`=5rLDáI=rb ­gÇ¡¼×!6€Ã’çÓL–6ª2¬~¸þ ´ñÞ@ÓÈ/qI5æœwwÃd9“°ÆÝ<Õ솹ñ³ÐÂ/àsÃ7LÐDʼnìŠÕ ±ayŽÚÅfŽODÄLÕԔeƒ3(7Ü(é`à gkAµi›i÷×Xô:·Ûúíç÷{¸•T­d9ÂZ^I¸Ry(ü¹³ã“—†^ÄdÄì>©µ§IÖq'°}Õ,üòL%«ñ÷¡¶I¨Ðr[FñHîb¼çýΞ®È›)lYïí¿ ¶ +âîvŸ&‹j›-og½•.HÂýö]ÙךKݐ/—B´¹äªjÆ"•òRâu_´À³ù}:fçËØ#¯J·eᲨ¹äÖÑ+¥hgî˜l˜ðùILK–³©ÏºñDé5©™ Û9_úïQ¸šeþàz5ø1ø ¾b\endstream +endobj +210 0 obj +743 +endobj +211 0 obj<>>>>>endobj +212 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS04±Ð³P072PIÑp VÎO+)O,JUpLÉÍÌË,.)J,É/*VðMÌ+MÌÑ Éâ҅h҅ê22 š™êY*€Ü2sRÜò‹rKŠAR®!\\c$`endstream +endobj +213 0 obj +124 +endobj +214 0 obj<>>>>>endobj +215 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 +218 0 obj<>stream +xÚ¥Vmsâ6þž_±Ã—$ÓØØ>J€o×&¹äæèÑ ™N{t:Â^ˆ.Bâ$9ýõ]Y61¯!WŒƒ¬Ýg÷ÙÕ£ývCD1¼k»o:;ùexÒ¼iAÃpBoڝV؁av6|D8~¥—íòåYÆ,–ÏЯWFg0á(2à,¹]Àdn'¨I±¨ñ[ŽÆ—ðA#ÊO¡LÂÐ흱ð)d!üõðéat^˜“;ÚMÆ-‚ ~&.°‰Ò3f{>†º.J%HZî헫«fÿóoÍ?éÓ»½íõû½û{ø)¢Ïßëa…Q;líÉv†öQeS½à÷An0£<®‡ h üãó½{¢MÃÑy™ÈLFå:=Lð„ ”l‹[‚¯ÌÃבžQ®äëé™9¦|ÂSfi;”f>Ûñ²Ø– +ŽÒ†p£4üú0¸/œr´àB ¶40Þ¬eÃA4ã0n²±ÌæfwÄ©’–qY‹›¸È…o´AU&gB,[—l#‰"ªÒ8· h›.3_áÕ"NU†˜F˜+cøX O¿³Ù\à´¢¸â¯‘K–Sshþ/±ÅҍiTùޮ쀍Õó1u/-ÁÌgcJ„ò.,*¸.fלՊ·ú1° Š6¡é©dp78m`dÁ +Ö5¦ÈŸ‰™‰V³z'yÄ.ė^“‚Vô¢I¨µÒÿ5…:ëÁí¤.ª"_YngDܑ0£±)½ŠÉ¤˜å‚yæLK.§¦:ØûÄHà3 +XÉfå½â«Ìjãç|I¢fŸ-›q·ÛíÅôíô’N©aðQI¾©f91G'ñô +ÍÓG´§î8žÎøž†¯zLâ^”Ô=&ÿÛcÒ£œ×<.˜”É…ðbQóu¼ Ñðv9/±ä¸,IZš$êÍÌ(i_nvÇõ&Fï¥ï6PiškY¸î´Öó»<þ±íÑågP“Šì>€€U0Gíî50ŠÚ„¥Nkßv· v'ýUI¾˜¨xy›×«m¯W8ΧSêþ5Á:ÁoÖj¹5B,Ñëל‚jwÝÍ5—–" ^}²^éI]ª›lCœxF +C·™p¬Ûa²C3ެ­hòÒ¾OZŽPõš0lašnÉbPtŠÅï6ߪëÑt´ýfV†$rE]*a7D±£—ù +¡áÚm\âz¡'JµpÍÄ_šuŸš–ÎÜì¡á«<«i«‹ (¯z©šs4‡¥¶:ÐJY¬]*ùs¥i48¿M¸Êp¹«kÃ\•dÁ¥ÿ‘­:?„» ,U‘°Æ3] Ì˜‹–¯‡b+±C;y"_|*K|Â*{¬Sæ·:Dc»Óõ0Åèw¯&vᦣ÷ٌKêÍ,]™Ðg’šµP +o\&‘³JZn±Eä$ÚÇ_O~?ùlX¶Ìendstream +endobj +219 0 obj +1085 +endobj +220 0 obj<>>>>>endobj +221 0 obj<>stream +xڍTËnÛ0¼ë+¶§:@¤ZŠkûÚ5Ð\D½(hqe3H‡\UèßwW8•tșݙٕ¢æü¤°Êàf E}Σ›¤)ä%ß,׋d ¹žå„«üž/—Ãå¬ èû£?ƒÒ`¥¡p–”±ˆYVÕ®ìޅw3yý¶Ýç#ÛãCƒŒÝÇŒ…9m ˆ¼Ù5„wW\Q„fW"ԂœCœÞ$™¦ƒ ,§B(‡£7V +'*[&‹glÝ»]lôŒ1lSïØÒ`ï¨ö;ä>}CÔ |DPÁc@rz{@‹˜Î܉ú/¿¶·ÀÈ-û¤Î½w^†ž’€+ùu€ì£|Í£ŸÑ?]fmendstream +endobj +222 0 obj +509 +endobj +223 0 obj<>>>>>endobj +224 0 obj<>stream +xÚ-‹± +Â0E÷÷wÔ¡5‰¥fU±› ô9K°©FÒӈ¿¯Q¹w:œó ñ™Ä²Î¿ ´aZ4R‚{ÈJ—+%ÀÝl{:´hCŸ^&Z¬»ÁnJѤ'ìÍø4~Îw*~Qñ¯Ta%D©ð|³°1†xöáŠÆy›…ӑÞLû&†endstream +endobj +225 0 obj +128 +endobj +226 0 obj<>>>/Annots 22 0 R>>endobj +227 0 obj<>stream +xڅTmkÛ0þž_qûÔÅvB\Æh»·@7¶Ö¥ÛGٖc­¶äIJÝþûÝIÎKcDbßór§çògC„ŸÒæK(»ÉU>™}Ê ‰ ¯ñ>>>>>endobj +230 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 +231 0 obj +475 +endobj +232 0 obj<>>>/Annots 66 0 R>>endobj +233 0 obj<>stream +xÚÕ[ÍrÛ8¾û)xÜ=ŒB€{š©ù5ÀH´Ã¬Hz(*.¿ý¢Ñ p,@;‡ˆ3S•¸Óè/ìпÈ_W,ËÍÿ,+yV¨lÓ]½__½»«2žg뇌ÉjÅ2UŠl½ý׺þ´k²á!»ú©é§ý¿×_®þ³¾ÊW¹Á€_üòñ™*äJg]f~Dì²{€µ~|ÌÞÝɌ1ø AN™¥æ¯û}lêMIQ¬¸a™?\-þ?vÒ*F1£ç+eÌR20¬%È,ïîÁl„â…á…ï_öSÓe'A=œÎˆ‹• Q‰Oh¿}mƯmó p‚­ª5e·¼2ç¨Ë´0š A‚µX¾²GôvØ:s4OÛ˓7ö⥱A€†|‡؋/åò蜺0¿K™Ïşl¾eR[ýXÄPGqc§rU„Xȵ?œÆðäºÌº’„Øo{ÛOmÿx̓ï²Jšƒ€[œsi"²Rz=cõ‚Áæûxȟñn:ëþ!„,áæ¥Œ/•uÃhKÌ>JÊ}ð&'–k£xD|Õl>÷Ãnx|@É̟.)JŠ„¹Da½°ÑIá™KtÁ? Ÿl¢Áªåç)…‹ÜèÐeæÐ;ÂSØ\êÝìêý¾ÙcÞ³`SÊïîUÙ[m OYfïø]»›šÑªj"±\ôö¦ÔÍ ëה†`b OÝ\xN²OßOî?{ F|‚»Û¯d?sšÔÒì'ã&UnݜÖf둘M&*†>î×fzÆÿšÈb}_¦Ñ”L˜KÀ)%ßßHɄ’èx<)s`6{ +АK(©´ÌÁ(HubÎûC»ÛF㺇`TÌM€ +àˆMpu¿¨7 Crþ¹ˆOP?öû©Þí¢ßæƒHYwÃ)Ë«Ýüùû½uG½Leââ˜HŸ£­ "ÞJò„<ÛL’…¢(€%6n`e„íƒx ßÂ܇qÓÄ6n‡³Ù@æX´Ûv?í§ÃÔ=¹‰Ë„ÎÓ;Wrع¢¤ì·0Q)W¨e +~ýcóס›Î5YT¾ ¯—ÒŽ Ì[ÍÖh¢<í¸D~3tOmêÚÎP¡Upþ|<·ÀA¯í¥{:a"ưóÀ¨d)ÏDŒcÒ{–kó àDqˆ¢> [@˜S¬îðÅáºA˜ ÁhÝÓs=bwN_êt&Œ]TÝ>ƒ†R³±‹ªBŸÿñÐ÷ KÏò—tˆæ`ÜҞ¸Sü„`´€ÀK_®ÒñTh9‡$$æ\®Ðêÿ +DG0ˆ±Õ9È¡0™eƒ| ó¾íëñ%¶_³8Ü HÆ0·@D—qH:šRcêmÎþüFBZÈ +½kOH˜Í4äJ*!u0R¼þ(bN²†òì’!± íCsh¢'IÎ +Šêõ§ŸÀ~©ûúцmµÙe£6K´Ô !]ÿ¥"â­4² +}~ºqå+aªÔ‘Ø„´{ª·]ÛG[…å ´2„#>Á™„¢3uvhÍõ¼l¦”4{Á­ë/!ƒAÂs•vÔe>ÿz/ºñUÐÒs§w)#U–˜Uð +Gƶ¡ˆÄl,^gÆZOÜõ+0âœßÚ^\¿2i±‡Æª2›Œ„g1MãûfŠOÁ1 àˆ]ž÷î˓ǹÆ+‹¿ñݗ ýCûxkhEN™‡cPµ">ª[@°wí®q/"¾{ÔMî^ŽO4<$<ŸÓ‡uÓ= c´íæ€×®ŽØsãÅôm²¨G s1$J¸¿HÌæbZ{ðHZ2 C2Qq]^‚|ý͙¤ÑÒÅß]0¯¾±éjÛsñ ý,ĆÑz7¦–øD ©£ÂÇUeö OGE!~nMTèé½Ì´LjhÒ¬T JFÊSQhtoïÇáy߸Í‹yõ•T¯ 7-¤<õ +÷œÂªw½ÝŽÍg»úâ0¢z)ŽSx[Ì#áy)ÎÏï8$–C37€"><Íæ0¶“}ÕX@» ƒÎCp–ÓˆŸÁË{¤¼sÓˆÿçasôÁ— þ+ÊÛ\§ +Güã·Ô‹{՗ROãÜúaŽç5 ¿¯w»áy¡N8¡Â±síLÎà œo›Þ^<ûÂbaq”%&þ’¦´ *!)ƒ.½´Góú0}^¿<Ùqº(–£!«RGÈ«€?±„ÿ²} +èf[¬ÿ4帛¯BÀuàS8ÍVA¹ãpxúµîìý7¨Ó¬P~ü·lšªTØUQ·^(eî-Gv ãOx*POøÏLy~¨w،ƒ›ùC‰s––ÌöÇÕÿEyLóendstream +endobj +234 0 obj +2249 +endobj +235 0 obj<>>>/Annots 80 0 R>>endobj +236 0 obj<>stream +xÚ՘MsÛ6†ïú8¶ӈâ”QÜ:íL3“FÊäØQe}°cŠ.Eדß]`I‚l)—X•=cxˆ}¹Ø]øï™`~Ë þ®«ÙÛåìöÞ1ÉÙr˄v™`Æ*¶|øa¹úóqÃê-»«íæÐ\þ5ûy9ã~ üúøŽY™qfr¬b"—™¦Ñ#[à&+š»½WL|¤•0×À\xââ˱ÝTïšúù Ÿex&a³`È^ñ#ÜI¿aßු™¿µÎ ÈmØÈÆàÁ} ZžEk+æÄDæU7Õ*¼ Y¼¾B“äg…»La €C݈Å`<óáW•Õ&k¿üãÝÓ×á\Â7Ž®çx.„¿É±Û{MÇ&YN³>ït²Y>¦ykG¹9M‰VÂñSÓMsÇùДÅšÄTñ¦xÑûÛBok¾^×χ¶<ìüëËáQ×sežNYZŸiLé# úÙåeH^Zېq>ï7M"{E˜ŠY<Î#&™‰ÕÖ§AÑZ|ß_L"»íRêá!Ñr€‰c ë&tûÚ'<Œ—c…s½ˆŒ&ì·z—€EËføT0˜{ù2 ÄÈ{¥;P*÷)ݪ0j V*dôåþ\ ì8‚|71ˆì„Z­×›ãñÇ¤Î$T5Fvˆ‰J#Lè+)4çDϹ/4A?ˆDÏE¨3ˆNç0„c™‰´išºIK!ð̙̎d'`/¸¹–Ú¢«3¢CUá½è~‰.Š %'Š+¦2{ÎÓj·9£wÁPo>¦‘½˜¨]üÔÆ~C9N¥) ¾Òp(h˜}ªœ§rAOœ›âÈLœTËá"ŽÂr4渘óéíÁiV´Z*Ìî#™‰u÷éÃ"ÑO «Q-5ÝىõR¶û”T*ڗ€ì(¦b©xg‹ùû·sÁ`{ÕÀ’6}x•µ¾¼[…Á×úe‹P>ïWm¢í(¶þvŒ$3¡Ê#K]l +YsD";‘¼Þoü(¿žÛßYéòEºAƒ!o*£CEø¥~Iè=,½±t8d&ÒO©6sX ϋƒÈL _§nXŠMá<#;îêöÜ=§阁#Ù ×w†#'}(¤îG2R^ŠïÒ¶­—£xqÅ$ä97AфÎYHW>Fsþ"ôlðiá+d?ˆ‚O_zD ñSÈ|aà&DGŒ!óeaGŠˆCöo ºŽç¯##^7Až¯Cñj `lfÆ,špAÄE‹ûˆ¡h‚œ$E,Kß!ä +|ذmÞÿc³ Br÷^ˤ)zÙõ¶}YÁ»˜?Tå¡<¶Íª­›#{¿:<¯‘w#T•úÆJïAY’<¿Ïþ "jÖendstream +endobj +237 0 obj +1081 +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<>1<>2<>4<>]>>>>endobj +xref +0 297 +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 +0000002561 00000 n +0000002646 00000 n +0000002704 00000 n +0000002787 00000 n +0000002825 00000 n +0000002885 00000 n +0000002969 00000 n +0000002993 00000 n +0000003044 00000 n +0000003129 00000 n +0000003153 00000 n +0000003257 00000 n +0000003362 00000 n +0000003467 00000 n +0000003571 00000 n +0000003676 00000 n +0000003781 00000 n +0000003886 00000 n +0000003991 00000 n +0000004096 00000 n +0000004201 00000 n +0000004306 00000 n +0000004410 00000 n +0000004515 00000 n +0000004620 00000 n +0000004725 00000 n +0000004830 00000 n +0000004935 00000 n +0000005040 00000 n +0000005144 00000 n +0000005249 00000 n +0000005354 00000 n +0000005459 00000 n +0000005564 00000 n +0000005669 00000 n +0000005774 00000 n +0000005879 00000 n +0000005984 00000 n +0000006088 00000 n +0000006193 00000 n +0000006298 00000 n +0000006403 00000 n +0000006508 00000 n +0000006613 00000 n +0000006718 00000 n +0000006823 00000 n +0000006928 00000 n +0000007033 00000 n +0000007138 00000 n +0000007243 00000 n +0000007348 00000 n +0000007452 00000 n +0000007555 00000 n +0000007658 00000 n +0000007976 00000 n +0000008081 00000 n +0000008185 00000 n +0000008290 00000 n +0000008395 00000 n +0000008499 00000 n +0000008603 00000 n +0000008707 00000 n +0000008811 00000 n +0000008915 00000 n +0000009019 00000 n +0000009123 00000 n +0000009227 00000 n +0000009331 00000 n +0000009439 00000 n +0000009471 00000 n +0000009503 00000 n +0000010254 00000 n +0000010302 00000 n +0000010350 00000 n +0000010398 00000 n +0000010446 00000 n +0000010494 00000 n +0000010542 00000 n +0000010590 00000 n +0000010638 00000 n +0000010686 00000 n +0000010734 00000 n +0000010782 00000 n +0000010830 00000 n +0000010878 00000 n +0000010926 00000 n +0000010974 00000 n +0000011022 00000 n +0000011071 00000 n +0000011120 00000 n +0000011169 00000 n +0000011218 00000 n +0000011267 00000 n +0000011316 00000 n +0000011365 00000 n +0000011414 00000 n +0000011463 00000 n +0000011512 00000 n +0000011561 00000 n +0000011610 00000 n +0000011659 00000 n +0000011708 00000 n +0000011757 00000 n +0000011806 00000 n +0000011855 00000 n +0000011904 00000 n +0000011953 00000 n +0000012002 00000 n +0000012051 00000 n +0000012100 00000 n +0000012149 00000 n +0000012198 00000 n +0000012247 00000 n +0000012296 00000 n +0000012345 00000 n +0000012394 00000 n +0000012443 00000 n +0000012492 00000 n +0000012541 00000 n +0000012590 00000 n +0000012639 00000 n +0000012688 00000 n +0000012737 00000 n +0000012786 00000 n +0000012835 00000 n +0000012884 00000 n +0000012933 00000 n +0000012982 00000 n +0000013031 00000 n +0000013356 00000 n +0000013508 00000 n +0000019863 00000 n +0000019885 00000 n +0000019980 00000 n +0000020082 00000 n +0000020102 00000 n +0000020233 00000 n +0000021003 00000 n +0000021024 00000 n +0000021165 00000 n +0000021551 00000 n +0000021572 00000 n +0000021712 00000 n +0000022630 00000 n +0000022651 00000 n +0000022791 00000 n +0000024223 00000 n +0000024245 00000 n +0000024385 00000 n +0000025276 00000 n +0000025297 00000 n +0000025410 00000 n +0000025607 00000 n +0000025628 00000 n +0000025782 00000 n +0000026758 00000 n +0000026779 00000 n +0000026942 00000 n +0000027943 00000 n +0000027964 00000 n +0000028095 00000 n +0000028589 00000 n +0000028610 00000 n +0000028723 00000 n +0000028918 00000 n +0000028939 00000 n +0000029097 00000 n +0000029897 00000 n +0000029918 00000 n +0000030076 00000 n +0000031055 00000 n +0000031076 00000 n +0000031234 00000 n +0000032240 00000 n +0000032261 00000 n +0000032410 00000 n +0000032933 00000 n +0000032954 00000 n +0000033103 00000 n +0000033796 00000 n +0000033817 00000 n +0000033975 00000 n +0000035064 00000 n +0000035086 00000 n +0000035254 00000 n +0000036289 00000 n +0000036310 00000 n +0000036459 00000 n +0000037294 00000 n +0000037315 00000 n +0000037465 00000 n +0000038323 00000 n +0000038344 00000 n +0000038494 00000 n +0000039842 00000 n +0000039864 00000 n +0000040004 00000 n +0000040818 00000 n +0000040839 00000 n +0000040952 00000 n +0000041147 00000 n +0000041168 00000 n +0000041317 00000 n +0000042106 00000 n +0000042127 00000 n +0000042286 00000 n +0000043442 00000 n +0000043464 00000 n +0000043604 00000 n +0000044184 00000 n +0000044205 00000 n +0000044318 00000 n +0000044517 00000 n +0000044538 00000 n +0000044692 00000 n +0000045385 00000 n +0000045406 00000 n +0000045555 00000 n +0000046101 00000 n +0000046122 00000 n +0000046276 00000 n +0000048596 00000 n +0000048618 00000 n +0000048772 00000 n +0000049924 00000 n +0000049946 00000 n +0000050001 00000 n +0000050106 00000 n +0000050250 00000 n +0000050353 00000 n +0000050458 00000 n +0000050623 00000 n +0000050731 00000 n +0000050846 00000 n +0000050951 00000 n +0000051059 00000 n +0000051167 00000 n +0000051283 00000 n +0000051381 00000 n +0000051550 00000 n +0000051706 00000 n +0000051806 00000 n +0000051921 00000 n +0000052045 00000 n +0000052153 00000 n +0000052273 00000 n +0000052438 00000 n +0000052545 00000 n +0000052711 00000 n +0000052816 00000 n +0000052934 00000 n +0000053050 00000 n +0000053178 00000 n +0000053309 00000 n +0000053431 00000 n +0000053598 00000 n +0000053718 00000 n +0000053834 00000 n +0000053992 00000 n +0000054084 00000 n +0000054191 00000 n +0000054302 00000 n +0000054403 00000 n +0000054556 00000 n +0000054652 00000 n +0000054758 00000 n +0000054864 00000 n +0000054969 00000 n +0000055078 00000 n +0000055188 00000 n +0000055302 00000 n +0000055401 00000 n +0000055537 00000 n +0000055635 00000 n +0000055733 00000 n +0000055892 00000 n +0000056007 00000 n +0000056127 00000 n +0000056246 00000 n +0000056351 00000 n +0000056500 00000 n +0000056602 00000 n +0000056737 00000 n +0000056859 00000 n +trailer +<> +startxref +57086 +%%EOF diff --git a/doc/sam.shtml b/doc/sam.shtml new file mode 100644 index 0000000000..e955423371 --- /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.1. + +

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..51b05a3371 --- /dev/null +++ b/doc/sdd.html @@ -0,0 +1,481 @@ + + + +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 + +
+

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..8bf97214a1 --- /dev/null +++ b/doc/sdd.pdf @@ -0,0 +1,760 @@ +%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[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 +]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[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 +]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<>stream +xÚìÏsë8rÇIŠºÌ‰öŒî´üt§çyšÝ­ÚJñÙfvçÖ$ÁÊ!•S*Ç6•üÿ±~X"H€èn$è5¦jêÙE|ˆÆ·@ƒúÇOßòýÛßò?=å¿ýžÿçÿô,~*ÅOÿÈÛÿù×?þøÛï¿ÿºÏÿü—_Ÿò§§§·kýñõ¥ù÷¯|­ÿöœþº?•ßNå÷SùË©¼œÊ¿žÊ¿üÇ×?òÿýŸÿû¯¯ÿ–ÿíÛ׿ç‡oß¾>ÃKþ=ÿãõ§öcøä²+âõi»Ý>ÜËÛ?¶ß_—Î%^¶wY¤*w÷¯ËäOj¤Üöû¸ē‰é½Ü?–KáÂC]о/ëå!"—x[ÎõœE¼r˜ë‰KåÒ!˜¾rÛg޹^òȾü\ÆÕÊÏ3s=GžJRÎÉõ-òVâÃl\ŽuЄõV¾ÌÂ%²( + ‚B¹ü29×$X,0X –€Åƒ %ƒ/° ¬(ÚMÄåÝoÙ9h6×ÄXo`å\ûhò’LÀõ#𡬼sÕÑ,åÏ\M6A!|…gi,A +Ú Ñ ê£s5Ѭåà‹+›— 9Ä`™ãÅ`ž‹,öD.1?V{àÊàŠRç\uD98æY\‰c®}HÙ8媣`Jé++D91WT蚐°ŒÒË TÔ  LÔ‹Š4ðZåªBÃ2t,OãQ ÔxŒsÆq‰±FãzX¢Æ#F,Ï%£FL×]w÷Ûí—×cy>|ðÛa0IwÅ÷_†ƒüxÂ[‡ÿîŠG’þÅ˃ŸßÝuoœ*=[ í,¸ö~ºªÛk[ça=xì.Bú±àæØ\ìPƒ–.Î$[q¹¸¡==·aMJ&³»XéԜ.K™\¬@ž› É貘ÇUùÑv‡]¶cqeSÙà՛eN¤ܯjؤ½s’  ®|²¡ÅϼJé\Í Xd°˜ÎEùØÍÉÜZ9ƹfÂ"‚­¨\Õ FÈ1ŒȕυEÛи'’ –Y¹0p7ñú¥uZj+Cg‘¼c,Òé« …«rÎX•½ÅÍÁ‘jÄ¥{.B J<—°ÒlKÃ7D=Ì:¸ÎåÛÁÉ %i=•œkˆàBf½ .Ú`Ø`¹Š¹2O”,Á W­Ç’ó ìÍПR4q‡ãÚa…„–¤8®´&1Š«žÙ#3ì€á«aÚz/8 [c¸²0Dƒ¢õ ‚«æfóuXiæ*B J‡íÌ\Y OjOjäªÃê.d‡%F®"°îBú°ÒĕÖ]È'½1p5Á¸dZ“RW\wá¢ÄÄÀ•6ºÐRVŽr‰» 7æw£\u€Ý…[FJG¹*OŠ…²¢d”+ (2$*ÇVå'ÆB ÃRåÓ©¹Z’ Wå“s! q5ÂÀÚÛ=W¢È£­ÔrAˆ"v@;-W¨jàLi­ã¡ªnè¯t\5-4”=Ùí§ž±¿ÿ.Ï´’T¹Æúù=¾aÀ +¢6(®–KH·Kh%ºÖRÕÓbQ®•–ër›®Îa‡Àà ¯Çé¹ £^ >ÜÌіœáµCrí´\MçùÖ 1£$UsÑys¥Z®³í%·NH)}¢æÊ‰Îkœ+ÑsÝ´BPf=ègŒàp‡åz7.×MÛk¼b”¾Tq5ÔÊÀµÑrÝD° ¬•T؇ô¹WŠçZ鹊÷G”Q&ß V<זByW¤çª/ŸÕPÌ1PRWF4C#×NËu¾×úü+ü’QØV +.A5C#WªçڟòáªÕr[¬àª©fhäŠõ\盽§5Rì•K,×êZ[Éu6Ž;êÊ12BªWNZ,×:{—'%WG¤(³ÔgO@• ž«x j®Š5K5†ˆëWC6Ãq®ZÂp ÖbI…Ó5 ÊFÒâ¹Ä»Y¨¹®&EZ,ip-â\9%pžê¹*֚Nè(; +\n£á¬5;c+\ŒôÅq®æ" +®K‰kvª‰@“¤¥pµ¥×qgéB™ÐdcMãº(½Ž«àôWòD@“ë¢ô:®Œ3¾êÙwCÅuQz WÍÛÃÈ0’ ¤h#!r]”^ÃUðûMÏ%s Æð2r•^Õñ6g +ÌÃ’lì¨\g¥Ws5Ì]Œ +㘁´¶ÑR¹ÎJ¯æ½ØER2WÁ^f®“Ò«¹rfæŽÀ8f DQ)ëd݅~^¹e¢IàkSYŽ­\§Öç*®³Ý Fȑ#š ”(ªT?º²k ±ÌukDŸ+?krN7Ä="àVÌµë>š>h¸Þ;а›‚]†Yw¹k6+IlºŠšô¸ Wuáiè†X!dr¸Ñ˜ÄjøCýsȵèÝJ´§•¸rŽlH[âã‹:\…’K\[°'¢@Ø¢C­I¤€]Ÿ«VrU×Ê=öEèà£ÃDïû¯´ùÖṌŸêsí¯#èùVž«áxåÛ-â;^WÈ\OÌɱonn0¾d=äª\ÝT”‚lˆ{ó€¼0ÚT¹WWojò$ ð\{–l lbÕ¹.¶*qeÝKž„‰×ñÒáÊY²Ñ˜×Ó{Šyq—KΈÚ{ÈhzªX¯üPy8Å:F—« »òúh9ÔNþnï5ùÒ*¹Ä€+“,¯ñª è¨Wo'ÍéŧñýGH©\SßËy°†ÇeŽæãvQ°2Ÿ,’+çEQÁse¼(*t.a#‡s5–r*W͍çª>š^¸ +vt6מ͕4™¿peM/\œ¥ùp‰'óg®úÃÉ<–k2ߝÎ-‡͋ó·•Ü:\[æ»uîªßFwÒ²ßmµwpœOm›.Ò,²Î-ï\·u›þà,•\×FÍÕI¿\¹r¶ûRãkT§×ćk¥äjÔûËÛ}©4fÜkbÄኔ\¹z߁¿h£¶W]nj¯‰;×NÁU UPn9Ár­4áËNŕr¸RW6|ŒŽ¹Î«Ëë51áp%C®wшﲫÝÊ-§h®š+Vqõó¡¸g¯r~ô'/ÙÅlp\ëQ®Ó¿^òHjÁZv,¥Šk£tEr<Џ¨ëdÞ7ÛnlÌ\—᯻?"éx@·‰+×à¢Zr—Ûj{‡àꤥÈ]|Ëíé71âp .’7.y<€ +£®[‘"K~­lâŽÃÕ¿(—óM +-áðì8—Ðpz®”ÃÕ¿¨7RNf™*Œj1\·Ùÿj®˜ÃÕ»¨ðTà¹b\Šã|f.ÅEußÁnßÊ#`ÂÃĞk¨Šã|f.ÝÀT5_ŽÜp ×^­óŠã|®áE…ÒÁ&ŒJ[=Ì®9·r‡Çù\Ër¥#Bq­Q\µÚ՚8JqœÁ5¼HËU;â*”ñÆË- é5qxœÁ5¼(S:"×Ã%¢"ÎSÇù0\ƒ‹´\?Œê´áò;ô¼RqœÃ5¸¨[ývGסµœm”MçÃp .Òr?ŒjÕ£YU4ñ"Ú4®þE\-š+Uý6.5MìçCqõ/Òr¹ê^,ÕMìçCqõ/Òríùáa«68Íòþ ‰ýã|(®þEY/Mõʕ;ãŠK W'T•šØ;·ãê]ÄçJ\ñ®óۋ_¾,{lÔMìçÃqõ.Ê;Š-qen¸:ù‡Ýxã¼ì‘ª›Ø;·ãê]4ˆ£*,WÚâæ)­Š«ó~(EO¢Må’/Ú÷#¢âÂùåªÇ¸äã|H.ÅÀn÷X®µW£‹ç¯AeNä’/ªúC%;s Ï\BsŠCqœÉ%_T÷$[DX®W;Ê.é"Ñ Í« ¸—|Q&°üÂeÎ=Üy䒎óa¹ä‹ +E2þW=/WÁá’.ªn»Ê·EÞÙ¹j—t‘è¶²¾Æ6ÓJ\‚Ã%_”ßö¿ž#W铫{œÍ%_T ö+Càª8\òE½H0?qÙL—Q\Ù8WÃá’/’gÆé>®Îq>ès¥”ºór=ŸÞa?bšK©;3×Cÿøšü²¡ÎæuÕ»ꝪHqPJÛ:k®|¾!çéw·§†u\y1Ô׏áŒF~™WsÛìø9QeäÚÉÔ—Pì(É/4¬®KüuòÈȵ™‚ TSë¼;Àz齺 ®u+ M?\™j« ºã “Òdúu\©l)^¸š÷§»nÝî«ko»õʺ ®Dºµ®êºQ(¾unڑÀ[v…².Ÿ«öÉUtv¬÷7ïÒqY·äsM]Õ2¿ú®òöNå“+ª›v^Ȭ©K㊯ۧoƒ8ñƕu—áòžÒߌ§©KãJ®£0qÙÄóҟá¦×VËIÚªº$®Õõq¼=™t®êöÓ5ä$mU]WÚ}tk;.CúáõÏÍÝ[ÙtĪ윑Ò×%qÏ]ÓÆ+W¢ûѧ“T<¶ÔçÊ/ƒô8„wÞ¸2]:ÎeO¹éÀd#©;x®ýåóŽŸ|ðÆuŽš¸1‘†‘¶.‰«¸ÈÐÑÒKo\—½Îûƒ:À:eR¼Ë¹¶.‰ nÙ¯qëë¢Z{þ⇬ã‹õu•\ÃÄÎEu¯G÷叫“Òkmñîm®¾X_—ÂU_ `ü`;®±}½n=é½ÄÕ0‹V[—ÂÕ\~<ºeK®±}ØByŽCš—ƺ.]_ˆ¾ç²Ú_ÚÌÒ|Õ¢¯Kàj/Žùô[\½,Ú¸ôdЍKá:;æ“[öÉÕyіL¡ú’9]] +×Ù1×'ï“ëý ì —J•l:ZÇuvÌõ©¾—1ïë9Sš\ùPÔuñ~ùäËãÿc—‹|¶—‡á¤¦ÒLrTu \ÕÉOnÙ?×­µ«^(u@Õ%póÉ-OÁõ. +‰vЌÕ%póÉ-[raß-Z‹ÁX]—x÷b멸n‰×f®^]×Ù1ŸEr”Ë&ûø*™ìе\cu)\o&˜4·õS/\²{ãb§®.…ëM2âúì-¹JÜú¡k¬.…ëØÓUt}Q7®D²­x”KW—Âçð±‰ËæÜM.ý9Õù±º®ê|²&±çڍO¿6ÝyÈJË5V—ÂUߜº7®ªÛŸûÞmz«Kájn³Q.›sˆçkãï·M­–k¬®!ž—Þ¶%ä]A ®qö¶ ©Ÿ,ŽÕ¥puÞ ë«™«õ¹F꒸r—Õ¹ìf¤jŸk¤.ƒ«´çZãÒmú¡ÿ VÑ×%qƒßxàjô +3àj¸ëQ2\ŸÊ(—Õû7䵘_ÚQ.}]—îý¬n¹:}l \Úº$®úêÓǹ¬²Þè!Ón”ØÔµ*–ïí¹Ê×ëMóU|–ïY +¶X¾ë“kz.ó떗ÉUüÓr•‹ä2/pÉe3aþ䚞Ëjb¹h®õ"¹Ä?-WºH.ólõA¹’ere0ðµü>ŽO®¸ö0ðÅ}Ïn‘\ðA¹ª Z~¯Ù\Åô²×å÷ÐÍULMÞá¾70¸@ªrÃ\ e’ºÒò{9ç*Š+[\Àa +%°ß{ZÀ‘›ì ù=Å¡­´e&=@~¯thG„â‚¥Âèo‘ßoXÀQã¸÷}ô•±mç˜Á8lc®Á9æ½Qæ#/Á9°Üè–ã‚s`™±Åš3‡}€²×ÀXcV@éK`3Ëڬހò9°ÊÜX@=€ÀXa6.@l`3°½9êT˜ËÍ"8á Kèmœ£ Jè„m®gƒú¡€S˜ „A:àª%ô¢©€ìڐ„>G˜ ‡bH}fv_ï\bAB/0Ò -Vè׋‘Ã]‡+_Ž V˜Ȑ+ A,0 +-V裥ÈaÜ媗#ˆ(Â-ôDˆ *âƒ-ôéBäpÝåB} Â(»‚-ôÇ¥€VÏP„#C̾:\ÕB")£œ· Å }ºÙHd.„Ð'‹TæB,Ýċu+_†pd8üƒ"âȇxà B8j¤—Â!Gl#´A `1Û¨«>BðÌØå +h)‚¸xí\Åú,(ÖCéÑg­¡% ÇÜ ýŽhIÂ1ó3?ú•‚+~€áï€d¼s°=z @KŽy>r’s˜y€Õø©bå™a÷H*:sˆH؇–(30Ê&ÐúyÖ9eˆιÈQDs‘ƒ²Ôā9£Ò7”AОQéI+Ò@½t>¥Ï)Mª’ζÚ&HšÔ¡9›!"li¥åڇkˆ´åhél¨vc! »ô™ ±¢g83âžö¼nų¢ †®@žâÌcˆñqCË`3Ĉ9qx@Ë`iˆf(Í4€ó`¦Ÿ¬Tԇ -g€M>kΩj-k€MœdY“½´¬6± +ÈcX]>±rz‹€5D'VFÔ +œéöÔ1GNÀY™8樼A:©ÔgB©œÇ Üϙ.H,8ޏÃtºc wàÊêd†kÍÁ…Tú‰:,c=càÔ4Æ €?R§é°ŒÖÛNÓaә_‚& :C¢Åqí±`»0ºk…äªé0‘qƒph­ ±÷UKó„ªY.´v†èuâ,øV­!zÕzìÓÝ ¹ð†èQ:j ›ÖÖãrfWŠØ ¬OKüñÍPË%¢¹-±±’.h­ ѓ&æV>¬­'BõÊXZ?Þ¹±´°öõ^†˜È,e \<1÷3–½í#×½{&ܸ¥rU¤s©ÍJÉ\"š LdöܹK0‘;¸)82‡i\o\´;¼•Ÿ'–‘P¬.t¬Â^¿¹1p1_uFÃÒÇàd}¡ãNSbé¥ +\EiW°/)áøf08Ô&[õ cœFwžÿf<[l2êR6W›qÀúßtŽ*OôÛø\‹+Š¿S;‹añcq€‰‹ÙaQt_zî¬ñ¹‘‘«ˆ¸ÿ¥ó/9k·6\"â—{”56¼OßYqYtØqœ=šÌñ…Ie˜>˜¹l:ìŒöªÿ짌ý¹K.ê4Li¯ƒ~/ÛÌæqµ¶\Mä¦ÜÝo·Û/¯oåe»}È,?mcÍå¢ÃœSþ#†KȵqÀe'‰³tŽ+¼Û9á +®ÃÌK_8.±´îBrvm¦(ˆ=$W›…ÄupÇU/«»Ð\¬•O_ºäj‚áÚ´.¹‚ÑzÜöžKdKÑxw gÑ q!Øý^ +—XŒÒ¸°DôÖ!‰kvKÄgиš…X!•kæø—°MäšÕ)¹/T®9½3eû‰Ê5c`OJš#sÍ6Ähi/t®™†1±ŒÁ5Ï#îí2¸fbÔ,%=pÍ`sM®ôT9×ÄÚÁÈdr‰<\)´ášRY©Ã\®éÀx™dl.FÚÏ$ŽËšk¢Éóā×þ9椰áòoŠü,M+.ß`ɧv\~UÑ&Yؒ˧ƒ¶Ê¶åòf—ŒoÍEΡö41qÏåcÚb™®î†Ë½,ڟ›pÂÕ +·¶øhß"7\o¶è®Ë’CW+Âé,—\ŽºìþІÆÕŠ'küâª-.¹ø©ÕªGw-qËe‘^Hݞ“‹Kæ–ʇìþ‹ë6øà"æÅÇ[ï¹ðÃõV^qÙññýw/·÷Æuê5ƒAÞm_}ÝÛ'ש۞¶wê~z|õy_ß\çŽ;žpØ>ÜËývûøúêý–“pÍPàÿÿÿârõä +äÿÿMŒÁ‚0ƒï<ÅÔÄM6`G<#Ì là ad›Þ^fbôÒ&m¿E´?s 1ˆ²çðU„Üœ®Uéý«µ + +åô0묞½6ÓVÜW”!%4ÇI0ý¨) +Dp†ˆ0œ¢)f¡.[·ü¾+kä£óî3d Nÿ~̼X=Ü<Î3´ +ßÁa¡¡ƒZ9eŸJ´Ñ%zŒñ8endstream +endobj +142 0 obj +6279 +endobj +143 0 obj<>>>endobj +144 0 obj<>stream +xÚ+ä2T0BCc3JÎår +ár á +äHÉHendstream +endobj +145 0 obj +31 +endobj +146 0 obj<>>>>>endobj +147 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 +148 0 obj +813 +endobj +149 0 obj<>>>>>endobj +150 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 +151 0 obj +113 +endobj +152 0 obj<>>>>>endobj +153 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 +154 0 obj +541 +endobj +155 0 obj<>>>>>endobj +156 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 +157 0 obj +118 +endobj +158 0 obj<>>>>>endobj +159 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 +162 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 +163 0 obj +890 +endobj +164 0 obj<>>>>>endobj +165 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 +166 0 obj +792 +endobj +167 0 obj<>>>>>endobj +168 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 +169 0 obj +982 +endobj +170 0 obj<>>>>>endobj +171 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 +174 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 +175 0 obj +984 +endobj +176 0 obj<>>>>>endobj +177 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 +178 0 obj +664 +endobj +179 0 obj<>>>>>endobj +180 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 +181 0 obj +117 +endobj +182 0 obj<>>>>>endobj +183 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 +184 0 obj +424 +endobj +185 0 obj<>>>>>endobj +186 0 obj<>stream +xڝ’ÁRÂ0†ï}Š=ꡕB©õ(Ð*L;Äi|€Ø† ‰¦Ô§7© +ƒ3DtÚÓþ³ßæÿw_¼zæ aÛ¿Zy#ì]d1„!à…-ÅI$€ë³[ä£q~ŽŸŒíu¿Q§Ó-§ZûˆTK¢j@Š MŒ¥ÐJrȉhÖ¤¡Ÿ„ï þŒ˜ýcÄL>œ‚Ÿ¦8;ŸZ” RÑ0A©a7€I»„LªÊÉEèl÷XËDJjYIî"–ó߈D3)‡RQ›0Z˜«†öÞ vŽ&ÇÙ¹q¾‹uBèʉ*¦EzœU¬¹f+Z3» +Â8¤¯Õ£Ù–+Rç¥!³æ¿œr9F²Õe¥Ø³Þû¦mWpçX£ãԒª!´mícG\VK gØqBX± 3«Î§€í°Ï(ùêK†Á†ÉUÛÎñ=*¡” ½%ŠZ_¬?íùáðÒôø—ýžm #[Œƒ ]án¸46ԛRìÝy¤.%Xendstream +endobj +187 0 obj +371 +endobj +188 0 obj<>>>/Annots 56 0 R>>endobj +189 0 obj<>stream +xÚ՛ÛrÛ6†ïý¼l/ª`q$/;N=“LÝX}E¦m&:•’“ºO_ ÚÜô&bœۛ%?“?Á—õ×TÌþƒÊðJèj¹>{=?{uÙTœUó» +T3ƒJYÍoš/>®Új{Wo7‡vsØÿ<ÿtöf~ÆfÌ2Ü7pß>¼uA¥…šÕÕºªg_U7Ž~´y_½ºT€û{n7m7µ ªñ ¹®ü‚²H¹Ynw­qeáö?f“ÿ‚Ï۞”ˆó™¶'®øLa€'þêR¢ŒöJj.lÆé8Q2ƒ¬í¾à´Ì‘˜GÔÕ­½êÝ]·\ºíÆA•±{LHWJ;ÖÌ䠝ðDbÀf2(Æ)ŐS+LÁ éHºyÚÚõÈ@Nû[ù ‡‡²ÏGÚï_ÚþK×~u8 ³fŠ«F[5Qñ$ÅUclì„â‘̍ç„yD]l—k;L_æå ”Òª[ãH,dçöÿN,;ŒÚ®ÒÍ`»á÷Á’É*Â=òq“0[tIóÙHùÐÞµ}»Y¶¾"ÈfZžð̗ ­ÒÉbCðœÅ*e‚/rÒb#±æV›‚ˆi$ÿy}3rIÒÞvà*æ.JÎÂ<²â0˜µÖ§½,”êR$sAfþ6õZSæ95³®Rp0¤ßm?"vÚÝy³óà†y„E±ãÀ'qˆq«c¿£UøßŸ³ +ð·¸ ŒQҏÀœ²žqÑî»ûÍË lg{Põp„HÂtýŒ'›Iú"Æ;Á\ý¨ôÁ³.ÃdpYA» å†fNÄ4’^/–ŸÛÍí >=õ^–Îp+l˜÷ÀÆuù!Àµ1²`€V°1ɲ]ïˎQ˜GX·Û9ˆÙ¤$(¡ŒñþÎÅ™P¦æå„â”PHB¡ræ¶ÚÝþˆBiéÛÁp.>ȄÒ*´‚N(A …$àõ¥…y„íýbµjW'øDz&J&ޝÙø “I "IJ$äw7\¼GíÛ¾[x8L¨©Ô„HÂögâƒL$QvnïB&$—öq¯@aaû­uôƒÊLÆÏõxý“ö¤†.;©ß“\E§ú½È±U•L#éuÛnWíӈæ*;,ÊV‚×d´óíz½ˆ5´¶®pbÍ©1 dcx,œ®˜Hr…€—(ÌóX–¾°‰=J‰¦N• I)Ñ4±p²dF°fàæJ °Õ®ÿ!•ªU*!ȔªãíKVÌÈÛí«„y*­½LÍtD",NH-~’Å Ãc% f¿"Ǹ›­à`Iço¯¼Bz6åÙnC +U§æ>Ù°òSQA4Òª" ¤kF æ¶\-öûv?[ÞwÞÏ' %’­NƒŸ‡ ɞ€Œ"‘.…$7ý,JæöiûqPh2ý*%“à™™û “Iˆhæ‚6)$ +óÛõÝæÐöi0~2È.÷ßà%>È\г ‘¤< +)~² „tà|Ãgo½ +RÈҕSùn±lGfú3‚›05Ç<Ü ßuûEÿ„Ã[žðšQƒš©ô|‚lP3«Š¤ I ´}¾(P˜GØùvó¥ÝtnŽD®8s¤3n€ÐËÇÍÒÍMÇy¨ïÚCó†§"‚¤1oD,B’ô×Hnn®ñûm>¿Ë&;,0n>º€Ù ëHڍeJcÓ¤‚LãšÅ&IsŽ$W½ +TÈGØÕõ˜ÄÙÞ 7ˆ°ãñ«§k\ëTCI­M¬ƒ’œ¹‰$ÜÞË +ó{·ØÜ?.îÇü"CX`­íu.€q$ž^ïšPY‰ô@‚Le5 gjÚ'rÜ¢,A˜÷¨÷WïߌFÚÙ?>¦¸<¹»À¢I•/™À’¥Ê§)‰‘àfi TÈGØõõŘc¤½-K»G’‚…DX©ò){hJh®³òÇuYþ¸IåÏPB# üN +óû°ØÆÖcs€Ï0f*€~ó\ tWfb#Ú÷Þ²Eï¤Þ›ƒŒ5PÝwäÔn>½à`I—ÝÊ=œàLñTg ¨ÑÉXVÍ|N±š)²Ž$Î2 +æö°»_¶;/œPÓŽP j“ªQ’JP×Q#ªWY ¼Guk[ì£DRL`~€ÒLjTLBéc†UwE¶Ÿ‘þeœ…y„¡F½·:|ò¤C©!$ÒÙ:{2‰ô°Î®È¶1’ÂJVÂ<Âvû8†&´’EÉ$³Uöd2Éa•]‘_$m"T‰Â<œLiì ïh$²öd •<›jÝ" lWeJæô9lv“±$J$ž-¯‡ ‰QMWä¸9]]‚0ïQ‡öïÃPÔ¦2£ÛŒ7LÀLZR Aj˜€ ‹ëšh˜"§ÑÇL×ñííã*ÞgS|YŠTLÞÈ›a‘]“­bÜ,jSpBI¿>¶}÷Oz锝T2B›:[¯ËEñzX×d‹„÷D]rBIça•é¹Û¼>:[ ×åR¸VÂ5Ù !üIôñ:x$¯ºv^b‘Óy4!RÙ¸*—ÀÕpoQÝBܔ£*(!‹/œlîºûÇ~w0ê}“ì((߀–½5ýTÀ€ýi +NÈ"é¢ëÛ¥í‡žÆæ‚›<¨ÝëTÓÈ»q/ã§üƒáwW™’—gKä¼>ZœHžN΂áú8¸u^ÿge?öu}=½7:ƒB鼨ðYÂߝ¶Í3XoÁÉz¿ðx³½;|]ôm…¯¢Û˾ÛÅ;JøGŽ_LXìP»?Îþ/Úi“endstream +endobj +190 0 obj +2132 +endobj +191 0 obj<>>>/Annots 73 0 R>>endobj +192 0 obj<>stream +xÚ՘Ïo›0€ïù+|Ü¥þ‰áØuk¥i“º%۝QÈiê¿gûLÕÆ»•6U¢WÇ}_Ìósþl¡ð`D¤æ·l6Ÿv›Ë›œpJv„©KHBK! +ÇVmYߗ%)æMā%)ý&¢á^‰XBƒÜó% +Ƕ¯ÓMÙÊH× )êHP[õ]6 æw ùE!‰qÓa,P8ްªõŠÞÏJbÚÕk›ˆ KlªI*æ9Œ*SŸCŽ[Ôñd0kéBþÏAݶA`ˆÊ¹n§1GHb¶µX paÇS±o\϶’¦6âHæt®Ú.˜ɜÍU;v:ò$ÓÔ¦KŽ#ìxÆb\[[ó¤õ\·]xÒÙ\·c$ObÜԞ +ÇÖWUùŽ<™³ŒT ‹ ¬`n—7 +Ýæ]¶è^kÿ§ù¶EK[Êí±†¢²÷œù +aEêEƒâüÁ@ +mk’°­»`R迹€#‚™+9WçºÎ‡1áý!Á #iWõ̀{`¶FQuÐ0¦“:Ìg* =@ê„ñ˜0ä0jÚñÇ=ªì»öÉIƒvK¬KšÓ5çH§oÀ2\G*ƒÅÃsl¯Ýmɶ{ÿ}E>WC}hÍKÙ×§±îì®vÁ”iM/4·©Ö5šü±ùiøòÃendstream +endobj +193 0 obj +869 +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<>1<>2<>4<>]>>>>endobj +xref +0 258 +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 +0000002492 00000 n +0000002597 00000 n +0000002702 00000 n +0000002807 00000 n +0000002911 00000 n +0000003016 00000 n +0000003121 00000 n +0000003225 00000 n +0000003330 00000 n +0000003435 00000 n +0000003540 00000 n +0000003645 00000 n +0000003750 00000 n +0000003855 00000 n +0000003960 00000 n +0000004065 00000 n +0000004170 00000 n +0000004275 00000 n +0000004380 00000 n +0000004485 00000 n +0000004590 00000 n +0000004695 00000 n +0000004800 00000 n +0000004905 00000 n +0000005010 00000 n +0000005115 00000 n +0000005220 00000 n +0000005325 00000 n +0000005430 00000 n +0000005535 00000 n +0000005640 00000 n +0000005745 00000 n +0000005850 00000 n +0000005955 00000 n +0000006060 00000 n +0000006165 00000 n +0000006270 00000 n +0000006375 00000 n +0000006480 00000 n +0000006585 00000 n +0000006690 00000 n +0000006795 00000 n +0000006899 00000 n +0000007002 00000 n +0000007105 00000 n +0000007437 00000 n +0000007542 00000 n +0000007647 00000 n +0000007752 00000 n +0000007857 00000 n +0000007961 00000 n +0000008066 00000 n +0000008171 00000 n +0000008276 00000 n +0000008381 00000 n +0000008486 00000 n +0000008591 00000 n +0000008696 00000 n +0000008801 00000 n +0000008904 00000 n +0000009008 00000 n +0000009112 00000 n +0000009241 00000 n +0000009273 00000 n +0000009305 00000 n +0000010161 00000 n +0000010209 00000 n +0000010257 00000 n +0000010305 00000 n +0000010353 00000 n +0000010401 00000 n +0000010449 00000 n +0000010497 00000 n +0000010545 00000 n +0000010593 00000 n +0000010641 00000 n +0000010689 00000 n +0000010737 00000 n +0000010785 00000 n +0000010833 00000 n +0000010881 00000 n +0000010929 00000 n +0000010977 00000 n +0000011025 00000 n +0000011073 00000 n +0000011121 00000 n +0000011169 00000 n +0000011217 00000 n +0000011265 00000 n +0000011314 00000 n +0000011363 00000 n +0000011412 00000 n +0000011461 00000 n +0000011510 00000 n +0000011559 00000 n +0000011608 00000 n +0000011657 00000 n +0000011706 00000 n +0000011755 00000 n +0000011804 00000 n +0000011853 00000 n +0000011902 00000 n +0000011951 00000 n +0000012000 00000 n +0000012049 00000 n +0000012098 00000 n +0000012147 00000 n +0000012196 00000 n +0000012245 00000 n +0000012294 00000 n +0000012343 00000 n +0000012392 00000 n +0000012441 00000 n +0000012490 00000 n +0000012539 00000 n +0000012588 00000 n +0000012637 00000 n +0000012686 00000 n +0000012735 00000 n +0000012784 00000 n +0000012833 00000 n +0000012882 00000 n +0000012931 00000 n +0000012980 00000 n +0000013029 00000 n +0000013078 00000 n +0000013127 00000 n +0000013176 00000 n +0000013389 00000 n +0000013541 00000 n +0000019891 00000 n +0000019913 00000 n +0000020008 00000 n +0000020110 00000 n +0000020130 00000 n +0000020271 00000 n +0000021155 00000 n +0000021176 00000 n +0000021289 00000 n +0000021473 00000 n +0000021494 00000 n +0000021635 00000 n +0000022247 00000 n +0000022268 00000 n +0000022381 00000 n +0000022570 00000 n +0000022591 00000 n +0000022741 00000 n +0000023750 00000 n +0000023771 00000 n +0000023930 00000 n +0000024891 00000 n +0000024912 00000 n +0000025043 00000 n +0000025906 00000 n +0000025927 00000 n +0000026068 00000 n +0000027121 00000 n +0000027142 00000 n +0000027273 00000 n +0000028247 00000 n +0000028268 00000 n +0000028408 00000 n +0000029463 00000 n +0000029484 00000 n +0000029615 00000 n +0000030350 00000 n +0000030371 00000 n +0000030484 00000 n +0000030672 00000 n +0000030693 00000 n +0000030833 00000 n +0000031328 00000 n +0000031349 00000 n +0000031480 00000 n +0000031922 00000 n +0000031943 00000 n +0000032097 00000 n +0000034300 00000 n +0000034322 00000 n +0000034476 00000 n +0000035416 00000 n +0000035437 00000 n +0000035492 00000 n +0000035597 00000 n +0000035741 00000 n +0000035847 00000 n +0000035967 00000 n +0000036076 00000 n +0000036225 00000 n +0000036335 00000 n +0000036442 00000 n +0000036596 00000 n +0000036732 00000 n +0000036829 00000 n +0000036939 00000 n +0000037054 00000 n +0000037167 00000 n +0000037267 00000 n +0000037425 00000 n +0000037522 00000 n +0000037632 00000 n +0000037730 00000 n +0000037874 00000 n +0000037979 00000 n +0000038094 00000 n +0000038200 00000 n +0000038363 00000 n +0000038478 00000 n +0000038599 00000 n +0000038719 00000 n +0000038844 00000 n +0000038965 00000 n +0000039085 00000 n +0000039195 00000 n +0000039343 00000 n +0000039445 00000 n +0000039561 00000 n +0000039681 00000 n +0000039794 00000 n +0000039911 00000 n +0000040028 00000 n +0000040130 00000 n +0000040281 00000 n +0000040388 00000 n +0000040502 00000 n +0000040615 00000 n +0000040735 00000 n +0000040860 00000 n +0000040970 00000 n +0000041081 00000 n +0000041195 00000 n +0000041306 00000 n +0000041409 00000 n +0000041554 00000 n +0000041654 00000 n +0000041767 00000 n +0000041881 00000 n +0000041994 00000 n +0000042103 00000 n +0000042217 00000 n +0000042330 00000 n +0000042430 00000 n +0000042564 00000 n +0000042661 00000 n +0000042761 00000 n +trailer +<> +startxref +42988 +%%EOF diff --git a/doc/sdd.shtml b/doc/sdd.shtml new file mode 100644 index 0000000000..15f0b4f793 --- /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.1. + +

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.1: CUPS Configuration Management Plan +
  • CUPS-IDD-1.1: CUPS System Interface Design Description +
  • CUPS-SAM-1.1.x: CUPS Software Administrators Manual +
  • CUPS-SDD-1.1: CUPS Software Design Description +
  • CUPS-SPM-1.1: CUPS Software Programming Manual +
  • CUPS-SSR-1.1: CUPS Software Security Report +
  • CUPS-STP-1.1: CUPS Software Test Plan +
  • CUPS-SUM-1.1.x: CUPS Software Users Manual +
  • CUPS-SVD-1.1.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.1 server that +manages the printers, classes, and jobs in the system. It also handles +a simple broadcast-based directory service so that remote print queues +and classes can be accessed transparently from the local system. + +

Authorization

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

Classes

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

Client

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

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

Configuration

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

Directory Services

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

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

IPP

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

Jobs

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

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..764970ee1e --- /dev/null +++ b/doc/spm.html @@ -0,0 +1,4002 @@ + + + +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 + +
+

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..96b15a6e80 --- /dev/null +++ b/doc/spm.pdf @@ -0,0 +1,8337 @@ +%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<>endobj +37 0 obj[33 0 R +34 0 R +35 0 R +36 0 R +]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[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[51 0 R +52 0 R +]endobj +54 0 obj<>endobj +55 0 obj<>endobj +56 0 obj[54 0 R +55 0 R +]endobj +57 0 obj<>endobj +58 0 obj<>endobj +59 0 obj<>endobj +60 0 obj<>endobj +61 0 obj[57 0 R +58 0 R +59 0 R +60 0 R +]endobj +62 0 obj<>endobj +63 0 obj[62 0 R +]endobj +64 0 obj<>endobj +65 0 obj<>endobj +66 0 obj[64 0 R +65 0 R +]endobj +67 0 obj<>endobj +68 0 obj<>endobj +69 0 obj<>endobj +70 0 obj<>endobj +71 0 obj<>endobj +72 0 obj[67 0 R +68 0 R +69 0 R +70 0 R +71 0 R +]endobj +73 0 obj<>endobj +74 0 obj<>endobj +75 0 obj<>endobj +76 0 obj<>endobj +77 0 obj<>endobj +78 0 obj[73 0 R +74 0 R +75 0 R +76 0 R +77 0 R +]endobj +79 0 obj<>endobj +80 0 obj<>endobj +81 0 obj<>endobj +82 0 obj<>endobj +83 0 obj<>endobj +84 0 obj[79 0 R +80 0 R +81 0 R +82 0 R +83 0 R +]endobj +85 0 obj<>endobj +86 0 obj<>endobj +87 0 obj<>endobj +88 0 obj<>endobj +89 0 obj<>endobj +90 0 obj[85 0 R +86 0 R +87 0 R +88 0 R +89 0 R +]endobj +91 0 obj<>endobj +92 0 obj<>endobj +93 0 obj<>endobj +94 0 obj<>endobj +95 0 obj<>endobj +96 0 obj[91 0 R +92 0 R +93 0 R +94 0 R +95 0 R +]endobj +97 0 obj<>endobj +98 0 obj<>endobj +99 0 obj<>endobj +100 0 obj<>endobj +101 0 obj<>endobj +102 0 obj[97 0 R +98 0 R +99 0 R +100 0 R +101 0 R +]endobj +103 0 obj<>endobj +104 0 obj<>endobj +105 0 obj[103 0 R +104 0 R +]endobj +106 0 obj<>endobj +107 0 obj<>endobj +108 0 obj<>endobj +109 0 obj<>endobj +110 0 obj[106 0 R +107 0 R +108 0 R +109 0 R +]endobj +111 0 obj<>endobj +112 0 obj<>endobj +113 0 obj<>endobj +114 0 obj<>endobj +115 0 obj[111 0 R +112 0 R +113 0 R +114 0 R +]endobj +116 0 obj<>endobj +117 0 obj<>endobj +118 0 obj[116 0 R +117 0 R +]endobj +119 0 obj<>endobj +120 0 obj<>endobj +121 0 obj<>endobj +122 0 obj<>endobj +123 0 obj<>endobj +124 0 obj[119 0 R +120 0 R +121 0 R +122 0 R +123 0 R +]endobj +125 0 obj<>endobj +126 0 obj<>endobj +127 0 obj<>endobj +128 0 obj<>endobj +129 0 obj<>endobj +130 0 obj[125 0 R +126 0 R +127 0 R +128 0 R +129 0 R +]endobj +131 0 obj<>endobj +132 0 obj<>endobj +133 0 obj<>endobj +134 0 obj<>endobj +135 0 obj<>endobj +136 0 obj[131 0 R +132 0 R +133 0 R +134 0 R +135 0 R +]endobj +137 0 obj<>endobj +138 0 obj<>endobj +139 0 obj<>endobj +140 0 obj<>endobj +141 0 obj<>endobj +142 0 obj[137 0 R +138 0 R +139 0 R +140 0 R +141 0 R +]endobj +143 0 obj<>endobj +144 0 obj<>endobj +145 0 obj<>endobj +146 0 obj<>endobj +147 0 obj<>endobj +148 0 obj[143 0 R +144 0 R +145 0 R +146 0 R +147 0 R +]endobj +149 0 obj<>endobj +150 0 obj<>endobj +151 0 obj<>endobj +152 0 obj<>endobj +153 0 obj<>endobj +154 0 obj[149 0 R +150 0 R +151 0 R +152 0 R +153 0 R +]endobj +155 0 obj<>endobj +156 0 obj<>endobj +157 0 obj[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<>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[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 +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 +]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[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 +]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[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 +]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[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 +]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[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 +]endobj +393 0 obj<>endobj +394 0 obj<>endobj +395 0 obj<>endobj +396 0 obj<>endobj +397 0 obj<>endobj +398 0 obj<>endobj +399 0 obj<>endobj +400 0 obj<>endobj +401 0 obj<>endobj +402 0 obj<>endobj +403 0 obj<>endobj +404 0 obj<>endobj +405 0 obj<>endobj +406 0 obj<>endobj +407 0 obj<>endobj +408 0 obj<>endobj +409 0 obj<>endobj +410 0 obj<>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[393 0 R +394 0 R +395 0 R +396 0 R +397 0 R +398 0 R +399 0 R +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 +]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<>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[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 +463 0 R +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 +]endobj +489 0 obj<>endobj +490 0 obj<>endobj +491 0 obj<>endobj +492 0 obj<>endobj +493 0 obj<>endobj +494 0 obj<>endobj +495 0 obj<>endobj +496 0 obj<>endobj +497 0 obj<>endobj +498 0 obj<>endobj +499 0 obj<>endobj +500 0 obj<>endobj +501 0 obj<>endobj +502 0 obj<>endobj +503 0 obj<>endobj +504 0 obj<>endobj +505 0 obj<>endobj +506 0 obj<>endobj +507 0 obj<>endobj +508 0 obj<>endobj +509 0 obj<>endobj +510 0 obj<>endobj +511 0 obj<>endobj +512 0 obj<>endobj +513 0 obj<>endobj +514 0 obj<>endobj +515 0 obj<>endobj +516 0 obj<>endobj +517 0 obj<>endobj +518 0 obj<>endobj +519 0 obj<>endobj +520 0 obj<>endobj +521 0 obj<>endobj +522 0 obj<>endobj +523 0 obj<>endobj +524 0 obj<>endobj +525 0 obj<>endobj +526 0 obj<>endobj +527 0 obj<>endobj +528 0 obj<>endobj +529 0 obj<>endobj +530 0 obj<>endobj +531 0 obj<>endobj +532 0 obj<>endobj +533 0 obj<>endobj +534 0 obj<>endobj +535 0 obj<>endobj +536 0 obj[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 +517 0 R +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 +]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<>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[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 +572 0 R +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 +]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<>endobj +628 0 obj<>endobj +629 0 obj<>endobj +630 0 obj<>endobj +631 0 obj<>endobj +632 0 obj[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 +627 0 R +628 0 R +629 0 R +630 0 R +631 0 R +]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[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 +]endobj +681 0 obj<>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[681 0 R +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 +]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<>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[729 0 R +730 0 R +731 0 R +732 0 R +733 0 R +734 0 R +735 0 R +736 0 R +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 +]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<>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[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 +791 0 R +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 +]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<>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[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 +845 0 R +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 +]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<>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[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 +900 0 R +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 +]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<>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[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 +955 0 R +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 +]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[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 +]endobj +1006 0 obj<>endobj +1007 0 obj<>endobj +1008 0 obj<>endobj +1009 0 obj<>endobj +1010 0 obj<>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<>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<>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<>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<>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<>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<>stream +xÚìÏsë8rÇIŠºÌ‰öŒî´üt§çyšÝ­ÚJñÙfvçÖ$ÁÊ!•S*Ç6•üÿ±~X"H€èn$è5¦jêÙE|ˆÆ·@ƒúÇOßòýÛßò?=å¿ýžÿçÿô,~*ÅOÿÈÛÿù×?þøÛï¿ÿºÏÿü—_Ÿò§§§·kýñõ¥ù÷¯|­ÿöœþº?•ßNå÷SùË©¼œÊ¿žÊ¿üÇ×?òÿýŸÿû¯¯ÿ–ÿíÛ׿ç‡oß¾>ÃKþ=ÿãõ§öcøä²+âõi»Ý>ÜËÛ?¶ß_—Î%^¶wY¤*w÷¯ËäOj¤Üöû¸ē‰é½Ü?–KáÂC]о/ëå!"—x[ÎõœE¼r˜ë‰KåÒ!˜¾rÛg޹^òȾü\ÆÕÊÏ3s=GžJRÎÉõ-òVâÃl\ŽuЄõV¾ÌÂ%²( + ‚B¹ü29×$X,0X –€Åƒ %ƒ/° ¬(ÚMÄåÝoÙ9h6×ÄXo`å\ûhò’LÀõ#𡬼sÕÑ,åÏ\M6A!|…gi,A +Ú Ñ ê£s5Ѭåà‹+›— 9Ä`™ãÅ`ž‹,öD.1?V{àÊàŠRç\uD98æY\‰c®}HÙ8媣`Jé++D91WT蚐°ŒÒË TÔ  LÔ‹Š4ðZåªBÃ2t,OãQ ÔxŒsÆq‰±FãzX¢Æ#F,Ï%£FL×]w÷Ûí—×cy>|ðÛa0IwÅ÷_†ƒüxÂ[‡ÿîŠG’þÅ˃ŸßÝuoœ*=[ í,¸ö~ºªÛk[ça=xì.Bú±àæØ\ìPƒ–.Î$[q¹¸¡==·aMJ&³»XéԜ.K™\¬@ž› É貘ÇUùÑv‡]¶cqeSÙà՛eN¤ܯjؤ½s’  ®|²¡ÅϼJé\Í Xd°˜ÎEùØÍÉÜZ9ƹfÂ"‚­¨\Õ FÈ1ŒȕυEÛи'’ –Y¹0p7ñú¥uZj+Cg‘¼c,Òé« …«rÎX•½ÅÍÁ‘jÄ¥{.B J<—°ÒlKÃ7D=Ì:¸ÎåÛÁÉ %i=•œkˆàBf½ .Ú`Ø`¹Š¹2O”,Á W­Ç’ó ìÍПR4q‡ãÚa…„–¤8®´&1Š«žÙ#3ì€á«aÚz/8 [c¸²0Dƒ¢õ ‚«æfóuXiæ*B J‡íÌ\Y OjOjäªÃê.d‡%F®"°îBú°ÒĕÖ]È'½1p5Á¸dZ“RW\wá¢ÄÄÀ•6ºÐRVŽr‰» 7æw£\u€Ý…[FJG¹*OŠ…²¢d”+ (2$*ÇVå'ÆB ÃRåÓ©¹Z’ Wå“s! q5ÂÀÚÛ=W¢È£­ÔrAˆ"v@;-W¨jàLi­ã¡ªnè¯t\5-4”=Ùí§ž±¿ÿ.Ï´’T¹Æúù=¾aÀ +¢6(®–KH·Kh%ºÖRÕÓbQ®•–ër›®Îa‡Àà ¯Çé¹ £^ >ÜÌіœáµCrí´\MçùÖ 1£$UsÑys¥Z®³í%·NH)}¢æÊ‰Îkœ+ÑsÝ´BPf=ègŒàp‡åz7.×MÛk¼b”¾Tq5ÔÊÀµÑrÝD° ¬•T؇ô¹WŠçZ鹊÷G”Q&ß V<זByW¤çª/ŸÕPÌ1PRWF4C#×NËu¾×úü+ü’QØV +.A5C#WªçڟòáªÕr[¬àª©fhäŠõ\盽§5Rì•K,×êZ[Éu6Ž;êÊ12BªWNZ,×:{—'%WG¤(³ÔgO@• ž«x j®Š5K5†ˆëWC6Ãq®ZÂp ÖbI…Ó5 ÊFÒâ¹Ä»Y¨¹®&EZ,ip-â\9%pžê¹*֚Nè(; +\n£á¬5;c+\ŒôÅq®æ" +®K‰kvª‰@“¤¥pµ¥×qgéB™ÐdcMãº(½Ž«àôWòD@“ë¢ô:®Œ3¾êÙwCÅuQz WÍÛÃÈ0’ ¤h#!r]”^ÃUðûMÏ%s Æð2r•^Õñ6g +ÌÃ’lì¨\g¥Ws5Ì]Œ +㘁´¶ÑR¹ÎJ¯æ½ØER2WÁ^f®“Ò«¹rfæŽÀ8f DQ)ëd݅~^¹e¢IàkSYŽ­\§Öç*®³Ý Fȑ#š ”(ªT?º²k ±ÌukDŸ+?krN7Ä="àVÌµë>š>h¸Þ;а›‚]†Yw¹k6+IlºŠšô¸ Wuáiè†X!dr¸Ñ˜ÄjøCýsȵèÝJ´§•¸rŽlH[âã‹:\…’K\[°'¢@Ø¢C­I¤€]Ÿ«VrU×Ê=öEèà£ÃDïû¯´ùÖṌŸêsí¯#èùVž«áxåÛ-â;^WÈ\OÌɱonn0¾d=äª\ÝT”‚lˆ{ó€¼0ÚT¹WWojò$ ð\{–l lbÕ¹.¶*qeÝKž„‰×ñÒáÊY²Ñ˜×Ó{Šyq—KΈÚ{ÈhzªX¯üPy8Å:F—« »òúh9ÔNþnï5ùÒ*¹Ä€+“,¯ñª è¨Wo'ÍéŧñýGH©\SßËy°†ÇeŽæãvQ°2Ÿ,’+çEQÁse¼(*t.a#‡s5–r*W͍çª>š^¸ +vt6מ͕4™¿peM/\œ¥ùp‰'óg®úÃÉ<–k2ߝÎ-‡͋ó·•Ü:\[æ»uîªßFwÒ²ßmµwpœOm›.Ò,²Î-ï\·u›þà,•\×FÍÕI¿\¹r¶ûRãkT§×ćk¥äjÔûËÛ}©4fÜkbÄኔ\¹z߁¿h£¶W]nj¯‰;×NÁU UPn9Ár­4áËNŕr¸RW6|ŒŽ¹Î«Ëë51áp%C®wшﲫÝÊ-§h®š+Vqõó¡¸g¯r~ô'/ÙÅlp\ëQ®Ó¿^òHjÁZv,¥Šk£tEr<Џ¨ëdÞ7ÛnlÌ\—᯻?"éx@·‰+×à¢Zr—Ûj{‡àꤥÈ]|Ëíé71âp .’7.y<€ +£®[‘"K~­lâŽÃÕ¿(—óM +-áðì8—Ðpz®”ÃÕ¿¨7RNf™*Œj1\·Ùÿj®˜ÃÕ»¨ðTà¹b\Šã|f.ÅEußÁnßÊ#`ÂÃĞk¨Šã|f.ÝÀT5_ŽÜp ×^­óŠã|®áE…ÒÁ&ŒJ[=Ì®9·r‡Çù\Ër¥#Bq­Q\µÚ՚8JqœÁ5¼HËU;â*”ñÆË- é5qxœÁ5¼(S:"×Ã%¢"ÎSÇù0\ƒ‹´\?Œê´áò;ô¼RqœÃ5¸¨[ývGסµœm”MçÃp .Òr?ŒjÕ£YU4ñ"Ú4®þE\-š+Uý6.5MìçCqõ/Òr¹ê^,ÕMìçCqõ/Òríùáa«68Íòþ ‰ýã|(®þEY/Mõʕ;ãŠK W'T•šØ;·ãê]ÄçJ\ñ®óۋ_¾,{lÔMìçÃqõ.Ê;Š-qen¸:ù‡Ýxã¼ì‘ª›Ø;·ãê]4ˆ£*,WÚâæ)­Š«ó~(EO¢Må’/Ú÷#¢âÂùåªÇ¸äã|H.ÅÀn÷X®µW£‹ç¯AeNä’/ªúC%;s Ï\BsŠCqœÉ%_T÷$[DX®W;Ê.é"Ñ Í« ¸—|Q&°üÂeÎ=Üy䒎óa¹ä‹ +E2þW=/WÁá’.ªn»Ê·EÞÙ¹j—t‘è¶²¾Æ6ÓJ\‚Ã%_”ßö¿ž#W铫{œÍ%_T ö+Càª8\òE½H0?qÙL—Q\Ù8WÃá’/’gÆé>®Îq>ès¥”ºór=ŸÞa?bšK©;3×Cÿøšü²¡ÎæuÕ»ꝪHqPJÛ:k®|¾!çéw·§†u\y1Ô׏áŒF~™WsÛìø9QeäÚÉÔ—Pì(É/4¬®KüuòÈȵ™‚ TSë¼;Àz齺 ®u+ M?\™j« ºã “Òdúu\©l)^¸š÷§»nÝî«ko»õʺ ®Dºµ®êºQ(¾unڑÀ[v…².Ÿ«öÉUtv¬÷7ïÒqY·äsM]Õ2¿ú®òöNå“+ª›v^Ȭ©K㊯ۧoƒ8ñƕu—áòžÒߌ§©KãJ®£0qÙÄóҟá¦×VËIÚªº$®Õõq¼=™t®êöÓ5ä$mU]WÚ}tk;.CúáõÏÍÝ[ÙtĪ윑Ò×%qÏ]ÓÆ+W¢ûѧ“T<¶ÔçÊ/ƒô8„wÞ¸2]:ÎeO¹éÀd#©;x®ýåóŽŸ|ðÆuŽš¸1‘†‘¶.‰«¸ÈÐÑÒKo\—½Îûƒ:À:eR¼Ë¹¶.‰ nÙ¯qëë¢Z{þ⇬ã‹õu•\ÃÄÎEu¯G÷叫“Òkmñîm®¾X_—ÂU_ `ü`;®±}½n=é½ÄÕ0‹V[—ÂÕ\~<ºeK®±}ØByŽCš—ƺ.]_ˆ¾ç²Ú_ÚÌÒ|Õ¢¯Kàj/Žùô[\½,Ú¸ôdЍKá:;æ“[öÉÕyіL¡ú’9]] +×Ù1×'ï“ëý ì —J•l:ZÇuvÌõ©¾—1ïë9Sš\ùPÔuñ~ùäËãÿc—‹|¶—‡á¤¦ÒLrTu \ÕÉOnÙ?×­µ«^(u@Õ%póÉ-OÁõ. +‰vЌÕ%póÉ-[raß-Z‹ÁX]—x÷b멸n‰×f®^]×Ù1ŸEr”Ë&ûø*™ìе\cu)\o&˜4·õS/\²{ãb§®.…ëM2âúì-¹JÜú¡k¬.…ëØÓUt}Q7®D²­x”KW—Âçð±‰ËæÜM.ý9Õù±º®ê|²&±çڍO¿6ÝyÈJË5V—ÂUߜº7®ªÛŸûÞmz«Kájn³Q.›sˆçkãï·M­–k¬®!ž—Þ¶%ä]A ®qö¶ ©Ÿ,ŽÕ¥puÞ ë«™«õ¹F꒸r—Õ¹ìf¤jŸk¤.ƒ«´çZãÒmú¡ÿ VÑ×%qƒßxàjô +3àj¸ëQ2\ŸÊ(—Õû7䵘_ÚQ.}]—îý¬n¹:}l \Úº$®úêÓǹ¬²Þè!Ón”ØÔµ*–ïí¹Ê×ëMóU|–ïY +¶X¾ë“kz.ó떗ÉUüÓr•‹ä2/pÉe3aþ䚞Ëjb¹h®õ"¹Ä?-WºH.ólõA¹’ere0ðµü>ŽO®¸ö0ðÅ}Ïn‘\ðA¹ª Z~¯Ù\Åô²×å÷ÐÍULMÞá¾70¸@ªrÃ\ e’ºÒò{9ç*Š+[\Àa +%°ß{ZÀ‘›ì ù=Å¡­´e&=@~¯thG„â‚¥Âèo‘ßoXÀQã¸÷}ô•±mç˜Á8lc®Á9æ½Qæ#/Á9°Üè–ã‚s`™±Åš3‡}€²×ÀXcV@éK`3Ëڬހò9°ÊÜX@=€ÀXa6.@l`3°½9êT˜ËÍ"8á Kèmœ£ Jè„m®gƒú¡€S˜ „A:àª%ô¢©€ìڐ„>G˜ ‡bH}fv_ï\bAB/0Ò -Vè׋‘Ã]‡+_Ž V˜Ȑ+ A,0 +-V裥ÈaÜ媗#ˆ(Â-ôDˆ *âƒ-ôéBäpÝåB} Â(»‚-ôÇ¥€VÏP„#C̾:\ÕB")£œ· Å }ºÙHd.„Ð'‹TæB,Ýċu+_†pd8üƒ"âȇxà B8j¤—Â!Gl#´A `1Û¨«>BðÌØå +h)‚¸xí\Åú,(ÖCéÑg­¡% ÇÜ ýŽhIÂ1ó3?ú•‚+~€áï€d¼s°=z @KŽy>r’s˜y€Õø©bå™a÷H*:sˆH؇–(30Ê&ÐúyÖ9eˆιÈQDs‘ƒ²Ôā9£Ò7”AОQéI+Ò@½t>¥Ï)Mª’ζÚ&HšÔ¡9›!"li¥åڇkˆ´åhél¨vc! »ô™ ±¢g83âžö¼nų¢ †®@žâÌcˆñqCË`3Ĉ9qx@Ë`iˆf(Í4€ó`¦Ÿ¬Tԇ -g€M>kΩj-k€MœdY“½´¬6± +ÈcX]>±rz‹€5D'VFÔ +œéöÔ1GNÀY™8樼A:©ÔgB©œÇ Üϙ.H,8ޏÃtºc wàÊêd†kÍÁ…Tú‰:,c=càÔ4Æ €?R§é°ŒÖÛNÓaә_‚& :C¢Åqí±`»0ºk…äªé0‘qƒph­ ±÷UKó„ªY.´v†èuâ,øV­!zÕzìÓÝ ¹ð†èQ:j ›ÖÖãrfWŠØ ¬OKüñÍPË%¢¹-±±’.h­ ѓ&æV>¬­'BõÊXZ?Þ¹±´°öõ^†˜È,e \<1÷3–½í#×½{&ܸ¥rU¤s©ÍJÉ\"š LdöܹK0‘;¸)82‡i\o\´;¼•Ÿ'–‘P¬.t¬Â^¿¹1p1_uFÃÒÇàd}¡ãNSbé¥ +\EiW°/)áøf08Ô&[õ cœFwžÿf<[l2êR6W›qÀúßtŽ*OôÛø\‹+Š¿S;‹añcq€‰‹ÙaQt_zî¬ñ¹‘‘«ˆ¸ÿ¥ó/9k·6\"â—{”56¼OßYqYtØqœ=šÌñ…Ie˜>˜¹l:ìŒöªÿ짌ý¹K.ê4Li¯ƒ~/ÛÌæqµ¶\Mä¦ÜÝo·Û/¯oåe»}È,?mcÍå¢ÃœSþ#†KȵqÀe'‰³tŽ+¼Û9á +®ÃÌK_8.±´îBrvm¦(ˆ=$W›…ÄupÇU/«»Ð\¬•O_ºäj‚áÚ´.¹‚ÑzÜöžKdKÑxw gÑ q!Øý^ +—XŒÒ¸°DôÖ!‰kvKÄgиš…X!•kæø—°MäšÕ)¹/T®9½3eû‰Ê5c`OJš#sÍ6Ähi/t®™†1±ŒÁ5Ï#îí2¸fbÔ,%=pÍ`sM®ôT9×ÄÚÁÈdr‰<\)´ášRY©Ã\®éÀx™dl.FÚÏ$ŽËšk¢Éóā×þ9椰áòoŠü,M+.ß`ɧv\~UÑ&Yؒ˧ƒ¶Ê¶åòf—ŒoÍEΡö41qÏåcÚb™®î†Ë½,ڟ›pÂÕ +·¶øhß"7\o¶è®Ë’CW+Âé,—\ŽºìþІÆÕŠ'küâª-.¹ø©ÕªGw-qËe‘^Hݞ“‹Kæ–ʇìþ‹ë6øà"æÅÇ[ï¹ðÃõV^qÙññýw/·÷Æuê5ƒAÞm_}ÝÛ'ש۞¶wê~z|õy_ß\çŽ;žpØ>ÜËývûøúêý–“pÍPàÿÿÿârõä +äÿÿUA‚0E÷œb–š8•A»D… B=@•‚ӂ†ÛÛq¥›¿˜ÿߛô֙€ÀÙ¸d„‚mA֋C™dö§¢‚jhÆ·2 +3´Fõ½6rõ˜T·”w§ˆ€sRð áÈC„`¬Š9óϜ¦(\ƒAì>¹>Uvþ“×Óe´ß]²øG4Ûìó’endstream +endobj +1841 0 obj +6285 +endobj +1842 0 obj<>>>endobj +1843 0 obj<>stream +xÚ+ä2T0BCc3JÎår +ár á +äHÉHendstream +endobj +1844 0 obj +31 +endobj +1845 0 obj<>>>>>endobj +1846 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 +1847 0 obj +693 +endobj +1848 0 obj<>>>>>endobj +1849 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 +1850 0 obj +331 +endobj +1851 0 obj<>>>>>endobj +1852 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 +1855 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 +1856 0 obj +1365 +endobj +1857 0 obj<>>>>>endobj +1858 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 +1859 0 obj +824 +endobj +1860 0 obj<>>>>>endobj +1861 0 obj<>stream +xÚ-‹Á‚0DïûsÔC•ES¼ªÈͤÊúƒ±WÔߗ3s™7ybdc ›zŽ´šW+0CpnQää2)ëJ`°=¹uß ¯Nû«úƒ>±÷ÝËß§r#“<óm"K¶³¿í´í† (µ}ZzwBú©ð%\endstream +endobj +1862 0 obj +127 +endobj +1863 0 obj<>>>>>endobj +1864 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 +1865 0 obj +282 +endobj +1866 0 obj<>>>>>endobj +1867 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 +1870 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 +1871 0 obj +277 +endobj +1872 0 obj<>>>>>endobj +1873 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 +1874 0 obj +281 +endobj +1875 0 obj<>>>>>endobj +1876 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 +1877 0 obj +213 +endobj +1878 0 obj<>>>>>endobj +1879 0 obj<>stream +xÚ-‹A‚0÷ÿo©‹*’Ú­¨¸2¢Ô4Fc[l!^_kÌ{«É̋ÙwŒB¦_-•š–•3tÎ%VyÝζçu¥!°¹Ô ߏo:ÔÁ߂±¶ ã&óœë‰Ô‰ÈyB…R ‰8ãÝ»ãZ샟†˜„¦}@Î&Œendstream +endobj +1880 0 obj +131 +endobj +1881 0 obj<>>>>>endobj +1882 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 +1883 0 obj +278 +endobj +1884 0 obj<>>>>>endobj +1885 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 +1886 0 obj +193 +endobj +1887 0 obj<>>>>>endobj +1888 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 +1889 0 obj +327 +endobj +1890 0 obj<>>>>>endobj +1891 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 +1892 0 obj +207 +endobj +1893 0 obj<>>>>>endobj +1894 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 +1897 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 +1898 0 obj +221 +endobj +1899 0 obj<>>>>>endobj +1900 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 +1901 0 obj +207 +endobj +1902 0 obj<>>>>>endobj +1903 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 +1904 0 obj +165 +endobj +1905 0 obj<>>>>>endobj +1906 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 +1907 0 obj +172 +endobj +1908 0 obj<>>>>>endobj +1909 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 +1910 0 obj +126 +endobj +1911 0 obj<>>>>>endobj +1912 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 +1913 0 obj +167 +endobj +1914 0 obj<>>>>>endobj +1915 0 obj<>stream +xڕ•moÚ0Çßó)N4*Æy ê:©[Ûi/¶umú©òC3å9ɺîÓïl‡B(Y@ˆøþ>ÿ|¾;ÿ0 øa0sÕ7L‚ÁôÚæA°D‹ëyą †Õº¸ˆ¢oë2γÅp1?Ò6ʉC‰­”÷_ c¥à×F‹7qV*Ž0JæŽÃ<+J¹„qÆSqڒÃÎÓTÿæIuDŽ«CV¥¹^¬8âÁjåC ãq=i1:ÛÛúlfvw!WU*²²0 +SйO gâ³) óñÐ_Š"”±^CY®‚%çåçöØsTÛ¾ƒŽ˜å,J,î:Ä̛#•Q[Ž3·j}Êvç({ÎЈ*èM/ Ñ‚Gjò%”øßD‚ÁôtØS«;0 œË‡>á6=þpŽCh8­>g×éÓȬä×*ý!¤"¬í˜\Rb$Ϙ“›KɟQÏl\©7µV¤Æ!³ÝÄ79Ö +"—y#¨E?Jf£çޔZݙŸÛ›¹ž ñ­(+™ÕåµÉ_Õ^\S[:Sœ*ò݀“ƒ5Ûª;Õ´öÜh~€!ð(Âàdõj›¨kÆËXD¸u2\ýáé:9Ø4ßÄY˜T‘€w +„<¾oõ­Ö+!äuÁt —"L8†zïpa$?ÛËV-UÅåªû OªyIÌɶôr¥n —mCýÒu5Énâ zã&Á«ûüœÅe̓øo¯­66ç@Ûî7&õœÃbغ!#zÓ腢*âl{ÉuŒ«5á$QÌONá$%Ö,þkÞqðv÷âêíVŠ"O*õ¢|Ï(ÖñßÓëy]ÌrÁµ]`·×LàãýÍÜåËòI%ލÌW’§©|áYÅå`¢æM>>>/Annots 14 0 R>>endobj +1918 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 +1919 0 obj +264 +endobj +1920 0 obj<>>>/Annots 18 0 R>>endobj +1921 0 obj<>stream +xڍTMÚ0½ó+FÛ TÚ&D­*х­ºjU +ìm/&È*q¨hÛß±@P‚=Ï3ofÞøw‡Á/…ah~IÞù²ì|xˆF°Ü %Œ"/„庛T{}Ïe"²ÇbõÜ}îõ–/é;ä žoOšo…³ˆk#£ÎM*KcÂJ¼ÑÇI!u Ɏ+x¿ºì7àðæƒîàõ>žÑ]ıÚV¹¥vˆ(5Š)òŠéʀhL½]àöDèD¥û2-¤±L—â¬Øñ1ÿ +þэ<¬cD=ŒàC X\3{qft„ÁOh[z¿æa.kS KͰÔf +“ + +IƵÉsq¤‡èîV’}¤¥æ˜«/–¿Á ûß&ÿ¡…xüf*}±^§Žû,vŚ‹²RRŸ µÏ!¶`m}ÈñWY³ è• B(t•$Bë>pµáiV)áÁÏã(w„R¦+\ÂJÀ¦¨äVqe©Ü‚ô[Rj fX\L;ß¹.§ÆÍaÔ¥±',»^«ú>E13ºÌZFûèÝd‚FmsÓ{‘¤›Th3wíq§x¾ÏZ¯w©L²j-à“ îí>7¦üúq‡ÕêQ”w} ×f!Œ3]´J˜1$¢sˆãã¢ÖÁµ.hxºÏúu1%¾2”VÐñ¼Ëq| +Ù¿MEöŽxH3qME£ú3·X-öÉ|ü°„Ü?Ͱ(6å+GmÏT±U<υÒðƒËŠgÆç€²³³ÏB³åÛ>>>/Annots 22 0 R>>endobj +1924 0 obj<>stream +xÚ¥VmoÚHþί龐èpl㬴•Ú&i#q)Gœo‘ÐÆ^ƒ+{í®×¥ý÷ÝµM Øp:@Àzžyæu÷ÇÈßø6L=ˆòѧptu€åC˜ Äó}Ã0GuYÝwiF—ôGM+ñ<~¾¸¿k´£Ñ×4‰~ªÈšj© A#´-­*-˕€K)Ƨ–iÌz l„PHùû÷Þ¼µ\ï> +V ˆ6„ËMUQóˆþ·] ’e$§Ï×o"1jg?òuS&*pÁ²$—šØ¾W ’+° 5àãZE<-EZ0)¹ G¦ab¾º¯åpfˆv©¶iØÀ)<ÁZŽ´ªÁvàÁ+´Ê»Ó°s¥&gf¡iÈðKû;b_Ãp!#Áh$Ɂ( ¢ü'åÆ ž¾‹*Ïå©ÀGxjvž%™4ÙÞ§w¿X@#€˜rŠ•ëæÙ¬¸—•ÓN[PGâ֊@–$‡Å·ÇðÇ©ƒŠÏå¨À½ñ‘*Ͷ|÷9ÊÔ e1lS±Qôºx>Û¶Ö¥2~xšÏõ£¶zÆP)”Cš+5ô¤ðÎrÒ¹Þ)ðÑúÝõßÔóu"–TԜUû å0òtëéZ©JlkªŠ0!g¸ˆ®‰ 풐4« øÆÔ¿)I)åµE„Á‹Ìt}ùë,KÙúMH¬ÆM\ÀGƒ 9A·È´—x¾†S é¦•ãtN*q+)´³ú ¤joç’Ñ;ÃæÐk{]·]Ðâ‚V@@µÁ^UŒLɋŸiŒ¹×-,……²Žû-Å픞6¾Xm8b¡HP{Òp«¦™Lpš²ª€ êËÐ f½~ÉS!0{¹Td(ÇÎÌ¥¨$Uµ-x|`”Ô¸‡‰4"j’ +¥1ûÃxû‹äeÖ{,þ•²(«c +ïd,Í‡ƒ³h°^,ÏÁïóéЋÞz‘h·ì+q¼0š£O½×æݩ*U7¦ÕbÈ´ëì +t•¶îgp)Å5Þ$Np¤Ó9`—´‹!ÎTW¬º/ :ß]&®R¡¯FOë#ùzµ4 cpu _¨P•ӄԙ€Ö¸¼:w’÷ЕuË1ìò0W‹ÞØhülwߛ£‘M¥‚Œ•ßµyÀµÏœA±=Ýîu÷×ZÁI×W՝eÚHY-†]s<]y˜½ºý5$'š?FQâ‡r5 ViŒäÑÉÕbyÿ®îîç·Í qÖÌBËöÀS19_—ïB˜Àç§Å#<‰Ø<@¼Xs’ç”Wða5É-¹sâÛæàÐu|yPÛo¢øï責endstream +endobj +1925 0 obj +995 +endobj +1926 0 obj<>>>/Annots 32 0 R>>endobj +1927 0 obj<>stream +xÚµTmš@þòI/²î¢\s×PßjâyVñ›É…êúÒ(x°äúó;+,š;!^Òªfx^f˜× +Š_¦-ËCå»Wiô)8à­ñ†Ýn¼U5⯠…þ˜ý!á‘d_v+xöµæý®PÐ%mYó.l܁»Z¬ÚE|¾ÑîW"x w ™Ûó*”Pä#L¦€Ý4ñ°-<¥Áf’ê»üh#97­pw<"à Q‚͉KžL³äêB «Ãp2yñÜÁËó¤7u½áóø|©óÝÎz^ý ¸ühg9úrëG1ZÆóѨ…â ƒ e™(ò&mI}§¨PŸ*±$ƒerŒG~°éËpU¦rI‰¿á‹Ú¢vj“ž>§¨W—ÖÝæÑÈæî w³I/’Èß늚r«¬^å—‡S2|Ë/éùÍ{Ð:Z¦“þC‰óé°Ú ô$Úi¥dÓÞkˆsßhlÃXþ7"‡I´äÿƒàØ}ê!b–Šez#S‰{ ÕÂ1eÔ 64ÍæiLYÓΣÂ1U%¶Ó92YTµ¢ÍÆ2­+Y!Ý˃ZC„dËã" ->†AÌq'IänØßíù4-XT·BëÛ©;‚Á3¥]DüªC¾ÌJ÷¡nšä$iÆ9¸û8,Ý[–%Å cÌÀ-šF…ŽÉ­ËX +cYŒzÁ»|í'{¡ ¼Þ%Ö"­Ó0mÒ,¤9¦•a*Šn: e$?ìžRnò8ûaÒvÝÀMIù·Ë»ÊÉdfîrrbÞÎ %|Š‘œºN|)Šß‚óã«õòÁ2\Þp <¥ÁmseRb}Ü-%&9-âäp¬Iå„]Çû("e§ o0 Yù[™?me¿tÞh;©ÿÝ©Û÷@‡Î|2ƒY¸o~Äa…›È?xÓ$þ>Ý0Ae¡Ñ–—°@¯¼Ô?+¹µ@gendstream +endobj +1928 0 obj +727 +endobj +1929 0 obj<>>>/Annots 37 0 R>>endobj +1930 0 obj<>stream +xÚ¥VÛnâH}ç+JÚÇ6¾`±;“0¤LÂç-êØ xå ÓnOvÿ~ª/6 Á&Ò&q»NwŸ:uãçÀ-ðm{烯Ñàú[–Ñ-žïDÉ0®÷Õmҟ5­øóðùâ"úG!…¹¦áäSE¶TYM´Ñ¶Ô1é~¿æp)ÌøÖ2É‰ÃwœK”øu…w?ú8¦vöc㲨8Ä;ÂĆª¬YLŸ/¦üÕÛÖ9-x¥.X–@¾á¢?¾r¶ ŒX†'àë[ZÅ,Ýó´,„e LÃD¥Ûðœ ¢]Ó3l¼Û5°M|dV'ÀVà +…¶1î< eÈMÏœÀ,„~’˜<^ûEK¡DAcAx e¿(3úy:Ï0?ÍS¡OðTì|KÅG‡íˆâb¹m„prŽ™çâiŸf&ѝÌ\¦M~œR¯±AAr +›’Áòqc‰‡xŸg)Ñ'ã|HÔq0Q2†”׬ÐiÚ䁨9O娴ÚcþS©( ç¦@zøðtÿþ€!¤à;ÚÆbCÒ¬2౐O5RVÊž“^„u‘À˸β´Ø~ÐÄÒnâÆî=Ë!ÚE¦¼<³-˜ +h`ØM׸'Ÿ +MK:’Tîm]2:‹ý¨`ßÞ×êØÑ‚%%­€€Ì‘­tUÙ³òWš @¨ö6DZ›Wºa[²ªlÚÙXù»Ãc2<cY¿ä)ç¨ð»Ék(Ô̅iOªêµd QOc"kžTPPšÐ¤[Žù¿$ßg]ü´ˆ³:¡ð§ÐÄØ}9j¼½q·M÷±²ªEgÜZG[ …Ó!֝^ŒiïåV w˜CŽ^ô\na‰µ¡_g¤Øv3¸æGߨ=$€¤Yô˜øoæf¯óíœCÍÈ£úÀôDÄÞ, Ãè\_Âå2ûº!uÆ¡ñ.¯À­å/èÔFÄ“! û°­Wêèöá+Ä=Þs«Øt·ƒ¡t}$w÷xwÃ(᫹ ¯ïÊõƒwá¬w“@¦žeÚS¹è÷-Ð_¨0€ôõÿy¤I޾è£Üãe²#¬ÓÉ£“ë»y´^†‹‡h®gQ.¾>EóÕô‡éGq”PšžÍŸY’HQSF±EqÎҗšc{Sw·G֏çÈ9Þ_>¶ÛVÞ¶Â+ÔL:¡ásãՕ"šÝ­—óp-¯n¾ÏÂÕ<ºRq¢;¿e{àáà–Ѻ gß"ÁÍÓr«rÃ_ ŽÊ%+·Œä9eü EM23±säÛfçxq|᧴ہÖåïÁoŒøendstream +endobj +1931 0 obj +1006 +endobj +1932 0 obj<>>>/Annots 45 0 R>>endobj +1933 0 obj<>stream +xÚ­TÛn›@}ç+¦<áˆË.`0©ÒŠÆYrׯoHÅk슋³€òûÙ5§vL©€Í23çÌì^ ˆÝ ‹?a"üðmŒÀoË>X[ÕÁÛHðþƒ¢ ûßeAr%Ü4'…(Ã|=›ÉÐóþ#O@*b‰ù‚ù²œ€®cÕd -–0Ùê ¶bXqسµ!5‡°<ä³ Fi˜möiÄ¡NA¨’|)fNe¿ç÷¾r/¥Ê¤`Ä@Y¦cäÉÜîf³b5¥‘/QòR’¼aºX<{îäùi1ZºÞôi~ښ¹óÉڝŒä³LW۔EIƒXi¨5ýêŠo|áËÃѾ·[Ê·öã=ˆb]'ú%®—SÄ (UJº;ÉV§/2œ{MÛey‘ Ñ(ɳ’†äßµ;fPìÔäTU…;í̋å;diNฆٲrö¥]Qdh / µ±جd­†jñ|+BÀóìªj™}<8jc½+ëªfùð`\Áô±ó·r‡d”1cë÷®"bl«v‹©–Ú¿†‰ZL³Æl(Ö¸Õ8v‘¼ªNnº©¿ë‡­u·¦”Ïq[ç„vr2°ÑvˆqrÕ¸+áSŒ¸Ê³4%a{ˆ]é%¹[X¨Ï֝ýœ*ã6]!ër¦;ZäØªÓ‚á>âúúí²„š›ucƒ§9yíêÍ i=AOäF.ݱ +<®+XeÛâ5 4‹h$„æð3HË >þ˱nb눈o™¦èƒqþ%¼Æ«ïendstream +endobj +1934 0 obj +596 +endobj +1935 0 obj<>>>/Annots 50 0 R>>endobj +1936 0 obj<>stream +xڍ”[oÚ0ÇßùGÚ LÅØÎ]L“ØZúԍ•ô ©òÙraN²®ß~vœMM"âó÷9?Ÿ‹ÿŒ`ù#àP0l’Ñ4[z@ð·Òb;²ÁÇAyȗ‚óï‡"ÊÒ|3ÞL&þ/­5µvjad*íSÎv\[1xµ‘íèo…Ê&—Fn¯ï(- -“çL/Ü´ôÐzÔþZû\ÀÇz×f2oíë†fZˆ]™ð´ÈµÂB”‚`9’ÜÑÇjTJD<"MX-ßò<QSYîüFXfõøz¼ӕj ۈ±12€bùWpX÷ˆ)ö®Õ”zoÔUy̚ÏR ¦GÅYº*¾*JÅ÷­L~rÙj;D)0!Ø+ºÎkº¶äÊ«Õ=¼šÒ!ºýŒ«L–\BÙr¡mI¯ƒ +uoFO=a¯§¨ª‘uÎU'Ûº.ŽDSŸ1l¥Y%Ž!áI&^åyD¬à!¼DÅŠ=¯O¬ ùÑ6â!ºØ­wÿXrˆ/؇( â2äðIÎÔ í?÷ŒÂÙ§¸ÓsÖKóžQíŽÚüºw„ÐuA'“çÃoç¹7%kÎaçY§]HÝXõ&VáWZóëhéÅNETRrÂ\„¡¦lÊÝÎ¥È:Æ#–j˜ qÐqNqn ÊOª¸çÅbä ¨œòAƒ9⁉߭¶ïÅ –*PƒarÞÃhX‡`¬˜ÈÛã×õ8[ºu-§„RéÜ".ª.ÍÛÇÅ҇)|}Z­am‹&Èv‚% 9<°´d±ò+÷Ú0u(¾2ú¦cJêJa:)?Fÿø[Ýâendstream +endobj +1937 0 obj +623 +endobj +1938 0 obj<>>>/Annots 53 0 R>>endobj +1939 0 obj<>stream +xÚ¥UÛnÛ0 }ÏWØKÚ.ªåÄvŒnz5îÓ: ª#;|Éd{Ý0ìßGZJ“8q7`I`DäÑá)Òßürûô‹óÁe48½ %èñƒ€ù-†q³ªîd}•‰ª’Õãðñè(új y›ô¡©4^Bët¹áQEM.´p‡M1ÇK¡áøø8¶†£³½Hã±!»Ði“Ë¢® ÂÎ ú/0bÖBð³÷£ùZV±V«Z•yn¢ÃLÅËãþ&SD{H4ÅÈ. Áu˜ ZÂü˜¸}‹v'>îܠۜN¬84xܞÀ²UׯhÕÍJL“ÔP—@Ù1-VÖ(´?Ù_T;T¶VÝ¢ªÞ$}âÛzÝ˺хMùúTTaßd>>>/Annots 56 0 R>>endobj +1942 0 obj<>stream +xÚ}“QoÚ0…ßùG&Á4Ò8„hÓ$ZÚ>Mb¾åÅK drlf;°þûÙ:Vɑu¿œ{|}ò»Gڇ '(›Þ]Þ»}Ì@Rä+[IÒ4HWý²Ýê'fflE[nŠ~1ä¿<:òèp#‡>kºf¾";#rԑB”ªðÉ1¶DÂ`ò^‹¬«bðå¢O{©3­Ú×G äÔ*ñ>¦ØÊZ¦`$̆¡òÊö­M-¨©¥:ÕgL—ªÞ:èt–‹]C9™éc͌îꍭòö¤BÉ©Öò²ÖÐF*V¡ §¹ÅAä\hc¡ÒVn **ìkÎñ“Aî˜Ú«Ú&Pô[ÝRÎ_lÕlž4mv”·¬€®œFË J‹uæám¶¼ó‚?Ô¢ämÅðÕMçÖ-ÁæÛ›«~³= bUôo®œÿ£. +qó—3¿–‘%c˜r-ð÷ ´yw qËâÉmG±õÑ u×ê7Ëwà3 Á„ÙUú h@ÆY0>Ãï.̨5ÎcG£ÿ~‹{—¦Ý_‡0÷Ò§äýS _'GE%ˆ³±Ìl1}Ì1Äýó|‰¥\™=U s%׊6UÄw*lZœèÐ}9L£°;ñ£Ôy=q|õÞ_q7¸endstream +endobj +1943 0 obj +483 +endobj +1944 0 obj<>>>/Annots 61 0 R>>endobj +1945 0 obj<>stream +xڍ•Ûn›@†ïý£ôƉâ Ë¥­ä6uT)iҘÜEŠ(¬Zé­úö=`cÀØBÀþÌ|;'~O(ø£`¹âg“Oáäbõ \áŠëyą0™Æõkyͪ»×*-ò§éÓéiøS)m¥œ9±…ò±ŒÖL­èE“j3E^V¿D΄—¨Aümeeì¼#‡½#Í+Èë칐o—ÇÅ“V>Wp¦ßy:½ìíɲöœ¯ëŒåU©P*ƒæg¦§6ވ„†”xh_±2æ©ô!V¾„ƒõíéálՎá}›ÄÓÀKÎ`9 ¶M­6mÐ–Z¦ÏÖxŽ`°SPˆJ0i^‚…/ Äc(VPᵊ9iû.1FC*õ¤Bó¨JO+sCŒuöƒqA©5˜m qý{‹×9Í+Õy]ŇYÂQh¶ƒæF£Iõ`¾wk¾Šè«jžërmêAô¡«k^ ì kU´’¢MÍJ(84¬^~{¼¹Ù·6…´]7–$l•æ,!{©Ó;-¼Óf皫ýIÿ«”ã¤(â¸æœåñ¶žEm'MUÃ×!Ø47u‚*UQÍÔ°ˆÙJ³J¦XÏ!—&´èDqnÃшï4¼{¾'òò±3¾:·bØíŽVó\ŒÔþ ë©v“3 Z]' „H#ð:‰<‘ÏOÎ÷f5ŒÀKÆ`¾)‹^GQÝ$†˜J–è‹ ð›ÕÜlTtô| í® U ´ó$Ù/»Aw¾hÚÆum,Û íÐóv~Îeõ¡$À‚3v§#r º ¶ ¦ãÞtÃЀŽÁ¸ø¯1¦K[¡°p>yoa ëHˆûˆ—Ý`ôí],|Kl]_Á«‡ù"„|~¼_²XU#š÷¼Xó(Ë/á6Êëh#¬Î¨éÂÌ3å$·lñÈÆ/¬¥Fûà<Âp|ŸüÙ°^+endstream +endobj +1946 0 obj +742 +endobj +1947 0 obj<>>>/Annots 63 0 R>>endobj +1948 0 obj<>stream +xڍS˒Ú0¼óS› ¤‚°üv6IÉ.{Ù¤˜àĶI„ÍßG²dðòJŠ*ÀL3ÝÓÓó«‡ÁQ/ ‘ ^«²÷9í& àÒµª„Q„BH³þjW‹'*§Dˆ=ãÙ²¿ Òëì0p¯± A6ÔTHlÑŶ«„„Õ–px«1ª„_äèbkÎÊZ.÷g´žg:ùfWÒJ +ƒcHä)úÈhkAƒŒ"ÕAýü@ŊçµÌY¥+iÏA޲æð6{?Vè@5Š7F¸rS˜_ãD ÚUÿÄtã±oåZC€í fÊF\CшK·L$ƒ,uAþè¯Rv‚rô͎^âknÐ5M÷C»³•;^YËۙôºCë7Ô,¯$å­ÞÚnW= {"€ê2̀qhCcÚô¿-žŸ_wîC¾†Š»t «É8Ù#ôjÀÔÖyaæ0 ’çÕH•?Åa%°V㐃Né«Ù鋄\´ù÷”ËJBÅ$ÐՖ)/N—{q¬ÇRÖÅÕK{“W«b—Qø gé7´ýtrs§'hnÍ꼿 FÝæýgöÞM J5Ëë8õþî֍Ï)…q!ØYà±Í°zëØ–„êÃ<&Â'x¾nhqŒÍ"´Ø9å¿)ocp‘+ԧےa|¤>cs,›UdiÞ5y?×Ôð/đý¼Ñh[Ùa¢¼¼Ø8þ0OR—Åts¶–{¢ÎwÊن“²¤\ÀWRíH¡»±Â0rñ÷#_5n^`øÞû uˤ+endstream +endobj +1949 0 obj +607 +endobj +1950 0 obj<>>>>>endobj +1951 0 obj<>stream +xÚ¥TËnÛ0¼û+éÅ.`F”eÉAÚ¢i󸤅›(‡¾0e±•H—¤âæï»”(Gq-PØlîpwfgµ¿FüP˜Åî›Õ£Oéèðühi‘8IH i>ʍ¹àv¹<]W“Iú£ƒEl:Hä`7†­y àÈCês(i,d%ÓðÖa0D²ØO?„m´–ëÕäøIÉÙ¬Ëz¢×MÍ¥5b”: b¤4 “ŽXr zDI‚)ðø”›L‹JºÈY: +H€-Ù=®. Z zމ@cW4 HšÃõ3à†dæÑa“`€n{y~sÇaN½¯³e×ÖhÙ¥%Éjª‹¿=Šü…jà<ûgª-úYª͎bïÓ·–¾Õ½gqܵyȘåõFi¦ï¡4Ö2!…\·jÐìî\ièG¦K8þzsyù¸ÆÄ£@ƤTn9T*c–ç.M®¸<î§k†zUÉî8Òé ’gio $>÷&<°\sk°T¦6÷½k;2´¾AùÎLHªÚÞ¡4§Ë_Ç[õžž?pšû?Ke¬»@<¼gü]5`JÕT9š[+ìÅjÜÈJȟ«Éc†¬p$îÏp r%94Æù%lÇÓ¡ZŽÂ€±J£!Q¯±ÌŠ n›¢è¦xÀ–ɶ¢ªZMw\oµ°–K<³%p–•(£VíOÁ«~Ùij߬ÞT/n¡7BfU“sxçòº)?ìí£ýõÔ-£M~ü:Žò:SÀ{ +{jŸ_vÿQśëªí6ç¢ß‹a ó$ꀧW'ç)LáóÍò®Ua·Î÷¥VkÍêšk_˜lXåRLÝÍi¶›i»£ˆÆ„v«ê©W¸ ¾þä=¿endstream +endobj +1952 0 obj +661 +endobj +1953 0 obj<>>>/Annots 66 0 R>>endobj +1954 0 obj<>stream +xÚ¥UÛnÛ0 }ÏWØKÚ.ªåød+ÐûӀ,qŸÖaPÙÑàK&Ùë†aÿ>ʖs±ãnÀÀŽÈCò™o +~)ø6Œ=X¥ƒ›ppù0êC¡Æó}âA¸®Ê­zäÅLЬàR=ŸÏί5Ö©±#×"ŽÆ>)óZkÁÄ(mZ;B{­B µHpÒõjÃ$œŸŸoÉÙ´k<®Ý]˸LyV¨á¥1ñ0¢_Ói A'”øhâ;®VRl ‘gZs,ba5vù#8¢]t`d›LÀ¶ˆ ’ÃâXûö Úv<´Ü£«²:†œ«9¸ÔdÐdYÑ«‚Tôfy%†"]¶Ò‡­2)ÙOòږnÝ?Ó®Ð'iï«îx¦es^”235oÒÒMöꒇY™.‘jÉ°y+`ߙHØ2ᤷ¯­îè›Ô‰Ò{'FCˆyá ªÐL +äµ ¾ãC@ó•UN|]Ô&/“5,9D’£´T"‹µƒl¤­éhÜ)/ž(@(ÈrHò,ÆZd蓯ûó¿ÿÁÒmÒ;EoD¶JÊ5‡wº—úA6W­Áj1Y1=%Å^}iªÑ˜iìS·Ž„×‡¡à=tzø¿þEÏÇA®Àª›r€úÕ:D¹DC”¬)Ðú#7ZxqÑqø©ß?‰Ïfaõ“lÛt ~÷ތçp¨¼3ýÔ 4pœœ‚¯'¥úÍ~ÝëS(.ŠW°{} +Ô ðÎïÀ72†ÃÅàÒ£‘Û„)Å«}Û܀;±2)šjí©Ê_`üQÛÏ ê%p7¿~a·O³,ò¨xa¸ºf2%KSÝÿ,+Y¢Ž´åÈ·­W¶‡ã;؁ +1öM?þ¨âSendstream +endobj +1955 0 obj +663 +endobj +1956 0 obj<>>>/Annots 72 0 R>>endobj +1957 0 obj<>stream +xڍ•]oÚ0†ïùGÚ T#Ä %DÝ&±ªJÝ֕TÚRå&xrlf;tüûÙù`|„´ErÎëó>>>vþt¸æ‡ÀÙœu¾FÁ,@”šÈ(œDI7Î×êóå IqÎô¢»èõ¢ß¥vXjû—®3´Ú'…—¤ŒºVAU‰Wâ–pa5&„\gÜè±4Yô®NŒ|¿ÌõHt.¹*ãC@¨ö• X Ê5‘ è¤Ì ̸ä”–yl’ç¬É Q±¤kM¯×tbt¶:5TdÉ +¸ÁR!ùˆš¨©ª+ç;žõ7 +ÊI/Û"Í!g÷~òýö‡ð •‚g„kØ`Iñ 3nwi1_­ILSjî,c̹ÐðB€‰k2B^¨~Ìï~-ºS¾dT­½b³Ð+’8•².Ý5fì¸.çLÒTK³›© æ[ÈH&ä°R"¦Ø+Õ«¬¡Ð¯z+rÀfÞ²ïÓ¿8[³³}üò˜å O–v°Û±Õ—£®nhòg«~ÖpQϺ:9ŽÓže·´ÏÐÐ{Wí“ßÌ~XÿÚ«í$ÎÍnL˜V0:®ãš{Å>}<ÞÚxîØ¨3=ǯ æöÊ9ÒË%ìŸgÏ /¡)EBù²îFÇ00‹©-QÐâéVžWeö±èÊS²ÿÕa¹éï6ì3xÃÀ´ü 5è»!öŽH#ƒwé9áŽÁGãÝè,C ú^†[¢[|o¸[xC½]†šó½s-÷úá4ß`6®Ú©B[KT}¬n'³úpýô0‡¹Hõ«½¤XJœeD*ø†yŽ™ÍÛGÞúçډþؾòM›Ùèù€)ÉÏÎ?>@ù!endstream +endobj +1958 0 obj +654 +endobj +1959 0 obj<>>>/Annots 78 0 R>>endobj +1960 0 obj<>stream +xڕ•]o›0†ïó+޲›¶ +.Æ|u›Ô­Mo6©kè]¤ +‡0ÈøÐöówllÒA¾–HDدÎyÎ{|œ_ +6~)0’íäK4¹‡@ˆÖ¸ãñ!Z]%í®þéc‘”«¬H—WËëëèg'v;±åÙĕâ×:NE·kC¨7ª#mâ +nä..R›ðÃáåÊ[ŽKo ÜÈßc.¯ïFIëâÞWi»ESw +(• +jË +,'èЌJŠhHI€!pùAÔI•횬,äÎc4±‰Öô—'p9ª= āú>qÀ±ñQ X;Ô%¡V;Ãä{µòØÕ|ždð¨.ªðT…m˜-¨›ªMš¶ä ªªübT¥>ˆº7Ûõu¿^ÚjSŠl²¯m†]™¨ )¡Az¡+éñ‡mã ò¢?Œå +ñ¡JÞ[×S´µXÁº¬Ôv½I¶ÎpÅg HJ`šÕ¥Å¹Zt:3'–¡7È0m›µÅ§¨l’ãÕ<þ‰·»üè,|Ȋ$oW>ʒnMz²ù<˜ã2Ž»¡Hšþܘʇ"BÈéT½wŸÀØþ Öq›7Òõa¸Þà½zߤÁÿ… 6¯„:èüB¸Ïër4#T{|Ê|n3BõKޝú¾Jáý9§ìªw†MǹFú'Ú:¡†R™f  AíÉÛzs€úï Æ ;G`0/DP½9Aà¸Lޝš€Ù!^Rg æeOâtõpx{€ÐéߎÊËêr3 ãh·s®ÏE¹4Ããê2yx¹ŸG`Á××ç,Êuó;Æë÷¹*Ó*ÞnEUÃ÷¸hã\Fµ¨ƒÿgcŸº ÝÀÅèJÂBíǏÉ_»zQendstream +endobj +1961 0 obj +665 +endobj +1962 0 obj<>>>/Annots 84 0 R>>endobj +1963 0 obj<>stream +xڕ”]o›0†ïùGÚM" Çæ;Ú4©[Co6©-ô.7.8„É@fL۟?ŸòÑ*)i+Ò±_ŸóøõÁÿ,Ô< Ü߬²~¦Ö*^ !ݙ™ Ii¾ÈºCû›×E,»v¿]l—Ëôo¯ôz¥íSâ¡ò®å…èg)¬‡I‡õiš2Ç93Ä(‰ÞȌŠíòÛIz×í3\Š6SåA—M=al¬ô3°Þ \ÀN Ñ—¤‘uZ­ºLwʌë=×°çQÖd\‹œÌBmžxu³»þR֙ìrߑl5Ö$ûG^…„ó‚“Îû–²mP°I-J¨9yü0üÜ^anè+ˆ\†@B‚Mq¤W¼ø‰ëŽœ¿;ÞI=zÿfÁ(2dcEá–fJÒ¡ä€5Ôú +Ïnœ€M›:kò².ÎR°( î„áøÁdÃ,ÆÈúQŽØtÛY'`ğ\'œ¢Yú ‚+qþ(\Ó%/§ïÑ5Y¿0R~!ÑêÕQœæ[ÅÑÐN¶CŸíðÆ?þö"NÁ†_w× $ÍN?r%àZ5…âU%T xÝq‰ymæ`‡ŅÅ!ú¯¹¹{Árcý-§?Yendstream +endobj +1964 0 obj +457 +endobj +1965 0 obj<>>>/Annots 90 0 R>>endobj +1966 0 obj<>stream +xڍ”ÛŽÚ0†ïyŠ‘zUclÇ9i«J´»ìM+m—ìÒ* +&¤ÊæÐöñ;Nl@$„²çgæ›ùGþ=a@ñÃÀã`»瓯ád¾ €yn1âzq!ÜLãv_ŠdYI¹ž®g³ðW/½Ðr(JøVG‰ì£ä¬Ïò§L7*†WŒ˜XÞ3<¾7ðQý¶˜m={”³í>ã¢JÚ\MÝ+`L)‚i,îõLF¤4,`Äà xý(ë¸J÷MZ*òN(¡8Ã×ë3Õ&ò±v€59%* «1 |bk5x{¢î+4ž£¦{0}vx]‘/ÜI0!¨›ª›S5%lqVä2UÆÝÜ©G‘3®¶ìlnÊè¾-å´Û||_LÿÓ®…l±ÞË8ݦr3Ò,¹èûÓ¿(ßgíCZÄY»‘ðYÌMf²ûr¶~#Û8Ø¿‡3!äv–có÷¬ñJJXdu90•iŸ:g\ÖäàۄéCÖÛt¦¯8ÎZýÏAé ×£ÜFmÖ_F ú¾Ú]‘ùª³ %©.©±t­OÐ ev€x*âr“ÉU +滸žƒã·0 ë½ˬ­wW!¸«–Ú@Ø6?œ.BÒ{!žåu7lÛ;tžƒ`âö 罫¦:qc˜o¾ôõFYœªGè÷àu± Á‚oo/+X•Ûæo„ïÇKU&U”粪áGT´Q¦òZŒ»`yœ^z$„§²vaÁô<~NþP]¥endstream +endobj +1967 0 obj +569 +endobj +1968 0 obj<>>>/Annots 96 0 R>>endobj +1969 0 obj<>stream +xÚ¥•]oÚ0†ïùGÝ TÍóºMêV¨*mZWRiHUœ)q˜í¨ûù;Nœ”–@‘&Eâ×ç<çËüQ°ðCÁñõ7)GŸ£ÑÅb4€(Å?ˆÑzœÔ[ù5æÙ S«ñj2‰~·:·ÕM=‹¸Z÷ ㌵»Ì̦MŸ<håQÁ¹áµH¸ç ©¸Tlbç<.Ùjr¹çÑqZ£W"«KƕlPªÔ +E×AËÕ©´ˆÎ( о¾f2ùVå×;óhd SÒ/÷7à†¨öÐPÔ÷ˆ ¶…‹`°ÛÔ!3£¶m?«›Üº†ÏÓ 5Aè ´ÆAƒmè×P¥ ðwQ%qÁȘ–®×ɘzó9Ñ®o*tÏT-¸Is†®®oR Û*çŠ PÄ ë\c3€T¢NðhË>XÃWeн³g~°;Œ1¢7tƒŽ!­D“C¹eIžælÝenw“ ¹^)X³4ç(®—®UL’Ü}_Þþ„Õxγ"—›Õd縬I•«Z±õápçãr[“w9OŠzÍàƒŽù¢‹‡l>½š™êÇ«;uyü !ä¸ ÏæGxQ³Tœ™±üëÉ…`lÕû:6îKÆàªÕÞPÓÚøÔ p-!tðhж³_éE»½LT×,ë¢o·Awa¨Îø£¡Žë€CË84P§÷Ð$dªG˜ó¤Zç<;Ê@CŸ8=„;{ ¢#=bQÔØçÇl_i‡à8~_…ƒç‰M‡!p\J¼žÀ¥aÿt1Oö¿Tb§ û¶.¡i#œc ¼°¹*®ï¯LáËÃÝ–Uªžb¼ŽîD•‰¸,™ð-æu\h›Sjû0 ìæöwmýÊ¥n÷w0pýa~ŒþðNõÈendstream +endobj +1970 0 obj +684 +endobj +1971 0 obj<>>>/Annots 102 0 R>>endobj +1972 0 obj<>stream +xڍ–moÚ0Çßó)NÝZ7vžÕmR·oÚ©kÒ“PdJê$êöígÇ!@‚ûûîçó݅÷C¼1¸LÙà[8¸›ø€]caq\9.‡‹jSiUiÙ`g4O®Ñá°'wÕÏÐñ’t[7Ú1Ԗ`Ìùr¯:°ç ³a Ž!†ÄiÍy)Ä$­ŠõIâÈÎÕ¦é4'ÐK )/&¨«ã€iad7–xàÙgäåáëÖQя=ÝM<]@b2ˆb<ÔCìñõa¨îò¸üˆÄÔ~áùŠGYFyÏ«¢TzaâÀÈ%Fÿô³\KœY-°L‡Ÿƒÿͧ>Òendstream +endobj +1973 0 obj +728 +endobj +1974 0 obj<>>>/Annots 105 0 R>>endobj +1975 0 obj<>stream +xÚ}S]o›0}çW\i/‰´8(Pu›”¥aJ×–зH‘GœÔ“1̘u?v [¡Y\ßsÏ9Ø÷þt0¸úÁà‡æÍ çsæÌ“KÀdG £…&ySÕ·¤V+)K¹›ì¦Óì‡E9»pQ`59Q›uá²MzØÒ°ªÚ׊¨¦Þ+ƒÑ)ì¢øŒÂ¯’vÓ«Œï[¦ UµÍ€q§Z T4•D±R@^ +E˜`âê‰×B°NS F ª\Ó:—¬2Ý/ ”Fަó4i­žÖ[DA™ç”ô€`}Q¶©nה ` +žç-×À ö‘g¼hæýÃ×¾ÍöE‹Û/î“Ûõ2댟Çê7)*>z½ï˜Èys ðÁÊÜ,èéSï¢{áë–ûqõvBèm€e0¸šñ~ÚR + ^—°Ê¹z2̂ͲùbðbW£ ˆ|ä·‡­š^žàuWz1þ7FK"rÊoÊï]¯œ•‹bý/‚¿Ñ@Ðm[S­Òû—+Úz±J&TÂ8í, ÙæIÜÚ¿ðPÛn¿Þ,’ f°|L·°-ê™H +©,O’zÜj¸#¢!ܰΰÂ,ò\Sf+ÀXwª;:7ú,¾9NŽ8bendstream +endobj +1976 0 obj +484 +endobj +1977 0 obj<>>>/Annots 110 0 R>>endobj +1978 0 obj<>stream +xڕUÛn›@}÷WŒÔ—¤Š7ìrWªJnGyˆJcò)ښµCË­ ôò÷e—ÄÁØ¡ !`3ggÎ~Î(XxRðجóÙ§xv¾ úo0âù>ñ NNÖmUßrùãKÕ¤eQ?œ<œžÆß5ÖÑØ¹kGaïk¾:jAh‚ŒêDiѨ¾¡ FSWUò¸I3ñØÀ{¼?àap`F(Úü±Ôß¿Wå V0_=œ^ì­Ç¶5å…ܶ¹(šZ#\ T! ̙¯݃††”ø˜__Šz-Ó®†Š\Å3‹XØóçËÝ58¢]Ë# (s0³ðV +X€©ojÐÌsÕõÝ Ï1ô\ÅÁ ™b]ìxuÙ;^ñ“€(ºÕghJÈqä8ClMf¨Ñ# 5/Ÿêéì n„!F¿ å ‡ úG.%ÿûoäLçÝ¡òvŒÇ9/ *QŽH[úß<sOæÙ¡Gð"a; t›ïDÓʸWˆÚ•žVïëf¯Ëb“¥ë¦†MÙ 9¸3êVû}/õAçèiœt⫇#îÕIঞÕ%<ñ"ÉDðªJ‹­bzEæ;(xŽ1„ôûß&öñ¬ÅDeÜ^×ÕžWÙA{—ë¬M|P‹;Wòôqà;ƒGåR/ǎì/Fìpߟ†¨ÄCÙäÅñú„ã€1>{e¬0Á+WBÀ‡µ'ujԋzÎÿ-æ>ÓÒ åvÅîüŠI¢yör­0âöŨ§öÕx5ËTóýç"gеgPW})…Èy´>õBö˜cc£0$§p¸̈́0'$vÏÀ¶Ý7[`XNaqYÛ°Ÿð|˜ Î)õ1·Ç˜6†Ë»Å2†9|¾V°*7ÍoŽÉr+yž YÃ-/Zž©¼sÊ<˜ûÌ:â(Žï`úḦ#_gÿL4CŸendstream +endobj +1979 0 obj +718 +endobj +1980 0 obj<>>>/Annots 115 0 R>>endobj +1981 0 obj<>stream +xڍ•ÛnÚ@†ïyŠ•ªÁÆë³•¦mJԋ¨ip®Jm`·>е´oßÙõšÛ 2^ÏٙñŸ?,W~çIïSØ»˜@=—hq=¸.Îæå&¿c"çß6E”¥ùìl6„¿*±]‰GŽAl)~ÈيWVm4iå)J iÂ;Ô ~·ï9ž ˜¯™€s&VÃÆÐ<Ð'¤eò˜UŽêeD-~,àü\?7\¶þ“eUØc±*žy¥p€R©ð] 12½ê×"©¡%zÀÛ×<Ÿ‹HՖ/aÏ &~{º¿ÛGµc¸ÄjÚèÎ4ðRp˜vˆ©gªÕ¦ëÈóV­vÐÖxŽd°SR`"—ò®¸Â5‡¼QºÌxÁ¢T^f)‡L@’¡;rÛÆ,'cWêì +Ö£Õ¦íìg6ZŸ¸€lY#b @±Þ‚ý;ƍ þéÜJ½—ÛÑõÝÍ<†M†UŠÈEÖæ¬ÇxmcœÌ«ÔåñZßVàWé¾çE)R]Ýuùȶu«ÒVIç/ûÿšðÎþiô€œ ­û‡L tiÏUÄ|ÃçÑ2•.â%–mGõJX©Gsý”%üê™Å%ïoç„ET‡([(Ÿï§™ZøŠƒˆ¥ðÄñ'Žù’2.¢MÌ¡ˆI’aó$OÆÝÝ×¥ÈÈù3,Ö|ùþì|ùËt¹of¾‹Òy\.8|)º'²þؘr¥œ‰¯ÇN7]vŒßa¸GÕXB vÂMwµIW0kBÌ­'Þ:l— +Ž·çÎÏ᛼?a´O9‡qœg­æ£ºŸp¾lþð}¨¯ãª™j±‚ÝöQ¯ãñbQÁÖeÝË7‰S£®ìôîh†ŽæyÛ CP)k©èÁ›mÕŸº jÓ¶ð÷0€†<…á†'dÀ´bÕ–åM¦<…à–‰ß,´ý]L|½#J=ôêZz@\ߏ'!ŒàóÃݦٲxa8fîD¶,I¸Èᖥ%‹¥ß5]y¦ÿ¶+oY~€ÞŒC£3ò½÷ñl‚?endstream +endobj +1982 0 obj +794 +endobj +1983 0 obj<>>>>>endobj +1984 0 obj<>stream +xڕ•mOÛ0Çß÷SœØ@Ôä©I*¦ilÀÄ´I Â;$”¦N”8™ãˆñíwg'-´ -©Tž¿Ï¿œïÎG6Xø³!pÀõ!)FߢÑéÕì¢-~0¢ùaÒTõÌ„ºÊrþpøpt=¥g”ã‰Å>>>/Annots 118 0 R>>endobj +1987 0 obj<>stream +xÚuQo …ßùçQ“•B¡->:g—,[â,{ó…U4YZÙ¨f°áËÔ@nrážóÜ/ÂÁÂáU¼Ý@î5ɛ¸„Þ…ŸJqZ@o'­µ˜÷£›ê²Ô„Q„±ðX֏±AU +ª0 T¤¦G=ÿÍû=òF‚óD)e ”îô9.Ì¡³ý“{ßL6ӛ¸Zřǥ¢å- KÀ*‘î­/cýFx6ãqé½óç—ny£Rü² uðý[ÓÃzÞhdX¼­Z´nwü6ÞbåÝޛa°~ċ9œLM3^TÈê‚E¡TñIJveݯäåkd’endstream +endobj +1988 0 obj +238 +endobj +1989 0 obj<>>>/Annots 124 0 R>>endobj +1990 0 obj<>stream +xڕT]oÚ0}çW\i/0c'vœ¨Ó$֕íeƒT}Aª¢`h¦„0;lýù³cÂG+Á¾Ç÷ž{΍ÿô`ý!À=ðH‹Þ—¸7šD@8Ä+ 8GÄË~ºÛªY¢*!ïòR‰E1Ä¿-–ZìaD öA%ka£"ôˆMô·Ì–&¦·FáÉÜfãIÖ;O|ÔÿƒÛN9ß·Çr½+ĦRÁ€ƒ ˜"¢ërKªA‰â:…Þþ*T*³m••¹{a­Éþgö h¨ÑL' +°að0ò@ +˜Ÿ{˜ïў5ź—:~Ìp`Ä5¡{¬™±ÈòŠŸX@UR$T%¤Ft…'6޽™g>Éó 4 œQGb{m/ÆßÀê|vPš¾û¶ •nQmEš­2±l7‹Îš}ÿ’Ûüìt}È6i¾[ +ødxŒlRôüùhâN `{Þn/@]ÏØRáÊ Ï…€q®ÊŽ·ÄمÌ×À#ý°‹Üºu„—k8èmÎÑco~nŦ±æd½¢h_D‡U§"v+WêjE:¼^q˜‰dù]…¼ÈÄÃxßn>fˆ]£Òð}—iö"ru‘‹OÈ+¨çŸ7¢áÒ~;—G™U¢-L7mÿæò¨Pó2kçôûÍÜêì¬8рքÔ,ڒtYŒ&asÛzPº{b6žÄ0„»‡éæåªú—è{e*˵LŠBH?’Í.ÉMÒ¡99ä¾pyPNuâA#×÷¯ÞÑr®endstream +endobj +1991 0 obj +576 +endobj +1992 0 obj<>>>/Annots 130 0 R>>endobj +1993 0 obj<>stream +xڕ”mo›0ÇßçSœ´7锸6Ϩۤ¬M·IÝÖª¾©¡Ä¤L( K‹<jþމq4OðêjøBȰCÀGho +@Û©CsfÁ9ÌRYœY‘ÕöÂ`ށÈÀ£hK}“jwµôbÇ~bŽÙîÜuZHÞ´®3¡ç {›Œ O3ëKIë”5VkR¹óì"@3|Å?.I ª:Þ ˜Ô鯾Aixÿå>yá©d1™q´-–a½’õ²4ÀogyēÁO7æ<ìx2ìËGЬKv}×k¼²Õ°:±HEqº%ç—·^m3fàtêÁvÌnC˜VGE\î#A÷¢Øˆ(˸ð=ÊwQª‚N՛Sר¦¿MÕ#ÓW³”ö,û×è/ˆ©"endstream +endobj +1994 0 obj +715 +endobj +1995 0 obj<>>>>>endobj +1996 0 obj<>stream +xڍTÛnÚ@}ç+FªTA¯ñ ‘V"mhZ•‚óT*dÙ ¸Â—îÚJª(ÿÞÙ]; Æ@@ {çÌÌÙ3—¿ +~)¸& “ε߹œŽ€ºà¯Ñâ¸.qÀºa™‹y +Æç,ˆnñÇø²»ìõü?ÚÁÒÛ –t¸Á†i«£ÊhR­LE¼IY$íxL âO"OW\¯ +ø€Oý†´}”[Ž$V[Húê§eo|@{8ÔÌ&|S&,-„FØ@©D¸±‘¾«ïVƒ$†Ž(q1a"äq^ÄY*-7~Ç êûü7ÿ +–‡h›ºU7\¤oÄÎ`Ѧ¶ƒi5ÚôèZʪèْƒm˜ZTH1Sñ3Ë@+¢à,H È0LÁšg 9ÍÖ9ç­l5º…­âhy¦ÖYW¢Asy§’%Ò @4PÒ.âÄ`5sf瘻f{3s…nÕù¥Q,s¤Ež3d“VmR×A¶¸£{„B–‚(Ð ÑG¾Ýü˜BƁqžqr´]$Çç øéi¬Ùt•P¢¡¤¬8Ø"ga¼ŽY´ßǙÝ<I¾;:Ôïâ4ܕƒ+IïR%ÛOam¼bgw§lܲ^Ö@õ‘ÛàðyôõCZï!·¯cæñۉ_™¿›„Ó׹߯;Ë#’» Þ×[H×ë•óãÁ^;›`-µìJÅà#c¥\U&’Ç-‹7Û¢²\\¤xlY¨û7˜)Qªh…ú¯s\ÿ+˜˜1þ sTûõ鶛<5Nžt«yU?SÓGÀTc2ŸL}Àç»ÙÙº¸p^g<Ûð Ið=HË`'C ¤çÀ5s³c¹V½‹lZ햟ÿ#væendstream +endobj +1997 0 obj +665 +endobj +1998 0 obj<>>>/Annots 136 0 R>>endobj +1999 0 obj<>stream +xڍ“QOÂ0Çßû)îq$Ðõ¶®ˆN_Œ¸ÍøÂË…`6†D?¾­é¦ˆ[H›&×Þýÿ¿´×w‚ÀÌ@…«ŠÜäÄO¦€ò91Òòµ—)³²©Gù¹Ë £ÌÚí’ÞÛDÒ*ˆ•.(!³šòõü„¢s‰¸I5.«Ó¡I‹æ¨ô¼¬µô–£^ÃX²ÖEDEŸ%s–ËyÁJ_‚ý‚x:¨ý J¤ØAò©¢%½ž"UÅz±ûTe3Ș§’K8åY/K |=Ë«ÞՃRº…¹”õÆÃ]™¹ófLÒÈE½mbÓÑ$œ5Ç7Åù•\RøIì 2¦ÜŠÜ¦³$‡ Ì_dõæøQh ]ouQUJ7ðXìOEi5'¶p"f £Ànqûç?<“/³cÆMendstream +endobj +2000 0 obj +320 +endobj +2001 0 obj<>>>>>endobj +2002 0 obj<>stream +xڕUmOÛ0þÞ_qÒ¤©jâ4ol 6­+áÓ2!Ó:M¦¼tŽ#˜ÿ}g;%M[–J•c?w÷ÜÝãËï |FÌòÞyØ;¾õ!ŒñÄó}âA8ïÏêe5e•äbÊÙ|’>ò¬ŠúÑ`þ2Ž1ºq”ÁmÅܜZ0nmj¼ÕE•. +>Wç¸M-l¢vï„Þ¾“p€«£–t=«0K˜€ƒ¥öö–/2‰'YŽF&‘3±¨s^ÈÊ \ T!ÝmߔbR:¦ÄG¸}Á«™H—2- urö,ba;þýM?ƒ Úµ²|™mUïÒb–Õs§ŠÛ±qJ’­AÒzEYnΕ,-øIÇÈ{nÍ£fÜ.`‚Ùk¼Y´¡¯'_ó˜;ô# cûgۀ²;‡$Í8D­ö\ëè‘!GðÞp‰¦YkÆO3wo<€õõUÅàX'ºvpÚ$Lkž.ٜn„xêöÝÓ4_ˆõçJë.¾`Œæ3°‹tWfÏ­g#µ 3µ=ð\Ÿèi|1=» +aŸn'7pSÆòá՝ˆr!XžsQÁWVÔ,S.†ÊrèÛÖ¾‹ãøFÖ0wԌ™ï½¿¾ùendstream +endobj +2003 0 obj +700 +endobj +2004 0 obj<>>>/Annots 142 0 R>>endobj +2005 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 ùž½/+ÅÈendstream +endobj +2006 0 obj +318 +endobj +2007 0 obj<>>>/Annots 148 0 R>>endobj +2008 0 obj<>stream +xڕ•ÛnÚ@†ïyŠ‘*U¤Çk|BI+‘4‡‹V¥à¨¥Š,³€+c»»¶’ªê»wöà|€$²öþ;ûí¿3“_=&~ xŒ\ˆ¶½Ë wv3âA°Â×ó ‚e?*s> yAÙ7ôކKÊýÅÉIðS­°ÕŠ¡c¶XqÏÃ5U³&Œõ¤ET¸2åñ:¥K1¯‰iøv¯˜|ÿPÀ; j ¡õ#×åˆñ°‘‘Äb5Zœœ7ÀG#Å6aërKӂ+…„ŘÀS§«DBCpÊÃøú#å‹ó"ÎR1sôLÃD‹Ÿf·`û¨vˆg ñ¸ç,#3 +ó1ñ-Ô)µå¸{jyW¶ÆsƒcZÊ´H’Éø’,ØPP/ ·Pdð(\ƁqÖ»öµ°JÝ+mÔH›ÕEÔ('gq* ‘®@dq{ ¤ÏÀÇh=wx5­T·Zû’¶5V¾ÎhQ²TgFe½ÈkW¥,^Få|€øD˘љmµŒÅ҈z¤ø*޾²‡KãxN£xÓeÝÂp? ºÉ®ŸÂmžt–ð›8’rIáBà© ÆæC­2kx¹Í:M┞·´‚—š×Qú‡„Ïe®uiÕu ڄ¬Š™ÇO4áß}2¶~Ô†qø87#:¼Ýk5Ý1VƒE_xïÁ<—nÀ…>‚!v¸£ñzSè™ÓSuï;þ4ºáQpÕwЧҍ®<ì2\þÆÌšRö šGúۙEsJa’ð¬Q³D—!>€ë`ámÁ7±|å8Q5XS³5ìVë¢rï®’ŒÓª0ZwóŽÁ¿nÇ~¦ÞO!é Ý€Ú!ø’Óô ñˆA*Ë'Õé; 4åëfxiû-¢ÄB+œ +d4&G­@ØÿŨ’Jgl#dp0-Ñ ñžLIåCg^ xÔRÇÎn|NÄ&{²%Ï&7 áê~:‡y¶*Cü§0eٚ…Û-e>‡i&"äP¬z–y´O۞µ"uŽ£ýµ÷¡‰qÀendstream +endobj +2009 0 obj +778 +endobj +2010 0 obj<>>>>>endobj +2011 0 obj<>stream +xڕT[oÚ0~çWiÒmq㐫è&µëía“¤ÚØ*7˜‰æ8j§iÿ}¶Oh!„Ë BÆç;ǟÏåûÕ¢`©…ž§¿qÖºŠZç·!P¢©²x¾O<ˆ&í¸\CVH.¾‰TòAúÂçŸ=ît¢Ÿèá G×µˆ£= +–p´ZVF›b¸2/Ò$çmWÇÔ"Áž[ôñ£0çNÔî¬æku Ä3&àdiÂý§ëœç‰œ;ý­‡özø–K‘”Ïe(ÕjY„ªû˜ŽJƒhH‰¯B¨ãk^Ä"]Êt‘kËMÔ²ˆ¥jòú3¼'Ph×òˆ Ô¥*¨m©­à0jÓ0TïB´Ý ˆ»†6Åu*~®æà„¶f¡2jx™è†W4〇B +Î2 xÖEQ²ŸªxÄ:š*¢¨"AŸb™°x ,&L²WЇøy®Šy4?ƒÞÉÏ­:û¤_^fO*‹‹)<ý–¼8š¤ãªÀG“4èÆz¿ul/ 0—C.K‘Wýºê=öjmÍYòœìƒZ'ë©ß +|@EVTژ!•+E¤Xò8¦j7+Í6ûs7±›–-ç;¥è]šÇórÂáB³;Ç dö±&µ¿i.·Ecžæ¼ß ioÚU--aû€3Î&›:tSת…ò= ¡ý£î@ÙÿœZaî͵c­ gðIT¸;Æt!`ÜÖ9€`õM6à¢zÑ7Üó4™ÉÊrzŠe_‹ðgKšØÑS†z¥øë®t7¸ø¬8l?é/vI°ÒpÛÏvÐv=¼¼  Ÿ#-¦ò™©)ˆE"X–qQÀ–—l®Ctµg×· +¸ž>êy!ŠÂÞ!P‚ðµõýÝ.endstream +endobj +2012 0 obj +652 +endobj +2013 0 obj<>>>/Annots 154 0 R>>endobj +2014 0 obj<>stream +xڕ’ÁnÂ0DïþŠ=‚Æk;)mÚKUš¤ê…KQ%„: öó»® "B«(–ÖYϐ45;½öˆ‚¸è‡¡ä¯®fĵ»kœ%ãÝ®wæ|MŠAùt¡T #ò"‘ûdgЇÉÛ4…´Zî¾rk`j«•ÍËÒØžóÍ>/œfßìk).Óh7°ßíPû»¾²“vŗendstream +endobj +2015 0 obj +317 +endobj +2016 0 obj<>>>/Annots 157 0 R>>endobj +2017 0 obj<>stream +xڍ”ÛŽÚ0†ïyŠÑö*9p축¶-ìU+JB¯*o2WŽMmíÛ×΁Í&°ª@VâÿóÍdÆ¿;¸æçA0±ÿ8ë|Š:Ãå¼)D©±L¦SgQҍ¢<¡Üv·½^ô«pnƒ±ëŒ¬ÛF‘Væ¥Ñ÷J Á•†xO$¼µ>Æä¹Î¬)4Ùöî[1‚ Y£>J® +û<¯ +3)à (×(A Ð{„SrdT8Éй©þU,éASÁ«>>>>>endobj +2020 0 obj<>stream +xڍTMoÛ0 ½çWØ%Çrü‰º¥v(%îiÙAudGƒmy²Òµûõ£,;n]gm†øH>>Rü=!`ãŸ@àÀ҇¤˜|Ž'‹ëHqŠ?,âý49Vůêšçl7ÝÍfñ/t pîٖ«·5͘±ÚµF‡´QTÂ{mÅKb[áËÐ’âwI öa€…§?^*@X¦»ÙÅ BË¥Éy)³cÁJU„„hDàZ ë¤1$"V€ðzÅêDòJqQjËU<±-;›¯à†ˆöH`¡Ž¶9Ûr@2؎€‰YË턑>OèFz·¥çiží˜²;9zM’†^|` õ¢‰bj%y™pùÊ*$•ÐE°þ_‡ù˜ñ­uôH {7tLLF¸×ü/‘6T;‚]¼„»GÅê×>F|3á=*|?9®Õ7LeÙÎM×=Í~;4P œA”5ïFÞ žu¬wžZgÇt0j}¨' Çá)8d¬d’¢h@GZ©Ôƍvn‹{*ª¨†Ñö\²D ŒÐúõuÅžr¶Çu/t‰r"Ç>ÁI‹øf½ú¶†gå=—¢Ô¯§w9;/ÏÕ-ªüìbyÇË$?î|Ô-ôa> –ÇpïèMӉóÃñüŸ¯8<“ÿ´¢š1i³›öQؖKç54­6—×1ÌáËíz [‘ª?çp-E&iQ0Yà -4×!æÚs8ö¹þ»¸ÈB󤼨}+ß'ÿkJŒyendstream +endobj +2021 0 obj +594 +endobj +2022 0 obj<>>>/Annots 160 0 R>>endobj +2023 0 obj<>stream +xÚ}S]o›0}çW\i/É´$ê6)[šjR7¥¼åÅ'ñ6³MÓþûÙ@Ú$„ d÷ÜsÎý௃™ ƒÚ;-œo‰3^ÎGìL$Œ"7„$¤U©6ŠÊí`;&PЀFä´QdO›(‚YôpË ¸Òˆ„cB¹ÓKògÁ²íð®£àû ɚêJrÕÄÀø$6æP +Æ5• è…´’’r •¡ç¤  $œ6ك_›ÇÇK°]m³àǘ‚ŠgtÇ8ÍÜ^s ªRÉJÍ¿”83Øí㻨lŠ«•k¯D)‘2¢iG¦‚¬5¢L^)¤ý~­!Wõí ­éê Aõª4-NÃð]¯vHò¼¿ÆûR”yï?0žæUFá³-tl÷ðõjÜ×Ó?[ [ÕÝÿáuá_༑ýûS +ó\ ¸Oä"³ïöÀöX?Øð‘gJ/`:q'íK±ý®ðrç[ç£Sˌ—ªWf^G!ßZ}Sp†Ïq™g$j%[[­Ö§z¼]cµ‰˜Êç÷ÝêR—ÓÖ}€ i€Ã¦§‹õ|™À¾oV1Äb§DRXI±—¤(¨Tð“ðŠä–u„½F‘‡lbˆì§À·æÐ­ý6=xrþ)Pendstream +endobj +2024 0 obj +484 +endobj +2025 0 obj<>>>>>endobj +2026 0 obj<>stream +xڅ‘Ënà E÷þŠY& SC±±—N“tU)µÉ.ä×­_¬öó ±ڨ!±˜9÷Üy 0Dö``n¨º`Û}˜?ÛNÂJ€?­ž7íP½6}}ZÖkþâAêÁ0ŽuàQ‹Zº®­Qêk¹ª§NöF{U ;&NörÎ0bÖ֖·RWªM3ô®³ãA„"ûêå*–Žif¼Ò:PÊ`BÝØ ÍPö'=[“Åš¡è?g²8/ð%×9.šÅ>×BšIõzìâ՟¿tv¢Ûë€K)!oõàóM—|»ÕÌÚùžCwÇC åp6ïÂ>젆Z‰®“JÃè'Ñ:‹Ð)CF¢ß6OE©_O‚ç­<Ÿ„ç‘@endstream +endobj +2027 0 obj +293 +endobj +2028 0 obj<>>>>>endobj +2029 0 obj<>stream +xڅ’=oƒ0†w~ōÉŎÁñHóÑ©R +ΖQ‡¤å«6¨ýùõÕ5QÔ +Äp÷Ükû1Ð>1¾Eí=Jïa+€pGۉ9b¯³Sßw«“*Þ³Ã|.ßÅåGaÀÚ›¼Tص5Æ\-ÑåP«¦7n*BpŠPœñ)¿¦"‚ÜÆÚòZ™BŸ»þÜ6ØÙH/ B»åé“>[Z:b¹I›LA+ÈîÀ”á²#Íñ'}‰¦S4Âÿ’é”<Á£Ô‹.&"'5Uý s6J¼9ó¯Îæ+¯»êVp¦$•ißåä¯T¸…Öi²•àÃj¿Ë kýgn7¶Óm©óºVÚÀsÞ y…>Núœþø)–Ø…wÿ{%/Þ7ÄvŽendstream +endobj +2030 0 obj +291 +endobj +2031 0 obj<>>>>>endobj +2032 0 obj<>stream +xڅ‘?oƒ0Åw>ōɀ‹ƒa¤IèT)gËb%¥â_mPûñkˀÚ(JeÉÃÝï½³ß}zs00›΍÷̽§,̀_M'b EÀ/«÷aè·µ*«d}ѧÕi½æŽ¥ŽõÃQ˵(¥í𥮖ªrld;h§ +c«ÂÄj|ÂþR FÌØšòN곪ú¡êZÛÙs/@yørå/@cC‡41FNiœ ( ŘP;v¦Jғ5Y¬ +þs&‹óÏÑNqÑ$tÑærU«§Àæoþü«³ÿM_ß\H i­;—o¼ä™Å&nÐ.O3>l‡Šî:| ó°ƒêJ%šF* ¯¢Em-|«ô ,Ÿ2Šb·¡h3-æÍû¸¢“lendstream +endobj +2033 0 obj +295 +endobj +2034 0 obj<>>>>>endobj +2035 0 obj<>stream +xڅ’»nƒ0†wžâŒÉ€‹Áa¤¹tª”‚³e±R‡¦âVÛ¨}üÚ5 6ŠRÎùÎoû3†È>âÔ½§&xäÁÃ.̀Ÿm'e ¥À_oÆôëºÓò¸8.—üÝSÔSa!ꨃ•t][£Ô×rU löS `ì¦0q3!a)á #fcmy#õI]zséZ×Ùò B‘Ýòü)ž€®,ÐÌùI›L@I(oÀ„ºe'š¡ì.=F“9š¡è¿d2'Ïð$uÔE³ÄK-¤T«Ga“Ä«3ÿêl¿DÓ×ׂK)!¯uçý®f¿îJ3¿Ð¦ÈwBXö%”ÝÙ| +»±½ê*%šF* Ï¢Dí"B72òã?¥®DãØ:ŠnþöJ^‚oøßŽÒendstream +endobj +2036 0 obj +291 +endobj +2037 0 obj<>>>>>endobj +2038 0 obj<>stream +xڅ‘?oƒ0Åw>ōɀ‹]ƒa¤ùÓ©R +ΖŢM†£öãזµQÓʒ‡»ß{g¿{0Dö``î¨Úàwû 0~¶„1”Y½Óo:¥deN«ÓzÍß>>>>>endobj +2041 0 obj<>stream +xڅ’=oƒ0†w~ōɀk»‡‘–¤S¥Ȗ‡¦â«6¨ýùõՀڨ1Ü=÷Ú~̫ǀڇÁmˆoÙxw¹w³‹€IÈ϶JIBÈO«çaèUv'Šãê¸^ç/ôJ‚ST +»¶&„«ÅºÕÆMÀN1Ž3>—ß)„XĈ´±¶œ(SêK?\º;ÛÜ£„Ú]/ŸôÄÆÒˆl›´É´‚ì˜ \v¦%‰þ¤§h¾DKBÿKæKòÏ^']" +œ×T £nÍ$l–xuæ/í{ÑôõµàL)ˆkÓ9¿›Å/ÞjäJÒx—ƒ÷‡}YwÞ +»±½î*]4Ò‹v,jŒðqҗüÓbI0fÑß~{+OÞO-@endstream +endobj +2042 0 obj +293 +endobj +2043 0 obj<>>>>>endobj +2044 0 obj<>stream +xڅ‘?oà ÅwŠ“Á(6ftë¤S¥Ô&[”7•ÿcµ¿ «¢VH w¿÷Þ}D°;8…ûŽmô £»­ÂAž\'å¥ _WoÖ…n´Õ‡Õa½–ïc‹Œ˜Çö£ªµïºc¡–›zjugÇ J€¯"ÔkbÊS"‚ îl]¹Ðãќ{î;ßÙÈ#ìÞ¼\å°ÌÑ Î((3£¡ºSæÇ^hŽÄŸôlMkŽðÎtq^àKªs\L$!ÕRÛÉtãØ%Ä«?ÿèl¾T;4×WZCތ}È7[òMÝNET”ùVB û]U²ŸÊ=lgúÚ¨¶Õf„gÕMªñ±WƜâÛ{gœ¡,,'åóN^¢o}‚šendstream +endobj +2045 0 obj +290 +endobj +2046 0 obj<>>>>>endobj +2047 0 obj<>stream +xڅ’Írƒ …÷>Å]& ©PYÚÆtՙTÉ.Æ›ŽEœöñ Å8m&ӎŒ‹{¿s€sy0DöÃpŸ¸UµÁƒî¶0q²„1”€8®^ò®ê*¡‡Õa½o¤ ãQîGY+×µ5J}-ÓõԪΌ^ÆN…‰Ó„„ý¦„9FÌÚÚòF•>æÜw®“‹ B‘=õò+ž€¦–Ž)·F^i hå ˜P·í…fˆÿIÏÖd±f(úϙ,Î |ÉuŽ‹òØçZ(3énœ»„xuçüS¶Csp©dÍØû|Ó%_7Uî7ÚÙV@û] e2Òl§ûZ˶Uz„gÙM²q¡S†Œ|矤®D1F©È­§`§ò|f?\endstream +endobj +2048 0 obj +295 +endobj +2049 0 obj<>>>>>endobj +2050 0 obj<>stream +xڅ‘?oà ÅwŠ“Á(6ft§S¥Ôv¶,(%n*ÿ+`µ¿ «¢VH w¿÷Þ}D°;8…ûŽ]ôPGw[„C}r”s”Býºz³v,´ôauX¯ë÷@±@Å FÌS{#å»®ÆX¨åº™:Õ[T âU„zMLùoÊCDĝ­+o”9êóhÏCï;Ea„Ý“—«|–9:aÂ¥s¦ T7`ÊüØ Í‘ø“ž­ébÍþϙ.Î | uŽ‹‰$„Z*;éÞ́]B¼úóNñ%»±½¸R +òÖ !ßlÉ7u+aЦ̷5Äð¸ßUP 'û)ÝÃvzh´ì:¥ <Ë~’­·ˆ½2æß\;ã ea7©˜Wò}G⏠+endstream +endobj +2051 0 obj +290 +endobj +2052 0 obj<>>>>>endobj +2053 0 obj<>stream +xڅ’?oƒ0Åw>ōɵƒÃH›Ð©R +Ζ¥Iſڠöã×Wj£(ÃÝï½³ŸýáQ ö£°ŠpkïQzi T€<ÙN$D|[œû¾K«Áœ‹Ãr)ßÅå‡$àHíMQ*ìÚ箖èr¨UÓ§ +RTQ†Ÿ‰¿B4¦°¶¶¼Qæ¨/]iìl¥Gb·<ÿ²gàkK‡<¶FNihù ˜q;Ñ"ˆïÒ£5›­E@þsf³ó O¡Žqñ8t¡fªtcÆÀ¦¯Îü«³ý*ꮺ8W +’Ê´.ßõœ/^iìm²$•àÃÓ~—CޞúÏÂnl§ÛRu­´—¢Š +-|Tú‚ýä/–ø +G‘›ïÀ^É«÷ ¶Žêendstream +endobj +2054 0 obj +291 +endobj +2055 0 obj<>>>>>endobj +2056 0 obj<>stream +xڅ‘Ënà E÷þŠY& S Ø˜¥Û>>>>>endobj +2059 0 obj<>stream +xڅ’Ko„ …÷þŠ»œYH…A‘¥í;‘§àŽ Žendstream +endobj +2060 0 obj +291 +endobj +2061 0 obj<>>>>>endobj +2062 0 obj<>stream +xڅ‘?oà ÅwŠ“ÁÔlÌèÖI¦J©ílYPJ\WþWÀj?~A8VU©î~ï¼û0Dö``6 œ»à± +v0ƒêb; c(êuõf̸—&F–F5}}ZÖëêÝÓÔÓa!ê裵t][£Ô×2UOìöª0v*Lœ&$ì7å Ì1bÖ֖s©ÏªM3ô®³­‚EöéËU쁦–Ž)·F^i ( å0¡nì•fˆß¥gk²X3ýçL羆;ÇEyìÃ-¤™T¯çÀ®!ÞüùGgû%º±½ ¸”²V>ßtÉ7±«å~P^d» +Bx:J(‡‹ùöa5ÔJtTžE?‰ÖY„N2Ý]?e¥~Gl3¯æ%øÑÿ•endstream +endobj +2063 0 obj +296 +endobj +2064 0 obj<>>>>>endobj +2065 0 obj<>stream +xڅ’OSƒ0Åï|Š=¶"IiŽ(mOÎTHo½djŠ8ü3„яob(£ªÃa÷÷^6oy 0DöÁ°JÜ{j‚{Üm9`âl; c(ñ¼x1¦ß)“I£DÕ¨ãâ¸\ŠWÏRφq„¨cƒ,•ëÚ¥¾–êrlTk¯Šc§ÂÄiBÂ~RÂ#fmm9SÃIW½©ºÖu6"ˆPdŸ?ùèÚÒ1åÖÈ+­3­ ¸ꎽРñ?éɚÌÖ Eÿ9“Ùy†/ÑNqQûhseFÝS`—¯îü­³ùM__\(i=t>ßõœ¯[,÷eyºÂÃa_@ѝͻ´ƒíuWjÙ4Jð(ÛQÖÎ"tʐ‘¯üu¥•˜û…üò7ØÅ<Ÿbg“Oendstream +endobj +2066 0 obj +296 +endobj +2067 0 obj<>>>>>endobj +2068 0 obj<>stream +xڅ‘Ënà E÷þŠY& S ØØK·‰³ª”Úd—•ו_¬öó ±ڨ!±˜9÷Üy `{p +÷1œºàAwy +„ƒ¸ØNÌ9ŠAœW/ƌ;iòF¶çãê¸^‹W2†F́]ÕÒum1_ËT=u²7Ú«" Ä©ušòHJ·¶¶¼‘ú¤šÑ4Cï:[`„í«—«ØK,±Ôy¥u¦ $”?À”¹±Wš£ôOz¶¦‹5Gø?gº8/ð5×9.–F>×BšIõzìâ͟¿t¶U7¶·—RBÖêÁç›,ùÆv«©´)²\@‡} åp1ï•}Ø^ µªºN* OU?U­³2äÿ¶yÆJüzx4oå9ø2ûendstream +endobj +2069 0 obj +293 +endobj +2070 0 obj<>>>>>endobj +2071 0 obj<>stream +xڅ’;oà …wÿŠ;&ƒ)PlÂè6¥•R›lYPJœT~cµ?¿P«¢VFîýÎÎå="€ÝGà>õëPG2º[ äÑuRÎQ +òuv²¶Ûhû¤›Òžö³ý|.ßÉ'1OîzUjßu5ÆB-3åPëÆöA•!^E¨×Ĕÿ¦>>>>>endobj +2074 0 obj<>stream +xڅ‘?oà ÅwŠ“ÁÔPlÌè6I»TJm²eA qSù_«ýøáXmµBb¸û½wðî#¸ƒ¸ÏàÐF"ºÛpÀ ÄÉu2ÆPâ¸x³vxVò¸_ì—Kñ  8MõÐÎÈZù®«Qj…®ÇVuÖU +{&^ö›òæ1gëÊ+eú<ØsßùÎZD J܋ç«|š;:¥Ü¥s& T7`BýØ Íÿ“ž¬ÉlÍPòŸ3™gø’éåiÈ´Tvԝ™»„xõçõ—l‡æ:àJ)(Ӈ|ó9ßÌm”‡A«²Øˆáq·­ êOöSº‡mu_kÙ¶Jx‘Ý(o{eÌHrkë”Q”‡Õ06mä5úd‚Ùendstream +endobj +2075 0 obj +290 +endobj +2076 0 obj<>>>>>endobj +2077 0 obj<>stream +xڅ’;oà …wÿŠ;&ƒ)PlìÑm’ªC¥Ôv¶,(%®+¿ +X­úë űš¨îýμ°®c7mpSW›‡òh;1ç(†òiñlÌpßÕ¦Mý!÷‹ýrY¾x”y4Œ0bÝiQI×µ5Æ|-SÕØÊÎh¯Š€§"ÔiBÊÏ)‘” nmmy%õAՃ©ûÎuÖe€¶çž—üXb鈥ÖÈ+­3%¡ø¦Ìm{¢9Jÿ¤'k:[s„ÿs¦³ó Ÿ’âbiä“Í¥U§§ÀN!^Üù[gý.Ú¡¹ ¸²F÷>ßdÎ×½kê7ZåÙ¦„nwÛŠþhބ=ØVõ•m+•†э¢q¡S†œ~åÏWb”Xüûg°ïò|‹D“endstream +endobj +2078 0 obj +297 +endobj +2079 0 obj<>>>>>endobj +2080 0 obj<>stream +xڅ‘KSà …÷ùwÙ.‚€$„e´­+ǚÐ]7L¥±N^B2úóI3Úñ1̰¸÷;繯ìNá:…CÝÈèj#€pG×I9G)ȧÅó0ôýpêZ»_ì—Kù8¸8ÁˆyngU¥}×Õ µÜTc£ÛÁU„x¡^SþòqgëÊ+mæô9ÙwÖ2»GÏWq,st„3 +JçLÁh(€)ócÏ4GâOz²¦³5Gø?g:;Ïð9Ö).&’k¡‡Ñ´v +ìâş¿tÖïªéëˀK­!¯mòÍæ|S·T­Š|#!†Ûݶ„²;oÊ=lkºÊ¨¦ÑÆÂ½jGU{‹Ø+cNñ/‹gœ¡,l‡‹i)ÑgºÏendstream +endobj +2081 0 obj +290 +endobj +2082 0 obj<>>>>>endobj +2083 0 obj<>stream +xڅ’½nƒ0…wžâŽÉ€‹Áx¤MÒ©²eA©CSñWÛ¨}üÚ5 E­°îýα}®ß= ù0„±]çÖ»/½»Ì ¼˜NÌŠ¡|Ù¼j=d½Ò§Íi»-ßDäG¢:ªª¶kj”ºZ*뱝VNÆV…‰Õø„ý¦,„9FÌØšòN¨³¼úÚw¶³/½æÄË/š:¢Ü9¥q& 7`Bí¶3Íÿ“ž¬ÉbÍPðŸ3YœxÎtŠ‹òÈeš =ÊNMÍ!®îü£³ÿ¬Ú¡Y\i£z—o²äk'ÊÝF»<=”àÃÃ1+ è/ú£2Ëd_˪m…TðTucÕX ß*}F¾óO[¢!G¡Èú˜‰<{_·2Ž7endstream +endobj +2084 0 obj +291 +endobj +2085 0 obj<>>>>>endobj +2086 0 obj<>stream +xڅ‘?oƒ0Åw>ōɀk»ÃH›¤S% +ΖÅJ ¥â_Qûñk˵QÔʒ‡»ß{g¿û`{p +÷1œ»àAw‡QÙNÌ9ŠA¼nތsÝô¦:mNÛ­x÷óXaÄvœd­\×ÖóµL×s§z3yU„8¡NRþ›rI âÖ֖wj:ëf4ÍлÎ^aûæõ*ž€%–ŽXj¼Ò:SÐ +Ê0enì…æ(ý“^¬éjÍþϙ®Î+|Iu‰‹¥‘OµPfÖý´v ñêÏ?:û/ٍíuÀ¥RµÓàóMÖ|c»ÓÔÚÙA@Ç¼„r¨Ì§´ËõPkÙuJOð,ûY¶Î"tʐS|{ïŒ3”øå$dÙÉKð ŏÖendstream +endobj +2087 0 obj +291 +endobj +2088 0 obj<>>>>>endobj +2089 0 obj<>stream +xڅ’OO„0Åï|Š9Jèîz2A`o{iÖ.®áŸm‰~|[ D‰Ñ@8Ìüޛö o†È>n÷žÛà® +n0ƒêb; c(êyób̐æ´9m·Õ«g¨gÂ8BÔ1G-j麶F©¯eª[ÙíU1`ìT˜8MHØOÊA˜cĬ­-ï¤>«ë`®}ç:û*ˆPd¼|Š ©¥cÊ­‘WZgJBù L¨;Ó ñ?éɚ,Ö Eÿ9“ÅyçH§¸(}¤…4£êôØâêÎß:ûÑÍ:àRJÈÝû|Ó%_·PîíŠìPA÷Ǽ„²¿˜wa–«¾V¢m¥Òð(ºQ4Î"tʐ‘¯üSâJԎJýBV]ÈSð 8‚`endstream +endobj +2090 0 obj +290 +endobj +2091 0 obj<>>>>>endobj +2092 0 obj<>stream +xڅ‘?oà ÅwŠ“Á6ft›¤S¥Ô&[”7•ÿcµ¿ «¢VH w¿÷Þ}D°;8…U +Ç&z”ÑÃVá Ï®“rŽR§Å›µ}¡Õé°8,—ò=@,@q‚óÐ~P•ö]Wc,ÔrSníT âU„zMLùoÊCDĝ­+¯õp4—Þ^ºÖw62»ÏWñ ,st„3 +JçLÁh(ïÀ”ù±Wš#ñ'=YÓٚ#üŸ3gøšéIÈ´Ðv4í0v ñæÏ?:›/ÕôõmÀ¥Ö×CòÍæ|S·Q­‹|+!†§ý®„²;ÛOå¶3]eTÓh3À‹jGU{‹Ø+cNñ½­3ÎPV“­¦¼Fßz©êendstream +endobj +2093 0 obj +289 +endobj +2094 0 obj<>>>>>endobj +2095 0 obj<>stream +xڅ’?oƒ0Åw>ōɵ]ƒa¤MÒ©R +ΖQ‡¦â_Qûñ뫵Q” +‹áî÷žíwþð(ûQ¸p•÷ ½»]T€<ÙN$D|]½ÓgªìÚV•æ¸:®×òݑܑ~HŽäa(*…][ãÜÕR]jÍàT!PŠ*ÊPã3ñ—Bˆ&4Ö֖7j(õ¹7ç®ÅÎVz$ öØË/{[:ä‰5rJëÌ@+ȯÀŒã¶3-‚ä&=Y³ÅZä?g¶8/ðìOBl¦Ì¨Ûa +lñâο:Û¯¢éëˀs¥ ­‡Îå/ùâX·Ñ&Kw|x<ìsÈ»“ù,ìÁöº«tÑ4Jð\´cQ£…J_°ŸücŽ%Nây W߂ˋ÷ ùÒ1endstream +endobj +2096 0 obj +294 +endobj +2097 0 obj<>>>>>endobj +2098 0 obj<>stream +xڅ‘Ënà E÷þŠY& S Ø˜¥Û$]UJm²Ë¥ÄMåW1Vûùa[mԇX̜{î¼E°;8…ÛNMt'£›ÂAž]'å¥ ŸW/Öö¥î•QVWÇõZ¾0N0b< ªÒ¾ëjŒ…Znª±Ñ­‚*B¼ŠP¯‰)ÿNyˆ‚¸³uåNæÒÛK×úÎVFa÷êå*€eŽN˜pFAéœ) å0e~ìLs$þ¤'kºXs„ÿs¦‹óϹNq1‘„\ mGÓS`sˆWþÒÙ~¨¦¯¯.µ†¼ºo¶ä›º­Š0hSä; 1Üö%”ÝÙ¾+÷°½é*£šF›U;ªÚ[Ä^sŠÛ<ã ea=Y2må)ú o‘^endstream +endobj +2099 0 obj +292 +endobj +2100 0 obj<>>>>>endobj +2101 0 obj<>stream +xڅ’Írƒ …÷>Å]& ©PYÚ&vՙTÉ.&!֎Eœöñ Å8m&ӎŒ‹{¿s€sy0DöÃpŸ¸ulƒÜå0q¶„1”€8­^JeòZ5§Ãê°^‹7R†q„¨÷£¬”ëÚ¥¾–éjjUgF¯Šc§ÂÄiBÂ~SÂ#fmmy£Æ£®S÷ëlE¡ÈžzùO@SKǔ[#¯´Î´‚òL¨ÛöB3Äÿ¤gk²X3ýçLç¾ä:ÇEyìs-”™t7΁]B¼ºóÎöS¶Csp©dÍØû|Ó%_7Uî7ÚY. „Çý®„²?›i¶Ó}¥eÛ*=³ì&Ù8‹Ð)CF¾óOW¢ûqÜzv&/Á§endstream +endobj +2102 0 obj +293 +endobj +2103 0 obj<>>>>>endobj +2104 0 obj<>stream +xڅ‘?oà ÅwŠ“Á(6ft›¤S¥Ô&[ä7•ÿlµ¿ «¢VH w¿÷Þ}D°;8…ûª6zÑÝNá O®“rŽR¯«·q¤Q•>®Žëµ| Tœ`Ä>>>>>endobj +2107 0 obj<>stream +xڅ’;oà …wÿŠ;&ƒ)PlìÑm’N•R?¶,(!n*¿ +XíÏ/Ûj£¨ˆáÞïàÀ{@ÛAà>vóØep·Kp(϶sŽb(O«Wc†j8 #«Ãz]¾yŒy,Œ0b«´¨¥ëÚc¾–©zleg´WE@ˆSê4!å¿)‘” nmmy#õQ]sé;×ٖF؞yYò'`‰¥#–Z#¯´Î”„âL™Ûv¦9Jÿ¤'kºXs„ÿs¦‹óÏ©Nq±4ò©æÒŒªÓS`sˆWwþÑÙ~Švh®.¤„¬Ñ½Ï7Yòuošú6y¶+!„Çj_@џ͇°Û«¾V¢m¥Òð,ºQ4Î"tʐÓïü“Ä•ìuðí`ßä%ø}eºendstream +endobj +2108 0 obj +292 +endobj +2109 0 obj<>>>>>endobj +2110 0 obj<>stream +xڅ‘?oà ÅwŠ“Á(6ft›¤S¥Ôv”%‹•וÿ°Ú_¶ÕFQ+$†»ß{ï>ØœÂ} ç6x(‚»Â¡¸ØNÌ9Š¡x]½3UmäiuZ¯‹wO1O…FÌQ]VÒum1_KU5¶²3Ú«" Ä©ušòߔƒˆ ˆ[[[ÞH}Võ`ê¾sm`„í“—+{–X:bÂy¥u¦ $ä7`ÊÜØ™æHüIOÖt±æÿçLçžCâb"ò¡fҌªÓS`sˆWþÑÙ~•íÐ\œK i£{Ÿo²äە +?h“¥»Bx<ìsÈû‹ù,íÃöª¯TÙ¶Rix.»±lœEè”!§øæÚg(ñ»IÄ´’—àJ£endstream +endobj +2111 0 obj +291 +endobj +2112 0 obj<>>>>>endobj +2113 0 obj<>stream +xڅ’½nà …w?Å“Á(6atš¤S¥Ôv¶,(&–+ÿlµ_(¶ÕFQ+#÷~ççòÀö#ð»ui‚m<ùÕvbÎQ y±ªú>)Šm×ÕJ¶çÕy½Îß<É<F1GžŒ,•ëÚc¾–èrlT;¯Š€§"ÔiBÊS"‚ nmmy§ÌEWýPu­ëìó#l½üÒg`KGLX#¯´Î´‚ìL™Ûv¦9ғ5]¬9Âÿ9ÓÅyç`§¸˜ˆ|°©Fݚ)°9ě;ÿèì?eÓ×·gJAR›Îç»Yòuc~£]šráétÌ ë®Ã‡´;ê®Ô²i”6ð"ÛQÖÎ"tʐÓïüv%†#Dü@î¾;–×à I_‘‡endstream +endobj +2114 0 obj +295 +endobj +2115 0 obj<>>>>>endobj +2116 0 obj<>stream +xڅ‘?oà ÅwŠ“Á(6ftš¤S¥Ôv¶,(&–+ÿ+Øj?~A8V5­î~ï¼{`{p +1œÛ`S{„Cq±˜sCQ®êaHËrÓ÷’9­NëuñæQæÑ0ˆ9ôhd¥\×ÖóµTWS«ºÑxU„8¡NRþ“rqkkË[eκƺï\gWaûîåʞ%–Ž˜°F^i)hù/0enì•æHüIÏÖt±æÿçLç¾&;ÇÅDä“ÍÔ8éÎ́]C¼ùó·ÎîS¶Csp®¤é}¾É’ol÷*ü m–î áéxÈ!ï/ㇴ;è¾Ò²m•6ð"»I6Î"tʐS|÷Œ3”ø 2ïå5ø »’{endstream +endobj +2117 0 obj +294 +endobj +2118 0 obj<>>>>>endobj +2119 0 obj<>stream +xڅ’½nƒ0FwžâŽÉ€k»Ç#-I§Jip¶,Vp5 öñk׀Ú(Jb¸÷ÜÏö1l±{Ïuð$ƒ‡ÂA^l'æÅ óUÙuIž§jЧÕi½–ïc #Œ˜Ã޽*´ëÚc¾–˜b¬u3ô~*BÜ¡n&¤ü/å "â6֖SݟMÙ eÛ¸ÎVa»çåsx¶±tĄ ò“6™‚ѐ݀)sËÎ4Gâ.=EÓ%š#ü_2]’x¶:éb"òVzMÓOÂf‰WgþÕÙ~©º«®gZCRõ­÷»Yüº;~¡ôì$„ð|Ügµ—áSٍíM[U×ÚôðªšQU."t“!§?þu%F©u„oÿöNނoÆ?endstream +endobj +2120 0 obj +291 +endobj +2121 0 obj<>>>>>endobj +2122 0 obj<>stream +xڅ‘Ënà E÷þŠY& SC°1K·Iª.*¥1Ùeƒbb¹ò«`«ýü‚°­6êCH,fνwÞ ‘=M—&¸Áݞf ®¶“0†Ūêû¬(žÚA•JŸWçõZ¼z’z2Œ#Dy2²T®kk”úZ¦Ë±Qí`¼*Œ +§ ûN9sŒ˜µµå­2]õCÕµ®³A„"ûìå:>M-Sn¼Ò:Ð +ò`BÝØ™fˆÿIOÖd±f(úϙ,Î <;ÅEyìƒ=ªaÔ­™›C¼ùó—ÎîC6}}p®dµé|¾é’ob×Êý í1Û áátÈ!ï®Ã»´;è®Ô²i”6ð,ÛQÖÎ"tʐ‘è×ÕSFQê÷Ã7ÓZ^‚O”H‘³endstream +endobj +2123 0 obj +294 +endobj +2124 0 obj<>>>>>endobj +2125 0 obj<>stream +xڅ’½nà …w?Å“Á(6at›¤êP)µ- ЉåÊ[íãŠmµQÔÊÈýß9À¹¼°ýÜÇn›à!îö‡üb;1ç(†¼XU}ŸÅs;¨RisZÖëụ̈ͣa„sèÑÈR¹®­1æk‰.ÇFµƒñªq*B&¤ü7å "âÖ֖·ÊœuÕU׺Î.0ÂöÜË/}¶±tĄ5òJëLA+ÈnÀ”¹mgš#ñ'=YÓŚ#üŸ3]œxNvŠ‹‰È'›ªaÔ­™›C¼ºóÎîS6}}p¦$µé|¾›%_7Wá7Ú¦É>‡‡ ²î2|H{°ƒîJ-›ÆN^d;ÊÚY„Nrú¿`®Äp4äöc°sy ¾þv’“endstream +endobj +2126 0 obj +296 +endobj +2127 0 obj<>>>>>endobj +2128 0 obj<>stream +xڅ‘Ënà E÷þŠY& S Ø˜¥Û$]UJmg— Љåʯ‚­öó ¶ڨ!±˜9÷Üy `{p +÷1\Úà¡î‡âj;1ç(†¢ÜÔЖe&»J7çí¶xõó\aÄw2²R®kkŒùZª«©UÝh¼*BœŠP§ )ÿN9ˆ‚¸µµå2]cÝw®³/Œ°}ôzeOÀKGLX#¯´Î´‚ü˜27v¡9Ò³5]­9Âÿ9ÓÕy…—X縘ˆ|¬™'ݙ9°%ě?éì?d;4·çJAژÞ盬ùÆv©ÂÚe顀OÇòþ:¾Kû°£î+-ÛViϲ›dã,B§ 9Å¿,žq†¿ÍKy >rZóendstream +endobj +2129 0 obj +292 +endobj +2130 0 obj<>>>>>endobj +2131 0 obj<>stream +xڅ’½nà …w?Å“Á(6at›¤S¥Ôv¶,(&–+ÿlµ_(¶ÕFQ*#÷~ççòÀö#ð»un‚§>>>>>endobj +2134 0 obj<>stream +xڅ‘?oƒ0Åw>ōɀk»ã‘6I§J)-‹DſڠöãזµQ•Ê’‡»ß{g¿û`{p +1\Úੇâj;1ç(†¢ÜÔЖe¦LßLcÝwçÍy»-Þ=Ì<F1ŸŒ¬”ëÚc¾–êjjU7¯Š€§"ÔiBÊS"‚ nmmy§ÌE׃ì:û"Àۗ¯Wö,±tĄ5òJëLA+Èÿ€)scš#q—ž­éjÍþϙ®Î+¼d;ÇÅDä³ÍÔ8éÎ́-!ÞüùGgÿ%Û¡¹ 8W +ÒÆô>ßdÍ7¶›~Ð.K„ð|:æ÷×ñSڇu_iÙ¶Jx•Ý$g:eÈ)¾·}ÆJüŠŸ7ó|ƒP”ƒendstream +endobj +2135 0 obj +294 +endobj +2136 0 obj<>>>>>endobj +2137 0 obj<>stream +xڅ’Ënƒ0E÷|Å,“;ã%m’®*¥àì²AÁAT¼jƒÚϯ§&¨úˆÅ̹wì;¼zBûØÄøž[ï^zw{„ƒ¼ØNÌyƒ,Wõ0¤e™)Ó7ÓX÷9­Nëµ|q4s´…CúhŠJa×ÖsµTWS«ºÑ8U„ ŠPÔø”§"‚ÜÚÚòV™³®œŒô ´G_>Ù#°ÄÒÖÈ)­3­ ÿ¦ Ç^iˆ?éٚ.Ö<ÿs¦‹ó_Ýãb"ráfjœtgæÀ®!ÞÜùKg÷^´Csp®¤é]¾É’/®V¸AÛ,ÝKðááxÈ!ï/ã[avÐ}¥‹¶UÚÀSÑMEƒ>*}N?ó –6IâÖñëß`óì}Åÿ•endstream +endobj +2138 0 obj +296 +endobj +2139 0 obj<>>>>>endobj +2140 0 obj<>stream +xڅ‘?oƒ0Åw>ōɀk»ã‘6I§J)-‹DſڠöãזµQ•Ê’‡»ß{g¿û`{p +1\Úੇâj;1ç(†¢ÜÔЖe®©åØëóæ¼Ýïžež #Œ˜cOFVÊum1_Ku5µªWE@ˆSê4!å¿)A·¶¶¼Sæ¢ëa¬ûÎuöE€¶_¯ìXbéˆ kä•Ö™‚VÿSæÆ.4Gâ.=[Ó՚#üŸ3]Wx‰vŽ‹‰ÈG›©qҝ™[B¼ùóÎþK¶Csp®¤é}¾Éšol+ü ]– +áùtÌ!ï¯ã§´;ê¾Ò²m•6ð*»I6Î"tʐS|gùŒ3”ø 1/æ-øÁè“endstream +endobj +2141 0 obj +294 +endobj +2142 0 obj<>>>>>endobj +2143 0 obj<>stream +xڅ’½nà …w?Å“Á.PlÂè6I§J©M¶,(&–+ÿlµ_(¶ÕFQ*#÷~ççò`@öÃð˜¸un‚'<ì9`âb; cQ¢XU}ŸE>èª-O«Óz-Þ=H=Æ(¢<Y*×µ5J}-Õ娍v0^ÆN…‰Ó„„ý¥„9Ž˜µµå­2g]õCÕµ®³А=õòË^€n,Sn¼Ò:Ð +ò0¡nۙf¿KOÖd±fúϙ,Î <ç:ÅEyìsÍÔ0êÖLÍ!^ÝùWg÷%›¾¾8W +ÒÚt>ß͒¯›*÷m³t/ „çã!‡¼» ŸÒì »R˦QÚÀ«lGY;‹Ð)CF~òǹÅÉ<‘[oÁŽå-øžÜ‘%endstream +endobj +2144 0 obj +294 +endobj +2145 0 obj<>>>>>endobj +2146 0 obj<>stream +xڅ‘Ënà E÷þŠY& »@±1K·Iºª”Úd— Љåʯ‚­öó ¶ڨ!±˜9÷Üy 0 {00÷ \ÚàAw˜¸ÚNÂX”€(7õ0deYŒºî*sޜ·[ñêIêÉ0FuäÉÈJ¹®­Qêk™®¦Vu£ñª0v*Lœ&$ì;å ÌqĬ­-èzë¾s½P„ì³×+šZ:¦Üy¥u& ?À„º± Í"þ'=[“ÕšEè?g²:¯ðìå±6Wã¤;3¶„xóç/ý‡l‡æ6àB)ÈÓû|Ó5ßÄ®•ûA»<;áñt, è¯ã»´;ê¾Ò²m•6ð,»I6Î"tʐôëêi’.ûÁÏ{y >dÿ’endstream +endobj +2147 0 obj +293 +endobj +2148 0 obj<>>>>>endobj +2149 0 obj<>stream +xڅ’½nà …w?Å“Á(6atë¤S¥Ô&[”˕ÿ +¶ÚÇ/Çj£¨•‘‡{¿s€sy`÷¸Oý:µÑƒŒîvyv”s”‚|]ÕЫQË^Ö­>®Žëµ| $ dœ`Ä>>>>>endobj +2152 0 obj<>stream +xڅ‘?oƒ0Åw>ōɀk;㑖¤S¥ȖÅJDſڠöãזµQÔʒ‡»ß{g¿û`{p +».mðX„Cyµ˜sCù¶©‡!SÕysÞnËwO1O…FÌQ'#+庶Ƙ¯¥ºšZՍƫ" Ä©ušòߔƒˆ ˆ[[[Δ¹èzë¾s}`„í“×+–X:bÂy¥u¦ w`ÊÜØ…æHüIÏÖtµæÿçLWç^Bãb"ò¡æjœtgæÀ–oþü£³ÿ’íÐÜ\(iczŸo²æە +?(ËÓC !<Žýuü”öaGÝWZ¶­Ò^d7ÉÆY„NrŠï®Åɲ‚wóN^ƒooGŽÕendstream +endobj +2153 0 obj +289 +endobj +2154 0 obj<>>>>>endobj +2155 0 obj<>stream +xڅ’½nà …w?Å“Á(6ñè6q§J©ílYhB,Wþ+`µ_(¶ÕFU*ýß9À÷€¶ƒÀ}ìæ© Êà.K€p(/¶sŽb(Ï«z²º;§Æ¨úu4ò¸:®×囇™‡Ã#æàƒ•t][cÌ×RU­ìŒöªq*B&¤ü7å ’Ä­­-o¥>©z0u߹ή 0Âöä˒?ÛX:b‰5òJëLAI(þ€)sÛÎ4GÉMz²¦‹5Gø?gº8/ðœíK"Ÿm.ͨ:=6‡xuçÝ§h‡æ:àBJHÝû|7K¾îe¿Ñ6O³Bx<ì (ú‹ùö`{ÕWJ´­TžE7ŠÆY„Nrú?ÁÌÕ¦Ößúöi^‚/ÈӔendstream +endobj +2156 0 obj +296 +endobj +2157 0 obj<>>>>>endobj +2158 0 obj<>stream +xڅ‘?oà ÅwŠ“Á(6ft›¤K+¥6Ù² ”¸®ü¯ØVûñ ¶Ú(J…Äp÷{ïàÝg@ÛC€S¸áT2¸Û äÙvbÎQ òmUvݳnŠáý¸:®×òÃSÌSa„sÔ¡W…v][cÌ×RSŒµn†Þ«" Ä©ušò¿”ƒˆ ˆ[[[ÞèþdÊn(ÛÆu¶2ÀÛ'/Wö,±tĄ5òJëLÁhȯÀ”¹±3͑¸IOÖt±æÿçLçžCâb"ò¡fzMÓOÍ!^üùWgû­ê®º 8×Òªo}¾É’olW*ü M–î$„ðxØç·çáKهíM[U×Úôð¢šQUÎ"tʐS|uí,NæÝM;y ~øŽõendstream +endobj +2159 0 obj +291 +endobj +2160 0 obj<>>>>>endobj +2161 0 obj<>stream +xڅ’½nà …w?Å“ÁÔlÂè6I§V©M¶,(%–+ÿl¥_(¶ÕDQ+#÷~ççò`ˆì‡a•¸uªƒG<ì8`âl; c(ñ¾(»îU]Ž‹ãr)>>>>>>endobj +2164 0 obj<>stream +xڅ‘?oƒ0Åw>ōɀk»ã‘6I§Jœ-‹•:ˆŠ5 öãזµQ”Ê’‡»ß{g¿û `{p +1œ›àI„ƒ¼ØNÌ9ŠA¾oª¾Ï:3ž6§íV~x†y&Œ0bŽ9ªÔ®kkŒùZjÊ©Ñí8xU„8¡NRþ—rqkkË;=œMՏU׺Î^aûàõÊ_€%–Ž˜°F^i) Å ˜27v¡9wéٚ®Öáÿœéê¼ÂK¤s\LD>Ò\“i‡9°%Ä«?ÿêì¿UÓ××ZCZÏ7YóíB…´ËӃ„žYEw¿”}XfºÒ¨¦Ñf€WÕNªv¡S†œâKgq²l†`>oä-øÉV}endstream +endobj +2165 0 obj +288 +endobj +2166 0 obj<>>>>>endobj +2167 0 obj<>stream +xڅ’½nà …w?Å“Á6ft›¤S¥Ô&[”˕ÿŠmµ_(¶ÕFQ+#÷~ççòÀö#°‰Ý:×Á£ öyµ˜sƒ¼¬Ê®Ë´ºœV§õZ¾y†y&Œ0bŽ9öªÐ®kkŒùZjбÖÍÐ{U„8¡NRþ›rqkkË[ݟMÙ eÛ¸ÎNa{àå—=K,1a¼Ò:S0ò;0enۙæHüIOÖt±æÿçLçž#âb"ò‘fzMÓOÍ!ÞÜùGg÷©ê®º 8×Òªo}¾É’¯¨ðm³t/!„§ã!‡¼½Êì`Ú¨ºÖ¦‡Ռªr¡S†œ~çOpâjl“̹yv"¯ÁS•)endstream +endobj +2168 0 obj +290 +endobj +2169 0 obj<>>>>>endobj +2170 0 obj<>stream +xڅ‘?oƒ0Åw>ōɵ]ƒñHKÒ©R +ΖÅJDſڠöãזµQ›Ê’‡»ß{g¿{0 {00÷ œÛàAw{˜¸ØNÂX”€xÝÔà êV‰>—£:mNÛ­xó$õd£ˆ:òhd¥\×Ö(õµLWS«ºÑxU ;&Nö“ræ8bÖ֖seκƺï\g'!ûìõ*ž€¦–Ž)·F^i hå/0¡nìB³ˆß¤gk²Z³ýçLVç^‚ã¢<öÁjœtgæÀ–¯þü­³û”íÐ\\*YczŸoºæ›Øµr?(/²½€‡Êþ2~Hû°ƒî+-ÛViϲ›dã,B§ A®ž&鲌ø¼——à ê‘Õendstream +endobj +2171 0 obj +292 +endobj +2172 0 obj<>>>>>endobj +2173 0 obj<>stream +xڅ’½nà …w?Å“ÁÔ`lÂè6I§J©M”% J‰åÊ[íãŠcµVÕÊÈýß9À¹¼"ûaˆS·.Mp/‚»=Ì@\m'e ¥ ^VUߟt5¨óê¼^‹WQ…I„¨ƒŽF–ÊumR_Ët96ªŒW%€±Saâ4!a?)a޳¶¶¼U梫~¨ºÖuv"ˆPdO<ÿòG K'”[#¯´Î´‚â˜P·ífˆÿIOÖd¶f(úϙÌÎ3|ËtŠ‹òÄgš«aÔ­™»…¸¸ó·ÎîC6}½ ¸P +²Út>ß͜¯›(÷mól/ „‡ã¡€¢»ïÒì »R˦QÚÀ“lGY;‹Ð)CF¾òÇ8r5sû‰,߁Ésð ùŽ=endstream +endobj +2174 0 obj +293 +endobj +2175 0 obj<>>>>>endobj +2176 0 obj<>stream +xڅ‘?oƒ0Åw>ōɀk»ÃH›Ð©R +ΖQaHmPûñkˀڨdÉÃÝウ߽°=8…ûÎ*xÁ]žá .¶sŽbõFµJfu·Ý(õisÚnÅ«'™'Ã#æÈ£©麶Ƙ¯eº™”ìGãUâT„:MHùwÊA$%ˆ[[[ÞIsÖíul‡Þuö"ÀÛg¯Wñ,±tÄRkä•Ö™‚–PþSæÆ.4GéŸôlMWkŽðÎtu^á%Ø9.–F>ØBŽ“îÍØâ͟¿tö•ºv·—RB֙Á盬ùÆv­©´+²\@ÇC åpß+û°ƒ])%µçªŸªÎY„NrŠ]=‹“e?„y//Á'C‘Êendstream +endobj +2177 0 obj +292 +endobj +2178 0 obj<>>>>>endobj +2179 0 obj<>stream +xڅ’Áoƒ ÆïþïØdÀPôèÖv§%Ò[/¦Rã"ê@³í¿ k¶¦Ù"ñðÞïû€ïñÀö#p»uRÁƒîv)âl;1ç(Q­T£dVUâsÇÕq½¯žcž #Œ˜ã¦¬¥ëÚc¾–ézR²WE@ˆSê4!å¿)‘” nmmy#ÍI7ÃØôëlE€¶‡^~ù°ÄÒK­‘WZg +ZBq¦Ìm{¡9Jÿ¤gkºXs„ÿs¦‹ó_bãbiäcÍå8éÎ́]B¼ºóÎö£TC{p!%d­é}¾É’¯jê7ÚäÙN@‡}EßK{°½îk]*%µç²›ÊÖY„Nrú?!ÔÕNPâ'rã)Ø©¼_y>endstream +endobj +2180 0 obj +294 +endobj +2181 0 obj<>>>>>endobj +2182 0 obj<>stream +xڅ‘1oƒ0…w~ōɀk;ÃH›¤S¥œ- +¢ÂÚ ¶ÿ¾¶ ¨ªT–<Ü}ïýî= €í!À)lb8«àQûq±˜sƒ¨VªQ2«*ñu•ùØÊÓê´^‹7Ï2φF̱GSÖÒum1_Ët=*Ù Æ«" Ä©ušòߔƒHJ·¶¶¼•欛ëÐôëìD€¶_®üXb鈥ÖÈ+­3-¡ø¦ÌiŽÒ»ôdMkŽðÎtq^à9Ú).–F>Ú\£îÌØâ͟tvŸ¥º¶·RB֚Þç›,ùÆv±©´Í³½€žŽ‡Šþ2|”öaÝ׺TJj/e7–­³2äßY>‹“yC„l¦Í¼ßn“tendstream +endobj +2183 0 obj +294 +endobj +2184 0 obj<>>>>>endobj +2185 0 obj<>stream +xڅ’ASƒ0…ïüŠ=¶"‰4G”Ö“3Ò[/™š28j£?ßÄ£ÕÑ!Ãa÷{/ÉÛ¼F÷a¸Íü:éèND7;˜8»NÆÊ@<¯t£U¡Z5¨ãê¸^‹—€Ñ€Åi‚¨ÇVÖÊw]ÒPËM=jÕ 6¨RÀØ«0ñš˜°ï”‡0Lj9[W.”=™æ24}ç;[%(qg^~åЍ£SʝQP:gFAõ L¨ßv¦âғ5Y¬Jþs&‹óÏ©NqQž†TK5Œ¦³S`sˆWwþÒÙ¾K}i¯®”‚¼µ}Èw³äëgÊÃFE™ïÄpØWPõçáMºƒíM_©µ2e7ÊÖ[Ä^3ò™?ÆÔ×(Áa?߁ÉSô•õ%endstream +endobj +2186 0 obj +291 +endobj +2187 0 obj<>>>>>endobj +2188 0 obj<>stream +xڅ‘?oƒ0Åw>ōɀ‹]ƒa¤MèT)gËb¥¢Â@mPÛo_[ÔFý#Kî~ïýî5Àك¸Mଂ;Ü`üb; c(þ¼Q’EÓJþ1ÈÓæ´ÝòR†q„¨FÔÒumR_Ëu=)ٍƫbÀØ©0qš°ï”ƒp†³¶¶¼“欛alúÎuö<ˆPd_½^åÐÔÒ1ͬ‘WZgZBõL¨»Ð eÒ³5Y­Šþs&«ó +/¹ÎqÑ,ö¹–rœtgæÀ–¯þü¥³jh¯®¤„¼5½Ï7]óMìV3?hWæ‡ +ªþ2¾ û°ƒîk-”’ÚÀ£è&Ñ:‹Ð)CF¢ß6O“tYÆñ¼–§àÏW‘4endstream +endobj +2189 0 obj +292 +endobj +2190 0 obj<>>>>>endobj +2191 0 obj<>stream +xڅ’Asƒ …ïþŠ=&©9Ú&öԙTÉ-'%ŽÑtڟ_(ê´i¦»ß{À[Þ ‘ý0l·N*¸Á]Î3gÛIC ˆ—•j”Ì›vú¸:®×âÕcÔca!갃©j麶F©¯eº•ìãU1`ìT˜8MHØOÊA˜cĬ­-o¥9éæ24}ç:;D(²g^~Å#ÐÔÒ1åÖÈ+­3-¡¼궝i†øŸôdMk†¢ÿœÉâ¼ÀsªS\”Ç>ÕB£îÌØâ՝¿uv•º´×—RB֚Þç›.ùº™r¿Ñ¶Èr!<ö%”ýyx¯ìÁöº¯u¥”Ôžªn¬Zg:eÈÈWþ'®FIŠ6~"¿_‚Êsð Ù¦µendstream +endobj +2192 0 obj +293 +endobj +2193 0 obj<>>>>>endobj +2194 0 obj<>stream +xڅ‘1oà …wÿŠ“Á.PlÂè6I—VJm²eA ±\;[íÏ/Ûj£(ÃÝ÷ÞÁ»Ïr#ð˜ÁQGO"zØrÀ ÄÙu2ƒ Äi¡k­^;y:,Ë¥ø Pœ¢„zhoe¥|×Õ( µÜTƒVmoƒ*Œ½ +¯‰ ûKysœ0gëÊke¦¾ôu×úÎFD(AîÅóU¼]9:¥Ü¥s&`”7`Bý؉f ¿KÖd¶f úϙÌÎ3>>>>>endobj +2197 0 obj<>stream +xڅ’Aoƒ †ïþŠïØdÀPäèÖv§&Ò[/¦£ÆE´ÍöóÚ­iº@8|ßó¾À ìÇÔÏ£Žždô°@8ȓ뤜£äÛB7Zm•©ÕaqX.å{ X â#橽­jå»®ÆX¨å¦µêT âU„zMLù_ÊCDĝ­+¯”=šæ<4}ç;ka„Ý‘ç¥x–9:aÂ¥s¦`”7`Êü¶š#q—ž¬élÍþϙÎÎ3| uŠ‹‰$„Z¨a4»„xuç_õW¥ÏíuÀ¥R·¶ùfs¾þIEØhUä 1<ïw%”ýiø¬ÜÁv¦¯M¥µ2¶U7V­·ˆ½2æô'B2_c”8#|ó#¸7y¾C¸ŽÇendstream +endobj +2198 0 obj +291 +endobj +2199 0 obj<>>>>>endobj +2200 0 obj<>stream +xڅ‘1oà …wÿŠ“Á.PlÂè6I§V©M¶,(%–+c§`+ýùa[m¥Bb¸ûÞ;x÷a@î``38êèID[˜8¹NÆX’øXèZ«7u9,Ë¥ø Lœ¢„zfoe¥|×Õ( µÜTƒVmoƒ*Œ½ +¯‰ ûKysœ0gëÊke¦>÷u×úÎFD(AîÁóU¼]9:¥Ü¥s&`”7`Bý؉f ¿KÖd¶f úϙÌÎ3>>>>>endobj +2203 0 obj<>stream +xڅ’Áoƒ ÆïþïØdBQäèÖv§%Ò[/¤£ÆEÔ¡fÛ?Öl¦Ù"ñðÞïû€ïñ`ˆì‡a“¸uÖÁ½îö0q±„1”€xYéJ+ñÙ©Óê´^‹WQ…q„¨ƒŽ½,•ëÚ¥¾–™rÔªz¯Šc§ÂÄiBÂ~SÂ#fmmy«ú³©º¡j×ى B‘=ñüˁ¦–Ž)·F^i Å ˜P·í•fˆÿIOÖd¶f(úϙÌÎ3|ÍtŠ‹òØgš«a4M?v qqçÝ‡Ô]½ ¸P +²ºo}¾éœ¯›(÷mól/ „‡ã¡€¢½ ïÒì`ÚÒH­•éáI6£¬Eè”!#ßùÛ)¹%)Úø‰,߁Ésð4Ž(endstream +endobj +2204 0 obj +292 +endobj +2205 0 obj<>>>>>endobj +2206 0 obj<>stream +xڅ‘Ënà E÷þŠY& S Ø˜¥›GW•Ò˜ì²A ±RùU°Õ~~AØVE©X̜{î|F°;8…çNuô"£§­ÂA^\'å¥ ϋ®;¯ªÖêãâ¸\ʏ±Å FÌC«Jí»®ÆX¨å¦jÝô6¨ Ä«õš˜ò¿”‡ˆ ˆ;[W^k{2×®¿¶ïld„v/ž¯ý+°ÌÑ Î((3£¡¸SæÇN4Gâ!=ZÓٚ#üŸ3gxÊtŒ‹‰$dº×ý`;6…xóç_Í·ª»ê6àBkÈ+ۆ|³9ßÔmT„Aë}¾•Ãê°+ h/ý—rۙ¶4ª®µ±ð¦šAUÞ"öʘS|oë,ͦÕJƕ¼G?Žendstream +endobj +2207 0 obj +288 +endobj +2208 0 obj<>>>>>endobj +2209 0 obj<>stream +xڅ’»nƒ0†wžâŒÉ€k»Ç#Í¥S¥œ- "Qq« j¿vMPõ"Ã9ßùmæ5 €íCà>voÑ2¸; di;1ç(yY ÃeÛweS£9¯Îëµ|ñ ó`aÄx2y¥\×ÖóµDWS«ºÑø©qS„º™òˆ ˆÛX[Þ)Sèzë¾s½ 0Âv×Ë'}¶±tĄ ò“6™‚VýS施Ò‰?é9š.Ñáÿ’é’¼ÀW¯³.&"ï5Uã¤;3 »J¼9ó—Îþ=o‡æVp¦$é½ßÍâ×ݪð íÒä !„íé˜A֗ã[n7vÔ}¥ó¶UÚÀSÞMyã"B7rúéŸPêjŒ+ ÿö/Øky>åx‘gendstream +endobj +2210 0 obj +294 +endobj +2211 0 obj<>>>>>endobj +2212 0 obj<>stream +xڅ‘1oƒ0…w~ōɀk;ÃHèT) ΖQa ÔþüÚ2 6ŠRYòp÷½wö»O6‡§° ᢼgá=e1âj:!ç(Qnú²LU=fåysÞnŇ£˜£ü#f©ÓPTÒvM1WKt5)َƒS@ˆUj5>å) ‘˜ nlMy/‡‹®û±îZÛI…‡6O^¯ã+°ÈЋ‘Sg +ZB~¦ÌŽ]hŽâ‡ôlMWkŽðÎtu^á%Ô9..Ô£'Ýs`Kˆ7þÕI¿ Õ7·çRBÒ Ë7Zó ÍJc7hL2>¼œ9äÝuü*Ìú«t¡”Ô¼íT4Ö·JŸS|wí,Œ–ݺ›wòîýpށendstream +endobj +2213 0 obj +290 +endobj +2214 0 obj<>>>>>endobj +2215 0 obj<>stream +xڅ’½nƒ0…wžâŽÉ€‹ÁñHÒ©R +dËb%¢â¯6¨}üÚ5 E­°îýα}®ß= ù0„±]—Æ{,¼‡Ì ¸™NÌŠ¡¸núþš6Õpޜ·ÛâÍ1Ô1~ j™“¥´]S£ÔÕUŽlíT`lU˜XOØoÊB˜cČ­)量¨ªª®µ´ð˜/¿ìèÎÐåÆÈ)3%!¿j·i†øŸôdMk†‚ÿœÉâ¼Às¤S\”G.ÒL£jõØâêÎ?:é§húzp.%$µî\¾»%_;Pî6ÚgÉ¡žNÇòî6|s°£êJ%šF* /¢Em-|«ôùÎjk4ä(tY=3‘Wï pÀ@endstream +endobj +2216 0 obj +291 +endobj +2217 0 obj<>>>>>endobj +2218 0 obj<>stream +xڅ‘Ënƒ0E÷|Å,“®í Kš„®*¥ì²±À¡T¼jƒÚϯ-j£>dɋ™sïØwÞ<ØœÂ}Eë=äÞ]á_M'䅐—›a(Óº+w/}]ÈËæ²Ý毎dŽôŒ˜%ÏZTÒvM1WKT5µ²µS@ˆUj5>åß) ‘˜ nlMy/u¡êa¬ûÎv¹‡6Ï^¯Ó#°ÈЋ‘Sg +JBöL™»ÐÅÒ³5]­9Âÿ9ÓÕy…—`ç¸X¸`OrœT§çÀ–oþü¥søíÐÜœI I£{—o´æšµÆnÐþ”¤9ø°;3Èúëø.ÌΪ¯”h[©4<‰nµð­ÒçÿºzFË~ æ½<{Ÿ¡‘Áendstream +endobj +2219 0 obj +293 +endobj +2220 0 obj<>>>>>endobj +2221 0 obj<>stream +xڅ’Ínƒ0„ï<Å“»‡#MBO‘R ·\,p(-5 öñ»®5Q• +„Ðî7c{֏¾~³ÚzJ­‡(Â!½`ÇçÜñ!ÍW]—Ge“„z—ùöµ-3y^×ëôÍðÌð¶ç:Ló§^Rw±Æ˜©…ªkÙ ½Qy@ˆVª56åה†H@޶XÞÉ>Se7”m£;ûÔr7¿|âg`¤= ‘Q¢3%!ù¦L/;ÓÜ îғ5]¬¹ãþçLçžãâbgâå0ª¦Ÿ›C¼9ó¯ÎþKÔ]up"%„Uߚ|7K¾z¸Yh‡Q +6lOÇ’ö2| +ÜØQµ…u-Uь¢Ò¶Vڜþäÿº†Ffw.ÎæÅú%–endstream +endobj +2222 0 obj +299 +endobj +2223 0 obj<>>>>>endobj +2224 0 obj<>stream +xڅ‘Ënƒ0E÷|Å,“.v ÆKڄ®ª¦àì²AÁAT¼jƒÚϯ]j£>dɋ™sïØw^= 9Ûέw'¼›”f .¦1†"åfÊ´îʧa¬ûî´9m·âőԑ~ jÉ£.*i»¦F©«%ªšZٍکBÀت0±Ÿ°ï”…0Lj[SÞI}Võç`ÛÙ /@yöze@cC‡”#§4Δ„ü˜P;v¡âÒ³5Y­ +þs&«ó +/ÁÎqQº`39NªÓs`KˆWþÒÙ¿íÐ\œK I£{—o¼æ™µr7h—%©òþ2¾æaÕWªh[©4<ÝT4Ö·JŸ‘à×ÕÓ(^öƒ ›÷òì}j=’endstream +endobj +2225 0 obj +292 +endobj +2226 0 obj<>>>>>endobj +2227 0 obj<>stream +xڅ’½nà …w?Å“ÁÔPlÌè6IÕ!Rj“- Љ•Ö[íãŠcµQÔÊÈýß9À¹¼"ûa¸OÜ:6Áƒî60q²„1”€(}_>›­Ôoª<,Ë¥xõõ\Gˆ:nod¥\×Ö(õµLWc£ÚÁxU ;&Nö›ræ1kkË+eŽúÜç®uµ"ÙCÏ¿ü hjé˜rkä•Ö™€VP܀ uÛ^h†øŸôdMfk†¢ÿœÉì<×X§¸(}¬¹Fݚ)°KˆWwþÑYʦ¯¯.”‚¬6Ï7óuCå~£Užm„ð¸ßPt§áCڃítWiÙ4JØÊv”µ³2dä;LRW£8AØOäÆS°Sy ¾ "?endstream +endobj +2228 0 obj +296 +endobj +2229 0 obj<>>>>>endobj +2230 0 obj<>stream +xڅ‘?oà ÅwŠ“Á(6ftë¤S¤4v¶,(ÁVZÿ+Øj?~AØVU©î~ï¼û`{p +1œ›à©¶‡¢´˜sCqYõýe'õ{¦J9փ9­NëuñæYæÙ0ˆ9öhd¥\×ÖóµTWc£ÚÁxU„8¡NRþ›rqkk˙2g}í‡k׺Φ0ÂöáËux–X:bÂy¥u¦ äÀ”¹±3͑¸KOÖt±æÿçL瞣âb"òÑÔ0êÖLÍ!ÞüùGgó%›¾¾ 8W +ÒÚt>ßdÉ7¶‹~PvH·„ð|Üçwåð)íÃöº«´l¥ ìd;ÊÚY„NrŠï,ŸÅɼ!BÅ´™×à^ٓ³endstream +endobj +2231 0 obj +294 +endobj +2232 0 obj<>>>>>endobj +2233 0 obj<>stream +xڅ’Os‚0Åï|Š=ê4‰˜#­Ú“S ñæ%£‘±å_Lûñ›`ZÇi†Ãîï½MÞòÀö!°ˆÝ{,ƒG>>>>>endobj +2236 0 obj<>stream +xڅ‘?oà ÅwŠ“ÁÔlÂè6q§ª©M¶,(&V*ÿ+Øj?~AØVE­î~ï¼û0Dö``6 œ›àQÌ@\l'a % ÊUߗ¯½j³ò´:­×âÝSÔSa!ꨣ‘•r][£Ô×R]jãU1`ìT˜8MHØoÊA˜cĬ­-ï”9ëk?\»Öuö"ˆPdŸ¼\ù3Э¥cÊ­‘WZgZAq&ԍi†øŸôdMk†¢ÿœÉâ¼Às¨S\”Ç>Ô\ £nÍØâ͟tö_²éëۀ ¥ ­MçóÝ.ù&v¥ÜÚåi& „§ã¡€¢» ŸÒ>ì »J˦QÚÀ‹lGY;‹Ð)CF¢»k§ÉvÞ Þài'oÁ71”Žžendstream +endobj +2237 0 obj +290 +endobj +2238 0 obj<>>>>>endobj +2239 0 obj<>stream +xڅ’½nà …w?Å“ÁÔlÂè6q§ª©M¶,(!–+ÿlµ_(±ÕFQ*#÷~ççò`ˆì‡a•¸ul‚GÖ\ £nÍ%°)Ä«;ÿêl¿dÓ××JAZ›Î绞óuCå~£MžfBxÚï +(ºóð)íÁvº+µl¥ ¼Èv”µ³2dä'¼"®Fq2MäÆS°Sy ¾ éDendstream +endobj +2240 0 obj +294 +endobj +2241 0 obj<>>>>>endobj +2242 0 obj<>stream +xڅ‘?oà ÅwŠ“ÁÔ`lÌè6I§ª©M¶,(!V*ÿ+Øj?~AØVE­î~ï¼û0Dö``âNMð(‚‡Ì@\l'e ¥ Ϋ¾?¿öª=®Žëµx÷ õL˜Dˆ:æ`d¥\×Ö(õµ\Wc£ÚÁxU;&Nö›ræ1kkËeNúÚ×®u­"Ù/Wñ 4³tB¹5òJëL@+(ïÀ„º±3Íÿ“ž¬ÉbÍPôŸ3YœxŽtŠ‹òÄGZ¨aÔ­™›C¼ùóÎöK6}}p©äµé|¾Ù’ojÊý M‘ï„ðtؗPv—áSڇíuWiÙ4Jx‘í(kg:eÈHtgé4ÍæÍà8ž6ò|”/Lendstream +endobj +2243 0 obj +289 +endobj +2244 0 obj<>>>>>endobj +2245 0 obj<>stream +xڅ’½nà …w?Å“Á6at›¤K+¹6Ù²X qSù¯`«}üB±­6ŠZy¸÷;8—÷€¶UìÖ±îep·@8ȳíĜ£äiÑu§´(ՓjÊþõ°8,—ò͓̓a„säÞXÎum1_Kt9ÔªéWE@ˆSê4!å¿)A·¶¶¼Qæ¨/]i×ÙÊ#l=ÿ²G`kKGLX#¯´Î´‚üL™Ûv¢9Ò£5­9Âÿ9ÓÙy†§`Ǹ˜ˆ|°™êݘ1°)Ä«;ÿèl?‹º«®Ε‚¤2­Ïw=çëÆ*üF›,ÙIáaŸæ·çþ£°Ku[ꢮ•6ð\4CQ9‹Ð)CN¿ó'+æj S?›OÁNå%øßú‘vendstream +endobj +2246 0 obj +295 +endobj +2247 0 obj<>>>>>endobj +2248 0 obj<>stream +xڅ‘Ënà E÷þŠY& S ؘ¥Û$]Urc²ËÆJˆåʯ‚­Výú‚°­6êCH,fνw^ØœÂ&†sÜËàn/€pWۉ9G1È˪ï/YQª¼úP§Õi½–/žcž #Œ˜ãŽÆR®kkŒùZªË±Qí`¼*BœŠP§ )ÿN9ˆ‚¸µµå­2g]õCÕµ®³“FØ>z¹ÀKGLX#¯´Î´‚ü˜27v¦9ғ5]¬9Âÿ9ÓÅyçX§¸˜ˆ|¬5Œº5S`sˆ7þÒÙ½M_ßœ+im:Ÿo²äÛ¥ +?h{H÷Bx8f9äÝux+ìÃ2ݕºh¥ <íXÔÎ"tʐSüËâYœÌÛ!›hÚÊsð C—Zendstream +endobj +2249 0 obj +292 +endobj +2250 0 obj<>>>>>endobj +2251 0 obj<>stream +xڅ’½nƒ0…wžâŽÉ€‹ƒã‘6I§JuÉb‡RñWj¿v ¨¢VX ÷~çØ>×ï†À|6‘]çÚ»Þ݁f .¦1†"ùªëòDê¥Ì‡×Óê´^‹7Rúa€¨½Ál×Ô(uµXc­š¡wª0¶*L¬Æ'ì7e!Ì1bÆÖ”wª?ë²ʶ±½ð˜S/¿ôèÖÐ!åÆÈ)3­ »j·i†øŸôdMk†‚ÿœÉâ¼Às®S\”‡.×T £nú)°9Ä«;ÿèì?eÝU×gJA\õ­Ëw»äk§ÊÝF»4>ðáá˜dµ—áCšƒ%º-´¬k¥{x’Í(+ká[¥ÏÈwþxÙ  +ÝDn½3–gï  ‘endstream +endobj +2252 0 obj +296 +endobj +2253 0 obj<>>>/Annots 206 0 R>>endobj +2254 0 obj<>stream +xÚ͛AwÛ6€ïþ<î¢ ‚G׉»Ù—lÜXû‰vÔJd*QÉöß/3 É&èC-¦ï¹A0ø, 3`ôçËróËJž*[í®~Y^½½­2žgˇŒÉjÁ2UŠl¹þDzþºm²î!»éÚ¾iûÃ?—¿_½_^å‹Ü0àƒ_~…F¦ +¹ÐÙ.3ÿÔØf÷€?‘ß?fooeÆüB§Œ¨ùuwûæ¡^5ðKŠbÁM—ùÇÅìÿ°gµb&f¦ÇùBµ” k¤–··‚”`BñÂô˜ ßÿuè›]ö,4àìÌp±1•ú‰öùG³ÿ±i~N°E5#¥¦ô–WƎv™f&Ø ‚¶X¾°&ú®[wÆ4Ÿ×W0Þ苗F û/ÒŸ‹òэ'ua~M™‹ Ìï2©íü؈¢†áFO墈YØkožgãv™u%„ºîöMÛoÚÇçaÁø]VIc茺ŔMŒ6“ù¢ŒYÔnòâPŒo©*ëu¥4†§Ü‹,st²Ëo͈Æ=Äh\€~C"v;Rz‚ÑzÁ`ñCö{^gÂÍκ!sØy)åKeÝ0*Æ6¼’²DšžE+9‚ »Œ3vöáH€€›öyV8Ú°$ÜRD,#àI×Ǿ[u탵²êoLR›• ¥ÜAa#ˆR\b”ú¥>lV#Î͆°žƒq„(ê'Ø=œ8W”¾›™‹Kí3³Îöv%/Á4l+ØgŒcbÿ¡]më±Œ‡»ë“Bš  É&:*ÌCc =•Æ@žÃÀ–×SQUë~mú„7 +ƃž +ãó#š à¸7 +†ƒ7‚ÃH€`×?êÍÖ^ ¸$1û>Wf¹b$ ’’äÈ' †hö ‹‰N€ˆu»ÃÁ-é3 Tçç³üo»BMَ–©á‰­Àv´šv%Ç;܀:Ù`‹yœLuBK%£ƒäAØ +´dd4úÛäóãAMÔҜŸxÌ É`ÿøù{¿éÚe\ +)eKáƒ?ÆV lYap»©ÛU³ÝŽë;@À­ÇNˆ9ÜéK=žOBÚx¦”ÙCØðùD!Ʋ-—w#鄂MI –[ë IÔO¬(€w¸y¥)³*ø%KjfeŸ§gÍfÍ pvÙDJO¬B'Îáñ[ž¸ÃM×¶ÉÃMgϱސØwc^Ώ…m 7º1 T€‚¡è.Ù öÞìí¥¢ºTœJ-V.ÃÀ”Ë80åêeÉÑܵF4'@À/ÍŸÇæÐkšy`Ɇhšyàí¦Ù®¤k5K]óŠÇÍg–Ôòºæ=8Ž ]ûñøÔÎcš à˜=ƒaÙ ŒÅ( -›uàâÒ÷¼)u—ÕpúÓÔ +Ô­ée}â©f ÙSGD#œpª` +r¨†–Þ'Âu5Ì|8ÓX¼ïëþˆûD¾~Ž’Z2›/àaBS+X2UbD¼oÚuò4¡=MT;8MhœàªðãÙ;à(*{W÷õEvJ͒ +ì¶5K²¼:¥d?zð!Ë ˆÉ*VWæ§Í ˆHŗ»xO¤×¼ ð“Øðé5T\ðán$»†î² +ª¤"v;ÒÉ]ÝŸ#RfÉ]µä¿Ø +̒S­ÁÄ{ Ù;¢9Î.Á®zbX®ÀjlzbT¯p³oêÔ¥‹`¾®cœ bݎ'ëÚ³l³H€X£†_PéG0Q”¼`Z’Z²<nX±,YN×ëõ”TÄÁ$;…9Çëûýæë±GóŅÜ %1]W‰šZ^ILëÄþeÓ©ˆåtÚ¤ýX¼üQ'$Ð ÚƒÖÃtƒF}jÎðâv5K-UI…!6Äc+XªR¸SÞ¤b q¨ŽhN€€ãËåGÃrÁõIÌ"±˜²`~8¤ÕòtšN`˜éá{תg~ýÃ~jÁTN±µZÁ‚)æBajwãÁ§4#àq'þ‡_¸²*¥#QqÕµ Áæc×}O†Õ€&¹ÙÂÍxÜòÛ¾;>~ÁxHWg8 à™Ò_×駔\`a­²ÂF ã‚ÊjF÷f0®Áª"õÊxÛu½_ÝzìuB  âçï;žA„ºˆU§Ô̱€uÁYJùT%…`n†ú-èýÿú¦=…ŒéØП–1Ï <¥áò))ýæTגsãì±(8ŸV" v×Ê mŠž8‹òôÓÁEż°%Wã'è +«T4Ü_Uq¹KE*ëöñX?Žýh¬& +{Ÿ®v™Ï :a‹:¬rÑq‘‹~Y‹K\ôY…‹žkKBC*¬oQqy‹zYu‹ +‹[ÔYm‹š^ÚâHêÖÔYa‹#½kêãvìâÌ ¨ž¤"vÍm˜WÏSY>¾D’*?¬e\E"Õ ȁ¬Cu«‰Ëã8e_§§>9Ñÿã¡lžy#v[ØûvÕ­©¼üÕ¾™Zá +W@y"®[T2qeŠÁaJDE+¶›h£ÏUÃН=eȘƒÝę°6ž9‰>ýXØíjsLVkÃåkŸÉG >Å~'ƒë(RrªLùôáÓûÄ·=ˆ¯‡y„ÁÞjþ5¡¨'?½|øZ·¦jv7cªrßÒýr}»ÌÞd6M»ïúŸõ¾ÉîöÝã¾Þí òïSÝë-¬€Fޔø´¿!Uþvõ}E¾èendstream +endobj +2255 0 obj +2493 +endobj +2256 0 obj<>>>/Annots 250 0 R>>endobj +2257 0 obj<>stream +xÚ՛KwÛ¶€÷þ\¶ +ċ$–©'='9UmµÝtÃÊ´ËV¢\JNÛûë/3ÛäEC%[cŸ„`0˜¡ÿ:cEiþ²BTðo½=ûnuöêR¼,V·SzÁŠª–Åêæ›UûÛ¦+v·ÅÅn8tÃaÿíꏳ·«³rQ|aðåê]QóEYTB-šb[°²^Ô$mŠkxƒG#Æ»âÕ¥,ƒ·¬¹é[™¾æ¿֛‡›®øì…lóNÜ~Úð\^ö›Î~l¦Í¬Í³þaeF…œ/*˜c IM Ôą‘Í$>ìڛ~¸K¨)4íÙNMԁ€m +¥Ã¦¨7Fé ôñûo¬`´ai֋XԁhoÚCû[»ï(š…ø¢&ÌÚªÔF…°Üµ—[±r!q[ãÁV•™{D3&\ÒRÓP°” G ìàP×÷ݺ¿í×){M Cl°WDÄŽ˜±~0~[p3¨~DÃ޶ú÷ÞZž³û2–Ï™\éjÁ½ÉQšL®tmäãMîi\-xL“{Üá÷”C ƒÑë…~„¢ËmÐi<\<ù`ԁh`¢”ÁEøÙ´2vŒiԁhæ¤ù<+mOɍYԁX‰}†u¨«ÌuðæÜØuȤY°ÿý:Ì.B£´Ò.Â&l¥`6äu6‡n´'‡iœÀÙwÔ Í¹mfXi{¼«,cš ‰XT]âѾ\¾ù¼ƒ¡ÛÂÚ6â`³#]wã§~q‚æg'¥­#V„ªð@µ±JÁŠ0[¶zApåi6¸Šh®¿²àJIAG,Ä>(j’#ƒ«‰¦=; +®<0\y”äOQz%W|8xKq|Œ’Á$½OS³Y.k.Qúö")0—`蝸?ô»aŸ>l«‰Æp!Íu `;ܤŽÛi¸Uåãæ:ìݸ{¸Gdz隱ŒªYMGŠöR jÖ¼$ªq,Ñ}IJQ ÂÚ!¥ãi$¬d>'âP‡f²¿=è ”œÏe•\ +ºk/J.åâEjv4ÓG4«f‡ËÞõãn“'·÷粚2Q#8ØZx!Дè\³ÑO0ÜD?p{ŠXµ˜X‰ko0€„5b¨@ïW?¤¶þ4 'c˜ë üùaB2‘‰ùӄ٠’¥ò‘4¾~&’%UÚe:’v0ðF4l­Ž‹¤F=ÁPsõ’HÚÑ´|LSm9öƒ±[bÿʀ‰ó:ÆQ;áތý' +̅:‰(•©ôæšO8 +Ïâ\‹¯*Wé×Ú9xFÂtò†ÊÔGQ„'`DÂvÇ:µ0*§  +k¨BUT?½ØmR™š`0°yŒ¢vW¿n£o8M¨æ¬mf7ÂBmY+¦S+kð«vŸt,ÁXLûˆ˜DíXÓyÖþæ&çN¾l! MÁ3\HQ +V’¤Bíúá~ûá¾~ýæ×o[Wó–l³“ãTPm&)˜§jê4¹«®½yoþw£›"äü¿øY•™>±ÀH +æÅ¨ÔÏkÙÿÓmöÓ¼ä8;³’ê{¶ö„R0³’Š{ÓÌ.6»}ç×£ž¯Ò—žœuK¬Áš¦Q˜ÜkšãCqG²sD2¡8‘r¸c@¢¥‰!Ôn1ï—çˋéDN3Áäö#˜ë`ôpL}š¶‚ëˁãëg"pVQÑH¥#p³rDÃV¢ä"p‡QO0ÔLœã"pÿ¡Jk±§"ÜwíúÏn¸Á³MÎj´gÌXg¶œÄ2” üPx.|f’ŠQ_Iø\§½(®Z‡:J“eÂW«ŽËc{œÍcG8×A¹€óDòØ9qæ}_ER  þ²,¶§Ù,vDsN.‡SPY»ø ~Êæ˜ç‚±î‘¨X§vË(HKòžMÒ2 +,5Å®ºÃØÓÍåWå6›©F¨4¾fu|ŠÞñl†¾‰ë`x:ùù&óûX´²)ô*.UÚ9Âlr¾r¥/Ø![ tj™ù&ó±/}q|<>\½,)O(ÌÉ«¸úʼnvzùøŒ~$–ªl/ãڗä‹Üd#õdâÊ]Oµ… låþí¾ÝäŠs,OƇ,x$Ρ–»ñznȏ…ç;›G£fBQPj]k=ÓQ¶ž&Rú_°k(²<—Æ#Ԕ?{sõúrUœ?-¯‹ëÝíáïvìŠå¸»Ûí¶÷ÅÇvxh7=g¼*Îkn§Õ÷¤³Ïþ«ƒoÊendstream +endobj +2258 0 obj +2237 +endobj +2259 0 obj<>>>/Annots 296 0 R>>endobj +2260 0 obj<>stream +xÚÕZMoÛ8½ûWðØâð[ä1Mânlš¸·^\G ¼ðGjÙØýù;äŒ$ʈÅ™00¡õ¤7"ç ý{"‡ÿ‚U’)˖›É—ùäræ™älþ̄ñSÁl¥ÙüéÓ|ñk]³Ý3»ÞmõöÐ|žÿ3¹Oø”Føáãák˜UfêØ† >­(X³Çòýý »œ&D¸a¸ÎÂWávWì,~‚ 7ð§7 a¹Áñ Ž ßâøX7‡ÑÖvjàaáÏÓÿ –2°K9µHYQ@”/gšÞÌ+Œê?îÏg1A ¯;&-ŤñkF1•¥1›7 §»¼Å€8†lÁ´‹ëäùü~4[² +Ù²C$o±>r¶ŒT6ÌhàˆAŸ-ã+ˆÊ·û‘d%—n˜w(áÐ0!æÊ¶@³ùr +>7ÌI¨¹$ùrq>üµØ¾/õù”%WÃü’êԋÆu¹ËæÉz,Ø* Iž*ŽåúîÛÝíÈ*쯅,‰˜“ Ç[¬Ó<Ùrf–ä™dë²qðv1H’e*,Ê÷÷7#‹°¿4T, µoDãÕ[õ]MEQ«0›.xbªðž‚$]ZcU~X4‡z?Zã}% –«!ë·j|øÚG˜]¡Ç3¢Â2ÃÃú‰A×Gôq}íçDæOÁhøÝ\ ؞ øåñ°?.Ç}9¯ +›¥Ãw Â3^Ȏ/ïºæ¶W»P¼¨Î Gæì„ÒžS•ò‹Á»6 Ú ª>™MCwz&œÜ¦¡Å‰ÝÚǧ8³ãvyXÁ§µí +~KR×F]UTÐT½µmЕö<¾6WOO¿† üüôósÀ¯tISU곜+XZ½§‡> +¢ fm vž?hɐ¬J[‡Y‚FP§ÈA“0JšÈïjÿrÜÔåm}³äTED\¦1JÈ)‡íÝC R€KTɲ–h–¡ÔXÏ`{­(JBûËÐMÝ,÷«¸ã+ô¥LÓ,?!¨æÐhŒ~иÇJsûßbóºŽK^êª/Ê;¬/AA0èé)ï±¾<Ö#¾äR̓Ñ8A]­›]€¾¨]Œ—å 5š¦9F}_®œmåæz±]Öë?w¿:¹EuÒfæ<¯kõƒd>T VÉz“#h¬ 7% Ç‚U¬âäèiCÆ^PŒzÀD—®89†ðÀ²SŒ†Ja)Wqrü 2òNq0JøI^¶ÞäØq<ì@QàfX_8u¼Co‡ô&¢ñö§L½±ãz#=fÈP‡1êõFz:ËŠs³›­ÖõCýûX7‡Vu”Œz¦x±ÉñSäÐG±Á(á§ÉŸ/Wlrü$¹êQl0JøIòÔ˕›?xÔ z‚ ð¼Ü´8(7 '¨BåÆeä†sÚ½…ý,F‰ÜpU +åæDj +óÓüø„íù(8ôB¸âw79z•¢z䣄¼+W´ÜäèÙ֞rƒQBϒé]²àäjò¸£à`”0Ôäl—+89~Jw>‘ (á§ÈÐ.Wprü$ÚÙQ0HèÉwºi- +Ê꠮ öÒTæˆ[p2ÅEj¯¿ŸœLñ 6³}]ãéMÓɍ/gA+1>¹ßØè»[©w•¾Ö‡ëõ¢iê¦Ì>_ÉðLüß¤8ú!€0áwÀž,¤›‡«Ùœ]°øKâÇÝóáßžf÷ûÝË~±ÙÔû†Ý-¶ÇÅ:Ny£àҋ +­ÖÕjE)ý>ùª>F“endstream +endobj +2261 0 obj +1458 +endobj +2262 0 obj<>>>/Annots 344 0 R>>endobj +2263 0 obj<>stream +xÚ՚Isã6…ïú8ÎÌÁ¾±=—¤âؚÛ\›V)¥ÅђÉÏ€Ŗ«¢ö±m»TõL©¥G€_Oø{¦„Ì¿J_þžÖ³_æ³/wIh)æ/B¹Ô)áƒóçOóþÏÕ ¶/âëvs6‡ýçù_³ÛùLv2×(ª<<|AwRxãº(Ö"¥Î5±¥þ›ìâ˝J•w :?×ççæ7ü¾ïCy:?eþWÇäÇhÂ¼ÖÏæ•–]jª¹/µÉ:Û¹Þ-ŽëñTZŸO—¤=™:[ìIŸG²§dWgÌÃp8î6՜ÑyL !åХ⬠ éLS“C—ÊŒÌfn†ýÓnùzXn7u—‰Jú‹&?fJå+òëøÝþÛ¯_Wõ4‘Ó%Hºó Ø#óu™ øò8 â렗ÂY²ç…àøXêzµß–R*åÿ~„Ó”›O“ó@)¥‹½ªš½Ü œ @©§ãëþÛp¸^úãêðãӏϥl°¬f„!f„5•Xµ@3ÂZçŽC4€U‘ +94 +€ÅɔCY€äªCy™r'Í 5ª)äNZ _$þlfC2ˆÉžM +PC#y¬H>+Ԏ·RL‘l.#نÐî¬R¾q5!ن jHþ½Nô‘›ÈjÕ3ÂÛJ¬ŠdhFxÀâŒdÊ S Xe +9tšõ€2gðªöPÈ\†SäÞo(‡Ú¶5\é7 Cí€3|;å¯t$rÈ^½%|‘[Fd\¨o¥˜Ù^&²I±­ ^AMD6)§‘ïûýþçv÷<29:6ÓÁ]ž&T9âÄ4LôÜaLÙËÝ1ž` +ù º-ä¸â˜²ç"Àªâ²çÀŠ3Ž)‡Öf*ŽA!‡y¬,oSþò€èÓòg p†ï€ò—±/ÇvÙÓò}Íf¬Íæ¬ ‡BL[#ZD‘9Ôid‹ÅÇNs36oØÑØ_ž :A>^‚˜&ƒN-çÜn(ƒ¡%äµÝ€BcKÈÙ¶ʞ÷(m…ìùÀ?m¢:ƒÒ&PÈ¡cÞl(w&¡´ rg%÷´É_&©Öc²]PjB©ÖçÉöýn¹9 »ý)H lœš@ ¤B¹64ŽêäڔAÙrm©<ϵµl¹6[öTl¡v)¨ÉžŠìCÊ_h±vÅ((ä/´X›/H)~Š£USȟoa4_Rþl˜B"Ȟï ‰Æ:pß~V¨¬C¢p¹ß(cÛâ­l˜5õeÜýÚoo¾Jš¯"1´šR"h>hö‘=eOâTò'?@ªM8L8ÔNç™vbiæâ”D+“¹ØRh¾(&ÌyÈ¡+.}<» ò-„¦9܊†q8Úê0…p¤¶³´[,ûP€]6³xÌßÛÍÓöy¹YŒN’ÇElõ•Í”ÙóÛjþ›& w:¢=“:¾É„˜ï˜¬Þ&cò´³5Ž;[Ë6ØÔrŸ›‡ë»¹¸_¿ß?ŠÇíËág¿Äýn»Øõëu^ŠŠßúͱ_•¢WJ{q Ø\þÓÎá³ÿ%ª(endstream +endobj +2264 0 obj +1195 +endobj +2265 0 obj<>>>/Annots 392 0 R>>endobj +2266 0 obj<>stream +xÚ՚ËrÛFE÷üŠYÚ Ãó~,[ò&®(½óQ F  +H&ùüÌL‰†«Ìæ²-U±êbÈFaó6x‰¿JÈü¯DÐÂxñ´Yü´\¼¿KBK±|Ê¥N ¬XþþfÙÿ¶ÄîY|ØmÃö°»üsq»\ÈNæåA•‡‡O¹X'…7®‹b#”ônj-Ë ¾yŸïï¬Pªœ2”çúüÜ|Ƈáp·õ#‘_UðŒºÚ¯ZæW¸P[WœýêÂ6_©~%]© +ù•Š3¿‡ádW>òºþ°ŠèiaUúAZþ†EÚڎŰd—ššmR`X7ãê¸9]¬ZŸ7ƒ%‰øUõcP/Dð+¾~Lñy{öÕâó\†¯S|NU£©} á¹+ÝøTÜxV¦­söbuً­ í ¢>«É‹­‰Ý̍? ‡³vn¥‰vжºUµc¨´³âlÇ`íгW…•¿bkÇžI쪆 &<“ØãÀ‚$Œ¬¦Pˆ02¿ü§è‚¯©ã¢ ¼†ï¸¡ø\)SÂs ü…8§:0pf…Úz+ÅtäèË#ÇX×¾š³šFŽÉ†4 ,ãËvÅ4±0DGdÒ§‰u„1`Xœ'˜[Ož'(D¨%ëyCÁIžƒBp’@Nê„rP¡NÜr’/à€â‹Ür’Ï£€ÂóWä§:0qf…Ú:ë€üÂ6Չ£A¨iâh‡æÍþp;Ž»‘mâd‰†0("Âþ9¨[D^="Ô-"çìÉ¡2(t…•å:Q|R¢Ð Ⓤ{èDð©¦Ð Ą§b¼Î‘OUÀ‘geÚzdìÇö²«¹¸ÒåŠÔäÇ*Ø)tú܏ýR»|òäèØ´º#ZÁË)pZÁ+þh +œ@!B™Nž±(p…ðŒã8Q„Z¡À "Ԛ÷¨¡èd@(D'#÷À‰àKvʛÒ<ÎNîÚ´©Aƒ«Àªc5¹Ëƒ&žòð2g¢šMQO9Ó}?î¾cÆ·Å)dòóPÜ'þ“§nŠA “›'âŽ÷Ï˞ú¹ÅKvž†[Í?\"ðtÄÙRü&Zâž,U¸‰Lžï‘íYۅüñj ÒLJ›»¥x'>|¹»çÿý8ˆûq·ûÍf÷âs¿=öëú>æ&vâ]€pôŸ¶‰¿.þv*¸¥endstream +endobj +2267 0 obj +1144 +endobj +2268 0 obj<>>>/Annots 440 0 R>>endobj +2269 0 obj<>stream +xÚ՚KsÛF„ïü{´‚÷½Ø£,[É%…¢+_R1ŇR‰~vwÀ‚•ptÓØ¹š †þˆQ7Ñä_ %dú­„ñùÏÃnñqµøp…–bõ(”‹>X±úönµþcۉã¸9ìOÝþt|¿úsñyµL3ò•¿,A7RxãšVì„R*Ï(j+îóœ}Gÿ$>ÜÚtÇüA§ûútßôˆŸ¿¯wÏÛ.?Žiþ£éƆÁ/ë v­ŸØ£Lÿ€@ôŒ§M҉ä¾ëÄÿΩ¾žC;„ÇqÔõöxÈ£TLúGxšÒ)NO“Œ +áI=*ÄKËè•lÊâ=¼<ïúÍþt»Ùv_ß}}Ÿ§zFœ5\Þ}Zà´±q(¦p1$`¾×OeÝuà´î¯lMúšÎ¥–MDU¶åL^÷O/»Á:¬OOFÎGð2™O¨ +.Hð«ewzé÷Îèt£H:N“Å ª]ŸùÔúÍóisؗS¹¬)Ég XMI#PŸµ`5|‡â3ü%Lj +Ï(ð:q†98³AxG1Mœörâ8À¥”oª)qœj‡¼Y®§®¿ÙŽcâ„ÈçGÚFb¤)†qSDµ҂_qŽЖmâÔDh£Â×E\‡Â ìªØ1¨ +/´`W|í˜âóv´…ªâóL†¯S|NŸ){ ¢Âs¯4ãa +˜ñl çlÅñ²[ðúÐe¸¢&+¶é|Ÿ™ñ¯ÏÝ~ôâÀÔIb´…kÁlÅ ªUÐŒŠ±“€e;G+.ª"TºaýڟÂ3±«*¯ýAMx&F°*ƯýIÂÖá¥[PaËû•?ITÕCªè‚fÞ5‘|®º&ž‹¯íš†96³Ax¼D ¨ŠÐ`Î6j(<Ev‰Pžfß Q|»ì4 *>‰]6ß !ø¢«!b¢‹Ø`óÍ®…úºdA;/¯[ì®éÁ!1õ8:tà<ÆÓÂܚd8¾ê¿ó‡´°þ>‹—ó«™·/Î<õùx¿®¼_>/Àû7h<õ š¼?3ó&‹õ7Ûd!Ø4–Öp ӞÕIàLœƒ¥àMlrü-¯oWâJÜ|¹»÷‡ÇÓ?ë¾wýá©_ïv]¿¬÷/ëmžz¥´W*Ñ¿7ø<þ¶ø̤»yendstream +endobj +2270 0 obj +1218 +endobj +2271 0 obj<>>>/Annots 488 0 R>>endobj +2272 0 obj<>stream +xÚ͚KsÛF„ïü{´†÷ý8ʲ™Sª‰ºùÂÐ͘¯€”“ŸŸÝ1t•¹ºeä*ºZ†ú€E7ÐÄß3%dþ§DÐÂx±ÚÍ>,fïçIh)ÏB¹Ô)჋¯oË?·½8<‹ûÃþÜïϧ·‹¿fŸ3ÙÉ<£¼¨òòð[ÖIáë¢Ø ¥MgPmÅcyƒŸ~cX‹÷s+”*o™ÿo|þÙüŽûÓjØϛþ¼—MÎlÞÐýÏ_Î7صî|aWªì¿ª½ðå=â Æ§—»ã¶/³LäÂö*>™:›ù’Ì ž’]]0}/~9‡ü*ì'{=¶£î¶§C¥Rþ.ŸÝ~‰——°.ù|TónÒù?H—Ï5—B֙dõr<=öÏ~øòæËÛ2Ñ9>Œ#j¼½"\4ù5£¦Î¡˜V„‹õ >–ëºØuà´Ø_…瘙,á  ë¡?¿ ûjŒFço1bl:–Uí!t,‹¯%·ø¬¹XBEø¬£ákÉ->#ÁkŠo‚ xF×´-yœ–|5·ã(¦––¬Bõ©r"TēUyÑïŽóͶ=ÙGfçsj¬iªc!WAփ´`Xœ-¹hër,†%»„j"´IaÝ ë—Ýxµj}Ç%Z›x!€_ÕÄEðB¿âœ8-BoÁijâ€"„ށÏðMœŸS`55q@>§yçMºm¤Ö„ê/іƒWÅä£ÖÄîâ¤O§éÊÖz^ktüò²q,µ­fSÝ9”ځ×0vÓ&`û‹ÝTE•fo7-B“"±P¡I‰¹Ý4ù¢#vŠðEލC“.(¸œ)1‚À vÓ¾¼çÀåíÕ ÜŽ£x^ÞÞØMՕ‹pQ$Ë)¨É–K`TßÎçã‡íaõ}³__.p ;ÏR5a´PŔA5‘£†{ëÐ4-«\â‚"„ÆàÓKÜ&^>·ä%s@<-¹'N‹OÒá“Ü[îŸN´å5ñéĽånòÒrƒ xñÕ-÷82çjl¬[fŽöÐrǘÄ9ÚcË]"çþ[¿ú~)¹57;®°º±&é¹A5áØ'N Ï`Ï]á³Øs³MœžÆ’»&(‚§±äæœ9-B…5wÍP„PaÍÍ7sZ|rª§*Â'±œæ›9 >¡Ÿ®ÁbÂSñ•w9ãHœ«1¸ó=޾7*˜Ë-œF5Ž +Xm×ÀÙöËa¾é·_OcìËj9˜Ærðrê@åàÿÞ©h±æ®ŠZ¬¹ÙN Ï`Ç]Á3Øqsœ¡Æ–»(B¨™—j-:.^£P:‰57߸ið%¬µ‹±¤ëV;a©ÝNaC§ÀVœÃ4lÌí°‰P‹G—-'’R<'MÄN‚æpº|TlSç~Èámã¡.èÇkÔøëvÜc9Î9hlëù´©’3îºw¬?)n‘YEM²×͸ÕìLjáéHžKÒñ§Ž‰ùSI7‘ÉËó®Ÿwµ]ȧ@îæ ñNÜ?}~‡çó?Ë¡Ÿ‡ÃzXîvýp¿/÷/Ëm=Ž®¸ë»5éÍwã³ÿ׫Aendstream +endobj +2273 0 obj +1215 +endobj +2274 0 obj<>>>/Annots 536 0 R>>endobj +2275 0 obj<>stream +xÚ՚ËrIE÷úŠZÂÂM½K6«‰`l±c£1m#BӒ>ª*³ÕՎ¥–‰qˆ¸n9¥ÛºGJçυ2ÿSÂøòý°]¼_.ÞÝ&¡¥X> +åR§„V,¿½Y®þÙôbÿ(>ìwÇ~w<¼]þXÜ,²“¹F¹Qåæî“º“Â×E±J©R£ª¸/ðê7†'ñîÖæ;–‡ :ß×çûæG¼ù½Ú>oúò8&v:?ÑüÎÁ—·„w­;Ÿ½'™ÿÖ‹=m²ÎNîû^üoæWáÚy!<Ž¥®7‡})¥RÖÂiʗ8Ÿ&™²­|šBé*Ð]îE¯dWûîûñøœ[n×?¿¾ùú¶”ô²s|l‚Ww¾%\ò¹ƒ³×”Ÿ:ˆ©%\>ºØùrX=Õ~ׁS¿_d0š|›{UË.¡jÆz-¯‡§—í˜Ö³¹Š¤9Ÿ Ìd¹p sAB`ÝõǗaW͝Ä蒝‡¨É‘bP5]€ ù؆õóq½ßÕK˜¸´)éϚš5€#P?k!lø"‡òg$äKáˆÆžQ/4rÆ:€œY!<Ž¥˜"ǝGŽSRJº“š˜ãT‰ó±Øë½=!'2{={¢¤©‰¼©¢éi!°8ó†0hk;޼59´Iá;#®Ä¡ì…yU‰ª±"ägâP½…¤©ÄÕ8ôr†/q(NAÔTâ€jü9͛7”; _ÊëDcÎDÈš7càͬÇRLyãÏóÆj[S*–¶1áÆj!ÀÙôÇ~čÓÜò¸º DSԋˆÐÑ4…ҐYœ¡C4)bf耚š”ð½WèPö¢ÃwG: {ÑsGå/(›ŠP¿ !jø"‡òçâi^¤P5þ\‚¸á ʟu/… {ù…f/ƒÎX 3+„DZSè„óÐ1FCJÉò©ÔDc ¤T¡ÎÍîÕÇÏ*}$"_9DÓZrÇ eOâ p#Ý<¯$ÎÉÙ↰§Ž·+n@MötÂá6gàPL¸8 ‡GÜ|Cùóþ4-R¨ÇÚ|Cùs0Ô®TÑØsâf¬¸™•ÁãœaÏÃFGÓk´ÅÉxeÍ0ì‡4Öóz%Ÿì&¢#4ÌÉ+q@4¡qLΙ9”A…ƒòÊPC…ƒr¶Ì¡ìIœosä|P®%N·93‡p¨"ޏ+s@MUdþ‡rL³Vªq,÷Õʟ—ÓêˆÆžW—®Œu€9³Bx\±^Hç©£,ŒÇ£Í!b¢Ž²qZ¸Ý¼¾s§NDW;m€hºÂ8öÛ¤A­šíPCÍz¬Fš“¡Ù՘“‘ýöå0Ùfy ÙYh%Ç|u€2U³9çCí¨™ï Pæ|œÖü|œíÓ¥KX×Ô⫕±OҜ9A°1#ñàëZÌ|]àôǛOýi7-_~Ç1Ū¢þ|3­ ØùlÜjö ”;›}_͚xo €·É˜<íÍÆqo6?WŸÆyÒÝõíR\‰_>ߋûýãñ×jèÅçaÿ4¬¶Û~8ˆ¿V»—Õ¦½Rڋ«³Ò×ë5žÅ¿ÿZÉ·,endstream +endobj +2276 0 obj +1214 +endobj +2277 0 obj<>>>/Annots 584 0 R>>endobj +2278 0 obj<>stream +xÚ՚KoÛV…÷úw™,ÂÜ÷céÆqZ RKÙeÃ&´¢BW¢Ñ ¿¾—w†ä0@uµœÚ€€#Z#jx>i4­”ùW‰ …ñâËaõÓfõö! -ÅæI(—%|°bóõÕ¦ýc߉ӓxw:öݱ¿¼Þü¹z¿YÉFæÍn?äbÞ¸&ŠƒPÒ7Õ^¬‡'øáç­xû`…RÃS†áo}þÛüŒ]ÿr>–ç1:ß%‡;?AUÜkÝøÁ½6A…î‡ù^?˜¹ï._λç~w:õlʧŠ…Ëª?™;øSj萢ˆ?%›Ò3ï¿·‡ç}W^ÁÈÅÛ-þ\ºö ’Ì/ˆÙžK!ëìdÝuâ?됇Ây²ËBxKÝí/§¡”JùÞÿÃiÊi>MÑäۃˆÅKèÎ ºôÀ·¾þÐõ—ϯ>¿.Mn9]ȳU]éŸJž¥Ô8¤#‚„Èúti·¥ÝuàÔî7t#K6 qèDÖÝyûrãßú|2x¸¬Ú³«ð±g-$gæÔ YS˜Š84 +’†/sjþT(aÌEü©È›85wÒ@¾”(-‚˜“òåâ`$-„DZSâèëıÅÄÐävR3rlRRû¶ïÖýyw܎ô‰ŽM»›ë aC(U€bn"ägàÔ z‹y5qè¾3â +œš=§ ® +p@{NsÇM͟ 47 ˆ¿œ¾‘7njþrÂø 7 ˆ?í iø§æ¯‚ØSò¥œ±gQc)¦À1ׁcRœRÊ šcR‚”"ÀÙì݄Í'¯ìõ~0rä ˆ¹LôÜiS³ÆÕ@PÄ_Ðø®ˆ+mjö\„´*´Eì¹iř75‡ÖAÎހ"ókeyó¦æ/¿ zâ (âϾ¼©ù˹/Gހ ö´¼6c Í¢ ‡BLYc+¬‘03ϐI(j$ŽÅ5»nÿu䌗l’j2ë®÷ƒN0"/¼1÷ƒN8!çLœšÁ€3òBPÄaÄ9[âÔìymâ€"ö<¶9§æÐÁtˆŠ8tÌySsgÒ4(R¨ˆ;‹m¾¼©ùÓ0Ï.XAìig׉3Öâ, +áñq2Γ9î:s´çâaÈaEæâ:Zá\¡ókwÜöß&êDf´¯´„„ 9 G.äZ“3r*UÄyA¨Ù¡Š¼?âÔÌC6 +@sÁòߨ9ô’l €"½â¾5PógÙEüÙÈ}k æÏØyk±gÜ­[c@΢w¬·üuä( “ñhš€b&ŽÒÓ<í箝>àXÏëRž¼†JKÈ0¯ € -!#ÿµŠÁdÉÖ@Zɓc¾3PñYˆË yÔü*ö|$û>.ÒÊ'îÛ¡¶ÎB—–ÓlÇü››PûæfÞ°Ë9¶Õ·î `‘ñ[›¶Æ:L*Ÿi"™,Åņ€Nó‚À/Ç]¿k÷»¦¯k¼a¿qø¿fŸrژ¸1›?†|¹â4éþñîa#ވwŸ>®ÅúôÔÿݞ;ññ|ڞÛá;_Äoíñ¥Ý—®w&_oŒLwßñ¤þ¾úüº±endstream +endobj +2279 0 obj +1217 +endobj +2280 0 obj<>>>/Annots 632 0 R>>endobj +2281 0 obj<>stream +xÚ՚ËnÛHE÷úŠ^& 3ý~,=I<«Á8²²ËFqhzx(“ÏOwW“,ˆÊˊl¸¢]Ò!›÷ŠÅúo¥„Ì?J_~ï÷«?6«w7Ih)6B¹Ô)მoo6Û¯»^ÄûãáÜΧ·›W7+ÙÉ\£<©ò´þSÝIáë¢Ø‹”:×ÄNܕú?ýÃð(ÞÝX¡TyÇ óßúü·ù ?Ÿ¶}y:?e~©cò‘€×ºó^iÙ¥¦}!Ô&ëŒs=<¾ìÇ]i}ÞQ<(I<™:[ð¤ÏGÂS²«+fݟ_†C…3:SF‡"t©•h:ÓÔLèRY‘æCºžžÏOÇC=„‰ËB%ù¢ÉϙO©|†ƒB|±¿ß·ûç]=Mät +’t>÷È|ž@pA‚¿Üõ½øeô¯°—ì²lK]ïNÇRJ¥üêﰛ²ÇæÝä|u©äʯ¢Ñå,p.€Iýs>?ÿ]—øé˛/oKɼ)ò2ä ›ˆ5aMõ¬šG К°,‹sæP€F6Ë*™ +–Å6s(<À±jæ€Bx*rOŠOðHœªŸ´à4|‡à³Õ1ÇÄ5óÙ¤ÀmøfÅøKðB¡3g¬™³(Ô¶·RL3']Îëmu©P¾3‚˜3Çz&U2çöx:c77QË©j[5v@ eá4óÐ!ñLh®UBâ˧pä:$ž¶`Z5t@!<íÀ´ÇIXmfŒPˆPi0¶±Cñ™á[QP3ŸI ‡mì|с¿”lð¢]èŒU teÚvÏ7r.ì¢9&¨êQ™Ê51GŽ ,ªFÎðt8?L¡“ØøÔW+ÂE¸ª+Z.eqÎ +кfY%s@!Â/–uæPx9Bô”9 ž1àXœ3‡"Ìþ!§Ì…µä8tSÓH5…èdënóM‚O'èm×`1ãéÔZÛtæŒu s…Úö±KÎ3uÔåÔÑzäÁåUbN[‹¼¦ÎËt“W‚ãyÓEM, ó; вð­aÎ9v(@×Zæ5v@!BÇ;t(8Ó:Ý5t@!8ÛúܜC‡"Ծݒ+¡ +êÖíæ;Ÿ2SßH5…øTkpóŠOB{²A.»ÛZ¶îö+b§Õi±ƒ µíc£œgìè˱£"´Éë=sì¨8]ê¬ûí·éBÇó»SYÍå%¡‚™G @ÌKBË~Œ€ô€B„^ñ# ñl@c žìÇHBcÑ(Dhó1’O+4F +ñiæ½5ŠN†yŒ‚“ñµccˆœE¡¶=r#¸°›j䤹Gž@̉“Ü>>>/Annots 680 0 R>>endobj +2284 0 obj<>stream +xÚ͚KoÛFÇïú{Laöý8:÷T µdô’ kÑ® +½JÉh>~—;Cr ÇüMkÈ9;íhþ])!ó¯A ãÅÓaõi³úxŸ„–bó,”K>X±Ù¾Û´í;qzŸOÇkw¼^ÞoþY}ݬd#sŒáE /¿å`Þ¸&ŠƒH²ñ(öb=Äÿé ý‹øxo…RÃóuxãóÿæ®»NüòUØC~¯jìò$xCÝí/§!”Jù¯røKÃà'Ú_âå Ï·Pë|¹ùÆÆ @ºü¬¼6Yg’¿¯×óº;·}{í¾¿ûþ~ˆéeãøp¬#òE¦ü 3lʗa‡œP²)Iøxi_º!æEHºäó%çdÕ²I¨fB— !Uû—×ø¼¬góI¼hòkƓ¨ +/–Ç÷Ð]_ûcA3:/MFäó jM^wUÅ$Tš/Ýå©ß¯»Ó±<ÀÄ%MI>çK±j©BUñ¹Õæëöpޗ%h"§%HòYõe0žµP_hÏã€ç,áq ÅÔsÜmÏqF–*•Ë‘B1{Ž3 +ŠxÎõ~×í·œ=Ç9¡B©YÅs@T9¡"wÇ¡ð¤Á’U§¨ŠOZüpÄÕq<[ÖÛè8 f<›T,ΞC†µ¦x¨Š0D¨4|=‡âó>ÏUñyՆ¯çP|NA}RD…çôÛgŒ޳ƒÇ5c¿ñ·ýƚPjTt¹î€˜ýÆæÇG¿ÙôíÓ´Á±ž×Jžp‘Ú–npUFh%‹³çP€%IGÏU*ޏzgR„ŠU<ԌgR‚ŠÅÙs(¼åä9 *Âèy;EÔÔ1R¨*º ¡ÞðuŠÏE¨/ƒ1€¨ð\‚úB{Îmíb *<]mÚqÆ8à8‹@x|lótœxÛq´ƒöxÙ瀘G»ÉoþìwWþ»œD䄁^yñUNXl•sö +Pc³¼x¨ŠPc³œ­ëPx +{ÜÅu@Ux +;ܜ]‡"”¿Œ+®#å²lIìsóu‚OÅ0õŒª™OE滊.˜y¶Dì[çÆ8à9‹@xܲžH·=Gyl+3©Ùt”Çùî|¾Ûn?Nû®=ŽÖ,§„H’HæáUBØÈ~x€4¶UÇ{x€ÄÓªUáiîM5’O†jxTÅ'#óáŠ/Ùjv -»ÚÉ1Ÿ à¢šⲟõ[Ç08MŽjÎ37nÌ©aO\…aN-.F>>>/Annots 728 0 R>>endobj +2287 0 obj<>stream +xÚ՚KoY…÷üŠ»LîÜ÷céÄñh‘LvÙ0q1âá¬äççÞ[ÕômK¡ØMŶŽÛ.øšâº¨ÿfJÈü­„ñåçûvö~1{wŸ„–bñ$”K>X±x|³Xþ³éÅþI|ØïNýît|»øwöq1“Ì5ʍ*7ó¿DНÞ¸.Š­PÚtÕF<”;xõ‡•xwo…Rå.ƒÎëóßæ{¼ëßëçÓz¿+÷eS§óƒÍºÿù+)‚]ëÎv¥Êù« +Ù _>#¾`|ü¹Ü>oúRËD.lWñÉÔÙ̗dÑà)ÙՆyè{ñÛ:Í¿Ây²ÓBp|(u»9îK)•òoÿ„Ó”[X +—|~Vói +¹ @ ]~­¹ü[]HÖÏÏ·wËSÿíÍ··¥¢—ãC ¨úrG¸hòmFMù¡ƒ;ÂÅú$~=.WµÙuàÔìWáù„f&»„ªá  ëö°zÙÖh=›g‘ÄsüJ–Õà¹~5ïO/‡]…3:3z +IBkÀijj­Ÿá›8Ÿ‘Õj q@5|F×ðMŠOð— <¯Ë›¡ +äͤ ŒÓFi# x” Ń«jâFZð(ˆ›¿ó[¸U8'Ndör6—ÛÁÖ§ ãÄØ6)ð+΁C†€~UTC"¾/â8ž·`W5p@5xށ]qŠÐ)°š8 B§yÇ EgxMP ‰à5|ã†âÓü¥8 ˆO;ð:p†:8“BxK1s9rlżˆjŒ«4¸Ô$rŽCæ˪#ìåŽ0)µ\IcG˜”À°8'VIP aô¬ó†‚ +ß•¼ÕÀ ~Å9o(BÁijހj]Ÿá›8Ÿug«Q¨¾Ü‹–wâP|¹áô8 ”bš6îrÚh=ÌÅcPi£5Îś¼¯n«Ïp’'BÁ|¼ˆ¦!ŽÇ9(q@#§r-q@Î6p<q²]Ԉ§"ûËŠ/˜f›TÃ,÷ŠÏËfcTÃç÷ŠÏ†qcDƒgãµCœI!<Yo øË£ Îŵ=«1p”qíÊÀ¼?î7/¥×‡Ð‰<^Ó)Í Õ¸,¢iÍ~’FáÉÐ, €jødd¾,@à%Ûì +¤éh<9þ›^TÍ¢@T£Ššûšçc³%à§ClŸ¸ïj‹¥Y˜Ž¯Ý•Ÿ×` Üp¯×8T¨jГbù8RMv¬nWÆX9_Ì$Éã5œ"ñ&?Ž[:¾)ñß ¨t#š>>>/Annots 776 0 R>>endobj +2290 0 obj<>stream +xÚ՚IoÛH…ïú}Laz_ŽÊâ9 ±”[.LL ´ Ecò󧻫(6 D­ÛÔĀ€gÆ%}Té=±X¯ãñG0'™²ìÇaõa»zÿ˜älû̄ `Öi¶}z³m¿ï;vzfODZ;Ž—·ÛŸ«ÏÛox¬‘Dzxü#k8³Ê4ž˜¼ ¨öl“žàÕ_ ;öþA3!ÒSÆb•ÿ7>ãzؽ¦gÒ¶1ñ¥Æ_7ÿõ¿à+èR66¡sÛHTˆžð¤Š:r\Ôãó¯öpÞwùôTØîâó*>Xà±Ax>¿y›®c¿­Rü!œ%½,ƒÇs¡õþrJ…Dˆ¿û?œ¢è?ñÙþ%|4PÒ8՟Ïë§§Mwn‡v< ßÞ|{›êº@çB¥ŒÍvBÍ¢hãÀ­¾^Ú]îté(uú]€Z¡[¥(Uj nE6njxŠƒYå¸Uà)fE9nj„Ñä¸U +O;ljt\¡Óä°Éª ãœ†nØTøt 3žü¥7Sˆ›E!<Ž¥ˆN¸8Ú9p©ØÕ8Úyp) œq菻)m,!ÌFp^髳_å¼Qôƒ5`Wdó¦ÎgºUŠP ‘tæΦxUÎP[4&O:kê€RƒÉä¨UJC4lêxÙ;§¬Uà &C4kªx*x°–” f:XK=j¦:5‹BxKQŒš[g)'ò Š»è; æ¤Q޾ΙËõ²FùVœ8E¥âËõSЀ(ºÁIð*ÂASã3½* ¨Ðü:D4jjtÚà÷¡5  +º¢‰GM 0¾^yP R`1d£¦†=‘_£T'9é ©Áq˜nCp³´Žì;‚ë`Д…ðø4 '4âvÐȀƒp‘Fޠ树á1j>µc·=mûCwGSpy»¤ƒaxŽs/H³pÂ1Sã³8 Ï1ª´8 §35:ƒCì3  +:C=djx +ÇØ9d@xÇØdC¦†'íu&$Px‡×dc¦†'`r³DA'pp]™©ÄÌ¢Ÿfà$cFVb†ÃÜÛÔ¼˜§”á8ÿN)Óí»ñš0:º˜™aÕí–fá9m@Ì-!<õKšSÅÖ¨Ïiʛu:ˋÅPÄê€Ú{  +@íIïÔñ”.Ö@xʐ^ ¨ãI1o€(è䝳³© +dÍ¢ '<9S·“&MÌàrÍ¥þæn± ¸¿.<ôǧõ8ý÷—9qèl®o÷BÐóN@XÁƒ!¾P…ó¢Øð˸—”·ªhÖ»v9·ø&@•ΘrÀ,×hߘѵ3Å€^Žªµ$½Pe“~¾ÿ/—Cjî½ûEð +Æ¿º÷?Õ¡™*ùüÌ\üºõêqëU˜ÆÅç´6ù¸~زwìã×/¶9=ÿ´CǾ §ÝÐÝpa¶Ç—vŸA§Nxç`œú«ï{<­þú¯Àendstream +endobj +2291 0 obj +1221 +endobj +2292 0 obj<>>>/Annots 824 0 R>>endobj +2293 0 obj<>stream +xÚ՚MsÛ6†ïú8&3X|ãèÄq/mǵ•É%5¦UuôáRr“Ÿ_ Š`:Ñæ¸±=ò¼ÃÑJ¾¯¸Ú dú¡]þû¼[¼].ÞÜF¡¤X> °±á¼ËÇWË՟Û^žÄ»ÃþÔïOÇ×Ë¿ï— ÙÉT#?@~¸ÿ%Uê¤pÚvAìD­b+rýož0¬Å›[#ò+¦7áÒÓC~ÁÍóó¯ý~}úëÓ«O¯ó‹YÕ©ônÓ¡ŽÍHûÝuð*¯ƒRKëc^‡"ê:x•´N:}8®Ö}.¤P²‹U5€ »²{®‡õËnÜ5Æ¥µàIÒÙèÒùHt2ÿG5Ñ٘ÏV¸ïO/þ°i•v/›Hóéӝ®ª åäÝôÇÏÃæù´9ìËé‹<ö( çbñ H>†ªóæý×Õîy[.?ø\~4žuh-2ýCÑÐYÖòÐ÷â»uš§â2™y¡z¼–ºÞ¹Ĥ‚U*Ad.åó©EQáRØXcПRØüÞ“Æ¿¤AXGl -‹_•´AÑl hWŒÓ†â_í*§ ª笡ؤF·Â¬)ªa“݊qÖ€¦¸É˜5¨&@]†mÚPxÞã'¡’6¨¼ä?†uÚPxΠµäӆ¢¡s­…N›±¦Í¬P=^KñLw9mŒ…bPÞv¾Š)mŒU5kîÃi ˜8Ôÿa=±%´/ŽUÒE³%W`ž6Ÿ2Õ°rÚ j•­‹˜æ EW.À1oP5t Ð¯ç ¨c@§)yƒjÔ1¢Ï°Í +/Xü,TòUƒë´¡à< µäH@Ѱy…ÖB§ÍXÓfV¨¯¥x¦¿œ6چbPAžÅ”6ÚFô§”7÷ýê‘ÿÍM ö„±Å°JÜ höD2^íª_å¸AÕj]?1Š.]Yò7¨:%™‡ …'±ß]ÃFÚ¹cÉÚÔf6žŠêÜ#‚ª&<k›mÜPx»Ø%P4t¡6±é¸ë`ÜÌ +áñ±ϸ —ãF¹Ú ‡|ºQMy£\톧¼Ynvýòp³:õcêxÏd$ö‚Å–x‰Í^°ÜC†¢Óµ'^BUƒgjOœkÈPtª¶²KÈ jèTmd3Ž +týº-Ç ªj;›mÌPxRž›CPUƒ'k›mÌx°}]²ÅDáïiÆ*2³2õ8ã;šx9bÀc<äîŠ)aÀ›óhÀÇa3…‹1 oh$±œœFP4»Á÷Ñ’Ïøf4UhëђN›f4UC§-÷ÑPA3€ªT¬›g$œôÍhªNÞ£^4Ód@œ·­£ýѹ€Zc¦­‚G-㡀 ëSb&Àù6M¡˜R&ÔÆ÷.ÝÃ\?>Þn¶§~8߯N»ˆÙ¬0 ¸y÷ÛEµí$À¼ùm9/ChÆÌ¼óm÷!ŠN…f@…oÚH¼'m“çùÕPçWMçÓ¥U{<7÷×·Kq%Þ}¸{‡§Ó—ÕЋ»á°V»]?Åo«ýËj›‹^râÊcôëæßºˆ,þûŸ4endstream +endobj +2294 0 obj +1206 +endobj +2295 0 obj<>>>/Annots 872 0 R>>endobj +2296 0 obj<>stream +xÚ՚MsG†ïüŠ9Úãùþ8*¶•K\åHøæ ±V”R „çß§gº—UUhnéHUP/ Í>;M¿ÐÓ,ŒÒðoT²ÊEõ}·øiµx]”Õju¯L(K£bòju÷fµþm;¨ý½ú°<Ç緫ߟV ½Ô£Þ˜zsó3[j]XfµSƘ£©­º­oðꇍzíá‰õ-áD¢‹ð\xÇO?Ö»§íPßÇ奅…—ÿù1èÖ.#  w(ˆ¼ÒY@n‡Aýkœî¥x ý<§PWÛç} e +èÿÁU‚†«¤ PÜRD©^¶´Û=솫»»ÕßO÷7ßÞ֘É,ƒLà´ç³!”¹ ÙPà¬QLÙJ $_Ÿ×›–é6ÉÉôËø²ƒ[XG«aQu€¹­âÕa󲋆B֏g‹‹˜®Ë†ªcK ÕÍp|9<66gá!1Ëdžˆ%J‰#Õ†„æãðüýððt|Ø?¶,2r”ÇókL3!Tž÷XcÄ ‡ç4––ê(::g°´ðF3ÆA£™¢ãJ¦ÑØóFLÂ\‰Ôd4ÁäW6só²=YMqJ•1ŽÉíZ™B‹i¢Ëí±J ¶†Ï·,-Õ苡¯ABM†£K‰¾U“AÕÑ¥ŒEJ°Ép€Ñcyi&ƒªŒ‹‹X“áð‚ÁúÒLU‡¬h‹áà\ÂÒR?s(:6@ɗYÌ-fˆŽS(™ãÎ[Œ·ñ¥šMLãmÀúT=æã°Ž'{‰ZÐ/$õL>´õ#«AÑ僱X«[ ÃçJ¦ZU­ÕèJ¡/BB­†£ËKU³T]ŽÂ†ÃK‹L3T^²XbÄ ‡ò©dHux¡`™k5žXZª èèàCæ/³š1ZÍ,§P2­ÆŸ·ŸÉV t®IÐÔä5Î9,PÕk®¶ƒà¾Y`Ò–ENƒ¢K«…û G§©=Ž>£Ã¼TijKõ†Îê\7ŸA5ÑÙB}kÁNÃ&j^7§AÕfj^‹u/ÆSCȐêð"5­Å: ‡°eÝìEG.ô™1 +úÌ, ì2á¼ËX‡ïRíÅd2ÖSߛLæ8F‹ ²~ÎTÒÈä‚Åx³].Xj€ 6ŽÏP ¼ ªÐP \ªÑptš:×h4zÞ·šúւ†4™š×ÍhPM€&ËþAÃÁ%×Í êà’>ÀáE=Í è袹t`ŒƒF3 DǍä9€xÞjŒÇöw1'1Yñyøe¿¾;•U‡51 áü4 +€¢Kďp|Öt£¨:@+ºuƱéԍ êØt? +ÀßM?+V%Ÿ`زéÆò¼i­ð!†-æi ÎÛÕ±\:@AhÒ,¿ÚÿãÈô—ÄlÿcË»m̈́0ßû?mË|É»2™Û•™öÿý¼ëí­øÝÎænóßæW­$Ù[ÿ mâÒ§y×<λ©Æ2¶‹n®®WêúðõË­ºÝßÿZõå°ßÖ»ÝpxVŸ×/ëm«QA«w Û ?þ¤+øëâÈ©™endstream +endobj +2297 0 obj +1208 +endobj +2298 0 obj<>>>/Annots 920 0 R>>endobj +2299 0 obj<>stream +xÚ՚MsG†ïüŠ9Ú­çûã¨ÈRNI9¾ùBÄJ!Å;ÿ>3ӽ쬫BëØ‘TT½»Ðèzûezû¯…2ÿ*a|ù{?-’ÐR,Ÿ…r©SÂ+–ëwËÕïÛ^ìŸÅÝ~wîwçÓû埋ûåBv2Ç(ª<|þYÝIáë¢„’¾Ó¨¶â±¼Á¯8¾ˆV(UÞ2”çúüÜüŽŸûóëqWßÇè|H–ƒƒ¥"¯uç ¼6A…ð0õ…åcz:nçÍ~WâٔWŠ$'Sg žR%?ªjð”ìjÆÜ_ ‡m_?¿ÈíMx.•”D’ùc1ѹ²Î }/þ3NóRX&;„ç1Ôíö´/¡TÊGÿ«”/мJÑäÇAǵ .Wk ›¡ÿµÿöõÝ×÷%˜Ó|²`âLD6øT YJCÑdCP«¾œV/5ÓuàÅHó9µJv UèÔªÛãËë0–}ëóZp€¤é¬RUmTCg-”*ÆVC E¦Z ¨Ð((1l­†ÂS¡V°P žŠ¬†‚“JKuƒ*6i¡´¼Áh0MÏc(žF“®­ y•ÔELFcóQ?ZÍòŸCÏÚk´¼ž6„Z­ª×€˜†Ŋ¯×|Þb±*^ªô¿ñô’Î)¨UÕk@5tNóvϨ2Õi@5x¹òFÎNCâi ߃ªÓ€jð´ƒ:ÃÕkH¼ê è5 :¥¡´Ð^3Ư™ÂóŠ¥×\Y¥ê5&ÅZ ¢Íõ Ää5&%¨O‡Ãún»?]¼ÆzNò«®§„‰®Ö«ê6 ¦”0Ñ3÷Š.(,WÅk@5xAãW"¦^CѹÕªz ¨†Î%¨VŒÝ†´êLuP `þ¤,k·¡ðŒ¾ô†ªÏ¨4l݆ÂËU_Žn¢¡Óòm^3F¯™…óˆ§Ó(ÂiäØ/;vPÕH쁫Ù›§ói´o¸•b}=t‚vx5S6è„ÝpÆVCñì‡W«ÕFì‡sµŠÎc»Z ¨†Îc›±ÕP€:Ù`5 @ÇÛh(8“.½!…ª³Ø¿fk4ž†îuõ Ææ5m5c°šY >>>/Annots 968 0 R>>endobj +2302 0 obj<>stream +xÚ՚ËrÛFE÷üŠYÚ Ãó~,eÉLeá²#Ñ;o R˜ð’Jüù™™ U™­]ÚR«® 6u€Æ½¥Fÿ=SBæo%‚ƋûÍìÃbö~ž„–bñ(”K>X±xx³Xþ¾îÅîQ\ï¶§~{:¾]ü9û¸˜ÉNæåE•—Û_r±N +o\ÅF¤Ô¹&Öâ®Ôñ†Ã“x?·B©ò‰ùïðÆçßÍøõ¸|êˇèÐéüWæu,¾”v»ÖÏìJË.5Õà  6Ygš«ÃÓóf8“ÖçóÄ’¦“©³…Nú|]@!:%»Ú/·ýéù°­lFç+Êæ’€.°rùLgš]*í˜Ynúãýaµ?­vÛz.¥ñ¢É¯O©|wƒBx±^½ß—›ýºÞ~&ò¹ýh8ŸÀvd¾Ç@ ¶ ÁZîú^ü°z+œ$;-LJRWë㮔R)ÿô'8KÙ]óYr ʺBWU£Ë1à\ƒÚïæ«íçåá¯þáúÝê¾ÿöæÛۊ+ÿgSVڝ`Mµ©@ P'X .Å8d(>#›K•…—â2 +`R5d@!:™G …' Ø DLUOZ0¶CàÙê‘CĀñlRà/lC†Â ¬¥p@t!‚µÐ!3ԁ™jÇ[)ž!ã/‡Œõ JU–ªÆ±ÞAµù\»|ˆ—`9µC ÚÁ©êU5i@ vpšyÎPt&4«*9 +áå7rΊN[pªš3 vàTŒ“†¬Þ2$ (¨48 Û¤!ðLŠÍdJҀñLJ`2l“†Â‹¬¥X(Dýërf¨93)ӎ{¾).§Œ +ìIê³SÆ ö”Sæ×#ü#3dŒ7ܜ8Íàbõªš3 P3¸VÅ8i(¾úßè4 `Ë9i(ºúœ4 1àTŒ“†̾!ÏI +jÉ:g(8éÎó Õ‚“mfÍ6g<`b]ãÄH§SXÓI3ԁ¤™jLJÙ7ˬ‰—³F‡„ +Ԙ5:¶ÉwΚ’47ýãòy}:y5«JD7x€× ºÁ·ù7ã ¡ø\›€ÃutÓ ¸v¬c†b3mp]cb³mlÍ8f(@Ýf×5f@!@Ýf×lƒ†ÂSæ<RM!<ÕæÖlƒ†Â“0µ†4Ó¡µ–mhýŠ iuZÐàBíø0ÿf4érШئߪÌÁ@A£bD1óbp˜@*#/w‚ +f\1v‚ +–ûÉç%Z…½b½@Òـ–@!:¹/€Æ¢%PÐ8ÞK$žVh ÂÓ¬§f$œ ãÄ&ãk—†:2“Bíxd¼pá,ՐI0ùN.÷w²“ €äÎ Ÿ÷ýv~ž™¹Àé&Lu¹¢×âtú5÷% +ÎG´à§ÃoŸXoPhÎá€éäÛ1(C±Y…žþ[5}¢¦y?û§ØtDþu|1IâýàØF0y^PmAU¹.ä;«Mznn¯æ ñN\ýr'îv§—‡^|9ìžËͦ?ŧåöy¹® Öåò.Àôû?«U;¿Íþ+„ŸXendstream +endobj +2303 0 obj +1198 +endobj +2304 0 obj<>>>/Annots 1005 0 R>>endobj +2305 0 obj<>stream +xÚ՚MSÛ0†ïù:£oYG +¤—vJI˜^¸¤`RwòÕ$´L}%í:–;CÄ­[`2óâd×Z¿O¼ñ‘`<ü +¦lü{XŽÞMGçcÏ$gÓ'&Œ¯³N³éãÉtöuѰõ»\¯öÍj¿;~]OG¼â¡F|ñáö=s²âÌ*SÕlÉ<¯,Š›Äú½`;gçc̈́ˆ{t2<׆ç†Nš†½º¬ì2¼VTz¸܎¥.»u,%|ø/ÿ©þùPâUwá}‡#(ex·ÁçÁ(tÖÊJtp²Ù<~Ú4«q»hîOîOcM«*IÅ&X•…fá>,`h_è46„àUêÀ»ÝlÞÄBÒýgþŒ·á‡¥”¼ò¨zƒÆG?±M·óçewjiŽ“ewµ +±Q£/P™»:-Þm³Þ®’3%C?“Y¾²=ë!e§Peö‡Œ¹jvÛv³o׫´|žF–í 1BT Êì1sý2[néôS5Ó¯lO+ˆ–™;­!Zʬéêk…p;–¢Éyœ5FñPáÜu(zÔ% Ÿ5f´¥t÷^U¡#„Kq•`"ëQGMÉW˜V 5Ieö¸ÆODDQSp§Ó¹Ö¡TïN{aE6%ƒÎAÌ$Ø€Ê ºB†,lJö¬†B 6 2{Ö@А…Mɞ-±/AdîŒ|jº*€šAÜ.é‚FV/Ùdô–TOV»FÒ܄þЬæûooœ¦Ô +ºÐ +R§¤J”‘µ‚4T„9Sò—š³ã ¨Ì`Z^œ)¸S¾†œJœÕ»SÞCNæLÉ`m cg@ekKš2%sNæBUfÎI²”)Ù35DK„ˆÌñ-eÎtu€3ƒB¸KÑ$>N¥ W3 zÒ¨E:#ͤýMx|f + ÂGv¬‘5„RV„YSòX*3(9eҔ¼qœai¸fÇ 6aÒ JcìDP½AéqŒM–5%{ÎæBUf¯ÆÙ5Y֔ìY˜\' €ÈÜY\—YÓÕÖ +áönN’5æ8k¤é&àuåPõ¬‘&'͗ö1»¤Dr +lÚB3(˜„'΀ȚA㠜0gJþ$ŽÂg@e%ŽÂ©’¦äNà;‘TæNàüš0iJ9ÇoÙi8†Ç)6YÒì‰ÚÆBUoOÔ´¯iJæœêo‘ysú­·tu€3ƒB¸]S¾% ¥Þ?Ü Qã ÂÄ/h4ÎI¯n/ÆSvÆ.ïn&l²~Úÿšmv³]Ï·³å²ÙîØÇÙêy¶ˆUτ´ìÌÁ‡å—ŸmÛâ‘ü<ún½šendstream +endobj +2306 0 obj +1024 +endobj +2307 0 obj<>endobj +2308 0 obj<>endobj +2309 0 obj<>endobj +2310 0 obj<>endobj +2311 0 obj<>endobj +2312 0 obj<>endobj +2313 0 obj<>endobj +2314 0 obj<>endobj +2315 0 obj<>endobj +2316 0 obj<>endobj +2317 0 obj<>endobj +2318 0 obj<>endobj +2319 0 obj<>endobj +2320 0 obj<>endobj +2321 0 obj<>endobj +2322 0 obj<>endobj +2323 0 obj<>endobj +2324 0 obj<>endobj +2325 0 obj<>endobj +2326 0 obj<>endobj +2327 0 obj<>endobj +2328 0 obj<>endobj +2329 0 obj<>endobj +2330 0 obj<>endobj +2331 0 obj<>endobj +2332 0 obj<>endobj +2333 0 obj<>endobj +2334 0 obj<>endobj +2335 0 obj<>endobj +2336 0 obj<>endobj +2337 0 obj<>endobj +2338 0 obj<>endobj +2339 0 obj<>endobj +2340 0 obj<>endobj +2341 0 obj<>endobj +2342 0 obj<>endobj +2343 0 obj<>endobj +2344 0 obj<>endobj +2345 0 obj<>endobj +2346 0 obj<>endobj +2347 0 obj<>endobj +2348 0 obj<>endobj +2349 0 obj<>endobj +2350 0 obj<>endobj +2351 0 obj<>endobj +2352 0 obj<>endobj +2353 0 obj<>endobj +2354 0 obj<>endobj +2355 0 obj<>endobj +2356 0 obj<>endobj +2357 0 obj<>endobj +2358 0 obj<>endobj +2359 0 obj<>endobj +2360 0 obj<>endobj +2361 0 obj<>endobj +2362 0 obj<>endobj +2363 0 obj<>endobj +2364 0 obj<>endobj +2365 0 obj<>endobj +2366 0 obj<>endobj +2367 0 obj<>endobj +2368 0 obj<>endobj +2369 0 obj<>endobj +2370 0 obj<>endobj +2371 0 obj<>endobj +2372 0 obj<>endobj +2373 0 obj<>endobj +2374 0 obj<>endobj +2375 0 obj<>endobj +2376 0 obj<>endobj +2377 0 obj<>endobj +2378 0 obj<>endobj +2379 0 obj<>endobj +2380 0 obj<>endobj +2381 0 obj<>endobj +2382 0 obj<>endobj +2383 0 obj<>endobj +2384 0 obj<>endobj +2385 0 obj<>endobj +2386 0 obj<>endobj +2387 0 obj<>endobj +2388 0 obj<>endobj +2389 0 obj<>endobj +2390 0 obj<>endobj +2391 0 obj<>endobj +2392 0 obj<>endobj +2393 0 obj<>endobj +2394 0 obj<>endobj +2395 0 obj<>endobj +2396 0 obj<>endobj +2397 0 obj<>endobj +2398 0 obj<>endobj +2399 0 obj<>endobj +2400 0 obj<>endobj +2401 0 obj<>endobj +2402 0 obj<>endobj +2403 0 obj<>endobj +2404 0 obj<>endobj +2405 0 obj<>endobj +2406 0 obj<>endobj +2407 0 obj<>endobj +2408 0 obj<>endobj +2409 0 obj<>endobj +2410 0 obj<>endobj +2411 0 obj<>endobj +2412 0 obj<>endobj +2413 0 obj<>endobj +2414 0 obj<>endobj +2415 0 obj<>endobj +2416 0 obj<>endobj +2417 0 obj<>endobj +2418 0 obj<>endobj +2419 0 obj<>endobj +2420 0 obj<>endobj +2421 0 obj<>endobj +2422 0 obj<>endobj +2423 0 obj<>endobj +2424 0 obj<>endobj +2425 0 obj<>endobj +2426 0 obj<>endobj +2427 0 obj<>endobj +2428 0 obj<>endobj +2429 0 obj<>endobj +2430 0 obj<>endobj +2431 0 obj<>endobj +2432 0 obj<>endobj +2433 0 obj<>endobj +2434 0 obj<>endobj +2435 0 obj<>endobj +2436 0 obj<>endobj +2437 0 obj<>endobj +2438 0 obj<>endobj +2439 0 obj<>endobj +2440 0 obj<>endobj +2441 0 obj<>endobj +2442 0 obj<>endobj +2443 0 obj<>endobj +2444 0 obj<>endobj +2445 0 obj<>endobj +2446 0 obj<>endobj +2447 0 obj<>endobj +2448 0 obj<>endobj +2449 0 obj<>endobj +2450 0 obj<>endobj +2451 0 obj<>endobj +2452 0 obj<>endobj +2453 0 obj<>endobj +2454 0 obj<>endobj +2455 0 obj<>endobj +2456 0 obj<>endobj +2457 0 obj<>endobj +2458 0 obj<>endobj +2459 0 obj<>endobj +2460 0 obj<>endobj +2461 0 obj<>endobj +2462 0 obj<>endobj +2463 0 obj<>endobj +2464 0 obj<>endobj +2465 0 obj<>endobj +2466 0 obj<>endobj +2467 0 obj<>endobj +2468 0 obj<>endobj +2469 0 obj<>endobj +2470 0 obj<>endobj +2471 0 obj<>endobj +2472 0 obj<>endobj +2473 0 obj<>endobj +2474 0 obj<>endobj +2475 0 obj<>endobj +2476 0 obj<>endobj +2477 0 obj<>endobj +2478 0 obj<>endobj +2479 0 obj<>endobj +2480 0 obj<>endobj +2481 0 obj<>endobj +2482 0 obj<>endobj +2483 0 obj<>endobj +2484 0 obj<>endobj +2485 0 obj<>endobj +2486 0 obj<>endobj +2487 0 obj<>endobj +2488 0 obj<>endobj +2489 0 obj<>endobj +2490 0 obj<>endobj +2491 0 obj<>endobj +2492 0 obj<>endobj +2493 0 obj<>endobj +2494 0 obj<>endobj +2495 0 obj<>endobj +2496 0 obj<>endobj +2497 0 obj<>endobj +2498 0 obj<>endobj +2499 0 obj<>endobj +2500 0 obj<>endobj +2501 0 obj<>endobj +2502 0 obj<>endobj +2503 0 obj<>endobj +2504 0 obj<>endobj +2505 0 obj<>endobj +2506 0 obj<>endobj +2507 0 obj<>endobj +2508 0 obj<>endobj +2509 0 obj<>endobj +2510 0 obj<>endobj +2511 0 obj<>endobj +2512 0 obj<>endobj +2513 0 obj<>endobj +2514 0 obj<>endobj +2515 0 obj<>endobj +2516 0 obj<>endobj +2517 0 obj<>endobj +2518 0 obj<>endobj +2519 0 obj<>endobj +2520 0 obj<>endobj +2521 0 obj<>endobj +2522 0 obj<>endobj +2523 0 obj<>endobj +2524 0 obj<>endobj +2525 0 obj<>endobj +2526 0 obj<>endobj +2527 0 obj<>endobj +2528 0 obj<>endobj +2529 0 obj<>endobj +2530 0 obj<>endobj +2531 0 obj<>endobj +2532 0 obj<>endobj +2533 0 obj<>endobj +2534 0 obj<>endobj +2535 0 obj<>endobj +2536 0 obj<>endobj +2537 0 obj<>endobj +2538 0 obj<>endobj +2539 0 obj<>endobj +2540 0 obj<>endobj +2541 0 obj<>endobj +2542 0 obj<>endobj +2543 0 obj<>endobj +2544 0 obj<>endobj +2545 0 obj<>endobj +2546 0 obj<>endobj +2547 0 obj<>endobj +2548 0 obj<>endobj +2549 0 obj<>endobj +2550 0 obj<>endobj +2551 0 obj<>endobj +2552 0 obj<>endobj +2553 0 obj<>endobj +2554 0 obj<>endobj +2555 0 obj<>endobj +2556 0 obj<>endobj +2557 0 obj<>endobj +2558 0 obj<>endobj +2559 0 obj<>endobj +2560 0 obj<>endobj +2561 0 obj<>endobj +2562 0 obj<>endobj +2563 0 obj<>endobj +2564 0 obj<>endobj +2565 0 obj<>endobj +2566 0 obj<>endobj +2567 0 obj<>endobj +2568 0 obj<>endobj +2569 0 obj<>endobj +2570 0 obj<>endobj +2571 0 obj<>endobj +2572 0 obj<>endobj +2573 0 obj<>endobj +2574 0 obj<>endobj +2575 0 obj<>endobj +2576 0 obj<>endobj +2577 0 obj<>endobj +2578 0 obj<>endobj +2579 0 obj<>endobj +2580 0 obj<>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<>1<>2<>20<>]>>>>endobj +xref +0 3138 +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 +0000003319 00000 n +0000003423 00000 n +0000003461 00000 n +0000003566 00000 n +0000003672 00000 n +0000003778 00000 n +0000003883 00000 n +0000003989 00000 n +0000004095 00000 n +0000004201 00000 n +0000004306 00000 n +0000004412 00000 n +0000004492 00000 n +0000004597 00000 n +0000004703 00000 n +0000004809 00000 n +0000004912 00000 n +0000004957 00000 n +0000005063 00000 n +0000005168 00000 n +0000005274 00000 n +0000005380 00000 n +0000005486 00000 n +0000005591 00000 n +0000005697 00000 n +0000005763 00000 n +0000005868 00000 n +0000005974 00000 n +0000006080 00000 n +0000006186 00000 n +0000006231 00000 n +0000006334 00000 n +0000006438 00000 n +0000006469 00000 n +0000006574 00000 n +0000006680 00000 n +0000006711 00000 n +0000006816 00000 n +0000006922 00000 n +0000007028 00000 n +0000007134 00000 n +0000007179 00000 n +0000007284 00000 n +0000007308 00000 n +0000007411 00000 n +0000007515 00000 n +0000007546 00000 n +0000007651 00000 n +0000007757 00000 n +0000007863 00000 n +0000007969 00000 n +0000008075 00000 n +0000008127 00000 n +0000008232 00000 n +0000008338 00000 n +0000008444 00000 n +0000008550 00000 n +0000008656 00000 n +0000008708 00000 n +0000008813 00000 n +0000008919 00000 n +0000009025 00000 n +0000009131 00000 n +0000009237 00000 n +0000009289 00000 n +0000009394 00000 n +0000009500 00000 n +0000009606 00000 n +0000009712 00000 n +0000009818 00000 n +0000009870 00000 n +0000009975 00000 n +0000010081 00000 n +0000010187 00000 n +0000010293 00000 n +0000010399 00000 n +0000010451 00000 n +0000010556 00000 n +0000010662 00000 n +0000010768 00000 n +0000010875 00000 n +0000010982 00000 n +0000011037 00000 n +0000011143 00000 n +0000011250 00000 n +0000011284 00000 n +0000011390 00000 n +0000011497 00000 n +0000011604 00000 n +0000011711 00000 n +0000011761 00000 n +0000011867 00000 n +0000011974 00000 n +0000012081 00000 n +0000012188 00000 n +0000012238 00000 n +0000012344 00000 n +0000012451 00000 n +0000012485 00000 n +0000012591 00000 n +0000012698 00000 n +0000012805 00000 n +0000012912 00000 n +0000013018 00000 n +0000013076 00000 n +0000013182 00000 n +0000013289 00000 n +0000013396 00000 n +0000013503 00000 n +0000013609 00000 n +0000013667 00000 n +0000013773 00000 n +0000013880 00000 n +0000013987 00000 n +0000014094 00000 n +0000014200 00000 n +0000014258 00000 n +0000014364 00000 n +0000014471 00000 n +0000014578 00000 n +0000014685 00000 n +0000014791 00000 n +0000014849 00000 n +0000014955 00000 n +0000015062 00000 n +0000015169 00000 n +0000015276 00000 n +0000015381 00000 n +0000015439 00000 n +0000015545 00000 n +0000015652 00000 n +0000015759 00000 n +0000015866 00000 n +0000015972 00000 n +0000016030 00000 n +0000016136 00000 n +0000016243 00000 n +0000016277 00000 n +0000016383 00000 n +0000016490 00000 n +0000016524 00000 n +0000016630 00000 n +0000016737 00000 n +0000016844 00000 n +0000016950 00000 n +0000017057 00000 n +0000017164 00000 n +0000017271 00000 n +0000017378 00000 n +0000017485 00000 n +0000017592 00000 n +0000017699 00000 n +0000017805 00000 n +0000017912 00000 n +0000018019 00000 n +0000018126 00000 n +0000018233 00000 n +0000018340 00000 n +0000018447 00000 n +0000018554 00000 n +0000018661 00000 n +0000018768 00000 n +0000018875 00000 n +0000018982 00000 n +0000019089 00000 n +0000019196 00000 n +0000019303 00000 n +0000019410 00000 n +0000019517 00000 n +0000019624 00000 n +0000019731 00000 n +0000019838 00000 n +0000019945 00000 n +0000020052 00000 n +0000020159 00000 n +0000020266 00000 n +0000020373 00000 n +0000020480 00000 n +0000020587 00000 n +0000020694 00000 n +0000020801 00000 n +0000020908 00000 n +0000021015 00000 n +0000021121 00000 n +0000021226 00000 n +0000021331 00000 n +0000021709 00000 n +0000021816 00000 n +0000021923 00000 n +0000022030 00000 n +0000022137 00000 n +0000022244 00000 n +0000022350 00000 n +0000022457 00000 n +0000022564 00000 n +0000022671 00000 n +0000022778 00000 n +0000022885 00000 n +0000022992 00000 n +0000023099 00000 n +0000023206 00000 n +0000023312 00000 n +0000023418 00000 n +0000023525 00000 n +0000023632 00000 n +0000023739 00000 n +0000023845 00000 n +0000023952 00000 n +0000024058 00000 n +0000024164 00000 n +0000024270 00000 n +0000024376 00000 n +0000024483 00000 n +0000024590 00000 n +0000024696 00000 n +0000024803 00000 n +0000024910 00000 n +0000025017 00000 n +0000025124 00000 n +0000025230 00000 n +0000025336 00000 n +0000025442 00000 n +0000025549 00000 n +0000025656 00000 n +0000025763 00000 n +0000025870 00000 n +0000025976 00000 n +0000026083 00000 n +0000026188 00000 n +0000026292 00000 n +0000026654 00000 n +0000026760 00000 n +0000026867 00000 n +0000026974 00000 n +0000027081 00000 n +0000027188 00000 n +0000027295 00000 n +0000027402 00000 n +0000027509 00000 n +0000027615 00000 n +0000027721 00000 n +0000027828 00000 n +0000027935 00000 n +0000028042 00000 n +0000028149 00000 n +0000028256 00000 n +0000028363 00000 n +0000028470 00000 n +0000028577 00000 n +0000028684 00000 n +0000028791 00000 n +0000028898 00000 n +0000029005 00000 n +0000029112 00000 n +0000029219 00000 n +0000029326 00000 n +0000029433 00000 n +0000029540 00000 n +0000029647 00000 n +0000029754 00000 n +0000029861 00000 n +0000029968 00000 n +0000030075 00000 n +0000030182 00000 n +0000030289 00000 n +0000030396 00000 n +0000030503 00000 n +0000030610 00000 n +0000030717 00000 n +0000030824 00000 n +0000030931 00000 n +0000031038 00000 n +0000031145 00000 n +0000031251 00000 n +0000031356 00000 n +0000031461 00000 n +0000031839 00000 n +0000031946 00000 n +0000032053 00000 n +0000032160 00000 n +0000032267 00000 n +0000032374 00000 n +0000032481 00000 n +0000032587 00000 n +0000032694 00000 n +0000032801 00000 n +0000032908 00000 n +0000033015 00000 n +0000033122 00000 n +0000033228 00000 n +0000033335 00000 n +0000033442 00000 n +0000033549 00000 n +0000033656 00000 n +0000033763 00000 n +0000033869 00000 n +0000033976 00000 n +0000034083 00000 n +0000034190 00000 n +0000034297 00000 n +0000034404 00000 n +0000034511 00000 n +0000034617 00000 n +0000034724 00000 n +0000034831 00000 n +0000034938 00000 n +0000035045 00000 n +0000035152 00000 n +0000035258 00000 n +0000035365 00000 n +0000035472 00000 n +0000035579 00000 n +0000035686 00000 n +0000035793 00000 n +0000035900 00000 n +0000036006 00000 n +0000036113 00000 n +0000036220 00000 n +0000036327 00000 n +0000036434 00000 n +0000036541 00000 n +0000036646 00000 n +0000036751 00000 n +0000036856 00000 n +0000037250 00000 n +0000037357 00000 n +0000037464 00000 n +0000037571 00000 n +0000037678 00000 n +0000037785 00000 n +0000037892 00000 n +0000037999 00000 n +0000038106 00000 n +0000038213 00000 n +0000038320 00000 n +0000038427 00000 n +0000038534 00000 n +0000038641 00000 n +0000038748 00000 n +0000038855 00000 n +0000038962 00000 n +0000039069 00000 n +0000039176 00000 n +0000039283 00000 n +0000039390 00000 n +0000039497 00000 n +0000039604 00000 n +0000039711 00000 n +0000039818 00000 n +0000039925 00000 n +0000040032 00000 n +0000040139 00000 n +0000040246 00000 n +0000040353 00000 n +0000040460 00000 n +0000040567 00000 n +0000040674 00000 n +0000040781 00000 n +0000040888 00000 n +0000040995 00000 n +0000041102 00000 n +0000041209 00000 n +0000041316 00000 n +0000041423 00000 n +0000041530 00000 n +0000041637 00000 n +0000041744 00000 n +0000041851 00000 n +0000041958 00000 n +0000042064 00000 n +0000042169 00000 n +0000042274 00000 n +0000042668 00000 n +0000042775 00000 n +0000042882 00000 n +0000042988 00000 n +0000043095 00000 n +0000043202 00000 n +0000043309 00000 n +0000043416 00000 n +0000043523 00000 n +0000043630 00000 n +0000043736 00000 n +0000043843 00000 n +0000043950 00000 n +0000044057 00000 n +0000044164 00000 n +0000044271 00000 n +0000044377 00000 n +0000044484 00000 n +0000044591 00000 n +0000044698 00000 n +0000044805 00000 n +0000044912 00000 n +0000045019 00000 n +0000045125 00000 n +0000045232 00000 n +0000045339 00000 n +0000045446 00000 n +0000045553 00000 n +0000045660 00000 n +0000045767 00000 n +0000045873 00000 n +0000045980 00000 n +0000046087 00000 n +0000046194 00000 n +0000046301 00000 n +0000046408 00000 n +0000046515 00000 n +0000046621 00000 n +0000046728 00000 n +0000046835 00000 n +0000046942 00000 n +0000047049 00000 n +0000047156 00000 n +0000047263 00000 n +0000047369 00000 n +0000047475 00000 n +0000047580 00000 n +0000047685 00000 n +0000048079 00000 n +0000048186 00000 n +0000048293 00000 n +0000048400 00000 n +0000048507 00000 n +0000048614 00000 n +0000048721 00000 n +0000048828 00000 n +0000048935 00000 n +0000049042 00000 n +0000049149 00000 n +0000049256 00000 n +0000049363 00000 n +0000049470 00000 n +0000049577 00000 n +0000049684 00000 n +0000049791 00000 n +0000049898 00000 n +0000050005 00000 n +0000050112 00000 n +0000050219 00000 n +0000050326 00000 n +0000050433 00000 n +0000050540 00000 n +0000050647 00000 n +0000050754 00000 n +0000050861 00000 n +0000050968 00000 n +0000051075 00000 n +0000051182 00000 n +0000051289 00000 n +0000051396 00000 n +0000051503 00000 n +0000051610 00000 n +0000051717 00000 n +0000051824 00000 n +0000051931 00000 n +0000052038 00000 n +0000052145 00000 n +0000052252 00000 n +0000052359 00000 n +0000052466 00000 n +0000052573 00000 n +0000052680 00000 n +0000052787 00000 n +0000052893 00000 n +0000052998 00000 n +0000053103 00000 n +0000053497 00000 n +0000053604 00000 n +0000053711 00000 n +0000053817 00000 n +0000053924 00000 n +0000054031 00000 n +0000054138 00000 n +0000054245 00000 n +0000054352 00000 n +0000054459 00000 n +0000054565 00000 n +0000054672 00000 n +0000054779 00000 n +0000054886 00000 n +0000054993 00000 n +0000055100 00000 n +0000055207 00000 n +0000055313 00000 n +0000055420 00000 n +0000055527 00000 n +0000055634 00000 n +0000055741 00000 n +0000055848 00000 n +0000055955 00000 n +0000056061 00000 n +0000056168 00000 n +0000056275 00000 n +0000056382 00000 n +0000056489 00000 n +0000056596 00000 n +0000056703 00000 n +0000056809 00000 n +0000056916 00000 n +0000057023 00000 n +0000057130 00000 n +0000057237 00000 n +0000057344 00000 n +0000057451 00000 n +0000057557 00000 n +0000057664 00000 n +0000057771 00000 n +0000057878 00000 n +0000057985 00000 n +0000058092 00000 n +0000058199 00000 n +0000058304 00000 n +0000058409 00000 n +0000058514 00000 n +0000058908 00000 n +0000059015 00000 n +0000059122 00000 n +0000059229 00000 n +0000059336 00000 n +0000059443 00000 n +0000059550 00000 n +0000059657 00000 n +0000059764 00000 n +0000059871 00000 n +0000059978 00000 n +0000060085 00000 n +0000060192 00000 n +0000060299 00000 n +0000060406 00000 n +0000060513 00000 n +0000060620 00000 n +0000060727 00000 n +0000060834 00000 n +0000060941 00000 n +0000061048 00000 n +0000061155 00000 n +0000061262 00000 n +0000061369 00000 n +0000061476 00000 n +0000061583 00000 n +0000061690 00000 n +0000061797 00000 n +0000061904 00000 n +0000062011 00000 n +0000062118 00000 n +0000062225 00000 n +0000062332 00000 n +0000062439 00000 n +0000062546 00000 n +0000062653 00000 n +0000062760 00000 n +0000062867 00000 n +0000062974 00000 n +0000063081 00000 n +0000063188 00000 n +0000063295 00000 n +0000063402 00000 n +0000063509 00000 n +0000063616 00000 n +0000063722 00000 n +0000063827 00000 n +0000063932 00000 n +0000064326 00000 n +0000064433 00000 n +0000064540 00000 n +0000064647 00000 n +0000064754 00000 n +0000064861 00000 n +0000064968 00000 n +0000065074 00000 n +0000065181 00000 n +0000065288 00000 n +0000065395 00000 n +0000065502 00000 n +0000065609 00000 n +0000065716 00000 n +0000065822 00000 n +0000065929 00000 n +0000066036 00000 n +0000066143 00000 n +0000066250 00000 n +0000066357 00000 n +0000066464 00000 n +0000066570 00000 n +0000066677 00000 n +0000066784 00000 n +0000066891 00000 n +0000066998 00000 n +0000067105 00000 n +0000067212 00000 n +0000067318 00000 n +0000067425 00000 n +0000067532 00000 n +0000067639 00000 n +0000067746 00000 n +0000067853 00000 n +0000067960 00000 n +0000068066 00000 n +0000068173 00000 n +0000068280 00000 n +0000068387 00000 n +0000068494 00000 n +0000068601 00000 n +0000068708 00000 n +0000068814 00000 n +0000068921 00000 n +0000069028 00000 n +0000069134 00000 n +0000069239 00000 n +0000069344 00000 n +0000069738 00000 n +0000069845 00000 n +0000069952 00000 n +0000070059 00000 n +0000070166 00000 n +0000070273 00000 n +0000070380 00000 n +0000070487 00000 n +0000070594 00000 n +0000070701 00000 n +0000070808 00000 n +0000070915 00000 n +0000071022 00000 n +0000071129 00000 n +0000071236 00000 n +0000071343 00000 n +0000071450 00000 n +0000071557 00000 n +0000071664 00000 n +0000071771 00000 n +0000071878 00000 n +0000071985 00000 n +0000072092 00000 n +0000072199 00000 n +0000072306 00000 n +0000072413 00000 n +0000072520 00000 n +0000072627 00000 n +0000072734 00000 n +0000072841 00000 n +0000072948 00000 n +0000073055 00000 n +0000073162 00000 n +0000073269 00000 n +0000073376 00000 n +0000073483 00000 n +0000073590 00000 n +0000073697 00000 n +0000073804 00000 n +0000073911 00000 n +0000074018 00000 n +0000074125 00000 n +0000074232 00000 n +0000074339 00000 n +0000074446 00000 n +0000074552 00000 n +0000074657 00000 n +0000074762 00000 n +0000075156 00000 n +0000075263 00000 n +0000075370 00000 n +0000075477 00000 n +0000075583 00000 n +0000075690 00000 n +0000075797 00000 n +0000075904 00000 n +0000076011 00000 n +0000076118 00000 n +0000076225 00000 n +0000076331 00000 n +0000076438 00000 n +0000076545 00000 n +0000076652 00000 n +0000076759 00000 n +0000076866 00000 n +0000076973 00000 n +0000077079 00000 n +0000077186 00000 n +0000077293 00000 n +0000077400 00000 n +0000077507 00000 n +0000077614 00000 n +0000077721 00000 n +0000077827 00000 n +0000077934 00000 n +0000078041 00000 n +0000078148 00000 n +0000078255 00000 n +0000078362 00000 n +0000078469 00000 n +0000078575 00000 n +0000078682 00000 n +0000078789 00000 n +0000078896 00000 n +0000079003 00000 n +0000079110 00000 n +0000079217 00000 n +0000079323 00000 n +0000079430 00000 n +0000079537 00000 n +0000079644 00000 n +0000079751 00000 n +0000079858 00000 n +0000079964 00000 n +0000080068 00000 n +0000080173 00000 n +0000080567 00000 n +0000080674 00000 n +0000080781 00000 n +0000080888 00000 n +0000080995 00000 n +0000081102 00000 n +0000081209 00000 n +0000081316 00000 n +0000081423 00000 n +0000081530 00000 n +0000081637 00000 n +0000081744 00000 n +0000081851 00000 n +0000081958 00000 n +0000082065 00000 n +0000082172 00000 n +0000082279 00000 n +0000082386 00000 n +0000082493 00000 n +0000082600 00000 n +0000082707 00000 n +0000082814 00000 n +0000082921 00000 n +0000083028 00000 n +0000083135 00000 n +0000083242 00000 n +0000083349 00000 n +0000083456 00000 n +0000083563 00000 n +0000083670 00000 n +0000083777 00000 n +0000083884 00000 n +0000083991 00000 n +0000084098 00000 n +0000084205 00000 n +0000084312 00000 n +0000084419 00000 n +0000084526 00000 n +0000084633 00000 n +0000084740 00000 n +0000084847 00000 n +0000084954 00000 n +0000085061 00000 n +0000085168 00000 n +0000085275 00000 n +0000085381 00000 n +0000085486 00000 n +0000085591 00000 n +0000085985 00000 n +0000086091 00000 n +0000086198 00000 n +0000086305 00000 n +0000086412 00000 n +0000086519 00000 n +0000086626 00000 n +0000086733 00000 n +0000086839 00000 n +0000086946 00000 n +0000087053 00000 n +0000087160 00000 n +0000087267 00000 n +0000087374 00000 n +0000087481 00000 n +0000087587 00000 n +0000087694 00000 n +0000087801 00000 n +0000087908 00000 n +0000088015 00000 n +0000088122 00000 n +0000088229 00000 n +0000088335 00000 n +0000088442 00000 n +0000088549 00000 n +0000088656 00000 n +0000088763 00000 n +0000088870 00000 n +0000088977 00000 n +0000089083 00000 n +0000089190 00000 n +0000089297 00000 n +0000089404 00000 n +0000089511 00000 n +0000089618 00000 n +0000089725 00000 n +0000089831 00000 n +0000089938 00000 n +0000090045 00000 n +0000090152 00000 n +0000090259 00000 n +0000090366 00000 n +0000090473 00000 n +0000090579 00000 n +0000090686 00000 n +0000090792 00000 n +0000090897 00000 n +0000091002 00000 n +0000091396 00000 n +0000091503 00000 n +0000091610 00000 n +0000091717 00000 n +0000091824 00000 n +0000091931 00000 n +0000092038 00000 n +0000092145 00000 n +0000092252 00000 n +0000092359 00000 n +0000092466 00000 n +0000092573 00000 n +0000092680 00000 n +0000092787 00000 n +0000092894 00000 n +0000093001 00000 n +0000093108 00000 n +0000093215 00000 n +0000093322 00000 n +0000093429 00000 n +0000093536 00000 n +0000093643 00000 n +0000093750 00000 n +0000093857 00000 n +0000093964 00000 n +0000094071 00000 n +0000094178 00000 n +0000094285 00000 n +0000094392 00000 n +0000094499 00000 n +0000094606 00000 n +0000094713 00000 n +0000094820 00000 n +0000094927 00000 n +0000095034 00000 n +0000095141 00000 n +0000095248 00000 n +0000095355 00000 n +0000095462 00000 n +0000095569 00000 n +0000095676 00000 n +0000095783 00000 n +0000095890 00000 n +0000095997 00000 n +0000096104 00000 n +0000096210 00000 n +0000096315 00000 n +0000096420 00000 n +0000096814 00000 n +0000096921 00000 n +0000097028 00000 n +0000097135 00000 n +0000097242 00000 n +0000097348 00000 n +0000097455 00000 n +0000097562 00000 n +0000097669 00000 n +0000097776 00000 n +0000097883 00000 n +0000097990 00000 n +0000098096 00000 n +0000098203 00000 n +0000098310 00000 n +0000098417 00000 n +0000098524 00000 n +0000098631 00000 n +0000098738 00000 n +0000098844 00000 n +0000098951 00000 n +0000099058 00000 n +0000099165 00000 n +0000099272 00000 n +0000099379 00000 n +0000099486 00000 n +0000099592 00000 n +0000099699 00000 n +0000099806 00000 n +0000099913 00000 n +0000100020 00000 n +0000100127 00000 n +0000100234 00000 n +0000100340 00000 n +0000100447 00000 n +0000100554 00000 n +0000100661 00000 n +0000100768 00000 n +0000100875 00000 n +0000100982 00000 n +0000101088 00000 n +0000101195 00000 n +0000101302 00000 n +0000101409 00000 n +0000101516 00000 n +0000101622 00000 n +0000101727 00000 n +0000101831 00000 n +0000102225 00000 n +0000102332 00000 n +0000102439 00000 n +0000102546 00000 n +0000102653 00000 n +0000102760 00000 n +0000102867 00000 n +0000102974 00000 n +0000103081 00000 n +0000103188 00000 n +0000103295 00000 n +0000103402 00000 n +0000103509 00000 n +0000103616 00000 n +0000103723 00000 n +0000103830 00000 n +0000103937 00000 n +0000104044 00000 n +0000104151 00000 n +0000104258 00000 n +0000104365 00000 n +0000104472 00000 n +0000104579 00000 n +0000104686 00000 n +0000104793 00000 n +0000104900 00000 n +0000105007 00000 n +0000105114 00000 n +0000105221 00000 n +0000105328 00000 n +0000105435 00000 n +0000105542 00000 n +0000105649 00000 n +0000105756 00000 n +0000105863 00000 n +0000105970 00000 n +0000106077 00000 n +0000106184 00000 n +0000106291 00000 n +0000106398 00000 n +0000106505 00000 n +0000106612 00000 n +0000106719 00000 n +0000106826 00000 n +0000106933 00000 n +0000107039 00000 n +0000107144 00000 n +0000107249 00000 n +0000107643 00000 n +0000107750 00000 n +0000107856 00000 n +0000107963 00000 n +0000108070 00000 n +0000108177 00000 n +0000108284 00000 n +0000108391 00000 n +0000108498 00000 n +0000108604 00000 n +0000108711 00000 n +0000108818 00000 n +0000108925 00000 n +0000109032 00000 n +0000109139 00000 n +0000109246 00000 n +0000109352 00000 n +0000109459 00000 n +0000109566 00000 n +0000109673 00000 n +0000109780 00000 n +0000109887 00000 n +0000109994 00000 n +0000110100 00000 n +0000110207 00000 n +0000110314 00000 n +0000110421 00000 n +0000110528 00000 n +0000110635 00000 n +0000110742 00000 n +0000110848 00000 n +0000110955 00000 n +0000111063 00000 n +0000111171 00000 n +0000111279 00000 n +0000111387 00000 n +0000111495 00000 n +0000111807 00000 n +0000111843 00000 n +0000111879 00000 n +0000125625 00000 n +0000125676 00000 n +0000125727 00000 n +0000125778 00000 n +0000125829 00000 n +0000125880 00000 n +0000125931 00000 n +0000125982 00000 n +0000126033 00000 n +0000126084 00000 n +0000126135 00000 n +0000126186 00000 n +0000126237 00000 n +0000126288 00000 n +0000126339 00000 n +0000126390 00000 n +0000126441 00000 n +0000126492 00000 n +0000126543 00000 n +0000126594 00000 n +0000126645 00000 n +0000126696 00000 n +0000126747 00000 n +0000126798 00000 n +0000126849 00000 n +0000126900 00000 n +0000126951 00000 n +0000127002 00000 n +0000127053 00000 n +0000127104 00000 n +0000127155 00000 n +0000127206 00000 n +0000127257 00000 n +0000127308 00000 n +0000127359 00000 n +0000127410 00000 n +0000127461 00000 n +0000127512 00000 n +0000127563 00000 n +0000127614 00000 n +0000127665 00000 n +0000127716 00000 n +0000127767 00000 n +0000127818 00000 n +0000127869 00000 n +0000127920 00000 n +0000127971 00000 n +0000128022 00000 n +0000128073 00000 n +0000128124 00000 n +0000128175 00000 n +0000128226 00000 n +0000128277 00000 n +0000128328 00000 n +0000128379 00000 n +0000128430 00000 n +0000128481 00000 n +0000128532 00000 n +0000128583 00000 n +0000128634 00000 n +0000128685 00000 n +0000128736 00000 n +0000128787 00000 n +0000128838 00000 n +0000128889 00000 n +0000128940 00000 n +0000128991 00000 n +0000129042 00000 n +0000129093 00000 n +0000129144 00000 n +0000129195 00000 n +0000129246 00000 n +0000129297 00000 n +0000129348 00000 n +0000129399 00000 n +0000129450 00000 n +0000129501 00000 n +0000129552 00000 n +0000129603 00000 n +0000129654 00000 n +0000129705 00000 n +0000129756 00000 n +0000129807 00000 n +0000129858 00000 n +0000129909 00000 n +0000129960 00000 n +0000130011 00000 n +0000130062 00000 n +0000130113 00000 n +0000130164 00000 n +0000130215 00000 n +0000130266 00000 n +0000130317 00000 n +0000130368 00000 n +0000130419 00000 n +0000130470 00000 n +0000130521 00000 n +0000130572 00000 n +0000130623 00000 n +0000130674 00000 n +0000130725 00000 n +0000130776 00000 n +0000130827 00000 n +0000130878 00000 n +0000130929 00000 n +0000130980 00000 n +0000131031 00000 n +0000131082 00000 n +0000131133 00000 n +0000131184 00000 n +0000131235 00000 n +0000131286 00000 n +0000131337 00000 n +0000131388 00000 n +0000131439 00000 n +0000131490 00000 n +0000131541 00000 n +0000131592 00000 n +0000131643 00000 n +0000131694 00000 n +0000131745 00000 n +0000131796 00000 n +0000131847 00000 n +0000131898 00000 n +0000131949 00000 n +0000132000 00000 n +0000132051 00000 n +0000132102 00000 n +0000132153 00000 n +0000132204 00000 n +0000132255 00000 n +0000132306 00000 n +0000132357 00000 n +0000132408 00000 n +0000132459 00000 n +0000132510 00000 n +0000132561 00000 n +0000132612 00000 n +0000132663 00000 n +0000132714 00000 n +0000132765 00000 n +0000132816 00000 n +0000132867 00000 n +0000132918 00000 n +0000132969 00000 n +0000133020 00000 n +0000133071 00000 n +0000133122 00000 n +0000133173 00000 n +0000133224 00000 n +0000133275 00000 n +0000133326 00000 n +0000133377 00000 n +0000133428 00000 n +0000133479 00000 n +0000133530 00000 n +0000133581 00000 n +0000133632 00000 n +0000133683 00000 n +0000133734 00000 n +0000133785 00000 n +0000133836 00000 n +0000133887 00000 n +0000133938 00000 n +0000133989 00000 n +0000134040 00000 n +0000134091 00000 n +0000134142 00000 n +0000134193 00000 n +0000134244 00000 n +0000134295 00000 n +0000134346 00000 n +0000134397 00000 n +0000134448 00000 n +0000134499 00000 n +0000134550 00000 n +0000134601 00000 n +0000134652 00000 n +0000134703 00000 n +0000134754 00000 n +0000134805 00000 n +0000134856 00000 n +0000134907 00000 n +0000134958 00000 n +0000135009 00000 n +0000135060 00000 n +0000135111 00000 n +0000135162 00000 n +0000135213 00000 n +0000135264 00000 n +0000135315 00000 n +0000135366 00000 n +0000135417 00000 n +0000135468 00000 n +0000135519 00000 n +0000135570 00000 n +0000135621 00000 n +0000135672 00000 n +0000135723 00000 n +0000135774 00000 n +0000135825 00000 n +0000135876 00000 n +0000135927 00000 n +0000135978 00000 n +0000136029 00000 n +0000136080 00000 n +0000136131 00000 n +0000136182 00000 n +0000136233 00000 n +0000136284 00000 n +0000136335 00000 n +0000136386 00000 n +0000136437 00000 n +0000136488 00000 n +0000136539 00000 n +0000136590 00000 n +0000136641 00000 n +0000136692 00000 n +0000136743 00000 n +0000136794 00000 n +0000136845 00000 n +0000136896 00000 n +0000136947 00000 n +0000136998 00000 n +0000137049 00000 n +0000137100 00000 n +0000137151 00000 n +0000137202 00000 n +0000137253 00000 n +0000137304 00000 n +0000137355 00000 n +0000137406 00000 n +0000137457 00000 n +0000137508 00000 n +0000137559 00000 n +0000137610 00000 n +0000137661 00000 n +0000137712 00000 n +0000137763 00000 n +0000137814 00000 n +0000137865 00000 n +0000137916 00000 n +0000137967 00000 n +0000138018 00000 n +0000138069 00000 n +0000138120 00000 n +0000138171 00000 n +0000138222 00000 n +0000138273 00000 n +0000138324 00000 n +0000138375 00000 n +0000138426 00000 n +0000138477 00000 n +0000138528 00000 n +0000138579 00000 n +0000138630 00000 n +0000138681 00000 n +0000138732 00000 n +0000138783 00000 n +0000138834 00000 n +0000138885 00000 n +0000138936 00000 n +0000138987 00000 n +0000139038 00000 n +0000139089 00000 n +0000139140 00000 n +0000139191 00000 n +0000139242 00000 n +0000139293 00000 n +0000139344 00000 n +0000139395 00000 n +0000139446 00000 n +0000139497 00000 n +0000139548 00000 n +0000139599 00000 n +0000139650 00000 n +0000139701 00000 n +0000139752 00000 n +0000139803 00000 n +0000139854 00000 n +0000139905 00000 n +0000139956 00000 n +0000140007 00000 n +0000140058 00000 n +0000140109 00000 n +0000140160 00000 n +0000140211 00000 n +0000140262 00000 n +0000140313 00000 n +0000140364 00000 n +0000140415 00000 n +0000140466 00000 n +0000140517 00000 n +0000140568 00000 n +0000140619 00000 n +0000140670 00000 n +0000140721 00000 n +0000140772 00000 n +0000140823 00000 n +0000140874 00000 n +0000140925 00000 n +0000140976 00000 n +0000141027 00000 n +0000141078 00000 n +0000141129 00000 n +0000141180 00000 n +0000141231 00000 n +0000141282 00000 n +0000141333 00000 n +0000141384 00000 n +0000141435 00000 n +0000141486 00000 n +0000141537 00000 n +0000141588 00000 n +0000141639 00000 n +0000141690 00000 n +0000141741 00000 n +0000141792 00000 n +0000141843 00000 n +0000141894 00000 n +0000141945 00000 n +0000141996 00000 n +0000142047 00000 n +0000142098 00000 n +0000142149 00000 n +0000142200 00000 n +0000142251 00000 n +0000142302 00000 n +0000142353 00000 n +0000142404 00000 n +0000142455 00000 n +0000142506 00000 n +0000142557 00000 n +0000142608 00000 n +0000142659 00000 n +0000142710 00000 n +0000142761 00000 n +0000142812 00000 n +0000142863 00000 n +0000142914 00000 n +0000142965 00000 n +0000143016 00000 n +0000143067 00000 n +0000143118 00000 n +0000143169 00000 n +0000143220 00000 n +0000143271 00000 n +0000143322 00000 n +0000143373 00000 n +0000143424 00000 n +0000143475 00000 n +0000143526 00000 n +0000143577 00000 n +0000143628 00000 n +0000143679 00000 n +0000143730 00000 n +0000143781 00000 n +0000143832 00000 n +0000143883 00000 n +0000143934 00000 n +0000143985 00000 n +0000144036 00000 n +0000144087 00000 n +0000144138 00000 n +0000144189 00000 n +0000144240 00000 n +0000144291 00000 n +0000144342 00000 n +0000144393 00000 n +0000144444 00000 n +0000144495 00000 n +0000144546 00000 n +0000144597 00000 n +0000144648 00000 n +0000144699 00000 n +0000144750 00000 n +0000144801 00000 n +0000144852 00000 n +0000144903 00000 n +0000144954 00000 n +0000145005 00000 n +0000145056 00000 n +0000145107 00000 n +0000145158 00000 n +0000145209 00000 n +0000145260 00000 n +0000145311 00000 n +0000145362 00000 n +0000145413 00000 n +0000145464 00000 n +0000145515 00000 n +0000145566 00000 n +0000145617 00000 n +0000145668 00000 n +0000145719 00000 n +0000145770 00000 n +0000145821 00000 n +0000145872 00000 n +0000145923 00000 n +0000145974 00000 n +0000146025 00000 n +0000146076 00000 n +0000146127 00000 n +0000146178 00000 n +0000146229 00000 n +0000146280 00000 n +0000146331 00000 n +0000146382 00000 n +0000146433 00000 n +0000146484 00000 n +0000146535 00000 n +0000146586 00000 n +0000146637 00000 n +0000146688 00000 n +0000146739 00000 n +0000146790 00000 n +0000146841 00000 n +0000146892 00000 n +0000146943 00000 n +0000146994 00000 n +0000147045 00000 n +0000147096 00000 n +0000147147 00000 n +0000147198 00000 n +0000147249 00000 n +0000147300 00000 n +0000147351 00000 n +0000147402 00000 n +0000147453 00000 n +0000147504 00000 n +0000147555 00000 n +0000147606 00000 n +0000147657 00000 n +0000147708 00000 n +0000147759 00000 n +0000147810 00000 n +0000147861 00000 n +0000147912 00000 n +0000147963 00000 n +0000148014 00000 n +0000148065 00000 n +0000148116 00000 n +0000148167 00000 n +0000148218 00000 n +0000148269 00000 n +0000148320 00000 n +0000148371 00000 n +0000148422 00000 n +0000148473 00000 n +0000148524 00000 n +0000148575 00000 n +0000148626 00000 n +0000148677 00000 n +0000148728 00000 n +0000148779 00000 n +0000148830 00000 n +0000148881 00000 n +0000148932 00000 n +0000148983 00000 n +0000149034 00000 n +0000149085 00000 n +0000149136 00000 n +0000149187 00000 n +0000149238 00000 n +0000149289 00000 n +0000149340 00000 n +0000149391 00000 n +0000149442 00000 n +0000149493 00000 n +0000149544 00000 n +0000149595 00000 n +0000149646 00000 n +0000149697 00000 n +0000149748 00000 n +0000149799 00000 n +0000149850 00000 n +0000149901 00000 n +0000149952 00000 n +0000150003 00000 n +0000150054 00000 n +0000150105 00000 n +0000150156 00000 n +0000150207 00000 n +0000150258 00000 n +0000150309 00000 n +0000150360 00000 n +0000150411 00000 n +0000150462 00000 n +0000150513 00000 n +0000150564 00000 n +0000150615 00000 n +0000150666 00000 n +0000150717 00000 n +0000150768 00000 n +0000150819 00000 n +0000150870 00000 n +0000150921 00000 n +0000150972 00000 n +0000151023 00000 n +0000151074 00000 n +0000151125 00000 n +0000151176 00000 n +0000151227 00000 n +0000151278 00000 n +0000151329 00000 n +0000151380 00000 n +0000151431 00000 n +0000151482 00000 n +0000151533 00000 n +0000151584 00000 n +0000151635 00000 n +0000151686 00000 n +0000151737 00000 n +0000151788 00000 n +0000151839 00000 n +0000151890 00000 n +0000151941 00000 n +0000151992 00000 n +0000152043 00000 n +0000152094 00000 n +0000152145 00000 n +0000152196 00000 n +0000152247 00000 n +0000152298 00000 n +0000152349 00000 n +0000152400 00000 n +0000152451 00000 n +0000152502 00000 n +0000152553 00000 n +0000152604 00000 n +0000152655 00000 n +0000152706 00000 n +0000152757 00000 n +0000152808 00000 n +0000152859 00000 n +0000152910 00000 n +0000152961 00000 n +0000153012 00000 n +0000153063 00000 n +0000153114 00000 n +0000153165 00000 n +0000153216 00000 n +0000153267 00000 n +0000153318 00000 n +0000153369 00000 n +0000153420 00000 n +0000153471 00000 n +0000153522 00000 n +0000153573 00000 n +0000153624 00000 n +0000153675 00000 n +0000153726 00000 n +0000153777 00000 n +0000153828 00000 n +0000153879 00000 n +0000153930 00000 n +0000153981 00000 n +0000154032 00000 n +0000154083 00000 n +0000154134 00000 n +0000154185 00000 n +0000154236 00000 n +0000154287 00000 n +0000154338 00000 n +0000154389 00000 n +0000154440 00000 n +0000154491 00000 n +0000154542 00000 n +0000154593 00000 n +0000154644 00000 n +0000154695 00000 n +0000154746 00000 n +0000154797 00000 n +0000154848 00000 n +0000154899 00000 n +0000154950 00000 n +0000155001 00000 n +0000155052 00000 n +0000155103 00000 n +0000155154 00000 n +0000155205 00000 n +0000155256 00000 n +0000155307 00000 n +0000155358 00000 n +0000155409 00000 n +0000155460 00000 n +0000155511 00000 n +0000155562 00000 n +0000155613 00000 n +0000155664 00000 n +0000155715 00000 n +0000155766 00000 n +0000155817 00000 n +0000155868 00000 n +0000155919 00000 n +0000155970 00000 n +0000156021 00000 n +0000156072 00000 n +0000156123 00000 n +0000156174 00000 n +0000156225 00000 n +0000156276 00000 n +0000156327 00000 n +0000156378 00000 n +0000156429 00000 n +0000156480 00000 n +0000156531 00000 n +0000156582 00000 n +0000156633 00000 n +0000156684 00000 n +0000156735 00000 n +0000156786 00000 n +0000156837 00000 n +0000156888 00000 n +0000156939 00000 n +0000156990 00000 n +0000157041 00000 n +0000157092 00000 n +0000157143 00000 n +0000157194 00000 n +0000157245 00000 n +0000157296 00000 n +0000157347 00000 n +0000157398 00000 n +0000157449 00000 n +0000157500 00000 n +0000157551 00000 n +0000157602 00000 n +0000157653 00000 n +0000157704 00000 n +0000157755 00000 n +0000157806 00000 n +0000157857 00000 n +0000157908 00000 n +0000157959 00000 n +0000158010 00000 n +0000158061 00000 n +0000158112 00000 n +0000158163 00000 n +0000158214 00000 n +0000158265 00000 n +0000158316 00000 n +0000158367 00000 n +0000158418 00000 n +0000158469 00000 n +0000158520 00000 n +0000158571 00000 n +0000158622 00000 n +0000158673 00000 n +0000158724 00000 n +0000158775 00000 n +0000158826 00000 n +0000158877 00000 n +0000158928 00000 n +0000158979 00000 n +0000159030 00000 n +0000159081 00000 n +0000159132 00000 n +0000159183 00000 n +0000159234 00000 n +0000159285 00000 n +0000159336 00000 n +0000159387 00000 n +0000159438 00000 n +0000159489 00000 n +0000159540 00000 n +0000159591 00000 n +0000159642 00000 n +0000159693 00000 n +0000159744 00000 n +0000159795 00000 n +0000159846 00000 n +0000159897 00000 n +0000159948 00000 n +0000159999 00000 n +0000160050 00000 n +0000160101 00000 n +0000160152 00000 n +0000160203 00000 n +0000160254 00000 n +0000160305 00000 n +0000160356 00000 n +0000160407 00000 n +0000160458 00000 n +0000160509 00000 n +0000160560 00000 n +0000160611 00000 n +0000160662 00000 n +0000160713 00000 n +0000160764 00000 n +0000160815 00000 n +0000160866 00000 n +0000160917 00000 n +0000160968 00000 n +0000161019 00000 n +0000161070 00000 n +0000161121 00000 n +0000161172 00000 n +0000161223 00000 n +0000161274 00000 n +0000161325 00000 n +0000161376 00000 n +0000161427 00000 n +0000161478 00000 n +0000161529 00000 n +0000161580 00000 n +0000161631 00000 n +0000161682 00000 n +0000161733 00000 n +0000161784 00000 n +0000161835 00000 n +0000161886 00000 n +0000161937 00000 n +0000161988 00000 n +0000162039 00000 n +0000162090 00000 n +0000162141 00000 n +0000162192 00000 n +0000162243 00000 n +0000162294 00000 n +0000162345 00000 n +0000162396 00000 n +0000162447 00000 n +0000162498 00000 n +0000162549 00000 n +0000162600 00000 n +0000162651 00000 n +0000162702 00000 n +0000162753 00000 n +0000162804 00000 n +0000162855 00000 n +0000162906 00000 n +0000162957 00000 n +0000163008 00000 n +0000163059 00000 n +0000163110 00000 n +0000163161 00000 n +0000163212 00000 n +0000163263 00000 n +0000163314 00000 n +0000163365 00000 n +0000163416 00000 n +0000163467 00000 n +0000163518 00000 n +0000163569 00000 n +0000163620 00000 n +0000163671 00000 n +0000163722 00000 n +0000163773 00000 n +0000163824 00000 n +0000163875 00000 n +0000163926 00000 n +0000163977 00000 n +0000164028 00000 n +0000164079 00000 n +0000164130 00000 n +0000164181 00000 n +0000164232 00000 n +0000164283 00000 n +0000164334 00000 n +0000164385 00000 n +0000164436 00000 n +0000164487 00000 n +0000164538 00000 n +0000164589 00000 n +0000164640 00000 n +0000164691 00000 n +0000164742 00000 n +0000164793 00000 n +0000164844 00000 n +0000164895 00000 n +0000164946 00000 n +0000164997 00000 n +0000165048 00000 n +0000165099 00000 n +0000165150 00000 n +0000165201 00000 n +0000165252 00000 n +0000165303 00000 n +0000165354 00000 n +0000165405 00000 n +0000165456 00000 n +0000165507 00000 n +0000165558 00000 n +0000165609 00000 n +0000165660 00000 n +0000165711 00000 n +0000165762 00000 n +0000165813 00000 n +0000165864 00000 n +0000165915 00000 n +0000165966 00000 n +0000166017 00000 n +0000166068 00000 n +0000166119 00000 n +0000166170 00000 n +0000166221 00000 n +0000166272 00000 n +0000166323 00000 n +0000166374 00000 n +0000166425 00000 n +0000166476 00000 n +0000166527 00000 n +0000166578 00000 n +0000166629 00000 n +0000166680 00000 n +0000166731 00000 n +0000166782 00000 n +0000166833 00000 n +0000166884 00000 n +0000166935 00000 n +0000166986 00000 n +0000167037 00000 n +0000167088 00000 n +0000167139 00000 n +0000167190 00000 n +0000167241 00000 n +0000167292 00000 n +0000167343 00000 n +0000167394 00000 n +0000167445 00000 n +0000167496 00000 n +0000167547 00000 n +0000167598 00000 n +0000167649 00000 n +0000167700 00000 n +0000167751 00000 n +0000167802 00000 n +0000167853 00000 n +0000167904 00000 n +0000169379 00000 n +0000169534 00000 n +0000175892 00000 n +0000175915 00000 n +0000176013 00000 n +0000176117 00000 n +0000176138 00000 n +0000176272 00000 n +0000177038 00000 n +0000177060 00000 n +0000177204 00000 n +0000177608 00000 n +0000177630 00000 n +0000177773 00000 n +0000178693 00000 n +0000178715 00000 n +0000178858 00000 n +0000180296 00000 n +0000180319 00000 n +0000180462 00000 n +0000181359 00000 n +0000181381 00000 n +0000181497 00000 n +0000181697 00000 n +0000181719 00000 n +0000181853 00000 n +0000182208 00000 n +0000182230 00000 n +0000182355 00000 n +0000182705 00000 n +0000182727 00000 n +0000182852 00000 n +0000183202 00000 n +0000183224 00000 n +0000183349 00000 n +0000183703 00000 n +0000183725 00000 n +0000183850 00000 n +0000184136 00000 n +0000184158 00000 n +0000184274 00000 n +0000184478 00000 n +0000184500 00000 n +0000184634 00000 n +0000184985 00000 n +0000185007 00000 n +0000185132 00000 n +0000185398 00000 n +0000185420 00000 n +0000185554 00000 n +0000185954 00000 n +0000185976 00000 n +0000186101 00000 n +0000186381 00000 n +0000186403 00000 n +0000186537 00000 n +0000186954 00000 n +0000186976 00000 n +0000187101 00000 n +0000187395 00000 n +0000187417 00000 n +0000187551 00000 n +0000187831 00000 n +0000187853 00000 n +0000187978 00000 n +0000188216 00000 n +0000188238 00000 n +0000188372 00000 n +0000188617 00000 n +0000188639 00000 n +0000188755 00000 n +0000188954 00000 n +0000188976 00000 n +0000189110 00000 n +0000189350 00000 n +0000189372 00000 n +0000189524 00000 n +0000190311 00000 n +0000190333 00000 n +0000190490 00000 n +0000190827 00000 n +0000190849 00000 n +0000191015 00000 n +0000191705 00000 n +0000191727 00000 n +0000191893 00000 n +0000192961 00000 n +0000192983 00000 n +0000193140 00000 n +0000193940 00000 n +0000193962 00000 n +0000194128 00000 n +0000195207 00000 n +0000195230 00000 n +0000195387 00000 n +0000196056 00000 n +0000196078 00000 n +0000196244 00000 n +0000196940 00000 n +0000196962 00000 n +0000197128 00000 n +0000197868 00000 n +0000197890 00000 n +0000198047 00000 n +0000198603 00000 n +0000198625 00000 n +0000198791 00000 n +0000199606 00000 n +0000199628 00000 n +0000199794 00000 n +0000200474 00000 n +0000200496 00000 n +0000200648 00000 n +0000201382 00000 n +0000201404 00000 n +0000201570 00000 n +0000202306 00000 n +0000202328 00000 n +0000202485 00000 n +0000203212 00000 n +0000203234 00000 n +0000203400 00000 n +0000204138 00000 n +0000204160 00000 n +0000204317 00000 n +0000204847 00000 n +0000204869 00000 n +0000205035 00000 n +0000205677 00000 n +0000205699 00000 n +0000205865 00000 n +0000206622 00000 n +0000206644 00000 n +0000206811 00000 n +0000207612 00000 n +0000207634 00000 n +0000207792 00000 n +0000208349 00000 n +0000208371 00000 n +0000208538 00000 n +0000209329 00000 n +0000209351 00000 n +0000209518 00000 n +0000210385 00000 n +0000210407 00000 n +0000210559 00000 n +0000211345 00000 n +0000211367 00000 n +0000211516 00000 n +0000211827 00000 n +0000211849 00000 n +0000212016 00000 n +0000212665 00000 n +0000212687 00000 n +0000212854 00000 n +0000213642 00000 n +0000213664 00000 n +0000213816 00000 n +0000214554 00000 n +0000214576 00000 n +0000214725 00000 n +0000215118 00000 n +0000215140 00000 n +0000215292 00000 n +0000216065 00000 n +0000216087 00000 n +0000216236 00000 n +0000216627 00000 n +0000216649 00000 n +0000216816 00000 n +0000217667 00000 n +0000217689 00000 n +0000217841 00000 n +0000218566 00000 n +0000218588 00000 n +0000218737 00000 n +0000219127 00000 n +0000219149 00000 n +0000219316 00000 n +0000219984 00000 n +0000220006 00000 n +0000220167 00000 n +0000220834 00000 n +0000220856 00000 n +0000221014 00000 n +0000221571 00000 n +0000221593 00000 n +0000221727 00000 n +0000222093 00000 n +0000222115 00000 n +0000222249 00000 n +0000222613 00000 n +0000222635 00000 n +0000222769 00000 n +0000223137 00000 n +0000223159 00000 n +0000223293 00000 n +0000223657 00000 n +0000223679 00000 n +0000223813 00000 n +0000224178 00000 n +0000224200 00000 n +0000224334 00000 n +0000224700 00000 n +0000224722 00000 n +0000224856 00000 n +0000225219 00000 n +0000225241 00000 n +0000225375 00000 n +0000225743 00000 n +0000225765 00000 n +0000225899 00000 n +0000226262 00000 n +0000226284 00000 n +0000226418 00000 n +0000226782 00000 n +0000226804 00000 n +0000226938 00000 n +0000227299 00000 n +0000227321 00000 n +0000227455 00000 n +0000227819 00000 n +0000227841 00000 n +0000227975 00000 n +0000228344 00000 n +0000228366 00000 n +0000228500 00000 n +0000228869 00000 n +0000228891 00000 n +0000229025 00000 n +0000229391 00000 n +0000229413 00000 n +0000229547 00000 n +0000229914 00000 n +0000229936 00000 n +0000230070 00000 n +0000230433 00000 n +0000230455 00000 n +0000230589 00000 n +0000230959 00000 n +0000230981 00000 n +0000231115 00000 n +0000231478 00000 n +0000231500 00000 n +0000231634 00000 n +0000231998 00000 n +0000232020 00000 n +0000232154 00000 n +0000232518 00000 n +0000232540 00000 n +0000232674 00000 n +0000233037 00000 n +0000233059 00000 n +0000233193 00000 n +0000233555 00000 n +0000233577 00000 n +0000233711 00000 n +0000234078 00000 n +0000234100 00000 n +0000234234 00000 n +0000234599 00000 n +0000234621 00000 n +0000234755 00000 n +0000235121 00000 n +0000235143 00000 n +0000235277 00000 n +0000235640 00000 n +0000235662 00000 n +0000235796 00000 n +0000236161 00000 n +0000236183 00000 n +0000236317 00000 n +0000236681 00000 n +0000236703 00000 n +0000236837 00000 n +0000237205 00000 n +0000237227 00000 n +0000237361 00000 n +0000237728 00000 n +0000237750 00000 n +0000237884 00000 n +0000238248 00000 n +0000238270 00000 n +0000238404 00000 n +0000238771 00000 n +0000238793 00000 n +0000238927 00000 n +0000239296 00000 n +0000239318 00000 n +0000239452 00000 n +0000239817 00000 n +0000239839 00000 n +0000239973 00000 n +0000240340 00000 n +0000240362 00000 n +0000240496 00000 n +0000240863 00000 n +0000240885 00000 n +0000241019 00000 n +0000241388 00000 n +0000241410 00000 n +0000241544 00000 n +0000241911 00000 n +0000241933 00000 n +0000242067 00000 n +0000242434 00000 n +0000242456 00000 n +0000242590 00000 n +0000242956 00000 n +0000242978 00000 n +0000243112 00000 n +0000243480 00000 n +0000243502 00000 n +0000243636 00000 n +0000243998 00000 n +0000244020 00000 n +0000244154 00000 n +0000244523 00000 n +0000244545 00000 n +0000244679 00000 n +0000245043 00000 n +0000245065 00000 n +0000245199 00000 n +0000245562 00000 n +0000245584 00000 n +0000245718 00000 n +0000246079 00000 n +0000246101 00000 n +0000246235 00000 n +0000246598 00000 n +0000246620 00000 n +0000246754 00000 n +0000247119 00000 n +0000247141 00000 n +0000247275 00000 n +0000247641 00000 n +0000247663 00000 n +0000247797 00000 n +0000248162 00000 n +0000248184 00000 n +0000248318 00000 n +0000248685 00000 n +0000248707 00000 n +0000248841 00000 n +0000249208 00000 n +0000249230 00000 n +0000249364 00000 n +0000249728 00000 n +0000249750 00000 n +0000249884 00000 n +0000250249 00000 n +0000250271 00000 n +0000250405 00000 n +0000250771 00000 n +0000250793 00000 n +0000250927 00000 n +0000251289 00000 n +0000251311 00000 n +0000251445 00000 n +0000251809 00000 n +0000251831 00000 n +0000251965 00000 n +0000252326 00000 n +0000252348 00000 n +0000252482 00000 n +0000252847 00000 n +0000252869 00000 n +0000253003 00000 n +0000253364 00000 n +0000253386 00000 n +0000253520 00000 n +0000253887 00000 n +0000253909 00000 n +0000254043 00000 n +0000254406 00000 n +0000254428 00000 n +0000254562 00000 n +0000254926 00000 n +0000254948 00000 n +0000255082 00000 n +0000255448 00000 n +0000255470 00000 n +0000255604 00000 n +0000255976 00000 n +0000255998 00000 n +0000256132 00000 n +0000256497 00000 n +0000256519 00000 n +0000256653 00000 n +0000257022 00000 n +0000257044 00000 n +0000257178 00000 n +0000257545 00000 n +0000257567 00000 n +0000257701 00000 n +0000258069 00000 n +0000258091 00000 n +0000258225 00000 n +0000258588 00000 n +0000258610 00000 n +0000258744 00000 n +0000259111 00000 n +0000259133 00000 n +0000259267 00000 n +0000259629 00000 n +0000259651 00000 n +0000259785 00000 n +0000260153 00000 n +0000260175 00000 n +0000260309 00000 n +0000260674 00000 n +0000260696 00000 n +0000260830 00000 n +0000261199 00000 n +0000261221 00000 n +0000261379 00000 n +0000263945 00000 n +0000263968 00000 n +0000264126 00000 n +0000266436 00000 n +0000266459 00000 n +0000266617 00000 n +0000268148 00000 n +0000268171 00000 n +0000268320 00000 n +0000269588 00000 n +0000269611 00000 n +0000269760 00000 n +0000270977 00000 n +0000271000 00000 n +0000271149 00000 n +0000272440 00000 n +0000272463 00000 n +0000272612 00000 n +0000273900 00000 n +0000273923 00000 n +0000274072 00000 n +0000275359 00000 n +0000275382 00000 n +0000275531 00000 n +0000276821 00000 n +0000276844 00000 n +0000276993 00000 n +0000278261 00000 n +0000278284 00000 n +0000278433 00000 n +0000279721 00000 n +0000279744 00000 n +0000279893 00000 n +0000281174 00000 n +0000281197 00000 n +0000281346 00000 n +0000282640 00000 n +0000282663 00000 n +0000282812 00000 n +0000284091 00000 n +0000284114 00000 n +0000284263 00000 n +0000285544 00000 n +0000285567 00000 n +0000285716 00000 n +0000287011 00000 n +0000287034 00000 n +0000287183 00000 n +0000288454 00000 n +0000288477 00000 n +0000288627 00000 n +0000289724 00000 n +0000289747 00000 n +0000289806 00000 n +0000289915 00000 n +0000290066 00000 n +0000290173 00000 n +0000290282 00000 n +0000290454 00000 n +0000290566 00000 n +0000290686 00000 n +0000290796 00000 n +0000290909 00000 n +0000291022 00000 n +0000291143 00000 n +0000291245 00000 n +0000291405 00000 n +0000291551 00000 n +0000291667 00000 n +0000291825 00000 n +0000291930 00000 n +0000292078 00000 n +0000292198 00000 n +0000292327 00000 n +0000292434 00000 n +0000292591 00000 n +0000292696 00000 n +0000292824 00000 n +0000292952 00000 n +0000293075 00000 n +0000293207 00000 n +0000293333 00000 n +0000293445 00000 n +0000293602 00000 n +0000293707 00000 n +0000293836 00000 n +0000293959 00000 n +0000294087 00000 n +0000294216 00000 n +0000294340 00000 n +0000294472 00000 n +0000294601 00000 n +0000294731 00000 n +0000294848 00000 n +0000295009 00000 n +0000295114 00000 n +0000295248 00000 n +0000295383 00000 n +0000295500 00000 n +0000295657 00000 n +0000295762 00000 n +0000295891 00000 n +0000296025 00000 n +0000296162 00000 n +0000296261 00000 n +0000296403 00000 n +0000296508 00000 n +0000296632 00000 n +0000296756 00000 n +0000296879 00000 n +0000297004 00000 n +0000297125 00000 n +0000297253 00000 n +0000297360 00000 n +0000297523 00000 n +0000297661 00000 n +0000297776 00000 n +0000297897 00000 n +0000298004 00000 n +0000298170 00000 n +0000298263 00000 n +0000298390 00000 n +0000298503 00000 n +0000298674 00000 n +0000298812 00000 n +0000298919 00000 n +0000299027 00000 n +0000299187 00000 n +0000299297 00000 n +0000299427 00000 n +0000299557 00000 n +0000299668 00000 n +0000299783 00000 n +0000299947 00000 n +0000300085 00000 n +0000300200 00000 n +0000300321 00000 n +0000300442 00000 n +0000300541 00000 n +0000300707 00000 n +0000300800 00000 n +0000300927 00000 n +0000301048 00000 n +0000301205 00000 n +0000301311 00000 n +0000301431 00000 n +0000301550 00000 n +0000301674 00000 n +0000301794 00000 n +0000301913 00000 n +0000302021 00000 n +0000302179 00000 n +0000302257 00000 n +0000302402 00000 n +0000302549 00000 n +0000302646 00000 n +0000302761 00000 n +0000302874 00000 n +0000302991 00000 n +0000303104 00000 n +0000303204 00000 n +0000303365 00000 n +0000303462 00000 n +0000303577 00000 n +0000303690 00000 n +0000303807 00000 n +0000303920 00000 n +0000304020 00000 n +0000304185 00000 n +0000304282 00000 n +0000304397 00000 n +0000304510 00000 n +0000304627 00000 n +0000304740 00000 n +0000304840 00000 n +0000305001 00000 n +0000305098 00000 n +0000305213 00000 n +0000305326 00000 n +0000305443 00000 n +0000305556 00000 n +0000305656 00000 n +0000305819 00000 n +0000305916 00000 n +0000306031 00000 n +0000306148 00000 n +0000306261 00000 n +0000306361 00000 n +0000306523 00000 n +0000306620 00000 n +0000306735 00000 n +0000306848 00000 n +0000306965 00000 n +0000307078 00000 n +0000307178 00000 n +0000307340 00000 n +0000307437 00000 n +0000307550 00000 n +0000307667 00000 n +0000307780 00000 n +0000307880 00000 n +0000308041 00000 n +0000308138 00000 n +0000308253 00000 n +0000308366 00000 n +0000308483 00000 n +0000308583 00000 n +0000308746 00000 n +0000308843 00000 n +0000308958 00000 n +0000309071 00000 n +0000309188 00000 n +0000309301 00000 n +0000309401 00000 n +0000309559 00000 n +0000309656 00000 n +0000309771 00000 n +0000309884 00000 n +0000310001 00000 n +0000310100 00000 n +0000310263 00000 n +0000310360 00000 n +0000310475 00000 n +0000310588 00000 n +0000310705 00000 n +0000310818 00000 n +0000310918 00000 n +0000311081 00000 n +0000311178 00000 n +0000311291 00000 n +0000311408 00000 n +0000311521 00000 n +0000311621 00000 n +0000311785 00000 n +0000311882 00000 n +0000311997 00000 n +0000312110 00000 n +0000312227 00000 n +0000312340 00000 n +0000312440 00000 n +0000312601 00000 n +0000312698 00000 n +0000312815 00000 n +0000312928 00000 n +0000313028 00000 n +0000313188 00000 n +0000313285 00000 n +0000313400 00000 n +0000313517 00000 n +0000313630 00000 n +0000313730 00000 n +0000313889 00000 n +0000313986 00000 n +0000314101 00000 n +0000314214 00000 n +0000314331 00000 n +0000314444 00000 n +0000314544 00000 n +0000314706 00000 n +0000314803 00000 n +0000314918 00000 n +0000315031 00000 n +0000315148 00000 n +0000315261 00000 n +0000315361 00000 n +0000315522 00000 n +0000315619 00000 n +0000315732 00000 n +0000315849 00000 n +0000315962 00000 n +0000316062 00000 n +0000316225 00000 n +0000316322 00000 n +0000316437 00000 n +0000316550 00000 n +0000316667 00000 n +0000316780 00000 n +0000316880 00000 n +0000317044 00000 n +0000317141 00000 n +0000317256 00000 n +0000317369 00000 n +0000317486 00000 n +0000317599 00000 n +0000317699 00000 n +0000317860 00000 n +0000317957 00000 n +0000318072 00000 n +0000318185 00000 n +0000318302 00000 n +0000318415 00000 n +0000318515 00000 n +0000318678 00000 n +0000318775 00000 n +0000318890 00000 n +0000319007 00000 n +0000319120 00000 n +0000319220 00000 n +0000319382 00000 n +0000319479 00000 n +0000319594 00000 n +0000319707 00000 n +0000319824 00000 n +0000319937 00000 n +0000320037 00000 n +0000320205 00000 n +0000320302 00000 n +0000320417 00000 n +0000320530 00000 n +0000320647 00000 n +0000320760 00000 n +0000320860 00000 n +0000321028 00000 n +0000321125 00000 n +0000321240 00000 n +0000321353 00000 n +0000321470 00000 n +0000321583 00000 n +0000321683 00000 n +0000321852 00000 n +0000321949 00000 n +0000322064 00000 n +0000322177 00000 n +0000322294 00000 n +0000322407 00000 n +0000322507 00000 n +0000322676 00000 n +0000322773 00000 n +0000322888 00000 n +0000323001 00000 n +0000323118 00000 n +0000323231 00000 n +0000323331 00000 n +0000323489 00000 n +0000323586 00000 n +0000323699 00000 n +0000323816 00000 n +0000323929 00000 n +0000324029 00000 n +0000324189 00000 n +0000324286 00000 n +0000324401 00000 n +0000324514 00000 n +0000324631 00000 n +0000324730 00000 n +0000324886 00000 n +0000324983 00000 n +0000325096 00000 n +0000325213 00000 n +0000325326 00000 n +0000325426 00000 n +0000325586 00000 n +0000325683 00000 n +0000325798 00000 n +0000325911 00000 n +0000326028 00000 n +0000326141 00000 n +0000326241 00000 n +0000326398 00000 n +0000326495 00000 n +0000326610 00000 n +0000326723 00000 n +0000326840 00000 n +0000326953 00000 n +0000327053 00000 n +0000327216 00000 n +0000327313 00000 n +0000327428 00000 n +0000327541 00000 n +0000327658 00000 n +0000327771 00000 n +0000327871 00000 n +0000328028 00000 n +0000328125 00000 n +0000328240 00000 n +0000328353 00000 n +0000328470 00000 n +0000328583 00000 n +0000328683 00000 n +0000328842 00000 n +0000328939 00000 n +0000329054 00000 n +0000329167 00000 n +0000329284 00000 n +0000329397 00000 n +0000329497 00000 n +0000329657 00000 n +0000329754 00000 n +0000329869 00000 n +0000329982 00000 n +0000330099 00000 n +0000330212 00000 n +0000330312 00000 n +0000330470 00000 n +0000330567 00000 n +0000330682 00000 n +0000330795 00000 n +0000330912 00000 n +0000331025 00000 n +0000331125 00000 n +0000331285 00000 n +0000331382 00000 n +0000331497 00000 n +0000331610 00000 n +0000331727 00000 n +0000331840 00000 n +0000331940 00000 n +0000332097 00000 n +0000332194 00000 n +0000332309 00000 n +0000332422 00000 n +0000332539 00000 n +0000332652 00000 n +0000332752 00000 n +0000332909 00000 n +0000333006 00000 n +0000333121 00000 n +0000333234 00000 n +0000333351 00000 n +0000333464 00000 n +0000333564 00000 n +0000333719 00000 n +0000333816 00000 n +0000333931 00000 n +0000334044 00000 n +0000334161 00000 n +0000334274 00000 n +0000334374 00000 n +0000334530 00000 n +0000334627 00000 n +0000334742 00000 n +0000334855 00000 n +0000334972 00000 n +0000335085 00000 n +0000335185 00000 n +0000335350 00000 n +0000335447 00000 n +0000335562 00000 n +0000335675 00000 n +0000335792 00000 n +0000335905 00000 n +0000336005 00000 n +0000336168 00000 n +0000336265 00000 n +0000336380 00000 n +0000336493 00000 n +0000336610 00000 n +0000336723 00000 n +0000336823 00000 n +0000336983 00000 n +0000337080 00000 n +0000337195 00000 n +0000337308 00000 n +0000337425 00000 n +0000337538 00000 n +0000337638 00000 n +0000337799 00000 n +0000337896 00000 n +0000338011 00000 n +0000338124 00000 n +0000338241 00000 n +0000338354 00000 n +0000338454 00000 n +0000338610 00000 n +0000338707 00000 n +0000338822 00000 n +0000338935 00000 n +0000339052 00000 n +0000339165 00000 n +0000339265 00000 n +0000339427 00000 n +0000339524 00000 n +0000339639 00000 n +0000339752 00000 n +0000339869 00000 n +0000339982 00000 n +0000340082 00000 n +0000340241 00000 n +0000340338 00000 n +0000340453 00000 n +0000340566 00000 n +0000340683 00000 n +0000340796 00000 n +0000340896 00000 n +0000341052 00000 n +0000341149 00000 n +0000341264 00000 n +0000341377 00000 n +0000341494 00000 n +0000341607 00000 n +0000341707 00000 n +0000341865 00000 n +0000341962 00000 n +0000342077 00000 n +0000342190 00000 n +0000342307 00000 n +0000342420 00000 n +0000342520 00000 n +0000342675 00000 n +0000342772 00000 n +0000342887 00000 n +0000343000 00000 n +0000343117 00000 n +0000343230 00000 n +0000343330 00000 n +0000343486 00000 n +0000343583 00000 n +0000343698 00000 n +0000343811 00000 n +0000343928 00000 n +0000344041 00000 n +0000344141 00000 n +0000344302 00000 n +0000344399 00000 n +0000344514 00000 n +0000344627 00000 n +0000344744 00000 n +0000344857 00000 n +0000344957 00000 n +0000345117 00000 n +0000345214 00000 n +0000345329 00000 n +0000345442 00000 n +0000345559 00000 n +0000345672 00000 n +0000345772 00000 n +0000345932 00000 n +0000346029 00000 n +0000346144 00000 n +0000346257 00000 n +0000346374 00000 n +0000346487 00000 n +0000346587 00000 n +0000346744 00000 n +0000346841 00000 n +0000346956 00000 n +0000347069 00000 n +0000347186 00000 n +0000347299 00000 n +0000347399 00000 n +0000347557 00000 n +0000347654 00000 n +0000347769 00000 n +0000347882 00000 n +0000347999 00000 n +0000348112 00000 n +0000348212 00000 n +0000348369 00000 n +0000348466 00000 n +0000348581 00000 n +0000348694 00000 n +0000348811 00000 n +0000348924 00000 n +0000349024 00000 n +0000349185 00000 n +0000349282 00000 n +0000349397 00000 n +0000349510 00000 n +0000349627 00000 n +0000349740 00000 n +0000349840 00000 n +0000350002 00000 n +0000350099 00000 n +0000350214 00000 n +0000350327 00000 n +0000350444 00000 n +0000350557 00000 n +0000350657 00000 n +0000350815 00000 n +0000350912 00000 n +0000351027 00000 n +0000351140 00000 n +0000351257 00000 n +0000351370 00000 n +0000351470 00000 n +0000351631 00000 n +0000351728 00000 n +0000351843 00000 n +0000351956 00000 n +0000352073 00000 n +0000352186 00000 n +0000352286 00000 n +0000352448 00000 n +0000352545 00000 n +0000352660 00000 n +0000352773 00000 n +0000352890 00000 n +0000353003 00000 n +0000353103 00000 n +0000353262 00000 n +0000353359 00000 n +0000353474 00000 n +0000353587 00000 n +0000353704 00000 n +0000353817 00000 n +0000353917 00000 n +0000354077 00000 n +0000354174 00000 n +0000354289 00000 n +0000354402 00000 n +0000354519 00000 n +0000354632 00000 n +0000354732 00000 n +0000354896 00000 n +0000354993 00000 n +0000355108 00000 n +0000355221 00000 n +0000355338 00000 n +0000355451 00000 n +0000355551 00000 n +0000355716 00000 n +0000355813 00000 n +0000355928 00000 n +0000356041 00000 n +0000356158 00000 n +0000356271 00000 n +0000356371 00000 n +0000356534 00000 n +0000356631 00000 n +0000356746 00000 n +0000356859 00000 n +0000356976 00000 n +0000357089 00000 n +0000357189 00000 n +0000357349 00000 n +0000357446 00000 n +0000357561 00000 n +0000357674 00000 n +0000357791 00000 n +0000357904 00000 n +0000358004 00000 n +0000358165 00000 n +0000358262 00000 n +0000358377 00000 n +0000358490 00000 n +0000358607 00000 n +0000358720 00000 n +0000358820 00000 n +0000358981 00000 n +0000359078 00000 n +0000359193 00000 n +0000359306 00000 n +0000359423 00000 n +0000359536 00000 n +0000359636 00000 n +0000359793 00000 n +0000359890 00000 n +0000360005 00000 n +0000360118 00000 n +0000360235 00000 n +0000360348 00000 n +0000360448 00000 n +0000360612 00000 n +0000360709 00000 n +0000360824 00000 n +0000360937 00000 n +0000361054 00000 n +0000361167 00000 n +0000361267 00000 n +0000361424 00000 n +0000361521 00000 n +0000361636 00000 n +0000361749 00000 n +0000361866 00000 n +0000361979 00000 n +0000362079 00000 n +0000362233 00000 n +0000362330 00000 n +0000362445 00000 n +0000362558 00000 n +0000362675 00000 n +0000362788 00000 n +0000362888 00000 n +0000363043 00000 n +0000363140 00000 n +0000363255 00000 n +0000363368 00000 n +0000363485 00000 n +0000363598 00000 n +0000363698 00000 n +0000363853 00000 n +0000363950 00000 n +0000364065 00000 n +0000364178 00000 n +0000364295 00000 n +0000364408 00000 n +0000364508 00000 n +0000364669 00000 n +0000364766 00000 n +0000364881 00000 n +0000364994 00000 n +0000365111 00000 n +0000365224 00000 n +0000365324 00000 n +0000365480 00000 n +0000365577 00000 n +0000365692 00000 n +0000365805 00000 n +0000365922 00000 n +0000366035 00000 n +0000366135 00000 n +0000366296 00000 n +0000366393 00000 n +0000366508 00000 n +0000366621 00000 n +0000366738 00000 n +0000366851 00000 n +0000366951 00000 n +0000367110 00000 n +0000367207 00000 n +0000367322 00000 n +0000367435 00000 n +0000367552 00000 n +0000367665 00000 n +0000367765 00000 n +0000367928 00000 n +0000368025 00000 n +0000368140 00000 n +0000368253 00000 n +0000368370 00000 n +0000368483 00000 n +0000368583 00000 n +0000368741 00000 n +0000368838 00000 n +0000368953 00000 n +0000369066 00000 n +0000369183 00000 n +0000369296 00000 n +0000369396 00000 n +0000369556 00000 n +0000369653 00000 n +0000369768 00000 n +0000369881 00000 n +0000369998 00000 n +0000370111 00000 n +0000370211 00000 n +0000370369 00000 n +0000370466 00000 n +0000370581 00000 n +0000370694 00000 n +0000370811 00000 n +0000370924 00000 n +0000371024 00000 n +0000371180 00000 n +0000371277 00000 n +0000371392 00000 n +0000371505 00000 n +0000371622 00000 n +0000371735 00000 n +0000371835 00000 n +0000371992 00000 n +0000372089 00000 n +0000372204 00000 n +0000372317 00000 n +0000372434 00000 n +0000372547 00000 n +0000372647 00000 n +0000372802 00000 n +0000372899 00000 n +0000373014 00000 n +0000373127 00000 n +0000373244 00000 n +0000373357 00000 n +0000373457 00000 n +0000373613 00000 n +0000373710 00000 n +0000373825 00000 n +0000373938 00000 n +0000374055 00000 n +0000374168 00000 n +0000374268 00000 n +0000374424 00000 n +0000374521 00000 n +0000374636 00000 n +0000374749 00000 n +0000374866 00000 n +0000374979 00000 n +0000375079 00000 n +0000375239 00000 n +0000375336 00000 n +0000375451 00000 n +0000375564 00000 n +0000375681 00000 n +0000375794 00000 n +0000375894 00000 n +0000376051 00000 n +0000376148 00000 n +0000376263 00000 n +0000376376 00000 n +0000376493 00000 n +0000376606 00000 n +0000376706 00000 n +0000376861 00000 n +0000376958 00000 n +0000377073 00000 n +0000377186 00000 n +0000377303 00000 n +0000377416 00000 n +0000377516 00000 n +0000377677 00000 n +0000377774 00000 n +0000377889 00000 n +0000378002 00000 n +0000378119 00000 n +0000378232 00000 n +0000378332 00000 n +0000378499 00000 n +0000378596 00000 n +0000378711 00000 n +0000378824 00000 n +0000378941 00000 n +0000379054 00000 n +0000379154 00000 n +0000379315 00000 n +0000379412 00000 n +0000379527 00000 n +0000379640 00000 n +0000379757 00000 n +0000379870 00000 n +0000379970 00000 n +0000380129 00000 n +0000380226 00000 n +0000380341 00000 n +0000380454 00000 n +0000380571 00000 n +0000380684 00000 n +0000380784 00000 n +0000380947 00000 n +0000381044 00000 n +0000381159 00000 n +0000381272 00000 n +0000381389 00000 n +0000381502 00000 n +0000381602 00000 n +0000381763 00000 n +0000381860 00000 n +0000381975 00000 n +0000382088 00000 n +0000382205 00000 n +0000382318 00000 n +0000382418 00000 n +0000382575 00000 n +0000382672 00000 n +0000382787 00000 n +0000382900 00000 n +0000383017 00000 n +0000383130 00000 n +0000383230 00000 n +0000383389 00000 n +0000383486 00000 n +0000383601 00000 n +0000383714 00000 n +0000383831 00000 n +0000383944 00000 n +0000384044 00000 n +0000384199 00000 n +0000384296 00000 n +0000384411 00000 n +0000384524 00000 n +0000384641 00000 n +0000384754 00000 n +0000384854 00000 n +0000385015 00000 n +0000385112 00000 n +0000385227 00000 n +0000385340 00000 n +0000385457 00000 n +0000385570 00000 n +0000385670 00000 n +0000385829 00000 n +0000385926 00000 n +0000386041 00000 n +0000386154 00000 n +0000386271 00000 n +0000386384 00000 n +0000386484 00000 n +0000386630 00000 n +0000386727 00000 n +0000386842 00000 n +0000386955 00000 n +0000387072 00000 n +0000387185 00000 n +0000387285 00000 n +trailer +<> +startxref +387519 +%%EOF diff --git a/doc/spm.shtml b/doc/spm.shtml new file mode 100644 index 0000000000..079aea84ac --- /dev/null +++ b/doc/spm.shtml @@ -0,0 +1,4220 @@ + + + + + + DRAFT - CUPS Software Programmers Manual + + + +

Preface

+ +This software programmers manual provides software programming +information for the Common UNIX Printing System ("CUPS") Version 1.1. + +

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

+ + +

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

+ +

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

+ + +

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..8ed3746095 --- /dev/null +++ b/doc/ssr.html @@ -0,0 +1,243 @@ + + + +DRAFT - CUPS Software Security Report + + + + + + + +

+

DRAFT - CUPS Software Security Report


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

Table of Contents

+
+
1 Scope + +2 References + +3 Local Access Risks + +4 Remote Access Risks + +A Glossary + +
+

1 Scope

+

1.1 Identification

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

1.2 System Overview

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

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

+

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

+

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

+

1.3 Document Overview

+

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

+
    +
  • 1 - Scope
  • +
  • 2 - References
  • +
  • 3 - Local Access Risks
  • +
  • 4 - Remote Access Risks
  • +
  • A - Glossary
  • +
+

2 References

+

2.1 CUPS Documentation

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

2.2 Other Documents

+ The following non-CUPS documents are referenced by this document: +
    +
  • IEEE 1387.4, System Administration: Printing (draft)
  • +
  • IPP/1.0: Additional Optional Operations - Set 1
  • +
  • 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.
  2. +

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

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

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

    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.

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

    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.

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

    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.

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

    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.

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

    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.

    +
+

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 0000000000000000000000000000000000000000..28f36afb3485dfadc4e6459d4b8a6e812271995a GIT binary patch literal 25053 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 literal 0 Hc-jL100001 diff --git a/doc/ssr.shtml b/doc/ssr.shtml new file mode 100644 index 0000000000..ce456a3fb5 --- /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.1.

+ +

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.1: CUPS Configuration Management Plan +
  • CUPS-IDD-1.1: CUPS System Interface Design Description +
  • CUPS-SAM-1.1.x: CUPS Software Administrators Manual +
  • CUPS-SDD-1.1: CUPS Software Design Description +
  • CUPS-SPM-1.1: CUPS Software Programming Manual +
  • CUPS-SSR-1.1: CUPS Software Security Report +
  • CUPS-STP-1.1: CUPS Software Test Plan +
  • CUPS-SUM-1.1.x: CUPS Software Users Manual +
  • CUPS-SVD-1.1.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..019857384c --- /dev/null +++ b/doc/stp.html @@ -0,0 +1,159 @@ + + + +DRAFT - CUPS Software Test Plan + + + + + + + +

+

DRAFT - CUPS Software Test Plan


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

Table of Contents

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

1 Scope

+

1.1 Identification

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

1.2 System Overview

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

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

+

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

+

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

+

1.3 Document Overview

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

2 References

+

2.1 CUPS Documentation

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

2.2 Other Documents

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

3 Local Tests

+

4 Remote Tests

+

A Glossary

+

A.1 Terms

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

A.2 Acronyms

+
+
ASCII
+
American Standard Code for Information Interchange
+
CUPS
+
Common UNIX Printing System
+
ESC/P
+
EPSON Standard Code for Printers
+
FTP
+
File Transfer Protocol
+
HP-GL
+
Hewlett-Packard Graphics Language
+
HP-PCL
+
Hewlett-Packard Printer Control Language
+
HP-PJL
+
Hewlett-Packard Printer Job Language
+
IETF
+
Internet Engineering Task Force
+
IPP
+
Internet Printing Protocol
+
ISO
+
International Standards Organization
+
LPD
+
Line Printer Daemon
+
MIME
+
Multimedia Internet Mail Exchange
+
PCL
+
Page Control Language
+
PPD
+
PostScript Printer Description
+
SMB
+
Server Message Block
+
TFTP
+
Trivial File Transfer Protocol
+
+ + diff --git a/doc/stp.pdf b/doc/stp.pdf new file mode 100644 index 0000000000000000000000000000000000000000..3e97e08196387a4b09cdc033555e8a9ab946aba7 GIT binary patch literal 21277 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 + + + + + + DRAFT - CUPS Software Test Plan + + + +

Scope

+ +

Identification

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

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.1: CUPS Configuration Management Plan +
  • CUPS-IDD-1.1: CUPS System Interface Design Description +
  • CUPS-SAM-1.1.x: CUPS Software Administrators Manual +
  • CUPS-SDD-1.1: CUPS Software Design Description +
  • CUPS-SPM-1.1: CUPS Software Programming Manual +
  • CUPS-SSR-1.1: CUPS Software Security Report +
  • CUPS-STP-1.1: CUPS Software Test Plan +
  • CUPS-SUM-1.1.x: CUPS Software Users Manual +
  • CUPS-SVD-1.1.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..29a2484e24 --- /dev/null +++ b/doc/sum.html @@ -0,0 +1,540 @@ + + + +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 + +
+

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..84af849a31 --- /dev/null +++ b/doc/sum.pdf @@ -0,0 +1,628 @@ +%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[10 0 R +]endobj +12 0 obj<>endobj +13 0 obj<>endobj +14 0 obj[13 0 R +]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[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<>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<>stream +xÚìÏsë8rÇIŠºÌ‰öŒî´üt§çyšÝ­ÚJñÙfvçÖ$ÁÊ!•S*Ç6•üÿ±~X"H€èn$è5¦jêÙE|ˆÆ·@ƒúÇOßòýÛßò?=å¿ýžÿçÿô,~*ÅOÿÈÛÿù×?þøÛï¿ÿºÏÿü—_Ÿò§§§·kýñõ¥ù÷¯|­ÿöœþº?•ßNå÷SùË©¼œÊ¿žÊ¿üÇ×?òÿýŸÿû¯¯ÿ–ÿíÛ׿ç‡oß¾>ÃKþ=ÿãõ§öcøä²+âõi»Ý>ÜËÛ?¶ß_—Î%^¶wY¤*w÷¯ËäOj¤Üöû¸ē‰é½Ü?–KáÂC]о/ëå!"—x[ÎõœE¼r˜ë‰KåÒ!˜¾rÛg޹^òȾü\ÆÕÊÏ3s=GžJRÎÉõ-òVâÃl\ŽuЄõV¾ÌÂ%²( + ‚B¹ü29×$X,0X –€Åƒ %ƒ/° ¬(ÚMÄåÝoÙ9h6×ÄXo`å\ûhò’LÀõ#𡬼sÕÑ,åÏ\M6A!|…gi,A +Ú Ñ ê£s5Ѭåà‹+›— 9Ä`™ãÅ`ž‹,öD.1?V{àÊàŠRç\uD98æY\‰c®}HÙ8媣`Jé++D91WT蚐°ŒÒË TÔ  LÔ‹Š4ðZåªBÃ2t,OãQ ÔxŒsÆq‰±FãzX¢Æ#F,Ï%£FL×]w÷Ûí—×cy>|ðÛa0IwÅ÷_†ƒüxÂ[‡ÿîŠG’þÅ˃ŸßÝuoœ*=[ í,¸ö~ºªÛk[ça=xì.Bú±àæØ\ìPƒ–.Î$[q¹¸¡==·aMJ&³»XéԜ.K™\¬@ž› É貘ÇUùÑv‡]¶cqeSÙà՛eN¤ܯjؤ½s’  ®|²¡ÅϼJé\Í Xd°˜ÎEùØÍÉÜZ9ƹfÂ"‚­¨\Õ FÈ1ŒȕυEÛи'’ –Y¹0p7ñú¥uZj+Cg‘¼c,Òé« …«rÎX•½ÅÍÁ‘jÄ¥{.B J<—°ÒlKÃ7D=Ì:¸ÎåÛÁÉ %i=•œkˆàBf½ .Ú`Ø`¹Š¹2O”,Á W­Ç’ó ìÍПR4q‡ãÚa…„–¤8®´&1Š«žÙ#3ì€á«aÚz/8 [c¸²0Dƒ¢õ ‚«æfóuXiæ*B J‡íÌ\Y OjOjäªÃê.d‡%F®"°îBú°ÒĕÖ]È'½1p5Á¸dZ“RW\wá¢ÄÄÀ•6ºÐRVŽr‰» 7æw£\u€Ý…[FJG¹*OŠ…²¢d”+ (2$*ÇVå'ÆB ÃRåÓ©¹Z’ Wå“s! q5ÂÀÚÛ=W¢È£­ÔrAˆ"v@;-W¨jàLi­ã¡ªnè¯t\5-4”=Ùí§ž±¿ÿ.Ï´’T¹Æúù=¾aÀ +¢6(®–KH·Kh%ºÖRÕÓbQ®•–ër›®Îa‡Àà ¯Çé¹ £^ >ÜÌіœáµCrí´\MçùÖ 1£$UsÑys¥Z®³í%·NH)}¢æÊ‰Îkœ+ÑsÝ´BPf=ègŒàp‡åz7.×MÛk¼b”¾Tq5ÔÊÀµÑrÝD° ¬•T؇ô¹WŠçZ鹊÷G”Q&ß V<זByW¤çª/ŸÕPÌ1PRWF4C#×NËu¾×úü+ü’QØV +.A5C#WªçڟòáªÕr[¬àª©fhäŠõ\盽§5Rì•K,×êZ[Éu6Ž;êÊ12BªWNZ,×:{—'%WG¤(³ÔgO@• ž«x j®Š5K5†ˆëWC6Ãq®ZÂp ÖbI…Ó5 ÊFÒâ¹Ä»Y¨¹®&EZ,ip-â\9%pžê¹*֚Nè(; +\n£á¬5;c+\ŒôÅq®æ" +®K‰kvª‰@“¤¥pµ¥×qgéB™ÐdcMãº(½Ž«àôWòD@“ë¢ô:®Œ3¾êÙwCÅuQz WÍÛÃÈ0’ ¤h#!r]”^ÃUðûMÏ%s Æð2r•^Õñ6g +ÌÃ’lì¨\g¥Ws5Ì]Œ +㘁´¶ÑR¹ÎJ¯æ½ØER2WÁ^f®“Ò«¹rfæŽÀ8f DQ)ëd݅~^¹e¢IàkSYŽ­\§Öç*®³Ý Fȑ#š ”(ªT?º²k ±ÌukDŸ+?krN7Ä="àVÌµë>š>h¸Þ;а›‚]†Yw¹k6+IlºŠšô¸ Wuáiè†X!dr¸Ñ˜ÄjøCýsȵèÝJ´§•¸rŽlH[âã‹:\…’K\[°'¢@Ø¢C­I¤€]Ÿ«VrU×Ê=öEèà£ÃDïû¯´ùÖṌŸêsí¯#èùVž«áxåÛ-â;^WÈ\OÌɱonn0¾d=äª\ÝT”‚lˆ{ó€¼0ÚT¹WWojò$ ð\{–l lbÕ¹.¶*qeÝKž„‰×ñÒáÊY²Ñ˜×Ó{Šyq—KΈÚ{ÈhzªX¯üPy8Å:F—« »òúh9ÔNþnï5ùÒ*¹Ä€+“,¯ñª è¨Wo'ÍéŧñýGH©\SßËy°†ÇeŽæãvQ°2Ÿ,’+çEQÁse¼(*t.a#‡s5–r*W͍çª>š^¸ +vt6מ͕4™¿peM/\œ¥ùp‰'óg®úÃÉ<–k2ߝÎ-‡͋ó·•Ü:\[æ»uîªßFwÒ²ßmµwpœOm›.Ò,²Î-ï\·u›þà,•\×FÍÕI¿\¹r¶ûRãkT§×ćk¥äjÔûËÛ}©4fÜkbÄኔ\¹z߁¿h£¶W]nj¯‰;×NÁU UPn9Ár­4áËNŕr¸RW6|ŒŽ¹Î«Ëë51áp%C®wшﲫÝÊ-§h®š+Vqõó¡¸g¯r~ô'/ÙÅlp\ëQ®Ó¿^òHjÁZv,¥Šk£tEr<Џ¨ëdÞ7ÛnlÌ\—᯻?"éx@·‰+×à¢Zr—Ûj{‡àꤥÈ]|Ëíé71âp .’7.y<€ +£®[‘"K~­lâŽÃÕ¿(—óM +-áðì8—Ðpz®”ÃÕ¿¨7RNf™*Œj1\·Ùÿj®˜ÃÕ»¨ðTà¹b\Šã|f.ÅEußÁnßÊ#`ÂÃĞk¨Šã|f.ÝÀT5_ŽÜp ×^­óŠã|®áE…ÒÁ&ŒJ[=Ì®9·r‡Çù\Ër¥#Bq­Q\µÚ՚8JqœÁ5¼HËU;â*”ñÆË- é5qxœÁ5¼(S:"×Ã%¢"ÎSÇù0\ƒ‹´\?Œê´áò;ô¼RqœÃ5¸¨[ývGסµœm”MçÃp .Òr?ŒjÕ£YU4ñ"Ú4®þE\-š+Uý6.5MìçCqõ/Òr¹ê^,ÕMìçCqõ/Òríùáa«68Íòþ ‰ýã|(®þEY/Mõʕ;ãŠK W'T•šØ;·ãê]ÄçJ\ñ®óۋ_¾,{lÔMìçÃqõ.Ê;Š-qen¸:ù‡Ýxã¼ì‘ª›Ø;·ãê]4ˆ£*,WÚâæ)­Š«ó~(EO¢Må’/Ú÷#¢âÂùåªÇ¸äã|H.ÅÀn÷X®µW£‹ç¯AeNä’/ªúC%;s Ï\BsŠCqœÉ%_T÷$[DX®W;Ê.é"Ñ Í« ¸—|Q&°üÂeÎ=Üy䒎óa¹ä‹ +E2þW=/WÁá’.ªn»Ê·EÞÙ¹j—t‘è¶²¾Æ6ÓJ\‚Ã%_”ßö¿ž#W铫{œÍ%_T ö+Càª8\òE½H0?qÙL—Q\Ù8WÃá’/’gÆé>®Îq>ès¥”ºór=ŸÞa?bšK©;3×Cÿøšü²¡ÎæuÕ»ꝪHqPJÛ:k®|¾!çéw·§†u\y1Ô׏áŒF~™WsÛìø9QeäÚÉÔ—Pì(É/4¬®KüuòÈȵ™‚ TSë¼;Àz齺 ®u+ M?\™j« ºã “Òdúu\©l)^¸š÷§»nÝî«ko»õʺ ®Dºµ®êºQ(¾unڑÀ[v…².Ÿ«öÉUtv¬÷7ïÒqY·äsM]Õ2¿ú®òöNå“+ª›v^Ȭ©K㊯ۧoƒ8ñƕu—áòžÒߌ§©KãJ®£0qÙÄóҟá¦×VËIÚªº$®Õõq¼=™t®êöÓ5ä$mU]WÚ}tk;.CúáõÏÍÝ[ÙtĪ윑Ò×%qÏ]ÓÆ+W¢ûѧ“T<¶ÔçÊ/ƒô8„wÞ¸2]:ÎeO¹éÀd#©;x®ýåóŽŸ|ðÆuŽš¸1‘†‘¶.‰«¸ÈÐÑÒKo\—½Îûƒ:À:eR¼Ë¹¶.‰ nÙ¯qëë¢Z{þ⇬ã‹õu•\ÃÄÎEu¯G÷叫“Òkmñîm®¾X_—ÂU_ `ü`;®±}½n=é½ÄÕ0‹V[—ÂÕ\~<ºeK®±}ØByŽCš—ƺ.]_ˆ¾ç²Ú_ÚÌÒ|Õ¢¯Kàj/Žùô[\½,Ú¸ôdЍKá:;æ“[öÉÕyіL¡ú’9]] +×Ù1×'ï“ëý ì —J•l:ZÇuvÌõ©¾—1ïë9Sš\ùPÔuñ~ùäËãÿc—‹|¶—‡á¤¦ÒLrTu \ÕÉOnÙ?×­µ«^(u@Õ%póÉ-OÁõ. +‰vЌÕ%póÉ-[raß-Z‹ÁX]—x÷b멸n‰×f®^]×Ù1ŸEr”Ë&ûø*™ìе\cu)\o&˜4·õS/\²{ãb§®.…ëM2âúì-¹JÜú¡k¬.…ëØÓUt}Q7®D²­x”KW—Âçð±‰ËæÜM.ý9Õù±º®ê|²&±çڍO¿6ÝyÈJË5V—ÂUߜº7®ªÛŸûÞmz«Kájn³Q.›sˆçkãï·M­–k¬®!ž—Þ¶%ä]A ®qö¶ ©Ÿ,ŽÕ¥puÞ ë«™«õ¹F꒸r—Õ¹ìf¤jŸk¤.ƒ«´çZãÒmú¡ÿ VÑ×%qƒßxàjô +3àj¸ëQ2\ŸÊ(—Õû7䵘_ÚQ.}]—îý¬n¹:}l \Úº$®úêÓǹ¬²Þè!Ón”ØÔµ*–ïí¹Ê×ëMóU|–ïY +¶X¾ë“kz.ó떗ÉUüÓr•‹ä2/pÉe3aþ䚞Ëjb¹h®õ"¹Ä?-WºH.ólõA¹’ere0ðµü>ŽO®¸ö0ðÅ}Ïn‘\ðA¹ª Z~¯Ù\Åô²×å÷ÐÍULMÞá¾70¸@ªrÃ\ e’ºÒò{9ç*Š+[\Àa +%°ß{ZÀ‘›ì ù=Å¡­´e&=@~¯thG„â‚¥Âèo‘ßoXÀQã¸÷}ô•±mç˜Á8lc®Á9æ½Qæ#/Á9°Üè–ã‚s`™±Åš3‡}€²×ÀXcV@éK`3Ëڬހò9°ÊÜX@=€ÀXa6.@l`3°½9êT˜ËÍ"8á Kèmœ£ Jè„m®gƒú¡€S˜ „A:àª%ô¢©€ìڐ„>G˜ ‡bH}fv_ï\bAB/0Ò -Vè׋‘Ã]‡+_Ž V˜Ȑ+ A,0 +-V裥ÈaÜ媗#ˆ(Â-ôDˆ *âƒ-ôéBäpÝåB} Â(»‚-ôÇ¥€VÏP„#C̾:\ÕB")£œ· Å }ºÙHd.„Ð'‹TæB,Ýċu+_†pd8üƒ"âȇxà B8j¤—Â!Gl#´A `1Û¨«>BðÌØå +h)‚¸xí\Åú,(ÖCéÑg­¡% ÇÜ ýŽhIÂ1ó3?ú•‚+~€áï€d¼s°=z @KŽy>r’s˜y€Õø©bå™a÷H*:sˆH؇–(30Ê&ÐúyÖ9eˆιÈQDs‘ƒ²Ôā9£Ò7”AОQéI+Ò@½t>¥Ï)Mª’ζÚ&HšÔ¡9›!"li¥åڇkˆ´åhél¨vc! »ô™ ±¢g83âžö¼nų¢ †®@žâÌcˆñqCË`3Ĉ9qx@Ë`iˆf(Í4€ó`¦Ÿ¬Tԇ -g€M>kΩj-k€MœdY“½´¬6± +ÈcX]>±rz‹€5D'VFÔ +œéöÔ1GNÀY™8樼A:©ÔgB©œÇ Üϙ.H,8ޏÃtºc wàÊêd†kÍÁ…Tú‰:,c=càÔ4Æ €?R§é°ŒÖÛNÓaә_‚& :C¢Åqí±`»0ºk…äªé0‘qƒph­ ±÷UKó„ªY.´v†èuâ,øV­!zÕzìÓÝ ¹ð†èQ:j ›ÖÖãrfWŠØ ¬OKüñÍPË%¢¹-±±’.h­ ѓ&æV>¬­'BõÊXZ?Þ¹±´°öõ^†˜È,e \<1÷3–½í#×½{&ܸ¥rU¤s©ÍJÉ\"š LdöܹK0‘;¸)82‡i\o\´;¼•Ÿ'–‘P¬.t¬Â^¿¹1p1_uFÃÒÇàd}¡ãNSbé¥ +\EiW°/)áøf08Ô&[õ cœFwžÿf<[l2êR6W›qÀúßtŽ*OôÛø\‹+Š¿S;‹añcq€‰‹ÙaQt_zî¬ñ¹‘‘«ˆ¸ÿ¥ó/9k·6\"â—{”56¼OßYqYtØqœ=šÌñ…Ie˜>˜¹l:ìŒöªÿ짌ý¹K.ê4Li¯ƒ~/ÛÌæqµ¶\Mä¦ÜÝo·Û/¯oåe»}È,?mcÍå¢ÃœSþ#†KȵqÀe'‰³tŽ+¼Û9á +®ÃÌK_8.±´îBrvm¦(ˆ=$W›…ÄupÇU/«»Ð\¬•O_ºäj‚áÚ´.¹‚ÑzÜöžKdKÑxw gÑ q!Øý^ +—XŒÒ¸°DôÖ!‰kvKÄgиš…X!•kæø—°MäšÕ)¹/T®9½3eû‰Ê5c`OJš#sÍ6Ähi/t®™†1±ŒÁ5Ï#îí2¸fbÔ,%=pÍ`sM®ôT9×ÄÚÁÈdr‰<\)´ášRY©Ã\®éÀx™dl.FÚÏ$ŽËšk¢Éóā×þ9椰áòoŠü,M+.ß`ɧv\~UÑ&Yؒ˧ƒ¶Ê¶åòf—ŒoÍEΡö41qÏåcÚb™®î†Ë½,ڟ›pÂÕ +·¶øhß"7\o¶è®Ë’CW+Âé,—\ŽºìþІÆÕŠ'küâª-.¹ø©ÕªGw-qËe‘^Hݞ“‹Kæ–ʇìþ‹ë6øà"æÅÇ[ï¹ðÃõV^qÙññýw/·÷Æuê5ƒAÞm_}ÝÛ'ש۞¶wê~z|õy_ß\çŽ;žpØ>ÜËývûøúêý–“pÍPàÿÿÿârõä +äÿÿMŽÍ‚0„ï<Å5±+m ¸G5x#A(ÐØâOˆ˜4¼½ÔÄèe3óMf§¢õ@Ä Zà±@I¸eû¦¬¡îÛᥝ…Æ[ç¡Ð÷QwKu›©8e˜ãŗbuS0Ž1ÊÐdr‘bò\ûé·ZºÞŒ§Áz‰Äôo¨Lîz¾ À‰26 ­`ÛuPÓCeçGOkš«è½ZÝïendstream +endobj +99 0 obj +6278 +endobj +100 0 obj<>>>endobj +101 0 obj<>stream +xÚ+ä2T0BCc3JÎår +ár á +äHÉHendstream +endobj +102 0 obj +31 +endobj +103 0 obj<>>>>>endobj +104 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 +105 0 obj +689 +endobj +106 0 obj<>>>>>endobj +107 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 +108 0 obj +288 +endobj +109 0 obj<>>>>>endobj +110 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 +113 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 +114 0 obj +1356 +endobj +115 0 obj<>>>>>endobj +116 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 +117 0 obj +815 +endobj +118 0 obj<>>>>>endobj +119 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 +120 0 obj +116 +endobj +121 0 obj<>>>>>endobj +122 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 11 0 R>>endobj +125 0 obj<>stream +xڝVÛnã6}÷W ²(+U’eË)‡®‘mº­wíýZ¢-¥©’T ÿ}g(Qõ%¾´HàDòÌè̙3Gü{C„?1Œ§ô›×£O«ÑOŸ#x‚Õ†îLgY˜ÀªxüDc,³4ðòÇêåۏ«W N!Ž):À𠙆)…¯JA󪱕’`žW›Š°%Ù«vLZ° + çÀ@TƂÚ@£+i¹6Éƒ©L1”ѼQÚw?oµæXÂìå5a‰ ˆÇ܂oX+¬/JC.˜1a7àT]aeîÓ>Bkø ¥[]÷Qßý£hŽéx„\Õ56ñ³ôœIê%*=ÄM%¸d5¿É-öÒAZ܄¤ÿ& Áâ*¨'ˆ³T…3Ê\rk+¹…EŸø§fŽŸ@ügì‘ìÁîTNž…c§>Φ×Ä=¬9˜vƒCªhø,ƒbÒ 9/L¿©£ÁaÍû„mتÆ'îJ.)“ÌK&·Ý´ýó¨:ƒ†i[å­`.‰aq‡{>ÓÔ0!Ô蚈¡A‰žuÝ"¶¹ò#¿®*‹›œ5œ.ð5ž³ ]Õ¼¨Øó/é0ÜðµÙÞØå»•%3 •¿ ð¹žOGçIsŽ»—Õ( +#4"úˆéãÛ¯Ž“L)Á¡Õfþí®,ɦ"¼ì'JÙ«[ ~ÆßÓ{”TÃeADÒº”CT”ŒÎ& ¦‹!‡æ[p“ëjê¨$\Æy€ŒpNÂìçqŠÞ­õèç%kïØéhˆŽúèÇðdíºôaó½ á ®LÕ sÕ Ó^\½Oʖ÷9ÍóîÉýÛñîø ZiÚ,&‘}tnÕìiã™Sàu%Km䮣w܈ֺç¡÷®Wã/H¼cÌM]*]ãRîûƧ¾M©ìyãB0‹úè]µ¤`Ëí¿_ô8ü[änWØUýˆpãOÜkÞÕ~^é–ßgGâþV¸ßàç%ÏÿòFä]~‰'‚yÖªv÷çýÖÿŽ[Qïú -.±‘£nÐö‘ÅÞ¨‰ãüU­N~¦]וõCñ¼F;Õ¼'¨¾É Æç”²PÒ4ɲlz!.ââI6»5¢ÆY2K“ÆëZ$]Ò©³"÷†Òwǀ=jE¢§3´Â‰ÎT»²ÊËî­êٟ¬\5–Ûꍞoš‡¡IkÖ㋧OáO…t Å÷Å–jcwTô»¡ò_˜l™ ´ ‹²$¢àÝgÓp э#:í×Ñ?°D @endstream +endobj +126 0 obj +965 +endobj +127 0 obj<>>>/Annots 14 0 R>>endobj +128 0 obj<>stream +xÚ¥S]o›0}ϯ¸‹4)“Á„ÉãºvZµnYCµgCœB¾Ì6úïç’ŒN1y¸c +8ÁîUüé´éßÜZÜF@ˆiàé^û‘©ð]€B¥¾¨JϘK |g}u9‡N2»3õpj§^;lU…\®]ù }/Œ†äqŒÿÆuðˆn\ò2ˆ¢0I’xžqä*IÇPË3j™„iþh+ ÉY´¨¯p]²â`ÐF“¾+lõS; {ÝÿÉò¡îÁEõmÅ ׏›­‘VZüS…k>›—@…Ös¨TڗZ"PØwuíí™î&ØŽ,ÉÄ >dhzÅN˜}Óþ&›~ ãf~Äü>C˜WÑlíXâ_õ«¶&Œ^†Žj.ð¨ë›”4È+…b @îúÉW©X3ס`Ü"¾ÂÔJ?ì/ž`V*Õ®‹ Z—(Õ:^’!48A§>Üö’ +û4((?9ºtcòR1_é<À=5•ZÙ¹MôÜföLùX©Ò‹º*M!ï”Bþnhzð‡åT;VW¨3îpÜßL?M…;œ¶ÀðÆ +lÃ͝j‹KÃz|¬Ø`¼jw™«‘ ¿p‰OmÝÍ·\L€wMnÜ.õÜ©ÁZJçLûoÄÏ_­roW·o‹é˜ü…1îŒ ûqKû¯t&—QêÞ`'e‹{u¤:Ò¸xOyG­ žC{IüëtFi 'Á^[õãòcò)éŸRendstream +endobj +129 0 obj +634 +endobj +130 0 obj<>>>>>endobj +131 0 obj<>stream +xÚ-‹±‚0E÷÷wÔíCE\5º™`(q®Ø +*%¶%þ¾V̽ÓÉ9/bˆï‹,¾îh+i~ÈÁ iÀÙf¶Â:×É®*J”½ oå4*¯ÇQÙA=§òNÉè&™E„i¾ÄØ6º~´ö†Ðh®µA;”A…Áø¾ûñ³¾Äh/éDÓÙ*Sendstream +endobj +132 0 obj +133 +endobj +133 0 obj<>>>>>endobj +134 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 +135 0 obj +638 +endobj +136 0 obj<>>>>>endobj +137 0 obj<>stream +xڝVßoâ8~ç¯UZ]WJr$pPNêõەVÚv¹…¾õÅ$¼ +¶×vÊrýÍØ  ‚­€Æóó›oÿì¤ÐÅW +½½óUçnÚùósi +Ó9d7Iƒ›~rÓâú% áãô*tk…ëg­¹ ²~#ƒ¼4£§3l4·]ˆÓz~ÃçWµ>åӋßëó±*WF+ˏ]ûÓX‡ãw§Í̂ß3Írá6'Ò§cÈëóƒ ±G:ÎIŸÜO—Xî*V‚ÒN(iÁVZ+ãxÌp(ø\Hü.$8ÔÕFHÇÍÆãO0%oNr³Ÿˆÿ!ˆõ¾H]¹I©Ü‘"“E[w•G^6Ýè#„ë"’ AÚ¯-{½d@– Ÿò7#¸tŒ,Ú~ºm€®b%¦cS~Uǀµ(K0 +íy€+†Q[Î-8Ð"€¶Ö v1ÿnÊQLŠ8ó!?@©a?¤ÇY²‡‡§éÃ÷vm16Ս) •÷MrK˜ˆSQsŸá˜Ð‰J-™ÜºµŠé[Û%²!æÅKnjNê”J.j•†FÌz†)*]ò_˜ßk£j‘ +^®Å¼%¨©hA¸äå#ø Û¶Cs…óñæÊì¡G±¬—ˆâA®í‘ÊxÓ!eb˜pÁ߹潍â‰nRFݰúÞ²ß"|9&¼ä¹gƒïL¢)ò€æÒžå•²±·¾Ü-*Ö;µèÒ4.½B€¨¦ß9pöݧ—áÑ2‰ûï2ІÑ(N³“6`x8þA +,ÕZ›©Wíí¹A³qô1ž×ðÊʊ6°„®Wì¥\”‡Ñp®æªôÝBˆëÕjƍmámCIØ Í £M=Û ƒÕŠÙÄI舟@V®ÙÆRa¨ü&g6ç² f(Spá fŠ’Ûí®ðøãÄÀïõÚ¿ÚaÜp$©m¶¤R5k¼å’JVEÑPÙ°A·Ì³ÜÝâ§qxÈ†|^N ²ðÙ\>>>>>endobj +140 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 +141 0 obj +666 +endobj +142 0 obj<>>>>>endobj +143 0 obj<>stream +xڕWßOã8~篭t:Вl’¦¿î´,âönº'ñb—œ8k;”Þ_3vÒ6–¬(­ê|žù¾oƓôÇQ þÅ0Ñkž}™}ú#…8†Ù¯Œ&i8Yv<[r8™=âÅQ}ñø™ÉŠûµfÃ10ýPå¼° Xܓã‚(_¥…5¿gó¥ÿB˜øÓ8Á«¸¤4Dá`˜ç¡9…8õ$‚Á ‰kÍ­]õÆÍ¢xhçF\2 +ӆì‡@Aéð%Á?€*­PH£²,9˸fK«JP‹š{à°v鮸oE•ßs} +ê¬°’ÃÝqe*&åš@ijǃ0¡ì !yÁr~wr +¬È\˜ŒY™4êÎÝêùǏðÄ×+¥3ä£9,ÅÃRâ¿å™ß7W¹sRŠ‚{ˆ°Lйøg¿yíLI:–.Hœò_@–ÐV ¸ø{vq³1wL;ښF¾Æ—9‰½r>™ƒæ.””j…%¨]Eze‰f¬–®ËÂÅ£ôfMoç¨ Áä’#ðnUßñ¹äzΩ²d–+w)>»¦ü°¡5_²9Ppƒ¾Q‘™'È3Ïï=';ÙÞp“J_;¸±¿aò¦ù6gþ®º:W÷ Õ©»GMPûք…V9c«`E`J>‹uc«SŽ'PsÉÜ@ئ·ïŽ;Ù +õ*YáÝ œuÚ½!ÖƘ»ñi%¤$õr›ŠêéRr˱W˜ÙÆÅ/Hق&~À¨¹ ؉DQ'q+“ouÔV•$/u}ÛuZkÓk’½moœ¼öWs£dåœE¢[Q4ôÄ —†LqC5þbG‹]27Q½$)ùèw£—‰‹BÓÀ´þ¦þÂÈä.=ÏV`Ão‰vÒçì‰ï–CâÔÆ˜ÈªØ”ïòJZ‘½·žÚ=ß'tÇ`ýÌb]»ò£âÆî?ùgÙcelcâŸõâ CaÑ1-zŽƒeÅÛ§Þc.º ˆ¦0­£OŠpàKñä'„%—窰ZIj¥µªt·N\òga0Ë{scCëçFÀÏÞcÛ-Šá"ª}ÐTÔo¡¾¸s%±?È­¬!´Ç¹e÷²Û›¦Êñ.Ž3¤âG*šó+Úlx}³ÌÄbÁ5wbSû3¬YǃEÉØK½Ò ˜$Ð8 XX\%ςtH‹Ótwѯ]̎¢»~ûvódŒ³7N§ø>ŠÃÒÆ›åí[àINk0>Ù¤ÁÉhŒ­ƒûzu«fیtŒ¦˜ª§‡í©Ãa÷éÖ¿4¾ád.,k‹¹,2ñ ÚRεȍz¯ÍÒIÿÁà°=µ8ì>-ƒÔςó5ëœöñ؊ù‹žüƒ‚=o‹v@T2é?¶§(‡}kÖMšY‡%Â8ñø~} ·jaWôãä»áÚÀ7VT~¬Ôà8¥Å4#¥hϏ9TüÏÑÿ»Úû×endstream +endobj +144 0 obj +1228 +endobj +145 0 obj<>>>>>endobj +146 0 obj<>stream +xڝ’ÍnÛ0„ïzŠA€©¢¬Èv’ÀrH‘ÖÊ-Z^ٌ)R%)»yû’;?§‚'rw¿ÙðoĐúÃ0É0.P5ÑM}ÿ9ËQÖ¾RLY’¡\®WϝuB­á6„wáNh…§Ñ­–Ú<C×à +w _Óyùì190qV$yÀ”~ø,Ö°o€«–LEʝA·=÷J¶×9¶zx©‚˜…PAK­ 4]µ[:v`«ô2láµÙx°à!/º3p$i'¬‡þöL1 kúâ¬ßòd‹/·D-$)Þæ¿ÊùŸ÷>ãžpât(‡òèÀx?47ë® lÛR%jAöÄÇIµÑÏÒidišàús‡Y·F¯ºÊCøÿKÉ«mÌÕ*Þo„#ß(”»€¿HǎˎÂÓ±R¢á§‘ZÐ?g¨!ùâãw¤,%ƒ•éÁ ++fÉ¥ÿ:½Úíãà ]»=7„GKpÏUÇeЇÞx’¥ÿ÷»òIžLѳËð0/£ßÑ+IÚÞsendstream +endobj +147 0 obj +391 +endobj +148 0 obj<>>>>>endobj +149 0 obj<>stream +xÚ-‹±‚0E÷~ÅaiUÐQ‰&&ÊÆò!ÐÆÒÆßWÔÜ3œûdÉgët¡žØQ²ÕyÎ![ðto‘‰² òòV 0­{‘U(geg\I{C9°è×Fÿ˜§‹™ˆ7øŠC3øÙõºƒ{(ä¼%׍*ÈÍhl´ ËDZÎ'Éîì (,ƒendstream +endobj +150 0 obj +143 +endobj +151 0 obj<>>>/Annots 53 0 R>>endobj +152 0 obj<>stream +xÚ͛Ýs¹ ÀßýWìãÝL­,¹ß¯I{Ó|ô¬L_ò²–×¶î´Zw%%Mÿú¸ ®mr=s¶”Ì8fü,‚ ~ø?g*Šá¯Š +%y´jÏÞ.ÏÞ¼«"G˛HeÕBEy‘FË럖õÕ¦‰º›è¢Ûî›í~÷óò÷³¿-ÏâE ü¢ðËoï±åI¶(£6‚Rnl¢KÄOäûÛèÍ»,R + êå +?îsßÜÔ«H’,4tÁ.NþzÒ*00žÖ‹ÌR(4¬i°YÞ¼KÙ0¹N |ùc·oÚèI¨à´ ž.2—ÊýLûô­é¿­›ïˆKÕ¢:!£†ìWàGmT¦0jðÑZ*^ý¥[Zpͧí%ôÁ^º84ê·<Ç^úTœP{^V&ð,—¾l\eYiƧ<†ÔÁNÅ"qYÔkçO3„^™Pâ@¸;¥Õ¾Þî×ÛÛ§aB¿ª ݁qw:gÑm\/ +—Åý] ;º$þe’啉ºYŽMÇÂKVÄd—wÇâ#,ž¢}%‘º-)<‚VON¾äQÿÈë Ý´&üc +9…•2~–›0L†11FeYA1x†É™£âߢšÕݶÛt·?˜)øßSʒiÀ\ib¢0Œ)ç†0WšRþµ»2…†ªN¿ 8‰a mNobÀ° 4ïbSïv͎êžqh°Ý1¼æfU›†¬2küÝz³oz3TÈÄÙIOoh¸qbâZ^b21 1Ü8A²éŸ^ÿB׿šÂ¸Ÿq¿ôëol?ð¦üÔì—ùM–V± se SOÑdi¥(Æ}löß»þÈ,&Æéӌ™·$Kah.ÉèûGJ²4Ï(hQfa¦zrhÔ˔PYf1iÅÁp7s¾ì¼I]¨›µ>ùHÜͬ½/õ etý|j+îgT¸Ü¬7°ÒpÇÉL¤¢Ñ¬¥“H¤E`õ@º7e~UziFƒ;\µë½ß`‚„[I…ö’\î×¹›ÇöB›¶Y©Ë²vÓy"¢TT®§Ë +8nÁe£:Ú4†f/)Lˆ/c\¦!b_RR|¿¸ë:ÿòú&æ.Œ»W{8£*ν‰ÈˆúK'™¼]Ð)BÈè:5 'ÇÏL atñ‰KX'B¶80îg\0åKÆ),„ž`à§ûýºÛRÒ×'±1*f‡µŽu~±—ÂìJ/f}:ê*]÷3ïÃa³_ßo_x €»Lh˜xÑݯ©.×åñí0zR•Tr` Æhô¤ªx¯q׬þ « +ˆ¨Œ»«ù](cJÀtì ¸¿ùÝ»l¡5թ˳ ¼Ü×ûƒ/e ðJ<1uy,À¼›¾óœ0I} UFkæXNª·‘.ô0¿V9C½èÚ¶Þ^Ÿÿs½5ÇçEüç;kÈýʌªã¦!ܯ̟ã|Œ"ÿ(îÎgºsØ/$ˆûóç8ž¥‘WHšȟáv–F^áÐX Ÿít–U=§È纣´Ž!)¹¨J òß͕ ‹ñëìᫀïŠÊ!ÙÂÌvÖ¡Q/SBûd‹cìb¸›9°Ð·×uíÝàŽCij /OGڌªQITæ“A‚Àˆ“5#^¯ÙTà²/I´Iu… W¦ñØÞ61÷Â0’÷Ͷé덧tAöXÝÁr?㤵’Óº$}ÚpT¨ŠwïìÕ©e‡>¯cÚàlšUàìDèÓ]MåÒX€€þL"”iÿ>ù`,@¨ÍõÚI¥:fËW²#èúÍ_|érT‡#J&0 Øòǽ&ÕfüƁ±Á TxPBP9Þé»(àAv‡ž_Iċ¸/º\œña5^MQK¸\̯9‚»j©EšÆ4&iV€~§ê˜p©»0`ا~Ýl¡RƒeoîyËã*í·µ®ì;¼;¢Öhk]%âÈ!°¾Gӄƒ³öÝÈÖgëQëa,] 0ëm·¿óÕã>ÎVæ.ìû˜õµ÷ R0`Tƒ‡$NŒën|ñ¢s ãl: 0’¼þ)•1ZàÊuPVÀÎh}ÏÇmÉâ¥ïƒNXð㓨%œ°ä§3³³ÌÀ3csx,`‘¾Ä ”Ñ ñ(ÈE‘€EýVoo}ñC0iåè#Ž,Îë6BweX¬»,°¬Ïõ-Ÿ2½víœù<çJ£-MKÌ|^Pùôñü˽ÿ¸3QæÙAYbñ؉þÑ·1A#eü¬È¤+j #eé3²áÀ2ÙÊaYtf.P9¹(0¨·ýúön¿mv;zðt¤òW%+'•¨:¨%¬œÆÏª:YBÒXÀçXÚ² +ƒ—# {_·mí?*œ†ZeŠ#‹»èúC.×0¯·ÏSwQZó»¨M©ÝwQZ™þë9øºmTá‹ÄÝÅÃ+’ôøÛÝg;·JøŒÀøžJÜ «Òų‚ˆ¥‘óIš`àç¶°<ž~4+À°‡öÊ{€!T¢— ¤3R¬ÐÆÓJ,¤\ 0ëâ®îë>=ò”h‚ÒšE»L+ÀÌϾÁJu€Áº|@QÿØ®îÌ©>öyß ú_sž7îÇnžù¡Ú\ÿ³4òI³jÎ%ˆPüρ±ÃfúŸå‘ƒ8<`Þ ÿcþOX,À,¼˜ñ¹žàÁ¾oppÐa~ÇʸÑ(¦ŸÌ +0lp½êe÷!Ä£—±Š¢Ö肪|NvXÆA–˜›Û”ñ Åå|çhÆ;\ ”ó\ϒ´Â˜ä’X€K„Í¡åÄøZïiƒS]$¢”£–˜ê"}V)7Ðh:$Í +¤³K¹ÅT2±€}ØY{·“)îoZ©§µLûP÷·kž¦ìõßÅg,ùí‹ZbÆre¡`Ê~„®0”Š™ Ã+ AûÀã_f©À{`•tmd&Ö4ƚW¥%gúÖë7B™¬­\÷—/yNìá¸ÇZäQ‰}ö‰ÇÔ•Ø'š«zˆ£>(U.Í +d³*ŽQ·sø2ȅ±ÃÌdšƒ›#ï9‚ÖÖög‰¥•›\µÍ_¯?ìBçw£~kL“¸4+0ÃÖBm=.Š êïïÙݨL/*Ê Š êëOKˆ+_ö¿ª(G^…G’.Âe¢ÐÅ2÷¬.‰4Ýù*ÄQ˺|j.+0q̗~ô¼x|aª¸%·Ñ‚Ie¶Ëdf~Åâ¬ë}ž(!¸Í­¦H+ÀHŸ/JmÜÞjL¾‹ìÛaŸ7 +m|Ÿ3=ìnI€Y£?þ.C™_Å?d<üŽyÉ/ΕÙåÊþÂ՗ϗÑew³ÿ^÷Môe‡Çêí¡ÞÐ/dÑyAw­k6Á¿Îþ<ì/endstream +endobj +153 0 obj +2691 +endobj +154 0 obj<>>>>>endobj +155 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS04³Ô3U072PIÑp VÎO+)O,JU-N-*VðMÌ+MÌÑ Éâ҅¨Õ…*ÎÌ º†prÇvMendstream +endobj +156 0 obj +94 +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<>1<>2<>4<>]>>>>endobj +xref +0 198 +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 +0000002428 00000 n +0000002479 00000 n +0000002564 00000 n +0000002588 00000 n +0000002692 00000 n +0000002797 00000 n +0000002902 00000 n +0000003006 00000 n +0000003111 00000 n +0000003216 00000 n +0000003321 00000 n +0000003426 00000 n +0000003531 00000 n +0000003636 00000 n +0000003741 00000 n +0000003845 00000 n +0000003950 00000 n +0000004055 00000 n +0000004160 00000 n +0000004265 00000 n +0000004370 00000 n +0000004475 00000 n +0000004580 00000 n +0000004684 00000 n +0000004789 00000 n +0000004894 00000 n +0000004999 00000 n +0000005104 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 +0000006857 00000 n +0000006889 00000 n +0000006921 00000 n +0000007428 00000 n +0000007476 00000 n +0000007524 00000 n +0000007572 00000 n +0000007620 00000 n +0000007668 00000 n +0000007716 00000 n +0000007764 00000 n +0000007812 00000 n +0000007860 00000 n +0000007908 00000 n +0000007956 00000 n +0000008004 00000 n +0000008052 00000 n +0000008100 00000 n +0000008148 00000 n +0000008196 00000 n +0000008244 00000 n +0000008292 00000 n +0000008340 00000 n +0000008388 00000 n +0000008436 00000 n +0000008484 00000 n +0000008532 00000 n +0000008580 00000 n +0000008628 00000 n +0000008676 00000 n +0000008724 00000 n +0000008772 00000 n +0000008820 00000 n +0000008868 00000 n +0000008916 00000 n +0000008964 00000 n +0000009012 00000 n +0000009060 00000 n +0000009108 00000 n +0000009156 00000 n +0000009204 00000 n +0000009252 00000 n +0000009300 00000 n +0000009527 00000 n +0000009676 00000 n +0000016023 00000 n +0000016044 00000 n +0000016138 00000 n +0000016240 00000 n +0000016260 00000 n +0000016390 00000 n +0000017150 00000 n +0000017171 00000 n +0000017310 00000 n +0000017669 00000 n +0000017690 00000 n +0000017829 00000 n +0000018747 00000 n +0000018768 00000 n +0000018907 00000 n +0000020334 00000 n +0000020356 00000 n +0000020495 00000 n +0000021381 00000 n +0000021402 00000 n +0000021514 00000 n +0000021701 00000 n +0000021722 00000 n +0000021861 00000 n +0000022569 00000 n +0000022590 00000 n +0000022752 00000 n +0000023788 00000 n +0000023809 00000 n +0000023971 00000 n +0000024676 00000 n +0000024697 00000 n +0000024809 00000 n +0000025013 00000 n +0000025034 00000 n +0000025182 00000 n +0000025891 00000 n +0000025912 00000 n +0000026069 00000 n +0000027065 00000 n +0000027086 00000 n +0000027225 00000 n +0000027962 00000 n +0000027983 00000 n +0000028140 00000 n +0000029439 00000 n +0000029461 00000 n +0000029609 00000 n +0000030071 00000 n +0000030092 00000 n +0000030204 00000 n +0000030418 00000 n +0000030439 00000 n +0000030592 00000 n +0000033354 00000 n +0000033376 00000 n +0000033488 00000 n +0000033653 00000 n +0000033673 00000 n +0000033728 00000 n +0000033833 00000 n +0000033977 00000 n +0000034080 00000 n +0000034185 00000 n +0000034350 00000 n +0000034458 00000 n +0000034573 00000 n +0000034678 00000 n +0000034786 00000 n +0000034894 00000 n +0000035010 00000 n +0000035108 00000 n +0000035274 00000 n +0000035391 00000 n +0000035510 00000 n +0000035634 00000 n +0000035759 00000 n +0000035909 00000 n +0000036050 00000 n +0000036159 00000 n +0000036311 00000 n +0000036450 00000 n +0000036580 00000 n +0000036704 00000 n +0000036840 00000 n +0000036967 00000 n +0000037081 00000 n +0000037204 00000 n +0000037320 00000 n +0000037469 00000 n +0000037598 00000 n +0000037735 00000 n +0000037865 00000 n +0000037990 00000 n +0000038093 00000 n +0000038230 00000 n +0000038335 00000 n +0000038474 00000 n +0000038608 00000 n +trailer +<> +startxref +38834 +%%EOF diff --git a/doc/sum.shtml b/doc/sum.shtml new file mode 100644 index 0000000000..051339d09a --- /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.1. + +

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/svd.shtml b/doc/svd.shtml new file mode 100644 index 0000000000..51830cd06f --- /dev/null +++ b/doc/svd.shtml @@ -0,0 +1,165 @@ + + + + + + CUPS Software Version Description + + + +

Scope

+ +

Identification

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

System Overview

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

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

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

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

Document Overview

+ +

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

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

References

+ +

CUPS Documentation

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

Other Documents

+ +The following non-CUPS documents are referenced by this document: + +
    +
  • IPP/1.1: Encoding and Transport +
  • IPP/1.1: Implementers Guide +
  • IPP/1.1: Model and Semantics +
  • RFC 1179, Line Printer Daemon Protocol +
+ +

Additions

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

Changes

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

Glossary

+ +

Terms

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

Acronyms

+ +
+ +
ASCII +
American Standard Code for Information Interchange + +
CUPS +
Common UNIX Printing System + +
ESC/P +
EPSON Standard Code for Printers + +
FTP +
File Transfer Protocol + +
HP-GL +
Hewlett-Packard Graphics Language + +
HP-PCL +
Hewlett-Packard Printer Control Language + +
HP-PJL +
Hewlett-Packard Printer Job Language + +
IETF +
Internet Engineering Task Force + +
IPP +
Internet Printing Protocol + +
ISO +
International Standards Organization + +
LPD +
Line Printer Daemon + +
MIME +
Multimedia Internet Mail Exchange + +
PCL +
Page Control Language + +
PPD +
PostScript Printer Description + +
SMB +
Server Message Block + +
TFTP +
Trivial File Transfer Protocol + +
+ + + diff --git a/filter/Makefile b/filter/Makefile new file mode 100644 index 0000000000..a23e670b0f --- /dev/null +++ b/filter/Makefile @@ -0,0 +1,190 @@ +# +# "$Id$" +# +# Filter makefile for the Common UNIX Printing System (CUPS). +# +# Copyright 1997-2000 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 \ + rastertoepson 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 +FORMOBJS = form-attr.o form-main.o form-ps.o form-text.o form-tree.o +OBJS = $(HPGLOBJS) $(IMAGEOBJS) $(FORMOBJS) \ + imagetops.o imagetoraster.o common.o pstops.o raster.o \ + rastertoepson.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) $(SERVERBIN)/filter + $(CP) $(TARGETS) $(SERVERBIN)/filter + -$(MKDIR) $(INCLUDEDIR)/cups + $(CP) raster.h $(INCLUDEDIR)/cups + -$(MKDIR) $(LIBDIR) + $(CP) $(LIBCUPSIMAGE) $(LIBDIR) + -if test $(LIBCUPSIMAGE) != "libcupsimage.a"; then \ + $(RM) `basename $(LIBCUPSIMAGE) .2`; \ + $(LN) $(LIBCUPSIMAGE) `basename $(LIBCUPSIMAGE) .2`; \ + fi + + +# +# formtops +# + +formtops: $(FORMOBJS) common.o ../Makedefs ../cups/$(LIBCUPS) + echo Linking $@... + $(CC) $(LDFLAGS) -o $@ $(FORMOBJS) common.o $(LIBS) -lm +$(FORMOBJS): form.h + + +# +# hpgltops +# + +hpgltops: $(HPGLOBJS) common.o ../Makedefs ../cups/$(LIBCUPS) + echo Linking $@... + $(CC) $(LDFLAGS) -o $@ $(HPGLOBJS) common.o $(LIBS) -lm +$(HPGLOBJS): hpgltops.h + + +# +# libcupsimage.so.2, libcupsimage.sl.2 +# + +libcupsimage.so.2 libcupsimage.sl.2: $(IMAGEOBJS) raster.o ../Makedefs + echo Linking $@... + $(DSO) $@ $(IMAGEOBJS) raster.o $(DSOLIBS) -lm + -$(LN) $@ `basename $@ .2` + + +# +# libcupsimage.a +# + +libcupsimage.a: $(IMAGEOBJS) raster.o ../Makedefs + echo Archiving $@... + $(RM) $@ + $(AR) $(ARFLAGS) $@ $(IMAGEOBJS) raster.o + $(RANLIB) $@ + +$(IMAGEOBJS): image.h +raster.o: raster.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 raster.h + + +# +# pstops +# + +pstops: pstops.o common.o ../Makedefs ../cups/$(LIBCUPS) + echo Linking $@... + $(CC) $(LDFLAGS) -o $@ pstops.o common.o $(LIBS) +pstops.o: common.h + + +# +# rastertoepson +# + +rastertoepson: rastertoepson.o ../Makedefs ../cups/$(LIBCUPS) + echo Linking $@... + $(CC) $(LDFLAGS) -o $@ rastertoepson.o -L. -lcupsimage $(LIBS) +rastertoepson.o: raster.h + + +# +# rastertohp +# + +rastertohp: rastertohp.o ../Makedefs ../cups/$(LIBCUPS) + echo Linking $@... + $(CC) $(LDFLAGS) -o $@ rastertohp.o -L. -lcupsimage $(LIBS) +rastertohp.o: 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..b41cc4ec32 --- /dev/null +++ b/filter/common.c @@ -0,0 +1,255 @@ +/* + * "$Id$" + * + * Common filter routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2000 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..c92a121186 --- /dev/null +++ b/filter/common.h @@ -0,0 +1,67 @@ +/* + * "$Id$" + * + * Common filter definitions for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2000 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/form-attr.c b/filter/form-attr.c new file mode 100644 index 0000000000..362b6e0654 --- /dev/null +++ b/filter/form-attr.c @@ -0,0 +1,37 @@ +/* + * "$Id$" + * + * CUPS form attribute routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2000 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 "form.h" + + +/* + * End of "$Id$". + */ diff --git a/filter/form-main.c b/filter/form-main.c new file mode 100644 index 0000000000..c35b11a4c8 --- /dev/null +++ b/filter/form-main.c @@ -0,0 +1,37 @@ +/* + * "$Id$" + * + * CUPS form main entry for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2000 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 "form.h" + + +/* + * End of "$Id$". + */ diff --git a/filter/form-ps.c b/filter/form-ps.c new file mode 100644 index 0000000000..48e6a40d3a --- /dev/null +++ b/filter/form-ps.c @@ -0,0 +1,37 @@ +/* + * "$Id$" + * + * CUPS form PostScript routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2000 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 "form.h" + + +/* + * End of "$Id$". + */ diff --git a/filter/form-text.c b/filter/form-text.c new file mode 100644 index 0000000000..c128890d1a --- /dev/null +++ b/filter/form-text.c @@ -0,0 +1,37 @@ +/* + * "$Id$" + * + * CUPS form text routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2000 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 "form.h" + + +/* + * End of "$Id$". + */ diff --git a/filter/form-tree.c b/filter/form-tree.c new file mode 100644 index 0000000000..2c27820def --- /dev/null +++ b/filter/form-tree.c @@ -0,0 +1,38 @@ +/* + * "$Id$" + * + * CUPS form document tree routines for the Common UNIX Printing + * System (CUPS). + * + * Copyright 1997-2000 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 "form.h" + + +/* + * End of "$Id$". + */ diff --git a/filter/form.h b/filter/form.h new file mode 100644 index 0000000000..c05e0d67aa --- /dev/null +++ b/filter/form.h @@ -0,0 +1,34 @@ +/* + * "$Id$" + * + * CUPS form header file for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2000 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" + + +/* + * End of "$Id$". + */ diff --git a/filter/hpgl-attr.c b/filter/hpgl-attr.c new file mode 100644 index 0000000000..0056f3af1b --- /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-2000 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[1], 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[1], 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[1], 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[1], 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[1], 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..aa29ba909b --- /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-2000 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..0496e08815 --- /dev/null +++ b/filter/hpgl-config.c @@ -0,0 +1,638 @@ +/* + * "$Id$" + * + * HP-GL/2 configuration routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1993-2000 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; + + /* + * 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 : /* PS ; */ + if (Rotation == 0 || Rotation == 180) + { + PlotSize[0] = PageWidth; + PlotSize[1] = PageLength; + } + else + { + PlotSize[0] = PageLength; + PlotSize[1] = PageWidth; + } + break; + case 1 : /* PS length ; */ + 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 : /* PS length, width ; */ + /* + * Unfortunately, it appears that NO application correctly + * sends a two-argument PS command as documented in the + * HP-GL/2 Reference Manual from HP. Instead, applications + * send the width before the length, which causes all sorts + * of problems. + * + * Rather than fight it, we now look for them as width,length + * instead of length,width. + * + * Don't like it? Send mail to the folks that make Ideas, Pro/E, + * AutoCAD, etc. + */ + + if (Rotation == 0 || Rotation == 180) + { + PlotSize[0] = 72.0f * params[0].value.number / 1016.0f; + PlotSize[1] = 72.0f * params[1].value.number / 1016.0f; + } + else + { + PlotSize[0] = 72.0f * params[1].value.number / 1016.0f; + PlotSize[1] = 72.0f * params[0].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..720122ee17 --- /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-2000 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..cc3009e05e --- /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-2000 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..c6646a6e55 --- /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-2000 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..3b29f6dae2 --- /dev/null +++ b/filter/hpgl-prolog.c @@ -0,0 +1,373 @@ +/* + * "$Id$" + * + * HP-GL/2 prolog routines for for the Common UNIX Printing System (CUPS). + * + * Copyright 1993-2000 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.1 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("%%Trailer"); + 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 ++; + + if (PPD != NULL && !FitPlot) + { + /* + * Set the page size for this page... + */ + + if (PageRotation == 0 || PageRotation == 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("%%BeginSetup"); + 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("%%%%Page: %d %d\n", PageCount, PageCount); + + 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("%.0f 0 translate 90 rotate\n", PageLength); + printf("%.1f %.1f translate\n", PageLength - PageTop, + PageWidth - PageRight); + break; + case 2 : + printf("%.0f %.0f translate 180 rotate\n", PageWidth, PageLength); + printf("%.1f %.1f translate\n", PageLeft, PageLength - PageTop); + break; + case 3 : + printf("0 %.0f translate -90 rotate\n", PageWidth); + 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("%.0f 0 translate 90 rotate\n", PageLength); + printf("%.1f %.1f translate\n", PageBottom, PageWidth - PageRight); + break; + case 2 : + printf("%.0f %.0f translate 180 rotate\n", PageWidth, PageLength); + printf("%.1f %.1f translate\n", PageWidth - PageRight, + PageLength - PageTop); + break; + case 3 : + printf("0 %.0f translate -90 rotate\n", PageWidth); + 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..5b71629209 --- /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-2000 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..d1b65d2da9 --- /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-2000 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(0), /* 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..42f83c8ab7 --- /dev/null +++ b/filter/image-colorspace.c @@ -0,0 +1,883 @@ +/* + * "$Id$" + * + * Colorspace conversions for the Common UNIX Printing System (CUPS). + * + * Copyright 1993-2000 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..d1d5c6e977 --- /dev/null +++ b/filter/image-gif.c @@ -0,0 +1,644 @@ +/* + * "$Id$" + * + * GIF image routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1993-2000 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..b352642b81 --- /dev/null +++ b/filter/image-jpeg.c @@ -0,0 +1,190 @@ +/* + * "$Id$" + * + * JPEG image routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1993-2000 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..91eb05e3be --- /dev/null +++ b/filter/image-photocd.c @@ -0,0 +1,319 @@ +/* + * "$Id$" + * + * PhotoCD routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1993-2000 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..76be54c1d2 --- /dev/null +++ b/filter/image-png.c @@ -0,0 +1,205 @@ +/* + * "$Id$" + * + * PNG image routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1993-2000 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..dbc956c61c --- /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-2000 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..1e8b2e2e57 --- /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-2000 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..ad8aa9e61a --- /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-2000 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..c6b6d9c22b --- /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-2000 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..7589c4f2c0 --- /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-2000 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..9628ff7884 --- /dev/null +++ b/filter/image-tiff.c @@ -0,0 +1,1620 @@ +/* + * "$Id$" + * + * TIFF file routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1993-2000 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..fe15632f1d --- /dev/null +++ b/filter/image-zoom.c @@ -0,0 +1,310 @@ +/* + * "$Id$" + * + * Image zoom routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1993-2000 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..9f5138faac --- /dev/null +++ b/filter/image.c @@ -0,0 +1,779 @@ +/* + * "$Id$" + * + * Base image support for the Common UNIX Printing System (CUPS). + * + * Copyright 1993-2000 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..74525c5216 --- /dev/null +++ b/filter/image.h @@ -0,0 +1,225 @@ +/* + * "$Id$" + * + * Image library definitions for the Common UNIX Printing System (CUPS). + * + * Copyright 1993-2000 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..78e6c30c7c --- /dev/null +++ b/filter/imagetops.c @@ -0,0 +1,565 @@ +/* + * "$Id$" + * + * Image file to PostScript filter for the Common UNIX Printing System (CUPS). + * + * Copyright 1993-2000 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); + + 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..4e148d2908 --- /dev/null +++ b/filter/imagetoraster.c @@ -0,0 +1,3972 @@ +/* + * "$Id$" + * + * Image file to raster filter for the Common UNIX Printing System (CUPS). + * + * Copyright 1993-2000 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 "raster.h" +#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); + + 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 / 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 --, 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..afdcd232aa --- /dev/null +++ b/filter/pstops.c @@ -0,0 +1,867 @@ +/* + * "$Id$" + * + * PostScript filter for the Common UNIX Printing System (CUPS). + * + * Copyright 1993-2000 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]); + + options = NULL; + num_options = cupsParseOptions(argv[5], 0, &options); + + ppd = SetCommonOptions(num_options, options, 1); + + 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/raster.c b/filter/raster.c new file mode 100644 index 0000000000..be4f466234 --- /dev/null +++ b/filter/raster.c @@ -0,0 +1,252 @@ +/* + * "$Id$" + * + * Raster file routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2000 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/filter/raster.h b/filter/raster.h new file mode 100644 index 0000000000..2c4052d569 --- /dev/null +++ b/filter/raster.h @@ -0,0 +1,233 @@ +/* + * "$Id$" + * + * Raster file definitions for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2000 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/filter/rastertoepson.c b/filter/rastertoepson.c new file mode 100644 index 0000000000..3c2dd68b4c --- /dev/null +++ b/filter/rastertoepson.c @@ -0,0 +1,596 @@ +/* + * "$Id$" + * + * EPSON ESC/P and ESC/P2 filter for the Common UNIX Printing System + * (CUPS). + * + * Copyright 1993-2000 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: + * + * Setup() - Prepare the printer for printing. + * StartPage() - Start a page of graphics. + * EndPage() - Finish a page of graphics. + * Shutdown() - Shutdown the printer. + * CompressData() - Compress a line of graphics. + * OutputLine() - Output a line of graphics. + * main() - Main entry and processing of driver. + */ + +/* + * Include necessary headers... + */ + +#include +#include +#include +#include "raster.h" +#include +#include +#include + + +/* + * Macros... + */ + +#define pwrite(s,n) fwrite((s), 1, (n), stdout) + + +/* + * Globals... + */ + +unsigned char *Planes[6], /* 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, ppd_file_t *ppd); +void EndPage(cups_page_header_t *header); +void Shutdown(void); + +void CompressData(unsigned char *line, int length, int plane, int type, + int xstep, int ystep); +void OutputLine(cups_page_header_t *header); + + +/* + * 'Setup()' - Prepare the printer for printing. + */ + +void +Setup(void) +{ + /* + * Send a reset sequence. + */ + + printf("\033@"); +} + + +/* + * 'StartPage()' - Start a page of graphics. + */ + +void +StartPage(cups_page_header_t *header, /* I - Page header */ + ppd_file_t *ppd) /* I - PPD file */ +{ + int n, t; /* Numbers */ + int plane; /* Looping var */ + + + /* + * Send a reset sequence. + */ + + printf("\033@"); + + /* + * Set graphics mode... + */ + + pwrite("\033(G\001\000\001", 6); /* Graphics mode */ + + /* + * Set the media size... + */ + + pwrite("\033(U\001\000", 5); /* Resolution/units */ + putchar(3600 / header->HWResolution[1]); + + n = header->PageSize[1] * header->HWResolution[1] / 72.0; + + pwrite("\033(C\002\000", 5); /* Page length */ + putchar(n); + putchar(n >> 8); + + t = (ppd->sizes[1].length - ppd->sizes[1].top) * + header->HWResolution[1] / 72.0; + + pwrite("\033(c\004\000", 5); /* Top & bottom margins */ + putchar(t); + putchar(t >> 8); + putchar(n); + putchar(n >> 8); + + /* + * Set other stuff... + */ + + if (header->cupsColorSpace == CUPS_CSPACE_CMY) + NumPlanes = 3; + else if (header->cupsColorSpace == CUPS_CSPACE_KCMY) + NumPlanes = 4; + else if (header->cupsColorSpace == CUPS_CSPACE_KCMYcm) + NumPlanes = 6; + else + NumPlanes = 1; + + if (header->HWResolution[1] == 720) + { + pwrite("\033(i\001\000\001", 6); /* Microweave */ + pwrite("\033(e\002\000\000\001", 7);/* Small dots */ + } + + pwrite("\033(V\002\000\000\000", 7); /* Set absolute position 0 */ + + 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... + */ + + putchar(12); /* Form feed */ + + /* + * Free memory... + */ + + free(Planes[0]); + + if (header->cupsCompression) + free(CompBuffer); +} + + +/* + * 'Shutdown()' - Shutdown the printer. + */ + +void +Shutdown(void) +{ + /* + * Send a reset sequence. + */ + + printf("\033@"); +} + + +/* + * '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 */ + int xstep, /* I - X resolution */ + int ystep) /* I - Y resolution */ +{ + 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 */ + temp; /* Current byte */ + int count; /* Count of bytes for output */ + static int ctable[6] = { 0, 2, 1, 4, 2, 1 }; + /* KCMYcm color values */ + + + /* + * Setup pointers... + */ + + line_ptr = line; + line_end = line + length; + + /* + * Do depletion for 720 DPI printing... + */ + + if (ystep == 5) + { + for (comp_ptr = line; comp_ptr < line_end;) + { + /* + * Grab the current byte... + */ + + temp = *comp_ptr; + + /* + * Check adjacent bits... + */ + + if ((temp & 0xc0) == 0xc0) + temp &= 0xbf; + if ((temp & 0x60) == 0x60) + temp &= 0xdf; + if ((temp & 0x30) == 0x30) + temp &= 0xef; + if ((temp & 0x18) == 0x18) + temp &= 0xf7; + if ((temp & 0x0c) == 0x0c) + temp &= 0xfb; + if ((temp & 0x06) == 0x06) + temp &= 0xfd; + if ((temp & 0x03) == 0x03) + temp &= 0xfe; + + *comp_ptr++ = temp; + + /* + * Check the last bit in the current byte and the first bit in the + * next byte... + */ + + if ((temp & 0x01) && comp_ptr < line_end && *comp_ptr & 0x80) + *comp_ptr &= 0x7f; + } + } + + switch (type) + { + case 0 : + /* + * Do no compression... + */ + break; + + case 1 : + /* + * Do TIFF pack-bits encoding... + */ + + 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 color if necessary... + */ + + if (NumPlanes > 1) + { + if (plane > 3) + printf("\033(r%c%c%c%c", 2, 0, 1, ctable[plane]); + /* Set extended color */ + else if (NumPlanes == 3) + printf("\033r%c", ctable[plane + 1]); + /* Set color */ + else + printf("\033r%c", ctable[plane]); /* Set color */ + } + + /* + * Send a raster plane... + */ + + putchar(0x0d); /* Move print head to left margin */ + + length *= 8; + printf("\033."); /* Raster graphics */ + putchar(type); + putchar(ystep); + putchar(xstep); + putchar(1); + putchar(length); + putchar(length >> 8); + + pwrite(line_ptr, line_end - line_ptr); +} + + +/* + * 'OutputLine()' - Output a line of graphics. + */ + +void +OutputLine(cups_page_header_t *header) /* I - Page header */ +{ + int plane; /* Current plane */ + int bytes; /* Bytes per plane */ + int xstep, ystep; /* X & Y resolutions */ + + /* + * Write bitmap data as needed... + */ + + xstep = 3600 / header->HWResolution[0]; + ystep = 3600 / header->HWResolution[1]; + bytes = header->cupsBytesPerLine / NumPlanes; + + for (plane = 0; plane < NumPlanes; plane ++) + { + /* + * Skip blank data... + */ + + if (!Planes[plane][0] && + memcmp(Planes[plane], Planes[plane] + 1, bytes - 1) == 0) + continue; + + /* + * Output whitespace as needed... + */ + + if (Feed > 0) + { + pwrite("\033(v\002\000", 5); /* Relative vertical position */ + putchar(Feed); + putchar(Feed >> 8); + + Feed = 0; + } + + CompressData(Planes[plane], bytes, plane, header->cupsCompression, xstep, + ystep); + } + + Feed ++; +} + + +/* + * '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 */ + ppd_file_t *ppd; /* PPD 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 return. + */ + + fputs("ERROR: rastertoepson job-id user title copies options [file]\n", stderr); + 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... + */ + + ppd = ppdOpenFile(getenv("PPD")); + + 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, ppd); + + /* + * 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; + + /* + * Write it to the printer... + */ + + OutputLine(&header); + } + + /* + * Eject the page... + */ + + EndPage(&header); + } + + /* + * Shutdown the printer... + */ + + Shutdown(); + + ppdClose(ppd); + + /* + * 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); + + return (page == 0); +} + + +/* + * End of "$Id$". + */ diff --git a/filter/rastertohp.c b/filter/rastertohp.c new file mode 100644 index 0000000000..1365000896 --- /dev/null +++ b/filter/rastertohp.c @@ -0,0 +1,503 @@ +/* + * "$Id$" + * + * Hewlett-Packard Page Control Language filter for the Common UNIX + * Printing System (CUPS). + * + * Copyright 1993-2000 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: + * + * Setup() - Prepare the printer for printing. + * StartPage() - Start a page of graphics. + * EndPage() - Finish a page of graphics. + * Shutdown() - Shutdown the printer. + * CompressData() - Compress a line of graphics. + * OutputLine() - Output a line of graphics. + * main() - Main entry and processing of driver. + */ + +/* + * Include necessary headers... + */ + +#include +#include +#include "raster.h" +#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 return. + */ + + fputs("ERROR: rastertopcl job-id user title copies options [file]\n", stderr); + 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); + + return (page == 0); +} + + +/* + * End of "$Id$". + */ diff --git a/filter/textcommon.c b/filter/textcommon.c new file mode 100644 index 0000000000..107c7b04df --- /dev/null +++ b/filter/textcommon.c @@ -0,0 +1,745 @@ +/* + * "$Id$" + * + * Common text filter routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2000 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..354ce7ae5a --- /dev/null +++ b/filter/textcommon.h @@ -0,0 +1,93 @@ +/* + * "$Id$" + * + * Common text filter definitions for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2000 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_NORMAL 0x00 +#define ATTR_BOLD 0x01 +#define ATTR_ITALIC 0x02 +#define ATTR_BOLDITALIC 0x03 +#define ATTR_FONT 0x03 + +#define ATTR_UNDERLINE 0x04 +#define ATTR_RAISED 0x08 +#define ATTR_LOWERED 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..0959638f86 --- /dev/null +++ b/filter/texttops.c @@ -0,0 +1,1132 @@ +/* + * "$Id$" + * + * Text to PostScript filter for the Common UNIX Printing System (CUPS). + * + * Copyright 1993-2000 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 */ +int NumFonts; /* Number of fonts to use */ +char *Fonts[256][4]; /* Fonts to use */ +unsigned short Chars[65536]; /* 0xffcc (ff = font, cc = char) */ +unsigned short Codes[65536]; /* Unicode glyph mapping to fonts */ +int Widths[256]; /* Widths of each font */ +int Directions[256];/* Text directions for each font */ + + +/* + * Local functions... + */ + +static void write_line(int row, lchar_t *line); +static void write_string(int col, int row, int len, lchar_t *s); +static void write_text(char *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 i, j, k; /* Looping vars */ + char *charset; /* Character set string */ + char filename[1024]; /* Glyph filenames */ + FILE *fp; /* Glyph files */ + char line[1024], /* Line from file */ + *lineptr, /* Pointer into line */ + *valptr; /* Pointer to value in line */ + int ch, unicode; /* Character values */ + int start, end; /* Start and end values for range */ + char glyph[64]; /* Glyph name */ + time_t curtime; /* Current time */ + struct tm *curtm; /* Current date */ + char curdate[255]; /* Current date (text format) */ + int num_fonts; /* Number of unique fonts */ + char *fonts[1024]; /* Unique fonts */ + static char *names[] = /* Font names */ + { + "cupsNormal", + "cupsBold", + "cupsItalic" + }; + + + /* + * Allocate memory for the page... + */ + + 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 (i = 1; i < SizeLines; i ++) + Page[i] = Page[0] + i * SizeColumns; + + if (PageColumns > 1) + { + ColumnGutter = CharsPerInch / 2; + ColumnWidth = (SizeColumns - ColumnGutter * (PageColumns - 1)) / + PageColumns; + } + else + ColumnWidth = SizeColumns; + + /* + * Output the DSC header... + */ + + 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); + puts("%%DocumentSuppliedResources: procset texttops 1.1 0"); + puts("%%Pages: (atend)"); + + /* + * Initialize globals... + */ + + NumFonts = 0; + memset(Fonts, 0, sizeof(Fonts)); + memset(Glyphs, 0, sizeof(Glyphs)); + memset(Chars, 0, sizeof(Chars)); + memset(Codes, 0, sizeof(Codes)); + + /* + * Load the PostScript glyph names and the corresponding character + * set definition... + */ + + if ((fp = fopen(CUPS_DATADIR "/data/psglyphs", "r")) != NULL) + { + while (fscanf(fp, "%x%63s", &unicode, glyph) == 2) + Glyphs[unicode] = strdup(glyph); + + fclose(fp); + } + else + { + perror("ERROR: Unable to open " CUPS_DATADIR "/data/psglyphs"); + exit(1); + } + + /* + * Get the output character set... + */ + + charset = getenv("CHARSET"); + if (charset != NULL && strcmp(charset, "us-ascii") != 0) + { + snprintf(filename, sizeof(filename), CUPS_DATADIR "/charsets/%s", charset); + + if ((fp = fopen(filename, "r")) == NULL) + { + /* + * Can't open charset file! + */ + + fprintf(stderr, "ERROR: Unable to open %s: %s\n", filename, + strerror(errno)); + exit(1); + } + + /* + * Opened charset file; now see if this is really a charset file... + */ + + if (fgets(line, sizeof(line), fp) == NULL) + { + /* + * Bad/empty charset file! + */ + + fclose(fp); + fprintf(stderr, "ERROR: Bad/empty charset file %s\n", filename); + exit(1); + } + + if (strncmp(line, "charset", 7) != 0) + { + /* + * Bad format/not a charset file! + */ + + fclose(fp); + fprintf(stderr, "ERROR: Bad charset file %s\n", filename); + exit(1); + } + + /* + * See if this is an 8-bit or UTF-8 character set file... + */ + + line[strlen(line) - 1] = '\0'; /* Drop \n */ + for (lineptr = line + 7; isspace(*lineptr); lineptr ++); /* Skip whitespace */ + + if (strcmp(lineptr, "8bit") == 0) + { + /* + * 8-bit text... + */ + + UTF8 = 0; + NumFonts = 1; + + /* + * Read the font description... + */ + + while (fgets(line, sizeof(line), fp) != NULL) + { + /* + * Skip comment and blank lines... + */ + + if (line[0] != '#' && line[0] != '\n') + break; + } + + /* + * Read the font descriptions that should look like: + * + * direction width normal [bold italic bold-italic] + */ + + lineptr = line; + while (isspace(*lineptr)) + lineptr ++; + + valptr = lineptr; + + while (!isspace(*lineptr) && *lineptr) + lineptr ++; + + if (!*lineptr) + { + /* + * Can't have a font without all required values... + */ + + fprintf(stderr, "ERROR: bad font description line: %s\n", valptr); + fclose(fp); + exit(1); + } + + *lineptr++ = '\0'; + + if (strcmp(valptr, "ltor") == 0) + Directions[0] = 1; + else if (strcmp(valptr, "rtol") == 0) + Directions[0] = -1; + else + { + fprintf(stderr, "ERROR: Bad text direction %s\n", valptr); + fclose(fp); + exit(1); + } + + /* + * Got the direction, now get the width... + */ + + while (isspace(*lineptr)) + lineptr ++; + + valptr = lineptr; + + while (!isspace(*lineptr) && *lineptr) + lineptr ++; + + if (!*lineptr) + { + /* + * Can't have a font without all required values... + */ + + fprintf(stderr, "ERROR: bad font description line: %s\n", valptr); + fclose(fp); + exit(1); + } + + *lineptr++ = '\0'; + + if (strcmp(valptr, "single") == 0) + Widths[0] = 1; + else if (strcmp(valptr, "double") == 0) + Widths[0] = 2; + else + { + fprintf(stderr, "ERROR: Bad text width %s\n", valptr); + fclose(fp); + exit(1); + } + + /* + * Get the fonts... + */ + + for (i = 0; *lineptr && i < 4; i ++) + { + while (isspace(*lineptr)) + lineptr ++; + + valptr = lineptr; + + while (!isspace(*lineptr) && *lineptr) + lineptr ++; + + if (*lineptr) + *lineptr++ = '\0'; + + if (lineptr > valptr) + Fonts[0][i] = strdup(valptr); + } + + /* + * Fill in remaining fonts as needed... + */ + + for (j = i; j < 4; j ++) + Fonts[0][j] = strdup(Fonts[0][0]); + + /* + * Read encoding lines... + */ + + while (fgets(line, sizeof(line), fp) != NULL) + { + /* + * Skip comment and blank lines... + */ + + if (line[0] == '#' || line[0] == '\n') + continue; + + /* + * Grab the character and unicode glyph number. + */ + + if (sscanf(line, "%x%x", &ch, &unicode) == 2 && ch < 256) + { + Codes[ch] = unicode; + Chars[ch] = ch; + } + } + + fclose(fp); + } + else if (strcmp(lineptr, "utf8") == 0) + { + /* + * UTF-8 (Unicode) text... + */ + + UTF8 = 1; + + /* + * Read the font descriptions... + */ + + NumFonts = 0; + + while (fgets(line, sizeof(line), fp) != NULL) + { + /* + * Skip comment and blank lines... + */ + + if (line[0] == '#' || line[0] == '\n') + continue; + + /* + * Read the font descriptions that should look like: + * + * start end direction width normal [bold italic bold-italic] + */ + + lineptr = line; + + start = strtol(lineptr, &lineptr, 16); + end = strtol(lineptr, &lineptr, 16); + + while (isspace(*lineptr)) + lineptr ++; + + valptr = lineptr; + + while (!isspace(*lineptr) && *lineptr) + lineptr ++; + + if (!*lineptr) + { + /* + * Can't have a font without all required values... + */ + + fprintf(stderr, "ERROR: bad font description line: %s\n", valptr); + fclose(fp); + exit(1); + } + + *lineptr++ = '\0'; + + if (strcmp(valptr, "ltor") == 0) + Directions[NumFonts] = 1; + else if (strcmp(valptr, "rtol") == 0) + Directions[NumFonts] = -1; + else + { + fprintf(stderr, "ERROR: Bad text direction %s\n", valptr); + fclose(fp); + exit(1); + } + + /* + * Got the direction, now get the width... + */ + + while (isspace(*lineptr)) + lineptr ++; + + valptr = lineptr; + + while (!isspace(*lineptr) && *lineptr) + lineptr ++; + + if (!*lineptr) + { + /* + * Can't have a font without all required values... + */ + + fprintf(stderr, "ERROR: bad font description line: %s\n", valptr); + fclose(fp); + exit(1); + } + + *lineptr++ = '\0'; + + if (strcmp(valptr, "single") == 0) + Widths[NumFonts] = 1; + else if (strcmp(valptr, "double") == 0) + Widths[NumFonts] = 2; + else + { + fprintf(stderr, "ERROR: Bad text width %s\n", valptr); + fclose(fp); + exit(1); + } + + /* + * Get the fonts... + */ + + for (i = 0; *lineptr && i < 4; i ++) + { + while (isspace(*lineptr)) + lineptr ++; + + valptr = lineptr; + + while (!isspace(*lineptr) && *lineptr) + lineptr ++; + + if (*lineptr) + *lineptr++ = '\0'; + + if (lineptr > valptr) + Fonts[NumFonts][i] = strdup(valptr); + } + + /* + * Fill in remaining fonts as needed... + */ + + for (j = i; j < 4; j ++) + Fonts[NumFonts][j] = strdup(Fonts[NumFonts][0]); + + /* + * Define the character mappings... + */ + + for (i = start, j = NumFonts * 256; i <= end; i ++, j ++) + { + Chars[i] = j; + Codes[j] = i; + } + + /* + * Move to the next font, stopping if needed... + */ + + NumFonts ++; + if (NumFonts >= 256) + break; + } + + fclose(fp); + } + else + { + fprintf(stderr, "ERROR: Bad charset type %s\n", lineptr); + fclose(fp); + exit(1); + } + } + else + { + /* + * Standard ASCII output just uses Courier, Courier-Bold, and + * possibly Courier-Oblique. + */ + + NumFonts = 1; + + Fonts[0][ATTR_NORMAL] = strdup("Courier"); + Fonts[0][ATTR_BOLD] = strdup("Courier-Bold"); + Fonts[0][ATTR_ITALIC] = strdup("Courier-Oblique"); + Fonts[0][ATTR_BOLDITALIC] = strdup("Courier-BoldOblique"); + + Widths[0] = 1; + Directions[0] = 1; + + /* + * Define US-ASCII characters... + */ + + for (i = 32; i < 127; i ++) + { + Chars[i] = i; + Codes[i] = i; + } + } + + /* + * Generate a list of unique fonts to use... + */ + + for (i = 0, num_fonts = 0; i < NumFonts; i ++) + for (j = 1 + PrettyPrint; j >= 0; j --) + { + for (k = 0; k < num_fonts; k ++) + if (strcmp(Fonts[i][j], fonts[k]) == 0) + break; + + if (k >= num_fonts) + { + /* + * Add new font... + */ + + fonts[num_fonts] = Fonts[i][j]; + num_fonts ++; + } + } + + /* + * List the fonts that will be used... + */ + + for (i = 0; i < num_fonts; i ++) + if (i == 0) + printf("%%DocumentNeededResources: font %s\n", fonts[i]); + else + printf("%%+ font %s\n", fonts[i]); + + puts("%%EndComments"); + + puts("%%BeginProlog"); + + /* + * Write the encoding array(s)... + */ + + puts("% character encoding(s)"); + + for (i = 0; i < NumFonts; i ++) + { + printf("/cupsEncoding%02x [\n", i); + + for (ch = 0; ch < 256; ch ++) + { + if (Glyphs[Codes[i * 256 + ch]]) + printf("/%s", Glyphs[Codes[i * 256 + ch]]); + else + printf("/.notdef"); + + if ((ch & 7) == 7) + putchar('\n'); + } + + puts("] def"); + } + + /* + * Create the fonts... + */ + + if (NumFonts == 1) + { + /* + * Just reencode the named fonts... + */ + + puts("% Reencode fonts"); + + for (i = 1 + PrettyPrint; i >= 0; i --) + { + printf("/%s findfont\n", Fonts[0][i]); + puts("dup length 1 add dict begin\n" + " { 1 index /FID ne { def } { pop pop } ifelse } forall\n" + " /Encoding cupsEncoding00 def\n" + " currentdict\n" + "end"); + printf("/%s exch definefont pop\n", names[i]); + } + } + else + { + /* + * Construct composite fonts... Start by reencoding the base fonts... + */ + + puts("% Reencode base fonts"); + + for (i = 1 + PrettyPrint; i >= 0; i --) + for (j = 0; j < NumFonts; j ++) + { + printf("/%s findfont\n", Fonts[j][i]); + printf("dup length 1 add dict begin\n" + " { 1 index /FID ne { def } { pop pop } ifelse } forall\n" + " /Encoding cupsEncoding%02x def\n" + " currentdict\n" + "end\n", j); + printf("/%s%02x exch definefont /%s%02x exch def\n", names[i], j, + names[i], j); + } + + /* + * Then merge them into composite fonts... + */ + + puts("% Create composite fonts..."); + + for (i = 1 + PrettyPrint; i >= 0; i --) + { + puts("8 dict begin"); + puts("/FontType 0 def/FontMatrix[1.0 0 0 1.0 0 0]def/FMapType 2 def/Encoding["); + for (j = 0; j < NumFonts; j ++) + if (j == (NumFonts - 1)) + printf("%d", j); + else if ((j & 15) == 15) + printf("%d\n", j); + else + printf("%d ", j); + puts("]def/FDepVector["); + for (j = 0; j < NumFonts; j ++) + if (j == (NumFonts - 1)) + printf("%s%02x", names[i], j); + else if ((j & 3) == 3) + printf("%s%02x\n", names[i], j); + else + printf("%s%02x ", names[i], j); + puts("]def currentdict end"); + printf("/%s exch definefont pop\n", names[i]); + } + } + + /* + * Output the texttops procset... + */ + + puts("%%BeginResource: procset texttops 1.1 0"); + + puts("% Define fonts"); + + printf("/FN /cupsNormal findfont [%.1f 0 0 %.1f 0 0] makefont def\n", + 120.0 / CharsPerInch, 68.0 / LinesPerInch); + printf("/FB /cupsBold findfont [%.1f 0 0 %.1f 0 0] makefont def\n", + 120.0 / CharsPerInch, 68.0 / LinesPerInch); + if (PrettyPrint) + printf("/FI /cupsItalic 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"); + printf("/U { gsave 0.5 setlinewidth 0 %.2f rmoveto " + "0 rlineto stroke grestore } bind def\n", -6.8 / LinesPerInch); + + 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("/n {"); + puts("\t20 string cvs % convert page number to string"); + puts("\tdup length % get length"); + puts("\tdup 2 mul string /P exch def % P = string twice as long"); + puts("\t0 1 2 index 1 sub { % loop through each character in the page number"); + puts("\t\tdup 3 index exch get % get character N from the page number"); + puts("\t\texch 2 mul dup % compute offset in P"); + puts("\t\tP exch 0 put % font 0"); + puts("\t\t1 add P exch 2 index put % character"); + puts("\t\tpop % discard character"); + puts("\t} for % do for loop"); + puts("\tpop pop % discard string and length"); + puts("\tP % put string on stack"); + puts("} bind def"); + + printf("/T"); + write_text(title); + puts("def"); + + printf("/D"); + write_text(curdate); + 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("\tD dup 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 n 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("\tn 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 */ + + + /**** TODO - handle bidi text and arabic composition ****/ + 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 ch; /* Current character */ + int font; /* Font for character */ + 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); + + if (UTF8) + { + /* + * Write a hex string... + */ + + putchar('<'); + + while (len > 0) + { + printf("%04x", Chars[s->ch]); + + len --; + s ++; + } + + putchar('>'); + } + else + { + /* + * Write a quoted string... + */ + + putchar('('); + + while (len > 0) + { + ch = Chars[s->ch]; + + if (ch < 32 || ch > 126) + { + /* + * Quote 8-bit and control characters... + */ + + printf("\\%03o", ch); + } + else + { + /* + * Quote the parenthesis and backslash as needed... + */ + + if (ch == '(' || ch == ')' || ch == '\\') + putchar('\\'); + + putchar(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"); +} + + +/* + * 'write_text()' - Write a text string, quoting/encoding as needed. + */ + +static void +write_text(char *s) /* I - String to write */ +{ + int ch; /* Actual character value (UTF8) */ + unsigned char *utf8; /* UTF8 text */ + + + if (UTF8) + { + /* + * 8/8 encoding... + */ + + putchar('<'); + + utf8 = (unsigned char *)s; + + while (*utf8) + { + if (*utf8 < 0xc0) + ch = *utf8 ++; + else if ((*utf8 & 0xe0) == 0xc0) + { + /* + * Two byte character... + */ + + ch = ((utf8[0] & 0x1f) << 6) | (utf8[1] & 0x3f); + utf8 += 2; + } + else + { + /* + * Three byte character... + */ + + ch = ((((utf8[0] & 0x1f) << 6) | (utf8[1] & 0x3f)) << 6) | + (utf8[2] & 0x3f); + utf8 += 3; + } + + printf("%04x", Chars[ch]); + } + + putchar('>'); + } + else + { + /* + * Standard 8-bit encoding... + */ + + putchar('('); + + while (*s) + { + if (*s < 32 || *s > 126) + printf("\\%03o", *s); + else + { + if (*s == '(' || *s == ')' || *s == '\\') + putchar('\\'); + + putchar(*s); + } + + s ++; + } + + putchar(')'); + } +} + + +/* + * End of "$Id$". + */ diff --git a/fonts/AvantGarde-Book b/fonts/AvantGarde-Book new file mode 100644 index 0000000000000000000000000000000000000000..ff3b81847e96f619f08fcbd708ccb742704f2f56 GIT binary patch literal 25994 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 literal 0 Hc-jL100001 diff --git a/fonts/AvantGarde-Demi b/fonts/AvantGarde-Demi new file mode 100644 index 0000000000000000000000000000000000000000..e0df0c709564e1ff1c0c55493267de6747082122 GIT binary patch literal 26980 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
2_R@ zOsyMpYO=MLu7?PW^JrVA2O#Z(RIsb>V#_Nb;MI#DhAXM>kx@JSAai(hy(nsOyTwM) zT>=GyzeQJP(;dl414XfRn(pt_v?UAXe-JrG^Ta1hVp z&o8(W{-V`aZIX2i2~fCYnmt=bW d!J+*x5&U29pAdMUz1%P%fe+j;{(@0le*+})hEo6l literal 0 Hc-jL100001 diff --git a/fonts/Bookman-Light b/fonts/Bookman-Light new file mode 100644 index 0000000000000000000000000000000000000000..4416dbf312ca5414e817b179c9eb7f7b1037c7ac GIT binary patch literal 35522 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 SoRgYZRFa>YSd`7xzzhItFD_C5 literal 0 Hc-jL100001 diff --git a/fonts/Courier b/fonts/Courier new file mode 100644 index 0000000000000000000000000000000000000000..54fe52724bbb3c243fd616a0329e075c6976b320 GIT binary patch literal 35719 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 literal 0 Hc-jL100001 diff --git a/fonts/Courier-Bold b/fonts/Courier-Bold new file mode 100644 index 0000000000000000000000000000000000000000..7b31de35f3135bdbf792ab7b0a665d28fd8ec0fe GIT binary patch literal 38284 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 QD-SPM7b_1Z;t<^b05wus?EnA( literal 0 Hc-jL100001 diff --git a/fonts/Courier-BoldOblique b/fonts/Courier-BoldOblique new file mode 100644 index 0000000000000000000000000000000000000000..45b11a12f77fd52c4fb0e4606cf5171728b04cb9 GIT binary patch literal 40686 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%0A(4sOjcj8Y3Py;iJ>yMjZ)eK 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 Z|Bv8*1%bJPrKy{Tv!kh-J!&xg{{W?;%F6%% literal 0 Hc-jL100001 diff --git a/fonts/Courier-Oblique b/fonts/Courier-Oblique new file mode 100644 index 0000000000000000000000000000000000000000..bbd2f05345469c07f2b1838d72667e1ccec3cc94 GIT binary patch literal 34677 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 literal 0 Hc-jL100001 diff --git a/fonts/Helvetica b/fonts/Helvetica new file mode 100644 index 0000000000000000000000000000000000000000..5f20a5aade37ce33e120c93c2db56ff8141cce7e GIT binary patch literal 27505 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 VCj_Q;=Eg3rj`qebwlIO9{{aafGARH6 literal 0 Hc-jL100001 diff --git a/fonts/Helvetica-BoldOblique b/fonts/Helvetica-BoldOblique new file mode 100644 index 0000000000000000000000000000000000000000..48c34c1ca2fc617d4631f21c0d9e0be659a4cb4f GIT binary patch literal 28971 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 literal 0 Hc-jL100001 diff --git a/fonts/Helvetica-Narrow b/fonts/Helvetica-Narrow new file mode 100644 index 0000000000000000000000000000000000000000..e81691b52c032272dc8db6e127278462366a60b5 GIT binary patch literal 27406 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 z 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�D*3 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�S={MYA^(*AS6s#TVRJ$i(i<(N1*H8;*CLJnPuH}QniV(6~gH9rNvx6TTU6eve1kZ zfR(Z!^MBn98tS|7Qsi8@8$Q8txQ3}Rl^lY%Gs>4MU5J{WZYGQGKoH_6QDw&Dr%^u3 zwD?0P^D4)5a*laO>H z5Y5_43eqhz&-JYi0|NZ689M;v22t}Kx|us#sfwd?U{J4gGKqx*WLC`%I3XREsd{aB zwC^NQDNv$p+LC>(ALL%b(?Dc=t+^#SW4F~e_Vi7iIs@|Y@sAn_Tn$9+S0A~no6UV> zGXi9Dsw*OEOyp{7Tq9J4025Ftrv%qD3;F4rnKD(RYIz{*H#CV(oJ;lNgQD>6S-Wfb zw@Ue{Ye=_-iui%KIr)kyAo%1VA_3|>{K*p_zPTb?&f~^y**vzI%@PQb~RXqFdxDL#13x!8&*qNcQ zr!<#Mt#WB-7D($hr5Wc;Ts!zq{b{zLtSQ;?3ooV^hkE`TXMYOIIFSx5-B*W#DIlsg z_f9WoM1mWu3p3opRYag#Iv$i;M|bbn-l|y$o*yBl;0M!dVK-?l_;y!XeUM5cmKAiO zzz0uHMez+*RtZC8MI0r=K5*H!Jb?!=pD+Fy#4VFa<=y^bU7-03~r$cCX)1O>g>QY%+G{M8dyEkUOiBdH)K2eraYxdm;xndtl>pNJUe=( zdjkt((6)~fNzDC)Vvm7s=q=cbve&hSus*cw^XUFu39P~;Mjh)B$^NjXb{lu7|5&A9 zlwOv2dU~}QXmLs69;yN3eOJy}Hm)tga{@_PV2yVZpb3H$=n>?QY|w4J?4m*m4QdXp zn|*TViO-mVPM>~>`O!J;hbFB#dpg;t{E;YdkOfUkQdw~yCYR9!+K2l5)Yd=i1zF1V zZA%ltxmSQ_S{q%$WjC;~VL&78GV44WN!i!ue5zYW^gG;7xw)Bv1Au`>d^n%E(J|-N z)wg+>wp`a6h{FQ+Hl*>z{S zoe{V>tCR_fLT-&jO=XH?()9)2p2!E3nN9_oi5h*N7BNssS0rQ@%_o~;B>EMKTk6W^*n`5M zzLbn^0LuNY{k)&;+^J3_9jW59YDgYDwb3ci2dg#e>}ey^-S z7(d91`B@2_o!0_s8NMut9)2xB(-0GGJ@><{Tf_yE^R?bbBIheezU8;v#D*izCqTIw z&bHTuZpAvcVB;D)nSUsphvxyNe$D(I+0nfc#+P84M;6)nn5ef!n@{zpPQf|g&RYU$ zx+}HdJNVYIEdsR6qs<@qH;);)BB=VaQx|6s%R^AoPX38j6p&9O{;i-ZEfK}E(Ryd0 zA5ds$E-h{RnjHDBGo)s={cqA+&i>-gZ3bENlh+g4rIhXOHEI?O6~h

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

YqLw7Xhbt5P`d1Va<~6Rm zkMV#1(TCk*Yc1;n;duqh;l(5GR|zRS**{K6S}i$VaLc$2;IFsbmcau~;iL2LZZ$0G znS4s_1df^9$#DE6rqh5|YTr!kZT^XSZ92(}&h_jB;%>nenWtTXkv*@k_qwh{F6or( z_@*(7afwuThwp!SoT|N}t2sVl$*Y@YVh(MTgD0lY2f7By_01b2rY*Y)x-4#l0$K#B zKRY6U&Z9Di4PDye?X?rI&Ov|Vjf28$!v@hhg0VW2%Az30~Y)Q26}>LE@+I$ zE7qHS{WP)`AFp?Eny~NfmoEI${cKfjvsdNg&67Dz(Xki6 z-xA>Ucw0wq*R2bG_wwr&o>Rg+EM_O8i_HE!Qv#px z$fX-;+>m4+Oe@;`KkcEKsj@aT~n*;|;nx;r_TxZ1%5f&UNkI|5q( literal 0 Hc-jL100001 diff --git a/fonts/Makefile b/fonts/Makefile new file mode 100644 index 0000000000..08d23c2125 --- /dev/null +++ b/fonts/Makefile @@ -0,0 +1,68 @@ +# +# "$Id$" +# +# Fonts makefile for the Common UNIX Printing System (CUPS). +# +# Copyright 1993-2000 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 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 literal 0 Hc-jL100001 diff --git a/fonts/Times-Bold b/fonts/Times-Bold new file mode 100644 index 0000000000000000000000000000000000000000..b03ed85d48cb5970d4ddb7782737351ef9ee7c7c GIT binary patch literal 34996 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

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

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

d(A>0GW|SZx_`nCI2yl7&7Q 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 literal 0 Hc-jL100001 diff --git a/fonts/Utopia-BoldItalic b/fonts/Utopia-BoldItalic new file mode 100644 index 0000000000000000000000000000000000000000..c36689694d2810d66dce3b4c5d2b64b6ac816a16 GIT binary patch literal 37836 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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..e4654b1f28 --- /dev/null +++ b/locale/C/cups_C @@ -0,0 +1,132 @@ +us-ascii +OK +Cancel +Help +Quit +Close +Yes +No +On +Off +Save +Discard +Default +Options +More Info +Black +Color +Cyan +Magenta +Yellow +Copyright 1993-2000 by Easy Software Products, All Rights Reserved. +General +Printer +Image +HP-GL/2 +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 +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 +Text +Pretty Print +Margins +Left +Right +Bottom +Top +Filename(s) +Print +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..639e50da82 --- /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) $$dir/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..f6f699a3ae --- /dev/null +++ b/locale/de/cups_de @@ -0,0 +1,133 @@ +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-2000 durch Easy Software Products, alle Rechte vorbehalten. +Allgemein +Drucker +Bild +HP-GL/2 +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 +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 +Text +Spezieller Druck +Seitenränder +Links +Recht +Unterseite +Oberseite +Dateiname(s) +Druker +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..35d291a176 --- /dev/null +++ b/locale/en/cups_en @@ -0,0 +1,132 @@ +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-2000 by Easy Software Products, All Rights Reserved. +General +Printer +Image +HP-GL/2 +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 +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 +Text +Pretty Print +Margins +Left +Right +Bottom +Top +Filename(s) +Print +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..c9c3420cc8 --- /dev/null +++ b/locale/es/cups_es @@ -0,0 +1,132 @@ +iso-8859-1 +OK +Cancel +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-2000 por Easy Software Products, todos endereza reservado. +General +Impresora +Imagen +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 +Par +Más Oscuro Más Brillante +Talla De Media +Tipo De Media +Fuente De los Media +Orientación: +Retrato +Paisaje +Estatus del trabajo +Nombre del trabajo +Nombre del utilizador +Prioridad +Copias +Tamaño +Pendiente +Modo de impresión +Resolución +Texto +Especial impresión +Márgenes +Izquierda +La derecha +Fondo +Tapa +Nombre(s) +Impresión +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..542749347c --- /dev/null +++ b/locale/fr/cups_fr @@ -0,0 +1,132 @@ +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-2000 par Easy Software Products, tous droits réservés. +Général +Imprimante +Image +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 +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 +Texte +Empreinte Spéciale +Marge +Gauche +Droite +Bas +Haut +Nom du ficher(s) +Imprimer +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..29e7725b09 --- /dev/null +++ b/locale/it/cups_it @@ -0,0 +1,132 @@ +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-2000 di Easy Software Products, tutti i diritti riservati. +Generale +Stampante +Immagini +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 +Pari +Più Scuro Più Luminoso +Formato del supporto +Tipo del supporto +Sorgente del supporto +Orientamento: +Verticale +Orizzontale +Condizione di lavoro +Nome di lavoro +Nome dell' utente +Priorita' +Copie +Dimensioni del file +In attesa +Modo stampa +Risoluzione +Testo +Speciale stampa +Margini +Sinistra +Destra +Inferiore +Superiore +Nome(s) +Stampa +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..89f61db8f8 --- /dev/null +++ b/man/Makefile @@ -0,0 +1,87 @@ +# +# "$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... +# + +CAT1 = backend.1 filter.1 lp.1 lpq.1 lprm.1 lpr.1 lpstat.1 +CAT5 = classes.conf.5 cupsd.conf.5 mime.convs.5 mime.types.5 \ + printers.conf.5 +CAT8 = accept.8 cupsd.8 enable.8 lpadmin.8 lpc.8 + +MAN1 = $(MAN1:.1=.man) +MAN5 = $(MAN5:.5=.man) +MAN8 = $(MAN8:.8=.man) + + +# +# Make everything... +# + +all: $(CAT1) $(CAT5) $(CAT8) + + +# +# Clean all config and object files... +# + +clean: + + +# +# Install files... +# + +install: + -$(MKDIR) $(MANDIR)/man1 + for file in $(MAN1); do \ + $(CP) $$file $(MANDIR)/man1/`basename $$file man`1; \ + done + $(LN) lp.1 $(MANDIR)/man1/cancel.1 + -$(MKDIR) $(MANDIR)/cat1 + $(CP) $(CAT1) $(MANDIR)/cat1 + $(LN) lp.1 $(MANDIR)/cat1/cancel.1 + -$(MKDIR) $(MANDIR)/man5 + for file in $(MAN5); do \ + $(CP) $$file $(MANDIR)/man5/`basename $$file man`5; \ + done + -$(MKDIR) $(MANDIR)/cat5 + $(CP) $(CAT5) $(MANDIR)/cat5 + -$(MKDIR) $(MANDIR)/man8 + for file in $(MAN8); do \ + $(CP) $$file $(MANDIR)/man8/`basename $$file man`8; \ + done + $(LN) accept.8 $(MANDIR)/man8/reject.8 + $(LN) enable.8 $(MANDIR)/man8/disable.8 + -$(MKDIR) $(MANDIR)/cat8 + $(CP) $(CAT8) $(MANDIR)/cat8 + $(LN) accept.8 $(MANDIR)/cat8/reject.8 + $(LN) enable.8 $(MANDIR)/cat8/disable.8 + +# +# End of "$Id$". +# diff --git a/man/accept.8 b/man/accept.8 new file mode 100644 index 0000000000..4a7831efcb --- /dev/null +++ b/man/accept.8 @@ -0,0 +1,66 @@ + + + +accept(8) Easy Software Products accept(8) + + +NNAAMMEE + accept/reject - accept/reject jobs sent to a destination + +SSYYNNOOPPSSIISS + aacccceepptt destination(s) + rreejjeecctt [ -h _s_e_r_v_e_r ] [ -r [ _r_e_a_s_o_n ] ] destination(s) + +DDEESSCCRRIIPPTTIIOONN + _a_c_c_e_p_t instructs the printing system to accept print jobs + to the specified destinations. + + _r_e_j_e_c_t instructs the printing system to reject print jobs + to the specified destinations. The _-_r option sets the rea- + son for rejecting print jobs. If not specified the reason + defaults to "Reason Unknown". + +CCOOMMPPAATTIIBBIILLIITTYY + The CUPS versions of _a_c_c_e_p_t and _r_e_j_e_c_t 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. + +SSEEEE AALLSSOO + cancel(1), disable(8), enable(8), lp(1), lpadmin(8), + lpstat(1), CUPS Software Administrators Manual + +CCOOPPYYRRIIGGHHTT + Copyright 1993-2000 by Easy Software Products, All Rights + Reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + +22 September 1999 Common UNIX Printing System 1 + + diff --git a/man/accept.man b/man/accept.man new file mode 100644 index 0000000000..0e4b6e47d0 --- /dev/null +++ b/man/accept.man @@ -0,0 +1,57 @@ +.\" +.\" "$Id: accept.man 911 2000-02-23 03:17:06Z mike $" +.\" +.\" accept/reject man page for the Common UNIX Printing System (CUPS). +.\" +.\" Copyright 1997-2000 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-2000 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: accept.man 911 2000-02-23 03:17:06Z mike $". +.\" diff --git a/man/backend.1 b/man/backend.1 new file mode 100644 index 0000000000..161cbf8655 --- /dev/null +++ b/man/backend.1 @@ -0,0 +1,132 @@ + + + +backend(1) Easy Software Products backend(1) + + +NNAAMMEE + backend - backend transmission interfaces + +SSYYNNOOPPSSIISS + bbaacckkeenndd job user title num-copies options _[ _f_i_l_e_n_a_m_e _] + +DDEESSCCRRIIPPTTIIOONN + The CUPS backend interface provides a standard method for + sending document files to different physical interfaces. + + Backends must be capable of reading from a filename on the + command-line or from the standard input, copying stdin to + a temporary if required by the physical interface. + + The command name (argv[0]) is set to the device URI of the + destination printer. + +EENNVVIIRROONNMMEENNTT VVAARRIIAABBLLEESS + The following environment variables are defined by the + CUPS server when executing the backend: + + CHARSET + The default text character set (typically us-ascii or + iso-8859-1). + + CONTENT_TYPE + The MIME type associated with the file (e.g. applica- + tion/postscript). + + DEVICE_URI + The device-uri associated with the printer; this is + provided for shell scripts which may not be able to + get the passed argv[0] string. + + LANG + The default language locale (typically C or en). + + PATH + The standard execution path for external programs + that may be run by the backend. + + PPD + The full pathname of the PostScript Printer Descrip- + tion (PPD) file for this printer. + + PRINTER + The name of the printer. + + RIP_CACHE + The recommended amount of memory to use for Raster + Image Processors (RIPs). + + SERVER_ROOT + The root directory of the server. + + + +22 September 1999 Common UNIX Printing System 1 + + + + + +backend(1) Easy Software Products backend(1) + + + SOFTWARE + The name and version number of the server (typically + CUPS/1.0). + + TZ + The timezone of the server. + + USER + The user executing the backend (typically lp). + +SSEEEE AALLSSOO + cupsd(8), filter(1) CUPS Software Administrators Manual, + CUPS Interface Design Description + +CCOOPPYYRRIIGGHHTT + Copyright 1993-2000 by Easy Software Products, All Rights + Reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +22 September 1999 Common UNIX Printing System 2 + + diff --git a/man/backend.man b/man/backend.man new file mode 100644 index 0000000000..dcee092880 --- /dev/null +++ b/man/backend.man @@ -0,0 +1,102 @@ +.\" +.\" "$Id: backend.man 911 2000-02-23 03:17:06Z mike $" +.\" +.\" backend man page for the Common UNIX Printing System (CUPS). +.\" +.\" Copyright 1997-2000 by Easy Software Products. +.\" +.\" These coded instructions, statements, and computer programs are the +.\" property of Easy Software Products and are protected by Federal +.\" copyright law. Distribution and use rights are outlined in the file +.\" "LICENSE.txt" which should have been included with this file. If this +.\" file is missing or damaged please contact Easy Software Products +.\" at: +.\" +.\" Attn: CUPS Licensing Information +.\" Easy Software Products +.\" 44141 Airport View Drive, Suite 204 +.\" Hollywood, Maryland 20636-3111 USA +.\" +.\" Voice: (301) 373-9603 +.\" EMail: cups-info@cups.org +.\" WWW: http://www.cups.org +.\" +.TH backend 1 "Common UNIX Printing System" "22 September 1999" "Easy Software Products" +.SH NAME +backend \- backend transmission interfaces +.SH SYNOPSIS +.B backend +job user title num-copies options +.I [ filename ] +.SH DESCRIPTION +The CUPS backend interface provides a standard method for sending document +files to different physical interfaces. +.LP +Backends must be capable of reading from a filename on the command-line +or from the standard input, copying stdin to a temporary if required by +the physical interface. +.LP +The command name (argv[0]) is set to the device URI of the destination printer. +.SH ENVIRONMENT VARIABLES +The following environment variables are defined by the CUPS server when +executing the backend: +.TP 5 +CHARSET +.br +The default text character set (typically us-ascii or iso-8859-1). +.TP 5 +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; this is provided for shell +scripts which may not be able to get the passed argv[0] string. +.TP 5 +LANG +.br +The default language locale (typically C or en). +.TP 5 +PATH +.br +The standard execution path for external programs that may be run by +the backend. +.TP 5 +PPD +.br +The full pathname of the PostScript Printer Description (PPD) file for +this printer. +.TP 5 +PRINTER +.br +The name of the printer. +.TP 5 +RIP_CACHE +.br +The recommended amount of memory to use for Raster Image Processors (RIPs). +.TP 5 +SERVER_ROOT +.br +The root directory of the server. +.TP 5 +SOFTWARE +.br +The name and version number of the server (typically CUPS/1.0). +.TP 5 +TZ +.br +The timezone of the server. +.TP 5 +USER +.br +The user executing the backend (typically lp). +.SH SEE ALSO +cupsd(8), filter(1) +CUPS Software Administrators Manual, +CUPS Interface Design Description +.SH COPYRIGHT +Copyright 1993-2000 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: backend.man 911 2000-02-23 03:17:06Z mike $". +.\" diff --git a/man/classes.conf.5 b/man/classes.conf.5 new file mode 100644 index 0000000000..53b8945e4e --- /dev/null +++ b/man/classes.conf.5 @@ -0,0 +1,66 @@ + + + +classes.conf(5) Easy Software Products classes.conf(5) + + +NNAAMMEE + classes.conf - class configuration file for cups + +DDEESSCCRRIIPPTTIIOONN + The _c_l_a_s_s_e_s_._c_o_n_f file defines the local printer classes + that are available. It is normally generated by the + _c_u_p_s_d_(_8_) program when printer classes are added or + deleted. + +SSEEEE AALLSSOO + cupsd(8), cupsd.conf(5), mime.convs(5), mime.types(5), + printers.conf(5), CUPS Software Administrators Manual, + CUPS Interface Design Description + +CCOOPPYYRRIIGGHHTT + Copyright 1993-2000 by Easy Software Products, All Rights + Reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +22 September 1999 Common UNIX Printing System 1 + + diff --git a/man/classes.conf.man b/man/classes.conf.man new file mode 100644 index 0000000000..74d8a183a6 --- /dev/null +++ b/man/classes.conf.man @@ -0,0 +1,39 @@ +.\" +.\" "$Id: classes.conf.man 911 2000-02-23 03:17:06Z mike $" +.\" +.\" classes.conf man page for the Common UNIX Printing System (CUPS). +.\" +.\" Copyright 1997-2000 by Easy Software Products. +.\" +.\" These coded instructions, statements, and computer programs are the +.\" property of Easy Software Products and are protected by Federal +.\" copyright law. Distribution and use rights are outlined in the file +.\" "LICENSE.txt" which should have been included with this file. If this +.\" file is missing or damaged please contact Easy Software Products +.\" at: +.\" +.\" Attn: CUPS Licensing Information +.\" Easy Software Products +.\" 44141 Airport View Drive, Suite 204 +.\" Hollywood, Maryland 20636-3111 USA +.\" +.\" Voice: (301) 373-9603 +.\" EMail: cups-info@cups.org +.\" WWW: http://www.cups.org +.\" +.TH classes.conf 5 "Common UNIX Printing System" "22 September 1999" "Easy Software Products" +.SH NAME +classes.conf \- class configuration file for cups +.SH DESCRIPTION +The \fIclasses.conf\fR file defines the local printer classes that are +available. It is normally generated by the \fIcupsd(8)\fR program when +printer classes are added or deleted. +.SH SEE ALSO +cupsd(8), cupsd.conf(5), mime.convs(5), mime.types(5), printers.conf(5), +CUPS Software Administrators Manual, +CUPS Interface Design Description +.SH COPYRIGHT +Copyright 1993-2000 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: classes.conf.man 911 2000-02-23 03:17:06Z mike $". +.\" diff --git a/man/cupsd.8 b/man/cupsd.8 new file mode 100644 index 0000000000..8c2c15eeb9 --- /dev/null +++ b/man/cupsd.8 @@ -0,0 +1,66 @@ + + + +cupsd(8) Easy Software Products cupsd(8) + + +NNAAMMEE + cupsd - common unix printing system daemon + +SSYYNNOOPPSSIISS + ccuuppssdd _[ _-_c _c_o_n_f_i_g_-_f_i_l_e _] + +DDEESSCCRRIIPPTTIIOONN + _c_u_p_s_d is the scheduler for the Common UNIX Printing Sys- + tem. It implements a printing system based upon the Inter- + net Printing Protocol, version 1.0. If no options are + specified on the command-line then the default configura- + tion file (usually _/_v_a_r_/_c_u_p_s_/_c_o_n_f_/_c_u_p_s_d_._c_o_n_f) will be + used. + +CCOOMMPPAATTIIBBIILLIITTYY + _c_u_p_s_d implements all of the required IPP/1.0 attributes + and operations. It also implements optional operation set + 1 and several CUPS-specific administation operations. + +SSEEEE AALLSSOO + backend(1), classes.conf(5), cupsd.conf(5), filter(1), + mime.convs(5), mime.types(5), printers.conf(5), CUPS Soft- + ware Administrators Manual, CUPS Interface Design Descrip- + tion + +CCOOPPYYRRIIGGHHTT + Copyright 1993-2000 by Easy Software Products, All Rights + Reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +22 September 1999 Common UNIX Printing System 1 + + diff --git a/man/cupsd.conf.5 b/man/cupsd.conf.5 new file mode 100644 index 0000000000..da09c6d2ec --- /dev/null +++ b/man/cupsd.conf.5 @@ -0,0 +1,66 @@ + + + +cupsd.conf(5) Easy Software Products cupsd.conf(5) + + +NNAAMMEE + cupsd.conf - server configuration file for cups + +DDEESSCCRRIIPPTTIIOONN + The _c_u_p_s_d_._c_o_n_f file configures the CUPS scheduler, + _c_u_p_s_d_(_8_). + +SSEEEE AALLSSOO + classes.conf(5), cupsd(8), mime.convs(5), mime.types(5), + printers.conf(5), CUPS Software Administrators Manual, + CUPS Interface Design Description + +CCOOPPYYRRIIGGHHTT + Copyright 1993-2000 by Easy Software Products, All Rights + Reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +22 September 1999 Common UNIX Printing System 1 + + diff --git a/man/cupsd.conf.man b/man/cupsd.conf.man new file mode 100644 index 0000000000..5c1ecf59ca --- /dev/null +++ b/man/cupsd.conf.man @@ -0,0 +1,37 @@ +.\" +.\" "$Id: cupsd.conf.man 911 2000-02-23 03:17:06Z mike $" +.\" +.\" cupsd.conf man page for the Common UNIX Printing System (CUPS). +.\" +.\" Copyright 1997-2000 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-2000 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: cupsd.conf.man 911 2000-02-23 03:17:06Z mike $". +.\" diff --git a/man/cupsd.man b/man/cupsd.man new file mode 100644 index 0000000000..4b5616b3d6 --- /dev/null +++ b/man/cupsd.man @@ -0,0 +1,48 @@ +.\" +.\" "$Id: cupsd.man 911 2000-02-23 03:17:06Z mike $" +.\" +.\" cupsd man page for the Common UNIX Printing System (CUPS). +.\" +.\" Copyright 1997-2000 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-2000 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: cupsd.man 911 2000-02-23 03:17:06Z mike $". +.\" diff --git a/man/enable.8 b/man/enable.8 new file mode 100644 index 0000000000..dbf4a587d4 --- /dev/null +++ b/man/enable.8 @@ -0,0 +1,66 @@ + + + +enable(8) Easy Software Products enable(8) + + +NNAAMMEE + disable, enable - stop/start printers and classes + +SSYYNNOOPPSSIISS + ddiissaabbllee [ -c ] [ -h _s_e_r_v_e_r ] [ -r [ _r_e_a_s_o_n ] ] destina- + tion(s) + eennaabbllee destination(s) + +DDEESSCCRRIIPPTTIIOONN + _e_n_a_b_l_e starts the named printers or classes. + + _d_i_s_a_b_l_e stops the named printers or classes. The follow- + ing options may be used: + + -c + Cancels all jobs on the named destination. + + -r [ _r_e_a_s_o_n ] + Sets the message associated with the stopped state. + If no reason is specified then the message is set to + "Reason Unknown". + +CCOOMMPPAATTIIBBIILLIITTYY + The CUPS versions of _d_i_s_a_b_l_e and _e_n_a_b_l_e 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. + +SSEEEE AALLSSOO + accept(8), cancel(1), lp(1), lpadmin(8), lpstat(1), + reject(8), CUPS Software Administrators Manual + +CCOOPPYYRRIIGGHHTT + Copyright 1993-2000 by Easy Software Products, All Rights + Reserved. + + + + + + + + + + + + + + + + + + + + + + +22 September 1999 Common UNIX Printing System 1 + + diff --git a/man/enable.man b/man/enable.man new file mode 100644 index 0000000000..fd9e3b881e --- /dev/null +++ b/man/enable.man @@ -0,0 +1,64 @@ +.\" +.\" "$Id: enable.man 911 2000-02-23 03:17:06Z mike $" +.\" +.\" enable/disable man page for the Common UNIX Printing System (CUPS). +.\" +.\" Copyright 1997-2000 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-2000 by Easy Software Products, All Rights Reserved. + +.\" +.\" End of "$Id: enable.man 911 2000-02-23 03:17:06Z mike $". +.\" diff --git a/man/filter.1 b/man/filter.1 new file mode 100644 index 0000000000..d6d3cb8567 --- /dev/null +++ b/man/filter.1 @@ -0,0 +1,132 @@ + + + +filter(1) Easy Software Products filter(1) + + +NNAAMMEE + filter - file conversion filter interfaces + +SSYYNNOOPPSSIISS + ffiilltteerr job user title num-copies options _[ _f_i_l_e_n_a_m_e _] + +DDEESSCCRRIIPPTTIIOONN + 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. + + 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. + + The command name (argv[0]) is set to the name of the des- + tination printer. + +EENNVVIIRROONNMMEENNTT VVAARRIIAABBLLEESS + The following environment variables are defined by the + CUPS server when executing each filter: + + CHARSET + The default text character set (typically us-ascii or + iso-8859-1). + + CONTENT_TYPE + The MIME type associated with the file (e.g. applica- + tion/postscript). + + DEVICE_URI + The device-uri associated with the printer. + + LANG + The default language locale (typically C or en). + + PATH + The standard execution path for external programs + that may be run by the filter. + + PPD + The full pathname of the PostScript Printer Descrip- + tion (PPD) file for this printer. + + PRINTER + The name of the printer; this is provided for shell + scripts which may not be able to get the passed + argv[0] string. + + RIP_CACHE + The recommended amount of memory to use for Raster + Image Processors (RIPs). + + + +22 September 1999 Common UNIX Printing System 1 + + + + + +filter(1) Easy Software Products filter(1) + + + SERVER_ROOT + The root directory of the server. + + SOFTWARE + The name and version number of the server (typically + CUPS/1.0). + + TZ + The timezone of the server. + + USER + The user executing the filter (typically lp). + +CCOOMMPPAATTIIBBIILLIITTYY + 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 inter- + face script will be provided via the llppaaddmmiinn((88)) command + using the _-_i option. + +SSEEEE AALLSSOO + backend(1), cupsd(8), CUPS Software Administrators Manual, + CUPS Interface Design Description + +CCOOPPYYRRIIGGHHTT + Copyright 1993-2000 by Easy Software Products, All Rights + Reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +22 September 1999 Common UNIX Printing System 2 + + diff --git a/man/filter.man b/man/filter.man new file mode 100644 index 0000000000..b32c8c688e --- /dev/null +++ b/man/filter.man @@ -0,0 +1,108 @@ +.\" +.\" "$Id: filter.man 911 2000-02-23 03:17:06Z mike $" +.\" +.\" filter man page for the Common UNIX Printing System (CUPS). +.\" +.\" Copyright 1997-2000 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-2000 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: filter.man 911 2000-02-23 03:17:06Z mike $". +.\" diff --git a/man/lp.1 b/man/lp.1 new file mode 100644 index 0000000000..e01fca04ff --- /dev/null +++ b/man/lp.1 @@ -0,0 +1,132 @@ + + + +lp(1) Easy Software Products lp(1) + + +NNAAMMEE + lp - print files + cancel - cancel jobs + +SSYYNNOOPPSSIISS + llpp [ -c ] [ -d _d_e_s_t_i_n_a_t_i_o_n ] [ -h _s_e_r_v_e_r ] [ -m ] [ -n + _n_u_m_-_c_o_p_i_e_s [ -o _o_p_t_i_o_n ] [ -p/q _p_r_i_o_r_i_t_y ] [ -s ] [ -t + _t_i_t_l_e ] [ _f_i_l_e_(_s_) ] + ccaanncceell [ -a ] [ -h _s_e_r_v_e_r ] [ _i_d ] [ _d_e_s_t_i_n_a_t_i_o_n ] [ _d_e_s_- + _t_i_n_a_t_i_o_n_-_i_d ] + +DDEESSCCRRIIPPTTIIOONN + llpp submits files for printing. + + ccaanncceell cancels existing print jobs. The _-_a option will + remove all jobs from the specified destination. + +OOPPTTIIOONNSS + The following options are recognized by llpp: + + -d _d_e_s_t_i_n_a_t_i_o_n + Prints files to the named printer. + + -h _h_o_s_t_n_a_m_e + Specifies the print server hostname. The default is + "localhost" or the value of the CUPS_SERVER environ- + ment variable. + + -m + Send email when the job is completed (ignored in CUPS + 1.0.) + + -n _c_o_p_i_e_s + Sets the number of copies to print from 1 to 100. + + -o _o_p_t_i_o_n + Sets a job option. + + -p/q _p_r_i_o_r_i_t_y + Sets the job priority from 1 (lowest) to 100 (high- + est). The default priority is 50. + + -s + Do not report the resulting job IDs (silent mode.) + + -t _n_a_m_e + Sets the job name. + +CCOOMMPPAATTIIBBIILLIITTYY + 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 nnoott case-sensitive. + + The "m" option is not functional in CUPS 1.0. + + + +9 September 1999 Common UNIX Printing System 1 + + + + + +lp(1) Easy Software Products lp(1) + + +SSEEEE AALLSSOO + lpstat(1), CUPS Software Users Manual + +CCOOPPYYRRIIGGHHTT + Copyright 1993-2000 by Easy Software Products, All Rights + Reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +9 September 1999 Common UNIX Printing System 2 + + diff --git a/man/lp.man b/man/lp.man new file mode 100644 index 0000000000..cc5a5f8eff --- /dev/null +++ b/man/lp.man @@ -0,0 +1,111 @@ +.\" +.\" "$Id: lp.man 911 2000-02-23 03:17:06Z mike $" +.\" +.\" lp/cancel man page for the Common UNIX Printing System (CUPS). +.\" +.\" Copyright 1997-2000 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-2000 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: lp.man 911 2000-02-23 03:17:06Z mike $". +.\" diff --git a/man/lpadmin.8 b/man/lpadmin.8 new file mode 100644 index 0000000000..6504b1c483 --- /dev/null +++ b/man/lpadmin.8 @@ -0,0 +1,132 @@ + + + +lpadmin(8) Easy Software Products lpadmin(8) + + +NNAAMMEE + lpadmin - configure cups printers and classes + +SSYYNNOOPPSSIISS + llppaaddmmiinn [ -h _s_e_r_v_e_r ] -d _d_e_s_t_i_n_a_t_i_o_n + llppaaddmmiinn [ -h _s_e_r_v_e_r ] -p _p_r_i_n_t_e_r _o_p_t_i_o_n_(_s_) + llppaaddmmiinn [ -h _s_e_r_v_e_r ] -x _d_e_s_t_i_n_a_t_i_o_n + +DDEESSCCRRIIPPTTIIOONN + _l_p_a_d_m_i_n configures printer and class queues provided by + CUPS. It can also be used to set the system default + printer or class. + + The first form of the command sets the default printer or + class to _d_e_s_t_i_n_a_t_i_o_n. Subsequent print jobs submitted via + the _l_p_(_1_) or _l_p_r_(_1_) commands will use this destination + unless the user specifies otherwise. + + The second form of the command configures the named + printer. The additional options are described below. + + The third form of the command deletes the printer or class + _d_e_s_t_i_n_a_t_i_o_n. Any jobs that are pending for the destina- + tion will be removed and any job that is currently printed + will be aborted. + +CCOONNFFIIGGUURRAATTIIOONN OOPPTTIIOONNSS + The following options are recognized when configuring a + printer queue: + + -c _c_l_a_s_s + Adds the named _p_r_i_n_t_e_r to _c_l_a_s_s. If _c_l_a_s_s does not + exist it is created automatically. + + -i _i_n_t_e_r_f_a_c_e + Sets a System V style interface script for the + printer. This option cannot be specified with the _-_P + option (PPD file) and is intended for providing sup- + port for legacy printer drivers. + + -m _m_o_d_e_l + Sets a standard System V interface script or PPD file + from the model directory. + + -r _c_l_a_s_s + Removes the named _p_r_i_n_t_e_r from _c_l_a_s_s. If the result- + ing class becomes empty it is removed. + + -v _d_e_v_i_c_e_-_u_r_i + Sets the _d_e_v_i_c_e_-_u_r_i attribute of the printer queue. + If _d_e_v_i_c_e_-_u_r_i is a filename it is automatically con- + verted to the form ffiillee:://ffiillee//nnaammee. + + + + + +22 September 1999 Common UNIX Printing System 1 + + + + + +lpadmin(8) Easy Software Products lpadmin(8) + + + -D _i_n_f_o + Provides a textual description of the printer. + + -E + Enables the printer and accepts jobs; this is the + same as running the _a_c_c_e_p_t_(_8_) and _e_n_a_b_l_e_(_8_) programs + on the printer. + + -L _l_o_c_a_t_i_o_n + Provides a textual location of the printer. + + -P _p_p_d_-_f_i_l_e + Specifies a PostScript Printer Description file to + use with the printer. If specified, this option over- + rides the _-_i option (interface script). + +CCOOMMPPAATTIIBBIILLIITTYY + 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 nnoott case-sensitive. + Finally, the CUPS version of _l_p_a_d_m_i_n may ask the user for + an access password depending on the printing system con- + figuration. This differs from the System V version which + requires the root user to execute this command. + +LLIIMMIITTAATTIIOONNSS + The CUPS version of _l_p_a_d_m_i_n does not support all of the + System V or Solaris printing system configuration options. + +SSEEEE AALLSSOO + accept(8), cancel(1), disable(8), enable(8), lp(1), + lpstat(1), reject(8), CUPS Software Administrators Manual + +CCOOPPYYRRIIGGHHTT + Copyright 1993-2000 by Easy Software Products, All Rights + Reserved. + + + + + + + + + + + + + + + + + + + + + +22 September 1999 Common UNIX Printing System 2 + + diff --git a/man/lpadmin.man b/man/lpadmin.man new file mode 100644 index 0000000000..1b3e1f81cd --- /dev/null +++ b/man/lpadmin.man @@ -0,0 +1,124 @@ +.\" +.\" "$Id: lpadmin.man 911 2000-02-23 03:17:06Z mike $" +.\" +.\" lpadmin man page for the Common UNIX Printing System (CUPS). +.\" +.\" Copyright 1997-2000 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-2000 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: lpadmin.man 911 2000-02-23 03:17:06Z mike $". +.\" diff --git a/man/lpc.8 b/man/lpc.8 new file mode 100644 index 0000000000..0f77d52d8d --- /dev/null +++ b/man/lpc.8 @@ -0,0 +1,66 @@ + + + +lpc(8) Easy Software Products lpc(8) + + +NNAAMMEE + lpc - line printer control program + +SSYYNNOOPPSSIISS + llppcc [ _c_o_m_m_a_n_d [ _p_a_r_a_m_e_t_e_r_(_s_) ] ] + +DDEESSCCRRIIPPTTIIOONN + _l_p_c provides limited control over printer and class queues + provided by CUPS. It can also be used to query the state + of queues. + + If no command is specified on the command-line, lpc will + display a prompt and accept commands from the standard + input. + +CCOOMMMMAANNDDSS + The _l_p_c program accepts a subset of commands accepted by + the Berkeley _l_p_c program of the same name: + + _e_x_i_t + Exits the command interpreter. + + help _[_c_o_m_m_a_n_d_] + Displays a short help message. + + quit + Exits the command interpreter. + + status _[_q_u_e_u_e_] + Displays the status of one or more printer or class + queues. + + ? _[_c_o_m_m_a_n_d_] + Display a short help message. + +LLIIMMIITTAATTIIOONNSS + Since _l_p_c is geared towards the Berkeley printing system, + it is impossible to use _l_p_c to configure printer or class + queues provided by CUPS. To configure printer or class + queues you must use the _l_p_a_d_m_i_n_(_8_) command or another + CUPS-compatible client with that functionality. + +CCOOMMPPAATTIIBBIILLIITTYY + The CUPS version of _l_p_c does not implement all of the + standard Berkeley commands. + +SSEEEE AALLSSOO + accept(8), cancel(1), disable(8), enable(8), lp(1), + lpr(1), lprm(1), lpstat(1), reject(8), CUPS Software + Administrators Manual + +CCOOPPYYRRIIGGHHTT + Copyright 1993-2000 by Easy Software Products, All Rights + Reserved. + + + +22 September 1999 Common UNIX Printing System 1 + + diff --git a/man/lpc.man b/man/lpc.man new file mode 100644 index 0000000000..6e357b7924 --- /dev/null +++ b/man/lpc.man @@ -0,0 +1,79 @@ +.\" +.\" "$Id: lpc.man 911 2000-02-23 03:17:06Z mike $" +.\" +.\" lpc man page for the Common UNIX Printing System (CUPS). +.\" +.\" Copyright 1997-2000 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-2000 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: lpc.man 911 2000-02-23 03:17:06Z mike $". +.\" diff --git a/man/lpq.1 b/man/lpq.1 new file mode 100644 index 0000000000..b153b687e4 --- /dev/null +++ b/man/lpq.1 @@ -0,0 +1,66 @@ + + + +lpq(1) Easy Software Products lpq(1) + + +NNAAMMEE + lpq - show printer queue status + +SSYYNNOOPPSSIISS + llppqq [ -P _d_e_s_t ] [ -l ] [ _+_i_n_t_e_r_v_a_l ] + +DDEESSCCRRIIPPTTIIOONN + _l_p_q 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. + + The _i_n_t_e_r_v_a_l option allows you to continuously report the + jobs in the queue until the queue is empty; the list of + jobs is show one every _i_n_t_e_r_v_a_l seconds. + + The _-_l option requests a more verbose reporting format. + +SSEEEE AALLSSOO + cancel(1), lp(1), lpr(1), lprm(1), lpstat(1) + CUPS Software Users Manual + +CCOOPPYYRRIIGGHHTT + Copyright 1993-2000 by Easy Software Products, All Rights + Reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +7 December 1999 Common UNIX Printing System 1 + + diff --git a/man/lpq.man b/man/lpq.man new file mode 100644 index 0000000000..2879a0fcb2 --- /dev/null +++ b/man/lpq.man @@ -0,0 +1,52 @@ +.\" +.\" "$Id: lpq.man 911 2000-02-23 03:17:06Z mike $" +.\" +.\" lpq man page for the Common UNIX Printing System (CUPS). +.\" +.\" Copyright 1997-2000 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-2000 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: lpq.man 911 2000-02-23 03:17:06Z mike $". +.\" diff --git a/man/lpr.1 b/man/lpr.1 new file mode 100644 index 0000000000..7597c5e7b5 --- /dev/null +++ b/man/lpr.1 @@ -0,0 +1,132 @@ + + + +lpr(1) Easy Software Products lpr(1) + + +NNAAMMEE + lpr - print files + +SSYYNNOOPPSSIISS + llpprr [ -P _d_e_s_t_i_n_a_t_i_o_n ] [ -# _n_u_m_-_c_o_p_i_e_s [ -l ] [ -o _o_p_t_i_o_n + ] [ -p] [ -r ] [ -C/J/T _t_i_t_l_e ] [ _f_i_l_e_(_s_) ] + +DDEESSCCRRIIPPTTIIOONN + llpprr 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 llpprr reads the print file + from the standard input. + +OOPPTTIIOONNSS + The following options are recognized by llpprr: + + -P _d_e_s_t_i_n_a_t_i_o_n + Prints files to the named printer. + + -# _c_o_p_i_e_s + Sets the number of copies to print from 1 to 100. + + -C _n_a_m_e + Sets the job name. + + -J _n_a_m_e + Sets the job name. + + -T _n_a_m_e + Sets the job name. + + -l + Specifies that the print file is already formatted + for the destination and should be sent without fil- + tering. This option is equivalent to "-oraw". + + -o _o_p_t_i_o_n + Sets a job option. + + -p + 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. + + -r + Specifies that the named print files should be + deleted after printing them. + +CCOOMMPPAATTIIBBIILLIITTYY + The "c", "d", "f", "g", "i", "m", "n", "t", "v", and "w" + options are not supported by CUPS and will produce a + + + +9 September 1999 Common UNIX Printing System 1 + + + + + +lpr(1) Easy Software Products lpr(1) + + + warning message if used. + +SSEEEE AALLSSOO + cancel(1), lp(1), lpstat(1), CUPS Software Users Manual + +CCOOPPYYRRIIGGHHTT + Copyright 1993-2000 by Easy Software Products, All Rights + Reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +9 September 1999 Common UNIX Printing System 2 + + diff --git a/man/lpr.man b/man/lpr.man new file mode 100644 index 0000000000..ec91d456e0 --- /dev/null +++ b/man/lpr.man @@ -0,0 +1,96 @@ +.\" +.\" "$Id: lpr.man 911 2000-02-23 03:17:06Z mike $" +.\" +.\" lpr man page for the Common UNIX Printing System (CUPS). +.\" +.\" Copyright 1997-2000 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-2000 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: lpr.man 911 2000-02-23 03:17:06Z mike $". +.\" diff --git a/man/lprm.1 b/man/lprm.1 new file mode 100644 index 0000000000..475461b584 --- /dev/null +++ b/man/lprm.1 @@ -0,0 +1,66 @@ + + + +lprm(1) Easy Software Products lprm(1) + + +NNAAMMEE + lprm - cancel print jobs + +SSYYNNOOPPSSIISS + llpprrmm [ - ] [ -P _d_e_s_t_i_n_a_t_i_o_n ] [ _j_o_b _I_D_(_s_) ] + +DDEESSCCRRIIPPTTIIOONN + llpprrmm cancels print jobs that have been queued for print- + ing. The _-_P option specifies the destination printer or + class. + + 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 _- + option to cancel all jobs. + +CCOOMMPPAATTIIBBIILLIITTYY + The CUPS version of _l_p_r_m is compatible with the standard + Berkeley _l_p_r_m command. + +SSEEEE AALLSSOO + cancel(1), lp(1), lpstat(1), lpr(1), CUPS Software Users + Manual + +CCOOPPYYRRIIGGHHTT + Copyright 1993-2000 by Easy Software Products, All Rights + Reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +22 September 1999 Common UNIX Printing System 1 + + diff --git a/man/lprm.man b/man/lprm.man new file mode 100644 index 0000000000..5c3a58aa83 --- /dev/null +++ b/man/lprm.man @@ -0,0 +1,51 @@ +.\" +.\" "$Id: lprm.man 911 2000-02-23 03:17:06Z mike $" +.\" +.\" lprm man page for the Common UNIX Printing System (CUPS). +.\" +.\" Copyright 1997-2000 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-2000 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: lprm.man 911 2000-02-23 03:17:06Z mike $". +.\" diff --git a/man/lpstat.1 b/man/lpstat.1 new file mode 100644 index 0000000000..ac5c8f42c7 --- /dev/null +++ b/man/lpstat.1 @@ -0,0 +1,132 @@ + + + +lpstat(1) Easy Software Products lpstat(1) + + +NNAAMMEE + lpstat - print cups status information + +SSYYNNOOPPSSIISS + llppssttaatt [ -a [ _d_e_s_t_i_n_a_t_i_o_n_(_s_) ] ] [ -c [ _c_l_a_s_s_(_e_s_) ] ] [ -d + ] [ -h _s_e_r_v_e_r ] [ -o [ _d_e_s_t_i_n_a_t_i_o_n_(_s_) ] ] [ -p [ + _p_r_i_n_t_e_r_(_s_) ] ] [ -r ] [ -s ] [ -t ] [ -u [ _u_s_e_r_(_s_) ] ] [ + -v [ _p_r_i_n_t_e_r_(_s_) ] ] + +DDEESSCCRRIIPPTTIIOONN + llppssttaatt displays status information about the current + classes, jobs, and printers. When run with no arguments, + llppssttaatt will list jobs queued by the user. Other options + include: + + -a [_p_r_i_n_t_e_r_(_s_)] + Shows the accepting state of printer queues. If no + printers are specified then all printers are listed. + + -c [_c_l_a_s_s_(_e_s_)] + Shows the printer classes and the printers that + belong to them. If no classes are specified then all + classes are listed. + + -d + Shows the current default destination. + + -h _s_e_r_v_e_r + Specifies the CUPS server to communicate with. + + -o [_d_e_s_t_i_n_a_t_i_o_n_(_s_)] + Shows the jobs queue on the specified destinations. + If no destinations are specified all jobs are shown. + + -p [_p_r_i_n_t_e_r_(_s_)] + Shows the printers and whether or not they are + enabled for printing. If no printers are specified + then all printers are listed. + + -r + Shows whether or not the CUPS server is running. + + -s + 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. + + -t + Shows all status information. This is equivalent to + using the "-r", "-d", "-c", "-d", "-v", "-a", "-p", + and "-o" options. + + + + +22 September 1999 Common UNIX Printing System 1 + + + + + +lpstat(1) Easy Software Products lpstat(1) + + + -u [_u_s_e_r_(_s_)] + Shows a list of print jobs queued by the specified + users. If no users are specified, lists the jobs + queued by the current user. + + -v [_p_r_i_n_t_e_r_(_s_)] + Shows the printers and what device they are attached + to. If no printers are specified then all printers + are listed. + +CCOOMMPPAATTIIBBIILLIITTYY + 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 nnoott case-sensitive. + + The "-h" option is not a standard System V option. + +SSEEEE AALLSSOO + cancel(1), lp(1), CUPS Software Users Manual + +CCOOPPYYRRIIGGHHTT + Copyright 1993-2000 by Easy Software Products, All Rights + Reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +22 September 1999 Common UNIX Printing System 2 + + diff --git a/man/lpstat.man b/man/lpstat.man new file mode 100644 index 0000000000..a6af5296ae --- /dev/null +++ b/man/lpstat.man @@ -0,0 +1,115 @@ +.\" +.\" "$Id: lpstat.man 911 2000-02-23 03:17:06Z mike $" +.\" +.\" lpstat man page for the Common UNIX Printing System (CUPS). +.\" +.\" Copyright 1997-2000 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-2000 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: lpstat.man 911 2000-02-23 03:17:06Z mike $". +.\" diff --git a/man/mime.convs.5 b/man/mime.convs.5 new file mode 100644 index 0000000000..5e70155ffc --- /dev/null +++ b/man/mime.convs.5 @@ -0,0 +1,66 @@ + + + +mime.convs(5) Easy Software Products mime.convs(5) + + +NNAAMMEE + mime.convs - mime type conversion file for cups + +DDEESSCCRRIIPPTTIIOONN + The _m_i_m_e_._c_o_n_v_s file defines the filters that are available + for converting files from one format to another. The stan- + dard filters support text, PDF, PostScript, HP-GL/2, and + many types of image files. + + Additional filters can be added to the _m_i_m_e_._c_o_n_v_s file or + to other files in the configuration directory + (//vvaarr//ccuuppss//ccoonnff) with the extension ".convs". + +SSEEEE AALLSSOO + classes.conf(5), cupsd(8), cupsd.conf(5), mime.types(5), + printers.conf(5), CUPS Software Administrators Manual, + CUPS Interface Design Description + +CCOOPPYYRRIIGGHHTT + Copyright 1993-2000 by Easy Software Products, All Rights + Reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +22 September 1999 Common UNIX Printing System 1 + + diff --git a/man/mime.convs.man b/man/mime.convs.man new file mode 100644 index 0000000000..e764f9e6f8 --- /dev/null +++ b/man/mime.convs.man @@ -0,0 +1,43 @@ +.\" +.\" "$Id: mime.convs.man 911 2000-02-23 03:17:06Z mike $" +.\" +.\" mime.convs man page for the Common UNIX Printing System (CUPS). +.\" +.\" Copyright 1997-2000 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-2000 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: mime.convs.man 911 2000-02-23 03:17:06Z mike $". +.\" diff --git a/man/mime.types.5 b/man/mime.types.5 new file mode 100644 index 0000000000..8fdc6b9660 --- /dev/null +++ b/man/mime.types.5 @@ -0,0 +1,66 @@ + + + +mime.types(5) Easy Software Products mime.types(5) + + +NNAAMMEE + mime.types - mime type description file for cups + +DDEESSCCRRIIPPTTIIOONN + The _m_i_m_e_._t_y_p_e_s file defines the recognized file types. + + Additional file types can be added to _m_i_m_e_._t_y_p_e_s or in + additional files in the configuration directory + //vvaarr//ccuuppss//ccoonnff with the extension ".types". + +SSEEEE AALLSSOO + classes.conf(5), cupsd(8), cupsd.conf(5), mime.convs(5), + printers.conf(5), CUPS Software Administrators Manual, + CUPS Interface Design Description + +CCOOPPYYRRIIGGHHTT + Copyright 1993-2000 by Easy Software Products, All Rights + Reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +22 September 1999 Common UNIX Printing System 1 + + diff --git a/man/mime.types.man b/man/mime.types.man new file mode 100644 index 0000000000..049302455a --- /dev/null +++ b/man/mime.types.man @@ -0,0 +1,40 @@ +.\" +.\" "$Id: mime.types.man 911 2000-02-23 03:17:06Z mike $" +.\" +.\" mime.types man page for the Common UNIX Printing System (CUPS). +.\" +.\" Copyright 1997-2000 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-2000 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: mime.types.man 911 2000-02-23 03:17:06Z mike $". +.\" diff --git a/man/printers.conf.5 b/man/printers.conf.5 new file mode 100644 index 0000000000..46456d1ea1 --- /dev/null +++ b/man/printers.conf.5 @@ -0,0 +1,66 @@ + + + +printers.conf(5) Easy Software Products printers.conf(5) + + +NNAAMMEE + printers.conf - printer configuration file for cups + +DDEESSCCRRIIPPTTIIOONN + The _p_r_i_n_t_e_r_s_._c_o_n_f file defines the local printers that are + available. It is normally generated by the _c_u_p_s_d_(_8_) pro- + gram when printers are added, deleted, or modified. + +SSEEEE AALLSSOO + classes.conf(5), cupsd(8), cupsd.conf(5), mime.convs(5), + mime.types(5), CUPS Software Administrators Manual, CUPS + Interface Design Description + +CCOOPPYYRRIIGGHHTT + Copyright 1993-2000 by Easy Software Products, All Rights + Reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +22 September 1999 Common UNIX Printing System 1 + + diff --git a/man/printers.conf.man b/man/printers.conf.man new file mode 100644 index 0000000000..eae17b7041 --- /dev/null +++ b/man/printers.conf.man @@ -0,0 +1,39 @@ +.\" +.\" "$Id: printers.conf.man 911 2000-02-23 03:17:06Z mike $" +.\" +.\" printers.conf man page for the Common UNIX Printing System (CUPS). +.\" +.\" Copyright 1997-2000 by Easy Software Products. +.\" +.\" These coded instructions, statements, and computer programs are the +.\" property of Easy Software Products and are protected by Federal +.\" copyright law. Distribution and use rights are outlined in the file +.\" "LICENSE.txt" which should have been included with this file. If this +.\" file is missing or damaged please contact Easy Software Products +.\" at: +.\" +.\" Attn: CUPS Licensing Information +.\" Easy Software Products +.\" 44141 Airport View Drive, Suite 204 +.\" Hollywood, Maryland 20636-3111 USA +.\" +.\" Voice: (301) 373-9603 +.\" EMail: cups-info@cups.org +.\" WWW: http://www.cups.org +.\" +.TH printers.conf 5 "Common UNIX Printing System" "22 September 1999" "Easy Software Products" +.SH NAME +printers.conf \- printer configuration file for cups +.SH DESCRIPTION +The \fIprinters.conf\fR file defines the local printers that are +available. It is normally generated by the \fIcupsd(8)\fR program when +printers are added, deleted, or modified. +.SH SEE ALSO +classes.conf(5), cupsd(8), cupsd.conf(5), mime.convs(5), mime.types(5), +CUPS Software Administrators Manual, +CUPS Interface Design Description +.SH COPYRIGHT +Copyright 1993-2000 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: printers.conf.man 911 2000-02-23 03:17:06Z mike $". +.\" diff --git a/ppd/Makefile b/ppd/Makefile new file mode 100644 index 0000000000..511b476f65 --- /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 stcolor.ppd stphoto.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..c21a28887c --- /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-2000 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 +*% +*FormatVersion: "4.3" +*FileVersion: "1.1" +*LanguageVersion: English +*LanguageEncoding: ISOLatin1 +*PCFileName: "DESKJET.PPD" +*Manufacturer: "ESP" +*Product: "(CUPS v1.1)" +*cupsVersion: 1.1 +*cupsManualCopies: True +*cupsFilter: "application/vnd.cups-raster 0 rastertohp" +*ModelName: "HP DeskJet Series" +*ShortNickName: "HP DeskJet Series" +*NickName: "HP DeskJet Series CUPS v1.1" +*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..ca9e3a6317 --- /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-2000 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 +*% +*FormatVersion: "4.3" +*FileVersion: "1.1" +*LanguageVersion: English +*LanguageEncoding: ISOLatin1 +*PCFileName: "LASERJET.PPD" +*Manufacturer: "ESP" +*Product: "(CUPS v1.1)" +*cupsVersion: 1.1 +*cupsManualCopies: False +*cupsFilter: "application/vnd.cups-raster 0 rastertohp" +*ModelName: "HP LaserJet Series" +*ShortNickName: "HP LaserJet Series" +*NickName: "HP LaserJet Series CUPS v1.1" +*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/ppd/stcolor.ppd b/ppd/stcolor.ppd new file mode 100644 index 0000000000..7ecbef95d9 --- /dev/null +++ b/ppd/stcolor.ppd @@ -0,0 +1,131 @@ +*PPD-Adobe: "4.3" +*% +*% "$Id$" +*% +*% Sample EPSON Stylus Color driver PPD file for the Common UNIX Printing +*% System (CUPS). +*% +*% Copyright 1997-2000 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 +*% +*FormatVersion: "4.3" +*FileVersion: "1.1" +*LanguageVersion: English +*LanguageEncoding: ISOLatin1 +*PCFileName: "STCOLOR.PPD" +*Manufacturer: "ESP" +*Product: "(CUPS v1.1)" +*cupsVersion: 1.1 +*cupsManualCopies: True +*cupsFilter: "application/vnd.cups-raster 0 rastertoepson" +*cupsColorProfile 180dpi/-: "1.0 1.0 1.0 0.0 -0.2 -0.4 1.0 0.0 -0.2 0.0 1.0" +*cupsColorProfile 360dpi/-: "1.0 1.5 1.0 0.0 -0.2 -0.4 1.0 0.0 -0.2 0.0 1.0" +*cupsColorProfile 720dpi/-: "1.0 2.5 1.0 0.0 -0.2 -0.4 1.0 0.0 -0.2 0.0 1.0" +*ModelName: "EPSON Stylus Color Series" +*ShortNickName: "EPSON Stylus Color Series" +*NickName: "EPSON Stylus Color Series CUPS v1.1" +*PSVersion: "(2017.000) 0" +*LanguageLevel: "2" +*ColorDevice: True +*DefaultColorSpace: RGB +*FileSystem: False +*Throughput: "1" +*LandscapeOrientation: Plus90 +*VariablePaperSize: False +*TTRasterizer: Type42 + +*OpenUI *PageSize/Media Size: PickOne +*OrderDependency: 10 AnySetup *PageSize +*DefaultPageSize: Letter +*PageSize Letter: "<>setpagedevice" +*PageSize Legal: "<>setpagedevice" +*PageSize A4: "<>setpagedevice" +*CloseUI: *PageSize + +*OpenUI *PageRegion: PickOne +*OrderDependency: 10 AnySetup *PageRegion +*DefaultPageRegion: Letter +*PageRegion Letter: "<>setpagedevice" +*PageRegion Legal: "<>setpagedevice" +*PageRegion A4: "<>setpagedevice" +*CloseUI: *PageRegion + +*DefaultImageableArea: Letter +*ImageableArea Letter: "8.60 39.60 603.40 766.49" +*ImageableArea Legal: "8.60 39.60 603.40 982.49" +*ImageableArea A4: "8.60 39.60 586.40 816.49" + +*DefaultPaperDimension: Letter +*PaperDimension Letter: "612 792" +*PaperDimension Legal: "612 1008" +*PaperDimension A4: "595 842" + +*OpenUI *Resolution/Output Resolution: PickOne +*OrderDependency: 20 AnySetup *Resolution +*DefaultResolution: 360dpi +*Resolution 180dpi/180 DPI: "<>setpagedevice" +*Resolution 360dpi/360 DPI: "<>setpagedevice{0.6666 exp}bind settransfer" +*Resolution 720dpi/720 DPI: "<>setpagedevice{0.4 exp}bind settransfer" +*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/stphoto.ppd b/ppd/stphoto.ppd new file mode 100644 index 0000000000..08bf671efc --- /dev/null +++ b/ppd/stphoto.ppd @@ -0,0 +1,131 @@ +*PPD-Adobe: "4.3" +*% +*% "$Id$" +*% +*% Sample EPSON Stylus Photo driver PPD file for the Common UNIX Printing +*% System (CUPS). +*% +*% Copyright 1997-2000 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 +*% +*FormatVersion: "4.3" +*FileVersion: "1.1" +*LanguageVersion: English +*LanguageEncoding: ISOLatin1 +*PCFileName: "STPHOTO.PPD" +*Manufacturer: "ESP" +*Product: "(CUPS v1.1)" +*cupsVersion: 1.1 +*cupsManualCopies: True +*cupsFilter: "application/vnd.cups-raster 0 rastertoepson" +*cupsColorProfile 180dpi/-: "1.0 1.0 1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0" +*cupsColorProfile 360dpi/-: "1.0 1.5 1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0" +*cupsColorProfile 720dpi/-: "1.0 2.5 1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0" +*ModelName: "EPSON Stylus Photo Series" +*ShortNickName: "EPSON Stylus Photo Series" +*NickName: "EPSON Stylus Photo Series CUPS v1.1" +*PSVersion: "(2017.000) 0" +*LanguageLevel: "2" +*ColorDevice: True +*DefaultColorSpace: RGB +*FileSystem: False +*Throughput: "1" +*LandscapeOrientation: Plus90 +*VariablePaperSize: False +*TTRasterizer: Type42 + +*OpenUI *PageSize/Media Size: PickOne +*OrderDependency: 10 AnySetup *PageSize +*DefaultPageSize: Letter +*PageSize Letter: "<>setpagedevice" +*PageSize Legal: "<>setpagedevice" +*PageSize A4: "<>setpagedevice" +*CloseUI: *PageSize + +*OpenUI *PageRegion: PickOne +*OrderDependency: 10 AnySetup *PageRegion +*DefaultPageRegion: Letter +*PageRegion Letter: "<>setpagedevice" +*PageRegion Legal: "<>setpagedevice" +*PageRegion A4: "<>setpagedevice" +*CloseUI: *PageRegion + +*DefaultImageableArea: Letter +*ImageableArea Letter: "8.60 39.60 603.40 766.49" +*ImageableArea Legal: "8.60 39.60 603.40 982.49" +*ImageableArea A4: "8.60 39.60 586.40 816.49" + +*DefaultPaperDimension: Letter +*PaperDimension Letter: "612 792" +*PaperDimension Legal: "612 1008" +*PaperDimension A4: "595 842" + +*OpenUI *Resolution/Output Resolution: PickOne +*OrderDependency: 20 AnySetup *Resolution +*DefaultResolution: 360dpi +*Resolution 180dpi/180 DPI: "<>setpagedevice" +*Resolution 360dpi/360 DPI: "<>setpagedevice{0.6666 exp}bind settransfer" +*Resolution 720dpi/720 DPI: "<>setpagedevice{0.4 exp}bind settransfer" +*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/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..7657b3ba2d --- /dev/null +++ b/pstoraster/Makefile @@ -0,0 +1,167 @@ +# +# "$Id$" +# +# GNU Ghostscript makefile for the Common UNIX Printing System (CUPS). +# +# Copyright 1993-2000 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) $(SERVERBIN)/filter + $(CP) pstoraster $(SERVERBIN)/filter + -$(LN) pstoraster $(SERVERBIN)/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: ../filter/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 \ + ../filter/$(LIBCUPSIMAGE) $(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..19790f1dee --- /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-2000 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..a11f069ad4 --- /dev/null +++ b/pstoraster/gdevcups.c @@ -0,0 +1,2353 @@ +/* + * "$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 : + if (cups->header.cupsColorSpace == CUPS_CSPACE_KCMYcm && + cups->header.cupsBitsPerColor == 1) + cups->header.cupsBytesPerLine = (cups->header.cupsBitsPerColor * + cups->header.cupsWidth + 7) / 8 * 6; + else + cups->header.cupsBytesPerLine = (cups->header.cupsBitsPerColor * + cups->header.cupsWidth + 7) / 8 * + cups->color_info.num_components; + break; + + case CUPS_ORDER_PLANAR : + cups->header.cupsBytesPerLine = (cups->header.cupsBitsPerColor * + 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, 2, + "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 = 8; + 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.cupsWidth * cups->header.cupsBitsPerColor + 7) / 8; + + 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, kptr = dst, cptr = kptr + bandbytes, + mptr = cptr + bandbytes, yptr = mptr + bandbytes, + lcptr = yptr + bandbytes, lmptr = lcptr + bandbytes, + bit = 128; + x > 0; + x --, srcptr ++) + { + if (*srcptr & 0x20) + *kptr |= bit; + if (*srcptr & 0x10) + *cptr |= bit; + if (*srcptr & 0x08) + *mptr |= bit; + if (*srcptr & 0x04) + *yptr |= 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 %

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