From: msweet Date: Fri, 10 May 2013 18:56:23 +0000 (+0000) Subject: Import cups.org releases X-Git-Tag: release-1.1.5.2^0 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b28f92ab0eeaa8ea9bd61199e8f0a939e73cc1e8;p=thirdparty%2Fcups.git Import cups.org releases git-svn-id: svn+ssh://src.apple.com/svn/cups/cups.org/tags/release-1.1.5.2@4306 a1ca3aef-8c08-0410-bb20-df032aa958be --- b28f92ab0eeaa8ea9bd61199e8f0a939e73cc1e8 diff --git a/CHANGES.txt b/CHANGES.txt new file mode 100644 index 0000000000..f96a6da0f6 --- /dev/null +++ b/CHANGES.txt @@ -0,0 +1,1052 @@ +CHANGES.txt - 01/03/2000 +------------------------ + +CHANGES IN CUPS V1.1.5-2 + + - Fixed configure check for OpenSSL to work with RSA + code. + - Added configure check for , and use this + check in backend/serial.c. + - Updated configure script handling of data, + configuration, and state directories to use datadir, + sysconfdir, and localstatedir variables. + - NetBSD uses different serial port filenames than + FreeBSD and OpenBSD. + - The pdftops filter didn't need some X-specific files. + - The scheduler makefile doesn't do a chown anymore when + installing (cupsd did this automatically on startup + anyways) + + +CHANGES IN CUPS V1.1.5-1 + + - There was a typo in the top-level Makefile + - The top-level Makefile did not install an init script + for run level 5. + - The configure script did not add the "crypto" library + when checking for the OpenSSL library. + - The OKIDATA PPD files were missing. + - The config.h.in file defined the wrong version number. + - The serial backend did not define "funky_hex" under *BSD. + - Updated the Visual C++ project files and some of the + CUPS API sources to compile under Windows again. + + +CHANGES IN CUPS V1.1.5 + + - Security updates - new default configuration does + not broadcast printer information and only allows + access from the local system. + - EXPERIMENTAL encryption support - CUPS now optionally + supports TLS/SSL encryption via the OpenSSL library. + - Documentation updates. + - Makefile/configure script updates. + - The RPM spec file didn't work out-of-the-box under + RedHat or Mandrake. + - Minor code cleanup to remove extraneous compiler + warnings. + - cupsTempFile() was using %p for the temporary + filename; this should have been %08x (just 8 digit + hex) + - Deleting a printer with active print jobs would still + crash the server. + - ippWrite() and ipp_write_file() didn't send the + correct value length for name-with-language and + text-with-language attributes. + - Updated IPP code to support copied strings (that + should not be freed); this provides slightly more + efficient IPP server performance. + - Updated PDF filter to Xpdf 0.91. + - httpGets() could go into an infinite loop if a line + longer than the input buffer size was sent by a + client. This could be used in a Denial-of-Service + attack. + - The lpstat and CUPS API functions now request only the + data required when getting the list of printer or + class information. This should improve performance + with large numbers of printers on slower machines. + - The scheduler was always enforcing the FilterLimit, + even if FilterLimit was set to 0. + - Updated the Linux USB backend to support Mandrake's + /dev/usb/usblp# filenames. + - The PRINTER and LPDEST environment variables did not + override the lpoptions default printer. + - The PPD read functions incorrectly included trailing + characters (usually whitespace) after quoted string + attributes. + - The multiple-document-handling attribute handling code + did not check for the correct value for collated + copies (separate-documents-uncollated-copies). + - The EPSON driver did not work with OKIDATA printers in + EPSON emulation mode (needed change-emulation command) + - The HP-GL/2 filter did not scale the plot properly in + scale mode 2. + - Added PPD files for 9-pin and 24-pin OKIDATA printers. + - The httpSeparate() function didn't handle passwords + that started with a number. + - ippDelete() could free the character set string + multiple times in name-with-language and + text-with-language attributes. + - The scheduler would access freed memory right after + freeing it (for debug messages); these parts of the + code have been reordered to avoid this situation + which was causing sporatic errors and crashes. + - The ppdClose() function didn't free all of the strings + in the ppd_file_t structure. + - The LoadAllJobs() function in the scheduler did not + close the spool directory. + - Changed all sprintf's that use string formats to + snprintf's, even if the destination buffer is + larger than the source string(s); this protects + against buffer overflows caused outside of CUPS... + - Changed all strcpy's to strncpy's between local and + global variables, even if the destination buffer is + larger than the source string; this protects + against buffer overflows caused outside of CUPS... + - The CUPS certificate functions didn't use the + CUPS_SERVERROOT environment variable when set. + - The directory services code was copying instead of + comparing the remote printer info, resulting in + unnecessary updates of the printer attributes for + remote printers. + - Added new mime.types rules to allow automatic raw + printing of PCL and ESC/P files; PJL headers are + parsed to differentiate between PostScript and + PCL job files. This should eliminate a lot of + the reports of SAMBA printing problems due to + the missing "-oraw" or "-l" options. + - The mimeLoadType() function didn't handle the + 3-argument contains() function. + - The LoadPPDs() function in the scheduler didn't + properly set the alloc_ppds variable or handle a PPD + database containing 0 printers. + - The scheduler FindAvailablePrinter() function didn't + use the same queuing logic as the CheckJobs() + function. This caused classes to stall if a remote + printer was always busy. + - Jobs are now assigned to printers in a class + round-robin style. This should prevent the first + server in the class from bearing the brunt of the + jobs. + - The scheduler's LoadAllJobs() function didn't always + restore remote printers for queued jobs on startup. + - The serial backend didn't support the higher baud + rates with the old termios interface. It now supports + 57600 and 115200 baud. + - The serial backend now supports different types of + flow control; previously it ignored the flow=XYZ + option in the device URI. + - The serial backend now supports DTR/DSR flow control, + which is popular on dot-matrix printers (access with + "flow=dtrdsr" in the device URI) + - Added new job-originating-host-name attribute for + jobs. The new attribute provides the hostname or + IP address of the machine that submitted the job. + - The set-job-attributes code no longer allows read-only + job attributes to be changed. + - Expanded the click area for the navigation bar in the + web interface. + - Updated the lp and cancel commands to support all of + the Solaris print options (some are simply ignored + since they do not map) + - Updated the scheduler to limit the number of file + descriptors to the maximum select() set size. This + was causing problems on Solaris systems where the + max FD count was increased beyond 1024. + - The scheduler's LoadDevices() function was getting + interrupted by the SIGCHLD signal handler; now ignore + child signals while loading devices. + - Added quota and allow/deny user support for printers + and classes. + - Removed black/CMY adjustment code from the PS and + image file RIPs; it was interfering with some CUPS + driver dithering code. + - The lpc program stopped listing the queue statuses + after the first active printer. + - The cups-lpd program used an output format that the + Solaris printing system did not understand. + - Updated the lpq program to use the Solaris format + except under Tru64 UNIX. + - Some DEC PPD files incorrectly use "Off" for the null + value in UI constraints. Added "Off" to the list of + accepted null values. + - Changed the *BSD define constants to __*BSD__ in all + of the backends. + - Added support for "lpstat printername", which is an + undocumented feature in Solaris. + - The HP-GL/2 filter now only sets the plot size if it + is set in the plot file. + - The lpmove command wasn't sending the requesting + user name, causing it to always fail. + - Updated the cupsTempFile() code to use GetTempPath() + under Windows. + - The cups-lpd mini-daemon didn't limit the number of + data files accepted, didn't use cupsTempFile(), + didn't handle control file job information in any + order, and didn't free job options after printing + a file. + - The scheduler copy_banner() function did not + explicitly set the owner and permissions of the banner + files, which could prevent the banner pages from + printing on some systems. + - The lpstat program wasn't listing remote classes. + - The scheduler did not verify that the printer-uri + attribute was specified in all requests that required + it. + + +CHANGES IN CUPS v1.1.4 + + - Makefile and configure script fixes. + - **** Changed the default Printcap setting **** to + /etc/printcap. There are just too many people asking + why application XYZ doesn't see their printers! + - The web admin interface now displays an error if it + can't get the list of printer drivers from cupsd. + - The IPP backend was putting the copies option before + the other job options were set. This caused the IPP + request to contain attribute groups in the wrong + order, which prevented remote printing. + - Added checks in scheduler to free memory used for + IPP requests and language information when closing + a client connection. + - Fixed the duplex option in the HP LaserJet driver. It + should now work with all LaserJet printers (and + compatibles) + - The add-printer web interface didn't initialize the + "old info" data pointer, which caused random crashes + on many OS's. + - Fixed many page sizes defined in the Level 1 + compatibility file "gs_statd.ps" to match reality. + - Fixed another bug in the setpagedevice "code" in + Ghostscript. It should now accept all standard + Adobe attributes on all platforms. + - Fixed pstoraster so that it reallocates memory for + color depth changes as well as size/resolution + changes. This removes an ordering constraint on + the color, page size, and resolution options in + PPD files. + - The IPP backend didn't use the job's character set + when the destination printer supported it. This + caused problems when printing text files to other + CUPS servers. + - Updated the logic used to determine when to rebuild + the PPD file database. The scheduler now checks the + dates and the number of PPD files (was just checking + the dates.) + - Updated the ippSetCGIVars() function (used by the + web interfaces) to only filter valid string values. + - The PostScript filter was scaling 2-up pages + incorrectly. This caused the edges of some pages to + be clipped. + + +CHANGES IN CUPS v1.1.3 + + - Makefile fixes. + - RPM spec file changes. + - Documentation updates. + - Enabled pstoraster debug messages for everything + (only logged when LogLevel set to "debug"...) + - Changed the Input/OutputAttributes fix in + pstoraster so that it works on all platforms. + - The HP-GL/2 filter didn't set the right green + color value in encoded polylines or text. + - Updated the "fitplot" code to handle plot sizes + specified as "PSwidth,length" and "PSlength,width". + - Updated the Linux parallel and USB backends to open + the device files prior to looking in /proc for + autoprobe info. This makes sure that loadable device + driver modules are in fact loaded... + - Added new FilterLimit directive to limit the number + of processing jobs/filters on a system. + - set-job-attributes didn't change the job-state to + held/pending when the job-hold-until attribute was + specified. + - set-job-attributes didn't save the new job attributes. + - Now change the "requesting-user-name" attribute in + requests from remote systems to "remroot" when an + unauthenticated "root" user is sent. This can be + changed using the new RemoteRoot directive in + cupsd.conf. + - The cancel-job, hold-job, release-job, and restart-job + operations didn't log the authenticated username. + - The cups-lpd mini-daemon now checks for a + document-format option before forcing raw mode with + filter mode 'l'. + - The cups-lpd mini-daemon now supports "-o" options + on the command-line (passed by inetd) to set global + defaults for all print queues. + - The pstops filter assumed that a file with a Trailer + comment would also have an EOF comment. + - Added new cupsSetPasswordCB(), cupsSetServer(), + cupsSetUser(), and ippSetPort() functions to better + support client applications (especially GUIs...) + - The CUPS-add-class and CUPS-add-printer operations + didn't reset the printer-name attribute on remote + print queues that had to be renamed when a local + printer was defined with the same name. + - The lpoptions command now supports a "-r" option to + remove options for a printer or instance. + - The lpadmin and admin.cgi programs no longer allow + class and printer names to begin with a number; this + caused the command-line utilities to become confused. + - The Linux USB backend now looks for both the parallel + and usblp driver names in the device list. + - Added a new FontPath directive to cupsd.conf, and also + a "--with-fontpath" option for the configure script to + specify alternate font paths for pstoraster. + - The CUPS-move-job operation didn't update the + job-printer-uri attribute. + - The scheduler only looked up printers and classes by + name in IPP requests, instead of using the full URI. + This caused problems with KUPS and friends with + remote printers. + - The scheduler now handles better localization of + hostnames (e.g. server is host.foo.com, remote is + host.subfoo.foo.com, localized is not host.subfoo...) + - The scheduler logging functions now use a common + log file checking/rotation function (courtesy of + Crutcher Dunnavant at Red Hat) + - The scheduler could accept more client connections + than it allocated for if more than one Port or Listen + line was present in cupsd.conf. + - Other minor scheduler performance tweeks. + - The lpq and lprm commands didn't support the default + printer set using lpoptions. + - The lpoptions command now supports a "-l" option to + list the printer-specific options and their current + settings. + - The web printer and class lists now show a link to the + default printer or class at the top of the page. + - The text filter now supports pretty printing of shell + and perl scripts as well as C/C++ source files. + - The top and bottom margins were reversed for landscape + text printing. + - The lpq and lprm commands didn't understand printer + instances. + - The scheduler only selected on the first 100 file + descriptors instead of the maximum file descriptor + limit. + - The scheduler client, listener, and mainline functions + now share code to disable and enable monitoring for + new client connections. + - The imagetoraster filter didn't support all of the + required pagedevice parameters. + - The serial backend now checks for 100 serial ports + under Linux. + - The scheduler used sscanf() to pull out the remote + printer location, description, and make/model strings, + but if any of these options was empty then sscanf() + would stop processing. + - Added "debug2" log level to provide a little less + verbose debugging information at the "debug" level. + - The scheduler would crash if you stopped a printer + that was currently printing a job. + - The scheduler incorrectly allowed jobs in the cancelled, + aborted, or completed state to be cancelled. + - The image filters did not load TIFF images properly + for bottom-to-top and right-to-left orientations. + - Added new cupsEncodeOptions() function to encode + CUPS options as IPP job attributes. + - The IPP backend, LPD mini-daemon, client commands, + and CUPS API did not properly encode multiple + option values separated by commas. + - Added new scheduler malloc logging in debug mode + (provides summary of total arena size, allocated, + and free bytes once a minute) + - The EPM-based distributions didn't install the + correct symlinks for a few man pages. + - Fixed a memory leak in the scheduler - wasn't + freeing old filters when deleting or renaming + printers. + - The scheduler now queries the primary IP address + for the name of the server and maps any incoming + requests from that address to the server name. + This fixes web admin mapping problems from + server.domain.com to localhost. + - The web printer modify interface now remembers + the previous device and driver settings (except + for serial ports.) + - The job-k-octets attribute is now stored as part of + the job attributes; this preserves the information + after a job is completed when job file history is + turned off. + - Dropped option sub-group parsing code for the moment, + since many Xerox PPD files abuse this feature in PPD + files and don't follow the hierarchy rules. + - Added new wrapper code around options so that duplex + options for some HP printers don't prevent prints. + - Added support for Digital UNIX/Tru64 UNIX/OSF/1 format + for "lpstat -v" output. + - Now show the URI for remote printers instead of + /dev/null in "lpstat -v" output. + - Creating classes and adding printers to a class with + the lpadmin command didn't work. + - The banner pages and test page should now format + correctly in both portrait and landscape orientations. + - Updated banner page substitution so that { can appear + by itself without quoting. + + +CHANGES IN CUPS v1.1.2 + + - Makefile/configure fixes + - RPM spec file and EPM list file fixes + - The cupsTempFile() function now uses a different + algorithm for generating temp files and "reserves" + them to avoid possible security exploitation. + - Now use /dev/random (if available) to seed the random + number generator for certificates. + - The /var/spool/cups and /var/spool/cups/tmp directories + were incorrectly owned by root; they are now owned by + the filter user, typically "lp". + - The scheduler now resets the permissions on the spool + and temp directories as needed to match the filter + user. + - Now expose ppdCollect() as an externally callable + function. + - The image filters now support filtering from the + standard input. + - The imagetoraster filter now collects all printer + options and job patch files and applies them to the + page header as needed. + - Added format and banner options to LPD backend. + - The send-document operation didn't start a job + immediately when last-document was true. + - The set-job-attributes operation didn't correctly + replace the current job-hold-until value. + - Removed the option wrapper code from ppdEmit() and + friends since it caused problems with Ghostscript + and many PS printers. + - Was setting TZ environment variable twice for job + filters. + - Added syslog logging in cups-lpd to aide in + debugging problems. + - The HP-UX parallel port backend did not list the + available parallel ports on some systems (printf + calling problem...) + - The lp and lpr commands overrode user options if + -d/-P were specified after -o. + - The scheduler would crash with a */* filter. + - Added support for a "default" filter for unknown file + types. The example provided in the mime.types and + mime.convs file prints unknown files as if "-oraw" was + specified for the job. This functionality is disabled + by default. + - The "compatibility" mode fix for older backends did not + work for smbspool. Added a workaround for it. + - The HP-GL/2 filter didn't perform the right pen scaling + with some files and the "fitplot" option. + - New Software Performance Specification document that + describes the memory, disk, and CPU usage of all the + CUPS software. + + +CHANGES IN CUPS v1.1.1 + + - The pstoraster Makefile still referenced one of the + old PDF filter files. + - The filter Makefile used INSTALL_DATA instead of + INSTALL_LIB to install the CUPS image library. + - The administration CGI didn't work properly with + network devices. + - The BrowseACL variable was not updated after the + cupsd.conf file was loaded. + - The lpd mini-daemon didn't support printer instances. + - Now use a default umask of 077 for child processes. + - Now put temp files in /var/spool/cups/tmp for child + processes and the root user, unless TMPDIR or TempDir + is defined otherwise. + - cupsGetPPD() no longer uses easy-to-guess filenames. + - The CUPS-Delete-Class and CUPS-Delete-Printer + operations now save classes.conf file as needed. + - The lppasswd command wouldn't add a user. + - The ppdOpen() function could cause a segfault if a + 0-length PPD file was read. + - The image filters were not handling images with + different X and Y resolutions properly. + - The imagetoraster filter defaulted to RGB output + instead of black output like pstoraster. + - The pstops filter didn't handle binary data properly. + - The pstops filter didn't handle copies properly for + PS files lacking DSC comments. + - The pstops filter now appends %%EOF to the end of + documents if they don't have it. + - The cupsGetPPD() function didn't work with remote + printers lacking the @server in the name. + - The configure script didn't work right when only + --prefix was specified. + - The ppdEmit() code now wraps all printer commands so + that buggy PostScript printers will still print a file + after receiving an option that isn't available. + - Fixed the DeskJet margin bug, and disabled 600dpi + color mode until it can be fixed. + - The cupsAddDest() function didn't sort instances + correctly in all cases. + - The time-at-xyz attributes now expand to the date and + time in banner files. + + +CHANGES IN CUPS v1.1 + + - Documentation updates. + - Configuration script updates. + - Didn't map charset and language value strings to lowercase + and _ to - as required by SLP and IPP. + - ppdLoadXYZ() didn't add the list of available fonts to the + ppd_file_t structure. + - The text filter common code was freeing the PPD file data + before it was used. + - The text filter now embeds missing fonts. + - The CGI interface now maps local access to the server to + the localhost address. + - The HP-GL/2 filter didn't use the specified (or default) + color ranges, resulting in strange colors. + - The HP-GL/2 filter didn't default to no input window, which + caused unnecessary clipping of plots. + - Integrated Xpdf's pdftops filter into CUPS, which is a + lightweight and reliable replacement for Ghostscript's + PDF support. + - Removed all PDF support from Ghostscript. + - Updated HP driver to set top margin; this seems to fix + the offset problem seen on HP DeskJet printers. + - Fixed dependencies on the ZLIB and JPEG libraries in + pstoraster. + - The lpr command wasn't using the lpoptions defined by + the user. + - The lpr command would segfault if the CUPS server was + not running. + - The top-level makefile was not installing the CUPS + initialization script. It now does so if it sees there + is an init.d directory in /sbin, /etc/rc.d, or /etc. + - "lpstat -v all" didn't work. + - pstoraster would crash on some platforms doing the + setpagedevice operator. + - The web administration interface now allows you to set + the default banner pages. + - Images can now be positioned on the page using the new + "position" option. + - The AccessLog, ErrorLog, and PageLog directives now + support "%s" to insert the server name. + - Added a new BrowseShortNames directive to allow for + short remote printer names ("printer" instead of + "printer@server") when possible. + - The scheduler could crash if given an invalid PPD file + with no PageSize attributes. + - Updated the serial, parallel, and usb backends to do + multiple writes and ignore ioctl() errors as needed; + this should fix problems with serial printing on old + serial drivers and with the UltraSPARC parallel port + driver under Solaris 2.7. + - Now propagate LD_LIBRARY_PATH to child processes from + cupsd. + - New DataDir directive for installing in alternate + locations. + - New CUPS_SERVERROOT and CUPS_DATADIR environment + variables to specify installation directories as + needed. + - Queued remote jobs recreate remote printers as needed + when the scheduler is started. + - Deleting a printer also purges all jobs on that + printer. + - Old job and control files that don't belong to a + printer are automatically deleted. + - Wasn't updating time-at-processing and + time-at-completed attributes in job. + - Didn't send required multiple-operation-time-out + attribute in response to a get-printer-attributes + request. + - cups-lpd now supports options set with lpoptions. + - The job-hold-until attribute is now provided with all + jobs. For jobs that are not currently held the value + is "no-hold". + - The scheduler was not sending "unknown" values in IPP + responses. + - The lpoptions command now accumulates options from + previous runs rather than replacing all options for a + printer. + - The IPP backend now switches to IPP/1.0 if a 1.1 + request fails. + - The lpadmin and admin.cgi programs now validate new + printer and class names. + - The access_log file now includes the number of IPP bytes + received in a POST request. + + +CHANGES IN CUPS v1.1b5 + + - Documentation updates. + - The pstoraster filter didn't compile without the JPEG library. + - The cupsd server didn't support the HTTP OPTIONS request + method. + - Dropped the "CLOSE" method supported by the cupsd server. + (not defined in HTTP specification) + - Makefile/configure script fixes. + - Missing the job-restart template. + - Added IPP test suite for testing. + - Missing IPP documentation from binary distributions. + - Fixed multiple-document handling code when last-document + not specified. + - Added more checks to IPP requests to prevent bad requests + from getting through. + - Not all of the Ghostscript error output was being sent to + stderr. + - The PostScript filter now added PJL commands to set the + job name and display string, if supported. + - The scheduler would crash if the browse socket could not + be bound. Now disables browsing if port 631 (reserved for + IPP) is being used by a misbehaving daemon. + - The USB backend now looks for the older Linux 2.2.x USB + printer device filenames as well as the newer ones. + - The IPP backend now uses the UTF-8 charset exclusively, + since apparently only CUPS handles more than US-ASCII and + UTF-8... + - Wasn't quoting ( in PostScript banners... + - Send-document requests with no document-format attribute + could cause cupsd to crash. + - Old jobs in the spool directory might cause cupsd to + crash. + - CUPS now supports all of the recommended job-hold-until + keywords as well as name values of the form "HH:MM" and + "HH:MM:SS". + - Added placeholder pointer for TLS encryption to the HTTP + connection structure. + - Fixed the "fast poll" bug reported by DISA - the + status pipe wasn't being closed for multi-file jobs. + - Revamped put_params code in pstoraster to fix bitmap + allocation bug with FrameMaker output. + - Ripped out filename, etc. code from pstoraster as it + is a potential security hole. + - Added support for RIP_CACHE environment variable in the + new pstoraster. + - Fixed USB device filenames for Linux; now support new + pre-2.4 devices (/dev/usb/lp#) and 2.2 devices + (/dev/usblp#) + - Fixed accept-jobs crash with classes. + - Didn't include dot-matrix EPSON drivers in previous + release. + + +CHANGES IN CUPS v1.1b4 + + - Documentation updates. + - Many makefile and configuration script fixes (should + now compile better under *BSD.) + - The MediaPosition attribute was being mishandled by + GhostScript, causing the RIP to fail whenever a paper + tray was selected. + - The scheduler now logs the final line of log information + from a filter, even if it doesn't end with a newline; this + primarily affects GhostScript error output. + - The scheduler was saving implicit classes, so after a few + restarts you'll end up with AnyPrinter, AnyAnyPrinter, etc. + - The JPEG autodetection didn't work with some JPEG files that + came from digital cameras (JPEG but not JFIF); the new + magic types should work with all images that the JPEG library + can handle. + - Fixed a bug in the new contains() MIME type rule that could + cause cupsd to crash. + - Switched to using strtol() in the MIME type code so that you + can use hex, octal, or decimal constants as desired in the + mime.types file. + - Banner files are now treated as templates, allowing any type + of file to be used as a banner. + - Added a 30-second timeout to backend device reports so that a + hung backend will not prevent the scheduler from starting. + - Backends are once again terminated when jobs are stopped; the + CUPS-supplied backends will stay alive until the downstream + filters have had a chance to clear out old page data. + - The charset lookup in the CUPS localization support was wrong + (iso8859-x instead of iso-8859-x) + - Changed the "cpNNNN" code page files to "windows-NNNN" to match + the IANA registrations. + - New PostScript banner pages. + - Added Windows BMP and Alias PIX image file support to the image + filter. + - The PNG reading coded didn't free all of its buffers. + - Added Digest authentication support to the client and server + code. + - Added Solaris options to System V commands. + - Now support the output-bin job template attribute. + - Now log the job-billing attribute in the page_log file, and + keep track of the total number of pages in the + job-media-sheets-completed attribute. + - The penwidth option is now in micrometers to support more + accurate width specification. + - The image filters now support interlaced and transparent PNG + files. + - Didn't handle Keep-Alive for HTTP/1.0 clients. + - The BrowsePoll support didn't handle when BrowseInterval + was set to 0 (now uses 30 seconds if BrowseInterval is 0) + - The DeskJet driver now supports 600 DPI color for printers + that support it. + - New lpinfo and lpmove commands. + - The lpq command now supports the Digital UNIX output format. + - The LPD mini-daemon now supports all required LPD operations. + - Implemented timeouts for multi-file documents. + - New cupsPrintFiles() function in the CUPS API library to + print multiple files using create-job and send-document + requests (1 job ID for multiple files) + - The lp command now sends multiple files as a single job, + matching the behavior of the System V command. + - The "cancel -a" command now purges job history files. + + +CHANGES IN CUPS v1.1b3 + + - Documentation updates. + - The startup script redirected stderr before stdout, + which caused problems with some versions of Bourne + shell and Bash. + - Fixed a bug in the scheduler's PPD language reading + code. + - Fixed a bug in the scheduler's check for the + manufacturer in the PPD. + - The pstoraster filter didn't allow some input and + output attributes to be set. + - Added banner page support. + - Added missing PAM configuration file. + - Configuration script fixes for Linux and *BSD. + - The log file code was using the wrong sign for the + timezone offset. + - The default printcap file is now empty (no printcap + file is generated). + - The scheduler did not start jobs destined for remote + printers when they became available. + - The scheduler now sends jobs to remote printers + immediately. (when sending jobs to a class, the remote + printer is only used when it becomes available) + - The scheduler now supports printing of banner pages + via the job-sheets attribute (banner files go in + /usr/share/cups/banners) + - The cupsd process now forks itself into the background + (override with -f) + - Added several *BSD enhancements. + - Added UNSUPPORTED libtool option to configuration + script to allow the use of libtool. Note that this is + UNSUPPORTED by us, but added by request of the *BSD + folks. + - The parallel, serial, and usb backends now retry the + opening of their ports. This allows multiple print + queues to be associated with a single physical port, + and will allow CUPS to support several types of + parallel port auto-switches in the near future. + - Set-Job-Attributes now supports adding, changing, and + deleting job template attributes, and no longer allows + job-printer-uri to be set (see CUPS-Move-Job) + - Added CUPS-Move-Job operation to support moving of jobs. + - The CGI template functionality now supports multiple + languages (still only have templates for English) + - The CUPS-Get-Printers and CUPS-Get-Classes operations + now support filtering as defined in the IDD. + - The Get-Jobs, CUPS-Get-Printers, and CUPS-Get-Classes + operations no longer limit themselves to 1000 jobs, + printers, or classes (believe it or not, this is + needed for some sites) + - The web interfaces now support language-specific + templates. + - The web admin interface now supports class management. + - The web admin interface now shows a list of + manufacturers before selecting the PPD/driver for a + specific printer. + - The web admin interface now supports configuration of + the default printer options in the PPD file. + - The web interface now uses printer/class + authentication for the test page instead of admin + authentication. + - Updated the RPM spec file for the current release. + - Updated language support for Windows code pages. + - 8-bit character set files can now use multiple fonts + (needed for Arabic, Greek, Hebrew, etc.) + - Added basic right-to-left text support in the text + filter. + - The POSIX locale now uses ISO-8859-1 instead of + US-ASCII. + - Fixed PDF printing problems. + - Fixed PostScript RIP page device dictionary elements + that weren't getting passed in cups_get_params(). + - Added a new "contains" rule for the magic file typing. + - The "printable" rule now accepts characters from 128 to 255 + (needed for Microsoft character sets) + - Added support for ~/.cupsrc as well as /etc/cups/client.conf + so that the default server can be configured on a per-user + basis without environment variables. + - Added LPD mini-daemon to support incoming LPD jobs. + + +CHANGES IN CUPS v1.1b2 + + - Documentation updates. + - The lp command didn't always load the user-defined + destinations, preventing it from seeing the default + printer. + - Many configure script and makefile fixes. + - The Microsoft code page files were missing from the + distribution. + - Added a workaround for the HP IPP client (which is sending + an invalid printer-uri in requests) + - Fixed the encoding of text-with-language and name-with-language + to match the IPP spec. + - Added support for unknown value tags in the IPP routines + (previously they would be ignored) + - Integrated GNU GhostScript 5.50 into the pstoraster filter. + - Client hostname resolution was broken on little-endian + machines. + - Now look at client.conf file for client's default server + and printer. + - The cupsServer() function did not close the client.conf file + if it contained a ServerName directive. + - Added BrowseAllow, BrowseDeny, BrowseOrder, BrowsePoll, and + BrowseRelay directives. + - BrowseInterval 0 disables advertising of local printers, but + still receives information on remote printers. + - New browse polling daemon (for polling servers on different + networks) + - New PPD cache file for faster startup times with large numbers + of PPD files. + - The Host: field was incorrectly required for HTTP/1.0 clients. + - New set-job-attributes operation now supported. + - The mime_load_types() and mime_load_convs() functions did not + close their input files. + + +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/ENCRYPTION.txt b/ENCRYPTION.txt new file mode 100644 index 0000000000..f5f725fa34 --- /dev/null +++ b/ENCRYPTION.txt @@ -0,0 +1,129 @@ +ENCRYPTION - CUPS v1.1.5 - 12/20/2000 +------------------------------------- + +This file describes the encryption support provided by CUPS. + +WARNING: CLIENTS CURRENTLY TRUST ALL CERTIFICATES FROM SERVERS. +This makes the CUPS client applications vulnerable to "man in +the middle" attacks, so we don't recommend using this to do +remote administration over WANs at this time. + +Future versions of CUPS will keep track of server certificates +and provide a callback/confirmation interface for accepting new +certificates and warning when a certificate has changed. + + +LEGAL STUFF + +BEFORE USING THE ENCRYPTION SUPPORT, PLEASE VERIFY THAT IT IS +LEGAL TO DO SO IN YOUR COUNTRY. CUPS by itself doesn't include +any encryption code, but it can link against the OpenSSL library +which does. + + +OVERVIEW OF ENCRYPTION SUPPORT IN CUPS + +CUPS supports SSL/2.0, SSL/3.0, and TLS/1.0 encryption using +keys as large as 128-bits. Encryption support is provided via +the OpenSSL library and some new hooks in the CUPS code. + +CUPS provides support for dedicated (https) and "upgrade" (TLS) +encryption of sessions. The "HTTP Upgrade" method is described +in RFC 2817; basically, the client can be secure or unsecure, +and the client or server initiates an upgrade to a secure +connection via some new HTTP fields and status codes. The HTTP +Upgrade method is new and no browsers we know of support it yet. +Stick with "https" for web browsers. + +The current implementation is very basic. The CUPS client +software (lp, lpr, etc.) uses encryption as requested by the +server and/or as specified by the Encryption directive in the +client.conf file or in the CUPS_ENCRYPTION environment +variable: + + Never + + Never do encryption. + + Always + + Always do SSL/TLS encryption using the https scheme. + + IfRequested + + Upgrade to TLS encryption if the server asks for it. + This is the default setting. + + Required + + Always upgrade to TLS encryption as soon as the + connection is made. This is different than the "Always" + mode above since the connection is initially unsecure + and the client initiates the upgrade to TLS encryption. + +These keywords are also used in the cupsd.conf file to secure +particular locations. To secure all traffic on the server, listen +on port 443 (https port) instead of port 631 and change the "ipp" +service listing (or add it if you don't have one) in /etc/services +to 443. + + +BEFORE YOU BEGIN + +You'll need the OpenSSL library from: + + http://www.openssl.org + + +CONFIGURING WITH ENCRYPTION SUPPORT + +Once you have the OpenSSL library installed, you'll need to +configure CUPS to use it with the "--enable-ssl" option: + + ./configure --enable-ssl + +If the OpenSSL stuff is not in a standard location, make sure to +define the CFLAGS, CXXFLAGS, and LDFLAGS environment variables +with the appropriate compiler and linker options first. + + +GENERATING A SERVER CERTIFICATE AND KEY + +The following OpenSSL command will generate a server certificate +and key that you can play with. Since the certificate is not +properly signed it will generate all kinds of warnings in +Netscape and MSIE: + + openssl req -new -x509 -keyout /etc/cups/ssl/server.key \ + -out /etc/cups/ssl/server.crt -days 365 -nodes + + chmod 600 /etc/cups/ssl/server.* + +The "-nodes" option prevents the certificate and key from being +encrypted. The cupsd process runs in the background, detached +from any input source; if you encrypt these files then cupsd +will not be able to load them! + +Send all rants about non-encrypted certificate and key files to +/dev/null. It makes sense to encrypt user files, but not for +files used by system processes/daemons... + + +REPORTING PROBLEMS + +If you have problems, READ THE DOCUMENTATION FIRST! If the +documentation does not solve your 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. The "/var/log/cups/error_log" file should also be sent, +as it often helps to determine the cause of your problem. + +If you are running a version of Linux, be sure to provide the +Linux distribution you have, too. + +Please note that the "cups-support@cups.org" email address goes +to the CUPS developers; they are busy people, so your email may +go unanswered for days or weeks. In general, only general build +or distribution problems will actually get answered - for +end-user support see the "README.txt" for a summary of the +resources available. diff --git a/INSTALL.txt b/INSTALL.txt new file mode 100644 index 0000000000..597f38cff7 --- /dev/null +++ b/INSTALL.txt @@ -0,0 +1,154 @@ +INSTALL - CUPS v1.1.5 - 12/20/2000 +---------------------------------- + +This file describes how to compile and install CUPS from source +code. For more information on CUPS see the file called +"README.txt". A complete change log can be found in +"CHANGES.txt". + + +BEFORE YOU BEGIN + +You'll need ANSI-compliant C and C++ compilers, plus a make +program and Bourne shell. The GNU compiler tools work well - +we've tested the current CUPS code against GCC 2.95.x with +excellent results. + +The makefiles used by the project should work with all versions +of make. We've tested them with GNU make as well as the make +programs shipped by Compaq, HP, SGI, and Sun. FreeBSD users +should use GNU make (gmake). + +Besides these tools you'll want the following libraries: + + - JPEG 6b or higher + - PNG 1.0.6 or higher + - TIFF 3.4 or higher + - ZLIB 1.1.3 or higher + +CUPS will compile and run without these, however you'll miss out on +many of the features provided by CUPS. + + +CONFIGURATION + +CUPS uses GNU autoconf, so you should find the usual "configure" +script in the main CUPS source directory. To configure CUPS for +your system, type: + + ./configure ENTER + +The default installation will put the CUPS software in the +"/etc", "/usr", and "/var" directories on your system, which +will overwrite any existing printing commands on your system. +Use the "--prefix" option to install the CUPS software in +another location: + + ./configure --prefix=/some/directory 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, CXXFLAGS, and LDFLAGS +environment variables prior to running configure: + + setenv CFLAGS "-I/some/directory" ENTER + setenv CXXFLAGS "-I/some/directory" ENTER + setenv LDFLAGS "-L/some/directory" ENTER + ./configure ... ENTER + +or: + + CFLAGS="-I/some/directory"; export CFLAGS ENTER + CXXFLAGS="-I/some/directory"; export CXXFLAGS ENTER + LDFLAGS="-L/some/directory"; export LDFLAGS ENTER + ./configure ... ENTER + +To enable support for encryption, you'll also want to add the +"--enable-ssl" option: + + ./configure --enable-ssl + +SSL and TLS support require the OpenSSL library, available at: + + http://www.openssl.org + +Once you have configured things, just type: + + make ENTER + +or if you have FreeBSD: + + gmake ENTER + +to build the software. + + +INSTALLING THE SOFTWARE + +Once you have built the software you need to install it. The +"install" target provides a quick way to install the software on +your local system: + + make install ENTER + +or for FreeBSD: + + gmake install ENTER + +You can also build binary packages that can be installed on other +machines using the RPM spec file ("cups.spec") or EPM list file +("cups.list"). The latter also supports building of binary RPMs, +so it may be more convenient to use - we use EPM to build all of +our binary distributions. + +You can find the RPM software at: + + http://www.rpm.org + +The RPM software is at: + + http://www.easysw.com/epm + + +CREATING BINARY DISTRIBUTIONS WITH EPM + +The top level makefile supports generation of many types of binary +distributions using EPM. To build a binary distribution type: + + make ENTER + +or + + gmake ENTER + +for FreeBSD, where is one of the following: + + epm - Builds a portable shell script and tar file based + distribution. This format will also backup your + existing printing system if you decide to remove + CUPS at some future time. + rpm - Builds a RPM binary distribution. + deb - Builds a Debian binary distribution. + depot - Builds a HP-UX binary distribution. + pkg - Builds a Solaris binary distribution. + tardist - Builds an IRIX binary distribution. + + +REPORTING PROBLEMS + +If you have problems, READ THE DOCUMENTATION FIRST! If the +documentation does not solve your 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. The "/var/log/cups/error_log" file should also be sent, +as it often helps to determine the cause of your problem. + +If you are running a version of Linux, be sure to provide the +Linux distribution you have, too. + +Please note that the "cups-support@cups.org" email address goes +to the CUPS developers; they are busy people, so your email may +go unanswered for days or weeks. In general, only general build +or distribution problems will actually get answered - for +end-user support see the "README.txt" for a summary of the +resources available. diff --git a/LICENSE.html b/LICENSE.html new file mode 100644 index 0000000000..ad7fc21cd0 --- /dev/null +++ b/LICENSE.html @@ -0,0 +1,895 @@ + + + Software License Agreement - Common UNIX Printing System + + + + +

Common UNIX Printing System License Agreement

+ +

Copyright 1997-2000 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, ("CUPSTM"), +is provided under the GNU General Public License ("GPL") and GNU +Library General Public License ("LGPL"), Version 2. A copy of these +licenses follow this introduction. + +

The GNU LGPL applies to the CUPS API library, located in the "cups" +subdirectory of the CUPS source distribution and in the +"/usr/include/cups" directory and "libcups.a", "libcups.sl", or +"libcups.so" files in the binary distributions. + +

The GNU GPL applies to the remainder of the CUPS distribution, +including the "pstoraster" filter which is based upon GNU Ghostscript +5.50 and the "pdftops" filter which is based upon Xpdf 0.90. + +

For those not familiar with the GNU GPL, the license basically +allows you to: + +

    + +
  • Use the CUPS software at no charge. + +
  • Distribute verbatim copies of the software in source or + binary form. + +
  • Sell verbatim copies of the software for a media fee, or + sell support for the software. + +
  • Distribute or sell printer drivers and filters that use + CUPS so long as source code is made available under the GPL. + +
+ +

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 must provide source for any new drivers, changes, or +additions to the software, and all code must be provided under the GPL +or LGPL as appropriate. + +

The GNU LGPL relaxes the "link-to" restriction, allowing you to +develop applications that use the CUPS API library under other licenses +and/or conditions as appropriate for your application. + +

Trademarks

+ +

Easy Software Products has trademarked the Common UNIX Printing +System, CUPS, and CUPS logo. These names and logos may be used freely +in any direct port or binary distribution of CUPS. To use them in +derivative products, please contract Easy Software Products for written +permission. Our intention is to protect the value of these trademarks and +ensure that any derivative product meets the same high-quality +standards as the original. + +

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, additions, and modifications to +CUPS under the GNU GPL and LGPL. For information please contact us at +the address shown above. + +

The Common UNIX Printing System provides a "pstoraster" filter that +utilizes the GNU GhostScript 5.50 core 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 +
+ +

The "pdftops" filter is based on the Xpdf 0.90 software. For binary +distribution licensing of this software, please contact: + +

+Derek B. Noonburg
+Email: derekn@foolabs.com
+WWW: http://www.foolabs.com/xpdf/ +
+ +

Support

+ +

Easy Software Products sells software support for CUPS as well as a +commercial printing product based on CUPS called ESP Print Pro. You can +find out more at our web site: + +

+ + +

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

+ + +

GNU LIBRARY GENERAL PUBLIC LICENSE

+ +

Version 2, June 1991 + +

+Copyright (C) 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.
+
+[This is the first released version of the library GPL.  It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ +

Preamble

+ +

The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + +

This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, 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 library, or if you modify it. + +

For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + +

Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + +

Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, 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 companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + +

Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + +

The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + +

Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + +

However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + +

The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + +

Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + +

TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

+ +

0. +This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + +

A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + +

The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + +

"Source code" for a work means the preferred form of the work for +making modifications to it. For a library, 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 library. + +

Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + +

1. +You may copy and distribute verbatim copies of the Library's +complete 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 distribute a copy of this License along with the +Library. + +

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

2. +You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, 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. The modified work must itself be a software library. + +

    +

  2. You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + +

    +

  3. You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + +

    +

  4. If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + +

    (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +

+ +

These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +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 Library, 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 Library. + +

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

3. +You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + +

Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + +

This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + +

4. +You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you 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. + +

If distribution of 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 satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + +

5. +A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + +

However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + +

When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + +

If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + +

Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + +

6. +As an exception to the Sections above, you may also compile or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + +

You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + +

    + +
  1. Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + +

    +

  2. Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + +

    +

  3. If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + +

    +

  4. Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + +
+ +

For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. 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. + +

It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + +

7. +You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + +

    + +
  1. Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + +

    +

  2. Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + +
+ +

8. +You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library 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. + +

9. +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 Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + +

10. +Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +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. + +

11. +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 Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library 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 Library. + +

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

12. +If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library 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. + +

13. +The Free Software Foundation may publish revised and/or new +versions of the Library 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 Library +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 Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + +

14. +If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +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 + +

15. +BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "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 +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +

16. +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 LIBRARY 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 +LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), 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..fae98172e4 --- /dev/null +++ b/Makedefs.in @@ -0,0 +1,166 @@ +# +# "$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 = @LIBTOOL@ @CC@ +CHMOD = @CHMOD@ +CP = @CP@ +CXX = @LIBTOOL@ @CXX@ +DSO = @DSO@ +HTMLDOC = @HTMLDOC@ +LIBTOOL = @LIBTOOL@ +LN = /bin/ln -sf +MKDIR = @MKDIR@ -p +MV = @MV@ +NROFF = @NROFF@ +RANLIB = @RANLIB@ +RM = @RM@ -f +SED = @SED@ +SHELL = /bin/sh + +# +# Installation programs... +# + +INSTALL_BIN = $(LIBTOOL) $(CP) +INSTALL_DATA = $(CP) +INSTALL_LIB = $(LIBTOOL) $(CP) +INSTALL_MAN = $(CP) +INSTALL_SCRIPT = $(CP) +INSTALL_SYSV = @INSTALL_SYSV@ + +# +# Libraries... +# + +LIBCUPS = @LIBCUPS@ +LIBCUPSIMAGE = @LIBCUPSIMAGE@ +LIBJPEG = @LIBJPEG@ +LIBMALLOC = @LIBMALLOC@ +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) +CXXFLAGS = @CXXFLAGS@ $(OPTIM) -I.. $(OPTIONS) +DSOLIBS = @DSOLIBS@ +IMGLIBS = @IMGLIBS@ -lm +LDFLAGS = @LDFLAGS@ $(OPTIM) +LINKCUPS = @LINKCUPS@ +LINKCUPSIMAGE = @LINKCUPSIMAGE@ +LIBS = $(LINKCUPS) $(NETLIBS) @LIBS@ +NETLIBS = @NETLIBS@ +OPTIM = @OPTIM@ +OPTIONS = +SSLLIBS = @SSLLIBS@ + +# +# 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_DOCROOT@ +INCLUDEDIR = $(includedir) +INITDIR = @INITDIR@ +INITDDIR = @INITDDIR@ +LIBDIR = $(libdir) +LOCALEDIR = @CUPS_LOCALEDIR@ +LOGDIR = @CUPS_LOGDIR@ +MANDIR = @mandir@ +PAMDIR = @PAMDIR@ +REQUESTS = @CUPS_REQUESTS@ +SBINDIR = @sbindir@ +SERVERBIN = @CUPS_SERVERBIN@ +SERVERROOT = @CUPS_SERVERROOT@ + +CAT1EXT = @CAT1EXT@ +CAT5EXT = @CAT5EXT@ +CAT8EXT = @CAT8EXT@ + +# +# Rules... +# + +.SILENT: +.SUFFIXES: .a .c .cxx .h .man .o .0 .1 .5 .8 .z +.c.o: + echo Compiling $<... + $(CC) $(CFLAGS) -c $< +.cxx.o: + echo Compiling $<... + $(CXX) $(CXXFLAGS) -c $< +.man.0 .man.1 .man.5 .man.8: + echo Formatting $<... + $(RM) $@ + $(NROFF) -man $< >$@ +.man.z: + echo Formatting $<... + $(RM) $@ t.z + $(NROFF) -man $< >t + pack -f t + $(MV) t.z $@ + +# +# End of "$Id$" +# diff --git a/Makefile b/Makefile new file mode 100644 index 0000000000..50a97a24cc --- /dev/null +++ b/Makefile @@ -0,0 +1,127 @@ +# +# "$Id$" +# +# Top-level 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 + +# +# Directories to make... +# + +DIRS = cups backend berkeley cgi-bin filter man pdftops pstoraster \ + scheduler systemv + +# +# Make all targets... +# + +all: + for dir in $(DIRS); do\ + echo Making all in $$dir... ;\ + (cd $$dir ; $(MAKE) $(MFLAGS)) || exit 1;\ + done + +# +# Remove object and target files... +# + +clean: + for dir in $(DIRS); do\ + echo Cleaning in $$dir... ;\ + (cd $$dir; $(MAKE) $(MFLAGS) clean) || exit 1;\ + done + +# +# Install object and target files... +# + +install: + for dir in $(DIRS); do\ + echo Installing in $$dir... ;\ + (cd $$dir; $(MAKE) $(MFLAGS) install) || exit 1;\ + done + echo Installing in conf... + (cd conf; $(MAKE) $(MFLAGS) install) + echo Installing in data... + (cd data; $(MAKE) $(MFLAGS) install) + echo Installing in doc... + (cd doc; $(MAKE) $(MFLAGS) install) + echo Installing in fonts... + (cd fonts; $(MAKE) $(MFLAGS) install) + echo Installing in locale... + (cd locale; $(MAKE) $(MFLAGS) install) + echo Installing in ppd... + (cd ppd; $(MAKE) $(MFLAGS) install) + echo Installing in templates... + (cd templates; $(MAKE) $(MFLAGS) install) + echo Installing startup script... + if test "x$(INITDIR)" != "x"; then \ + $(MKDIR) $(prefix)/$(INITDIR)/init.d; \ + $(RM) $(prefix)/$(INITDIR)/init.d/cups; \ + $(INSTALL_SCRIPT) cups.sh $(prefix)/$(INITDIR)/init.d/cups; \ + $(CHMOD) ugo+rx $(prefix)/$(INITDIR)/init.d/cups; \ + $(MKDIR) $(prefix)/$(INITDIR)/rc0.d; \ + $(RM) $(prefix)/$(INITDIR)/rc0.d/K00cups; \ + ln -s $(INITDDIR)/cups $(prefix)/$(INITDIR)/rc0.d/K00cups; \ + $(MKDIR) $(prefix)/$(INITDIR)/rc3.d; \ + $(RM) $(prefix)/$(INITDIR)/rc3.d/S99cups; \ + ln -s $(INITDDIR)/cups $(prefix)/$(INITDIR)/rc3.d/S99cups; \ + $(MKDIR) $(prefix)/$(INITDIR)/rc5.d; \ + $(RM) $(prefix)/$(INITDIR)/rc5.d/S99cups; \ + ln -s $(INITDDIR)/cups $(prefix)/$(INITDIR)/rc5.d/S99cups; \ + fi + +# +# Make software distributions using EPM (http://www.easysw.com/epm)... +# + +EPMFLAGS = -v \ + BINDIR=$(BINDIR) DATADIR=$(DATADIR) \ + DOCDIR=$(DOCDIR) INCLUDEDIR=$(INCLUDEDIR) \ + LIBDIR=$(LIBDIR) LOCALEDIR=$(LOCALEDIR) \ + LOGDIR=$(LOGDIR) MANDIR=$(MANDIR) \ + PAMDIR=$(PAMDIR) REQUESTS=$(REQUESTS) \ + SBINDIR=$(SBINDIR) SERVERBIN=$(SERVERBIN) \ + SERVERROOT=$(SERVERROOT) + +epm: + epm $(EPMFLAGS) cups + +rpm: + epm $(EPMFLAGS) -f rpm cups + +deb: + epm $(EPMFLAGS) -f deb cups + +depot: + epm $(EPMFLAGS) -f depot cups + +pkg: + epm $(EPMFLAGS) -f pkg cups + +tardist: + epm $(EPMFLAGS) -f tardist cups + +# +# End of "$Id$". +# diff --git a/README.txt b/README.txt new file mode 100644 index 0000000000..fefbd38075 --- /dev/null +++ b/README.txt @@ -0,0 +1,276 @@ +README - CUPS v1.1.5 - 12/20/2000 +--------------------------------- + +Looking for compile instructions? Read the file "INSTALL.txt" +instead... + + +INTRODUCTION + +CUPS provides a portable printing layer for UNIX(r)-based +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 ("IPP") as the basis +for managing print jobs and queues. The Line Printer Daemon +("LPD") Server Message Block ("SMB"), and AppSocket (a.k.a. +JetDirect) protocols are also supported with reduced +functionality. CUPS adds network printer browsing and +PostScript Printer Description ("PPD") based printing options to +support real-world printing under UNIX. + +CUPS also includes a customized version of GNU Ghostscript +(currently based off GNU Ghostscript 5.50) and an image file RIP +that are used to support non-PostScript printers. Sample +drivers for HP and EPSON printers are included that use these +filters. + +Drivers for over 2300 printers are provided with our ESP Print +Pro software, available at: + + http://www.easysw.com/printpro + +CUPS is licensed under the GNU General Public License and GNU +Library General Public License. Please contact Easy Software +Products for commercial support and "binary distribution" +rights. + + +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 ANSI-compliant C +and C++ compilers and optionally one or more image file support +libraries. Complete source installation instructions can be +found in the file "INSTALL.txt". + + +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 "PORTABLE" CUPS DISTRIBUTIONS + +We are currently distributing "portable" 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. + + +INSTALLING HOST-SPECIFIC (RPM, DEBIAN, ETC.) DISTRIBUTIONS + +The host-specific distributions use the operating system +software installation tools. To install a host-specific +distribution please consult the CUPS Software Administrators +Manual or your operating system documentation. + + +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/doc/cups" directory in the binary +distributions, and under the "doc" directory in the source +archives. + +Please read the documentation before asking questions. + + +GETTING SUPPORT AND OTHER RESOURCES + +If you have problems, READ THE DOCUMENTATION FIRST! + +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. + +Commercial support (with a guaranteed response time) is +available from Easy Software Products. For more information +see: + + http://www.easysw.com/cups + +See the CUPS web site at "http://www.cups.org" for other site +links. + + +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. + +DO NOT use the hostname for your machine - it will not work with +the default CUPS configuration. To enable administration access +on other addresses, consult the CUPS Software Administrators +Manual. + + +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 + EPSON 24-pin Series epson24.ppd + +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 PDF, +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. + + +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. + +The MD5 Digest code is Copyright 1999 Aladdin Enterprises. + +The PostScript RIP software (pstoraster) is based on the GNU +Ghostscript 5.50 core, Copyright 1986-1998 by Aladdin +Enterprises. + +The PDF filter (pdftops) is based on the Xpdf 0.90 software, +Copyright 1996-1999 by Derek B. Noonburg. + +This software is based in part on the work of the Independent +JPEG Group. + +CUPS is provided under the terms of the GNU General Public +License and GNU Library General Public License. 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 "LICENSE.html", +"LICENSE.txt", or "cups.license" files for more information. + +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 + +Note that commercial licensors may also require a license from +Artifex Software Inc. which handles commercial licensing of the +Ghostscript software, and from Derek B. Noonburg who developed +the Xpdf software used to print PDF files. diff --git a/backend/Makefile b/backend/Makefile new file mode 100644 index 0000000000..be7b7f7a2d --- /dev/null +++ b/backend/Makefile @@ -0,0 +1,141 @@ +# +# "$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) $(OBJS) $(TARGETS) http + + +# +# Install all targets... +# + +install: + -$(MKDIR) $(SERVERBIN)/backend + $(CHMOD) ugo+rx $(SERVERBIN) + $(CHMOD) ugo+rx $(SERVERBIN)/backend + $(INSTALL_BIN) $(BACKENDS) $(SERVERBIN)/backend + $(RM) $(SERVERBIN)/backend/http + $(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) + $(RM) http + $(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..c407330f32 --- /dev/null +++ b/backend/ipp.c @@ -0,0 +1,659 @@ +/* + * "$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 +#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 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 */ + ipp_attribute_t *charset_sup; /* charset-supported attribute */ + const char *charset; /* Character set to use */ + 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 defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) + struct sigaction action; /* Actions for POSIX signals */ +#endif /* HAVE_SIGACTION && !HAVE_SIGSET */ + int version; /* IPP version */ + + + if (argc == 1) + { + char *s; + + 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(); + charset_sup = NULL; + copies_sup = NULL; + version = 1; + + do + { + /* + * Build the IPP request... + */ + + request = ippNew(); + request->request.op.version[1] = version; + 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, "utf-8"); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, + "attributes-natural-language", NULL, + language != NULL ? language->language : "en"); + + 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 (response = NULL, ipp_status = IPP_ERROR;;) + { + /* + * 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 if (ipp_status == IPP_BAD_REQUEST && version == 1) + { + /* + * Switch to IPP/1.0... + */ + + fputs("INFO: Printer does not support IPP/1.1, trying IPP/1.0...\n", stderr); + version = 0; + } + else + { + fprintf(stderr, "ERROR: Printer will not accept print file (%x)!\n", + ipp_status); + fprintf(stderr, "ERROR: %s\n", ippErrorString(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 */ + } + + charset_sup = ippFindAttribute(response, "charset-supported", + IPP_TAG_CHARSET); + } + else + { + response = NULL; + + 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); + ipp_status = IPP_FORBIDDEN; + } + } + + httpFlush(http); + + break; + } + + if (status != HTTP_OK) + { + if (fp != stdin) + fclose(fp); + + httpClose(http); + + return (1); + } + else if (ipp_status > IPP_OK_CONFLICT) + httpReconnect(http); + } + while (ipp_status > IPP_OK_CONFLICT); + + /* + * Now that we are "connected" to the port, ignore SIGTERM so that we + * can finish out any page data the driver sends (e.g. to eject the + * current page... + */ + +#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ + sigset(SIGTERM, SIG_IGN); +#elif defined(HAVE_SIGACTION) + memset(&action, 0, sizeof(action)); + + sigemptyset(&action.sa_mask); + action.sa_handler = SIG_IGN; + sigaction(SIGTERM, &action, NULL); +#else + signal(SIGTERM, SIG_IGN); +#endif /* HAVE_SIGSET */ + + /* + * See if the printer supports multiple copies... + */ + + if (copies_sup) + copies = 1; + else + copies = atoi(argv[4]); + + /* + * Figure out the character set to use... + */ + + charset = language ? cupsLangEncoding(language) : "us-ascii"; + + if (charset_sup) + { + /* + * See if IPP server supports the requested character set... + */ + + for (i = 0; i < charset_sup->num_values; i ++) + if (strcasecmp(charset, charset_sup->values[i].string.text) == 0) + break; + + /* + * If not, choose us-ascii or utf-8... + */ + + if (i >= charset_sup->num_values) + { + /* + * See if us-ascii is supported... + */ + + for (i = 0; i < charset_sup->num_values; i ++) + if (strcasecmp("us-ascii", charset_sup->values[i].string.text) == 0) + break; + + if (i < charset_sup->num_values) + charset = "us-ascii"; + else + charset = "utf-8"; + } + } + + if (response) + ippDelete(response); + + /* + * Then issue the print-job request... + */ + + while (copies > 0) + { + /* + * Build the IPP request... + */ + + request = ippNew(); + request->request.op.version[1] = version; + 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, charset); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, + "attributes-natural-language", NULL, + language != NULL ? language->language : "en"); + + 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 ((content_type = getenv("CONTENT_TYPE")) != NULL && + strcasecmp(content_type, "application/vnd.cups-raw") == 0) + num_options = cupsAddOption("raw", "", num_options, &options); + + cupsEncodeOptions(request, num_options, options); + cupsFreeOptions(num_options, options); + + if (copies_sup) + ippAddInteger(request, IPP_TAG_JOB, IPP_TAG_INTEGER, "copies", atoi(argv[4])); + + /* + * 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); + fprintf(stderr, "ERROR: %s\n", ippErrorString(ipp_status)); + } + } + 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..720c4311b3 --- /dev/null +++ b/backend/lpd.c @@ -0,0 +1,536 @@ +/* + * "$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 +#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, char *title, int copies, int banner, + int format); + + +/* + * '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) */ + *options, /* Pointer to options */ + name[255], /* Name of option */ + value[255], /* Value of option */ + *ptr, /* Pointer into name or value */ + filename[1024]; /* File to print */ + int port; /* Port number (not used) */ + int status; /* Status of LPD job */ + int banner; /* Print banner page? */ + int format; /* Print format */ + + + 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); + + /* + * See if there are any options... + */ + + banner = 0; + format = 'l'; + + if ((options = strchr(resource, '?')) != NULL) + { + /* + * Yup, terminate the device name string and move to the first + * character of the options... + */ + + *options++ = '\0'; + + /* + * Parse options... + */ + + 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, "banner") == 0) + { + /* + * Set the banner... + */ + + banner = !value[0] || + strcasecmp(value, "on") == 0 || + strcasecmp(value, "yes") == 0 || + strcasecmp(value, "true") == 0; + } + else if (strcasecmp(name, "format") == 0 && value[0]) + { + /* + * Set output format... + */ + + if (strchr("cdfglnoprtv", value[0]) != NULL) + format = value[0]; + else + fprintf(stderr, "ERROR: Unknown format character \"%c\"\n", value[0]); + } + } + } + + /* + * Queue the job... + */ + + if (argc > 6) + { + status = lpd_queue(hostname, resource + 1, filename, + argv[2] /* user */, argv[3] /* title */, + atoi(argv[4]) /* copies */, banner, format); + + if (!status) + fprintf(stderr, "PAGE: 1 %d\n", atoi(argv[4])); + } + else + status = lpd_queue(hostname, resource + 1, filename, + argv[2] /* user */, argv[3] /* title */, 1, + banner, format); + + /* + * 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 %2.2x %s", buf[0], buf + 1); + + /* + * Send the command... + */ + + fprintf(stderr, "DEBUG: Sending command string (%d bytes)...\n", bytes); + + if (send(fd, buf, bytes, 0) < bytes) + return (-1); + + /* + * Read back the status from the command and return it... + */ + + fprintf(stderr, "DEBUG: Reading command status...\n"); + + 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 */ + char *title, /* I - Job title */ + int copies, /* I - Number of copies */ + int banner, /* I - Print LPD banner? */ + int format) /* I - Format specifier */ +{ + 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 */ +#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) + struct sigaction action; /* Actions for POSIX signals */ +#endif /* HAVE_SIGACTION && !HAVE_SIGSET */ + + + /* + * 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; + } + + fprintf(stderr, "INFO: Connected on port %d...\n", port); + + /* + * Now that we are "connected" to the port, ignore SIGTERM so that we + * can finish out any page data the driver sends (e.g. to eject the + * current page... + */ + +#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ + sigset(SIGTERM, SIG_IGN); +#elif defined(HAVE_SIGACTION) + memset(&action, 0, sizeof(action)); + + sigemptyset(&action.sa_mask); + action.sa_handler = SIG_IGN; + sigaction(SIGTERM, &action, NULL); +#else + signal(SIGTERM, SIG_IGN); +#endif /* HAVE_SIGSET */ + + /* + * 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\nJ%s\n", localhost, user, title); + cptr = control + strlen(control); + + if (banner) + { + snprintf(cptr, sizeof(control) - (cptr - control), "L%s\n", user); + cptr += strlen(cptr); + } + + while (copies > 0) + { + snprintf(cptr, sizeof(control) - (cptr - control), "%cdfA%03d%s\n", format, + getpid() % 1000, localhost); + cptr += strlen(cptr); + copies --; + } + + snprintf(cptr, sizeof(control) - (cptr - control), + "UdfA%03d%s\nNdfA%03d%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..0ab93cfa08 --- /dev/null +++ b/backend/parallel.c @@ -0,0 +1,589 @@ +/* + * "$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 +#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 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 termios opts; /* Parallel port options */ +#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) + struct sigaction action; /* Actions for POSIX signals */ +#endif /* HAVE_SIGACTION && !HAVE_SIGSET */ + + + 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... + */ + + do + { + if ((fd = open(resource, O_WRONLY | O_EXCL)) == -1) + { + if (errno == EBUSY) + { + fputs("INFO: Parallel port busy; will retry in 30 seconds...\n", stderr); + sleep(30); + } + else + { + perror("ERROR: Unable to open parallel port device file"); + return (1); + } + } + } + while (fd < 0); + + /* + * Set any options provided... + */ + + tcgetattr(fd, &opts); + + opts.c_lflag &= ~(ICANON | ECHO | ISIG); /* Raw mode */ + + /**** No options supported yet ****/ + + tcsetattr(fd, TCSANOW, &opts); + + /* + * Now that we are "connected" to the port, ignore SIGTERM so that we + * can finish out any page data the driver sends (e.g. to eject the + * current page... + */ + +#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ + sigset(SIGTERM, SIG_IGN); +#elif defined(HAVE_SIGACTION) + memset(&action, 0, sizeof(action)); + + sigemptyset(&action.sa_mask); + action.sa_handler = SIG_IGN; + sigaction(SIGTERM, &action, NULL); +#else + signal(SIGTERM, SIG_IGN); +#endif /* HAVE_SIGSET */ + + /* + * 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... + */ + + tbytes += nbytes; + bufptr = buffer; + + while (nbytes > 0) + { + if ((wbytes = write(fd, bufptr, nbytes)) < 0) + if (errno == ENOTTY) + wbytes = write(fd, bufptr, nbytes); + + if (wbytes < 0) + { + perror("ERROR: Unable to send print file to printer"); + break; + } + + nbytes -= wbytes; + bufptr += wbytes; + } + + 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) +{ +#if defined(__hpux) || defined(__sgi) || defined(__sun) + static char *funky_hex = "0123456789abcdefghijklmnopqrstuvwxyz"; + /* Funky hex numbering used for some devices */ +#endif /* __hpux || __sgi || __sun */ + +#ifdef __linux + int i; /* Looping var */ + int fd; /* File descriptor */ + char device[255], /* Device filename */ + probefile[255]; /* Probe 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 ++) + { + /* + * First open the device to make sure the driver module is loaded... + */ + + sprintf(device, "/dev/lp%d", i); + if ((fd = open(device, O_WRONLY)) >= 0) + close(fd); + else + { + sprintf(device, "/dev/par%d", i); + if ((fd = open(device, O_WRONLY)) >= 0) + close(fd); + } + + /* + * Then try looking at the probe file... + */ + + sprintf(probefile, "/proc/parport/%d/autoprobe", i); + if ((probe = fopen(probefile, "r")) == NULL) + { + /* + * Linux 2.4 kernel has different path... + */ + + sprintf(probefile, "/proc/sys/dev/parport/parport%d/autoprobe", i); + probe = fopen(probefile, "r"); + } + + if (probe != NULL) + { + /* + * Found a probe file! + */ + + 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 if (fd >= 0) + { + /* + * No probe file, but we know the port is there... + */ + + 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 */ + + + /* + * 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", + device, 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 */ + int fd; /* File descriptor */ + 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 */ + int fd; /* File descriptor */ + 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..1182b82909 --- /dev/null +++ b/backend/serial.c @@ -0,0 +1,846 @@ +/* + * "$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. + * list_devices() - List all serial devices. + */ + +/* + * Include necessary headers. + */ + +#include +#include +#include +#include +#include +#include + +#ifdef __hpux +# include +#endif /* __hpux */ + +#if defined(WIN32) || defined(__EMX__) +# include +#else +# include +# include +# include +# ifdef HAVE_SYS_IOCTL_H +# include +# endif /* __linux */ +#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 */ + +#ifndef CRTSCTS +# ifdef CNEW_RTSCTS +# define CRTSCTS CNEW_RTSCTS +# else +# define CRTSCTS 0 +# endif /* CNEW_RTSCTS */ +#endif /* !CRTSCTS */ + + +/* + * 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 wbytes; /* Number of bytes written */ + size_t nbytes, /* Number of bytes read */ + tbytes; /* Total number of bytes written */ + int dtrdsr; /* Do dtr/dsr flow control? */ + int bufsize; /* Size of output buffer for writes */ + char buffer[8192], /* Output buffer */ + *bufptr; /* Pointer into buffer */ + struct termios opts; /* Parallel port options */ +#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) + struct sigaction action; /* Actions for POSIX signals */ +#endif /* HAVE_SIGACTION && !HAVE_SIGSET */ + + + 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... + */ + + do + { + if ((fd = open(resource, O_WRONLY | O_NOCTTY | O_EXCL)) == -1) + { + if (errno == EBUSY) + { + fputs("INFO: Serial port busy; will retry in 30 seconds...\n", stderr); + sleep(30); + } + else + { + perror("ERROR: Unable to open serial port device file"); + return (1); + } + } + } + while (fd < 0); + + /* + * Set any options provided... + */ + + tcgetattr(fd, &opts); + + opts.c_lflag &= ~(ICANON | ECHO | ISIG); /* Raw mode */ + + bufsize = 480; /* 9600 baud / 10 bits/char / 2Hz */ + dtrdsr = 0; /* No dtr/dsr flow control */ + + 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... + */ + + bufsize = atoi(value) / 20; + +#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; +#ifdef B57600 + case 57600 : + cfsetispeed(&opts, B57600); + cfsetospeed(&opts, B57600); + break; +#endif /* B57600 */ +#ifdef B115200 + case 115200 : + cfsetispeed(&opts, B115200); + cfsetospeed(&opts, B115200); + break; +#endif /* B115200 */ + 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; + } + else if (strcasecmp(name, "flow") == 0) + { + /* + * Set flow control... + */ + + if (strcasecmp(value, "none") == 0) + { + opts.c_iflag &= ~(IXON | IXOFF | IXANY); + opts.c_cflag &= ~CRTSCTS; + } + else if (strcasecmp(value, "soft") == 0) + { + opts.c_iflag |= IXON | IXOFF | IXANY; + opts.c_cflag &= ~CRTSCTS; + } + else if (strcasecmp(value, "hard") == 0 || + strcasecmp(value, "rtscts") == 0) + { + opts.c_iflag &= ~(IXON | IXOFF | IXANY); + opts.c_cflag |= CRTSCTS; + } + else if (strcasecmp(value, "dtrdsr") == 0) + { + opts.c_iflag &= ~(IXON | IXOFF | IXANY); + opts.c_cflag &= ~CRTSCTS; + + dtrdsr = 1; + } + } + } + + tcsetattr(fd, TCSANOW, &opts); + + /* + * Now that we are "connected" to the port, ignore SIGTERM so that we + * can finish out any page data the driver sends (e.g. to eject the + * current page... + */ + +#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ + sigset(SIGTERM, SIG_IGN); +#elif defined(HAVE_SIGACTION) + memset(&action, 0, sizeof(action)); + + sigemptyset(&action.sa_mask); + action.sa_handler = SIG_IGN; + sigaction(SIGTERM, &action, NULL); +#else + signal(SIGTERM, SIG_IGN); +#endif /* HAVE_SIGSET */ + + /* + * Finally, send the print file... + */ + + if (bufsize > sizeof(buffer)) + bufsize = sizeof(buffer); + + while (copies > 0) + { + copies --; + + if (fp != stdin) + { + fputs("PAGE: 1 1\n", stderr); + rewind(fp); + } + + if (dtrdsr) + { + /* + * Check the port and sleep until DSR is set... + */ + + int status; + + + if (!ioctl(fd, TIOCMGET, &status)) + if (!(status & TIOCM_DSR)) + { + /* + * Wait for DSR to go high... + */ + + fputs("DEBUG: DSR is low; waiting for device...\n", stderr); + + do + { + sleep(1); + if (ioctl(fd, TIOCMGET, &status)) + break; + } + while (!(status & TIOCM_DSR)); + + fputs("DEBUG: DSR is high; writing to device...\n", stderr); + } + } + + tbytes = 0; + while ((nbytes = fread(buffer, 1, bufsize, fp)) > 0) + { + /* + * Write the print data to the printer... + */ + + tbytes += nbytes; + bufptr = buffer; + + while (nbytes > 0) + { + if ((wbytes = write(fd, bufptr, nbytes)) < 0) + if (errno == ENOTTY) + wbytes = write(fd, bufptr, nbytes); + + if (wbytes < 0) + { + perror("ERROR: Unable to send print file to printer"); + break; + } + + nbytes -= wbytes; + bufptr += wbytes; + } + + 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) +{ +#if defined(__hpux) || defined(__sgi) || defined(__sun) || defined(__FreeBSD__) || defined(__OpenBSD__) + static char *funky_hex = "0123456789abcdefghijklmnopqrstuvwxyz"; + /* Funky hex numbering used for some devices */ +#endif /* __hpux || __sgi || __sun || __FreeBSD__ || __OpenBSD__ */ + +#ifdef __linux + int i; /* Looping var */ + int fd; /* File descriptor */ + char device[255]; /* Device filename */ + + + for (i = 0; i < 100; i ++) + { + sprintf(device, "/dev/ttyS%d", i); + if ((fd = open(device, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 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 * (int)inv->inv_controller; + + for (n = 0; n < (int)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, (int)inv->inv_controller); + } + else if (inv->inv_state > 1) + { + /* + * Standard serial port under IRIX 6.4 and earlier... + */ + + for (n = 0; n < (int)inv->inv_state; n ++) + printf("serial serial:/dev/ttyd%d?baud=19200 \"Unknown\" \"Onboard Serial Port %d\"\n", + n + (int)inv->inv_unit + 1, n + (int)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", + (int)inv->inv_controller, (int)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) +#ifdef B115200 + printf("serial serial:%s?baud=115200 \"Unknown\" \"Serial Port #%d\"\n", + device, i + 1); +#else + printf("serial serial:%s?baud=38400 \"Unknown\" \"Serial Port #%d\"\n", + device, i + 1); +#endif /* B115200 */ + } + + /* + * 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__) + 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 | O_NDELAY)) >= 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 | O_NDELAY)) >= 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 | O_NDELAY)) >= 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 | O_NDELAY)) >= 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 | O_NDELAY)) >= 0) + { + close(fd); + printf("serial serial:%s?baud=115200 \"Unknown\" \"SX Serial Port #%d\"\n", + device, i + 1); + } + } ++#elif defined(__NetBSD__) + int i, j; /* Looping vars */ + int fd; /* File descriptor */ + char device[255]; /* Device filename */ + + + /* + * Standard serial ports... + */ + + for (i = 0; i < 4; i ++) + { + sprintf(device, "/dev/tty%02d", i); + if ((fd = open(device, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0) + { + close(fd); + printf("serial serial:%s?baud=115200 \"Unknown\" \"Serial Port #%d\"\n", + device, i + 1); + } + } + + /* + * Cyclades-Z ports... + */ + + for (i = 0; i < 16; i ++) /* Should be up to 65536 boards... */ + for (j = 0; j < 64; j ++) + { + sprintf(device, "/dev/ttyCZ%02d%02d", i, j); + if ((fd = open(device, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0) + { + close(fd); + printf("serial serial:%s?baud=115200 \"Unknown\" \"Cyclades #%d Serial Prt #%d\"\n", + device, i, j + 1); + } + } + +#endif +} + + +/* + * End of "$Id$". + */ diff --git a/backend/socket.c b/backend/socket.c new file mode 100644 index 0000000000..bc21f88521 --- /dev/null +++ b/backend/socket.c @@ -0,0 +1,281 @@ +/* + * "$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 +#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 defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) + struct sigaction action; /* Actions for POSIX signals */ +#endif /* HAVE_SIGACTION && !HAVE_SIGSET */ + + + 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\n", + 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; + } + + /* + * Now that we are "connected" to the port, ignore SIGTERM so that we + * can finish out any page data the driver sends (e.g. to eject the + * current page... + */ + +#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ + sigset(SIGTERM, SIG_IGN); +#elif defined(HAVE_SIGACTION) + memset(&action, 0, sizeof(action)); + + sigemptyset(&action.sa_mask); + action.sa_handler = SIG_IGN; + sigaction(SIGTERM, &action, NULL); +#else + signal(SIGTERM, SIG_IGN); +#endif /* HAVE_SIGSET */ + + /* + * 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..c804e910e1 --- /dev/null +++ b/backend/usb.c @@ -0,0 +1,412 @@ +/* + * "$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 +#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 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 termios opts; /* Parallel port options */ +#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) + struct sigaction action; /* Actions for POSIX signals */ +#endif /* HAVE_SIGACTION && !HAVE_SIGSET */ + + + 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... + */ + + do + { + if ((fd = open(resource, O_WRONLY | O_EXCL)) == -1) + { + if (errno == EBUSY) + { + fputs("INFO: USB port busy; will retry in 30 seconds...\n", stderr); + sleep(30); + } + else + { + perror("ERROR: Unable to open USB port device file"); + return (1); + } + } + } + while (fd < 0); + + /* + * Set any options provided... + */ + + tcgetattr(fd, &opts); + + opts.c_lflag &= ~(ICANON | ECHO | ISIG); /* Raw mode */ + + /**** No options supported yet ****/ + + tcsetattr(fd, TCSANOW, &opts); + + /* + * Now that we are "connected" to the port, ignore SIGTERM so that we + * can finish out any page data the driver sends (e.g. to eject the + * current page... + */ + +#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ + sigset(SIGTERM, SIG_IGN); +#elif defined(HAVE_SIGACTION) + memset(&action, 0, sizeof(action)); + + sigemptyset(&action.sa_mask); + action.sa_handler = SIG_IGN; + sigaction(SIGTERM, &action, NULL); +#else + signal(SIGTERM, SIG_IGN); +#endif /* HAVE_SIGSET */ + + /* + * 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... + */ + + tbytes += nbytes; + bufptr = buffer; + + while (nbytes > 0) + { + if ((wbytes = write(fd, bufptr, nbytes)) < 0) + if (errno == ENOTTY) + wbytes = write(fd, bufptr, nbytes); + + if (wbytes < 0) + { + perror("ERROR: Unable to send print file to printer"); + break; + } + + nbytes -= wbytes; + bufptr += wbytes; + } + + 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/bus/usb/devices 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 */ + + + /* + * First try opening one of the USB devices to load the driver + * module as needed... + */ + + if ((fd = open("/dev/usb/lp0", O_WRONLY)) >= 0) + close(fd); /* 2.3.x and 2.4.x */ + else if ((fd = open("/dev/usb/usblp0", O_WRONLY)) >= 0) + close(fd); /* Mandrake 7.x */ + else if ((fd = open("/dev/usblp0", O_WRONLY)) >= 0) + close(fd); /* 2.2.x */ + + /* + * Then look at the device list for the USB bus... + */ + + if ((probe = fopen("/proc/bus/usb/devices", "r")) != NULL) + { + /* + * Scan the device list... + */ + + 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 || + strstr(line, "Driver=usblp") != NULL) && + make[0] && model[0]) + { + /* + * We were processing a printer device; send the info out... + */ + + sprintf(device, "/dev/usb/lp%d", i); + if (access(device, 0)) + { + sprintf(device, "/dev/usb/usblp%d", i); + + if (access(device, 0)) + sprintf(device, "/dev/usblp%d", i); + } + + printf("direct usb:%s \"%s %s\" \"USB Printer #%d\"\n", + device, make, model, i + 1); + + i ++; + + memset(make, 0, sizeof(make)); + memset(model, 0, sizeof(model)); + } + } + + fclose(probe); + } + else + { + /* + * Just probe manually for USB devices... + */ + + for (i = 0; i < 8; i ++) + { + sprintf(device, "/dev/usb/lp%d", i); + if ((fd = open(device, O_WRONLY)) >= 0) + { + close(fd); + printf("direct usb:%s \"Unknown\" \"USB Printer #%d\"\n", device, i + 1); + } + + 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); + } + + sprintf(device, "/dev/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__) + int i; /* Looping var */ + int fd; /* File descriptor */ + char device[255]; /* Device filename */ + + + for (i = 0; i < 3; i ++) + { + sprintf(device, "/dev/ulpt%d", i); + if ((fd = open(device, O_WRONLY)) >= 0) + { + close(fd); + printf("direct usb:%s \"Unknown\" \"USB Port #%d\"\n", device, i + 1); + } + } +#endif +} + + +/* + * End of "$Id$". + */ diff --git a/berkeley/Makefile b/berkeley/Makefile new file mode 100644 index 0000000000..e56596172e --- /dev/null +++ b/berkeley/Makefile @@ -0,0 +1,105 @@ +# +# "$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) $(OBJS) $(TARGETS) + + +# +# Install all targets... +# + +install: + -$(MKDIR) $(BINDIR) + $(CHMOD) ugo+rx $(BINDIR) + $(INSTALL_BIN) lpq lpr lprm $(BINDIR) + -$(MKDIR) $(SBINDIR) + $(CHMOD) ugo+rx $(SBINDIR) + $(INSTALL_BIN) 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..d54d51bb1c --- /dev/null +++ b/berkeley/lpc.c @@ -0,0 +1,481 @@ +/* + * "$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 */ +{ + 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 */ + *jattr; /* Current job 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 */ + static const char *requested[] = + { /* Requested attributes */ + "printer-name", + "device-uri", + "printer-state", + "printer-is-accepting-jobs" + }; + + + 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(); + + 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); + + ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, + "requested-attributes", sizeof(requested) / sizeof(requested[0]), + NULL, requested); + + /* + * 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); + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, + "printer-uri", NULL, printer_uri); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, + "requested-attributes", NULL, "job-id"); + + if ((jobs = cupsDoRequest(http, request, "/jobs/")) != NULL) + { + for (jattr = jobs->attrs; jattr != NULL; jattr = jattr->next) + if (jattr->name && strcmp(jattr->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..ec7cdb89ec --- /dev/null +++ b/berkeley/lpq.c @@ -0,0 +1,517 @@ +/* + * "$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. + * show_printer() - Show printer status. + */ + +/* + * 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 */ + char *instance; /* Printer instance */ + int id, /* Desired job ID */ + interval, /* Reporting interval */ + longstatus; /* Show file details */ + int num_dests; /* Number of destinations */ + cups_dest_t *dests; /* Destinations */ + + + /* + * Connect to the scheduler... + */ + + http = httpConnect(cupsServer(), ippPort()); + + /* + * Check for command-line options... + */ + + dest = NULL; + user = NULL; + id = 0; + interval = 0; + longstatus = 0; + + num_dests = cupsGetDests(&dests); + + for (i = 0; i < num_dests; i ++) + if (dests[i].is_default) + dest = dests[i].name; + + 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]; + } + + if ((instance = strchr(dest, '/')) != NULL) + *instance = '\0'; + break; + + case 'l' : /* Long status */ + longstatus = 1; + break; + + default : + fputs("Usage: lpq [-P dest] [-l] [+interval]\n", stderr); + httpClose(http); + cupsFreeDests(num_dests, dests); + 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... + */ + + cupsFreeDests(num_dests, dests); + 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 */ +#ifdef __osf__ + jobpriority, /* job-priority */ +#endif /* __osf__ */ + 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, "printer-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, "/")) != 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; +#ifdef __osf__ + jobpriority = 50; +#endif /* __osf__ */ + 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; + +#ifdef __osf__ + if (strcmp(attr->name, "job-priority") == 0 && + attr->value_tag == IPP_TAG_INTEGER) + jobpriority = attr->values[0].integer; +#endif /* __osf__ */ + + 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) +#ifdef __osf__ + puts("Rank Owner Pri Job Files Total Size"); +#else + puts("Rank Owner Job File(s) Total Size"); +#endif /* __osf__ */ + + jobcount ++; + + /* + * Display the job... + */ + + if (jobstate == IPP_JOB_PROCESSING) + strcpy(rankstr, "active"); + else + { + snprintf(rankstr, sizeof(rankstr), "%d%s", rank, ranks[rank % 10]); + rank ++; + } + + if (longstatus) + { + puts(""); + + if (jobcopies > 1) + snprintf(namestr, sizeof(namestr), "%d copies of %s", jobcopies, + jobname); + else + { + strncpy(namestr, jobname, sizeof(namestr) - 1); + namestr[sizeof(namestr) - 1] = '\0'; + } + + printf("%s: %-34.34s[job %d localhost]\n", jobuser, rankstr, jobid); + printf(" %-40.40s%d bytes\n", namestr, jobsize); + } + else +#ifdef __osf__ + printf("%-6s %-10.10s %-4d %-10d %-27.27s %d bytes\n", rankstr, jobuser, + jobpriority, jobid, jobname, jobsize); +#else + printf("%-7s %-8.8s%-8d%-32.32s%d bytes\n", rankstr, jobuser, + jobid, jobname, jobsize); +#endif /* __osf */ + + 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 */ + 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); + + snprintf(uri, sizeof(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..55645914fc --- /dev/null +++ b/berkeley/lpr.c @@ -0,0 +1,357 @@ +/* + * "$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, j; /* Looping var */ + int job_id; /* Job ID */ + char *printer, /* Destination printer or class */ + *instance; /* Instance */ + const char *title; /* Job title */ + int num_copies; /* Number of copies per file */ + int num_files; /* Number of files to print */ + const char *files[1000]; /* Files to print */ + int num_dests; /* Number of destinations */ + cups_dest_t *dests, /* Destinations */ + *dest; /* Selected destination */ + int num_options; /* Number of options */ + cups_option_t *options; /* Options */ + int 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 */ + + + deletefile = 0; + printer = NULL; + num_dests = 0; + dests = NULL; + 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 = cupsAddOption("raw", "", num_options, &options); + break; + + case 'p' : /* Prettyprint */ + num_options = cupsAddOption("prettyprint", "", num_options, &options); + break; + + case 'h' : /* Suppress burst page */ + num_options = cupsAddOption("job-sheets", "none", num_options, &options); + break; + + 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') + printer = argv[i] + 2; + else + { + i ++; + printer = argv[i]; + } + + if ((instance = strrchr(printer, '/')) != NULL) + *instance++ = '\0'; + + if (num_dests == 0) + num_dests = cupsGetDests(&dests); + + if ((dest = cupsGetDest(printer, instance, num_dests, dests)) != NULL) + { + for (j = 0; j < dest->num_options; j ++) + if (cupsGetOption(dest->options[j].name, num_options, options) == NULL) + num_options = cupsAddOption(dest->options[j].name, + dest->options[j].value, + num_options, &options); + } + 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 if (num_files < 1000) + { + /* + * Print a file... + */ + + files[num_files] = argv[i]; + num_files ++; + + if (title == NULL) + { + if ((title = strrchr(argv[i], '/')) != NULL) + title ++; + else + title = argv[i]; + } + } + else + fprintf(stderr, "lpr: Too many files - \"%s\"\n", argv[i]); + /* + * See if we have any files to print; if not, print from stdin... + */ + + if (printer == NULL) + { + if (num_dests == 0) + num_dests = cupsGetDests(&dests); + + for (j = 0, dest = dests; j < num_dests; j ++, dest ++) + if (dest->is_default) + { + printer = dests[j].name; + + for (j = 0; j < dest->num_options; j ++) + if (cupsGetOption(dest->options[j].name, num_options, options) == NULL) + num_options = cupsAddOption(dest->options[j].name, + dest->options[j].value, + num_options, &options); + break; + } + } + + if (printer == NULL) + { + fputs("lpr: error - no default destination available.\n", stderr); + return (1); + } + + if (num_files > 0) + { + job_id = cupsPrintFiles(printer, num_files, files, title, num_options, options); + + if (deletefile) + { + /* + * Delete print files after printing... + */ + + for (i = 0; i < num_files; i ++) + unlink(files[i]); + } + } + else + { + num_files = 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: stdin is empty, so no job has been sent.\n", stderr); + return (1); + } + + if (title) + job_id = cupsPrintFile(printer, tempfile, title, num_options, options); + else + job_id = cupsPrintFile(printer, tempfile, "(stdin)", num_options, options); + + unlink(tempfile); + } + + if (job_id < 1) + { + fprintf(stderr, "lpr: unable to print file: %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..ba37c42f62 --- /dev/null +++ b/berkeley/lprm.c @@ -0,0 +1,243 @@ +/* + * "$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 *instance; /* Pointer to instance name */ + 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 */ + int num_dests; /* Number of destinations */ + cups_dest_t *dests; /* Destinations */ + + + /* + * Setup to cancel individual print jobs... + */ + + op = IPP_CANCEL_JOB; + job_id = 0; + dest = NULL; + response = NULL; + http = NULL; + + num_dests = cupsGetDests(&dests); + + for (i = 0; i < num_dests; i ++) + if (dests[i].is_default) + dest = dests[i].name; + + /* + * Open a connection to the server... + */ + + if ((http = httpConnect(cupsServer(), ippPort())) == NULL) + { + fputs("lprm: Unable to contact server!\n", stderr); + cupsFreeDests(num_dests, dests); + 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]; + } + + if ((instance = strchr(dest, '/')) != NULL) + *instance = '\0'; + break; + + default : + fprintf(stderr, "lprm: Unknown option \'%c\'!\n", argv[i][1]); + cupsFreeDests(num_dests, dests); + httpClose(http); + 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); + cupsFreeDests(num_dests, dests); + httpClose(http); + 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); + cupsFreeDests(num_dests, dests); + httpClose(http); + return (1); + } + + cupsFreeDests(num_dests, dests); + httpClose(http); + + return (0); +} + + +/* + * End of "$Id$". + */ diff --git a/cgi-bin/Makefile b/cgi-bin/Makefile new file mode 100644 index 0000000000..8eecaa55ea --- /dev/null +++ b/cgi-bin/Makefile @@ -0,0 +1,119 @@ +# +# "$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) $(OBJS) libcgi.a $(TARGETS) + + +# +# Install all targets... +# + +install: + -$(MKDIR) $(SERVERBIN)/cgi-bin + $(CHMOD) ugo+rx $(SERVERBIN) + $(CHMOD) ugo+rx $(SERVERBIN)/cgi-bin + $(INSTALL_BIN) $(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..2579131bf3 --- /dev/null +++ b/cgi-bin/admin.c @@ -0,0 +1,1585 @@ +/* + * "$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: + * + * main() - Main entry for CGI. + * do_am_class() - Add or modify a class. + * do_am_printer() - Add or modify a printer. + * do_config_printer() - Configure the default options for a printer. + * do_delete_class() - Delete a class... + * do_delete_printer() - Delete a printer... + * do_job_op() - Do a job operation. + * do_printer_op() - Do a printer operation. + * get_line() - Get a line that is terminated by a LF, CR, or CR LF. + */ + +/* + * Include necessary headers... + */ + +#include "ipp-var.h" +#include + + +/* + * 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_config_printer(http_t *http, cups_lang_t *language); +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 char *get_line(char *buf, int length, FILE *fp); + + +/* + * '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"); + ippSetServerVersion(); + + cgiCopyTemplateLang(stdout, TEMPLATES, "header.tmpl", getenv("LANG")); + + /* + * See if we have form data... + */ + + if (!cgiInitialize()) + { + /* + * Nope, send the administration menu... + */ + + cgiCopyTemplateLang(stdout, TEMPLATES, "admin.tmpl", getenv("LANG")); + } + 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, "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 if (strcmp(op, "config-printer") == 0) + do_config_printer(http, language); + else + { + /* + * Bad operation code... Display an error... + */ + + cgiCopyTemplateLang(stdout, TEMPLATES, "admin-op.tmpl", getenv("LANG")); + } + + /* + * Close the HTTP server connection... + */ + + httpClose(http); + } + else + { + /* + * Form data but no operation code... Display an error... + */ + + cgiCopyTemplateLang(stdout, TEMPLATES, "admin-op.tmpl", getenv("LANG")); + } + + /* + * Send the standard trailer... + */ + + cgiCopyTemplateLang(stdout, TEMPLATES, "trailer.tmpl", getenv("LANG")); + + /* + * 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? */ +{ + int i, j; /* Looping vars */ + int element; /* Element number */ + int num_printers; /* Number of printers */ + ipp_t *request, /* IPP request */ + *response; /* IPP response */ + ipp_attribute_t *attr; /* member-uris attribute */ + ipp_status_t status; /* Request status */ + char uri[HTTP_MAX_URI]; /* Device or printer URI */ + const char *name, /* Pointer to class name */ + *ptr; /* Pointer to CGI variable */ + + + 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/classes/%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, NULL, NULL); + ippDelete(response); + } + + /* + * Update the location and description of an existing printer... + */ + + cgiCopyTemplateLang(stdout, TEMPLATES, "modify-class.tmpl", getenv("LANG")); + } + else + { + /* + * Get the name, location, and description for a new printer... + */ + + cgiCopyTemplateLang(stdout, TEMPLATES, "add-class.tmpl", getenv("LANG")); + } + + return; + } + + name = cgiGetVariable("PRINTER_NAME"); + if (isdigit(*name)) + ptr = name; + else + for (ptr = name; *ptr; ptr ++) + if (!isalnum(*ptr) && *ptr != '_') + break; + + if (*ptr || ptr == name) + { + cgiSetVariable("ERROR", "The class name may only contain letters, " + "numbers, and the underscore."); + cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG")); + return; + } + + if (cgiGetVariable("MEMBER_URIS") == NULL) + { + /* + * Build a CUPS_GET_PRINTERS request, which requires the + * following attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + */ + + request = ippNew(); + + request->request.op.operation_id = CUPS_GET_PRINTERS; + request->request.op.request_id = 1; + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, + "attributes-charset", NULL, cupsLangEncoding(language)); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, + "attributes-natural-language", NULL, language->language); + + 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) + { + /* + * Create MEMBER_URIS and MEMBER_NAMES arrays... + */ + + for (element = 0, attr = response->attrs; + attr != NULL; + attr = attr->next) + if (attr->name && strcmp(attr->name, "printer-uri-supported") == 0) + { + cgiSetArray("MEMBER_URIS", element, attr->values[0].string.text); + element ++; + } + + for (element = 0, attr = response->attrs; + attr != NULL; + attr = attr->next) + if (attr->name && strcmp(attr->name, "printer-name") == 0) + { + cgiSetArray("MEMBER_NAMES", element, attr->values[0].string.text); + element ++; + } + + num_printers = cgiGetSize("MEMBER_URIS"); + + ippDelete(response); + } + else + num_printers = 0; + + /* + * 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/classes/%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) + { + if ((attr = ippFindAttribute(response, "member-uris", IPP_TAG_URI)) != NULL) + { + /* + * Mark any current members in the class... + */ + + for (j = 0; j < num_printers; j ++) + cgiSetArray("MEMBER_SELECTED", j, ""); + + for (i = 0; i < attr->num_values; i ++) + for (j = 0; j < num_printers; j ++) + if (strcmp(attr->values[i].string.text, cgiGetArray("MEMBER_URIS", j)) == 0) + { + cgiSetArray("MEMBER_SELECTED", j, "SELECTED"); + break; + } + } + + ippDelete(response); + } + + /* + * Let the user choose... + */ + + cgiCopyTemplateLang(stdout, TEMPLATES, "choose-members.tmpl", getenv("LANG")); + } + else + { + /* + * Build a CUPS_ADD_CLASS request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + * printer-location + * printer-info + * printer-is-accepting-jobs + * printer-state + * member-uris + */ + + request = ippNew(); + + request->request.op.operation_id = CUPS_ADD_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); + + snprintf(uri, sizeof(uri), "ipp://localhost/classes/%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")); + + ippAddBoolean(request, IPP_TAG_PRINTER, "printer-is-accepting-jobs", 1); + + ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state", + IPP_PRINTER_IDLE); + + if ((num_printers = cgiGetSize("MEMBER_URIS")) > 0) + { + attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_URI, "member-uris", + num_printers, NULL, NULL); + for (i = 0; i < num_printers; i ++) + attr->values[i].string.text = strdup(cgiGetArray("MEMBER_URIS", i)); + } + + /* + * 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)); + cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG")); + } + else if (modify) + cgiCopyTemplateLang(stdout, TEMPLATES, "class-modified.tmpl", getenv("LANG")); + else + cgiCopyTemplateLang(stdout, TEMPLATES, "class-added.tmpl", getenv("LANG")); + } +} + + +/* + * '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 */ + int element; /* Element number */ + ipp_attribute_t *attr, /* Current attribute */ + *last; /* Last attribute */ + ipp_t *request, /* IPP request */ + *response, /* IPP response */ + *oldinfo; /* Old printer information */ + ipp_status_t status; /* Request status */ + 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 */ + const char *name, /* Pointer to class name */ + *ptr; /* Pointer to CGI variable */ + static int baudrates[] = /* Baud rates */ + { + 1200, + 2400, + 4800, + 9600, + 19200, + 38400, + 57600, + 115200, + 230400, + 460800 + }; + + + 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... + */ + + oldinfo = cupsDoRequest(http, request, "/"); + } + else + oldinfo = NULL; + + if ((name = cgiGetVariable("PRINTER_NAME")) == NULL) + { + if (modify) + { + /* + * Update the location and description of an existing printer... + */ + + if (oldinfo) + ippSetCGIVars(oldinfo, NULL, NULL); + + cgiCopyTemplateLang(stdout, TEMPLATES, "modify-printer.tmpl", getenv("LANG")); + } + else + { + /* + * Get the name, location, and description for a new printer... + */ + + cgiCopyTemplateLang(stdout, TEMPLATES, "add-printer.tmpl", getenv("LANG")); + } + + if (oldinfo) + ippDelete(oldinfo); + + return; + } + + if (isdigit(*name)) + ptr = name; + else + for (ptr = name; *ptr; ptr ++) + if (!isalnum(*ptr) && *ptr != '_') + break; + + if (*ptr || ptr == name) + { + cgiSetVariable("ERROR", "The printer name may only contain letters, " + "numbers, and the underscore."); + cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG")); + return; + } + + 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, NULL, NULL); + ippDelete(response); + } + + /* + * Let the user choose... + */ + + if (oldinfo && + (attr = ippFindAttribute(oldinfo, "device-uri", IPP_TAG_URI)) != NULL) + { + strncpy(uri, attr->values[0].string.text, sizeof(uri) - 1); + uri[sizeof(uri) - 1] = '\0'; + if ((uriptr = strchr(uri, ':')) != NULL && strncmp(uriptr, "://", 3) == 0) + *uriptr = '\0'; + + cgiSetVariable("CURRENT_DEVICE_URI", uri); + } + + cgiCopyTemplateLang(stdout, TEMPLATES, "choose-device.tmpl", getenv("LANG")); + } + else if (strchr(var, '/') == NULL) + { + if (oldinfo && + (attr = ippFindAttribute(oldinfo, "device-uri", IPP_TAG_URI)) != NULL) + { + /* + * Set the current device URI for the form to the old one... + */ + + if (strncmp(attr->values[0].string.text, var, strlen(var)) == 0) + cgiSetVariable("DEVICE_URI", attr->values[0].string.text); + } + + /* + * User needs to set the full URI... + */ + + cgiCopyTemplateLang(stdout, TEMPLATES, "choose-uri.tmpl", getenv("LANG")); + } + 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); + } + + cgiCopyTemplateLang(stdout, TEMPLATES, "choose-serial.tmpl", getenv("LANG")); + } + else if ((var = cgiGetVariable("PPD_NAME")) == NULL) + { + if (modify) + { + /* + * Get the PPD file... + */ + + FILE *fp; /* PPD file */ + char filename[1024]; /* PPD filename */ + ppd_file_t *ppd; /* PPD information */ + char buffer[1024]; /* Buffer */ + int bytes; /* Number of bytes */ + + + snprintf(uri, sizeof(uri), "/printers/%s.ppd", name); + cupsTempFile(filename, sizeof(filename)); + + if (httpGet(http, uri)) + httpGet(http, uri); + + while (httpUpdate(http) == HTTP_CONTINUE); + + if ((fp = fopen(filename, "w")) != NULL) + { + while ((bytes = httpRead(http, buffer, sizeof(buffer))) > 0) + fwrite(buffer, 1, bytes, fp); + + fclose(fp); + + if ((ppd = ppdOpenFile(filename)) != NULL) + { + if (ppd->manufacturer) + cgiSetVariable("CURRENT_MAKE", ppd->manufacturer); + if (ppd->nickname) + cgiSetVariable("CURRENT_MAKE_AND_MODEL", ppd->nickname); + + ppdClose(ppd); + } + } + else + httpFlush(http); + + unlink(filename); + } + + /* + * 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) + { + if ((var = cgiGetVariable("PPD_MAKE")) == NULL) + { + /* + * Let the user choose a make... + */ + + for (element = 0, attr = response->attrs, last = NULL; + attr != NULL; + attr = attr->next) + if (attr->name && strcmp(attr->name, "ppd-make") == 0) + if (last == NULL || + strcasecmp(last->values[0].string.text, + attr->values[0].string.text) != 0) + { + cgiSetArray("PPD_MAKE", element, attr->values[0].string.text); + element ++; + last = attr; + } + + cgiCopyTemplateLang(stdout, TEMPLATES, "choose-make.tmpl", + getenv("LANG")); + } + else + { + /* + * Let the user choose a model... + */ + + ippSetCGIVars(response, "ppd-make", var); + cgiCopyTemplateLang(stdout, TEMPLATES, "choose-model.tmpl", + getenv("LANG")); + } + + ippDelete(response); + } + else + { + char message[1024]; + + + snprintf(message, sizeof(message), "Unable to get list of printer drivers: %s", + ippErrorString(cupsLastError())); + cgiSetVariable("ERROR", message); + cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG")); + } + } + 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")); + + strncpy(uri, cgiGetVariable("DEVICE_URI"), sizeof(uri) - 1); + uri[sizeof(uri) - 1] = '\0'; + if (strncmp(uri, "serial:", 7) == 0) + { + /* + * Update serial port URI to include baud rate, etc. + */ + + if ((uriptr = strchr(uri, '?')) == NULL) + uriptr = uri + strlen(uri); + + snprintf(uriptr, sizeof(uri) - (uriptr - uri), + "?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)); + cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG")); + } + else if (modify) + cgiCopyTemplateLang(stdout, TEMPLATES, "printer-modified.tmpl", getenv("LANG")); + else + cgiCopyTemplateLang(stdout, TEMPLATES, "printer-added.tmpl", getenv("LANG")); + } + + if (oldinfo) + ippDelete(oldinfo); +} + + +/* + * 'do_config_printer()' - Configure the default options for a printer. + */ + +static void +do_config_printer(http_t *http, /* I - HTTP connection */ + cups_lang_t *language)/* I - Client's language */ +{ + int i, j, k; /* Looping vars */ + int have_options; /* Have options? */ + ipp_t *request, /* IPP request */ + *response; /* IPP response */ + ipp_attribute_t *attr; /* IPP attribute */ + char uri[HTTP_MAX_URI]; /* Job URI */ + const char *var; /* Variable value */ + const char *printer; /* Printer printer name */ + ipp_status_t status; /* Operation status... */ + const char *filename; /* PPD filename */ + char tempfile[1024]; /* Temporary filename */ + FILE *in, /* Input file */ + *out; /* Output file */ + char line[1024]; /* Line from PPD file */ + char keyword[1024], /* Keyword from Default line */ + *keyptr; /* Pointer into keyword... */ + ppd_file_t *ppd; /* PPD file */ + ppd_group_t *group; /* Option group */ + ppd_option_t *option; /* Option */ + + + /* + * Get the printer name... + */ + + if ((printer = cgiGetVariable("PRINTER_NAME")) != NULL) + snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", printer); + else + { + cgiSetVariable("ERROR", ippErrorString(IPP_NOT_FOUND)); + cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG")); + return; + } + + /* + * Get the PPD file... + */ + + if ((filename = cupsGetPPD(printer)) == NULL) + { + cgiSetVariable("ERROR", ippErrorString(IPP_NOT_FOUND)); + cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG")); + return; + } + + ppd = ppdOpenFile(filename); + + if (cgiGetVariable("job_sheets_start") != NULL || + cgiGetVariable("job_sheets_end") != NULL) + have_options = 1; + else + have_options = 0; + + for (i = ppd->num_groups, group = ppd->groups; + i > 0 && !have_options; + i --, group ++) + for (j = group->num_options, option = group->options; + j > 0; + j --, option ++) + if ((var = cgiGetVariable(option->keyword)) != NULL) + { + have_options = 1; + break; + } + + if (!have_options) + { + /* + * Show the options to the user... + */ + + cgiCopyTemplateLang(stdout, TEMPLATES, "config-printer.tmpl", + getenv("LANG")); + + for (i = ppd->num_groups, group = ppd->groups; + i > 0; + i --, group ++) + { + cgiSetVariable("GROUP", group->text); + cgiCopyTemplateLang(stdout, TEMPLATES, "option-header.tmpl", + getenv("LANG")); + + for (j = group->num_options, option = group->options; + j > 0; + j --, option ++) + { + if (strcmp(option->keyword, "PageRegion") == 0) + continue; + + cgiSetVariable("KEYWORD", option->keyword); + cgiSetVariable("KEYTEXT", option->text); + cgiSetVariable("DEFCHOICE", option->defchoice); + + cgiSetSize("CHOICES", option->num_choices); + cgiSetSize("TEXT", option->num_choices); + for (k = 0; k < option->num_choices; k ++) + { + cgiSetArray("CHOICES", k, option->choices[k].choice); + cgiSetArray("TEXT", k, option->choices[k].text); + } + + switch (option->ui) + { + case PPD_UI_BOOLEAN : + cgiCopyTemplateLang(stdout, TEMPLATES, "option-boolean.tmpl", + getenv("LANG")); + break; + case PPD_UI_PICKONE : + cgiCopyTemplateLang(stdout, TEMPLATES, "option-pickone.tmpl", + getenv("LANG")); + break; + case PPD_UI_PICKMANY : + cgiCopyTemplateLang(stdout, TEMPLATES, "option-pickmany.tmpl", + getenv("LANG")); + break; + } + } + + cgiCopyTemplateLang(stdout, TEMPLATES, "option-trailer.tmpl", + getenv("LANG")); + } + + /* + * 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) + { + if ((attr = ippFindAttribute(response, "job-sheets-supported", IPP_TAG_ZERO)) != NULL) + { + /* + * Add the job sheets options... + */ + + cgiSetVariable("GROUP", "Banners"); + cgiCopyTemplateLang(stdout, TEMPLATES, "option-header.tmpl", + getenv("LANG")); + + cgiSetSize("CHOICES", attr->num_values); + cgiSetSize("TEXT", attr->num_values); + for (k = 0; k < attr->num_values; k ++) + { + cgiSetArray("CHOICES", k, attr->values[k].string.text); + cgiSetArray("TEXT", k, attr->values[k].string.text); + } + + attr = ippFindAttribute(response, "job-sheets-default", IPP_TAG_ZERO); + + cgiSetVariable("KEYWORD", "job_sheets_start"); + cgiSetVariable("KEYTEXT", "Starting Banner"); + cgiSetVariable("DEFCHOICE", attr == NULL ? + "" : attr->values[0].string.text); + + cgiCopyTemplateLang(stdout, TEMPLATES, "option-pickone.tmpl", + getenv("LANG")); + + cgiSetVariable("KEYWORD", "job_sheets_end"); + cgiSetVariable("KEYTEXT", "Ending Banner"); + cgiSetVariable("DEFCHOICE", attr == NULL && attr->num_values > 1 ? + "" : attr->values[1].string.text); + + cgiCopyTemplateLang(stdout, TEMPLATES, "option-pickone.tmpl", + getenv("LANG")); + + cgiCopyTemplateLang(stdout, TEMPLATES, "option-trailer.tmpl", + getenv("LANG")); + } + + ippDelete(response); + } + + cgiCopyTemplateLang(stdout, TEMPLATES, "config-printer2.tmpl", + getenv("LANG")); + } + else + { + /* + * Set default options... + */ + + cupsTempFile(tempfile, sizeof(tempfile)); + + in = fopen(filename, "rb"); + out = fopen(tempfile, "wb"); + + while (get_line(line, sizeof(line), in) != NULL) + { + if (strncmp(line, "*Default", 8) != 0) + fprintf(out, "%s\n", line); + else + { + /* + * Get default option name... + */ + + strncpy(keyword, line + 8, sizeof(keyword) - 1); + keyword[sizeof(keyword) - 1] = '\0'; + + for (keyptr = keyword; *keyptr; keyptr ++) + if (*keyptr == ':' || isspace(*keyptr)) + break; + + *keyptr = '\0'; + + if (strcmp(keyword, "PageRegion") == 0) + var = cgiGetVariable("PageSize"); + else + var = cgiGetVariable(keyword); + + if (var != NULL) + fprintf(out, "*Default%s: %s\n", keyword, var); + else + fprintf(out, "%s\n", line); + } + } + + fclose(in); + fclose(out); + + /* + * Build a CUPS_ADD_PRINTER request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + * job-sheets-default + * [ppd file] + */ + + 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); + + attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_NAME, + "job-sheets-default", 2, NULL, NULL); + attr->values[0].string.text = strdup(cgiGetVariable("job_sheets_start")); + attr->values[1].string.text = strdup(cgiGetVariable("job_sheets_end")); + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoFileRequest(http, request, "/admin/", tempfile)) != NULL) + { + status = response->request.status.status_code; + ippDelete(response); + } + else + status = IPP_NOT_AUTHORIZED; + + if (status > IPP_OK_CONFLICT) + { + cgiSetVariable("ERROR", ippErrorString(status)); + cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG")); + } + else + cgiCopyTemplateLang(stdout, TEMPLATES, "printer-configured.tmpl", getenv("LANG")); + + unlink(tempfile); + } + + unlink(filename); +} + + +/* + * '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) + { + cgiCopyTemplateLang(stdout, TEMPLATES, "class-confirm.tmpl", getenv("LANG")); + return; + } + + if ((pclass = cgiGetVariable("PRINTER_NAME")) != NULL) + snprintf(uri, sizeof(uri), "ipp://localhost/classes/%s", pclass); + else + { + cgiSetVariable("ERROR", ippErrorString(IPP_NOT_FOUND)); + cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG")); + 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)); + cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG")); + } + else + cgiCopyTemplateLang(stdout, TEMPLATES, "class-deleted.tmpl", getenv("LANG")); +} + + +/* + * '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) + { + cgiCopyTemplateLang(stdout, TEMPLATES, "printer-confirm.tmpl", getenv("LANG")); + return; + } + + if ((printer = cgiGetVariable("PRINTER_NAME")) != NULL) + snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", printer); + else + { + cgiSetVariable("ERROR", ippErrorString(IPP_NOT_FOUND)); + cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG")); + 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)); + cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG")); + } + else + cgiCopyTemplateLang(stdout, TEMPLATES, "printer-deleted.tmpl", getenv("LANG")); +} + + +/* + * '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)); + cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG")); + 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)); + cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG")); + } + else if (op == IPP_CANCEL_JOB) + cgiCopyTemplateLang(stdout, TEMPLATES, "job-cancel.tmpl", getenv("LANG")); + else if (op == IPP_HOLD_JOB) + cgiCopyTemplateLang(stdout, TEMPLATES, "job-hold.tmpl", getenv("LANG")); + else if (op == IPP_RELEASE_JOB) + cgiCopyTemplateLang(stdout, TEMPLATES, "job-release.tmpl", getenv("LANG")); + else if (op == IPP_RESTART_JOB) + cgiCopyTemplateLang(stdout, TEMPLATES, "job-restart.tmpl", getenv("LANG")); +} + + +/* + * '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)); + cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG")); + 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)); + cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG")); + } + else if (op == IPP_PAUSE_PRINTER) + cgiCopyTemplateLang(stdout, TEMPLATES, "printer-stop.tmpl", getenv("LANG")); + else if (op == IPP_RESUME_PRINTER) + cgiCopyTemplateLang(stdout, TEMPLATES, "printer-start.tmpl", getenv("LANG")); + else if (op == CUPS_ACCEPT_JOBS) + cgiCopyTemplateLang(stdout, TEMPLATES, "printer-accept.tmpl", getenv("LANG")); + else if (op == CUPS_REJECT_JOBS) + cgiCopyTemplateLang(stdout, TEMPLATES, "printer-reject.tmpl", getenv("LANG")); +} + + +/* + * 'get_line()' - Get a line that is terminated by a LF, CR, or CR LF. + */ + +static char * /* O - Pointer to buf or NULL on EOF */ +get_line(char *buf, /* I - Line buffer */ + int length, /* I - Length of buffer */ + FILE *fp) /* I - File to read from */ +{ + char *bufptr; /* Pointer into buffer */ + int ch; /* Character from file */ + + + length --; + bufptr = buf; + + while ((ch = getc(fp)) != EOF) + { + if (ch == '\n') + break; + else if (ch == '\r') + { + /* + * Look for LF... + */ + + ch = getc(fp); + if (ch != '\n' && ch != EOF) + ungetc(ch, fp); + + break; + } + + *bufptr++ = ch; + length --; + if (length == 0) + break; + } + + *bufptr = '\0'; + + if (ch == EOF) + return (NULL); + else + return (buf); +} + + +/* + * End of "$Id$". + */ diff --git a/cgi-bin/cgi.h b/cgi-bin/cgi.h new file mode 100644 index 0000000000..838bd87678 --- /dev/null +++ b/cgi-bin/cgi.h @@ -0,0 +1,87 @@ +/* + * "$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 *tmpl); +extern void cgiCopyTemplateLang(FILE *out, const char *directory, + const char *tmpl, const char *lang); + +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); + +extern char *cgiGetCookie(const char *name, char *buf, int buflen); +extern void cgiSetCookie(const char *name, const char *value, + const char *path, const char *domain, + time_t expires, int secure); + +# 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..debf334954 --- /dev/null +++ b/cgi-bin/classes.c @@ -0,0 +1,360 @@ +/* + * "$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 */ + ipp_attribute_t *attr; /* IPP attribute */ + ipp_status_t status; /* Operation status... */ + char uri[HTTP_MAX_URI]; + /* Printer URI */ + const char *which_jobs; /* Which jobs to show */ + const char *op; /* Operation to perform, if any */ + + + /* + * Get any form variables... + */ + + cgiInitialize(); + op = cgiGetVariable("OP"); + + /* + * 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... + */ + + ippSetServerVersion(); + + pclass = argv[0]; + if (strcmp(pclass, "/") == 0 || strcmp(pclass, "classes.cgi") == 0) + { + pclass = NULL; + cgiSetVariable("TITLE", cupsLangString(language, CUPS_MSG_CLASS)); + } + else + cgiSetVariable("TITLE", pclass); + + cgiCopyTemplateLang(stdout, TEMPLATES, "header.tmpl", getenv("LANG")); + + if (op == NULL || strcasecmp(op, "print-test-page") != 0) + { + /* + * Get the default destination... + */ + + request = ippNew(); + request->request.op.operation_id = CUPS_GET_DEFAULT; + 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 ((response = cupsDoRequest(http, request, "/")) != NULL) + { + if ((attr = ippFindAttribute(response, "printer-name", IPP_TAG_NAME)) != NULL) + cgiSetVariable("DEFAULT_NAME", attr->values[0].string.text); + + if ((attr = ippFindAttribute(response, "printer-uri-supported", IPP_TAG_URI)) != NULL) + { + char method[HTTP_MAX_URI], + username[HTTP_MAX_URI], + hostname[HTTP_MAX_URI], + resource[HTTP_MAX_URI], + uri[HTTP_MAX_URI]; + int port; /* URI data */ + const char *server; /* Name of server */ + + + /* + * Map localhost access to localhost... + */ + + server = getenv("SERVER_NAME"); + + httpSeparate(attr->values[0].string.text, method, username, + hostname, &port, resource); + + if (strcasecmp(hostname, server) == 0 && + (strcmp(getenv("REMOTE_HOST"), "127.0.0.1") == 0 || + strcmp(getenv("REMOTE_HOST"), "localhost") == 0 || + strcmp(getenv("REMOTE_HOST"), server) == 0)) + strcpy(hostname, "localhost"); + + /* + * Rewrite URI with HTTP address... + */ + + snprintf(uri, sizeof(uri), "http://%s:%d%s", hostname, port, + resource); + + cgiSetVariable("DEFAULT_URI", uri); + } + + ippDelete(response); + } + + /* + * Get the class 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, NULL, NULL); + ippDelete(response); + } + + /* + * Write the report... + */ + + cgiCopyTemplateLang(stdout, TEMPLATES, "classes.tmpl", getenv("LANG")); + + /* + * 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, NULL, NULL); + ippDelete(response); + + cgiCopyTemplateLang(stdout, TEMPLATES, "jobs.tmpl", getenv("LANG")); + } + } + } + else + { + /* + * Print a test page... + */ + + snprintf(uri, sizeof(uri), "ipp://localhost/classes/%s", pclass); + + /* + * 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, NULL, NULL); + + ippDelete(response); + } + else + status = IPP_GONE; + + cgiSetVariable("PRINTER_NAME", pclass); + + if (status > IPP_OK_CONFLICT) + { + cgiSetVariable("ERROR", ippErrorString(status)); + cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG")); + } + else + cgiCopyTemplateLang(stdout, TEMPLATES, "test-page.tmpl", getenv("LANG")); + } + + cgiCopyTemplateLang(stdout, TEMPLATES, "trailer.tmpl", getenv("LANG")); + + /* + * 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..510eee4785 --- /dev/null +++ b/cgi-bin/ipp-var.c @@ -0,0 +1,263 @@ +/* + * "$Id$" + * + * IPP variable 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: + * + * ippGetTemplateDir() - Get the templates directory... + * ippSetServerVersion() - Set the server name and CUPS version... + * ippSetCGIVars() - Set CGI variables from an IPP response. + */ + +/* + * Include necessary headers... + */ + +#include "ipp-var.h" + + +/* + * 'ippGetTemplateDir()' - Get the templates directory... + */ + +char * /* O - Template directory */ +ippGetTemplateDir(void) +{ + const char *datadir; /* CUPS_DATADIR env var */ + static char templates[1024] = ""; /* Template directory */ + + + if (!templates[0]) + { + /* + * Build the template directory pathname... + */ + + if ((datadir = getenv("CUPS_DATADIR")) == NULL) + datadir = CUPS_DATADIR; + + snprintf(templates, sizeof(templates), "%s/templates", datadir); + } + + return (templates); +} + + +/* + * 'ippSetServerVersion()' - Set the server name and CUPS version... + */ + +void +ippSetServerVersion(void) +{ + cgiSetVariable("SERVER_NAME", getenv("SERVER_NAME")); + cgiSetVariable("REMOTE_USER", getenv("REMOTE_USER")); + cgiSetVariable("CUPS_VERSION", CUPS_SVERSION); +} + + +/* + * 'ippSetCGIVars()' - Set CGI variables from an IPP response. + */ + +void +ippSetCGIVars(ipp_t *response, /* I - Response data to be copied... */ + const char *filter_name, /* I - Filter name */ + const char *filter_value) /* I - Filter value */ +{ + int element; /* Element in CGI array */ + ipp_attribute_t *attr, /* Attribute in response... */ + *filter; /* Filtering attribute */ + 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; /* URI data */ + const char *server; /* Name of server */ + + + ippSetServerVersion(); + + server = getenv("SERVER_NAME"); + + 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... + */ + + if (filter_name) + { + for (filter = attr; + filter != NULL && filter->group_tag != IPP_TAG_ZERO; + filter = filter->next) + if (filter->name && strcmp(filter->name, filter_name) == 0 && + (filter->value_tag == IPP_TAG_STRING || + (filter->value_tag >= IPP_TAG_TEXTLANG && + filter->value_tag <= IPP_TAG_MIMETYPE)) && + filter->values[0].string.text != NULL && + strcasecmp(filter->values[0].string.text, filter_value) == 0) + break; + + if (!filter) + return; + + if (filter->group_tag == IPP_TAG_ZERO) + { + attr = filter; + element --; + continue; + } + } + + for (; attr != NULL && attr->group_tag != IPP_TAG_ZERO; attr = attr->next) + { + /* + * Copy the attribute name, substituting "_" for "-"... + */ + + if (attr->name == NULL) + continue; + + 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 (strchr(attr->values[i].string.text, ':') != NULL) + { + httpSeparate(attr->values[i].string.text, method, username, + hostname, &port, resource); + + if (strcmp(method, "ipp") == 0 || + strcmp(method, "http") == 0) + { + /* + * Map localhost access to localhost... + */ + + if (strcasecmp(hostname, server) == 0 && + (strcmp(getenv("REMOTE_HOST"), "127.0.0.1") == 0 || + strcmp(getenv("REMOTE_HOST"), "localhost") == 0 || + strcmp(getenv("REMOTE_HOST"), server) == 0)) + strcpy(hostname, "localhost"); + + /* + * Rewrite URI with HTTP address... + */ + + 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; + + default : + break; /* anti-compiler-warning-code */ + } + } + + /* + * 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..4b60b49afa --- /dev/null +++ b/cgi-bin/ipp-var.h @@ -0,0 +1,55 @@ +/* + * "$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 ippGetTemplateDir() + + +/* + * Prototype... + */ + +extern char *ippGetTemplateDir(void); +extern void ippSetServerVersion(void); +extern void ippSetCGIVars(ipp_t *, const char *, const char *); + + +/* + * End of "$Id$". + */ diff --git a/cgi-bin/jobs.c b/cgi-bin/jobs.c new file mode 100644 index 0000000000..3e6d4ab5d6 --- /dev/null +++ b/cgi-bin/jobs.c @@ -0,0 +1,139 @@ +/* + * "$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"); + + ippSetServerVersion(); + + cgiCopyTemplateLang(stdout, TEMPLATES, "header.tmpl", getenv("LANG")); + + /* + * 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, NULL, NULL); + ippDelete(response); + + cgiCopyTemplateLang(stdout, TEMPLATES, "jobs.tmpl", getenv("LANG")); + } + + cgiCopyTemplateLang(stdout, TEMPLATES, "trailer.tmpl", getenv("LANG")); + + /* + * 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..dd1fab52a9 --- /dev/null +++ b/cgi-bin/printers.c @@ -0,0 +1,360 @@ +/* + * "$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 */ + ipp_attribute_t *attr; /* IPP attribute */ + ipp_status_t status; /* Operation status... */ + char uri[HTTP_MAX_URI]; + /* Printer URI */ + const char *which_jobs; /* Which jobs to show */ + const char *op; /* Operation to perform, if any */ + + + /* + * Get any form variables... + */ + + cgiInitialize(); + op = cgiGetVariable("OP"); + + /* + * 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... + */ + + ippSetServerVersion(); + + printer = argv[0]; + if (strcmp(printer, "/") == 0 || strcmp(printer, "printers.cgi") == 0) + { + printer = NULL; + cgiSetVariable("TITLE", cupsLangString(language, CUPS_MSG_PRINTER)); + } + else + cgiSetVariable("TITLE", printer); + + cgiCopyTemplateLang(stdout, TEMPLATES, "header.tmpl", getenv("LANG")); + + if (op == NULL || strcasecmp(op, "print-test-page") != 0) + { + /* + * Get the default destination... + */ + + request = ippNew(); + request->request.op.operation_id = CUPS_GET_DEFAULT; + 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 ((response = cupsDoRequest(http, request, "/")) != NULL) + { + if ((attr = ippFindAttribute(response, "printer-name", IPP_TAG_NAME)) != NULL) + cgiSetVariable("DEFAULT_NAME", attr->values[0].string.text); + + if ((attr = ippFindAttribute(response, "printer-uri-supported", IPP_TAG_URI)) != NULL) + { + char method[HTTP_MAX_URI], + username[HTTP_MAX_URI], + hostname[HTTP_MAX_URI], + resource[HTTP_MAX_URI], + uri[HTTP_MAX_URI]; + int port; /* URI data */ + const char *server; /* Name of server */ + + + /* + * Map localhost access to localhost... + */ + + server = getenv("SERVER_NAME"); + + httpSeparate(attr->values[0].string.text, method, username, + hostname, &port, resource); + + if (strcasecmp(hostname, server) == 0 && + (strcmp(getenv("REMOTE_HOST"), "127.0.0.1") == 0 || + strcmp(getenv("REMOTE_HOST"), "localhost") == 0 || + strcmp(getenv("REMOTE_HOST"), server) == 0)) + strcpy(hostname, "localhost"); + + /* + * Rewrite URI with HTTP address... + */ + + snprintf(uri, sizeof(uri), "http://%s:%d%s", hostname, port, + resource); + + cgiSetVariable("DEFAULT_URI", uri); + } + + ippDelete(response); + } + + /* + * 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, NULL, NULL); + ippDelete(response); + } + + /* + * Write the report... + */ + + cgiCopyTemplateLang(stdout, TEMPLATES, "printers.tmpl", getenv("LANG")); + + /* + * 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, NULL, NULL); + ippDelete(response); + + cgiCopyTemplateLang(stdout, TEMPLATES, "jobs.tmpl", getenv("LANG")); + } + } + } + else + { + /* + * Print a test page... + */ + + snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", printer); + + /* + * 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, NULL, NULL); + + ippDelete(response); + } + else + status = IPP_GONE; + + cgiSetVariable("PRINTER_NAME", printer); + + if (status > IPP_OK_CONFLICT) + { + cgiSetVariable("ERROR", ippErrorString(status)); + cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG")); + } + else + cgiCopyTemplateLang(stdout, TEMPLATES, "test-page.tmpl", getenv("LANG")); + } + + cgiCopyTemplateLang(stdout, TEMPLATES, "trailer.tmpl", getenv("LANG")); + + /* + * 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..1a8f436555 --- /dev/null +++ b/cgi-bin/template.c @@ -0,0 +1,499 @@ +/* + * "$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. + * cgiCopyTemplateLang() - Copy a template file using a language... + * 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 *tmpl) /* I - Template file to read */ +{ + FILE *in; /* Input file */ + + + /* + * Open the template file... + */ + + if ((in = fopen(tmpl, "r")) == NULL) + return; + + /* + * Parse the file to the end... + */ + + cgi_copy(out, in, 0, 0); + + /* + * Close the template file and return... + */ + + fclose(in); +} + + +/* + * 'cgiCopyTemplateLang()' - Copy a template file using a language... + */ + +void +cgiCopyTemplateLang(FILE *out, /* I - Output file */ + const char *directory, /* I - Directory */ + const char *tmpl, /* I - Base filename */ + const char *lang) /* I - Language */ +{ + int i; /* Looping var */ + char filename[1024], /* Filename */ + locale[16]; /* Locale name */ + FILE *in; /* Input file */ + + + /* + * Convert the language to a locale name... + */ + + if (lang != NULL) + { + for (i = 0; lang[i] && i < 15; i ++) + if (isalnum(lang[i])) + locale[i] = tolower(lang[i]); + else + locale[i] = '_'; + + locale[i] = '\0'; + } + else + locale[0] = '\0'; + + /* + * See if we have a template file for this language... + */ + + snprintf(filename, sizeof(filename), "%s/%s/%s", directory, locale, tmpl); + if (access(filename, 0)) + { + locale[2] = '\0'; + + snprintf(filename, sizeof(filename), "%s/%s/%s", directory, locale, tmpl); + if (access(filename, 0)) + snprintf(filename, sizeof(filename), "%s/%s", directory, tmpl); + } + + /* + * Open the template file... + */ + + if ((in = fopen(filename, "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 */ + *nameptr, /* Pointer into name */ + innername[255], /* Inner comparison name */ + *innerptr, /* Pointer into inner name */ + *s; /* String pointer */ + const char *value; /* Value of variable */ + const char *innerval; /* Inner value */ + const char *outptr; /* Output string pointer */ + char outval[1024], /* Formatted 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("}]<>=! \t\n", ch)) + break; + else if (s > name && ch == '?') + break; + else if (s < (name + sizeof(name) - 1)) + *s++ = ch; + + *s = '\0'; + + if (s == name && isspace(ch)) + { + if (out) + { + putc('{', out); + putc(ch, out); + } + + continue; + } + + /* + * See if it has a value... + */ + + if (name[0] == '?') + { + /* + * Insert value only if it exists... + */ + + if ((nameptr = strrchr(name, '-')) != NULL && isdigit(nameptr[1])) + { + *nameptr++ = '\0'; + + if ((value = cgiGetArray(name + 1, atoi(nameptr) - 1)) != NULL) + outptr = value; + else + { + outval[0] = '\0'; + outptr = outval; + } + } + if ((value = cgiGetArray(name + 1, element)) != NULL) + outptr = value; + else + { + outval[0] = '\0'; + outptr = outval; + } + } + else if (name[0] == '#') + { + /* + * Insert count... + */ + + if (name[1]) + sprintf(outval, "%d", cgiGetSize(name + 1)); + else + sprintf(outval, "%d", element + 1); + + outptr = outval; + } + 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 ((nameptr = strrchr(name, '-')) != NULL && isdigit(nameptr[1])) + { + *nameptr++ = '\0'; + if ((value = cgiGetArray(name, atoi(nameptr) - 1)) == NULL) + { + snprintf(outval, sizeof(outval), "{%s}", name); + outptr = outval; + } + else + outptr = value; + } + else if ((value = cgiGetArray(name, element)) == NULL) + { + snprintf(outval, sizeof(outval), "{%s}", name); + outptr = outval; + } + else + outptr = value; + } + + /* + * See if the terminating character requires another test... + */ + + if (ch == '}') + { + /* + * End of substitution... + */ + + if (out) + cgi_puts(outptr, 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 (s >= (compare + sizeof(compare) - 1)) + continue; + 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 != '}') + if (innerptr < (innername + sizeof(innername) - 1)) + *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) - 1)) == NULL) + *s = '\0'; + else + { + strncpy(s, innerval, sizeof(compare) - (s - compare) - 1); + compare[sizeof(compare) - 1] = '\0'; + } + } + else if (innername[0] == '?') + { + if ((innerval = cgiGetArray(innername + 1, element)) == NULL) + *s = '\0'; + else + { + strncpy(s, innerval, sizeof(compare) - (s - compare) - 1); + compare[sizeof(compare) - 1] = '\0'; + } + } + else if ((innerval = cgiGetArray(innername, element)) == NULL) + snprintf(s, sizeof(s), "{%s}", innername); + else + { + strncpy(s, innerval, sizeof(compare) - (s - compare) - 1); + compare[sizeof(compare) - 1] = '\0'; + } + + 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(outptr, compare) < 0; + break; + case '>' : + result = strcasecmp(outptr, compare) > 0; + break; + case '=' : + result = strcasecmp(outptr, compare) == 0; + break; + case '!' : + result = strcasecmp(outptr, compare) != 0; + break; + default : + result = 1; + 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); + + /* + * Flush any pending output... + */ + + if (out) + fflush(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..66101305c7 --- /dev/null +++ b/cgi-bin/var.c @@ -0,0 +1,657 @@ +/* + * "$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'; + if (value[0]) + cgiSetArray(name, atoi(s) - 1, value); + } + else if (cgiGetVariable(name) != NULL) + cgiSetArray(name, cgiGetSize(name), 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..643e231439 --- /dev/null +++ b/conf/Makefile @@ -0,0 +1,73 @@ +# +# "$Id$" +# +# Configuration file 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 + +# +# Config files... +# + +KEEP = classes.conf client.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) + $(CHMOD) ugo+rx $(SERVERROOT) + for file in $(KEEP); do \ + if test -r $(SERVERROOT)/$$file ; then \ + $(INSTALL_DATA) $$file $(SERVERROOT)/$$file.N ; \ + else \ + $(INSTALL_DATA) $$file $(SERVERROOT) ; \ + fi ; \ + done + for file in $(REPLACE); do \ + if test -r $(SERVERROOT)/$$file ; then \ + $(MV) $(SERVERROOT)/$$file $(SERVERROOT)/$$file.O ; \ + fi ; \ + $(INSTALL_DATA) $$file $(SERVERROOT) ; \ + done + + +# +# End of "$Id$". +# diff --git a/conf/classes.conf b/conf/classes.conf new file mode 100644 index 0000000000..8819625b27 --- /dev/null +++ b/conf/classes.conf @@ -0,0 +1,89 @@ +# +# "$Id: classes.conf 1152 2000-06-22 18:25:29Z mike $" +# +# Sample class configuration file for the Common UNIX Printing System +# (CUPS) scheduler. +# +# 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 +# + +######################################################################## +# # +# 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 + +# +# Location: the location of the printer. +# + +#Location Room 101 in the activities building + +# +# State: sets the initial state of the class. Can be one of the +# following: +# +# Idle - Class is available to print new jobs. +# Stopped - Class is disabled but accepting new jobs. +# + +#State Idle + +# +# StateMessage: sets the printer-state-message attribute for the class. +# + +#StateMessage Class is idle. + +# +# 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 1152 2000-06-22 18:25:29Z mike $". +# diff --git a/conf/client.conf b/conf/client.conf new file mode 100644 index 0000000000..3582e7d84b --- /dev/null +++ b/conf/client.conf @@ -0,0 +1,65 @@ +# +# "$Id: client.conf 1485 2000-12-20 13:41:17Z mike $" +# +# Sample client configuration file 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 +# + +######################################################################## +# # +# This is the CUPS client configuration file. This file is used to # +# define client-specific parameters, such as the default server or # +# default encryption settings. # +# # +######################################################################## + +# +# ServerName: the hostname of your server. By default CUPS will use the +# hostname of the system or the value of the CUPS_SERVER environment +# variable. +# + +#ServerName myhost.domain.com + +# +# Encryption: whether or not to use encryption; this depends on having +# the OpenSSL library linked into the CUPS library. +# +# Possible values: +# +# Always - Always use encryption (SSL) +# Never - Never use encryption +# Required - Use TLS encryption upgrade +# IfRequested - Use encryption if the server requests it +# +# The default value is "IfRequested". This parameter can also be set +# using the CUPS_ENCRYPTION environment variable. +# + +#Encryption Always +#Encryption Never +#Encryption Required +#Encryption IfRequested + + +# +# End of "$Id: client.conf 1485 2000-12-20 13:41:17Z mike $". +# diff --git a/conf/cupsd.conf b/conf/cupsd.conf new file mode 100644 index 0000000000..6f269e9cdd --- /dev/null +++ b/conf/cupsd.conf @@ -0,0 +1,628 @@ +# +# "$Id: cupsd.conf 1485 2000-12-20 13:41:17Z mike $" +# +# Sample configuration file for the Common UNIX Printing System (CUPS) +# scheduler. +# +# 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 +# + +######################################################################## +# # +# 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... # +# # +######################################################################## + + +######## +######## Server Identity +######## + +# +# ServerName: the hostname of your server, as advertised to the world. +# By default CUPS will use the hostname of the system. +# +# To set the default server used by clients, see the client.conf file. +# + +#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 + + +######## +######## Server Options +######## + +# +# 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 +# "/var/log/cups/access_log" +# +# You can also use the special name "syslog" to send the output to the +# syslog file or daemon. +# + +#AccessLog /var/log/cups/access_log + +# +# DataDir: the root directory for the CUPS data files. +# By default /usr/share/cups. +# + +#DataDir /usr/share/cups + +# +# DefaultCharset: the default character set to use. If not specified, +# defaults to utf-8. Note that this can also be overridden in +# HTML documents... +# + +#DefaultCharset utf-8 + +# +# DefaultLanguage: the default language if not specified by the browser. +# If not specified, the current locale is used. +# + +#DefaultLanguage en + +# +# DocumentRoot: the root directory for HTTP documents that are served. +# By default the compiled in directory. +# + +#DocumentRoot /usr/share/cups/doc + +# +# 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 +# "/var/log/cups/error_log" +# +# You can also use the special name "syslog" to send the output to the +# syslog file or daemon. +# + +#ErrorLog /var/log/cups/error_log + +# +# FontPath: the path to locate all font files (currently only for pstoraster) +# By default /usr/share/cups/fonts. +# + +#FontPath /usr/share/cups/fonts + +# +# LogLevel: controls the number of messages logged to the ErrorLog +# file and can be one of the following: +# +# debug2 Log everything. +# debug Log almost 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 + +# +# 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 +# "/var/log/cups/page_log" +# +# You can also use the special name "syslog" to send the output to the +# syslog file or daemon. +# + +#PageLog /var/log/cups/page_log + +# +# PreserveJobHistory: whether or not to preserve the job history after a +# job is completed, cancelled, or stopped. Default is Yes. +# + +#PreserveJobHistory Yes + +# +# PreserveJobFiles: whether or not to preserve the job files after a +# job is completed, cancelled, or stopped. Default is No. +# + +#PreserveJobFiles No + +# +# AutoPurgeJobs: automatically purge jobs when not needed for quotas. +# Default is No. +# + +#AutoPurgeJobs No + +# +# MaxJobs: maximum number of jobs to keep in memory (active and completed.) +# Default is 0 (no limit.) +# + +#MaxJobs 0 + +# +# Printcap: the name of the printcap file. Default is /etc/printcap. +# Leave blank to disable printcap file generation. +# + +#Printcap /etc/printcap + +# +# RequestRoot: the directory where request files are stored. +# By default /var/spool/cups. +# + +#RequestRoot /var/spool/cups + +# +# RemoteRoot: the name of the user assigned to unauthenticated accesses +# from remote systems. By default "remroot". +# + +#RemoteRoot remroot + +# +# ServerBin: the root directory for the scheduler executables. +# By default /usr/lib/cups or /usr/lib32/cups (IRIX 6.5). +# + +#ServerBin /usr/lib/cups + +# +# ServerRoot: the root directory for the scheduler. +# By default /etc/cups. +# + +#ServerRoot /etc/cups + + +######## +######## Encryption Support +######## + +# +# ServerCertificate: the file to read containing the server's certificate. +# Defaults to "/etc/cups/ssl/server.crt". +# + +#ServerCertificate /etc/cups/ssl/server.crt + +# +# ServerKey: the file to read containing the server's key. +# Defaults to "/etc/cups/ssl/server.key". +# + +#ServerKey /etc/cups/ssl/server.key + + +######## +######## Filter Options +######## + +# +# 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 + +# +# 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/spool/cups/tmp" or +# the value of the TMPDIR environment variable. +# + +#TempDir /var/spool/cups/tmp + +# +# FilterLimit: sets the maximum cost of all job filters that can be run +# at the same time. A limit of 0 means no limit. A typical job may need +# a filter limit of at least 200; limits less than the minimum required +# by a job force a single job to be printed at any time. +# +# The default limit is 0 (unlimited). +# + +#FilterLimit 0 + +######## +######## Network Options +######## + +# +# 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 +# +# NOTE: Unfortunately, most web browsers don't support TLS or HTTP Upgrades +# for encryption. If you want to support web-based encryption you'll +# probably need to listen on port 443 (the "https" port...) +# + +#Port 80 +#Port 443 +Port 631 + +# +# 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 + +# +# 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 + +# +# MaxClients: controls the maximum number of simultaneous clients that +# will be handled. Defaults to 100. +# + +#MaxClients 100 + +# +# MaxRequestSize: controls the maximum size of HTTP requests and print files. +# Set to 0 to disable this feature (defaults to 0.) +# + +#MaxRequestSize 0 + +# +# Timeout: the timeout before requests time out. Default is 300 seconds. +# + +#Timeout 300 + + +######## +######## Browsing Options +######## + +# +# Browsing: whether or not to broadcast and/or listen for CUPS printer +# information on the network. Enabled by default. +# + +#Browsing On + +# +# BrowseAddress: specifies a broadcast address to be used. By +# default browsing information is not sent! +# +# Note: HP-UX does not properly handle broadcast unless you have a +# Class A, B, C, or D netmask (i.e. no CIDR support). +# +# Note: Using the "global" broadcast address (255.255.255.255) will +# activate a Linux demand-dial link with the default configuration. +# If you have a LAN as well as the dial-up link, use the LAN's +# broadcast address. +# + +#BrowseAddress x.y.z.255 +#BrowseAddress x.y.255.255 +#BrowseAddress x.255.255.255 +#BrowseAddress 255.255.255.255 + +# +# BrowseShortNames: whether or not to use "short" names for remote printers +# when possible (e.g. "printer" instead of "printer@host".) Enabled by +# default. +# + +#BrowseShortNames Yes + +# +# BrowseAllow: specifies an address mask to allow for incoming browser +# packets. The default is to allow packets from all addresses. +# +# BrowseDeny: specifies an address mask to deny for incoming browser +# packets. The default is to deny packets from no addresses. +# +# Both "BrowseAllow" and "BrowseDeny" 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 hostname/domainname restrictions only work if you have turned hostname +# lookups on! +# + +#BrowseAllow address +#BrowseDeny address + +# +# 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. +# +# Set this to 0 to disable outgoing broadcasts so your local printers are +# not advertised but you can still see printers on other hosts. +# + +#BrowseInterval 30 + +# +# BrowseOrder: specifies the order of BrowseAllow/BrowseDeny comparisons. +# + +#BrowseOrder allow,deny +#BrowseOrder deny,allow + +# +# BrowsePoll: poll the named server(s) for printers +# + +#BrowsePoll address:port + +# +# 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 + +# +# BrowseRelay: relay browser packets from one address/network to another. +# + +#BrowseRelay source-address destination-address + +# +# 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 + +# +# 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 + + +######## +######## Security Options +######## + +# +# 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 + +# +# Access permissions for each directory served by the scheduler. +# Locations are relative to DocumentRoot... +# +# AuthType: the authorization to use: +# +# None - Perform no authentication +# Basic - Perform authentication using the HTTP Basic method. +# Digest - Perform authentication using the HTTP Digest method. +# +# (Note: local certificate authentication can be substituted by +# the client for Basic or Digest when connecting to the +# localhost interface) +# +# 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. +# +# Encryption: whether or not to use encryption; this depends on having +# the OpenSSL library linked into the CUPS library and scheduler. +# +# Possible values: +# +# Always - Always use encryption (SSL) +# Never - Never use encryption +# Required - Use TLS encryption upgrade +# IfRequested - Use encryption if the server requests it +# +# The default value is "IfRequested". +# + + +Order Deny,Allow +Deny From All +Allow From 127.0.0.1 + + +# +# +# You may wish to limit access to printers and classes, either with Allow +# and Deny lines, or by requiring a username and password. +# +# + +# +# +# You may wish to limit access to printers and classes, either with Allow +# and Deny lines, or by requiring a username and password. +# +# + +# +# +# You may wish to limit access to printers and classes, either with Allow +# and Deny lines, or by requiring a username and password. +# +# + +# +# +# You may wish to limit access to printers and classes, either with Allow +# and Deny lines, or by requiring a username and password. +# + +## Anonymous access (default) +#AuthType None + +## Require a username and password (Basic authentication) +#AuthType Basic +#AuthClass User + +## Require a username and password (Digest/MD5 authentication) +#AuthType Digest +#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 functions. +# 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 + +#Encryption Required + + +# +# End of "$Id: cupsd.conf 1485 2000-12-20 13:41:17Z mike $". +# diff --git a/conf/mime.convs b/conf/mime.convs new file mode 100644 index 0000000000..b09649ec24 --- /dev/null +++ b/conf/mime.convs @@ -0,0 +1,78 @@ +# +# "$Id: mime.convs 1340 2000-09-06 13:53:00Z mike $" +# +# MIME converts 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 +# + +######################################################################## +# +# 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 33 mswordtops +application/pdf application/postscript 33 pdftops +application/postscript application/vnd.cups-postscript 66 pstops +application/vnd.hp-HPGL application/postscript 66 hpgltops +image/* application/vnd.cups-postscript 66 imagetops +#text/html application/postscript 33 htmltops +application/x-cshell application/postscript 33 texttops +application/x-perl application/postscript 33 texttops +application/x-shell application/postscript 33 texttops +text/html application/postscript 33 texttops +text/plain application/postscript 33 texttops +application/vnd.cups-form application/vnd.cups-postscript 33 formtops + +######################################################################## +# +# Raster filters... +# + +image/* application/vnd.cups-raster 100 imagetoraster +application/vnd.cups-postscript application/vnd.cups-raster 100 pstoraster + +######################################################################## +# +# Raw filter... +# +# Uncomment the following filter and the application/octet-stream type +# in mime.types to allow printing of arbitrary files without the -oraw +# option. +# + +#*/* application/vnd.cups-raw 0 - + +# +# End of "$Id: mime.convs 1340 2000-09-06 13:53:00Z mike $". +# diff --git a/conf/mime.types b/conf/mime.types new file mode 100644 index 0000000000..beadd7fe6d --- /dev/null +++ b/conf/mime.types @@ -0,0 +1,149 @@ +# +# "$Id: mime.types 1430 2000-11-06 16:39:17Z mike $" +# +# MIME types 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 +# + +######################################################################## +# +# 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, 128-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 +# contains(offset,range,"string") True if the range contains the 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 128-255. +# +# 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(0,) &&\ + (char(3,0xe0) char(3,0xe1) char(3,0xe2) char(3,0xe3)\ + char(3,0xe4) char(3,0xe5) char(3,0xe6) char(3,0xe7)\ + char(3,0xe8) char(3,0xe9) char(3,0xea) char(3,0xeb)\ + char(3,0xec) char(3,0xed) char(3,0xee) char(3,0xef)) +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 + +#image/fpx fpx +image/x-alias pix short(8,8) short(8,24) +image/x-bitmap bmp string(0,BM) && !printable(2,14) + +######################################################################## +# +# Text files... +# + +text/html html htm printable(0,1024) +\ + (string(0,"") string(0,"") +application/vnd.cups-postscript string(0,<1B>%-12345X) + \ + contains(9,512,"LANGUAGE=POSTSCRIPT") +application/vnd.cups-raster string(0,"RaSt") string(0,"tSaR") +application/vnd.cups-raw string(0,<1B>E) \ + string(0,<1B>@) \ + (string(0,<1B>%-12345X) + \ + contains(9,512,"LANGUAGE=PCL")) + +######################################################################## +# +# Raw print file support... +# +# Uncomment the following type and the application/octet-stream +# filter line in mime.convs to allow raw file printing without the +# -oraw option. +# + +#application/octet-stream + +# +# End of "$Id: mime.types 1430 2000-11-06 16:39:17Z 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..d594875c65 --- /dev/null +++ b/conf/printers.conf @@ -0,0 +1,96 @@ +# +# "$Id: printers.conf 1152 2000-06-22 18:25:29Z mike $" +# +# Sample printer configuration file for the Common UNIX Printing System +# (CUPS) scheduler. +# +# 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 +# + +######################################################################## +# # +# 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 + +# +# 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 + +# +# StateMessage: sets the printer-state-message attribute for the printer. +# + +#StateMessage Printer is idle. + +# +# Accepting: is the printer accepting jobs? +# +#Accepting Yes +#Accepting No + +# + +# +# End of "$Id: printers.conf 1152 2000-06-22 18:25:29Z mike $". +# diff --git a/config.h.in b/config.h.in new file mode 100644 index 0000000000..71da5faaaf --- /dev/null +++ b/config.h.in @@ -0,0 +1,147 @@ +/* + * "$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.1.5" + +/* + * 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" +#define CUPS_FONTPATH "/usr/share/cups/fonts" + + +/* + * 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 vsyslog() function? + */ + +#undef HAVE_VSYSLOG + +/* + * 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 + +/* + * Do we have the mallinfo function and malloc.h? + */ + +#undef HAVE_MALLINFO +#undef HAVE_MALLOC_H + +/* + * Do we have the OpenSSL library? + */ + +#undef HAVE_LIBSSL + +/* + * Do we have ? + */ + +#undef HAVE_SYS_IOCTL_H + +/* + * End of "$Id$". + */ diff --git a/configure.in b/configure.in new file mode 100644 index 0000000000..b59b7b4b19 --- /dev/null +++ b/configure.in @@ -0,0 +1,605 @@ +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(/) + +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:=}" +CXXFLAGS="${CXXFLAGS:=}" + +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]]) +AC_ARG_ENABLE(ssl, [ --enable-ssl turn on SSL/TLS support [default=no]]) +AC_ARG_ENABLE(libtool_unsupported, [ --enable-libtool-unsupported=LIBTOOL_PATH + turn on building with libtool (UNSUPPORTED!) [default=no]],[if eval "test x$enable_libtool_unsupported != xno"; then + LIBTOOL="$enable_libtool_unsupported" + enable_shared=no + echo "WARNING: libtool is not supported or endorsed by Easy Software Products." + echo " WE DO NOT PROVIDE TECHNICAL SUPPORT FOR LIBTOOL PROBLEMS." + echo " (even if you have a support contract)" +else + LIBTOOL="" +fi]) + +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 + +if test "$LIBTOOL" != ""; then + LIBCUPS="libcups.la" + LIBCUPSIMAGE="libcupsimage.la" + LINKCUPS="../cups/\$(LIBCUPS)" + LINKCUPSIMAGE="../filter/\$(LIBCUPSIMAGE)" + DSO=":" +else + LINKCUPS="-L../cups -lcups" + LINKCUPSIMAGE="-L../filter -lcupsimage" +fi + +AC_ARG_ENABLE(pam, [ --enable-pam turn on PAM support [default=yes]]) + +AC_ARG_WITH(fontpath, [ --with-fontpath set font path for pstoraster],fontpath="$withval",fontpath="") + +dnl Checks for programs... +AC_PROG_AWK +AC_PROG_CC +AC_PROG_CXX +AC_PROG_CPP +AC_PROG_RANLIB +AC_PATH_PROG(AR,ar) +AC_PATH_PROG(CHMOD,chmod) +AC_PATH_PROG(CHOWN,chown) +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") +if test "$ac_cv_lib_c_crypt" = "no"; then + AC_CHECK_LIB(crypt,crypt) +fi +AC_CHECK_LIB(sec,getspent) + +LIBMALLOC="" +AC_CHECK_LIB(c,mallinfo,LIBS="$LIBS"; AC_DEFINE(HAVE_MALLINFO),LIBS="$LIBS") +if test "$ac_cv_lib_c_mallinfo" = "no"; then + AC_CHECK_LIB(malloc,mallinfo, + LIBS="$LIBS" + LIBMALLOC="-lmalloc" + AC_DEFINE(HAVE_MALLINFO), + LIBS="$LIBS") +fi +AC_SUBST(LIBMALLOC) + +if test "$enable_pam" != "no"; then + OLDLIBS="$LIBS" + AC_CHECK_LIB(dl,dlopen) + AC_CHECK_LIB(pam,pam_start) + if test "$ac_cv_lib_pam_pam_start" != "no"; then + PAMDIR="/etc/pam.d" + else + PAMDIR="" + LIBS="$OLDLIBS" + fi + AC_SUBST(PAMDIR) +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 Encryption support... + +SSLLIBS="" +AC_SUBST(SSLLIBS) + +if test "$enable_ssl" = "yes"; then + dnl Save the current libraries so the crypto stuff isn't always + dnl included... + SAVELIBS="$LIBS" + + dnl Some ELF systems can't resolve all the symbols in libcrypto + dnl if libcrypto was linked against RSAREF, and fail to link the + dnl test program correctly, even though a correct installation + dnl of OpenSSL exists. So we test the linking three times in + dnl case the RSAREF libraries are needed. + + for libcrypto in \ + "-lcrypto" \ + "-lcrypto -lrsaref" \ + "-lcrypto -lRSAglue -lrsaref" + do + AC_CHECK_LIB(ssl,SSL_new, + [SSLLIBS="-lssl $libcrypto" + AC_DEFINE(HAVE_LIBSSL)],, + $libcrypto + ) + if test "x${SSLLIBS}" != "x"; then + break + fi + done + + LIBS="$SAVELIBS" +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, gzgets, + 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_set_tRNS_to_alpha, + 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(crypt.h,AC_DEFINE(HAVE_CRYPT_H)) +AC_CHECK_HEADER(malloc.h,AC_DEFINE(HAVE_MALLOC_H)) +AC_CHECK_HEADER(shadow.h,AC_DEFINE(HAVE_SHADOW_H)) +AC_CHECK_HEADER(stddef.h,AC_DEFINE(HAVE_STDDEF_H)) +AC_CHECK_HEADER(stdlib.h,AC_DEFINE(HAVE_STDLIB_H)) +AC_CHECK_HEADER(sys/ioctl.h,AC_DEFINE(HAVE_SYS_IOCTL_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 vsyslog function. +AC_CHECK_FUNCS(vsyslog) + +dnl Checks for signal functions. +if test "$uname" != "Linux"; then + AC_CHECK_FUNCS(sigset) +fi + +AC_CHECK_FUNCS(sigaction) + +dnl Checks for wait functions. +AC_CHECK_FUNCS(waitpid) +AC_CHECK_FUNCS(wait3) + +dnl Update compiler options... +if test -n "$GCC"; then + GXX="gcc" + + if test -z "$OPTIM"; then + OPTIM="-O2 -g3" + fi + if test $PICFLAG = 1; then + OPTIM="-fPIC $OPTIM" + fi + OPTIM="-Wall $OPTIM" +else + case $uname in + IRIX*) + if test -z "$OPTIM"; then + OPTIM="-O2" + fi + if test $uversion -ge 62; then + OPTIM="$OPTIM -n32 -mips3" + fi + OPTIM="-fullwarn $OPTIM" + ;; + HP-UX*) + if test -z "$OPTIM"; then + OPTIM="+O2 -g3" + fi + OPTIM="-Ae $OPTIM" + ;; + SunOS*) + # Solaris + if test -z "$OPTIM"; then + OPTIM="-xO4" + 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 *BSD, HP-UX, and Solaris run-time linkers need help when + # 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="$LDFLAGS -R$libdir" + ;; + FreeBSD* | NetBSD* | OpenBSD*) + # *BSD + LDFLAGS="$LDFLAGS -Wl,-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) +AC_SUBST(LIBTOOL) +AC_SUBST(LINKCUPS) +AC_SUBST(LINKCUPSIMAGE) + +dnl Fix "prefix" variable if it hasn't been specified... +if test "$prefix" = "NONE"; then + prefix="/" +fi + +dnl Fix "exec_prefix" variable if it hasn't been specified... +if test "$exec_prefix" = "NONE"; then + if test "$prefix" = "/"; then + exec_prefix="/usr" + else + exec_prefix="$prefix" + fi +fi + +dnl Fix "sharedstatedir" variable if it hasn't been specified... +if test "$sharedstatedir" = "\${prefix}/com" -a "$prefix" = "/"; then + sharedstatedir="/usr/com" +fi + +dnl Fix "infodir" variable if it hasn't been specified... +if test "$infodir" = "\${prefix}/info" -a "$prefix" = "/"; then + infodir="/usr/info" +fi + +dnl Fix "datadir" variable if it hasn't been specified... +if test "$datadir" = "\${prefix}/share"; then + if test "$prefix" = "/"; then + datadir="/usr/share" + else + datadir="$prefix/share" + fi +fi + +dnl Fix "includedir" variable if it hasn't been specified... +if test "$includedir" = "\${prefix}/include" -a "$prefix" = "/"; then + includedir="/usr/include" +fi + +dnl Fix "localstatedir" variable if it hasn't been specified... +if test "$localstatedir" = "\${prefix}/var"; then + if test "$prefix" = "/"; then + localstatedir="/var" + else + localstatedir="$prefix/var" + fi +fi + +dnl Fix "sysconfdir" variable if it hasn't been specified... +if test "$sysconfdir" = "\${prefix}/etc"; then + if test "$prefix" = "/"; then + sysconfdir="/etc" + else + sysconfdir="$prefix/etc" + fi +fi + +dnl Fix "libdir" variable for IRIX 6.x... +if test "$uname" = "IRIX" -a $uversion -ge 62; then + libdir="$exec_prefix/lib32" +fi + +dnl Fix "mandir" variable... +if test "$mandir" = "\${prefix}/man" -a "$prefix" = "/"; then + case "$uname" in + FreeBSD* | NetBSD* | OpenBSD*) + # *BSD + mandir="/usr/share/man" + ;; + IRIX*) + # SGI IRIX + mandir="/usr/share/catman" + ;; + *) + # All others + mandir="/usr/man" + ;; + esac +fi + +dnl Fix "fontpath" variable... +if test "x$fontpath" = "x"; then + fontpath="$datadir/cups/fonts" +fi + +dnl Setup manpage extensions... +case "$uname" in + FreeBSD* | NetBSD* | OpenBSD*) + # *BSD + CAT1EXT=0 + CAT5EXT=0 + CAT8EXT=0 + ;; + IRIX*) + # SGI IRIX + CAT1EXT=z + CAT5EXT=z + CAT8EXT=z + ;; + *) + # All others + CAT1EXT=1 + CAT5EXT=5 + CAT8EXT=8 + ;; +esac + +AC_SUBST(CAT1EXT) +AC_SUBST(CAT5EXT) +AC_SUBST(CAT8EXT) + +dnl Setup init.d locations... +case "$uname" in + FreeBSD* | NetBSD* | OpenBSD*) + # *BSD + INITDIR="" + INITDDIR="" + ;; + + Linux*) + # Linux seems to choose an init.d directory at random... + if test -d /sbin/init.d; then + # SuSE + INITDIR="/sbin/init.d" + INITDDIR=".." + else + if test -d /etc/rc.d; then + # RedHat + INITDIR="/etc/rc.d" + INITDDIR="../init.d" + else + # Others + INITDIR="/etc" + INITDDIR="../init.d" + fi + fi + ;; + + OSF1* | HP-UX*) + INITDIR="/sbin" + INITDDIR="../init.d" + ;; + + *) + INITDIR="/etc" + INITDDIR="../init.d" + ;; + +esac + +AC_SUBST(INITDIR) +AC_SUBST(INITDDIR) + +dnl Setup default locations... +CUPS_SERVERROOT='${sysconfdif}/cups' +CUPS_LOGDIR='${localstatedir}/log/cups' +CUPS_REQUESTS='${localstatedir}/spool/cups' + +AC_DEFINE_UNQUOTED(CUPS_SERVERROOT, "$sysconfdir/cups") +AC_DEFINE_UNQUOTED(CUPS_LOGDIR, "$localstatedir/log/cups") +AC_DEFINE_UNQUOTED(CUPS_REQUESTS, "$localstatedir/spool/cups") + +dnl See what directory to put server executables... +case "$uname" in + FreeBSD* | NetBSD* | OpenBSD*) + # *BSD + INSTALL_SYSV="" + CUPS_SERVERBIN='${exec_prefix}/libexec/cups' + AC_DEFINE_UNQUOTED(CUPS_SERVERBIN, "$exec_prefix/libexec/cups") + ;; + *) + # All others + INSTALL_SYSV="install-sysv" + CUPS_SERVERBIN='${exec_prefix}/lib/cups' + AC_DEFINE_UNQUOTED(CUPS_SERVERBIN, "$exec_prefix/lib/cups") + ;; +esac + +AC_SUBST(INSTALL_SYSV) +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* | FreeBSD* | NetBSD* | OpenBSD*) + CUPS_LOCALEDIR='${datadir}/locale' + AC_DEFINE_UNQUOTED(CUPS_LOCALEDIR, "$datadir/locale") + ;; + + OSF1*) + CUPS_LOCALEDIR='${exec_prefix}/lib/nls/msg' + AC_DEFINE_UNQUOTED(CUPS_LOCALEDIR, "$exec_prefix/lib/nls/msg") + ;; + + *) + # This is the standard System V location... + CUPS_LOCALEDIR='${exec_prefix}/lib/locale' + AC_DEFINE_UNQUOTED(CUPS_LOCALEDIR, "$exec_prefix/lib/locale") + ;; +esac + +AC_SUBST(CUPS_LOCALEDIR) + +dnl Set the CUPS_DATADIR directory... +CUPS_DATADIR='${datadir}/cups' +AC_DEFINE_UNQUOTED(CUPS_DATADIR, "$datadir/cups") +AC_SUBST(CUPS_DATADIR) + +dnl Set the CUPS_DOCROOT directory... +CUPS_DOCROOT='${datadir}/doc/cups' +AC_DEFINE_UNQUOTED(CUPS_DOCROOT, "$datadir/doc/cups") +AC_SUBST(CUPS_DOCROOT) + +dnl Set the CUPS_FONTPATH directory... +AC_DEFINE_UNQUOTED(CUPS_FONTPATH, "$fontpath") + +AC_OUTPUT(Makedefs cups.sh) + +dnl +dnl End of "$Id$". +dnl diff --git a/cups.dsw b/cups.dsw new file mode 100644 index 0000000000..28bdbaa895 --- /dev/null +++ b/cups.dsw @@ -0,0 +1,29 @@ +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> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/cups.list b/cups.list new file mode 100644 index 0000000000..a317dd5dae --- /dev/null +++ b/cups.list @@ -0,0 +1,320 @@ +# +# "$Id: cups.list 1471 2000-12-11 04:40:31Z 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 information +%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.1.5 +%incompat printpro + +# Server programs +%system all +# Server files +f 0555 root sys $SBINDIR/cupsd scheduler/cupsd + +d 0555 root sys $SERVERBIN - +d 0555 root sys $SERVERBIN/backend - +f 0555 root sys $SERVERBIN/backend/ipp backend/ipp +l 0555 root sys $SERVERBIN/backend/http ipp +f 0555 root sys $SERVERBIN/backend/lpd backend/lpd +f 0555 root sys $SERVERBIN/backend/parallel backend/parallel +f 0555 root sys $SERVERBIN/backend/serial backend/serial +f 0555 root sys $SERVERBIN/backend/socket backend/socket +f 0555 root sys $SERVERBIN/backend/usb backend/usb +d 0555 root sys $SERVERBIN/cgi-bin - +f 0555 root sys $SERVERBIN/cgi-bin/admin.cgi cgi-bin/admin.cgi +f 0555 root sys $SERVERBIN/cgi-bin/classes.cgi cgi-bin/classes.cgi +f 0555 root sys $SERVERBIN/cgi-bin/jobs.cgi cgi-bin/jobs.cgi +f 0555 root sys $SERVERBIN/cgi-bin/printers.cgi cgi-bin/printers.cgi +d 0555 root sys $SERVERBIN/daemon - +f 0555 root sys $SERVERBIN/daemon/cups-lpd scheduler/cups-lpd +f 0555 root sys $SERVERBIN/daemon/cups-polld scheduler/cups-polld +d 0555 root sys $SERVERBIN/filter - +f 0555 root sys $SERVERBIN/filter/pstoraster pstoraster/pstoraster +f 0555 root sys $SERVERBIN/filter/pdftops pdftops/pdftops +f 0555 root sys $SERVERBIN/filter/imagetops filter/imagetops +f 0555 root sys $SERVERBIN/filter/pstops filter/pstops +f 0555 root sys $SERVERBIN/filter/texttops filter/texttops +f 0555 root sys $SERVERBIN/filter/rastertoepson filter/rastertoepson +f 0555 root sys $SERVERBIN/filter/rastertohp filter/rastertohp +f 0555 root sys $SERVERBIN/filter/hpgltops filter/hpgltops +f 0555 root sys $SERVERBIN/filter/imagetoraster filter/imagetoraster + +# Admin commands +l 0555 root sys $BINDIR/disable $SBINDIR/accept +l 0555 root sys $BINDIR/enable $SBINDIR/accept +l 0555 root sys $LIBDIR/accept $SBINDIR/accept +l 0555 root sys $LIBDIR/lpadmin $SBINDIR/lpadmin +l 0555 root sys $LIBDIR/reject accept +f 0555 root sys $SBINDIR/accept systemv/accept +f 0555 root sys $SBINDIR/lpadmin systemv/lpadmin +f 0555 root sys $SBINDIR/lpc berkeley/lpc +f 0555 root sys $SBINDIR/lpinfo systemv/lpinfo +f 0555 root sys $SBINDIR/lpmove systemv/lpmove +l 0555 root sys $SBINDIR/reject accept + +%system irix +l 0555 root sys /usr/etc/lpc $SBINDIR/lpc +%system all + +# User commands +f 0555 root sys $BINDIR/cancel systemv/cancel +f 0555 root sys $BINDIR/lp systemv/lp +f 0555 root sys $BINDIR/lpoptions systemv/lpoptions +f 4555 root sys $BINDIR/lppasswd systemv/lppasswd +f 0555 root sys $BINDIR/lpq berkeley/lpq +f 0555 root sys $BINDIR/lpr berkeley/lpr +f 0555 root sys $BINDIR/lprm berkeley/lprm +f 0555 root sys $BINDIR/lpstat systemv/lpstat + +%system irix +l 0555 root sys /usr/bsd/lpq $BINDIR/lpq +l 0555 root sys /usr/bsd/lpr $BINDIR/lpr +l 0555 root sys /usr/bsd/lprm $BINDIR/lprm +%system all + +# DSOs +%system hpux +f 0555 root sys $LIBDIR/libcups.sl.2 cups/libcups.sl.2 +l 0555 root sys $LIBDIR/libcups.sl libcups.sl.2 +f 0555 root sys $LIBDIR/libcupsimage.sl.2 filter/libcupsimage.sl.2 +l 0555 root sys $LIBDIR/libcupsimage.sl libcupsimage.sl.2 +%system !hpux +f 0555 root sys $LIBDIR/libcups.so.2 cups/libcups.so.2 +l 0555 root sys $LIBDIR/libcups.so libcups.so.2 +f 0555 root sys $LIBDIR/libcupsimage.so.2 filter/libcupsimage.so.2 +l 0555 root sys $LIBDIR/libcupsimage.so libcupsimage.so.2 +%system all + +# Directories +d 0755 root sys $LOGDIR - +d 0700 lp sys $REQUESTS - +d 1700 lp sys $REQUESTS/tmp - + +# Data files +f 0444 root sys $LOCALEDIR/C/cups_C locale/C/cups_C +f 0444 root sys $LOCALEDIR/de/cups_de locale/de/cups_de +f 0444 root sys $LOCALEDIR/en/cups_en locale/en/cups_en +f 0444 root sys $LOCALEDIR/es/cups_es locale/es/cups_es +f 0444 root sys $LOCALEDIR/fr/cups_fr locale/fr/cups_fr +f 0444 root sys $LOCALEDIR/it/cups_it locale/it/cups_it + +d 0555 root sys $DATADIR - + +d 0555 root sys $DATADIR/banners - +f 0444 root sys $DATADIR/banners/classified data/classified +f 0444 root sys $DATADIR/banners/confidential data/confidential +f 0444 root sys $DATADIR/banners/secret data/secret +f 0444 root sys $DATADIR/banners/standard data/standard +f 0444 root sys $DATADIR/banners/topsecret data/topsecret +f 0444 root sys $DATADIR/banners/unclassified data/unclassified + +d 0555 root sys $DATADIR/charsets - +f 0444 root sys $DATADIR/charsets/windows-874 data/windows-874 +f 0444 root sys $DATADIR/charsets/windows-1250 data/windows-1250 +f 0444 root sys $DATADIR/charsets/windows-1251 data/windows-1251 +f 0444 root sys $DATADIR/charsets/windows-1252 data/windows-1252 +f 0444 root sys $DATADIR/charsets/windows-1253 data/windows-1253 +f 0444 root sys $DATADIR/charsets/windows-1254 data/windows-1254 +f 0444 root sys $DATADIR/charsets/windows-1255 data/windows-1255 +f 0444 root sys $DATADIR/charsets/windows-1256 data/windows-1256 +f 0444 root sys $DATADIR/charsets/windows-1257 data/windows-1257 +f 0444 root sys $DATADIR/charsets/windows-1258 data/windows-1258 +f 0444 root sys $DATADIR/charsets/iso-8859-1 data/iso-8859-1 +f 0444 root sys $DATADIR/charsets/iso-8859-14 data/iso-8859-14 +f 0444 root sys $DATADIR/charsets/iso-8859-15 data/iso-8859-15 +f 0444 root sys $DATADIR/charsets/iso-8859-2 data/iso-8859-2 +f 0444 root sys $DATADIR/charsets/iso-8859-3 data/iso-8859-3 +f 0444 root sys $DATADIR/charsets/iso-8859-4 data/iso-8859-4 +f 0444 root sys $DATADIR/charsets/iso-8859-5 data/iso-8859-5 +f 0444 root sys $DATADIR/charsets/iso-8859-6 data/iso-8859-6 +f 0444 root sys $DATADIR/charsets/iso-8859-7 data/iso-8859-7 +f 0444 root sys $DATADIR/charsets/iso-8859-8 data/iso-8859-8 +f 0444 root sys $DATADIR/charsets/iso-8859-9 data/iso-8859-9 +f 0444 root sys $DATADIR/charsets/utf-8 data/utf-8 + +d 0555 root sys $DATADIR/data - +f 0444 root sys $DATADIR/data/HPGLprolog data/HPGLprolog +f 0444 root sys $DATADIR/data/psglyphs data/psglyphs +f 0444 root sys $DATADIR/data/testprint.ps data/testprint.ps + +d 0555 root sys $DATADIR/fonts - +f 0444 root sys $DATADIR/fonts fonts/* + +d 0555 root sys $DATADIR/pstoraster - +f 0444 root sys $DATADIR/pstoraster/Fontmap pstoraster/Fontmap +f 0444 root sys $DATADIR/pstoraster pstoraster/gs*.ps + +d 0555 root sys $DATADIR/model - +f 0444 root sys $DATADIR/model ppd/*.ppd + +d 0555 root sys $DATADIR/templates - +f 0444 root sys $DATADIR/templates templates/*.tmpl + +# Config files +d 0555 root sys $SERVERROOT - +d 0711 root sys $SERVERROOT/certs - +d 0755 root sys $SERVERROOT/interfaces - +d 0755 root sys $SERVERROOT/ppd - +c 0644 root sys $SERVERROOT conf/*.conf +f 0644 root sys $SERVERROOT/mime.convs conf/mime.convs +f 0644 root sys $SERVERROOT/mime.types conf/mime.types + +%system linux +d 0555 root sys $PAMDIR - +c 0644 root sys $PAMDIR/cups data/cups.pam +c 0644 root sys $PAMDIR/cups.suse data/cups.suse +%install if test -f /lib/security/pam_unix.so; then +%install mv $PAMDIR/cups.suse $PAMDIR/cups +%install fi +%system all + +# Developer files +d 0555 root sys $INCLUDEDIR/cups - +f 0444 root sys $INCLUDEDIR/cups/cups.h cups/cups.h +f 0444 root sys $INCLUDEDIR/cups/http.h cups/http.h +f 0444 root sys $INCLUDEDIR/cups/image.h filter/image.h +f 0444 root sys $INCLUDEDIR/cups/ipp.h cups/ipp.h +f 0444 root sys $INCLUDEDIR/cups/language.h cups/language.h +f 0444 root sys $INCLUDEDIR/cups/md5.h cups/md5.h +f 0444 root sys $INCLUDEDIR/cups/ppd.h cups/ppd.h +f 0444 root sys $INCLUDEDIR/cups/raster.h filter/raster.h + +f 0444 root sys $LIBDIR/libcups.a cups/libcups.a + +# Documentation files +d 0555 root sys $DOCDIR - +f 0444 root sys $DOCDIR/cups.css doc/cups.css +f 0444 root sys $DOCDIR doc/*.html +f 0444 root sys $DOCDIR doc/*.pdf +d 0555 root sys $DOCDIR/images - +f 0444 root sys $DOCDIR/images doc/images/*.gif + +# Man pages +%system irix +d 0555 root sys $MANDIR/a_man - +d 0555 root sys $MANDIR/a_man/cat1 - +d 0555 root sys $MANDIR/u_man - +d 0555 root sys $MANDIR/u_man/cat1 - +d 0555 root sys $MANDIR/u_man/cat5 - + +f 0444 root sys $MANDIR/a_man/cat1/accept.z man/accept.z +l 0444 root sys $MANDIR/a_man/cat1/reject.z accept.z +f 0444 root sys $MANDIR/u_man/cat1/backend.z man/backend.z +f 0444 root sys $MANDIR/u_man/cat5/classes.conf.z man/classes.conf.z +f 0444 root sys $MANDIR/a_man/cat1/cups-lpd.z man/cups-lpd.z +f 0444 root sys $MANDIR/a_man/cat1/cups-polld.z man/cups-polld.z +f 0444 root sys $MANDIR/u_man/cat5/cupsd.conf.z man/cupsd.conf.z +f 0444 root sys $MANDIR/a_man/cat1/cupsd.z man/cupsd.z +f 0444 root sys $MANDIR/a_man/cat1/enable.z man/enable.z +l 0444 root sys $MANDIR/a_man/cat1/disable.z enable.z +f 0444 root sys $MANDIR/u_man/cat1/filter.z man/filter.z +f 0444 root sys $MANDIR/a_man/cat1/lpadmin.z man/lpadmin.z +f 0444 root sys $MANDIR/a_man/cat1/lpc.z man/lpc.z +f 0444 root sys $MANDIR/a_man/cat1/lpinfo.z man/lpinfo.z +f 0444 root sys $MANDIR/a_man/cat1/lpmove.z man/lpmove.z +f 0444 root sys $MANDIR/u_man/cat1/lpoptions.z man/lpoptions.z +f 0444 root sys $MANDIR/u_man/cat1/lpq.z man/lpq.z +f 0444 root sys $MANDIR/u_man/cat1/lprm.z man/lprm.z +f 0444 root sys $MANDIR/u_man/cat1/lpr.z man/lpr.z +f 0444 root sys $MANDIR/u_man/cat1/lpstat.z man/lpstat.z +f 0444 root sys $MANDIR/u_man/cat1/lp.z man/lp.z +l 0444 root sys $MANDIR/u_man/cat1/cancel.z lp.z +f 0444 root sys $MANDIR/u_man/cat5/mime.convs.z man/mime.convs.z +f 0444 root sys $MANDIR/u_man/cat5/mime.types.z man/mime.types.z +f 0444 root sys $MANDIR/u_man/cat5/printers.conf.z man/printers.conf.z + +%system solaris hpux +d 0555 root sys $MANDIR/man1 - +d 0555 root sys $MANDIR/man5 - +d 0555 root sys $MANDIR/man1m - + +f 0444 root sys $MANDIR/man1m/accept.1m man/accept.man +l 0444 root sys $MANDIR/man1m/reject.1m accept.1m +f 0444 root sys $MANDIR/man1/backend.1 man/backend.man +f 0444 root sys $MANDIR/man1/classes.conf.5 man/classes.conf.man +f 0444 root sys $MANDIR/man1m/cups-lpd.1m man/cups-lpd.man +f 0444 root sys $MANDIR/man1m/cups-polld.1m man/cups-polld.man +f 0444 root sys $MANDIR/man1m/cupsd.1m man/cupsd.man +f 0444 root sys $MANDIR/man5/cupsd.conf.5 man/cupsd.conf.man +f 0444 root sys $MANDIR/man1m/enable.1m man/enable.man +l 0444 root sys $MANDIR/man1m/disable.1m enable.1m +f 0444 root sys $MANDIR/man1/filter.1 man/filter.man +f 0444 root sys $MANDIR/man1m/lpadmin.1m man/lpadmin.man +f 0444 root sys $MANDIR/man1m/lpc.1m man/lpc.man +f 0444 root sys $MANDIR/man1m/lpinfo.1m man/lpinfo.man +f 0444 root sys $MANDIR/man1m/lpmove.1m man/lpmove.man +f 0444 root sys $MANDIR/man1/lpoptions.1 man/lpoptions.man +f 0444 root sys $MANDIR/man1/lpq.1 man/lpq.man +f 0444 root sys $MANDIR/man1/lprm.1 man/lprm.man +f 0444 root sys $MANDIR/man1/lpr.1 man/lpr.man +f 0444 root sys $MANDIR/man1/lpstat.1 man/lpstat.man +f 0444 root sys $MANDIR/man1/lp.1 man/lp.man +l 0444 root sys $MANDIR/man1/cancel.1 lp.1 +f 0444 root sys $MANDIR/man5/mime.convs.5 man/mime.convs.man +f 0444 root sys $MANDIR/man5/mime.types.5 man/mime.types.man +f 0444 root sys $MANDIR/man5/printers.conf.5 man/printers.conf.man + +%system !irix !solaris !hpux +d 0555 root sys $MANDIR/man1 - +d 0555 root sys $MANDIR/man5 - +d 0555 root sys $MANDIR/man8 - + +f 0444 root sys $MANDIR/man8/accept.8 man/accept.man +l 0444 root sys $MANDIR/man8/reject.8 accept.8 +f 0444 root sys $MANDIR/man1/backend.1 man/backend.man +f 0444 root sys $MANDIR/man1/classes.conf.5 man/classes.conf.man +f 0444 root sys $MANDIR/man8/cups-lpd.8 man/cups-lpd.man +f 0444 root sys $MANDIR/man8/cups-polld.8 man/cups-polld.man +f 0444 root sys $MANDIR/man8/cupsd.8 man/cupsd.man +f 0444 root sys $MANDIR/man5/cupsd.conf.5 man/cupsd.conf.man +f 0444 root sys $MANDIR/man8/enable.8 man/enable.man +l 0444 root sys $MANDIR/man8/disable.8 enable.8 +f 0444 root sys $MANDIR/man1/filter.1 man/filter.man +f 0444 root sys $MANDIR/man8/lpadmin.8 man/lpadmin.man +f 0444 root sys $MANDIR/man8/lpc.8 man/lpc.man +f 0444 root sys $MANDIR/man8/lpinfo.8 man/lpinfo.man +f 0444 root sys $MANDIR/man8/lpmove.8 man/lpmove.man +f 0444 root sys $MANDIR/man1/lpoptions.1 man/lpoptions.man +f 0444 root sys $MANDIR/man1/lpq.1 man/lpq.man +f 0444 root sys $MANDIR/man1/lprm.1 man/lprm.man +f 0444 root sys $MANDIR/man1/lpr.1 man/lpr.man +f 0444 root sys $MANDIR/man1/lpstat.1 man/lpstat.man +f 0444 root sys $MANDIR/man1/lp.1 man/lp.man +l 0444 root sys $MANDIR/man1/cancel.1 lp.1 +f 0444 root sys $MANDIR/man5/mime.convs.5 man/mime.convs.man +f 0444 root sys $MANDIR/man5/mime.types.5 man/mime.types.man +f 0444 root sys $MANDIR/man5/printers.conf.5 man/printers.conf.man + +# Startup script +%system all +i 0555 root sys cups cups.sh + +# +# End of "$Id: cups.list 1471 2000-12-11 04:40:31Z mike $". +# diff --git a/cups.sh.in b/cups.sh.in new file mode 100755 index 0000000000..e76eaca150 --- /dev/null +++ b/cups.sh.in @@ -0,0 +1,114 @@ +#!/bin/sh +# +# "$Id$" +# +# Startup/shutdown script for the Common UNIX Printing System (CUPS). +# +# Linux chkconfig stuff: +# +# chkconfig: 0235 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*) + IS_ON=/sbin/chkconfig + ;; + + *) + IS_ON=/bin/true + ;; +esac + +# The verbose flag controls the printing of the names of +# daemons as they are started. +if $IS_ON verbose; then + ECHO=echo +else + ECHO=: +fi + +# See if the CUPS server is running... +case "`uname`" in + IRIX* | HP-UX | SunOS) + pid=`ps -e | awk '{print $1,$4}' | grep cupsd | awk '{print $1}'` + ;; + OSF1) + pid=`ps -e | awk '{print $1,$5}' | grep cupsd | awk '{print $1}'` + ;; + Linux) + pid=`ps ax | awk '{print $1,$5}' | grep cupsd | awk '{print $1}'` + ;; + *) + pid="" + ;; +esac + +# Start or stop the CUPS server based upon the first argument to the script. +case $1 in + start | restart | reload) + if test "$pid" != ""; then + if $IS_ON cups; then + kill -HUP $pid + $ECHO "cups: scheduler restarted." + else + kill $pid + $ECHO "cups: scheduler stopped." + fi + else + if $IS_ON cups; then + prefix=@prefix@ + exec_prefix=@exec_prefix@ + @sbindir@/cupsd + $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..2e616697ee --- /dev/null +++ b/cups.spec @@ -0,0 +1,176 @@ +# +# "$Id: cups.spec 1421 2000-10-19 20:55:06Z 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.1.5 +Release: 0 +Copyright: GPL +Group: System Environment/Daemons +Source: ftp://ftp.easysw.com/pub/cups/%{version}/cups-%{version}-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: /var/tmp/%{name}-root +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 +mkdir -p $RPM_BUILD_ROOT/etc/rc.d/rc0.d +mkdir -p $RPM_BUILD_ROOT/etc/rc.d/rc3.d +mkdir -p $RPM_BUILD_ROOT/etc/rc.d/rc5.d + +make prefix=$RPM_BUILD_ROOT \ + exec_prefix=$RPM_BUILD_ROOT/usr \ + BINDIR=$RPM_BUILD_ROOT/usr/bin \ + DATADIR=$RPM_BUILD_ROOT/usr/share/cups \ + DOCDIR=$RPM_BUILD_ROOT/usr/share/doc/cups \ + INCLUDEDIR=$RPM_BUILD_ROOT/usr/include \ + LIBDIR=$RPM_BUILD_ROOT/usr/lib \ + LOCALEDIR=$RPM_BUILD_ROOT/usr/share/locale \ + MANDIR=$RPM_BUILD_ROOT/usr/man \ + PAMDIR=$RPM_BUILD_ROOT/etc/pam.d \ + REQUESTS=$RPM_BUILD_ROOT/var/spool/cups \ + SBINDIR=$RPM_BUILD_ROOT/usr/sbin \ + SERVERBIN=$RPM_BUILD_ROOT/usr/lib/cups \ + SERVERROOT=$RPM_BUILD_ROOT/etc/cups \ + install + +%post +if test -x /sbin/chkconfig; then + /sbin/chkconfig --add cups + /sbin/chkconfig cups on +fi + +if test -f /sbin/init.d/cups; then + /sbin/init.d/cups start +fi +if test -f /etc/rc.d/init.d/cups; then + /etc/rc.d/init.d/cups start +fi +if test -f /etc/init.d/cups; then + /etc/init.d/cups start +fi + +%preun +if test -f /sbin/init.d/cups; then + /sbin/init.d/cups stop +fi +if test -f /etc/rc.d/init.d/cups; then + /etc/rc.d/init.d/cups stop +fi +if test -f /etc/init.d/cups; then + /etc/init.d/cups stop +fi + +if test -x /sbin/chkconfig; then + /sbin/chkconfig --del cups +fi + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +%defattr(-,root,root) +%dir /etc/cups +%config /etc/cups/*.conf +%dir /etc/cups/certs +%dir /etc/cups/interfaces +/etc/cups/mime.types +/etc/cups/mime.convs +%dir /etc/cups/ppd +%dir /etc/pam.d +/etc/pam.d/* + +# RC dirs are a pain under Linux... Uncomment the appropriate ones if you +# don't use Red Hat or Mandrake... + +/etc/rc.d/init.d/* +/etc/rc.d/rc0.d/* +/etc/rc.d/rc3.d/* +/etc/rc.d/rc5.d/* + +#/etc/init.d/* +#/etc/rc0.d/* +#/etc/rc3.d/* +#/etc/rc5.d/* + +#/sbin/rc.d/* +#/sbin/rc.d/rc0.d/* +#/sbin/rc.d/rc3.d/* +#/sbin/rc.d/rc5.d/* + +/usr/bin/* +/usr/lib/*.so* +%dir /usr/lib/cups +/usr/lib/cups/* +/usr/man/* +/usr/sbin/* +%dir /usr/share/cups +/usr/share/cups/* +%dir /usr/share/doc/cups +/usr/share/doc/cups/* +%dir /usr/share/locale +/usr/share/locale/* +%attr(0700,lp,root) %dir /var/spool/cups +%attr(1700,lp,root) %dir /var/spool/cups/tmp + +%files devel +%dir /usr/include/cups +/usr/include/cups/* +/usr/lib/*.a + +# +# End of "$Id: cups.spec 1421 2000-10-19 20:55:06Z mike $". +# diff --git a/cups/Makefile b/cups/Makefile new file mode 100644 index 0000000000..96eeef0480 --- /dev/null +++ b/cups/Makefile @@ -0,0 +1,166 @@ +# +# "$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 md5passwd.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 md5.h ppd.h + + +# +# Targets in this directory... +# + +TARGETS = $(LIBCUPS) libcups.a + + +# +# Make all targets... +# + +all: $(TARGETS) + + +# +# Remove object and target files... +# + +clean: + $(RM) $(OBJS) $(TARGETS) `basename $(LIBCUPS) .2` + + +# +# Install object and target files... +# + +install: all + -$(MKDIR) $(INCLUDEDIR)/cups + $(CHMOD) ugo+rx $(INCLUDEDIR) + $(CHMOD) ugo+rx $(INCLUDEDIR)/cups + $(INSTALL_DATA) $(HEADERS) $(INCLUDEDIR)/cups + -$(MKDIR) $(LIBDIR) + $(CHMOD) ugo+rx $(LIBDIR) + $(INSTALL_LIB) $(LIBCUPS) $(LIBDIR) + if test $(LIBCUPS) != "libcups.a" -a $(LIBCUPS) != "libcups.la"; then \ + $(INSTALL_LIB) libcups.a $(LIBDIR); \ + $(RM) $(LIBDIR)/`basename $(LIBCUPS) .2`; \ + $(LN) $(LIBCUPS) $(LIBDIR)/`basename $(LIBCUPS) .2`; \ + fi + + +# +# libcups.so.2, libcups.sl.1 +# + +libcups.so.2 libcups.sl.2: $(LIBOBJS) ../Makedefs + echo Linking $@... + $(DSO) $@ $(LIBOBJS) $(LDFLAGS) $(SSLLIBS) + $(RM) `basename $@ .2` + $(LN) $@ `basename $@ .2` + + +# +# libcups.la +# + +libcups.la: $(LIBOBJS) ../Makedefs + echo Linking $@... + $(CC) -o $@ $(LIBOBJS:.o=.lo) -rpath $(LIBDIR) -version-info 2:0 + + +# +# 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..8822fdbe02 --- /dev/null +++ b/cups/cups.dsp @@ -0,0 +1,188 @@ +# 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=.\dest.c +# End Source File +# Begin Source File + +SOURCE=.\emit.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=.\md5.c +# End Source File +# Begin Source File + +SOURCE=.\md5passwd.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=.\snprintf.c +# End Source File +# Begin Source File + +SOURCE=.\string.c +# End Source File +# Begin Source File + +SOURCE=.\usersys.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=.\cups_C.h +# End Source File +# Begin Source File + +SOURCE=.\debug.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=.\md5.h +# End Source File +# Begin Source File + +SOURCE=.\ppd.h +# End Source File +# Begin Source File + +SOURCE=.\string.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..9134e33920 --- /dev/null +++ b/cups/cups.h @@ -0,0 +1,156 @@ +/* + * "$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 "ipp.h" +# include "ppd.h" + + +/* + * C++ magic... + */ + +# ifdef __cplusplus +extern "C" { +# endif /* __cplusplus */ + + +/* + * Constants... + */ + +# define CUPS_VERSION 1.0103 +# 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_DEFAULT = 0x20000, /* Default printer on network */ + 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 or NULL */ + 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 http_encryption_t cupsEncryption(void); +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 int cupsPrintFiles(const char *printer, int num_files, + const char **files, 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 cupsEncodeOptions(ipp_t *ipp, 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 void cupsSetEncryption(http_encryption_t e); +extern void cupsSetPasswordCB(const char *(*cb)(const char *)); +extern void cupsSetServer(const char *server); +extern void cupsSetUser(const char *user); +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..869849d04b --- /dev/null +++ b/cups/cups_C.h @@ -0,0 +1,133 @@ +"iso-8859-1", +"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.", +"426 An upgrade to a secure connection is required. If you are seeing this message in a web browser then it does not support HTTP encryption upgrades.", +"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..a2f15c369a --- /dev/null +++ b/cups/dest.c @@ -0,0 +1,521 @@ +/* + * "$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. + * cups_get_dests() - Get destinations from a file. + */ + +/* + * Include necessary headers... + */ + +#include "cups.h" +#include "string.h" +#include +#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 (strcasecmp(name, dest->name) == 0 && + 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 (num_dests == 0 || dests == NULL) + return (NULL); + + if (name == NULL) + { + /* + * NULL name for default printer. + */ + + while (num_dests > 0) + { + if (dests->is_default) + return (dests); + + num_dests --; + dests ++; + } + } + else + { + /* + * Lookup name and optionally the instance... + */ + + 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... + */ + + if ((home = getenv("CUPS_SERVERROOT")) != NULL) + { + snprintf(filename, sizeof(filename), "%s/lpoptions", home); + num_dests = cups_get_dests(filename, num_dests, dests); + } + else + 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... + */ + +#ifdef WIN32 + if ((home = getenv("CUPS_SERVERROOT")) == NULL) + home = CUPS_SERVERROOT; + + snprintf(filename, sizeof(filename), "%s/lpoptions", home); +#else + if (getuid() == 0) + { + if ((home = getenv("CUPS_SERVERROOT")) == NULL) + home = CUPS_SERVERROOT; + + snprintf(filename, sizeof(filename), "%s/lpoptions", home); + } + else if ((home = getenv("HOME")) != NULL) + snprintf(filename, sizeof(filename), "%s/.lpoptions", home); + else + return; +#endif /* WIN32 */ + + /* + * 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 ++) + if (option->value[0]) + fprintf(fp, " %s=%s", option->name, option->value); + else + fprintf(fp, " %s", option->name); + + 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 */ + const char *printer; /* PRINTER or LPDEST */ + + + /* + * Check environment variables... + */ + + if ((printer = getenv("LPDEST")) == NULL) + if ((printer = getenv("PRINTER")) != NULL) + if (strcmp(printer, "lp") == 0) + printer = NULL; + + /* + * 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... + */ + + if (dest->num_options) + { + /* + * Free old options... + */ + + cupsFreeOptions(dest->num_options, dest->options); + + dest->num_options = 0; + dest->options = (cups_option_t *)0; + } + + dest->num_options = cupsParseOptions(lineptr, dest->num_options, + &(dest->options)); + + /* + * Set this as default if needed... + */ + + if (strncasecmp(line, "default", 7) == 0 && printer == NULL) + { + 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..6e9f628ba3 --- /dev/null +++ b/cups/emit.c @@ -0,0 +1,336 @@ +/* + * "$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: + * + * ppdCollect() - Collect all marked options that reside in the specified + * ppdEmit() - Emit code for marked options to a file. + * ppdEmitFd() - Emit code for marked options to a file. + * ppd_sort() - Sort options by ordering numbers... + */ + +/* + * 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); + + +/* + * 'ppdCollect()' - Collect all marked options that reside in the specified + * section. + */ + +int /* O - Number of options marked */ +ppdCollect(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); + } +} + + +/* + * '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 = ppdCollect(ppd, section, &choices)) == 0) + return (0); + + for (i = 0; i < count; i ++) + if (section != PPD_ORDER_EXIT && section != PPD_ORDER_JCL) + { + /* + * Send wrapper commands to prevent printer errors for unsupported + * options... + */ + + if (fputs("[{\n", fp) < 0) + { + free(choices); + return (-1); + } + + /* + * 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); + } + + if (fputs("} stopped cleartomark\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 = ppdCollect(ppd, section, &choices)) == 0) + return (0); + + for (i = 0; i < count; i ++) + if (section != PPD_ORDER_EXIT && section != PPD_ORDER_JCL) + { + /* + * Send wrapper commands to prevent printer errors for unsupported + * options... + */ + + if (write(fd, "[{\n", 3) < 1) + { + free(choices); + return (-1); + } + + /* + * Send DSC comments with option... + */ + + snprintf(buf, sizeof(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); + } + + if (write(fd, "} stopped cleartomark\n", 22) < 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); +} + + +/* + * End of "$Id$". + */ diff --git a/cups/http.c b/cups/http.c new file mode 100644 index 0000000000..53badf6c88 --- /dev/null +++ b/cups/http.c @@ -0,0 +1,1970 @@ +/* + * "$Id$" + * + * HTTP routines for the Common UNIX Printing System (CUPS) scheduler. + * + * 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: + * + * 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. + * httpEncryption() - Set the required encryption on the link. + * 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. + * http_upgrade() - Force upgrade to TLS encryption. + */ + +/* + * 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__ */ + +#ifdef HAVE_LIBSSL +# include +# include +#endif /* HAVE_LIBSSL */ + + +/* + * 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); +static int http_upgrade(http_t *http); + + +/* + * 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) +{ +#ifdef HAVE_LIBSSL +# if defined(WIN32) || defined(__EMX__) +# else + struct timeval curtime; /* Current time in microseconds */ +# endif /* WIN32 || __EMX__ */ +#endif /* HAVE_LIBSSL */ + +#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__ */ + +#ifdef HAVE_LIBSSL + SSL_library_init(); + + /* + * Using the current time is a dubious random seed, but on some systems + * it is the best we can do (on others, this seed isn't even used...) + */ + +# if defined(WIN32) || defined(__EMX__) +# else + gettimeofday(&curtime, NULL); + RAND_seed(&curtime, sizeof(curtime)); +# endif /* WIN32 || __EMX__ */ +#endif /* HAVE_LIBSSL */ +} + + +/* + * '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 */ +{ +#ifdef HAVE_LIBSSL + SSL_CTX *context; /* Context for encryption */ + SSL *conn; /* Connection for encryption */ +#endif /* HAVE_LIBSSL */ + + + if (!http) + return; + +#ifdef HAVE_LIBSSL + if (http->tls) + { + conn = (SSL *)(http->tls); + context = SSL_get_SSL_CTX(conn); + + SSL_shutdown(conn); + SSL_CTX_free(context); + SSL_free(conn); + + http->tls = NULL; + } +#endif /* HAVE_LIBSSL */ + +#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 */ + + + if (host == NULL) + return (NULL); + + 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 */ + + /* + * Set the default encryption status... + */ + + if (port == 443) + http->encryption = HTTP_ENCRYPT_ALWAYS; + + /* + * Connect to the remote system... + */ + + if (httpReconnect(http)) + { + free(http); + return (NULL); + } + else + return (http); +} + + +/* + * 'httpEncryption()' - Set the required encryption on the link. + */ + +int /* O - -1 on error, 0 on success */ +httpEncryption(http_t *http, /* I - HTTP data */ + http_encryption_t e) /* I - New encryption preference */ +{ +#ifdef HAVE_LIBSSL + if (!http) + return (0); + + http->encryption = e; + + if ((http->encryption == HTTP_ENCRYPT_ALWAYS && !http->tls) || + (http->encryption == HTTP_ENCRYPT_NEVER && http->tls)) + return (httpReconnect(http)); + else if (http->encryption == HTTP_ENCRYPT_REQUIRED && !http->tls) + return (http_upgrade(http)); + else + return (0); +#else + if (e == HTTP_ENCRYPT_ALWAYS || e == HTTP_ENCRYPT_REQUIRED) + return (-1); + else + return (0); +#endif /* HAVE_LIBSSL */ +} + + +/* + * '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 */ +#ifdef HAVE_LIBSSL + SSL_CTX *context; /* Context for encryption */ + SSL *conn; /* Connection for encryption */ + + + if (http->tls) + { + conn = (SSL *)(http->tls); + context = SSL_get_SSL_CTX(conn); + + SSL_shutdown(conn); + SSL_CTX_free(context); + SSL_free(conn); + + http->tls = NULL; + } +#endif /* HAVE_LIBSSL */ + + /* + * 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; + +#ifdef HAVE_LIBSSL + if (http->encryption == HTTP_ENCRYPT_ALWAYS) + { + /* + * Always do encryption via SSL. + */ + + context = SSL_CTX_new(SSLv23_method()); + conn = SSL_new(context); + + SSL_set_fd(conn, http->fd); + if (SSL_connect(conn) != 1) + { + SSL_CTX_free(context); + SSL_free(conn); + +#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->tls = conn; + } + else if (http->encryption == HTTP_ENCRYPT_REQUIRED) + return (http_upgrade(http)); +#endif /* HAVE_LIBSSL */ + + 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... */ + const char *atsign, /* @ sign */ + *slash; /* Separator */ + + + if (uri == NULL || method == NULL || username == NULL || host == NULL || + port == NULL || resource == NULL) + return; + + /* + * Grab the method portion of the URI... + */ + + if (strncmp(uri, "//", 2) == 0) + { + /* + * Workaround for HP IPP client bug... + */ + + strcpy(method, "ipp"); + } + else + { + /* + * Standard URI with method... + */ + + 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 = 631; + + 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 usenname, if any... + */ + + while (*uri == '/') + uri ++; + + if ((slash = strchr(uri, '/')) == NULL) + slash = uri + strlen(uri); + + if ((atsign = strchr(uri, '@')) != NULL && atsign < slash) + { + /* + * Got a username:password combo... + */ + + for (ptr = username; + uri < atsign && ptr < (username + sizeof(username) - 1); + *ptr++ = *uri++); + + *ptr = '\0'; + + uri = atsign + 1; + } + else + username[0] = '\0'; + + /* + * Grab the hostname... + */ + + ptr = host; + while (*uri != ':' && *uri != '/' && *uri != '\0') + *ptr ++ = *uri ++; + + *ptr = '\0'; + + if (*uri != ':') + { + if (strcasecmp(method, "http") == 0) + *port = 80; + else if (strcasecmp(method, "https") == 0) + *port = 443; + else if (strcasecmp(method, "ipp") == 0) + *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'; +} + + +/* + * 'httpGetSubField()' - Get a sub-field value. + */ + +char * /* O - Value or NULL */ +httpGetSubField(http_t *http, /* I - HTTP data */ + http_field_t field, /* I - Field index */ + const char *name, /* I - Name of sub-field */ + char *value) /* O - Value string */ +{ + const char *fptr; /* Pointer into field */ + char temp[HTTP_MAX_VALUE], /* Temporary buffer for name */ + *ptr; /* Pointer into string buffer */ + + + if (http == NULL || + field < HTTP_FIELD_ACCEPT_LANGUAGE || + field > HTTP_FIELD_WWW_AUTHENTICATE || + name == NULL || value == NULL) + return (NULL); + + for (fptr = http->fields[field]; *fptr;) + { + /* + * Skip leading whitespace... + */ + + while (isspace(*fptr)); + fptr ++; + + if (*fptr == ',') + { + fptr ++; + continue; + } + + /* + * Get the sub-field name... + */ + + for (ptr = temp; + *fptr && *fptr != '=' && !isspace(*fptr) && ptr < (temp + sizeof(temp) - 1); + *ptr++ = *fptr++); + + *ptr = '\0'; + + /* + * Skip trailing chars up to the '='... + */ + + while (*fptr && *fptr != '=') + fptr ++; + + if (!*fptr) + break; + + /* + * Skip = and leading whitespace... + */ + + fptr ++; + + while (isspace(*fptr)); + fptr ++; + + if (*fptr == '\"') + { + /* + * Read quoted string... + */ + + for (ptr = value, fptr ++; + *fptr && *fptr != '\"' && ptr < (value + HTTP_MAX_VALUE - 1); + *ptr++ = *fptr++); + + *ptr = '\0'; + + while (*fptr && *fptr != '\"') + fptr ++; + + if (*fptr) + fptr ++; + } + else + { + /* + * Read unquoted string... + */ + + for (ptr = value; + *fptr && !isspace(*fptr) && *fptr != ',' && ptr < (value + HTTP_MAX_VALUE - 1); + *ptr++ = *fptr++); + + *ptr = '\0'; + + while (*fptr && !isspace(*fptr) && *fptr != ',') + fptr ++; + } + + /* + * See if this is the one... + */ + + if (strcmp(name, temp) == 0) + return (value); + } + + value[0] = '\0'; + + return (NULL); +} + + +/* + * '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 */ +{ + if (http == NULL || + field < HTTP_FIELD_ACCEPT_LANGUAGE || + field > HTTP_FIELD_WWW_AUTHENTICATE || + value == NULL) + return; + + 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); + } +#ifdef HAVE_LIBSSL + else if (http->tls) + bytes = SSL_read((SSL *)(http->tls), buffer, length); +#endif /* HAVE_LIBSSL */ + 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) + { +#ifdef HAVE_LIBSSL + if (http->tls) + bytes = SSL_write((SSL *)(http->tls), buffer, length); + else +#endif /* HAVE_LIBSSL */ + 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 && http->used < HTTP_MAX_BUFFER) + { + /* + * No newline; see if there is more data to be read... + */ + +#ifdef HAVE_LIBSSL + if (http->tls) + bytes = SSL_read((SSL *)(http->tls), bufend, + HTTP_MAX_BUFFER - http->used); + else +#endif /* HAVE_LIBSSL */ + bytes = recv(http->fd, bufend, HTTP_MAX_BUFFER - http->used, 0); + + if (bytes < 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->used < HTTP_MAX_BUFFER); + + 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) + { +#ifdef HAVE_LIBSSL + if (http->tls) + nbytes = SSL_write((SSL *)(http->tls), bufptr, bytes - tbytes); + else +#endif /* HAVE_LIBSSL */ + nbytes = send(http->fd, bufptr, bytes - tbytes, 0); + + if (nbytes < 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_CONTINUE : + return ("Continue"); + case HTTP_SWITCHING_PROTOCOLS : + return ("Switching Protocols"); + 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_UPGRADE_REQUIRED : + return ("Upgrade Required"); + 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); + snprintf(datetime, sizeof(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 */ +#ifdef HAVE_LIBSSL + SSL_CTX *context; /* Context for encryption */ + SSL *conn; /* Connection for encryption */ +#endif /* HAVE_LIBSSL */ + + + 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); + +#ifdef HAVE_LIBSSL + if (http->status == HTTP_SWITCHING_PROTOCOLS && !http->tls) + { + context = SSL_CTX_new(SSLv23_method()); + conn = SSL_new(context); + + SSL_set_fd(conn, http->fd); + if (SSL_connect(conn) != 1) + { + SSL_CTX_free(context); + SSL_free(conn); + +#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 (HTTP_ERROR); + } + + http->tls = conn; + + return (HTTP_CONTINUE); + } + else if (http->status == HTTP_UPGRADE_REQUIRED && + http->encryption != HTTP_ENCRYPT_NEVER) + http->encryption = HTTP_ENCRYPT_REQUIRED; +#endif /* HAVE_LIBSSL */ + + 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, (int *)&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; + +#ifdef HAVE_LIBSSL + if (http->encryption == HTTP_ENCRYPT_REQUIRED && !http->tls) + { + httpSetField(http, HTTP_FIELD_CONNECTION, "Upgrade"); + httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.0,SSL/2.0,SSL/3.0"); + } +#endif /* HAVE_LIBSSL */ + + 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); +} + + +#ifdef HAVE_LIBSSL +/* + * 'http_upgrade()' - Force upgrade to TLS encryption. + */ + +static int /* O - Status of connection */ +http_upgrade(http_t *http) /* I - HTTP data */ +{ + SSL_CTX *context; /* Context for encryption */ + SSL *conn; /* Connection for encryption */ + char buffer[1024]; /* Status from server... */ + + + /* + * Send an OPTIONS request to the server, requiring SSL or TLS + * encryption on the link... + */ + + if (httpPrintf(http, "OPTIONS * HTTP/1.1\r\n") < 0) + return (-1); + if (httpPrintf(http, "Host: %s\r\n", http->hostname) < 0) + return (-1); + if (httpPrintf(http, "Connection: upgrade\r\n") < 0) + return (-1); + if (httpPrintf(http, "Upgrade: TLS/1.0, SSL/2.0, SSL/3.0\r\n") < 0) + return (-1); + if (httpPrintf(http, "\r\n") < 0) + return (-1); + + /* + * Wait for the response data... + */ + + while (httpGets(buffer, sizeof(buffer), http) != NULL) + if (!buffer[0]) + break; + + context = SSL_CTX_new(SSLv23_method()); + conn = SSL_new(context); + + SSL_set_fd(conn, http->fd); + if (SSL_connect(conn) != 1) + { + SSL_CTX_free(context); + SSL_free(conn); + +#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->tls = conn; + + return (0); +} +#endif /* HAVE_LIBSSL */ + + +/* + * End of "$Id$". + */ diff --git a/cups/http.h b/cups/http.h new file mode 100644 index 0000000000..c0e271848a --- /dev/null +++ b/cups/http.h @@ -0,0 +1,342 @@ +/* + * "$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 encryption values... + */ + +typedef enum +{ + HTTP_ENCRYPT_IF_REQUESTED, /* Encrypt if requested (TLS upgrade) */ + HTTP_ENCRYPT_NEVER, /* Never encrypt */ + HTTP_ENCRYPT_REQUIRED, /* Encryption is required (TLS upgrade) */ + HTTP_ENCRYPT_ALWAYS /* Always encrypt (SSL) */ +} http_encryption_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_SWITCHING_PROTOCOLS, /* HTTP upgrade to TLS/SSL */ + + 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_UPGRADE_REQUIRED = 426, /* Upgrade to SSL/TLS required */ + + 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 */ + void *tls; /* TLS state information */ + http_encryption_t encryption; /* Encryption requirements */ +} http_t; + + +/* + * Prototypes... + */ + +# define httpBlocking(http,b) (http)->blocking = (b) +extern int httpCheck(http_t *http); +# define httpClearFields(http) memset((http)->fields, 0, sizeof((http)->fields)),\ + httpSetField((http), HTTP_FIELD_HOST, (http)->hostname) +extern void httpClose(http_t *http); +extern http_t *httpConnect(const char *host, int port); +extern int httpDelete(http_t *http, const char *uri); +extern int httpEncryption(http_t *http, http_encryption_t e); +# 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 char *httpGetSubField(http_t *http, http_field_t field, + const char *name, char *value); +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); +extern char *httpMD5(const char *, const char *, const char *, + char [33]); +extern char *httpMD5Final(const char *, const char *, const char *, + char [33]); +extern char *httpMD5String(const md5_byte_t *, char [33]); + + +/* + * 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..756cebda15 --- /dev/null +++ b/cups/ipp.c @@ -0,0 +1,1742 @@ +/* + * "$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. + * ippNew() - Allocate a new IPP request. + * ippPort() - Return the default IPP port number. + * ippRead() - Read data for an IPP request. + * ippSetPort() - Set the default port number. + * 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_free_attr() - Free an attribute. + * 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" +#include + + +/* + * Local globals... + */ + +static int ipp_port = 0; + + +/* + * 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(%p, %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(%p, %02x, \'%s\', %d, %p)\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(%p, %02x, \'%s\', %p)\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(%p, %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 = value ? strdup(value) : NULL; + + if ((type == IPP_TAG_LANGUAGE || type == IPP_TAG_CHARSET) && + attr->values[0].string.text) + { + /* + * Convert to lowercase and change _ to - as needed... + */ + + char *p; + + + for (p = attr->values[0].string.text; *p; p ++) + if (*p == '_') + *p = '-'; + else + *p = tolower(*p); + } + + 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(%p)\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 */ +{ + ipp_attribute_t *attr, /* Current attribute */ + *next; /* Next attribute */ + + + DEBUG_printf(("ippNew(): %p\n", ipp)); + + if (ipp == NULL) + return; + + for (attr = ipp->attrs; attr != NULL; attr = next) + { + next = attr->next; + _ipp_free_attr(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_ERROR : + 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)); + + default : + 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 */ + ipp_tag_t value_tag; /* Value tag */ + + + DEBUG_printf(("ippFindAttribute(%p, \'%s\')\n", ipp, name)); + + if (ipp == NULL || name == NULL) + return (NULL); + + for (attr = ipp->attrs; attr != NULL; attr = attr->next) + { + DEBUG_printf(("ippFindAttribute: attr = %p, name = \'%s\'\n", attr, + attr->name)); + + value_tag = attr->value_tag & ~IPP_TAG_COPY; + + if (attr->name != NULL && strcasecmp(attr->name, name) == 0 && + (value_tag == type || type == IPP_TAG_ZERO || + (value_tag == IPP_TAG_TEXTLANG && type == IPP_TAG_TEXT) || + (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 & ~IPP_TAG_COPY) + { + 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 += 4 * attr->num_values;/* Charset + text length */ + for (i = 0; i < attr->num_values; i ++) + bytes += strlen(attr->values[i].string.charset) + + strlen(attr->values[i].string.text); + break; + + default : + for (i = 0; i < attr->num_values; i ++) + bytes += attr->values[0].unknown.length; + 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; + } + + DEBUG_printf(("ippNew(): %p\n", temp)); + + 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 */ + *bufptr; /* Pointer into buffer */ + ipp_attribute_t *attr; /* Current attribute */ + ipp_tag_t tag; /* Current tag */ + + + DEBUG_printf(("ippRead(%p, %p)\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; + + DEBUG_printf(("ippRead: version=%d.%d\n", buffer[0], buffer[1])); + DEBUG_printf(("ippRead: op_status=%04x\n", ipp->request.any.op_status)); + DEBUG_printf(("ippRead: request_id=%d\n", ipp->request.any.request_id)); + + /* + * 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); + + bufptr = buffer; + + /* + * text-with-language and name-with-language are composite + * values: + * + * charset-length + * charset + * text-length + * text + */ + + n = (bufptr[0] << 8) | bufptr[1]; + + attr->values[attr->num_values].string.charset = calloc(n + 1, 1); + + memcpy(attr->values[attr->num_values].string.charset, + bufptr + 2, n); + + bufptr += 2 + n; + n = (bufptr[0] << 8) | bufptr[1]; + + attr->values[attr->num_values].string.text = calloc(n + 1, 1); + + memcpy(attr->values[attr->num_values].string.text, + bufptr + 2, n); + + break; + + default : /* Other unsupported values */ + attr->values[attr->num_values].unknown.length = n; + if (n > 0) + { + attr->values[attr->num_values].unknown.data = malloc(n); + if (ipp_read(http, attr->values[attr->num_values].unknown.data, n) < n) + return (IPP_ERROR); + } + else + attr->values[attr->num_values].unknown.data = NULL; + break; + } + + attr->num_values ++; + + /* + * If blocking is disabled, stop here... + */ + + if (!http->blocking && http->used == 0) + break; + } + break; + + case IPP_DATA : + break; + + default : + break; /* anti-compiler-warning-code */ + } + + 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; + + DEBUG_printf(("ippWrite: version=%d.%d\n", buffer[0], buffer[1])); + DEBUG_printf(("ippWrite: op_status=%04x\n", ipp->request.any.op_status)); + DEBUG_printf(("ippWrite: request_id=%d\n", ipp->request.any.request_id)); + + /* + * 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 & ~IPP_TAG_COPY) + { + 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) + + strlen(attr->values[i].string.text) + + 4; + + 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; + } + + /* Length of entire value */ + *bufptr++ = n >> 8; + *bufptr++ = n; + + /* Length of charset */ + n = strlen(attr->values[i].string.charset); + *bufptr++ = n >> 8; + *bufptr++ = n; + + /* Charset */ + memcpy(bufptr, attr->values[i].string.charset, n); + bufptr += n; + + /* Length of text */ + n = strlen(attr->values[i].string.text); + *bufptr++ = n >> 8; + *bufptr++ = n; + + /* Text */ + memcpy(bufptr, attr->values[i].string.text, n); + bufptr += n; + } + break; + + default : + 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 = attr->values[i].unknown.length; + + 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; + } + + /* Length of unknown value */ + *bufptr++ = n >> 8; + *bufptr++ = n; + + /* Value */ + if (n > 0) + { + memcpy(bufptr, attr->values[i].unknown.data, n); + bufptr += n; + } + } + break; + } + + /* + * Write the data out... + */ + + if (httpWrite(http, (char *)buffer, bufptr - buffer) < 0) + { + DEBUG_puts("ippWrite: Could not write IPP attribute..."); + return (IPP_ERROR); + } + + DEBUG_printf(("ippWrite: wrote %d bytes\n", bufptr - buffer)); + + /* + * If blocking is disabled, stop here... + */ + + if (!http->blocking) + break; + } + + if (ipp->current == NULL) + { + /* + * Done with all of the attributes; add the end-of-attributes tag... + */ + + buffer[0] = IPP_TAG_END; + if (httpWrite(http, (char *)buffer, 1) < 0) + { + DEBUG_puts("ippWrite: Could not write IPP end-tag..."); + return (IPP_ERROR); + } + + ipp->state = IPP_DATA; + } + break; + + case IPP_DATA : + break; + + default : + break; /* anti-compiler-warning-code */ + } + + 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 (ipp_port) + return (ipp_port); + else if ((server_port = getenv("IPP_PORT")) != NULL) + return (ipp_port = atoi(server_port)); + else if ((port = getservbyname("ipp", NULL)) == NULL) + return (ipp_port = IPP_PORT); + else + return (ipp_port = ntohs(port->s_port)); +} + + +/* + * 'ippSetPort()' - Set the default port number. + */ + +void +ippSetPort(int p) /* I - Port number to use */ +{ + ipp_port = p; +} + + +/* + * '_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(%p, %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; + + DEBUG_printf(("_ipp_add_attr(): %p\n", attr)); + + return (attr); +} + + +/* + * '_ipp_free_attr()' - Free an attribute. + */ + +void +_ipp_free_attr(ipp_attribute_t *attr) /* I - Attribute to free */ +{ + int i; /* Looping var */ + + + DEBUG_printf(("_ipp_free_attr(): %p\n", attr)); + + 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 && i == 0) + free(attr->values[i].string.charset); + free(attr->values[i].string.text); + } + break; + + default : + break; /* anti-compiler-warning-code */ + } + + if (attr->name != NULL) + free(attr->name); + + free(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..9cf755096e --- /dev/null +++ b/cups/ipp.h @@ -0,0 +1,363 @@ +/* + * "$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 "http.h" + + +/* + * 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_NOTSETTABLE = 0x15, + IPP_TAG_DELETEATTR, + IPP_TAG_ANYVALUE, + 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_COPY = 0x80000000 +} ipp_tag_t; + +typedef enum /**** Resolution units... ****/ +{ + IPP_RES_PER_INCH = 3, + IPP_RES_PER_CM +} ipp_res_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_SET_PRINTER_ATTRIBUTES, + IPP_SET_JOB_ATTRIBUTES, + IPP_GET_PRINTER_SUPPORTED_VALUES, + 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, + CUPS_MOVE_JOB +} 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_COMPRESSION_NOT_SUPPORTED, + IPP_COMPRESSION_ERROR, + IPP_DOCUMENT_FORMAT_ERROR, + IPP_DOCUMENT_ACCESS_ERROR, + IPP_INTERNAL_ERROR = 0x0500, + IPP_OPERATION_NOT_SUPPORTED, + IPP_SERVICE_UNAVAILABLE, + IPP_VERSION_NOT_SUPPORTED, + IPP_DEVICE_ERROR, + IPP_TEMPORARY_ERROR, + IPP_NOT_ACCEPTING, + IPP_PRINTER_BUSY, + IPP_ERROR_JOB_CANCELLED, + IPP_MULTIPLE_JOBS_NOT_SUPPORTED +} 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 */ + + struct + { + int length; /* Length of attribute */ + void *data; /* Data in attribute */ + } unknown; /* Unknown attribute type */ +} 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 void ippSetPort(int p); + +extern ipp_attribute_t *_ipp_add_attr(ipp_t *, int); +extern void _ipp_free_attr(ipp_attribute_t *); + + +/* + * 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..988f7a7ddc --- /dev/null +++ b/cups/language.c @@ -0,0 +1,407 @@ +/* + * "$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", + "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", + "utf-8", + "iso-8859-13", + "iso-8859-14", + "iso-8859-15", + "windows-874", + "windows-1250", + "windows-1251", + "windows-1252", + "windows-1253", + "windows-1254", + "windows-1255", + "windows-1256", + "windows-1257", + "windows-1258" + }; +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) + { + strncpy(line, lang_default[0], sizeof(line) - 1); + line[sizeof(line) - 1] = '\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 ++; + strncpy(lang->language, langname, sizeof(lang->language) - 1); + lang->language[sizeof(lang->language) - 1] = '\0'; + + 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; + + strncpy(line, lang_default[count], sizeof(line) - 1); + /* Already set last byte to 0 above... */ + } + 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..76a14a41c3 --- /dev/null +++ b/cups/language.h @@ -0,0 +1,222 @@ +/* + * "$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_ISO8859_13, + CUPS_ISO8859_14, + CUPS_ISO8859_15, + CUPS_WINDOWS_874, + CUPS_WINDOWS_1250, + CUPS_WINDOWS_1251, + CUPS_WINDOWS_1252, + CUPS_WINDOWS_1253, + CUPS_WINDOWS_1254, + CUPS_WINDOWS_1255, + CUPS_WINDOWS_1256, + CUPS_WINDOWS_1257, + CUPS_WINDOWS_1258 +} 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..94be9ebfac --- /dev/null +++ b/cups/mark.c @@ -0,0 +1,441 @@ +/* + * "$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" +#include "debug.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 || + strcasecmp(c1->choice, "Off") == 0 || + strcasecmp(c1->choice, "False") == 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 || + strcasecmp(c2->choice, "Off") == 0 || + strcasecmp(c2->choice, "False") == 0) + c2 = NULL; + } + + /* + * If both options are marked then there is a conflict... + */ + + if (c1 != NULL && c1->marked && + c2 != NULL && c2->marked) + { + DEBUG_printf(("%s->%s conflicts with %s->%s (%s %s %s %s)\n", + o1->keyword, c1->choice, o2->keyword, c2->choice, + c->option1, c->choice1, c->option2, c->choice2)); + 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; + } + } + else if (strcasecmp(option, "InputSlot") == 0) + { + /* + * Unmark ManualFeed option... + */ + + if ((o = ppdFindOption(ppd, "ManualFeed")) != NULL) + for (i = 0; i < o->num_choices; i ++) + o->choices[i].marked = 0; + } + else if (strcasecmp(option, "ManualFeed") == 0) + { + /* + * Unmark InputSlot option... + */ + + if ((o = ppdFindOption(ppd, "InputSlot")) != 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..5db868858e --- /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" +#include "string.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. + */ +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/md5passwd.c b/cups/md5passwd.c new file mode 100644 index 0000000000..bf63460cce --- /dev/null +++ b/cups/md5passwd.c @@ -0,0 +1,148 @@ +/* + * "$Id$" + * + * MD5 password 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: + * + * httpMD5() - Compute the MD5 sum of the username:group:password. + * httpMD5Nonce() - Combine the MD5 sum of the username, group, and password + * with the server-supplied nonce value. + * httpMD5String() - Convert an MD5 sum to a character string. + */ + +/* + * Include necessary headers... + */ + +#include "http.h" +#include "string.h" + + +/* + * 'httpMD5()' - Compute the MD5 sum of the username:group:password. + */ + +char * /* O - MD5 sum */ +httpMD5(const char *username, /* I - User name */ + const char *realm, /* I - Realm name */ + const char *passwd, /* I - Password string */ + char md5[33]) /* O - MD5 string */ +{ + md5_state_t state; /* MD5 state info */ + md5_byte_t sum[16]; /* Sum data */ + char line[256]; /* Line to sum */ + + + /* + * Compute the MD5 sum of the user name, group name, and password. + */ + + snprintf(line, sizeof(line), "%s:%s:%s", username, realm, passwd); + md5_init(&state); + md5_append(&state, (md5_byte_t *)line, strlen(line)); + md5_finish(&state, sum); + + /* + * Return the sum... + */ + + return (httpMD5String(sum, md5)); +} + + +/* + * 'httpMD5Final()' - Combine the MD5 sum of the username, group, and password + * with the server-supplied nonce value, method, and + * request-uri. + */ + +char * /* O - New sum */ +httpMD5Final(const char *nonce, /* I - Server nonce value */ + const char *method, /* I - METHOD (GET, POST, etc.) */ + const char *resource, /* I - Resource path */ + char md5[33]) /* IO - MD5 sum */ +{ + md5_state_t state; /* MD5 state info */ + md5_byte_t sum[16]; /* Sum data */ + char line[1024]; /* Line of data */ + char a2[33]; /* Hash of method and resource */ + + + /* + * First compute the MD5 sum of the method and resource... + */ + + snprintf(line, sizeof(line), "%s:%s", method, resource); + md5_init(&state); + md5_append(&state, (md5_byte_t *)line, strlen(line)); + md5_finish(&state, sum); + httpMD5String(sum, a2); + + /* + * Then combine A1 (MD5 of username, realm, and password) with the nonce + * and A2 (method + resource) values to get the final MD5 sum for the + * request... + */ + + snprintf(line, sizeof(line), "%s%s:%s", md5, nonce, a2); + + md5_init(&state); + md5_append(&state, (md5_byte_t *)line, strlen(line)); + md5_finish(&state, sum); + + return (httpMD5String(sum, md5)); +} + + +/* + * 'httpMD5String()' - Convert an MD5 sum to a character string. + */ + +char * /* O - MD5 sum in hex */ +httpMD5String(const md5_byte_t *sum, /* I - MD5 sum data */ + char md5[33]) /* O - MD5 sum in hex */ +{ + int i; /* Looping var */ + char *md5ptr; /* Pointer into MD5 string */ + static char *hex = "0123456789abcdef"; + /* Hex digits */ + + + /* + * Convert the MD5 sum to hexadecimal... + */ + + for (i = 16, md5ptr = md5; i > 0; i --, sum ++) + { + *md5ptr++ = hex[*sum >> 4]; + *md5ptr++ = hex[*sum & 15]; + } + + *md5ptr = '\0'; + + return (md5); +} + + +/* + * End of "$Id$". + */ diff --git a/cups/options.c b/cups/options.c new file mode 100644 index 0000000000..bb9b276b0c --- /dev/null +++ b/cups/options.c @@ -0,0 +1,665 @@ +/* + * "$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. + * cupsEncodeOptions() - Encode printer options into IPP attributes. + * 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" +#include "debug.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); +} + + +/* + * 'cupsEncodeOptions()' - Encode printer options into IPP attributes. + */ + +void +cupsEncodeOptions(ipp_t *ipp, /* I - Request to add to */ + int num_options, /* I - Number of options */ + cups_option_t *options) /* I - Options */ +{ + int i, j; /* Looping vars */ + int count; /* Number of values */ + int n; /* Attribute value */ + char *s, /* Pointer into option value */ + *val, /* Pointer to option value */ + *copy, /* Copy of option value */ + *sep; /* Option separator */ + ipp_attribute_t *attr; /* IPP job-id attribute */ + + + DEBUG_printf(("cupsEncodeOptions(%p, %d, %p)\n", ipp, num_options, options)); + + if (ipp == NULL || num_options < 1 || options == NULL) + return; + + /* + * Handle the document format stuff first... + */ + + if ((val = (char *)cupsGetOption("document-format", num_options, options)) != NULL) + ippAddString(ipp, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format", + NULL, val); + else if (cupsGetOption("raw", num_options, options)) + ippAddString(ipp, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format", + NULL, "application/vnd.cups-raw"); + else + ippAddString(ipp, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format", + NULL, "application/octet-stream"); + + /* + * Then add all other options... + */ + + for (i = 0; i < num_options; i ++) + { + /* + * Skip document format options - handled above... + */ + + if (strcasecmp(options[i].name, "raw") == 0 || + strcasecmp(options[i].name, "document-format") == 0) + continue; + + /* + * Count the number of values... + */ + + for (count = 1, sep = options[i].value; + (sep = strchr(sep + 1, ',')) != NULL; + count ++); + + DEBUG_printf(("cupsEncodeOptions: option = \'%s\', count = %d\n", + options[i].name, count)); + + if ((attr = _ipp_add_attr(ipp, count)) == NULL) + { + /* + * Ran out of memory! + */ + + DEBUG_puts("cupsEncodeOptions: Ran out of memory for attributes!"); + return; + } + + attr->group_tag = IPP_TAG_JOB; + + if ((attr->name = strdup(options[i].name)) == NULL) + { + /* + * Ran out of memory! + */ + + DEBUG_puts("cupsEncodeOptions: Ran out of memory for name!"); + return; + } + + if (count > 1) + { + /* + * Make a copy of the value we can fiddle with... + */ + + if ((copy = strdup(options[i].value)) == NULL) + { + /* + * Ran out of memory! + */ + + DEBUG_puts("cupsEncodeOptions: Ran out of memory for value copy!"); + return; + } + + val = copy; + } + else + { + /* + * Since we have a single value, use the value directly... + */ + + val = options[i].value; + copy = NULL; + } + + /* + * 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, option=MxN, and option=val1,val2,...,valN. + */ + + if (*val == '\0') + { + /* + * Old-style System V boolean value... + */ + + attr->value_tag = IPP_TAG_BOOLEAN; + + if (strncasecmp(attr->name, "no", 2) == 0) + { + DEBUG_puts("cupsEncodeOptions: Added boolean false value..."); + strcpy(attr->name, attr->name + 2); + attr->values[0].boolean = 0; + } + else + { + DEBUG_puts("cupsEncodeOptions: Added boolean true value..."); + attr->values[0].boolean = 1; + } + } + else + { + /* + * Scan the value string for values... + */ + + for (j = 0; *val != '\0'; val = sep, j ++) + { + /* + * Find the end of this value and mark it if needed... + */ + + if ((sep = strchr(val, ',')) != NULL) + *sep++ = '\0'; + else + sep = val + strlen(val); + + /* + * See what kind of value it is... + */ + + if (strcasecmp(val, "true") == 0 || + strcasecmp(val, "on") == 0 || + strcasecmp(val, "yes") == 0) + { + /* + * Boolean value - true... + */ + + attr->value_tag = IPP_TAG_BOOLEAN; + attr->values[j].boolean = 1; + + DEBUG_puts("cupsEncodeOptions: Added boolean true value..."); + } + else if (strcasecmp(val, "false") == 0 || + strcasecmp(val, "off") == 0 || + strcasecmp(val, "no") == 0) + { + /* + * Boolean value - false... + */ + + attr->value_tag = IPP_TAG_BOOLEAN; + attr->values[j].boolean = 0; + + DEBUG_puts("cupsEncodeOptions: Added boolean false value..."); + } + else + { + /* + * Number, range, resolution, or string... + */ + + n = strtol(val, &s, 0); + + if (*s != '\0' && *s != '-' && (*s != 'x' || s == val)) + { + /* + * String value(s)... + */ + + if ((attr->values[j].string.text = strdup(val)) == NULL) + { + /* + * Ran out of memory! + */ + + DEBUG_puts("cupsEncodeOptions: Ran out of memory for string!"); + return; + } + + attr->value_tag = IPP_TAG_NAME; + + DEBUG_printf(("cupsEncodeOptions: Added string value \'%s\'...\n", val)); + } + else if (*s == '-') + { + attr->value_tag = IPP_TAG_RANGE; + attr->values[j].range.lower = n; + attr->values[j].range.upper = strtol(s + 1, NULL, 0); + + DEBUG_printf(("cupsEncodeOptions: Added range option value %d-%d...\n", + n, attr->values[j].range.upper)); + } + else if (*s == 'x') + { + attr->value_tag = IPP_TAG_RESOLUTION; + attr->values[j].resolution.xres = n; + attr->values[j].resolution.yres = strtol(s + 1, &s, 0); + + if (strcasecmp(s, "dpc") == 0) + attr->values[j].resolution.units = IPP_RES_PER_CM; + else if (strcasecmp(s, "dpi") == 0) + attr->values[j].resolution.units = IPP_RES_PER_INCH; + else + { + if ((attr->values[j].string.text = strdup(val)) == NULL) + { + /* + * Ran out of memory! + */ + + DEBUG_puts("cupsEncodeOptions: Ran out of memory for string!"); + return; + } + + attr->value_tag = IPP_TAG_NAME; + + DEBUG_printf(("cupsEncodeOptions: Added string value \'%s\'...\n", val)); + continue; + } + + DEBUG_printf(("cupsEncodeOptions: Adding resolution option value %s...\n", + val)); + } + else + { + attr->value_tag = IPP_TAG_INTEGER; + attr->values[j].integer = n; + + DEBUG_printf(("cupsEncodeOptions: Adding integer option value %d...\n", n)); + } + } + } + } + } +} + + +/* + * '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; + + /* + * Skip leading spaces... + */ + + while (isspace(*ptr)) + ptr ++; + + /* + * Loop through the string... + */ + + 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 (strcasecmp(options->name, "output-bin") == 0) + { + if (ppdMarkOption(ppd, "OutputBin", options->value)) + 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..432759d614 --- /dev/null +++ b/cups/ppd.c @@ -0,0 +1,1904 @@ +/* + * "$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 */ + char **filter; /* Current filter */ + + + /* + * Range check the PPD file record... + */ + + if (ppd == NULL) + return; + + /* + * Free all strings at the top level... + */ + + safe_free(ppd->patches); + safe_free(ppd->jcl_begin); + safe_free(ppd->jcl_ps); + safe_free(ppd->jcl_end); + 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 filters... + */ + + if (ppd->num_filters > 0) + { + for (i = ppd->num_filters, filter = ppd->filters; i > 0; i --, filter ++) + safe_free(*filter); + + safe_free(ppd->filters); + } + + /* + * 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, "cupsFlipDuplex") == 0) + ppd->flip_duplex = strcmp(string, "True") == 0; + 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, "Font") == 0) + { + /* + * Add this font to the list of available fonts... + */ + + if (ppd->num_fonts == 0) + ppd->fonts = (char **)malloc(sizeof(char *)); + else + ppd->fonts = (char **)realloc(ppd->fonts, + sizeof(char *) * (ppd->num_fonts + 1)); + + if (ppd->fonts == NULL) + { + ppdClose(ppd); + return (NULL); + } + + ppd->fonts[ppd->num_fonts] = strdup(name); + ppd->num_fonts ++; + } + 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 ((option = ppdFindOption(ppd, "PageSize")) == NULL) + { + ppd_group_t *temp; + + + if ((temp = ppd_get_group(ppd, + cupsLangString(language, + CUPS_MSG_GENERAL))) == NULL) + { + ppdClose(ppd); + safe_free(string); + return (NULL); + } + + if ((option = ppd_get_option(temp, "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); + 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 ((option = ppdFindOption(ppd, "PageSize")) == NULL) + { + ppd_group_t *temp; + + + if ((temp = ppd_get_group(ppd, + cupsLangString(language, + CUPS_MSG_GENERAL))) == NULL) + { + DEBUG_puts("Unable to get general group!"); + ppdClose(ppd); + safe_free(string); + return (NULL); + } + + if ((option = ppd_get_option(temp, "PageSize")) == NULL) + { + DEBUG_puts("Unable to get PageSize option!"); + ppdClose(ppd); + safe_free(string); + return (NULL); + } + } + + if ((choice = ppd_add_choice(option, "Custom")) == NULL) + { + DEBUG_puts("Unable to add Custom choice!"); + ppdClose(ppd); + safe_free(string); + return (NULL); + } + + strncpy(choice->text, cupsLangString(language, CUPS_MSG_VARIABLE), + sizeof(choice->text) - 1); + option = NULL; + } + + if ((option = ppdFindOption(ppd, "PageSize")) == NULL) + { + DEBUG_puts("Unable to find PageSize option!"); + ppdClose(ppd); + safe_free(string); + return (NULL); + } + + if ((choice = ppdFindChoice(option, "Custom")) == NULL) + { + DEBUG_puts("Unable to find Custom choice!"); + 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, "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) + { + ppd_group_t *temp; + + + /* + * Only valid for Non-UI options... + */ + + for (i = ppd->num_groups, temp = ppd->groups; i > 0; i --, temp ++) + if (temp->text[0] == '\0') + break; + + if (i > 0) + for (i = 0; i < temp->num_options; i ++) + if (strcmp(keyword, temp->options[i].keyword) == 0) + { + temp->options[i].section = section; + temp->options[i].order = order; + break; + } + } + 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) + { + ppd_group_t *temp; + + + /* + * Only valid for Non-UI options... + */ + + for (i = ppd->num_groups, temp = ppd->groups; i > 0; i --, temp ++) + if (temp->text[0] == '\0') + break; + + if (i > 0) + for (i = 0; i < temp->num_options; i ++) + if (strcmp(keyword, temp->options[i].keyword) == 0) + { + strncpy(temp->options[i].defchoice, string, + sizeof(temp->options[i].defchoice) - 1); + break; + } + } + 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)) + { + DEBUG_printf(("group = %p, subgroup = %p\n", group, subgroup)); + + 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[65536]; /* Line buffer (64k) */ + + + /* + * Range check everything... + */ + + if (fp == NULL || keyword == NULL || option == NULL || text == NULL || + string == NULL) + return (0); + + /* + * Now loop until we have a valid line... + */ + + *string = NULL; + + 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); + } + + ch = '\n'; + + if (!endquote) /* Continue for multi-line text */ + break; + + *lineptr++ = '\n'; + } + else + { + /* + * Any other character... + */ + + *lineptr++ = ch; + + if (ch == '\"') + { + endquote = !endquote; + + if (!endquote) + { + /* + * End of quoted string; ignore trailing characters... + */ + + while ((ch = getc(fp)) != EOF) + if (ch == '\n') + break; + else if (ch == '\r') + { + ch = getc(fp); + if (ch != '\n') + ungetc(ch, fp); + break; + } + + break; + } + } + } + } + + if (endquote) + { + /* + * Didn't finish this quoted string... + */ + + while ((ch = getc(fp)) != EOF) + if (ch == '\"') + break; + } + + if (ch != '\n') + { + /* + * Didn't finish this line... + */ + + while ((ch = getc(fp)) != EOF) + if (ch == '\r' || ch == '\n') + { + /* + * Line feed or carriage return... + */ + + if (ch == '\r') + { + /* + * Check for a trailing line feed... + */ + + if ((ch = getc(fp)) == EOF) + break; + if (ch != 0x0a) + ungetc(ch, fp); + } + + break; + } + } + + 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..26dd4059bd --- /dev/null +++ b/cups/ppd.h @@ -0,0 +1,243 @@ +/* + * "$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... */ + int flip_duplex; /* 1 = Flip page for back sides */ +} ppd_file_t; + + +/* + * Prototypes... + */ + +extern void ppdClose(ppd_file_t *ppd); +extern int ppdCollect(ppd_file_t *ppd, ppd_section_t section, + ppd_choice_t ***choices); +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..a800feb51a --- /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 */ + long 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 %ld bytes, %ld 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..f7a7ccec28 --- /dev/null +++ b/cups/testppd.c @@ -0,0 +1,198 @@ +/* + * "$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; /* 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'); + } + } + } + } + + printf(" num_profiles = %d\n", ppd->num_profiles); + for (j = 0; j < ppd->num_profiles; j ++) + printf(" profiles[%d] = %s/%s %.3f %.3f [ %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f ]\n", + j, ppd->profiles[j].resolution, ppd->profiles[j].media_type, + ppd->profiles[j].gamma, ppd->profiles[j].density, + ppd->profiles[j].matrix[0][0], ppd->profiles[j].matrix[0][1], + ppd->profiles[j].matrix[0][2], ppd->profiles[j].matrix[1][0], + ppd->profiles[j].matrix[1][1], ppd->profiles[j].matrix[1][2], + ppd->profiles[j].matrix[2][0], ppd->profiles[j].matrix[2][1], + ppd->profiles[j].matrix[2][2]); + + printf(" num_fonts = %d\n", ppd->num_fonts); + for (j = 0; j < ppd->num_fonts; j ++) + printf(" fonts[%d] = %s\n", j, ppd->fonts[j]); + + 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..3fb9fa0545 --- /dev/null +++ b/cups/usersys.c @@ -0,0 +1,411 @@ +/* + * "$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: + * + * cupsEncryption() - Get the default encryption settings... + * cupsGetPassword() - Get a password from the user... + * cupsServer() - Return the hostname of the default server... + * cupsSetEncryption() - Set the encryption preference. + * cupsSetPasswordCB() - Set the password callback for CUPS. + * cupsSetServer() - Set the default server name... + * cupsSetUser() - Set the default user name... + * cupsUser() - Return the current users name. + * cups_get_password() - Get a password from the user... + */ + +/* + * Include necessary headers... + */ + +#include "cups.h" +#include "string.h" +#include +#include + + +/* + * Local functions... + */ + +static const char *cups_get_password(const char *prompt); + + +/* + * Local globals... + */ + +static http_encryption_t cups_encryption = (http_encryption_t)-1; +static char cups_user[65] = "", + cups_server[256] = ""; +static const char *(*cups_pwdcb)(const char *) = cups_get_password; + + +/* + * 'cupsEncryption()' - Get the default encryption settings... + */ + +http_encryption_t +cupsEncryption(void) +{ + FILE *fp; /* client.conf file */ + char *encryption; /* CUPS_ENCRYPTION variable */ + const char *home; /* Home directory of user */ + static char line[1024]; /* Line from file */ + + + /* + * First see if we have already set the encryption stuff... + */ + + if (cups_encryption == (http_encryption_t)-1) + { + /* + * Then see if the CUPS_ENCRYPTION environment variable is set... + */ + + if ((encryption = getenv("CUPS_ENCRYPTION")) == NULL) + { + /* + * Next check to see if we have a $HOME/.cupsrc or client.conf file... + */ + + if ((home = getenv("HOME")) != NULL) + { + snprintf(line, sizeof(line), "%s/.cupsrc", home); + fp = fopen(line, "r"); + } + else + fp = NULL; + + if (fp == NULL) + { + if ((home = getenv("CUPS_SERVERROOT")) != NULL) + { + snprintf(line, sizeof(line), "%s/client.conf", home); + fp = fopen(line, "r"); + } + else + fp = fopen(CUPS_SERVERROOT "/client.conf", "r"); + } + + encryption = "IfRequested"; + + if (fp != NULL) + { + /* + * Read the config file and look for a ServerName line... + */ + + while (fgets(line, sizeof(line), fp) != NULL) + if (strncmp(line, "Encryption ", 11) == 0) + { + /* + * Got it! Drop any trailing newline and find the name... + */ + + encryption = line + strlen(line) - 1; + if (*encryption == '\n') + *encryption = '\0'; + + for (encryption = line + 11; isspace(*encryption); encryption ++); + break; + } + + fclose(fp); + } + } + + /* + * Set the encryption preference... + */ + + if (strcasecmp(encryption, "never") == 0) + cups_encryption = HTTP_ENCRYPT_NEVER; + else if (strcasecmp(encryption, "always") == 0) + cups_encryption = HTTP_ENCRYPT_ALWAYS; + else if (strcasecmp(encryption, "required") == 0) + cups_encryption = HTTP_ENCRYPT_REQUIRED; + else + cups_encryption = HTTP_ENCRYPT_IF_REQUESTED; + } + + return (cups_encryption); +} + + +/* + * 'cupsGetPassword()' - Get a password from the user... + */ + +const char * /* O - Password */ +cupsGetPassword(const char *prompt) /* I - Prompt string */ +{ + return ((*cups_pwdcb)(prompt)); +} + + +/* + * 'cupsSetEncryption()' - Set the encryption preference. + */ + +void +cupsSetEncryption(http_encryption_t e) /* I - New encryption preference */ +{ + cups_encryption = e; +} + + +/* + * 'cupsServer()' - Return the hostname of the default server... + */ + +const char * /* O - Server name */ +cupsServer(void) +{ + FILE *fp; /* client.conf file */ + char *server; /* Pointer to server name */ + const char *home; /* Home directory of user */ + static char line[1024]; /* Line from file */ + + + /* + * First see if we have already set the server name... + */ + + if (!cups_server[0]) + { + /* + * Then see if the CUPS_SERVER environment variable is set... + */ + + if ((server = getenv("CUPS_SERVER")) == NULL) + { + /* + * Next check to see if we have a $HOME/.cupsrc or client.conf file... + */ + + if ((home = getenv("HOME")) != NULL) + { + snprintf(line, sizeof(line), "%s/.cupsrc", home); + fp = fopen(line, "r"); + } + else + fp = NULL; + + if (fp == NULL) + { + if ((home = getenv("CUPS_SERVERROOT")) != NULL) + { + snprintf(line, sizeof(line), "%s/client.conf", home); + fp = fopen(line, "r"); + } + else + fp = fopen(CUPS_SERVERROOT "/client.conf", "r"); + } + + server = "localhost"; + + if (fp != NULL) + { + /* + * Read the config 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 ++); + break; + } + + fclose(fp); + } + } + + /* + * Copy the server name over... + */ + + strncpy(cups_server, server, sizeof(cups_server) - 1); + cups_server[sizeof(cups_server) - 1] = '\0'; + } + + return (cups_server); +} + + +/* + * 'cupsSetPasswordCB()' - Set the password callback for CUPS. + */ + +void +cupsSetPasswordCB(const char *(*cb)(const char *)) /* I - Callback function */ +{ + if (cb == (const char *(*)(const char *))0) + cups_pwdcb = cups_get_password; + else + cups_pwdcb = cb; +} + + +/* + * 'cupsSetServer()' - Set the default server name... + */ + +void +cupsSetServer(const char *server) /* I - Server name */ +{ + if (server) + { + strncpy(cups_server, server, sizeof(cups_server) - 1); + cups_server[sizeof(cups_server) - 1] = '\0'; + } + else + cups_server[0] = '\0'; +} + + +/* + * 'cupsSetUser()' - Set the default user name... + */ + +void +cupsSetUser(const char *user) /* I - User name */ +{ + if (user) + { + strncpy(cups_user, user, sizeof(cups_user) - 1); + cups_user[sizeof(cups_user) - 1] = '\0'; + } + else + cups_user[0] = '\0'; +} + + +#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) +{ + if (!cups_user[0]) + strcpy(cups_user, "WindowsUser"); + + return (cups_user); +} + + +/* + * 'cups_get_password()' - Get a password from the user... + */ + +static const char * /* O - Password */ +cups_get_password(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 */ + + + if (!cups_user[0]) + { + /* + * Rewind the password file... + */ + + setpwent(); + + /* + * Lookup the password entry for the current user. + */ + + if ((pwd = getpwuid(getuid())) == NULL) + strcpy(cups_user, "unknown"); /* Unknown user! */ + else + { + /* + * Copy the username... + */ + + setpwent(); + + strncpy(cups_user, pwd->pw_name, sizeof(cups_user) - 1); + cups_user[sizeof(cups_user) - 1] = '\0'; + } + + /* + * Rewind the password file again... + */ + + setpwent(); + } + + return (cups_user); +} + + +/* + * 'cups_get_password()' - Get a password from the user... + */ + +static const char * /* O - Password */ +cups_get_password(const char *prompt) /* I - Prompt string */ +{ + return (getpass(prompt)); +} +#endif /* WIN32 || __EMX__ */ + + +/* + * End of "$Id$". + */ diff --git a/cups/util.c b/cups/util.c new file mode 100644 index 0000000000..f1fa7af45c --- /dev/null +++ b/cups/util.c @@ -0,0 +1,1507 @@ +/* + * "$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. + * cupsLastError() - Return the last IPP error that occurred. + * cupsPrintFile() - Print a file to a printer or class. + * cupsPrintFiles() - Print one or more files to a printer or class. + * cupsTempFile() - Generate a temporary filename. + * 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 +#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[1024] = ""; /* 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 realm[HTTP_MAX_VALUE], /* realm="xyz" string */ + nonce[HTTP_MAX_VALUE], /* nonce="xyz" string */ + plain[255], /* Plaintext username:password */ + encode[255]; /* Encoded username:password */ + char prompt[1024]; /* Prompt string */ + + + if (http == NULL || request == NULL || resource == NULL) + { + if (request != NULL) + ippDelete(request); + + last_error = IPP_INTERNAL_ERROR; + return (NULL); + } + + DEBUG_printf(("cupsDoFileRequest(%p, %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); + } + } + else + file = NULL; + + /* + * Loop until we can send the request without authorization problems. + */ + + response = NULL; + status = HTTP_ERROR; + + 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... + */ + + snprintf(prompt, sizeof(prompt), "Password for %s on %s? ", cupsUser(), + http->hostname); + + if ((password = cupsGetPassword(prompt)) != NULL) + { + /* + * Got a password; send it to the server... + */ + + if (!password[0]) + break; + + if (strncmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Basic", 5) == 0) + { + /* + * Basic authentication... + */ + + snprintf(plain, sizeof(plain), "%s:%s", cupsUser(), password); + httpEncode64(encode, plain); + snprintf(authstring, sizeof(authstring), "Basic %s", encode); + } + else + { + /* + * Digest authentication... + */ + + httpGetSubField(http, HTTP_FIELD_WWW_AUTHENTICATE, "realm", realm); + httpGetSubField(http, HTTP_FIELD_WWW_AUTHENTICATE, "nonce", nonce); + + httpMD5(cupsUser(), realm, password, encode); + httpMD5Final(nonce, "POST", resource, encode); + snprintf(authstring, sizeof(authstring), + "Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", " + "response=\"%s\"", cupsUser(), realm, nonce, 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 */ + + + if (classes == NULL) + { + last_error = IPP_INTERNAL_ERROR; + return (0); + } + + /* + * 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 + * requested-attributes + */ + + 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); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, + "requested-attributes", NULL, "printer-name"); + + /* + * 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) +{ + FILE *fp; /* cupsd.conf file */ + char *printer; /* Pointer to server name */ + char line[1024]; /* Line from file */ + 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[256];/* 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); + + /* + * Next check to see if we have a client.conf file... + */ + + if ((var = getenv("CUPS_SERVERROOT")) == NULL) + var = CUPS_SERVERROOT; + + snprintf(line, sizeof(line), "%s/client.conf", var); + + if ((fp = fopen(line, "r")) != NULL) + { + /* + * Read the client.conf file and look for a DefaultPrinter line... + */ + + while (fgets(line, sizeof(line), fp) != NULL) + if (strncmp(line, "DefaultPrinter ", 15) == 0) + { + /* + * Got it! Drop any trailing newline and find the name... + */ + + printer = line + strlen(line) - 1; + if (*printer == '\n') + *printer = '\0'; + + for (printer = line + 15; isspace(*printer); printer ++); + + if (*printer) + { + strncpy(def_printer, printer, sizeof(def_printer) - 1); + def_printer[sizeof(def_printer) - 1] = '\0'; + + fclose(fp); + + return (def_printer); + } + } + + fclose(fp); + } + + /* + * 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 */ +{ + int i; /* Looping var */ + ipp_t *request, /* IPP request */ + *response; /* IPP response */ + ipp_attribute_t *attr; /* Current attribute */ + cups_lang_t *language; /* Local language */ + FILE *fp; /* PPD file */ + int bytes; /* Number of bytes read */ + char buffer[8192]; /* Buffer for file */ + char printer[HTTP_MAX_URI], /* Printer name */ + method[HTTP_MAX_URI], /* Method/scheme name */ + username[HTTP_MAX_URI], /* Username:password */ + hostname[HTTP_MAX_URI], /* Hostname */ + resource[HTTP_MAX_URI]; /* Resource name */ + int port; /* Port number */ + const char *password; /* Password string */ + char realm[HTTP_MAX_VALUE], /* realm="xyz" string */ + nonce[HTTP_MAX_VALUE], /* nonce="xyz" string */ + plain[255], /* Plaintext username:password */ + encode[255]; /* Encoded username:password */ + http_status_t status; /* HTTP status from server */ + char prompt[1024]; /* Prompt string */ + static char filename[HTTP_MAX_URI]; /* Local filename */ + static const char *requested_attrs[] =/* Requested attributes */ + { + "printer-uri-supported", + "printer-type", + "member-uris" + }; + + + if (name == NULL) + { + last_error = IPP_INTERNAL_ERROR; + return (NULL); + } + + /* + * See if we can connect to the server... + */ + + if (!cups_connect(name, printer, hostname)) + { + last_error = IPP_SERVICE_UNAVAILABLE; + return (NULL); + } + + /* + * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + * requested-attributes + */ + + 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); + + snprintf(buffer, sizeof(buffer), "ipp://localhost/printers/%s", name); + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, + "printer-uri", NULL, buffer); + + ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME, + "requested-attributes", + sizeof(requested_attrs) / sizeof(requested_attrs[0]), + NULL, requested_attrs); + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoRequest(cups_server, request, "/")) != NULL) + { + last_error = response->request.status.status_code; + printer[0] = '\0'; + hostname[0] = '\0'; + + if ((attr = ippFindAttribute(response, "member-uris", IPP_TAG_URI)) != NULL) + { + /* + * Get the first actual server and printer name in the class... + */ + + for (i = 0; i < attr->num_values; i ++) + { + httpSeparate(attr->values[0].string.text, method, username, hostname, + &port, resource); + if (strncmp(resource, "/printers/", 10) == 0) + { + /* + * Found a printer! + */ + + strncpy(printer, resource + 10, sizeof(printer) - 1); + printer[sizeof(printer) - 1] = '\0'; + break; + } + } + } + else if ((attr = ippFindAttribute(response, "printer-uri-supported", + IPP_TAG_URI)) != NULL) + { + /* + * Get the actual server and printer names... + */ + + httpSeparate(attr->values[0].string.text, method, username, hostname, + &port, resource); + strncpy(printer, strrchr(resource, '/') + 1, sizeof(printer) - 1); + printer[sizeof(printer) - 1] = '\0'; + } + + ippDelete(response); + + /* + * Remap local hostname to localhost... + */ + + gethostname(buffer, sizeof(buffer)); + + if (strcasecmp(buffer, hostname) == 0) + strcpy(hostname, "localhost"); + } + + cupsLangFree(language); + + if (!printer[0]) + return (NULL); + + /* + * Reconnect to the correct server as needed... + */ + + if (strcasecmp(cups_server->hostname, hostname) != 0) + { + httpClose(cups_server); + + if ((cups_server = httpConnect(hostname, ippPort())) == NULL) + { + last_error = IPP_SERVICE_UNAVAILABLE; + return (NULL); + } + } + + /* + * Get a temp file... + */ + + cupsTempFile(filename, sizeof(filename)); + + /* + * 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... + */ + + snprintf(prompt, sizeof(prompt), "Password for %s on %s? ", cupsUser(), + cups_server->hostname); + + if ((password = cupsGetPassword(prompt)) != NULL) + { + /* + * Got a password; send it to the server... + */ + + if (!password[0]) + break; + + if (strncmp(cups_server->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Basic", 5) == 0) + { + /* + * Basic authentication... + */ + + snprintf(plain, sizeof(plain), "%s:%s", cupsUser(), password); + httpEncode64(encode, plain); + snprintf(authstring, sizeof(authstring), "Basic %s", encode); + } + else + { + /* + * Digest authentication... + */ + + httpGetSubField(cups_server, HTTP_FIELD_WWW_AUTHENTICATE, "realm", realm); + httpGetSubField(cups_server, HTTP_FIELD_WWW_AUTHENTICATE, "nonce", nonce); + + httpMD5(cupsUser(), realm, password, encode); + httpMD5Final(nonce, "GET", resource, encode); + snprintf(authstring, sizeof(authstring), + "Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", " + "response=\"%s\"", cupsUser(), realm, nonce, encode); + } + continue; + } + else + break; + } + } + while (status == HTTP_UNAUTHORIZED); + + /* + * OK, we need to copy the file; open the file and copy it... + */ + + if ((fp = fopen(filename, "w")) == NULL) + { + /* + * Can't open file; close the server connection and return NULL... + */ + + httpFlush(cups_server); + 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 */ + + + if (printers == NULL) + { + last_error = IPP_INTERNAL_ERROR; + return (0); + } + + /* + * 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 + * requested-attributes + */ + + 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); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, + "requested-attributes", NULL, "printer-name"); + + /* + * 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 */ +{ + DEBUG_printf(("cupsPrintFile(\'%s\', \'%s\', %d, %p)\n", + printer, filename, num_options, options)); + + return (cupsPrintFiles(name, 1, &filename, title, num_options, options)); +} + + +/* + * 'cupsPrintFiles()' - Print one or more files to a printer or class. + */ + +int /* O - Job ID */ +cupsPrintFiles(const char *name, /* I - Printer or class name */ + int num_files, /* I - Number of files */ + const char **files, /* I - File(s) 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 */ + const char *val; /* Pointer to 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(("cupsPrintFiles(\'%s\', %d, %p, %d, %p)\n", + printer, num_files, files, num_options, options)); + + if (name == NULL || num_files < 1 || files == NULL) + return (0); + + /* + * Setup a connection and request data... + */ + + if (!cups_connect(name, printer, hostname)) + { + DEBUG_printf(("cupsPrintFile: Unable to open connection - %s.\n", + strerror(errno))); + last_error = IPP_SERVICE_UNAVAILABLE; + return (0); + } + + language = cupsLangDefault(); + + /* + * Build a standard CUPS URI for the printer and fill the standard IPP + * attributes... + */ + + if ((request = ippNew()) == NULL) + return (0); + + request->request.op.operation_id = num_files == 1 ? IPP_PRINT_JOB : + IPP_CREATE_JOB; + request->request.op.request_id = 1; + + snprintf(uri, sizeof(uri), "ipp://%s:%d/printers/%s", hostname, ippPort(), printer); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, + "attributes-charset", NULL, cupsLangEncoding(language)); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, + "attributes-natural-language", NULL, + language != NULL ? language->language : "C"); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", + NULL, uri); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", + NULL, cupsUser()); + + if (title) + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL, title); + + /* + * Then add all options... + */ + + cupsEncodeOptions(request, num_options, options); + + /* + * Do the request... + */ + + snprintf(uri, sizeof(uri), "/printers/%s", printer); + + if (num_files == 1) + response = cupsDoFileRequest(cups_server, request, uri, *files); + else + response = cupsDoRequest(cups_server, request, uri); + + if (response == 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); + + /* + * Handle multiple file jobs if the create-job operation worked... + */ + + if (jobid > 0 && num_files > 1) + for (i = 0; i < num_files; i ++) + { + /* + * Build a standard CUPS URI for the job and fill the standard IPP + * attributes... + */ + + if ((request = ippNew()) == NULL) + return (0); + + request->request.op.operation_id = IPP_SEND_DOCUMENT; + request->request.op.request_id = 1; + + snprintf(uri, sizeof(uri), "ipp://%s:%d/jobs/%d", hostname, ippPort(), + jobid); + + 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, "job-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 if ((val = cupsGetOption("document-format", num_options, options)) != NULL) + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format", + NULL, val); + 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()); + + /* + * Is this the last document? + */ + + if (i == (num_files - 1)) + ippAddBoolean(request, IPP_TAG_OPERATION, "last-document", 1); + + /* + * Send the file... + */ + + snprintf(uri, sizeof(uri), "/printers/%s", printer); + + if ((response = cupsDoFileRequest(cups_server, request, uri, + files[i])) != 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 */ +{ + int fd; /* File descriptor for temp file */ +#ifdef WIN32 + char tmpdir[1024]; /* Windows temporary directory */ + DWORD curtime; /* Current time */ +#else + char *tmpdir; /* TMPDIR environment var */ + struct timeval curtime; /* Current time */ +#endif /* WIN32 */ + 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... + */ + +#ifdef WIN32 + GetTempPath(sizeof(tmpdir), tmpdir); +#else + if ((tmpdir = getenv("TMPDIR")) == NULL) + { + /* + * Put root temp files in restricted temp directory... + */ + + if (getuid() == 0) + tmpdir = CUPS_REQUESTS "/tmp"; + else + tmpdir = "/var/tmp"; + } +#endif /* WIN32 */ + + /* + * Make the temporary name using the specified directory... + */ + + do + { +#ifdef WIN32 + /* + * Get the current time of day... + */ + + curtime = GetTickCount(); + + /* + * Format a string using the hex time values... + */ + + snprintf(filename, len - 1, "%s/%08lx", tmpdir, curtime); +#else + /* + * Get the current time of day... + */ + + gettimeofday(&curtime, NULL); + + /* + * Format a string using the hex time values... + */ + + snprintf(filename, len - 1, "%s/%08lx%05lx", tmpdir, + curtime.tv_sec, curtime.tv_usec); +#endif /* WIN32 */ + + /* + * Open the file in "exclusive" mode, making sure that we don't + * stomp on an existing file or someone's symlink crack... + */ + +#ifdef O_NOFOLLOW + fd = open(filename, O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW, 0600); +#else + fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0600); +#endif /* O_NOFOLLOW */ + } + while (fd < 0); + + /* + * Close the temp file - it'll be reopened later as needed... + */ + + close(fd); + + /* + * Return the temp filename... + */ + + return (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 + { + httpEncryption(cups_server, cupsEncryption()); + 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 */ + const char *root; /* Server root directory */ + + + /* + * 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... + */ + + if ((root = getenv("CUPS_SERVERROOT")) == NULL) + root = CUPS_SERVERROOT; + + pid = getpid(); + snprintf(filename, sizeof(filename), "%s/certs/%d", root, pid); + if ((fp = fopen(filename, "r")) == NULL && pid > 0) + { + snprintf(filename, sizeof(filename), "%s/certs/0", root); + fp = fopen(filename, "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... + */ + + snprintf(authstring, sizeof(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..12efc729ae --- /dev/null +++ b/data/Makefile @@ -0,0 +1,107 @@ +# +# "$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... +# + +BANNERS = classified \ + confidential \ + secret \ + standard \ + topsecret \ + unclassified + +CHARSETS = windows-874 \ + windows-1250 \ + windows-1251 \ + windows-1252 \ + windows-1253 \ + windows-1254 \ + windows-1255 \ + windows-1256 \ + windows-1257 \ + windows-1258 \ + 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 testprint.ps + + +# +# Make everything... +# + +all: + + +# +# Clean all config and object files... +# + +clean: + + +# +# Install files... +# + +install: + -$(MKDIR) $(DATADIR)/banners + $(CHMOD) ugo+rx $(DATADIR) + $(CHMOD) ugo+rx $(DATADIR)/banners + $(INSTALL_DATA) $(BANNERS) $(DATADIR)/banners + -$(MKDIR) $(DATADIR)/charsets + $(CHMOD) ugo+rx $(DATADIR)/charsets + $(INSTALL_DATA) $(CHARSETS) $(DATADIR)/charsets + -$(MKDIR) $(DATADIR)/data + $(CHMOD) ugo+rx $(DATADIR)/data + $(INSTALL_DATA) $(DATAFILES) $(DATADIR)/data + -if test "$(PAMDIR)" != ""; then \ + $(MKDIR) $(PAMDIR); \ + $(CHMOD) ugo+rx $(PAMDIR); \ + if test -f /lib/security/pam_unix.so; then \ + $(INSTALL_DATA) cups.suse $(PAMDIR)/cups; \ + else \ + $(INSTALL_DATA) cups.pam $(PAMDIR)/cups; \ + fi \ + fi + + +# +# End of "$Id$". +# diff --git a/data/classified b/data/classified new file mode 100644 index 0000000000..141c933d38 --- /dev/null +++ b/data/classified @@ -0,0 +1,267 @@ +%!PS-Adobe-3.0 +%%BoundingBox: 0 0 612 792 +%%Pages: 1 +%%LanguageLevel: 1 +%%DocumentData: Clean7Bit +%%DocumentSuppliedResources: procset bannerprint/1.0 +%%DocumentNeededResources: font Helvetica Helvetica-Bold Times-Roman +%%Creator: Michael Sweet, Easy Software Products +%%CreationDate: May 10, 2000 +%%Title: Test Page +%%EndComments +%%BeginProlog +%%BeginResource procset bannerprint 1.1 0 +% +% PostScript banner page for the Common UNIX Printing System ("CUPS"). +% +% Copyright 1993-2000 Easy Software Products +% +% These coded instructions, statements, and computer programs contain +% unpublished proprietary information of Easy Software Products, and +% are protected by Federal copyright law. They may not be disclosed +% to third parties or copied or duplicated in any form, in whole or +% in part, without the prior written consent of Easy Software Products. +% +/CENTER { % Draw centered text + % (name) CENTER - + dup stringwidth pop % Get the width of the string + 0.5 mul neg 0 rmoveto % Shift left 1/2 of the distance + show % Show the string +} bind def +/RIGHT { % Draw right-justified text + % (name) RIGHT - + dup stringwidth pop % Get the width of the string + neg 0 rmoveto % Shift left the entire distance + show % Show the string +} bind def +/NUMBER { % Draw a number + % power n NUMBER - + 1 index 1 eq { % power == 1? + round cvi exch pop % Convert "n" to integer + } { + 1 index mul round exch div % Truncate extra decimal places + } ifelse + 100 string cvs show % Convert to a string and show it... +} bind def +/CUPSLOGO { % Draw the CUPS logo + % height CUPSLOGO + % Start with a big C... + /Helvetica findfont 1 index scalefont setfont + 0 setgray + 0 0 moveto + (C) show + + % Then "UNIX Printing System" much smaller... + /Helvetica-Bold findfont 1 index 9 div scalefont setfont + 0.25 mul + dup dup 2.0 mul moveto + (UNIX) show + dup dup 1.6 mul moveto + (Printing) show + dup 1.2 mul moveto + (System) show +} bind def +/ESPLOGO { % Draw the ESP logo + % height ESPLOGO + % Compute the size of the logo... + 0 0 + 2 index 1.5 mul 3 index + + % Do the "metallic" fill from 10% black to 40% black... + 1 -0.001 0 { + dup % loopval + -0.15 mul % loopval * -0.15 + 0.9 add % 0.9 - loopval * 0.15 + setgray % set gray shade + + 0 % x + 1 index neg % loopval + 1 add % 1 - loopval + 3 index % height + mul % height * (1 - loopval) + moveto % starting point + + dup % loopval + 3 index % width + mul % loopval * width + 2 index % height + lineto % Next point + + 0 % x + 2 index % height + lineto % Next point + + closepath + fill + + dup % loopval + 0.15 mul % loopval * 0.15 + 0.6 add % 0.6 + loopval * 0.15 + setgray + + dup % loopval + neg 1 add % 1 - loopval + 3 index % width + mul % (1 - loopval) * width + 0 % y + moveto % Starting point + + 2 index % width + exch % loopval + 2 index % height + mul % loopval * height + lineto % Next point + + 1 index % width + 0 % y + lineto % Next point + + closepath + fill + } for + + 0 setgray rectstroke + + /Helvetica-BoldOblique findfont 1 index 3 div scalefont setfont + dup 40 div + + dup 4 mul 1 index 25 mul moveto (E) show + dup 10 mul 1 index 15 mul moveto (S) show + dup 16 mul 1 index 5 mul moveto (P) show + + /Helvetica-BoldOblique findfont 2 index 5 div scalefont setfont + dup 14 mul 1 index 29 mul moveto (asy) show + dup 20 mul 1 index 19 mul moveto (oftware) show + dup 26 mul 1 index 9 mul moveto (roducts) show + + pop +} bind def +%%EndResource +%%EndProlog +%%Page: 1 1 +gsave + + % Determine the imageable area and device resolution... + initclip newpath clippath pathbbox % Get bounding rectangle + 72 div /pageTop exch def % Get top margin in inches + 72 div /pageRight exch def % Get right margin in inches + 72 div /pageBottom exch def % Get bottom margin in inches + 72 div /pageLeft exch def % Get left margin in inches + + /pageWidth pageRight pageLeft sub def % pageWidth = pageRight - pageLeft + /pageHeight pageTop pageBottom sub def% pageHeight = pageTop - pageBottom + + /boxWidth % width of text box + pageWidth pageHeight lt + { pageWidth 54 mul } + { pageHeight 42 mul } + ifelse def + + newpath % Clear bounding path + + % Create fonts... + /bigFont /Helvetica-Bold findfont % bigFont = Helvetica-Bold + pageHeight 3 mul scalefont def % size = pageHeight * 3 (nominally 33) + + /mediumFont /Helvetica findfont % mediumFont = Helvetica + pageHeight 1.5 mul scalefont def % size = pageHeight * 1.5 (nominally 16.5) + + % Offset page to account for lower-left margin... + pageLeft 72 mul + pageBottom 72 mul + translate + + % Draw the label at the top and bottom... + 0 setgray % Color + + pageWidth 36 mul % Center of page + pageHeight 72 mul % Top of page + pageWidth -7 mul add % - 2 lines + moveto % Position text + bigFont setfont % Font + (Classified) CENTER % Show text centered + + pageWidth 36 mul % Center of page + pageHeight 6 mul % Bottom of page + moveto % Position text + bigFont setfont % Font + (Classified) CENTER % Show text centered + + % Job information box... + pageWidth 36 mul 9 add % x = pageWidth * 1/2 * 72 + 9 + boxWidth 0.5 mul sub % x-= 1/2 box width + pageHeight 30 mul 9 sub % y = pageHeight * 1/2 * 72 - 9 + boxWidth % w = box width + pageHeight 14 mul % h = pageHeight * 1/2 * 72 + 0.5 setgray rectfill % Draw a shadow + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + boxWidth 0.5 mul sub % x-= 1/2 box width + pageHeight 30 mul % y = pageHeight * 1/4 * 72 + boxWidth % w = box width + pageHeight 14 mul % h = pageHeight * 1/2 * 72 + + 4 copy 1 setgray rectfill % Clear the box to white + 0 setgray rectstroke % Draw a black box around it... + + % Job information text... + mediumFont setfont % Medium sized font + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight 5 mul add % y += 2 lines + 2 copy % Copy X & Y + moveto + (Job ID: ) RIGHT + moveto + ({printer-name}-{job-id}) show + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight 2 mul add % y += 1 line + 2 copy % Copy X & Y + moveto + (Title: ) RIGHT + moveto + ({job-name}) show + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight -1 mul add % y -= 1 line + 2 copy % Copy X & Y + moveto + (Requesting User: ) RIGHT + moveto + ({job-originating-user-name}) show + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight -4 mul add % y -= 2 lines + 2 copy % Copy X & Y + moveto + (Billing Info: ) RIGHT + moveto + ({job-billing}) show + + % Then the CUPS logo.... + gsave + pageWidth 4 mul + pageWidth 6 mul + translate + pageWidth 9 mul CUPSLOGO + grestore + + % And the ESP logo.... + gsave + pageWidth 59 mul + pageWidth 6 mul + translate + pageWidth 6 mul ESPLOGO + grestore +% Show the page... +grestore +showpage +% +% End of "$Id: classified 1379 2000-09-18 17:12:42Z mike $". +% +%%EOF diff --git a/data/confidential b/data/confidential new file mode 100644 index 0000000000..26b3bf731f --- /dev/null +++ b/data/confidential @@ -0,0 +1,267 @@ +%!PS-Adobe-3.0 +%%BoundingBox: 0 0 612 792 +%%Pages: 1 +%%LanguageLevel: 1 +%%DocumentData: Clean7Bit +%%DocumentSuppliedResources: procset bannerprint/1.0 +%%DocumentNeededResources: font Helvetica Helvetica-Bold Times-Roman +%%Creator: Michael Sweet, Easy Software Products +%%CreationDate: May 10, 2000 +%%Title: Test Page +%%EndComments +%%BeginProlog +%%BeginResource procset bannerprint 1.1 0 +% +% PostScript banner page for the Common UNIX Printing System ("CUPS"). +% +% Copyright 1993-2000 Easy Software Products +% +% These coded instructions, statements, and computer programs contain +% unpublished proprietary information of Easy Software Products, and +% are protected by Federal copyright law. They may not be disclosed +% to third parties or copied or duplicated in any form, in whole or +% in part, without the prior written consent of Easy Software Products. +% +/CENTER { % Draw centered text + % (name) CENTER - + dup stringwidth pop % Get the width of the string + 0.5 mul neg 0 rmoveto % Shift left 1/2 of the distance + show % Show the string +} bind def +/RIGHT { % Draw right-justified text + % (name) RIGHT - + dup stringwidth pop % Get the width of the string + neg 0 rmoveto % Shift left the entire distance + show % Show the string +} bind def +/NUMBER { % Draw a number + % power n NUMBER - + 1 index 1 eq { % power == 1? + round cvi exch pop % Convert "n" to integer + } { + 1 index mul round exch div % Truncate extra decimal places + } ifelse + 100 string cvs show % Convert to a string and show it... +} bind def +/CUPSLOGO { % Draw the CUPS logo + % height CUPSLOGO + % Start with a big C... + /Helvetica findfont 1 index scalefont setfont + 0 setgray + 0 0 moveto + (C) show + + % Then "UNIX Printing System" much smaller... + /Helvetica-Bold findfont 1 index 9 div scalefont setfont + 0.25 mul + dup dup 2.0 mul moveto + (UNIX) show + dup dup 1.6 mul moveto + (Printing) show + dup 1.2 mul moveto + (System) show +} bind def +/ESPLOGO { % Draw the ESP logo + % height ESPLOGO + % Compute the size of the logo... + 0 0 + 2 index 1.5 mul 3 index + + % Do the "metallic" fill from 10% black to 40% black... + 1 -0.001 0 { + dup % loopval + -0.15 mul % loopval * -0.15 + 0.9 add % 0.9 - loopval * 0.15 + setgray % set gray shade + + 0 % x + 1 index neg % loopval + 1 add % 1 - loopval + 3 index % height + mul % height * (1 - loopval) + moveto % starting point + + dup % loopval + 3 index % width + mul % loopval * width + 2 index % height + lineto % Next point + + 0 % x + 2 index % height + lineto % Next point + + closepath + fill + + dup % loopval + 0.15 mul % loopval * 0.15 + 0.6 add % 0.6 + loopval * 0.15 + setgray + + dup % loopval + neg 1 add % 1 - loopval + 3 index % width + mul % (1 - loopval) * width + 0 % y + moveto % Starting point + + 2 index % width + exch % loopval + 2 index % height + mul % loopval * height + lineto % Next point + + 1 index % width + 0 % y + lineto % Next point + + closepath + fill + } for + + 0 setgray rectstroke + + /Helvetica-BoldOblique findfont 1 index 3 div scalefont setfont + dup 40 div + + dup 4 mul 1 index 25 mul moveto (E) show + dup 10 mul 1 index 15 mul moveto (S) show + dup 16 mul 1 index 5 mul moveto (P) show + + /Helvetica-BoldOblique findfont 2 index 5 div scalefont setfont + dup 14 mul 1 index 29 mul moveto (asy) show + dup 20 mul 1 index 19 mul moveto (oftware) show + dup 26 mul 1 index 9 mul moveto (roducts) show + + pop +} bind def +%%EndResource +%%EndProlog +%%Page: 1 1 +gsave + + % Determine the imageable area and device resolution... + initclip newpath clippath pathbbox % Get bounding rectangle + 72 div /pageTop exch def % Get top margin in inches + 72 div /pageRight exch def % Get right margin in inches + 72 div /pageBottom exch def % Get bottom margin in inches + 72 div /pageLeft exch def % Get left margin in inches + + /pageWidth pageRight pageLeft sub def % pageWidth = pageRight - pageLeft + /pageHeight pageTop pageBottom sub def% pageHeight = pageTop - pageBottom + + /boxWidth % width of text box + pageWidth pageHeight lt + { pageWidth 54 mul } + { pageHeight 42 mul } + ifelse def + + newpath % Clear bounding path + + % Create fonts... + /bigFont /Helvetica-Bold findfont % bigFont = Helvetica-Bold + pageHeight 3 mul scalefont def % size = pageHeight * 3 (nominally 33) + + /mediumFont /Helvetica findfont % mediumFont = Helvetica + pageHeight 1.5 mul scalefont def % size = pageHeight * 1.5 (nominally 16.5) + + % Offset page to account for lower-left margin... + pageLeft 72 mul + pageBottom 72 mul + translate + + % Draw the label at the top and bottom... + 0 setgray % Color + + pageWidth 36 mul % Center of page + pageHeight 72 mul % Top of page + pageWidth -7 mul add % - 2 lines + moveto % Position text + bigFont setfont % Font + (Confidential) CENTER % Show text centered + + pageWidth 36 mul % Center of page + pageHeight 6 mul % Bottom of page + moveto % Position text + bigFont setfont % Font + (Confidential) CENTER % Show text centered + + % Job information box... + pageWidth 36 mul 9 add % x = pageWidth * 1/2 * 72 + 9 + boxWidth 0.5 mul sub % x-= 1/2 box width + pageHeight 30 mul 9 sub % y = pageHeight * 1/2 * 72 - 9 + boxWidth % w = box width + pageHeight 14 mul % h = pageHeight * 1/2 * 72 + 0.5 setgray rectfill % Draw a shadow + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + boxWidth 0.5 mul sub % x-= 1/2 box width + pageHeight 30 mul % y = pageHeight * 1/4 * 72 + boxWidth % w = box width + pageHeight 14 mul % h = pageHeight * 1/2 * 72 + + 4 copy 1 setgray rectfill % Clear the box to white + 0 setgray rectstroke % Draw a black box around it... + + % Job information text... + mediumFont setfont % Medium sized font + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight 5 mul add % y += 2 lines + 2 copy % Copy X & Y + moveto + (Job ID: ) RIGHT + moveto + ({printer-name}-{job-id}) show + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight 2 mul add % y += 1 line + 2 copy % Copy X & Y + moveto + (Title: ) RIGHT + moveto + ({job-name}) show + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight -1 mul add % y -= 1 line + 2 copy % Copy X & Y + moveto + (Requesting User: ) RIGHT + moveto + ({job-originating-user-name}) show + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight -4 mul add % y -= 2 lines + 2 copy % Copy X & Y + moveto + (Billing Info: ) RIGHT + moveto + ({job-billing}) show + + % Then the CUPS logo.... + gsave + pageWidth 4 mul + pageWidth 6 mul + translate + pageWidth 9 mul CUPSLOGO + grestore + + % And the ESP logo.... + gsave + pageWidth 59 mul + pageWidth 6 mul + translate + pageWidth 6 mul ESPLOGO + grestore +% Show the page... +grestore +showpage +% +% End of "$Id: confidential 1379 2000-09-18 17:12:42Z mike $". +% +%%EOF diff --git a/data/cups.pam b/data/cups.pam new file mode 100644 index 0000000000..f38e70184a --- /dev/null +++ b/data/cups.pam @@ -0,0 +1,2 @@ +auth required /lib/security/pam_pwdb.so nullok shadow +account required /lib/security/pam_pwdb.so diff --git a/data/cups.suse b/data/cups.suse new file mode 100644 index 0000000000..0c26fbe0d8 --- /dev/null +++ b/data/cups.suse @@ -0,0 +1,2 @@ +auth required /lib/security/pam_unix.so nullok shadow +account required /lib/security/pam_unix.so diff --git a/data/iso-8859-1 b/data/iso-8859-1 new file mode 100644 index 0000000000..057d8aee3d --- /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. +# + +00 ff 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..31f55552ee --- /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. +# + +00 ff 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..dcfacca9d3 --- /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. +# + +00 ff 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..ca0097a47d --- /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. +# + +00 ff 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..334160f4f2 --- /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. +# + +00 ff 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..19b77878d4 --- /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. +# + +00 ff 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..efc4529ed0 --- /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. +# + +00 ff 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..5c93156eb5 --- /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. +# + +00 ff 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..59ee84d57a --- /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. +# + +00 ff 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..356fe72e3b --- /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. +# + +00 ff 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..57647841cf --- /dev/null +++ b/data/iso-8859-7 @@ -0,0 +1,246 @@ +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. +# + +00 9f ltor single Courier Courier-Bold Courier-Italic Courier-BoldItalic +a0 ff ltor single Symbol + +# +# 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..a64c598f13 --- /dev/null +++ b/data/iso-8859-8 @@ -0,0 +1,214 @@ +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. +# + +00 7f ltor single Courier Courier-Bold Courier-Italic Courier-BoldItalic +80 ff rtol single Courier-Hebrew + +# +# 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..83a661edc2 --- /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. +# + +00 ff 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/secret b/data/secret new file mode 100644 index 0000000000..c02a4d6309 --- /dev/null +++ b/data/secret @@ -0,0 +1,267 @@ +%!PS-Adobe-3.0 +%%BoundingBox: 0 0 612 792 +%%Pages: 1 +%%LanguageLevel: 1 +%%DocumentData: Clean7Bit +%%DocumentSuppliedResources: procset bannerprint/1.0 +%%DocumentNeededResources: font Helvetica Helvetica-Bold Times-Roman +%%Creator: Michael Sweet, Easy Software Products +%%CreationDate: May 10, 2000 +%%Title: Test Page +%%EndComments +%%BeginProlog +%%BeginResource procset bannerprint 1.1 0 +% +% PostScript banner page for the Common UNIX Printing System ("CUPS"). +% +% Copyright 1993-2000 Easy Software Products +% +% These coded instructions, statements, and computer programs contain +% unpublished proprietary information of Easy Software Products, and +% are protected by Federal copyright law. They may not be disclosed +% to third parties or copied or duplicated in any form, in whole or +% in part, without the prior written consent of Easy Software Products. +% +/CENTER { % Draw centered text + % (name) CENTER - + dup stringwidth pop % Get the width of the string + 0.5 mul neg 0 rmoveto % Shift left 1/2 of the distance + show % Show the string +} bind def +/RIGHT { % Draw right-justified text + % (name) RIGHT - + dup stringwidth pop % Get the width of the string + neg 0 rmoveto % Shift left the entire distance + show % Show the string +} bind def +/NUMBER { % Draw a number + % power n NUMBER - + 1 index 1 eq { % power == 1? + round cvi exch pop % Convert "n" to integer + } { + 1 index mul round exch div % Truncate extra decimal places + } ifelse + 100 string cvs show % Convert to a string and show it... +} bind def +/CUPSLOGO { % Draw the CUPS logo + % height CUPSLOGO + % Start with a big C... + /Helvetica findfont 1 index scalefont setfont + 0 setgray + 0 0 moveto + (C) show + + % Then "UNIX Printing System" much smaller... + /Helvetica-Bold findfont 1 index 9 div scalefont setfont + 0.25 mul + dup dup 2.0 mul moveto + (UNIX) show + dup dup 1.6 mul moveto + (Printing) show + dup 1.2 mul moveto + (System) show +} bind def +/ESPLOGO { % Draw the ESP logo + % height ESPLOGO + % Compute the size of the logo... + 0 0 + 2 index 1.5 mul 3 index + + % Do the "metallic" fill from 10% black to 40% black... + 1 -0.001 0 { + dup % loopval + -0.15 mul % loopval * -0.15 + 0.9 add % 0.9 - loopval * 0.15 + setgray % set gray shade + + 0 % x + 1 index neg % loopval + 1 add % 1 - loopval + 3 index % height + mul % height * (1 - loopval) + moveto % starting point + + dup % loopval + 3 index % width + mul % loopval * width + 2 index % height + lineto % Next point + + 0 % x + 2 index % height + lineto % Next point + + closepath + fill + + dup % loopval + 0.15 mul % loopval * 0.15 + 0.6 add % 0.6 + loopval * 0.15 + setgray + + dup % loopval + neg 1 add % 1 - loopval + 3 index % width + mul % (1 - loopval) * width + 0 % y + moveto % Starting point + + 2 index % width + exch % loopval + 2 index % height + mul % loopval * height + lineto % Next point + + 1 index % width + 0 % y + lineto % Next point + + closepath + fill + } for + + 0 setgray rectstroke + + /Helvetica-BoldOblique findfont 1 index 3 div scalefont setfont + dup 40 div + + dup 4 mul 1 index 25 mul moveto (E) show + dup 10 mul 1 index 15 mul moveto (S) show + dup 16 mul 1 index 5 mul moveto (P) show + + /Helvetica-BoldOblique findfont 2 index 5 div scalefont setfont + dup 14 mul 1 index 29 mul moveto (asy) show + dup 20 mul 1 index 19 mul moveto (oftware) show + dup 26 mul 1 index 9 mul moveto (roducts) show + + pop +} bind def +%%EndResource +%%EndProlog +%%Page: 1 1 +gsave + + % Determine the imageable area and device resolution... + initclip newpath clippath pathbbox % Get bounding rectangle + 72 div /pageTop exch def % Get top margin in inches + 72 div /pageRight exch def % Get right margin in inches + 72 div /pageBottom exch def % Get bottom margin in inches + 72 div /pageLeft exch def % Get left margin in inches + + /pageWidth pageRight pageLeft sub def % pageWidth = pageRight - pageLeft + /pageHeight pageTop pageBottom sub def% pageHeight = pageTop - pageBottom + + /boxWidth % width of text box + pageWidth pageHeight lt + { pageWidth 54 mul } + { pageHeight 42 mul } + ifelse def + + newpath % Clear bounding path + + % Create fonts... + /bigFont /Helvetica-Bold findfont % bigFont = Helvetica-Bold + pageHeight 3 mul scalefont def % size = pageHeight * 3 (nominally 33) + + /mediumFont /Helvetica findfont % mediumFont = Helvetica + pageHeight 1.5 mul scalefont def % size = pageHeight * 1.5 (nominally 16.5) + + % Offset page to account for lower-left margin... + pageLeft 72 mul + pageBottom 72 mul + translate + + % Draw the label at the top and bottom... + 0 setgray % Color + + pageWidth 36 mul % Center of page + pageHeight 72 mul % Top of page + pageWidth -7 mul add % - 2 lines + moveto % Position text + bigFont setfont % Font + (Secret) CENTER % Show text centered + + pageWidth 36 mul % Center of page + pageHeight 6 mul % Bottom of page + moveto % Position text + bigFont setfont % Font + (Secret) CENTER % Show text centered + + % Job information box... + pageWidth 36 mul 9 add % x = pageWidth * 1/2 * 72 + 9 + boxWidth 0.5 mul sub % x-= 1/2 box width + pageHeight 30 mul 9 sub % y = pageHeight * 1/2 * 72 - 9 + boxWidth % w = box width + pageHeight 14 mul % h = pageHeight * 1/2 * 72 + 0.5 setgray rectfill % Draw a shadow + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + boxWidth 0.5 mul sub % x-= 1/2 box width + pageHeight 30 mul % y = pageHeight * 1/4 * 72 + boxWidth % w = box width + pageHeight 14 mul % h = pageHeight * 1/2 * 72 + + 4 copy 1 setgray rectfill % Clear the box to white + 0 setgray rectstroke % Draw a black box around it... + + % Job information text... + mediumFont setfont % Medium sized font + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight 5 mul add % y += 2 lines + 2 copy % Copy X & Y + moveto + (Job ID: ) RIGHT + moveto + ({printer-name}-{job-id}) show + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight 2 mul add % y += 1 line + 2 copy % Copy X & Y + moveto + (Title: ) RIGHT + moveto + ({job-name}) show + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight -1 mul add % y -= 1 line + 2 copy % Copy X & Y + moveto + (Requesting User: ) RIGHT + moveto + ({job-originating-user-name}) show + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight -4 mul add % y -= 2 lines + 2 copy % Copy X & Y + moveto + (Billing Info: ) RIGHT + moveto + ({job-billing}) show + + % Then the CUPS logo.... + gsave + pageWidth 4 mul + pageWidth 6 mul + translate + pageWidth 9 mul CUPSLOGO + grestore + + % And the ESP logo.... + gsave + pageWidth 59 mul + pageWidth 6 mul + translate + pageWidth 6 mul ESPLOGO + grestore +% Show the page... +grestore +showpage +% +% End of "$Id: secret 1379 2000-09-18 17:12:42Z mike $". +% +%%EOF diff --git a/data/standard b/data/standard new file mode 100644 index 0000000000..9d2d3e3afe --- /dev/null +++ b/data/standard @@ -0,0 +1,251 @@ +%!PS-Adobe-3.0 +%%BoundingBox: 0 0 612 792 +%%Pages: 1 +%%LanguageLevel: 1 +%%DocumentData: Clean7Bit +%%DocumentSuppliedResources: procset bannerprint/1.0 +%%DocumentNeededResources: font Helvetica Helvetica-Bold Times-Roman +%%Creator: Michael Sweet, Easy Software Products +%%CreationDate: May 10, 2000 +%%Title: Test Page +%%EndComments +%%BeginProlog +%%BeginResource procset bannerprint 1.1 0 +% +% PostScript banner page for the Common UNIX Printing System ("CUPS"). +% +% Copyright 1993-2000 Easy Software Products +% +% These coded instructions, statements, and computer programs contain +% unpublished proprietary information of Easy Software Products, and +% are protected by Federal copyright law. They may not be disclosed +% to third parties or copied or duplicated in any form, in whole or +% in part, without the prior written consent of Easy Software Products. +% +/CENTER { % Draw centered text + % (name) CENTER - + dup stringwidth pop % Get the width of the string + 0.5 mul neg 0 rmoveto % Shift left 1/2 of the distance + show % Show the string +} bind def +/RIGHT { % Draw right-justified text + % (name) RIGHT - + dup stringwidth pop % Get the width of the string + neg 0 rmoveto % Shift left the entire distance + show % Show the string +} bind def +/NUMBER { % Draw a number + % power n NUMBER - + 1 index 1 eq { % power == 1? + round cvi exch pop % Convert "n" to integer + } { + 1 index mul round exch div % Truncate extra decimal places + } ifelse + 100 string cvs show % Convert to a string and show it... +} bind def +/CUPSLOGO { % Draw the CUPS logo + % height CUPSLOGO + % Start with a big C... + /Helvetica findfont 1 index scalefont setfont + 0 setgray + 0 0 moveto + (C) show + + % Then "UNIX Printing System" much smaller... + /Helvetica-Bold findfont 1 index 9 div scalefont setfont + 0.25 mul + dup dup 2.0 mul moveto + (UNIX) show + dup dup 1.6 mul moveto + (Printing) show + dup 1.2 mul moveto + (System) show +} bind def +/ESPLOGO { % Draw the ESP logo + % height ESPLOGO + % Compute the size of the logo... + 0 0 + 2 index 1.5 mul 3 index + + % Do the "metallic" fill from 10% black to 40% black... + 1 -0.001 0 { + dup % loopval + -0.15 mul % loopval * -0.15 + 0.9 add % 0.9 - loopval * 0.15 + setgray % set gray shade + + 0 % x + 1 index neg % loopval + 1 add % 1 - loopval + 3 index % height + mul % height * (1 - loopval) + moveto % starting point + + dup % loopval + 3 index % width + mul % loopval * width + 2 index % height + lineto % Next point + + 0 % x + 2 index % height + lineto % Next point + + closepath + fill + + dup % loopval + 0.15 mul % loopval * 0.15 + 0.6 add % 0.6 + loopval * 0.15 + setgray + + dup % loopval + neg 1 add % 1 - loopval + 3 index % width + mul % (1 - loopval) * width + 0 % y + moveto % Starting point + + 2 index % width + exch % loopval + 2 index % height + mul % loopval * height + lineto % Next point + + 1 index % width + 0 % y + lineto % Next point + + closepath + fill + } for + + 0 setgray rectstroke + + /Helvetica-BoldOblique findfont 1 index 3 div scalefont setfont + dup 40 div + + dup 4 mul 1 index 25 mul moveto (E) show + dup 10 mul 1 index 15 mul moveto (S) show + dup 16 mul 1 index 5 mul moveto (P) show + + /Helvetica-BoldOblique findfont 2 index 5 div scalefont setfont + dup 14 mul 1 index 29 mul moveto (asy) show + dup 20 mul 1 index 19 mul moveto (oftware) show + dup 26 mul 1 index 9 mul moveto (roducts) show + + pop +} bind def +%%EndResource +%%EndProlog +%%Page: 1 1 +gsave + + % Determine the imageable area and device resolution... + initclip newpath clippath pathbbox % Get bounding rectangle + 72 div /pageTop exch def % Get top margin in inches + 72 div /pageRight exch def % Get right margin in inches + 72 div /pageBottom exch def % Get bottom margin in inches + 72 div /pageLeft exch def % Get left margin in inches + + /pageWidth pageRight pageLeft sub def % pageWidth = pageRight - pageLeft + /pageHeight pageTop pageBottom sub def% pageHeight = pageTop - pageBottom + + /boxWidth % width of text box + pageWidth pageHeight lt + { pageWidth 54 mul } + { pageHeight 42 mul } + ifelse def + + newpath % Clear bounding path + + % Create fonts... + /bigFont /Helvetica-Bold findfont % bigFont = Helvetica-Bold + pageHeight 3 mul scalefont def % size = pageHeight * 3 (nominally 33) + + /mediumFont /Helvetica findfont % mediumFont = Helvetica + pageHeight 1.5 mul scalefont def % size = pageHeight * 1.5 (nominally 16.5) + + % Offset page to account for lower-left margin... + pageLeft 72 mul + pageBottom 72 mul + translate + + % Job information box... + pageWidth 36 mul 9 add % x = pageWidth * 1/2 * 72 + 9 + boxWidth 0.5 mul sub % x-= 1/2 box width + pageHeight 30 mul 9 sub % y = pageHeight * 1/2 * 72 - 9 + boxWidth % w = box width + pageHeight 14 mul % h = pageHeight * 1/2 * 72 + 0.5 setgray rectfill % Draw a shadow + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + boxWidth 0.5 mul sub % x-= 1/2 box width + pageHeight 30 mul % y = pageHeight * 1/4 * 72 + boxWidth % w = box width + pageHeight 14 mul % h = pageHeight * 1/2 * 72 + + 4 copy 1 setgray rectfill % Clear the box to white + 0 setgray rectstroke % Draw a black box around it... + + % Job information text... + mediumFont setfont % Medium sized font + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight 5 mul add % y += 2 lines + 2 copy % Copy X & Y + moveto + (Job ID: ) RIGHT + moveto + ({printer-name}-{job-id}) show + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight 2 mul add % y += 1 line + 2 copy % Copy X & Y + moveto + (Title: ) RIGHT + moveto + ({job-name}) show + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight -1 mul add % y -= 1 line + 2 copy % Copy X & Y + moveto + (Requesting User: ) RIGHT + moveto + ({job-originating-user-name}) show + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight -4 mul add % y -= 2 lines + 2 copy % Copy X & Y + moveto + (Billing Info: ) RIGHT + moveto + ({job-billing}) show + + % Then the CUPS logo.... + gsave + pageWidth 4 mul + pageWidth 6 mul + translate + pageWidth 9 mul CUPSLOGO + grestore + + % And the ESP logo.... + gsave + pageWidth 59 mul + pageWidth 6 mul + translate + pageWidth 6 mul ESPLOGO + grestore +% Show the page... +grestore +showpage +% +% End of "$Id: standard 1379 2000-09-18 17:12:42Z mike $". +% +%%EOF diff --git a/data/testprint.ps b/data/testprint.ps new file mode 100644 index 0000000000..da10ad109c --- /dev/null +++ b/data/testprint.ps @@ -0,0 +1,512 @@ +%!PS-Adobe-3.0 +%%BoundingBox: 0 0 612 792 +%%Pages: 1 +%%LanguageLevel: 1 +%%DocumentData: Clean7Bit +%%DocumentSuppliedResources: procset testprint/1.0 +%%DocumentNeededResources: font Helvetica Helvetica-Bold Times-Roman +%%Creator: Michael Sweet, Easy Software Products +%%CreationDate: May 11, 1999 +%%Title: Test Page +%%EndComments +%%BeginProlog +%%BeginResource procset testprint 1.1 0 +% +% PostScript test page for the Common UNIX Printing System ("CUPS"). +% +% Copyright 1993-2000 Easy Software Products +% +% These coded instructions, statements, and computer programs contain +% unpublished proprietary information of Easy Software Products, and +% are protected by Federal copyright law. They may not be disclosed +% to third parties or copied or duplicated in any form, in whole or +% in part, without the prior written consent of Easy Software Products. +% +/OCTANT { % Draw a color wheel OCTANT... + % (name) radius r g b OCTANT - + % Loop through 100 shades... + 0 0.010101 0.98 { + % Set the color... + 3 index 1 eq % R == 1? + 3 index 1 eq % G == 1? + 3 index 1 eq % B == 1? + and and { + 0 index 4 index mul % R * val + 1 index 4 index mul % G * val + 2 index 4 index mul % B * val + } { + 0 index 4 index mul % R * val + 1 index neg 1 add add % + (1 - val) + 1 index 4 index mul % G * val + 2 index neg 1 add add % + (1 - val) + 2 index 4 index mul % B * val + 3 index neg 1 add add % + (1 - val) + } ifelse + setrgbcolor + + % Draw a polygon... + dup 5 index mul dup 0 % x1, y1 + moveto + 0.707106781 mul dup lineto % x2, y2 + + 0.010101 add 4 index mul dup % x3 + 0.707106781 mul dup lineto % x3, y3 + 0 lineto % x4, y4 + closepath + fill + } for + + % Draw a line around the polygons... + pop pop pop dup + 0 setgray + 0 0 moveto + dup 0 lineto + 0.707106781 mul dup lineto + closepath + stroke + + % Draw the label... + 0 exch dup -9 div exch % text offset = 0, -radius/9 + dup 0.923879532 mul % x = radius * cos(22.5) + exch 0.382683432 mul % y = radius * cos(22.5) + moveto % position label + gsave + 22.5 rotate % rotate label + rmoveto % offset label + show % show label + grestore +} bind def +/CENTER { % Draw centered text + % (name) CENTER - + dup stringwidth pop % Get the width of the string + 0.5 mul neg 0 rmoveto % Shift left 1/2 of the distance + show % Show the string +} bind def +/RIGHT { % Draw right-justified text + % (name) RIGHT - + dup stringwidth pop % Get the width of the string + neg 0 rmoveto % Shift left the entire distance + show % Show the string +} bind def +/NUMBER { % Draw a number + % power n NUMBER - + 1 index 1 eq { % power == 1? + round cvi exch pop % Convert "n" to integer + } { + 1 index mul round exch div % Truncate extra decimal places + } ifelse + 100 string cvs show % Convert to a string and show it... +} bind def +/CUPSLOGO { % Draw the CUPS logo + % height CUPSLOGO + % Start with a big C... + /Helvetica findfont 1 index scalefont setfont + 0 setgray + 0 0 moveto + (C) show + + % Then "UNIX Printing System" much smaller... + /Helvetica-Bold findfont 1 index 9 div scalefont setfont + 0.25 mul + dup dup 2.0 mul moveto + (UNIX) show + dup dup 1.6 mul moveto + (Printing) show + dup 1.2 mul moveto + (System) show +} bind def +/ESPLOGO { % Draw the ESP logo + % height ESPLOGO + % Compute the size of the logo... + 0 0 + 2 index 1.5 mul 3 index + + % Do the "metallic" fill from 10% black to 40% black... + 1 -0.001 0 { + dup % loopval + -0.15 mul % loopval * -0.15 + 0.9 add % 0.9 - loopval * 0.15 + setgray % set gray shade + + 0 % x + 1 index neg % loopval + 1 add % 1 - loopval + 3 index % height + mul % height * (1 - loopval) + moveto % starting point + + dup % loopval + 3 index % width + mul % loopval * width + 2 index % height + lineto % Next point + + 0 % x + 2 index % height + lineto % Next point + + closepath + fill + + dup % loopval + 0.15 mul % loopval * 0.15 + 0.6 add % 0.6 + loopval * 0.15 + setgray + + dup % loopval + neg 1 add % 1 - loopval + 3 index % width + mul % (1 - loopval) * width + 0 % y + moveto % Starting point + + 2 index % width + exch % loopval + 2 index % height + mul % loopval * height + lineto % Next point + + 1 index % width + 0 % y + lineto % Next point + + closepath + fill + } for + + 0 setgray rectstroke + + /Helvetica-BoldOblique findfont 1 index 3 div scalefont setfont + dup 40 div + + dup 4 mul 1 index 25 mul moveto (E) show + dup 10 mul 1 index 15 mul moveto (S) show + dup 16 mul 1 index 5 mul moveto (P) show + + /Helvetica-BoldOblique findfont 2 index 5 div scalefont setfont + dup 14 mul 1 index 29 mul moveto (asy) show + dup 20 mul 1 index 19 mul moveto (oftware) show + dup 26 mul 1 index 9 mul moveto (roducts) show + + pop +} bind def +%%EndResource +%%EndProlog +%%Page: 1 1 +gsave + + % Determine the imageable area and device resolution... + initclip newpath clippath pathbbox % Get bounding rectangle + 72 div /pageTop exch def % Get top margin in inches + 72 div /pageRight exch def % Get right margin in inches + 72 div /pageBottom exch def % Get bottom margin in inches + 72 div /pageLeft exch def % Get left margin in inches + + 4 setlinewidth % Draw wide lines + 0 setgray closepath stroke % Draw a clipping rectangle + 1 setlinewidth % Draw normal lines + + /pageWidth pageRight pageLeft sub def % pageWidth = pageRight - pageLeft + /pageHeight pageTop pageBottom sub def% pageHeight = pageTop - pageBottom + + 72 72 dtransform % Get device resolution per inch + /yResolution exch abs def % yResolution = abs(yres) + /xResolution exch abs def % xResolution = abs(xres) + + % Figure out the sizes of things... + /wheelSize % size of wheels + pageWidth pageHeight lt + { pageWidth 9 mul } + { pageHeight 7 mul } + ifelse def + + % Create fonts... + /bigFont /Helvetica-Bold findfont % bigFont = Helvetica-Bold + pageHeight 3 mul scalefont def % size = pageHeight * 3 (nominally 33) + + /mediumFont /Helvetica findfont % mediumFont = Helvetica + pageHeight 1.5 mul scalefont def % size = pageHeight * 1.5 (nominally 16.5) + + /smallFont /Times-Roman findfont % smallFont = Times-Roman + pageHeight scalefont def % size = pageHeight (nominally 11) + + % Offset page to account for lower-left margin... + pageLeft 72 mul + pageBottom 72 mul + translate + + % Draw the color wheel... + mediumFont setfont % Font + 0 setgray % Color + + gsave + % Position the wheel on the left side... + pageWidth 18 mul % x = pageWidth * 1/4 * 72 + pageHeight 54 mul % y = pageHeight * 3/4 * 72 + translate + + % Size the wheel... + wheelSize + + % Draw the colors... + dup (C) exch 0 1 1 OCTANT 45 rotate + dup (M) exch 1 0 1 OCTANT 45 rotate + dup (Y) exch 1 1 0 OCTANT 45 rotate + dup (K) exch 0 0 0 OCTANT 45 rotate + dup (R) exch 1 0 0 OCTANT 45 rotate + dup (G) exch 0 1 0 OCTANT 45 rotate + dup (B) exch 0 0 1 OCTANT 45 rotate + (W) exch 1 1 1 OCTANT 45 rotate + grestore + + % Label the color wheel... + pageWidth 18 mul % x = pageWidth * 1/4 * 72 + pageHeight 44 mul % y = pageHeight * 19/32 * 72 + moveto % Position the text + (Color Wheel) CENTER % Show the text centered + + % Draw radial lines... + gsave + 0 setlinewidth % 1 pixel lines + + % Position the lines on the left side... + pageWidth 54 mul % x = pageWidth * 3/4 * 72 + pageHeight 54 mul % y = pageHeight * 3/4 * 72 + translate + + % Size the wheel... + wheelSize + + % Loop at 1 degree increments + 0 1 359 { + pop % Discard angle - not used + 0 0 moveto % Start line at the center + dup 0 lineto % Draw to the radius + 1 rotate % Rotate 1 degree + } for + + pop % Discard radius - not needed anymore + stroke % Draw lines... + + grestore + + % Label the lines... + pageWidth 54 mul % x = pageWidth * 3/4 * 72 + pageHeight 44 mul % y = pageHeight * 19/32 * 72 + moveto % Position the text + (1 Degree Radial Lines) CENTER % Show the text centered + + % Imageable area... + pageHeight 15 mul % Height of imageable area + + pageWidth 4.5 mul % x = pageWidth * 1/16 * 72 + pageHeight 35.5 mul % y = pageHeight * 1/2 * 72 + 2 index sub % y -= height + pageWidth 28 mul % width = pageWidth * 1/4 * 72 + 3 index % height + 0.5 setgray rectfill % Draw a shadow + + pageWidth 4 mul % x = pageWidth * 1/16 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + 2 index sub % y -= height + pageWidth 28 mul % width = pageWidth * 3/8 * 72 + 3 index % height + 4 copy 1 setgray rectfill % Clear the box to white + 0 setgray rectstroke % Draw a black box around it... + + pop % Discard height + + % Label the imageable area... + pageWidth 4 mul % x = pageWidth * 1/16 * 72 + pageHeight 37 mul % y = pageHeight * 1/2 * 72 + moveto % Position the text + mediumFont setfont % Font + (Imageable Area) show % Show the text + + smallFont setfont % Font + pageWidth 14 mul % x = pageWidth * 3/16 * 72 + pageHeight 36 mul % y = pageWidth * 1/2 * 72 + pageHeight -2 mul add % y -= 2 * smallFont height + + % Page Size inches + 2 copy moveto % Move to x & y + (Page Size: ) RIGHT % Label + 100 pageWidth NUMBER % pageWidth + (x) show % "x" + 100 pageHeight NUMBER % pageHeight + (in) show % "in" + + % Page Size millimeters + pageHeight sub % Move down... + + 2 copy moveto % Move to x & y + 10 pageWidth 25.4 mul NUMBER % pageWidth + (x) show % "x" + 10 pageHeight 25.4 mul NUMBER % pageHeight + (mm) show % "mm" + + % Lower-left inches + pageHeight 2 mul sub % Move down... + + 2 copy moveto % Move to x & y + (Lower-Left: ) RIGHT % Label + 100 pageLeft NUMBER % pageLeft + (x) show % "x" + 100 pageBottom NUMBER % pageBottom + (in) show % "in" + + % Lower-left millimeters + pageHeight sub % Move down... + + 2 copy moveto % Move to x & y + 10 pageLeft 25.4 mul NUMBER % pageLeft + (x) show % "x" + 10 pageBottom 25.4 mul NUMBER % pageBottom + (mm) show % "mm" + + % Upper-right inches + pageHeight 2 mul sub % Move down... + + 2 copy moveto % Move to x & y + (Upper-Right: ) RIGHT % Label + 100 pageRight NUMBER % pageRight + (x) show % "x" + 100 pageTop NUMBER % pageTop + (in) show % "in" + + % Upper-right millimeters + pageHeight sub % Move down... + + 2 copy moveto % Move to x & y + 10 pageRight 25.4 mul NUMBER % pageRight + (x) show % "x" + 10 pageTop 25.4 mul NUMBER % pageTop + (mm) show % "mm" + + % Resolution dots-per-inch + pageHeight 2 mul sub % Move down... + + 2 copy moveto % Move to x & y + (Resolution: ) RIGHT % Label + 1 xResolution NUMBER % xResolution + (x) show % "x" + 1 yResolution NUMBER % yResolution + (dpi) show % "dpi" + + % Resolution dots-per-meter + pageHeight sub % Move down... + + moveto % Move to x & y + 1 xResolution 39.27 mul NUMBER % xResolution + (x) show % "x" + 1 yResolution 39.27 mul NUMBER % yResolution + (dpm) show % "dpm" + + % Interpreter Information... + pageHeight 15 mul % Height of interpreter information + + pageWidth 40.5 mul % x = pageWidth * 9/16 * 72 + pageHeight 35.5 mul % y = pageHeight * 1/2 * 72 + 2 index sub % y -= height + pageWidth 28 mul % width = pageWidth * 1/4 * 72 + 3 index % height + 0.5 setgray rectfill % Draw a shadow + + pageWidth 40 mul % x = pageWidth * 9/16 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + 2 index sub % y -= height + pageWidth 28 mul % width = pageWidth * 3/8 * 72 + 3 index % height + 4 copy 1 setgray rectfill % Clear the box to white + 0 setgray rectstroke % Draw a black box around it... + + pop % Discard height + + % Label the interpreter info... + pageWidth 40 mul % x = pageWidth * 9/16 * 72 + pageHeight 37 mul % y = pageHeight * 1/2 * 72 + moveto % Position the text + mediumFont setfont % Font + (Interpreter Information) show % Show the text + + smallFont setfont % Font + pageWidth 49 mul % x = pageWidth * 11/16 * 72 + pageHeight 36 mul % y = pageWidth * 1/2 * 72 + pageHeight 2 mul sub % y -= 2 * smallFont height + + % Language level + 2 copy moveto % Move to x & y + (PostScript: ) RIGHT % Label + (Level ) show % "Level " + 1 languagelevel NUMBER % Language level + + % Version + pageHeight 2 mul sub % Move down... + 2 copy moveto % Move to x & y + (Version: ) RIGHT % Label + version show % Version + ( \() show % " (" + 1 revision NUMBER % Revision + (\)) show % ")" + + % Product + pageHeight 2 mul sub % Move down... + 2 copy moveto % Move to x & y + (Product: ) RIGHT % Label + product show % Product name + + % Serial Number + pageHeight 2 mul sub % Move down... + 2 copy moveto % Move to x & y + (Serial #: ) RIGHT % Label + 1 serialnumber NUMBER % S/N + + % Draw the label at the top... + pageWidth 36 mul % Center of page + pageHeight 68 mul % Top of page (15/16ths) + 2 copy moveto % Position text + bigFont setfont % Font + (Printer Test Page) CENTER % Show text centered + + % Draw the copyright notice at the bottom... + pageWidth 36 mul % Center of page + pageHeight 10 mul % Bottom of page + 2 copy moveto % Position text + (Printed Using CUPS v1.1.x) CENTER % Show text centered + + pageHeight 2 mul sub % Move down... + 2 copy moveto % Position text + smallFont setfont % Font + (Copyright 1993-2000 Easy Software Products, All Rights Reserved.) CENTER + pageHeight sub % Move down... + 2 copy moveto % Position text + (CUPS, and the CUPS logo are the trademark property of) CENTER + pageHeight sub % Move down... + 2 copy moveto % Position text + (Easy Software Products, 44141 Airport View Drive, Suite 204,) CENTER + pageHeight sub % Move down... + 2 copy moveto % Position text + (Hollywood, Maryland, 20636-3111, USA.) CENTER + + % Then the CUPS logo.... + gsave + pageWidth 4 mul + pageHeight 4 mul + translate + pageWidth 9 mul CUPSLOGO + grestore + + % And the ESP logo.... + gsave + pageWidth 59 mul + pageHeight 4 mul + translate + pageWidth 6 mul ESPLOGO + grestore +% Show the page... +grestore +showpage +% +% End of "$Id: testprint.ps 1379 2000-09-18 17:12:42Z mike $". +% +%%EOF diff --git a/data/topsecret b/data/topsecret new file mode 100644 index 0000000000..1b178d8fe9 --- /dev/null +++ b/data/topsecret @@ -0,0 +1,267 @@ +%!PS-Adobe-3.0 +%%BoundingBox: 0 0 612 792 +%%Pages: 1 +%%LanguageLevel: 1 +%%DocumentData: Clean7Bit +%%DocumentSuppliedResources: procset bannerprint/1.0 +%%DocumentNeededResources: font Helvetica Helvetica-Bold Times-Roman +%%Creator: Michael Sweet, Easy Software Products +%%CreationDate: May 10, 2000 +%%Title: Test Page +%%EndComments +%%BeginProlog +%%BeginResource procset bannerprint 1.1 0 +% +% PostScript banner page for the Common UNIX Printing System ("CUPS"). +% +% Copyright 1993-2000 Easy Software Products +% +% These coded instructions, statements, and computer programs contain +% unpublished proprietary information of Easy Software Products, and +% are protected by Federal copyright law. They may not be disclosed +% to third parties or copied or duplicated in any form, in whole or +% in part, without the prior written consent of Easy Software Products. +% +/CENTER { % Draw centered text + % (name) CENTER - + dup stringwidth pop % Get the width of the string + 0.5 mul neg 0 rmoveto % Shift left 1/2 of the distance + show % Show the string +} bind def +/RIGHT { % Draw right-justified text + % (name) RIGHT - + dup stringwidth pop % Get the width of the string + neg 0 rmoveto % Shift left the entire distance + show % Show the string +} bind def +/NUMBER { % Draw a number + % power n NUMBER - + 1 index 1 eq { % power == 1? + round cvi exch pop % Convert "n" to integer + } { + 1 index mul round exch div % Truncate extra decimal places + } ifelse + 100 string cvs show % Convert to a string and show it... +} bind def +/CUPSLOGO { % Draw the CUPS logo + % height CUPSLOGO + % Start with a big C... + /Helvetica findfont 1 index scalefont setfont + 0 setgray + 0 0 moveto + (C) show + + % Then "UNIX Printing System" much smaller... + /Helvetica-Bold findfont 1 index 9 div scalefont setfont + 0.25 mul + dup dup 2.0 mul moveto + (UNIX) show + dup dup 1.6 mul moveto + (Printing) show + dup 1.2 mul moveto + (System) show +} bind def +/ESPLOGO { % Draw the ESP logo + % height ESPLOGO + % Compute the size of the logo... + 0 0 + 2 index 1.5 mul 3 index + + % Do the "metallic" fill from 10% black to 40% black... + 1 -0.001 0 { + dup % loopval + -0.15 mul % loopval * -0.15 + 0.9 add % 0.9 - loopval * 0.15 + setgray % set gray shade + + 0 % x + 1 index neg % loopval + 1 add % 1 - loopval + 3 index % height + mul % height * (1 - loopval) + moveto % starting point + + dup % loopval + 3 index % width + mul % loopval * width + 2 index % height + lineto % Next point + + 0 % x + 2 index % height + lineto % Next point + + closepath + fill + + dup % loopval + 0.15 mul % loopval * 0.15 + 0.6 add % 0.6 + loopval * 0.15 + setgray + + dup % loopval + neg 1 add % 1 - loopval + 3 index % width + mul % (1 - loopval) * width + 0 % y + moveto % Starting point + + 2 index % width + exch % loopval + 2 index % height + mul % loopval * height + lineto % Next point + + 1 index % width + 0 % y + lineto % Next point + + closepath + fill + } for + + 0 setgray rectstroke + + /Helvetica-BoldOblique findfont 1 index 3 div scalefont setfont + dup 40 div + + dup 4 mul 1 index 25 mul moveto (E) show + dup 10 mul 1 index 15 mul moveto (S) show + dup 16 mul 1 index 5 mul moveto (P) show + + /Helvetica-BoldOblique findfont 2 index 5 div scalefont setfont + dup 14 mul 1 index 29 mul moveto (asy) show + dup 20 mul 1 index 19 mul moveto (oftware) show + dup 26 mul 1 index 9 mul moveto (roducts) show + + pop +} bind def +%%EndResource +%%EndProlog +%%Page: 1 1 +gsave + + % Determine the imageable area and device resolution... + initclip newpath clippath pathbbox % Get bounding rectangle + 72 div /pageTop exch def % Get top margin in inches + 72 div /pageRight exch def % Get right margin in inches + 72 div /pageBottom exch def % Get bottom margin in inches + 72 div /pageLeft exch def % Get left margin in inches + + /pageWidth pageRight pageLeft sub def % pageWidth = pageRight - pageLeft + /pageHeight pageTop pageBottom sub def% pageHeight = pageTop - pageBottom + + /boxWidth % width of text box + pageWidth pageHeight lt + { pageWidth 54 mul } + { pageHeight 42 mul } + ifelse def + + newpath % Clear bounding path + + % Create fonts... + /bigFont /Helvetica-Bold findfont % bigFont = Helvetica-Bold + pageHeight 3 mul scalefont def % size = pageHeight * 3 (nominally 33) + + /mediumFont /Helvetica findfont % mediumFont = Helvetica + pageHeight 1.5 mul scalefont def % size = pageHeight * 1.5 (nominally 16.5) + + % Offset page to account for lower-left margin... + pageLeft 72 mul + pageBottom 72 mul + translate + + % Draw the label at the top and bottom... + 0 setgray % Color + + pageWidth 36 mul % Center of page + pageHeight 72 mul % Top of page + pageWidth -7 mul add % - 2 lines + moveto % Position text + bigFont setfont % Font + (Top Secret) CENTER % Show text centered + + pageWidth 36 mul % Center of page + pageHeight 6 mul % Bottom of page + moveto % Position text + bigFont setfont % Font + (Top Secret) CENTER % Show text centered + + % Job information box... + pageWidth 36 mul 9 add % x = pageWidth * 1/2 * 72 + 9 + boxWidth 0.5 mul sub % x-= 1/2 box width + pageHeight 30 mul 9 sub % y = pageHeight * 1/2 * 72 - 9 + boxWidth % w = box width + pageHeight 14 mul % h = pageHeight * 1/2 * 72 + 0.5 setgray rectfill % Draw a shadow + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + boxWidth 0.5 mul sub % x-= 1/2 box width + pageHeight 30 mul % y = pageHeight * 1/4 * 72 + boxWidth % w = box width + pageHeight 14 mul % h = pageHeight * 1/2 * 72 + + 4 copy 1 setgray rectfill % Clear the box to white + 0 setgray rectstroke % Draw a black box around it... + + % Job information text... + mediumFont setfont % Medium sized font + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight 5 mul add % y += 2 lines + 2 copy % Copy X & Y + moveto + (Job ID: ) RIGHT + moveto + ({printer-name}-{job-id}) show + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight 2 mul add % y += 1 line + 2 copy % Copy X & Y + moveto + (Title: ) RIGHT + moveto + ({job-name}) show + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight -1 mul add % y -= 1 line + 2 copy % Copy X & Y + moveto + (Requesting User: ) RIGHT + moveto + ({job-originating-user-name}) show + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight -4 mul add % y -= 2 lines + 2 copy % Copy X & Y + moveto + (Billing Info: ) RIGHT + moveto + ({job-billing}) show + + % Then the CUPS logo.... + gsave + pageWidth 4 mul + pageWidth 6 mul + translate + pageWidth 9 mul CUPSLOGO + grestore + + % And the ESP logo.... + gsave + pageWidth 59 mul + pageWidth 6 mul + translate + pageWidth 6 mul ESPLOGO + grestore +% Show the page... +grestore +showpage +% +% End of "$Id: topsecret 1379 2000-09-18 17:12:42Z mike $". +% +%%EOF diff --git a/data/unclassified b/data/unclassified new file mode 100644 index 0000000000..2631b5ece3 --- /dev/null +++ b/data/unclassified @@ -0,0 +1,267 @@ +%!PS-Adobe-3.0 +%%BoundingBox: 0 0 612 792 +%%Pages: 1 +%%LanguageLevel: 1 +%%DocumentData: Clean7Bit +%%DocumentSuppliedResources: procset bannerprint/1.0 +%%DocumentNeededResources: font Helvetica Helvetica-Bold Times-Roman +%%Creator: Michael Sweet, Easy Software Products +%%CreationDate: May 10, 2000 +%%Title: Test Page +%%EndComments +%%BeginProlog +%%BeginResource procset bannerprint 1.1 0 +% +% PostScript banner page for the Common UNIX Printing System ("CUPS"). +% +% Copyright 1993-2000 Easy Software Products +% +% These coded instructions, statements, and computer programs contain +% unpublished proprietary information of Easy Software Products, and +% are protected by Federal copyright law. They may not be disclosed +% to third parties or copied or duplicated in any form, in whole or +% in part, without the prior written consent of Easy Software Products. +% +/CENTER { % Draw centered text + % (name) CENTER - + dup stringwidth pop % Get the width of the string + 0.5 mul neg 0 rmoveto % Shift left 1/2 of the distance + show % Show the string +} bind def +/RIGHT { % Draw right-justified text + % (name) RIGHT - + dup stringwidth pop % Get the width of the string + neg 0 rmoveto % Shift left the entire distance + show % Show the string +} bind def +/NUMBER { % Draw a number + % power n NUMBER - + 1 index 1 eq { % power == 1? + round cvi exch pop % Convert "n" to integer + } { + 1 index mul round exch div % Truncate extra decimal places + } ifelse + 100 string cvs show % Convert to a string and show it... +} bind def +/CUPSLOGO { % Draw the CUPS logo + % height CUPSLOGO + % Start with a big C... + /Helvetica findfont 1 index scalefont setfont + 0 setgray + 0 0 moveto + (C) show + + % Then "UNIX Printing System" much smaller... + /Helvetica-Bold findfont 1 index 9 div scalefont setfont + 0.25 mul + dup dup 2.0 mul moveto + (UNIX) show + dup dup 1.6 mul moveto + (Printing) show + dup 1.2 mul moveto + (System) show +} bind def +/ESPLOGO { % Draw the ESP logo + % height ESPLOGO + % Compute the size of the logo... + 0 0 + 2 index 1.5 mul 3 index + + % Do the "metallic" fill from 10% black to 40% black... + 1 -0.001 0 { + dup % loopval + -0.15 mul % loopval * -0.15 + 0.9 add % 0.9 - loopval * 0.15 + setgray % set gray shade + + 0 % x + 1 index neg % loopval + 1 add % 1 - loopval + 3 index % height + mul % height * (1 - loopval) + moveto % starting point + + dup % loopval + 3 index % width + mul % loopval * width + 2 index % height + lineto % Next point + + 0 % x + 2 index % height + lineto % Next point + + closepath + fill + + dup % loopval + 0.15 mul % loopval * 0.15 + 0.6 add % 0.6 + loopval * 0.15 + setgray + + dup % loopval + neg 1 add % 1 - loopval + 3 index % width + mul % (1 - loopval) * width + 0 % y + moveto % Starting point + + 2 index % width + exch % loopval + 2 index % height + mul % loopval * height + lineto % Next point + + 1 index % width + 0 % y + lineto % Next point + + closepath + fill + } for + + 0 setgray rectstroke + + /Helvetica-BoldOblique findfont 1 index 3 div scalefont setfont + dup 40 div + + dup 4 mul 1 index 25 mul moveto (E) show + dup 10 mul 1 index 15 mul moveto (S) show + dup 16 mul 1 index 5 mul moveto (P) show + + /Helvetica-BoldOblique findfont 2 index 5 div scalefont setfont + dup 14 mul 1 index 29 mul moveto (asy) show + dup 20 mul 1 index 19 mul moveto (oftware) show + dup 26 mul 1 index 9 mul moveto (roducts) show + + pop +} bind def +%%EndResource +%%EndProlog +%%Page: 1 1 +gsave + + % Determine the imageable area and device resolution... + initclip newpath clippath pathbbox % Get bounding rectangle + 72 div /pageTop exch def % Get top margin in inches + 72 div /pageRight exch def % Get right margin in inches + 72 div /pageBottom exch def % Get bottom margin in inches + 72 div /pageLeft exch def % Get left margin in inches + + /pageWidth pageRight pageLeft sub def % pageWidth = pageRight - pageLeft + /pageHeight pageTop pageBottom sub def% pageHeight = pageTop - pageBottom + + /boxWidth % width of text box + pageWidth pageHeight lt + { pageWidth 54 mul } + { pageHeight 42 mul } + ifelse def + + newpath % Clear bounding path + + % Create fonts... + /bigFont /Helvetica-Bold findfont % bigFont = Helvetica-Bold + pageHeight 3 mul scalefont def % size = pageHeight * 3 (nominally 33) + + /mediumFont /Helvetica findfont % mediumFont = Helvetica + pageHeight 1.5 mul scalefont def % size = pageHeight * 1.5 (nominally 16.5) + + % Offset page to account for lower-left margin... + pageLeft 72 mul + pageBottom 72 mul + translate + + % Draw the label at the top and bottom... + 0 setgray % Color + + pageWidth 36 mul % Center of page + pageHeight 72 mul % Top of page + pageWidth -7 mul add % - 2 lines + moveto % Position text + bigFont setfont % Font + (Unclassified) CENTER % Show text centered + + pageWidth 36 mul % Center of page + pageHeight 6 mul % Bottom of page + moveto % Position text + bigFont setfont % Font + (Unclassified) CENTER % Show text centered + + % Job information box... + pageWidth 36 mul 9 add % x = pageWidth * 1/2 * 72 + 9 + boxWidth 0.5 mul sub % x-= 1/2 box width + pageHeight 30 mul 9 sub % y = pageHeight * 1/2 * 72 - 9 + boxWidth % w = box width + pageHeight 14 mul % h = pageHeight * 1/2 * 72 + 0.5 setgray rectfill % Draw a shadow + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + boxWidth 0.5 mul sub % x-= 1/2 box width + pageHeight 30 mul % y = pageHeight * 1/4 * 72 + boxWidth % w = box width + pageHeight 14 mul % h = pageHeight * 1/2 * 72 + + 4 copy 1 setgray rectfill % Clear the box to white + 0 setgray rectstroke % Draw a black box around it... + + % Job information text... + mediumFont setfont % Medium sized font + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight 5 mul add % y += 2 lines + 2 copy % Copy X & Y + moveto + (Job ID: ) RIGHT + moveto + ({printer-name}-{job-id}) show + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight 2 mul add % y += 1 line + 2 copy % Copy X & Y + moveto + (Title: ) RIGHT + moveto + ({job-name}) show + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight -1 mul add % y -= 1 line + 2 copy % Copy X & Y + moveto + (Requesting User: ) RIGHT + moveto + ({job-originating-user-name}) show + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight -4 mul add % y -= 2 lines + 2 copy % Copy X & Y + moveto + (Billing Info: ) RIGHT + moveto + ({job-billing}) show + + % Then the CUPS logo.... + gsave + pageWidth 4 mul + pageWidth 6 mul + translate + pageWidth 9 mul CUPSLOGO + grestore + + % And the ESP logo.... + gsave + pageWidth 59 mul + pageWidth 6 mul + translate + pageWidth 6 mul ESPLOGO + grestore +% Show the page... +grestore +showpage +% +% End of "$Id: unclassified 1379 2000-09-18 17:12:42Z mike $". +% +%%EOF diff --git a/data/utf-8 b/data/utf-8 new file mode 100644 index 0000000000..e808223a06 --- /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 within each group, with 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/data/windows-1250 b/data/windows-1250 new file mode 100644 index 0000000000..afcc62ed5f --- /dev/null +++ b/data/windows-1250 @@ -0,0 +1,254 @@ +charset 8bit + +# +# This file defines the font and character mappings used for Windows +# Code Page 1250 (WinLatin2) 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. +# + +00 ff 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 +7F 007F +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 +9C 015B +9D 0165 +9E 017E +9F 017A +A0 00A0 +A1 02C7 +A2 02D8 +A3 0141 +A4 00A4 +A5 0104 +A6 00A6 +A7 00A7 +A8 00A8 +A9 00A9 +AA 015E +AB 00AB +AC 00AC +AD 00AD +AE 00AE +AF 017B +B0 00B0 +B1 00B1 +B2 02DB +B3 0142 +B4 00B4 +B5 00B5 +B6 00B6 +B7 00B7 +B8 00B8 +B9 0105 +BA 015F +BB 00BB +BC 013D +BD 02DD +BE 013E +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/windows-1251 b/data/windows-1251 new file mode 100644 index 0000000000..6d31dee09c --- /dev/null +++ b/data/windows-1251 @@ -0,0 +1,258 @@ +charset 8bit + +# +# This file defines the font and character mappings used for Windows +# Code Page 1251 (WinCyrillic) 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. +# + +00 ff 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 +7F 007F +80 0402 +81 0403 +82 201A +83 0453 +84 201E +85 2026 +86 2020 +87 2021 +88 20AC +89 2030 +8A 0409 +8B 2039 +8C 040A +8D 040C +8E 040B +8F 040F +90 0452 +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +99 2122 +9A 0459 +9B 203A +9C 045A +9D 045C +9E 045B +9F 045F +A0 00A0 +A1 040E +A2 045E +A3 0408 +A4 00A4 +A5 0490 +A6 00A6 +A7 00A7 +A8 0401 +A9 00A9 +AA 0404 +AB 00AB +AC 00AC +AD 00AD +AE 00AE +AF 0407 +B0 00B0 +B1 00B1 +B2 0406 +B3 0456 +B4 0491 +B5 00B5 +B6 00B6 +B7 00B7 +B8 0451 +B9 2116 +BA 0454 +BB 00BB +BC 0458 +BD 0405 +BE 0455 +BF 0457 +C0 0410 +C1 0411 +C2 0412 +C3 0413 +C4 0414 +C5 0415 +C6 0416 +C7 0417 +C8 0418 +C9 0419 +CA 041A +CB 041B +CC 041C +CD 041D +CE 041E +CF 041F +D0 0420 +D1 0421 +D2 0422 +D3 0423 +D4 0424 +D5 0425 +D6 0426 +D7 0427 +D8 0428 +D9 0429 +DA 042A +DB 042B +DC 042C +DD 042D +DE 042E +DF 042F +E0 0430 +E1 0431 +E2 0432 +E3 0433 +E4 0434 +E5 0435 +E6 0436 +E7 0437 +E8 0438 +E9 0439 +EA 043A +EB 043B +EC 043C +ED 043D +EE 043E +EF 043F +F0 0440 +F1 0441 +F2 0442 +F3 0443 +F4 0444 +F5 0445 +F6 0446 +F7 0447 +F8 0448 +F9 0449 +FA 044A +FB 044B +FC 044C +FD 044D +FE 044E +FF 044F diff --git a/data/windows-1252 b/data/windows-1252 new file mode 100644 index 0000000000..a98595874d --- /dev/null +++ b/data/windows-1252 @@ -0,0 +1,254 @@ +charset 8bit + +# +# This file defines the font and character mappings used for Windows +# Code Page 1252 (WinLatin1) 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. +# + +00 ff 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 +7F 007F +80 20AC +82 201A +83 0192 +84 201E +85 2026 +86 2020 +87 2021 +88 02C6 +89 2030 +8A 0160 +8B 2039 +8C 0152 +8E 017D +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +98 02DC +99 2122 +9A 0161 +9B 203A +9C 0153 +9E 017E +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/windows-1253 b/data/windows-1253 new file mode 100644 index 0000000000..c736ecd6c8 --- /dev/null +++ b/data/windows-1253 @@ -0,0 +1,243 @@ +charset 8bit + +# +# This file defines the font and character mappings used for Windows +# Code Page 1253 (WinGreek) 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. +# + +00 9f ltor single Courier Courier-Bold Courier-Italic Courier-BoldItalic +a0 ff ltor single Symbol + +# +# 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 +7F 007F +80 20AC +82 201A +83 0192 +84 201E +85 2026 +86 2020 +87 2021 +89 2030 +8B 2039 +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +99 2122 +9B 203A +A0 00A0 +A1 0385 +A2 0386 +A3 00A3 +A4 00A4 +A5 00A5 +A6 00A6 +A7 00A7 +A8 00A8 +A9 00A9 +AB 00AB +AC 00AC +AD 00AD +AE 00AE +AF 2015 +B0 00B0 +B1 00B1 +B2 00B2 +B3 00B3 +B4 0384 +B5 00B5 +B6 00B6 +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/windows-1254 b/data/windows-1254 new file mode 100644 index 0000000000..87fff2db7e --- /dev/null +++ b/data/windows-1254 @@ -0,0 +1,252 @@ +charset 8bit + +# +# This file defines the font and character mappings used for Windows +# Code Page 1254 (WinTurkish) 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. +# + +00 ff 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 +7F 007F +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/windows-1255 b/data/windows-1255 new file mode 100644 index 0000000000..a8b26a85d9 --- /dev/null +++ b/data/windows-1255 @@ -0,0 +1,236 @@ +charset 8bit + +# +# This file defines the font and character mappings used for Windows +# Code Page 1255 (WinHebrew) 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. +# + +00 ff 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 +7F 007F +80 20AC +82 201A +83 0192 +84 201E +85 2026 +86 2020 +87 2021 +88 02C6 +89 2030 +8B 2039 +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +98 02DC +99 2122 +9B 203A +A0 00A0 +A1 00A1 +A2 00A2 +A3 00A3 +A4 20AA +A5 00A5 +A6 00A6 +A7 00A7 +A8 00A8 +A9 00A9 +AA 00D7 +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 00F7 +BB 00BB +BC 00BC +BD 00BD +BE 00BE +BF 00BF +C0 05B0 +C1 05B1 +C2 05B2 +C3 05B3 +C4 05B4 +C5 05B5 +C6 05B6 +C7 05B7 +C8 05B8 +C9 05B9 +CB 05BB +CC 05BC +CD 05BD +CE 05BE +CF 05BF +D0 05C0 +D1 05C1 +D2 05C2 +D3 05C3 +D4 05F0 +D5 05F1 +D6 05F2 +D7 05F3 +D8 05F4 +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 +FD 200E +FE 200F diff --git a/data/windows-1256 b/data/windows-1256 new file mode 100644 index 0000000000..6908f1eb5a --- /dev/null +++ b/data/windows-1256 @@ -0,0 +1,259 @@ +charset 8bit + +# +# This file defines the font and character mappings used for Windows +# Code Page 1256 (WinArabic) 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. +# + +00 ff 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 +7F 007F +80 20AC +81 067E +82 201A +83 0192 +84 201E +85 2026 +86 2020 +87 2021 +88 02C6 +89 2030 +8A 0679 +8B 2039 +8C 0152 +8D 0686 +8E 0698 +8F 0688 +90 06AF +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +98 06A9 +99 2122 +9A 0691 +9B 203A +9C 0153 +9D 200C +9E 200D +9F 06BA +A0 00A0 +A1 060C +A2 00A2 +A3 00A3 +A4 00A4 +A5 00A5 +A6 00A6 +A7 00A7 +A8 00A8 +A9 00A9 +AA 06BE +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 061B +BB 00BB +BC 00BC +BD 00BD +BE 00BE +BF 061F +C0 06C1 +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 00D7 +D8 0637 +D9 0638 +DA 0639 +DB 063A +DC 0640 +DD 0641 +DE 0642 +DF 0643 +E0 00E0 +E1 0644 +E2 00E2 +E3 0645 +E4 0646 +E5 0647 +E6 0648 +E7 00E7 +E8 00E8 +E9 00E9 +EA 00EA +EB 00EB +EC 0649 +ED 064A +EE 00EE +EF 00EF +F0 064B +F1 064C +F2 064D +F3 064E +F4 00F4 +F5 064F +F6 0650 +F7 00F7 +F8 0651 +F9 00F9 +FA 0652 +FB 00FB +FC 00FC +FD 200E +FE 200F +FF 06D2 diff --git a/data/windows-1257 b/data/windows-1257 new file mode 100644 index 0000000000..ac5f8e0b7c --- /dev/null +++ b/data/windows-1257 @@ -0,0 +1,247 @@ +charset 8bit + +# +# This file defines the font and character mappings used for Windows +# Code Page 1257 (WinBaltic) 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. +# + +00 ff 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 +7F 007F +80 20AC +82 201A +84 201E +85 2026 +86 2020 +87 2021 +89 2030 +8B 2039 +8D 00A8 +8E 02C7 +8F 00B8 +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +99 2122 +9B 203A +9D 00AF +9E 02DB +A0 00A0 +A2 00A2 +A3 00A3 +A4 00A4 +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 00B4 +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 02D9 diff --git a/data/windows-1258 b/data/windows-1258 new file mode 100644 index 0000000000..f7721c51b1 --- /dev/null +++ b/data/windows-1258 @@ -0,0 +1,250 @@ +charset 8bit + +# +# This file defines the font and character mappings used for Windows +# Code Page 1258 (WinVietnamese) 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. +# + +00 ff 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 +7F 007F +80 20AC +82 201A +83 0192 +84 201E +85 2026 +86 2020 +87 2021 +88 02C6 +89 2030 +8B 2039 +8C 0152 +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +98 02DC +99 2122 +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 0102 +C4 00C4 +C5 00C5 +C6 00C6 +C7 00C7 +C8 00C8 +C9 00C9 +CA 00CA +CB 00CB +CC 0300 +CD 00CD +CE 00CE +CF 00CF +D0 0110 +D1 00D1 +D2 0309 +D3 00D3 +D4 00D4 +D5 01A0 +D6 00D6 +D7 00D7 +D8 00D8 +D9 00D9 +DA 00DA +DB 00DB +DC 00DC +DD 01AF +DE 0303 +DF 00DF +E0 00E0 +E1 00E1 +E2 00E2 +E3 0103 +E4 00E4 +E5 00E5 +E6 00E6 +E7 00E7 +E8 00E8 +E9 00E9 +EA 00EA +EB 00EB +EC 0301 +ED 00ED +EE 00EE +EF 00EF +F0 0111 +F1 00F1 +F2 0323 +F3 00F3 +F4 00F4 +F5 01A1 +F6 00F6 +F7 00F7 +F8 00F8 +F9 00F9 +FA 00FA +FB 00FB +FC 00FC +FD 01B0 +FE 20AB +FF 00FF diff --git a/data/windows-874 b/data/windows-874 new file mode 100644 index 0000000000..886e46a4b4 --- /dev/null +++ b/data/windows-874 @@ -0,0 +1,228 @@ +charset 8bit + +# +# This file defines the font and character mappings used for Windows +# Code Page 874 (Thai) 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. +# + +00 ff 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 +7F 007F +80 20AC +85 2026 +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +A0 00A0 +A1 0E01 +A2 0E02 +A3 0E03 +A4 0E04 +A5 0E05 +A6 0E06 +A7 0E07 +A8 0E08 +A9 0E09 +AA 0E0A +AB 0E0B +AC 0E0C +AD 0E0D +AE 0E0E +AF 0E0F +B0 0E10 +B1 0E11 +B2 0E12 +B3 0E13 +B4 0E14 +B5 0E15 +B6 0E16 +B7 0E17 +B8 0E18 +B9 0E19 +BA 0E1A +BB 0E1B +BC 0E1C +BD 0E1D +BE 0E1E +BF 0E1F +C0 0E20 +C1 0E21 +C2 0E22 +C3 0E23 +C4 0E24 +C5 0E25 +C6 0E26 +C7 0E27 +C8 0E28 +C9 0E29 +CA 0E2A +CB 0E2B +CC 0E2C +CD 0E2D +CE 0E2E +CF 0E2F +D0 0E30 +D1 0E31 +D2 0E32 +D3 0E33 +D4 0E34 +D5 0E35 +D6 0E36 +D7 0E37 +D8 0E38 +D9 0E39 +DA 0E3A +DF 0E3F +E0 0E40 +E1 0E41 +E2 0E42 +E3 0E43 +E4 0E44 +E5 0E45 +E6 0E46 +E7 0E47 +E8 0E48 +E9 0E49 +EA 0E4A +EB 0E4B +EC 0E4C +ED 0E4D +EE 0E4E +EF 0E4F +F0 0E50 +F1 0E51 +F2 0E52 +F3 0E53 +F4 0E54 +F5 0E55 +F6 0E56 +F7 0E57 +F8 0E58 +F9 0E59 +FA 0E5A +FB 0E5B diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 0000000000..07bb917fd9 --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,230 @@ +# +# "$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 .ps .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 $@ $< +.shtml.ps: + echo Formatting $@... + htmldoc --titleimage images/cups-large.gif --duplex --numbered \ + --jpeg -f $@ $< + + +# +# Document files... +# + +DOCUMENTS = cmp.shtml idd.shtml ipp.shtml sam.shtml sdd.shtml \ + spm.shtml sps.shtml ssr.shtml stp.shtml sum.shtml \ + svd.shtml +DOCIMAGES = images/cups-block-diagram.gif images/cups-large.gif \ + images/cups-medium.gif images/cups-small.gif +WEBPAGES = cups.css cupsdoc.css index.html documentation.html +WEBIMAGES = images/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/config-printer.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/restart-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 + + +# +# Make PS files... +# + +ps: $(DOCUMENTS:.shtml=.ps) overview.ps + + +# +# Remove all generated files... +# + +clean: + $(RM) $(DOCUMENTS:.shtml=.pdf) + $(RM) $(DOCUMENTS:.shtml=.html) + $(RM) overview.pdf + + +# +# Install all documentation files... +# + +install: + -$(MKDIR) $(DOCDIR) + $(CHMOD) ugo+rx $(DOCDIR) + $(INSTALL_MAN) $(WEBPAGES) $(DOCDIR) + $(INSTALL_MAN) overview.html overview.pdf $(DOCDIR) + $(INSTALL_MAN) $(DOCUMENTS:.shtml=.html) $(DOCDIR) + $(INSTALL_MAN) $(DOCUMENTS:.shtml=.pdf) $(DOCDIR) + -$(MKDIR) $(DOCDIR)/images + $(CHMOD) ugo+rx $(DOCDIR)/images + $(INSTALL_MAN) $(WEBIMAGES) $(DOCDIR)/images + $(INSTALL_MAN) $(DOCIMAGES) $(DOCDIR)/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 +overview.ps: overview.html + echo Formatting $@... + htmldoc --duplex --jpeg --webpage -f overview.ps 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 $@ $< +sam.ps: sam.shtml + echo Formatting $@... + htmldoc --titleimage images/cups-large.gif --duplex --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 $@ $< +spm.ps: spm.shtml + echo Formatting $@... + htmldoc --titleimage images/cups-large.gif --duplex --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 $@ $< +sum.ps: sum.shtml + echo Formatting $@... + htmldoc --titleimage images/cups-large.gif --duplex --jpeg -f $@ $< + +sam-7x8.pdf: sam.shtml + echo Formatting $@... + htmldoc --titleimage images/cups-large.gif --duplex --compression=9 \ + --pagelayout tworight --pagemode document \ + --jpeg --size 7x8.5in --left 0.5in --right 0.25in \ + --top 0.25in --bottom 0.25in --fontsize 10 --headfootsize 10 -f $@ sam.shtml +sam-7x8.ps: sam.shtml + echo Formatting $@... + htmldoc --titleimage images/cups-large.gif --duplex --jpeg \ + --size 7x8.5in --left 0.5in --right 0.25in \ + --top 0.25in --bottom 0.25in --fontsize 10 --headfootsize 10 -f $@ sam.shtml +spm-7x8.pdf: spm.shtml + echo Formatting $@... + htmldoc --titleimage images/cups-large.gif --duplex --compression=9 \ + --pagelayout tworight --pagemode document \ + --jpeg --size 7x8.5in --left 0.5in --right 0.25in \ + --top 0.25in --bottom 0.25in --fontsize 10 --headfootsize 10 -f $@ spm.shtml +spm-7x8.ps: spm.shtml + echo Formatting $@... + htmldoc --titleimage images/cups-large.gif --duplex --jpeg \ + --size 7x8.5in --left 0.5in --right 0.25in \ + --top 0.25in --bottom 0.25in --fontsize 10 --headfootsize 10 -f $@ spm.shtml +sum-7x8.pdf: sum.shtml + echo Formatting $@... + htmldoc --titleimage images/cups-large.gif --duplex --compression=9 \ + --pagelayout tworight --pagemode document \ + --jpeg --size 7x8.5in --left 0.5in --right 0.25in \ + --top 0.25in --bottom 0.25in --fontsize 10 --headfootsize 10 -f $@ sum.shtml +sum-7x8.ps: sum.shtml + echo Formatting $@... + htmldoc --titleimage images/cups-large.gif --duplex --jpeg \ + --size 7x8.5in --left 0.5in --right 0.25in \ + --top 0.25in --bottom 0.25in --fontsize 10 --headfootsize 10 -f $@ sum.shtml + +$(DOCUMENTS:.shtml=.html): \ + glossary.shtml printing-overview.shtml \ + references.shtml system-overview.shtml \ + ../LICENSE.html + +$(DOCUMENTS:.shtml=.pdf): \ + glossary.shtml printing-overview.shtml \ + references.shtml system-overview.shtml \ + ../LICENSE.html + +$(DOCUMENTS:.shtml=.ps): \ + glossary.shtml printing-overview.shtml \ + references.shtml system-overview.shtml \ + ../LICENSE.html + + +# +# End of Makefile. +# diff --git a/doc/cmp.html b/doc/cmp.html new file mode 100644 index 0000000000..173b66b848 --- /dev/null +++ b/doc/cmp.html @@ -0,0 +1,746 @@ + + + + CUPS Configuration Management Plan + + + + + + + +

+

CUPS Configuration Management Plan


+CUPS-CMP-1.1
+Easy Software Products
+Copyright 1997-2000, 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 maintenance of +the Common UNIX Printing System ("CUPS") Version +1.1 software. +

1.2 System Overview

+

CUPS provides a portable printing layer for +UNIX®-based 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 ("IPP") +as the basis for managing print jobs and +queues. The Line Printer Daemon ("LPD") Server +Message Block ("SMB"), and AppSocket (a.k.a. +JetDirect) protocols are also supported with reduced +functionality. CUPS adds network printer browsing and +PostScript Printer Description ("PPD") based printing +options to support real-world printing under UNIX.

+

CUPS also includes a customized version of GNU +Ghostscript (currently based off GNU Ghostscript +5.50) and an image file RIP that are used to +support non-PostScript printers. Sample drivers for +HP and EPSON printers are included that use +these filters.

+

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.1: CUPS Configuration Management Plan
  • +
  • CUPS-IDD-1.1: CUPS System Interface Design +Description
  • +
  • CUPS-IPP-1.1: CUPS Implementation of IPP
  • +
  • CUPS-SAM-1.1.x: CUPS Software Administrators Manual
  • +
  • CUPS-SDD-1.1: CUPS Software Design Description
  • +
  • CUPS-SPM-1.1.x: 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: CUPS Software Version Description
  • +
+

2.2 Other Documents

+

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

+ +

3 File Management

+

3.1 Directory Structure

+ Each source file shall be placed a sub-directory +corresponding to the software sub-system it belongs +to ("scheduler", "cups", 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.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
    +
    +
+

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.1. 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 Page 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
+
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 ".cxx" 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$" 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
    + *       44141 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$" 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.1 */
    +do_this(float x) /* I - Power value (0.0 <= x <= 1.1) */
    +{
    +  ...
    +  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..38a8ab1246 --- /dev/null +++ b/doc/cmp.pdf @@ -0,0 +1,839 @@ +%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 +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[16 0 R +18 0 R +20 0 R +22 0 R +24 0 R +26 0 R +28 0 R +30 0 R +32 0 R +34 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<>endobj +46 0 obj<>endobj +47 0 obj<>endobj +48 0 obj<>endobj +49 0 obj<>endobj +50 0 obj<>endobj +51 0 obj<>endobj +52 0 obj<>endobj +53 0 obj<>endobj +54 0 obj<>endobj +55 0 obj<>endobj +56 0 obj<>endobj +57 0 obj<>endobj +58 0 obj<>endobj +59 0 obj<>endobj +60 0 obj<>endobj +61 0 obj<>endobj +62 0 obj<>endobj +63 0 obj<>endobj +64 0 obj<>endobj +65 0 obj<>endobj +66 0 obj<>endobj +67 0 obj<>endobj +68 0 obj<>endobj +69 0 obj<>endobj +70 0 obj<>endobj +71 0 obj<>endobj +72 0 obj<>endobj +73 0 obj<>endobj +74 0 obj<>endobj +75 0 obj<>endobj +76 0 obj<>endobj +77 0 obj<>endobj +78 0 obj<>endobj +79 0 obj<>endobj +80 0 obj[38 0 R +39 0 R +40 0 R +41 0 R +42 0 R +43 0 R +44 0 R +45 0 R +46 0 R +47 0 R +48 0 R +49 0 R +50 0 R +51 0 R +52 0 R +53 0 R +54 0 R +55 0 R +56 0 R +57 0 R +58 0 R +59 0 R +60 0 R +61 0 R +62 0 R +63 0 R +64 0 R +65 0 R +66 0 R +67 0 R +68 0 R +69 0 R +70 0 R +71 0 R +72 0 R +73 0 R +74 0 R +75 0 R +76 0 R +77 0 R +78 0 R +79 0 R +]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[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 +]endobj +93 0 obj<>endobj +94 0 obj<>endobj +95 0 obj<>endobj +96 0 obj<>endobj +97 0 obj<>endobj +98 0 obj<>endobj +99 0 obj<>endobj +100 0 obj<>endobj +101 0 obj<>endobj +102 0 obj<>endobj +103 0 obj<>endobj +104 0 obj<>endobj +105 0 obj<>endobj +106 0 obj<>endobj +107 0 obj<>endobj +108 0 obj<>endobj +109 0 obj<>endobj +110 0 obj<>endobj +111 0 obj<>endobj +112 0 obj<>endobj +113 0 obj<>endobj +114 0 obj<>endobj +115 0 obj<>endobj +116 0 obj<>endobj +117 0 obj<>endobj +118 0 obj<>endobj +119 0 obj<>endobj +120 0 obj<>endobj +121 0 obj<>endobj +122 0 obj<>endobj +123 0 obj<>endobj +124 0 obj<>endobj +125 0 obj<>endobj +126 0 obj<>endobj +127 0 obj<>endobj +128 0 obj<>endobj +129 0 obj<>endobj +130 0 obj<>endobj +131 0 obj<>endobj +132 0 obj<>endobj +133 0 obj<>endobj +134 0 obj<>endobj +135 0 obj<>endobj +136 0 obj<>endobj +137 0 obj<>endobj +138 0 obj<>endobj +139 0 obj<>endobj +140 0 obj<>endobj +141 0 obj<>endobj +142 0 obj<>endobj +143 0 obj<>endobj +144 0 obj<>endobj +145 0 obj<>endobj +146 0 obj<>endobj +147 0 obj<>endobj +148 0 obj<>endobj +149 0 obj<>endobj +150 0 obj<>endobj +151 0 obj<>>>>>endobj +152 0 obj<>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ÌA‚0Ð=§˜¥&¶ò±",•莵 ‘‚lM©n/uåfóçýŒ–‡I Ù`ò ”‰)e=Cq©Î(¬iºöå”ï¬A©ŒjõCªWf.ï +œDÆ0ZM9ùÀYQVŒ8…!#Á ,I¹ç½Fœmã?ÊiTÎÖ¯«~C±âéßû]×Þ<(Ï7,‰ãxmßãÊ'=h÷Öu {£/;“òendstream +endobj +153 0 obj +6289 +endobj +154 0 obj<>>>endobj +155 0 obj<>stream +xÚ+ä2T0BCc3JÎår +ár á +äHÉHendstream +endobj +156 0 obj +31 +endobj +157 0 obj<>>>/Annots 14 0 R>>endobj +158 0 obj<>stream +xڝVMoã6½ûW ö”µjɟémgS›¬j9‹|¡¥‘­ %:$eÃýõ!åxÓ¢0¡9œyïÍãÐo­:ôÂ0‚îÒ²5ž·~ýrQæ9í †#˜g7!$©Úàíü‡Û ‡~·Ýí‘ÛB˜fXÙ"/Ra UùЄa ƒ‡ÎׅTUy±ªµ …RTb…%‡d*­ýJ«m‘¡»FXÕô¯,*ZæJC†[”jãâD•Q’¢²X‰*EP9—§¢a×ããó÷ª,©ØËóô/ˆ5Õ +’½±XÂâæÓýKœ|ZÜÂwԆA1%£r»ƒŸ‰GAϏ9¾mQo ÜqìÃ¼Õ :$-„ü1{„Þ FÐïEAJ荛_IH¼ð'½ú½.çgT'l”¶b)‘¾kH±Gíaf‹¨?h/…Á ¨_¬/…Ð0µ°–ˆÕA? +\îÁÉõ°^Á̓0û¥C èG#¢Dd¢ ß,˜ËÜO%ŒÂãц9/ïgµ¤Ñœz¤²:µæ=¶ÎXÅ”Ê"éb,y@è줋Q²vîbi„”¾ñ[¬2¥sLm¨Õ¼“øß4íýîΌQ¿¢Ä=9¸$Ûfm6$°ót.R4A“ x¸äTÈ[xÊqړÿˆ¤U©’ìÀi³…¥&Þéîzp°ã?ÔÒ㫱¦Š0§è¯ã»«A֘dßS¯ñ„ $äSúþ ¡kc©ÒWÞNžÆ´ý‹Ëýy³Ièk‚º¸Ák øí¤Ð˜ZJ±i`ꔐF]7õ†­JîÚv ©•´Èë*å¦YØ}#½È2$ÊNéWO‘À-µÚæÌ`bel’êbÓ‡ú¢ÚÛ.<ÏØóô×àhåö û¦AG°„lS]yVWú»ôa/™+õ;•µ¿im¬*‹¿©Ò¶™*‡Ççx\l‹@¥µÖ4ªä¾¥òŸ£úA¿³¸½àÆÐL,JîU^Ð՟Mcrˆ°Nûš“QªTÕ>ӫѓ\’ˆrC‡3]0Ng¬ßc'ïCœ|{¾¨z8çj4t3_•*²ACãrÿÇtìÂä0ÌÏçã/ÃñQ  ¥W¢ršJå®K®¤T;wñÑYÌüƅèQ;ö/„öù3–6ÚC<XDƒ!¼‡Ç{GQ"J0é‘©×déR–/Üǧ#¹kSõ(Õ\«š„ºþÓ@!l|u®MÚg™CxFÎüz5ÙϔìQ*š4zmŽ1å¸W÷v†o5Í Öìÿ@6é­¡æEäËèâçLoÔ îüÁ°yêþlýÁdz{endstream +endobj +159 0 obj +993 +endobj +160 0 obj<>>>>>endobj +161 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS041Ó3V072PIÑPp VpÎÏKËL/-J,ÉÌÏSðMÌKLOÍMÍ+QÈIÌÓ Éâ҅h҅ê2‰™…ÌÀ|C…àäü‚T¨kW _)!rendstream +endobj +162 0 obj +117 +endobj +163 0 obj<>>>/Annots 37 0 R>>endobj +164 0 obj<>stream +xÚµ˜MSãF†ïüŠ>nªl­4²õÁ 0°¤ ÖAbO¹yl”²$G’‹åß§{F–ÚY3rÀ)ªLõh>ºßy§ÇŸ9`㟾׃4?»ŒÏ¾Þ„ lˆ—øÄóˆ_<Ê¥¬d‘Êú·ø/…8¾FÆîÄ +²¸zšG0+Óm.‹&i²²Ðø§Å…oy„Ç/–åz]¾fÅJ¿¸à/BVCµuÏoмàW;æœ:Æ9…gM¨?êa|õ0;–s®û»*‹e¶ÚVº¿‡¤HV’Þ…ù:i'–¶ûV€³Ã~þžû³¦gcÇÕËTãÜÍflœè­ndwE#«e’J˜É:[ô/­²M†Ž6竺Ë7kه©\>ÿTÿÑÅõoýÜ­§\6¯I%áb‘gEV7Á²ª)‚Ûdý¹¡ö·èÄ‹æï,h^•«*És’Ü)V=ZM$Óm•5o¸k6eÕ|nˆx~hˆXÖ'qôôNœžjy¢|ÿ8˜ïØ=‰÷¿%|g:càcWè/°ñ½y‘Uç<õ‘®S”ÅxÏyj Ù ÙÎu|f[6:'}8ôñx‹þiÙà.Ž“ƒ êÆ¢4rœe€«5áŽãq~2È3"G7<'ÂòÍ<#Ÿú˜#ψ\ȧÈ{Î@8Ýi`¹=ïOöú¿ü%_ՊÎ;7˜hU\,Êg4‡²n"%Gô‰ŒÌœën²µ„›²Ê“¢L³e–* uržX®EéG³ÛьÊ6èÉ·Qã;=©†IO-Ýêɀ·zÚñm!#ÏÌ·#(ڞȻ¡55óŒ@Þ§¼ôüÁüõۛ2é;Ú ~Éä}R¬¶xî÷Ì◬ZÀõ"£ì}$aï8žÃçð{ù I±è$ɾo¤.Bꏚ)výUùèu‘– ò.#®’¢þÌÓuÛäû·Ûl!?ÝåC¹k5ÍHæIÑdéðê ;Áž(mL•PT㰔Càw¯¦@ûÆÀ9A>,H§&žÈÊ5M<#hŸ…VÈø#ö=Õûàñæ +¿õÃÜg…ìý,‘9ú–AM™–ë“z•T@›!Ý0dhG«˜h`…3€s‚2b<Œ<#È 'q#Ïä}ò]#ÏÊèt`þœ “•v•‘gò¡½üaňPè}KŠSÏíŠñÛ2Y×X,U¸‡õݦíÉHþóÿh£ewR “†ZZKÄ@3s†u£çiȘ 'HC.îa#ϪÎ<Œ‰çi(èŸtú*ŚxF ïэÚÈ3ù`:ONPõGµAÏ¡Q?d + Fð¨Ód-•<±ô‡¨©¶i³ÅâïÃôEú˜…ú¥ëÂ,ñ +Ú£Rt'hÕ0 º¥µ^ 4ȇ:ç 4 t›xF ÒEËÈ3‚J庉ç]7B’«‰g•‡ ¨ã7µ&!<’͆rü,›W) ¸ŸÏ”Z°|éò^ŸÖÛ¦ŽºèL«†I +-­3m @Þæ’SpNÐù5ÈûœÎÏ Zóô9A©u)µDj§BßáTj=ÇÁ·7,·ù³Ñõ1–ý]Fa<†oq¬*ÔÓ&× úòT7LÉmi;Í*O} +Žç•›ÁÀd8¡‹ßÈsB,æùp"ow¡‘g3¹PÇ!7ìË_3”m¸Ø¢ÁÓ Dçp™ÔYª¶û,[Ñ/ii*ëú½bÿõ#.FÁî¡þ¡ª›Ö¿GŸ6®P½í¶úúãìfck”endstream +endobj +165 0 obj +1334 +endobj +166 0 obj<>>>>>endobj +167 0 obj<>stream +xÚ-‹Á‚0DïûsÔȖ¦z–È͵~@ƒ[‚‘% þ¿VÍÌeÞäMÄ(>a”.µhïiSïÀ ÁÖå%¶¦€¿­P]› ªQcß½æ°ô£â4t2ˆ.hA×þNÙOÊþ–MÌξÛà,QfÑVžé:x:Ñr#vendstream +endobj +168 0 obj +122 +endobj +169 0 obj<>>>>>endobj +170 0 obj<>stream +xڍ“OoÓ@Åïù#ŸZ)5±’”mZ)`qèe³Û ë]wÿ–OÏìÚ`)UŠ¥hå7ûf~oü8Ë`A¿ 69,×À»ÙM9{s ùʚެ7[(«‹%Ü ‰ð)Ö`‡Ê]–ߣ.Û º«å*Í£2Í`' r§Í3Îxî¼ÁA¿‚,õù&]ýã-Xí G¨ƒ‡m™”pDè%ãXëWÕß+¹6m¯U%TNƒk©H×îÄ F­}¶;Žn‘Z5–TÁŸ\³åÐåÃEby‹•—h’9$Ü÷–þÑñôáJ ;&™u=sâH}„kAË + |ý¸ÿ›œì¦öëЎC(íÎ|ñ‰#͔ê–Æ ä#Q5®M_RÍÓÕ@5‡b€‚°¯â,&’vBYiîCj§ª Ö¦c.ž,Th¹G:Pïû ìÜÌáVGÂ_ðÑÓt¡Üþ«Á%¨Z4Þ0­^ìÊ7;æîU@ÂåZ9£%è:Ɇ{Úåà@øÈËB1DN±ÞŠ„"ü³éˆí,‡3˄vÿˆ’!h kI©&,ù2©ãYàL…RG)Re:äëÇn$>° 'v~(¦M!x.}E¶Ñ2(N­pس -eï÷ïàmŠ”(ůG1^p6ÑÒ²÷Á3cÚNÄW!°W>ãÕv‘^“ˆÞ¿ ç»röyöUDK­endstream +endobj +171 0 obj +540 +endobj +172 0 obj<>>>>>endobj +173 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS041Ó3V072PIÑPp VpÎÏKËL/-J,ÉÌÏSðMÌKLOÍMÍ+QÈIÌÓ Éâ҅h҅ê2‰[éY*€ùÆ +n™9©HAò®!\\ÍZ%endstream +endobj +174 0 obj +119 +endobj +175 0 obj<>>>>>endobj +176 0 obj<>stream +xڍVMs"7½ó+ºödW-ó±ÆÎÍq’ª\’ÍÖ^¸ˆ™£”f4+iÀüû¼–fÀ€ [@ ûu÷ë×-~ FtƒÇˆfcšÜR^ ~›~ùóžÆ74/ñËíìŽæÅՔæÎ¶KÃôču¾:›³÷º~¹žÿ)FÉc8¾ËÆâó@϶ åøØyqõéyþôiqM~¥Œ¡%“o—• â5»-]1)j=;²ŽÖ\xã׆æ¡ñcã,@+IaG“v£ÃŠÂŠéñÛ×gò] +Ù.s€?òª”®^«k *¨¥òLÄÖL¶ŒX¥5ÆnP-ù û_%(Žo³©DE=¤=åÆz€E÷ÜVá ½5mж¯áH8‡Ë(#9ã¸ËýŶá#ÿñ‡þ*zÍƓP+…-®jސ| ¢UQh ¨ ˆ)­«”œH­•6 +,.®Ч }8þ²‡?æ{×ê&I¶¢Ÿ~¹ñYÕ=f¨&ãÄó4Ñ£QP^©sÕsr¨¿Yv+¦ßW,= yHŎs?èy ªõA’Ê;L|«Âû7P¦9íüÿh ¥è³^)ˆ³â:\jõï6oÅ.ËÎYw©»ßj¡ž‚…Ð-j+µ¹Øæc/|Pé#»÷šx6"žÆx}y¯õàÍç¶Ù‘ØM*4`[†·BzépU?µ'v§Ï†sérʸRù +–'è­SMÈÁaÑÕʪ.QüÐ4Fc¹ˆ7ÔÚÅDÕÅ –ù½h##{َé¯í¾,Û  HZÔ[Œ|À婞ßÐ(ýʓ:L©.®<–­®×Ö¬ûõÓ£ÍÙwI|÷˜Øœ+©Ô¶x»°äª¶îjÚïmЩ±Ã°9τmö}ÿrŒ¬3íg-Žt¬ñ£ÒV +ù-fº£›‹Ï¢®_P ²Úh46ЮÆ™ct_8ÁÁ°àâ(Oé]W]éŽríYæÿçܛУuØDgµ°7I÷•ÏW\´Ñä–ÂmlLJܚ:l£\ÒÅó*ÇÃùË(ŠK”²ô‘¯£:#{•*ø3ݒJB^¨a}›Ë/[c‘äÞØ‰Î±a¹A}­Œ{è ×2:¢¥‡tŽ¢ +t*êŠ ¸Eá߀p‹0€1™Á®²®ŽsLOéoûs7?•-R¯mÒmzé•ú5Þ±ýU(öúpÍm|Ô/ú´M qÁwYÞíƒßO~âßÕôî&»O[f&ç?æƒÿñnendstream +endobj +177 0 obj +945 +endobj +178 0 obj<>>>>>endobj +179 0 obj<>stream +xÚ-‹A‚0D÷ÿ³ÔJm¬%º3Aý bij Õ÷—ª™ÙÌ˼7 äKd‘Ú´gÚ+î T±‘(w9ø±B}k®¨ƒïœ£ž\ð8i¯­ŒŸÐôÚ¯ùIÙOÊþV•˜T%¾Kc˜ï½ÁżB\¬Z3ŽÎÛô;0é#Õ(Óendstream +endobj +180 0 obj +131 +endobj +181 0 obj<>>>>>endobj +182 0 obj<>stream +xÚµVMsÛ6½ëWìøÔÎDŒ()þè-Îĝ^2n¤¦Ç .-zH€@»þ÷} P¦$gr¨}°I,Þ¾}ûÅ&9Íð›Ó՜—¤ÛÉízòþî†æ3ZW8¹¼º¦uùËZÙ*<+Çô•Vžý¯ëÇh™_%Ëéb™Í£m–Ó7v¾¶†¾ômÁ®6ÉzIy>Xϯ²K±þô×ýŠzà‘¢°qÌÓN¹@O€‰äoUà’Šê€hKOÁ’ãαgp—©UÖ½£¶6òG™’:ôV‘²p€ç|‘x&hÿ[¢6£a¦óe¶ƒ—E´,mfY%Ïòlö:°i¼»å ¦}غG„¯6%èÖUbQ]Ǧ„@1€†C@´·TÙ¦±ÏÉDоnÊAŒŸ \Ä{§hùYâéÓ·y£:¿±jOl8©_YGŒÜ¼Pð¢ÄUmT³1¾‰ÙÖ£$"UšË]P£t ±_<]Dç:l"Hɺnᡳµ ^2Þ(@zhé¼¶(ó¢<åßg߇xTH¯ÏŠðY¡nôF™ ^@?H™Vªo ‹Á¿~Û¾/¦þÅnq ·,d…ÿ«¤Èè +·þHUUяÜÝÁ—ìëC¶¢Ø/83©â%×#pH×4ÈϞÔIØœl’† +Ò\³H3:DhÛvÈ7/°H|¸Ü·ÝO¹M1uëäøœOòPӄŸ»Ú¡çbyŽÂ|Uÿs±]±¶ðû#c¢=pçlÙë e}þF~D™‹§Œüýð›—þWólvBNǃSÆoyØ]Ú¯‹Øi‹a]Ìé÷4`pïìžØíŸÝ4õ•Jl4ž¤s}¯5{_õ Êu[¹å¾Ÿ‚³}ÑXg]Èè#lñˆÆ“B(ÿ˺J쫺9ô\rÂí°œ”(V8´2Ï1'z±Š“Gl|ï†aâmïô-%$ñXfÇ{užjüC¶ 5öÉ[Ût§RH†{ªRèHt¡Æ,K+ÇÆþ¾»).è¾Qæ]<˜®Ö÷S©ºSÂ/"û‘BZaæÓjý5.åW)Áó0:Óüq:¶©Âô~+ØåöKãl°Ç)8ºQŽñâ ۇE Èð3•µ®.úX¢X+˜î2Ú§òq¶,uÆø¨E¨m9žXÛåx‘Ñ{b$ ²Có °'öe'ɦ‹µSÞ_΢ˆÀâÀX„ºÞG¿¸Lџù$[^ϲØÁâFž?¯'Nþû¦Yendstream +endobj +183 0 obj +947 +endobj +184 0 obj<>>>>>endobj +185 0 obj<>stream +xÚ-‹A‚0D÷ÿ³ÔØo-²–èÎ¥àG Á@¡ÆëkÕ̬^Þ{C}ÆÐEúu¤¥Õ¡3l Þ¹Æv­`o T—ºA|ÛwÏIb<Žâ¥s£óõ ~iï”ý¢ì_±JP—&7øƒ&´ñ%“ÃÙ Nf7'coéDoC¦&Kendstream +endobj +186 0 obj +128 +endobj +187 0 obj<>>>>>endobj +188 0 obj<>stream +xڝ•QsÚ0 ÇßùzÜH`ÀÛ4´éAë]Ò»½G¤ŽÍlSÆ>ý”À±önqéŽG"ñ“þ²¤üìÅpIŸ&ŽAÔ½ë¢w1û +ƒK(VdO¦P”Ÿ®àVç¸Ý.~´ñäàÐŽ¢AëÅP ­ÝÁc q|ôL¢qã‘,££…âõãáñÏ L½Ùz´ ¸®¶¼Âè-§ÿÚ}Ã-W +U70G]J]±`Q |inJî9ÔÆ"øg®IõRzàt—u8 Ü`({£±¿ãûFE½ÕRp/v (ŒFKô;D ~g`cMeyíBáZÉÿKÝ49#ÖèCª(ÝV•¦ô]w¨‹Þ¶Dc8ˆF‡¦À•°Fï}q•'YÈ£¦j:¯Üs]r[BbJ„‰Ï4}×m:ô›º§I©Â€èä‰åÝ¡H¨§‡ì;0+µoêšïÇ:ÀLóä‚uCS–?>ü#ù6Z ϊw&Ba¹v+lhÆaT€vÇú·ónÞîzßg\¬›Do-ßKÏסmk_ˆ´@zRÛ^+ZœVœÚÂÒ¶¦Ó Mïô5öËè¸%ß¼‚G“Q4¥%J†8n¤Eï[ï°#Âendstream +endobj +189 0 obj +596 +endobj +190 0 obj<>>>>>endobj +191 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS041Ó3V072PIÑPp VpÎÏKËL/-J,ÉÌÏSðMÌKLOÍMÍ+QÈIÌÓ Éâ҅h҅ê24 šë)€Üsò‹‹‹*A®!\\í€#endstream +endobj +192 0 obj +122 +endobj +193 0 obj<>>>>>endobj +194 0 obj<>stream +xڍV[sÚ:~çWì0}H[0¾ ÎK)I¦Ì´™žIÎC^„-°ZÛr%¿ïJ2Ä;C FÚë·»ßúOÇÿ=ù !Ê:_—ÁÝ|–k¼Ž®a_}…Y¾ÿ蟒 šÑ\ɏË_(‚çYÙ¾íøZz™PI!²¢¦…à[Sˆ©",¥1°|ÍEFã9àGòRDÖxöBi$!æQ©Xوç +8:ôìuϛ}¤,§dBÒVHQ¤ *údflÎ>®»<ÆΩf?ŽÍr Þ¨Ê2ðÐ`âx°°ÊwZù(]gX ¢è=É0•sÌFZdŠ!’“¬½‡µIˆ ‘¢B€2ÁÃï|ƒ‘bV4—¥Ð¨gB´b)S{›Oc*àá~þÿ´Œ«½T4“Î!ë^ÃKX®±_—y¤!?D“-¢™}ÁHS·5t¨« ÓûżÏ^^ì)âüÆu=Ytú\%e—åQZÆ´[ò®Ï¤ëœîÕAO7õ¦iÁ{ñ+´IJ¢ä¤­û + P¢±Ü°­†#6…ÒªúY«ôÌSQŠ‚c'bî9Qº.V¤«ñb/Ø&QÁ”E:]ô”s…Ï=sj<‹RÅfFé„ËêÉÆ‡jo< ºeÈú²Ú¬öÆÚìqÝóøCÙL,„.Œ5‚H}?´p>¸Ža øT靝Ÿ ÜP V¨ª´&òjÄ¥s‘…Ù9o<õ}×uu·Dî±µ×jG°?ËHɞá#.›Œ d±¥ñe®tgŠ •(mmz ±ñ,óÙÒéá,q„5ÌA2 U“IÓC‚Tà# Íi›úEEnÐek2wG±kIZk¯”석a´lUܵ±±°»¼TšFã&›µvƒî÷ùìö~që¨Յ]Âô%¼Lc;º+Ju§™É¶Üڜ46 m_˜¯_ê¾Ì˜4ƒ€“ŒlÐL‘R"m› /6lCMM.ª«þ›*•OÌ"€ïÇiœ¿ÎL›^³ë6é0ôB¦ IC(xdt7‚mqà%S·qئú§é~Çy܃DìS]EßÃ~à!Ñ=,¦çúÈ1à <_®÷ü‚QÐÝ 5ŸÂ'•…ìkù¢Ÿ.6m +OOOH”*&ƒÁn·sZ5ÎMÌ*6¸¬t~ôž¯0“þ ¿xÎ{~ƒ†ÿ®FРœk N×Oß°çð°€V\)ž]´ƒ”ЯNï.!œãÃÕ)7¼/!y° ;çugU£‡|­À«ßÆÅÆÂ+Rí`Öé!¦Ú¤2eö Ç_+ŒH%DŽ|AB¤¥‡”K9%¢îíPµx®_ww8ªö|ۛi8 +zWËx¦‡o—;QQJ-endstream +endobj +195 0 obj +1072 +endobj +196 0 obj<>>>>>endobj +197 0 obj<>stream +xÚÕV]oÚ0}çW\¡J-„| (l}i RÚu*{CªŒsC<%6‹6í¿ï: В~îeZ@ÈØ÷ßs|áG×^}ûæiãlÚèN\Â4²3ý…GÝãÖô{Ŏç:'vŽa,CP4.æS[ïڙîdÞÀbu¬øvíÌña’Kn„’zÕ³Q„¸N¿Šr<¸f©‹2¨žWù²ab`°HԜ% ¹Z"è˜% Ì8[ +ÃñC˜5/Ô4ºÙ†bÄL9ºU)š˜ö'i + wf-˜ÆJ&ë ½À)(àŠãÒn F¥iÈòäі†ÒοÝ܂³ˆq„DÌ3–­!Ú CÊ֔±rCb™a$V𠲐Ò÷6NÔfœi´Lx¾Ô;6›o£²ü*Ùï;½gõJ¯Ë"OXFZ5µaFð&0:iZØí]¤ç2Čr3Ô´jeQ´Þ+™ + ՝©ª,†¥è4ÔÕïð±ìµ¦ð‡%Û>\(ž§(muJ¾ÐcFÚn´Þ’{$3W©Å€ñ ֚gbN¥Ð¹0Sœà6=T¨ÛÅÔRi-ætÔB.sC‡š +S',"Òl=kµ éžä©ÜØÄ{–ä¤Û~( A/‘ :!#•¥Gˆ!†£’ëΝ¿Wêòœ?+ÕgG³Ö!tà\¥´3ÂN¡œ_ÍZußց®•A=©$¾`s«ºWÚ¶ìˆE"Ú§{ _h÷KyOÝb… &*é·Áu\ø|JчGnߢmð·J<*Øâ]Þ͇T¬€V…Õ ~í—ŽS£š<“„HGòioõ÷+7ZWÔÈ*|í> ÞºÏ*ˆ©[ßk:øˆÍöo³·L|ÄtiÁâ/-W%ÿŸ†£{SëÑèŸøng¸§ÏûíçÖ=³OèC.t·.ìNNªNñ9€þ0(U,#ϕŒÄ"ÏJ寘d ,úä&aE§u¼^ŸÒ:ßµY^ÏNö¼¡3÷Ù?ãiãkã‘m•Äendstream +endobj +198 0 obj +767 +endobj +199 0 obj<>>>>>endobj +200 0 obj<>stream +xÚ¥UÁrÚ0½ó;>%™b°“4§$Mzj'Ðž2“‘å5¨µ-W–Ii§ÿޕ„ÁBÓépÀ’vßîÛ}Z}ï0¤_ÓFð¼w=ë î†p³ÔìDçô•œü:}í ¡ ýs³ð}oO¡®U'«ÇÓËÎéo³Ü]@05Ð}ÂîBsríá S‚ÅV«±±"ÿÑЏÖV~Y.й3C¬Â©1ـÀ³Ð `0ÏdÌ2¨¸,ªË2ˆ8+…f™ø‰ ¥êÍ¢j<½7@k¦w×¢zÐLck5÷O†#ßò˜-d‘­p,µh šÜAÕY+M†7Ÿï@UÊ8B&bÅÔªÉx¹e²|y]iòœ‹ÂQ#„NðRa*~€Çë²ò -óÑ¥æövè9&ð¾w“¬Â2£ ˆWÖ7¼:±™š×9Úd‹.QA)«JP£‘0¢&jQ&ù~‡2ùŒŠ³ +U]$¨ÈD‘[Œú‘Ê URž¦¾OË ¡NjtÌtë¸á{U¬Ö¡w(«]ž.K*:ƒJ֊ú”Šv#ä™õñ*ˆàž¿'ßðÂ7ò áä¶R¬©âß2jx“ՁXÒ¦ƒ%S¤INÀŠdk(òAg¤ÄTf¦––.sbbþ­S¨+®DL—Ëʳ‰ÿÖ%¹ýpì‘va§ö—08s x­” dªBw"u—àlÐ ¢ÕŸãL¯!^˜"˜­Ê£dò· rE%ÔËۗàՂ4ðž´¬,‘¬7háX8ìNõ›ØäMWÕÖe³ÜΛÄ5ùqY†ŽÛ‚-±«ŒŘM›·qK0}Yƒ³î‹`zI·韠ÜàK%ÒNÉjï!ÙSÊ:´˜`†ØS«Z—G$ÁƒV5§Wé¨.¢×è¢jþS„sLe˜X›1çR°Dv¶Ú29_sƑ?‚h2Y×ÖÖÿF©˜×ÊJ>°‚ÍÑ +à>cV:}ç֟†ÃƒOôx:&<{LÌÆí¬÷©÷?ðendstream +endobj +201 0 obj +789 +endobj +202 0 obj<>>>>>endobj +203 0 obj<>stream +xÚՖMoÚ@†ïüЧ$ +2МMÕš¦{¨ ­×vc{ÝÝu(ªúß;»kdò©J•*"×óξ3óŒ”ôña˜?žwÎÃNÿÝ ü1„+zLéG|tîÞÞ +^åXh¦SQ‡ß)r ¾ï"{ɉ¼`<¥eÅu%T² v‡À€‹ÜÈ!Ê¿…”â”i̶áJP´N°Ö+b@“+Çä«Î4 –á¶$gXÐH»€û=Rôj“`w´/¥P*5Øk 6®ÒOßšUˆ¶náD^¦Jï‰ÍŸ¾póûޘÛ_ô•°fìj7Ó~| M¥Ï®Æ®©á—ù·SG¶]V-Ùö¡eØ5Ü( Qù{Šþ»i]OÊ3ߪ-„Ë*]Wnð‘l¶ð«ŒÙÞôüq@¢Þd80*?0‡£é˜ÎOüßpv>wþK†Œ-endstream +endobj +204 0 obj +729 +endobj +205 0 obj<>>>>>endobj +206 0 obj<>stream +xÚµUßoÚ0~ç¯ø–§Ò¤ÊØÖ_R¥MêT¦=Œi2‰^ÍâPÔMýßw¶C) LÛÄøî|÷Ýùûì­}b œô‘.ZgãV÷*ÂãÜZú§ô/;zµÇßÉ1D<°ž¹:'‰u…CœëŒ?ôl@Dî(ìWaŒ ®\•¬ZùØ⸊M6ò”0zU¤)e„™3²¬J!ÅOŽ©Ôé96ÁZ”s¡¯TjS”7i!¦åœC/yÁ¼kʅšÖ¹.<ÃôÁ" ºñIèš`˜zµ„Îa"w%^{˜Ûat’^سáÝãÍþ(<µã\rV¸Â.XQ°ªL%9ÖŸÏ„ +ð±³[Y’ØÏ‹6`r$ðÑoha¨OŽ\ÎI]l,;ž/Ñ×I{Ò¶»^¾œ´ë•<¤/â+¥¾¿_~»¾x9ª•ß×Ûg&JX\¾µtÎԌ›¿i&Óµ_ Tÿ¯_@äØÄRÛ/ž÷½7˜œÝÕgR%"Œoÿˆî9ª½ùä|99Š tÍûˆõ\HþïUF»ÂsÊL†á%¸-äVœ»‚s!õÊK³ï9oÅéTéthÀU*µqb¢¡±ôŽ“(½b՝@7BTV6ŠV + Н!…â!ÆóJìIjÖR굩©“XW”6ÃÎ^°¼ä^q>3S„pͰfIvS!´[ç +.%­²Ýĵê“ÝZn°²Ò7Vj”ɪ¤›ßáK£É|¡JˆºÇx¯õÒV¸§+¤¡!4%Iš¼)4õfhdzJ»î™\qZzA§Fwáp8Ü#Ð=ٛŒ£(:(ª_{héotJÒ$ö“Ÿ•üu)ìrÐ3Úa½¥IÞq§¿½§±=¡ ÓÁ+\n©3û#rú¶ìœÆ‚'š6¹F/ —2¬‘à̓žÞGaù¢x:ª—©™´÷”Ô1•³tŽ e„Í£ÉxÎV² `m‡‰ãË<»Èü©t¯N« Å4¹ûTW=ÿtsKo²ÊÅlåŸ@|`ŠÍܸp#™Sy'îõi[gDõw¼7èQ*gŽÖp9n}lýJÈVªendstream +endobj +207 0 obj +817 +endobj +208 0 obj<>>>>>endobj +209 0 obj<>stream +xڕRmo›0þί8åS" ¥I«Nj»TšÔIÙ¶£ª8‚7°3¿µÓþû΁-­¢T lŸŸ{ûéEÒA)uy ìóÕV)i)ünïI’%^*Ù<ˬ¦ »œw!ƒçO’.D b†­ïç+M*àNÊí鼿V(p‡ +r)v(8‰€Úy +ië‚ì–L…lE˨UFÂ*éVÞl•Ü!УX[T¥T 9žARÀá4BYfC¦{¤f_Z¾…÷dô!ºo/!t«ïg££îàüž8•éë2ëG!NÎz§›ÏËÜHQòUl߆L° ºeÍöÃäGɔÜü³Iè¼¢™3&qL$á¿ÃÊ<Öèn©÷Ñû¡¦7nendstream +endobj +210 0 obj +534 +endobj +211 0 obj<>>>>>endobj +212 0 obj<>stream +xÚíSËNÃ0¼ç+ö›Øqí© Í QH8W&u!¨‰ÃÖõﱛ¤ñ¸c_,kfggÇ~‰Ä~3P e]ÑY6C±¦RÊ@ªŠåÉävåÞ4(ÐnÖîLkÑAf±>-ž=qŒ"Q‚ށ$"¡Uàô¦5è]6$ßmœ§_C)6’!Ø£ÖÔ8í.aj6%VmÓ7!ïÉ +y8“ÞçãO±pÓ$Ä¢º'ýó_þ‡¦]l.fEt½ 4ïendstream +endobj +213 0 obj +345 +endobj +214 0 obj<>>>>>endobj +215 0 obj<>stream +xÚ-‹A ÷ÿo©‹V(Úº–؝IµxThj +(¡ñúŠš÷V“™'q°Ï8Du´S´j·àʂ¯ëR ©ÔmyîzÈàí8ÌQ§1x´×ƒqÆ't“öKu§âÿªbŠª)7ø‰>ØôÒÑ@Å0_&ƒ“y„˜Ð†è²¼Wt¤7%*Oendstream +endobj +216 0 obj +135 +endobj +217 0 obj<>>>/Annots 80 0 R>>endobj +218 0 obj<>stream +xÚ՛MsÛ6†ïþ<¶‡2ø$€cœ6™š¤±š»"ӎ:–˜PR2þ÷° ÐÈ@o†“GȚOŒ—»/@,óýŠvÄþ¦bºÍîêzuõê­ééVw•¦”èV·¿¬Ö_ÆnºëÞLûã¸?~]ý{õÇêŠôÄÜê¾|zçÝ ŒýºëtÏðóCwãØgß>ßw¯ÞʎR÷¯ÙË$qÿ힄Gà®ã²×9ÝGq³™¾Ãdçÿ¢oþ}rÖ|pšúùî:Éz‰œö«·%´÷p°ß¬½Š}ADz³×R§dŠÄ8¢þ¼µw|{·Ý¬Ûiï RÙHCºÖ´c¬íü'êc܎½b¬¦r´ê‡œƒa$Ý<Žã®Æñz+?§ËâHûðcœlǟ'hoš¾¦81½X÷ƒDqJzŠóšâÈ¡Äås‚x@ý>mN;›¦OóR„ +aÿ̀ø ˜ÉÎln<³ì´h¹RóÅráóâÑ`¥ö3ceƒ (ilþe,ˆzƧñnœÇýfô+uaÕ¸ÏòrÂÊÁD{…Á%{•Š€'²ª½¢föŒá@zóÏǛ ‰WÛ¤•Äݒ”ñÀ +U°õ0<ïm©©.‡hÌ0ˆ6!¥dUcM¬£d #éÃñë8ϗ;_vFÁ0ް v¨ÖDð²MØI±`þó%›àn)´Sá£@Ó¶ú3D‘òvk·ŽO‚’‹wñ’§$ #ê¯õ~}?:Ñý.ÄôMîîd%é©õ©é­†ú’æu£AžQN¼”‡a°†í>>>/Annots 92 0 R>>endobj +221 0 obj<>stream +xÚ՗ώ›0Æï<…í!¬ÿ_7mzjµÝÐ`wI”*„–U}ûzìq0‘Ôšd³B þÁ|žo€Ÿ#Ôýþ_›ì±Ì–pJÊaÊm$)ßޕÕ˶&íŠÌÛ]_ïúýûò{ö±ÌhN ϟˆá9%ZZwlˆ-rÁ–,~² [“‡…$ŒÁõ 'ZQ¸Üc®sNÎ^#Á6„iËñEB> >´¯‡ÆÝqÕoÚÝ醸TþŸÿ˜>[‘РšPyá*R2`Ans´;¥ژóÊ$KR˜S¦‘4ßVû}í·R0§÷UDùWÅBŸqîv:ö™°Rè%.\ËÙT7!‰ y䎺)¾TÍf·öš‰k5Ò_ID­³G”ȉDŒæ2J4i8$¡áRTÈGØYNY4h¹ –SDñê–‹·ÂŒ9˜F’Ÿû¾Âù)ù͙nª›T!†Á‚¡›T½TLÚ-r‚ÝF ÌË{4›ÒÖOÞPƒy ¼˜4[$³P!a÷d6¥ýŒ –ðAb6eâ´¶SfCށ#¦‘4oßj ¹anoðኙ‰~’bÞ!HúIÊ8¼í´á„ý”¢0/ooxO©#hº¾$êøWTgÒmHbP˜Gزÿ½õ=ÅìÍôÔ™(¨DE˜$M>ÀÒ +ß¼á,‰/…ç¥JÎÄ +tIq˜Fβ]õ¿ª®¾àåàö™#¦Wví>AÎïã€Ç +?V÷1ä÷\ÿh»þB© ÀáTqzw¶h»Æuµ–`n`(„¿® +Üã™ßÎTèd2ÿö´„ϹÕf}è¼ÛÉçjW­kp?yÚVÞý3&µ›©3Ã}e› Jö5ûI@âJendstream +endobj +222 0 obj +668 +endobj +223 0 obj<>endobj +224 0 obj<>endobj +225 0 obj<>endobj +226 0 obj<>endobj +227 0 obj<>endobj +228 0 obj<>endobj +229 0 obj<>endobj +230 0 obj<>endobj +231 0 obj<>endobj +232 0 obj<>endobj +233 0 obj<>endobj +234 0 obj<>endobj +235 0 obj<>endobj +236 0 obj<>endobj +237 0 obj<>endobj +238 0 obj<>endobj +239 0 obj<>endobj +240 0 obj<>endobj +241 0 obj<>endobj +242 0 obj<>endobj +243 0 obj<>endobj +244 0 obj<>endobj +245 0 obj<>endobj +246 0 obj<>endobj +247 0 obj<>endobj +248 0 obj<>endobj +249 0 obj<>endobj +250 0 obj<>endobj +251 0 obj<>endobj +252 0 obj<>endobj +253 0 obj<>endobj +254 0 obj<>endobj +255 0 obj<>endobj +256 0 obj<>endobj +257 0 obj<>endobj +258 0 obj<>endobj +259 0 obj<>endobj +260 0 obj<>endobj +261 0 obj<>endobj +262 0 obj<>endobj +263 0 obj<>endobj +264 0 obj<>endobj +265 0 obj<>endobj +266 0 obj<>endobj +267 0 obj<>endobj +268 0 obj<>endobj +269 0 obj<>endobj +270 0 obj<>endobj +271 0 obj<>endobj +272 0 obj<>endobj +273 0 obj<>endobj +274 0 obj<>endobj +275 0 obj<>endobj +276 0 obj<>endobj +277 0 obj<>endobj +278 0 obj<>1<>2<>4<>]>>>>endobj +xref +0 279 +0000000000 65535 f +0000000015 00000 n +0000000228 00000 n +0000001794 00000 n +0000001868 00000 n +0000001946 00000 n +0000002023 00000 n +0000002102 00000 n +0000002178 00000 n +0000002259 00000 n +0000002317 00000 n +0000002369 00000 n +0000002454 00000 n +0000002506 00000 n +0000002590 00000 n +0000002621 00000 n +0000002722 00000 n +0000002807 00000 n +0000002908 00000 n +0000002993 00000 n +0000003094 00000 n +0000003179 00000 n +0000003266 00000 n +0000003351 00000 n +0000003438 00000 n +0000003523 00000 n +0000003589 00000 n +0000003674 00000 n +0000003740 00000 n +0000003825 00000 n +0000003891 00000 n +0000003976 00000 n +0000004042 00000 n +0000004127 00000 n +0000004193 00000 n +0000004278 00000 n +0000004344 00000 n +0000004429 00000 n +0000004523 00000 n +0000004627 00000 n +0000004732 00000 n +0000004837 00000 n +0000004942 00000 n +0000005046 00000 n +0000005151 00000 n +0000005256 00000 n +0000005360 00000 n +0000005465 00000 n +0000005570 00000 n +0000005675 00000 n +0000005779 00000 n +0000005884 00000 n +0000005989 00000 n +0000006094 00000 n +0000006199 00000 n +0000006303 00000 n +0000006408 00000 n +0000006513 00000 n +0000006618 00000 n +0000006723 00000 n +0000006827 00000 n +0000006932 00000 n +0000007037 00000 n +0000007141 00000 n +0000007246 00000 n +0000007351 00000 n +0000007456 00000 n +0000007561 00000 n +0000007666 00000 n +0000007771 00000 n +0000007876 00000 n +0000007981 00000 n +0000008086 00000 n +0000008191 00000 n +0000008296 00000 n +0000008401 00000 n +0000008506 00000 n +0000008611 00000 n +0000008715 00000 n +0000008818 00000 n +0000008921 00000 n +0000009232 00000 n +0000009337 00000 n +0000009441 00000 n +0000009546 00000 n +0000009651 00000 n +0000009755 00000 n +0000009860 00000 n +0000009965 00000 n +0000010069 00000 n +0000010174 00000 n +0000010279 00000 n +0000010383 00000 n +0000010477 00000 n +0000010509 00000 n +0000010541 00000 n +0000011261 00000 n +0000011309 00000 n +0000011357 00000 n +0000011405 00000 n +0000011453 00000 n +0000011502 00000 n +0000011551 00000 n +0000011600 00000 n +0000011649 00000 n +0000011698 00000 n +0000011747 00000 n +0000011796 00000 n +0000011845 00000 n +0000011894 00000 n +0000011943 00000 n +0000011992 00000 n +0000012041 00000 n +0000012090 00000 n +0000012139 00000 n +0000012188 00000 n +0000012237 00000 n +0000012286 00000 n +0000012335 00000 n +0000012384 00000 n +0000012433 00000 n +0000012482 00000 n +0000012531 00000 n +0000012580 00000 n +0000012629 00000 n +0000012678 00000 n +0000012727 00000 n +0000012776 00000 n +0000012825 00000 n +0000012874 00000 n +0000012923 00000 n +0000012972 00000 n +0000013021 00000 n +0000013070 00000 n +0000013119 00000 n +0000013168 00000 n +0000013217 00000 n +0000013266 00000 n +0000013315 00000 n +0000013364 00000 n +0000013413 00000 n +0000013462 00000 n +0000013511 00000 n +0000013560 00000 n +0000013609 00000 n +0000013658 00000 n +0000013707 00000 n +0000013756 00000 n +0000013805 00000 n +0000013854 00000 n +0000013903 00000 n +0000014164 00000 n +0000014316 00000 n +0000020676 00000 n +0000020698 00000 n +0000020793 00000 n +0000020895 00000 n +0000020915 00000 n +0000021069 00000 n +0000022133 00000 n +0000022154 00000 n +0000022267 00000 n +0000022455 00000 n +0000022476 00000 n +0000022630 00000 n +0000024035 00000 n +0000024057 00000 n +0000024170 00000 n +0000024363 00000 n +0000024384 00000 n +0000024515 00000 n +0000025126 00000 n +0000025147 00000 n +0000025260 00000 n +0000025450 00000 n +0000025471 00000 n +0000025602 00000 n +0000026618 00000 n +0000026639 00000 n +0000026752 00000 n +0000026954 00000 n +0000026975 00000 n +0000027115 00000 n +0000028133 00000 n +0000028154 00000 n +0000028267 00000 n +0000028466 00000 n +0000028487 00000 n +0000028627 00000 n +0000029294 00000 n +0000029315 00000 n +0000029428 00000 n +0000029621 00000 n +0000029642 00000 n +0000029782 00000 n +0000030925 00000 n +0000030947 00000 n +0000031087 00000 n +0000031925 00000 n +0000031946 00000 n +0000032086 00000 n +0000032946 00000 n +0000032967 00000 n +0000033107 00000 n +0000033907 00000 n +0000033928 00000 n +0000034068 00000 n +0000034956 00000 n +0000034977 00000 n +0000035117 00000 n +0000035722 00000 n +0000035743 00000 n +0000035883 00000 n +0000036299 00000 n +0000036320 00000 n +0000036433 00000 n +0000036639 00000 n +0000036660 00000 n +0000036814 00000 n +0000038864 00000 n +0000038886 00000 n +0000039040 00000 n +0000039779 00000 n +0000039800 00000 n +0000039855 00000 n +0000039960 00000 n +0000040104 00000 n +0000040210 00000 n +0000040330 00000 n +0000040439 00000 n +0000040588 00000 n +0000040698 00000 n +0000040805 00000 n +0000040959 00000 n +0000041070 00000 n +0000041187 00000 n +0000041303 00000 n +0000041467 00000 n +0000041573 00000 n +0000041692 00000 n +0000041807 00000 n +0000041911 00000 n +0000042067 00000 n +0000042176 00000 n +0000042291 00000 n +0000042403 00000 n +0000042502 00000 n +0000042649 00000 n +0000042746 00000 n +0000042846 00000 n +0000043004 00000 n +0000043144 00000 n +0000043244 00000 n +0000043351 00000 n +0000043501 00000 n +0000043601 00000 n +0000043708 00000 n +0000043856 00000 n +0000043956 00000 n +0000044063 00000 n +0000044213 00000 n +0000044313 00000 n +0000044420 00000 n +0000044566 00000 n +0000044666 00000 n +0000044773 00000 n +0000044924 00000 n +0000045024 00000 n +0000045131 00000 n +0000045279 00000 n +0000045379 00000 n +0000045486 00000 n +0000045636 00000 n +0000045736 00000 n +0000045843 00000 n +0000045975 00000 n +0000046082 00000 n +0000046181 00000 n +0000046299 00000 n +trailer +<<5b48a799cbdaa6a0d8d5f18bb0a35984>]>> +startxref +46526 +%%EOF diff --git a/doc/cmp.shtml b/doc/cmp.shtml new file mode 100644 index 0000000000..38c592d467 --- /dev/null +++ b/doc/cmp.shtml @@ -0,0 +1,595 @@ + + + + + + CUPS Configuration Management Plan + + + +

Scope

+ +

Identification

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

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

File Management

+ +

Directory Structure

+ +Each source file shall be placed a sub-directory corresponding to the software +sub-system it belongs to ("scheduler", "cups", 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. + + + +

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 +".cxx" 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$" 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
    + *       44141 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$" 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$".
    + */
    +
    +
+ +

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..9285a5b5ee --- /dev/null +++ b/doc/cups.css @@ -0,0 +1,4 @@ +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..39cc1f308b --- /dev/null +++ b/doc/documentation.html @@ -0,0 +1,81 @@ + + + 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 + + + + +
+Common UNIX Printing System +
+ +

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 ) + +
  • CUPS Implementation of IPP ( + HTML | + PDF ) + +
  • Interface Design Description ( + HTML | + PDF ) + +
  • Software Design Description ( + HTML | + PDF ) + +
  • Software Performance Specification ( + 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 0000000000..f51e814a63 Binary files /dev/null and b/doc/figures.sc differ diff --git a/doc/glossary.shtml b/doc/glossary.shtml new file mode 100644 index 0000000000..2cc0c1c893 --- /dev/null +++ b/doc/glossary.shtml @@ -0,0 +1,73 @@ +

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 Page 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 + +
PPD +
PostScript Printer Description + +
SMB +
Server Message Block + +
TFTP +
Trivial File Transfer Protocol + +
diff --git a/doc/idd.html b/doc/idd.html new file mode 100644 index 0000000000..cfec47f68d --- /dev/null +++ b/doc/idd.html @@ -0,0 +1,1245 @@ + + + + CUPS Interface Design Description + + + + + + + +

+

CUPS Interface Design Description


+CUPS-IDD-1.1
+Easy Software Products
+Copyright 1997-2000, All Rights Reserved
+
+
+

Table of Contents

+

+

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

+

1.2 System Overview

+

CUPS provides a portable printing layer for +UNIX®-based 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 ("IPP") +as the basis for managing print jobs and +queues. The Line Printer Daemon ("LPD") Server +Message Block ("SMB"), and AppSocket (a.k.a. +JetDirect) protocols are also supported with reduced +functionality. CUPS adds network printer browsing and +PostScript Printer Description ("PPD") based printing +options to support real-world printing under UNIX.

+

CUPS also includes a customized version of GNU +Ghostscript (currently based off GNU Ghostscript +5.50) and an image file RIP that are used to +support non-PostScript printers. Sample drivers for +HP and EPSON printers are included that use +these filters.

+

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.1: CUPS Configuration Management Plan
  • +
  • CUPS-IDD-1.1: CUPS System Interface Design +Description
  • +
  • CUPS-IPP-1.1: CUPS Implementation of IPP
  • +
  • CUPS-SAM-1.1.x: CUPS Software Administrators Manual
  • +
  • CUPS-SDD-1.1: CUPS Software Design Description
  • +
  • CUPS-SPM-1.1.x: 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: CUPS Software Version Description
  • +
+

2.2 Other Documents

+

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

+ +

3 Internal Interfaces

+

3.1 Character Set Files

+

The character set files define a mapping +between 8-bit characters and the Unicode character +set, or between Unicode and printer fonts. They +are named using the IETF charset names defined +in RFCnnnn. These files are ASCII text, the +content of which is described below. Comments can +be included by using the # character in +the first column of a line.

+

3.1.1 8-Bit Character Set Files

+

8-bit character set files start with a line +reading:

+
    +
    +charset 8bit
    +
    +
+

Following this are lines that define the font +information:

+
    +
    +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 within each group, with +a maximum of 256 mappings (this is a PostScript +limitation.) The glyph values are hexadecimal.

+

Direction is the string "ltor", "rtol", +or "rtola" indicating left-to-right, right-to-left, or +right-to-left Arabic 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.

+

The remaining lines define a character to +Unicode glyph mapping for the character set. The +character and glyph values are hexadecimal:

+
    +
    +xx yyyy
    +
    +
+

3.1.2 Unicode Character Set Files

+

Unicode character set files start with a line +reading:

+
    +
    +charset encoding
    +
    +
+

Encoding is the encoding to use for +the text; currently only the string "utf8" is +supported.

+

Following this are lines defining the font +information:

+
    +
    +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 within each group, with +a maximum of 256 mappings (this is a PostScript +limitation.) The glyph values are hexadecimal.

+

Direction is the string "ltor", "rtol", +or "rtola" indicating left-to-right, right-to-left, or +right-to-left Arabic 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.

+

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:

+
    +
  • 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
  • +
  • us-ascii
  • +
  • utf-8
  • +
  • windows-874
  • +
  • windows-1250
  • +
  • windows-1251
  • +
  • windows-1252
  • +
  • windows-1253
  • +
  • windows-1254
  • +
  • windows-1255
  • +
  • windows-1256
  • +
  • windows-1257
  • +
  • windows-1258
  • +
+

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 ")" |
    +	 "contains(" offset "," length "," 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:

+
    +
    +super/type SP super/type2 SP cost SP program
    +
    +
+

3.4 Option Files

+

CUPS maintains user-defined printer and option +files for each printer and user on the system. +The printers and options defined in the system +option file (/etc/cups/lpoptions) are +loaded first, followed by the user option file ( +$HOME/.lpoptions). Options in the user file +replace those defined in the system file for +the same destination. Each line in the files +can be one of the following:

+
    +
    +Dest name option=value option=value ... option=value
    +Dest name/instance option=value option=value ... option=value
    +Default name option=value option=value ... option=value
    +Default name/instance option=value option=value ... option=value
    +
    +
+

The line beginning with "Default" indicates the +default destination for print jobs; a default line +in the user option file overrides the default +defined in the system option file.

+

Name is the name of a printer known +to the local server.

+

Instance can be any string of letters, +numbers, and the underscore up to 127 characters +in length.

+

The remainder of the line contains a list of +space-separated options and their values.

+

3.5 PostScript Printer Description Files +

+

PostScript Printer Description ("PPD") files describe +the capabilities of each printer and are used +by CUPS to support printer-specific features and +intelligent filtering.

+

3.5.1 PPD Specification

+

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

+

3.5.2 CUPS Extensions to PPD Files +

+

CUPS adds several new attributes that are +described below.

+

3.5.2.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.5.2.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.5.2.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.5.2.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.5.2.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" +or "1.1".

+

3.6 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.6.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".
AllowUsersSpecifies a list of users +that are allowed to access the class.
BannerStartSpecifies the banner that is +printed before other files in a job.
BannerEndSpecifies the banner that is +printed after other files in a job.
DenyUsersSpecifies a list of users +that are not allowed to access the class.
InfoA textual description of the +class.
LocationA textual location of the +class.
PrinterSpecifies a printer that is a +member of the class.
StateSpecifies the initial state of +the class; can be "Idle" or "Stopped".
StateMessageSpecifies a textual message +for the current class state.
+
+

+

3.6.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 +
AccessLogaccess_logSpecifies the +location of the access log file. The special +name "syslog" can be used to send access log +information to the system log.
Allow-Allows connections from +the specified host, network, or domain.
AuthClass-Specifies what level +of authentication is required; may be "User", +"System", or "Group".
AuthTypeNoneSpecifies the type +of authentication to perform; may be "None", +"Basic", or "Digest".
BrowseAddress255.255.255.255Specifies +a broadcast address to send CUPS browsing packets +to.
BrowseAllow-Specifies hosts or +addresses from which browsing information should be +used.
BrowseDeny-Specifies hosts or +addresses from which browsing information should not +be used.
BrowseInterval30Specifies the +number of seconds between browsing updates. A + browse interval of 0 seconds disables outgoing +packets.
BrowseOrderAllow,DenySpecifies the +order of BrowseAllow and BrowseDeny directive + processing; can be "Deny,Allow" to implicitly deny +hosts unless they are allowed by a BrowseAllow +line, or "Allow,Deny" to implicitly allow hosts +unless they are denied by a BrowseDeny line.
BrowsePoll-Specifies a server +to poll for available printers and classes.
BrowsePort631Specifies the UDP +port number to use for browse packets.
BrowseRelay-Specifies a source +and destination address for relaying browser + information from one subnet to another.
BrowseShortNamesyesSpecifies whether +or not to provide short names (without the + "@server" part) for remote printers.
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".
DataDir/usr/share/cupsSpecifies the +directory where CUPS data files are stored.
DefaultCharsetiso-8859-1Specifies +the default character set.
DefaultLanguagecurrent locale +Specifies the default language.
Deny-Refuses connections from +the specified host, network, or domain.
DocumentRoot/usr/share/doc/cups +Specifies the document data root directory.
ErrorLogerror_logSpecifies the +error log file location. The special name + "syslog" can be used to send error log +information to the system log.
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 available 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.
PageLogpage_logSpecifies the +location of the page log file. The special name + "syslog" can be used to send page log +information to the system log.
Port631Specifies a port number +to listen to for HTTP connections.
Printcap/etc/printcapSpecifies the +location of a Berkeley printcap file to update + with a list of current printers and classes. +If no filename is supplied then this automatic +generation is disabled.
RequestRoot/var/spool/cupsSpecifies +the location of request files.
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/etc/cupsSpecifies the +root directory for server configuration files.
SystemGrouproot, sys, system +Specifies 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.6.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.
AllowUsersSpecifies a list of users +that are allowed to access the printer.
BannerStartSpecifies the banner that is +printed before other files in a job.
BannerEndSpecifies the banner that is +printed after other files in a job.
DenyUsersSpecifies a list of users +that are not allowed to access the printer.
DeviceURISpecifies the device-uri +attribute for the printer.
InfoA textual description of the +printer.
LocationA textual location of the +printer.
<Printer name> +

</Printer>
Surrounds the printer +definition.
StateSpecifies the initial state of +the printer; can be "Idle" or "Stopped".
StateMessageSpecifies a textual message +for the current printer state.
+
+

+

4 External Interfaces

+

4.1 AppSocket Protocol

+

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

+

The AppSocket protocol is used by the Hewlett +Packard JetDirect network interfaces and print +servers, as well as many other vendors' products. +See the CUPS Software Administrators Manual for a +list of supported products.

+

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 SP "location" SP "info" SP "make-and-model" NL
    +
    +
+

State, uri, location, info, and +make-and-model, correspond to the IPP +printer-state, printer-uri-supported, +printer-location, printer-info, and +printer-make-and-model attributes.

+

Type 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 Form File

+

CUPS Form files are XML files used by the +CUPS formtops filter to produce dynamic +banner pages and support preprinted forms.

+

The MIME type for CUPS Form files is +application/vnd.cups-form.

+

4.3.1 CUPS Form DTD

+

The following DTD describes the available elements +and attributes in a CUPS Form file: +

+ + +
+
+<!ENTITY % Angle "CDATA" -- angle in degrees -->
+
+<!ENTITY % Color "CDATA" -- a color using sRGB: #RRGGBB as Hex values -->
+
+<!ENTITY % Length "CDATA" -- nn for pixels or nn% for percentage length -->
+
+<!ENTITY % Lengths "CDATA" -- comma-separated Length values -->
+
+<!ENTITY % Text "CDATA">
+
+<!ENTITY % heading "H1|H2|H3|H4|H5|H6">
+
+<!ENTITY % preformatted "PRE">
+
+<!ENTITY % i18n
+ "lang        %LanguageCode; #IMPLIED  -- language code --
+  dir         (ltr|rtl)      #IMPLIED  -- direction for weak/neutral text --"
+  >
+
+<!ENTITY % attrs "%i18n;">
+
+<!ENTITY % fontstyle
+ "B | FONT | I | TT">
+
+<!ENTITY % graphics
+ "BOX | RECT | LINE | POLY | ARC | PIE | TEXT">
+
+<!ENTITY % insert
+ "IMG | VAR">
+
+<!-- %inline; covers inline or "text-level" elements -->
+<!ENTITY % inline "#PCDATA | %fontstyle; | %graphics; | %insert;">
+
+<!ELEMENT (%fontstyle;) - - (%inline;)*>
+<!ATTLIST (%fontstyle;)
+  %attrs;                              -- %i18n --
+  >
+
+<!ELEMENT BR - O EMPTY                 -- forced line break -->
+<!ATTLIST BR
+  %attrs;                              -- %i18n --
+  >
+
+<!ENTITY % block
+     "P | %heading; | %preformatted;">
+
+<!ENTITY % flow "%block; | %inline;">
+
+<!ELEMENT PAGE O O (%flow;)+           -- document body -->
+<!ATTLIST PAGE
+  %attrs;                              -- %i18n --
+  align       (left|center|right) #IMPLIED -- horizontal alignment --
+  valign      (top|middle|center|bottom) #IMPLIED -- vertical alignment --
+  >
+
+<!ELEMENT P - O (%inline;)*            -- paragraph -->
+<!ATTLIST P
+  %attrs;                              -- %i18n --
+  align       (left|center|right) #IMPLIED -- horizontal alignment --
+  >
+
+<!ELEMENT (%heading;)  - - (%inline;)* -- heading -->
+<!ATTLIST (%heading;)
+  %attrs;                              -- %i18n --
+  align       (left|center|right) #IMPLIED -- horizontal alignment --
+  >
+
+<!ELEMENT PRE - - (%inline;)*          -- preformatted text -->
+<!ATTLIST PRE
+  %attrs;                              -- %i18n --
+  align       (left|center|right) #IMPLIED -- horizontal alignment --
+  >
+
+<!ELEMENT BOX - O EMPTY                -- unfilled box -->
+<!ATTLIST BOX
+  color       %Color;        #IMPLIED  -- override color --
+  height      %Length;       #REQUIRED -- height of box --
+  thickness   %Length;       #IMPLIED  -- override line thickness --
+  width       %Length;       #REQUIRED -- width of box --
+  x           %Length;       #REQUIRED -- horizontal position --
+  y           %Length;       #REQUIRED -- vertical position --
+  >
+
+<!ELEMENT RECT - O EMPTY               -- filled box -->
+<!ATTLIST RECT
+  color       %Color;        #IMPLIED  -- override color --
+  height      %Length;       #REQUIRED -- height of box --
+  width       %Length;       #REQUIRED -- width of box --
+  x           %Length;       #REQUIRED -- horizontal position --
+  y           %Length;       #REQUIRED -- vertical position --
+  >
+
+<!ELEMENT LINE - O EMPTY               -- polyline -->
+<!ATTLIST LINE
+  color       %Color;        #IMPLIED  -- override color --
+  thickness   %Length;       #IMPLIED  -- override line thickness --
+  x           %Lengths;      #REQUIRED -- horizontal positions --
+  y           %Lengths;      #REQUIRED -- vertical positions --
+  >
+
+<!ELEMENT POLY - O EMPTY               -- polygon (filled) -->
+<!ATTLIST POLY
+  color       %Color;        #IMPLIED  -- override color --
+  x           %Lengths;      #REQUIRED -- horizontal positions --
+  y           %Lengths;      #REQUIRED -- vertical positions --
+  >
+
+<!ELEMENT ARC - O EMPTY                -- unfilled arc -->
+<!ATTLIST ARC
+  color       %Color;        #IMPLIED  -- override color --
+  end         %Angle;        #IMPLIED  -- override end angle --
+  height      %Length;       #REQUIRED -- height of arc --
+  start       %Angle;        #IMPLIED  -- override start angle --
+  thickness   %Length;       #IMPLIED  -- override line thickness --
+  width       %Length;       #REQUIRED -- width of arc --
+  x           %Length;       #REQUIRED -- horizontal position --
+  y           %Length;       #REQUIRED -- vertical position --
+  >
+
+<!ELEMENT PIE - O EMPTY                -- filled arc -->
+<!ATTLIST PIE
+  color       %Color;        #IMPLIED  -- override color --
+  end         %Angle;        #IMPLIED  -- override end angle --
+  height      %Length;       #REQUIRED -- height of arc --
+  start       %Angle;        #IMPLIED  -- override start angle --
+  width       %Length;       #REQUIRED -- width of arc --
+  x           %Length;       #REQUIRED -- horizontal position --
+  y           %Length;       #REQUIRED -- vertical position --
+  >
+
+<!ELEMENT TEXT - - (%flow;)*           -- text box -->
+<!ATTLIST RECT
+  align       (left|center|right) #IMPLIED -- horizontal alignment --
+  height      %Length;       #REQUIRED -- height of box --
+  valign      (top|middle|center|bottom) #IMPLIED -- vertical alignment --
+  width       %Length;       #REQUIRED -- width of box --
+  x           %Length;       #REQUIRED -- horizontal position --
+  y           %Length;       #REQUIRED -- vertical position --
+  >
+
+
+<!ELEMENT IMG - O EMPTY                -- Embedded image -->
+<!ATTLIST IMG
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  src         %URI;          #REQUIRED -- URI of image to embed --
+  height      %Length;       #IMPLIED  -- override height --
+  width       %Length;       #IMPLIED  -- override width --
+  >
+
+<!ELEMENT HEAD O O (DEFVAR)*           -- document head -->
+<!ATTLIST HEAD
+  %i18n;                               -- lang, dir --
+  >
+
+<!ELEMENT DEFVAR - O EMPTY             -- variable definition -->
+<!ATTLIST DEFVAR
+  name        CDATA          #REQUIRED -- name
+  value       CDATA          #REQUIRED -- value
+  >
+
+
+<!ENTITY % html.content "HEAD, PAGE">
+
+<!ELEMENT CUPSFORM - - (HEAD) (PAGE)+  -- document root element -->
+<!ATTLIST CUPSFORM
+  %i18n;                               -- lang, dir --
+  >
+
+
+
+

+

4.4 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.5 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 +Image 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. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BytesDescription +Values
0-63MediaClassNul-terminated ASCII +string
64-127MediaColorNul-terminated ASCII +string
128-191MediaTypeNul-terminated ASCII +string
192-255OutputTypeNul-terminated +ASCII string
256-259AdvanceDistance0 to 2 +32 - 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 2 +32 - 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.

+

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

+

The Internet Printing Protocol and the CUPS +extensions to it are described in the CUPS +Implementation of IPP document.

+

4.8 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.9 Server Message Block Protocol

+

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

+

The URI method name for SMB is "smb". +Support for this protocol is provided via the +SAMBA smbspool(1) program provided with +SAMBA 2.0.6 and higher.

+

5 Directories

+
+
/etc/cups
+
The scheduler configuration and MIME files reside +here.
+
/etc/cups/certs
+
The authentication certificates reside here.
+
/etc/cups/interfaces
+
System V interface scripts reside here.
+
/etc/cups/ppd
+
This directory contains PPD files for each +printer.
+
/usr/bin
+
The cancel, lp, lpq +, lpr, lprm, and +lpstat commands reside here.
+
/usr/lib, /usr/lib32
+
The shared libraries (DSOs) reside here.
+
/usr/lib/cups/backend
+
The backend filters reside here.
+
/usr/lib/cups/cgi-bin
+
The CGI programs reside here.
+
/usr/lib/cups/daemon
+
The polling and LPD daemons reside here.
+
/usr/lib/cups/filter
+
The file filters 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/charsets
+
The character set files reside here.
+
/usr/share/cups/data
+
The 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. +
+
/usr/share/doc/cups
+
The scheduler documentation files reside here.
+
/var/log/cups
+
The access_log, error_log, +and page_log files reside here.
+
/var/spool/cups
+
This directory contains 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 Page 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
+
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..b00ade9253 --- /dev/null +++ b/doc/idd.pdf @@ -0,0 +1,890 @@ +%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[12 0 R +14 0 R +]endobj +16 0 obj<>endobj +17 0 obj<>endobj +18 0 obj<>endobj +19 0 obj<>endobj +20 0 obj<>endobj +21 0 obj<>endobj +22 0 obj<>endobj +23 0 obj<>endobj +24 0 obj<>endobj +25 0 obj<>endobj +26 0 obj<>endobj +27 0 obj<>endobj +28 0 obj<>endobj +29 0 obj<>endobj +30 0 obj<>endobj +31 0 obj<>endobj +32 0 obj<>endobj +33 0 obj<>endobj +34 0 obj<>endobj +35 0 obj<>endobj +36 0 obj<>endobj +37 0 obj<>endobj +38 0 obj[17 0 R +19 0 R +21 0 R +23 0 R +25 0 R +27 0 R +29 0 R +31 0 R +33 0 R +35 0 R +37 0 R +]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[40 0 R +42 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[47 0 R +49 0 R +]endobj +51 0 obj<>endobj +52 0 obj<>endobj +53 0 obj<>endobj +54 0 obj<>endobj +55 0 obj[52 0 R +54 0 R +]endobj +56 0 obj<>endobj +57 0 obj<>endobj +58 0 obj<>endobj +59 0 obj<>endobj +60 0 obj<>endobj +61 0 obj<>endobj +62 0 obj<>endobj +63 0 obj<>endobj +64 0 obj<>endobj +65 0 obj<>endobj +66 0 obj<>endobj +67 0 obj<>endobj +68 0 obj<>endobj +69 0 obj<>endobj +70 0 obj<>endobj +71 0 obj<>endobj +72 0 obj<>endobj +73 0 obj<>endobj +74 0 obj<>endobj +75 0 obj<>endobj +76 0 obj<>endobj +77 0 obj<>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[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<>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Ð=_q—šØÚi냥 +&î|Ô PC€´UãßkݸšäÎ=“Ùšd¾O!L•æKÐZó5L5Áîz¼àÐëꢴȬo›>ŽÒµch‡~jî_­A5)É).#š²Œ§Xd´à)˜\r×yá߸ uxÎâè†êQÿ+jõ}ãgß®mn”¦+&…3lºçzœ­·îi«Hs“œ’!@ñ endstream +endobj +140 0 obj +6290 +endobj +141 0 obj<>>>endobj +142 0 obj<>stream +xÚ+ä2T0BCc3JÎår +ár á +äHÉHendstream +endobj +143 0 obj +31 +endobj +144 0 obj<>>>/Annots 15 0 R>>endobj +145 0 obj<>stream +xÚ­UMsÛ6½ëWìädÏT I‘’œ[¹®:‰Ãšr¦] ”ƒ€RÕ_ß]€ú°’v:nÇ3´H,vß{û°ø6ˆ Ä¿&1ŒÆPԃÛÅàíÏ7‡°¨pe<™Â¢¼Š /T˯_Ýj4ñ«ÃQÄn=ˆ`^òƊJÌ +ÕøÐ¢¨'Á˜Ba@4–ëŠJnĺ¡…-í„R]¹ Õj+pW-’—Pá*¥kfÍOPscØúìkJÚ´Ö¬¦úX5y€…j¶O5†ÂÁn8|Puåžæ¿C¦’h֐ïå5,¯Þ|xÊò7ËkøÂµ!XÈ1ø^€8H¼ñaëç-×[Áw{·„AˆÓ#¢Çã=$ã(˜BšÄA5$S‚èß$ä¾'ÝÒdDù ÌI­Ò–­PŒö\²=׎ZÆéx¸b5þiæBŒh˜[Ø0+ÎIù-—SÂjNµ—€õ®î˜Ùÿ-|4ž"%$iÿB\~ÀýPÃ4:ní™ÓëMà,—«Êî˜æØUv…5/±…l` S+ËQcÑL—']Œ’³IäôýF3”Jç˜Î`‡x!ñ…}È.}{¿¸=·\?sÉ÷P ‰ðÃPІŸlm‚>A<öþpɱqΛS\ÃíÉvHÒªBI2Þ<ËÈwÌÇb…÷,Öak +vÜà«Zyüß:ÞaEX`ôG„qÝÕ@kÌ'»cÙŒ +äèSüþ©?E·RÏ´œºÅešÞ·mŽŸêòŠÏ àWngBóÂbж‡@°SLuQÜt-Yݵvšc+éwMAMaRØ}/=+K(ÊNégOÁ­´ÚâL`2elîÆô¤.ªÍΦÉW£§[úªX‘ j—û¦ãf‡©~>ÿë J¯YãtÇ-Ê™JI©vîðsg3óŽŠáwìaÃó+­èQ '8|B +XÆã ¼„HkGabLðÈ+ŽÍ,ü¸xM–fñÀIÿÃM×¦K0ÝÝÿ[ºÓù£®´x}š÷˜æ^*œ2zÿ/rL‹x1 Êq’ZvlX2 ƒ¿1êï¥ßªô gendstream +endobj +146 0 obj +963 +endobj +147 0 obj<>>>>>endobj +148 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS045Ó3T072PIÑPp VðÌ+I-JKLNUpI-ÎLÏQÉE™%™ùyš!Y\º=ºPMF 13=30ßP!89¿ $êÂÈ+Å ÿendstream +endobj +149 0 obj +115 +endobj +150 0 obj<>>>/Annots 38 0 R>>endobj +151 0 obj<>stream +xÚµ˜MSãF†ïüŠ>nªl­4²õÁ 0°¤ ÖAbO¹yl”²$G’‹åß§{F–ÚY3rÀ)ªLõh>ºßy§ÇŸ9`㟾׃4?»ŒÏ¾Þ„ lˆ—øÄóˆ_<Ê¥¬d‘Êú·ø/…8¾FÆîÄ +²¸zšG0+Óm.‹&i²²Ðø§Å…oy„Ç/–åz]¾fÅJ¿¸à/BVCµuÏoмàW;æœ:Æ9…gM¨?êa|õ0;–s®û»*‹e¶ÚVº¿‡¤HV’Þ…ù:i'–¶ûV€³Ã~þžû³¦gcÇÕËTãÜÍflœè­ndwE#«e’J˜É:[ô/­²M†Ž6竺Ë7kه©\>ÿTÿÑÅõoýÜ­§\6¯I%áb‘gEV7Á²ª)‚Ûdý¹¡ö·èÄ‹æï,h^•«*És’Ü)V=ZM$Óm•5o¸k6eÕ|nˆx~hˆXÖ'qôôNœžjy¢|ÿ8˜ïØ=‰÷¿%|g:càcWè/°ñ½y‘Uç<õ‘®S”ÅxÏyj Ù ÙÎu|f[6:'}8ôñx‹þiÙà.Ž“ƒ êÆ¢4rœe€«5áŽãq~2È3"G7<'ÂòÍ<#Ÿú˜#ψ\ȧÈ{Î@8Ýi`¹=ïOöú¿ü%_ՊÎ;7˜hU\,Êg4‡²n"%Gô‰ŒÌœën²µ„›²Ê“¢L³e–* uržX®EéG³ÛьÊ6èÉ·Qã;=©†IO-Ýêɀ·zÚñm!#ÏÌ·#(ڞȻ¡55óŒ@Þ§¼ôüÁüõۛ2é;Ú ~Éä}R¬¶xî÷Ì◬ZÀõ"£ì}$aï8žÃçð{ù I±è$ɾo¤.Bꏚ)výUùèu‘– ò.#®’¢þÌÓuÛäû·Ûl!?ÝåC¹k5ÍHæIÑdéðê ;Áž(mL•PT㰔Càw¯¦@ûÆÀ9A>,H§&žÈÊ5M<#hŸ…VÈø#ö=Õûàñæ +¿õÃÜg…ìý,‘9ú–AM™–ë“z•T@›!Ý0dhG«˜h`…3€s‚2b<Œ<#È 'q#Ïä}ò]#ÏÊèt`þœ “•v•‘gò¡½üaňPè}KŠSÏíŠñÛ2Y×X,U¸‡õݦíÉHþóÿh£ewR “†ZZKÄ@3s†u£çiȘ 'HC.îa#ϪÎ<Œ‰çi(èŸtú*ŚxF ïэÚÈ3ù`:ONPõGµAÏ¡Q?d + Fð¨Ód-•<±ô‡¨©¶i³ÅâïÃôEú˜…ú¥ëÂ,ñ +Ú£Rt'hÕ0 º¥µ^ 4ȇ:ç 4 t›xF ÒEËÈ3‚J庉ç]7B’«‰g•‡ ¨ã7µ&!<’͆rü,›W) ¸ŸÏ”Z°|éò^ŸÖÛ¦ŽºèL«†I +-­3m @Þæ’SpNÐù5ÈûœÎÏ Zóô9A©u)µDj§BßáTj=ÇÁ·7,·ù³Ñõ1–ý]Fa<†oq¬*ÔÓ&× úòT7LÉmi;Í*O} +Žç•›ÁÀd8¡‹ßÈsB,æùp"ow¡‘g3¹PÇ!7ìË_3”m¸Ø¢ÁÓ Dçp™ÔYª¶û,[Ñ/ii*ëú½bÿõ#.FÁî¡þ¡ª›Ö¿GŸ6®P½í¶úúãìfck”endstream +endobj +152 0 obj +1334 +endobj +153 0 obj<>>>>>endobj +154 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS045Ó3T072PIÑPp VðÌ+I-JKLNUpI-ÎLÏQÉE™%™ùyš!Y\º=ºPM& 1#C=30ßH!(5-µ(5/9µ$åÂÈÞÀ#endstream +endobj +155 0 obj +120 +endobj +156 0 obj<>>>>>endobj +157 0 obj<>stream +xÚ½VM"7½ó+J½V‚Îð± dN»d¸DI†(—¹˜n7íÈmwl÷ÿ>U6†îžaw¥H™‘À4õñüêUÿ &ð€ÿxœÂlY5ø²ü´YÁôv~³x\Â.Î`«7ŠÉp(XÆíÇÝßÞvòldzy:õÖéÖ%3,CSxá6BFû9L&ûécº û]É!»Ú[´/Èr^ŁAÅêZ¨ì¹;r®`9Þ ws±ÀT£ü©D¦ó^´h] fžÌÒhOþµt5(´r6uf8(VñK(Çöy·ñ (}æ ü±Y+üóþ–‡‹ô’RÐÏ/ëí?!: +šaR®èŽ¥ÈJÕfFì1îžK}La­« +,dLá3L—É&§ïÏ-|æ‡ ÍÃ]ڇ7nz°<¹ÂXäV˦R‡Ä»¥×bÏcñVéüRl,÷rü+òcE'¯^[E·ŽGáÊKj0œåx¹ŸãÅV Õ:žÎ„XŒ%Æìæ{3/²–Hb É¥"Pt‹™‹Ró`)ÚB›Š9¡Õý¼*Éð%†gdÈs„®È[Â^KT…cRdþ<瑽’"ö Fâìz )ç3Ã[$'ì Ïui!V—.ÛÉß<ÓÆp[kê ‘Ñ“o»“¨šŠT0ý´èÉ¥Õ}9RX#•³q†*>ÝÔ£XÍn¼ÃÂëЗ„ª¿ië^Pöµë哢Bòˆâôõ#uW¸|e²á¡ž%?±œg™O»„‘î¡h¿ÄJõùÖ3d!né´IF§eâGˆ?²©ÌE†HÐJòq(±“ý}¦çÞ§ó>¶Õo]Œ†À}¸‘œ¾•Z_òÄcÌu³Çó„Tœ©‹Æ]ä,°åŽ"ÃÉgI±þ=̤[]ߟk݁ëÎ5§5pú¯¾F^ø#h+ÿz“Ñ{â~Ó(o5“[ÒlCsïîW£˜qF¡À¶èl ôÖJžûóø+’YxEM$÷,}2å}ðå–l©Isgˆu(ú×!O)$/ç +á'$Ñg‚ãûͳ5»Ø…”=oAaˆ\•ÔŒ&»(@qŽ' x$,~K!Âô!’M axńòºô“íº?oséŠ;/´OœD ëïa¿ÅZ\ø·zðþà<àŒݝÆà*î”éèo•w×ÿß+\aT´¼;¶Ÿ;oú4ú·ÅêUŒÿYƒX9/1|i7vãŠeBQlS×Ú xúe¿»Õ|íãO‚ÿm¥-ÛÜÌVé·<Ηé +«‡6Ÿèóónðûà_«¡Rwendstream +endobj +158 0 obj +1014 +endobj +159 0 obj<>>>>>endobj +160 0 obj<>stream +xÚ­WÛnÛ8}÷W üä–Ö’ãK¶OmÚ‹.â¢/ +š¢l©%©:Þ¯ßRò­ q,™Μ9CŽþd0Á¿ ¦súðjðq5øížA–ÁªÄ'óåVÅè^Zçß­~೛öÙ˜. Žuö#Å^0³üV@IaYÁFíë­©ãC£=T¬®¥ÞàóÀµÂÕí½‰CdôÚ=˪©À”Ïæ´Þ’lšæä*ß2˸ÖgÖ"ÀŠvÒoq5Áø6Ö4õ8 ý‚×¹áài„3ÐE‡6_ŒóÜÊÚ_¬§d%=óÒèôé¬0–üdª.D¿Ϭ\VL¥ç„!N>Oo瓴‚Ì%¸<1ä¼%n†Ê;ÃÐz£ðjl¼eC¤²=A+%JŸx“X¹Ùú1„ ý¦ñ0çl>X¶–ü"0/žýëî~“…ßþ‡«¿• Ó¬ñþ=ĨÓ.¦ÕwœE¶üNrÌavŠpýðx÷ðǼ^øÙ*èÎ4V + ~_‹’qñºë‹™ÃÚ¨b ˜<c?‰dü’¸É>yÑü ñnqGšméÚFÅÕ(f¡[¡ÀCyO˜m´Ú_Æ~2©‘…!2ˆl"¹{Óa~—·5*HôJ:¢‰t“Âðq_¡ûC’ègr'Ô[`sÖÚî¤R. FA0ÄGavZ”r²-Þ!àŽ|©1å$½–ö[È-íÓ<ÒN0½iØFÀ½T³HZ¤s2¥*RiI¦PˆRêH2Þ²Fù#ƒàDÜXîJÅ2¢j& £ÒœCœv«Áˆ;䔪uOì_D­Y…!®÷”´R>Ç-é(kÞÔîû0îJèž%*i±S§]õ^’» „YBSé†Û’ªXxŽ)¹X>&£Æh´Ãܸ¿3TH•±”\-Â`,C¥žˆ|uØqɰ”0=èP¬Ðsê0’.ѤW2èH op/ÖՆ{”Ùhùš7¸ßim<>‹Kg’årv›d1żMq²H—˜g´xÊç 8Ï?=;u‡÷F˜öF¸é0ë0荰ìpÛ!›ô‡è¯ˆ¬¿$²7k¢q s\Ê7Ï÷åÛS¹Ã.Ãì\²\Üô…ÈòÙä +Ù0ò+`L¯€q NgWÀ˜_cqŒÿ#Ó$_âü³ÐáiEmþ»†slXBsNÏ®¡8mBcvrüŧØ!a#À©Û¡¦€nªµ°ã؄á×åH<- ќ`šº`Ôi‘C¡]$xVÒ9L?O ñ,n;©e^6›§Y÷>w_¿<ƒƙ¡ïû$œÜhº„W”ö-"‰s’E8 IÞN‘ŸÉë ÙçÕà¯Á¿öùíóendstream +endobj +161 0 obj +1028 +endobj +162 0 obj<>>>>>endobj +163 0 obj<>stream +xÚ­WMsÛ6½ûWlٜքDY‘¬Ìä :öTÛi­^÷‘ „šŒ£Äýïݨ3’{jÏH&ñÞîÛÅ.þx@öàxiyðëô s>‚dÓW' L³Ãcv “‹38—…°¯¦ÿ ¨I@qoÈ;ýóý5ÔVXpw:r"€T ë¸Ê¸É Õ*—óÚp'µbÁ:í¯ìX¿qË(e)˜[V;lº[ ï2‘KEBp͈Tϕü"²°`(…tXiQ™Î1 Ú@©€Â3ñÕøút2'>;§º,…r$'ǬG®ã2î¤[x•®ÑöÍaôctó +Ò7¦;HÅTï0´¡ï–²Û}p„ŒÈÿå}ˆ¹ø\/÷-8¬~"nS) ®óÜ +ÑQ…PsÜó'˜•‘ÊñY!^Ķéó5¼|ŠJMÁ¥²{ü~¿l̖O¼¨Å“ÒÚ¸—1_/¡:å!Ë[qµÐë£ø… +%ü|€BÏ%òa|ùþÞçƒÜ ÛèëêÇI?Dë¿?@­¸YÂåÕ4p6gyìûx°:ÍW-e8w7ðCz·P>ëmœ?2š.+´¾…S€ö°ôŸKJà¬2·0[: óÇg·Œ3˜ÉyŒç¯ä +ϼÕ)×:ÖJm]l%Q9æC¹`(—ƺÇ[/Ì,¬ÕOÿ×`ÃGa=o´µjLün´­«r¸î¼ã^¨Ê>\U>ßqÏ+¹ §,%ÅÄ¡.3ð‡>Цê`,Ü©ñÕÅ6‚¨ CÈv‰÷‰2ܒŒm%ycÔÂÊ¡Üfo»Ä=máÒNZW¶ST™ÖyA›Om¢yæ› +»øÂÍŸgËBxÌíO¿]]œuØ~Ÿ¬I»]ãmzcXþOéz§­Øsè}mZÂ<‚—ÄZ7ߚ¾!#awš›§Æ÷:ïW½³¿êÞ¡aPä"Dö6ô҃ÆØƒÁØI|Òëâ 0zÝL_YÚúœ¢Fx²ÒWj¤7Bô8y=@V<ìuwÿsÒ?é²øÅ!=ŸM~?ø·;ؾendstream +endobj +164 0 obj +1191 +endobj +165 0 obj<>>>/Annots 45 0 R>>endobj +166 0 obj<>stream +xÚ­VMsÛ6½ëW쨇:3MR_V:=´IÜñ¡5V{Ê"! ) °hWÿ¾oR¢åXJ:Ë@.v÷íÇ[ü=H(Æ_Bã²rðËjp}ӂV~2»Á*¿z/­#-Jy­´uBg’Lå”Ñ?=Š¢9ÙDQôìÁ›ÕçAL£$Žn‚®hŠ îÿÑò_º¾P’0Ò ŽÒ+^í$JKZË­ÒZé-=)·£akqHJç*NZrÍ[Gr„HiÁhcjªj¥}6kû#‰ƒ”׬´?ÙXYw¨ÆQÊÆƒ‡´QÜ”u­òf6P‘w:ìÞ:YRï\‰Y̸¢ +¿G¨žÃ¾"´‡\là¨w[Öô—6O0aüëÂd¢ ¸ —^××fáÔF&4‚IBïɺš +K…t0c ݔk¿:aÑ9ö™©±¬Øƒ$S¶µÈø#/¤Þº]Ô¯³Ï™«e)+`®Kef´Ãc |…B%㝭D&GVVÐëÏAÛy¡jòeb[¸ Jæ-Üq̍£)-uY­*GË6phÿ€óq‹|Øçá`瑯´ ‡?] —Ë÷ÃOo|Z-Þ! +•X«B9…7€#E¶;äŽ1ˆÚXNë=½ûcù€@žÔšmªÊÔ®;5²•ÌÔFe´‘Â5µ ±àwE¡¶Å ? ˆƒ2é0-A‰‚ßôЪóÁòVƒ8ŠA7ü•ð×Ç_)™Þ “äÇKJcü†]AŒŽ‘›$‹c¦Ù†ï4[)Wr!߯›\Ä=“éxB9š|)ߗ€ü<À³ò=‰’Æø=/ߗ€ü4Žæçå{%MâÉÿûO'ô÷% ?¡ÎŸ¥ääH½=d±MÏϹA™®d¶»7NÒwÓ8¿ýš^¡[ŸËWS‡ àLQ¿%Íx„Í—qôJZ°ÿç¤{¨Ã$å”Ä4¶³Ð8Ï*›þ'ñï$û;hŽÛà\ï–4´ç‡œÔÖS(‹û5òàƒþˆÈs R'ƒœµ|"á@¯ë&L&´sÀ±'Ö²0OG_NÙÛûÔYSÙ[ßè/mˆÍÖRùÁ&xÄ<úq%˜oÛ°ÔM!;.æN}´o#”›×jMSgòÚí+&lËÄd¶µ(ÏNêþÔõ'ᙰ¶)¸^-¿}o½@Dwý1ג`˜‚Áƒ 'WµÌ\±/8ã¢8!Ð@‡›4 ©{u-•ÊüR¸Sî߄nDñÎTêK ï}mL!1NQׯ±¥àãݲ%é¶ÜIˆ:عÁ íð#à՞@ò¨%/¨ô XÌßü Ѫw w+8¶…•—ÐŽZ“ËâÞOýó`ÙÕ-³Ø.®ö˜ÁãØ*Yo{`/¡!lº H7=ÏÜ R”È?76DÏ4®jœ¿Ñ :±…²n½¸„|â‘/kÃëûª:3…¿ZšpCüš¶Â 7EÃI ­•3Í8$[”¥ UÆ þÁ{ ÖpªL°N±N±NÓ ù¦u7IyºÍÓp äuÇ1ØàBŌ®¶ºOì||”`Š$4šC+Ýð³Œ;§ø[oR˜ ¿þ 1ÁÕendstream +endobj +167 0 obj +1197 +endobj +168 0 obj<>>>>>endobj +169 0 obj<>stream +xÚ­WßsÚ8~Ï_±Ã½›âúèôn&%i'¹Ëz3É‹°å Ö–¨$‡ðßßJ² ˜8¡¹Nfˆ±v¥ïÛývWü8 ÀÇ¿Æ!D1$ÅهÅÙۏCXd¸OưHû‹…óÅ7\Š«¥¾¤Jä¥f‚»…Ú§„§mc½]Ó¶ÙÉKª  [XRè z DQ@`Ãò4!2õào½¢rÃ|ØBQ*N:YàDf^»½ýö ˆ¼Ðÿ܉RH8ôêßД‘ÅH‰Ö’-KhSš1NS`Ü ··—±œzƏ coد”rÅôö„`ݓ¢ Ñrçƒ5±¾Õ¶@Òo˜‚r YÉÃT‰AÒ+¢ßÕL§f3Lô : Ù]ÿñîþhöùkãIšÝ!î Zø~¼^IQÞ¯Ž,Ãðyš¢Ç´$\eBbÒ +ü'Ù#à ›‚ÙÍWHDŽßœ¯Ó^´÷ÔÐD†¡ÄÖëœÑ£à“LSyŒßsˆÄsfӝêêôGÞÈ ½$åZýK¥:’߁TŒ¤?J&M#5d |Ä`lV óøàö©³/·s¸¾¼„ –K©ÐµH­I ÚDApåµâ0+¥D¥ä[`ÚÔÒV(<ßC/ðüž©|z;žã +{ÖXæ„·»}ÕncN +;©HKÝ.ƒìS*ò\l\ʺÚ^æZ™[²l!jœ1H¡cäµi%úQ¼Ñ؛ ܉ƒ{Y{£÷Š0ºæ½m7ëzR^-Î|ÏÇ»AóñùØ¡†–pàOÍç¡àÙó'Œƒ(ò¦•u„§÷¬.6¡?qáý̤×FìÏá÷oíš}íΏÏۙI¹7Xu8m²¦Iw³ &”ÛÍvµgÙ8kÇfgl,‡`W@/iFÊ\ÿb*M‡OÝöfDhÆÉ)4G1ŠàdšÖº“f4v$.’„¢`œ0Y¬iÂ2fg5×7 Ûñ1£·vN7ðM,qh߸k`]-ª°ÞWªÜDúKô^"ë>O%k­;Ɂ«› S„_p®¨[ÿ+ÁâÇQŠu^;7µLi’ª¶íý§’Ú…ã%*þ¨‘çËÅæ¬Ÿ(6KeºP~ œS97-ª“ŠÁ·´vŽ&ÍõvlP43ÝUØ´ºñŒ—abÒø™Iìù's±Æ]TÆÑŽÈO_CÃÞó^Ã"ÞUÒË,â]!³E¸h[/ß¾RY\èÿ¡®áø':¹5î¢ ]á_óL´X\ØÉ[’¼ºÑÚS_NAi'×ÉófÒskÜLªqcš›ù½kÁU×hsiÉHB§ »çІç3¨œìíÞy^5Wl~són®½Ã‰x¬Ã´"øÏÙìßQ¦endstream +endobj +170 0 obj +1287 +endobj +171 0 obj<>>>>>endobj +172 0 obj<>stream +xÚ½˜MoÛ8†ïù„öÒ±ªoÛÛSš´E€v7Û8· F¢mn%Q©dóïwf(YŽYÊe‘Æh¤—äÌÃù ýóÌgüø,Lð_Zœ}؜½û1ßg›- 7bÉ*f›ìÍ•r#Uùvóϙï­ÝÆÁã fÄ¿¦á9Ë[S[fö‚¥9×ÚEùÇ͙çz°ÐáãÛgD8÷r官Î_»«»}A쇡»nÕa°r—Gj°ØÚ™ÄðLº©eiD=0ô¶©ÜJ¡g•U€™Ü0‰O +QÜÃט“ÑsM'õ¨éQoÑHÍ5M“¥4hkT>³÷=KyÉîs®³\8LÕ̹5ªªDæLùyð9ÛRú,á³óå«Ðšïĉ½è§°J¶Uµõ©©kQë›uwʋÀcf{Aê¼x÷iÍüÃßcñš\ ÝiSéÌMU¹E;ú,ñØ"X¢lCfw"¶•9ü­J-µÑ¸U>îI¡`¡\–‚]Ü^^_—]ª¢@íKð¸6ìQš=á¨TSfìûç7çû[\VõC° +ÖM÷¼æ)´Û¾ €yºg¥*÷9/ÐÄv^ÝO\ò‚∣©[¹kj›Å™¬EjäîHž«G‘±û'&aèÏá2ôÖ¾’ån`Ña0ì0¸ ¦‹Z¥²ß-º¸E/!e°dîU7ʆK;Cár%¶¼É =£.ˆ®„NkYu5i<.¢åk2ÕªWkøï)qôâ ¤*ö<ˆžÕÐ(­‹i +qþEíÁéùß¹}aWoY>Ïÿa•µáñŽâ¶e°'€ £vô“±Ó‹FÃÆÅ´€ð²“ †ãÔ²„´,ì ƅa# +\x"-£0r½ÃÇiü¤&§Ä-~[ü½º«D‘µÐ1HÀÎmé%‘Æ$(1!mÙ¶V…õµÝ‚Œí•6ç@¥0ªþqŽÙ©‚ËrŠˆç2 àÁi"¤&SO‰["$¶DzuG$\‘ÁÙ_bYb҇Þ#vÊ\<ˆœjL•J¶¡´?ÈÞìý€MÁŸ¨%ÝiQ;çА(jbå|®USMõ¦0Yªú4,«ž ˊGaEë62ÀÛÍS5lb¨RŒð10è\@•¨1¡Þ3à3 †´pj¤õk™¶°®äNh3I+Lª´H=—‰GiùKkÿ‡ÒH\dY-~ ° ŽÝ£ßqzœÝ׊g)׆q;Õ¡H]ÞÝÜ™ášÐ…XÅÓ vŠ“N<38‘z.'q +V‘=¥¶œæ”¦ž –áÐBm‘zÜKèô†ãâ­÷ªÉ³®ðO@ +–Á¡rOC²ê™¬xRØÊm!]‰òéÿgT*3—S¸~E=·ê¹œÂõ‰zøá1§k¼ÔÀélÀ*ô&ÎeÓ]~´€þ—iðÛ< +QŽÑjª ŽãÚeV×»4Nâ¦É¤æ÷¹ž(Tcvê(]'ðúë× ¬zæŠÇ~t”©ÖÙ/wJÊÞó.<햆¿òU8Éå<ãe6ÀÒûÑỪžÉ€Vw¿ŒrpÀ9Íé`”E•ËTšfÁ©l:4eN5t/†ýÏç¼?àógFâÛÏpÍÞñáš4Õ¬EÁ:ù|Mr—œ +¯ÿÖ`O譚6甸 ۀèÕ]@¬ÖÇ;u—Ÿùe‰CVÔø¥´I]þÀeŽ)Ò}%¡_ˆ º‹©,Y&¯hhËd~?#íXŠ“ãnv£j3 ’„þéCÒÝÕ ð€«n[…”\¢ckˀƼšE¯è\Q4¿qEщ¾ú=‹o"ç/v­S_)‡=\$ÞjÊn«'ÃOËÛ^‚-×CóñcD%6œ9ÒJ‹vý‘wWàU{ö!J|¶ ˆßµª-Oƒk¼Ü•lp›_Ø1‹vO-,ò7l{Ú ßÈØ¿ÎþýZ2endstream +endobj +173 0 obj +1479 +endobj +174 0 obj<>>>>>endobj +175 0 obj<>stream +xڝX[oÛ6~ϯ ôÔ±­‹¯hQlMÚ5XÖv÷V` %Êæ*‘I%õ¿ß9¤,;LtÉ qäG<ß¹}ä¿ á'"‹˜$s’–ïדSEd“8žWd¾œ‘uöênÏRžs¦ %ZV*e„ŠŒdL.¨áRšeŠiMr©^¯ÿ¹É(JÆ1.V¬ .¶d£äƒfŠp Ò-˕,‰Œèj#˜!Fz«©fÇÔX_„ãvÝüúöl4ÁÎâñŸ‘él<'Š‘»g°Óy _ÞÛ-­,\Åsø¸'Ëڄ‡H}Ø1ô‘HEÀ[à€ì•¼ç°‚öˆ8<ãåû«nv²øŽ‘à öž©€ì©2ß_cÀ±R¶¸0Lé +§èIŒŒ¸-'èf /Qby±hëN¸&тãd TÐG +g«äœÂ5/¸åñ—„aÃߑ‚H¨Ê r˜ÍR)2<>PnH% /j6<Ï2r¶…¨{–¹¼D³…Liqžéž…‚kÓÃìl¿3]ç˜uhëhz:°cö„n˜MϘ…ôHý"çdD¶ìӂB¡oÎlžñÁ5a‚n +–½!)dÉùEh'ø’çAWÓøYèгЁ[³0ÆGàÀ55ôš+ªI¥ÕDï E&iµï¨e̙Œ+–©È"¼å꯯w$»$糉汦Ͳ>nìvscqC¹±à6n¦«ÚÍk–Óª0WÀƒf~‰r-GËål5ŠvÂg¸q&H +6hŠ)–zŸ®Â¦€¢0Öé¸C»NÑvŽ;°sü„n_,ê¤p»¾¥b[Ñ-óÇli°ã=Ôq nu|#.ž·#?ù¿±¼Òà t]yo{iÓ?uíFvR›K/ïaä?HõãÛC&KÊE#nÃkÀ¡ր·Öè!ÛK¯eZ•íoRšö&‘Éôq£x.jK®5(°wê}4D§V0 1¢¦ HŒèÔ +ž&FÃÚVÄ¥¤º•þHaøøïÂ=ï˜Ö³µ-ÑV&Θ¬9C ?W@‘@4¬ +޳/ÃA¯ ¦Æ¨?“Î'`mZ´a%b{˜N`†ƒ‡·CÞÜ6¼“ÙÔ1ý›’ÕÞ£“坸¬=éH[4ae$ÚÍ5<¤†À¨¶ôÁòUª„@ÉÎ~B‡ €@n-ûDd2^0¢z`y:p[y&aìvþ º +ð[)Ôõw®xò¼aÊ®ëÓáLaêÀ»@\kFn¾úǓúØS¸×áš-sš¦[ÌaÛCæß’ e=ÅùT£ƒ˜çšoì>šâðDÁB\ऀo¬wKœÏ@ã#+=ÜـðOZÞzxu ڃ\>â4&úŸWÂvsLˆ?X/úúR[LŽQ¨1a¶Gˆ¬Q~\¤4F݆èϘ9µ‰ 7nNÚò–¿P`ÇQØ ÐrÙ!‹¶|uëY°‹Ð }ŒP´ŠÜ†glÿkÁïÙÿ?@h sYf>­×~Mâ Fö $‡ˆUª©½1-–êìïe=°—9p[/‹,yçLµ‰»»>-%}m'€õHÚ0ØÆÚI½j¹Û°Ó8-$óïSéÑtþ‚£›Cå˂[ùJtàím-"ȞšÝ;Ͻ·“ã×ïN4Ö´ÚTm„ ²Þ(žèì)ö|#û—Ÿ†=” ncdº}v “«ðOj ‡žôÁ+)Œ’…Ÿ:´S­@5m¡7q_5<vcråtöA°dlSmƒK ÝÀ?T üÖZ ì± °>r][°ÍF©2Û<0¾6®æÐ{Íð‚&hÁ{ Å¶µ@P0–ê?èÏ«‚ƒò÷ÇStvËṍ¡¤?yY•çW]ða¨€îàXÅ©{ +kˆÜ=-*;`ìDv¬¼äÆ©èh’ô\.NǯÑ<žöMx‡·þtÃë ‚sï +“°hw;ZǯhW¸öŸúwòqYßvG³ùoÂ-éN4Ý C9)uÍP€áŸTñýñpä֌êEPŽÀ;ù²1´R+3§ ÌÙ¨&öϋÿß+'endstream +endobj +176 0 obj +1711 +endobj +177 0 obj<>>>>>endobj +178 0 obj<>stream +xڕXßoÛ6~Ï_Ad/-àÈÖË6ö²6]»Ýæ%î[‘h››$ª$•ÄûëwǓe[±% ÜFúxä}w÷ÝÑ?®|6Ÿ…1þ&ùÕÇÕÕøsÄ|Ÿ­Ö,¦Þ‚Åó)[¥ïԚ٭`VYž±¢Ê…fðŒ?q™ñÇL°µ„T˜DËÒ*m¼÷«®~]]M¼ lÒ|Ü»!ڝͽ9>cþ ˜ìá 6Š/ˆ=¶›Ÿ¬Ì®±±8ŠÑŸßùËWµyÿ <§?Yx‚/&ø÷|–`¯9>y(E"×RÇ@Î_d^åÌÀRV³Â“D3bBk¥GŒ)™°?„ら’oËÔÆ±d˜,ØãÎ +ã±»53­°9X*X¡ö;´L¸ý¤A¸Ç¾6¦8¡!(V¤ŒWVåÜʄgَ=ƒ¹– »Eµ!ñ’‘Š´#Pò8ÞAS$óû~èØwhG_¸•!è&P“ |R¨îŏJۮ؋û£õÛjµ„mœ5ŒC‹ KQíH;„§‡¶é|硃†<褍Ð΍.0ÑF`¢í€ÞÓ6æä˟:ºÅև,SÏ£O¢Ø5´¹E¯xS¸ s+0£®b©Ô"±òI´\+,Yl~f ‡ôìŒÜúk¤Ræe&i!5ÓúG¶ +RÓî;—ÙWCf?ŸE}–Lbl¸>øÖÞÎYa¯vhÀýà`²ÞŽüÅÍú"íO›HÏHèîH;´c¾ \Gځ)Òô>ÒXq¡[‚º€"´bšówFIÏjGO#©$C{-;‘*­¶íP\ŽM€çd³3¾Þ½2@°odÌÞTˀ,ÖJç´)@qS°bEŽØ²£ÙA"$§“lB;ç»ÀD6‰ìº!{Z«ÑRiÛb:ýË*ÄY +ö-üÍ$øê<œ µøITQ`‘©Âô±¾Ed=Pd|Id¢ID½q©ea^¶ ›ŒË£w õ89û(ô¿"ƒò߯¦ÁªIU™BÏcÏÒnarŠë“JkQXZ,´q•dÜ’õ–Ps´î2;cU‚f`“æÃ£¦¥¶VnD!4P©48õµÒÐ #C[)¡¶R_j¥a<%æë>z¯T;‡ÇO\M©T6NªÒ41›t¬n¥4Œô¹?]4ÙÚ5ÇÕî;ô>oz†>“ûtã~伸¿[Þòd۞ æy÷q<èå"Wzbfš)ÞpÛÖ8CR¶Ez0û +f°zh9z`9øR9‡~T·¡Ÿ„þæ4±¤!e~¡×@¹tåG ž’´ƒ’YžXªR Fò^&óFád‰C;”%ÁܯåéÄË#p‚(Ž?ßQ÷0—§º¢Îê=¼+¬Á^ `Ì¨¦“¦2â!œíT¬y•µ³íöÛòZ.Û5DºgwË%#óŒã¨pûBĘ!C›,¡6Y_j²A‡àœLac9¨³5‹ÙZϪX¯ÈIM¤äZn*ÒîCD,Hz`øR~=€<¸Yé‹VUy¦FG8Kêª›¤ š 1Î%²DÆ©e¶çã +Û¢­s¨‡&ñ–É„Ði"ð%šüyD¾®D^~’ú\›³yÙ¥_@Œl\ïŽ2Ⱥ‚ìsšp4Xº=Pº|Iº|×òÑi™ Uµ‹&œ¼º%¯ÐOc3ê"50ÁCˆ½d ¢x{%[ +³FÔešf‚f¸z(èc+ŠßPI„š"|1EöWÞoæÕ9+»k’@7ºîª¿faº* +¸û2ñb]ðìõíx£yoëóÿ†¢q行8ðFƟ‘.üºØ­y¨63´‡’‰?|3®³}àhZ‡ÿ‰·mH®ê,Ǭ»´{ôááöîÊìÅzìVå9æ½4–ëz\p“„ª`~ÿþîú§ëïïÛé·åf ¡=:Û¼>›?=ŸÅ³*¢îƒxÂ5OÜêÜøû¢²n7´êf¸,ð|.jy¸Àò¯«ÿºŽ>endstream +endobj +179 0 obj +1566 +endobj +180 0 obj<>>>>>endobj +181 0 obj<>stream +xÚµ–QoÚ0…ßùWßõ¹±ö>>>>>endobj +184 0 obj<>stream +xÚ-L»Â0Ûï+<ÂÐÐ#ڕ—Äâø$ҒöÿȖ,Û²_Ĩ?`X§ôOZ Íö ˜!¼t†±š×Û›ËñŒCC‰W° Cºg_R?¦.OåAÕoSýG¼Ðж-¾Ög,ú’ôe0¾ËQûÐ‰Þ¹ $íendstream +endobj +185 0 obj +123 +endobj +186 0 obj<>>>>>endobj +187 0 obj<>stream +xڕ—]sê6†ïù;ܔÌÇ2þ¢3½8$iK§=Ã9»Ü[7²åÊr€ߕd“ÀÁ˜Nfˆ±_­žÝ}%™\ü#y0 !ɳÕàá×)x.¬6ø$ŒbX¥#ž÷ŠÉ‚r˜x±¡ «îVÿ-‰¬v<ñϨ_Êr)’7¦`!…‰àVî!Ü‹œPËW[öI^6rÈ* Äãu¦ á ¯W‹‡ù*+LDQ°De¢p@‡HنÖ\V0ùž% J!•Ž3%®kDšg& úò}9S[‘BAs¦¥C}è4R/tüëuÅRX@¡âw¶ãLaÎ4y£2…?˜zÊ$RBÁÔNÈ7ȎåÃìR „7 /“Õ=ÐêŒpÇ8Ç»Ó⧐ðΊTÈê' ‘Ö‰ªX2f¦|Y,a)6jG%â¦yVd•’T¡þ¢EýÛ 8Þ±ª.u‘Xz6ï1öMölAt¯Í|3)vUVü}[£/1͆—'ÝßñššŠJAӄVªí¦³Ã±Éj‹#Ú6‹’aŽXQQ`÷Ï29ñB8!ç}¦ÉöÓd%5 NY•Èl1u]+…áu¹(hlÎlß°X̄ÓÊ6Ó:öËòq>ÅöH®¤ÎÖ%(ÄÜ3¼õAƒcKµp—©-ÎQ ‹²‚ÁëÈÝ»ôõÎú» †“` sª°iÚÁ9Vóg[u¦ºè¸–ÇžoT‡’ÁrÑ$µÌô¿! ÕËgh¾eÅFØ«œ¾±1æ3ÎEÊø¾þicÓ¦£cÝtt©cÞëˆ÷І»êÔ£{S Ó8£Ó‰~‘)YU +ˆµÓ}˜/ÐæÙȚFŒMvç!Nµ'ö¶£||²N:¦j½UßUŽ^º«õt:´Fû8§uý¼kaïÏǙ¥¶e{š²$ËqG(ê|Vnü%Y‰Ug…Ò_ZÒuÆ3ux06½¸uZÐ$¦{±q–)ý<Šð¦«o<™•T¶{^ \ÇÅCçøñý7\!ÞtŠûš™âpÜ–—Ä‘6¶“0t‚Ojszµ©?ÖQcƒa֝‰ÚÍȅ_ÚU|¶$ >1‹º7ÔIš˜fS¼ÎkĖ÷C¼ ¥OÌÔGÊFcjÃñ ’åBŸi¯#ÊwôPy½ëKÀ#mÁý¯®'`Ä6õGnlëêSpÅÄ]Ñt³>"W—æV ñ X"O­%'׈ð𲇊ē¶ÑýTVÜM¹ÍKÒeª´.9Û÷…¾ãÞ dÄÝ@q^p·UäéÃñ}'¾Lj»qð„6¯œaG}lô9ˆ2c}+”xÁí;ŠwƒÏ<êãœêͳÍ o·ºw²M'Öéq‡Óëßq¶‚÷,Žn7z]óyÔü˜^FJÄ;ë[va|»É¶&ÌÜîe–ufÏâ+(åfƒm'Ê$°ö&¤cÁá«Hï9ùŽÉ®S2>¾-¸Wáù‘^¯–1hȾ þœi¥nendstream +endobj +188 0 obj +1130 +endobj +189 0 obj<>>>>>endobj +190 0 obj<>stream +xڍVmoªXþµ1i7 +ÅÛÝM|×D[ײ›Þ¤_ŽpTvñÀôڍ?~gP­oUÛÒ9Ì<óÌ3s8ü(iPů5‹~Üe©é”î»h83Ð [ÕÀ²Mp¼[M¿sþ)é¶Zòáwp™€(öE +«ÒêÍ_¸ žsÇ)UÕ*føø3é!¨E ¶jƒDÓêª1‡—SΆjäΚe©æž7RÍ Z&Þ&Jµ¯)jöF¿–£YW­«9JçóђœŒ¯9Ö¬a_ÉѨbòk9Jçóõ¼MœÌK×,öÙ4àøÿ}ÍO×0ϵü¤ó ~÷Ý:ºÐHVÁ¬kÄÉ@ÄÖ_ãè†ñº~À‰Énv« `9RòÛ Ý`û:æÖ*áLß!]ð 0éæ8·3 LÃ(ù KÑ)©]Qz+—ƒ÷.ØÒwaʄÀ;›S2áQ$ÒÑjXÒIVQÆ)†q)(¦§‰šûéVÖ £¤ï'8,ÄOɲ( +|—¥~(î×ÂSÝU”(„~À^ÍlTÕ(ĪgYQWlÛ.SÛiŸ¶à7 ƒ üé‹9ùÇ7ö§ÈŒÄdkærPxÀ—\¤R `iŠ>«”ø `E}+ +ªS®š‰\>ùí—Γ3p¾CbޏåV»á4Ê (ˆL èñyÌ[Qþ(ôÔ²1Ø o…ʹ®\Z%TK2é5¿ÁÍdÒë5›Àèó Ž}°ú +wÈÅ<]ì !;ù$€ÿ QÉVxì¢&8#dQW 'ûÐn¸\2%á‹ QžüžߤÔ·géQîkÛ¾¾í×¶}cÛ7·}ëRÎ5MöI•Ç“Î%g_³E±?ªÙSÊvòOeˆÆ +ej…„›Áh<tÚ@ +ù-”Âã¸pž8ðv¤ñ6Nƒ·»lázr—¶lÎOÎþ½|•Æ,€”ÄR”òú…²hȱY*ïñRý³÷Eúž=½>‰Ð„-tŸŸ¼ ð×q.ÁÌc-|79Fy~ÅàI§E8ÃÁS/ãçáw¼4&-2´ät^/âû"áqz„>õ0øïÆäD,ŠZñEà ìš®yLûLÚeU øšåÝãa7³EŠOdpùf,çóV>Ä{$«Ð@á“Ò;#Åy؋ǙPð‹k9å·»_¹4g8x9 +=ŒŠlÿ#\üH}p>>>>>endobj +193 0 obj<>stream +xÚå—mo¢@Çßû)æÚè]à@­ÚxiÒlHlµ”&ׄ7‹ìYºl[½øáoÐZEô’ë s’ âÌogþ3» Ï T~hЮC£î¤raU¾÷T8ˇƉ¢A«ÓË«þørnY}ãނ ³fýª¨ kªÒHc4éBéG–AÂZ'″üN]SZÙhú­eX Á($îӆÿ aR€G㮸Ž)ò ð`×=*aú!yƒ#)E§ž8 +q„ +}úú ÷ƒáùµ~ØUI¸wíÚ·ÉyÄ}™ ˆÁˆx3~ãl-èwëßkè„xåvv5D>›»<Dçf×àØ¸ö ýJ`Bño1'ÌÓÈ ¨¯+X»ÊH<Ÿ`Ï Ñ‚="Œ‘ÉüQ†Ý]è±AΔÎëb×¾®©;ÔS'ʅ>•·KÁEX´8gs]ä5]Ä(™A©8‡/ËÐÔ ´øÐ!+‹04eåbê‡/ÊÅàg:qô›!_æ6}‰|†\Ž™–ªÁAú$$4gI—âÇR™ebÂ'?ÅÊ +È>'õQ4fÁulêw†™ ’Ù?wÄì>E(I +@…!‰FYñ*@¾a°;¶Ìn{hÓåKs|/zLÌ0)ì¤Ùž¸åÂ[ÛÞ@¦~imí Žß³}æúçÿ.v߸Õˊ“p–N˜²R È'–úfxA±kü®b%{V«·Q­ä/w¼AÿqW¹Æ¼ìj6Kùî’N·*ª¢òçüåɼ†Fƒ?Û×ëJzZí?S÷¦Í“†rZh›¾,t@ÓÄۂvÒRċ„šfrù0¼Clv¾ã"¸B‰Ø ù—Kq,Ò‘É™œ;5•Fæ×ã7ôpˆ„Q³Ýäê¤Z;Ïç®ò’ç1endstream +endobj +194 0 obj +693 +endobj +195 0 obj<>>>>>endobj +196 0 obj<>stream +xÚíWmo›0þž_qk) + ¡MSuªÄÒ!%mšºÓ*å 'xÜ÷eSüÎ@š¦7mû0mNÂÜ=~îîñ!«PǟfSý½¨òTÞuëp dæ¡n@³uį½cÒs® .z7{äK¥šQ×[ê%€ÇC. Õ¶z8ɟ`×ézŽÝÐ4à÷TæÓÜAÓ +H0Ս§2Hr¬Ý¡}yí  +‘.ØK7„[ž0Éxœ”á}߉Iæ­C;Íg†ÞÌÒb÷ì¾}NÀ¶Aƒ °ûr¯âßņÔWxø|ú +zž_úƒé¥±?O‡OCºI9¸Ê® - lȅäÎà‹•ÙñI}(‘®ÛÐÊ–“ó¾Æ4IJˆ•â…,¦/¼J ˜/Xkf·<ԁ—ç¬(ð õ] +WÐ÷vò8öJyo(n„ù/î_÷¿­Db&(E Fµê$ä'£½·‹Z”ôQ˜?®TâÐn“ªnȦq4ª…t"Ÿ<K*ž„ªñho^°Å¼¤Žšþ!eä @÷/øj’ß>EÌ÷C:#9æRòèËçt¯ä¸µ¦–Pü4e6ôƒEM9ý³•Ý͎ÆÔ÷±¿±ÈÒ•ºB¨ÂÂUWJ‘œÀʁËT=.hj»Uf´b¼Ñ{¬Xé)Á]ýœ›ë¡ó!7øJ,£.9P̶:-íS¹Ã–r*…ʶjm«ƒ5»À­Ð±»Ÿ¬a¡øÜ»KP×_Y5…U,›*Ášª©eBìÔûà3±ÿŒôÝ)M»‚¹cüøtÂ♪—ǐáÄnDg¨íŽE¬%2QveçŽnàœÚm²áΉƒ‘V!Q¨{ØTyvTú÷a`Ù;©M*u½ŽG“çËð L#†žÎ@ó¨‰WAáªÄôàÐԏKmÓóM CpŒÃ&B5ê)Ýöõà +ÕH'®G¡CÕlñæ v«²¯˜i™–;-5i¶ZXÜtâ@73 .tYHóx.+?ߊW endstream +endobj +197 0 obj +778 +endobj +198 0 obj<>>>/Annots 50 0 R>>endobj +199 0 obj<>stream +xÚ­XÛnÛ8}ÏWÌX ÅVŠHݬ½nêt$m6ñîS_h‰¶YȒKQI½_¿CRòE–?4K:œ™sæB*ß.xøK ¦àG®.ÞO/®n¡ªã÷ˆ‚ƒøßI$­î´G‰½kS÷Èç\ò"åpϊšåï0ÉBf0Ʉeašä°pÑø¥«ï;ƇC#üDº8îoï' 6kóRBå‰ +l­zM­^²õ:)Óþ®ž‹ÌMëuå¬q]eÖV¶õ½ßŽOmº(ŒÏGV).Ïh i-Ñ ÄJ‹eqjɤe¡Ö);h ²&pȤš“›vÐø˜Ct̊l؍Üõ8K—ÖbÓí¼4}Xñ½¨ë +›F• $+*Ìgc®ã8cŠÁ\–+cm/lю <Þ>TÚÚQø­îxæR[MôÆ.dÇk)P¬YnªbŔÛI3òl;:rHBzxNq{þa4Ã@ŸqÏ£i°gÓ4è“4bH&Ô¡axHòs­Öµú¡,ýQg²4سYôI–”Øã #ä™ògÏ ÏmNÈ"í’õôFLÛÓÏH7;ÕojúŒ„}zx0ÂùÖ<Á÷5ëwìW%áكËbÏVÅ O©BðàkJk7¿WSé;IÚ}Ƀ?à“Þ;Y¾{æyg'!ï=6o7õ’ö#¿–³ÐïV\u€A?PoIÃÙ ßf#Öº eÃb­2C`› ‹¶ÙØ¡·Ù ÍE€¹èŒUœ¨9¶Ú. Q³Ï ɬ„¢Ô§HÁ¿kqt4Ӊ8 h€^3tÍ+Á kÃ7´Õ`‡n5ˆÛ6Føzљ¹×µzµÓZÁªuÀõgTaÕ_Põu@¯WžŸ´¢¿ZxznÝpOÙ]݌š¡EÂÈÕÿ•2:7GÙƒž3ì<“‰E£™c×8Í¢¡¦±žÍžÝg þ¾ø36õ—endstream +endobj +200 0 obj +1526 +endobj +201 0 obj<>>>>>endobj +202 0 obj<>stream +xÚ­X]s›8}ϯÐãîLq‘_ûҤ٦ӏlíNŸ –me1¢’¦¿¾Wص²²³“LìHG {¸÷è\¾_`ÂFQ¢~ËýśÕÅëkŠ0F« ŠÃEŠ’,F«õ$%Iã?W÷”. +’E¢Æ¯ú¦b?Ô0£EÃpˆþB·’×jy½­XÐò5[+XˆÁ„ µèï~½]]„‹övøóåoD3µ$†;è-Dî'ZN`s²È¬Ù— Œód hBÉ"ü „bb"#i,:ªÁwß¾°VT}ÇE}äÂL ÉŠº+*TÔkôÀdÇKøG ^]4L¼.w‹3Ð.®oŽsøã¤@cÍv\à6Ñ +H²È4 HžŸRp³/¶ð¨ßˆ¾^ëÏçIq-z ÁvlËd‹¶üp¨Û1T±M÷ +݉®ûWHòíþUlu¢±r¦-W¤µHlôÚ¦Ø2Xjî +_~(:·iÏЈ)„é™IëI=—IqNaB‰Â0ˆB+“nê2d¹c¬›,ª+jÑAŒ +†ZÖ²è„D­ZÑNØÍ%ó+Tż]oÙ4©+Ñ ³ˆ·@—l» Z¿¨Ru¢«ota;aŠÖ ÏAó¬ÒäPÀgY5X_V z–Õë-c¬Z*ø± ‚­uèȔž‰Cp$J)ß+ùòT, +÷É<…ß`}…ߠ焟’xxJ‹DvÈu_T×̜Üs‚µ×¨ê mˆöl͋‰|ú8rP‚Éxž*ƒõ*ƒžª(Ï' TĪjã·ÃIeåÂMÝô Çp2žeh#!)B8íÐ'w¸Q®Èò˃õ̓žË€( Ç )‰ðD¸ß˜Ò+X=ƒõ”Êò­,ö-ŸÏV+ç÷¾ç,_”êü|Ðé±Î=‚Nu>t<ÔTz[As)…Ôöՙ÷†9–·ñö¼ƒê(¬o®ôl®óè£X°ôîÛ`gyàµr¾ó<ÜØóÂ|,‚óƒ`lÊ(¢ º±%ºŸû’ë¢d_›ÉÂ3´Ä؂ô›œg£ù8[uë[u=Wu8‹‡– Ž-ý¹…ç¸ä?™UtßøºÛiÇU±z _=NóQbÏV”ÁúV”AÏUNŒQO@XKX–¦sS=¯ã5K)öÚN0c)gß´”¢R=àé5„ÐÔ[k Öû©kôìS'éû HLbIÌJOËGޕ;בS¼p‹ø‚®Xف¯T#ªÇ`û¦{š`êÒ{¡ƒ8LýËӗ” ¦ŽrÉG«ž€f¤–f¬úý]Å\œ ¢ÌX=´¸;øºÖoù ]œWjç’yž2ÿž½Ä¾g.÷žŒæ=II-cW¢õcRS gÓgDZqã?XuîU“¿kO^bÚ—gG˞‚oKóçA¾›rìfð¿…Iý}:}‰M§N—nšñ ”Ó~+«‚ÔÈꩱOˆ+ ®UmÃJ¾á¥é¾NmÜ;ÿ_lš×N^Ò´“™žýõu6ìÇ 8͔èˆÑå×Û%ølpRúÀ¿b-ßÖ꣔¼íZ`ÖÃ"ªAá6¼©–H_ÚÛn©W¢ëáePðÏÅ/©Æ endstream +endobj +203 0 obj +1496 +endobj +204 0 obj<>>>/Annots 55 0 R>>endobj +205 0 obj<>stream +xÚÅWKoâH¾ó+Jsb¤Ø¸íök¤=,d˜E Z˜C¤\ŒiÀ;~­m&“¿Un›°‰çEÂqõWÝý}õèöþ1°u0,ð£Áx=M90똚jƒå˜°Þ ‡+†c^ÿ;à\ÕÑ þ1ÍÇA‘/D6IÂ$£Q¦*—Ãìô;àwàÀQ4úu=ÐT =ý,¿whÛQ(çf.þdV-XWWÝ ++Wºf®¥Z纪5ÐÈTò³L-:Šá²N†‹à—/B‘€¡÷¡gºªÕ—^‰íM¯DwÒãŽ=WGzf ½×B¿Ç môt2RR8”º©2àªÌ‰ÓÌ”jLª MüŽ*\õzªRb{«R¢;Ua´d©Š…ª¸×ª”ùüw¶¤f†tÒàðÇøÇ+¤”9<'ó§8ý<&/ ”Ú…¡ËƋ·bÛp™L`>ŸÃÓÓ<<\ûè蓆^ìeg>ªª’=ГèŒéß­µéòºÀ¸‰9qKk‰•¬o¥Ö-µ~C×Z›ºŽ³ ®i +׌­W©ç7ò“š×Z¿‚B´ºü6n‘ ­^˜ R?ôüvŽv ׅÕDëÓ|raµ$öáÂlKð¥ÙAóÃõÔneö£Û±â¦uj††ƒ²Þ +–×)z-£%áUe¼ÁëpqnÈ~È5Žá²ÛÂ¥™Èó ‰/úÅ}ü™’§ÂvÆ«þ[pûõw2ìÞýTbûv‰îê\粟rÍQ8k9.–ÉË$9ÆÅjÜÞ]Ub{kS¢;µÑ̪ҙŽÚ˜­ÚL…Ø~œ4Øë©ÿõ’FbûJ#Ñ]ÒŽUµf¡4n«4«B¤(£Qÿî'M‰í-M‰n‘Fìn_냀ùlþŠ×TÀ.É`ò}±‚¥—"ƒ]Š‚$=­¢7ôÒ4 |¯ÀV4úoURÉJŸs!†ª|wÙôŽ=Ù¨%¬çj­˜ÒBç®ÕmYó„[ñBš1.¤lE*ðd i©ÅÁ+JXƒG„"|ϏAámBAQ,ñVäE—û¯§ÃC^¨{õâàøk¡,&w€Ï埢ðñÀ‡NÕ^~W²—ßЈí4,hÓA¼Ç’"ñ“°S;Új·àݨT¤Ü¿øUˆ˜Î—œ„ +¤Ž¨•Ÿ¼A¡¢'è,JC¡øRÄdw!Ül±€mâ r‹“tÿ•à Ü{"Â隬Î*‡U ®›T_ŒS[Œ@·é8•o¡Lñ¦ŒW—Ò¢m¹çáãâÚ֪`øÞho^¡{•#04ªª·}\ã›ÄëÔnâÄ[Œ +ÿ¾ˆð``'•ÚñMâóýŒ¯(gû“ô•¦Ëé…¶Ý/ïò¢MáT2Û9£¢[oQú¾œA$ŠC²…Ø‹d‰aŒ(0ŸÂtûéVJ¹°vo˜ãeÉÛ ‡‰ÿ£_¥´z>Wó1¦ÕJ&B¯À¤ÀËñ;U50X½bŒèsa6]5ò)?/¤ÎlbåiN_Í0]£/>z©C¨yÙ´±£ ZÇfx(ŠôËhäÅG5÷¢§&Ù~„GX~+£©S©ÁðŽÊðÃ]“E\•:qÜáW܋<ØÇô@"iQ]D饨ºÖÝ×¹Mµ^ôú@ügð?W…!endstream +endobj +206 0 obj +1244 +endobj +207 0 obj<>>>>>endobj +208 0 obj<>stream +xÚEŽ=oƒ0„w~Å)p1PÂÚFÊ© ΖŃ]¦ÆMþ~mè‡lɯî޻ǟEìEšû[Aɂ‡CJÁZçäŬ ™¸œ„•ºÁȁVT§jÆfÞ7Õ×4icÇJ§OF[]ëë|ShpSܹÕþTî·ìÃñâ?^DS’x¢kœ'­ûkH¯Ûuë÷W¡ïê þ;ïÊʵ ‰I>6ª“5\ü„écN(²|¥àéòZá8ZaZ^ <‹Yu£j£&«ôèÓÑŠvIìCIâÅ´ÈIEÈp):ó;ª³_xaÁ[ð dJendstream +endobj +209 0 obj +248 +endobj +210 0 obj<>>>>>endobj +211 0 obj<>stream +xÚ­–]oÚ0†ïùç’J…@ ÀnWº©Òª15ÛU¥ÉØ'‰Y§¶3©ÿ~Ç$í +d \$ñk?öñùzLaB¿),}˜-€§ƒÁÀûôü !,–+ÄðÖR#·JK4WÁŽ4 ˜NKÍÈ_}§òÐry¥˜W +Zx4•’ F0ÿ–œÁ¹½†×§™ß1Ó(€”𹍂§áúñ«yºêŠ,cËø/ÌD3³9‡ 0ýH<’£V׸ý|O~¦"ÍҞÁ0U-”\%‰Ì¢ýµ~!G/çô–FiºHêe=Ó5˜ç˜Û6'wí‘ÀDzŒ¯“ñsâEãŽr̉—}´ Êkô§¼ Z)û.Ç©pÿõöûæ\ KN`Y¬ÇéÑ`[Õp*Æé΁´«ÓÐm°ÕÅÉ /C…TL'Ÿ£L¨43'Q0·Öe»I•8® '‘¥9…×ߊÕõ¯cô>ýEw!T·žˆôEJ=JÙ¡t£þf”ÏTt¯&Ûó“æ¶e ÔZéZaM®ÈY„5Ú§2¹RÉ9©¢¦Ú÷;°Sے[±V‡¬›Ú6w¾œWÔâҘ?sî‚Á·Á¥"Ðendstream +endobj +212 0 obj +611 +endobj +213 0 obj<>>>>>endobj +214 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS045Ó3T072PIÑPp VðÌ+I-JKLNUpI-ÎLÏQÉE™%™ùyš!Y\º=ºPMF& A#S=c°€©‚KfQjrI~Qfj1HÎ5„+ &#´endstream +endobj +215 0 obj +122 +endobj +216 0 obj<>>>>>endobj +217 0 obj<>stream +xڝ•QsÚ0 ÇßùzÜH›@¡{lÓЦ­wIïöê:jêáØÌ6eìÓW kï—îÈq$?é/KʯA §ô‰ašÀh¢\–ƒ“Ù7HN¡|"Ëdzeõ宕qŽÛí×ògçOwÃÑ8J:—(†mãvˆã½G2&­Gº³Œ÷Š7ŒGû?ƒ0Íjíтâº^ó£÷œá[÷·\)TýÀu%u ƂEò¥½©¸çÐ‹àŸ¹&ՏÒ§ ¼lÂå +Cٍà ߶*šµ–‚{i´Aa4*xD¿AÔà7VÖԖ7.Ρ•ü¿Ô}B“3b‰>¤ŠÒíTiJߨeºè}Kt1FI4Þ5E½ ôÅE‘æy †ª!è¼ +ÏuÅm©©žH|®é»éÒ¡ßÔ=mJ5D§¬è•’@B=Üå?€Y©}[×bë<6fV¤'¬š±âþîÉwкyV¸3©J˵{–f¼Fh7lx=ïçÝàF¡÷CÆÅ²MôÚòÕ³æû‰ £Yú 6#UB{kÔ±üÛÏðwµ…[óx >ÏÊY?¼ë,šÈt-5R7RW”Ü-af¬r;{è´#Î0/î?"vãÀÕ¡ãÜۚkù§3ØsvÕϞ“òCY¯86AÔ"_dý¬ÅZµË©’EXp© ûýá³P’Ì8_+WþoªèºaéÅâ2´mí ‘H/@jÛKE‹3À*ƒS[ZÚÖt:¡é=‹=ï·ä»Wðx:ŽÎi‰’!9kdåàûà°N#Çendstream +endobj +218 0 obj +597 +endobj +219 0 obj<>>>>>endobj +220 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS045Ó3T072PIÑPp VðÌ+I-JKLNUpI-ÎLÏQÉE™%™ùyš!Y\º=ºPMFf Acc=#°€£‚{N~qqbQ%HÂ5„+ ¹"—endstream +endobj +221 0 obj +119 +endobj +222 0 obj<>>>/Annots 94 0 R>>endobj +223 0 obj<>stream +xÚ͛ÏrÛ8‡ï~ +w£ÿð˜ÄñTª&oäy­L;š•D-%'›·_4ÐM´ 貓*GH_Änà‡FùÏ«jû›UšW¢©Ö»«wWïnڊ×ÕÝCÅT[5ZVw÷ÿ¸[ýkÛUýCõ±ßŸºýéøÛÝßWŸî®êEm ðƒÁo@£jdkî*³àøy[-=é>µhÀ§îyw•â … |ìw7]hcØØÎÆyq‘ñcÙÙ± <#ю¨Ï÷6⛇ÍzuÚô{€*m-3òkÉwœ/šÑw® +㶝ÇxÉcÈ1zѤ4#iùëxêv™iÆ[÷ 6~EšÈގ´¯?ºáǦû 8Éí,_òxÝ.äèq׈<Îê…ô%#‡Õ0Ÿ·êº_?íì4}#,PJûgÄDLÜÎíܸ°ÛYVr•£äúÏ£:UÆ=Ï ,¡Tkç_ÂòVÇøÖ=tC·_wn'°*¬g®³"?aUÓyõ—äUéÚk"/Ê+ ·$Do&ÒÇ¿n—™€„ÑvÒªB³¼X´ +F¡nšË†¥äuÕaö Ji/€¼(ÌÄ1µU”„ƒf$}=}³ÃpÐe‚†v„‘³iðY¬‘— ûPœdÂ}~I&l…öQDA(fŸ]¥4oEÊg›1ûÕöuXØUm3¥¡9Æ=¬Hyæ§;ª0ç™öòêf¦k¼¨4Ì­hQÖäµf„'sßs>~_ «õ)7û#$…„%Ƶ†`Ë.·ÏF#a50bup¨›ÍÖ’׳X@¯OspO-œ·û>•=B©Z.(h¹°Eƒ­ƒ¸´{g‚B;ÂÌï69wGã-Mƒu@Ü!†X¤Ñãƒ; 2?¢á;{°4 ª ÌDßnœ Öü[M‡BÐe[»ÁÅÅ7BÐeËüvA煠‰‰g(´#ì¯ýfÝßw·Š„gӑò¨Ï {±È¶µs8EbDæÃ ·a·«[M`ØaAØÛè@A¥¥Öáã!3‘Úø3‚(f&ıâÚ¤4#éÏÕþñiõØeå¹qŒ×ã—åy}³x!µ³Ù"›‚ÓéRï׈œÞ(ÌJЧFâ‘pЌ¤/Ÿ¿|ʤ8a4@!LXhGVìðf^9‰.țb>p‚ᑼ)òyqG#“z +B»Cí6»nqúuOŽâÂÞ*¹Gè°åûFäahËeõGãxŠB;œ‹Öýþ‡s‘ºp^¤ ‹ÖæãÎ7¢EË펲´h‘c ™pЌ¤¯8Üf—­a¬Öàꘆv5Ùw˜™‘NžåwÆ¢Ê5"¿3N;”*ù9¬®§ ´#ê¶?ž–ëasÈÙê)`Q$Hê@Ìa³Ï'%Âç¢S v@àuwt_1;EbŒÏI› ;ðç›éÛ-F“×%Ñ:/l]mK›¥* +7‘ƒ2^‚B;Âno¯sç¾0"zÊ¢[ºuúR¡¹ÌÆYò³Œq{ôÈϦ!/—ÔŸ8Œë‘šxÙ£òåÀx08ÙLQ¶‘>ý÷ÔíÖ¹ÇÜQÏÄ<»qÊÓã7;õ¹FÚÅø3vhŠó(lQvyëE&úýWo“×c¡Y¨ ûFÐc¡9å MA‰ãÖIÂA3’–ëïÝýÓ6[Ñ ÜÆy2¢ûýÃæñiXÄ3âÀ”}I¨Ô/žUxÞþ¥a[XÜʄ£½oD‹Û½ñA+‹(’˜„A +í[oWÇcw„üîaé]ÉCRù¬{׈<$J3š²" ^½é…v„­ŸÇûÑ?²Y\ø>« .<ډ]#r‘ËOÐE¢ä"$1»ÔuŠB;Â>oŠf‘¼èyƳ¯Dí¯@6à?¿ðÚAÔxß@æ_;LÁ»ð„æ­Hí/ÿÚ!8¹­SšéDúÚAÎ퐿`…Šo£K¾ñÒ{ÞâµY|ó@DVC߉vD½?–ýúßÙzaĉ€dÏßMfï@Þåô߯lÓÉþûœ&£Üê)͎òǶ·}øåæQ; ë·B©.98ÍYñ—*{ Ên½ÏVöÄÎf1âI}¼Iwݰ󙔞çÜ+¹®Å»+ðTmzu¥Å"ï³E¹q ¿@aŠ·g=ôû_;*‹y¹Ë;*<`=þÿLƒ3HAÉ£á˜CW.»‹âÕuwÜ<î«èú…[]ÜXMÿ]s÷¬tã?¯þÇöÒendstream +endobj +224 0 obj +2381 +endobj +225 0 obj<>>>>>endobj +226 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS045Ó3T072PIÑPp VðÌ+I-JKLNUpI-ÎLÏQÉE™%™ùyš!Y\º=ºPM™™ A×®@.¯µendstream +endobj +227 0 obj +99 +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<>1<>2<>4<>]>>>>endobj +xref +0 269 +0000000000 65535 f +0000000015 00000 n +0000000227 00000 n +0000001793 00000 n +0000001867 00000 n +0000001945 00000 n +0000002022 00000 n +0000002101 00000 n +0000002177 00000 n +0000002258 00000 n +0000002342 00000 n +0000002401 00000 n +0000002453 00000 n +0000002538 00000 n +0000002590 00000 n +0000002674 00000 n +0000002705 00000 n +0000002806 00000 n +0000002891 00000 n +0000002992 00000 n +0000003077 00000 n +0000003178 00000 n +0000003263 00000 n +0000003350 00000 n +0000003435 00000 n +0000003522 00000 n +0000003607 00000 n +0000003673 00000 n +0000003758 00000 n +0000003824 00000 n +0000003909 00000 n +0000003975 00000 n +0000004060 00000 n +0000004126 00000 n +0000004211 00000 n +0000004277 00000 n +0000004362 00000 n +0000004428 00000 n +0000004513 00000 n +0000004607 00000 n +0000004708 00000 n +0000004793 00000 n +0000004894 00000 n +0000004979 00000 n +0000005080 00000 n +0000005164 00000 n +0000005202 00000 n +0000005289 00000 n +0000005374 00000 n +0000005461 00000 n +0000005546 00000 n +0000005577 00000 n +0000005643 00000 n +0000005728 00000 n +0000005784 00000 n +0000005866 00000 n +0000005897 00000 n +0000006001 00000 n +0000006106 00000 n +0000006211 00000 n +0000006316 00000 n +0000006420 00000 n +0000006525 00000 n +0000006630 00000 n +0000006734 00000 n +0000006839 00000 n +0000006944 00000 n +0000007049 00000 n +0000007154 00000 n +0000007259 00000 n +0000007364 00000 n +0000007469 00000 n +0000007574 00000 n +0000007679 00000 n +0000007784 00000 n +0000007889 00000 n +0000007994 00000 n +0000008099 00000 n +0000008204 00000 n +0000008309 00000 n +0000008413 00000 n +0000008518 00000 n +0000008623 00000 n +0000008728 00000 n +0000008833 00000 n +0000008938 00000 n +0000009043 00000 n +0000009148 00000 n +0000009253 00000 n +0000009358 00000 n +0000009463 00000 n +0000009567 00000 n +0000009671 00000 n +0000009776 00000 n +0000009881 00000 n +0000010164 00000 n +0000010196 00000 n +0000010228 00000 n +0000010758 00000 n +0000010806 00000 n +0000010854 00000 n +0000010903 00000 n +0000010952 00000 n +0000011001 00000 n +0000011050 00000 n +0000011099 00000 n +0000011148 00000 n +0000011197 00000 n +0000011246 00000 n +0000011295 00000 n +0000011344 00000 n +0000011393 00000 n +0000011442 00000 n +0000011491 00000 n +0000011540 00000 n +0000011589 00000 n +0000011638 00000 n +0000011687 00000 n +0000011736 00000 n +0000011785 00000 n +0000011834 00000 n +0000011883 00000 n +0000011932 00000 n +0000011981 00000 n +0000012030 00000 n +0000012079 00000 n +0000012128 00000 n +0000012177 00000 n +0000012226 00000 n +0000012275 00000 n +0000012324 00000 n +0000012373 00000 n +0000012422 00000 n +0000012471 00000 n +0000012520 00000 n +0000012569 00000 n +0000012618 00000 n +0000012667 00000 n +0000012976 00000 n +0000013128 00000 n +0000019489 00000 n +0000019511 00000 n +0000019606 00000 n +0000019708 00000 n +0000019728 00000 n +0000019883 00000 n +0000020917 00000 n +0000020938 00000 n +0000021051 00000 n +0000021237 00000 n +0000021258 00000 n +0000021413 00000 n +0000022818 00000 n +0000022840 00000 n +0000022953 00000 n +0000023144 00000 n +0000023165 00000 n +0000023314 00000 n +0000024399 00000 n +0000024421 00000 n +0000024571 00000 n +0000025670 00000 n +0000025692 00000 n +0000025832 00000 n +0000027094 00000 n +0000027116 00000 n +0000027279 00000 n +0000028547 00000 n +0000028569 00000 n +0000028727 00000 n +0000030085 00000 n +0000030107 00000 n +0000030247 00000 n +0000031797 00000 n +0000031819 00000 n +0000031941 00000 n +0000033723 00000 n +0000033745 00000 n +0000033876 00000 n +0000035513 00000 n +0000035535 00000 n +0000035666 00000 n +0000036568 00000 n +0000036589 00000 n +0000036702 00000 n +0000036896 00000 n +0000036917 00000 n +0000037075 00000 n +0000038276 00000 n +0000038298 00000 n +0000038438 00000 n +0000039552 00000 n +0000039574 00000 n +0000039696 00000 n +0000040460 00000 n +0000040481 00000 n +0000040603 00000 n +0000041452 00000 n +0000041473 00000 n +0000041636 00000 n +0000043233 00000 n +0000043255 00000 n +0000043377 00000 n +0000044944 00000 n +0000044966 00000 n +0000045120 00000 n +0000046435 00000 n +0000046457 00000 n +0000046588 00000 n +0000046907 00000 n +0000046928 00000 n +0000047077 00000 n +0000047759 00000 n +0000047780 00000 n +0000047893 00000 n +0000048086 00000 n +0000048107 00000 n +0000048247 00000 n +0000048915 00000 n +0000048936 00000 n +0000049049 00000 n +0000049239 00000 n +0000049260 00000 n +0000049414 00000 n +0000051866 00000 n +0000051888 00000 n +0000052001 00000 n +0000052171 00000 n +0000052191 00000 n +0000052246 00000 n +0000052351 00000 n +0000052495 00000 n +0000052601 00000 n +0000052721 00000 n +0000052830 00000 n +0000052979 00000 n +0000053089 00000 n +0000053196 00000 n +0000053354 00000 n +0000053501 00000 n +0000053620 00000 n +0000053741 00000 n +0000053860 00000 n +0000054011 00000 n +0000054115 00000 n +0000054219 00000 n +0000054336 00000 n +0000054513 00000 n +0000054624 00000 n +0000054746 00000 n +0000054903 00000 n +0000055009 00000 n +0000055126 00000 n +0000055233 00000 n +0000055391 00000 n +0000055501 00000 n +0000055628 00000 n +0000055783 00000 n +0000055877 00000 n +0000056002 00000 n +0000056123 00000 n +0000056242 00000 n +0000056373 00000 n +0000056506 00000 n +0000056627 00000 n +0000056741 00000 n +0000056875 00000 n +0000056972 00000 n +0000057072 00000 n +trailer +<<910e97aaa8d4818393c8eeaaf6a5f23d>]>> +startxref +57299 +%%EOF diff --git a/doc/idd.shtml b/doc/idd.shtml new file mode 100644 index 0000000000..2f156a27d3 --- /dev/null +++ b/doc/idd.shtml @@ -0,0 +1,1429 @@ + + + + + + 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. + + + +

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

Internal Interfaces

+ +

Character Set Files

+ +

The character set files define a mapping between 8-bit characters +and the Unicode character set, or between Unicode and printer fonts. +They are named using the IETF charset names defined in RFCnnnn. These +files are ASCII text, the content of which is described below. Comments +can be included by using the # character in the first column +of a line. + +

8-Bit Character Set Files

+ +

8-bit character set files start with a line reading: + +

    +charset 8bit
    +
+ +

Following this are lines that define the font information: + +

    +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 within each group, with a maximum of 256 +mappings (this is a PostScript limitation.) The glyph values are +hexadecimal. + +

Direction is the string "ltor", "rtol", or "rtola" indicating +left-to-right, right-to-left, or right-to-left Arabic 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. + +

The remaining lines define a character to Unicode glyph mapping for the +character set. The character and glyph values are hexadecimal: + +

    +xx yyyy
    +
+ +

Unicode Character Set Files

+ +

Unicode character set files start with a line reading: + +

    +charset encoding
    +
+ +

Encoding is the encoding to use for the text; currently only +the string "utf8" is supported. + +

Following this are lines defining the font information: + +

    +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 within each group, with a maximum of 256 +mappings (this is a PostScript limitation.) The glyph values are +hexadecimal. + +

Direction is the string "ltor", "rtol", or "rtola" indicating +left-to-right, right-to-left, or right-to-left Arabic 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. + +

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

    +
  • 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 +
  • us-ascii +
  • utf-8 +
  • windows-874 +
  • windows-1250 +
  • windows-1251 +
  • windows-1252 +
  • windows-1253 +
  • windows-1254 +
  • windows-1255 +
  • windows-1256 +
  • windows-1257 +
  • windows-1258 +
+ +

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 ")" |
    +	 "contains(" offset "," length "," 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: + +

    +super/type SP super/type2 SP cost SP program
    +
+ +

Option Files

+ +

CUPS maintains user-defined printer and option files for each +printer and user on the system. The printers and options defined in the +system option file (/etc/cups/lpoptions) are loaded first, +followed by the user option file ($HOME/.lpoptions). +Options in the user file replace those defined in the system file for +the same destination. Each line in the files can be one of the +following: + +

    +Dest name option=value option=value ... option=value
    +Dest name/instance option=value option=value ... option=value
    +Default name option=value option=value ... option=value
    +Default name/instance option=value option=value ... option=value
    +
+ +

The line beginning with "Default" indicates the default destination for +print jobs; a default line in the user option file overrides the default +defined in the system option file. + +

Name is the name of a printer known to the local server. + +

Instance can be any string of letters, numbers, and the underscore +up to 127 characters in length. + +

The remainder of the line contains a list of space-separated options +and their values. + +

PostScript Printer Description Files

+ +

PostScript Printer Description ("PPD") files describe the capabilities +of each printer and are used by CUPS to support printer-specific features +and intelligent filtering. + +

PPD Specification

+ +

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

CUPS Extensions to PPD Files

+ +

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

cupsFilter

+ +

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

    +source/type cost program
    +
+ +

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

cupsManualCopies

+ +

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

cupsModelNumber

+ +

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

cupsProfile

+ +

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

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

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

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

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

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

cupsVersion

+ +

This required attribute describes which version of the CUPS IDD was used +for the PPD file extensions. Currently it must be the string "1.0" or "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".
AllowUsersSpecifies a list of users that are allowed to access the class.
BannerStartSpecifies the banner that is printed before other files in a + job.
BannerEndSpecifies the banner that is printed after other files in a + job.
DenyUsersSpecifies a list of users that are not allowed to access the + class.
InfoA textual description of the class.
LocationA textual location of the class.
PrinterSpecifies a printer that is a member of the class.
StateSpecifies the initial state of the class; can be "Idle" or + "Stopped".
StateMessageSpecifies a textual message for the current class state.
+ +

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
AccessLogaccess_logSpecifies the location of the access log file. The special name + "syslog" can be used to send access log information to the system + log.
Allow-Allows connections from the specified host, network, or + domain.
AuthClass-Specifies what level of authentication is required; may be + "User", "System", or "Group".
AuthTypeNoneSpecifies the type of authentication to perform; may be + "None", "Basic", or "Digest".
BrowseAddress255.255.255.255Specifies a broadcast address to send CUPS browsing packets to.
BrowseAllow-Specifies hosts or addresses from which browsing information + should be used.
BrowseDeny-Specifies hosts or addresses from which browsing information + should not be used.
BrowseInterval30Specifies the number of seconds between browsing updates. A + browse interval of 0 seconds disables outgoing packets.
BrowseOrderAllow,DenySpecifies the order of BrowseAllow and BrowseDeny directive + processing; can be "Deny,Allow" to implicitly deny hosts unless + they are allowed by a BrowseAllow line, or "Allow,Deny" to + implicitly allow hosts unless they are denied by a BrowseDeny + line.
BrowsePoll-Specifies a server to poll for available printers and classes.
BrowsePort631Specifies the UDP port number to use for browse packets.
BrowseRelay-Specifies a source and destination address for relaying browser + information from one subnet to another.
BrowseShortNamesyesSpecifies whether or not to provide short names (without the + "@server" part) for remote printers.
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".
DataDir/usr/share/cupsSpecifies the directory where CUPS data files are stored.
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/doc/cupsSpecifies the document data root directory.
ErrorLogerror_logSpecifies the error log file location. The special name + "syslog" can be used to send error log information to the system + log.
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 + available 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.
PageLogpage_logSpecifies the location of the page log file. The special name + "syslog" can be used to send page log information to the system + log.
Port631Specifies a port number to listen to for HTTP connections.
Printcap/etc/printcapSpecifies the location of a Berkeley printcap file to update + with a list of current printers and classes. If no filename is + supplied then this automatic generation is disabled.
RequestRoot/var/spool/cupsSpecifies the location of request files.
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/etc/cupsSpecifies the root directory for server configuration 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.
AllowUsersSpecifies a list of users that are allowed to access the printer.
BannerStartSpecifies the banner that is printed before other files in a + job.
BannerEndSpecifies the banner that is printed after other files in a + job.
DenyUsersSpecifies a list of users that are not allowed to access the + printer.
DeviceURISpecifies the device-uri attribute for the printer.
InfoA textual description of the printer.
LocationA textual location of the printer.
<Printer name>
+ </Printer>
Surrounds the printer definition.
StateSpecifies the initial state of the printer; can be "Idle" or + "Stopped".
StateMessageSpecifies a textual message for the current printer state.
+ +

External Interfaces

+ +

AppSocket Protocol

+ +

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

The AppSocket protocol is used by the Hewlett Packard JetDirect +network interfaces and print servers, as well as many other vendors' +products. See the CUPS Software Administrators Manual for a list of +supported products. + +

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 SP "location" SP "info" SP "make-and-model" NL
    +
+ +

State, uri, location, info, and make-and-model, +correspond to the IPP printer-state, +printer-uri-supported, printer-location, +printer-info, and printer-make-and-model +attributes. + +

Type 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 Form File

+ +

CUPS Form files are XML files used by the CUPS formtops +filter to produce dynamic banner pages and support preprinted forms. + +

The MIME type for CUPS Form files is +application/vnd.cups-form. + +

CUPS Form DTD

+ +

The following DTD describes the available elements and attributes in +a CUPS Form file: + +

+ + + +
+<!ENTITY % Angle "CDATA" -- angle in degrees -->
+
+<!ENTITY % Color "CDATA" -- a color using sRGB: #RRGGBB as Hex values -->
+
+<!ENTITY % Length "CDATA" -- nn for pixels or nn% for percentage length -->
+
+<!ENTITY % Lengths "CDATA" -- comma-separated Length values -->
+
+<!ENTITY % Text "CDATA">
+
+<!ENTITY % heading "H1|H2|H3|H4|H5|H6">
+
+<!ENTITY % preformatted "PRE">
+
+<!ENTITY % i18n
+ "lang        %LanguageCode; #IMPLIED  -- language code --
+  dir         (ltr|rtl)      #IMPLIED  -- direction for weak/neutral text --"
+  >
+
+<!ENTITY % attrs "%i18n;">
+
+<!ENTITY % fontstyle
+ "B | FONT | I | TT">
+
+<!ENTITY % graphics
+ "BOX | RECT | LINE | POLY | ARC | PIE | TEXT">
+
+<!ENTITY % insert
+ "IMG | VAR">
+
+<!-- %inline; covers inline or "text-level" elements -->
+<!ENTITY % inline "#PCDATA | %fontstyle; | %graphics; | %insert;">
+
+<!ELEMENT (%fontstyle;) - - (%inline;)*>
+<!ATTLIST (%fontstyle;)
+  %attrs;                              -- %i18n --
+  >
+
+<!ELEMENT BR - O EMPTY                 -- forced line break -->
+<!ATTLIST BR
+  %attrs;                              -- %i18n --
+  >
+
+<!ENTITY % block
+     "P | %heading; | %preformatted;">
+
+<!ENTITY % flow "%block; | %inline;">
+
+<!ELEMENT PAGE O O (%flow;)+           -- document body -->
+<!ATTLIST PAGE
+  %attrs;                              -- %i18n --
+  align       (left|center|right) #IMPLIED -- horizontal alignment --
+  valign      (top|middle|center|bottom) #IMPLIED -- vertical alignment --
+  >
+
+<!ELEMENT P - O (%inline;)*            -- paragraph -->
+<!ATTLIST P
+  %attrs;                              -- %i18n --
+  align       (left|center|right) #IMPLIED -- horizontal alignment --
+  >
+
+<!ELEMENT (%heading;)  - - (%inline;)* -- heading -->
+<!ATTLIST (%heading;)
+  %attrs;                              -- %i18n --
+  align       (left|center|right) #IMPLIED -- horizontal alignment --
+  >
+
+<!ELEMENT PRE - - (%inline;)*          -- preformatted text -->
+<!ATTLIST PRE
+  %attrs;                              -- %i18n --
+  align       (left|center|right) #IMPLIED -- horizontal alignment --
+  >
+
+<!ELEMENT BOX - O EMPTY                -- unfilled box -->
+<!ATTLIST BOX
+  color       %Color;        #IMPLIED  -- override color --
+  height      %Length;       #REQUIRED -- height of box --
+  thickness   %Length;       #IMPLIED  -- override line thickness --
+  width       %Length;       #REQUIRED -- width of box --
+  x           %Length;       #REQUIRED -- horizontal position --
+  y           %Length;       #REQUIRED -- vertical position --
+  >
+
+<!ELEMENT RECT - O EMPTY               -- filled box -->
+<!ATTLIST RECT
+  color       %Color;        #IMPLIED  -- override color --
+  height      %Length;       #REQUIRED -- height of box --
+  width       %Length;       #REQUIRED -- width of box --
+  x           %Length;       #REQUIRED -- horizontal position --
+  y           %Length;       #REQUIRED -- vertical position --
+  >
+
+<!ELEMENT LINE - O EMPTY               -- polyline -->
+<!ATTLIST LINE
+  color       %Color;        #IMPLIED  -- override color --
+  thickness   %Length;       #IMPLIED  -- override line thickness --
+  x           %Lengths;      #REQUIRED -- horizontal positions --
+  y           %Lengths;      #REQUIRED -- vertical positions --
+  >
+
+<!ELEMENT POLY - O EMPTY               -- polygon (filled) -->
+<!ATTLIST POLY
+  color       %Color;        #IMPLIED  -- override color --
+  x           %Lengths;      #REQUIRED -- horizontal positions --
+  y           %Lengths;      #REQUIRED -- vertical positions --
+  >
+
+<!ELEMENT ARC - O EMPTY                -- unfilled arc -->
+<!ATTLIST ARC
+  color       %Color;        #IMPLIED  -- override color --
+  end         %Angle;        #IMPLIED  -- override end angle --
+  height      %Length;       #REQUIRED -- height of arc --
+  start       %Angle;        #IMPLIED  -- override start angle --
+  thickness   %Length;       #IMPLIED  -- override line thickness --
+  width       %Length;       #REQUIRED -- width of arc --
+  x           %Length;       #REQUIRED -- horizontal position --
+  y           %Length;       #REQUIRED -- vertical position --
+  >
+
+<!ELEMENT PIE - O EMPTY                -- filled arc -->
+<!ATTLIST PIE
+  color       %Color;        #IMPLIED  -- override color --
+  end         %Angle;        #IMPLIED  -- override end angle --
+  height      %Length;       #REQUIRED -- height of arc --
+  start       %Angle;        #IMPLIED  -- override start angle --
+  width       %Length;       #REQUIRED -- width of arc --
+  x           %Length;       #REQUIRED -- horizontal position --
+  y           %Length;       #REQUIRED -- vertical position --
+  >
+
+<!ELEMENT TEXT - - (%flow;)*           -- text box -->
+<!ATTLIST RECT
+  align       (left|center|right) #IMPLIED -- horizontal alignment --
+  height      %Length;       #REQUIRED -- height of box --
+  valign      (top|middle|center|bottom) #IMPLIED -- vertical alignment --
+  width       %Length;       #REQUIRED -- width of box --
+  x           %Length;       #REQUIRED -- horizontal position --
+  y           %Length;       #REQUIRED -- vertical position --
+  >
+
+
+<!ELEMENT IMG - O EMPTY                -- Embedded image -->
+<!ATTLIST IMG
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  src         %URI;          #REQUIRED -- URI of image to embed --
+  height      %Length;       #IMPLIED  -- override height --
+  width       %Length;       #IMPLIED  -- override width --
+  >
+
+<!ELEMENT HEAD O O (DEFVAR)*           -- document head -->
+<!ATTLIST HEAD
+  %i18n;                               -- lang, dir --
+  >
+
+<!ELEMENT DEFVAR - O EMPTY             -- variable definition -->
+<!ATTLIST DEFVAR
+  name        CDATA          #REQUIRED -- name
+  value       CDATA          #REQUIRED -- value
+  >
+
+
+<!ENTITY % html.content "HEAD, PAGE">
+
+<!ELEMENT CUPSFORM - - (HEAD) (PAGE)+  -- document root element -->
+<!ATTLIST CUPSFORM
+  %i18n;                               -- lang, dir --
+  >
+
+ +

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 Image 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 and the CUPS extensions to it are +described in the CUPS Implementation of IPP document. + +

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". Support for this protocol is +provided via the SAMBA smbspool(1) program provided with +SAMBA 2.0.6 and higher. + +

Directories

+ +
+ +
/etc/cups +
The scheduler configuration and MIME files reside here. + +
/etc/cups/certs +
The authentication certificates reside here. + +
/etc/cups/interfaces +
System V interface scripts reside here. + +
/etc/cups/ppd +
This directory contains PPD files for each printer. + +
/usr/bin +
The cancel, lp, lpq, + lpr, lprm, and lpstat commands + reside here. + +
/usr/lib, /usr/lib32 +
The shared libraries (DSOs) reside here. + +
/usr/lib/cups/backend +
The backend filters reside here. + +
/usr/lib/cups/cgi-bin +
The CGI programs reside here. + +
/usr/lib/cups/daemon +
The polling and LPD daemons reside here. + +
/usr/lib/cups/filter +
The file filters 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/charsets +
The character set files reside here. + +
/usr/share/cups/data +
The 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. + +
/usr/share/doc/cups +
The scheduler documentation files reside here. + +
/var/log/cups +
The access_log, error_log, and + page_log files reside here. + +
/var/spool/cups +
This directory contains print job files. + +
+ + + + + diff --git a/doc/images/accept-jobs.gif b/doc/images/accept-jobs.gif new file mode 100644 index 0000000000..9da7a0dce1 Binary files /dev/null and b/doc/images/accept-jobs.gif differ diff --git a/doc/images/add-class.gif b/doc/images/add-class.gif new file mode 100644 index 0000000000..0f43a6fcdf Binary files /dev/null and b/doc/images/add-class.gif differ diff --git a/doc/images/add-printer.gif b/doc/images/add-printer.gif new file mode 100644 index 0000000000..90d17eb3f1 Binary files /dev/null and b/doc/images/add-printer.gif differ diff --git a/doc/images/cancel-job.gif b/doc/images/cancel-job.gif new file mode 100644 index 0000000000..3cc1e23bc6 Binary files /dev/null and b/doc/images/cancel-job.gif differ diff --git a/doc/images/cancel-jobs.gif b/doc/images/cancel-jobs.gif new file mode 100644 index 0000000000..2384b903c6 Binary files /dev/null and b/doc/images/cancel-jobs.gif differ diff --git a/doc/images/cancel.gif b/doc/images/cancel.gif new file mode 100644 index 0000000000..e994606782 Binary files /dev/null and b/doc/images/cancel.gif differ diff --git a/doc/images/classes.gif b/doc/images/classes.gif new file mode 100644 index 0000000000..ace15df980 Binary files /dev/null and b/doc/images/classes.gif differ diff --git a/doc/images/config-printer.gif b/doc/images/config-printer.gif new file mode 100644 index 0000000000..22849db7d5 Binary files /dev/null and b/doc/images/config-printer.gif differ diff --git a/doc/images/continue.gif b/doc/images/continue.gif new file mode 100644 index 0000000000..ff774adb34 Binary files /dev/null and b/doc/images/continue.gif differ diff --git a/doc/images/cups-bar.gif b/doc/images/cups-bar.gif new file mode 100644 index 0000000000..b2bdf4b520 Binary files /dev/null and b/doc/images/cups-bar.gif differ diff --git a/doc/images/cups-block-diagram.gif b/doc/images/cups-block-diagram.gif new file mode 100644 index 0000000000..2fe505e44b Binary files /dev/null and b/doc/images/cups-block-diagram.gif differ diff --git a/doc/images/cups-large.gif b/doc/images/cups-large.gif new file mode 100644 index 0000000000..fc66ef07c0 Binary files /dev/null and b/doc/images/cups-large.gif differ diff --git a/doc/images/cups-medium.gif b/doc/images/cups-medium.gif new file mode 100644 index 0000000000..c45ed6ab9e Binary files /dev/null and b/doc/images/cups-medium.gif differ diff --git a/doc/images/cups-small.gif b/doc/images/cups-small.gif new file mode 100644 index 0000000000..6adb4a29ff Binary files /dev/null and b/doc/images/cups-small.gif differ diff --git a/doc/images/delete-class.gif b/doc/images/delete-class.gif new file mode 100644 index 0000000000..81b1465acd Binary files /dev/null and b/doc/images/delete-class.gif differ diff --git a/doc/images/delete-printer.gif b/doc/images/delete-printer.gif new file mode 100644 index 0000000000..41ce85d788 Binary files /dev/null and b/doc/images/delete-printer.gif differ diff --git a/doc/images/draft.gif b/doc/images/draft.gif new file mode 100644 index 0000000000..77d9716abd Binary files /dev/null and b/doc/images/draft.gif differ diff --git a/doc/images/hold-job.gif b/doc/images/hold-job.gif new file mode 100644 index 0000000000..ebd448ae9f Binary files /dev/null and b/doc/images/hold-job.gif differ diff --git a/doc/images/left.gif b/doc/images/left.gif new file mode 100644 index 0000000000..fd7b041043 Binary files /dev/null and b/doc/images/left.gif differ diff --git a/doc/images/logo.gif b/doc/images/logo.gif new file mode 100644 index 0000000000..9999795caa Binary files /dev/null and b/doc/images/logo.gif differ diff --git a/doc/images/manage-classes.gif b/doc/images/manage-classes.gif new file mode 100644 index 0000000000..69d5b01470 Binary files /dev/null and b/doc/images/manage-classes.gif differ diff --git a/doc/images/manage-jobs.gif b/doc/images/manage-jobs.gif new file mode 100644 index 0000000000..adaff856f0 Binary files /dev/null and b/doc/images/manage-jobs.gif differ diff --git a/doc/images/manage-printers.gif b/doc/images/manage-printers.gif new file mode 100644 index 0000000000..cd897291dd Binary files /dev/null and b/doc/images/manage-printers.gif differ diff --git a/doc/images/modify-class.gif b/doc/images/modify-class.gif new file mode 100644 index 0000000000..58a0ead829 Binary files /dev/null and b/doc/images/modify-class.gif differ diff --git a/doc/images/modify-printer.gif b/doc/images/modify-printer.gif new file mode 100644 index 0000000000..593b5f8818 Binary files /dev/null and b/doc/images/modify-printer.gif differ diff --git a/doc/images/navbar.gif b/doc/images/navbar.gif new file mode 100644 index 0000000000..c19f634c0d Binary files /dev/null and b/doc/images/navbar.gif differ diff --git a/doc/images/navbar.xcf.gz b/doc/images/navbar.xcf.gz new file mode 100644 index 0000000000..28438a6bb8 Binary files /dev/null and b/doc/images/navbar.xcf.gz differ diff --git a/doc/images/print-test-page.gif b/doc/images/print-test-page.gif new file mode 100644 index 0000000000..807dca10e6 Binary files /dev/null and b/doc/images/print-test-page.gif differ diff --git a/doc/images/printer-idle.gif b/doc/images/printer-idle.gif new file mode 100644 index 0000000000..68d990c628 Binary files /dev/null and b/doc/images/printer-idle.gif differ diff --git a/doc/images/printer-processing.gif b/doc/images/printer-processing.gif new file mode 100644 index 0000000000..a9a23f7951 Binary files /dev/null and b/doc/images/printer-processing.gif differ diff --git a/doc/images/printer-stopped.gif b/doc/images/printer-stopped.gif new file mode 100644 index 0000000000..76f45649b1 Binary files /dev/null and b/doc/images/printer-stopped.gif differ diff --git a/doc/images/reject-jobs.gif b/doc/images/reject-jobs.gif new file mode 100644 index 0000000000..6d938e3084 Binary files /dev/null and b/doc/images/reject-jobs.gif differ diff --git a/doc/images/release-job.gif b/doc/images/release-job.gif new file mode 100644 index 0000000000..a05cd9cc71 Binary files /dev/null and b/doc/images/release-job.gif differ diff --git a/doc/images/restart-job.gif b/doc/images/restart-job.gif new file mode 100644 index 0000000000..a007efc5b4 Binary files /dev/null and b/doc/images/restart-job.gif differ diff --git a/doc/images/right.gif b/doc/images/right.gif new file mode 100644 index 0000000000..8ae8213cea Binary files /dev/null and b/doc/images/right.gif differ diff --git a/doc/images/show-active.gif b/doc/images/show-active.gif new file mode 100644 index 0000000000..d232ef9f84 Binary files /dev/null and b/doc/images/show-active.gif differ diff --git a/doc/images/show-completed.gif b/doc/images/show-completed.gif new file mode 100644 index 0000000000..efd206cd54 Binary files /dev/null and b/doc/images/show-completed.gif differ diff --git a/doc/images/start-class.gif b/doc/images/start-class.gif new file mode 100644 index 0000000000..2b6f43fad3 Binary files /dev/null and b/doc/images/start-class.gif differ diff --git a/doc/images/start-printer.gif b/doc/images/start-printer.gif new file mode 100644 index 0000000000..017bb394aa Binary files /dev/null and b/doc/images/start-printer.gif differ diff --git a/doc/images/stop-class.gif b/doc/images/stop-class.gif new file mode 100644 index 0000000000..5cb7adfd80 Binary files /dev/null and b/doc/images/stop-class.gif differ diff --git a/doc/images/stop-printer.gif b/doc/images/stop-printer.gif new file mode 100644 index 0000000000..b3accf3dfb Binary files /dev/null and b/doc/images/stop-printer.gif differ diff --git a/doc/index.html b/doc/index.html new file mode 100644 index 0000000000..1150e4cdf0 --- /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 + + + + +
+Common UNIX Printing System +
+ +

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/ipp.html b/doc/ipp.html new file mode 100644 index 0000000000..8cc01906fa --- /dev/null +++ b/doc/ipp.html @@ -0,0 +1,1614 @@ + + + + CUPS Implementation of IPP + + + + + + + +


+

CUPS Implementation of IPP


+CUPS-IPP-1.1
+Easy Software Products
+Copyright 1997-2000, All Rights Reserved
+
+
+

Table of Contents

+

+

1 Scope + +2 References + +3 Overview + +4 Operations + +5 Attributes + +A Glossary + +
+

1 Scope

+

1.1 Identification

+

This document provides an overview of the +Internet Printing Protocol ("IPP") version 1.1 as +implemented in the Common UNIX Printing System +("CUPS") version 1.1.

+

1.2 System Overview

+

CUPS provides a portable printing layer for +UNIX®-based 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 ("IPP") +as the basis for managing print jobs and +queues. The Line Printer Daemon ("LPD") Server +Message Block ("SMB"), and AppSocket (a.k.a. +JetDirect) protocols are also supported with reduced +functionality. CUPS adds network printer browsing and +PostScript Printer Description ("PPD") based printing +options to support real-world printing under UNIX.

+

CUPS also includes a customized version of GNU +Ghostscript (currently based off GNU Ghostscript +5.50) and an image file RIP that are used to +support non-PostScript printers. Sample drivers for +HP and EPSON printers are included that use +these filters.

+

1.3 Document Overview

+

This document is organized into the following +sections:

+ +

2 References

+

2.1 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-IPP-1.1: CUPS Implementation of IPP
  • +
  • CUPS-SAM-1.1.x: CUPS Software Administrators Manual
  • +
  • CUPS-SDD-1.1: CUPS Software Design Description
  • +
  • CUPS-SPM-1.1.x: 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: CUPS Software Version Description
  • +
+

2.2 Other Documents

+

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

+ +

3 Overview

+

CUPS 1.1 implements IPP/1.1 and the operations +and attributes defined in the "IPP: Job and +Printer Set Operations", "IPP/1.1: Output-bin Attribute +Extension", and "IPP/1.1: finishings 'fold',' trim', +and 'bale' attribute values extension" specifications. +

+

CUPS also provides 13 new operations and many +new attributes to support multiple IPP printers +and printer classes on a single host.

+

3.1 IPP URIs

+

CUPS supports both the "http" and "ipp" +methods. The following resource names are used:

+
+
method://hostname:port/
+
Can be used for all "get" operations.
+
method://hostname:port/admin
+
Used for all administrative operations.
+
method://hostname:port/classes/name
+
Specifies a printer class.
+
method://hostname:port/jobs/id
+
Specifies a job.
+
method://hostname:port/printers/name
+
Specifies a printer.
+
+

So a typical printer URI would be +"ipp://foo.bar.com/printers/LaserJet".

+

In addition, the CUPS server also supports +normal browser access to "method://hostname:port/admin/", +"method://hostname:port/classes/", "method://hostname:port/jobs/", +and "method://hostname:port/printers/" to view and +manage resources on the server dynamically.

+

3.2 CUPS IPP Operations

+

CUPS provides 13 extension operations in addition +to most of the standard IPP and registered +extension operations: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Operation NameCUPSCodeBrief Description
Print-Job1.0 +0x0002Print a file.
Validate-Job1.0 +0x0004Validate job attributes.
Create-Job1.1 +0x0005Create a print job.
Send-Document1.10x0006Send a file for +a print job.
Cancel-Job1.0 +0x0008Cancel a print job.
Get-Job-Attributes1.00x0009Get job attributes.
Get-Jobs1.0 +0x000AGet all jobs.
Get-Printer-Attributes1.0 +0x000BGet printer +attributes.
Hold-Job1.1 +0x000CHold a job for printing.
Release-Job1.1 +0x000DRelease a job for printing. +
Pause-Printer1.00x0010Pause printing on +a printer.
Resume-Printer1.00x0011Resume printing on +a printer.
Purge-Jobs1.0 +0x0012Purge all jobs.
Set-Job-Attributes1.10x0014Set attributes for +a pending or held job.
CUPS-Get-Default1.00x4001Get the default +destination.
CUPS-Get-Printers1.00x4002Get all of the +available printers.
CUPS-Add-Printer1.00x4003Add or modify a +printer.
CUPS-Delete-Printer1.00x4004Delete a printer.
CUPS-Get-Classes1.00x4005Get all of the +available printer classes.
CUPS-Add-Class1.00x4006Add or modify a +printer class.
CUPS-Delete-Class1.00x4007Delete a printer +class.
CUPS-Accept-Jobs1.00x4008Accept jobs on a +printer or printer class.
CUPS-Reject-Jobs1.00x4009Reject jobs on a +printer or printer class.
CUPS-Set-Default1.00x400ASet the default +destination.
CUPS-Get-Devices1.10x400BGet all of the +available devices.
CUPS-Get-PPDs1.10x400CGet all of the +available PPDs.
CUPS-Move-Job1.10x400DMove a job to a +different printer.
+
+

+

4 Operations

+

The following sections describe the operations +supported by CUPS. In the interest of brevity, +operations which use only the standard IPP +attributes are not described.

+

4.1 Print-Job Operation

+

The Print-Job operation (0x0002) prints a file.

+

4.1.1 Print-Job Request

+

The following groups of attributes are supplied +as part of the Print-Job request:

+

Group 1: Operation Attributes

+
    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the +IPP Model and Semantics document.

    +

    "printer-uri" (uri):

    +

    The client MUST supply a URI for the +specified printer.

    +
+

Group 2: Job Template Attributes

+
    +

    "job-billing" (text(MAX)):

    +

    (CUPS 1.1 and higher)

    +

    The client OPTIONALLY supplies a billing string +that is logged with the page accounting +information.

    +

    "job-sheets" (1setof type3 keyword | name(MAX)):

    +

    (CUPS 1.1 and higher)

    +

    The client OPTIONALLY supplies one or two +banner pages that are printed before and after +any files in the print job. The name of +"none" is reserved to indicate that no banner +page should be printed. If the client does not +specify this attribute then the value of the +"job-sheets-default" printer object attribute is used. +

    +

    Note: Standard IPP only allows specification +of a single job-sheets attribute value.

    +

    "media" (1setof type3 keyword | name(MAX)):

    +

    The client OPTIONALLY supplies one or more +media attributes specifying the size, type, source, +and color of the output media. If the client +does not specify this attribute then the value +of the "media-default" printer object attribute is +used.

    +

    Note: Standard IPP only allows specification +of a single media attribute value.

    +

    Other Job Template Attributes

    +
+

The Print-Job request is followed by a file +to be printed.

+

4.1.2 Print-Job Response

+

The following groups of attributes are send as +part of the Print-Job Response:

+

Group 1: Operation Attributes

+
    +

    Status Message:

    +

    The standard response status message.

    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the +IPP Model and Semantics document.

    +
+

Group 2: Job Attributes

+
    +

    Standard Job Attributes

    +
+

4.2 Create-Job Operation

+

The Create-Job operation (0x0005) creates a new, +empty print job.

+

4.2.1 Create-Job Request

+

The following groups of attributes are supplied +as part of the Create-Job request:

+

Group 1: Operation Attributes

+
    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the +IPP Model and Semantics document.

    +

    "printer-uri" (uri):

    +

    The client MUST supply a URI for the +specified printer.

    +
+

Group 2: Job Template Attributes

+
    +

    "job-billing" (text(MAX)):

    +

    (CUPS 1.1 and higher)

    +

    The client OPTIONALLY supplies a billing string +that is logged with the page accounting +information.

    +

    "job-sheets" (1setof type3 keyword | name(MAX)):

    +

    (CUPS 1.1 and higher)

    +

    The client OPTIONALLY supplies one or two +banner pages that are printed before and after +any files in the print job. The name of +"none" is reserved to indicate that no banner +page should be printed. If the client does not +specify this attribute then the value of the +"job-sheets-default" printer object attribute is used. +

    +

    Note: Standard IPP only allows specification +of a single job-sheets attribute value.

    +

    "media" (1setof type3 keyword | name(MAX)):

    +

    The client OPTIONALLY supplies one or more +media attributes specifying the size, type, source, +and color of the output media. If the client +does not specify this attribute then the value +of the "media-default" printer object attribute is +used.

    +

    Note: Standard IPP only allows specification +of a single media attribute value.

    +

    Standard Job Template Attributes

    +
+

4.2.2 Create-Job Response

+

The following groups of attributes are send as +part of the Create-Job Response:

+

Group 1: Operation Attributes

+
    +

    Status Message:

    +

    The standard response status message.

    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the +IPP Model and Semantics document.

    +
+

Group 2: Job Attributes

+
    +

    Standard Job Attributes

    +
+

4.3 Set-Job-Attributes Operation

+

The Set-Job-Attributes operation (0x0014) changes the +attributes of an active (not completed) job.

+

4.3.1 Set-Job-Attributes Request

+

The following groups of attributes are supplied +as part of the Set-Job-Attributes request:

+

Group 1: Operation Attributes

+
    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the +IPP Model and Semantics document.

    +

    "printer-uri" (uri) and "job-id" (integer)

    +

    OR

    +

    "job-uri":

    +

    The client MUST supply a URI for the +specified printer and a job ID number, or the +job URI.

    +
+

Group 2: Job Template Attributes

+
    +

    "job-sheets" (1setof type3 keyword | name(MAX)):

    +

    (CUPS 1.1 and higher)

    +

    The client OPTIONALLY supplies one or two +banner pages that are printed before and after +any files in the print job. The name of +"none" is reserved to indicate that no banner +page should be printed. If the client does not +specify this attribute then the value of the +"job-sheets-default" printer object attribute is used. +

    +

    Note: Standard IPP only allows specification +of a single job-sheets attribute value.

    +

    "media" (1setof type3 keyword | name(MAX)):

    +

    The client OPTIONALLY supplies one or more +media attributes specifying the size, type, source, +and color of the output media. If the client +does not specify this attribute then the value +of the "media-default" printer object attribute is +used.

    +

    Note: Standard IPP only allows specification +of a single media attribute value.

    +

    Other Job Template Attributes

    +
+

4.3.2 Set-Job-Attributes Response

+

The following groups of attributes are send as +part of the Set-Job-Attributes Response:

+

Group 1: Operation Attributes

+
    +

    Status Message:

    +

    The standard response status message.

    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the +IPP Model and Semantics document.

    +
+

4.4 CUPS-Get-Default Operation

+

The CUPS-Get-Default operation (0x4001) returns the +default printer URI and attributes.

+

4.4.1 CUPS-Get-Default Request

+

The following groups of attributes are supplied +as part of the CUPS-Get-Default request:

+

Group 1: Operation Attributes

+
    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the +IPP Model and Semantics document.

    +

    "requested-attributes" (1setOf keyword) :

    +

    The client OPTIONALLY supplies a set of +attribute names and/or attribute group names in +whose values the requester is interested. If the +client omits this attribute, the server responds +as if this attribute had been supplied with a +value of 'all'.

    +
+

4.4.2 CUPS-Get-Default Response

+

The following groups of attributes are send as +part of the CUPS-Get-Default Response:

+

Group 1: Operation Attributes

+
    +

    Status Message:

    +

    The standard response status message.

    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the +IPP Model and Semantics document.

    +
+

Group 2: Printer Object Attributes

+
    +

    The set of requested attributes and their +current values.

    +
+

4.5 CUPS-Get-Printers Operation

+

The CUPS-Get-Printers operation (0x4002) returns the +printer attributes for every printer known to the +system. This may include printers that are not +served directly by the server.

+

4.5.1 CUPS-Get-Printers Request

+

The following groups of attributes are supplied +as part of the CUPS-Get-Printers request:

+

Group 1: Operation Attributes

+
    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the +IPP Model and Semantics document.

    +

    "limit" (integer (1:MAX)):

    +

    The client OPTIONALLY supplies this attribute +limiting the number of printers that are +returned.

    +

    "printer-info" (text(127)):

    +

    (CUPS 1.1 and higher)

    +

    The client OPTIONALLY supplies this attribute to + select which printers are returned.

    +

    "printer-location" (text(127)):

    +

    (CUPS 1.1 and higher)

    +

    The client OPTIONALLY supplies this attribute to + select which printers are returned.

    +

    "printer-type" (type2 enum):

    +

    (CUPS 1.1 and higher)

    +

    The client OPTIONALLY supplies a printer type +enumeration to select which printers are returned. +

    +

    "printer-type-mask" (type2 enum):

    +

    (CUPS 1.1 and higher)

    +

    The client OPTIONALLY supplies a printer type +mask enumeration to select which bits are used +in the "printer-type" attribute.

    +

    "requested-attributes" (1setOf keyword) :

    +

    The client OPTIONALLY supplies a set of +attribute names and/or attribute group names in +whose values the requester is interested. If the +client omits this attribute, the server responds +as if this attribute had been supplied with a +value of 'all'.

    +
+

4.5.2 CUPS-Get-Printers Response

+

The following groups of attributes are send as +part of the CUPS-Get-Printers Response:

+

Group 1: Operation Attributes

+
    +

    Status Message:

    +

    The standard response status message.

    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the +IPP Model and Semantics document.

    +
+

Group 2: Printer Object Attributes

+
    +

    The set of requested attributes and their +current values for each printer.

    +
+

4.6 CUPS-Add-Printer Operation

+

The CUPS-Add-Printer operation (0x4003) adds a new +printer or modifies an existing printer on the +system.

+

4.6.1 CUPS-Add-Printer Request

+

The following groups of attributes are supplied +as part of the CUPS-Add-Printer request:

+

Group 1: Operation Attributes

+
    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the +IPP Model and Semantics document.

    +

    "printer-uri" (uri):

    +

    The client MUST supply a URI for the +specified printer.

    +
+

Group 2: Printer Object Attributes

+
    +

    "banner-end-default" (name(127)):

    +

    (CUPS 1.1 and higher)

    +

    The client OPTIONALLY supplies a banner page +name that is printed after files in a job. +The reserved name "none" is used to specify +that no banner page should be printed.

    +

    "banner-start-default" (name(127)):

    +

    (CUPS 1.1 and higher)

    +

    The client OPTIONALLY supplies a banner page +name that is printed before files in a job. +The reserved name "none" is used to specify +that no banner page should be printed.

    +

    "device-uri" (uri):

    +

    The client OPTIONALLY supplies a device URI for +the specified printer.

    +

    "ppd-name" (name(127)):

    +

    The client OPTIONALLY supplies a PPD name for +the specified printer.

    +

    "printer-is-accepting-jobs" (boolean):

    +

    The client OPTIONALLY supplies this boolean +attribute indicating whether or not the printer +object should accept new jobs.

    +

    "printer-info" (text(127)):

    +

    The client OPTIONALLY supplies this attribute +indicating the printer information string.

    +

    "printer-location" (text(127)):

    +

    The client OPTIONALLY supplies this attribute +indicating a textual location of the printer.

    +

    "printer-more-info" (uri):

    +

    The client OPTIONALLY supplies this attribute +indicating a URI for additional printer information. +

    +

    "printer-state" (type2 enum):

    +

    The client OPTIONALLY supplies this attribute +indicating the initial/current state of the printer. +Only the "idle" and "stopped" enumerations are +recognized.

    +

    "printer-state-message" (text(MAX)):

    +

    The client OPTIONALLY supplies this attribute +indicating a textual reason for the current +printer state.

    +

    "requesting-user-name-allowed" (1setof name(127) | +delete)

    +

    OR

    +

    "requesting-user-name-denied" (1setof name(127) | +delete):

    +

    The client OPTIONALLY supplies one of these +attributes to specify an access control list for +incoming print jobs. To allow all users access +to a printer, use the delete tag for the + attribute value.

    +
+

The CUPS-Add-Printer request can optionally be +followed by a PPD file or System V interface +script to be used for the printer. The +"ppd-name" attribute overrides any file that is +attached to the end of the request with a +local CUPS PPD file.

+

4.6.2 CUPS-Add-Printer Response

+

The following groups of attributes are send as +part of the CUPS-Add-Printer Response:

+

Group 1: Operation Attributes

+
    +

    Status Message:

    +

    The standard response status message.

    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the +IPP Model and Semantics document.

    +
+

4.7 CUPS-Delete-Printer Operation

+

The CUPS-Delete-Printer operation (0x4004) removes an +existing printer from the system.

+

4.7.1 CUPS-Delete-Printer Request

+

The following groups of attributes are supplied +as part of the CUPS-Delete-Printer request:

+

Group 1: Operation Attributes

+
    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the +IPP Model and Semantics document.

    +

    "printer-uri" (uri):

    +

    The client MUST supply a URI for the +specified printer.

    +
+

4.7.2 CUPS-Delete-Printer Response

+

The following groups of attributes are send as +part of the CUPS-Delete-Printer Response:

+

Group 1: Operation Attributes

+
    +

    Status Message:

    +

    The standard response status message.

    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the +IPP Model and Semantics document.

    +
+

4.8 CUPS-Get-Classes Operation

+

The CUPS-Get-Classes operation (0x4005) returns the +printer attributes for every printer class known +to the system. This may include printer classes +that are not served directly by the server.

+

4.8.1 CUPS-Get-Classes Request

+

The following groups of attributes are supplied +as part of the CUPS-Get-Classes request:

+

Group 1: Operation Attributes

+
    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the +IPP Model and Semantics document.

    +

    "limit" (integer (1:MAX)):

    +

    The client OPTIONALLY supplies this attribute +limiting the number of printer classes that are +returned.

    +

    "printer-info" (text(127)):

    +

    (CUPS 1.1 and higher)

    +

    The client OPTIONALLY supplies this attribute to + select which printer classes are returned.

    +

    "printer-location" (text(127)):

    +

    (CUPS 1.1 and higher)

    +

    The client OPTIONALLY supplies this attribute to + select which printer classes are returned.

    +

    "printer-type" (type2 enum):

    +

    (CUPS 1.1 and higher)

    +

    The client OPTIONALLY supplies a printer type +enumeration to select which printer classes are +returned.

    +

    "printer-type-mask" (type2 enum):

    +

    (CUPS 1.1 and higher)

    +

    The client OPTIONALLY supplies a printer type +mask enumeration to select which bits are used +in the "printer-type" attribute.

    +

    "requested-attributes" (1setOf keyword) :

    +

    The client OPTIONALLY supplies a set of +attribute names and/or attribute group names in +whose values the requester is interested. If the +client omits this attribute, the server responds +as if this attribute had been supplied with a +value of 'all'.

    +
+

4.8.2 CUPS-Get-Classes Response

+

The following groups of attributes are send as +part of the CUPS-Get-Classes Response:

+

Group 1: Operation Attributes

+
    +

    Status Message:

    +

    The standard response status message.

    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the +IPP Model and Semantics document.

    +
+

Group 2: Printer Class Object Attributes

+
    +

    The set of requested attributes and their +current values for each printer class.

    +
+

4.9 CUPS-Add-Class Operation

+

The CUPS-Add-Class operation (0x4006) adds a new +printer class or modifies and existing printer +class on the system.

+

4.9.1 CUPS-Add-Class Request

+

The following groups of attributes are supplied +as part of the CUPS-Add-Class request:

+

Group 1: Operation Attributes

+
    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the +IPP Model and Semantics document.

    +

    "printer-uri" (uri):

    +

    The client MUST supply a URI for the +specified printer class.

    +
+

Group 2: Printer Object Attributes

+
    +

    "member-uris" (1setof uri):

    +

    The client OPTIONALLY supplies the "member-uris" +set specifying the printers and printer classes +that are part of the class.

    +

    "printer-is-accepting-jobs" (boolean):

    +

    The client OPTIONALLY supplies this boolean +attribute indicating whether or not the class +object should accept new jobs.

    +

    "printer-info" (text(127)):

    +

    The client OPTIONALLY supplies this attribute +indicating the printer information string.

    +

    "printer-location" (text(127)):

    +

    The client OPTIONALLY supplies this attribute +indicating a textual location of the class.

    +

    "printer-more-info" (uri):

    +

    The client OPTIONALLY supplies this attribute +indicating a URI for additional class information. +

    +

    "printer-state" (type2 enum):

    +

    The client OPTIONALLY supplies this attribute +indicating the initial/current state of the class. +Only the "idle" and "stopped" enumerations are +recognized.

    +

    "printer-state-message" (text(MAX)):

    +

    The client OPTIONALLY supplies this attribute +indicating a textual reason for the current class +state.

    +

    "requesting-user-name-allowed" (1setof name(127))

    +

    OR

    +

    "requesting-user-name-denied" (1setof name(127)):

    +

    The client OPTIONALLY supplies one of these +attributes to specify an access control list for +incoming print jobs. To allow all users access +to a class, use the delete tag for the + attribute value.

    +
+

4.9.2 CUPS-Add-Class Response

+

The following groups of attributes are send as +part of the CUPS-Add-Class Response:

+

Group 1: Operation Attributes

+
    +

    Status Message:

    +

    The standard response status message.

    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the +IPP Model and Semantics document.

    +
+

4.10 CUPS-Delete-Class Operation

+

The CUPS-Delete-Class operation (0x4007) removes an +existing printer class from the system.

+

4.10.1 CUPS-Delete-Class Request

+

The following groups of attributes are supplied +as part of the CUPS-Delete-Class request:

+

Group 1: Operation Attributes

+
    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the +IPP Model and Semantics document.

    +

    "printer-uri" (uri):

    +

    The client MUST supply a URI for the +specified printer class.

    +
+

4.10.2 CUPS-Delete-Class Response

+

The following groups of attributes are send as +part of the CUPS-Delete-Class Response:

+

Group 1: Operation Attributes

+
    +

    Status Message:

    +

    The standard response status message.

    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the +IPP Model and Semantics document.

    +
+

4.11 CUPS-Accept-Jobs Operation

+

The CUPS-Accept-Jobs operation (0x4008) sets the +"printer-is-accepting-jobs" attribute to true for the +specified printer or printer class.

+

4.11.1 CUPS-Accept-Jobs Request

+

The following groups of attributes are supplied +as part of the CUPS-Accept-Jobs request:

+

Group 1: Operation Attributes

+
    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the +IPP Model and Semantics document.

    +

    "printer-uri" (uri):

    +

    The client MUST supply a URI for the +specified printer or printer class.

    +
+

4.11.2 CUPS-Accept-Jobs Response

+

The following groups of attributes are send as +part of the CUPS-Accept-Jobs Response:

+

Group 1: Operation Attributes

+
    +

    Status Message:

    +

    The standard response status message.

    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the +IPP Model and Semantics document.

    +
+

4.12 CUPS-Reject-Jobs Operation

+

The CUPS-Reject-Jobs operation (0x4009) sets +the"printer-is-accepting-jobs" attribute to false for +the specified printer or printer class.

+

4.12.1 CUPS-Reject-Jobs Request

+

The following groups of attributes are supplied +as part of the CUPS-Reject-Jobs request:

+

Group 1: Operation Attributes

+
    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the +IPP Model and Semantics document.

    +

    "printer-uri" (uri):

    +

    The client MUST supply a URI for the +specified printer or printer class.

    +
+

Group 2: Printer Object Attributes

+
    +

    "printer-state-message" (text(MAX)):

    +

    The client OPTIONALLY supplies this attribute +indicating a textual reason for the current +printer state.

    +
+

4.12.2 CUPS-Reject-Jobs Response

+

The following groups of attributes are send as +part of the CUPS-Reject-Jobs Response:

+

Group 1: Operation Attributes

+
    +

    Status Message:

    +

    The standard response status message.

    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the +IPP Model and Semantics document.

    +
+

4.13 CUPS-Set-Default Operation

+

The CUPS-Set-Default operation (0x400A) sets the +default printer destination for all clients when a +resource name of "/printers" is specified.

+

4.13.1 CUPS-Set-Default Request

+

The following groups of attributes are supplied +as part of the CUPS-Set-Default request:

+

Group 1: Operation Attributes

+
    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the +IPP Model and Semantics document.

    +

    "printer-uri" (uri):

    +

    The client MUST supply a URI for the +specified printer or printer class.

    +
+

4.13.2 CUPS-Set-Default Response

+

The following groups of attributes are send as +part of the CUPS-Set-Default Response:

+

Group 1: Operation Attributes

+
    +

    Status Message:

    +

    The standard response status message.

    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the +IPP Model and Semantics document.

    +
+

4.14 CUPS-Get-Devices Operation

+

The CUPS-Get-Devices operation (0x400B) returns all +of the supported device-uri's for the server (CUPS +1.1 and higher).

+

4.14.1 CUPS-Get-Devices Request

+

The following groups of attributes are supplied +as part of the CUPS-Get-Devices request:

+

Group 1: Operation Attributes

+
    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the +IPP Model and Semantics document.

    +

    "device-class" (type1 keyword):

    +

    The client OPTIONALLY supplies a device class +keyword to select which devices are returned.

    +

    "limit" (integer (1:MAX)):

    +

    The client OPTIONALLY supplies this attribute +limiting the number of devices that are returned. +

    +

    "requested-attributes" (1setOf keyword) :

    +

    The client OPTIONALLY supplies a set of +attribute names and/or attribute group names in +whose values the requester is interested. If the +client omits this attribute, the server responds +as if this attribute had been supplied with a +value of 'all'.

    +
+

4.14.2 CUPS-Get-Devices Response

+

The following groups of attributes are send as +part of the CUPS-Get-Devices Response:

+

Group 1: Operation Attributes

+
    +

    Status Message:

    +

    The standard response status message.

    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the +IPP Model and Semantics document.

    +
+

Group 2: Device Object Attributes

+
    +

    The set of requested attributes and their +current values for each device.

    +
+

4.15 CUPS-Get-PPDs Operation

+

The CUPS-Get-PPDs operation (0x400C) returns all +of the locally available PPD files on the +system (CUPS 1.1 and higher).

+

4.15.1 CUPS-Get-PPDs Request

+

The following groups of attributes are supplied +as part of the CUPS-Get-PPDs request:

+

Group 1: Operation Attributes

+
    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the +IPP Model and Semantics document.

    +

    "limit" (integer (1:MAX)):

    +

    The client OPTIONALLY supplies this attribute +limiting the number of PPDs that are returned.

    +

    "ppd-make" (text(127)):

    +

    The client OPTIONALLY supplies a printer +manufacturer to select which PPDs are returned.

    +

    "requested-attributes" (1setOf keyword) :

    +

    The client OPTIONALLY supplies a set of +attribute names and/or attribute group names in +whose values the requester is interested. If the +client omits this attribute, the server responds +as if this attribute had been supplied with a +value of 'all'.

    +
+

4.15.2 CUPS-Get-PPDs Response

+

The following groups of attributes are send as +part of the CUPS-Get-PPDs Response:

+

Group 1: Operation Attributes

+
    +

    Status Message:

    +

    The standard response status message.

    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the +IPP Model and Semantics document.

    +
+

Group 2: PPD Attributes

+
    +

    The set of requested attributes and their +current values for each PPD file.

    +
+

4.16 CUPS-Move-Job Operation

+

The CUPS-Move-Job operation (0x400D) moves an +active print job to a different printer (CUPS +1.1 and higher).

+

4.16.1 CUPS-Move-Job Request

+

The following groups of attributes are supplied +as part of the CUPS-Move-Job request:

+

Group 1: Operation Attributes

+
    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the +IPP Model and Semantics document.

    +

    "printer-uri" (uri) and "job-id" (integer)

    +

    OR

    +

    "job-uri":

    +

    The client MUST supply a URI for the +specified printer and a job ID number, or the +job URI.

    +
+

Group 2: Job Template Attributes

+
    +

    "job-printer-uri" (uri)

    +

    The client MUST supply a URI for a printer +on the same server.

    +
+

4.16.2 CUPS-Move-Job Response

+

The following groups of attributes are send as +part of the CUPS-Move-Job Response:

+

Group 1: Operation Attributes

+
    +

    Status Message:

    +

    The standard response status message.

    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the +IPP Model and Semantics document.

    +
+

5 Attributes

+

CUPS provides many extension attributes to support +multiple devices, PPD files, standard job filters, +printers, and printer classes.

+

5.1 Device Attributes

+

Device attributes are returned by the +CUPS-Get-Devices operation and enumerate all of the +available hardware devices and network protocols that +are supported by the server.

+

5.1.1 device-class (type2 keyword)

+

The device-class attribute specifies the class of +device and can be one of the following:

+
    +
  • "file" - a disk file.
  • +
  • "direct" - a parallel or fixed-rate serial +data port, currently used for Centronics, IEEE-1284, +and USB printer ports.
  • +
  • "serial" - a variable-rate serial port.
  • +
  • "network" - a network connection, typically via +AppSocket, HTTP, IPP, LPD, or SMB/CIFS protocols.
  • +
+

5.1.2 device-info (text(127))

+

The device-info attribute specifies a human-readable +string describing the device, e.g. "Parallel Port +#1".

+

5.1.3 device-make-and-model (text(127))

+

The device-makr-and-model attribute specifies a +device identification string provided by the printer +connected to the device. If the device or +printer does not support identification then this +attribute contains the string "unknown".

+

5.1.4 device-uri (uri)

+

The device-uri attribute specifies a unique +identifier for the device. The actual format of +the device-uri string depends on the value of +the device-class attribute:

+
    +
  • "file" - The device-uri will be of the form + "file:/path/to/filename".
  • +
  • "direct" - The device-uri will be of the +form "method:/dev/filename", where method may be +"parallel" or "usb" in the current implementation. +
  • +
  • "serial" - The device-uri will be of the +form "serial:/dev/filename?baud=value+parity=value+flow=value". + The baud value is the data rate in bits per +second; the supported values depend on the +underlying hardware. The parity value can be one +of "none", "even", or "odd". The flow value +can be one of "none", "soft" (XON/XOFF + handshaking), "hard" or "rts/cts" (RTS/CTS +handshaking), or "dtrdsr" (DTR/DSR handshaking).
  • +

    The URI returned by CUPS-Get-Devices will contain +the maximum baud rate supported by the device +and the best type of flow control available +("soft" or "hard").

    +
  • "network" - The device-uri will be of the +form "method://[username:password@]hostname[:port]/[resource]", + where method may be "http", "ipp", "lpd", "smb", +or "socket" in the current implementation.
  • +

    The URI returned by CUPS-Get-Devices will only +contain the method name followed by two slashes +("method://"). It is up to the client application +to add the appropriate host and other information +when adding a new printer.

    +

    The URI returned by Get-Printer-Attributes and + CUPS-Get-Printers has any username and password +information stripped; the information is still +stored and used by the server internally to +perform any needed authentication.

    +
+

5.2 Job Template Attributes

+

5.2.1 blackplot (boolean)

+

The blackplot attribute specifies whether HP-GL/2 +plot files should be rendered entirely in black +ink (blackplot=true) or using the colors and +shades specified in the file (blackplot=false). The +default value is false.

+

5.2.2 brightness (integer(0:200))

+

The brightness attribute specifies the overall +brightness of the printed output in percent. A +brightness of 100 is normal, while 200 is twice +as bright and 50 is half as bright. The +default value is 100.

+

Brightness is applied to the Cyan, Magenta, +Yellow, and Black values using the function "f(x) += brightness / 100 * x".

+

5.2.3 columns (integer(1:4))

+

The columns attribute specifies the number of +columns to generate when printing text files. The +default value is 1.

+

5.2.4 cpi (type2 enum)

+

The cpi attribute specifies the number of +characters per inch when printing text files. Only +the values 10, 12, and 17 are currently +supported. The default value is 10.

+

5.2.5 fitplot (boolean)

+

The fitplot attribute specifies whether to scale +HP-GL/2 plot files to fit on the selected media +(fitplot=true) or use the physical scale specified +in the plot file (fitplot=false). The default +value is false.

+

5.2.6 gamma (integer(1:10000))

+

The gamma attribute specifies the luminance +correction for the output. A value of 1000 +specifies no correction, while values of 2000 and +500 will generate lighter and darker output, +respectively. The default value is 1000.

+

Gamma is applied to the Red, Green, and Blue +values (or luminance for grayscale output) using +the function "f(x) = x(1000/gamma)".

+

5.2.7 hue (integer(-180:180))

+

The hue attribute specifies a color hue +rotation when printing image files. The default +value is 0.

+

5.2.8 job-billing (text(MAX))

+

(CUPS 1.1 and higher)

+

The job-billing attribute provides a text value +to associate with a job for billing purposes.

+

5.2.9 job-hold-until (keyword | +name(MAX))

+

(CUPS 1.1 and higher)

+

The job-hold-until attribute specifies a hold +time. In addition to the standard IPP/1.1 keyword +names, CUPS supports name values of the form +"HH:MM" and "HH:MM:SS" that specify a hold time. +The hold time is in Greenwich Mean Time (GMT) +and not in the local time zone. If the +specified time is less than the current time, +the job is held until the next day.

+

5.2.10 job-sheets (1setof type3 +keyword | name(MAX))

+

(CUPS 1.1 and higher)

+

The job-sheets attribute specifies one or two +banner files that are printed before and after +a job. The reserved value of "none" disables +banner printing. The default value is stored in +the job-sheets-default attribute.

+

If only one value is supplied, the banner +file is printed before the job. If two values +are supplied, the first value is used as the +starting banner file and the second as the +ending banner file.

+

5.2.11 job-originating-host-name (name(MAX)) +

+

(CUPS 1.1.5 and higher)

+

The job-originating-host-name attribute specifies the +host from which the job was queued. The value +will be the hostname or IP address of the +client depending on whether hostname resolution is +enabled. The localhost address (127.0.0.1) is +always resolved to the name "localhost".

+

This attribute is read-only.

+

5.2.12 lpi (type2 enum)

+

The lpi attribute specifies the number of lines +per inch when printing text files. Only the +values 6 and 8 are currently supported. The +default value is 6.

+

5.2.13 page-bottom (integer(0:MAX))

+

The page-bottom attribute specifies the bottom +margin in points (72 points equals 1 inch). The +default value is the device physical margin.

+

5.2.14 page-left (integer(0:MAX))

+

The page-left attribute specifies the left margin +in points (72 points equals 1 inch). The +default value is the device physical margin.

+

5.2.15 page-right (integer(0:MAX))

+

The page-right attribute specifies the right +margin in points (72 points equals 1 inch). The +default value is the device physical margin.

+

5.2.16 page-set (type2 keyword)

+

The page-set attribute specifies which pages to +print in a file. The supported keywords are +"all", "even", and "odd". The default value is +"all".

+

5.2.17 page-top (integer(0:MAX))

+

The page-top attribute specifies the top margin +in points (72 points equals 1 inch). The +default value is the device physical margin.

+

5.2.18 penwidth (integer(0:MAX))

+

The penwidth attribute specifies the default pen +width in micrometers when printing HP-GL/2 plot +files. The default value is 1000 (1 millimeter). +

+

5.2.19 position (type2 keyword)

+

The position attribute specifies the location of +image files on the media. The following keyword +values are recognized:

+
    +
  • center - Center the image on the +page (default)
  • +
  • top - Print the image centered at +the top of the page
  • +
  • left - Print the image centered on +the left of page
  • +
  • right - Print the image centered on +the right of the page
  • +
  • top-left - Print the image at the +top left corner of the page
  • +
  • top-right - Print the image at the +top right corner of the page
  • +
  • bottom - Print the image centered at +the bottom of the page
  • +
  • bottom-left - Print the image at the +bottom left corner of the page
  • +
  • bottom-right - Print the image at +the bottom right corner of the page
  • +
+

5.2.20 ppi (integer(1:MAX))

+

The ppi attribute specifies the resolution of +an image file in pixels per inch. The default +value is the resolution included with the file +or 128 if no resolution information is available. +

+

5.2.21 prettyprint (boolean)

+

The prettyprint attribute specifies whether text +files should be printed with a shaded header +and keyword highlighting (prettyprint=true) or without +additional formatting (prettyprint=false). The default +value is false.

+

5.2.22 saturation (integer(0:200))

+

The saturation attribute specifies the color +saturation when printing image files. A saturation +of 100 is normal, while values of 50 and 200 +will be half and twice as colorful, respectively. +The default value is 100.

+

5.2.23 scaling (integer(1:1000))

+

The scaling attribute specifies the scaling of +image files with respect to the selected media. +A value of 100 specifies that the image file +should fit 100% of the page, or as much as +possible given the image dimensions. The default +value is unspecified.

+

The scaling attribute overrides the ppi attribute +if specified.

+

5.2.24 wrap (boolean)

+

The wrap attribute specifies whether long lines +should be wrapped (wrap=true) or not (wrap=false) +when printing text files. The default value is +true.

+

5.3 PPD Attributes

+

5.3.1 ppd-natural-language (naturalLanguage) +

+

The ppd-natural-language attribute specifies the +language encoding of the PPD file (the +LanguageVersion attribute in the PPD file). If the +language is unknown or undefined then "en" +(English) is assumed.

+

5.3.2 ppd-make (text(127))

+

The ppd-make attribute specifies the manufacturer +of the printer (the Manufacturer attribute in the +PPD file). If the manufacturer is not specified +in the PPD file then an educated guess is +made using the NickName attribute in the PPD +file.

+

5.3.3 ppd-make-and-model (text(127))

+

The ppd-make-and-model attribute specifies the +manufacturer and model name of the PPD file +(the NickName attribute in the PPD file). If +the make and model is not specified in the +PPD file then the ModelName or ShortNickName +attributes are used instead.

+

5.3.4 ppd-name (name(255))

+

The ppd-name attribute specifies the PPD filename +on the server relative to the model directory. +The forward slash (/) is used to delineate +directories.

+

5.4 Printer Attributes

+

5.4.1 job-k-limit (integer)

+

(CUPS 1.1 and higher)

+

The job-k-limit attribute specifies the maximum +number of kilobytes that may be printed by a +user, including banner files. The default value of +0 specifies that there is no limit.

+

5.4.2 job-page-limit (integer)

+

(CUPS 1.1 and higher)

+

The job-page-limit attribute specifies the maximum +number of pages that may be printed by a +user, including banner files. The default value of +0 specifies that there is no limit.

+

5.4.3 job-quota-period (integer)

+

(CUPS 1.1 and higher)

+

The job-quota-period attribute specifies the time +period used for quota calculations, in seconds. +The default value of 0 specifies that the +limits apply to all jobs that have been printed +by a user that are still known to the +system.

+

5.4.4 job-sheets-supported (1setof type3 +keyword | name(MAX))

+

(CUPS 1.1 and higher)

+

The job-sheets-supported attribute specifies the +available banner files. There will always be at +least one banner file available called "none".

+

5.4.5 printer-type (type2 enum)

+

The printer-type attribute specifies printer type +and capability bits for the printer or class. +The default value is computed from internal state +information and the PPD file for the printer. +The following bits are defined: +

+ + + + + + + + + + + + + + + + + + + +
BitDescription
0x00000001Is a +printer class.
0x00000002Is a +remote destination.
0x00000004Can print +in black.
0x00000008Can print +in color.
0x00000010Can print +on both sides of the page in hardware.
0x00000020Can staple +output.
0x00000040Can do +fast copies in hardware.
0x00000080Can do +fast copy collation in hardware.
0x00000100Can punch +output.
0x00000200Can cover +output.
0x00000400Can bind +output.
0x00000800Can sort +output.
0x00001000Can handle +media up to US-Legal/A4.
0x00002000Can handle +media from US-Legal/A4 to ISO-C/A2.
0x00004000Can handle +media larger than ISO-C/A2.
0x00008000Can handle +user-defined media sizes.
0x00010000Is an +implicit (server-generated) class.
+
+

+

5.4.6 printer-type-mask (type2 enum)

+

(CUPS 1.1 and higher)

+

The printer-type-mask attribute is used to choose +printers or classes with the CUPS-Get-Printers and +CUPS-Get-Classes operations. The bits are defined +identically to the printer-type attribute and default +to all 1's.

+

5.4.7 requesting-user-name-allowed (1setof +name(127))

+

(CUPS 1.1 and higher)

+

The requesting-user-name-allowed attribute lists all +of the users that are allowed to access a +printer or class. Either this attribute or the +requesting-user-name-denied attribute will be defined, +but not both.

+

5.4.8 requesting-user-name-denied (1setof +name(127))

+

(CUPS 1.1 and higher)

+

The requesting-user-name-denied attribute lists all +of the users that are not allowed to access +a printer or class. Either this attribute or +the requesting-user-name-allowed attribute will be +defined, but not both.

+

5.5 Printer Class Attributes

+

5.5.1 member-names (1setof name(127)) +

+

The member-names attribute specifies each of the +printer-name attributes of the member printers and +classes. Each name corresponds to the same element +of the member-uris attribute.

+

5.5.2 member-uris (1setof uri)

+

The member-uris attribute specifies each of the +printer-uri attributes of the member printers and +classes. Each URI corresponds to the same element +of the member-names attribute.

+

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 Page 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
+
PPD
+
PostScript Printer Description
+
SMB
+
Server Message Block
+
TFTP
+
Trivial File Transfer Protocol
+
+ + diff --git a/doc/ipp.pdf b/doc/ipp.pdf new file mode 100644 index 0000000000..e4aa6b6aaa --- /dev/null +++ b/doc/ipp.pdf @@ -0,0 +1,1520 @@ +%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[11 0 R +13 0 R +14 0 R +15 0 R +16 0 R +17 0 R +18 0 R +19 0 R +]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[22 0 R +24 0 R +26 0 R +28 0 R +30 0 R +32 0 R +34 0 R +36 0 R +38 0 R +40 0 R +42 0 R +]endobj +44 0 obj<>endobj +45 0 obj<>endobj +46 0 obj<>endobj +47 0 obj<>endobj +48 0 obj<>endobj +49 0 obj<>endobj +50 0 obj<>endobj +51 0 obj<>endobj +52 0 obj<>endobj +53 0 obj<>endobj +54 0 obj<>endobj +55 0 obj<>endobj +56 0 obj<>endobj +57 0 obj<>endobj +58 0 obj<>endobj +59 0 obj<>endobj +60 0 obj<>endobj +61 0 obj<>endobj +62 0 obj<>endobj +63 0 obj<>endobj +64 0 obj<>endobj +65 0 obj<>endobj +66 0 obj<>endobj +67 0 obj<>endobj +68 0 obj<>endobj +69 0 obj<>endobj +70 0 obj<>endobj +71 0 obj<>endobj +72 0 obj<>endobj +73 0 obj<>endobj +74 0 obj<>endobj +75 0 obj<>endobj +76 0 obj<>endobj +77 0 obj<>endobj +78 0 obj<>endobj +79 0 obj<>endobj +80 0 obj<>endobj +81 0 obj<>endobj +82 0 obj<>endobj +83 0 obj<>endobj +84 0 obj<>endobj +85 0 obj<>endobj +86 0 obj<>endobj +87 0 obj<>endobj +88 0 obj<>endobj +89 0 obj[44 0 R +45 0 R +46 0 R +47 0 R +48 0 R +49 0 R +50 0 R +51 0 R +52 0 R +53 0 R +54 0 R +55 0 R +56 0 R +57 0 R +58 0 R +59 0 R +60 0 R +61 0 R +62 0 R +63 0 R +64 0 R +65 0 R +66 0 R +67 0 R +68 0 R +69 0 R +70 0 R +71 0 R +72 0 R +73 0 R +74 0 R +75 0 R +76 0 R +77 0 R +78 0 R +79 0 R +80 0 R +81 0 R +82 0 R +83 0 R +84 0 R +85 0 R +86 0 R +87 0 R +88 0 R +]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[90 0 R +91 0 R +92 0 R +93 0 R +94 0 R +95 0 R +96 0 R +97 0 R +98 0 R +99 0 R +100 0 R +101 0 R +102 0 R +103 0 R +104 0 R +105 0 R +106 0 R +107 0 R +108 0 R +109 0 R +110 0 R +111 0 R +112 0 R +113 0 R +114 0 R +115 0 R +116 0 R +117 0 R +118 0 R +119 0 R +120 0 R +121 0 R +122 0 R +123 0 R +124 0 R +125 0 R +126 0 R +127 0 R +128 0 R +129 0 R +130 0 R +131 0 R +132 0 R +133 0 R +134 0 R +135 0 R +136 0 R +]endobj +138 0 obj<>endobj +139 0 obj<>endobj +140 0 obj<>endobj +141 0 obj<>endobj +142 0 obj<>endobj +143 0 obj<>endobj +144 0 obj<>endobj +145 0 obj<>endobj +146 0 obj<>endobj +147 0 obj<>endobj +148 0 obj<>endobj +149 0 obj<>endobj +150 0 obj<>endobj +151 0 obj<>endobj +152 0 obj<>endobj +153 0 obj<>endobj +154 0 obj<>endobj +155 0 obj<>endobj +156 0 obj[138 0 R +139 0 R +140 0 R +141 0 R +142 0 R +143 0 R +144 0 R +145 0 R +146 0 R +147 0 R +148 0 R +149 0 R +150 0 R +151 0 R +152 0 R +153 0 R +154 0 R +155 0 R +]endobj +157 0 obj<>endobj +158 0 obj<>endobj +159 0 obj<>endobj +160 0 obj<>endobj +161 0 obj<>endobj +162 0 obj<>endobj +163 0 obj<>endobj +164 0 obj<>endobj +165 0 obj<>endobj +166 0 obj<>endobj +167 0 obj<>endobj +168 0 obj<>endobj +169 0 obj<>endobj +170 0 obj<>endobj +171 0 obj<>endobj +172 0 obj<>endobj +173 0 obj<>endobj +174 0 obj<>endobj +175 0 obj<>endobj +176 0 obj<>endobj +177 0 obj<>endobj +178 0 obj<>endobj +179 0 obj<>endobj +180 0 obj<>endobj +181 0 obj<>endobj +182 0 obj<>endobj +183 0 obj<>endobj +184 0 obj<>endobj +185 0 obj<>endobj +186 0 obj<>endobj +187 0 obj<>endobj +188 0 obj<>endobj +189 0 obj<>endobj +190 0 obj<>endobj +191 0 obj<>endobj +192 0 obj<>endobj +193 0 obj<>endobj +194 0 obj<>endobj +195 0 obj<>endobj +196 0 obj<>endobj +197 0 obj<>endobj +198 0 obj<>endobj +199 0 obj<>endobj +200 0 obj<>endobj +201 0 obj<>endobj +202 0 obj<>endobj +203 0 obj<>endobj +204 0 obj<>endobj +205 0 obj<>endobj +206 0 obj<>endobj +207 0 obj<>endobj +208 0 obj<>endobj +209 0 obj<>endobj +210 0 obj<>endobj +211 0 obj<>endobj +212 0 obj<>endobj +213 0 obj<>endobj +214 0 obj<>endobj +215 0 obj<>endobj +216 0 obj<>endobj +217 0 obj<>endobj +218 0 obj<>endobj +219 0 obj<>endobj +220 0 obj<>endobj +221 0 obj<>endobj +222 0 obj<>endobj +223 0 obj<>endobj +224 0 obj<>endobj +225 0 obj<>endobj +226 0 obj<>endobj +227 0 obj<>endobj +228 0 obj<>endobj +229 0 obj<>endobj +230 0 obj<>endobj +231 0 obj<>endobj +232 0 obj<>endobj +233 0 obj<>endobj +234 0 obj<>endobj +235 0 obj<>endobj +236 0 obj<>endobj +237 0 obj<>endobj +238 0 obj<>endobj +239 0 obj<>endobj +240 0 obj<>endobj +241 0 obj<>endobj +242 0 obj<>endobj +243 0 obj<>endobj +244 0 obj<>endobj +245 0 obj<>endobj +246 0 obj<>endobj +247 0 obj<>endobj +248 0 obj<>endobj +249 0 obj<>endobj +250 0 obj<>endobj +251 0 obj<>endobj +252 0 obj<>endobj +253 0 obj<>endobj +254 0 obj<>endobj +255 0 obj<>endobj +256 0 obj<>endobj +257 0 obj<>endobj +258 0 obj<>endobj +259 0 obj<>endobj +260 0 obj<>endobj +261 0 obj<>endobj +262 0 obj<>endobj +263 0 obj<>endobj +264 0 obj<>endobj +265 0 obj<>endobj +266 0 obj<>endobj +267 0 obj<>endobj +268 0 obj<>endobj +269 0 obj<>endobj +270 0 obj<>endobj +271 0 obj<>endobj +272 0 obj<>>>>>endobj +273 0 obj<>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ÌK‚0…á9«8CMlíä1Tƒ 3„º"E1@ T »—êÈé½ÿwÒٞb¸²‰'Päó²ZáxÉ +¤ÝЪNõ¦4î¡k¤Y¶–Åù ú9`äq×:ËØ1âdCFá2È܀ûö”ÓŒB׿]Ž +Ù¨«çÕLßÐÿßÑÃ<6·»ÅqÈ\!Äû¶Enr5©ñ¥*K霝ÚÄîõendstream +endobj +274 0 obj +6280 +endobj +275 0 obj<>>>endobj +276 0 obj<>stream +xÚ+ä2T0BCc3JÎår +ár á +äHÉHendstream +endobj +277 0 obj +31 +endobj +278 0 obj<>>>/Annots 20 0 R>>endobj +279 0 obj<>stream +xÚ­WMSã8½ó+ºæUc;vœÌ &Àfk†Éâ0µ‡\[d+#ɤ2¿~[Á&€7µEQ•Ьçî÷ºŸZá×I>þ„0AV\.Nί'ú°(pg”Œa‘Ÿf|CÏ?ÍnØÝÁ0òB³ï0Ëi­Ê¢Ìˆ*ym¡ƒ†‰7ÒÐÅC)!çYS!6‚?•9•@jàOT<•t ¼õ@aV+*jª`.JŒ\¯ñ W<㠖§Ÿfóù§åà;Ӂf@$”Õ†Q™æP˜:Z–:è^U¿¿ýÓÆMwRÑJGýr?OÂz¯U‡^dU‡ûW¿;î{µ8ñ=ëª?ýqwÑ(ðÆG¡çCÑXS²+©­z[¬8êøšL§B°áB‘£øÌgdG\AË0 VD¢vl– " AéÁLÁVhEi 9}¢ 19¬v`ªô’°XÃé‘»wåàâpŒ’PLèÅn¡µ¼¡½T0ž_uÊõr⟥¼P["¨îtÞdJ¾äæï¹âº0Wë"©s"ò¶.’³F»Ð”†0fûýDëœ íµ‰öàE‰ß°‹kïóÎ%”Ñdh"|0`eMÑfhӂdTz.@8²þ0Á1‘<ÞÎÄb±‰xJ4yÌCÖl´ÁO¾²ü5´ÁŒ°@ôW¤qÀÝä@kL ÕvÇ_çS EŸâóoTJ²¦pÉxö¨·Óo—¸ý‡‰}±Ù¤ø©.O‰÷èþ¢jZ +š) ±q´‘vŠ0É’Ëf£­ŠîږêÅVâ¢hêL7…°Rí\éIžKÀ¢l¹x´‘ÜJð­Ôš5™9—*ÍD¹q…£â ۔J³]Zs«ÓƒgCp³/µo;¤EØó²¬©sjÏқ½ÔZ±ßkìÌ©xUþÆLû³ëæön¶å…¤²FœIlçhñâ5*öbyv M'cYé^%ý»ÙB”©}£ƒu$Õ¼têåê‰.I‰ž‹‹Ró4ÆúsnÊ{5O¿ßdÝ¿gr8¹¹ÍеA¥acb÷LÇ!L÷s¾;¸ð;kR›Ò"nNEÁã[s¾©q’üüpÌ ¹à„Òה]¼3¡Z@ñð?ÐÎ3ož}¹xc–âÕ: W´—éëÑv~¹â œ‰¾~eŽèWNää”ÚEÒ=ÚéCw~ˆR[ø›RÛæ¢èp2¶Ž +Qô-(ž‚ŒÊU>Žì•j„™EŸr‡¶ÂzÐ@“š´E!|kúC”ÝuþljN|{õMfÑ'Ú¡­¦t ÛàµÝPö´nû éÇ*õÀØ+7‹>åm…õ ;lwò}„ðxl§XŒÂ/”åªQísdfÙÈKÜâá-…ÇÚ¹=è…GH¨E!<ŠíT»@á7Œã +±û²Ï¯ÇûÍPŒÁsàÎŽÚ‰}1pµúûä_óàXendstream +endobj +280 0 obj +1134 +endobj +281 0 obj<>>>>>endobj +282 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS047Ô3T072PIÑPp VðÌ-ÈIÍMÍ+I,ÉÌÏSÈOSð Ð Éâ҅(օª6‰™˜˜é™)€ù† +ÁÉù© Q×®@. óendstream +endobj +283 0 obj +110 +endobj +284 0 obj<>>>/Annots 43 0 R>>endobj +285 0 obj<>stream +xÚµ˜MSãF†ïüŠ>nªl­4²õÁ 0°¤ ÖAbO¹yl”²$G’‹åß§{F–ÚY3rÀ)ªLõh>ºßy§ÇŸ9`㟾׃4?»ŒÏ¾Þ„ lˆ—øÄóˆ_<Ê¥¬d‘Êú·ø/…8¾FÆîÄ +²¸zšG0+Óm.‹&i²²Ðø§Å…oy„Ç/–åz]¾fÅJ¿¸à/BVCµuÏoмàW;æœ:Æ9…gM¨?êa|õ0;–s®û»*‹e¶ÚVº¿‡¤HV’Þ…ù:i'–¶ûV€³Ã~þžû³¦gcÇÕËTãÜÍflœè­ndwE#«e’J˜É:[ô/­²M†Ž6竺Ë7kه©\>ÿTÿÑÅõoýÜ­§\6¯I%áb‘gEV7Á²ª)‚Ûdý¹¡ö·èÄ‹æï,h^•«*És’Ü)V=ZM$Óm•5o¸k6eÕ|nˆx~hˆXÖ'qôôNœžjy¢|ÿ8˜ïØ=‰÷¿%|g:càcWè/°ñ½y‘Uç<õ‘®S”ÅxÏyj Ù ÙÎu|f[6:'}8ôñx‹þiÙà.Ž“ƒ êÆ¢4rœe€«5áŽãq~2È3"G7<'ÂòÍ<#Ÿú˜#ψ\ȧÈ{Î@8Ýi`¹=ïOöú¿ü%_ՊÎ;7˜hU\,Êg4‡²n"%Gô‰ŒÌœën²µ„›²Ê“¢L³e–* uržX®EéG³ÛьÊ6èÉ·Qã;=©†IO-Ýêɀ·zÚñm!#ÏÌ·#(ڞȻ¡55óŒ@Þ§¼ôüÁüõۛ2é;Ú ~Éä}R¬¶xî÷Ì◬ZÀõ"£ì}$aï8žÃçð{ù I±è$ɾo¤.Bꏚ)výUùèu‘– ò.#®’¢þÌÓuÛäû·Ûl!?ÝåC¹k5ÍHæIÑdéðê ;Áž(mL•PT㰔Càw¯¦@ûÆÀ9A>,H§&žÈÊ5M<#hŸ…VÈø#ö=Õûàñæ +¿õÃÜg…ìý,‘9ú–AM™–ë“z•T@›!Ý0dhG«˜h`…3€s‚2b<Œ<#È 'q#Ïä}ò]#ÏÊèt`þœ “•v•‘gò¡½üaňPè}KŠSÏíŠñÛ2Y×X,U¸‡õݦíÉHþóÿh£ewR “†ZZKÄ@3s†u£çiȘ 'HC.îa#ϪÎ<Œ‰çi(èŸtú*ŚxF ïэÚÈ3ù`:ONPõGµAÏ¡Q?d + Fð¨Ód-•<±ô‡¨©¶i³ÅâïÃôEú˜…ú¥ëÂ,ñ +Ú£Rt'hÕ0 º¥µ^ 4ȇ:ç 4 t›xF ÒEËÈ3‚J庉ç]7B’«‰g•‡ ¨ã7µ&!<’͆rü,›W) ¸ŸÏ”Z°|éò^ŸÖÛ¦ŽºèL«†I +-­3m @Þæ’SpNÐù5ÈûœÎÏ Zóô9A©u)µDj§BßáTj=ÇÁ·7,·ù³Ñõ1–ý]Fa<†oq¬*ÔÓ&× úòT7LÉmi;Í*O} +Žç•›ÁÀd8¡‹ßÈsB,æùp"ow¡‘g3¹PÇ!7ìË_3”m¸Ø¢ÁÓ Dçp™ÔYª¶û,[Ñ/ii*ëú½bÿõ#.FÁî¡þ¡ª›Ö¿GŸ6®P½í¶úúãìfck”endstream +endobj +286 0 obj +1334 +endobj +287 0 obj<>>>>>endobj +288 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS047Ô3T072PIÑPp VðÌ-ÈIÍMÍ+I,ÉÌÏSÈOSð Ð Éâ҅(օª6‰™ê™)€ùF +A©i©E©yɩŠ)×®@.²9 endstream +endobj +289 0 obj +115 +endobj +290 0 obj<>>>>>endobj +291 0 obj<>stream +xÚ¥˜ÛnÛ8†ïó߸ IJ޶”»¦í)›lãì½,Ñ1 IԒtÒ¼ý‡’|HìÐ- + õÏéãpÈô¿‹|üÀ<„hE}q½¸˜þ™AèÃb…_fóå‡nŸ˜|âìùÅÄV0 S/4’Ow÷xðº­XÍ­àæînj–ò¦½f Z&sÍE£h)×ZòåF3%[ñ†•ÀŽÐò +¾‰%éî$o4“pÏ´ AƒÈ½Ž.ÉȄ»‚ۍn7z²Doûðå§fB-J×­CsµæÍ£‚ñJTåør hU­p¼Ì+6>ˆ<äOyµÁ +ØàTË +¾â…ÍÌë,Ù òJ h¥xâ%Ú4ìùO7/´¾ÃI P›¶RC½©4GԆ2º"DÖ°ûá ã¢Ê•B¢V‹¦k¡´g·4ƒ`ÞmiÚL#Ü:ãüáûz½ïso6”Óå¤`)ôÚîàZëvdAóÿU3½¥ò`_‘r%ž1L‰,4yÉå’ÁF±òÊÆ›íÄëðY?WÓ©ÉÝ]™ÈÓýü°—‡º?å ,­WŒ+}£G¦G;¼½ýp“]û#ó²æÍñ¨»áH˕6ўØïÅí¶qjVއ¿·-hˆöídù ˆ¥šòÒ-Š!Dß¾çWEÁ(Dß ÷¿ê—Ï_5Ԏ- ÏbS•¦LCb ++!¼e.½BÔÛþʓ߰;í ›²äfÛ.©ÃmããTdÒçá4BÖ{)ų2‹‚):º£S½4]œØÑ;-`fÞ©=ëÝ{ÐG˜ÛAh3êû!”?²á˜Òø0Õw…—/èϐ®^N͑ÐÒ2Ãd;²O”Ýá8ÌÖÝÉ·bØÖXˆ•MNcê¹,) ©B²G<~Lâ™|T¼õÜ͞¤Kl–x ]sñލw­ø¾aú]âf)޽ [%‰²£ÐʵälŸ™*$ou—Ç—Å…ïùx}ÿ +qêÍ!@Ks’Bôdèäýâ`æ{i§ŽRcrJœeX“Ç fJb5½ç ‹È°WÓk¡ßÁÄ7ùÎS»‰tiOð +'F”?Õx¾Y¡iÁÿéû~Hؒ$ã1^ñŠy.sDjW@$vdóx ÈbI2Û?ÿæ/s͜ÉÄûdz{3hwïAJL—;C"µ+$»B²yƒûݕ-Ù1DÁˆ’}DÖº¿"†é(ö|w:¤v¥CbW:6ct€®7֔“Ϣؘ'¶žÙ>ã ;ZöâÎ) ,]9‘Ú•‰]9Ù<Žqò/í~«œZzÐEd},9cP“Ø‘ iÑØ$ސIC;š¿2̓áw#å(Û„^ÎBóÙƒšÄŽ€HëÈ&qÐ,²Cºä†åãk,æÍo^`ïIæg e;!­#›Ä ¨{ ÝoáçvÍõk<ý£Ü¹sÐ¥û|&±#(Ò:‚²I¼õJ‡'¬ÿú?KâÔ÷2û!éªüçâ<>>>>>endobj +294 0 obj<>stream +xÚ­ØÛrÚ0à{žB—í®dùx™@“¦3Ò@À€HȜچ¶oßÕ®C9Tñ*ÓI†dÌ/±þFZ?JHøQB'öw±\Ïn"¡”˜­D,ƒT$Y,fËwŸªr9ü\ÍßϞJ… —U ì ]¿¤”#{-ŠM×ìXQˆ§j.VU-žëõ¶]o›ú8È@B‡‡û[eö…Ó,Ƚ–ʃPÔFLÿV‰„¥±ŽWÃyÄ] |-FÑaf•kø7 PēÄð,Üä½)MÑ¶ÑøÔ¨þ¦8·÷ÌeÂ4— Ã\&ªÃÅ%ð,Üç¤ØÒÄޛ©/ ä%”’§P8ÁGT[ {¦éú¤"D|)Ls¥0̕¢:\Ra +ÏâŠhv?*u¾¦ì o³ +ƶÂ4× +Ã\+ªÃe%3¸dÅ®~À­×°œÂ³%eG‹¢,íÞkúddH¾ ¦¹2æÊP™8ËíMMkU†Wm[¯ç»Ö4œÞ¤¢S˜E‡°9Á:2Û%.ªZ<èï@×#g¡GC§4SŽÂL¹®—\’SC}ŸL‡·86«bW¶ý++ºS9.ÚG#–4üm`'íºÚöa%Ú£­Sš‹…a.Õá‚Çä«kW K+¼Ô²»°Z!Z±/Öe1/ÍKÏêۚ1TÌoð”æša˜kFu¸Ì´¢fWË%¿Å™>%ƒávnªåzõ›ÝÝã0öèî”æBa˜ Eu¸  ¾ð5†Rk¼¬ÎÚÍÀG’‰G£§4 Ã\$ªÃåúdÿÊ¢i oûÅ~ÛO,hî·(K<Ú<¥™nfºuu¸ÜR}Ôæí.D9–[ÂڃÄՇ•¤mžÒ\, s±¨Vµùn'ò½Ò×÷! +ù½Ò\( s¡¨”Ž{ûbaž[汜²³u…ÃñLzrt/¹taîÑí)Í¥Ã0—ŽêpÑ©ä¨Ûߛ'³ð ËÏ?ùØáÿNI÷Jsé0Ì¥£:t:OpSÏëÕåQÿmVK¶Oi&…™T].ª4½8Ýï× Îç"Àºf¾a.iÎ>±Tyô~JsÅ0Ì£:\bqv~ğŒy\#&—°Ï*=Ú?¥¹VæZQ.+µÿ/՞ùu`tñu Û}ØVð-V¦6ۖyxÕZ{ô|Js½0Ìõ¢:.½>ÜdÝ·Ì +–Ÿiˆ÷-¬œ¸Û<—fw‹Ç.˜»ÉÄÞðÂÃ.M1’™_÷¦Þ¯ÍÏÎæÛà®+$endstream +endobj +295 0 obj +964 +endobj +296 0 obj<>>>>>endobj +297 0 obj<>stream +xÚ½Vݏâ6ç¯ñҒ#@awß¶§^µÕ~Ð#+µ/&ˆ·ÁÎÙÎrœúÇwÆÈ^¥S¥Š‡ٙù}ÍÀ—N CúÄ0Áx +é¶ósÒùðéFCHÖt2]C’õ&ð\¢NjeûÉ+]™@‡+ƒÑu4âKIްÖE¡wRmÀbê¯C†65r…àè\ˀ­ÊR‡¬öðñe¾ˆà^ùKR94hè5¬ ¾I·¿:y“PÛxÚîr™æPY*®Š½/`P™0ÜÏç œ£ö•C  (펐²(¹xV“¢‰gÅ07„dð›^5ìÛägÑô@¾¹ ËÞðëp8-ûPò1€µ,°é<9Tº9v>ëý¿T$Æ;Û¢oŒ®J˺]°f± IZ ¥0^Zwل6·µº£i@ó+W„ø¶‘ù.ÅæxùI¸Êˆ„ÚTbƒ@6ÀÇ\‘’£°ÀVy†ßm°RºlÑuý›§*”uéîÃ&e¥ç=“”$çE`j꜍Gaá{-p+”“)UÒiµEå¢ ¨]ïšAed—|¥Ç²ÿŸ”„V_IÐ}Ož¿|¾'ŸLˆg‰©\³uIßjpªd}t lM‚Û²ÿEùî«^ V²(( ÎáW·ì=Þý±ì× ?|šžd§~mÙãÁ‹ËMŽfÙog­MïyžÜ??Ý=<üyG»†@høárá@Z(ôfCtwÒå^Ò‡#MuEš«Í…AR‘R[¶– ÌÓæˆÎ2͘²ÂvîKÃ_¸ßiú¿A‰-þÿìµ¢Dï4¬„Rx¦iƒ<„ÁmÚwHüÂpˆ5†P{¿lKˆ ¿Ä<†Àìx~»Š:vY^Z–hÞ¨²ÓÿL¦ßVa›ëª`,´s×M]Ã2ÓŸfH,/Wêv<¾‰¢ÂÃN9ñháZTÍstЫW΋–ME*O›ü°—j{ð¤ޞ;ԃÅé¾÷¿‚7¢=LZ¯E°”·¡ÁxÂÇÓhEn‹™?”¶Î̖óàûœ®µZõ0Hdžü†W¾ûX]™¯.u¤D¥º ‚µºreåBe¶þ«¹ ƒ6ßs¾çëuíœ_yã8z÷?Æäzݐõt4ãï¿$ß;ÿ7Ñ¿°endstream +endobj +298 0 obj +882 +endobj +299 0 obj<>>>>>endobj +300 0 obj<>stream +xÚÍUMoÚ@½ó+Fœ@ª¯!@¸¥QS¥* ŽÔƒ/‹=ÀFf×Ù]7ɿϬ×PÒäKÂóõ潷뇃ˆ> #÷Ͷ¯Içäòƒdå&cHòÞµ²8í'÷6Á,,—9×9\Íç dñ ¼(Ô£Sb&V"ãV( jŒëa‹¹àÀ­ÕbYY„?¼¨0t#âQ8tÃnì5üPKHp[œòÎwÆålŸlæZH¸ + ÂÀJ94˜Ã’€ÁJÐx«`‰PºlÌC¿Ï°¡ÛÇ8ó-‡! ãVÓ[4¥’ pã?Œ–„µVUiê­÷ kƒ2n äÚº°=¾›1}EÆwרnJԞÐC2Ú\"¶20Ccøú¨•Ãivšéfž{âj¶¾æµ×Ô¼€Ÿ\®+Š•ÃņkžYiö­)Ý¿«%´Ýº²¾uP4­»„ÈÑdô—’ÈËêÝ$Í0Œ›™l@:Ñ̆MçÙʱ¨g-pË¥uRYµEiÃ#óxvãií¶wyõ¬§Õ;?ԍñÎB1\h$ïÖêîÅ{ÃBáhG[«@íÕN{ÑSE§i²:Nä€ÄÇ/@‡Ã>{7ýZ¾çç8díî·þ”|ÒÏUY<ݚӜÆOyúÿt û„[P»þ.ÒA¥E—¤¦Ÿ´ÿÖ>1M2Ïî‰'ÞÝiw·W$”®'7w.amZ~`ö\­íü.™*XŠ¢ 8pŸlڛÿNû ȓËQË>>>>>endobj +303 0 obj<>stream +xÚÅU]o*7}çWŒx)»aB’·4jªTùº7Tê•x1»³°©×ÞÚÞPªþøÎØ K€Û(êCÅZÛ3sæœãñôK`:„ÑÒ²óã¬s~;†$YÎK“‹)̲Þl…Ê•ƒ§çÙÝÓãõýý7°uUÑ¢‹BÊB-Á:Ãn%¤^.1ƒuáV´†P‰%‚HS]+Gçú³×΢d¹J¡rmJá +­âfk8‰Ç¼Õ}ՋȮí¼—Xt:·©p¿ãf­Mƒ%Î{׿Íûóþ§8¿4Íì%›÷n~}~$N@¨ VÅr…fÞçÇÇç?è^+mÀ­5,„Rh|›6 uMœ8¢aÔúš"wtN¨ ä…D{DD`‹ã€:!pw@]wUì2½-š7Êì4*+Rá0”Uﰀ]éZ2€-–îòƒ¢®í2Ó_i¶Â´È7”“ª Gâ.j_Â7!k‰?ö4Š2ÌE-]·©g@/^1u%ی”¾¶+hðñÚáÕ{…zðâˆKAÒß=?“ rBJ½¶ næƒ¼ÄøXò›Dh1îõãÛ8²\‰Y!>å¶O{¦d?ø:-š-úM¸H$^ñžùêg`umR<;ä‘•jI )tíªÚ…Ì,5üWq +n¾§2üºxZÒ]Þ_ôfXV’/ÌõŽù€ã’1ãˆhþEÃË:އÔúAŠˆ8ü+ÚJ+‹ÇSc71sͨYÆ¥Ñue=àVf yXº¥ÆmÅ;QäÐ]?s>H®à©BÈx߅‡Þvíj h-͂SFµ[^LSW8¦ 1‡<>Ò¦î…ZÖ~¤S7+aDÊ.xAwªJ·í=Jé0ݪ®ÜßP!u$›ÔÝwŒYÈЦôI3†¤%³qï£8‰I “6t²‡t†Ò×zÁRÐۓR&Ö%]ß\´OX`wxåmò¯¼¶n:a¢éÎD£áÖD#&‡¥Ú€VÄ^Š'[úNêúóÞàÏÁ Ïû@Ôªðüà>wì=Eo¯+ސŽóH5ݤ׀¢ø• å/šòɔÈÉh_0ðoæG0k»HôzÃñh:|x]ƃøü¹KþþiÖùÒù¨õµêendstream +endobj +304 0 obj +858 +endobj +305 0 obj<>>>>>endobj +306 0 obj<>stream +xÚÅVÛN"A}ç+*M©¤Áwޟ(_sw®ÀÞuy’´Ö¸@ch1TÊWēÎGډݣN|̱à×dŸ”B¾ªÖ¢“+~¡'G¼B££öG'«Ä'pðÚ?_Fµµ&Åendstream +endobj +307 0 obj +834 +endobj +308 0 obj<>>>>>endobj +309 0 obj<>stream +xÚíUÁRÛ0½ç+vrfj9n Ü(-Lf€¤Ä:ÃE؛ÄԖŒ$“öﻒì$„LÛ.=trHâÝÕ{ûôvýÜc0 ƒ$‚Ც÷)í_ÆÀ¤sûht’@š¦Km¸È¹ÊA¡®¥Ðî‰i4T¨5_`x”>õD£0¶5·T¼„k. ŁÊábÉÏ *˜¡9Û©°(}nŒ*ƒ:È(Y£é»Êí€ðGe{4e¬ƒÀ5ä¨3ú‹94f¦†! ã0j1Ù0Œ,¦œƒ!Øñt +72ÇÒaͰâ$³¦Ba\sǗ§À«L@ÒÃÈӎéëâ~: ®ÐŸqΛÒÀ¤FÅ-®/ì$µÝ&á¨ëöM™ìÊàápð# ØÃ Ní +íˆæmb­ +ae¼¿;Ê6TãñtM4do1ïð¹AmöíhÎeYÊU!°P²©5jۊ+òBS×eAŠ“ü5WZaß )¶{÷Wö``gáà|`s­âÿ¶µØ;¬µEµß*„y°î“žÌá;þ\I•“/ö5™Ñ%²ß4Onϯ¯¿u7C쉯yuu xe"?–jë±»å6Hm®–RãNs/¼$’®Áޝ‚¦ÓÇ>„± ¥$«ÂØJZ#}p Õ Uû½’;™‹¹ËÜÝ0\òÅÆw«Â,©EÇË6yÀËò`gÜØnOC´oüv{ç8 øó(tP™_Â7~ ï³ÄÿÅl æÕÎ`Ú®ÐÉã!ýFb'¢õl¾"NÈÄ¥P5JY¯ûéhÝwÒzˆ ?ÒúÅ̟êüãª.Ñõ÷LԑãÌFéA þî%'qx.™¹Uô%í}íý܊ƒ®endstream +endobj +310 0 obj +657 +endobj +311 0 obj<>>>>>endobj +312 0 obj<>stream +xÚÝVÛnÚ@}ç+F¼¤Úa …$oiÔDHI  •ZÉ/‹=àmì]gwÂßwÖ6†ªÒVªª +$.;—sÎÌÎø©Å G/ý¡{GYëìuz}l³ ÏÌâÎÀW_¦Þ Zoª…´¨ LrÔÜ +%»³ïä5Æ*//ùCç7KðˆŸÚøAØé½ z½ ì‚F[hiÀ’K^Y·V‹yaÑÀBiÀgÔëæðQª•«œ‡@iYß\Z³63f‰0ñ5¥EÜvY¸®¤²`P?c ±ÐÙt óu‰¢ü[û9’d°!wîjQ|v„Þg|*ÐØ#¢l$Y¨4U+!—°ÔªÈI‘Å.W‡Ëyž +BÅ ä\[gbª©«tµÁ°Bwã"»ØV .›ΖêÝßsŸ§pËå²àK.c¸J¸æ‘“úÂ;í-f/"cƒ¶]zîÈ*´—Ö¡Û¯˜ˆÑDô“˜ +I’G%Ò¾ÏüÏöÊZK0žNáNؖ¹0ãҊˆ"©¨ÈPZj;™ daÇ)¶$>a‡]Ü]~ »a÷¯ˆ„—&ÓÙxry{ûmS ×7ÔQ (#»::\²ÈæœP¶YÕÝ`«M=!ÊA´øb ^0jÀ^wz¨ö ;®€Q:±LP‡ÝÞû-Zt© ¦T X%"J¶|ÞD%UQÙoÿ »Î±¤BŸ Uù/2á͸séËì›Ûü笼Œ›Ç…šÃòS~sa+n…)‡ÅÞpp7p¯fM¨PÏLŒ½í0rB0a“<âz¥tL[éÇ'ÈöÕ4É3w ãSµ³ÐªÁ_Òà[%Êìo±gžX-Ä ^ ™ӗ½ãj$֐Tæ4zÝýïvvÅ1¹’q9xÅ¢´ÜKºE˜ðæˆr»ŠVÂ&D±ÄåHžð4=©÷ãY]ÖwKqxÞ«Ê}ã,Oэ檲äJ3ÜùyläÚÉ=g͂r1±3¿½7>w|œµ>µ~ÔÎÆendstream +endobj +313 0 obj +766 +endobj +314 0 obj<>>>>>endobj +315 0 obj<>stream +xÚ͕Moâ0†ïüŠ'8$Å!…¶·nµ­ÚÂzX‰‹Ip•Ø©íôãßïØ1”vµ{Xq(çãw‡çƒ} è +[ßf­“ës`)̖t28£/y'Oã®'Óèm4ÑBZÔÐTJìΞ(-ƚ´(º´Ùa©ŠB½ +¹‚•Vue@-[«Å¢¶h€kƒ2n âÚºcKi¿ïuᚹƒØk»qe]À¸BÍ­P.·õ], ¶ žZnkwh _í•rzå2ç:ú¹'.§lrâ/9÷t¨y·\®j:J‡«5×<#Ù0E{¨KûÂ(£`ƒ¶í3wdS:*Béö'ã äh2ús’LÌüìý˜Åiœ„ž¬O{£žÁÕÑdw*ÇÂ÷šbÉ¥URY]¢´~¸h×°ÆÝäÂ`¼x¢N°Ø›ˆ~‘Ÿk4–î +§Î¤EhÈj­©)¼ð‚ˆ ȳ5TM«¸¡Š`:ª¼¬~  "—ym¥m8€#Åm{ijËͼÓ{K{½þ¼ <ÏI*H|ÝÈ’Wª\,…ðMë¸ÞžKï±y§‰ËñéFÃùVzÌöU<4^y“êª*¾M»ÝÂfŽºKÿ'ùìòw¤¶ÃV£Z‹6AæÝCódä71|÷85ö¿6#³ç¡ÂÌA“âúÈKÖ^p)I½9£—¼.¬S)y‰óK†ónP{r=Øa)dÏ;`Ä¡sc-VkÔóî>{ûsŽ'³Ñøþòööç6wM5„Qà4Ðà܂0adâqéÆZŠ‚ÂiežÔ"ªûe[ôÒEýB ¾J[*I»§:µ¡gV3ߛúR}jlÖª.rXà¦ëÞNƒiôB×ö_ÛvâYÿ”Îçi3¿z0*«f͝"&‰GºrÑ0éýíïl:Lã3ðá¬ï|Ÿµ~´~Gwmendstream +endobj +316 0 obj +727 +endobj +317 0 obj<>>>>>endobj +318 0 obj<>stream +xÚµV]OÛ@|ϯXå‰Hµ‰Cš@ßè-)„ª•òr¶7É!ûÎܝ¡©úã»{gC¤-¨((‘ÎçÙÙÝY®: ôé“Àވÿ²²óvÚÙ=B’ÀtÎG£ý1Lóé!+$*§“éñéçӓï`몢C R¡¨ÄA‰Á-…i¡2R9Ì!Ź6sYÐ}©è•KÆ@{ÓËN¢d/0”A‹æšÞðaºJ+ìr ÚҙÓ`+Ìä|”¾‡l—º.«…›àƒQ<äàݯe†Qmdf;ô3ë½Ù¸ó×\C ¸8;ʉˆ`CJÃlWUqF Ë¿³d0žõž?™¼Ú<<œGÒF"˰rR-"Òß2›Të…z2·¤ª4/ƒpÎÈ´vHµÍe&n–Hü O¥çÚ0^bæ6Jߔ/P…7Ü#v{6j®9‡?ÜsåôIßN†|¸×Çà†ñk‚öRD×Jmá mE.àú0í|éü3‘œendstream +endobj +319 0 obj +834 +endobj +320 0 obj<>>>>>endobj +321 0 obj<>stream +xÚíUMo›@½ûWŒ|Šl½˜€“[š~ÈRݺ6¾ù²…Á¡‚]²»´É¿ï,âºXŠdEÊ¡âÀÇ̛73ïi¹q˜ÒÅ!òaBRŽÞÇ£wŸ®€g çô^,d>ÜnWï&M½•Î¥E k4•’'ñOBÀy‹òüÈ¡â;„L…úË=쵪+*a­ÎÔ `P¦ TB[¶;Iuí¸CȚÎ>»ªÀ¯á[…ZØ\I¸éË»\«OÞXakK4Fìÿ)åÚ5VÈTètÇç¾8LÙbØæ+µ(à‹ûšâ@p¸½Z$®ë Ú!–ñ󼄒 Úqƒ< ȶ´Wt¥ÇíÍ@Š&¡WL!—´Ã¤™}Æ8 ˜ßqò©FœÝR«,UŠEõÁRH›'TI%u‰Ò²VGR?r:znu3ŸuˆZQ>`{]úµx€…O!U/ØîbúL§ÁnBk/Õ/7Ÿ|ȍuÆ©:@¦UÙÌaÅò¹Ûà‰ñªï•ñAÎ5Þ×hì™~­«ªÈqسG„º%<˵oÓcü ´:îÔõjÉ tÛM†æIhåÒÂr»‰[AÀv½ ÅtëŠ +“>>>>>endobj +324 0 obj<>stream +xÚÝUÁNÛ@½ç+F9%›làFQAH@ÒâJ­äËÆž$[ìµÙ]ü÷ÌØN€„¶´‡ªª)r¼oæ½7ÏãûŽ€}ŒþÆYçCØ98?1pAw‚#aÒûGpöevë] óÎRi-Z˜h¤S¹î‡ß 4!7œøÃÂîÃò ¢Þàq<F}0èJ£-8BFi‡¤sFÍKG˜EnÐTۛ1Wƒ;¯5¸œq̂z‹‘?äÞ¶²3•²É +”ŽÓ2Áא[JÒ è܁Eó€ $Ê`ìÒ +æUM©þÛøPrg¼zì[|±/õ3ޗhÝþlÜYäiš¯•^ÂÒäeAî,^êfZ¶,ŠT)i¡Æñ÷–±¦évÒ1 n\ÄÉó¼àtہÏÒ෇o$ÍA¦p%õ²”K©8[I#cöì÷ʳŠî3e/¦Ã]·F¾¼¡›Ò^ږî¾j!AÓ% Uš k¦#_øc_ì̶uàr6ƒë<Á´îu‹™ÔNÅT)Ë µów¨vS•)bõ8KÒõÄÉõéרõßÒ“ïÚÁt^NoN¯®¾m†Á©¡Xm@]™Çȼt™Í©8±üQÖvô4éÇdp‹÷”^äÌÛá£#ÎÃɖñÁyð"W-.êq8@P&ٙ•Z®ÐDýýþ‘VzÜ,¦4 X¯T¼ÚÉ¡ý¥¢4ë,þ_ª\U`­ˆ~‡€„¿(Hn9sûºû恇¸ß$÷ð2iïþ½Ìå§¢çÊ5c,m½dvó“»3Èm:ö\hw-&Þóc#­¾éî°Zç&¡[ëÆQ«NŒI}Œ›žõ‡Ë¬H‘VÛöm6ÆybÂfy“á€O‹ ^×ôn¼ï¥ü1ì|ê<›Ôu”endstream +endobj +325 0 obj +679 +endobj +326 0 obj<>>>>>endobj +327 0 obj<>stream +xÚÍUMoâ0½ó+F\ÚJ›–@oÝj[!µ…-éa¥^Ll U¾j;¥üûqÌWʶ+õ²â@bÏǛ7ïÁK‹A? º}ˆ³Ö¨u~ÝÆ šÓQB$N£¥„8Mdn`<‰FãûËÛÛß «²ÄC ´4Ṕ£’Ye$ä<£‹\œjïx¡Šªt—I«e¡åYôÜê€Çº~@½^yZá­Á–J¾à£‘ + +Çz>ŒæöÞA*²ÄPm;}³ZªWÌÆ´²È^c™¹l4Ý!\r3)óÍtV‰Y∠yÂÓôħç×C`=¢ÊC®¼`è÷¨XÏ`Õ«ÇÉÔ»‘Æ»J¹Ö8уEQÏ»#A[ŽçEš«$_ÔDéN¾¢‘rAs”\YÊiÌ¿¶ºpcýٍ¥Ÿ]À¸”Š›¤Èár[žbí.xj¸©4ÜI­ùâ])‚« .˜+áÖö„r²:ÇoäÜã¥â)Üò|Qá=é®–\ñ˜–<•æX—öŽ/Æ`ÔZÛfî_äui/u¥Û¼iRÇøŠëDÙiÛÙ»>ó{~ÐЂ#u4™À]!dj{MeÆs“ÄX©ˆ« eg‡óö «Ù .`¢¬XÁ®Ƴgì÷іÊÚ@ŋøØ% +âJ)R¼óȽ%y¼„Ò5Œ©áNšáVšÝ`#Ía­–K!<o#…#ºôû|¤b«Ÿ§ÓÎ[¯Óé?d1Èåê ̬É>>>>>endobj +330 0 obj<>stream +xÚµT]o1|çW¬xJ¤p@!ɍš +) 4©•x1¾ÝÙÛ×4ýõÝõ!PµU"özwvfvk1´èC§Ç_™Õ>MkÍ«.Ä1L|Ô;ëÃ49©çVi6R.Rbî•^Ffîê0;™“¢Ð³Ó‹ÓéC­Q»×èò³é +A¦ +µ‡Ñx:Ý®¯¿ƒ+òœø•rP=á½UóÂ#(()¸<­Ð¯Ð‚± §œO8fþ€ÒWåâN£ÍåÜÊi%@ÐøŒ°±jۋ^†ïñ§ŸÄíþìôÿZ8±V•€+ٌ΍G±zyTjdˆ{?`8o!RX׳ØR{Yf,n8+¬zSH÷wC Ž@$‰bH„®z‡º£ÈœaÏ9¶u‘½±J*‘6ea-g_Ò#>ï’oë*I œÐ ԝ7yŽI=@Dº¢ªÁ¢4K­~aòç.£ KÜÚãfðíìaQ82ËÚ¬z/u h^aµøX  Ë¡p„Y‹ #‘¦æ‰»&/;ôÄoŒÍ9šW½jçìdݕWÝ×W‡ %¨Õñ:ÿȐÑkn™"æ ¸¥Z<o-Ú5Ć4Ú[C¥œgÂö| ´4“´,·L fø¸ ·ÎF%DIó¾ì'˜" åÅr#ÈV¾"-J1šWçw™­ˆ¶wÔ>/{í6Î Éåýx ’$º Þ¡ËÉøšåþšŸ…a„Œ|iM‘;fd‡ v®Cr¶p ë×q¤Ð¾_8'Ä0Ê«a€Á&9džªà ®ppSúÿ˜dI›qËzÁ¤ô¦š™}·ÞÒ¥%Ÿ_ ½,è>ÌèåJX!yiOЪRßöI +&§UÓ½s¡ËÔQZ¥®¿`͑šNÒ_LhòˆAzï4âF·ÑÞóNEép<†C.µ&˜ 핤LFÒ*ѾRÿ¬R1î|lÄÐë·Ê$AfyмÙú”•ßEq?¦ð¨ßnqt|ȏ¹ëÖ_Ùçó´öµö©endstream +endobj +331 0 obj +778 +endobj +332 0 obj<>>>>>endobj +333 0 obj<>stream +xÚíUMoÚ@½ó+FœÂa]¯q1ä–ÒQ5- æÆecđ½ëì®ÛäßwÖÆ|ZU*T©‡Šž7ï͛§á©ÇÁ§‡(€á’¢÷.î½ù8A¼¦7£1‡8½ +=îÃt9_°÷˜£E6ͅ1ð­D-l¦ä ~$Xœ70DÞÈãìÀ©«+ÿ9ôýh5…ú„|ΌÍäJI‹’¶ÖªK͋±Xx +‰ [։¶r=ÞA|‡OÛ!·»Vy®~:îVUIZ× ¬ÕÙ}e8MìUYæ¦ ”B[Wb;çÔ Ýµãs,£FÞ'×øõÞ?¸ÙQ¸ZZÅ®ø«°•9|rS‰ ’?)L„‰sfgíÝý½f–P±AÛ¯‘‡/dӚåÛÖý£I ¤húI“f &µÒ¡Ç=òwËɇ^à8·Ìæs¸U)æ5× !m–P'•TJëHíoÌ*õ) ôµt͓áÒÂír7þ¿€€å݌ö¥›H”˜dk·•£Ìœd„ÕΦ$èL‰)•4xaLP¾""-×EYXÚ¤[4†ÖØåŸ±´¡SŠdÃçž8LÑ`Nóo¦.¸ uû«V‡`ìB°=7I‚¥eŸÕý¶CØÙ]Ó]#L-söÌ0Q£(?쑀€U`u…m°O&>9•ý.ñÇW‘{Ãþý£xÈöÿ&v§s¼5žßҒFî]“Ú@˜eŽ®¸q†:SW‡c>>>>>endobj +336 0 obj<>stream +xÚÍUMoÚ@½ó+Fœà°Ž×¸@¸Ñ¨©¨B àH­Äe³ÈFÆvv×júï;ë¯BÓVQ« +$Œç㽙y³ûÐáàӇÃ`è¾rßyuÎ.Cࢭ{5 Š{Ý\«Ô¢f…V]Øôègӟô£ûŽ,z¡sŠîd¢0µ0¿YG`Šâ´·ÃqX=eÌöy‚N?Õ²PJZ9Îʝßy~90ß÷ށÿ»—Þ‡¨ó¹ó£üs:endstream +endobj +337 0 obj +651 +endobj +338 0 obj<>>>>>endobj +339 0 obj<>stream +xÚíTMsÚ0½ûWìø6–ñØ$·4m2̔–sã¢Ú2¨cˎ$7í¿ïJ2fÚ—:Àì>½÷´ÏûêˆðC ‹a’BÑxïroü˜!WXI§äå͓lûÈ|š·üK¯™å_=q&¦y©©î̙RtÃîL9:Tó-¥©(©,A2ÕµBÙ ¦q˜ðó ‹’Öð‘ŠMu@8glÒ±Fè¯2ÿo&”\‘Ð#©þ0× —ÜÇ0á×ztÉË ÌWËÜ]ÿLÍêefe˜÷™ØÇ »ŸEM•: ‹};~‰K|).n‹\™&~Ÿ•ÕUaù¿ ¯Y‰›Ê“Ê7^ Œ“9@2‚Û%M#·$-fMW3C㦄šPÁ®=ÈâèWq’%álwl_µ¹÷ìýE4KØendstream +endobj +340 0 obj +571 +endobj +341 0 obj<>>>>>endobj +342 0 obj<>stream +xÚÍUMsÚ0½ó+v¸$ÌÔ2”$ܒ´É0“ZèL;ÃEØ VjË®$‡æßw%L ýÈäÒ ‡€V»ï½}»úÑbÐ¥?½ýÄyërÖ:¹îc0[ÒÉàìfÉñ,E¸ú2™7h‚ø(bÔP”¨¸…„ùq÷g¿Û½œw@¡©”ÔÀ³ Š%º¨«²,”Áw3¨”8Ò°,”?FõˆŠr؝ÙC« 녑­ËB\&ŠUŠjÞ íùÉõ9°¾ÇDçaßFöCFŸCŸñG…Úø{ ¯ ÚòZYV¬…\ÁJU©-lnŒ‹ÊP®<ƒL®¡äÊl˜TS¾Ú°¦ <¸›ØÆ[É.¶l,i¿ ¾ç¤ Ïà–ËUÅWè¸J¹â±!¦xÞ²h7ƒ˜‚5š¶»¹{ }ê «S·ŸÕÔÓW"*$õ%vH{! IÚ½ÎÔ +Œ&¸+Ì\­)æ\S¦"®r”&܃ڮ-g\ë65Ý<•Èà;>­ •Ì;/Q‹Izi`<™Æ÷··ß6ý ̵¥ÀåÛ¤SúŒðÃ:qZù^zƒbr€,¹0’WΑlxwñuÞy5,“ +ÝH .³5˜ULVù‚’“~T&åæÏÐj[a4ý²Huy¼lԃWËG žù$ÏíLNh<›ŸÝhԇäuZhÜsÄ#Ï*Ç7c@4… §úFÞ55¤‚dÙëÝîN ke!çM±t‘{E„)O`(›a] “E‡Ë’<¢t´·A7y»;$zi‡Xžð–Ê¿/M©7m©¡9×p‡ZӐ¿ä m¨Ãœ&EÕõì/öNîïì;ðÿÜIÑvR°+˜W7‚oŒvyü^a§¡íl>ÃM… ŠPWJY¯×Óa=äەT»ñ¬¶ë½§7lÐë{>Î0ÊË -nßv*IvjßÇà4êÚèÈÉÑ랇öQÿ·'ñã¬õ©õ Ц’endstream +endobj +343 0 obj +749 +endobj +344 0 obj<>>>>>endobj +345 0 obj<>stream +xÚ͕KsÚ0Çï|Š.™ÚÁ†â„[š¶™Ì$:ÓÎpö«‘eG’Còí»’íðHúÌ¥ÃÛÚÝß_ºë0 _QÃ1ÄyçÝ¢süñ‚)}Ÿ°Hz#?x ç_fsï7›½×0-Q1à Ù_|'“Am⅑?¶F‹ lŠÖ–½ÁÃh08_öA¡©”ÔÀ„€"CV¢ˆééØ=キ™CÊ’éŽèGm0'?6‚E ÀÁÐmàÀ€É2¾ÎP-û~HªF-â©?juÑá}ÊÏxW¡6/èjU¥…ņË5¬UQ•Úr3c_U†™"¾ª,ǘ†’)ÓJÛ¥êP“F@8®±.¬W&Û$Ãٓ{{–jõtø†Qþ˜€+&×[£“~ž1Åbƒ +æøÌ½•ÐÝòz1ÖhºÎr÷ƒ¬]{¢qÝÝS©!AÓ#©ä4Ǝtè>åõ &üËÙ ®‹…‹5ǜIÃcòTÄUŽÒø¨]ÁsNdË—פgÙ &×g_—ýeÿ%]1%]˜Î—Ó›³««om%4Åçz+œg[CË%«|EΉÒÕÅd̸2Ö͉É3®²L¼œÝ¢E3ø`+ŒþŠA©¬4”Š*¥šUŠLAù”QØd<Îjª_5­„‰·­‘… ¨²ÓnñqS¨„æí¯ÉÁ^ƒƒd¹ý “ãBí¼v³Ð|¤~Ød…ƃ.¸g¢r•À¶õI+·Ç鏣÷á²î”© "–îM½Pݓ5™•…L\?òԝ<º%ÌX+D¹Î 7It\Vä흣ƒ}á¹iÛÝ᳍ajµ¯X(³.Ú8¯ÚsCS­áµ¦‘~©´¡Ú2•4¹ÕÉk›ÃÞû?7PøŠ äí&¬În8q—ÐÏóê2WÊÓ,îÑR8à +âJ)ÛÛÍ4¤4EÈê!w—\Ó'MC{GÇ‘b㸞€Ë¼hyërSPæÐƒÈÞ^þäæE#r뎆Cûââó©ób§endstream +endobj +346 0 obj +772 +endobj +347 0 obj<>>>>>endobj +348 0 obj<>stream +xÚÍUMoÚ@½ó+Fœ©vXCL­MšŠª4)87.‹=6ù+»ë´ý÷YÛ ÔåR@ìμy3ïyÑKÀ8äw\ >Dƒ³›KSˆRº /DÉÉÄ!\Ýß­¼Eõ„Þçj·5jiUUžF”2!Ú/˜ú!'E[ÜË©úXŸŒ~LF£ëõ)tk@– c«žj­J n+¨4Etä.PS.£‚ðe%\žŠŠ±pѭʶ¨×§~K‹:™ô´.ýIß ¥¾f¶ÄǍ=ÒKßIZåyõ]•dºjjU +ÒZ­6eþÁ4u+L@¨¥¶b† ÛR³Žx¶´>1*ˆÙË`áý3<ǒ>ÏÁ_¥m´Ìá‹,³Ffȃ€«­Ô4CšÐ +ๅá _/¦`ƒvè2w/ÊÚË;èá«. $hbúI]ª ƎéØ>ÍuO‹®ýùÝ,ªsWk……,­Š ©Š›‚„õ÷¨;¡½F«!©M_dǓ\ᩄ9"c¡[ÉÂÉ:˜Û塚}ÆaôcSŠIBrÛâ~µŠþ$Þ/çäíú15Æ*e{G27é,;¿†²)6¨ßAͧ”íšôv5lfÀ¦ˆ°¨siñ7š;ÒÇFó¯=ÈgÞ¤œkHôú õÞÚ´„w'8XSW¥Á7n–ؚ¾Î›ÖfeÉÜh 9û˜øÆ’–R'´¥m=>ᜢÍÙ÷êÿ¹ˆÁñìæ¢QŒÏé9Šs†prÀœ\ŠÚNšp Ó9[LùyìMƒG7ú€èÀèoþ@>Fƒoƒ_²Ü“endstream +endobj +349 0 obj +613 +endobj +350 0 obj<>>>>>endobj +351 0 obj<>stream +xÚ­VMoã6½çW ÔK‚ZöZqb'EQìæ£ ÐvÝØöà -Žc®%RKRvüï;$%ÙÖz³i±0`Hâ gÞãã#¿œôáýú0LàüÒüäÃô¤wÉ;˜.här8‚)?½€÷Öj1/-š³ég +@¿BâdÔM\ÐÍÓx…VkÁÑ@ÎäðÅ¢4BI`M>X¦, +¥-äefE‘!p\‹MÆã[XˆÌ=Ë$gšÃg5wß,júZh!ý“냪÷ÏCuŠ­Ç ͘1hº¡Õ+è«VϓîÀãéöá֗|ذ{颫È=L#h´¥–Èa¾»DpðãßÑÆ!܀*P3ëÁSo(ËܽÓwÍÔkÔ;5¤«†¢ Ì{º`vj·&°Â-•á³³#|¸Ôé^À˜Š…pkLAa”òŠ?2 s%±¦`¡²Lm„|¾võH„qrzŒœ"ˆfåeQ!J«¦âawDQð,¹ÂaÇn¬a4âBcjÃtÓ´HË iÖä±_"M° 8³Btv -µFi³-”†È]Pü ½k%EJZ|¸»»‹ûÉhÐqàZkø4ùÐÒÍfŽõ^«ý†‹Ð[hÍè™Dsе+ñÿÙ©´毅–*)‰3RpH"%Ò¶° ÞÅD¥+$Šþ˜NÇÄĘþþßv¥“¿>ônî'-Bݾ‘ˆZ¶Á`âAv£“nR+PȅrÊ%£™ö“áìì-ºõYÇdË`Y’qÅw “Ñ +>SžI)Ø=Úfš`÷¹ ѸVÓØYÚOýèõmw^w‘³Ƥ›8Wœ²ÿ3 +Ê×{ùÇñT{,YZú–Cª`UfݸF%×ÖºU2 0rîü.<,ö^ÝÂ×rçŠjKeŸo•§,÷'ö½ƒªX&¤·ŽVU·Q)WRmäwøÔü”Z©ôÿ2]ðqK)¾”; ž³}Ü4,µ%íBÊɓÕ>3~Œc’“GzJh_g%¶r[ûm“laÙ:eæ{.«sð±×½‚ÙeϪž{“,ÇèG˜ê[Êçh—Š_÷(nW¼›%ÒéÚ°¥¼OQmؑSYTšy"pV94ˆœ®9=y…ý «ý>¨v£!÷âosVò_ýâþL@„ÝV/ :øÂcDä+ˆp†ú³ÈÛ<ᝠkڞJr4H{‡ÿÎýæ"à§1$V+¬”u¶u»©¾b„Ê¡¯ªöÁ!ÝF(é3-Z„k”‘·ûHq^pˆŽMMšQ ÒËìôÓÇ¿{Ÿ>ÞßS´–lE=ÍÎڗºÈuÐ^jË}œNz7ÓI+ÕGq«¹Ñ.èvúØ»<ÓÅEÒ½¦‹áUèÅá{z|8¸÷}uçó©¬Ì3ž³‘—yXÚp^·îj_yBsYrùs4Ö¾žEO¯›]«lww$°­ŽÏXƒtT#už1V.Ùºô†ƒzÇ'îÃÝô䟓âóÀÏendstream +endobj +352 0 obj +1167 +endobj +353 0 obj<>>>>>endobj +354 0 obj<>stream +xڕVßOãF~Ï_1ÊTqb;pT'õ¸ö®T­JÛÜCExØØì²Þuwׄü÷Ùµ“` w‰<¿¿™ùÆÿˆé/éŒ?Y5¸Z &ŸÎ I`±æG³‹9,ò“¡B·Ñæa, +„Ë £Æ”°)¥„‚^ƒ#ÉZ›êtñÏ †(™ŽSo\¡+t~9™Ü6^ÖÂZr˜ÿpWhëøÑíe­»›Ü´º1Þ G°)Ð {¨Ä– çj’ ˚¾ú±d³ÌV+ú҆~éìÝJåóËcP9(«ZbE¿„+µ³›É§¬-<š/ ÏØå2Í!È;`X§ôŸäŒÇ—?¯Á kŒÂV[øøåæ¯è3ºèG” (i%·iŠÙ&ÓÆåpRêM0'¬{uY)lA~–h—§c¸¦R,458ê“%—'êZ–™¯%"Ͻ”]›R8„ÊA“Äô╊ì© Š=”ê(ÜyP͸5êz á&¨Gœ3åªqTÇ݁ÔÊ-‚%[èÆ„Õz‰uƒ‡Zò[טï‹<”6Ö1öÖiCq\òP&] +ôˆ||%$õÇõ¡¯Ñ°?Ÿ˜BÌÙKC¶Êµ·Ãó’¹Z›hšHÎÉÇ/z ¤ycÔ÷ì¬Î؊Nãñ¬µ'°’"{¨¥vÔó•Ö…Zž>C†~Þ¿×]°5fåºäù+» ?ßDŸ¤à×¥$‘-t#sÞ,ZŒ%®Í Asêýҏ‡,”Uñ½3 .OyÝËSâQKmB£m!rÔf“w»ÈñáÐÏZH‹<ՁcÖ¢‘…l¨©¶ßëŽ_€˜¾ÛOz+SÞN¡åÍá&ߣYžÄ—i/OÃ¹·| ON_Óä&¿½jK‚a?h³W7ŽË¥!ÊÕ1|è©'qÜ_= ŠçW2ý1B”,ϱÛ“mHpà‘=÷’BÈõ^ð:z¨¿¯WûLHÁS%ÝÉÇ­P#øMÜ3GŽàodzù¨W~$¼g{Ðñu£2¿tÃõò䉿áýa­“^™”|OÃã-œò5•zÖ¿äòì+ÝëŒÞjjªmáßiRÕT)5”t=áùúÒð©]•W}Ù»äxAgÕ%ã¶5¦´hMu¼Rþ†" +aDæ)´öl–GŠøÏ;h;˜Ä#HÒþ%åF¡ ³»™de›š¯4æoÙñêÏ)÷?H­Ó>FiÔ9› ړW¸dä´jÉ^bÆ{Ya^ +J¡u¿ç¯t)Â>[Kd/Û@/ˆlñÀçQ.ƒo`¯܋ªÏŸ¶æ«ÔÌޚ÷R •ñ’P[ÃÆÒ ”æ ‹Y*d*>p¡úçqï¥ã«v¬È6eÛÀSqxÚí˜db î±4æÙÑâp®|¤ ô ¾^äCjëæî¢$™'tCgiPõïpý읏¼¾¹a»(¨Gó4fítƧç<¯ñ7\ñŸƒ?ÿÛF–2endstream +endobj +355 0 obj +1143 +endobj +356 0 obj<>>>>>endobj +357 0 obj<>stream +xÚ½VMoã6½ûW |R€H‘dÇvôÐ-ÚlFÓÆzЅ–(‹[‰Ô’Týñ!¥ØV½Ùî¡E ö ç½7_äçI1þ$°La¶€¼™|ØLn~šC’À¦DËbµ„M<°¦a °¶­/À*°‡_yq šsy Lð¡î8¼0ük ”†ºk„d2çP⧝f“³šƒêlÛÙì +:#äÎÅ*;™[¡äÕæÓ$†0™E)AOË,xEÇïà•,DnEÜf+´Ï£[òɂ$Žã›±Ì®7¯a¾Œ{ÇiäwÌÉ®n£„é]4'óm”FK¨PCiùŽë,“U|¿ÙÕ84²L]z6HŸN1kµØv–ƒiy.Ji`«µ“]+ËH"ì+.¡ÕˆAêEÃv¨_ÔÜD@± +^²®¶>“”öxÄ;>缂OjnE]S¸,°üÕfÁúûߏœcÎYðÃoOϐ`v¨r•ØU¨ö‚Â…Ç!^§(G­­V/¢pR ¸gŒQ¹`è²¶B3žw}0Äh;Ý*ƒªßUwçp+Ua‡ «Qàü°Wº€¿@²†ÿWRO /W–ÀІGð(…pÕí‡ÃXDcÈòñéé†ÀÖÄÙ\‘5»éÚVikœË0Hªôó¡tӏï×ë©Óáÿ¿~ž¢ÙžÙ᜗kÍá#µ’˜ß½È+Xs&aC~Yð°ÞàÐÌyR©ìyâ éÖ +GÛãü©$åÄ2v䀍nˆ³?—wZsiG´È÷ÚÙ©kðPÅQ…¯}+©Õ +vx¿w’ØUÒTœ[ZI‰á–òyhù þŸ.ê±/uf pì^Á–Iɵ_¾œLs¿"0q[ŽÕç—•ýÜ,ùêjn¸~áÅ(~ +QëT"Ì +aؖ‚÷HÃöùÂÆ1‹¡´Gáàù¦'êÝXu%ëƒw ×ù‹ÃWôD,G*{@ß?˜š~ (çaJ¡½(ƒv#23L¢v›ö˜’éŒ>ÑÚÓ4ÏýšÊ±>'“·}*ýu‡&}<‰Tݹe‰¥â’:³Gw[„GÈ ÎpºŒbüIpAáiŸ¥Ûa±zŒñŠr€/LJ‹c1}ڎ›xS‰Ó‘Åš³"¤ÆþJ?¤P·‚î`\1)JëšwŸ äü¥‚áÙ-f ‹·%~×â!±rçÏwéö¯‡Ÿiòlõvw,\C­hxFùì·.º÷—ÎP€¬‚E¯xÕóO–´óU´ @îƒÇ¦­yƒý9ã­GçBï.Óø_?±æË9¾iœº¤/~ÜL~™ü ÇLûendstream +endobj +358 0 obj +1065 +endobj +359 0 obj<>>>>>endobj +360 0 obj<>stream +xÚ͗MoÛ0 †ïùDN 0»¶óÝÛVì£ÀdX쐋jӉ6Ùre%Y÷ëGIv›¤óZ§9 ÐÀÉ÷!iQ¹í„Ð_ƒ±ùÄYçÝ¢sñaá)­Œ§ô%éüÈP°z7Rk™Á²Çs+TË^pùåíeÙï/~’õÂÐY{ÑÄX/Öx`Ê´Vüf£Êcžr,AӞj9cjÅs O!)FI¡&Qýo7L”¤˜çñzÙ÷Á8O0e¡aËč +üÈçÎw‚[“Œõ]Éc&ª ¾SüÀëE3ÿxèd LõI¼Ö°‰Ö.¾ÝòI¬#'YñÕú4XgÙDëV_îØ‰.ÑÀê»#ø…w;©’§IÑ¿8wk¯í’)¡P„eX¤\ ã)7E!•ƤWS]&D÷ tq‹9ýgyrٕIÒmH‰5~‚wâ¤kYœT\c×TZ³öz +;…óOôº5hm×ZK¦àvoÆc%3Ô¨LЊ-;ÏWðiî}ü|AYRÛ(-ù#È£<„Aô< Á­gÊÙÿ¡g”ê’k.óvÝ\5žQ2fvƒLgÔŽè‰YÎ0á̕3•BȝÁ®; ÛÝGÄ +c¹ÊùL.¶ ÒFȋÆ+F*:ÔÞ®ìsÝ ª¤˜.%ö*›5u\YzJèäw'p֬݋£f~tnß䇘N½ÃLß¿”¡ZÇ©±ÍDh¼"·s„¢¿$²=Û‡v‡úÈ)Þóè÷2nÁc©rê‡3ixföD¸œO…»µoÁêît6íÊQE?sE*%íŠRIyA]êC֋¦¤ãࠍ( +¾?XÂç 2i¼a)Ŧ>cY¾wÌÚiÊ#Î‚ Ìðl{ŽŽ/Ày,6 uʎÓÄ2[­s© Œ¦ÀSÈå¾ +ž§ReîÔ'×l˸`7t}q€Ó +0œ„~ãÙÈ%®¾Ï¿ÁuV̨3ï‡Æõ|nì<·Ý›D6ÙÑÔ<Cä²ßâ÷ÅûEçkç/™¹ÏDendstream +endobj +361 0 obj +783 +endobj +362 0 obj<>>>>>endobj +363 0 obj<>stream +xڝ–ÛnÛ8†ïýƒ V%Ù±“{Ñî¶@€máE½½ò #RŠTI*Þ¼}gDI–1A`›š‡Cý%ã_‹¦sÈÊѧÕèý—{Hf°ÊñÉü¿ðñm”Fi•Þ¿TVjëñ£1J0½¾¹YýDÑ ’$ˆ&é‚D«Bì)˜÷V>Ö^€«D&s)l á aÁ‹ÿ<äRá’+L­8<’e‚ÃVú>`?,0ÍáI¼lå£&Ó(¥¸…Ü +ÿ½ÔLsÂÞÖb}Æ6>MIq.½4š)ȍ-1ÇcUΔCYT9«•‡g¦jÒAó4 + và&é}´C—‚c¾¶Œ"¡s*k#ìzHãx}sá@yŠ âƒÌ(,i`ˆXuÀGÕȒmD ÁÇ¡É!‰c¬â¡&êúAQ(ՑñmÜpǤ R´ISy³è·2À\È&¯Qnåéå³P/gèaøWØMÁeL…]éÁ%Pø*¹Vw[÷  +íÖ¦ÞS¡ðv_)¸dD1TÐFa¾ÑïüwýKOÒ·ä‚,*4xG‰Ë:+è³2ÎÉGÔl¡8â²Úáºè öIȵîRâ}:ˆOs2ÏÂZÉ[NU%ÏdûÞÎoÝ ¶–UWŽŠÆôҌPsÄD÷f©*ܗõ˜¾ ¸6¾[lÏos*põgd7€Î4*yޕ»hӟ¦]¹SX.ÿ‚]þîˆÌ4Žæ­i„£´âÝD5QLojÚÖõ¸]ú»]¹<[O¹8×뽁Йám×ÓʺéËõ˜~v‘Kýu€kÐzOMÓñ!ߏÔ4ޓ6[MûQkDŠ›ÇÉHáß`ÈÏz£¤+psК9W——›Šò ºKöÔdŒ»†Ã ]¼2 zÉ9<%ÓuÎ2„‰ÖÈæú±-˜¯C‹KµTö`­Ôžý1:ô1 ‚×£±³ÁìHWâåµkZßdöô•âÚ}ºÌvڃšàDŸ”† õ?(ÄWñ¦Û#˜k,åtcØÕ ×tdØù>Èuôc~%uÛù{a¬?ΛØÒþ4^ÇW•ËÄgí).Ãá/ÅzœÞÞ^ÁYï¿O·«$àÔí fq¨ã½¦]ÈÝŐpiñz3¶½¥ñMhˎޫœb®À4߇ÓÚ‰^PÇ»´÷‚i´Ußµé'‹gÞ|>%?ðç¿ËïðPVJà-æû7‘‡å’T“`>>>>>endobj +366 0 obj<>stream +xÚ͗Moã6†ïþƒ=9ÀZ%Y–{ۏ¶È¡€Ûu|¡$*æš"µ"¯þøIÅñ—bèM‰^ržyg†´¿„øM NíOQ>.G?ý:2ƒe…OҌÀ²Oƒ-—†µðÁ˜–çaúaùՋ/žÄaöò€ÀW•O6Ákn`5¶‹ŸX»zð«R ¤_ÍìšÕøÓ_‹/@p!•%¬ùÓúU¨SdAýr͎"Ð,Ð +xřƒšš~çuWƒìêéU.T¾3î95(ØAΠq镐ï€B§Yûކƀ$"ËBt%—OS)q«Š ¦° %«h' >>>>>endobj +369 0 obj<>stream +xÚŖÛnã6†ïýs· PÉ"­“/Ó`³0P`ӍsçY¢m¶’¨©f·O¿3:XòY +4‚˜úgøñÎÈß' üep˜ùg“ß—“é‹ ŒÁržcà‡,“ç‡C?Ìq—M˜3Ã8\~Žr(ª<ށªLQ›ž~^NÛÁÌû?ß¾€R² ´CÀhwÛJogÄÌc{5}Û¨±ó=|Ú£ñ3h±úG”#Ѽ9m3­V_Dsi½GsÏ ­ežŒ$sÛOV«/’ñŸödá2­J3’Œ3Ü`4Y­¾H愸´'ËvJ¶‹ò$‰DFP`¼¿Yˆm”NŸÜ[°'̱°µú¬Î{T~uSªlHJà‹·¯Öóô‰ß öB~GÇ4ê‹Ôþ|Ø1îMî4*·Ø?Góú³;Ú¨Q_äÅ¿ƒ6 +¯ðVZ”V"62I ¯å¿BߢuÝ;Z«Q_¤±AkÑý=¤]h@^™©Œ¥Õ"ãt²¶"edD²z„8ôMfîÝÑtú óôeÌ¥1ï€;¯¯…g»¨*J™ä2? ae‘þQé"¯²Õ#ÑM_üöá€Å +^=<¿¿¾³3ÜîD٩݁Úo\Zîę­"cJ¹®Œ©©¨ µJ¼SJïÕTÙ%4|H³Ãû)€6·¾c½v*¤ ÍqK6k&Ë^óÜF«‚œ—*×6ÏZŒC‡º›$‘Giú“@Ìó—ÎŒQQ•RbÄÑæìSSØ¡ïŸ7fó–æ{%´‘ùÖªïseÂÂLêQVL £6@«ø«Çÿ´WwïšJM&¥) BbM3ÂÔÖudB Úγ}áì#o>cë9ƒEïwReÿ,ÖE`}H$Zï+÷à*äÊÀZ™Ýuãë[ü?¾Ÿœï–ítÔëÖyÞî·þôJŒô>h?ã÷´Ý +uGÂS—RŸlÖ¾ +0ÍÍD¶nyôÕ +¹Ç"Ç¢ûcèBÄr#qMDô…vsÐï¤îź{ÜäêgÓéÔiGZMYë4±*K¡ •'º+šÖE*28‡¹­ªÖæÚ]¦Q? Ú;ƒŸÆ8r¸Ó CP<ΏnXŸt=%}ÿ¶¸ÓŽ£²µ~„í±X@Íçûíðú½ |éÖ©êaOù¯¯g5r+àÎ}/@7 ¹QÍXû¾þsò eã²*endstream +endobj +370 0 obj +914 +endobj +371 0 obj<>>>>>endobj +372 0 obj<>stream +xÚ-‹± „wžâÆvùÁ¶ÎMºaÄ­K£4© +Ŋƒo¯¨¹._¾»3‚ü„ ëܓgkË»ˆ`PC‚Ð( {.°9šZoλú4NӀ֘Ò^ÿÉüok•¡–RTø‚J,E8!¹™§WtÜ÷+º"ož¾+óikٞ½˜¤(Ãendstream +endobj +373 0 obj +136 +endobj +374 0 obj<>>>>>endobj +375 0 obj<>stream +xڝ•QsÚ0 ÇßùzÜH`ÀÛ4´éAë]Ò»½G¤ŽÍlSÆ>ý”À±önqéŽG"ñ“þ²¤üìÅpIŸ&ŽAÔ½ë¢w1û +ƒK(VdO¦P”Ÿ®àVç¸Ý.~´ñäàÐŽ¢AëÅP ­ÝÁc q|ôL¢qã‘,££…âõãáñÏ L½Ùz´ ¸®¶¼Âè-§ÿÚ}Ã-W +U70G]J]±`Q |inJî9ÔÆ"øg®IõRzàt—u8 Ü`({£±¿ãûFE½ÕRp/v (ŒFKô;D ~g`cMeyíBáZÉÿKÝ49#ÖèCª(ÝV•¦ô]w¨‹Þ¶Dc8ˆF‡¦À•°Fï}q•'YÈ£¦j:¯Üs]r[BbJ„‰Ï4}×m:ô›º§I©Â€èä‰åÝ¡H¨§‡ì;0+µoêšïÇ:ÀLóä‚uCS–?>ü#ù6Z ϊw&Ba¹v+lhÆaT€vÇú·ónÞîzßg\¬›Do-ßKÏסmk_ˆ´@zRÛ^+ZœVœÚÂÒ¶¦Ó Mïô5öËè¸%ß¼‚G“Q4¥%J†á°y½o½?°E#Æendstream +endobj +376 0 obj +596 +endobj +377 0 obj<>>>>>endobj +378 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS047Ô3T072PIÑPp VðÌ-ÈIÍMÍ+I,ÉÌÏSÈOSð Ð Éâ҅(օª66 šë)€Üsò‹‹‹*A®!\\H¥endstream +endobj +379 0 obj +114 +endobj +380 0 obj<>>>/Annots 89 0 R>>endobj +381 0 obj<>stream +xÚ͛ÏRä8Æï<…»ªúcËǙî퉞K³À<M›]&(` z&öíWRfZ)S8«&¢ +è@òô9ý¥$‹?N iã?hzÓØ®¹^Ÿü|yòáóИ¶¹¼iÀM×»æòû?.¯¾ÝÍÃMóñá~3ÞožÿyùûÉ¿.OÚU é¤O翤FÓ¹!~^7aeèû»æ"±gݟþÓ|øì€ôÓâe¾M? šWá¸n¬_…šž£È¸¸~xÆø&ÿÇêÝÀ«£¶]Ò4wÝx³òÔ aøìHÂx»Ø9dW : +È:^ II‰¤8¡¾|wüöæöújsûpŸ ¾‘w¤«¦1«nÒ.7h I1cc;+f4ňúUWs(L¤‹ÿ=oÆõB—ë£ü¦_‘ãDûúçøôçíøWÂ9X ïBxMñvX¹IñÜŠC»r¨¸Õ'´)Ÿ+ÆõéáúÇ:¦éë<‰ˆ@çâ× +H˜XÉnbn¼±ì°h¹>ØÉrñûÉŠÁúGf– –Q~ˆùW±0šçãÍø4Þ_¹Dîß¹ÏÚå„õÝPìÛìÕ÷-z¢Q핉ÁÄ/ÃLúøÛÙÅ )WǤõmº%’…qfñS0u×½ímÑT÷]1fl›ð¾G4ª13'´ÑQ*…‰ôuóßñiAìryòådŒâc±ù 0ïâ °Ë6eØ&ò÷Ûl¦R‡b£ ˜·IcIÃ(Q*#uïD¦¥¯$-ôè9µrc«U@~$­nÄëSù©xÆIØÙÙëqéºRe«8Μßοä„Íóww'4é[+\:7„_´nE’«~AtOÉ¡°Ûݛ •f®fQœX‹7P^&'©žV,î@°¯ãS6y4Ÿ>úқÞK¿è:®ïó¤+Ù~¿Åu\pâå–]‡a]ªy £D©Ê·õ]ûN¿œù®sèµi ØØf:®óhºNµ&!v­ˆ&ÒÙÓíýæôׇo¯ó"%¯™)NÀéÎÐÌÚ½ùy]ûÞ$í= ±¦õ06ØXcÂyÖ{Iqq)*äjÅw\"¯ïç¿w08WÿãÇø¼I4kßfý¨)lûl|(Cn…m@ÓKMc"‘Eq‚í®2ƒK…$rBžÏÑoFÊk8ºÐAñãÊl¥z:ãqZëÔêÉh}¾QœPŸÆ«Í¨ˆ, XùfHî@ÌÚ=ì[¾ $6@.V˜{¹! U¼•Ñ̓H87¨P'ØN¢ HÊlŸüY"¹1¥ƒ¸7ØúST¶CÀR–„ÀFQÙ—D£Ú“püŠâÛ]å 9¤½» +ɈYùG{ôÌ–ÝÃÆ,™–=Ø(îay‡¶¡Çp01¥wèbÌÞ|úÓfótûíÇf|^’įùkŽ˜;wãO +%•{(•"•{ÕЪ†Á¤$ˆ©Q'Ø^Z غ1¦Mù+ÑÜÁpI,Æq­¡UÔõ!— 7„ºyÓÔU‚H4^‰¢8Áþ†º„6&­m*4w öÌ0.ð‚¼hΗ]l‹pW;§™qÒ&}[ƒ(N¨´>?ý%*üi¼¹úq·´û/P鮅98v(ܹMyÏ +@IckD½Ë ‘ÆÖr½sºI) bkÅ ¶‡Ò•’Ø&‹`î`WæåÜâð¯Tqa(«=lqMËÒªA®aQ{ KXcÓ_a©rgÞpè 兠mÅëklkh;®k^³â@|vm ¢xW¶î²®y¡7>-N ++ݯaNæÝló zGö³œ¾f0¥Äa£¤¯,—8¯z“’ ¾FQœ`ûH-XÉüôO9Œ,W8¹uqø„ªn?”õ6„º¡å +çU{` X¢0ΰýÕ%²±í´"SFW‡ö^P^š®+[œØ(aºž«Z§XsRɇDñ^Ô´Ÿ¾ge—gPÀyöP¹C¿m‹óøó«d±·¥ÄaCd±§ît‡ ž +Dq·§ÎÄs‡ +ËܛÌ4YíPÖnزº–k\§›‘h¸…q'ì%-qöP©“=PÞü#N +`C˜ƒé¹¬õš9|z¹V(ދ¢öi¼7ãâ +ZÚééçlîÐoÛĄ£žYP³¬(q¹!²—¸^·"A~ÿS¡(îD‰ÛYkAK‰œ¦›;¸—{—wbUܶ-+7lq[à×ëA$­DQD•ÛS\b›üàWlî[¶,á ¯ò4‡€ Že`£8D476(þÀ,è†âõêâãÝÕóóòîdñÔ¡Âr‡ð&ÝrúBoK…ÃFI_èW¸ z“°êT(лվJ O*0wp/÷&2}ÐÄíÚ²rÆ·.qAõ&р%Šâ0[¹í*.qúP¹lݚ<øôA9>®/;“ØæàøäÉjÐì8`ûØ·Q<¬ê9oVvAWJ7 æXî¶ïLý](¯òÁºRá°!²ØNÇSÝ"ˆ!mV(ŠûÙ:NÓZ€bCšŒUXîà_îLú£¼ŽSÅ5â$ +6„¸f’V5âЀÍü$ +¡ö– Æ¤™WåÛ^s>ƒA9-žððajshËé“vÁ‚¥Ù¾©I>’œ‘iÊ +.,f\î¶nMõ2(¯6>5’rapUy¦Ã'Ð.ƒ¸åð‰ÂþåNÓ¹ Ru3Ñr+.†ý¶MÉ篦j 3yä¡>`¦ó%Ð.y‚¸˜U•$ +›—‹µT%nÚlèj.†Í–ÍÈCÎ@9èÐáyüDw¡Ú…즣$Š|°ÄD'` úëõõø˜ß/úÀ„IwÈϘ¶í>ÂqXjùêé˜FÎ)ï« +æÙ@÷æä‡Rr(Üí)páàÎ9ÔP ¿xüÍÁSjz::å‘Gíêó"n:. ?ÿLÊC•$ +¹å¸»¦„5ùàd…Űٲ߇=L˜,æùøûx­ŠY0陓ÂÃÛï/²¼eíô·ÞNªŸBˆN7Ð{¨&ÿÅ—õãÝ8ýõZúcó/ggù)ƒ´ÇwÚã‹í[’èß'ÿ5kÙendstream +endobj +382 0 obj +2378 +endobj +383 0 obj<>>>/Annots 137 0 R>>endobj +384 0 obj<>stream +xÚ͜[s·Çßý)øh?Æu±ð[יtš©j«3}ð %­dÚ¼E\%ÍL?|q98Xڀ45©Ä±gÜý{þ¸1¿¾à3æ~ñ™ìü¿×›¹|ñú 6»¼qmgQ³Ë›——Ë«õ0ÛÝÎ~ÜmÇa;^]~~ñ×ËlÁÁÿàþÇûŸfF,جSÖýÜÌ8 ¥õìƒÇO®¸¿›½~§fœû4.V3ÿyjÁłϾù)ì>ƊEW~ Dڏÿºø0?|®ÇùßvW‡ +—63!úô0ȍ‘û~øõa8Œž&¥û¸ð—‹“ý#XCu©}V=”à¶½²²seÔV4µEX|` +Ãà=Y] ©fB† ¿ûÝö0x â uR+êºûqê +o›™îSîÚ½:®ŕ߀\ë”UÆ??%é>“‚¬†qþv¸]>¬ÇЬäŒO±äì‡ûå¸Úmƒ®b!OÝqKy£3ëZ:õâP"½˜³…B¡‘!f3ºìÅÈ{‚Ü–Þ¦ÆýY’-á–9¢?yŽh¨«mçžՍ¥¬®¶Æ•QÝfŽH0›Ñ…º‰÷Tu‘ìsŸ-áâ´ ¸¢lȺ—Á4Â; 9?è;­jdÄp-¦—€äü)ÈùÛêz¨¥\‚ñ ÕM¡.©e^ }ƼÐ췝%ÞK¤ß–¼Mµ³B‚…~UÀ yOš°|¿õI¸$Ç$Ó¼pb¡…hh«»èñÙC‰h«M²6õˆœ€°ø¸††ÜS´²½K­%€\dvÚ~\7¦÷"©”B¤¥’›éVbw#¡ É'$%U/.ÞÖ$%Çìõ”é2ô93CY6z°dÔÕB‰ô`÷2¢«éGd„9Qd ÃN\íZ00Ÿ +,p4µ³¥†G‰Ë ™ÌÅ—÷IÚvr@T|`ŠÂ€þéÂ4ŽÄJ(ôçÎ + ]cf`2xE|»Cd¦’£u­Ì ÿNw%Ég$QÙý6øYZ=3t™éœ01°Óل=wnPõî«,#îK¹û*˓»uíܐ`N[Â0€w{„Úä»0wýµÄBGk˹AxFü8y!ÓµX"òš>\×Î šÂ0 '6÷hy×sJ,ô8[Ë9BÚÓ÷劺Ìߪæ!µõþÑÃÃm¿~§aÍÌרŒòå.Ût.ó¬X?ŒãýêêaÂúž2g~•Ÿ*ž®'X%ML°Â?r($ùpÉÑ¥Z寓!“UÇâÚ£sÝ¥ B5âˆ¶Ò ùz×Ù%›Ò h“VñËÏß.ñc^*¤4ë×òb¤¡c:s’×D'û±ž¢ `7Aõùõzy¨Îˆ5…:©M Å ~|9þ±j©‹ bŽ™Ü%ðËðÇï»û›¯`YóÔkB͖âBˆÐHnFÎJÔ „Þ,¿ óåöf¾ÙÝ ëoÃ)ÏÑ;¿ˆQÐ]@†Mps’quSÙ0EeC(Û§T£Zº‡+¿¸P€ ž&š‡ûUmØùÑOÄH2%ä½ûëgÉï-?•†g?…qøM‡ŠЧaݪ¶zqœ©K àk |©™.‰˜@1 €¶ËÍP¶½ýÞã¨f Kz:%–H+–-˜³Ö&H‚…å­Èó-}ø4 㡵Š–˜}HT3 Ó¹Âaw·õ=•ˆ‚{«)‰1‰~,&k›Ð̶ÄAâÚݐ <ÐÏäK` @`­#’‹7a„(§¨€¨£®Ø±ÿw®Ùõ=¼K¤ë Cf÷ÍíM„ùEl^Â0x¾ëíÜÜsµ]Ž.—»„sçþñ+bè& Qdù`p r,§ü~îÙ–K²±KDX®ò(„776Œûç-`¼u}”/ˆõ*-‰·&Bá'Búèî €d*ôãóf›1z(–H›1žG4µcÚôro·aH͎Î%Þ~y7̯vã¸ÛÔì6c\÷W!©PàGkì yܸó„£tÑ׿== KYaÞgŸS-}*,„( 蓺ëávl-¶#Ð'>B@ÿ|Ê>R_#ÉH"–ˆ¾F‘‘„n*Œ0íGð €4K‰õ‘DŸ˜BÝ ¨E]æþÔg¯š"wôHP,‘;N<³kŠŒ0¥¦0 ^Ù ®ê+µ„htºY²RKˆíüN~¬fŽnÑèŒ+v¦¥=Ïjd³±=`K¤±TO|Ø4 aªKè²±kÜíëI'ߞ~JRU—yß|N/rSa©ˆkÆQXjâš}Sa„)°ª€aðöÃö÷ÕÍø©¦pfD…Õ„ºa™æ [M•§Î)xéœ"kl›#*c-PÞVþdf}Ngžñ›j%Ä#ÓMĵÈéíA€8>ÃδùÑl'f¨3S:0볋æ\>Á¸[0 Þ¾>îϗûý%ï % ú#ëå“η©[J[E\ؖ'ĬÎ,šóV$i㒠`ûûat=øÞ‰Sæ$ˆ—ÚÏ8 b¬ÖŠMiaë +÷œXg_žìêَnN`‘쌒 `‡åøOƒ×WwE8îRcµ¨ïEwö,{-»ž8gWžèêlöMќm"IvTìp½l¬g€W×oý´Xm¿²ÍÉV9Û!ӖÂZÓ/Ÿ”'»tNªý½´È¡åOê÷ûemÀ—¯õ«¾ as”žg+Ó6ŽG“Ó\ª<Ì¥ÒY.Ù: G¹üÐLMOr!æââmå Wº4ÚdɉµâO|ú1XX¢Ÿì£ÑÉæñ+Àxÿ76ŒÁåö7ómÈÃëùz¹½{p3™Úw+l65mA†j›—døïÀMÊïk{QÏ|³,ý¯Bz8·?ç¬ó©Í–ëÌ!döóf¿6ÃvŒ´»ý|qáQs?ðä³¹‰':V+ÐãŸ/þ+¦0Òendstream +endobj +385 0 obj +2916 +endobj +386 0 obj<>>>/Annots 156 0 R>>endobj +387 0 obj<>stream +xÚ͙MoÛF†ïú<Ú1\r—Gרƒ +¸ +䠋3.cQ’I +©þøÎìΈ³‚ÅuÐX©Þìð!ùÎì|HO3%ðOEEeyô¹ý²˜½»©¢4‰_"eª(/t´¸¿X¬îÖu´ý]o7C½úËÅ×Ù¯‹Y'@À_ +ýñPq庂ßmTåqI‹uôéGtÑ»)…÷ƒ§ÈM‚·3q§ÑÉ{l)îH7qûµÛÝÏÛÕc}š&€«²¸ðq`À´åÅPÿ=,/TZ,/——È„«‹ÈnÆgùI«€ö™·gíí‚ÞõÍðIá,¤0‘ÒD£hŸ`¬ñ|µ?¶÷õú4Y :ÍÄ~IqWo¥xPÝ4óƒºv!ÔM3X“º:¤.‘(ü$Šö †ênVm8‚ ˆm3oy´åEj +jÌÙ"xBà̾ERtmdR » —€ •«$ÖNà yÅ¥mTÈ$Çm3é¶k £u§iÎJ«cœÛgÜÕ0tÍÝ~¨m†Ô +$?cn8õ“%ÓQm âRŽj·£ÚT¬è± +D5“¨œù(Ú'Ø×íÝüq¾nÚf˜lAÁԜÀý=&tyÎ|¨;ÖYqÞÔÖ¹ÌÆºèBç’C;Xû˜£òbÙѾfw«‡:(³À`þÀÓåAÙ@¿$2ºãL"õÍ«±ö¹…зH¸öé`íc’*J|s‰rû CŸöÛa5ßÕ]³½ŸPY @e•£ÊLLþI:56ùXÝBhl +®€:X™¤ì‰öP´O0Ô¸ÿ«®‡~Þïw»m7ÔS: èœb‡áÁÙ àz¨úz€ÞötÏ"@4ØñyD6 âð¼«'LW•UG„{¬Ÿ¿m»‰7–ˆ6ʒú#X 5ÿ9 ’—(Ç.Ʊ¡\#ñÛÕ'n$òNÖwi0Ütf+¯‹»á¦õ¡HÊè× 7†í\K0G7NÕ&-O•úøùÀ`d.mPLäu Àì`uöpd@Àz³oæiq¦tU–ˆ.Â.„«25vyÈUDR¥@‰¢}‚IWÁÒ?N <²P`¬™ ÷IN2éñ£²…ÇÊ·óW¦NR…hAìB8I +drqR`¤Jí[TW?íë~h6ó}ŽÂŒ1_­×ÛoS)\BávDÞ-Ø |eÈk©ÁlíñÈ ³š8Mÿ§)è“$m‹]Ÿ$zl[ʐWˆ”f¶‡“(Ú'؋~¹¯7ͤ[X¥ä=Ø@ǯuŒ` c’ƒL$"þp×L:Ǥ¦ŽœR·R])îwL` eŽ=méu)ӔÂOK<íîz½êû‰¬(®ÇÒhŽil@¸£ù6ÍϛoCÇJÅØ:¸Åx¬44ÛÔ:˜àTË$ízå£hŸ`mÝÞÑiš]`pÞÂ;=(”Ü<ϑ``‡ŠÝGd"¾tŽÔÛx2è¥\]ƒ[/冻œŠ™¤L u×CÑ>ÁÈKû®™r’ àŒ¢PRÉdÃýBÈI’nG÷øD2 "<ŸsŽ:×!›ðffn(N '»=ù»Câ£Ué’õՄ#ÁfÖÌÇÑ6qÞ¯·}¿êží\½Uœþ@³@EIµ«(¹]däïB°¶@›ârîT~¨-ÙϵÅmiQwmO3Cù”1(T#}Î.D1V)};•*ĥɸa‹¢}F}g'šÖß;ܞG®ñ“Ãwj%§†Õ;Kh^®ÿ¼ý}hw뺭7Ãjh¶üVïÃí­=\I vó"µ/Ù4 ‰øûì_ñÉÙÀendstream +endobj +388 0 obj +1406 +endobj +389 0 obj<>>>>>endobj +390 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS047Ô3T072PIÑPp VðÌ-ÈIÍMÍ+I,ÉÌÏSÈOSð Ð Éâ҅(օªÎ, º†prÐ*-endstream +endobj +391 0 obj +95 +endobj +392 0 obj<>endobj +393 0 obj<>endobj +394 0 obj<>endobj +395 0 obj<>endobj +396 0 obj<>endobj +397 0 obj<>endobj +398 0 obj<>endobj +399 0 obj<>endobj +400 0 obj<>endobj +401 0 obj<>endobj +402 0 obj<>endobj +403 0 obj<>endobj +404 0 obj<>endobj +405 0 obj<>endobj +406 0 obj<>endobj +407 0 obj<>endobj +408 0 obj<>endobj +409 0 obj<>endobj +410 0 obj<>endobj +411 0 obj<>endobj +412 0 obj<>endobj +413 0 obj<>endobj +414 0 obj<>endobj +415 0 obj<>endobj +416 0 obj<>endobj +417 0 obj<>endobj +418 0 obj<>endobj +419 0 obj<>endobj +420 0 obj<>endobj +421 0 obj<>endobj +422 0 obj<>endobj +423 0 obj<>endobj +424 0 obj<>endobj +425 0 obj<>endobj +426 0 obj<>endobj +427 0 obj<>endobj +428 0 obj<>endobj +429 0 obj<>endobj +430 0 obj<>endobj +431 0 obj<>endobj +432 0 obj<>endobj +433 0 obj<>endobj +434 0 obj<>endobj +435 0 obj<>endobj +436 0 obj<>endobj +437 0 obj<>endobj +438 0 obj<>endobj +439 0 obj<>endobj +440 0 obj<>endobj +441 0 obj<>endobj +442 0 obj<>endobj +443 0 obj<>endobj +444 0 obj<>endobj +445 0 obj<>endobj +446 0 obj<>endobj +447 0 obj<>endobj +448 0 obj<>endobj +449 0 obj<>endobj +450 0 obj<>endobj +451 0 obj<>endobj +452 0 obj<>endobj +453 0 obj<>endobj +454 0 obj<>endobj +455 0 obj<>endobj +456 0 obj<>endobj +457 0 obj<>endobj +458 0 obj<>endobj +459 0 obj<>endobj +460 0 obj<>endobj +461 0 obj<>endobj +462 0 obj<>endobj +463 0 obj<>endobj +464 0 obj<>endobj +465 0 obj<>endobj +466 0 obj<>endobj +467 0 obj<>endobj +468 0 obj<>endobj +469 0 obj<>endobj +470 0 obj<>endobj +471 0 obj<>endobj +472 0 obj<>endobj +473 0 obj<>endobj +474 0 obj<>endobj +475 0 obj<>endobj +476 0 obj<>endobj +477 0 obj<>endobj +478 0 obj<>endobj +479 0 obj<>endobj +480 0 obj<>endobj +481 0 obj<>endobj +482 0 obj<>endobj +483 0 obj<>endobj +484 0 obj<>endobj +485 0 obj<>endobj +486 0 obj<>endobj +487 0 obj<>endobj +488 0 obj<>endobj +489 0 obj<>endobj +490 0 obj<>endobj +491 0 obj<>endobj +492 0 obj<>endobj +493 0 obj<>endobj +494 0 obj<>endobj +495 0 obj<>endobj +496 0 obj<>endobj +497 0 obj<>endobj +498 0 obj<>endobj +499 0 obj<>endobj +500 0 obj<>endobj +501 0 obj<>endobj +502 0 obj<>endobj +503 0 obj<>endobj +504 0 obj<>1<>2<>6<>]>>>>endobj +xref +0 505 +0000000000 65535 f +0000000015 00000 n +0000000220 00000 n +0000001786 00000 n +0000001860 00000 n +0000001938 00000 n +0000002015 00000 n +0000002094 00000 n +0000002170 00000 n +0000002251 00000 n +0000002309 00000 n +0000002361 00000 n +0000002446 00000 n +0000002498 00000 n +0000002582 00000 n +0000002687 00000 n +0000002792 00000 n +0000002897 00000 n +0000003002 00000 n +0000003107 00000 n +0000003212 00000 n +0000003285 00000 n +0000003386 00000 n +0000003471 00000 n +0000003572 00000 n +0000003657 00000 n +0000003758 00000 n +0000003843 00000 n +0000003930 00000 n +0000004015 00000 n +0000004102 00000 n +0000004187 00000 n +0000004253 00000 n +0000004338 00000 n +0000004404 00000 n +0000004489 00000 n +0000004555 00000 n +0000004640 00000 n +0000004706 00000 n +0000004791 00000 n +0000004857 00000 n +0000004942 00000 n +0000005008 00000 n +0000005093 00000 n +0000005187 00000 n +0000005291 00000 n +0000005396 00000 n +0000005501 00000 n +0000005606 00000 n +0000005710 00000 n +0000005815 00000 n +0000005920 00000 n +0000006024 00000 n +0000006129 00000 n +0000006234 00000 n +0000006338 00000 n +0000006443 00000 n +0000006548 00000 n +0000006653 00000 n +0000006758 00000 n +0000006863 00000 n +0000006968 00000 n +0000007073 00000 n +0000007178 00000 n +0000007283 00000 n +0000007388 00000 n +0000007493 00000 n +0000007598 00000 n +0000007703 00000 n +0000007808 00000 n +0000007913 00000 n +0000008018 00000 n +0000008123 00000 n +0000008228 00000 n +0000008333 00000 n +0000008438 00000 n +0000008543 00000 n +0000008648 00000 n +0000008753 00000 n +0000008858 00000 n +0000008963 00000 n +0000009068 00000 n +0000009173 00000 n +0000009278 00000 n +0000009383 00000 n +0000009488 00000 n +0000009593 00000 n +0000009697 00000 n +0000009800 00000 n +0000009903 00000 n +0000010235 00000 n +0000010340 00000 n +0000010445 00000 n +0000010549 00000 n +0000010654 00000 n +0000010759 00000 n +0000010863 00000 n +0000010968 00000 n +0000011073 00000 n +0000011177 00000 n +0000011282 00000 n +0000011388 00000 n +0000011493 00000 n +0000011599 00000 n +0000011705 00000 n +0000011809 00000 n +0000011914 00000 n +0000012020 00000 n +0000012126 00000 n +0000012232 00000 n +0000012338 00000 n +0000012443 00000 n +0000012549 00000 n +0000012655 00000 n +0000012761 00000 n +0000012867 00000 n +0000012973 00000 n +0000013079 00000 n +0000013185 00000 n +0000013291 00000 n +0000013397 00000 n +0000013503 00000 n +0000013609 00000 n +0000013715 00000 n +0000013821 00000 n +0000013927 00000 n +0000014033 00000 n +0000014139 00000 n +0000014245 00000 n +0000014351 00000 n +0000014457 00000 n +0000014563 00000 n +0000014669 00000 n +0000014775 00000 n +0000014881 00000 n +0000014986 00000 n +0000015089 00000 n +0000015193 00000 n +0000015577 00000 n +0000015683 00000 n +0000015789 00000 n +0000015895 00000 n +0000016001 00000 n +0000016107 00000 n +0000016213 00000 n +0000016319 00000 n +0000016425 00000 n +0000016531 00000 n +0000016637 00000 n +0000016743 00000 n +0000016849 00000 n +0000016955 00000 n +0000017061 00000 n +0000017167 00000 n +0000017272 00000 n +0000017378 00000 n +0000017484 00000 n +0000017646 00000 n +0000017680 00000 n +0000017714 00000 n +0000019275 00000 n +0000019324 00000 n +0000019373 00000 n +0000019422 00000 n +0000019471 00000 n +0000019520 00000 n +0000019569 00000 n +0000019618 00000 n +0000019667 00000 n +0000019716 00000 n +0000019765 00000 n +0000019814 00000 n +0000019863 00000 n +0000019912 00000 n +0000019961 00000 n +0000020010 00000 n +0000020059 00000 n +0000020108 00000 n +0000020157 00000 n +0000020206 00000 n +0000020255 00000 n +0000020304 00000 n +0000020353 00000 n +0000020402 00000 n +0000020451 00000 n +0000020500 00000 n +0000020549 00000 n +0000020598 00000 n +0000020647 00000 n +0000020696 00000 n +0000020745 00000 n +0000020794 00000 n +0000020843 00000 n +0000020892 00000 n +0000020941 00000 n +0000020990 00000 n +0000021039 00000 n +0000021088 00000 n +0000021137 00000 n +0000021186 00000 n +0000021235 00000 n +0000021284 00000 n +0000021333 00000 n +0000021382 00000 n +0000021431 00000 n +0000021480 00000 n +0000021529 00000 n +0000021578 00000 n +0000021627 00000 n +0000021676 00000 n +0000021725 00000 n +0000021774 00000 n +0000021823 00000 n +0000021872 00000 n +0000021921 00000 n +0000021970 00000 n +0000022019 00000 n +0000022068 00000 n +0000022117 00000 n +0000022166 00000 n +0000022215 00000 n +0000022264 00000 n +0000022313 00000 n +0000022362 00000 n +0000022411 00000 n +0000022460 00000 n +0000022509 00000 n +0000022558 00000 n +0000022607 00000 n +0000022656 00000 n +0000022705 00000 n +0000022754 00000 n +0000022803 00000 n +0000022852 00000 n +0000022901 00000 n +0000022950 00000 n +0000022999 00000 n +0000023048 00000 n +0000023097 00000 n +0000023146 00000 n +0000023195 00000 n +0000023244 00000 n +0000023293 00000 n +0000023342 00000 n +0000023391 00000 n +0000023440 00000 n +0000023489 00000 n +0000023538 00000 n +0000023587 00000 n +0000023636 00000 n +0000023685 00000 n +0000023734 00000 n +0000023783 00000 n +0000023832 00000 n +0000023881 00000 n +0000023930 00000 n +0000023979 00000 n +0000024028 00000 n +0000024077 00000 n +0000024126 00000 n +0000024175 00000 n +0000024224 00000 n +0000024273 00000 n +0000024322 00000 n +0000024371 00000 n +0000024420 00000 n +0000024469 00000 n +0000024518 00000 n +0000024567 00000 n +0000024616 00000 n +0000024665 00000 n +0000024714 00000 n +0000025103 00000 n +0000025255 00000 n +0000031606 00000 n +0000031628 00000 n +0000031723 00000 n +0000031825 00000 n +0000031845 00000 n +0000031999 00000 n +0000033204 00000 n +0000033226 00000 n +0000033339 00000 n +0000033520 00000 n +0000033541 00000 n +0000033695 00000 n +0000035100 00000 n +0000035122 00000 n +0000035235 00000 n +0000035421 00000 n +0000035442 00000 n +0000035591 00000 n +0000036819 00000 n +0000036841 00000 n +0000036963 00000 n +0000037998 00000 n +0000038019 00000 n +0000038168 00000 n +0000039121 00000 n +0000039142 00000 n +0000039291 00000 n +0000040023 00000 n +0000040044 00000 n +0000040193 00000 n +0000041122 00000 n +0000041143 00000 n +0000041292 00000 n +0000042197 00000 n +0000042218 00000 n +0000042349 00000 n +0000043077 00000 n +0000043098 00000 n +0000043238 00000 n +0000044075 00000 n +0000044096 00000 n +0000044236 00000 n +0000045034 00000 n +0000045055 00000 n +0000045186 00000 n +0000046091 00000 n +0000046112 00000 n +0000046243 00000 n +0000046855 00000 n +0000046876 00000 n +0000047016 00000 n +0000047766 00000 n +0000047787 00000 n +0000047918 00000 n +0000048747 00000 n +0000048768 00000 n +0000048908 00000 n +0000049757 00000 n +0000049778 00000 n +0000049909 00000 n +0000050574 00000 n +0000050595 00000 n +0000050726 00000 n +0000051448 00000 n +0000051469 00000 n +0000051600 00000 n +0000052242 00000 n +0000052263 00000 n +0000052394 00000 n +0000053214 00000 n +0000053235 00000 n +0000053366 00000 n +0000054209 00000 n +0000054230 00000 n +0000054370 00000 n +0000055054 00000 n +0000055075 00000 n +0000055215 00000 n +0000056453 00000 n +0000056475 00000 n +0000056615 00000 n +0000057829 00000 n +0000057851 00000 n +0000058000 00000 n +0000059136 00000 n +0000059158 00000 n +0000059307 00000 n +0000060161 00000 n +0000060182 00000 n +0000060313 00000 n +0000061347 00000 n +0000061368 00000 n +0000061517 00000 n +0000062552 00000 n +0000062573 00000 n +0000062713 00000 n +0000063698 00000 n +0000063719 00000 n +0000063832 00000 n +0000064039 00000 n +0000064060 00000 n +0000064200 00000 n +0000064867 00000 n +0000064888 00000 n +0000065001 00000 n +0000065186 00000 n +0000065207 00000 n +0000065361 00000 n +0000067810 00000 n +0000067832 00000 n +0000067987 00000 n +0000070974 00000 n +0000070996 00000 n +0000071151 00000 n +0000072628 00000 n +0000072650 00000 n +0000072763 00000 n +0000072929 00000 n +0000072949 00000 n +0000073004 00000 n +0000073109 00000 n +0000073253 00000 n +0000073359 00000 n +0000073479 00000 n +0000073588 00000 n +0000073737 00000 n +0000073847 00000 n +0000073954 00000 n +0000074101 00000 n +0000074201 00000 n +0000074312 00000 n +0000074462 00000 n +0000074609 00000 n +0000074720 00000 n +0000074832 00000 n +0000074993 00000 n +0000075105 00000 n +0000075218 00000 n +0000075387 00000 n +0000075507 00000 n +0000075628 00000 n +0000075795 00000 n +0000075913 00000 n +0000076032 00000 n +0000076200 00000 n +0000076319 00000 n +0000076439 00000 n +0000076606 00000 n +0000076724 00000 n +0000076843 00000 n +0000077013 00000 n +0000077134 00000 n +0000077256 00000 n +0000077423 00000 n +0000077541 00000 n +0000077660 00000 n +0000077825 00000 n +0000077941 00000 n +0000078058 00000 n +0000078227 00000 n +0000078347 00000 n +0000078468 00000 n +0000078636 00000 n +0000078755 00000 n +0000078875 00000 n +0000079043 00000 n +0000079162 00000 n +0000079282 00000 n +0000079450 00000 n +0000079569 00000 n +0000079689 00000 n +0000079857 00000 n +0000079976 00000 n +0000080096 00000 n +0000080261 00000 n +0000080377 00000 n +0000080494 00000 n +0000080646 00000 n +0000080762 00000 n +0000080879 00000 n +0000081028 00000 n +0000081173 00000 n +0000081297 00000 n +0000081431 00000 n +0000081575 00000 n +0000081687 00000 n +0000081852 00000 n +0000081967 00000 n +0000082105 00000 n +0000082238 00000 n +0000082363 00000 n +0000082489 00000 n +0000082624 00000 n +0000082758 00000 n +0000082892 00000 n +0000083039 00000 n +0000083196 00000 n +0000083345 00000 n +0000083471 00000 n +0000083611 00000 n +0000083749 00000 n +0000083888 00000 n +0000084022 00000 n +0000084159 00000 n +0000084296 00000 n +0000084430 00000 n +0000084562 00000 n +0000084693 00000 n +0000084832 00000 n +0000084969 00000 n +0000085080 00000 n +0000085235 00000 n +0000085369 00000 n +0000085500 00000 n +0000085641 00000 n +0000085759 00000 n +0000085918 00000 n +0000086035 00000 n +0000086168 00000 n +0000086303 00000 n +0000086469 00000 n +0000086603 00000 n +0000086742 00000 n +0000086900 00000 n +0000087044 00000 n +0000087196 00000 n +0000087325 00000 n +0000087445 00000 n +0000087579 00000 n +0000087676 00000 n +0000087776 00000 n +trailer +<]>> +startxref +88004 +%%EOF diff --git a/doc/ipp.shtml b/doc/ipp.shtml new file mode 100644 index 0000000000..a9c9fcff99 --- /dev/null +++ b/doc/ipp.shtml @@ -0,0 +1,1917 @@ + + + + + + CUPS Implementation of IPP + + + +

Scope

+ +

Identification

+ +

This document provides an overview of the Internet Printing Protocol +("IPP") version 1.1 as implemented in the Common UNIX Printing System +("CUPS") version 1.1. + + + +

Document Overview

+ +

This document is organized into the following sections: + +

+ + + +

Overview

+ +

CUPS 1.1 implements IPP/1.1 and the operations and attributes +defined in the "IPP: Job and Printer Set Operations", +"IPP/1.1: Output-bin Attribute Extension", and "IPP/1.1: finishings +'fold',' trim', and 'bale' attribute values extension" specifications. + +

CUPS also provides 13 new operations and many new attributes to +support multiple IPP printers and printer classes on a single host. + +

IPP URIs

+ +

CUPS supports both the "http" and "ipp" methods. The following +resource names are used: + +

+ +
method://hostname:port/ + +
Can be used for all "get" operations. + +
method://hostname:port/admin + +
Used for all administrative operations. + +
method://hostname:port/classes/name + +
Specifies a printer class. + +
method://hostname:port/jobs/id + +
Specifies a job. + +
method://hostname:port/printers/name + +
Specifies a printer. + +
+ +

So a typical printer URI would be "ipp://foo.bar.com/printers/LaserJet". + +

In addition, the CUPS server also supports normal browser access to +"method://hostname:port/admin/", "method://hostname:port/classes/", +"method://hostname:port/jobs/", and "method://hostname:port/printers/" +to view and manage resources on the server dynamically. + +

CUPS IPP Operations

+ +

CUPS provides 13 extension operations in addition to most of the +standard IPP and registered extension operations: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Operation NameCUPSCodeBrief Description
Print-Job1.00x0002Print a file.
Validate-Job1.00x0004Validate job attributes.
Create-Job1.10x0005Create a print job.
Send-Document1.10x0006Send a file for a print job.
Cancel-Job1.00x0008Cancel a print job.
Get-Job-Attributes1.00x0009Get job attributes.
Get-Jobs1.00x000AGet all jobs.
Get-Printer-Attributes1.00x000BGet printer attributes.
Hold-Job1.10x000CHold a job for printing.
Release-Job1.10x000DRelease a job for printing.
Pause-Printer1.00x0010Pause printing on a printer.
Resume-Printer1.00x0011Resume printing on a printer.
Purge-Jobs1.00x0012Purge all jobs.
Set-Job-Attributes1.10x0014Set attributes for a pending or held job.
CUPS-Get-Default1.00x4001Get the default destination.
CUPS-Get-Printers1.00x4002Get all of the available printers.
CUPS-Add-Printer1.00x4003Add or modify a printer.
CUPS-Delete-Printer1.00x4004Delete a printer.
CUPS-Get-Classes1.00x4005Get all of the available printer classes.
CUPS-Add-Class1.00x4006Add or modify a printer class.
CUPS-Delete-Class1.00x4007Delete a printer class.
CUPS-Accept-Jobs1.00x4008Accept jobs on a printer or printer class.
CUPS-Reject-Jobs1.00x4009Reject jobs on a printer or printer class.
CUPS-Set-Default1.00x400ASet the default destination.
CUPS-Get-Devices1.10x400BGet all of the available devices.
CUPS-Get-PPDs1.10x400CGet all of the available PPDs.
CUPS-Move-Job1.10x400DMove a job to a different printer.
+
+ +

Operations

+ +

The following sections describe the operations supported by CUPS. +In the interest of brevity, operations which use only the standard +IPP attributes are not described. + +

Print-Job Operation

+ +

The Print-Job operation (0x0002) prints a file. + +

Print-Job Request

+ +

The following groups of attributes are supplied as part of the +Print-Job request: + +

Group 1: Operation Attributes + +

    + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the IPP Model and + Semantics document. + +

    "printer-uri" (uri): + +

    The client MUST supply a URI for the specified printer. + +

+ +

Group 2: Job Template Attributes + +

    + +

    "job-billing" (text(MAX)): + +

    (CUPS 1.1 and higher) + +

    The client OPTIONALLY supplies a billing string that is logged + with the page accounting information. + +

    "job-sheets" (1setof type3 keyword | name(MAX)): + +

    (CUPS 1.1 and higher) + +

    The client OPTIONALLY supplies one or two banner pages that + are printed before and after any files in the print job. The + name of "none" is reserved to indicate that no banner page + should be printed. If the client does not specify this + attribute then the value of the "job-sheets-default" printer + object attribute is used. + +

    Note: Standard IPP only allows specification of a single + job-sheets attribute value. + +

    "media" (1setof type3 keyword | name(MAX)): + +

    The client OPTIONALLY supplies one or more media attributes + specifying the size, type, source, and color of the output + media. If the client does not specify this attribute then the + value of the "media-default" printer object attribute is used. + +

    Note: Standard IPP only allows specification of a single + media attribute value. + +

    Other Job Template Attributes + +

+ +

The Print-Job request is followed by a file to be printed. + +

Print-Job Response

+ +

The following groups of attributes are send as part of the Print-Job +Response: + +

Group 1: Operation Attributes + +

    + +

    Status Message: + +

    The standard response status message. + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the IPP Model and + Semantics document. + +

+ +

Group 2: Job Attributes + +

    + +

    Standard Job Attributes + +

+ +

Create-Job Operation

+ +

The Create-Job operation (0x0005) creates a new, empty print job. + +

Create-Job Request

+ +

The following groups of attributes are supplied as part of the +Create-Job request: + +

Group 1: Operation Attributes + +

    + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the IPP Model and + Semantics document. + +

    "printer-uri" (uri): + +

    The client MUST supply a URI for the specified printer. + +

+ +

Group 2: Job Template Attributes + +

    + +

    "job-billing" (text(MAX)): + +

    (CUPS 1.1 and higher) + +

    The client OPTIONALLY supplies a billing string that is logged + with the page accounting information. + +

    "job-sheets" (1setof type3 keyword | name(MAX)): + +

    (CUPS 1.1 and higher) + +

    The client OPTIONALLY supplies one or two banner pages that + are printed before and after any files in the print job. The + name of "none" is reserved to indicate that no banner page + should be printed. If the client does not specify this + attribute then the value of the "job-sheets-default" printer + object attribute is used. + +

    Note: Standard IPP only allows specification of a single + job-sheets attribute value. + +

    "media" (1setof type3 keyword | name(MAX)): + +

    The client OPTIONALLY supplies one or more media attributes + specifying the size, type, source, and color of the output + media. If the client does not specify this attribute then the + value of the "media-default" printer object attribute is used. + +

    Note: Standard IPP only allows specification of a single + media attribute value. + +

    Standard Job Template Attributes + +

+ +

Create-Job Response

+ +

The following groups of attributes are send as part of the +Create-Job Response: + +

Group 1: Operation Attributes + +

    + +

    Status Message: + +

    The standard response status message. + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the IPP Model and + Semantics document. + +

+ +

Group 2: Job Attributes + +

    + +

    Standard Job Attributes + +

+ +

Set-Job-Attributes Operation

+ +

The Set-Job-Attributes operation (0x0014) changes the attributes of +an active (not completed) job. + +

Set-Job-Attributes Request

+ +

The following groups of attributes are supplied as part of the +Set-Job-Attributes request: + +

Group 1: Operation Attributes + +

    + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the IPP Model and + Semantics document. + +

    "printer-uri" (uri) and "job-id" (integer) +

    OR +

    "job-uri": + +

    The client MUST supply a URI for the specified printer and + a job ID number, or the job URI. + +

+ +

Group 2: Job Template Attributes + +

    + +

    "job-sheets" (1setof type3 keyword | name(MAX)): + +

    (CUPS 1.1 and higher) + +

    The client OPTIONALLY supplies one or two banner pages that + are printed before and after any files in the print job. The + name of "none" is reserved to indicate that no banner page + should be printed. If the client does not specify this + attribute then the value of the "job-sheets-default" printer + object attribute is used. + +

    Note: Standard IPP only allows specification of a single + job-sheets attribute value. + +

    "media" (1setof type3 keyword | name(MAX)): + +

    The client OPTIONALLY supplies one or more media attributes + specifying the size, type, source, and color of the output + media. If the client does not specify this attribute then the + value of the "media-default" printer object attribute is used. + +

    Note: Standard IPP only allows specification of a single + media attribute value. + +

    Other Job Template Attributes + +

+ +

Set-Job-Attributes Response

+ +

The following groups of attributes are send as part of the Set-Job-Attributes +Response: + +

Group 1: Operation Attributes + +

    + +

    Status Message: + +

    The standard response status message. + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the IPP Model and + Semantics document. + +

+ +

CUPS-Get-Default Operation

+ +

The CUPS-Get-Default operation (0x4001) returns the default printer +URI and attributes. + +

CUPS-Get-Default Request

+ +

The following groups of attributes are supplied as part of the +CUPS-Get-Default request: + +

Group 1: Operation Attributes + +

    + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the IPP Model and + Semantics document. + +

    "requested-attributes" (1setOf keyword) : + +

    The client OPTIONALLY supplies a set of attribute names + and/or attribute group names in whose values the requester is + interested. If the client omits this attribute, the server + responds as if this attribute had been supplied with a value of + 'all'. + +

+ +

CUPS-Get-Default Response

+ +

The following groups of attributes are send as part of the +CUPS-Get-Default Response: + +

Group 1: Operation Attributes + +

    + +

    Status Message: + +

    The standard response status message. + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the IPP Model and + Semantics document. + +

+ +

Group 2: Printer Object Attributes + +

    + +

    The set of requested attributes and their current values. + +

+ +

CUPS-Get-Printers Operation

+ +

The CUPS-Get-Printers operation (0x4002) returns the printer +attributes for every printer known to the system. This may include +printers that are not served directly by the server. + +

CUPS-Get-Printers Request

+ +

The following groups of attributes are supplied as part of the +CUPS-Get-Printers request: + +

Group 1: Operation Attributes + +

    + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the IPP Model and + Semantics document. + +

    "limit" (integer (1:MAX)): + +

    The client OPTIONALLY supplies this attribute limiting the + number of printers that are returned. + +

    "printer-info" (text(127)): + +

    (CUPS 1.1 and higher) + +

    The client OPTIONALLY supplies this attribute to + select which printers are returned. + +

    "printer-location" (text(127)): + +

    (CUPS 1.1 and higher) + +

    The client OPTIONALLY supplies this attribute to + select which printers are returned. + +

    "printer-type" (type2 enum): + +

    (CUPS 1.1 and higher) + +

    The client OPTIONALLY supplies a printer type enumeration to + select which printers are returned. + +

    "printer-type-mask" (type2 enum): + +

    (CUPS 1.1 and higher) + +

    The client OPTIONALLY supplies a printer type mask + enumeration to select which bits are used in the "printer-type" + attribute. + +

    "requested-attributes" (1setOf keyword) : + +

    The client OPTIONALLY supplies a set of attribute names + and/or attribute group names in whose values the requester is + interested. If the client omits this attribute, the server + responds as if this attribute had been supplied with a value of + 'all'. + +

+ +

CUPS-Get-Printers Response

+ +

The following groups of attributes are send as part of the +CUPS-Get-Printers Response: + +

Group 1: Operation Attributes + +

    + +

    Status Message: + +

    The standard response status message. + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the IPP Model and + Semantics document. + +

+ +

Group 2: Printer Object Attributes + +

    + +

    The set of requested attributes and their current values for + each printer. + +

+ +

CUPS-Add-Printer Operation

+ +

The CUPS-Add-Printer operation (0x4003) adds a new printer or +modifies an existing printer on the system. + +

CUPS-Add-Printer Request

+ +

The following groups of attributes are supplied as part of the +CUPS-Add-Printer request: + +

Group 1: Operation Attributes + +

    + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the IPP Model and + Semantics document. + +

    "printer-uri" (uri): + +

    The client MUST supply a URI for the specified printer. + +

+ +

Group 2: Printer Object Attributes + +

    + +

    "banner-end-default" (name(127)): + +

    (CUPS 1.1 and higher) + +

    The client OPTIONALLY supplies a banner page name that is + printed after files in a job. The reserved name "none" is used to + specify that no banner page should be printed. + +

    "banner-start-default" (name(127)): + +

    (CUPS 1.1 and higher) + +

    The client OPTIONALLY supplies a banner page name that is + printed before files in a job. The reserved name "none" is used to + specify that no banner page should be printed. + +

    "device-uri" (uri): + +

    The client OPTIONALLY supplies a device URI for the + specified printer. + +

    "ppd-name" (name(127)): + +

    The client OPTIONALLY supplies a PPD name for the specified + printer. + +

    "printer-is-accepting-jobs" (boolean): + +

    The client OPTIONALLY supplies this boolean attribute + indicating whether or not the printer object should accept new jobs. + +

    "printer-info" (text(127)): + +

    The client OPTIONALLY supplies this attribute indicating the + printer information string. + +

    "printer-location" (text(127)): + +

    The client OPTIONALLY supplies this attribute indicating a + textual location of the printer. + +

    "printer-more-info" (uri): + +

    The client OPTIONALLY supplies this attribute indicating a + URI for additional printer information. + +

    "printer-state" (type2 enum): + +

    The client OPTIONALLY supplies this attribute indicating the + initial/current state of the printer. Only the "idle" and "stopped" + enumerations are recognized. + +

    "printer-state-message" (text(MAX)): + +

    The client OPTIONALLY supplies this attribute indicating a + textual reason for the current printer state. + +

    "requesting-user-name-allowed" (1setof name(127) | delete) +

    OR +

    "requesting-user-name-denied" (1setof name(127) | delete): + +

    The client OPTIONALLY supplies one of these attributes to + specify an access control list for incoming print jobs. To allow + all users access to a printer, use the delete tag for the + attribute value. + +

+ +

The CUPS-Add-Printer request can optionally be followed by a PPD +file or System V interface script to be used for the printer. The +"ppd-name" attribute overrides any file that is attached to the end of +the request with a local CUPS PPD file. + +

CUPS-Add-Printer Response

+ +

The following groups of attributes are send as part of the +CUPS-Add-Printer Response: + +

Group 1: Operation Attributes + +

    + +

    Status Message: + +

    The standard response status message. + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the IPP Model and + Semantics document. + +

+ +

CUPS-Delete-Printer Operation

+ +

The CUPS-Delete-Printer operation (0x4004) removes an existing +printer from the system. + +

CUPS-Delete-Printer Request

+ +

The following groups of attributes are supplied as part of the +CUPS-Delete-Printer request: + +

Group 1: Operation Attributes + +

    + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the IPP Model and + Semantics document. + +

    "printer-uri" (uri): + +

    The client MUST supply a URI for the specified printer. + +

+ +

CUPS-Delete-Printer Response

+ +

The following groups of attributes are send as part of the +CUPS-Delete-Printer Response: + +

Group 1: Operation Attributes + +

    + +

    Status Message: + +

    The standard response status message. + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the IPP Model and + Semantics document. + +

+ +

CUPS-Get-Classes Operation

+ +

The CUPS-Get-Classes operation (0x4005) returns the printer +attributes for every printer class known to the system. This may +include printer classes that are not served directly by the server. + +

CUPS-Get-Classes Request

+ +

The following groups of attributes are supplied as part of the +CUPS-Get-Classes request: + +

Group 1: Operation Attributes + +

    + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the IPP Model and + Semantics document. + +

    "limit" (integer (1:MAX)): + +

    The client OPTIONALLY supplies this attribute limiting the + number of printer classes that are returned. + +

    "printer-info" (text(127)): + +

    (CUPS 1.1 and higher) + +

    The client OPTIONALLY supplies this attribute to + select which printer classes are returned. + +

    "printer-location" (text(127)): + +

    (CUPS 1.1 and higher) + +

    The client OPTIONALLY supplies this attribute to + select which printer classes are returned. + +

    "printer-type" (type2 enum): + +

    (CUPS 1.1 and higher) + +

    The client OPTIONALLY supplies a printer type enumeration to + select which printer classes are returned. + +

    "printer-type-mask" (type2 enum): + +

    (CUPS 1.1 and higher) + +

    The client OPTIONALLY supplies a printer type mask + enumeration to select which bits are used in the "printer-type" + attribute. + +

    "requested-attributes" (1setOf keyword) : + +

    The client OPTIONALLY supplies a set of attribute names + and/or attribute group names in whose values the requester is + interested. If the client omits this attribute, the server responds as + if this attribute had been supplied with a value of 'all'. + +

+ +

CUPS-Get-Classes Response

+ +

The following groups of attributes are send as part of the +CUPS-Get-Classes Response: + +

Group 1: Operation Attributes + +

    + +

    Status Message: + +

    The standard response status message. + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the IPP Model and + Semantics document. + +

+ +

Group 2: Printer Class Object Attributes + +

    + +

    The set of requested attributes and their current values for + each printer class. + +

+ +

CUPS-Add-Class Operation

+ +

The CUPS-Add-Class operation (0x4006) adds a new printer class or +modifies and existing printer class on the system. + +

CUPS-Add-Class Request

+ +

The following groups of attributes are supplied as part of the +CUPS-Add-Class request: + +

Group 1: Operation Attributes + +

    + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the IPP Model and + Semantics document. + +

    "printer-uri" (uri): + +

    The client MUST supply a URI for the specified printer class. + +

+ +

Group 2: Printer Object Attributes + +

    + +

    "member-uris" (1setof uri): + +

    The client OPTIONALLY supplies the "member-uris" set + specifying the printers and printer classes that are part of the class. + +

    "printer-is-accepting-jobs" (boolean): + +

    The client OPTIONALLY supplies this boolean attribute + indicating whether or not the class object should accept new jobs. + +

    "printer-info" (text(127)): + +

    The client OPTIONALLY supplies this attribute indicating the + printer information string. + +

    "printer-location" (text(127)): + +

    The client OPTIONALLY supplies this attribute indicating a + textual location of the class. + +

    "printer-more-info" (uri): + +

    The client OPTIONALLY supplies this attribute indicating a + URI for additional class information. + +

    "printer-state" (type2 enum): + +

    The client OPTIONALLY supplies this attribute indicating the + initial/current state of the class. Only the "idle" and "stopped" + enumerations are recognized. + +

    "printer-state-message" (text(MAX)): + +

    The client OPTIONALLY supplies this attribute indicating a + textual reason for the current class state. + +

    "requesting-user-name-allowed" (1setof name(127)) +

    OR +

    "requesting-user-name-denied" (1setof name(127)): + +

    The client OPTIONALLY supplies one of these attributes to + specify an access control list for incoming print jobs. To allow + all users access to a class, use the delete tag for the + attribute value. + +

+ +

CUPS-Add-Class Response

+ +

The following groups of attributes are send as part of the CUPS-Add-Class Response: + +

Group 1: Operation Attributes + +

    + +

    Status Message: + +

    The standard response status message. + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the IPP Model and + Semantics document. + +

+ +

CUPS-Delete-Class Operation

+ +

The CUPS-Delete-Class operation (0x4007) removes an existing printer +class from the system. + +

CUPS-Delete-Class Request

+ +

The following groups of attributes are supplied as part of the +CUPS-Delete-Class request: + +

Group 1: Operation Attributes + +

    + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the IPP Model and + Semantics document. + +

    "printer-uri" (uri): + +

    The client MUST supply a URI for the specified printer class. + +

+ +

CUPS-Delete-Class Response

+ +

The following groups of attributes are send as part of the +CUPS-Delete-Class Response: + +

Group 1: Operation Attributes + +

    + +

    Status Message: + +

    The standard response status message. + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the IPP Model and + Semantics document. + +

+ +

CUPS-Accept-Jobs Operation

+ +

The CUPS-Accept-Jobs operation (0x4008) sets the +"printer-is-accepting-jobs" attribute to true for the specified printer +or printer class. + +

CUPS-Accept-Jobs Request

+ +

The following groups of attributes are supplied as part of the +CUPS-Accept-Jobs request: + +

Group 1: Operation Attributes + +

    + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the IPP Model and + Semantics document. + +

    "printer-uri" (uri): + +

    The client MUST supply a URI for the specified printer or printer class. + +

+ +

CUPS-Accept-Jobs Response

+ +

The following groups of attributes are send as part of the +CUPS-Accept-Jobs Response: + +

Group 1: Operation Attributes + +

    + +

    Status Message: + +

    The standard response status message. + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the IPP Model and + Semantics document. + +

+ +

CUPS-Reject-Jobs Operation

+ +

The CUPS-Reject-Jobs operation (0x4009) sets +the"printer-is-accepting-jobs" attribute to false for the specified +printer or printer class. + +

CUPS-Reject-Jobs Request

+ +

The following groups of attributes are supplied as part of the +CUPS-Reject-Jobs request: + +

Group 1: Operation Attributes + +

    + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the IPP Model and + Semantics document. + +

    "printer-uri" (uri): + +

    The client MUST supply a URI for the specified printer or printer class. + +

+ +

Group 2: Printer Object Attributes + +

    + +

    "printer-state-message" (text(MAX)): + +

    The client OPTIONALLY supplies this attribute indicating a + textual reason for the current printer state. + +

+ +

CUPS-Reject-Jobs Response

+ +

The following groups of attributes are send as part of the +CUPS-Reject-Jobs Response: + +

Group 1: Operation Attributes + +

    + +

    Status Message: + +

    The standard response status message. + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the IPP Model and + Semantics document. + +

+ +

CUPS-Set-Default Operation

+ +

The CUPS-Set-Default operation (0x400A) sets the default printer +destination for all clients when a resource name of "/printers" is +specified. + +

CUPS-Set-Default Request

+ +

The following groups of attributes are supplied as part of the +CUPS-Set-Default request: + +

Group 1: Operation Attributes + +

    + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the IPP Model and + Semantics document. + +

    "printer-uri" (uri): + +

    The client MUST supply a URI for the specified printer or + printer class. + +

+ +

CUPS-Set-Default Response

+ +

The following groups of attributes are send as part of the +CUPS-Set-Default Response: + +

Group 1: Operation Attributes + +

    + +

    Status Message: + +

    The standard response status message. + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the IPP Model and + Semantics document. + +

+ +

CUPS-Get-Devices Operation

+ +

The CUPS-Get-Devices operation (0x400B) returns all of the supported +device-uri's for the server (CUPS 1.1 and higher). + +

CUPS-Get-Devices Request

+ +

The following groups of attributes are supplied as part of the +CUPS-Get-Devices request: + +

Group 1: Operation Attributes + +

    + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the IPP Model and + Semantics document. + +

    "device-class" (type1 keyword): + +

    The client OPTIONALLY supplies a device class keyword to select + which devices are returned. + +

    "limit" (integer (1:MAX)): + +

    The client OPTIONALLY supplies this attribute limiting the number of + devices that are returned. + +

    "requested-attributes" (1setOf keyword) : + +

    The client OPTIONALLY supplies a set of attribute names and/or + attribute group names in whose values the requester is interested. If + the client omits this attribute, the server responds as if this + attribute had been supplied with a value of 'all'. + +

+ +

CUPS-Get-Devices Response

+ +

The following groups of attributes are send as part of the +CUPS-Get-Devices Response: + +

Group 1: Operation Attributes + +

    + +

    Status Message: + +

    The standard response status message. + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the IPP Model and + Semantics document. + +

+ +

Group 2: Device Object Attributes + +

    + +

    The set of requested attributes and their current values for + each device. + +

+ +

CUPS-Get-PPDs Operation

+ +

The CUPS-Get-PPDs operation (0x400C) returns all of the locally +available PPD files on the system (CUPS 1.1 and higher). + +

CUPS-Get-PPDs Request

+ +

The following groups of attributes are supplied as part of the +CUPS-Get-PPDs request: + +

Group 1: Operation Attributes + +

    + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the IPP Model and + Semantics document. + +

    "limit" (integer (1:MAX)): + +

    The client OPTIONALLY supplies this attribute limiting the number of + PPDs that are returned. + +

    "ppd-make" (text(127)): + +

    The client OPTIONALLY supplies a printer manufacturer to select + which PPDs are returned. + +

    "requested-attributes" (1setOf keyword) : + +

    The client OPTIONALLY supplies a set of attribute names and/or + attribute group names in whose values the requester is interested. If + the client omits this attribute, the server responds as if this + attribute had been supplied with a value of 'all'. + +

+ +

CUPS-Get-PPDs Response

+ +

The following groups of attributes are send as part of the +CUPS-Get-PPDs Response: + +

Group 1: Operation Attributes + +

    + +

    Status Message: + +

    The standard response status message. + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the IPP Model and + Semantics document. + +

+ +

Group 2: PPD Attributes + +

    + +

    The set of requested attributes and their current values for each + PPD file. + +

+ +

CUPS-Move-Job Operation

+ +

The CUPS-Move-Job operation (0x400D) moves an active print job to a +different printer (CUPS 1.1 and higher). + +

CUPS-Move-Job Request

+ +

The following groups of attributes are supplied as part of the +CUPS-Move-Job request: + +

Group 1: Operation Attributes + +

    + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the IPP Model and + Semantics document. + +

    "printer-uri" (uri) and "job-id" (integer) +

    OR +

    "job-uri": + +

    The client MUST supply a URI for the specified printer and + a job ID number, or the job URI. + +

+ +

Group 2: Job Template Attributes + +

    + +

    "job-printer-uri" (uri) + +

    The client MUST supply a URI for a printer on the same server. + +

+ +

CUPS-Move-Job Response

+ +

The following groups of attributes are send as part of the +CUPS-Move-Job Response: + +

Group 1: Operation Attributes + +

    + +

    Status Message: + +

    The standard response status message. + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the IPP Model and + Semantics document. + +

+ +

Attributes

+ +

CUPS provides many extension attributes to support multiple devices, +PPD files, standard job filters, printers, and printer classes. + +

Device Attributes

+ +

Device attributes are returned by the CUPS-Get-Devices operation and +enumerate all of the available hardware devices and network protocols +that are supported by the server. + +

device-class (type2 keyword)

+ +

The device-class attribute specifies the class of device and can be +one of the following: + +

    + +
  • "file" - a disk file. + +
  • "direct" - a parallel or fixed-rate serial data port, + currently used for Centronics, IEEE-1284, and USB printer + ports. + +
  • "serial" - a variable-rate serial port. + +
  • "network" - a network connection, typically via AppSocket, + HTTP, IPP, LPD, or SMB/CIFS protocols. + +
+ +

device-info (text(127))

+ +

The device-info attribute specifies a human-readable string describing +the device, e.g. "Parallel Port #1". + +

device-make-and-model (text(127))

+ +

The device-makr-and-model attribute specifies a device +identification string provided by the printer connected to the device. +If the device or printer does not support identification then this +attribute contains the string "unknown". + +

device-uri (uri)

+ +

The device-uri attribute specifies a unique identifier for the +device. The actual format of the device-uri string depends on the value +of the device-class attribute: + +

    + +
  • "file" - The device-uri will be of the form + "file:/path/to/filename". + +
  • "direct" - The device-uri will be of the form + "method:/dev/filename", where method may be "parallel" or "usb" + in the current implementation. + +
  • "serial" - The device-uri will be of the form + "serial:/dev/filename?baud=value+parity=value+flow=value". + The baud value is the data rate in bits per second; the + supported values depend on the underlying hardware. + The parity value can be one of "none", "even", or "odd". + The flow value can be one of "none", "soft" (XON/XOFF + handshaking), "hard" or "rts/cts" (RTS/CTS handshaking), + or "dtrdsr" (DTR/DSR handshaking). + +

    The URI returned by CUPS-Get-Devices will contain the + maximum baud rate supported by the device and the best + type of flow control available ("soft" or "hard"). + +

  • "network" - The device-uri will be of the form + "method://[username:password@]hostname[:port]/[resource]", + where method may be "http", "ipp", "lpd", "smb", or + "socket" in the current implementation. + +

    The URI returned by CUPS-Get-Devices will only contain + the method name followed by two slashes ("method://"). + It is up to the client application to add the appropriate + host and other information when adding a new printer. + +

    The URI returned by Get-Printer-Attributes and + CUPS-Get-Printers has any username and password information + stripped; the information is still stored and used by the + server internally to perform any needed authentication. + +

+ +

Job Template Attributes

+ +

blackplot (boolean)

+ +

The blackplot attribute specifies whether HP-GL/2 plot files should be +rendered entirely in black ink (blackplot=true) or using the colors and shades +specified in the file (blackplot=false). The default value is false. + +

brightness (integer(0:200))

+ +

The brightness attribute specifies the overall brightness of the printed +output in percent. A brightness of 100 is normal, while 200 is twice as +bright and 50 is half as bright. The default value is 100. + +

Brightness is applied to the Cyan, Magenta, Yellow, and Black values using +the function "f(x) = brightness / 100 * x". + +

columns (integer(1:4))

+ +

The columns attribute specifies the number of columns to generate when +printing text files. The default value is 1. + +

cpi (type2 enum)

+ +

The cpi attribute specifies the number of characters per inch when +printing text files. Only the values 10, 12, and 17 are currently +supported. The default value is 10. + +

fitplot (boolean)

+ +

The fitplot attribute specifies whether to scale HP-GL/2 plot files to +fit on the selected media (fitplot=true) or use the physical scale specified +in the plot file (fitplot=false). The default value is false. + +

gamma (integer(1:10000))

+ +

The gamma attribute specifies the luminance correction for the output. +A value of 1000 specifies no correction, while values of 2000 and 500 will +generate lighter and darker output, respectively. The default value is +1000. + +

Gamma is applied to the Red, Green, and Blue values (or luminance for +grayscale output) using the function "f(x) = x(1000/gamma)". + +

hue (integer(-180:180))

+ +

The hue attribute specifies a color hue rotation when printing image +files. The default value is 0. + +

job-billing (text(MAX))

+ +

(CUPS 1.1 and higher) + +

The job-billing attribute provides a text value to associate with a job +for billing purposes. + +

job-hold-until (keyword | name(MAX))

+ +

(CUPS 1.1 and higher) + +

The job-hold-until attribute specifies a hold time. In addition to the +standard IPP/1.1 keyword names, CUPS supports name values of the form +"HH:MM" and "HH:MM:SS" that specify a hold time. The hold time is in +Greenwich Mean Time (GMT) and not in the local time zone. If the +specified time is less than the current time, the job is held until the +next day. + +

job-sheets (1setof type3 keyword | name(MAX))

+ +

(CUPS 1.1 and higher) + +

The job-sheets attribute specifies one or two banner files that are printed +before and after a job. The reserved value of "none" disables banner printing. +The default value is stored in the job-sheets-default attribute. + +

If only one value is supplied, the banner file is printed before the job. +If two values are supplied, the first value is used as the starting banner +file and the second as the ending banner file. + +

job-originating-host-name (name(MAX))

+ +

(CUPS 1.1.5 and higher) + +

The job-originating-host-name attribute specifies the host +from which the job was queued. The value will be the hostname or +IP address of the client depending on whether hostname +resolution is enabled. The localhost address (127.0.0.1) is +always resolved to the name "localhost". + +

This attribute is read-only. + +

lpi (type2 enum)

+ +

The lpi attribute specifies the number of lines per inch when +printing text files. Only the values 6 and 8 are currently supported. +The default value is 6. + +

page-bottom (integer(0:MAX))

+ +

The page-bottom attribute specifies the bottom margin in points (72 points +equals 1 inch). The default value is the device physical margin. + +

page-left (integer(0:MAX))

+ +

The page-left attribute specifies the left margin in points (72 points +equals 1 inch). The default value is the device physical margin. + +

page-right (integer(0:MAX))

+ +

The page-right attribute specifies the right margin in points (72 points +equals 1 inch). The default value is the device physical margin. + +

page-set (type2 keyword)

+ +

The page-set attribute specifies which pages to print in a file. The +supported keywords are "all", "even", and "odd". The default value is +"all". + +

page-top (integer(0:MAX))

+ +

The page-top attribute specifies the top margin in points (72 points +equals 1 inch). The default value is the device physical margin. + +

penwidth (integer(0:MAX))

+ +

The penwidth attribute specifies the default pen width in micrometers +when printing HP-GL/2 plot files. The default value is 1000 (1 millimeter). + +

position (type2 keyword)

+ +

The position attribute specifies the location of image files on the +media. The following keyword values are recognized: + +

    + +
  • center - Center the image on the page (default) + +
  • top - Print the image centered at the top of the page + +
  • left - Print the image centered on the left of page + +
  • right - Print the image centered on the right of the page + +
  • top-left - Print the image at the top left corner of + the page + +
  • top-right - Print the image at the top right corner of + the page + +
  • bottom - Print the image centered at the bottom of + the page + +
  • bottom-left - Print the image at the bottom left + corner of the page + +
  • bottom-right - Print the image at the bottom right + corner of the page + +
+ +

ppi (integer(1:MAX))

+ +

The ppi attribute specifies the resolution of an image file in pixels +per inch. The default value is the resolution included with the file or +128 if no resolution information is available. + +

prettyprint (boolean)

+ +

The prettyprint attribute specifies whether text files should be printed +with a shaded header and keyword highlighting (prettyprint=true) or without +additional formatting (prettyprint=false). The default value is false. + +

saturation (integer(0:200))

+ +

The saturation attribute specifies the color saturation when +printing image files. A saturation of 100 is normal, while values of 50 +and 200 will be half and twice as colorful, respectively. The default +value is 100. + +

scaling (integer(1:1000))

+ +

The scaling attribute specifies the scaling of image files with +respect to the selected media. A value of 100 specifies that the image +file should fit 100% of the page, or as much as possible given the +image dimensions. The default value is unspecified. + +

The scaling attribute overrides the ppi attribute if specified. + +

wrap (boolean)

+ +

The wrap attribute specifies whether long lines should be wrapped +(wrap=true) or not (wrap=false) when printing text files. The default +value is true. + +

PPD Attributes

+ +

ppd-natural-language (naturalLanguage)

+ +

The ppd-natural-language attribute specifies the language encoding +of the PPD file (the LanguageVersion attribute in the PPD file). If the +language is unknown or undefined then "en" (English) is assumed. + +

ppd-make (text(127))

+ +

The ppd-make attribute specifies the manufacturer of the printer +(the Manufacturer attribute in the PPD file). If the manufacturer +is not specified in the PPD file then an educated guess is made using +the NickName attribute in the PPD file. + +

ppd-make-and-model (text(127))

+ +

The ppd-make-and-model attribute specifies the manufacturer and model +name of the PPD file (the NickName attribute in the PPD file). If the +make and model is not specified in the PPD file then the ModelName or +ShortNickName attributes are used instead. + +

ppd-name (name(255))

+ +

The ppd-name attribute specifies the PPD filename on the server +relative to the model directory. The forward slash (/) is used to +delineate directories. + +

Printer Attributes

+ +

job-k-limit (integer)

+ +

(CUPS 1.1 and higher) + +

The job-k-limit attribute specifies the maximum number of kilobytes that +may be printed by a user, including banner files. The default value of 0 +specifies that there is no limit. + +

job-page-limit (integer)

+ +

(CUPS 1.1 and higher) + +

The job-page-limit attribute specifies the maximum number of pages that +may be printed by a user, including banner files. The default value of 0 +specifies that there is no limit. + +

job-quota-period (integer)

+ +

(CUPS 1.1 and higher) + +

The job-quota-period attribute specifies the time period used for quota +calculations, in seconds. The default value of 0 specifies that the limits +apply to all jobs that have been printed by a user that are still known to +the system. + +

job-sheets-supported (1setof type3 keyword | name(MAX))

+ +

(CUPS 1.1 and higher) + +

The job-sheets-supported attribute specifies the available banner files. +There will always be at least one banner file available called "none". + +

printer-type (type2 enum)

+ +

The printer-type attribute specifies printer type and capability bits for +the printer or class. The default value is computed from internal state +information and the PPD file for the printer. The following bits are defined: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BitDescription
0x00000001Is a printer class.
0x00000002Is a remote destination.
0x00000004Can print in black.
0x00000008Can print in color.
0x00000010Can print on both sides of the page in hardware.
0x00000020Can staple output.
0x00000040Can do fast copies in hardware.
0x00000080Can do fast copy collation in hardware.
0x00000100Can punch output.
0x00000200Can cover output.
0x00000400Can bind output.
0x00000800Can sort output.
0x00001000Can handle media up to US-Legal/A4.
0x00002000Can handle media from US-Legal/A4 to ISO-C/A2.
0x00004000Can handle media larger than ISO-C/A2.
0x00008000Can handle user-defined media sizes.
0x00010000Is an implicit (server-generated) class.
+ +

printer-type-mask (type2 enum)

+ +

(CUPS 1.1 and higher) + +

The printer-type-mask attribute is used to choose printers or classes with +the CUPS-Get-Printers and CUPS-Get-Classes operations. The bits are defined +identically to the printer-type attribute and default to all 1's. + +

requesting-user-name-allowed (1setof name(127))

+ +

(CUPS 1.1 and higher) + +

The requesting-user-name-allowed attribute lists all of the users that are +allowed to access a printer or class. Either this attribute or the +requesting-user-name-denied attribute will be defined, but not both. + +

requesting-user-name-denied (1setof name(127))

+ +

(CUPS 1.1 and higher) + +

The requesting-user-name-denied attribute lists all of the users that are +not allowed to access a printer or class. Either this attribute or the +requesting-user-name-allowed attribute will be defined, but not both. + +

Printer Class Attributes

+ +

member-names (1setof name(127))

+ +

The member-names attribute specifies each of the printer-name attributes of +the member printers and classes. Each name corresponds to the same element of +the member-uris attribute. + +

member-uris (1setof uri)

+ +

The member-uris attribute specifies each of the printer-uri attributes of +the member printers and classes. Each URI corresponds to the same element of +the member-names attribute. + + + + + diff --git a/doc/overview.html b/doc/overview.html new file mode 100644 index 0000000000..12bec26820 --- /dev/null +++ b/doc/overview.html @@ -0,0 +1,500 @@ + + + + An Overview of the Common UNIX Printing System + + + + + + + + +

An Overview of the
+ Common UNIX Printing System,
+ Version 1.1

+ +

July 10, 2000
+ Michael Sweet, Easy Software Products
+ Copyright 1998-2000, 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 UNIX 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. These printing systems were +designed in the 70's for printing text to line printers; vendors have +since added varying levels of support for other types of printers. + +

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 developed by the Institute of Electrical and Electronics +Engineers, Inc. ("IEEE") [IEEE-1387.4] and Internet Printing Protocol +("IPP") developed by the Internet Engineering Task Force ("IETF") +through the Printer Working Group ("PWG") [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, but has been +shelved by the IEEE. + +

The Internet Printing Protocol defines extensions to the HyperText +Transport Protocol 1.1 [RFC2616] to provide support for remote printing +services. IPP/1.0 was accepted by the IETF as an experimental Request +For Comments [RFC] document in October of 1999. Since then the Printer +Working Group has developed an updated set of specifications for +IPP/1.1 which have been accepted by the IETF and are awaiting +publication as proposed standards. Unlike POSIX Printing, IPP enjoys +widespread industry support and is poised to become the standard +network printing solution for all operating systems. + +

CUPS uses IPP/1.1 to provide a complete, modern printing system for +UNIX that can be extended to support new printers, devices, and +protocols while providing compatibility with existing UNIX +applications. CUPS is free software provided under the terms of the +GNU General Public License and GNU Library General Public License. + +

History

+ +

The first production release of CUPS (based on IPP/1.0) was released +in October of 1999. Since then, we have released several patch updates +to the original CUPS 1.0 release that addressed security, portability, +and bugs found, but no new functionality was added to improve the +stability of the CUPS code. + +

CUPS 1.1 is based on IPP/1.1 and adds many of the functional +enhancements that have been requested by our users. As with 1.0, CUPS +1.1 will be followed by patch releases that address any problems found +with the software but add no new features. + +

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, +status monitoring, and administration. + +

The scheduler also manages a list of available printers on the LAN +and dispatches print jobs as needed using the appropriate filters and +backends. + +

Configuration Files

+ +The configuration files consist of: + +
    + +
  • The 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 or Send-File request is received with a +document-format of application/octet-stream. + +

The MIME conversion rule files list the available filters. 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 all printers, not just +PostScript printers. There is one PPD file for each printer. PPD files +for non-PostScript printers define additional filters through +cupsFilter attributes to support printer drivers. + +

CUPS API

+ +

The CUPS API contains CUPS-specific convenience functions for queuing +print jobs, getting printer information, accessing resources via HTTP +and IPP, and manipulating PPD files. Unlike the rest of CUPS, the CUPS +API is provided under the terms of the GNU LGPL so it may be used by +non-GPL applications. + +

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@server") when printer browsing is enabled. + +

The System V administation commands are supplied for managing +printers and classes. 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. + +

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

Filters are provided for many file formats and include image file +and PostScript raster filters that support non-PostScript printers. Multiple +filters are run in parallel to produce the required output format. + +

The PostScript raster filter is based on the GNU Ghostscript 5.50 +core. Instead of using the Ghostscript printer drivers and front-end, +the CUPS filter uses a generic raster printer driver and CUPS-compliant +front-end to support any kind of raster printer. This allows the same +printer driver filter to be used for printing raster data from any +filter. + +

CUPS Imaging

+ +

The CUPS Imaging library provides functions for managing large +images, doing colorspace conversion and color management, scaling +images for printing, and managing raster page streams. It is used by +the CUPS image file filters, the PostScript RIP, and all raster +printers drivers. + +

Backends

+ +

A backend program is a special filter that sends print data to a +device or network connection. Backends for parallel, serial, USB, LPD, IPP, +and AppSocket (JetDirect) connections are provided in CUPS 1.1. + +

SAMBA version 2.0.6 and higher includes a SMB backend +(smbspool(1)) that can be used with CUPS 1.0 or 1.1 for +printing to Windows. + +

Network Printing

+ +

Traditionally, network printing has been one of the hardest things to +get working under UNIX. One reason is because each vendor added their +own extensions to the LPD protocol (the previous standard for network +printing), making cross-platform printing difficult if not impossible. + +

Another reason is that you have to administer every network printer +on every client machine. In some cases you can "clone" the printer +configuration from a "master" client to each of the others, but even +that can be time-consuming and error-prone. Something better is needed. + +

CUPS provides "printer browsing", which allows clients to +automatically see and use printers from any server on a LAN. This means +that you only need to configure the server and the clients will +automatically see the printers and classes on it. + +

In addition, CUPS can automatically merge multiple identical network +printers into "implicit classes". This allows clients to send jobs to +the implicit class and have them print on the first available printer +or server. In addition, failsafe and load-balancing functions are +enabled simply by defining the same printer on multiple servers! + +

New Features in CUPS 1.1

+ +

CUPS 1.1 includes many new features and capabilities: + +

    + +
  1. Backends + +
  2. Banner Page Support + +
  3. Digest Authentication + +
  4. Directory Services + +
  5. Directory Structure Changes + +
  6. Documentation + +
  7. Drivers + +
  8. Filters + +
  9. IPP Support + +
  10. Job Persistence + +
  11. LPD Client Support + +
  12. User-Defined Printers and Options + +
  13. Web Administration Interface + +
+ +

1. Backends

+ +

CUPS 1.1 implements a new backend interface for retrieving a list of +available devices for CUPS clients. This allows administration +interfaces to query the CUPS scheduler for a list of available devices, +automatically configure printers if the device identification +information is available, and present the user with a list of available +devices rather than relying on the user to know what devices are +configured on the system. + +

The new release also includes a backend for USB printers under +*BSD and Linux. Support for USB under Solaris 8 will be provided in +a subsequent patch release. + +

2. Banner Page Support

+ +

CUPS 1.1 includes support for banner pages at the beginning and end +of a job. Banner pages may be of any file format and support variable +substitution for job titles, usernames, etc. Default banner pages are +associated with each printer and can be overridden with command-line +options by the user. + +

3. Digest Authentication

+ +

Digest authentication provides a more secure method of authenticating +access to the printing system. Unlike Basic authentication, Digest +authentication does not send passwords "in the clear" so it is more +difficult to gain unauthorized access to your system. + +

CUPS 1.1 implements Digest authentication using a special MD5 +password file instead of the UNIX password file. This file is managed +using the new lppasswd command. + +

4. Directory Services

+ +

CUPS 1.1 adds new directory service ("printer browsing") features to +make using CUPS on large LANs and WANs easier. You can now poll a +remote server for printer information and relay it to the LAN as well +as restrict what printer information is processed (e.g. to "hide" +servers, domains, or networks that you don't want to see.) + +

5. Directory Structure Changes

+ +

CUPS 1.1 now uses a directory structure that complies with the +Filesystem Hierarchy Standard ("FHS"), version 2.0. This should make +integration into existing Linux and *BSD distributions a lot easier. + +

6. Documentation

+ +

The CUPS 1.1 documentation has gone through many revisions, +including a completely rewritten administrators manual, a new +programmers manual, and an IPP implementation reference manual. + +

7. Drivers

+ +

CUPS 1.1 includes drivers for EPSON dot-matrix and inkjet printers. +As with the HP PCL drivers, the EPSON drivers don't necessarily provide +the best possible output for each printer but should provide adequate +printing quality for general day-to-day printing. + +

8. Filters

+ +

CUPS 1.1 includes new image, PostScript, PDF, and text filters. The image +filters have been upgraded to support Windows BMP and Alias PIX files. + +

The PostScript filter is now based off GNU Ghostscript 5.50. The new +filter provides much better performance with higher-resolution printers +and supports most Level 3 PostScript language features. + +

The new PDF filter is based off the excellent Xpdf software from +Derek Noonburg and supports automatic page scaling. The new filter is a +faster, smaller, more reliable replacement for the GNU Ghostscript PDF +filtering that was used in CUPS 1.0. + +

The new text filter now supports bidirectional text and can embed +fonts as needed. + +

9. IPP Support

+ +

Probably the least visible portion of CUPS is the IPP support. CUPS +1.1 implements all of the required IPP/1.1 operations and attributes +and most of the optional ones. The optional Create-Job and Send-File +operations are now implemented, allowing for better System V printing +system compatibility (one job ID per lp command) and +support for banner pages. + +

10. Job Persistence

+ +

CUPS 1.1 supports job persistence. This means that jobs are preserved +even after a reboot, a feature that was sorely missing from CUPS 1.0. + +

In addition, CUPS 1.1 allows you to keep job information after the +job has printed. The basic post-job persistence mode provides a job +history (number of pages printed, time job was printed, etc.) but does +not preserve the actual job files. This can be changed to discard all +information after a job is printed or keep the job files after printing +so you can reprint a job at some later time. + +

11. LPD Client Support

+ +

By popular request, CUPS 1.1 supports LPD-based clients using a new +mini-daemon that handles LPD requests and passes them on to the main +server. + +

12. User-Defined Printers and Options

+ +

CUPS 1.1 includes support for user-defined printers and options via +a new lpoptions command. User-defined printers are special +instances of the available printers (e.g. "printer/instance" or +"printer@server/instance") that can have their own default options such +as media size, resolution, and so forth. The lpoptions +command can also be used to set a different default printer queue. + +

13. Web Administration Interface

+ +

CUPS 1.0 provided a simple class, job, and printer monitoring +interface for web browsers. CUPS 1.1 replaces this interface with an +enhanced administration interface that allows you to add, modify, +delete, configure, and control classes, jobs, and printers. + +

Software Using CUPS

+ +

A lot has happened since CUPS 1.0 came out, and many software packages +are supporting CUPS. We have contributed code to the SAMBA team to support +CUPS, and parts of that are already available in SAMBA 2.0.6 and 2.0.7. +With any luck the final pieces that provide a complete integration with +SAMBA will be available in the next release of SAMBA. + +

Two graphical interfaces have appeared on the scene that use CUPS as +well. The KUPS project provides a KDE-based interface for CUPS and can be +found at: + +

+ +

The X Printing Panel ("XPP") project provides a graphical printing +panel for CUPS and can be found at: + +

+ +

Numerous other filters, drivers, tutorials, etc. have been made available +on the CUPS bazaar, available at: + +

+ +

Finally, our own ESP Print Pro software uses CUPS to provide drivers +for over 2300 printers and can be found at: + +

+ +

Operating Systems Using CUPS

+ +

One of our goals has always been to get as many UNIX/Linux +distributions using CUPS as possible. Debian is currently providing +CUPS as part of its stable distribution, and many other distributions +are considering it in their next releases. + +

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. CUPS 1.1 +adds many new features that make it an even better choice for printing +under UNIX. + +

Who to Contact

+ +

For more information on CUPS please contact us at: + +

    +Attn: CUPS Information
    +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.1
+ +
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
+ +
RFC2616
+ +
Hypertext Transfer Protocol -- HTTP/1.1
+ +
+ +

Trademarks

+ +

The Common UNIX Printing System, CUPS, and the CUPS logo are the +trademark property 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 0000000000..581ecd9d7a Binary files /dev/null and b/doc/overview.pdf differ diff --git a/doc/printing-overview.shtml b/doc/printing-overview.shtml new file mode 100644 index 0000000000..1682dae7f4 --- /dev/null +++ b/doc/printing-overview.shtml @@ -0,0 +1,125 @@ +

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 Mac OS, UNIX has no standard interface or +system in place for supporting printers. Among the solutions currently +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 and operating systems 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. + +

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. IPP has been embraced by dozens of printer and +printer server manufacturers and is supported by Microsoft Windows +2000. + +

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 capable and secure printing +solution than older ones. + +

IPP is layered on top of the Hyper-Text Transport Protocol ("HTTP") +which is the basis of web servers on the Internet. This allows users +to view documentation, check status information on a printer or server, +and manage their printers, classes, and jobs using their web browser. + +

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

Jobs

+ +

Each file or set of files 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. + +

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 Processor ("RIP") filters that convert +PostScript or image files into bitmaps that can be sent to a raster +printer. + +

Backends

+ +

Backends perform the most important task of all - they send the +filtered print data to the printer. + +

CUPS provides backends for printing over parallel, serial, and USB +ports, and over the network via the IPP, JetDirect (AppSocket), and +Line Printer Daemon ("LPD") protocols. Additional backends are +available in network service packages such as the SMB backend +included with the popular SAMBA software. + +

Backends are also used to determine the available devices. On +startup each backend is asked for a list of devices it supports, +and any information that is available. This allows the parallel +backend to tell CUPS that an EPSON Stylus Color 600 printer is +attached to parallel port 1, for example. + +

Printer Drivers

+ +

Printer drivers in CUPS consist of one of more filters specific to a +printer. CUPS includes sample printer drivers for Hewlett-Packard +LaserJet and DeskJet printers and EPSON 9-pin, 24-pin, Stylus Color, +and Stylus Photo printers. While these drivers do not generate optimal +output for the different printer models, they do provide basic printing +and 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. Users may then select a local printer by +name or a remote printer using "name@server". + +

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 go down! diff --git a/doc/references.shtml b/doc/references.shtml new file mode 100644 index 0000000000..4b4930e574 --- /dev/null +++ b/doc/references.shtml @@ -0,0 +1,42 @@ +

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-IPP-1.1: CUPS Implementation of IPP +
  • CUPS-SAM-1.1.x: CUPS Software Administrators Manual +
  • CUPS-SDD-1.1: CUPS Software Design Description +
  • CUPS-SPM-1.1.x: 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: CUPS Software Version Description +
+ +

Other Documents

+ +

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

diff --git a/doc/sam.html b/doc/sam.html new file mode 100644 index 0000000000..18e01af8bb --- /dev/null +++ b/doc/sam.html @@ -0,0 +1,5192 @@ + + + + CUPS Software Administrators Manual + + + + + + + +

+

CUPS Software Administrators Manual


+CUPS-SAM-1.1.5
+Easy Software Products
+Copyright 1997-2000, All Rights Reserved
+
+
+

Table of Contents

+

+

Preface + +1 - Printing System Overview + +2 - Building and +Installing CUPS + +3 - Printer Management + +4 - Printer Classes + +5 - Client Setup + +6 - Printing System +Management + +7 - Printing with Other +Systems + +A - Software License Agreement + +B - Common Network Settings + + +C - Printer Drivers + +D - List of Files +

+

E - Troubleshooting Common +Problems + +
+

Preface

+

This software administrators manual provides printer +administration information for the Common UNIX +Printing SystemTM ("CUPSTM"), +version 1.1.5.

+

System Overview

+

CUPS provides a portable printing layer for +UNIX®-based 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 ("IPP") +as the basis for managing print jobs and +queues. The Line Printer Daemon ("LPD") Server +Message Block ("SMB"), and AppSocket (a.k.a. +JetDirect) protocols are also supported with reduced +functionality. CUPS adds network printer browsing and +PostScript Printer Description ("PPD") based printing +options to support real-world printing under UNIX.

+

CUPS also includes a customized version of GNU +Ghostscript (currently based off GNU Ghostscript +5.50) and an image file RIP that are used to +support non-PostScript printers. Sample drivers for +HP and EPSON printers are included that use +these filters.

+ + + +

Document Overview

+

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

+ +

Notation Conventions

+

Various font and syntax conventions are used in +this guide. Examples and their meanings and uses +are explained below: +

+ + + + + + + + + + + + +
Example   Description
 
lpstat +

lpstat(1)
   The names +of commands; the first mention of a command or + function in a chapter is followed by a manual +page section number.
 
/var +

/usr/share/cups/data/testprint.ps
    +File and directory names.
 
Request ID is Printer-123 +   Screen output.
 
lp -d printer filename +ENTER   Literal user input; +special keys like ENTER are in ALL +CAPS.
 
12.3   Numbers in +the text are written using the period (.) to +indicate the decimal point.
+
+ + +

+

Abbreviations

+ The following abbreviations are used throughout this +manual: +
    +
    +
    kb
    +
    Kilobytes, or 1024 bytes +

     
    +
    Mb
    +
    Megabytes, or 1048576 bytes +

     
    +
    Gb
    +
    Gigabytes, or 1073741824 bytes +

     
    +
    +
+

Other References

+
    +
    +
    CUPS Software Programmers Manual
    +
    A programmer guide for interfacing with and/or +extending the CUPS software. +

     
    +
    CUPS Software Users Manual
    +
    An end-user guide for using the CUPS software. +

     
    +
    +
+

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 Mac OS, UNIX +has no standard interface or system in place +for supporting printers. Among the solutions +currently 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 and operating systems 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.

+

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. IPP +has been embraced by dozens of printer and +printer server manufacturers and is supported by +Microsoft Windows 2000.

+

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 capable and secure printing solution than +older ones.

+

IPP is layered on top of the Hyper-Text +Transport Protocol ("HTTP") which is the basis of +web servers on the Internet. This allows users +to view documentation, check status information on +a printer or server, and manage their printers, +classes, and jobs using their web browser.

+

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

+

Jobs

+

Each file or set of files 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.

+

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 Processor ("RIP") filters +that convert PostScript or image files into +bitmaps that can be sent to a raster printer. +

+

Backends

+

Backends perform the most important task of all +- they send the filtered print data to the +printer.

+

CUPS provides backends for printing over parallel, +serial, and USB ports, and over the network via +the IPP, JetDirect (AppSocket), and Line Printer +Daemon ("LPD") protocols. Additional backends are +available in network service packages such as the +SMB backend included with the popular SAMBA +software.

+

Backends are also used to determine the +available devices. On startup each backend is +asked for a list of devices it supports, and +any information that is available. This allows the +parallel backend to tell CUPS that an EPSON +Stylus Color 600 printer is attached to parallel +port 1, for example.

+

Printer Drivers

+

Printer drivers in CUPS consist of one of +more filters specific to a printer. CUPS includes +sample printer drivers for Hewlett-Packard LaserJet +and DeskJet printers and EPSON 9-pin, 24-pin, +Stylus Color, and Stylus Photo printers. While +these drivers do not generate optimal output for +the different printer models, they do provide +basic printing and 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. Users may then select a local printer +by name or a remote printer using "name@server". +

+

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

+

This section describes how to compile and +install CUPS on your system from the source +code.

+

Requirements

+

You'll need ANSI-compliant C and C++ compilers +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 compile and 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 +significantly 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. Type +the following command to configure CUPS for your +system:

+
    +
    +./configure ENTER
    +
    +
+

The default installation will put the CUPS +software in the /etc, /usr, +and /var directories on your system, which +will overwrite any existing printing commands on +your system. Use the --prefix option to +install the CUPS software in another location:

+
    +
    +./configure --prefix=/some/directory 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, +CXXFLAGS, and LDFLAGS environment +variables prior to running configure:

+
    +
    +setenv CFLAGS "-I/some/directory" ENTER
    +setenv CXXFLAGS "-I/some/directory" ENTER
    +setenv LDFLAGS "-L/some/directory" ENTER
    +./configure ... ENTER
    +
    +
+

or:

+
    +
    +CFLAGS="-I/some/directory"; export CFLAGS ENTER
    +CXXFLAGS="-I/some/directory"; export CXXFLAGS ENTER
    +LDFLAGS="-L/some/directory"; export LDFLAGS ENTER
    +./configure ... ENTER
    +
    +
+

To enable support for encryption, you'll also +want to add the "--enable-ssl" option:

+
    +
    +./configure --enable-ssl
    +
    +
+

SSL and TLS support require the OpenSSL +library, available at:

+ +

Once you have configured things, just type:

+
    +
    +make ENTER
    +
    +
+

to build the software. + +

+

Installing the Software

+

Use the "install" target to install the +software:

+
    +
    +make install ENTER
    +
    +
+
+ + +
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 +reinstall the old printing system from your +operating system CDs.

+
+
+

Running the Software

+

Once you have installed the software you can +start the CUPS server by typing:

+
    +
    +/usr/sbin/cupsd ENTER
    +
    +
+ + + +

Installing a Binary Distribution

+

CUPS comes in a variety of binary distribution +formats. Easy Software Products provides binaries in +TAR format with installation and removal scripts +("portable" distributions), and in RPM and DPKG +formats for Red Hat and Debian-based distributions. + Portable distributions are available for all +platforms, while the RPM and DPKG distributions +are only available for Linux. +

+ + +
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/or reinstall the old printing system from +your operating system CDs.

+
+
+

+

Installing a Portable +Distribution

+

To install the CUPS software from a portable +distribution 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. + +

+

Installing an RPM Distribution

+

To install the CUPS software from an RPM +distribution you will need to be logged in as +root; doing an su is good enough. +Once you are the root user, run RPM with:

+
    +
    +rpm -e lpr
    +rpm -i cups-1.1-linux-M.m.n-intel.rpm ENTER
    +
    +
+

After a short delay the CUPS software will +be installed and the scheduler will be started +automatically.

+

Installing an Debian Distribution +

+

To install the CUPS software from a Debian +distribution you will need to be logged in as +root; doing an su is good enough. +Once you are the root user, run dpkg with:

+
    +
    +dpkg -i cups-1.1-linux-M.m.n-intel.deb ENTER
    +
    +
+

After a short delay the CUPS software will +be installed and the scheduler will be started +automatically.

+

3 - Printer +Management

+

This chapter describes how to add your first +printer and how to manage your printers.

+

The Basics

+

Each printer queue has a name associated with +it; the printer name must start with a letter +and can contain up to 127 letters, numbers, and +the underscore (_). Case is not significant, e.g. +"PRINTER", "Printer", and "printer" are considered to +be the same name.

+

Printer queues also have a device associated +with them. The device can be a parallel port, +a network interface, and so forth. Devices within +CUPS use Uniform Resource Identifiers ("URIs") which +are a more general form of Uniform Resource +Locators ("URLs") that are used in your web +browser. For example, the first parallel port in +Linux usually uses a device URI of +parallel:/dev/lp1. + +

+

You can see a complete list of supported +devices by running the lpinfo(8) command: +

+
    +
    +lpinfo -v ENTER
    +file file
    +network socket
    +network http
    +network ipp
    +network lpd
    +direct parallel:/dev/lp1
    +serial serial:/dev/ttyS1?baud=115200
    +serial serial:/dev/ttyS2?baud=115200
    +direct usb:/dev/usb/lp0
    +network smb
    +
    +
+

The -v option specifies that you want +a list of available devices. The first word in +each line is the type of device (direct, file, +network, or serial) and is followed by the +device URI or method name for that device. File +devices have device URIs of the form +file:/directory/filename while network devices use +the more familiar method://server or +method://server/path format.

+

Finally, printer queues usually have a PostScript +Printer Description ("PPD") file associated with +them. PPD files describe the capabilities of each +printer, the page sizes supported, etc., and are +used for PostScript and non-PostScript printers. CUPS +includes PPD files for HP LaserJet, HP DeskJet, +EPSON 9-pin, EPSON 24-pin, and EPSON Stylus +printers.

+

Adding Your First Printer

+

CUPS provides two methods for adding printers: +a command-line program called lpadmin(8) + and a Web interface. The lpadmin + command allows you to perform most printer +administration tasks from the command-line and is +located in /usr/sbin. The Web interface +is located at:

+ +

and steps you through printer configuration. If +you don't like command-line interfaces, try the +Web interface instead.

+

Adding Your First Printer from the +Command-Line

+

Run the lpadmin command with the +-p option to add a printer to CUPS:

+
    +
    +/usr/sbin/lpadmin -p printer -E -v device -m ppd ENTER
    +
    +
+

For an HP DeskJet printer connected to the +parallel port this would look like:

+
    +
    +/usr/sbin/lpadmin -p DeskJet -E -v parallel:/dev/lp1 -m deskjet.ppd ENTER
    +
    +
+

Similarly, an HP LaserJet printer using a +JetDirect network interface at IP address 11.22.33.44 +would be added with the command:

+
    +
    +/usr/sbin/lpadmin -p LaserJet -E -v socket://11.22.33.44 -m laserjet.ppd ENTER
    +
    +
+

As you can see, deskjet.ppd and +laserjet.ppd are the PPD files for the HP +DeskJet and HP LaserJet drivers included with +CUPS. You'll find a complete list of PPD files +and the printers they will work with in +Appendix C, "Printer Drivers".

+

Adding Your First Printer from the +Web

+

The CUPS web server provides a user-friendly +"wizard" interface for adding your printers. Rather +than figuring out which device URI and PPD file +to use, you can instead click on the +appropriate listings and fill in some simple +information. Enter the following URL in your web +browser to begin:

+ +

Click on the Add Printer button to +add a printer.

+

Managing Printers from the Command-Line +

+

The lpadmin command enables you to +perform most printer administration tasks from the +command-line. You'll find lpadmin in the +/usr/sbin directory.

+

Adding and Modifying Printers

+

Run the lpadmin command with the +-p option to add or modify a printer:

+
    +
    +/usr/sbin/lpadmin -p printer options ENTER
    +
    +
+

The options arguments can be any of the +following:

+
    +
    +
    -c class
    +
    Adds the named printer to printer class +class. If the class does not exist then +it is created.
    +
    -i interface
    +
    Copies the named interface script to +the printer. Interface scripts are used by System +V printer drivers. Since all filtering is +disabled when using an interface script, scripts + generally should not be used unless there is +no other driver for a printer.
    +
    -m model
    +
    Specifies a standard printer driver which is +usually a PPD file. A list of all available +models can be displayed using the lpinfo + command with the -m option. A list +of printer drivers included with CUPS can be +found in Appendix C, "Printer +Drivers".
    +
    -r class
    +
    Removes the named printer from printer class +class. If the resulting class becomes empty +then it is removed.
    +
    -v device-uri
    +
    Sets the device for communicating with the +printer. If a job is currently printing on the +named printer then the job will be restarted +and sent to the new device.
    +
    -D info
    +
    Provides a textual description of the printer, +e.g. "John's Personal Printer".
    +
    -E
    +
    Enables the printer and accepts job. This +option is equivalent to running the enable(1) + and accept(8) commands on the +printer.
    +
    -L location
    +
    Provides a textual location for the printer, +e.g. "Computer Lab 5".
    +
    -P ppd-file
    +
    Specifies a local PPD file for the printer +driver.
    +
    +
+

Deleting Printers

+

Run the lpadmin command with the +-x option to delete a printer:

+
    +
    +/usr/sbin/lpadmin -x printer ENTER
    +
    +
+

Setting the Default Printer

+

Run the lpadmin command with the +-d option to set a default printer:

+
    +
    +/usr/sbin/lpadmin -d printer ENTER
    +
    +
+

The default printer can be overridden by the +user using the lpoptions(1) command.

+

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 queued 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/sbin/accept printer ENTER
    +/usr/sbin/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.

+

Managing Printers from the Web

+

The Web interface is located at:

+ +

From there you can perform all printer +management tasks with a few simple mouse clicks. +

+

4 - Printer Classes +

+

This chapter describes what printer classes are +and how to manage them.

+

The Basics

+

CUPS provides collections of printers called +printer classes. Jobs sent to a class are +forwarded to the first available printer in the +class. Classes can themselves be members of other +classes, so it is possible for you to define +very large, distributed printer classes for +high-availability printing.

+

CUPS also supports implicit classes. +Implicit classes work just like printer classes, +but they are created automatically based upon the +available printers and classes on the network. +This allows you to setup multiple print servers +with identical printer configurations and have the +client machines send their print jobs to the +first available server. If one or more servers +go down, the jobs are automatically redirected to +the servers that are running, providing fail-safe +printing.

+

Managing Printer Classes from the +Command-Line

+

Run the lpadmin command with the +-p and -c options to add a +printer to a class:

+
    +
    +/usr/sbin/lpadmin -p printer -c class ENTER
    +
    +
+

The class is created automatically if it +doesn't exist. To remove a printer from a class +use the -r option:

+
    +
    +/usr/sbin/lpadmin -p printer -r class ENTER
    +
    +
+

To remove the entire class just use the +-x option:

+
    +
    +/usr/sbin/lpadmin -x class ENTER
    +
    +
+

Managing Printer Classes from the Web +Interface

+

The Web interface is located at:

+ +

The Add Class and Modify Class + interfaces provide a list of available printers; +click on the printers of interest to add them +to the class.

+

Implicit Classes

+

A noted earlier, implicit classes are created +automatically from the available network printers and +classes. To disable this functionality, set the +ImplicitClasses directive to Off + in the cupsd.conf file. You will find +more information on doing this in +Chapter 6, "Printing System Management".

+

5 - Client Setup +

+

This chapter discusses several ways to configure +CUPS clients for printing.

+

The Basics

+

A client is any machine that sends print +jobs to another machine for final printing. +Clients can also be servers if they communicate +directly with any printers of their own.

+

CUPS supports several methods of configuring +client machines:

+ +

Manual Configuration of Print +Queues

+

The most tedious method of configuring client +machines is to configure each remote queue by +hand using the lpadmin command:

+
    +
    +lpadmin -p printer -E -v ipp://server/printers/printer ENTER
    +
    +
+

The printer name is the name of +the printer on the server machine. The server + name is the hostname or IP address of +the server machine. Repeat the lpadmin + command for each remote printer you wish to +use.

+

Specifying a Single Server for +Printing

+

CUPS can be configured to run without a +local spooler and send all jobs to a single +server. However, if that server goes down then +all printing will be disabled. Use this +configuration only as absolutely needed.

+

The default server is normally "localhost". To +override the default server create a file named +/etc/cups/client.conf and add a line reading:

+
    +
    +ServerName server
    +
    +
+

to the file. The server name can be +the hostname or IP address of the default +server.

+

The default server can also be customized on +a per-user basis. To set a user-specific server +create a file named ~/.cupsrc and add a +line reading:

+
    +
    +ServerName server
    +
    +
+

to the file. The server name can be +the hostname or IP address of the default +server.

+

Automatic Configuration of Print +Queues

+

CUPS supports automatic client configuration of +printers on the same subnet. To configure printers +on the same subnet, do nothing. Each +client should see the available printers within 30 +seconds automatically. The printer and class lists +are updated automatically as printers and servers +are added or removed.

+

If you want to see printers on other subnets +as well, use the BrowsePoll + directive as described next.

+

Specifying Multiple Servers for +Printing

+

If you have CUPS servers on different subnets, +then you should configure CUPS to poll those +servers. Polling provides the benefits of automatic +configuration without significant configuration on the +clients, and multiple clients on the same subnet +can share the same configuration information.

+

Polling is enabled by specifying one or more BrowsePoll directives in +the /etc/cups/cupsd.conf file. For information +on making these changes, see +Chapter 6, "Printing System Management".

+

6 - Printing +System Management

+

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

+

The Basics

+

Several text files are used to configure CUPS. +All of the server configuration files are located +in the /etc/cups directory:

+
    +
    + + +
    classes.conf
    +
    This file contains information on each printer +class. Normally you manipulate this file using +the lpadmin command or the Web +interface. +

      + +
    +
    client.conf
    +
    This file provides the default server name for +client machines. See Chapter 5, +"Client Setup" for more information. +

      + +
    +
    cupsd.conf
    +
    This file controls how the CUPS server ( +/usr/sbin/cupsd) operates and is normally +edited by hand. +

      + +
    +
    mime.convs
    +
    This file contains a list of standard file +conversion filters and their costs. You normally +do not edit this file. +

      + +
    +
    mime.types
    +
    This file contains a list of standard file +formats and how to recognize them. You normally +do not edit this file. +

      + +
    +
    printers.conf
    +
    This file contains information on each printer. +Normally you manipulate this file using the +lpadmin command or the Web Interface. +

     
    +
    +
+

Restarting the CUPS Server

+

Once you have made a change to a +configuration file you need to restart the CUPS +server by sending it a HUP signal or +using the supplied initialization script. The CUPS +distributions install the script in the init.d + directory with the name cups. The +location varies based upon the operating system:

+
    +
    +/etc/rc.d/init.d/cups restart ENTER
    +/etc/init.d/cups restart ENTER
    +/sbin/init.d/cups restart ENTER
    +
    +
+

Changing the Server Configuration

+

The /etc/cups/cupsd.conf file contains +configuration directives that control how the +server functions. Each directive is listed on a +line by itself followed by its value. Comments +are introduced using the number sign ("#") +character at the beginning of a line. Since the +server configuration file consists of plain text, +you can use your favorite text editor to make +changes to it. + +

+

Server Directives

+

The cupsd.conf file contains many +directives that determine how the server operates:

+ + + + +

AccessLog

+
+

Examples

+
    +
    +AccessLog /var/log/cups/access_log
    +AccessLog /var/log/cups/access_log-%s
    +AccessLog syslog
    +
    +
+

Description

+

The AccessLog directive sets the name +of the access log file. If the filename is +not absolute then it is assumed to be relative +to the ServerRoot + directory. The access log file is stored in +"common log format" and can be used by any +web access reporting tool to generate a report +on CUPS server activity.

+

The server name can be included in the +filename by using %s in the name.

+

The special name "syslog" can be used to +send the access information to the system log +instead of a plain file.

+

The default access log file is +/var/log/cups/access_log. + +

+

Allow

+
+

Examples

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

Description

+

The Allow directive specifies a +hostname, IP address, or network that is allowed +access to the server. 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 +mmnetmask
00.0.0.0 +8255.0.0.0
1128.0.0.0 +16255.255.0.0
2192.0.0.0 +24255.255.255.0
...... +32255.255.255.255
+
+

+

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

+

AuthClass

+
+

Examples

+
    +
    +AuthClass Anonymous
    +AuthClass User
    +AuthClass System
    +AuthClass Group
    +
    +
+

Description

+

The AuthClass directive defines what +level of authentication 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.
  • +
  • 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

+
+

Examples

+
    +
    +AuthGroupName mygroup
    +AuthGroupName lp
    +
    +
+

Description

+

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

+

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

+

AuthType

+
+

Examples

+
    +
    +AuthType None
    +AuthType Basic
    +AuthType Digest
    +
    +
+

Description

+

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.
  • +
  • Digest - Digest authentication should +be performed using the /etc/cups/passwd.md5 + file.
  • +
+

When using Basic or Digest + authentication, clients connecting through the +localhost interface can also authenticate using certificates.

+

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

+

AutoPurgeJobs

+
+

Examples

+
    +
    +AutoPurgeJobs Yes
    +AutoPurgeJobs No
    +
    +
+

Description

+

The AutoPurgeJobs directive specifies +whether or not to purge completed jobs once +they are no longer required for quotas. This +option has no effect if quotas are not enabled. +The default setting is No. + +

+

BrowseAddress

+
+

Examples

+
    +
    +BrowseAddress 255.255.255.255:631
    +BrowseAddress 192.0.2.255:631
    +BrowseAddress host.domain.com:631
    +
    +
+

Description

+

The BrowseAddress directive specifies an +address to send browsing information to. Multiple +BrowseAddress directives can be specified to +send browsing information to different networks or +systems.

+

The default address is 255.255.255.255:631 + which will broadcast the information to all +networks the server is connected to. +

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

+
+
+ + +

+

BrowseAllow

+
+

Examples

+
    +
    +BrowseAllow from all
    +BrowseAllow from none
    +BrowseAllow from 192.0.2
    +BrowseAllow from 192.0.2.0/24
    +BrowseAllow from 192.0.2.0/255.255.255.0
    +BrowseAllow from *.domain.com
    +
    +
+

Description

+

The BrowseAllow directive specifies a +system or network to accept browse packets from. +The default is to accept browse packets from +all hosts.

+

Host and domain name matching require that you +enable the HostNameLookups + directive.

+

IP address matching supports exact matches, +partial addresses that match networks using netmasks +of 255.0.0.0, 255.255.0.0, and 255.255.255.0, or +network addresses using the specified netmask or +bit count. + +

+

BrowseDeny

+
+

Examples

+
    +
    +BrowseDeny from all
    +BrowseDeny from none
    +BrowseDeny from 192.0.2
    +BrowseDeny from 192.0.2.0/24
    +BrowseDeny from 192.0.2.0/255.255.255.0
    +BrowseDeny from *.domain.com
    +
    +
+

Description

+

The BrowseDeny directive specifies a +system or network to reject browse packets from. +The default is to deny browse packets from no +hosts.

+

Host and domain name matching require that you +enable the HostNameLookups + directive.

+

IP address matching supports exact matches, +partial addresses that match networks using netmasks +of 255.0.0.0, 255.255.0.0, and 255.255.255.0, or +network addresses using the specified netmask or +bit count. + +

+

BrowseOrder

+
+

Examples

+
    +
    +BrowseOrder allow,deny
    +BrowseOrder deny,allow
    +
    +
+

Description

+

The BrowseOrder directive specifies the +order of allow/deny processing. The default order +is deny,allow:

+
    +
  • allow,deny - Browse packets are +accepted unless specifically denied.
  • +
  • deny,allow - Browse packets are +rejected unless specifically allowed.
  • +
+ + + +

BrowseInterval

+
+

Examples

+
    +
    +BrowseInterval 0
    +BrowseInterval 30
    +
    +
+

Description

+

The BrowseInterval directive specifies the +maximum amount of time between browsing updates. +Specifying a value of 0 seconds disables outgoing +browse updates but allows a server to receive +printer information from other hosts.

+

The BrowseInterval value should always +be less than the +BrowseTimeout value. Otherwise printers and +classes will disappear from client systems between +updates. + +

+

BrowsePoll

+
+

Examples

+
    +
    +BrowsePoll 192.0.2.2:631
    +BrowsePoll host.domain.com:631
    +
    +
+

Description

+

The BrowsePoll directive polls a server +for available printers once every +BrowseInterval seconds. Multiple +BrowsePoll directives can be specified to poll +multiple servers.

+

If BrowseInterval is set to 0 then +the server is polled once every 30 seconds. + + +

+

BrowsePort

+
+

Examples

+
    +
    +BrowsePort 631
    +BrowsePort 9999
    +
    +
+

Description

+

The BrowsePort directive specifies the +UDP port number used for browse packets. The +default port number is 631. +

+ + +
NOTE: +

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

+
+
+ + +

+

BrowseRelay

+
+

Examples

+
    +
    +BrowseRelay 193.0.2.1 192.0.2.255
    +BrowseRelay 193.0.2.0/255.255.255.0 192.0.2.255
    +BrowseRelay 193.0.2.0/24 192.0.2.255
    +BrowseRelay *.domain.com 192.0.2.255
    +BrowseRelay host.domain.com 192.0.2.255
    +
    +
+

Description

+

The BrowseRelay directive specifies source +and destination addresses for relaying browsing +information from one host or network to another. +Multiple BrowseRelay directives can be +specified as needed.

+

BrowseRelay is typically used on systems +that bridge multiple subnets using one or more +network interfaces. It can also be used to +relay printer information from polled servers with +the line:

+
    +
    +BrowseRelay 127.0.0.1 255.255.255.255
    +
    +
+

This effectively provides access to printers on +a WAN for all clients on the LAN(s). + +

+

BrowseShortNames

+
+

Examples

+
    +
    +BrowseShortNames Yes
    +BrowseShortNames No
    +
    +
+

Description

+

The BrowseShortNames directive specifies +whether or not short names are used for remote +printers when possible. Short names are just the +remote printer name, without the server ("printer"). +If more than one remote printer is detected +with the same name, the printers will have long +names ("printer@server1", "printer@server2".)

+

The default value for this option is Yes +. + +

+

BrowseTimeout

+
+

Examples

+
    +
    +BrowseTimeout 300
    +BrowseTimeout 60
    +
    +
+

Description

+

The BrowseTimeout directive sets the +timeout for printer or class information that is +received in browse packets. Once a printer or +class times out it is removed from the list +of available destinations.

+

The BrowseTimeout value should always be +greater than the BrowseInterval + value. Otherwise printers and classes will +disappear from client systems between updates. + +

+

Browsing

+
+

Examples

+
    +
    +Browsing On
    +Browsing Off
    +
    +
+

Description

+

The Browsing directive controls whether +or not network printer browsing is enabled. The +default setting is On. +

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

+
+
+ + +

+

DataDir

+
+

Examples

+
    +
    +DataDir /usr/share/cups
    +
    +
+

Description

+

The DataDir directive sets the directory +to use for data files. + +

+

DefaultCharset

+
+

Examples

+
    +
    +DefaultCharset utf-8
    +DefaultCharset iso-8859-1
    +DefaultCharset windows-1251
    +
    +
+

Description

+

The DefaultCharset directive sets the +default character set to use for client +connections. The default character set is utf-8 + but is overridden by the character set for +the language specified by the client or the +DefaultLanguage directive. + +

+

DefaultLanguage

+
+

Examples

+
    +
    +DefaultLanguage de
    +DefaultLanguage en
    +DefaultLanguage es
    +DefaultLanguage fr
    +DefaultLanguage it
    +
    +
+

Description

+

The DefaultLanguage directive specifies the +default language to use for client connections. +Setting the default language also sets the default +character set if a language localization file +exists for it. The default language is "en" +for English. + +

+

Deny

+
+

Examples

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

Description

+

The Deny directive specifies a hostname, +IP address, or network that is allowed access +to the server. 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 +mmnetmask
00.0.0.0 +8255.0.0.0
1128.0.0.0 +16255.255.0.0
2192.0.0.0 +24255.255.255.0
...... +32255.255.255.255
+
+

+

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

+

DocumentRoot

+
+

Examples

+
    +
    +DocumentRoot /usr/share/doc/cups
    +DocumentRoot /foo/bar/doc/cups
    +
    +
+

Description

+

The DocumentRoot directive specifies the +location of web content for the HTTP server in +CUPS. If an absolute path is not specified then +it is assumed to be relative to the +ServerRoot directory. The default +directory is /usr/share/doc/cups.

+

Documents are first looked up in a +sub-directory for the primary language requested by +the client (e.g. /usr/share/doc/cups/fr/...) +and then directly under the DocumentRoot + directory (e.g. /usr/share/doc/cups/...), so +it is possible to localize the web content by +providing subdirectories for each language needed. + + +

+

ErrorLog

+
+

Examples

+
    +
    +ErrorLog /var/log/cups/error_log
    +ErrorLog /var/log/cups/error_log-%s
    +ErrorLog syslog
    +
    +
+

Description

+

The ErrorLog directive sets the name +of the error log file. If the filename is +not absolute then it is assumed to be relative +to the ServerRoot + directory. The default error log file is +/var/log/cups/error_log.

+

The server name can be included in the +filename by using %s in the name.

+

The special name "syslog" can be used to +send the error information to the system log +instead of a plain file. + +

+

FilterLimit

+
+

Examples

+
    +
    +FilterLimit 0
    +FilterLimit 200
    +FilterLimit 1000
    +
    +
+

Description

+

The FilterLimit directive sets the +maximum cost of all running job filters. It can +be used to limit the number of filter programs +that are run on a server to minimize disk, +memory, and CPU resource problems. A limit of 0 +disables filter limiting.

+

An average print to a non-PostScript printer +needs a filter limit of about 200. A PostScript +printer needs about half that (100). Setting the +limit below these thresholds will effectively limit +the scheduler to printing a single job at any +time.

+

The default limit is 0. + +

+

Group

+
+

Examples

+
    +
    +Group sys
    +Group system
    +Group root
    +
    +
+

Description

+

The Group directive specifies the UNIX +group that filter and CGI programs run as. The +default group is sys, system +, or root depending on the operating +system. + +

+

HostNameLookups

+
+

Examples

+
    +
    +HostNameLookups On
    +HostNameLookups Off
    +
    +
+

Description

+

The HostNameLookups directive controls +whether or not CUPS looks up the hostname for +connecting clients. The default is Off + to avoid the potential server performance problems +with hostname lookups. Turn this option On + only if absolutely required. + +

+

ImplicitClasses

+
+

Examples

+
    +
    +ImplicitClasses On
    +ImplicitClasses Off
    +
    +
+

Description

+

The ImplicitClasses directive controls +whether implicit classes are created based upon +the available network printers and classes. The +default setting is On but is +automatically turned Off if +Browsing is turned Off. + + +

+

KeepAlive

+
+

Examples

+
    +
    +KeepAlive On
    +KeepAlive Off
    +
    +
+

Description

+

The KeepAlive directive controls whether +or not to support persistent HTTP connections. The +default is On.

+

HTTP/1.1 clients automatically support persistent +connections, while HTTP/1.0 clients must specifically +request them using the Keep-Alive attribute +in the Connection: field of each +request. + +

+

KeepAliveTimeout

+
+

Examples

+
    +
    +KeepAliveTimeout 60
    +KeepAliveTimeout 30
    +
    +
+

Description

+

The KeepAliveTimeout directive controls how +long a persistent HTTP connection will remain open +after the last request. The default is 60 +seconds. + +

+

Listen

+
+

Examples

+
    +
    +Listen 127.0.0.1:631
    +Listen 192.0.2.1:631
    +
    +
+

Description

+

The Listen directive specifies a network +address and port to listen for connections. +Multiple Listen directives can be provided +to listen on multiple addresses.

+

Description

+

The Listen directive is similar to +the Port directive but +allows you to restrict access to specific +interfaces or networks. + +

+

Location

+
+

Examples

+
    +
    +<Location />
    +...
    +</Location>
    +
    +<Location /admin>
    +...
    +</Location>
    +
    +<Location /printers/name>
    +...
    +</Location>
    +
    +
+

Description

+

The Location directive specifies access +control and authentication options for the specified +HTTP resource or path. More information can be +found later in this chapter in +"Printing System Security". + +

+

LogLevel

+
+

Examples

+
    +
    +LogLevel debug
    +LogLevel error
    +LogLevel info
    +LogLevel none
    +LogLevel warn
    +
    +
+

Description

+

The LogLevel directive specifies the +level of logging for the +ErrorLog file. The following values are +recognized:

+
    +
  • debug - Log everything.
  • +
  • info - Log all requests and state +changes (default).
  • +
  • warn - Log errors and warnings.
  • +
  • error - Log only errors.
  • +
  • none - Log nothing.
  • +
+ + + +

MaxClients

+
+

Examples

+
    +
    +MaxClients 100
    +MaxClients 1024
    +
    +
+

Description

+

The MaxClients directive controls the +maximum number of simultaneous clients that will +be allowed by the server. The default is 100 +clients. +

+ + +
NOTE: +

Since each print job requires a file descriptor +for the status pipe, the CUPS server internally +limits the MaxClients value to 1/3 of +the available file descriptors to avoid possible +problems when printing large numbers of jobs.

+
+
+ + +

+

MaxJobs

+
+

Examples

+
    +
    +MaxJobs 100
    +MaxJobs 9999
    +MaxJobs 0
    +
    +
+

Description

+

The MaxJobs directive controls the +maximum number of jobs that are kept in memory. +Once the number of jobs reaches the limit, the +oldest completed job is automatically purged from +the system to make room for the new one. If +all of the known jobs are still pending or +active then the new job will be rejected.

+

Setting the maximum size to 0 disables this +functionality. The default setting is 0. + +

+

MaxLogSize

+
+

Examples

+
    +
    +MaxLogSize 1048576
    +MaxLogSize 1m
    +MaxLogSize 0
    +
    +
+

Description

+

The MaxLogSize directive controls the +maximum size of each log file. Once a log +file reaches or exceeds the maximum size it is +closed and renamed to filename.O. This +allows you to rotate the logs automatically. The +default size is 1048576 bytes (1MB).

+

Setting the maximum size to 0 disables log +rotation. + +

+

MaxRequestSize

+
+

Examples

+
    +
    +MaxRequestSize 10485760
    +MaxRequestSize 10m
    +MaxRequestSize 0
    +
    +
+

Description

+

The MaxRequestSize directive controls the +maximum size of print files, IPP requests, and +HTML form data in HTTP POST requests. The +default limit is 0 which disables the limit +check. + +

+

Order

+
+

Examples

+
    +
    +Order Allow,Deny
    +Order Deny,Allow
    +
    +
+

Description

+

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

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

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

+

PageLog

+
+

Examples

+
    +
    +PageLog /var/log/cups/page_log
    +PageLog /var/log/cups/page_log-%s
    +PageLog syslog
    +
    +
+

Description

+

The PageLog directive sets the name +of the page log file. If the filename is not +absolute then it is assumed to be relative to +the ServerRoot directory. +The default page log file is +/var/log/cups/page_log.

+

The server name can be included in the +filename by using %s in the name.

+

The special name "syslog" can be used to +send the page information to the system log +instead of a plain file. + +

+

Port

+
+

Examples

+
    +
    +Port 631
    +Port 80
    +
    +
+

Description

+

The Port directive specifies a port +to listen on. Multiple Port lines can +be specified to listen on multiple ports. The +default port is 631.

+

Description

+

The Port directive will listen for +connections on all network interfaces. To limit +connections to a single interface use the +Listen directive with the interface +address. + +

+

PreserveJobHistory

+
+

Examples

+
    +
    +PreserveJobHistory On
    +PreserveJobHistory Off
    +
    +
+

Description

+

The PreserveJobHistory directive controls +whether the history of completed, cancelled, or +aborted print jobs is stored on disk.

+

A value of On (the default) preserves +job information until the administrator purges it +with the cancel command.

+

A value of Off removes the job +information as soon as each job is completed, +cancelled, or aborted. + +

+

PreserveJobFiles

+
+

Examples

+
    +
    +PreserveJobFiles On
    +PreserveJobFiles Off
    +
    +
+

Description

+

The PreserveJobFiles directive controls +whether the document files of completed, cancelled, +or aborted print jobs are stored on disk.

+

A value of On preserves job files +until the administrator purges them with the +cancel command. Jobs can be restarted (and +reprinted) as desired until they are purged.

+

A value of Off (the default) removes +the job files as soon as each job is +completed, cancelled, or aborted. + +

+

Printcap

+
+

Examples

+
    +
    +Printcap
    +Printcap /etc/printcap
    +
    +
+

Description

+

The Printcap directive controls whether +or not a printcap file is automatically generated +and updated with a list of available printers. +If specified with no value, then no printcap +file will be generated. The default is to +generate a file named /etc/printcap.

+

When a filename is specified (e.g. +/etc/printcap), the printcap file is written +whenever a printer is added or removed. The +printcap file can then be used by applications +that are hardcoded to look at the printcap file +for the available printers. + +

+

RemoteRoot

+
+

Examples

+
    +
    +RemoteRoot remroot
    +RemoteRoot root
    +
    +
+

Description

+

The RemoteRoot directive sets the +username for unauthenticated root requests from +remote hosts. The default username is remroot +. Setting RemoteRoot to root + effectively disables this security mechanism. + +

+

RequestRoot

+
+

Examples

+
    +
    +RequestRoot /var/spool/cups
    +RequestRoot /foo/bar/spool/cups
    +
    +
+

Description

+

The RequestRoot directive sets the +directory for incoming IPP requests and HTML +forms. If an absolute path is not provided then +it is assumed to be relative to the +ServerRoot directory. The default request +directory is /var/spool/cups. + +

+

RIPCache

+
+

Examples

+
    +
    +RIPCache 8m
    +RIPCache 1g
    +RIPCache 2048k
    +
    +
+

Description

+

The RIPCache directive sets the size +of the memory cache used by Raster Image +Processor ("RIP") filters such as imagetoraster + and pstoraster. The size can be +suffixed with a "k" for kilobytes, "m" for +megabytes, or "g" for gigabytes. The default cache +size is "8m", or 8 megabytes. + +

+

ServerAdmin

+
+

Examples

+
    +
    +ServerAdmin user@host
    +ServerAdmin root@foo.bar.com
    +
    +
+

Description

+

The ServerAdmin directive identifies the +email address for the administrator on the system. +By default the administrator email address is +root@server, where server is the +server name. + +

+

ServerBin

+
+

Examples

+
    +
    +ServerBin /usr/lib/cups
    +ServerBin /foo/bar/lib/cups
    +
    +
+

Description

+

The ServerBin directive sets the +directory for server-run executables. If an absolute +path is not provided then it is assumed to +be relative to the ServerRoot + directory. The default executable directory is +/usr/lib/cups or /usr/lib32/cups (IRIX +6.5). + +

+

ServerName

+
+

Examples

+
    +
    +ServerName foo.domain.com
    +ServerName myserver.domain.com
    +
    +
+

Description

+

The ServerName directive specifies the +hostname that is reported to clients. By default +the server name is the hostname. + +

+

ServerRoot

+
+

Examples

+
    +
    +ServerRoot /etc/cups
    +ServerRoot /foo/bar/cups
    +
    +
+

Description

+

The ServerRoot directive specifies the +absolute path to the server configuration and +state files. It is also used to resolve +relative paths in the cupsd.conf file. The +default server directory is /etc/cups. + + +

+

SystemGroup

+
+

Examples

+
    +
    +SystemGroup sys
    +SystemGroup system
    +SystemGroup root
    +
    +
+

Description

+

The SystemGroup directive specifies the +system administration group for System + authentication. More information can be found later +in this chapter in "Printing +System Security". + +

+

TempDir

+
+

Examples

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

Description

+

The TempDir directive specifies an +absolute path for the directory to use for +temporary files. The default directory is +/var/tmp.

+

Temporary directories must be world-writable and +should have the "sticky" permission bit enabled so +that other users cannot delete filter temporary +files. The following commands will create an +appropriate temporary directory called /foo/bar/tmp +:

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

Timeout

+
+

Examples

+
    +
    +Timeout 300
    +Timeout 90
    +
    +
+

Description

+

The Timeout directive controls the +amount of time to wait before an active HTTP +or IPP request times out. The default timeout +is 300 seconds. + +

+

User

+
+

Examples

+
    +
    +User lp
    +User guest
    +
    +
+

Description

+

The User directive specifies the UNIX +user that filter and CGI programs run as. The +default user is lp. + +

+

Printing System Security

+

CUPS provides support for address, certificate, +and password (Basic and Digest) based authentication +and access control. Certificate and password +authentication provide ways to limit access to +individual people or groups.

+

Address based access control allows you to +limit access to specific systems, networks, or +domains. While this does not provide authentication, +it does allow you to limit the potential users +of your system efficiently.

+

CUPS maintains a list of locations that have +access control and/or authentication enabled. Locations +are specified using the Location + directive:

+ +

Locations generally follow the directory structure +of the DocumentRoot + directory, however CUPS does have several virtual +locations for administration, classes, jobs, and +printers: +

+ + + + + + + + + + + + +
LocationDescription
/adminThe path for all administration +operations.
/classesThe path for all classes.
/classes/nameThe resource for class +name.
/jobsThe path for all jobs.
/jobs/idThe resource for job id +.
/printersThe path for all printers.
/printers/nameThe path for printer +name.
/printers/name.ppdThe PPD file path for +printer name.
+
+

+

Authentication Using Certificates +

+

CUPS supports a local certificate-based +authentication scheme that can be used in place +of Basic or Digest authentication +by clients connecting through the localhost + interface. Certificate authentication is not supported +or allowed from clients on any other interface.

+

Certificates are 128-bit random numbers that refer +to an internal authentication record in the +server. A client connecting via the localhost + interface sends a request with an authorization +header of:

+
    +
    +Authorization: Local 0123456789ABCDEF0123456789ABCDEF
    +
    +
+

The server then looks up the local certificate +and authenticates using the username associated with +it.

+

Certificates are generated by the server +automatically and stored in the /etc/cups/certs + directory using the process ID of the CGI +program started by the server. Certificate files +are only readable by the User + and Group defined in +the cupsd.conf file. When the CGI program +ends the certificate is removed and invalidated +automatically.

+

The special file /etc/cups/certs/0 defines +the root certificate which can be used by +any client running as the super-user or another +user that is part of the group defined by +the SystemGroup + directive. The root certificate is automatically +regenerated every 5 minutes.

+

Using Basic Authentication

+

Basic authentication uses UNIX users and passwords +to authenticate access to resources such as +printers and classes, and to limit access to +administrative functions. +

+ + +
NOTE: +

Basic authentication sends the username and +password Base64 encoded from the client to the +server, so it offers no protection against +eavesdropping. This means that a malicious user +can monitor network packets and discover valid +users and passwords that could result in a +serious compromise in network security. Use Basic +authentication with extreme care.

+
+
+

+

The CUPS implementation of Basic authentication +does not allow access through user accounts +without a password. If you try to authenticate +using an account without a password, your access +will be immediately blocked.

+

Once a valid username and password is +authenticated by CUPS, any additional group +membership requirements are checked. +

+ + +
NOTE: +

The root user is considered by CUPS to be +a member of every group.

+
+
+ + +

+

Use the AuthType directive to enable +Basic authentication:

+
    +
    +AuthType Basic
    +
    +
+ + + +

Using Digest Authentication

+

Digest authentication uses users and passwords +defined in the /etc/cups/passwd.md5 file to +authenticate access to resources such as printers +and classes, and to limit access to administrative +functions. +

+ + +
NOTE: +

Unlike Basic authentication, Digest passes the MD5 +sum (basically a complicated checksum) of the +username and password instead of the strings +themselves. Also, Digest authentication does not use +the UNIX password file, so if an attacker does + discover the original password it is less likely +to result in a serious security problem so +long as you use a different UNIX password than +the corresponding Digest password.

+

The current CUPS implementation of Digest +authentication uses the client's hostname or IP +address for the "nonce" value. The nonce value +is an additional string added to the username + and password to make guessing the password more +difficult. The server checks that the nonce value +matches the client's hostname or address and +rejects the MD5 sum if it doesn't. Future +versions of CUPS will support Digest "session" +authentication which adds the request data to the +MD5 sum, providing even better authentication and +security.

+

Digest authentication does not guarantee that an +attacker cannot gain unauthorized access, but it +is safer than Basic authentication and should be +used in place of Basic authentication whenever +possible. Support for Digest authentication in +web browsers is not yet universally available.

+
+
+ + +

+

The lppasswd(1) command is used to +add, change, or remove accounts from the +passwd.md5 file. To add a user to the +default system group, type:

+
    +
    +lppasswd -a user ENTER
    +Password: (password) ENTER [password is not echoed]
    +Password again: (password) ENTER [password is not echoed]
    +
    +
+ + + +

Once added, a user can change his/her password +by typing:

+
    +
    +lppasswd ENTER
    +Old password: (password) ENTER [password is not echoed]
    +Password: (password) ENTER [password is not echoed]
    +Password again: (password) ENTER [password is not echoed]
    +
    +
+ + + +

To remove a user from the password file, +type:

+
    +
    +lppasswd -x user ENTER
    +
    +
+

Once a valid username and password is +authenticated by CUPS, any additional group +membership requirements are checked. +

+ + +
NOTE: +

The root user is considered by CUPS to be +a member of every group.

+
+
+

+

Use the AuthType directive to enable +Digest authentication:

+
    +
    +AuthType Digest
    +
    +
+

System and Group Authentication

+

The AuthClass directive +controls the level of authentication to perform. +System and Group authentication extend +the normal user-based authentication to require +membership in a UNIX group. For System + authentication each user must belong to the +sys, system, or root + group; the actual group depends on the operating +system.

+

For Group authentication each user must +belong to the group named by the +AuthGroupName directive:

+
    +
    +<Location /path>
    +AuthType Digest
    +AuthClass Group
    +AuthGroupName mygroup
    +</Location>
    +
    +
+

The named group must be a valid UNIX user +group, usually defined in the /etc/group + or /etc/netgroup files. Additionally, when +using Digest authentication you need to create +user accounts with the named group:

+
    +
    +lppasswd -g mygroup -a user ENTER
    +Password: (password) ENTER [password is not echoed]
    +Password again: (password) ENTER [password is not echoed]
    +
    +
+ + + +

Printer Accounting

+

ESP Print Pro maintains a log of all +accesses, errors, and pages that are printed. The +log files are normally stored in the +/var/log/cups directory. You can change this by +editing the /etc/cups/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 enabled the +HostNameLookups directive in the +cupsd.conf file.

+

The group field always contains "-" in +CUPS.

+

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 local time and is in the +format:

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

where ZZZZ is the timezone offset in +hours and minutes from Greenwich Mean Time (a.k.a. +GMT a.k.a. ZULU.)

+

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 that +was 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 job-billing
    +
    +DeskJet root 2 [20/May/1999:19:21:05 +0000] 1 0 acme-123
    +
    +
+

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.

+

The job-billing field contains a copy of +the job-billing attribute provided with the +IPP create-job or print-job + requests or "-" if none was provided. + +

+

File Typing and Filtering +

+

CUPS provides a MIME-based file typing and +filtering mechanism to convert files to a +printable format for each printer. On startup the +CUPS server reads MIME database files from the +/etc/cups directory (or a directory specified +by the ServerRoot + directive) to build a file type and conversion +database in memory. These database files are plain +ASCII text and can be edited with your favorite +text editor.

+

The mime.types and mime.convs + files define the standard file types and filters +that are available on the system.

+

mime.types

+

The mime.types file 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 rule 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 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
  • +
  • contains(offset,range,"string") - True if +the range of bytes contains the 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
  • +
+

All numeric values can be in decimal (123), +octal (0123), or hexadecimal (0x123) as desired. + + +

+

Strings can be in quotes, all by themselves, +as a string of hexadecimal values, or some +combination:

+
    +
    +"string"
    +'string'
    +string
    +<737472696e67>
    +<7374>ring
    +
    +
+

As shown in the text/html example, +rules can continue on multiple lines using the +backslash (\) character. A more complex example is +the image/jpeg rules:

+
    +
    +image/jpeg      jpeg jpg jpe string(0,<FFD8FF>) &&\
    +                (char(3,0xe0) char(3,0xe1) char(3,0xe2) char(3,0xe3)\
    +                 char(3,0xe4) char(3,0xe5) char(3,0xe6) char(3,0xe7)\
    +                 char(3,0xe8) char(3,0xe9) char(3,0xea) char(3,0xeb)\
    +                 char(3,0xec) char(3,0xed) char(3,0xee) char(3,0xef))
    +
    +
+

This rule states that any file with an +extension of .jpeg, .jpg, or +.jpe is a JPEG file. In addition, any +file starting with the hexadecimal string +<FFD8FF> (JPEG Start-Of-Image) followed by a +character between and including 0xe0 and +0xef (JPEG APPn markers) is also a JPEG +file.

+

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 Description and CUPS Software +Programmers Manual:

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

+

Adding Filetypes and Filters

+

Adding a new file type or filter is fairly +straight-forward. Rather than adding the new type +and filter to the mime.types and +mime.convs files which are overwritten when you +upgrade to a new version of CUPS, you simple +need to create new files with .types + and .convs extensions in the /etc/cups + directory. We recommend that you use the +product or format name, e.g.:

+
    +
    +myproduct.types
    +myproduct.convs
    +
    +
+

If you are providing a filter for a common +file format or printer, add the company or +author name:

+
    +
    +acme-msword.types
    +acme.msword.convs
    +
    +
+

This will help to prevent name collisions if +you install many different file types and filters. +

+

Once you choose the names for these files, +create them using your favorite text editor as +described earlier in this chapter. Once you have +created the files, restart the cupsd + process as described earlier in +"Restarting the CUPS Server".

+

Printer Drivers and PPD Files

+

Most CUPS printer drivers utilize one or more +printer-specific filters and a PPD file for each +printer model. Printer driver filters are registered +via the PPD file using cupsFilter + attributes:

+
    +
    +*cupsFilter: "application/vnd.cups-raster 0 rastertohp"
    +
    +
+

The filter is specified using the source file +type only; the destination file type is assumed +to be printer/name - suitable for +sending to the printer.

+

Writing Your Own Filter or Printer +Driver

+

CUPS supports an unlimited number of file +formats and filters, and can handle any printer. +If you'd like to write a filter or printer +driver for your favorite file format or printer, +consult the CUPS Software Programmers Manual for +step-by-step instructions.

+

7 - Printing with +Other Systems

+

This chapter describes how to print from client +systems that use the LPD, Mac OS, or Windows +printing protocols.

+

The Basics

+

CUPS is based on the IPP protocol, so any +system that supports IPP can send jobs to and +receive jobs from CUPS automatically. However, not +all systems support IPP yet. This chapter will +show you how to connect these systems to your +CUPS server, either to accept jobs from your +server for printing, or to send jobs to your +server.

+

Printing from LPD Clients

+

CUPS supports limited functionality for LPD-based +clients. With LPD you can print files to +specific printers, list the queue status, and so +forth. However, the automatic client configuration +and printer options are not supported by the +LPD protocol, so you must manually configure each +client for the printers it needs to access.

+

The cups-lpd(8) program provides support +for LPD clients. To enable LPD support on your +server, edit the /etc/inetd.conf file and +add a line reading:

+
    +
    +printer stream tcp nowait lp /usr/lib/cups/daemon/cups-lpd cups-lpd
    +
    +
+

The path to the cups-lpd may vary +depending on your installation.

+

Once you have added this line, send the +inetd(8) process a HUP signal or +reboot the system:

+
    +
    +killall -HUP inetd ENTER [IRIX and some versions of Linux]
    +kill -HUP pid ENTER [Others]
    +reboot ENTER [For all systems if the HUP signal fails]
    +
    +
+

Printing to LPD Servers

+

CUPS provides the lpd backend for +printing to LPD-based servers and printers. Use a +device URI of lpd://server/name to print +to a printer on an LPD server, where +server is the hostname or IP address of +the server and name is the queue +name.

+

Microsoft Windows NT provides an LPD service +under the name "TCP/IP Printing Services". To +enable LPD printing on NT, open the "Services" +control panel, select the "TCP/IP Printing Services" +service, and click on the "Start" button. Any +shared printer will then be available via the +LPD protocol.

+

Printing from Mac OS Clients

+

CUPS does not provide Mac OS support directly. +However, there are several free and commercial +software packages that do.

+

Columbia Appletalk Package (CAP)

+

Because the CAP LaserWriter server (lwsrv(8) +) does not support specification of PPD +files, we do not recommend that you use CAP +with CUPS. However, you can run the lpsrv + program for limited printing with the command:

+
    +
    +lwsrv -n "Name" -p printer -a /usr/lib/adicts -f /usr/lib/LW+Fonts
    +
    +
+

where Name is the name you want to +use when sharing the printer, and printer + is the name of the CUPS print queue. + +

+

XINET KA/Spool

+

To use your system as a print server for +Mac OS clients, configure each printer using a +papserver(8) in the /usr/adm/appletalk/services + file, specifying the corresponding PPD file in +the /etc/cups/ppd directory for each printer. + For a printer named MyPrinter the entry +would look like:

+
    +
    +/usr/etc/appletalk/papserver -I -L -P /etc/cups/ppd/MyPrinter.ppd \
    +"Printer Description" MyPrinter
    +
    +
+
+ + +
NOTE: +

Enter the text above on a single line +without the backslash (\) character.

+
+
+

NetATalk

+

To use your system as a print server for +Mac OS clients, configure each printer in the +papd.conf file, specifying the corresponding PPD +file in the /etc/cups/ppd directory for +each printer. For a printer named MyPrinter + the entry would look like:

+
    +
    +Printer Description:MyPrinter@MyServer:\
    +        :pr=|/usr/bin/lp -d MyPrinter:\
    +        :op=daemon:\
    +        :pd=/etc/cups/ppd/MyPrinter.ppd
    +
    +
+ + + +

Printing to Mac OS Servers

+

CUPS currently does not provide a backend to +communicate with a Mac OS server. However, you +can write and install a short shell script in +the /usr/lib/cups/backend directory that sends +a print file using the appropriate command. The +following is a short script that will run the +papif command provided with CAP.

+

After copying this script to +/usr/lib/cups/backend/cap, specify a device URI +of cap://server/printer to use this backend +with a print queue. + +

+
    +
    +"/usr/lib/cups/backend/cap"
    +#!/bin/sh
    +#
    +# Usage: cap job user title copies options [filename]
    +#
    +
    +# No arguments means show available devices...
    +
    +if test ${#argv} = 0; then
    +	echo "network cap \"Unknown\" \"Mac OS Printer via CAP\""
    +	exit 0
    +fi
    +
    +# Collect arguments...
    +
    +user=$2
    +copies=$4
    +
    +if test ${#argv} = 5; then
    +	# Get print file from stdin; copies have already been handled...
    +	file=/var/tmp/$$.prn
    +	copies=1
    +	cat > $file
    +else
    +	# Print file is on command-line...
    +	file=$6
    +fi
    +
    +# Create a dummy cap.printers file for this printer based
    +# upon a device URI of "cap://server/printer"...
    +
    +echo $PRINTER/$DEVICE_URI | \
    +	awk -F/ '{print $1 "=" $5 ":LaserWriter@" $4}' > /var/tmp/$$.cap
    +
    +CAPPRINTERS=/var/tmp/$$.cap; export CAPPRINTERS
    +
    +# Send the file to the printer, once for each copy. This assumes that you
    +# have properly initialized the cap.printers file...
    +
    +while [ $copies -gt 0 ]; do
    +	papif -n $user < $file
    +
    +        copies=`expr $copies - 1`
    +done
    +
    +# Remove any temporary files...
    +if test ${#argv} = 5; then
    +	/bin/rm -f $file
    +fi
    +
    +/bin/rm -f /var/tmp/$$.cap
    +
    +exit 0
    +
    +
+ + + +

Printing from Windows Clients

+

While CUPS does not provide Windows support +directly, the free SAMBA software package does. +SAMBA version 2.0.6 is the first release of +SAMBA that supports CUPS. You can download SAMBA +from:

+ +

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.

+

Printing to Windows Servers

+

CUPS can print to Windows servers in one of +two ways. The first way uses the LPD protocol +on the CUPS system and the "TCP/IP Printing +Services" on the Windows system. You can find +out more about this configuration in the +LPD section earlier in this chapter.

+

The second way is through the Microsoft Server +Message Block ("SMB") protocol. Support for this +protocol is provided with the free SAMBA software +package. You can download SAMBA from:

+ +

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

+
    +
    +ln -s `which smbspool` /usr/lib/cups/backend/smb ENTER
    +
    +
+

The smbspool(1) program is provided with +SAMBA starting with SAMBA 2.0.6. Once you have +made the link you can configure your printers +with one of the following device URIs:

+
    +
    +smb://workgroup/server/sharename
    +smb://server/sharename
    +smb://user:pass@workgroup/server/sharename
    +smb://user:pass@server/sharename
    +
    +
+

The workgroup name need only be +specified if your system is using a different +workgroup. The user:pass strings are +required when printing to Windows NT servers or +to shares with passwords enabled under Windows 95 +and 98.

+

A - Software License +Agreement

+

Common UNIX Printing System +License Agreement

+

Copyright 1997-2000 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, +("CUPSTM"), is provided under the GNU +General Public License ("GPL") and GNU Library +General Public License ("LGPL"), Version 2. A copy +of these licenses follow this introduction.

+

The GNU LGPL applies to the CUPS API +library, located in the "cups" subdirectory of the +CUPS source distribution and in the +"/usr/include/cups" directory and "libcups.a", +"libcups.sl", or "libcups.so" files in the binary +distributions.

+

The GNU GPL applies to the remainder of the +CUPS distribution, including the "pstoraster" filter +which is based upon GNU Ghostscript 5.50 and +the "pdftops" filter which is based upon Xpdf +0.90.

+

For those not familiar with the GNU GPL, the +license basically allows you to:

+
    +
  • Use the CUPS software at no charge.
  • +
  • Distribute verbatim copies of the software in +source or binary form.
  • +
  • Sell verbatim copies of the software for a +media fee, or sell support for the software.
  • +
  • Distribute or sell printer drivers and filters +that use CUPS so long as source code is +made available under the GPL.
  • +
+

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 must provide source for any new +drivers, changes, or additions to the software, +and all code must be provided under the GPL +or LGPL as appropriate.

+

The GNU LGPL relaxes the "link-to" restriction, +allowing you to develop applications that use the +CUPS API library under other licenses and/or +conditions as appropriate for your application.

+

Trademarks

+

Easy Software Products has trademarked the Common +UNIX Printing System, CUPS, and CUPS logo. These +names and logos may be used freely in any +direct port or binary distribution of CUPS. To +use them in derivative products, please contract +Easy Software Products for written permission. Our +intention is to protect the value of these +trademarks and ensure that any derivative product +meets the same high-quality standards as the +original.

+

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, additions, and +modifications to CUPS under the GNU GPL and +LGPL. For information please contact us at the +address shown above.

+

The Common UNIX Printing System provides a +"pstoraster" filter that utilizes the GNU GhostScript +5.50 core 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 +

+

The "pdftops" filter is based on the Xpdf +0.90 software. For binary distribution licensing of +this software, please contact:

Derek B. +Noonburg +

Email: +derekn@foolabs.com +

WWW: +http://www.foolabs.com/xpdf/

+

Support

+

Easy Software Products sells software support for +CUPS as well as a commercial printing product +based on CUPS called ESP Print Pro. You can +find out more at our web site:

+ + + + +

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

    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.

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

    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.

    +
  5. 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. +
    3. 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.
    4. +
    5. 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.)
    6. +
    +
  6. +

    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.

    +
  7. 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. +
    3. 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,
    4. +
    5. 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.)
    6. +
    +
  8. +

    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.

    +
  9. 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.
  10. +
  11. 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.
  12. +
  13. 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.
  14. +
  15. 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.
  16. +

    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.

    +
  17. 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.
  18. +
  19. 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.
  20. +

    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.

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

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

END OF TERMS AND CONDITIONS

+ + + +

GNU LIBRARY GENERAL PUBLIC LICENSE

+

Version 2, June 1991

+
+Copyright (C) 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.
+
+[This is the first released version of the library GPL.  It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+

Preamble

+

The licenses for most software are designed to +take away your freedom to share and change it. + By contrast, the GNU General Public Licenses are +intended to guarantee your freedom to share and +change free software--to make sure the software is +free for all its users.

+

This license, the Library General Public License, +applies to some specially designated Free Software +Foundation software, and to any other libraries +whose authors decide to use it. You can use +it for your libraries, 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 +library, or if you modify it.

+

For example, if you distribute copies of the +library, whether gratis or for a fee, you must +give the recipients all the rights that we gave +you. You must make sure that they, too, +receive or can get the source code. If you +link a program with the library, you must +provide complete object files to the recipients so +that they can relink them with the library, +after making changes to the library and +recompiling it. And you must show them these +terms so they know their rights.

+

Our method of protecting your rights has two +steps: (1) copyright the library, and (2) offer +you this license which gives you legal permission +to copy, distribute and/or modify the library.

+

Also, for each distributor's protection, we want +to make certain that everyone understands that +there is no warranty for this free library. If +the library is modified by someone else and +passed on, we want its recipients to know that +what they have is not the original version, 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 companies distributing free software will +individually obtain patent licenses, thus in effect +transforming the program into proprietary software. + To prevent this, we have made it clear that +any patent must be licensed for everyone's free +use or not licensed at all.

+

Most GNU software, including some libraries, is +covered by the ordinary GNU General Public +License, which was designed for utility programs. + This license, the GNU Library General Public +License, applies to certain designated libraries. + This license is quite different from the ordinary +one; be sure to read it in full, and don't +assume that anything in it is the same as in +the ordinary license.

+

The reason we have a separate public license +for some libraries is that they blur the +distinction we usually make between modifying or +adding to a program and simply using it. + Linking a program with a library, without +changing the library, is in some sense simply +using the library, and is analogous to running +a utility program or application program. However, +in a textual and legal sense, the linked +executable is a combined work, a derivative of +the original library, and the ordinary General +Public License treats it as such.

+

Because of this blurred distinction, using the +ordinary General Public License for libraries did +not effectively promote software sharing, because +most developers did not use the libraries. We +concluded that weaker conditions might promote +sharing better.

+

However, unrestricted linking of non-free programs +would deprive the users of those programs of +all benefit from the free status of the +libraries themselves. This Library General Public +License is intended to permit developers of +non-free programs to use free libraries, while +preserving your freedom as a user of such +programs to change the free libraries that are +incorporated in them. (We have not seen how to +achieve this as regards changes in header files, +but we have achieved it as regards changes in +the actual functions of the Library.) The hope +is that this will lead to faster development of +free libraries.

+

The precise terms and conditions for copying, +distribution and modification follow. Pay close +attention to the difference between a "work based +on the library" and a "work that uses the +library". The former contains code derived from +the library, while the latter only works together +with the library.

+

Note that it is possible for a library to +be covered by the ordinary General Public License +rather than by this special one.

+

TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION +AND MODIFICATION

+

0. This License Agreement applies to +any software library which contains a notice +placed by the copyright holder or other authorized +party saying it may be distributed under the +terms of this Library General Public License (also +called "this License"). Each licensee is addressed +as "you".

+

A "library" means a collection of software +functions and/or data prepared so as to be +conveniently linked with application programs (which +use some of those functions and data) to form +executables.

+

The "Library", below, refers to any such +software library or work which has been +distributed under these terms. A "work based on +the Library" means either the Library or any +derivative work under copyright law: that is to +say, a work containing the Library or a portion +of it, either verbatim or with modifications +and/or translated straightforwardly into another +language. (Hereinafter, translation is included without +limitation in the term "modification".)

+

"Source code" for a work means the preferred +form of the work for making modifications to +it. For a library, 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 library.

+

Activities other than copying, distribution and +modification are not covered by this License; they +are outside its scope. The act of running a +program using the Library is not restricted, and +output from such a program is covered only if +its contents constitute a work based on the +Library (independent of the use of the Library +in a tool for writing it). Whether that is +true depends on what the Library does and what +the program that uses the Library does.

+

1. You may copy and distribute +verbatim copies of the Library's complete 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 distribute a copy +of this License along with the Library.

+

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.

+

2. You may modify your copy or +copies of the Library or any portion of it, +thus forming a work based on the Library, 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. The modified work must itself be a software +library.
  2. +

    +
  3. You must cause the files modified to carry +prominent notices stating that you changed the +files and the date of any change.
  4. +

    +
  5. You must cause the whole of the work to +be licensed at no charge to all third parties +under the terms of this License.
  6. +

    +
  7. If a facility in the modified Library refers +to a function or a table of data to be +supplied by an application program that uses the +facility, other than as an argument passed when +the facility is invoked, then you must make a +good faith effort to ensure that, in the event +an application does not supply such function or + table, the facility still operates, and performs +whatever part of its purpose remains meaningful.
  8. +

    (For example, a function in a library to +compute square roots has a purpose that is +entirely well-defined independent of the application. + Therefore, Subsection 2d requires that any + application-supplied function or table used by this +function must be optional: if the application +does not supply it, the square root function +must still compute square roots.)

    +
+

These requirements apply to the modified work +as a whole. If identifiable sections of that +work are not derived from the Library, 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 Library, 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 +Library.

+

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

+

3. You may opt to apply the +terms of the ordinary GNU General Public License +instead of this License to a given copy of +the Library. To do this, you must alter all +the notices that refer to this License, so that +they refer to the ordinary GNU General Public +License, version 2, instead of to this License. + (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, +then you can specify that version instead if +you wish.) Do not make any other change in +these notices.

+

Once this change is made in a given copy, +it is irreversible for that copy, so the +ordinary GNU General Public License applies to all +subsequent copies and derivative works made from +that copy.

+

This option is useful when you wish to copy +part of the code of the Library into a +program that is not a library.

+

4. You may copy and distribute +the Library (or a portion or derivative of it, +under Section 2) in object code or executable +form under the terms of Sections 1 and 2 +above provided that you 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.

+

If distribution of 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 satisfies the requirement +to distribute the source code, even though third +parties are not compelled to copy the source +along with the object code.

+

5. A program that contains no +derivative of any portion of the Library, but +is designed to work with the Library by being +compiled or linked with it, is called a "work +that uses the Library". Such a work, in +isolation, is not a derivative work of the +Library, and therefore falls outside the scope of +this License.

+

However, linking a "work that uses the Library" +with the Library creates an executable that is +a derivative of the Library (because it contains +portions of the Library), rather than a "work +that uses the library". The executable is +therefore covered by this License. Section 6 +states terms for distribution of such executables.

+

When a "work that uses the Library" uses +material from a header file that is part of +the Library, the object code for the work may +be a derivative work of the Library even though +the source code is not. Whether this is true +is especially significant if the work can be +linked without the Library, or if the work is +itself a library. The threshold for this to be +true is not precisely defined by law.

+

If such an object file uses only numerical +parameters, data structure layouts and accessors, and +small macros and small inline functions (ten lines +or less in length), then the use of the +object file is unrestricted, regardless of whether +it is legally a derivative work. (Executables +containing this object code plus portions of the +Library will still fall under Section 6.)

+

Otherwise, if the work is a derivative of +the Library, you may distribute the object code +for the work under the terms of Section 6. +Any executables containing that work also fall +under Section 6, whether or not they are linked +directly with the Library itself.

+

6. As an exception to the +Sections above, you may also compile or link a +"work that uses the Library" with the Library +to produce a work containing portions of the +Library, and distribute that work under terms of +your choice, provided that the terms permit +modification of the work for the customer's own +use and reverse engineering for debugging such +modifications.

+

You must give prominent notice with each copy +of the work that the Library is used in it +and that the Library and its use are covered +by this License. You must supply a copy of +this License. If the work during execution +displays copyright notices, you must include the +copyright notice for the Library among them, as +well as a reference directing the user to the +copy of this License. Also, you must do one +of these things:

+
    +
  1. Accompany the work with the complete +corresponding machine-readable source code for the +Library including whatever changes were used in +the work (which must be distributed under + Sections 1 and 2 above); and, if the work +is an executable linked with the Library, with +the complete machine-readable "work that uses the +Library", as object code and/or source code, so +that the user can modify the Library and then +relink to produce a modified executable containing +the modified Library. (It is understood that the +user who changes the contents of definitions files +in the Library will not necessarily be able to +recompile the application to use the modified +definitions.)
  2. +

    +
  3. Accompany the work with a written offer, valid +for at least three years, to give the same +user the materials specified in Subsection 6a, +above, for a charge no more than the cost +of performing this distribution.
  4. +

    +
  5. If distribution of the work is made by +offering access to copy from a designated place, +offer equivalent access to copy the above + specified materials from the same place.
  6. +

    +
  7. Verify that the user has already received a +copy of these materials or that you have +already sent this user a copy.
  8. +
+

For an executable, the required form of the +"work that uses the Library" must include any +data and utility programs needed for reproducing +the executable from it. 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.

+

It may happen that this requirement contradicts +the license restrictions of other proprietary +libraries that do not normally accompany the +operating system. Such a contradiction means you +cannot use both them and the Library together +in an executable that you distribute.

+

7. You may place library facilities +that are a work based on the Library +side-by-side in a single library together with +other library facilities not covered by this +License, and distribute such a combined library, +provided that the separate distribution of the +work based on the Library and of the other +library facilities is otherwise permitted, and +provided that you do these two things:

+
    +
  1. Accompany the combined library with a copy of +the same work based on the Library, uncombined +with any other library facilities. This must be +distributed under the terms of the Sections +above.
  2. +

    +
  3. Give prominent notice with the combined library +of the fact that part of it is a work +based on the Library, and explaining where to +find the accompanying uncombined form of the same +work.
  4. +
+

8. You may not copy, modify, +sublicense, link with, or distribute the Library +except as expressly provided under this License. + Any attempt otherwise to copy, modify, sublicense, +link with, or distribute the Library 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.

+

9. 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 Library or its derivative +works. These actions are prohibited by law if +you do not accept this License. Therefore, by +modifying or distributing the Library (or any work +based on the Library), you indicate your +acceptance of this License to do so, and all +its terms and conditions for copying, distributing +or modifying the Library or works based on it. +

+

10. Each time you redistribute the +Library (or any work based on the Library), the +recipient automatically receives a license from the +original licensor to copy, distribute, link with +or modify the Library 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.

+

11. 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 Library at +all. For example, if a patent license would +not permit royalty-free redistribution of the Library +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 +Library.

+

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.

+

12. If the distribution and/or use +of the Library is restricted in certain countries +either by patents or by copyrighted interfaces, +the original copyright holder who places the +Library 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.

+

13. The Free Software Foundation may +publish revised and/or new versions of the Library +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 Library 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 Library does not +specify a license version number, you may choose +any version ever published by the Free Software +Foundation.

+

14. If you wish to incorporate +parts of the Library into other free programs +whose distribution conditions are incompatible with +these, 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

+

15. BECAUSE THE LIBRARY IS LICENSED +FREE OF CHARGE, THERE IS NO WARRANTY FOR THE +LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE +LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE +COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE +LIBRARY "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 +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE +DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY +SERVICING, REPAIR OR CORRECTION.

+

16. 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 LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE +WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER +OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES.

+

END OF TERMS AND CONDITIONS

+

B - Common Network +Settings

+

This appendix covers many of the popular TCP/IP +network interfaces and printer servers available on +the market today.

+

Configuring a Network Interface

+

When you first install a network printer or +print server on your LAN, you need to set +the Internet Protocol ("IP") address. On most +higher-end "workgroup" printers, you can set the +address through the printer control panel. However, +in most cases you will want to assign the +addresses remotely from your workstation. This makes +administration a bit easier and avoids assigning +duplicate addresses accidentally.

+

To setup your printer or print server for +remote address assignment, you'll need the Ethernet +Media Access Control ("MAC") address, also sometimes +called a node address, and the IP address you +want to use for the device. The Ethernet MAC +address can often be found on the printer test +page or bottom of the print server. + +

+

Configuring the IP Address Using ARP +

+

The easiest way to set the IP address of +a network device is to use the arp(8) + command. The arp sends an Address +Resolution Protocol ("ARP") packet to the specified +Ethernet MAC address, setting the network device's +IP address:

+
    +
    +arp -s ip-address ethernet-address ENTER
    +arp -s host.domain.com 08:00:69:00:12:34 ENTER
    +arp -s 192.0.2.2 08:00:69:00:12:34 ENTER
    +
    +
+

Configuring the IP Address Using +RARP

+

The most flexible way to remotely assign IP +addresses under UNIX is through the Reverse +Address Resolution Protocol ("RARP"). RARP allows a +network device to request an IP address using +its Ethernet MAC address, and one or more RARP +servers on the network will respond with an ARP +packet with the IP address the device can use. +

+

RARP should be used when you have to manage +many printers or print servers, or when you +have a network device that does not remember +its IP address after a power cycle. If you +just have a single printer or print server, the +arp command is the way to go.

+

Some UNIX operating systems use a program +called rarpd(8) to manage RARP. Others, +like Linux, support this protocol in the kernel. +For systems that provide the rarpd + program you will need to start it before RARP +lookups will work:

+
    +
    +rarpd ENTER
    +
    +
+

Under IRIX you can enable this functionality by +default using:

+
    +
    +chkconfig rarpd on ENTER
    +
    +
+

Both the rarpd program and kernel +RARP support read a list of Ethernet and IP +addresses from the file /etc/ethers. Each +line contains the Ethernet address (colon delimited) +followed by an IP address or hostname like:

+
    +
    +08:00:69:00:12:34 myprinter.mydomain.com
    +08:00:69:00:12:34 192.0.2.2
    +
    +
+

Add a line to this file and cycle the +power on the printer or print server to set +its address. + +

+

Configuring the IP Address Using +BOOTP

+

The BOOTP protocol is used when you need to +provide additional information such as the location +of a configuration file to the network interface. +Using the standard bootpd(8) program +supplied with UNIX you simply need to add a +line to the /etc/bootptab file; for IRIX: +

+
    +
    +myprinter 08:00:69:00:12:34 192.0.2.2 myprinter.boot
    +
    +
+ + + +

Newer versions of bootpd use a +different format:

+
    +
    +myprinter:ha=080069001234:ip=192.0.2.2:t144=myprinter.boot
    +
    +
+

The myprinter.boot file resides in the +/usr/local/boot directory by default. If you do +not need to provide a boot file you may +leave the last part of the line blank. + + +

+ + +
NOTE: +

Some versions of UNIX do not enable the +BOOTP service by default. The /etc/inetd.conf + usually contains a line for the BOOTP service +that can be uncommented if needed.

+
+
+

+

Verifying the Printer Connection

+

To test that the IP address has been +successfully assigned and that the printer is +properly connected to your LAN, type:

+
    +
    +ping ip-address ENTER
    +
    +
+

If the connection is working properly you will +see something like:

+
    +
    +ping myprinter ENTER
    +PING myprinter (192.0.2.2): 56 data bytes
    +64 bytes from 192.0.2.2: icmp_seq=0 ttl=15 time=5 ms
    +64 bytes from 192.0.2.2: icmp_seq=1 ttl=15 time=3 ms
    +64 bytes from 192.0.2.2: icmp_seq=2 ttl=15 time=3 ms
    +64 bytes from 192.0.2.2: icmp_seq=3 ttl=15 time=3 ms
    +
    +
+

If not, verify that the printer or print +server is connected to the LAN, it is powered +on, the LAN cabling is good, and the IP +address is set correctly. You can usually see +the current IP address and network status by +printing a configuration or test page on the +device. + +

+

Common Network Interface Settings

+

Once you have set the IP address you can +access the printer or print server using the +ipp, lpd, or socket + backends. The following is a list of common +network interfaces and printer servers and the +settings you should use with CUPS: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Model/ManufacturerDevice +URI(s)
Apple LaserWriterlpd:// +address/PASSTHRU
Axis w/o IPP +

(see directions)
socket:// +address:9100 +

socket://address:9101 +

socket://address:9102
Axis w/IPPipp:// +address/LPT1 +

ipp://address/LPT2 +

ipp://address/COM1
Castelle LANpressTM +lpd://address/pr1 +

lpd://address/pr2 +

lpd://address/pr3
DPI NETPrintlpd:// +address/pr1 +

lpd://address/pr2 +

lpd://address/pr3
EFI® Fiery® RIP +lpd://address/print
EPSON® Multiprotocol Ethernet +Interface Boardsocket://address
Extended System ExtendNET +lpd://address/pr1 +

lpd://address/pr2 +

lpd://address/pr3
Hewlett Packard JetDirect +w/o IPPsocket://address:9100 +

socket://address:9101 +

socket://address:9102
Hewlett Packard JetDirect +w/IPPipp://address/ipp +

ipp://address/ipp/port1 +

ipp://address/ipp/port2 +

ipp://address/ipp/port3
Intel® NetportExpress XL, +PRO/100lpd://address/LPT1_PASSTHRU +

lpd://address/LPT2_PASSTHRU +

lpd://address/COM1_PASSTHRU
LexmarkTM MarkNet +lpd://address/ps
Linksys EtherFast® +

(see directions)
+socket://address:4010 +

socket://address:4020 +

socket://address:4030
Kodak®lpd://address +/ps
QMS® CrownNetTM +lpd://address/ps
Tektronix® PhaserShareTM +socket://address:9100
XEROX® 4512 NIC +lpd://address/PORT1
XEROX® XNIClpd:// +address/PASSTHRU
XEROX® (most others) +socket://address:5503
+
+

+

Configuring Axis Print Servers

+

The Axis print servers can be configured using +ARP, RARP, or BOOTP. However, on models that do +not provide IPP support an additional step must +be performed to configure the TCP/IP portion of +the print server for use with CUPS. + +

+

Each print server contains a configuration file +named config that contains a list of +network parameters used by the server. To modify +this file you must first download it from the +print server using the ftp(1) program:

+
    +
    +ftp ip-address ENTER
    +Connected to ip-address.
    +220 Axis NPS ### FTP Printer Server V#.## MON DD YEAR ready.
    +ftp> user root ENTER
    +331 User name ok, need password
    +Password: pass ENTER (this is not echoed)
    +230 User logged in
    +ftp> get config ENTER
    +local: config remote: config
    +200 PORT command successful.
    +150 Opening data connection for config (192,0,2,2),
    +(mode ascii).
    +226 Transfer complete.
    +##### bytes received in #.## seconds (##### Kbytes/s)
    +ftp> quit ENTER
    +221 Goodbye.
    +
    +
+ + + +

Next, edit the file with your favorite text +editor and locate the lines beginning with:

+
    +
    +RTN_OPT.     : YES
    +RTEL_PR1.    : 0
    +RTEL_PR2.    : 0
    +RTEL_PR3.    : 0
    +RTEL_PR4.    : 0
    +RTEL_PR5.    : 0
    +RTEL_PR6.    : 0
    +RTEL_PR7.    : 0
    +RTEL_PR8.    : 0
    +
    +
+ + + Change the RTN_OPT line to read: +
    +
    +RTN_OPT.     : NO
    +
    +
+ + + +

This disables the Reverse TELNET protocol and +enables the standard TELNET protocol on the print +server. Next, assign a port number for each +parallel and serial port on the server as +follows:

+
    +
    +RTEL_PR1.    : 9100
    +RTEL_PR2.    : 9101
    +RTEL_PR3.    : 9102
    +RTEL_PR4.    : 9103
    +RTEL_PR5.    : 9104
    +RTEL_PR6.    : 9105
    +RTEL_PR7.    : 9106
    +RTEL_PR8.    : 9107
    +
    +
+ + + +

This essentially makes the Axis print server +look like a Hewlett Packard JetDirect EX print +server. Save the file and then upload the new +config file using the ftp command:

+
    +
    +ftp ip-address ENTER
    +Connected to ip-address.
    +220 Axis NPS ### FTP Printer Server V#.## MON DD YEAR ready.
    +ftp> user root ENTER
    +331 User name ok, need password
    +Password: pass ENTER (this is not echoed)
    +230 User logged in
    +ftp> put config CONFIG ENTER
    +local: config remote: CONFIG
    +200 PORT command successful.
    +150 Opening data connection for config (192,0,2,2), (mode ascii).
    +226 Transfer complete.
    +##### bytes received in #.## seconds (##### Kbytes/s)
    +ftp> get hardreset ENTER
    +local: hardreset remote: hardreset
    +200 PORT command successful.
    +421 Axis NPS ### hard reset, closing connection.
    +ftp> quit ENTER
    +221 Goodbye.
    +
    +
+

Your Axis print server is now ready for use! +

+

Configuring Linksys Print Servers

+

The Linksys print servers can be configured +using ARP, RARP, or BOOTP. Like older Axis +print servers, an additional step must be +performed to configure the TCP/IP portion of the +print server for use with CUPS. + +

+

Each print server contains a configuration file +named CONFIG that contains a list of +network parameters used by the server. To modify +this file you must first download it from the +print server using the ftp(1) program:

+
    +
    +ftp -n ip-address ENTER
    +Connected to ip-address.
    +220 Print Server Ready.
    +Remote system type is Print.
    +ftp> get CONFIG ENTER
    +local: CONFIG remote: CONFIG
    +200 Command OK.
    +150 Open ASCII Mode Connection.
    +WARNING! 68 bare linefeeds received in ASCII mode
    +File may not have transferred correctly.
    +226 Transfer complete.
    +##### bytes received in #.## seconds (##### Kbytes/s)
    +ftp> quit ENTER
    +221 Goodbye.
    +
    +
+ + + +

Next, edit the file with your favorite text +editor and locate the lines beginning with:

+
    +
    +0100 L1_PROUT:P1
    +0120 L2_PROUT:P1
    +0140 L3_PROUT:P1
    +
    +
+

Change the port number for each parallel and +serial port on the server as follows:

+
    +
    +0100 L1_PROUT:P1
    +0120 L2_PROUT:P2
    +0140 L3_PROUT:P3
    +
    +
+ + + +

This maps each virtual printer with a physical +port. Save the file and then upload the new +CONFIG file using the ftp command:

+
    +
    +ftp -n ip-address ENTER
    +Connected to ip-address.
    +220 Print Server Ready.
    +Remote system type is Print.
    +ftp> put CONFIG ENTER
    +local: CONFIG remote: CONFIG
    +200 Command OK.
    +150 Open ASCII Mode Connection.
    +226 Transfer complete.
    +##### bytes received in #.## seconds (##### Kbytes/s)
    +ftp> quit ENTER
    +221 Goodbye.
    +
    +
+

Your Linksys print server is now ready for +use!

+

C - Printer Drivers +

+

This appendix lists the printer drivers that +are provided with CUPS.

+

Printer Drivers

+

CUPS includes the following printer drivers:

+ +

EPSON 9-pin Dot Matrix

+

The EPSON 9-pin Dot Matrix driver ( +epson9.ppd) supports 9-pin dot matrix printers +that implement the ESC/P command set. It provides +60x72, 120x72, and 240x72 DPI output in black +only.

+

EPSON 24-pin Dot Matrix

+

The EPSON 24-pin Dot Matrix driver ( +epson9.ppd) supports 24-pin dot matrix printers +that implement the ESC/P command set. It provides +120x180, 180x180, 360x180, and 360x360 DPI output +in black only.

+

EPSON Stylus Color

+

The EPSON Stylus Color driver (stcolor.ppd +) supports EPSON Stylus Color printers that +implement the ESC/P2 command set. It provides 180, +360, and 720 DPI output in black and color +(CMYK).

+

EPSON Stylus Photo

+

The EPSON Stylus Photo driver (stphoto.ppd +) supports EPSON Stylus Photo printers that +implement the ESC/P2 command set. It provides 180, +360, and 720 DPI output in black and color +(CMYKcm).

+

HP DeskJet

+

The HP DeskJet driver (deskjet.ppd) +supports HP DeskJet printers that implement the +PCL command set. It provides 150, 300, and 600 +DPI output in black and color (CMYK).

+

The DeskJet printers that implement the HP-PPA +command set (720C, 722C, 820C, and 1100C) are +not supported due to a complete lack of +documentation and support from Hewlett Packard.

+

The duplexer provided with the HP DeskJet 900 +series printers is also not supported for similar +reasons.

+

HP LaserJet

+

The HP LaserJet driver (laserjet.ppd) +supports HP LaserJet printers that implement the +PCL command set. It provides 150, 300, and 600 +DPI output in black only and supports the +duplexer if installed.

+

LaserJet printers that do not implement PCL +(3100, 3150) are not supported due to a +complete lack of documentation and support from +Hewlett Packard.

+

D - List of Files

+

This appendix lists the files and directories +that are installed for the Common UNIX Printing +System. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathnameDescription
/etc/cups/certs/The location of +authentication certificate files for local HTTP +clients.
/etc/cups/classes.confThe printer +classes configuration file for the scheduler.
/etc/cups/cupsd.confThe scheduler +configuration file.
/etc/cups/interfaces/The location +of System V interface scripts for printers.
/etc/cups/mime.convsThe list of +standard file filters included with ESP Print Pro. +
/etc/cups/mime.typesThe list of +recognized file types for ESP Print Pro.
/etc/cups/ppd/The location of +PostScript Printer Description ("PPD") files for + printers.
/etc/cups/printers.confThe printer +configuration file for the scheduler.
/usr/bin/cancelThe System V +cancel job(s) command.
/usr/bin/disableThe System V +disable printer command.
/usr/bin/enableThe System V +enable printer command.
/usr/bin/lpThe System V print +command.
/usr/bin/lpoptionsSets user-defined +printing options and defaults.
/usr/bin/lppasswdAdds, changes, +or removes Digest password accounts.
/usr/bin/lpqThe Berkeley status +command.
/usr/bin/lprThe Berkeley print +command.
/usr/bin/lprmThe Berkeley cancel +job(s) command.
/usr/bin/lpstatThe System V +status command.
/usr/include/cups/CUPS API +header files.
/usr/lib32/libcups.a +

/usr/lib32/libcupsimage.a
Static libraries +(IRIX 6.5)
/usr/lib/libcups.a +

/usr/lib/libcupsimage.a
Static libraries +(all others)
/usr/lib/libcups.sl.2 +

/usr/lib/libcupsimage.sl.2
Shared libraries +(HP-UX)
/usr/lib32/libcups.so.2 +

/usr/lib32/libcupsimage.so.2
Shared libraries +(IRIX 6.5)
/usr/lib/libcups.so.2 +

/usr/lib/libcupsimage.so.2
Shared libraries +(all others)
/usr/lib/cups/backend/Backends for +various types of printer connections.
/usr/lib/cups/cgi-bin/CGI programs +for the scheduler.
/usr/lib/cups/daemon/Daemons for +polling and LPD support.
/usr/lib/cups/filter/Filters for +various types of files.
/usr/lib/locale/The location of +language-specific message files. (System V)
/usr/lib/nls/msg/The location of +language-specific message files. (Compaq Tru64 UNIX)
/usr/share/locale/The location +of language-specific message files. (Linux, *BSD)
/usr/sbin/acceptThe accept-jobs +command.
/usr/sbin/cupsdThe CUPS print +scheduler.
/usr/sbin/lpadminThe System V +printer administration tool.
/usr/sbin/lpcThe Berkeley +printer administration tool.
/usr/sbin/lpinfoThe get-devices +and get-ppds command.
/usr/sbin/lpmoveThe move-jobs +command.
/usr/sbin/rejectThe reject-jobs +command.
/usr/share/catman/a_man/ +

/usr/share/catman/u_man/
Man pages (IRIX)
/usr/share/man/Man pages (Compaq +Tru64 UNIX, HP-UX, Solaris)
/usr/man/Man pages (all +others)
/usr/share/cups/data/The location +of filter data files.
/usr/share/cups/data/testprint.psThe +PostScript test page file.
/usr/share/cups/fonts/The location +of PostScript fonts for the PostScript RIP.
/usr/share/cups/model/The location +of PostScript Printer Description ("PPD") files and + interface scripts that may be used to setup a +printer queue.
/usr/share/cups/pstoraster/Other +PostScript RIP initialization files.
/usr/share/cups/pstoraster/FontmapThe +font mapping file (converts filenames to fontnames)
/usr/share/cups/templates/The +location of HTML template files for the web +interfaces.
/usr/share/doc/cups/Documentation +and web page data for the scheduler.
/var/log/cups/The location of +scheduler log files.
/var/spool/cups/The location of +print files waiting to be printed.
+
+

+

E - Troubleshooting Common +Problems

+

This appendix covers some of the common +problems first-time users encounter when installing +and configuring CUPS.

+

Commercial support for CUPS is available from +Easy Software Products. For more information please +contact us at:

+ +

My Applications Don't See the +Available Printers

+

Many applications read the /etc/printcap + file to get a list of available printers.

+

The default CUPS configuration does not create +the /etc/printcap file automatically. To +enable automatic creation and updating of this +file, use the Printcap + directive described in Chapter +6, "Printing System Management".

+

CUPS Doesn't Recognize My Username or +Password!

+

CUPS will ask you for a UNIX username and +password when you perform printer administration +tasks remotely or via a web browser. The +default configuration requires that you use the +root username and the corresponding password +to authenticate the request.

+

CUPS does not allow you to authenticate an +administration request with an account that has no +password for security reasons. If you do not +have a password on your root account +then you won't be able to add printers remotely +or via the web interface! + +

+

To disable password authentication you need to +edit the /etc/cups/cupsd.conf file and +comment out the lines reading:

+
    +
    +AuthType Basic
    +AuthClass System
    +
    +
+ for the /admin location. Then restart the +CUPS server as described in +Chapter 8, "Printing System Management". +
+ + +
NOTE: +

Disabling password checks will allow any local +user to change your printer and class +configuration, but remote administration from another +machine will still not be allowed.

+
+
+

I Can't Do Administration Tasks from +Another Machine!

+

The default CUPS configuration limits administration +to the local machine. To open up access, edit +the /etc/cups/cupsd.conf and comment out the +lines reading:

+
    +
    +Order deny,allow
    +Deny from all
    +Allow from 127.0.0.1
    +
    +
+ for the /admin location. Then restart the +CUPS server as described in +Chapter 8, "Printing System Management". +
+ + +
NOTE: +

Allowing administration access from all hosts is +a potential security risk. Please read +Chapter 6, "Printing System Management" for a +description of these risks and ways to minimize +them.

+
+
+ + + +

I Can't Do Administration Tasks from +My Web Browser!

+

This problem is usually caused by:

+
    +
  1. not specifying the correct password for the + root account.
  2. +
  3. accessing the CUPS server using the hostname +or IP address of the server without enabling +remote access for administration functions. This can +be corrected by following the instructions in the "I Can't Do Administration Tasks +from Another Machine!" section earlier in this +appendix.
  4. +
  5. not setting a password on the root account. +CUPS will not authenticate a user account that +does not have a password for security reasons.
  6. +
  7. authenticating using an account other than root, +but the account you are using is not a +member of the system group.
  8. +
  9. configuring CUPS to use Digest authentication, +but your web browser does not support Digest +authentication.
  10. +
+

Connection Refused Messages

+

Under normal circumstances, "connection refused" +messages for a networked printer should be +expected from time to time. Most network +interfaces only allow a single connection to be +made at any given time (one job at a time) +and will refuse access to all other systems +while the first connection is active. CUPS +automatically retries the connection once every 30 +seconds.

+

If the problem persists and you are unable +to print any jobs to the printer, verify that +another machine is not maintaining a connection +with the printer, and that you have selected +the proper port or printer name for the +printer.

+

Also, most external print servers will refuse +connections if the connected printer is turned off +or is off-line. Verify that the affected printer +is turned on and is online.

+

Write Error Messages

+

If you get "write error" messages on a +printer queue the printer interface (usually a +Hewlett Packard JetDirect interface) has timed out +and reset the network connection from your +workstation.

+

The error is caused by that startup delay +between the initial setup of the printer or +plotter and the first page of print data that +is sent. + +

+

To correct the problem, change the idle timeout +on the interface to at least 180 seconds or +3 minutes. To change the timeout on a Hewlett +Packard JetDirect interface, type:

+
    +
    +telnet ip-address ENTER
    +
    +Trying ip-address...
    +Connected to ip-address.
    +Escape character is `^]'.
    +
    +Please type [Return] two times, to initialize telnet configuration
    +For HELP type "?"
    +> idle-timeout: 180 ENTER
    +> quit ENTER
    +
    +
+ + diff --git a/doc/sam.pdf b/doc/sam.pdf new file mode 100644 index 0000000000..048591702d --- /dev/null +++ b/doc/sam.pdf @@ -0,0 +1,3234 @@ +%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[16 0 R +18 0 R +19 0 R +]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[21 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 +]endobj +34 0 obj<>endobj +35 0 obj<>endobj +36 0 obj<>endobj +37 0 obj<>endobj +38 0 obj<>endobj +39 0 obj[34 0 R +36 0 R +38 0 R +]endobj +40 0 obj<>endobj +41 0 obj<>endobj +42 0 obj<>endobj +43 0 obj<>endobj +44 0 obj[41 0 R +43 0 R +]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[46 0 R +47 0 R +48 0 R +49 0 R +51 0 R +]endobj +53 0 obj<>endobj +54 0 obj<>endobj +55 0 obj[53 0 R +54 0 R +]endobj +56 0 obj<>endobj +57 0 obj<>endobj +58 0 obj[57 0 R +]endobj +59 0 obj<>endobj +60 0 obj<>endobj +61 0 obj<>endobj +62 0 obj<>endobj +63 0 obj[60 0 R +61 0 R +62 0 R +]endobj +64 0 obj<>endobj +65 0 obj<>endobj +66 0 obj<>endobj +67 0 obj<>endobj +68 0 obj[64 0 R +65 0 R +66 0 R +67 0 R +]endobj +69 0 obj<>endobj +70 0 obj<>endobj +71 0 obj<>endobj +72 0 obj[69 0 R +70 0 R +71 0 R +]endobj +73 0 obj<>endobj +74 0 obj<>endobj +75 0 obj[73 0 R +74 0 R +]endobj +76 0 obj<>endobj +77 0 obj<>endobj +78 0 obj<>endobj +79 0 obj<>endobj +80 0 obj<>endobj +81 0 obj<>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[76 0 R +77 0 R +78 0 R +79 0 R +80 0 R +81 0 R +82 0 R +83 0 R +84 0 R +85 0 R +86 0 R +87 0 R +88 0 R +89 0 R +90 0 R +91 0 R +92 0 R +93 0 R +94 0 R +95 0 R +96 0 R +97 0 R +98 0 R +99 0 R +100 0 R +101 0 R +102 0 R +103 0 R +104 0 R +105 0 R +106 0 R +107 0 R +108 0 R +109 0 R +110 0 R +111 0 R +112 0 R +113 0 R +114 0 R +115 0 R +116 0 R +117 0 R +118 0 R +119 0 R +120 0 R +121 0 R +122 0 R +123 0 R +124 0 R +125 0 R +126 0 R +127 0 R +128 0 R +]endobj +130 0 obj<>endobj +131 0 obj[130 0 R +]endobj +132 0 obj<>endobj +133 0 obj<>endobj +134 0 obj<>endobj +135 0 obj<>endobj +136 0 obj[132 0 R +133 0 R +134 0 R +135 0 R +]endobj +137 0 obj<>endobj +138 0 obj<>endobj +139 0 obj[137 0 R +138 0 R +]endobj +140 0 obj<>endobj +141 0 obj<>endobj +142 0 obj[140 0 R +141 0 R +]endobj +143 0 obj<>endobj +144 0 obj<>endobj +145 0 obj[143 0 R +144 0 R +]endobj +146 0 obj<>endobj +147 0 obj[146 0 R +]endobj +148 0 obj<>endobj +149 0 obj<>endobj +150 0 obj<>endobj +151 0 obj[148 0 R +149 0 R +150 0 R +]endobj +152 0 obj<>endobj +153 0 obj[152 0 R +]endobj +154 0 obj<>endobj +155 0 obj<>endobj +156 0 obj<>endobj +157 0 obj[154 0 R +155 0 R +156 0 R +]endobj +158 0 obj<>endobj +159 0 obj<>endobj +160 0 obj[158 0 R +159 0 R +]endobj +161 0 obj<>endobj +162 0 obj[161 0 R +]endobj +163 0 obj<>endobj +164 0 obj[163 0 R +]endobj +165 0 obj<>endobj +166 0 obj[165 0 R +]endobj +167 0 obj<>endobj +168 0 obj[167 0 R +]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[169 0 R +170 0 R +171 0 R +172 0 R +173 0 R +174 0 R +175 0 R +176 0 R +]endobj +178 0 obj<>endobj +179 0 obj<>endobj +180 0 obj<>endobj +181 0 obj[178 0 R +179 0 R +180 0 R +]endobj +182 0 obj<>endobj +183 0 obj<>endobj +184 0 obj[182 0 R +183 0 R +]endobj +185 0 obj<>endobj +186 0 obj[185 0 R +]endobj +187 0 obj<>endobj +188 0 obj[187 0 R +]endobj +189 0 obj<>endobj +190 0 obj<>endobj +191 0 obj[189 0 R +190 0 R +]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[193 0 R +195 0 R +197 0 R +]endobj +199 0 obj<>endobj +200 0 obj<>endobj +201 0 obj<>endobj +202 0 obj<>endobj +203 0 obj[200 0 R +202 0 R +]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[205 0 R +207 0 R +209 0 R +]endobj +211 0 obj<>endobj +212 0 obj<>endobj +213 0 obj[212 0 R +]endobj +214 0 obj<>endobj +215 0 obj[214 0 R +]endobj +216 0 obj<>endobj +217 0 obj[216 0 R +]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[218 0 R +219 0 R +220 0 R +221 0 R +222 0 R +223 0 R +]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[226 0 R +228 0 R +229 0 R +230 0 R +231 0 R +]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[233 0 R +234 0 R +235 0 R +236 0 R +237 0 R +238 0 R +240 0 R +242 0 R +244 0 R +]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[246 0 R +247 0 R +248 0 R +249 0 R +250 0 R +251 0 R +252 0 R +253 0 R +254 0 R +255 0 R +256 0 R +257 0 R +258 0 R +259 0 R +260 0 R +261 0 R +262 0 R +263 0 R +264 0 R +265 0 R +266 0 R +267 0 R +268 0 R +269 0 R +270 0 R +271 0 R +272 0 R +273 0 R +274 0 R +275 0 R +276 0 R +277 0 R +278 0 R +279 0 R +280 0 R +281 0 R +282 0 R +283 0 R +284 0 R +285 0 R +286 0 R +287 0 R +288 0 R +]endobj +290 0 obj<>endobj +291 0 obj<>endobj +292 0 obj<>endobj +293 0 obj<>endobj +294 0 obj<>endobj +295 0 obj<>endobj +296 0 obj<>endobj +297 0 obj<>endobj +298 0 obj<>endobj +299 0 obj<>endobj +300 0 obj<>endobj +301 0 obj<>endobj +302 0 obj<>endobj +303 0 obj<>endobj +304 0 obj<>endobj +305 0 obj<>endobj +306 0 obj<>endobj +307 0 obj<>endobj +308 0 obj<>endobj +309 0 obj<>endobj +310 0 obj<>endobj +311 0 obj<>endobj +312 0 obj<>endobj +313 0 obj<>endobj +314 0 obj<>endobj +315 0 obj<>endobj +316 0 obj<>endobj +317 0 obj<>endobj +318 0 obj<>endobj +319 0 obj<>endobj +320 0 obj<>endobj +321 0 obj<>endobj +322 0 obj<>endobj +323 0 obj<>endobj +324 0 obj<>endobj +325 0 obj<>endobj +326 0 obj<>endobj +327 0 obj<>endobj +328 0 obj<>endobj +329 0 obj<>endobj +330 0 obj<>endobj +331 0 obj<>endobj +332 0 obj<>endobj +333 0 obj<>endobj +334 0 obj<>endobj +335 0 obj<>endobj +336 0 obj<>endobj +337 0 obj[290 0 R +291 0 R +292 0 R +293 0 R +294 0 R +295 0 R +296 0 R +297 0 R +298 0 R +299 0 R +300 0 R +301 0 R +302 0 R +303 0 R +304 0 R +305 0 R +306 0 R +307 0 R +308 0 R +309 0 R +310 0 R +311 0 R +312 0 R +313 0 R +314 0 R +315 0 R +316 0 R +317 0 R +318 0 R +319 0 R +320 0 R +321 0 R +322 0 R +323 0 R +324 0 R +325 0 R +326 0 R +327 0 R +328 0 R +329 0 R +330 0 R +331 0 R +332 0 R +333 0 R +334 0 R +335 0 R +336 0 R +]endobj +338 0 obj<>endobj +339 0 obj<>endobj +340 0 obj<>endobj +341 0 obj<>endobj +342 0 obj<>endobj +343 0 obj<>endobj +344 0 obj<>endobj +345 0 obj<>endobj +346 0 obj<>endobj +347 0 obj<>endobj +348 0 obj<>endobj +349 0 obj<>endobj +350 0 obj<>endobj +351 0 obj<>endobj +352 0 obj<>endobj +353 0 obj<>endobj +354 0 obj<>endobj +355 0 obj<>endobj +356 0 obj<>endobj +357 0 obj<>endobj +358 0 obj<>endobj +359 0 obj<>endobj +360 0 obj<>endobj +361 0 obj<>endobj +362 0 obj<>endobj +363 0 obj<>endobj +364 0 obj<>endobj +365 0 obj<>endobj +366 0 obj<>endobj +367 0 obj<>endobj +368 0 obj<>endobj +369 0 obj<>endobj +370 0 obj<>endobj +371 0 obj<>endobj +372 0 obj<>endobj +373 0 obj<>endobj +374 0 obj<>endobj +375 0 obj<>endobj +376 0 obj<>endobj +377 0 obj<>endobj +378 0 obj<>endobj +379 0 obj<>endobj +380 0 obj<>endobj +381 0 obj<>endobj +382 0 obj<>endobj +383 0 obj<>endobj +384 0 obj[338 0 R +339 0 R +340 0 R +341 0 R +342 0 R +343 0 R +344 0 R +345 0 R +346 0 R +347 0 R +348 0 R +349 0 R +350 0 R +351 0 R +352 0 R +353 0 R +354 0 R +355 0 R +356 0 R +357 0 R +358 0 R +359 0 R +360 0 R +361 0 R +362 0 R +363 0 R +364 0 R +365 0 R +366 0 R +367 0 R +368 0 R +369 0 R +370 0 R +371 0 R +372 0 R +373 0 R +374 0 R +375 0 R +376 0 R +377 0 R +378 0 R +379 0 R +380 0 R +381 0 R +382 0 R +383 0 R +]endobj +385 0 obj<>endobj +386 0 obj<>endobj +387 0 obj<>endobj +388 0 obj<>endobj +389 0 obj<>endobj +390 0 obj<>endobj +391 0 obj<>endobj +392 0 obj<>endobj +393 0 obj<>endobj +394 0 obj<>endobj +395 0 obj<>endobj +396 0 obj<>endobj +397 0 obj<>endobj +398 0 obj<>endobj +399 0 obj<>endobj +400 0 obj<>endobj +401 0 obj<>endobj +402 0 obj<>endobj +403 0 obj<>endobj +404 0 obj<>endobj +405 0 obj<>endobj +406 0 obj<>endobj +407 0 obj<>endobj +408 0 obj<>endobj +409 0 obj<>endobj +410 0 obj<>endobj +411 0 obj<>endobj +412 0 obj<>endobj +413 0 obj<>endobj +414 0 obj[385 0 R +386 0 R +387 0 R +388 0 R +389 0 R +390 0 R +391 0 R +392 0 R +393 0 R +394 0 R +395 0 R +396 0 R +397 0 R +398 0 R +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 +]endobj +415 0 obj<>endobj +416 0 obj<>endobj +417 0 obj<>endobj +418 0 obj<>endobj +419 0 obj<>endobj +420 0 obj<>endobj +421 0 obj<>endobj +422 0 obj<>endobj +423 0 obj<>endobj +424 0 obj<>endobj +425 0 obj<>endobj +426 0 obj<>endobj +427 0 obj<>endobj +428 0 obj<>endobj +429 0 obj<>endobj +430 0 obj<>endobj +431 0 obj<>endobj +432 0 obj<>endobj +433 0 obj<>endobj +434 0 obj<>endobj +435 0 obj<>endobj +436 0 obj<>endobj +437 0 obj<>endobj +438 0 obj<>endobj +439 0 obj<>endobj +440 0 obj<>endobj +441 0 obj<>endobj +442 0 obj<>endobj +443 0 obj<>endobj +444 0 obj<>endobj +445 0 obj<>endobj +446 0 obj<>endobj +447 0 obj<>endobj +448 0 obj<>endobj +449 0 obj<>endobj +450 0 obj<>endobj +451 0 obj<>endobj +452 0 obj<>endobj +453 0 obj<>endobj +454 0 obj<>endobj +455 0 obj<>endobj +456 0 obj<>endobj +457 0 obj<>endobj +458 0 obj<>endobj +459 0 obj<>endobj +460 0 obj<>endobj +461 0 obj<>endobj +462 0 obj<>endobj +463 0 obj<>endobj +464 0 obj<>endobj +465 0 obj<>endobj +466 0 obj<>endobj +467 0 obj<>endobj +468 0 obj<>endobj +469 0 obj<>endobj +470 0 obj<>endobj +471 0 obj<>endobj +472 0 obj<>endobj +473 0 obj<>endobj +474 0 obj<>endobj +475 0 obj<>endobj +476 0 obj<>endobj +477 0 obj<>endobj +478 0 obj<>endobj +479 0 obj<>endobj +480 0 obj<>endobj +481 0 obj<>endobj +482 0 obj<>endobj +483 0 obj<>endobj +484 0 obj<>endobj +485 0 obj<>endobj +486 0 obj<>endobj +487 0 obj<>endobj +488 0 obj<>endobj +489 0 obj<>endobj +490 0 obj<>endobj +491 0 obj<>endobj +492 0 obj<>endobj +493 0 obj<>endobj +494 0 obj<>endobj +495 0 obj<>endobj +496 0 obj<>endobj +497 0 obj<>endobj +498 0 obj<>endobj +499 0 obj<>endobj +500 0 obj<>endobj +501 0 obj<>endobj +502 0 obj<>endobj +503 0 obj<>endobj +504 0 obj<>endobj +505 0 obj<>endobj +506 0 obj<>endobj +507 0 obj<>endobj +508 0 obj<>endobj +509 0 obj<>endobj +510 0 obj<>endobj +511 0 obj<>endobj +512 0 obj<>endobj +513 0 obj<>endobj +514 0 obj<>endobj +515 0 obj<>endobj +516 0 obj<>endobj +517 0 obj<>endobj +518 0 obj<>endobj +519 0 obj<>endobj +520 0 obj<>endobj +521 0 obj<>endobj +522 0 obj<>endobj +523 0 obj<>endobj +524 0 obj<>endobj +525 0 obj<>endobj +526 0 obj<>endobj +527 0 obj<>endobj +528 0 obj<>endobj +529 0 obj<>endobj +530 0 obj<>endobj +531 0 obj<>endobj +532 0 obj<>endobj +533 0 obj<>endobj +534 0 obj<>endobj +535 0 obj<>endobj +536 0 obj<>endobj +537 0 obj<>endobj +538 0 obj<>endobj +539 0 obj<>endobj +540 0 obj<>endobj +541 0 obj<>endobj +542 0 obj<>endobj +543 0 obj<>endobj +544 0 obj<>endobj +545 0 obj<>endobj +546 0 obj<>endobj +547 0 obj<>endobj +548 0 obj<>endobj +549 0 obj<>endobj +550 0 obj<>endobj +551 0 obj<>endobj +552 0 obj<>endobj +553 0 obj<>endobj +554 0 obj<>endobj +555 0 obj<>endobj +556 0 obj<>endobj +557 0 obj<>endobj +558 0 obj<>endobj +559 0 obj<>endobj +560 0 obj<>endobj +561 0 obj<>endobj +562 0 obj<>endobj +563 0 obj<>endobj +564 0 obj<>endobj +565 0 obj<>endobj +566 0 obj<>endobj +567 0 obj<>endobj +568 0 obj<>endobj +569 0 obj<>endobj +570 0 obj<>endobj +571 0 obj<>endobj +572 0 obj<>endobj +573 0 obj<>endobj +574 0 obj<>endobj +575 0 obj<>endobj +576 0 obj<>endobj +577 0 obj<>endobj +578 0 obj<>endobj +579 0 obj<>endobj +580 0 obj<>endobj +581 0 obj<>endobj +582 0 obj<>endobj +583 0 obj<>endobj +584 0 obj<>endobj +585 0 obj<>>>>>endobj +586 0 obj<>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ŒË‚0D÷|Å]jb+· %ܑ Ôh¤(©i‹†¿·u£›YÌÌ9{l9°x»„f€Yì’w+8œëZÕ۷Њî1Lƒ±ZX¥ TbšÅ¸æwÇǀèyŒ#‡Œ(óϓ¶¨R¤;%9M°„Æ~/…Y~þZ«n¾Xóý9Qò'RÏEכÌó”°0 7PŒ#4¾4ÐH#õKv-yp +>P™òûendstream +endobj +587 0 obj +6286 +endobj +588 0 obj<>>>endobj +589 0 obj<>stream +xÚ+ä2T0BCc3JÎår +ár á +äHÉHendstream +endobj +590 0 obj +31 +endobj +591 0 obj<>>>/Annots 20 0 R>>endobj +592 0 obj<>stream +xڍVMoÛ8½ûW zJ€•ª/ËòÞÖušõ¢Iµµ³Øƒ/´DÙj(Ñ%©Þ_¿3¤üÙ$( ¢øÈyóæqèƒü…0Š N¡h“Åàãç1D,*HÂÄA:Ê`QÞäŠW¬à·‹ïˆH á9ˆ'‘j±©5hY™SXÙÔm­bF* k;&`«äK]r/uk¸:‡Õ²…º­¤jÜ;¾Ùpø$›‡O³‰A^»ˆ9mR·k˜ïµá́_FôFŸBâ-³‡Kêa„ìÝ,o>|zÊçkãÌO~aí‡åíoð•&¶¡úCßaÇެDa£@î†pG¾âŠ—šïz·~€u GHo÷¤¡ŸA„ÏH2J֍Ì]•dœˆpw§$Nò2ØJeØJp§4‰$Ø'UIÊe4L½Ó¼¹å$?B´¥¨}˜Ø0 +Î[(ù ˆ)aµ[KÊj 7wLïßL%¤)¦¡vn@Ù¼’ý Ð@—ö¹ÓpÜëy°Z®dÙF_r ÜÀH¦‘] Ú°¶dª<颥莆cBXy°®mIÆE4t‹ìÅÄWV$£öþÇ®™põÌßCöÅž¨[Öôt–´ßo¥.»9ÒÖó3µÜÀÑ☤‘…dØYž£÷€9,‘Ç8lM`›|—+ÇÿGÇ;Œ DA¯#´Æ”q:hàK>¥st*~àZ³5‡‰Å3MÏ&Öû´÷Ûí?#Õå óŸ}æÃ_ÜLkÅ ƒ[l{ÚH„š‚Ðò*¸î¶dUt×®6PK‰ƒªk * +µÙ÷Ò³²Ô€¢ì¤z>6•’;M9™\j3/T½í…ãê*ڔk;]»^E=¬³1útK#’Aµec÷¾lÁ©7NeÑ5˜õEw<ïs^4r}îWnDHµf­éI{N*)„ÜÙÏ­·ôïo¶¬8ÅÆSã–•`¦öýŽuœo`¿=Í701÷w°§ùoÓ|@t:öÇ'ôdñJËÆ;?IÐ<¸ºH/ªðsGýø¹8üáMÐ.Ë(+Zv˜Œ2LÖsQÎþB$Y€ì쪰/À߃ÿ"}}Àendstream +endobj +593 0 obj +982 +endobj +594 0 obj<>>>/Annots 33 0 R>>endobj +595 0 obj<>stream +xÚ­˜Ysâ8Çßó)ú1Sµß6;O¹fjj3Ùl`÷)/hãk,9Ç·ßnÉÁLj‹JŠDæ'¹ûߗáÇY>þ¥ô»(Ï.gg7³3ßóñ:½ôòðßõ|Hsz-!޽°_0ým%$Ñ´”0‰½ÄI[@ Ay· ä“̋ݼE ŸÇÞÄâ/Ò¦]ÃøKŒ·ÙŠ4Ló fËóFpىb)ª5°j ß*©XQÐòêïûé§Ù¿ÖIþö¤EÒ(órŒ žô¦îˆK"=ÄE/\qéi#»ƒ¶TÂ÷½Ô‰ÛòQŒwüÊe²èq„Ú}g[“X÷­¨oåiK&hê ˜^¸ëi£‡ƒ¶€ò„2ÇA[%r¾‡!WJr£¿1ÊÕ«W“’ŸX¬8ŊÄÒ —X=m´pЀbQš¸h  \ÌH¬-~„X1U5ú› XW…à•‚)W]sZ¥"òiPJ/\Jõ´ÂA[öǀړƒ¶T*L©&¸M˜~ç[üÊFä ê“iHU;}“Š—¦Šy‰jŸVçзæ^¸tîi#£ƒ¶€AgmfeNÜ&šb.Þ"Ïò=㏈Kš™•¡6ð§Ú`£0:q£ðS3†RòT/Þ ËÀ°$”Ú0,9Msm4„’p› ô¨±lù#dö33´.Pèi½R/¬åp+¼’.Ö-?}ú'“ÈL¯M7‹wu¶4Êè;i Ð:gNÚ(ý· Jç‹gǬs‚}zÚ]R¯Ë²®àŽ«—º}¢FNé}ÚdNrßL=­¡^¸Dîi£¡ƒ¶œziè -€z¹¿‡!Z˜©we="\·âùÔÏSIš™ÁG…mŽÊh]Ø.ÚJÀ”Iœ´hic'mô@‘£·;üiÓ܌½k”öVHõ +¾ˆâÄÏ^I›I§}Ӌw„Ý(lL¾9h  ¼š`Ósá6AÅKeëä-¢„0HPª„¸IBúÜ ´³¶îæ¨ê¦®õëKÿ¾­ñêÿš_ã/4P¿R GQhŠä®VL <üª®ž±gã¿ÒlLóqKfÚÐ?¬u'aUã“$}¾“o•b¯°ØíšäK¨°îĒ{póÊÊ}Òûp‹JÎ*jaúîћµs0 +"“iüµ)˜¨ð¼9/ê—ߍmIo[Ò§'²O;Ó߃˜`2D¸ærъ†Ì3»ýA§0£É·Õ¢hðÓª:0À\|<?íëԜl¶áP±}À’X`¼Ð'ù™…•håá©¥‘‹`6àP·°êª…~CT;Û°†z™ (‰ò†ûqsNJ¾ÁgPÜœVu圷žq€mÝ×lÝ?³öàq'Û±Ü`XƋ®‘ã%Sl¬¸T õU¯‘.I¨1èÐ.E‹vÔí›QÈ;Œ‚1#NL’=ðÞ¾]“§}a¤u/àé8PËN5êOÞq²h`´„¦ +4‘l‚›»ÙÍû7¸³‚rå¯ð.ŸA6|!ðÚ“Pˆ'¾_KÄ_œ}®Ë+äâö®.î§ÚêC[ƒÐÓN[–Üé@JS\Uú¨—V(…t ê ˆ6+w çÞã'P5î_ŠS\Ÿ²DOʟ¨¦64ö"´06^Ìç-ÌÝ6¨6LÆêï…ì=»v¡6ØôÖ ¢i&©ûzOwmM0÷~šïߐÞlÿCõü õ7*ªÀcÐËýÓFöqßÇ}çkfçI–~xâ×þÄ|hVA ¿òëUÑ߈힞/–¥¨p¤¶ +E҇Ⱦ¦GALz”…:Bºá3NßÝÞkà8^ÿ:û'Ùøendstream +endobj +596 0 obj +1408 +endobj +597 0 obj<>>>>>endobj +598 0 obj<>stream +xڍ‘ÑNƒ0†ïyŠÿRË(t.§Q¯ŒÓ±¨PXmK¦ooË6#1Ó«žžïü_Nß"ŠÄ +ž"ËQ÷Ñe-n(EՆj^pTÍÙ­êÄӇ“öƒMxÆ-R†©x^={ªå"#lç¼w;ið([i¤®O­ù1Àg’”:¯¶ë 6CëöÂH¬ÍÐÑ÷ÒXÜ =Š—ɾ‘4‹Ó@®ðúՍnTDë-•vÒ´¢VºÃ^¹„n¾.ߝÔM¨z7L±öÏõÈä—Çì§ßÖþËLÃG‘ÑÎÄFûWxqZþÒÏ Ë2ÌÁ<|ÕôJ+ëŒpÃ̂PÆ=å ùmù¬HâÓsî×Uô} .—’endstream +endobj +599 0 obj +273 +endobj +600 0 obj<>>>>>endobj +601 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS041×3R072PIÑPp VÎO+)O,JUpLÉÍÌË,.)J,É/*VðMÌ+MÌÑ Éâ҅è҅j3‰™…À|ÿ’ŒÔ"… Ô´Ô¢Ô¼äÔb´kW íâ%Üendstream +endobj +602 0 obj +127 +endobj +603 0 obj<>>>>>endobj +604 0 obj<>stream +xڝUÁrÓ0½ç+öØÎ¤¦IKҁ4LRàЋb¯cQY2’œ¿ç­ì¤Áía:“iâÝ÷Þ¾}’&t‰¿ ͧt5£¼½]^}¸¥é%­J|β+šÍohUœMè‚^ۨ톖û¹¦»-û­æÝùê'Ú®i2‘¶‹®ïâêzšM¥uUé@y¥šÈžﶺà@ʒëûɕT¹Ŋ靫kgéþ˧ÏøvÎ?†¬c»¥É\Ø.A4Í®;~jYx·6\ÿ- ÅÓy6“âÎӞ•ԕÌú’3ÑPš—PΨR£6-IiF÷ÖèG¦Ï:÷.¸2>L_Ïè»¶…Û…ô?è>«œî–ãn6°N€!jrÕ9¢²…òž}©r–¾ÐM¯­pâ§R~k›Æù^cª½s›äbp¦ÚYøÞzÏ6š=©­ÒFaœ±” ˜ß²dè²ÅÁîoO>t°4Ï ¿v!â)o•xփMgÇE~ÞÜk&£-UÓÃYäߑœ5û‡swìeîuŸ‰¸WM¥óðp>Nßw:VC]͔;õ[wvì)GÚ֐­ +èwG%ŠÊÖòÊnXBxäàR›äu­"¼ýèvŒ¸Ž“«ã±Ê‡¼[å5ì$1)íÙ5ìՉ „^àS¡Ë’e3CŸÐ +±Òoe䬯5'‹¦Âk( rI…‚˜ðåy†JáX‚Âs͈‡ÒykbF«JEøW¯±¨Îà¤ÇèZG.†C#jubËÛá<èD‹øÓYp°E"'90ûütólÇ]XÌ“QۜÆ[ ”Óš‡¹{w¿XÊP¸^ôF¤‘EµU‘ÿãœgtg%HéF®©ÖYÐç9zAj?{8MÝ_̖¹â€ä /¦ÄM£vEk”—dJÉÓ%ð>'¤†g$Èq—™ç'e,ô„g±9M~·~£c4é2²°´Ä3Äd©-¸“é‡[}@¾v}tŽ7Šñx×M‹ñ$Œ;pÜ¥N5Ñ¹J÷®q³jàš-—âI:kzHlñR‰œWÖ·Ùw3@9^Bñð +¹yz+ÌçÙ?½å®o.³[4 ôµ|¿}ý üjºendstream +endobj +605 0 obj +836 +endobj +606 0 obj<>>>>>endobj +607 0 obj<>stream +xÚ}WMoÛ8¼çW<ô”¶»““¦Ù¤H°ÞÚÅ^z¡)*f-‘*IÅëþúGJ²-ÄE$²È÷13oHÿ:›Ð~&ôqÆ¿²:»]ž}¸ÿD“+Zx3»žÐ2?_®-•\[ڗÝûåO,º¤É$-O¯²/ûü}¾ íi%¼Ê©©­!aHUʽhóB&(gT „É…ËIвÄʀðý˹Ó&ðò¹³ÁJ[fô8ŸÓZ ®R†“#åäc6唪Z9!cµ£ÜþVƓ-¨æÊ!{Þÿï•{şJ˜¦24N9 `ßÔµu!…yÖÒYo‹@ÿj“Û­¤œ^\\dígÓYvɟq…¹*´Qˆ¹ï¯n[ ÂºT7†N¶ª,ù/ª›ø’~ڕ?*ÚÖA[ôTꍢJåZ Šñú·‘Sޖ /ÅíÞrưÎè‰7e`8N´t5ùQÄU‚¡•¢†_•– ÙеŒÕ/ÁR·5zZ7&w*÷¼/¬mãQB¤¡Ò%ã±»Œ¾›ØƒELwXÃÚnr¥bD‰Ê[2°QJå‡èKk‚³%úl +€J±ï[évuz®Ä†Õ„T\SeB»µX•*¡¤$T°ç¥ÃMˆ¡Îl™3à÷-ê!¡Rì@ ÞnkîžÑ{ØÕʍ—ê¿@K'ŒçÆzaӏówËåüݏ÷´]k”ˆ8¼ DéàV­ZÝâqXÒ!;-רö W&‚¥W­¶ ÙT@ªÅI®•ܰDCãI褊o¸r±^70ØAæ¨ZÅ¥j×핲Þ+Ÿ¨ˆRn<ãšÖq/+‡ò”B}šxÕyœi«ºTA±&>L² uÊíˆÚù *¦)ì·Ý49¢;ý¢|H5D=“T.è‚u¢}K(naèF€¬X…~n’©ÕZ荶C†A¯B—QbÚPÑ°Ï ²2›q¨A0wž%?ݛîøã4áòž4Û/‚)0a‰«ÀáŠ8p—èj«Jvµ#ûÁ›Öw¥è³6ú9H;ÎwžÑ×èI˜ lÈ䒂£5ŠLS­”ÚR.y]ÀéÂÀrÈC¿6|ËRã%²)…ƒuz¬nÚø&ºP/ƶvªhkñª:g2꽕ZpÏ[Ö,½ +8)6[öOJŽ™ªf̤­u'Z$´N‡ÝiJ>'ÿùì C^*:¶{ÇÜ»5\ÒùVôŽørqYDÄnqÐ$HÙ +í|‚ÒK²›nmââçt¯÷ºäjOöÚ¾O®Ã‚ðÉ8D]—ÝL¡¬t´Á3v`‡~/T¦È6`N*øÌÊÒ ùǾeÆu¨±t Gb%,LU°Ëc_Þ:OՊ­“ÒÂVÝú8Ì“u³c)×E`Ȝ¼±(ÄzûŒÂĈ€|îgô7Ÿqžàü:áŠZ!DYPæbÂoüŸí°«õh†ÑÔ§ˆ Œèa>þëéô{œßÝwÿræÀGQ|ÎÞ´?€KÌÍ­ étÒE©OC߄çÎã'8ÏØQ´oñ<몎Ðu0ijCÇ8èò +*QwÒ-e¯— +èh=©á[!7Ãiw zºx0*ŠvyˆgKŒ3ߣƼ`Ö\+½$ó\ÑÍâaq'é]uùø×/$û4î:ºebðû▢»¤Çþ¢†[ÀÖº Î|‘.nóùh€ñWAÔM]/,R‡ïS '\^Óì!àP´ +>ŸæwÌgcËè&Ï5+Gk_|t÷ƒ“o¸«GVK ƒ} Û÷ÖÌ/žo»€ˆ Ë&?pq´\Ç£bqó|{C|=‡ñ©–øë–×Éåή?%¤£Â1ñi- +¯´Ñ^,¤ùŒo¢äã´o|5½àm3þìòâ:ãoGo~ûù²<ûçìH]]áendstream +endobj +608 0 obj +1453 +endobj +609 0 obj<>>>>>endobj +610 0 obj<>stream +xڅUˎã6¼û+:{ɰ5~Áž¹%³A²ë`¼È™#Ñ#f(RaSãè﷚”¼¶7‹ÀY|tUWu·þ™,hŽß‚¶KZm¨l&ûÉí‡5-´?`gs·¥}uó Êí*&4)˞:ÖEO•Ž:4ÆiŠ5¶^•±êÉj¬¿šRsAŸqT!v-iUÖô”C‘A0~Aƒ¤ÈŽä?íÿžÌi¶XKÁ¢‰Ä]ÛúyJ +·•ëÉ8\mT4Þ\År$Pо–wký‘·V¼i{böQ[Ko?ïS€+påèýîñÓGzŒ½í˜Þz ª›ùœÚ`ÒN€1"«¬Å AˆÒbšRÓÿª¦ ~ûážÛ¬ìlµ,Ö³‚½ æUÎç¾:0[n‹Íù¹*ŸCú™yégñÈÃ<—ÆF9Æ­.ÍÁ”BPÌ‹|Õ¸ÒvôåÄqܽ6a”l~ÕG«cœí ¡ +ý®X‡ßtL¦¼Óü"ÿ‡0œ³„÷³Ö¸)-×ùy®h2ô +rØßÕ^dÂôWml*4Ö'*OÎGzÖN‘M£,ù.¶]L¤ÅýÊ:hwb•*myz…Œ³½Älƒ5•F±0´KwŒ{NUºä1¡ÕþH½ï¨D±ƒÁ +Þù£;áŒDå*÷Ձ«ßâ6ØFºâÌ÷«å£ŽG^Àåÿ +%#–V1ÃáÔ#š¬/¡ ÷—š¹‹^z˶'®±VÑÑĚ<·áèé¾Ëð¹»®û%÷šÈ4XKËKEh£“…˜8b– 8šiäÅgP_`#·Þ[(ÎÙUÀ]@é ÇDÕò™E„Fõ²Š)¤­.£Œš¤Áÿ©'§Mi +XO}bâùÙÿ9óxS ˜ËMö#õQšˆCÅ0ec6ƒ17­eJL°ÁŠKßn¦t¬ 梘Qz+1ÐXúø¼nÁoô2Ù#™²vŕç³ï¦³ÑH«çt£j¨l™†cȶîY*b´{dr1ѦÄþ¿Æ¦à!÷c„œ¶—Ø(E¢¥=Uƒ»ª ]ªS$5vÈttcHzj¸”Òú7 J] $§¥ž?ô¤ž0&¾rKbˆò|E:Ò9«9)ICq‡º‚ŸñUÄø!}7½XoqlµÚwr8àGˆGqþ— +ßP“†ŠGˆ?”ëT*ïY¾7Û.çßùX¬ïæÅ=¥Ý­¼¿ßOþœ|Ù䞗endstream +endobj +611 0 obj +924 +endobj +612 0 obj<>>>>>endobj +613 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS041×3R072PIÑPp VÎO+)O,JUpLÉÍÌË,.)J,É/*VðMÌ+MÌÑ Éâ҅è҅j³‰™šé™+€ùE™y%©E +.E™e©EÅ Y×®@.˃%«endstream +endobj +614 0 obj +127 +endobj +615 0 obj<>>>/Annots 39 0 R>>endobj +616 0 obj<>stream +xڍUÛrÓ0}ÏWì0$Ší„\x£¥é„NhÒáò¦Ør"°$#ÉÍäïٕrqK L§Ê(Ý=:{öìöW'…Rg0A®:«N6…,U éxÌÞÀh<Uñ2ƒ\4²*¤Þ×̵ó¼ªèzy·X¾ZýÀÔ!¤)¥öbno0ÌXFé«­toyí…·5;x€7°&Ѐ(#"ø­€K£”Ñpw3ÿ + +µ§w–{ç…b0/aoàVs)¢pµê$,ÁªèH鸽†A6`SK§øoώ}–À”<= ÐÃð—¾~ÛïãÉÖãv ›Ù¯›uÿÄâéño­„Þ†™»ZñŸ‚ö¿ÞwܗŠk¨9}ÑîãõÍl¬)K@a¸6iAÓ½J"HÄ$Ö +”üžËНÉ=8óÿl0ÁCA:IiÉÒå¿äLjµÑ 3v„ +´žiÒ)¢üÏ?×á$Á]šPøôPÐçÎoH]Gendstream +endobj +617 0 obj +886 +endobj +618 0 obj<>>>/Annots 44 0 R>>endobj +619 0 obj<>stream +xÚ¥VßoÚH~ç¯ñr©„MœòЦ!lj&¹âHÕ©/{íÙ»îz å¿¿¯mÀ5%§S"'à™Ùïûæ×~ïøàᏗ#ú “· ÓŸÁ÷!Xâ›Ñø‚è"XsˆT˜'\f„’ 2X*0cxy&ä + ý|š|ºƒL-͖iîÂl ;•ƒähg$ìášÉϊ!“°â†¼ßß:8þ¥; C›±`©UrCF÷AÇs=DNŸŸ¿‹x‡cw ø“;*?Ű Z ½‚þԃ ñ¼$Ó šâ©kcқ~»Ýºœe»lë†*é¯M£Â:ŽWǙ€?¤@FrŠs§’TĤËÝËó‚uu…®ô +ÕC)_€åF…J.I'ú+V9²&YIµ¥ˆÑŽÉÉuˆ*ªˆSHF Õðą`—ZŸ¥ŠcµE Y‘NBQŽ)€4bÝXÐ~­‘3ZÜþÞóþ1¸ÿ|LϪ0ª ‡/Y23,ŽmýlECšy·§×i²øÒÆde̋>7áñ1½ŸlòLÿdC\›vÖ´ƒHh¥ŠŒøtè5Ü®E¸¶Ԇë­†ã);à?Df(㩲ø§Ôºх—Œô*Ž“jLô&8•¢aÊJZEdRá÷bš¿-Ÿ„Û~¦Þ¯dٝI4¶9x~|èÁŸÏ÷ø fÓ©UÿïùìÄâU³B]‚‡Ð**8l)M]-jøzav©ÑrwœÆþ”ø¾aœG¼©][þÉ5L¿¾£$ý†y­¦UfS3MwÓùû‡Å‰jÜ[}ùÒn·GTÛÎ?¶™—¡•¤± X³‚½â hä‹ ûÁê\J[te.O'yah°< ëÌÉîî³M'yîøÐ«äõ_ýJŽè6“ÛaUº®{¦•>M×ò¼mÁû;6mª´©¤hÃQñýµ%J[„’ùm ó:@¥ÎÿW"PX7T)åi›;—¡Þc¤WU9‹3[†µ…Õâ¨(õ®ãXo'Ëân9ynªr=3:öž'Ñ-ó¢‚ù¢Æ§ù÷\”«î)å’lì¼Øa·l˜ˆ :̜Ùþþø +{·ÿÕ…³ŸÞ´ýýñÈ6ÓÁöW‰¸J¯N­ýzO73ÝkÖlÃ÷­HÚbof=ø–g¨7.éÓåZܑ~cLØk.b›²ú²eÍ«ËÝ2ÊKÍ̎Úꖶ(NÜJªåÔ-'t ÓÅ­Þ?GçžaR¹0—Gú¾º&>Û Vaƒ÷Q"$.TͰQ2øÄdΊ²rüá5z9׏Ü|¾zC÷ +¼ö›VÌ_ÏË,Üendstream +endobj +620 0 obj +1017 +endobj +621 0 obj<>>>>>endobj +622 0 obj<>stream +xÚåVMsÛ6½ëWìää̘(ÑúhOv,»žÆ®*«ÓK. Jh(€@)ü÷Ý)F¢”´¦§Žgh ±xowßâQŸz! ð/„ÉFcH¶½»Uo¾ê Øß·³†hÊ&0ŽØFÓ>g6# ëù­q±A³5¥¥ßº#¨¡Õ¸0„U7œâ:½úývùòôòøÃÛÕ½þCÔD ŽYDOÊ:žçR­áÝo‹WØË<½fo¤PéҀø,­£ˆÂHå¶²NlÒÒ3ë<í’^w(ˆß'}À0BÖ5y® ½mð1o~¼õîÞ2"˜Ÿµxù_•ä•$é?Ì ŒêöÞLÇlJÙ-K¥žRym*>×bB¡¿`û|77|' ©J£m³h?á +pÓ¸£f +ƒ’A\« +äkôaF8ƒÁ0ªõî—Öôm,U?) ›Âüe5_Öјþ„Š ;ÓÁáN*n*¸Ça02.ÔêB)Ø<è³Jôe— +Ïî8·«@g×0é dÚl¹³ æÜVm£`atZ&΢‚z'Só‡eºº]vf¡†©­i ÷ø4cFlõŽç`# Äüpõ¦ÐÆñ8oN²±Þ^ûȱ\<ûåýâçÇC–ô¿C¼D~Bf*bÉUs‹/Op,ÂÓ÷à¯ÁŽËÜï!<Ðø˜µ•}ùk¬#=œjQñNÍÿHÊïÛZ›b æX´V>¨¿Ø~CMB²0ÈÉ0ƒg¶e*ÀË,rFk6Ànðž@*r^}Ÿ9€KÊO›ˆLa|3­V³µßÒÛt+IƝ6ž¹*¹·­ >L†ƒoýb‰&6ȇ„acT¿öþìWjíendstream +endobj +623 0 obj +950 +endobj +624 0 obj<>>>>>endobj +625 0 obj<>stream +xڍ’]Oƒ0…ïùïåLl¥°ìC¯¦Îċù5ü…¨B;û‘¹ï[Ø—xah”sÎû䔯„AŠƒ|WÕ'·Erõ°6…¢Æ/³>ˆÉ£vžwÒ p ÷²Tñ¦œ·ª ^}Q| o +Œ>’Í£¯0 F+øVÂÝûËœ©ýž[ µ5=ðSšø•`¯Ð¥¥à ”:Ó4ø¢4pÖ‰Æñéqüąsž (w‹å4‹d1¤6¡i)<ëJ3#Vñœ´—`²í>äñíõ˜Ë`c±1’MéÐÐ ! +ª°s„QF°¬ðM6´§š(íeG…,aýT¬ßÎáÈ3‹!«ÚK‹•¸ÖXBvüðGoC1XȱYì„k1è\ÕJ:Ì8iPa}TozîU…†G6c',›Ñbœ¶=M[‰^éx6Üë`Ãuà] £Ì³4ÚX7ó<£9¤ÿþgÖEòšü’­Æ“endstream +endobj +626 0 obj +372 +endobj +627 0 obj<>>>>>endobj +628 0 obj<>stream +xڍT]OÛ@|ϯXå)‘c;i>¨ªJPh•†ðP)Ru¶/ñûÎÜ!ÿ¾»>›‚iªŠœ»Ù™ÙÙµ{„øÁ<†É Ò²w±é]/!a³ƒx ˜Í°ÉÃJ i¹†¯L²=/¹´ÃÍ/,˜BQÁØWŒ'Ó8ˆ©h“ iÎ*ªÊ¸IµH¸\À*`YGå4ì„6ª†É¬E”µ5×&ðšKˆæ¤¢\L½‡ fDjÞÚBH<f¹biþ"ôè¸ã3 $+90cT*˜å„ÍA؏`‘´-¨A¥C¯Æ2m=ˆAÁmë;eR%-\E6P<šø4°¡(ž7p3éʤ~ JÒq2ÃߩҶƒŸÛa—ÌpÀ ¥BM±—b'PŽ€ûú«õÍ·ÍÕº?ÂGï±_³u„ûM}`HþŒ@!ì%¼–6Ôõ4µñ̇ºz&U…‘=aX8Ð'‘¾O éÊh €BI¨ bš/ R{ÀÔ¹=(ýµÄŽ¥|ÔqNÉ àñy_j>SË`À—÷«;pÐ=æ¢t knpSPñ&ÃÝĬ0ML²¿¾1ýí¹ÀñS JJyÏ%GKњKíÞÓÞª”YÕrÞ֜6g¶¦D#6â—õÀH´:®¸Vø3+«‚ê°ë}Ɇxn…tÏÈêðøHìæOäØôk6kþBq~†°³¢ŠÞ¾ƒîh(WÏÆp +$UdÐr(.8²W‘ì*krOŽ ”Bîë6:òE%äNm‹í°#LÜø*gçþ<‚%ãgO½_ ã'¸¢…n™—ÍëÑg…&# +J¯àmxÍy»G¸ˆܞ¸Ì­­N\‰êÔMQe›LhžZøkد`8yÁ +ðÿ<ÈÚã]ô9a.ûEâ0ü¿’ø%gÇôžŠ§L|²‹öƒÝÌ`öï/üt>E¢@ф®6½ï½ßY„î8endstream +endobj +629 0 obj +746 +endobj +630 0 obj<>>>/Annots 52 0 R>>endobj +631 0 obj<>stream +xÚ¥WmoÛ6þž_qȗº€%[¶jÇù–¥ÉÖ!ë¼ØÅ0 _h‰ŽYK¢JRöÜ_¿;’’ÙmZ -ÜR:ÞËsϽèËECüÁxB“üâ—åÅà>†(‚åßL®¦°L{Ë ‡·ËÏøjè_õ‚{PËö@–FÈtɱ\ƒÙ0YÁždBk`;&2¶Ê8¤|'®C k¡ðý^ªDœ%¼Qp¤‰ƒ9”o“Õ!Ñ8‘gN<õR¡xbú¨%ã}(¸AEÛ>Hš+Á²§·ÀŠ””­e–É=Oau°Š½ŠOH:çf#S(XŽáÙáDB¸Gågаa»¶*M’vԑw±#¯Îc©:“Á.¢û ¾¨c©Á‚JsÒÜñ#— +±\d‚©®AÔõ`€Xì¸:ÉÜk%3›î-ŠŒ™Ðû1š„1ùq/ +–e‡>”J†+øRñÊz]Ñs‡ƒ¹Ôf‘(Q˜{Á÷\ÛD¢§Þå|þþ“FØÓZ&‚LÚ^˜ …Ÿ‡€HX#P¤heQ‚„•l… b$æÄòÊûÖ·%{æ ÅW|¯«²” +Íô›$ì[Ê01O-Z~㻎ùBAKÀ[Azß~š/ÔIV¡oä78OIãosx`óïً„akÿ7_üùfA) +è˜Åî9鄿UúhØ¥lÑԕs0¹,ݤ©(žáY)$5՝ÏÂË$S^§á„nØJ%w‚B@FúJqA0§¯6|Ndž£g­a¼ø¬XŽÙÈ2D²Ã¶¬di.ЧÞÕÓÛ.Ëlào¾êo ­Uå™îä5v•yŸ€Qж7 %*¢*Í1u mí}lXŠYB¦·ª’ù™Ú{ªï2™L,_±•9/XíÅ Òj W'Þ¹@0Rhbk+bæš.Ü-/†á»6ýDôóø+öîpñd†©Ê1ÙTŠî”Á‚Zzç†zÂjFf±íÇÓ¡ËñƘkž,fãz2Ž g-Çñ#ŽÇÖt<¾ +Çþtbzؘ>Ò+ŽcgšPӆ—>)%«ç¦N1oÅZ®\“·;A¡çyu6´!a:"–9`\ïü¡Ž ‘+¦ÆÞK#u¼=tCcé±㺸f¯”cÃ8¸õ>`„gŠ”´Z%–¤~Óယð²M±Õù~NM/º"°›OÂȨéiþGÞ͚«ç¥[9Ì&øÏ÷¤[8ÒÆ4QŽâgG)”7eɋTü ·}¸löK‡ïå7ºôÿêÎ~ŽœiÊ4Óíî´ÇÁî¶éãÅh±TÁZ t—ã˽øÊTzÙªÄÖvu ŽKå#îäÜ~ 'k0ÎJº!+C¸ñ¶>rˆ"5a¨§¡ ý¦Jü¨‚$ɤ(¬DÑ0ó”CՎikâ•èš×2§…š8Š/Ýg‚Ûwn\د"ÚÀÈÅO´#ÙØ¢•ÂÍÌ •Å+Kϔ~êÇ~hå™N_ßw¾·¹´ZÌm©Îª‡Ì9¿X÷`Usf˜z^y¹(ž"¦“ÉŒ,9-äÚì©ÝÜ7T‰…þ+𠋮îV0 éZÓÃñd‚%4|uùG¨ÿºøÑºendstream +endobj +632 0 obj +1529 +endobj +633 0 obj<>>>/Annots 55 0 R>>endobj +634 0 obj<>stream +xÚ½WÛnã6}ÏW ò²^`¥X¶ã˾¥IZ´Ènì(Z¢bn%RKRvü÷!)_ۛìÃ"€[s9s8s†úv‘@ÿõ ?„´¼øe~qõë’Ìs|2'0Ï:_˜dÏB>ÃT i¹6kU‚]r¸UeÉd=É?ο¢÷’Ä{G½Q<$ÿ9ú‡Ýð°ST,+…úxü zýaœ@ÜÙöR¹zYšrÒbd$†ù© ÷ ü«ÅЁ]K¤éPcö;Æeyê$O_mú××9Ÿû©3~md̈́S}“²?@¡RwÝ|×Y4N®œ^¢«šèz` ¸>S¨ª,¢5ð¶ýB¹‹íêh#‚ܺ¦F¨²Û‹ê/¸ýù—Ó—Ó—ÓŒñ¼•¾œ¾•¿nIq'AZl³BïxÎPèv~9Ùir ·ÈLPýCÙ{I’`ÿ 'îÑïã™Êíš.€7»—5…ïøF‰ƒAîQ2 ­ˆ-×}ç«æ`4ˆÇþ%"¹‹þ¯‹ÿâLåendstream +endobj +635 0 obj +1221 +endobj +636 0 obj<>>>/Annots 58 0 R>>endobj +637 0 obj<>stream +xÚ¥UMoÛ:¼ûWì­˒e8·¼‡ôZ´±‹^r¡%*fJ‘ªHÅð¿ï,I»¶_ +¤(, Èݝ®~Œ +Êñ+¨\ðSµ£V£éû9­ì,®¯hUWIµlÄ =u½2^öT CkIöEö½ªk‰ÕŽ<»ƒSæ),/VÏH™§”cÝÙÎ+kÜã¸x¼ˆ›ûzcªlÛ +Sgñý óˆc2»ÉæŒdéEï95NÑÒÛ®ãÅçˆÉ¦ã°ü3҈µ–çå9éÙÁZ¹×N& Ž +hìüä Ý%õÒu²òêEêÝmLRÐ çߓ٠àÛýƒûPæ·öMÊq`<™ä9HÉ Ñ¢ÇÔöyÚ±S¿2uH”þ½©ïD]c~]’8Ÿj|—;ì³}ÅA6#·GôÀ<'aB;˱ýAXœ?sÕ¹Û ÜOÊãå6’o˜u2Þ³x‘È…¡Íù?÷³4Û öÙæíࠛìñ²=+Ø +h„©0ªÍ‰}Yó-ß^P ŒxJ‡ÑÓ<º@¶h5”­É6áRýrúU²k9‹ÚF<fjzۆêßäú—g‹½Ï±O!¦€Œ†µ­DÊ¯Ý¯Fy–ã«Åÿ=üße9•èyA-Ð,€"®4-ù“vÑ?ߐ½eËbëo¼ïn§S®¨¡…¿]”ÅTÔ­2ÕC’üäo½Obt°6ìŒ$ ¢æ(’­„¼pßáå7แǜj;(ÐZ@•VÕw—¸¾NõŠùô—Eä›þýúyIKÛø-¬;†¬œï…·àj`òr‚IŒ›\Ír+ü²œçYIùÛ¾® ÿËè'»Á€?endstream +endobj +638 0 obj +857 +endobj +639 0 obj<>>>>>endobj +640 0 obj<>stream +xÚµUÁrÚ0½ó{+Á…¤ÇdҙvÚNšÒ–Œ7±$W’¡ü}W’‚JfÚC‡ Øoß>½}Z~Ž +˜Ñ§€õ+(åèf3š~¸†ù 6,fëü¬ÖW°áã%dpoP9aà¶aÖ +ûvóHè%…Ggž-–ó|î+65Z(kÖú.lip+,jæ í™ÊÈÌ`ŠC­à4H¦ØN€«…Ìc—k(־ˌÌóeäpÃ,–‰‚Ì×ùÊCnܧ^zÔJÝ4¢t¨•] è9£ç"˪g'Ï{Œsø¤·¬PÎ fÎQis`†#½ #@…Æ:_OʊE4‡í6lۈg+PpàÉ‹I[x,­höôs+@ +¹õªéšÞ< œ€Õ€ÈôV[‹ž›¤ÀQw$$iÏE…JÀ^˜#4ÌìÄ8ZGê OÇãyjÜÕY/tLjBµË{òù*&¸Î’c»¶ÕÆÙÔ[”mƒ%‰}Í܏ Ú<Ácg4ø$R ÝÞ§c˜@i£c¤–wNKæÐû[fé ]«£íÌÆ<í{”Î É!d›xôÁöS\ׂì‡m#’ށ” fï™èj Hª æt­*Üu†Åˆ†ûÀö¢ú¨IVÖ4¸<î_ ‰åðèãøW‹*Èc +e€F+µÏâv¸>¨I` +¬árž™gGCWé”ñ¡ÚùÛMIwÓ)EI™ô—‘¾BEz2Ë*qž£‹Wý‹ß¾(Ù@P-Cÿ[-iiðì3¹óê:xèâ#`6Ä­i—¨’Ò8eœÖ…²¬M+<:•)H·q¼~kpN›cÿi¼5\‡5¼¢,£ÓΚ©Ý¢šö¢!kû–‹ˆöÖŲ2…F èîëæî!Ýê¾ûjØ·É=~Ar: ßúñ&©ÁÊï'®…Uoˆ_´pè&iJ“Ôó“aªÃJí¬¸è¾¹lìÿðÎü›wW/½[¼‹Ý_ùÿ\®—ùe”ÅÚ?¸ÛŒ¾~¦øZBendstream +endobj +641 0 obj +776 +endobj +642 0 obj<>>>/Annots 63 0 R>>endobj +643 0 obj<>stream +xڝUMs›0½ûWìäDgÂ7;=¥™´“CÚ4¦ÓéQ+‰"‘Äÿ¾»Âø+v3ŒO»Ú÷Þ.'!ø !Né*šÉ—|âM !¯ðM:Ë /\AÇõÂÁ,9piDÇ¡¨™ÖðÔk½Þ|ʟp{°Þî¸oÃÂÏÕ¡äŰœV1±%^B‰ü^w¾~Ò¯[V6B‚û¶ŽhÇ¦Ý àÀõ÷üú~X›C˜Ñ¢Ka㈂Þ2É…|„»NHÃ;¸¢\Cթƞû7€zU±‚ïŸ9ÀÃe^jYX#ň¡¡V3¼flU×ù$ð$•n!Ýî¿a…^ӌÂ4x¼kžjXã;ºG Gr¦ÙlÈ¿4¦½ð}ÊX/•6iú–%ʼ l‚ŒEX2¢MC…lTå²,JÕb²<ÄÞªRT«ãð /ÚN½ˆ’ƒZ ?T셉š=ÔßY þŒÅ3(i5—lË7Œ=«Ÿ]çÆ(`xVD7ôŸvY7xûÒ$ü৛¦ÅŒ’ŸÔö¤"9ëjÁ»sãÎbmF–ïø voTÌ@!êÕÖFÛ%7¯ª{ÞET®#y«“V “)ž>>>/Annots 68 0 R>>endobj +646 0 obj<>stream +xÚ½–MSÛ0†ïù{¤‡8¶ìøƒ0Ðé¡ +é­a+XL$K†É¿ïJ²…ÃL;fâ˜<ڏwWZ=Ï"ñ/‚Œ@œB)f—«Ùâ¦Âj qœ ¤Y«êl s¸Úp&5Ü3Ý·_VOˆ&E;v'$ _Õ\AYÓV³*®Ê^)¦@±ÖÑ ¼Ò­Ý@ÙÈ5ì;W¿nï¡´¬›ڎKÍåcà<eÆSˆNº²>\RÅKu "$ Rƒ\ &£¡r ‚–5— tM5#+åüÀSó`¢²Ñ5†<‚&’5—ò.žALJ ÕÀC[ffA÷QìTàkô͘¦½ä%Õ ÅèX©7[x庶AY˸‹óšW ¦H꒵ú¨¾m›NïuL×MeWŽRbˆcÒCêÜØº^Í Äz›È|Ü}Ū!V;rØèʽlàþí¢8ù÷ ä“4ˆ§y@>-ð9É{„ÀgDy”o÷hºœ„f*úÊ%u£š7Òéâ¹g=S® +;3á`fqSŽŸ¡±Ð˜ûMÒ ¦…ŽŠ%¶¥€ÜÔÔ½œÎÌÉnéiÚP6bd˜Â}ù% ²iÞ#LYr,Ò$ï¦,Ë ðø“eÙï],PT¤nóÞ·¬äë­ih + +›qŸÿ®F¹ir¬Ñ·°{y§F{À4wöîFõÂÔ`Š÷aŸÙ4ï¨zdUßñŸP=ÝAsÑëFàf(ÿëÎÀ­Lv;þL팁ŽÈ}Lá>áTϦy@>[šNžâ=¨NŒê;þªg¡›^¯‹~£y»ëuõ×Ín‡gb$9º›“•z8¯ÞÖùÖÖù§­ó‰Ñ:Î^Ñ( šU¼éÕ0‰>Df L}†?@ÇDƒƒÑö€q¸nZZ .<³³ œ»ÿGP RÏIâ²ÖÁ¼ԉs6ÌჅg0¿†ù ð¶=_,yWŸC|1óÅgl_ÿX]ß½½I™PÓQãÃìÍìs–T0«-®°ßÝMb¼Y–Õ¼‡çPN8ðs:m¿Æª;ݛÛη[ UÕ15ÞdŽÞ±–áÅKû.¦Ý~¯Œ‰m›ïQª6]Õ+6Üó}³ÄÙ{—×$KƝÃéôsöækÙendstream +endobj +647 0 obj +891 +endobj +648 0 obj<>>>/Annots 72 0 R>>endobj +649 0 obj<>stream +xÚåVMsÛ6½ûWìøäÎX4I}÷–x’6‡tœJù JHI€%H«ê¡¿=o’"eٓzêØC Ô.v÷íÛ·þó&¢?Mü›7ï·7×Íh›á›Å +Ò»M)•”Þ“  þä’6²z–e¦¢§JéoÚ~ƒ÷Œ¢È{Oâ%{?~}ÚP"4í$%FgjßT2¥ÚPÕh:ªú`šç&9ÙҘ ’•xˆ<§ofgÙAõÑ­‹Яæ(ñážTFõAԜGÓ æÐތöFZJÍQÃFjwcÙæŒø8!³TY±ËeÐW+a§lŸ¬¨•Ñdt~"aIì¬É›Z⤥LáэCk{Àm2M^·y.Ó¦*øD·®Îƒ±õm@[C•J9æ ¿¤’¢–(;S(Z‹B¦dq¹«õAÖÉCҔö!ɕÔuÀé[rçPiÊh+- ×§ágoҚ­À„I<óµø.ÿ†ÀämboÓ";¾~â<ì‡^q9œ6ŠŠvÅ~`ûå*˜¿m?°€¾€RË7퇰_Î!=ãê_´³¬Åäñ JVÒÅ=ÝvM›“­eAŸ…{Y€Í·×û}תǪ۽³0ˆh†+¾ÛîÆdõ‘9ÿ.-”†Lƒë:€Ûáˆ4‰fKd3YÆ!»Å!¿œ†n ÿå¿âèڗ›ï¯’Ýendstream +endobj +650 0 obj +1116 +endobj +651 0 obj<>>>/Annots 75 0 R>>endobj +652 0 obj<>stream +xڕTQoÓ0~ï¯8í©“¨§i²ñÆ&à 4hBڋç8‘cÛôßsŽ“®‰`0µ²då|ß÷Ý}w?üQ(RØäÀ›ÅÍ~±~w iû +h±¼¸‚}¹ÌawVj/õvGçE˜fÑí/÷ßñY”†g«ðnµÉR’†§ûZ:à5k½°àjóÓp4p¦]ÉCgøZÀ헻8a…%1ë5ÒYL™’,fpÜän +Œ!iAò²˜)ð◇J*á€!DçD ޜ@o”Sõ "ø)‚yiôYe8ó˜DêñÙ>ÝDÑkáùšwíŒáJi÷Æ_Ç/ùðË¿Jó¨+æœp$p˜¾Q#D_×@,põLj‡¤*c›Hÿ‚ñÚе ($%ð1(uìëß0-ÛN¡ 3fëö8ÀžÉ …‰L’Q‰jYÙH=×ÇMƒYK0¶¯æWñ=~Ÿ SÉ«©f‰F:I~»_$$As†ƒ†ãó{TŸ“-ÐüI5%¡ÃMÁ.Zw$‚†¦E2/TkÍ£,±“Z)*Ö)?6\³F–"¬ ¯¥Æ.ÀNDñätÎ9Ñí„ÓâÏ"0>{R4h˜=±‡Qö(çv¥í+¸¸í¹þ•\‘¼ls<  iúۀª´-â¼ø®½è»~ʒ øË¾,A÷ŸìÙf¢ñËÙ××Âl Àýr:cËuçìÚ=HݏW9óßý%˜'߇qE"†/J&÷á83wÏ©id#‚˜G÷¢ad ¤óa­8̖§憵‚ŒLQ¸ kÇy´Ü7ÎïÒÌkã{1OCûOúþ؊þÕ$hûÛ=+2r… ƒS:øíÓâ7LAÆdendstream +endobj +653 0 obj +669 +endobj +654 0 obj<>>>/Annots 129 0 R>>endobj +655 0 obj<>stream +xÚµšÛrã6†ïý¨ìSµ¦y)åÎc{2³ëL´¶¦¶R•˜„$$$¡ð`GóôۍnȲv&Á¤²K6$6ð}ÀGP¿%"†ŸDdþVíٛÕÙåÛ\$‰X­E™Šb^ŠU}¾ÚêA¬u£DeºQênR4z…Y‹a”]-ûš.X›¾•#|ÞÕbkžÅhD¯*³éô'%Æ­j#ñ“™D‡—5Í^ÔæÛÕ/g±¸H²(ű:3 +Uë.æA#¼âòmÁ².@êEZD9^½ëu7ª~ˆ@ؚ®sòñ2×ég& ;’ªM'àWÉj+¸·H|pòö µ•ÞMՋ&1 ºÛà„hИ=šH³“u«»×¢ÎA@Ûâ☭ÅÕ£xƒ®eåfºIig +¸ÈgQÝÝ+Xè~äQÅõÇåƒxPý“ê_ +ҒL~ì*eg°•O +¦Q+p[µ•ÝF¡_$.ÆZo¦žVÁÎ /Éqvȗñ;žxÜÃ]RÀOò‹+ðîãòtöƒÞt²ÁÉP Ón×hRwzԲџHÏPõz7Fb冯!âzý8á§è@P×4ԅ½Þzñˆü=ØTŸJª5èhú½xÖãÖv×ÉV‰×ݜWÓn81%i©Hï“ìµÄ£`.ÓÎX1Âì®/ÌuØ£j¿£N±pAšæ˗j¬.û*ª/Iè%ypÂí‡Õí½Ë•8š,¼/u÷ÇW… +Ëìª]cÀ8_QĉëãÀùbüáꜬ¢UŒƒÛ—ú3i{~’§¯côu)8'ßé'uê+GÛIo*D&¤~=u•¡HÜBڟ CŸr‹xFƂ×)Œ}=ªYC¥kó Ò[àþfR,MÛª+`=àøõTa@⽛ÚGP©p2ôÏçßü㛟¿ÅíeEAHʾGè°(¸¤$óûh^ŸIgxk€) h·k$&ˆú}ü§MóJv Jh€O`…ä“é5<¸Ú–c,WjȯŠ+Ȁmˆ¥×qcÔP8s¨Ü|ÁE'¾Ñ¥t/^¢€Ü^+Xº½uâxÊE5ؼ]ÅQ  ¾$ørÿ=äc‹t>‡”iÅb3¡F#ps<1è7â¥ðAƤóåÚUU©a¸3»¸£ø`T¹Í¬ƒØú>-Jñ'ºJÜ ZQ, O]eA+}…!VSîvkežšŠŒâäj·×†°ºòÄs+’4+jy +›Å” (ìûÞL»°„g_[aC‹žÚ²Ò)[íwE¥©z^1ÛòT•föÓh–S¿Qÿ2Ý/lè³8ÛòûŸý7½yÔU]öV\²(l$ñ†¢–Ÿ¸dQR°¸àé™Ì3Jƒ8=´<¥ÍsJ’v£º}Xeels Iç°ÔòTV&/º,;ÃÖVÛ¬ T ‡Ú–§¶YI©@ê~ìkâópÒòŒj[žÒòü8–€/a•e1gAzhy*˒ã,Xš~ «,)9 ¬;mËSY2?N‚{ÕÈÀYç”y‚ÒlËSZ<{ö°…5Ãm*la[ÄG;‚møi[$ÇI°Ò­2SX—–¥Í»Úÿý„•󣜪©ÈmüÏSû¿Ÿ¦bFÁ#G °JR”¸8 ,’YæÏ²Î˜qöF­åԌp'Øj ¬¡6-懖¿B¶¬ðîL&¹Q%2ãâΞùC®3fÎ ¹ƒr×̸ø7ñg\6v˜{cª ïXï íZÆ\dÉҟs±EÝÛ¾7}À)îœY7ÍÓhæÏºÎ˜q÷­n>ît«C/Ón +[éŸvÙØ¯½w +̑.%«7é:c†Ýwf°›Õ1¿ò©Z@‰L¼,їx1Cïûv×èJöÆT…–Èè‹Ånæ¾ÎØÒᅰÚ]5ú)ôîʃ0§é*ž7;cfàƒÆÀâ1/fþ쌙‚ïðd¯ ¬Œ˜ +ž7;c¦à;>P¬!˜µùB°3f†J|§žTXSpšÍ-mÂ?È߯'¯aµ1§I{¬/³)c0H y B3Ӓù"0›2ƒ.ðçƒþ8A„‰9}I˜M†AÚ½úmRÃR^ãÎí˜8ˊCËÕ٘™8ì­=õÍ(œÍâ¯:àecFá%ðoȓgê8ːýÏy٘8è=uÍœÃ^Å1/;^öÊ>!€,¦ xMÃ0çPy‹¯8îeãòDá;ظL¿¬‘8›aùþ²1ñŸŸWrXÓpV,¾ê엌 ߫֌*äM à8+ñ¯ÿá/3s±ûä1“cý€Ù˜qøþýòZVÛÀ…Øq0/÷0'/O¯Ü7-ŠcÎ +\2ÿ3`6f&yo‚‹c¦”ð?fcF`ôé ÀÌê¼O‚Ù89~~ü7dƒ0G÷i03?Ø/s½Å昅 üO„ÙزðJµ»€G‰Ô7ƒ0éò> &SáÐ'Á¶sa"ï³`2eþ8ü%”»|;w&9Rd‘sìò׳Ìz|ƯØò„_^’°sâÙMôÄ +ì0ü.ÊÔöœ¦øf–ã}müç_ú‚EùÏÙÿÉRa5endstream +endobj +656 0 obj +1983 +endobj +657 0 obj<>>>/Annots 131 0 R>>endobj +658 0 obj<>stream +xÚ­WYoÛ8~÷¯(Ð-bZ—uì[ÏE€í¢»Ï#Ñ©Z‰ôŠTRÿûɖª¨ +°0dð˜ëûf8”þ[ùàáχ$€0†¼^½Ù¯62ð#Øp'NqP¼|çLÊ¿Åýûo«÷û•Gp+ H Qšà8À§apèÕ}§ù$ÕÞÿ õ±bRëo>xé}ô¸"2ô›Úl*q¿ÉÛ£ÜP³þ¥²®=Xûžµø{…õ ù¤Ž´Šõœ·uÝÚ~{ RNT‰eü>>>/Annots 136 0 R>>endobj +661 0 obj<>stream +xÚÍVMo›@½ûWŒrJ¤²e/ОœæÒFmíÜ|ÙÀÚÞ +XÂB\ÿûÎòaƒc7N¤HQ+x†}oÞ¼xQ°ñ‡‚ËÌo”Ž.g£Ïß< f Œ°À‡Y|>[ ¸˜ýÁÝ†Î'I¢Ö滛ÙÈ&6c>¨ùø} 4‰w3bC +Žçq{•Àt2vHØá@, •òI@Zéxž ^€Ì´ŒðšÃX±„«ï*â¥TÙ0ÑÞ&v =$ÒõLĪùXNH<ÃhR•««„k½+˜Çˆ^àãÿþMMáN8:n¸ùËÓ<º“/4qÔÚr¼=˜d*Û¤ªªsm°¨M‚aƽÅÑàt£K‘ ߪʷµÖ4­š3y×BG…Ì;íúÀŒ†é!ôå9(/Äb!3¡a½â%$âI$ ÀñF‘•²iH*>VxSüeÑPl¥ê ÔG³àNí©WªJbx‹b¡ŠTÄ0?G6¼JJ2¿hΈ:)|ÔË6 s‡ù{eš˜E]l:Æ» ñ'ðÄC…ÑŒ§hÖ,†…Y«"î—Gފ»kï‘?ÕÔh—ZكHT¶„RÕ±3½ÑgÇç:4sá¹!r¹öÂÚ«v®±]žg7Œ—Æq_ñT$ñÌ´"Zñl) Yi [Cýw¤›º·î}ÝTdî”<¦tg³Þ¤¼£ÐËmE»›\´ìf«ÌÞ¨ÕÌî0é踝Xww§å³°ƒì” ?è ‡2‚OÀ¨‡ž`îÏæêÙ®÷CâbÌotþÛ¾f4ØöÛïâÆg/l|7~pòÆß¢@º8¡··w9É»,î—ÝZ”zçVc]´4à6Ý?ïàÌ 72iK| «Ã†«_'ÛH…† ÇØÂæê™á¨=Æ÷ǦªÁq ¥åf›¼ï6Êù·Q·]²'¹Íà#2\VÇ.¹–ѱàµ\ +]6A',¥ˆÏÜÖópuÿs +Sµ(×éNâTfR—/U¡áÏ*ž˜,êùfáøNýÌs<ó¥ç2\ö¡×­_£ +ßendstream +endobj +662 0 obj +787 +endobj +663 0 obj<>>>/Annots 139 0 R>>endobj +664 0 obj<>stream +xÚ­V]s£6}÷¯¸ÎL,cç-éfÛítÓ´q¦Û™¼È lm±D$±Þüû^ A0v&îÇdB\Ý{Îý8—çQþ„F0›C¶ݬF·«Q@ø¼»¨ Ä ’Â,&ÌK2‡…ýW1(쉀Ö²½ ùôãÂVzŸ/RXåãLgŠW†Kq±ú:š~Œ;‹I4'±µYm4/ÿr|]›íê¥b‡gƐsÅ2ÿ1ÈYÁÓ`ð°AKP<ńáµñÀH¨˜*¤Ú]ºGÒ]ð;)Ž¢LàNé­¬ËÖ¬õÉrx# +Z—†<]4>2ïc’’RDÿOÑ<°³ï&áŒDöý Õ<;àŸƒ¡Ö\l\ï>}Šj½—**rØ(YWPð’iòoñ}à¦Í1Àæù?CØx¡­—)3Ù4«+=u¨s²Ë“a þìí‰I´@Ü]uÿ@pÀ ÃNæ]ª¡Ùiú‡¬/!+9ÞjȤ¶?_LþfÛãÝù,eFË­ce9æò0f¯—΋®­Û-Ö¢Èß g±ûÊ,fpÿ…Ý9ldý¢ ÛéSÚveËô¸+ß({ÿ~˳-ìyYZ˜4Ï(j¤]@¬ :”ø~“©o8»¼Ûg޾‚ÄGKb+ƒ³ÈEýºº½z³ >ð"k7ŽÍúùé~òø‰÷¡BA×kD„`¨±íÔFñ%„óK«! Xs£/¡RnEðv%y[g\îPãX¾¦+Ë\¯>]4²!l¼”TJ¢FìüJ±­6Œ‚#Ì¿3çßãG‰'GK.ðKî­og¿à>Mal7w¹øáñþdaö6Y×ùŽ ®¢F"¤ÏTÔ´´'Í©‰?Ö_¸q·ŸGQâÁý6ú}bendstream +endobj +665 0 obj +1086 +endobj +666 0 obj<>>>/Annots 142 0 R>>endobj +667 0 obj<>stream +xÚíVÛr›0}÷WìcÚ± ÀI“´é%­ÝP@Ä$ IÔÉßw… 8Ž'™éL:†eÏîJg—ƒoG ( ¦‘û¥Õèd1:<Ÿ a‘£'Jð&;8ÑjeÄqYªÕ»Åõèl1¢q@"“ï<µ€¼OÀÖ BF—âìŽWu)Œ‹?<§0s~¬9 B²]r­*àeéÀ&Œú RI±Ãf¸6¼Fèa¾{tDº“î {O2UñB’TUž†Ž§IKDä¢N…IuQÛBI {.á©Z,tüº˜Ã\åvÅqÇYUÈÂXÍ­Ò¾rÙðV„&,t£9‰Úr¹‡aÝýêÇèýÀëendstream +endobj +668 0 obj +679 +endobj +669 0 obj<>>>/Annots 145 0 R>>endobj +670 0 obj<>stream +xÚ­VËrÛ0 ¼û+pLgjE¢Ëî­ïÉ!ÓGÜ[/4%l%Q%©¸þû¢¬ØŽ“:Ó&M<±‹Å‚ò¯I1ý& Hg êɛåäüÃ’–%Efó–ÅÙ;tÊêÖkÓ¼Xþ Œl̘ŠY”qÎò!ã!xöƚµÃO¶@»ì +mQy}‡àZTºÔèÀSÃÉ`JUeÖç6h­Qèœnn"`”KÙU~ÈÕn•(%i$˜Ÿ~Ù:€µ„ZÛèÓ_òÉCÊSý@+ÕOô¤EJa뱀®©ˆã¶Ee6D´ÑXD¡ +MóhN$ 께å’qìïôS±øƒ$}„J_æ4.4ý¬Š9ñ˜ŠE& ^6희8õýrG1\Ìrzfs~ +ú#*塏.ÒYèéýoY·DoÛöbÔ?;1'òHcbú0œÆ#çÐPå?{v·ÍSl[ËߺîjµéÏþõºFX¡_#6°â¢ä_èÚBztѶ«aÒ×}± gH عD •i +G°N®H50¿1œ¶ +óêÁªóaÄd:eïh1¼¡Q(d²­ÕÜЪnJckÉ +AiM †Z±pkœ>K©`ºQø‘ðãëGyNpé"£Ö4ê”,>Up|²Õ7ID”Rð"ÌzPÂݚ®*¨½µÜP§½»ý­lzé{¢û¨öð\ҍm¦–º‰”©·Éÿ÷ö»>pSJI +B*RCFWT>|zà¦ùE´ XàvV·%€=¡%y'uÅ+6NL£6§Zlwžöذ×ýü§=ÏÑQWôfÓ4º§µ9z'9P´«û»©à;€»…z[5ôü`½/Ëç݃š^/è¹|ÌK6qГbŒIè;¦ñ^ÓOšÞúÓ'Yú×· /¥x–í­‡ÇÍNÁý„"óñnJc–¥½™Þ~û| צôk~ó¾.jÝhç­ô†œs%›.H6M2¾ü¦¹ˆïÆïCYžm_¿"Zþ2ùA»¼endstream +endobj +671 0 obj +861 +endobj +672 0 obj<>>>>>endobj +673 0 obj<>stream +xÚµVßoÛ6~÷_qȓ3Ԍ$˲ݧ¥k:X½¬v1È -b¶é‘T\ÿ÷;’²-+k“nd’x?¾ïî>Ò bˆèŠaœ¹O^Þ¬7«AÄfôþø£ ±)L²˜%0žÍYSZP:—ˆEÎôðCöWïæǰ*)|6›Âª¾E“k±µBÉËÕçÁÕ»ôh1J2–:›Õ!,FíâðV;ƒ·JÛs¯!BcnÅ#‚Ùb.J,øôö¶d²©×¨¡1X@©4¬}(Øòü ZÃÀe+°äMe½ƒK@`â1±$0­»0c²OÚ쓔ê1'öâ÷ÕÍëo’ºS ԍ±`Ðz€/fh•·7¼FxäUƒ $ðªU†…½±X;ÖÜÂ^5=;.­‹a=ü›'úøë·;»tõ}L¡ÉØÓ p?bÅ÷§ 0IòMgSºOè{î ¤ó˜BSˆ›¯¼ÞVh…˜»uÀQ’²~ˆçc±„Åt—ø»d290BÀ²®ÈŽ¾Ñ{§/tù‰ªæB²\Õ/tÙ(c¿ãu*ÚÈW%ûÏú9¶ë9ÕèË‚¤a¬Ü%^!'$í¢ ùån„¤÷5?€ë a©‰Ÿ’è99K´;¥¿¸ÁäRÑkH‚‚&â߀7s 뉸¡,X`ÁÎãu*õÈ$x»ßŠœ„¶›àLjk-Š$Q·¨M³&V†Œ]-YâY+Ò@K¶W!-ê’çH›Ð{ëñóÊ(GÂç£ÒøÃV{ÓnyÁt«ªŠ êGÔvÂnüŽP ‰¯_&«„¤JW ]™0}:€« UË2”½rèÔ£ )žã`·€ß¨àÏ녟·eå•@iý‚úÛõâ~hî/ÙqÞÓC‡æ]°Ë í‹ ÚMg³Iûì™Í&žO`«9¥»`üD¹“…úTzNö9©î6èÔã5¥ètÙø3ÏäOǞÆZY<µ†üú"Ý*cĺBË^”Ïîàr ;â-^ù¹SM0³÷Ã‹Öæ‚º ïË ҍtÊè%îE¥+ÐS‚~œiü…|îñÄCÐXm8Õ¤R$»€ù”þç(¾xÕËÙ3H.ØýekÒíÐáŸA8x]!­€ò½uH{-¼{Òµv¶gísœN @6͘ŸøåÓí–ª´;Wèë¢R«¹UDî— ¯\€QðM“ȹ%3÷2ÓqÑi:H! þÚSäCendstream +endobj +674 0 obj +942 +endobj +675 0 obj<>>>/Annots 147 0 R>>endobj +676 0 obj<>stream +xÚµUÁr›0½û+öèÌ î­i’6‡6iãÌô‹ "VˆJ"Žÿ¾»ØNœ4íL;žÑ`Vz»ûôÞòsB€¿Ò¦ äõèd1:[Œ?Ã÷ÛEÝAœù)DÑÜO`šÑšÅ>8”t$ðÚ:,¸r>‡0†E‰ðI†ÅøDɵæ Qsٙ£Å—Ãi„xq–âs´j!Â"ýŒ@ÎYÝV\ÓùÉysŠcé^û‡Y`´3/ ÀÓx8 !“g¡ÚxÊu®Dk„lܞx[ îpÉ+C%.xØåîà +¡xnÄ͍ƒÇM_I)´J4†+ÀǼbZƒhðuͨÜÌ ôä + ÂÒ&:œúÕ²üÑ}¸lrì•Rj ¤¢G¬%–JÖ¶¦Jh²öÀDŖ‡‚k#[ˆöû|CÂÙ¾FBZ¾}„5” ëN †išúaÿ¯‚k§€º0˜Ù­±oïXÕ!‰+ÙU°jÍ6–îgÔ*rÕØNl©O[q>«ô‚B̧ÛwZÞÝ MŒÔ"¸Z ǽçªÛ]€#\k +G9Ò½U…÷¯YÛr¦×y%xc@o´á55`֜7еváxÞ÷‘‡öÛi\4w{&Š“àMÅxþ/L„ PB/ÙÇFÊò¿X§oëe×ä²1JVÈæŠÓ ¦i A椺ßJ}9T‰êæ )¸ð2¼d]eÈ~ÆÅŸÖ°g£Ëgµûû˜õÿg$^o¹v¾\.ÎÞ½ÚìE ÙÃ[él]Ÿ®¼›ï¨j? +¬Jèn‰]l]N]Eñ1„É15™ÁR}<4øÌñÛvodžƒ¡d¹A_TÄ+r†~¦¹a¯äöȉ‘RkÄ fl•DžjpÅ)!ŸgAI‰G7xúúÑPþ½ƒÞÞ¯~2®·Âì…=‹§Ì°S¡ötÎCR÷ou¢ö£?Òu“N«‰^á}Lò®ÕÿZÈ{m¼1ýÝ+©6H7JƒÛϺŸ!ÕÕvdÃŒSl4™&ýüpsu ײ4kRÖû¢ NnÅPÃgÖtn¢y¢Ø^úÇiŒæ¶±hÞsÿuô –~Ijendstream +endobj +677 0 obj +822 +endobj +678 0 obj<>>>>>endobj +679 0 obj<>stream +xÚµVao›0ýž_qê§®*.PBÈÇ®k¥IÛÔ©ÙpI¼;³MÓî×ï &mTڔ ß»wÏÇ;“ß“BüDp™ú/+'“‹Û9D , +Œ¤Þ䧟xA+é®WÔXî>,~Nn“`|“’l†÷1^†CÑqD[Ž$"™g¹y¢åZrëó/nC˜û8– â„(•+‚̃C¢°áxVY6Q?n#T®76ˆâiԔoõµ€´É±ÌˆµZ5˜¤Û"‰‹‡V<М—ÌSȅá̉G´à0?o€aeާ¡²Ø>m€IÁƵR>W+K`ñ’Ønõ’Ä^Ò>°¯õumܕõPÕPýȍyÎ<<×âöÙ¼¿*©ZVt‰›Xs& +Áóßhmpû•w4n{ôeKs´I¤{8IÛøùž7v¶Lf)é÷`’Lš±lë`Ï;«p5°€Â „ûOž|ÝóÞwng‡ÓÞsç„Z¶ÖØ1Ä&*­Q}ɐšQ)þP_ +!±ÓOÂ"W#\ßÈt8'\Ô)7j)…]õYP=ïø.žfƒ¾‹ãÙhß©gt‚.áJÊ7~hcß´âGƒg$×%Š0]Á¬´ucpJ)rÖ‡Âk,î¢,ß-ÉÎõï§­1ÎЈѺóŠ–ü>ßÍsí=÷‡«ân£Í/ZÜTJ½ÁS˜2†?‡~l,7x “žc¸G’¢…YU–•¤~áp$ñ‡èÜwíÉ£øFáþpȽ¸Zn+Ö[Gëw¼ŠlK%3”›ÎCR7®ÜÝý.ÜÆ ¼ÊK¡pÎ uÚXøJUEë š¼`‡>í2ô‹ n=…ð蟘έÇendstream +endobj +680 0 obj +673 +endobj +681 0 obj<>>>/Annots 151 0 R>>endobj +682 0 obj<>stream +xÚÅWmoÛ6þž_q(P fYÔ»ömk²­@t‰û­@AK´£EUQJêýúݑ”üÙцƒ‘À$ïõ¹ãsô·+.~ÄødÕÕÏ««å/0« žDI «üZ¶P‹îY¶ÊÕƒ€w«?Qεr×˪2;ƒæ5Ô²ã]!kPÈŠM!pxÿáæŽ,U\=þh4B«Á˜çD°ð' Æ`äáÊ¥µU¢ÍÄwb³yAèvuå:.&7þ»ûÒ%£äƒ°Ôñ p?!˂ÈaVXë]öß çZöR'-¡ÏX +‘Ÿ<\©;d޶è£á‡ôZ†!ÓK¿ŽRðð}Ԙ‹‡ž‹Ç<ˏ)ˈ‡FÁsqSbÇ2ì–=ɸi±±- Æ+P°ÀqgC¡…çB1ϲ…bÊò…ËtJ'@ Þ^@kŒ6=BƒqŠ0 œd.Fx&3-(&-k(bd‹0axЉ9ŽCéľÉsX²áºø¯€v„ý{Š8D_s¡ÐÂs¡˜gÙB1e¡p! ™!‰ f¾õîEzl©C]T¯ÀóCl³*OÉ“ó÷Ž /Z‘uœ€ªW𦼅¢VE.çÉ㉻v a}”™žǂî(¸Ÿ#£'Çd–"Ðt²Ð-<ˏ72ë+QwwRvû|!d®F8ÆïxE´I,g\§¦‹n¿óª)… Léܧ¡¼tË^µKõÀ[±Ìe¶ÌúF+º°@ŸÉKñ”Ë5o„÷a,´ŸH« •µE3Às8ŽQâ|¥O˜ñ`wh¢´e¹g±†LÖš€ |:ÿmµúJ´O‚Š ï?ºwàÃx}¶§¼”*âÇÈÌØS~Ž«rèW?N)¾V²ì; ï PôdãËÉ EG\)L ·$¬Ö°ä:\v‡‹Ív¯p™Ón²Ý™wN.6¼/»¡°¾C£g°æãShº-|8ÖÚPË¡p˜'µgÑâ…*¥|Ąû†`ç úõbït¨NÓÇuÉëmÏ·„Ì·^¨×;-‘••ó˵p¶Îq éL„¼Ü´KË¢‘y‡•·•1á”;èë\´c!þQCR2ÿ"¶©À~%m·4R©b]êþ /‹¿„Žï°Ã ¦•OE^Ô[‚wˆná+xöpRõæZˆ\ä'|äî¹è¶meûQnxÈ S=ÿ/ñç%ÆÑ«<48€åJ)·AÛ_Kãø€‡^_¼Uç4ÔNY{ÿ%Ut†¦Dgªæ• v¢ï:`,é/I)4Ñ6-´˜¥‘W^2ÈYÖÂÂà f4a+`¡?®FÒb,rtÎÿ ä?Å=çÛáÿ ËñƌהaQge}N t3^^ѵ9©êÛS¢4IkÒ)q=/×7¦ÕÞ î{e_ Ã86û¢ÆÛY™¡e¡GÅNT|€t‚çÔ0š’cºUL`ÉðÃ*ˆõ°È\7=Öà^nºg"àŸòª¨ Õµ+ àw^÷¼$ £·ˆ=wêÅÄôT5ÏMf폫¿Éãý±endstream +endobj +683 0 obj +1183 +endobj +684 0 obj<>>>>>endobj +685 0 obj<>stream +xÚ­VMSÛ0½çWì‘Î×NҐ)Ê ¥t3=ô¢ØëD KF’¡é¯ï®”/´=tò1Žw÷íÛÝ·rzäô*`8æwÙô>ÎzïϦPŒ`V“e<¡‹êàL*öR6Ò¿›ÝõNg½<#ãÑ ÃhrD×úX„z P¬FE6aˆÓŸ¢i:Ž–Ô픳?eiÈÙ+‡~‘Çà}Û ÿ“µÈ£yÇ¡’ŒÙñºÒÊÖK££Ïh˓<"ÙaÃ1ÓêwaPI‹¥—½OÁø)›®Ò8¦¡ØNk©pgæP4—Á…‡Rh˜#t+ðT(@6³sÒ]3GË`1ZkV4œPxÔxÊFƒ ö‘<­‘šð~!‘t÷‡Ð`cìê„®àäú–¦åLgKd°¹Â†'y#Ãý! A^nà ˜¨¤l²iß1q übÁ¸R{&"@Ý¿¦~܄öG hÄʑy3´lnº0h¢oÅ%\cÌR¨:6åÇIáÇ» nÐ3Ñ0›˜aŽÊ<ño‡ôM}XE<ž$M +ë:T­vãW.±êTìk`Áˆ"¡àè¦Â0džŠ^— ¦bUX‹Nùué ϶¢m9þçÖtíÞÖ §¼oÞºáx)ýuë:¸•Kvj{ßcóªÉãÿ÷¢mK}cÅZ,e-1îÙíÕÅwX.aàkyŸ_ìV„7C¸÷ûä{ž”+—ð8LÉîzóÌËØÔqש½¢°E]±ˆhi¹ÓÒÒUEÜ·õð™öáJ4xiÌ}׺=e ˆýä/Ê(&ÃÒE’¾êD/êúËá•J_Fi´·FÑ +/‘šiyÚx8¹½¾EÑ‚J–© jr¡0Íz‘,r©$jŸh†¶4á·-yljO»G#«¬5ž`¤P›C™fLy¡÷N]:vürÇKÅZ)uguBË/‰ƒ m|AE§LŒ¦LòYêŒê<Ÿg:êYµÖÖdí[ŒŽü¡à±g7¦öOüX9®ø)â>>>/Annots 153 0 R>>endobj +688 0 obj<>stream +xÚµVÑr›0|÷WÜc:Sc2ØyKÒ¤í´¤û +ˆX­ˆqû÷=! „8q:ÓŽÇ íííÝ­$ßÍ„ø!F'•³ÓÍlq±BaSàJ²Â—üècYI‘ {&Y]óúÍæÇì|3 ¤Q]¥øá×p(ґP¬Íù/†D>~qÂÚ­cÞyDƒ}yàR9hsz†'€¢ðd}¶yK—8ì;^gFTVhå1tP„Ÿp³åЫñ‹ûj}=‚\žYqÏ!ÓÊ-kØm¹Ýr¢‹„¬Sǰ™áÌònXÏ¦Ò + ìž Én$ï ŒƒÈ RÜî´ù •Êrƒ*ïùprs^°FZ¨¹µB݂¨§\ª©è›Æ:k¬.™“ò7ØÆ(”4 öõãEs¸qoï!^ÇÁ–Ô ¾J“ î~I¸öSïsÆ+Ò.Wˆ¢M3a4·0J|jô®Æ‚ÃøPh‡2÷)†Î½XÎ(< C{3¬½>q^HíÈßÞÙ/û›./á ¿‡ O=Zú÷ž~TÙ+ݬ (mÁj¨›ªÒÆB…~µåÊÂ‡ÍæÊ…(­ÕĚ¢~œäï'Þ º>ôêó‚M/0ÓÔ´{´Œd¼EõBrèH¤ljÜ1ÏDá‰&ÛÎð»†#+/¡q6lwéž6Î÷ö‘Ykî2Bí‹<4OC ÁeºÎ²-tB^aҍ(¹nìÈ«Qº<èՈҿõj—’ð9Ëöˆ8üoÆU{À¿[½©q€ìÃÂNH‰ *ÎKW\+𸝸 ^;Leârl ÃȚ×Ïìs«`4&¾2Ó×ޘžH„lø!ÇIL&cê!kLDÅŪËGÁ‚“Uì9áìûÕ5\ëÂîÜ v’—B!‡aVã…ô…©†Éö&4Ÿy…ÏüI )E íjw-ø:û-Faendstream +endobj +689 0 obj +726 +endobj +690 0 obj<>>>/Annots 157 0 R>>endobj +691 0 obj<>stream +xÚ­VÁrÛ6½ë+vrr¢IŠÅN&3Ië¶gƭԛ/0 ÒHH@A»ê×÷eš²F‰“±L‰ØÅ¾Ý·û@~Eâ/¢ÅÊ~òföq;»ü=£(¢m ËjÒ¶¸ø·¹;#”|»ý äà1WAb}¶÷œœ1ôƋkÑ>ÙqA…Ð<7âS»ã¹(o‰‘äæQé/ĊBó+² Ò†Œ¢ºC¥Ò”+)ín%ۀ>uµ»š?‡ENÑ"ˆmNgh)g’î8í´z/F`JRãÃ9ñ6p¡²ã꘡«í, BtÃ^"{ùûŠÒ$XÐ2[+j(à õw5m\¯œe,qI`ԈdÑR+Q3m«3>‡ –®h”Õ xîœ^êã]gˆÕµzli¯: ºŒ9–óÜvK¾Ù9 i¸.Ö-ƼOüÐ1´ØOˆìd 2sD^«œ L;Þh™„¨ÛÃэTU%żøå9CŽaÇß¡åc¨9!#BMzÉÊh>´(EC»û6^¥ú­íÂ0ÇÁñxÂÔ~Eöƽ[´Ò¶Š–*ºEb%Ãóþöí«ÁŸfë¨2KºƒµN¨°}5ÊAÇ0JÖ{õêðƒxŽ£KõͽY{#†œVYì‡ù×n6´Q¥œ>Ø"Þ~43–›OLv¬—Ð>>>>>endobj +694 0 obj<>stream +xÚµVÁrÛ6½ë+öèÌD4)A•[“:™vê:­”[. ʰA€@ÉÊ×g ™Ž3ngbiŠ‹}ûvñè/“ Rüd°šÁ| E=y»\m'i’ãóáb÷ÀòdŒeÉæù¯9K0  ¢”4IiiÁõ—ïא1ØV¿Ìñ¦¼¸æï”Ú»WÛ»Xc«‚±|…÷³3ПuùX6'„«^7J„üË÷)¬)޼§3–ŒJ@–¦´,…i–ÆìGÁ‹ }•i€YҺ߅+¬l¼4:®a\ moô,bpÔÞ÷¬ (¥…—…ÑÞåÀc~ÍdÝÖ Ûz',˜ +~WžkaZEÇÕßrG©ìp¥ÌQ”°;õÍ͓"@'ìA؈\)*ŽX Ã$z°$R[tÔ 7u:ŸÅžþ¾Ù^½y¶ãÔ…Á‹[h¬ÔîÌwëK‹Í9àPIEUã茅 +)Ï=vÓÈF¼Þ}ú¸é¨Žz@Ta5¶x%kéã˜^<æW­o »œÓ4)™¸T|‡ÔFüیÊóƒ‘%4Æ9I 5ø§vp¼:ö,õ·{Ñ홣28‡8׫'>ø÷Ãó¾Ù *ï\²ï"þ1ÏLÂÒ9]j’9iöR“þ"küy&”þÛôÝþ/ÏÐø£G8Žå^4¨y µ¨=%pC¢¥Ä!a´é!ݒ¬E¬”•jêÅ#š§GבäÑP¼õ¦æ^AªM‹‚(¡²¦Ž‚?9/jÒaÍïXƒÏ;3Œjkq£ETdì^³÷Úuì‹Zrž¼ß]’üˆÇ¹x’eh aˆYFXq‡£eҕ,|Pðùü,“âÀù„†€-V­.h'¹’þôøDq ®J“A ¬ßéõ ²¿Ì~ƒðg:Îò;ÿ¹Ž3Ö!¼DÇ] ”2Ë«åSÍ êçc¿BÒg½ÿU‡Ý@„SV™}8´:óáÁ WԂx(„(Ý^0exÊ8T*×%Bh^ã=n}äÈ{ŽTbÉ͈<©€ÄOo 'ÓR²5x¼G‡!½‘5’­G* +´\¿søBóØÑç‹ìúíçW¬ò®tÆV°\/âÄãdc*$üVÖRKç-Çú5×-W0yÓÕ,}úï[1B̝Dÿ™|fݧgendstream +endobj +695 0 obj +887 +endobj +696 0 obj<>>>/Annots 160 0 R>>endobj +697 0 obj<>stream +xÚ­VQ›8~ϯUªÔ“„@ro½k¯­´«æ6ô­Rå“uklj›ÝMý1B“tOª²A1Ï|ó}3ãý> !ÀO‹ÄþåÕì¯l6ÿ'†0„¬Äd•BV¼ÚRc˜Ø¹§P‘'V5höƒ‚‘hT0Mî8ÕÀå”4Ä0)ü?²¯èj aì\yÑڏ­³òtK¿7T›-º°fo³Yàc°8ñ#ˆW)þŽð«(”Ðú(\:/oŸHUcP&€µÝǼ(> ^-Ó$°ö& üÕI«ê²A0¤Õòڈ‰5|Cu®Xmsw6ÑÂaʐ¿°Û<ÁÆáä+¤VÑܰ +¹FI®Ö@–P+& ” ù¸‚› R׺ļÏn®¡”jÈm<#œ‚Là~¶ÍÇm6œóÁB-hIn€³Š`Sy¼gùýAq Æíæ÷4ÿv^ôª j¤uœ,ìó¢Öñ"r8©uë^s.¯ÞP±Ÿhè¶íÆUkó»5’;-ÒÈDGVO)Ésªu¯ª£»”œí³ÂQ ȊnêZ*C‹?ƒ:ÐÒqâcž#eÐJ%+ œƒÞkC+Ý¥’ô'èSNk3uƒµƒè¥¶bã±Â ™²p*þ@BWyÏyŠÊûç(I'žìÞP£SÕ.ä&ß»Â*¦`Ozü_hûc^´B¤Ï*Wû8qí#´Ûw®Ö~ +Qšú Tő¿ìV¶ÇóxùkÜ[ùm±Ž*¬j4–T]S¢0]Í +ÚÉ3 §v0Âu-sҗúÁ0 ÏÓ7¸×"š|CvôZîFm-,u—Û< +Òg5yçæDÍñª™çM­ç5¾ýÂ]ÐQË_6ö^ê3ö؝³ß9 FĜš7©Ú‰n[´íj»Ü[»h­p ‰²ßiÉCí¦7§‰ÖME‹³5‡z¤°¶¼V.ý¢+8ä¾»dñz¿£('-J\š.¹‹…µ¥êª[)ÍsKKªýñ•s”»MÉqGúsç‹`äÜïD+£[lŽççæÇDΛÂMŠ#†ïöÐh;'r¾ÔS%»“öÔÉ 5Íá.ê Wc/úðÆÐH­¦xUº3a/ì¶?{ÞÝÈnYÁ&7”¶RԜ`ü¶H®U‡+ŒSM “ üýi³…­,Í£½Y^8"Aú5ÜÑnxFíÌ[$öe,°Õƒ³ÿÀý;ûãêendstream +endobj +698 0 obj +930 +endobj +699 0 obj<>>>/Annots 162 0 R>>endobj +700 0 obj<>stream +xÚµVßsš@~÷¯ØG3S (}LÛ¤L3I«}ËË G¼îìÝ›ÿ¾»w€J“Ì$ãˆÀþú¾ÝoÁ?ƒBüDŽa’@V >/§—3ˆbXhI¦x’o•¶'‹‡ÁÅbx7 ÄÓÏÇøÕŠ.2j"ã(˜RìÅ_V­Kn(þô2„Ù±Øh]rH&9„0ŠBçnOCÖæ¹À„ì_¹É´X[¡¤÷‰»ÚèáS/VÚºÞØQÙú!šgV=šøÞD–9®wCtÅkǙ縎¨ÙœA”;lÏ®R+ÒiS/ŠSL› ];àËïÛ9ÌUa7r¾ËÉÀ5“5s€G>n”ŽÃÝB±{M¹[“´ùÏÁ?¿·¿endstream +endobj +701 0 obj +751 +endobj +702 0 obj<>>>/Annots 164 0 R>>endobj +703 0 obj<>stream +xÚ­VÛr›0}÷Wì£3ScÀėÇ4½e¦º±;}ñ‹ "V+•„Ýü}wŒ4É8v@¬öröœ¿øø `2¥¿8¼]Æ"X§ød:ŸÁ:ÞÀžÉ’ƒJájý-üÚbø5MÝJ³g›¡ÝqHxÊJi7W y¦öÜ­þT[H…Ä;fÀ(•ÓÎâ]õDˆUVHnyòb–Ç\JºTØVi\ö\´‘Ëp.¼ˆr\j‘Û˜dð~=ð=Ì>šz!Dó^‡øÕRW᢭0¸vûßÿaÚ4.è9‚2 +£ó7ð½ywÆÜÆã¢cԆU~¦dþŽ›X‹Â +•ŸG¥L]¤5"ÕÃyyâ·;šÇVì9"—[­¤ÃŽ#Ԛ@˕MNò2+­Ê˜1“òxÎ5Clå ”ER]„Ý5•NEL‹Æ ؞ ɶè­ò͵ñà.SðX¤¢ÞÑmÞPësº=Íä ¤„-oð`Ý2‡µª—BcŠUU.r–a4 +k@¹Ðˆ#`^í°úe朑/ +ÚV±rïÁû÷›«ªØsÈZX‹¡°99ßcwX]Ր$ÁpJ÷ªuÊ©a9u‰âp¨"~¥ÁÍÛG`E!±§D-RÃÞ#ãwL'±"ÿVTêàƒóÓ³èds¡ÑO +ð³µü^)ۑ`äÏP&ÏKp2›½H€mš)ºԑb× ~úš<-ð² + ·nÒaStÅ(Ê%‡Ý"ɑ¸´«áwÉ š§ZeՔD^ï®T ïu£QÅÑ/Ò¦GÌ(]ÆÃŠ[+ò‡——ƒD黾`ÅÓԍ3$†XB¥“‚x\"ß!ãñŽåÂdϱ¦B¡G›pBSùyڄ~äM_Hœc ï™›B)9ŽËœ1¨c™*5ޞY¿.£NŠÿ¥Ü’ҏ§DŽg%µõn¹l¹D#üÓúËg2ÉÜTÆIÁ¶FÉÒòa<öé' Ÿû^S;?D2˜„×Ç; +Mý‰Ã¨`8Û±Ët¸ZíE5[h‰jh3cÊ̍NšKV•·¶F _?@“×8HZSÿhÚ 9=9j4ú +:Âw. ¬è—Ù{·¼Å·ޝx‹'Þ¼vD3Lhúän¿/W°R©=а¾I°¥xÈâ§´/,/™$ç#·kTo›Ìi1Â÷›øÞ~¾ þcåè>>>/Annots 166 0 R>>endobj +706 0 obj<>stream +xÚ­V]OÛ0}ﯸêHkš/Úô ÊØÔ‡M¬tÒxq§xÄqg;@÷ëwm§!IËÇ$„ˆûÜßs|Ô?ƒ|ü `B4”æ«ÁøË ‚V9îL’)¬²“«'·U§«ß¸íÃÌìbÀ(Œ½Ø–‹ëK’ÞQH¸Áø0 +|/éì›—vB?Nî]ê}å‘M>1°ÏT¥’m5¥ÃÄMwˆpåW˜eߛÛl²wcN c’¦š=PPT+ЩØ_ +"·ïœr!wÚÆ*E3Xï`I”¦œl(\K‘R¥„„Û“!VޞBÎ +¨ý#/4]©*½¢ú1“F i“öÛ#eÖÇoÕ `VûîSRÂß«®F–ÑR³œQ§IÊ +€d™D­Y2Ì*19˜Ò’ $@”N¾;Ô÷`¾kÒN÷-‚»‘Ýìì@¢v"ʶÝëø<ÞQypÄ£X“Ø6h7¡$œ¾%ŒyGQ<Ãç번‚ĝð²À +0®”l=N«­:* ‹BIŒQäÇëbþš*rKƚŒÜDG²*>Ñ´Òd]˜[ºÈÑ@€¬•(*MaKА„RhØJñ€˞NjÎoy,¿B01ÃÓ/‡0:k¾ +¸1S7ŸSw쨦Mn¢TÅÑq´0$iAlãø©ë÷JÉ Ì`‰zëBýÚ ΠkGÏhM‰Õl‘g&öWá€ýv n7°GáрۓÅrñ &ÞÙíé[êþŽ7 %ï`½ézAþ—ë™`¼,xÇ˽ÜâøÎ ©þxïþ‚È·4}v>cÖÆ*ðƒX…IºR;‰¥C›T}³k[LM}‹ðv֚¢¤n#ˆ§ˆ™$µ‡ÀåÏ븹~$ÈÆEÛ4|#eE +“`äâFÓÐoÿ’1[ñ4Æ9ÛåhV“ýcð"-³Àendstream +endobj +707 0 obj +831 +endobj +708 0 obj<>>>/Annots 168 0 R>>endobj +709 0 obj<>stream +xÚ­VMsÚ0½ó+vrJ§ƒ±ùê­mH¦‡tÒ@€°ePcY®$Cø÷ݵŒ12€Ç²vß¾Ý}Z󷀏Ÿ†cúƲ÷mÙÜÏ ˆ`™âÎxŠ7Éí‚ë-×ÏJÙOË?½ù²ç{¸7 ½1DÓ Þ‡øÓÒÆ?¨ý£À›Âü•É"ã†ü÷>ÌhCöÃÈ넀·ñ .‹Ê؇~à;Œ¶IªÔ`Åtcv Ú¯PÇäpÇM¬Ea…ʝMÔC w¹áp å6;Ù½n!šÇVl9˜‚Ç"܀E¶2*+-‡‚Ù XU=4 Ä*OźԌhË0–¡i*°ü° °Ì¨C¶C/$b¥á AiŽØQóŒU¡)†‘WACv`HåH< +Ù¥Ná< lž²2³~.'¥÷Ä£w҉š×”<:”sV·qo,—Z•EK*#ßǤ®K%×ïKåÌþJNwñþЁnšüò9-ÁÿèÇñ–H‘ ck­¬+Š©Òç#tÁY‰P¹qåíÁ£ÒüØ<çt èòüaz3ŽÆX áh„GÙ­2XPk|\N\ÁDޤã³VØ=U¢Q( J‰¨xÊz}9l+†QKŽaÏØ·,$ ‡ACú@óÔE¯›Ìjò7OZ`Qò5¸ªÁ‚Ç¥vSÉ¢q÷k÷®¶û¯ø’ËâN薸‡Éúº¸ÃéØêwÅ]ãÃ`‹ÓÍÊ¢#Þfû0k“p+Å÷ċj8}¤VRôqªàÃQæ6Xi†ëá×Géwu*mÛyŸ¥vfM´1–¥±¤àÒYÒß¡Ø*ãn.oT™%°a˜"åpcð0½ìo àZ +cHÿ+açä‚ö4çY—¹BWM)kC§%Ç·UÂ3î&>³UHU–©É4VR";‘ekN/ ªsQhUhAËâbÕb–ÅnåÞ¨¦©Þ·Þ*R¾$ÁÁüçrþÜQf¼‘*öYï^íëÖ©ª̪6 ÉUÙþc1ºtž¦5Ù š`¾“Ð'øþûi •ÚCӯǪ°,/YFà}çÕ¯Ý"ŸF8Q"ðÏþÇùÕû†ùžendstream +endobj +710 0 obj +830 +endobj +711 0 obj<>>>/Annots 177 0 R>>endobj +712 0 obj<>stream +xÚ­W]Oä6}çWÜGV‚Lœd&™jU‰…-Ej·tÔ>ì‹I<3Þ&qÖv óï{¯íÌŒP…@q|¯Ï¹_ÇáÇ ƒä ¤(›“O³“Ñ/S` fsܙ9̪ÓÏÿò¦«…ù0ûŽÛ1LiΓ,ÊÈ`&¡z i“M ç,ŽŠíi읇³Ïû„L®„)µì¬T­·ÉÖøh–t¿9œ¼ër +•Ô¢´òQ@©Z«UmÀ¢3oTßZPs°èVÁ—Ä\iÜm{§_g³[PnnoA‹½0Öy@¬h.’U%漯½* eŒ@øÊD먳!¢©èÞM›Ÿg'qÃ8ãû¬Èñ9Á_$5߯ƘeÑä¨zÐáPw{µpoÒÿ]‹!˜Ã…0(å\ +_‰û/7COTì’[˜ËÚâ3o+¸¼¾N«…æÝcMLÛ9v^˜à=tèö&ëyàž&žû­–­•íîVƊîDÙkiWσÍ}ª/ïoïˆÔ£¬¿é»Ni$«J cΠÚbx%·âÌÅÑqcž”®àÛé'ndé^^É&þÛxàFTÀ{ÌRA/Ì5Yìõ/K<}hâ.7(» {'®ØÞ+Cm^Ëû<œ†kÙV z^C'vvûôB«¾3C³e¿ðñüwè¯kõd`¥úC˜¡J0.똳VX$ÿ>a&+ÕpÙb­ÿZJäc—Òì1ª&¿UvÝnÐg€pÎÆñØ¥A=×)KÖ3µ!@ø€˜#9‰õj?jW¢g‰"p<Ô8©•Ç6¾—}?)m5¢FÙ-hùC-ª~[ŸÀµØH*2ýaôçë5cLA2‰‘N,-Hܪ†;Z2Ïu˜³ +£¤·aP÷Õ ØžÅ®a¼6<0Ð?½¨;‡Ó`„½‚.ÅÏ/F–N(–„âk  ió‹!°g¬S²˜øŽ¸À¤^Ö8‡yŸBEo ³Ìç4¦#ýêUh6ƒ€Ð×4"_x#Þ§qù”ÐÝâUô8h?¡ÏVÝûYA÷K“t½x ˜)Áþ¡+/ñïÃ̙«²Çt‹W1ó$T™Æù%Ô¹VÍÐatÆ$èlgrBÃt%ÚÕ1È[÷ëÇÑÐþ/7}’M£X⋟&E4«ÀjûbI(úF*¢Un…wÓ:r?™J¯ÀXݗ¶Ç¯úÒ9fþ¯TÙ7(O_•²Çj"ÁR=‰G¼B’øîi¶SDC&(»R[ºr6ªé¯ÐF¶¨§:¨xI-ðRø®L¸KéÂFÉš3L(3êNድ-b,¥9|Íì$a1‹rÈ'x~|Àh1w‡l‹)–ËÙ²éxÇx§r Ç9§fwm1raßP·KŸ†ºÞK¨Nø'½ÁÜõõ‘Ìý >>>/Annots 181 0 R>>endobj +715 0 obj<>stream +xÚµXÛrÛ6}÷Wì£;Q$%ê’7ǗŒgzIkyÚWˆ%Ä$À ]õë» II±Úi';»gwÏ^˜oW„ø'‚ÉŒþ¦åÕ§ÕÕýê* x¾ÿ¡70]sX.‚&‹e0ƒ( +ƒ)h9] ƒDÛ(?~˜¢ ¬rˆÂ ^-Xe×ã´`Æp3–¬ä?¬¾^-æÁà«Õ–£>£j¢V¥Á‰ ÂFÙu{ï ÿ: çû#¿}FÓ™ž/І3-ƒ˜@?F¿’F8Z&=it±qcF/ȑ¯jmލ˜Ý:ð¬(€DÞ—P4/ç„σ›Îðu n,²wŒRÃðú;ÿ$¸SâÁ¥øðyüñ_þJ i¹~/À­Ø» ã] +Ò Ÿ.ð¬ ò —÷H¹ÿ‚ÉaŒx©Nø¬ÉbyìEPU'HóåË䢸_\JñåÅé…O¸4~XB4%ƒ!$Iâ«à¦¶[.­H™J³r·\[‘Ó7}¨!Œâ9Ý»}þò¦®*¥­…JYéáâhÍ Ï€õõ›tËKvË,¤LšCMbBBU0,9•ãõ‰‘J÷¥W4ñ”»nìðÂÇz‡SàTIÉSK~Û­Võf‹¿ù…óo«Ž»ç=è†m`.u +RÙ6|è¾/Uõ†ÿ̵*÷Ø)“;P¨Kw,5êâ™ïÝtÃtGñb´4“j“u¹Fòú¨kž£.«P±×(1oƒèhž*í’B‘0\¿rÀMkàL'~¯‚ý»Ø¡ ™4ÿVcöàM`!B¦´øËãÚr–!x•l-,IåQ<õ±¸é^ø?:Z†Q<™&8µ–7Ÿnïî†Ï}\#§oÖ¶wŸü’Èrõb ®œ—G”GÀ=Âc6jãyåh®©ôçµJ£´;/…}7Ÿ.¹v7·‡”-U2²U;gÝX¥ù>sÞ/ÖÆ{Ìm:Nëʌ ´f#˜w¼¿; >êKQÓj¦˜}܆æþ,aŠ#+lž +ßlè1ö-¦Ò*帤<ÞQu®ÛϏØÕF³3}äY¿–¨­ú@(‰~jd[c§m®¸èõºÝjÏ¿gTÚ:^À®)|gÝuî% LO “Éþ¡õõ;ÆItéÓú›Kõ>ŽŒçBžÍ!¥/ °æòaú(JüN4ÆØvɊMHóR½R“ö®w;”|e…Èçz,rÕUHőЅßçÜ8·DßPÊ÷½”¯O;cyy)]\ՊW̽Û]1fÃÝOz¿ih~h.+o ”BÖØzïÃÒ0Š&û-Á f¸9t'¶/:˜25Ï??þáâg\ÿª°;¾áì1nBuZ)°Ô5¥>8íx¹%ƃ2–¡·ÂXŒÆòZ¦®u>iôÊ`¤\N!ŠÊÞrç° ç)g¯ÜdZUfŽ˜‚D(9“~)XaPbñ§BÕÆS›J¬TRàpÉ-~Aäé ·>k™0©¢äšÆ!½äºýOÕEFÙ¬ Kݎ‘CÎhªJô¡†ÓykÑð´ÖÂîÜR9ì×Â.ð~ÌÝxåZM+gŠóãüž}ö˽ió‰ÿ¢¥s«¯(«ÕJëMa½ŸL{¦¸ßõÜz·ç]³gºà♪iÙ#¸ªFÑ3a à1‡ªÁb•ËÏlژ¼ºƒ¶=Ç>ÐeÝbxømˆ}S”%Ïh)v»k\p^xÖT¢ýŸŠé_ÏÚáî£ñ¤rûFúæPN +9ð“5+HÁÈßÍc÷Å4ép7P}…`â~½úFendstream +endobj +716 0 obj +1519 +endobj +717 0 obj<>>>>>endobj +718 0 obj<>stream +xÚ­VMoÛ8½ûW r© ؊å8vÒ[ºM=lÛm`Íh‘²ÙJ¤*R ¼¿~ߐRlËî°…’È™7ofÞÌ×AJüRZLébNY9x½Ü.“ä +ïŸÿê5Í®’¥‹i2£‹«ëdNÓëËdJµ¢|¾Í'8Ú~»\à/|zͶ&l¦ûƒ­ó·3JSZæp=¿ZÐR?˜L‘ GQhISµ%^I•pîÉ֒´#Ñø2^gÂ+I«-ývÿñn„c[Rj¯­­kÛTTªr¥j·ÑÕËåçÁ„ÆéðÂU­¾6ºV% Á"Pf•}Q2ásço/[h—35¾à€qéý‡åí«x`‡}<Ç¯Ë¢ÚZ3Ð̧¥ªw(É[Zqˆٜԣª·mð}{ÄÕ§ßé›ÜÞnñ8Ç30Ü;E`‡"ÈI rxʖÛJb’™×Š)#V…¢×ÂélŸdðùª³wÍ÷P#ãé,ÝYŽ×â±kJg|n^G\Ú¬é^+çéæÀö1Ÿ¡Ú³‡8˜ZøueáHª\­Í^ü¢ ô\ùì¸,*•Kè¦pvÔ3:ÛÒ­‰ÌÝ¿÷×ÎglDΒ΂„÷-\‡k=ûR»Ì¢Ó‚[ëµfØ¡öܯg‡Y1ÇMá¹¢!Vmd[eM­ýé¶h–²çX +‹BG=lm` 4YžCŒïÁ÷‹5³5|UÖÈ]“ô w—’öý¾æQ°F#AÕ"ƒHÃw)8/4^¿è¶±Î‡ìښÞ}da­™ÜF +ό…VŸ±T7*!†ÞÄA¥Í¾Ç:跓”*´Ç·Ë K²^7ðÎìðÑ篥…2½:C¦’žy£œõX½Ì¸ö±–Âãó!´~;€ ‘ÏÏÆB-¢š¸Í ŸÐÛÆ7 Žœòô¤ °ÒT•­ý锟9ٚ³~êž6š%GÊè˜''X +/:2[0#.ÓG-©ÇÔ1˜DŠÕ7ÏüweÞ/·´éºµ€ +ªÈô~Of„íÔ6€.ü÷Hf¢DŽhÕø¶)ÈCÛÂØ)m‹p7¶)$OVTQ˜U!`ý<–öôùT†§0U„£«:”áá]›'®þÓÀå“Zõü¬jûF•Žôl”Ìh®…¨·B ®ö_êeÇhÜ­æ»­™µtÔq‰nkÓGíÎ7\ܝU¬¢`’ð|~—ÇÅN¨q”Wm”iš¢Næ×ÓX-Q:ïlîŸxe¿ÙmQ]ö‡0(ØÀ8-pc¼˜N~bùœ-f(œœ]´øçà?' «endstream +endobj +719 0 obj +1286 +endobj +720 0 obj<>>>/Annots 184 0 R>>endobj +721 0 obj<>stream +xÚÕVmÚFþίå‘À`l¸F‘®Wî)½ÐœOjÕTÕb/àÖö:»ë#þ÷ÙµÁ6>é"õK•‹xv^žç™Ùù:paŠÿ\ð®è/L?ƒu0˜:Küýô{ð—ÎæîÜAÃå +Ÿó>$‡™:S2­h?¹›Â +‚¹½Zâ§h¸aJ…Œ®ámð÷`rçZƒá—a^½ùòÖÁú³}_9Âõ{ˆdB‚G’ÙÆ.æØôlÏâì?2¹óÁuÉnŒõŒgW/X*ž90(—°“"}àpò´‹>]æüº•qâ;>¹IrcÁø›uÓH®'ê§,¤€Ï,‰#cŸ±È"hæÏ +Ì#ÓqÈ4`[ÂíÓæq„f%°(Šu,2–À^Š"‡”§[.Õ!Îk@=gF¡$ÿZÄX":BÈuxàá?…‚¿rmOŠ–jþm’Ä,@¦Ú¹!BB#͘ÏØ6áðS¼çJ7QF@¯[‚jR\»®ÎY»¸þ™[Ó!¥Ò<5dÞjnZ.Jw«Òݕ³û` +),VŽW}IlíM&|ú`y0l·}UÛ@ä6AUµ-Ï-Þª¥H”8Aæb°!™s¹2uº4X º$ $m»†L TÚù7ÍUÊ)è¨}àxË +ï2¹JùÖ€8CI>=|ø­¡ÃFwB¾²’Nb,<ØfH TԖ'"ÛS += +U¥êxõ˜\ÆÁerԄÝÔLa?˜È,ÔE= :•F>>>/Annots 186 0 R>>endobj +724 0 obj<>stream +xÚ¥WmsÚ8þž_±Ã—¤Ó`l—òö­wyí”6w¹¹6a ðE–¨$‡£¿þv%Ûá- maƀ-­ž}v÷ÙåÛQ!¾#èÆð¦I~ôÛø¨uBÆSºÓéá·ôd®Œ…™VÅ +Ã5¤Ìò¦ÍrwwœÛ¹JAs£ +pxàÚdJâ0–ÙÂÀde¹y5þ÷(„f2ÅÝ ÄwM|‰Ã֐­ZQ¿ßDýAâ>¼ñõ7ŸFch±4Ïd ®Æã›VD h‡¿4…AoÛlžÝó}–ßD/YŽÃÐ[n]´!ŠˆŒ&²ÑŒôñœƒØ):‚6ןÀ4ã"…e&H¥s&Ä +”Ä˄“p},M‘5…ô±RÌÙ.ÙDð윓Ñóñº„ˆèÑåÏKú¨´!‡~¿þ!`D1ÜZ¯g@QõÈhi—¢'Wû#Ëù¥î‹…Q½3¬w>ú”fš'6CŒ™$x%¬Z •4H”œî²!xPå@Ç¿‡H—dû™dbÉVиe™4Ðh6Åï·7£ SÞç +ð*m–`n§.Í%2jêžjþ­àÆfræp=Ũ>.c2…3f©´³hŠÅBd<­ÒóM°©Òëæè;ñˆ<–uçpª®Ãg=£U «ØM‡ˆA¡&üCZ…»ÊàN)míÀ…fÜöˆ¾œµ†Ÿ>¶þÆ×àêj0F#xý__Ÿ¬žåœëGh˶%zÂõ]I>5Üž£Ð‡ë¶@m©V9\jÎå2Kæ0äX`c§O',¸X—Ã1ø¯[!ù|ûá6¸{õ2Ù^çžešJ=ÄÔHñøÆåù¸qŠJsë?Ppð“Ûä 3+Q}öT*­=¹Ê5ù€T*Uûe÷̂'ٔÊ—Wb}¬Ü²_Ú.0Ù©:ËÆ'ºIJ–'|+Zƒ€ì»Ë~Äu!Õ¸‘‹Bت%mRÀ­)œ@g–œm`À(M + +—éÒóú¼5ĉJ1ÿ¦ôB“¡n{Çù,_~êºTÉ_£¤2Jgߑ-–$¨úu“,k®Ül¢‰[Ý[_à@ùA¿ÝŽê¸šÂìºayǬÉû¶EÑöÑvÎ,,™Á£޽$õ廖:þˆ>Dmß°šqÿ‘®µÒÿ5ƒ LüM4´´»ÉTݛê}ûZˆŒ|Î1"lV +!2ɜ§…@üwނ9EìZb'0U?­‚?p±6.•ö·f¡ë)%ê â^5¥¼WÑ0*R…µv|ÆÍý{n©àŽiÊ9¶Æ ]‹q4ãu‹ñ/[Œq{Ó"5a2áBx9X³uè(å(; ¡íjᯤ´ŽßâðA8߶քwÒ§¨$)´æi 1© vÑë6ßŝ.lÚ¦gurÿµkœœÂ¹¥ÑR¸i¬‚×ÔRÁ(jµ èOŸ{½{îµô Íb?/yùéÎv8ã“b6£èŒ×Q{hø¦™èïÌ4K?I¡ #.ÒTM p¡3IC[à‚âéñÚ_\Ù¶¢g©…Ìî…ÉžºöÆ^ìŸRŸ’Ç^y3jwJ§÷֗žo¢#5µKê3ïèß +ª•fÕ†Lbë"M¿¯ÙÃ§µ²ÝmWAj¿-ÿ]üqô?3hendstream +endobj +725 0 obj +1256 +endobj +726 0 obj<>>>/Annots 188 0 R>>endobj +727 0 obj<>stream +xڕWmS7þίØð¥0áŽ;ãÌt:“hɔ î‡NÝéÈw:¬äNr$Žÿ}w¥{±å—PÃû$­vŸ}öÙåëQ + þ¤p1¢ß¬:úert~7„4…I+£«K˜ä'“9‡ÓÉg\5K'7†=sÿ´=p…àen SÒ2! 0(4çQ¡t–³5+¡9û³cH‡þ²h0އíu Üño©žáN”Á-´3p‹µ´Ç¶ý*9”ÂXœesgìœY —¬BgZHËu ·´©’÷¡X¼­Pe©–B>ƒ³BÉkYcº qŒCHcjƒoŸÕ,9äÌòȊʇɺšá"þ‰2µܸ}3Qâå. +Š6Gdî=7_>p Z) ø{œ?°Õy:¯Óñõ ½N~„· ¾þÊ,Ë*¥ƒ‹M0"çáhO^—wæu É0U¸Ïm Qÿ%÷ ”h¸/`¥jÂ9G1À ´!+™1gM°éE< ßì3ã¯]"í݇¯^2¤œ1âY6÷ã]q‹â¨gW4åçFìR:=¡÷ÐR 9­ùך‹)ŒhcD'à ˜µZÌj˧§ÞySÏ*a¹ÝH”D?íãEïË3îQF"¶¨R}Ì81½Ig º]²æ ¹á®nRXιä/. <ðþæÏÇ'̼¦Uª5Ë4Z;£ Wò 9_/¥74~ø»k)È7ßµ«ªWDK{á•® +1`ò¾ºñ°&®ò©Ú=<1… ‚9J‰ÈPä»ÓMvÀ͆ށ¦±,CÅܧj¯àÁšÐl‘av“Ñ sXÛ{ÀšŒ‘©žD˜mPÈ£Çlš×ˆ»–Ûm-gL‚T$'*¯3ÞZt<á/Yʳ]öߋ +—lEÞAúÊ:ZSäôbäåª-¢@˜é´€¢}A‘Ÿv¼lZƒ.Ӝˆ–C‹ˆfp½w×ÖF¬ 9ŽŽAˆ;v>Ó֝¾Y_6.\ <^ԟa²ZPž‰øS¸£kÚ¾9Eh d÷·ÑŒ Ú©œí­1²9“ÂTTYˆ7ʉuÛÍZ/a³²«TüðÌ7þ¶Ã”¾Òë…Cy]¦Tä9¹EZÁȵæªB«jW‰žs›gõb‹s¹Ð<³J¯°W ¼ŒÖo'GIœààEo)½}ú ã1 Fø*H¯’î[ O4–%ø5¥0z“fÁ3 Ìa¶ê¼ +LëgXãÀ“ ðΛ[“nkèºxqýIÁ¬%uï6E^B}& NA=T¨ ¯ÐÁ8H––á!¤ÔI% Ê»§›û{7%zÓXÿX <¶-"4ìEi|æwÒ²Òû‹¸KQ…ª“ßf¿nn¦ØÌ.É5س +š s$‘Ì™î¹K1uÔ5^Ë(HöÂDéê%,ǬŒåÕþ¡xŸÿ‡¦áý1;g}¾)~‘¨§k1¬Àœ¹EW3¦W'W%*¶ +šµC³g)é +Ö²ƒ¯1 ‰¦ž¥ at]ÒíÔø7V-J~¶KL)ùçs[•;#sVE›'¤­Ù?¤w–À¿ÜG|ƒé´%‰¯h'¯Ns¦'ÉYš †X)o¿lzb,i:þé·ÉÃï?ãÉõ‡oÞ¼™üõx‹Ï§§Ç÷BhƒCØRyàÀ°UC9¹òX¸Ta-a˜\ºJÅ|D‰w!Ùµmá.ANAøiÄ K8"aACäÙšg7ܛ+ӆAê¼f™m§Ì^Ø;e9è‘3!E<´ÛQíí¦ì‡cD6Á’—eS«WͶtx‰fF—ã&뮣<©Â.)Œwy%°}YÍP®°¹0‰ÿ +“ÈŸ‹. ŽèáÅx ÉÞ…±üqô¸ +·µendstream +endobj +728 0 obj +1418 +endobj +729 0 obj<>>>>>endobj +730 0 obj<>stream +xÚ¥WQsÚ8~ϯØã¡%w†`‡brÓé m“›ÜôÚ\ýñ"l«±%W’CòïoWÆ;0¥”„dkw?í~»Úý~æÃÿ|¸œ@”Ÿ½ŸŸ]܌Á÷ažà›É4„yܟ§¡»V ËŒˆ9ËÀ¨Œgϰ6‹›$Ë9¨ÄýNDÆaɅ\}.x<„y* àixRf°N¹t;•+!Q‰Šóù·³ üËa@æQäAªµô UkþÈ5$JC¡…´NÄ8-†kz+näk ){äÀ•`¬•~pX +>I…ŽÝiÀ²Ô1Mè;Ö-¡.”1b)2aŸÉXiU܈X†çOĪԨ@•v{t:4,™á1”…ªN)i¹´¦å#!å,nì“á¸v:{d"cKÒÆ Š!À?iÛÅÍh# [#±è*4,Ϋ=uû0€;•hÒàaÈ{´‘ã™ØJ«²À0UBÑFh§ÈRLBh[¥wƒþxií“Z‘k`öùã©Z½®V½Nú¡`ß±ñåë©&~; üó—ù©Z‘Qºè÷ +f-ײ·?€1Øeþ)FùòŠ¢y„­ÞïÃf{ïTƒÌDB,ú*I ·‚_ÙtßIçºD†'°|ÆÈá‘e"®²×1{vÿáöý_=øüɃùì½ïï=¸ ~0©•þ<ÄÆÄI0·§ƒ¥°¥L›=0;Õ¢í? ‚7ã½è뽇Pç³±ˆaÕ ïUëÞqøEŒù•¯’<ՑTµV©‰frŏÂCEÎí¦ŠW«µUEû׀aLPÈ«’ÿÈ7tý4ž9Õ¬I•¶ÇÛõ'Ž@H'¾Â jòIrëî%,o½¥X ¸Œ“=‡¶Ã-¥c®‰QˆáxÜHåqÃa¤G98ShÓö†E¥¦› *™ªÊ!ˎ&V­sLÑxã©Y–,s®EÎSÔHìgÐØûD"w^ðƒËŹ*²n9ª×RþĶûFOî 0jœŒÐüÅuïïZù^*̰Å@¯Rºä†gîæøæˆ”X»¶*°‚Q9µù›+‹Å¾i®šÎa\¯]n„ŽÂǯ«Ç¯;·¾Ýyø6¼ Ça0¹šðIønßËwۈ4N¯ÚçpŒ¶w’NN•¡M¾Å+ë"µyÖe=/2îmÚRrU!‘xÙåef¾‡LHN­§ëGSêÌ¢“1“bt áU9ì¤Ý r¥#QÏSmòaNŒÁŠ_|+øª Ôá;‚­ ¸ûõ­ o]&‘FÞۛ›Ó››wøÕ+„Ýö3t>‹M‰¼ôFO|´9äf鷗A{‰dý¡öÝýã¶ø›örÒ^†?©|Ú¿j/Y{¹üIåQ[×]=ãd™ášaçOJ#N€n=\ŠŒ*uDfÝÜ(‡ÃÿÆZ}qùCGzW™‹ [:`E‘a{@81[iQXx3ÚdU±9ßts>ß÷1ž“« Š*|øïîîUb×t”Yœ ‰`5³ +[ï˜,«žmàCº«Ã`ôÒããp\ßòã\ÏÏþ=û ð×\endstream +endobj +731 0 obj +1418 +endobj +732 0 obj<>>>/Annots 191 0 R>>endobj +733 0 obj<>stream +xڕWßSã6~ç¯ØÉÇ$ŽB€ë-G‡æ(ÐéC¯ÂÞ$¢¶ä“ääè_ß]IN“P:0[ûûÛýVù~”AJ?œÎø7¯Ž~~:ߤp Os~3» Oű¨ëRæÂI­Æ+U$ySÛQ­­³¹‘µƒ½çFX‡ÎR¨­ÓáéÓÓËQ +£,M.Ø®¬ÄÇ'ð_öɆuº¶ÿÇÄ6„¨¾b|3…,ã4G”çh2ccOK„p8‹‡ÇV7&Ç]c˜K, ÜÝÞ}÷ZãtÍîEY¾Bc¥ZÐéZ–E.LsmÀ‘yÛÔhF,ôÆ6Ïáó·cLI›Ûi2áp¸q] +©CÄTùãÉx[Á·O­âd–LäQ uRùú|$(p.ÒkåÃ:¢Õ©d… ËÙ·ÆJü@89…¿?Žà˜ƒ1XR¼+ސ„\]M•ô ÁÜ芺ØiÈÒ4öçu(§ÆRt/µ¶Ø+ð3º5"e¸ÖPÈù *=ž,¬—$’kµBãª>I¸¡ˆð‡¨ê’°gA$D’KÛäv/5.úY;½+Ú ïžîY«n(€† +Hw ۍ  nB}Ù݁íÁëkÂhˆ^5v¢ …§êCˆ˜íå=Áìš!ìpS3r)ݲæ‡óٟ -hTÖwýþM9F—™¸ûš…4˜ ¾&ðGŸ@èDÓ$R„š õˆL£W4¹óØkSÑ)OÉøúpx`«×¨·M·s‡ÚžîÉqwh9ƌV²ØlÃ-csàZ…&j&YÉl4äôiX-Ô+Ÿ‰Æ-é§q8‘W8ªìZSGïKÏ“xþ~OKɝ@½Ä²æ>© ®˜Q8 +¬,e4¤+6‰Wïö–°Cۙ Û_P_ñ¯ßÍþþ&üØö>c14ç°mWzWÅë#éQYÅJÓpÐõ`!׬³…)%“€zÃd”j¾5E–À&”¥à;•÷V´¬Èº" +ãömln`¿k¾<¥IJ_øOÆ~…ivžœB6K)ç +¦³Ëä<>•ð¾R´@LÎ/ °l–…òpåhí¡„à°ÏŽòyÁ)ïøì©˜Å&Ìè{ðò„xÐ=‰Ÿ“ý +NS¶àØÍ[áŽ@³Óä¬#ÍAÑãE'l_4ÄkÛÆVã=>¼CîÃ<Áµ‘Ì‹¾ïï¯ýR9´Dîø彯i„"j7N–ò"båwJ¥ý€{™QÜÒùææÇ®„wÖÎ8áELÞ­teÿ›ÌýŽÇ­-rdp!mX¬+)|ómŒ‡1ØÓ‹a]¾am稁‡ö0‘œlÕ?Ãà½o„ÿàô²{ÑU–e”×lvȧw“º**©$/bÕö2ÅF¡F瓔զüòô,£–I?r3 öüíè_EÒyendstream +endobj +734 0 obj +1478 +endobj +735 0 obj<>>>>>endobj +736 0 obj<>stream +xڕQKOƒ@¾ó+æfMJ[()m<ùL<kď ,:Êîâ>Úðï]hS½°Ì÷šo¿£ô$§°\A%¢«"šße$P44Y­s(êIñÁ¡ÁÖr hÀt¼Ây Π|KS£œ®ˆƒí;J¶ýEÕÜX”Ì¢’'sÒaÆ8A*VAÉϋOr^ãd9K½w§Q’ñ\21‚ñ&ƒqhYI¢Ò`¸¬C ŒGæl`m ÉFét3˼ô«Fëño÷î†Ij;páFãŽëß¾^!Ôrý²}¦]§´¥u$8Ù¢@K;I'J¯Ô +S:Á¦‹4Óp¨ˆõA„a²?F†ûzåÎjhñ‹S>ÁI){JNŒÃ¥Pà‘ uêèýZ Û©>Éq‚ŸB¥¤q­ ……žUc÷Ló?–[­Þ5‚¢Ã“޵Cç–wqÙÇþ (Õ®òWmÆÚ×ciI–“N’n¼Öo#¸¬J$*³ê¨îéñÀŠótñïûÊòl¶†ÀË6þÇm=E?]µñîendstream +endobj +737 0 obj +399 +endobj +738 0 obj<>>>>>endobj +739 0 obj<>stream +xÚ-‹=‚0E÷þŠ;êÒª £_lFŒ5Ʊ0Ï@Eþ¾VÍ=ÃÍIÎSH$ŸILÓÀ­k-&ùRBא³,VÈT]ް9'œ\íÃVeK–:ÏÆ;î°7¶7ÍX?Dô«¢6O‚TK§øŠ “'{ÇÕõŒÃ`‘Sã+†cL6Ü-Ó«âÐí´8Š7[)/endstream +endobj +740 0 obj +144 +endobj +741 0 obj<>>>>>endobj +742 0 obj<>stream +xڍTÝoÚ0篸G*AÂWî±Ý¦MÚ4¦2í¥/Æ9W‰Ú(ÿýîl %Zµ©ªˆ¬;ßïëü:˜Â„þ¦°šÁ| ²Üoùç;˜M`»‡éú6›Árµ†m1\Á6Vi¯ô3•/á‡/ÑÂcç<ÖîfûB ˜N¹s[ÇóŌ~¨{[*²§–´j‡Jso á{aoM ²RHß.Þ +¾Z‡ôðmóq߅„#0~+]˜£‹í‹1Lhö<Îl¬ñFšÊeÜLW ŽJæ³la!Ü §d?•ÌVْK~mÀï„ÃŒH¾n6®3 twÂ!»¶iŒõ.TJ¡Á¡.àÅìóômQ¢:`*.e­;Ó&ͥѥïM%r$öY}Ç6ÌF|gRbã/ bq¬ƒ=”Œ nQÕ\ܛ[߷뜿0â!.ÿpïlF¥jåÉÅ}«¥WF‹Jù. ¥»ÆÑá@—Qº(ã<ƒEc O)Uü®A©öJÆs´nÔcS)çCZ^[lIT/|ëFÁ|J MõåK¹ðlwZ2i¯ž[+mè< Óð‘a‘ÓÐ22&:».­Îu`™TÝÀZè–Óuž…€B– ‹Ã$’ ©Œ”y< +h¡þë$‘Ææèe®4ú"cæ}Pls\ôOÉÑH++ +J߇DîŽKéÝÏ‘y2Çy*¥—@6äÍQdUyël^©]Îbä…ÀÚè< é£÷Ž†Û—IÕFP$Iwÿ¾Â}µèà lGnCÛÇ˓ôRš"YU![§[_6h±ŒôïþbµÈÖÔCÕ·S>ø´üü³òendstream +endobj +743 0 obj +743 +endobj +744 0 obj<>>>>>endobj +745 0 obj<>stream +xÚ½WQSâH~÷WtñÄ֑E|s]¼µN‘“XnÕrC2Ȝa&;3åß_÷L‚âݽܕ%IO÷×_w=þ8éAzpzN¿Éúäs|2ŽOºá>ßè\„CõÃ.œ^ŒÂs8â‡æ°¤ݰK–ÕšG7èõ ^¢÷ó‹!ÄiûA&vª€Ûp`iÊS°+a ’wÀpIß9|Šÿ<‰nºåñ6¾´é¼}1ÿä_T~ېk•pc€Õ|}šÖmx‘,¥óB)ë"™±|}ém{0"Sd!èÂ!~YƲ tŒ'ñø± +7ò¾¿ß>Þ~†ðZsØpm„’Ôî„,~þq  AI­ü{çÞâ´ô˜‹ôàHۇ…ïˆZç2£Òæs$Ð>9bér¥(% K&2S‚AoH!Êû´Oî¦ZH+ä XwÓ/0ãšR:dÃ÷©Ðþúi:£ZlDÊMS³<­—cÁ’Wª÷Áæ‡ñ‚3ØÆGu´: ü“Á΁”oöÒÓã-r|Œh9 ]ö2мŸH²5¯ƒÀxÎ3ýÁª  $Æt‰û£Ø"éGIù—u—°RÆRDê·Û)õºÆF­ÊVâS¾0ޑ˳¢ sàGÁ d–^ûç¾gïE¢•QK ÏB¦jk`¿Uç]fÄ`!S MÚV|=ï¾fÞδBˆpÉ'µLöDî&qTÎ¥óÚÚ;€DI«U9“<£iÏxâ§ðã¨Ύc'ÉDòŠ!jÁ}Ë´mÁ¢°VÉ®ä̊i¾ïØÒ¬¡­„¶ÐGÀ%³́ V%«•…‡£Ñ¥Áðäî!.µZÃ=KàaיàÒþÃ|¤ +ٗ8¥e)ªÃ¦Ès¥-¤B#Ù.„¯jË]ÛY×v˜Ҁhp5çž +µ^s|F¥Þ¢Q½$8`ìÅÍ#Cïê-§AoäsºVY±^ Wyžq˲W˜úÃ0o__Mëºë2£ƒŸy +œG¢íàçV?kAl—M=o×¥`kô¦IÌçŸÞ(ª819OÄR$Ì¢œ’šN±HK‘qƒ3Éў¬ky#‹Ä[%˜8­ÂHø¶Â®€ŠñŽczŸàPèB6+ÂmX;/š­vebù¦{ «¡q!É/ÂÂ]lŽ÷«Æ„–7é—Ê?Ùk@µnZäphTöxm- ¢Âè(‹ˆ¥"±‚åÛ£»ç_nÔQߺ=Ðw}Û({“5ÉIºe^S‰ø-M¢x´*±všï fÿ¥hR›DÈ ãÇÍþív2Žá·«h–+•}ÐØ±‡Ž©èr‹3Ն¨Z›ª_Îpâ C·/²ÆY²ÚKOa(ù£[JÎrï«ñr#štαÊÈՒ¥ëˆU£•Šiêîhl:åDíªZ$Jã^ʕLéI5]š‚q›DI‘›(?Þç^¾”ÞÕ@Kï¹Á]OöÔPMÚà~7mnB…LëlU‘¥)õŠ#øÊ?ž+G!£hÏ;·ÜA0…ƒÜ¢}ü¿Á|^»nµÊ·ð…›D‹œÔ©5Ðg%è]›Ë‹Õä!_÷\¹¸ÇÎ'¥hùO l¡ð–L— öÁ²Ð5ى˜*üâ¤K”ɘY¡ÎÎ&$8g,!àe|t/üõÃküŒ®ñïGæ|ೝp{#mÿÓ¬4÷–, éDc[×zî¿orøWmí_T0"¼óљ¯¶S0˜•ˮҵÂXÍпA²dÁœ<þ\0ìwéØYŸžû!ýãö÷—u¬ÿï'’3$ìendstream +endobj +746 0 obj +1360 +endobj +747 0 obj<>>>>>endobj +748 0 obj<>stream +xڍVmSÛFþίØ̈́Î`É2ÆSwB I™))Ŧý2ÍYZዥ;åîdÕyùïÙÓÉ`ä‚gé^ž{ö¹}või'„ýBtá Q¶óÛd'xM#!Lšé `ï].¯Õϓ4ß«ç÷ÀÌPµ„Ri ©”sHù‡neŽíBÂnw{~ÏbÕHð +u¤xn¸Ã{ü——Ë1ªªáí­Eè@;ìøGvÔÃ\¾…VÁ”‹ Í¡Ãýþ'¶É|3Ìè´' ãQ€& +¢"×AžÇÁ=°Oo.¤c6¦¶ ê {w`$\²þƒ‹B?֋Žìü¾Ýrvs5†¨PŠÔK—KÔ ¤\ɏLY4G[ÌHfY!xÄ BÉ͌fëctuŒ¿Ëéa–²€ˆ (7¸ +óÀ¯h2BãB–¦„ gRúôæn‚&« u¤Ùê’+­S>uªÔ´š‰s…‘‘”fÆ––h:$·Ê@ÂS„BW +Í6Xå3­³ÁÙ@‰¥¢‘È4•¥ÝÄõ_Ç´:¤äD]ë¤W™»—³œ'M’5üJ䨉yvzåלº}—£§‰ÍÐHæKǙ¬–?$O±¼qú>è#ž,)–æðQN-Q†›Ô^tÎ)ãee ïl†–áû-˜ÝÐÙfÞJ`ê®ÈÈ72d´›2£¶`ÑDkæÜ@§1™ð8Ï(ûÉQÁnÆcõyÝ–“väõžþðÉèwá šu'Jf MÌÅÉêglAµ*UÈâ%Lˆ8ÅømÖB‚SÉòÀóü\mcP‡n›¦ð+x°±S[£ºzˆˆL#Ū,´S.ðÞ^ÿnŽÔ0¶‚ÇE–-mÚøµyu­£Tΰõ0Wc¼áž"'nZ­ÿ+ +­ÍܨR×»º¾x;9¿¼Wç_œÿkA¾ÂÖþÇÊ9´_ð⋻u/„Ö¨Þ!´†Gõí*ê% õ¾½ íׯ±®xkÈ5ñ¨±ò„|Ûz¾¶fCÈqÕþl'°ªQ¥³ÏuÈûtq‘“Y4«jµm¶UhMŽÑ®GP?ܶJZÛtPQëå‚ÎRþÝa÷µ)n9³„ށW» }G–†÷'ÔÆ·([µ#h ðª"øË£¬]Á6ÒþI¤΀ðƒ«ÈGuñÐúDÿøÀUr¨>)Æ21%S§qF‘i£ueMß ¢`©h‡½íkºç¿]zƒR-<<°瓝¿v¾¸úsendstream +endobj +749 0 obj +1088 +endobj +750 0 obj<>>>/Annots 198 0 R>>endobj +751 0 obj<>stream +xÚµVmOãFþž_1å$â—Ä ÕIÊU'•+…œN•øp{l±w}»kÒ¨êïÌ®m‚9NTU Šâõ¼Ï3Ïì—A ~b˜Ìè?-çËAø.‚,s:™ÍñW6̔äGË?ŒÆq0££7pÃKõÀÉX^VJ3½ƒ\ÜAÐHÇQ0'i‘£Œ±pø×¦×Ã[˜þvÃeOš¿p%d¨KåpH6{b¹è…³'>0Ú² +ƒ”U=Aþ§°Ñaønñ %:ÂLG“1½¾ÖBZ!אkUÂ'!3µ5pQ.­ñZ Ä1i‘ÑoôÓC„‹×·)n@* •V"㝠SWX# ™Ð<µÅî˜ÒG7œÃíÙÕù•Û-Ó*–Þ³5w¦ÿ²M¸(¸6BI Œ7%4VXó‚3ÃAåY»a¶un\Œü®jH™D[Y(–5¢”ó)¹º\¢ BhÐWL_7?#‚’Å=–'I÷TÀ-ᦧ¡×°¤d‘øZm¬­NÃp»Ý†•+(½véuêQ§Þ–Ú5hìԗ +R%s±®u[¸\i—×1ð ›KµðbúД«€´ž6pèЊΰjUÁRît!ÆA j±ª²D)C¢½N¨Êb# l…Ý8íBH~êý<&?'ABâÉ·ÖUPûYbÓ¾GEAF1Sê±a¿scg9Ô1€nQBª-¬0&ƒB+pói9wtæ~‚f§j fgphƒ§sÑø@»9@åÁ·\ð^œ‡‚Uç¶Ã¾×!1‡M»U°e;Ä÷²ƒ.>SZÍ¿\ÿD#dUª +ŠšÎÈA¯þ>—,I,/®Ã÷×ЅO1‹”›ƒÖF’/@7 +9žƒª-”JS-é§Ýóâ8ÌÁ&ñ‰$¦IóԎ>Î}aZÀ2 +¡…èó‘bÞ_Ÿ†!V1u8ÓÈGÚB`¤Vas[ÎÏ| ©°¨¢0/ª¬c ­êµÇé•Hµ"ÊiÚ +WÜbóB¥÷p7<¸½:?¸;ꚀLÔ0͛sܾêõÄ¿!òËçâD÷_øh<Ýç#ÿô*>Oÿ>r@åqñƒ®}¯sUj»G% CÄÏ¢02ðy»é·L¥TñÂÚè°«h#\aá¸ÌB|—–—7ß ’– £=2tFï†ñÝQŸ±qkÍJxÖæu–i7W{gn ð«DþDn Ã[AÉ2ރEÎ÷NˆºýX7GIG9Û-O<©^Æi˜áãÍ{ó2Çb~ÔO¥ï×÷*ôäš BN²²•ðâ¯"Î=­˜1?þK돊_mã:§ý¦‘![¥d±£]`*žŠ\à Þ¼öŸúZ*%ËHžãjA¦î ;6~êu¯]}ÿÆbëÖ¸®°•š©ñ†ƒ¨ÁËÝã +Ý[–Ý> "QàŠÑ´Ìc8¸k±<¸Ðúû¶–rUkj1uÌ¿˜7‹lބ''(>›%^ÉÏåmK;gY)$îxäc…A\1Y3Ça#¯7:G¤6Mèp’µG¯º"Oý6øqÛgÄendstream +endobj +752 0 obj +1186 +endobj +753 0 obj<>>>/Annots 203 0 R>>endobj +754 0 obj<>stream +xڍU]“Ú8|çWLñ´©€°lc›}:’åö¨"»¼KR•c Е±|’ŠŸ +v“M®(>dO÷ô´Zæ¿_b‚ò}çCÚü=߃t<2¢8´¸C–jc™0“¹¨Œ€ñV ±•}—þë€<&`Ÿ#Æ¡„  ø£ÚïUOÓ/0ײ²²ÚÂòh¬Ø¿ÅçÄ5ŠY}?fQKTµÜî,ðÑ(îûžçÁú“Ì/êæZMn ùÁyÐêCrOóÇE +ÏÓÉ +î°L'8qHåÔ(¾Ôÿó8›}]=>ÞõàÓxñu6~¸ÃÊ(ˆúGyOË1† PbÄBÂ<+èÞsxøŽ6м€ê&iÇc(Ø}púX܃χÌ? «÷x¤·]•°¤ýà‰ÏpG‚¨•4Ùg²¼â{E¦·p“7µéËj£þ¢_Léío'¸G¾ïc{jœ ÃíêÔøñNô<á(Â÷²Z­Þ”±³¶¾ ‡»Öñ3£ËLØfƑ÷ýQkã´²í6JU½L„Gq ’t'à7É:£—å(Dސ ðÓKFŽ}O·zðí¦ûñi¾|IڟÁÝoïz ÔZ}—…( © +¡Á¢Îû‡'¸•ÐY óf]Êüü6v8vtÉj¸ŸÏ²ªpؙ\ëLßà ѳуg¡ š>ƒ1äx`@mH–•m¹*KuÀ«ÒïÒZ^ùÎN÷ÎÑNOƒP+È꺔He•<ƒñ|Š=œÒ”*Ï,š +WÐ¥$tÁ4ëBj‘[¥ÏÂZ¬QÎÅ+5…4VËuCjœg²Acô@VyÙbÐ2_h©°‹:\ö²nï²0%®”¾º º°‘%ÎÑ2¿ê¿–¹~-üåÊ/LÑO«ËÀõ¤×l˜7ÅÖ V!Ãüj' ¿á°“ù~Ú©uf(b5:ãÚ&ײ¶0dCϹÐR«È¡W|pÅð‹ðTŽ<Ö¦;¹¶žÀÿë ŒC,õ¨x8<=x>w~sÐ?endstream +endobj +755 0 obj +781 +endobj +756 0 obj<>>>/Annots 210 0 R>>endobj +757 0 obj<>stream +xÚ­V]sÛ6|÷¯¸ñ“;•(RßòSœ:ö¤§nd×éL_ ’P“„€’Õ_ß=Ô#'m§c$’ìÝÞby_Î" +ñQoÈÿqvööá¬sÓ§(¢‡9ž Ç#zH.n´!·ÔVR®ÍE¦R% m”[⾤ۏt{ÿ¡å/RË¡3aU,ÒtKøÐK[]Ó—?<üy°vwôyóGÄòºŸï§dõÜm„‘$°(^ +³/éÜÄUZíQ0FnXúGw8¢òa3?kG½ Ëϯ•uFÍ +'i-ÍL8•Q¬WJZÒsºÃS9~&–„Zg*fKsm²ÿŒ=•iú]T  L&JÐ\ʃ[^h‹ÕJçWüTÔ+£r' %F!OK"Oh®RÇ¿Ý (ì®+”ê|AÂÖ$Å:g–2o±*³T2~¸Ç,òD–éC§2¯O$ßîŽñ¬Ý›CŽxâ|܈µ¼ÊðA~‘hÐ uïrQj¯’%ºÌùY²²òw HP·®0¸F”/™É@æyI•¨$Ñ(0©IU:÷§A€~pVX²õZ%²~êŸo)—›šÿVS«JJñ¶>#$Ò@®õÐò‰¢È²#j&k´„ŽZÀû~àoôQ¬Wj*ÜȇêDûP#Sñ¼àæyªòç¶Óç¸Ë…Çœ`«¤XA5Ër-S½b4KTUԂªz£ «û÷híÌð¹+“Öˆ4u»½:;È?ÖyMÌqžRd`q+ÑM(ꗆÖîNª" ”› ólÃ!ÞóÞ »¥i}PïNŠØYZÕÕkeR–£³ xüøþ3q¨˜ŒéÖ:™µ|­e—¼®R½ÐbÛli.²²LÃ2Ýr+Áäi¤„‘¤X4‰22†¤Ø önu$F ÃI׬gXÞÔ¯„ô@ÔÚ+ÆØ¢U*…eýæ¨0¯ÁtoŒrgd%M¦¬eÂét€}%÷y(¯_lîq©[‹´•-rš»®x"ÐyÊR;¾ð¯ò…wJWªÓ‚?ZªÅ²ý¥©r[²›“ذ(h£ .}]$oKf¯™ý÷/E#R8(‰%ã—W‡ºv×½¥–Ò'{Z;˜o´–y¢k×fä"g;fœ_ßÎCê¥¢ÌÞzvvSJ5ӉšïÏnå‰>¹M¬^ÿ~%›F@<0¨œßŸ~‹CM±¤ +KÞÎ%ãÂKðZYê Ä=Óë“vôV{¶¤ó•uÚÜ6çÕ«¬2‡‰å¯ÊÆ|º˜fÜ46jåh ÂFU±6ž=$ ~Ý-öA +€èŽë·D%• 8xIÀë=äì½æ•}Õ׏)ûjjºóiü¬sÙÜâÚ»ðpÇ&Åd5ÝÖ85—/{©¾Ïã ÓôéŽÊ-ü•XºBoZ4-Ì6 +Ǎð©ÀÙs!SxÞMú“°GÓ«FØo \ҏQЏAÒ &ãaÔº/͐.‡¼{8 ƒ#+Düñ閆“ GÑ Ä<‘á÷‚Iu•Ò”çY° "\óù¼Ã¤rég‡ÆFfA¬Ø7Âp‚XgÇQaÕ>ìkó|•̝^ٝâày˜}áÚè7ëí3°|®ÝšVƒ£ïèãZùLoú¨u>+ÌâuþÆAD£sèv±»¿Ø³7ê–3Ø»ì[ä% ˜¿™kQÐÖüDõ‚c$šQ7Ñ_Tˆ_SŽ•#?==½šÁÒ¹Õe§³Ùl‚ƒ,:/ ¿sº—›qåàQ!á0,K-ýnw:®’LåÜ&áØfïDŽ7 oَú#SG]?„†|³ÑµWNåÇSÈøõìoTv(òendstream +endobj +758 0 obj +1397 +endobj +759 0 obj<>>>/Annots 213 0 R>>endobj +760 0 obj<>stream +xڅW[Sã6~çWœ·]fŒ‰K`û;ag;tK7¡Îð¢ØJ¬bK®$ãæß÷;’í0ä&óËw.þû(£ þ2šMéì‚òúèfytz{EÙ9-×8¹¸Ä‡âã¢mcýñò/œžS–ÅӓéŒOçÂmiaÖ¾VÒ½5E›{GNV^‡ß]ÔAkcéËÃý‚„£Wø]PnêZÚ\‰Š«´WzƒA­„“ÍðÍÎÒ)Ã%¹¨*Î÷†çô§iq¢i­4[OµÂã³芜òò3ë›/&éAà—Œ_~|E(R¸ž]¦çT#Wxß*Zp„FvC§·ºâ  Š ÀÀÒûæóéi×u©Dˆ\—ÂËàÄN~²“GÌg¬àN΂ƒ_¿?Ð×ù÷ùë;º¸¹ûö…ð?ÿ¾˜¿‘ˆô‚E~—Ö)£išÐÏ­–”]]eñroß=æ}1ÍÖªMéqëò* wéÖJ¹Ïå­iu!<4&ôMç鐁IzÉ>A¥¬› +I¯D.Z´ˆ+Mº1γØ/×4™fY†´Mfô°¸îuL³hñüYÚ­©ÊQ#m­¼G>½#š- ä¯PÎ[µj¡wW0§ف«J:2kò%ÔT*—ÚI*LÞÖRû„ Ly)ô†i¥G%ï!¿ð;7 %â¼ÚҐ•;µ²Ânß͎v^Š"}<¡]‹Ã²¥hhÈXïKð‹Šp á¥Ôèiä)ž¸B&>bS­\KkÙkhí)„*@¿ÍeJ¿èm‹+ÙzÈëCR ÇÂd*Ås¤ÈÙêx_°/ŒE2z.ÚM$×ó˜Ò>Ã.Rë€Ô)W>'{h+s©žYiks†*$Av#}¨þ^5¯¢|§/ØþN°2p›àA}`•š´ì¢7C¶~Š´”?iÓíP +ÃŽq7ÎéÒ°/s Ú´ ¹Ôò èVrHs&¥‹HÚJ\ ÜS9êR‡~ÓãEMì׋{â£qÑN¦åöaC£ —rÐðÅU¨\Z/ Ühp¨VªR^õ­‘MèÿÞ(ü=…!ދ֦Pk®qÄnqGþ#x%ÿ…×òûFŸ$„´”¡ØñÍ«˜ÐÄh-¡(@¶èLõü'À5Åå¶·ÖËJˆ IP4ªHlCU';Þp5FaGãt„~ zí,t%èz f)wÈɇOjàÒ«."ßbªË—ä;0ÂËÆ}FfÇa4ÇÍáež˜ï§¸aÖè6=í&rW*DŸƒ9®j¾ZÉ ¯¼¸°Åô[@r˜I`œ†Iˆpˆ?véºr+gS +Îy˜½Ÿ Âzhce…~0TÖÀå%9ì(-ׄós»ü…10òFh³;Ç~ý4ëŸi~;úʚˆendstream +endobj +761 0 obj +1524 +endobj +762 0 obj<>>>>>endobj +763 0 obj<>stream +xڍXÛNÜH}ç+J¼l" HòDȎ” ƒV‘xé±{˜ÞØno·ÍÄ¿§ªÛ—1°»J‚»».§N*çïà׌ŽNøw’ï|Zìì_ÓlF‹ޜœÒ"}S:[:£+åš)-,•N?颢jmü„6šÖêIS®RM¦¢$ÓÊᝪH •ªâ³yí+ZjÊL¢ ¯SZYG0ã[èß<­œÖT{MÖ½]üµs@{³£é!{/lÕßb£Y6GO¦Ç|d±ÖTbp¿Ò.÷ðœRb‹ÔTÆ^œ%¶lLñ8¡ÔøÊ™eͯä`nS³2‰’+›ev#ö/ßwPt¾¾^ÝÓ׋«‹ÛóotsÿéÛü3áÏÅÕÝÅ(îÅÅí÷;:¿úBŸ¯¯¾Ìóë«;º¼¾Å?o~̯¾NèËünq;ÿtϯäà÷ë/óËùçs~hkò ²5ž¾DH•ef´§Ê´}t*Šd«µv´±î'mÖ&Y3•2@C0Å}*3•ÔeƒrișÇu5Jdm³–¼bø¸Â¹j¸”Ž0Q|„­üíJØA_u¡Êè¦^¢†mÔ`Nîބ`w'#‡K +LÈé•v]f¾F +ƒô8±‰”OÑ®d¹TÌ”ÃhmS®RÖFÐÀ‘¯›Þ"{Aæ DŸÅfÈ«C†2µù¸m$2€‚ Âو/ƒ4ˆà9¡•Ö ׀’©&mph†%\‡ìðh‹—Bé}¼©òɃn +Á&:SÅc­õtäíáÍïÚiS¨*3鮳{¤`Š$«SØb‡¶æNËM_]AiwËîôá-](Ô#ö%úޏ“LS§½´¬§ÝÆÖ»Øè|ú>9˜?“½ÙÁ»é ?;O€=šŒ¶±bªø¿­«œffã8 lyÝ÷ÊGN§áS£X‘·7"^ž<|E~ª¤â +¹ºxVSeGÈá$¨E`"±8®œÍGWF^Û(m‘5dVâ)µ”¿øÊT譖]/±›Þ´ÔøQH°PbŽu©u1r'ò D^Hçáí”þ\ëïÀmW£ÃÅ´g¯~>tZíÇ:üÃÖ"\/¤—ˆžÝx)å] Íax[»„Uq‚3  ðM4·"7‰á‚7ã¤tjê|ºðd˜Æ>_eK“Ô¶öYˆJ)s ­ƒ'% ’_sjZ‰8JÈÃSÏêՊ@TϘ`’)“9$´QíU5é§Ö%÷'sKR ×|ˆQč¤ÚRó"y•x±ôº€O8a™êqŒ?-Ã3¶A•$ÍVœ£×qçfôÜíº÷ÝáôŒÍúîmº+ÿZ¹G&î +ÊÀ£—í”ëÆ£Q³¶­Dˆ€c2†ÀB5ÑJ($p-£Vâð(Ô®¥“Vµô/DP<ßÅkDùh‚Ÿ{™Ÿí|)wµ®e¹ÈC}£Žf«m'q=yÞ$2ä¶e?Žº—&ì]Ly6®àÒòRS¨Ì[ D82ôz°(}`K¼k´¦(^ÝÅË»áñg²°x$(ƒÔ0°µD÷ðË"™,ýQç«ñqºŽ¿_ Ï$Œá—BœåÁbû?¶x]A'|6lFû—gñ|&Ä9yĞéóýÍÝÙUµáώó³]ªÊ¢¹¿«¢VY çñ)níðµwg2agÇtðßÿ™p±Øùcç‡åå¹endstream +endobj +764 0 obj +1797 +endobj +765 0 obj<>>>>>endobj +766 0 obj<>stream +xڝXÁnÜF ½û+xtyã];k§99“Hƒ´v|™•F»“HeFZgÿ¾I–F·(‚&õH"É÷HŽœ,é–tµ¢‹5¥åÉÛû“—ï/i¹¤ûœÖ×WtŸÖڕÆ{c+O¹ud›vT˜TW^kOúg£«ŒKx@ºjŒÓô¸³…NHñƒ]ëù©VéNô^»ÕÊ5äôV¹¬ÐÞ¿¸ÿvrNgˋŊÚœMУ³&Ó,ºÇ«õâ’ßÃf‚s2ž*ۈgSGCø²ÙáØë´föœʔäÌv×xB©Å«¾¡ƒm]Œ×­û¦.ŽâáÚø«7äg!;6!ʟڥÆky"¶<:[Èaf|ã̦t@›igöª1{°#ßëÈ3£ó´Q^gÄaÁÒg·N•qr>V¤²Ì°ý„Jj¨í–3Ý{TU¨¡Ìé;f•M³›<œŸœª#؎yxÁŠö¶hK-¾É7Ö©­;IE©3Ӗ”Yjºq¦ÚŠ1A{Ìe[!yòŠOm­‡Ú +äŒó·m©Tä¸>ÿz¨¢iT¦I:w³VˆÎ ¡›o8€ÑŒcŠ`‚iÛ¨M¡Y;åqYyFܙó"cZ‘ÚXp¡vvo2ÍúQBUR…·HÀt‘ÆÉÁûˆ¬ýÆ àáÉMšÚ²VՁ53–Ï +Ýðÿ8§}m«ŒS^B¨¦ÒgN«L{è$ÕaYè¸l}KcDmÀþï‘ +Cºê§°kKåLq –3ŸÏRêmÞ<*tçҝª¶ú 2Ÿð{gËsÔº/¸ZÊÙÙÅëÅúx.Ô z›ç¬ê½*Œ¸&¤¾ÐÊs‡qZÓA+‡ÆEoY¯l„s™t³C>‰ð¡Ý+K¥uL4U…ΓZ/íªÞ¼IUÑk™&\….éc‰ Ÿ5‹œÌj&,‰Ê;©&"y¾nó¾ü?«HÿR·%õÚtU[ÒÙ«Õâú×ü5'+´5ˆÓ©FY2R¾GRPþa$õI:fä’³@¸çn¢ +à­B‡–!2é ˆŽ«lt%÷}UL{'HÞ39#Œœ xiÝ5ŸYG¡¸‡Hü¾•iÚ3_)äL䧑Ÿ»vÓOÃM¨ÖâáœZú¼§!ïgkü¼¼O/žj±|}Fï¤!ʇ^YjZ„`4`¹Pù²ç¡¼Äï—ê»4›™ÌtB‘0èéýLðˆr”6’<µ®1”àõ #!‰sxl±m0‹x$+SAÍuÑú™K ï-*ʚÆæŠå¨sSÉh¥ÜÀRøºAÎÔØ$„ð£™ÏPM¡>Àg,r0W—ìPC´ ú\Ûs…ÁiÌÎZ ÉôÏTס%ġ޵\iþ ³ÔTiÑfz%º— YÕ­R÷¡±‘‡SKÙ:GÈæÆTÊ ÿyÈ’,Õ7YbJÈ KQœ×‡Ó è;D¥‹°#zžj¼,„`–cÁ’fuð.¹¹„¹3M¹– ØV¼AJqï큠â^¹ˆ„‰Ñ>Nu¼Eå³Mmä˜÷à‘J‘»RáßÍ!’¡Ã• ²¡çΖ¨`¦½ÙV̪j]€_RÎêɆþÑb7,8€È܌ál^-1†-JæD®â¸"[ oè¼ÆÙv»Í7Î÷o&gQcS͎R…5ց!£´ýj? jÌSéø×·›î‘LöÆéÞTÁJÑ?с¼ç‰Ú¯Q2×"P“e‘nXôXJؐ•óQöxûK,Ï@Ý½5Y2S7h4"Õò€lº±Ï“Ö0)&W’~1í /ߒv +“©&3Ԇ۔íÍ&*ї¯o?}|GøïöóÝ-¿|yu ëòâ«×|p{òçÉ?z„áúendstream +endobj +767 0 obj +1714 +endobj +768 0 obj<>>>>>endobj +769 0 obj<>stream +xڅXMo9½çWX\¤É$ â(A‘X6»„ÃJ¹xºÝ3†n»±Ýúß﫲=ý1+ hzÊ®ªW¯^UçÇÉJœãÏJ¼¼¤¿Esòþáäìö•X­ÄCE.¯¯ÄCùüF[t£Do;áT©}pzÝ%ÂV‰{g7N6âñ¹uBš^ì¬û.ÖÒ«RX36y|±àNºÕʄßNÎÅéêåò‚É.ØF]ȺîÉJé'å…µ.”ñJTÎ6|ƒuz£¬Ó7p¬(lÛ/Ä(:†XㄍEñÆg<÷vʖºš@!FñÂg ¨;}Mèln<& 4]Q…Éá„I¾÷A5 ­MÝG¬Ñ$m‡~/ö Ø: ¯„¬ø‘ÏLj²8Œ ÑG,•Ø(£Ð0>ªeò™Æ H¯a‚‰¶á”ã£j§~#ɝeŽœh€&‰Ó ùá<‰Ñ‹Â@wÈL<ô–z¹vm{ÅÖº³ÒšX©“ÁAƒ8 ¿eNît]sìTŠS9öAESÈ,­R•Õ<í G2-¶¶s.?ÌÚwÜ!üN7Y½RÔ +ݺ#`¹^ê)ZBr†w\MÀS[Í"9XƽN؅LÏHI†E&ë/îÉ‘"ÕZˆT‚IT+‡ô¨åÖýÀ¶=7_ƒÕ¬’ çbºîô„tŒ¿­ÉrÕ0÷ʌA6ßAKšŒTD/i£èp»¥¥tš>ï(‘€˜ûuWÆ~¥2ïÓ\ÐìfnNŽÌå8ð¯1Iý Ǎåý.C• ýÝ©+ƒIò"ã*2JM›ÂBQÐõGÄ{=T­°s€!ßÚږý|Ù9دçãNޒ}É}r‹ðË臶V¿=ž4mm‰CFíēr~X±”øHòÐïY¤~±ÈÄ5‹ÞM¨×ñÿR|!@&R+S/`mÒ4ؐ¢o5òÍт­$*éÄB NG¸W‰JññRÎ5«²Äaϡۦ S]Ò¿Ç,wқ³ #¿`%ßÔ;¬*( s¤êq+[˜®Y+Çûâ˜Þ¾…¬Uš_˜¦¦¿oõ4XPã[BÚaž‘¶ÕàË÷=[ðÐäÀ-Øfý­l]Û]žXü5o¬ÉUîÿ,Ý9`ëò؜8μ‰c+ÌY6s5pî¤Ò¦FŠhõǰš-øyá…P§×¾™»|T×ýO £v8¢°äiGÝÁ[ɾ}y'ók`'om|îIýüT©DuòY ú/XÔtj2Çýw~uc•òžq¥m~? ÷ûÅH¯çËâïјùþ•Ù[±£Ü(juϓðàݺPmLŽB¦R.Å_x?¢¡ÏeÊj€¾*‡2…+k0è{ÊtŽÔ²ãoñj1åô¤ßVÀ€^Ǧ[‘?.vÝïu~+iñä/Jctdå¯î“‚\._ïuwuEäìö:ý¶fuqµ¼—ˆ ć¯÷_ߕ6D¬ó´Üu²Ž×¾ºB +§Wçü€szørõJðǏŸ¿Š7Ÿoþy÷IÜ}ÿéîƒÀ¿›Ï_nÈìæáäï“ÿ—Î?¡endstream +endobj +770 0 obj +1859 +endobj +771 0 obj<>>>>>endobj +772 0 obj<>stream +xڅVMsâF½ûWtíi· +X„½`WNƒ`²B’õaBÅ91€bÈH˜âß§{$0oR¶Ëêyýúõëÿsg@¿ èuྠñö®Ü}>a@°Ä7ÝÇ‹¯¶SæyÌf߂¿1⡊ÀCÍN·õ@A}n²ÐçŒ9¸ž3òØ„–0¹íó =ÎÁ‚9fވ7(ÎãQCoCÓ¸ourèx—pxÆÑÏü€Û¸Ü›ˆ @ìþ ˜ëb*Ö·8XlÚ“»A p:æ68”y*ª0:-l˜z"öH£›Ž;óÄhÀرÜóÙƒïHE¬!ºÌ ÷‰â‹\Wÿ…ùXߘŠ`ì„Á¹JRÙ3ø)ìA£†Ç%Aö®Ç}’ óŠ –Æ $jZáy6 x¶ ¼(†ŽVô[¯»ÌLD1÷„{Ø;`}a ¤ƒåÁP6&’œ®Ê -æz®ãóV Q·±…žð–Z5ç9dgTìN˜mêÖ_[£Î+‡™¶ÀGµ¬ÁU4ÉËaÀ‡Ü Ä º1§NxÕ3?À 5HfY`sëbÞ |î½S«çq— ´5Ï#LÇÖ6nëí­.F ècýiÓ0[ô1MË_Ȅ¡m‘nQŒO¬HYØÍOMºðÚMùH–\Q·_Cà m?ݚLÇLØ &Î@ g•AkˆÈFø'Ð*×¾Ä^}Œë;¤g¹ +MI’¸Ã¼›°÷/l¨i¸Í=f5Àw¹)è|£€þ²J…qüŸC2 ³>‡†"<š’Ê'´JÈûöɥȫ¶^j`¯_?ˆÝŽXޝÝ?`#dý»Ï)Úã6 +}35˜Û4CwÅÓy¤ê‡¸5„]vš„Ò;Jx8­=AC&¬Ð㷞¼l²r°”@»ÿ¢Ëe„ÿú­¡}bˆ™Íq剿i7Uæcƒû±Á‹Ð;¤=¬@Tj:^ՁOÍß)Íÿq!4'=÷媲Kd´’^‘Ô遠QòÏÇzå=ҼÄȱ'}æ±2n˜>ŽË颸¾`ðh§WÒy‘*O²: ø}ŸJ0žžŒ2¸ O§Ø‡2™íŽ*Y­ xýj¾~Ó±0TR‚Ÿ-‹C¤$ ³}ºˆ +DDæñy¿µËÿr»ÛHp7Q,¡ þ>)$Üß·qX²¼ sÐ’´{ ô'«Áðw©Ž²MrØIµMŠB. È F†¥ X$y¡’ù±1vŽŒ¶ô2‘y *[B±F˜MË4—°ÈâýV¦Eð0Äë(]%é +’‚r¥YÑf“äâTYÇ(uü3 ü.Ö–‰Ê Pr#£‰½Wë\SÍU¤Ž0r­€ ä)H÷Û¹Tx´sG{$† V™Ìáë3b焙©E’ž@ÿºö±Ô]%£í|#oÍPý³hvZˆ–™‚-¶òSség!ód•–jÑ~xˆŽpÌö +–è„E¶¥7ùZÇc#´‚ľý#¶ -T”õû™J d*U´w?G`¸Z’2]”™WûHEø,ÿ?3½«e;Ôlâ-‘ïñ‘8׊¤“Zl9¶AåçÆŸ5ûpOCcX§þ~ZL¢ÝnƒFÔl³-æÜÉ8ÁÇJ܈Ì|5VõàÎCvæÛÐ%#b”!Cª²%:¬34P´/֙Ê1Iœ,$Ŗ¶jÁ,ÛC¥Õ³.™d­e=ãa•YV—aº–)t1ѹR«÷AïPÚGÉ¥TŠ& +óWmkè¹Ú)Ô§¶ó?\PãtéÆËFFUëè½lë…A.6C¹nÈâv«ü£V¥hCÔ=$Õ;ò‚d©3’|M·Ê9µ’±LÞ t¯bJµ !Õ2¯d¡÷Iu}ŒG)¦2/rÿ…w Œú…Äe ™B*e5;•­T´Í+qK³Ã9Ë"£ 9åÁ–ÜZ;#”BÆE9fz÷纗©¼]I’4&Cæe&mž,Ȍ´¥Iu™ê-Qå+‘¨²lþF¯ê+!£f*y¥{XžiAP"\åÄeopnô U¡±Ã—É<Ù$ER-4¢P ÿ™ÊÍøXmF㡇\ºOÝrŃºþÇUÇÛ$%Œ¨ ±šDé>ڔ¾>×ìuÚ§ËùחòCïw¾ìꋗwÏwÿ¨Â0¨endstream +endobj +773 0 obj +1658 +endobj +774 0 obj<>>>>>endobj +775 0 obj<>stream +xڅX]o9}ﯰx¤hAí>*,RaÙ¥­Ä‹3ãÉ;؞†üû=çzf2™†]A¥&¾¾Ÿçž{Ýgçê þ«§—ü_mÎ^ݜ=~óLŸ«›'—/ž«›úAnrvuÜ/TˆÊ6j:µ µmöÊæåÛogOÔ£‹Ëå3Ê¿Œù©7[gƒpmSŽvÕe£ª°µ&©Ð¨#Å»ÖàsT먳M´ÓàG«Æ@‹ØëRVk{kä^4•…ŸSoýüéò‚ÖµsEÀ®Ûœð«ÎjgÔZã"Ô,Õ?ƒ®þnTê¢)B¸7r *74*íÕÚÈ©J¡‹¨ÍR½“ÀfƝõßáó6„±Q;›Ûã(Ç@ rkk*cž–°úfª¬된fAÂöÁK:53˜Æé)«ºÉÈ,âµ~­ªVûõÁF/¤´¯iîXG1ÔU½Äw£Ç© ;103¯Rhâ¦÷~÷EÖÆ¾sŒüÙÁ<Ô’‘<ÍÂÜpGµ^î‚JÙlÓoêëƒó¯ Ÿ½œÏB„«_\@ 4 ‚¥Û¹œ­ŒOfæô®µU+hJ"êÌZ;µE6%<³CK‹)raã1 Ñb~ÝK—€"â×h˜U„x?Á¿ 0wÚgZ4V&fm})µ¹5q¼Q¯MLæÓ Áù0KÇ…{1.ñ7Ñü$j§EǹDcM­V{”ochи$Ѫ­N GSW- +óËæC}éÙu#^[6Ÿ¸[ªP@ë‘pD˜$¼µß3A+g€&ës uWç£N@7Šî4@ãØ?,ÝԂîÃçm—5Ó~Œo(éDû’¯¡-ÎÆÃ‰ +wQ…ìö%YMFº!Ìc@\}AŠljYM}l-žÔì¶(ÑÍ\f¯iO.ÂFå®õµ[tôD!)Vx'0WÛ1eÊÿHDP°¡N823>Fèá->l£5™,/Õ BâHH%7Äe³ªœÑqR·â‘ÅÊ žÕ„âÌø€ìû=<»$\KxŒ·¨Ô¹y©Þ(ûáóè&&Œ¯\W3J·‡¶eFP½*ÀTÁO%U¼EQ# ò±[Áªº.–'™b*ªM²k_R¨•³y? Õ¿™°ÍB¬ÑÈußi¿0¦ôv묰ñ=«Hm}íØãüÑY:ÜÇ"41lŽ#FºgYÊÀ è]³ˆ0ÑtÎ ƒÎ\¨ƒ¿*¤ÔmÌXf@ÓÁËÝTæ¢Æ¹ð™ìý›×ðF&›NhÕQZ%³Õ˜ü覒 !6æú¸®Åê@-+×ÅÒgè!@ Nµ]’n™E$$»2ygŒïyœÑpѨBlݱûɀÉb>ï¡n˜‰×˜³ü}6åõ8ŠæøÁièr»}/Ɩ•¬I€Iâ=²wgÂA\ƒ«Â:t2Àcç}q¦Çã/ºœh•ààùRývìE6tdó3wäLX*1ÀÌý4?MA‹3Ü_VM1:ÄïpèöF¹L5ÇÌ|Øqsžì0ˆ8wÀZêªv¬W¦ÒB%M}Ä›Å$³ÿgÐ; ®Ÿ“  +½" w"ÙŒöw§WýzÄÇ6d¯waËY6èäÙ¡ÖÒà_¸ +³™zXbÞxg†`4ÈPSYŠF'Šm‚«Ù Dû²Æ–Ëk<±’z¯=@JÊ½GÏ/žðÚå¿|zþLÉGY¯>\ýýòZ}üüêúÝk…Ÿ«Ÿ®(vusö×Ù¿Ô¯ßXendstream +endobj +776 0 obj +1780 +endobj +777 0 obj<>>>>>endobj +778 0 obj<>stream +xڅW]oÛ¸}ϯøå¶€ëÖn6éî>¥iÒ5¦½‰‹E¼Ðes#‘Z’Š×÷×ß3Cɖe‹E"‰óqæÌ™áßgSz‡SºœÑû ʪ³‹³··¿ÒtJ‹o.>\Ò"µ¸yøòHW÷Ÿèúëý§ùbþõþ‘n¿>àÏo?æ÷ŸÇôiþ¸x˜üίäÃ/_?Íoç×Wüàõâ/X½ÜY}3»˜œ³Ýw“ôê¼}õŠkèÎdÚMW+¯u¥m$Uץс¢#e·\7Êk*ÍÒ+¿¥ÍÚdkʜÊØ@Ь‹0Bu©2ÓrKq­ñ¾Þz³ZGöŠ0¦ï'3cíÊ\{røÁgžT×Λÿád­|„?µ5vE&R¥¶´Ô”›½Y6Ÿ4–³ý¨}ÈøC²H±}ÖV{UÒ·fYšlàºKõé•*ƒ£L•%LŽb†ÑÓë Ý(äW¦šðRå¹×!àch´uÍhҚîÀ½¢Q ψ*­–ÌÁ~³æÆ¢±òŸØü-pÈUTT{ôá)Á~ÉÚm ŠRn}Æû‰ëA^R°L‰§Ú»•W@æéUªSƒ„ƒ«t‚Ê…Aâýé5;,œ¯Hÿ£³&ªe©Ã0ÇPµ@Æˆ¯t›1y]h¿'K—GŒA’çŸ[欑ßRk{º°A²“BO‹¥â: S&ÁÝ!æÚ¥zoØ5Çãæ½èIr·ã(•jóÛÐïZE.>2%Ç(¨œlyÏú¡Úù®Ü&Ž»p^´_Âu%0àU.7E[°ŽCçù”Š‘FŠcDyj&+h§þ)•]5j¥'¨øÚkcUÈÆÔ™à€†±YÙä-\ƒ”MebûÚ垌FýXG“§×NŒ]ã3fj®GÌ ¦T¶S C˜ÚB0¡a[þ¾Rόå!&ÈÏÄ ÝŠ½–EãAŒ™«êRGf÷.„®÷ÊRœôßHlxG ÈÍúÒIØÒÕበ+ÁeFpÊڐ´ß\(¿àVXjO‹¿Ì›:s`ޕġš¶Üsð‹êÈÂgÛ,„­úoˆØµäVVˆ ÔÆûêL÷q$îAПƒƒ4ïÅîwv¼•¯@ˆ`òaª¹ø¹¸ùU9ZßX¡¿êÄùÛNØ1Táe€s,ÑÁM êÞUI*ö6L8ªo +ÚY¦q»ö{CLʳ¡sµ ÚfB!Î{ïh·J‰ì7”Öné@&™=ô‡m¿«ãZùÛ*t’0!ÐzÐâeא¢ô¬±©+Ùmj·mk%¸Ô­âpÂ]àƒô€yl·t…þØU+ŸÅÏÙ8û)E”¶)†Š?MÂn\i\C`yz¤úýtó$ Nu‚HÏáÄéV” æc ǔÔš´§ø©…!—í²Ò:ñ-ed›ËenY5p8X­R<< e~6!²äé²àMP-Uö›é;x'´œ?‘‡4bK™bÕã´dfíñ”¶œàe™ìš#ðv ºÞ5²P!ï™®'6¬”»öHgÚ`§Ô}¶l£Ò›÷¿N.~ë—}°1¤½¸ÝÍs&¶u]“ðR$ým|ºK0¿õD;hΦ;©éÃڅ:/¸TfJexÄ~ý:.÷6ãÝΝöDÙ¯9/YýSN¡‘k— ieÿ}Ã?»hÆý5AÑQ¿jäbW+¹ÃlÖÚœ9ž½Æ¾¸gڑ¿Ýv•Á®ÆT\9‡eN±„ém9à×x-Q;Hô‹Ü'-õ㗁Ž \Jþí¢–`5>Œ£Ÿ«ÆU/òÆí?X!‚ÌY8öB¤ 3Æ×îèjáu%WXÞÁô¢)wDýe6ù Û^ªÿÛÛ­ªMg3¾˜É]®¿{¤Ç®5¯r´ˌŠ•ÿ¢l£Êdñü§Þ\ΤW?ß§»ùLJ«‡ôùæþæáꎾ}ÿx7¿Æãë›ûÇ>t~yŽäÀÅ{~p³8ûïÙÿDbo endstream +endobj +779 0 obj +1726 +endobj +780 0 obj<>>>>>endobj +781 0 obj<>stream +xڕXMoÛF½ûW z²Y‰?*'íÉNÔ€›¦±‚"€/+r)mBréÝ¥ýû¾™%ere')ђ;óæÍ̛QNè%þœÐٌÿfÕÁÕüàÅÛs:9¡yÁG³W4ÏïßZGú›ªšROHQÑÖY0¶&Sã[iN¹-K™­š6hò­ršœµÁÓJy¼Õ´®±^SX©@Ɠ®ƒqºÜÍ¿¼¤ã“³é)ûÚè²<ÎuajÃ|®:-pU“jšÒdнOi¾ÒNÖÔ]»ð:‚:ÍÉé‡Ö}ô¦êÔËÀʱoù ¼í¢B°A-JM­Çñ‘­x÷¸j} …&ÛðWUþFfåVûÄim‰³-™0‘žû>˜²|’Ïéý>F~ŽOgÓs6 "@muº¼€‘œ°ŸÊæ¦à7Ö}%ÉÇfeK=¥›‚ ó‹ÇrG¢|ƒ¼xÎ? (×ά™8g+qs+%R甩šYrZy°´˜ váÌ%™å—½n”Sˆ”Ýy®+Ø«¼.×ÚO·xRǔܚL×^GAí*?ùŒvHWÞ.´ ØÚ–rãƒ3 f˜Ý11c ÓÄõUž»M^U0CR¶×ø4يK_ERŠËËÖcêð%¥¹÷#µK-ZÜUb´!ÑÇ7†äl$ú÷-C7zW^B§èoùH©Žå{5:d‡Uë™Y­赆HÈN/•ËKí .ÑÆYdBOçcٶȖ=à„±/S‡]»ß*âR*S‘3Ë2PNAƒäÂõÇxM¸Ý8`g§2ÜÅxï÷$>d,L†ŽMŒë›v™ñ1³b;Ê[œ-å0͊4z­#¶²däë¾¢ûdï×rŸú”œhkž¶?¡ +]Cj¹dn{ªŽ9”€™¾§ +Š6&¬F÷‡À'§±DO¹?âEk[¶(r©i¬SK vDE¥sÓV¢”3õRŒ жè|÷>³N+Xˆyñö¢›KŠÎºGýÈ:¤ÏèËJmY›9aŒ{ƒ1ç¦f.Þ½ÿDït­*éC»@7ôNQ>h•§`Äj‚|‰4×Hy³íô)¥¹e1bÑ éXU >c!$˜îFÆ›´°·ñ1Þ߯wžnԟlBèT/sr2 +rìsŠ:¹á<×zDý HKxgîÿ°+;AÓh –\Ú/J*Ï ßèÌÛpgcôæÓ‡;ºë5ø2¯LÍ,*ìàžþRu«Jù?xëøâô%_›óáéìlúšä€÷Û›«—?Ó»ë÷×/oéç«Û›78~sýþîš/\Ïþ9ø[endstream +endobj +782 0 obj +1730 +endobj +783 0 obj<>>>>>endobj +784 0 obj<>stream +xÚ}WMo9 ½çW½l8nœ&N»{J‹´ Ûí6ér‘gdÚɕ4ñúßï#5ßq‹I쑏ä#õãhAgøYÐÕ9½ZRV½}8zùþ‚ zXãÉòõ=äÇÑךL ¶:3ª,÷ÌÆšµÉ”dÖ M;翾 •¦ÒØï:§‰…«£<¾3+¯ü~FΏNÀ®‰A—kR8&ïÌO¾ÑéâÕüœý?àÝXx +W洆XàXtìªg]¤­>ØÚS®×ÆÁjO¥Úµϗó 6x»¦Pg¬[}ÓY¤µ)5ÕArÇm]ièJÚ*¯*µ3ÊUTà0‹µGjà¬ä¤²L‡àø-þ*°D•ʼ “`úÇÆ‚&MëÚfÑ8èñ8jËÜ1 O%,â%üµ›X<žÌ˜4+Ì)¹Dâ0ÐP[ð=ê|F^o”ÏÙÐï +óHFäs%ÞäÄ*Pç͓Šæ)%hX7ÿ鬎jC”9•±ÆnRÿ™Ë5mË:ÐÖùN8qܔJ „È¿×LFmá—îµPAËùãÉ$g3ز;›–ÏrÃJWmHò€‚0ÌʪŽzȚ NÕØÌüPIH=Dº¶{Ò?£FÅdP•Á qÖeþ¹zñÿ~Z,¾ë¥Ü ¸c¹—¦ÆØ´ÔøË÷W]óvÌ-›Gm_Ó5- gz+XÐIl°†‡+÷¤{î$„ÌU[®1.L ë/$>‰T:g€é… <@c‹·Þåu¦a()GOÞ¤‚údrïŒْœ¨íràÓf…3b‚×'“ƒO9Ügv‹ßè„Êå"kB‹ÔY[$Y¢ƒ8üG;+È¨¼~‚DL‹‹fFq"(6ëU½Ùð'‘Ÿ¡³0Õ¨¯L>œÑ†Ë°+˜‚Ú¢RHª­`%sÛýjYW qæ¬%‘áN_9 Q¨ªJ0C9ø¤¦Òów@`ƒžS2ÔÛ­¨GføÞí^^ ©qùÄ7ò»…²±äͦhCMA²;c³²ÎS+OßëRՆ¯*'©+TP F/⯚8öz - ¤VKm,ZëÛ9Ý5úc.w"­ Sáwv‡)Û%ø:ã–RvßSÓµ6?)1uð‡žoÍ +léS¯UΒC…žé±ŒNibŒì{®VÊ +e7š ñº+Ëãñ®0\¤ÒJú.+YÀÁs>-"‘Ç“?øásͶå® ã†FÈÄÇ3B~¥I’ý¡ðØK6 q†}spæ§2àÒ¶ûq‰IOa8{-â8’·ÔæˆoñhTèî•ÃÒGðmLÓÄC€\>F‰¤º.Ÿ‰/‹]"ŠÊ.dRªxMmžWŠLfžGVóN£¼Ac£7Co4£€m(ô}«—xX= +h輙駋34À՛¦JæÄ_Êwxr9_þª70+¼‰¼%¹5ºuFOª4i%¥V!ʦ¨i¯/c€$úÉf¹¦›‹ç…„1€Õ6ì¸,Ý׫ÐÎk5k碸cºýFƒ)ëeنz€í˜(x±j¥ç2—Ú ¶ç‰–µÒ°jHYÐéåùüu³²Œ…Q)ÔójŸha—i!åøE³Ö˜²(ñ⮸‡!²<åÀtlý¨±N•1¬®½{Ñ?œg!.0¶gGr â$ÙëRÐå'¡<=¿ìA¾ç¼…K6r@_<9Ýmb~¹fW¹Ü,XDÜÒÄiKBK6¸†à’£užÁkR˜VBâ"y0qNº+½Ÿ¢æöÖï} þ@þ~V£pɞE°e°¥åæ+¹B =bð6²æ6Ž€}e,«&óõx҉ü³–ü†WYœ){DŒXJ£lB“¯-¢¶®GS纻 6ªdš|ö¶ž]0£,ÎÔQnl*Õ_[*e‰ö*ÇM-Y+Ó:Aíý­Ý€‡do½Ñ‘yK×ä„Bñ¾1A/âÝfC¤tJÎÇáV—J+8çFÂÀcs¬ë+—òTµãî'W»è6ÍÍÒNæ|מ}‰4w“×ÍÝdqqcËå2u½ûòéžîÝ:îx½Î!§|TE\µé/ekU¦Î•s§Wçg|ìÃÇ/twûöóõç¯ôáæãÍçë;úôåíÝí;|ýîæãý º¸º€¶Êå%qópôÏÑÿXÆDendstream +endobj +785 0 obj +1744 +endobj +786 0 obj<>>>>>endobj +787 0 obj<>stream +xÚ¥XßoÓH~ï_1oW¤&4-—ÂñTPCâGËR_Öö:Y°½fwݐÿþ¾™];Ž“ “N  Þõüøæ›oÆü8[Ð%~-èzÉ¿óúìÍÃÙó?oh± ‡'˗7ôPœß̟=|ÃÁ‹tpN_mGµÚR[©\Se2§Ü–J•›Ê£=…µ +¤œ&Eë¾S¦¼.È68Ðô!Ý÷¦Ð³l;ã¿É4¸ëM³ªƒìõ’f‹ëù‡ìJãuGÖdåŸG\76PnŸ´ƒÃl ‡ÆÃc®¯/H5Æg².hò]¾†ÛÜ֙ip?™»˜xn}BŒEL‹SðºUNÁÂ`Ì 9[ÊáéŒÙ}ºt2~ã'Þ忯xM­vµ A1‘ý°¶¨IaÙ6n† ÿ hú?ت;»ZÎ_°¹Û鶪ÙJÓÔ#¸ I»íCõªþERÔ5½•IäÑ<JvN\žºó²˜pÒ5^a?Yû>–{3ԞT† 1g‹KdÖûTsâ‡òlvýj¾ä‡ï̓f¸jÙ¦S= +Br†@CÕüÔÔç©'™ØpôOô‰iP Údd©4M!>T_>Þ!I¥uõAR¾‹!Û,f»kÚÙÕï»´_žlÜØ$-¬maJüí»¬ê»¤2ÍwA炬÷˘Ëúg®[4¹çüœö¾ÚŒœ Ñ×r׉sº-¸\ÃÆŽá@æ†uÐ>OÖ¤~٘ª"Õ[+Ô_U˜¹end´#gVëàéX¼ٍ†¨\¸O7kKk^9kðkš4òÀ5 5š½  ”>=tƒã²ˆMdd¸aäÌïÂ,È[ª,¨ÜE½R8çN×`‹jÙÁ.S¬2ªÉõ|Ÿ.—;]xu”,¬á•Ó?:Ҋ +²\ù}e…tç‚bL€ßñfÅL6a„ž³,‘®óÊ©p㥩àr¾Þ³¦Â_äÂ/jŽ;ÀÔ<¡´O±YD]X U/ND`m2âp¨Ô†L9qž„”38’©u퉤a"Ç)ããŸÇ>žã”•ð? +Çã³ Á*¦öôŒáp£2Œè˜³·‘éà¶ ¥“Ÿä–" ]š 1NÝ^ü¸¶Kn·à»Ë%>É+(ñ”Xw +Ä ¦Ž|«Ž—õ4h4‚‰D t¤}¯½šB•õ;uVìHÇèQtX•Nàx¢]t# Ú¡³¿ÒtÙ7ÍCÃN——8–Ôc¾'ʦn-SY—“± m…ÿÄá”ÿ°ÿ ò«]Îâ§Å4é(iÒjÀ¹kšù¤·} Û&ÃêÅäÐ þ̹ê;ÝH«”+ý v¿/N`q@€÷å ¯xõG§¥ù²¦o]±ª¹œL€ªÒ+ÕïW-šÏMS:¨ûKebŠMˆ)ëçÈnGeji~Dߛò¾Óž™4ê†&–B(Ç4}<Çðó€"†i]Áš¦VN‘ ³ìñ™¬S¡ N¡©CÚ<—“Žbo{!°í|l—²§ßà#ªš«†m÷_Ëeû’Wòº« 0Úv<ÏEu,&p,À±Éõf€Êdɚ.±;#’YsXÿí¨ N(TT՜þd–þT 'p2̛TÌÔ×Ó=ÔvU!vãMÎnU¶³…ëÏh‰ï]¢Ø¬¦aÍmÉ3?©ÅùŽHñ T¬Š¯¬Ýé,¬íVkN1e/šÓàh£ffbìëM^6•l‰ã5A®e"ø˜BS~â0À-, Q~‘Ú<½Ø÷)8Ãul­Û]†g7nÞ{×¾Mó¤*S0×»&J…V,‘b‚%"ï*…Ac\ÞÕ^†VÔêLUüÔiÓÝ93Ы¦HGÛVi™ß +¡&p~ì^"+ÇQøƒ¼e§gv°í¶s¢ÀÓôaíOå§(A)c¦Ÿ€÷ n…mÜý(Ç@-Ç“ +O‚ª òñÁ&e»‹ï½ÞeÍ=Ë0pâ£xá3ð•4®•KåslŸ8÷¶ »=žø­Çbd B`d¹ÑXàâÖÔÊN>ÌÐÖñ‚ÅÀÒ߂…¶¸×ÀZS—+Ýhtƒ'‘Âä2^ƒ t¤b\õaxòµ›I>ÌR¨¨48'`YÁ‡2ļà…j ø`âuú¶ëÚ>¬këž¶‰Û@™ËÿQQ’ì ä×B;^Ür»¯¬1òƒ5 ƾ̔€¨h)Ä%JuÚ$Ì|mMÚßGä}˜´è¸ jõßµâíW¹ac¸™/ìär3Ӈ³8®>ôp°¨ŽÇþË4Ú/np¼\.ã(½ýòéžîû*ÞøŠaŒT°Î3[:UÅOZyovsuɯ-—üðjy=EòàÝÇ/ôáý›Ï·Ÿ¿Ò»»wŸo?Ч/o>¼‹Çoï>Þßñ wgÿœý ͔i+endstream +endobj +788 0 obj +1824 +endobj +789 0 obj<>>>>>endobj +790 0 obj<>stream +xڅVMsÚH½ûWtù”T;^;[{bÀS+$¬;Tå"Ð`´V&þ÷ûz$#ìlùh¦_¿~ýºåÏ.è þ.èæ’¾^Ój{6 +Ï>Onèâ‚Â5N®¿ÝP˜|¸¸~ ÿÁÉU{òäšª¢$-«"]ÖUªsŠóä³.¨.鿨I—E\n˜Jëx¥ÊI¦qæqF/—h£³ û¦]Æ7XÕ9V°sҕÊÁ{?Sœ$(¥—XýÚeé*­èQéÇ"ÞmÒ2•Ÿ¥Û´ŠÍWõk•ÕIš?]ö¥Ì•Ïâê8 vª@8×¥ó Šõ @x«x,×°ê²M§’!ɜÊzµ¡U\ªÁqii¾ÒÅNP·‘á߸¤tMû‚ ä§¹ùöR'ÏM[˜­+~ùty=¼2Žùz☠“B) +ôºÚÇ~¡’¤!Àºïêe––8å)-UÒÙ)W{zRE‰keßWS•«}˜sèªÇº+|]è-UéVQ¥ÍçÖèxŸf-•%‹ öh¹K!ˆ BÊ [vBë í$]¯Uq*Z¢àðŒÃa(—&á®ÐËLm»W:Çä對ìÄ1صy؏éºËÀS5Dbku7òz»TŰÉN›r§Véš}÷®vm|G¯=¼½¡xóS4Aô‚Îãü™2اèðÎô¬kÚÄOª™Ài&à×:Ëô¾œÁÛ¥Á@ÉIʗúÉÛñ7Ìâ•Y%<:IÜy.Á¨~ã¬Y­ú¹y޵0ü‹F†c͚J¹ß«æ‘fNÝ…/ÿC©—òÁ÷gèê­­Ë4ö<&ܘÃHckÕÉ|`EjÒFÙ5³û°¼Ð‹½YKG;èÐ:å˙¶XÌ)̋ôՆÓðŠá¡º‰k¬»ÂX¾ü ÍV+Kӈ ~—]‡“Áܯ7z#\_ªw:ÛËýÞµ¿h©Ö[œ_¢ƒ?ïKµkJe’< Ã^V¯.(%L»å€ÑKý­öšuœÕÍz(ž:ǵKl×ڜƈǻ&}¥'eéºéI/ï‹@<-WouÕÁ–›¸àï|X¨öEûòØlÃìù}O¹=X¾o¹á¢·t.þ8qÛHØV +o9rä[þ‚d€¯¶p1¦‰/y²o-*|Ï|ãUšx~¯ÄWpˆñ ¼ø +7¤¹ðg2 =Z5Ÿ#•5rpÝzâŽ-æ!=Ü +·ß,Îü A5-Ž–.=ø2”îÔ ÛÞ|áËémH·ž3~@–;þìùdinù¡Atî{÷r|\ý¹ ¾szá­…‡*¡‚å.èoéŽ$¤ßç¾X¨ ä ¥ \•®íDcðÐx®"$@PèE©½ÛåQdëá̈́&¸¡5’Ž”GºHÏ «©ÑŽ åFþÜ Ä°ˆhš/ƒ¿ ŅÞͺ‹¬Tt€3˵Më{Ö`]háExÃBgüúü yÅDØ¡¼‡{A4mςÐÈê8ä +•pŽ@ø÷Ò6zùbnIÿT[Ûó}ÆôÜ߬ÖëÓÕê²mÅ=Û0rVÎwÄyÌĚNanÓk·=HÇéña_ô 8088pc{4³4óÆr²h-Ú„¾„YŽ‰Þ†Çy¬èˆ edyÙ +ckfME0è;²3¢¡5®ð-g@Á\ؒ¿àÇ9LÝö°î"6´dÁE@ègvNáe‚hév>¯þ‚ùñŠÊéHôÿeñž0-2Åás$8Ö.„6»À²íÈÇ^àªA„M!ݦ·¦ÏÙ'鏻Õ`ÚEK:‘â{áA{N`üÿÒ×hàMB ±øñq`|Frömë :ÚG ºEKG׬ñ½4[Ĥíꑭš^‹×ö£µøŸ§ö‡4 †1«û9–<2A󭍹¸ºAšk$ûÆqdGóà𒵒mšó¿q¥‹’fq^Ç|jâ>Ý\~á°©½ˆÕ: Kh„yêÞ%tus…,&àú†ˆðìîì?é‰kendstream +endobj +791 0 obj +1612 +endobj +792 0 obj<>>>>>endobj +793 0 obj<>stream +xÚ-ËA ‚0Åñû>Å;ÖAs3ԎÛX"Ø0‡Ž#ŒTšF_?­xïô‡ß“PË(Âhýµ'Ý1¥0-è>öbÀ4Ⱥ¨Píü¶îÞôÝÐM³³óè&œì𲏭¹ï§¼?‹’5²(ôø†T×È3Qòò‚TiUòE-òL.Y*]©(CÎä»ö)?endstream +endobj +794 0 obj +143 +endobj +795 0 obj<>>>>>endobj +796 0 obj<>stream +xڅUMoÚ@½ó+F\B$plcñu#ˆ¨‘Ú”¦®zá²ØcØÆÞuw×Pþ}g½6!¦Bk™™÷潙õïN>}‡0ARtîãÎÝÃB⠂iä…0O N{÷0€…, +)à ÍAªøŽÆp±Õ·ñ/ʊ lÖÀ¥ †QH?”ï¸V–(Rþ¹G¥¡`â2³C(eYåLA¼XÝ=®@4å¹0¨2– e‹JU€FUW`{Æs¶Éˆ•±,|B:Ԃ©4`dʎžc8…`lRÔ0ô"µ"ãۊJo{l‘ßvFyáØÙ¼Ÿ;p”d\iCTµayN%Zò-[©ÜcCÛr¥4ŸçOýº€@L‰%ýoj1jlª+%Ld~Ñ׺×}\u×·ÀÒT¡Ö|PH"±ãÛªÉ ]Ëa«dUv[&ÚÁ%Lœ š +ôL‘۝ó¢áHaÔxÉæ|’¤fúÔ·ƒN˜&—lý'LXåiÍ·â‹¢Ò`~„Lɉaْ€†Kၗ+/_ì¤\U’Ön™æD×ÛKžêÔšVeÎfÎÑY’ð…uˍ…5uä†!®]¨JGê_ftàz8 è *[‹|C8[©ñ%}Õ~~Á”3˜'4ϗý-œØ@Þ~™/ÎÌíË5±’^ý„xSaš3™âY”p`´=-§ÚŒÆ‡JcMûzKRÜó­èçLç‹S;/234í[£" ·n'} Ҕl‹V©4†\mûL·×ŒÚ]š^ï`ÓļAÿ¡íáüyõÎ"º«Ý…;¾Ù£W)ˆÍëbºŽ®¤FìÊûMùSåº7Yß¾EíÑRto¥N®ëœËpM«hï® ÍÛæžQ˼ªg¹Ýu;Ô­€’%îþª êžq²þ=—ú¶kÓê×tú®Ó7úL˜™#ÀÔò¥À Œœ%Ô 4ðrÐjˆ ìé`ù/Ÿ[ ߛœ¥íèJðRY0.<’ üÉÌ÷g£©ýÂÙ0ú(9˜†žïÙWÇiw“ömciG£ýŸwT4ŽÊ·‘£©=XƝo¿cx:Íendstream +endobj +797 0 obj +823 +endobj +798 0 obj<>>>>>endobj +799 0 obj<>stream +xڕW]oâ:}ï¯í•J¥ÀUڊ^UºÛöR*Ý^Lâ€'ÎÚNYþý±>B©ºj U°}Μ93c~]t!ğ.ôôgw³‹Éì" †ø|÷¢—Ð×]ô†£`Ã~€Ï9¤´# BZY¿àòÎú}˜¥xú`ˆÿ$­{•§bYj‘/Á®8<¾Àm’hn ¼z8½¾\Î~^túÐíú½íèšöÎp}¦Œ…Tòßb!9lجB™²\n#–9Êü¡Ü@™'\ÃÛÓã bjU.W{Êß¹6¼&@¨ˆÕíaxˆ6åFÉÒ +•ËVVÅJ¼õø}›_Ž(0)ÕÆƒœÛÒkHø»ˆ¹'õ«äH–òÒ)¬ Rи­ûãö¾^|…{P9¥1pÔÙa®‰7~ࢨ‘7BJ5…ÂMaW„Lë ¯¹õ¼ä Ț}XñqoixP­ŒËžÇ_©R&°à´¡V<‡­*aÅÞ]àËْÓÛ +L´udµÿ¿fEOŽ·îDlЫ%]1 ‰ÂŒæÊRÊy¶ÀĒ”ú²áð¨Bmð=ÞÆ’ð˜:”Ÿ%¦£‚¢4 *~;z hOöÊ)ãMV¦l1]Û´±Ê2ʘðRVæ\ª¦Š¯*ãސªàšYr„ÙË3ò±+´Zj–a¤D‰Ð±“yk8¿l2Ø«O™ +à™<†ZK±æðÈËßWÍË¢PÚ"ad]Ô>ÞZk2¨ àå© º4àÂw‘ðtq䚼êx( Χ9ǰ­± ÁES÷Owv—J­ËÂø}d±?½ #:V;ê{a6Lžf“é1ƒ¶[5 5o®úAž0}ÒëJÙ3Í®. +*)x5ô¨¯6(Q”Fd^ê`Y#™uÖÅàKÀ[¶h"ST¡›}9ïΝáÃíÝöýž€ÐϺñ‰“Ïh’¢Ì†ñ¡pMæ~¼$"M¹æhHŸß/D0^±›p†ƒQv£^,Š›]ããl·ß¿ùb³Sé?Ûéµ§kZÕÔsª™»ÒèyTv>:!šÇVéÃö¾»#$Ê]/NŠ¢9 ð\O…6e8é%wת†]¸ ¹†YqÈf ÉòuUæß+.ßûxn÷"¯õÓól2>-äÃKÃa¾Ý¢¢»›`u¹S£¡KÓa„(õçiÚ$ >µM‰7‘í¾åWµC%p +ê®4XÍfŽÃïHh9ŽEìG +¯¡?XŽ‘`ÛïjWÛ®Czh@„ôE™ÿ{ñ?õ +endstream +endobj +800 0 obj +1329 +endobj +801 0 obj<>>>/Annots 215 0 R>>endobj +802 0 obj<>stream +xÚÝX]oâ8}ﯸ­TB섕úÐvè «)e ÝÕJ•Vib Û$ÎØNþý^Û Z +,Ziµiäܯs¯oú㄀‹ÿ´)xDÙÉõø¤yÛ҆ñŸãøô7&’É"ɧ f †"ÉpÃóœE*áùÙø/4ókÖ m'ІcŠI…f¡2¶ý!„q,˜”0 %<3–ƒ,£˜”iº€PÊdš³Â<~3+ª‰Ä¼`‘‘ PÅaÁK¡³ÀØÄs¨ŽýýjpjQ° ›®ÎëlPßñ5¤Ð%%E£N©7÷֋i¼)¦?1¹D˲u:s.^´—eZ˜ ̓4ÉHž15ÓÏÓäeW"Ù¢.s%ׂu]®ÓÑØaðuûtJºÔqêЧ³ h‡*„ç_3RY¾ý&‚g°4»€$ʊ?%ûqé‚Ré%iJ2vقìpdͅ÷O\Ðã]xºØÖ֜«sx5"¯9.ìGl¨xµ\“žÆ­%Êè“Ï™À'§FjrC£SÎãóJêk‡I¦0(]8ðê* +s(eꃢåeäX"³[1Öþr¦´4AªP•xБMI:§PW3I¦¥¦±\sd‹pʰ#f¯IÄKáÛthxÔÊ÷†gBU̾æmF FLé r뀸Ï¥Ì,|e¦ä "UÙ¡™Ÿ6¦”õ„ªŽ wšÅz§ç›´ˆßA¸X­°'yôÂԆ<‡økKƘĄ§)ŸÛ¶#Ëi‚¤ò ²m¸ªû“Ô\ٶյْäRr…È•<4;rÆË4ÆêÎ5ƒ›Çᨚ4­*5Bt£´cÛuÇc–6ï¼ÄÀªÌJ ÅññÓmx|è?Ê§3ý¬7>qïŠå_Áï8-ð¼ŽãÅ~b°.f%°ë€i;@œE“€b÷ßÐæÒ©il¹Ú+méL®Š"Å"¿‹DUyšX&SìÚE³ik ê6TÊÙhNsx5¿=<î(‡tpÄì]ŽAPŽ-ÂmÙquõS_MŽº¾ O*Æ„v ºÊ í:ÝêKº¿F¯pӃ%üú1­ýS{î°³8?âD؛¬jóFhU1±&û})¿è×ÝìáÈÑèç-§míÙ귐žO[nѶåoèºå4pm–UË«†¯HgÑޒý>oV 9=ÂüæþŽì`ÎLñ½™3è­Ìß*ó&”Š¥©¹8‹Õ¼::­Ž‡#ÌwÌtß­§L|ß!Шž2 +±ÉóaÖô(kïs–I‡.'ìn–-zË$èš ?ìà76‹ü#õ¿M› Tö¦Í ·ÒF={sönûOWìۄ‰…ùôÐÅ`ՁOê íåxÚ}#Yô¶‰¸¾eº7ÝLþweª|yQ<â)ôp׸š¬¬p×<ñF‰{ÌàíuYºûí sä{?®_¸{8C2°ßQèÿW·è7àm +÷ºVàߨ<ÅU†¸Êbßᦾ˜%au9L ÿÎF°” ý¶Â5ªÏõŽ{É1?Y·@}Ï^x{@+¶]Dd•ù’ÖÊí,ï+}VÛÔiÖvñ‰š‡èø*Βßð¥Œãk€ÞÕÃT×ݰVÊlŸ¿Ìøm 1ðvÍݯ'٘¯Iendstream +endobj +803 0 obj +1275 +endobj +804 0 obj<>>>/Annots 217 0 R>>endobj +805 0 obj<>stream +xÚ­X[oâ8~ï¯8R_¨Á ¹@VêtèÌì´%éª+!­\b KgSÚ¿ÇvÂ% +ì´E´œ|>þ¾s³ÛŸg&ü6¡ãÊ×$9ûœµol0M¦`y]p»a£à“—íöEð/"ÜÑ a˜³¢ÐÖj]ã²gKÚúÁ1î±~~A·®AÀõºFWÚÀìä F¿Àڝ®á‰Ýö›ì¬ŒÊ"-®ƒ”ô•­b&øt² y2ñ9ÊÙDÀªýÍ÷%}Ëòp‘è(ˎUßF¬4h™¤{úêvÆsa~€ë|tö&ÒV¶d^t¤ì÷³£Ð¦kîzâI–ßRÁâ±å¸pτ¤ÐÉ$Cx¼m‚?´MBj鉳ðha·~`þã_FÁ×áC-@'ú±>ÂÏõàn—Ïþ`;žmØe°mcøn°5Z{ƒ®‚í¸&>E®·ì%¡ù¢¢Õ•¬:=ÃÛP½Üí26-h•àb’$Àôdcœ¬8 Ùq0¤Zòáî×h-yƒ^K¶-žÛ(]¯ôŜå7´²ÚÞð0K×z­ÕEÿ xÄè•â"z  JùsÿôÆ>«ü÷$³q£` B5ˆ"žã UY»rqM²ÜNÏ61I­`Oö`ý¶‡9yÒÃ,]ì +½¯Øíž‹&dù‡tQeûC%k÷ȺK—¬Fï+YÛót—þ¸©‘xóUZ¶Üº]»[o_»Ú.>¬:öCuzæ ­©Ñ{uâi Ê(` ‘ó4zQjý9-X>šÓœí6I»lŸbl:o­øô«Ëº´k}â![¡÷ÊìJ°íàx½ÿvýå醁y@BÇš8Z‚B¦î®ˆÇßpÔYhãàq× Ð{5¢ÇÃFø‘ðB—'D9…·äœXTŽC\£:=û„™¡Ñ¿PÓ¾ééÉMäÚº¥®y:fËÞáAzÀ…À§Êº­£¶5:B V‘˜Ãõƒ?2J€åêñÛ§“ù޹£ QZ]oNÕnÓ(fRILǖVu qµâÐÙòG²î¦2±âù2š£3!cÃó§W¥M“2 à2ÎÑTZ1uŠË+_ê M£¼±_¥1§!DhÉyò&6eBѬ©’Mm¬ã%²qÃÔm±­S8C¶—ÚnBO]&]Œ£­ãˆ !ÊZeŸ@ÿ>è«]zÕ&D¬Û¯A:Á›EUj*˜e]§÷þÎÏÏá&ðu‰£]äð×¹î÷ðù3üÝ¿bÇÐðµî +Ùý;ÜòrÎÅû\;$T&ø¢‰éCâ- +LbXÛÇ/͗µÍ$|{KÛM »­ϸ¡òŠ/ì`“9ga•†’UKÃ7ñéM-æ³rŠÒêgL”Uý¾ì˜Oh|YAs–pÁªõ4á“G>Mš†Øâ“ ¦sºŒëi0ƒŒ¥² +C*Tƒ¥úB ²SËí°{V“4­¦5¾hÖ|Èù³„“(_¼­q9M‹©êä$‹±Áê sùO¯‚(m¢g=PµT0dHBþ+\»º°¿ݟËè@9Y– _8Ÿ^5«MµT7©}Ï^DNGÕª×ÕÆÏaJŸy ˆS(ŒœŒ»Ì™Ðs2ŽRÔöÄfQª‚-W—½Û]_=ly×ÓïÉÑ#>+¼‘ÁU˜D)N+|§ÓM—4–Ë[zU˳TÑzêÿ›]ŇO$<)œýcÙÇíendstream +endobj +806 0 obj +1462 +endobj +807 0 obj<>>>>>endobj +808 0 obj<>stream +xڝVmoâ8þߘS¿´Ð$¤@ûá¤.¥{»· 9Ȟn¥J+71à#±³¶S¶ÿþÆvh!…P­*ê™g^?3òϖþø0 ×‡$o}ˆ[—÷\C¼0'ý!~KÏgñäÇ4Š»`>7ð}<¿ˆÿmyÐñ½îÐ9Œ¿üˆf~×9x‡ÍA³¹×l›ÍWÍæ~³yÐlîš/ïCð}ÃP)ê}ã8Z¾¤ WœWùlÉÛGžCÆ8º ”¤7[Ȗ÷NvÃÌ;?ßùO¦GˉWLAÊy̨²UÍ蕊64ÇPH¡E"2 <Ê_ý”Æ"Ó7Ž‚[{!× ¨ÄpÝ-[½n`²Nè/Ý¢[r P©—ù#•°(IVPI²ŒºÄ†‘Ì9Vñ]d ‚,ÕDΞêöɹö=oy\o€þ `ï08 {'€Wǀá `ÿðêpp Ø?šÕJ•¢\£²gÈɺ’ãí/4íj2!Ö8=kŠ +ûƒn2ª5D$YÍ~¦úŽIšhÿ³¯T˜“';ž5É.XF­ÑÄ¡,2AìwàtSµ@¶3›¾`Ëú Û¥b|yhúº¨‘ç˜ñf ]]#XÑ!i*‘Oâñìé#Á9öKS³K^AÝÚ ÏQ9‰æpvv÷q‘!;bÿ>ë¢áëtww¸ãogv7=×Cau¿×.·D’A +¡›kíõ|øf\9É)ˆuIÆÂ \!ÓZž¨:®+É¸ïæ Ü¹7b6D>œk#(üåXMV‚¦{Uuœû+?=ϕ–‰åkbüt×E©ÁIFÓÉý§ÍÝg"!ÙÍ!i.4½©õÛò<ˆ¦³x+Pe’à­.ʬ~þ•ӂr#¿”hbâA0\§fçVéÎýë íµƒvðpÑÆs‘¢îUÂØÃÅ[±àTJÂՂšy3FëNgæÏ'޲'KX)ŠyS…yœÛŸÖïR¹[h¦uI5¬p˜QÆT¿‹ÒWï-«/'ÿŸØ0ð÷'ÆÄ´ I&ìÀ¿’ýŽ)ùY²ý˜ó£éã³£ûà²ü.Jy`-ZµoÜÈڛǡü͹PeênŌ¬,JišøÂøZ=+·ªe öÓ#2t«]M_»(H‡GZ)®”(·ogQfö/–õa:£.†À.²”èEá‚×ö4î5fxÆ×‚Ò´€¼TÚd+¨Äfs·ÿ^RÛM¢ËO‘}\˜i‹7ï—-O°az£oѼ¢}Xõí‡Lßës±Ð‚InӜq¦´$Z`ÿ_ /Ift®3¼w“BõØ×À8nýÕú„”7`endstream +endobj +809 0 obj +1034 +endobj +810 0 obj<>>>>>endobj +811 0 obj<>stream +xÚÝVßoÚ0~篸ª/TiZ&uˆV¨-0H5Mª4™Ä¯‰Ú,ÿýÎNҒt­ú8?Îwçïî>ø©å‹Ozó +’Ö7¿uzÕÏ?•Áùü°=!ÁRɸEåŽJׄqÄ|Ø&“D3Á!b1N‰ÿ“‘2Y{<Ÿ]M¯ cµCô–èÃl1SDœê½‰É4•ÊDºÐñzN×`Ên±Î1-A9à HDÈ"ceªÀ’‹ ’ “FLâ{(ö<$†)_+-SŒoŒ¹€ê>7ãyëH§mïá¤YK*Åю +»ƌ}ítûN¿ „–vHJªLfþdYmtQíã:çÆ},8§Æ:µ8rªN”nÝ® [Áª¨`II˜7½–4[•+M±ê<¥€-²qMW„ùjE´7TC1À÷!Ç" ñ¨r•vÏêg¶ëÂX$ á!Ìoš¼3æ)åp¹O§p'B +e?fMï—ËÙtv}„„…5‘iÄiDi¨C@Ù{Ȫ\Hڈ¿2LIH\hؒ- W•#Žóם€_:¢W’ÆÈÔ¦Ó±y S5­ƒ9vЬ(rQ>”n7ÖïTäz&OrøÝit»\ ®óÕ Y;––ã4£ô !&3gÁš=Ó[sr$Dd'$Câht³^B‚™™´1o‹f+XÓ ãܜ=ªa:<®‡ƒ¿õ~-–ó{´ð…ºÒù¶ûör—{µå–5Þ¾)ð¥BjàY²Æ)EŸZ9Ca‰cÛbðè3Ž(b/šeDıثVTR…ðõpê…6¢ºoGÖ߈ê½Ù ßèaBRU¿cRg¦`sü±J;oé6W,(áÀÊ„Š¦OøƒC–Z5 œî?&ó6ƒUֆŒ›,u¡5To†…N|FeM³ÿZY?…Äý4JvËø#Ψþgƒâb q®VðZqTä9/óxý!Rõl8pl.ß/V°‘Þ›?šË0aï,xýRÁáx®L‚N×"‡0lØ7ƞå«[RÐ^›Œ`Vйfï;¿õ½õLÃ+endstream +endobj +812 0 obj +840 +endobj +813 0 obj<>>>/Annots 224 0 R>>endobj +814 0 obj<>stream +xÚµ–Ks›0€ïþ{tfb" Ì£ÇØi›N´¦7_¨!11¯‚œÇ¿ï.©LÇÓñ#óiÑ~BZ~O80üpp˜6l²Éu0¹zï`܁əá‚í¸DÓÌÀ¯’\Æ,«ä1®ê‹ài 8'z¦ð™i CP`›Ô–eœGÉ3¤I-kÛJ%RQð¿PBXхâ1‰âž¹…ÅOe¨[xÀºÃè°(øàPŽa7ÃÆ(ä›tÅêöwEšOI~ÿ÷@ÞQ›` †VèÀéðãº1ËÅ[gà˜Y5RX¡{@œ ƒâ}yÁ s˜ïÈÏ_ó×ã¯îin…å)q7þêÛWðfe’òð%”UòL©wý˜î7½%6Ôb§qY¹g”e¤.lÚÉwpêÅ_ ہ&Í9>!­É¦1dRӜ9'ð>A&mÓ ß#Èäkþ¨Éî#§˜èœ +ë©Â:תxl­6!«šæÌ¤¬ð>AV]Ãëñ#, ³s´’/龆E‘ÕX=µÜ~®æ"ÝêiCz4­“ÀûéñŒy¡‡y†{ Èß²/¨$üLAܛcâÌvRã÷€ \Zr}:_îÙjgþèÃ2®wŸb96OÜÁw±<7OW4;§J£i å©i—æµ£GäéšjÃÅ>>>>>endobj +817 0 obj<>stream +xÚŕOoÚ@Åï|Š9)¯ †S'i“Öî¡—­w-6Ø^wwšoßY›…`‘Z,`Þ<¿ùíÿìððE í;-z’ÞðþÈ’ +á”@œ»xþå3ÌÍk^kˆd.U?yFái…â†Vš,9œÊ)ñÂ,œ¶‘nmR[w«Šýié,ú ëª’Êè· +%JÕ³¤DQå¼à¥Á¯Üa"¸~~ cRY´d ¹qáÁ |Œk Sï +§Ç‹-O|n㐵©j4.áGNÓUSk¢â ÑÓ÷O‹¾ÛÞþ;:Á/¥‘—ãjä¸*[®ÖðãJ‹.`³n¹^}ä¦Ô^v&\=cän@F` Ž9ÁÚS[*ކJè½k‰ì˜aKŽyI´Y<ˆã›Ãth‰‡]á‘øx6Ÿmϋpzªx‹d¼§»£”Gä-,΀Õp…¨½f0šadL¦µDes³MdJ0ãk”ˆQN{kVV£ã/®¶ûÅ`-Ìr3âŽÄ5òÔ\ ½ƒ"4Ð\KÀèY3d«E!rª@qªe©;×ï{·Õ]¼Ü +.Ú¼Õ?]=Y毇'¤›Ûìð‹ ¥ÚÐ<ç'çt&0kÙïsÛÌ ' 6J€©Ú;: ³Ët4Þ_¬Öð~ºANFtycëÑ·xs™™µsà +Q +m5Gy¢eMsÛ>h»ö/ Û&¡ý1˜†®}Hž}Þ%½¯½ß@¼9óendstream +endobj +818 0 obj +588 +endobj +819 0 obj<>>>>>endobj +820 0 obj<>stream +xڕ–Ko›@…÷þWY% à ooÛ$m¥ªrkZu‘ †x"^epÛô×÷¶…Á€,!Ûsïι~­(üPð-°=`Ùê]¸27`°íÀðÀóãÛ{XÃg!k(x)—wá+j Ti×Z¼¶˰”>Ü QYò<!ŝê=‡Dí…(!guQ ®V¢¢ŠƒÈe¥)!)ªfÃû"ˊ¾ùô¶•Èk‘¿ÀîMÖ<3´·õ@‰c8°¶¼¢ƒmTïó(ãJD7ÿ$ —¬e-Š\­<„+b,Ãñòí8áƒM(¢Pwc`‰6øííÄñjË&X…“º©gW#— Î +] “×Ìd‡RšŒWµ4›îF› <-X¤\ªŠG,¢·ÿ¨"Q¿º‚bµÔ ¬©­ï¯¶§ð1 ·ÀR›¥q×ò#hym Ëu•W«5ïI¼šÒu G™FRri°"O.XKu°¼‚VJ$^•ÆUˆ]z”’íy|Hy5g{èq6\£…³l°38¼ÄÃhG‡PS¦©¿ Z=@m›£—»¦äIÄøDøt³Á8nÝBC±kOr*l4p„M«Ç΃ú´¶Ld\ÇoyIÖ1œ3yUq›.‘*׈ÈÒCŒã珨÷ð°Ûö𚠄s¨˜âs­yÓêQ>{ÓÏ[ÃW¿•|œ‡kñ’‹¼%lÔM!Ìæ°íÔê±R‹ô#X–ñõìm YiËØF½~v8O·7ÛíýÍÓÝi(ÂÜ<²$z켿ǣ‰ëÃotèÁÜ1PUù™§ÕˆÇËSsq•ù,r“E9ãé…ùãpÐëðZՎcgIC8×úÁîÚ¡sÌóë†õúB¿–£œÎ}†(ñàKLоĐö-jèuÐñ՘nÖ}¿uõuõÞᰙendstream +endobj +821 0 obj +752 +endobj +822 0 obj<>>>>>endobj +823 0 obj<>stream +xÚµ˜]s£6†ïý+t™t–ñÍe²i¶žI;éÚéì…g: +È6Y@Avóï{„lLD§d<‰üÏ G¯Žx^`dÃFn ~“bq½^X·Â­·È·Í‘Öé…ÕòÚzÌJ+¯.×O ìÇp Œ¯÷­^yC ôªê¬lPŠ‚”©)t¿®¶iÃEN_¿ /ç #3BpbÓA5œè±c‡'µãÚfÐS­d |øvHɪ&c%À®hÃQËim¤t›•4•ÄY¹C9p_’6oø”`ôtj¥/€ñ¡ƒŠpþ#¸JSþ %{Rî(üÁj8KÁ^(G7Œ4¨;†ÕÝQ62° ‚ãH’°¶œv䄠—Ž\Çô&ujéèM}r„=y힣çQé\Óú;Íé+â iZ®[;v$î¹îïÔª;ïÇçõ]«)ç¸Í)p©VB†ã¯ 5gBʄæè‰=n.øæR—8˜SÐR­$öÇ-ž±:êj‚pXÓ'h­F€rxb0§ >êb¼~#S²,ò·ø|¯EÈړ¬ß ÿNJTAHûþɕ&š±[s¢÷7kÖmtxí‰=ñ^+tº[,³lŶÍàFWoAk¤-ɝ!2‡…‘ô°m»8d ;8P¬J·bí9Xúsñ?cÅendstream +endobj +824 0 obj +1199 +endobj +825 0 obj<>>>>>endobj +826 0 obj<>stream +xڕV]oÚ0}çW\í©•J¾?àq+c­Ôn¬¤Rxq™’8Vۯߵ(¤„¤BŠ >W>çÞãc^F6Xø±!tÀ ÎGߢ‘9÷À¶!Zƒo!¢ä¬yeò-©¨™“¼ŒþŒlŠÅ¸vO +(ɆrX]\³¼$/UuàÁãÏÛ§+¸YŒŸ®d…cÛ5Y³d©R¾º”ï¿G#˰Êþñð¼‰Ü=ðp'Ã×1<¨(,O€+Ü£×Âç;5i%¾ƒïwZΪ YLliÕOÐ pMО¢¶óZ|Gï º.®7;®Kn&Dc²Ñ–BÆb"RV[Ã:Í­@åwʍÚNˆ»¦­Ð´mOÏô$mA¹(«´FÉ?HX0.–q•–$Nõ_ñï£oM$ñ¡ôº‹¾?õO‘_³BðóM?`¯Ðø¬@Éj¹þávÑ£Ì?cxî2¼þ@[Κ Ö¶ÓCsÍ(W/ђµºø²X̾¬.µ÷€ ¨š5‰)è*Ž!ròži«¾æ4Á€SQ—@ lv|©iÝgÅï¬àÉnœo˜B놽£÷ ³ÃSí*¹`áÈè¸g¿dBv +NjºS‘’,ý§[9ä0ú¶eL»Y£»ÜìMC\=/bŽfÍIùaþÒÄ8 ²L‹"ŽI³â•VÒÛø» 9NW°ÖødZê K/œìòßÜÝen³þdX +š—Á89oð›èþvØÆ·»óûFŸ[÷n‡ o —¨Ð]·%0a±y$mÆâ:§…ÐÚäáC:Kõ… eµ$ñxK“:£UŸ",žHݩȲšDz%•™±Í 5íAíyâÛÍ óäN½OÜÉÝužÜ‰ÝØL2æ%cÙÎ*ÀS½ >>>>>endobj +829 0 obj<>stream +xÚ-‹Ë‚0÷÷+ÎRÅ^$K_¬4ÑP? šÔm¿/UsÎj&ó$†œÇXoÒï#í­š +ÌP\”YŽ2—PÝûÛ¥EëL|kßcۍv²!z8ë饇¥zøUâŸU2Á‚eVã 8Í!œAc‡>$Tt¥ ¯%Iendstream +endobj +830 0 obj +128 +endobj +831 0 obj<>>>/Annots 232 0 R>>endobj +832 0 obj<>stream +xÚ¥VKsÛ6¾ëWlr©2±(¾DJ>%MäLî¨=îÁ˜\IHI€@³ê¯Ï$õp,Ï´ä!±o±ß·ëï£|ú†%W£_³Ñôf¡Ù?öBHÒ9dÅx ȔlKÔ;) [ø$«J +X)Io+ý.ûFÞ1õžtî“(éEÈv\«kÿrù„Jƒ–‚Ü€Ù!½ráê>l¸Òfb8Y4Ú£Èe# *hw(€ mXYZ$L6»OY£.[.ņoåpÞ­Ö^&^lÏ-vT9g%覮¥2°‘Ê™‚ÅùÄxÉl”¬`ÉôÖrcZ¦Ð\4¹ÑܐK%éä]1Ãm%2?ã1,7T 0sm—ÙÈ÷|j€ý ìÏ×/Fžálæ%PAÌɹ{*am»Cm +g =SÈûûûkpiÎè-Loü¾ ã1õõtÚ¶­G°öºõèžÏ½üƒW>4/õæÄ Jò&)\„›,¼BêpLpƒdæ-ú§î‘xuw¿¼¥Ë½}Ü·ãÃÿB{LlÏ]ȰÄz'ÂÃøvrs‹É –ëìáÝ5¼¼È§/µ`‘øQåÕ RwÎÓî¼Û=|¬ë’çŽ>Kñ‹5¢cùdzVDN"ó3ÝXަ]ƒo™Ø[ÅC)d…‹Òù°¡ÉS4ù´¶ñrVŸÇ“Ž(™‘°E J®Uܑáuã¹D2ÊSà†5¥ét1hª£y!QƒrBeð¿Áb‘V69 yïA&IäÔáà"÷‚¹½ï \tZ‰fԃî©'™F~w“¢Mƒšº`n~¹¹ÃµCregÌ¡†Wµ:)èEda9"‹œ¦Ï‘½@æábúBäPp…¹áO¶:Wü š6—%yšŽ’Ïã³ä/؟XTSóÓWíO-È~¶ð‚KÅ w×ßÇPÒ§«íO®à­»Kۋõ^¬.Vå[ŒAâæLИ鎝Ò^|L°-V(ÌÛ—ÇÆØ;¯®#ùg¢µÕëWÌåVðHÏw´³«JÁŠiÝJU¼¹¨[§åe Lÿ{Ù¸ÕÂàî÷ßþt«Ì…²T¬ûXÝB³–5*»IQ+*.H²½è EÔÏV‹ÂJ,÷Üg”¨ÅGxT²¥T¤©Ÿ+Xá÷†Ø¥‰ö̸ì§8a¼¢…ÿ\¾guÏOûNQäZÒ²§îê¤1Dʦb­äû¡aa 6}_æÇûŒ‚ñŸGœÆÃˆž=þýÝx®endstream +endobj +833 0 obj +955 +endobj +834 0 obj<>>>/Annots 245 0 R>>endobj +835 0 obj<>stream +xÚµWÛr£F}×Wôú%N•!ûæËnj6ëÄJåy#k²Àhg†Õ*_Ÿî@€.v’rم ÓÓӗsÍ·I>þ0é7+'w‹É‡ÅÄ÷|Þ]Ô3D‰7‡ <4LR¼&‘‡ V»Es/yi/èêæcA‹ž'sXä—÷<>A.¹†J`E!·°“5 ¬6k^‘1ÁUÀòRTBԐó­æÚÀV˜µ]Î2YW̚X3r¦õVªVRý¼økâÃu0Åhñ`ͳZ ³C?LËJ{ðieOÎ¥ e;ã©{x"®* 77ý&K%¥qÚÔ.{‘p» ¶²úÉÀý- nSËsØ(Q®ô(.ÅKix±©à»`ä¶| ÖxÅ2þ®ÙÆ^Dr¡­ç.Ø^é„ *Îs:šçÂFÖ$ÂÚ¨o¸Én²z£í%÷2Y­Æ‰­DAÈ!“e‰þAÖÖ×(…BTØO¬k.ªç÷mÁRòP»#ø-¹Øm8Ü1-²Ö®]¼/0xÚiÃËa(×ÖOL†ØÙ£éX´ÐÃ}$tùý˜ú‰7…Ù,ÁÓJ˜F3üëî +x"ðîϊ#»–º¸ ®¨,¨½ +!Ȕ«¨Å²æê;W€øË¹Î”XbÙE§#靍‘ÌâA$Gì{hŸ¦Þì¼}Ï¢„hxé0ÓѤi[œ&åû5Û ö ¹‚‹G-vµ×•£Yá Ì0³όí‘ö¦=oc϶ï3«Ø3'0]XhÆ¥ç:;kÚ1‹Ps®§¡ÃЯ_ޱѣƃå…Û1#[óì«FÑ(ŠFmXµ³M- ÆÞE²5«ž¹£{ÃR‡zÂãëDñ\;Mº‚%Â1x,W+%Kô"( +J–­‘$. mèJš³3ÉFÈsï Î~Sç“ +܀8…`îŠVo?Á=#1zp; pÁ4Ɔyۄùمùî°Às×=¤Â|ÅêÂ8ôÊ…(…ÑãJ`…‰-®æM%Mä UoH?¹ÖWT ©Ý+Ïk4ëˆ\Á+ê‹Ê±9¯vW¶#‰zÀ…¦­E1–/ -»`±°]^ð&6õ©­„¹»ã6õ#Wµ7’°.+PûHNIXgoê¬}Ï¢•°A¦§$¬Kù¿JX˜Òµ‘0wÓIX˜o.`FëˆBŽ!ø`-5òLhXP{0?¤Ö~Âú«:Ü¢þdÎ6¶0HlÒiˆ%t7ÇûÒ3@˜û1ìŒy€-ëÙG/Ú÷,Ð> ¼à¼}Ï¢„0šü…I“oÚÇH|ˆx¹É4abõa6¶IrE”¢’ RV¢-ۍ_ ¨†ÔÚRüÍɼ|Aë âZ ^£W«ýçü‰杒[dþ9±G€m”ÄI³$¬ÕºFìí cøâÌa¹³8v²æŽ§wšÞðL¬vTL˜L*Å33˜Ìí ÒíälkpÐ' +z <+=x»/Zü·>û¢UwO‰+9 ҟiäVÄו֜>è­À«fPp/¢SKœ*D±€Nzª€É'Á>@ŠÑPWý£I}±Š~º,»ºØ:ⶖ÷ª¨psí6‘·¯ŠãîcÂâ@?ÀC +4Ù¨/¼œVzbdÛQrb/ìÿÇé¸_§w`„Q1B‚uk=óÛcNXï Ðz!íÏYï P‚¥üŒuÏ­gôæé¬]‡ãyóþÿ7#ÔIÝ@•¶{9S…À ¶Á¤äœ†rñ£ãBKªpO‡iê˜iyƍU¬á'ë³Y¶íÄ9üÆvðàCºý4©Öøë˜€~ðEÝFÞnšz͈“4â„#3—™‹íI®Ì–¡¬õŠ+•& F½q>íÀ{=­>$!=$÷ÿׄ‹ˆÿmò,ý©Çendstream +endobj +836 0 obj +1438 +endobj +837 0 obj<>>>>>endobj +838 0 obj<>stream +xڍV]sÛ6|ׯ¸ñK‰Ñ—-%í¤‰2i¦î¸ŽÒ>4é"Њúë»P2-'m'ãX&pw»{{GÝöF4Ä¿ÍÆ4¹¤¼îý¸ì=}=¥Ñˆ–¥<ºœÏhYœ«&l؝« Íš/ÿ+C*ÏmcY; +­š€?ùxaoRŽÛHíÉØ@Šj®W´¥\~²üÔÒ`4ÉÆRÓï}àšÖÎ6ÛLÎ@u8œf$ðd0¾Ì¦ò(·¦ÔëÆI—ï¯ßQ°(ÇôJ¯Ù£X‡‚5 !P9ÚñŠVÎî<€–4ßl·Ö…6øÙÃT°]$lO_?£ÑLtŒ/h0½È.åô¥5†s ¤.° +ö^¡NŠ:¨‚ãYŠyo +€3ÖÕª¢\»¼©}P&gß§³ü>¡K Ï kÊH¥uÙpØY÷¥¶' —ßئ*hÅÄ_¶ˆæâ„célMA×,2Ê,dlSQLS*@ kª=©ª²;”’þVLPˆG™ZpÚ`ö´ÖwlRòç֜6þ“]śñƇ')h§«ª¥'ž=ɋ¢­õ’Y<í6ÕÅy¥v€ÛÁÓ)|º±ÇãžÚZIO+°qœ5IÔIa!9ñ»=M†äG…ÏÚLþÍ ¥íª‚·ì¼öÁGÇ10jUEicC¢* I¥à¨oŸPK—{™,¹”¸Ö*ßhÃíð¨"ñ´‹}§Ãæan ªºc0ª¢€âÀEç…¶‰­Ol{åT•·}ªÅ=üç&N´1r èt÷²']v;б/¨‡Æ<±e)èðŸtÉNPý֑0®¤²üf2EÑÑӇT÷sŒ¤“qâô»ÓiájÿçøÂ"ñšíb K`gL¥ðÏmà w[u?l˜—Æ7Ñ¢ŠÞð®âèZ埕+è-‡WځۉÇhÌÒFù8VàڄHÖ±ç$Ìa´;¦‰[ mIœ`ç^§¿ËMKH„ËU\i«Vp„¸Ðl©àJí±Žeô‹ ' :Îmù€°ø­²A>&—æy ¹pùkÆ£B•ª‡Ç‚~Ԃ›…ºÚ§ï­uR\2–H䱤õeåªXÉh~ÜwBµ6M`ŸÑҞÀëäï¤þ—ޗìSØoùy²Öˆžµ¯åÁxš(®Ð6Òہ* +'kqñËrq“îÓ}Q`”œ¸tûøþ=^ϲ㸠³yçý$KÀv/ž\[ø\mY¤sتiŠþúóãwGÍۊעGôÇ Ë }$ø,*×—INÐãZ¢sx•G»~ ±ß,~¾N)Ï~8;9ÿžˆu.´²?]ûªBß +¿mtèFÌÛñFhîÅdžh¦oïlv²ß_p¶>Xì·+e0´é{Ât†¸Ál<ü_¦³)Pśó‰>>>>>endobj +841 0 obj<>stream +xÚ-‹A ÷œâ-uQ-…ØnµÑ]µxÒ~ ÆB¯oQóÞj2óbå2±Ë&vPl{jÀ9”—õ¦B]•Pã +ííÜ£÷&½u ìÇÉ:SÐɇˆN»Y?×êÁŠ_Uü³Ff(„\Ø´Þ9’õW2s¤Ũï³yTìÂ>ßà*Lendstream +endobj +842 0 obj +134 +endobj +843 0 obj<>>>/Annots 289 0 R>>endobj +844 0 obj<>stream +xÚ͜ÝsÜ6ÀßýWèñúH‘”ô˜ËÍÝ\ÚÔöÍM嵜¨ÝwwLþûP"Ö6)w.ö¦3‰’¿,Alÿ.¯h>ÈK× Aã~æ yé…> yåDU¶pà`‹Õð©‰J• –޺ðÝ$¶Ö4DUiUL£þÀ“ð$Do¬=Yé´¤lë` ë¢mÀ¾Pc’”mq}°„7WW»þëЍksåžœ9Ê-µ©¼1vXjDKm¼ +9|éwï‡h*š½¨%ˆû=꼿éwýfÙ{wZ«’~ËZG¦ÔO?zrRÖÖd"TÂ֌W[,¦Q/S^=N‰f®aS‚9îfΧÝgpóùq\D€oA1Ç݌ËyŸh>,є¸%b÷×Xӗß6sbLå-Ÿµ`ø¨ñ§¶Æ¼üÒ'¤>A@êe¹›Iy%F4Í +·@Ìãþ‘·…¸mí#)ŒÅNá$æ„_•Þ2“`|#2W°`=SäÌQe  î¨~ùe³]m?÷ÞKÁŽ=% ï2â+P’¸7"q)ûýk{危jO?˜Î-·¬|¼ëÚ±-·4ì¾[uû=9 ê”WœY¬iKo^žijL‹5­"ÛúaXú_,µö¤œ[0–>~m@Ôˆ\7dÔÞvË?úÍõž¯2úTWœ[,¨ ”kÀwR#Z¬³d¼GHÆfÓt4vêÆýŒ{¿¾òf©Ê³tð«Îˆ ¬3»¦}NHdÖ¯ðçþðm»ûœ¨7çú4M^ŒC6cJ??‡mÉèt`>\4êµóâЀqxëîfÎÛ»au a",±_,pÜ͸nsXÞ4¯ô÷ÄÅýŒúçfèV«äg‹!€´õ¨°X-¤öî?Ÿ.¼å}Ñ£ÔfŽRÞ¬‚8*n<ϸؙ¹‚ŠXÆdŠs7»gšŠ*Ds.AÔÏ ‹íÝnÙ§Ô7pÇc,paóÞûÃn¸ºÃ þ‹š‹Ç5XkÐ`Õ6dß« +Bj…\Œ†vKÖý¼ÿónØõ될uåixÇÜêK™PNíhu ´íúvÈÞi>^J1Ü´0àèè¾l6T•éԊS¼×ã[‘t`L3ÛºEJìY ˜yHݲâéxÖ0I*a<€aۛ÷nGiýæe6fVÖ¶!ï01L­HÖ¶%«~·Ùd=Í'ÏÔHZÀÀ´ £ésüH`˜tûB@eRՕ±“O¢ÆÊUÆ=э8tÇÝnž' +¥1:– êgÐÛaÓí¾§”6ðtàMUàÂ÷¨'z «”PJ“#"Cá[Ñ÷¤ŸhŒPW(Þ0³K {šŒ'óaÅõi»;øÍljc]h…ilIäL¼§>õ<Ù¶¬¾TËI{/KÕJתË'j+à4¾  b·I)kš‹!¶½G¢D:ÿô1Š&ƒ–J´‰Eõ€ŽÔ3±¬šJûøÒJ_º'ûø$YÆÀ0€™3TXΌUª*°Þ÷WC’ðTÕÌ +ž‹iÇú*áïŸãLéäå\×ô.Š! ýüÀå\7ü8Z¥/çæïЂæ{%w9kŽ?uN6›p7b¢\à¨?à>v›î³¿nøÛ†:ì£ªÒá‡vnze ÆCWbíê¹ï èË‘»™ô¶ÛËý)\<þ²ì,=ûXŸS覭ßo®Ó9 hîºhÑw{ÔopçO¼‡Ms)j+%‰û eÊwûC:d›V§ì= (>H^˜`}Éû£Iû wo¾Ë…ê[“oѦ$k›ÓX<=$"Œ^Zmñ|”µ?èxyô-§º¸U"qÖM°¬Œè§0—8€7»mâ©<ž4ݯ•Zò2O_ƒ¯Ä` ÓêÝv½î6ׯþ=lüu°þÿ<Ù-§¹.€¶„vâ­5WÌÜrF;"†…̛µåvŒ ñ€:¼«ÍÙrGBàpËé¸:cƖcïã œµåöLL êù‡x:ÀL{¬S¿åê¿ý•kþV1±ýÈA)*hðjDJ™(xIg¦ùä[*Iã~#b«}ÚÁTÐ`ɦ†LLë8žÁ9–àH`Z:ÇMû’? ã&Ôü–þ˜¨lÆæ”¡ÞÃۄ²™ ]rµÇL›`Ó30/ù>OǃB ã û¸½n¾§?_A;QÞû|<@‰÷c®…x® oNYª©ÇZBÇ­IY`êè6¹ê3Ò¬#Ì`@-`a@ó€(^¶*+¡ºâ¨ oԊ$Ts¥ËEȈ(šûYô0ÀÌIùGÓéuô装&änº»U҉Öñ§kðhI 0"róawûÜ̪̕õ`"žZ‘Ê×ë\º]Ng ¼k \ f¼‘ÇÓÑ¡—00~¼íímÆM ̺Ԑ ò%bŸg.ÇR.£-S~=´"m.6z³\ö·uE S1 )xxoieE“ñ]AmÕ¨äMÆ$‚Á°öQŸ–¸0€qcíaóã}ÊT\©Šª¤|ÜF).T—H͌ Œb6Aã~YÁ• G Û0 `✸p¤ù¸MÒxÓfą#¬Qǒ 6EÿÏ_G‘P¿? >p£¼-ýü@Þ«…½§1é¼m€ùôª Q/SryۀñiUáîffÆ"pyœ qws¿<֜^Reª[*ÎòiÕVÇE™Û– ´ò‰[Æù¼mŒ£ÎPÕvúYیÔ5݉%®Ä~ҍ˜IøŽT +õê™O Ñ|Œ%1ãà{dñ†Mőãt<“¨9Á¢n=ëZ=ÍT‹ñ¬@Q·žs§ž&ƒ§t´ Q·~äB­„¿Ìm×LÒ5Â?ºöIî‘I¤äE½íÌêæh~Ø$1 7I`ÍÜ$åõ(XÔÝÎò±Óì°IŠºÛ9všŒ×y47‚DÝíè]S9¿qòŸ)À-Ç$înCˆ}ü’uý£’7ªÉ|ƒJõjüÒ­µò»+T³»¾] Ë!NsñæåŽ@Ô뎽މ}k !&ÿՌÕàºy¸\sí—Í<77S)xŒò}í¼BpfŸŽnŽÊÀäÝjH~{š ÚǍ“¨3T³õ‡»[ïxíó<ÿÿýù×i•åøÿ6hXC5~gÖµün^`íiêôŠ7×ëaƒÅÝa ÷°°w݊nË(ÓW5Õ¯ ,Í_Ïþ]¦vÓendstream +endobj +845 0 obj +2726 +endobj +846 0 obj<>>>/Annots 337 0 R>>endobj +847 0 obj<>stream +xÚÕ[]wÔ6}ϯðcûÀ¢O<†„PÚІdûÌFIÜz×Áë ¤¿¾#id—+í9a p&–îêj¤™Ñ•ù|Ä¿y"Sûgµ>z³@€‡¸Úç àô&'Ýí&/öG Øh“ÛˆðB›|Âå6ë´pù,‡Qùãp_Ÿi¬¢ QÆ|NKŸæ?Ør‚ÖÍ= (¯¦òߊ½Âº“ÂøÇ'LáDe7 ¬“BöÁùÇîêqۙõÓ`¤?PÔÙþŒùç +¨òÖ¬¡´µ€é‹méç,>]\kºÌä +]oô‹€”ÒZg>?ŋé€èŠé">F¤ù—ÓѹsÙÜ1 2µ3¦”í—fەíôZ%¶:gvyQ¼\ xݔh__¤©1Rh€`'^\M×ij@ó[f„† ÍG]tiz¸5/"~“ÌêÜnLo¿IîƒôÉ]¹¹öÚÐ"L }†nÒm¤³MÀ…u…Âçœ&·©ô;Ødi«ß\h˜ÒzËE,Ǿ§÷¢ƒàoèif§ÔÄc<ܐ¾0)\Ø¥HøÜaV­YuՃ¯É”øÎÓñçÊ×qLú,%œßEê8¦|Ž:^­Ìv{Þ¸"D¥LQ{ôä4=U0—^Š†ì*¸O.ÇuÝ|qÈ¦êYå–(Á,óágŽa˜åý¹ëî¤.·~…Êù¬P¡"üRå㒲L¼Eø¥Ú%Ëï]Ûìî/ׯ"fê  £´4ÇÈbSŸ·-ݓZ>ÞôYöÃøLf>¦H›8¼EÈÉcÊ®k.ví­ùµùäÖeª¿.…ŽpÊ GÊɽE¸ åjÛ|ٚãëëÖø=—揙QjœchÇÞ"Ը𡩅™²9„L‘Ns“EÞWK +­›, +F<·S³y´pZÍ#NFÉåÚ(Ñ$Z„\NVäíµ/¹u6‹¥–ñ>”ähjNâïɽßtPՕõlbI!§s”Û¥õ›³98@Ï]4µ#¦Š¹”(QzJ£$,¡´ô¡U¤¢ôÚî£'…)~×9‹Ðƒ JBÊ¥©ËÇ9í»>>>/Annots 384 0 R>>endobj +850 0 obj<>stream +xÚ՛MsÜ6†ïú<&‡Œ‰/~e9Îz×±µÒ¸’­JÕ=¢e®5C…CÙå4ºA6èì™Mªì ñmúóLd¹ýWd¥ÌT‘m¶gO×gOž×™Ì³õ»L˜:+J­o~X7oïÚ¬—]ô»±Ýû×ÿ;ûy}–¯rK€?üqõ‹E­ò¬Ðµýs› !V‚JwÙ5à=†ÛìÉsm´ŸQ˜~ÞesÛ¾ìo᧨j¥2÷?W'ð*ʕYUVyÛ¯Æ qª°e×#pD±’§£mÒX&4J¹*`tMe?KL¤T¶ "‡vßÛöoÿÑíÇ~ø ØÊMpRW^¯4èÒÅÊP‰éùJ/t=ïîZ·ì*9æ0¦”™&šU–W«’J³2S—¶ì”u»qÓÜ»egV愦¦ª ++…G–vöa‰)¬ÜÈ]µÛ~l¯úÞ->£íb<…IiEí\А•ýKLZ™£O¹jÿ|h÷ãÿ:S 3ð7–˜:S¢3¹zqyÑlÞ·ÓÊN♚IyöcOQÂnXbò´FŸr e8¿Ùv;7xåI,>U'Ä©Ý +Ž+1qV²œÅ=Ei'5x)}¢œœŠ/1}¢šÕ½j¶--»“—”–+r*ÒFhXbÒr½bâ¼O±q܉„+:ËÓ6þr^EI»’°4ËÓµ@¯rýy?¶Û_†þÁíyE~ +ú’ÚÊ]А֥`‰i++t)ëv{ÿ¬N/„Nê+4+5ès%¦¯0èUÖݶíÆŒU’pn¥–v‘aé3NÝbºB}rç-•gÏ7Vž*k)aà°@òìS«ŠŽ@kv»Ûìq[Íý§ÉÀiTO<\ʏÓ8Cü<Äùž×n†ntg+ë¸N=brœQR£»Ó¹õæXbSJtwçã{{xï6ÍØõ»ˆ­ÆB pûÔ7 î›}t 9`›IQ¯êŽî¢Æî|%®ô÷q_Z&Œ,úÝ\L%fdëõ!Æ`½1¦—!Ë6˜aO›}·‰ÀXw «áä¨á à¶<ý}]gÊȪ®Èù‹©4YÕõJlä‰å‚€€Fž`Ϻ[{pŠÐX°riçoH£Äû+ÏíW«„‰+ƒQm^ÚEŒ%fâª8̝ΝaÃEW€ò ­ÙÝÄ&ñÜ.•à,¢¨C¹`-cÝ­¯‘³`£Åc#ek¿ùXißBU)Ü6UÀu æ-T•’m¡íð¸1Xw£|"Œê w¾ÙônO¦X¿:‘Ð#b-œÐ¦r;‹êk*°ùljÜUÖïÛÇ-źÂ. +u¢zB5›M»ßÿ÷®¹ Y —‰Ò7 &\%º€ï˜Ȥ¥µq; šÃ˜¥mL¥´4q„‹ÜÕª†~Hš1ÀÐæ4'ú„œ ]qzk“0´ÝQädhW`†VŠŽ@iCG(½Q=¡î›Û6eǵfþÌÉΚg;¯Žjé"áj¦ªŒ,S®Væ^Êã†a=]ÞG‡¬FÐúó}4na½ñȓ‡,¬GV|Oe}ñ´³g0uv!·¯Ž|ÐI¤×Tnh3SS‰-ŒœòkÛnÛ®ÆÏ÷t~¨Oåú#%O֔Y“ರ4˓5e֜¼M¿ûèä™Ó¸“Ó‰”,)»–áKL[EÙµó››Dh?w7”/aÔÀó`íº™‹sŽ´‡Q³@bŒ¯<Ö Å† Ø÷ÙÕçR~O?©‰ Yø”!$XbÃUð”a,åýñ‚B‡4߀€Ï†î£µGürBÏ@?‰0>Z¬»…U³òi豁—{ù,«¸ád®¾Z1ËM¹ãïxŗt£ØÖƒ%6èÆÍØß†nL,њ³lX Bl>ûOÿ0Äc5“løl$jàX¯?Åî´Xgi³è°UjÃ%Öå´jbõ1ë ÇÕ–BÀ©KÏI.5ÞÝ $˜o ç…†~çíúñ$œE¥ÄÔ/ܤàÓw>ynèE4¢ pù¸ð`Ç¢„ ÁiXK”Ÿ"c1÷´á [öCÕ¥ܒº¾f+N%Žª ÷©ßGôͽ!í£`ž +±žX¯Ç÷Ñ©ËúڂÛÂP(5(yŽlOy–£Æ&‘y“í.äÆÂ4£ü3ÕK¡8¨2ˆ?¸­ˆT­Ù=-mâ«ÓKÙb»sù.«‚…ù$sÁ¶ûtÖÆÃj¸¹`TM¸wC¹cd½!$†ójÀ¢zb½Œnͬ7Lz5)žî±Á.î:ÿÊQÖG=¿¦ÆMTøFÁ ó¸‰êkrmUÁá#@Qµƒ}ÄQÍ=}p¨¾Jë‹r „Â7 +è ÄÑÁF&Æ«Tsv l¼JýUÙQs+!€Q5áXg×ÄEÈ¢zbýÚDRsoýàmBÀò öú:üͽáXV-¿Ë7 [³*?Қ5‰ô–(è]Ѝìö¥9À½K¹èï¶o»&¶‹Ï0„ÁÎ7 âùý½=7wb'ׂǗr¤„¼l6šÛÈʨ }þñÃÅùå?:§[~ëLŽ”.§ëŠ’Jl¤4½²ùýÅ«Ÿ×ñۊrfgÎò ÷¯ó'×÷}G/厙IHééñŸ/1)z¦óªÏ×vޝÚÛ¿¤Ÿ–‚í«R„ûªüšhÈ£p÷ã(ª–‡í«„Á ®€Cõ2íŸY_ðõÖ$ß@&½3ë 3»ü‚D är†5p¬I`TbÔsöv lÔó¯{»äa¸æË§KîÝ9÷ï–ÔòèžX¿u»›þSôúL±OƒÍS‡<ß ú»]õÇ?“H–×ø®ÈÙ´f¯ŠìˆÕæÐÓúܛÖ)'a%±’ë”(BÁ5$Ç`-aÒ5÷‡ ^-`TM´p}‰#­¯ÈHÁ}OáŸöØ] `ÏgøuOáßÐÄ|˜ï7o V$vÙSϐÌ@j¹îߍŸš!çÌýA¼¦à0¬%ØËnÓîömLÜÔ¼ªþBž«öFºÚvk—§K‰#úՕ1ñEjðAN –5ì9Np1c(øÝnc¯gž1눵ø,ñՋßãGÌzâhˆ–Mð~ÉUè>X¸\Vð»†Õ‡½¬š{Í0øÜ…ÕÅA³‰u·¬¢^h¤ê⋹¤‹oz“z_IPx¨¡EÙÕôFéÅnú›‡®u"¹Ï”4I¯€¤v©¿EV—Þ' ÍM»m†§”Ô5.a=«Ê§ßÙ­hÙJˆŠš²™ÙśËëlr™îšºý84c?ì³_›ÝCãÎ6ʽ˜ü©Ä]בýþ}öîªZ¦endstream +endobj +851 0 obj +2524 +endobj +852 0 obj<>>>/Annots 414 0 R>>endobj +853 0 obj<>stream +xÚ͛]WܼÇïùîUۋl,K²ìKÞò4=@èîÒçôÒ/¸a×Ô^’'ýôÕH£ÕȀlÒIràh5ú­5ó·4zÉöX’ê¿,á9ü»\ï,÷Þ(“,M–«„É2ɕH–WYVŸoë¤]%‡íf[o¶ý_—ÿÞ;^Tàƒóß•ÍÒ$¥þ¹NX*f +K·ÉðƒÝuòþƒHƒ/TY’˾ï ÙTÝ÷äÉo¡`ý5y:ËïAK;júm×|¾ß6í&Â$Í,Ê0­eΛëë†,ןšÏf¯ôGæ#îçrV÷çú·-aÀÅ>Տ»¸¿»k»-°x¦?zÕ>ŒôP=ÙCýôº‡Y¦¾Ö¿!"¦€äP溬ûòÛÙÅÓá&Mµ§Xr¡ ¬w¨ã³ãùþID=„ y²˜Éç x~qpòñ0Â#„µ~!ùðùœò4ìølq <‘éŠ× +æh¤Òr&v‘2)–ÎÄÄH!‡1>Ùz‡:ùx0ߟÿ+)Ny¹ÏRìžm4ô¡*!.Ð8àXè)A󤀗˜òÐÀ÷؇dò"¡Ïٓϫ ‰,8Žø3†|Ø÷$ï`eø 6°ïÚkX9„aµ¡¼‹PJBÉå,PJO9l×ëØ¬@ZCïŠY²°Þ°Îêí·¶ûëo¯i"ðdh`p‹z»m6×f’ájÆÞt€ÎËø{.óÒÌ9% >¶°€›ßõ/Uj'H¬šëûNwði8?wQ´­wÈ*æxßÏô›ÐÀ¡Æ#I,¤Ã^£~ÔiS·ª.k fþêÁŒÐ$ RævêÊ`^±%Ÿ4H©ì<3)n”î†\, :„noꘫ}s˜Y*€¡Â>žÇfUßƗ|×ñݬj µuÕÕ}irâ»,“0²À2÷¸‹>ê6Ú\Ãôð0„3pO7?–ÎʓӨlô”#¼lL‰ÈF‡F}ZÕðJ1#š± S&k*DÓüBB23Ëþ³îšÕ÷h¿Is¬@^°°ºU +iªƒË!@Xo@çZÁzúD–´‡lƒҜK6õ%lf˜”¿xƒdB±‘`¥Ü$Fª/˜ V*\ϽIk+RH) ëÅԜ`á{ψAÎ[úy¼ã0¢†H4@dÒg/µVû¡‰25i‡É©mÁ‡L”ìéAØ­±‘û4}|_…y˜€*€9¤™w-6À{€Æ)þ‡ˆ[ÔÝ׺³ñJ_q[…. œRfâ·^58U<##;¨±ˆõˆ™Âc;‚³iY4Ø‹õˆ£îKß øÿ|— 3+Øiµ2féÌÓ ¾Çç‹Og‘ôÀ7±QÖ#¬|w×ÄNH{H6Œ$”æ wÔÆF*Ò¾‡04@Øiµíš?̚ †³7 åhà3£¯õ­)À±Ì޼“‡$–ª! +ë–‰±È)ŠËàt+À9äDÎ7‡È=„¡Â~•ȍō›Ôãf >n¼,í"oJ܉™47@a=ÂÛï·÷±ì€ìV@âœAévnÛÎx:{Áý®çø<ñy!Í4hÝb +ÄçÅä!ÎqЄõù3üí`œ!0g`óè›vÛoËW]¦ü°³3ó¦„õ–-g«ÌNš‹ìא–뤀!#À`5‚ŽêþËßëí¬ã~šÃdaf'Û/S “¥™Æ†˜Âȉb°A'U_wÎcòm'¹g; rv®ãœ¹œÝÉÙ9çv´:ÉÚw¸rˆÃjäŒåíŽ#à )䔔sÒô‘i´6Š<V#ª]E5áŸI‰!«ô¡¹­íök]?¡ªPqU¤îªNmÁ]tÒE¼hsb¿C¤5pÈØ;G[ë8›Ëy!Ë8օN_6Õ:¦Â1B*ÑÀÛ.¦BßZ³”ö ë¼êûomwõ'¼ö³×G£úËs›…À²Øˆþr…§¥‘Ä7Ô*Vº«‘sXE•Gšë¼TÀÛJYX¬£6rVèۂ‚¹žìÖ+w~»n6pÓ¸¹gL@ö°oÐYg€ÜeÕ‰ õ·}8 ·êÚuìî! g&àÜ* iÒåM«Ç瘎 @ã +5|8g€ÀÓêò¦ÙÔVÆìgNùÅÈ) +\›Hw +–>endobj +856 0 obj<>endobj +857 0 obj<>endobj +858 0 obj<>endobj +859 0 obj<>endobj +860 0 obj<>endobj +861 0 obj<>endobj +862 0 obj<>endobj +863 0 obj<>endobj +864 0 obj<>endobj +865 0 obj<>endobj +866 0 obj<>endobj +867 0 obj<>endobj +868 0 obj<>endobj +869 0 obj<>endobj +870 0 obj<>endobj +871 0 obj<>endobj +872 0 obj<>endobj +873 0 obj<>endobj +874 0 obj<>endobj +875 0 obj<>endobj +876 0 obj<>endobj +877 0 obj<>endobj +878 0 obj<>endobj +879 0 obj<>endobj +880 0 obj<>endobj +881 0 obj<>endobj +882 0 obj<>endobj +883 0 obj<>endobj +884 0 obj<>endobj +885 0 obj<>endobj +886 0 obj<>endobj +887 0 obj<>endobj +888 0 obj<>endobj +889 0 obj<>endobj +890 0 obj<>endobj +891 0 obj<>endobj +892 0 obj<>endobj +893 0 obj<>endobj +894 0 obj<>endobj +895 0 obj<>endobj +896 0 obj<>endobj +897 0 obj<>endobj +898 0 obj<>endobj +899 0 obj<>endobj +900 0 obj<>endobj +901 0 obj<>endobj +902 0 obj<>endobj +903 0 obj<>endobj +904 0 obj<>endobj +905 0 obj<>endobj +906 0 obj<>endobj +907 0 obj<>endobj +908 0 obj<>endobj +909 0 obj<>endobj +910 0 obj<>endobj +911 0 obj<>endobj +912 0 obj<>endobj +913 0 obj<>endobj +914 0 obj<>endobj +915 0 obj<>endobj +916 0 obj<>endobj +917 0 obj<>endobj +918 0 obj<>endobj +919 0 obj<>endobj +920 0 obj<>endobj +921 0 obj<>endobj +922 0 obj<>endobj +923 0 obj<>endobj +924 0 obj<>endobj +925 0 obj<>endobj +926 0 obj<>endobj +927 0 obj<>endobj +928 0 obj<>endobj +929 0 obj<>endobj +930 0 obj<>endobj +931 0 obj<>endobj +932 0 obj<>endobj +933 0 obj<>endobj +934 0 obj<>endobj +935 0 obj<>endobj +936 0 obj<>endobj +937 0 obj<>endobj +938 0 obj<>endobj +939 0 obj<>endobj +940 0 obj<>endobj +941 0 obj<>endobj +942 0 obj<>endobj +943 0 obj<>endobj +944 0 obj<>endobj +945 0 obj<>endobj +946 0 obj<>endobj +947 0 obj<>endobj +948 0 obj<>endobj +949 0 obj<>endobj +950 0 obj<>endobj +951 0 obj<>endobj +952 0 obj<>endobj +953 0 obj<>endobj +954 0 obj<>endobj +955 0 obj<>endobj +956 0 obj<>endobj +957 0 obj<>endobj +958 0 obj<>endobj +959 0 obj<>endobj +960 0 obj<>endobj +961 0 obj<>endobj +962 0 obj<>endobj +963 0 obj<>endobj +964 0 obj<>endobj +965 0 obj<>endobj +966 0 obj<>endobj +967 0 obj<>endobj +968 0 obj<>endobj +969 0 obj<>endobj +970 0 obj<>endobj +971 0 obj<>endobj +972 0 obj<>endobj +973 0 obj<>endobj +974 0 obj<>endobj +975 0 obj<>endobj +976 0 obj<>endobj +977 0 obj<>endobj +978 0 obj<>endobj +979 0 obj<>endobj +980 0 obj<>endobj +981 0 obj<>endobj +982 0 obj<>endobj +983 0 obj<>endobj +984 0 obj<>endobj +985 0 obj<>endobj +986 0 obj<>endobj +987 0 obj<>endobj +988 0 obj<>endobj +989 0 obj<>endobj +990 0 obj<>endobj +991 0 obj<>endobj +992 0 obj<>endobj +993 0 obj<>endobj +994 0 obj<>endobj +995 0 obj<>endobj +996 0 obj<>endobj +997 0 obj<>endobj +998 0 obj<>endobj +999 0 obj<>endobj +1000 0 obj<>endobj +1001 0 obj<>endobj +1002 0 obj<>endobj +1003 0 obj<>endobj +1004 0 obj<>endobj +1005 0 obj<>endobj +1006 0 obj<>endobj +1007 0 obj<>endobj +1008 0 obj<>endobj +1009 0 obj<>endobj +1010 0 obj<>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<>1<>2<>6<>]>>>>endobj +xref +0 1023 +0000000000 65535 f +0000000015 00000 n +0000000229 00000 n +0000001795 00000 n +0000001869 00000 n +0000001948 00000 n +0000002030 00000 n +0000002116 00000 n +0000002194 00000 n +0000002271 00000 n +0000002350 00000 n +0000002434 00000 n +0000002511 00000 n +0000002593 00000 n +0000002678 00000 n +0000002737 00000 n +0000002789 00000 n +0000002874 00000 n +0000002926 00000 n +0000003010 00000 n +0000003113 00000 n +0000003151 00000 n +0000003255 00000 n +0000003304 00000 n +0000003388 00000 n +0000003492 00000 n +0000003596 00000 n +0000003700 00000 n +0000003804 00000 n +0000003908 00000 n +0000004012 00000 n +0000004116 00000 n +0000004220 00000 n +0000004324 00000 n +0000004418 00000 n +0000004523 00000 n +0000004588 00000 n +0000004673 00000 n +0000004731 00000 n +0000004814 00000 n +0000004852 00000 n +0000004912 00000 n +0000004996 00000 n +0000005049 00000 n +0000005133 00000 n +0000005164 00000 n +0000005221 00000 n +0000005305 00000 n +0000005410 00000 n +0000005513 00000 n +0000005617 00000 n +0000005674 00000 n +0000005758 00000 n +0000005810 00000 n +0000005915 00000 n +0000006020 00000 n +0000006051 00000 n +0000006108 00000 n +0000006192 00000 n +0000006216 00000 n +0000006273 00000 n +0000006357 00000 n +0000006462 00000 n +0000006567 00000 n +0000006605 00000 n +0000006710 00000 n +0000006815 00000 n +0000006920 00000 n +0000007025 00000 n +0000007070 00000 n +0000007175 00000 n +0000007280 00000 n +0000007385 00000 n +0000007423 00000 n +0000007528 00000 n +0000007633 00000 n +0000007664 00000 n +0000007768 00000 n +0000007872 00000 n +0000007976 00000 n +0000008080 00000 n +0000008184 00000 n +0000008288 00000 n +0000008392 00000 n +0000008496 00000 n +0000008600 00000 n +0000008704 00000 n +0000008808 00000 n +0000008912 00000 n +0000009016 00000 n +0000009120 00000 n +0000009224 00000 n +0000009328 00000 n +0000009432 00000 n +0000009535 00000 n +0000009640 00000 n +0000009745 00000 n +0000009850 00000 n +0000009955 00000 n +0000010060 00000 n +0000010165 00000 n +0000010271 00000 n +0000010377 00000 n +0000010483 00000 n +0000010589 00000 n +0000010695 00000 n +0000010801 00000 n +0000010907 00000 n +0000011013 00000 n +0000011119 00000 n +0000011225 00000 n +0000011331 00000 n +0000011436 00000 n +0000011542 00000 n +0000011648 00000 n +0000011754 00000 n +0000011860 00000 n +0000011966 00000 n +0000012072 00000 n +0000012178 00000 n +0000012284 00000 n +0000012390 00000 n +0000012496 00000 n +0000012602 00000 n +0000012708 00000 n +0000012814 00000 n +0000012920 00000 n +0000013026 00000 n +0000013132 00000 n +0000013238 00000 n +0000013656 00000 n +0000013762 00000 n +0000013788 00000 n +0000013894 00000 n +0000014000 00000 n +0000014106 00000 n +0000014212 00000 n +0000014262 00000 n +0000014368 00000 n +0000014474 00000 n +0000014508 00000 n +0000014614 00000 n +0000014720 00000 n +0000014754 00000 n +0000014860 00000 n +0000014966 00000 n +0000015000 00000 n +0000015106 00000 n +0000015132 00000 n +0000015238 00000 n +0000015344 00000 n +0000015450 00000 n +0000015492 00000 n +0000015598 00000 n +0000015624 00000 n +0000015730 00000 n +0000015836 00000 n +0000015942 00000 n +0000015984 00000 n +0000016090 00000 n +0000016196 00000 n +0000016230 00000 n +0000016336 00000 n +0000016362 00000 n +0000016468 00000 n +0000016494 00000 n +0000016600 00000 n +0000016626 00000 n +0000016732 00000 n +0000016758 00000 n +0000016864 00000 n +0000016970 00000 n +0000017076 00000 n +0000017182 00000 n +0000017288 00000 n +0000017394 00000 n +0000017500 00000 n +0000017606 00000 n +0000017688 00000 n +0000017794 00000 n +0000017898 00000 n +0000018004 00000 n +0000018046 00000 n +0000018151 00000 n +0000018257 00000 n +0000018291 00000 n +0000018396 00000 n +0000018422 00000 n +0000018528 00000 n +0000018554 00000 n +0000018660 00000 n +0000018764 00000 n +0000018798 00000 n +0000018850 00000 n +0000018936 00000 n +0000018972 00000 n +0000019059 00000 n +0000019111 00000 n +0000019197 00000 n +0000019239 00000 n +0000019296 00000 n +0000019383 00000 n +0000019434 00000 n +0000019521 00000 n +0000019555 00000 n +0000019609 00000 n +0000019696 00000 n +0000019753 00000 n +0000019840 00000 n +0000019900 00000 n +0000019986 00000 n +0000020028 00000 n +0000020081 00000 n +0000020168 00000 n +0000020194 00000 n +0000020300 00000 n +0000020326 00000 n +0000020431 00000 n +0000020457 00000 n +0000020563 00000 n +0000020669 00000 n +0000020775 00000 n +0000020881 00000 n +0000020987 00000 n +0000021093 00000 n +0000021159 00000 n +0000021212 00000 n +0000021299 00000 n +0000021356 00000 n +0000021443 00000 n +0000021549 00000 n +0000021655 00000 n +0000021760 00000 n +0000021818 00000 n +0000021924 00000 n +0000022028 00000 n +0000022134 00000 n +0000022238 00000 n +0000022343 00000 n +0000022449 00000 n +0000022494 00000 n +0000022581 00000 n +0000022626 00000 n +0000022712 00000 n +0000022757 00000 n +0000022844 00000 n +0000022934 00000 n +0000023039 00000 n +0000023145 00000 n +0000023251 00000 n +0000023357 00000 n +0000023463 00000 n +0000023569 00000 n +0000023674 00000 n +0000023780 00000 n +0000023886 00000 n +0000023992 00000 n +0000024098 00000 n +0000024204 00000 n +0000024310 00000 n +0000024416 00000 n +0000024522 00000 n +0000024627 00000 n +0000024733 00000 n +0000024839 00000 n +0000024945 00000 n +0000025051 00000 n +0000025157 00000 n +0000025263 00000 n +0000025369 00000 n +0000025475 00000 n +0000025581 00000 n +0000025686 00000 n +0000025792 00000 n +0000025898 00000 n +0000026004 00000 n +0000026110 00000 n +0000026216 00000 n +0000026322 00000 n +0000026428 00000 n +0000026534 00000 n +0000026640 00000 n +0000026746 00000 n +0000026852 00000 n +0000026957 00000 n +0000027063 00000 n +0000027169 00000 n +0000027275 00000 n +0000027380 00000 n +0000027483 00000 n +0000027845 00000 n +0000027950 00000 n +0000028056 00000 n +0000028162 00000 n +0000028268 00000 n +0000028374 00000 n +0000028479 00000 n +0000028584 00000 n +0000028689 00000 n +0000028794 00000 n +0000028899 00000 n +0000029005 00000 n +0000029111 00000 n +0000029217 00000 n +0000029323 00000 n +0000029429 00000 n +0000029535 00000 n +0000029641 00000 n +0000029747 00000 n +0000029853 00000 n +0000029959 00000 n +0000030065 00000 n +0000030171 00000 n +0000030277 00000 n +0000030383 00000 n +0000030489 00000 n +0000030595 00000 n +0000030701 00000 n +0000030807 00000 n +0000030913 00000 n +0000031019 00000 n +0000031125 00000 n +0000031231 00000 n +0000031337 00000 n +0000031443 00000 n +0000031549 00000 n +0000031655 00000 n +0000031761 00000 n +0000031867 00000 n +0000031973 00000 n +0000032079 00000 n +0000032185 00000 n +0000032291 00000 n +0000032397 00000 n +0000032503 00000 n +0000032608 00000 n +0000032712 00000 n +0000032816 00000 n +0000033210 00000 n +0000033316 00000 n +0000033422 00000 n +0000033528 00000 n +0000033634 00000 n +0000033740 00000 n +0000033846 00000 n +0000033952 00000 n +0000034058 00000 n +0000034164 00000 n +0000034270 00000 n +0000034376 00000 n +0000034482 00000 n +0000034588 00000 n +0000034694 00000 n +0000034800 00000 n +0000034906 00000 n +0000035012 00000 n +0000035118 00000 n +0000035224 00000 n +0000035330 00000 n +0000035436 00000 n +0000035542 00000 n +0000035648 00000 n +0000035754 00000 n +0000035860 00000 n +0000035966 00000 n +0000036072 00000 n +0000036178 00000 n +0000036284 00000 n +0000036390 00000 n +0000036496 00000 n +0000036601 00000 n +0000036707 00000 n +0000036813 00000 n +0000036919 00000 n +0000037025 00000 n +0000037131 00000 n +0000037237 00000 n +0000037343 00000 n +0000037449 00000 n +0000037555 00000 n +0000037661 00000 n +0000037766 00000 n +0000037871 00000 n +0000037975 00000 n +0000038079 00000 n +0000038465 00000 n +0000038571 00000 n +0000038677 00000 n +0000038782 00000 n +0000038887 00000 n +0000038992 00000 n +0000039097 00000 n +0000039203 00000 n +0000039309 00000 n +0000039415 00000 n +0000039520 00000 n +0000039625 00000 n +0000039730 00000 n +0000039835 00000 n +0000039940 00000 n +0000040045 00000 n +0000040150 00000 n +0000040255 00000 n +0000040360 00000 n +0000040465 00000 n +0000040570 00000 n +0000040675 00000 n +0000040780 00000 n +0000040885 00000 n +0000040990 00000 n +0000041095 00000 n +0000041200 00000 n +0000041305 00000 n +0000041410 00000 n +0000041515 00000 n +0000041765 00000 n +0000041799 00000 n +0000041833 00000 n +0000044618 00000 n +0000044667 00000 n +0000044716 00000 n +0000044765 00000 n +0000044814 00000 n +0000044863 00000 n +0000044912 00000 n +0000044961 00000 n +0000045010 00000 n +0000045059 00000 n +0000045108 00000 n +0000045157 00000 n +0000045206 00000 n +0000045255 00000 n +0000045304 00000 n +0000045353 00000 n +0000045402 00000 n +0000045451 00000 n +0000045500 00000 n +0000045549 00000 n +0000045598 00000 n +0000045647 00000 n +0000045696 00000 n +0000045745 00000 n +0000045794 00000 n +0000045843 00000 n +0000045892 00000 n +0000045941 00000 n +0000045990 00000 n +0000046039 00000 n +0000046088 00000 n +0000046137 00000 n +0000046186 00000 n +0000046235 00000 n +0000046284 00000 n +0000046333 00000 n +0000046382 00000 n +0000046431 00000 n +0000046480 00000 n +0000046529 00000 n +0000046578 00000 n +0000046627 00000 n +0000046676 00000 n +0000046725 00000 n +0000046774 00000 n +0000046823 00000 n +0000046872 00000 n +0000046921 00000 n +0000046970 00000 n +0000047019 00000 n +0000047068 00000 n +0000047117 00000 n +0000047166 00000 n +0000047215 00000 n +0000047264 00000 n +0000047313 00000 n +0000047362 00000 n +0000047411 00000 n +0000047460 00000 n +0000047509 00000 n +0000047558 00000 n +0000047607 00000 n +0000047656 00000 n +0000047705 00000 n +0000047754 00000 n +0000047803 00000 n +0000047852 00000 n +0000047901 00000 n +0000047950 00000 n +0000047999 00000 n +0000048048 00000 n +0000048097 00000 n +0000048146 00000 n +0000048195 00000 n +0000048244 00000 n +0000048293 00000 n +0000048342 00000 n +0000048391 00000 n +0000048440 00000 n +0000048489 00000 n +0000048538 00000 n +0000048587 00000 n +0000048636 00000 n +0000048685 00000 n +0000048734 00000 n +0000048783 00000 n +0000048832 00000 n +0000048881 00000 n +0000048930 00000 n +0000048979 00000 n +0000049028 00000 n +0000049077 00000 n +0000049126 00000 n +0000049175 00000 n +0000049224 00000 n +0000049273 00000 n +0000049322 00000 n +0000049371 00000 n +0000049420 00000 n +0000049469 00000 n +0000049518 00000 n +0000049567 00000 n +0000049616 00000 n +0000049665 00000 n +0000049714 00000 n +0000049763 00000 n +0000049812 00000 n +0000049861 00000 n +0000049910 00000 n +0000049959 00000 n +0000050008 00000 n +0000050057 00000 n +0000050106 00000 n +0000050155 00000 n +0000050204 00000 n +0000050253 00000 n +0000050302 00000 n +0000050351 00000 n +0000050400 00000 n +0000050449 00000 n +0000050498 00000 n +0000050547 00000 n +0000050596 00000 n +0000050645 00000 n +0000050694 00000 n +0000050743 00000 n +0000050792 00000 n +0000050841 00000 n +0000050890 00000 n +0000050939 00000 n +0000050988 00000 n +0000051037 00000 n +0000051086 00000 n +0000051135 00000 n +0000051184 00000 n +0000051233 00000 n +0000051282 00000 n +0000051331 00000 n +0000051380 00000 n +0000051429 00000 n +0000051478 00000 n +0000051527 00000 n +0000051576 00000 n +0000051625 00000 n +0000051674 00000 n +0000051723 00000 n +0000051772 00000 n +0000051821 00000 n +0000051870 00000 n +0000051919 00000 n +0000051968 00000 n +0000052017 00000 n +0000052066 00000 n +0000052115 00000 n +0000052164 00000 n +0000052213 00000 n +0000052262 00000 n +0000052311 00000 n +0000052360 00000 n +0000052409 00000 n +0000052458 00000 n +0000052507 00000 n +0000052556 00000 n +0000052605 00000 n +0000052654 00000 n +0000052703 00000 n +0000052752 00000 n +0000053541 00000 n +0000053695 00000 n +0000060052 00000 n +0000060074 00000 n +0000060169 00000 n +0000060271 00000 n +0000060291 00000 n +0000060448 00000 n +0000061501 00000 n +0000061522 00000 n +0000061725 00000 n +0000063204 00000 n +0000063226 00000 n +0000063368 00000 n +0000063712 00000 n +0000063733 00000 n +0000063847 00000 n +0000064045 00000 n +0000064066 00000 n +0000064208 00000 n +0000065115 00000 n +0000065136 00000 n +0000065278 00000 n +0000066802 00000 n +0000066824 00000 n +0000066966 00000 n +0000067961 00000 n +0000067982 00000 n +0000068096 00000 n +0000068294 00000 n +0000068315 00000 n +0000068471 00000 n +0000069428 00000 n +0000069449 00000 n +0000069624 00000 n +0000070712 00000 n +0000070734 00000 n +0000070894 00000 n +0000071915 00000 n +0000071936 00000 n +0000072087 00000 n +0000072530 00000 n +0000072551 00000 n +0000072702 00000 n +0000073519 00000 n +0000073540 00000 n +0000073724 00000 n +0000075324 00000 n +0000075346 00000 n +0000075539 00000 n +0000076831 00000 n +0000076853 00000 n +0000077027 00000 n +0000077955 00000 n +0000077976 00000 n +0000078145 00000 n +0000078992 00000 n +0000079013 00000 n +0000079197 00000 n +0000080000 00000 n +0000080021 00000 n +0000080205 00000 n +0000081167 00000 n +0000081188 00000 n +0000081372 00000 n +0000082559 00000 n +0000082581 00000 n +0000082756 00000 n +0000083496 00000 n +0000083517 00000 n +0000083712 00000 n +0000085766 00000 n +0000085788 00000 n +0000085964 00000 n +0000087086 00000 n +0000087108 00000 n +0000087275 00000 n +0000088133 00000 n +0000088154 00000 n +0000088340 00000 n +0000089497 00000 n +0000089519 00000 n +0000089676 00000 n +0000090426 00000 n +0000090447 00000 n +0000090614 00000 n +0000091546 00000 n +0000091567 00000 n +0000091718 00000 n +0000092731 00000 n +0000092752 00000 n +0000092918 00000 n +0000093811 00000 n +0000093832 00000 n +0000093974 00000 n +0000094718 00000 n +0000094739 00000 n +0000094915 00000 n +0000096169 00000 n +0000096191 00000 n +0000096333 00000 n +0000097225 00000 n +0000097246 00000 n +0000097403 00000 n +0000098200 00000 n +0000098221 00000 n +0000098388 00000 n +0000099359 00000 n +0000099380 00000 n +0000099541 00000 n +0000100499 00000 n +0000100520 00000 n +0000100706 00000 n +0000101707 00000 n +0000101728 00000 n +0000101885 00000 n +0000102707 00000 n +0000102728 00000 n +0000102895 00000 n +0000103882 00000 n +0000103903 00000 n +0000104070 00000 n +0000104972 00000 n +0000104993 00000 n +0000105169 00000 n +0000106070 00000 n +0000106091 00000 n +0000106257 00000 n +0000107495 00000 n +0000107517 00000 n +0000107702 00000 n +0000109292 00000 n +0000109314 00000 n +0000109484 00000 n +0000110841 00000 n +0000110863 00000 n +0000111048 00000 n +0000112348 00000 n +0000112370 00000 n +0000112556 00000 n +0000113883 00000 n +0000113905 00000 n +0000114081 00000 n +0000115570 00000 n +0000115592 00000 n +0000115754 00000 n +0000117243 00000 n +0000117265 00000 n +0000117441 00000 n +0000118990 00000 n +0000119012 00000 n +0000119154 00000 n +0000119624 00000 n +0000119645 00000 n +0000119759 00000 n +0000119974 00000 n +0000119995 00000 n +0000120147 00000 n +0000120961 00000 n +0000120982 00000 n +0000121170 00000 n +0000122601 00000 n +0000122623 00000 n +0000122784 00000 n +0000123943 00000 n +0000123965 00000 n +0000124141 00000 n +0000125398 00000 n +0000125420 00000 n +0000125568 00000 n +0000126420 00000 n +0000126441 00000 n +0000126608 00000 n +0000128076 00000 n +0000128098 00000 n +0000128255 00000 n +0000129850 00000 n +0000129872 00000 n +0000130005 00000 n +0000131873 00000 n +0000131895 00000 n +0000132018 00000 n +0000133803 00000 n +0000133825 00000 n +0000133948 00000 n +0000135878 00000 n +0000135900 00000 n +0000136042 00000 n +0000137771 00000 n +0000137793 00000 n +0000137916 00000 n +0000139767 00000 n +0000139789 00000 n +0000139932 00000 n +0000141729 00000 n +0000141751 00000 n +0000141884 00000 n +0000143685 00000 n +0000143707 00000 n +0000143840 00000 n +0000145655 00000 n +0000145677 00000 n +0000145810 00000 n +0000147705 00000 n +0000147727 00000 n +0000147870 00000 n +0000149553 00000 n +0000149575 00000 n +0000149689 00000 n +0000149903 00000 n +0000149924 00000 n +0000150075 00000 n +0000150969 00000 n +0000150990 00000 n +0000151160 00000 n +0000152560 00000 n +0000152582 00000 n +0000152766 00000 n +0000154112 00000 n +0000154134 00000 n +0000154328 00000 n +0000155861 00000 n +0000155883 00000 n +0000156053 00000 n +0000157158 00000 n +0000157180 00000 n +0000157331 00000 n +0000158242 00000 n +0000158263 00000 n +0000158431 00000 n +0000159204 00000 n +0000159225 00000 n +0000159377 00000 n +0000160036 00000 n +0000160057 00000 n +0000160199 00000 n +0000161022 00000 n +0000161043 00000 n +0000161166 00000 n +0000162436 00000 n +0000162458 00000 n +0000162581 00000 n +0000163429 00000 n +0000163450 00000 n +0000163564 00000 n +0000163763 00000 n +0000163784 00000 n +0000163961 00000 n +0000164987 00000 n +0000165008 00000 n +0000165184 00000 n +0000166693 00000 n +0000166715 00000 n +0000166866 00000 n +0000168039 00000 n +0000168061 00000 n +0000168175 00000 n +0000168380 00000 n +0000168401 00000 n +0000168558 00000 n +0000171355 00000 n +0000171377 00000 n +0000171534 00000 n +0000173526 00000 n +0000173548 00000 n +0000173705 00000 n +0000176300 00000 n +0000176322 00000 n +0000176479 00000 n +0000178985 00000 n +0000179007 00000 n +0000179064 00000 n +0000179169 00000 n +0000179313 00000 n +0000179416 00000 n +0000179534 00000 n +0000179655 00000 n +0000179769 00000 n +0000179873 00000 n +0000180038 00000 n +0000180146 00000 n +0000180261 00000 n +0000180366 00000 n +0000180474 00000 n +0000180582 00000 n +0000180691 00000 n +0000180807 00000 n +0000180905 00000 n +0000181074 00000 n +0000181230 00000 n +0000181330 00000 n +0000181445 00000 n +0000181569 00000 n +0000181677 00000 n +0000181833 00000 n +0000181955 00000 n +0000182086 00000 n +0000182207 00000 n +0000182366 00000 n +0000182464 00000 n +0000182626 00000 n +0000182761 00000 n +0000182887 00000 n +0000183063 00000 n +0000183180 00000 n +0000183298 00000 n +0000183426 00000 n +0000183557 00000 n +0000183679 00000 n +0000183797 00000 n +0000183953 00000 n +0000184051 00000 n +0000184198 00000 n +0000184346 00000 n +0000184450 00000 n +0000184603 00000 n +0000184724 00000 n +0000184848 00000 n +0000184988 00000 n +0000185128 00000 n +0000185256 00000 n +0000185423 00000 n +0000185521 00000 n +0000185648 00000 n +0000185782 00000 n +0000185937 00000 n +0000186034 00000 n +0000186140 00000 n +0000186250 00000 n +0000186364 00000 n +0000186473 00000 n +0000186587 00000 n +0000186701 00000 n +0000186813 00000 n +0000186924 00000 n +0000187036 00000 n +0000187151 00000 n +0000187262 00000 n +0000187373 00000 n +0000187485 00000 n +0000187602 00000 n +0000187716 00000 n +0000187825 00000 n +0000187933 00000 n +0000188048 00000 n +0000188164 00000 n +0000188269 00000 n +0000188382 00000 n +0000188491 00000 n +0000188603 00000 n +0000188709 00000 n +0000188825 00000 n +0000188941 00000 n +0000189051 00000 n +0000189168 00000 n +0000189275 00000 n +0000189384 00000 n +0000189493 00000 n +0000189604 00000 n +0000189712 00000 n +0000189823 00000 n +0000189938 00000 n +0000190044 00000 n +0000190152 00000 n +0000190257 00000 n +0000190376 00000 n +0000190493 00000 n +0000190602 00000 n +0000190713 00000 n +0000190825 00000 n +0000190934 00000 n +0000191046 00000 n +0000191156 00000 n +0000191267 00000 n +0000191378 00000 n +0000191490 00000 n +0000191598 00000 n +0000191706 00000 n +0000191798 00000 n +0000191959 00000 n +0000192080 00000 n +0000192207 00000 n +0000192335 00000 n +0000192454 00000 n +0000192609 00000 n +0000192716 00000 n +0000192835 00000 n +0000192940 00000 n +0000193089 00000 n +0000193187 00000 n +0000193298 00000 n +0000193427 00000 n +0000193557 00000 n +0000193686 00000 n +0000193854 00000 n +0000193952 00000 n +0000194078 00000 n +0000194202 00000 n +0000194367 00000 n +0000194489 00000 n +0000194604 00000 n +0000194700 00000 n +0000194827 00000 n +0000194957 00000 n +0000195072 00000 n +0000195239 00000 n +0000195408 00000 n +0000195508 00000 n +0000195619 00000 n +0000195746 00000 n +0000195841 00000 n +0000195968 00000 n +0000196090 00000 n +0000196256 00000 n +0000196413 00000 n +0000196538 00000 n +0000196678 00000 n +0000196806 00000 n +0000196941 00000 n +0000197078 00000 n +0000197212 00000 n +0000197335 00000 n +0000197495 00000 n +0000197601 00000 n +0000197728 00000 n +0000197856 00000 n +0000197979 00000 n +0000198102 00000 n +0000198217 00000 n +0000198319 00000 n +0000198440 00000 n +0000198603 00000 n +0000198742 00000 n +0000198894 00000 n +0000199052 00000 n +0000199209 00000 n +0000199341 00000 n +0000199452 00000 n +trailer +<]>> +startxref +199681 +%%EOF diff --git a/doc/sam.shtml b/doc/sam.shtml new file mode 100644 index 0000000000..1e3633288c --- /dev/null +++ b/doc/sam.shtml @@ -0,0 +1,3992 @@ + + + + + + CUPS Software Administrators Manual + + + +

Preface

+ +

This software administrators manual provides printer administration +information for the Common UNIX Printing SystemTM +("CUPSTM"), version 1.1.5. + + + + +

Document Overview

+ +

This software administrators manual is organized into the following sections:

+ + + +

Notation Conventions

+ +

Various font and syntax conventions are used in this guide. Examples and +their meanings and uses are explained below: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Example   Description
 
lpstat
+ lpstat(1)
   The names of commands; the first mention of a command or + function in a chapter is followed by a manual page section + number.
 
/var
+ /usr/share/cups/data/testprint.ps
   File and directory names.
 
Request ID is Printer-123   Screen output.
 
lp -d printer filename ENTER   Literal user input; special keys like ENTER are + in ALL CAPS.
 
12.3   Numbers in the text are written using the period (.) to indicate + the decimal point.
+ + +

Abbreviations

+ +The following abbreviations are used throughout this manual: + +
    +
    + +
    kb +
    Kilobytes, or 1024 bytes
      + +
    Mb +
    Megabytes, or 1048576 bytes
      + +
    Gb +
    Gigabytes, or 1073741824 bytes
      + +
    +
+ +

Other References

+ +
    +
    + +
    CUPS Software Programmers Manual + +
    A programmer guide for interfacing with and/or extending the CUPS + software.
      + +
    CUPS Software Users Manual + +
    An end-user guide for using the CUPS software.
      + +
    +
+ + + + + +

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

+ +

This section describes how to compile and install CUPS on your system +from the source code. + +

Requirements

+ +

You'll need ANSI-compliant C and C++ compilers 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 compile and 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 +significantly 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. Type the following command to configure CUPS for your +system: + +

    +./configure ENTER
    +
+ +

The default installation will put the CUPS software in the +/etc, /usr, and /var directories on +your system, which will overwrite any existing printing commands on +your system. Use the --prefix option to install the CUPS +software in another location: + +

    +./configure --prefix=/some/directory 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, +CXXFLAGS, and LDFLAGS environment variables +prior to running configure: + +

    +setenv CFLAGS "-I/some/directory" ENTER
    +setenv CXXFLAGS "-I/some/directory" ENTER
    +setenv LDFLAGS "-L/some/directory" ENTER
    +./configure ... ENTER
    +
+ +

or: + +

    +CFLAGS="-I/some/directory"; export CFLAGS ENTER
    +CXXFLAGS="-I/some/directory"; export CXXFLAGS ENTER
    +LDFLAGS="-L/some/directory"; export LDFLAGS ENTER
    +./configure ... ENTER
    +
+ +

To enable support for encryption, you'll also want to add the +"--enable-ssl" option: + +

    +./configure --enable-ssl
    +
+ +

SSL and TLS support require the OpenSSL library, available at: + +

+ +

Once you have configured things, just type: + +

    +make ENTER
    +
+ +

to build the software. + + +

Installing the Software

+ +

Use the "install" target to install the software: + +

    +make install ENTER
    +
+ +
+ + + +
+ 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 reinstall the old printing system from your operating system CDs. +

+ +

Running the Software

+ +

Once you have installed the software you can start the CUPS server by +typing: + +

    +/usr/sbin/cupsd ENTER
    +
+ + +

Installing a Binary Distribution

+ +

CUPS comes in a variety of binary distribution formats. Easy +Software Products provides binaries in TAR format with installation and +removal scripts ("portable" distributions), and in RPM and DPKG formats +for Red Hat and Debian-based distributions. Portable distributions are +available for all platforms, while the RPM and DPKG distributions are +only available for Linux. + +

+ + + +
+ 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/or + reinstall the old printing system from your operating system CDs. +

+ + +

Installing a Portable Distribution

+ +

To install the CUPS software from a portable distribution 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. + + +

Installing an RPM Distribution

+ +

To install the CUPS software from an RPM distribution you will need +to be logged in as root; doing an su is good enough. Once +you are the root user, run RPM with: + +

    +rpm -e lpr
    +rpm -i cups-1.1-linux-M.m.n-intel.rpm ENTER
    +
+ +

After a short delay the CUPS software will be +installed and the scheduler will be started automatically. + +

Installing an Debian Distribution

+ +

To install the CUPS software from a Debian distribution you will +need to be logged in as root; doing an su is good enough. +Once you are the root user, run dpkg with: + +

    +dpkg -i cups-1.1-linux-M.m.n-intel.deb ENTER
    +
+ +

After a short delay the CUPS software will be installed and the +scheduler will be started automatically. + + +

3 - Printer Management

+ +

This chapter describes how to add your first printer and how to +manage your printers. + +

The Basics

+ +

Each printer queue has a name associated with it; the printer name +must start with a letter and can contain up to 127 letters, numbers, +and the underscore (_). Case is not significant, e.g. "PRINTER", "Printer", +and "printer" are considered to be the same name. + +

Printer queues also have a device associated with them. The device can be +a parallel port, a network interface, and so forth. Devices within CUPS use +Uniform Resource Identifiers ("URIs") which are a more general form of +Uniform Resource Locators ("URLs") that are used in your web browser. For +example, the first parallel port in Linux usually uses a device URI of +parallel:/dev/lp1. + + +

You can see a complete list of supported devices by running the +lpinfo(8) command: + +

    +lpinfo -v ENTER
    +file file
    +network socket
    +network http
    +network ipp
    +network lpd
    +direct parallel:/dev/lp1
    +serial serial:/dev/ttyS1?baud=115200
    +serial serial:/dev/ttyS2?baud=115200
    +direct usb:/dev/usb/lp0
    +network smb
    +
+ +

The -v option specifies that you want a list of available +devices. The first word in each line is the type of device (direct, file, +network, or serial) and is followed by the device URI or method name for +that device. File devices have device URIs of the form +file:/directory/filename while network devices use the more +familiar method://server or method://server/path +format. + +

Finally, printer queues usually have a PostScript Printer Description +("PPD") file associated with them. PPD files describe the capabilities of +each printer, the page sizes supported, etc., and are used for PostScript +and non-PostScript printers. CUPS includes PPD files for HP LaserJet, HP +DeskJet, EPSON 9-pin, EPSON 24-pin, and EPSON Stylus printers. + +

Adding Your First Printer

+ +

CUPS provides two methods for adding printers: a command-line +program called lpadmin(8) and a Web interface. The +lpadmin command allows you to perform most printer +administration tasks from the command-line and is located in +/usr/sbin. The Web interface is located at: + +

+ +

and steps you through printer configuration. If you don't like +command-line interfaces, try the Web interface instead. + +

Adding Your First Printer from the Command-Line

+ +

Run the lpadmin command with the -p option to add a +printer to CUPS: + +

    +/usr/sbin/lpadmin -p printer -E -v device -m ppd ENTER
    +
+ +

For an HP DeskJet printer connected to the parallel port this would look +like: + +

    +/usr/sbin/lpadmin -p DeskJet -E -v parallel:/dev/lp1 -m deskjet.ppd ENTER
    +
+ +

Similarly, an HP LaserJet printer using a JetDirect network interface at +IP address 11.22.33.44 would be added with the command: + +

    +/usr/sbin/lpadmin -p LaserJet -E -v socket://11.22.33.44 -m laserjet.ppd ENTER
    +
+ +

As you can see, deskjet.ppd and laserjet.ppd are +the PPD files for the HP DeskJet and HP LaserJet drivers included with CUPS. +You'll find a complete list of PPD files and the printers they will work with +in Appendix C, "Printer Drivers". + +

Adding Your First Printer from the Web

+ +

The CUPS web server provides a user-friendly "wizard" interface for +adding your printers. Rather than figuring out which device URI and PPD file +to use, you can instead click on the appropriate listings and fill in some +simple information. Enter the following URL in your web browser to begin: + +

+ +

Click on the Add Printer button to add a printer. + +

Managing Printers from the Command-Line

+ +

The lpadmin command enables you to perform most printer +administration tasks from the command-line. You'll find lpadmin +in the /usr/sbin directory. + +

Adding and Modifying Printers

+ +

Run the lpadmin command with the -p option +to add or modify a printer: + +

    +/usr/sbin/lpadmin -p printer options ENTER
    +
+ +

The options arguments can be any of the following: + +

    +
    + +
    -c class + +
    Adds the named printer to printer class class. + If the class does not exist then it is created. + +
    -i interface + +
    Copies the named interface script to the printer. + Interface scripts are used by System V printer drivers. Since + all filtering is disabled when using an interface script, scripts + generally should not be used unless there is no other driver for + a printer. + +
    -m model + +
    Specifies a standard printer driver which is usually a PPD + file. A list of all available models can be displayed using the + lpinfo command with the -m option. A + list of printer drivers included with CUPS can be found in + Appendix C, "Printer Drivers". + +
    -r class + +
    Removes the named printer from printer class class. + If the resulting class becomes empty then it is removed. + +
    -v device-uri + +
    Sets the device for communicating with the printer. If a + job is currently printing on the named printer then the job + will be restarted and sent to the new device. + +
    -D info + +
    Provides a textual description of the printer, e.g. + "John's Personal Printer". + +
    -E + +
    Enables the printer and accepts job. This option is + equivalent to running the enable(1) and + accept(8) commands on the printer. + +
    -L location + +
    Provides a textual location for the printer, e.g. + "Computer Lab 5". + +
    -P ppd-file + +
    Specifies a local PPD file for the printer driver. + +
    +
+ +

Deleting Printers

+ +

Run the lpadmin command with the -x option +to delete a printer: + +

    +/usr/sbin/lpadmin -x printer ENTER
    +
+ +

Setting the Default Printer

+ +

Run the lpadmin command with the -d option +to set a default printer: + +

    +/usr/sbin/lpadmin -d printer ENTER
    +
+ +

The default printer can be overridden by the user using the +lpoptions(1) command. + +

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 queued +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/sbin/accept printer ENTER
    +/usr/sbin/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. + +

Managing Printers from the Web

+ +

The Web interface is located at: + +

+ +

From there you can perform all printer management tasks with a few +simple mouse clicks. + + +

4 - Printer Classes

+ +

This chapter describes what printer classes are and how to manage them. + +

The Basics

+ +

CUPS provides collections of printers called printer classes. Jobs +sent to a class are forwarded to the first available printer in the class. +Classes can themselves be members of other classes, so it is possible for +you to define very large, distributed printer classes for high-availability +printing. + +

CUPS also supports implicit classes. Implicit classes work just +like printer classes, but they are created automatically based upon the +available printers and classes on the network. This allows you to setup +multiple print servers with identical printer configurations and have the +client machines send their print jobs to the first available server. If +one or more servers go down, the jobs are automatically redirected to the +servers that are running, providing fail-safe printing. + +

Managing Printer Classes from the Command-Line

+ +

Run the lpadmin command with the -p and -c options +to add a printer to a class: + +

    +/usr/sbin/lpadmin -p printer -c class ENTER
    +
+ +

The class is created automatically if it doesn't exist. To remove a +printer from a class use the -r option: + +

    +/usr/sbin/lpadmin -p printer -r class ENTER
    +
+ +

To remove the entire class just use the -x option: + +

    +/usr/sbin/lpadmin -x class ENTER
    +
+ +

Managing Printer Classes from the Web Interface

+ +

The Web interface is located at: + +

+ +

The Add Class and Modify Class interfaces provide a +list of available printers; click on the printers of interest to add them to +the class. + +

Implicit Classes

+ +

A noted earlier, implicit classes are created automatically from the +available network printers and classes. To disable this functionality, +set the ImplicitClasses +directive to Off in the cupsd.conf file. You +will find more information on doing this in +Chapter 6, "Printing System +Management". + + +

5 - Client Setup

+ +

This chapter discusses several ways to configure CUPS clients for +printing. + +

The Basics

+ +

A client is any machine that sends print jobs to another machine for +final printing. Clients can also be servers if they communicate directly with +any printers of their own. + +

CUPS supports several methods of configuring client machines: + +

+ +

Manual Configuration of Print Queues

+ +

The most tedious method of configuring client machines is to configure +each remote queue by hand using the lpadmin command: + +

    +lpadmin -p printer -E -v ipp://server/printers/printer ENTER
    +
+ +

The printer name is the name of the printer on the server +machine. The server name is the hostname or IP address of the +server machine. Repeat the lpadmin command for each remote +printer you wish to use. + +

Specifying a Single Server for Printing

+ +

CUPS can be configured to run without a local spooler and send all +jobs to a single server. However, if that server goes down then all +printing will be disabled. Use this configuration only as absolutely needed. + +

The default server is normally "localhost". To override the default +server create a file named /etc/cups/client.conf and add +a line reading: + +

    +ServerName server
    +
+ +

to the file. The server name can be the hostname or IP address +of the default server. + +

The default server can also be customized on a per-user basis. To set a +user-specific server create a file named ~/.cupsrc and add a line +reading: + +

    +ServerName server
    +
+ +

to the file. The server name can be the hostname or IP +address of the default server. + +

Automatic Configuration of Print Queues

+ +

CUPS supports automatic client configuration of printers on the same +subnet. To configure printers on the same subnet, do nothing. +Each client should see the available printers within 30 seconds +automatically. The printer and class lists are updated automatically as +printers and servers are added or removed. + +

If you want to see printers on other subnets as well, use the +BrowsePoll directive as +described next. + +

Specifying Multiple Servers for Printing

+ +

If you have CUPS servers on different subnets, then you should configure +CUPS to poll those servers. Polling provides the benefits of automatic +configuration without significant configuration on the clients, and multiple +clients on the same subnet can share the same configuration information. + +

Polling is enabled by specifying one or more +BrowsePoll directives in the +/etc/cups/cupsd.conf file. For information on making these +changes, see Chapter 6, "Printing System +Management". + + +

6 - Printing System Management

+ +

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

The Basics

+ +

Several text files are used to configure CUPS. All of the server +configuration files are located in the /etc/cups directory: + +

    +
    + + +
    classes.conf + +
    This file contains information on each printer class. + Normally you manipulate this file using the + lpadmin command or the Web interface.
      + + +
    client.conf + +
    This file provides the default server name for client + machines. See Chapter 5, "Client + Setup" for more information.
      + + +
    cupsd.conf + +
    This file controls how the CUPS server + (/usr/sbin/cupsd) operates and is normally edited by + hand.
      + + +
    mime.convs + +
    This file contains a list of standard file conversion filters + and their costs. You normally do not edit this file.
      + + +
    mime.types + +
    This file contains a list of standard file formats and how to + recognize them. You normally do not edit this file.
      + + +
    printers.conf + +
    This file contains information on each printer. Normally + you manipulate this file using the lpadmin command + or the Web Interface.
      + +
    +
+ +

Restarting the CUPS Server

+ +

Once you have made a change to a configuration file you need to +restart the CUPS server by sending it a HUP signal or using the +supplied initialization script. The CUPS distributions install the +script in the init.d directory with the name +cups. The location varies based upon the operating system: + +

    +/etc/rc.d/init.d/cups restart ENTER
    +/etc/init.d/cups restart ENTER
    +/sbin/init.d/cups restart ENTER
    +
+ +

Changing the Server Configuration

+ +

The /etc/cups/cupsd.conf file contains configuration +directives that control how the server functions. Each directive +is listed on a line by itself followed by its value. Comments are +introduced using the number sign ("#") character at the beginning of a +line. Since the server configuration file consists of plain text, you +can use your favorite text editor to make changes to it. + + +

Server Directives

+ +

The cupsd.conf file contains many directives that +determine how the server operates: + +

+ + +

AccessLog

+
+ +

Examples

+ +
    +AccessLog /var/log/cups/access_log
    +AccessLog /var/log/cups/access_log-%s
    +AccessLog syslog
    +
+ +

Description

+ +

The AccessLog directive sets the name of the access log +file. If the filename is not absolute then it is assumed to be relative +to the ServerRoot directory. The +access log file is stored in "common log format" and can be used by any +web access reporting tool to generate a report on CUPS server activity. + +

The server name can be included in the filename by using +%s in the name. + +

The special name "syslog" can be used to send the access information +to the system log instead of a plain file. + +

The default access log file is /var/log/cups/access_log. + + +

Allow

+
+ +

Examples

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

Description

+ +

The Allow directive specifies a hostname, IP address, +or network that is allowed access to the server. 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: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
mmnetmaskmmnetmask
00.0.0.08255.0.0.0
1128.0.0.016255.255.0.0
2192.0.0.024255.255.255.0
......32255.255.255.255
+ +

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

AuthClass

+
+ +

Examples

+ +
    +AuthClass Anonymous
    +AuthClass User
    +AuthClass System
    +AuthClass Group
    +
+ +

Description

+ +

The AuthClass directive defines what level of authentication +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. + +
  • 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

+
+ +

Examples

+ +
    +AuthGroupName mygroup
    +AuthGroupName lp
    +
+ +

Description

+ +

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

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

AuthType

+
+ +

Examples

+ +
    +AuthType None
    +AuthType Basic
    +AuthType Digest
    +
+ +

Description

+ +

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. + +
  • Digest - Digest authentication should be + performed using the /etc/cups/passwd.md5 file. + +
+ +

When using Basic or Digest authentication, +clients connecting through the localhost interface can also +authenticate using certificates. + +

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

AutoPurgeJobs

+
+ +

Examples

+ +
    +AutoPurgeJobs Yes
    +AutoPurgeJobs No
    +
+ +

Description

+ +

The AutoPurgeJobs directive specifies whether or not to purge +completed jobs once they are no longer required for quotas. This option has +no effect if quotas are not enabled. The default setting is No. + + +

BrowseAddress

+
+ +

Examples

+ +
    +BrowseAddress 255.255.255.255:631
    +BrowseAddress 192.0.2.255:631
    +BrowseAddress host.domain.com:631
    +
+ +

Description

+ +

The BrowseAddress directive specifies an address to +send browsing information to. Multiple BrowseAddress +directives can be specified to send browsing information to different +networks or systems. + +

The default address is 255.255.255.255:631 which will +broadcast the information to all networks the server is connected to. + +

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

+ + +

BrowseAllow

+
+ +

Examples

+ +
    +BrowseAllow from all
    +BrowseAllow from none
    +BrowseAllow from 192.0.2
    +BrowseAllow from 192.0.2.0/24
    +BrowseAllow from 192.0.2.0/255.255.255.0
    +BrowseAllow from *.domain.com
    +
+ +

Description

+ +

The BrowseAllow directive specifies a system or network +to accept browse packets from. The default is to accept browse packets +from all hosts. + +

Host and domain name matching require that you enable the +HostNameLookups directive. + +

IP address matching supports exact matches, partial addresses that +match networks using netmasks of 255.0.0.0, 255.255.0.0, and 255.255.255.0, +or network addresses using the specified netmask or bit count. + + +

BrowseDeny

+
+ +

Examples

+ +
    +BrowseDeny from all
    +BrowseDeny from none
    +BrowseDeny from 192.0.2
    +BrowseDeny from 192.0.2.0/24
    +BrowseDeny from 192.0.2.0/255.255.255.0
    +BrowseDeny from *.domain.com
    +
+ +

Description

+ +

The BrowseDeny directive specifies a system or network +to reject browse packets from. The default is to deny browse packets +from no hosts. + +

Host and domain name matching require that you enable the +HostNameLookups directive. + +

IP address matching supports exact matches, partial addresses that +match networks using netmasks of 255.0.0.0, 255.255.0.0, and 255.255.255.0, +or network addresses using the specified netmask or bit count. + + +

BrowseOrder

+
+ +

Examples

+ +
    +BrowseOrder allow,deny
    +BrowseOrder deny,allow
    +
+ +

Description

+ +

The BrowseOrder directive specifies the order of allow/deny +processing. The default order is deny,allow: + +

    + +
  • allow,deny - Browse packets are accepted unless + specifically denied. + +
  • deny,allow - Browse packets are rejected unless + specifically allowed. + +
+ + +

BrowseInterval

+
+ +

Examples

+ +
    +BrowseInterval 0
    +BrowseInterval 30
    +
+ +

Description

+ +

The BrowseInterval directive specifies the maximum amount of +time between browsing updates. Specifying a value of 0 seconds disables +outgoing browse updates but allows a server to receive printer information +from other hosts. + +

The BrowseInterval value should always be less than the +BrowseTimeout value. Otherwise +printers and classes will disappear from client systems between updates. + + +

BrowsePoll

+
+ +

Examples

+ +
    +BrowsePoll 192.0.2.2:631
    +BrowsePoll host.domain.com:631
    +
+ +

Description

+ +

The BrowsePoll directive polls a server for available +printers once every +BrowseInterval seconds. +Multiple BrowsePoll directives can be specified to poll +multiple servers. + +

If BrowseInterval is set to 0 then the server is polled +once every 30 seconds. + + +

BrowsePort

+
+ +

Examples

+ +
    +BrowsePort 631
    +BrowsePort 9999
    +
+ +

Description

+ +

The BrowsePort directive specifies the UDP port number +used for browse packets. The default port number is 631. + +

+ + + +
+ NOTE: + +

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

+ + +

BrowseRelay

+
+ +

Examples

+ +
    +BrowseRelay 193.0.2.1 192.0.2.255
    +BrowseRelay 193.0.2.0/255.255.255.0 192.0.2.255
    +BrowseRelay 193.0.2.0/24 192.0.2.255
    +BrowseRelay *.domain.com 192.0.2.255
    +BrowseRelay host.domain.com 192.0.2.255
    +
+ +

Description

+ +

The BrowseRelay directive specifies source and destination +addresses for relaying browsing information from one host or network to +another. Multiple BrowseRelay directives can be specified +as needed. + +

BrowseRelay is typically used on systems that bridge +multiple subnets using one or more network interfaces. It can also be +used to relay printer information from polled servers with the line: + +

    +BrowseRelay 127.0.0.1 255.255.255.255
    +
+ +

This effectively provides access to printers on a WAN for all clients +on the LAN(s). + + +

BrowseShortNames

+
+ +

Examples

+ +
    +BrowseShortNames Yes
    +BrowseShortNames No
    +
+ +

Description

+ +

The BrowseShortNames directive specifies whether or not +short names are used for remote printers when possible. Short names are +just the remote printer name, without the server ("printer"). If more than +one remote printer is detected with the same name, the printers will have +long names ("printer@server1", "printer@server2".) + +

The default value for this option is Yes. + + +

BrowseTimeout

+
+ +

Examples

+ +
    +BrowseTimeout 300
    +BrowseTimeout 60
    +
+ +

Description

+ +

The BrowseTimeout directive sets the timeout for +printer or class information that is received in browse packets. Once a +printer or class times out it is removed from the list of available +destinations. + +

The BrowseTimeout value should always be greater than the +BrowseInterval value. Otherwise +printers and classes will disappear from client systems between updates. + + +

Browsing

+
+ +

Examples

+ +
    +Browsing On
    +Browsing Off
    +
+ +

Description

+ +

The Browsing directive controls whether or not network printer +browsing is enabled. The default setting is On. + +

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

+ + +

DataDir

+
+ +

Examples

+ +
    +DataDir /usr/share/cups
    +
+ +

Description

+ +

The DataDir directive sets the directory to use for data +files. + + +

DefaultCharset

+
+ +

Examples

+ +
    +DefaultCharset utf-8
    +DefaultCharset iso-8859-1
    +DefaultCharset windows-1251
    +
+ +

Description

+ +

The DefaultCharset directive sets the default character set +to use for client connections. The default character set is +utf-8 but is overridden by the character set for the language +specified by the client or the DefaultLanguage directive. + + +

DefaultLanguage

+
+ +

Examples

+ +
    +DefaultLanguage de
    +DefaultLanguage en
    +DefaultLanguage es
    +DefaultLanguage fr
    +DefaultLanguage it
    +
+ +

Description

+ +

The DefaultLanguage directive specifies the default language +to use for client connections. Setting the default language also sets the +default character set if a language localization file exists for it. The +default language is "en" for English. + + +

Deny

+
+ +

Examples

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

Description

+ +

The Deny directive specifies a hostname, IP address, or +network that is allowed access to the server. 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: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
mmnetmaskmmnetmask
00.0.0.08255.0.0.0
1128.0.0.016255.255.0.0
2192.0.0.024255.255.255.0
......32255.255.255.255
+ +

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

DocumentRoot

+
+ +

Examples

+ +
    +DocumentRoot /usr/share/doc/cups
    +DocumentRoot /foo/bar/doc/cups
    +
+ +

Description

+ +

The DocumentRoot directive specifies the location of +web content for the HTTP server in CUPS. If an absolute path is not +specified then it is assumed to be relative to the +ServerRoot directory. The +default directory is /usr/share/doc/cups. + +

Documents are first looked up in a sub-directory for the primary +language requested by the client (e.g. /usr/share/doc/cups/fr/...) +and then directly under the DocumentRoot directory +(e.g. /usr/share/doc/cups/...), so it is possible to localize +the web content by providing subdirectories for each language needed. + + +

ErrorLog

+
+ +

Examples

+ +
    +ErrorLog /var/log/cups/error_log
    +ErrorLog /var/log/cups/error_log-%s
    +ErrorLog syslog
    +
+ +

Description

+ +

The ErrorLog directive sets the name of the error log +file. If the filename is not absolute then it is assumed to be relative +to the ServerRoot directory. The +default error log file is /var/log/cups/error_log. + +

The server name can be included in the filename by using +%s in the name. + +

The special name "syslog" can be used to send the error information +to the system log instead of a plain file. + + +

FilterLimit

+
+ +

Examples

+ +
    +FilterLimit 0
    +FilterLimit 200
    +FilterLimit 1000
    +
+ +

Description

+ +

The FilterLimit directive sets the maximum cost +of all running job filters. It can be used to limit the number +of filter programs that are run on a server to minimize disk, +memory, and CPU resource problems. A limit of 0 disables filter +limiting. + +

An average print to a non-PostScript printer needs a filter +limit of about 200. A PostScript printer needs about half that +(100). Setting the limit below these thresholds will effectively +limit the scheduler to printing a single job at any time. + +

The default limit is 0. + + +

Group

+
+ +

Examples

+ +
    +Group sys
    +Group system
    +Group root
    +
+ +

Description

+ +

The Group directive specifies the UNIX group that +filter and CGI programs run as. The default group is sys, +system, or root depending on the operating +system. + + +

HostNameLookups

+
+ +

Examples

+ +
    +HostNameLookups On
    +HostNameLookups Off
    +
+ +

Description

+ +

The HostNameLookups directive controls whether or not +CUPS looks up the hostname for connecting clients. The default is +Off to avoid the potential server performance problems +with hostname lookups. Turn this option On only if +absolutely required. + + +

ImplicitClasses

+
+ +

Examples

+ +
    +ImplicitClasses On
    +ImplicitClasses Off
    +
+ +

Description

+ +

The ImplicitClasses directive controls whether implicit +classes are created based upon the available network printers and classes. +The default setting is On but is automatically turned +Off if Browsing is +turned Off. + + +

KeepAlive

+
+ +

Examples

+ +
    +KeepAlive On
    +KeepAlive Off
    +
+ +

Description

+ +

The KeepAlive directive controls whether or not to support +persistent HTTP connections. The default is On. + +

HTTP/1.1 clients automatically support persistent connections, while +HTTP/1.0 clients must specifically request them using the +Keep-Alive attribute in the Connection: +field of each request. + + +

KeepAliveTimeout

+
+ +

Examples

+ +
    +KeepAliveTimeout 60
    +KeepAliveTimeout 30
    +
+ +

Description

+ +

The KeepAliveTimeout directive controls how long a +persistent HTTP connection will remain open after the last request. The +default is 60 seconds. + + +

Listen

+
+ +

Examples

+ +
    +Listen 127.0.0.1:631
    +Listen 192.0.2.1:631
    +
+ +

Description

+ +

The Listen directive specifies a network address and port +to listen for connections. Multiple Listen directives can be +provided to listen on multiple addresses. + +

Description

+ +

The Listen directive is similar to the +Port directive but allows you to restrict +access to specific interfaces or networks. + + +

Location

+
+ +

Examples

+ +
    +<Location />
    +...
    +</Location>
    +
    +<Location /admin>
    +...
    +</Location>
    +
    +<Location /printers/name>
    +...
    +</Location>
    +
+ +

Description

+ +

The Location directive specifies access control and +authentication options for the specified HTTP resource or path. More +information can be found later in this chapter in +"Printing System Security". + + +

LogLevel

+
+ +

Examples

+ +
    +LogLevel debug
    +LogLevel error
    +LogLevel info
    +LogLevel none
    +LogLevel warn
    +
+ +

Description

+ +

The LogLevel directive specifies the level of logging +for the ErrorLog file. The +following values are recognized: + +

    + +
  • debug - Log everything. + +
  • info - Log all requests and state changes (default). + +
  • warn - Log errors and warnings. + +
  • error - Log only errors. + +
  • none - Log nothing. + +
+ + +

MaxClients

+
+ +

Examples

+ +
    +MaxClients 100
    +MaxClients 1024
    +
+ +

Description

+ +

The MaxClients directive controls the maximum number of +simultaneous clients that will be allowed by the server. The default is +100 clients. + +

+ + + +
+ NOTE: + +

Since each print job requires a file descriptor for the + status pipe, the CUPS server internally limits the + MaxClients value to 1/3 of the available file descriptors + to avoid possible problems when printing large numbers of jobs. +

+ + +

MaxJobs

+
+ +

Examples

+ +
    +MaxJobs 100
    +MaxJobs 9999
    +MaxJobs 0
    +
+ +

Description

+ +

The MaxJobs directive controls the maximum number of jobs +that are kept in memory. Once the number of jobs reaches the limit, the +oldest completed job is automatically purged from the system to make room +for the new one. If all of the known jobs are still pending or active then +the new job will be rejected. + +

Setting the maximum size to 0 disables this functionality. The default +setting is 0. + + +

MaxLogSize

+
+ +

Examples

+ +
    +MaxLogSize 1048576
    +MaxLogSize 1m
    +MaxLogSize 0
    +
+ +

Description

+ +

The MaxLogSize directive controls the maximum size of each +log file. Once a log file reaches or exceeds the maximum size it is closed +and renamed to filename.O. This allows you to rotate the logs +automatically. The default size is 1048576 bytes (1MB). + +

Setting the maximum size to 0 disables log rotation. + + +

MaxRequestSize

+
+ +

Examples

+ +
    +MaxRequestSize 10485760
    +MaxRequestSize 10m
    +MaxRequestSize 0
    +
+ +

Description

+ +

The MaxRequestSize directive controls the maximum size of +print files, IPP requests, and HTML form data in HTTP POST requests. The +default limit is 0 which disables the limit check. + + +

Order

+
+ +

Examples

+ +
    +Order Allow,Deny
    +Order Deny,Allow
    +
+ +

Description

+ +

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

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

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

PageLog

+
+ +

Examples

+ +
    +PageLog /var/log/cups/page_log
    +PageLog /var/log/cups/page_log-%s
    +PageLog syslog
    +
+ +

Description

+ +

The PageLog directive sets the name of the page log +file. If the filename is not absolute then it is assumed to be relative +to the ServerRoot directory. The +default page log file is /var/log/cups/page_log. + +

The server name can be included in the filename by using +%s in the name. + +

The special name "syslog" can be used to send the page information +to the system log instead of a plain file. + + +

Port

+
+ +

Examples

+ +
    +Port 631
    +Port 80
    +
+ +

Description

+ +

The Port directive specifies a port to listen on. +Multiple Port lines can be specified to listen on multiple +ports. The default port is 631. + +

Description

+ +

The Port directive will listen for connections on all +network interfaces. To limit connections to a single interface use the +Listen directive with the interface +address. + + +

PreserveJobHistory

+
+ +

Examples

+ +
    +PreserveJobHistory On
    +PreserveJobHistory Off
    +
+ +

Description

+ +

The PreserveJobHistory directive controls whether +the history of completed, cancelled, or aborted print jobs is stored +on disk. + +

A value of On (the default) preserves job information +until the administrator purges it with the cancel +command. + +

A value of Off removes the job information as soon as +each job is completed, cancelled, or aborted. + + +

PreserveJobFiles

+
+ +

Examples

+ +
    +PreserveJobFiles On
    +PreserveJobFiles Off
    +
+ +

Description

+ +

The PreserveJobFiles directive controls whether the +document files of completed, cancelled, or aborted print jobs are +stored on disk. + +

A value of On preserves job files until the +administrator purges them with the cancel command. Jobs +can be restarted (and reprinted) as desired until they are purged. + +

A value of Off (the default) removes the job files as +soon as each job is completed, cancelled, or aborted. + + +

Printcap

+
+ +

Examples

+ +
    +Printcap
    +Printcap /etc/printcap
    +
+ +

Description

+ +

The Printcap directive controls whether or not a +printcap file is automatically generated and updated with a list +of available printers. If specified with no value, then no +printcap file will be generated. The default is to generate a +file named /etc/printcap. + +

When a filename is specified (e.g. /etc/printcap), the +printcap file is written whenever a printer is added or removed. The +printcap file can then be used by applications that are hardcoded to +look at the printcap file for the available printers. + + +

RemoteRoot

+
+ +

Examples

+ +
    +RemoteRoot remroot
    +RemoteRoot root
    +
+ +

Description

+ +

The RemoteRoot directive sets the username for +unauthenticated root requests from remote hosts. The default +username is remroot. Setting RemoteRoot +to root effectively disables this security mechanism. + + +

RequestRoot

+
+ +

Examples

+ +
    +RequestRoot /var/spool/cups
    +RequestRoot /foo/bar/spool/cups
    +
+ +

Description

+ +

The RequestRoot directive sets the directory for +incoming IPP requests and HTML forms. If an absolute path is not +provided then it is assumed to be relative to the +ServerRoot directory. The +default request directory is /var/spool/cups. + + +

RIPCache

+
+ +

Examples

+ +
    +RIPCache 8m
    +RIPCache 1g
    +RIPCache 2048k
    +
+ +

Description

+ +

The RIPCache directive sets the size of the memory +cache used by Raster Image Processor ("RIP") filters such as +imagetoraster and pstoraster. The size can +be suffixed with a "k" for kilobytes, "m" for megabytes, or +"g" for gigabytes. The default cache size is "8m", or 8 megabytes. + + +

ServerAdmin

+
+ +

Examples

+ +
    +ServerAdmin user@host
    +ServerAdmin root@foo.bar.com
    +
+ +

Description

+ +

The ServerAdmin directive identifies the email address for the +administrator on the system. By default the administrator email address is +root@server, where server is the server name. + + +

ServerBin

+
+ +

Examples

+ +
    +ServerBin /usr/lib/cups
    +ServerBin /foo/bar/lib/cups
    +
+ +

Description

+ +

The ServerBin directive sets the directory for +server-run executables. If an absolute path is not provided then it is +assumed to be relative to the +ServerRoot directory. The +default executable directory is /usr/lib/cups or +/usr/lib32/cups (IRIX 6.5). + + +

ServerName

+
+ +

Examples

+ +
    +ServerName foo.domain.com
    +ServerName myserver.domain.com
    +
+ +

Description

+ +

The ServerName directive specifies the hostname that is +reported to clients. By default the server name is the hostname. + + +

ServerRoot

+
+ +

Examples

+ +
    +ServerRoot /etc/cups
    +ServerRoot /foo/bar/cups
    +
+ +

Description

+ +

The ServerRoot directive specifies the absolute path to +the server configuration and state files. It is also used to resolve +relative paths in the cupsd.conf file. The default server +directory is /etc/cups. + + +

SystemGroup

+
+ +

Examples

+ +
    +SystemGroup sys
    +SystemGroup system
    +SystemGroup root
    +
+ +

Description

+ +

The SystemGroup directive specifies the system +administration group for System authentication. More +information can be found later in this chapter in +"Printing System Security". + + +

TempDir

+
+ +

Examples

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

Description

+ +

The TempDir directive specifies an absolute path for +the directory to use for temporary files. The default directory is +/var/tmp. + +

Temporary directories must be world-writable and should have the +"sticky" permission bit enabled so that other users cannot delete +filter temporary files. The following commands will create an +appropriate temporary directory called /foo/bar/tmp: + +

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

Timeout

+
+ +

Examples

+ +
    +Timeout 300
    +Timeout 90
    +
+ +

Description

+ +

The Timeout directive controls the amount of time to +wait before an active HTTP or IPP request times out. The default +timeout is 300 seconds. + + +

User

+
+ +

Examples

+ +
    +User lp
    +User guest
    +
+ +

Description

+ +

The User directive specifies the UNIX user that +filter and CGI programs run as. The default user is lp. + + +

Printing System Security

+ +

CUPS provides support for address, certificate, and password (Basic +and Digest) based authentication and access control. Certificate and +password authentication provide ways to limit access to individual +people or groups. + +

Address based access control allows you to limit access to specific +systems, networks, or domains. While this does not provide authentication, +it does allow you to limit the potential users of your system efficiently. + +

CUPS maintains a list of locations that have access control and/or +authentication enabled. Locations are specified using the +Location directive: + +

+ +

Locations generally follow the directory structure of the +DocumentRoot directory, however +CUPS does have several virtual locations for administration, classes, jobs, +and printers: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LocationDescription
/adminThe path for all administration operations.
/classesThe path for all classes.
/classes/nameThe resource for class name.
/jobsThe path for all jobs.
/jobs/idThe resource for job id.
/printersThe path for all printers.
/printers/nameThe path for printer name.
/printers/name.ppdThe PPD file path for printer name.
+ +

Authentication Using Certificates

+ +

CUPS supports a local certificate-based authentication scheme that +can be used in place of Basic or Digest +authentication by clients connecting through the localhost +interface. Certificate authentication is not supported or allowed from +clients on any other interface. + +

Certificates are 128-bit random numbers that refer to an internal +authentication record in the server. A client connecting via the +localhost interface sends a request with an +authorization header of: + +

    +Authorization: Local 0123456789ABCDEF0123456789ABCDEF
    +
+ +

The server then looks up the local certificate and authenticates +using the username associated with it. + +

Certificates are generated by the server automatically and stored in +the /etc/cups/certs directory using the process ID of the +CGI program started by the server. Certificate files are only readable +by the User and +Group defined in the +cupsd.conf file. When the CGI program ends the certificate +is removed and invalidated automatically. + +

The special file /etc/cups/certs/0 defines the root +certificate which can be used by any client running as the super-user +or another user that is part of the group defined by the +SystemGroup directive. The +root certificate is automatically regenerated every 5 minutes. + +

Using Basic Authentication

+ +

Basic authentication uses UNIX users and passwords to authenticate +access to resources such as printers and classes, and to limit access +to administrative functions. + +

+ + + +
+ NOTE: + +

Basic authentication sends the username and password Base64 + encoded from the client to the server, so it offers no + protection against eavesdropping. This means that a malicious + user can monitor network packets and discover valid users and + passwords that could result in a serious compromise in network + security. Use Basic authentication with extreme care. +

+ +

The CUPS implementation of Basic authentication does not allow access +through user accounts without a password. If you try to authenticate +using an account without a password, your access will be immediately +blocked. + +

Once a valid username and password is authenticated by CUPS, any +additional group membership requirements are checked. + +

+ + + +
+ NOTE: + +

The root user is considered by CUPS to be a member of every + group. +

+ + +

Use the AuthType directive to enable Basic authentication: + +

    +AuthType Basic
    +
+ + +

Using Digest Authentication

+ +

Digest authentication uses users and passwords defined in the +/etc/cups/passwd.md5 file to authenticate access to +resources such as printers and classes, and to limit access to +administrative functions. + +

+ + + +
+ NOTE: + +

Unlike Basic authentication, Digest passes the MD5 sum + (basically a complicated checksum) of the username and password + instead of the strings themselves. Also, Digest authentication + does not use the UNIX password file, so if an attacker does + discover the original password it is less likely to result in a + serious security problem so long as you use a different UNIX + password than the corresponding Digest password. + +

The current CUPS implementation of Digest authentication + uses the client's hostname or IP address for the "nonce" value. + The nonce value is an additional string added to the username + and password to make guessing the password more difficult. The + server checks that the nonce value matches the client's hostname + or address and rejects the MD5 sum if it doesn't. Future versions + of CUPS will support Digest "session" authentication which adds + the request data to the MD5 sum, providing even better + authentication and security. + +

Digest authentication does not guarantee that an attacker + cannot gain unauthorized access, but it is safer than Basic + authentication and should be used in place of Basic + authentication whenever possible. Support for Digest + authentication in web browsers is not yet universally + available. +

+ + +

The lppasswd(1) command is used to add, change, or +remove accounts from the passwd.md5 file. To add a +user to the default system group, type: + +

    +lppasswd -a user ENTER
    +Password: (password) ENTER [password is not echoed]
    +Password again: (password) ENTER [password is not echoed]
    +
+ + +

Once added, a user can change his/her password by typing: + +

    +lppasswd ENTER
    +Old password: (password) ENTER [password is not echoed]
    +Password: (password) ENTER [password is not echoed]
    +Password again: (password) ENTER [password is not echoed]
    +
+ + +

To remove a user from the password file, type: + +

    +lppasswd -x user ENTER
    +
+ +

Once a valid username and password is authenticated by CUPS, any +additional group membership requirements are checked. + +

+ + + +
+ NOTE: + +

The root user is considered by CUPS to be a member of every + group. +

+ +

Use the AuthType directive to enable Digest authentication: + +

    +AuthType Digest
    +
+ +

System and Group Authentication

+ +

The AuthClass directive controls +the level of authentication to perform. System and +Group authentication extend the normal user-based authentication +to require membership in a UNIX group. For System authentication +each user must belong to the sys, system, or +root group; the actual group depends on the operating system. + +

For Group authentication each user must belong to the +group named by the AuthGroupName +directive: + +

    +<Location /path>
    +AuthType Digest
    +AuthClass Group
    +AuthGroupName mygroup
    +</Location>
    +
+ +

The named group must be a valid UNIX user group, usually defined in the +/etc/group or /etc/netgroup files. Additionally, when +using Digest authentication you need to create user accounts with the named +group: + +

    +lppasswd -g mygroup -a user ENTER
    +Password: (password) ENTER [password is not echoed]
    +Password again: (password) ENTER [password is not echoed]
    +
+ + +

Printer Accounting

+ +

ESP Print Pro maintains a log of all accesses, errors, and +pages that are printed. The log files are normally stored in the +/var/log/cups directory. You can change this by +editing the /etc/cups/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 enabled the HostNameLookups +directive in the cupsd.conf file. + +

The group field always contains "-" in CUPS. + +

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 local time +and is in the format: + +

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

where ZZZZ is the timezone offset in hours and minutes from Greenwich +Mean Time (a.k.a. GMT a.k.a. ZULU.) + +

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 +that was 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 job-billing
    +
    +DeskJet root 2 [20/May/1999:19:21:05 +0000] 1 0 acme-123
    +
+ +

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

The job-billing field contains a copy of the +job-billing attribute provided with the IPP +create-job or print-job requests or "-" if none +was provided. + + +

File Typing and Filtering

+ +

CUPS provides a MIME-based file typing and filtering mechanism to +convert files to a printable format for each printer. On startup the +CUPS server reads MIME database files from the /etc/cups +directory (or a directory specified by the +ServerRoot directive) to build +a file type and conversion database in memory. These database files are +plain ASCII text and can be edited with your favorite text editor. + +

The mime.types and mime.convs files define the +standard file types and filters that are available on the system. + +

mime.types

+ +

The mime.types file 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 rule +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 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 + +
  • contains(offset,range,"string") - True if the + range of bytes contains the 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 + +
+ +

All numeric values can be in decimal (123), octal (0123), or hexadecimal +(0x123) as desired. + + +

Strings can be in quotes, all by themselves, as a string +of hexadecimal values, or some combination: + +

    +"string"
    +'string'
    +string
    +<737472696e67>
    +<7374>ring
    +
+ +

As shown in the text/html example, rules can continue on +multiple lines using the backslash (\) character. A more complex example is +the image/jpeg rules: + +

    +image/jpeg      jpeg jpg jpe string(0,<FFD8FF>) &&\
    +                (char(3,0xe0) char(3,0xe1) char(3,0xe2) char(3,0xe3)\
    +                 char(3,0xe4) char(3,0xe5) char(3,0xe6) char(3,0xe7)\
    +                 char(3,0xe8) char(3,0xe9) char(3,0xea) char(3,0xeb)\
    +                 char(3,0xec) char(3,0xed) char(3,0xee) char(3,0xef))
    +
+ +

This rule states that any file with an extension of +.jpeg, .jpg, or .jpe is a JPEG file. +In addition, any file starting with the hexadecimal string +<FFD8FF> (JPEG Start-Of-Image) followed by a +character between and including 0xe0 and 0xef +(JPEG APPn markers) is also a JPEG file. + +

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 Description and CUPS +Software Programmers Manual: + +

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

Adding Filetypes and Filters

+ +

Adding a new file type or filter is fairly straight-forward. Rather +than adding the new type and filter to the mime.types and +mime.convs files which are overwritten when you upgrade to a +new version of CUPS, you simple need to create new files with +.types and .convs extensions in the +/etc/cups directory. We recommend that you use the product +or format name, e.g.: + +

    +myproduct.types
    +myproduct.convs
    +
+ +

If you are providing a filter for a common file format or printer, +add the company or author name: + +

    +acme-msword.types
    +acme.msword.convs
    +
+ +

This will help to prevent name collisions if you install many +different file types and filters. + +

Once you choose the names for these files, create them using your +favorite text editor as described earlier in this chapter. Once you +have created the files, restart the cupsd process as +described earlier in "Restarting the CUPS Server". + +

Printer Drivers and PPD Files

+ +

Most CUPS printer drivers utilize one or more printer-specific filters +and a PPD file for each printer model. Printer driver filters are registered +via the PPD file using cupsFilter attributes: + +

    +*cupsFilter: "application/vnd.cups-raster 0 rastertohp"
    +
+ +

The filter is specified using the source file type only; the destination +file type is assumed to be printer/name - suitable for sending +to the printer. + +

Writing Your Own Filter or Printer Driver

+ +

CUPS supports an unlimited number of file formats and filters, and can +handle any printer. If you'd like to write a filter or printer driver for +your favorite file format or printer, consult the CUPS Software Programmers +Manual for step-by-step instructions. + + +

7 - Printing with Other Systems

+ +

This chapter describes how to print from client systems that use the +LPD, Mac OS, or Windows printing protocols. + +

The Basics

+ +

CUPS is based on the IPP protocol, so any system that supports IPP +can send jobs to and receive jobs from CUPS automatically. However, not +all systems support IPP yet. This chapter will show you how to connect +these systems to your CUPS server, either to accept jobs from your +server for printing, or to send jobs to your server. + +

Printing from LPD Clients

+ +

CUPS supports limited functionality for LPD-based clients. With LPD you can +print files to specific printers, list the queue status, and so forth. However, +the automatic client configuration and printer options are not supported by +the LPD protocol, so you must manually configure each client for the printers +it needs to access. + +

The cups-lpd(8) program provides support for LPD clients. +To enable LPD support on your server, edit the /etc/inetd.conf +file and add a line reading: + +

    +printer stream tcp nowait lp /usr/lib/cups/daemon/cups-lpd cups-lpd
    +
+ +

The path to the cups-lpd may vary depending on your +installation. + +

Once you have added this line, send the inetd(8) process +a HUP signal or reboot the system: + +

    +killall -HUP inetd ENTER [IRIX and some versions of Linux]
    +kill -HUP pid ENTER [Others]
    +reboot ENTER [For all systems if the HUP signal fails]
    +
+ +

Printing to LPD Servers

+ +

CUPS provides the lpd backend for printing to LPD-based +servers and printers. Use a device URI of lpd://server/name +to print to a printer on an LPD server, where server +is the hostname or IP address of the server and name is +the queue name. + +

Microsoft Windows NT provides an LPD service under the name "TCP/IP +Printing Services". To enable LPD printing on NT, open the "Services" +control panel, select the "TCP/IP Printing Services" service, and click +on the "Start" button. Any shared printer will then be available via +the LPD protocol. + +

Printing from Mac OS Clients

+ +

CUPS does not provide Mac OS support directly. However, there are several +free and commercial software packages that do. + +

Columbia Appletalk Package (CAP)

+ +

Because the CAP LaserWriter server (lwsrv(8)) does +not support specification of PPD files, we do not recommend that you +use CAP with CUPS. However, you can run the lpsrv program +for limited printing with the command: + +

    +lwsrv -n "Name" -p printer -a /usr/lib/adicts -f /usr/lib/LW+Fonts
    +
+ +

where Name is the name you want to use when sharing the +printer, and printer is the name of the CUPS print queue. + + +

XINET KA/Spool

+ +

To use your system as a print server for Mac OS clients, +configure each printer using a papserver(8) in the +/usr/adm/appletalk/services file, specifying the +corresponding PPD file in the /etc/cups/ppd directory for +each printer. For a printer named MyPrinter the entry +would look like: + +

    +/usr/etc/appletalk/papserver -I -L -P /etc/cups/ppd/MyPrinter.ppd \
    +"Printer Description" MyPrinter
    +
+ +
+ + + +
+ NOTE: + +

Enter the text above on a single line without the backslash (\) + character. +

+ +

NetATalk

+ +

To use your system as a print server for Mac OS clients, +configure each printer in the papd.conf file, specifying the +corresponding PPD file in the /etc/cups/ppd directory for +each printer. For a printer named MyPrinter the entry +would look like: + +

    +Printer Description:MyPrinter@MyServer:\
    +        :pr=|/usr/bin/lp -d MyPrinter:\
    +        :op=daemon:\
    +        :pd=/etc/cups/ppd/MyPrinter.ppd
    +
+ + + +

Printing to Mac OS Servers

+ +

CUPS currently does not provide a backend to communicate with a Mac OS +server. However, you can write and install a short shell script +in the /usr/lib/cups/backend directory that sends a print file +using the appropriate command. The following is a short script that will +run the papif command provided with CAP. + +

After copying this script to /usr/lib/cups/backend/cap, +specify a device URI of cap://server/printer to use this +backend with a print queue. + + +

    +
    +"/usr/lib/cups/backend/cap"
    +#!/bin/sh
    +#
    +# Usage: cap job user title copies options [filename]
    +#
    +
    +# No arguments means show available devices...
    +
    +if test ${#argv} = 0; then
    +	echo "network cap \"Unknown\" \"Mac OS Printer via CAP\""
    +	exit 0
    +fi
    +
    +# Collect arguments...
    +
    +user=$2
    +copies=$4
    +
    +if test ${#argv} = 5; then
    +	# Get print file from stdin; copies have already been handled...
    +	file=/var/tmp/$$.prn
    +	copies=1
    +	cat > $file
    +else
    +	# Print file is on command-line...
    +	file=$6
    +fi
    +
    +# Create a dummy cap.printers file for this printer based
    +# upon a device URI of "cap://server/printer"...
    +
    +echo $PRINTER/$DEVICE_URI | \
    +	awk -F/ '{print $1 "=" $5 ":LaserWriter@" $4}' > /var/tmp/$$.cap
    +
    +CAPPRINTERS=/var/tmp/$$.cap; export CAPPRINTERS
    +
    +# Send the file to the printer, once for each copy. This assumes that you
    +# have properly initialized the cap.printers file...
    +
    +while [ $copies -gt 0 ]; do
    +	papif -n $user < $file
    +
    +        copies=`expr $copies - 1`
    +done
    +
    +# Remove any temporary files...
    +if test ${#argv} = 5; then
    +	/bin/rm -f $file
    +fi
    +
    +/bin/rm -f /var/tmp/$$.cap
    +
    +exit 0
    +
+ + +

Printing from Windows Clients

+ +

While CUPS does not provide Windows support directly, the free +SAMBA software package does. SAMBA version 2.0.6 is the first release +of SAMBA that supports CUPS. You can download SAMBA from: + +

+ +

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

Printing to Windows Servers

+ +

CUPS can print to Windows servers in one of two ways. The first way uses +the LPD protocol on the CUPS system and the "TCP/IP Printing Services" on +the Windows system. You can find out more about this configuration in the +LPD section earlier in this chapter. + +

The second way is through the Microsoft Server Message Block ("SMB") +protocol. Support for this protocol is provided with the free SAMBA +software package. You can download SAMBA from: + +

+ +

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

    +ln -s `which smbspool` /usr/lib/cups/backend/smb ENTER
    +
+ +

The smbspool(1) program is provided with SAMBA starting +with SAMBA 2.0.6. Once you have made the link you can configure your +printers with one of the following device URIs: + +

    +smb://workgroup/server/sharename
    +smb://server/sharename
    +smb://user:pass@workgroup/server/sharename
    +smb://user:pass@server/sharename
    +
+ +

The workgroup name need only be specified if your +system is using a different workgroup. The user:pass +strings are required when printing to Windows NT servers or to shares +with passwords enabled under Windows 95 and 98. + + +

A - Software License Agreement

+ + + + +

B - Common Network Settings

+ +

This appendix covers many of the popular TCP/IP network interfaces +and printer servers available on the market today. + +

Configuring a Network Interface

+ +

When you first install a network printer or print server on your +LAN, you need to set the Internet Protocol ("IP") address. On most +higher-end "workgroup" printers, you can set the address through the +printer control panel. However, in most cases you will want to assign +the addresses remotely from your workstation. This makes administration +a bit easier and avoids assigning duplicate addresses accidentally. + +

To setup your printer or print server for remote address assignment, +you'll need the Ethernet Media Access Control ("MAC") address, also +sometimes called a node address, and the IP address you want to use for +the device. The Ethernet MAC address can often be found on the printer +test page or bottom of the print server. + + +

Configuring the IP Address Using ARP

+ +

The easiest way to set the IP address of a network device is to use +the arp(8) command. The arp sends an Address +Resolution Protocol ("ARP") packet to the specified Ethernet MAC address, +setting the network device's IP address: + +

    +arp -s ip-address ethernet-address ENTER
    +arp -s host.domain.com 08:00:69:00:12:34 ENTER
    +arp -s 192.0.2.2 08:00:69:00:12:34 ENTER
    +
+ +

Configuring the IP Address Using RARP

+ +

The most flexible way to remotely assign IP addresses under UNIX +is through the Reverse Address Resolution Protocol ("RARP"). RARP +allows a network device to request an IP address using its Ethernet +MAC address, and one or more RARP servers on the network will +respond with an ARP packet with the IP address the device can use. + +

RARP should be used when you have to manage many printers or print +servers, or when you have a network device that does not remember its +IP address after a power cycle. If you just have a single printer or +print server, the arp command is the way to go. + +

Some UNIX operating systems use a program called +rarpd(8) to manage RARP. Others, like Linux, support this +protocol in the kernel. For systems that provide the rarpd +program you will need to start it before RARP lookups will work: + +

    +rarpd ENTER
    +
+ +

Under IRIX you can enable this functionality by default using: + +

    +chkconfig rarpd on ENTER
    +
+ +

Both the rarpd program and kernel RARP support read a +list of Ethernet and IP addresses from the file /etc/ethers. +Each line contains the Ethernet address (colon delimited) followed by +an IP address or hostname like: + +

    +08:00:69:00:12:34 myprinter.mydomain.com
    +08:00:69:00:12:34 192.0.2.2
    +
+ +

Add a line to this file and cycle the power on the printer or print +server to set its address. + + +

Configuring the IP Address Using BOOTP

+ +

The BOOTP protocol is used when you need to provide additional information +such as the location of a configuration file to the network interface. Using +the standard bootpd(8) program supplied with UNIX you simply need to +add a line to the /etc/bootptab file; for IRIX: + +

    +myprinter 08:00:69:00:12:34 192.0.2.2 myprinter.boot
    +
+ + +

Newer versions of bootpd use a different format: + +

    +myprinter:ha=080069001234:ip=192.0.2.2:t144=myprinter.boot
    +
+ +

The myprinter.boot file resides in the /usr/local/boot +directory by default. If you do not need to provide a boot file you may leave +the last part of the line blank. + + +

+ + + +
+ NOTE: + +

Some versions of UNIX do not enable the BOOTP service by + default. The /etc/inetd.conf usually contains a + line for the BOOTP service that can be uncommented if + needed. +

+ +

Verifying the Printer Connection

+ +

To test that the IP address has been successfully assigned and that the +printer is properly connected to your LAN, type: + +

    +ping ip-address ENTER
    +
+ +

If the connection is working properly you will see something like: + +

    +ping myprinter ENTER
    +PING myprinter (192.0.2.2): 56 data bytes
    +64 bytes from 192.0.2.2: icmp_seq=0 ttl=15 time=5 ms
    +64 bytes from 192.0.2.2: icmp_seq=1 ttl=15 time=3 ms
    +64 bytes from 192.0.2.2: icmp_seq=2 ttl=15 time=3 ms
    +64 bytes from 192.0.2.2: icmp_seq=3 ttl=15 time=3 ms
    +
+ +

If not, verify that the printer or print server is connected to the +LAN, it is powered on, the LAN cabling is good, and the IP address is +set correctly. You can usually see the current IP address and network +status by printing a configuration or test page on the device. + + +

Common Network Interface Settings

+ +

Once you have set the IP address you can access the printer or print +server using the ipp, lpd, or +socket backends. The following is a list of common network +interfaces and printer servers and the settings you should use with +CUPS: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Model/ManufacturerDevice URI(s)
Apple LaserWriterlpd://address/PASSTHRU
Axis w/o IPP
+ (see directions)
socket://address:9100
+ socket://address:9101
+ socket://address:9102
Axis w/IPPipp://address/LPT1
+ ipp://address/LPT2
+ ipp://address/COM1
Castelle LANpressTMlpd://address/pr1
+ lpd://address/pr2
+ lpd://address/pr3
DPI NETPrintlpd://address/pr1
+ lpd://address/pr2
+ lpd://address/pr3
EFI® Fiery® RIPlpd://address/print
EPSON® Multiprotocol Ethernet Interface Boardsocket://address
Extended System ExtendNETlpd://address/pr1
+ lpd://address/pr2
+ lpd://address/pr3
Hewlett Packard JetDirect w/o IPPsocket://address:9100
+ socket://address:9101
+ socket://address:9102
Hewlett Packard JetDirect w/IPPipp://address/ipp
+ ipp://address/ipp/port1
+ ipp://address/ipp/port2
+ ipp://address/ipp/port3
Intel® NetportExpress XL, PRO/100lpd://address/LPT1_PASSTHRU
+ lpd://address/LPT2_PASSTHRU
+ lpd://address/COM1_PASSTHRU
LexmarkTM MarkNetlpd://address/ps
Linksys EtherFast®
+ (see directions)
socket://address:4010
+ socket://address:4020
+ socket://address:4030
Kodak®lpd://address/ps
QMS® CrownNetTMlpd://address/ps
Tektronix® PhaserShareTMsocket://address:9100
XEROX® 4512 NIClpd://address/PORT1
XEROX® XNIClpd://address/PASSTHRU
XEROX® (most others)socket://address:5503
+ +

Configuring Axis Print Servers

+ +

The Axis print servers can be configured using ARP, RARP, or BOOTP. +However, on models that do not provide IPP support an additional step +must be performed to configure the TCP/IP portion of the print server +for use with CUPS. + + +

Each print server contains a configuration file named +config that contains a list of network parameters used by +the server. To modify this file you must first download it from the +print server using the ftp(1) program: + +

    +ftp ip-address ENTER
    +Connected to ip-address.
    +220 Axis NPS ### FTP Printer Server V#.## MON DD YEAR ready.
    +ftp> user root ENTER
    +331 User name ok, need password
    +Password: pass ENTER (this is not echoed)
    +230 User logged in
    +ftp> get config ENTER
    +local: config remote: config
    +200 PORT command successful.
    +150 Opening data connection for config (192,0,2,2),
    +(mode ascii).
    +226 Transfer complete.
    +##### bytes received in #.## seconds (##### Kbytes/s)
    +ftp> quit ENTER
    +221 Goodbye.
    +
+ + +

Next, edit the file with your favorite text editor and locate the +lines beginning with: + +

    +RTN_OPT.     : YES
    +RTEL_PR1.    : 0
    +RTEL_PR2.    : 0
    +RTEL_PR3.    : 0
    +RTEL_PR4.    : 0
    +RTEL_PR5.    : 0
    +RTEL_PR6.    : 0
    +RTEL_PR7.    : 0
    +RTEL_PR8.    : 0
    +
+ + +Change the RTN_OPT line to read: + +
    +RTN_OPT.     : NO
    +
+ + +

This disables the Reverse TELNET protocol and enables the standard +TELNET protocol on the print server. Next, assign a port number for +each parallel and serial port on the server as follows: + +

    +RTEL_PR1.    : 9100
    +RTEL_PR2.    : 9101
    +RTEL_PR3.    : 9102
    +RTEL_PR4.    : 9103
    +RTEL_PR5.    : 9104
    +RTEL_PR6.    : 9105
    +RTEL_PR7.    : 9106
    +RTEL_PR8.    : 9107
    +
+ + +

This essentially makes the Axis print server look like a Hewlett +Packard JetDirect EX print server. Save the file and then upload the +new config file using the ftp command: + +

    +ftp ip-address ENTER
    +Connected to ip-address.
    +220 Axis NPS ### FTP Printer Server V#.## MON DD YEAR ready.
    +ftp> user root ENTER
    +331 User name ok, need password
    +Password: pass ENTER (this is not echoed)
    +230 User logged in
    +ftp> put config CONFIG ENTER
    +local: config remote: CONFIG
    +200 PORT command successful.
    +150 Opening data connection for config (192,0,2,2), (mode ascii).
    +226 Transfer complete.
    +##### bytes received in #.## seconds (##### Kbytes/s)
    +ftp> get hardreset ENTER
    +local: hardreset remote: hardreset
    +200 PORT command successful.
    +421 Axis NPS ### hard reset, closing connection.
    +ftp> quit ENTER
    +221 Goodbye.
    +
+ +

Your Axis print server is now ready for use! + +

Configuring Linksys Print Servers

+ +

The Linksys print servers can be configured using ARP, RARP, or +BOOTP. Like older Axis print servers, an additional step must be +performed to configure the TCP/IP portion of the print server for use +with CUPS. + + +

Each print server contains a configuration file named +CONFIG that contains a list of network parameters used by +the server. To modify this file you must first download it from the +print server using the ftp(1) program: + +

    +ftp -n ip-address ENTER
    +Connected to ip-address.
    +220 Print Server Ready.
    +Remote system type is Print.
    +ftp> get CONFIG ENTER
    +local: CONFIG remote: CONFIG
    +200 Command OK.
    +150 Open ASCII Mode Connection.
    +WARNING! 68 bare linefeeds received in ASCII mode
    +File may not have transferred correctly.
    +226 Transfer complete.
    +##### bytes received in #.## seconds (##### Kbytes/s)
    +ftp> quit ENTER
    +221 Goodbye.
    +
+ + +

Next, edit the file with your favorite text editor and locate the +lines beginning with: + +

    +0100 L1_PROUT:P1
    +0120 L2_PROUT:P1
    +0140 L3_PROUT:P1
    +
+ +

Change the port number for +each parallel and serial port on the server as follows: + +

    +0100 L1_PROUT:P1
    +0120 L2_PROUT:P2
    +0140 L3_PROUT:P3
    +
+ + +

This maps each virtual printer with a physical port. Save the file and then upload the +new CONFIG file using the ftp command: + +

    +ftp -n ip-address ENTER
    +Connected to ip-address.
    +220 Print Server Ready.
    +Remote system type is Print.
    +ftp> put CONFIG ENTER
    +local: CONFIG remote: CONFIG
    +200 Command OK.
    +150 Open ASCII Mode Connection.
    +226 Transfer complete.
    +##### bytes received in #.## seconds (##### Kbytes/s)
    +ftp> quit ENTER
    +221 Goodbye.
    +
+ +

Your Linksys print server is now ready for use! + + +

C - Printer Drivers

+ +

This appendix lists the printer drivers that are provided with CUPS. + +

Printer Drivers

+ +

CUPS includes the following printer drivers: + +

+ +

EPSON 9-pin Dot Matrix

+ +

The EPSON 9-pin Dot Matrix driver (epson9.ppd) supports +9-pin dot matrix printers that implement the ESC/P command set. It +provides 60x72, 120x72, and 240x72 DPI output in black only. + +

EPSON 24-pin Dot Matrix

+ +

The EPSON 24-pin Dot Matrix driver (epson9.ppd) supports +24-pin dot matrix printers that implement the ESC/P command set. It +provides 120x180, 180x180, 360x180, and 360x360 DPI output in black +only. + +

EPSON Stylus Color

+ +

The EPSON Stylus Color driver (stcolor.ppd) supports +EPSON Stylus Color printers that implement the ESC/P2 command set. It +provides 180, 360, and 720 DPI output in black and color (CMYK). + +

EPSON Stylus Photo

+ +

The EPSON Stylus Photo driver (stphoto.ppd) supports +EPSON Stylus Photo printers that implement the ESC/P2 command set. It +provides 180, 360, and 720 DPI output in black and color (CMYKcm). + +

HP DeskJet

+ +

The HP DeskJet driver (deskjet.ppd) supports HP DeskJet +printers that implement the PCL command set. It provides 150, 300, and +600 DPI output in black and color (CMYK). + +

The DeskJet printers that implement the HP-PPA command set (720C, +722C, 820C, and 1100C) are not supported due to a complete lack +of documentation and support from Hewlett Packard. + +

The duplexer provided with the HP DeskJet 900 series printers is also +not supported for similar reasons. + +

HP LaserJet

+ +

The HP LaserJet driver (laserjet.ppd) supports HP +LaserJet printers that implement the PCL command set. It provides 150, +300, and 600 DPI output in black only and supports the duplexer if +installed. + +

LaserJet printers that do not implement PCL (3100, 3150) are not +supported due to a complete lack of documentation and support from +Hewlett Packard. + + +

D - List of Files

+ +

This appendix lists the files and directories that are installed for +the Common UNIX Printing System. + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathnameDescription
/etc/cups/certs/The location of authentication certificate files for local + HTTP clients.
/etc/cups/classes.confThe printer classes configuration file for the scheduler.
/etc/cups/cupsd.confThe scheduler configuration file.
/etc/cups/interfaces/The location of System V interface scripts for printers.
/etc/cups/mime.convsThe list of standard file filters included with ESP Print Pro.
/etc/cups/mime.typesThe list of recognized file types for ESP Print Pro.
/etc/cups/ppd/The location of PostScript Printer Description ("PPD") files for + printers.
/etc/cups/printers.confThe printer configuration file for the scheduler.
/usr/bin/cancelThe System V cancel job(s) command.
/usr/bin/disableThe System V disable printer command.
/usr/bin/enableThe System V enable printer command.
/usr/bin/lpThe System V print command.
/usr/bin/lpoptionsSets user-defined printing options and defaults.
/usr/bin/lppasswdAdds, changes, or removes Digest password accounts.
/usr/bin/lpqThe Berkeley status command.
/usr/bin/lprThe Berkeley print command.
/usr/bin/lprmThe Berkeley cancel job(s) command.
/usr/bin/lpstatThe System V status command.
/usr/include/cups/CUPS API header files.
/usr/lib32/libcups.a
+ /usr/lib32/libcupsimage.a
Static libraries (IRIX 6.5)
/usr/lib/libcups.a
+ /usr/lib/libcupsimage.a
Static libraries (all others)
/usr/lib/libcups.sl.2
+ /usr/lib/libcupsimage.sl.2
Shared libraries (HP-UX)
/usr/lib32/libcups.so.2
+ /usr/lib32/libcupsimage.so.2
Shared libraries (IRIX 6.5)
/usr/lib/libcups.so.2
+ /usr/lib/libcupsimage.so.2
Shared libraries (all others)
/usr/lib/cups/backend/Backends for various types of printer connections.
/usr/lib/cups/cgi-bin/CGI programs for the scheduler.
/usr/lib/cups/daemon/Daemons for polling and LPD support.
/usr/lib/cups/filter/Filters for various types of files.
/usr/lib/locale/The location of language-specific message files. (System V)
/usr/lib/nls/msg/The location of language-specific message files. (Compaq Tru64 UNIX)
/usr/share/locale/The location of language-specific message files. (Linux, *BSD)
/usr/sbin/acceptThe accept-jobs command.
/usr/sbin/cupsdThe CUPS print scheduler.
/usr/sbin/lpadminThe System V printer administration tool.
/usr/sbin/lpcThe Berkeley printer administration tool.
/usr/sbin/lpinfoThe get-devices and get-ppds command.
/usr/sbin/lpmoveThe move-jobs command.
/usr/sbin/rejectThe reject-jobs command.
/usr/share/catman/a_man/
+ /usr/share/catman/u_man/
Man pages (IRIX)
/usr/share/man/Man pages (Compaq Tru64 UNIX, HP-UX, Solaris)
/usr/man/Man pages (all others)
/usr/share/cups/data/The location of filter data files.
/usr/share/cups/data/testprint.psThe PostScript test page file.
/usr/share/cups/fonts/The location of PostScript fonts for the PostScript RIP.
/usr/share/cups/model/The location of PostScript Printer Description ("PPD") files and + interface scripts that may be used to setup a printer queue.
/usr/share/cups/pstoraster/Other PostScript RIP initialization files.
/usr/share/cups/pstoraster/FontmapThe font mapping file (converts filenames to fontnames)
/usr/share/cups/templates/The location of HTML template files for the web interfaces.
/usr/share/doc/cups/Documentation and web page data for the scheduler.
/var/log/cups/The location of scheduler log files.
/var/spool/cups/The location of print files waiting to be printed.
+ + +

E - Troubleshooting Common Problems

+ +

This appendix covers some of the common problems first-time users +encounter when installing and configuring CUPS. + +

Commercial support for CUPS is available from Easy Software Products. +For more information please contact us at: + +

+ +

My Applications Don't See the Available Printers

+ +

Many applications read the /etc/printcap file to +get a list of available printers. + +

The default CUPS configuration does not create the +/etc/printcap file automatically. To enable automatic +creation and updating of this file, use the +Printcap directive described in +Chapter 6, "Printing System Management". + +

CUPS Doesn't Recognize My Username or Password!

+ +

CUPS will ask you for a UNIX username and password when you perform +printer administration tasks remotely or via a web browser. The default +configuration requires that you use the root username and +the corresponding password to authenticate the request. + +

CUPS does not allow you to authenticate an administration request +with an account that has no password for security reasons. If you do +not have a password on your root account then you won't be +able to add printers remotely or via the web interface! + + +

To disable password authentication you need to edit the +/etc/cups/cupsd.conf file and comment out the +lines reading: + +

    +AuthType Basic
    +AuthClass System
    +
+ +for the /admin location. Then restart the CUPS server as +described in Chapter 8, "Printing System +Management". + +
+ + + +
+ NOTE: + +

Disabling password checks will allow any local user to + change your printer and class configuration, but remote + administration from another machine will still not be allowed. +

+ +

I Can't Do Administration Tasks from Another Machine!

+ +

The default CUPS configuration limits administration to the local +machine. To open up access, edit the /etc/cups/cupsd.conf +and comment out the lines reading: + +

    +Order deny,allow
    +Deny from all
    +Allow from 127.0.0.1
    +
+ +for the /admin location. Then restart the CUPS server as +described in Chapter 8, "Printing System +Management". + +
+ + + +
+ NOTE: + +

Allowing administration access from all hosts is a potential + security risk. Please read Chapter + 6, "Printing System Management" for a description of these + risks and ways to minimize them. +

+ + +

I Can't Do Administration Tasks from My Web Browser!

+ +

This problem is usually caused by: + +

    + +
  1. not specifying the correct password for the + root account. + +
  2. accessing the CUPS server using the hostname or IP + address of the server without enabling remote access for + administration functions. This can be corrected by following + the instructions in the "I Can't Do + Administration Tasks from Another Machine!" section earlier + in this appendix. + +
  3. not setting a password on the root account. CUPS will not + authenticate a user account that does not have a password for + security reasons. + +
  4. authenticating using an account other than root, but the + account you are using is not a member of the system group. + +
  5. configuring CUPS to use Digest authentication, but + your web browser does not support Digest authentication. + +
+ +

Connection Refused Messages

+ +

Under normal circumstances, "connection refused" messages for a +networked printer should be expected from time to time. Most network +interfaces only allow a single connection to be made at any given time +(one job at a time) and will refuse access to all other systems while +the first connection is active. CUPS automatically retries the +connection once every 30 seconds. + +

If the problem persists and you are unable to print any jobs to the printer, +verify that another machine is not maintaining a connection with the printer, +and that you have selected the proper port or printer name for the printer. + +

Also, most external print servers will refuse connections if the connected +printer is turned off or is off-line. Verify that the affected printer is +turned on and is online. + +

Write Error Messages

+ +

If you get "write error" messages on a printer queue the printer +interface (usually a Hewlett Packard JetDirect interface) has timed out +and reset the network connection from your workstation. + +

The error is caused by that startup delay between the initial setup +of the printer or plotter and the first page of print data that is +sent. + + +

To correct the problem, change the idle timeout on the interface to at least +180 seconds or 3 minutes. To change the timeout on a Hewlett Packard +JetDirect interface, type: + +

    +telnet ip-address ENTER
    +
    +Trying ip-address...
    +Connected to ip-address.
    +Escape character is `^]'.
    +
    +Please type [Return] two times, to initialize telnet configuration
    +For HELP type "?"
    +> idle-timeout: 180 ENTER
    +> quit ENTER
    +
+ + + diff --git a/doc/sdd.html b/doc/sdd.html new file mode 100644 index 0000000000..fb7e7c3600 --- /dev/null +++ b/doc/sdd.html @@ -0,0 +1,706 @@ + + + + CUPS Software Design Description + + + + + + + +

+

CUPS Software Design Description


+CUPS-SDD-1.1
+Easy Software Products
+Copyright 1997-2000, 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 +general information on the architecture and coding +of the Common UNIX Printing System ("CUPS") +Version 1.1. +

1.2 System Overview

+

CUPS provides a portable printing layer for +UNIX®-based 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 ("IPP") +as the basis for managing print jobs and +queues. The Line Printer Daemon ("LPD") Server +Message Block ("SMB"), and AppSocket (a.k.a. +JetDirect) protocols are also supported with reduced +functionality. CUPS adds network printer browsing and +PostScript Printer Description ("PPD") based printing +options to support real-world printing under UNIX.

+

CUPS also includes a customized version of GNU +Ghostscript (currently based off GNU Ghostscript +5.50) and an image file RIP that are used to +support non-PostScript printers. Sample drivers for +HP and EPSON printers are included that use +these filters.

+

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.1: CUPS Configuration Management Plan
  • +
  • CUPS-IDD-1.1: CUPS System Interface Design +Description
  • +
  • CUPS-IPP-1.1: CUPS Implementation of IPP
  • +
  • CUPS-SAM-1.1.x: CUPS Software Administrators Manual
  • +
  • CUPS-SDD-1.1: CUPS Software Design Description
  • +
  • CUPS-SPM-1.1.x: 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: CUPS Software Version Description
  • +
+

2.2 Other Documents

+

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

+ +

3 Design Overview

+ CUPS is composed of 9 software sub-systems that +operate together to perform common printing tasks: +
    +
  • Backends
  • +
  • Berkeley Commands
  • +
  • CGI
  • +
  • CUPS Application Programmers Interface
  • +
  • CUPS Imaging Library
  • +
  • Daemons
  • +
  • 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 scheme 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.
  • +
  • flow=dtrdsr - Turns DTR/DSR +(hardware) flow control on.
  • +
  • flow=hard - Turns RTS/CTS + (hardware) flow control on.
  • +
  • flow=none - Turns flow control +off.
  • +
  • flow=rtscts - Turns RTS/CTS + (hardware) flow control on.
  • +
  • flow=xonxoff - Turns XON/XOFF + (software) flow control on.
  • +
+

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.1.6 usb

+

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

+
    +
    usb:/dev/file
    +
    +
+

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

+

The lpq command shows the current queue status. +

+

3.2.3 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.4 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. Each +of the CGIs utilize HTML template files that +can be customized to provide alternate appearances. +

+

3.3.1 admin.cgi

+

The admin CGI provides administration interfaces +for printers and classes. The user can add, +modify, delete, start, stop, and configure printers +and classes using "wizard" interfaces.

+

3.3.2 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.3 jobs.cgi

+

The jobs CGI lists the queued print jobs in +order of priority. The list can be limited by +printer or job.

+

3.3.4 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 Application Programmers Interface +

+

The CUPS Application Programmers Interface ("API") +provides common convenience, HTTP, IPP, language, and +PPD 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, UTF-8, ISO-8859-1, etc.)

+

3.4.5 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.5 CUPS Imaging Library

+

The CUPS imaging library provides colorspace +conversion, color management, image management, scaling, +image file, and raster functions used by the +CUPS raster filters.

+

3.5.1 Colorspace Conversion Functions +

+

The colorspace conversion functions handle conversion +of grayscale and RGB colors to grayscale, RGB, +K, CMY, CMYK, and CMYKcm colorspaces.

+

3.5.2 Color Management Functions

+

The color management functions handle gamut +mapping and density correction. These are integrated +with the colorspace conversion functions so that +colorspace conversion and color management are +processed in a single step.

+

3.5.3 Image Management Functions

+

The image management functions manage a tiled +image database that is swapped to/from disk as +needed.

+

3.5.4 Scaling Functions

+

The scaling functions provide image scaling +services using nearest-neighbor sampling and bilinear +interpolation as appropriate.

+

3.5.5 Image File Functions

+

The image file functions handle loading of all +image file formats.

+

3.5.6 Raster Functions

+

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

+

3.6 Daemons

+

The daemons provide additional network functions +for the scheduler. Currently only two daemons are +provided with CUPS.

+

3.6.1 Line Printer Daemon

+

The line printer daemon provides remote LPD +client support and is run by the inetd(8) + daemon as needed.

+

3.6.2 Polling Daemon

+

The polling daemon is used to poll a remote +server for a list of available printers and +provide it to the scheduler for addition. A +separate polling daemon is run by the scheduler +for every remote system listed for polling in +the scheduler configuration file.

+

3.7 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.7.1 hpgltops

+

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

+

3.7.2 imagetops

+

The imagetops filter converts image files into +PostScript.

+

3.7.3 imagetoraster

+

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

+

3.7.4 pdftops

+

The pdftops filter converts PDF files into +PostScript.

+

3.7.5 pstops

+

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

+

3.7.6 pstoraster

+

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

+

3.7.7 rastertoepson

+

The rastertoepson filter handles converting CUPS +raster data to ESC/P and supports both color +and black-and-white printers.

+

3.7.8 rastertohp

+

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

+

3.7.9 texttops

+

The texttops filter converts text files into +PostScript.

+

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

+

3.8.1 Authorization

+

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

+

3.8.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.8.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 +and administration.

+

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

+

3.8.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.8.5 Devices

+

The devices module is responsible for managing +the list of available devices for the +CUPS-Get-Devices operation.

+

3.8.6 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.8.7 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.8.8 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.8.9 Logging

+

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

+

3.8.10 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.8.11 MIME

+

The Multimedia Internet Mail Exchange module +manages 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.8.12 PPDs

+

The PPDs module is responsible for managing the +list of available PPD files for the CUPS-Get-PPDs +operation.

+

3.8.13 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.9 System V Commands

+

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

+

3.9.1 accept

+

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

+

3.9.2 cancel

+

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

+

3.9.3 disable

+

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

+

3.9.4 enable

+

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

+

3.9.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.9.6 lpadmin

+

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

+

3.9.7 lpinfo

+

The lpinfo command lists the available PPD +files or devices as selected by the user.

+

3.9.8 lpmove

+

The lpmove command moves a print job to a +new destination.

+

3.9.9 lpoptions

+

The lpoptions command manages user-defined printers +and options.

+

3.9.10 lpstat

+

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

+

3.9.11 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 Page 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
+
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..76f2d8801a --- /dev/null +++ b/doc/sdd.pdf @@ -0,0 +1,1003 @@ +%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[12 0 R +14 0 R +]endobj +16 0 obj<>endobj +17 0 obj<>endobj +18 0 obj<>endobj +19 0 obj<>endobj +20 0 obj<>endobj +21 0 obj<>endobj +22 0 obj<>endobj +23 0 obj<>endobj +24 0 obj<>endobj +25 0 obj<>endobj +26 0 obj<>endobj +27 0 obj<>endobj +28 0 obj<>endobj +29 0 obj<>endobj +30 0 obj<>endobj +31 0 obj<>endobj +32 0 obj<>endobj +33 0 obj<>endobj +34 0 obj<>endobj +35 0 obj<>endobj +36 0 obj<>endobj +37 0 obj<>endobj +38 0 obj[17 0 R +19 0 R +21 0 R +23 0 R +25 0 R +27 0 R +29 0 R +31 0 R +33 0 R +35 0 R +37 0 R +]endobj +39 0 obj<>endobj +40 0 obj<>endobj +41 0 obj<>endobj +42 0 obj<>endobj +43 0 obj<>endobj +44 0 obj<>endobj +45 0 obj<>endobj +46 0 obj<>endobj +47 0 obj<>endobj +48 0 obj<>endobj +49 0 obj<>endobj +50 0 obj<>endobj +51 0 obj<>endobj +52 0 obj<>endobj +53 0 obj<>endobj +54 0 obj<>endobj +55 0 obj<>endobj +56 0 obj<>endobj +57 0 obj<>endobj +58 0 obj<>endobj +59 0 obj<>endobj +60 0 obj<>endobj +61 0 obj<>endobj +62 0 obj<>endobj +63 0 obj<>endobj +64 0 obj<>endobj +65 0 obj<>endobj +66 0 obj<>endobj +67 0 obj<>endobj +68 0 obj<>endobj +69 0 obj<>endobj +70 0 obj<>endobj +71 0 obj<>endobj +72 0 obj<>endobj +73 0 obj<>endobj +74 0 obj<>endobj +75 0 obj<>endobj +76 0 obj<>endobj +77 0 obj<>endobj +78 0 obj<>endobj +79 0 obj<>endobj +80 0 obj<>endobj +81 0 obj<>endobj +82 0 obj<>endobj +83 0 obj<>endobj +84 0 obj<>endobj +85 0 obj[39 0 R +40 0 R +41 0 R +42 0 R +43 0 R +44 0 R +45 0 R +46 0 R +47 0 R +48 0 R +49 0 R +50 0 R +51 0 R +52 0 R +53 0 R +54 0 R +55 0 R +56 0 R +57 0 R +58 0 R +59 0 R +60 0 R +61 0 R +62 0 R +63 0 R +64 0 R +65 0 R +66 0 R +67 0 R +68 0 R +69 0 R +70 0 R +71 0 R +72 0 R +73 0 R +74 0 R +75 0 R +76 0 R +77 0 R +78 0 R +79 0 R +80 0 R +81 0 R +82 0 R +83 0 R +84 0 R +]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[86 0 R +87 0 R +88 0 R +89 0 R +90 0 R +91 0 R +92 0 R +93 0 R +94 0 R +95 0 R +96 0 R +97 0 R +98 0 R +99 0 R +100 0 R +101 0 R +102 0 R +103 0 R +104 0 R +105 0 R +106 0 R +107 0 R +108 0 R +109 0 R +110 0 R +111 0 R +112 0 R +113 0 R +114 0 R +115 0 R +116 0 R +117 0 R +118 0 R +119 0 R +]endobj +121 0 obj<>endobj +122 0 obj<>endobj +123 0 obj<>endobj +124 0 obj<>endobj +125 0 obj<>endobj +126 0 obj<>endobj +127 0 obj<>endobj +128 0 obj<>endobj +129 0 obj<>endobj +130 0 obj<>endobj +131 0 obj<>endobj +132 0 obj<>endobj +133 0 obj<>endobj +134 0 obj<>endobj +135 0 obj<>endobj +136 0 obj<>endobj +137 0 obj<>endobj +138 0 obj<>endobj +139 0 obj<>endobj +140 0 obj<>endobj +141 0 obj<>endobj +142 0 obj<>endobj +143 0 obj<>endobj +144 0 obj<>endobj +145 0 obj<>endobj +146 0 obj<>endobj +147 0 obj<>endobj +148 0 obj<>endobj +149 0 obj<>endobj +150 0 obj<>endobj +151 0 obj<>endobj +152 0 obj<>endobj +153 0 obj<>endobj +154 0 obj<>endobj +155 0 obj<>endobj +156 0 obj<>endobj +157 0 obj<>endobj +158 0 obj<>endobj +159 0 obj<>endobj +160 0 obj<>endobj +161 0 obj<>endobj +162 0 obj<>endobj +163 0 obj<>endobj +164 0 obj<>endobj +165 0 obj<>endobj +166 0 obj<>endobj +167 0 obj<>endobj +168 0 obj<>endobj +169 0 obj<>endobj +170 0 obj<>endobj +171 0 obj<>endobj +172 0 obj<>endobj +173 0 obj<>endobj +174 0 obj<>endobj +175 0 obj<>endobj +176 0 obj<>endobj +177 0 obj<>endobj +178 0 obj<>endobj +179 0 obj<>endobj +180 0 obj<>endobj +181 0 obj<>endobj +182 0 obj<>endobj +183 0 obj<>endobj +184 0 obj<>endobj +185 0 obj<>endobj +186 0 obj<>endobj +187 0 obj<>endobj +188 0 obj<>endobj +189 0 obj<>endobj +190 0 obj<>endobj +191 0 obj<>endobj +192 0 obj<>endobj +193 0 obj<>endobj +194 0 obj<>endobj +195 0 obj<>endobj +196 0 obj<>endobj +197 0 obj<>endobj +198 0 obj<>endobj +199 0 obj<>endobj +200 0 obj<>endobj +201 0 obj<>endobj +202 0 obj<>endobj +203 0 obj<>endobj +204 0 obj<>endobj +205 0 obj<>endobj +206 0 obj<>>>>>endobj +207 0 obj<>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ÌM‚0à=§˜¥&¶vJÃÏR×õD +ÖJÚªáöR7ÆÕ$oÞ÷Ž2ڟsà d©ÌÍ@v8]«ÓûwkÊéa +çfõ쵙¶ò±ÒU` #M€`LyГ¦(R E‚‚¦@xBEx—­[~ە5ÝóæÝ·(â¿3/Vw˜ç)ጱÆê:¨•Sö¥º@K]¢t“ðÿendstream +endobj +208 0 obj +6279 +endobj +209 0 obj<>>>endobj +210 0 obj<>stream +xÚ+ä2T0BCc3JÎår +ár á +äHÉHendstream +endobj +211 0 obj +31 +endobj +212 0 obj<>>>/Annots 15 0 R>>endobj +213 0 obj<>stream +xÚ¥UMsÛ6½ëWìädÏDI}º·8r\u‡1åLº@$(! ¥Q}wÊúHÚi“±Çr»ï½}X~ëÅáO “cÈ«Þí¢÷æý $,JŒŒ'SXW1d¹nÄõ⫏Ɠí†,ñqüµ“¥Ì¹“º©Cˆã.5™°1¥.6҂եÛq# V®kú—ÙÐA(tÞVX +£·#°µ0\¬Km*_ð×mp“o¤¹k±¯ Èu!ë5è’Â[ǃ€ò®*<÷ô0ÿR#-ff{ëDË«WïžÒìÕò¾c©’bß3NØ00NG?m…ÙJ±£Ü»E/bjJbúóxÃq̦0&,‚ +†S‚ždAñ£P£áÀcE0G84Ú8¾RßuÀß ¨ˆ'´LFãþŠ[QÊpŸb=@Ë`î`Ã-¬„ ­·BaN«=x…Λ5\Ýq»ÿG:ø£dŠ”LÂFÝqù÷cBÓøåhǜo˜÷XvðDjtÑæÎžc‹ØÀi¦Ò'ÖáÔ¹)ŽºX­Zo’†+æ½u¡õi-N˜Á™ÄV!ouãýâÏÜ +ó,”Ø£Áª +_ô•¬:Ò Sò\XÖHÆÁ¾86²Þ¦sÊ«…;ÚI:kEƛ§)ùއ\"ޏ}øš’=7øªWÿ·V´Ø˜ýa\`÷=Ð3.ÈîØàC:£úßÖòµ€[¥óg +go1üÚ×~Û4¾F¨Ë+Ξgð‡p3iðŽa‰¦ƒ@èÂ)«/šÛ¶!«¢»vÒmÀ%>”mÓP¸’nßIϋÂвӿ9PDp+£w–8˜T[—ùÅ©‹n³“½DÒÀ3\ƒCh·ä›Â⪏}ÕIZ["Ü¥Β¸â¼sՆ ™·ÖéJþ…¶ÝÂÀ¥sÿð÷„p!¨¼5·™Úw°tù}ֈ¢åõ7€× +šU)ñê?ÎStw^û–ŠPªuÝ?Ñ«Ó]’ñªÁő„Óë÷ÔË{—fŸ.ºÎùÝ"tŎdPëÑøÚÿ²0;ìñÓýø‹ŸÌÓfÍk/;ÕþƔZ)½ów_x—Ùߨ~Ð^FCÿô–w úÜ=%,“ñÎRìE— <ŠRà,ó°-~¦Ê«Ì¿sUþ©·Xê^i¼ÊfÿjLAܾ I³Ë/ûp±›p0î–ÿçÞߕhssendstream +endobj +214 0 obj +941 +endobj +215 0 obj<>>>>>endobj +216 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS045Õ³P072PIÑPp VÎO+)O,JUpI-ÎLÏQÉE™%™ùyš!Y\º-ºP=F 13=30ßP!89¿ $êÂÈ Åendstream +endobj +217 0 obj +114 +endobj +218 0 obj<>>>/Annots 38 0 R>>endobj +219 0 obj<>stream +xÚµ˜MSãF†ïüŠ>nªl­4²õÁ 0°¤ ÖAbO¹yl”²$G’‹åß§{F–ÚY3rÀ)ªLõh>ºßy§ÇŸ9`㟾׃4?»ŒÏ¾Þ„ lˆ—øÄóˆ_<Ê¥¬d‘Êú·ø/…8¾FÆîÄ +²¸zšG0+Óm.‹&i²²Ðø§Å…oy„Ç/–åz]¾fÅJ¿¸à/BVCµuÏoмàW;æœ:Æ9…gM¨?êa|õ0;–s®û»*‹e¶ÚVº¿‡¤HV’Þ…ù:i'–¶ûV€³Ã~þžû³¦gcÇÕËTãÜÍflœè­ndwE#«e’J˜É:[ô/­²M†Ž6竺Ë7kه©\>ÿTÿÑÅõoýÜ­§\6¯I%áb‘gEV7Á²ª)‚Ûdý¹¡ö·èÄ‹æï,h^•«*És’Ü)V=ZM$Óm•5o¸k6eÕ|nˆx~hˆXÖ'qôôNœžjy¢|ÿ8˜ïØ=‰÷¿%|g:càcWè/°ñ½y‘Uç<õ‘®S”ÅxÏyj Ù ÙÎu|f[6:'}8ôñx‹þiÙà.Ž“ƒ êÆ¢4rœe€«5áŽãq~2È3"G7<'ÂòÍ<#Ÿú˜#ψ\ȧÈ{Î@8Ýi`¹=ïOöú¿ü%_ՊÎ;7˜hU\,Êg4‡²n"%Gô‰ŒÌœën²µ„›²Ê“¢L³e–* uržX®EéG³ÛьÊ6èÉ·Qã;=©†IO-Ýêɀ·zÚñm!#ÏÌ·#(ڞȻ¡55óŒ@Þ§¼ôüÁüõۛ2é;Ú ~Éä}R¬¶xî÷Ì◬ZÀõ"£ì}$aï8žÃçð{ù I±è$ɾo¤.Bꏚ)výUùèu‘– ò.#®’¢þÌÓuÛäû·Ûl!?ÝåC¹k5ÍHæIÑdéðê ;Áž(mL•PT㰔Càw¯¦@ûÆÀ9A>,H§&žÈÊ5M<#hŸ…VÈø#ö=Õûàñæ +¿õÃÜg…ìý,‘9ú–AM™–ë“z•T@›!Ý0dhG«˜h`…3€s‚2b<Œ<#È 'q#Ïä}ò]#ÏÊèt`þœ “•v•‘gò¡½üaňPè}KŠSÏíŠñÛ2Y×X,U¸‡õݦíÉHþóÿh£ewR “†ZZKÄ@3s†u£çiȘ 'HC.îa#ϪÎ<Œ‰çi(èŸtú*ŚxF ïэÚÈ3ù`:ONPõGµAÏ¡Q?d + Fð¨Ód-•<±ô‡¨©¶i³ÅâïÃôEú˜…ú¥ëÂ,ñ +Ú£Rt'hÕ0 º¥µ^ 4ȇ:ç 4 t›xF ÒEËÈ3‚J庉ç]7B’«‰g•‡ ¨ã7µ&!<’͆rü,›W) ¸ŸÏ”Z°|éò^ŸÖÛ¦ŽºèL«†I +-­3m @Þæ’SpNÐù5ÈûœÎÏ Zóô9A©u)µDj§BßáTj=ÇÁ·7,·ù³Ñõ1–ý]Fa<†oq¬*ÔÓ&× úòT7LÉmi;Í*O} +Žç•›ÁÀd8¡‹ßÈsB,æùp"ow¡‘g3¹PÇ!7ìË_3”m¸Ø¢ÁÓ Dçp™ÔYª¶û,[Ñ/ii*ëú½bÿõ#.FÁî¡þ¡ª›Ö¿GŸ6®P½í¶úúãìfck”endstream +endobj +220 0 obj +1334 +endobj +221 0 obj<>>>>>endobj +222 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS045Õ³P072PIÑPp VÎO+)O,JUpI-ÎLÏQÉE™%™ùyš!Y\º-ºP=& 1#C=30ßH!(5-µ(5/9µ$åÂÈ¿ä"Éendstream +endobj +223 0 obj +119 +endobj +224 0 obj<>>>>>endobj +225 0 obj<>stream +xÚµVMsÛ8 ½ûW`rrf"ùsý‘=5ÉvÇ;¶›:{ò…– ›$2$Oþý¤äÈÞ4Ó8Ýñ…&AïxÐCg}ú `:„Ñ’¢sµìô>Îa؇eF'“é –iw7h妄/h%îΗßÉn ƒA°‹†³xȖ×w_¿´¨B+‹)¨ æ`Uæv ØjÙ'ë°°à¶ÂÒh„Cpjƒn‹†@[™2û(T ÚÈÒÉrNØ{{É¡)×h8‰ÇñJ$÷X¦6¤”Ô)EÓxFyÑùj8™Âa¾| F!ã+4÷˜ã\S8ñG×.N¾Ê¬}Ð:—‰p’05jcDQ ±°("|—÷E!6Lâ'¹6Â<êëF ½ÉÉ}”99ùú·d‹i•£9ف¯=øç-=‡ÁÔúFÃPw£x‡µ×n‡iƒªòÖ F‘ÄÑ÷ õ“wÉÎâ½,µï%™D™l_ÐãFétO¨õˆ<‚†q_Ž“/Ñ픹>>>>>endobj +228 0 obj<>stream +xÚÅV_oÛ6÷§¸Ç…eKvl'@1¬É‚õemc(Ð쁢¨šµD*$eÇß~w¤äĞmdiŠ!”Çûýá‘Çû^ Cü‰a4¡_^õÞ§½ÁÍ. -hd2ÿò³šV–¢¼äb5(d)Þ¤?0ðâ1Eö1´ŸøÐQGc°ÂHV† 1Ä1 1dJ!éB´1¾*ÇUnÁÑD-¸,¤Èá‡ÎÀi`PjŽ¡µ‘Ê \+%¸Ã€•d{KÚ¬µ6©ä"D#ˆ¢„ð¿Ü~iA~u¡Mu˜>êî'cT±!ã£îßtí¤VßކïÛ(Šþޕ¼˜tBCœÎd˜Ú ‚*“ŠÑø#‰²Ôk©¾o™„d!W ’±&¦“vúÌ0'váÏ s႙´(†Tú‘Ö•°†w”§Ñ ·1î’Év)ÐÜÖºL:»Ïa +˜{v‚…jª 7¥æÌ1 /&€•(ÝfŸ‚X u„MAX|!øM~etçGÀqæc+­@Ú,¹=d܀âÅè–ç»Ü™Üšcp×éíàz~ wg fò53âî Ð::²Îè´ú9|Ê{ ý6®Òù/D?eõ.ÐÏúlœåÎþJ´z@Ç|ýø×àëǛd`uá^Î`Û>’¢c µs°[ƒ;ÕB|ÀóZˆn­ÍÚ:h,Šü½®ç!Km´Ó™ãå\iUn0Jä{#ÛÀŸb] +çúŸÝÇû<‡T,Q´’]²¾ëÀê3žÆå`@ «Ä·Kêb§{K. +֔.ô»ö–EÀ‹x8Œvîº;AuÙ kqöµ[3¥|žŒé|ÆOXóDÇsî§ñ¡²•„~A>>>>>>endobj +231 0 obj<>stream +xÚ­VÛnÛ8}÷W ôÔ²6¾ÔN»éelñ¾õ…–F»©” ÷ë;CJ²Wiå-Ppds.gΜêy2ƒú›Áz‹äÕäÏíäw0[¶¤“Õ-=¯Ù<›ƒªŸ_o¿Òùf³x>¯ù|û„| +¹©*¡ pOæèÀÓ¯yc-jÏ 6Π߸,F9g™Îï²>ς"ÙÑ<öœ§ÙUÒ;ðÕì 4j+µ—zŸÛÞÿ³y„Z'S_'R'{m,F˜‰LRH<Tüñ”¤ Ï§æt‰KÀԞ‚]©aəªñ"*°X™0 W„&âçj.2¬[÷ż˰€û?Ÿ­º÷ÄÕüQx<Š>>>>>endobj +234 0 obj<>stream +xڕVMsÚ0½ó+öØÌ§æ+䨒¦e’Li!‡Îô"ìŨ±%G’“æßwW²@Jé$“éiõÞÛóØIà=ý$ÐñoZv>.:çח `±¢Ñ˜²wýx÷àËb1ƒëZ¥NjeÏ¿:€$ Ðn‹5àªBeô“ÌpgÅiHµR˜:~ôp‹æ @Z[#|¬Ñ:úlPd '`et ¢AF|?ݚô‰Ý+TÏF: X +Û"ãÀt+ªÛ»Œ7²ú0¦Šq­„·5•B‰<þ s鬶’ÊVtm£mOS£¶ÚvBÛÓ5àV¨¼fn§-Zða +é>Gl„É@*‡f%R‚iC¤H>I•Sf˒røÛÕ¢€­¥`ÖÃTÂ8™Ö…0{b Š½Ö )t)GsD(ÕÆp­ JuƋ?ßaœÇp?‡óÉtÁýâº;Ž`:ÿڏ‡—Ý$tiüóì¨/C˜Í®N²d¦­›§FVfÆ+‡+´~«akTSw% N¶Å‚¹k¤ÏéÓoFXâNX2åZ'ñ{®`)]³6yÿÊm²Ý¸hè÷{­Ô!Lîgs˜–"gûnåÒóò†ÞxÔ*öds Ú2°ts¡­8ûDŸ—xEa¹ñ Då"_­XJ3ÅÜïßdÏB½aÙå­³µ%–/^¸'×"dAÿì±Æ L¶Œ'Æ'åþM­;ÄÖD·xµ§Wñb7ýýóÇ& 7íf/ânö½˜Üýˆ€þÜ+ø)-wxüCl/ˆ…»ë§ëÜIÕ¡Ä\”µ#DUqQ„NUVº—¶ Ų$Û $–+÷Yº5§nO鿼µš ÷—0ƒÖ|1Õ)¹ÄCr0U‰<‰¡â©ŽûØ÷ ƒÿëã~ÉNz=Qg ’_KA–y¥’D?“ôíô¹-dÒ>€° 3̎sÀ<ô×IT›^|cÐjí>¿d$9JMÈ’ÉÖuÊ|½$û­(«¢­‰¥¤G<˜ï~jVº~è‘ite$ÕG£iÜpL†Ãx £þ(Œ£Ðîs½rϜ\¼2W»ó—OwáîEï=ŸóZÌßnŽ|ù´è|ëüaVà‹endstream +endobj +235 0 obj +853 +endobj +236 0 obj<>>>>>endobj +237 0 obj<>stream +xÚµVMoÛ8½ûWÌÑVJ,'þ螺IÓÍ"m½÷æ -R6[‰TI*ÿ}gø!;†áhIœ™7ïqfÈoƒ\áߦŒ'P6ƒ¿–ƒËû9Œ®aYáÊd†|8ÎoòxhØFÀ½¬ñ§S¥“Zًåt¸†Ñ(8dŔ–[қWd^%sØ2ÅñC­—jºVׯLµi˜³y¼Ï$+æyŸËþcÖ óSy˜`ºÏ¡aŠà¬3‚5–r¸ý¼xJvœ9«!¶4r-8HÃ<(\­X)àNX¹Qp§Ë®Ê­. ³‚Sˆ;ç!¯w ´ÊÚº' Ô:hTÀÈga, }n²Æ¤§‘ŸH¤'pÇDsš).F®<Ø –~–\ã\iVƒîE›¯: Ôž™-·‚wµ09ÜvÆ ¥zZázô!™G#‡é¶^Ãs»6ÉGð(•€EÔ!ð9³q5Y÷ªyëD̂ÁW'àqqe-1g°]Ûjã¼® :¸ D0`\EŒ!†u|5œ­.^ƒ³¨–@fçù°ÐuMeüC*m4Œ˜• 8íW€%:V˜gªÜ†ü­óòÌdÍÖu/F¨´ÇÒQäy´=ý¶†p±rx‹(-3̝Jë@µ×þóÚõiî°lŸ ²Àåãʈqcëì#•ZUrÓ!8¦âþ\ÍOiØß³5›‡H[ jÈ0HŠÚŒpHUYŠPñ¾Ná-ªž±²¡Ä1”*™¡oÓx?Òÿˆ3ßöö -àÔ̊IH8¶b€Ì3÷¸…ôŒUë¤ +ÌSU¯†ÞGʵºˆb”‘h6ÍgÈC¯ŠÉ^«@k}Rÿè5Þ:jendstream +endobj +238 0 obj +988 +endobj +239 0 obj<>>>>>endobj +240 0 obj<>stream +xÚµUÛnÛ0 }ÏWðqæ4ν[/h=xHö²,ÇêdIåuÙ׏²ì¤K»x+0$@™ä9<¼øq”„>)̖áËëѧíèâöÒ9lKz²\Ó¡x7¯ÆS5Û o,¾ß>ÕÒ4Z%ÓU°ÚVâh¥T^8àFÎc|nµ7ôî¤õãð›L/ÇàYÔ1¤ˆÃàÑn˜ÀÕ×lqÁ<;Oc¶(²ï,^@g×·oÉ|‡ñ9 ÔØâYG8Â%h—¥äĤ®™.ÈЙ²ìº£Cw`…+«É«Ó‡<¥ÞCpⱤOn:£6 ä|žÀB;ŸÁ²%8X¸£ÑKéZQVfçXÝÖê-\u¦Þ‹FŸáó›]O©"±‚fµ Ñ)>§›ÍÕEÖ +‹µ&ä_‘›2.ܟj©ÿ–Ð}òTI/úÚáù\ÖŽ•ý‹D*ûYÜeIvõù¿§q ^üð=ޛ¼èð`h®V]¸Ù´G]ÆW¢hÔ«-I-ÛÁbo’ÊF©}R6š{i4Sp·Ýfé8mEºÏâ™&‚¸Ñt04q4Q؎J/ÇàŠ! +:·“㉐R·¸§zÔc¸÷ÀšCÝ ¬­;à +NUKr†¢€B:ÁiŒö-É)„‰<œ¨M_ nâàŸàv¼€3 ¹Æ¹À×;¦Ñ2'´Wû¸??e8iбé$\Î'kZH“?¼]o¶£/£_Jd{endstream +endobj +241 0 obj +675 +endobj +242 0 obj<>>>>>endobj +243 0 obj<>stream +xڍVÛr9}÷Wô㦠+HÀ6¶_×Îf½µUëñMJf¤‰¤Á!_¿§% &O¶x`µºÏ9}ãÛٔ>à3¥«ÏI7g¿/ÎÞÿqCÓ Z¬p2¿ÆCõÛùäz2£ÛZ…ÀáÝâ l.h:Í6ãٕØ,6L:[P㪮f2<‡ÖÙ`–ø¹ržeÕÚØ5µÞØÈ~ÅXŠðv!r3¡Joò™xQ¤]]³ŽÆYr+A€¸Ós€BäÚiU“²Õ{ðܸȽû0¡¸T Uä={q µ³+³î¼JW¦æI¦ý"Íxv3ًsq Û8¨ H£êšþ\,zK횦³F' ri¸5àÕ*Y‘è‹2\©’ø¯”æ0"¥5·QìAÌf­¼k ” ­¼Ùöa—¸䂱À! šço1áÛ +GG‹a"'²:(ëïïö)9”#eä„&üu—€Kvø;(YäúöÓýQP ^{Õ ¡,sŕ]Û:陗㥠+xYêb”3i|qK +QÅN +Ěè¼”U:´Îu0)1góœø¬òì¼ùÁÕ(eðþáE%RžE¤˜Eàt˜—ÓÝàPUýT¨o—T{/ãíÓÃ㉠+OŒA7U›ÅøHfÕBhh¨Ðb•Š +ºùNÇáÒõ­ªÁ¼dø´”è]2ŒÀ~kPk´dÀäCœG¡ßŒÈQù˜Ú·!µ’™_EOæ%aئ à ¸¤;N¸¤¯²ÅÿvHz³‹ÔV™Z‰Iï@Lû¼Œ?qÄ>Àµ|P‡oBŸÓñhhçwôXÔb±7Þ§¢’îEcmx‹“~hK·€±ò& ì¶x­h靪´ÓàôWŽúœæñ«nÍÓ9yïg®4 ºÉ‰G ôz‡ö+}\æú¿ÒÐJz¦©ß#Ú;J:Œã¦æ¬¨X„.”ÍX†$.>Ý=ŒšmÜ3ˑ‰Ç ß/ú€UÓÕÑ´RÇU…Ò ¥‡ÄÍ17³}%3e ½/g¿<~žP2å´>>>>>endobj +246 0 obj<>stream +xÚ­–Moã6†ïþŸRÀV-9_>¶Iº1Ð.ìôN“#‡[ŠÔ’T¼þ÷¡dyëòŠ–,¾Ãyæ‹ò·Q3úËa~Ëÿ²ý¾ýúÇòkؔ´r{O7êjžÝgù ^„¶¿l¾’âò¼UL‹;VlÞ*Z†Ê©Æ èCílÐ[úZ:QWÚîÀ5„U t¨E”oüLÛº{J«|Ëzi4ÚÒY‹2jÚ*ƒ%©Lp A®óyV°ó=ïƒ!Yi+]òӂÎ:ЫõòËóëê¿ôWÉåGáÃóŸçÊ w–\O(,ㄠ+)â€þ=#–z×xÁ”PjC,"€ET¨&ìä ø±ˆ¢7 +jï$†è½ó!1áwCÖ2œª1-Ù©9¼,_žêñÒÊ9*-`i#z‹‘Khàé»$‚‹U +v̜v„x¨1QP\^ࠔˆb+RØ"žEšºv>†9[sú· +"¢MÖÝf‘ëÉ÷EˆSéBlmèƒøØ¬ô®"Žà/i/G÷ +CÔö”Û3ïL{!S¬Va S¼<й)?LÇ57š¨] âR)XBÖ]ÑS›“æáuµž~Á8=úý×ÕØ6Êè9¬(#”–!ðº“ü |¯å +œ˜ifS+BÄ*ƒOv= €¼ð ðN{¯#¶ãÐÛ}ˆS°w]óâìÖÉ9ü ®"^õYÈÙí1è^-;5OлVÔ´àݶ ñ¸25ÚRRªm?qiøšm¥cߙޙÿ<^’|uÛÁq\d9)±ŽÅjG6ˆhLwŒÐéʼnö©á[•Å}òšjj”ºÔ²Gf)@ ++Ñ °´‚K,ÊQ¹“œÇ–‰ôí[ƒ ªÄ˜Ð¨Ï†Ñæ|îóÔ °uŠKp!ºº÷Úr¹®—Ût¡úÉ|]Ú L­à2’ðñÿaºSð˜ºgi;9ô×ÓQԗ^­Ñÿ` ÉHxu£Ó^>zÉàÃ̧©ùÁç^;´|”ñجEº¥aù˜¼£oÝ+ÛE‡.r•Áot„LÍÚáii\Ž'0~æÕxræ}¼§·(Œcpuú-Ú/Ðî6šÐ˙šSu)½ï2–ßÜd÷p»˜ó&íä¯]÷lúˆüFç‹ô:mɶÓÖdzWÌØ&/øáuÁå˜}òCèi3úkô/tâ[endstream +endobj +247 0 obj +883 +endobj +248 0 obj<>>>>>endobj +249 0 obj<>stream +xڕTÁnâ0½ó£œŠD²(ãö°USõÂÅ8j䨩íPíßïŒC¨„V‘VHb¿ñ›¼yæc’Ü>9 X®A6“åäÛÓò”5í¬7ô£º[fÛl ºU£Ì´<gyÞsÒEÁœòHÛ4ÂT@ Žè¡uÊtðÑaG¼%µð}\÷bµpÊCò=™AòÄð‹á7Îá™á%™±8IæËlÁ¢IÉë¯ o 5ƒfh,ƒg,›t Ø6(k¨ ‡`lßµ­u«žbðóJ!qØßívP+ûé|<ñ‘)hÄAc¬RböÓx~ëìYUXA°äЩձ£ÕŸ¯»—Ô·(U­$Ô(­ú¬wöËýt±Í®þä®2µµŸ W÷µòÁC  qJLJWñ`TxV’çáÁ£FIÀáO¬è<ºñ~6$ר3Žöį4Љõi€“=°)"ú]¡Ê6}\uK‡^†3*< ð6‰ü^i…µ2ô®—Xö¼TŒËçs:ÛFřp3…Aj6¿Ï™íwHWÃÿ—ÿ¤ìðDCi¥'\[ ¨u/ß±ê4]I¾<†Ú8‹ØSMñ¸thþÒÐæ"•ßßS +–EÞ7SMW¹ŸœüôêhøK:½åê´/J‹ÅüŸ,«bEÛq/_òÂc9yžü{-`lendstream +endobj +250 0 obj +520 +endobj +251 0 obj<>>>>>endobj +252 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS045Õ³P072PIÑPp VÎO+)O,JUpI-ÎLÏQÉE™%™ùyš!Y\º-ºP=†& A#5@®±ž¥ž™BNAbJn&X¹kW ¶Û"Eendstream +endobj +253 0 obj +118 +endobj +254 0 obj<>>>>>endobj +255 0 obj<>stream +xڝ•QsÚ0 ÇßùzÜH Ð=BÚô õ.éÝ^]GM=›Ù¦Œ}ú*cíÝâÒ9ŽDâ'ýeIùՋáœ>1L0ƒ¨{³¢w6ÿƒs(žÈ2ž\BQ~™Âµ2Îq»ûZülâÉÞ¡?EƒÖ%Š¡@[»½Çâøà1˜DãÆ#Ù[F ÅëÇÃßA˜z½ñhAq]mx…Ñ{Nÿ­ûš[®ªn`Žº”ºcÁ¢@ùÒܔÜs¨EðÏ\“êGéÓ^Öá€r¡ìÆþ–ïõFKÁ½4ځ 0<¢ß"jð[kk*Ëk +çÐJþ_ê>¡É±BRE鶪4¥oìªC]ô¾%ÚÃA4Ú7Ŧ½ ôÅ4O²,GMÕt^¹çºä¶„Ä”O$>Óô]·éÐoêž&¥ +¢“–w‡JH ¡î²À¬Ô¾©k¾së3͓3Ö MY~÷äÛh]€ãbÕ$zmùúY +‹ÃD†Ñ,ù›Ž*¡½5êTþígøûÚ­y<Ÿ¥Å¼Þvͤº’©©+ +îV07V¹Œ€=vÚ g˜å÷ÛqàêØqîmŵüÓì»êf/Hù±¬Wë j™-ÓnÖr£šåTJÇ",¹Tþþp€Y(IfœÏ…•kÿ7Ut탰ô|9 m[ûB¤%Ò Úv¦hqXEpj KۚN'4½—o±£Ã–|÷ +MFÑ%-Q2Ä̓´è}ï½°C#Æendstream +endobj +256 0 obj +597 +endobj +257 0 obj<>>>>>endobj +258 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS045Õ³P072PIÑPp VÎO+)O,JUpI-ÎLÏQÉE™%™ùyš!Y\º-ºP=†f Acc=#°€£‚{N~qqbQ%HÂ5„+ š:"\endstream +endobj +259 0 obj +118 +endobj +260 0 obj<>>>/Annots 85 0 R>>endobj +261 0 obj<>stream +xÚ՛]sÛ¶†ïý+xyzQ…ø$xÙ8u뙜©OìþF¦Uµú*¥¤“°À.hdnn±ÍŒtÁÇâ ðÝý}#ªÚÿU#+e«åöæíÓ͛»¶’uõôR ÓV¶ÑÕÓ󞺏›¾Ú¿T·ûݩߝŽ?<ýyóóÓM½¨=~øñáhTV·þç¶r ‰ÿÞTÀ>ë>¬ª7w¦~›¿ÌÔð»Dõ*<·•2 WÒC42—ûCiªð?³ÿO¼z×ʂ¦á~·•‘ ƒ ¼í7w%ôch}gT\Lè˜A¶þZJæHŒ#êþُøúe½ìNëý ¦ñ‘éÊi'åŽڅÞ((&•oÅ$§r\³°%ÃHzür<õۉiœ®÷ò+1~DšÈ1Ž´ß>÷Ãçuÿà´X´³žS¼nzT<42ÅE½ÐQqÅ)ŽQÃ|.@1N¨wûå§­Ÿ¦¯ór„jíÿ.€Øˆ…ìÒύ+Ë.&-×85Znü÷èÉ` w&§ –P¦õó¯`Åh`|è_ú¡ß-û ¼ 73÷Y5=am“½ÆÆ%{5M=Q²öJD'ý_1†‰tûûÃ㤫ý¤55 IΊqbÑS0µµ×Nuc“1ÇF² cšh€’5fâ¸Ú;JÁÁ0’~;ýÑb§ËÁ—Á +ÆFbÓ gñ¨i›ð7%É&¿/ل‚TèoE1F0æ`N‹Q¤¼ëëÕîuTv¹ÿ`nü”ÈÂ0ÂÎ\yž®c˜Y/šh°an†ÆE¯á™V¼Ó ¯50=s†çm·ü«ß=±ŒóSîuÙ ²Õ*¸` eilàmú勩õ‚äš,»*ßú…q„­ µ˜Õ2‚J·up°p/±‘„Ò­ˆöBIF("E¡ +ƶ9<ÿ…jšP Æ{ L¨ÆÅB„RœPH*¡…q„º¡Ûlú àÔ\ü‹“ÉêàÍñNB#“ÉL^&ÍɄ$!a&(Œ#ìØë.ˆ$Ō–š–ʈhÄá^B#ʌ2N&ä©ýr¯a<Š´÷Ž~ +"5³ñsN"Õ$L"咉[N$$ ‘¸…Hûtü8Go²ÓE‚öc?–Ʊ‘Jc- ™8WÇuÉÁ0’ÞöÃ_ý¦ÿ2¡ºÉ>–ÐƧق×f´ÛývÛQ±á¼}^YxnV +‘%‚ÐÈf¥Ÿ`˜$[Z 2¦,QGØæ° ³²žY Ë(¥Z—rAl$¥TÛR.lmA¤X[(Œ#lsø{ŽÏoÃåLʱ‘ åèée+ ∺©…L °a–Ó‰S©)ÄF¦R#)H¶´ ’ðëS¢0Ž0¯Ô6HÕÎG¨f:(ãR.ˆ” TxOTâÞ¦§W*8FÒí/÷A!»˜óî 7µ|†==6²©¥-yºb=HBá…q„uÏÛõn±\­ãûúÚq)™™yhd)Ef®x3G’ÐàÒ +ã[nºã±?Ž"Í`Šq"‰63rіF.k’ˆ5räÀ~*A1Qî?Žê(9“µ'Qm2¯Méâµ%W¼‹#I„‰Q 0Ž°Ã°Þú!M¤ë¿eL\¶Ù&dl$—­"׌‰'¼ù/8FÒWì+J¨æü3aY?ÜþØ`Ë(žéË·3&u@èð_ ÝvëGqša¶•T³J(v@è=̊—n6ÿýïûÆ+æÁM›rPl¤Cºšrfs‘„±‹¶DÅ8Án÷»Ïýn [sªf¯j û;ôîÓn ƒO/¿ëzŽÓØÚ”Äb#ÓØ6”Ä4›Äˆ$d3r  öëÓÓĸÙåր†ÌwH¬3i¯äaŽÑب”c#ÓØŒ³˜ËÄj¨„ñ€º˜’7»žwþ‘¨Ãř{ÍýPNdÕ¦,™Èº¦,ªÙ,J$¡%<Å9*Æ ö¾Û­>u«)§Èè,8EÄD¼¾ÞœÊҦ͑ØÈT–͘†Ù·´DÞù(Œ#ìááÝÔtNW{–…åHÁ¢+¾fè˜zG¨t(6²zGhÊ}†«w+’œƒa$}M½ƒ(!a}R°0ެûm·ZïVSŸ`BæœGø~ýqè†/XÔ_ueÈ=u¥Óº.ÓiM'†/Y$ÂÍ…q„Ýî7ûáxè&+– Kúé;äD_ ÇÉr5gx¢_Õ·%‘:ˆK‰Z~Óu+3FÂ5)ÇF#áWðG„×øãnŸ©g!] )B{»*XÔ!ÀþÛí|ÂaŽêe ?4Òù¹V±ƒ»JōN“Sˆltšñœ‚aË%"Ŋ²@aaàW=W‘Ž4¥gAƒŠt„}Ý%,Ë`;·$b}¹,øö nlvF"6²A²ã Ã[D +<¡@aaËn3T2,À‘ +u—Jë$Nf°ˆLf=ž°0lµE$œËúü„ÅûºghÖ¹-< »[o&“RºÞx@ò(YØÁ]ZF«ï^´Ì`©ìœGldƒ¥LJýÜÞ<‘D¨Z Æö¡;žúaz´lÂ5bü˜i´Bs)I«kUZíti,¤Hc#•ƾrŒ2[¦0&J«Gd^#ç]×o“ïÎðÔ7)ëìÀHld“²ŒX¶%R\P(Œ#ìýz×s ¶f`k²€Q¤=Ä7ÕS/ã²3l•@ì€À8¢a)¡¿ÿ·A˜ájuJ«­.²j;žY±leŠ˜¸W’sbIû —QÇëam /s†‘–éj¯¶‹Î8‡iMíD±¤vã)•†1„8¨,rH Ê1óÁþ +ž.›ë>03mvXŖgUìxT¥a1xlÁ‰Q$ýqXmNûCL™yHÆèc²3*¦<¢b,©Ã=«uA‰ÑÀYCQFâhuõmMQs²SŠå©=JiøcÁx&%|‰DŸI!Š3„Z¿^yÅÙÃi#]öՕïOÇ£( ÿ’:bàÄtɉQ$ž_Ægj»áQžtSõøMf‡ßݐð’ܶ¸wV…“û—Ó?ÝÐWømÿ×rXè{ZJBrÿ±‰gÖ¨ÜÿnþMà_ endstream +endobj +262 0 obj +2356 +endobj +263 0 obj<>>>/Annots 120 0 R>>endobj +264 0 obj<>stream +xÚ՚MsÛ6†ïþ<¶‡0X€ £kǙtê·V{WdÚfFU’Nëþúâc—œ±Ð\*:É8³^ê‘ð +|]ðÏ3(˜ù …¨í¿Íîì§ÕÙû+]pV¬î º¨›ªXÝý°ZÞ¶E_\ôû©ÝO㏫/gVg¬d†`€ýñÛÇ¢á%+êJ›Ÿ»B×¥Â`[ÜZú‹ Åû«ª°ï×ð¢–̾(›R¯¾G„ÝÀ«R§oâóu§þà>.oJ^¸ß•§ý,£žæó“z.ÀY…„ý-jTç4BmôLP˜G˜UiXS;X`§Ö)+çfð$‘ "‰¸01JÔä$BHYV) +óóòL}{û½eJ;GO¦SV!¦ÍxH!D +++RHåBT̨™ |ž`¤ÐãÁM"Ã>ñ4Êi$Íç礑‚FR[¿@tF#"3[æ6µOdH‚›Ìé éˆJÆŒJJ8£•ÜÌwàÐ̚!Σ#³(z¡Óúӎs»yldC 1ìï™RµÞíƒhJ5Œ¼[•›RHi§_‚òy‚?MýÐý³ž:oL5+ÅÉtË +$ëàÜ>ˆ’ 9·2ß}F $×/Q˜GØÅv=Ží¢n9ȈdÌs6oD"U™·2_tF$$[Ææv±í̾Î퓪S®kß%“`‘» ’Iù·2CÌȄ$ÊšQŒÂ<ÂÌþ÷¾{xâ›ít&•š°÷A$Ì^”ÛkÌýÃSæê²ýÚmÞ֍ÆDd×.ˆbU°ëÜV›H`V­&Eaa—ÝÐnÌnûùu`Ì0ÄFÙ &Òˆ¼m‡ |e>êÿ.|NçJ³àú>:W‚ëçöëD°;õ…y„}º¹±$Kq³ÿ¤SÓã÷A¤S£‚ñçvíD¨Í"‘ 0°ŸûÏnâ€^ŠLY‘ê*ؾ"‘jl?·m'˜»†¥(Ì#ì—þá¡Û?¸L.aBe5’à›YÇöQ$’œ%vć¢Û-„y‚¢ ízݹ‘ÃÉ ?Ԉg47X? +E mÖ!«ÁÄ70ºyן®?,¨•U‰WÞpý(\©d&ÅìÝÀ³*Œ×f’$0ºy77—#Î&õ6f€7\?E:™åjönY&l¹œÀèäÝ Ý~j‡ålºŽèäÚ B+ç¹®ì÷Ah'­É½u¦¡@e«¼„ƒi$Ý>S»{½Þ,)¶¢J`˜FØG”ðR» T/G‡yMuÄn·Þß¹¯­jNl˜¹©-” e„ÂÌ +ïmiǶì_€0ïPëͦ=Lh‘âMÜü¢PGø R¨á´’èlWƒH¨QŒÂ<Â6ëý¦Ý¾-•¤ +U€"•¤.癔kk ¸mŽ%(Ì#ì®íѕsG¶‘²U2T>ˆ4ªjZEt¶§A$¿oKP˜GX»'‰ÞÎLr»,RÉ‘JB̋H¶µA$`ÒúsŒÂ<¶îTC-©!U ¢cXD*qFåzÄ·ÁH@>ïQÛÃúnçk€…I"£‹Z}éÃêàÚ¹®‘l›•¥(Ì#l{èö÷ýÂÚ¬™¸Ž[}dâZÛÎ5%ˆä[ö +óÛvý×vIÄœFMtÜêƒH#łmçzDa·… Êç ¶=ôۅö[µ€b2+R§¤®„ñQ¤RÝÛη%f˜)%!…Ñ 9÷8­§eµ&rJIµo|)%çٔoLÌ(Wr'(ºÀŸÞ·_ÚÍ´¬’ûu•˜‰ã }.Á8°÷WŸ)²Wá1àù1¥f‚+LEŠÃ4r>nûq\Ïî¶³EÏŽ¨¿QQ/È9ø#BiŸ£òÁ,#=šeJsxRx~¬Î‹ ¦43žJsŸFÒªvôh–Z¢ŒYé˜?6ôÃb,éep†g†çNJ¾è¥v&Û3ý„yBm†~ÿìE«ª…lÖ_ÈÆÈæGüÎ#éžþì„¿ßÜ·ýýô×zh‹Ëvìöö¿ÍÐè€õ}2Kï¿Éì:”ò׳W}ïendstream +endobj +265 0 obj +1550 +endobj +266 0 obj<>endobj +267 0 obj<>endobj +268 0 obj<>endobj +269 0 obj<>endobj +270 0 obj<>endobj +271 0 obj<>endobj +272 0 obj<>endobj +273 0 obj<>endobj +274 0 obj<>endobj +275 0 obj<>endobj +276 0 obj<>endobj +277 0 obj<>endobj +278 0 obj<>endobj +279 0 obj<>endobj +280 0 obj<>endobj +281 0 obj<>endobj +282 0 obj<>endobj +283 0 obj<>endobj +284 0 obj<>endobj +285 0 obj<>endobj +286 0 obj<>endobj +287 0 obj<>endobj +288 0 obj<>endobj +289 0 obj<>endobj +290 0 obj<>endobj +291 0 obj<>endobj +292 0 obj<>endobj +293 0 obj<>endobj +294 0 obj<>endobj +295 0 obj<>endobj +296 0 obj<>endobj +297 0 obj<>endobj +298 0 obj<>endobj +299 0 obj<>endobj +300 0 obj<>endobj +301 0 obj<>endobj +302 0 obj<>endobj +303 0 obj<>endobj +304 0 obj<>endobj +305 0 obj<>endobj +306 0 obj<>endobj +307 0 obj<>endobj +308 0 obj<>endobj +309 0 obj<>endobj +310 0 obj<>endobj +311 0 obj<>endobj +312 0 obj<>endobj +313 0 obj<>endobj +314 0 obj<>endobj +315 0 obj<>endobj +316 0 obj<>endobj +317 0 obj<>endobj +318 0 obj<>endobj +319 0 obj<>endobj +320 0 obj<>endobj +321 0 obj<>endobj +322 0 obj<>endobj +323 0 obj<>endobj +324 0 obj<>endobj +325 0 obj<>endobj +326 0 obj<>endobj +327 0 obj<>endobj +328 0 obj<>endobj +329 0 obj<>endobj +330 0 obj<>endobj +331 0 obj<>endobj +332 0 obj<>endobj +333 0 obj<>endobj +334 0 obj<>endobj +335 0 obj<>endobj +336 0 obj<>endobj +337 0 obj<>endobj +338 0 obj<>endobj +339 0 obj<>endobj +340 0 obj<>endobj +341 0 obj<>endobj +342 0 obj<>endobj +343 0 obj<>endobj +344 0 obj<>endobj +345 0 obj<>endobj +346 0 obj<>endobj +347 0 obj<>endobj +348 0 obj<>1<>2<>4<>]>>>>endobj +xref +0 349 +0000000000 65535 f +0000000015 00000 n +0000000226 00000 n +0000001792 00000 n +0000001866 00000 n +0000001948 00000 n +0000002026 00000 n +0000002103 00000 n +0000002182 00000 n +0000002258 00000 n +0000002339 00000 n +0000002398 00000 n +0000002450 00000 n +0000002535 00000 n +0000002587 00000 n +0000002671 00000 n +0000002702 00000 n +0000002803 00000 n +0000002888 00000 n +0000002989 00000 n +0000003074 00000 n +0000003175 00000 n +0000003260 00000 n +0000003347 00000 n +0000003432 00000 n +0000003519 00000 n +0000003604 00000 n +0000003670 00000 n +0000003755 00000 n +0000003821 00000 n +0000003906 00000 n +0000003972 00000 n +0000004057 00000 n +0000004123 00000 n +0000004208 00000 n +0000004274 00000 n +0000004359 00000 n +0000004425 00000 n +0000004510 00000 n +0000004604 00000 n +0000004708 00000 n +0000004813 00000 n +0000004918 00000 n +0000005023 00000 n +0000005127 00000 n +0000005232 00000 n +0000005337 00000 n +0000005441 00000 n +0000005546 00000 n +0000005651 00000 n +0000005756 00000 n +0000005861 00000 n +0000005966 00000 n +0000006071 00000 n +0000006176 00000 n +0000006281 00000 n +0000006386 00000 n +0000006491 00000 n +0000006596 00000 n +0000006701 00000 n +0000006806 00000 n +0000006911 00000 n +0000007016 00000 n +0000007121 00000 n +0000007226 00000 n +0000007331 00000 n +0000007436 00000 n +0000007541 00000 n +0000007646 00000 n +0000007751 00000 n +0000007856 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 +0000008906 00000 n +0000009011 00000 n +0000009116 00000 n +0000009220 00000 n +0000009323 00000 n +0000009426 00000 n +0000009765 00000 n +0000009870 00000 n +0000009975 00000 n +0000010080 00000 n +0000010185 00000 n +0000010290 00000 n +0000010394 00000 n +0000010499 00000 n +0000010604 00000 n +0000010709 00000 n +0000010814 00000 n +0000010919 00000 n +0000011024 00000 n +0000011129 00000 n +0000011234 00000 n +0000011340 00000 n +0000011446 00000 n +0000011552 00000 n +0000011658 00000 n +0000011764 00000 n +0000011869 00000 n +0000011975 00000 n +0000012081 00000 n +0000012187 00000 n +0000012293 00000 n +0000012399 00000 n +0000012505 00000 n +0000012611 00000 n +0000012717 00000 n +0000012823 00000 n +0000012929 00000 n +0000013035 00000 n +0000013139 00000 n +0000013244 00000 n +0000013349 00000 n +0000013625 00000 n +0000013659 00000 n +0000013693 00000 n +0000014840 00000 n +0000014889 00000 n +0000014938 00000 n +0000014987 00000 n +0000015036 00000 n +0000015085 00000 n +0000015134 00000 n +0000015183 00000 n +0000015232 00000 n +0000015281 00000 n +0000015330 00000 n +0000015379 00000 n +0000015428 00000 n +0000015477 00000 n +0000015526 00000 n +0000015575 00000 n +0000015624 00000 n +0000015673 00000 n +0000015722 00000 n +0000015771 00000 n +0000015820 00000 n +0000015869 00000 n +0000015918 00000 n +0000015967 00000 n +0000016016 00000 n +0000016065 00000 n +0000016114 00000 n +0000016163 00000 n +0000016212 00000 n +0000016261 00000 n +0000016310 00000 n +0000016359 00000 n +0000016408 00000 n +0000016457 00000 n +0000016506 00000 n +0000016555 00000 n +0000016604 00000 n +0000016653 00000 n +0000016702 00000 n +0000016751 00000 n +0000016800 00000 n +0000016849 00000 n +0000016898 00000 n +0000016947 00000 n +0000016996 00000 n +0000017045 00000 n +0000017094 00000 n +0000017143 00000 n +0000017192 00000 n +0000017241 00000 n +0000017290 00000 n +0000017339 00000 n +0000017388 00000 n +0000017437 00000 n +0000017486 00000 n +0000017535 00000 n +0000017584 00000 n +0000017633 00000 n +0000017682 00000 n +0000017731 00000 n +0000017780 00000 n +0000017829 00000 n +0000017878 00000 n +0000017927 00000 n +0000017976 00000 n +0000018025 00000 n +0000018074 00000 n +0000018123 00000 n +0000018172 00000 n +0000018221 00000 n +0000018270 00000 n +0000018319 00000 n +0000018368 00000 n +0000018417 00000 n +0000018466 00000 n +0000018515 00000 n +0000018564 00000 n +0000018613 00000 n +0000018662 00000 n +0000018711 00000 n +0000018760 00000 n +0000018809 00000 n +0000019038 00000 n +0000019190 00000 n +0000025540 00000 n +0000025562 00000 n +0000025657 00000 n +0000025759 00000 n +0000025779 00000 n +0000025934 00000 n +0000026946 00000 n +0000026967 00000 n +0000027080 00000 n +0000027265 00000 n +0000027286 00000 n +0000027441 00000 n +0000028846 00000 n +0000028868 00000 n +0000028981 00000 n +0000029171 00000 n +0000029192 00000 n +0000029342 00000 n +0000030390 00000 n +0000030411 00000 n +0000030570 00000 n +0000031576 00000 n +0000031597 00000 n +0000031728 00000 n +0000032713 00000 n +0000032734 00000 n +0000032865 00000 n +0000033789 00000 n +0000033810 00000 n +0000033960 00000 n +0000035019 00000 n +0000035040 00000 n +0000035171 00000 n +0000035917 00000 n +0000035938 00000 n +0000036069 00000 n +0000037202 00000 n +0000037224 00000 n +0000037364 00000 n +0000038318 00000 n +0000038339 00000 n +0000038470 00000 n +0000039061 00000 n +0000039082 00000 n +0000039195 00000 n +0000039384 00000 n +0000039405 00000 n +0000039545 00000 n +0000040213 00000 n +0000040234 00000 n +0000040347 00000 n +0000040536 00000 n +0000040557 00000 n +0000040711 00000 n +0000043138 00000 n +0000043160 00000 n +0000043315 00000 n +0000044936 00000 n +0000044958 00000 n +0000045013 00000 n +0000045118 00000 n +0000045262 00000 n +0000045368 00000 n +0000045488 00000 n +0000045597 00000 n +0000045746 00000 n +0000045856 00000 n +0000045963 00000 n +0000046117 00000 n +0000046253 00000 n +0000046350 00000 n +0000046460 00000 n +0000046575 00000 n +0000046688 00000 n +0000046801 00000 n +0000046898 00000 n +0000047056 00000 n +0000047153 00000 n +0000047263 00000 n +0000047373 00000 n +0000047471 00000 n +0000047615 00000 n +0000047718 00000 n +0000047836 00000 n +0000047951 00000 n +0000048057 00000 n +0000048236 00000 n +0000048351 00000 n +0000048472 00000 n +0000048592 00000 n +0000048717 00000 n +0000048824 00000 n +0000048985 00000 n +0000049110 00000 n +0000049243 00000 n +0000049376 00000 n +0000049500 00000 n +0000049627 00000 n +0000049737 00000 n +0000049885 00000 n +0000049998 00000 n +0000050106 00000 n +0000050254 00000 n +0000050356 00000 n +0000050472 00000 n +0000050592 00000 n +0000050706 00000 n +0000050819 00000 n +0000050936 00000 n +0000051056 00000 n +0000051173 00000 n +0000051275 00000 n +0000051426 00000 n +0000051533 00000 n +0000051647 00000 n +0000051760 00000 n +0000051880 00000 n +0000051994 00000 n +0000052119 00000 n +0000052229 00000 n +0000052340 00000 n +0000052454 00000 n +0000052566 00000 n +0000052678 00000 n +0000052790 00000 n +0000052893 00000 n +0000053039 00000 n +0000053139 00000 n +0000053252 00000 n +0000053366 00000 n +0000053479 00000 n +0000053588 00000 n +0000053702 00000 n +0000053815 00000 n +0000053928 00000 n +0000054044 00000 n +0000054158 00000 n +0000054259 00000 n +0000054393 00000 n +0000054490 00000 n +0000054590 00000 n +trailer +<<37fb8667307f7e56a5efc07d8835ab6c>]>> +startxref +54818 +%%EOF diff --git a/doc/sdd.shtml b/doc/sdd.shtml new file mode 100644 index 0000000000..66992f7763 --- /dev/null +++ b/doc/sdd.shtml @@ -0,0 +1,564 @@ + + + + + + CUPS Software Design Description + + + +

Scope

+ +

Identification

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

Document Overview

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

Design Overview

+ +CUPS is composed of 9 software sub-systems that operate together to +perform common printing tasks: + +
    + +
  • Backends + +
  • Berkeley Commands + +
  • CGI + +
  • CUPS Application Programmers Interface + +
  • CUPS Imaging Library + +
  • Daemons + +
  • 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 scheme 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. + +
  • flow=dtrdsr - Turns DTR/DSR (hardware) flow + control on. + +
  • flow=hard - Turns RTS/CTS + (hardware) flow control on. + +
  • flow=none - Turns flow control off. + +
  • flow=rtscts - Turns RTS/CTS + (hardware) flow control on. + +
  • flow=xonxoff - Turns XON/XOFF + (software) flow control on. + +
+ +

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

usb

+ +

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

    usb:/dev/file
    +
+ +

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

lpq

+ +

The lpq command shows the current queue status. + +

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. +Each of the CGIs utilize HTML template files that can be customized to +provide alternate appearances. + +

admin.cgi

+ +

The admin CGI provides administration interfaces for printers and +classes. The user can add, modify, delete, start, stop, and configure +printers and classes using "wizard" interfaces. + +

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

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 Application Programmers Interface

+ +

The CUPS Application Programmers Interface ("API") provides common +convenience, HTTP, IPP, language, and PPD 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, UTF-8, ISO-8859-1, etc.) + +

PPD Functions

+ +

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

CUPS Imaging Library

+ +

The CUPS imaging library provides colorspace conversion, color +management, image management, scaling, image file, and raster functions +used by the CUPS raster filters. + +

Colorspace Conversion Functions

+ +

The colorspace conversion functions handle conversion of grayscale +and RGB colors to grayscale, RGB, K, CMY, CMYK, and CMYKcm colorspaces. + +

Color Management Functions

+ +

The color management functions handle gamut mapping and density +correction. These are integrated with the colorspace conversion +functions so that colorspace conversion and color management are +processed in a single step. + +

Image Management Functions

+ +

The image management functions manage a tiled image database that is +swapped to/from disk as needed. + +

Scaling Functions

+ +

The scaling functions provide image scaling services using +nearest-neighbor sampling and bilinear interpolation as appropriate. + +

Image File Functions

+ +

The image file functions handle loading of all image file formats. + +

Raster Functions

+ +

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

Daemons

+ +

The daemons provide additional network functions for the scheduler. +Currently only two daemons are provided with CUPS. + +

Line Printer Daemon

+ +

The line printer daemon provides remote LPD client support and is +run by the inetd(8) daemon as needed. + +

Polling Daemon

+ +

The polling daemon is used to poll a remote server for a list of +available printers and provide it to the scheduler for addition. A +separate polling daemon is run by the scheduler for every remote +system listed for polling in the scheduler configuration file. + +

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

pdftops

+ +

The pdftops filter converts PDF files into PostScript. + +

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

rastertoepson

+ +

The rastertoepson filter handles converting CUPS raster data to +ESC/P and supports both color and black-and-white printers. + +

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

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

Devices

+ +

The devices module is responsible for managing the list of available +devices for the CUPS-Get-Devices operation. + +

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

MIME

+ +

The Multimedia Internet Mail Exchange module manages 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. + +

PPDs

+ +

The PPDs module is responsible for managing the list of available +PPD files for the CUPS-Get-PPDs operation. + +

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) and "E" (enable and accept) are provided to configure +CUPS-specific features. + +

lpinfo

+ +

The lpinfo command lists the available PPD files or devices as selected +by the user. + +

lpmove

+ +

The lpmove command moves a print job to a new destination. + +

lpoptions

+ +

The lpoptions command manages user-defined printers and options. + +

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. + + + + + diff --git a/doc/spm.html b/doc/spm.html new file mode 100644 index 0000000000..7a2062095b --- /dev/null +++ b/doc/spm.html @@ -0,0 +1,8346 @@ + + + + CUPS Software Programmers Manual + + + + + + + +


+

CUPS Software Programmers Manual


+CUPS-SPM-1.1.5
+Easy Software Products
+Copyright 1997-2000, 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 - Software License Agreement + +B - Constants + +C - Structures + +D - Functions + +
+

Preface

+

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

+

System Overview

+

CUPS provides a portable printing layer for +UNIX®-based 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 ("IPP") +as the basis for managing print jobs and +queues. The Line Printer Daemon ("LPD") Server +Message Block ("SMB"), and AppSocket (a.k.a. +JetDirect) protocols are also supported with reduced +functionality. CUPS adds network printer browsing and +PostScript Printer Description ("PPD") based printing +options to support real-world printing under UNIX.

+

CUPS also includes a customized version of GNU +Ghostscript (currently based off GNU Ghostscript +5.50) and an image file RIP that are used to +support non-PostScript printers. Sample drivers for +HP and EPSON printers are included that use +these filters.

+ + + +

Document Overview

+

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

+ +

Notation Conventions

+

Various font and syntax conventions are used in +this guide. Examples and their meanings and uses +are explained below: +

+ + + + + + + + + + + + +
Example   Description
 
lpstat +

lpstat(1)
   The names +of commands; the first mention of a command or + function in a chapter is followed by a manual +page section number.
 
/var +

/usr/share/cups/data/testprint.ps
    +File and directory names.
 
Request ID is Printer-123 +   Screen output.
 
lp -d printer filename +ENTER   Literal user input; +special keys like ENTER are in ALL +CAPS.
 
12.3   Numbers in +the text are written using the period (.) to +indicate the decimal point.
+
+ + +

+

Abbreviations

+ The following abbreviations are used throughout this +manual: +
    +
    +
    kb
    +
    Kilobytes, or 1024 bytes +

     
    +
    Mb
    +
    Megabytes, or 1048576 bytes +

     
    +
    Gb
    +
    Gigabytes, or 1073741824 bytes +

     
    +
    +
+

Other References

+
    +
    +
    CUPS Software Administrators Manual
    +
    An administration guide for the CUPS software. +

     
    +
    CUPS Software Users Manual
    +
    An end-user guide for using the CUPS software. +

     
    +
    +
+

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 Mac OS, UNIX +has no standard interface or system in place +for supporting printers. Among the solutions +currently 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 and operating systems 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.

+

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. IPP +has been embraced by dozens of printer and +printer server manufacturers and is supported by +Microsoft Windows 2000.

+

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 capable and secure printing solution than +older ones.

+

IPP is layered on top of the Hyper-Text +Transport Protocol ("HTTP") which is the basis of +web servers on the Internet. This allows users +to view documentation, check status information on +a printer or server, and manage their printers, +classes, and jobs using their web browser.

+

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

+

Jobs

+

Each file or set of files 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.

+

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 Processor ("RIP") filters +that convert PostScript or image files into +bitmaps that can be sent to a raster printer. +

+

Backends

+

Backends perform the most important task of all +- they send the filtered print data to the +printer.

+

CUPS provides backends for printing over parallel, +serial, and USB ports, and over the network via +the IPP, JetDirect (AppSocket), and Line Printer +Daemon ("LPD") protocols. Additional backends are +available in network service packages such as the +SMB backend included with the popular SAMBA +software.

+

Backends are also used to determine the +available devices. On startup each backend is +asked for a list of devices it supports, and +any information that is available. This allows the +parallel backend to tell CUPS that an EPSON +Stylus Color 600 printer is attached to parallel +port 1, for example.

+

Printer Drivers

+

Printer drivers in CUPS consist of one of +more filters specific to a printer. CUPS includes +sample printer drivers for Hewlett-Packard LaserJet +and DeskJet printers and EPSON 9-pin, 24-pin, +Stylus Color, and Stylus Photo printers. While +these drivers do not generate optimal output for +the different printer models, they do provide +basic printing and 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. Users may then select a local printer +by name or a remote printer using "name@server". +

+

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 go down!

+

2 - The CUPS API

+

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

+

The CUPS API Library

+

The CUPS library provides a whole collection of +interfaces needed to support the internal needs of +the CUPS software as well as the needs of +applications, filters, printer drivers, and backends.

+

Unlike the rest of CUPS, the CUPS API +library is provided under the GNU Library General +Public License. This means that you can use the +CUPS API library in both proprietary and +open-source programs.

+

Programs that use the CUPS API library +typically will include the <cups/cups.h> + header file:

+
    +
    +#include <cups/cups.h>
    +
    +...
    +
    +jobid = cupsPrintFile("myprinter", "filename.ps", "title",
    +                      num_options, options);
    +
    +
+

Use the -lcups compiler option when +linking to the CUPS API library:

+
    +
    +cc -o program program.c -lcups ENTER
    +
    +
+

Additional options and libraries may be required +depending on the operating system and the location +of the CUPS API library.

+

Detecting the CUPS API Library in +GNU Autoconf

+

GNU autoconf is a popular configuration tool +used by many programs. Add the following lines +to your configure.in file to check for the +CUPS API library in your configuration script: +

+
    +
    +AC_CHECK_LIB(socket,socket,
    +if test "$uname" != "IRIX"; then
    +	LIBS="-lsocket $LIBS"
    +else
    +	echo "Not using -lsocket since you are running IRIX."
    +fi)
    +AC_CHECK_LIB(nsl,gethostbyaddr,
    +if test "$uname" != "IRIX"; then
    +	LIBS="-lnsl $LIBS"
    +else
    +	echo "Not using -lnsl since you are running IRIX."
    +fi)
    +
    +AC_CHECK_LIB(cups,httpConnect)
    +
    +
+

Printing Services

+

The CUPS API library provides some basic +printing services for applications that need to +print files.

+

Include Files

+

The include file used by all of these +functions is <cups/cups.h>:

+
    +
    +#include <cups/cups.h>
    +
    +
+

Printing a File

+

The CUPS API provides two functions for +printing files. The first is cupsPrintFile + which prints a single named file:

+
    +
    +#include <cups/cups.h>
    +
    +...
    +
    +int jobid;
    +
    +...
    +
    +jobid = cupsPrintFile("name", "filename", "title", 0, NULL);
    +
    +
+

The name string is the name of the +printer or class to print to. The filename + string is the name of the file to print. +The title string is the name of the +print job, e.g. "Acme Word Document".

+

The return value is a unique ID number for +the print job or 0 if there was an error.

+

Printing Multiple Files

+

The second printing function is cupsPrintFiles +:

+
    +
    +#include <cups/cups.h>
    +
    +...
    +
    +int        jobid;
    +int        num_files;
    +const char *files[100];
    +...
    +
    +jobid = cupsPrintFiles("name", num_files, files, "title", 0, NULL);
    +
    +
+

Instead of passing a filename string as with +cupsPrintFile(), you pass a file count ( +num_files) and filename pointer array ( +files) for each file that you want to +print.

+

As with cupsPrintFile(), the return +value is a unique ID for the print job.

+

Cancelling Jobs

+

The cupsCancelJob() function cancels a +queued print job:

+
    +
    +#include <cups/cups.h>
    +
    +...
    +
    +int jobid;
    +int status;
    +...
    +
    +status = cupsCancelJob("name", jobid);
    +
    +
+

The name string specifies the +destination and is used to determine the server +to send the request to. The jobid + value is the integer returned from a previous +cupsPrintFile() or cupsPrintFiles() call. +

+

cupsCancelJob() returns 1 if +the job was successfully cancelled and 0 + if there was an error.

+

Getting the Available Printers and +Classes

+

The cupsGetDests() function can be used +to get a list of the available printers, +classes, and instances that a user has defined:

+
    +
    +#include <cups/cups.h>
    +
    +...
    +
    +int         num_dests;
    +cups_dest_t *dests;
    +
    +...
    +
    +num_dests = cupsGetDests(&dests);
    +
    +
+

Each destination is stored in a cups_dest_t + structure which defines the printer or class +name, the instance name (if any), if it is +the default destination, and the default options +the user has defined for the destination:

+
    +
    +typedef struct               /**** Destination ****/
    +{
    +  char          *name,       /* Printer or class name */
    +                *instance;   /* Local instance name or NULL */
    +  int           is_default;  /* Is this printer the default? */
    +  int           num_options; /* Number of options */
    +  cups_option_t *options;    /* Options */
    +} cups_dest_t;
    +
    +
+

The destinations are sorted by name and +instance for your convenience. Once you have the +list of available destinations, you can lookup a +specific destination using the cupsGetDest() + function:

+
    +
    +#include <cups/cups.h>
    +
    +...
    +
    +int         num_dests;
    +cups_dest_t *dests;
    +cups_dest_t *mydest;
    +
    +...
    +
    +mydest = cupsGetDest("name", "instance", num_dests, dests);
    +
    +
+

The name string is the printer or +class name. You can pass a value of NULL + to get the default destination.

+

The instance string is the user-defined +instance name. Pass NULL to select the +default instance, e.g. "name" instead of +"name/instance".

+

Printing with Options

+

All of the previous printing examples have +passed 0 and NULL for the +last two arguments to the cupsPrintFile() + and cupsPrintFiles() functions. These last +two arguments are the number of options and a +pointer to the option array:

+
    +
    +int cupsPrintFile(const char *name, const char *filename, const char *title,
    +                  int num_options, cups_option_t *options);
    +int cupsPrintFiles(const char *name, int num_files, const char **files,
    +                   const char *title, int num_options,
    +		   cups_option_t *options);
    +
    +
+

The cups_option_t structure holds each +option and its value. These are converted as +needed and passed to the CUPS server when +printing a file.

+

The simplest way of handling options is to +use the num_options and options + members of the cups_dest_t structure +described earlier:

+
    +
    +#include <cups/cups.h>
    +
    +...
    +
    +int         jobid;
    +int         num_dests;
    +cups_dest_t *dests;
    +cups_dest_t *mydest;
    +
    +...
    +
    +mydest = cupsGetDest("name", "instance", num_dests, dests);
    +
    +jobid  = cupsPrintFile(mydest->name, "filename", "title",
    +                       mydest->num_options, mydest->options);
    +
    +
+

This effectively uses the options a user has +previous selected without a lot of code.

+

Setting Printer Options

+

Options can also be set by your program +using the cupsAddOption() function:

+
    +
    +#include <cups/cups.h>
    +
    +...
    +
    +int           num_options;
    +cups_option_t *options;
    +
    +...
    +
    +num_options = 0;
    +options     = NULL;
    +
    +...
    +
    +num_options = cupsAddOption("name", "value", num_options, &options);
    +num_options = cupsAddOption("name", "value", num_options, &options);
    +num_options = cupsAddOption("name", "value", num_options, &options);
    +num_options = cupsAddOption("name", "value", num_options, &options);
    +
    +
+

The name string is the name of the +option, and the value string is the +value for that option.

+

Each call to cupsAddOption() returns the +new number of options. Since adding two options +with the same name overwrites the first value +with the second, do not assume that calling +cupsAddOptions() 20 times will result in 20 +options.

+

Call cupsFreeOptions once you are done +using the options:

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

Getting Errors

+

If any of the CUPS API printing functions +returns an error, the reason for that error can +be found by calling cupsLastError() and +cupsErrorString(). cupsLastError() returns +the last IPP error code that was encountered. +cupsErrorString() converts the error code to a +localized message string suitable for presentation to +the user:

+
    +
    +#include <cups/cups.h>
    +
    +...
    +
    +int jobid;
    +
    +...
    +
    +if (jobid == 0)
    +  puts(cupsErrorString(cupsLastError()));
    +
    +
+

Passwords and Authentication

+

CUPS supports authentication of any request, +including submission of print jobs. The default +mechanism for getting the username and password is +to use the login user and a password from +the console.

+

To support other types of applications, in +particular Graphical User Interfaces ("GUIs"), the +CUPS API provides functions to set the default +username and to register a callback function that +returns a password string.

+

The cupsSetPasswordCB() + function is used to set a password callback +in your program. Only one function can be used +at any time.

+

The cupsSetUser() + function sets the current username for +authentication. This function can be called by +your password callback function to change the +current username as needed.

+

The following example shows a simple password +callback that gets a username and password from +the user:

+
    +
    +#include <cups/cups.h>
    +
    +const char *
    +my_password_cb(const char *prompt)
    +{
    +  char	user[65];
    +
    +
    +  puts(prompt);
    +
    + /* Get a username from the user */
    +  printf("Username: ");
    +  if (fgets(user, sizeof(user), stdin) == NULL)
    +    return (NULL);
    +
    + /* Strip the newline from the string and set the user */
    +  user[strlen(user) - 1] = '\0';
    +
    +  cupsSetUser(user);
    +
    + /* Use getpass() to ask for the password... */
    +  return (getpass("Password: "));
    +}
    +
    +...
    +
    +cupsSetPasswordCB(my_password_cb);
    +
    +
+

Similarly, a GUI interface could display the +prompt string in a window with input fields for +the username and password. The username should +probably default to the value of +cupsUser() to make things easier on the +user.

+

PPD Services

+

CUPS includes functions to access and manipulate +PostScript Printer Description ("PPD") files that are +used with the printer drivers in CUPS.

+

Each PPD file enumerates the available features +provided by a printer, including conflict information +for specific options (e.g. can't duplex output on +envelopes.)

+

Include Files

+

Include the <cups/ppd.h> header file to +use the PPD functions:

+
    +
    +#include <cups/ppd.h>
    +
    +
+

This header file is also included by the +<cups/cups.h> header file.

+

Getting a PPD File for a Printer +

+

The cupsGetPPD() function retrieves the +PPD file for the named printer or class:

+
    +
    +#include <cups/cups.h>
    +
    +...
    +
    +const char *filename;
    +
    +filename = cupsGetPPD("name");
    +
    +
+

The name string is the name of the +printer or class, including the remote server name +as appropriate (e.g. "printer@server".)

+

The return value is a pointer to a filename +in static storage; this value is overwritten with +each call to cupsGetPPD(). If the +printer or class does not exist, a NULL + pointer will be returned.

+

Loading a PPD File

+

The ppdOpenFile() function "opens" a PPD +file and loads it into memory:

+
    +
    +#include <cups/ppd.h>
    +
    +...
    +
    +ppd_file_t *ppd;
    +
    +ppd = ppdOpenFile("filename");
    +
    +
+

The filename string is the name of +the file to load, such as the value returned +by the cupsGetPPD() function.

+

The return value is a pointer to a structure +describing the contents of the PPD file or NULL +if the PPD file could not be read.

+

Freeing PPD File Information

+

Once you are done using a PPD file, call +the ppdClose() function to free all +memory that has been used:

+
    +
    +#include <cups/ppd.h>
    +
    +...
    +
    +ppd_file_t *ppd;
    +
    +...
    +
    +ppdClose(ppd);
    +
    +
+

The PPD File Structure

+

Each PPD file contains a number of capability +attributes, printer options, and conflict definitions. +The page size options also include the physical +margins for the printer and the minimum and +maximum sizes for the printer. All of this +information is stored in the ppd_file_t + structure.

+

Capabilities

+

Each PPD file contains a number of +informational attributes that describe the capabilities +of the printer. These are provided in the +ppd_file_t structure in the following members: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
MemberTypeDescription
accurate_screensint +1 = supports accurate screens
color_deviceint +1 = color device
colorspaceppd_cs_t +Default colorspace: PPD_CS_CMYK, PPD_CS_CMY, PPD_CS_GRAY, + PPD_CS_RGB, PPD_CS_RGBK, PPD_CS_N
contone_onlyint +1 = printer is continuous tone only
num_emulations +

emulations
int +

ppd_emul_t *
Emulations supported +by the printer
flip_duplexint +1 = need to flip odd pages when duplexing
num_fonts +

fonts
int +

char **
The fonts available on +the printer.
jcl_begin +

jcl_ps +

jcl_end
char * +Job Control Language commands for PostScript output
landscapeint +Landscape orientation, -90 or 90 degrees
lang_encodingchar * +The character used for the option strings
lang_versionchar * +The language used for the options strings +(English, French, etc.)
language_levelint +PostScript language level, 1 to 3
manual_copiesint +1 = Copies are done manually
model_numberint +Driver-specific model number.
patcheschar * +Patch commands to send to the printer
manufacturerchar * +The Manufacturer attribute from the PPD file, if +any
modelnamechar * +The ModelName attribute from the PPD file
nicknamechar * +The NickName attribute from the PPD file, if any +
productchar * +The Product attribute from the PPD file, if any +
shortnicknamechar * +The ShortNickName attribute from the PPD file, if +any
throughputint +Number of pages per minute
ttrasterizerchar * +The TruType font rasterizer (Type42)
variable_sizesint +1 = supports variable sizes
+
+

+

Options and Groups

+

PPD files support multiple options, which are +stored in ppd_option_t and ppd_choice_t + structures by the PPD functions.

+

Each option in turn is associated with a +group stored in the ppd_group_t structure. +Groups can be specified in the PPD file; if +an option is not associated with a group then +it is put in a "General" or "Extra" group +depending on the option.

+

Groups can also have sub-groups; CUPS currently +limits the depth of sub-groups to 1 level to +reduce programming complexity.

+

Conflicts

+

PPD files support specification of conflict +conditions between different options. Conflicts are +stored in ppd_conflict_t structures which +specify the options that conflict with each other. +

+

Page Sizes

+

PPD files specify all of the available pages +sizes and the physical margins associated with +them. These sizes are stored in ppd_size_t + structures and are available in the num_sizes + and sizes members of the +ppd_file_t structure. You can lookup a +particular page size with the ppdPageWidth() +, ppdPageLength(), and ppdPageSize() + functions:

+
    +
    +#include <cups/ppd.h>
    +
    +...
    +
    +ppd_file_t *ppd;
    +ppd_size_t *size;
    +float      width;
    +float      length;
    +
    +...
    +
    +size   = ppdPageSize(ppd, "size");
    +width  = ppdPageWidth(ppd, "size");
    +length = ppdPageLength(ppd, "size");
    +
    +
+

The size string is the named page +size option. The width and length are in +points; there are 72 points per inch. The +ppd_size_t structure contains the width, length, +and margin information:

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

Custom Page Sizes

+

Besides the standard page sizes listed in a +PPD file, some printers support variable or custom +page sizes. If variables_sizes is non-zero, +the custom_min, custom_max, +and custom_margins members of the +ppd_file_t structure define the limits of the +variable sizes.

+

To get the resulting media size, use a page +size string of Custom.widthxlength +, where width and length + are integer values in points:

+
    +
    +Custom.612x792   [8.5 inches wide, 11 inches long]
    +Custom.1224x792  [17 inches wide, 11 inches long]
    +
    +
+

Marking Options

+

Before marking any user-defined options, call the +ppdMarkDefaults() function to mark the default +options from the PPD file:

+
    +
    +#include <cups/ppd.h>
    +
    +...
    +
    +ppd_file_t *ppd;
    +
    +...
    +
    +ppdMarkDefaults(ppd);
    +
    +
+

Then call the ppdMarkOption() function +to mark individual options:

+
    +
    +#include <cups/ppd.h>
    +
    +...
    +
    +ppd_file_t *ppd;
    +int        conflicts;
    +
    +...
    +
    +conflicts = ppdMarkOption(ppd, "name", "value");
    +
    +
+

The name and value strings +choose a particular option and choice, respectively. +The return value is 0 if there are not +conflicts created by the selection.

+

CUPS also provides a convenience function for +marking all options in the cups_option_t + structure:

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

The cupsMarkOptions() function also handles +mapping the IPP job template attributes to PPD +options. The return value is the number of +conflicts present.

+

Checking for Conflicts

+

The ppdMarkOption() and cupsMarkOptions() + functions return the number of conflicts with +the currently marked options.

+

Call the ppdConflicts() function to get +the number of conflicts after you have marked +all of the options:

+
    +
    +#include <cups/cups.h>
    +
    +...
    +
    +ppd_file_t *ppd;
    +int        conflicts;
    +
    +...
    +
    +conflicts = ppdConflicts(ppd);
    +
    +
+

The return value is the number of conflicting +options, or 0 if there are no conflicts.

+

3 - Writing Filters +

+

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

+

Overview

+

File filters are programs that convert from one +or more MIME types to another type. Filters use +a common command-line and environment interface that +allows them to be joined as needed to print +files to any type of printer.

+

Security Considerations

+

Filters are normally run as a non-priviledged +user, so the major security consideration is +resource utilization - filters should not depend +on unlimited amounts of memory and disk space.

+

Users and Groups

+

The default CUPS configuration runs filters as +user "lp" and group "other".

+

Temporary Files

+

Temporary files should be created in the +directory specified by the "TMPDIR" environment +variable. The cupsTempFile() + function can be used to safely choose +temporary files in this directory.

+

Sending Messages to the User

+

The CUPS scheduler collects messages sent to +the standard error file by the filter. These +messages are relayed to the user based upon the +scheduler LogLevel directive.

+

The type of message is determined by an +initial prefix sent on each line:

+
    +
  • DEBUG: - a debug message
  • +
  • INFO: - an informational message
  • +
  • WARNING: - a warning message
  • +
  • ERROR: - an error message
  • +
  • PAGE: - a page accounting message
  • +
+

If the line of text does not begin with +any of the above prefixes, it is treated as +a debug message. Text following the prefix is +copied to the printer-state-message attribute +for the printer, and also added to the +error_log unless it is an informational or +page accounting message.

+

Page Accounting

+

Page accounting messages are used to inform the +server when one or more pages are printed. Each +line has the form:

+
    +
    +PAGE: page-number copy-count
    +
    +
+

The page-number field is the current page +number, starting at 1. The copy-count field +specifies the number of copies of that page +that was produced.

+

Page account messages are added to the +page_log file and cause the +job-sheets-completed attribute to be updated for +the job.

+

Command-Line Arguments

+

Every filter accepts exactly 6 or 7 +command-line arguments:

+
    +
    +printer job user title copies options [filename]
    +
    +
  • printer - The name of the printer +queue (normally this is the name of the +program being run)
  • +
  • job - The numeric job ID for the +job being printed
  • +
  • user - The string from the + originating-user-name attribute
  • +
  • title - The string from the + job-name attribute
  • +
  • copies - The numeric value from the + number-copies attribute
  • +
  • options - String representations of the + job template attributes, separated by spaces. +Boolean attributes are provided as "name" for +true values and "noname" for false values. All +other attributes are provided as "name=value" for + single-valued attributes and "name=value1,value2,...,valueN" +for set attributes
  • +
  • filename - The request file
  • +
+

The filename argument is only provided to +the first filter in the chain; all filters +must be prepared to read the print file +from the standard input if the filename + argument is omitted.

+

Copy Generation

+

The copies argument specifies the number of +copies to produce of the input file. In +general, you should only generate copies if the +filename argument is supplied. The only exception +to this are filters that produce device-independent +PostScript output (without any printer commands from +the printer's PPD file), since the PostScript +filter pstops is responsible for copy +generation.

+

Environment Variables

+

Every filter receives a fixed set of +environment variables that can be used by the +filter:

+
    +
  • CHARSET - The character set used by +the client for this print file
  • +
  • CONTENT_TYPE - The original document +type, such as "application/postscript"
  • +
  • CUPS_DATADIR - The location of CUPS +data files
  • +
  • CUPS_SERVERROOT - The location of CUPS +configuration files
  • +
  • DEVICE_URI - The output device URI
  • +
  • LANG - The language used by the +client for this print file
  • +
  • PATH - The execution path exported +to the filter
  • +
  • PPD - The full filename of the +printer's PPD file
  • +
  • PRINTER - The name of the printer +queue
  • +
  • RIP_CACHE - The maximum amount of +memory each filter should use
  • +
  • SOFTWARE - The name of the CUPS +software, typically "CUPS/1.1"
  • +
  • TZ - The local timezone
  • +
  • USER - The name of the current +user
  • +
+

Dissecting the HP-GL/2 Filter

+

The HP-GL/2 filter (hpgltops) +provided with CUPS is a complex program that +converts HP-GL/2 files into device-independent +PostScript output. Since it produces device-independent +PostScript output, it does not need to handle +copy generation or writing printer options from +the printer's PPD file.

+

Initializing the Filter

+

The first task of any filter is to ensure +that the correct number of command-line arguments +are present:

+
    +
    +if (argc < 6 || argc > 7)
    +{
    +  fputs("ERROR: hpgltops job-id user title copies options [file]\n", stderr);
    +  return (1);
    +}
    +
    +
+

After this you open the print file or read +from the standard input as needed:

+
    +
    +FILE *fp;
    +
    +/*
    + * 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);
    +  }
    +}
    +
    +
+

Once the print file has been opened, options +can be processed using the +cupsParseOptions() and +cupsGetOption() functions:

+
    +
    +int           num_options;
    +cups_option_t *options;
    +const char    *val;
    +
    +/*
    + * Process command-line options and write the prolog...
    + */
    +
    +options     = NULL;
    +num_options = cupsParseOptions(argv[5], 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)atoi(val) * 0.001f;
    +
    +
+

After the options have been processed, the +filter writes PostScript code to the standard +output based on the print file, closes the +print file (as needed), and returns 0 to the +scheduler.

+

PostScript Output

+

Filters that produce PostScript output must +generate output conforming to the Adobe Document +Structuring Conventions, 3.0. In general this means +the beginning of each file must begin with:

+
    +
    +%!PS-Adobe-3.0
    +%%BoundingBox: left bottom right top
    +%%Pages: (atend)
    +%%EndComments
    +
    +
+

The left, bottom, right, +and top values are integers in points from +the lower-lefthand corner of the page.

+

Pages must be surrounded by:

+
    +
    +%%Page: number number
    +gsave
    +...
    +grestore
    +showpage
    +
    +
+

And the end of each file must contain:

+
    +
    +%%Trailer
    +%%Pages: number-pages
    +%%EOF
    +
    +
+

These comments allow the PostScript filter to +correctly perform page accounting, copy generation, +N-up printing, and so forth.

+

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

+

Raster printers utilitize PPD files that specify +one or more device-specific filters that handle +converting print files for the printer. The +simplest raster printer drivers provide a single +filter that converts CUPS raster data to the +printer's native format.

+

CUPS Raster Data

+

CUPS raster data (application/vnd.cups-raster +) consists of a stream of raster page +descriptions produced by one of the RIP filters, +such as pstoraster or imagetoraster +.

+

Each page of data begins with a page +dictionary structure called +cups_raster_header_t. This structure contains +the colorspace, bits per color, media size, media +type, hardware resolution, and so forth.

+

After the page dictionary comes the page data +which is a full-resolution, uncompressed bitmap +representing the page in the printer's output +colorspace.

+

Page Accounting

+

Printer drivers must handle all page accounting. +This means they must send "PAGE:" messages to +the standard error file for each page (and in +many cases, copy) sent to the printer.

+

Color Management

+

Printer drivers can implement their color +management via the cupsColorProfile attributes +in the PPD file or internally in the driver +from a device-independent colorspace. In general, +color management performed by the RIP filters is +more efficient than that performed inside printer +drivers.

+

For example, the pstoraster filter often +only has to perform a color conversion once +each time the color is used for multiple output +pixels, while the raster filter must convert every +pixel on the page.

+

Device and Bitmap Variables

+

Besides the standard PostScript page device +dictionary variables defined in the Adobe PostScript +Level 3 reference manual, the CUPS filters support +additional variables that are passed in the page +device dictionary header for the page and in +some cases control the type of raster data that +is generated: +

+ + + + + + + + + + + + + + +
VariableTypeDescription
cupsWidthread-only integerWidth +of bitmap in pixels
cupsHeightread-only integer Height +of bitmap in pixels
cupsMediaTyperead-write integer +Device-specific media type code
cupsBitsPerColorread-write integer +Number of bits per color; 1, 2, 4, and 8 +are currently supported
cupsBitsPerPixelread-only integer +Number of bits per pixel; 1 to 32
cupsBytesPerLineread-only integer +Number of bytes per line of raster graphics
cupsColorOrderread-write enumThe +order of color values in the bitmap: +
    +
  • CUPS_ORDER_CHUNKED - CMYK CMYK CMYK
  • +
  • CUPS_ORDER_BANDED - CCC MMM YYY KKK
  • +
  • CUPS_ORDER_PLANAR - +CCC ... MMM ... YYY ... KKK ...
  • +
+
cupsColorSpaceread-write enumThe +colorspace of the bitmap: +
    +
  • CUPS_CSPACE_W - White (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 - Metallic yellow (gold), +metallic magenta, metallic cyan, black
  • +
  • CUPS_CSPACE_GMCS - Metallic yellow (gold), +metallic magenta, metallic cyan, metallic grey +(silver)
  • +
  • CUPS_CSPACE_WHITE - White pigment (black +as white pigment)
  • +
  • CUPS_CSPACE_GOLD - Gold foil (black as +gold foil)
  • +
  • CUPS_CSPACE_SILVER - Silver foil (black +as silver foil)
  • +
+
cupsCompressionread-write integer +Device-specific compression type code
cupsRowCountread-write integer +Device-specific row count value
cupsRowFeedread-write integer +Device-specific row feed value
cupsRowStepread-write integer +Device-specific row step value
+
+

+

Bitmaps with a colorspace of CUPS_CSPACE_KCMYcm +and more than 1 bit per color are transmitted +to the raster driver in KCMY colorspace; the +driver is responsible for producing the correct +separation of normal and light cyan and magenta +inks.

+

Dissecting the HP-PCL Driver

+

The HP-PCL driver provided with CUPS ( +rastertohp) converts bitmap data from the +raster filters into HP-PCL commands for most +PCL-compatible printers. The actual format of the +raster data is controlled by the PPD file being +used - deskjet.ppd or laserjet.ppd +.

+

PPD Files

+

PPD files play an important part of all +raster printer drivers. Options defined in the PPD +file contain PostScript commands that control the +raster data that is sent to the printer driver. +

+

A typical CUPS printer driver will include +ColorModel, InputSlot, PageSize +, PageRegion, and Resolution + options. Each option is shown using the standard +PPD format:

+
    +
    +*OpenUI *PageSize/Media Size: PickOne
    +*OrderDependency: 10 AnySetup *PageSize
    +*DefaultPageSize: Letter
    +*PageSize Letter/US Letter: "<<
    +/PageSize [612 792]
    +/ImagingBBox null
    +>> setpagedevice"
    +*End
    +*PageSize Legal/US Legal: "<<
    +/PageSize [612 1008]
    +/ImagingBBox null
    +>> setpagedevice"
    +*End
    +*PageSize A4/A4: "<<
    +/PageSize [595 842]
    +/ImagingBBox null
    +>> setpagedevice"
    +*End
    +*CloseUI: *PageSize
    +
    +
+

The OpenUI keyword specifies the new +option. The first name is the option with an +asterisk (*) in front of it. The first name +is usually followed by a slash (/) and a +human-readable version of the option name.

+

Every option must have a default value, +specified using the DefaultOption + keyword.

+

Each option begins with the option name +followed by the computer and human-readable values. +The PostScript commands follow these inside double +quotes. PostScript commands can be provided on a +single line:

+
    +
    +*PageSize A4/A4: "<</PageSize[595 842]/ImagingBBox null>> setpagedevice"
    +
    +
+

or broken down on separate lines using the +End keyword to terminate them:

+
    +
    +*PageSize A4/A4: "<<
    +/PageSize [595 842]
    +/ImagingBBox null
    +>> setpagedevice"
    +*End
    +
    +
+

The choice of the two formats is usually +esthetic. However, each line in a PPD file must +not exceed 255 characters, so if your PostScript +commands are long you may need to break them +up on separate lines.

+

Reading Raster Data

+

As with any filter, your printer driver should +handle raster data from a filename specified on +the command-line or from the standard input. The cupsRasterOpen() function +opens a raster stream for printing:

+
    +
    +int           fd;   /* File descriptor */
    +cups_raster_t *ras; /* Raster stream for printing */
    +
    +
    +/*
    + * 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);
    +
    +
+

Once you have opened the raster stream you +just need to read each page and print it:

+
    +
    +cups_raster_header_t header;
    +int                  y;
    +unsigned char        data[8192];
    +
    +while (cupsRasterReadHeader(ras, &header))
    +{
    +  ... initialize the printer ...
    +  for (y = header.cupsHeight; y > 0; y ++)
    +  {
    +    cupsRasterReadPixels(ras, data, header.cupsBytesPerLine);
    +    ... send raster line to printer ...
    +  }
    +}
    +
    +
+

After you have processed all pages, close the +raster stream and return:

+
    +
    +cupsRasterClose(ras);
    +
    +return (0);
    +
    +
+

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

+

Backends are special filters that communicate with +printers directly. They are treated slightly +differently than filters, however, and have some +unique requirements.

+

Security Considerations

+

Backends are run as the root user, so +special care must be taken to avoid potential +security violations. In particular, remember that a +backend will be able to manipulate disk files, +devices, and other resources that potentially could +damage a system or printer.

+

Command-Line Arguments

+

Besides the standard filter arguments, backends +are also run with no arguments to get a list +of available devices. This discovery process is +described later in this chapter.

+

Copy Generation

+

Like filters, backends should send multiple copies +of the print file only if a filename is +supplied on the command-line. Otherwise the backend +should assume that the upstream filter has already +added the necessary commands or data to produce +the multiple copies.

+

Page Accounting

+

Backend filters generally do not do page +accounting, however they should at a minimum +produce a single page message for each copy +that is produced when a filename is present on +the command-line. This is because the user +selected "raw" printing and no other accounting +information is possible.

+

Exclusive Access

+

Backends that talk to local character or block +devices should open the device file in exclusive +mode (O_EXCL) to cooperate with other +printers defined for the same device.

+

Retries

+

All backends must retry connections to the +device. This includes backends that talk to local +character or block devices, as the user may +define more than one printer queue pointing at +the same physical device.

+

To prevent excess CPU utilitization, the backend +should go to sleep for an amount of time +between retries; the CUPS-supplied backends retry +once every 30 seconds.

+

Dissecting the Serial Port Backend

+

The serial port backend provides support for +serial printers. Since it does everything a good +backend needs to do, it provides an excellent +example of what to do.

+

Supporting Device Discovery

+

As previously noted, backends are special filter +programs that talk to printer devices. Another +task a backend must perform is to list the +available devices it supports. The backend lists +the available devices when no additioanl arguments +are supplied on the command-line (i.e. just the +command name...)

+

The serial backend lists devices by looking at +serial port files in the /dev directory, +by consulting a hardware inventory (IRIX), and in +some cases by trying to open the ports to +see if they actually exist.

+

Once it finds a serial port it writes a +single line for each port to the standard error +file. Each line looks like this:

+
    +
    +serial serial:/dev/ttyS0?baud=115200 "Unknown" "Serial Port 1"
    +
    +
+

The first word "serial" is the device class +; this identifies the class of device which +can be used to categorize it in user +interfaces. CUPS currently recognizes the following +classes:

+
    +
  • "file" - a disk file.
  • +
  • "direct" - a parallel or fixed-rate serial +data port, currently used for Centronics, IEEE-1284, +and USB printer ports.
  • +
  • "serial" - a variable-rate serial port.
  • +
  • "network" - a network connection, typically via +AppSocket, HTTP, IPP, LPD, or SMB/CIFS protocols.
  • +
+

After the device class is the device URI +, in this case "serial:/dev/ttyS0?baud=115200". This +is the URI that should be used by the user +to select this port. For serial ports, the +"baud=115200" specifies the maximum baud rate +supported by the port - the actual value will +vary based on the speed the user selects for +the printer.

+

The last two strings are the model and +description for the port. The "Unknown" string +means that the printer model is unknown - some +devices are able to provide a make and model +such as "HP DeskJet" that allows users and +software to choose an appropriate printer driver +more easily. Both the model and description must +be enclosed inside double quotes.

+

Opening the Serial Port

+

As noted previously, all backends should open +device files in exclusive mode, and retry as +needed until the port is available. The serial +port does this using a do-while loop:

+
    +
    +do
    +{
    +  if ((fd = open(resource, O_WRONLY | O_NOCTTY | O_EXCL)) == -1)
    +  {
    +    if (errno == EBUSY)
    +    {
    +      fputs("INFO: Serial port busy; will retry in 30 seconds...\n", stderr);
    +      sleep(30);
    +    }
    +    else
    +    {
    +      perror("ERROR: Unable to open serial port device file");
    +      return (1);
    +    }
    +  }
    +}
    +while (fd < 0);
    +
    +
+

If the port is busy or in use by another +process, the backend will go to sleep for 30 +seconds and try again. If another error is +detected a message is sent to the user and +the backend aborts the print job until the +problem can be corrected.

+

Writing Data to the Port

+

Network and character devices pose an interesting +problem when writing data to the port - they +may not be able to write all of the bytes +in your buffer before returning. To work around +this problem you must loop until all bytes have +been written:

+
    +
    +while (nbytes > 0)
    +{
    +  if ((wbytes = write(fd, bufptr, nbytes)) < 0)
    +    if (errno == ENOTTY)
    +      wbytes = write(fd, bufptr, nbytes);
    +
    +  if (wbytes < 0)
    +  {
    +    perror("ERROR: Unable to send print file to printer");
    +    break;
    +  }
    +
    +  nbytes -= wbytes;
    +  bufptr += wbytes;
    +}
    +
    +
+

The check for the ENOTTY error is +needed on some platforms to clear an error from +a previous ioctl() call.

+

Finishing Up

+

Once you have sent the print file, return 0 +if the file printed successfully or 1 if it +did not. This will allow the scheduler to stop +the print job if there is a device error, +preserving the print job for later printing once +the problem has been corrected.

+

A - Software License +Agreement

+

Common UNIX Printing System +License Agreement

+

Copyright 1997-2000 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, +("CUPSTM"), is provided under the GNU +General Public License ("GPL") and GNU Library +General Public License ("LGPL"), Version 2. A copy +of these licenses follow this introduction.

+

The GNU LGPL applies to the CUPS API +library, located in the "cups" subdirectory of the +CUPS source distribution and in the +"/usr/include/cups" directory and "libcups.a", +"libcups.sl", or "libcups.so" files in the binary +distributions.

+

The GNU GPL applies to the remainder of the +CUPS distribution, including the "pstoraster" filter +which is based upon GNU Ghostscript 5.50 and +the "pdftops" filter which is based upon Xpdf +0.90.

+

For those not familiar with the GNU GPL, the +license basically allows you to:

+
    +
  • Use the CUPS software at no charge.
  • +
  • Distribute verbatim copies of the software in +source or binary form.
  • +
  • Sell verbatim copies of the software for a +media fee, or sell support for the software.
  • +
  • Distribute or sell printer drivers and filters +that use CUPS so long as source code is +made available under the GPL.
  • +
+

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 must provide source for any new +drivers, changes, or additions to the software, +and all code must be provided under the GPL +or LGPL as appropriate.

+

The GNU LGPL relaxes the "link-to" restriction, +allowing you to develop applications that use the +CUPS API library under other licenses and/or +conditions as appropriate for your application.

+

Trademarks

+

Easy Software Products has trademarked the Common +UNIX Printing System, CUPS, and CUPS logo. These +names and logos may be used freely in any +direct port or binary distribution of CUPS. To +use them in derivative products, please contract +Easy Software Products for written permission. Our +intention is to protect the value of these +trademarks and ensure that any derivative product +meets the same high-quality standards as the +original.

+

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, additions, and +modifications to CUPS under the GNU GPL and +LGPL. For information please contact us at the +address shown above.

+

The Common UNIX Printing System provides a +"pstoraster" filter that utilizes the GNU GhostScript +5.50 core 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 +

+

The "pdftops" filter is based on the Xpdf +0.90 software. For binary distribution licensing of +this software, please contact:

Derek B. +Noonburg +

Email: +derekn@foolabs.com +

WWW: +http://www.foolabs.com/xpdf/

+

Support

+

Easy Software Products sells software support for +CUPS as well as a commercial printing product +based on CUPS called ESP Print Pro. You can +find out more at our web site:

+ + + + +

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

    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.

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

    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.

    +
  5. 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. +
    3. 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.
    4. +
    5. 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.)
    6. +
    +
  6. +

    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.

    +
  7. 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. +
    3. 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,
    4. +
    5. 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.)
    6. +
    +
  8. +

    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.

    +
  9. 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.
  10. +
  11. 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.
  12. +
  13. 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.
  14. +
  15. 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.
  16. +

    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.

    +
  17. 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.
  18. +
  19. 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.
  20. +

    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.

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

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

END OF TERMS AND CONDITIONS

+ + + +

GNU LIBRARY GENERAL PUBLIC LICENSE

+

Version 2, June 1991

+
+Copyright (C) 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.
+
+[This is the first released version of the library GPL.  It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+

Preamble

+

The licenses for most software are designed to +take away your freedom to share and change it. + By contrast, the GNU General Public Licenses are +intended to guarantee your freedom to share and +change free software--to make sure the software is +free for all its users.

+

This license, the Library General Public License, +applies to some specially designated Free Software +Foundation software, and to any other libraries +whose authors decide to use it. You can use +it for your libraries, 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 +library, or if you modify it.

+

For example, if you distribute copies of the +library, whether gratis or for a fee, you must +give the recipients all the rights that we gave +you. You must make sure that they, too, +receive or can get the source code. If you +link a program with the library, you must +provide complete object files to the recipients so +that they can relink them with the library, +after making changes to the library and +recompiling it. And you must show them these +terms so they know their rights.

+

Our method of protecting your rights has two +steps: (1) copyright the library, and (2) offer +you this license which gives you legal permission +to copy, distribute and/or modify the library.

+

Also, for each distributor's protection, we want +to make certain that everyone understands that +there is no warranty for this free library. If +the library is modified by someone else and +passed on, we want its recipients to know that +what they have is not the original version, 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 companies distributing free software will +individually obtain patent licenses, thus in effect +transforming the program into proprietary software. + To prevent this, we have made it clear that +any patent must be licensed for everyone's free +use or not licensed at all.

+

Most GNU software, including some libraries, is +covered by the ordinary GNU General Public +License, which was designed for utility programs. + This license, the GNU Library General Public +License, applies to certain designated libraries. + This license is quite different from the ordinary +one; be sure to read it in full, and don't +assume that anything in it is the same as in +the ordinary license.

+

The reason we have a separate public license +for some libraries is that they blur the +distinction we usually make between modifying or +adding to a program and simply using it. + Linking a program with a library, without +changing the library, is in some sense simply +using the library, and is analogous to running +a utility program or application program. However, +in a textual and legal sense, the linked +executable is a combined work, a derivative of +the original library, and the ordinary General +Public License treats it as such.

+

Because of this blurred distinction, using the +ordinary General Public License for libraries did +not effectively promote software sharing, because +most developers did not use the libraries. We +concluded that weaker conditions might promote +sharing better.

+

However, unrestricted linking of non-free programs +would deprive the users of those programs of +all benefit from the free status of the +libraries themselves. This Library General Public +License is intended to permit developers of +non-free programs to use free libraries, while +preserving your freedom as a user of such +programs to change the free libraries that are +incorporated in them. (We have not seen how to +achieve this as regards changes in header files, +but we have achieved it as regards changes in +the actual functions of the Library.) The hope +is that this will lead to faster development of +free libraries.

+

The precise terms and conditions for copying, +distribution and modification follow. Pay close +attention to the difference between a "work based +on the library" and a "work that uses the +library". The former contains code derived from +the library, while the latter only works together +with the library.

+

Note that it is possible for a library to +be covered by the ordinary General Public License +rather than by this special one.

+

TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION +AND MODIFICATION

+

0. This License Agreement applies to +any software library which contains a notice +placed by the copyright holder or other authorized +party saying it may be distributed under the +terms of this Library General Public License (also +called "this License"). Each licensee is addressed +as "you".

+

A "library" means a collection of software +functions and/or data prepared so as to be +conveniently linked with application programs (which +use some of those functions and data) to form +executables.

+

The "Library", below, refers to any such +software library or work which has been +distributed under these terms. A "work based on +the Library" means either the Library or any +derivative work under copyright law: that is to +say, a work containing the Library or a portion +of it, either verbatim or with modifications +and/or translated straightforwardly into another +language. (Hereinafter, translation is included without +limitation in the term "modification".)

+

"Source code" for a work means the preferred +form of the work for making modifications to +it. For a library, 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 library.

+

Activities other than copying, distribution and +modification are not covered by this License; they +are outside its scope. The act of running a +program using the Library is not restricted, and +output from such a program is covered only if +its contents constitute a work based on the +Library (independent of the use of the Library +in a tool for writing it). Whether that is +true depends on what the Library does and what +the program that uses the Library does.

+

1. You may copy and distribute +verbatim copies of the Library's complete 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 distribute a copy +of this License along with the Library.

+

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.

+

2. You may modify your copy or +copies of the Library or any portion of it, +thus forming a work based on the Library, 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. The modified work must itself be a software +library.
  2. +

    +
  3. You must cause the files modified to carry +prominent notices stating that you changed the +files and the date of any change.
  4. +

    +
  5. You must cause the whole of the work to +be licensed at no charge to all third parties +under the terms of this License.
  6. +

    +
  7. If a facility in the modified Library refers +to a function or a table of data to be +supplied by an application program that uses the +facility, other than as an argument passed when +the facility is invoked, then you must make a +good faith effort to ensure that, in the event +an application does not supply such function or + table, the facility still operates, and performs +whatever part of its purpose remains meaningful.
  8. +

    (For example, a function in a library to +compute square roots has a purpose that is +entirely well-defined independent of the application. + Therefore, Subsection 2d requires that any + application-supplied function or table used by this +function must be optional: if the application +does not supply it, the square root function +must still compute square roots.)

    +
+

These requirements apply to the modified work +as a whole. If identifiable sections of that +work are not derived from the Library, 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 Library, 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 +Library.

+

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

+

3. You may opt to apply the +terms of the ordinary GNU General Public License +instead of this License to a given copy of +the Library. To do this, you must alter all +the notices that refer to this License, so that +they refer to the ordinary GNU General Public +License, version 2, instead of to this License. + (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, +then you can specify that version instead if +you wish.) Do not make any other change in +these notices.

+

Once this change is made in a given copy, +it is irreversible for that copy, so the +ordinary GNU General Public License applies to all +subsequent copies and derivative works made from +that copy.

+

This option is useful when you wish to copy +part of the code of the Library into a +program that is not a library.

+

4. You may copy and distribute +the Library (or a portion or derivative of it, +under Section 2) in object code or executable +form under the terms of Sections 1 and 2 +above provided that you 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.

+

If distribution of 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 satisfies the requirement +to distribute the source code, even though third +parties are not compelled to copy the source +along with the object code.

+

5. A program that contains no +derivative of any portion of the Library, but +is designed to work with the Library by being +compiled or linked with it, is called a "work +that uses the Library". Such a work, in +isolation, is not a derivative work of the +Library, and therefore falls outside the scope of +this License.

+

However, linking a "work that uses the Library" +with the Library creates an executable that is +a derivative of the Library (because it contains +portions of the Library), rather than a "work +that uses the library". The executable is +therefore covered by this License. Section 6 +states terms for distribution of such executables.

+

When a "work that uses the Library" uses +material from a header file that is part of +the Library, the object code for the work may +be a derivative work of the Library even though +the source code is not. Whether this is true +is especially significant if the work can be +linked without the Library, or if the work is +itself a library. The threshold for this to be +true is not precisely defined by law.

+

If such an object file uses only numerical +parameters, data structure layouts and accessors, and +small macros and small inline functions (ten lines +or less in length), then the use of the +object file is unrestricted, regardless of whether +it is legally a derivative work. (Executables +containing this object code plus portions of the +Library will still fall under Section 6.)

+

Otherwise, if the work is a derivative of +the Library, you may distribute the object code +for the work under the terms of Section 6. +Any executables containing that work also fall +under Section 6, whether or not they are linked +directly with the Library itself.

+

6. As an exception to the +Sections above, you may also compile or link a +"work that uses the Library" with the Library +to produce a work containing portions of the +Library, and distribute that work under terms of +your choice, provided that the terms permit +modification of the work for the customer's own +use and reverse engineering for debugging such +modifications.

+

You must give prominent notice with each copy +of the work that the Library is used in it +and that the Library and its use are covered +by this License. You must supply a copy of +this License. If the work during execution +displays copyright notices, you must include the +copyright notice for the Library among them, as +well as a reference directing the user to the +copy of this License. Also, you must do one +of these things:

+
    +
  1. Accompany the work with the complete +corresponding machine-readable source code for the +Library including whatever changes were used in +the work (which must be distributed under + Sections 1 and 2 above); and, if the work +is an executable linked with the Library, with +the complete machine-readable "work that uses the +Library", as object code and/or source code, so +that the user can modify the Library and then +relink to produce a modified executable containing +the modified Library. (It is understood that the +user who changes the contents of definitions files +in the Library will not necessarily be able to +recompile the application to use the modified +definitions.)
  2. +

    +
  3. Accompany the work with a written offer, valid +for at least three years, to give the same +user the materials specified in Subsection 6a, +above, for a charge no more than the cost +of performing this distribution.
  4. +

    +
  5. If distribution of the work is made by +offering access to copy from a designated place, +offer equivalent access to copy the above + specified materials from the same place.
  6. +

    +
  7. Verify that the user has already received a +copy of these materials or that you have +already sent this user a copy.
  8. +
+

For an executable, the required form of the +"work that uses the Library" must include any +data and utility programs needed for reproducing +the executable from it. 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.

+

It may happen that this requirement contradicts +the license restrictions of other proprietary +libraries that do not normally accompany the +operating system. Such a contradiction means you +cannot use both them and the Library together +in an executable that you distribute.

+

7. You may place library facilities +that are a work based on the Library +side-by-side in a single library together with +other library facilities not covered by this +License, and distribute such a combined library, +provided that the separate distribution of the +work based on the Library and of the other +library facilities is otherwise permitted, and +provided that you do these two things:

+
    +
  1. Accompany the combined library with a copy of +the same work based on the Library, uncombined +with any other library facilities. This must be +distributed under the terms of the Sections +above.
  2. +

    +
  3. Give prominent notice with the combined library +of the fact that part of it is a work +based on the Library, and explaining where to +find the accompanying uncombined form of the same +work.
  4. +
+

8. You may not copy, modify, +sublicense, link with, or distribute the Library +except as expressly provided under this License. + Any attempt otherwise to copy, modify, sublicense, +link with, or distribute the Library 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.

+

9. 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 Library or its derivative +works. These actions are prohibited by law if +you do not accept this License. Therefore, by +modifying or distributing the Library (or any work +based on the Library), you indicate your +acceptance of this License to do so, and all +its terms and conditions for copying, distributing +or modifying the Library or works based on it. +

+

10. Each time you redistribute the +Library (or any work based on the Library), the +recipient automatically receives a license from the +original licensor to copy, distribute, link with +or modify the Library 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.

+

11. 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 Library at +all. For example, if a patent license would +not permit royalty-free redistribution of the Library +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 +Library.

+

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.

+

12. If the distribution and/or use +of the Library is restricted in certain countries +either by patents or by copyrighted interfaces, +the original copyright holder who places the +Library 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.

+

13. The Free Software Foundation may +publish revised and/or new versions of the Library +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 Library 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 Library does not +specify a license version number, you may choose +any version ever published by the Free Software +Foundation.

+

14. If you wish to incorporate +parts of the Library into other free programs +whose distribution conditions are incompatible with +these, 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

+

15. BECAUSE THE LIBRARY IS LICENSED +FREE OF CHARGE, THERE IS NO WARRANTY FOR THE +LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE +LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE +COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE +LIBRARY "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 +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE +DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY +SERVICING, REPAIR OR CORRECTION.

+

16. 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 LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE +WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER +OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES.

+

END OF TERMS AND CONDITIONS

+

B - Constants

+

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

+

CUPS Constants

+

Version Number

+

The CUPS_VERSION constant is a +floating-point number representing the API version +number. The current version number is 1.0100 which +represents CUPS version 1.1.0.

+

Printer Capabilities

+

The CUPS_PRINTER constants represent +capability bits for printers and classes:

+
    +
  • CUPS_PRINTER_LOCAL - Is a local printer +or class.
  • +
  • CUPS_PRINTER_REMOTE - Is a remote +printer or class.
  • +
  • CUPS_PRINTER_CLASS - Is a class.
  • +
  • CUPS_PRINTER_BW - Printer prints in +black and white.
  • +
  • CUPS_PRINTER_COLOR - Printer prints in +color.
  • +
  • CUPS_PRINTER_DUPLEX - Printer can print +double-sided.
  • +
  • CUPS_PRINTER_STAPLE - Printer can staple +output.
  • +
  • CUPS_PRINTER_COPIES - Printer can produce +multiple copies on its own.
  • +
  • CUPS_PRINTER_COLLATE - Printer can collate +copies.
  • +
  • CUPS_PRINTER_PUNCH - Printer can punch +holes in output.
  • +
  • CUPS_PRINTER_COVER - Printer can put +covers on output.
  • +
  • CUPS_PRINTER_BIND - Printer can bind +output.
  • +
  • CUPS_PRINTER_SORT - Printer can sort +output.
  • +
  • CUPS_PRINTER_SMALL - Printer can print +on media up to 9x14 inches.
  • +
  • CUPS_PRINTER_MEDIUM - Printer can print +on media from 9x14 to 18x24 inches.
  • +
  • CUPS_PRINTER_LARGE - Printer can print +on media larger than 18x24 inches.
  • +
  • CUPS_PRINTER_VARIABLE - Printer can print +on variable or custom media sizes.
  • +
  • CUPS_PRINTER_IMPLICIT - Is an implicit +class.
  • +
  • CUPS_PRINTER_OPTIONS - All of the +printer capability and option bits.
  • +
+

Encodings

+

CUPS defines the following character set encoding +constants:

+
    +
  • CUPS_US_ASCII - US ASCII character set. +
  • +
  • CUPS_UTF_8 - UTF-8 encoding of Unicode. +
  • +
  • CUPS_ISO8859_1 - ISO-8859-1 character set. +
  • +
  • CUPS_ISO8859_2 - ISO-8859-2 character set. +
  • +
  • CUPS_ISO8859_3 - ISO-8859-3 character set. +
  • +
  • CUPS_ISO8859_4 - ISO-8859-4 character set. +
  • +
  • CUPS_ISO8859_5 - ISO-8859-5 character set. +
  • +
  • CUPS_ISO8859_6 - ISO-8859-6 character set. +
  • +
  • CUPS_ISO8859_7 - ISO-8859-7 character set. +
  • +
  • CUPS_ISO8859_8 - ISO-8859-8 character set. +
  • +
  • CUPS_ISO8859_9 - ISO-8859-9 character set. +
  • +
  • CUPS_ISO8859_10 - ISO-8859-10 character +set.
  • +
  • CUPS_ISO8859_13 - ISO-8859-13 character +set.
  • +
  • CUPS_ISO8859_14 - ISO-8859-14 character +set.
  • +
  • CUPS_ISO8859_15 - ISO-8859-15 character +set.
  • +
  • CUPS_WINDOWS_874 - Windows code page +874.
  • +
  • CUPS_WINDOWS_1250 - Windows code page +1250.
  • +
  • CUPS_WINDOWS_1251 - Windows code page +1251.
  • +
  • CUPS_WINDOWS_1252 - Windows code page +1252.
  • +
  • CUPS_WINDOWS_1253 - Windows code page +1253.
  • +
  • CUPS_WINDOWS_1254 - Windows code page +1254.
  • +
  • CUPS_WINDOWS_1255 - Windows code page +1255.
  • +
  • CUPS_WINDOWS_1256 - Windows code page +1256.
  • +
  • CUPS_WINDOWS_1257 - Windows code page +1257.
  • +
  • CUPS_WINDOWS_1258 - Windows code page +1258.
  • +
+

HTTP Constants

+

Limits

+

The following constants define the limits for +strings:

+
    +
  • HTTP_MAX_BUFFER - Size of socket +buffer.
  • +
  • HTTP_MAX_HOST - Maximum length of +hostname.
  • +
  • HTTP_MAX_URI - Maximum length of URI. +
  • +
  • HTTP_MAX_VALUE - Maximum length of +field values.
  • +
+

Status Codes

+

The following status codes can be returned by +httpUpdate():

+
    +
  • HTTP_ERROR - A network error occurred +
  • +
  • HTTP_CONTINUE - Continue response from +HTTP proxy
  • +
  • HTTP_OK - 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
  • +
  • HTTP_RESET_CONTENT - Content was +reset/recreated
  • +
  • HTTP_PARTIAL_CONTENT - Only a partial +file was recieved/sent
  • +
  • HTTP_MULTIPLE_CHOICES - 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 - 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 - 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
  • +
+

Fields

+

The following fields are indices for each of +the standard HTTP fields in HTTP 1/1:

+
    +
  • HTTP_FIELD_ACCEPT_LANGUAGE - Accept-Language
  • +
  • HTTP_FIELD_ACCEPT_RANGES - Accept-Ranges
  • +
  • HTTP_FIELD_AUTHORIZATION - Authorization
  • +
  • HTTP_FIELD_CONNECTION - Connection
  • +
  • HTTP_FIELD_CONTENT_ENCODING - Content-Encoding +
  • +
  • HTTP_FIELD_CONTENT_LANGUAGE - Content-Language +
  • +
  • HTTP_FIELD_CONTENT_LENGTH - Content-Length
  • +
  • HTTP_FIELD_CONTENT_LOCATION - Content-Location +
  • +
  • HTTP_FIELD_CONTENT_MD5 - Content-MD5
  • +
  • HTTP_FIELD_CONTENT_RANGE - Content-Range
  • +
  • HTTP_FIELD_CONTENT_TYPE - Content-Type
  • +
  • HTTP_FIELD_CONTENT_VERSION - Content-Version
  • +
  • HTTP_FIELD_DATE - Date
  • +
  • HTTP_FIELD_HOST - Host
  • +
  • HTTP_FIELD_IF_MODIFIED_SINCE - If-Modified-Since +
  • +
  • HTTP_FIELD_IF_UNMODIFIED_SINCE - +If-Unmodified-Since
  • +
  • HTTP_FIELD_KEEP_ALIVE - Keep-Alive
  • +
  • HTTP_FIELD_LAST_MODIFIED - Last-Modified
  • +
  • HTTP_FIELD_LINK - Link
  • +
  • HTTP_FIELD_LOCATION - Location
  • +
  • HTTP_FIELD_RANGE - Range
  • +
  • HTTP_FIELD_REFERER - Referer
  • +
  • HTTP_FIELD_RETRY_AFTER - Retry-After
  • +
  • HTTP_FIELD_TRANSFER_ENCODING - Transfer-Encoding +
  • +
  • HTTP_FIELD_UPGRADE - Upgrade
  • +
  • HTTP_FIELD_USER_AGENT - User-Agent
  • +
  • HTTP_FIELD_WWW_AUTHENTICATE - WWW-Authenticate +
  • +
+

IPP Constants

+

Limits

+

The following constants define array limits for +IPP data:

+
    +
  • IPP_MAX_NAME - Maximum length of an +attribute name
  • +
  • IPP_MAX_VALUES - Maximum number of +set-of values that can be read in a request. +
  • +
+

Tags

+
    +
  • IPP_TAG_ZERO - Wildcard tag value for +searches; also used to separate groups of +attributes
  • +
  • IPP_TAG_OPERATION - Tag for values of +type operation
  • +
  • IPP_TAG_JOB - Tag for values of type +job
  • +
  • IPP_TAG_END - Tag for values of type +end
  • +
  • IPP_TAG_PRINTER - Tag for values of +type printer
  • +
  • IPP_TAG_UNSUPPORTED_GROUP - Tag for values +of type unsupported_group
  • +
  • IPP_TAG_UNSUPPORTED_VALUE - Tag for values +of type unsupported_value
  • +
  • IPP_TAG_DEFAULT - Tag for values of +type default
  • +
  • IPP_TAG_UNKNOWN - Tag for values of +type unknown
  • +
  • IPP_TAG_NOVALUE - Tag for values of +type novalue
  • +
  • IPP_TAG_NOTSETTABLE - Tag for values of +type notsettable
  • +
  • IPP_TAG_DELETEATTR - Tag for values of +type deleteattr
  • +
  • IPP_TAG_ANYVALUE - Tag for values of +type anyvalue
  • +
  • IPP_TAG_INTEGER - Tag for values of +type integer
  • +
  • IPP_TAG_BOOLEAN - Tag for values of +type boolean
  • +
  • IPP_TAG_ENUM - Tag for values of +type enum
  • +
  • IPP_TAG_STRING - Tag for values of +type string
  • +
  • IPP_TAG_DATE - Tag for values of +type date
  • +
  • IPP_TAG_RESOLUTION - Tag for values of +type resolution
  • +
  • IPP_TAG_RANGE - Tag for values of +type range
  • +
  • IPP_TAG_COLLECTION - Tag for values of +type collection
  • +
  • IPP_TAG_TEXTLANG - Tag for values of +type textlang
  • +
  • IPP_TAG_NAMELANG - Tag for values of +type namelang
  • +
  • IPP_TAG_TEXT - Tag for values of +type text
  • +
  • IPP_TAG_NAME - Tag for values of +type name
  • +
  • IPP_TAG_KEYWORD - Tag for values of +type keyword
  • +
  • IPP_TAG_URI - Tag for values of type +uri
  • +
  • IPP_TAG_URISCHEME - Tag for values of +type urischeme
  • +
  • IPP_TAG_CHARSET - Tag for values of +type charset
  • +
  • IPP_TAG_LANGUAGE - Tag for values of +type language
  • +
  • IPP_TAG_MIMETYPE - Tag for values of +type mimetype
  • +
+

Resolution Units

+

The IPP_RES_PER_INCH and IPP_RES_PER_CM + constants specify dots per inch and dots +per centimeter, respectively.

+

Finishings

+

The finishing values specify special finishing +operations to be performed on the job.

+
    +
  • IPP_FINISH_NONE - Do no finishing
  • +
  • IPP_FINISH_STAPLE - Staple the job
  • +
  • IPP_FINISH_PUNCH - Punch the job
  • +
  • IPP_FINISH_COVER - Cover the job
  • +
  • IPP_FINISH_BIND - Bind the job
  • +
+

Orientations

+

The orientation values specify the orientation of +the job.

+
    +
  • IPP_PORTRAIT - No rotation
  • +
  • IPP_LANDSCAPE - 90 degrees +counter-clockwise
  • +
  • IPP_REVERSE_LANDSCAPE - 90 degrees +clockwise
  • +
  • IPP_REVERSE_PORTRAIT - 180 degrees
  • +
+

Qualities

+

The quality values specify the desired quality +of the print.

+
    +
  • IPP_QUALITY_DRAFT - Draft quality
  • +
  • IPP_QUALITY_NORMAL - Normal quality
  • +
  • IPP_QUALITY_HIGH - High quality
  • +
+

Job States

+

The job state values are used to represent +the current job state.

+
    +
  • IPP_JOB_PENDING - Job is pending
  • +
  • IPP_JOB_HELD - Job is held
  • +
  • IPP_JOB_PROCESSING - Job is processing
  • +
  • IPP_JOB_STOPPED - Job is stopped
  • +
  • IPP_JOB_CANCELLED - Job is cancelled
  • +
  • IPP_JOB_ABORTED - Job is aborted
  • +
  • IPP_JOB_COMPLETED - Job is completed
  • +
+

Printer States

+

The printer state values are used to represent +the current printer state.

+
    +
  • IPP_PRINTER_IDLE - Printer is idle
  • +
  • IPP_PRINTER_PROCESSING - Printer is +processing
  • +
  • IPP_PRINTER_STOPPED - Printer is stopped +
  • +
+

Operations

+

The operation values represent the available IPP +operations.

+
    +
  • IPP_PRINT_JOB - Print a file
  • +
  • IPP_PRINT_URI - Print a URI
  • +
  • IPP_VALIDATE_JOB - Validate job attributes +
  • +
  • IPP_CREATE_JOB - Create a new job
  • +
  • IPP_SEND_DOCUMENT - Send a document to +a job
  • +
  • IPP_SEND_URI - Send a URI to a +job
  • +
  • IPP_CANCEL_JOB - Cancel a job
  • +
  • IPP_GET_JOB_ATTRIBUTES - Get job +attributes
  • +
  • IPP_GET_JOBS - Get a list of all +jobs
  • +
  • IPP_GET_PRINTER_ATTRIBUTES - Get printer +attributes
  • +
  • IPP_HOLD_JOB - Hold a pending job
  • +
  • IPP_RELEASE_JOB - Release a held job
  • +
  • IPP_RESTART_JOB - Restart a completed +job
  • +
  • IPP_PAUSE_PRINTER - Pause a printer
  • +
  • IPP_RESUME_PRINTER - Restart a paused +printer
  • +
  • IPP_PURGE_JOBS - Purge jobs from the +queue
  • +
  • IPP_SET_PRINTER_ATTRIBUTES - Set printer +attributes
  • +
  • IPP_SET_JOB_ATTRIBUTES - Set job +attributes
  • +
  • IPP_GET_PRINTER_SUPPORTED_VALUES - Get +printer supported values
  • +
  • CUPS_GET_DEFAULT - Get the default +destination
  • +
  • CUPS_GET_PRINTERS - Get a list of +all printers
  • +
  • CUPS_ADD_PRINTER - Add or modify a +printer
  • +
  • CUPS_DELETE_PRINTER - Delete a printer
  • +
  • CUPS_GET_CLASSES - Get a list of all +classes
  • +
  • CUPS_ADD_CLASS - Add or modify a +class
  • +
  • CUPS_DELETE_CLASS - Delete a class
  • +
  • CUPS_ACCEPT_JOBS - Accept jobs on a +printer or class
  • +
  • CUPS_REJECT_JOBS - Reject jobs on a +printer or class
  • +
  • CUPS_SET_DEFAULT - Set the default +destination
  • +
  • CUPS_GET_DEVICES - Get a list of all +devices
  • +
  • CUPS_GET_PPDS - Get a list of all +PPDs
  • +
  • CUPS_MOVE_JOB - Move a job to a +new destination
  • +
+

Status Codes

+

Status codes are returned by all IPP requests. +

+
    +
  • IPP_OK - Request completed with no +errors
  • +
  • IPP_OK_SUBST - Request completed but +some attribute values were substituted
  • +
  • IPP_OK_CONFLICT - Request completed but +some attributes conflicted
  • +
  • IPP_BAD_REQUEST - The request was bad +
  • +
  • IPP_FORBIDDEN - You don't have access +to the resource
  • +
  • IPP_NOT_AUTHENTICATED - You are not +authenticated for the resource
  • +
  • IPP_NOT_AUTHORIZED - You not authorized +to access the resource
  • +
  • IPP_NOT_POSSIBLE - The requested operation +cannot be completed
  • +
  • IPP_TIMEOUT - A timeout occurred
  • +
  • IPP_NOT_FOUND - The resource was not +found
  • +
  • IPP_GONE - The resource has gone +away
  • +
  • IPP_REQUEST_ENTITY - The request was +too large
  • +
  • IPP_REQUEST_VALUE - The request contained +a value that was unknown to the server
  • +
  • IPP_DOCUMENT_FORMAT - The document format +is not supported by the server
  • +
  • IPP_ATTRIBUTES - Required attributes are +missing
  • +
  • IPP_URI_SCHEME - The URI scheme is +not supported
  • +
  • IPP_CHARSET - The charset is not +supported
  • +
  • IPP_CONFLICT - One or more attributes +conflict
  • +
  • IPP_COMPRESSION_NOT_SUPPORTED - The specified + compression is not supported
  • +
  • IPP_COMPRESSION_ERROR - The compressed +data contained an error
  • +
  • IPP_DOCUMENT_FORMAT_ERROR - The document +data contained an error in it
  • +
  • IPP_DOCUMENT_ACCESS_ERROR - The remote +document could not be accessed
  • +
  • IPP_INTERNAL_ERROR - The server +encountered an internal error
  • +
  • IPP_OPERATION_NOT_SUPPORTED - The requested +operation is not supported
  • +
  • IPP_SERVICE_UNAVAILABLE - The requested +service is unavailable
  • +
  • IPP_VERSION_NOT_SUPPORTED - The IPP +request version is not supported
  • +
  • IPP_DEVICE_ERROR - The output device +encountered an error
  • +
  • IPP_TEMPORARY_ERROR - A temporary error +occurred
  • +
  • IPP_NOT_ACCEPTING - The destination is +not accepting jobs
  • +
  • IPP_PRINTER_BUSY - The destination is +busy
  • +
  • IPP_ERROR_JOB_CANCELLED - The requested +job has been cancelled
  • +
  • IPP_MULTIPLE_JOBS_NOT_SUPPORTED - The server + does not support multiple jobs
  • +
+

PPD Constants

+

PPD Format Version

+

The PPD_VERSION constant defines a +floating point number representing the newest format +version that is supported by CUPS, currently 4.3. +

+

PPD User-Interface Types

+

Each printer option has a type associated with +it:

+
    +
  • PPD_UI_BOOLEAN - The user can turn +this option on or off
  • +
  • PPD_UI_PICKONE - The user can choose +one option value to use.
  • +
  • PPD_UI_PICKMANY - The user can choose +zero or more option values.
  • +
+

PPD Sections

+

Some options must be output before others, or +in different sections of the output document. The +ppd_section_t enumeration defines which section +the option must be output in:

+
    +
  • PPD_ORDER_ANY - The option can be +output in any of the document, page, or prolog +sections of the document
  • +
  • PPD_ORDER_DOCUMENT - The option must be +output in the DocumentSetup section of the +document
  • +
  • PPD_ORDER_EXIT - The option must be +output before the document
  • +
  • PPD_ORDER_JCL - The option must be +output in the job control section of the +document
  • +
  • PPD_ORDER_PAGE - The option must be +output in the PageSetup section of the document +
  • +
  • PPD_ORDER_PROLOG - The option must be +output in the Prolog section of the document
  • +
+

PPD Colorspaces

+

Each printer has a default colorspace:

+
    +
  • PPD_CS_CMYK - The printer uses CMYK +colors by default
  • +
  • PPD_CS_CMY - The printer uses CMY +colors by default
  • +
  • PPD_CS_GRAY - The printer uses +grayscale by default
  • +
  • PPD_CS_RGB - The printer uses RGB +colors by default
  • +
  • PPD_CS_RGBK - The printer uses RGBK +colors by default
  • +
  • PPD_CS_N - The printer uses a +DeviceN colorspace by default
  • +
+

Raster Constants

+

Raster Sync Words

+

The CUPS_RASTER_SYNC and +CUPS_RASTER_REVSYNC constants define the standard +sync words at the beginning of each CUPS raster +file.

+

Raster Stream Modes

+

The CUPS_RASTER_READ and +CUPS_RASTER_WRITE constants are used with the cupsRasterOpen() function +to specify a stream for reading or writing.

+

Raster Boolean Constants

+

The CUPS_FALSE and CUPS_TRUE + constants represent boolean values in the page +header.

+

Raster Jog Values

+

The cups_jog_t enumeration defines +constants for the Jog page device dictionary +variable:

+
    +
  • CUPS_JOG_NONE - Do no jogging
  • +
  • CUPS_JOG_FILE - Jog pages after each +file
  • +
  • CUPS_JOG_JOB - Jog pages after each +job
  • +
  • CUPS_JOG_SET - Jog pages after each +set of jobs
  • +
+

Raster Orientation Values

+

The cups_orient_t enumeration defines +constants for the Orientation page device dictionary +variable:

+
    +
  • CUPS_ORIENT_0 - Portrait orientation
  • +
  • CUPS_ORIENT_90 - Landscape orientation
  • +
  • CUPS_ORIENT_180 - Reverse-portrait +orientation
  • +
  • CUPS_ORIENT_270 - Reverse-landscape +orientation
  • +
+

Raster CutMedia Values

+

The cups_cut_t enumeration defines +constants for the CutMedia page device dictionary +variable:

+
    +
  • CUPS_CUT_NONE - Do no jogging
  • +
  • CUPS_CUT_FILE - Cut pages after each +file
  • +
  • CUPS_CUT_JOB - Cut pages after each +job
  • +
  • CUPS_CUT_SET - Cut pages after each +set of jobs
  • +
  • CUPS_CUT_PAGE - Cut each page
  • +
+

Raster AdvanceMedia Values

+

The cups_advance_t enumeration defines +constants for the AdvanceMedia page device dictionary +variable:

+
    +
  • CUPS_ADVANCE_NONE - Do no jogging
  • +
  • CUPS_ADVANCE_FILE - Advance media after +each file
  • +
  • CUPS_ADVANCE_JOB - Advance media after +each job
  • +
  • CUPS_ADVANCE_SET - Advance media after +each set of jobs
  • +
  • CUPS_ADVANCE_PAGE - Advance media for +each page
  • +
+

Raster LeadingEdge Values

+

The cups_edge_t enumeration defines +constants for the LeadingEdge page device dictionary +variable:

+
    +
  • CUPS_EDGE_TOP - The top of the media +is the leading edge
  • +
  • CUPS_EDGE_RIGHT - The right of the +media is the leading edge
  • +
  • CUPS_EDGE_BOTTOM - The bottom of the +media is the leading edge
  • +
  • CUPS_EDGE_LEFT - The left of the +media is the leading edge
  • +
+

Raster Color Order Values

+

The cups_order_t enumeration defines the +possible color value orderings:

+
    +
  • CUPS_ORDER_CHUNKED - CMYK CMYK CMYK
  • +
  • CUPS_ORDER_BANDED - CCC MMM YYY KKK
  • +
  • CUPS_ORDER_PLANAR - +CCC ... MMM ... YYY ... KKK ...
  • +
+

Raster Colorspace Values

+

The cups_cspace_t enumeration defines the +possible colorspaces:

+
    +
  • CUPS_CSPACE_W - White (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 - Metallic yellow (gold), +metallic magenta, metallic cyan, black
  • +
  • CUPS_CSPACE_GMCS - Metallic yellow (gold), +metallic magenta, metallic cyan, metallic grey +(silver)
  • +
  • CUPS_CSPACE_WHITE - White pigment (black +as white pigment)
  • +
  • CUPS_CSPACE_GOLD - Gold foil (black as +gold foil)
  • +
  • CUPS_CSPACE_SILVER - Silver foil (black +as silver foil)
  • +
+

C - Structures

+

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

+

Raster Structures

+

Raster Page Header

+

The raster page header consists of the +PostScript page device dictionary for the page: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MemberTypeDescription
MediaClasschar[64]The media class +name
MediaColorchar[64]The media color +name
MediaTypechar[64]The media type +name
OutputTypechar[64]The output type +name
AdvanceDistanceunsignedThe distance +to advance the media in points
AdvanceMediacups_adv_tWhen to +advance the media
Collatecups_bool_tWhether or not +to produce collated copies
CutMediacups_cut_tWhen to cut +the media
Duplexcups_bool_tWhether or not +to print on both sides of the paper
HWResolutionunsigned[2]The +resolution of the page image in pixels per +inch; the HWResolution[0] represents the horizontal +resolution and HWResolution[1] represents the vertical +resolution
ImagingBoundingBoxunsigned[4]The +bounding box for the page in points; the +elements represent the left, bottom, right, and +top coordinates of the imaged area (if 0 then +the whole page is imaged)
InsertSheetcups_bool_tWhether or +not to insert a sheet before this page
Jogcups_jog_tWhen to jog +copies of the page
LeadingEdgecups_edge_tThe leading +edge of the page
Marginsunsigned[2]The lower-lefthand +margin of the page in points
ManualFeedcups_bool_tWhether or +not to manually feed the page
MediaPositionunsignedThe input +slot number to use
MediaWeightunsignedThe weight of +the output media in grams/m2
MirrorPrintcups_bool_tWhether or +not to mirror the print
NegativePrintcups_bool_tWhether or +not to invert the print
NumCopiesunsignedThe number of +copies to produce
Orientationcups_orient_tThe +orientation of the page image
OutputFaceUpcups_bool_tWhether or +not to output the page face up
PageSizeunsigned[2]The width and +height of the page in points
Separationscups_bool_tWhether or +not to output separations
TraySwitchcups_bool_tWhether or +not to automatically switch trays for the +requested media size/type
Tumblecups_bool_tWhether or not +to rotate the back side of the page
cupsWidthunsignedThe width of +the page image in pixels
cupsHeightunsignedThe height of +the page image in pixels
cupsMediaTypeunsignedThe +device-specific media type code
cupsBitsPerColorunsignedThe number +of bits per color
cupsBitsPerPixelunsignedThe number +of bits per pixel
cupsBytesPerLineunsignedThe number +of bytes per line of image data
cupsColorOrdercups_order_tThe order +of color values
cupsColorSpacecups_cspace_tThe type +of color values
cupsCompressionunsignedThe +device-specific compression code
cupsRowCountunsignedThe +device-specific row count
cupsRowFeedunsignedThe +device-specific row feed
cupsRowStepunsignedThe +device-specific row step
+
+

+

D - 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(), +cupsSetPasswordCB(), cupsSetServer() +, cupsSetUser(), +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;
+int           jobid;
+
+...
+
+jobid = cupsPrintFile("printer@hostname", "filename.ps", "Job Title",
+                      num_options, options);
+
+

See Also

+

cupsCancelJob(), +cupsLastError(), cupsPrintFiles() + + +

+

cupsPrintFiles()

+

Usage

+
+int
+cupsPrintFiles(const char    *printer,
+               int           num_files,
+               const char    **files,
+               const char    *title,
+	       int           num_options,
+	       cups_option_t *options);
+
+

Arguments

+
+ + + + + + + + +
ArgumentDescription
printerThe printer or class to print +to.
num_filesThe number of files to +print.
filesThe files 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

+

cupsPrintFiles() sends multiple files 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_files;
+const char    *files[100];
+int           num_options;
+cups_option_t *options;
+int           jobid;
+
+...
+
+jobid = cupsPrintFiles("printer@hostname", num_files, files,
+                       "Job Title", num_options, options);
+
+

See Also

+

cupsCancelJob(), +cupsLastError(), cupsPrintFile() + + +

+

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 + client.conf file,
  4. +
  5. The default host, "localhost".
  6. +
+

Example

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

See Also

+

cupsGetPassword(), +cupsSetPasswordCB(), cupsSetServer() +, cupsSetUser(), +cupsUser() + +

+

cupsSetPasswordCB()

+

Usage

+
+void
+cupsSetPasswordCB(const char *(*cb)(const char *prompt));
+
+

Arguments

+
+ + + +
ArgumentDescription
cbThe password callback function.
+
+

Description

+

cupsSetPasswordCB() sets the callback +function to use when asking the user for a +password. The callback function must accept a +single character string pointer (the prompt string) +and return NULL if the user did not +enter a password string or a pointer to the +password string otherwise.

+

Example

+
+#include <cups/cups.h>
+
+const char *
+my_password_cb(const char *prompt)
+{
+  return (getpass(prompt));
+}
+
+...
+
+char *password;
+
+...
+
+cupsSetPasswordCB(my_password_cb);
+password = cupsGetPassword("Please enter a password:");
+
+

See Also

+

cupsServer(), +cupsSetServer(), cupsSetUser(), cupsUser() + +

+

cupsSetServer()

+

Usage

+
+void
+cupsSetServer(const char *server);
+
+

Arguments

+
+ + + +
ArgumentDescription
serverThe default server to use.
+
+

Description

+

cupsSetServer() sets the default server +to use for the CUPS API. If the server + argument is NULL, the default server +is used.

+

Example

+
+#include <cups/cups.h>
+
+cupsSetServer("foo.bar.com");
+
+

See Also

+

cupsServer(), +cupsSetPasswordCB(), cupsSetUser() +, cupsUser() + +

+

cupsSetUser()

+

Usage

+
+void
+cupsSetUser(const char *user);
+
+

Arguments

+
+ + + + +
ArgumentDescription
userThe user name string to use.
+
+

Description

+

cupsSetUser() sets the default user name +for authentication. If the user argument +is NULL then the current login user +is used.

+

Example

+
+#include <cups/cups.h>
+
+...
+
+cupsSetUser("root");
+
+

See Also

+

cupsServer(), +cupsSetPasswordCB(), cupsSetServer() +, 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

+
+void httpBlocking(http_t *http, int blocking)
+
+

Arguments

+
+ + + + + +
ArgumentDescription
httpThe HTTP connection
blocking0 if the connection should +be non-blocking, 1 if it should be blocking
+
+

Description

+

The httpBlocking() function sets the +blocking mode for the HTTP connection. By default +HTTP connections will block (stop) the client +program until data is available or can be sent +to the server.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+
+http = httpConnect("server", port);
+httpBlocking(http, 0);
+
+

See Also

+ httpCheck(), +httpConnect() + + +

httpCheck()

+

Usage

+
+int httpCheck(http_t *http);
+
+

Arguments

+
+ + + +
ArgumentDescription
httpThe HTTP connection
+
+

Returns

+

0 if there is no data pending, 1 otherwise. +

+

Description

+

The httpCheck() function checks to see +if there is any data pending on an HTTP +connection.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+
+if (httpCheck(http))
+{
+  ... do something ...
+}
+
+

See Also

+ httpBlocking(), +httpConnect(), +httpGets(), httpRead() + + + +

httpClearFields()

+

Usage

+
+void httpClearFields(http_t *http)
+
+

Arguments

+
+ + + +
ArgumentDescription
httpThe HTTP connection
+
+

Description

+

The httpClearFields() function clears all +HTTP request fields for the HTTP connection.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+
+httpClearFields(http);
+
+

See Also

+ httpConnect(), +httpGetField(), +httpSetField() + + +

httpClose()

+

Usage

+
+void httpClose(http_t *http);
+
+

Arguments

+
+ + + +
ArgumentDescription
httpThe HTTP connection
+
+

Description

+

The httpClose() function closes an +active HTTP connection.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+
+httpClose(http);
+
+

See Also

+ httpConnect() + + +

httpConnect()

+

Usage

+
+http_t *httpConnect(const char *hostname, int port);
+
+

Arguments

+
+ + + + +
ArgumentDescription
hostnameThe name or IP address of +the server to connect to
portThe port number to use
+
+

Returns

+

A pointer to a HTTP connection structure or +NULL if the connection could not be made.

+

Description

+

The httpConnect() function opens a HTTP +connection to the specified server and port.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+
+http = httpConnect(cupsServer(), ippPort());
+
+

See Also

+ httpClose(), +httpGet(), httpGets() +, httpPost(), httpRead(), +httpWrite() + + +

httpDecode64()

+

Usage

+
+char *httpDecode64(char *out, const char *in);
+
+

Arguments

+
+ + + + +
ArgumentDescription
outThe output string
inThe input string
+
+

Returns

+

A pointer to the decoded string.

+

Description

+

The httpDecode64() function decodes a +base-64 encoded string to the original string.

+

Example

+
+#include <cups/http.h>
+
+char encoded_string[255];
+char original_string[255];
+
+httpDecode64(original_string, encoded_string);
+
+

See Also

+ httpEncode64() + + +

httpDelete()

+

Usage

+
+int httpDelete(http_t *http, const char *uri);
+
+

Arguments

+
+ + + + +
ArgumentDescription
httpThe HTTP connection
uriThe URI to delete
+
+

Returns

+

0 on success, non-zero on failure.

+

Description

+

The httpDelete() function sends a HTTP +DELETE request to the server.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+
+httpDelete(http, "/some/uri");
+
+

See Also

+ httpConnect(), +httpSetField(), +httpUpdate() + + +

httpEncode64()

+

Usage

+
+char *httpEncode64(char *out, const char *in);
+
+

Arguments

+
+ + + + +
ArgumentDescription
outThe output string
inThe input string
+
+

Returns

+

A pointer to the encoded string.

+

Description

+

The httpEncode64() function decodes a +base-64 encoded string to the original string.

+

Example

+
+#include <cups/http.h>
+
+char encoded_string[255];
+char original_string[255];
+
+httpEncode64(encoded_string, original_string);
+
+

See Also

+ httpDecode64() + + +

httpError()

+

Usage

+
+int httpError(http_t *http);
+
+

Arguments

+
+ + + +
ArgumentDescription
httpThe HTTP connection
+
+

Returns

+

The last error that occurred or 0 if no +error has occurred.

+

Description

+

The httpError() function returns the +last error that occurred on the HTTP connection. +

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+
+if (httpError(http))
+{
+  ... show an error message ...
+}
+
+

See Also

+ httpConnect() + + +

httpFlush()

+

Usage

+
+void httpFlush(http_t *http);
+
+

Arguments

+
+ + + +
ArgumentDescription
httpThe HTTP connection
+
+

Description

+

The httpFlush() function flushes any +remaining data left from a GET or POST +operation.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+
+httpFlush(http);
+
+

See Also

+ httpConnect(), + + +

httpGet()

+

Usage

+
+int httpGet(http_t *http, const char *uri);
+
+

Arguments

+
+ + + + +
ArgumentDescription
httpThe HTTP connection
uriThe URI to get
+
+

Returns

+

0 on success, non-zero on failure.

+

Description

+

The httpGet() function sends a HTTP +GET request to the server.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+
+httpGet(http, "/some/uri");
+
+

See Also

+ httpConnect(), +httpSetField(), +httpUpdate() + + +

httpGets()

+

Usage

+
+char *httpGets(char *line, int length, http_t *http)
+
+

Arguments

+
+ + + + + +
ArgumentDescription
lineThe string to fill with a +line from the HTTP connection
lengthThe maximum length of the +string
httpThe HTTP connection
+
+

Returns

+

A pointer to the string or NULL if no +line could be retrieved.

+

Description

+

The httpGets() function is used to +read a request line from the HTTP connection. +It is not normally used by a client program.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+char line[1024];
+
+if (httpGets(line, sizeof(line), http))
+{
+  ... process the line ...
+}
+
+

See Also

+ httpConnect(), +httpUpdate() + + +

httpGetDateString()

+

Usage

+
+const char *httpGetDateString(time_t time)
+
+

Arguments

+
+ + + +
ArgumentDescription
timeThe UNIX date/time value
+
+

Returns

+

A pointer to a static string containing the +HTTP date/time string for the specified UNIX time +value.

+

Description

+

The httpGetDateString() function generates +a date/time string suitable for HTTP requests from +a UNIX time value.

+

Example

+
+#include <cups/http.h>
+
+puts(httpGetDateString(time(NULL)));
+
+

See Also

+ httpGetDateTime() + + +

httpGetDateTime()

+

Usage

+
+time_t httpGetDateTime(const char *date)
+
+

Arguments

+
+ + + +
ArgumentDescription
dateThe HTTP date/time string
+
+

Returns

+

A UNIX time value.

+

Description

+

The httpGetDateTime() function converts a +HTTP date/time string to a UNIX time value.

+

Example

+
+#include <cups/http.h>
+
+printf("%d\n", httpGetDateTime("Fri, 30 June 2000 12:34:56 GMT"));
+
+

See Also

+ httpGetDateString() + + +

httpGetField()

+

Usage

+
+const char *httpGetField(http_t *http, http_field_t field);
+
+

Arguments

+
+ + + + +
ArgumentDescription
httpThe HTTP connection
fieldThe HTTP field
+
+

Returns

+

A pointer to the field value string.

+

Description

+

The httpGetField() function returns the +current value for the specified HTTP field.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+
+httpGet(http, "/some/uri");
+while (httpUpdate(http) == HTTP_CONTINUE);
+
+puts(httpGetField(http, HTTP_FIELD_CONTENT_TYPE));
+
+

See Also

+ httpConnect(), +httpSetField() + + +

httpHead()

+

Usage

+
+int httpHead(http_t *http, const char *uri);
+
+

Arguments

+
+ + + + +
ArgumentDescription
httpThe HTTP connection
uriThe URI to head
+
+

Returns

+

0 on success, non-zero on failure.

+

Description

+

The httpHead() function sends a HTTP +HEAD request to the server.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+
+httpHead(http, "/some/uri");
+
+

See Also

+ httpConnect(), +httpSetField(), +httpUpdate() + + +

httpInitialize()

+

Usage

+
+void httpInitialize(void);
+
+

Description

+

The httpInitialize() function initializes +the networking code as needed by the underlying +platform. It is called automatically by the +httpConnect() function.

+

Example

+
+#include <cups/http.h>
+
+httpInitialize();
+
+

See Also

+ httpConnect() + + +

httpOptions()

+

Usage

+
+int httpOptions(http_t *http, const char *uri);
+
+

Arguments

+
+ + + + + +
ArgumentDescription
httpThe HTTP connection
uriThe URI to check for options
+
+

Returns

+

0 on success, non-zero on failure.

+

Description

+

The httpOptions() function sends a HTTP +OPTIONS request to the server.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+
+httpOptions(http, "/some/uri");
+
+

See Also

+ httpConnect(), +httpSetField(), +httpUpdate() + + +

httpPost()

+

Usage

+
+int httpPost(http_t *http, const char *uri);
+
+

Arguments

+
+ + + + +
ArgumentDescription
httpThe HTTP connection
uriThe URI to post to
+
+

Returns

+

0 on success, non-zero on failure.

+

Description

+

The httpPost() function sends a HTTP +POST request to the server.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+
+httpPost(http, "/some/uri");
+
+

See Also

+ httpConnect(), +httpSetField(), +httpUpdate() + + +

httpPrintf()

+

Usage

+
+int httpPrintf(http_t *http, const char *format, ...);
+
+

Arguments

+
+ + + + +
ArgumentDescription
httpThe HTTP connection
formatA printf-style format string
+
+

Returns

+

The number of bytes written.

+

Description

+

The httpPrintf() function sends a +formatted string to the HTTP connection. It is +normally only used by the CUPS API and +scheduler.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+
+httpPrintf(http, "GET / HTTP/1.1 \r\n");
+
+

See Also

+ httpConnect() + + +

httpPut()

+

Usage

+
+int httpPut(http_t *http, const char *uri);
+
+

Arguments

+
+ + + + +
ArgumentDescription
httpThe HTTP connection
uriThe URI to put
+
+

Returns

+

0 on success, non-zero on failure.

+

Description

+

The httpPut() function sends a HTTP +PUT request to the server.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+
+httpDelete(http, "/some/uri");
+
+

See Also

+ httpConnect(), +httpSetField(), +httpUpdate() + + +

httpRead()

+

Usage

+
+int httpRead(http_t *http, char *buffer, int length);
+
+

Arguments

+
+ + + + + + +
ArgumentDescription
httpThe HTTP connection
bufferThe buffer to read into
lengthThe number of bytes to read
+
+

Returns

+

The number of bytes read or -1 on error.

+

Description

+

The httpRead() function reads data from +the HTTP connection, possibly the result of a +GET or POST request.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+char buffer[1024];
+int  bytes;
+
+httpGet(http, "/");
+while (httpUpdate(http) != HTTP_CONTINUE);
+while ((bytes = httpRead(http, buffer, sizeof(buffer) - 1)) > 0)
+{
+  buffer[bytes] = '\0';
+  fputs(buffer, stdout);
+}
+
+

See Also

+ httpConnect(), +httpWrite() + + +

httpReconnect()

+

Usage

+
+int httpReconnect(http_t *http);
+
+

Arguments

+
+ + + +
ArgumentDescription
httpThe HTTP connection
+
+

Returns

+

0 on success, non-zero on failure.

+

Description

+

The httpReconnect() function reconnects to +the HTTP server. This is usually done +automatically if the HTTP functions detect that +the server connection has terminated.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+
+httpReconnect(http);
+
+

See Also

+ httpConnect() + + +

httpSeparate()

+

Usage

+
+void httpSeparate(const char *uri, char *method,
+                  char *username, char *host, int *port,
+                  char *resource);
+
+

Arguments

+
+ + + + + + + + +
ArgumentDescription
uriThe URI to separate
methodThe method (scheme) of the URI +
usernameThe username (and password) +portion of the URI, if any
hostThe hostname portion of the URI, +if any
portThe port number for the URI, +either as specified or as default for the +method/scheme
resourceThe resource string, usually a +filename on the server
+
+

Description

+

The httpSeparate() function separates the +specified URI into its component parts. The +method, username, hostname, and resource strings +should be at least HTTP_MAX_URI characters +long to avoid potential buffer overflow problems.

+

Example

+
+char uri[HTTP_MAX_URI];
+char method[HTTP_MAX_URI];
+char username[HTTP_MAX_URI];
+char host[HTTP_MAX_URI];
+char resource[HTTP_MAX_URI];
+int port;
+
+httpSeparate(uri, method, username, host, &port, resource);
+
+

See Also

+ httpConnect() + + +

httpSetField()

+

Usage

+
+void httpSetField(http_t *http, http_field_t field, const char *value);
+
+

Arguments

+
+ + + + + +
ArgumentDescription
httpThe HTTP connection
fieldThe HTTP field
valueThe string value for the field +
+
+

Description

+

The httpSetField() function sets the +current value for the specified HTTP field.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+
+httpSetField(http, HTTP_FIELD_AUTHORIZATION, "Basic dfdr34453454325"));
+httpGet(http, "/some/uri");
+while (httpUpdate(http) == HTTP_CONTINUE);
+
+

See Also

+ httpConnect(), +httpGetField() + + +

httpTrace()

+

Usage

+
+int httpTrace(http_t *http, const char *uri);
+
+

Arguments

+
+ + + + +
ArgumentDescription
httpThe HTTP connection
uriThe URI to trace
+
+

Returns

+

0 on success, non-zero on failure.

+

Description

+

The httpTrace() function sends a HTTP +TRACE request to the server.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+
+httpTrace(http, "/some/uri");
+
+

See Also

+ httpConnect(), +httpSetField(), +httpUpdate() + + +

httpUpdate()

+

Usage

+
+http_status_t httpUpdate(http_t *http);
+
+

Arguments

+
+ + + +
ArgumentDescription
httpThe HTTP connection
+
+

Returns

+

The HTTP status of the current request.

+

Description

+

The httpUpdate() function updates the +current request status. It is used after any +DELETE, GET, HEAD, OPTIONS, POST, PUT, or TRACE +request to finalize the HTTP request and retrieve +the request status.

+

Since proxies and the current blocking mode can +cause the request to take longer, programs should +continue calling httpUpdate() until the +return status is not the constant value +HTTP_CONTINUE.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+http_status_t status;
+
+httpGet(http, "/some/uri");
+while ((status = httpUpdate(http)) == HTTP_CONTINUE);
+printf("Request status is %d\n", status);
+
+

See Also

+ httpConnect(), +httpDelete(), httpGet() +, httpHead(), httpOptions(), +httpPost(), httpPut() +, httpTrace() + + +

httpWrite()

+

Usage

+
+int httpWrite(http_t *http, char *buffer, int length);
+
+

Arguments

+
+ + + + + + +
ArgumentDescription
httpThe HTTP connection
bufferThe buffer to read into
lengthThe number of bytes to read
+
+

Returns

+

The number of bytes read or -1 on error.

+

Description

+

The httpWrite() function reads data from +the HTTP connection, possibly the result of a +GET or POST request.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+FILE *fp;
+char buffer[1024];
+int  bytes;
+
+httpPost(http, "/");
+
+while ((bytes = fread(buffer, 1, sizeof(buffer), fp)) > 0)
+  httpWrite(http, buffer, bytes);
+
+while (httpUpdate(http) != HTTP_CONTINUE);
+
+while ((bytes = httpRead(http, buffer, sizeof(buffer) - 1)) > 0)
+{
+  buffer[bytes] = '\0';
+  fputs(buffer, stdout);
+}
+
+

See Also

+ httpConnect(), +httpRead() + + +

ippAddBoolean()

+

Usage

+
+ipp_attribute_t *ippAddBoolean(ipp_t *ipp, ipp_tag_t group,
+                               const char *name, char value);
+
+

Arguments

+
+ + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
nameThe name of attribute
valueThe boolean value
+
+

Returns

+

A pointer to the new attribute or NULL if +the attribute could not be created.

+

Description

+

The ippAddBoolean() function adds a +single boolean attribute value to the specified +IPP request.

+

Example

+
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+
+ippAddBoolean(ipp, IPP_TAG_OPERATION, "my-jobs", 1);
+
+

See Also

+ ippAddBooleans(), +ippAddDate(), +ippAddInteger(), +ippAddIntegers(), +ippAddRange(), +ippAddRanges(), +ippAddResolution(), +ippAddResolutions(), +ippAddSeparator(), +ippAddString(), +ippAddStrings() + + +

ippAddBooleans()

+

Usage

+
+ipp_attribute_t *ippAddBooleans(ipp_t *ipp, ipp_tag_t group,
+                                const char *name, int num_values,
+                                const char *values);
+
+

Arguments

+
+ + + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
nameThe name of attribute
num_valuesThe number of values
valuesThe boolean values
+
+

Returns

+

A pointer to the new attribute or NULL if +the attribute could not be created.

+

Description

+

The ippAddBooleans() function adds one +or more boolean attribute values to the specified +IPP request. If the values pointer is +NULL then an array of num_values + false values is created.

+

Example

+
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+char values[10];
+
+ippAddBooleans(ipp, IPP_TAG_OPERATION, "some-attribute", 10, values);
+
+

See Also

+ ippAddBoolean(), +ippAddDate(), +ippAddInteger(), +ippAddIntegers(), +ippAddRange(), +ippAddRanges(), +ippAddResolution(), +ippAddResolutions(), +ippAddSeparator(), +ippAddString(), +ippAddStrings() + + +

ippAddDate()

+

Usage

+
+ipp_attribute_t *ippAddDate(ipp_t *ipp, ipp_tag_t group,
+                            const char *name, ipp_uchar_t *value);
+
+

Arguments

+
+ + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
nameThe name of attribute
valueThe date value
+
+

Returns

+

A pointer to the new attribute or NULL if +the attribute could not be created.

+

Description

+

The ippAddDate() function adds a single +date-time attribute value to the specified IPP +request.

+

Example

+
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+
+ippAddDate(ipp, IPP_TAG_OPERATION, "some-attribute", 
+           ippTimeToDate(time(NULL));
+
+

See Also

+ ippAddBoolean(), +ippAddBooleans(), +ippAddInteger(), +ippAddIntegers(), +ippAddRange(), +ippAddRanges(), +ippAddResolution(), +ippAddResolutions(), +ippAddSeparator(), +ippAddString(), +ippAddStrings(), +ippTimeToDate() + + +

ippAddInteger()

+

Usage

+
+ipp_attribute_t *ippAddInteger(ipp_t *ipp, ipp_tag_t group,
+                               ipp_tag_t tag, const char *name,
+                               int value);
+
+

Arguments

+
+ + + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
tagThe type of integer value +(IPP_TAG_INTEGER or IPP_TAG_ENUM)
nameThe name of attribute
valueThe integer value
+
+

Returns

+

A pointer to the new attribute or NULL if +the attribute could not be created.

+

Description

+

The ippAddInteger() function adds a +single integer attribute value to the specified +IPP request.

+

Example

+
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+
+ippAddInteger(ipp, IPP_TAG_OPERATION, "limit", 100);
+
+

See Also

+ ippAddBoolean(), +ippAddBooleans(), +ippAddDate(), +ippAddIntegers(), +ippAddRange(), +ippAddRanges(), +ippAddResolution(), +ippAddResolutions(), +ippAddSeparator(), +ippAddString(), +ippAddStrings() + + +

ippAddIntegers()

+

Usage

+
+ipp_attribute_t *ippAddIntegers(ipp_t *ipp, ipp_tag_t group,
+                                ipp_tag_t tag, const char *name,
+                                int num_values, const int *values);
+
+

Arguments

+
+ + + + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
tagThe type of integer value +(IPP_TAG_INTEGER or IPP_TAG_ENUM)
nameThe name of attribute
num_valuesThe number of values
valuesThe integer values
+
+

Returns

+

A pointer to the new attribute or NULL if +the attribute could not be created.

+

Description

+

The ippAddIntegers() function adds one +or more integer attribute values to the specified +IPP request. If the values pointer is +NULL then an array of num_values + 0 values is created.

+

Example

+
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+int values[100];
+
+ippAddIntegers(ipp, IPP_TAG_OPERATION, "some-attribute", 100, values);
+
+

See Also

+ ippAddBoolean(), +ippAddBooleans(), +ippAddDate(), +ippAddInteger(), +ippAddRange(), +ippAddRanges(), +ippAddResolution(), +ippAddResolutions(), +ippAddSeparator(), +ippAddString(), +ippAddStrings() + + +

ippAddRange()

+

Usage

+
+ipp_attribute_t *ippAddRange(ipp_t *ipp, ipp_tag_t group,
+                             const char *name, int low,
+                             int high);
+
+

Arguments

+
+ + + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
nameThe name of attribute
lowThe lower value
highThe higher value
+
+

Returns

+

A pointer to the new attribute or NULL if +the attribute could not be created.

+

Description

+

The ippAddRange() function adds a single +range attribute value to the specified IPP +request.

+

Example

+
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+
+ippAddRange(ipp, IPP_TAG_OPERATION, "page-ranges", 1, 10);
+
+

See Also

+ ippAddBoolean(), +ippAddBooleans(), +ippAddDate(), +ippAddInteger(), +ippAddIntegers(), +ippAddRanges(), +ippAddResolution(), +ippAddResolutions(), +ippAddSeparator(), +ippAddString(), +ippAddStrings() + + +

ippAddRanges()

+

Usage

+
+ipp_attribute_t *ippAddRanges(ipp_t *ipp, ipp_tag_t group,
+                              const char *name, int num_values,
+                              const int *lows, const int *highs);
+
+

Arguments

+
+ + + + + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
nameThe name of attribute
num_valuesThe number of range values
lowsThe lower values
highsThe higher values
+
+

Returns

+

A pointer to the new attribute or NULL if +the attribute could not be created.

+

Description

+

The ippAddRanges() function adds one or +more range attribute values to the specified IPP +request. If the values pointer is +NULL then an array of num_values + 0,0 ranges is created.

+

Example

+
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+int lows[2];
+int highs[2];
+
+ippAddRanges(ipp, IPP_TAG_OPERATION, "page-ranges", 2, lows, highs);
+
+

See Also

+ ippAddBoolean(), +ippAddBooleans(), +ippAddDate(), +ippAddInteger(), +ippAddIntegers(), +ippAddRange(), +ippAddResolution(), +ippAddResolutions(), +ippAddSeparator(), +ippAddString(), +ippAddStrings() + + +

ippAddResolution()

+

Usage

+
+ipp_attribute_t *ippAddResolution(ipp_t *ipp, ipp_tag_t group,
+                                  const char *name, int xres,
+                                  int yres, ipp_res_t units);
+
+

Arguments

+
+ + + + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
nameThe name of attribute
xresThe horizontal resolution
yresThe vertical resolution
unitsThe resolution units
+
+

Returns

+

A pointer to the new attribute or NULL if +the attribute could not be created.

+

Description

+

The ippAddResolution() function adds a +single resolution attribute value to the specified +IPP request.

+

Example

+
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+
+ippAddBoolean(ipp, IPP_TAG_OPERATION, "printer-resolution",
+              720, 720, IPP_RES_PER_INCH);
+
+

See Also

+ ippAddBoolean(), +ippAddBooleans(), +ippAddDate(), +ippAddInteger(), +ippAddIntegers(), +ippAddRange(), +ippAddRanges(), +ippAddResolutions(), +ippAddSeparator(), +ippAddString(), +ippAddStrings() + + +

ippAddResolutions()

+

Usage

+
+ipp_attribute_t *ippAddResolutions(ipp_t *ipp, ipp_tag_t group,
+                                   const char *name, int num_values,
+                                   const int *xres, const int *yres,
+                                   const ipp_res_t *units);
+
+

Arguments

+
+ + + + + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
nameThe name of attribute
num_valuesThe number of resolution +values
xresThe horizontal resolutions
yresThe vertical resolutions
unitsThe resolution units
+
+

Returns

+

A pointer to the new attribute or NULL if +the attribute could not be created.

+

Description

+

The ippAddResolutions() function adds one +or more resolution attribute values to the +specified IPP request. If the values + pointer is NULL then an array of +num_values 0,0 resolutions is created.

+

Example

+
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+int xres[5];
+int yres[5];
+ipp_res_t units[5];
+
+ippAddBoolean(ipp, IPP_TAG_OPERATION, "printer-resolutions-supported",
+              5, xres, yres, units);
+
+

See Also

+ ippAddBoolean(), +ippAddBooleans(), +ippAddDate(), +ippAddInteger(), +ippAddIntegers(), +ippAddRange(), +ippAddRanges(), +ippAddResolution(), +ippAddSeparator(), +ippAddString(), +ippAddStrings() + + +

ippAddSeparator()

+

Usage

+
+ipp_attribute_t *ippAddSeparator(ipp_t *ipp);
+
+

Arguments

+
+ + + +
ArgumentDescription
ippThe IPP request
+
+

Returns

+

A pointer to the new separator or NULL if +the separator could not be created.

+

Description

+

The ippAddSeparator() function adds a +group separator to the specified IPP request.

+

Example

+
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+
+ippAddSeparator(ipp);
+
+

See Also

+ ippAddBoolean(), +ippAddBooleans(), +ippAddDate(), +ippAddInteger(), +ippAddIntegers(), +ippAddRange(), +ippAddRanges(), +ippAddResolution(), +ippAddResolutions(), +ippAddString(), +ippAddStrings() + + +

ippAddString()

+

Usage

+
+ipp_attribute_t *ippAddString(ipp_t *ipp, ipp_tag_t group,
+                              ipp_tag_t tag, const char *name,
+                              const char *charset, const char *value);
+
+

Arguments

+
+ + + + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
tagThe type of string value
nameThe name of attribute
charsetThe character set for the +string
valueThe string value
+
+

Returns

+

A pointer to the new attribute or NULL if +the attribute could not be created.

+

Description

+

The ippAddString() function adds a +single string attribute value to the specified IPP +request. For IPP_TAG_NAMELANG and +IPP_TAG_TEXTLANG strings, the charset value is +provided with the string to identify the string +encoding used. Otherwise the charset value is +ignored.

+

Example

+
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+
+ippAddString(ipp, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name",
+             NULL, "abc123");
+
+

See Also

+ ippAddBoolean(), +ippAddBooleans(), +ippAddDate(), +ippAddInteger(), +ippAddIntegers(), +ippAddRange(), +ippAddRanges(), +ippAddResolution(), +ippAddResolutions(), +ippAddSeparator(), +ippAddStrings() + + +

ippAddStrings()

+

Usage

+
+ipp_attribute_t *ippAddStrings(ipp_t *ipp, ipp_tag_t group,
+                               ipp_tag_t tag, const char *name,
+                               int num_values, const char *charset,
+                               const char **values);
+
+

Arguments

+
+ + + + + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
tagThe type of string value
nameThe name of attribute
num_valuesThe number of strings
charsetThe character set for the +strings
valuesThe string values
+
+

Returns

+

A pointer to the new attribute or NULL if +the attribute could not be created.

+

Description

+

The ippAddStrings() function adds one or +more string attribute values to the specified IPP +request. For IPP_TAG_NAMELANG and +IPP_TAG_TEXTLANG strings, the charset value is +provided with the strings to identify the string +encoding used. Otherwise the charset value is +ignored. If the values pointer is +NULL then an array of num_values + NULL strings is created.

+

Example

+
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+char *values[2] = { "one", "two" };
+
+ippAddStrings(ipp, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "attr-name",
+              2, NULL, values);
+
+

See Also

+ ippAddBoolean(), +ippAddBooleans(), +ippAddDate(), +ippAddInteger(), +ippAddIntegers(), +ippAddRange(), +ippAddRanges(), +ippAddResolution(), +ippAddResolutions(), +ippAddSeparator(), +ippAddString() + + +

ippDateToTime()

+

Usage

+
+time_t ippDateToTime(const ipp_uchar_t date[11]);
+
+

Arguments

+
+ + + +
ArgumentDescription
dateThe IPP date-time value
+
+

Returns

+

A UNIX time value.

+

Description

+

The ippDateToTime() function converts an +IPP date-time value to a UNIX time value.

+

Example

+
+#include <cups/ipp.h>
+
+ipp_uchar_t date[11];
+
+printf("UNIX time is %d\n", ippDateToTime(date));
+
+

See Also

+ ippTimeToDate() + + +

ippDelete()

+

Usage

+
+void ippDelete(ipp_t *ipp);
+
+

Arguments

+
+ + + +
ArgumentDescription
ippThe IPP request or response
+
+

Description

+

The ippDelete() function deletes all +memory used by an IPP request or response.

+

Example

+
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+
+ippDelete(ipp);
+
+

See Also

+ ippNew() + + +

ippFindAttribute()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + + +

ippLength()

+

Usage

+
+
+

Arguments

+
+ + + +
ArgumentDescription
+
+

Returns

+

Description

+

Example

+
+
+

See Also

+ + + +

ippNew()

+

Usage

+
+ipp_t *ippNew(void);
+
+

Returns

+

A pointer to a new IPP request or response. +

+

Description

+

The ippNew() function creates a new +IPP request or response.

+

Example

+
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+
+ipp = ippNew();
+
+

See Also

+ ippDelete() + + +

ippPort()

+

Usage

+
+int ippPort(void);
+
+

Returns

+

The default TCP/IP port number for IPP +requests.

+

Description

+

The ippPort() function returns the +default IPP port number for requests.

+

Example

+
+#include <cups/http.h>
+#include <cups/ipp.h>
+
+http_t *http;
+
+http = httpConnect(cupsServer(), ippPort());
+
+

See Also

+ cupsServer(), +ippSetPort() + + +

ippRead()

+

Usage

+
+ipp_state_t ippRead(http_t *http, ipp_t *ipp);
+
+

Arguments

+
+ + + + +
ArgumentDescription
httpThe HTTP connection
ippThe IPP request or response
+
+

Returns

+

The current read state.

+

Description

+

The ippRead() function reads IPP +attributes from the specified HTTP connection. +Programs should continue calling ippRead() + until IPP_ERROR or IPP_DATA is +returned.

+

Example

+
+#include <cups/http.h>
+#include <cups/ipp.h>
+
+http_t *http;
+ipp_t *ipp;
+ipp_state_t status;
+
+ipp = ippNew();
+
+while ((status = ippRead(http, ipp)) != IPP_ERROR)
+  if (status == IPP_DATA)
+    break;
+
+if (status == IPP_DATA)
+{
+  ... read additional non-IPP data using httpRead() ...
+}
+
+

See Also

+ ippWrite() + + +

ippSetPort()

+

Usage

+
+void
+ippSetPort(int port);
+
+

Arguments

+
+ + + +
ArgumentDescription
portThe port number to use
+
+

Description

+

The ippSetPort() function sets the +default IPP port number for requests.

+

Example

+
+#include <cups/http.h>
+#include <cups/ipp.h>
+
+...
+
+ippSetPort(8631);
+
+

See Also

+ ippPort() + + +

ippTimeToDate()

+

Usage

+
+ipp_uchar_t *ippTimeToDate(time_t time);
+
+

Arguments

+
+ + + +
ArgumentDescription
timeThe UNIX time value
+
+

Returns

+

A static pointer to an IPP date-time value.

+

Description

+

The ippTimeToDate() function converts a +UNIX time to an IPP date-time value.

+

Example

+
+#include <cups/ipp.h>
+
+ipp_uchar_t *date;
+
+date = ippTimeToDate(time(NULL));
+
+

See Also

+ ippDateToTime() + + +

ippWrite()

+

Usage

+
+ipp_state_t ippWrite(http_t *http, ipp_t *ipp);
+
+

Arguments

+
+ + + + +
ArgumentDescription
httpThe HTTP connection
ippThe IPP request or response
+
+

Returns

+

The current write state.

+

Description

+

The ippWrite() function writes IPP +attributes to the specified HTTP connection. Programs +should continue calling ippWrite() until +IPP_ERROR or IPP_DATA is returned.

+

Example

+
+#include <cups/http.h>
+#include <cups/ipp.h>
+
+http_t *http;
+ipp_t *ipp;
+ipp_state_t status;
+
+ipp = ippNew();
+... add attributes ...
+
+while ((status = ippWrite(http, ipp)) != IPP_ERROR)
+  if (status == IPP_DATA)
+    break;
+
+if (status == IPP_DATA)
+{
+  ... read additional non-IPP data using httpWrite() ...
+}
+
+

See Also

+ ippRead() + + +

ppdClose()

+

Usage

+
+void ppdClose(ppd_file_t *ppd);
+
+

Arguments

+
+ + + +
ArgumentDescription
ppdThe PPD file
+
+

Description

+

The ppdClose() function frees all memory +associated with the PPD file.

+

Example

+
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+
+ppdClose(ppd);
+
+

See Also

+ ppdOpen(), +ppdOpenFd(), +ppdOpenFile() + + +

ppdConflicts()

+

Usage

+
+int ppdConflicts(ppd_file_t *ppd);
+
+

Arguments

+
+ + + +
ArgumentDescription
ppdThe PPD file
+
+

Returns

+

The number of option conflicts in the file.

+

Description

+

The ppdConflicts() function returns the +number of conflicts with the currently selected +options.

+

Example

+
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+
+printf("%d conflicts\n", ppdConflicts(ppd));
+
+

See Also

+ cupsMarkOptions(), +ppdIsMarked(), +ppdMarkDefaults(), +ppdMarkOption() + + +

ppdEmit()

+

Usage

+
+int ppdEmit(ppd_file_t *ppd, FILE *file, ppd_section_t section);
+
+

Arguments

+
+ + + + + + +
ArgumentDescription
ppdThe PPD file
fileThe file to write to
sectionThe option section to write
+
+

Returns

+

0 on success, -1 on error.

+

Description

+

The ppdEmit() function sends +printer-specific option commands to the specified +file.

+

Example

+
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+
+ppdEmit(ppd, stdout, PPD_ORDER_PAGE);
+
+

See Also

+ ppdEmitFd() + + +

ppdEmitFd()

+

Usage

+
+int ppdEmitFd(ppd_file_t *ppd, int fd, ppd_section_t section);
+
+

Arguments

+
+ + + + + + + +
ArgumentDescription
ppdThe PPD file
fdThe file descriptor to write to
sectionThe option section to write
+
+

Returns

+

0 on success, -1 on error.

+

Description

+

The ppdEmitFd() function sends +printer-specific option commands to the specified +file descriptor.

+

Example

+
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+
+ppdEmitFd(ppd, 1, PPD_ORDER_PAGE);
+
+

See Also

+ ppdEmit() + + +

ppdFindChoice()

+

Usage

+
+ppd_choice_t *ppdFindChoice(ppd_option_t *option, const char *choice);
+
+

Arguments

+
+ + + + +
ArgumentDescription
optionA pointer to the option
choiceThe name of the choice
+
+

Returns

+

A pointer to the choice data or NULL if +the choice does not exist.

+

Description

+

The ppdFindChoice() function returns a +pointer to the choice data for the specified +option.

+

Example

+
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+ppd_option_t *option;
+ppd_choice_t *choice;
+
+option = ppdFindOption(ppd, "PageSize");
+choice = ppdFindChoice(option, "Letter");
+
+

See Also

+ ppdFindMarkedChoice() +, ppdFindOption() + + +

ppdFindMarkedChoice()

+

Usage

+
+ppd_choice_t *ppdFindMarkedChoice(ppd_file_t *ppd, const char *keyword);
+
+

Arguments

+
+ + + + +
ArgumentDescription
ppdThe PPD file
keywordThe name of the option
+
+

Returns

+

A pointer to the choice data or NULL if +the choice does not exist or is not marked.

+

Description

+

The ppdFindMarkedChoice() function returns +a pointer to the marked choice data for the +specified option.

+

Example

+
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+ppd_choice_t *choice;
+
+choice = ppdFindMarkedChoice(ppd, "PageSize");
+
+

See Also

+ ppdFindChoice(), +ppdFindOption() + + +

ppdFindOption()

+

Usage

+
+ppd_option_t *ppdFindOption(ppd_file_t *ppd, const char *keyword);
+
+

Arguments

+
+ + + + +
ArgumentDescription
ppdThe PPD file
keywordThe name of the option
+
+

Returns

+

A pointer to the option data or NULL if +the option does not exist.

+

Description

+

The ppdFindOption() function returns a +pointer to the option data for the specified +option.

+

Example

+
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+ppd_option_t *option;
+
+option = ppdFindOption(ppd, "PageSize");
+
+

See Also

+ ppdFindChoice(), +ppdFindMarkedChoice() + + +

ppdIsMarked()

+

Usage

+
+int ppdIsMarked(ppd_file_t *ppd, const char *keyword, char char *choice);
+
+

Arguments

+
+ + + + + +
ArgumentDescription
ppdThe PPD file
keywordThe name of the option
choiceThe name of the option choice +
+
+

Returns

+

1 if the choice is marked, 0 otherwise.

+

Description

+

The ppdIsMarked() function returns whether +or not the specified option choice is marked.

+

Example

+
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+
+printf("Letter size %s selected.\n",
+       ppdIsMarked(ppd, "PageSize", "Letter") ? "is" : "is not");
+
+

See Also

+ cupsMarkOptions(), +ppdConflicts(), +ppdIsMarked(), +ppdMarkDefaults(), +ppdMarkOption() + + +

ppdMarkDefaults()

+

Usage

+
+void ppdMarkDefaults(ppd_file_t *ppd);
+
+

Arguments

+
+ + + +
ArgumentDescription
ppdThe PPD file
+
+

Description

+

The ppdMarkDefaults() function marks all +of the default choices in the PPD file.

+

Example

+
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+
+ppdMarkDefaults(ppd);
+
+

See Also

+ cupsMarkOptions(), +ppdConflicts(), +ppdIsMarked(), +ppdMarkDefaults(), +ppdMarkOption() + + +

ppdMarkOption()

+

Usage

+
+int ppdMarkOption(ppd_file_t *ppd, const char *keyword, const char *choice);
+
+

Arguments

+
+ + + + + +
ArgumentDescription
ppdThe PPD file
keywordThe name of the option
choiceThe name of the choice
+
+

Returns

+

The number of conflicts in the PPD file.

+

Description

+

The ppdMarkOption() function marks the +specified option choice.

+

Example

+
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+
+ppdMarkOption(ppd, "PageSize", "Letter");
+
+

See Also

+ cupsMarkOptions(), +ppdConflicts(), +ppdIsMarked(), +ppdMarkDefaults(), +ppdMarkOption() + + +

ppdOpen()

+

Usage

+
+ppd_file_t *ppdOpen(FILE *file);
+
+

Arguments

+
+ + + +
ArgumentDescription
fileThe file to read from
+
+

Returns

+

A pointer to a PPD file structure or NULL +if the PPD file could not be read.

+

Description

+

The ppdOpen() function reads a PPD +file from the specified file into memory.

+

Example

+
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+FILE *file;
+
+file = fopen("filename.ppd", "rb");
+ppd = ppdOpen(file);
+fclose(file);
+
+

See Also

+ ppdClose(), +ppdOpenFd(), +ppdOpenFile() + + +

ppdOpenFd()

+

Usage

+
+ppd_file_t *ppdOpenFd(int fd);
+
+

Arguments

+
+ + + + +
ArgumentDescription
fdThe file descriptor to read from
+
+

Returns

+

A pointer to a PPD file structure or NULL +if the PPD file could not be read.

+

Description

+

The ppdOpenFd() function reads a PPD +file from the specified file descriptor into +memory.

+

Example

+
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+int        fd;
+
+fd = open("filename.ppd", O_RDONLY);
+ppd = ppdOpenFd(fd);
+close(fd);
+
+

See Also

+ ppdClose(), +ppdOpen(), +ppdOpenFile() + + +

ppdOpenFile()

+

Usage

+
+ppd_file_t *ppdOpenFile(const char *filename);
+
+

Arguments

+
+ + + +
ArgumentDescription
filenameThe name of the file to +read from
+
+

Returns

+

A pointer to a PPD file structure or NULL +if the PPD file could not be read.

+

Description

+

The ppdOpenFile() function reads a PPD +file from the named file into memory.

+

Example

+
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+
+ppd = ppdOpenFile("filename.ppd");
+
+

See Also

+ ppdClose(), +ppdOpen(), ppdOpenFd() + + + +

ppdPageLength()

+

Usage

+
+float ppdPageLength(ppd_file_t *ppd, const char *name);
+
+

Arguments

+
+ + + + +
ArgumentDescription
ppdThe PPD file
nameThe name of the page size
+
+

Returns

+

The length of the specified page size in +points or 0 if the page size does not exist. +

+

Description

+

The ppdPageLength() function returns the +page length of the specified page size.

+

Example

+
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+
+printf("Length = %.0f\n", ppdPageLength(ppd, "Letter"));
+
+

See Also

+ ppdPageLength(), +ppdPageSize(), +ppdPageWidth() + + +

ppdPageSize()

+

Usage

+
+ppd_size_t *ppdPageSize(ppd_file_t *ppd, const char *name);
+
+

Arguments

+
+ + + + +
ArgumentDescription
ppdThe PPD file
nameThe name of the page size
+
+

Returns

+

A pointer to the page size record of the +specified page size in points or NULL if the +page size does not exist.

+

Description

+

The ppdPageSize() function returns the +page size record for the specified page size.

+

Example

+
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+ppd_size_t *size;
+
+size = ppdPageSize(ppd, "Letter");
+if (size != NULL)
+{
+  printf(" Width = %.0f\n", size->width);
+  printf("Length = %.0f\n", size->length);
+  printf("  Left = %.0f\n", size->left);
+  printf(" Right = %.0f\n", size->right);
+  printf("Bottom = %.0f\n", size->bottom);
+  printf("   Top = %.0f\n", size->top);
+}
+
+

See Also

+ ppdPageLength(), +ppdPageWidth() + + +

ppdPageWidth()

+

Usage

+
+float ppdPageWidth(ppd_file_t *ppd, const char *name);
+
+

Arguments

+
+ + + + +
ArgumentDescription
ppdThe PPD file
nameThe name of the page size
+
+

Returns

+

The width of the specified page size in +points or 0 if the page size does not exist. +

+

Description

+

The ppdPageWidth() function returns the +page width of the specified page size.

+

Example

+
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+
+printf("Width = %.0f\n", ppdPageWidth(ppd, "Letter"));
+
+

See Also

+ ppdPageLength(), +ppdPageSize() + diff --git a/doc/spm.pdf b/doc/spm.pdf new file mode 100644 index 0000000000..7cfb93d87b --- /dev/null +++ b/doc/spm.pdf @@ -0,0 +1,9436 @@ +%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[15 0 R +17 0 R +18 0 R +]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[20 0 R +21 0 R +22 0 R +23 0 R +24 0 R +25 0 R +26 0 R +28 0 R +]endobj +30 0 obj<>endobj +31 0 obj<>endobj +32 0 obj<>endobj +33 0 obj[30 0 R +31 0 R +32 0 R +]endobj +34 0 obj<>endobj +35 0 obj[34 0 R +]endobj +36 0 obj<>endobj +37 0 obj<>endobj +38 0 obj[36 0 R +37 0 R +]endobj +39 0 obj<>endobj +40 0 obj<>endobj +41 0 obj[40 0 R +]endobj +42 0 obj<>endobj +43 0 obj[42 0 R +]endobj +44 0 obj<>endobj +45 0 obj<>endobj +46 0 obj<>endobj +47 0 obj<>endobj +48 0 obj[45 0 R +47 0 R +]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[50 0 R +52 0 R +54 0 R +]endobj +56 0 obj<>endobj +57 0 obj<>endobj +58 0 obj[57 0 R +]endobj +59 0 obj<>endobj +60 0 obj[59 0 R +]endobj +61 0 obj<>endobj +62 0 obj<>endobj +63 0 obj[62 0 R +]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[65 0 R +66 0 R +67 0 R +68 0 R +69 0 R +]endobj +71 0 obj<>endobj +72 0 obj<>endobj +73 0 obj<>endobj +74 0 obj<>endobj +75 0 obj<>endobj +76 0 obj[71 0 R +72 0 R +73 0 R +75 0 R +]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[78 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 +]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[93 0 R +95 0 R +97 0 R +99 0 R +100 0 R +101 0 R +102 0 R +103 0 R +104 0 R +105 0 R +106 0 R +107 0 R +108 0 R +109 0 R +]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<>endobj +119 0 obj<>endobj +120 0 obj[116 0 R +117 0 R +118 0 R +119 0 R +]endobj +121 0 obj<>endobj +122 0 obj<>endobj +123 0 obj<>endobj +124 0 obj<>endobj +125 0 obj[121 0 R +122 0 R +123 0 R +124 0 R +]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[126 0 R +127 0 R +128 0 R +129 0 R +131 0 R +]endobj +133 0 obj<>endobj +134 0 obj<>endobj +135 0 obj[133 0 R +134 0 R +]endobj +136 0 obj<>endobj +137 0 obj<>endobj +138 0 obj<>endobj +139 0 obj<>endobj +140 0 obj<>endobj +141 0 obj<>endobj +142 0 obj<>endobj +143 0 obj<>endobj +144 0 obj<>endobj +145 0 obj<>endobj +146 0 obj[136 0 R +137 0 R +138 0 R +139 0 R +140 0 R +141 0 R +142 0 R +143 0 R +144 0 R +145 0 R +]endobj +147 0 obj<>endobj +148 0 obj<>endobj +149 0 obj<>endobj +150 0 obj<>endobj +151 0 obj<>endobj +152 0 obj<>endobj +153 0 obj<>endobj +154 0 obj<>endobj +155 0 obj<>endobj +156 0 obj<>endobj +157 0 obj[147 0 R +148 0 R +149 0 R +150 0 R +151 0 R +152 0 R +153 0 R +154 0 R +155 0 R +156 0 R +]endobj +158 0 obj<>endobj +159 0 obj<>endobj +160 0 obj<>endobj +161 0 obj<>endobj +162 0 obj<>endobj +163 0 obj[158 0 R +159 0 R +160 0 R +161 0 R +162 0 R +]endobj +164 0 obj<>endobj +165 0 obj<>endobj +166 0 obj<>endobj +167 0 obj<>endobj +168 0 obj<>endobj +169 0 obj[164 0 R +165 0 R +166 0 R +167 0 R +168 0 R +]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[170 0 R +171 0 R +172 0 R +173 0 R +174 0 R +175 0 R +]endobj +177 0 obj<>endobj +178 0 obj<>endobj +179 0 obj<>endobj +180 0 obj<>endobj +181 0 obj[177 0 R +178 0 R +179 0 R +180 0 R +]endobj +182 0 obj<>endobj +183 0 obj<>endobj +184 0 obj<>endobj +185 0 obj[182 0 R +183 0 R +184 0 R +]endobj +186 0 obj<>endobj +187 0 obj<>endobj +188 0 obj<>endobj +189 0 obj[186 0 R +187 0 R +188 0 R +]endobj +190 0 obj<>endobj +191 0 obj<>endobj +192 0 obj<>endobj +193 0 obj<>endobj +194 0 obj<>endobj +195 0 obj[190 0 R +191 0 R +192 0 R +193 0 R +194 0 R +]endobj +196 0 obj<>endobj +197 0 obj<>endobj +198 0 obj<>endobj +199 0 obj<>endobj +200 0 obj<>endobj +201 0 obj[196 0 R +197 0 R +198 0 R +199 0 R +200 0 R +]endobj +202 0 obj<>endobj +203 0 obj<>endobj +204 0 obj<>endobj +205 0 obj<>endobj +206 0 obj<>endobj +207 0 obj[202 0 R +203 0 R +204 0 R +205 0 R +206 0 R +]endobj +208 0 obj<>endobj +209 0 obj<>endobj +210 0 obj<>endobj +211 0 obj<>endobj +212 0 obj<>endobj +213 0 obj[208 0 R +209 0 R +210 0 R +211 0 R +212 0 R +]endobj +214 0 obj<>endobj +215 0 obj<>endobj +216 0 obj<>endobj +217 0 obj<>endobj +218 0 obj<>endobj +219 0 obj[214 0 R +215 0 R +216 0 R +217 0 R +218 0 R +]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[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 +]endobj +231 0 obj<>endobj +232 0 obj<>endobj +233 0 obj<>endobj +234 0 obj<>endobj +235 0 obj<>endobj +236 0 obj[231 0 R +232 0 R +233 0 R +235 0 R +]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[237 0 R +238 0 R +239 0 R +241 0 R +242 0 R +243 0 R +244 0 R +246 0 R +]endobj +248 0 obj<>endobj +249 0 obj<>endobj +250 0 obj<>endobj +251 0 obj<>endobj +252 0 obj[248 0 R +249 0 R +250 0 R +251 0 R +]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[253 0 R +254 0 R +255 0 R +256 0 R +257 0 R +258 0 R +259 0 R +]endobj +261 0 obj<>endobj +262 0 obj[261 0 R +]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[263 0 R +264 0 R +265 0 R +266 0 R +267 0 R +268 0 R +269 0 R +]endobj +271 0 obj<>endobj +272 0 obj<>endobj +273 0 obj<>endobj +274 0 obj[271 0 R +272 0 R +273 0 R +]endobj +275 0 obj<>endobj +276 0 obj[275 0 R +]endobj +277 0 obj<>endobj +278 0 obj<>endobj +279 0 obj[277 0 R +278 0 R +]endobj +280 0 obj<>endobj +281 0 obj<>endobj +282 0 obj<>endobj +283 0 obj[280 0 R +281 0 R +282 0 R +]endobj +284 0 obj<>endobj +285 0 obj<>endobj +286 0 obj<>endobj +287 0 obj[284 0 R +285 0 R +286 0 R +]endobj +288 0 obj<>endobj +289 0 obj[288 0 R +]endobj +290 0 obj<>endobj +291 0 obj<>endobj +292 0 obj<>endobj +293 0 obj<>endobj +294 0 obj<>endobj +295 0 obj[290 0 R +291 0 R +292 0 R +293 0 R +294 0 R +]endobj +296 0 obj<>endobj +297 0 obj[296 0 R +]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[298 0 R +299 0 R +300 0 R +301 0 R +302 0 R +303 0 R +]endobj +305 0 obj<>endobj +306 0 obj[305 0 R +]endobj +307 0 obj<>endobj +308 0 obj<>endobj +309 0 obj<>endobj +310 0 obj<>endobj +311 0 obj<>endobj +312 0 obj[307 0 R +308 0 R +309 0 R +310 0 R +311 0 R +]endobj +313 0 obj<>endobj +314 0 obj[313 0 R +]endobj +315 0 obj<>endobj +316 0 obj[315 0 R +]endobj +317 0 obj<>endobj +318 0 obj<>endobj +319 0 obj<>endobj +320 0 obj<>endobj +321 0 obj<>endobj +322 0 obj[317 0 R +318 0 R +319 0 R +320 0 R +321 0 R +]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[323 0 R +324 0 R +325 0 R +326 0 R +327 0 R +328 0 R +329 0 R +330 0 R +]endobj +332 0 obj<>endobj +333 0 obj<>endobj +334 0 obj[332 0 R +333 0 R +]endobj +335 0 obj<>endobj +336 0 obj<>endobj +337 0 obj<>endobj +338 0 obj<>endobj +339 0 obj<>endobj +340 0 obj<>endobj +341 0 obj<>endobj +342 0 obj<>endobj +343 0 obj<>endobj +344 0 obj<>endobj +345 0 obj<>endobj +346 0 obj[335 0 R +336 0 R +337 0 R +338 0 R +339 0 R +340 0 R +341 0 R +342 0 R +343 0 R +344 0 R +345 0 R +]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[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 +]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[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 +]endobj +383 0 obj<>endobj +384 0 obj<>endobj +385 0 obj<>endobj +386 0 obj<>endobj +387 0 obj<>endobj +388 0 obj<>endobj +389 0 obj<>endobj +390 0 obj<>endobj +391 0 obj<>endobj +392 0 obj<>endobj +393 0 obj<>endobj +394 0 obj[383 0 R +384 0 R +385 0 R +386 0 R +387 0 R +388 0 R +389 0 R +390 0 R +391 0 R +392 0 R +393 0 R +]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[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 +]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[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 +]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[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 +]endobj +431 0 obj<>endobj +432 0 obj<>endobj +433 0 obj<>endobj +434 0 obj<>endobj +435 0 obj<>endobj +436 0 obj<>endobj +437 0 obj<>endobj +438 0 obj<>endobj +439 0 obj<>endobj +440 0 obj<>endobj +441 0 obj<>endobj +442 0 obj[431 0 R +432 0 R +433 0 R +434 0 R +435 0 R +436 0 R +437 0 R +438 0 R +439 0 R +440 0 R +441 0 R +]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[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 +]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[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 +]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[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 +]endobj +480 0 obj<>endobj +481 0 obj[480 0 R +]endobj +482 0 obj<>endobj +483 0 obj[482 0 R +]endobj +484 0 obj<>endobj +485 0 obj<>endobj +486 0 obj[484 0 R +485 0 R +]endobj +487 0 obj<>endobj +488 0 obj[487 0 R +]endobj +489 0 obj<>endobj +490 0 obj<>endobj +491 0 obj[489 0 R +490 0 R +]endobj +492 0 obj<>endobj +493 0 obj[492 0 R +]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[494 0 R +495 0 R +496 0 R +497 0 R +498 0 R +499 0 R +500 0 R +]endobj +502 0 obj<>endobj +503 0 obj[502 0 R +]endobj +504 0 obj<>endobj +505 0 obj[504 0 R +]endobj +506 0 obj<>endobj +507 0 obj<>endobj +508 0 obj<>endobj +509 0 obj<>endobj +510 0 obj[506 0 R +507 0 R +508 0 R +509 0 R +]endobj +511 0 obj<>endobj +512 0 obj<>endobj +513 0 obj[511 0 R +512 0 R +]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[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 +]endobj +525 0 obj<>endobj +526 0 obj<>endobj +527 0 obj<>endobj +528 0 obj<>endobj +529 0 obj<>endobj +530 0 obj[525 0 R +526 0 R +527 0 R +528 0 R +529 0 R +]endobj +531 0 obj<>endobj +532 0 obj<>endobj +533 0 obj<>endobj +534 0 obj[531 0 R +532 0 R +533 0 R +]endobj +535 0 obj<>endobj +536 0 obj<>endobj +537 0 obj<>endobj +538 0 obj<>endobj +539 0 obj<>endobj +540 0 obj<>endobj +541 0 obj[535 0 R +536 0 R +537 0 R +538 0 R +539 0 R +540 0 R +]endobj +542 0 obj<>endobj +543 0 obj<>endobj +544 0 obj<>endobj +545 0 obj[542 0 R +543 0 R +544 0 R +]endobj +546 0 obj<>endobj +547 0 obj<>endobj +548 0 obj<>endobj +549 0 obj<>endobj +550 0 obj[546 0 R +547 0 R +548 0 R +549 0 R +]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<>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[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 +584 0 R +585 0 R +586 0 R +587 0 R +588 0 R +589 0 R +590 0 R +591 0 R +592 0 R +593 0 R +594 0 R +595 0 R +]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<>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[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 +632 0 R +633 0 R +634 0 R +635 0 R +636 0 R +637 0 R +638 0 R +639 0 R +640 0 R +]endobj +642 0 obj<>endobj +643 0 obj<>endobj +644 0 obj<>endobj +645 0 obj<>endobj +646 0 obj<>endobj +647 0 obj<>endobj +648 0 obj<>endobj +649 0 obj<>endobj +650 0 obj<>endobj +651 0 obj<>endobj +652 0 obj<>endobj +653 0 obj<>endobj +654 0 obj<>endobj +655 0 obj<>endobj +656 0 obj<>endobj +657 0 obj<>endobj +658 0 obj<>endobj +659 0 obj<>endobj +660 0 obj<>endobj +661 0 obj<>endobj +662 0 obj<>endobj +663 0 obj<>endobj +664 0 obj<>endobj +665 0 obj<>endobj +666 0 obj<>endobj +667 0 obj<>endobj +668 0 obj<>endobj +669 0 obj<>endobj +670 0 obj<>endobj +671 0 obj<>endobj +672 0 obj<>endobj +673 0 obj<>endobj +674 0 obj<>endobj +675 0 obj<>endobj +676 0 obj<>endobj +677 0 obj<>endobj +678 0 obj<>endobj +679 0 obj<>endobj +680 0 obj<>endobj +681 0 obj<>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[642 0 R +643 0 R +644 0 R +645 0 R +646 0 R +647 0 R +648 0 R +649 0 R +650 0 R +651 0 R +652 0 R +653 0 R +654 0 R +655 0 R +656 0 R +657 0 R +658 0 R +659 0 R +660 0 R +661 0 R +662 0 R +663 0 R +664 0 R +665 0 R +666 0 R +667 0 R +668 0 R +669 0 R +670 0 R +671 0 R +672 0 R +673 0 R +674 0 R +675 0 R +676 0 R +677 0 R +678 0 R +679 0 R +680 0 R +681 0 R +682 0 R +683 0 R +684 0 R +685 0 R +686 0 R +687 0 R +]endobj +689 0 obj<>endobj +690 0 obj<>endobj +691 0 obj<>endobj +692 0 obj<>endobj +693 0 obj<>endobj +694 0 obj<>endobj +695 0 obj<>endobj +696 0 obj<>endobj +697 0 obj<>endobj +698 0 obj<>endobj +699 0 obj<>endobj +700 0 obj<>endobj +701 0 obj<>endobj +702 0 obj<>endobj +703 0 obj<>endobj +704 0 obj<>endobj +705 0 obj<>endobj +706 0 obj<>endobj +707 0 obj<>endobj +708 0 obj<>endobj +709 0 obj<>endobj +710 0 obj<>endobj +711 0 obj<>endobj +712 0 obj<>endobj +713 0 obj<>endobj +714 0 obj<>endobj +715 0 obj<>endobj +716 0 obj<>endobj +717 0 obj<>endobj +718 0 obj<>endobj +719 0 obj<>endobj +720 0 obj<>endobj +721 0 obj<>endobj +722 0 obj<>endobj +723 0 obj<>endobj +724 0 obj<>endobj +725 0 obj<>endobj +726 0 obj<>endobj +727 0 obj<>endobj +728 0 obj<>endobj +729 0 obj<>endobj +730 0 obj<>endobj +731 0 obj<>endobj +732 0 obj<>endobj +733 0 obj<>endobj +734 0 obj<>endobj +735 0 obj<>endobj +736 0 obj<>endobj +737 0 obj[689 0 R +690 0 R +691 0 R +692 0 R +693 0 R +694 0 R +695 0 R +696 0 R +697 0 R +698 0 R +699 0 R +700 0 R +701 0 R +702 0 R +703 0 R +704 0 R +705 0 R +706 0 R +707 0 R +708 0 R +709 0 R +710 0 R +711 0 R +712 0 R +713 0 R +714 0 R +715 0 R +716 0 R +717 0 R +718 0 R +719 0 R +720 0 R +721 0 R +722 0 R +723 0 R +724 0 R +725 0 R +726 0 R +727 0 R +728 0 R +729 0 R +730 0 R +731 0 R +732 0 R +733 0 R +734 0 R +735 0 R +736 0 R +]endobj +738 0 obj<>endobj +739 0 obj<>endobj +740 0 obj<>endobj +741 0 obj<>endobj +742 0 obj<>endobj +743 0 obj<>endobj +744 0 obj<>endobj +745 0 obj<>endobj +746 0 obj<>endobj +747 0 obj<>endobj +748 0 obj<>endobj +749 0 obj<>endobj +750 0 obj<>endobj +751 0 obj<>endobj +752 0 obj<>endobj +753 0 obj<>endobj +754 0 obj<>endobj +755 0 obj<>endobj +756 0 obj<>endobj +757 0 obj<>endobj +758 0 obj<>endobj +759 0 obj<>endobj +760 0 obj<>endobj +761 0 obj<>endobj +762 0 obj<>endobj +763 0 obj<>endobj +764 0 obj<>endobj +765 0 obj<>endobj +766 0 obj<>endobj +767 0 obj<>endobj +768 0 obj<>endobj +769 0 obj<>endobj +770 0 obj<>endobj +771 0 obj<>endobj +772 0 obj<>endobj +773 0 obj<>endobj +774 0 obj<>endobj +775 0 obj<>endobj +776 0 obj<>endobj +777 0 obj<>endobj +778 0 obj<>endobj +779 0 obj<>endobj +780 0 obj<>endobj +781 0 obj<>endobj +782 0 obj<>endobj +783 0 obj<>endobj +784 0 obj<>endobj +785 0 obj<>endobj +786 0 obj[738 0 R +739 0 R +740 0 R +741 0 R +742 0 R +743 0 R +744 0 R +745 0 R +746 0 R +747 0 R +748 0 R +749 0 R +750 0 R +751 0 R +752 0 R +753 0 R +754 0 R +755 0 R +756 0 R +757 0 R +758 0 R +759 0 R +760 0 R +761 0 R +762 0 R +763 0 R +764 0 R +765 0 R +766 0 R +767 0 R +768 0 R +769 0 R +770 0 R +771 0 R +772 0 R +773 0 R +774 0 R +775 0 R +776 0 R +777 0 R +778 0 R +779 0 R +780 0 R +781 0 R +782 0 R +783 0 R +784 0 R +785 0 R +]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<>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[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 +824 0 R +825 0 R +826 0 R +827 0 R +828 0 R +829 0 R +830 0 R +831 0 R +832 0 R +833 0 R +834 0 R +]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<>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[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 +872 0 R +873 0 R +874 0 R +875 0 R +876 0 R +877 0 R +878 0 R +879 0 R +880 0 R +881 0 R +882 0 R +883 0 R +]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<>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[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 +920 0 R +921 0 R +922 0 R +923 0 R +924 0 R +925 0 R +926 0 R +927 0 R +928 0 R +929 0 R +930 0 R +931 0 R +932 0 R +]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<>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[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 +968 0 R +969 0 R +970 0 R +971 0 R +972 0 R +973 0 R +974 0 R +975 0 R +976 0 R +977 0 R +978 0 R +979 0 R +980 0 R +981 0 R +]endobj +983 0 obj<>endobj +984 0 obj<>endobj +985 0 obj<>endobj +986 0 obj<>endobj +987 0 obj<>endobj +988 0 obj<>endobj +989 0 obj<>endobj +990 0 obj<>endobj +991 0 obj<>endobj +992 0 obj<>endobj +993 0 obj<>endobj +994 0 obj<>endobj +995 0 obj<>endobj +996 0 obj<>endobj +997 0 obj<>endobj +998 0 obj<>endobj +999 0 obj<>endobj +1000 0 obj<>endobj +1001 0 obj<>endobj +1002 0 obj<>endobj +1003 0 obj<>endobj +1004 0 obj<>endobj +1005 0 obj<>endobj +1006 0 obj<>endobj +1007 0 obj<>endobj +1008 0 obj<>endobj +1009 0 obj<>endobj +1010 0 obj<>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[983 0 R +984 0 R +985 0 R +986 0 R +987 0 R +988 0 R +989 0 R +990 0 R +991 0 R +992 0 R +993 0 R +994 0 R +995 0 R +996 0 R +997 0 R +998 0 R +999 0 R +1000 0 R +1001 0 R +1002 0 R +1003 0 R +1004 0 R +1005 0 R +1006 0 R +1007 0 R +1008 0 R +1009 0 R +1010 0 R +1011 0 R +1012 0 R +1013 0 R +1014 0 R +1015 0 R +1016 0 R +1017 0 R +1018 0 R +1019 0 R +1020 0 R +1021 0 R +1022 0 R +1023 0 R +1024 0 R +1025 0 R +1026 0 R +1027 0 R +1028 0 R +1029 0 R +1030 0 R +]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[1032 0 R +1033 0 R +1034 0 R +1035 0 R +1036 0 R +1037 0 R +1038 0 R +1039 0 R +1040 0 R +1041 0 R +1042 0 R +1043 0 R +1044 0 R +1045 0 R +1046 0 R +1047 0 R +1048 0 R +1049 0 R +1050 0 R +1051 0 R +1052 0 R +1053 0 R +1054 0 R +1055 0 R +1056 0 R +1057 0 R +1058 0 R +1059 0 R +1060 0 R +1061 0 R +1062 0 R +1063 0 R +1064 0 R +1065 0 R +1066 0 R +1067 0 R +1068 0 R +1069 0 R +1070 0 R +1071 0 R +1072 0 R +1073 0 R +1074 0 R +1075 0 R +1076 0 R +1077 0 R +1078 0 R +1079 0 R +]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[1081 0 R +1082 0 R +1083 0 R +1084 0 R +1085 0 R +1086 0 R +1087 0 R +1088 0 R +1089 0 R +1090 0 R +1091 0 R +1092 0 R +1093 0 R +1094 0 R +1095 0 R +1096 0 R +1097 0 R +1098 0 R +1099 0 R +1100 0 R +1101 0 R +1102 0 R +1103 0 R +1104 0 R +1105 0 R +1106 0 R +1107 0 R +1108 0 R +1109 0 R +1110 0 R +1111 0 R +1112 0 R +1113 0 R +1114 0 R +1115 0 R +1116 0 R +1117 0 R +1118 0 R +1119 0 R +1120 0 R +1121 0 R +1122 0 R +1123 0 R +1124 0 R +1125 0 R +1126 0 R +1127 0 R +1128 0 R +]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[1130 0 R +1131 0 R +1132 0 R +1133 0 R +1134 0 R +1135 0 R +1136 0 R +1137 0 R +1138 0 R +1139 0 R +1140 0 R +1141 0 R +1142 0 R +1143 0 R +1144 0 R +1145 0 R +1146 0 R +1147 0 R +1148 0 R +1149 0 R +1150 0 R +1151 0 R +1152 0 R +1153 0 R +1154 0 R +1155 0 R +1156 0 R +1157 0 R +1158 0 R +1159 0 R +1160 0 R +1161 0 R +1162 0 R +1163 0 R +1164 0 R +1165 0 R +1166 0 R +1167 0 R +1168 0 R +1169 0 R +1170 0 R +1171 0 R +1172 0 R +1173 0 R +1174 0 R +1175 0 R +1176 0 R +1177 0 R +]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[1179 0 R +1180 0 R +1181 0 R +1182 0 R +1183 0 R +1184 0 R +1185 0 R +1186 0 R +1187 0 R +1188 0 R +1189 0 R +1190 0 R +1191 0 R +1192 0 R +1193 0 R +1194 0 R +1195 0 R +1196 0 R +1197 0 R +1198 0 R +1199 0 R +1200 0 R +1201 0 R +1202 0 R +1203 0 R +1204 0 R +1205 0 R +1206 0 R +1207 0 R +1208 0 R +1209 0 R +1210 0 R +1211 0 R +1212 0 R +1213 0 R +1214 0 R +1215 0 R +1216 0 R +1217 0 R +1218 0 R +1219 0 R +1220 0 R +1221 0 R +1222 0 R +1223 0 R +1224 0 R +1225 0 R +1226 0 R +]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[1228 0 R +1229 0 R +1230 0 R +1231 0 R +1232 0 R +1233 0 R +1234 0 R +1235 0 R +1236 0 R +1237 0 R +1238 0 R +1239 0 R +1240 0 R +1241 0 R +1242 0 R +1243 0 R +1244 0 R +1245 0 R +1246 0 R +1247 0 R +1248 0 R +1249 0 R +1250 0 R +1251 0 R +1252 0 R +1253 0 R +1254 0 R +1255 0 R +1256 0 R +1257 0 R +1258 0 R +1259 0 R +1260 0 R +1261 0 R +1262 0 R +1263 0 R +1264 0 R +1265 0 R +1266 0 R +1267 0 R +1268 0 R +1269 0 R +1270 0 R +1271 0 R +1272 0 R +1273 0 R +1274 0 R +1275 0 R +]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[1277 0 R +1278 0 R +1279 0 R +1280 0 R +1281 0 R +1282 0 R +1283 0 R +1284 0 R +1285 0 R +1286 0 R +1287 0 R +1288 0 R +1289 0 R +1290 0 R +1291 0 R +1292 0 R +1293 0 R +1294 0 R +1295 0 R +1296 0 R +1297 0 R +1298 0 R +1299 0 R +1300 0 R +1301 0 R +1302 0 R +1303 0 R +1304 0 R +1305 0 R +1306 0 R +1307 0 R +1308 0 R +1309 0 R +1310 0 R +1311 0 R +1312 0 R +1313 0 R +1314 0 R +1315 0 R +1316 0 R +1317 0 R +1318 0 R +1319 0 R +1320 0 R +1321 0 R +1322 0 R +1323 0 R +1324 0 R +]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[1326 0 R +1327 0 R +1328 0 R +1329 0 R +1330 0 R +1331 0 R +1332 0 R +1333 0 R +1334 0 R +1335 0 R +1336 0 R +1337 0 R +1338 0 R +1339 0 R +1340 0 R +1341 0 R +1342 0 R +1343 0 R +1344 0 R +1345 0 R +1346 0 R +1347 0 R +1348 0 R +1349 0 R +1350 0 R +1351 0 R +1352 0 R +1353 0 R +1354 0 R +1355 0 R +]endobj +1357 0 obj<>endobj +1358 0 obj<>endobj +1359 0 obj<>endobj +1360 0 obj<>endobj +1361 0 obj<>endobj +1362 0 obj<>endobj +1363 0 obj<>endobj +1364 0 obj<>endobj +1365 0 obj<>endobj +1366 0 obj<>endobj +1367 0 obj<>endobj +1368 0 obj<>endobj +1369 0 obj<>endobj +1370 0 obj<>endobj +1371 0 obj<>endobj +1372 0 obj<>endobj +1373 0 obj<>endobj +1374 0 obj<>endobj +1375 0 obj<>endobj +1376 0 obj<>endobj +1377 0 obj<>endobj +1378 0 obj<>endobj +1379 0 obj<>endobj +1380 0 obj<>endobj +1381 0 obj<>endobj +1382 0 obj<>endobj +1383 0 obj<>endobj +1384 0 obj<>endobj +1385 0 obj<>endobj +1386 0 obj<>endobj +1387 0 obj<>endobj +1388 0 obj<>endobj +1389 0 obj<>endobj +1390 0 obj<>endobj +1391 0 obj<>endobj +1392 0 obj<>endobj +1393 0 obj<>endobj +1394 0 obj<>endobj +1395 0 obj<>endobj +1396 0 obj<>endobj +1397 0 obj<>endobj +1398 0 obj<>endobj +1399 0 obj<>endobj +1400 0 obj<>endobj +1401 0 obj<>endobj +1402 0 obj<>endobj +1403 0 obj<>endobj +1404 0 obj<>endobj +1405 0 obj<>endobj +1406 0 obj<>endobj +1407 0 obj<>endobj +1408 0 obj<>endobj +1409 0 obj<>endobj +1410 0 obj<>endobj +1411 0 obj<>endobj +1412 0 obj<>endobj +1413 0 obj<>endobj +1414 0 obj<>endobj +1415 0 obj<>endobj +1416 0 obj<>endobj +1417 0 obj<>endobj +1418 0 obj<>endobj +1419 0 obj<>endobj +1420 0 obj<>endobj +1421 0 obj<>endobj +1422 0 obj<>endobj +1423 0 obj<>endobj +1424 0 obj<>endobj +1425 0 obj<>endobj +1426 0 obj<>endobj +1427 0 obj<>endobj +1428 0 obj<>endobj +1429 0 obj<>endobj +1430 0 obj<>endobj +1431 0 obj<>endobj +1432 0 obj<>endobj +1433 0 obj<>endobj +1434 0 obj<>endobj +1435 0 obj<>endobj +1436 0 obj<>endobj +1437 0 obj<>endobj +1438 0 obj<>endobj +1439 0 obj<>endobj +1440 0 obj<>endobj +1441 0 obj<>endobj +1442 0 obj<>endobj +1443 0 obj<>endobj +1444 0 obj<>endobj +1445 0 obj<>endobj +1446 0 obj<>endobj +1447 0 obj<>endobj +1448 0 obj<>endobj +1449 0 obj<>endobj +1450 0 obj<>endobj +1451 0 obj<>endobj +1452 0 obj<>endobj +1453 0 obj<>endobj +1454 0 obj<>endobj +1455 0 obj<>endobj +1456 0 obj<>endobj +1457 0 obj<>endobj +1458 0 obj<>endobj +1459 0 obj<>endobj +1460 0 obj<>endobj +1461 0 obj<>endobj +1462 0 obj<>endobj +1463 0 obj<>endobj +1464 0 obj<>endobj +1465 0 obj<>endobj +1466 0 obj<>endobj +1467 0 obj<>endobj +1468 0 obj<>endobj +1469 0 obj<>endobj +1470 0 obj<>endobj +1471 0 obj<>endobj +1472 0 obj<>endobj +1473 0 obj<>endobj +1474 0 obj<>endobj +1475 0 obj<>endobj +1476 0 obj<>endobj +1477 0 obj<>endobj +1478 0 obj<>endobj +1479 0 obj<>endobj +1480 0 obj<>endobj +1481 0 obj<>endobj +1482 0 obj<>endobj +1483 0 obj<>endobj +1484 0 obj<>endobj +1485 0 obj<>endobj +1486 0 obj<>endobj +1487 0 obj<>endobj +1488 0 obj<>endobj +1489 0 obj<>endobj +1490 0 obj<>endobj +1491 0 obj<>endobj +1492 0 obj<>endobj +1493 0 obj<>endobj +1494 0 obj<>endobj +1495 0 obj<>endobj +1496 0 obj<>endobj +1497 0 obj<>endobj +1498 0 obj<>endobj +1499 0 obj<>endobj +1500 0 obj<>endobj +1501 0 obj<>endobj +1502 0 obj<>endobj +1503 0 obj<>endobj +1504 0 obj<>endobj +1505 0 obj<>endobj +1506 0 obj<>endobj +1507 0 obj<>endobj +1508 0 obj<>endobj +1509 0 obj<>endobj +1510 0 obj<>endobj +1511 0 obj<>endobj +1512 0 obj<>endobj +1513 0 obj<>endobj +1514 0 obj<>endobj +1515 0 obj<>endobj +1516 0 obj<>endobj +1517 0 obj<>endobj +1518 0 obj<>endobj +1519 0 obj<>endobj +1520 0 obj<>endobj +1521 0 obj<>endobj +1522 0 obj<>endobj +1523 0 obj<>endobj +1524 0 obj<>endobj +1525 0 obj<>endobj +1526 0 obj<>endobj +1527 0 obj<>endobj +1528 0 obj<>endobj +1529 0 obj<>endobj +1530 0 obj<>endobj +1531 0 obj<>endobj +1532 0 obj<>endobj +1533 0 obj<>endobj +1534 0 obj<>endobj +1535 0 obj<>endobj +1536 0 obj<>endobj +1537 0 obj<>endobj +1538 0 obj<>endobj +1539 0 obj<>endobj +1540 0 obj<>endobj +1541 0 obj<>endobj +1542 0 obj<>endobj +1543 0 obj<>endobj +1544 0 obj<>endobj +1545 0 obj<>endobj +1546 0 obj<>endobj +1547 0 obj<>endobj +1548 0 obj<>endobj +1549 0 obj<>endobj +1550 0 obj<>endobj +1551 0 obj<>endobj +1552 0 obj<>endobj +1553 0 obj<>endobj +1554 0 obj<>endobj +1555 0 obj<>endobj +1556 0 obj<>endobj +1557 0 obj<>endobj +1558 0 obj<>endobj +1559 0 obj<>endobj +1560 0 obj<>endobj +1561 0 obj<>endobj +1562 0 obj<>endobj +1563 0 obj<>endobj +1564 0 obj<>endobj +1565 0 obj<>endobj +1566 0 obj<>endobj +1567 0 obj<>endobj +1568 0 obj<>endobj +1569 0 obj<>endobj +1570 0 obj<>endobj +1571 0 obj<>endobj +1572 0 obj<>endobj +1573 0 obj<>endobj +1574 0 obj<>endobj +1575 0 obj<>endobj +1576 0 obj<>endobj +1577 0 obj<>endobj +1578 0 obj<>endobj +1579 0 obj<>endobj +1580 0 obj<>endobj +1581 0 obj<>endobj +1582 0 obj<>endobj +1583 0 obj<>endobj +1584 0 obj<>endobj +1585 0 obj<>endobj +1586 0 obj<>endobj +1587 0 obj<>endobj +1588 0 obj<>endobj +1589 0 obj<>endobj +1590 0 obj<>endobj +1591 0 obj<>endobj +1592 0 obj<>endobj +1593 0 obj<>endobj +1594 0 obj<>endobj +1595 0 obj<>endobj +1596 0 obj<>endobj +1597 0 obj<>endobj +1598 0 obj<>endobj +1599 0 obj<>endobj +1600 0 obj<>endobj +1601 0 obj<>endobj +1602 0 obj<>endobj +1603 0 obj<>endobj +1604 0 obj<>endobj +1605 0 obj<>endobj +1606 0 obj<>endobj +1607 0 obj<>endobj +1608 0 obj<>endobj +1609 0 obj<>endobj +1610 0 obj<>endobj +1611 0 obj<>endobj +1612 0 obj<>endobj +1613 0 obj<>endobj +1614 0 obj<>endobj +1615 0 obj<>endobj +1616 0 obj<>endobj +1617 0 obj<>endobj +1618 0 obj<>endobj +1619 0 obj<>endobj +1620 0 obj<>endobj +1621 0 obj<>endobj +1622 0 obj<>endobj +1623 0 obj<>endobj +1624 0 obj<>endobj +1625 0 obj<>endobj +1626 0 obj<>endobj +1627 0 obj<>endobj +1628 0 obj<>endobj +1629 0 obj<>endobj +1630 0 obj<>endobj +1631 0 obj<>endobj +1632 0 obj<>endobj +1633 0 obj<>endobj +1634 0 obj<>endobj +1635 0 obj<>endobj +1636 0 obj<>endobj +1637 0 obj<>endobj +1638 0 obj<>endobj +1639 0 obj<>endobj +1640 0 obj<>endobj +1641 0 obj<>endobj +1642 0 obj<>endobj +1643 0 obj<>endobj +1644 0 obj<>endobj +1645 0 obj<>endobj +1646 0 obj<>endobj +1647 0 obj<>endobj +1648 0 obj<>endobj +1649 0 obj<>endobj +1650 0 obj<>endobj +1651 0 obj<>endobj +1652 0 obj<>endobj +1653 0 obj<>endobj +1654 0 obj<>endobj +1655 0 obj<>endobj +1656 0 obj<>endobj +1657 0 obj<>endobj +1658 0 obj<>endobj +1659 0 obj<>endobj +1660 0 obj<>endobj +1661 0 obj<>endobj +1662 0 obj<>endobj +1663 0 obj<>endobj +1664 0 obj<>endobj +1665 0 obj<>endobj +1666 0 obj<>endobj +1667 0 obj<>endobj +1668 0 obj<>endobj +1669 0 obj<>endobj +1670 0 obj<>endobj +1671 0 obj<>endobj +1672 0 obj<>endobj +1673 0 obj<>endobj +1674 0 obj<>endobj +1675 0 obj<>endobj +1676 0 obj<>endobj +1677 0 obj<>endobj +1678 0 obj<>endobj +1679 0 obj<>endobj +1680 0 obj<>endobj +1681 0 obj<>endobj +1682 0 obj<>endobj +1683 0 obj<>endobj +1684 0 obj<>endobj +1685 0 obj<>endobj +1686 0 obj<>endobj +1687 0 obj<>endobj +1688 0 obj<>endobj +1689 0 obj<>endobj +1690 0 obj<>endobj +1691 0 obj<>endobj +1692 0 obj<>endobj +1693 0 obj<>endobj +1694 0 obj<>endobj +1695 0 obj<>endobj +1696 0 obj<>endobj +1697 0 obj<>endobj +1698 0 obj<>endobj +1699 0 obj<>endobj +1700 0 obj<>endobj +1701 0 obj<>endobj +1702 0 obj<>endobj +1703 0 obj<>endobj +1704 0 obj<>endobj +1705 0 obj<>endobj +1706 0 obj<>endobj +1707 0 obj<>endobj +1708 0 obj<>endobj +1709 0 obj<>endobj +1710 0 obj<>endobj +1711 0 obj<>endobj +1712 0 obj<>endobj +1713 0 obj<>endobj +1714 0 obj<>endobj +1715 0 obj<>endobj +1716 0 obj<>endobj +1717 0 obj<>endobj +1718 0 obj<>endobj +1719 0 obj<>endobj +1720 0 obj<>endobj +1721 0 obj<>endobj +1722 0 obj<>endobj +1723 0 obj<>endobj +1724 0 obj<>endobj +1725 0 obj<>endobj +1726 0 obj<>endobj +1727 0 obj<>endobj +1728 0 obj<>endobj +1729 0 obj<>endobj +1730 0 obj<>endobj +1731 0 obj<>endobj +1732 0 obj<>endobj +1733 0 obj<>endobj +1734 0 obj<>endobj +1735 0 obj<>endobj +1736 0 obj<>endobj +1737 0 obj<>endobj +1738 0 obj<>endobj +1739 0 obj<>endobj +1740 0 obj<>endobj +1741 0 obj<>endobj +1742 0 obj<>endobj +1743 0 obj<>endobj +1744 0 obj<>endobj +1745 0 obj<>endobj +1746 0 obj<>endobj +1747 0 obj<>endobj +1748 0 obj<>endobj +1749 0 obj<>endobj +1750 0 obj<>endobj +1751 0 obj<>endobj +1752 0 obj<>endobj +1753 0 obj<>endobj +1754 0 obj<>endobj +1755 0 obj<>endobj +1756 0 obj<>endobj +1757 0 obj<>endobj +1758 0 obj<>endobj +1759 0 obj<>endobj +1760 0 obj<>endobj +1761 0 obj<>endobj +1762 0 obj<>endobj +1763 0 obj<>endobj +1764 0 obj<>endobj +1765 0 obj<>endobj +1766 0 obj<>endobj +1767 0 obj<>endobj +1768 0 obj<>endobj +1769 0 obj<>endobj +1770 0 obj<>endobj +1771 0 obj<>endobj +1772 0 obj<>endobj +1773 0 obj<>endobj +1774 0 obj<>endobj +1775 0 obj<>endobj +1776 0 obj<>endobj +1777 0 obj<>endobj +1778 0 obj<>endobj +1779 0 obj<>endobj +1780 0 obj<>endobj +1781 0 obj<>endobj +1782 0 obj<>endobj +1783 0 obj<>endobj +1784 0 obj<>endobj +1785 0 obj<>endobj +1786 0 obj<>endobj +1787 0 obj<>endobj +1788 0 obj<>endobj +1789 0 obj<>endobj +1790 0 obj<>endobj +1791 0 obj<>endobj +1792 0 obj<>endobj +1793 0 obj<>endobj +1794 0 obj<>endobj +1795 0 obj<>endobj +1796 0 obj<>endobj +1797 0 obj<>endobj +1798 0 obj<>endobj +1799 0 obj<>endobj +1800 0 obj<>endobj +1801 0 obj<>endobj +1802 0 obj<>endobj +1803 0 obj<>endobj +1804 0 obj<>endobj +1805 0 obj<>endobj +1806 0 obj<>endobj +1807 0 obj<>endobj +1808 0 obj<>endobj +1809 0 obj<>endobj +1810 0 obj<>endobj +1811 0 obj<>endobj +1812 0 obj<>endobj +1813 0 obj<>endobj +1814 0 obj<>endobj +1815 0 obj<>endobj +1816 0 obj<>endobj +1817 0 obj<>endobj +1818 0 obj<>endobj +1819 0 obj<>endobj +1820 0 obj<>endobj +1821 0 obj<>endobj +1822 0 obj<>endobj +1823 0 obj<>endobj +1824 0 obj<>endobj +1825 0 obj<>endobj +1826 0 obj<>endobj +1827 0 obj<>endobj +1828 0 obj<>endobj +1829 0 obj<>endobj +1830 0 obj<>endobj +1831 0 obj<>endobj +1832 0 obj<>endobj +1833 0 obj<>endobj +1834 0 obj<>endobj +1835 0 obj<>endobj +1836 0 obj<>endobj +1837 0 obj<>endobj +1838 0 obj<>endobj +1839 0 obj<>endobj +1840 0 obj<>endobj +1841 0 obj<>endobj +1842 0 obj<>endobj +1843 0 obj<>endobj +1844 0 obj<>endobj +1845 0 obj<>endobj +1846 0 obj<>endobj +1847 0 obj<>endobj +1848 0 obj<>endobj +1849 0 obj<>endobj +1850 0 obj<>endobj +1851 0 obj<>endobj +1852 0 obj<>endobj +1853 0 obj<>endobj +1854 0 obj<>endobj +1855 0 obj<>endobj +1856 0 obj<>endobj +1857 0 obj<>endobj +1858 0 obj<>endobj +1859 0 obj<>endobj +1860 0 obj<>endobj +1861 0 obj<>endobj +1862 0 obj<>endobj +1863 0 obj<>endobj +1864 0 obj<>endobj +1865 0 obj<>endobj +1866 0 obj<>endobj +1867 0 obj<>endobj +1868 0 obj<>endobj +1869 0 obj<>endobj +1870 0 obj<>endobj +1871 0 obj<>endobj +1872 0 obj<>endobj +1873 0 obj<>endobj +1874 0 obj<>endobj +1875 0 obj<>endobj +1876 0 obj<>endobj +1877 0 obj<>endobj +1878 0 obj<>endobj +1879 0 obj<>endobj +1880 0 obj<>endobj +1881 0 obj<>endobj +1882 0 obj<>endobj +1883 0 obj<>endobj +1884 0 obj<>endobj +1885 0 obj<>endobj +1886 0 obj<>endobj +1887 0 obj<>endobj +1888 0 obj<>endobj +1889 0 obj<>endobj +1890 0 obj<>endobj +1891 0 obj<>endobj +1892 0 obj<>endobj +1893 0 obj<>endobj +1894 0 obj<>endobj +1895 0 obj<>endobj +1896 0 obj<>endobj +1897 0 obj<>endobj +1898 0 obj<>endobj +1899 0 obj<>endobj +1900 0 obj<>endobj +1901 0 obj<>endobj +1902 0 obj<>endobj +1903 0 obj<>endobj +1904 0 obj<>endobj +1905 0 obj<>endobj +1906 0 obj<>endobj +1907 0 obj<>endobj +1908 0 obj<>endobj +1909 0 obj<>endobj +1910 0 obj<>endobj +1911 0 obj<>endobj +1912 0 obj<>endobj +1913 0 obj<>endobj +1914 0 obj<>endobj +1915 0 obj<>endobj +1916 0 obj<>endobj +1917 0 obj<>endobj +1918 0 obj<>endobj +1919 0 obj<>endobj +1920 0 obj<>endobj +1921 0 obj<>endobj +1922 0 obj<>endobj +1923 0 obj<>endobj +1924 0 obj<>endobj +1925 0 obj<>endobj +1926 0 obj<>endobj +1927 0 obj<>endobj +1928 0 obj<>endobj +1929 0 obj<>endobj +1930 0 obj<>endobj +1931 0 obj<>endobj +1932 0 obj<>endobj +1933 0 obj<>endobj +1934 0 obj<>endobj +1935 0 obj<>endobj +1936 0 obj<>endobj +1937 0 obj<>endobj +1938 0 obj<>endobj +1939 0 obj<>endobj +1940 0 obj<>endobj +1941 0 obj<>endobj +1942 0 obj<>endobj +1943 0 obj<>endobj +1944 0 obj<>endobj +1945 0 obj<>endobj +1946 0 obj<>endobj +1947 0 obj<>endobj +1948 0 obj<>endobj +1949 0 obj<>endobj +1950 0 obj<>endobj +1951 0 obj<>endobj +1952 0 obj<>endobj +1953 0 obj<>endobj +1954 0 obj<>endobj +1955 0 obj<>endobj +1956 0 obj<>endobj +1957 0 obj<>endobj +1958 0 obj<>endobj +1959 0 obj<>endobj +1960 0 obj<>endobj +1961 0 obj<>endobj +1962 0 obj<>endobj +1963 0 obj<>endobj +1964 0 obj<>endobj +1965 0 obj<>endobj +1966 0 obj<>endobj +1967 0 obj<>endobj +1968 0 obj<>endobj +1969 0 obj<>endobj +1970 0 obj<>endobj +1971 0 obj<>endobj +1972 0 obj<>endobj +1973 0 obj<>endobj +1974 0 obj<>endobj +1975 0 obj<>endobj +1976 0 obj<>endobj +1977 0 obj<>endobj +1978 0 obj<>endobj +1979 0 obj<>endobj +1980 0 obj<>endobj +1981 0 obj<>endobj +1982 0 obj<>endobj +1983 0 obj<>endobj +1984 0 obj<>endobj +1985 0 obj<>endobj +1986 0 obj<>endobj +1987 0 obj<>endobj +1988 0 obj<>endobj +1989 0 obj<>endobj +1990 0 obj<>endobj +1991 0 obj<>endobj +1992 0 obj<>endobj +1993 0 obj<>endobj +1994 0 obj<>endobj +1995 0 obj<>endobj +1996 0 obj<>endobj +1997 0 obj<>endobj +1998 0 obj<>endobj +1999 0 obj<>endobj +2000 0 obj<>endobj +2001 0 obj<>endobj +2002 0 obj<>endobj +2003 0 obj<>endobj +2004 0 obj<>endobj +2005 0 obj<>endobj +2006 0 obj<>endobj +2007 0 obj<>endobj +2008 0 obj<>endobj +2009 0 obj<>endobj +2010 0 obj<>endobj +2011 0 obj<>endobj +2012 0 obj<>endobj +2013 0 obj<>endobj +2014 0 obj<>endobj +2015 0 obj<>endobj +2016 0 obj<>endobj +2017 0 obj<>endobj +2018 0 obj<>endobj +2019 0 obj<>endobj +2020 0 obj<>endobj +2021 0 obj<>endobj +2022 0 obj<>endobj +2023 0 obj<>endobj +2024 0 obj<>endobj +2025 0 obj<>endobj +2026 0 obj<>endobj +2027 0 obj<>endobj +2028 0 obj<>endobj +2029 0 obj<>endobj +2030 0 obj<>endobj +2031 0 obj<>endobj +2032 0 obj<>endobj +2033 0 obj<>endobj +2034 0 obj<>endobj +2035 0 obj<>endobj +2036 0 obj<>endobj +2037 0 obj<>endobj +2038 0 obj<>endobj +2039 0 obj<>endobj +2040 0 obj<>endobj +2041 0 obj<>endobj +2042 0 obj<>endobj +2043 0 obj<>endobj +2044 0 obj<>endobj +2045 0 obj<>endobj +2046 0 obj<>endobj +2047 0 obj<>endobj +2048 0 obj<>endobj +2049 0 obj<>endobj +2050 0 obj<>endobj +2051 0 obj<>endobj +2052 0 obj<>endobj +2053 0 obj<>endobj +2054 0 obj<>endobj +2055 0 obj<>endobj +2056 0 obj<>endobj +2057 0 obj<>endobj +2058 0 obj<>endobj +2059 0 obj<>endobj +2060 0 obj<>endobj +2061 0 obj<>endobj +2062 0 obj<>endobj +2063 0 obj<>endobj +2064 0 obj<>endobj +2065 0 obj<>endobj +2066 0 obj<>endobj +2067 0 obj<>endobj +2068 0 obj<>endobj +2069 0 obj<>endobj +2070 0 obj<>endobj +2071 0 obj<>endobj +2072 0 obj<>endobj +2073 0 obj<>endobj +2074 0 obj<>endobj +2075 0 obj<>endobj +2076 0 obj<>endobj +2077 0 obj<>endobj +2078 0 obj<>endobj +2079 0 obj<>endobj +2080 0 obj<>endobj +2081 0 obj<>endobj +2082 0 obj<>endobj +2083 0 obj<>endobj +2084 0 obj<>endobj +2085 0 obj<>endobj +2086 0 obj<>endobj +2087 0 obj<>endobj +2088 0 obj<>endobj +2089 0 obj<>endobj +2090 0 obj<>endobj +2091 0 obj<>endobj +2092 0 obj<>endobj +2093 0 obj<>endobj +2094 0 obj<>endobj +2095 0 obj<>endobj +2096 0 obj<>endobj +2097 0 obj<>endobj +2098 0 obj<>endobj +2099 0 obj<>endobj +2100 0 obj<>endobj +2101 0 obj<>endobj +2102 0 obj<>endobj +2103 0 obj<>endobj +2104 0 obj<>endobj +2105 0 obj<>endobj +2106 0 obj<>endobj +2107 0 obj<>endobj +2108 0 obj<>endobj +2109 0 obj<>endobj +2110 0 obj<>endobj +2111 0 obj<>endobj +2112 0 obj<>endobj +2113 0 obj<>endobj +2114 0 obj<>endobj +2115 0 obj<>endobj +2116 0 obj<>endobj +2117 0 obj<>endobj +2118 0 obj<>endobj +2119 0 obj<>endobj +2120 0 obj<>endobj +2121 0 obj<>endobj +2122 0 obj<>endobj +2123 0 obj<>endobj +2124 0 obj<>endobj +2125 0 obj<>endobj +2126 0 obj<>endobj +2127 0 obj<>endobj +2128 0 obj<>endobj +2129 0 obj<>endobj +2130 0 obj<>endobj +2131 0 obj<>endobj +2132 0 obj<>endobj +2133 0 obj<>endobj +2134 0 obj<>endobj +2135 0 obj<>endobj +2136 0 obj<>endobj +2137 0 obj<>endobj +2138 0 obj<>endobj +2139 0 obj<>endobj +2140 0 obj<>endobj +2141 0 obj<>endobj +2142 0 obj<>endobj +2143 0 obj<>endobj +2144 0 obj<>endobj +2145 0 obj<>endobj +2146 0 obj<>endobj +2147 0 obj<>endobj +2148 0 obj<>endobj +2149 0 obj<>endobj +2150 0 obj<>endobj +2151 0 obj<>>>>>endobj +2152 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‚0…á=§˜¥&¶vJEºTƒ;„z€F +j@L n¯ãÎíËÿ½½‰ÖG R€i ‘\¦Š§`êÎEÕЌoë~h½í{çäö1Ùniî_¬‘0Æ)O€aÌ%i¬*r†ù†R†‚™pEAfÃü÷^O—1üBÿ= ÏÙßÚë¨õ–I!Ä +v]%Jœ¹šhf¢Sô²ñìendstream +endobj +2153 0 obj +6279 +endobj +2154 0 obj<>>>endobj +2155 0 obj<>stream +xÚ+ä2T0BCc3JÎår +ár á +äHÉHendstream +endobj +2156 0 obj +31 +endobj +2157 0 obj<>>>/Annots 19 0 R>>endobj +2158 0 obj<>stream +xڅU]Ú:}çWŒú´+ݤIîÛ¥l·Tí6·a«>ðbÒubj; úë;c‡¥ìVHÎ{Ι9žüì…à/„aýòº7™÷Þ¾CÀ¼„8Œý!$Ã̋›Tñ’åüvþ1„!!<ñúqäG„š¯+ Z–fLJ’+Åêš+ 5kZ&èÕ¶*øPÕ¬ jJ©jf*Ùþ³æðNÖ5.fß)y^ØwÉRU5†¶e{mx ‹›7ïÓìÍâ¾aJ:$ôCà;Òc‡DOèG~L't¿l¹ÚV|G¸»y/ð, =Bz|½‡8 ýDøL †xDÜJ@æŠv(I€x:‘9 f°‘ʰ¥ ÉqÁö\Y¥$o oÉ4/@n¸b¢-EíÃÌÀšiXrÞ@Á·\ ¦€ålUžSV+¸¹czÿ¢ \@° +('ò݂Ô\QÔ0 +[;í´wõ<45U²hs£Ÿs ÜÀH*L- Ǻhڂ©âT-E{4–¶¼)$Z ÑÐjì°ÏJ|a2O×àovτ«'.ør´¾ðDÕpôœáЬ­ýî€(qjìá˜H[Î×pGÛ¡H#s)Èx³4%ß1‡Å&â= ò˜‡­lµÁ¹tü¶¼ÅŒ0Gô'¤qÍÚh)ãd~Lð)R‚ Šï?s­ÙŠÃDÈü‰ÂÙç †ÿ±gÿ·Ùdø©.n˜ÿä3>r3­Ï ±éh#ìZ^$×톬ŠîÚUf Šc+qQ¶MNMa¢2û®ô¬(4`QvR=9‰Hn©äN“f"“Jm²\U›®p\]d›rmÕә:î !m\“o:vH‹ óŠ3XÛÜÝ¥«½$­Øï\´îBæ­6²®~a¦m70d ÷p¿Fڎ’Ê[¥xcľ£%Ë?Q,n/´QXUM½*+¼ú_g):„[û–;“ÔÈÆ;«WWOtIÆê n.TE<­±>¤¶¼wiöåá"ëaŸÍÑÉ-\VÌHՖ=ûÅÙ8•y[£êgÓñ|ÎyÑÐ͹¿} Kµb­4r“ö’”R¹³×[cé_œWý§NŸ¦ΫeÚÿ/Œ«c¼†Aÿuì)^Ã8Dá¯`OñBôUòø €èdìOèÉüʼÆïo?¤j†àÁå—í¼ŽÓ·ïóÃ÷xˆŸ©€NYDÉ\ÇF‡`4B±žËrö9G²³»Â®ÿ÷~¨×b endstream +endobj +2159 0 obj +942 +endobj +2160 0 obj<>>>/Annots 29 0 R>>endobj +2161 0 obj<>stream +xÚ­—Koã8 Çïý<¶ÀƱüÎÎ)}b°¢Ûfw/½(Ž’hëרrß~IÉq”Lë‹ E9?RäŸ"­üµcà}ú:ƒ>ýñ ¯÷œŒÛ¦7k,Ë8m«f¼àŠ•hTE×§j†$Áû˜Ð¥]Èã(ëw£³_FšCö ~¶¸|¿¤L»{Ç+ýÑ^ºÀ)ÎÔ²UU«:ïì“$³ +F ¨ºÛÌC¤˜àênvõðé·ažÑEù Üå4•H%>{ï dòYìîk‰øïSÝ&Ø!ÓÛ[¸˜Þ?ê¨÷cež£“¶"¹Ó…lLs PâMiW¯xãP¨AÛ`Cí‘ÀJ`ç.àéÔy:U¢ýB¦\ íe™ä¿ ’J¼?<¢¯ê#|ë§óy-^$ÔæÄÒ¥ˆÛ6Ûq¡ÖuÙ®ÖXD36Ì¡îú=ڎD Áìý<ßݐ¾ÛÄþ‡ÌÊù;Ôߨ©˜ë —»ÞF¶»î~ˆ·ÝIG_z¼ðx#w=Æ~°d7̤³‹czÓFÌXš…ýè¾.W5Ïs:?ú90bÁF±§OGÏü„m&âgCߎžü3ü¾áendstream +endobj +2162 0 obj +1155 +endobj +2163 0 obj<>>>>>endobj +2164 0 obj<>stream +xڍÁnà Dï|ÅÛÔØØÇ´jnQ҆|бKƒ +¶òûÅN¤Æª"U{aµófF|Ž, ‡ÌQ{òªÈ˺—PmºˆŠC5OÛáË|šÖãŽ&>«S’ p>ÉIsÉĤ|;ìöØûv¸è`°jzël‚|ˆØh7êó.ï`^°|‚Wú—°Þ¡mcÐú€Ô³y¼™³e :·¬üÛâÍÿkè˜Äw±c´®{^Ý|¤d<=ëk:–ñ»à» û~Y‚ò²N•yöè‡Ë*c5æs1íïŠ|8ó}þendstream +endobj +2165 0 obj +226 +endobj +2166 0 obj<>>>>>endobj +2167 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS04±Ô3T072PIÑPp VÎO+)O,JU(ÊO/JÌÍM-*VðMÌ+MÌÑ Éâ҅hхê1‰™è)€ùþ%©E +A©i©E©yɩŠi×®@.`$™endstream +endobj +2168 0 obj +125 +endobj +2169 0 obj<>>>>>endobj +2170 0 obj<>stream +xڝUÁrÓ0½ç+öØÎ¤¦IKҁ4LRàЋb¯cQY2’œ¿ç­ì¤Áía:“iâÝ÷Þ¾}’&t‰¿ ͧt5£¼½]^}¸¥é%­J|β+šÍohUœMè‚^ۨ톖û¹¦»-û­æÝùê'Ú®i2‘¶‹®ïâêzšM¥uUé@y¥šÈžﶺà@ʒëûɕT¹Ŋ靫kgéþ˧ÏøvÎ?†¬c»¥É\Ø.A4Í®;~jYx·6\ÿ- ÅÓy6“âÎӞ•ԕÌú’3ÑPš—PΨR£6-IiF÷ÖèG¦Ï:÷.¸2>L_Ïè»¶…Û…ô?è>«œî–ãn6°N€!jrÕ9¢²…òž}©r–¾ÐM¯­pâ§R~k›Æù^cª½s›äbp¦ÚYøÞzÏ6š=©­ÒFaœ±” ˜ß²dè²ÅÁîoO>t°4Ï ¿v!â)o•xփMgÇE~ÞÜk&£-UÓÃYäߑœ5û‡swìeîuŸ‰¸WM¥óðp>Nßw:VC]͔;õ[wvì)GÚ֐­ +èwG%ŠÊÖòÊnXBxäàR›äu­"¼ýèvŒ¸Ž“«ã±Ê‡¼[å5ì$1)íÙ5ìՉ „^àS¡Ë’e3CŸÐ +±Òoe䬯5'‹¦Âk( rI…‚˜ðåy†JáX‚Âs͈‡ÒykbF«JEøW¯±¨Îà¤ÇèZG.†C#jubËÛá<èD‹øÓYp°E"'90ûütólÇ]XÌ“QۜÆ[ ”Óš‡¹{w¿XÊP¸^ôF¤‘EµU‘ÿãœgtg%HéF®©ÖYÐç9zAj?{8MÝ_̖¹â€ä /¦ÄM£vEk”—dJÉÓ%ð>'¤†g$Èq—™ç'e,ô„g±9M~·~£c4é2²°´Ä3Äd©-¸“é‡[}@¾v}tŽ7Šñx×M‹ñ$Œ;pÜ¥N5Ñ¹J÷®q³jàš-—âI:kzHlñR‰œWÖ·Ùw3@9^Bñð +¹yz+ÌçÙ?½å®o.³[4 ôµ|¿}ý üjºendstream +endobj +2171 0 obj +836 +endobj +2172 0 obj<>>>>>endobj +2173 0 obj<>stream +xÚ}WMoÛ8¼çW<ô”¶»““¦Ý¦H°ÞÚÅ^z¡)Êf-‰*IÅëþúGв-ÄE$²È÷13oHÿº˜Ð~&ô~Æ¿²º¸_^¼ûü&7´,ðfv;¡e~¹Ü(Z*¹©MiÖû·ËŸXtM“I\4žÞd3^öñû|AÚÑJ8•SۘšDMªRv­ë5=Ö^ÙZyr^Ô¹°9IQ–Xé¾9·ºö¼|n7Ҕ=Îç´ˆ«TÍɑrò>›rJU­¬ˆ±ÚSn~«Ú‘)¨áÊ"{Þÿï”}ÁŸJÔm!¤o­².,@Á®mc} ó¬¥5ΞþÕunvnrzuu•uŸMgÙ5ÆæªÐµBÌCMׯÆB¸1t²SeÉQ؄—ôÓ¬ÜIѦñÚ §RoU*×bPŒÓ¿Õˆ¬r¦lyé(lw†3úMFO¼(Ãq¤%ÕäFW †VŠZ~U&dO(Ö0V'¼x3HÝÕèhÓÖ¹U¹ã}~cZ‡ •.Øgô½=Ä´Ç5lÌN!W,F”¨¼#¥Tnˆ¾4µ·¦DŸ-BP)}«ZÚ}Ÿ+±e`µ!U+7T«Ðn#V¥Š() xI¢ 1ԙ)s¦ü¾F=$TнÄÛMÃÝ3z_ö²ã¥úÏÓҊÚqc½°éÇå›/Ëåü͏·´Ûh”ˆ8¼ DéàN­:ÝâqXÒ1;-7Øö W&¼¡­v ÙV@ªÃIn”ܲD}ëH×ÐIÞpåâ ¼40ØAæ ZÅ¥j›v€JY +甋T)·Žqë¸—•EyÊ! ¾M¼è<̏4US*¯Xï&ل’rQ{çUÅ4ùö{€&Gô ×ÊùXCÐ3Ie½.X'jÐÇ©„†nÈ*¡Pèç&ª‘:ýð§Å‘Þh§1d$ñ"t$¦k*Zö™AVf3 5æÎ³è§Ó¿ŸF\¾ófûI@0&,rå9\.à\mUiÏ®vb?xÓù® }ÖE¿i§ù.3ú< s”k2º¤ ¶Ö¿ZEu[­”ڒ6zÇéÂÀrÈC¯k6|ÃRã%²-……u:¬îÚº6¸P/Æ®vª`ñ¢’3uÎH-¸çö–^€›-û'EnjU3fÒ4:‰ Õ~ž’Qã>{ЗJúÄvï˜ÛÚìj.i€¿|-zâÀþˆ\X±;4R6„B[燠ô’LÓ­ë°8Ä9ßëg]rµg{íÞG×aA¸h¢iÊ4S(+mðŒ=yØ¡;•)2­'Ø£¤ +>³²xˆþqh™qj,è†P SìòؗwÎSubKRZ˜*­Ì!YšC¹. +CæèÝ@!Öë`&Ž@äs?£¿ùŒsççÐùš+ê„tf@™  +·u¶ÃTëÉ Ÿ¢©+Nїùø¯§wÓô8øœþå̞¢ðœ½†i—˜ šçÒêÆÇ‹RŸ†¾ ǝ?†Opž±5¢>hßÃy–ªÐ%˜â™¡cõy‚†•ö•hR„xK9èÁÆ­g5|/äb8/â´ §‹£B¡h—‡XpF°Ä8ó=jÌ öAaÝÀuҋ2υi‹;Kï*å?á7\¿`ìÓ¸ë@êZ”‘Áï‹{ +îû‹n;c·8óE¼¸Íç£Æ_•Ð:QwM³0Hí¼žpy³‡€BUÐ*ø|š?0Ÿý-£»<׬d­}ñÁݏN¾AâT¬–@û@·ë­™ ^<ß§€ˆ Ë6?rq´Ü„£bq÷|G|=‡ñ©ŽøÛŽ×ÉõÜf·"ÒAá˜ø¸–uº¶¢ªX—Ïø JÞ=Ž›Æ7Ó+Þ3ãÏ®¯n3þjôêWŸOˋ.þ°\žendstream +endobj +2174 0 obj +1452 +endobj +2175 0 obj<>>>>>endobj +2176 0 obj<>stream +xڅUێÛ6}÷WLóÒ-`k}ƒ½ûl.(Š6q±ú̕F+v)RåP«êï;CJŠ­4ü ‹—9gΙý³ØÀš8naw€¼^<œ·÷°ÙÀ¹äÃÝÎÅ̓Ê_ÐÊ#(CZ‚ƒúZ[„PñÖ«ÒF=äõW#eðÙåCÛª¼‚§ +4£R: +Œ¦®üåü÷b «Í.Û +îtj›Æù@KP|[ٴ嫵 +ÚYW!† dp®äÝ×QäÖ(Ïoh&Ì> 1ðîËé1˜+ NŸ?ÁcèMKðΦzX¯¡ñÚrÚ0Î*i1!QØ,cjø¯ªæ#Áo?ÞÃæ˜”]í¶Ù^`NC°÷^¿¢§tî««í1;\ž+Ò9N?1ϝ¥$8¶µc—Jm‚£s]ê\ª‘y–®j››¶`})rwç& €’ͯØ aub •/àwEèÃMyô"ÿ‡0“„÷«FÛ%l÷éy©h4t9ìŸ*'²á2ø«Ò&á$CáÀºÏhÑ«Àù7A×ʀkCӆHZÜ/tY¢G;±c• +4´œ!óÙ^b6Þ½ê¹Xˆµ‹w´}ŽX³ä!¢U®ƒÞµs±t^ó +¿yppF¢r•wž«ƒ¯~‹[ó6§+Î|¿Z>aèœa.?*”„˜EÄÇA0.gm¨§Àp±™ÛइxÙô@¯ÐéPãó~8:Ý· >u×¼_R¯‰œ¡´¼Tä€6:yUˆ‘#ÏÎÍ4ò¢‹\_,°Ô8gXqJ®2܌—¾pŒÄ¹Z¾ˆP«^Vy +¡Á<Ȩ‰ŒñŸz°ªFˆSȳµaê&&ž¿‘ý·‰Ç›lÀÜ’±âD*† sŒ¹ÑÜZ:ç 6XqíÛͺJó\3rg„#4’>¾ì£[æ7zí‘LIˆ »l¦Äåì»ò£nMÐÒê)âQ5T¶LÃ1dSõ$1Ú=2¹šhK ÷cSð8ûs`9M/±¹xˆ–fª 4vU˜«© +¢š;d:º1¤¿œ.¦4Cÿ&A)°«dQê‰ãûԏ‰¯Ü¢¢|É_‘– i­AŠJÂP\—¡fÐ#â3yü”Œ¾ŒÞìï³ ìvÇìN§üèÊЉó'ªk¹ÿ‡²­Šµ½J—VÇíú;_ŠýÝ:»‡¸{”÷纋ÿâpTendstream +endobj +2177 0 obj +923 +endobj +2178 0 obj<>>>>>endobj +2179 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS04±Ô3T072PIÑPp VÎO+)O,JU(ÊO/JÌÍM-*VðMÌ+MÌÑ Éâ҅hх걉™šé™+€ùE™y%©E +.E™e@ Y×®@.>é$hendstream +endobj +2180 0 obj +123 +endobj +2181 0 obj<>>>>>endobj +2182 0 obj<>stream +xÚuTÛnÛ0 }ÏWÙK +$jìd¹ìtC;ŠlsÞ + ŠÄ4jeɕìùû‘¾ô’¶1Û2Åsxx¨û^cº˜§0™Ê{ß³ÞéÅÒ1d[˜$sñfódzÂ²õê/œ­.O²[ +B’p訉M¦©H9<ۙj'‹hŒ*˜ F(3…5J–Æ;XdžcˆpéhÃV*„ëAŸ`ú×'¢ZB2g¨1¡¤bڀ<ñ_fd8¼äEÁé\Ì^Û&Šà Q û·Ê[‹ª¦ä·`:&¢F ¥‡X…e]Gभ?GÞÒUÇ9™4ZD¿-÷2 È{´–ïú¸O>‰‡°5–ÓCjÐÁ<Ô ÒiØHu‡NGт¤³F‹µ³æë¼cÉi™Êð™ä$RW;5§-_Cå4pØÏ«u'#üD‡Š[UâFË +]DqTZÝæ¥ãŠd _’ªˆï;ØørÇèT–¼ÆeùÝ(ú*Pç‹Æ¯Jl}ÒB½ Q +ÓÚì ‰mœ²•nbsŒ[s ¾¨ªˆ§ü'vß^g;”¬ u?uû–õẌҴ¡ô¡Ëþ*óNç !ŽVnýÆhø +¿â._ +>?´=ï¡ÏÈNæ(ŠÈ¯¥)-ö‡]Æ¢KxóçªüŸ/Z?µ×'Ÿg– ©ù¬ã›úŒ,<Fù¼ j¡MLÎÄwwÆÝðŒ¼Õ”VÁ䵂JÁÈw-ïî‚kl8¿ÊÎÿ¼ËûLkÃȧm•µ™PC“›Ëlx"î+ÈëÉgš‰q&J¾ 4x´±Ä¼ÞϬoO§f®|\_{F-ž;‹¦Õo›ÓÅX,)ˆ>/ùý<ëýîýúi±endstream +endobj +2183 0 obj +670 +endobj +2184 0 obj<>>>>>endobj +2185 0 obj<>stream +xÚ­VQo9~çWÌmû@$ز„&¡¹œDI{‡šDiCt÷©2^/ëÖØ[ÛÄ¿¯Ç^–°K°Þ™ùf¾™ÏÞ_­zîÀá~è¢õqÚz÷yɦ™»stâþ¤ísfµ\ÎÁæ Æ·×70ºžÀŸi¢WÀ%ü}u £Ò*ªdv0ýႠIBnÿƒ  ©L€ P¨¢D®ðy©‰åJ‚UJ@iX +³,ˆ\A¡Õ\“…‰a”¦>…L ¡–˜à’ç+Uê€L6ÈÉaÜGì5‹]® =hÎèOJoW%6UaÌFv†j^Ø©CrÔuûƒØS5ÿóiüåûÅäã]Û(ú“ÙNõƒN˜T/>ASžeÆBô¶”dÁ"øã ¢É·ÉÑ)f$æP½\à›³¨+BPx‹×QÖ Ãqg4W])ë8Fë@îŠ2,ˆf K)ñ6æ7Ãgüî ±´]·4¢3g6WÆÎV$Mõ+×îâ¿BáåeU÷“øh·jZ¦“[[Œ•”N0ÁÜëé礋ƒrèòZséuÃô=§ÌìM€˜î›M§ˆ{žºÁ7jÁ`F §n­ +iª~´IQNýì:™äĂdNZnü½½ƒ‰ë<kôa牤¢L|F³G„òÊÎkk-^"¨ ûiܝRҐ…ÓþZ>!RûOdî~Åù_Û(íÇ¥öf ºÇ}]Ч¼?Ü¢œøjþ§˜šîšf»T +@^k¶€~×n¤wËÃÌ<ú.n–9§y‡{"ަ¨G¸Ú¾P"©Gz æ5ŽãÆ +ÎÀ5ãéé“¦Þ Î`«œ»vRꇔ|®[I¶£4l°’çØYnÅ®Q¯W·w§Û\†^×¢i4aƒ·áÞX-䯟hQÍkèÓà:M1f#«B³á·KzDÆwú¼ًð€ŒgW€­í‹ç1D#ênþ«t +犖 &mTwø(Ì¢jfK-ឈ’…cº”ü—û?9Y.fŽ”õ‘YC M=àØí¢KâÜ$0­•~|k©õxY +Ë ñô&c˜;‹ÓÒ«ù”äÌþ-夺NÃ8q:‡!¯ ÿ•Ù% ×áácÁ´K"K"лœºÇýú$=\ìÞÇï¡÷²'¦OÓÖ×ÖofáÊQendstream +endobj +2186 0 obj +878 +endobj +2187 0 obj<>>>>>endobj +2188 0 obj<>stream +xÚµUïoÓ0ýÞ¿â4$ÔNmš”ª[ ! åE“—8«QjÿØTñÏsggiš¶›"“¦Ê>¿{w÷žý«“@Œ àÙÒeçõ¬3¼ˆa +³œV&Çø+ë>2-\ÆáEêJ3¤ÑâUoö³Ã`”D +Š¢¨µ"¤…êû©®DvRí'qtÜڗny™‹‚›vLª¤±.˜†Cð=‰ãí¨íÜ>!¼âúYc¦ :<ïH¶ä} ðáÅ(TڭӇåªÝvØÎ+lAq>}ûðaÞ; !cHŠ`##ÏêÃY*‡’#ä50 TbÆj¿bàVØÜ% +(ݍJæÝyo3 2Y)ça+LH•ÃÏ»- V±5À¼Lfw}ˆqM®T˜šk`Z³Õ6èÀ\ià,]BvÁ¬gyː˜UPR=õè&јRžþmývÁAs봄V8‚Zá¤ø…¿ß{2㳒$£1…dLÄa8œ1™ò¢ q¼WW­Â(f¶ƒe8Œçv°„ÜÉÔ +%!õQÄé9ž­i=ߐ˜WÏ8Ðú#îu ±Ì:ó°£B\e©F‰-+¡X6-²å6Oe3æ>Óìèò:ɺ±•{LÉS‘ nü¨3n¬Ì7ÅMŠp{ÚË8Êy)$÷†ëT7®ŽqAJ8C:9lRhX¤QΚM-@B"ç\#z'¦ÏµZâàKÍo„¦>Rê€B¾ïˆÙu&eEmqgºu¸oQMÚq"÷%cSÐåŒKSnLîŠbUI¾ÀÐ,ZHñn$Í=“ÀµVz¿eßrkI”ýô†‰‚]á•ã{µñÏ +¼ù#݌¸ç(ó™áŠ×ÚºæÇ[T +ý`5£²bԇ4ÐéeâÓ@í1þ–lÝŒ5,°ÏQ³Ù¹#š¯19gû5F0¿siáp#b?p V]ë~>õË÷Yÿ =M£¡ŒUšS¿°Ã;ÆUÑÛq;¸ŒjZJm4ë÷ۋ®ò#º^ú•sÃTZóð/⼋ +er5ïõI«ÂÞÙ±™+l“x˜qsS•´´‡[¿T „ý·«’ãÁªDØü†‡øÁy£…´0lÍõw?®Ú•` L¦£P-œ}ûü¾ªÜÞ2M–Rך-—䪏L:VÐéA2žâ¡ÁÑ(Þ󀎏ƘÍï&þÚx3ë|éüɒ +åendstream +endobj +2189 0 obj +914 +endobj +2190 0 obj<>>>>>endobj +2191 0 obj<>stream +xÚåWMoÛF½ëW ”‹,H”( ²¥-Ú¤ +8‰ƒ(‡Œ97].YîRªùïÙÙ%e’¦>.=E6 z9óöÍ×ûߎcóåÃõŒ¾ƒ¸óDz3ºÃ–k:™Ýš§°D,ƒÃ§/YŒƒâ—Q2.5fd¦Ð{菮–ß:cúcïÖÁÔ?}.•f2À…ƒ¹O& Ñ+s ۢ͊àJSdl˸`+%¿koBW/X׀IIòOž•bÀ×<¨’ƒ\q¹±è.žqOB}ú±}ì=^Õ£íÁ:—¼.ÝÊNN¦Þ”ؼâ2yˆð† FôË~-(O|ÏæÊó¼ÆIµ¼T\"«JTêýóñžžgïvvð Ԃïº'.ÄÕ¯t¯;€†MYÚv‡ˆ¶ +êñêt5Šò|÷s%”Ψ„\Ù*¦mîÁßE3¤tÄ`ËDŽÔJ |šà&¾N`ƒº:–Õ:¤pæªÞBºžŒcÄs…ÙÐ\À%†uiñàX_FU¡À Î¶z¯13]º¡km…”{2*ºž»dþ”.¡Pç.T+¦ÁŽë¨T:%²¾!Û߅ lW!Üò$/üñ?§•›t*‘IA#Üq3VR RBÚbµƒ™ÆÖ»ÄˆÑ&QjEÙ2oê•ÌÐ Øï¸À6 haPóQ§tCy`ZEµ#½$βÔòFÍJe' Ò¤Ø6œBö FÆöÇʼnT¦ _ÃÄîÏbmVOÖÆæå©æZààÌöt+«²¨GP!¨4UÏž8ª:Á¾;;˰%ª¬/9Ö¥Wiь<йi(¡dAt(9íTÓ>VÜÊö¢^²kÕ®_fô1¤'cì&­Ñ\E½ýúðňIfa¡|žV”Ó6ÝS܎±†ÛÓ´GæA.eÃr;tFéÚn%ÕLÚËidT¡5'g»ØŽÇ3lÞ_™d!ËÇìÝõߒÛúÿ'ücඨ†oêåÃl>uŒ\S~IÖzGmý%›ŒÅ1Õû“9ä=ô§sã4¼™ŒÉǟÐáõíÌ£!Nm­?—Ïh†¢Pendstream +endobj +2192 0 obj +965 +endobj +2193 0 obj<>>>>>endobj +2194 0 obj<>stream +xÚíVmkÛ0þž_qt0ܑ8±ò²®…®4£ÐmI¿ŠbˍŠ#u’œýúÝù%±]§Ð}Ú` G¾{îE÷<Òϖ=üz0ôálÁºõyÞêNz0†yD+ƒáÈõa:Oj)B€ ’g3ÕBډˆùÂYïBnlçR²5oÃI„‹ôx‚ÏVØNçO­t¼ž;" hþìq’õƒz¶BIÓÞ/æ ‹ÓsëNúày”`3ìø‚¯„E<°bÃã$†°+¹30ZÒ°bž5ß•0BÚýžÅ¨fGöC²ÎßBÀ$°Ø(XrŒla¹ƒJ4¦£5[c~„I9g@½È¡ž_…a†³p§Õ@D‰ èÝDZؿŽßÏ2~'d'!‡OÖ¥wu™ïï¹i]×­­`y¥M*mÎym[ 0÷`áCÍêx€$W¯[¼¢Ï|»¿»{+d­w'Y‡ü¬CÍj¥gMnÕfÃâä¥QePßW'´TÀÿdþÞdŽÉ ú¢g¬&²ŠLcȂTã 7m`2lâr)Ích© DJã?fsÀý”2Bß°`…ŠÇ`՛õBs›h™çηԥ%ÊVwȅ +†©&mÕ^GI*ɱØÎ³ì€0Ԃ¬®·ZØ\#¡Ík*|Qþ%Ã6„ +$ +.3&AÏ´\ª‰b¾V“i*ÊïÕR²bÍ)_ì‘æ&‰-‰Vûk½¦f6DhÎÞE=B ¦9Ö"yIÃó(ÿž$×j^8Õ)TœŽ…Æð%?o´VúØ¡x!Cvi®ï§3¸šÞâYˆõ‘sq¤™ý°âéÉ ±zhΌ’–¤¯Ò#vIÜI}x¾æÃTÝÕ҈P­wÌØ4Õ¦¡"7ÌDj?KYÛàå6¹¼¦LÈ áv:-J›H}°©à-^d¸ °R¼ðÐ}{š-‘«6 {ˆFŠB!lžø…—#d‘a¼P)“˖q=)Ú ¼X.-£#Â¥[ן ;å‰zƒÁhœß Óa™©Èn‰vÓìö´æÚÀW&“wÇëÑ©3D¾¿~aëûˆ›Zyg´p3oýhýÈßI[endstream +endobj +2195 0 obj +867 +endobj +2196 0 obj<>>>/Annots 33 0 R>>endobj +2197 0 obj<>stream +xڕVmoÛ6þî_qÈ>Ô bEò[ânÐm Û²Ùù4-Q6ITIª®7ì¿ïŽ¥ø%h + +(Þï>÷œ¾ô"ñÁhJIÑ{»è]|a‹ŒÞL/¯‚!,Ò~§‹Ï½Ã(˜ÒQø,—"ýyoãˆiqßÚÂõ5„ñi³…ÁíTµÑq?©+ý^)©æF‰rå^Ü1mì˸ŸÒϞwñaј²`šƒáŒâÜ3­7R¥X™Â›Ú¬yiDŒ¥sC‘%wI.ïîç ëª’Ê ÛŽ È mAñ/5׿D™äuŠ™¡Ç²Z7F•jÀÐ,ÖRž±:7PðdÍJ¡ Ȥò5 +n E¡Ö\•¬à6íª)„#iÏÚär%Jki­Xg—)YX“D–Zæ¼EŒé¤…ô‚D3f[qm‹«ª¼©USuSañuÎÜ(V­q3‡:ó¶4\e,AǸróp«OâÓs{¬…ðÍýí^•’_EŠöY]&ö*GscÓPržòô Ã֔\žË u4ÿƊ*ç ×rC4ÕÂ.ϵt^Q¹ì h[›¶_; ëÄy0»órÂÄá‚ý‚Áú×=&u0TŸ‚³=ý-¶Ÿü‘Ÿ’e¼cŠ”+*s ÙÿH¸5·‰þ=|ôCa4t)z‰÷áö‡\œÁewÝO‹‡³‹Ã¡A²›¡=4.¯á¤‹ÜÙÙñ“ÐqŸbã•üÃeæV$cÚ ªÇ§4~¸»;2  ÑŒä,Ž@c«²)—|“‹òI N”ìíz |®, !Úç¼ô¢p ¯â8|up2ì4›ó8–îÝ誩'‰îL?Ú¶¢|<p~K«­¿ qâ%Ïâ~ˆüßý08"{\ôÓÞ …›öÖy. +“*ߞ#kp"¡J63 +'a§ +]ål늳¼ó׀zʛ5•ügÖøé ™à9~>>>>>endobj +2200 0 obj<>stream +xÚ¥VmoÚ0þί8±£UI›”AÛ4mk§JÝÆý†T¹Žž;³hÿýîâ-¨ê„Ä‹}/Ï=÷܅¿­Îð ‚ó>ð¬õeÚ:½êAÂ4Á›þŦq§°ÂGÓ?x7„pàïºçQУÛñøL„YJ.¬7ÚèFƒ OF_oÇŠ§E,,$…âNjeÁi`-0CƔ̋”9cm݄™;©œ0ðMØòaÖicÞöì™bD·`˜€XcB¹Ãó ¢Ü+éh ¯ÅF.…±ˆWPÙG}_Ð%ã  ª(4Ud $[Æ`K&Sv‰`®0xœ½”±ˆáþXä¤ªVª9p­’Tr‡G‰6++Ào;8m.¸L${rfÌàL½uy*@./`¡–"Õ¹°Áìhݜ^ÍûÐ×rí)‡+bé™îlÛPyÞä¬2é|àEnOó<ŸšÞX#™%IØF$¾ŒPW÷÷}oH>¨±nÔóÀÞTb€ý)º¥})ŸéBÚFBüÉR«kI•ÜïÅOo‡ öø]8G=deaD#uŽ~ú>ïátú ¡ÀhfÖ©;¶SSF8#Ų’ÛZ†””˰ÚZÉxÈSf_Îó„5ôÓÁÎ JÖ:à fà˜òSÚюM}a»¶¶Çy,²h ëàԎtú q›º,’„]‘vM +è¤1ä55ۃH÷Fd÷ ®4Üޓ¡˜rœbt¥ÕãÇng8ÛUÜÏÞ±] ÝÖژ–Áq%(X²´ð…\{8´è`ÍnëppüІÍű¡ýÚQcŽ•‘Î åþ´”8KSŒÔäg äA‰pý.ª‹°7 Bè÷Ãà‚b”d˜èÄ­èi>6znX–ÑÓúSKɻ띺ƒèì¹? ½Aƒ•Wá;:¸œ¶~·þ ¤Èendstream +endobj +2201 0 obj +858 +endobj +2202 0 obj<>>>>>endobj +2203 0 obj<>stream +xÚ¥XmoÛ6þî_qÀ¾$E¬H²dKí6 u“`[Òe±û¡@ƒ–([…$ªzIêýúݑz±[²1´0$ê¹ãÝÃçÈc~ ÐñŸ£1ý÷âÁ§ùàúÖÀy€_ÆÎæþÅ|Í!ãE™%ð¢’C˜ƒT„IÁ3(¾äEVzˆààóÜËÂe˜¬ @;O ()r||ü Aq|ùzáîøåüû@‡¡1ÒLšÚeäC" +XR Ì×p}ë‚a©‡¦«Y½Í8§YÉÓ-ÍðGˆ,fE(eÔ&64eb'‡(Qà"áPæä‚5á\Ç¢HF¨|蕏‹4õ§‘ÈùóÅóå®û ÊÄ£i‰›ÃòóXdtÅ +X³â ÎÇý÷µg—¬q!†¦¥Rú%L¼¨ô9üê•i~Sjëß+†LCFÓ´½„-(öEïðùÃ)U*øô|ùa—⡌ȭ…ÐÐ;«—ü¹7Ì[·ËM:`aBÂIÊx‰ºAAx,eË0 +‹ °¢@Քϯ ͔²DJ$âK|rD¡W À‚0 å (¢”­öe“‡ÿòÚÉÏÔLÒJ¦ëMâºB̲ń:Qª‰i>zq¢¸Œå{Ì~ÊgrÝXìM[Ùkð×[ ++%leH…“"ã>ŽUµtû’j +¬-€†î±RË´f3äùÛ5©@'¬ÊVÀÈQ»0JºU}+&½­)ë +oHÀµÉ÷¢BK3ñúÿ‡ƒÚ2Q$^©b±¸0ú¼*%»2qFšƒ©;*õ‰!„¡Û¨|]Jz“Ê ¬9S }–¦õ¾q3蚎eóót–£M`dŽÐaèôë¢9F6;6lWUh‡¦é›ÖH³k×®… ´h¹=×DÙ:… ''b=¯ÌXÁ;n,R*2™.É.›N“®¿A^¦©Èp—®ÝÀ–›tÚ¨N&@¢O%@¹î%Àt µºžˆD¶ðùKèñ󒗖ÐZÏ×tl +þÄ|úÄ|+×ýùÚæV¾yÊÞdKõãå‹C)£cG)<`eT@ëã=í ‹él1}øö×Õ^ѶŸ®jØÝÓÇoG`OwŸ>óö¥‡j¹a©´lÃî¦Z¢eŽ]àŠjåZRÝ¢PWT'6 ‘D›ó¤U(¸ï““0)E‰û(uµ³ +ôÉ9j“èSÕ¦\÷ªrÑðtXð¸Œä©ï­èî‡*àê[EÐö!‰ú$ jOp7VûÙMã³ÞœðÀXn¶O˜nöŒ‰LN3¢šédO¡e]`Å^åZ²×¢°76T½aã’.ü2øÏóô“p̚šHtÂ÷e¯“Ãë[Gå¿lûŒCJ¡OTQåº_E–©•T`ì ¨ëӎ·f¼ëÍ\vtß`/,ŒØ’nÉN_ÒC—9jŠîÙHô©²Q®ûeƒ“Ël¿{ÑbɱCÝcÆÓüÀ Oü·,*ΎSö§XÂ)ËD÷,Y•(1Ü­â»^Ùèîïß"/f²AQiYt:™4ò³H.|J° ® «èTŽ%›-ø-›cK¥Q:دžÑÜ×&xY ñ+÷£+º:Ý^ñ×ç+ì’zš$Û9£G’àËO9î­>$ǪX¡B<áW{Æ G5¢×EEæÑYFWÖæÆ¤îXԙ£Ó¾nÑ=ã8“àS{E÷ØaæT¹–«01e:0ýú8ƒ™ŠWºŽ>>>>>endobj +2206 0 obj<>stream +xÚ¥˜ÝoÛ6ÀßóW²—tHTÉú°µn{X›ä¥í¼ÙÃ0 €AK´ÅU"5‘Jêýõ;’’í8¶Åt`;ÖÝñîÇû ýÏE>þ0A˜@V]ü2¿x{‡ß0_Aì{cH&1Ìó«’ðõâ‘6’ þfþ÷Eø^7 ¾àÓ¬ |¯¿{uړÈA÷|^PÐZ²¦ÐJšÃJ4 ð[Q+´(Aª†ñµÔ&|¸ BÔE½‡«[¾.™,®á®¡<Ãwª2ïፖ»_øžl_~¿‡h¢}Nb\׺޼ +³#ÂAœza'mÜ='<ŠB/îM§‘7ٓ>‚-ÙÐû°%}¤å¯2®Ž@3¦BªYÖ°ZíÈ׸_J@8€ J¼¨C¤hô<#m?'Ü!°¦ ‚ôaˆrJExKÊE&jF¥;~‚÷F.‘ NÁš*7ÁÆ:×à´kðÖôpðAdS¸9-¼­–´qýCðØndM3¶b+`­xÁûÏwÞH»oM§¦gÔDeŋ?Ù+lÚkÈD…;Kè’ò\¿ënQc“P–ãiñd¢ýs`¥t¦‡$i·û˜¯+’©¶y±û.=óӞ:…=rÙ* +«FT†Çtúá c®XI¯­€ð"‰ã]‡n’VÚ±Iv¦›d&(Ñ 'ýFZ÷3êº3жäÆH»‚±¦‡Áø‘mœe_¾‘ËgT}·¼‰ÒàÃÕJ;âéLâ‰ÆÆçºy›©o`3µš'Ð@ã€Ñ0š8ÝÎ4Fڍ5=Œ&Lm˜²úé3Óúgrè€Í>6‡%ÛíÊH»‚²¦‡A¡ç¦÷¨¢íº¨[å>ž?›A b5žË$ÔøOÅ8òˆÛokgx4YiÇÑԙM!J˜MÆ%‡)û×}4ù}v̛v¾©1W°³Wúëh4tBqºO­´#ˆÎô0ˆql{ì#iY–t!1„WžOe[×X'z#°5r&ø$}ÅñÔJ»Ÿ¤§Ž§i€adŽg¿vW/ç›VüHùú¸æ‰ž¬•tQÙµÜz½T?L°îJóãYÙæ~̰¼Eƒ^ñ³•žtvt1€d’Úší*3±ROzo§]KÐø?™ßƒ´öM¥¨t3m):•ï>ÌzÖZ0ëáh'ø¸Ô¿]ü·°| endstream +endobj +2207 0 obj +1405 +endobj +2208 0 obj<>>>>>endobj +2209 0 obj<>stream +xÚ¥VmoÛ6þî_qè¾$…,[Šç—¹Û€´ 0`Á¼ÅE?$EÀH”ÍM"U’jÒûï»#©Ø‘ízie6É»çž{¥>ôâ'³1}³ªw¾ì .†0ƒeA;ãÉ4Na™ŸÄq|ºü«7„~šÄcÚ©ëü¶%¿µðÿÏÃq2Œ§í±ŸÝ1ývϋR1 î¹¹]á¼ärµhíï2"3(þ# í[ñ+\ß‘^èà"õŽ9I¿\=yqsÚeàhmÁ½£õ7ày76x¿¹õs#HÚêc~ú©ó|¹æÐŠûÃ-„VþŒÕB®@°¨ YÅs¨‘ ¸È©Ú +%c 0ï;“y>0ÍAH¨•ÖÌI7hs’†M¨¹n=>óE#d¶öxr›âØC±ÉlƒÀ™’– é¹:>Q 9bÓ+d$d¡tňúO"æ¢3ŠGDÄ~ªy΋€N55x‰P€ÊÄ­ŒýÓYZ#m4ý7ÏçÆc¸^òÌòügØAÈÖLƒ‹ùõ(y?'ÍKž ¶û}z¾‚ÿÞ¢+DPTà1-ûÔ·;(òê¾îž©_XgÝëj¬$ËîJ¾ÉÃQ”;e­ª‹s·ø*-VkÛãOZ|ŒUõZ§–ª~È¿°©áЗ³Ý¾|ÝrrSfO˝fרWè97"ç¾ØÅúfz«7 ”Â`e#‹Å ÉQ÷´¹6`šºVÚÂG¦…sCiÈ<ƒ R ¿O»q«a[Mã<3ÝæÄÁ!•ìæZEŽi§­½±ÛJȎftH’=ìHRo’¦¬ì°ªxuGî«¢3~ìþÁã/­Ãƒ…ÜùWŠJXBv«Ç¸ú@¶·OÈàRÁŠ['¨¹iJK£¶zlñƒskކiŒà’¾jâöF»nt$:2¾ÏwBzï¦uGw o þÁâØ .ËW\c€Êkõ±mäàâ8I&³[ðzt_ >2Ãp¡°.•\½ïô_HÒt䮓ÉQ}×££MÎé‡9åáw7‚÷tèÄ÷'^3n08a&?Q>ußK¸‰ ce û+,½áÃÚ07'7§ÝPÌÜ5`•3ä`r¯Ð)í` +ÍMbíL8òï0e“sx•5µ ŸxýÓÑwªoy_Txê'nyu‘Ç‚æSó¿B&d.>мae›’‘iÐIF³8ñ, —Á뷋+¸R…½§J^hµÒ¬ªhž\2‰0¤Ý÷JýI:$dJ›g“³xÃöõ‹p‚«vÐ/ËÞ½ÿ®XEßendstream +endobj +2210 0 obj +978 +endobj +2211 0 obj<>>>>>endobj +2212 0 obj<>stream +xÚµUßoÚ0~ç¯8u/´*)¡”uÛúUÚC5¦²·JȧqçØ™íPñß÷ÎIø‘B»NjìïÎß}÷ùۉ¡¯F8Ï;_§³ë>ŒašÒÊð¿-º¤æª\øÄ˝Å"ʾO:}è âhH˜(ŠZ+›¥R‰™‡ü~YoÇý肶¥öP?ÜèTIîÝå«I×Pø ˜ô†Ù?? /¾£óNáˆðg׃ª„®f¹¨VꢺGÏ0K¦Ê6èîø²ZI Ži©‡jôÂ4ÐÀ«Í­c|˜^´a['mpÎ[©ïðÌ'€AÁ¬—¼T̂ ¥…T¸-¹8+\!¸—K¡V+|i5„ä 6T¦Öçр(ûLXLomüFnàV0/0_BÀ E©^«>ŒŠ¿ú=¹¦œÂš¥\‡<1ÍRh)4–:Bj,äØ, T]©Ã -AÈN³ +2ó{„)9–&>î4'4"©xµŒIot&>¯˜]æ5K×îT'P»éþÓîtÔÆï®6ü·ÓFí7º÷Yâ»ãv/Öý &ÈА +=³¢ FSgL&ð`æàE^(40Æž—qÞÀdò­aµÌ¹ÏÔ+› œt˰Ú_hUüÆ'ď×NÍæ##^5q»å|t@‹Öò\‰=cýý\Sé¡¥Ïh³¥/­ÅºÕ* NlKËõ ÒÌù½e­Åx±¿Øª{áÒc©Ç¥•)ÑKѐ ƒž† š×{Žì»ý™l)„¿^¢³,Yq3ž6\ΰ}oøÖ¦¾¨‹“qÃ0WB¸ƒoMê)pbͽey.¬ƒ¦K¦(ºWõFƒþËЌL@ñ˜¾O;¿:O&Çdendstream +endobj +2213 0 obj +678 +endobj +2214 0 obj<>>>>>endobj +2215 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS04±Ô3T072PIÑPp VÎO+)O,JU(ÊO/JÌÍM-*VðMÌ+MÌÑ Éâ҅hхê12 [€,r3R“³3óÒÒò‹œóóÒr2“KŠAJ\C¸¹&Ï&’endstream +endobj +2216 0 obj +130 +endobj +2217 0 obj<>>>/Annots 35 0 R>>endobj +2218 0 obj<>stream +xÚu”QoÚ0Çßù'žZi¤I ^וªÕº’j/}1΅¸‹íÌv@ìÓïÎ@XÑ’eìóÝÿ~ùÛ¿¤ôË`šÃø¤|-7‹9ä)Œ³YrwÓåÕFðÓ© Ìª èüuñAÑÈ2ŽíÃGãIžä|¢¨•Y‹–b¡D/Z¡‡Ún!XØR.•jª¬ƒû·—e²Ï<‡lʙSJš'Îù}ƒn£pû¹4äSªM‹S:Â!´Î®ÐB-Hk(C€ÊY Ö PEm)ìùéù®%$NjÄ É±]è< –VkkX•ÍÆû^yQ˜rÔ(ÊI@³Q΍&€2t¼÷DÓØ-ëA͵V–Ž• <Ēf´Ü::éí¢°ÕYéˆîÄlrD2ß3[¢ìöî­ñªD'‚¢ÙöìŒušÔîÀu†Õ Z1#*¸!Y嚄÷¼ån@‹Âéåä¿å€¼àÐÛΆ.¨Fý‰ëg͌úoçkÛ5% ä )%éL£4ù†Xiۙà h¤/¸‹ÔKåo õeo>¶GяÎví%5Tb%º&DOr;•Zw‡vˆˆ?ù,zÃÁ°i‡1óš3Ã0šhxYJºµNx¶íE%}ÔÞ 2äéP0 e"ÿR9”Yø¥ªm­vqkX<¿|{z~òåF8%V 9œšåâÅ MRzxÈxx}ä?p›'3Ð0ç[ç ,ù­8‹vk¸Y¤½þÛqŸI”¹ nòýêý:~óþdڟ>>>>>endobj +2221 0 obj<>stream +xÚµWßOÜ8~篰úD%’²îBO÷íR!QÊñC÷pœNÞd²ë*±SÛÙeÿû›±ìnHÐt¢¢Ž¿ùfæ›ÏÎϽ;ğ;Ó¿´Ü;¿ßûpqÊFÇì>Ǖñ >dûw 3!çìÃç`˜UÌ.€=Ðïïà–c6ù-Q2¡-÷¸üùáæŽ™tY]€f©* +H­aec@ÚËX.3®3Z+ÍrQ›­Ý>[Ð1CL›Ý\ÓPð5dDCŽâ„‚Èé±7±ºR҇iéx⇁øþ•š_ÁŠÝ|öY&4’KˆCd7ÚuLå '& ˹–BbP¤Ï%RXÁ ViÈœÏÉO¬À÷>íÁ>´!¾LϾ~ê2ŠÇ(³zބõ/¤á…hŸ`pûc2žtÒ¤µ¶L—×ßûЉs®tÉ­P™¿1̟g·×—×ýy¬¸–¤¬7†˜ÞÞ~¿íOÅËéø7g_§½ü+ê:OSUKûky48Qr‚1ږ_æN¦$ –…'Ë2…j—ʲ̅d+a˜ÙÚ­ã»|¦–俀 K:´¸Erӕ ¢vF&ÇáT+J ƒV&U•@”0Q™©´¨ög×B´“û¦LÜZ-fµÅ9ÆFxt·í“@~…QŒgÙÐ{8ÞÀ¹vþS¨y7L- Œ’&aŒ<ЪØm>>>>>endobj +2224 0 obj<>stream +xÚµWmOãFþίñ¥á„Qw½J)ˆÄi⻪m*´Øãd¯ö®owÈõúß;»kHHKsªP읝·g^Þ áþBè¶à¨q¾óc´sp~a¢”N:Çô#iœÊb(P1å؋>‘TÂÐK­®•Šfþ¨S5bYpÔOåÀÔ´ÌQÐÆ<% 0tW”ù-*)øk`$J&eŒö¥á¢( ¤<Ã& LKÙ>,d z&Ë,)²…5Hn…G͖ű¬õr¯lÅW«U°7zË5è²(2ŽIl°Öà}Œ…ÍŠu×ÌHˆ)´.T6.fê V¼JpÎc ¸H°@úG†R›q¬xa@–Ɔ:iÜqC`bAЏ µGž3‘hH•Ì],ÕÉw†Ã3— ÉÞ>h.(wt¾bú‘ïh•‹Ã:èBY¬áF±)ԅšßf£´žPeL—•ÑôW +(h4] õŜ+)\"?2ÅiÐ +©?Gµ¨=S#ŸjŒÞÜc-|¤p^+ôùŽ™€[„R“ôíÂåÇ+{ý4L*ù Õñþ^öFã~´rà€ŽgL±Øzc?ÖS56{‡ƒË¿×Wš‚nó˜$C“V§»’n{¶Äæôú}ÔÝD¿ ûÏ{#ŸrÁ2Hdì+Ó, +$´ËxLÃ.³E;@ +‚Z;¨w·öèÃp|s֋zgƒÑóeÒ[³¸XiH˜a. ú›ŒŽû£ýÑèú:z¡ÝXŠ”OK_ŒßæÀYÿãà´óa4؀‚oPßŰûzï/6„ÇÄ´dSüŸ+n؋.Ÿwï1.]* ffôXHeÈ7éê¦ÚÚìðìy«i™ePOãzò¯¸­íŽÔa*ù“ð¹Ärkk£Áðæ´wz¹¡—svÏó2–ËR¸¹–c.iú!£f®F`µÙ¨ +¶õb|}ýÜõÿ=h×FZ¦æŽÖؾ,4I2Ús»öä l†[ϑè×Í]œá9~‘bë?Œ_‚i\*eۇrù’Â¥EÖu‡­c²µü²8ãZcl¸˜:¥—Ãàâê çúáÉRkvj~T‹VÈN+‹wVL³gVïdϒˆ9O¨ù,!ð0Y®a¹@‘á½=Ÿ*–WP +Ú¡F?¶çGá#@Õ-á%,¤ cG$ø’ÊèÝÛ·7¹fXHý™Ép•GЎƒ;Å]†ë6”Žeý#çÙL?‚”±Œ©1ۈUTʕ¦ÍÊô¶v,ûª0㎘¢Ð¥BŸmWX’ ++6OH¬#iAÆ.I¤g‡Ñ(zXґ“%i{w‰¡Nt'†ï¡_¿‚ûýt'{u.©\Iòϕg€”2¯']»8G¯¡®(ø$oî¦mn²%®û›MáØ%.aTj²÷fM½BS*Aî…ë§=Ígà –=é¥6unaY®.©f0tØYȲä_m(}L%ë'fc‹“Íi;\õáUZÔ~µBßy¯VÃxƒîÊoŽÐ}€g¿ò¨Zo~x؏Š +äH›ë*¯IFÝqm¹õ„M"ä½6W³¹~ã`ÅÏØß¾…ÎÖ[xëÕ¾ñI8®RRo…Ð9 œ›ãjˆÃÐO†Ü~¼c¢d™½„íºt[‡>ñÚÝv=[GöE?Úùiço' &«endstream +endobj +2225 0 obj +1273 +endobj +2226 0 obj<>>>/Annots 38 0 R>>endobj +2227 0 obj<>stream +xڝVmoâFþߘCB„›·„DùpI“S¥kC§~(Õi±×/­½Ëí®CO§ûïÙ5„˜p흉L<;/ÏÌ<3æS+„?!Œ¦ô•­›eëì>€,’L/ð¿¸Ë Í{Ë¿Zxaà_èKãÎúM ôa©>ƒ‘ 7\€É8lT. $yÁ}ß?Ö?«EÃП:QžÀª»ê&¸†„ܬºL¥OLÿ@[­Û«Þª××ðë‡÷ïW½#G(ñÚp¥¤ZuÛw—P ¶.øæ3Dðý_½âBqS)ÈÂ×ο6$öùnÙ +ü«M·nï`Ný LÆ#%ŒGT?°p½CR3<ãú{oT2¦aÍ>åÀã~›\ + x€ª2âZó*‹Ôš[˜/1©¨ý.d7ª6zΔæÎv¢÷Ò(Øípv‰ødÂø“ÝK˜Íöu¶ßCª!eO Þqã ý?DI%"›À%éòÛŽý1y¥B>_¢*?Öl¶—Â×g ôOi¡Ì@”1EîúO¬¸jPûx\ú0wM‚H–%VÑ+rÁ÷DlUnv­—…L_¢£ÚÙÓ忤 ö [Ô8nº¸ \0€†óz<1¿Úò 3íuÁ¢¿7…4íÁaE÷Ü´³ûæäìêŒÅDÕk®¾'l’›zŸ›9£Ûð»‚âÔmóØd?uÎÅïdŽq×’™U™ÛhhÙ·´“+Çß³=Ë` îmb¸²ÌØu2cOÜ­„ýì¬î Òµ\Ò0—Ú,"•o®2¶k”´A¾1ƒ¬Ì¦2°f´;¤Ýâ;ø#·Žž·Ð¢BjtÚXNH! ‚ó˜Ç«ÞÀ2ÙmPc½ e<® +®|—ã Âs7÷ÞhèfôêƒEõ²Ôªsת{›"á`†Ò+ܘæuRe…Cšâ¾T Ǫâè&R•vI:hoc‰ô'U%ǔFU¢GF%n¥xB ×ù‘øð³¨ýè)×Pr&\yÖ<ͅ (2΢̕ÊB²g°ÍMvzauÞÌžEæa¤£:Y šžùÏ%iH–†ÚRÈ-WAÎÈo$vZd)Ú-Üá´&%Um×6Ðþ¶ÀÊ㬬?£y¶Ø—´*ÖèÞ}5êjà†ìxß§Šk#w¡.êtCddˆ?Þ¦Ž—pûa¾€…L̖òÇ×Lª6Kð +ÈÚ Ç34ò·Ù Ç$'89}ø’ÿ­õ/Uòñ"endstream +endobj +2228 0 obj +1042 +endobj +2229 0 obj<>>>>>endobj +2230 0 obj<>stream +xÚuËNÃ0E÷ùŠÙT©±úÚjwТ†0®ó@‰ÆUý{ÆMHEr¬™s=ÇþL$düIX(˜ÍÁtÉc‘Üm3XAQÆÊ|É»ãM¨ý©×•½->¸ƒ”±/jwª-Xþû¬65”Mk¡ñŽtãÖcüçt¡ò4ñɤ@Í8F"!³t9Ö÷<5¬Á Ý»EÂf³Ûþ+VÔ6Xè:ë(€n[º˜î} ƒÁ¦§(J>>>>>endobj +2233 0 obj<>stream +xÚ-‹A‚0÷ÿo© ° â£;cMë"±K¯¯UóÞj&ó$†øŒ±®Ò[K¦Õ¡3t.·9cSè뻋TP®/ã;Hïo¬íüŒ£yDs_ꑲ_’ý›¢J°"¯ñÒÍAµþ6œb˜bH~¯éLo®•%{endstream +endobj +2234 0 obj +126 +endobj +2235 0 obj<>>>/Annots 41 0 R>>endobj +2236 0 obj<>stream +xڅTKoÛ0 ¾çWð¶H\Ûñâ中ݰӲÖÃ. +U–c ¶¥Jr‚ö׏”œÄI; ?H~’zž$ã/<…Åx;ù\L®¿®!¡¨ ]¬£–ù +ŠršÁ~éd·…‘nŒÜ c¯Š?˜•A’PÖ<¤ÍY¥”YÔÒ¯™¦”RZÞ[+,ÔjNÁk +` ‡š¥¯9ƒ}-y ˜ÉÀjÁ%k ’ Eh£¶†µàj怫݅/¿6÷D$†y²À†Y_‘9X\a"iÌG0†¨\µ-ëJÄèÊfÄs/(¡RæD* + +אä¤!i”ÄßI±?·ÒŸ¸§ÅÇÐ,Bn’ôjQ‚÷õIlega/]M{ፐœL`慜ê¹ëqd9k4ÀsNÁla¤Úð<ւ•øçΓâcÒIø³äˆva?vÏ1bI¦sÕ(c5ãbO[ª±þå ZQJšêWq¸w/ïkfÊ=CFXÕô¤næÏ«h`] ˆé2Lé§*,„xã-޾‡£#­ê›f>Fé;ÌÐøÆÒøH×2,è…èh¹ßÛ)*,;8ß/Õ;Ý»‘üaÇV§ÕYåýŽô,ÏpDbŠLóa¬~Nþ°]óendstream +endobj +2237 0 obj +734 +endobj +2238 0 obj<>>>>>endobj +2239 0 obj<>stream +xÚ­XÛnÛ8}ÏW}J[«›oÝ'ÛIÓ"qêuÜ-h‰Ž¸«ÛRTRÿýÎ %;ñ-Bk´ëpÎ̙ Éüwæ0þ9Ìëâÿ 9ÍÏþø<`ŽÏæKxÓíÃáù”? 6 ‚¬LµLŸ>Îÿ”ÏÇ ÚnPJ¦Z(*ù,TÁ’²Ð,âi Æã˜åh…¯­XlI@ žLGbe" هéðêòÓxY° +ÞgAb s<ËEÂBƒq®B&”Ê[J Z‚‘a{8“)Kxºb/DÑbA–¯>"‘®ì²Ü¸n™È6ñ·ÝE +Œ³ Ox +VXØP‚€§L&yLkI* GSÉÚ{–œœ06íÊæyPæÑNU†¡½¥ùòBgŠ`a[8ã ˖Z¤,KA“ˆS…U.€&È K‘Yf „©+-A|„ÙŠ, «0)c-sÔ¿Ôy ʟ"†ò{‰0)hÁ¸WûCÕo(5ð\™%Àmj?\ ”A†å>’:á9û›+ɱ(ÔêH ÌÔzlÝIÓ¬Ðw’¹6 d +ƒ…2Ð Ÿžk³ðn)SÊÙ†ÙB¼6pAÄÌےH‰¥På„*±¢pñøûôn]&E™çˆÀÃPmüЕЅ+Ô£(6ìû½ÝâŽQpÈÎzM5 Š ÒJs UD¯rHà²NUÈ57@¦MKh~2 +w*…}¬Ð¶Û7‰©Ó€˜¾mu!ðíìâ7Nטm2Xnà9¾¹œŸÙ– ãyý˜]1×´oû–Íúx8 ´¸ÛƒuìÁÜXÎqp·ou*°;ðß iO¨Ë‡ÚÏëû&8œQ?d¨#Š®Ãº嘇mì¬íö€†~2 IUp²€*/LåB:L³×Áë9°žtð\øý¨L¬GÁ¤ƒ6hÐÁDßqëØ¿ùéß +ޘø…è=LPÓè Ü4zŒ +£[Ç?¡äu-oIð¢¤Í40ë]ä"°3À¶➈½d¡xG»kõ Aà¦Bøn¿g­ fn1j\ï ¿®Åm™,hwÂz(pO2;͟Ìi1·Åü¬>ÍÀ T0K5laÕÌáq±Ü>ŠeÀ Å2àƒbu|ò­XS¬òßê=ZQë€V¸Ÿ{î;bøn=HˆAà¦bø ®»Ÿ£œà@ØKO%š$5b0újûzR<dðÎdqíAó¹jÀMe!ð!Yœž½i(ê¤o*MÛI¤e²–Äóh“ððQ̑î™ÇåæÀl&î§·'G¸­â±äñÛìârö8þòýöúòbû0ÙfãÉýõæaÞÕûvªžv÷·ÛÛ:¢â»}L£áíÅ^¢ñ˜M&vÏ®¯OÁ4½Þg;L[Ê"¯eYčŸÈŸà~îñ£^¹våp±9^¯.¶öÌÑb3`ÊðQ0››bÛ w3øÑ}Svwxë©ÊÎn^tõ—óúr@·'¬½æµ6¾›Ǘ?v³ÿ#z¸ÐÆe"Sç燏¿UÓìj´Ë5a †…i‹- aND4|Ÿ 6·8ø)¯wÙF1þ=…mèô=ý¹âE—ŠTó[‰8Î^NÁv?ï²Ý“ùW|П(¶ë†ÁaΚ(z¸ý;®]ŸGÚ^߅•G€S·½7û ¶½÷$´{ëw]°õhé$©Všßâz¸ô+ßÌ)’Â\pï²¥~ÁsÛTe°' Þv't F™ÚfI»ZãöñKßöj=÷ü”ýëì7DTendstream +endobj +2240 0 obj +1482 +endobj +2241 0 obj<>>>>>endobj +2242 0 obj<>stream +xÚµWmoâ8þÞ_1ÚOmURH!@oµR ´[mQ¹†ÞªºžVnbÀ['ÎÙN9î×ߨIx °›;qªDCüxæ™gÆ3æÏ£Ôñ¯m.<¢£ëñÑù ¾iÀxnÝsZàuZ0{O#ÿ[Ï]õߞ‡½/'ãïmæÐc¨Á3å\ÌÏ "SkrÁ‚ÄgðÊI𖡃]k;ô‹V_\¯ ÙbáÕ¬ÕŽ[öú¥7|Þözm̾–®–Ë¡¼QE¿V_ÙYäŠp6éš=çv,öîãèzN³Ìñvg>†TÎY‹/ÇSÁד2˨À-Õ[¾ùqÿ#Uÿ¤ºü:•tfãïT¾œˆý×ÏwãÁ6ý¯3¦)$l!)ôj¢Jìç밃qº}¸ïoSºEý`"_£ÓâåNçÿúhøw÷¿ ·}ûVô-ïY.Jšìe³%Å`|TwêØ¯–·Ðð:Ø¢ZnuÁwÐh·$¸é¹¸X¼n9ÚØÊoûd³ÍJ«^GÖH8HÕQ"©RLĆ:vP·ã¢¤$¬Í%ÖAIk:ÍÔiuFïÓwКJhÀ&¦ÊW†A/Š/BºW·‰ÄšÆÚiáDž‹ß÷Å[ï.Á–ÁÁVœ ìv›h”Æ +ÒDL³äQÌ{"õaՐØ*cÞ O¦C«…Vªê`ÁUu°à½:\xk*ÜP^„ Z­¤klWÕÀ‚«j`Á{5¨_8ë*øš&‡WA¡Õ**\tÍQ­¨B®¨BÞ¡zòræ×LG$Q0gzë— ©Pؾy‰CˆÒ3ã]í•iH°½Ú@̂$±Š˜ÖXZ ®¬¡$(„P2ӗY Æôšç_̞å²BÖ*±b¯œb—H¦‹§)i AфH¢M+B汐á%džûêò“…’Mndñ¦œ¬ïw±›>Š­h&½L)ôQ¸ü<ªz÷з 7nrۙ²ã2‰¿³e±bqq mN·\-fIi’½œ`¨1šÑʈŽIƒ ó‰‘e•Ë:aÿ)ŒH‹Rü9ìÚÆ®¬˜‘PðmÍôr”ψœHSæR9`b N 7àˆh£íš3ËS„Ì´œcl¯‹’Wú†…WjDLkù`'E„!Uoß©v’$,Oq$Zs¢¨Ü^å±Y¤¤›åÑиAjGҊuCSAÂÉ X”© öt¬.=^èŠèsòô¢\‰©?!°CÄÚވÞÈDX\h„)ðɽJ ž.]¨º%¸]DՕ¹ßeG¬ÄÅÉ]7´+3žY€i´U· ÆrĘXð4¤¥ÛÖqÏË!Žu^Rù¬Œ¼‹“Tû\èŸGxæ|ö7­‚{¤ÓüÖ²D6Ákr>R%xª··ÈÒãÀ€³ü›Õq&æ1eq¾&<$2Ìgëþ²p×5¦p†ÖlïFw§ Ÿîà´ë|HCFÀ<^ˆoñ²旲ÓRÙ§¸3¤q°¸ÄîWñ§:MV–Ê»útBR®‹åK¸§ØeeV¬çËçO~þt >~,¡Ï—èß½† í®ûGq‡M¥¹¾Aœr^Zÿô Q'h&´SðC™Ï KÖŠSÂ3†ø°$x~ÓɳÖÀ´â˜íxYr³úõÅDÏͬI1•$ŠLÃ’8ÍZ~­Ñ4²ÖvëUºw³Ý,~o¸Ý|Vÿzô¦üendstream +endobj +2243 0 obj +1319 +endobj +2244 0 obj<>>>/Annots 43 0 R>>endobj +2245 0 obj<>stream +xÚÅVßsâ6~ç¯ØÉK sÛI&3ùÙæ¡s”$ӇãæFØt±%Ÿ$ÃÑ^ÿ÷îZ‚!éKK‘´»ß~»ß*ßøø@·Oß8kÜ<7:> áyF+ý¾%ÍΈÍù“øƒÃ§~BàûƒÏ§Ï_>´ß”G36r~s£¾ƒ,Ò´¶u†Ûý$|)b~RÛoÝˤ¾´zu®£s8¹¼¬GÝë {0ˆÂÿ×mª y<‡-B:Ñyˆ ˆ¸62×ûtöyÁÁmú›ÍæÇœË—Ç}‹&¼òõJéLÎc1܀ESÉW r+”ô€\̈́6$Ë8wÂíÂJØ0 ÌX®…y…I³59!a¦•´ f ¬W%Òõ +ܾÇÂ,M×0SiªV<é˜”™zì G&\Y“mÍY¦)‡%׆P`”7˜Èi2ì{…¼Ç£ëê€ã WqÆÖiY°%Çx Ÿ±"µ°diÁ?lIJ0Ö¶ ZcùÎY¸ÕpÇ=~‡û¬,^TP§›È8šk)î‘E{±ÊòËPrUgŠ0e1kÅ)cŸb-rKÐ(1ÏäÔ`y¤ ‡Däè[¡,9:f3 ¹VK´Hb‘¨´4’ŸWÌU¢o‡‘#à˜·ŠÛ +î@aG%uTJÃT«W.1«•$œ†çL3ˁ™÷Ë»Qå1YH~&$¹AÓìß%ø¿M˜wçG¼PhV‰Ë®ö…Θ5oË nZ{ð ö"ªìpê_â‘ÆƒÑèՎ­C:©,ðï1Çö{½Z[Ä ,BŒ,Ԛ1ƒµ*ôÑ^ck¥°Hx2¶Æ‘ÅËL±ç_Kþ¡ÈK빔‡D”2ÉnèŠ2F­PÕÇå,ƒ;fÙ>=töŒN^›jî­)3KI—@s-$Ù&Z `ªHQŠÓ×Îo‚~i8fH ÑRJy7X°u½nøž÷$=zŒ†Ðz„QÏëCÝ òÎ6¿Rx¢[Ôǟ}¯¬á†«vY +lù2(•ÒX\fزBâÀp¾¬Ä~8=‡7¹qÔÐE2iNN÷Mü­ÉN³BÆå¼Rh‚5«80‹”Q;Õ $‹ð¾tpvŸYrÏN ¨ÁnÊ.Á\[Z·ü/.ü -|» »qTv.º¡ ÝiÕ|B n<~-íp +¼¢ô¼È¸´Æó¼ƒÓ•Ã0pÂþž4Ñ"†KèÏP¾_Áن۝íŸu_‡XÌï4¥åOÖÝ^îJКǨº"›bš(å-À XiªÀ™ÍµÆ2n ‹#~é>ÑÜZz‡»õ¤°(ØTfÒ<¹?ŽÏ75·*Søª¦mA·'‚±Â¦„0§:ܽfàIâód"OpØ‘MN/‚:0H^p¸û—kÁ¦ l­úÃhƒîöeôOjfW4AFZÍ5Ë2œ8ð+“8ÒȺD¤²öYè“M×§Åî òºàÿä@ÁþÖø »6åendstream +endobj +2246 0 obj +1131 +endobj +2247 0 obj<>>>>>endobj +2248 0 obj<>stream +xڍSMoÚ@½ó+F9T`ã5D©”¢ÒB 9Tq„¶ö;2¶»»$¥Uÿ{wÖ$´ÆM Ãx>Þ¼÷æk‹£¿ †.ô®ZóVïځc˜Ç G¶ ó¨Ý;ìÌ[X̱G€C˜”˜ƒJJ¾DJ _Ù¶½—ØÛF\f(’Æ´¹X†pvàS+øQo¦ hÇœA¡‡šê§ûÁC& ÿjòñösÐ :ÔÎb{ýö;”(D!‚öÁØ÷'þ ÜåüK†  +3— +Ä©ŽYptNzÈ ± Ú¬ù­@µ9üåýÏZ¤þ3‰{E†ç´Æ§ÆªÃẔ¾A=1ÅQ.靈…>›ý…?>¿Úé]{ÀIli-×t™ä!¦XCŸА€‘QwKE¥¯Éx\K9ÒûB¯É#@&• xA)Ò\AªNªa;;Y®g{4ŒÀ.ªÆ‹D7ÐՏ:UÔjﳩg­s™. q˜pñ’qÅïGìØ}¨Söœ°A{Gš¯‡ßڅw2Ö? ª]ižª”géw¬n‚8д5ąг7Z´j†M0n0]&ê6ð^K¬GGÿiå?—˜¦ß´w¶KÝß§\lÊ)ŠÛ4ÇfÛÒ.µŠ[Ý3I:¿µP£™]vSW›•¢QJ­Ï2c :Ì +‰ Ö#kUGõ¶±*..©‹¡a·ç뿜¦óz£-VÆú6o0¨2Í Á¬ˆÕ3SQ,_­PHøÀó5ϨÚbÞ±.²†®C5¤Bš/¡ÂWZÊò†žfÇdôÆóÖ§Ö/ž†ˆ³endstream +endobj +2249 0 obj +622 +endobj +2250 0 obj<>>>>>endobj +2251 0 obj<>stream +xÚ-‹K‚@÷}Š·ÔH3Dqëog‚Р#Ñ8‡1^_GÍ{«JՃÙg ³Œ¿8Ú-%˜!¸X§ŒUžAÚ¶çªA3vá¥Þ¢òcïÕ9ë'uxê}.7J~IòoL¡)‹Ôà j«íuèQë¬ÇNƒFc/t¢7òm%—endstream +endobj +2252 0 obj +127 +endobj +2253 0 obj<>>>>>endobj +2254 0 obj<>stream +xÚ}TMo1½ó+æØJa`’c5U¥Hiªž×°Óxííí¿ï›ý€B›ˆ‹ϛ÷1û:™Ñ>3ZÎiqMºšÜ­&—·4¿¢Õ†æ7y6§ëå ­ŠŸhJ¿'v[ºSúŸ"~\ýFyN³™”Oûúé"Ÿã WV%GÒ¥ª“ T˜¨¯M¤Òï)yÚ£™!Eë¾m| ûŸßŸ³C{Ò¾ªÇZ¡°à`t²-í9•TvèI¹B¦¸¢élÑ£*k0Px7ÔцmwàQ •5Q)×RjkC~TçÅÞQ +ÊÅZ〜õtoi¶º€\̳\ Ÿ±c³?Õóev-FhE±6š•=ŽSªtBõ”áH<£UiÚ®C +uEËÛR4)x³1ý”ÒΝI2 ]ˆô³^tr”j‡a|eÀ¯¡`^€Uèdó‘ËmOöÙèÖµtï]äÂ%RÅÿpÿ‡yh)!ŒGï´—Y¢?H¢¥ªjb¢5X*ܳÔÎsAµOLªâ8Á޽íÑ3úvN¶%֍U€RÕqè´>fnÏÖ +”Z[#H•r\ãJ—·ø"ÈV˜kyÙ<Æè}pص<‡G…Ú7V¢V©­¤=¶1™ŠõÁළ¾G$8}dgèsØ61oélċ^ۘpM…1ð~¸{1ïíPҋ']àœ?Š[#JY†X +µSlE¦3ªƒ4N–¬Fí°ì<Ž#Éá°ù‰°¦þõfxO€º¥¯Æ {ƒù#¿:$ü@0–ðÝ¢WM\Ãbík†Hà#:ut“w°ŠA³ûé–Ʀ®-cpy”çÔõà…?=I,öM×z Ø0…ŠÂö铿›:ÊW£C%¶BYœXð¢âwùpsò6Éß{çË<»A!J 9ø²šü˜üô]ï?endstream +endobj +2255 0 obj +718 +endobj +2256 0 obj<>>>>>endobj +2257 0 obj<>stream +xڝWao9ýž_1âS"BIÒêtJÒT©U¹B¤~ˆt2»\ví­í…Ò_oì݅l“SujUÖ;óæÍ›7î÷“! ðgHþ›ä'·ó“óci¾Ä“ÉÕ%ÍÓS-霰{JLž :2–RáyC…5i™HòkIy™yUd %]ÿlþ ¯i8Ž{£ëþ˜CNÅJÒM’˜R{¥WñÜ!qoߊd#uJK•yi­¤–VdٞRCÚxþ(8’h"uimvr+-ãٓ[›2KIx”+­ò2o rx!“œ)‡ý' s.ŸK*E²æ‚ö‰@ÊÕRÚ­¥Fà“Zä2>“NjOFF*Æz™Ò²Oó5N(×ʸ‰(]dŸ–œÌdâ¿cÅ®ƒ*ÔF„²Éà =ª™”Î\x…¤ Á8§™|þûIV:µ =@©ÿÍ¿‹…{‘m¸á™IDFÉZX–µ°ÀwJåV!ZMº)dä ~XT’MòܤmöŸN#–A…åôó?÷_ï>>xútÆ@ƒVxI;å×-,K*—à< -dŽ¡¼NÌé-„û +7YF‹š“xæM )/o¡$‹h<4ÄÍqŒúÀH­ >Rð¶øMºÛò9&¿K„”‹}Ÿ¶¬0¡¡LY³DßKYâ7S ̨*Ö{§8õgÌÄ$25çÉÇ Aêh(4DwÓG*½Ê”W?ƒ»!XUU­Š•á¢\&eZ@"g!“Y’WH¼~'!{ñ®U.Ǽ{œÎz®,ŠL¡Ã o‘o£!6¶€=] 0Kà?=²¢Ëª¥£XÈ{å·ås虴 +EOõTéÿ5ô'æ*ž/ø|]*üa«¸£ ‘p¡õÁJŸ}š)ªØÅp4öëАdš²HKɚ0-RÓ嗛\"L–̲Ø‘³ƒÓ]“A–×e?‹89ùû8¬`%1 éµQN·U¦t°cx±L»‡FhÍ2Ⴃy3ΕyKܵ+õöéFÇ1öÂm@ÄâЁ£Òy֣ϮdžÇS¢\隷 +• ¸_cG ©êƒã‰;(’ßq¯¼œ]·9i +u¡3”¸*sP][kñÛ§§SÕǰ++ˆÕCâ•Ñï÷ŸÎÚ£uÕs¨5¸Å®`6ÕÄ+=–%䉭µãõ¶C¥ÊBûÆî»“âxƒ ÂpÒjkQ 4Ï<Þ@Y_¾>uÃ^BNg0½‰p!F1̔9,‚Ѓ0þÂ_Æ W+ÃN—?PdÛf>W3c]=+_ï¬òÒ5«œßÍÒ§*Ëu(QIkñœ‰êÓ=Ÿ +ï0Ÿ?nä/v£ÜÛz']3k¸*õF㯂?Þ2ÃçÞïgƒ?¢Lÿߌê<ê6;ݡα» ;Ï»Ñ cY* ½ì wbüNÐzÓØIÝÅj¿&™hoòÓwäÊIÑ3µ„›FòIö†êÍÝZñ²‹# Û‹ue¬úÉüÿ"‚¸_Âð.E˜\ödJJk‘ +݄®ÌJãí˜ri²ÌìX!¹ŒœÆŠ#•nI‡zhfª0ü¡C±œ¤fè² âkÂhrIÏkåg ÀNv W¾4ʌBßÈ´. UïÂ=–•Ò=BH`Ýáwk´J°Yîïï{ÃÑÕ8(¾EÉãì¶q³è5/`on9¯Ào¸¨Îð·?۞¡æÿŸkì&Ư~9º§`qï Þý`b«ÝÅ w ŠþšÏ§`bŠ>Nßw™ÒÙ§Û󻇳ö=Úo“ý.WÕóáhп¦Éå(îØ¨«™Yz6#šÆ5’ó ï“Ðp~»7_÷‡= +õ_ŒùËñà¢&ä…ÿnÜÏOþ>ùmß%&endstream +endobj +2258 0 obj +1432 +endobj +2259 0 obj<>>>>>endobj +2260 0 obj<>stream +xڍVmOãFþίåSP‡\x»´*訮„BÐõ$KÕÆ_œ]ßîš\Ôö¿wf×&Á$WćØËÌ<óò̳þ¶BþB8êÃáâÅÞùdïàja“”þ3<>‚IÒþ5µ¨ÁÎ|Êb„8Æ@fÜÙþä+9 +§veòpwíÿQGkw “ä@^±0-ƒ:ùé9X»ºïý2e2 +Ãwý^¯À„M+ ŠF¿ÂrÈtÃàω™™*ó¦¥Aú]9cz¦lÌ1¶²PÚp¥4xXw`: ¦À8K3ôÀ ñ=[”‹.;€Á”GZƒótÝ£ˆmIHO"/–YΏzSÁ¹*él^ž³ö)H•ïw¡3I½*üþ00þ„þE# Ú–T¦%£GB£OY%˜ƒ MËÄ:+lF`Ï]#8@ëAÎ¥ZÊV(¤qmÞÄn”î£SGKïMµµ¨™á³Óy…VOYBïÔÆ9º”¼»)㭏·ðÍü7´-,ò\-M“[cœ»Q©]ºBÄ3¥ GQ¥Ë©²†DgOô³PdŒÂdù*€seg?hÑ¢4M‚³Pƹâ‰eÒp1‰*¹¼o¥²hÏñ~cºý?¢q’›Êp÷žr·Ôú—;Áö~à HÅ,*4õQ•&_u¸D–xŽ21PQ]QØz Ó,§†ÓRá÷8/ Õë +ë¸Â4ZâõXÁ(p)m–s6 +_iœâId9ΓccK¨b· #•éö¾C‰ªSéÇ|ðwã K!jGí4‘«ê:iK´ 5›‘.`ZU@µd~NÊÝÜs'šëq¹½r[õ(2ÀuÚØ¥:¸ë'ã'hIÎiûH M<"Ÿ”–1žUßÅÝÈCLùrZ‹0|UÓõsî4Ÿæ“’\ÅJk‡¹[š>ëÌòVÔyü@›nn=wYÆ3¡éZc}­ô¾¨4Ø©.¸J–3¢Ï²BK6Ð֗䊮†kåÞìfEB€N •Ÿîte½î­H +hÆiJùL1e©÷ä#<’1ruykUºóg@•y:¹wå[ÛDgñu@3AÂ:Ū‹r·¤ÕD•Þóg&ë[Ené}F¾^&{‡k+¬î€çTíý–˜[ìfLz¸Õà-HõâöÃ`¸‘fåº=‰mê²[[ 3ÝӛåÄ/8íP–©F1?Û)ëL«îwGU¥¯}|µðÓ ‹ƒ«ãŠú!‘ „áIßS.nïá¾þô¸ÕêQ‹Å‚¿I~’>ñØ»NÈ©{ÔïýÏõ?8PÎêð\NöþØûXšuendstream +endobj +2261 0 obj +1227 +endobj +2262 0 obj<>>>>>endobj +2263 0 obj<>stream +xÚmQÁRÛ0½ç+Þ1Ì`×vLÀW¸µÐÁ:ÃE‘×XT–\IN†Cÿ½»‰¤íØéí{»ûž~­Jü•Ølå×ãê¶]}y(РíÙÞð©[ÿ¾h߯Q–Rȸ’U[©´A¤¢÷‰o'j±P×÷ßÛöǹ~ +é&ÂuÔÁ;D?&«7#’‡¶¤”[Ø}ð#¦@{ãçx>§@VnòJV2^'ûº~½ø{¨VÖæ'°AY/²ªÉk‘=gâ`Ü^¦s¥®…òè4áÃÏԞÉ¥£ã)>õÆÒ%¥98–˜þXôD`—q֚bìgk?ÀŽJa™„Îtp>åhŽä`¬¯êÒAVùd.rØÝl)H@1ùéÓï~·Œ $Ù*t¯|ÌïR’‹öbñ\$OÇÁsÓ#&/Vÿ?¿³4r;"íC Íæ–`o–ÌʺÉK”WQáîåéϾOÅ«=ÿÔ8RˆøªÜ¬¬h³“$»® +Ñl¶ÖÕUÞ øßûÜ·«ï«?øÔÔÅendstream +endobj +2264 0 obj +402 +endobj +2265 0 obj<>>>/Annots 48 0 R>>endobj +2266 0 obj<>stream +xڍU]“Ú8|çWLñ´©€°lc›}:’åö¨"»¼KR•c Е±|’ŠŸ +v“M®(>dO÷ô´Zæ¿_b‚ò}çCÚü=߃t<2¢8´¸C–jc™0“¹¨Œ€ñV ±•}—þë€<&`Ÿ#Æ¡„  ø£ÚïUOÓ/0ײ²²ÚÂòh¬Ø¿ÅçÄ5ŠY}?fQKTµÜî,ðÑ(îûžçÁú“Ì/êæZMn ùÁyÐêCrOóÇE +ÏÓÉ +î°L'8qHåÔ(¾Ôÿó8›}]=>ÞõàÓxñu6~¸ÃÊ(ˆúGyOË1† PbÄBÂ<+èÞsxøŽ6м€ê&iÇc(Ø}púX܃χÌ? «÷x¤·]•°¤ýà‰ÏpG‚¨•4Ùg²¼â{E¦·p“7µéËj£þ¢_Léío'¸G¾ïc{jœ ÃíêÔøñNô<á(Â÷²Z­Þ”±³¶¾ ‡»Öñ3£ËLØfƑ÷ýQkã´²í6JU½L„Gq ’t'à7É:£—å(Dސ ðÓKFŽ}O·zðí¦ûñi¾|IڟÁÝoïz ÔZ}—…( © +¡Á¢Îû‡'¸•ÐY óf]Êüü6v8vtÉj¸ŸÏ²ªpؙ\ëLßà ѳуg¡ š>ƒ1äx`@mH–•m¹*KuÀ«ÒïÒZ^ùÎN÷ÎÑNOƒP+È꺔He•<ƒñ|Š=œÒ”*Ï,š +WÐ¥$tÁ4ëBj‘[¥ÏÂZ¬QÎÅ+5…4VËuCjœg²Acô@VyÙbÐ2_h©°‹:\ö²nï²0%®”¾º º°‘%ÎÑ2¿ê¿–¹~-üåÊ/LÑO«ËÀõ¤×l˜7ÅÖ V!Ãüj' ¿á°“ù~Ú©uf(b5:ãÚ&ײ¶0dCϹÐR«È¡W|pÅð‹ðTŽ<Ö¦;¹¶žÀÿë ŒC,õ¨8ˆOžÏsÐ?endstream +endobj +2267 0 obj +780 +endobj +2268 0 obj<>>>/Annots 55 0 R>>endobj +2269 0 obj<>stream +xÚ­V]sÛ6|÷¯¸ñ“;•(RßòSì:ö¤§nd×éL_ ’P“„€’Õ_ß=´$ZNÚNÇI$Ø»½Åò¾žDâ/¢Þÿãìäòþ¤sݧ(¢û9ž Ç#ºOήµ!·ÔVR®ÍE¦R% m”[⾤›Ots÷±å/RË¡3aU,ÒtKøÐK[]Óç?Üÿy°vwôyóÄòºŸî¦dõÜm„‘$°(^ +³/é\ÇUZíQ0FnXúGw8¢òa3?kG½ Ëϯ”uFÍ +'i-ÍL8•Q¬WJZÒsú‚§rü.L, µÎT.̖æÚdÿ{*Óô»¨@ A™L” ¹”-·¼Ð«•6Îì¯ø?¨¨1VFåNJŒBž–DžÐ\¥Ž»%Pؗ®Pªó [“ëœYʾÅZ¨TÌRÉøá³ÈY¦q˼<’|»;Ƴvo 9â‘óqK Öò*ÃUøY¢A/Ôy¸ËY©½Jz”è2ç'ÉÊÊÜ4 AÝR¸ÂàQ¾d&™ç%U¢’D£À¤&Uéܟ]¸}†úÀYaÈÖk•Èú©o|¾¥\njþ[uN­*)ÅÛúŒH¹ÖCË'Š"ˎx¨™¬Ñ:hïû‘¿ÑG±B  \©©pw ï«íCLÅ3󂛧©ÊŸÚNŸâ.s‚­’byÔ,˵LõŠ!Ð,QUQ ª>ꍂ.î> µ3Ãç®LZ#ÒÔíöêì ÿXç51‡UxJ‘ÙÇ­D7¡¨_Z»;©Š4Pn&̓=T ‡xÏ{/얦õA½3:)bgi TW¯•IYŽÎ2àáӇ/Ä¡b2¦[ëdÖòµ–]òºJõBŠm³¥¹ÈÊ2} ËtË­g§‘F +“bÑ$ÊÈ’bƒØ¹Õa4 $]³žayS¿ÒQk¯_`‹V©–õ›£NÀ¼AÓ½1Ê9œ‘•4™²– §_Ðö•Ü硼~±¹CÆ t¦n-ÒBV¶Èi¾tŁÎãP–Úñ…¿ÊÞ)]©N þh©Ëö×B¤ÊmÉ:l"LbÀ¢\ Z€ºôm‘\–Ì^í3ûî_ŠF¤pP6KÆ/¯uí®;K-¥/Žö´v>0ß(h-óD×®ÍÈEÎvÌ(8¿¾û ÕKE™õ¼ØM)ÕL'j¾;»•'úäŽ4±zýû•lñÀ r~ú-ö5Œ*,y;—Œ /Áke©7÷L¯ÚÑ7NXíuؒNWÖi#pۜV¯²Êx&–¿*óébšqÓØ¨•£A0UÅÚxö0øqt·‹Æ¶Ø)h¢;Rd¬ß•T&àà%o÷³÷šWöM_?¤ìÕÔtëÓøY粹ŕwàá–MŠÉjº­qj.ŸwRýÇA#¦?èÓG•ø;*±tÞ´hZ(˜mŽáS³!æB¦ð¼ šô'a¦°ß48§£  ‚þ¤LÆÃ¨t-ž›!]y!FVþˆøãó 'A¢Aˆy"Ãî“ê*¥)ϳ`-D¸æóy‹IåÜύÌ‚ÎX±ï„á±Î£Â*ª½ßÖæé*™;½²/Šƒçaö…k£ß¬·/ÀòI¸›âþ¹>^Ö´}GWÒÈ'º è“Öù¬0‹·ù"ÌY oØÅîþbÇÞ¨[Î`ï³o‘—0`þn®5FA[ówqÔ BŒ‘hFÝpDQ!¾¦9 *G~|||3ƒ¥s«óNg³Ù{YtžAçx/;×ãÊÁ#ÐÑp–¥–~·oä #²Œ'ã[‘ãõÂûµ£þ‹Ú£®ŸÀ{þDô1·öʑüpÄ¿žü ¾'¯endstream +endobj +2270 0 obj +1394 +endobj +2271 0 obj<>>>/Annots 58 0 R>>endobj +2272 0 obj<>stream +xڅW[Sã6~çWœ·]fŒ‰ dû;ag;tK7ÐNgxQl%V±%W’ãæß÷;’í0ä&Ûw¾sñßGMð—Ñå”Î.(¯nŽNog”Óà +'WøP|\´Mc¬?~ø §ç”eñôdzɧsá¶´0+ß +éޚ¢Í½#'« +¯Ãï.ꠕ±ôåñ~AÂQ‡+ü.(7u-m®DEUÚ+½Æ‡ ‰–ÂɂŒfó0š¥S6”䢪p8_ÜÃ0äØ|Jš'šVJC°õTx <>[]’S^~f}ó‡£I:ü’ñˏ¯€"EèÙUzN5 ˜á=~«hÁ$ìšNo'4cP€âEÆp°ô¾ù|zÚu]*‘ëRD‚ØÉOvòÀü’œ@ÃÉYðë÷Gú:ÿ>ÿq}G÷7wß¾þçßó7‘^°ÈïÒ:e4Mú¹Õ’²Ù,‹—{ÿøîytï‹i¶V­K[W³$Ü¥[+å>—·¦Õ…ðИÐ7§C&ékø•²n*$½¹LhÑW:;›$tcœg±_®i2Ͳ i›\Òãâº×1Í¢Çó´[W•£FÚZy|zF4[È_¡œ·jÙB3î.áN=òW•tdVäK¨©T.µ“T˜¼­¥ö A˜òRè5ÓJy¶¥'pÇt²H#B³=œŸ&¬öÞJQ/+ù틈àC)c.ðºFÐ{Æó!Zë‘Ïø±[Ú2W€º05Ÿ¸2ÜG°ÁK€áSºÙí­p>QßÃp`‡ÔÒ¢dîÛ%ü »>p„‡Rºˆv×­°ßåÿÛ峑­!œ“Ô‚k!Ä.ì"…A– T¸ï¨uàbJœ‘wüMSqâX1#gVoÄù#?ôŽJ„Þ’ŒåÖ±¶¢¦®4l§õ¥±.4d7[™ÒÓDž©Ç1G%ïY~wn@Jà¼ÜҐ•;µ´Ânß͎v^Š"}:Yºò¥èhÈXKð‹Šp á¥Ôèiä)ž¹B&>bW­\Ik9jhí)„*@¿ÍeJ¿ÂÐÛ;V0òõ×‡¤@…ËTŠM¤ÈÙêx_°/œE2z.Úu$×ó˜Ònà©U°Ô)W>'{ÓVæRmXiks6UH‚&v-}¨þ^5¯¢|§/øþN°2p›Ac`•š´ìb4C¶~Š´”?kÓí¬†-8¶ƒ”¸qN kñ2÷‘¡M»K-@·’!͙”.ZhKUp%pOeÔ¥ý¦·5q \/ÆEg8™–Û‡ 9Œ2\ÊAà ›h,®>˜Ê¥õHàFƒCµT•òªoìBü[Dx£ð÷†x/Z›B­¸6ƈÝâŽüGð0JþËBËKì}’i)C±ã›W˜ÐÄh%¡(˜lљÖjó'À5ňrÛۃõ²âBjÛPÕɎ·\(ìhœŽ¬_ƒ^;] zA ˆ…YÊ2˜ˆäÃ'5péU‘o1ÕåKòáeã>£@³§ã0šãæð2OÌ÷§SÜ0+t›žv¹+Ðg0ÇUÍW+¹æõ—¶˜~ H3 §aÒ"Ú‡t]9ÀÊٔ‚s†¦F'a=´±²B?*kàrȒv”–kÂyˆ¹]þÂE£ ´YºÛ]{ÙêRú¶z5CCP*‡©Ä&eåâ|k„‹kðÞYŒÙ÷ ‰Hú¬ÃÏn [ìÌýþÃö ©´¨’È\ã) +Œ°øÔa[xt*ÌEfȯŒ¯*&gî@ó0~?€âMëÃ}Å¿[¾Ym“`ý°²¯¾Ä&†}N`#bü=d©¯ácîQà1O„ÐÝ6FÁ“‚[º ѽryG-^ÐÄKë!T>>>>>endobj +2275 0 obj<>stream +xڍXÛNÜH}ç+J¼,‘† „„ä Ȏ” ƒV‘xé±{˜ÞØno·ÍÄ¿§ªÛ—1°»J‚»».§N*çïà׌ŽNøw’ïœ/vÞ^ÓlF‹ޜ|xO‹t¯t¶tFWÊ5SZX*~ÒEEÕÚø m4­Õ“¦\¥šLEI¦•Ã;U‘**UÅgóÚW´Ô”™D^§´²Ž`Æ5¶Ð¿yZ9­©öš¬{³økç€ögGÓCö^ت¿ÅF³lžLùÈb­9¨Äà~¥]îá9¥Ä©©Œ-¼8Kl٘âqB©ñ•3˚_ÉÁܦfe%V6ËìF<¼½<í è|}½º§¯W·gßèæþüÛü3áÏÅÕÝÅ(îÅÅí÷;:»úBŸ¯¯¾Ìóë«;º¼¾Å?o~̯¾NèËünq;?¿çWrðûõ—ùåüó?´µ@yÙOß"¤Ê23ÚSeÚÎ>:•E²ÕZ;ÚX÷“6k“¬J ¡˜â>•™Jê²A¹´äÌãº%²¶Y +K^1|\á\5\ÊG˜¨ >ÂVþv%ì ¯ºÐNetS/QÃ6j°'woB°»“‘Ã¥F&äôJ».3_#…AzœØDʧhW²\*fJÈa´¶)× +)k#hàÇÈ×Mo‘½ ó"€Ïb3äÕ!C™Ú| Ü6@AálėADðœÐŠJë„k@ÉT“684îCvx´ÅK¡ô[¼©òɃn +Á&:SÅc­õtäíaïwí´)Ô +•™t×Ù=R0E’Õ)l±C[s§å¦Š¯‹® ´;Œewúð†.êû}ïÇI¦©Ó^ZÖÓncë] lt~ŽL‰áÉþìàÝô„Ÿ%ÀM FÛX1UüßÖUN3³qP¶¼î{å§Óð©Q¬ÈÛ/O¾"?URq…\]<«)Œ²#dˆpÔ"0‘ÀX WÎæ£+#¯m”¶È2+ñ΂ZÊ_|e*ôVË®—ØM{-5~,”˜c]j]ŒÜ‰<‘Òyx3¥?׺Å;pÛÕèp1íÙ놟]§Vû±ÿ°µˆ×Ké%¢g7^JyWCs˜ÞÖ.aBœà (|Í­ÈMb¸àÍ8)š:Ÿ°.<¦±„ÏWÀÒ$µ­}bRÊCëàIɂäלšV"ŽòðÔ³zµ"Õ3&˜dÊä@ m”C{UÍ'ú©uÉýÉÂÀ’TÃ5bqc©¶Ô¼HG^å^,½.àNX¦zGÄ#cďCËð ÄL£mA%I³çèuܹ™=D€w»î}w8ýÀÇf}÷¶ ݕ­Ü#weàÑËvÊuãѨYÛV"DÀÀ1C`¡‰šh%¸–Q+qxj ׿ÒI«Zú"(ƒo‰â5¢Š|4ÁO€Æ½ÌÏv>Œ”»Zײ\ä!‰¾QÇ +³Õ¶“¸ž²%Þ5ZS¯n‰âåŒÝ‡ðxƒ3YX<”AjX‡Z¢{$"5mSJYÒÆp°ÕjhŠîk©îDú |]–‘€ül»°}¼Ò+Œ^Âl U`eeÎfò/•«ú¥‰Ÿ%\¶Fb,ö-[Ø÷¤¶« #5\€/bÁŸbÌڶᙞecX—Š=æækÛV»^µ½Ú¢²ì{õè4 Z³Ú.f»Y 3ÜcNh•òÊsÅ#Z†Eާ3«çf­ ž$“Э=àhŠqòQ0ÁñÆÒnLáúÀ¬lÿqçÈ-,Z—bmq¬v Yæ)縈X]¹{ÆÌ/ +[C's¦aØm¤3·t^Tòn)®â¤s:Œù×4ça¿`2N‹«qG²Øy\ßx S 7N O¬µ,?ÿ=Ÿ7E[“®Ü[½Weí8gô¶ÆêÉèÍ+zÿ|C¼ø•hQُd¶eK‰ÎVaSì+…xeþËÔ1&”GÊú¯…™½}}«é¶«¿kÃRWz®ãÀÖÐ^Ú!”®ï€èÝ^yØwÀál?ÐÐè%—yÉ_S řÛõ†DÚ·ë”æ@„7.¼VKô¯B%7ž-šœÕkš‡R\rPÊÛ¶YdàÌɾßïz|ØkšÝq…ž‰†ÎQ¾'íYàt±Å‚à—NÑìÖVP@`ý 5é㑂²ƒq¡ý(¬)ƒ-¯ÜFçä¸,’ÉÒ¥1|º§ëøKñúLÂ~)ÄY,¶ÿa‹×tÂgÃfôöòCüŸÁëŒNNØ3}¾¿¹£;»ª6üÙ}çÜÙßUQ«,0óøtÊ Òáß9>ñ:;¦ƒÿþŸ„‹ÅÎ;ÿ¯xämendstream +endobj +2276 0 obj +1793 +endobj +2277 0 obj<>>>>>endobj +2278 0 obj<>stream +xڝXÁnÜF ½û+xtyã]ol§9%“Hƒ´v|™•F»“HeFZ{ÿ¾I–F·(‚&õH"É÷HŽž,é–tµ¢‹KJ˓ww'/?¬i¹¤»œ.¯¯è.;­µ+÷ÆVžrëÈ6;í¨0©®¼Öžôc£«ŒKx@ºjŒÓô°³…NHñƒ]ëù©VéNô^»ÕÊ5äôV¹¬ÐÞ¿¸û~rNgˋŊÚœMЃ³&Ó,ºÇ«ËŚßÁf‚s2ž*ۈgSGCø²ÙáØë´föœʔäÌv×xB©Å«¾¡ƒm]Œ×¬û¦.ŽâáÚø«7äg!;6!ÊGíRãµ<ۂ-ä03¾qfÓ +: Í´3{՘½؊‚‘ïuä™ÑyÚ(¯3â°`髳[§Ê89Ÿ*RYfØ~B¥F5Ôv˙î=ª*ÔPæô³J¦ÙMîOONÕlGÜ¿àE{[´¥ßäëÔV‚¤¢Ô™iKʬ5Ý8SmŘ =æ²­pÇÝDÀ[…-?BdÒVÙ +èJîûª˜ö4N¼grF9ð2Òºk>³ŽBq‘ø}+Ó´g,¾RȘÈO#?·í¦Ÿ†›P­Åý‹'µôyOCÞÏ..ñóòB>½xªÅòõu½“†(ze©h‚Ñ€åBå˞‡ò¿_ªÒhlfr0?Ð E §3Á#ÊQ +ØHòÔºÆP‚Ô'Œ„$Îá±Å¶Á,⑬L5×Eëg.1 ¼·¨(kB›+–£ÎM%£•rKáën9Sc“f>C5…øŸ °ÈÁ\]²C Ñ.èwpmϧ1;k-$ӏ©®CKˆCk¹Òüf©©Ò¢Íô»ß0·‘^f½üpÝýfc¹Z/ðóèý·¯·tÛ/§lsžþPU«Š`ný]­Îù›_¾ÑǛ/7½ýL_¿½ûüé=Ί/·7üòúj ÓòâzÉ7w'žü­yà®endstream +endobj +2279 0 obj +1710 +endobj +2280 0 obj<>>>>>endobj +2281 0 obj<>stream +xڅXMoÛ8½çW{Ùpœ8MÝ=m‹¤Ðíf7éa\h‰²ÙJ¤JJqõï÷͐ԗÝ.Ú¦°<ä̼yóf”ï'+q?+ñzM³êäýÓÉùݕX­ÄSAÖ×oÅS~z+³ht¥Dg[áT®}ãô¦m”hvJ<8»u²줅 i:±·î›ØH¯raÍØäùՂ?:•éZ+Ó¼zúzr!ÎV¯——äH¶­d£3Y–Y)ý¢¼¢Ô™2^‰Âيo°Noµ‘eüŽ+2[w 1Š+›ë¢1óéÛÍW•5tFðÑ(WÁ§ÉqŸÉu£­ñKñ/2¯d'Œm„®j CJµhN9ÄJN36NI÷Yúßg>Õå2+l,õv×xèLÐp¡Ò&ø”N±O8¨q·Þ”@y)ƒŸ™6[DYÕ¥–&SbC‰j—ÏÜÕÒ58rŠÚ‹OÍ%™¡Øo.—×d·^ +z„'gë5=¸/Bþ@«ï­"'ˆ™ qñµÍ·$ Q2µ•YÔ²¡çÚ1ªdTD†ØšôÖ̂}>¥tK]i‚!§«¼o•' eatB5˜jDÏçÓýNñõ@#„i]®2Ù:•"™9åxö¨Èó+@$òÑ8™k" +4rÉ%@dBw"·\%õ#k}h“žªÃÙ¹ÓéMKq_ðÉLºkÄco© ÀÂ`:{]µe#²­G§à”vSêP/ZƒŒùö™Ïè‹é=¢V ˆad†K83sXÿnÔ S%˜ùJº8AŽ¥¸#Úþ`+PÓÄ¢XÚÔÝ{ۖ9ߋ€Pál'˦;+P¸±îD’ýÜ%J—0 >ÝïlÒ’ê„\ãAä’6ý§fçl»ÝQŠ1{Öƒ¯ö’ažùË8âT• ЛÀW6&¶QTB§ +'µA7p‹›™(GRKzÕ·éÍåòŠœ¾Útµº­ êP9k놀W,Ihˆ +BÐæE–:§´[$DI’”@¾‚Ä"kKéD¦]ÖV¾!mYA{#Kâ9ÓÐ1ÜÈý+ëYL#¦*ßGíssø($¿Œ_^®0÷¤ÌòT·ŽezŽ\ ämd2 +"Ó'JzB(ö†³Ô]i‘•RWÇ²ð`ˆ5NØPßb|†s說쨫 ‚a/|6du§¯ ­ÃÇ„†¢¢+ŠfOr8a’ï|£ª€Öˆ€¦î# Öh’ºE¿g}ÖNÂ+!+þDäó1¢,#hôQ%s%¶Ê(4Œj}Æ1Òk˜`¢m9¥Ãø¨Ú±ßHrçc™#' IÂtC>¤C8O¢A4Á¢0Ð2½£D®mBÁ^±³î<·&T*ÇdFpРNÃÀ{]–\;•â˜GŠ}PÑ2Kk‚T%5;ÑL³…íœËO³öwH%¿ÑM–@¯d¥B·î Xn€—z –œƒáVðÔ³H–ƒqo…ƒv!ÓsR’a‘Iú‹{ÒF¤HuD†"Ճ`U ÁJ§!=j¹Mw °uǍÇ×`5+$蹘‘€žŽ‘â×%YN¢¦b¯Ìdó4§ÉˆAEô‘¶Š×;ZJ§é󎈹_¶yèW*sŸæ‚f7ssrô`.‡×ðÕr\YÞïdAÙÐoÁÊ±2˜(/2¬"£Ô´É,Å]D¼GÑC…Ð +{GòM mlÞ͗ƒñz¾1>áäéÑcê“;„Ÿ?´5°âøèñ¢ik‹2j/^”óÊ¥ÄG’€þÀ"õ“E&¬YônB½Žÿ—â‘™\H­L½€µIÓ`CоÖÈ7 D ¶’¨Ä :á^% +ÅÇs:—<®ò‡=;„nc˜VLetHo|Yꤛ³#¿`EßÔ;[¬*( s¤jq+Y˜¶Ú(Çûâ˜Þ¾†¬š_˜¦¦¿nõ8XPÃ[BÜa~#m+Á—îûmÁC“G·`ô·°ei÷ibñ;Ô¼±&oT©ÿ“t§€­Kcsâ8ñ&Œ­fβ™«s å66R@«;†ÕlÁO /„:¾öÍÜ¥  ºîµÃ…%O{êÞJúöåÌh¬U˜<¼Ôá¹'õóS¥>ÕÉ T`5è¿` PÓ©É÷ßøÕUÊ{ƕ¶ù~öûÅH¯çËâ¯Ñ˜ùþ™Ù;±§\)juϓðàÝ:SuHŽB¦R.Å_x?¢¡ÏeJj€¾Ê‡25{+¶V–>,`Ð÷’è6,¨eËßâÕb. ÊéH¿­€½ŽM·2"Xì*Ûïu~'iñä/Šc´?² òWvQAÖË7½î®.‚ˆœß]ÇßÖ¬.o–k±F@l >|yxŒœ©@TÚìZY†;¯n–¡·—tæê’¾^] þøñóññöóí?|_Þºÿ ðïöóã-™Ý>ü}ò³l>^endstream +endobj +2282 0 obj +1854 +endobj +2283 0 obj<>>>>>endobj +2284 0 obj<>stream +xڅVÛrâF}÷WtíÓn°{}©< b€É +IÖńŠó `Å ‘‘0Åß§{F`Þ¤l—ÔsúôéÓ=þçÆ‚6~YðЁÛ{˜mnºÑÍ÷þXD |sÿøÑü«ëÁ˜s£É·èoŒ¸«"ðP³sߺ£ .·Yrˆ†üÀl"GØÜ yúçàõÁ²`ÀpЍ¡·¡iݶ:Ù÷‚s8<ãéÏüˆ»ø<‰(Bìî˜ïc*Öu88lÜ›ûQ p<ä.x”y,j1:-\"î@£Ûž? Ä`ÁÐsz<¹½ïHE¬!ú,ˆ‰â‹è]Vÿ……Xß‹hèÅÑ©JR¹ø)Ü^£†Ç%Aö~ÀC’ óŠ–Æ{ $j;qy6 ‹x®¡¼(†EžVô[¯Ûd&¢˜{Äl‚±®pÒÁò /"IÎ@WeÇ Àß y«†¨Û€ˆØÂ@„?K­šó³*vG̵uë/­Q爕Ãċ[¢ZNï"šäåÐã}nGâ݃˜3ŒG¼êYa†$sp¹u±`!^„­Õ ¸ÏD@ÚÚ^¦çê +›Ö}ëXí­{°¬Ðcý´iY­GzŒ†AÓò2aì:¤[ÀŸcã+R6@óS“μvU>’%WÔí×ÐøBÛO·fã¡#6‘×ýIeÐ"²a´Ê¥/±W£ÃºéÙE®BSF’$nÿ +¯ÇFlÀÃ3jZîò€9 }n úßã( ¿£0ŽÿsLfaÎçÀÐC„GSRù„V yß=ºyÕÖK ìõë±ëñÇ µû{,b„¬w9EÜE¡¯¦sÛvàŽ x:T÷†pM§I(½£DЃã*ÐÔg‰~íÉóF +;A ´ûϺl"Â×o í3}Ìl+OÔ0»©2ÇÜåxˆõ^„Þ!Õèa¢RÓ«ðª|jþŽ1ÿDžдžôܚUåd´’^‘Ô鞠Q +OÇÌ=Ò¼í˜KbàÆØ“n@óX7LÇåxQ\^0x´ó`è¼HU¤yü¾Ë$XOO– nÃÓ1öΤ±óíA¥ËU ¯_í×o:úJJóE¹O”„~¾ËæI‰ˆhØlvÚom3â?Rn¶k þ:™IhB¸KK ··m–¼(é܈´;–e¡$í‡ú“Õ`ø»T‡Ù¦l¥Ú¤e)çPæ0C†ds˜§E©Òé±1vŠŒ6ô2•E *_@¹B˜u:“Y!ažÏv™• ÀÃ0[%Ù2͖–”+ËKHÖë|/çÇÊ:–ÑñψPð»\IX¤ª(AɵL +$ö^i¬sIL5U‰:ÀÀwZ‚k¤ Ûm¦RáÑLå,Ù!1d°Ìeû´\;GÌ\ÍÓìú×¥¿ˆ¥æè+™l¦kym†êŸH³ÓB°Èl°%P›K?sY¤Ę̈]&oøpŸàï,Ð ó|CoŠ•ŽÇFh‰} ºlAVª¤(ë÷3•@&ÈLªd þnŠ<À9r!´4+e67™—»D%øYþfzWËv,¨ÙÄ*¢Øá!"qª;I'µ +Ør, lƒ*N?iöឆÆpŽýý´˜$Ûí¨Ùæ̹•³s*q2óÅXÕÿ; ىoC—ŒˆIv€Y¨Êf”h¿ÊÑ@É®\åªÀ$³t.)ÖØª“|³$«>ë’IÖZÖV™çuÆ+™Á^“¼‘+µzôöÆ>J.¤R4Q˜¿j[CÏÕV¡>-ð°ÿá‚§s7ž72)©X%玲g9Û f!\‘ÅíVùG-hCÔ=$Õ;ò‚t¡3íÓbE·Ê)µ’3™¾èNÍ(՜†T˼”¥Þ'ÕIô1~<;J1•y‘û/¼K`Ô/¬`fj È 2¹7ÕlU¾TɦøÍ8ãþ–åûS–yN +ʃ-¹¶vN(¥œ•fÌôî/t/3y&º’$éŒ Y˜L(Ú4“iK“ê2Ó[¢Êg¨²lñF¯ê+!§f*y¥{hδ 29qkœ}HU&¨Flñe:M×i™V (TÂf³«ÍhÝ=µ,¸º7+ìØ?®:ß¼Á£$Û%ksÛëC͇Nûx3ÿúF¾{¸Ã…¯ïnénžoþð/eendstream +endobj +2285 0 obj +1656 +endobj +2286 0 obj<>>>>>endobj +2287 0 obj<>stream +xڅX]7}ß_aõ*…@`µÐö ÐÒVÚÒmY„*ñâÌx2.ŽÚž ù÷=çzf2™ ­`¥Müqîǹç^ï?+õ ÿVêÅÿWۋ7wOß]ªÕJÝ5X¹zõRÝՏsk”³ë¨ãa¡BT¶Q‡Ð©m¨msP6/¿¿ûûâ™zòüjyÉýï°Ç|Õ۝3‹asmSŽvÝe£ª°³&©Ð¨“‹÷­Áç¨6Qg›ˆÓàG«ÆàÁëRV{oä\4•Å=>§}õbùœèÚ¹²Ánڜð«ÎjoÔFã ®Yª¿†»¶ú‹Q©‹¦lÂ!˜‘CXðrC Pi¯6FVU +]¬è@m–êWqlî¬ÿ›w1À­ÚÛܞz9:‚-÷¶æeŒÂÖ›*«Æ:'‡™“À>ZI£fÀÑ4VÏ¡ê&#²ð×úªZí7GŒ~“Ò¾&̱ŽÛWõߍ§6ì`¯Bhâ¶·~ñe¯}æù½ƒ=Hx¨I#ÃyÂn8£Z +÷A¥lvéGõùñêó÷¤ÏAÖg.ÂÔϏŸcCh8K³s "9[ŸÌÌè}k«Vؔd«3íÔNؔlðŒ‘Sæã)(Ñ?÷îµK`ùk4`Æ+B|”Fgƒ_˜{í3ф•‰Y[_RmîM<oTçkS|IÖÂ9æ~éqáAÀÅÿ&š£dí4éXo¬©Õú€ôm Kâ­Ú锰45Õ"1ß,>øÑ§žU7òµeñ‰¹%k ´‡‡I1Ð[û´vl²>ÇPwU1.Ðëv£Àqуh뇩›"è$‹élÞuY3ìÈøŽ;èPâ5°eÀ£ÑÙxQá,²Ý¡«É76sWŸ"›ZfSß[‹%5«-Šw3“YkÚS G‚°Āñrq×úÚB-:Z ¡ŠÔÞ ÊÕv ™2à?‘Áƒly' ™zX‹»hM&%䥺ãHH~‚IBÉäVC¸lV•3:NòV,±X›Á²šTœÌ~ÔÓ³K¢µ¤ÇxŠ—:7OÕo—ÿüþãh&:Œ¯\WÓKÒ·§¶eD½*ªð§Ðé%¯øI Èm·ªº)ȋ³J±‡Õ&ٍ/)äÊÙ|˜‚ìßMÔf!h¹é+í`JïvΊÏÙÑKAAEhë£k§`ôóŸÎB PÉÐ>&¡‰a{ê1ÂýÓR^@=èšIDÓ9' +:3¡þ²R·5cšAv/gSé‹ëZÈwÙÛ7Ïát6Pª£´Jf§ÑùQM%@ƒoŒõi^ ê -k×ÅRg¨!PÎk»$Õ2óHDvmòÞßë8½á Q …XºcõS“E>ມ'Þ Ïò÷Y—×c+šó«¡Ë¥íöµxl[V¢&&ñ÷ïA‡Ãv ­ +›ÐI÷؞ß¨r:H¢U"€ƒåKõKسYD¸#›¯¹£f©4Ät$3ç pÐ|5t-Æp~Y[ÅÜë¿Àd°7Ú{€r˜jN•ùıÓâ<[+P4q"ïÀµÔUíœXoL¥EJšÒúÈ ÿ„‹IdÿÔ;²®†žS Š¼Â!w&Ø[´ö£v§GýfÆöT¯waÇ^6Üɵc®¥À?q4e3õ0Ă¼ñAAk¦¦¶2Fl’£ÙJp¹ªîëëÌY®+Qˆ¦+å4¤nÜgk‰iœbß"êÕ¶ýçØàD£Ÿ'}~¶l_¸õ4DçzȎcèøô ŠLªÅË^êï8_Aü¸± ½½6Á¹°_ª[—•#•uæ$Ó?º7´ÙêØK´úŽ’§ÖºÌËSéþN ‡0&lYJ 8®ÚíÙú“¼4°˜õWüäM¢ÊW´Œôh$Ä$û6åu=ÎãúžÚ!&–ö¾ xQìËc|x7 ,kóíáê|‘‚Õm™„}9bç„M;d1«ˆaOß½êÿ±ºüa¹RWWWË+nTo?Þ~P¡½-U¶emÿ¦=ÊÓOÊ¡'/Ÿ?ã™ËK~ùbu©ä£L€×ï¯ÿ|}£n?¾¹ùõ­ÂÏõû×Üv}wñÇÅ¿Þendstream +endobj +2288 0 obj +1779 +endobj +2289 0 obj<>>>>>endobj +2290 0 obj<>stream +xڅWÛnÛ8}ÏW ü² ั›&íö)÷5:ÙØÁ¢@^h‰²¸‘H-IÙõ~ýÎ E[–,‰$Îå̙3Ãކp†ÿ†p9‚ϐ”G׳£O÷ß`8„Y†o.¾^Â,=žÝ½ü˜ÂÕänž&·ãÙøi2…û§üóùçxòЇÛñtö2¾~¥WüᏧÛñýøæŠœÌþF«—«§£‹Á9Ù=„WçÍ«c˜åÊÁ£J¤v®VÊRj¢ª +%xB¯Á™Ì¯„•P¨¹v «\%9$F{¡´Úx4U!™Â| >—ø¾Z[µÈ=yÅ0†Ÿ# +#7E*-üÁÏ,ˆÚçÆªñd%¬Gb­ô”‡R¬a.!UÎ[5¯=~Rk:Lö½´¥“áœEˆíAjiEÏõ¼PIÇuLõíXÎ@"ŠMö| †ÞÛÉîæW„ð¥HS+Ã…ƒÞÚÔ½Ac:‚{½ž”R0,‰Aû‰WFS˜³ZóCüD§Ÿ‡Tx••˜>zÀÀc?' õRj…E)֐~Ç÷+åóN^\°D°§Êš…ˆÌÛq¨S ;SʕqØûÛ 9̌-Aþ’Iíż®›ã Qï5@÷ú_aV}°2“vK–]î1“\ûÞ0'ÇüæRêÅu²“zˆ0ۘ ªfJ$xÜÅ\*¦Të ¹¦¸Ð¸Z"BK" î6…B¬~ïúͅ§âcfHÉ>”O6¼'Švý@el,·òýÎRÚ9º.|¥IUÖ,² ëÜb>… d#A1byÔ™ 4£ú§zQ‹…`ÅÿV*-2„¬Ñ„i(uÚÈԘ²*•o^ë½ÜCƒA¯koðvÒáDojj›SSÙ#E˜BAÈNÅ !j3Á˜†MèûR¼–»˜`~Êàží5,êwbLLYÒ»7!ÄÞ+ +vÒ~ñástT#¹I_¢„õQºjÇ<ΙD1´JZÇo*3,?ã–)´Ôœf‰U•wÔs)å@¬)€BUM)¨çЧÇXD$ m²ÜlÕ%zÈMCn¡™¸ˆZÛBÑtG DšàçÈÁ(Í[±ûNŽ×ü©´›ªÂ\úBrQó‹ÄS´¶ÖLÅóí¶:!Ǩš^‚pö9:tS!õ2kÊ [ÊíÕ7m4Qž:Ê1 ¨†ü‹óÊ£tDÂÒl …^IüOûˆ4)bóë&\ĪÛ G¤YY„Ÿ͆¿rËÔÁÖ8¡Ø…#ï+zÞ6„vó&fÌ&0æÎިڞ|8҇{#ý§©ylA‚¼o4v«Cø’ù´ƒÁovŠ5<¬d"I=I×öä‚:§”©ªË>e·T¤3œ¥ZU*©MíŠ,k*K}†O*šÕ.'ô¤à͂coµG¨ÛÍêÑdšB•´\d€R‰úç×ßá]ʊ𙨅!s!FÖ'j×vo°I~Öu.æNê„)Dyouà!‘í†ÒØ- ’‰ç@ ýnÛoê˜ » [™ ÆÊ×[¼ˆ ÉJOº’܆v[7VB!—ªQJ8ÞI1÷Íւ]!azÑÈ'Eñ1G²‘Eib ØÃ$Œãº3H}ŽKÓ#$¸×'`p¨Xzv'N\Q,˜ÓŽ!ˆ9jҖ⇂œ·ËRÊÀ·¡ãm.å¹áxÕÀ;ÀÎjâ¡Íó³vž$Om‚bo©b°O‡ghàŒi9zÂviD–AªGiñÌÚ:£)…DXSR/ÉdlGÛëzld¦BÚ2ƒ¸Øp¥Ü´G8Ó;„øÙ¼‰v§Ÿ¿ .>ˆu…—¹³1„½¸ÙÍS"¶6±Ih)âþV6Ü%ˆ_zv¢í4g ӍԴa¡Ž3ꑨBy¾]¿ÈåÖf¼Ù¹ÃžÈû5åÅ«ÈÉÕ|íâ!-ôÿoø»ãcM¿½&Ç:j5_ì*Áw˜U.õΙýÙ«ôÒ¼ÓÐöôí:Vw5¢âÂ\æI˜Ì°-=¥€øÕVrTý‰\ò}RC;~ˆÈ±ŽKο¹@´Ñb¬ú»ñâè§Æªðªçi£öÆ?H!ÏYtl™AAÎ[™½«…•%_aikD¦gu±!ê—Ñà+o{¡þŸî¿6ª6†p1â»:ܼ>Oa[ó9”¦¤²ÿºE0wþ œ^ޏQ&¯ð8¾~¹zù w“»—«Gx~½~ßà㛻ÉôŽ_žc|àü =¸›ýyôÍmÈendstream +endobj +2291 0 obj +1720 +endobj +2292 0 obj<>>>>>endobj +2293 0 obj<>stream +xڕXQoÓH~ï¯ñÔJi m¯ÀÝå +W©p=tBêËÆ^' ¶×Ý]'äßß7³vjoZàªèÚ;óÍ73ߌ¹?˜Ñ ü™Ñé9ÿͪƒ‹ùÁówg4›Ñ¼à£óW/ižÞ¾³ŽôwU5¥ž¢¢­³`lM¦Æo¥Y8å¶,e¶jÚ Éß·ÊirÖO+åñVÓºÆzMa¥OºÆér{4ÿzð‚Žg§ÓöµÑeyœëÂÔ:‡ù\7?ê@¶ÀUMªiJ“)ö>¥ùJ;]XP·íÂëê$'§ï[X÷ћªS/+Ǿå_àm‚ jQjj=ŽˆlÀ»ÇUë-4نUåïdö°QnµOœÖ68ے ¹1à)±ïƒ)ËGùœÞ±ácäçøä|zƦA¨í¢®@—0’öSÙÜãÆºo$ùجl©§tUa~ñXBîHô‘ooÀ9à'åڙ5çl%n®c% Dêœ2U3KN+–“Á.œ¹$³ü²×r +‘²;Ïu{•×åZûIâOꘒk“éÚëèÏ è ]å' ŸÑ)àÊۅ¶a[ÛRn|pfÁ ³;&f dš¸¾hÃS·É«jà¦`Hʶã?M¶âÒW‘Ô…âò²õ˜:ü’ÒÜû‘ÚŒ¥-î*1ڐèãCr6}ƒ‡Æ{‡–!‹½+/¡Sô÷€|¤TÇò‰½F²Ãªõ̬V‰ôZC$d§—Êå¥ö‚—hã,H2¡§ó¡l[dˈpÂØ—©Ã®Ýï q)•©È™å +™F(§ Aráúc¼&Ünœ °³Sîb¼÷G2 &CÇ&Æõ]»Ìø˜Y±å­Ζr˜fEš½¿Ö[Y2òu_Ñ}²÷k¹O}Jδ5Ï ÛŸP…®!µ\2·½GUÇJÀLßcEV£ƒ»Cà“ÓX‡ ¢ÇŒÜñ¢µ-[¹Ô´Ö©¥;¢¢Ò¹i+Ñ¿ʙz)Æh[t¾{„ +ŸÙF§,Ä<÷²›KŠN»GýÈ:¤/èËJmY›9aŒ{ƒ1ç¦f.ÞüLïu­*é¦] z§(´ÊS0b5A¾Dšk¤¼Ùöú”Òܲ±‰h†t¬*?c!$˜îFÆ›´°·ñ1Þ߯woÔ_lBèT/sr2 +rìsŠ:¹â<×zDý HKxgîÿ°+;AÓh –\Ú/J*Ï ßèÌÛpg>>>>>endobj +2296 0 obj<>stream +xÚ}WMo9 ½çW½l8n¦N»{J‹´ Ûí6é|‘gdÚɕ4ñúßï#5ßq‹I쑏ä#õãdA/ð³ « z¹¤¬:yûpòüý%-ô°Á“åë+zÈO£¯5™@:ìtfTY(˜­5“)Él(šöÎ'|AkM¥±ßuN{ WGy|gÖ^ù̜€]ƒ.7¤pLޙŸ=|;yA狗ó öÿ€wcáu(\™Óbcѱ«œu‘vø`ë@¹Þ ë•jß¼XÎ/Ùàí†B°nýMg‘6¦ÔTÈY·u¥=¢+i§¼ªtÔ>Ì(WQQ€Ã,ÖAª‚ °’“Ê2‚ã·øc¨ÀU*ó.L‚é š4mj›Eãl ÕiԖ¹cžJXÄKøk·±XÍ˜4+Ì)¹Dâ0ÐP[ð=ê|F^o•ÏÙÐï óHFäs%ÞäÄ*PçÍ£Šæ1%hX7ÿ鬎j C”9•±ÆnSÿ™Ë5íÊ:ÐÎùN8qܔJ „È¿7LFmá—îµPAËùêl’³¿ìٝMËg¹a¥«6¤y@Afe]G=dMP§‚jì Ž f~ˆ +¨$¤"]ÛéŸQ£b2¨ÊàŽ†8ë2ÿ\½øÿ0-ßõRnPܱ1¬®½{Ñ?œg!.0¶gGr$â$ÙëRÐå'¡<¿xՃ|Ïy +—l䀾xEÍí­ßûüüý¬Fá’=‹* `Ë`K1ÊÌWr…[að6²æ6Ž€}m,«&óµ:ëDþIK~ë¬Ί”­NáA@ßµ·ºl.[ÝÓ½ÛÄ=R`ýô—²µ*SÛÊ¡ó«‹|æÃÇ/twûöóõç¯ôáæãÍçë;úôåíÝí;|ýîæãý º¼º„°ÊË+þâæá䟓ÿÚöÅendstream +endobj +2297 0 obj +1743 +endobj +2298 0 obj<>>>>>endobj +2299 0 obj<>stream +xÚ¥XßoÓH~ï_1oW¤&4¥Úã PCê!ÊR_Öö:Y°½fwݐÿþ¾™];Ž“ “N  öîüøæ›oÆü8[Ð%~-èŒçõٛ‡³ç¾¤Å‚J¼YÞ¼¤‡âüåüÙÃ7¼¸N/Îé«í¨V[j+•kªLæ”ÛR©rS™`´§°V”Ó¤hcÝwʔ×Ù/4ݧóÞz–mgü7™g½iVÕ`½^Òlñb~Åa»Ò¸îhcš¬üóˆëÆÊí“vp˜máÐxxÌuãõ©¦ ÂøàLÖM¾Ë×p›Û:3 Î'sÏ­³Oˆ±ˆiq +^·Ê)XŒ$gKyy:cvŸŒßø‰w9¹1^S«]mBÐELd?¬-jRX¶“aÃÿšþ¶†êή–ók6÷:Gº­j¶Æ4õ.CÒnûP½ª‘ÔuMoey´O§’Ó—§î| l&œtM+ì' kßÇòYç µ'•¡ÆBÌÙâ™õ>՜ø¡<›½¸/ùá;ó¤®A6)BÄT‚œ!ÐÁEµ?5õ9FêIæ6\'ý}bTƒ6ÀY*MSˆ՗ƒ_Һú )ßŐm³Ý5íìê÷]Ú7'76I‹k[˜û.«ú.©Ló]й ëÆý2æ²þ™ëMî9?§½¯¶#'hôµÜuâœ^ƒ +\®acÇp ó?Ã:hŸ'kR¿lLU‘ê‚­ê¯*ÌÜ2 72ÚǑ3«uðt,Þ¿ìFCT.„ +ܧ›µ¥µ¯œÎ5ø5Myà˜„Í^P JŸ:ˆÁqYÄ&22Ü0òÎïÂ,È[ª,¨ÜE½R8çN×`‹jÙÁ.S¬2ªÉõ|Ÿ.—;]¸=JÖpŽÊéaIE…@Y®ü¾²BºsA1&Àw¼Y1“M¡‡ç,K¤+ä¼rªܸ4\Î×{ÖTø‹\øEÍñÆÀ05O(íSlQCÕK†X›Ì„8*µ!SNœ'!å Žd*FF{"i˜ˆÁqJãøøçq„çxËJø…ãñم` •S{zÆp¸ŒQFôLˆÙÛÈtp[‰ÒÉOr K„.M†§ƒn/~Û%7[ðÝ偟ä”xJ¬;âSG¾€UÇËz4ÁÄ?¢ º Ò¾×ÞM!Êú:+v¤Œcô(:¬Joàx¢]t# Ú¡³¿ÒtÙ7ÍCÃN——8–Ôc¾'ʦn-SY—“± m…ÿÄá”ÿ°ÿ ò«]Îâ§Å4é(iÒjÀ¹kšù¤·} Û&ÃêÅäÐ þ̹ê;ÝH«”+ý v¿/N`q@€÷å ¯¸ú£Ó‰ÒüYÓ·®XÕ\N&@Ué•ê÷«̀ç¦)Ôý¡21Å&ĔÇñÇsd7£2µ4?¢ïMyßiÏLõCK!”cš>žcx‹y@ô®`MS+§‡H†YöøLV‡ƒ©Ð§ÐÔ!mƒËIG ±·½aØv>¶Ë@ÙÓwçøˆªæªa[ãý×r€…À¾ä•¼î*(Œ¶ÏsQ‹  pl2F½ ‡rY²¦KìΈdÖÖ;jƒŠÀU5§?™¥?È œ ó&3õõtµ]UˆÝ¸A“³[U…í¬DáÆú3Zâ{—(6«iXs[òÌO*Bq¾#R<«âÄ+kwzÖÎv«5§˜²Íiðj£ffbìëM^6•l‰ã5AŽe"ø˜BS~â0À-, Q~‘Ú<]ìûœá:¶Öíó7ï½k ߦyR•)˜ë]¥B+–ŽÈ 1Á‘w• 1.ïj/C+ju¦*þaʏ´éîœèUS¤£m«´LO …P8?v×ŸÈÊqþ oÙé™l»íœ(ð4}EA»ÄSù)JPʘéçà=ƒ[aw?ÊñPËëƒÉÀŠ…'AÕùø`“²ÝÅ{¯öCYsÏ2 œø(^ø |$kÆcå’EùœÛ'ν-ÆÅn'~뱘YƒYn4¸¸5µ²“3´u¼`1°ô·`¡-ŽÇ5°VÅÔåJ7ÝàI¤0¹Lã„×à©WD}ž|íÆf’³** ÎÇI…XVpãP†˜¼P L¼Jßv]ۇ‚UbmÝóÂ6q(0sù?*J’}üZhNj»@n÷•5F~°ÄØw‚™í!…¸D©Nۀ„™¯­Iûûˆ¼“7A­¾ó]+.Ñy¥Ñ‘6†“ðÂN.'3}8‹ãšáCß ‹êxìߤѾ¸¾/h¹\ÆPzûåãgúÜWñ£³ØCêZ;ÏTéT¿gåÒìåÕ%ß¹¾á‡WËó[’ï>|¡û÷o>½þô•ÞÝ}¸ûôúž>~ysÿþ-¿½ûðùŽ/Ü=œýsö/gågèendstream +endobj +2300 0 obj +1824 +endobj +2301 0 obj<>>>>>endobj +2302 0 obj<>stream +xڅVMsÚH½ûWtù”Ta¯Ôž„ì© ëÃU¹4m„†•„‰ÿý¾I„- šéî×ï½nñïـ>ão@7—ôåšë³axöi|Cƒ…Kœ\½¡0ù0¸ì ÿÁÉUsòä’ª•¢$-«"o«TççÉ']жT¤ëc'qñBiI…⛋J%”æ´PEó½ÍñX•¤R4¡M\©¼*Ió7®û™._ú—Œd¡7/Eú´ªÓTªXÆ UöL1ƒ43z½D+%Hº[iÚd|óÕ6çÃjtNºP9p¯ãŠ“­t +«ß›,]¤=)ýTěUº@¥£ö³tV±ù¨~/²m’æOÈ®‘öµÍ•Ïâê86ª@8÷¥ó Œu€x­‘qOY®+äږM9•ôIæTn+Zĥ귖æ ]ltvkðÆ%¥KÚ ?­Í·ç:y©eÝçl\±÷ËÅåuÿÊ8æË‰cB$JQ —Õ..ð $5æ}³gi¹‚SžÓR%­rµ£gU”¸Vv}u«rU@‡)‡.:¨ÛƗ…^S•®UÚüïSÀ%Þ¥YFsE%HÉâ‚=ZnRb‚PrÖmD ¤Ë¥*NIKžq8 …àÒÜzž©µq÷B瘃¼ì7‘-y"º¦[ã)}†*±± <µIl­öF¾]ÏUÑoG²å¦Ü¨EºdŸÄ«­Œï𵃷Wo`xvŠ&-è<Î_(ƒ}Š6ßy^ô–Vñ³ª'pcÄDú¥Î2½«gðvir å$åKÝâÍødñ+Ë̝n½—`aTpÖ -‰VÝÚ²^³B!$œX®m¤ïXƒy¡™á ~œÑáùô +‰±°Cù÷ ‚h"͂ÐÐê8ä +p@øÒ6|ùbjIÿ”[Ûó}Îé¹X­×§«Õeۊ¶aä:̜/î#ó†‰9½…ýY¦C·=JÇéàa_t Ø3 p°7à ÆöhbÍhâäxÖX´“ hdúf9v&´Û5ô˜Ñ!ÈÉô²FÖĺA¯ëÈֈÖ­p…o9= +¦Â–üç8Ìa趇p±yð II\„ ÝáŒÂÖ)¼L-ÝÖ§ÀÕ]0? œŽD÷'‹ð4Ah‘iÿ‡‚c}á‚h³ ,ێ|ì¾Á€DØÒ­µ5]Ì>0IÔ®#-éDþ‰ïфñÿ«®¤71ÄâçǞñÉ1pØw'èhÍè’®Y£i¶ˆ)Û#ô#6½&_£Gcño§ö5& cV!ë9’<2Aóµ‰\}ëèžrÙÑ4Ø¿d§õ¯‰5~Ñ$ηqÆÑuÐÅÍåg޹u£W¦[a 1L틄ƒ®n®PÂ\}ã"<»?û~RiÄendstream +endobj +2303 0 obj +1610 +endobj +2304 0 obj<>>>>>endobj +2305 0 obj<>stream +xÚ-Ë»‚0…á½OqFÀe¤M%$Ø`/ƒc£`bDbÕøú‚šs¦?ùŽcH³éǞpKÛ ƒíÀ–y̰N(ìiá3tÏ·-š0œƒïû6<°ó·—¿Îí…D?ý͊N1ÉÒ8Ç7”Ê¡®¸.ô¥TR5ÇëJŒYHeä¤%{ò 'óendstream +endobj +2306 0 obj +141 +endobj +2307 0 obj<>>>>>endobj +2308 0 obj<>stream +xÚµ•Á’š@†ï>E7 +š›R±Ê(Ü䐪-Æ8É8C˜!›}ûô€¬¥㦊'èŸþºÿn†¼\<Ž€ì³tðúÝ<Ò- o=cH‹›XJ¡t&´z•~C•®kT–‘YCß³=£LwLAV–Tìp¦4Þrr zGtIð.ӐU +ºe‚?6Šp'0çv‹™€Œƒ Ïö ¢QœUƒ2¿“9öÈÈîh¥˜°¬÷9­N‹F™´åRhCÎ!Ô¤¿¿‹ÖÉ|µ<}ëæ©|0M–ËL3ñÕ*%Ãg¢AEˊ**L¤é›Ÿ‡bZ †KêªB™a`=î°5ðTi@®í¸Ž;FvÇìªuª“»6Êìgfx“Ö³¸Â +1]˜•YÎ8ӌª´$^ϗi´¾d‰:–¤£‚qôƶùºü_úß½{ëšQ:ø8ø w€æendstream +endobj +2309 0 obj +581 +endobj +2310 0 obj<>>>>>endobj +2311 0 obj<>stream +xÚµ˜]“š0†ïý¹Ü^h (½SW»Ìèbv{Ñ'bд@,„Ým}OD·u´”­aôB9'y^Îä„7|oaԅFº!¿aÒú­÷¸‚‘ÉK†e"}3 +æÞr¾pîýñb9rƋwþWÈì2oPÍ3– +𡐤hWò'šåˆ§ˆ.tÊ!áaHÛìXÀ†É¿h†‰Êà‘,cm¬w´3øÐ¹¿­f¯XºVŠô܅_Ìy&Ô"gƒéô%–¿euºf;$8²_p±4ÜÒ\ÙøÖ foRe<)…€ l½hjM‹ã7 ŠI¶ˆØBH½ž‡Á §u%=‘Œ‘UL‡@‘ ¨U©2g?UIrfó©3r.,Z'G †%»˜… Z4&¹"¦;÷÷Þ;GâñªOË"ì ²#+3ñÔ@¯îã²oE--6‚¥%ƒš:ښÝéɌqò5K7ù©„.d¼nahM#–Ò|¯&âq̟a +·$#¡T–Sèa"ØÀÒ\TäN‹Ûb[3J꾁·x#Ç9¿ùÀCûÈ)⺊þdi]@ù“¶õ[<”>>>>>endobj +2314 0 obj<>stream +xÚµXMsÛ6½ûWàVç ÉR\ôFSÌ)E2$èԝÌh`”ÐP€‚vÝ_ßI{&1”¦e|±Mowñöí¾œLÑüLÑå ½¿@Åî䆜L×hzŽHO.®à—ò4ÓT· òeɚwä/XrަÓ~Éhvi–-C•¬kùÄÅ5ý …yT †Ó­¬DϨÿÈÙð‘Ó­Öû|_RÍ>~z÷5Âéo_/†8G³‹q×-!ɧiœ~ó! ¦Ÿ¤úŒ˜RR!Y­R¬ìWÃÊÑåø +’€o}š]\~—y6š¾Ï^±ü8"A”ã·p¾š‹Ö¤Ùì¥h Jîy í•üûÙ 7þý-bœ ޲É“É-öæ“$ÎȄ¤ž¡ð»%z¢ jÚ¢`MSµµ[ê)öž¿#ÉÉÏÀó|'VÀ91ù)9F1Y{9¹Ó€x$¸³ìs *©vTs)oÄ/ÑVo¥âÀxþÈá;‚ሼÅÍ^3|IÜ *Å&‡Ñ ›™Ð]mÐLO+ƒuƒM¼”^x8õ3¢hO•æ´F¯ÙDÁÙ#+' „åÂ*I„xí߯³·1¬ÚZó=ôÁf[àKËGèøÏ× NW^ه÷nˢݙÊo!靄ŒÑžßü¯~>:Á«$N½4øAtÍv{©¨âŽèÆë˜Üb‹RgŒ!½å ’z˪¹ø<yσE`…a•R,yÅ9gx¤ñ÷6&5µ0 h?–ˆv}Ü'œ§ô7‡NþãÌÒJ7´< +kóhÄ?mµÌÅ ÿ²¼¦·•ލ‰w¿‚éÒ RëÜ¡ÏWMŽÜu°/âô&˜Ïqda‹T¼,™8öî’.â<²U5 :Ù3$­dë(ö+ û7ï§[ÆmÕ\1ØÅFZ‡I‘s,i× qï&´LÒp<(ç^ӇÚmpví×Mn Là{ÆYÓµ tÚðâe†£ôÚpM‚ŽsK;¦}+"ÍwÐ)²Õ®Ftþwp ±†ÕÕ¨¢ªyætㄸŒ#lÓnõšmæÅF +º'ê6'B-ÉíwÚÞÿӛ“š‰Þ"ðöLÀIÜ;xs9HR ž‡ˆÄ †’wª(L“#q'Ž×¡—.ñá]5ÌÕfŽHTSµqkP™3Ž–v êp¤#sò(Ë0`æAŠæGîKŠæ9Ì+hhN‘~Þ3³©­hÚ=øWÿ™áô§‡ŽŒðJ °MÏêîà謁Á +ܦ™eV+žºU½á;0f¤9&i\ÁÎj½{»+؀wíSSI°ÏÆÜyAh—x£¼v>B§8KýØa]öÉ•¬èZô8’köò•Èoq»“>°¦1ˆf;ÿc_n\F³+@Í®ûûguùc7.U·Qài—ÂÎ.²ÃÂÌ¥Œ(©*ûP‡¸èÿœN¦ÿuÑf:œ#t*ZæžMªú™> +©Ø´ÔQ¡¾‚LÒv^S|¹žrƒìîá ~·óG€ƒAaߎ忒ø€®†‡ÓÙÙø]\u,A~žd(“•~2Ü´Qt·ž¢-í.LFÓóëñ¾:;³]÷_ž¿ÀýúÞü““'ÿmOZÐendstream +endobj +2315 0 obj +1271 +endobj +2316 0 obj<>>>>>endobj +2317 0 obj<>stream +xÚ­—]sâ6†ïó+t¹½0 „…Ð^) À‘][NšNg<Âà]#³²¼Ùüû›À´ÃÀZ3€Ï±žó!¿:|»é¢[xuÑÝ zÇۛvóë®t[U—÷CĒOsƼhjg]Êe¡cwbÓÙ/ì ÜÒ¿å²Ð8—ZHmçI*×{øÝÃvî ‹þÓ ÑÞx V6«{×靀:˜ÎB<#§¡—ë’¯…I(¡36?ƒr­7&î3Û¥gyÌušKƒÐÅäóiÞÑhåCϴЇšì{ñÎÐØÛÎ$ì‰øÁÙÖ= U˜éܳ†¼&\›Ègîìãâó¼Ð·§ÑÄ~L¢À¦ã†4앵õX¥"±‚TÆÂ 6¤€C¹5~$ċ°c?5…ØY8K¿›98`Çâ~d9¼ÐÇšÀÙô±’ʯ&?©ƒõï„™!ŸL‰Oü€X %”ó_"Äæ^=ù±@«<ËòWh%Š‹¡D¬R)WŠ¿¡¬^üª ×ü·ÿWFI«78F-ð_ŋ†ìüGº-·(«§*”¯—ˆk­Òe©’|ûÓí>€Ÿ°’à4Z–Û¥Pºڂï<+Eô†kC8K”à J!2øö ŒºsY›úÿiSo´/ã뢡\ÃCÌ Ï¢¿‰ï6l•4Kb®¤ùze݄BpoDñ;âY‘£²à‘ÃåW°¡ÐZå宨k{(lѦ¨U€®Güj ùÕa½—°†.”ï„j¥âôîÃÅÐ/ù²-ŽÐÉÅ8!“¶8Ï·i£´Ÿ@îT*[¨ýÒ ô<×g0*Í|7ô. ”E¹ÛåJ‹$ªwšÉPêg÷§B©MmC™)vq “¼Ìtû +>>>>>endobj +2320 0 obj<>stream +xÚ­—]s¢0†ïý¹ìά®PëÇ%ETf(„ÝíÌÎ8)DM ĆЮÿ~•ÚZڅ…ñBMNΓ÷ðæD[ +芗*¸ìƒ n]ÃÖ·‰Q\É¡þp`xa:ÎjÓ¥aù‹/ð^ÄôŽ1  Zƒeà EN]¾Ûb€“,>Çàö 3<‘ð·Ú€ÃdN“små²£¾zÐ5­iidÊIÖu¡c ¥‘!â¸.Ð5<{îCÓ¶JcNi”qB“Úp͚–—ËP²®­W·çsC¯¤7 Q„ƒ&ôBãœkLÅñ¡ú¶²´…Q œ 7–Š+©mBi%•ußÛŸ¶;.Í|À»gʺXß5K#3FÀyų́P[Mƒ ®_`}¦¹žQÞEÁ±×6’<.¾V¡=É㒡úja. xë”Ç$ÆòC ð(½ý¤:ж:êôd„ûÒсŸž¾EwEàþ*†|&`¿iq…,Ã]š–>;ß4JÂϖèï®ô€&)G OAºÅYí@Hŗ-f€$ÁfŸ0‘k»§8Ი}•wÔVöì'í:oµwOº'$!éF\۟)^åAyÝóíßQô*€ŠM!YÆp +î°Ü¤x`1(-Éîé]çm=Ä/¶Ú?ìG–fbZ¦7[Z¶Uà€1 =ëXíÈñ æÌ HGÛç{näøöh'“Oµ9Œnÿ0Ü÷> 5‡¹6­‚–M„;ËC>86#ÂÉ}âKz +;w&?›–¢”ùۅ®f4[‹Féê”OtÕ±§kEÝmÔ!^3,t4KÄ1n žIZ«§º†p„g”E7‰ü¸œÊðùÿF¹ÉPD8ÁŸ¹äq³+rHˆSÂDkÊCŽ.يÿ1ü>¹ñµ¹ o—cW›¨3´âyÞ:…Ì9–í.´y‘+Y,:pƒ¤™9-èR3²ÞT  “ŠÚíŒ@¿/cDÐ}Ç]ñgÄ0p]3ǘ¥`‘]®n+½QGyÕîGWsoÐË¡WWrÀ€­›Ö_k^àendstream +endobj +2321 0 obj +797 +endobj +2322 0 obj<>>>>>endobj +2323 0 obj<>stream +xÚ­˜Ñr¢0†ï}Š\î^à +µV/Rk‡ + ¡W;ãDˆ-HhíìÛo‚`ëT”-L;Smùòçä?'ú:ÐÁHþèàj¢~£Ý`Ž¿ng@´•#“©|ÿ¸gä8'â'z‘c ëû͸Q虀$Txô `N@!H r8É8$ÍA.C£‚sõúðÈp?祥W®E3&Ò½ô¼õ½;_{pe/W‹ãüP‹KÈH'éÓ~<ªÆµ›áT®RNóǘ܀cŠÓô«¡ñs»‘ñLhÜàù®ƒà¬Î""Djäzl$r–e¤³&Ë\YÐq΀"œF„Òî(sîúè oÏ{Pä>x<ŠØ.£¤ª6”fL%F3fû£íñ$Í ¿l­¬ +üO{=vÁbž¿\!诗¶¿j®W*u'1%]v·óÁ'\?^¨¡~øDl´ºá8OXz.¥¬ªÓyœBü†Š7”¹ü`Ñ&‹ê7(l“ò·ýe3â0ø=£é,mÁÓ:1MbeÕÀúŠ +d“ ˜EÅ®<L¾ëy2YMŽõÚ·€†=,‹wÆ¢}@È_ÎCƒ¯¬É{<±ƒMDØ`Jµ3«®S—֕½•w®cŸÎÜ£êTw«®ùó¡Í Áh>¡ å4uËêŽ +é£&”ìˆ\åïÐÄ»ò<3”ªô¨Œ¸(¥Uyë¨L֏fԇ¸ —׃˜^è/`ƒ¼‚?•ÅX€-g»²{½¤ ÝÊV;/½{!hQc‚ÞkÌá~z^y¿UM0¼ä~QdYyÛ­îß]…zA¹ ޚ¡ƒNSUbc²ÅÍå_‘'iy%é ­´·ª±•ònJMÛn¶ǀq°cq²ýÛݱ%Іê£D3Ó&ªõS[j9fÀV;Q,龡%òòv–¸>6³wØÊ¶ i5¨£á Lf£áDEÅÛæïês–ÇÙÇ»>>>>>endobj +2326 0 obj<>stream +xÚµX[sâ6~ϯ8oÝÎ +„BòhŒ’õl¯/̤ÓFœÚ+Éa²¿¾G¶Ù܀Ð5Bl‰ï;÷Ë·‹.tðӅa.ä£èâ÷|҅he ®†-?Ù±Î-Û&~4ÿâÂ_£<ׯÏ}‚XIÂ6ÄBà@a#S®™!!ɨRՕ¤¾Ò¶¯úïÞ`ÕË®y×ê^¶{? ò…؇ öÀ’ÿ :$Ñ|Ln¬x½‡™½f°d+Zdÿ*rªSÁÞ– 3Ç&{ä½EP +Yª4ˆÐ,CØÇ4aª1¤ïOÂÃsÍÀ¦ÞŒk¾›ŠG†hhLпp¶ýZ½†n¿|Ù»BÄVïºÝ7'BMu¡À˝¢v°<4|q$1G€J’éBr¶„ÅS)·ãûøì[|TûµŒ+­Þ ‚ÂcsïÏ}ŽZ^E€|“1¿»Mõ¸&¥?­Ò +oÆ£0:uQhP"G=k-SüÁ#ÍðlJ­Šê[ããeCF¶çÞLû'IKðU–& ‰Œ¬1&¯1Ù§hÍv&…-U° °n¼`äŒÇÄ}t' +X +þ‹†55>Ž S)ã交 D!ÖÛõ¢¹GŸ‰9¶‘ñ~Ʊ¹À.˜ë4¡Fý+L–ç&âÎ_‡Xì™~GxëµBÎHÂ÷ÂÐMÈQ³#ºØ0Y¦H(7ÌìÙ3›ˆœ)ñâ=ngNs&ÐçE’R6ƒ1²Þx±;>$h¥ÎÒÁx+QðF€·žK>ÀZ#Ö½àèè[úÔ«ݹqëèîãÖB@Få=;è̚ÄÇÝÇ$)MSS%h•FхiE¥àÿp±å» WL>2Ù„ÖØ³ã)*Â䙩u -ERäÙ&¦sd’VFWÅf#¤®ªÙyèXQ8£8"áþ ŸJ£•ç|nROž*•òû&°qàÌCû3™° ¾•¬“·²7µ?[vƒû1“5•Šéó,ŸÆ&ì\Ƚõ²èÔæMÏ-óJû¾ì­&FnµaIºJÑÎ&abô+“FÏ«…gB$¼à€jxd²¤š¾ K^õWg ¼cD~„ߐ¢~ôYȘ‰, ‘‘,ú§DÙêWUÜfÖq܈®59F¢J4À8¢›Á¬RF9£qš57Žç“ÀŠNtØ}Uÿœî’ÀÌmóصf–3±Nh?Œ~p~34 +NišÑEÖ¨|ÍHpj¿˜i­töð­ÆØcî]ЦÐõûÖK;GD¦(¾Ü¢€­ËQN*Ÿê=WKV-L÷ö@¢xkw§åËc¹Íh‚ïedÎGqxwü¢PÚ´R»f¦ŸÛ–k“Éäã4C¾iŒ•w²¬™Ö§ñ$rüI¹[O*_UjZ +öÊå!/2bÿª®¡;|±t¸ìU›ßƒ-¸Ò”kõz=ÑÁSö`wê¦êÕfUXPƯ5`îî¢ý­„I l¶SX°ý‚U&hé^éx‘/PzÉLå4³ ¾1!g[“êþq—ʶ6-Åè<«ýU[i–;¿A=\gOÐo_Ö{’«šV·ÝîÂàº_Ý.o@(VzkšC_Š{IóaJyA3s»U]j {}›œþ°¿³ÈCó€D_/þ b¸†endstream +endobj +2327 0 obj +1259 +endobj +2328 0 obj<>>>/Annots 60 0 R>>endobj +2329 0 obj<>stream +xÚ­Wێâ8}ç+ê±Gš°º¹ì ÄvsÙ$ìLK-!“8ÄYÛÄ~ý–ã„ —4ƒ@Q®:§N•Ë•+&ÔðcB£©¾Þ¦òìVþøÒóÜÿi¶ñƘNû0”ÃHR‚»‹©øä~Çå`šz¹Qo©åñVóP-ːE°"H´"óB"©ÛP® ”jGµÌR1êÍj=Ÿ çϓɫÕ>€îŠB‚ÔÀ#ȄãeŠU}‘BhC/34ZÕ6ÒE÷ïõf ÑÕ†Ù¨Ö ðÓaïe2¶®À{+ÆEPšãÿ 넂djMõFÝñ[9ÿQÎTìÆو2<ò +0êmä`Ô;ûd€C=åì\î¶Éñl!aÏ‰Œu¤läŠrñY± #ðà  œFDæó…IÜ[ùÌK6øUÅy(Sí§HqìÏ3sy,Ð'©> ˆ +Ø®B¬ÒÌDãi•ŽH‡Ñ•êœØ}˞ŸMLæU¥¦èH´ËÍ#ü 1YÒT˜˜³5[%QÞ ñíN$4_v®¶~  ?éÍFÖØ½Å/Ú¤üû‡Ê$ÞKªƒ;¢}WÊÖ·á‡èfõwEºÒ{R“ø«÷zƒdßÙ<ILó‘`w¤6í¬¸M±O¥òžÌìÉëdp ·ƒ}q± ­‡®¹ˆñt+u°é Û IÖ“™_i=gÞ½½œŽ=÷Ý\€Z–ù…Å.Gúñ5v9è»#ìnè%';á‘5½²=x.Œ«î3ú|)}ÿLKèÓ¡GDžúýÜO­Â~jÔu¥ÛD(ž]’DRn>ÜPZµYXèì"¾2îŸÛzŠúa̽Ùî:.6çmÜ;Ž—Dþ%Ûú甕—SÎ&…´Á¨_|Â}ŠçVñ"Oœo º £(Œ–ª5QÕ.$pe®ó1° Eރr)$§d#æÓŰ­nÿƒb|µ‡®u^ +ÂÓ 3س°-·R«ÖðB]Lu±ê:JŒ ˜µ'Ìqú°G½Z-çK(ÎrG­¡—ÄBk1‰iôþðþ)yo[ÛÛþ¤$Q6È11õÂ`‡Å-´”xêÞøiZ8ly(ñöj"ž[SێЏt6¾t_«l\{vANcN…’)=ËçÇ¢ša…!Rž…Õ옏ª‰ïqu­­.G‡r«rŠÇ)öÛ ÇF$JÈZYÚÈhÕÓÝþÔV?6žžª½ý/½bQü]ù+ÐÕendstream +endobj +2330 0 obj +967 +endobj +2331 0 obj<>>>>>endobj +2332 0 obj<>stream +xÚ½—MÚ0†ïüŠ9ÒCR’e!ôÆG  ²{ª™Ä A!¦¶¡ê¿¯MHv ¢ ¬8ð1¶ŸwÆï ʯŠ5ñ2 iÂSüM¥ãV¾ö[`ÔÁ E¤a‰AuŽÇF$‚W”ì0ûâ®Åº:F¶N3›r»Â…jÇPÕßm™·&‘ÇÏ÷T§» ¦ˆÇ$…‡qŠø$e¥œAH(pqœdnQ„Å’}싷ؗ;ý{Dc´Lð·s¤HD3úAx÷e¶ðFÎÀ›:Sû½ zRB]§Qöa­©["1qÆO³Ñ|—•ŒiƓnž1úñ‚‘'À…²ˆù+ã—捜΍¸5Y–¦-l÷FÃH(¡ìjn6Í´Q3[ú©åã”g&)d=r8 ¨ûNñ%]è̇öÔõj‹8#”S‹¢½ÑJ]×ÕR°Æ( ˜¶øÞ0ÃRÐæx)ÃÚöAšÍ+Ф`ª× ÙÝñ bT̍þ®°ÿKú°ûâ>|J†zŠ,0 %O9 •¸²ÓPҔÓPIû¿ix:k.Ôô€’ìÒo{”ú¸„ÉQvBQ£Ÿ P›]\{«Ï­Öo÷^ÛÓ®ýpûçu óƒÍ!Á{¶AÎU¶ÂElÙvȩʖ¸H½W[ätukœã¥Ãî×(cŒá;-Ô'Xì,Ú$§ð’vo`{®3ûX=)œ“­¼'É̊³Ã—$2‰RxÀχƒï®Z£ÿ Çu‰ZÒpN6Ÿ bl÷/”!Áá]ª`ƒ†YÓ[Ðx¶2 5À‚„ü7¢f”Dm„LPºC‰Ü­õ–nˆsÍÚŧÂz³žSŸ[òÛ­ü¨üÈö>endstream +endobj +2333 0 obj +653 +endobj +2334 0 obj<>>>>>endobj +2335 0 obj<>stream +xÚµ–mš@Çßû)æ¥&B-jß)ZUï.$&fW¤]ÀžñÛwñᄋöºÆ]wvç÷ŸœõwI_*ÔtþvüRgVúò½jf+´èMœ,Ë'4#da£h‰óg¶4®Ì~âþ:¨êa¿¤5øþٚÂÁ¤d¦²³Ýċ]$ïO•[ŸF$ñ–tå4†]lÂ8ö^'¿q$¤>¼À¿½' ~IÓåT¯ñ4ž.F“no²0ž†f¯{”À°lóüq°;™]jÈMŒ=Í5½q +·IjMÖ®Hö°[2 °, lÛÓAÚÃö¤˜$ËrJã#'ò©|¼ƒ|¬¼¤5‘*i-9WÿxCú¹ò;éÙÏÖ?=|³êÆtÜ6z‹—|v^Ö^Ba^f[ß HàÐyåŸj‘‘&ýNž5¡Ë*¸¥A^1S‚@íÛ¤*¶Y@3Oë0âüásÏïž`>qi*ì)cáNͶŒ<ÍNÝ_ðÄ ŠÍ¼38^3AÅÍ;ƒH5 ™>&GÖ¨'§:þßq«À>>>>>endobj +2338 0 obj<>stream +xÚ¥–ÉnÛ0@ïþŠ9¶‡¨"µ÷–:ÝAÝØEEЫEV¢‚äï;Ên“X Â€$“ËãP#þž1ñÇ ã¥PîfïV³7 +à!¬6ÅEAšå°ª^Íá –¦J3t²½ú…` ŒYð̑xã·ðj[÷ ´–mUßA%û²«×‹šÔÌVBè ÿ +¢“nêVV°¾'dþm±„óÅçÀVËìh!ă؎s%z#»'óB2ޓaþC.č„ORT²{¨€(ÏÜÔ%tÖÞ ¥jûº7ý~ú ՛%Ziã°JÞÖ%ÞêÒÔªÝ=lTG¤­~ëKÆÁ’$(p¼ÜI\ÊÝÚM§ˆqùBšÅ½–¶„%|_tA«¨m÷¶æýj!†ïp¹ú<Æ.9c؆…>³qe—G`Æ3 š£Ó/Ë +„Þ²Žö”uðY§˜U£ºSmÁŒ¹¿ Ѿ‚O +&EÒßÐ`Á$ÂWÔ[h_A‚'ã17|ŒÌI†Ššx+FtõU$ÚW‘àIEÎ\Ž9¯nE[Ê LaöþÈsÀÜvƒ‰÷©g56£@¸>(©¹×-hU·¦AŸ%'$$Gûê<©Žß£QŸvò㺿FµkóÐþûV¶G­ŸwÅYù§#‚=M‰Í#úD«¦F\+Õ1D©lRƺêNUº–®£ +t-_ˆn–žŸö4&vÊ8\ršf2ªå`¦¢Zڗ×/¢IvBz"ØÓØ)¿8v¹ébЍ¼ûŸâû ª…µ2[èk<‹í0Zhwì˜vòòÁžîÄ=Gä‡YxüØg1†ž*S6Nÿëì[— endstream +endobj +2339 0 obj +710 +endobj +2340 0 obj<>>>>>endobj +2341 0 obj<>stream +xÚ¥™ÝnÛ8…ïó¼lÆõ/ì]‚f»‹v›­]ä¢- +E¢mueQ¥¨¸éÓïp([±#Éd‚nmŽõ͐G#æç%üPâ…ê7ۜ].Î.®}B)Y,‰Î|ÆYä¯ÞÝ~b /[YðêõâÇu<<§ÞÌUÃmÕ«Šå_Üoj4Œgٍ-֌ˆýd—DÂ'uºb¤ØàkEêâ+R3ï²õJ¢9ýW<¾‚/Î7YCTVÉã­¹(~óJ¦åã/K«|* }æž YdAT€·‹3gæ@²ö/Ÿþ$®¯ò¸ðªÓá³&’ù€˜ºÑ,êԘžIqμNì†áAh(‘. ¼"Ñ_Ä¢Z]ò¶Êñß_}œƒâøÃŹëfÂ~‘%ê•áä BXÉ6*SG)ݧE%[Ê7JJ¾yCD±ZÃ[¨‘¼&ç¾*•¬éÂQ,\9IKÉ×WÅ@Taä횗» kôÚÉ¿¾>Q'œÅæåAµiyPŠšÙtÀÞ°¾‡‡î㼟øô1gšÚK £ÓjCj-£öbWÝG´©ë4cŸëç/ëÎìöèKˆGÚú|ZxšV›Â£x>ô´“ÝÀµÎ‹ß̦•Ù¹\ã“ÍúÀïmº/ˆ,ìL«MÉQZð-À¶§ŽßÂÁPlȚøþÓÞ¾€tà¬ÕtÙçŒ «B±!'jÇ8C·÷)àœKV¿ˆ³éLý¥Äæì<´8:‡ êâ:îN©ŸÌ(‰\$ WŸoædΗr›‚ôFpu8ºa¢!ú|]aœë)çݜH}î’sEÎÉ\Š6“­ØÛÕ¿gÿ0œdendstream +endobj +2342 0 obj +1563 +endobj +2343 0 obj<>>>/Annots 63 0 R>>endobj +2344 0 obj<>stream +xڕ”Ms›0†ïüŠ=ƞšJâKLONÛtzi†Ü<“¡ l:|U@¦ù÷]IØÆ©)ÌÀ }WûHûŠß‚7…€ãCRZ·‘õ9²ˆMp\=¨züøŽçÚ ü ° ”৯¦ôÁ™>¤¶ûoýHQ‚ËÕû¤¿}…$wðþ.F ʎp¢ôæ¬à®¯’.¯«výe’c¦ ”ªÌ•I]9.ÃfGû¼…¸iD•æ ‘õsž +)2!E•Èj qQ@A·ðñqóëÍWÈEmUUÑÑ@Õ 8=ÃÅáìIß´ë4ýÞ(Ýöf»8*݃’ؾR>¶ñN˜(p2O…òªÓ˂%6Ÿ˜6A†’},aYÅ¥xw!‡³k¬~Ž‹þŠ«C՗Oµ.Ö^™ÁåSË吴]|xµpªôµÜõ¥¨ºÖĽ¡M<´½K‰RPtM€Ùªí¢Md®çW‘3“Ád.G5u 6ƒ²ÐÆê!v]Š3GÄ4àØ +£f^¨2jôãÉCQ1˜« ×hº1ž †Ž1»`_Ád«ÍÆÔê LG¸q·îïÿ?<ÂðlÎÆÓê·ð¸îëÈT„ßúò§ +oˆ£¯$žÅ®xA;jæXÊøå +2ghѹÄZü°³Oãnj<#ÈÛÕ£ílg!úŽîå>>>/Annots 70 0 R>>endobj +2347 0 obj<>stream +xڕVÛNÛ@}ÏWŒ¨TA”˜]Û±cQ*ÑrU+( o‘Ðbo‚‘/é®-J¿¾3¾%1 N´òfÎΜ¹nþô80üp°úúqïÛ´w|é·a:G‰3ƗàðNf¹JôÑô¥6p^J‡¦KÒ铄D¾@’ǏRA:‡t™…i¢òÀJÝÐôŒBá¹Ô¾ + T‰am¥~¾ÔgApS`f‡³£M㇠‚@ƒH*[¥!½”~8eB)ñºÁÅ_/#Y[÷jñˆ„ŸÂďò@¢a<}%I¹áÜ0ŒÖ/Ç}8—~$”,hT(I@ÿ¸BsfŒ &¬ŒÛCuà„€Ó3&†NËÝmÀ3$ƒË ³ÚD0¡œµðj„楫äCeà!+˜4hV¡¡¿Î`Ó±ë$ÌB…ÿöòmÍ8vÒ×"zNa¶Iú³#ÖÁ ¡1›ë0YÀ›òØE¤uà –A(pÉ,“ +ßÖðø\½ÍŽN>¤VIF9mH·ÅX° wèn•'٘H g‘Nß­ËãcC˜Xånk9¬w˜eyuY\*)o*6UuÚãÜ5ÜÆ¢Éf÷Æ"k,Ö½Z,¬`³ß,ˆ]Él³õ;i™æÊõ,›7aكVíÅGhÝ +¥Û벁uéа42´ÌU+~‰/£éãjª­€Åʪ¿×b±e:áôhÕdK­ì2🄂~ u6hÁaã¡aôŒÇ¶Vã™Zä±L²jþš´2ƒ·1áGŸYǜ¿x“L¢=F4wF˜IîrZ=\pN:À& +½ +mò1Fu….î®:»#FZGTȃ¢PP+ Ôn:NוœÛZC"b¹ƒ¤í`iíM²@w,©Y±ÀÀ·xaáú|ÓÁLîM¤@wFk•kÏ+ëníªïl9‹{—fs 6óêMÔN×,UrÀûYç¾/5N?F»¹£\Inš÷ân‘JQ>ðZ”0Oó$€ÇWÜG ý½Zô§ÐÙ©y¯?›¿Õ„q]Ó¶‡5íØnÙ®ðýþv“tž½ÐÍ~«Ò…q,•†_"ÉED§‡å¡¡kùslúÑÆ<Ê„nFôwï?Žnm*endstream +endobj +2348 0 obj +832 +endobj +2349 0 obj<>>>/Annots 76 0 R>>endobj +2350 0 obj<>stream +xÚ­VmoÛ8 þž_Al_ÒCãYŽǸaÀ^º» ½-×¤ß + Š£$l˓äõöì¼Úm¸Hãò¡øˆ|Húǀ¿ âÆH‹Á»ÅàÕÇX‹5Z&Sü²~:UYe2Y^-¾#}˜CŒ‚˜i]é÷¼LEþY.†W6¸!¤Ö¨ÁlèJ¤Ù:¾Ë¥çû˜£ ñlԛxQ墍˜´æˆŒ/³2Í땀×ÚÛ¾!Y™7é ôâ–k¡> óâØÃÕïAÉk.¼Íµ$óÍbà{>æ‡>}ÜýA!~$»‡攺¼ÚÀaª"ǜ˜!s£”Tmª:ƒ1?ô¢]¸ÀïžÎâù»xmʓ¤ x 67Op³œf*+ÍÇ,-§®Ó1c1yŒðøÑ8p…"ï’\ïďZh³ÀA†Ç¾«Ì½æ›ž¢fUõÍÀoM)™ïM{Žßc‘ô÷úg?ͱÊy?Oe© ¤[®ÈIËZ¥â¿y­‘lÉ Ñ¯´·jS¢4ÚÙ£¦±)=‚%̋Ñû¼oÎd€Ê §ˆc#MÀ:²Ä @ TÍ9–…Ӂƒ$ö’´­¢"ŸeWFJ=Åßûs±˜QJ‘90°ç~ +å=ӁKyZpOˎþo%ÙÔú˜à§Ù ¬¸áÏð +Ð3¸”—÷òЧø/ËËÉ©#s­ H8°– +f_ç‹ç8ÆŽƒK9Zp/ÇȪ®•î1Cê>WÐr™ÙZr»l> ÷ÂðËýííé +¨$¡ [C)KáuL¾ã»EöÚ¥w³àNýî{/"'Þ;ajUêc†»eæt¢+lha…XŒ .ˆ£õÖ&eͳ\{ðµ´ßj$DVAcŸÖ!,©Ê5æsù Ÿó<+7Oî6 ñ¢ÍÞqí6ösúló<µC†ýËù²W‚ž­°OÙJâ[ÛGŠâ˜—JɟÙJ¸—†Ãæ%£´±1m¿ÈÜNç±k3œB††+È5ž¾nÄÛÓL%ø„'ᲇ-ž—c¬y½,2c°G•´d„ž,ÈTq­¥Zå5ú”&K¹\C)ÄJ¬þÏ7œ^qXe`W²ýÞ+ ÄŒðo¦[͂³¶ÙaÓ¦j,L<“dì.ïïgs˜Ëµyä¨ñ™’ŋB( ñ²æ9yœÓ(ºvX‡Ø¼Ö2‰škþ=ø:J¹Ðendstream +endobj +2351 0 obj +908 +endobj +2352 0 obj<>>>/Annots 92 0 R>>endobj +2353 0 obj<>stream +xÚ­Wmoâ8þߘãE$Äy%[íž8JY$–r¾!¡Ê 6q¶÷óoü’@¤Tw¥±=ãyž™ñŒùY#`àËåßÕ¡öGPë5C7pž?L|n§ƒÏ8¾n«Áf\åB>ÙBûÙ‚ p5|Y7VÙ1]îÃh»dÁßg*†Ri@“/gá–>r‰rž§›ˆÃôŠA).ÐA°;ËMËO3¡?3š2aߍz§P=ɤÇ8Ji.dÝåBº®_Ì´›0  Ø+…5݄ٞAΚí ÅÊW(e/=OL|€8‰ÉQ)¥aáSÅ`„vž$šEcñPâANÚçtz …"úÃÉ”îéä Òq:†È*b˜hFŽªé8¢‚2¦oŸä `ißԋñK“íâh¹[#\¤µœL‡ã`ù<õoóz·zåêœ/y¼Îƒîz-|µKèBƒÝ_£©ò[iª;Ä©îÚh]*RÝ!n‘êhp†V¢m‰s9“– t˗IÚ †/ãÓTï{w:ë­ 'Àù§~¢£­^Ã$¥¬Þ‚ñ|4j•‡ÞDß`$ [¤²exœŸ•òËUœ÷¹ÜVñºŠg~°‹™r§"<çÞºÏ-£îx0ïúwû% +Y–„{-ǒ;¨J¿(¿}Âð{1¥}+¿@½WWČÿÂi>¶ ~DF-KvõJt2¾u´ó¥Ý~S…ÚÆÚgɊþ/ˆÆÝ}4¡DQMËR„Æ ݃­4÷d¥±|W•Q·•æ^®âroŽX*ŠOžkRó¼<Å¢#äõC×oOÙb°˜pSOñónO§RaÑxeìØ‚Âƒõ“×q°AIî!ýÃò(´Ÿ} ¶ìƚ)ºñŒRèîÓ¸²úX†lø{Œ©F•ŸiÄ2üŠvs;(Äӽ¢i¹ºSfÑ(,ÚÊbPX•‘¯xU;*‘™¶yæ ùÿnd9‘Ï ;Ϭ›ˆ,ìçÎ ‘ïëÖýˆPðxx®õâ(¢«ŠÛÂióF«2¡LŸ÷±øüÎ"wå“é;ÅE쬈T¸Oª_˜#ށ¹UbB§LÞᤏn"âüy\T{k–yª#Oqq°¥þ»Ój²nÌS,örµ¸Xk¦sºœ6/JÈÅÖ<Ž\JԎªÚ j»¼¼TÊ®°H1àM_\‹E*¯9Ýd›hÄR¹îäîö0™/D¸ñ FÍàÓO4]%»#¿£]EÜP·;(M¿ÛÁè_Šñ¾&˜ ®’6m‹kҘ§\™ã«_Üy™Ø_ ûî~@°ðôþ¢‰^ Ôç5å^œBøLÎóÏ®¥èÎoè됅€òL ò½ „p(¼tçL$Å-¯åkÀÛlâ&/³àˆŽÅãv'D!|3¼¼qؾNŠ@½ùd³xÃÞB$ñ6 š¤ð#Œ²p/ºPєŽëòIÛ¶$±‹¶úgí_²{ƚendstream +endobj +2354 0 obj +1127 +endobj +2355 0 obj<>>>/Annots 110 0 R>>endobj +2356 0 obj<>stream +xÚ¥WYoâH~ϯ¨e^H„°ñd““0 R6aÁ¼EBܯ|0ív2ûï·ºÛ6·C4$Bn×ùÕÕÅÏ  ü3ÁµÀv`_|ó/Úß=0;à/‘âôð!hN(ÏY’]úÿ"µ¦©¨šå +êh<F³ušd ¤ ¯Qð6g»âM—À_)ŠþÌiÆaIÂ(Óá)‘O9£’JCm ’À …eš'¼ü‡ç( +“•Ð8ð/ Ý@âË_“¡8€Ó±ôÄàyÕ!‚©@¸ÇÏV°ñT°ÚȊ¸ù:{ ž›Ï—ÂÜFÖ¨d+Hº‚¸‰ŸfyºŒà=Í,\ó0Mv#SEQX»O'*¥µíp)̀ÀßÃøiêW#“5KßÂDÌTB‘§Õ«Œ²7Êt¡H”¥ h¦­[Âþ+ª‰Pf2‰CÎ1¾;ù‘f([¦,¤5ɲ÷”@räJx¸  JœÆà‰×-á•ä® ~ “E”þÑ_ok“Üñ\t?ÛBÕêp2ɂ»W€å|=çÇóÙù¹<×õÆ{Z¡+p©Cñž«à \óˆ$«Ó\ rNVôܮ[êpd@ÂõGàáªÈúuY%†ê )ºáQM_2Y¦Ò¯ëúޛö )—åÐ%É#%B¸jïÙ¨(7p½ +¹”ˆÁ욘Vu:‰¿0·{;YÝ+oNwwS‚Ó¤ô6œ;F §Ø }ßi¸8%áC8¶Û“ådšQ§z8¶[t¦å‘¾Eá˜v[<èéÿ)“}<tÍ‡>žŒýÁdÞ÷ýÉèÛÌL¯£ÜQV< +U½y}Xý ‘ ÅIÂ9 _rŽSHEñdáÛ8µDá;´®5…o›ªðÑà­¨»ãH žK$- ÞïçOãÁ¤ïž7¯î~ô'ӁßÚ l8Ú╰ŒòF ÄEØ:]Æój¨«Ë6\Ï¨½»J{·²É" êp–mö|ù|©ÊCiªÒ³­óÂòÐÎúÃÁÙqI.$ÒJ_ÊÕÉWãáÉ U¯´ÛŠøw˜ñ;˜f“Q kà”i9 µÞ©ü6ÐÎ×vû5ÍxBbÚÆI™ælAx„MpŸn_´8= ‘b¿º½EA\S-¨4lí]ÁB۔Rè+ÀÉ3힚®¦…ÓUÎZ LÛ«²G-𦫻•MËvôî)›‡‹WébaWõW“]R뛅Ëã&¶Ñ«NgøVBùœo3\Öj}C¯»ñ —\û|Ÿ§<5v—& ]ð³öàV}aYjkñÄΦçՕåk⚠á>èUæÌ®!*츽C…w…É3‚ôÑ,ûЬšÔ­Éµh“ïŒÒ'ùó Ûìþ[}kʏY†Ãíøâü–†ÁÞÔ8ЌC ’<ž§êEKiê•mÔñtÏRK2ÜÍÆS˜¦KþNðר˜¥+F☲ þ&IN"yi(!͵Œ½_ŠW\Îò­ã)úçâv «Ôendstream +endobj +2357 0 obj +1164 +endobj +2358 0 obj<>>>/Annots 115 0 R>>endobj +2359 0 obj<>stream +xÚ­–KoÚ@Çï|Š‘z!¨l¼~b¥ª”¦INii ·HÑÆ^À­tm7Í·ïìÆC|hˆ{ÿÞùÍk‡ß# +¾(8¾ü²Ñ—åèüƂ–+\ðgø%Cç/ª·åS±­’"ª`¢¿•gg˟øxÔÕÏOÌä—b]g<¯J­ð€R© –K˜Úá¾FJhHqÁ’·¿ò2‰2!W®—#‹XHݾÝ߂;CµO]‚¾øq€†ÄÁaÑ#¶­uZmÛáµrß5tž%wµ¨¤ÈëÌx¬\ÐVß·:{折uHr`B°Wrš× ] ÎP^­îáU”ÞŒê@÷3΋$¯²*ZÈA„Güá„JÝÑ]Ex¸±Û“VYt:êX5v ²ÊnçßMyÏ´²ÉÏV¸Œ®¤)d<+Ä+°²,¢„U<†—¤Ú@µáÆcí0”[%«„Çä V\‘]ÿeÙ6å UØ,{rñC’Gisø$ñÎåÙ|–Z)¡a°÷ºe¯t.ŒZ:[ýtÑَÒ¹sš=áD?êN[p—iYdŸš„â8Ž‹ñÈ ڋTç³£kØåDJ=G yǚ±É^¯¹™M¼Öõ|ü%aK`cÒ÷Ì!wLüêTq/†í9˜ßÃÁÃ3x£a‚1g¢ìvÓᎪ^™Ë©Þ|êØ»„b<¯Rì2¾×ûç½¥ ô¡dë#”è¾ÓûûF&`2™DæÆÑ:>2UBÿHשkcuœ:åÞ¾QÛ®/Ÿ<1R¨gNã ¢S6º‡µŒ‹äÅÖÜrlS,#{8µR÷RïNm•Ö{^Õ"/ßÃ큽ÄÃ6o§áVhbã$°?,IÙsʏŸ¼ÃfB_ îFšWh Ò¤¬$…­å.‰,”S81̄ØuÃ3WÓ%†ºLòuS±2Tˆ!w}K8–â>ž— Ï!© )!/ -ò5ÚÏqãv͚CnˆÝ懦…àêa¾€E±ª^¦d.е`YÆE w,¯Y*Ÿžê‡¦­Jǟɛ®ã`cY‚ócô‡”Xendstream +endobj +2360 0 obj +826 +endobj +2361 0 obj<>>>/Annots 120 0 R>>endobj +2362 0 obj<>stream +xÚ¥T[oÓ0}ï¯8Bj7ê&iš4LÚý i¬ÝAȤNk”K±„øïع´%½ D+%ñwŽ¿«¿ulXúoÃw0ô¥«igpÀv15âõǬ{û¦Ë„õ¦_5j!¨À¾32à+žEI1cxK90²¸0\C±‰gH>>>/Annots 125 0 R>>endobj +2365 0 obj<>stream +xÚµVÛn›@}÷WŒÚ'Š7,檴•ÒK¢JIãÆÎ[¤h k‡Ö€»@£þ}g/ŒqÌK±…읳3ggÎ üQ°ðCaêÉo”Ž>.FçW!PK´x…E<ŽªMqÍË»M™äÙãøñädñS㍛L-âIäCÁV\[-Ñv•“<+Jˆž™€S‰@µHÐ㿍ÌXÊÏ:pع’¬„¬JŸrµ»x,#äS §fÏãÉÅމìP*åYYh» ”J{è¢óD"hH‰»qù3/"‘(ÿÒòe1²ˆ…ÙÞÞî¯Á íÚ:£ŽMÐ{Hlæ=`éÛ6hÛñ m¡UÙCε¤WêêóË*j*€¢¶xæ —!_B‰¿uÈšVˆ%LS¡{h*rNèi¹´êÖDZJp!Y ÖZfB°¿Gø:¡EœÁ|5ú _ßG+²:̵f8ˆš/C¦¦Ð½oäê8Šß=/+‘±Özbö•Ra“c·`J˼UxøÃÖ/ Pw®Þ8þöps³ëk I[3å%Ä|™d<&=]¤×é†&Ɩ܁Óúl*ú28!ò(ª„àY´U²Tu\ë¾öQM²h]ňÒZª§ÅÛX—QÚ3`C²R'ƒhžÛd´Æ £sñÖP€wòÌçòFž?"6՝!§Zsµúä¢gvîO´=T3Rñ:Å,%좒ÒYQ0xÚ¼QëoÎvÆ.¥sÎár]ä{ÍAÞñ>yäàH;®þ³ÖrïàÅ +Ú§yI®—q¼«£Þpê?z²:Z& ï7qΔ,öI)W‚ó;“×(P/$ᖃíz‡]s0DѸeâ×¶G[©˜â¨ñÑ@®I̘(ºÉØ÷×¼uL¤ëÉÔÖÍb¤7cEñ’‹øÿ½|4ÚØÈÓM¹Õt`ôF§±7 ôԀO³9ÌóeùÂp:ÏD¾,M¹(à–e[ËݽiâÛê¡á[rѱ<2ÕO‘Þˆåú>úäX€¦endstream +endobj +2366 0 obj +772 +endobj +2367 0 obj<>>>/Annots 132 0 R>>endobj +2368 0 obj<>stream +xÚ­•YsÚ0€ßù;íKÒ)Žä7mgr5/i‡xˋ +Üږ+™ÿ¾«ÃÆá1L‹Þå¸wö-ÂxŽ’x€f'r±*xY«Óño”G@©–§‘@ßO»*Zƒ¦ÔKðk|}ÍÕTfU‰RKnÆ=âôÙ÷·P;Æs€~©‡ÖSÏÉa´C™¦…VÛǓv´ |èà"¢­ê!G%EQY8ãÂÀ—¬j³LU9{Ñk¬—Þf?õâ㙍öNæN‰ßóz%K—ð&&‚ÙNL¶¡YYsÙÐVL©'!gøÀjxb +¸ó ÖqFN~Lîî^Û=l¥X[éð¬ê n7j»öÐbNW•ºåõЙ}8y8Ýtì²®l¶ª–Y¹V΀©?ª-Ì1ÖRz0~9®!3C`†¡5ðéR`&6 »3¨›gVT9oJq¤…ï³rš¯f>ëÈÎôá-¿:>ÅòꠗL‡ë|CêyÞÆ›6€/°•¯wÜ3Åm-:¡z÷pz¾#moÄ9\äJlõ.u툘f, Š1Mö!·Ý¸¡/Ðí¿ .JDqùÈeS՝¾b= g4&Øû{¼çÍ5n>šæÝfrþÛT]]¾‰Aãí5¾™ +8ì± GäÂÇA´ ÚÔì…p¤ÇBLÔ„€¤m½!J°é 8Σºþ·-™^Mtõ­Ñ~à†]Ó÷Ãëõˆèôuã{¢ØbÏ͜ŠRÕ`¯^3ˆý]ã]µJš ºÿ"íÙz”ÄHýŸÖ½Bâ@Ÿo¬ŸúØ;VÛ÷c¼Áo­=…n¶Ø ñÑÄ܍]£u`ÛQ<ÃãQöNÔu¢)Î@ÿð¶ëò2œóE%$“/0ÏrXҚe¥^:,³}ôÞëd¦¬Ô ã‡\LYm×çLp…Û±ÞØ,KöȧqèVÊ é’0Åñ¦Kàj2ÁHÌë'†yJ±¬(¸Tð•+–ëoûö“~â“­î “›Ù¼O¨+ÓÏÞ?3*~endstream +endobj +2369 0 obj +814 +endobj +2370 0 obj<>>>>>endobj +2371 0 obj<>stream +xÚµUMoÛ0 ½çWÝ%)5v\'F·aízµéa@€A±åX›-y²Ü¬ÿ~”då»k/C‹ "©GR|ùÝ `„ŒcóŸV½OóÞŗ‚æ9zâ)~Éú׬I¯5—b0ÿ‰Œ bN "mëæ–éÙìzÑ_ (ê@}X1݅TÖO sÐDBÎK¹TÖ hÅ2¨š)s4u낔 +X2ŽQ•¹ c +gü 0£?|(d£MüéàaLlMße M!Û2Å*ùÈ`ÑoEÉůÅ`Ÿ!Í ‰'ÄSÅ “‚AÛp±®Oƒ²y– +ëàëm4Õ<…e›çL°¥"ƒ5/K[Ó#SkŵfmºFÓ F¯–°ßñwš¸óv€Ã0qåÞü¡U]2Ÿ,ñîKã|ÃEZ¶ƒ·&û…ù Å{ß°€ÄvÄUp^×ÙՁƒr`A¼ƒ]¦ÇóX ^ÎÓÍÃäëà¶¶IG~î>=wA³íÊNÆ#—ð¡¡«gz€Ñ~D#2=™Øuàü¼ö–NÛ~›ÐjÕVLèÆù/»ù$ñ!Àøƒ$ Œ=^´›yoDF¸¢›»[ˆ¦ˆ' ¾£ + Þm¾â˼?6¹ãF1FnÑv×ýÓ¹™¬qì^§¯ÐÒ³—Xz3é_¥éMÍ¡îŒT)úD^ ãñõ´-ú$ímÇÃqèÆuÇt«D³¿2{*Új‰DQB¼²ø:>R^Òeɞߠ׋àÑK>>>/Annots 135 0 R>>endobj +2374 0 obj<>stream +xڅTkoÚ0ýί¸Ò¾@;Bu«Ô¨R·±B¥IËT¹ÁOŽÍl§šößg;“v‰°ïñ¹ÇçÚ÷W+_¿D!ôGd­óe«7õaËTFcýgÕö<¯³üÙò¡ÞḚ̀<»ß +Â>B’oå «y9·ø!I!Þg9?À÷ÆõǤ\è…DçôO€€‰ïјÉãã"ÐO*0ŽÛð;ùwNU.èQý5ãÞtÁ °¨Z‹Ã•Ü„¯–-ß󵱿˜ÏíÌ `è‡Þ2ˆFú§PX4€_2ÞäMô @Ápì…/àçbÄzÓA±¡ß×P½…²ˆI‰u ãÎûª°—8E9UfÎúQú5¡v$*é‡Ï„7ˆ­Õ{îõýÂù;‰Ö¸ˆÖ§¯- gRA²AŽœjdxädU­¡H·Xå‚É"úì@7ŒLô ¶Ü–µÁ°*Xê ¹–R‰<ÑØkHPìùËD­"œU»qÒ¼êJ%¨ ¢Ð ¨!µ½Mê윭“ÿ¶â}+¶úK+ƒÁÄ `¤/·­\ÜͰà©z2þÌ_ ”e¦“B,GԬQè»Mr ô†ìtÔ/»æ×Ö?(×hendstream +endobj +2375 0 obj +681 +endobj +2376 0 obj<>>>/Annots 146 0 R>>endobj +2377 0 obj<>stream +xÚ­–ÉnÛ0@ïþЁ{I‚ˆ)jCÚi³\Z [€@i[…WKÛÏï"eG^¤M9"‡3³úׄ‚¿OþÅÙäË|ruå0_âŽà?‹³™p“VÅùüçän>±‰ÇäƒÊÇӃ|Ïõð™AȈ£_R˜I=ùrW÷(Õ6\_ڈ›Mõ-ÊWwy\,’|õrör~Ô^蓠3HýmmQS)S— ïSu ÷iS­OP—€qŸð!ƒ9¡â$s ;‡ÝÛQƒ9ŽàAÔ'Æ»KgÀm:ìC9`V—;y°¯M%ª/“Èj[#üT.í¦¶åØÄ“ÂÏU´í® ¡Þd®Ò³ŽJ¸PÖÁ¢6Fü r¹òšâÒk ò³A/ç×{&Y(ܔ«&y]µû®®jûԓ‘"4¤ÄÇã¸|+ª¸L6uRä{q±u\x€Ò<äêy„ ñQ + ʾ0£×J3æ û¶Òª˜:um©5 ’Â\QÁ) +n¾`¶ ªË&®›RPŸ£[Gƒ*郠[7s}k7oŽÅTþÝÀ¦HòZ”PP#»Ð•ìøA„¯M¯^dÞôtO@ƒq†èŠN™îÜÖ14•XÀ²(Õvµq²LpÅ^‚ +Ó¤*¬ pC‹N/Mž:èd˜6õÒ +¦(YÇÇïr÷7Ê6é‘üÿäqÚ,|”º2ÆÉú³¶ÅhëéƒpÝ/YMúçÂ\´/Dééî|ó Œ[oÅ2jR՞úç;n¥·AèÕæI³oñpUš‘Ô‘Ú3Bõ˨I±³½¡ÚñÀQƒA€gŒEê0i:ªÆÒ¶þǘôv˜à`0 £!%wd‡Ñ Žb×`0 cG%ue{3ø]„ !αï–JõÞ°|Í÷NÊßE²82'µ^)ÑUO`f1Ø^àµ- ¾>?Î`V,ë?vöDzX•Q–‰²‚ïQÞD©>>>/Annots 157 0 R>>endobj +2380 0 obj<>stream +xÚµ–ÛnÓ@†ïó#q“"²õ®Ï*B*4é H…¤w•*ãl#Ç>Ÿ™µ×9؉]Šät³¿w¾™ù՟#~8¸LÂíèãbt=ó[°XáŽãáËñÌÃ,ÚQš\-~ ßá•b"\R„å.ÿ$ëY\曧ñÓU¥³jÝV™”9q 1ÊÊ`-!/²2,Ê /6A›àEÂw)’¥aPÈ%«ŽÙM„ÏÒôw°ÝÅRãøzÛ¦Í7QÆåRÂ{âºÖÙæéIƙCBÆØÉ/­Dn:H8—nã<¥íébd0KINo÷´Ûˆ»Ïd¼^Ä0§*Ÿè³5ì«Eï™UšçN®‚2.te;z¦ #rÏ`Þ¹F²Æªc½U‹X1MÂt%ë‹Üs˜Ù`ÛiÊpC³å˜a/]dgvÃ` +·Ye@ÐWÜËËWašæÁí[†Ïü>M9a^dWÑ>Oµ¬Kí4©ŽÆ¯ãž:,ãQƒ›F5 9M÷„½¤Ñ²žN—×:–VÏ4xϼÕx~šn³u¹•I‘Wûv= >Mû‰„ÜçÌÅ·ÛÞ4mÕ¯ÃòPmZÆ-“ã>I¼‹¶˜û6p¥Mñ^­ìQ©mЩX[UU£ÂSAÞb#;ŠT9"ëAFWѕºy_oá¿ÖяºäÔÐ L/ßÉ0ZErّèÿ6ðÎ6»9éÌ .¯’ëoÏAfÏ :½6ûj1Èì9ƒóWf¯#Vz&ä‘Ù7±þ¥Ùk áès=šu(ÇÑgÜÞ¡Á®!Les=št(D¿ß»Mæè÷ÜꯃæŠð¿WG·üþ ‰ë™W·™ ŸjTàÓãÃæéªø }>>>/Annots 163 0 R>>endobj +2383 0 obj<>stream +xÚ­•ëkÛ0À¿ç¯8¶/IiTËoÓmЭ +ëšö!P:»Ž€º0OQ⇸XŽD¼b“ùO”Y5¢©í)QRoÄc—«G 'J%Ô"¡‘}FÑ “‹qR•BB²Ž9œ”qÁ“óÆãóiS;Rf|U¬”¢‘{@©’S+ t_G©Ðˆ’Íqû’‰„g™U¥’\ÍG±0ÄîqnˆÚ^è Ü÷ˆ 4Âg0ëQ¶©C¢VÛ¶]ânië\¹-g)¯U*< ¦Ýk°ùšÚ†*‰ë¼J✑W }y4¤Öî…|N±çÄW@÷LÖ¼lSl‚PWèô¦ÊJÉ8È +bP÷[c €¼Nа!ß»;âö\ª˜=ç;e±˜ì"Œ[“õ iÅuþĆ%Yš±¥É$Ün'2e%aÉÒ¬D%””êa +ÔÁô ÉÝ×ÙíwXŒ¯ÊUž‰õb²e.êBf²–ly8Ø«ßq±É´ÆÛ¬LòzÉàŠøÌDCÖZ ›6w±ÓCFí|O‰²·Ó¥ç=ì¤ôMÊß´Ý5hoŒ®9c‹ÎÛᾜ1¹¨^-mëÐÒM¢¼:ج͟¼)Ã=}¾‚í³m{—ê’¥qwÒ{`¢9‘†–®ÿÞ#­öÈ«=ëtJ^€uWeR-³r5HACŸ8†í[،¯`Öc9®óËsÂö},Iá8~w! éѺN—¯cpiØý;Ȁ ÿ@0“|ë2^zÓE¨‚š*ÇSÇnÚ´ß~§Ä«auzv˜qÆuo/ŸîÁîߴݺ`B váÀtŒþ×tćš;>.‡çއùÕÊê£ÁÙèxMì&'̀ô ›Ý ‡ÎSÍøŸWæ#¾…ý£1µr/fhRèFørlÍŸîf0«Rù+FÕ;^­x\Œ ø—uœ+´ic2mm_mº^7õ»b¾þÌÚ_Èendstream +endobj +2384 0 obj +771 +endobj +2385 0 obj<>>>/Annots 169 0 R>>endobj +2386 0 obj<>stream +xÚ­•Qo›0Çßó)NÝK:5DÝ&umZUKÛ¬I&EBŒ˜Ä1™mÖ}üÙ`¦í´%ûw?ÛwçŸ=¶ú#ð18ěÞçyïôÊ„`žÀж|ð‚!̗ý "Z‘ãùò<5nëÑùš€™–o¾niÅxÞ³-[¹®×àڛX”ÐÈÂÀ ̞c4´\£Æ[£†º`T®f´Á"ËÓ0Dæœ °[ƒ ìëÙsØf”IÂAf ÜBrÊVq(-mcÙ¿{œLöõ&{¶TË$,IBYZ¥z‡6À#µ +ü’ˆ˜Ó­¤ÛRãÅùVL"¶š4‹þ⸚—˃¨½±%1M(Y¶—DYk>Ur%8 :þm¶)© GÕt‘ï(‹Ó|Iàƒ¦=­½­?i½–™“ÐÓ¡ž%¼¯dgF„lu¦Z´Ž8˜ß{ўµ,«å´ò¡Ú¬k"ý£„-ŽÏZjѐU{Zy8‹Çé,¼]‡ßƳ®m7vå銲óc,[©õ3Bà<Y§ÉoõöUJo p,d>Ò2½[z¾‚fB;8PÒÕ%I¢<•UÒ<0ÔJªˆ(л| ¤mB,뤨Ž.X 1fq¶l¤î³(ð,§ÆÀž­ +ûŒŠõ­Wi.Ö/B`Õ}ÜÂq¼ú,BT¤o†(òäÇEÖ°fpm¿þ:È @ÿ‚ ( ëªÈX_gÓ@{8¸¬þÒXÈ1çßõ Fz;vYÕeÐít» …Œd.BÙ.ù}ÿ¿2º<\C¯´sDÝ8„Gº©Bœ1Q¦»žny© +7Ó)éßûrgKºm¹V E²8Î9W—Ü$ê²0SÕ¨6c@%<Ñ45¾:$È)]yï¿´ºW© /îï®&7ó–ÁÿiþúÑmüͳ‡òÅo`Â#w¤ÚŠ7Â咊N ³,‘O‘ºÜ§<[ñh£ŽUÀmÄò(ÕփÒhàc»•®ïªÌ*F}ßÛ×Þ…ÇT¸endstream +endobj +2387 0 obj +769 +endobj +2388 0 obj<>>>/Annots 176 0 R>>endobj +2389 0 obj<>stream +xڕ–moÚ0Çßó)Nڛv*!Žó¨n“X[¦N«–ú®R傡ly`N²‡o¿;ÇÂÊHü÷ÝÏwç3?{ lü0à>}§iïã¤7ÙÁdŽ~ZLfg–eO¾÷lè;ÌòéMQв*à=L«UñEåR¹z<{<¿$å`sk+}'¢c)a˜9 ßLz¶e£oº1ºÝ¢ð¢í§p‹›‡ƄÕÒ« F.0fHm»æ"œ+‘Meò9&œ½îpmáÚsÝõӎCÛ8ÔPkO C²ƒ¥bµÌÊÑ2‘ ®5¢€ðûÚpŸ;–Û,áN¨_Wå2ϊÆÂ«rñPˆ…¬G×Yë; !€É³qm]†W«ÙÓ!ŸJx‹¿/Zzh]h²*}ÊëùÇääÎhɁ™µ¿@†jQ¥2+‹zÜ3É }4ߒ‚EÌ +p6¾¾–ÅT-µýtÛ&Ýnˆj—ùXdÌq1Ò,ÂÚV“½+f˜fԎï¡p£Ö[¤©<Ï&«6' +Œ æÒÖ5×äEB_ÅÊR ¾u˜G´ÜS ku¡æâ!¯3³•´B}– +ò9 &Jh…Râï1î ÀŠ<™[«÷rûn]ÝÝÌCXåXŠˆŒ!ýoN/$ÂS9µº³6åË9«»ä½,+•™òÝô¦¾ì†zšgód9- ˜çU6³:öDÝ ZµMû¼exo¿hÎtáíô6•iÁm ;3¼ˆl–Èå«Õ2[çm›y‰ÇPÒì{^/û—H*ÀdÅmñþUÝüé*ÙÓ¹Þ,³iRÍ$¼£¥ èf½|h@Ԍ6×V…_vt½Ý6ÔVmµB¼¨^¶]ýôâU‡„£Mï¤S‘Ó.ÇC1h~Ÿt&ò`€álVS<CÇòģ-Òím} k'Oђ²Uþ™YQà¸Ô½ÈS>Éò„8n„G±!àÜ;Cy +A,TÑC×߂Ðd°¹Ø°|LŠÞfpõaœÏËßÛP¬ò…i*Uw"«DBöú Àð…£[eÒK×åuçlÛ·Þ?/†(endstream +endobj +2390 0 obj +812 +endobj +2391 0 obj<>>>/Annots 181 0 R>>endobj +2392 0 obj<>stream +xÚ­VÛnÚ@}ç+FTª‚×W¬4•è%Q¢¦<•*ÚÀn}¡k;iÿ¾³cbLࡎd²ÌÙ3'gg&û»CÁ + Žó¤óaÚ9¿ +0]bÄQ˜.Îæå&¿e"ç_7E”¥ùìlÖëMj¨«¡CÇ"¾ßçlÅuԂÐmO†¢´\S‹ŒÚ™çø.`¾fúL¬ Ð|Ò2yÈ4ÁQ¼ÌhÀôûf߬w±÷Ù¡d‹U™ð´ÈuÜJe|äc‚D"hHI€»ñëO<Ÿ‹HñËÈçiÇ"¾}Ý]ƒ;B´gŒÚ.q†ÄÁaÒ¦C¨AÛ¾‡À­NÎ5âQ·FÔEuíšÇ°É°FQr‘í묂ÇôTæ>U¯B·H]Ý®«Dßñ¢©©íª|dí[ÃùóaÓk³£-it€œ ‡GK%æ 62ž«|ù†Ï£e„+S¾K,ؖº•R%à tS–ðË'—¼»ú‚ùU¬;û»i¦¾àb)ÿa R¶OÊ7Q:Ë‡wÒ sù"ë÷F»Mu£ÈÑW?;msÑ2ewf^UÑBßìPÂ%XMÚ*$ŸK˜5ÓÌz{;^îŸ=Nª§ïޏÁ‹‰oÎè ç0Žól¯‹¨i \uäÜLûµZĺ/x±‚Ý^ NXÛ8^,´ÚªP[ӍlâmóQ_µm{BË$ ‚:ϔm{¢”€+Á›½Ò*ú! ·lבÿa^×P =EÆ5/NðÁvCâlE8Žw܈Jé)"n˜øÕðbŸ°¾Ï 5÷бuªúÃ.-®¢˜ÿç;MM»s¡Á§¿jà¿~OiìY"‘M-adJ“¢»ïhÆ*øx;I¶,žNÂ[‘­K.r¸aiÉb¹{¨7 Ûzmüº‹¤ +„æx¿uþëÑ®jendstream +endobj +2393 0 obj +829 +endobj +2394 0 obj<>>>/Annots 185 0 R>>endobj +2395 0 obj<>stream +xڝ–moÚ0€¿ó+NìK[•çu›Öueê´I]¡ß*U!8*$Ì êúïwg;’ÐÐB±ï|~roöŸ¿ l~Ѫ÷uÚŽMÁ4FàÃüö>Qž%DËPÐè¬LʔŸŸNŸz& ˜iÍIVÍê1_— šy{Y´YZó±„3½æáô‚V Ç#`ŽÂXóR,6+ž•…’»Àɍ×THƒ˜áãjœþƋH$Ò>I®§=Ó0Ñ3Û¿»ïà¨í™¶a³Ã6ÂGÁaÒ¢Ì|Û`ZÛò\Z³Õ–.v4œk¢Uwd¢9Ö]Ҥ“{Hºé’ƒ–@. Jâ€2Wsø`¼ÍìŽaͬ´[˜©Ïˆ(NRž…+ÞJ¢-\™ç`hŽ&“ÚÉ\¦rHæc ØS>)ë‚r\Ã;Jj„²-”"ÀNη ¡tF±Aë`Å@‰‚j +¾tq[Ë-µr3¥H×Î| ë\¥#úݜ¦ÿŽRÚ­%ôZÿN ±îx¹™®þªÀ¨;ø[Góg™7ß¶>¨‘gÀ…È…ÑÒX”j ‚ZdÍ<5«[Êù1ÀÃÉÃé>Æ <›£‡¶B~+ևx8܊|!ÂՊ‹~…Ù&Liõ@-ø–<)“&ÛF³quĤûÝû<Ë~endstream +endobj +2396 0 obj +858 +endobj +2397 0 obj<>>>/Annots 189 0 R>>endobj +2398 0 obj<>stream +xڕ–[oÚ0ÇßùGÝK;A‡ÜP·i]/S§Mê +}Z§*©›Ùɺ~û_¸4$@Šûïãß±Ï9Οÿ"ú!¤Eç˨szíÂFSclLŽáõ/­ò‘/ʌ³Çޛ–|89;=áìßLïyzú¹˜Ue¥4ã¢ÆãЉë¥ âD8»/©LE¦í«‘«QÇu\$^=£:ô|4Fðé8 +Ã1‰ú±j/ P¸Vk×} ¸Ê*!¨CŽ…ÈXI…¦ÓkhºÑœ‚. Í)¡ä¦Îf7pÂý™µºY“G‘‰UÅã4Ë©l`ű±B‚V¬PwpxPþޜFÝʉ_ñ´1FFj•}É´º•,ð± )ʬÌiÙƒÛ…Ow(­n…êËCµYöæ±Z d JX¾&B$/»¨½ø€2êVj˜´if>‡7IƒÇ|0§;8 iŒº1Ñ×Uʏ=“w´¬³UjYT‹V[MŸuÜ\®v] ‚3 Bpá4@cºVÈT‰­™WEõVÅüµÊ€‡ã‡“×Ç )›H(ª¼ÌùF¦¨-” šfӌN¶ Ò[º3c3n¦Z¯œHÆx cìÈAú&Œ…‰Öi· åªä¨Es›ÀøßóMÂk´ßY^©™ n´ïÑÕ¿¤X˜ÔÛ¸‚zžNwKó +1>¨NÕÙ²ä1ÅO•ÝõoU +ϖº&,S ¶Òy"”ì½Öü"®û».ܶgCuËbãø¶9<‚lrVóÀqœZ–ÁG¨ÇǑ=èÏs.K–ô¨»ö¸k¢£[€æßÑ7Œ†‘*mֆåïÂΫ}H)œç’o%-±yèªZ¨««Lɾ}ÉMÖôb›‰G‚Ðìòý"a)͑tSËEºŠÙõVŒ mA×.h¡ìJ]ÎÛXÍa݈@ð"YûìyëheX‚%Ķ9}N‘ÚÞ±ÜëÛ +§ Ü¡T\ä\Òuznlß5÷2™µ$ã_žM2à•eB÷¨”ÀÖ*Šb{ÂĨ›Ð3u.îo‡0äÓò9Á:}+øL$EA…„ «’\Íî™I½Ès·>-ýH}Öéþ˜ØóùÙùƒ¯Æðendstream +endobj +2399 0 obj +867 +endobj +2400 0 obj<>>>/Annots 195 0 R>>endobj +2401 0 obj<>stream +xÚ­–[OÛ0Çßû)Ž´—2±si1Mê l“ØÆÒ"^ª¨qJ¦\:'|üã¤—\ڂ4 !±ÿ¶ç–Ó¿˜#ú[¤ƒ/³Áå­‚Y„3#oÂáX-שÌÊâlöçm‚æ·˜€ ÃÛאDx‚9¸‡od±PñªŒóŒf&³gÝ^ü¯`¹¨áÕa{ €é‘»SpÈ´ê!©\ßÒ«%ìÜÇÁ⥠¦_+™m<Ý{žk1o{ ðvOy}¢¦ÚuÚ®=_á7üHu”ÄÀ-­-ŠÉmfŸB©xßËr¿Ê¤8Êb +±Ë0bÃR¿‡åQÅ¥l:¦»íðüxª¸#¼bä°díúé`®¼UŠš¡é.ƒÎc§Îc³.øþk¤¼~u ô¡– +³Uqum ^½ùÚgÄY QxÞRAóGo™æ¡Ä éßáb<ÐlãÿµC˜˜¶;{ã +nROÐbÓ´0”Ç:ƒ±I²(¤ÓõîÛÎʼn„°æËõ†õÉÎ@…ÄߊY‰{05œp¡ç»p4Z]A³O ¯î§s<Mü¹?ß´›ÚrdÅ£ÿ}6i-9e´c¡5o5Z‹{c³Ë+a9UÆû²\«¬hòl;áV9¦²ÔÁ Z½¼kæÏ‡»»¶3∺$2¼H¥ru¸9¾§;7ËyÏÿ8^tp#äś0Ζ„þ‚ï¼­IÜÍ·-ËC'ìú Pà`šGåK€&Ü«|©‚4•ª€A¶Z}Q-ºp =®Aƒ–I±àâÅ ÿüED…uendstream +endobj +2402 0 obj +794 +endobj +2403 0 obj<>>>/Annots 201 0 R>>endobj +2404 0 obj<>stream +xÚ­VÛnÚ@}ç+FªT‘ +Ì®ï(m%šö¥J +D}(²Ì®|¡»¶©?ßًC°1I¥­=gfŽgΌùÝ£@ðB`ƒãCœõ>-z£›1P´ø!Öýéc”íSv±ø…Vcmڞ4¾Iò8­Ö ÞÇÕ^Œx$JÆ­ÝG‰– jù&+m\•ðO— „eY;‚ =gÊñvÏòeŸ àêþn¾šMæ‹él5›N®——šÜúÐËsÆ`’ŠBš§‹±>±ü¢òköY^€ç– „Ä +ÌE +sYŒžoatã¥:‡ç„5§)^¥…`Ëþò¢3aè£O‘Ž}‹v¥$&¥¡er @U©E쉋Ö_ðŸñ³Ll"ë\Sqˆßýô5•šï¿q¹KY*Îrq¨ý¬,®í>1ëäR~=—ï<)ÙqaÚaûƒóZAjDvŽ–g®:Å"áÞ±@‡ã‚´9(!FȎm¹Ç1Úý=R¾CôøÜ‹hÛ1´U.’mÎÖfà(±ÂîíÑ4üàÔG¹í‘Âj§I_}ê× ßVËK¡ížµ ÄZ7 AÇ%@äík&bžìˤÈ[ý#¦nˆhÇ£(Ù¾åŒGΰ}m0õ|LªÑvHÐjMÖ{À“ãéÔ2Äê(f*¾b¶Ø1ÐÕQreP&ZÆ™õ[ì>y=[…>ÁVs¤ª€º ’ØI.9"¹dÛ@%é*.+ UóF`ñoœçðõ¼úd•±COëzƐMn$rØÆC;V +E¢Šc&ÄoãÕôö +Œó‚['”§ç«¡ 94Ðç'°fÒWE*Ê^C‰R{'›„­EÑÍë¼}±cíM“œ]žØ‡Y7ŸçoëSÀ§ùև&´^6ï"^ÇÜ«ø#¤cûgÓ¡ýKàa—¤ – ÞÖ»Å,ÕC¸?­meŒnBÓ3êŽñ½æã›V ±úóbS>D(Å;^ly”eŒ øåU”Jï¡v6i´É Üz®BÇÌÉ·Þ_9”kBendstream +endobj +2405 0 obj +785 +endobj +2406 0 obj<>>>/Annots 207 0 R>>endobj +2407 0 obj<>stream +xڕ–ÛnÚ@†ïyŠ‘*U€ñúŒÒVJÒÐ\´ +¢^”*r` ®| k[IUõÝ;{p5Ȳwgw¾ýg¼¿:tü0þ_Ɲ«yg8Öaó;V]€ e°èFaBá=è žÞÁ†ú+Ê´e±Íni¸Þäªçü|ÑëÍvt]óäj-|äÔÏrʦ8Õ$|¦Q¶è2?ëÃV¼ô÷}\ýÎi6¡ì3úXô.Ô|ќr>MÓj^þVZÄûp<bÉU ±Ê¥pe)ルwtMÇØðá·é'þ¶ãjÄà隫^"˜ñ°UìÙ†c ‘>lÇCSô²[ñu”ftѕ‘jtè98¦ôH×ÙâRW.–òÕ±ôØÄݖ&GˆK4òa¸;¤Vˆ’ôtŠýÍ?Âbxä%ê1˜#녬•¥>å sz+DWÂÔ§íö«Ä¶ðŽ{¦»š­ÞZeÂÍíCi†Ã€Ô„„]%aÓЬÃ9ê1=м©Ë¬¹Ïü5•½/i?0O‘dá:¡«Jþ4»à­L4?äpÆS¸!ßkWé–ŸÁ™JúÿÑdoT=hÈëK¶.bšä™ì·UNz6N^1ádÄE¦óæ4[²p›‡iRÛn]m·å¡µéê~b¸Ûd„Rcw»n̓ÉPÖ +—ìY‹Ê[ ›ç±i»rS1˜‚LÌ/Èæ +2ؐåŒú1ä)N㯠`i¬½BksŠ“i…u­d4UfɝkÀܦaÂ9ЗE‹ À’þ +%JZ?RX·R±ÍR) ŒI?"bÀ#ÿÄðIºòs¿ ík¼Ä@AÌ+¬5°°áÙ2I§4/X¢¼û¨ ·mB øÑÖ!Màæn̟)c©Œz%K¤Ê*jçõ âèxq)¹ºÂy¶A.JÈ3ÛÒe„˜µêm‡ºyöãmÔR Þ„É2*VxádC9¥¶ùP9 þê僟S.*Û®†©‹—²c†ò|‚öò¡jzXàÔ%“å»GFƏê€Ý¦äڄ…E%üå'J–ÞJç‹^íÜU?u)ñ§6ŒX#T¡ƒg‘Ép}?™Á, ò'U9aéšùqLY_ü¤ð#>z  \C$‘gñFË2eNUŽR_;ÿéÀ¦ñendstream +endobj +2408 0 obj +866 +endobj +2409 0 obj<>>>/Annots 213 0 R>>endobj +2410 0 obj<>stream +xÚ¥–[oÚ0€ßùGš4ÑBœ{ÔmRەõaÓPíaLU\È’Ìj§iÿ}Çvä­RäËñ9ŸÏÅö¯ÿ\LÂMïjލuðaþ€އeà!e°èÇQBáè [oaMƒ%eZ¸Íø-V뼘9?_œÍöt]ó”Ž?±rðœ²)ªšDO4æ‹> ø2ÙÚ¸úS>¡ìÚXœ]ú ¢9¥>MÓVþÖFd4öXj—CCîrF)\Æ<Ó7óž®éèñ!â3ý(:`;®fÀ<]s‹N 3ᶚ<[Áhl!ʆíx(ŠVö;¾ŽSN}å©VƒžƒkJ‹Ä±qŸ&õÂdUØ€ÜzìâKF“£ Ä%ÙAÙ9¡¢$}>…þ­ŒóQbïXLßÓüS,ü"’o,Êi¥©´?8ž#¶…_Œ˜î +\ÙëL!nWC2”µÐÅ Ø-Ø44«EGu•”7uU4w‡7¢„[ê½ù“ë2„¸W….«VQá-•zÉVÛ Mr®æí¢Ê|‚a®‰ ‚.®Æá”‡,Êò(M!ԋZJ›žPFLS3øØd#Ø&žÑU҆íT¤åYZ¶¨L³ÌDt$“ú%Ù|MA¹xÎh°<…Gáalh'`ñlX)Ý«-é?‚ã%di”DdËXÄ­8 w¸§X-ÓáÙ¬RºÕ±û¬0‰­’yJó-KŠ¬ØŸ½CÃ³Òø6 )ÇkE=ÊXÊ´–,SåTËQ"5' +®dè+×pé4žÑ0zˆè²î¾ šÝ\7OÁ&‹;ÊöU”„ñv‰×³€)•Úú}í¶Ä86‹Q\Þ-õ¾/ìâ'êû˜à®–U£.Z-®VêTþwøÆú‚ý½^òwx^>^WƒEÿÿŒi>bšh‡ÏšÊYþ‚wÍhì¹C,/`Ç7Uìáún2ƒYú?X –®X°ÙPÆáslƒX¬ªEC×Ðë/˵\{vQª_{ÿg*šmendstream +endobj +2411 0 obj +820 +endobj +2412 0 obj<>>>/Annots 219 0 R>>endobj +2413 0 obj<>stream +xڕ–moÚ0Çßó)Nš4ѵ¤qò v“Ú®]_lª½X§*™òÀ£všöÝwg;P Jì³ïÇÝÿ.ùÝb`㇁ëÓw”µ.‡­Ó"NpÂñbÜþw4ü…Ã0Ow5>à.Ò² éëa˶l܍NŒNýOt¾ëà9ƒÐ¶s“€ÕìÅNo<`Ìøv]ò1ZÌË~\J.®Ò¢ä÷íû£Fw¡o9KÌïZ~“CÛ84PÊÓ ÐÆ›P/¾Îy¾“€ÌbK'dË4"Tœ‡2ôy<¾Å;I FwIâFl0÷•½ä™§eű¹cûd·4Xh…”*; Vuר 2Ð`MßE"ù> +¥ÜÀ(CàíÝcM뮍¡Ãwe<åzvY §KS‹¼L¦9+ÿÐaöNN~jüAÂ;¼:©-„­GåF³XÀ»¹Úî•KSžOåìþ謡¤/Ät‘ñ\–z¾kʑÙ6êºfC& …àrþÈˑHæ2)ò¬Û&ë^ˆÖžÛÅ:e]*L©‚cÒ7YDùÖ֎¢DVÖªOUÍ¢KUì9N"ÆS‘©ýÙpÆAÇJ)xœ,à‰R‚ÖXæ£R†UÖ[`5¢­ŠK'n £š€q,ã%à:7òÑë¡tÚº‰Î ]-!­‘-|ù"{Äxü#yy0d` ©¬·æ{¥V‰U÷¹\ˆÜ¨uõðè8A4Kž[[ +@oYÓ1U{mÛ=½£Âhëè`œ£œóQ2I°׳¯+³ëú9ÎæiCz“ä£t1æpNl§zKköÁ4‡é–är³7¤IÎ϶t®U‹2uª]†3õTB{}Q7]o_æÐµð#d‘ó³¾À²¬-ðÕc:(¼Õ^Mk{±hR¸oÓ¿„÷`Ÿ©ÿ çÒ¢-oy2I3s|lž#+¿=v  A +Îôê—N/I=.>£Ótå¼r…Uÿõ"z¯ðàê®7€A1‘O1–GOSg%|‰óEœÒêŽ^Ô UÀ¡Oƒžçêz®½»}ký oendstream +endobj +2414 0 obj +803 +endobj +2415 0 obj<>>>/Annots 230 0 R>>endobj +2416 0 obj<>stream +xڕ–YsÚ0€ßù;é d‚cÙ`›¦íL’&éK[ +¤}a¦£ØÔ±-* Hÿ}W¾‚Í2 tí~»Úƒ¿-6~ø¸„IëfÒº¼éÁd†;^€?¢ö˜1¸Ž•èLþ´î&-Û²ñšˆFf^ßÃ1À¶übÃØHlœ—s¸¼ï!…޾ot„«¥Q¥™¼…bÓö´sP]àYN¥x}Ë;¤Ð.P™¦ 0‚w¡¶¾/Yz”€øÄ"‚ÊJÎSFŒF_ðËäQÑ¯HÜy݈ûFŽ!f±*9v%¶/އFϱóTızÅì`l˜ã.¨ÅÄ/É5«{c—"‹\?ª®kT2ÆL®_.nx×µÑ_xìQÑ9Ëwm›N?“ R¥!\P ç™bèû°¾<šv®v48srÄôJ¦*ß} þ®“=Ã5,OÑNÐô‚AÄftkP™pHi¬=’s?3J¾Ô\¤¥ ùûœPB´Aæl@O¡€ nl-W ´,ž¢¥©æ!Ä"¤%q˜‹‹ 4`Ããž±ÁwÕ,Å5½† ÿ ¤¸uSŽš`ìôr_Lv±0bhUÂS„œI‘dÆÍD‹ Oç«zoÄb!¬IkpÜ>Ç¿Çw£Ÿw£¦YºæR¤ K5¬©äô)fYbt‰)´(X™8œVÙ£"7ó:·©!⒅š¯™ñµ®nÒÊI1GåFì¬yuƛ0Î~˜Ò{ ¡ôœçÄæ÷™U»íZPH“-UHÞ=ÓdH¨w< ãUÄàƒyÔK3X‹OE¤8$OÈí¬Ëòªq¢xޏPCxR#)ÒØÄúXTóÉIMŒ`öÊL{`zH•Ú-ݲ¥‘ÆuTVm,Ç*t-ÞãˆÛ›ã½lг‡ƒmÊy£„=¤ž·ûۘo:t áºnåšÃm¬ =âQ½‚àºAõ舀rýאóD€míÇ:W׈l4¯=ùÖfšÓÞÞU“½sÓöyø4íÔ—X<—WË, Š ½ù?„ÜYS%a,fzC%ƒ¡sI“„I_iº¢q^J²K]ß±›ùÙó{™-~ñ`?Zÿ{ú¿endstream +endobj +2417 0 obj +855 +endobj +2418 0 obj<>>>/Annots 236 0 R>>endobj +2419 0 obj<>stream +xÚ­•YoÓ@Çßó)Fð’"²õúJL©œBHúf©ÚڛÔà#ìÚ„øîÌv\;mó€Z¹µ÷¿3¿9vçDŽ‚ƒ?¼Pý&ÅäÕzrú.êÃzƒ+áÿI§çbÛ¼¬åÉú®@©Zæ$€™õ%JA#Jæ¸?¿á2ٮΪR­¼]Oâ Ïîñõ=ø T‡ø\ ß OD\VÄ4ò;µë{$ì©5¼oáGé¼uȑ\i0?4Xëk;&åM%RHXž_±ä;lš2Q¤äT7RnEÕꃨ½<;.ñäëôcÃq0ÑsI³“+^/-ýëWñ4>1Ú6ô)H^K¨1ÈQlPWÐH7×¼&¿gåV ñ›€M%€u‰!€iR–Ñ7õ\yÙ+YK¾Ã? Ñ^Žn¯™`I&e-”‹]••ê5ž*g;Q(7kñ °2Ŵԍ(ávÔÓÏ?ƒË6ñ€.ÍR(«¸öµ¤¥0áYLDÝoƒVƒÅM&91~÷EÂN7Ezû‹»œ·¨Q»¨ÅÇY™äMÊṪԩzë—Ô¥Ø*U‰YSY‚'m ŽéÔâ÷e‹t™\Å·¤&o¦Ü½-ïÐ&3žny­¬ÅÓvk|r6Pÿ°B†´Æ¹¥:{X?nÑAT#ˆ® +/@í~¿ßO-sΰe‡U}öÈÚIÙ[q繬F'™ÚÉ/àÎ. ±}ÌKnÎæ@/¶°o@µ/ì*~rу¾Bu¶Î¨çv®GÞëÍY7Oõ©3µ‰>zê®î¢H]Ÿ÷3 èñò× ˆ×¸×áÜ `)Aèû[Ò 2Wś£3ÏÞ·3x«Ÿ<Ǹ¿l{ǑÿYe頟vû‡Xšow¶îÖbÝÿ5m)ÕãÓ½w„¹ND"«vÝæì¾iK›+¢†Ó.º™›ò kr¼ùµÀ΢Æ-NQÿhT->HÚ¶s3-ŽžµÃî80g¦ç©Z}}±\Áùòfv ¦Ü>_}ãÌ2yÄX|ª çám*´ƒT©l‹¶±üˆP#Oºª6õ ÃÜ-Eµ¬(¸ð‰• ËÕޙÙ2›»º°‹…úè{¶¾3ê`,ì—É?tÁÊendstream +endobj +2420 0 obj +861 +endobj +2421 0 obj<>>>/Annots 247 0 R>>endobj +2422 0 obj<>stream +xÚ­U]o›0}ϯ¸ê^Ú©¸¶ùÖ¦Im×N“º©[’·¾0b&À™¶?¾B¾hÑÖDrÀ>¾çøÞë“?Tølâ|r5›\܆À˜%zÅ ôÃâôæ9Êי8›ýÖ«B³hqߥEœÕ ãz]^à@VŸ‹F<áìTTS¡…z8=I¤$¿"Eb™Ÿ<œ}0‘{^‹‡¸k*\f¥Äå›Ù„ªåâÀpøù_À (q ×#¼}É`Š'Ùë%\Ü:À˜ápFœ^›öp6Èå1âoȘG b£-[«¨¥9‡&'šºÜÜGeù$ÕâúêEÌsuJ;œû$|MG'v¤yùJ&¸mëH AŸ˜A Î1¶ù#5mâc -Ô²ùvwäïô”MM/ÎËh9Ðˏ2]´Ë( ¢Æ²(+ˆW‘‚÷5Î ¶î¥ZÖ¹(ªÒ¬»mÛ1ÊtØ= BXˆY¤8ýY”±J×U*‹ƒжN Ñ ôəëàê^SBçÿÌ©­ëoÐÜv5°G7¾».ŨÔ5ùÄ6Ò‚FÚl%§¡ˆre¥Òb •Ä9ò²V;DʱZ ú¨Ö>Ó¶v­ÃtaQ»+nq°1º3ŸB)ª*}²…H¢:«¶N˜HQ­×Š*#¤ ð5iÀ»\›dmŽÚúBZîÿÏïîöáHƒC׀6áF½R$“Ë´0Út<ý» Gz¼‘aBŽ[¸É≒²ú_çf¾¯Ø:·yåÜ̺ԌwîŽÌ˜áێsohÞÔ¹;ØÜÁk::±#…ŒÈw±{A¸‘4ìÝ­Ò1"Æ{wtÇ»g"_ߦ™øWó6¶|ľûÀ’èg¼Þç{XØþ¤xåD±¬V›.:wB]ÏmÿÌàz~?…©Lª§HûÔ½’Kå¹P%|‹Š:Êp·e6Y>§{ÔñMßÌa[·“¿¤‚\endstream +endobj +2423 0 obj +725 +endobj +2424 0 obj<>>>>>endobj +2425 0 obj<>stream +xÚµU]oÓ0}ﯸ/+biœ¤i£° MÚÐØÚ'ʃ—8­QbÛÙ¿žk'iº,ӆjµ¾_çž{®ósDÀǁ0¶ß´}\Œ&§ 9Zâ9þÈ>¨uU2aôxñíS ÄÚg‘—Àaì»X’o†Ñx|ÌtªøÖp)¬åd1ò=kîWŸ!š£wŒÏ9ß÷b ‰€bp=àL¢Ä ï`žxþž·5াÍNÑqä¼`‚–ÌÁsE¼Å†Aº¡Š¦†)ÐFq±#a#‹  +·RQumï™>‚ÄvðÒ>œ÷@5z£abåµÙ `×ü7™;¨-À¶ .àæÞ0ý`â{ÑË;ïAâ;ÕLç!Zâ3•jÚÁø(™™“ l%–xd¼öñŸóêB¼úW +ÕçEBëRíÊ¥ÕV/pœ§˜zu°÷RÚ ¦(t`ìKåh®Ãh6¹¥jbÊm?[ÆKÄ M\w ·,å9gÎdž!BÒÖØ1±¸¸<>»ê§gâ–+)ìÆ"àô¦`O“sò‹–Û‚µ™“Ö<µÆW\¤E•1xk𨇷yß H­@»$;.¾ÓøûQßã½­ë'Q™w'«ñj|´C:k „A›c©™êƳ×Lèׅ–š®Ÿh%•B·ÐðºeÖ¯/€.õ­äÙ>„ެ¿”¬VZ)egPaj'œvo€_–ççýññzemœ×P‰Œå\°ì_%þ¿®¤ªsuRªµL9 +>ƒ;n6Ú±À¨Æ8ÜãÄ +ò\cZäs  ¾×¸F=§´(þ«N÷`›è«Ô5öö‰j”0o€Û{Ž@< êø´¼¼†k™›;ŠwÝ¥’kE˒) TT´°Ñ‡uÐá,p7sâÛÃ( Qzþ£÷'^Å_G] +€endstream +endobj +2426 0 obj +702 +endobj +2427 0 obj<>>>/Annots 252 0 R>>endobj +2428 0 obj<>stream +xÚ­VÛn›@}÷WŒÒ»2d—;êEJÒ$}©äÖΛ¥ŠàµM,e—$ýûî 6Æu«Ê6̙™3ggÿa@âƒÁ·Àö ÎF׋Ñå]؁ÅZX¼@üXç„ÀUÊèdñct»! 7yÁòòí^ހçzâšAàšn}“Â\F<À—¸¼sã:‡ëËqU°{Âgc/´\-ÇËÉ`ºwòaÇ7­¡„¨NX“R™¦ ÷I) +sR>“²ÉÞ¤Ôñ%sCÅ4lËTm9/®S?%ù¦qïJiØÈô$ðE¢­ÂÚh¹ÒôL“ì’wß9¼•ßSHr­ŸÂ +e”«rSe$çLÛÝZi×ù …š¾ð?—IÁš÷´GµöN Ð.rÌÜ@HŽC¡~I„ð},FÞlÛXäoѪӚ.p‘À9‚HÐH)󻁦µØø¼XÌ ¦yNâ?ÓsÄÑxçÒÓà#ô4)ßÒÇÖÈÞ%† YìZbÀ¶´JWðH §¹ÑxMŐ lÂ;önĵxžh°skQà£R·mâØÒÒ?îîP–ß(ß´ª6 ôyã9†u•×BΔ8MÑ5-ÕӃ5áú¬È:ªR®ljüÀÀ¶æÚ"¼$iª£ÂrÌ8-–} +i"zŠ’nÊ(ƒ*çI +«ˆG0ˆž£$S‚@åò˜„sªœ™|óÈLéù¾}²"Ü7I§•¨î½Ü!—R#sû±.Áºƒº£üîˆ >¨Ù¿Ñ•.ÇšÒÅ +Zòå¤ñÁ¨“ýE1Tά…³–¸eË-‘êz}sb‰£]¿X¶Ór³%ñÓÉî&Þåžm†CÉPïQS«ó -óƒŽÝ‰zÆ^W ööú^A»ÔåÎîévÁða ìpŒ!ÕZ{òç©Íba_àزHj‡{a«šâ¥ÂÿÛ÷äèŸËOò íœÐ”ÿt¸y˜ÍaN×ü%Й^)|‰ò*J%5C»µOw€_¾ÓÔã×e|ýò©_3endstream +endobj +2429 0 obj +784 +endobj +2430 0 obj<>>>/Annots 260 0 R>>endobj +2431 0 obj<>stream +xÚÍVMo›@½ûWŒÔ‹]Â.¥ª”¤Iz©”Æäf©B°¶i`qøhZUýïaÁ8§X¹T¶ì]æí̛ٙ'' ü00ú†é䟜^{À,ðWhq\\DÓ;QV¹,fþw´ZÀ˜²j|NV┑ ˆ DAÀVÈ(–ëôž‘ñ).„®èþ äDÏX¡ó¤ÈÈ|åO ÝÀþ F?w7´‹™È0cÔ&µNŸ¯¡»-:guY_$Yø€äÚ«ŒæÍuo޹¦>?ÏØÅk; aׄ<©{ç5~ªÔêÖ_%Å\Oç;Vܶw»¬Ú$Ž£u#ÊâUNÜ1vµIÁäÎ1•jS8ŽÓ¢–Ӑwì­95å^3¹šºÌ‰òëX$Qэî^3š†¢r_ëãõ#‹#xákžüª&?Ï×U*dÙè™Ý^áb·õ0aÃr2uõ¢°x–‹hîPºÌ¡5£~AÅY €9›#N¡97@‡®µ¸½$›.˜[^WĚZÀhõ±§\ÿ h™i4Å=H±+0gÎÛÄ|¨/†$p¨ßI¢RÎÅc%ŠVõQXe9‰üÿ"äƒ]ºœ½EƒM ™§àÚ¨çõz”›öÞ Ž:l|³ ¥”k8ÖKMQĚpãU®®Ðõm8q—J<–S“Áq¤=RCÜæ€f’„â;“ºw¸¼¿]À"[•ONËmž­ó Mvî—@VABþ4†3Í@›ózŠ=N-P[õÞ«Öãëä/d»kKendstream +endobj +2432 0 obj +733 +endobj +2433 0 obj<>>>/Annots 262 0 R>>endobj +2434 0 obj<>stream +xÚ­UkkÛ0ýž_qa_Ò±¸–ü¦cÐuݺ‘5î·Âpmå1l)“äv?W’]‡ÄmSDÑ=W>÷Üså?>~$‚Êfò1Ÿœ~΀$/1§òjºÖz{Q Ån§·''ùo‡ fø^lP7ªX1õ!ë‚42¡{±©`ç³ü¥á­ù½=9;8’f&ë\®Ú†q­\<BLœø©—íc „dÄK0·?1UÊÍVo7‘Ë|â{>ÖúøuýÂÑQL< +$6k’áR2XŒ€)I¼°CSê#mE ;v‘oNųi¯œ¥f`©åk_ó|¥àœ•GP ©çOÑ¢G)G$ôҝ†2L’žnßT³CŸ6…eËmMP„‚‚C÷E{#]GþøÈË¿E³­Ÿ°Ò› /ë¶bð¾l·êÔpñÖ Ö@ˆ³â®¿ÎFb;6|Ú~ Æà¼Vâ ;¤ÿ@¨qi„‚º?µÓ{/W0HhòÂÁ!N”^νÖÚÌa&gu2d¾v.wuz< +[¤4”ëBb@(͋†½ƒ ×°R¿z\“ ýOÓJR; +~€ +<7 +$¢éÐ45ž›V[r}­–œ}Ä㼚m¾Í¡¨*ɔ±Åä=“ Eïl\¾PCLÑ*G×`Ñ#58æaææØtf„·ÙÞ6wŽb«Ø ÜÂ=s47‹Õw0!±³ë5Ó­äê‰kæ¹¢ÅÏbÿ®¥e[b¾í›«+Ø8ýw0¥hë +¸ÐpÇ )*ÖÝ0iÿÞ@±ÄýXÀÅÍ| ±Ôž;—b%‹¦aRÁ÷‚·Em²g.i–PôE&æ"µ±,è´ý9ùŒãEendstream +endobj +2435 0 obj +647 +endobj +2436 0 obj<>>>/Annots 270 0 R>>endobj +2437 0 obj<>stream +xÚ¥•ßoÚ0Çßù+NÚ  ßê6©kÙö2‰ª=¬S•%2“Åζ?w1!…U Hì¯ÏŸ»³ï~õØøaàøôMV½÷ÓÞ凘 ÓÎø!>¤ý[¡’2+t–Ë‹éOT¸À˜Q y@ŠéB€™²×Sý…ÖÅM.¥HôCÿáâéÂ>Ì*™AÈ !Äði:CbиÎA£UUˆ$›e"%Êߢ„X¦P䥶ŒÅvÈ#«ÆýWÅR4>>>/Annots 274 0 R>>endobj +2440 0 obj<>stream +xÚ­–]oÚ0†ïùGÝM[A°MBušÔµt›´I] w•¦(1)q¨ílÓ~ýŽí¤´%0:MH|^û<>_ð0 @ðE!d0™BV Þ'ƒñM 4„d‰–iD!ÉO×Zo®yÉ5¿?½?;K¾;‘ïD£ ñ¦F¶PéŠ;+¸5²À˜ +¡áé)æù›†só9„¬JC¶N%œ7²¸?»ØñÁbsÌ¥\5Z9{”;%‘¿Ô ©âv\¾æ*“ÅFµ0–Y2 ÁÛ?¾Ý}?Bu0¥:5Ï4ÆGÉaÞ#f4ôüVÍA€­Ú†ÑoébNųYK‹fX´dÍác’Üš8žè3hÕ=ˆÌE ÃÞCµ¸ûº†Üfí/LŒyÑñLVݶmÒý8p…uÇu#E›ô.¬¦(Bc%P PM–q¥† j1úÍem—iQ6’{=Մ »EÑs¸‰BWÒÎÔÛ Ý¾SX6Âf¹‚Ôeözöy–Ìð– ÇRǘjÆZ8Ù߃sÎá²TõN9Ð6ÃÄT[¢“ +¢À¤Ù~)]‚_èå +¶¡5û¢-ܕk‡.ʽΰÁ'Þh4ÁêÛãŽ<ºë’Õµ‡6χð,Ԝ뛂—ùA*™šî°6…rFæªÌ잉¬ÎùÔÿ×ùîf÷ó“ÜZÝè羯ŸïÔG‚ÿ4ß)™â½idÊôà b[5#1šïñįkÁ"²¢¸¶i4(- ±: …æ·çH6+îA³@¡ï~o +±ÃSˆcq°pÉÑ8VÜ©¨Ë£{æÏ†%«ÅíæõRÿLQz+ë•L«ŠK_RѤ¥A¹-£vÏîèõñž‘»Z´—ù:ø‹,ÿendstream +endobj +2441 0 obj +719 +endobj +2442 0 obj<>>>/Annots 276 0 R>>endobj +2443 0 obj<>stream +xÚµTßoÓ0~ï_q/-¢žæG£!¤Á¼ 5{¢h2©Û%v±mâÇ'K›µ°—©U›ä¾»|þî»û5b@݇Á,Æo^Þg£³)°²µ‹Äsw±ß[ki&ÙO 1 F/`§ +i…«Àn™«•X±ºâÓú¢Ó %MÙKar]ìl¡ä‰Ò™«æC´ ·ÖÄár¼œfŽa]Ë+ÂJ ȇ܈ixul•.6…äåé^=ðjWŠŽOڅ# ¾*d^Ö+oózgΐ%Ù¾C,B‰”o¹îXÜù×} ¢èûy‹c”Ìq¯cÀ®à¡‡•ß +,'çGΆeBÀEi†¯²%ÔÙþÜ|Âg  ‚4prø›è˜^o ïæÅڒ½‡ëSécª£—´ôf—¾9§ÖJ÷ß;Čz5n ߜhó'ìÁË; ¯ñÿ´,zSWBÚÖøQ{$Fç$bÂRF—þÔÚ¢ÒVÔpîÐÁœ~Ëñ`,–“v2ûuô{p@³U÷Àe{ÌJœ>Œ Ð<ùy7=aJÄiÔÖúp{½€…ZÛ{î¼r­ÕFóªÚÀ.k^böÔ'M“ ñpãÃÐÙ3ò¦Þó‘3ò×Ñ_¦ÊÜgendstream +endobj +2444 0 obj +629 +endobj +2445 0 obj<>>>/Annots 279 0 R>>endobj +2446 0 obj<>stream +xÚÅUM›0½ó+Fê%YmˆMƒ¶ª´Ý&iUÓ ¹Eª,b©1íößׯPÂvi{¨"›yÏ~žyC¾üa ,\3ãm`ÌW>`‚HF\ON“-cpŸ–Å4øj,™HÒԀÕð¸V pWŽxŽé5‹¶jÇ <a¾’sܜáuÆQˆÓC‘ç,ûÉ~ªŽêxè̓ڈæÍ–i·ÌUZ•ǖ׿ÁlLW¡v%™Ž"ð› å¨Ð÷"9@o5ý"àF=÷Ó»«--_±îy\e,¥Ž;ͅ0òLÿ£ ØÇ&‘tùú+CžœDRäW)EMJmO¢dËdbWͱoZÀ™Lé5ØÂDæB£- Iº.©Ý¨sÜɖJ¼6sµ´ú€ZZpdð>6êZ¼(іõvGKÔèA‰]‚mÇӕ½ÈSw UÒÊm‹ªCCvhiˆª¼¾D +ÁJ ùO©!£Ižä1¨ ²H@ċ (¬—6Ÿ¶òybœ*²9à-xùD³SúŒÍ^%y˜V¯ÃêTΕNóø¦6º„`mÓ¾÷îb=‹>oÍQýjWº éW½Õ¯!{Ftì9ù·gµC¼fâoû7Éœ·è'ðV¹¸)‡›Š'ÿ·›±õ'­¢Ñ/w3ÆVgífŒ\uôX‰5z@b-Ì_èêʼÈÚ=~Q@ÌÄïyDî;VP L™×ÔöMõW뀇Ýf Û"?¨„nxsšeŒ—ð‘æM•´™¦ÌN¿·l¢>¸õkŸ4×ølü"ãÑ1endstream +endobj +2447 0 obj +600 +endobj +2448 0 obj<>>>/Annots 283 0 R>>endobj +2449 0 obj<>stream +xÚ½UÛn›@}÷WŒÒ§²1 ؀RUJÓ$­”Vil?5UE`±©`qv—\úõaÁNãKœ‡V¶10³3göœ¹í0°ñÃÀÑ7.:&ÁỸIŠ–Q€7I÷ŠëJ +u8ù…V3Ö¾ã“Õ†R€ªâ˜+ÕQŠþo.Kz™FY^In™…«°}'´êÀ¹Še¶ÐY)¶ŸÌ9“ݘºs­ç\_w¯ÿ^ԅ´1ÅE¢ ‚O“É%œŸN@òۊ+ º!—w\nvú‹œ·™ÃÖ<$ã›LÄy•pxW 5 <Öü=ù’ ³FäDojxKÿGlutӃƒ* >¨dvp}x´­sǹ*É|:騖ÔхÑåêœÀóFx- ZAóÃ˜X}æ/g°ÚQZç·¸NJ!x¼Üݍ©Bf¹Ë\,p-[2{™¬%©VçëÕÔî‚VCs}–ñ<ى‰¡å,A9£‰ÜT[ÃkPMI¤y‹iStäÐ'÷¾ ßw#®†~µRð¶]Ûhdª¢ÙýÅóHa™(æ9ÏïA&4ä\Ìô¼O%¸!“ÑÕ±œUº9ÝæDß¶Âç.äÁ{W¯ÞÓµ-FV¼½ÐCÎC cD’äÈȺ/óHVÆÙ }dnå]÷¥–­¡MA†~ƒê¦üu|»íJËLÌ踧YžÃ}¦çØÈRYu¨›Clôþrþãï[Dí¼¡}äŽ Qëà‹è!+ª¢!ÊÔô¬º¤PG¨±}QÖÎ[QzîJ®ë_·y®á÷…U;oTÀJ½³_žLǰ(ñ@p¹lûF¥„¯Ó‹ ÈRWFqYå ÜpL†>üŽ'ÿfj©c+SP)ž\É£ÛέÊµà³¦µ¢Ôø“E”çu fî0waÝ>>>/Annots 287 0 R>>endobj +2452 0 obj<>stream +xÚ¥T[oÓ0~ï¯8/-ZR;—&iìHck*ñ …Ôé‚r›íñßñ±“®´)B•œÚçö}çv?¡@ԏBà€»€¬š¼Ž'óKĹ,‚Ðv ^O‹’靔í&E2-‹š€(~°&7·dv(OfÉl™°(±C´ý¹w°mZÞdLw Ð>î)þÂûü2ê8–áû’18-Eƒâ‹xBl¢HàAñ¸}ƒðÃPy© ôÕÇ\JX"¿=}¾dL©‰á‡‘‰ŽlΚºf™L¦†Ôh°ˆÚî6 ˆí G¶á¼>\®x:§A­Úu*ـi̽ÊX€ê–öo¹Ží ŒTýΕõRò¢Þ >þȱKìj¯DºaFºíËñQ”5µÝ¥ž8•EÅ>IÀψSÃS¾é*VKaä~O׎öuP…ª4Ê\=Ÿ3‘ñ¢•ES…ôEñB¥í¹¢BýÏH52gª$‡Ê T ¶ãª¬ïhëyÊåôêx&AÈOCÓ4´X5óêúÝGÀ +ÍQ¾¦eÇÁICU 'ãÔÚ£8²ìªtéÁ½e²ãuŸeoÛå–è CÛµdd)™Ê"S¬#¨*Ë´¨ñ/éÛ8¾ÙáÕ+å ×RѲ¬È ¶6ü¨Û# `Úq¯Ž#ð0Cî À‘̧wu†naÃjƕªPä ‹®éç’išg÷R@Λ +Òa¹&•O&vñ=­ÚòÈì<+ê¬ìÖ ^f]+æÈǾ{Շr¨i­¶Ã-{d´’éõêê +m2{ñ?+’.0œZZÔQ ÍíI;’.ƒsa¬‘=¾“Èè>Úµþ×mÔ¯›o»[JoÌÞ{8ì/²),<ß ³ÕÍ–M.¿¥j¤nx³áiU1.à}Zwi‰Ö–1²‡ì§Ù <µlõsõyÿ0ù è~ñ¹endstream +endobj +2453 0 obj +721 +endobj +2454 0 obj<>>>/Annots 289 0 R>>endobj +2455 0 obj<>stream +xÚµ•moÓ0Çß÷SœŠZ´evžš „4Ø:@k&ñ"Ò¥n”'gðñ¹³Óõaéè P«´ñýÏþùÎåç€ÃǧoZ >Dƒ³i܅h?À?óх\¶…(U3Ž~`ÜÎ)Ιcùpj‡Û’ð[LÇáKѤ2«UV•¹ŠÌb¸èÓåîÜÕ>^à^`!PhÙ ÌzÄ6óŸÔ¶Ã`£ÖônGç1Ò9êcž(¡Ñ¼À€E+Ÿ¢è(r¦²B@£dV.ÿ‚i‡´ä±˜Z݋¹e2³-móP­,;“×Û`hðD ÷_?Mú˜ä­°Œp3VÂL´gzÏd´{b]h´Rª¾êíˆpxw“G°h˔&…´*…T $ý‚ª0t4ïÕ廊s± +×a‚¯²2ÍÛ¹€wi[7g„i­Þ“–$ä,Šj\U-âÑðõ<ŽËá <ÛÍp*³p|iKåÁ2qûÜqÏ=®o¢a<ŽÇo{iö™p‘7Õ³£Á»jã 8×gõpWæ.7ÕÞKKØøN‰º$[Ä3mâº{‡Kg#â¤CtºÓÓåO3‘Ï7ÅÛڋÌW÷M²<à5ÖµQ® ov磻eF» Šà˜þ=lÞÁæXá¿j¶ãRóðéÿ‹O%Ÿ YFmÛ ^j6ž®`m­FÓ ì¶´¬éˆÜ£&p,¢V÷ 0캔ÚúCdOÁÃP<ôq±c¡Œº×·MÕ¹O‘#ºY]á#+$µ +…ÈšÖ4Š®‰üŸþ¶÷|ô47iÀ5UÚJ‰ç²ãZTR6µH3žoÝÑëãí†Ç׏k̀÷·3˜U õ+A×neµ”IQÙÀMR¶INÙ§&étbëBrÆhÔu«{gí>>>/Annots 295 0 R>>endobj +2458 0 obj<>stream +xÚµUÛn›@}÷WŒÒ—82xw¹«M¥4q.R›º1~¨d)BxmSapXhª~}g—Å$nÜH•%¼0gçÎÌ= +<– ñº÷)ì / 6„ Œ¸>.æÇ£_Ñz“ò~ø£‚:h0Gß%YœVsâj#†«²Ü˜«+!Ôt%H>½/áDþ¿ïˆ]ñr¦8Š|͇U‘Íú –ӗØÇU’r¨¡ÓÍ<*y½žõáô®Ãp|þõ6¼¹ŽÚÍ Ñ¦*Ŭ¡»Lx:o8ÕÆË›Ñç µ}tއßǘB'yê‰Á™lÂ9œ¥"—áQØ#&A+å…ÊËݕ¼‡¹¦ kð”_ߤ0‘.ïà‹%Hg)­9æ™vãÍyže¢-Ï1PW®i€Ë‚c5^‚•Þ×hÆ +hÑê@6•rˆÌê2 j•4E ¤…+®zYú {æu‰Ž‹mz°D…îX ³-©mïP5½»2‡ÖìE–‹Ír°"…î4­-¹E‚º©îxY™.¹½=mód”@ž¨â˜ 1€,ό߼ÈåÃE”¤UÁ͎^ª[z§%:’Kšv~rŒžŸƒf×1,ªLUÏæ¢ºª×£³ |NJc“£›%&¼øÉ‹ýÒþÿìnÏa×ð~ëèô$ƒžœj}ÐàôX«ë๩©ê±Ù͵gj6toš’¨/ûXkbxìƒ5é7ø7QÍgtÿ÷5ܰlÌìÚúKçÓñ&ù¢|Œð؍‹|YDë5/|‰²*Je>ƒÚIÁðÙéF»”PmÇ·Þ\“#‹endstream +endobj +2459 0 obj +732 +endobj +2460 0 obj<>>>/Annots 297 0 R>>endobj +2461 0 obj<>stream +xÚµU]OÛ0}ﯸb/€hjç£mÄ4‰1¶õa££á iò·ÍHìb;°òëç7T¥É@HS«Tö=÷úäÜsÝ»b?‚!~Ó²÷1é >Ç@GÌmd8¦d‡KcV‘›œù#¿9¼9:J~;`è€ý€xC„^k¶à.J ÞýC÷2Ïày)ܼ9:Ý«çǘò‰ëTå+“Ká!PÚ FˆH–šã\¨“m“{óJ¤Xò'˜c+ n¤ºÍÅR™q`ÚnñŒgðk]*‘qU¬°*˜™KUz01x€¥DÏGR¹†”…Mc•‘%39.×M‘¾çRžš‘õZ4òB<îâ+WE‡êïr‘•}—÷iµÒ<Ì[~Øö©ëÚ¾d]™qg…–¾HzÄ#ÖAø ø¸ú‚ }¢„qä7‹fh®gxµ€­˜:[$Ùf’§Ì­Qûï´ÀÌËÚ0ú­>ͅ2¸øiàO¬1„6.™‚ãJåÝR©EUra´‹G›×¤„xÑs BhL½‘Mß÷ýŽÐd#t8¶hä[½iD­Ð4¶â)n…Þûõ¡í£t=óß"‚U£¸Ñ²&V—'͸}M’)ª€Ýy™`äãa¯%X£[:ZAl÷- +{ ¯ë« i;ÃÓ[°“ Ò5ð‚A`ñj‚5ºUÁmÿ}2tf¼â¦RBw\]ì ¤«4åZŸ€¢ÿȕÄÍ9ˋJñî‰ó½¸7-—¢æ"ÓÀ\Ÿ/§Éäòû̾ç]Å­ï­Àx…i®î¹úßWR3t§-±é<ƒ–%Xg>>>/Annots 304 0 R>>endobj +2464 0 obj<>stream +xÚ­V]oÚ0}çW\u/mÆv>Q§I]×n{˜ÆJx«4EÁP&’PÛÙ¦ýú]Û Ð6¡ôCHÁ‰ï=¹çÞw=? "^YÞû˜ô†W#`>$sÜ c\̎'BÀùJ•'ɯÞeÒ£„â1saærýÙÜ@„xÍ!H\߬`b">ÀË ¯pÍêAdrÜj½¾(‹Bdúæøæ¤3Ոo“‹Å‰º’ÑM2¿NVS³ùú`Rì£f)M„¾ZŠÕl/'ߐâaLüÃI5ïðVÓõ,Õ¢áÔ5Œ |àÂ>>>/Annots 306 0 R>>endobj +2467 0 obj<>stream +xÚ½UMoÚ@½ó+Fé…DÁìúŒRU¢i’æP‰sCª³€+{Mö£ ýõñš@($¹´²eìݙÙ7oÞ - /Aî¬l}NZÝë8‡dóúЋ#Hfíy¥ÊԜ&?[<êy!záâV*—fÞÑf]p6  ..Èô*i1áϏ»cŠÚ½\(>ð|PÆŒ}y¼±öƒ ·Ö5Öð°2èEÜëª;a¬’šlsaÐñû´›,H[Þ Õî×FhxT¹1BzÎe²ã:}:SùÊä•|%¬ÛbÍV{iÌjTó3mOO_úµaneFñ@ 9Ӑ6ì1kSÁ¨_“dY%¥¨í=¸5kd^k¨$>¬F¿û5‚8… Èýr2Ãpt ©ÄÈÙRÌl!ÔñT¯žÒrUˆM.ƒÍv­‚¹Ì +;ð1³+Ý¥ ½å§æT¿áŸV8£ß‹{NèýNn®èÖYv9Öz:UÓ©<™ž^€H!ÆBÀ°ÐÕ_ãfðBÆ0â…ã> +'™={µ€mÉȏ;Ü¥#}S½=u֞ˆ®ß  ü­çȚmÍw2˜£a¢ÓÅŠ‘x±Kå9‰@Ȗ©‚3«òã Õ–Bš¦¢&=Îbo°oS·ô€cO²J?ÞÁ~HÈ{ôþjó>òâ¬}Ÿ!€½~1mü ç¤K×ÐêئÅöšá ˆIáÝkë0^·9Ò~ÕäueÍ€8£©÷^@µõAζçqðž©Ç€&Í2¡õ9ÎÙù-TE‹ó4/¬ÿböí6Á+ƒ¯®éh’`~V Â›Á§…úõŸ'U÷:Þô + +ÿx4?ÐҍÑq57)–a¤ª…JËR( ßRiӂ¼;ΩÓ÷kepÒjˆ¥œVvj„"ùÞú@¹ôJendstream +endobj +2468 0 obj +710 +endobj +2469 0 obj<>>>/Annots 312 0 R>>endobj +2470 0 obj<>stream +xÚ¥VÛnÚ@}ç+¦éC Âf×lD)MHڇ&4õ¡Ž"kpå Y¯•¦Uÿ½{±!\œPUHfÍÌÎ9;sv†ÇÄ?Ì.L“ÆG¯Ñ¹BÐ/䆮ãêx³æ‚±å%‰ #¾\·á¨“g é4:ò[ý–÷ƒïë¶ÔFÍè‰m#Bà<Î3ax ¤#'X<î®Å t ÌApmÝ-_b &[þt‚Æ%9ÃX“»ÈҔL™ßô[µ`=¬›+4욺S‡VpV W’+Û @^£'I»ŠH<{•v{yÞ¦JÑoäÝà Jï=-ÓáVÎBUa5e–ñÁLT){ƒž‰¹*¦'½kéaW)L c½´H&œ^Â䙑¼âùE,Ô}0Eé½·Äkš¼_ÈyGXAÓR Öªwi†SGYæ5£üêA–¡4£úý«û¸%ãˆê.¾h›—¸ÚՄ°H¥æ$xŸ ¤YlW—mXfyMâgi¥$/b&ÀõÀgގ<ÙbøiL•J ’³ú# ~É2®éï£t3¦Å2苳ÂÀJ/ÛJ¿‚GJزÉ(ÇȰî·DßQ•èï {MØzVƒïÅî§Eð7º¬Xû-xw*ó÷pq{ã}¾ê7ûM¥„Ó­Vنª9æÑ/’…~yMyp °ßâßg€Ê¦¾û{ëªóK”{sìû踿ã. –W ”Ͳ‚íÒþó?ÃßrxrËÙ/׍~Ë]—äàÉ_Bᮩ÷j°jæ~wàxýF£×§«[zs&ü‰ƒ•ðáb<Á( ÙSÀ{ʐfs$ ¡9| Ò"ˆE8 [=ƒæh;ÇV×­¦Fv™‹¯¿P˜{³endstream +endobj +2471 0 obj +849 +endobj +2472 0 obj<>>>/Annots 314 0 R>>endobj +2473 0 obj<>stream +xÚ­U[oÚ0~çWi/´‚4Ε¨Ó¤®ë.“:Hߐ&+1M&b3Ûi×ýúùØIi!´lDø|çøó¹|ù9"à›/0Á«hFïóÑÙÇ H +ùÊX’¼WZo欜³B/Ç˓“ü‡ÃE7 }/A䍢·ÌY}È:c£©æváãw §ø¿<9ߋdèx!oۆq­œ=BÐNü™—íbB2â¥ÆÝ,`ªõFׂ£å*ùžoŽüø3ÿÑÌ ã„xïIfn%ƒÅ8 ©uè ð -Úæ.êØÅ>F5±ƒ>–šÝÀRË+Ÿóüºl¼N1 +<ÿxŠ=Hq›à˜DÞ É̙n%ïÜ ¢ÕÁAµEÁ”š|ú›I‹+Z¯[ɼÊûŽyèƙµ[ï:†UËmÂÌ¡:”-@÷)ULÞ1éA^Õ +ÌÕª–®×P +΀¶Z4Tׅ]ªWè†F$tå²AúM”L›- Žj»‡ ÿ¤pPQC€É¦æT³òp:®~Ñf³>0 oj^¬Û’Áۢݨ3̂W½ë¨Ä ØÓ‘9°íL×á©Z0k%öšŽt}äcÿ$¡ ÝÀ,6}âÖ®vðò¶D¿hKéòy!w:Özng.Uè¹`*MFÿUrîD]Âó@&;JCQQ §­¬'ÝmÃt%ÊIß¾ Øûtަ8mXï] ¥'€wºRF2%ZY°¿–¾åç?)_†$ãÐ _⣜Xl&ÏÀû²—¦îÜ&¿¸· þ¨y7ó/8«ª«ÈËäRìì#ÉYì9§Ä3×,®Îû¬Ü:,Ǫ¨Xc* +Ò}E–±_¤h±‡(†Fô͵O²·š”—°¡JÝ Y²Øu¨C[ÒT6Ê^&¢àIÞb‹?ëßÈQæHK.o®°+}O ôZŠ[I›†I_)7zŒÌ¦ÎeÚù?ÁÕÈ|K¾ +Ìy¾þi›Cendstream +endobj +2474 0 obj +757 +endobj +2475 0 obj<>>>/Annots 316 0 R>>endobj +2476 0 obj<>stream +xÚ¥VmoÛ6þî_qÀ€!)E”¬£E¬kÖ~(Õ0`F¦l ’¨‘TÚþûݑ–T«¶cl0`KäCÞswÏÝùŸƒ? Ò¢òzöËjv};Æ`U@ø)$Y «õÅVjs¹ú{G~„Gpeµ@« ¯´R™R6 0¸~ÿù£e¼ùF‡Þ¯f ©áëóo0Ïèö4ó3°—²…‚°<€eAè;p%{h¤ìˆÆ´„ĈË@5ñ“ž,­CÓÕOBA!ÕHT”ø¨€kЭÈË¢kö}- +ÞU¦‡Ó­\±Èª…ÙÊõµÎ·¢/ø9Oü¹ó3 +ñ鴟ìüуŸQ„Kh^ -;•‹ÓÒï€6ªl6tºãUõ 8e%lÆ0Y-Ô³P/StøÜ$Yð$]ß.€ÍIW +,×_…ÎUْrˆÁ¨< r˜öÞ¸­`·u±5¦]Š–+nÄÃÅÃåþÉ (º&·ZÔ;vŽ©ÅœCÙ ¥ÑËº•h ØhÈ¢K¬7Iw‡±¢Ðyƒì=øzmTÑVvÕžp•àÚL}ø°ZÝ=~ºùã¹Lùç[d¡4T²Ùåϲ\OØ´Ò ë’WðÔÊWb‹J~VɧJÔÚw7Q¿ +N9ï¿òº­DOjÑoÛJ'ûЩòÏïIþõº7` ö(§3€}è΀RlπõA? -)¯XöýzÈ\;Ø×:ëõ9‡ý,{ð3÷{—¯„•î\ +7•–?ÔÛÕ¾@„M*²˜:™}©\yLðj£^ð\ŒÌßɦ¹éÅ?©D{Ù¥;v¶ƒ >›ÛRTë±n¾s#ڙ¸×|sD¤CØ¿ˆÞ ¼¢_Ïî=´ƒkö×Ãk°lÖ^=óª;õéj”µvûñÎ0ýC¶`؟õ’ãÝ, 2 {±…¶9tx¨íI¶ˆÇ0[jû-™dJ‘ Ä½H‘edé\Š‹,M\ðÙ8Æl؇bLu6E‹OO*F®*þǬšÖÜÁYeܘÊ;¥híû>¯1[ÿ±½ÿT6yÕ­¼É»V_CûÖa³¾Þæ Ÿáß­ÔuQxw·„¥,ÌŽ1ºSr£x]ӄúÄügA§¯Ü¡«4>>>/Annots 322 0 R>>endobj +2479 0 obj<>stream +xڝUÙnÚ@}ç+®èKˆ°ñxÁ¶ÚT"¤6IÁ¼THÈ2¸26™'U¿¾³x€“’ +d{|·s·ã§‹ÿ8]ñO6ë¨ÑZB´ä‚nÀkƶs—âþ¹ýjX`ØÈìjÙ³aгÅLžÚpEóáhðífޛFwãÑÏ^4z¸oCó:¦i‹å‚8®ë9®ç:¶×œµf-íYf ßb¦}6;´ØàNIÒæ[ݗušaPªÓí"fX=ÏZpu¥àôî£ÑýtPw†! WeiØ2Ë ÆÐËh!ă¨a™¯¸ qߊxAÀCn ðøM2˜ˆ²é“ˆB"¤bxA¸O«_ä9Nxj³ÖÉ`!2]48¦*œµ çVá*pUÄ6Èj½O׺j¢BU€×̆Œ`8¶éêœ"'XÛ¾ª®c©I™Òx…•t7`†í Qš38pr8omHŠœ2HÖ1KÞþÓ ì‘U¹Á9£JîUÙ!+0Ãc¡‚x}nÎ_ß`štËÒ"Ó«êˆpm×ñy6¨+žQhÚ@0ïÇ[eù¼6JÛ¶-`¯-wL÷ʳ„WÛÝo“„&HhÑË uSóoˆ(à¡Ï†(µk *`–§ZÌ _ƒk:+€‰¶½Ê …ïsA)íÚºí»îø¶À1Ƭ$yÕsw·p†í ©E´LLiò"7þ`Rˆ—Ë8ÍJ‚ÍšaR)ÍDsQ=Лt´ +Úì–e.ûç +±êk4îõ<çó9åän)&Ϙœ7øo¶Ù‰uú”æIV.0|IÊ-íLæúk q¿Gê»XǾÿK Èqùµ"Pu8‹@‘ã}˜>u,EŸ'‚ Ï*ޙä99"ÏZL(;P²»rMÏ¥sø*ý)<ƒÐ•ûWŒþÚú£”.Nj²˜•t®Èýðìo7LNÓ M]ß> ?}œÀ¤X²—˜3À#)V$Þl0¡ð=ÎË8¶†21|[Òg{ñÖuESGCù£ñÞé?/endstream +endobj +2480 0 obj +778 +endobj +2481 0 obj<>>>/Annots 331 0 R>>endobj +2482 0 obj<>stream +xÚ­—mo£FÇßûSŒRU²O˜°€ÁèšJiâK"µ±cõ¥ˆàµM/>X¾³ø)᪊b;;óÛÿÎã/þðmp<ˆ7ßÂÎõ§ˆ áG¼!^,º·ùªÜPƋ^ø7Ž€1N¬¡@ßm„ ˆéãt||O‹8O¶<ɘ…Ë´0èîãåÜ!Z{ø9â‰k˜6ä¦5Æ6ñMW[Û¶…{kIïjº%¼:´CŽ5ç[‰&H´pMá1 'gŒÑ¸¢˜^{Di]‹x °e›Râʘi«%X(®„Zðˆ—dKàø(.ó%GÏ_JZpSÍÞ{Ç­QÞOváL5dé!)Ùl»ˆ8wç½ãy]X–LJ¥4)ê€4® O’ʂ. ZršCÄ~Àýè÷Q82àað8º½7D $"ª…LãIø4~ž0OÑd2Ï,‡ðåön´ Á3X&,J“¨D2Uƒ[à5ÏúUž€é€¶§dš&,¦°Í³ï .HL>\Ô[šÅŸ¶‚M¶À§Ã\ґ_¤áÑg +iÆV47„¯Um +(ÖY™.Dªñ„•ôd¥q”¦ÂóE;P¢«TGÉS%*Í2®Ð3†‘ýk”–ï6XHõz7~Ÿžg£ïçsiô=ÚlSZù +ªáü LK”ç—¸Ü×bæú×Jf‚BŸÅWÄ÷ÇJ kN_ÕB^«múX3ÿò¹¼0àêºÈ6ôºÌ“«yïÔß·u’R@ùºZ8TU\Ï{óÜÜÀ‘ï=mó„ñå¼{õr”CBîŸó9»2ô=õD<™_”ÂmZdïÊ Ñ•oÀöE±ØÀPT.u“ªÂqbŸ¯`¿™8oh©dkºS%­J›Ú`X¤]4â[æà\8k®ÊWE4df5áI¨{šÒ}*×2ß;ÀÆêí¶‡Òk¸JfR’íŠ +^!9–·»k¤Wp!Ò#L±w S0ÄïÖLz 2åÛ£hÄr-_–ë»»6XjbM²b·}MÞ»Fó¡óDÞm` Šœºiwè<¿:r“²9>>>/Annots 334 0 R>>endobj +2485 0 obj<>stream +xڍV]oÛ6}÷¯¸ëj²BÊ_²H3· °¶^¬`SÈ6ekD•¤ÖuCÿû.IÉvm)³c(ïá=ç~QþÜ£@ðÂhª¿ë¼÷&ì]¿ €Ž!LÐ2õñfÓ`ª…„¢u ”ZëЛik¸cPTùŠ à ¬¾*&A°x\À/€ Á…k·œ½À5îfr-ÒR¥¼x†ÂšHmêï”*©bQ?|¿­IU¬µ;£CÂ&V1$‚ç ÐÑ/a¸€5/ +f0”\Êt•}5VÁd•)I ïæ¡bñqj”CG®§ ö¹bRuÇ4ÿ;Îˌ5¢ƒÆ<ÑÆÓbU?­«R^ëPÜÝëšÂ£îTƒô꓂+ýÿ¦¡'®¯moïÃUr¶¾ÞÅVU’0ñ%ÞøÓ) -ØÝ´Ð-¸T‘¹sàÅõ‹hp +ú²K3˜ñ¾-ó+Ì*f §Ô™þÃxÒ,E’2Dx ÄVêHÀQ-qãÊ0tKÐàÇ+[oD‚^™Ú>Ý}üÞxœ_¢_o}0!|Ï~ vFñïYTu Ë'¤yEäåÍ,)+%ٓjÃ+uÝ¿µ´™^_2·™äÚ<{Ä%8ÎúBõåá~Ï×ÁçàOЙ}È`©'ý/¶p˜/½Ï;tƝ—fÖZÉêŽölt2Û?Ñ‘=]3²µ¸šÑ1Ãþœ¼þ¡nu5Zœc¾f<4އ#ώfZ–·›ÍÎ3‡Óã(»#bu<ÊxÛ1Âèä)VJ¤«J1=¦'^µÝ®:`îã->o¯Jç¬ žýàI%˜É¾*âœ9öþ¯8«XÝ*-­q+¶UÎ +Uړ:o”îä£!«7ÃíçÇñü¬rX뱏hJ̝.Òx0 +†•>{Ô×8ƒöð:;B›NÓ¢mdj³i3ʌÒ¼î ¨OßÿQGÖûbuÝ¢Îhòg¶uLý:Dímݒp¼‹p— ©oßCº!Zôèeó +k:ôy]SωKup—®±i,ӛ-²Vv:`oï–4öp8.•dÀ­å7}?\ +3ÏH»ÇÅ–.ª8Ó҆v˰ÞC)Ñ«c7±ý(Â0~ëýÓLc¹endstream +endobj +2486 0 obj +868 +endobj +2487 0 obj<>>>/Annots 346 0 R>>endobj +2488 0 obj<>stream +xÚݗÛnÛ8†ïýƒöÆ)lUÔÁ’Т€»Íº;wZ¢’¨RÒvûö;¤N>IVÒ½Ú$PLϐó‘ü9Cý˜Ðñ—€c€¹?™|ÜLÞþé±`³CËÂÅÁôŽ¥Hó«Íw´Z@HeŽ´.!ãQZ0‡â‰AÊ~- +m˂ðõþˈvÊØ|^Ƥ¼€-6£ ´*FG07ˆ|Ü}– °¬> ºU+†µTÎQB·²£sBœ7{r6!D#]@O×̾€z°ÙۆO)a ñÕ\ŸP„ÃLž­¹-“áYmk S=…ç1ÝàÙ +™Ä2õnq°pîÞx¬f/Âj·p(Ât6¬)Ó@€\µ¶ª1NR¦‰®­¨îhïžGä*ÕшkjN_¸Ó9ÔpuÄÑˤ .èÜõ4£Å2u·]’1šªgñl.–󸔹oXXÄÔì–Í2])¬±l8•ß"ûO´E<Ì¸ÛЋ¬ZãÄeèû9vÍ2*hÁŅ”åÈݨcD— ì|Ì3[Y!6qG/Ø‹TrDeÚË$VÛ“ªi¼kp±9²Ç¼Š1GeYýUâ f™5Î}NÞÚ*ëf[Âë +z0lWXg >ÓÛ¡àe6«+-r)ù…åZ€ÿD¼IiÂpÀ´€´LÕÕ!ÿñªú ÷R„eÂÒ¢¾¡Ù­žt\Í#éB0:ØýôZu}¢å¢·ÕÄÅÝ"ò)ó•`¨œSgeb×Þž†}ou»lTeërÔ½ ®ÈÔøzsÛ»^] 3TÃh:å}†®bR§ ”z¨ZÛ&rk<“òîc’×u0¤´Î ɯïº ë0ZUqÆ¢UÞ½hο’h­ÖÏ–Éß±sàsdêͧ¼{ùlu¯é%kîú£¸lý‡ ò>{º#L ³RÛÿã%+¿ü–ÅSśpÑû¢•_~Ӓ©Ô¬„wSMú«ÛÏ}”f£üØ_®ß±7‹lø'ý%Å{ÔçPòS¦qÞNƒ.½ÛdhËê·ðLUþ¸_­aÍwÅOŠK³<4IðŠ Ñ´¤±ì;¯ºÌC?µp›¤Ž/NµŽ¿Mþ­Zéiendstream +endobj +2489 0 obj +1027 +endobj +2490 0 obj<>>>/Annots 358 0 R>>endobj +2491 0 obj<>stream +xÚµWm›Fþî_1J¿ÜE†° ÐE‘œä”&î™ûTW'kŽŠ·ðÒôçwf°cBÒæ|Â^fvæÙ™gfà󂁁æŠþÃlñÚ_¼øÕf¿GÉÊÅÑÕí?AV¦âÚÿ ¥xJ¨q›„¿$y˜¶‘€—a[Ö/’²ÔŸ^‘*i0}E:xó±çøuÓI˜¡»$ Ÿ‚ +þÒVÔ0ãϛóë(z]©òzGë%Üm6þúÝãÇÍíýÚ¿ûøa Ïê"ZÐ4Uò©mij%0cÙÙÝ]ß(ä‡siÜ#ë[!`Ö‰oý…¡º0ºÜ¿£ؖ‹× lË;;Áîjw=ꌖnî˜kêΘ?cðguþ<¯w¸à l¦·A#¦¹žÎ@Üu‡Õ @=þïÃt—7"Õ$,î"“‰y1çÃêOñC°êה‡«å4L ™Ÿkã—ZÌ£“i«ŠQˆîƒ<žÎžÇ(.·.—ݝŸ¡×yœ& ªžÃ©–i¸CHæsêûq‰ºHÛ&)¦ Ðd&`‡Í2]ݛ òŸý/ܒm³Í8Y®æ‘‹óã~»ePM1]‡Œ9”Î'ÇŽÎÆ|^He±ó;;`[ìðy<ݘF{\&³†ÕœþÐãÇpM&ǏC;4åC3¹nb~܍¿U¦¡ <ÔA<2‚i¼³¯´ƒÉÃì]‚üĸŽ«¢-—'Ã&þB¤hr\?σL(c-Ý órԎOÚu·™È›ZÉ힆‡w¢C* »—ƒÛñö[Q‡URRœ¥ÜèRŽÝßÓö0RlåaÙ2ê2•À|Ÿ+sæ¢žÒæ¨èiË矞 ¶AV­ÕP™´/‘ùO‚žEpçg|Ìh¾Î20ݳÑIí è&î(êÈ,Ž d˜°*ø|LR{“Aƒý9.@¢ÛPìaàé7 ÚlhR{ w%¿$E/ ‹°L`ŽCâ.Ç2™ Ii_äס:¸m+r݋¦­ò®:¬¡/kܑ•e‘à#HM S|9Š +><¼É^ +‚°hÓò¢O¸¨4Ò/T¨"ÓI¡]ÀAÑê;Ðè£äÑ´‚}›‡d‚(ª!€{dª"®5IvŒU& ?_]Š0Ù'":®¯qä?áýä됡“Î|ùï«hÃǃû…2IAØ]Qöv×C÷tûîhy8'VöJ¼yØla[ì›/’iSqd>–ÂoAÞ)íÖÔ&Íá’ß8fé®eYhÃ8‰Rý÷Å¿¾CfÆendstream +endobj +2492 0 obj +981 +endobj +2493 0 obj<>>>/Annots 382 0 R>>endobj +2494 0 obj<>stream +xÚµ—YoÛ8€ßý+íKR؊(êD ¸[7Ц®­¼T›v´ÐUÛÝ¿C‘’[R¨4MYùf83äü˜ÐñŸ€cµaO>ø“«OüöØ.¾l/֌Á<*ÒKÿïÉÂŸèšŽÓøƒðÇêš7À¶l|Æàym#‚5_ñd|¾‡«OøN¤ Ëá2Â,›o·Ò4bArqÙ+Œè¦fµâ ¢k¤OžÞÊ3¥<ÏkNKb{ÊT BÄÒ슳m)@5:ŒãºIJ¶gù 5։Á4,ÍQÇj´xVk®! Óa—2 ÍEn×ÂÑPs)“âÐÖ©VA²gƒfòˆF[iÄ¥ÜJÝâÎupR¢²™j¨aŸ"®§-ÕÝÖ$ +X£¹X‘FU¦ÃAH åA(ÙLêjž:ªòKd¯â[†‡Î»M n亥æ\TÇ¡­s­YäA™Ç!!ß )SÆ{·ÌŽ­ˆ\eƒ­Ëøó뇛[q½XAšCóiq{÷¥#7<á§çPäƒûø©kã'Äå®®ÿÊh#ó0—/ª`õà^0»¾zÕ;çzbÐg˜l]=4ÄàÎÐ8„5¥TxንUžÈ°6ÛSrfÔèsÈRΙC™BɍÉ~ É÷üöîógwuç¡c“VÑ’´„ïØÈfå­Ö‘Z„ߝ¤ˆn¯&ç]¢®°«’ _‚í¶€ +<´¢ƒÙ°Â£¥‚EÆ6á.dÛãäЏ¾ø7ˆ³¨çæU¯¥4q é×Yÿ5ò~GØ0y&†*“Ô`,ÖñU¥û¥ëΉ'iOI(0ék?—_¬déW¿+ù=æèÂOŠS·¬ž²¯÷úUŸdEŸ*“Ô`4Ԙ’O‚‰ŠOŒ|¿€õ*õ·j[îñ†’C9º¸¼ Øe‘Ô)°¯Ôk„þ†JO@ÉIJ¨ðB¨Á½s匙&2=Ylüu·\Ã:ݕ?¼z,ótŸqŒi¾ID|µ1yI8s ýôx2m·©¡Ò ß&ÿx›á endstream +endobj +2495 0 obj +1161 +endobj +2496 0 obj<>>>/Annots 394 0 R>>endobj +2497 0 obj<>stream +xÚ­—moÚ:€¿ó+޶/´‚ÔŽ“¨Ó$vÇ*¤­ãý´N(C¹"q–—»»ã8iCáÞµ("ö±Ïãój~ô(ü§ÀùY½ËÞÍ'è–[œq\ +ËMEãÍf¦|Çãä±ÿxuµüK ZJpȈáHчÄßq5KÀ+&M»Øeå§i¼ÊR¾JẾ­PÃÈ¿û;|ßÅ"‹rK܉Õ{Á™¿j9>°a’Âúُá:ô~ñva +a¬þöOô~rôZ =^Ý™ÄôäÖãx—ɦ \3×+OŸ£2­îI¡„Óµ*5Ì©Xœó4‹Ã¢Ôèt–¥h”׈„!JkòŸ•›e4Þ?|þ ûm>YM¬EvØ@(Rx—˜û)ß åNåg­l5pHƒé¡¦Nv½¶Û,\Ë=ÁßlaΈ¸²}¬¼ O™D|½ßîùæeÝ2`ºÕM€‰|ŒU¹ó%жâ>©ËKûÕ¥q[„ÆOû¿däÖÖ¼ö—+‰>*:köÉ?~N´Þ·ûp}È6Þ­³(¹AkÏï‹ã›´¬óE÷½­uGÙçÉ7JÈ÷Ûã…õ6>(ëÚ×Ùd>^N¿ÞàM">,½ôf€!Np®.8‡ñ!GIE‹D!2‘˜N ÀóʗƒÊ“š|¼ƒÊöRÔQÎW‡ø āû¡Ž¿Fu”X†]*4ÑHô”FRjÔNõ¼Jå „6¾×TI+–ImY"4–g¡ï:céS\Jöc²•Šb°’Š¡{ØTÅ!.¥*BQƒµ©èÚÃʔM4ז ùK·°2YTs?ܵ[ ï|¬ÔE]†uÿ„²ãhì" åHíñD]Ùm4#niŽPú RñD2YäÛc + ¶]’YÌ5¼îdxÿÁ•üŽ˜BSºÒÏԔÎߺ)®GŠjÁ#?öS·»‘ޤ' +Ež7ëlpcXèíl°–øp×¥\\ŒZå[÷rõ¹Z¨û•Ž!3U{mHå›O®¶^\)8–©"üñ0[ÀBlӟ>ÞOf±ØÅ~`s„/~˜ù¹z¨ Gf~‰¤Ô’£±õÏ¿æ+óÏÞ¿–qÑiendstream +endobj +2498 0 obj +1072 +endobj +2499 0 obj<>>>/Annots 406 0 R>>endobj +2500 0 obj<>stream +xÚ­—ÛnÛ8@ßýƒîKØ*©»ÐÅn›²­7vÞ¬DËZȒ*JÍ~þIɗD’å q`˜œ!çs“~N(üPðL°\w“«Éû/PV”¸>þˆ®‹ùõê_”´hf:R”ŚUU™ü¨+¾®à'æQôÀ²˜?)©ž›‚úÍbÇe^S¹nC‰áˍ`è/Ì3QA¸e%ÜdlÇq·¬‚4¾h¹f›ÄÛ§ëú0‡ƒÎÌ@.Ÿ—q½ãY%´ÜJ¥œ’Àp^êHPÃÃå8ý™‹°LŠ*É3)¹]MˆAðv÷__ÁöQÛñ,ÃêšðgÉaÙ¡lRßpm½#må&»¡sˆÜÕ%(ÔQdjE¶Úr¸[,påϚ‹ê cd<Òî ÓL6•ö•»{˜ö²"ËFߎ&RÚ½D&Õq"ƒ¨INC¾}DŸA£š¦´{ш‰RäÀ¨î ÃY^Â/–Ög˜ìÀ5ìÑLZ»Éö-C™5Prz$•ç]ôZ»3è)k;ŠãWu™5 Û¦„LhO%+9¦=BV9TÒÃüùà]ÈKøöxÉF ‚0¯Ó²¼‚8(9«xdt }=/r¿ƒCÞV[@µèê¤P>]Ÿ.¼‚M…rC`Q$€H²8åPJý#Pu÷íáDÁÃd“ðè8ßû±oÿc»"í)ì$Y˜Ö‡?úï‘ÖØþÕT[Ì"·-þº¼x-9éSI´^Í¿®¿/næ«»ïߦð®À¶2S'ï¦@ñŸô׿%ç0OEþ*Ðh;D•"¿wûAªCç…~ÃÁRÕ:`Ì󔳬õJ§1Jll ­9ûí³GööZïAkpª¢bˆí”I B™M…i ] +GBµg¸Œë3fÆ “Eˆaí™,tŒuSs„˘î0ác^¶XC®¦ƒáDíïÐ۪ЫѨx¢xNÿQ Ѱ÷(¥è€Ö¤I, °“¯Ò6fGߕJÑ3QE‚£«°LO¶ã±\í1.æâ"OkY‡£Ë²0žZ6ÛñUÇÉÖåílâwĘ/=‡1†Ia6£q1æ»ÇÅvÉ V²*/Ï™'¯¨±©s¾ÇfG5ˆÝѶÄn•Å#JWËeQ{?]ºÞÊ5èDlCž\1Ó6f–©{gWöœ4-‹h˜7¾;‰ß÷òÔóö”Õ»µzzoÙMîpƒ¥bz>>>/Annots 418 0 R>>endobj +2503 0 obj<>stream +xÚ­—mo›:€¿çWm_ډ0Û¼íjR¶uS¥Ý-·I?­W%aâ%3p»ýû{lC )¡dZ%àsìóØç ~L(ü§`¹ò¦“w«Éë>PV”¸3¼X_ÌET¥<+‹ËÕw”;@©”Sb™6L™ßՑ*Ô§¦‡Óqø/BïÊ8Ϥäj5!&A£û¯›O`ÏPÛÅïPÇÃkê› ‡e2#.ÕÚÌ¢¦ßÑVôvM繪å rÄ»"Së+²Õ–Ãõb3T¼(Ÿ¡c¾éާSÚ=tš‰º(E‚HäÕ)ª½l€‰´5šIiŸbr|ÏT®Î‚”÷ ÉaÈ7”¥ˆª’£9l4šÖ>‰æÍpH¢UéýA‚Îê¬Ò.$¢²ˆC«8@é1“Œ§TÚ')•IþØG‡Ã7ŠÉag¤Ö>Édù:ø·q´íÒãc¹,ëŒÐÚ½éÙG©"Ê /+‘ÕÅ¥I_‚…ÅS…vyœ•ÈYæPJWóÇ6!ðåöógˆ7JØ +¼J֐å%<ààAÉצ¶Ñ2`ñÒ Guª‡C˜‘Z$‹Ê|½¾‘WÜ]Ü]μ€M•…rEÖëòLѦ9†ÒV» Ùa±ãa¼‰ùº[ L¸V[°%¶ê,S½j.‹Úû»ñÕë7¹ˆÝȓ3¦ÚÆÔbÝ´~¥ýË"ºpÝØøúÛµlÅûG™º)-ÜvkÔuá½zÉ1Žz4<ûbЖn¯ä‹ .‰}ý§àÅùkə¿äL……ˆUeq9ÐËO¾ ;•èmÛ†Ë°Ó >mcµ%Z™1ï@Y=lÏ6ÛGÇ{LAÀûÛÅ–ù¦| Pu!òHiŠ•þ²*H$ÚTO™Ös(u娍]o¦·rp +¸‘&ÿn-í1endstream +endobj +2504 0 obj +1097 +endobj +2505 0 obj<>>>/Annots 430 0 R>>endobj +2506 0 obj<>stream +xÚ­˜moÛ6€¿ûWº/I`+"õŽÜ6mt©g;ߪL+dÉ¥¨¶Û¯ß‘Ô‹HŠÌâ<òžãyÇ|Ÿ0ñ‡€GÁr!ÚOÞ­'×m Ö;pLÃ×w`½½H‡ËõßâRÃÂ)س~dp»XgßKV9z³ž˜†‰K6¿–ŸÀöå*žoø g“À 8 V”ì¤)õN¤‘M¹Ž"AÌ󲏪`rÃϤ¤{™lGQîY’ì†|¡<ùV +öšmöx4%݋†ý¶äøÅYсö˜óäß<aŠóŠ<-E’g/àQ‚ZFã)é^<ÓÇ.dù§ïã"‰Î3)* §¤ûà?e–ˆ.¶ ‘~0ǧgœ-Ývý1bËó‰BŽ£ÃnÉDÉ3О_fԓ£s8äI&‘ƒáÈ~¶¡9‡»û/_ Ù©Áv ÊËt Y.à68 ÛZGË0£Ž¯¬ˆxr¨=ÔÁ!÷L™Õ¼WæÛí²Ùȇ‹‡ËÓÙ°+³Hmr¸ÝB‘dqz²û-ò0-Ymfq`Q²KØöø¢ê7àæW¸?¤¬& êauþ–dQZnü•‡â¹Ç?¤¨” Ú Ø¹p…_oŸ ™ïò•Ï © +µ£÷jfñ° )æ»ÁÒ>UYñ*¬bDhÕ\6u0iæªÍ8›«¹éŠÿ#¼|Y +¡¯ •5‡j /Ÿè$ ©VìòPäü…øòäU:õ‘ïÑÙáÈ +±Ò;zÃV˜ê²xÄÍUsYÄnZ£o®×r :3‘'gÌ´Ž™E÷¼#N’—eêк/¸'IËÜÔU*~ºr›¤§ þcl«÷ÂpªíüD¸¦€è1äp%‹|\3•ûªDŠW/)—¹’%ûô¸Cɯ_­ÅùÒzU®öWs—{–‰ª tê\ëcž~"¢Êâ€à90;ŠÀþj8)‹Ø^fCŰ¼î\-Lm©åI-|òVõ­¦ôPXjõó«ž'߅#єpZõ,Ô!Û¾TŸ#x©:¾| ŽRÂ}@¶£O\óL=å9ó™jÉõÇr)áNúõh†ü_„÷÷‹¬òø¢è‚ç1÷{Lùðg˜•a*Ñfzʬšsô +²]¿I¼¥+3þšüæq3endstream +endobj +2507 0 obj +1097 +endobj +2508 0 obj<>>>/Annots 442 0 R>>endobj +2509 0 obj<>stream +xÚ­—moÚH€¿ó+F½/äÎîÚÆX­*Ñ6­"õ…òérŠXˆOÆë®í¶¹_³»~ƒÇDMÈÌìγ3³3Ã÷‚ÿì‰z­÷ƒw«ÁåG(…Õ\by0™º°Ú ã|÷#ˆrž^¬þPdz|\‰‚ÕÞs b ’§"ʳPÄPk_­Ä"h©z[|gª6÷¦ÖÌnÔ·®‡e‹2õ'Ö¤Ðfŕµ6"Љ‹R$ú%[!„ ÿqD Êçø\íöæÓÚ'ù¥ƒ0í|?¸ÌÂõYt±œþtZû$óPŠ(yfmxÈV*hŒ¢…ÞhZ»íò#.wT.p}Í·àY.gêL%0fž’Î aœa2f2•šü'Y&Ãû<ã $|½ùü­ւµÈ£ Ä"ƒ{|<ÈøÆ26j‚1ó>ðt-ÃD9ã‡ò˜‘B4 “d¶Ù,êàÞo/—a›Çkíã`³IAÄy/äÿklsÇʳ¦ _‡Ûoàz>W;#µÑ$ùwÔÌ,¸6G?‚«/k“¦ôe˜ë+/kã¶È†/)ƒGU ŽÖ–æJ2"ͬWöžÁÕ¯`ŸD¼´á—b]­þãu”o8¼YçIz‰®·ÞÁ\Ó׿¼ËàOüx]úŠ˜‚‡UDþvÿi=žá~(Á=õýhh4,b¼"âA|«G*Rw«Ù§»oó«Åluýíë^%R»}ÜpÉ8͓DHôȫё]8øsG}¤)Gåöâu‹ÕÚ%ç0‹Rñä2Óâ~â0_•µ=àGù™ëy¤/wP‡›€MHë¹MÖ·š£Ä±ÜÊ Ã#ÒSIe±Ì#߯MŽtòuñR¥XŒºª°—X¾£ÚP_,sŠóÉ>`þwR©-íŠÊÆOû *}ˆó©®13w\–`]&†£î´šNð&ï1æÚ¹ú©W^±iѪˆº#H)U©TšÄ®ãŸ2ùô %aa¶·¯A¼ë!#Lõä«H¬ÞXÅ)^„•öI­‚ËÁžLûs•Ç8›«*w¿#»<Õø0Ԕ©ÑB?õË.Ï1Ó@-yÈ ò™ôòpt)mu«ÝfK ÄÂno-q +ˆw} +WÁeS§zê]¸^ʕv‘§VŒ±Íš7ú‰Ï:—]”¬›4؝hÿªWCRÑä÷­›ÿéæ8“»|Ïã¬WÜ*\“c =.ûjz%-ãáé)™2†©J§Lýꘒ™M±-mF&ÚO±QâNÐ\z÷jŒÇyŠYð6¢©ú²iíV¶Ú¯žk"÷‚>-Cw<ÂׂŽ~Z†ÎQ…lâQ“mðþf¾„¥Øf?äK±“Á~½¾qDjõØ,{LûÒ©úÖA¹Æ«Ó 7ÿü¬ZÊgendstream +endobj +2510 0 obj +1057 +endobj +2511 0 obj<>>>/Annots 454 0 R>>endobj +2512 0 obj<>stream +xÚ­—moÛ6ÇßûS°7Na«"%븫H³,v€½°­h°%U¤šõÛïH=ùARäl ›æ‘÷ãݟ<êû„€‰ÿ\ +–Á~òq3yÿÙbÃf‹=އ_Âé'.‚<Îdœ&W›¿ÑÂBJ‹9u•Åæ™CÙeV]Ó8˖a¸æ˙LóÇéãÕñà)l‹$P“ C ¢<-2õ)HœXd<ˆ·1áËÝäü{Á…4ÊÉZÖ9õ M»ú‡í³¯qüº{¡:‰“`W„~ ŠL¼GHãù7eª,ˆá(üñIÂ;üøpÞs¼&üáñêCв^s˝HU÷j31 £­D=î¯U&Eì=ø~ÓØÁZ%âÄ> ®2µÊå–LÓtÇYRG¹Ó1mcÑ8¤Ä4HŸG³ñXgË÷[—3ë!¾c*1ˆEÉ£Û`ù¶áÇªWq)Ù'&ù •eš†ÕPY˜ëªj—R}I$x³W†\Lgƒ²²=ß NLܲ5JW¶o¢i£«Šh8ƒ„LBãÒw ¿ÏåùB*ÂÚíèXݳ$N!Õ骱ʜŒÇ*Wñ6,1BZ5—Mü&x£¥õ..Ò]¡NÛÿC]®ƒOL5]¨ëÖ8u¹n«­éyY¦JEå“RKE¯ÛgG+D÷¢h­e'Ѱº¨§QQYÔmZc²X-â-Tb(X„\5b^z˜[ô°J/ë¨daŒu‰{,꩝ª.2‰S|+$¯*äÁ¤mٜþÎ"lëš>«ê(֞š ÿÚÁøœA€ú<³Þ%lÏ/›ìp´z +.§üÁvï/âË<*ö<‘¢ì_4å7퉉² >1\}~kZ)Ed{hma èWMIÔ1sTй1ñ•ÆJkj›XË[k}q«Õµ0qVzpk2=¿YßÖ®RÃtÔ³QÓcéJ뺒É%Ê¿ÖDSÓ7@ä¨#p4‘¶î%ZRE(µ"ù3ãnAhƒÖÊ+p¶*g£á´u/î^½)•ì;èÔϊ®Ù”¯ QƒÑhÚºTw›jOuЩHžã^ÂVÝçÕe^GòPÓ½`C”Ö} ë¥ÞMîN0ǧ–xÞ;¡´îܧí!Cœê»ç²ÈÑózµ„,Êê•(á/mÖC{ûpsñVw¶AZìBHR ß°‘s¼ô†ý/Nÿå5擄ô¿ã ´Û5QoQuü‡ßøàsš{WUÀ*Ӌ†O›åõÓíòëêfy{}ÊÁ’ð½²YýµéR2Š™Fªt^qƲ<ý‡ˆøËçiãêU¡¡U"ãíÏC#ži¨¾S`Wþ Þí+Ž’4oRçÕW­DÇÑE~¸[Ã:ÝʆJ»ËÓ(gû=^Ýá+K +¶Scç吹K»*”íxuí"įöŸ“ÿÏø1endstream +endobj +2513 0 obj +1086 +endobj +2514 0 obj<>>>/Annots 466 0 R>>endobj +2515 0 obj<>stream +xÚ­˜mOã8€¿ó+,î  6'iÚhO'uoY„ÄG‹tIܒU󲎳ÿþfì¼5$iz:eëx<óxf<ãòó„þQb»øëG'_Ö'Ÿ¾y„:d½w‚³ËX”îøùú̚ÄӓSk†“¿…±¿ËN~÷ó4û¦©ñúŠ¢5\”—Ï’\ÀŸ?Î,ƒ`%EoŸp4!×÷÷ÏëåÕóÝýåÃr}}w[¿º]~¿œÓÉË4f?Ú¨i,PiþÜ>Þ܀0{ñ©eŸ>Öüõ‡‹Vœ“å.Kpúr}b&8W8 3gψx^5ؑú«%/¶}D©¶1s¼z›_’dÇYütötÞkŒšŽ1«ÌY°3ÚgϬì9…=Ï+ NˆrÍÛ>S6eÑ„«‚òp÷h¨rÇq}e’2Ù¦iØ“ ±`*¶pÓu,ù–‹kÈÀÙd8l´A´•cÕh\>Ù3ê{DÃÑ£”bJ“žkx}&?n¤$,̎öÕ‹·Ã´LËp*¬""£±Š]ü'¬lLb\õ*çO¬ã¹x–ìr&ñÿ‘]ªºB¨­zXÆe—e5Ër u ÁlƒQXµ=Ömµ#’day´ÇVd¢Yd"$âœØ66(êxm(,Òð£0õZÚrL¬¥Õ­Lљ‰Z«°+.¥]q­_9ޝ`ÝOع<ÀFàÓÑlJºƒM™ETIÕCUÍõ3Yà|w4“–îc²®>9ªDò=å$ِL¢’åÜÂD¬±pJºΝë€Ç¦ƒ_#]u¬ ¹͌ESÒ½h ÑRhÕÑìÌ£.jf눃 ¥{õÙ,*DÎ0_̓M"ˆ„·ã8¡ø?Zº—Óôô¡èub3÷™ö1'CIwV’º Ò¹«sðË\ÄEtªÛÁԚ«HÒ*5xS&ʑ1«ó’€wñ› 7j²žð“|8‘ä‚Ã?0:J±fh•ÔtXÙÿ†ÚoãÚD6yì£J‚ #I¬p£DT®¯quÊ=f)÷ÃMȃf=5È·Dì#`k²õqi~i½YÞ^µYX´ùË%ëË¿×]KŠ”(¤"ß5( 3’ŠäWâ[(_›)›(ÛfÁb± 7ï )Âc? ðCžA`ÈL‰·0ãÝÆÂm n¹kçÖNênò—‰ë[ò˜2miP·¸DNöŽu¦¥a¿:5õ¨t,]¦÷soQÞC¼è»nÑ$ȟ÷+²J6òAz܋d+XÁw-òÅ9Ûáê©^4[êSËÄ·Žã­ÙúË å¿NþYDendstream +endobj +2516 0 obj +1188 +endobj +2517 0 obj<>>>/Annots 479 0 R>>endobj +2518 0 obj<>stream +xÚ­VmoÚ0þί81Mj+’ÆÎQ·Itíªj]Ë h›JUYàR&’°¼´“¦ý÷Ý%!Y¤a+HÇgßsÏsöݏ ¿ lº¯uì¶?8À pïpÆêâŸéÞéOá-rßý޳8Ù¤ÂMš|5÷'‹d*áÍ$YF‡óåR½G¦dÁT‹lðåm øs”Ï0MíÒÌä^„p𠉌®ù ¼…_Ð|Ùî@;~ Úðûh}¯Þt:ŒÃ¹?‹Æ4ìÀy¿ëöÎn¯ú§ƒž{~uY¾úxúíËÕà·q*¾ðpï +xòá¸]\t C5Þ?Ê/iQ¸CˆRBo4}ê¶4UC6éÁè18£˜º­rðÀqŠÁ†DtÅ>œ‘ËXæÃÔ»hZÄ{ )üñÞx«;¦ªY8äÛæQ+<¹GÇ)]v %¨ßSTQ-,ÎLT®€åHzcX«(vEv"bY‹J×4U/Pé(¾ª<ˆ]Qû±œÉp¬ÎÅ^§>­¸O5OÉMGÍò*;µOðÔëÇ# VKu¶9\c…Ï܉§ðgõòq«F*×£1¨<†5Iª•Áœ‚¸æIµ+*‹$žþKdUz#¢ÈÜ$vÓQ³¬Âé–yU‚z&µt„ȽrC'¾6{Ý b2÷ܘ±¡\ŠPÄAXŸ`F—7‡¦¬ §‰”y$;CK«ZX„lZ d.ŽAÆ;]ynàνâä<©YHuZ?G‘˜m)å1®Å:]Ùk‚*¦/oªÖh0ÅÙkÆn¶—Æ^8K<éÇQ6o·Uµ æ0ÕÆÅøúDF“p¾¤ÔY“FË¥AelÐMãaÇÂsÆ!”¨Ëº1gÔ7d֜[¸²´N»•f¦F»VÆ…˜BK¤ÐÜ{I]E½BTe Â30 j 3µÞ³¤XgzVv2NB?§Ø(΢Âí”`]ž…¨ºA«,y*¤o،b_åL™±›2®¸ià.ñ'´%`=È0Ž@ø›„8Ñì‹4£ÕL®6™K<‡ñÝx¯]šGðz:ûؙVB§MÆûÿÙ'ÚfÙ&¦ÿÝ»¶U4‰„Å þî{6ÝÝÕI4¨6Yx‰dðûQÃà.~˜sý0˜…Âó°5€OÂOĂöS²EŠÍµŠ†Õ]`ÆYççÖâMúÐendstream +endobj +2519 0 obj +898 +endobj +2520 0 obj<>>>/Annots 481 0 R>>endobj +2521 0 obj<>stream +xÚ­TËnÛ0¼û+èÅ.`†¤(ÉBŠn“=´pcåf P,ÚQ¡WH©iþ¾KR~Ԗš +´ÄYîÎý4b@ñÃÀ Ìw]Œ>Å£‹›Xñ#ÁŒAœŽ³º¾’¹läj¼šLâŸ#fêQԝN¶ÒE)D]û&ô«ÊR8ʂ÷ ¼ÇŸÕäò,! g®¶m!ËF»¸Œ™8£œðSŒ°ˆ‘é¸}%õZeu“U¥‰\Ç#J(vº_n¿€˜!Ú&c¾oÖ%aÙæÔ#Q‡æž âm%]u>5Y17ït³•Ùü¶²øQÂ×Å™O­Ô T +u]•Z¾R©à„¾½R‹î­ô ³Ï™õÈuèÆÌ"ܕ½›¬ õybGæ-×&¤¢!És(dQ©hµLáá’rH Òãlë¸þu>`²wY¹ÎÛT‡u[ë ,<~4Pƒ`Σã]žGŽÜ9lË¥”0Ïuu6.ÖM_Àó<½Ÿ£Âî%w8Á«-45<±wÎwù¼“öd̖t¸¤S;ut“•é¼iTöоõ¶âžðÜ©CWŽS<à?]9MóŸFԚסC4õ ‘™¹žneÓªRw]y}…í÷ÿ²ÒlשˆƒÀö‹ø|·X²Ú4Ï ¼PÕV%E!•†oIÙ&¹aOir›—qnv…:íý÷Dq~ŒþÔyeFendstream +endobj +2522 0 obj +534 +endobj +2523 0 obj<>>>/Annots 483 0 R>>endobj +2524 0 obj<>stream +xڝSۊÛ0}÷W ô%)D±lŶ-l»›RhKºñ¾Šq&Ž‹-{%¹ÙϯäKâ:^ºƒçœ͜™y²(Øú£à;àzÖÇÈZ®C  ¢ƒF¼@_ö³-"Üæ²œG¿ZØoá…ë8«ª¯ÈSuÜÍvó3‡õ›x†õ(ã ªmÌ%Ž±ÝŠ´.+Ùz­€RãE›0X8ác(4¤Ä×Aµùe"²Je%7È}dÙÄÖ՜‡ÏÀÍ^1‡èOêwÂv‚ì0óhÏöI8`dYÙ L¨jÁeW•;•ØÙ~ÿU>VàßÒ~ÇÓët]®m;ÐYuÞ?¼íƒü.³ýn~s©ÕyPËrͺNÔoºU™q…T 1p<Á—ÍF«óT£TP +}•UÉ%’‰ø„M(3ñJtDèKi¡+zŸjž˜XŒÊÿMkИk ßd<Éë=»¤®äRgCŽº:´íÀEæ›kÞÃ¥„—´NÁ_“L»áÔ?zêôQè]Õ±›{ÞNæˆ-R¸È§½h—È樰r4ÿSЯ ÏkRƒO›-l˃:Åz6¢LE\($|‹yç&Ú¢uYøŽ=.‡yA¿²Ôq»XpÖ*ïendstream +endobj +2525 0 obj +475 +endobj +2526 0 obj<>>>/Annots 486 0 R>>endobj +2527 0 obj<>stream +xÚ­Ußo›@ ~Ï_ai/í´PHê6)k³­ÓXBß*E. ¿zwtûógßAš&¤é¦)üÙþΟm lü1pÇôOŠÁ§hpñ9æC´BËx Jϲº+¡îÎîÎÏ£ŸáÄе­1ane¼æÆjCН‘v/lCY£ ‡”¯â&W]…7!Ôʦ¸çV•€›0Á.•´z’Xºæ2Y­²ª|!Uwc:¬Bçt«¦L(¦ÖüAí0%Jû4OSœýŽ‹:?RÑ7Y™äMÊá}ÒÔòb£Tmm>!̶&= ¤ÿ„q˜Q<— +ÞÒý²Ç€nWUYòN‘\>>>/Annots 488 0 R>>endobj +2530 0 obj<>stream +xÚ½TMÓ0½÷W âÒ"êÝ4Z©°qJÛ—J+o㶁|tc‡"!þ;3qšî¦Aì ErâÌ{“73Ϲïqpðâà y°N{o–½‹w!p–Œx>DýéO™î5X~è¡ ؂Ïãl”‘‚Wër¯/vÆìÙî5aÂt€âýŒàÌ# 1o ¼ ûe‹ +á­+¢4 +ãt/õe+/"à +pý¤«þjЎvq¢#}˷๒ѪÒô’¶«ÁjÏ®àÃlv;Ï?ÏWƒ–€x§z=YN:w…’ßϔ>1Á¯³„Œ1ÀŒÈ(ŠMœg2,φ˜"i$”:ζ@åØÂ°ä´òü¶>Í(Bz¿P +&‰Î)<]öæ mhá´ÌßÓ\2)x^³I`AŽjá‹-‹8·ßpGB휾±Q$®ÖМ††ÒüZÚH0·¦-”™å…9U€Ù«ÞÞh¹ý‹ƒäqtîª&iœØÓ“uNG&ŶLUf´ëÚ¸ã£Ä† <äÌG:¾¾Vz]Ä{ÙYwº»n€háùØ&NÍ-v÷,¸ËF5ZgqBW§Û­ÕÊ:vmó©ÀJZõJÚr§ªº!+Ó;U€ÉÑEê*quž®²Bwª<õXˆz&­V*¡9øGÅÇÛP§;޼>lÊlMù@+£Á =RY&†ÎÞ£â7yêîK¥f6`ÿñGy:¸~qM•7âUƒ£ݐqðF®ÅÃۛÙùÆ$ö|VäÛB¦©*4|”Y)b-iè §U›ëGÿr1®ñ¥÷Žè¨Iendstream +endobj +2531 0 obj +630 +endobj +2532 0 obj<>>>/Annots 491 0 R>>endobj +2533 0 obj<>stream +xÚ­U]oÚ0}çW\i/04vœ¨Û$¶¶[¥®b%h{@ª¢` ù¨ãtûù»× ÐB`¬›@ŽcŸ{}|?N: lü1p<úÇiçCØ9» +€ ç¸ãù8™uÇRÂpUæ½ðGç2ìØ–f40î>Ñ x®‡c +n`‰æecò¸ƒW 8»Â9kÎptFR£\éiwÚ£c¶6öÆy j›¾Ã-ÑX…I*Ãü"Òrmûô}ǶNFcçsý3BèHå ¥©T%|‰²*Zµ~mÒol÷hUˆFœwíkç7ßö›endstream +endobj +2534 0 obj +661 +endobj +2535 0 obj<>>>/Annots 493 0 R>>endobj +2536 0 obj<>stream +xڝUÛnÓ@}ÏW â%AÄõn®V)R åò„Ä/•*×Þ$ ¾±»& Ä¿3ãµëÔq¡ H¾dÎÏåøøk‹?3£)„Iï…ß;y僿ÁÈtŽQ%L¡R=ð?ct ŒÙèÏ(êï„…R"5°WÒÐ&0±ð†lÈ=§¤;:T272Kÿ@iCnêË<ÿDäWý«Áݬ>lŠ4$6ûx o—KŒQò¦ [“AB‹Pn¤ˆàï/!ÌÒT”i,U¶UA¢Aï²"Žˆka#‡S5ˆ42-°Ë Žeºý—Ò +LÛ XßõÅjõaÕFgª z¾ðm¤Ô Ê­ˆèþA_|’<5¥W‡'|,Ó0."ÏÂ"×';crg÷¼nÝuæ ì´ÁpæL C™×žÐù´• ÂSW¤Ô Æé\èÓ/"à ðø^ìi´mÇq ˆ¢ÃMã_-’ýNÆ0½ob«uQÅOéþjp5€Ggp»»Èƒ‡È 4$J‹é@Ü(|9êç?©SdŒ¨]IŠ bH³tH:@¡I–ÔέfQýê +ý¿±Î(|á÷\ÇEW £Ãê5Ý÷8Š* iËÞİ&ÃháÕýRÞȊǼÂꗤÉro³°²YUو۬<^ƙ>x·Ê¹v²—:ØÞ£òo™Œ !Á«ë *‚D‰×•¨:f²PÛ"AG«LoRõ؇žÐ„y̙aú±½Ý™¨[Mt·¶…ý•••ünm«Ëå9ÐþRç¸ó—V¢;Kk덭 +ÿËýeÐáþ%ÐУ!I¦~@ uJô˜öÒìʯ@Ýåšóz±cÏa0p;;xy¹\Ã:ۘ}€ÍT߇D( bÊڤጻ­¯äx:¯ÕÀø¬õÇÞoe"üendstream +endobj +2537 0 obj +738 +endobj +2538 0 obj<>>>/Annots 501 0 R>>endobj +2539 0 obj<>stream +xÚµ–mkÛ0€¿çWƒ¤Ô®%˱MÇ kÓQXiÖ¤ß Åsäԛ_2¿Ðíßï$YqšÄ!¥ŒÇötϽ*¿,ü°Çâeƒ/óÁù„ÁªBƒ˜c¡ƒ/Ÿâ$åO5œâýÅ®ø*-*ˆ»`t¡ uõ…ÚŒs¸L«Bˆ'óeZH/.D\¾ŠpÏô Ç7YûÂL8¶¥_.A8Cˆ²á௅¹_ñ<£^CcfúkKÄvM§Ï”µ6ÅZS-Xkí d, i ›ÅA$Âì ï)¿G3iÞ…IÕXû `]¡o( †MM¦3^äqšDu¥×¿Ê¸m©Òx¬ÂeOá%y ¯÷Ù*³þJº,—MÆóºRrG‡ø&ÝÖ*Ä'¦‹Ëñõ5¯¢2YÕI‘ïäÂjsÁ<Ôf–‹.Ol)÷-9&bW™bdüV›ZƧӖí¸. wµ}¶îI&÷—dógÓé5ˆF³=O˜9MiïEëk Jâ×M™·eëö2¨«ó&ûÁK(b(d!Ò„$‡5„æžÔ©ÚÙÊ@]3]½î)8½rq“G¦Tü’£#í_’úY +£¦,±<Ò¿Pñ”G5_´þTýèÿ}–Øq0<ù¸èƒ ?9Ûí”`ôÎIK¨)ÇùG¨¨#ùtÔ¨%”©Z~ޅå¯{·Ãó¸X¹Ú&µl'=6÷Ì·±µ{Ü|»•lüðØ¥–¿ +›’þPìbi/ބ% ®y6i}8b6oDŒQgýtšöäÍh*—G ÊÆæ™0ɒúÇÚb«OÎàæöÛNÅ+Ù +O—íŽòönÝ ž®æ›ÿÙêL„«Çé fE\¿„8§e±,Ã,ãewaބ©Xm¨E†KåD&ÔoczFo ÌÙ÷Á?ή_pendstream +endobj +2540 0 obj +736 +endobj +2541 0 obj<>>>/Annots 503 0 R>>endobj +2542 0 obj<>stream +xÚ­”ÛnÛ0 †ïóvÓ‰+ʧtkÚ«¡Y’Þ [I=ćÉ6ºÇ%ÙMâ8­w@G2ŠŸIŠ?GŒ~>ۃ(}Y®î@V²xSZÄ7r[§"«ÊËÕ²»€¨ìÈlˁ 5J‚Z>¹Óë[QF2)ª$ϔe¶1‹QÐ×Çâœ)©=zN]ŸÖX¤€e˜3‚5·Ñ +ԚÞiè\¦Nµ]ÒGQĚLŸ¯ÉVÏæó[Ø$;ñ,o8šV÷  ôÈJáÛ°"õª^dR©Å;dÈ(â`2­>Gæ¾¥«]Ѝ-W.×u„FðŠù6£KÍÀ3uoa÷mézt!ªZfMS¶egԐ¾²2P¨u‰²ÃÕVH™KË8쏣6_Þi֞CUŒ‰5&ÕY³4©ž.ž..`SgQ“±,.¡IV 9) %›$jóåi*%´¢]ĺÎãÎ~…iaºHñ­ÙUÆIíêXÀ§¨.Ê+¢´ž?+©R éAz¹V!Ö|¤õõ©Ù|-ÆPVq^WcugÖ‹ÛÙb=¿¹Ÿ=]^÷ð)ï¥p³+O;›‚ÓlîÑ3¥D!ÍfgêÝÑË-ìs®üü»¸Í~§­´‘ù ™ÍMæNüŽømf¾ÿ± ·g²K…„ƒC:‰ƒ²oè_šëB¶fu>gg-³Üÿ5hÑwô Eõ|ó>ª FÍmÿH}:hÑÃΠUû?´èºzÐDÓê4äðfÐöñè17)Ëåð‰‹¶§'î@D­>‹È힉{ÄùWÑ×w £V÷Vxߟû÷;m»Ù ,ÏÕNðõq¾„e¾©^B +<—ùV†i*d ߬wÊwb\&>g'·Äñ¦í@4‰ù>ú m"2¿endstream +endobj +2543 0 obj +690 +endobj +2544 0 obj<>>>/Annots 505 0 R>>endobj +2545 0 obj<>stream +xÚ½U]oÚ0}çW\±Z•ÔÎê6‰µ´/le@ß*¡(qÀ‰3Û¨Õ~ý®c‡”¯ªÚÃBNî¹×çžk~·(üPzæ›ä­o‹Öõýh‹ #½.ÒÎS‰ä¥æ¢¸XüBD”ZD×ïÄbÍÀ†ˆ uÊ2ç\ߧϝç‹ý´dÛ"1å@±"UPJ^h&»ªd Ïx¢Ú ‘ç±h·pq–BÆ7 RÇKHÏnÐ0ïúC¯â>~órÃjrÃ:™à'^$›mÊàs²-Õ5RöÖ_ Ô ¨×3|¹4»-5\âúæ8\·‰Ë+ W0Þ-gwãÙr:z?_ܜ gRçŒÁh£„ -✆ù¡ægö` ">6’Cdú±˜›Aàå +õM^`pë)4Yd—…ÌúŽYàï²îy‘Þ®OX3Á7=Ä +ð¤âÕytIUÁ‰÷¶¤ Ú1› ]]áÄ ¥!YÇ.mêyýFrµÍY¡•G®wJúžˆ1:¤^ӏOôžúÄ©D‹Ñ^ä@‡¸” Õ?û4ÄaY´ï‡{èêRÕg?"¦j0À ò; +v‹ŠÜJQ݇ú؋Åɑ­Ð'ˆZz´ÒÎê@ÎÜô"ΑTVqk@ïp£¾7ø8· +}RÄæøƒÈ¿Ó[Y¨3¾t$¥¥ i¬c~¼Õ§0-ØÕ¡­º?€/à{¬žÇ¶§h9sþ‡µ9¼)îäÙ%ÖR×Ӟ0j¶w¶2¨m#zzaßցۧéæ"Ó/1À©+ç9“ +¾ÇÅ6ޘì®MêöýênЀ˜·aàŸs™Ÿ­¿Ì"endstream +endobj +2546 0 obj +680 +endobj +2547 0 obj<>>>/Annots 510 0 R>>endobj +2548 0 obj<>stream +xÚÍVÛNÛ@}ÏWŒè b¼ëõM´•(—¾@›’ð†„,{¸ÄÞÔví×wöb“8µ*Uª¬]vfΙ{~ŒØøGÀ§àxç£O³Ñéu„Á,Å/ÀCr8åΗ•8š}]ÍF¶e£šüù¹û,/à¹~s N`y涄©4ÙQ(çpzgb@\_‚¬VÉuV$·Qùē‹…Èbþpøp´“0f‘•2§½í Ú-*3¨ I…|ä-’ ¹¯«:EC«cçK±F;Ôbðn3àcÇF-”¿¯¢9ׯ6„摺ÆÔc¬,<ÖpÜkXŠ¤Ù²8XU ñ"*áø‰ÿ|eòpt¶ƒNC p^Î×9/êJ¿»MÌl}éÈHËGuü÷%¯â2SQÚIœmÇ”vmf@<Ý%¡E¡ä˜µ]aJ˜åiJf÷UZk“Q×F« ™&FŠ™²¯˜Í&“Kay› ©Ô´t5Mȧ:Ÿ&è=¤Š(ç R¨ñ,DŽy¦a0=%ݹ׼3G¾ Ÿ;^¯ËÂ䝵:¦ªOÎa%²¢æ%ÔBÑÕUITG JørsYºõ$x…¨¿dX€(”é{®êÕê©@Ý/Bêa#c×4Èv—ö7YcàÒuKà å.D]Ç4»-ÿRä.Ÿª³4ã*•¶ìs:ºý]½Dùj¹§¥ßeE¼\'ÞÇëUuŠ~X‹€]Až>kðí¶â7¦‚>uL>À¾¡qœ;Óì?Ø?­âû˜°½ ÚÄt@ Ç!›§ƒÛRÛio6A¾Bþ“E€Ý-°­ý7ó_WÛÆüoLþÿ“ŸÊ=t|)áÞé4ÜXhÉ0Š\ÜO¦0iý¡è¤ó2Ês^Vpëh)©µÊØèlV3ó‚ÆâãÇ·ÑoZZÂendstream +endobj +2549 0 obj +717 +endobj +2550 0 obj<>>>/Annots 513 0 R>>endobj +2551 0 obj<>stream +xÚ­–moÚ@ €¿ó+¬îK[Az—’¨Û¤®ošÔn¬Ðo•ª(\ +Ée— ºýúÙ¹@•&JÎ>û9Ûgó«Çá‡ƒ5¤o˜ô¾Lzg76p“f¸0ô˜L³lz2ùÙãCÇâ\™ÌŒFWÅ A¢ëI íÕ?·`{dÂõ ôVî&(ãe“Û†Ui›¦m° mÓ8hÅ#÷/â÷Jª.¨4HÈ +|–YËôxŽO`‡â•Úxg7>p›âÆ`h™†M<¢Xª4'€&® ¦KÒ ÈdœBA!7paHßïî Ž¶DRäÊÄkœ†6Ü8˜¾v|%òPÅõé;œS¨´ˆU"JòMœN¿—ÛžŽŸN¶·C´LÃCésA°ïÖòL„q‹i%ÝM}ý$™.'Âò×â²?Äi¸XN| —Y~†°Æü3©’Ǥè2}¦‚|.àŸÏ+1gºhH¬HA?·LT'ø­hàkŽFÁLŒã?âèéä¼ãd`,\,rù¦êxUHø–g¡»|¿~Yè:jé«4"U»>)Ñ]ÎeŠu®:ÝqfNíд-ƒïòÈjëœû~ã²_ÖË>¾5Õ} ^D‹­Ë ÆÎ¥}t3Xß´ñ5ך܈²Å4Îc޹è.,IØ2Óª‹>„2Í 灂Ӫ•ôõ«^ 5ûÎ$_¨Ù2iQ]m§¶ˆ–JÙ¢|Ž†uÜÌÝ}É,Âmºûú÷=̨Ö6m†Š­¾´ÕÏMî×a.ÉJûïìè&·ÈÍ¡h¥všb´ÞêèÛPïíèÜ/»óxZ{÷8aèz8ˆ Ý=ˆ®M3ñPÄR»3¹MerÛÕcÿÐá뉢1!Î!)oIu$ +Ô*ÎÅÿŸ,oïôž¹²š "¡!HîkŠ¼á¯½Ê*Ŗ㸮þ/Àåãh c«£7Rr¦‚$*‡û ] Ú=Л®Yæ—[&­Ú˜1Gg|#´˜Û½¿Þ+bßendstream +endobj +2552 0 obj +768 +endobj +2553 0 obj<>>>/Annots 524 0 R>>endobj +2554 0 obj<>stream +xÚ½VÛnÓ@}ÏWŒ‚Ò*qw})Z¤o‘*Ë^§¦¾Û¡À×3ãõ:­›[­H$Ç»;—3gç’ ¿ üdðn18ùà7aâ‰=ŗ`tñËKÖ±8Z|ÇS®<œè¾ˆR?Þ^û›uq²^ÚÍ% ®Ù$ƒ›×a‹ëŽñý´}œGi.GÃÏ¢,EEôGÀË + ¿¶\¦Ãq­Ä™6%%4÷©¸ôò[,Éφ3o%æhbˆïÒâpyoaCxE?f%îÊˆ¶ñNt—Lυ€³¸Èèøb1`CšèÁéñí#-À2§øL€s]ÓëU s¢°¥¯€hã\:±ÌÊ ±E¸¿¬Ë(K‹åhy´×çŽæ4u¤€ïóȏfíQ¬¼Ž¡¢ñ@"ñ}–†q䗇QéÜÂûS¨ Æ5³;*DTÛ{>Ê`¶æ6 Lîö¡JÅÐA:¡·‰·lr1Î*ÃÄôNÀu›E·¤2,Y5$™U‡aÖ;uÖºfÞÓm‡ó B &köªÀ*ÛÝ~fQlµzÀþê;ËW›D¤e!Ï­&]L㖠‰p—cq0Ú>…ŸGUèXf5˘ SÃàS2YÙͲüXX7Ì&)­3†4m¥«^©®ÕbdÕaM¿«Uö+d‹³Ù9ÿ€f›ä¦+´Jz'´-±Šê;øÙÂ'ò…SÝêá$¿—ÒnRŸŒB‚‚xq Y%Ú +¤ø7Yä‹¢´ÚVTh;r@û?3gG~>q"p‹ú¡šrÕ©x¹eKPýg‚ò)ÛéŸûfBã÷ù§‚Â%;jg\*Œ^¸zÌK΅ΰT½`=ódà&uéz2ÈE·ä2Ýý)“á¡nß¹€ò e¨U¤cð1í©[x9ߊßwYÞڔ¤©Ô©Jh“.ÔÆnX¡€÷W³9̳°¼ó°#Îòl•{I"ò.½tãŤ=‘JGg­ŽcÚS5R¸aÔ×òuð ø¾Lendstream +endobj +2555 0 obj +769 +endobj +2556 0 obj<>>>/Annots 530 0 R>>endobj +2557 0 obj<>stream +xÚ­•YOÛ@€ßó+FôÏúŠEU‰rTH¡¤$¼!!㬃‹¯®mÑö×wv×vq¤*‘eïÌì|;Çί‚I?˕ÿ0|N®|@¦IÜ!½ÌöÏļNyV•ӟ$wQÊÑô ÇÌ_֑*è£á‘9-_ð2qQÅy&%—Ӂi˜ä´{Ü}{HÚ.=‡€®cX€>í+8Lz”چÙh3f¿ÑVôvCç˜rWË!=â(Š™"Sû+²é3‡ñø¢8á[Иo¸»£)í4 „.IÉý ÿóš‹>¨,H9äTôžï94 {w<¥½Ïñ=C¥<|Îão¡[(­§s¨ØÎtZ»7¯‹ªt\…xÇ«ZdMM¶Y7©½ŽµNŸ¸´ažEIV%ęBo3ohóÅæTÎ:ï*w -2‘,³›@¼Ü*³‡ý‡ƒ·¦ûÕY(e’Z©Pʂ‡qóY“í&¬ëÉ.i¡‹Vºö[±#…Ÿâ,Lê‡Ïa]”'d<‘ªRuíÑâ£<üc‡ô~º*^>}ÁÞ8˜óIü—ïÑûˆW{§=Œr‡ çp–”ùJi`“mú‹¹ôL)4Œ­¿íwb‹KC~y¾gÙF»×¢GµØzdԸΣÙyl³Ö*¯G*å›eÀÎÛzÛHÅСˆ·T–‰”ߝ©ÚC|€êZŋÏ6BY¦kø”M]øPµgø”DºàQP'‹hmr±´¹ª(YC÷ýîc·¢B«›«-ÜDUï5Uo1ݙd{[ð¥Æ_ê ËÔÝu_R'õ÷Ô[]].áP.¯ï·uZ•ÈÐèÊë=¤-7_ä¾äR›áÐp6h¤½UXÚ1¬tãF.C•“y0ƒHäéH[fbgH¥Ý ¹1R“²íóæ Š<ÎèZ”´A7_ ¬D’! MßïG#ˆ£7ˆfSÌ Ë+xâêœÍÍ?l³hËt-Ôõ ç÷ã Lò¨z h×±Èç"HS.J¸ ²:H¤õ±6:ö˜Š$Z¶\µ-YãæJÅP< þWsYendstream +endobj +2558 0 obj +798 +endobj +2559 0 obj<>>>/Annots 534 0 R>>endobj +2560 0 obj<>stream +xÚÍTÛnÓ@}ÏWŒÂKŠš­×ñU¤Ò¦)´¡I*U®½Nl¯YÛþž™õ%i.¥¨/$ÒÊöœ™=»sæüp0ðÏÁ5aâ@˜ >.'—>p –1F¢Ñ…(C•U"ó£åwDXÀyƒ›.!–šÑ†FE]"¿Ý=MA\ç!%‚¨„æó ˆ“T@¬d+ &q"¢æ{’W2‘Iõ›5ÕÖ$ǦÏ4Íé¯ +RÑñð»°MÁ7I¦u$à]Xå ²cJÎÂàÇ{Ú·ø|چ¹Á< +_~žMá-N·5Ç÷K}à!½æA&ÃP= «a Sú[¢œ]P¦²O¢[G'ÔB8KKIáér`0ÛJ §åæ½€åҚãô/),¨ã[xµ‚u Ê[ºç —¦Ÿ{÷q9³û¸e1~h'£ß©“…ãt[k)=Ǫ×eô,nùÌéù˜uòb>ý¥DjIí+Ís ?nê'f#ޝ=éóÄh„v[«ßoW 'âè°vÎÔªÎD^•MÜnã{Ì܆‚ûœ¹˜½ë +ӝëÄX¢'ÜC5sËŒÜÇE ¼þ]0÷mæ·hÓ¢{Y£µ1u­± ªjØíŒDš˜.otf¤'2jJhd6Ú`žgkú$š—²mÐ{Ù®¯ÚtÛ&߈ªVyyÀDÏ Ø.¡Ùn˜bY©:ÄDx«ÛÙ ’X›deFË +„>ça“|—oŠó5n¾Ñ—ÿÂØiFÚ_íx;Ùô~c¿¾¿¹¸¾š}û‹¹Óµõ#¸ê¼}=^ï=>zƒãhïóÛù2®~¨¹’+d™P%| ò:H)wܤŒ]sßlZŽ×M-ŸØ­þ¿þQòAendstream +endobj +2561 0 obj +687 +endobj +2562 0 obj<>>>/Annots 541 0 R>>endobj +2563 0 obj<>stream +xÚ­UÉnÛ0½û+é% b…¤© i ¤I܋ۺ±s ¨½’¨jA—¯ïZb˒だA"ç½áp (üQYêïGƒOóÁåØÊa¾ÀËÁ—àt&\‡™<›ÿÜÍÄ ¸L=¨zÜV`™>#°¬æ#„™ŠØÂ§K¸ã;­8L[q$IpÊL<ž>žõòØÔ0":"†ÛÇD&^1YVMuŠ`Ÿ*¥æ["â½bèÈ2x£†1f°ÃÕÔâ_)h¼›ê +¥³~XÆŽ˜Á«Ým/߬óіÂ=dÞR”³Üj’™Uˆ§®Êá|+œ/ã,å¥p®±‰Ç³«æª0×鲈Dœgå¼Y%蚆݆(u)N5|+2?]'ùZÆ;5!UM¸ƒh“pÃA^fŒ€ºX•T`AvÁ*6©ÐŒÛ[hÝu±L‚Q9¢¥£ÎQËÓ$ZÞ|%@ ƒ\@Žï +¹Äp^‹TFûEsÇÄ*ºDwŠ~Þqn:eõïE^¤qµã¼é¼!ӧ﹎s‘*µL§·¥ö,O bF)|}˜L`]fÖ |Y„Ä2‡Bçit½”Ð*^‡ µõÉë?ôÏ OaQľ +¨©³Méj»µTU Ã%D"’éß~™w¼( {:àÝ:öÃ"ðÞ/’ìÕ«ºAËjuÉÕî4|€­¼NêódàðIãdŒL¤2áòã f(¿Î†kªÒiz¸:m¸!{S#®õ0âöçÞgÄGHGñ-v"âe¾:֊¡ôrh…j¼ Øôå£<™þV–l)¢èGî^scÄÆä5˜”éî3d¼jYµ¥Z–ŽÞXqí/]xVÕ¥Áº´š‘6±æ^سy/$X3ÈÖÿ^P†4ÎÁÊ4¸sǜº–Ü5(ØLK‚›‡é fr‘ÿö:Må2õ¢H¤|ñ⠕´a¹dX­Á&S£œW×]ˎ¾þW…endstream +endobj +2564 0 obj +751 +endobj +2565 0 obj<>>>/Annots 545 0 R>>endobj +2566 0 obj<>stream +xÚÍUÛnÛ0 }ÏWp$EâJŠoB×ÝÚí¥²&Å^ †-'|›ì Å¾~”Û­ã6ÙӆŠe‰‡ä1ùkDà‚Ã`nCŽ>®FgŸ9PVZlÂñ­¨¶2+'«Ÿh5Rm1GYW‰ÈÖÕò*ܕ…â(!þ·ñoqEgU ¹Ä³±Fvö0%dyâ1.+Cûê˜Ì7j.W¢ d\Tqž½ÂG›ÈÎ4.Špžnj–Þ؛#o|¢ã‚ xgÈó²“)ô"ÆíWUBžxor>ÀZݹ.“2WæëՈ¢ª–Û/j¦iãšçí&¥O/×ÐUAA]XûÕtF‰iX­;ʉ1Éiý5Uå¼q8­õð·†Ó ú:#nnˈ¹®ÁŽgÔð—¤~Äa—§¡û±ŠŽ:0Ófs¦8Ô³’ωÒ]‰¨a™* *•ï$Ø]×Óæ‚<++6¾„ÓÌOÅË»”ëm*°h»Õd‡˜}„PN ïû×{ÙÆ™.¢7±JÔr tαDR`uöÁŒ8˜f˜ ç ºn…Må,ec.EœNJͬ¾Ÿ4=g±¸•‘Ô ]M­FPӄl¦ ¨ò=ÀH½n:WÛ¯гlÔÎÑôjô`溪3¦,ÇÈ¥žBB•÷fƒA.ã§Ë·»››3`žinj—§ñEÈý¿2”´Zo€úï¡:€ è÷†§Ó¦%–ÆÓçÞ\ÔÅjæ6Àä›Ïuˆðén±„eU> +l!óµôÓTȾúÙÖOÔé™>4séiʹݦÐ¹³“ÿ÷Ñ'­bHendstream +endobj +2567 0 obj +709 +endobj +2568 0 obj<>>>/Annots 550 0 R>>endobj +2569 0 obj<>stream +xڕUmo›0þž_qê4)©µyGÝ*µk»/”5©ö©bÄ$L€8jµiÿ}gÞ² ™!Ûwïñ=¾óÏ ‚? +º%ÿA2¹YM.î ¸° +Ñ`98XOÏV?&JTGβäÊ ŒðkX•÷­!Õ·=&͖÷WtíàHàƒüêDµ¤ãSn•µ­E3¥)Œ¹/àp'œ=‡Q̞œãxO ÁÖÏá<õVkÛ£åu¾Ù%,Ee7ësbJ»ҁºTµŒË·¬ò(O„!µ0†ƒÞ1U ¨é *ÔÅaÎP•cgØxøÊ[ÃDØÿx—ý Q̔6ÝÕÐXå´dVî_2[m,· 32NMw,¼œ§R«¼{¨U„l]—Ùîá#—‡ pœ¡peÙ½Aβ° O&Wz÷æm¯¹®»Õýzdb—§µæF[{Šf7„ËÆÙ0.2DaÄÖ{ql+ð¡Qçl°æ¬€” `¯Q!ԞëWÕDç Ðija¤ +÷È)„»4;bʃu®a¢w¯~’ÅUù.Jƒx·fð!ØeÅòS·Wu;Õh•ôN•^vÍM“>~ˎª}øn Áò3o6\Û'õiJdüºOW““ú4%Z{¬ÿêÓM@êUŠØÛ§Û§÷é%J:Ö¦}O¡`Ñú€OO‹%,y(^|¬£EÎ7¹Ÿ$,/à‹ŸîüXn§PÃEbke•Sݑ«†¡WUßIþ×É_Û]Fêendstream +endobj +2570 0 obj +738 +endobj +2571 0 obj<>>>/Annots 596 0 R>>endobj +2572 0 obj<>stream +xÚ͛QsÛ8€ßó+ôx÷PW¤D‰z춛NoÚnn“Î=;Ž’øÖ¶r²Lÿý(NBúvöbugÚp |1AIø?g*Ëá?•Õ:+ªl±>ûåêìýy“é<»ºÍ”i²ª.³«›¿]ͯWmÖÝf»Í®Ýì¶¿ú÷Ù¯Wgù,þ¥ð¯ß?c#«Êþ^g…™•ÜXe—?ïï²÷ç&S +è™ÙEßÞÎ-þŠ¢˜™ûŸ³ÉÿQ¯Ú¤¨Ð(` F©ÕLqƒòþ¼dÀ$T lqÀ—?·»v½ +œ5¨—3R¹Ÿi¿=¶ýã²}B\©f̈́Œš²›Ö³ +†hKø‡²³ùÄ"ü©&ƒèŒÁÎZðsj“7Âïíî©ëÿ€Mԅs=͐WGóÐR—CJ?¿‡–ÚPÐñ<ÔÃ\ºШ×—‡zL«0Àp7s¢;³Pv1܆$îfÒÇ—¿µC ¸›Q.¾¸ ÐN$:øÓ$Ü^©1¥ÆKùh ³#óQO´î,’ÈÝLŠOÐÆÐƒÙÀâ~fÁD\Lhc^Û²¼Ã¾.¯ûyï2¶b[ÀëSXk˜Â¢± nÑÔò—)Ú ‡çv×.âI@KÞž`ä.æ R`°oä0`Xܤ>Ð,BBZUެ¸?åu¦5fï!ŠÆþð:P"Ns0 ^€ËÈõ˜Ô–±àæ!‹˜õùûL¨¬AÏa,àͶßu‹nsë\¿ù«\_åñTXãvÞ3 jŒ;oa¼Ú¸œ‘$‹ûéo ø©˜P¢±­ôZэ|^ãÊq-±ÒAÆQ¾l«ýMli +}¼¯ÆÛ™€æǀ–OyS0VÒLàÕ.+QnÙ¹–0“i޽ՒН6Äy&Îã¡ÕŽ¨Â ŸS„V;¢ÐäÎâåҊ¤ÅKC›+Ùõ„ÅËêØ+( œÉÑ&ç˜øm¿Ú-V1_ LTõáôL¾~𗬤­ M{ Æ|…ZÂÖ°©Òv:ß,ÚÕ*nmÀ›ÖïmÃÌ.{p×8­S*•°’¢gbŒd–[ÂJÚ}úÏí.áŽB-^€K, \<ʘ5¸A( ԇÇùråÞÅ#ш€Í=Gÿ $ sqÖßF’AÀ´Èঠy,@¼ùæ&–ÊC H€PòF-ÿ?­¹¤»äþ­Û…—Ü„;kÎ/ÝG0ƒÅdBœ`âÓrwË¡G}t< ‡4ð/ñÃsb/i'Y£JÇm­~'ÏñvÝ%¸U`ÚÈþ?°öI"¢*¶®ù¡ÝÅ)j [[~f?2´¯ü xà¯}ß ÷Ƨ?B'ÍTU¼§âŸZÂL¿Ù_@ zêú›m,̏ºl°!Ï 02G¥:†xsøá¼@=œßî±Zb᪠+\QAñvIŒ*ãçE®—FÅuæê* +w—ÏNxør3±›9eé&֟ô¨%²Ìÿ§“Þ@s'½€Æ8µ“^ÊLš‹(úè*ÜJ4—Þ©o¦ l¹hÆ}uɪàLc}IP»~èâBwsãÉâé£xòîďó)óT¾òç» + o*.ª¸l77É'; LQ57®›ißÚív~ׯn G=T!Žº}O{`tñ€_ ‘»*•ñ R~$êf.Ø·~Չ' cü£¢ŸÇi6t%s 2ƒžÏe%„z©–p±èöî…éÍO`Æ,¥ÒsnŒv)µßJÖkˆœï¾.71Àkð…Kò {~èïÜ·1©FÛ¾iUzÊ šÊ;÷LdÞµ|Þü ”£¦÷‰¡ÞÆ_jnxƒv†¨O|êÑî‰eQ>|Ûúì ¿3ÜðQæÊý.»ÛÝÓ¼o³‹¾»ëçë5îÕßæ›ý|EG9ü¦×»šÞ‰—lµžýö§Rendstream +endobj +2573 0 obj +2588 +endobj +2574 0 obj<>>>/Annots 641 0 R>>endobj +2575 0 obj<>stream +xÚ՛[wÛ¸€ßý+øØ}°BÜHâÑvœ¬Ïñ:®/Ûí##3»åRRvÓ__ f@² ªí‰©f÷8F0øD €Á\¨±,7ÿ±Lðÿ|ytzwôîƒÎxžÝ}ɘÒYQÊìîá/wõçE“­¾dg«nÓt›õOwÿ8:¿;Êg¹!À?n>f%ŸåY!µù¹Ì˜à3N­Ev øýcöîƒÌƒ,¬Êáóλom¿ê–棲W?*¤›Ï*åLğEˆüµî[˜…}tɌ¬ýçÙ[þáâÕɈô&Ô¬2s©<·mÐTÌòF¤‚G~ß®×Í|Óv¯ë& Õäl&cõqóµI¨9mX²œ1Ë ìçë㏗ïx `ÝØLíI€€ÚŦéÇŌM°l©uÃýιy`3ó€®Es=mþµ€‡¾èÚM[/Ú%—.„ÀÒ°R!Òxfzé‚ÁU€úb ,Òôd¯C’k³ÝÌ!‘C#8$,ŸY‹u½Zonç}û”0 Áh‡I؇!¯’ž÷i»yÚn¬jôDŠyAUòÕ¹™F¦*aMceÖ§‰½û È䂐ŸL¨i§Õ싈…½–qœØ‰~Ü2SÏ Ôm)ëÛ´mS!KË]– +X×}kî«þuV0ޝž•1Œú-ì}ß~kz{0ŸÓï^¦Š*´µ±%ljl ;À]ºæÐ¨2GKûÉÌï[Ûü1áù¿ÍÚZc¥ +´w9‡Å³-o•*ÑØÝ_ߦn=?¬0˜ÎåˆvS¯“-$ž3½Ã#⽯75ÀXe–nºeÕµÖzêÞ6UKIƸ~LÜRÁXô/TL¢~bÌç«mÂîR=›ÖójDA"7¦Â(6 fÚ°W‹UÊJùÁ°wJ0¹!Šú öKÝ}ƒï @+=•†Fµc ¿µ¼¹‚ó`[zú»Í·vžtPý`0âpG('`iu÷ò½ü`д½" XÔi»YÖO Z0~i‚*«ÑH š6@I¬^#¹ða 6¼Ç¥rù†%‡qCÄ£~¹wX2°Œy(b–CXr}v™ŠJ<üp€c ¸éZoÀ:„Å4'Œëôá’:·—ña45üْšáEs}ý>ééÃXat¨Ÿ áî^þāø£Z*Kòÿa»`+PSYáµsÓÔé°-û¼ƒˆæpÌa»å;< žsx>™½y2‘Š áþþB8"•½ÃT:q(7D,ìåû„#¢žA¨›ïŽ d¼BÃT;­ç¿7Ýšxilÿ!9Øb$ð–¢ôÑ6^Š&¤¨þŸ¢ 1’Û‘\’õ³Ç×¶ûÀÚ¾Ûf¾5;åû¨p8{”#œ âÙª[·M_oZó` 9…YU}lôÜ]+PãhŸÎVË¥ñ½Ž/Û®I礆¬`„4žyÒ?n—.-+sòÞN;cjºBÇ¿2ˉ ¯¡µsüŸ[&ë"£ˆDýÄúØt´[¬:ÊIÇ=dœ½Ü…ŽØT{ŽCê 9Ô_`Ø(äˆrJ†~¨‰ÿµíkbÏÿœ/¶k㈦̎'€–´1ÄÏ Ò(ªYc’ ½ •4ª#UQžG˜€­@G&¶ÂÌL³éۆftX®L_¸B*ÌtCT„ w Yã·oÜåpE<ê'âq×ÀâzˆXN€`· k©Û äÎÍɌy$P¸Ä~Ÿª ã ­Ò»3uD#‡ÌnŽâ­ æè·õK,+Ô +6¸h÷o·OOF)£E¥Â•µ•!Ð s4ç µÆ#摀ãµëùÊøƒß­õoxS*™Qý˜A] [’¹}ÎOOM7ýùѰ`àG,@\ú€ƒ]¶/F¡¢FW0¼Nµ;I@.›u.&qׅY«Ü´õÐ +Ö*§‚ñhÈŽÇ·TL3‘uú-åY2F1‹\­}•ò~ýhˆùóÝY:½êöÁpXù +.þVä5íʏ-<תŸ¼¤|¸UØ +ô“S!}ô-æp<¦ ELs<«ŸêÏí¢ÝP]Dñ «ócJÒ®þ†EÇåwMµòón¾‚×sÖ?Öbÿ“ãiËR1oL+x**rÿ|ww4&ÜQð„ìå/Yä³$|ä6TÏ!óTÄÅôB»|ϲ¥¸¡<´·MÆæ§¨ˆÃ«t*®…+|ÁdSo¶ët]®8\ۗÉCi»é͒zOOMó}ªgÚ}ÅÄ6]Áۆq)\r÷%±fïUÙðþ°| 5òfÇB¶²éË Œ :ªb_\'Œ€h•”GìÔþ¥¢ÐèCӔ­ÖùæÃ—D+ò³„&…¦¯eeÖÕ2Ç×ý걯—KãRd¿Ôݶ^îÞz`Ùq‰E®¶%EþõèßhŸüuendstream +endobj +2576 0 obj +2515 +endobj +2577 0 obj<>>>/Annots 688 0 R>>endobj +2578 0 obj<>stream +xÚ՛MsÛ6†ïþ<&‡0ø&qtì¸m&™8þH/¹0ã²#‰)µÍ¿/X€ÒÅbã{Ök_.v,óýŒfÄ|Ѭ`WÙb}öæîìõ•ÎÉî¾eTêL"»[¾¸«¾®ê¬ý–]´›m½Ùö/ïþ<{{wFrbðÂ·›_ *'™Ú|_g”¼@k•Ý~ïŽî!{}%2Jᚏ¡$¿÷¾Y7"ç™ý]>“R$œç2/óšç ôüãÊØVÑëÕóòîË<]óS xȸ±G7uß®vÛ¦ÝdOòB„ +evôy¿ña¿8¥pR&D"Ú|pã-ÌwV %¹XWͦéÿh6.7Óe&árPj•3ʸâ¬ÑA© cG>vÉ„uQ²Y8˜ô®ä.ƒQj‰³ïJûð>íªU³mjë/s6Ÿ©œôOi—¤È`îÄ%©wí×§çnp+èS7i2‚nM8™˜œQˆ«„HR¹¼Dµ•dá’Òuט¢ØMd¹à~Cãt`û,‡¨%Œ~§W+)”à.Ù1Q`­@(!\²ûøXwc&0É^Î$’þqâr¡æ 9+ðϝp'µf×ÿV kZ›U™:Bk³'@̐~ùßÕÕz‚ &)H ïðŒ,OµâN*m¶ÙbTÚZÒ”¹Ü Ò&`ýÁüä½iÛU]MO,aóqãÄžýD ¥3×%nd@g:s­sv¸ÎÌìúö`~òÞµSɃ„0 êÆ0€°ÏÕjWû³á“žžJPÛÄ Õ¶V vyDöPB0Bùjï¸m@ ªaM#q€ÚÓ»|öӈ¤Ä Ê¡³‰Í˜#ÊáÚdÎæ ïb·ýP/›j*sŒ ÐÖ#1 1PYŸ`=’ÔÙì¼ÇRè¬@g©)…Ì:Áüä/ÿª6‹:¥uÀYgŒÀ‚.¦â¤Fý|):©±AtV ±PÇÁf7òÌ@ÞûºZ6›‡·Ë‡É 눁 +ÄP€ÐHâg]t$U¶ÌAek*s~T ô0Îæð`K6µ¦åáh0ÆáîÛ*ËÉO ûØTápÿOM}ö6†"‰FuXE©Ž«(#G<.’p ¡p€£ûçé"JGb ‹í˜è8âIÓû„ÂÐÃaÛ¯aÎ@^_IlÍÃ(ìÁ^L©< Iìãð2r^MptÀQ°î‹9:ä˜íÒn±ÝuN^SUùì:êàÓç ¬pMc{VáŒáIø—$¸ÊXI+ǵ2eLu×=mOÈY‹L(g“S*ÈêΓSÅ1Y}€±b@Gibà]W“E3¸’œÚÅ4VŒ¬_M®;{¬IN&ü„Î6Upl÷ڙ̃no”*¶}/S©Âãô>Î]öœdª@ŽÕ6æèsµÛŒ‡Ç‚Ï¢·úä“à‰\Á°Lù`ý4Y0ì*/výùrùñøòâËKàbNo-Løìf9u}f (g“œb›ù¾7³ÏؼžpÒAB‚#gl Ÿw»µ oF}ô”{´ô]˜¨ÎÝ£¥Û«×¦a‡Íçeë_âÍ8Zøf,7«gþØ:½¬ûEרy8¯%KÒ?… K +%gþ)ìV¾ý§Z?®êù½•ôO`3sFàž:õä[QjàP{Tð:¢ÎW}ëޝE#3-“-=”c’@ä:kì×QŽ]H(8p|³z×~ +M¶:("˜k(ڊ㌠"›{½I¹G|ꍳÿöëf[oîiß¿ƒr£ãööÝ»ÿo¹)±-e«M÷ÌJìHÍ·Ö¤^ Æ~-5*nT)lͷФ^¿u­[ dÜ’ê°ƒWbB†»ªf\^dâm¼Ñ&‚– ¼ ‚í¨-—íU³ªoêﻺßúú¢É>>>/Annots 737 0 R>>endobj +2581 0 obj<>stream +xÚ՚KoÛH„ïúsLaæý8&vœÓb½¶r˅ëІ=QÚìÏߙ閨 nÛr%Ú-|b»Š,ëÇB ™ÿ)a|ùÿ°^|\.Þß$¡¥X> +å’ðÁŠå·7ËþïÕ ¶âj»Ù›ýøvù}ñi¹Ìʃ*wŸEНÞ¦ü¸JË.¡Z‰û2þ—ŸØ=‰÷7V(U^0há,¯÷a÷tX_ÇúΉút÷y×7®‹\úN£Bðg|֙ãnØv› +gt˜ÀG¨uçë©5AEó³¾À\ãÃîùeÿ¼ÝÔS˜ò7³ lòÉÔÙ§T§P>%»ú ñéß~ý²êŒùT³9ƒ->—Êf®E’ùD˜ð\ +Yg’ûa¿C~Þ';„Çqԇո-£TÊÏòy›üoñò/i~›¢SºàU…xÙ)]¬Kðpx¯·wÏÃ0ùú¶Ì –Õ:øÆ:øT +¥ì± È: ~õeìŸê®ëÀ î,@çѯJ"„.€_± œž5`W5p@H7N È>HÏ¿pjê„yµdP¡NXs¶äaÀмZ2(B±"çkÉ->?UÛ +áóXl_¬%kÝvõMÏÙó ù8 y6Û˵cm^W¥|Ñj²cm±GC†:æäNJÍåcù +²±  +òjÈ È6hìÇrPaE^o@B…9×[€&žÄ~òFÎûq-±gœ7-B©œ@M„*FÖiÓ¤ ¤!AàÂÙ ùqøñlgݐ¿ò6UGVr]ìÔäÈʓ†<;òm?Ž?·»oGOŽŽ‹k5×Á’~YË¿oڏƒ"„†y?TOc?^íÁÓì͸Å'±!3–ó†\IlÈùÚqƒ/MŶ1Ñ%,µÙ^ù·à"ÔÚ5¢šYKÄN»4Q ++;›GqӔQ¯§Œ'e¸']xŽUø1an¯áâ §æœ=pP‰Ã‡~慸c¹ß`³ØˆÃŸ_煸Å>üRÃEGZ-Å_š%öÅàMlòô àˆŸ¶¥Ëô $qõåö^Üo÷?ûÝ nwÛ§]¿^»QüÑoýªŒ{§r¸(ñ.@Gúü¾…-þ'Íãƒendstream +endobj +2582 0 obj +1201 +endobj +2583 0 obj<>>>/Annots 786 0 R>>endobj +2584 0 obj<>stream +xÚ՚ËrÛFE÷üŠYڋÀó~,[Ò&©RLzç "CŒR|(™äó33= ª2‡»4¤*ª.!6qÆià­ãñW0'™²ìi¿úy³úp˜äló̄ Ì:Í6ßßmÚßw;>³OÇé;œ†÷›?Ww›ox¬^DzùòK5œYâëž ©UԎ­Sù7Ÿè·ìýfB¤/Œ«a Oß÷¹žú—×ÓËñ¾)P,/hþç'+Εi|r.D#Š*Γ;e£Ž6îþm÷¯».ÕR¾‘4¼UüÅuþ¤llö§â_PşJ:½­<_‡‡îôØ¿Ävé‡oï¾½Ou#ã´º#yht4BcŠ@ûQð&_‡v›÷¢t”öâ-M°q•Ó1ʛPÔäЄd(ÚùØoÏûñˆ×6n .«ö¼ñd ²çóîûҝÎý![S²q”v`՟ šŒXPȟãšÅ‚Ô[@“@ + +ù3@³D‚?­€/<ìi |YwûaôQØNz^¨,/¥>î†c*%B|—ÎfR×çQ(W[5Í£P*͛_ÚÃös÷ܞw§qÞxI‡WªÒÂe^åyõƒðÔ§MÍW€+ÀqVÈ׀+Ê@®8Ôùp jr¨ƒ`Ñr͟sЈ¢?ç3t\ógu&MÞq =k4u uȳBey)EÈú:µåÒΧ6Ïj²63ßžŽß_ۑÇq8¦¯˜„^P.Ó*Ãê…Ø×äq\3(uU:ù…J°"{ò_³—½qڀBö„lȟþWªàËÕ[š6 &‡*6®¤=mjþ¼Ìäi +ùóÄOþk¤™‹ÿâo›5c˜5³Bey)µÌY£Œ/׀<¢Ô4k” Sؔ¦Íýî<üq‰š4•V¿©!´™Ò&¨!"yõÂŽŠ€E¼Ê +9TŠ:¯Lş˜W"Ìy%9m^ÕÜqƒxÅç¡¶âöf^qƒy… •å–4¯Ìu^ÉPÂqžÎŸ@M¼’A½áUßu#®¬'vþQééP<bêé× ZƒB-õx¼fÏ(t‡²gô¢i,U@wá@!wšS¿ Wó'!ÏЁìɒ×y<ÖÏ +•å¥ÔBy,J6ÎåE!‹’Œ<~è.Á±U”Îoj A9™ó9®xÉÉ)Ù^7(¼+ÄJ@59ޓÆq͜Ãñ8(dÎ- ¯9´8…Zòñx͟Æñ8(äO“ÇkþŠÇA {êæx|¬#gV¨,§Ûë#Gȏ uQÓÈr¯O= +ǝ^T?p‘ƒ@ýÀ‘W œ‡y@¨çãoÇã~žŽû„ã®òìÎÆí<·ä“qW{0Mfž‹ⱸ«Ý¶™R&=Åõ͙¸Æ‘¸~›ˆkځ¸«\Ðxœ/ù7ñN—†Ó]ß{/yzGðä’_žöåY`ò{JÄ>}}\³õñùôOÛwì±?nûv¿ïúýÚÎí.7»JèúÉAØúwٔ¿­þԇæ?endstream +endobj +2585 0 obj +1179 +endobj +2586 0 obj<>>>/Annots 835 0 R>>endobj +2587 0 obj<>stream +xÚ՚IsÛF…ïüs´†g_޶b%—‰¾ù‚ȐJ¤’üüÌL7†ªÌÑ---¬z„ØÔÞù×J ™¿•0¾üÜnW׫÷—Ih)ÖwB¹$|°býýͺÿc3ˆý¸ØïŽÃîxx»þ±ú´^ÉNæ åF•›ë_EНÞ¦|»)uÅFܔéÏ0ދ÷—V(Už/há,O÷õÐßå)tè´¨wuL¾Bh ×Ō®¤Ïÿ:(d/|Ægq®‡ãÓ¸«»Ñè.pbljÝùB¨MgPÂ|¯/0¿ ‡Ûñáñø°ß•yy”M>™:[ø”ê*§dW‰OÿöÛÇM]¥&rZ¥->—ÊȨ̂Ì/ˆÏ¥rÄe’›a?C +ûÉ.ávõasؗQ*å{ùì¦øS¼|æÝMõ0•¸F…xÙ+]¬‹àöéñð¹ÿüR×ùáۛooËÔè¸,ˆ3”°|ªvUY A‚[qöã óèV²K¨¡ àVÆû§í)جÏ;ƒeÏ0«7 žµ`Vœã¦Eh$ØLP„Ð(0¾qÓâS|¦Æ (§"ï°iÑIþR¡ +'-øË Âç`ØÐA¸G½Î°±â6 æ°±IK•¸¹êÇÃÀ7oÒùõ`C¨~Uóļlˆ`Wœó¦è-ÚUÉP„Ð;<'âš7-<§À­jހ"xNsO›Ÿ à35m@¾l¾‘wÚ´ø´£©iŠðiFÃ7oZ|50o@<¥Á_Úysšy³„ÛqÓ¼IçóƤ.%õ¤æ¼1ٝõ”7ãÃîxù°Naã=+Gn­“Ãqê¢@Ì+ÂDÿÊóÆ…†UòáË9çM” <Á¯jހ"x._1Nœ&¡uà45q@ÂüZY։Óä3zª‰*Âg X ÛÄiò)ìºK,€ xZ¾,oNS oc`; â™6gv¤œ;qƒŠ¤ÄN|‘6Óµ/§\¯èxÖ êñš7 æõ ¶ãŒ§ °¯‰ŠFìÇÙ&Žjày¬µkâ€"xKmΉÓ"t§f»$(Bè˜çM‹Î¤©)R¨ÅJ›oÞ´ø4Ú5@<}v;qNs qƒpû©ç™9ê|æh…Ÿòùè5gŽVXŒ—̹îÇa¼ØìÓ5NH|B§¹ $ä8rُk‰ý8çÀiªˆ y P3¡Š¼/pt.R8"pÁ2/œš|^’ áóŠyáÔä³a.œ@<_Z8æ€/áöȹp:³›ª+ƒµ¸*×· f;VÆÍ…Øñ—Ça7¹1ŸÓ«ærÐjn›@å Ù[q OÒ6"|2v¯ÚŒ“%eSZvãÉñ¯šxQ‘¦).»ñ¨¹÷L 8IÍäãâ,È'î%“i}Šeî˜Ü²Âv/<ßÇøº{Ö/9Χú¦ñæ96àvä­s=wK,×Cÿý·ü;Œ§x)6ö?¯…Öë¯#é”â³J‰£Téf49}ô7âGm¹Þò «#qñõêFÜìïŽÿôã ®ÆýýØo·ÃxŸûÝS¿)ãÞ©ü %ÞhFÿ~À=øûê?Óä*endstream +endobj +2588 0 obj +1214 +endobj +2589 0 obj<>>>/Annots 884 0 R>>endobj +2590 0 obj<>stream +xÚ՚KoÛ8…÷þ\¶‹ª|?–mÚÌlÈĺÉF“(~d$'íÏ’—Ž®‚Vôη `àXε?“9G>Ö ÁxüÌI¦,»Û.>¯/“œ­˜0Y§ÙêþݪýgÓ±ý»ØïÝî0¼_ý»øºZð†Ç éF¤›ë?⨆3«C¼Ý2!yŠÚ°eÿæ/úGöñR3!ÒƗa OÏ÷©|ÞŸGÛÆ°|wsî¯*àÊ4>sÛÈ¢ +x‚S6êÈqÝžû]†S²qDàN#”²±yiU£ŠB„ñ^›`¾tÃ]¿~:¬÷»¼„!>˜e•‡F'>!Qâ¼Éÿ_´Û§M—WÐÇ¥&³‚5>ÒÎܲÀãBñLpQG’e×±_ÎA +*Ç˨O›aŸF‰ï¥ó6é_âÅÒø6y¦Ó6Uð¢SŸ7ÁÝóÓp݇®¿îÚû«õn3ܾ»}Ÿq¹>»kÍ@Â^°!»Uñ¥‚@{Áq0«›¡}Ì]:Jý$@c‹Y¥…³"›65<­À«rڀBxZƒWQN›¡âà29m@!B%Àcè¦MO8°™œ6 Ÿð´³¦FÇøK„,\4Hb֔9%kð r¼Œ"š5f>kt†HYã#¨1ktàRcÚ|ëׇîÏ9]ÿ7‚Ÿx†1oí\¶ª5 Æ­ §¢55@«‹S¥¨…­)gCT£¦†gUŽPÏHêASãS,& (Ä}×ÓšŸÔà19h@!>iÀcèFM/GC‰OHð—zÔç@ÔL•ãeѨ±óQ£‚—ŠçЦ¨1jTtgù“¨yûÉæìæ<ƒ™wƒò&»UNãnPÞRϚžŬRրB|ñ1žtÖÔðŒ¯ÊY +á™^E9mj„Ú€Ëä´…ãZiÚiS㋠"_ÓâS +l†nÚÔøôÛ9@ <ÉO˚ãȚÉ8ƒˆ&«$ ‡&<¤µ‚†—"<Ͳë_Æ2ÆÐòâyÔ¼d€J<§ ˆq7ÈPqÊyStõL ¡çô{¦¡µ¨g…­£Þ3ÕøŒB=(Ägˆ§Q£Saì™@ 8ÍO홎sÀ'ƒàøqÔïiÉR–6\¥bÔèÉRº±gZv‡«v¾ïûû‹ÏGkÎßñœ¶º„›&h3M¿iªrŽš&Pˆ âM“ŸÇ¾TâيAxÂïajtn¬²EQˆÎ•"›®×ø,tÙÙ/A <[ªìºç€O•ãeQ+öóV,´{=£REV _ŒV<=C¶©‹¤tnUÛ +šñlÈ Ð–P¥§lÈ5@)ÐÕN ¡ü½í˜ãb‚ãä‹ñ +_À½x˜Öâ|+æá<*Åý´÷'Wâ7âþm!îi÷áaއ-ÔáÁ§kÙ¦e¸E]xôà›90o¨µµ`P!n¦}¸!_O„Úw?¨ ×Ó2\SïÂ+lÒ£«-¥S-Q¿Ö2ÍdüõŠ__®ø•)Nl(»¸¹Z²åþáð½í;vÕïûv»íúýÕîžÛ TKésêåèËz]ÞÀ¿ÿ }æ®endstream +endobj +2591 0 obj +1214 +endobj +2592 0 obj<>>>/Annots 933 0 R>>endobj +2593 0 obj<>stream +xÚ՚MsÚH†ïüŠ9&‡(óýqÜ8qN[•ñ-˄ "ðîþü™nI­T­‡ãÈvQõZÐðJ­§G/ú¹ŒÇ_Á”MÛãêÃzõþ>0ÉÙú™ ˜uš­ŸÞ¬7ZÖ=³»îtmO×ËÛõ_«Oëox¬Dzøú™9ÙpfuˆG&„hª{HåyE¿cïïu|bzC'™5<½ß§7Çó¡Mï¢|#YþgSÁçÊ4>:¼±(Ðx2§lÔÑÉCÛ²ÿ­C^ +{PÏ áv,õÛáÒ¥R"Äÿ.a7Åw“”ñãF{Ü6 +ڋh¥Š:ZÙ¾œ/ëöx¾ßÚoo¾½ME­Æ«1zCGð`ìˆÐ¤#oò öxÙìr»KWS»ßbÐ?r<–’7ÕäЄd(5j¿{9èÐ6îŒ:\^°ç°Œ'c ˆ=Ÿß×öúҟ²5%WÓ,ú³HO:…Šøs8ó±½lûýùºïNù†øä*\ý ¨É³ñg ¦Ú‰óŠ¿ŒR£Uæ‹×éðe1‘Ôh |I$}¼´ý@Ñxºº0sãÑT<Ã&Ó9˜Jk*¦iÑ p7Y‡Â/7\QÜdEüq½pÜè¼<pjò§ƒX.nÀŸs°œIÆ@{ÎnÊ Ü¡,pg…p;–ªsÄëTÖV∧ù j²¶@õýz=8tÛûÓn\àªZzý³ÐFdfe(ƒ =aªGrɞrˆ¬´ÀEü)Wbµ.pKö¤be"ƒ"ö¤bÕK䒿L˜‘ÈYBgê%rÁŸ +–D › &{*ž“ò6"u€È³B¸K-“Èʛ )ï㙠b²òvÀñÝ÷vûc`±‘µ±ø¦ŽpB¨Äc¤#âSü‰¬ŒGd%"ƒ"Md-•ÈJ V¾EìE'Շ²à0~`9ÎPÄ¡R@šzgNɟ 8(âOÖrÝqrƒ æøÍ!÷P'ÿ5äKU:qäëG9^ +JTÓȑCî'/ù³4'EüÙêsò’?Mrrо9'ê’g…p{Ý9¹zÉBAN\ê5É…"1ù]w:µÛ똒óê \l Ibr¤%äâqÌiLŠøãµÇä{Aw,I“¹€y͉LÁžÇ<?ÏÈ=Fäõ]¸kJ¶r ¦ÚõN]ºÁ¨’¦1óÛn\÷c ˜1´l­yɯ ßÃB.¸ùƒð4]>¶ÛºÖ» KM !‡µþ<—˜†×>>>/Annots 982 0 R>>endobj +2596 0 obj<>stream +xÚ՚KoÛH„ïúsLËÌ£çuÌÆvN dc喋֡/ôðR46?g¦‡f3@4ºm+”h·ü‰Í*©¤VJÈô_ ¯…qâa¿ú}½zw…–bý(”Âyëoo֛¿v½8>ŠÇÃØÆÓÛõß«ÛõJv2MÈ7*ß|þ˜FuR8ˆév/”–]¬j'îóøŸ~c؊ww ”ʘþ ge~¼÷Ãöe?=¸ÎŠrw÷ÿ‹Ð7¶ \ºNWUÁ3œqI'ŽÏýø2 +œÑgw¡Ö+§Öt¦*B˜îuæ¦?= OÏãÓñPNaL?̂²É'c™O©NUEø”ìÊqûc³Þõå †tªÙœÁŸy3÷"Êt¢PÌx6ú¤É}ߋ_Î!¿ŠÏ,ÕãuÔûÝé˜G©˜î½†§)]¤éi +¦8Xˆ‰E¥KFiCفïãø|Óïú±ÿúæëÛ<ÏjN«ðÊj+áb1­“Ï¢ +á%z֗Óf[ö]{nM@ëªgå8BE­GÏb:-<0hY%tP<´,ΡÓ"4ͦ„*BhZ ßÐiñ)¯—Jè "|*ðŽœ4è/%Š pÐ_.ˆœ:§FT×QL#Ǟ(ù2Î,ª9s *t©œ:·‡‡ã·ÞÁ”;α2äÖB€÷ŰJ࠘|@¿ºâÀÕ¯rà "„Î֗FW8`ÚU TÏjîqã|ƣє¸AEø’ûÞqÓâӀNSâáӝ†oà´øJ@ÔÀAAð”FiÎ4g1¨¯£˜Ž;8&†âRéݍ¯bÎ#šTɛa8SØ@.1ؽÉio… ¶¸VIóV˜à¸gN Ï«jZ9sP¾ô3uæ´ðl¨¯Žræ "x6¢g]qê°è6%uPÂt®àªSÇýÚ©ªŸ1è7W›:Faé]¢ÁÓò²Ì™¦`æ,ÆàqÄ4q|#q$Öã²EIҎçđµωs·{9}'‰ãY&Ž?¿:bW^ż:Öªœsæ´}-ËKæ "„¡–ål3§…穝P<ç¹×N->kH턊ðYæŸt´èLœk'䥵Ó4y1O£®Ó“µÆrÜ»¼ãÚ-Z'­ýÜ:}ìÇɑÓ&XŽŽ|ÉZ(3—O(ÈZ(à_>µ¥$å*B(óò©§‚'åªOö°‡Ÿ7¤|BEø

˜WO ¼¤yŠË² Çí°Ùïûá$þØ^6»r)~óؓ>ý¨Oߟ«ÿ=HáÃendstream +endobj +2597 0 obj +1198 +endobj +2598 0 obj<>>>/Annots 1031 0 R>>endobj +2599 0 obj<>stream +xÚ՚MsÛ6†ïú8&‡0X|ã˜&qÚC§n¬ÜraÚUG®DO3ýõ°+q™™º´=ò¼¢´òC®Þ^áAh—¾ìV?­W¯o¢PR¬ïØ(œ7býõźÿc;ˆÃ½x{؏Ã~<½\ÿµz¿^ÉN¦ +ùòÍÇ«N +gbºÝ P²‹¤¶â.—ÿîÇñúÆ€ü‚^ ge~½7LJ§ÝùuŒë¬(wwÿ÷WŒpm»Á¥ë)ÏpÚ%8>ãÓq_à´ê|#p×*Õ¹riu§I1Ât¯Ë0ï†Ó—ãæqÜöåÆôà&(«|2v&ót@ŠñìÊâý·~÷¸Ê éR7sk|6æÎ܉(ӅB1áÙè“N$wà ~X‡=ϓ™¢ãTêÍötÈ¥ ¦{—pšÒ›4¦ /¦I^rJJü9Ž†ñ]?ëÍnøüâóË\5¨Åø•u±øUŒéOFÁºÁK´«O§þ¡´ºò-µúU€Ö‘]å$BÅ­G»j3o@Ê +ÑhV%nP1:cЬš›: –è2%mP1@ è1¦M<ºL T BÃQS‡“½¥ÄAŒMô–+’†êPÒðBtœJµ˜4ϝ¥4¦0¤³’?¡˜rÆD@¢¤¹Ù Û¯ç˜q²™˜¹²#Œ÷Å®JÚ ˜:Âø€nÕlÚÔùœ!·ÊaƒŠ:K+¢e†±€fU£³jÙQc´G›)QƒŠá%ë KŽ£ .„JÔ bxÊ¢Ñ46PÁ+á@aƒ‚сBk©‡Í¹†Í¬§Rm† <6:†bPéßOb +lYÃæç¡¿ÉS‹¦VýWµ„¶øUISKèàϚ²«œ5¨^zLh9kjt6 [•¬AÅèlD·j8mj€Æ¢Ï”´AÅӕ2M§M /]uIT Oktš¥¦œo—H@Á蔼.kÎU0kfeð8ZfÒH; –P°¤‘4ÏIóË~3núíæßËüÌéV†ÅgXõ|;¨ˆ3ñ‹bji$ÞpÖÔø|df…ŠÙ¸YÕðœcf…Šá9߸YÕð¬žÌ +£³W.ŒÏUЬfeèxÃËbõ¼Y)MSp›Û[ǙY)#'³ú­t÷éìTÖ·¶2®wƒrÌ«Ô|®”_¼WÄ˺‰·º.®ÑIš‡—u1*F'iÞ𺸁&â%jPM€’ƒü4ÉR ÎÓ{©AŽFÙù +Fçh”]šsŒšY!:N¥Ú ý|؀Á!xYE¡˜Â ÁsØÜNãe­}òZÇŦÐ8/yƒ‚5…¦‘xÃySãSÀ¶:¡b€ªé‰Mz¶› c“¡ñÝLUÀhØ^¦8‰GÛôN¦*[¶)ÌâA5½‹©ÊæÂ´‡É…™¥¸xí&*‚)ëàÑØîö¥jÆXœ|›wõØùÖ¥ËçÉ·ÇÍ~¼¿LlìÓä«ÁÀ4e2ó¸Qo^ªÂ©À¶.©ðÝT©íKm⒗½¾öúj|“ÑèH¼ýt{'î÷ã?ýq·ÇÃñßí†ãIüÚïŸúm.÷ +R“‚xåq.úÎÞï«ÿû‰ÚÝendstream +endobj +2600 0 obj +1212 +endobj +2601 0 obj<>>>/Annots 1080 0 R>>endobj +2602 0 obj<>stream +xÚ՚KoG„ïüs´YÏûqt+§ŠHÝ|ÙH+E_YRˆ~f¦›Ú^á(·^P\«éÛ¬¢Jó÷J ™ÿ*´0^<ìV?oVŸn’ÐRlž„rIø`Åæñæÿc;ˆÃ“ør؟‡ýùôqó×êëf%;™'”/ª|¹û5ê¤ð6å¯;¡¤ï4ª­X—ñ?|Çø,>ÝX¡TyÂüßðN–ç»ίã¾>‹Ñ]õÁŽÁ%mݸ.tm:ƒ +Ñ žñYg–_†ÓÃør<¿öe^~… È6žÖ/xJu +ÁËоP|ýÞïŽÛ¡Þ¿˜W€ÉýkãÉÔٌ—dæAè”ìê»a= â?ço…—ÉÎÁõ˨ÏÛÓ¡ŒR)?º€W)ï¯.•·õN—wÂeq)dAþ<Ÿ·¯ço¾}Ä=p|ÞÇÿg)\4ÕÍRÊ ¦¥p±ÞÇûSÿ\×]>ëþ>:ŸÐ°d—P¼ Á°>Ï¯»‹ó[Ïä^¶éœ¿ªIŠÐ¹~µÜ¼qրÓÔ¼E­ŸYjÞ8#«Õ@ހ"xF×,5oœ +`-%@:ߗ6—)6³1x=òÍ×Èiª=UÛA²FZp§’5wCÿx [>f± ›k°ul½]˜4 ¦u°IY1Κ_hV%k@ÀñCÓ¬iÑy ^U³¡ó¼ŠqÖ´Ÿ©YŠ:Í:iZp&À砚4 \Ž•È:iZxڂµSAè´kigÍedÍl^ÇQ‹L[©à-œPMqc•ƒ‚¸y8ì÷ÃÃÛ8>òz3ûë aR¬nU³Ä´&?ª™gM‹/:4«’5 `ôœ“¦ÅxUMP„-ÿ›ÈÎN/ù4^º?>’ÚÅq;½Ô\çȱ¥yýíü²“Å*rfÉÎëo«yŸXJù‘XÒñ‡*‰ýq¥J7¡É·C¾ùZ[ÎÅ&lÄ—ûÛµXžÎÿôã nÇÃóØïvÃx¿õû×~[?hD¿¿àË÷ûê_Æ÷ØRendstream +endobj +2603 0 obj +1186 +endobj +2604 0 obj<>>>/Annots 1129 0 R>>endobj +2605 0 obj<>stream +xÚ՚MoÛF†ïú{Lavö{ÎWÑCÔVÐK.lL+*ôUIFóó»»3—êUOۆŒ+ð³ó’Ãù{B¦_Úå¿oÛÅ»åâí§(”Ë6 +çXÞ¿Zön±ï÷»ó°;Ÿ^/ÿZ|\.d'S„üùåöáU'…31½n(ÝiRq—Ã?ùÄq%Þ~2 ¡WÂY™¿ïÃpúv\Îëý.S + EYè~êÈØ×¶  Ržá´K:Q|üÑo›!ÇÒ¡SЮÃSªs /ÊôEE—N¶Ë wà þ3NõQSD• Ò`©âë3->SRqôT ‰@WD<¦Iç=Vªâ4¨*:°R1vh:ƒ5¦8 ª +ÐY¬0l¦…gŠLvTžU¬}¦§=––¼çPTl %\ç3cô™Y Z§P<}ž÷£ Ý´ùœáEM>c”Å5sšÓÅjò¥% Òv6”³GFƒ¢ÊPX©MƒOÇ@•* ª P'lÅÙhZté®[^ŒUEÜ˶íKL±T^zOxÉ6£m¸4†€T…g#Ö¶F£xÆbiÉn€¢¢K›Ì\g4c4šY Z§P<F=o4:íÉrÛçs1ùŒÖëú̇~j 9ɤH]Ÿ€}òb5(ª|P’¹Ñ´è$5ÃÑhä¼®%5ùMƒNEêa£A5Ñ©HlÆVÓôØÆF«AUêc³µšžs—¦ªð5®_ªÕ(‹mëâ(*:{¥ÑŒQÐhfah±ÍèçmFé±ùíSÍA5ùŒ2ÔüFŸùuwVÃñb5×V֍dPØ/>ƒ¢JE]pÆNÓâꃧAUõÁ¹:M‹NRûFÎûàJRóš±Ó4!øj\Ձ÷-M Îëj$Uç &ž“ÓHŠŠÎÁµ#ctšY ZÆ#-¯ã/7lÔä5`¨ý=óšÏÇ4¦‘ÚLã(ª|Жû8@“OA5€ªT¬{g-6é«qT› ìÇ€ÑTÓÑÌjU´ÌglªQ€0ïZÅ| ÁæÂ4àæýj¯  4sžÌŒqxڋiŒŒ=ï|¡kí| z*sÛïVS»Ì1*¼Í00=ý7ó®·QìŸýÛÆ~¨ý«ð¤“ÄûÁA›¸äeª7ÐT¯ÆíEí"ñþËç;q·8ÿÓñù¸_ûí6]îˆßúÝc¿ÉáÞ@*» ÞxlþX¯éøý¾øƒÜ×Üendstream +endobj +2606 0 obj +1209 +endobj +2607 0 obj<>>>/Annots 1178 0 R>>endobj +2608 0 obj<>stream +xÚ՚ÉnãF†ïzŠ>ÎÂé}9:³ä`bknsaÆ´ @[(™ÇOwWQlˆÊ·”-@À/Z%ýdu}buý½RBæ‡A ãŏýê×õê×$´ë'¡\>X±~|·îÿÜ âø$>—áp9¿_ÿµú¼^ÉNæåI•§ûßr¨N +oS~Þ %}§QíÄC ÿâãF|øb…Råó×ðN–Ï».Ïã¡~ŠÑ]õŎÁŸRްn\‹um:ƒ +­{Æg½|Î?Æíé²=J¼|† “´=­;_ì)Õ)T½lÚŸöûÓn¨×/æ`rýh{2u6ÛK2ûѸS²««áaÄÆiÞ +§É.Áñ)ÔÝî|,¡Tʯ¾³”óW +—ʲ.Ë;æµ +Ýå2âRÈ:;ٞNw÷ýa3œ¿¿ûþ¾ ªslV3™.šZÇRÊßĜ.Ö+øíÜoj¢ëÀ'Ñ_çÎ',U²K¨{AB©º7Ïû©æ[Ïäú)å wÎC¥ª Õ¸s*cÒP­SIª1h-T¶¤¡ì E¦’TcÏ((2lICÙSJKÁˆÆŠ¯ãÌ8³ƒÇ#_Êx‚2Ò`y²WÕPFZ(OH™á|Ü=—$ŸH#§dØz™0 æ4°IA‘bÌÊ_X¤ +c@5CğAo“1Ö[ü!TªqçÔ(ƌ „A§ ¾Tƀj :͚0”9 ÀT€jÌeœDք¡ìåºé'€hÜi¥…f̳„Ç1Oʄ۔±ÕUÉðX2¼ª™2Vi(P/)s½¡IåWòÿn–L“b­T•3 æd0ùU͜3”¿è°P΀j Fϙ2”·|Ó¯”ÕxËÿ™S&]„ +S)ª1èÔ¶œ¡ìYwm)T½œˆ–5g({9Ûôč;c ´Ðœ™âgð8†âəx›3FaK\ÅRUÓϜ1ZΔyNýØ_Žãµi–¸,g:$´¿3rÙý6»ßŒ9CøÓ ûߕ3 fƒ:aÿ›+i(wÛ֕4 w›Öo—4Úc纒TcÐcçš-iaϙk;H¡jì9ޜ¡ÌhWW€h¼YìVӜ™âgàøŠ'gÒmÎh=µ½ -A͜ÑÛÞHšË¸=l&ÌxϨÓé  ý]I¢I…ÝoƤ¡üIìiä²ÿ­%ö¿¹’†p§bh&@ÍîTä~GCÙ ¦™ÕØ –ùeÏËf +TcÏ+ÞSZöl˜§@4îl|íÀH³„Ç#ã)€g©’F™©ùrÕ5“F×Ni˜Žù Õ<¢ÉͼuFº“¡ÕØ“‘õå.Ùf + -›àÉqŸ ÜEՌDµ(TQó ¼ùØìÿûeÇÚ'Þ»ÿZQÃ)Íæÿ²Wí^¹-ƒ!pç߽ܸç»#sãÜàŽ Þž•^ŠU‹]«¯›þŸú˰>®·ûá +.+—¼ü:Λþ:¾h!qßòs³3yã8ÇkË-µOØ-¿}}ǧË?ý8ˆ¯ãq3öûý0žÅïýá¹ßAÝuy•ÿ ús»Ýâücõ//ôÙSendstream +endobj +2609 0 obj +1220 +endobj +2610 0 obj<>>>/Annots 1227 0 R>>endobj +2611 0 obj<>stream +xÚ՚MsÛ6†ïú8&‡0X|ãè&q/mǵ”[.JL+ÊèÕè&?¿v%®2C·‚¶G3/)¯üËw¡×ügB¦oÚåŸ/ÛÙo‹ÙÛÛ(”‹G6 +çX<¼Z,?oz±ïö»¡ß Ç׋o³‹™ìdª ?Üÿ.¼ê¤p&¦Ç­%»Hj#æ¹üO¿qX‰··FäôJ8+óëÝVÏÛÓë×YQwÿï(¨pkۅÌ-]§HwfÓ.é„qßχ]aÓªóM°] ¨TçÊÂêN“b€é¨Ë,ïûã—ÃúiXïweczru<;“ñ: Åð@våjøðc¹}ÚôeýBZèFÖ¯ŠgcnË­ˆ2-Š‘ÎFŸt™÷½øeö«ø6™ËBtžJÝlŽû\ +b::w)] é] +º˜Wp©P\òHJ¬ŸžÞ÷›~è?½úôšZܶsŸQU¥!\,~ó_‚5„—hWËUivåÛiöëø¬#»Ês´íªÕiS£3ݪ˜1*Fg ºU³f\ÃÓòì2@Šái@i֌kxà‹Í cÁè \iÅT…¬˜—¡ó¡]#V#–wS‰J“bN, ÚSòâÛõîáfëÏÏ£%ûlgM°V{Á”µ"F1ö‚‰€65]6ޓSeFÅ}@§š¨gШʮ£sªá] Ð}œËƒ´jÊcÆhO.“Ç *—fJ˜ò˜1Ê µdSAÁè”Ek©šS4…è<•jsÔè—G)Tiϲ1Nª;íúÿèw«áëiÄXÕF“_ËZ:BǀŸó°A1v„NGUãæÆ, ŸP1ÀÐô–¿ÆæL¨[zNëS Ð0¡b€660ÕðŒe*†—±í€©†—ºí0¡`tZ_0êà°¹(DçuËSeØhÀtÜç¥E1­$š¿úïçt ÚòàëBÚ1`BÁBºæ¦ +ŸŠ”‡?F5ªHyøtýXùÈ2&T 0ÈÆ3¦žs,cBÅðœoÕaÇDPŒp‘Òìfg}™-`ž]æA€ W ”f× Á9ëàYªÓ攱/O‡xÈ~Ç"ð4c%àiÄÌûïûیûmíüXnñ¹ÌÂmë»ý +š¡0ÿ«|™…ŠÂ[,4Åcp~Š•Á Û&Ï7úºÑWåIâ"…GâÝÇ»¹˜ï‡ïËC/îûÕa¹Ýö‡£øs¹{^nr¹7ø@¼ñ˜þXÿKoàß³ÿÚ~Øendstream +endobj +2612 0 obj +1200 +endobj +2613 0 obj<>>>/Annots 1276 0 R>>endobj +2614 0 obj<>stream +xÚ՚MoÛF†ïú{Leöûã˜8vOÒXA.¹¨6í²D•’Ûüüîî ½ÃÑê֕ xEićÍ»|Å¿W‚ñø/˜“LYö°[}X¯ÞÝ&9[?1a³N³õã›õæmÏÆ'v3îOýþt|»þku»^ñŽÇ +éA¤‡Ï¿ÆRgV‡ø¸cBˆN Ú²ûTþ‡wLÏìݝŽ/LwÞ>ïöûfwØöéS”ï$ËOvÿûŸ¦®Lç#xàEÜ‰MÙ¨#È}ß³ŸÖ!o…¨—…p;–z¿=Ž©”ñÙfŽ’ý)]Üïx”¤Œ{›èTbÉ +éTÒéÙH2ëaׯǏ›SÿíÍ··©ªs`ž£„^à!ž»Ø ¡3(H/Þåo֗ãæ9÷¹tíôùE|&ظÇñ,JÞTЄē:tz~ÙÍ#CÛx,Z€¬Óy#Œ'.P„Îç“÷¹?½LûL¦dçÚ9}u<`ÀÄ/›BEð‡ñò±?>LÃá4Œû|úB|qu#à!]™(>#œ~M˜’ÏÜ=ÎNcLcNSoËKº‚´‚ͧK5>íHºŠjßvºT£S˜„gŸEè&á×ë3BbŠ}”M‡gŠWà¸{ͅ*Ç1ÇnÕejxsë4SÂ2¶˜Z×M‹€ÇÐ*°ë4é1gŽOö/^/Ô$ˆb1Sïè0wÃþñæÏqx(·dé+ê ù7ܔµL¿-†ßíºK Î`ú ?“/Ãoc6–˜ÆÄ~!_&ßÓêv]¥F'1±†‹ÿC#¥mS)`üõ®^wõÊä#6`ÌÃn¾|ºg÷ãÓéßÍÔ³OÓø>>>/Annots 1325 0 R>>endobj +2617 0 obj<>stream +xÚ՚KsG…÷ú½„C¿ËÄàT‹›Á;JôÊHNøùéîÛ£¾ã*ÔÚq”Šã‘¯ôi®Î‘ŽôÏB0ÿ +¦lúw¿Yüº\¼½ Lr¶|dÂffˇWËþÛz`»Gv³Û‡íñðzù×âýrÁ;'¤ ‘.>ÿƜì8³:ÄË Bt¢¨5»Kã_üÆøÄÞÞêxÅtƒN2kxº½÷ßûÍ~=¤[Q¾“,ÿ°ûé„â pe:Áïl…;±)u¹öÃ9èWáÔóAåxõËú°K£Dˆ?%ó(‰ÒÅû%)㽍tÚ$º¬ +]\C+Uԑd¿¸]m>ôãßÃÃ͟»ÕýðõÕ××—»Ÿ»çaxˆlqBgŠ@› x—ŸW_ýSÞréèlùE|&Øxã9”¼ EU@OÚÏñéy3†¶ñ± Ù¦ó + Œ'.PˆÎç“÷y8>ÛL¦dç蜾6ž `/ñ©¦ŠBxŽƒ¹¼÷ãj\í¶ùô…xemH…àâu<éœQ <ãÁZR€@t&€µ´“fšI3TŽ—Q4³FÏ•ë²É @Õ¬Qыtɚ”4ï†Çþy},­;5Kɇ_4KT^RµwÁ¨Z+@»`ôu{°TÕJ žæ´k%Ý “ÕJ täk¥ P¨V……&^+µð8Gµ(„ÇñZ©'¼«µˆJ'ü…Ÿ‘OS dfcÊqŸëó#´Þ^ŧ%ˆš0ÂéS«ôq?œ²E§W„LøÒm°¼öJ Ð6XA¾Wjñi‡Þ¶B€ÚÓî•ZtJ£^ ¢S†|¯Ô”õJ  ”¤ƒÆ4à¸C½(Ç=ñ^©t­•¼°æÒR© ˜ÁSਡÜ(™ó1ã¡ñŽ +þ_CÆËS›”2æöô¹…qÔR¦¹Ö×>É΋oÈ·I¦õeT&™yëm,åd1­ÏcÊ'kù£ñyã­KáM8Vt²4ÕðÆ¿è‘:K?U*?}“×—oòÊd6”–‡Ý|ùtÇîvÇÿúq`ŸÆÝÓØo6Ãx`úís¿NãވÈ'Øýç÷Wåücñ?6×Cendstream +endobj +2618 0 obj +1192 +endobj +2619 0 obj<>>>/Annots 1356 0 R>>endobj +2620 0 obj<>stream +xÚՙKoÓ@…÷ù³l¸ó~,¡´l@”&›nB놠¼pR¨øõܙ{OÚéŽI+E:±síã¹>_|ós$‡Áœdʲ»åèÝdtv˜älòÀ„ Ì:Í&÷'“é·EËÖì|½Úµ«Ýötòct1ñ†C…ø"âËõ(Õpfu€×%B4‚Ô‚cù>ÑÍØÙ¥†ãá4¬áñxOÓåfÑÆ£(ßH–ÞlþûŸP¦`\™ÆƒñÀK‚|Goʂ#ã¶eÏÖÉ>ŠP¢íTêíb»Ž¥D€w«¹JöYwpÞp•¤„³wœƒ TäÚÐJœl6÷Ÿ7íêr¾hoOnOcM«êi†’Ul`¡!BcHd !x“n¯›ít–š]º#óg‚…3†¥”¼ ¤ƒ&D?±M»Ùã²Ï máZÔ`²ìÎ+Ì1}¡ÊÜù´x×íî±[%gJ6®žå+Û³Sî8E*³ç8fÌûv{×Í7»ùz•–/ÀΘ,Û3c&QUfÏ8Œ™jYS²§FKŠÌÖ-eÖôu5…h;•:JÖÅ1 „Œî’Xc”À€Ö\AlW³Ý÷ž6N×Ñé¯káRV%Ò ÈÚAø#ç WU‰3Ieö¸¦¯CÇɝn´ž3¨w:LªŠIã +ÃŒI¤A•t¦ZҔìYM!Iƒ*³g †Lµ¤)Ù3£%ö%ŠÌ‘¯ãL_9sP†¶Ëz)ã^¦ŒVã‰G¾ (£aµ}F™ñüOÅO4¥f:eU⠊¬¤Á¨ª˜4%©={Ò Ê ¦¯“¦àNI•Hƒjp§`Qåq“Fyƒ)“Hƒ*3èí1sF9± R™9ØÇ3g”ñ-(2w&`´”IÓ×AÒ¢íTªNÖø—Y£´Á€âîLTkd‘ÎXóu~Ÿ=ЈJrªdÛ¢Gö¤A‘µƒRU“¦äOД<‘UfPòš9SòÆi€œá‡“pÅi|]1g +e vâ ªÁ  4î–4%{.ì‡B‚TfÏÓàºZҔìY[' ÈÜYšZ—IÓ×AÒ¢íý¼^Ò Öøþ9O¿È¥x0û•ß\Ùxý°û=íZvÕ­gÝt¹l»-û4]=NxKè˜7ãëé×|N—ðËè/…§¤uendstream +endobj +2621 0 obj +885 +endobj +2622 0 obj<>>>>>endobj +2623 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS04±Ô3T072PIÑPp VÎO+)O,JU(ÊO/JÌÍM-*VðMÌ+MÌÑ Éâ҅hхê©(ËÌ̉»†pr÷Á5endstream +endobj +2624 0 obj +104 +endobj +2625 0 obj<>endobj +2626 0 obj<>endobj +2627 0 obj<>endobj +2628 0 obj<>endobj +2629 0 obj<>endobj +2630 0 obj<>endobj +2631 0 obj<>endobj +2632 0 obj<>endobj +2633 0 obj<>endobj +2634 0 obj<>endobj +2635 0 obj<>endobj +2636 0 obj<>endobj +2637 0 obj<>endobj +2638 0 obj<>endobj +2639 0 obj<>endobj +2640 0 obj<>endobj +2641 0 obj<>endobj +2642 0 obj<>endobj +2643 0 obj<>endobj +2644 0 obj<>endobj +2645 0 obj<>endobj +2646 0 obj<>endobj +2647 0 obj<>endobj +2648 0 obj<>endobj +2649 0 obj<>endobj +2650 0 obj<>endobj +2651 0 obj<>endobj +2652 0 obj<>endobj +2653 0 obj<>endobj +2654 0 obj<>endobj +2655 0 obj<>endobj +2656 0 obj<>endobj +2657 0 obj<>endobj +2658 0 obj<>endobj +2659 0 obj<>endobj +2660 0 obj<>endobj +2661 0 obj<>endobj +2662 0 obj<>endobj +2663 0 obj<>endobj +2664 0 obj<>endobj +2665 0 obj<>endobj +2666 0 obj<>endobj +2667 0 obj<>endobj +2668 0 obj<>endobj +2669 0 obj<>endobj +2670 0 obj<>endobj +2671 0 obj<>endobj +2672 0 obj<>endobj +2673 0 obj<>endobj +2674 0 obj<>endobj +2675 0 obj<>endobj +2676 0 obj<>endobj +2677 0 obj<>endobj +2678 0 obj<>endobj +2679 0 obj<>endobj +2680 0 obj<>endobj +2681 0 obj<>endobj +2682 0 obj<>endobj +2683 0 obj<>endobj +2684 0 obj<>endobj +2685 0 obj<>endobj +2686 0 obj<>endobj +2687 0 obj<>endobj +2688 0 obj<>endobj +2689 0 obj<>endobj +2690 0 obj<>endobj +2691 0 obj<>endobj +2692 0 obj<>endobj +2693 0 obj<>endobj +2694 0 obj<>endobj +2695 0 obj<>endobj +2696 0 obj<>endobj +2697 0 obj<>endobj +2698 0 obj<>endobj +2699 0 obj<>endobj +2700 0 obj<>endobj +2701 0 obj<>endobj +2702 0 obj<>endobj +2703 0 obj<>endobj +2704 0 obj<>endobj +2705 0 obj<>endobj +2706 0 obj<>endobj +2707 0 obj<>endobj +2708 0 obj<>endobj +2709 0 obj<>endobj +2710 0 obj<>endobj +2711 0 obj<>endobj +2712 0 obj<>endobj +2713 0 obj<>endobj +2714 0 obj<>endobj +2715 0 obj<>endobj +2716 0 obj<>endobj +2717 0 obj<>endobj +2718 0 obj<>endobj +2719 0 obj<>endobj +2720 0 obj<>endobj +2721 0 obj<>endobj +2722 0 obj<>endobj +2723 0 obj<>endobj +2724 0 obj<>endobj +2725 0 obj<>endobj +2726 0 obj<>endobj +2727 0 obj<>endobj +2728 0 obj<>endobj +2729 0 obj<>endobj +2730 0 obj<>endobj +2731 0 obj<>endobj +2732 0 obj<>endobj +2733 0 obj<>endobj +2734 0 obj<>endobj +2735 0 obj<>endobj +2736 0 obj<>endobj +2737 0 obj<>endobj +2738 0 obj<>endobj +2739 0 obj<>endobj +2740 0 obj<>endobj +2741 0 obj<>endobj +2742 0 obj<>endobj +2743 0 obj<>endobj +2744 0 obj<>endobj +2745 0 obj<>endobj +2746 0 obj<>endobj +2747 0 obj<>endobj +2748 0 obj<>endobj +2749 0 obj<>endobj +2750 0 obj<>endobj +2751 0 obj<>endobj +2752 0 obj<>endobj +2753 0 obj<>endobj +2754 0 obj<>endobj +2755 0 obj<>endobj +2756 0 obj<>endobj +2757 0 obj<>endobj +2758 0 obj<>endobj +2759 0 obj<>endobj +2760 0 obj<>endobj +2761 0 obj<>endobj +2762 0 obj<>endobj +2763 0 obj<>endobj +2764 0 obj<>endobj +2765 0 obj<>endobj +2766 0 obj<>endobj +2767 0 obj<>endobj +2768 0 obj<>endobj +2769 0 obj<>endobj +2770 0 obj<>endobj +2771 0 obj<>endobj +2772 0 obj<>endobj +2773 0 obj<>endobj +2774 0 obj<>endobj +2775 0 obj<>endobj +2776 0 obj<>endobj +2777 0 obj<>endobj +2778 0 obj<>endobj +2779 0 obj<>endobj +2780 0 obj<>endobj +2781 0 obj<>endobj +2782 0 obj<>endobj +2783 0 obj<>endobj +2784 0 obj<>endobj +2785 0 obj<>endobj +2786 0 obj<>endobj +2787 0 obj<>endobj +2788 0 obj<>endobj +2789 0 obj<>endobj +2790 0 obj<>endobj +2791 0 obj<>endobj +2792 0 obj<>endobj +2793 0 obj<>endobj +2794 0 obj<>endobj +2795 0 obj<>endobj +2796 0 obj<>endobj +2797 0 obj<>endobj +2798 0 obj<>endobj +2799 0 obj<>endobj +2800 0 obj<>endobj +2801 0 obj<>endobj +2802 0 obj<>endobj +2803 0 obj<>endobj +2804 0 obj<>endobj +2805 0 obj<>endobj +2806 0 obj<>endobj +2807 0 obj<>endobj +2808 0 obj<>endobj +2809 0 obj<>endobj +2810 0 obj<>endobj +2811 0 obj<>endobj +2812 0 obj<>endobj +2813 0 obj<>endobj +2814 0 obj<>endobj +2815 0 obj<>endobj +2816 0 obj<>endobj +2817 0 obj<>endobj +2818 0 obj<>endobj +2819 0 obj<>endobj +2820 0 obj<>endobj +2821 0 obj<>endobj +2822 0 obj<>endobj +2823 0 obj<>endobj +2824 0 obj<>endobj +2825 0 obj<>endobj +2826 0 obj<>endobj +2827 0 obj<>endobj +2828 0 obj<>endobj +2829 0 obj<>endobj +2830 0 obj<>endobj +2831 0 obj<>endobj +2832 0 obj<>endobj +2833 0 obj<>endobj +2834 0 obj<>endobj +2835 0 obj<>endobj +2836 0 obj<>endobj +2837 0 obj<>endobj +2838 0 obj<>endobj +2839 0 obj<>endobj +2840 0 obj<>endobj +2841 0 obj<>endobj +2842 0 obj<>endobj +2843 0 obj<>endobj +2844 0 obj<>endobj +2845 0 obj<>endobj +2846 0 obj<>endobj +2847 0 obj<>endobj +2848 0 obj<>endobj +2849 0 obj<>endobj +2850 0 obj<>endobj +2851 0 obj<>endobj +2852 0 obj<>endobj +2853 0 obj<>endobj +2854 0 obj<>endobj +2855 0 obj<>endobj +2856 0 obj<>endobj +2857 0 obj<>endobj +2858 0 obj<>endobj +2859 0 obj<>endobj +2860 0 obj<>endobj +2861 0 obj<>endobj +2862 0 obj<>endobj +2863 0 obj<>endobj +2864 0 obj<>endobj +2865 0 obj<>endobj +2866 0 obj<>endobj +2867 0 obj<>endobj +2868 0 obj<>endobj +2869 0 obj<>endobj +2870 0 obj<>endobj +2871 0 obj<>endobj +2872 0 obj<>endobj +2873 0 obj<>endobj +2874 0 obj<>endobj +2875 0 obj<>endobj +2876 0 obj<>endobj +2877 0 obj<>endobj +2878 0 obj<>endobj +2879 0 obj<>endobj +2880 0 obj<>endobj +2881 0 obj<>endobj +2882 0 obj<>endobj +2883 0 obj<>endobj +2884 0 obj<>endobj +2885 0 obj<>endobj +2886 0 obj<>endobj +2887 0 obj<>endobj +2888 0 obj<>endobj +2889 0 obj<>endobj +2890 0 obj<>endobj +2891 0 obj<>endobj +2892 0 obj<>endobj +2893 0 obj<>endobj +2894 0 obj<>endobj +2895 0 obj<>endobj +2896 0 obj<>endobj +2897 0 obj<>endobj +2898 0 obj<>endobj +2899 0 obj<>endobj +2900 0 obj<>endobj +2901 0 obj<>endobj +2902 0 obj<>endobj +2903 0 obj<>endobj +2904 0 obj<>endobj +2905 0 obj<>endobj +2906 0 obj<>endobj +2907 0 obj<>endobj +2908 0 obj<>endobj +2909 0 obj<>endobj +2910 0 obj<>endobj +2911 0 obj<>endobj +2912 0 obj<>endobj +2913 0 obj<>endobj +2914 0 obj<>endobj +2915 0 obj<>endobj +2916 0 obj<>endobj +2917 0 obj<>endobj +2918 0 obj<>endobj +2919 0 obj<>endobj +2920 0 obj<>endobj +2921 0 obj<>endobj +2922 0 obj<>endobj +2923 0 obj<>endobj +2924 0 obj<>endobj +2925 0 obj<>endobj +2926 0 obj<>endobj +2927 0 obj<>endobj +2928 0 obj<>endobj +2929 0 obj<>endobj +2930 0 obj<>endobj +2931 0 obj<>endobj +2932 0 obj<>endobj +2933 0 obj<>endobj +2934 0 obj<>endobj +2935 0 obj<>endobj +2936 0 obj<>endobj +2937 0 obj<>endobj +2938 0 obj<>endobj +2939 0 obj<>endobj +2940 0 obj<>endobj +2941 0 obj<>endobj +2942 0 obj<>endobj +2943 0 obj<>endobj +2944 0 obj<>endobj +2945 0 obj<>endobj +2946 0 obj<>endobj +2947 0 obj<>endobj +2948 0 obj<>endobj +2949 0 obj<>endobj +2950 0 obj<>endobj +2951 0 obj<>endobj +2952 0 obj<>endobj +2953 0 obj<>endobj +2954 0 obj<>endobj +2955 0 obj<>endobj +2956 0 obj<>endobj +2957 0 obj<>endobj +2958 0 obj<>endobj +2959 0 obj<>endobj +2960 0 obj<>endobj +2961 0 obj<>endobj +2962 0 obj<>endobj +2963 0 obj<>endobj +2964 0 obj<>endobj +2965 0 obj<>endobj +2966 0 obj<>endobj +2967 0 obj<>endobj +2968 0 obj<>endobj +2969 0 obj<>endobj +2970 0 obj<>endobj +2971 0 obj<>endobj +2972 0 obj<>endobj +2973 0 obj<>endobj +2974 0 obj<>endobj +2975 0 obj<>endobj +2976 0 obj<>endobj +2977 0 obj<>endobj +2978 0 obj<>endobj +2979 0 obj<>endobj +2980 0 obj<>endobj +2981 0 obj<>endobj +2982 0 obj<>endobj +2983 0 obj<>endobj +2984 0 obj<>endobj +2985 0 obj<>endobj +2986 0 obj<>endobj +2987 0 obj<>endobj +2988 0 obj<>endobj +2989 0 obj<>endobj +2990 0 obj<>endobj +2991 0 obj<>endobj +2992 0 obj<>endobj +2993 0 obj<>endobj +2994 0 obj<>endobj +2995 0 obj<>endobj +2996 0 obj<>endobj +2997 0 obj<>endobj +2998 0 obj<>endobj +2999 0 obj<>endobj +3000 0 obj<>endobj +3001 0 obj<>endobj +3002 0 obj<>endobj +3003 0 obj<>endobj +3004 0 obj<>endobj +3005 0 obj<>endobj +3006 0 obj<>endobj +3007 0 obj<>endobj +3008 0 obj<>endobj +3009 0 obj<>endobj +3010 0 obj<>endobj +3011 0 obj<>endobj +3012 0 obj<>endobj +3013 0 obj<>endobj +3014 0 obj<>endobj +3015 0 obj<>endobj +3016 0 obj<>endobj +3017 0 obj<>endobj +3018 0 obj<>endobj +3019 0 obj<>endobj +3020 0 obj<>endobj +3021 0 obj<>endobj +3022 0 obj<>endobj +3023 0 obj<>endobj +3024 0 obj<>endobj +3025 0 obj<>endobj +3026 0 obj<>endobj +3027 0 obj<>endobj +3028 0 obj<>endobj +3029 0 obj<>endobj +3030 0 obj<>endobj +3031 0 obj<>endobj +3032 0 obj<>endobj +3033 0 obj<>endobj +3034 0 obj<>endobj +3035 0 obj<>endobj +3036 0 obj<>endobj +3037 0 obj<>endobj +3038 0 obj<>endobj +3039 0 obj<>endobj +3040 0 obj<>endobj +3041 0 obj<>endobj +3042 0 obj<>endobj +3043 0 obj<>endobj +3044 0 obj<>endobj +3045 0 obj<>endobj +3046 0 obj<>endobj +3047 0 obj<>endobj +3048 0 obj<>endobj +3049 0 obj<>endobj +3050 0 obj<>endobj +3051 0 obj<>endobj +3052 0 obj<>endobj +3053 0 obj<>endobj +3054 0 obj<>endobj +3055 0 obj<>endobj +3056 0 obj<>endobj +3057 0 obj<>endobj +3058 0 obj<>endobj +3059 0 obj<>endobj +3060 0 obj<>endobj +3061 0 obj<>endobj +3062 0 obj<>endobj +3063 0 obj<>endobj +3064 0 obj<>endobj +3065 0 obj<>endobj +3066 0 obj<>endobj +3067 0 obj<>endobj +3068 0 obj<>endobj +3069 0 obj<>endobj +3070 0 obj<>endobj +3071 0 obj<>endobj +3072 0 obj<>endobj +3073 0 obj<>endobj +3074 0 obj<>endobj +3075 0 obj<>endobj +3076 0 obj<>endobj +3077 0 obj<>endobj +3078 0 obj<>endobj +3079 0 obj<>endobj +3080 0 obj<>endobj +3081 0 obj<>endobj +3082 0 obj<>endobj +3083 0 obj<>endobj +3084 0 obj<>endobj +3085 0 obj<>endobj +3086 0 obj<>endobj +3087 0 obj<>endobj +3088 0 obj<>endobj +3089 0 obj<>endobj +3090 0 obj<>endobj +3091 0 obj<>endobj +3092 0 obj<>endobj +3093 0 obj<>endobj +3094 0 obj<>endobj +3095 0 obj<>endobj +3096 0 obj<>endobj +3097 0 obj<>endobj +3098 0 obj<>endobj +3099 0 obj<>endobj +3100 0 obj<>endobj +3101 0 obj<>endobj +3102 0 obj<>endobj +3103 0 obj<>endobj +3104 0 obj<>endobj +3105 0 obj<>endobj +3106 0 obj<>endobj +3107 0 obj<>endobj +3108 0 obj<>endobj +3109 0 obj<>endobj +3110 0 obj<>endobj +3111 0 obj<>endobj +3112 0 obj<>endobj +3113 0 obj<>endobj +3114 0 obj<>endobj +3115 0 obj<>endobj +3116 0 obj<>endobj +3117 0 obj<>endobj +3118 0 obj<>endobj +3119 0 obj<>endobj +3120 0 obj<>endobj +3121 0 obj<>endobj +3122 0 obj<>endobj +3123 0 obj<>endobj +3124 0 obj<>endobj +3125 0 obj<>endobj +3126 0 obj<>endobj +3127 0 obj<>endobj +3128 0 obj<>endobj +3129 0 obj<>endobj +3130 0 obj<>endobj +3131 0 obj<>endobj +3132 0 obj<>endobj +3133 0 obj<>endobj +3134 0 obj<>endobj +3135 0 obj<>endobj +3136 0 obj<>endobj +3137 0 obj<>endobj +3138 0 obj<>endobj +3139 0 obj<>endobj +3140 0 obj<>endobj +3141 0 obj<>endobj +3142 0 obj<>endobj +3143 0 obj<>endobj +3144 0 obj<>endobj +3145 0 obj<>endobj +3146 0 obj<>endobj +3147 0 obj<>endobj +3148 0 obj<>endobj +3149 0 obj<>endobj +3150 0 obj<>endobj +3151 0 obj<>endobj +3152 0 obj<>endobj +3153 0 obj<>endobj +3154 0 obj<>endobj +3155 0 obj<>endobj +3156 0 obj<>endobj +3157 0 obj<>endobj +3158 0 obj<>endobj +3159 0 obj<>endobj +3160 0 obj<>endobj +3161 0 obj<>endobj +3162 0 obj<>endobj +3163 0 obj<>endobj +3164 0 obj<>endobj +3165 0 obj<>endobj +3166 0 obj<>endobj +3167 0 obj<>endobj +3168 0 obj<>endobj +3169 0 obj<>endobj +3170 0 obj<>endobj +3171 0 obj<>endobj +3172 0 obj<>endobj +3173 0 obj<>endobj +3174 0 obj<>endobj +3175 0 obj<>endobj +3176 0 obj<>endobj +3177 0 obj<>endobj +3178 0 obj<>endobj +3179 0 obj<>endobj +3180 0 obj<>endobj +3181 0 obj<>endobj +3182 0 obj<>endobj +3183 0 obj<>endobj +3184 0 obj<>endobj +3185 0 obj<>endobj +3186 0 obj<>endobj +3187 0 obj<>endobj +3188 0 obj<>endobj +3189 0 obj<>endobj +3190 0 obj<>endobj +3191 0 obj<>endobj +3192 0 obj<>endobj +3193 0 obj<>endobj +3194 0 obj<>endobj +3195 0 obj<>endobj +3196 0 obj<>endobj +3197 0 obj<>endobj +3198 0 obj<>endobj +3199 0 obj<>endobj +3200 0 obj<>endobj +3201 0 obj<>endobj +3202 0 obj<>endobj +3203 0 obj<>endobj +3204 0 obj<>endobj +3205 0 obj<>endobj +3206 0 obj<>endobj +3207 0 obj<>endobj +3208 0 obj<>endobj +3209 0 obj<>endobj +3210 0 obj<>endobj +3211 0 obj<>endobj +3212 0 obj<>endobj +3213 0 obj<>endobj +3214 0 obj<>endobj +3215 0 obj<>endobj +3216 0 obj<>endobj +3217 0 obj<>endobj +3218 0 obj<>endobj +3219 0 obj<>endobj +3220 0 obj<>endobj +3221 0 obj<>endobj +3222 0 obj<>endobj +3223 0 obj<>endobj +3224 0 obj<>endobj +3225 0 obj<>endobj +3226 0 obj<>endobj +3227 0 obj<>endobj +3228 0 obj<>endobj +3229 0 obj<>endobj +3230 0 obj<>endobj +3231 0 obj<>endobj +3232 0 obj<>endobj +3233 0 obj<>endobj +3234 0 obj<>endobj +3235 0 obj<>endobj +3236 0 obj<>endobj +3237 0 obj<>endobj +3238 0 obj<>endobj +3239 0 obj<>endobj +3240 0 obj<>endobj +3241 0 obj<>endobj +3242 0 obj<>endobj +3243 0 obj<>endobj +3244 0 obj<>endobj +3245 0 obj<>endobj +3246 0 obj<>endobj +3247 0 obj<>endobj +3248 0 obj<>endobj +3249 0 obj<>endobj +3250 0 obj<>endobj +3251 0 obj<>endobj +3252 0 obj<>endobj +3253 0 obj<>endobj +3254 0 obj<>endobj +3255 0 obj<>endobj +3256 0 obj<>endobj +3257 0 obj<>endobj +3258 0 obj<>endobj +3259 0 obj<>endobj +3260 0 obj<>endobj +3261 0 obj<>endobj +3262 0 obj<>endobj +3263 0 obj<>endobj +3264 0 obj<>endobj +3265 0 obj<>endobj +3266 0 obj<>endobj +3267 0 obj<>endobj +3268 0 obj<>endobj +3269 0 obj<>endobj +3270 0 obj<>endobj +3271 0 obj<>endobj +3272 0 obj<>endobj +3273 0 obj<>endobj +3274 0 obj<>endobj +3275 0 obj<>endobj +3276 0 obj<>endobj +3277 0 obj<>endobj +3278 0 obj<>endobj +3279 0 obj<>endobj +3280 0 obj<>endobj +3281 0 obj<>endobj +3282 0 obj<>endobj +3283 0 obj<>endobj +3284 0 obj<>endobj +3285 0 obj<>endobj +3286 0 obj<>endobj +3287 0 obj<>endobj +3288 0 obj<>endobj +3289 0 obj<>endobj +3290 0 obj<>endobj +3291 0 obj<>endobj +3292 0 obj<>endobj +3293 0 obj<>endobj +3294 0 obj<>endobj +3295 0 obj<>endobj +3296 0 obj<>endobj +3297 0 obj<>endobj +3298 0 obj<>endobj +3299 0 obj<>endobj +3300 0 obj<>endobj +3301 0 obj<>endobj +3302 0 obj<>endobj +3303 0 obj<>endobj +3304 0 obj<>endobj +3305 0 obj<>endobj +3306 0 obj<>endobj +3307 0 obj<>endobj +3308 0 obj<>endobj +3309 0 obj<>endobj +3310 0 obj<>endobj +3311 0 obj<>endobj +3312 0 obj<>endobj +3313 0 obj<>endobj +3314 0 obj<>endobj +3315 0 obj<>endobj +3316 0 obj<>endobj +3317 0 obj<>endobj +3318 0 obj<>endobj +3319 0 obj<>endobj +3320 0 obj<>endobj +3321 0 obj<>endobj +3322 0 obj<>endobj +3323 0 obj<>endobj +3324 0 obj<>endobj +3325 0 obj<>endobj +3326 0 obj<>endobj +3327 0 obj<>endobj +3328 0 obj<>endobj +3329 0 obj<>endobj +3330 0 obj<>endobj +3331 0 obj<>endobj +3332 0 obj<>endobj +3333 0 obj<>endobj +3334 0 obj<>endobj +3335 0 obj<>endobj +3336 0 obj<>endobj +3337 0 obj<>endobj +3338 0 obj<>endobj +3339 0 obj<>endobj +3340 0 obj<>endobj +3341 0 obj<>endobj +3342 0 obj<>endobj +3343 0 obj<>endobj +3344 0 obj<>endobj +3345 0 obj<>endobj +3346 0 obj<>endobj +3347 0 obj<>endobj +3348 0 obj<>endobj +3349 0 obj<>endobj +3350 0 obj<>endobj +3351 0 obj<>endobj +3352 0 obj<>endobj +3353 0 obj<>endobj +3354 0 obj<>endobj +3355 0 obj<>endobj +3356 0 obj<>endobj +3357 0 obj<>endobj +3358 0 obj<>endobj +3359 0 obj<>endobj +3360 0 obj<>endobj +3361 0 obj<>endobj +3362 0 obj<>endobj +3363 0 obj<>endobj +3364 0 obj<>endobj +3365 0 obj<>endobj +3366 0 obj<>endobj +3367 0 obj<>endobj +3368 0 obj<>endobj +3369 0 obj<>endobj +3370 0 obj<>endobj +3371 0 obj<>endobj +3372 0 obj<>endobj +3373 0 obj<>endobj +3374 0 obj<>endobj +3375 0 obj<>endobj +3376 0 obj<>endobj +3377 0 obj<>endobj +3378 0 obj<>endobj +3379 0 obj<>endobj +3380 0 obj<>endobj +3381 0 obj<>endobj +3382 0 obj<>endobj +3383 0 obj<>endobj +3384 0 obj<>endobj +3385 0 obj<>endobj +3386 0 obj<>endobj +3387 0 obj<>endobj +3388 0 obj<>endobj +3389 0 obj<>endobj +3390 0 obj<>endobj +3391 0 obj<>endobj +3392 0 obj<>endobj +3393 0 obj<>endobj +3394 0 obj<>endobj +3395 0 obj<>endobj +3396 0 obj<>endobj +3397 0 obj<>endobj +3398 0 obj<>endobj +3399 0 obj<>endobj +3400 0 obj<>endobj +3401 0 obj<>endobj +3402 0 obj<>endobj +3403 0 obj<>endobj +3404 0 obj<>endobj +3405 0 obj<>endobj +3406 0 obj<>endobj +3407 0 obj<>endobj +3408 0 obj<>endobj +3409 0 obj<>endobj +3410 0 obj<>endobj +3411 0 obj<>endobj +3412 0 obj<>endobj +3413 0 obj<>endobj +3414 0 obj<>endobj +3415 0 obj<>endobj +3416 0 obj<>1<>2<>20<>]>>>>endobj +xref +0 3417 +0000000000 65535 f +0000000015 00000 n +0000000226 00000 n +0000001792 00000 n +0000001866 00000 n +0000001945 00000 n +0000002027 00000 n +0000002105 00000 n +0000002182 00000 n +0000002261 00000 n +0000002344 00000 n +0000002421 00000 n +0000002503 00000 n +0000002588 00000 n +0000002647 00000 n +0000002699 00000 n +0000002784 00000 n +0000002836 00000 n +0000002920 00000 n +0000003024 00000 n +0000003062 00000 n +0000003167 00000 n +0000003272 00000 n +0000003377 00000 n +0000003482 00000 n +0000003587 00000 n +0000003692 00000 n +0000003797 00000 n +0000003838 00000 n +0000003922 00000 n +0000003995 00000 n +0000004100 00000 n +0000004205 00000 n +0000004309 00000 n +0000004347 00000 n +0000004451 00000 n +0000004475 00000 n +0000004581 00000 n +0000004686 00000 n +0000004717 00000 n +0000004769 00000 n +0000004854 00000 n +0000004878 00000 n +0000004984 00000 n +0000005008 00000 n +0000005064 00000 n +0000005149 00000 n +0000005199 00000 n +0000005284 00000 n +0000005315 00000 n +0000005368 00000 n +0000005453 00000 n +0000005509 00000 n +0000005594 00000 n +0000005653 00000 n +0000005737 00000 n +0000005775 00000 n +0000005827 00000 n +0000005912 00000 n +0000005936 00000 n +0000006041 00000 n +0000006065 00000 n +0000006105 00000 n +0000006190 00000 n +0000006214 00000 n +0000006259 00000 n +0000006343 00000 n +0000006448 00000 n +0000006554 00000 n +0000006660 00000 n +0000006766 00000 n +0000006818 00000 n +0000006923 00000 n +0000007029 00000 n +0000007134 00000 n +0000007172 00000 n +0000007254 00000 n +0000007299 00000 n +0000007342 00000 n +0000007425 00000 n +0000007462 00000 n +0000007545 00000 n +0000007650 00000 n +0000007755 00000 n +0000007860 00000 n +0000007966 00000 n +0000008072 00000 n +0000008177 00000 n +0000008283 00000 n +0000008389 00000 n +0000008495 00000 n +0000008600 00000 n +0000008706 00000 n +0000008814 00000 n +0000008919 00000 n +0000008957 00000 n +0000009041 00000 n +0000009084 00000 n +0000009168 00000 n +0000009205 00000 n +0000009288 00000 n +0000009395 00000 n +0000009502 00000 n +0000009608 00000 n +0000009715 00000 n +0000009821 00000 n +0000009928 00000 n +0000010035 00000 n +0000010142 00000 n +0000010248 00000 n +0000010355 00000 n +0000010481 00000 n +0000010587 00000 n +0000010694 00000 n +0000010801 00000 n +0000010908 00000 n +0000010958 00000 n +0000011064 00000 n +0000011171 00000 n +0000011275 00000 n +0000011380 00000 n +0000011430 00000 n +0000011536 00000 n +0000011643 00000 n +0000011750 00000 n +0000011857 00000 n +0000011907 00000 n +0000012013 00000 n +0000012120 00000 n +0000012227 00000 n +0000012334 00000 n +0000012379 00000 n +0000012466 00000 n +0000012524 00000 n +0000012630 00000 n +0000012737 00000 n +0000012771 00000 n +0000012877 00000 n +0000012984 00000 n +0000013091 00000 n +0000013198 00000 n +0000013305 00000 n +0000013411 00000 n +0000013518 00000 n +0000013625 00000 n +0000013732 00000 n +0000013839 00000 n +0000013937 00000 n +0000014043 00000 n +0000014150 00000 n +0000014257 00000 n +0000014364 00000 n +0000014471 00000 n +0000014577 00000 n +0000014684 00000 n +0000014791 00000 n +0000014898 00000 n +0000015005 00000 n +0000015103 00000 n +0000015209 00000 n +0000015316 00000 n +0000015423 00000 n +0000015530 00000 n +0000015637 00000 n +0000015695 00000 n +0000015801 00000 n +0000015908 00000 n +0000016015 00000 n +0000016122 00000 n +0000016229 00000 n +0000016287 00000 n +0000016393 00000 n +0000016500 00000 n +0000016604 00000 n +0000016709 00000 n +0000016814 00000 n +0000016919 00000 n +0000016985 00000 n +0000017091 00000 n +0000017198 00000 n +0000017305 00000 n +0000017412 00000 n +0000017462 00000 n +0000017568 00000 n +0000017675 00000 n +0000017782 00000 n +0000017824 00000 n +0000017930 00000 n +0000018037 00000 n +0000018144 00000 n +0000018186 00000 n +0000018292 00000 n +0000018399 00000 n +0000018506 00000 n +0000018613 00000 n +0000018719 00000 n +0000018777 00000 n +0000018883 00000 n +0000018990 00000 n +0000019097 00000 n +0000019204 00000 n +0000019310 00000 n +0000019368 00000 n +0000019474 00000 n +0000019581 00000 n +0000019688 00000 n +0000019795 00000 n +0000019901 00000 n +0000019959 00000 n +0000020065 00000 n +0000020172 00000 n +0000020279 00000 n +0000020386 00000 n +0000020492 00000 n +0000020550 00000 n +0000020656 00000 n +0000020763 00000 n +0000020870 00000 n +0000020977 00000 n +0000021083 00000 n +0000021141 00000 n +0000021247 00000 n +0000021354 00000 n +0000021461 00000 n +0000021568 00000 n +0000021674 00000 n +0000021780 00000 n +0000021887 00000 n +0000021994 00000 n +0000022101 00000 n +0000022208 00000 n +0000022306 00000 n +0000022411 00000 n +0000022517 00000 n +0000022624 00000 n +0000022669 00000 n +0000022756 00000 n +0000022806 00000 n +0000022912 00000 n +0000023019 00000 n +0000023126 00000 n +0000023171 00000 n +0000023258 00000 n +0000023364 00000 n +0000023471 00000 n +0000023578 00000 n +0000023623 00000 n +0000023710 00000 n +0000023792 00000 n +0000023898 00000 n +0000024005 00000 n +0000024111 00000 n +0000024218 00000 n +0000024268 00000 n +0000024374 00000 n +0000024481 00000 n +0000024588 00000 n +0000024695 00000 n +0000024799 00000 n +0000024904 00000 n +0000025009 00000 n +0000025083 00000 n +0000025189 00000 n +0000025215 00000 n +0000025321 00000 n +0000025428 00000 n +0000025535 00000 n +0000025642 00000 n +0000025749 00000 n +0000025856 00000 n +0000025960 00000 n +0000026034 00000 n +0000026140 00000 n +0000026247 00000 n +0000026354 00000 n +0000026396 00000 n +0000026502 00000 n +0000026528 00000 n +0000026634 00000 n +0000026740 00000 n +0000026774 00000 n +0000026880 00000 n +0000026987 00000 n +0000027094 00000 n +0000027136 00000 n +0000027242 00000 n +0000027349 00000 n +0000027455 00000 n +0000027497 00000 n +0000027603 00000 n +0000027629 00000 n +0000027735 00000 n +0000027842 00000 n +0000027948 00000 n +0000028055 00000 n +0000028162 00000 n +0000028220 00000 n +0000028326 00000 n +0000028352 00000 n +0000028458 00000 n +0000028565 00000 n +0000028672 00000 n +0000028778 00000 n +0000028885 00000 n +0000028992 00000 n +0000029058 00000 n +0000029164 00000 n +0000029190 00000 n +0000029296 00000 n +0000029403 00000 n +0000029510 00000 n +0000029614 00000 n +0000029719 00000 n +0000029777 00000 n +0000029883 00000 n +0000029909 00000 n +0000030015 00000 n +0000030041 00000 n +0000030147 00000 n +0000030254 00000 n +0000030360 00000 n +0000030467 00000 n +0000030574 00000 n +0000030632 00000 n +0000030738 00000 n +0000030845 00000 n +0000030952 00000 n +0000031059 00000 n +0000031166 00000 n +0000031273 00000 n +0000031379 00000 n +0000031486 00000 n +0000031568 00000 n +0000031674 00000 n +0000031781 00000 n +0000031815 00000 n +0000031921 00000 n +0000032028 00000 n +0000032135 00000 n +0000032242 00000 n +0000032348 00000 n +0000032455 00000 n +0000032562 00000 n +0000032669 00000 n +0000032775 00000 n +0000032882 00000 n +0000032989 00000 n +0000033095 00000 n +0000033201 00000 n +0000033308 00000 n +0000033415 00000 n +0000033522 00000 n +0000033628 00000 n +0000033735 00000 n +0000033842 00000 n +0000033949 00000 n +0000034055 00000 n +0000034162 00000 n +0000034269 00000 n +0000034375 00000 n +0000034481 00000 n +0000034588 00000 n +0000034695 00000 n +0000034802 00000 n +0000034908 00000 n +0000035015 00000 n +0000035122 00000 n +0000035229 00000 n +0000035335 00000 n +0000035442 00000 n +0000035549 00000 n +0000035656 00000 n +0000035762 00000 n +0000035869 00000 n +0000035976 00000 n +0000036083 00000 n +0000036189 00000 n +0000036296 00000 n +0000036403 00000 n +0000036510 00000 n +0000036616 00000 n +0000036723 00000 n +0000036830 00000 n +0000037032 00000 n +0000037138 00000 n +0000037245 00000 n +0000037352 00000 n +0000037459 00000 n +0000037565 00000 n +0000037672 00000 n +0000037779 00000 n +0000037886 00000 n +0000037992 00000 n +0000038099 00000 n +0000038206 00000 n +0000038312 00000 n +0000038418 00000 n +0000038525 00000 n +0000038632 00000 n +0000038739 00000 n +0000038845 00000 n +0000038952 00000 n +0000039059 00000 n +0000039166 00000 n +0000039272 00000 n +0000039379 00000 n +0000039486 00000 n +0000039592 00000 n +0000039698 00000 n +0000039805 00000 n +0000039912 00000 n +0000040019 00000 n +0000040125 00000 n +0000040232 00000 n +0000040339 00000 n +0000040446 00000 n +0000040552 00000 n +0000040659 00000 n +0000040766 00000 n +0000040872 00000 n +0000040978 00000 n +0000041085 00000 n +0000041192 00000 n +0000041299 00000 n +0000041405 00000 n +0000041512 00000 n +0000041619 00000 n +0000041726 00000 n +0000041832 00000 n +0000041939 00000 n +0000042046 00000 n +0000042152 00000 n +0000042258 00000 n +0000042365 00000 n +0000042472 00000 n +0000042579 00000 n +0000042685 00000 n +0000042792 00000 n +0000042899 00000 n +0000043006 00000 n +0000043112 00000 n +0000043219 00000 n +0000043326 00000 n +0000043432 00000 n +0000043538 00000 n +0000043645 00000 n +0000043752 00000 n +0000043859 00000 n +0000043965 00000 n +0000044072 00000 n +0000044179 00000 n +0000044286 00000 n +0000044392 00000 n +0000044499 00000 n +0000044606 00000 n +0000044712 00000 n +0000044818 00000 n +0000044925 00000 n +0000045032 00000 n +0000045139 00000 n +0000045245 00000 n +0000045352 00000 n +0000045459 00000 n +0000045566 00000 n +0000045672 00000 n +0000045779 00000 n +0000045886 00000 n +0000045992 00000 n +0000046098 00000 n +0000046205 00000 n +0000046312 00000 n +0000046419 00000 n +0000046525 00000 n +0000046632 00000 n +0000046739 00000 n +0000046846 00000 n +0000046952 00000 n +0000047059 00000 n +0000047166 00000 n +0000047272 00000 n +0000047386 00000 n +0000047491 00000 n +0000047517 00000 n +0000047621 00000 n +0000047647 00000 n +0000047753 00000 n +0000047860 00000 n +0000047894 00000 n +0000048000 00000 n +0000048026 00000 n +0000048131 00000 n +0000048237 00000 n +0000048271 00000 n +0000048377 00000 n +0000048403 00000 n +0000048508 00000 n +0000048615 00000 n +0000048722 00000 n +0000048828 00000 n +0000048935 00000 n +0000049042 00000 n +0000049149 00000 n +0000049223 00000 n +0000049329 00000 n +0000049355 00000 n +0000049460 00000 n +0000049486 00000 n +0000049592 00000 n +0000049699 00000 n +0000049805 00000 n +0000049912 00000 n +0000049962 00000 n +0000050068 00000 n +0000050175 00000 n +0000050209 00000 n +0000050315 00000 n +0000050422 00000 n +0000050529 00000 n +0000050636 00000 n +0000050742 00000 n +0000050848 00000 n +0000050955 00000 n +0000051062 00000 n +0000051169 00000 n +0000051275 00000 n +0000051373 00000 n +0000051479 00000 n +0000051586 00000 n +0000051693 00000 n +0000051800 00000 n +0000051906 00000 n +0000051964 00000 n +0000052070 00000 n +0000052177 00000 n +0000052284 00000 n +0000052326 00000 n +0000052432 00000 n +0000052539 00000 n +0000052646 00000 n +0000052752 00000 n +0000052859 00000 n +0000052966 00000 n +0000053032 00000 n +0000053138 00000 n +0000053245 00000 n +0000053352 00000 n +0000053394 00000 n +0000053500 00000 n +0000053607 00000 n +0000053713 00000 n +0000053820 00000 n +0000053870 00000 n +0000053976 00000 n +0000054083 00000 n +0000054190 00000 n +0000054297 00000 n +0000054404 00000 n +0000054511 00000 n +0000054617 00000 n +0000054724 00000 n +0000054831 00000 n +0000054938 00000 n +0000055045 00000 n +0000055152 00000 n +0000055259 00000 n +0000055366 00000 n +0000055473 00000 n +0000055579 00000 n +0000055686 00000 n +0000055793 00000 n +0000055900 00000 n +0000056007 00000 n +0000056114 00000 n +0000056221 00000 n +0000056328 00000 n +0000056435 00000 n +0000056542 00000 n +0000056649 00000 n +0000056756 00000 n +0000056863 00000 n +0000056970 00000 n +0000057077 00000 n +0000057184 00000 n +0000057291 00000 n +0000057398 00000 n +0000057505 00000 n +0000057612 00000 n +0000057719 00000 n +0000057825 00000 n +0000057932 00000 n +0000058039 00000 n +0000058146 00000 n +0000058253 00000 n +0000058360 00000 n +0000058466 00000 n +0000058571 00000 n +0000058676 00000 n +0000059054 00000 n +0000059161 00000 n +0000059267 00000 n +0000059374 00000 n +0000059480 00000 n +0000059586 00000 n +0000059692 00000 n +0000059799 00000 n +0000059906 00000 n +0000060013 00000 n +0000060120 00000 n +0000060226 00000 n +0000060333 00000 n +0000060440 00000 n +0000060546 00000 n +0000060652 00000 n +0000060759 00000 n +0000060866 00000 n +0000060973 00000 n +0000061080 00000 n +0000061187 00000 n +0000061294 00000 n +0000061400 00000 n +0000061507 00000 n +0000061614 00000 n +0000061721 00000 n +0000061828 00000 n +0000061934 00000 n +0000062040 00000 n +0000062147 00000 n +0000062254 00000 n +0000062361 00000 n +0000062468 00000 n +0000062574 00000 n +0000062680 00000 n +0000062786 00000 n +0000062892 00000 n +0000062999 00000 n +0000063106 00000 n +0000063213 00000 n +0000063319 00000 n +0000063426 00000 n +0000063532 00000 n +0000063637 00000 n +0000063741 00000 n +0000064111 00000 n +0000064218 00000 n +0000064325 00000 n +0000064432 00000 n +0000064539 00000 n +0000064646 00000 n +0000064753 00000 n +0000064860 00000 n +0000064967 00000 n +0000065074 00000 n +0000065181 00000 n +0000065288 00000 n +0000065395 00000 n +0000065502 00000 n +0000065609 00000 n +0000065716 00000 n +0000065823 00000 n +0000065930 00000 n +0000066037 00000 n +0000066144 00000 n +0000066251 00000 n +0000066358 00000 n +0000066465 00000 n +0000066572 00000 n +0000066679 00000 n +0000066786 00000 n +0000066893 00000 n +0000066999 00000 n +0000067106 00000 n +0000067213 00000 n +0000067319 00000 n +0000067426 00000 n +0000067533 00000 n +0000067640 00000 n +0000067747 00000 n +0000067854 00000 n +0000067961 00000 n +0000068068 00000 n +0000068175 00000 n +0000068282 00000 n +0000068389 00000 n +0000068496 00000 n +0000068603 00000 n +0000068710 00000 n +0000068816 00000 n +0000068921 00000 n +0000069026 00000 n +0000069412 00000 n +0000069519 00000 n +0000069626 00000 n +0000069733 00000 n +0000069840 00000 n +0000069947 00000 n +0000070053 00000 n +0000070160 00000 n +0000070267 00000 n +0000070374 00000 n +0000070481 00000 n +0000070588 00000 n +0000070695 00000 n +0000070801 00000 n +0000070908 00000 n +0000071015 00000 n +0000071122 00000 n +0000071229 00000 n +0000071336 00000 n +0000071442 00000 n +0000071549 00000 n +0000071656 00000 n +0000071763 00000 n +0000071870 00000 n +0000071977 00000 n +0000072084 00000 n +0000072190 00000 n +0000072297 00000 n +0000072404 00000 n +0000072511 00000 n +0000072618 00000 n +0000072725 00000 n +0000072831 00000 n +0000072938 00000 n +0000073045 00000 n +0000073152 00000 n +0000073259 00000 n +0000073366 00000 n +0000073472 00000 n +0000073579 00000 n +0000073686 00000 n +0000073793 00000 n +0000073900 00000 n +0000074007 00000 n +0000074114 00000 n +0000074220 00000 n +0000074326 00000 n +0000074431 00000 n +0000074536 00000 n +0000074938 00000 n +0000075045 00000 n +0000075152 00000 n +0000075259 00000 n +0000075366 00000 n +0000075473 00000 n +0000075580 00000 n +0000075687 00000 n +0000075794 00000 n +0000075901 00000 n +0000076008 00000 n +0000076115 00000 n +0000076222 00000 n +0000076329 00000 n +0000076436 00000 n +0000076543 00000 n +0000076650 00000 n +0000076757 00000 n +0000076864 00000 n +0000076971 00000 n +0000077078 00000 n +0000077185 00000 n +0000077292 00000 n +0000077399 00000 n +0000077506 00000 n +0000077613 00000 n +0000077720 00000 n +0000077827 00000 n +0000077934 00000 n +0000078041 00000 n +0000078148 00000 n +0000078255 00000 n +0000078362 00000 n +0000078469 00000 n +0000078576 00000 n +0000078683 00000 n +0000078790 00000 n +0000078897 00000 n +0000079004 00000 n +0000079111 00000 n +0000079218 00000 n +0000079325 00000 n +0000079432 00000 n +0000079539 00000 n +0000079646 00000 n +0000079753 00000 n +0000079859 00000 n +0000079964 00000 n +0000080069 00000 n +0000080471 00000 n +0000080578 00000 n +0000080685 00000 n +0000080792 00000 n +0000080899 00000 n +0000081006 00000 n +0000081112 00000 n +0000081219 00000 n +0000081326 00000 n +0000081433 00000 n +0000081540 00000 n +0000081647 00000 n +0000081754 00000 n +0000081860 00000 n +0000081967 00000 n +0000082074 00000 n +0000082181 00000 n +0000082288 00000 n +0000082395 00000 n +0000082502 00000 n +0000082608 00000 n +0000082715 00000 n +0000082822 00000 n +0000082929 00000 n +0000083036 00000 n +0000083143 00000 n +0000083250 00000 n +0000083356 00000 n +0000083463 00000 n +0000083570 00000 n +0000083677 00000 n +0000083784 00000 n +0000083891 00000 n +0000083998 00000 n +0000084104 00000 n +0000084211 00000 n +0000084318 00000 n +0000084425 00000 n +0000084532 00000 n +0000084639 00000 n +0000084745 00000 n +0000084852 00000 n +0000084959 00000 n +0000085066 00000 n +0000085173 00000 n +0000085280 00000 n +0000085386 00000 n +0000085490 00000 n +0000085595 00000 n +0000085997 00000 n +0000086104 00000 n +0000086211 00000 n +0000086318 00000 n +0000086425 00000 n +0000086532 00000 n +0000086639 00000 n +0000086746 00000 n +0000086853 00000 n +0000086960 00000 n +0000087067 00000 n +0000087174 00000 n +0000087281 00000 n +0000087388 00000 n +0000087495 00000 n +0000087602 00000 n +0000087709 00000 n +0000087816 00000 n +0000087923 00000 n +0000088030 00000 n +0000088137 00000 n +0000088244 00000 n +0000088351 00000 n +0000088458 00000 n +0000088565 00000 n +0000088672 00000 n +0000088779 00000 n +0000088886 00000 n +0000088993 00000 n +0000089100 00000 n +0000089207 00000 n +0000089314 00000 n +0000089421 00000 n +0000089528 00000 n +0000089635 00000 n +0000089742 00000 n +0000089849 00000 n +0000089956 00000 n +0000090063 00000 n +0000090170 00000 n +0000090277 00000 n +0000090384 00000 n +0000090491 00000 n +0000090598 00000 n +0000090705 00000 n +0000090812 00000 n +0000090918 00000 n +0000091023 00000 n +0000091128 00000 n +0000091530 00000 n +0000091637 00000 n +0000091744 00000 n +0000091850 00000 n +0000091957 00000 n +0000092064 00000 n +0000092171 00000 n +0000092278 00000 n +0000092385 00000 n +0000092491 00000 n +0000092598 00000 n +0000092705 00000 n +0000092812 00000 n +0000092919 00000 n +0000093026 00000 n +0000093132 00000 n +0000093239 00000 n +0000093346 00000 n +0000093453 00000 n +0000093560 00000 n +0000093667 00000 n +0000093773 00000 n +0000093880 00000 n +0000093987 00000 n +0000094094 00000 n +0000094201 00000 n +0000094308 00000 n +0000094415 00000 n +0000094521 00000 n +0000094628 00000 n +0000094735 00000 n +0000094842 00000 n +0000094949 00000 n +0000095056 00000 n +0000095162 00000 n +0000095269 00000 n +0000095376 00000 n +0000095483 00000 n +0000095590 00000 n +0000095697 00000 n +0000095803 00000 n +0000095910 00000 n +0000096017 00000 n +0000096124 00000 n +0000096231 00000 n +0000096338 00000 n +0000096444 00000 n +0000096548 00000 n +0000096653 00000 n +0000097055 00000 n +0000097162 00000 n +0000097269 00000 n +0000097376 00000 n +0000097483 00000 n +0000097590 00000 n +0000097697 00000 n +0000097804 00000 n +0000097911 00000 n +0000098018 00000 n +0000098125 00000 n +0000098232 00000 n +0000098339 00000 n +0000098446 00000 n +0000098553 00000 n +0000098660 00000 n +0000098767 00000 n +0000098874 00000 n +0000098981 00000 n +0000099088 00000 n +0000099195 00000 n +0000099302 00000 n +0000099409 00000 n +0000099516 00000 n +0000099623 00000 n +0000099730 00000 n +0000099837 00000 n +0000099944 00000 n +0000100051 00000 n +0000100158 00000 n +0000100265 00000 n +0000100372 00000 n +0000100479 00000 n +0000100586 00000 n +0000100693 00000 n +0000100800 00000 n +0000100907 00000 n +0000101014 00000 n +0000101121 00000 n +0000101228 00000 n +0000101335 00000 n +0000101442 00000 n +0000101549 00000 n +0000101656 00000 n +0000101763 00000 n +0000101870 00000 n +0000101976 00000 n +0000102081 00000 n +0000102186 00000 n +0000102588 00000 n +0000102695 00000 n +0000102802 00000 n +0000102909 00000 n +0000103016 00000 n +0000103123 00000 n +0000103229 00000 n +0000103336 00000 n +0000103443 00000 n +0000103550 00000 n +0000103657 00000 n +0000103764 00000 n +0000103871 00000 n +0000103977 00000 n +0000104084 00000 n +0000104191 00000 n +0000104298 00000 n +0000104405 00000 n +0000104513 00000 n +0000104621 00000 n +0000104728 00000 n +0000104836 00000 n +0000104944 00000 n +0000105052 00000 n +0000105160 00000 n +0000105268 00000 n +0000105376 00000 n +0000105483 00000 n +0000105591 00000 n +0000105699 00000 n +0000105807 00000 n +0000105915 00000 n +0000106022 00000 n +0000106130 00000 n +0000106238 00000 n +0000106346 00000 n +0000106454 00000 n +0000106562 00000 n +0000106670 00000 n +0000106777 00000 n +0000106885 00000 n +0000106993 00000 n +0000107101 00000 n +0000107209 00000 n +0000107317 00000 n +0000107425 00000 n +0000107531 00000 n +0000107637 00000 n +0000107743 00000 n +0000108177 00000 n +0000108285 00000 n +0000108393 00000 n +0000108501 00000 n +0000108609 00000 n +0000108717 00000 n +0000108825 00000 n +0000108933 00000 n +0000109041 00000 n +0000109149 00000 n +0000109257 00000 n +0000109365 00000 n +0000109473 00000 n +0000109581 00000 n +0000109689 00000 n +0000109797 00000 n +0000109905 00000 n +0000110013 00000 n +0000110121 00000 n +0000110229 00000 n +0000110337 00000 n +0000110445 00000 n +0000110553 00000 n +0000110661 00000 n +0000110769 00000 n +0000110877 00000 n +0000110985 00000 n +0000111093 00000 n +0000111201 00000 n +0000111309 00000 n +0000111417 00000 n +0000111525 00000 n +0000111633 00000 n +0000111741 00000 n +0000111849 00000 n +0000111957 00000 n +0000112065 00000 n +0000112173 00000 n +0000112281 00000 n +0000112389 00000 n +0000112497 00000 n +0000112605 00000 n +0000112713 00000 n +0000112821 00000 n +0000112929 00000 n +0000113037 00000 n +0000113144 00000 n +0000113250 00000 n +0000113356 00000 n +0000113807 00000 n +0000113915 00000 n +0000114023 00000 n +0000114131 00000 n +0000114238 00000 n +0000114346 00000 n +0000114454 00000 n +0000114562 00000 n +0000114670 00000 n +0000114778 00000 n +0000114886 00000 n +0000114993 00000 n +0000115101 00000 n +0000115209 00000 n +0000115317 00000 n +0000115425 00000 n +0000115533 00000 n +0000115641 00000 n +0000115748 00000 n +0000115856 00000 n +0000115964 00000 n +0000116072 00000 n +0000116180 00000 n +0000116288 00000 n +0000116396 00000 n +0000116503 00000 n +0000116611 00000 n +0000116719 00000 n +0000116827 00000 n +0000116935 00000 n +0000117043 00000 n +0000117151 00000 n +0000117258 00000 n +0000117366 00000 n +0000117474 00000 n +0000117582 00000 n +0000117690 00000 n +0000117798 00000 n +0000117906 00000 n +0000118013 00000 n +0000118121 00000 n +0000118229 00000 n +0000118337 00000 n +0000118445 00000 n +0000118553 00000 n +0000118661 00000 n +0000118767 00000 n +0000118873 00000 n +0000118979 00000 n +0000119430 00000 n +0000119538 00000 n +0000119646 00000 n +0000119754 00000 n +0000119862 00000 n +0000119970 00000 n +0000120078 00000 n +0000120186 00000 n +0000120294 00000 n +0000120402 00000 n +0000120510 00000 n +0000120618 00000 n +0000120726 00000 n +0000120834 00000 n +0000120942 00000 n +0000121050 00000 n +0000121158 00000 n +0000121266 00000 n +0000121374 00000 n +0000121482 00000 n +0000121590 00000 n +0000121698 00000 n +0000121806 00000 n +0000121914 00000 n +0000122022 00000 n +0000122130 00000 n +0000122238 00000 n +0000122346 00000 n +0000122454 00000 n +0000122562 00000 n +0000122670 00000 n +0000122778 00000 n +0000122886 00000 n +0000122994 00000 n +0000123102 00000 n +0000123210 00000 n +0000123318 00000 n +0000123426 00000 n +0000123534 00000 n +0000123642 00000 n +0000123750 00000 n +0000123858 00000 n +0000123966 00000 n +0000124074 00000 n +0000124182 00000 n +0000124290 00000 n +0000124397 00000 n +0000124503 00000 n +0000124609 00000 n +0000125060 00000 n +0000125168 00000 n +0000125276 00000 n +0000125384 00000 n +0000125492 00000 n +0000125600 00000 n +0000125707 00000 n +0000125815 00000 n +0000125923 00000 n +0000126031 00000 n +0000126139 00000 n +0000126247 00000 n +0000126354 00000 n +0000126462 00000 n +0000126570 00000 n +0000126678 00000 n +0000126786 00000 n +0000126894 00000 n +0000127002 00000 n +0000127109 00000 n +0000127217 00000 n +0000127325 00000 n +0000127433 00000 n +0000127541 00000 n +0000127649 00000 n +0000127757 00000 n +0000127864 00000 n +0000127972 00000 n +0000128080 00000 n +0000128188 00000 n +0000128296 00000 n +0000128404 00000 n +0000128511 00000 n +0000128619 00000 n +0000128727 00000 n +0000128835 00000 n +0000128943 00000 n +0000129051 00000 n +0000129158 00000 n +0000129266 00000 n +0000129374 00000 n +0000129482 00000 n +0000129590 00000 n +0000129698 00000 n +0000129806 00000 n +0000129913 00000 n +0000130020 00000 n +0000130126 00000 n +0000130232 00000 n +0000130683 00000 n +0000130791 00000 n +0000130899 00000 n +0000131007 00000 n +0000131115 00000 n +0000131223 00000 n +0000131331 00000 n +0000131439 00000 n +0000131547 00000 n +0000131655 00000 n +0000131763 00000 n +0000131871 00000 n +0000131979 00000 n +0000132087 00000 n +0000132195 00000 n +0000132303 00000 n +0000132411 00000 n +0000132519 00000 n +0000132627 00000 n +0000132735 00000 n +0000132843 00000 n +0000132951 00000 n +0000133059 00000 n +0000133167 00000 n +0000133275 00000 n +0000133383 00000 n +0000133491 00000 n +0000133599 00000 n +0000133707 00000 n +0000133815 00000 n +0000133923 00000 n +0000134031 00000 n +0000134139 00000 n +0000134247 00000 n +0000134355 00000 n +0000134463 00000 n +0000134571 00000 n +0000134679 00000 n +0000134787 00000 n +0000134895 00000 n +0000135003 00000 n +0000135111 00000 n +0000135219 00000 n +0000135327 00000 n +0000135435 00000 n +0000135543 00000 n +0000135650 00000 n +0000135756 00000 n +0000135862 00000 n +0000136313 00000 n +0000136421 00000 n +0000136529 00000 n +0000136636 00000 n +0000136744 00000 n +0000136852 00000 n +0000136960 00000 n +0000137068 00000 n +0000137176 00000 n +0000137284 00000 n +0000137391 00000 n +0000137499 00000 n +0000137607 00000 n +0000137715 00000 n +0000137823 00000 n +0000137931 00000 n +0000138039 00000 n +0000138146 00000 n +0000138254 00000 n +0000138362 00000 n +0000138470 00000 n +0000138578 00000 n +0000138686 00000 n +0000138794 00000 n +0000138901 00000 n +0000139009 00000 n +0000139117 00000 n +0000139225 00000 n +0000139333 00000 n +0000139441 00000 n +0000139548 00000 n +0000139656 00000 n +0000139764 00000 n +0000139872 00000 n +0000139980 00000 n +0000140088 00000 n +0000140196 00000 n +0000140303 00000 n +0000140411 00000 n +0000140519 00000 n +0000140627 00000 n +0000140735 00000 n +0000140843 00000 n +0000140951 00000 n +0000141058 00000 n +0000141166 00000 n +0000141273 00000 n +0000141379 00000 n +0000141485 00000 n +0000141936 00000 n +0000142044 00000 n +0000142152 00000 n +0000142260 00000 n +0000142368 00000 n +0000142476 00000 n +0000142584 00000 n +0000142692 00000 n +0000142800 00000 n +0000142908 00000 n +0000143016 00000 n +0000143124 00000 n +0000143232 00000 n +0000143340 00000 n +0000143448 00000 n +0000143556 00000 n +0000143664 00000 n +0000143772 00000 n +0000143880 00000 n +0000143988 00000 n +0000144096 00000 n +0000144204 00000 n +0000144312 00000 n +0000144420 00000 n +0000144528 00000 n +0000144636 00000 n +0000144744 00000 n +0000144852 00000 n +0000144960 00000 n +0000145068 00000 n +0000145176 00000 n +0000145465 00000 n +0000145501 00000 n +0000145537 00000 n +0000159248 00000 n +0000159299 00000 n +0000159350 00000 n +0000159401 00000 n +0000159452 00000 n +0000159503 00000 n +0000159554 00000 n +0000159605 00000 n +0000159656 00000 n +0000159707 00000 n +0000159758 00000 n +0000159809 00000 n +0000159860 00000 n +0000159911 00000 n +0000159962 00000 n +0000160013 00000 n +0000160064 00000 n +0000160115 00000 n +0000160166 00000 n +0000160217 00000 n +0000160268 00000 n +0000160319 00000 n +0000160370 00000 n +0000160421 00000 n +0000160472 00000 n +0000160523 00000 n +0000160574 00000 n +0000160625 00000 n +0000160676 00000 n +0000160727 00000 n +0000160778 00000 n +0000160829 00000 n +0000160880 00000 n +0000160931 00000 n +0000160982 00000 n +0000161033 00000 n +0000161084 00000 n +0000161135 00000 n +0000161186 00000 n +0000161237 00000 n +0000161288 00000 n +0000161339 00000 n +0000161390 00000 n +0000161441 00000 n +0000161492 00000 n +0000161543 00000 n +0000161594 00000 n +0000161645 00000 n +0000161696 00000 n +0000161747 00000 n +0000161798 00000 n +0000161849 00000 n +0000161900 00000 n +0000161951 00000 n +0000162002 00000 n +0000162053 00000 n +0000162104 00000 n +0000162155 00000 n +0000162206 00000 n +0000162257 00000 n +0000162308 00000 n +0000162359 00000 n +0000162410 00000 n +0000162461 00000 n +0000162512 00000 n +0000162563 00000 n +0000162614 00000 n +0000162665 00000 n +0000162716 00000 n +0000162767 00000 n +0000162818 00000 n +0000162869 00000 n +0000162920 00000 n +0000162971 00000 n +0000163022 00000 n +0000163073 00000 n +0000163124 00000 n +0000163175 00000 n +0000163226 00000 n +0000163277 00000 n +0000163328 00000 n +0000163379 00000 n +0000163430 00000 n +0000163481 00000 n +0000163532 00000 n +0000163583 00000 n +0000163634 00000 n +0000163685 00000 n +0000163736 00000 n +0000163787 00000 n +0000163838 00000 n +0000163889 00000 n +0000163940 00000 n +0000163991 00000 n +0000164042 00000 n +0000164093 00000 n +0000164144 00000 n +0000164195 00000 n +0000164246 00000 n +0000164297 00000 n +0000164348 00000 n +0000164399 00000 n +0000164450 00000 n +0000164501 00000 n +0000164552 00000 n +0000164603 00000 n +0000164654 00000 n +0000164705 00000 n +0000164756 00000 n +0000164807 00000 n +0000164858 00000 n +0000164909 00000 n +0000164960 00000 n +0000165011 00000 n +0000165062 00000 n +0000165113 00000 n +0000165164 00000 n +0000165215 00000 n +0000165266 00000 n +0000165317 00000 n +0000165368 00000 n +0000165419 00000 n +0000165470 00000 n +0000165521 00000 n +0000165572 00000 n +0000165623 00000 n +0000165674 00000 n +0000165725 00000 n +0000165776 00000 n +0000165827 00000 n +0000165878 00000 n +0000165929 00000 n +0000165980 00000 n +0000166031 00000 n +0000166082 00000 n +0000166133 00000 n +0000166184 00000 n +0000166235 00000 n +0000166286 00000 n +0000166337 00000 n +0000166388 00000 n +0000166439 00000 n +0000166490 00000 n +0000166541 00000 n +0000166592 00000 n +0000166643 00000 n +0000166694 00000 n +0000166745 00000 n +0000166796 00000 n +0000166847 00000 n +0000166898 00000 n +0000166949 00000 n +0000167000 00000 n +0000167051 00000 n +0000167102 00000 n +0000167153 00000 n +0000167204 00000 n +0000167255 00000 n +0000167306 00000 n +0000167357 00000 n +0000167408 00000 n +0000167459 00000 n +0000167510 00000 n +0000167561 00000 n +0000167612 00000 n +0000167663 00000 n +0000167714 00000 n +0000167765 00000 n +0000167816 00000 n +0000167867 00000 n +0000167918 00000 n +0000167969 00000 n +0000168020 00000 n +0000168071 00000 n +0000168122 00000 n +0000168173 00000 n +0000168224 00000 n +0000168275 00000 n +0000168326 00000 n +0000168377 00000 n +0000168428 00000 n +0000168479 00000 n +0000168530 00000 n +0000168581 00000 n +0000168632 00000 n +0000168683 00000 n +0000168734 00000 n +0000168785 00000 n +0000168836 00000 n +0000168887 00000 n +0000168938 00000 n +0000168989 00000 n +0000169040 00000 n +0000169091 00000 n +0000169142 00000 n +0000169193 00000 n +0000169244 00000 n +0000169295 00000 n +0000169346 00000 n +0000169397 00000 n +0000169448 00000 n +0000169499 00000 n +0000169550 00000 n +0000169601 00000 n +0000169652 00000 n +0000169703 00000 n +0000169754 00000 n +0000169805 00000 n +0000169856 00000 n +0000169907 00000 n +0000169958 00000 n +0000170009 00000 n +0000170060 00000 n +0000170111 00000 n +0000170162 00000 n +0000170213 00000 n +0000170264 00000 n +0000170315 00000 n +0000170366 00000 n +0000170417 00000 n +0000170468 00000 n +0000170519 00000 n +0000170570 00000 n +0000170621 00000 n +0000170672 00000 n +0000170723 00000 n +0000170774 00000 n +0000170825 00000 n +0000170876 00000 n +0000170927 00000 n +0000170978 00000 n +0000171029 00000 n +0000171080 00000 n +0000171131 00000 n +0000171182 00000 n +0000171233 00000 n +0000171284 00000 n +0000171335 00000 n +0000171386 00000 n +0000171437 00000 n +0000171488 00000 n +0000171539 00000 n +0000171590 00000 n +0000171641 00000 n +0000171692 00000 n +0000171743 00000 n +0000171794 00000 n +0000171845 00000 n +0000171896 00000 n +0000171947 00000 n +0000171998 00000 n +0000172049 00000 n +0000172100 00000 n +0000172151 00000 n +0000172202 00000 n +0000172253 00000 n +0000172304 00000 n +0000172355 00000 n +0000172406 00000 n +0000172457 00000 n +0000172508 00000 n +0000172559 00000 n +0000172610 00000 n +0000172661 00000 n +0000172712 00000 n +0000172763 00000 n +0000172814 00000 n +0000172865 00000 n +0000172916 00000 n +0000172967 00000 n +0000173018 00000 n +0000173069 00000 n +0000173120 00000 n +0000173171 00000 n +0000173222 00000 n +0000173273 00000 n +0000173324 00000 n +0000173375 00000 n +0000173426 00000 n +0000173477 00000 n +0000173528 00000 n +0000173579 00000 n +0000173630 00000 n +0000173681 00000 n +0000173732 00000 n +0000173783 00000 n +0000173834 00000 n +0000173885 00000 n +0000173936 00000 n +0000173987 00000 n +0000174038 00000 n +0000174089 00000 n +0000174140 00000 n +0000174191 00000 n +0000174242 00000 n +0000174293 00000 n +0000174344 00000 n +0000174395 00000 n +0000174446 00000 n +0000174497 00000 n +0000174548 00000 n +0000174599 00000 n +0000174650 00000 n +0000174701 00000 n +0000174752 00000 n +0000174803 00000 n +0000174854 00000 n +0000174905 00000 n +0000174956 00000 n +0000175007 00000 n +0000175058 00000 n +0000175109 00000 n +0000175160 00000 n +0000175211 00000 n +0000175262 00000 n +0000175313 00000 n +0000175364 00000 n +0000175415 00000 n +0000175466 00000 n +0000175517 00000 n +0000175568 00000 n +0000175619 00000 n +0000175670 00000 n +0000175721 00000 n +0000175772 00000 n +0000175823 00000 n +0000175874 00000 n +0000175925 00000 n +0000175976 00000 n +0000176027 00000 n +0000176078 00000 n +0000176129 00000 n +0000176180 00000 n +0000176231 00000 n +0000176282 00000 n +0000176333 00000 n +0000176384 00000 n +0000176435 00000 n +0000176486 00000 n +0000176537 00000 n +0000176588 00000 n +0000176639 00000 n +0000176690 00000 n +0000176741 00000 n +0000176792 00000 n +0000176843 00000 n +0000176894 00000 n +0000176945 00000 n +0000176996 00000 n +0000177047 00000 n +0000177098 00000 n +0000177149 00000 n +0000177200 00000 n +0000177251 00000 n +0000177302 00000 n +0000177353 00000 n +0000177404 00000 n +0000177455 00000 n +0000177506 00000 n +0000177557 00000 n +0000177608 00000 n +0000177659 00000 n +0000177710 00000 n +0000177761 00000 n +0000177812 00000 n +0000177863 00000 n +0000177914 00000 n +0000177965 00000 n +0000178016 00000 n +0000178067 00000 n +0000178118 00000 n +0000178169 00000 n +0000178220 00000 n +0000178271 00000 n +0000178322 00000 n +0000178373 00000 n +0000178424 00000 n +0000178475 00000 n +0000178526 00000 n +0000178577 00000 n +0000178628 00000 n +0000178679 00000 n +0000178730 00000 n +0000178781 00000 n +0000178832 00000 n +0000178883 00000 n +0000178934 00000 n +0000178985 00000 n +0000179036 00000 n +0000179087 00000 n +0000179138 00000 n +0000179189 00000 n +0000179240 00000 n +0000179291 00000 n +0000179342 00000 n +0000179393 00000 n +0000179444 00000 n +0000179495 00000 n +0000179546 00000 n +0000179597 00000 n +0000179648 00000 n +0000179699 00000 n +0000179750 00000 n +0000179801 00000 n +0000179852 00000 n +0000179903 00000 n +0000179954 00000 n +0000180005 00000 n +0000180056 00000 n +0000180107 00000 n +0000180158 00000 n +0000180209 00000 n +0000180260 00000 n +0000180311 00000 n +0000180362 00000 n +0000180413 00000 n +0000180464 00000 n +0000180515 00000 n +0000180566 00000 n +0000180617 00000 n +0000180668 00000 n +0000180719 00000 n +0000180770 00000 n +0000180821 00000 n +0000180872 00000 n +0000180923 00000 n +0000180974 00000 n +0000181025 00000 n +0000181076 00000 n +0000181127 00000 n +0000181178 00000 n +0000181229 00000 n +0000181280 00000 n +0000181331 00000 n +0000181382 00000 n +0000181433 00000 n +0000181484 00000 n +0000181535 00000 n +0000181586 00000 n +0000181637 00000 n +0000181688 00000 n +0000181739 00000 n +0000181790 00000 n +0000181841 00000 n +0000181892 00000 n +0000181943 00000 n +0000181994 00000 n +0000182045 00000 n +0000182096 00000 n +0000182147 00000 n +0000182198 00000 n +0000182249 00000 n +0000182300 00000 n +0000182351 00000 n +0000182402 00000 n +0000182453 00000 n +0000182504 00000 n +0000182555 00000 n +0000182606 00000 n +0000182657 00000 n +0000182708 00000 n +0000182759 00000 n +0000182810 00000 n +0000182861 00000 n +0000182912 00000 n +0000182963 00000 n +0000183014 00000 n +0000183065 00000 n +0000183116 00000 n +0000183167 00000 n +0000183218 00000 n +0000183269 00000 n +0000183320 00000 n +0000183371 00000 n +0000183422 00000 n +0000183473 00000 n +0000183524 00000 n +0000183575 00000 n +0000183626 00000 n +0000183677 00000 n +0000183728 00000 n +0000183779 00000 n +0000183830 00000 n +0000183881 00000 n +0000183932 00000 n +0000183983 00000 n +0000184034 00000 n +0000184085 00000 n +0000184136 00000 n +0000184187 00000 n +0000184238 00000 n +0000184289 00000 n +0000184340 00000 n +0000184391 00000 n +0000184442 00000 n +0000184493 00000 n +0000184544 00000 n +0000184595 00000 n +0000184646 00000 n +0000184697 00000 n +0000184748 00000 n +0000184799 00000 n +0000184850 00000 n +0000184901 00000 n +0000184952 00000 n +0000185003 00000 n +0000185054 00000 n +0000185105 00000 n +0000185156 00000 n +0000185207 00000 n +0000185258 00000 n +0000185309 00000 n +0000185360 00000 n +0000185411 00000 n +0000185462 00000 n +0000185513 00000 n +0000185564 00000 n +0000185615 00000 n +0000185666 00000 n +0000185717 00000 n +0000185768 00000 n +0000185819 00000 n +0000185870 00000 n +0000185921 00000 n +0000185972 00000 n +0000186023 00000 n +0000186074 00000 n +0000186125 00000 n +0000186176 00000 n +0000186227 00000 n +0000186278 00000 n +0000186329 00000 n +0000186380 00000 n +0000186431 00000 n +0000186482 00000 n +0000186533 00000 n +0000186584 00000 n +0000186635 00000 n +0000186686 00000 n +0000186737 00000 n +0000186788 00000 n +0000186839 00000 n +0000186890 00000 n +0000186941 00000 n +0000186992 00000 n +0000187043 00000 n +0000187094 00000 n +0000187145 00000 n +0000187196 00000 n +0000187247 00000 n +0000187298 00000 n +0000187349 00000 n +0000187400 00000 n +0000187451 00000 n +0000187502 00000 n +0000187553 00000 n +0000187604 00000 n +0000187655 00000 n +0000187706 00000 n +0000187757 00000 n +0000187808 00000 n +0000187859 00000 n +0000187910 00000 n +0000187961 00000 n +0000188012 00000 n +0000188063 00000 n +0000188114 00000 n +0000188165 00000 n +0000188216 00000 n +0000188267 00000 n +0000188318 00000 n +0000188369 00000 n +0000188420 00000 n +0000188471 00000 n +0000188522 00000 n +0000188573 00000 n +0000188624 00000 n +0000188675 00000 n +0000188726 00000 n +0000188777 00000 n +0000188828 00000 n +0000188879 00000 n +0000188930 00000 n +0000188981 00000 n +0000189032 00000 n +0000189083 00000 n +0000189134 00000 n +0000189185 00000 n +0000189236 00000 n +0000189287 00000 n +0000189338 00000 n +0000189389 00000 n +0000189440 00000 n +0000189491 00000 n +0000189542 00000 n +0000189593 00000 n +0000189644 00000 n +0000189695 00000 n +0000189746 00000 n +0000189797 00000 n +0000189848 00000 n +0000189899 00000 n +0000189950 00000 n +0000190001 00000 n +0000190052 00000 n +0000190103 00000 n +0000190154 00000 n +0000190205 00000 n +0000190256 00000 n +0000190307 00000 n +0000190358 00000 n +0000190409 00000 n +0000190460 00000 n +0000190511 00000 n +0000190562 00000 n +0000190613 00000 n +0000190664 00000 n +0000190715 00000 n +0000190766 00000 n +0000190817 00000 n +0000190868 00000 n +0000190919 00000 n +0000190970 00000 n +0000191021 00000 n +0000191072 00000 n +0000191123 00000 n +0000191174 00000 n +0000191225 00000 n +0000191276 00000 n +0000191327 00000 n +0000191378 00000 n +0000191429 00000 n +0000191480 00000 n +0000191531 00000 n +0000191582 00000 n +0000191633 00000 n +0000191684 00000 n +0000191735 00000 n +0000191786 00000 n +0000191837 00000 n +0000191888 00000 n +0000191939 00000 n +0000191990 00000 n +0000192041 00000 n +0000192092 00000 n +0000192143 00000 n +0000192194 00000 n +0000192245 00000 n +0000192296 00000 n +0000192347 00000 n +0000192398 00000 n +0000192449 00000 n +0000192500 00000 n +0000192551 00000 n +0000192602 00000 n +0000192653 00000 n +0000192704 00000 n +0000192755 00000 n +0000192806 00000 n +0000192857 00000 n +0000192908 00000 n +0000192959 00000 n +0000193010 00000 n +0000193061 00000 n +0000193112 00000 n +0000193163 00000 n +0000193214 00000 n +0000193265 00000 n +0000193316 00000 n +0000193367 00000 n +0000193418 00000 n +0000193469 00000 n +0000193520 00000 n +0000193571 00000 n +0000193622 00000 n +0000193673 00000 n +0000193724 00000 n +0000193775 00000 n +0000193826 00000 n +0000193877 00000 n +0000193928 00000 n +0000193979 00000 n +0000194030 00000 n +0000194081 00000 n +0000194132 00000 n +0000194183 00000 n +0000194234 00000 n +0000194285 00000 n +0000194336 00000 n +0000194387 00000 n +0000194438 00000 n +0000194489 00000 n +0000194540 00000 n +0000194591 00000 n +0000194642 00000 n +0000194693 00000 n +0000194744 00000 n +0000194795 00000 n +0000194846 00000 n +0000194897 00000 n +0000194948 00000 n +0000194999 00000 n +0000195050 00000 n +0000195101 00000 n +0000195152 00000 n +0000195203 00000 n +0000195254 00000 n +0000195305 00000 n +0000195356 00000 n +0000195407 00000 n +0000195458 00000 n +0000195509 00000 n +0000195560 00000 n +0000195611 00000 n +0000195662 00000 n +0000195713 00000 n +0000195764 00000 n +0000195815 00000 n +0000195866 00000 n +0000195917 00000 n +0000195968 00000 n +0000196019 00000 n +0000196070 00000 n +0000196121 00000 n +0000196172 00000 n +0000196223 00000 n +0000196274 00000 n +0000196325 00000 n +0000196376 00000 n +0000196427 00000 n +0000196478 00000 n +0000196529 00000 n +0000196580 00000 n +0000196631 00000 n +0000196682 00000 n +0000196733 00000 n +0000196784 00000 n +0000196835 00000 n +0000196886 00000 n +0000196937 00000 n +0000196988 00000 n +0000197039 00000 n +0000197090 00000 n +0000197141 00000 n +0000197192 00000 n +0000197243 00000 n +0000197294 00000 n +0000197345 00000 n +0000197396 00000 n +0000197447 00000 n +0000197498 00000 n +0000197549 00000 n +0000197600 00000 n +0000197651 00000 n +0000197702 00000 n +0000197753 00000 n +0000197804 00000 n +0000197855 00000 n +0000197906 00000 n +0000197957 00000 n +0000198008 00000 n +0000198059 00000 n +0000198110 00000 n +0000198161 00000 n +0000198212 00000 n +0000198263 00000 n +0000198314 00000 n +0000198365 00000 n +0000198416 00000 n +0000198467 00000 n +0000198518 00000 n +0000198569 00000 n +0000198620 00000 n +0000198671 00000 n +0000198722 00000 n +0000198773 00000 n +0000198824 00000 n +0000198875 00000 n +0000198926 00000 n +0000198977 00000 n +0000199028 00000 n +0000199079 00000 n +0000199130 00000 n +0000199181 00000 n +0000199232 00000 n +0000199283 00000 n +0000199334 00000 n +0000199385 00000 n +0000199436 00000 n +0000199487 00000 n +0000199538 00000 n +0000201031 00000 n +0000201188 00000 n +0000207540 00000 n +0000207563 00000 n +0000207661 00000 n +0000207765 00000 n +0000207786 00000 n +0000207946 00000 n +0000208961 00000 n +0000208983 00000 n +0000209189 00000 n +0000210417 00000 n +0000210440 00000 n +0000210585 00000 n +0000210884 00000 n +0000210906 00000 n +0000211023 00000 n +0000211221 00000 n +0000211243 00000 n +0000211388 00000 n +0000212297 00000 n +0000212319 00000 n +0000212464 00000 n +0000213989 00000 n +0000214012 00000 n +0000214157 00000 n +0000215153 00000 n +0000215175 00000 n +0000215292 00000 n +0000215488 00000 n +0000215510 00000 n +0000215664 00000 n +0000216407 00000 n +0000216429 00000 n +0000216593 00000 n +0000217544 00000 n +0000217566 00000 n +0000217720 00000 n +0000218707 00000 n +0000218729 00000 n +0000218883 00000 n +0000219921 00000 n +0000219943 00000 n +0000220097 00000 n +0000221037 00000 n +0000221059 00000 n +0000221218 00000 n +0000222384 00000 n +0000222407 00000 n +0000222561 00000 n +0000223492 00000 n +0000223514 00000 n +0000223668 00000 n +0000225072 00000 n +0000225095 00000 n +0000225240 00000 n +0000226718 00000 n +0000226741 00000 n +0000226895 00000 n +0000227946 00000 n +0000227968 00000 n +0000228122 00000 n +0000228873 00000 n +0000228895 00000 n +0000229012 00000 n +0000229215 00000 n +0000229237 00000 n +0000229396 00000 n +0000230133 00000 n +0000230155 00000 n +0000230338 00000 n +0000231669 00000 n +0000231692 00000 n +0000231856 00000 n +0000233202 00000 n +0000233225 00000 n +0000233393 00000 n +0000234508 00000 n +0000234531 00000 n +0000234666 00000 n +0000235049 00000 n +0000235071 00000 n +0000235188 00000 n +0000235387 00000 n +0000235409 00000 n +0000235568 00000 n +0000236375 00000 n +0000236397 00000 n +0000236561 00000 n +0000238116 00000 n +0000238139 00000 n +0000238304 00000 n +0000239696 00000 n +0000239719 00000 n +0000239896 00000 n +0000241100 00000 n +0000241123 00000 n +0000241258 00000 n +0000241953 00000 n +0000241975 00000 n +0000242092 00000 n +0000242292 00000 n +0000242314 00000 n +0000242450 00000 n +0000243241 00000 n +0000243263 00000 n +0000243446 00000 n +0000244951 00000 n +0000244974 00000 n +0000245128 00000 n +0000246428 00000 n +0000246451 00000 n +0000246596 00000 n +0000247071 00000 n +0000247093 00000 n +0000247243 00000 n +0000248096 00000 n +0000248118 00000 n +0000248287 00000 n +0000249754 00000 n +0000249777 00000 n +0000249936 00000 n +0000251528 00000 n +0000251551 00000 n +0000251687 00000 n +0000253553 00000 n +0000253576 00000 n +0000253702 00000 n +0000255485 00000 n +0000255508 00000 n +0000255634 00000 n +0000257561 00000 n +0000257584 00000 n +0000257729 00000 n +0000259458 00000 n +0000259481 00000 n +0000259607 00000 n +0000261459 00000 n +0000261482 00000 n +0000261627 00000 n +0000263420 00000 n +0000263443 00000 n +0000263578 00000 n +0000265378 00000 n +0000265401 00000 n +0000265536 00000 n +0000267352 00000 n +0000267375 00000 n +0000267510 00000 n +0000269407 00000 n +0000269430 00000 n +0000269575 00000 n +0000271258 00000 n +0000271281 00000 n +0000271398 00000 n +0000271612 00000 n +0000271634 00000 n +0000271789 00000 n +0000272443 00000 n +0000272465 00000 n +0000272620 00000 n +0000273513 00000 n +0000273535 00000 n +0000273690 00000 n +0000275034 00000 n +0000275057 00000 n +0000275212 00000 n +0000276245 00000 n +0000276267 00000 n +0000276422 00000 n +0000277292 00000 n +0000277314 00000 n +0000277469 00000 n +0000278380 00000 n +0000278402 00000 n +0000278557 00000 n +0000279889 00000 n +0000279912 00000 n +0000280081 00000 n +0000281121 00000 n +0000281143 00000 n +0000281298 00000 n +0000282024 00000 n +0000282046 00000 n +0000282201 00000 n +0000282892 00000 n +0000282914 00000 n +0000283059 00000 n +0000283842 00000 n +0000283864 00000 n +0000283990 00000 n +0000285626 00000 n +0000285649 00000 n +0000285817 00000 n +0000286424 00000 n +0000286446 00000 n +0000286614 00000 n +0000287519 00000 n +0000287541 00000 n +0000287709 00000 n +0000288690 00000 n +0000288712 00000 n +0000288880 00000 n +0000290080 00000 n +0000290103 00000 n +0000290263 00000 n +0000291500 00000 n +0000291523 00000 n +0000291692 00000 n +0000292591 00000 n +0000292613 00000 n +0000292773 00000 n +0000293480 00000 n +0000293502 00000 n +0000293671 00000 n +0000294516 00000 n +0000294538 00000 n +0000294707 00000 n +0000295594 00000 n +0000295616 00000 n +0000295770 00000 n +0000296550 00000 n +0000296572 00000 n +0000296732 00000 n +0000297486 00000 n +0000297508 00000 n +0000297677 00000 n +0000298532 00000 n +0000298554 00000 n +0000298723 00000 n +0000299506 00000 n +0000299528 00000 n +0000299697 00000 n +0000300541 00000 n +0000300563 00000 n +0000300723 00000 n +0000301565 00000 n +0000301587 00000 n +0000301756 00000 n +0000302641 00000 n +0000302663 00000 n +0000302832 00000 n +0000303734 00000 n +0000303756 00000 n +0000303925 00000 n +0000304856 00000 n +0000304878 00000 n +0000305047 00000 n +0000305987 00000 n +0000306009 00000 n +0000306178 00000 n +0000307045 00000 n +0000307067 00000 n +0000307236 00000 n +0000308094 00000 n +0000308116 00000 n +0000308285 00000 n +0000309224 00000 n +0000309246 00000 n +0000309415 00000 n +0000310308 00000 n +0000310330 00000 n +0000310499 00000 n +0000311375 00000 n +0000311397 00000 n +0000311567 00000 n +0000312495 00000 n +0000312517 00000 n +0000312686 00000 n +0000313620 00000 n +0000313642 00000 n +0000313811 00000 n +0000314609 00000 n +0000314631 00000 n +0000314795 00000 n +0000315570 00000 n +0000315592 00000 n +0000315761 00000 n +0000316618 00000 n +0000316640 00000 n +0000316809 00000 n +0000317615 00000 n +0000317637 00000 n +0000317806 00000 n +0000318526 00000 n +0000318548 00000 n +0000318717 00000 n +0000319563 00000 n +0000319585 00000 n +0000319754 00000 n +0000320546 00000 n +0000320568 00000 n +0000320737 00000 n +0000321439 00000 n +0000321461 00000 n +0000321630 00000 n +0000322303 00000 n +0000322325 00000 n +0000322494 00000 n +0000323357 00000 n +0000323379 00000 n +0000323548 00000 n +0000324342 00000 n +0000324364 00000 n +0000324533 00000 n +0000325294 00000 n +0000325316 00000 n +0000325485 00000 n +0000326290 00000 n +0000326312 00000 n +0000326481 00000 n +0000327230 00000 n +0000327252 00000 n +0000327421 00000 n +0000328228 00000 n +0000328250 00000 n +0000328419 00000 n +0000329202 00000 n +0000329224 00000 n +0000329393 00000 n +0000330315 00000 n +0000330337 00000 n +0000330506 00000 n +0000331336 00000 n +0000331358 00000 n +0000331527 00000 n +0000332512 00000 n +0000332534 00000 n +0000332703 00000 n +0000333554 00000 n +0000333576 00000 n +0000333745 00000 n +0000334890 00000 n +0000334913 00000 n +0000335082 00000 n +0000336023 00000 n +0000336045 00000 n +0000336214 00000 n +0000337314 00000 n +0000337337 00000 n +0000337506 00000 n +0000338560 00000 n +0000338582 00000 n +0000338751 00000 n +0000339985 00000 n +0000340008 00000 n +0000340177 00000 n +0000341322 00000 n +0000341345 00000 n +0000341514 00000 n +0000342573 00000 n +0000342595 00000 n +0000342764 00000 n +0000343934 00000 n +0000343957 00000 n +0000344126 00000 n +0000345296 00000 n +0000345319 00000 n +0000345488 00000 n +0000346618 00000 n +0000346641 00000 n +0000346810 00000 n +0000347969 00000 n +0000347992 00000 n +0000348161 00000 n +0000349422 00000 n +0000349445 00000 n +0000349614 00000 n +0000350585 00000 n +0000350607 00000 n +0000350776 00000 n +0000351383 00000 n +0000351405 00000 n +0000351574 00000 n +0000352122 00000 n +0000352144 00000 n +0000352313 00000 n +0000353109 00000 n +0000353131 00000 n +0000353300 00000 n +0000354003 00000 n +0000354025 00000 n +0000354194 00000 n +0000354928 00000 n +0000354950 00000 n +0000355119 00000 n +0000355930 00000 n +0000355952 00000 n +0000356121 00000 n +0000356930 00000 n +0000356952 00000 n +0000357121 00000 n +0000357884 00000 n +0000357906 00000 n +0000358075 00000 n +0000358828 00000 n +0000358850 00000 n +0000359019 00000 n +0000359809 00000 n +0000359831 00000 n +0000360000 00000 n +0000360841 00000 n +0000360863 00000 n +0000361032 00000 n +0000361874 00000 n +0000361896 00000 n +0000362065 00000 n +0000362936 00000 n +0000362958 00000 n +0000363127 00000 n +0000363887 00000 n +0000363909 00000 n +0000364078 00000 n +0000364902 00000 n +0000364924 00000 n +0000365093 00000 n +0000365875 00000 n +0000365897 00000 n +0000366066 00000 n +0000366877 00000 n +0000366899 00000 n +0000367059 00000 n +0000369720 00000 n +0000369743 00000 n +0000369903 00000 n +0000372491 00000 n +0000372514 00000 n +0000372674 00000 n +0000374716 00000 n +0000374739 00000 n +0000374890 00000 n +0000376164 00000 n +0000376187 00000 n +0000376338 00000 n +0000377590 00000 n +0000377613 00000 n +0000377764 00000 n +0000379051 00000 n +0000379074 00000 n +0000379225 00000 n +0000380512 00000 n +0000380535 00000 n +0000380686 00000 n +0000381966 00000 n +0000381989 00000 n +0000382140 00000 n +0000383411 00000 n +0000383434 00000 n +0000383586 00000 n +0000384871 00000 n +0000384894 00000 n +0000385046 00000 n +0000386305 00000 n +0000386328 00000 n +0000386480 00000 n +0000387762 00000 n +0000387785 00000 n +0000387937 00000 n +0000389230 00000 n +0000389253 00000 n +0000389405 00000 n +0000390678 00000 n +0000390701 00000 n +0000390853 00000 n +0000392120 00000 n +0000392143 00000 n +0000392295 00000 n +0000393560 00000 n +0000393583 00000 n +0000393735 00000 n +0000394693 00000 n +0000394715 00000 n +0000394832 00000 n +0000395009 00000 n +0000395031 00000 n +0000395090 00000 n +0000395199 00000 n +0000395350 00000 n +0000395457 00000 n +0000395580 00000 n +0000395706 00000 n +0000395825 00000 n +0000395933 00000 n +0000396105 00000 n +0000396217 00000 n +0000396337 00000 n +0000396447 00000 n +0000396560 00000 n +0000396673 00000 n +0000396787 00000 n +0000396908 00000 n +0000397010 00000 n +0000397170 00000 n +0000397320 00000 n +0000397444 00000 n +0000397605 00000 n +0000397710 00000 n +0000397831 00000 n +0000397960 00000 n +0000398081 00000 n +0000398229 00000 n +0000398356 00000 n +0000398485 00000 n +0000398605 00000 n +0000398725 00000 n +0000398867 00000 n +0000398972 00000 n +0000399110 00000 n +0000399234 00000 n +0000399368 00000 n +0000399496 00000 n +0000399617 00000 n +0000399731 00000 n +0000399894 00000 n +0000400032 00000 n +0000400147 00000 n +0000400269 00000 n +0000400390 00000 n +0000400524 00000 n +0000400645 00000 n +0000400773 00000 n +0000400894 00000 n +0000401007 00000 n +0000401180 00000 n +0000401281 00000 n +0000401390 00000 n +0000401561 00000 n +0000401699 00000 n +0000401807 00000 n +0000401928 00000 n +0000402050 00000 n +0000402169 00000 n +0000402327 00000 n +0000402428 00000 n +0000402539 00000 n +0000402703 00000 n +0000402841 00000 n +0000402956 00000 n +0000403084 00000 n +0000403205 00000 n +0000403326 00000 n +0000403448 00000 n +0000403547 00000 n +0000403711 00000 n +0000403830 00000 n +0000403959 00000 n +0000404089 00000 n +0000404193 00000 n +0000404367 00000 n +0000404542 00000 n +0000404646 00000 n +0000404762 00000 n +0000404894 00000 n +0000404993 00000 n +0000405125 00000 n +0000405251 00000 n +0000405408 00000 n +0000405552 00000 n +0000405658 00000 n +0000405784 00000 n +0000405885 00000 n +0000406043 00000 n +0000406141 00000 n +0000406259 00000 n +0000406357 00000 n +0000406515 00000 n +0000406613 00000 n +0000406723 00000 n +0000406845 00000 n +0000406961 00000 n +0000407079 00000 n +0000407194 00000 n +0000407310 00000 n +0000407430 00000 n +0000407546 00000 n +0000407650 00000 n +0000407807 00000 n +0000407917 00000 n +0000408047 00000 n +0000408165 00000 n +0000408272 00000 n +0000408419 00000 n +0000408528 00000 n +0000408653 00000 n +0000408783 00000 n +0000408906 00000 n +0000409037 00000 n +0000409165 00000 n +0000409297 00000 n +0000409428 00000 n +0000409559 00000 n +0000409675 00000 n +0000409833 00000 n +0000409966 00000 n +0000410062 00000 n +0000410207 00000 n +0000410354 00000 n +0000410451 00000 n +0000410566 00000 n +0000410679 00000 n +0000410796 00000 n +0000410909 00000 n +0000411009 00000 n +0000411170 00000 n +0000411267 00000 n +0000411382 00000 n +0000411495 00000 n +0000411612 00000 n +0000411725 00000 n +0000411825 00000 n +0000411990 00000 n +0000412087 00000 n +0000412202 00000 n +0000412315 00000 n +0000412432 00000 n +0000412545 00000 n +0000412645 00000 n +0000412806 00000 n +0000412903 00000 n +0000413018 00000 n +0000413131 00000 n +0000413248 00000 n +0000413361 00000 n +0000413461 00000 n +0000413624 00000 n +0000413721 00000 n +0000413836 00000 n +0000413953 00000 n +0000414066 00000 n +0000414166 00000 n +0000414328 00000 n +0000414425 00000 n +0000414540 00000 n +0000414653 00000 n +0000414770 00000 n +0000414883 00000 n +0000414983 00000 n +0000415145 00000 n +0000415242 00000 n +0000415355 00000 n +0000415472 00000 n +0000415585 00000 n +0000415685 00000 n +0000415846 00000 n +0000415943 00000 n +0000416058 00000 n +0000416171 00000 n +0000416288 00000 n +0000416388 00000 n +0000416551 00000 n +0000416648 00000 n +0000416763 00000 n +0000416876 00000 n +0000416993 00000 n +0000417106 00000 n +0000417206 00000 n +0000417364 00000 n +0000417461 00000 n +0000417576 00000 n +0000417689 00000 n +0000417806 00000 n +0000417905 00000 n +0000418068 00000 n +0000418165 00000 n +0000418280 00000 n +0000418393 00000 n +0000418510 00000 n +0000418623 00000 n +0000418723 00000 n +0000418886 00000 n +0000418983 00000 n +0000419096 00000 n +0000419213 00000 n +0000419326 00000 n +0000419426 00000 n +0000419590 00000 n +0000419687 00000 n +0000419802 00000 n +0000419915 00000 n +0000420032 00000 n +0000420145 00000 n +0000420245 00000 n +0000420406 00000 n +0000420503 00000 n +0000420620 00000 n +0000420733 00000 n +0000420833 00000 n +0000420993 00000 n +0000421090 00000 n +0000421205 00000 n +0000421322 00000 n +0000421435 00000 n +0000421535 00000 n +0000421694 00000 n +0000421791 00000 n +0000421906 00000 n +0000422019 00000 n +0000422136 00000 n +0000422249 00000 n +0000422349 00000 n +0000422511 00000 n +0000422608 00000 n +0000422723 00000 n +0000422836 00000 n +0000422953 00000 n +0000423066 00000 n +0000423166 00000 n +0000423327 00000 n +0000423424 00000 n +0000423537 00000 n +0000423654 00000 n +0000423767 00000 n +0000423867 00000 n +0000424030 00000 n +0000424127 00000 n +0000424242 00000 n +0000424355 00000 n +0000424472 00000 n +0000424585 00000 n +0000424685 00000 n +0000424849 00000 n +0000424946 00000 n +0000425061 00000 n +0000425174 00000 n +0000425291 00000 n +0000425404 00000 n +0000425504 00000 n +0000425665 00000 n +0000425762 00000 n +0000425877 00000 n +0000425990 00000 n +0000426107 00000 n +0000426220 00000 n +0000426320 00000 n +0000426482 00000 n +0000426579 00000 n +0000426694 00000 n +0000426807 00000 n +0000426924 00000 n +0000427037 00000 n +0000427137 00000 n +0000427300 00000 n +0000427397 00000 n +0000427512 00000 n +0000427629 00000 n +0000427742 00000 n +0000427842 00000 n +0000428004 00000 n +0000428101 00000 n +0000428216 00000 n +0000428329 00000 n +0000428446 00000 n +0000428559 00000 n +0000428659 00000 n +0000428827 00000 n +0000428924 00000 n +0000429039 00000 n +0000429152 00000 n +0000429269 00000 n +0000429382 00000 n +0000429482 00000 n +0000429650 00000 n +0000429747 00000 n +0000429862 00000 n +0000429975 00000 n +0000430092 00000 n +0000430205 00000 n +0000430305 00000 n +0000430474 00000 n +0000430571 00000 n +0000430686 00000 n +0000430799 00000 n +0000430916 00000 n +0000431029 00000 n +0000431129 00000 n +0000431298 00000 n +0000431395 00000 n +0000431510 00000 n +0000431623 00000 n +0000431740 00000 n +0000431853 00000 n +0000431953 00000 n +0000432111 00000 n +0000432208 00000 n +0000432321 00000 n +0000432438 00000 n +0000432551 00000 n +0000432651 00000 n +0000432816 00000 n +0000432913 00000 n +0000433028 00000 n +0000433145 00000 n +0000433258 00000 n +0000433358 00000 n +0000433519 00000 n +0000433616 00000 n +0000433731 00000 n +0000433848 00000 n +0000433961 00000 n +0000434061 00000 n +0000434220 00000 n +0000434317 00000 n +0000434432 00000 n +0000434549 00000 n +0000434662 00000 n +0000434762 00000 n +0000434922 00000 n +0000435019 00000 n +0000435134 00000 n +0000435247 00000 n +0000435364 00000 n +0000435463 00000 n +0000435619 00000 n +0000435716 00000 n +0000435829 00000 n +0000435946 00000 n +0000436059 00000 n +0000436159 00000 n +0000436319 00000 n +0000436416 00000 n +0000436531 00000 n +0000436648 00000 n +0000436761 00000 n +0000436861 00000 n +0000437018 00000 n +0000437115 00000 n +0000437230 00000 n +0000437343 00000 n +0000437460 00000 n +0000437573 00000 n +0000437673 00000 n +0000437836 00000 n +0000437933 00000 n +0000438048 00000 n +0000438165 00000 n +0000438278 00000 n +0000438378 00000 n +0000438535 00000 n +0000438632 00000 n +0000438747 00000 n +0000438864 00000 n +0000438977 00000 n +0000439077 00000 n +0000439236 00000 n +0000439333 00000 n +0000439448 00000 n +0000439561 00000 n +0000439678 00000 n +0000439791 00000 n +0000439891 00000 n +0000440051 00000 n +0000440148 00000 n +0000440263 00000 n +0000440376 00000 n +0000440493 00000 n +0000440606 00000 n +0000440706 00000 n +0000440864 00000 n +0000440961 00000 n +0000441076 00000 n +0000441189 00000 n +0000441306 00000 n +0000441419 00000 n +0000441519 00000 n +0000441679 00000 n +0000441776 00000 n +0000441891 00000 n +0000442004 00000 n +0000442121 00000 n +0000442234 00000 n +0000442334 00000 n +0000442491 00000 n +0000442588 00000 n +0000442703 00000 n +0000442816 00000 n +0000442933 00000 n +0000443046 00000 n +0000443146 00000 n +0000443303 00000 n +0000443400 00000 n +0000443515 00000 n +0000443632 00000 n +0000443745 00000 n +0000443845 00000 n +0000444000 00000 n +0000444097 00000 n +0000444212 00000 n +0000444325 00000 n +0000444442 00000 n +0000444555 00000 n +0000444655 00000 n +0000444811 00000 n +0000444908 00000 n +0000445023 00000 n +0000445136 00000 n +0000445253 00000 n +0000445366 00000 n +0000445466 00000 n +0000445631 00000 n +0000445728 00000 n +0000445843 00000 n +0000445956 00000 n +0000446073 00000 n +0000446186 00000 n +0000446286 00000 n +0000446449 00000 n +0000446546 00000 n +0000446661 00000 n +0000446774 00000 n +0000446891 00000 n +0000447004 00000 n +0000447104 00000 n +0000447264 00000 n +0000447361 00000 n +0000447476 00000 n +0000447589 00000 n +0000447706 00000 n +0000447819 00000 n +0000447919 00000 n +0000448075 00000 n +0000448172 00000 n +0000448287 00000 n +0000448400 00000 n +0000448517 00000 n +0000448630 00000 n +0000448730 00000 n +0000448892 00000 n +0000448989 00000 n +0000449106 00000 n +0000449219 00000 n +0000449319 00000 n +0000449478 00000 n +0000449575 00000 n +0000449690 00000 n +0000449803 00000 n +0000449920 00000 n +0000450033 00000 n +0000450133 00000 n +0000450289 00000 n +0000450386 00000 n +0000450501 00000 n +0000450614 00000 n +0000450731 00000 n +0000450844 00000 n +0000450944 00000 n +0000451102 00000 n +0000451199 00000 n +0000451314 00000 n +0000451427 00000 n +0000451544 00000 n +0000451657 00000 n +0000451757 00000 n +0000451912 00000 n +0000452009 00000 n +0000452124 00000 n +0000452237 00000 n +0000452354 00000 n +0000452467 00000 n +0000452567 00000 n +0000452723 00000 n +0000452820 00000 n +0000452935 00000 n +0000453048 00000 n +0000453165 00000 n +0000453278 00000 n +0000453378 00000 n +0000453539 00000 n +0000453636 00000 n +0000453751 00000 n +0000453864 00000 n +0000453981 00000 n +0000454094 00000 n +0000454194 00000 n +0000454354 00000 n +0000454451 00000 n +0000454566 00000 n +0000454683 00000 n +0000454796 00000 n +0000454896 00000 n +0000455056 00000 n +0000455153 00000 n +0000455268 00000 n +0000455385 00000 n +0000455498 00000 n +0000455598 00000 n +0000455755 00000 n +0000455852 00000 n +0000455967 00000 n +0000456080 00000 n +0000456197 00000 n +0000456310 00000 n +0000456410 00000 n +0000456568 00000 n +0000456665 00000 n +0000456780 00000 n +0000456893 00000 n +0000457010 00000 n +0000457123 00000 n +0000457223 00000 n +0000457380 00000 n +0000457477 00000 n +0000457592 00000 n +0000457705 00000 n +0000457822 00000 n +0000457935 00000 n +0000458035 00000 n +0000458196 00000 n +0000458293 00000 n +0000458408 00000 n +0000458521 00000 n +0000458638 00000 n +0000458751 00000 n +0000458851 00000 n +0000459013 00000 n +0000459110 00000 n +0000459225 00000 n +0000459338 00000 n +0000459455 00000 n +0000459568 00000 n +0000459668 00000 n +0000459826 00000 n +0000459923 00000 n +0000460038 00000 n +0000460151 00000 n +0000460268 00000 n +0000460381 00000 n +0000460481 00000 n +0000460642 00000 n +0000460739 00000 n +0000460854 00000 n +0000460967 00000 n +0000461084 00000 n +0000461197 00000 n +0000461297 00000 n +0000461459 00000 n +0000461556 00000 n +0000461671 00000 n +0000461784 00000 n +0000461901 00000 n +0000462014 00000 n +0000462114 00000 n +0000462273 00000 n +0000462370 00000 n +0000462485 00000 n +0000462598 00000 n +0000462715 00000 n +0000462828 00000 n +0000462928 00000 n +0000463088 00000 n +0000463185 00000 n +0000463300 00000 n +0000463413 00000 n +0000463530 00000 n +0000463643 00000 n +0000463743 00000 n +0000463907 00000 n +0000464004 00000 n +0000464119 00000 n +0000464232 00000 n +0000464349 00000 n +0000464462 00000 n +0000464562 00000 n +0000464727 00000 n +0000464824 00000 n +0000464939 00000 n +0000465052 00000 n +0000465169 00000 n +0000465282 00000 n +0000465382 00000 n +0000465545 00000 n +0000465642 00000 n +0000465757 00000 n +0000465870 00000 n +0000465987 00000 n +0000466100 00000 n +0000466200 00000 n +0000466360 00000 n +0000466457 00000 n +0000466572 00000 n +0000466685 00000 n +0000466802 00000 n +0000466915 00000 n +0000467015 00000 n +0000467176 00000 n +0000467273 00000 n +0000467388 00000 n +0000467501 00000 n +0000467618 00000 n +0000467731 00000 n +0000467831 00000 n +0000467992 00000 n +0000468089 00000 n +0000468204 00000 n +0000468317 00000 n +0000468434 00000 n +0000468547 00000 n +0000468647 00000 n +0000468804 00000 n +0000468901 00000 n +0000469016 00000 n +0000469133 00000 n +0000469246 00000 n +0000469346 00000 n +0000469510 00000 n +0000469607 00000 n +0000469722 00000 n +0000469835 00000 n +0000469952 00000 n +0000470065 00000 n +0000470165 00000 n +0000470322 00000 n +0000470419 00000 n +0000470534 00000 n +0000470647 00000 n +0000470764 00000 n +0000470877 00000 n +0000470977 00000 n +0000471131 00000 n +0000471228 00000 n +0000471341 00000 n +0000471458 00000 n +0000471571 00000 n +0000471671 00000 n +0000471826 00000 n +0000471923 00000 n +0000472036 00000 n +0000472153 00000 n +0000472266 00000 n +0000472366 00000 n +0000472521 00000 n +0000472618 00000 n +0000472733 00000 n +0000472846 00000 n +0000472963 00000 n +0000473076 00000 n +0000473176 00000 n +0000473334 00000 n +0000473431 00000 n +0000473546 00000 n +0000473663 00000 n +0000473776 00000 n +0000473876 00000 n +0000474037 00000 n +0000474134 00000 n +0000474249 00000 n +0000474362 00000 n +0000474479 00000 n +0000474592 00000 n +0000474692 00000 n +0000474848 00000 n +0000474945 00000 n +0000475060 00000 n +0000475173 00000 n +0000475290 00000 n +0000475403 00000 n +0000475503 00000 n +0000475659 00000 n +0000475756 00000 n +0000475871 00000 n +0000475988 00000 n +0000476101 00000 n +0000476201 00000 n +0000476361 00000 n +0000476458 00000 n +0000476573 00000 n +0000476686 00000 n +0000476803 00000 n +0000476916 00000 n +0000477016 00000 n +0000477171 00000 n +0000477268 00000 n +0000477383 00000 n +0000477496 00000 n +0000477613 00000 n +0000477726 00000 n +0000477826 00000 n +0000477983 00000 n +0000478080 00000 n +0000478195 00000 n +0000478308 00000 n +0000478425 00000 n +0000478538 00000 n +0000478638 00000 n +0000478799 00000 n +0000478896 00000 n +0000479011 00000 n +0000479124 00000 n +0000479241 00000 n +0000479354 00000 n +0000479454 00000 n +0000479621 00000 n +0000479718 00000 n +0000479833 00000 n +0000479946 00000 n +0000480063 00000 n +0000480176 00000 n +0000480276 00000 n +0000480437 00000 n +0000480534 00000 n +0000480649 00000 n +0000480762 00000 n +0000480879 00000 n +0000480992 00000 n +0000481092 00000 n +0000481251 00000 n +0000481348 00000 n +0000481463 00000 n +0000481576 00000 n +0000481693 00000 n +0000481806 00000 n +0000481906 00000 n +0000482069 00000 n +0000482166 00000 n +0000482281 00000 n +0000482398 00000 n +0000482511 00000 n +0000482611 00000 n +0000482772 00000 n +0000482869 00000 n +0000482984 00000 n +0000483097 00000 n +0000483214 00000 n +0000483327 00000 n +0000483427 00000 n +0000483582 00000 n +0000483679 00000 n +0000483794 00000 n +0000483907 00000 n +0000484024 00000 n +0000484137 00000 n +0000484237 00000 n +0000484394 00000 n +0000484491 00000 n +0000484606 00000 n +0000484719 00000 n +0000484836 00000 n +0000484949 00000 n +0000485049 00000 n +0000485208 00000 n +0000485305 00000 n +0000485420 00000 n +0000485533 00000 n +0000485650 00000 n +0000485763 00000 n +0000485863 00000 n +0000486024 00000 n +0000486121 00000 n +0000486236 00000 n +0000486349 00000 n +0000486466 00000 n +0000486579 00000 n +0000486679 00000 n +0000486838 00000 n +0000486935 00000 n +0000487050 00000 n +0000487163 00000 n +0000487280 00000 n +0000487393 00000 n +0000487493 00000 n +0000487639 00000 n +0000487736 00000 n +0000487851 00000 n +0000487964 00000 n +0000488081 00000 n +0000488194 00000 n +0000488294 00000 n +trailer +<<2fe306598ce03bf37f727cf96ec46f9b>]>> +startxref +488528 +%%EOF diff --git a/doc/spm.shtml b/doc/spm.shtml new file mode 100644 index 0000000000..5b5a88d3f1 --- /dev/null +++ b/doc/spm.shtml @@ -0,0 +1,8309 @@ + + + + + + CUPS Software Programmers Manual + + + +

Preface

+ +

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

Document Overview

+ +

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

+ +

Notation Conventions

+ +

Various font and syntax conventions are used in this guide. Examples and +their meanings and uses are explained below: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Example   Description
 
lpstat
+ lpstat(1)
   The names of commands; the first mention of a command or + function in a chapter is followed by a manual page section + number.
 
/var
+ /usr/share/cups/data/testprint.ps
   File and directory names.
 
Request ID is Printer-123   Screen output.
 
lp -d printer filename ENTER   Literal user input; special keys like ENTER are + in ALL CAPS.
 
12.3   Numbers in the text are written using the period (.) to indicate + the decimal point.
+ + +

Abbreviations

+ +The following abbreviations are used throughout this manual: + +
    +
    + +
    kb +
    Kilobytes, or 1024 bytes
      + +
    Mb +
    Megabytes, or 1048576 bytes
      + +
    Gb +
    Gigabytes, or 1073741824 bytes
      + +
    +
+ +

Other References

+ +
    +
    + +
    CUPS Software Administrators Manual + +
    An administration guide for the CUPS software.
      + +
    CUPS Software Users Manual + +
    An end-user guide for using the CUPS software.
      + +
    +
+ + + + + +

2 - The CUPS API

+ +

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

The CUPS API Library

+ +

The CUPS library provides a whole collection of interfaces needed to +support the internal needs of the CUPS software as well as the needs of +applications, filters, printer drivers, and backends. + +

Unlike the rest of CUPS, the CUPS API library is provided under the +GNU Library General Public License. This means that you can use the +CUPS API library in both proprietary and open-source programs. + +

Programs that use the CUPS API library typically will include the +<cups/cups.h> header file: + +

    +#include <cups/cups.h>
    +
    +...
    +
    +jobid = cupsPrintFile("myprinter", "filename.ps", "title",
    +                      num_options, options);
    +
+ +

Use the -lcups compiler option when linking to the CUPS API +library: + +

    +cc -o program program.c -lcups ENTER
    +
+ +

Additional options and libraries may be required depending on the +operating system and the location of the CUPS API library. + +

Detecting the CUPS API Library in GNU Autoconf

+ +

GNU autoconf is a popular configuration tool used by many programs. +Add the following lines to your configure.in file to check +for the CUPS API library in your configuration script: + +

    +AC_CHECK_LIB(socket,socket,
    +if test "$uname" != "IRIX"; then
    +	LIBS="-lsocket $LIBS"
    +else
    +	echo "Not using -lsocket since you are running IRIX."
    +fi)
    +AC_CHECK_LIB(nsl,gethostbyaddr,
    +if test "$uname" != "IRIX"; then
    +	LIBS="-lnsl $LIBS"
    +else
    +	echo "Not using -lnsl since you are running IRIX."
    +fi)
    +
    +AC_CHECK_LIB(cups,httpConnect)
    +
+ +

Printing Services

+ +

The CUPS API library provides some basic printing services for applications +that need to print files. + +

Include Files

+ +

The include file used by all of these functions is +<cups/cups.h>: + +

    +#include <cups/cups.h>
    +
+ +

Printing a File

+ +

The CUPS API provides two functions for printing files. The first is +cupsPrintFile which prints a single named file: + +

    +#include <cups/cups.h>
    +
    +...
    +
    +int jobid;
    +
    +...
    +
    +jobid = cupsPrintFile("name", "filename", "title", 0, NULL);
    +
+ +

The name string is the name of the printer or class to +print to. The filename string is the name of the file to +print. The title string is the name of the print job, e.g. +"Acme Word Document". + +

The return value is a unique ID number for the print job or 0 if there +was an error. + +

Printing Multiple Files

+ +

The second printing function is cupsPrintFiles: + +

    +#include <cups/cups.h>
    +
    +...
    +
    +int        jobid;
    +int        num_files;
    +const char *files[100];
    +...
    +
    +jobid = cupsPrintFiles("name", num_files, files, "title", 0, NULL);
    +
+ +

Instead of passing a filename string as with cupsPrintFile(), +you pass a file count (num_files) and filename pointer array +(files) for each file that you want to print. + +

As with cupsPrintFile(), the return value is a unique ID for +the print job. + +

Cancelling Jobs

+ +

The cupsCancelJob() function cancels a queued print job: + +

    +#include <cups/cups.h>
    +
    +...
    +
    +int jobid;
    +int status;
    +...
    +
    +status = cupsCancelJob("name", jobid);
    +
+ +

The name string specifies the destination and is used +to determine the server to send the request to. The jobid +value is the integer returned from a previous cupsPrintFile() +or cupsPrintFiles() call. + +

cupsCancelJob() returns 1 if the job was +successfully cancelled and 0 if there was an error. + +

Getting the Available Printers and Classes

+ +

The cupsGetDests() function can be used to get a list +of the available printers, classes, and instances that a user has defined: + +

    +#include <cups/cups.h>
    +
    +...
    +
    +int         num_dests;
    +cups_dest_t *dests;
    +
    +...
    +
    +num_dests = cupsGetDests(&dests);
    +
+ +

Each destination is stored in a cups_dest_t structure which +defines the printer or class name, the instance name (if any), if it is the +default destination, and the default options the user has defined for the +destination: + +

    +typedef struct               /**** Destination ****/
    +{
    +  char          *name,       /* Printer or class name */
    +                *instance;   /* Local instance name or NULL */
    +  int           is_default;  /* Is this printer the default? */
    +  int           num_options; /* Number of options */
    +  cups_option_t *options;    /* Options */
    +} cups_dest_t;
    +
+ +

The destinations are sorted by name and instance for your convenience. +Once you have the list of available destinations, you can lookup a specific +destination using the cupsGetDest() function: + +

    +#include <cups/cups.h>
    +
    +...
    +
    +int         num_dests;
    +cups_dest_t *dests;
    +cups_dest_t *mydest;
    +
    +...
    +
    +mydest = cupsGetDest("name", "instance", num_dests, dests);
    +
+ +

The name string is the printer or class name. You can pass +a value of NULL to get the default destination. + +

The instance string is the user-defined instance name. Pass +NULL to select the default instance, e.g. "name" instead of +"name/instance". + +

Printing with Options

+ +

All of the previous printing examples have passed 0 and +NULL for the last two arguments to the cupsPrintFile() +and cupsPrintFiles() functions. These last two arguments are the +number of options and a pointer to the option array: + +

    +int cupsPrintFile(const char *name, const char *filename, const char *title,
    +                  int num_options, cups_option_t *options);
    +int cupsPrintFiles(const char *name, int num_files, const char **files,
    +                   const char *title, int num_options,
    +		   cups_option_t *options);
    +
+ +

The cups_option_t structure holds each option and its value. +These are converted as needed and passed to the CUPS server when printing a +file. + +

The simplest way of handling options is to use the num_options +and options members of the cups_dest_t +structure described earlier: + +

    +#include <cups/cups.h>
    +
    +...
    +
    +int         jobid;
    +int         num_dests;
    +cups_dest_t *dests;
    +cups_dest_t *mydest;
    +
    +...
    +
    +mydest = cupsGetDest("name", "instance", num_dests, dests);
    +
    +jobid  = cupsPrintFile(mydest->name, "filename", "title",
    +                       mydest->num_options, mydest->options);
    +
+ +

This effectively uses the options a user has previous selected without a +lot of code. + +

Setting Printer Options

+ +

Options can also be set by your program using the cupsAddOption() +function: + +

    +#include <cups/cups.h>
    +
    +...
    +
    +int           num_options;
    +cups_option_t *options;
    +
    +...
    +
    +num_options = 0;
    +options     = NULL;
    +
    +...
    +
    +num_options = cupsAddOption("name", "value", num_options, &options);
    +num_options = cupsAddOption("name", "value", num_options, &options);
    +num_options = cupsAddOption("name", "value", num_options, &options);
    +num_options = cupsAddOption("name", "value", num_options, &options);
    +
+ +

The name string is the name of the option, and the +value string is the value for that option. + +

Each call to cupsAddOption() returns the new number of +options. Since adding two options with the same name overwrites the +first value with the second, do not assume that calling +cupsAddOptions() 20 times will result in 20 options. + +

Call cupsFreeOptions once you are done using the options: + +

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

Getting Errors

+ +

If any of the CUPS API printing functions returns an error, the reason for +that error can be found by calling cupsLastError() and +cupsErrorString(). cupsLastError() returns the +last IPP error code that was encountered. cupsErrorString() +converts the error code to a localized message string suitable for +presentation to the user: + +

    +#include <cups/cups.h>
    +
    +...
    +
    +int jobid;
    +
    +...
    +
    +if (jobid == 0)
    +  puts(cupsErrorString(cupsLastError()));
    +
+ +

Passwords and Authentication

+ +

CUPS supports authentication of any request, including +submission of print jobs. The default mechanism for getting the +username and password is to use the login user and a password +from the console. + +

To support other types of applications, in particular +Graphical User Interfaces ("GUIs"), the CUPS API provides +functions to set the default username and to register a callback +function that returns a password string. + +

The cupsSetPasswordCB() +function is used to set a password callback in your program. Only one +function can be used at any time. + +

The cupsSetUser() function sets +the current username for authentication. This function can be called by +your password callback function to change the current username as needed. + +

The following example shows a simple password callback that gets a +username and password from the user: + +

    +#include <cups/cups.h>
    +
    +const char *
    +my_password_cb(const char *prompt)
    +{
    +  char	user[65];
    +
    +
    +  puts(prompt);
    +
    + /* Get a username from the user */
    +  printf("Username: ");
    +  if (fgets(user, sizeof(user), stdin) == NULL)
    +    return (NULL);
    +
    + /* Strip the newline from the string and set the user */
    +  user[strlen(user) - 1] = '\0';
    +
    +  cupsSetUser(user);
    +
    + /* Use getpass() to ask for the password... */
    +  return (getpass("Password: "));
    +}
    +
    +...
    +
    +cupsSetPasswordCB(my_password_cb);
    +
+ +

Similarly, a GUI interface could display the prompt string in a +window with input fields for the username and password. The username +should probably default to the value of +cupsUser() to make things easier +on the user. + +

PPD Services

+ +

CUPS includes functions to access and manipulate PostScript Printer +Description ("PPD") files that are used with the printer drivers in CUPS. + +

Each PPD file enumerates the available features provided by a +printer, including conflict information for specific options (e.g. +can't duplex output on envelopes.) + +

Include Files

+ +

Include the <cups/ppd.h> header file to use the PPD +functions: + +

    +#include <cups/ppd.h>
    +
+ +

This header file is also included by the +<cups/cups.h> header file. + +

Getting a PPD File for a Printer

+ +

The cupsGetPPD() function retrieves the PPD file for the +named printer or class: + +

    +#include <cups/cups.h>
    +
    +...
    +
    +const char *filename;
    +
    +filename = cupsGetPPD("name");
    +
+ +

The name string is the name of the printer or class, including +the remote server name as appropriate (e.g. "printer@server".) + +

The return value is a pointer to a filename in static storage; this value +is overwritten with each call to cupsGetPPD(). If the printer +or class does not exist, a NULL pointer will be returned. + +

Loading a PPD File

+ +

The ppdOpenFile() function "opens" a PPD file and loads it +into memory: + +

    +#include <cups/ppd.h>
    +
    +...
    +
    +ppd_file_t *ppd;
    +
    +ppd = ppdOpenFile("filename");
    +
+ +

The filename string is the name of the file to load, such as +the value returned by the cupsGetPPD() function. + +

The return value is a pointer to a structure describing the contents of the +PPD file or NULL if the PPD file could not be read. + +

Freeing PPD File Information

+ +

Once you are done using a PPD file, call the ppdClose() function +to free all memory that has been used: + +

    +#include <cups/ppd.h>
    +
    +...
    +
    +ppd_file_t *ppd;
    +
    +...
    +
    +ppdClose(ppd);
    +
+ +

The PPD File Structure

+ +

Each PPD file contains a number of capability attributes, printer options, +and conflict definitions. The page size options also include the physical +margins for the printer and the minimum and maximum sizes for the printer. +All of this information is stored in the ppd_file_t structure. + +

Capabilities

+ +

Each PPD file contains a number of informational attributes that +describe the capabilities of the printer. These are provided in the +ppd_file_t structure in the following members: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MemberTypeDescription
accurate_screensint1 = supports accurate screens
color_deviceint1 = color device
colorspaceppd_cs_tDefault colorspace: PPD_CS_CMYK, PPD_CS_CMY, PPD_CS_GRAY, + PPD_CS_RGB, PPD_CS_RGBK, PPD_CS_N
contone_onlyint1 = printer is continuous tone only
num_emulations
+ emulations
int
+ ppd_emul_t *
Emulations supported by the printer
flip_duplexint1 = need to flip odd pages when duplexing
num_fonts
+ fonts
int
+ char **
The fonts available on the printer.
jcl_begin
+ jcl_ps
+ jcl_end
char *Job Control Language commands for PostScript output
landscapeintLandscape orientation, -90 or 90 degrees
lang_encodingchar *The character used for the option strings
lang_versionchar *The language used for the options strings (English, French, etc.)
language_levelintPostScript language level, 1 to 3
manual_copiesint1 = Copies are done manually
model_numberintDriver-specific model number.
patcheschar *Patch commands to send to the printer
manufacturerchar *The Manufacturer attribute from the PPD file, if any
modelnamechar *The ModelName attribute from the PPD file
nicknamechar *The NickName attribute from the PPD file, if any
productchar *The Product attribute from the PPD file, if any
shortnicknamechar *The ShortNickName attribute from the PPD file, if any
throughputintNumber of pages per minute
ttrasterizerchar *The TruType font rasterizer (Type42)
variable_sizesint1 = supports variable sizes
+ +

Options and Groups

+ +

PPD files support multiple options, which are stored in +ppd_option_t and ppd_choice_t structures by +the PPD functions. + +

Each option in turn is associated with a group +stored in the ppd_group_t structure. Groups can be +specified in the PPD file; if an option is not associated with a group +then it is put in a "General" or "Extra" group depending on the option. + +

Groups can also have sub-groups; CUPS currently limits the depth of +sub-groups to 1 level to reduce programming complexity. + +

Conflicts

+ +

PPD files support specification of conflict conditions between +different options. Conflicts are stored in ppd_conflict_t +structures which specify the options that conflict with each other. + +

Page Sizes

+ +

PPD files specify all of the available pages sizes and the physical +margins associated with them. These sizes are stored in +ppd_size_t structures and are available in the +num_sizes and sizes members of the +ppd_file_t structure. You can lookup a particular page size +with the ppdPageWidth(), ppdPageLength(), and +ppdPageSize() functions: + +

    +#include <cups/ppd.h>
    +
    +...
    +
    +ppd_file_t *ppd;
    +ppd_size_t *size;
    +float      width;
    +float      length;
    +
    +...
    +
    +size   = ppdPageSize(ppd, "size");
    +width  = ppdPageWidth(ppd, "size");
    +length = ppdPageLength(ppd, "size");
    +
+ +

The size string is the named page size option. The +width and length are in points; there are 72 points per inch. The +ppd_size_t structure contains the width, length, and +margin information: + +

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

Custom Page Sizes

+ +

Besides the standard page sizes listed in a PPD file, some printers +support variable or custom page sizes. If variables_sizes +is non-zero, the custom_min, custom_max, and +custom_margins members of the ppd_file_t +structure define the limits of the variable sizes. + +

To get the resulting media size, use a page size string of +Custom.widthxlength, where width +and length are integer values in points: + +

    +Custom.612x792   [8.5 inches wide, 11 inches long]
    +Custom.1224x792  [17 inches wide, 11 inches long]
    +
+ +

Marking Options

+ +

Before marking any user-defined options, call the ppdMarkDefaults() +function to mark the default options from the PPD file: + +

    +#include <cups/ppd.h>
    +
    +...
    +
    +ppd_file_t *ppd;
    +
    +...
    +
    +ppdMarkDefaults(ppd);
    +
+ +

Then call the ppdMarkOption() function to mark individual +options: + +

    +#include <cups/ppd.h>
    +
    +...
    +
    +ppd_file_t *ppd;
    +int        conflicts;
    +
    +...
    +
    +conflicts = ppdMarkOption(ppd, "name", "value");
    +
+ +

The name and value strings choose a +particular option and choice, respectively. The return value is 0 +if there are not conflicts created by the selection. + +

CUPS also provides a convenience function for marking all options +in the cups_option_t structure: + +

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

The cupsMarkOptions() function also handles mapping the +IPP job template attributes to PPD options. The return value is the number +of conflicts present. + +

Checking for Conflicts

+ +

The ppdMarkOption() and cupsMarkOptions() +functions return the number of conflicts with the currently marked options. + +

Call the ppdConflicts() function to get the number of +conflicts after you have marked all of the options: + +

    +#include <cups/cups.h>
    +
    +...
    +
    +ppd_file_t *ppd;
    +int        conflicts;
    +
    +...
    +
    +conflicts = ppdConflicts(ppd);
    +
+ +

The return value is the number of conflicting options, or 0 if there +are no conflicts. + + +

3 - Writing Filters

+ +

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

Overview

+ +

File filters are programs that convert from one or more MIME types to +another type. Filters use a common command-line and environment interface +that allows them to be joined as needed to print files to any type of +printer. + +

Security Considerations

+ +

Filters are normally run as a non-priviledged user, so the major +security consideration is resource utilization - filters should not +depend on unlimited amounts of memory and disk space. + +

Users and Groups

+ +

The default CUPS configuration runs filters as user "lp" and group "other". + +

Temporary Files

+ +

Temporary files should be created in the directory specified by the +"TMPDIR" environment variable. The +cupsTempFile() function can be +used to safely choose temporary files in this directory. + +

Sending Messages to the User

+ +

The CUPS scheduler collects messages sent to the standard error file +by the filter. These messages are relayed to the user based upon the +scheduler LogLevel directive. + +

The type of message is determined by an initial prefix sent on each +line: + +

    + +
  • DEBUG: - a debug message + +
  • INFO: - an informational message + +
  • WARNING: - a warning message + +
  • ERROR: - an error message + +
  • PAGE: - a page accounting message + +
+ +

If the line of text does not begin with any of the above prefixes, it +is treated as a debug message. Text following the prefix is copied to the +printer-state-message attribute for the printer, and also +added to the error_log unless it is an informational or page +accounting message. + +

Page Accounting

+ +

Page accounting messages are used to inform the server when one or more +pages are printed. Each line has the form: + +

    +PAGE: page-number copy-count
    +
+ +

The page-number field is the current page number, starting at 1. +The copy-count field specifies the number of copies of that page +that was produced. + +

Page account messages are added to the page_log file and +cause the job-sheets-completed attribute to be updated for +the job. + +

Command-Line Arguments

+ +

Every filter accepts exactly 6 or 7 command-line arguments: + +

    +printer job user title copies options [filename]
    +
    + +
  • printer - The name of the printer queue (normally + this is the name of the program being run) + +
  • job - The numeric job ID for the job being + printed + +
  • user - The string from the + originating-user-name attribute + +
  • title - The string from the + job-name attribute + +
  • copies - The numeric value from the + number-copies attribute + +
  • options - String representations of the + job template attributes, separated by spaces. Boolean attributes + are provided as "name" for true values and "noname" for false + values. All other attributes are provided as "name=value" for + single-valued attributes and "name=value1,value2,...,valueN" for + set attributes + +
  • filename - The request file + +
+ +

The filename argument is only provided to the first filter in the +chain; all filters must be prepared to read the print file from +the standard input if the filename argument is omitted. + +

Copy Generation

+ +

The copies argument specifies the number of copies to produce +of the input file. In general, you should only generate copies if the +filename argument is supplied. The only exception to this are +filters that produce device-independent PostScript output (without any +printer commands from the printer's PPD file), since the PostScript +filter pstops is responsible for copy generation. + +

Environment Variables

+ +

Every filter receives a fixed set of environment variables that can +be used by the filter: + +

    + +
  • CHARSET - The character set used by the client for + this print file + +
  • CONTENT_TYPE - The original document type, such as + "application/postscript" + +
  • CUPS_DATADIR - The location of CUPS data files + +
  • CUPS_SERVERROOT - The location of CUPS configuration + files + +
  • DEVICE_URI - The output device URI + +
  • LANG - The language used by the client for + this print file + +
  • PATH - The execution path exported to the filter + +
  • PPD - The full filename of the printer's PPD file + +
  • PRINTER - The name of the printer queue + +
  • RIP_CACHE - The maximum amount of memory each filter + should use + +
  • SOFTWARE - The name of the CUPS software, typically + "CUPS/1.1" + +
  • TZ - The local timezone + +
  • USER - The name of the current user + +
+ +

Dissecting the HP-GL/2 Filter

+ +

The HP-GL/2 filter (hpgltops) provided with CUPS is a +complex program that converts HP-GL/2 files into device-independent PostScript +output. Since it produces device-independent PostScript output, it does not +need to handle copy generation or writing printer options from the printer's +PPD file. + +

Initializing the Filter

+ +

The first task of any filter is to ensure that the correct number of +command-line arguments are present: + +

    +if (argc < 6 || argc > 7)
    +{
    +  fputs("ERROR: hpgltops job-id user title copies options [file]\n", stderr);
    +  return (1);
    +}
    +
+ +

After this you open the print file or read from the standard input +as needed: + +

    +FILE *fp;
    +
    +/*
    + * 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);
    +  }
    +}
    +
+ +

Once the print file has been opened, options can be processed using +the cupsParseOptions() and +cupsGetOption() functions: + +

    +int           num_options;
    +cups_option_t *options;
    +const char    *val;
    +
    +/*
    + * Process command-line options and write the prolog...
    + */
    +
    +options     = NULL;
    +num_options = cupsParseOptions(argv[5], 0, &options);
    +
    +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)atoi(val) * 0.001f;
    +
+ +

After the options have been processed, the filter writes PostScript code +to the standard output based on the print file, closes the print file (as +needed), and returns 0 to the scheduler. + +

PostScript Output

+ +

Filters that produce PostScript output must generate output conforming +to the Adobe Document Structuring Conventions, 3.0. In general this means +the beginning of each file must begin with: + +

    +%!PS-Adobe-3.0
    +%%BoundingBox: left bottom right top
    +%%Pages: (atend)
    +%%EndComments
    +
+ +

The left, bottom, right, and top values +are integers in points from the lower-lefthand corner of the page. + +

Pages must be surrounded by: + +

    +%%Page: number number
    +gsave
    +...
    +grestore
    +showpage
    +
+ +

And the end of each file must contain: + +

    +%%Trailer
    +%%Pages: number-pages
    +%%EOF
    +
+ +

These comments allow the PostScript filter to correctly perform page +accounting, copy generation, N-up printing, and so forth. + +

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

+ +

Raster printers utilitize PPD files that specify one or more +device-specific filters that handle converting print files for the +printer. The simplest raster printer drivers provide a single filter +that converts CUPS raster data to the printer's native format. + +

CUPS Raster Data

+ +

CUPS raster data (application/vnd.cups-raster) consists of +a stream of raster page descriptions produced by one of the RIP filters, +such as pstoraster or imagetoraster. + +

Each page of data begins with a page dictionary structure called +cups_raster_header_t. This +structure contains the colorspace, bits per color, media size, media type, +hardware resolution, and so forth. + +

After the page dictionary comes the page data which is a full-resolution, +uncompressed bitmap representing the page in the printer's output colorspace. + +

Page Accounting

+ +

Printer drivers must handle all page accounting. This means they must +send "PAGE:" messages to the standard error file for each page (and in many +cases, copy) sent to the printer. + +

Color Management

+ +

Printer drivers can implement their color management via the +cupsColorProfile attributes in the PPD file or internally +in the driver from a device-independent colorspace. In general, color +management performed by the RIP filters is more efficient than that +performed inside printer drivers. + +

For example, the pstoraster filter often only has to +perform a color conversion once each time the color is used for +multiple output pixels, while the raster filter must convert every +pixel on the page. + +

Device and Bitmap Variables

+ +

Besides the standard PostScript page device dictionary variables defined +in the Adobe PostScript Level 3 reference manual, the CUPS filters support +additional variables that are passed in the page device dictionary header for +the page and in some cases control the type of raster data that is generated: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
VariableTypeDescription
cupsWidthread-only integerWidth of bitmap in pixels
cupsHeightread-only integer Height of bitmap in pixels
cupsMediaTyperead-write integerDevice-specific media type code
cupsBitsPerColorread-write integerNumber of bits per color; 1, 2, 4, and 8 are currently + supported
cupsBitsPerPixelread-only integer Number of bits per pixel; 1 to 32
cupsBytesPerLineread-only integerNumber of bytes per line of raster graphics
cupsColorOrderread-write enumThe order of color values in the bitmap: +
    +
  • CUPS_ORDER_CHUNKED - CMYK CMYK CMYK +
  • CUPS_ORDER_BANDED - CCC MMM YYY KKK +
  • CUPS_ORDER_PLANAR - CCC ... MMM ... YYY ... KKK ... +
+
cupsColorSpaceread-write enumThe colorspace of the bitmap: +
    +
  • CUPS_CSPACE_W - White (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 - Metallic yellow (gold), metallic magenta, + metallic cyan, black +
  • CUPS_CSPACE_GMCS - Metallic yellow (gold), metallic magenta, + metallic cyan, metallic grey (silver) +
  • CUPS_CSPACE_WHITE - White pigment (black as white pigment) +
  • CUPS_CSPACE_GOLD - Gold foil (black as gold foil) +
  • CUPS_CSPACE_SILVER - Silver foil (black as silver foil) +
+
cupsCompressionread-write integerDevice-specific compression type code
cupsRowCountread-write integerDevice-specific row count value
cupsRowFeedread-write integerDevice-specific row feed value
cupsRowStepread-write integerDevice-specific row step value
+ +

Bitmaps with a colorspace of CUPS_CSPACE_KCMYcm and more than 1 bit per +color are transmitted to the raster driver in KCMY colorspace; the driver +is responsible for producing the correct separation of normal and light +cyan and magenta inks. + +

Dissecting the HP-PCL Driver

+ +

The HP-PCL driver provided with CUPS (rastertohp) converts +bitmap data from the raster filters into HP-PCL commands for most +PCL-compatible printers. The actual format of the raster data is controlled +by the PPD file being used - deskjet.ppd or laserjet.ppd. + +

PPD Files

+ +

PPD files play an important part of all raster printer drivers. Options +defined in the PPD file contain PostScript commands that control the raster +data that is sent to the printer driver. + +

A typical CUPS printer driver will include ColorModel, +InputSlot, PageSize, PageRegion, +and Resolution options. Each option is shown using the +standard PPD format: + +

    +*OpenUI *PageSize/Media Size: PickOne
    +*OrderDependency: 10 AnySetup *PageSize
    +*DefaultPageSize: Letter
    +*PageSize Letter/US Letter: "<<
    +/PageSize [612 792]
    +/ImagingBBox null
    +>> setpagedevice"
    +*End
    +*PageSize Legal/US Legal: "<<
    +/PageSize [612 1008]
    +/ImagingBBox null
    +>> setpagedevice"
    +*End
    +*PageSize A4/A4: "<<
    +/PageSize [595 842]
    +/ImagingBBox null
    +>> setpagedevice"
    +*End
    +*CloseUI: *PageSize
    +
+ +

The OpenUI keyword specifies the new option. The first +name is the option with an asterisk (*) in front of it. The first name is +usually followed by a slash (/) and a human-readable version of the +option name. + +

Every option must have a default value, specified using the +DefaultOption keyword. + +

Each option begins with the option name followed by the computer and +human-readable values. The PostScript commands follow these inside double +quotes. PostScript commands can be provided on a single line: + +

    +*PageSize A4/A4: "<</PageSize[595 842]/ImagingBBox null>> setpagedevice"
    +
+ +

or broken down on separate lines using the End keyword to +terminate them: + +

    +*PageSize A4/A4: "<<
    +/PageSize [595 842]
    +/ImagingBBox null
    +>> setpagedevice"
    +*End
    +
+ +

The choice of the two formats is usually esthetic. However, each line in +a PPD file must not exceed 255 characters, so if your PostScript commands are +long you may need to break them up on separate lines. + +

Reading Raster Data

+ +

As with any filter, your printer driver should handle raster data from +a filename specified on the command-line or from the standard input. The +cupsRasterOpen() function opens +a raster stream for printing: + +

    +int           fd;   /* File descriptor */
    +cups_raster_t *ras; /* Raster stream for printing */
    +
    +
    +/*
    + * 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);
    +
+ +

Once you have opened the raster stream you just need to read each +page and print it: + +

    +cups_raster_header_t header;
    +int                  y;
    +unsigned char        data[8192];
    +
    +while (cupsRasterReadHeader(ras, &header))
    +{
    +  ... initialize the printer ...
    +  for (y = header.cupsHeight; y > 0; y ++)
    +  {
    +    cupsRasterReadPixels(ras, data, header.cupsBytesPerLine);
    +    ... send raster line to printer ...
    +  }
    +}
    +
+ +

After you have processed all pages, close the raster stream and +return: + +

    +cupsRasterClose(ras);
    +
    +return (0);
    +
+ +

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

+ +

Backends are special filters that communicate with printers directly. +They are treated slightly differently than filters, however, and have some +unique requirements. + +

Security Considerations

+ +

Backends are run as the root user, so special care must be taken to +avoid potential security violations. In particular, remember that a backend +will be able to manipulate disk files, devices, and other resources that +potentially could damage a system or printer. + +

Command-Line Arguments

+ +

Besides the standard filter arguments, backends are also run with no +arguments to get a list of available devices. This discovery process is +described later in this chapter. + +

Copy Generation

+ +

Like filters, backends should send multiple copies of the print file only +if a filename is supplied on the command-line. Otherwise the backend should +assume that the upstream filter has already added the necessary commands or +data to produce the multiple copies. + +

Page Accounting

+ +

Backend filters generally do not do page accounting, however they should +at a minimum produce a single page message for each copy that is produced +when a filename is present on the command-line. This is because the user +selected "raw" printing and no other accounting information is possible. + +

Exclusive Access

+ +

Backends that talk to local character or block devices should open the +device file in exclusive mode (O_EXCL) to cooperate with other +printers defined for the same device. + +

Retries

+ +

All backends must retry connections to the device. This +includes backends that talk to local character or block devices, as the +user may define more than one printer queue pointing at the same +physical device. + +

To prevent excess CPU utilitization, the backend should go to sleep +for an amount of time between retries; the CUPS-supplied backends retry +once every 30 seconds. + +

Dissecting the Serial Port Backend

+ +

The serial port backend provides support for serial printers. Since +it does everything a good backend needs to do, it provides an excellent +example of what to do. + +

Supporting Device Discovery

+ +

As previously noted, backends are special filter programs that talk +to printer devices. Another task a backend must perform is to list the +available devices it supports. The backend lists the available devices +when no additioanl arguments are supplied on the command-line (i.e. +just the command name...) + +

The serial backend lists devices by looking at serial port files in the +/dev directory, by consulting a hardware inventory (IRIX), and +in some cases by trying to open the ports to see if they actually exist. + +

Once it finds a serial port it writes a single line for each port to +the standard error file. Each line looks like this: + +

    +serial serial:/dev/ttyS0?baud=115200 "Unknown" "Serial Port 1"
    +
+ +

The first word "serial" is the device class; this identifies the +class of device which can be used to categorize it in user interfaces. CUPS +currently recognizes the following classes: + +

    + +
  • "file" - a disk file. + +
  • "direct" - a parallel or fixed-rate serial data port, + currently used for Centronics, IEEE-1284, and USB printer + ports. + +
  • "serial" - a variable-rate serial port. + +
  • "network" - a network connection, typically via AppSocket, + HTTP, IPP, LPD, or SMB/CIFS protocols. + +
+ +

After the device class is the device URI, in this case +"serial:/dev/ttyS0?baud=115200". This is the URI that should be used by +the user to select this port. For serial ports, the "baud=115200" +specifies the maximum baud rate supported by the port - the actual +value will vary based on the speed the user selects for the printer. + +

The last two strings are the model and description for the port. The +"Unknown" string means that the printer model is unknown - some devices +are able to provide a make and model such as "HP DeskJet" that allows +users and software to choose an appropriate printer driver more easily. +Both the model and description must be enclosed inside double quotes. + +

Opening the Serial Port

+ +

As noted previously, all backends should open device files in exclusive +mode, and retry as needed until the port is available. The serial port does +this using a do-while loop: + +

    +do
    +{
    +  if ((fd = open(resource, O_WRONLY | O_NOCTTY | O_EXCL)) == -1)
    +  {
    +    if (errno == EBUSY)
    +    {
    +      fputs("INFO: Serial port busy; will retry in 30 seconds...\n", stderr);
    +      sleep(30);
    +    }
    +    else
    +    {
    +      perror("ERROR: Unable to open serial port device file");
    +      return (1);
    +    }
    +  }
    +}
    +while (fd < 0);
    +
+ +

If the port is busy or in use by another process, the backend will +go to sleep for 30 seconds and try again. If another error is detected +a message is sent to the user and the backend aborts the print job +until the problem can be corrected. + +

Writing Data to the Port

+ +

Network and character devices pose an interesting problem when writing +data to the port - they may not be able to write all of the bytes in your +buffer before returning. To work around this problem you must loop until +all bytes have been written: + +

    +while (nbytes > 0)
    +{
    +  if ((wbytes = write(fd, bufptr, nbytes)) < 0)
    +    if (errno == ENOTTY)
    +      wbytes = write(fd, bufptr, nbytes);
    +
    +  if (wbytes < 0)
    +  {
    +    perror("ERROR: Unable to send print file to printer");
    +    break;
    +  }
    +
    +  nbytes -= wbytes;
    +  bufptr += wbytes;
    +}
    +
+ +

The check for the ENOTTY error is needed on some platforms +to clear an error from a previous ioctl() call. + +

Finishing Up

+ +

Once you have sent the print file, return 0 if the file printed +successfully or 1 if it did not. This will allow the scheduler to stop +the print job if there is a device error, preserving the print job for +later printing once the problem has been corrected. + +

A - Software License Agreement

+ + + + +

B - Constants

+ +

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

CUPS Constants

+ +

Version Number

+ +

The CUPS_VERSION constant is a floating-point number +representing the API version number. The current version number is +1.0100 which represents CUPS version 1.1.0. + +

Printer Capabilities

+ +

The CUPS_PRINTER constants represent capability bits for +printers and classes: + +

    + +
  • CUPS_PRINTER_LOCAL - Is a local printer or class. + +
  • CUPS_PRINTER_REMOTE - Is a remote printer or class. + +
  • CUPS_PRINTER_CLASS - Is a class. + +
  • CUPS_PRINTER_BW - Printer prints in black and white. + +
  • CUPS_PRINTER_COLOR - Printer prints in color. + +
  • CUPS_PRINTER_DUPLEX - Printer can print double-sided. + +
  • CUPS_PRINTER_STAPLE - Printer can staple output. + +
  • CUPS_PRINTER_COPIES - Printer can produce multiple + copies on its own. + +
  • CUPS_PRINTER_COLLATE - Printer can collate copies. + +
  • CUPS_PRINTER_PUNCH - Printer can punch holes in output. + +
  • CUPS_PRINTER_COVER - Printer can put covers on output. + +
  • CUPS_PRINTER_BIND - Printer can bind output. + +
  • CUPS_PRINTER_SORT - Printer can sort output. + +
  • CUPS_PRINTER_SMALL - Printer can print on media up + to 9x14 inches. + +
  • CUPS_PRINTER_MEDIUM - Printer can print on media + from 9x14 to 18x24 inches. + +
  • CUPS_PRINTER_LARGE - Printer can print on media + larger than 18x24 inches. + +
  • CUPS_PRINTER_VARIABLE - Printer can print on + variable or custom media sizes. + +
  • CUPS_PRINTER_IMPLICIT - Is an implicit class. + +
  • CUPS_PRINTER_OPTIONS - All of the printer capability + and option bits. + +
+ +

Encodings

+ +

CUPS defines the following character set encoding constants: + +

    + +
  • CUPS_US_ASCII - US ASCII character set. + +
  • CUPS_UTF_8 - UTF-8 encoding of Unicode. + +
  • CUPS_ISO8859_1 - ISO-8859-1 character set. + +
  • CUPS_ISO8859_2 - ISO-8859-2 character set. + +
  • CUPS_ISO8859_3 - ISO-8859-3 character set. + +
  • CUPS_ISO8859_4 - ISO-8859-4 character set. + +
  • CUPS_ISO8859_5 - ISO-8859-5 character set. + +
  • CUPS_ISO8859_6 - ISO-8859-6 character set. + +
  • CUPS_ISO8859_7 - ISO-8859-7 character set. + +
  • CUPS_ISO8859_8 - ISO-8859-8 character set. + +
  • CUPS_ISO8859_9 - ISO-8859-9 character set. + +
  • CUPS_ISO8859_10 - ISO-8859-10 character set. + +
  • CUPS_ISO8859_13 - ISO-8859-13 character set. + +
  • CUPS_ISO8859_14 - ISO-8859-14 character set. + +
  • CUPS_ISO8859_15 - ISO-8859-15 character set. + +
  • CUPS_WINDOWS_874 - Windows code page 874. + +
  • CUPS_WINDOWS_1250 - Windows code page 1250. + +
  • CUPS_WINDOWS_1251 - Windows code page 1251. + +
  • CUPS_WINDOWS_1252 - Windows code page 1252. + +
  • CUPS_WINDOWS_1253 - Windows code page 1253. + +
  • CUPS_WINDOWS_1254 - Windows code page 1254. + +
  • CUPS_WINDOWS_1255 - Windows code page 1255. + +
  • CUPS_WINDOWS_1256 - Windows code page 1256. + +
  • CUPS_WINDOWS_1257 - Windows code page 1257. + +
  • CUPS_WINDOWS_1258 - Windows code page 1258. + +
+ +

HTTP Constants

+ +

Limits

+ +

The following constants define the limits for strings: + +

    + +
  • HTTP_MAX_BUFFER - Size of socket buffer. + +
  • HTTP_MAX_HOST - Maximum length of hostname. + +
  • HTTP_MAX_URI - Maximum length of URI. + +
  • HTTP_MAX_VALUE - Maximum length of field values. + +
+ +

Status Codes

+ +

The following status codes can be returned by httpUpdate(): + +

    + +
  • HTTP_ERROR - A network error occurred + +
  • HTTP_CONTINUE - Continue response from HTTP proxy + +
  • HTTP_OK - 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 + +
  • HTTP_RESET_CONTENT - Content was reset/recreated + +
  • HTTP_PARTIAL_CONTENT - Only a partial file was recieved/sent + +
  • HTTP_MULTIPLE_CHOICES - 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 - 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 - 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 + +
+ +

Fields

+ +

The following fields are indices for each of the standard HTTP fields in +HTTP 1/1: + +

    + +
  • HTTP_FIELD_ACCEPT_LANGUAGE - Accept-Language + +
  • HTTP_FIELD_ACCEPT_RANGES - Accept-Ranges + +
  • HTTP_FIELD_AUTHORIZATION - Authorization + +
  • HTTP_FIELD_CONNECTION - Connection + +
  • HTTP_FIELD_CONTENT_ENCODING - Content-Encoding + +
  • HTTP_FIELD_CONTENT_LANGUAGE - Content-Language + +
  • HTTP_FIELD_CONTENT_LENGTH - Content-Length + +
  • HTTP_FIELD_CONTENT_LOCATION - Content-Location + +
  • HTTP_FIELD_CONTENT_MD5 - Content-MD5 + +
  • HTTP_FIELD_CONTENT_RANGE - Content-Range + +
  • HTTP_FIELD_CONTENT_TYPE - Content-Type + +
  • HTTP_FIELD_CONTENT_VERSION - Content-Version + +
  • HTTP_FIELD_DATE - Date + +
  • HTTP_FIELD_HOST - Host + +
  • HTTP_FIELD_IF_MODIFIED_SINCE - If-Modified-Since + +
  • HTTP_FIELD_IF_UNMODIFIED_SINCE - If-Unmodified-Since + +
  • HTTP_FIELD_KEEP_ALIVE - Keep-Alive + +
  • HTTP_FIELD_LAST_MODIFIED - Last-Modified + +
  • HTTP_FIELD_LINK - Link + +
  • HTTP_FIELD_LOCATION - Location + +
  • HTTP_FIELD_RANGE - Range + +
  • HTTP_FIELD_REFERER - Referer + +
  • HTTP_FIELD_RETRY_AFTER - Retry-After + +
  • HTTP_FIELD_TRANSFER_ENCODING - Transfer-Encoding + +
  • HTTP_FIELD_UPGRADE - Upgrade + +
  • HTTP_FIELD_USER_AGENT - User-Agent + +
  • HTTP_FIELD_WWW_AUTHENTICATE - WWW-Authenticate + + +
+ +

IPP Constants

+ +

Limits

+ +

The following constants define array limits for IPP data: + +

    + +
  • IPP_MAX_NAME - Maximum length of an attribute name + +
  • IPP_MAX_VALUES - Maximum number of set-of values + that can be read in a request. + +
+ +

Tags

+ +
    + +
  • IPP_TAG_ZERO - Wildcard tag value for searches; also + used to separate groups of attributes + +
  • IPP_TAG_OPERATION - Tag for values of type operation + +
  • IPP_TAG_JOB - Tag for values of type job + +
  • IPP_TAG_END - Tag for values of type end + +
  • IPP_TAG_PRINTER - Tag for values of type printer + +
  • IPP_TAG_UNSUPPORTED_GROUP - Tag for values of type unsupported_group + +
  • IPP_TAG_UNSUPPORTED_VALUE - Tag for values of type unsupported_value + +
  • IPP_TAG_DEFAULT - Tag for values of type default + +
  • IPP_TAG_UNKNOWN - Tag for values of type unknown + +
  • IPP_TAG_NOVALUE - Tag for values of type novalue + +
  • IPP_TAG_NOTSETTABLE - Tag for values of type notsettable + +
  • IPP_TAG_DELETEATTR - Tag for values of type deleteattr + +
  • IPP_TAG_ANYVALUE - Tag for values of type anyvalue + +
  • IPP_TAG_INTEGER - Tag for values of type integer + +
  • IPP_TAG_BOOLEAN - Tag for values of type boolean + +
  • IPP_TAG_ENUM - Tag for values of type enum + +
  • IPP_TAG_STRING - Tag for values of type string + +
  • IPP_TAG_DATE - Tag for values of type date + +
  • IPP_TAG_RESOLUTION - Tag for values of type resolution + +
  • IPP_TAG_RANGE - Tag for values of type range + +
  • IPP_TAG_COLLECTION - Tag for values of type collection + +
  • IPP_TAG_TEXTLANG - Tag for values of type textlang + +
  • IPP_TAG_NAMELANG - Tag for values of type namelang + +
  • IPP_TAG_TEXT - Tag for values of type text + +
  • IPP_TAG_NAME - Tag for values of type name + +
  • IPP_TAG_KEYWORD - Tag for values of type keyword + +
  • IPP_TAG_URI - Tag for values of type uri + +
  • IPP_TAG_URISCHEME - Tag for values of type urischeme + +
  • IPP_TAG_CHARSET - Tag for values of type charset + +
  • IPP_TAG_LANGUAGE - Tag for values of type language + +
  • IPP_TAG_MIMETYPE - Tag for values of type mimetype + +
+ +

Resolution Units

+ +

The IPP_RES_PER_INCH and IPP_RES_PER_CM constants +specify dots per inch and dots per centimeter, respectively. + +

Finishings

+ +

The finishing values specify special finishing operations to be +performed on the job. + +

    + +
  • IPP_FINISH_NONE - Do no finishing + +
  • IPP_FINISH_STAPLE - Staple the job + +
  • IPP_FINISH_PUNCH - Punch the job + +
  • IPP_FINISH_COVER - Cover the job + +
  • IPP_FINISH_BIND - Bind the job + +
+ +

Orientations

+ +

The orientation values specify the orientation of the job. + +

    + +
  • IPP_PORTRAIT - No rotation + +
  • IPP_LANDSCAPE - 90 degrees counter-clockwise + +
  • IPP_REVERSE_LANDSCAPE - 90 degrees clockwise + +
  • IPP_REVERSE_PORTRAIT - 180 degrees + +
+ +

Qualities

+ +

The quality values specify the desired quality of the print. +

    + +
  • IPP_QUALITY_DRAFT - Draft quality + +
  • IPP_QUALITY_NORMAL - Normal quality + +
  • IPP_QUALITY_HIGH - High quality + +
+ +

Job States

+ +

The job state values are used to represent the current job state. + +

    + +
  • IPP_JOB_PENDING - Job is pending + +
  • IPP_JOB_HELD - Job is held + +
  • IPP_JOB_PROCESSING - Job is processing + +
  • IPP_JOB_STOPPED - Job is stopped + +
  • IPP_JOB_CANCELLED - Job is cancelled + +
  • IPP_JOB_ABORTED - Job is aborted + +
  • IPP_JOB_COMPLETED - Job is completed + +
+ +

Printer States

+ +

The printer state values are used to represent the current printer +state. + +

    + +
  • IPP_PRINTER_IDLE - Printer is idle + +
  • IPP_PRINTER_PROCESSING - Printer is processing + +
  • IPP_PRINTER_STOPPED - Printer is stopped + +
+ +

Operations

+ +

The operation values represent the available IPP operations. + +

    + +
  • IPP_PRINT_JOB - Print a file + +
  • IPP_PRINT_URI - Print a URI + +
  • IPP_VALIDATE_JOB - Validate job attributes + +
  • IPP_CREATE_JOB - Create a new job + +
  • IPP_SEND_DOCUMENT - Send a document to a job + +
  • IPP_SEND_URI - Send a URI to a job + +
  • IPP_CANCEL_JOB - Cancel a job + +
  • IPP_GET_JOB_ATTRIBUTES - Get job attributes + +
  • IPP_GET_JOBS - Get a list of all jobs + +
  • IPP_GET_PRINTER_ATTRIBUTES - Get printer attributes + +
  • IPP_HOLD_JOB - Hold a pending job + +
  • IPP_RELEASE_JOB - Release a held job + +
  • IPP_RESTART_JOB - Restart a completed job + +
  • IPP_PAUSE_PRINTER - Pause a printer + +
  • IPP_RESUME_PRINTER - Restart a paused printer + +
  • IPP_PURGE_JOBS - Purge jobs from the queue + +
  • IPP_SET_PRINTER_ATTRIBUTES - Set printer attributes + +
  • IPP_SET_JOB_ATTRIBUTES - Set job attributes + +
  • IPP_GET_PRINTER_SUPPORTED_VALUES - Get printer supported values + +
  • CUPS_GET_DEFAULT - Get the default destination + +
  • CUPS_GET_PRINTERS - Get a list of all printers + +
  • CUPS_ADD_PRINTER - Add or modify a printer + +
  • CUPS_DELETE_PRINTER - Delete a printer + +
  • CUPS_GET_CLASSES - Get a list of all classes + +
  • CUPS_ADD_CLASS - Add or modify a class + +
  • CUPS_DELETE_CLASS - Delete a class + +
  • CUPS_ACCEPT_JOBS - Accept jobs on a printer or class + +
  • CUPS_REJECT_JOBS - Reject jobs on a printer or class + +
  • CUPS_SET_DEFAULT - Set the default destination + +
  • CUPS_GET_DEVICES - Get a list of all devices + +
  • CUPS_GET_PPDS - Get a list of all PPDs + +
  • CUPS_MOVE_JOB - Move a job to a new destination + +
+ +

Status Codes

+ +

Status codes are returned by all IPP requests. + +

    + +
  • IPP_OK - Request completed with no errors + +
  • IPP_OK_SUBST - Request completed but some attribute + values were substituted + +
  • IPP_OK_CONFLICT - Request completed but some attributes + conflicted + +
  • IPP_BAD_REQUEST - The request was bad + +
  • IPP_FORBIDDEN - You don't have access to the resource + +
  • IPP_NOT_AUTHENTICATED - You are not authenticated for + the resource + +
  • IPP_NOT_AUTHORIZED - You not authorized to access + the resource + +
  • IPP_NOT_POSSIBLE - The requested operation cannot be + completed + +
  • IPP_TIMEOUT - A timeout occurred + +
  • IPP_NOT_FOUND - The resource was not found + +
  • IPP_GONE - The resource has gone away + +
  • IPP_REQUEST_ENTITY - The request was too large + +
  • IPP_REQUEST_VALUE - The request contained a value + that was unknown to the server + +
  • IPP_DOCUMENT_FORMAT - The document format is not + supported by the server + +
  • IPP_ATTRIBUTES - Required attributes are missing + +
  • IPP_URI_SCHEME - The URI scheme is not supported + +
  • IPP_CHARSET - The charset is not supported + +
  • IPP_CONFLICT - One or more attributes conflict + +
  • IPP_COMPRESSION_NOT_SUPPORTED - The specified + compression is not supported + +
  • IPP_COMPRESSION_ERROR - The compressed data + contained an error + +
  • IPP_DOCUMENT_FORMAT_ERROR - The document data + contained an error in it + +
  • IPP_DOCUMENT_ACCESS_ERROR - The remote document + could not be accessed + +
  • IPP_INTERNAL_ERROR - The server encountered an + internal error + +
  • IPP_OPERATION_NOT_SUPPORTED - The requested operation + is not supported + +
  • IPP_SERVICE_UNAVAILABLE - The requested service + is unavailable + +
  • IPP_VERSION_NOT_SUPPORTED - The IPP request + version is not supported + +
  • IPP_DEVICE_ERROR - The output device encountered + an error + +
  • IPP_TEMPORARY_ERROR - A temporary error occurred + +
  • IPP_NOT_ACCEPTING - The destination is not accepting + jobs + +
  • IPP_PRINTER_BUSY - The destination is busy + +
  • IPP_ERROR_JOB_CANCELLED - The requested job has been + cancelled + +
  • IPP_MULTIPLE_JOBS_NOT_SUPPORTED - The server + does not support multiple jobs + +
+ +

PPD Constants

+ +

PPD Format Version

+ +

The PPD_VERSION constant defines a floating point number +representing the newest format version that is supported by CUPS, currently +4.3. + +

PPD User-Interface Types

+ +

Each printer option has a type associated with it: + +

    + +
  • PPD_UI_BOOLEAN - The user can turn this option on or off + +
  • PPD_UI_PICKONE - The user can choose one option value + to use. + +
  • PPD_UI_PICKMANY - The user can choose zero or more + option values. + +
+ +

PPD Sections

+ +

Some options must be output before others, or in different sections of +the output document. The ppd_section_t enumeration defines +which section the option must be output in: + +

    + +
  • PPD_ORDER_ANY - The option can be output in any of + the document, page, or prolog sections of the document + +
  • PPD_ORDER_DOCUMENT - The option must be output in + the DocumentSetup section of the document + +
  • PPD_ORDER_EXIT - The option must be output before + the document + +
  • PPD_ORDER_JCL - The option must be output in the + job control section of the document + +
  • PPD_ORDER_PAGE - The option must be output in the + PageSetup section of the document + +
  • PPD_ORDER_PROLOG - The option must be output in the + Prolog section of the document + +
+ +

PPD Colorspaces

+ +

Each printer has a default colorspace: + +

    + +
  • PPD_CS_CMYK - The printer uses CMYK colors by default + +
  • PPD_CS_CMY - The printer uses CMY colors by default + +
  • PPD_CS_GRAY - The printer uses grayscale by default + +
  • PPD_CS_RGB - The printer uses RGB colors by default + +
  • PPD_CS_RGBK - The printer uses RGBK colors by default + +
  • PPD_CS_N - The printer uses a DeviceN colorspace + by default + +
+ +

Raster Constants

+ +

Raster Sync Words

+ +

The CUPS_RASTER_SYNC and CUPS_RASTER_REVSYNC +constants define the standard sync words at the beginning of each CUPS +raster file. + +

Raster Stream Modes

+ +

The CUPS_RASTER_READ and CUPS_RASTER_WRITE +constants are used with the +cupsRasterOpen() function to +specify a stream for reading or writing. + +

Raster Boolean Constants

+ +

The CUPS_FALSE and CUPS_TRUE constants +represent boolean values in the page header. + +

Raster Jog Values

+ +

The cups_jog_t enumeration defines constants for the +Jog page device dictionary variable: + +

    + +
  • CUPS_JOG_NONE - Do no jogging + +
  • CUPS_JOG_FILE - Jog pages after each file + +
  • CUPS_JOG_JOB - Jog pages after each job + +
  • CUPS_JOG_SET - Jog pages after each set of jobs + +
+ +

Raster Orientation Values

+ +

The cups_orient_t enumeration defines constants for the +Orientation page device dictionary variable: + +

    + +
  • CUPS_ORIENT_0 - Portrait orientation + +
  • CUPS_ORIENT_90 - Landscape orientation + +
  • CUPS_ORIENT_180 - Reverse-portrait orientation + +
  • CUPS_ORIENT_270 - Reverse-landscape orientation + +
+ +

Raster CutMedia Values

+ +

The cups_cut_t enumeration defines constants for the +CutMedia page device dictionary variable: + +

    + +
  • CUPS_CUT_NONE - Do no jogging + +
  • CUPS_CUT_FILE - Cut pages after each file + +
  • CUPS_CUT_JOB - Cut pages after each job + +
  • CUPS_CUT_SET - Cut pages after each set of jobs + +
  • CUPS_CUT_PAGE - Cut each page + +
+ +

Raster AdvanceMedia Values

+ +

The cups_advance_t enumeration defines constants for the +AdvanceMedia page device dictionary variable: + +

    + +
  • CUPS_ADVANCE_NONE - Do no jogging + +
  • CUPS_ADVANCE_FILE - Advance media after each file + +
  • CUPS_ADVANCE_JOB - Advance media after each job + +
  • CUPS_ADVANCE_SET - Advance media after each set of jobs + +
  • CUPS_ADVANCE_PAGE - Advance media for each page + +
+ +

Raster LeadingEdge Values

+ +

The cups_edge_t enumeration defines constants for the +LeadingEdge page device dictionary variable: + +

    + +
  • CUPS_EDGE_TOP - The top of the media is the leading + edge + +
  • CUPS_EDGE_RIGHT - The right of the media is the leading + edge + +
  • CUPS_EDGE_BOTTOM - The bottom of the media is the + leading edge + +
  • CUPS_EDGE_LEFT - The left of the media is the leading + edge + +
+ +

Raster Color Order Values

+ +

The cups_order_t enumeration defines the possible color +value orderings: + +

    + +
  • CUPS_ORDER_CHUNKED - CMYK CMYK CMYK + +
  • CUPS_ORDER_BANDED - CCC MMM YYY KKK + +
  • CUPS_ORDER_PLANAR - CCC ... MMM ... YYY ... KKK ... + +
+ +

Raster Colorspace Values

+ +

The cups_cspace_t enumeration defines the possible colorspaces: + +

    + +
  • CUPS_CSPACE_W - White (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 - Metallic yellow (gold), metallic magenta, + metallic cyan, black + +
  • CUPS_CSPACE_GMCS - Metallic yellow (gold), metallic magenta, + metallic cyan, metallic grey (silver) + +
  • CUPS_CSPACE_WHITE - White pigment (black as white pigment) + +
  • CUPS_CSPACE_GOLD - Gold foil (black as gold foil) + +
  • CUPS_CSPACE_SILVER - Silver foil (black as silver foil) + +
+ +

C - Structures

+ +

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

Raster Structures

+ +

Raster Page Header

+ +

The raster page header consists of the PostScript page device dictionary +for the page: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MemberTypeDescription
MediaClasschar[64]The media class name
MediaColorchar[64]The media color name
MediaTypechar[64]The media type name
OutputTypechar[64]The output type name
AdvanceDistanceunsignedThe distance to advance the media in points
AdvanceMediacups_adv_tWhen to advance the media
Collatecups_bool_tWhether or not to produce collated copies
CutMediacups_cut_tWhen to cut the media
Duplexcups_bool_tWhether or not to print on both sides of the paper
HWResolutionunsigned[2]The resolution of the page image in pixels per inch; the + HWResolution[0] represents the horizontal resolution and + HWResolution[1] represents the vertical resolution
ImagingBoundingBoxunsigned[4]The bounding box for the page in points; the elements + represent the left, bottom, right, and top coordinates of the + imaged area (if 0 then the whole page is imaged)
InsertSheetcups_bool_tWhether or not to insert a sheet before this page
Jogcups_jog_tWhen to jog copies of the page
LeadingEdgecups_edge_tThe leading edge of the page
Marginsunsigned[2]The lower-lefthand margin of the page in points
ManualFeedcups_bool_tWhether or not to manually feed the page
MediaPositionunsignedThe input slot number to use
MediaWeightunsignedThe weight of the output media in grams/m2
MirrorPrintcups_bool_tWhether or not to mirror the print
NegativePrintcups_bool_tWhether or not to invert the print
NumCopiesunsignedThe number of copies to produce
Orientationcups_orient_tThe orientation of the page image
OutputFaceUpcups_bool_tWhether or not to output the page face up
PageSizeunsigned[2]The width and height of the page in points
Separationscups_bool_tWhether or not to output separations
TraySwitchcups_bool_tWhether or not to automatically switch trays for the requested + media size/type
Tumblecups_bool_tWhether or not to rotate the back side of the page
cupsWidthunsignedThe width of the page image in pixels
cupsHeightunsignedThe height of the page image in pixels
cupsMediaTypeunsignedThe device-specific media type code
cupsBitsPerColorunsignedThe number of bits per color
cupsBitsPerPixelunsignedThe number of bits per pixel
cupsBytesPerLineunsignedThe number of bytes per line of image data
cupsColorOrdercups_order_tThe order of color values
cupsColorSpacecups_cspace_tThe type of color values
cupsCompressionunsignedThe device-specific compression code
cupsRowCountunsignedThe device-specific row count
cupsRowFeedunsignedThe device-specific row feed
cupsRowStepunsignedThe device-specific row step
+ +

D - 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(), +cupsSetPasswordCB(), +cupsSetServer(), +cupsSetUser(), +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;
+int           jobid;
+
+...
+
+jobid = cupsPrintFile("printer@hostname", "filename.ps", "Job Title",
+                      num_options, options);
+
+ +

See Also

+ +

+cupsCancelJob(), +cupsLastError(), +cupsPrintFiles() + +

cupsPrintFiles()

+ +

Usage

+ +
+int
+cupsPrintFiles(const char    *printer,
+               int           num_files,
+               const char    **files,
+               const char    *title,
+	       int           num_options,
+	       cups_option_t *options);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ArgumentDescription
printerThe printer or class to print to.
num_filesThe number of files to print.
filesThe files 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

+ +

cupsPrintFiles() sends multiple files 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_files;
+const char    *files[100];
+int           num_options;
+cups_option_t *options;
+int           jobid;
+
+...
+
+jobid = cupsPrintFiles("printer@hostname", num_files, files,
+                       "Job Title", num_options, options);
+
+ +

See Also

+ +

+cupsCancelJob(), +cupsLastError(), +cupsPrintFile() + +

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 + client.conf file, + +
  3. The default host, "localhost". + +
+ +

Example

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

See Also

+ +

+cupsGetPassword(), +cupsSetPasswordCB(), +cupsSetServer(), +cupsSetUser(), +cupsUser() + +

cupsSetPasswordCB()

+ +

Usage

+ +
+void
+cupsSetPasswordCB(const char *(*cb)(const char *prompt));
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
cbThe password callback function.
+ +

Description

+ +

cupsSetPasswordCB() sets the callback function to use when +asking the user for a password. The callback function must accept a single +character string pointer (the prompt string) and return NULL +if the user did not enter a password string or a pointer to the password +string otherwise. + +

Example

+ +
+#include <cups/cups.h>
+
+const char *
+my_password_cb(const char *prompt)
+{
+  return (getpass(prompt));
+}
+
+...
+
+char *password;
+
+...
+
+cupsSetPasswordCB(my_password_cb);
+password = cupsGetPassword("Please enter a password:");
+
+ +

See Also

+ +

+cupsServer(), +cupsSetServer(), +cupsSetUser(), +cupsUser() + +

cupsSetServer()

+ +

Usage

+ +
+void
+cupsSetServer(const char *server);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
serverThe default server to use.
+ +

Description

+ +

cupsSetServer() sets the default server to use for +the CUPS API. If the server argument is NULL, +the default server is used. + +

Example

+ +
+#include <cups/cups.h>
+
+cupsSetServer("foo.bar.com");
+
+ +

See Also

+ +

+cupsServer(), +cupsSetPasswordCB(), +cupsSetUser(), +cupsUser() + +

cupsSetUser()

+ +

Usage

+ +
+void
+cupsSetUser(const char *user);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
userThe user name string to use.
+ +

Description

+ +

cupsSetUser() sets the default user name for authentication. +If the user argument is NULL then the current +login user is used. + +

Example

+ +
+#include <cups/cups.h>
+
+...
+
+cupsSetUser("root");
+
+ +

See Also

+ +

+cupsServer(), +cupsSetPasswordCB(), +cupsSetServer(), +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

+ +
+void httpBlocking(http_t *http, int blocking)
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
httpThe HTTP connection
blocking0 if the connection should be non-blocking, 1 if it should + be blocking
+ +

Description

+ +

The httpBlocking() function sets the blocking mode for the +HTTP connection. By default HTTP connections will block (stop) the client +program until data is available or can be sent to the server. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+
+http = httpConnect("server", port);
+httpBlocking(http, 0);
+
+ +

See Also

+ +httpCheck(), +httpConnect() + +

httpCheck()

+ +

Usage

+ +
+int httpCheck(http_t *http);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
httpThe HTTP connection
+ +

Returns

+ +

0 if there is no data pending, 1 otherwise. + +

Description

+ +

The httpCheck() function checks to see if there is any data +pending on an HTTP connection. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+
+if (httpCheck(http))
+{
+  ... do something ...
+}
+
+ +

See Also

+ +httpBlocking(), +httpConnect(), +httpGets(), +httpRead() + + +

httpClearFields()

+ +

Usage

+ +
+void httpClearFields(http_t *http)
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
httpThe HTTP connection
+ +

Description

+ +

The httpClearFields() function clears all HTTP request fields +for the HTTP connection. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+
+httpClearFields(http);
+
+ +

See Also

+ +httpConnect(), +httpGetField(), +httpSetField() + +

httpClose()

+ +

Usage

+ +
+void httpClose(http_t *http);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
httpThe HTTP connection
+ +

Description

+ +

The httpClose() function closes an active HTTP connection. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+
+httpClose(http);
+
+ +

See Also

+ +httpConnect() + +

httpConnect()

+ +

Usage

+ +
+http_t *httpConnect(const char *hostname, int port);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
hostnameThe name or IP address of the server to connect to
portThe port number to use
+ +

Returns

+ +

A pointer to a HTTP connection structure or NULL if the connection could +not be made. + +

Description

+ +

The httpConnect() function opens a HTTP connection to the +specified server and port. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+
+http = httpConnect(cupsServer(), ippPort());
+
+ +

See Also

+ +httpClose(), +httpGet(), +httpGets(), +httpPost(), +httpRead(), +httpWrite() + + +

httpDecode64()

+ +

Usage

+ +
+char *httpDecode64(char *out, const char *in);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
outThe output string
inThe input string
+ +

Returns

+ +

A pointer to the decoded string. + +

Description

+ +

The httpDecode64() function decodes a base-64 encoded string +to the original string. + +

Example

+ +
+#include <cups/http.h>
+
+char encoded_string[255];
+char original_string[255];
+
+httpDecode64(original_string, encoded_string);
+
+ +

See Also

+ +httpEncode64() + +

httpDelete()

+ +

Usage

+ +
+int httpDelete(http_t *http, const char *uri);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
httpThe HTTP connection
uriThe URI to delete
+ +

Returns

+ +

0 on success, non-zero on failure. + +

Description

+ +

The httpDelete() function sends a HTTP DELETE request to +the server. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+
+httpDelete(http, "/some/uri");
+
+ +

See Also

+ +httpConnect(), +httpSetField(), +httpUpdate() + +

httpEncode64()

+ +

Usage

+ +
+char *httpEncode64(char *out, const char *in);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
outThe output string
inThe input string
+ +

Returns

+ +

A pointer to the encoded string. + +

Description

+ +

The httpEncode64() function decodes a base-64 encoded string +to the original string. + +

Example

+ +
+#include <cups/http.h>
+
+char encoded_string[255];
+char original_string[255];
+
+httpEncode64(encoded_string, original_string);
+
+ +

See Also

+ +httpDecode64() + +

httpError()

+ +

Usage

+ +
+int httpError(http_t *http);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
httpThe HTTP connection
+ +

Returns

+ +

The last error that occurred or 0 if no error has occurred. + +

Description

+ +

The httpError() function returns the last error that occurred +on the HTTP connection. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+
+if (httpError(http))
+{
+  ... show an error message ...
+}
+
+ +

See Also

+ +httpConnect() + +

httpFlush()

+ +

Usage

+ +
+void httpFlush(http_t *http);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
httpThe HTTP connection
+ +

Description

+ +

The httpFlush() function flushes any remaining data left from +a GET or POST operation. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+
+httpFlush(http);
+
+ +

See Also

+ +httpConnect(), + +

httpGet()

+ +

Usage

+ +
+int httpGet(http_t *http, const char *uri);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
httpThe HTTP connection
uriThe URI to get
+ +

Returns

+ +

0 on success, non-zero on failure. + +

Description

+ +

The httpGet() function sends a HTTP GET request to the +server. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+
+httpGet(http, "/some/uri");
+
+ +

See Also

+ +httpConnect(), +httpSetField(), +httpUpdate() + + +

httpGets()

+ +

Usage

+ +
+char *httpGets(char *line, int length, http_t *http)
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + +
ArgumentDescription
lineThe string to fill with a line from the HTTP connection
lengthThe maximum length of the string
httpThe HTTP connection
+ +

Returns

+ +

A pointer to the string or NULL if no line could be retrieved. + +

Description

+ +

The httpGets() function is used to read a request line from +the HTTP connection. It is not normally used by a client program. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+char line[1024];
+
+if (httpGets(line, sizeof(line), http))
+{
+  ... process the line ...
+}
+
+ +

See Also

+ +httpConnect(), +httpUpdate() + +

httpGetDateString()

+ +

Usage

+ +
+const char *httpGetDateString(time_t time)
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
timeThe UNIX date/time value
+ +

Returns

+ +

A pointer to a static string containing the HTTP date/time string for +the specified UNIX time value. + +

Description

+ +

The httpGetDateString() function generates a date/time string +suitable for HTTP requests from a UNIX time value. + +

Example

+ +
+#include <cups/http.h>
+
+puts(httpGetDateString(time(NULL)));
+
+ +

See Also

+ +httpGetDateTime() + + +

httpGetDateTime()

+ +

Usage

+ +
+time_t httpGetDateTime(const char *date)
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
dateThe HTTP date/time string
+ +

Returns

+ +

A UNIX time value. + +

Description

+ +

The httpGetDateTime() function converts a HTTP +date/time string to a UNIX time value. + +

Example

+ +
+#include <cups/http.h>
+
+printf("%d\n", httpGetDateTime("Fri, 30 June 2000 12:34:56 GMT"));
+
+ +

See Also

+ +httpGetDateString() + + +

httpGetField()

+ +

Usage

+ +
+const char *httpGetField(http_t *http, http_field_t field);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
httpThe HTTP connection
fieldThe HTTP field
+ +

Returns

+ +

A pointer to the field value string. + +

Description

+ +

The httpGetField() function returns the current value for +the specified HTTP field. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+
+httpGet(http, "/some/uri");
+while (httpUpdate(http) == HTTP_CONTINUE);
+
+puts(httpGetField(http, HTTP_FIELD_CONTENT_TYPE));
+
+ +

See Also

+ +httpConnect(), +httpSetField() + + +

httpHead()

+ +

Usage

+ +
+int httpHead(http_t *http, const char *uri);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
httpThe HTTP connection
uriThe URI to head
+ +

Returns

+ +

0 on success, non-zero on failure. + +

Description

+ +

The httpHead() function sends a HTTP HEAD request to the +server. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+
+httpHead(http, "/some/uri");
+
+ +

See Also

+ +httpConnect(), +httpSetField(), +httpUpdate() + + +

httpInitialize()

+ +

Usage

+ +
+void httpInitialize(void);
+
+ +

Description

+ +

The httpInitialize() function initializes the networking +code as needed by the underlying platform. It is called automatically by +the httpConnect() function. + +

Example

+ +
+#include <cups/http.h>
+
+httpInitialize();
+
+ +

See Also

+ +httpConnect() + +

httpOptions()

+ +

Usage

+ +
+int httpOptions(http_t *http, const char *uri);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
httpThe HTTP connection
uriThe URI to check for options
+ +

Returns

+ +

0 on success, non-zero on failure. + +

Description

+ +

The httpOptions() function sends a HTTP OPTIONS request to the +server. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+
+httpOptions(http, "/some/uri");
+
+ +

See Also

+ +httpConnect(), +httpSetField(), +httpUpdate() + + +

httpPost()

+ +

Usage

+ +
+int httpPost(http_t *http, const char *uri);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
httpThe HTTP connection
uriThe URI to post to
+ +

Returns

+ +

0 on success, non-zero on failure. + +

Description

+ +

The httpPost() function sends a HTTP POST request to the +server. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+
+httpPost(http, "/some/uri");
+
+ +

See Also

+ +httpConnect(), +httpSetField(), +httpUpdate() + + +

httpPrintf()

+ +

Usage

+ +
+int httpPrintf(http_t *http, const char *format, ...);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
httpThe HTTP connection
formatA printf-style format string
+ +

Returns

+ +

The number of bytes written. + +

Description

+ +

The httpPrintf() function sends a formatted string to the +HTTP connection. It is normally only used by the CUPS API and scheduler. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+
+httpPrintf(http, "GET / HTTP/1.1 \r\n");
+
+ +

See Also

+ +httpConnect() + +

httpPut()

+ +

Usage

+ +
+int httpPut(http_t *http, const char *uri);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
httpThe HTTP connection
uriThe URI to put
+ +

Returns

+ +

0 on success, non-zero on failure. + +

Description

+ +

The httpPut() function sends a HTTP PUT request to the +server. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+
+httpDelete(http, "/some/uri");
+
+ +

See Also

+ +httpConnect(), +httpSetField(), +httpUpdate() + + +

httpRead()

+ +

Usage

+ +
+int httpRead(http_t *http, char *buffer, int length);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + +
ArgumentDescription
httpThe HTTP connection
bufferThe buffer to read into
lengthThe number of bytes to read
+ +

Returns

+ +

The number of bytes read or -1 on error. + +

Description

+ +

The httpRead() function reads data from the HTTP connection, +possibly the result of a GET or POST request. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+char buffer[1024];
+int  bytes;
+
+httpGet(http, "/");
+while (httpUpdate(http) != HTTP_CONTINUE);
+while ((bytes = httpRead(http, buffer, sizeof(buffer) - 1)) > 0)
+{
+  buffer[bytes] = '\0';
+  fputs(buffer, stdout);
+}
+
+ +

See Also

+ +httpConnect(), +httpWrite() + +

httpReconnect()

+ +

Usage

+ +
+int httpReconnect(http_t *http);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
httpThe HTTP connection
+ +

Returns

+ +

0 on success, non-zero on failure. + +

Description

+ +

The httpReconnect() function reconnects to the HTTP server. +This is usually done automatically if the HTTP functions detect that the +server connection has terminated. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+
+httpReconnect(http);
+
+ +

See Also

+ +httpConnect() + +

httpSeparate()

+ +

Usage

+ +
+void httpSeparate(const char *uri, char *method,
+                  char *username, char *host, int *port,
+                  char *resource);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ArgumentDescription
uriThe URI to separate
methodThe method (scheme) of the URI
usernameThe username (and password) portion of the URI, if any
hostThe hostname portion of the URI, if any
portThe port number for the URI, either as specified or as + default for the method/scheme
resourceThe resource string, usually a filename on the server
+ +

Description

+ +

The httpSeparate() function separates the specified URI into +its component parts. The method, username, hostname, and resource strings should +be at least HTTP_MAX_URI characters long to avoid potential +buffer overflow problems. + +

Example

+ +
+char uri[HTTP_MAX_URI];
+char method[HTTP_MAX_URI];
+char username[HTTP_MAX_URI];
+char host[HTTP_MAX_URI];
+char resource[HTTP_MAX_URI];
+int port;
+
+httpSeparate(uri, method, username, host, &port, resource);
+
+ +

See Also

+ +httpConnect() + +

httpSetField()

+ +

Usage

+ +
+void httpSetField(http_t *http, http_field_t field, const char *value);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + +
ArgumentDescription
httpThe HTTP connection
fieldThe HTTP field
valueThe string value for the field
+ +

Description

+ +

The httpSetField() function sets the current value for +the specified HTTP field. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+
+httpSetField(http, HTTP_FIELD_AUTHORIZATION, "Basic dfdr34453454325"));
+httpGet(http, "/some/uri");
+while (httpUpdate(http) == HTTP_CONTINUE);
+
+ +

See Also

+ +httpConnect(), +httpGetField() + + +

httpTrace()

+ +

Usage

+ +
+int httpTrace(http_t *http, const char *uri);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
httpThe HTTP connection
uriThe URI to trace
+ +

Returns

+ +

0 on success, non-zero on failure. + +

Description

+ +

The httpTrace() function sends a HTTP TRACE request to the +server. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+
+httpTrace(http, "/some/uri");
+
+ +

See Also

+ +httpConnect(), +httpSetField(), +httpUpdate() + + +

httpUpdate()

+ +

Usage

+ +
+http_status_t httpUpdate(http_t *http);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
httpThe HTTP connection
+ +

Returns

+ +

The HTTP status of the current request. + +

Description

+ +

The httpUpdate() function updates the current request status. +It is used after any DELETE, GET, HEAD, OPTIONS, POST, PUT, or TRACE +request to finalize the HTTP request and retrieve the request status. + +

Since proxies and the current blocking mode can cause the request to +take longer, programs should continue calling httpUpdate() +until the return status is not the constant value HTTP_CONTINUE. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+http_status_t status;
+
+httpGet(http, "/some/uri");
+while ((status = httpUpdate(http)) == HTTP_CONTINUE);
+printf("Request status is %d\n", status);
+
+ +

See Also

+ +httpConnect(), +httpDelete(), +httpGet(), +httpHead(), +httpOptions(), +httpPost(), +httpPut(), +httpTrace() + +

httpWrite()

+ +

Usage

+ +
+int httpWrite(http_t *http, char *buffer, int length);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + +
ArgumentDescription
httpThe HTTP connection
bufferThe buffer to read into
lengthThe number of bytes to read
+ +

Returns

+ +

The number of bytes read or -1 on error. + +

Description

+ +

The httpWrite() function reads data from the HTTP connection, +possibly the result of a GET or POST request. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+FILE *fp;
+char buffer[1024];
+int  bytes;
+
+httpPost(http, "/");
+
+while ((bytes = fread(buffer, 1, sizeof(buffer), fp)) > 0)
+  httpWrite(http, buffer, bytes);
+
+while (httpUpdate(http) != HTTP_CONTINUE);
+
+while ((bytes = httpRead(http, buffer, sizeof(buffer) - 1)) > 0)
+{
+  buffer[bytes] = '\0';
+  fputs(buffer, stdout);
+}
+
+ +

See Also

+ +httpConnect(), +httpRead() + +

ippAddBoolean()

+ +

Usage

+ +
+ipp_attribute_t *ippAddBoolean(ipp_t *ipp, ipp_tag_t group,
+                               const char *name, char value);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
nameThe name of attribute
valueThe boolean value
+ +

Returns

+ +

A pointer to the new attribute or NULL if the attribute could not be +created. + +

Description

+ +

The ippAddBoolean() function adds a single boolean attribute +value to the specified IPP request. + +

Example

+ +
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+
+ippAddBoolean(ipp, IPP_TAG_OPERATION, "my-jobs", 1);
+
+ +

See Also

+ +ippAddBooleans(), +ippAddDate(), +ippAddInteger(), +ippAddIntegers(), +ippAddRange(), +ippAddRanges(), +ippAddResolution(), +ippAddResolutions(), +ippAddSeparator(), +ippAddString(), +ippAddStrings() + + +

ippAddBooleans()

+ +

Usage

+ +
+ipp_attribute_t *ippAddBooleans(ipp_t *ipp, ipp_tag_t group,
+                                const char *name, int num_values,
+                                const char *values);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
nameThe name of attribute
num_valuesThe number of values
valuesThe boolean values
+ +

Returns

+ +

A pointer to the new attribute or NULL if the attribute could not be +created. + +

Description

+ +

The ippAddBooleans() function adds one or more boolean +attribute values to the specified IPP request. If the +values pointer is NULL then an array of +num_values false values is created. + +

Example

+ +
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+char values[10];
+
+ippAddBooleans(ipp, IPP_TAG_OPERATION, "some-attribute", 10, values);
+
+ +

See Also

+ +ippAddBoolean(), +ippAddDate(), +ippAddInteger(), +ippAddIntegers(), +ippAddRange(), +ippAddRanges(), +ippAddResolution(), +ippAddResolutions(), +ippAddSeparator(), +ippAddString(), +ippAddStrings() + + +

ippAddDate()

+ +

Usage

+ +
+ipp_attribute_t *ippAddDate(ipp_t *ipp, ipp_tag_t group,
+                            const char *name, ipp_uchar_t *value);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
nameThe name of attribute
valueThe date value
+ +

Returns

+ +

A pointer to the new attribute or NULL if the attribute could not be +created. + +

Description

+ +

The ippAddDate() function adds a single date-time attribute +value to the specified IPP request. + +

Example

+ +
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+
+ippAddDate(ipp, IPP_TAG_OPERATION, "some-attribute", 
+           ippTimeToDate(time(NULL));
+
+ +

See Also

+ +ippAddBoolean(), +ippAddBooleans(), +ippAddInteger(), +ippAddIntegers(), +ippAddRange(), +ippAddRanges(), +ippAddResolution(), +ippAddResolutions(), +ippAddSeparator(), +ippAddString(), +ippAddStrings(), +ippTimeToDate() + + +

ippAddInteger()

+ +

Usage

+ +
+ipp_attribute_t *ippAddInteger(ipp_t *ipp, ipp_tag_t group,
+                               ipp_tag_t tag, const char *name,
+                               int value);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
tagThe type of integer value (IPP_TAG_INTEGER or IPP_TAG_ENUM)
nameThe name of attribute
valueThe integer value
+ +

Returns

+ +

A pointer to the new attribute or NULL if the attribute could not be +created. + +

Description

+ +

The ippAddInteger() function adds a single integer attribute +value to the specified IPP request. + +

Example

+ +
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+
+ippAddInteger(ipp, IPP_TAG_OPERATION, "limit", 100);
+
+ +

See Also

+ +ippAddBoolean(), +ippAddBooleans(), +ippAddDate(), +ippAddIntegers(), +ippAddRange(), +ippAddRanges(), +ippAddResolution(), +ippAddResolutions(), +ippAddSeparator(), +ippAddString(), +ippAddStrings() + + +

ippAddIntegers()

+ +

Usage

+ +
+ipp_attribute_t *ippAddIntegers(ipp_t *ipp, ipp_tag_t group,
+                                ipp_tag_t tag, const char *name,
+                                int num_values, const int *values);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
tagThe type of integer value (IPP_TAG_INTEGER or IPP_TAG_ENUM)
nameThe name of attribute
num_valuesThe number of values
valuesThe integer values
+ +

Returns

+ +

A pointer to the new attribute or NULL if the attribute could not be +created. + +

Description

+ +

The ippAddIntegers() function adds one or more integer +attribute values to the specified IPP request. If the +values pointer is NULL then an array of +num_values 0 values is created. + +

Example

+ +
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+int values[100];
+
+ippAddIntegers(ipp, IPP_TAG_OPERATION, "some-attribute", 100, values);
+
+ +

See Also

+ +ippAddBoolean(), +ippAddBooleans(), +ippAddDate(), +ippAddInteger(), +ippAddRange(), +ippAddRanges(), +ippAddResolution(), +ippAddResolutions(), +ippAddSeparator(), +ippAddString(), +ippAddStrings() + + +

ippAddRange()

+ +

Usage

+ +
+ipp_attribute_t *ippAddRange(ipp_t *ipp, ipp_tag_t group,
+                             const char *name, int low,
+                             int high);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
nameThe name of attribute
lowThe lower value
highThe higher value
+ +

Returns

+ +

A pointer to the new attribute or NULL if the attribute could not be +created. + +

Description

+ +

The ippAddRange() function adds a single range attribute +value to the specified IPP request. + +

Example

+ +
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+
+ippAddRange(ipp, IPP_TAG_OPERATION, "page-ranges", 1, 10);
+
+ +

See Also

+ +ippAddBoolean(), +ippAddBooleans(), +ippAddDate(), +ippAddInteger(), +ippAddIntegers(), +ippAddRanges(), +ippAddResolution(), +ippAddResolutions(), +ippAddSeparator(), +ippAddString(), +ippAddStrings() + + +

ippAddRanges()

+ +

Usage

+ +
+ipp_attribute_t *ippAddRanges(ipp_t *ipp, ipp_tag_t group,
+                              const char *name, int num_values,
+                              const int *lows, const int *highs);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
nameThe name of attribute
num_valuesThe number of range values
lowsThe lower values
highsThe higher values
+ +

Returns

+ +

A pointer to the new attribute or NULL if the attribute could not be +created. + +

Description

+ +

The ippAddRanges() function adds one or more range +attribute values to the specified IPP request. If the +values pointer is NULL then an array of +num_values 0,0 ranges is created. + +

Example

+ +
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+int lows[2];
+int highs[2];
+
+ippAddRanges(ipp, IPP_TAG_OPERATION, "page-ranges", 2, lows, highs);
+
+ +

See Also

+ +ippAddBoolean(), +ippAddBooleans(), +ippAddDate(), +ippAddInteger(), +ippAddIntegers(), +ippAddRange(), +ippAddResolution(), +ippAddResolutions(), +ippAddSeparator(), +ippAddString(), +ippAddStrings() + + +

ippAddResolution()

+ +

Usage

+ +
+ipp_attribute_t *ippAddResolution(ipp_t *ipp, ipp_tag_t group,
+                                  const char *name, int xres,
+                                  int yres, ipp_res_t units);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
nameThe name of attribute
xresThe horizontal resolution
yresThe vertical resolution
unitsThe resolution units
+ +

Returns

+ +

A pointer to the new attribute or NULL if the attribute could not be +created. + +

Description

+ +

The ippAddResolution() function adds a single resolution attribute +value to the specified IPP request. + +

Example

+ +
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+
+ippAddBoolean(ipp, IPP_TAG_OPERATION, "printer-resolution",
+              720, 720, IPP_RES_PER_INCH);
+
+ +

See Also

+ +ippAddBoolean(), +ippAddBooleans(), +ippAddDate(), +ippAddInteger(), +ippAddIntegers(), +ippAddRange(), +ippAddRanges(), +ippAddResolutions(), +ippAddSeparator(), +ippAddString(), +ippAddStrings() + + +

ippAddResolutions()

+ +

Usage

+ +
+ipp_attribute_t *ippAddResolutions(ipp_t *ipp, ipp_tag_t group,
+                                   const char *name, int num_values,
+                                   const int *xres, const int *yres,
+                                   const ipp_res_t *units);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
nameThe name of attribute
num_valuesThe number of resolution values
xresThe horizontal resolutions
yresThe vertical resolutions
unitsThe resolution units
+ +

Returns

+ +

A pointer to the new attribute or NULL if the attribute could not be +created. + +

Description

+ +

The ippAddResolutions() function adds one or more +resolution attribute values to the specified IPP request. If the +values pointer is NULL then an array of +num_values 0,0 resolutions is created. + +

Example

+ +
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+int xres[5];
+int yres[5];
+ipp_res_t units[5];
+
+ippAddBoolean(ipp, IPP_TAG_OPERATION, "printer-resolutions-supported",
+              5, xres, yres, units);
+
+ +

See Also

+ +ippAddBoolean(), +ippAddBooleans(), +ippAddDate(), +ippAddInteger(), +ippAddIntegers(), +ippAddRange(), +ippAddRanges(), +ippAddResolution(), +ippAddSeparator(), +ippAddString(), +ippAddStrings() + + +

ippAddSeparator()

+ +

Usage

+ +
+ipp_attribute_t *ippAddSeparator(ipp_t *ipp);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
ippThe IPP request
+ +

Returns

+ +

A pointer to the new separator or NULL if the separator could not be +created. + +

Description

+ +

The ippAddSeparator() function adds a group separator +to the specified IPP request. + +

Example

+ +
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+
+ippAddSeparator(ipp);
+
+ +

See Also

+ +ippAddBoolean(), +ippAddBooleans(), +ippAddDate(), +ippAddInteger(), +ippAddIntegers(), +ippAddRange(), +ippAddRanges(), +ippAddResolution(), +ippAddResolutions(), +ippAddString(), +ippAddStrings() + + +

ippAddString()

+ +

Usage

+ +
+ipp_attribute_t *ippAddString(ipp_t *ipp, ipp_tag_t group,
+                              ipp_tag_t tag, const char *name,
+                              const char *charset, const char *value);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
tagThe type of string value
nameThe name of attribute
charsetThe character set for the string
valueThe string value
+ +

Returns

+ +

A pointer to the new attribute or NULL if the attribute could not be +created. + +

Description

+ +

The ippAddString() function adds a single string attribute +value to the specified IPP request. For IPP_TAG_NAMELANG and +IPP_TAG_TEXTLANG strings, the charset value is provided with +the string to identify the string encoding used. Otherwise the charset value +is ignored. + +

Example

+ +
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+
+ippAddString(ipp, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name",
+             NULL, "abc123");
+
+ +

See Also

+ +ippAddBoolean(), +ippAddBooleans(), +ippAddDate(), +ippAddInteger(), +ippAddIntegers(), +ippAddRange(), +ippAddRanges(), +ippAddResolution(), +ippAddResolutions(), +ippAddSeparator(), +ippAddStrings() + + +

ippAddStrings()

+ +

Usage

+ +
+ipp_attribute_t *ippAddStrings(ipp_t *ipp, ipp_tag_t group,
+                               ipp_tag_t tag, const char *name,
+                               int num_values, const char *charset,
+                               const char **values);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
tagThe type of string value
nameThe name of attribute
num_valuesThe number of strings
charsetThe character set for the strings
valuesThe string values
+ +

Returns

+ +

A pointer to the new attribute or NULL if the attribute could not be +created. + +

Description

+ +

The ippAddStrings() function adds one or more string +attribute values to the specified IPP request. For +IPP_TAG_NAMELANG and IPP_TAG_TEXTLANG +strings, the charset value is provided with the strings to identify the +string encoding used. Otherwise the charset value is ignored. If the +values pointer is NULL then an array of +num_values NULL strings is created. + +

Example

+ +
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+char *values[2] = { "one", "two" };
+
+ippAddStrings(ipp, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "attr-name",
+              2, NULL, values);
+
+ +

See Also

+ +ippAddBoolean(), +ippAddBooleans(), +ippAddDate(), +ippAddInteger(), +ippAddIntegers(), +ippAddRange(), +ippAddRanges(), +ippAddResolution(), +ippAddResolutions(), +ippAddSeparator(), +ippAddString() + + +

ippDateToTime()

+ +

Usage

+ +
+time_t ippDateToTime(const ipp_uchar_t date[11]);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
dateThe IPP date-time value
+ +

Returns

+ +

A UNIX time value. + +

Description

+ +

The ippDateToTime() function converts an IPP date-time value +to a UNIX time value. + +

Example

+ +
+#include <cups/ipp.h>
+
+ipp_uchar_t date[11];
+
+printf("UNIX time is %d\n", ippDateToTime(date));
+
+ +

See Also

+ +ippTimeToDate() + + +

ippDelete()

+ +

Usage

+ +
+void ippDelete(ipp_t *ipp);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
ippThe IPP request or response
+ +

Description

+ +

The ippDelete() function deletes all memory used by an IPP +request or response. + +

Example

+ +
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+
+ippDelete(ipp);
+
+ +

See Also

+ +ippNew() + + +

ippFindAttribute()

+ +

Usage

+ +
+
+ +

Arguments

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

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

ippLength()

+ +

Usage

+ +
+
+ +

Arguments

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

Returns

+ +

Description

+ +

Example

+ +
+
+ +

See Also

+ + +

ippNew()

+ +

Usage

+ +
+ipp_t *ippNew(void);
+
+ +

Returns

+ +

A pointer to a new IPP request or response. + +

Description

+ +

The ippNew() function creates a new IPP request or response. + +

Example

+ +
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+
+ipp = ippNew();
+
+ +

See Also

+ +ippDelete() + + +

ippPort()

+ +

Usage

+ +
+int ippPort(void);
+
+ +

Returns

+ +

The default TCP/IP port number for IPP requests. + +

Description

+ +

The ippPort() function returns the default IPP port number +for requests. + +

Example

+ +
+#include <cups/http.h>
+#include <cups/ipp.h>
+
+http_t *http;
+
+http = httpConnect(cupsServer(), ippPort());
+
+ +

See Also

+ +cupsServer(), +ippSetPort() + + +

ippRead()

+ +

Usage

+ +
+ipp_state_t ippRead(http_t *http, ipp_t *ipp);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
httpThe HTTP connection
ippThe IPP request or response
+ +

Returns

+ +

The current read state. + +

Description

+ +

The ippRead() function reads IPP attributes from the specified +HTTP connection. Programs should continue calling ippRead() until +IPP_ERROR or IPP_DATA is returned. + +

Example

+ +
+#include <cups/http.h>
+#include <cups/ipp.h>
+
+http_t *http;
+ipp_t *ipp;
+ipp_state_t status;
+
+ipp = ippNew();
+
+while ((status = ippRead(http, ipp)) != IPP_ERROR)
+  if (status == IPP_DATA)
+    break;
+
+if (status == IPP_DATA)
+{
+  ... read additional non-IPP data using httpRead() ...
+}
+
+ +

See Also

+ +ippWrite() + + +

ippSetPort()

+ +

Usage

+ +
+void
+ippSetPort(int port);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
portThe port number to use
+ +

Description

+ +

The ippSetPort() function sets the default IPP port number +for requests. + +

Example

+ +
+#include <cups/http.h>
+#include <cups/ipp.h>
+
+...
+
+ippSetPort(8631);
+
+ +

See Also

+ +ippPort() + + +

ippTimeToDate()

+ +

Usage

+ +
+ipp_uchar_t *ippTimeToDate(time_t time);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
timeThe UNIX time value
+ +

Returns

+ +

A static pointer to an IPP date-time value. + +

Description

+ +

The ippTimeToDate() function converts a UNIX time to an IPP +date-time value. + +

Example

+ +
+#include <cups/ipp.h>
+
+ipp_uchar_t *date;
+
+date = ippTimeToDate(time(NULL));
+
+ +

See Also

+ +ippDateToTime() + + +

ippWrite()

+ +

Usage

+ +
+ipp_state_t ippWrite(http_t *http, ipp_t *ipp);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
httpThe HTTP connection
ippThe IPP request or response
+ +

Returns

+ +

The current write state. + +

Description

+ +

The ippWrite() function writes IPP attributes to the specified +HTTP connection. Programs should continue calling ippWrite() until +IPP_ERROR or IPP_DATA is returned. + +

Example

+ +
+#include <cups/http.h>
+#include <cups/ipp.h>
+
+http_t *http;
+ipp_t *ipp;
+ipp_state_t status;
+
+ipp = ippNew();
+... add attributes ...
+
+while ((status = ippWrite(http, ipp)) != IPP_ERROR)
+  if (status == IPP_DATA)
+    break;
+
+if (status == IPP_DATA)
+{
+  ... read additional non-IPP data using httpWrite() ...
+}
+
+ +

See Also

+ +ippRead() + + +

ppdClose()

+ +

Usage

+ +
+void ppdClose(ppd_file_t *ppd);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
ppdThe PPD file
+ +

Description

+ +

The ppdClose() function frees all memory associated with the +PPD file. + +

Example

+ +
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+
+ppdClose(ppd);
+
+ +

See Also

+ +ppdOpen(), +ppdOpenFd(), +ppdOpenFile() + + +

ppdConflicts()

+ +

Usage

+ +
+int ppdConflicts(ppd_file_t *ppd);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
ppdThe PPD file
+ +

Returns

+ +

The number of option conflicts in the file. + +

Description

+ +

The ppdConflicts() function returns the number of conflicts +with the currently selected options. + +

Example

+ +
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+
+printf("%d conflicts\n", ppdConflicts(ppd));
+
+ +

See Also

+ +cupsMarkOptions(), +ppdIsMarked(), +ppdMarkDefaults(), +ppdMarkOption() + + +

ppdEmit()

+ +

Usage

+ +
+int ppdEmit(ppd_file_t *ppd, FILE *file, ppd_section_t section);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + +
ArgumentDescription
ppdThe PPD file
fileThe file to write to
sectionThe option section to write
+ +

Returns

+ +

0 on success, -1 on error. + +

Description

+ +

The ppdEmit() function sends printer-specific option +commands to the specified file. + +

Example

+ +
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+
+ppdEmit(ppd, stdout, PPD_ORDER_PAGE);
+
+ +

See Also

+ +ppdEmitFd() + + +

ppdEmitFd()

+ +

Usage

+ +
+int ppdEmitFd(ppd_file_t *ppd, int fd, ppd_section_t section);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + +
ArgumentDescription
ppdThe PPD file
fdThe file descriptor to write to
sectionThe option section to write
+ +

Returns

+ +

0 on success, -1 on error. + +

Description

+ +

The ppdEmitFd() function sends printer-specific option +commands to the specified file descriptor. + +

Example

+ +
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+
+ppdEmitFd(ppd, 1, PPD_ORDER_PAGE);
+
+ +

See Also

+ +ppdEmit() + + +

ppdFindChoice()

+ +

Usage

+ +
+ppd_choice_t *ppdFindChoice(ppd_option_t *option, const char *choice);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
optionA pointer to the option
choiceThe name of the choice
+ +

Returns

+ +

A pointer to the choice data or NULL if the choice does not exist. + +

Description

+ +

The ppdFindChoice() function returns a pointer to the choice +data for the specified option. + +

Example

+ +
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+ppd_option_t *option;
+ppd_choice_t *choice;
+
+option = ppdFindOption(ppd, "PageSize");
+choice = ppdFindChoice(option, "Letter");
+
+ +

See Also

+ +ppdFindMarkedChoice(), +ppdFindOption() + + +

ppdFindMarkedChoice()

+ +

Usage

+ +
+ppd_choice_t *ppdFindMarkedChoice(ppd_file_t *ppd, const char *keyword);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
ppdThe PPD file
keywordThe name of the option
+ +

Returns

+ +

A pointer to the choice data or NULL if the choice does not exist or +is not marked. + +

Description

+ +

The ppdFindMarkedChoice() function returns a pointer to +the marked choice data for the specified option. + +

Example

+ +
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+ppd_choice_t *choice;
+
+choice = ppdFindMarkedChoice(ppd, "PageSize");
+
+ +

See Also

+ +ppdFindChoice(), +ppdFindOption() + + +

ppdFindOption()

+ +

Usage

+ +
+ppd_option_t *ppdFindOption(ppd_file_t *ppd, const char *keyword);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
ppdThe PPD file
keywordThe name of the option
+ +

Returns

+ +

A pointer to the option data or NULL if the option does not exist. + +

Description

+ +

The ppdFindOption() function returns a pointer to the option +data for the specified option. + +

Example

+ +
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+ppd_option_t *option;
+
+option = ppdFindOption(ppd, "PageSize");
+
+ +

See Also

+ +ppdFindChoice(), +ppdFindMarkedChoice() + + +

ppdIsMarked()

+ +

Usage

+ +
+int ppdIsMarked(ppd_file_t *ppd, const char *keyword, char char *choice);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + +
ArgumentDescription
ppdThe PPD file
keywordThe name of the option
choiceThe name of the option choice
+ +

Returns

+ +

1 if the choice is marked, 0 otherwise. + +

Description

+ +

The ppdIsMarked() function returns whether or not the +specified option choice is marked. + +

Example

+ +
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+
+printf("Letter size %s selected.\n",
+       ppdIsMarked(ppd, "PageSize", "Letter") ? "is" : "is not");
+
+ +

See Also

+ +cupsMarkOptions(), +ppdConflicts(), +ppdIsMarked(), +ppdMarkDefaults(), +ppdMarkOption() + + +

ppdMarkDefaults()

+ +

Usage

+ +
+void ppdMarkDefaults(ppd_file_t *ppd);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
ppdThe PPD file
+ +

Description

+ +

The ppdMarkDefaults() function marks all of the default +choices in the PPD file. + +

Example

+ +
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+
+ppdMarkDefaults(ppd);
+
+ +

See Also

+ +cupsMarkOptions(), +ppdConflicts(), +ppdIsMarked(), +ppdMarkDefaults(), +ppdMarkOption() + + +

ppdMarkOption()

+ +

Usage

+ +
+int ppdMarkOption(ppd_file_t *ppd, const char *keyword, const char *choice);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + +
ArgumentDescription
ppdThe PPD file
keywordThe name of the option
choiceThe name of the choice
+ +

Returns

+ +

The number of conflicts in the PPD file. + +

Description

+ +

The ppdMarkOption() function marks the specified option +choice. + +

Example

+ +
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+
+ppdMarkOption(ppd, "PageSize", "Letter");
+
+ +

See Also

+ +cupsMarkOptions(), +ppdConflicts(), +ppdIsMarked(), +ppdMarkDefaults(), +ppdMarkOption() + + +

ppdOpen()

+ +

Usage

+ +
+ppd_file_t *ppdOpen(FILE *file);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
fileThe file to read from
+ +

Returns

+ +

A pointer to a PPD file structure or NULL if the PPD file could not be +read. + +

Description

+ +

The ppdOpen() function reads a PPD file from the specified +file into memory. + +

Example

+ +
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+FILE *file;
+
+file = fopen("filename.ppd", "rb");
+ppd = ppdOpen(file);
+fclose(file);
+
+ +

See Also

+ +ppdClose(), +ppdOpenFd(), +ppdOpenFile() + + +

ppdOpenFd()

+ +

Usage

+ +
+ppd_file_t *ppdOpenFd(int fd);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
fdThe file descriptor to read from
+ +

Returns

+ +

A pointer to a PPD file structure or NULL if the PPD file could not be +read. + +

Description

+ +

The ppdOpenFd() function reads a PPD file from the specified +file descriptor into memory. + +

Example

+ +
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+int        fd;
+
+fd = open("filename.ppd", O_RDONLY);
+ppd = ppdOpenFd(fd);
+close(fd);
+
+ +

See Also

+ +ppdClose(), +ppdOpen(), +ppdOpenFile() + + +

ppdOpenFile()

+ +

Usage

+ +
+ppd_file_t *ppdOpenFile(const char *filename);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
filenameThe name of the file to read from
+ +

Returns

+ +

A pointer to a PPD file structure or NULL if the PPD file could not be +read. + +

Description

+ +

The ppdOpenFile() function reads a PPD file from the named +file into memory. + +

Example

+ +
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+
+ppd = ppdOpenFile("filename.ppd");
+
+ +

See Also

+ +ppdClose(), +ppdOpen(), +ppdOpenFd() + + +

ppdPageLength()

+ +

Usage

+ +
+float ppdPageLength(ppd_file_t *ppd, const char *name);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
ppdThe PPD file
nameThe name of the page size
+ +

Returns

+ +

The length of the specified page size in points or 0 if the page size +does not exist. + +

Description

+ +

The ppdPageLength() function returns the page length of the +specified page size. + +

Example

+ +
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+
+printf("Length = %.0f\n", ppdPageLength(ppd, "Letter"));
+
+ +

See Also

+ +ppdPageLength(), +ppdPageSize(), +ppdPageWidth() + + +

ppdPageSize()

+ +

Usage

+ +
+ppd_size_t *ppdPageSize(ppd_file_t *ppd, const char *name);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
ppdThe PPD file
nameThe name of the page size
+ +

Returns

+ +

A pointer to the page size record of the specified page size in +points or NULL if the page size does not exist. + +

Description

+ +

The ppdPageSize() function returns the page size record for the +specified page size. + +

Example

+ +
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+ppd_size_t *size;
+
+size = ppdPageSize(ppd, "Letter");
+if (size != NULL)
+{
+  printf(" Width = %.0f\n", size->width);
+  printf("Length = %.0f\n", size->length);
+  printf("  Left = %.0f\n", size->left);
+  printf(" Right = %.0f\n", size->right);
+  printf("Bottom = %.0f\n", size->bottom);
+  printf("   Top = %.0f\n", size->top);
+}
+
+ +

See Also

+ +ppdPageLength(), +ppdPageWidth() + + +

ppdPageWidth()

+ +

Usage

+ +
+float ppdPageWidth(ppd_file_t *ppd, const char *name);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
ppdThe PPD file
nameThe name of the page size
+ +

Returns

+ +

The width of the specified page size in points or 0 if the page size +does not exist. + +

Description

+ +

The ppdPageWidth() function returns the page width of the +specified page size. + +

Example

+ +
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+
+printf("Width = %.0f\n", ppdPageWidth(ppd, "Letter"));
+
+ +

See Also

+ +ppdPageLength(), +ppdPageSize() + + + + diff --git a/doc/sps.html b/doc/sps.html new file mode 100644 index 0000000000..fb091b26fd --- /dev/null +++ b/doc/sps.html @@ -0,0 +1,297 @@ + + + + CUPS Software Performance Specification + + + + + + + +

+

CUPS Software Performance Specification


+CUPS-SPS-1.1
+Easy Software Products
+Copyright 1997-2000, All Rights Reserved
+
+
+

Table of Contents

+
+
1 Scope + +2 References + +3 Programs +
+
4 Scheduler Objects +
+
A Glossary + +
+

1 Scope

+

1.1 Identification

+

This software performance specification provides an analysis of the +memory, disk, and processor utilitization of each program in the Common +UNIX Printing System ("CUPS") Version 1.1.

+

For the purposes of comparison, all figures are for the Linux Intel +platform. Memory utilization on other platforms should be similar.

+

1.2 System Overview

+

CUPS provides a portable printing layer for UNIX®-based 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 ("IPP") as the basis for +managing print jobs and queues. The Line Printer Daemon ("LPD") Server +Message Block ("SMB"), and AppSocket (a.k.a. JetDirect) protocols are +also supported with reduced functionality. CUPS adds network printer +browsing and PostScript Printer Description ("PPD") based printing +options to support real-world printing under UNIX.

+

CUPS also includes a customized version of GNU Ghostscript +(currently based off GNU Ghostscript 5.50) and an image file RIP that +are used to support non-PostScript printers. Sample drivers for HP and +EPSON printers are included that use these filters.

+

1.3 Document Overview

+

This software performance specification is organized into the +following sections:

+
    +
  • 1 - Scope
  • +
  • 2 - References
  • +
  • 3 - Programs
  • +
  • 4 - Scheduler Objects
  • +
  • A - Glossary
  • +
+

2 References

+

2.1 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-IPP-1.1: CUPS Implementation of IPP
  • +
  • CUPS-SAM-1.1.x: CUPS Software Administrators Manual
  • +
  • CUPS-SDD-1.1: CUPS Software Design Description
  • +
  • CUPS-SPM-1.1.x: 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: CUPS Software Version Description
  • +
+

2.2 Other Documents

+

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

+ +

3 Programs

+

The following table describes the average memory, disk, and CPU +usage of each program in CUPS.

+

The base memory column shows the initial memory requirements for +each program, including any shared libraries that are provided by CUPS.

+

The max memory column shows the maximum amount of memory that will +be used by the program based upon the default configuration settings +supplied with CUPS.

+

The temp files column indicates whether any temporary files are +created.

+

The CPU usage column specifies a relative CPU usage by the program +under normal conditions, either low, medium, or high. Low usage +indicates that the program will never use more than 33% of the +available CPU time. Medium usage indicates the program will use as much +as 66% of the available CPU time. High usage indicates the program uses +66% or more of the available CPU time. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Backends
ProgramBase MemoryMax MemoryTemp +FilesCPU Usage
ipp91k256kUp to size of print file +Low
lpd89k89kUp to size of print file +Low
parallel85k85kUp to size of print +fileLow
serial85k85kUp to size of print file +Low
socket85k85kUp to size of print file +Low
usb85k85kUp to size of print file +Low
CGIs
ProgramBase MemoryMax MemoryTemp +FilesCPU Usage
admin.cgi107k256kUp to size of PPD +fileMedium
classes.cgi95kSize of class objects +NoneMedium
jobs.cgi93kSize of job objectsNone +Medium
printers.cgi95kSize of printer objects +NoneMedium
Command-Line Programs
ProgramBase MemoryMax MemoryTemp +FilesCPU Usage
accept88k128kNoneLow
cancel88k128kNoneLow
disable88k128kNoneLow
enable88k128kNoneLow
lp90k256kNoneLow
lpadmin148k256kNoneLow
lpc86kSize of job and printer objects +NoneMedium
lpinfo89kSize of device and PPD objects +NoneMedium
lpmove88k128kNoneLow
lpoptions89k128kNoneLow
lppasswd90k90kNoneLow
lpq87kSize of job objectsNone +Medium
lpr87k256kNoneLow
lprm84k128kNoneLow
lpstat119kSize of job, printer, and class +objectsNoneMedium
reject88k128kNoneLow
Daemons
ProgramBase MemoryMax MemoryTemp +FilesCPU Usage
cups-lpd92k256kOne file per control +or data file from clientLow
cupsd308kSee Scheduler Requirements +See Scheduler RequirementsMedium
cups-polld84kSize of printer and class objects +NoneLow
Filters
ProgramBase MemoryMax MemoryTemp +FilesCPU Usage
hpgltops263k320kNoneMedium
imagetops628k10MSwap file for +uncompressed image dataMedium
imagetoraster652k10MSwap file for +uncompressed image dataHigh
pstops775k840kUp to size of print +fileMedium
pstoraster4M14MSwap file for command +listsHigh
rastertoepson693k1MNoneLow
rastertohp690k1MNoneLow
texttops638k4*cols*rowsNone +Low
+
+

+

4 Scheduler Objects

+

The cupsd program is the CUPS scheduler process. It +manages many interdependent server objects that are used to manage and +print files to printers.

+

The following table provides the memory and disk cost associated +with each server object. +

+ + + + + + + + + + + + + + + +
ObjectMemory PerDisk Per
Browse ACL1k120
Browse Poll2480
Browse Relay2880
Certificate7632
Class9k200
Client13k-
Device256-
Job2k1k + size of document files
Location ACL1k120
MIME Filter26880
MIME Type34080
PPD200656
Printer11k32k
+
+

+

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 Page 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
+
PPD
+
PostScript Printer Description
+
SMB
+
Server Message Block
+
TFTP
+
Trivial File Transfer Protocol
+
+ + diff --git a/doc/sps.pdf b/doc/sps.pdf new file mode 100644 index 0000000000..03f77b6c8b Binary files /dev/null and b/doc/sps.pdf differ diff --git a/doc/sps.shtml b/doc/sps.shtml new file mode 100644 index 0000000000..e37f22224a --- /dev/null +++ b/doc/sps.shtml @@ -0,0 +1,457 @@ + + + + + + CUPS Software Performance Specification + + + +

Scope

+ +

Identification

+ +

This software performance specification provides an analysis of the +memory, disk, and processor utilitization of each program in the +Common UNIX Printing System ("CUPS") Version 1.1.

+ +

For the purposes of comparison, all figures are for the Linux Intel +platform. Memory utilization on other platforms should be similar. + + + +

Document Overview

+ +

This software performance specification is organized into the +following sections:

+ +
    +
  • 1 - Scope
  • +
  • 2 - References
  • +
  • 3 - Programs
  • +
  • 4 - Scheduler Objects
  • +
  • A - Glossary
  • +
+ + + +

Programs

+ +

The following table describes the average memory, disk, and CPU usage of +each program in CUPS. + +

The base memory column shows the initial memory requirements for each +program, including any shared libraries that are provided by CUPS. + +

The max memory column shows the maximum amount of memory that will be +used by the program based upon the default configuration settings supplied +with CUPS. + +

The temp files column indicates whether any temporary files are created. + +

The CPU usage column specifies a relative CPU usage by the program under +normal conditions, either low, medium, or high. Low usage indicates that +the program will never use more than 33% of the available CPU time. Medium +usage indicates the program will use as much as 66% of the available CPU +time. High usage indicates the program uses 66% or more of the available CPU +time. + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Backends
ProgramBase MemoryMax MemoryTemp FilesCPU Usage
ipp91k256kUp to size of print fileLow
lpd89k89kUp to size of print fileLow
parallel85k85kUp to size of print fileLow
serial85k85kUp to size of print fileLow
socket85k85kUp to size of print fileLow
usb85k85kUp to size of print fileLow
CGIs
ProgramBase MemoryMax MemoryTemp FilesCPU Usage
admin.cgi107k256kUp to size of PPD fileMedium
classes.cgi95kSize of class objectsNoneMedium
jobs.cgi93kSize of job objectsNoneMedium
printers.cgi95kSize of printer objectsNoneMedium
Command-Line Programs
ProgramBase MemoryMax MemoryTemp FilesCPU Usage
accept88k128kNoneLow
cancel88k128kNoneLow
disable88k128kNoneLow
enable88k128kNoneLow
lp90k256kNoneLow
lpadmin148k256kNoneLow
lpc86kSize of job and printer objectsNoneMedium
lpinfo89kSize of device and PPD objectsNoneMedium
lpmove88k128kNoneLow
lpoptions89k128kNoneLow
lppasswd90k90kNoneLow
lpq87kSize of job objectsNoneMedium
lpr87k256kNoneLow
lprm84k128kNoneLow
lpstat119kSize of job, printer, and class objectsNoneMedium
reject88k128kNoneLow
Daemons
ProgramBase MemoryMax MemoryTemp FilesCPU Usage
cups-lpd92k256kOne file per control or data file from clientLow
cupsd308kSee Scheduler RequirementsSee Scheduler RequirementsMedium
cups-polld84kSize of printer and class objectsNoneLow
Filters
ProgramBase MemoryMax MemoryTemp FilesCPU Usage
hpgltops263k320kNoneMedium
imagetops628k10MSwap file for uncompressed image dataMedium
imagetoraster652k10MSwap file for uncompressed image dataHigh
pstops775k840kUp to size of print fileMedium
pstoraster4M14MSwap file for command listsHigh
rastertoepson693k1MNoneLow
rastertohp690k1MNoneLow
texttops638k4*cols*rowsNoneLow
+ + +

Scheduler Objects

+ +

The cupsd program is the CUPS scheduler process. It manages +many interdependent server objects that are used to manage and print files +to printers. + +

The following table provides the memory and disk cost associated with each +server object. + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ObjectMemory PerDisk Per
Browse ACL1k120
Browse Poll2480
Browse Relay2880
Certificate7632
Class9k200
Client13k-
Device256-
Job2k1k + size of document files
Location ACL1k120
MIME Filter26880
MIME Type34080
PPD200656
Printer11k32k
+ + + + + diff --git a/doc/ssr.html b/doc/ssr.html new file mode 100644 index 0000000000..91593a5f78 --- /dev/null +++ b/doc/ssr.html @@ -0,0 +1,270 @@ + + + + CUPS Software Security Report + + + + + + + +

+

CUPS Software Security Report


+CUPS-SSR-1.1
+Easy Software Products
+Copyright 1997-2000, 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.1.

+

1.2 System Overview

+

CUPS provides a portable printing layer for UNIX®-based 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 ("IPP") as the basis for +managing print jobs and queues. The Line Printer Daemon ("LPD") Server +Message Block ("SMB"), and AppSocket (a.k.a. JetDirect) protocols are +also supported with reduced functionality. CUPS adds network printer +browsing and PostScript Printer Description ("PPD") based printing +options to support real-world printing under UNIX.

+

CUPS also includes a customized version of GNU Ghostscript +(currently based off GNU Ghostscript 5.50) and an image file RIP that +are used to support non-PostScript printers. Sample drivers for HP and +EPSON printers are included that use these filters.

+

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.1: CUPS Configuration Management Plan
  • +
  • CUPS-IDD-1.1: CUPS System Interface Design Description
  • +
  • CUPS-IPP-1.1: CUPS Implementation of IPP
  • +
  • CUPS-SAM-1.1.x: CUPS Software Administrators Manual
  • +
  • CUPS-SDD-1.1: CUPS Software Design Description
  • +
  • CUPS-SPM-1.1.x: 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: CUPS Software Version Description
  • +
+

2.2 Other Documents

+

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

+ +

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 is one known security vulnerability with local access:

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

    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 distributed 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 supports Basic, Digest, and local +certificate authentication:

+
    +
  1. Basic authentication 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.
  2. +
  3. Digest authentication uses an MD5 checksum of the username, + password, and domain ("CUPS"), so the original username and password +is not sent over the network. However, the current implementation does +not authenticate the entire message and uses the client's IP address +for the nonce value, making it possible to launch "man in the middle" +and replay attacks from the same client. The next minor release of +CUPS will support Digest authentication of the entire message body, +effectively stopping these methods of attack.
  4. +
  5. Local certificate authentication passes 128-bit "certificates" +that identify an authenticated user. Certificates are created +on-the-fly from random data and stored in files under +/etc/cups/certs. They have restricted read permissions: root + +system for the root certificate, and lp + system for CGI certificates. +Because certificates are only available on the local system, the CUPS + server does not accept local authentication unless the client is +connected to the localhost address (127.0.0.1.)
  6. +
+

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. Also, we highly recommend using Digest +authentication when possible. Unfortunately, most web browsers do not +support Digest authentication at this time.

+

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 Page 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
+
PPD
+
PostScript Printer Description
+
SMB
+
Server Message Block
+
TFTP
+
Trivial File Transfer Protocol
+
+ + diff --git a/doc/ssr.pdf b/doc/ssr.pdf new file mode 100644 index 0000000000..58a13b866f Binary files /dev/null and b/doc/ssr.pdf differ diff --git a/doc/ssr.shtml b/doc/ssr.shtml new file mode 100644 index 0000000000..a192cdad47 --- /dev/null +++ b/doc/ssr.shtml @@ -0,0 +1,167 @@ + + + + + + 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.

+ + + +

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

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 is one known security vulnerability with local access: + +

    + +
  1. 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 distributed + 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 supports Basic, Digest, and local certificate +authentication: + +

    + +
  1. Basic authentication 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. + +
  2. Digest authentication uses an MD5 checksum of the username, + password, and domain ("CUPS"), so the original username and + password is not sent over the network. However, the current + implementation does not authenticate the entire message and + uses the client's IP address for the nonce value, making it + possible to launch "man in the middle" and replay attacks from + the same client. The next minor release of CUPS will support + Digest authentication of the entire message body, effectively + stopping these methods of attack. + +
  3. Local certificate authentication passes 128-bit + "certificates" that identify an authenticated user. + Certificates are created on-the-fly from random data and stored + in files under /etc/cups/certs. They have + restricted read permissions: root + system for the root + certificate, and lp + system for CGI certificates. Because + certificates are only available on the local system, the CUPS + server does not accept local authentication unless the client + is connected to the localhost address (127.0.0.1.) + +
+ +

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. + +Also, we highly recommend using Digest authentication when possible. +Unfortunately, most web browsers do not support Digest authentication +at this time. + + + + + diff --git a/doc/stp.html b/doc/stp.html new file mode 100644 index 0000000000..5503243a3a --- /dev/null +++ b/doc/stp.html @@ -0,0 +1,174 @@ + + + + DRAFT - CUPS Software Test Plan + + + + + + + +


+

DRAFT - CUPS Software Test Plan


+CUPS-STP-1.1
+Easy Software Products
+Copyright 1997-2000, 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.1.

+

1.2 System Overview

+

CUPS provides a portable printing layer for UNIX®-based 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 ("IPP") as the basis for +managing print jobs and queues. The Line Printer Daemon ("LPD") Server +Message Block ("SMB"), and AppSocket (a.k.a. JetDirect) protocols are +also supported with reduced functionality. CUPS adds network printer +browsing and PostScript Printer Description ("PPD") based printing +options to support real-world printing under UNIX.

+

CUPS also includes a customized version of GNU Ghostscript +(currently based off GNU Ghostscript 5.50) and an image file RIP that +are used to support non-PostScript printers. Sample drivers for HP and +EPSON printers are included that use these filters.

+

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.1: CUPS Configuration Management Plan
  • +
  • CUPS-IDD-1.1: CUPS System Interface Design Description
  • +
  • CUPS-IPP-1.1: CUPS Implementation of IPP
  • +
  • CUPS-SAM-1.1.x: CUPS Software Administrators Manual
  • +
  • CUPS-SDD-1.1: CUPS Software Design Description
  • +
  • CUPS-SPM-1.1.x: 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: CUPS Software Version Description
  • +
+

2.2 Other Documents

+

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

+ +

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 Page 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
+
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 0000000000..58e9daf191 Binary files /dev/null and b/doc/stp.pdf differ diff --git a/doc/stp.shtml b/doc/stp.shtml new file mode 100644 index 0000000000..729a8f6412 --- /dev/null +++ b/doc/stp.shtml @@ -0,0 +1,47 @@ + + + + + + + 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. + + + +

Document Overview

+ +

This software test plan is organized into the following sections: + +

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

Local Tests

+ + + + +

Remote Tests

+ + + + + + + + diff --git a/doc/sum.html b/doc/sum.html new file mode 100644 index 0000000000..606705add4 --- /dev/null +++ b/doc/sum.html @@ -0,0 +1,2079 @@ + + + + CUPS Software Users Manual + + + + + + + +

+

CUPS Software Users Manual


+CUPS-SUM-1.1.5
+Easy Software Products
+Copyright 1997-2000, All Rights Reserved
+
+
+

Table of Contents

+

+

Preface + +1 - Printing System Overview + +2 - Using the Printing System + + +3 - Standard Printer Options + + +4 - Saving Printer Options +and Defaults + +A - Software License Agreement + +
+

Preface

+

This software users manual describes how to use +the Common UNIX Printing SystemTM ("CUPS +TM") Version 1.1.5.

+

System Overview

+

CUPS provides a portable printing layer for +UNIX®-based 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 ("IPP") +as the basis for managing print jobs and +queues. The Line Printer Daemon ("LPD") Server +Message Block ("SMB"), and AppSocket (a.k.a. +JetDirect) protocols are also supported with reduced +functionality. CUPS adds network printer browsing and +PostScript Printer Description ("PPD") based printing +options to support real-world printing under UNIX.

+

CUPS also includes a customized version of GNU +Ghostscript (currently based off GNU Ghostscript +5.50) and an image file RIP that are used to +support non-PostScript printers. Sample drivers for +HP and EPSON printers are included that use +these filters.

+ + + +

Document Overview

+

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

+ +

Notation Conventions

+

Various font and syntax conventions are used in +this guide. Examples and their meanings and uses +are explained below: +

+ + + + + + + + + + + + +
Example   Description
 
lpstat +

lpstat(1)
   The names +of commands; the first mention of a command or + function in a chapter is followed by a manual +page section number.
 
/var +

/usr/share/cups/data/testprint.ps
    +File and directory names.
 
Request ID is Printer-123 +   Screen output.
 
lp -d printer filename +ENTER   Literal user input; +special keys like ENTER are in ALL +CAPS.
 
12.3   Numbers in +the text are written using the period (.) to +indicate the decimal point.
+
+ + +

+

Abbreviations

+ The following abbreviations are used throughout this +manual: +
    +
    +
    kb
    +
    Kilobytes, or 1024 bytes +

     
    +
    Mb
    +
    Megabytes, or 1048576 bytes +

     
    +
    Gb
    +
    Gigabytes, or 1073741824 bytes +

     
    +
    +
+

Other References

+
    +
    +
    CUPS Software Administrators Manual
    +
    An administration guide for the CUPS software. +

     
    +
    CUPS Software Programmers Manual
    +
    A programmer guide for interfacing with and/or +extending the CUPS software. +

     
    +
    +
+

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 Mac OS, UNIX +has no standard interface or system in place +for supporting printers. Among the solutions +currently 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 and operating systems 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.

+

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. IPP +has been embraced by dozens of printer and +printer server manufacturers and is supported by +Microsoft Windows 2000.

+

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 capable and secure printing solution than +older ones.

+

IPP is layered on top of the Hyper-Text +Transport Protocol ("HTTP") which is the basis of +web servers on the Internet. This allows users +to view documentation, check status information on +a printer or server, and manage their printers, +classes, and jobs using their web browser.

+

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

+

Jobs

+

Each file or set of files 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.

+

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 Processor ("RIP") filters +that convert PostScript or image files into +bitmaps that can be sent to a raster printer. +

+

Backends

+

Backends perform the most important task of all +- they send the filtered print data to the +printer.

+

CUPS provides backends for printing over parallel, +serial, and USB ports, and over the network via +the IPP, JetDirect (AppSocket), and Line Printer +Daemon ("LPD") protocols. Additional backends are +available in network service packages such as the +SMB backend included with the popular SAMBA +software.

+

Backends are also used to determine the +available devices. On startup each backend is +asked for a list of devices it supports, and +any information that is available. This allows the +parallel backend to tell CUPS that an EPSON +Stylus Color 600 printer is attached to parallel +port 1, for example.

+

Printer Drivers

+

Printer drivers in CUPS consist of one of +more filters specific to a printer. CUPS includes +sample printer drivers for Hewlett-Packard LaserJet +and DeskJet printers and EPSON 9-pin, 24-pin, +Stylus Color, and Stylus Photo printers. While +these drivers do not generate optimal output for +the different printer models, they do provide +basic printing and 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. Users may then select a local printer +by name or a remote printer using "name@server". +

+

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 go 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(1) +) and Berkeley (lpr(1)) printing +commands. Type the following command to print a +file to the default (or only) printer on the +system:

+
    +
    +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, +serial, or USB port, or available over the +network.

+

Use the lpstat(1) command to see a +list of available printers:

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

+

Use the -d option with the lp + command to print to a specific printer:

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

or the -P option with 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 and lpr commands +allow you to pass printer options using the +-o option:

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

The available printer options vary depending on +the printer. The standard options are described in Chapter 3, "Standard Printing +Options".

+

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. +Use the -o Collate=True option to get +collated copies :

+
    +
    +lp -n num-copies -o Collate=True filename ENTER
    +lpr -#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. Use the -p option to see +which files and printers are active:

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

Use the -o and -p options +together to show the jobs and the printers:

+
    +
    +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 fully-functional web server. To +use your web browser to monitor the printers on +your system, open the URL:

+ +

From there you can view the status of +classes, jobs, and printers with the click of a +button!

+

Canceling a Print Job

+

The cancel(1) and lprm(1) + commands cancel a print job:

+
    +
    +cancel job-id ENTER
    +lprm job-id ENTER
    +
    +
+

The job-id is the 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 and lpr commands.

+

General Options

+

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

+

Setting the Orientation

+

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

+
    +
    +lp -o landscape filename ENTER
    +lpr -o landscape filename ENTER
    +
    +
+ + + +

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
    +lpr -o media=Letter,Transparency filename ENTER
    +lpr -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 not 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.

+

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 -o sides=two-sided-short-edge option +is suitable for landscape pages, while the +-o sides=two-sided-long-edge option is suitable +for portrait pages:

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

The default is to print single-sided:

+
    +
    +lp -o sides=one-sided filename ENTER
    +lpr -o sides=one-sided filename ENTER
    +
    +
+

Banner Options

+

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

+

Selecting the Banner Page(s)

+

The -o jobsheets=start,end option sets +the banner page(s) to use for a job:

+
    +
    +lp -o job-sheets=none filename ENTER
    +lp -o job-sheets=standard filename ENTER
    +lpr -o job-sheets=classified,classified filename ENTER
    +
    +
+

If only one banner file is specified, it +will be printed before the files in the job. +If a second banner file is specified, it is +printed after the files in the job.

+

The available banner pages depend on the local +system configuration; CUPS includes the following +banner files:

+
    +
  • none - Do not produce a banner +page.
  • +
  • classified - A banner page with a +"classified" label at the top and bottom.
  • +
  • confidential - A banner page with a + "confidential" label at the top and bottom.
  • +
  • secret - A banner page with a +"secret" label at the top and bottom.
  • +
  • standard - A banner page with no +label at the top and bottom.
  • +
  • topsecret - A banner page with a +"top secret" label at the top and bottom.
  • +
  • unclassified - A banner page with an + "unclassified" label at the top and bottom.
  • +
+

Document Options

+

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

+

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
    +lpr -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-ranges option.

+

The default is to print all pages.

+

Selecting Even or Odd Pages

+

Use the -o page-set=set option to +select the even or odd pages:

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

The default is to print all pages.

+

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

+

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=10 filename ENTER
    +lp -o cpi=12 filename ENTER
    +lpr -o cpi=17 filename ENTER
    +
    +
+

The default characters per inch is 10.

+

Setting the Number of Lines Per +Inch

+

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

+
    +
    +lp -o lpi=6 filename ENTER
    +lpr -o lpi=8 filename ENTER
    +
    +
+

The default lines per inch is 6.

+

Setting the Number of Columns

+

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

+
    +
    +lp -o columns=2 filename ENTER
    +lpr -o columns=3 filename ENTER
    +
    +
+

The default number of columns is 1.

+

Setting the Page Margins

+

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

+
    +
    +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
    +lpr -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
    +lpr -o prettyprint filename ENTER
    +
    +
+

Image Options

+

The following options apply when printing image +files.

+

Positioning the Image

+

The -o position=name option specifies +the position of the image on the page:

+
    +
  • center - Center the image on the +page (default)
  • +
  • top - Print the image centered at +the top of the page
  • +
  • left - Print the image centered on +the left of page
  • +
  • right - Print the image centered on +the right of the page
  • +
  • top-left - Print the image at the +top left corner of the page
  • +
  • top-right - Print the image at the +top right corner of the page
  • +
  • bottom - Print the image centered at +the bottom of the page
  • +
  • bottom-left - Print the image at the +bottom left corner of the page
  • +
  • bottom-right - Print the image at +the bottom right corner of the page
  • +
+

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
    +lpr -o ppi=value filename ENTER
    +
    +
+

The percent value 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
    +lpr -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
+
+

+

The default hue adjustment is 0.

+

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

+

The default saturation is 100. + +

+

HP-GL/2 Options

+

The following options apply to HP-GL/2 files.

+

Printing in Black

+

The -o blackplot option specifies that +all pens should plot in black:

+
    +
    +lp -o blackplot filename ENTER
    +lpr -o blackplot filename ENTER
    +
    +
+

The default is to use the colors defined in +the plot file or the standard pen colors +defined in the HP-GL/2 reference manual from +Hewlett Packard.

+

Fitting the Plot on the Page

+

The -o fitplot option specifies that +the plot should be scaled to fit on the +page:

+
    +
    +lp -o fitplot filename ENTER
    +lpr -o fitplot filename ENTER
    +
    +
+

The default is to use the absolute distances +specified in the plot file. +

+ + +
NOTE: +

This feature depends upon an accurate plot size +(PS) command in the HP-GL/2 file. +If no plot size is given in the file than +the HP-GL/2 filter assumes the plot is ANSI E +size.

+
+
+

+

Setting the Default Pen Width

+

The -o penwidth=value option specifies +the default pen width for HP-GL/2 files:

+
    +
    +lp -o penwidth=value filename ENTER
    +lpr -o penwidth=value filename ENTER
    +
    +
+

The pen width value specifies the pen +width in micrometers. The default value of 1000 +produces lines that are 1 millimeter in width. +Specifying a pen width of 0 produces lines that +are exactly 1 pixel wide. +

+ + +
NOTE: +

This option is ignored when the pen widths +are set in the plot file.

+
+
+

+

Raw or Unfiltered Output

+

The -o raw option allows you to +send files directly to a printer without +filtering. This is sometimes required when printing +from applications that provide their own "printer +drivers" for your printer:

+
    +
    +lp -o raw filename ENTER
    +lpr -o raw filename ENTER
    +
    +
+

The -l option can also be used +with the lpr command to send files +directly to a printer:

+
    +
    +lpr -l filename ENTER
    +
    +
+

4 - Saving Printer +Options and Defaults

+

This chapter describes how to save printer +options for your printer and set your own +default printer.

+

Printer Options

+

Each printer supports a large number of +options, which you learned about in +Chapter 3, "Standard Printer Options". Rather +than specifying these options each time you print +a file, CUPS allows you to save them as +"default" options for the printer.

+

The lpoptions(1) command saves the +options for your printers. Like the lp + and lpr commands, it accepts printer +options using the -o argument:

+
    +
    +lpoptions -o media=A4 -o sides=two-sided-long-edge ENTER
    +lpoptions -o media=Legal -o scaling=100 ENTER
    +
    +
+

Once saved, any lp or lpr + command will use them when you print.

+

Setting Options for a Specific Printer +

+

The previous example shows how to set the +options for the default printer. The -p +printer option specifies the options are for +another printer:

+
    +
    +lpoptions -p laserjet -o media=A4 -o sides=two-sided-long-edge ENTER
    +lpoptions -p deskjet -o media=Legal -o scaling=100 ENTER
    +
    +
+

Viewing the Current Defaults

+

The lpoptions command can also be +used to show the current options by not +specifying any new options on the command-line:

+
    +
    +lpoptions ENTER
    +media=A4 sides=two-sided-long-edge
    +lpoptions -p deskjet ENTER
    +media=Legal scaling=100
    +
    +
+

Setting the Default Printer

+

The administrator normally will set a system-wide +default printer that is normally used as the +default printer by everyone. Use the -d +printer option to set your own default +printer:

+
    +
    +lpoptions -d deskjet ENTER
    +
    +
+

The printer can be local (deskjet) +or remote (deskjet@server).

+

Printer Instances

+

Besides setting options for each print queue, +CUPS supports printer instances which allow +you to define several different sets of options +for each printer. You specify a printer instance +using the slash (/) character:

+
    +
    +lpoptions -p laserjet/duplex -o sides=two-sided-long-edge ENTER
    +lpoptions -p laserjet/legal -o media=Legal ENTER
    +
    +
+

The lp and lpr commands also +understand this notation:

+
    +
    +lp -d laserjet/duplex filename ENTER
    +lpr -P laserjet/legal filename ENTER
    +
    +
+

Removing Instances

+

Use the -x printer/instance option to +remove a printer instance that you no longer +need:

+
    +
    +lpoptions -x laserjet ENTER
    +lpoptions -x laserjet/duplex ENTER
    +lpoptions -x laserjet/legal ENTER
    +
    +
+

The -x option only removes the +default options for that printer and instance; the +original print queue will remain until deleted +with the lpadmin(8) command by the +administrator.

+

A - Software License +Agreement

+

Common UNIX Printing System +License Agreement

+

Copyright 1997-2000 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, +("CUPSTM"), is provided under the GNU +General Public License ("GPL") and GNU Library +General Public License ("LGPL"), Version 2. A copy +of these licenses follow this introduction.

+

The GNU LGPL applies to the CUPS API +library, located in the "cups" subdirectory of the +CUPS source distribution and in the +"/usr/include/cups" directory and "libcups.a", +"libcups.sl", or "libcups.so" files in the binary +distributions.

+

The GNU GPL applies to the remainder of the +CUPS distribution, including the "pstoraster" filter +which is based upon GNU Ghostscript 5.50 and +the "pdftops" filter which is based upon Xpdf +0.90.

+

For those not familiar with the GNU GPL, the +license basically allows you to:

+
    +
  • Use the CUPS software at no charge.
  • +
  • Distribute verbatim copies of the software in +source or binary form.
  • +
  • Sell verbatim copies of the software for a +media fee, or sell support for the software.
  • +
  • Distribute or sell printer drivers and filters +that use CUPS so long as source code is +made available under the GPL.
  • +
+

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 must provide source for any new +drivers, changes, or additions to the software, +and all code must be provided under the GPL +or LGPL as appropriate.

+

The GNU LGPL relaxes the "link-to" restriction, +allowing you to develop applications that use the +CUPS API library under other licenses and/or +conditions as appropriate for your application.

+

Trademarks

+

Easy Software Products has trademarked the Common +UNIX Printing System, CUPS, and CUPS logo. These +names and logos may be used freely in any +direct port or binary distribution of CUPS. To +use them in derivative products, please contract +Easy Software Products for written permission. Our +intention is to protect the value of these +trademarks and ensure that any derivative product +meets the same high-quality standards as the +original.

+

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, additions, and +modifications to CUPS under the GNU GPL and +LGPL. For information please contact us at the +address shown above.

+

The Common UNIX Printing System provides a +"pstoraster" filter that utilizes the GNU GhostScript +5.50 core 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 +

+

The "pdftops" filter is based on the Xpdf +0.90 software. For binary distribution licensing of +this software, please contact:

Derek B. +Noonburg +

Email: +derekn@foolabs.com +

WWW: +http://www.foolabs.com/xpdf/

+

Support

+

Easy Software Products sells software support for +CUPS as well as a commercial printing product +based on CUPS called ESP Print Pro. You can +find out more at our web site:

+ + + + +

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

    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.

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

    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.

    +
  5. 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. +
    3. 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.
    4. +
    5. 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.)
    6. +
    +
  6. +

    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.

    +
  7. 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. +
    3. 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,
    4. +
    5. 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.)
    6. +
    +
  8. +

    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.

    +
  9. 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.
  10. +
  11. 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.
  12. +
  13. 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.
  14. +
  15. 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.
  16. +

    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.

    +
  17. 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.
  18. +
  19. 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.
  20. +

    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.

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

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

END OF TERMS AND CONDITIONS

+ + + +

GNU LIBRARY GENERAL PUBLIC LICENSE

+

Version 2, June 1991

+
+Copyright (C) 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.
+
+[This is the first released version of the library GPL.  It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+

Preamble

+

The licenses for most software are designed to +take away your freedom to share and change it. + By contrast, the GNU General Public Licenses are +intended to guarantee your freedom to share and +change free software--to make sure the software is +free for all its users.

+

This license, the Library General Public License, +applies to some specially designated Free Software +Foundation software, and to any other libraries +whose authors decide to use it. You can use +it for your libraries, 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 +library, or if you modify it.

+

For example, if you distribute copies of the +library, whether gratis or for a fee, you must +give the recipients all the rights that we gave +you. You must make sure that they, too, +receive or can get the source code. If you +link a program with the library, you must +provide complete object files to the recipients so +that they can relink them with the library, +after making changes to the library and +recompiling it. And you must show them these +terms so they know their rights.

+

Our method of protecting your rights has two +steps: (1) copyright the library, and (2) offer +you this license which gives you legal permission +to copy, distribute and/or modify the library.

+

Also, for each distributor's protection, we want +to make certain that everyone understands that +there is no warranty for this free library. If +the library is modified by someone else and +passed on, we want its recipients to know that +what they have is not the original version, 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 companies distributing free software will +individually obtain patent licenses, thus in effect +transforming the program into proprietary software. + To prevent this, we have made it clear that +any patent must be licensed for everyone's free +use or not licensed at all.

+

Most GNU software, including some libraries, is +covered by the ordinary GNU General Public +License, which was designed for utility programs. + This license, the GNU Library General Public +License, applies to certain designated libraries. + This license is quite different from the ordinary +one; be sure to read it in full, and don't +assume that anything in it is the same as in +the ordinary license.

+

The reason we have a separate public license +for some libraries is that they blur the +distinction we usually make between modifying or +adding to a program and simply using it. + Linking a program with a library, without +changing the library, is in some sense simply +using the library, and is analogous to running +a utility program or application program. However, +in a textual and legal sense, the linked +executable is a combined work, a derivative of +the original library, and the ordinary General +Public License treats it as such.

+

Because of this blurred distinction, using the +ordinary General Public License for libraries did +not effectively promote software sharing, because +most developers did not use the libraries. We +concluded that weaker conditions might promote +sharing better.

+

However, unrestricted linking of non-free programs +would deprive the users of those programs of +all benefit from the free status of the +libraries themselves. This Library General Public +License is intended to permit developers of +non-free programs to use free libraries, while +preserving your freedom as a user of such +programs to change the free libraries that are +incorporated in them. (We have not seen how to +achieve this as regards changes in header files, +but we have achieved it as regards changes in +the actual functions of the Library.) The hope +is that this will lead to faster development of +free libraries.

+

The precise terms and conditions for copying, +distribution and modification follow. Pay close +attention to the difference between a "work based +on the library" and a "work that uses the +library". The former contains code derived from +the library, while the latter only works together +with the library.

+

Note that it is possible for a library to +be covered by the ordinary General Public License +rather than by this special one.

+

TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION +AND MODIFICATION

+

0. This License Agreement applies to +any software library which contains a notice +placed by the copyright holder or other authorized +party saying it may be distributed under the +terms of this Library General Public License (also +called "this License"). Each licensee is addressed +as "you".

+

A "library" means a collection of software +functions and/or data prepared so as to be +conveniently linked with application programs (which +use some of those functions and data) to form +executables.

+

The "Library", below, refers to any such +software library or work which has been +distributed under these terms. A "work based on +the Library" means either the Library or any +derivative work under copyright law: that is to +say, a work containing the Library or a portion +of it, either verbatim or with modifications +and/or translated straightforwardly into another +language. (Hereinafter, translation is included without +limitation in the term "modification".)

+

"Source code" for a work means the preferred +form of the work for making modifications to +it. For a library, 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 library.

+

Activities other than copying, distribution and +modification are not covered by this License; they +are outside its scope. The act of running a +program using the Library is not restricted, and +output from such a program is covered only if +its contents constitute a work based on the +Library (independent of the use of the Library +in a tool for writing it). Whether that is +true depends on what the Library does and what +the program that uses the Library does.

+

1. You may copy and distribute +verbatim copies of the Library's complete 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 distribute a copy +of this License along with the Library.

+

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.

+

2. You may modify your copy or +copies of the Library or any portion of it, +thus forming a work based on the Library, 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. The modified work must itself be a software +library.
  2. +

    +
  3. You must cause the files modified to carry +prominent notices stating that you changed the +files and the date of any change.
  4. +

    +
  5. You must cause the whole of the work to +be licensed at no charge to all third parties +under the terms of this License.
  6. +

    +
  7. If a facility in the modified Library refers +to a function or a table of data to be +supplied by an application program that uses the +facility, other than as an argument passed when +the facility is invoked, then you must make a +good faith effort to ensure that, in the event +an application does not supply such function or + table, the facility still operates, and performs +whatever part of its purpose remains meaningful.
  8. +

    (For example, a function in a library to +compute square roots has a purpose that is +entirely well-defined independent of the application. + Therefore, Subsection 2d requires that any + application-supplied function or table used by this +function must be optional: if the application +does not supply it, the square root function +must still compute square roots.)

    +
+

These requirements apply to the modified work +as a whole. If identifiable sections of that +work are not derived from the Library, 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 Library, 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 +Library.

+

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

+

3. You may opt to apply the +terms of the ordinary GNU General Public License +instead of this License to a given copy of +the Library. To do this, you must alter all +the notices that refer to this License, so that +they refer to the ordinary GNU General Public +License, version 2, instead of to this License. + (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, +then you can specify that version instead if +you wish.) Do not make any other change in +these notices.

+

Once this change is made in a given copy, +it is irreversible for that copy, so the +ordinary GNU General Public License applies to all +subsequent copies and derivative works made from +that copy.

+

This option is useful when you wish to copy +part of the code of the Library into a +program that is not a library.

+

4. You may copy and distribute +the Library (or a portion or derivative of it, +under Section 2) in object code or executable +form under the terms of Sections 1 and 2 +above provided that you 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.

+

If distribution of 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 satisfies the requirement +to distribute the source code, even though third +parties are not compelled to copy the source +along with the object code.

+

5. A program that contains no +derivative of any portion of the Library, but +is designed to work with the Library by being +compiled or linked with it, is called a "work +that uses the Library". Such a work, in +isolation, is not a derivative work of the +Library, and therefore falls outside the scope of +this License.

+

However, linking a "work that uses the Library" +with the Library creates an executable that is +a derivative of the Library (because it contains +portions of the Library), rather than a "work +that uses the library". The executable is +therefore covered by this License. Section 6 +states terms for distribution of such executables.

+

When a "work that uses the Library" uses +material from a header file that is part of +the Library, the object code for the work may +be a derivative work of the Library even though +the source code is not. Whether this is true +is especially significant if the work can be +linked without the Library, or if the work is +itself a library. The threshold for this to be +true is not precisely defined by law.

+

If such an object file uses only numerical +parameters, data structure layouts and accessors, and +small macros and small inline functions (ten lines +or less in length), then the use of the +object file is unrestricted, regardless of whether +it is legally a derivative work. (Executables +containing this object code plus portions of the +Library will still fall under Section 6.)

+

Otherwise, if the work is a derivative of +the Library, you may distribute the object code +for the work under the terms of Section 6. +Any executables containing that work also fall +under Section 6, whether or not they are linked +directly with the Library itself.

+

6. As an exception to the +Sections above, you may also compile or link a +"work that uses the Library" with the Library +to produce a work containing portions of the +Library, and distribute that work under terms of +your choice, provided that the terms permit +modification of the work for the customer's own +use and reverse engineering for debugging such +modifications.

+

You must give prominent notice with each copy +of the work that the Library is used in it +and that the Library and its use are covered +by this License. You must supply a copy of +this License. If the work during execution +displays copyright notices, you must include the +copyright notice for the Library among them, as +well as a reference directing the user to the +copy of this License. Also, you must do one +of these things:

+
    +
  1. Accompany the work with the complete +corresponding machine-readable source code for the +Library including whatever changes were used in +the work (which must be distributed under + Sections 1 and 2 above); and, if the work +is an executable linked with the Library, with +the complete machine-readable "work that uses the +Library", as object code and/or source code, so +that the user can modify the Library and then +relink to produce a modified executable containing +the modified Library. (It is understood that the +user who changes the contents of definitions files +in the Library will not necessarily be able to +recompile the application to use the modified +definitions.)
  2. +

    +
  3. Accompany the work with a written offer, valid +for at least three years, to give the same +user the materials specified in Subsection 6a, +above, for a charge no more than the cost +of performing this distribution.
  4. +

    +
  5. If distribution of the work is made by +offering access to copy from a designated place, +offer equivalent access to copy the above + specified materials from the same place.
  6. +

    +
  7. Verify that the user has already received a +copy of these materials or that you have +already sent this user a copy.
  8. +
+

For an executable, the required form of the +"work that uses the Library" must include any +data and utility programs needed for reproducing +the executable from it. 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.

+

It may happen that this requirement contradicts +the license restrictions of other proprietary +libraries that do not normally accompany the +operating system. Such a contradiction means you +cannot use both them and the Library together +in an executable that you distribute.

+

7. You may place library facilities +that are a work based on the Library +side-by-side in a single library together with +other library facilities not covered by this +License, and distribute such a combined library, +provided that the separate distribution of the +work based on the Library and of the other +library facilities is otherwise permitted, and +provided that you do these two things:

+
    +
  1. Accompany the combined library with a copy of +the same work based on the Library, uncombined +with any other library facilities. This must be +distributed under the terms of the Sections +above.
  2. +

    +
  3. Give prominent notice with the combined library +of the fact that part of it is a work +based on the Library, and explaining where to +find the accompanying uncombined form of the same +work.
  4. +
+

8. You may not copy, modify, +sublicense, link with, or distribute the Library +except as expressly provided under this License. + Any attempt otherwise to copy, modify, sublicense, +link with, or distribute the Library 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.

+

9. 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 Library or its derivative +works. These actions are prohibited by law if +you do not accept this License. Therefore, by +modifying or distributing the Library (or any work +based on the Library), you indicate your +acceptance of this License to do so, and all +its terms and conditions for copying, distributing +or modifying the Library or works based on it. +

+

10. Each time you redistribute the +Library (or any work based on the Library), the +recipient automatically receives a license from the +original licensor to copy, distribute, link with +or modify the Library 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.

+

11. 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 Library at +all. For example, if a patent license would +not permit royalty-free redistribution of the Library +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 +Library.

+

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.

+

12. If the distribution and/or use +of the Library is restricted in certain countries +either by patents or by copyrighted interfaces, +the original copyright holder who places the +Library 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.

+

13. The Free Software Foundation may +publish revised and/or new versions of the Library +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 Library 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 Library does not +specify a license version number, you may choose +any version ever published by the Free Software +Foundation.

+

14. If you wish to incorporate +parts of the Library into other free programs +whose distribution conditions are incompatible with +these, 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

+

15. BECAUSE THE LIBRARY IS LICENSED +FREE OF CHARGE, THERE IS NO WARRANTY FOR THE +LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE +LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE +COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE +LIBRARY "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 +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE +DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY +SERVICING, REPAIR OR CORRECTION.

+

16. 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 LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE +WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER +OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES.

+

END OF TERMS AND CONDITIONS

+ + diff --git a/doc/sum.pdf b/doc/sum.pdf new file mode 100644 index 0000000000..e82f8cfe01 --- /dev/null +++ b/doc/sum.pdf @@ -0,0 +1,1259 @@ +%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[15 0 R +17 0 R +18 0 R +]endobj +20 0 obj<>endobj +21 0 obj<>endobj +22 0 obj<>endobj +23 0 obj<>endobj +24 0 obj[20 0 R +21 0 R +22 0 R +23 0 R +]endobj +25 0 obj<>endobj +26 0 obj<>endobj +27 0 obj[25 0 R +26 0 R +]endobj +28 0 obj<>endobj +29 0 obj<>endobj +30 0 obj[29 0 R +]endobj +31 0 obj<>endobj +32 0 obj<>endobj +33 0 obj[31 0 R +32 0 R +]endobj +34 0 obj<>endobj +35 0 obj<>endobj +36 0 obj<>endobj +37 0 obj<>endobj +38 0 obj[35 0 R +37 0 R +]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[40 0 R +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<>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[49 0 R +50 0 R +51 0 R +52 0 R +53 0 R +54 0 R +55 0 R +56 0 R +57 0 R +58 0 R +59 0 R +60 0 R +61 0 R +62 0 R +63 0 R +64 0 R +65 0 R +66 0 R +67 0 R +68 0 R +69 0 R +70 0 R +71 0 R +72 0 R +73 0 R +74 0 R +75 0 R +76 0 R +77 0 R +78 0 R +79 0 R +80 0 R +81 0 R +82 0 R +83 0 R +84 0 R +85 0 R +86 0 R +87 0 R +88 0 R +89 0 R +90 0 R +91 0 R +92 0 R +93 0 R +]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[95 0 R +96 0 R +97 0 R +98 0 R +99 0 R +100 0 R +101 0 R +102 0 R +103 0 R +104 0 R +105 0 R +106 0 R +107 0 R +108 0 R +109 0 R +110 0 R +111 0 R +112 0 R +113 0 R +114 0 R +115 0 R +116 0 R +]endobj +118 0 obj<>endobj +119 0 obj<>endobj +120 0 obj<>endobj +121 0 obj<>endobj +122 0 obj<>endobj +123 0 obj<>endobj +124 0 obj<>endobj +125 0 obj<>endobj +126 0 obj<>endobj +127 0 obj<>endobj +128 0 obj<>endobj +129 0 obj<>endobj +130 0 obj<>endobj +131 0 obj<>endobj +132 0 obj<>endobj +133 0 obj<>endobj +134 0 obj<>endobj +135 0 obj<>endobj +136 0 obj<>endobj +137 0 obj<>endobj +138 0 obj<>endobj +139 0 obj<>endobj +140 0 obj<>endobj +141 0 obj<>endobj +142 0 obj<>endobj +143 0 obj<>endobj +144 0 obj<>endobj +145 0 obj<>endobj +146 0 obj<>endobj +147 0 obj<>endobj +148 0 obj<>endobj +149 0 obj<>endobj +150 0 obj<>endobj +151 0 obj<>endobj +152 0 obj<>endobj +153 0 obj<>endobj +154 0 obj<>endobj +155 0 obj<>endobj +156 0 obj<>endobj +157 0 obj<>endobj +158 0 obj<>endobj +159 0 obj<>endobj +160 0 obj<>endobj +161 0 obj<>endobj +162 0 obj<>endobj +163 0 obj<>endobj +164 0 obj<>endobj +165 0 obj<>endobj +166 0 obj<>endobj +167 0 obj<>endobj +168 0 obj<>endobj +169 0 obj<>endobj +170 0 obj<>endobj +171 0 obj<>endobj +172 0 obj<>endobj +173 0 obj<>endobj +174 0 obj<>endobj +175 0 obj<>endobj +176 0 obj<>endobj +177 0 obj<>endobj +178 0 obj<>endobj +179 0 obj<>endobj +180 0 obj<>endobj +181 0 obj<>endobj +182 0 obj<>endobj +183 0 obj<>endobj +184 0 obj<>endobj +185 0 obj<>endobj +186 0 obj<>endobj +187 0 obj<>endobj +188 0 obj<>endobj +189 0 obj<>endobj +190 0 obj<>>>>>endobj +191 0 obj<>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ÎM‚0à=§˜¥&vì”"t©w$åDŠ?!bZÐp{©‰Ñí¼÷½ÌNëƒÁA·@œ#%ÐÍöU^Bٷë¶*g¬ƒ¬¾u·Ô·ÙI úº…(¼óŒ•UÆ #_e +c`bƒÒçií¦ßlnûf< îӓ!nþ†úÇd¯çˤTÌç|Û®ƒÂf~éiOSƒ7Þïbendstream +endobj +192 0 obj +6279 +endobj +193 0 obj<>>>endobj +194 0 obj<>stream +xÚ+ä2T0BCc3JÎår +ár á +äHÉHendstream +endobj +195 0 obj +31 +endobj +196 0 obj<>>>/Annots 19 0 R>>endobj +197 0 obj<>stream +xڍVMoÛ8½ûW zJ•*ɲ,ïm]§Y/šT[9E¾Ðm«¡D•¤lxýΐrüÑ$(‘æ‘óÞÌãÐ?!øÂ8‚aE=˜.>M +`±†8Œý1$ãåM¦øšüýâ"bCBxâ ãȏµØV´\›=S:͕†š5Pr]¨jÅ5l匤(˜-‡²®eóª1U³ü  ¯ÙRJ6§˜$öG6Ñý%“0B2.˛w³ürqêÇ¿±öÝò=ż8HW8t²¾¡Ž +9†~è|·zá˜V(?ÂÍæH×W»Šï w»~€U¦GH¯w'¡ŸB„ÏjˆSÊâÞä®Gn" àî¤ Z%w–´R¶¿õEìÀ¬¥²Å\F£Ä[1ÍK-WÌB´¥¨}˜Ø2 +Îl͎ Ĕ°:±¾¢¬6psËôáUAøQL%F9–Ò½šԟ5¤áóÒ^;½Núz”)Yv…Ñ—Ü‚#7r¦–†c]´aMÉTyª‹–¢3Ô?* ÂymǛR¢?íœêÃE‰m²“Ȫ}ƒ¿Ù5S®ž¸à(ÐÀøÁUÃSrE'EûýQâÔØÍ1‘¶®Ÿ®áædyid!ùwžehE`‹MÄcEä1ÛØjƒråøÿìx‡aèÏH㊻́֘1NG |Îf” G§â÷{®5Ûp˜ +Y :™ø“zºxaRãE> ©Ž!x×÷éEñ¤>Nj}ŒT@»,£d ®Wé1ÑEì¹,g¿ â4@vvUØ7àßÁÿÓ¸k\endstream +endobj +198 0 obj +973 +endobj +199 0 obj<>>>/Annots 24 0 R>>endobj +200 0 obj<>stream +xÚ­–KSã8Çï|Š>BÕÆ‰¿²sbxÕÖ2 Kž¸(¶´ø5’ äÛO·ä$Š µ5å*Û¿nuÿûáü8òa‚>LcúÏÊ£¯‹£‹ÅÑěàsºøt¹»Â·Þ┮%„¡t7Ìß  „húí%¤Á´”0K½pv€|Ì"Ä]ùx¶Ëšø¯¿(#×0¾ Á÷a±"ã4E~À֠9ÜJQiº™o”æåÉâ?ÇÍdç&ë܌/Å¢ ›‡ N€ð’$Òے˜›¡’t´U|€v9òüAÚP´€âÂ]‚DHòÿ ‘“)²¨ÏežkVåLæVe.á{£E]©ß«r4÷*››!•;ڊ8@;6~ìEƒ´ jþìç.|“æC¼C ŸD48C¼C”ø—8ü'ªOEýCª"{¦éÕ°´pÎW¬-ôo.hcðXИ¢67ït`A#êÔÚÌnòi Ý}€»òéԛ9ü'dQŸS¼^é&9\‹ŒWŠÃéZr^òJÿÇ—3ló2H±éFÓÀžtSkF•„³ºzFßÛÁÜÇ5A“ÄöÁ¿LŠºU°ª+m*¯6•f¯ím"nÏAT¸Z…‚u+rîÁÅ++›‚ÛŽÁ+$”œUØSöÚc“Œ|<<’¿6ú[ò¢~ùÓÆu±ùíŠÏ$ӝAŒ?›mE8ç*“Âô«µžlu +ªÐN‹¢Q(F/ûðáØ89Ô%ðCTe‹-ð+R±s¨W¨GYbNê‹ù¸¬„T}¯¥•‹`¶Å¡–°j«Ì¼UϱGÖÐè *@b(´Gã–=¾akŠ[oU[.¹ôll—¾É`—þø™Éž“q«äX=bYÆYÛ¨qÎ4k®tCkÀkԐ$—¢à¦´¹G-7V!¯_FÙ&»ã?Z<þ:§L»}3ÂJ¿u–)ð<ÃÁ@-[Ý´ºódÑÀ(‡¦Ûb+ ‘b‚‹›ÅÅÝ»\ „YA=ŠòWxÊP Ï>{â…xâ‡ç:"¾áû، NÈéõ5œÞÎMÔýXqa›¤HnL!•.š¿jãêE +­Qƒ–~ÒôŠH`Ãqrsx8öN@×hŸ‹Œin¼ä˜IùkÕTâþòˆC¿éÓ°ÛSË¥äς ¯ š Û±ôa®Í~]èGY·ëG,¢]¶©»y÷;C°g?-¤wÛØÿE½Ü`£þACåO‚Ìí¡·‘ëîۀ»o|Í\wa%ñ‡¯<^‰CÉ4 ýô0̝èI°ŸŽïX0 w|Å%¯²þùæøNõ³ûÛùþ#rš—¢JK†ƒ¨àÛneŒ/Óí2Ò¯vßZáù½âV#?N)0Ӕ=™¢e·pßû¦àÇþŸ£Ÿ€^3Ðendstream +endobj +201 0 obj +1068 +endobj +202 0 obj<>>>>>endobj +203 0 obj<>stream +xÚuASà „ïüŠ=ê!4$’µ£7:¥?€iHŠc +Ôúó…4:öàpïíîム”é´j‰ÃÄî[=6jȪìZ¨þ掠ûɒ Ñëha<ÙÞ`pñh°Ùownˆgí ¿U¯ÉE..Er.*ɛl4ƒ»ÄÖ»Ñëi2>àIÓI¿]F +äIQój®€÷_úOº¥hü –Fœm>>>>>endobj +206 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS04³P072PIÑPp VÎO+)O,JU-N-*VðMÌ+MÌÑ ÉâÒ)Յª5‰[êY(€ù~ù%‰%™ùy +Îùye©y f1H‰kW {!#Lendstream +endobj +207 0 obj +119 +endobj +208 0 obj<>>>>>endobj +209 0 obj<>stream +xڝUÁrÓ0½ç+öØÎ¤¦IKҁ4LRàЋb¯cQY2’œ¿ç­ì¤Áía:“iâÝ÷Þ¾}’&t‰¿ ͧt5£¼½]^}¸¥é%­J|β+šÍohUœMè‚^ۨ톖û¹¦»-û­æÝùê'Ú®i2‘¶‹®ïâêzšM¥uUé@y¥šÈžﶺà@ʒëûɕT¹Ŋ靫kgéþ˧ÏøvÎ?†¬c»¥É\Ø.A4Í®;~jYx·6\ÿ- ÅÓy6“âÎӞ•ԕÌú’3ÑPš—PΨR£6-IiF÷ÖèG¦Ï:÷.¸2>L_Ïè»¶…Û…ô?è>«œî–ãn6°N€!jrÕ9¢²…òž}©r–¾ÐM¯­pâ§R~k›Æù^cª½s›äbp¦ÚYøÞzÏ6š=©­ÒFaœ±” ˜ß²dè²ÅÁîoO>t°4Ï ¿v!â)o•xփMgÇE~ÞÜk&£-UÓÃYäߑœ5û‡swìeîuŸ‰¸WM¥óðp>Nßw:VC]͔;õ[wvì)GÚ֐­ +èwG%ŠÊÖòÊnXBxäàR›äu­"¼ýèvŒ¸Ž“«ã±Ê‡¼[å5ì$1)íÙ5ìՉ „^àS¡Ë’e3CŸÐ +±Òoe䬯5'‹¦Âk( rI…‚˜ðåy†JáX‚Âs͈‡ÒykbF«JEøW¯±¨Îà¤ÇèZG.†C#jubËÛá<èD‹øÓYp°E"'90ûütólÇ]XÌ“QۜÆ[ ”Óš‡¹{w¿XÊP¸^ôF¤‘EµU‘ÿãœgtg%HéF®©ÖYÐç9zAj?{8MÝ_̖¹â€ä /¦ÄM£vEk”—dJÉÓ%ð>'¤†g$Èq—™ç'e,ô„g±9M~·~£c4é2²°´Ä3Äd©-¸“é‡[}@¾v}tŽ7Šñx×M‹ñ$Œ;pÜ¥N5Ñ¹J÷®q³jàš-—âI:kzHlñR‰œWÖ·Ùw3@9^Bñð +¹yz+ÌçÙ?½å®o.³[4 ôµ|¿}ý üjºendstream +endobj +210 0 obj +836 +endobj +211 0 obj<>>>>>endobj +212 0 obj<>stream +xÚ}WMoÛ8¼çW<ô”¶»…““¦Ù¦H°ÞÚÁ^z¡)*f-‘*IÅëþúGJ²-ÄE$²È÷13oHÿ:›Ð%~&ôaÆ¿²:»]ž½¿ÿD“+Zx3»žÐ2?_®-•\[ڗÝÅò'}¤É$-O¯²/ûü<_ö´^åÔÔ֐0¤*å^´y¡”3*ÂäÂå$EYbe@øþåÜixùÜÙ`¥-3z˜Ïi-W)Ãɑrò!›rJU­œˆ±ÚQn+ãÉTs å=ïÿ÷ʽâO%LS§œ P°oêÚºÂ'ÿùì C^*:¶{ÇÜ»5\ÒùVôŽørqYDÄnqÐ$HÙ +í|‚ÒK²›nmââçt¯÷ºäjOöÚ¾O®Ã‚ðÉ8D]—ÝL¡¬t´Á3v`‡~/T¦È6`N*øÌÊÒ ùǾeÆu¨±t Gb%,LU°Ëc_Þ:OՊ­“ÒÂVÝú8Ì“u³c)×E`Ȝ¼±(ÄzûŒÂĈ€|îgô7Ÿqžàü:áŠZ!DYPæbÂoüŸí°«õh†ÑÔ§ˆ Œèë|ü×ãûi÷8¿»ïþǻ¢øœ½…i—˜ š[Òé:¤‹RŸ†¾ ϝ?ÄOpž±5¢>hßâyÖU¡ë`>ˆg‡ŽqÐä V:T¢î"¤[Ê^.ÐÑzR÷Bn †Ó"îôtñ`T(íò Ζg¾GyÁ.*¬¸VzIæ¹¢›ÅÃâNÒ»êòñ¯_0HöiÜu u-ÊÄàó▢»¤Çþ¢†[ÀÖº Î|‘.nóùh€ñ7AÔM]/,R‡)Ð#.¯iöðN¨ +ZŸó;泿±et“çš•Œ£µ/>ºûÁÉ7HÜÕÆ#«%Á>Ðí{kæ‚O·]@De“¸8Z®ãQ±¸yº½!¾žÃøTKüuËëdv¯,ŸÎQߘ÷´’žã¥è ×Qò®1/_M/yíŒ?ùxyñ¢7¿ð|Yžýsö?e&Yeendstream +endobj +213 0 obj +1446 +endobj +214 0 obj<>>>>>endobj +215 0 obj<>stream +xڅUێÛ6}÷WLóÒ-`k}YØÞ·`sAQ´‰‹uÐg®4Z±K‘*‡ZUßRRl¥AàY¼Ì9sÎÌèŸÅÖüÛÀa »=äõâἸýx› œKÞÙp.nTþ‚¶ PArÐÐ×Ú"„Š·^•6êÉ ¯¿ê)ƒÏ((ÚPå<¥P 9½pÒyP`4på/ç¿kXmvÙVp‡( PÛ4ÎZ‚âÛÊö -_­UÐÎ2¸ +1äH ƒs%ïÆ¸Ž"·Fy~C31`öw_N1À \Yøpzüü CoZ‚wÎ0Õýz ×–ÓŽ€!pVI‹ AˆÂfSÃUÝ0 ~ûñ6‡¤ìj·Íîæ4{ïõ+zJç¾:°Ú²ýå¹"ãôóÜYJâcøQ;v©Ô&È1j0ץ΅ ™g骶¹i ֗"ÇqwnÂ(ÙüŠÁV'ÖPù~W„þ7 є÷H/òCq1Ix¿j´]Âö.=/†Î ‡ýSåDÖ!\UÚÄB#œd(Xà-z8ÿ&èZpmhÚI‹û….Kôh'v¬R†–3d>ÛKÌÆ»W]  ±vñ޶Ï1£k–>>>>>endobj +218 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS04³P072PIÑPp VÎO+)O,JU-N-*VðMÌ+MÌÑ ÉâÒ)Յªµ‰˜šé™+€ùE™y%©E +.E™e@m Y×®@.ž!/endstream +endobj +219 0 obj +115 +endobj +220 0 obj<>>>>>endobj +221 0 obj<>stream +xڍ”MsÚ0†ïüŠíÌ`;=&“ÜÚI‹é‰‹°×±Yr$Æÿ¾»!MÒ3€Ì~¼ûì+'Ìé•Á2‡óTÝ䲜|½YA>‡²¡÷"Í`±¼€²žæÀÆI}¾E¸µR{>¬Gç±;+ï)¯€,ã¼$&&çEžæœ[¶ÒAՊޣךƒƒÑ @_Àpî“~ÚqB×P ]¡‚ž»À½Ù9Ž«eÓ Ezž£ui컂lÉ}çÔ2O î¸5ƒÂ©ÐAcìIôkµ”•/Óg]mn×TÜìeM);ãÛ0lœ~ÃvSçÇÔ©ê·Ól{öºàt{†¸Dû€ +Ç÷Òìyý×Êtq)”cAFc”2‡£~RGºÇPF hhf>sZ”'„Àh5>µA>†üåd°b5ä‡$/"MՇŠZt×?Êë_oöbAc?«bÿ·LXÄ kÚ±g +@Ž/ à‰‰ӄzŽ~°XyE摺RCÍoóëÊÊއeÈNÜa '¤ìGÁ4Ý–lËÇÆšŽ*:rûՂè{%+á¥ÑԝÎ>à;. QRã ­¬ZÜ]jґ +ú]ïQKþåCÃ^µÆ„Û%¢MÑ~èÒïÌ"®ÌÁA*­Ø#µ²ì¡i«xÚ°Ø ©ÄîÙƒCËН‚ß7Ø!Íãi¯±oØ(S ul {)Hj/,aD5ª*}•Íúzc}8<÷7Œ„hôcÒcù| l\´ù_w…,àß».ðÂøI=(I´ÉÏMŸ&ü̕\’’ú¥+/^¹²ˆèÿù'X\ÌÓ-‹bW|¾.'?'‰#©8endstream +endobj +222 0 obj +640 +endobj +223 0 obj<>>>/Annots 27 0 R>>endobj +224 0 obj<>stream +xÚ­WÛrÛ6}÷Wì$/êLÈòfQʌ×i§“´j¤|DB"`Ðý}wÁKt£lg2öȹ׳gwáÿnBð'„xJ¿YuóauóëÇÂV|3¥°Ê'«‚Ã/«G|t¯&^Ý>èe' j+”SóLl7` fa¯Ø1iÁ*0œƒR jµÒrmÞ“9 +Ÿ»ÈG\h^+mÓÉ­9š7{cyE +xaìGwÎ7¬)mï +”†¬dÆø\4õ’ûjø«Ø [\R(Ï@ÉTU¹ôT}a=FYØûV-„9ia%¼(i#+kðò!þ(¹d‡‡¿W_Ž}yNmJJ˜æ¥l¯ÎF¤s-^ ÞâjÀsÓ!àØÕiÉ­r ‹Ní˜9öNõJ}—àGÌãØƒÝ×H4$9B&QgEo¡ÂÖL³AäqfƒfŸ$ç¹ñáOµãO\;3šw +'”²¢B»‚KGmÒ¤šf“Û–D½?²Î fڊ¬)Y †SbhÜE‡9ŸRqõV£^\,¬,ÕÎy&"ÿϰi Á‰4ê2i®3VAIŽ3Vs:à—íߥ·tªx.ØÝoÉ@ÿ±Þö(þl ÑYyXÝ~€c>Búøò$q„ÌI‹XA’ø·=•°<zIµµ¦Z°'&J¶.ùfOLï‘l5—9‡DøuR>²±˜Óù C•ϹɴX#o„„ñˆb¤ˆgˆîQÄ'*z;$ÙE_°šâß:ÁÄó~¢‹©wòp!¢ïÌÿöªô@aûóq +s +óͲiѵDßþo)ËA—æÄ?ž#M‘–{ƒ…Ï8DE»W5®¢ÑAòA½t¿²å +öt< ú~‡JišL"cp}©zOó‹9_ï*Ù·¯'²©¼ì ¿NmraꞶÖÛ¶tqá´(;vK¥+œ7û.ÖiTö¬²dû ›Ã>Œía…ut²w+Ýð‘5†³mËíw«mBð“0=‰á'bü¼å‹;ó¾àÙ·~j÷‹{É6H8­*÷ü¾å£÷IH>ÚWŽ.;v™É¼¸IÓï>ŒÄñQ­®}®L³®„í«ÜwÁµ¢çÃ܃VèÞ.[/D‡…̇$‰Ò4ž”¡—‹¹ð6IŃTœF³$e;áå2%¾Óm¶ån÷뜻Ë×oUeI(µ !'w=Îgº0ï +‘íýÆ ¡þÚLÞOî&,³â‰?‹­W_‡·_t¿sóí/ì(‰—‡a|u½ÐÅg´‹_0SÇÐ@Z)ìî‚ÐE\ + Éeèþ}è‘é˜u&Âé ¦ó¤…î¿.–°T»£êa¨ˆäg&V’–GÂ^$ô(NiïÏ\Sq½þ{ó?søÊSendstream +endobj +225 0 obj +1066 +endobj +226 0 obj<>>>/Annots 30 0 R>>endobj +227 0 obj<>stream +xڕ”Ms›0†ïþۛ3bˆM“N3mǵÉô’‹Àr •Dÿûj%l'ŽsÈx†±¥ç]ïÇ»ü›ˆì‡@C2ƒª|-&·® ØàÉ,·ßÖSÞiC ‚n~7˳âɂ‘#HæH.T# S'Y‹µd¦q–e3œàâ=G.³ü#*ÙSIçi|„uƒoL?ß1BàÎñ¸; Hès¾’aҁ-/HbÔ_׬zFÖÔ Æÿ„•­¸×°Q²uçYé¤@ÈXuœ…3 °jDÅàú~±‚^3íøEØl»LJYI~FåZ…MÏù6Øô¢2”ÃÀJÐL½0B!1"le¯ð|WxºÄK%K‚‘ÐJÑ©Ü_ýÐ …Wê­6¬=Ù1áˆûåÏ9ƺ)&QYàƒàcùÝÎ=Œà2ÅÚZ iºÿÅa…9R¨GØ;Áöô2Í}SjcºùÅ—åµÔf>KˆË/öò]OÝPb'¿¯\õPQ/ \úÚÏFn âTێŸ[ƒ”öIÅúPýИÚáoªg¤)”½1R|yk…¦Î +ÔN’ã´¨Üɏç^Øà»Mð—ÓÊx˜’‡³·²©KîˆæjO²•l[Ëkðñl6®,,sîÙÒqê“YŸøû©UÍúfzØáW[„¹|J{rl'Zò:Ê¡ÂÆ¯‰èÛ\Û÷Ë@5(ÖIeØ=s/·{×·ãpÖúï´ÉGßùxAf9$dt®ßä•ܘZûÝktÓ/*zÊQ dqôÙwGš¥¶ÕNFȸ~&ÿdø½endstream +endobj +228 0 obj +628 +endobj +229 0 obj<>>>>>endobj +230 0 obj<>stream +xÚ-‹»Â0C÷|…G*z*™©`C*J*æPn@S‘¤â÷!²¿!ÿ…°-R›QŒØœˆ`ZP¡°—9Ì}…²®4ôÔÆõŒ:°8[7Û×Ú>>>>>endobj +233 0 obj<>stream +xڕTÝn›0¾ç)Îe&Â_C˜´›JénÖµ[xN‚'c»¶³,}úÙ84 jE+îà|¿Çæ9H ¶OE +Ùê.¸­‚Å] i ÕÒä&Ê`Y¬ jf„°1„7D5ð¨(7¨àA*¸þRý±°’ÄÁB ³<R­Zª¡n‰tu­èj0-‚å‰QxFû‘ +ü%”‘'†ph‘û9Êwp ¦í)¼x|Ÿ1yífVáz&†0ɼ5&Õx¼]g!:òJHŠ(K£Ü¾#GEØÛéí\ZDKŸa+gxHF¤dÇQ˜£´¥ˆ-l)à õ|`-½úMqÙEnˆ#~ÃÅàaÔP(€¹€5‘8ïMÚr­!%,3ö:’ìÊØ.o§Ð­Nxï@ù™ ÄÙÍWOœ@éxíÙ +ÓÜÛg. ôi9éÖ?«õos뉣Õi=SÓçŽÂ^¦ô1¬_[ºÇ†ØÐœCe[ž»#±W5~ª¶Î}ûw|y§6Æë~t¯hŅP {Ñ©v¼Î»h{#& +ÏÏï÷ÌÐǽ’B¬Ý+t¥×Ò^<^?¾Ôž¢ZÜ­††kàfåoäÔ&/r«»Ñ$s/ÖUð+øB0pÅendstream +endobj +234 0 obj +480 +endobj +235 0 obj<>>>>>endobj +236 0 obj<>stream +xÚ­Wßoâ8~ç¯é–J$›p§}ØþX©R{åúÖ“8à•±}±³Àýõ7ŽJÛÒvÕª Œg¾oì™oœ;!øB?¶¿Éºs9ï|þ6€0„y†–x<‚yڝ¯(Ÿ„q²àÖ4e4ûê˜²ÿˆHAË"O¨†”*Š¥ƒ~*gÂм‹ÂÀZjºPJ榴f’s¹ab R&…¾˜ÿèà…}?²ÈO݄h +Lƒèɖ‚e,!Â<]üi—~þTd‘¿ÅþÀzÝQƒÎ^'ÓgàLðÔûÃ-Z˜HV6™CÆÛh4Y¯Ÿ.œkR¹z#Œ›aéDñš¸Ö¶§{G—„ÿ-5ì  ÛÆý:8Ƽ=À×A‰0S?ž4Qƒm4}õêá> N&ûGÀøI¹TL0çFÁA¸ ƒáG\ߝNûúî}ìÇ1Â÷û ô(À= >‚>ωЊäT$»c‡Öªcl«Xl×'ï…}TêdiÛ¯Aû×äd÷î +–›Sá˯Cøû‚6-r%5=F)­žræß‘ ɗôŠ(’0sâŒJ3$•ýmxu/ÂþzVžR)S`¯W‚VËM«Å1cŸYC?i˜N¯!c(¯•¥™VwJ–t†’ÛÊ¢×^w+Taf\š£…(Ñ͵2{o tŽõÙÞ¤* ß}?”.çM\ÂS›€Õï—Ò¬`ÆRœ2+“˜’£bµ¾û¡Ò"ïI”xtÿb6Ò³O©§W¸wM—GÔìÈyݟK±<é^φqÞ:T”s.-§Ûr6µFË?×'¬N¦Õ8?IÇÒÎ?]0SÒÊPB8&¯±pm“,­¤mV¶tÌ;°_Ù #h›iN˜qÈÕa²ŸÁW\Á‹ÇY» k +7Ïo¾×,ìµ_zﹾ朿Õû ¡ÝE¢®PìW‚ªd·ÁHwâX,9uQÏÛ)ªåo þ’Oي£=Ý~y²—D¬Æ‡ç‹T«ëü}VG×. Jñ–.Ik#œ»ûmgKâ˜QN“ÒËaEŊÖSW×3öL ø!zE©Ñ_´!¹éÑZ¸ŽjSã¢oáðTgϪЮ`‰ øÚ1᯸ñçç ò)ÉÏ;Ý¿„­ñBKÓÞóã¹Õy›¡.á™YºUþn~`Ã*š¸°(I¥ÂÁ¢–«q[œX”‡ZO$æFÅ»=M$ªk3j[GZ‡'™Õēѫa¹­88Ãö;— T½Ó†®©elYäĖÀ_põ8Ù›/ìÜi¾S¸-â%«ªÆÕ¶†ñâÑК]À™ÌÌÆÎëGMs ÷DîbïÙ¥Þ(*ïayï?r„3§áͼóOçSæìIendstream +endobj +237 0 obj +1052 +endobj +238 0 obj<>>>>>endobj +239 0 obj<>stream +xÚµVMoÚ@½ó+F9Q »Øq0TÊ!mè­Iš[/‹½®Ö»ÛÝuÿ¾³»6@‚I„ð|¼73oÆüëE0ÄOi ç#ȪÞ÷YïëO|Á¬°FãfyŸ N¿Ìþ¢-il}àZ¤yQ 0'œS’<Ñлg{†cDÂTâQ +ÞØâX[‡±µgŒh]%Íw¯¶`Yš‚žm"΀‘9e@ ˜#$žÃ\#ª3¼(sÊMIXgN[1§a¥i¦¨éÊÇ{Ÿˆ‰Á$Du›'á€iŽkˆÅ=eSj~¬9œm}šÖ¢Ôã1R +Îã0±×"«+&ÜJS +®_’¢{ެã Q Á˜X–ü „÷"%[ÁrA9î}‰úFa ÌJR ¢€¢dT‡k +I›uâá(£™‚{±zŒ¹Ã.ì#ÒÒxÙç~ \ßeãõ¥Üî7|qÄiƒjÁœ;V¦Ö|óÁLš«ĉgË$¼‹\œT¦7³é½ E®Ñ'°? H>2H“ ŠEª£B7ý \‘nÌWôB,9¹x¦'¶WýÞÛàgÂj +ÊvnO¿Æ>2ê¸ vº=ì6 Õd‡si,ÀëjN•n k–Ç +Ý„”DCQù+LPUD‡`5áǸ,Q{„-ÉJ[n¢è[b9:£>>>>>endobj +242 0 obj<>stream +xڝV]Ú0|çWì#•”„J÷rˆV•ÚëõÈUê£/8Ö±SÛ9ÚßµãCG!‰à™Ý™qà÷ˆ@ˆ/ÓØ¾ójt›Þ}˜™AVà7qŠÖã3¦0[·ªÜl`Z¿É~bñ ñÅA”Øâ²œ +È¥0Jr’ÏLQÎáiY¸ojU +ÃÖ S7ýÂ㻇m÷q À75S9æt‚1ÈڔR¼÷Çæö÷ +¢ÙÄíÁk8íC¢Š’3A+Ë»lù`±¸ + '©G¨NÃ#Œ-ø;å Ó°QŒ¦p+T…„!ìJ”‚ÛŽLDx »-ö…gâV¤SȚª_ˆ(ÍÄS| +¢ùä•SiUQXH¥XnuàׯµÈ÷-¸æZܸ¥†Ùå$ìfÕÅò>6 ñé•Q!lÍ +ÚpãG{™z:‰,y©îàhҚ3¼ûcà«Sê܍›¸,K!9—;k„×U­kþ§ÅQÜäÎ$ÛÎ +£»…让žPô}±¥Šæ¨†{<ù$ò핝 B^——bší(Ş2?P⍇)¯¥Å²«IÙWF2åJ“®y:¶üÌà,ï«þçŸ>Äçý…玭«æ– î$¤­L‡èx:•0î_ɛJè~™õ˜¾ò¹KÖb¯¶¥è˜Ä¶z:DÄ£‹åÛ¸(¶:¦-–Ä)ÄIêŸ+°x¼_ÁJfGƒGmƒü…Іr‹ +lqà/"֒ØMkBxù_Ã2}ý¨n†Kendstream +endobj +243 0 obj +582 +endobj +244 0 obj<>>>>>endobj +245 0 obj<>stream +xÚ­WKsÛ6¾ëWìQž˜ I©’œŒ‰ÇÉ!©+7]`ဠ€Õ¸¿¾»i½mÉæH Ü÷~»øøÏ †?1LM -_烏^A<†yŽO&3ü‘ ï¹µ¢Z‚-8ܱ%‡ïL/Ee.æ(>†8öâA2%ñJ—LÊ''_“|éåi†[°Ê=+˜Î@ŠRX*÷âZT–ë~¨õ1 ”³HžÛë™løvÃË} :ÀàâQ˜PxN_‹eq²ïÒªúˆ«²cJÊZUÔU[¡°*X –=6ÆR‚íÊ÷ɈáŠô±aA2]ƒd […ñ‚#/8ÜpÞê!’W¬äpûc~û³s…³s¾NýÙ£"ög­­î» ê>,®[¸ÞLÈö|±€nJ^YÆÁÞ·ð[+œó8K ÿ‡dâ8³¢Â#¥! +G”eèm®§7H®<<î4ðÜÑláÛùáisºn,ãêǗAÁYÆ50‡bÄtM#íƒ& ¯„-Ö ¡jÊ®/áQ=€VrX ÓÐÖØRéj½¸ð³Fg³<„/Ò¨K¸q§7>Àoþ´R:ó›¦@ìJÂ/ϼ^ªJWc)*îE„eR¤â?ž½:\ë:œ†¦å]›¦ÏX¹T¿•Tš¿üV8ФðQ¹’R­h%w;„Õ5.ÜUÁ+¿Bé™pöȹyÊ2ÑíwÄyi-\SŠG0bjžŠ\pîN£[ú>PüßáãÓ¶?N>ޔÓý°ë&€w~Ø‚+ã9k¤]\xÍ´›Ô)6-"»‹d2ÝIŽž­q¨ê}§n¢6|úàx¶3]oõM;ý çmæ¤EÞßãÙ­ÿó];µ>2ǧe¿Qq—xªt…xè)†ë°„/AQø‹é|z½þ"8¯­÷ž;ÒFr^SÚPÞїn{É ãxÞ ÷)Þ!oޞÆk_×\SëöxÁajY‹—)eZ°jé ´Áۍe-·Î|Y^»ïº¸¶™ÐV”gÑ5Œ¸'šöFK§Ò³#pNˆy±–¼@®N1±÷Yµ7ÜSWudošK殺ö•§½Ž¼õIg½R{þžñ..àË)j›CmÑw2r,))s¹vÅ ±žZrˑ0³9²Mñ#BaPÁ†í$Šv_G6=yrƒ¹55¥7v;ª1k3‰'3˜\Ež»Àͯ»{¸W¹]ûÂwø{ð? yE}endstream +endobj +246 0 obj +960 +endobj +247 0 obj<>>>>>endobj +248 0 obj<>stream +xÚ¥WMoÛ8½ûWÌmS RõY^ ‡&ȦÚM6q ôB۔ÍZUŠJìýõ;CJ–ì؉Š ‚Œ†3ófɧ_#<üñ!Œéwž.§£Eàû0MñMœŒaº8›®8”¥€ӟøÚk^Ÿ=±¬æÖÖ.9Qƒ¢Îg\AªdŽÑµ?ð<¨J>éVKÐQñJfµ²™‹ÈÙŸ”bó +JŒ!ŠùʅÏåñÀñC7 ’¬«^1MCÏó6A„9š•Ï"Ë T¢Ðà{›ÄDáX™&×ÃðçJ|Ãò2ã.ÜÚblµ‚/2÷ÊÎÙƒv•gL-1&VUk‰ÆsÈëL ŒlþmJ›q[_Pw*¦E•n›®üªy¥]Û× ø‘…L܈ò^ü¬+Ý6ñKÍáÇÙCýø@mÄÌ·TËþXhùn’St$¬jþéè0eipš’™Ék’¢;²…ia¯ kn^jêÿ\ZÉ 0ÎVÖꠛšgüIT˜åO›Ü‡ åF::Adg%4EZ—кôù׬:ƒTd¼`9‡ë¿§×m2ÏMl õžH]gS^|¢£G[‰Ô¨s^è—ƒyÄúÊ2 DŽ¡«¥Ö\fÈNj¹’šÑ<\ ¤©Ì2ùŒ<8ì(›!ת:ϙÿ5üœ#%‘ 8€?p”ç8S½‚…HS®¸™f©š\4Uûa€p‚ÄÎáN‰¥(XFNãÀ ‘Vh¥n:Ñ'Qßhm×ӑçâžë7xø8‘( \‰É÷í®ºl‹ÑãzëÌk‡©ãäkh¼ Ì4qŠÆ8ŸBN{ú|Ãk ÐlÐm±K¹çJ‰¼’o1.LâáG„uˆÇ:ŸÄ3M‘[v°‹ö÷Jç«X®´S°§nt¯ÁŠãáçƒu +Ë8¿„åAîîÆZð”¡,1׊½ØÛ»Éª<™®•¹P€\ÑõñRí‚}BU6ÇZNH[¬½ÔºE­±·)H¬â˜$9¸+íݺ.䬕'0\ôjÞW{~K™¼;äP‰r¢É;‘ÒŠß¾éµÛè#ZP×£:é!i䥒‹zNºû ï³ŒÍ׊çy%t£"ÏÿAéÂÀ( +A_ F|’ÒîO˜o´â9϶@ò³¨¸Ûdb;¢>É{e!Á}¯GñqÃM#tpٗ{çæëÇî Ûª#îöÐN€5ÜD˜e‰aWÚ04 êô†º'Ø {I-ù­=cšXfòÔVéÏ?|}a« ZÉ:[­¤Ä&Ì[\ßå:ʹ¤Ó‹øÉ˜ØÁÕ÷ûGx”©~fx +}¯8Îí+j+ ?NÀæôô2…¸ý8ü#OÙFÿôþßendstream +endobj +249 0 obj +1176 +endobj +250 0 obj<>>>>>endobj +251 0 obj<>stream +xÚ¥VMoÛ0 ½çW;e»¶ã| Øaé6`ë²&Å.½¨¶œhS,O’ëv¿~¤ìÔ©¯††!‰äã#å_ƒü…0`4d7x»,փÀŸáúÃCo žùSˆF¡gsã)>4‡là¶âQäϚ­YìõÖ[‚ +eÿ@¨³óæ°ÎÈãd†oéP<7’%? ©,dBòœí8,.֋˗냳óÌ<´ó¢ Ù­·Rž±RZ¬‚Òp°¸š(©´¡M‘óDîV°Ai·`,ËS¦S(xÞcóqé}ø|Q xá@Ϛg\ó<á°cyÉ$dZíà#¯$·–˜¢úuàsc +Í£¹“ù¹°Väç`IA©ÚْmøãlÉhºÏµÞ +š­!R– KI=¶‚*¬@HSðDd‚#5[f[ +ÌV•2…$ asµiEQ¼ª!ÛRyQ\Ç. h©±„²9¨kÿÙ¬*»1J–·U.ÁÄö)>­qÃþ¸q0ŽQ¦ÊÔ%qñu½xõ”éI½»Þ¢ßŒ3[j +ő( ¤‡á?IJÍìžJñ›Ãõ°S™åªS‘ë—(¯j¥««6Ôu}Ê WøÍFÜ¢D['a,é$Ë50cʝ+y"Z¿¹X}‚EÇ A;ϋ'mzùzÛzEm}¨ê8û®p+Þªú}SÀ%Fý]¤vûO²FÆ+2z}ËdÉOPw«êdg 6ù!Ëæ9M?x­ÏêsÃÓáI²ÿ/¸ÞÎhóëÐv”ªÇµ¶(¤Hpfq”Œñá°ç¨ Â¥Ph•–Ôi§b=H::b(Šá¤ŽÀVÎý=‰‚xW$€#À@PüŽ%VÞ#d!î¸$“ÿîåF1ø&6¹Ò8-ª-ÏsbœwÃíñIÒß$ǮŶI¦u>>>>>endobj +254 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS04³P072PIÑPp VÎO+)O,JU-N-*VðMÌ+MÌÑ ÉâÒ)Յª52 ›šè+€Ü2KJ2óÒJ2RròKòó ìÄôTR×®@.·%cendstream +endobj +255 0 obj +126 +endobj +256 0 obj<>>>/Annots 33 0 R>>endobj +257 0 obj<>stream +xÚ­UMo›@½ûWŒ|r$Cù +ؕrhS·—¨IczËek³ °”]âæßwöã¸I¥Êò²3ofÞ¼~M|ððçC@CVM>§“_—xnÀ÷=wq²€4ŸEàÀš<±z 7-«%mẑŒ×HÃº!])ÅYú€ú*Ç@8a¸BI & +H£üs*²–ÝS߁ä È…Æ¢s‹¾á-<ó®Ý_¨p‚Jó’ïjÄѱ{×ä°?Q9x>p#}”¸²[¥ÏõõðÕãö„aâ" I„¹W&çî¹=•°6õzxqîj†V$+öIŠ®ix+‘(I»¥PwÕ½ªjÓ6‡]ÁÐˀ’’¶¦9{ÞI`5œNm ¦¶ˆR{Å~`QA„L,þj?´@û8p“ÃÒG.ívϖ¥áÒv7œÃt-±Y¤Í{ɜ, ľ«¢–nh}L<xDtÛº©Bzñl*3n‰,0º,H ¢¡Û<+ÍâKA÷š¢ªU’UT³¯{†Ú°’ÎáòçÍHYòÐ·½.¡¢Eƒ’òC#è©ßô@¯h{ Ftb£Á¯Œ@=+¡YÙXß»™wv8A3ÈxUiÉcB#Ÿš áÂ{ԙ‡Ã*È#£öDp+“£ÊI–Ñ>ž×NX¾Çð?Ê¡Ýv­åGsáÃR½ÇMä‘akO 8*š3rñ)RÿÃíq!wÜQÿr§äõÖ¡9Úê{ººísõŒ&_¹¢[Rj¤Œ”˜ñ…ÚûV˜NÇh¯Î¨nC>GúžßæûónŠaÇÊɳBÛ´~ç镶¦R*¾¯š °ÖÂgÙpî†;Ë 3N©*}b¼Ã©øMª¦Ä ¥ý~'㦋NÇK^¶Óô×GÌh´‘¢Ì¸²‘ÊIKMU5דmߥ™—¯ íÖð¿ôÓ¨ÏÖãâ[RZ ¥y¦ØøžFzÿzÊ+ðí +ý1ùžõ<ûendstream +endobj +258 0 obj +749 +endobj +259 0 obj<>>>>>endobj +260 0 obj<>stream +xڝVQoÚ0~çWÜ#H `@7UÚÚuÒ¤mêZ:i/nrwŽÚNÿ~g'¡4Mð€ˆïî»û¾ûœÇNCú„0žºo”v.Á×3g°HèÉtÂ"îþæXp¹»F¸ÌµFiá &,Öô20,C‚Ѭ?uA :\>V»"S™åJ6‚º©4e2†ˆI`Â(¸GÈ Æ`˜µ*|娪\å€û-HeÁdñdëð1Ia{UP8î %Ë4e­@p‰J !œ94‚`4éOÜáT¸ú¹¸º©9«š ‡ý¹;–bÌÙùç £9·… +Ü/Ê®ä*Àx…/*ìE>2 Ø¿hO©õWL€‰á_‡Ãay¼æ,pMŒ}¿·hmÍZÅ\k.-êWIcqÊ%7V3«4X§Lˆ-\P]ÉÀlÅ4(¨S‚^fÎÊÌTYàæ9ÎóȌ‡Ñ8Ü ˆÅ'Ô[%±w}HCBA¼¼¯¡rœ^1r«r ªÍ’§0N5ŽRWòí¦U÷í¤KªŠ˜e·»Ê×À¼ìMXcª,¶Æ|2¨ŸÚ]öú/‰:ÚËN*’á›4–ÉÛwô½nÝļTê $ Y´.»ƒÇs|—w×·`ò,SښŠ˜i ¨ž?^´ ŚSB’­3±ãˆ"nh *0N4Ø' ú…'tT҂uþP¾ÊHžM($ÁzŒ`f}8êÁ!1њiª˜ (1j¢kç™À ªÝžeÕf»l¯;%Ûßþ·Uy`¼M6œÛŠL×nhJÛÍeŒÚ œwí—Ø2‡éµ¸ui6Ÿp’¥mj®›-†5µZ–'ÇæÛânsM-A-v+q»ù„Ç4å}ÎéX*pÄÒ3‰Ÿ¤–Í®ù·”°9íéâÿ´lZÆ¡$¹y9—n¾¿—~,õ°œŽê}ô!Jó—kÏXüÍÒ0*ø$=ZNN€-]"·ëcŒŠÌ_YËî|Ùk{³ »Å6ï¶ÊAçÕáp:‡÷³I  4»[•Ø‚it·‘6ðƒÉœy¨;ÌFCwv4r'3žò¶tµèüêüéçendstream +endobj +261 0 obj +835 +endobj +262 0 obj<>>>/Annots 38 0 R>>endobj +263 0 obj<>stream +xڍU]oÚ0}çW\ñÔi`b'$¡Oc+ëhË ”MÚKH x +qf;Cüû]; h»vâÃÉ=çž{|~µ(xø¢1ðCÈv­I«÷ỹd 4êaC’_ ¡ s¹6ûTq˜ˆŒ—šÃp£8ßñÒ¼K~: ,°Ký¡Ðõƒ üIîv²„ÅýøL•((70?hÃw¯q@©åD$†.‹HØU%6[t0ˆºÌó´ ~L|”’Àb%t ï)ñ=|G>„žoëFIË#(Ø}Pû1»FûÄæ[«wà{Vo³*`n÷ƒÆŒàŽøa#i´KEq –ï™ÚÀUVWº+ʵü`©6o4ŽqcØÞ6ŽÑáful|†xGzSÁ˜o…,—ËWel©®{½ý~O.u¼dt™ šÌ8ò.46ŽKÓl£åÓDx6¶$Ùrx#Y'Tì²È¾Þ=e¤Ø÷x«?®ÚŸÓùt`¥ýÜþñ®BC¥äo‘óê2ç + ê¼½_À-/¹J ˜Ö«Bd§à7±Ã±ÃsîPÃít‚t–¹ÃNÄJ¥êð +‡=ixäJ£iÀ !Ãrm5`YєkXË¢{¼*Ü)ñέŅïäxïíä8ˆmiU©ŒtZÏ`8c§´…ÌRƒ&ˆÒ´mÚ ëU.όT'a VËZeü™š\h£Äª¶jœ'²^­UO”YQç¼×0Ÿimau¸ì¥íÎy¡ \IuqA¶a- +œ£a~Ö%Jëú¥ ýš+1Eq<­.—“^²a^Ü6¶n°Jã)æW9aø û­È¶ðb§V©¶«Ð×~+µÑ™•>é{΅†2_izÆ ß°OåÀ#Mºãóa ìø¿þ‚(ÀRϳÓïkërÓÐ:endstream +endobj +264 0 obj +777 +endobj +265 0 obj<>>>/Annots 45 0 R>>endobj +266 0 obj<>stream +xÚ­W]sÛ6|÷¯¸ñ“;•(RßòSœ:ö¤§nd×éL_ ’P“„€’Õ_ß=Ô#'m§cd’ìÝÞbyþrQˆŸˆzCþ³³·g›>E=Ìñd8ÑCrq£ ¹¥¶’ríh.2•*ah£Ü÷%Ý~|¤Ûû-‘ªXæ «b‘¦[‡ÞXÚꂜ¾üááÏ3€µ»Ã Ï›?"–×ýôx?%«çn#Œ$á€EñR˜… xIç&®Òj‚1rÃÒ?ºÃ•ëœùY;ê]~~­¬3jV8Ikif©Œb½RҒž{ОÊñwabI¨u¦ra¶4×&ûÏØS™¦ßE Êd¢Í¥l1¸å…¶X­´q>àpÅÿAE±2*wÒPbò´$ò„æ*uü·[¢…Ýu…R/Hؚ¤X'àÌR&ð-ÖB¥b–JÆ÷˜EžÈ2}ˆãTæuà‰äÛÝ1žµ{“`ÈOœ[±–W>¨Â/ z¡Îã].JíUÒ£D—9?KVV¾àŽ  ê–Â׈ò%3ÈQYvÄCÍd–ÐQ xßü>Šb áJM…ûùPhjd*^˜ÜweÒ‘¦n·WgùÇ:¯‰9®ÂSŠ Ì!n%º EýÒÐÚÝIU¤r3aží±b8Ä{Þ;a·4­ê½ÑI;KK ºz­LÊrt–AßF “1ÝZ'³–¯µì’×Uª: Pl›-ÍEV–écX¦[n%8ƒ<”0R˜‹&QFƐÄÞ­ŽÄ£a8 éšõ ˛ú•ˆZ{Åø[´J¥°¬ßuæ"˜îQÎጬ¤É”µL8ý‚°¯ä>åõ‹Í2n 3uk‘²²ENs×O:CYjÇþU¾ðNéJuZðGKµX¶¿"UnKÖaaÛåmÔÔ¥¯‹ämÉìõ!³Ÿ€àþ¥hD +e#±düòêP×ÔRúâdOkçó‚Ö2Otíڌ\älnj‚óëÛyR½T”Ù[ÏÎnJ©f:QóýÙ­<Ñ'w¢‰Õë߯dÓˆ•óûÓoq¨)–TaÉÛ¹d\x ^+K½¸gz}Ҏ¾qÂj¯Ã–t¾²NÛæ¼z•UÆã0±üU٘Oӌ›ÆF­ ‚Aب*ÖÆ³‡„Á£û}4¶Å>HAݑ"cý–¨¤2/ x½‡œ½×¼²¯úú1e_MMw>Ÿu.›[\{w>îØ¤˜¬¦Û§æòe/Õ÷y4búƒ>}ÀQ¹…¿£KWèM‹¦…‚ÙFá¸>8b.d +Ï»¢IöèqzÕûMƒKú1 +úÑ èOºÁd<ŒA7â¥Òåwgabd又?>ÝÒpô(„˜'2á^0©®Ršò< Ö¢A„k>Ÿw˜T.ýìÐØÈ,è‚ûFîAëì8*¬¢Ú‡]`mž¯’¹Ó+»S<³/\ýf½}F–OÂý÷Ïõ±[Ójpô}\K#Ÿém@µÎg…Y¼Îß8ˆhaÎ}Ã.v÷{öFÝr{—}‹¼„ó7s­1 +ښ¿“ˆ£^Ò`ŒD3ê†C ú‹ +ñkʑàrä§§§W3X:·ºìt6›MpEçôwN÷²s3®<êui8 ËBK·Û üƒo½9^+¼O;b°uýÜÝíó­>¦Õ^9ˆ¨ÿ׳¿ !$qendstream +endobj +267 0 obj +1392 +endobj +268 0 obj<>>>/Annots 48 0 R>>endobj +269 0 obj<>stream +xڅW[Sã6~çWœ·]f–Ëö vÂÎvè–n Îð¢ØJ¬bK®$ãæß÷;’ÚaÈM:·ï|ç⿏2šâ/£‹žS^Ý<Ü^QvF+œœ_âCñqÑ6±þøá/œžQ–ÅÓÉì‚OçÂmhaV¾VÒ½5E›{GNV^‡ß]ÔA+céËãý‚„£Wø]PnêZÚ\‰Š«´WzA-…“Íæa4;Mgl6(ÉEUáp¾¸‡aȱù”þ4-N4­”†`ë©6ð@x|¶0º$§¼üÌúæGÓt +ø%ã—_EŠÐ³ËôŒj@q…÷ø­¢#4’°k:¹ÒƒÏ3€ƒ¥÷Í瓓®ëR ˆ\—"ÊÄV~º•æ¬` “Óà×ïôuþ}þãúŽîoî¾}!üÏ¿/摞³ÈïÒ:e4Íú¹Õ’²««,^îýã»gѽ/¦ÙXµ.=n]^%á.ÝZ)w¹¼5­.„‡Æ„¾é<20M/YÃ'¨”uS!é•ÈeB‹¸Òéé4¡ã<‹ýrMÓY–eHÛô‚×½ŽY=ž¿H»1pU9j¤­•÷ȧ7`D³!üÊy«–-4ãîîÔ#?pUIGfE¾„šJåR;I…ÉÛZjŸ„)/…^3­”g[ÚxwL'‹4"tµƒóӔÕÞ[)êe%ߢ}|(å`Ì^×zÇxþ/¤Sk#òâ?vbCæá +P¦æW†û6x 0|J7` ½Î'#ê{ìZZ”Ì}»„t׎ðP +RÑîºVà»ü»|6²5„3™@ æ\ !va) ²dÀ Â}G­SzàŒ¼ã§hšŠNJ9³:ç{Œü°×[8(zC2–[ÇڊšºÒ°Ö—ƺÐd}Ül]dBJO¦Ç•¼gùUܹ)órCCVîÔÒ +»y7;Úy)ŠôéxduèZ ˆ¢£!c}4.Á/f(„”R£§‘k¤xæ™\Løˆ]µr%­å¨¡µ§@ªý6—)ý +C‡=v¬`äë>¯÷I —©/‘"{dÛ«ã]Á¾rÉè¹hבL\Ïc>Jû¿H­‚¥N¹òé8ٙ¶2—ê…•¶6gS…$hb`×҇êï%Qøº'ÊwúB€ïïÔ+· ä1V©IË.F3dë§HËAù³6ÝÖJa؂c;H‰çôÁ°/s Ú´ ¹Ôrt+ҜIé¢%€¶TW÷TF]êÐoz{QÇÀõâžùh\t†“i¹}ؐÃ(Ã¥4¼²‰Æâ*ჩ\Z/€n48TKU)¯úÖÈ.ôÀ"ÂßQâ½hm +µâÚ#v‹;òÁÃ(ù/;-/±oôI¤¥ Ŏo^`B£•„¢`²EgZ«—Cœ×k ÊmoÖëJˆ IP4ªHlBU'[Þîq5¢°¥q:²~ zm=t%èz f)wÈ`"’ŸÔÀ¥7]DbªË—ä;0ÂËÆ}FfOÇa4ÇÍáuž˜ïOg¸aVè6=íö&rW* Ï`Ž«š¯VrÍë/.l1ýìg6N¤ DØ·?éºr€•³)ç< L>N6 Âzhce…~0TÖÀå%9ì(-ׄósÛü…10ŠFh³5æl¹U7ÈË~ƒÌÎ/ñ`â“ÐvÇx䝉~¦XfÂW'³éè!ìì⠛oøuö©Œùíè_Sόendstream +endobj +270 0 obj +1518 +endobj +271 0 obj<>>>>>endobj +272 0 obj<>stream +xڍXÛrÓH}ÏWtåe¡Ê˜8à ra]!›8µEU^ÆÒ؞EÒhg¤ýýžî],'»[@ +¤™¾œ>}ºÅß3:¯œòï$?ø¼8x}õ†f3Z¬ðæôì-Ò¥³¥3ºR®™ÒÂRéô£.*ª6ÆOh«i£5å*Õd*J2­Þ©ŠTÑP©*>›×¾¢¥¦Ì$ºð:¥•u3®±…þÍÓÊiMµ×dÝËÅ_Gôjv2=fú[l4˦ñÈñéô Yl4•ܯ´Ë=<§”Ø"5•±…g‰-S¬'”_9³¬ù•ÌmjV&Qò`e³ÌnÅÃë«÷¯/×÷ôåòúòöÓWº¹ÿüu~Nøsy}w9Š{qyûíŽ>]_Ðù÷ë‹ùbþýúŽ®¾ßâŸ7?æ×_&t1¿[ÜÎ?ßó+9øíûÅüj~þ‰„ÚZ <ƒl§¯Re™í©²mg×Nå@‘lµÑ޶Öý¤íÆ$Æ£Rh(¦¸Oe¦€ºlP.-9³ÞT£D66KaÉ+†+œ«†KÙáuÁGØJÀß®„ôEÚ©Œnê%jØF áäáMöp2r¸Ô¨À„œ^i×eæk¤0H›HùJ–KÅ A 9ŒÖ6åZ!em üùºé-²daAðYl†¼:d(SہÛF"("œø2Hƒö ­¨´N¸”L5iƒC3,á:d‡G;¼J¿Æ›Ê!ŸL1è¦lB¡3U¬kµÖӑ·‡¿k§M¡V¨Ì¤»Î)’¬Na‹ښ;-7U|]t¥Ãa,‡Ó‡—t©PØ—è{?N2MöÒ²ž[J`¯@çwïÑ£)ñ# ±@)eŽ¡uð¤dAòNM+G yxj¯^­DõŒ &™29CB[åÐ^Uó‘~j]r2‡0°$Õp͇EÜXAª5/ґW9K¯ ø„–©Þ±fŒøqh„€˜i´ 2¨$i¶â½Ž;7³ ‡Ðàn×½o§g|lÖwoÛÐ]ù7Ê­™¸+(^¶SnFÍÚ¶!ŽÉ MÔD+¡ÀµŒZ‰Ã£P[¸þ•NZÕÒ¿A±¾%Šçˆ*òÑ?÷4?Ûù0RîjSËr‘‡$úF+ÌNÛNâz²ß$2äve?Žº§&ì]Ly6®àÒòTS¨Ì[ D82ôz°(}`K¼k´¦(^ÝÅË»áñg²°x$(ƒÔ0°µD÷qlD”8ÜØ[49«ç4#¤¸ä ”·l7²ÈÀ™“}¿ßõø°×&4»ã +퉆ÎQ¾GíYàt±Ã‚à—NÑìÖVP@`ý 5é㑂²ƒq¡ý(¬)}[ž¹ÎÉ>pY$“¥?Jcøt5>N×ñ—âô™„2üRˆ³>>>>>endobj +275 0 obj<>stream +xڝXÁnÜF ½û+xtyã];k§9%“Hƒ´¶|™•F»“HeFZgÿ¾I–F·(‚&õH"É÷HŽœ,é–tµ¢‹5¥åÉ»»“—.i¹¤»œÖ×Wt—ÖڕÆ{c+O¹ud›vT˜TW^kOúg£«ŒKx@ºjŒÓô¸³…NHñƒ]ëù©VéNô^»ÕÊ5äôV¹¬ÐÞ¿¸ûvrNgˋŊÚœMУ³&Ó,ºÇ«õâ’ßÁf‚s2ž*ۈgSGCø²ÙáØë´föœʔäÌv×xB©Å«¾¡ƒm]Œ×­û¦.ŽâáÚø«7äg!;6!ʟڥÆky"¶<:[Èaf|ã̦t@›igöª1{°#ßëÈ3£ó´Q^gÄaÁÒWg·N•qr>U¤²Ì°ý„Jj¨í–3Ý{TU¨¡Ìé;f•M³›<œŸœª#؎yxÁŠö¶hK-¾É7Ö©­;IE©3Ӗ”Yjºq¦ÚŠ1A{Ìe[!yòŠOm­‡ÚäŒó·m©Tä¸>ÿz¨¢iT¦I:·³VˆÎ ¡›o8€ÑŒcŠ`‚iÛ¨M¡Y;åqYyFܙó"cZ‘ÚXp¡vvo2ÍúQBUR…·HÀt‘ÆÉÁûˆ¬ýÆ àáÉÛ4µe­ªkf(,ŸºáÿqNûÚV§¼„PM¥ÏœV™ ÷ÐIª%²4ÐqÙú&–ƈڀýß#†tÕOaזʙâ@-g>Ÿ¥ÔÛ¼yT.èÎ¥;Umõd>á÷Ζç¨u_pµ >”³³‹×‹õñ\¨Aõ6ÏYÕ{UqMH}¡•çã´¦ƒVŠÞ²^Ùç2éf‡$|áBºW–Jë˜hª +'µ^ÚU½;x“ª!£×2M¸ +]ÒÇA?j9™ÕL8X•wRMDò|Ýæ}ùV‘þ¥nKê ´éª¶¤³W«Åõ¯ùk*NVhk,§S²d¤|?ޤ üÃHê“tÌÈ5$g>pÇÝDÀ[…-?BdÒVÙ +èJîûª˜ö4N¼grF9ð2Òºk>³ŽBq‘ø}+Ó´g,¾RȘÈO#?·í¦Ÿ†›P­ÅË'µôyOCÞÏ.Öøyy!Ÿ^<Õbùú:ŒÞIC”½²Ô +´ÁhÀr¡òeÏCy‰ß/Õwi4639˜è„"aÐӇ™àå(l$yj]c(Á?êFB çðØbÛ`ñHV¦‚šë¢õ3—Þ[T”5!ŒÍËQ禒ÑJ¹¥ðu7‚œ©±IáG3Ÿ¡šB |€ÏXä`®.Ù¡†hô;¸¶ç +ƒÓ˜µ’韩®CKˆCk¹Òüf©©Ò¢ÍôOZä˜\IúI<Æ8´ƒ¾ |KÚ)L¦~˜ÌPnS¶7›ªð¼œ;à8ÿb™áªçŸ`Š`¹ÈœkžD1—;pN—h±<œò¶°0ªJCåyæ÷þòiά×=z²9– \cÔÍ4J‚þ&¹ °ùVwîf”3¾öˆª +·B¥Â&žî»ì/Tý™Jã zËø'7µaP"¡ª[–Kœ$gwfc8›h…zì–^ñ9‚#‘ŠQŒVì‘ ÀqH“ËT¸6EPý™K["8 ¤t e€Ãŋ¯Y²^YPâÛyêr~Â%€OR^¼šá× ,. N¦øyI‚‹Ò=½ G>»ß0·‘^f½üpÝýfcyyAk¼.¼£÷÷_oé¶_Mï½vžþPU«Š`f}MgW«s~÷ã—{úxó忝·Ÿéëý»ÏŸÞþ»ùr{ï^^]¤¼¸ºâƒ›»“?OþÀ/Ýyendstream +endobj +276 0 obj +1707 +endobj +277 0 obj<>>>>>endobj +278 0 obj<>stream +xڅXMoÛ8½çW{Ùpœ8M]=m‹¤Ðíf7Îa\h‰²ÙJ¤JJqõï÷͐´>ìvÑ6…å!gæÍ›7£|?[ˆ+üYˆ×Kú›UgÖg—w7b±ë‚-WoÅ:?¿•ÙN4ºR¢³­p*×¾qzÓ6J4;%œÝ:Y‰çsë„4Ø[÷Ml¤W¹°fhòüjƝÊt­•i^­¿ž]‰‹Åëù59’mc+ÙèL–eGVJ¿(/¤(u¦ŒW¢p¶â¬Ó[md¿ãƊÌÖÝL ¢ÃãÊæºè†AL|úvóUe ‡|4ÊUðirÜgrÝhkü\ü‹Ì+Ù c¡«ÚR-Z‡S±’ÓŒS҇,ýïŸê‡r™Æ¶–z»k¼@t¦h¸Pi|J§Ø'Ô¸[oJ €¼”ÁÏL›-¢¬êRK“)±¡DµË'îjé 9EíÅç€æœÌ.Pì7×óÙ-ç‚áÉÅrI„?ðê{«È b¦H\|móm… h”Lm%@µlè¹6…CŒ*‘!6‚&½5“`ŸÏ)ÝRWš @Èé*ï[å‰A}YP ¦Ñóù|¿S|=ÐaZ—+‡L¶N¥H&N9ž=*òü +Ɇ|4N暈 \rÉz™ÐÈ-WIýÈZÚä@ÕþìÔéø¦¹¸/ød& Ý5à±·T`ᰝ½®Ú²‘FÙÖ£SpÊ »)u(€­AÆ|ûÄgôÅôî Q+Ä02ý%œ™9®7脱L|%]œ Ç\ÜmH°¨ibQ,mêî½m˜ïE@¨¿p¶“eÓ](ÜPw"É~KPŸîw6i IuB®ñ rI›Ã§fçl»ÝQŠ1{Öƒ¯ö’ažøË8âT• ЛÀV6&¶QTB§ +'µA7p‹›™('RKzuhÓw×órú¶oÓÅbZÔ¡rÖÖõ7 ¯X’Ð<„ Í‹,uNi·&Hˆ’$)0|‰E֖҉L»¬­|CÚ2;öF–2*Å;p¦¡c¸‘ûWÖ5² ˜ôFL+T¾OÚ!ææðAH~¿¼^`îI%˜?ä©nËô ¸@ÉÛÈdþD*¦O”ô„Pì g©=º Ò"+¥®Ž:9ŽdáÁkœ°¡(¾Åø çޏCÙQW(à ^ølÈêN_:[‡O  EEW͞äpÄ$ßùFU3­MÝG¬Ñ$u‹~Ï X; ¯„¬ø‘OLj²8Œ ÑG•Ì•Ø*£Ð0>¨eôÇ H¯a‚‰¶å”Žã£jÇ~#ɝŽeŽœh€& Ó ùá<‰Ñ‹BOwÈL8ôžz¹¶u +{ÅκËܚP©“ÁAƒŽ8 ¿cNîuYrìXŠc)ö^EcÈ,­ R•Ô<î '2Ív¶S.¯'í;ìJ~£›,€^ÉJ…nݰÜ/õ,!9GÃ;¬&à©-&‘-ÃÞ +GìB¦—¤$ý"“ô÷¤H‘êˆ -DªÁ$ª@‚•NCzÐr›îH`뎏¯ÁjVHÐs6ÞFzB:FŠ_—d9ŠªŸŠeÆ ›î 9MF *¢ˆ´Ut¸ÞÑR:NŸw”@@Ìý²ÍC¿R™iÎhv37GGærx ¯1Qý Ǖåý.A” ýÜ©+ƒ‰ò"Ã*2HM›ÌBQÐõ'Ä{=T­°w€!ßÚÆæÝtÙ9ÚWӍq“w¤G©Oî~üÐÖÀŠãw Ç‹¦­-rȨ½xQÎ÷+–ŸH^ú‹ÔO™°fÑ» õ:þŸ‹Gdt!µ2õÖ&Mƒ )úZ#ß$5ØJ¢OÌêt‚x•(Ïè\ò¸Êsö캍aZ1•Ñu ½ñÌR'½ë1K0ò VôM½³Åª‚²0g@ª€·’…i«r¼/éíkÈZ¡ù…ilúëVÓ5¼%Äæ7Ò¶üqé¾ßf<4yp ÖI [–vŸ&¿CMkôF•ú?Iw +غ46GŽoÂØj¦,›¸ê9wRnc#´ºSXMü´ðB¨ãkßÄ]ºªëþ'ÐA;œPXò´§îà­äо¼“ù#5° +“‡7€:<÷¤~~¬ÔG¢:z +¬ýg¬j<5™ãþ¿º±JyϸÒ6†‡ýb ×Óeñ×hL|ÿÌì½ØÓ ®µºçIxôn©:$G!S)çâ/¼ÑÐç2%5@_å}™š½[+K0è{ItÔ²åoñj1åô ¤ßVÀ€^ÇÆ[‘?,v•=ìu~'iñä/Šcôpdä¯ì¢‚,çoº»¸ +"ry·Š¿­Yܬðý±øøôðØø„l<ít­,ãm+qñöúŠl¯WôèõâFðÇO_žÄ§Û/·ÿüñY<<}ø|ÿQàßí—Ç[2»]Ÿý}ö†¥;‡endstream +endobj +279 0 obj +1850 +endobj +280 0 obj<>>>>>endobj +281 0 obj<>stream +xڅVÁrâF½û+ºö´[,Â^lWNƒ`²B’G’ ç ` ŠA"#aŠ¿O÷H`Þ¤l—Ôóúõë×=þçÆ‚6~Yp߁Û.Ì77½ðæûà, ÂW|Ó}¸‡pñÕõ`¤dn8ýþwUjvº­; +êq›E‡pÄÁ—ÞP²1ˆas7à}HÎÁ€=brÈ'9EÔÐÛдn[‚xòÏxæ3ÿ#än>—c†ˆÝ›ó}LÅz‡MZcs?¬NF܏2OR BF§… )Bá ºíùS)†£FžÓç2æö¿#s°†è3 +ÅgÑ¿¬þ °¾/0áȋÂS•¤s§ðS¸ýF  J‚ì}É’ óŠ1–Æû $j;Qy6 ‡x®¢¼(†…žQô[¯»ÌLD1÷˜Kl‚²žpÒÁò` BIÎÀTeG“àGÒ÷Þª!š6 "¶PŠà'`©Usž"vBÅ!à˜¹¶iý¥5ê±r˜zQ TËé_D“¼ú|ÀíP<£{0sјW= BÌPƒdŽ.·±.&§pù,l£žä>’´µ=) ÓsM…M«ÛúVûG«K–Õzlž6-ë¡õ@Ñ0hZþL&Œ\‡t“ü)B1>±"eaC4?5éÌkWå#YrEÝ~ €/ŒýLk¦0y0fS{}1˜V­!"„R U.}‰½úÖóHÏr†2’$qWx}6fCœÙÐÐr—Kæ4 ð¹-è|£€þrJ…qüŸ"2 s>‡†"<š’Ê'´JÈûîѥȫ¶^j`/_?ˆ]8^`Üßg!#dó»Ç)Zr…¾šÌmۑÄAñt©n ᖝ&¡Ì޲ÇU`&hÀ„I~íÉóF +;A ŒûϺ\F/߯g ˜ÙUž¨awSeŽ6¸Çñë? ³CªÑà +D¥¦WáUøÔüÒüBÓz4sp[®*·DF+™Iî ¥àtì¾¼Gš·ò’ºö¤'i+ãà†éá¸/ŠË vîK:ÏJçI–B§¿ïRÖã£U·áñ{W¦±³íA'ËU/_í—o&Z)²×bkƒl—.âѰéü´ßÚåˆÿ@HµÙ®øëx®  Á.)ÜÞ¶qX²¼ scÐîX–…’´ïèOVƒáïJ2d›ä°Uz“…Z@‘ÁBœ.`‘ä…Nf;ÄÆØ2ÚÐËDå5¨ìЬ“¹Js‹l¾Û¨´h†ù*N—Iº„¤ \iV@¼^g{µ8VÖ±Jÿ ¿‹•‚×DçhµVqŽÄÞ+M.…©f:ÖúN @r¤»ÍLi<ځ™šÇ;$† –™ÊaŸ«b爙éE’Aÿºô±4}­âÍl­®ÍPý³vFˆ^3 l äÇæÒÏBåÉ2-Õ.â7|¸pÈv^Ñ ‹lCoò•‰ÇF‰} zlAZè8/ê÷3•@&ªTéx þn†<À9r!´$-Tº(3/w±Žñ³úÿÌô®–íXP³‰6TD¾ÃCDâT+v’N°åX@؝ŸÒìÃ= ƒáûûi1 ˆ·Û5ѰÍ6˜s«æ æ8TâÆd拱ªÿw²߆)ãô²Ð•Í(Ñ~•¡â]±ÊtŽIæÉBQli«L³Ìã´úlJ&YkYOxXe–Õe˜¬T +{SLüF®4ê}ÐۗöÑêUiM…ù«¶5Ì\m5êÓÛù.¨q:wãy#ã‚*€Uü^¶õÌ g›¡\Wdq»UþÑËÒ´!êRúyAòj2í“|E·Ê)µVs•¼èNÏ)Ղ†ÔȼT…Ù'ÕIô1~<;J1•y‘û/¼K`Ô/¬`^Ö@)¤j_V³ÕÙRǛü·ÒGð·4۟²,2ʐSlɵµ3B)Ô¼(ÇÌìþÜô2Ug¢kE’Îɐy™ E›% 2#miR]¥fKTùJ$ª,›¿Ñ«úJȨ™šF^›–gZ–9qäkœs(]ĨFlñe2KÖI‘T (TÂf„r3>T›Ñê>@÷±[.x°#?ø¸è"Ú0ŽÓ]¼®nùhÞwÚÇûø×÷ðÝý®yØy¤<¼yºùð.,0endstream +endobj +282 0 obj +1651 +endobj +283 0 obj<>>>>>endobj +284 0 obj<>stream +xڅX]Ó8}Ÿ_añH¥0€´ûh`‘vv„VâÅMœÆàÚÅv¦ôßï9×IšfÊ®`¤isís?Î=÷f~œ«'øw®ž]ðµ9{}söøísu~®n<¹xùBÝÔrk”³«¨ã~¡BT¶QûЩM¨m³W6/Þ|;{¢=½X>§ý[ؘŸz³uf1×6åhW]6ª +[k’ +:ºx×|Žju¶‰8 ~´j n¼.eµ¶·FÎESYÜãsêÑϟ-Ÿ];W ìºÍ ¿ê¬vF­5⚥úg¸k£¿•ºhŠÁ‚—ÁJ{µ6òT¥ÐŊÔf©ÞK`3pgýwø¼alÔÎæö8Ê1˜Üښ—1OHKX}3UVuHN³ }ð’Ǹ£h<=…ª›ŒÌ"^ëתjµ_0z#¥}M<¸cÍPWõ +ߍ§6ì`¯Rhâ¦÷~÷ÅÖÆ¾sŽüÙÁ<Ô$’‘Äїž]7òµe󉻥j´ G„I1Ð[û=´rl²>ÇPwUq.0êv£Áqѝhû‡¥›"è$‹é>|ÞvY3íwÈø––NH´/ùØ2áÑèl<œ¨pUÈn_’Õd¤Æ| Š«/H‘M-«©oƒ­Å“šÝ%º™Ëì5í©…#AØâÀx¹„k}m¡½„PE +ê@ïåj;¦Lð‰ÈàA 6¼ŽÌÀÇ=¼Å‡m´&“òRÝðHH~‚IB©äFC¸lV•3:NêV<±X™Á³šTœ̾ßÓ³K¢µ¤ÇxŠ—:7/Շ€Ëß}ü<º‰ ã+×Ռ’ôí©m™T¯ +€*ü)´€!£äïPÔŠ\w+ ª«‚¼8©;HQm’]ûB­œÍû)¨þÍDm‚F«¾Ó~¦ôv묨ñœ½T¤¶>„v Æ8t…N†ö±M ›ãˆ‘îßY–2ðúA×," šÎ9QЙ uð÷Q…”ºË *p:x9›Ê\Ôx®…|G½óÞÈdÓ ­:0J«d¶“ÝT4ÄÆ\×µ Ò²r],}†Øà¼¶KÒ-³ˆDdW&ïŒñ½Ž3.µPˆ­;v?0YÌç=®fâæ,ŸMy=Ž¢9ð4t¹ŒÝ¾cËJÖ$À$ñáݙp0×Ъ° ðØy_œéùø‹.g€$Z%8x¾T„{‘M„;²ù™;j&Ê@L2s¿ÍOSAG!Ðâ ÷—•ESÌ£ñ;\{£½(—©æX™;nΓ½Eƒ'ò\K]ÕΉõÚTZ¤¤)£Ü`óO¨±˜döÿðH½ëjè9ªÈ+r'’½Áh?hwjqÔ¯`\qlCõª‘q¶œeÝ|v¨µ4ø®†¢l¦–X7ޙ! 2ÔÔF–¢Ñ‰‚M²c5›gj¬{ç£á쩊¾j#>øGÓIˆ¹:‡T Š~‡×±ßãCšXâ.á+dµ±ó¡7 +Ss˜ÈÝì]@Ôkf2îv”ºÿ–ÑÒF˜>’¬Pö¸9ò$ï'Ä9Öa²/Ɂþ;Zaɍ·ã†J«‘höÁ;ÉÉÓ (·—Åûü4\j+W:_…¸ Qä¾È)ºôëƒ/½N’,‰Ú%»8´ªj­‘r°ӝh­#vÆaãDž-TÎÊ[xÙ僗«ê¾¿Nœ¥ãº…hºÒNCéfÀ}µ–ØÆ)ö-²>QmÛ/qŽA4:ñõ¤¯Ï†ã ·§èÔ Ùr _=¨"“n`ór—þ;ìW?–¥·WÃ&8vKu­ñfåHe¹Éô¯wÃÆlu˜%Zݣ䩕.ûòTºï ä`!IcґÉRÅuÍÐoÏџäMó‹ÙõaÀO^ ITùŠþƒ‘ƒ„˜dߺ¼]Ïß çyýHíËxß¼QìËËøðހ´¬Ì¯—«ÓM +V·eö初6mQQÄ®"Ž=~û²ÿcÄùÅKuqq±¼ ™zóùú“ú4ÈìgÑ¡ڃ™<õˆÆ^<}BÛgOøÕ³óçJ>ÊÞwùñòïWWêúóë«÷o~.?~º¤ÙåÍÙ_gÿ? Ú×endstream +endobj +285 0 obj +1774 +endobj +286 0 obj<>>>>>endobj +287 0 obj<>stream +xڅWmOã8þίõˁTº8`ï>ñºW‰ŽV⋛8ÄÎÙN»¹_3ã¸MÓ¢Ó¢ØÉ¼<óÌ3“Æp‚ÿÆpy +g”7³ƒ/_a<†Y†7W—0Kg÷¯ß§pýt·ÏOw“Ùäùi +ϯøçˏÉÓ·!ÜM¦³×ÉÍ]ñƒßŸï&“Ûk:8šýV/×VO/Fçd÷d®ÎÛ«C˜åÊÁ£J¤v®VÊRj¢ª +%xB7àLæWÂJ(ÔÜ +ÛÀ*WI‰Ñ^(í@€6@UˆD¦0oÀçï«ÆªEîÉ+†1>R¹)RiÁà>fAÔ>7Vý‹oVÂzô'¥ <”¢¹„T9oÕ¼öøH­ée²ï¥-˜ ÿà,Blߤ–VðRÏ •ô\ÇTßEá $¢(ÐäÀw`¼à^`~E8€—"M­t©£Öt÷-<(¥`Xƒö¯Œ¦0×0fµæC|D§_‡Tx••˜>zÀÀc?' õRj…E) HàýJù¼—,쩲fa"ó~êTcÂΔ2@e\/öþ~D3cK?eR{1/¤ëç8CÔ-Ѓ!ÆW˜Õ¬Ì¤Ý¥F—;ŒÁ$WÆ~´ÌÉ1¿¹”zaìeDž"Ì6æ‚ꀙ ·1—Š)Õ¹!×WKDh)C$Áݚ£PˆÕo}¿¹ðT|Ì )9Ăò›-}?PË­ü0†³”vŽ®K† 4©ÊڂEô[̧„ b$(F,‚š"”f´CÿB/j±#¬øÒJ¥E† !š €0 ¥“¢N[™SV¥òíµÞÉ=4 º±FïG=N ¦¦¶ 15•bP„)„ìTÌ¢6ŒiØVž/Åa¹ æ§üØ^Ë¢a/ÆÄ”U!=±{Bì½¢`'ÝŽ ÏÑQä&}‰6DéªóD8gŸ#ÊÒf(i=¿©Ì°üŒ[¦ÐRû6ûK¬ª¼£žK)r`MªjKA=‡>=Æ""YèÝ6ËaÁV]¢7ŒØ´äš‰‹¨ 7-MwqêA¤ >ŽŒÒ¼»ßÉqÃO!!œJû©*ÌÅ¡/$5¿H]À–PØè•Äÿ´H“"¶¿®ÃE¬ú-`°pDš•Eøy Ñlø+—± AlŠ]8ò¾¢ó®éÔÈ ´ë›˜1›À`˜;;£jóöèӑ>Þé?LÍc“ä}­±ÂKæÓ¿8ØÛQ(Ö8𰒉$õ$]ۑ êœR¦ª.‡”ÝR‘Îpzô*ÕªRImjW„ p`YSYê3<©hV»œÐ“‚7 ޽ûÔ5¢n·«G›iRUÒr‘J%êŸo~‡)+jfbo†ðš 1²>Q»v{ƒMòYß¹˜;©¦å½qԃ[„D6Jk·0H&žôûm¿®c.ì‚le2H(o¶x’•ž46t%¹ íÖ´VB!—ªUJ8ÞK1÷íւ]!bzÑÊ'Eñ9O?e#‹Rb Øý$Œãº7H}ŽKÓ#$¸Óïû›'`°¯Xz¶'N\Qö,˜ÓŽ1ˆ9j҆âû‚œ·ËRÊÀ·¡ãm.å¹áxÕÀo€­Õ*ÄCšçgí?ƒ‹SþR‡Û·—)Lcc¾9*÷w¡kQ3Wp|yÊíùíé '7¯×¯?àÛýÓýëõ#¼¼Ý>>>>>endobj +290 0 obj<>stream +xڕXßsÓF~Ï_±Ó§dÆ1$¡Ú'BÍLJ)q¦ÃL^ÎÒÉ>tÊÝÉÆÿ}¿Ý“éœ>éöÇ·»ß~æþà„žãÏ ó߬:¸X<{÷‚NNhQðÑù«—´ÈïßYGú›ªšRÏHQÑÖY0¶&Sã[i–N¹K™­š6hò÷­ršœµÁÓZy¼Õ´®±^SX«@Ɠ®ƒqºÜ-¾<§ã“³ù)ûÚê²<ÎuajÃ|®:-pU“jšÒdнÏi±ÖNÖ!¨›véu ê4'§ï[X÷ћªS/#+Ǿå/ð6d…dƒZ–šZã%2[#àáqÕú@KM¶á¯ªüÌ^l”[í§µ $ÎvdÂLnŒpJìû`ÊòQ<çwGløõ9>=Ÿ¿`ÓÐvYW€ËK0RöSÙÜœãÖº¯$õØ®m©çtUa|ñXRî@ôo€oÀ9ÂOʵ3ÎÙJÜ\ÇN@‹Ô9eªf”œV(-L»pæ’ÊòË^7Ê)dÊî<÷ìU^—íg‰[<©cI®M¦k¯£?ƒ¤ƒv•Ÿ|Žv wސږ ìlK¹ñÁ™%#Ìî˜i óÄõEžºM^U#0CÒ¶Öø4ٚ[_EP—ŠÛËÖSèð%…¹÷#½[-Z:1ڐìãcp¶’}ƒ‡Æ{ #C7fW^¤èoõH¡Žíg5:`‡uëY­èHÊN¯”ËKí%\¢­³É„·¶mQ-#|Àc_¦øß*äR*S‘3«5* ÐNAÔÂõÇxM°Ý:`g`žb¼÷{’* fcÇ&æõM»ÌøXY±é­Ζr˜VE†³¿Ñ1¶²äÈ7}G÷ÅÞïå¾ô)8WàÖ<7lF¦†ÔjÅØöUk( 3|5mMXOÆ>L"zÌÈÝ(ÚØ²E“KOû`ZI²(*›¶þ‹A9S¯ÄØ(Ú“ïÂg¶Ñi 0ÏÞ½ìöÒ¢³îQ¿²é3æ²R;æf.XÇÓÙà˜sS3ï?ÜÒ{]k§JúØ.1 ½S´ƒZåi0b5‰|…2×(y³ëô%¥…e2b3á ™XU"|ÆFH0Ý­*¬3< +6aoãc¼¿‹ï<>¨?‘ØŒ0©^öäl’äÔç}rÅu®õõwEÚƒ¹ÿƒ®h‚¦ÑX,¹Œ_¤T޾љ)v1áÎxâ²{—om_c+Ò‘ö+õUóÎï.CÈ+Ý­?àŽÛßu¦#ýK¹Žç¡Ä=_ç´DÇ[“ UâoøV#I¨‡E„âöð,jî[¦%æLµ#¦‰Ü"avK¸‹aŸir,<„Mі«ŒŒ×솽Å)d6×IS3QZtޜªA'7É«QÛ£üâÉ –P$Ý隝Т°®×lc.Db ÍÐM¯ Ñ"(¦]~ÁA—Y:Gàý¬â5­: ¹éWü‰„wJjiápl nòˆƒª2–o܈蘁†ù¬Ô!]ò™E?ùÆÖ9Óe…µ +| ñ”GY†—ÅrÌ:!Ñ/ÿ|òŸ 7U¼°{ÇÜìÚJ9æÌÍím¶¬yKº8!{ «Ø[Šc¬ûyZ2K‚Á8O@Ä2¡ï<éa…Bz³ª'Ԕ*ÓAô·Ò’AônT)JrjN6Êp:U¤š˜Æ?ƒñ…ÌÜz¢ ÙÊ´õ¿“’èhRÛ®¸ÊÆå2E2±Q:KÝñۆd?ã(èííǺéøÖCuÐ_ªnU)ÿÀ¯¿<}.ŠXøýôülþšä€¥ÇõÕŧ7Ÿ>ÓûË—ŸÞ\ÓÇۋ뫷8~{ùáæ’/\.þ9ø4ìÚendstream +endobj +291 0 obj +1722 +endobj +292 0 obj<>>>>>endobj +293 0 obj<>stream +xÚ}WMOI½ó+J¹,HÆÁ@ Ù=‘ˆd‘Øl6ÀJ‘|iÏ´=Ìt;Ý=xýï÷Uõ|yp"$ÀžéªW¯ª^Uÿ8šÑ~ftuNsʪ£wG¯?\ÒlF+<™__Ñc~}­ÉÒa£3£ÊrGÁ¬­Y™LÙHfE±Ð´uþ;á Zj*ý®sښX¸:Êã{³ôÊï&äüÞ Ø51èrE +ÇäéÉã·£3:]LÏÙÿ#ލ…סpeN+ˆŽEÇ®ZpÖEÚxàƒ­åze,,wTªmkð|>½dƒw+ +uVÀºå7EZ™RSt gqÜ֕öˆ®¤òªÒQû0¡\EE³X{©v.ÀJN*ËtŽß⏡KT©Ì»0 +¦l,hÒ´ªm³ÇQ[æŽax*a/á¯]Çbq2aÒ¬0¤ä‰Ã@CmÁSö¨ó y½V>gC#8¼-4Î#‘Ï•x“«@7Ï*šç” )`Ýþ§³:ª% QælTÆ»NYhüg.×´)ë@çS8 àÈqS( 0"ÿ^1µ…_zÐBͧ‹“QÎþf°[dw2.Ÿ=È +]µ!EÈ +Â0+Ë:ê!k‚:TcOpŒ0óCT@%!õéÆîHÿŒ“AUw0ÄI—øçêÅÿ»q±ø®—rƒâŽåNšjcÓ>Rã¯?\uÍÛ17oµ}}L7\´€žé`A'±Á.ݳ2Wm¸Æ¸0¬¿’ø$R霦W‚ò-fxÜx—×™†¡¤=y£ +ê“ɽ³—È–äDm—#ç0+œÉ¼>›|Êá>³üF'T.YZÜ ÎÚ"ÉêÄá78ÚZiDFåõ3$b\ìh\43ŠA±\/ëõš?‰ü …±F}eòáŒÖ\ր]ÁÔ•‚@Rh+™Ûìö v‘ugÎZ‚îø•…ªJÑ¡3”ƒOj*=6è)u C½Ùˆzôh†ïÝ àåµð‘‘|#¿(kKÞ¬‹6äÐ$»36+ë<µòø½.UmøªrґºBÚjô"þª‘c¯WÒÂ@jµÔÆ¢µ¾íÃÑÝ ?àr‡!Ò*Q`0~gw˜²]‚o2n)ew=5]kó“SÿxèùÆÙœá` À–>õZå,9Pè™Þ—±Ã)MŒ±‘-rÏÕJY¡ìZ3!^wÒaYo ÃEÊ!-õ ïò}% X ¸`ÎÇEÄ"²8ùƒ¾Ôl;PÎẰßð/ùxAȯ4I²?~{ Ò$Nð¡oÎüXF\Úv·_bÒSÎ^‹8îÉ[jsÄ7ˆxoTèî•ÃÒGð]LÓÄC€\¾Iu]>_»D5”]ȤTñšÚ<®™Ì<¬æFyƒÆFn†ÞhFÛPèûV/ñ°z/ ¡óf¦ŸÎÎÐWo›*™)ßáɛéüW½YáMä-ɭЭzV¥I+!Ø(µ +Q6EM;­x$ÑO6°È5Ý\¼,$Œ¬¶dÇè`é¡^†v^«I;ÅÓí×L!X/ÃÈ6ÔhÇDÁ‹U»(½”¹ÔN°=M´Ì¨•†eCʌNߜO¯›•uxdOðQ•B=/w‰v™RŽ_4k…ù!‹/îŠ{"ËóPŒÇ֏ëTÉÓfdF2Î$ hê©'Óâ`Úg¼k¡aÆ/Þ¦„ÿ ÒSâ.X¥KîíWF"ó½ÃêÚ»ýÃyâBc{6p$r N’½.]~ÊÓó7=Èœ÷¡pÉFhà‹Ç#§»MÌ/—£½ÆU.7 $·4qܒВ5®!¸äh'G𚦕¸HLœÒŸnËJ/§¨¹½õ{_‚?¿ŸÕ(\²gQ…ll)F¹€ùJ®Ãc ÒFÖÜÆ°/eÕd¾'È¿hÉox•uÀY‘²Åq#<è»öV—Íe‹ç-ì´"4ž’év!jdÄRe#š|m¡µ=p=’˜:×ݵQ%Óä³·õâ‚eq. ŽrcS©þÚR©Ø(K´W9njÉZ™Ö jïoíì„<${㍎Ì[º&'Š÷zï6jOJÇäL!q| au©´‚sn$ <6Ǻ¾t)OU;î~rµ‹nÝÜ,íhÎwíٗHs7¹nî&³ù5ÍçóÔoôþéó=¸UÜòú„v ô—²µ*S»âåÓ«ó3~÷ã§'º¿{÷åæËWúxûéöËÍ=}~zw÷_¿¿ýôpËG.¯.!§rà₿¸}<úçèþ¶ÁÃendstream +endobj +294 0 obj +1739 +endobj +295 0 obj<>>>>>endobj +296 0 obj<>stream +xÚ¥XßoÓH~ï_1oW¤&4-—ÂñTPCâíR_Öö:Y°½fwݐÿþ¾™];Ž“ “N  Þõüøæ›oÆü8[Ð%~-èzÉ¿óúìÍýÙó?oh± û'˗7t_œß̟ÝÃÁ‹tpN_mGµÚR[©\Se2§Ü–J•›Ê£=…µ +¤œ&Eë¾S¦¼.È68Ðô!Ý÷¦Ð³l;ã¿É4¸ëM³ªƒìõ’f‹ëù‡ìJãuGÖdåŸG\76PnŸ´ƒÃl ‡ÆÃc®¯/H5Æg².hò]¾†ÛÜ֙ip?™»˜xn}BŒEL‹SðºUNÁÂ`Ì 9[ÊáéŒÙ}ºt2~ã'Þ忯xM­vµ A1‘ý°¶¨IaÙ6n† ÿ hú?ت;»ZÎ_°¹Û鶪ÙJÓÔ#¸ I»íCõªþERÔ5½•IäÑ<JvN÷\žºó²˜pÒ5^a?Yû>–/:g¨=© 5bΗȬ÷©æÄåÙìúÕ|Éߙ'ÍpÕ² L"¦z„ä †.ªø© ¨Ï1RO2°á:éŸèÓ ´ÈÈRišB|¨¾|¼C’Jëꃤ|C¶YÌv×´³«ßwi¿<Ù¸±IZXÛ”øÛwYÕwIešï‚ÎY7î—1—õÏ\·hrÏù9í}µ9A£¯å®çt Z(p¹†ÁÌÿ ë }ž¬Iý²1UEª ¶V¨¿ª0sË4ÜÈhGάÖÁÓ±xÿ² Q¹*pŸnÖ–Ö +¼r:×à×4iäkj4{A%(}zè Çe›ÈÈpÃș߅Y·TYP¸‹z¥p&Ν®Á8Õ²ƒ]¦XeT“ëù>].wºðê(YXÃ9*§t†%e¹òûÊ +éÎŘ¿ã͊™lÂ=nܼ÷®5|›æIU¦`®wM” +­X:"7ÄKDÞU +ƒÆ¸¼«½ ­¨Õ™ªø‡)?Ò¦»sf WM‘6޶­Ò2=¾%BMàüØ ¼þDVŽ£ðyËNÏì`ÛmçD§éÃ( +Ú%žÊOQ‚RÆL??ïÜ +Û¸ûQŽ€ZŽ&+žUäãƒMÊvß{½ʚ{–aàÄGñÂgà+i\3+—,Êç Ø>qîm6,v{<ñ[ÅÈ„ÀÈr£±ÀÅ­©•|˜¡­ã‹¥¿ mq=®µ*¦.WºÑèO"…Ée'¼èHŸ"êÃðäk76“|˜¥PQip>N*$À²‚7eˆyÁ Õ@ðÁÄëôm×µ}(X%ÖÖ=/l·3—ÿ£¢$Ùȯ…v¼¸ äv_Ycäk@Œ}'˜)QÑRˆK”ê´ H˜ùښ´¿È{?iÑqÔê;¿kÅ%Ú!¯4:rÃÆp3^ØÉåf¦gq\3|è;á`Qý—i´/–/i¹\ÆÏOzûðé }ékøàµóL‘NUñ;—g7W—|÷ú?ºZ^Ï_‘¼óùöóWzw÷ñîóíúôðæÃû·xüöîã—;~áîþ쟳-Òdªendstream +endobj +297 0 obj +1818 +endobj +298 0 obj<>>>>>endobj +299 0 obj<>stream +xڅVMSÛH½ó+º8%UƉ[{’å1LE–Œ> ®ÊEXc¬¬ñJ2ÿ~_$lː-–4ýñúõëþ=ÐWü èúœ.®h¾:†'_Æ×4P¸ÀÉÕÍ5…ɧÁyÿsøN.›“O$T-%iYéÓ¦JuNqž|ÑmJEº>vÒ§".^)-©Pl9¯TBiNsUT1ÿêMŽÏª$•¡ §WZǕʫ’4¿qÞ¯t6¸èŸ3’¹^¿éó²S©bÏUÙ3É4Ò<Îè͈–:Kt»Ô´ÎØòÕ&çÃj tN:W9p¯âWŠ“¥t«ßë,§=+ý\Äëe:G¦ƒò³t•V±yT¿çÙ&IógD×ûVfJoquè +kUÀëÒyƺÀF¼Òˆ¸£,×bmÊ&Jú$s*7ó%ÍãRõKKó¹.Öº»5 {xã’Òm çfë'¼ÖmÝÅlT±ÓËÙùUÿÒ(æâH1!‚Œ ¥(ЋjxC%I €y_ož²´\B)/i©’VN¹Úҋ*J˜•]]ݪ\èÔ]çÔmá‹B¯¨JWŠ*m~û0G·i–Ñ“¢¤dqÁ-×)1NH¹†€!ËÖ£Gh¤‹…*ŽIKž±;çÒ$\ú)S+£î¹Î1yÙo<[òD tM–Æsú‚®ÄF2ÐÔ$±´Z‹|³zRE¿ɖ›r­æé‚uwLÛ6~À×Ú^R¼†àY)š@zA§qþJäS´ñN{ôª7´Œ_T=kÓL„_è,ÓÛzpm—&JNR6ê&oÆß ‹ßXf–ðé(q«¨ £úƒ²ŽhI´êææ9ªÙÂðc,j9«+å~ϗšGš1µ& +ÿ©“ràÇ3tùÞÖe[nÌn¤±5‹êh>°"5iÃì‚Ñ@}X^èÅÖ¬¥ƒ´k ãåL+,æâEújÉixÅðÎPíŒÄ¬»ÂH¾ü õV+Kӈ1Þ˶CµÈ îý^×¥êƒÎvrdö7m1Õz¥xòKtð—â}©Öu© ’g¡ßÉêm +J Óßv9`ô’]«­¦gg†u³Š—Vñ†íÛucNcøã®I_éE™OzS÷¤“÷ žW¯tՆ-—qÁÏ|X¨æ¢}sy®·aöú±¦\-ß·ÜpÖY:ƒoGj +ۊAᝠG}˟‘ ðh 7#ûB7&ûÎòoEí|Á{Yhìù÷ÂÁÇ3áŏP¸!M…?‘aˆØÃYÓ)RYCæÖc6¶˜†ôx'Ün³8ó£Ô ´Ø[ºôèËPº·&ºíMg¾¼½ éÎsFÂÈrG_<ŸŒ#M-?”"èúރVj¨ï”exçEá®J°`¹3ú.ÝQ„4aŏ©/&êˆ9Ai¦Òµhœ="žë…È +àz†QjlÛ\Šlxᣠnh ¥#åÑX†.ÒsȪk´#ÇB¹‘?õѯ‰GD4͗ÁwBq¡÷N³î#ë-*:„€˵Më;Ò`^hæE¸aÁ3Ú?‡^A#1v( ¸AMDÓ³ 4´:¹ÂF%œ#þƒ´ _¾˜ZÒ?æÖö|ŸczîVëÕñjuY¶âe¹3ç‹ûä¼#FbNo!nÓ¾Ú¥ãtð°.ºì™8Ø pa{4±f4ñFrö[° 6…tëނš.f˜¤?jWƒi-éDþ‘îQ„î9Ñÿ[_;AobˆÅÏÏ=£3’cà°ïMÐÁ>šÑZ:0³FÒl“¶;F¨G6lzM¼¦Äÿ:–?¨1Ñ ³ +¹Ÿ#É#Ô>7Ïàꆮê†½ÈަÁpߕ4‰óMœ±×Ÿ]ŸeÛ[7zã§öÎ#Ô^ìry}‰ÐÆáâáÉýÉ2¸f†endstream +endobj +300 0 obj +1604 +endobj +301 0 obj<>>>>>endobj +302 0 obj<>stream +xÚ-‹; Â0E÷ïWÜQ‡jÓ@¬cSb)ÄP󃶃øÀVñïۈÜ3Î}C>‹ÄéFÒÓzW‚1øL”Ø9üy:tî1¼>qì¦~œ°÷w¼.ý…²”fÿ–‹¤ +ÁW[üDct+meh”Q¶Òè‚Ôm=ëZ§ÒAy:Ð[W$¾endstream +endobj +303 0 obj +134 +endobj +304 0 obj<>>>/Annots 94 0 R>>endobj +305 0 obj<>stream +xÚ͜KsÜ6€ïú<&Uë1‚×JìJjýXK®½äB(iÖ3C-g¤¬óën Z¨ªµD§ÊŒîÏӍF£ñ˜üçDfÂþ'³Jey™­w'oÎO^¿5™ÙùU& “••ÎÎ/:o.¶mÖ]e§ÝþØî‡ŸÏÿ}òëù‰X K€ß$üöù4²Rûû.ˋ•¦Æ6;øD¾¿Î^¿-2)៳z…€ìSß^5ëþ‰<_å™ûËÕâÉG}’—àëÚ:¥’+I rÊ뷚\`¡´Â5|öíplwÙ£PÆÙYu½*B*õíã}ÛßoÚ?§åÊ,È©)¿)µ*­‰µ¶`ƒ,o©Ü¶­%¿t뻝 ÌÇýÅô­¿Te}ШŸx¿ÔJ-Ã_)W c'œ ±Ê~`l0WI±rsùCwlŽ›n ­Qߺ*Wà*NÃ~ϳ)áÞzÞ]V(Š%øJÅ=U˜Òš°ËLmó 6FOì³&üýâ¢oï7Í`[)VÅâÒQÊÔ:wɸÌm&À3µvCøñxÓöÇS…T£VU¢~‡úÜ^µ}»_·Îaº\–ÃTtÝ*ŠS~üyÈÐã"U¦É5Àú«‚ã4ì%Ê«Ç)LsgƒÒ¦óCÝÄùÔoìÜ_?Žcø…˜G݄K­>Lߚ¨„§Qõ@6}ù€(3Fç.ó…M|Øxh¥.´Æx~ÓF¼>B¬×5ø˜©›HéAdHÍB€ó¨àu¶nÛ¹J +j±%ÌĔósá23:Æ5Xº²«™.'޵5<Q¿Gµë›}·í®¿¹ÕKڈ]R†/î²Y@ »Jj0wIWûýÞ]¸d,Íò‹é”¹"wõni†3Wh,vO·ÍဠP¾d‹Æj#\z-aNcc4V‰¹õíf{l{g¬-j‹EpÊ`[Xºúµ¶ãˆ fpUcR{Ó¬¿¶ûËmeÔR-Nk‡TYÛµÌØ²ÀìäV„hm6ªC²“Sõî—~sOÁ’‹…e:û«J¸ÌfgHvumãÌe…³ðC{ü³ë¿ÚEÔ¥sµÌ”WEëP­ôP‡âÏÔ¡Z˜T¼õ0W.4ì-æÕ¡c+zb¨›8_Ñú…©»Ä6ùHÔM¬cl•gÊøåÔWÔ_Ì-9J+9(°“ +^!»™´ˆšÁ$掔.·Öä×x¨¨Õvwç²ìÙÝÅnsŒ»Œ±`_(ÁcœLýD´ U{ˆøŸéãi^€pW]$+ru +Õô£yÞT)ËÎÄ(æ¦v‰¾vž`c̀¹1˜åOoº.> ™¾K§e£nÂ5Ψ +y9a¿ 3Wª˜A¦œ^x‚ŸÌé5fƒ61W˜2¤+8x PÔ_ÎZô¹>ä*¨ûšÀÝ÷íp€•«ì¥Hø»’xRe 6˜¿+…E~:£3}‚a€punFô‰Bƒ£¨¿dåÌèó< Îóœ}ž‡ÁðH€x³¢ÏÓÌwÖz9žãê6ú\™„0˜ú¯öÂ¥Èg¹Z‘‰´¯¨Å|]Òóƒ³vÛ®Þf¼4!Ï 2îm¦Ž‡&“çö¾½ÜD–.€´B xs7µ‹)#ÀÖÖ®|‚#»á8ÀâÜl p^€p6EG`LÝÂJxŒÂHÀ›ÚÝõôÀMüˆêdþ-\‹b‹`1ó2š«Ã\‡Š.€yœœûØDu¡>†b0$‘ÞuǛXmV¿0m\®tÈÂ~Oã+²^ÖeaÄ]8K=¯Á®Øó˜¥Ê?ՙ½Lx¦qÎó՜ã¦˄›˜Œ–ONÀÝç”Gþ¥SsÝþñÓᏟéîåkÒd€K|˜ãޒbƒ¸¤W93ߪz˜”Î#œFýÄ[fÑ)‹Dt Á‹ !Â"HȧAžç]Àó2¹ÝæÊ°AÆQ$@¨ÏÍþ:6U§ŠœàH€pÑõƒiÃ4ÀY$@,˜&JüÏ©‘‡BM #­qäe]?iÜš–;wþz߯ +¦ ŸÇÒғ¢LŠ=µÐ +xÎÇËËXᡙq0ÐùDõt°Ÿq˓é*§UÞa`‹tEïµ>¼úr¿ìÊGT^Ù?”ÐáÅÐR^=&T +:\€1¶˜“J¹*Ÿ°óhngм€œ³È3uÈ\pƒÂH€`oúÍõÍqßðYVñBː,¾Ö;åÀ󵮟tÊ1ÐМæêÙ§¬00¯ ì]³Û5ñ»jÀ)Q~‡#Ú£ï!ÕҙÉóòÉÄ 9™ã«¶¢Wæá 9™þýî#•ÓÝe’F¢nB…{…ziǒÁ­$½.p±§d¸®*õ”Ðö, =Îòjn`{T)¦Ë à˽»ÝE|Ÿ øs·ì!Ò¥Ӆ+*8Î I$@¯iš¾YÃÛȞœ1vnó)B¢ÀÒ,f&W¶(wI¢´ð ßöëwG<@´&#NTÃ.ÜP‹Eœ¨é‚cfÌyF§yΉ:à`$@°™qçyˆ7#òˆU˜°H€Xp% ;€3QHòN°‡ÅÎ)éR5ýd^€`Cèýà/¤BÐhV<ÔN¦xRéäQ.<ŒžN¦˜]7y’ Œ€„ÝDšyæ"#€a7ÁÒaG %! ì.üsíݎVAóL'f©Q®%+ÛjTmµzRÑæQn$8ŠºÕìŠÍ“4ô$ìöoK›èÁ¨ çËjbuê}Ó_ohhŠçÿ®‡¬â£TÖ÷¨1ŽR9¼µÃô-u;íI9|”“ànºäÏIýFoÏß^(èié¾þ~QËM¼ßvÑHÑÅ2 `ï÷—ÐË*bS¤ém¥Òð=”Ú?üì00>×G ÉGÝjN91*CF‡+倄ÝDrCèÎaʗÚ'<¬è‰¡[ÚU^)ø·ëf›È¤ƒ6¸šEݳÞ*ŽÊ°õ…̐°›H£w_xw†N­Ãÿ̤¦7&®,* ½KÈN¿|:Ëκ«ãŸMßf_°™xßìïš-^bÀmÇ«J9“6䬞üjD4>>>/Annots 117 0 R>>endobj +308 0 obj<>stream +xÚ͚_sÓ8Àßû)üumY¶åGÚk¹ÎôJIÒû3ËIbHœžã÷¿]i¯\"çnh)0U»¿X»«Ý•ÌßGqÁï8H2ü3_ÎŽN.Š@DÁlÄid¹ fw¯fåÇe¬Áٺ骦ۼž}>:ŸEaüˆñcò6ÈE™,àsı +c-ƒ)âí}pr!A¿0A–Fø}oî>o7]ÝÜ{¿ˆ³á›&î7‘€vŸ*Š)*MC9@ƒúuëC1e@©$T”0¨¯fuÓ}xíá1ðŠ4Ì<#`xà ý$¦»«°Œ€!•Í~×R’ ÍE†t¹*ï+d‰4Äxƒ…Oó+V#Q™¤`ª]Tê=1F¬Cý·Ø³<œgyHôY˜`$@°iÙmÛ²«×/lcŠ8G9L æ‡WgëåºõE"‡RC¤ ¤/¹6°¤Ó‹ˆåF¦ ¬<ÚyÚ²H€X}<æ`ž„ï‡"Ìà1Áú‚ô”3‘À3ÌÍñÛ«±ÍLÃ9ÇXã0š'Ü» ²“Lñ”{ðGn×c×ájôˆmWø©.M7-¤Ð‘ÝÚ'b Ž#K¬}‹iKæÃG#Ë:]–ó/:ÚäO¶ü˜¹Ó"ƒµÀš" ádF½¹ÓW +OQw#Öfúhív™C³ôçF¦ŽæŽ`»0 ØÍrÝyhLë<ºÄ¥‘Ѽ–i ÒN>`‘ÀAËdêXåÅÐVÀ.“RX\üøæ¢b$ˆ эJ”B`F,ˆ”ÞÓj4„zm !mβò€ê•Ñåù𱬀FýR-ÊíÒA €^Ï= ˜ÔTùˆ)c?&!Y»(Ш?ê»î“Î#È=“Ë=ÞÖÕ,Í +]tSl÷Ì ¯fi™‚;)¿î·S]ZÃá˜iKZ·ûAL×tx’™·¤ÛfQ/»ª­îüMCJÜk’,óݶ{ØvºÊF?3Ó{¼†½Q*]»¤óoZÎÉEJç0’¦~IO²àN@ãpš™%ʱoì4!b4(ÇÐ4q¦å?ÞÄÁôaj£iɇÊR €YèŽæ G]–/9<OÎZ…,_p2u<4(øÛ…‘Á(³™&P=oxŠx$$‘®{™Â§»´W˜P’˜ªß˜ãKö¼–æ ç¶ÇÉKi3ì,– +° «ƒÊ-SFsåh.Ž¢yuX”3}Ü5 Ö0N³·ð¥t®Œ§lÝ9(0gDß »W¬g°B+`ìõPÍëE=÷ðÛµÇ<P,\uñÆÀ{¶ø ž(1e[ +3`Á ‰~üßëê«7|˜ú*€ÖU¹,š–܄0e KGÑ<¡Î¶m[5¾fÐíxOå𬝙=ñeÕ~¯ ¿×déc¿Þ•fÐ{M±9ó¶é-KájMÍë5¦lN׃ǢyB·ØŒ€;Öl‡gÈ·Wñ|½ñÿñ\žëj­Ë0ÏåêÀ¶„©cºÆ5;0š'Üe³éÊf^QåÕ ªo£ˤ.á +ÏFfÀ –¥¦~OªÕÚß2}ŒÐr³C£yâ¹띗`1­°«—In²23øN[/uà·¯€ïXۆ8š&ޝ±/'Óv8çL׋îkÙz² #à*±8<š'ÞU=¯šï^€ÌUУuk°û¶ªVPn9é'…HFv:uæÚÂzð½vZÂ>Ð ôl½ZùnºÇä›Â¥Ò<Ñn¯/ÿô™½WÇ3¾%q`V eÉÝWÄæ…[2 ’§ß6]µò¿pKvyªË¡oìû‡vÿ3JQ¿v¬ðp’äôF?8»½™»¦ùvSµ›à·²Ù–K$Ǚ +Žs¡¶®Éïþ˲Γendstream +endobj +309 0 obj +1826 +endobj +310 0 obj<>endobj +311 0 obj<>endobj +312 0 obj<>endobj +313 0 obj<>endobj +314 0 obj<>endobj +315 0 obj<>endobj +316 0 obj<>endobj +317 0 obj<>endobj +318 0 obj<>endobj +319 0 obj<>endobj +320 0 obj<>endobj +321 0 obj<>endobj +322 0 obj<>endobj +323 0 obj<>endobj +324 0 obj<>endobj +325 0 obj<>endobj +326 0 obj<>endobj +327 0 obj<>endobj +328 0 obj<>endobj +329 0 obj<>endobj +330 0 obj<>endobj +331 0 obj<>endobj +332 0 obj<>endobj +333 0 obj<>endobj +334 0 obj<>endobj +335 0 obj<>endobj +336 0 obj<>endobj +337 0 obj<>endobj +338 0 obj<>endobj +339 0 obj<>endobj +340 0 obj<>endobj +341 0 obj<>endobj +342 0 obj<>endobj +343 0 obj<>endobj +344 0 obj<>endobj +345 0 obj<>endobj +346 0 obj<>endobj +347 0 obj<>endobj +348 0 obj<>endobj +349 0 obj<>endobj +350 0 obj<>endobj +351 0 obj<>endobj +352 0 obj<>endobj +353 0 obj<>endobj +354 0 obj<>endobj +355 0 obj<>endobj +356 0 obj<>endobj +357 0 obj<>endobj +358 0 obj<>endobj +359 0 obj<>endobj +360 0 obj<>endobj +361 0 obj<>endobj +362 0 obj<>endobj +363 0 obj<>endobj +364 0 obj<>endobj +365 0 obj<>endobj +366 0 obj<>endobj +367 0 obj<>endobj +368 0 obj<>endobj +369 0 obj<>endobj +370 0 obj<>endobj +371 0 obj<>endobj +372 0 obj<>endobj +373 0 obj<>endobj +374 0 obj<>endobj +375 0 obj<>endobj +376 0 obj<>endobj +377 0 obj<>endobj +378 0 obj<>endobj +379 0 obj<>1<>2<>4<>]>>>>endobj +xref +0 380 +0000000000 65535 f +0000000015 00000 n +0000000220 00000 n +0000001786 00000 n +0000001860 00000 n +0000001939 00000 n +0000002025 00000 n +0000002103 00000 n +0000002180 00000 n +0000002259 00000 n +0000002342 00000 n +0000002419 00000 n +0000002501 00000 n +0000002586 00000 n +0000002645 00000 n +0000002697 00000 n +0000002782 00000 n +0000002834 00000 n +0000002918 00000 n +0000003021 00000 n +0000003059 00000 n +0000003163 00000 n +0000003267 00000 n +0000003371 00000 n +0000003475 00000 n +0000003520 00000 n +0000003625 00000 n +0000003729 00000 n +0000003760 00000 n +0000003811 00000 n +0000003896 00000 n +0000003920 00000 n +0000004025 00000 n +0000004129 00000 n +0000004160 00000 n +0000004216 00000 n +0000004301 00000 n +0000004351 00000 n +0000004436 00000 n +0000004467 00000 n +0000004520 00000 n +0000004605 00000 n +0000004661 00000 n +0000004746 00000 n +0000004805 00000 n +0000004889 00000 n +0000004927 00000 n +0000004979 00000 n +0000005064 00000 n +0000005088 00000 n +0000005192 00000 n +0000005297 00000 n +0000005402 00000 n +0000005507 00000 n +0000005612 00000 n +0000005717 00000 n +0000005821 00000 n +0000005926 00000 n +0000006031 00000 n +0000006136 00000 n +0000006241 00000 n +0000006346 00000 n +0000006451 00000 n +0000006556 00000 n +0000006661 00000 n +0000006765 00000 n +0000006870 00000 n +0000006975 00000 n +0000007080 00000 n +0000007185 00000 n +0000007290 00000 n +0000007395 00000 n +0000007500 00000 n +0000007604 00000 n +0000007709 00000 n +0000007814 00000 n +0000007919 00000 n +0000008024 00000 n +0000008129 00000 n +0000008234 00000 n +0000008339 00000 n +0000008444 00000 n +0000008549 00000 n +0000008654 00000 n +0000008759 00000 n +0000008864 00000 n +0000008969 00000 n +0000009074 00000 n +0000009179 00000 n +0000009284 00000 n +0000009389 00000 n +0000009494 00000 n +0000009598 00000 n +0000009701 00000 n +0000009804 00000 n +0000010136 00000 n +0000010241 00000 n +0000010346 00000 n +0000010450 00000 n +0000010555 00000 n +0000010660 00000 n +0000010766 00000 n +0000010871 00000 n +0000010976 00000 n +0000011081 00000 n +0000011186 00000 n +0000011291 00000 n +0000011396 00000 n +0000011501 00000 n +0000011606 00000 n +0000011711 00000 n +0000011816 00000 n +0000011922 00000 n +0000012028 00000 n +0000012134 00000 n +0000012240 00000 n +0000012345 00000 n +0000012450 00000 n +0000012639 00000 n +0000012673 00000 n +0000012707 00000 n +0000013673 00000 n +0000013722 00000 n +0000013771 00000 n +0000013820 00000 n +0000013869 00000 n +0000013918 00000 n +0000013967 00000 n +0000014016 00000 n +0000014065 00000 n +0000014114 00000 n +0000014163 00000 n +0000014212 00000 n +0000014261 00000 n +0000014310 00000 n +0000014359 00000 n +0000014408 00000 n +0000014457 00000 n +0000014506 00000 n +0000014555 00000 n +0000014604 00000 n +0000014653 00000 n +0000014702 00000 n +0000014751 00000 n +0000014800 00000 n +0000014849 00000 n +0000014898 00000 n +0000014947 00000 n +0000014996 00000 n +0000015045 00000 n +0000015094 00000 n +0000015143 00000 n +0000015192 00000 n +0000015241 00000 n +0000015290 00000 n +0000015339 00000 n +0000015388 00000 n +0000015437 00000 n +0000015486 00000 n +0000015535 00000 n +0000015584 00000 n +0000015633 00000 n +0000015682 00000 n +0000015731 00000 n +0000015780 00000 n +0000015829 00000 n +0000015878 00000 n +0000015927 00000 n +0000015976 00000 n +0000016025 00000 n +0000016074 00000 n +0000016123 00000 n +0000016172 00000 n +0000016221 00000 n +0000016270 00000 n +0000016319 00000 n +0000016368 00000 n +0000016417 00000 n +0000016466 00000 n +0000016515 00000 n +0000016564 00000 n +0000016613 00000 n +0000016662 00000 n +0000016711 00000 n +0000016760 00000 n +0000016809 00000 n +0000016858 00000 n +0000016907 00000 n +0000016956 00000 n +0000017005 00000 n +0000017394 00000 n +0000017548 00000 n +0000023898 00000 n +0000023920 00000 n +0000024015 00000 n +0000024117 00000 n +0000024137 00000 n +0000024294 00000 n +0000025338 00000 n +0000025359 00000 n +0000025562 00000 n +0000026701 00000 n +0000026723 00000 n +0000026855 00000 n +0000027152 00000 n +0000027173 00000 n +0000027287 00000 n +0000027477 00000 n +0000027498 00000 n +0000027640 00000 n +0000028547 00000 n +0000028568 00000 n +0000028710 00000 n +0000030227 00000 n +0000030249 00000 n +0000030391 00000 n +0000031378 00000 n +0000031399 00000 n +0000031513 00000 n +0000031699 00000 n +0000031720 00000 n +0000031871 00000 n +0000032582 00000 n +0000032603 00000 n +0000032786 00000 n +0000033923 00000 n +0000033945 00000 n +0000034119 00000 n +0000034818 00000 n +0000034839 00000 n +0000034953 00000 n +0000035157 00000 n +0000035178 00000 n +0000035329 00000 n +0000035880 00000 n +0000035901 00000 n +0000036062 00000 n +0000037185 00000 n +0000037207 00000 n +0000037368 00000 n +0000038240 00000 n +0000038261 00000 n +0000038412 00000 n +0000039065 00000 n +0000039086 00000 n +0000039265 00000 n +0000040296 00000 n +0000040317 00000 n +0000040486 00000 n +0000041733 00000 n +0000041755 00000 n +0000041924 00000 n +0000042929 00000 n +0000042950 00000 n +0000043064 00000 n +0000043261 00000 n +0000043282 00000 n +0000043447 00000 n +0000044267 00000 n +0000044288 00000 n +0000044448 00000 n +0000045354 00000 n +0000045375 00000 n +0000045522 00000 n +0000046370 00000 n +0000046391 00000 n +0000046557 00000 n +0000048020 00000 n +0000048042 00000 n +0000048198 00000 n +0000049787 00000 n +0000049809 00000 n +0000049942 00000 n +0000051802 00000 n +0000051824 00000 n +0000051947 00000 n +0000053725 00000 n +0000053747 00000 n +0000053870 00000 n +0000055791 00000 n +0000055813 00000 n +0000055955 00000 n +0000057677 00000 n +0000057699 00000 n +0000057822 00000 n +0000059667 00000 n +0000059689 00000 n +0000059831 00000 n +0000061617 00000 n +0000061639 00000 n +0000061771 00000 n +0000063564 00000 n +0000063586 00000 n +0000063718 00000 n +0000065528 00000 n +0000065550 00000 n +0000065682 00000 n +0000067571 00000 n +0000067593 00000 n +0000067735 00000 n +0000069410 00000 n +0000069432 00000 n +0000069546 00000 n +0000069751 00000 n +0000069772 00000 n +0000069928 00000 n +0000072881 00000 n +0000072903 00000 n +0000073060 00000 n +0000074957 00000 n +0000074979 00000 n +0000075034 00000 n +0000075139 00000 n +0000075283 00000 n +0000075386 00000 n +0000075504 00000 n +0000075625 00000 n +0000075739 00000 n +0000075843 00000 n +0000076008 00000 n +0000076116 00000 n +0000076231 00000 n +0000076336 00000 n +0000076444 00000 n +0000076552 00000 n +0000076661 00000 n +0000076777 00000 n +0000076875 00000 n +0000077041 00000 n +0000077158 00000 n +0000077277 00000 n +0000077401 00000 n +0000077526 00000 n +0000077676 00000 n +0000077817 00000 n +0000077926 00000 n +0000078091 00000 n +0000078230 00000 n +0000078341 00000 n +0000078484 00000 n +0000078607 00000 n +0000078758 00000 n +0000078863 00000 n +0000079016 00000 n +0000079130 00000 n +0000079258 00000 n +0000079372 00000 n +0000079495 00000 n +0000079611 00000 n +0000079760 00000 n +0000079889 00000 n +0000080026 00000 n +0000080156 00000 n +0000080281 00000 n +0000080384 00000 n +0000080534 00000 n +0000080643 00000 n +0000080761 00000 n +0000080900 00000 n +0000081034 00000 n +0000081186 00000 n +0000081291 00000 n +0000081420 00000 n +0000081537 00000 n +0000081649 00000 n +0000081825 00000 n +0000081928 00000 n +0000082067 00000 n +0000082196 00000 n +0000082324 00000 n +0000082442 00000 n +0000082548 00000 n +0000082702 00000 n +0000082871 00000 n +0000082971 00000 n +0000083082 00000 n +0000083209 00000 n +0000083304 00000 n +0000083431 00000 n +0000083553 00000 n +trailer +<]>> +startxref +83781 +%%EOF diff --git a/doc/sum.shtml b/doc/sum.shtml new file mode 100644 index 0000000000..555b1f0ccc --- /dev/null +++ b/doc/sum.shtml @@ -0,0 +1,878 @@ + + + + + + + CUPS Software Users Manual + + + +

Preface

+ +

This software users manual describes how to use the Common UNIX Printing +SystemTM ("CUPSTM") Version 1.1.5. + + + + +

Document Overview

+ +

This software users manual is organized into the following sections:

+ + + +

Notation Conventions

+ +

Various font and syntax conventions are used in this guide. Examples and +their meanings and uses are explained below: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Example   Description
 
lpstat
+ lpstat(1)
   The names of commands; the first mention of a command or + function in a chapter is followed by a manual page section + number.
 
/var
+ /usr/share/cups/data/testprint.ps
   File and directory names.
 
Request ID is Printer-123   Screen output.
 
lp -d printer filename ENTER   Literal user input; special keys like ENTER are + in ALL CAPS.
 
12.3   Numbers in the text are written using the period (.) to indicate + the decimal point.
+ + +

Abbreviations

+ +The following abbreviations are used throughout this manual: + +
    +
    + +
    kb +
    Kilobytes, or 1024 bytes
      + +
    Mb +
    Megabytes, or 1048576 bytes
      + +
    Gb +
    Gigabytes, or 1073741824 bytes
      + +
    +
+ +

Other References

+ +
    +
    + +
    CUPS Software Administrators Manual + +
    An administration guide for the CUPS software.
      + +
    CUPS Software Programmers Manual + +
    A programmer guide for interfacing with and/or extending the CUPS + software.
      + +
    +
+ + + + + +

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(1)) and Berkeley +(lpr(1)) printing commands. Type the following command to +print a file to the default (or only) printer on the system: + +

    +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, serial, or USB +port, or available over the network. + +

Use the lpstat(1) command to see a list of available printers: + +

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

Use the -d option with the lp command to +print to a specific printer: + +

    +lp -d printer filename ENTER
    +
+ +

or the -P option with 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 and lpr commands allow you to pass +printer options using the -o option: + +

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

The available printer options vary depending on the printer. The standard +options are described in Chapter 3, "Standard +Printing Options". + +

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. Use the -o +Collate=True option to get collated copies : + +

    +lp -n num-copies -o Collate=True filename ENTER
    +lpr -#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. Use the +-p option to see which files and printers are active: + +

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

Use the -o and -p options together to show +the jobs and the printers: + +

    +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 +fully-functional web server. To use your web browser to monitor the +printers on your system, open the URL: + +

+ +

From there you can view the status of classes, jobs, and printers +with the click of a button! + +

Canceling a Print Job

+ +

The cancel(1) and lprm(1) commands cancel +a print job: + +

    +cancel job-id ENTER
    +lprm job-id ENTER
    +
+ +

The job-id is the 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 and lpr commands. + +

General Options

+ +

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

Setting the Orientation

+ +

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

    +lp -o landscape filename ENTER
    +lpr -o landscape filename ENTER
    +
+ + +

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
    +lpr -o media=Letter,Transparency filename ENTER
    +lpr -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 not 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. + +

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 -o +sides=two-sided-short-edge option is suitable for landscape +pages, while the -o sides=two-sided-long-edge option is +suitable for portrait pages: + +

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

The default is to print single-sided: + +

    +lp -o sides=one-sided filename ENTER
    +lpr -o sides=one-sided filename ENTER
    +
+ +

Banner Options

+ +

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

Selecting the Banner Page(s)

+ +

The -o jobsheets=start,end option sets the banner page(s) to +use for a job: + +

    +lp -o job-sheets=none filename ENTER
    +lp -o job-sheets=standard filename ENTER
    +lpr -o job-sheets=classified,classified filename ENTER
    +
+ +

If only one banner file is specified, it will be printed before the +files in the job. If a second banner file is specified, it is printed after +the files in the job. + +

The available banner pages depend on the local system configuration; CUPS +includes the following banner files: + +

    + +
  • none - Do not produce a banner page. + +
  • classified - A banner page with a "classified" + label at the top and bottom. + +
  • confidential - A banner page with a + "confidential" label at the top and bottom. + +
  • secret - A banner page with a "secret" label + at the top and bottom. + +
  • standard - A banner page with no label at the + top and bottom. + +
  • topsecret - A banner page with a "top secret" + label at the top and bottom. + +
  • unclassified - A banner page with an + "unclassified" label at the top and bottom. + +
+ +

Document Options

+ +

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

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
    +lpr -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-ranges option. + +

The default is to print all pages. + +

Selecting Even or Odd Pages

+ +

Use the -o page-set=set option to select the even or odd pages: + +

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

The default is to print all pages. + +

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

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=10 filename ENTER
    +lp -o cpi=12 filename ENTER
    +lpr -o cpi=17 filename ENTER
    +
+ +

The default characters per inch is 10. + +

Setting the Number of Lines Per Inch

+ +

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

    +lp -o lpi=6 filename ENTER
    +lpr -o lpi=8 filename ENTER
    +
+ +

The default lines per inch is 6. + +

Setting the Number of Columns

+ +

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

    +lp -o columns=2 filename ENTER
    +lpr -o columns=3 filename ENTER
    +
+ +

The default number of columns is 1. + +

Setting the Page Margins

+ +

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

    +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
    +lpr -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
    +lpr -o prettyprint filename ENTER
    +
+ +

Image Options

+ +

The following options apply when printing image files. + +

Positioning the Image

+ +

The -o position=name option specifies the position of the +image on the page: + +

    + +
  • center - Center the image on the page (default) + +
  • top - Print the image centered at the top of the page + +
  • left - Print the image centered on the left of page + +
  • right - Print the image centered on the right of the page + +
  • top-left - Print the image at the top left corner of + the page + +
  • top-right - Print the image at the top right corner of + the page + +
  • bottom - Print the image centered at the bottom of + the page + +
  • bottom-left - Print the image at the bottom left + corner of the page + +
  • bottom-right - Print the image at the bottom right + corner of the page + +
+ +

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
    +lpr -o ppi=value filename ENTER
    +
+ +

The percent value 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
    +lpr -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
+ +

The default hue adjustment is 0. + +

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

The default saturation is 100. + + +

HP-GL/2 Options

+ +

The following options apply to HP-GL/2 files. + +

Printing in Black

+ +

The -o blackplot option specifies that all pens should +plot in black: + +

    +lp -o blackplot filename ENTER
    +lpr -o blackplot filename ENTER
    +
+ +

The default is to use the colors defined in the plot file or the +standard pen colors defined in the HP-GL/2 reference manual from +Hewlett Packard. + +

Fitting the Plot on the Page

+ +

The -o fitplot option specifies that the plot should be +scaled to fit on the page: + +

    +lp -o fitplot filename ENTER
    +lpr -o fitplot filename ENTER
    +
+ +

The default is to use the absolute distances specified in the plot +file. + +

+ + + +
+ NOTE: + +

This feature depends upon an accurate plot size (PS) + command in the HP-GL/2 file. If no plot size is given in the file + than the HP-GL/2 filter assumes the plot is ANSI E size. +

+ +

Setting the Default Pen Width

+ +

The -o penwidth=value option specifies the default pen +width for HP-GL/2 files: + +

    +lp -o penwidth=value filename ENTER
    +lpr -o penwidth=value filename ENTER
    +
+ +

The pen width value specifies the pen width in micrometers. +The default value of 1000 produces lines that are 1 millimeter in width. +Specifying a pen width of 0 produces lines that are exactly 1 pixel wide. + +

+ + + +
+ NOTE: + +

This option is ignored when the pen widths are set in the + plot file. +

+ +

Raw or Unfiltered Output

+ +

The -o raw option allows you to send files directly to +a printer without filtering. This is sometimes required when printing +from applications that provide their own "printer drivers" for your +printer: + +

    +lp -o raw filename ENTER
    +lpr -o raw filename ENTER
    +
+ +

The -l option can also be used with the +lpr command to send files directly to a printer: + +

    +lpr -l filename ENTER
    +
+ + +

4 - Saving Printer Options and Defaults

+ +

This chapter describes how to save printer options for your printer and +set your own default printer. + +

Printer Options

+ +

Each printer supports a large number of options, which you learned about +in Chapter 3, "Standard Printer Options". +Rather than specifying these options each time you print a file, CUPS allows +you to save them as "default" options for the printer. + +

The lpoptions(1) command saves the options for your printers. +Like the lp and lpr commands, it accepts printer +options using the -o argument: + +

    +lpoptions -o media=A4 -o sides=two-sided-long-edge ENTER
    +lpoptions -o media=Legal -o scaling=100 ENTER
    +
+ +

Once saved, any lp or lpr command will +use them when you print. + +

Setting Options for a Specific Printer

+ +

The previous example shows how to set the options for the default +printer. The -p printer option specifies the options are +for another printer: + +

    +lpoptions -p laserjet -o media=A4 -o sides=two-sided-long-edge ENTER
    +lpoptions -p deskjet -o media=Legal -o scaling=100 ENTER
    +
+ +

Viewing the Current Defaults

+ +

The lpoptions command can also be used to show the current +options by not specifying any new options on the command-line: + +

    +lpoptions ENTER
    +media=A4 sides=two-sided-long-edge
    +lpoptions -p deskjet ENTER
    +media=Legal scaling=100
    +
+ +

Setting the Default Printer

+ +

The administrator normally will set a system-wide default printer +that is normally used as the default printer by everyone. Use the +-d printer option to set your own default printer: + +

    +lpoptions -d deskjet ENTER
    +
+ +

The printer can be local (deskjet) or remote +(deskjet@server). + +

Printer Instances

+ +

Besides setting options for each print queue, CUPS supports +printer instances which allow you to define several different +sets of options for each printer. You specify a printer instance using +the slash (/) character: + +

    +lpoptions -p laserjet/duplex -o sides=two-sided-long-edge ENTER
    +lpoptions -p laserjet/legal -o media=Legal ENTER
    +
+ +

The lp and lpr commands also understand +this notation: + +

    +lp -d laserjet/duplex filename ENTER
    +lpr -P laserjet/legal filename ENTER
    +
+ +

Removing Instances

+ +

Use the -x printer/instance option to remove a printer +instance that you no longer need: + +

    +lpoptions -x laserjet ENTER
    +lpoptions -x laserjet/duplex ENTER
    +lpoptions -x laserjet/legal ENTER
    +
+ +

The -x option only removes the default options for that +printer and instance; the original print queue will remain until deleted +with the lpadmin(8) command by the administrator. + + +

A - Software License +Agreement

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

+

CUPS Software Version Description


+CUPS-SVD-1.1
+Easy Software Products
+Copyright 1997-2000, All Rights Reserved
+
+
+

Table of Contents

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

1 Scope

+

1.1 Identification

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

1.2 System Overview

+

CUPS provides a portable printing layer for UNIX®-based 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 ("IPP") as the basis for +managing print jobs and queues. The Line Printer Daemon ("LPD") Server +Message Block ("SMB"), and AppSocket (a.k.a. JetDirect) protocols are +also supported with reduced functionality. CUPS adds network printer +browsing and PostScript Printer Description ("PPD") based printing +options to support real-world printing under UNIX.

+

CUPS also includes a customized version of GNU Ghostscript +(currently based off GNU Ghostscript 5.50) and an image file RIP that +are used to support non-PostScript printers. Sample drivers for HP and +EPSON printers are included that use these filters.

+

1.3 Document Overview

+

This software version description document is organized into the +following sections:

+ +

2 References

+

2.1 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-IPP-1.1: CUPS Implementation of IPP
  • +
  • CUPS-SAM-1.1.x: CUPS Software Administrators Manual
  • +
  • CUPS-SDD-1.1: CUPS Software Design Description
  • +
  • CUPS-SPM-1.1.x: 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: CUPS Software Version Description
  • +
+

2.2 Other Documents

+

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

+ +

3 Additions

+

CUPS 1.1 includes many new features from the 1.0.x releases.

+

3.1 Filters

+

3.1.1 imagetoraster, imagetops +

+

The image file filters have been upgraded to support conversion of +Microsoft Bitmap ("BMP") and Alias PIX files.

+

3.1.2 pdftops

+

A new pdftops filter has been developed that is based on the +excellent Xpdf 0.90 software from Derek B. Noonburg. The new filter is +faster, smaller, and considerably more reliable than the +Ghostscript-based filter in CUPS 1.0.

+

3.1.3 pstoraster

+

The pstoraster filter has been integrated with GNU +GhostScript 5.50. The new RIP supports most Level 3 PostScript language +features.

+

3.1.4 rastertoepson

+

The new rastertoepson filter supports EPSON printers +using the ESC/P or ESC/P2 command sets. PPDs are supplied for 9-pin, +24-pin, Stylus Color, and Stylus Photo printers.

+

3.2 User-Defined Printers and Options

+

The new lpoptions command allows users to configure +default document options and create additional "instances" of existing +printers, each with unique options.

+

The lp, lpr, and lpstat + commands have been upgraded to use this option and printer instance +information automatically.

+

3.3 Daemons

+

CUPS 1.1 includes two new daemons that provide enhanced network +printing support.

+

3.3.1 cups-lpd

+

The cups-lpd daemon provides support for clients using +the Line Printer Daemon protocol.

+

3.3.2 cups-polld

+

The cups-polld daemon provides remote polling services +for the scheduler.

+

3.4 Commands

+

CUPS 1.1 includes several new printing commands.

+

3.4.1 lpoptions

+

The lpoptions command provides user-defined printers +and options.

+

3.4.2 lpmove

+

The lpmove command moves a print job to a new +destination.

+

3.4.3 lpinfo

+

The lpinfo command lists the available PPD files or +devices.

+

3.5 IPP Implementation

+

CUPS 1.1 adds support for the set-job-attributes + extension operation as well as two new CUPS-specific extension +operations to determine which devices and printer drivers are available +on the system.

+

Further information on the CUPS implementation of IPP can be found +in CUPS-IPP-1.1.

+

4 Changes

+

CUPS 1.1 includes many changes from the 1.0.x releases.

+

4.1 Directory Structure

+

The directory structure in CUPS 1.1 has been modified to conform to +the Filesystem Hierarchy Standard, 2.0. The following table describes +the new file locations. +

+ + + + + + + + + + + + + + + + +
Table 1: Directory structure +changes from CUPS 1.0.x to 1.1.x.
DescriptionCUPS 1.0.xCUPS 1.1.x
Backends/var/cups/backend/usr/lib/cups/backend
CGI programs/var/cups/cgi-bin +/usr/lib/cups/cgi-bin
Configuration files/var/cups/conf/etc/cups
Documentation/usr/share/cups/doc +/usr/share/doc/cups
Filter programs/var/cups/filter +/usr/lib/cups/filter
Interface scripts/var/cups/interfaces +/etc/cups/interfaces
Locale data/usr/lib/locale/usr/share/locale
Log files/var/cups/logs/var/log/cups
PPD files/var/cups/ppd/etc/cups/ppd
Request files/var/cups/requests/var/spool/cups
+
+

+

4.2 IPP Implementation

+

CUPS 1.1 is based on version 1.1 of the Internet Printing Protocol.

+

The new scheduler supports the create-job and +send-document operations. In addition, the job-sheets +, job-sheets-default, and job-sheets-supported + attributes are now supported for banner pages.

+

The CUPS-get-printers and CUPS-get-classes + operations have been upgraded to support limited filtering based upon +the printer-type, printer-location, +printer-info, and printer-make-and-model + attributes.

+

The CUPS-add-printer operation now supports the +ppd-name attribute to specify a locally-available PPD file +rather than sending the PPD file from the client with the request.

+

Further information on the CUPS implementation of IPP can be found +in CUPS-IPP-1.1.

+

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 Page 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
+
PPD
+
PostScript Printer Description
+
SMB
+
Server Message Block
+
TFTP
+
Trivial File Transfer Protocol
+
+ + diff --git a/doc/svd.pdf b/doc/svd.pdf new file mode 100644 index 0000000000..27b574fd90 --- /dev/null +++ b/doc/svd.pdf @@ -0,0 +1,544 @@ +%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[12 0 R +14 0 R +15 0 R +16 0 R +17 0 R +18 0 R +19 0 R +]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[22 0 R +24 0 R +26 0 R +28 0 R +30 0 R +32 0 R +34 0 R +36 0 R +38 0 R +40 0 R +42 0 R +]endobj +44 0 obj<>endobj +45 0 obj<>endobj +46 0 obj<>endobj +47 0 obj<>endobj +48 0 obj<>endobj +49 0 obj<>endobj +50 0 obj<>endobj +51 0 obj<>endobj +52 0 obj<>endobj +53 0 obj<>endobj +54 0 obj<>endobj +55 0 obj<>endobj +56 0 obj<>endobj +57 0 obj<>endobj +58 0 obj<>endobj +59 0 obj<>endobj +60 0 obj<>endobj +61 0 obj<>endobj +62 0 obj<>endobj +63 0 obj<>endobj +64 0 obj<>endobj +65 0 obj<>endobj +66 0 obj<>endobj +67 0 obj<>endobj +68 0 obj<>endobj +69 0 obj<>endobj +70 0 obj<>endobj +71 0 obj<>endobj +72 0 obj[44 0 R +45 0 R +46 0 R +47 0 R +48 0 R +49 0 R +50 0 R +51 0 R +52 0 R +53 0 R +54 0 R +55 0 R +56 0 R +57 0 R +58 0 R +59 0 R +60 0 R +61 0 R +62 0 R +63 0 R +64 0 R +65 0 R +66 0 R +67 0 R +68 0 R +69 0 R +70 0 R +71 0 R +]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<>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ŒË‚0D÷|Å]jbko©<–*¸F¨ì ÅKÚªáï¥nt7™™s2؞Rà d1£1`"h²[ÁñRTPéÞ½£ VÆú™²­&·äµ¼/´DOc¸‚!åö,©êŒ E#(7á~Î;ÿԅÑݳuö{!þ>>>endobj +110 0 obj<>stream +xÚ+ä2T0BCc3JÎår +ár á +äHÉHendstream +endobj +111 0 obj +31 +endobj +112 0 obj<>>>/Annots 20 0 R>>endobj +113 0 obj<>stream +xÚµV]s£6}ϯ¸³OÉLMƒ?ú–mêÎn–g§~‘AØly%ˆÇýõ=’°!NâÍL·ãÆBGºçÜ{tÅ÷3\ü<û4QRž]ÍÏ~ý}J¾Kó 3£ñ„æé¹Gq"6übþÍÌzc;;Žoæf)¯ê<ËV碲Ѐ<¯…úcg¤¡óu®H‰¬Þ2Éé‰K4¥\%2ßÔæ¿Hš{ÑFЧ3$yÁ™â”W™¥ÙŸðê5§kQ–>ÜÍþ¦Hæ P­tp„ô†–]¼S5/iqþáú!Š?,.èk¼—¢|'°¢|j—~ϧœo5öãüÌu\¤M?<ý¸¿¥`ä9 +ßq©¤`¢#ÛQA±Mj—‹0êý5™N#£5[ï¬ *؎K£TË[øáh°DRB-$3e*‡f5­™¢%ç:›O¼&¥åŽL2ž–+:ÿÈÔîM9PèO b|'lZË+Ú;@Iï°´U®‡SÇØ(ޗ=’"m’Z=çæî¹Q-tbJQsäEÕ¬J™L»¼(Q4°¢°ÕâU*$2Y¥Ô(TØ¡g)>r…6O[Þ¯fÍ—0ڎX +/E^iÏÕ\f,áÊi7ðGÖfsRƇ3«x}0¡Y‹DÚx³(Ò¾c‹"âhòˆÃVl´Ñ7±´ü¿7¼ADšý 4ޏ›°Æ ãÚüð)ºÑbøï?s¥ØŠÓU!’G=¾Âô/fïËÍ&ÆkP]œ3çÑaýÉë›\ò¤Æ›–6ˆ R¬Pâ(¸j6Úªp×6¯×8œ(%YS%º(¬Èë]›z–¦Š”­V"È-¥Ø*­Y“‰„ªcsô©uí¦× $²:í18B˜y¥}Ó²-V ·èÁš*åö,½ZK­õNŠÆȤQµ(óiß§DF·wt»mË ¤’FJô«b×ÒÙKTè„îââH›N«(/u­²Gÿ~Á!¬6¹oôf=I•¨½|µù„KbVn°8•¹æiŒõGdÒû1Š¿ÜEݯ31Z¹©ŠˆÚ Ê°1{ŸèŽCºÙwê~ü¯]@!W¬2ySaŽL&ŠBlÍáçÆfê7,iƒ¡åø]=þhLo¶·áMjè¹À¢¿é;ÌÞèo ¤pøt€nèâbìÐWóW:q—/ÜÀCÏkÓKƒîÎ}Ù";݃1zë¡¶ïÐíOÇÀ¶ºíà„î=ÚÈ:…îJò\Â;ø…ûӉU€"Ò=Ï8NTÂÕÏW? ìmęÁ)õ-ڊ;îJšŽ`úýñ“PÓBúešæÆÞ?_ùص÷¹f§”·h+캀rý!ءߡ|ìÙOƒÚ¯×¬Zý5u‚ò‘3no(ïPê*ž@÷P€T‡~‡òpb[ã%”߶ܽ%}²—Ž…ƒÃÊÞWy€N3EÃÕoÛdüuö/û*›endstream +endobj +114 0 obj +1103 +endobj +115 0 obj<>>>>>endobj +116 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS045Ñ3V072PIÑPp VÎO+)O,JUK-*ÎÌÏSpI-N.Ê,(²5C²¸t!zt¡šŒ@b&&fzf +`¾¡Bpr~A*HÔ5„+ >Ï!Eendstream +endobj +117 0 obj +116 +endobj +118 0 obj<>>>/Annots 43 0 R>>endobj +119 0 obj<>stream +xÚµ˜KSãH Çï| +ÙªÄãGâ7 À°5Ylæ´ãt‚·b;k;ÅðíGêöCYB;¶¨ +ÕÉÏjEú·¤Î¿'˜øggƒãB’\D'ß®°Mˆ–ø‰ëù-NmxKQŠ<ÕÑ?±<…Œ‰aKȰàòq¬H¶™Èë¸N‹\á°¬·=Ã%rýuòHÒU'endstream +endobj +120 0 obj +1328 +endobj +121 0 obj<>>>>>endobj +122 0 obj<>stream +xÚ-‹;‚@„ûýSJ²Ç‰Ô¾j•Õޜ{ &‚Ü‘ø÷åÔÌóÈ7£œÅ¨êd÷¤ÐòЀâÁ+[TX›r_`{9¶h?½oAqÕ»¡ÇN£ Ýkšs&ÊLþ‡lÚ¬á¢Æ·œÕkÐÞiL×^èDó(#Iendstream +endobj +123 0 obj +120 +endobj +124 0 obj<>>>>>endobj +125 0 obj<>stream +xڕVËnÛ:Ýû+Y¹€­J²Ç˼ZhSÝkè¢FYl)’%);ùû;%§õC¸…[Ï̜9󐍈é“À"…Ùäõèv=zÿa i ë’N®×°.Æ3¸) +öÝú!æ$1M¯£Ôc$Q\æ¢)ÐBÍä+HÜA‰Ì5†ž”FÕà*$\½€AÌ¢‚Ó%$‹Îé,æm`ò÷ ‡Æî1óGW†Pá8éŽÇ¼ftÊ0K¶šŽ'gÀúDr aMŒ[ ”\´_žTl‹ðŒ(¡Ñà +,À)°ÖÊ8ȕÜŠ4UžeUéà–»šiø>¾¸ý’]|Lp#8³}úæPÜdDõñ~“§O=]îå!œ.Êò7m :Lǝ¨ÛÀ¼À- +¥=õŠ9àô˜*R±öu—…@éày€8ZÆà³Ø1ƒ¡š÷hð'ÜFÄ•’ύÙDàÅk› D¦e[” ؚ‘oºð +\–hسx…Z‘{êNwè™6+eÍ ×nh§±¹„®ãaéf íŸ=r²ôá(îŽÆçlÆGâréÃÑw||| +9¬Úà2ºŒßú÷SÖ7Í¡à³/ÎAr3ÈÞ&7M݄ۗ ç;‡ÀÛ)ÔVɁ”=Ÿƒ´L÷™ïé?d«¯ W€&¥±\nÚ>¬îÞg L¸H©ìuíËoÑÙÃʲ{ ¾Ñ¼[Á}¹Ép9Õ\N ‡ß•{…;%T×Iݓ¬R4=…¡““E3½Ç’K +’õ¬½³¯úÌÖ[„åsF,¡Õ)Ãñ>_ê|µóÂø@ēڿä*!MdÉá PySûÉë<…)1ThÖmcvØ\ZÇdŽöÂo|áÖyé{&€,¯B76’ÿj°wߋŸ^YN4¾ÐÙLŽæâiÁˆ¤;#͹½JRQÑú„[¿]ZÐg}´¨ajàSþ2'å_‡ºa÷ 롚¿éÜNµ]P˰KµQ[Úh€²òÜ +BÎü ¬}UºqZÿÌm§BÿE¶wüzfvÿ®òs•Ó„I÷û¬~¦qè§¡ś:•+1Ì9 œµâoYŸ°9æmè–ÆÀc[Ñlyîÿ_Pž¹Í+,z·t4¯ß¢Ï–'þÐ̯éÍF§tréïÖ£Fÿ¨]¿†endstream +endobj +126 0 obj +900 +endobj +127 0 obj<>>>>>endobj +128 0 obj<>stream +xڕ”Aoœ0…ïüŠ9n¦k ìæÚ¤‘r£ +íÝ Cב±©m ý÷cPÒî6UÄJhñ̼7OüH8ìé␗á×ôɧ:ùøp üuG'å‘CÝîò´€;Ó÷B·îCýL%pKXvHËPt÷µzžrºQc‹Nh…3 Vj/õwhÖ9iDZÅ6è–d¢MQƒ¼4úš`¨ªÏñh¿íþѲÛ4 ÂL2-k±“ۈ†ÖA(Y'¼M—]o&|Úeý W8#ùHÏæÞÐßàђm"@½Í”“ԝyÓeý “’Î;ðÔ&&!•8)„ªº‡N*b5–È&Ùà+§Ö̰<Û¨n౪à±ö¨ýòÿϏh[ÊÎ8 ÆzèHÉ_²;ôŒ|bÂ{+O£Ç‹ãOÚ‘ ­”R¤A8˜Q©p÷³ þ†.bà9íte`nÀFv²¹6…ʹHqé);0Ÿesޜ€±%LÐZ9-™²¯ ¤Qô2‰º_ÎcŸ®O³2º÷0Z*µvdûÈÛaqJþá*˜nñºNH®Ä"õRÊ耑±ë¦Ž«Eü&„&/ŽÑþ8õÉt~Ìß>̽G×X9l›c±‹²}h*󂇅ï¯}(>×ɗä7®™L4endstream +endobj +129 0 obj +484 +endobj +130 0 obj<>>>>>endobj +131 0 obj<>stream +xڕ˜Ûrâ8†ïó}™­ŠO`ØËI6³©š vÂ<€hƶ<’œ o¿­ƒ9L¥*è·ÔŸºÕêöï‡"ü‹!O ­¾,F¯3H"X¬pd’OaQǶ°Ù4uN}þúkIª~`ºæÁ’×W4W€ó- ìՁºx’ùƒ'•¯[i=PW¸Q{ +Í4µƒ7@ÇÓ0êÕAº4ÛÃ*h[±Z“ýqÝÇ© ‘Ìa‚^r­SààÞtj¬ÊëÕyº71¿£Í˜s5“·ƒyeuWcy/¹Bl“ã`b¯HìÔ}ÄÑÄ%ª·­\ÊÀ%æ~fÞ)U_8ŸH®pGÑ=9Ë«r;uw:Í]Îú† ¹‰&—"Û¸±´’þ¨Þ÷“¦ÓøŽdÕ©‡‘zuéÄ×CßÄúFŠ*Åú̧fplÓIrGšêԝº1›[çó—€MSôƬ»Â—%w¤¥N=Ï©ûø’™KKßÙï–)}ƒR:ÕEWªFˆrˆ3“ôŽŒÔ©Â:õ¥"j_v'³´+»x›Ïá­jJvt ]¬º÷U?VÖXЀ7ó“ÊÜÐæw±²°Íw5Ó0—˜­L<—B *Ê®šÞUÁ¾^VtʶÄkAµM#¤v¥´³$ò–鋟N×Þ+ƒ‚­H[ê³'.X|ð”ßVœjF«±9Àôµø„#큹Øç —êÚܵdí»¯“½?±À88X34Ò^3jÀ>%QŠ©þ­ÆŽìƒ¹–¬mðî/\Kæí‡’Wü…½âM ¹ˆkŒµ ±á-ô¶a·ÜÓi»m¨žcïxɑ½Ó=X‘_,@a€­(+û}:ÔE¯‹z·û06.ž&LÊAM*ÖkŽuNÃ(_mØn¶,·ù ¼4Í뉣ºpù ƜÆÌ!´}2.¿ìÞВãلO®7ö»O®§»ðÚJ;#·­»ƒóA`3?Ê^& ™œFqù¥éÕ[ŒYÿ^ ÀÀ´¹Žyº÷ØÌwG¯>²iÎ\‚Ï}JÿïáZÛz—endstream +endobj +132 0 obj +1206 +endobj +133 0 obj<>>>>>endobj +134 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS045Ñ3V072PIÑPp VÎO+)O,JUK-*ÎÌÏSpI-N.Ê,(²5C²¸t!zt¡š,@b&ÆÆz +`¾‰‚sFb^zj1HÜ5„+ …œ" endstream +endobj +135 0 obj +118 +endobj +136 0 obj<>>>>>endobj +137 0 obj<>stream +xڝ•QsÚ0 ÇßùzÜH`Ð>–4´éAë]Ò»½GM=›Ù¦Œ}ú*cíÝâÒ9ŽDâ'ýeIùՋáœ>1L0ƒ¨{Ó¢w6»„Á9OdO. (¿\Á2Îq»ûZülâÉÞ¡?EƒÖ%Š¡@[»½Çâøà1˜DãÆ#Ù[F ÅëÇÃßA˜z½ñhAq]mx…Ñ{Nÿ­ûš[®ªn`Žº”ºcÁ¢@ùÒܔÜs¨EðÏ\“ê¥ôÀé/ëp@¹ÆPöFcËwŠz£¥à^í@P +–è·ˆüÖÀښÊòڅÂ9´’ÿ—ºOhrF¬Ð‡TQº­*Mé»êP½o‰6ÆpöM1€+aÞúâ*O²,GMÕt^¹çºä¶„Ä”O$>Óô]·éÐoêž&¥ +¢“G–w‡JH ¡ï³À¬Ô¾©k¾së3͓3Ö MYþpÿäÛh]€<+ܙT…åÚ=aC3Þ£´[Ö¿™wónq«Ðû>ãbÕ$zcùúY +óÃD†Ñ,ù›Ž*¡½5êTþÝgøûڝYž‚ÏÒbÖ o;‹fR]IÔÔw+˜+‚\ÆNÀ;í„3Ìò‡ˆí8puì8¶âZþi öœ]w³ç¤üXÖkŽuµÈi7k±QÍr*%‡c\*H8À,”$3ÎçÂʵÿ›*ºöAXz¾˜†¶­}!ÒéHm;U´8¬"8µ…¥mM§šÞ‹·Øo£Ã–|÷ +]œG—´DÉpÙܧEï{#—endstream +endobj +138 0 obj +596 +endobj +139 0 obj<>>>>>endobj +140 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS045Ñ3V072PIÑPp VÎO+)O,JUK-*ÎÌÏSpI-N.Ê,(²5C²¸t!zt¡š @‚&ÆÆzF +`G÷œüââÄ¢J„kW Ì,"Öendstream +endobj +141 0 obj +120 +endobj +142 0 obj<>>>/Annots 72 0 R>>endobj +143 0 obj<>stream +xÚ՚Ënã6†÷~ +.[ Qě(.Ó¤Ì*éØ3{צ3*,K• òöååP$¶ˆnb5Ÿñ‹ù“üyË? ŒJý‘ ˆVhÓ.~_-n%"%ZíæU‚¡Õö—Õú¯½BÝÝw‡“:œŽ¿®þ^ü±Z”E© æ›—/ŸL€*ʋµ¨.¼ß£¥aÿôøð‚n9ÂØü5S¬Òê¿†ÑE|@¶ÈþHø. ”å¦ë•®áúÅì¿ðÅzëJi)*]qN +Tüö‘Œº+BuÆèXL(AZ]-c$äõy«[½Ù5›õ©éʅ.1#]sڕ²`£v6€ŠÅpY0§É)œZhaŽK{ÒòýxRíDGåµüÑwe›÷´§75¼5ê‡Á1\ÈYŸQœËJ« Š» (ΥбUœf÷\šþœ€ ¨‡nóÚênz™#41­nô1‘èß]Yv>>>>>endobj +146 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS045Ñ3V072PIÑPp VÎO+)O,JUK-*ÎÌÏSpI-N.Ê,(²5C²¸t!zt¡š23A‚®!\\½Wendstream +endobj +147 0 obj +100 +endobj +148 0 obj<>endobj +149 0 obj<>endobj +150 0 obj<>endobj +151 0 obj<>endobj +152 0 obj<>endobj +153 0 obj<>endobj +154 0 obj<>endobj +155 0 obj<>endobj +156 0 obj<>endobj +157 0 obj<>endobj +158 0 obj<>endobj +159 0 obj<>endobj +160 0 obj<>endobj +161 0 obj<>endobj +162 0 obj<>endobj +163 0 obj<>endobj +164 0 obj<>endobj +165 0 obj<>endobj +166 0 obj<>endobj +167 0 obj<>endobj +168 0 obj<>endobj +169 0 obj<>endobj +170 0 obj<>endobj +171 0 obj<>endobj +172 0 obj<>endobj +173 0 obj<>endobj +174 0 obj<>endobj +175 0 obj<>endobj +176 0 obj<>endobj +177 0 obj<>endobj +178 0 obj<>1<>2<>4<>]>>>>endobj +xref +0 179 +0000000000 65535 f +0000000015 00000 n +0000000227 00000 n +0000001793 00000 n +0000001867 00000 n +0000001946 00000 n +0000002024 00000 n +0000002101 00000 n +0000002180 00000 n +0000002256 00000 n +0000002337 00000 n +0000002396 00000 n +0000002448 00000 n +0000002533 00000 n +0000002585 00000 n +0000002669 00000 n +0000002774 00000 n +0000002879 00000 n +0000002984 00000 n +0000003089 00000 n +0000003194 00000 n +0000003260 00000 n +0000003361 00000 n +0000003446 00000 n +0000003547 00000 n +0000003632 00000 n +0000003733 00000 n +0000003818 00000 n +0000003905 00000 n +0000003990 00000 n +0000004077 00000 n +0000004162 00000 n +0000004228 00000 n +0000004313 00000 n +0000004379 00000 n +0000004464 00000 n +0000004530 00000 n +0000004615 00000 n +0000004681 00000 n +0000004766 00000 n +0000004832 00000 n +0000004917 00000 n +0000004983 00000 n +0000005068 00000 n +0000005162 00000 n +0000005266 00000 n +0000005371 00000 n +0000005476 00000 n +0000005581 00000 n +0000005685 00000 n +0000005790 00000 n +0000005895 00000 n +0000005999 00000 n +0000006104 00000 n +0000006209 00000 n +0000006314 00000 n +0000006419 00000 n +0000006524 00000 n +0000006629 00000 n +0000006734 00000 n +0000006839 00000 n +0000006944 00000 n +0000007049 00000 n +0000007154 00000 n +0000007259 00000 n +0000007364 00000 n +0000007469 00000 n +0000007573 00000 n +0000007678 00000 n +0000007783 00000 n +0000007887 00000 n +0000007992 00000 n +0000008097 00000 n +0000008310 00000 n +0000008342 00000 n +0000008374 00000 n +0000008762 00000 n +0000008810 00000 n +0000008858 00000 n +0000008906 00000 n +0000008954 00000 n +0000009002 00000 n +0000009050 00000 n +0000009098 00000 n +0000009146 00000 n +0000009194 00000 n +0000009242 00000 n +0000009290 00000 n +0000009338 00000 n +0000009386 00000 n +0000009434 00000 n +0000009482 00000 n +0000009530 00000 n +0000009578 00000 n +0000009626 00000 n +0000009674 00000 n +0000009722 00000 n +0000009770 00000 n +0000009818 00000 n +0000009866 00000 n +0000009914 00000 n +0000009963 00000 n +0000010012 00000 n +0000010061 00000 n +0000010110 00000 n +0000010159 00000 n +0000010340 00000 n +0000010492 00000 n +0000016844 00000 n +0000016866 00000 n +0000016961 00000 n +0000017063 00000 n +0000017083 00000 n +0000017238 00000 n +0000018412 00000 n +0000018434 00000 n +0000018547 00000 n +0000018734 00000 n +0000018755 00000 n +0000018910 00000 n +0000020309 00000 n +0000020331 00000 n +0000020444 00000 n +0000020635 00000 n +0000020656 00000 n +0000020805 00000 n +0000021776 00000 n +0000021797 00000 n +0000021937 00000 n +0000022492 00000 n +0000022513 00000 n +0000022662 00000 n +0000023939 00000 n +0000023961 00000 n +0000024074 00000 n +0000024263 00000 n +0000024284 00000 n +0000024424 00000 n +0000025091 00000 n +0000025112 00000 n +0000025225 00000 n +0000025416 00000 n +0000025437 00000 n +0000025591 00000 n +0000027185 00000 n +0000027207 00000 n +0000027320 00000 n +0000027491 00000 n +0000027512 00000 n +0000027567 00000 n +0000027672 00000 n +0000027816 00000 n +0000027922 00000 n +0000028042 00000 n +0000028151 00000 n +0000028300 00000 n +0000028410 00000 n +0000028517 00000 n +0000028665 00000 n +0000028800 00000 n +0000028918 00000 n +0000029032 00000 n +0000029149 00000 n +0000029256 00000 n +0000029394 00000 n +0000029542 00000 n +0000029644 00000 n +0000029748 00000 n +0000029897 00000 n +0000030000 00000 n +0000030113 00000 n +0000030213 00000 n +0000030323 00000 n +0000030469 00000 n +0000030580 00000 n +0000030690 00000 n +0000030824 00000 n +0000030921 00000 n +0000031021 00000 n +trailer +<<7c81fc334a74b7e117b3327dd928e447>]>> +startxref +31248 +%%EOF diff --git a/doc/svd.shtml b/doc/svd.shtml new file mode 100644 index 0000000000..e47acf5bca --- /dev/null +++ b/doc/svd.shtml @@ -0,0 +1,212 @@ + + + + + + CUPS Software Version Description + + + +

Scope

+ +

Identification

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

Document Overview

+ +

This software version description document is organized into the following +sections:

+ + + + + +

Additions

+ +

CUPS 1.1 includes many new features from the 1.0.x releases. + +

Filters

+ +

imagetoraster, imagetops

+ +

The image file filters have been upgraded to support conversion of +Microsoft Bitmap ("BMP") and Alias PIX files. + +

pdftops

+ +

A new pdftops filter has been developed that is based on the +excellent Xpdf 0.90 software from Derek B. Noonburg. The new filter is +faster, smaller, and considerably more reliable than the +Ghostscript-based filter in CUPS 1.0. + +

pstoraster

+ +

The pstoraster filter has been integrated with GNU +GhostScript 5.50. The new RIP supports most Level 3 PostScript language +features. + +

rastertoepson

+ +

The new rastertoepson filter supports EPSON printers +using the ESC/P or ESC/P2 command sets. PPDs are supplied for 9-pin, +24-pin, Stylus Color, and Stylus Photo printers. + +

User-Defined Printers and Options

+ +

The new lpoptions command allows users to configure default +document options and create additional "instances" of existing printers, +each with unique options. + +

The lp, lpr, and lpstat commands +have been upgraded to use this option and printer instance information +automatically. + +

Daemons

+ +

CUPS 1.1 includes two new daemons that provide enhanced network printing +support. + +

cups-lpd

+ +

The cups-lpd daemon provides support for clients using the +Line Printer Daemon protocol. + +

cups-polld

+ +

The cups-polld daemon provides remote polling services for +the scheduler. + +

Commands

+ +

CUPS 1.1 includes several new printing commands. + +

lpoptions

+ +

The lpoptions command provides user-defined printers and +options. + +

lpmove

+ +

The lpmove command moves a print job to a new destination. + +

lpinfo

+ +

The lpinfo command lists the available PPD files or devices. + +

IPP Implementation

+ +

CUPS 1.1 adds support for the set-job-attributes +extension operation as well as two new CUPS-specific extension +operations to determine which devices and printer drivers are available +on the system. + +

Further information on the CUPS implementation of IPP can be found +in CUPS-IPP-1.1. + + +

Changes

+ +

CUPS 1.1 includes many changes from the 1.0.x releases. + +

Directory Structure

+ +

The directory structure in CUPS 1.1 has been modified to conform to the +Filesystem Hierarchy Standard, 2.0. The following table describes the +new file locations. + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Table 1: Directory structure changes from CUPS 1.0.x to 1.1.x.
DescriptionCUPS 1.0.xCUPS 1.1.x
Backends/var/cups/backend/usr/lib/cups/backend
CGI programs/var/cups/cgi-bin/usr/lib/cups/cgi-bin
Configuration files/var/cups/conf/etc/cups
Documentation/usr/share/cups/doc/usr/share/doc/cups
Filter programs/var/cups/filter/usr/lib/cups/filter
Interface scripts/var/cups/interfaces/etc/cups/interfaces
Locale data/usr/lib/locale/usr/share/locale
Log files/var/cups/logs/var/log/cups
PPD files/var/cups/ppd/etc/cups/ppd
Request files/var/cups/requests/var/spool/cups
+ +

IPP Implementation

+ +

CUPS 1.1 is based on version 1.1 of the Internet Printing Protocol. + +

The new scheduler supports the create-job and +send-document operations. In addition, the +job-sheets, job-sheets-default, and +job-sheets-supported attributes are now supported for +banner pages. + +

The CUPS-get-printers and CUPS-get-classes +operations have been upgraded to support limited filtering based upon +the printer-type, printer-location, +printer-info, and printer-make-and-model +attributes. + +

The CUPS-add-printer operation now supports the +ppd-name attribute to specify a locally-available PPD file +rather than sending the PPD file from the client with the request. + +

Further information on the CUPS implementation of IPP can be found +in CUPS-IPP-1.1. + + + + + diff --git a/doc/system-overview.shtml b/doc/system-overview.shtml new file mode 100644 index 0000000000..54b7df5e97 --- /dev/null +++ b/doc/system-overview.shtml @@ -0,0 +1,19 @@ +

System Overview

+ +

CUPS provides a portable printing layer for UNIX®-based +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 ("IPP") as the basis for +managing print jobs and queues. The Line Printer Daemon ("LPD") Server +Message Block ("SMB"), and AppSocket (a.k.a. JetDirect) protocols are +also supported with reduced functionality. CUPS adds network printer +browsing and PostScript Printer Description ("PPD") based +printing options to support real-world printing under UNIX. + +

CUPS also includes a customized version of GNU Ghostscript +(currently based off GNU Ghostscript 5.50) and an image file RIP that +are used to support non-PostScript printers. Sample drivers for HP and +EPSON printers are included that use these filters. diff --git a/filter/Makefile b/filter/Makefile new file mode 100644 index 0000000000..2ff93e94ca --- /dev/null +++ b/filter/Makefile @@ -0,0 +1,207 @@ +# +# "$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-bmp.o image-colorspace.o image-gif.o image-jpeg.o \ + image-photocd.o image-pix.o image-png.o image-pnm.o \ + image-sgi.o image-sgilib.o image-sun.o image-tiff.o \ + image-zoom.o image.o raster.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) $(OBJS) $(TARGETS) $(LIBCUPSIMAGE) `basename $(LIBCUPSIMAGE) .2` + + +# +# Install all targets... +# + +install: + -$(MKDIR) $(LIBDIR) + $(CHMOD) ugo+rx $(LIBDIR) + $(INSTALL_LIB) $(LIBCUPSIMAGE) $(LIBDIR) + -if test $(LIBCUPSIMAGE) != "libcupsimage.a" -a $(LIBCUPSIMAGE) != "libcupsimage.la"; then \ + $(RM) $(LIBDIR)/`basename $(LIBCUPSIMAGE) .2`; \ + $(LN) $(LIBCUPSIMAGE) $(LIBDIR)/`basename $(LIBCUPSIMAGE) .2`; \ + fi + -$(MKDIR) $(SERVERBIN)/filter + $(CHMOD) ugo+rx $(SERVERBIN) + $(CHMOD) ugo+rx $(SERVERBIN)/filter + $(INSTALL_BIN) $(TARGETS) $(SERVERBIN)/filter + -$(MKDIR) $(INCLUDEDIR)/cups + $(CHMOD) ugo+rx $(INCLUDEDIR) + $(CHMOD) ugo+rx $(INCLUDEDIR)/cups + $(INSTALL_DATA) raster.h $(INCLUDEDIR)/cups + + +# +# 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) ../Makedefs + echo Linking $@... + $(DSO) $@ $(IMAGEOBJS) $(DSOLIBS) -lm + $(RM) `basename $@ .2` + $(LN) $@ `basename $@ .2` + + +# +# libcupsimage.la +# + +libcupsimage.la: $(IMAGEOBJS) ../Makedefs + echo Linking $@... + $(CC) -o $@ $(IMAGEOBJS:.o=.lo) -rpath $(LIBDIR) \ + -version-info 2:0 + + +# +# libcupsimage.a +# + +libcupsimage.a: $(IMAGEOBJS) ../Makedefs + echo Archiving $@... + $(RM) $@ + $(AR) $(ARFLAGS) $@ $(IMAGEOBJS) + $(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 $(LINKCUPSIMAGE) \ + $(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 $(LINKCUPSIMAGE) \ + $(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) $(LIBCUPSIMAGE) + echo Linking $@... + $(CC) $(LDFLAGS) -o $@ rastertoepson.o $(LINKCUPSIMAGE) $(IMGLIBS) $(LIBS) +rastertoepson.o: raster.h + + +# +# rastertohp +# + +rastertohp: rastertohp.o ../Makedefs ../cups/$(LIBCUPS) $(LIBCUPSIMAGE) + echo Linking $@... + $(CC) $(LDFLAGS) -o $@ rastertohp.o $(LINKCUPSIMAGE) $(IMGLIBS) $(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..f42f754e2c --- /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 : + PageLeft = (float)atof(val); + break; + case 2 : + PageTop = PageLength - (float)atof(val); + break; + case 3 : + PageRight = PageWidth - (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 : + PageRight = PageWidth - (float)atof(val); + break; + case 2 : + PageBottom = (float)atof(val); + break; + case 3 : + PageLeft = (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-main.c b/filter/form-main.c new file mode 100644 index 0000000000..941cafa0c3 --- /dev/null +++ b/filter/form-main.c @@ -0,0 +1,60 @@ +/* + * "$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: + * + * main() - Load the specified form file and output PostScript. + */ + +/* + * Include necessary headers... + */ + +#include "form.h" + + +/* + * Globals... + */ + +int NumOptions; /* Number of command-line options */ +cups_option_t *Options; /* Command-line options */ +ppd_file_t *PPD; /* PPD file */ + + +/* + * 'main()' - Load the specified form file and output PostScript. + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line arguments */ + char *argv[]) /* I - Command-line arguments */ +{ + + return (0); +} + + +/* + * End of "$Id$". + */ diff --git a/filter/form-ps.c b/filter/form-ps.c new file mode 100644 index 0000000000..4d1349f3b9 --- /dev/null +++ b/filter/form-ps.c @@ -0,0 +1,47 @@ +/* + * "$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" + + +/* + * 'formWrite()' - Write PostScript output for the given form document. + */ + +void +formWrite(tree_t *t) /* I - Document tree to write */ +{ +} + + +/* + * End of "$Id$". + */ diff --git a/filter/form-tree.c b/filter/form-tree.c new file mode 100644 index 0000000000..9e44558d20 --- /dev/null +++ b/filter/form-tree.c @@ -0,0 +1,622 @@ +/* + * "$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" + + +/* + * Local functions... + */ + +static int compare_attr(attr_t *a0, attr_t *a1); +static int compare_elements(char **e0, char **e1); +static int parse_attr(tree_t *t, FILE *fp); +static int parse_element(tree_t *t, FILE *fp); + + +/* + * Local globals... + */ + +static char *elements[] = + { + "", + "!--", + "ARC", + "BOX", + "BR", + "B", + "CUPSFORM", + "DEFVAR", + "FONT", + "H1", + "H2", + "H3", + "H4", + "H5", + "H6", + "HEAD", + "IMG", + "I", + "LINE", + "PAGE", + "PIE", + "POLY", + "PRE", + "P", + "RECT", + "TEXT", + "TT", + "VAR" + }; + + +/* + * 'formDelete()' - Delete a node and its children. + */ + +void +formDelete(tree_t *t) /* I - Tree node */ +{ +} + + +/* + * 'formGetAttr()' - Get a node attribute value. + */ + +char * /* O - Value or NULL */ +formGetAttr(tree_t *t, /* I - Tree node */ + const char *name) /* I - Name of attribute */ +{ +} + + +/* + * 'formNew()' - Create a new form node. + */ + +tree_t * /* O - New tree node */ +formNew(tree_t *p) /* I - Parent node */ +{ + tree_t *t; /* New tree node */ + + + /* + * Allocate the new node... + */ + + if ((t = (tree_t *)calloc(sizeof(tree_t), 1)) == NULL) + return (NULL); + + /* + * Set/copy attributes... + */ + + if (p == NULL) + { + t->bg[0] = 1.0; + t->bg[1] = 1.0; + t->bg[2] = 1.0; + t->halign = HALIGN_LEFT; + t->valign = VALIGN_MIDDLE; + t->typeface = "Courier"; + t->size = 12.0; + } + else + { + memcpy(t, p, sizeof(tree_t)); + + t->prev = NULL; + t->next = NULL; + t->child = NULL; + t->last_child = NULL; + t->parent = NULL; + t->num_attrs = 0; + t->attrs = NULL; + t->data = NULL; + } + + /* + * Return the new node... + */ + + return (t); +} + + +/* + * 'formRead()' - Read a form tree from a file. + */ + +tree_t * /* O - New form tree */ +formRead(FILE *fp, /* I - File to read from */ + tree_t *p) /* I - Parent node */ +{ + int ch, /* Character from file */ + closech, /* Closing character */ + have_whitespace; /* Leading whitespace? */ + static char s[10240]; /* String from file */ + uchar *ptr, /* Pointer in string */ + glyph[16], /* Glyph name (&#nnn;) */ + *glyphptr; /* Pointer in glyph string */ + tree_t *tree, /* "top" of this tree */ + *t, /* New tree node */ + *prev, /* Previous tree node */ + *temp; /* Temporary looping var */ + uchar *face, /* Typeface for FONT tag */ + *color, /* Color for FONT tag */ + *size; /* Size for FONT tag */ + + + /* + * Start off with no previous tree node... + */ + + prev = NULL; + tree = NULL; + + /* + * Parse data until we hit end-of-file... + */ + + while ((ch = getc(fp)) != EOF) + { + /* + * Ignore leading whitespace... + */ + + have_whitespace = 0; + closech = '/'; + + if (p == NULL || !p->preformatted) + { + while (isspace(ch)) + { + have_whitespace = 1; + ch = getc(fp); + } + + if (ch == EOF) + break; + } + + /* + * Allocate a new tree node - use calloc() to get zeroed data... + */ + + t = formNew(p); + + /* + * See what the character was... + */ + + if (ch == '<') + { + /* + * Markup char; grab the next char to see if this is a /... + */ + + ch = getc(fp); + if (ch == ' ') + { + /* + * Illegal lone "<"! Ignore it... + */ + + free(t); + continue; + } + + if (ch != '/') + ungetc(ch, fp); + + if (parse_element(t, fp) < 0) + { + free(t); + break; + } + + if ((closech = getc(fp)) == '/') + getc(fp); + + /* + * If this is the matching close mark, or if we are starting the same + * element, or if we've completed a list, we're done! + */ + + if (ch == '/') + { + /* + * Close element; find matching element... + */ + + for (temp = p; temp != NULL; temp = temp->p) + if (temp->element == t->element) + break; + + free(t); + + if (temp != NULL) + break; + else + continue; + } + } + else if (t->preformatted) + { + /* + * Read a pre-formatted string into the current tree node... + */ + + ptr = s; + while (ch != '<' && ch != EOF && ptr < (s + sizeof(s) - 1)) + { + if (ch == '&') + { + for (glyphptr = glyph; + (ch = getc(fp)) != EOF && (glyphptr - glyph) < 15; + glyphptr ++) + if (!isalnum(ch)) + break; + else + *glyphptr = ch; + + *glyphptr = '\0'; + if (atoi(glyph) > 0) + ch = atoi(glyph); + else if (strcmp(glyph, "lt") == 0) + ch = '<'; + else if (strcmp(glyph, "gt") == 0) + ch = '>'; + else if (strcmp(glyph, "quot") == 0) + ch = '\''; + else if (strcmp(glyph, "nbsp") == 0) + ch = ' '; + else + ch = '&'; + } + + if (ch != 0) + *ptr++ = ch; + + if (ch == '\n') + break; + + ch = getc(fp); + } + + *ptr = '\0'; + + if (ch == '<') + ungetc(ch, fp); + + t->element = ELEMENT_FRAGMENT; + t->data = strdup(s); + } + else + { + /* + * Read the next string fragment... + */ + + ptr = s; + if (have_whitespace) + *ptr++ = ' '; + + while (!isspace(ch) && ch != '<' && ch != EOF && ptr < (s + sizeof(s) - 1)) + { + if (ch == '&') + { + for (glyphptr = glyph; + (ch = getc(fp)) != EOF && (glyphptr - glyph) < 15; + glyphptr ++) + if (!isalnum(ch)) + break; + else + *glyphptr = ch; + + *glyphptr = '\0'; + if (atoi(glyph) > 0) + ch = atoi(glyph); + else if (strcmp(glyph, "lt") == 0) + ch = '<'; + else if (strcmp(glyph, "gt") == 0) + ch = '>'; + else if (strcmp(glyph, "quot") == 0) + ch = '\''; + else if (strcmp(glyph, "nbsp") == 0) + ch = ' '; + else + ch = '&'; + } + + if (ch != 0) + *ptr++ = ch; + + ch = getc(fp); + } + + if (isspace(ch)) + *ptr++ = ' '; + + *ptr = '\0'; + + if (ch == '<') + ungetc(ch, fp); + + t->element = ELEMENT_FRAGMENT; + t->data = strdup(s); + } + + /* + * If the p tree pointer is not NULL and this is the first + * entry we've read, set the child pointer... + */ + + if (p != NULL && prev == NULL) + p->child = t; + + if (p != NULL) + p->last_child = t; + + /* + * Do the prev/next links... + */ + + t->parent = p; + t->prev = prev; + if (prev != NULL) + prev->next = t; + else + tree = t; + + prev = t; + + /* + * Do child stuff as needed... + */ + + if (closech == '>') + t->child = formRead(t, fp); + } + + return (tree); +} + + +/* + * 'formSetAttr()' - Set a node attribute. + */ + +void +formSetAttr(tree_t *t, /* I - Tree node */ + const char *name, /* I - Attribute name */ + const char *value) /* I - Attribute value */ +{ +} + + +/* + * 'compare_attr()' - Compare two attributes. + */ + +static int /* O - -1 if a0 < a1, etc. */ +compare_attr(attr_t *a0, /* I - First attribute */ + attr_t *a1) /* I - Second attribute */ +{ + return (strcasecmp(a0->name, a1->name)); +} + + +/* + * 'compare_elements()' - Compare two elements. + */ + +static int /* O - -1 if e0 < e1, etc. */ +compare_elements(char **e0, /* I - First element */ + char **e1) /* I - Second element */ +{ + return (strcasecmp(*e0, *e1)); +} + + +/* + * 'parse_attr()' - Parse an element attribute string. + */ + +static int /* O - -1 on error, 0 on success */ +parse_attr(tree_t *t, /* I - Current tree node */ + FILE *fp) /* I - Input file */ +{ + char name[1024], /* Name of attr */ + value[10240], /* Value of attr */ + *ptr; /* Temporary pointer */ + int ch; /* Character from file */ + + + ptr = name; + while ((ch = getc(fp)) != EOF) + if (isalnum(ch)) + { + if (ptr < (name + sizeof(name) - 1)) + *ptr++ = ch; + } + else + break; + + *ptr = '\0'; + + while (isspace(ch) || ch == '\r') + ch = getc(fp); + + switch (ch) + { + default : + ungetc(ch, fp); + return (formSetAttr(t, name, NULL)); + case EOF : + return (-1); + case '=' : + ptr = value; + ch = getc(fp); + + while (isspace(ch) || ch == '\r') + ch = getc(fp); + + if (ch == EOF) + return (-1); + + if (ch == '\'') + { + while ((ch = getc(fp)) != EOF) + if (ch == '\'') + break; + else if (ptr < (value + sizeof(value) - 1)) + *ptr++ = ch; + + *ptr = '\0'; + } + else if (ch == '\"') + { + while ((ch = getc(fp)) != EOF) + if (ch == '\"') + break; + else if (ptr < (value + sizeof(value) - 1)) + *ptr++ = ch; + + *ptr = '\0'; + } + else + { + *ptr++ = ch; + while ((ch = getc(fp)) != EOF) + if (isspace(ch) || ch == '>' || ch == '/' || ch == '\r') + break; + else if (ptr < (value + sizeof(value) - 1)) + *ptr++ = ch; + + *ptr = '\0'; + if (ch == '>' || ch == '/') + ungetc(ch, fp); + } + + return (formSetAttr(t, name, value)); + } +} + + +/* + * 'parse_element()' - Parse an element. + */ + +static int /* O - -1 on error or ELEMENT_nnnn */ +parse_element(tree_t *t, /* I - Current tree node */ + FILE *fp) /* I - Input file */ +{ + int ch; /* Character from file */ + char element[255], /* Element string... */ + *eptr, /* Current character... */ + comment[10240], /* Comment string */ + *cptr, /* Current char... */ + **temp; /* Element variable entry */ + + + eptr = element; + + while ((ch = getc(fp)) != EOF && eptr < (element + sizeof(element) - 1)) + if (ch == '>' || ch == '/' || isspace(ch)) + break; + else + *eptr++ = ch; + + *eptr = '\0'; + + if (ch == EOF) + return (ELEMENT_ERROR); + + eptr = element; + temp = bsearch(&mptr, elements, sizeof(elements) / sizeof(elements[0]), + sizeof(elements[0]), + (int (*)(const void *, const void *))compare_elements); + + if (temp == NULL) + { + /* + * Unrecognized element stuff... + */ + + t->element = ELEMENT_COMMENT; + strcpy(comment, element); + cptr = comment + strlen(comment); + } + else + { + t->element = (element_t)((char **)temp - elements); + cptr = comment; + } + + if (t->element == ELEMENT_COMMENT) + { + while (ch != EOF && ch != '>' && cptr < (comment + sizeof(comment) - 1)) + { + *cptr++ = ch; + ch = getc(fp); + } + + *cptr = '\0'; + t->data = strdup(comment); + } + else + { + while (ch != EOF && ch != '>' && ch != '/') + { + if (!isspace(ch)) + { + ungetc(ch, fp); + parse_variable(t, fp); + } + + ch = getc(fp); + } + + if (ch != EOF) + ungetc(ch, fp); + } + + return (t->element); +} + + +/* + * End of "$Id$". + */ diff --git a/filter/form.h b/filter/form.h new file mode 100644 index 0000000000..2644b2889f --- /dev/null +++ b/filter/form.h @@ -0,0 +1,175 @@ +/* + * "$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" + + +/* + * Form elements... + */ + +typedef enum +{ + ELEMENT_FILE = -1, /* Pseudo element, not in file, but above */ + ELEMENT_FRAGMENT, /* Text fragment */ + ELEMENT_COMMENT, /* */ + ELEMENT_ARC, + ELEMENT_BOX, + ELEMENT_BR, + ELEMENT_B, + ELEMENT_CUPSFORM, + ELEMENT_DEFVAR, + ELEMENT_FONT, + ELEMENT_H1, + ELEMENT_H2, + ELEMENT_H3, + ELEMENT_H4, + ELEMENT_H5, + ELEMENT_H6, + ELEMENT_HEAD, + ELEMENT_IMG, + ELEMENT_I, + ELEMENT_LINE, + ELEMENT_PAGE, + ELEMENT_PIE, + ELEMENT_POLY, + ELEMENT_PRE, + ELEMENT_P, + ELEMENT_RECT, + ELEMENT_TEXT, + ELEMENT_TT, + ELEMENT_VAR +} element_t; + + +/* + * Font styles... + */ + +typedef enum +{ + STYLE_NORMAL, + STYLE_BOLD, + STYLE_ITALIC, + STYLE_BOLD_ITALIC +} style_t; + + +/* + * Text alignments... + */ + +typedef enum +{ + HALIGN_LEFT, + HALIGN_CENTER, + HALIGN_RIGHT +} halign_t; + +typedef enum +{ + VALIGN_BOTTOM, + VALIGN_CENTER, + VALIGN_TOP +} valign_t; + + +/* + * Text directions... + */ + +typedef enun +{ + DIR_LEFT_TO_RIGHT, + DIR_RIGHT_TO_LEFT +} dir_t; + + +/* + * Attribute structure... + */ + +typedef struct +{ + char *name, /* Name of attribute */ + *value; /* Value of attribute */ +} attr_t; + + +/* + * Form document tree structure... + */ + +typedef struct tree_str +{ + struct tree_str *prev, /* Previous tree node */ + *next, /* Next tree node */ + *parent, /* Parent tree node */ + *child, /* First child node */ + *last_child; /* Last child node */ + element_t element; /* Element type */ + float x, y, w, h; /* Position and size in points */ + float bg[3], fg[3]; /* Colors of element */ + float thickness; /* Thickness of lines */ + int preformatted; /* Preformatted text? */ + float size; /* Height of text in points */ + char *typeface; /* Typeface of text */ + style_t style; /* Style of text */ + halign_t halign; /* Horizontal alignment */ + valign_t valign; /* Vertical alignment */ + dir_t dir; /* Direction of text */ + int num_attrs; /* Number of attributes */ + attr_t *attrs; /* Attributes */ + void *data; /* Text fragment data */ +} tree_t; + + +/* + * Globals... + */ + +extern int NumOptions; /* Number of command-line options */ +extern cups_option_t *Options; /* Command-line options */ +extern ppd_file_t *PPD; /* PPD file */ + + +/* + * Prototypes... + */ + +extern void formDelete(tree_t *t); +extern char *formGetAttr(tree_t *t, const char *name); +extern tree_t *formNew(tree_t *p); +extern tree_t *formRead(FILE *fp, tree_t *p); +extern void formSetAttr(tree_t *t, const char *name, const char *value); +extern void formWrite(tree_t *p); + + +/* + * End of "$Id$". + */ diff --git a/filter/hpgl-attr.c b/filter/hpgl-attr.c new file mode 100644 index 0000000000..2a1d59ad5d --- /dev/null +++ b/filter/hpgl-attr.c @@ -0,0 +1,452 @@ +/* + * "$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 - ColorRange[0][0]) / + (ColorRange[0][1] - ColorRange[0][0]); + Pens[i].rgb[1] = (params[2].value.number - ColorRange[1][0]) / + (ColorRange[1][1] - ColorRange[1][0]); + Pens[i].rgb[2] = (params[3].value.number - ColorRange[2][0]) / + (ColorRange[2][1] - ColorRange[2][0]); + + fprintf(stderr, "DEBUG: Pen %d %.0f %.0f %.0f = %.3f %.3f %.3f\n", + i, params[1].value.number, params[2].value.number, + params[3].value.number, Pens[i].rgb[0], Pens[i].rgb[1], + Pens[i].rgb[2]); + } + + 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..bec8d66d52 --- /dev/null +++ b/filter/hpgl-char.c @@ -0,0 +1,500 @@ +/* + * "$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); + puts("SA"); + } + } + 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); + puts("SS"); + } + } +} + + +/* + * '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[1], 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..d21c703f7e --- /dev/null +++ b/filter/hpgl-config.c @@ -0,0 +1,641 @@ +/* + * "$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" + +#define max(a,b) ((a) < (b) ? (b) : (a)) + + +/* + * '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) + { + default : /* 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] * 1016.0f / 72.0f; + top = bottom + page_height * Scaling2[1] * 1016.0f / 72.0f; + 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) + scaling *= max(page_width, page_height) / max(PlotSize[1], 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] = 0.0; + IW1[1] = 0.0; + IW2[0] = 0.0; + IW2[1] = 0.0; + + 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] = 0.0; + IW1[1] = 0.0; + IW2[0] = 0.0; + IW2[1] = 0.0; + + 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; + } + + PlotSizeSet = 0; + 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]; + } + + PlotSizeSet = 1; + 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 when scaling. + * + * 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; + } + + PlotSizeSet = 1; + 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..117c21c9aa --- /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)atoi(val) * 0.001f; + + /* + * 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..6b3b5b3d11 --- /dev/null +++ b/filter/hpgl-prolog.c @@ -0,0 +1,407 @@ +/* + * "$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 */ + const char *datadir; /* CUPS_DATADIR environment variable */ + char filename[1024]; /* Name of 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 ((datadir = getenv("CUPS_DATADIR")) == NULL) + datadir = CUPS_DATADIR; + + snprintf(filename, sizeof(filename), "%s/data/HPGLprolog", datadir); + + if ((prolog = fopen(filename, "r")) == NULL) + { + fprintf(stderr, "ERROR: Unable to open HPGL prolog \"%s\" for reading - %s\n", + filename, strerror(errno)); + 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 ++; + + printf("%%%%Page: %d %d\n", PageCount, PageCount); + + landscape = 0; + + if (!FitPlot && PlotSizeSet) + { + /* + * 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]; + } + + fprintf(stderr, "DEBUG: hpgltops setting page size (%.0f x %.0f)\n", + width, length); + + if (PPD != NULL) + { + fputs("DEBUG: hpgltops has a PPD file!\n", stderr); + + /* + * Lookup the closest PageSize and set it... + */ + + for (i = PPD->num_sizes, size = PPD->sizes; i > 0; i --, size ++) + if ((fabs(length - size->length) < 36.0 && size->width >= width) || + (fabs(length - size->width) < 36.0 && size->length >= width)) + break; + + if (i == 0 && PPD->variable_sizes) + { + for (i = PPD->num_sizes, size = PPD->sizes; i > 0; i --, size ++) + if (strcasecmp(size->name, "custom") == 0) + break; + } + + if (i > 0) + { + /* + * Found a matching size... + */ + + option = ppdFindOption(PPD, "PageSize"); + choice = ppdFindChoice(option, size->name); + + puts("%%BeginPageSetup"); + printf("%%%%BeginFeature: PageSize %s\n", size->name); + + if (strcasecmp(size->name, "custom") == 0) + { + PageLeft = PPD->custom_margins[0]; + PageRight = width - PPD->custom_margins[2]; + PageWidth = width; + PageBottom = PPD->custom_margins[1]; + PageTop = length - PPD->custom_margins[3]; + PageLength = length; + + printf("%.0f %.0f 0 0 0\n", width, length); + + if (choice->code == NULL) + { + /* + * This can happen with certain buggy PPD files that don't include + * a CustomPageSize command sequence... We just use a generic + * Level 2 command sequence... + */ + + puts("pop pop pop"); + puts("<>setpagedevice\n"); + } + else + { + /* + * Use the vendor-supplied command... + */ + + printf("%s\n", choice->code); + } + } + else + { + if (choice->code) + printf("%s\n", choice->code); + + if (fabs(length - size->width) < 36.0) + { + /* + * Do landscape orientation... + */ + + PageLeft = size->bottom; + PageRight = size->top; + PageWidth = size->length; + PageBottom = size->left; + PageTop = size->right; + PageLength = size->width; + + landscape = 1; + } + else + { + /* + * Do portrait orientation... + */ + + PageLeft = size->left; + PageRight = size->right; + PageWidth = size->width; + PageBottom = size->bottom; + PageTop = size->top; + PageLength = size->length; + } + } + + puts("%%EndFeature"); + puts("%%EndPageSetup"); + } + } + else + { + fputs("DEBUG: hpgltops does not have a PPD file!\n", stderr); + + puts("%%BeginPageSetup"); + printf("%%%%BeginFeature: PageSize w%.0fh%.0f\n", width, length); + printf("<>setpagedevice\n", + width, length); + puts("%%EndFeature"); + puts("%%EndPageSetup"); + + PageLeft = 0.0; + PageRight = width; + PageWidth = width; + PageBottom = 0.0; + PageTop = length; + PageLength = length; + } + } + + 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..9fe745a798 --- /dev/null +++ b/filter/hpgl-vector.c @@ -0,0 +1,731 @@ +/* + * "$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; + +#ifdef DEBUG + fputs("DEBUG: 7-bit\n", stderr); +#endif /* DEBUG */ + 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[1], Pens[PenNumber].rgb[2], + Pens[PenNumber].width * PenScaling); + +#ifdef DEBUG + fprintf(stderr, "DEBUG: set pen #%d\n", PenNumber); +#endif /* DEBUG */ + break; + case '<' : /* Next coords are a move-to */ + draw = 0; + s ++; + +#ifdef DEBUG + fputs("DEBUG: moveto\n", stderr); +#endif /* DEBUG */ + break; + case '>' : /* Set fractional bits */ + s ++; + temp = (int)decode_number(&s, base_bits, 1.0); + frac_bits = 1.0 / (1 << temp); + +#ifdef DEBUG + fprintf(stderr, "DEBUG: set fractional bits %d\n", temp); +#endif /* DEBUG */ + break; + case '=' : /* Next coords are absolute */ + s ++; + abscoords = 1; + +#ifdef DEBUG + fputs("DEBUG: absolute\n", stderr); +#endif /* DEBUG */ + break; + default : + if (*s >= 63) + { + /* + * Coordinate... + */ + + x = decode_number(&s, base_bits, frac_bits); + y = decode_number(&s, base_bits, frac_bits); + +#ifdef DEBUG + fprintf(stderr, "DEBUG: coords %.3f %.3f\n", x, y); +#endif /* DEBUG */ + + 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..5d1924dbfb --- /dev/null +++ b/filter/hpgltops.h @@ -0,0 +1,233 @@ +/* + * "$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 PlotSizeSet VALUE(0); /* Plot size set? */ +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-bmp.c b/filter/image-bmp.c new file mode 100644 index 0000000000..3a0d606324 --- /dev/null +++ b/filter/image-bmp.c @@ -0,0 +1,499 @@ +/* + * "$Id$" + * + * BMP 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: + * + * ImageReadBMP() - Read a BMP image file. + * read_word() - Read a 16-bit unsigned integer. + * read_dword() - Read a 32-bit unsigned integer. + * read_long() - Read a 32-bit signed integer. + */ + +/* + * Include necessary headers... + */ + +#include "image.h" + + +/* + * Constants for the bitmap compression... + */ + +# define BI_RGB 0 /* No compression - straight BGR data */ +# define BI_RLE8 1 /* 8-bit run-length compression */ +# define BI_RLE4 2 /* 4-bit run-length compression */ +# define BI_BITFIELDS 3 /* RGB bitmap with RGB masks */ + + +/* + * Local functions... + */ + +static unsigned short read_word(FILE *fp); +static unsigned int read_dword(FILE *fp); +static int read_long(FILE *fp); + + +/* + * 'ImageReadBMP()' - Read a BMP image file. + */ + +int /* O - Read status */ +ImageReadBMP(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 offset, /* Offset to bitmap data */ + info_size, /* Size of info header */ + planes, /* Number of planes (always 1) */ + depth, /* Depth of image (bits) */ + compression, /* Type of compression */ + image_size, /* Size of image in bytes */ + colors_used, /* Number of colors used */ + colors_important, /* Number of important colors */ + bpp, /* Bytes per pixel */ + x, y, /* Looping vars */ + color, /* Color of RLE pixel */ + count, /* Number of times to repeat */ + temp, /* Temporary color */ + align; /* Alignment bytes */ + ib_t bit, /* Bit in image */ + byte; /* Byte in image */ + ib_t *in, /* Input pixels */ + *out, /* Output pixels */ + *ptr; /* Pointer into pixels */ + ib_t colormap[256][4]; /* Colormap */ + + + /* + * Get the header... + */ + + getc(fp); /* Skip "BM" sync chars */ + getc(fp); + read_dword(fp); /* Skip size */ + read_word(fp); /* Skip reserved stuff */ + read_word(fp); + offset = read_dword(fp); + + fprintf(stderr, "offset = %d\n", offset); + + /* + * Then the bitmap information... + */ + + info_size = read_dword(fp); + img->xsize = read_long(fp); + img->ysize = read_long(fp); + planes = read_word(fp); + depth = read_word(fp); + compression = read_dword(fp); + image_size = read_dword(fp); + img->xppi = read_long(fp) * 0.0254 + 0.5; + img->yppi = read_long(fp) * 0.0254 + 0.5; + colors_used = read_dword(fp); + colors_important = read_dword(fp); + + fprintf(stderr, "info_size = %d, xsize = %d, ysize = %d, planes = %d, depth = %d\n", + info_size, img->xsize, img->ysize, planes, depth); + fprintf(stderr, "compression = %d, image_size = %d, xppi = %d, yppi = %d\n", + compression, image_size, img->xppi, img->yppi); + fprintf(stderr, "colors_used = %d, colors_important = %d\n", colors_used, + colors_important); + + if (info_size > 40) + for (info_size -= 40; info_size > 0; info_size --) + getc(fp); + + /* + * Get colormap... + */ + + if (colors_used == 0 && depth <= 8) + colors_used = 1 << depth; + + fread(colormap, colors_used, 4, fp); + + /* + * Setup image and buffers... + */ + + img->colorspace = primary; + + ImageSetMaxTiles(img, 0); + + in = malloc(img->xsize * 3); + bpp = ImageGetDepth(img); + out = malloc(img->xsize * bpp); + + /* + * Read the image data... + */ + + color = 0; + count = 0; + align = 0; + + for (y = img->ysize - 1; y >= 0; y --) + { + if (img->colorspace == IMAGE_RGB) + ptr = out; + else + ptr = in; + + switch (depth) + { + case 1 : /* Bitmap */ + for (x = img->xsize, bit = 128, byte = 0; x > 0; x --) + { + if (bit == 128) + byte = getc(fp); + + if (byte & bit) + { + *ptr++ = colormap[1][2]; + *ptr++ = colormap[1][1]; + *ptr++ = colormap[1][0]; + } + else + { + *ptr++ = colormap[0][2]; + *ptr++ = colormap[0][1]; + *ptr++ = colormap[0][0]; + } + + if (bit > 1) + bit >>= 1; + else + bit = 128; + } + + /* + * Read remaining bytes to align to 32 bits... + */ + + for (temp = (img->xsize + 7) / 8; temp & 3; temp ++) + getc(fp); + break; + + case 4 : /* 16-color */ + for (x = img->xsize, bit = 0xf0, temp = 0; x > 0; x --) + { + /* + * Get a new count as needed... + */ + + if (compression != BI_RLE4 && count == 0) + { + count = 2; + color = -1; + } + + if (count == 0) + { + while (align > 0) + { + align --; + getc(fp); + } + + if ((count = getc(fp)) == 0) + { + if ((count = getc(fp)) == 0) + { + /* + * End of line... + */ + + x ++; + continue; + } + else if (count == 1) + { + /* + * End of image... + */ + + break; + } + else if (count == 2) + { + /* + * Delta... + */ + + count = getc(fp) * getc(fp) * img->xsize; + color = 0; + } + else + { + /* + * Absolute... + */ + + color = -1; + align = ((4 - (count & 3)) / 2) & 1; + } + } + else + color = getc(fp); + } + + /* + * Get a new color as needed... + */ + + count --; + + if (bit == 0xf0) + { + if (color < 0) + temp = getc(fp); + else + temp = color; + + /* + * Copy the color value... + */ + + *ptr++ = colormap[temp >> 4][2]; + *ptr++ = colormap[temp >> 4][1]; + *ptr++ = colormap[temp >> 4][0]; + bit = 0x0f; + } + else + { + /* + * Copy the color value... + */ + + *ptr++ = colormap[temp & 15][2]; + *ptr++ = colormap[temp & 15][1]; + *ptr++ = colormap[temp & 15][0]; + bit = 0xf0; + } + } + break; + + case 8 : /* 256-color */ + for (x = img->xsize; x > 0; x --) + { + /* + * Get a new count as needed... + */ + + if (compression != BI_RLE8) + { + count = 1; + color = -1; + } + + if (count == 0) + { + while (align > 0) + { + align --; + getc(fp); + } + + if ((count = getc(fp)) == 0) + { + if ((count = getc(fp)) == 0) + { + /* + * End of line... + */ + + x ++; + continue; + } + else if (count == 1) + { + /* + * End of image... + */ + + break; + } + else if (count == 2) + { + /* + * Delta... + */ + + count = getc(fp) * getc(fp) * img->xsize; + color = 0; + } + else + { + /* + * Absolute... + */ + + color = -1; + align = (2 - (count & 1)) & 1; + } + } + else + color = getc(fp); + } + + /* + * Get a new color as needed... + */ + + if (color < 0) + temp = getc(fp); + else + temp = color; + + count --; + + /* + * Copy the color value... + */ + + *ptr++ = colormap[temp][2]; + *ptr++ = colormap[temp][1]; + *ptr++ = colormap[temp][0]; + } + break; + + case 24 : /* 24-bit RGB */ + for (x = img->xsize; x > 0; x --, ptr += 3) + { + ptr[2] = getc(fp); + ptr[1] = getc(fp); + ptr[0] = getc(fp); + } + + /* + * Read remaining bytes to align to 32 bits... + */ + + for (temp = img->xsize * 3; temp & 3; temp ++) + getc(fp); + break; + } + + if (img->colorspace == IMAGE_RGB) + { + if (saturation != 100 || hue != 0) + ImageRGBAdjust(out, img->xsize, saturation, hue); + } + else + { + if (saturation != 100 || hue != 0) + 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); + } + + fclose(fp); + free(in); + free(out); + + return (0); +} + + +/* + * 'read_word()' - Read a 16-bit unsigned integer. + */ + +static unsigned short /* O - 16-bit unsigned integer */ +read_word(FILE *fp) /* I - File to read from */ +{ + unsigned char b0, b1; /* Bytes from file */ + + b0 = getc(fp); + b1 = getc(fp); + + return ((b1 << 8) | b0); +} + + +/* + * 'read_dword()' - Read a 32-bit unsigned integer. + */ + +static unsigned int /* O - 32-bit unsigned integer */ +read_dword(FILE *fp) /* I - File to read from */ +{ + unsigned char b0, b1, b2, b3; /* Bytes from file */ + + b0 = getc(fp); + b1 = getc(fp); + b2 = getc(fp); + b3 = getc(fp); + + return ((((((b3 << 8) | b2) << 8) | b1) << 8) | b0); +} + + +/* + * 'read_long()' - Read a 32-bit signed integer. + */ + +static int /* O - 32-bit signed integer */ +read_long(FILE *fp) /* I - File to read from */ +{ + unsigned char b0, b1, b2, b3; /* Bytes from file */ + + b0 = getc(fp); + b1 = getc(fp); + b2 = getc(fp); + b3 = getc(fp); + + return ((int)(((((b3 << 8) | b2) << 8) | b1) << 8) | b0); +} + + +/* + * End of "$Id$". + */ diff --git a/filter/image-colorspace.c b/filter/image-colorspace.c new file mode 100644 index 0000000000..90dfcc5e6f --- /dev/null +++ b/filter/image-colorspace.c @@ -0,0 +1,875 @@ +/* + * "$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 */ + 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]); + 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)); + + 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..2f92dc263f --- /dev/null +++ b/filter/image-jpeg.c @@ -0,0 +1,194 @@ +/* + * "$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); + } + } + + fprintf(stderr, "DEBUG: JPEG image %dx%dx%d, %dx%d PPI\n", + img->xsize, img->colorspace, cinfo.output_components, + img->xppi, img->yppi); + + 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..9df3044dee --- /dev/null +++ b/filter/image-photocd.c @@ -0,0 +1,323 @@ +/* + * "$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); + else + rgb = NULL; + + 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. + */ + + cb = cr = 0.0f; + + 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-pix.c b/filter/image-pix.c new file mode 100644 index 0000000000..6c82721460 --- /dev/null +++ b/filter/image-pix.c @@ -0,0 +1,223 @@ +/* + * "$Id$" + * + * Alias PIX 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: + * + * ImageReadPIX() - Read a PIX image file. + * read_short() - Read a 16-bit integer. + */ + +/* + * Include necessary headers... + */ + +#include "image.h" + + +/* + * Local functions... + */ + +static short read_short(FILE *fp); + + +/* + * 'ImageReadPIX()' - Read a PIX image file. + */ + +int /* O - Read status */ +ImageReadPIX(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 */ +{ + short width, /* Width of image */ + height, /* Height of image */ + depth; /* Depth of image (bits) */ + int count, /* Repetition count */ + bpp, /* Bytes per pixel */ + x, y; /* Looping vars */ + ib_t r, g, b; /* Red, green/gray, blue values */ + ib_t *in, /* Input pixels */ + *out, /* Output pixels */ + *ptr; /* Pointer into pixels */ + + + /* + * Get the image dimensions and setup the image... + */ + + width = read_short(fp); + height = read_short(fp); + read_short(fp); + read_short(fp); + depth = read_short(fp); + + if (depth == 8) + img->colorspace = secondary; + else + img->colorspace = primary; + + img->xsize = width; + img->ysize = height; + + ImageSetMaxTiles(img, 0); + + in = malloc(img->xsize * (depth / 8)); + bpp = ImageGetDepth(img); + out = malloc(img->xsize * bpp); + + /* + * Read the image data... + */ + + if (depth == 8) + { + for (count = 0, y = 0, g = 0; y < img->ysize; y ++) + { + if (img->colorspace == IMAGE_WHITE) + ptr = out; + else + ptr = in; + + for (x = img->xsize; x > 0; x --, count --) + { + if (count == 0) + { + count = getc(fp); + g = getc(fp); + } + + *ptr++ = g; + } + + if (img->colorspace != IMAGE_WHITE) + 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 + { + for (count = 0, y = 0, r = 0, g = 0, b = 0; y < img->ysize; y ++) + { + if (img->colorspace == IMAGE_RGB) + ptr = out; + else + ptr = in; + + for (x = img->xsize; x > 0; x --, count --) + { + if (count == 0) + { + count = getc(fp); + b = getc(fp); + g = getc(fp); + r = getc(fp); + } + + *ptr++ = r; + *ptr++ = g; + *ptr++ = b; + } + + if (img->colorspace == IMAGE_RGB) + { + if (saturation != 100 || hue != 0) + ImageRGBAdjust(out, img->xsize, saturation, hue); + } + else + { + if (saturation != 100 || hue != 0) + 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); + } + } + + fclose(fp); + free(in); + free(out); + + return (0); +} + + +/* + * 'read_short()' - Read a 16-bit integer. + */ + +static short /* O - Value from file */ +read_short(FILE *fp) /* I - File to read from */ +{ + int ch; /* Character from file */ + + + ch = getc(fp); + return ((ch << 8) | getc(fp)); +} + + +/* + * End of "$Id$". + */ diff --git a/filter/image-png.c b/filter/image-png.c new file mode 100644 index 0000000000..996e1726a9 --- /dev/null +++ b/filter/image-png.c @@ -0,0 +1,250 @@ +/* + * "$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 */ + int pass, /* Current pass */ + passes; /* Number of passes required */ + ib_t *in, /* Input pixels */ + *inptr, /* Pointer into pixels */ + *out; /* Output pixels */ + png_color_16 bg; /* Background color */ + + /* + * 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); + + passes = png_set_interlace_handling(pp); + + /* + * Handle transparency... + */ + + if (png_get_valid(pp, info, PNG_INFO_tRNS)) + png_set_tRNS_to_alpha(pp); + + bg.red = 65535; + bg.green = 65535; + bg.blue = 65535; + + png_set_background(pp, &bg, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); + + if (passes == 1) + { + /* + * Load one row at a time... + */ + + 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); + } + else + { + /* + * Interlaced images must be loaded all at once... + */ + + if (info->color_type == PNG_COLOR_TYPE_GRAY || + info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + in = malloc(img->xsize * img->ysize); + else + in = malloc(img->xsize * img->ysize * 3); + } + + bpp = ImageGetDepth(img); + out = malloc(img->xsize * bpp); + + /* + * Read the image, interlacing as needed... + */ + + for (pass = 1; pass <= passes; pass ++) + for (inptr = in, y = 0; y < img->ysize; y ++) + { + png_read_row(pp, (png_bytep)inptr, NULL); + + if (pass == passes) + { + /* + * Output this row... + */ + + if (info->color_type == PNG_COLOR_TYPE_GRAY || + info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + switch (img->colorspace) + { + case IMAGE_WHITE : + memcpy(out, inptr, img->xsize); + break; + case IMAGE_RGB : + ImageWhiteToRGB(inptr, out, img->xsize); + break; + case IMAGE_BLACK : + ImageWhiteToBlack(inptr, out, img->xsize); + break; + case IMAGE_CMY : + ImageWhiteToCMY(inptr, out, img->xsize); + break; + case IMAGE_CMYK : + ImageWhiteToCMYK(inptr, out, img->xsize); + break; + } + } + else + { + if ((saturation != 100 || hue != 0) && bpp > 1) + ImageRGBAdjust(inptr, img->xsize, saturation, hue); + + switch (img->colorspace) + { + case IMAGE_WHITE : + ImageRGBToWhite(inptr, out, img->xsize); + break; + case IMAGE_RGB : + memcpy(out, inptr, img->xsize * 3); + break; + case IMAGE_BLACK : + ImageRGBToBlack(inptr, out, img->xsize); + break; + case IMAGE_CMY : + ImageRGBToCMY(inptr, out, img->xsize); + break; + case IMAGE_CMYK : + ImageRGBToCMYK(inptr, out, img->xsize); + break; + } + } + + if (lut) + ImageLut(out, img->xsize * bpp, lut); + + ImagePutRow(img, 0, y, img->xsize, out); + } + + if (passes > 1) + { + if (info->color_type == PNG_COLOR_TYPE_GRAY || + info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + inptr += img->xsize; + else + inptr += img->xsize * 3; + } + } + + png_read_end(pp, info); + png_read_destroy(pp, info, NULL); + + fclose(fp); + free(in); + free(out); + + 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..8aa11321a8 --- /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], alpha = rows[3], 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..ada20b5bbc --- /dev/null +++ b/filter/image-sun.c @@ -0,0 +1,377 @@ +/* + * "$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; + run_value = 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..259cc406cd --- /dev/null +++ b/filter/image-tiff.c @@ -0,0 +1,1661 @@ +/* + * "$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 +# 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 */ + compression, /* Type of compression */ + 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 */ + row, /* Current row in image */ + 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_COMPRESSION, &compression) || + !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; + } + + fprintf(stderr, "DEBUG: TIFF resolution = %fx%f, units=%d\n", + xres, yres, resunit); + fprintf(stderr, "DEBUG: Stored resolution = %dx%d PPI\n", + img->xppi, img->yppi); + } + + /* + * 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 : + fputs("DEBUG: orientation = top-right\n", stderr); + break; + case ORIENTATION_RIGHTTOP : + fputs("DEBUG: orientation = right-top\n", stderr); + break; + default : + case ORIENTATION_TOPLEFT : + fputs("DEBUG: orientation = top-left\n", stderr); + break; + case ORIENTATION_LEFTTOP : + fputs("DEBUG: orientation = left-top\n", stderr); + break; + case ORIENTATION_BOTLEFT : + fputs("DEBUG: orientation = bottom-left\n", stderr); + break; + case ORIENTATION_LEFTBOT : + fputs("DEBUG: orientation = left-bottom\n", stderr); + break; + case ORIENTATION_BOTRIGHT : + fputs("DEBUG: orientation = bottom-right\n", stderr); + break; + case ORIENTATION_RIGHTBOT : + fputs("DEBUG: orientation = right-bottom\n", stderr); + break; + } + + 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... + */ + + fprintf(stderr, "DEBUG: photometric = %d\n", photometric); + fprintf(stderr, "DEBUG: compression = %d\n", compression); + + switch (photometric) + { + case PHOTOMETRIC_MINISWHITE : + case PHOTOMETRIC_MINISBLACK : + if (photometric == PHOTOMETRIC_MINISWHITE) + { + zero = 255; + one = 0; + } + else + { + zero = 0; + one = 255; + } + + if (orientation < ORIENTATION_LEFTTOP) + { + /* + * Row major order... + */ + + for (y = ystart, ycount = img->ysize, row = 0; + ycount > 0; + ycount --, y += ydir, row ++) + { + if (bits == 1) + { + TIFFReadScanline(tif, scanline, row, 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, row, 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, row, 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, row, 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, row, 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, row = 0; + xcount > 0; + xcount --, x += xdir, row ++) + { + if (bits == 1) + { + TIFFReadScanline(tif, scanline, row, 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, row, 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, row, 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, row, 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, row, 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, row = 0; + ycount > 0; + ycount --, y += ydir, row ++) + { + if (bits == 1) + { + TIFFReadScanline(tif, scanline, row, 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, row, 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, row, 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, row, 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, row = 0; + xcount > 0; + xcount --, x += xdir, row ++) + { + if (bits == 1) + { + TIFFReadScanline(tif, scanline, row, 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, row, 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, row, 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, row, 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, row = 0; + ycount > 0; + ycount --, y += ydir, row ++) + { + if (bits == 1) + { + TIFFReadScanline(tif, scanline, row, 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, row, 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, row, 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, row, 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, row, 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, row = 0; + xcount > 0; + xcount --, x += xdir, row ++) + { + if (bits == 1) + { + TIFFReadScanline(tif, scanline, row, 0); + for (ycount = img->ysize, scanptr = scanline, p = in + ystart * 3, bit = 0xf0; + ycount > 0; + ycount --, 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, row, 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, row, 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, row, 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, row, 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, row = 0; + ycount > 0; + ycount --, y += ydir, row ++) + { + if (bits == 1) + { + TIFFReadScanline(tif, scanline, row, 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, row, 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, row, 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, row, 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, row = 0; + xcount > 0; + xcount --, x += xdir, row ++) + { + if (bits == 1) + { + TIFFReadScanline(tif, scanline, row, 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, row, 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, row, 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, row, 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..0bc6cceffe --- /dev/null +++ b/filter/image.c @@ -0,0 +1,800 @@ +/* + * "$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 +#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... */ + + + fprintf(stderr, "DEBUG: ImageOpen(\"%s\", %d, %d, %d, %d, %p)\n", + filename ? filename : "(null)", primary, secondary, + saturation, hue, lut); + + /* + * Range check... + */ + + if (filename == NULL) + { + fputs("ERROR: Image filename == NULL!\n", stderr); + return (NULL); + } + + /* + * Figure out the file type... + */ + + if ((fp = fopen(filename, "r")) == NULL) + { + perror("ERROR: Unable to open image file"); + return (NULL); + } + + if (fread(header, 1, sizeof(header), fp) == 0) + { + perror("ERROR: Unable to read image file header"); + + 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) + { + perror("ERROR: Unable to allocate memory for image file"); + 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 (memcmp(header, "BM", 2) == 0) + status = ImageReadBMP(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); + else if (memcmp(header + 8, "\000\010", 2) == 0 || + memcmp(header + 8, "\000\030", 2) == 0) + status = ImageReadPIX(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, "\377\330\377", 3) == 0 && /* Start-of-Image */ + header[3] >= 0xe0 && header[3] <= 0xef) /* APPn */ + 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 + { + fputs("ERROR: Unknown image file format!\n", stderr); + 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, next = NULL; current != NULL; current = next) + { + fprintf(stderr, "DEBUG: Freeing cache (%p, next = %p)...\n", + current, next); + + next = current->next; + free(current); + } + + /* + * Free the rest of memory... + */ + + if (img->tiles != NULL) + { + fprintf(stderr, "DEBUG: Freeing tiles (%p)...\n", img->tiles[0]); + + free(img->tiles[0]); + + fprintf(stderr, "DEBUG: Freeing tile pointers (%p)...\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 (%p)...\n", + img->num_ics, ic); + } + else + { + fprintf(stderr, "DEBUG: Flushing old cache tile (%p)...\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 %ld...\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 %ld...\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..858926d6ea --- /dev/null +++ b/filter/image.h @@ -0,0 +1,231 @@ +/* + * "$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 ImageReadBMP(image_t *img, FILE *fp, int primary, int secondary, + int saturation, int hue, const ib_t *lut); +extern int ImageReadFPX(image_t *img, FILE *fp, int primary, int secondary, + int saturation, int hue, const ib_t *lut); +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 ImageReadPIX(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..f99dc9e30a --- /dev/null +++ b/filter/imagetops.c @@ -0,0 +1,735 @@ +/* + * "$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 */ + XPosition = 0, /* Horizontal position on page */ + YPosition = 0, /* Vertical position on page */ + 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; + float aspect; /* Aspect ratio */ + 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 xppi, yppi; /* Pixels-per-inch */ + int hue, sat; /* Hue and saturation adjustment */ + int realcopies; /* Real copies being printed */ + float left, top; /* Left and top of image */ + char filename[1024]; /* Name of file to print */ + + + /* + * Check arguments... + */ + + if (argc < 6 || argc > 7) + { + fputs("ERROR: imagetops 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] ? argv[6] : "(null)"); + + /* + * Copy stdin as needed... + */ + + if (argc == 6) + { + FILE *fp; /* File to read from */ + char buffer[8192]; /* Buffer to read into */ + int bytes; /* # of bytes to read */ + + + if ((fp = fopen(cupsTempFile(filename, sizeof(filename)), "w")) == NULL) + { + perror("ERROR: Unable to copy image file"); + return (1); + } + + fprintf(stderr, "DEBUG: imagetops - copying to temp print file \"%s\"\n", + filename); + + while ((bytes = fread(buffer, 1, sizeof(buffer), stdin)) > 0) + fwrite(buffer, 1, bytes, fp); + fclose(fp); + } + else + { + strncpy(filename, argv[6], sizeof(filename) - 1); + filename[sizeof(filename) - 1] = '\0'; + } + + /* + * Process command-line options and write the prolog... + */ + + zoom = 0.0; + xppi = 0; + yppi = 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-uncollated-copies allows for uncollated copies. + */ + + Collate = strcasecmp(val, "separate-documents-uncollated-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) + if (sscanf(val, "%dx%d", &xppi, &yppi) < 2) + yppi = xppi; + + if ((val = cupsGetOption("position", num_options, options)) != NULL) + { + if (strcasecmp(val, "center") == 0) + { + XPosition = 0; + YPosition = 0; + } + else if (strcasecmp(val, "top") == 0) + { + XPosition = 0; + YPosition = 1; + } + else if (strcasecmp(val, "left") == 0) + { + XPosition = -1; + YPosition = 0; + } + else if (strcasecmp(val, "right") == 0) + { + XPosition = 1; + YPosition = 0; + } + else if (strcasecmp(val, "top-left") == 0) + { + XPosition = -1; + YPosition = 1; + } + else if (strcasecmp(val, "top-right") == 0) + { + XPosition = 1; + YPosition = 1; + } + else if (strcasecmp(val, "bottom") == 0) + { + XPosition = 0; + YPosition = -1; + } + else if (strcasecmp(val, "bottom-left") == 0) + { + XPosition = -1; + YPosition = -1; + } + else if (strcasecmp(val, "bottom-right") == 0) + { + XPosition = 1; + YPosition = -1; + } + } + + 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; + + img = ImageOpen(filename, colorspace, IMAGE_WHITE, sat, hue, NULL); + + if (argc == 6) + unlink(filename); + + if (img == NULL) + { + fputs("ERROR: Unable to open image file for printing!\n", stderr); + ppdClose(ppd); + return (1); + } + + colorspace = img->colorspace; + + /* + * Scale as necessary... + */ + + xprint = (PageRight - PageLeft) / 72.0; + yprint = (PageTop - PageBottom) / 72.0; + + if (zoom == 0.0 && xppi == 0) + { + xppi = img->xppi; + yppi = img->yppi; + } + + if (yppi == 0) + yppi = xppi; + + if (xppi > 0) + { + /* + * Scale the image as neccesary to match the desired pixels-per-inch. + */ + + xinches = (float)img->xsize / (float)xppi; + yinches = (float)img->ysize / (float)yppi; + + if (cupsGetOption("orientation", num_options, options) == NULL && + cupsGetOption("landscape", num_options, options) == NULL) + { + /* + * 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... + */ + + aspect = (float)img->yppi / (float)img->xppi; + + fprintf(stderr, "DEBUG: img->xppi = %d, img->yppi = %d, aspect = %f\n", + img->xppi, img->yppi, aspect); + + xsize = xprint * zoom; + ysize = xsize * img->ysize / img->xsize / aspect; + + if (ysize > (yprint * zoom)) + { + ysize = yprint * zoom; + xsize = ysize * img->xsize * aspect / img->ysize; + } + + xsize2 = yprint * zoom; + ysize2 = xsize2 * img->ysize / img->xsize / aspect; + + if (ysize2 > (xprint * zoom)) + { + ysize2 = xprint * zoom; + xsize2 = ysize2 * img->xsize * aspect / img->ysize; + } + + fprintf(stderr, "DEBUG: xsize = %.0f, ysize = %.0f\n", xsize, ysize); + fprintf(stderr, "DEBUG: xsize2 = %.0f, ysize2 = %.0f\n", xsize2, ysize2); + + if (cupsGetOption("orientation", num_options, options) == NULL && + cupsGetOption("landscape", num_options, options) == NULL) + { + /* + * 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; + } + } + else if (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 + { + xinches = xsize; + yinches = ysize; + xprint = (PageRight - PageLeft) / 72.0; + yprint = (PageTop - PageBottom) / 72.0; + } + } + + 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; + + switch (XPosition) + { + case -1 : + left = PageLeft; + break; + default : + left = (PageWidth - xprint * 72.0) * 0.5; + break; + case 1 : + left = PageRight - xprint * 72.0; + break; + } + + switch (YPosition) + { + case -1 : + top = PageBottom + 72.0 * yprint; + break; + default : + top = (PageLength + yprint * 72.0) * 0.5; + break; + case 1 : + top = PageTop; + break; + } + + printf("%.1f %.1f translate\n", left, top); + + 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? */ +{ + 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..c1fc046cdb --- /dev/null +++ b/filter/imagetoraster.c @@ -0,0 +1,4316 @@ +/* + * "$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... + * exec_code() - Execute PostScript setpagedevice commands as + * appropriate. + * 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 "common.h" +#include "image.h" +#include "raster.h" +#include + + +/* + * Globals... + */ + +int Flip = 0, /* Flip/mirror pages */ + XPosition = 0, /* Horizontal position on page */ + YPosition = 0, /* Vertical position on page */ + 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_code(cups_page_header_t *header, const char *code); +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; + float aspect; /* Aspect ratio */ + 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 */ + **choices; /* List of marked choices */ + int count; /* Number of marked choices */ + 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 xppi, yppi; /* 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 */ + char filename[1024]; /* Name of file to print */ + + + /* + * Check arguments... + */ + + if (argc < 6 || 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] ? argv[6] : "(null)"); + + /* + * Copy stdin as needed... + */ + + if (argc == 6) + { + FILE *fp; /* File to read from */ + char buffer[8192]; /* Buffer to read into */ + int bytes; /* # of bytes to read */ + + + if ((fp = fopen(cupsTempFile(filename, sizeof(filename)), "w")) == NULL) + { + perror("ERROR: Unable to copy image file"); + return (1); + } + + fprintf(stderr, "DEBUG: imagetoraster - copying to temp print file \"%s\"\n", + filename); + + while ((bytes = fread(buffer, 1, sizeof(buffer), stdin)) > 0) + fwrite(buffer, 1, bytes, fp); + fclose(fp); + } + else + { + strncpy(filename, argv[6], sizeof(filename) - 1); + filename[sizeof(filename) - 1] = '\0'; + } + + /* + * Process command-line options and write the prolog... + */ + + zoom = 0.0; + xppi = 0; + yppi = 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) + if (sscanf(val, "%dx%d", &xppi, &yppi) < 2) + yppi = xppi; + + if ((val = cupsGetOption("position", num_options, options)) != NULL) + { + if (strcasecmp(val, "center") == 0) + { + XPosition = 0; + YPosition = 0; + } + else if (strcasecmp(val, "top") == 0) + { + XPosition = 0; + YPosition = 1; + } + else if (strcasecmp(val, "left") == 0) + { + XPosition = -1; + YPosition = 0; + } + else if (strcasecmp(val, "right") == 0) + { + XPosition = 1; + YPosition = 0; + } + else if (strcasecmp(val, "top-left") == 0) + { + XPosition = -1; + YPosition = 1; + } + else if (strcasecmp(val, "top-right") == 0) + { + XPosition = 1; + YPosition = 1; + } + else if (strcasecmp(val, "bottom") == 0) + { + XPosition = 0; + YPosition = -1; + } + else if (strcasecmp(val, "bottom-left") == 0) + { + XPosition = -1; + YPosition = -1; + } + else if (strcasecmp(val, "bottom-right") == 0) + { + XPosition = 1; + YPosition = -1; + } + } + + 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_K; + + if (ppd && ppd->patches) + exec_code(&header, ppd->patches); + + if ((count = ppdCollect(ppd, PPD_ORDER_DOCUMENT, &choices)) > 0) + for (i = 0; i < count; i ++) + exec_code(&header, choices[i]->code); + + if ((count = ppdCollect(ppd, PPD_ORDER_ANY, &choices)) > 0) + for (i = 0; i < count; i ++) + exec_code(&header, choices[i]->code); + + if ((count = ppdCollect(ppd, PPD_ORDER_PROLOG, &choices)) > 0) + for (i = 0; i < count; i ++) + exec_code(&header, choices[i]->code); + + if ((count = ppdCollect(ppd, PPD_ORDER_PAGE, &choices)) > 0) + for (i = 0; i < count; i ++) + exec_code(&header, choices[i]->code); + + /* + * Get the media type and resolution that have been chosen... + */ + + if ((choice = ppdFindMarkedChoice(ppd, "MediaType")) != NULL) + media_type = choice->choice; + else + media_type = ""; + + if ((choice = ppdFindMarkedChoice(ppd, "Resolution")) != NULL) + 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; + } + else + 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); + + img = ImageOpen(filename, primary, secondary, sat, hue, lut); + + if (argc == 6) + unlink(filename); + + if (img == NULL) + { + fputs("ERROR: Unable to open image file for printing!\n", stderr); + ppdClose(ppd); + return (1); + } + + /* + * Scale as necessary... + */ + + if (zoom == 0.0 && xppi == 0) + { + xppi = img->xppi; + yppi = img->yppi; + } + + if (yppi == 0) + yppi = xppi; + + if (xppi > 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)xppi; + yinches = (float)img->ysize / (float)yppi; + + if (cupsGetOption("orientation", num_options, options) == NULL && + cupsGetOption("landscape", num_options, options) == NULL) + { + /* + * 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; + aspect = (float)img->yppi / (float)img->xppi; + + fprintf(stderr, "DEBUG: img->xppi = %d, img->yppi = %d, aspect = %f\n", + img->xppi, img->yppi, aspect); + + xsize = xprint * zoom; + ysize = xsize * img->ysize / img->xsize / aspect; + + if (ysize > (yprint * zoom)) + { + ysize = yprint * zoom; + xsize = ysize * img->xsize * aspect / img->ysize; + } + + xsize2 = yprint * zoom; + ysize2 = xsize2 * img->ysize / img->xsize / aspect; + + if (ysize2 > (xprint * zoom)) + { + ysize2 = xprint * zoom; + xsize2 = ysize2 * img->xsize * aspect / img->ysize; + } + + fprintf(stderr, "DEBUG: xsize = %.0f, ysize = %.0f\n", xsize, ysize); + fprintf(stderr, "DEBUG: xsize2 = %.0f, ysize2 = %.0f\n", xsize2, ysize2); + + if (cupsGetOption("orientation", num_options, options) == NULL && + cupsGetOption("landscape", num_options, options) == NULL) + { + /* + * 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; + } + } + else if (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 + { + xinches = xsize; + yinches = ysize; + xprint = (PageRight - PageLeft) / 72.0; + yprint = (PageTop - PageBottom) / 72.0; + } + } + + xpages = ceil(xinches / xprint); + ypages = ceil(yinches / yprint); + + fprintf(stderr, "DEBUG: xpages = %d, ypages = %d\n", xpages, ypages); + + /* + * 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; + + fprintf(stderr, "DEBUG: PageSize = [%d %d]\n", header.PageSize[0], + header.PageSize[1]); + + switch (Orientation) + { + case 0 : + switch (XPosition) + { + case -1 : + header.ImagingBoundingBox[0] = PageLeft; + header.ImagingBoundingBox[2] = PageLeft + xprint * 72; + break; + default : + header.ImagingBoundingBox[0] = (PageRight + PageLeft - xprint * 72) / 2; + header.ImagingBoundingBox[2] = (PageRight + PageLeft + xprint * 72) / 2; + break; + case 1 : + header.ImagingBoundingBox[0] = PageRight - xprint * 72; + header.ImagingBoundingBox[2] = PageRight; + break; + } + + switch (YPosition) + { + case -1 : + header.ImagingBoundingBox[1] = PageBottom; + header.ImagingBoundingBox[3] = PageBottom + yprint * 72; + break; + default : + header.ImagingBoundingBox[1] = (PageTop + PageBottom - yprint * 72) / 2; + header.ImagingBoundingBox[3] = (PageTop + PageBottom + yprint * 72) / 2; + break; + case 1 : + header.ImagingBoundingBox[1] = PageTop - yprint * 72; + header.ImagingBoundingBox[3] = PageTop; + break; + } + break; + + case 1 : + switch (XPosition) + { + case -1 : + header.ImagingBoundingBox[0] = PageBottom; + header.ImagingBoundingBox[2] = PageBottom + yprint * 72; + break; + default : + header.ImagingBoundingBox[0] = (PageTop + PageBottom - yprint * 72) / 2; + header.ImagingBoundingBox[2] = (PageTop + PageBottom + yprint * 72) / 2; + break; + case 1 : + header.ImagingBoundingBox[0] = PageTop - yprint * 72; + header.ImagingBoundingBox[2] = PageTop; + break; + } + + switch (YPosition) + { + case -1 : + header.ImagingBoundingBox[1] = PageLeft; + header.ImagingBoundingBox[3] = PageLeft + xprint * 72; + break; + default : + header.ImagingBoundingBox[1] = (PageRight + PageLeft - xprint * 72) / 2; + header.ImagingBoundingBox[3] = (PageRight + PageLeft + xprint * 72) / 2; + break; + case 1 : + header.ImagingBoundingBox[1] = PageRight - xprint * 72; + header.ImagingBoundingBox[3] = PageRight; + break; + } + break; + + case 2 : + switch (XPosition) + { + case 1 : + header.ImagingBoundingBox[0] = PageLeft; + header.ImagingBoundingBox[2] = PageLeft + xprint * 72; + break; + default : + header.ImagingBoundingBox[0] = (PageRight + PageLeft - xprint * 72) / 2; + header.ImagingBoundingBox[2] = (PageRight + PageLeft + xprint * 72) / 2; + break; + case -1 : + header.ImagingBoundingBox[0] = PageRight - xprint * 72; + header.ImagingBoundingBox[2] = PageRight; + break; + } + + switch (YPosition) + { + case 1 : + header.ImagingBoundingBox[1] = PageBottom; + header.ImagingBoundingBox[3] = PageBottom + yprint * 72; + break; + default : + header.ImagingBoundingBox[1] = (PageTop + PageBottom - yprint * 72) / 2; + header.ImagingBoundingBox[3] = (PageTop + PageBottom + yprint * 72) / 2; + break; + case -1 : + header.ImagingBoundingBox[1] = PageTop - yprint * 72; + header.ImagingBoundingBox[3] = PageTop; + break; + } + break; + + case 3 : + switch (XPosition) + { + case 1 : + header.ImagingBoundingBox[0] = PageBottom; + header.ImagingBoundingBox[2] = PageBottom + yprint * 72; + break; + default : + header.ImagingBoundingBox[0] = (PageTop + PageBottom - yprint * 72) / 2; + header.ImagingBoundingBox[2] = (PageTop + PageBottom + yprint * 72) / 2; + break; + case -1 : + header.ImagingBoundingBox[0] = PageTop - yprint * 72; + header.ImagingBoundingBox[2] = PageTop; + break; + } + + switch (YPosition) + { + case 1 : + header.ImagingBoundingBox[1] = PageLeft; + header.ImagingBoundingBox[3] = PageLeft + xprint * 72; + break; + default : + header.ImagingBoundingBox[1] = (PageRight + PageLeft - xprint * 72) / 2; + header.ImagingBoundingBox[3] = (PageRight + PageLeft + xprint * 72) / 2; + break; + case -1 : + header.ImagingBoundingBox[1] = PageRight - xprint * 72; + header.ImagingBoundingBox[3] = PageRight; + break; + } + break; + } + + switch (header.cupsColorOrder) + { + default : + 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 && YPosition <= 0) + { + memset(row, blank, header.cupsBytesPerLine); + + y = header.cupsHeight - z->ysize; + if (YPosition == 0) + y /= 2; + + for (; 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 && YPosition >= 0) + { + memset(row, blank, header.cupsBytesPerLine); + + y = header.cupsHeight - z->ysize; + if (YPosition == 0) + y = y - y / 2; + + for (; 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_code()' - Execute PostScript setpagedevice commands as appropriate. + */ + +static void +exec_code(cups_page_header_t *header, /* I - Page header */ + const char *code) /* I - Option choice to execute */ +{ + char *ptr, /* Pointer into name/value string */ + name[255], /* Name of pagedevice entry */ + value[1024]; /* Value of pagedevice entry */ + + + for (; *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, (char **)&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 || /* Compatibility */ + strcmp(name, "MediaPosition") == 0) + header->MediaPosition = atoi(value); + else if (strcmp(name, "MediaClass") == 0) + strncpy(header->MediaClass, value, sizeof(header->MediaClass) - 1); + else if (strcmp(name, "MediaColor") == 0) + strncpy(header->MediaColor, value, sizeof(header->MediaColor) - 1); + 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 */ + + + switch (XPosition) + { + case -1 : + bitoffset = 0; + break; + default : + bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2); + break; + case 1 : + bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize); + break; + } + + 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 */ + + + switch (XPosition) + { + case -1 : + bitoffset = 0; + break; + default : + bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2); + break; + case 1 : + bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize); + break; + } + + 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 */ + + + switch (XPosition) + { + case -1 : + bitoffset = 0; + break; + default : + bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2); + break; + case 1 : + bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize); + break; + } + + 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 */ + + + switch (XPosition) + { + case -1 : + bitoffset = 0; + break; + default : + bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2); + break; + case 1 : + bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize); + break; + } + + 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 */ + + + switch (XPosition) + { + case -1 : + bitoffset = 0; + break; + default : + bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2); + break; + case 1 : + bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize); + break; + } + + 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 */ + + + switch (XPosition) + { + case -1 : + bitoffset = 0; + break; + default : + bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2); + break; + case 1 : + bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize); + break; + } + + 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 */ + + + switch (XPosition) + { + case -1 : + bitoffset = 0; + break; + default : + bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2); + break; + case 1 : + bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize); + break; + } + + 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 */ + + + switch (XPosition) + { + case -1 : + bitoffset = 0; + break; + default : + bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2); + break; + case 1 : + bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize); + break; + } + + 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 */ + + + switch (XPosition) + { + case -1 : + bitoffset = 0; + break; + default : + bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2); + break; + case 1 : + bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize); + break; + } + + 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..fb07d22d90 --- /dev/null +++ b/filter/pstops.c @@ -0,0 +1,910 @@ +/* + * "$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 */ + int saweof; /* Did we see a %%EOF tag? */ + + + /* + * Check arguments... + */ + + 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-uncollated-copies allows for uncollated copies. + */ + + Collate = strcasecmp(val, "separate-documents-uncollated-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; + } + else + temp = 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); + + if (strncmp(ppd->jcl_ps, "@PJL", 4) == 0) + { + /* + * Send other PJL commands before we enter PostScript mode... + */ + + printf("@PJL JOB NAME = \"%s\" DISPLAY = \"%s %s %s\"\n", argv[3], + argv[1], argv[2], argv[3]); + } + + 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); + + saweof = 0; + + 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) + { + if (tbytes > sizeof(line)) + nbytes = fread(line, 1, sizeof(line), fp); + else + nbytes = fread(line, 1, tbytes, 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 (strcmp(line, "%%EOF") == 0 && level == 0) + saweof = 1; + 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) + { + if (tbytes > sizeof(line)) + nbytes = fread(line, 1, sizeof(line), fp); + else + nbytes = fread(line, 1, tbytes, 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); + Copies --; + } + } + } + + /* + * Send %%EOF if needed... + */ + + if (!saweof) + puts("%%EOF"); + + /* + * 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; + ch = EOF; + + 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("%.1f 0.0 translate -1 1 scale\n", PageWidth); + + pw = PageRight - PageLeft; + pl = PageTop - PageBottom; + + fprintf(stderr, "DEBUG: pw = %.1f, pl = %.1f\n", pw, pl); + fprintf(stderr, "DEBUG: PageLeft = %.1f, PageRight = %.1f\n", PageLeft, PageRight); + fprintf(stderr, "DEBUG: PageTop = %.1f, PageBottom = %.1f\n", PageTop, PageBottom); + fprintf(stderr, "DEBUG: PageWidth = %.1f, PageLength = %.1f\n", PageWidth, PageLength); + + switch (Orientation) + { + case 1 : /* Landscape */ + printf("%.1f 0.0 translate 90 rotate\n", PageLength); + break; + case 2 : /* Reverse Portrait */ + printf("%.1f %.1f translate 180 rotate\n", PageWidth, PageLength); + break; + case 3 : /* Reverse Landscape */ + printf("0.0 %.1f 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("%.1f %.1f translate\n", PageWidth - PageRight, PageBottom); + else + printf("%.1f %.1f translate\n", PageLeft, PageBottom); + + if (Orientation & 1) + { + printf("0.0 %.1f translate -90 rotate\n", pl); + printf("%.1f %.1f translate %.3f %.3f scale\n", + ty, tx + l * x, w / PageWidth, l / PageLength); + } + else + { + printf("%.1f 0.0 translate 90 rotate\n", pw); + printf("%.1f %.1f translate %.3f %.3f scale\n", + tx + w * x, ty, w / PageWidth, l / PageLength); + } + + printf("newpath\n" + "0.0 0.0 moveto\n" + "%.1f 0.0 lineto\n" + "%.1f %.1f lineto\n" + "0.0 %.1f 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("%.1f %.1f translate\n", PageWidth - PageRight, PageBottom); + else + printf("%.1f %.1f translate\n", PageLeft, PageBottom); + + printf("%.1f %.1f translate %.3f %.3f scale\n", x * w, y * l, + w / PageWidth, l / PageLength); + printf("newpath\n" + "0.0 0.0 moveto\n" + "%.1f 0.0 lineto\n" + "%.1f %.1f lineto\n" + "0.0 %.1f 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..4398932fac --- /dev/null +++ b/filter/rastertoepson.c @@ -0,0 +1,992 @@ +/* + * "$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 + + +/* + * Model numbers... + */ + +#define EPSON_9PIN 0 +#define EPSON_24PIN 1 +#define EPSON_COLOR 2 +#define EPSON_PHOTO 3 + + +/* + * Macros... + */ + +#define pwrite(s,n) fwrite((s), 1, (n), stdout) + + +/* + * Globals... + */ + +unsigned char *Planes[6], /* Output buffers */ + *CompBuffer, /* Compression buffer */ + *LineBuffers[2]; /* Line bitmap buffers */ +int NumPlanes, /* Number of color planes */ + Feed; /* Number of lines to skip */ +int DotBit, /* Bit in buffers */ + DotBytes, /* # bytes in a dot column */ + DotColumns, /* # columns in 1/60 inch */ + LineCount, /* # of lines processed */ + EvenOffset, /* Offset into 'even' buffers */ + OddOffset, /* Offset into 'odd' buffers */ + Shingling; /* Shingle output? */ + + +/* + * Prototypes... + */ + +void Setup(void); +void StartPage(const ppd_file_t *ppd, const cups_page_header_t *header); +void EndPage(const cups_page_header_t *header); +void Shutdown(void); + +void CompressData(const unsigned char *line, int length, int plane, + int type, int xstep, int ystep); +void OutputLine(const cups_page_header_t *header); +void OutputRows(const cups_page_header_t *header, int row); + + +/* + * 'Setup()' - Prepare the printer for printing. + */ + +void +Setup(void) +{ +} + + +/* + * 'StartPage()' - Start a page of graphics. + */ + +void +StartPage(const ppd_file_t *ppd, /* I - PPD file */ + const cups_page_header_t *header) /* I - Page header */ +{ + int n, t; /* Numbers */ + int plane; /* Looping var */ + + + /* + * Send a reset sequence. + */ + + if (ppd->nickname && strstr(ppd->nickname, "OKIDATA") != NULL) + printf("\033{A"); /* Set EPSON emulation mode */ + + printf("\033@"); + + /* + * See which type of printer we are using... + */ + + switch (ppd->model_number) + { + case EPSON_9PIN : + case EPSON_24PIN : + printf("\033P"); /* Set 10 CPI */ + + if (header->HWResolution[0] == 360 || header->HWResolution[0] == 240) + { + printf("\033x1"); /* LQ printing */ + printf("\033U1"); /* Unidirectional */ + } + else + { + printf("\033x0"); /* Draft printing */ + printf("\033U0"); /* Bidirectional */ + } + + printf("\033l%c\033Q%c", 0, /* Side margins */ + (int)(10.0 * header->PageSize[0] / 72.0 + 0.5)); + printf("\033C%c%c", 0, /* Page length */ + (int)(header->PageSize[1] / 72.0 + 0.5)); + printf("\033N%c", 0); /* Bottom margin */ + + /* + * Setup various buffer limits... + */ + + DotBytes = header->cupsRowCount / 8; + DotColumns = header->HWResolution[0] / 60; + Shingling = 0; + + if (ppd->model_number == EPSON_9PIN) + printf("\033\063\030"); /* Set line feed */ + else + switch (header->HWResolution[0]) + { + case 60: + case 120 : + printf("\033\063\030"); /* Set line feed */ + break; + + case 180 : + case 360 : + Shingling = 1; + + if (header->HWResolution[1] == 180) + printf("\033\063\010");/* Set line feed */ + else + printf("\033+\010"); /* Set line feed */ + break; + } + break; + + case EPSON_COLOR : + case EPSON_PHOTO : + /* + * 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); + + 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 */ + + DotBytes = 0; + DotColumns = 0; + Shingling = 0; + break; + } + + /* + * 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; + + Feed = 0; /* No blank lines yet */ + + /* + * Allocate memory for a line/row of graphics... + */ + + Planes[0] = malloc(header->cupsBytesPerLine); + for (plane = 1; plane < NumPlanes; plane ++) + Planes[plane] = Planes[0] + plane * header->cupsBytesPerLine / NumPlanes; + + if (header->cupsCompression || DotBytes) + CompBuffer = calloc(2, header->cupsWidth); + + if (DotBytes) + { + LineBuffers[0] = calloc(DotBytes, header->cupsWidth * (Shingling + 1)); + LineBuffers[1] = LineBuffers[0] + DotBytes * header->cupsWidth; + DotBit = 128; + LineCount = 0; + EvenOffset = 0; + OddOffset = 0; + } +} + + +/* + * 'EndPage()' - Finish a page of graphics. + */ + +void +EndPage(const cups_page_header_t *header) /* I - Page header */ +{ + if (DotBytes) + { + /* + * Flush remaining graphics as needed... + */ + + if (!Shingling) + OutputRows(header, 0); + else if (OddOffset > EvenOffset) + { + OutputRows(header, 1); + OutputRows(header, 0); + } + else + { + OutputRows(header, 0); + OutputRows(header, 1); + } + } + + /* + * Eject the current page... + */ + + putchar(12); /* Form feed */ + + /* + * Free memory... + */ + + free(Planes[0]); + + if (header->cupsCompression || DotBytes) + free(CompBuffer); + + if (DotBytes) + free(LineBuffers[0]); +} + + +/* + * 'Shutdown()' - Shutdown the printer. + */ + +void +Shutdown(void) +{ + /* + * Send a reset sequence. + */ + + printf("\033@"); +} + + +/* + * 'CompressData()' - Compress a line of graphics. + */ + +void +CompressData(const 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 */ +{ + const unsigned char *line_ptr, /* Current byte pointer */ + *line_end, /* End-of-line byte pointer */ + *start; /* Start of compression sequence */ + unsigned char *comp_ptr, /* Pointer into compression buffer */ + 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 = (unsigned char *)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(const cups_page_header_t *header) /* I - Page header */ +{ + if (header->cupsRowCount) + { + int width; + unsigned char *tempptr, + *evenptr, + *oddptr; + register int x; + unsigned char bit; + const unsigned char *pixel; + unsigned char *temp; + + + /* + * Collect bitmap data in the line buffers and write after each buffer. + */ + + for (x = header->cupsWidth, bit = 128, pixel = Planes[0], + temp = CompBuffer; + x > 0; + x --, temp ++) + { + if (*pixel & bit) + *temp |= DotBit; + + if (bit > 1) + bit >>= 1; + else + { + bit = 128; + pixel ++; + } + } + + if (DotBit > 1) + DotBit >>= 1; + else + { + /* + * Copy the holding buffer to the output buffer, shingling as necessary... + */ + + if (Shingling && LineCount != 0) + { + /* + * Shingle the output... + */ + + if (LineCount & 1) + { + evenptr = LineBuffers[1] + OddOffset; + oddptr = LineBuffers[0] + EvenOffset + DotBytes; + } + else + { + evenptr = LineBuffers[0] + EvenOffset; + oddptr = LineBuffers[1] + OddOffset + DotBytes; + } + + for (width = header->cupsWidth, tempptr = CompBuffer; + width > 0; + width -= 2, tempptr += 2, oddptr += DotBytes * 2, + evenptr += DotBytes * 2) + { + evenptr[0] = tempptr[0]; + oddptr[0] = tempptr[1]; + } + } + else + { + /* + * Don't shingle the output... + */ + + for (width = header->cupsWidth, tempptr = CompBuffer, + evenptr = LineBuffers[0] + EvenOffset; + width >= 0; + width --, tempptr ++, evenptr += DotBytes) + *evenptr = tempptr[0]; + } + + if (Shingling && LineCount != 0) + { + EvenOffset ++; + OddOffset ++; + + if (EvenOffset == DotBytes) + { + EvenOffset = 0; + OutputRows(header, 0); + } + + if (OddOffset == DotBytes) + { + OddOffset = 0; + OutputRows(header, 1); + } + } + else + { + EvenOffset ++; + + if (EvenOffset == DotBytes) + { + EvenOffset = 0; + OutputRows(header, 0); + } + } + + DotBit = 128; + LineCount ++; + + memset(CompBuffer, 0, header->cupsWidth); + } + } + else + { + int plane; /* Current plane */ + int bytes; /* Bytes per plane */ + int xstep, ystep; /* X & Y resolutions */ + + + /* + * Write a single line of 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 ++; + } +} + + +/* + * 'OutputRows()' - Output 8, 24, or 48 rows. + */ + +void +OutputRows(const cups_page_header_t *header, /* I - Page image header */ + int row) /* I - Row number (0 or 1) */ +{ + unsigned i, n; /* Looping vars */ + int dot_count, /* Number of bytes to print */ + dot_min; /* Minimum number of bytes */ + unsigned char *dot_ptr, /* Pointer to print data */ + *ptr; /* Current data */ + + + dot_min = DotBytes * DotColumns; + + if (LineBuffers[row][0] != 0 || + memcmp(LineBuffers[row], LineBuffers[row] + 1, + header->cupsWidth * DotBytes - 1)) + { + /* + * Skip leading space... + */ + + i = 0; + dot_count = header->cupsWidth * DotBytes; + dot_ptr = LineBuffers[row]; + + while (dot_count >= dot_min && dot_ptr[0] == 0 && + memcmp(dot_ptr, dot_ptr + 1, dot_min - 1) == 0) + { + i ++; + dot_ptr += dot_min; + dot_count -= dot_min; + } + + /* + * Skip trailing space... + */ + + while (dot_count >= dot_min && dot_ptr[dot_count - dot_min] == 0 && + memcmp(dot_ptr + dot_count - dot_min, + dot_ptr + dot_count - dot_min + 1, dot_min - 1) == 0) + dot_count -= dot_min; + + /* + * Position print head for printing... + */ + + putchar(0x1b); + putchar('$'); + putchar(i & 255); + putchar(i >> 8); + + /* + * Start bitmap graphics for this line... + */ + + printf("\033*"); /* Select bit image */ + switch (header->HWResolution[0]) + { + case 60 : /* 60x60/72 DPI gfx */ + putchar(0); + break; + case 120 : /* 120x60/72 DPI gfx */ + putchar(1); + break; + case 180 : /* 180 DPI gfx */ + putchar(39); + break; + case 240 : /* 240x72 DPI gfx */ + putchar(3); + break; + case 360 : /* 360x180/360 DPI gfx */ + if (header->HWResolution[1] == 180) + { + if (Shingling && LineCount != 0) + putchar(40); /* 360x180 fast */ + else + putchar(41); /* 360x180 slow */ + } + else + { + if (Shingling && LineCount != 0) + putchar(72); /* 360x360 fast */ + else + putchar(73); /* 360x360 slow */ + } + break; + } + + n = (unsigned)dot_count / DotBytes; + putchar(n & 255); + putchar(n / 256); + + /* + * Write the graphics data... + */ + + if (header->HWResolution[0] == 120 || + header->HWResolution[0] == 240) + { + /* + * Need to interleave the dots to avoid hosing the print head... + */ + + for (n = dot_count / 2, ptr = dot_ptr; n > 0; n --, ptr += 2) + { + putchar(*ptr); + putchar(0); + } + + /* + * Move the head back and print the odd bytes... + */ + + putchar(0x1b); + putchar('$'); + putchar(i & 255); + putchar(i >> 8); + + if (header->HWResolution[0] == 120) + printf("\033*\001"); /* Select bit image */ + else + printf("\033*\003"); /* Select bit image */ + + n = (unsigned)dot_count / DotBytes; + putchar(n & 255); + putchar(n / 256); + + for (n = dot_count / 2, ptr = dot_ptr + 1; n > 0; n --, ptr += 2) + { + putchar(0); + putchar(*ptr); + } + } + else + pwrite(dot_ptr, dot_count); + } + + /* + * Feed the paper... + */ + + putchar('\n'); + + if (Shingling && row == 1) + { + if (header->HWResolution[1] == 360) + printf("\n\n\n\n"); + else + printf("\n"); + } + + /* + * Clear the buffer... + */ + + memset(LineBuffers[row], 0, header->cupsWidth * DotBytes); +} + + +/* + * '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(ppd, &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; + + /* + * 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..3adb145006 --- /dev/null +++ b/filter/rastertohp.c @@ -0,0 +1,575 @@ +/* + * "$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 */ + Page; /* Current page number */ + + +/* + * 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 */ + + + if (!header->Duplex || (Page & 1)) + { + /* + * Set the media type, position, and size... + */ + + printf("\033&l6D\033&k12H"); /* Set 6 LPI, 10 CPI */ + + switch (header->PageSize[1]) + { + case 540 : /* Monarch Envelope */ + printf("\033&l80A"); /* Set page size */ + break; + + case 624 : /* DL Envelope */ + printf("\033&l90A"); /* Set page size */ + break; + + case 649 : /* C5 Envelope */ + printf("\033&l91A"); /* Set page size */ + break; + + case 684 : /* COM-10 Envelope */ + printf("\033&l81A"); /* Set page size */ + break; + + case 709 : /* B5 Envelope */ + printf("\033&l100A"); /* Set page size */ + break; + + case 756 : /* Executive */ + printf("\033&l1A"); /* Set page size */ + break; + + case 792 : /* Letter */ + printf("\033&l2A"); /* Set page size */ + break; + + case 842 : /* A4 */ + printf("\033&l26A"); /* Set page size */ + break; + + case 1008 : /* Legal */ + printf("\033&l3A"); /* Set page size */ + break; + + case 1191 : /* A3 */ + printf("\033&l27A"); /* Set page size */ + break; + + case 1224 : /* Tabloid */ + printf("\033&l6A"); /* Set page size */ + break; + } + + printf("\033&l%dP", /* Set page length */ + header->PageSize[1] / 12); + printf("\033&l0E"); /* Set top margin to 0 */ + + printf("\033&l%dX", header->NumCopies); /* Set number copies */ + + if (header->MediaPosition) + printf("\033&l%dH", /* Set media position */ + header->MediaPosition); + + if (header->cupsMediaType) + printf("\033&l%dM", /* Set media type */ + header->cupsMediaType); + + if (header->Duplex) + printf("\033&l%dS", /* Set duplex mode */ + header->Duplex + header->Tumble); + + printf("\033&l0L"); /* Turn off perforation skip */ + } + else + printf("\033&a2G"); /* Set back side */ + + /* + * Set graphics mode... + */ + + 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 */ + + if (header->cupsColorSpace == CUPS_CSPACE_KCMY) + { + NumPlanes = 4; + printf("\033*r-4U"); /* Set KCMY graphics */ + } + else if (header->cupsColorSpace == CUPS_CSPACE_CMY) + { + NumPlanes = 3; + printf("\033*r-3U"); /* Set CMY graphics */ + } + else + NumPlanes = 1; /* Black&white graphics */ + + printf("\033&a0H\033&a330V"); /* 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 */ + + if (!(header->Duplex && (Page & 1))) + printf("\014"); /* Eject current 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) + { + default : + /* + * 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 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..08513d7b68 --- /dev/null +++ b/filter/textcommon.c @@ -0,0 +1,1135 @@ +/* + * "$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? */ +int NumKeywords = 0; /* Number of known keywords */ +char **Keywords = NULL; /* List of known keywords */ + + +/* + * Local globals... + */ + +static char *code_keywords[] = /* List of known C/C++ 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" + }, + *sh_keywords[] = /* List of known Boure/Korn/zsh/bash keywords... */ + { + "alias", + "bg", + "break", + "case", + "cd", + "command", + "continue", + "do", + "done", + "echo", + "elif", + "else", + "esac", + "eval", + "exec", + "exit", + "export", + "fc", + "fg", + "fi", + "for", + "function", + "getopts", + "if", + "in", + "jobs", + "kill", + "let", + "limit", + "newgrp", + "print", + "pwd", + "read", + "readonly", + "return", + "select", + "set", + "shift", + "test", + "then", + "time", + "times", + "trap", + "typeset", + "ulimit", + "umask", + "unalias", + "unlimit", + "unset", + "until", + "wait", + "whence" + "while", + }, + *csh_keywords[] = /* List of known csh/tcsh keywords... */ + { + "alias", + "aliases", + "bg", + "bindkey", + "break", + "breaksw", + "builtins", + "case", + "cd", + "chdir", + "complete", + "continue", + "default", + "dirs", + "echo", + "echotc", + "else", + "end", + "endif", + "eval", + "exec", + "exit", + "fg", + "foreach", + "glob", + "goto", + "history", + "if", + "jobs", + "kill", + "limit", + "login", + "logout", + "ls", + "nice", + "nohup", + "notify", + "onintr", + "popd", + "pushd", + "pwd", + "rehash", + "repeat", + "set", + "setenv", + "settc", + "shift", + "source", + "stop", + "suspend", + "switch", + "telltc", + "then", + "time", + "umask", + "unalias", + "unbindkey", + "unhash", + "unlimit", + "unset", + "unsetenv", + "wait", + "where", + "which", + "while" + }, + *perl_keywords[] = /* List of known perl keywords... */ + { + "abs", + "accept", + "alarm", + "and", + "atan2", + "bind", + "binmode", + "bless", + "caller", + "chdir", + "chmod", + "chomp", + "chop", + "chown", + "chr", + "chroot", + "closdir", + "close", + "connect", + "continue", + "cos", + "crypt", + "dbmclose", + "dbmopen", + "defined", + "delete", + "die", + "do", + "dump", + "each", + "else", + "elsif", + "endgrent", + "endhostent", + "endnetent", + "endprotoent", + "endpwent", + "endservent", + "eof", + "eval", + "exec", + "exists", + "exit", + "exp", + "fcntl", + "fileno", + "flock", + "for", + "foreach", + "fork", + "format", + "formline", + "getc", + "getgrent", + "getgrgid", + "getgrnam", + "gethostbyaddr", + "gethostbyname", + "gethostent", + "getlogin", + "getnetbyaddr", + "getnetbyname", + "getnetent", + "getpeername", + "getpgrp", + "getppid", + "getpriority", + "getprotobyname", + "getprotobynumber", + "getprotoent", + "getpwent", + "getpwnam", + "getpwuid", + "getservbyname", + "getservbyport", + "getservent", + "getsockname", + "getsockopt", + "glob", + "gmtime", + "goto", + "grep", + "hex", + "if", + "import", + "index", + "int", + "ioctl", + "join", + "keys", + "kill", + "last", + "lc", + "lcfirst", + "length", + "link", + "listen", + "local", + "localtime", + "log", + "lstat", + "map", + "mkdir", + "msgctl", + "msgget", + "msgrcv", + "msgsend", + "my", + "next", + "no", + "not", + "oct", + "open", + "opendir", + "or", + "ord", + "pack", + "package", + "pipe", + "pop", + "pos", + "print", + "printf", + "push", + "quotemeta", + "rand", + "read", + "readdir", + "readlink", + "recv", + "redo", + "ref", + "rename", + "require", + "reset", + "return", + "reverse", + "rewinddir", + "rindex", + "rmdir", + "scalar", + "seek", + "seekdir", + "select", + "semctl", + "semget", + "semop", + "send", + "setgrent", + "sethostent", + "setnetent", + "setpgrp", + "setpriority", + "setprotoent", + "setpwent", + "setservent", + "setsockopt", + "shift", + "shmctl", + "shmget", + "shmread", + "shmwrite", + "shutdown", + "sin", + "sleep", + "socket", + "socketpair", + "sort", + "splice", + "split", + "sprintf", + "sqrt", + "srand", + "stat", + "study", + "sub", + "substr", + "symlink", + "syscall", + "sysread", + "sysseek", + "system", + "syswrite", + "tell", + "telldir", + "tie", + "tied", + "time", + "times" + "times", + "truncate", + "uc", + "ucfirst", + "umask", + "undef", + "unless", + "unlink", + "unpack", + "unshift", + "untie", + "until", + "use", + "utime", + "values", + "vec", + "wait", + "waitpid", + "wantarray", + "warn", + "while", + "write" + }; + + +/* + * 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) + { + PageLeft = 72.0f; + PageRight = PageWidth - 36.0f; + PageBottom = PageBottom > 36.0f ? PageBottom : 36.0f; + PageTop = PageLength - 36.0f; + CharsPerInch = 12; + LinesPerInch = 8; + + if ((val = getenv("CONTENT_TYPE")) == NULL) + { + PrettyPrint = PRETTY_CODE; + NumKeywords = sizeof(code_keywords) / sizeof(code_keywords[0]); + Keywords = code_keywords; + } + else if (strcasecmp(val, "application/x-cshell") == 0) + { + PrettyPrint = PRETTY_SHELL; + NumKeywords = sizeof(csh_keywords) / sizeof(csh_keywords[0]); + Keywords = csh_keywords; + } + else if (strcasecmp(val, "application/x-perl") == 0) + { + PrettyPrint = PRETTY_PERL; + NumKeywords = sizeof(perl_keywords) / sizeof(perl_keywords[0]); + Keywords = perl_keywords; + } + else if (strcasecmp(val, "application/x-shell") == 0) + { + PrettyPrint = PRETTY_SHELL; + NumKeywords = sizeof(sh_keywords) / sizeof(sh_keywords[0]); + Keywords = sh_keywords; + } + else + { + PrettyPrint = PRETTY_CODE; + NumKeywords = sizeof(code_keywords) / sizeof(code_keywords[0]); + Keywords = code_keywords; + } + } + + ppd = SetCommonOptions(num_options, options, 1); + + 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... + */ + + lastch = 0; + 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, NumKeywords, sizeof(char *), + 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, NumKeywords, sizeof(char *), + 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, NumKeywords, sizeof(char *), + 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, NumKeywords, sizeof(char *), + 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 && + PrettyPrint != PRETTY_SHELL) + { + /* + * Start a C-style comment... + */ + + ccomment = 1; + attr |= ATTR_ITALIC | ATTR_GREEN; + } + else if (ch == '/' && lastch == '/' && !cstring && + PrettyPrint == PRETTY_CODE) + { + /* + * Start a C++-style comment... + */ + + attr |= ATTR_ITALIC | ATTR_GREEN; + } + else if (ch == '#' && !cstring && PrettyPrint != PRETTY_CODE) + { + /* + * Start a shell-style comment... + */ + + attr |= ATTR_ITALIC | ATTR_GREEN; + } + else if (ch == '#' && column == 0 && !ccomment && !cstring && + PrettyPrint == PRETTY_CODE) + { + /* + * 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][column].attr |= ATTR_BOLD; + } + else if ((ch == '/' || ch == '*') && lastch == '/' && + column < ColumnWidth && PrettyPrint != PRETTY_SHELL) + { + /* + * Highlight first comment character... + */ + + Page[line][column - 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(); + + if (ppd != NULL) + ppdClose(ppd); + + 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..eb0897c4ab --- /dev/null +++ b/filter/textcommon.h @@ -0,0 +1,100 @@ +/* + * "$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 + +#define PRETTY_OFF 0 +#define PRETTY_CODE 1 +#define PRETTY_SHELL 2 +#define PRETTY_PERL 3 +#define PRETTY_HTML 4 + + +/* + * 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 int NumKeywords; /* Number of known keywords */ +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..0661c5fb12 --- /dev/null +++ b/filter/texttops.c @@ -0,0 +1,1274 @@ +/* + * "$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 */ + const char *datadir; /* CUPS_DATADIR environment variable */ + 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" + }; + + + /* + * Get the data directory... + */ + + if ((datadir = getenv("CUPS_DATADIR")) == NULL) + datadir = CUPS_DATADIR; + + /* + * 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("%%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... + */ + + snprintf(filename, sizeof(filename), "%s/data/psglyphs", datadir); + + if ((fp = fopen(filename, "r")) != NULL) + { + while (fscanf(fp, "%x%63s", &unicode, glyph) == 2) + Glyphs[unicode] = strdup(glyph); + + fclose(fp); + } + else + { + fprintf(stderr, "ERROR: Unable to open \"%s\" - %s\n", filename, + strerror(errno)); + exit(1); + } + + /* + * Get the output character set... + */ + + charset = getenv("CHARSET"); + if (charset != NULL && strcmp(charset, "us-ascii") != 0) + { + snprintf(filename, sizeof(filename), "%s/charsets/%s", datadir, 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 = 0; + + /* + * Read the font description(s)... + */ + + 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: + * + * first last direction width normal [bold italic bold-italic] + */ + + lineptr = line; + + start = strtol(lineptr, &lineptr, 16); + end = strtol(lineptr, &lineptr, 16); + + while (isspace(*lineptr)) + lineptr ++; + + if (!*lineptr) + break; /* Must be a font mapping */ + + 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; + + NumFonts ++; + } + + /* + * Read encoding lines... + */ + + do + { + /* + * 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[Chars[ch]] = unicode; + } + while (fgets(line, sizeof(line), fp) != NULL); + + 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 = PrettyPrint ? 2 : 1; 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("%%DocumentSuppliedResources: procset texttops 1.1 0"); + + for (i = 0; i < num_fonts; i ++) + { + if (ppd != NULL) + { + fprintf(stderr, "DEBUG: ppd->num_fonts = %d\n", ppd->num_fonts); + + for (j = 0; j < ppd->num_fonts; j ++) + { + fprintf(stderr, "DEBUG: ppd->fonts[%d] = %s\n", j, ppd->fonts[j]); + + if (strcmp(fonts[i], ppd->fonts[j]) == 0) + break; + } + } + + if (ppd == NULL || j >= ppd->num_fonts) + { + /* + * Need to embed this font... + */ + + printf("%%%%+ font %s\n", fonts[i]); + } + } + + puts("%%EndComments"); + + puts("%%BeginProlog"); + + /* + * Download any missing fonts... + */ + + for (i = 0; i < num_fonts; i ++) + { + if (ppd != NULL) + for (j = 0; j < ppd->num_fonts; j ++) + if (strcmp(fonts[i], ppd->fonts[j]) == 0) + break; + + if (ppd == NULL || j >= ppd->num_fonts) + { + /* + * Need to embed this font... + */ + + printf("%%%%BeginResource: font %s\n", fonts[i]); + + snprintf(filename, sizeof(filename), "%s/fonts/%s", datadir, fonts[i]); + if ((fp = fopen(filename, "rb")) != NULL) + { + while ((j = fread(line, 1, sizeof(line), fp)) > 0) + fwrite(line, 1, j, stdout); + + fclose(fp); + } + + puts("\n%%EndResource"); + } + } + + /* + * 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 = PrettyPrint ? 2 : 1; 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 i; /* Looping var */ + int col; /* Current column */ + int attr; /* Current attribute */ + int font, /* Font to use */ + lastfont, /* Last font */ + mono; /* Monospaced? */ + lchar_t *start; /* First character in sequence */ + + + for (col = 0, start = line; col < SizeColumns;) + { + while (col < SizeColumns && (line->ch == ' ' || line->ch == 0)) + { + col ++; + line ++; + } + + if (col >= SizeColumns) + break; + + if (NumFonts == 1) + { + /* + * All characters in a single font - assume monospaced... + */ + + 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); + } + else + { + /* + * Multiple fonts; break up based on the font... + */ + + attr = line->attr; + start = line; + lastfont = Chars[line->ch] / 256; + mono = strncmp(Fonts[lastfont][0], "Courier", 7) == 0; + col ++; + line ++; + + if (mono) + { + while (col < SizeColumns && line->ch != 0 && attr == line->attr) + { + font = Chars[line->ch] / 256; + if (strncmp(Fonts[font][0], "Courier", 7) != 0 || + font != lastfont) + break; + + col ++; + line ++; + } + } + + if (Directions[lastfont] > 0) + write_string(col - (line - start), row, line - start, start); + else + { + /* + * Do right-to-left text... + */ + + while (col < SizeColumns && line->ch != 0 && attr == line->attr) + { + if (Directions[Chars[line->ch] / 256] > 0 && + !ispunct(line->ch) && !isspace(line->ch)) + break; + + col ++; + line ++; + } + + for (i = 1; start < line; i ++, start ++) + if (!isspace(start->ch)) + write_string(col - i, row, 1, 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 */ + 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 (NumFonts > 1) + { + /* + * 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 (NumFonts > 1) + { + /* + * 8/8 encoding... + */ + + putchar('<'); + + utf8 = (unsigned char *)s; + + while (*utf8) + { + if (*utf8 < 0xc0 || !UTF8) + 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 0000000000..4d3a8b2ba7 Binary files /dev/null and b/fonts/AvantGarde-Book differ diff --git a/fonts/AvantGarde-BookOblique b/fonts/AvantGarde-BookOblique new file mode 100644 index 0000000000..c25c6ee4cc Binary files /dev/null and b/fonts/AvantGarde-BookOblique differ diff --git a/fonts/AvantGarde-Demi b/fonts/AvantGarde-Demi new file mode 100644 index 0000000000..67046dbe68 Binary files /dev/null and b/fonts/AvantGarde-Demi differ diff --git a/fonts/AvantGarde-DemiOblique b/fonts/AvantGarde-DemiOblique new file mode 100644 index 0000000000..e0f6559e93 Binary files /dev/null and b/fonts/AvantGarde-DemiOblique differ diff --git a/fonts/Bookman-Demi b/fonts/Bookman-Demi new file mode 100644 index 0000000000..4e26c1cf52 Binary files /dev/null and b/fonts/Bookman-Demi differ diff --git a/fonts/Bookman-DemiItalic b/fonts/Bookman-DemiItalic new file mode 100644 index 0000000000..6520e718dc Binary files /dev/null and b/fonts/Bookman-DemiItalic differ diff --git a/fonts/Bookman-Light b/fonts/Bookman-Light new file mode 100644 index 0000000000..7cbac2c456 Binary files /dev/null and b/fonts/Bookman-Light differ diff --git a/fonts/Bookman-LightItalic b/fonts/Bookman-LightItalic new file mode 100644 index 0000000000..3ef45dcbec Binary files /dev/null and b/fonts/Bookman-LightItalic differ diff --git a/fonts/Charter-Bold b/fonts/Charter-Bold new file mode 100644 index 0000000000..0d82077ec4 Binary files /dev/null and b/fonts/Charter-Bold differ diff --git a/fonts/Charter-BoldItalic b/fonts/Charter-BoldItalic new file mode 100644 index 0000000000..c7a5f8798b Binary files /dev/null and b/fonts/Charter-BoldItalic differ diff --git a/fonts/Charter-Italic b/fonts/Charter-Italic new file mode 100644 index 0000000000..6abe1cdfdb Binary files /dev/null and b/fonts/Charter-Italic differ diff --git a/fonts/Charter-Roman b/fonts/Charter-Roman new file mode 100644 index 0000000000..b25133d510 Binary files /dev/null and b/fonts/Charter-Roman differ diff --git a/fonts/Courier b/fonts/Courier new file mode 100644 index 0000000000..0cadce7d13 Binary files /dev/null and b/fonts/Courier differ diff --git a/fonts/Courier-Bold b/fonts/Courier-Bold new file mode 100644 index 0000000000..f1da6121bb Binary files /dev/null and b/fonts/Courier-Bold differ diff --git a/fonts/Courier-BoldOblique b/fonts/Courier-BoldOblique new file mode 100644 index 0000000000..8b7c24ff3a Binary files /dev/null and b/fonts/Courier-BoldOblique differ diff --git a/fonts/Courier-Oblique b/fonts/Courier-Oblique new file mode 100644 index 0000000000..107a513372 Binary files /dev/null and b/fonts/Courier-Oblique differ diff --git a/fonts/Helvetica b/fonts/Helvetica new file mode 100644 index 0000000000..ff605552c9 Binary files /dev/null and b/fonts/Helvetica differ diff --git a/fonts/Helvetica-Bold b/fonts/Helvetica-Bold new file mode 100644 index 0000000000..aec380a331 Binary files /dev/null and b/fonts/Helvetica-Bold differ diff --git a/fonts/Helvetica-BoldOblique b/fonts/Helvetica-BoldOblique new file mode 100644 index 0000000000..479904083a Binary files /dev/null and b/fonts/Helvetica-BoldOblique differ diff --git a/fonts/Helvetica-Narrow b/fonts/Helvetica-Narrow new file mode 100644 index 0000000000..f2387225df Binary files /dev/null and b/fonts/Helvetica-Narrow differ diff --git a/fonts/Helvetica-Narrow-Bold b/fonts/Helvetica-Narrow-Bold new file mode 100644 index 0000000000..7ee6a2c812 Binary files /dev/null and b/fonts/Helvetica-Narrow-Bold differ diff --git a/fonts/Helvetica-Narrow-BoldOblique b/fonts/Helvetica-Narrow-BoldOblique new file mode 100644 index 0000000000..d2e96f3b7e Binary files /dev/null and b/fonts/Helvetica-Narrow-BoldOblique differ diff --git a/fonts/Helvetica-Narrow-Oblique b/fonts/Helvetica-Narrow-Oblique new file mode 100644 index 0000000000..4ff13e5f64 Binary files /dev/null and b/fonts/Helvetica-Narrow-Oblique differ diff --git a/fonts/Helvetica-Oblique b/fonts/Helvetica-Oblique new file mode 100644 index 0000000000..876cda876d Binary files /dev/null and b/fonts/Helvetica-Oblique differ diff --git a/fonts/Makefile b/fonts/Makefile new file mode 100644 index 0000000000..57ee8daa6f --- /dev/null +++ b/fonts/Makefile @@ -0,0 +1,75 @@ +# +# "$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 Charter-Bold \ + Charter-BoldItalic Charter-Italic Charter-Roman 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 + $(CHMOD) ugo+rx $(DATADIR) + $(CHMOD) ugo+rx $(DATADIR)/fonts + $(INSTALL_DATA) $(FONTS) $(DATADIR)/fonts + + +# +# End of "$Id$". +# diff --git a/fonts/NewCenturySchlbk-Bold b/fonts/NewCenturySchlbk-Bold new file mode 100644 index 0000000000..321a282f43 Binary files /dev/null and b/fonts/NewCenturySchlbk-Bold differ diff --git a/fonts/NewCenturySchlbk-BoldItalic b/fonts/NewCenturySchlbk-BoldItalic new file mode 100644 index 0000000000..31e589003a Binary files /dev/null and b/fonts/NewCenturySchlbk-BoldItalic differ diff --git a/fonts/NewCenturySchlbk-Italic b/fonts/NewCenturySchlbk-Italic new file mode 100644 index 0000000000..2fbd616479 Binary files /dev/null and b/fonts/NewCenturySchlbk-Italic differ diff --git a/fonts/NewCenturySchlbk-Roman b/fonts/NewCenturySchlbk-Roman new file mode 100644 index 0000000000..6cbded3c76 Binary files /dev/null and b/fonts/NewCenturySchlbk-Roman differ diff --git a/fonts/Palatino-Bold b/fonts/Palatino-Bold new file mode 100644 index 0000000000..7f5df43f3d Binary files /dev/null and b/fonts/Palatino-Bold differ diff --git a/fonts/Palatino-BoldItalic b/fonts/Palatino-BoldItalic new file mode 100644 index 0000000000..1c812b8391 Binary files /dev/null and b/fonts/Palatino-BoldItalic differ diff --git a/fonts/Palatino-Italic b/fonts/Palatino-Italic new file mode 100644 index 0000000000..8d0f820de1 Binary files /dev/null and b/fonts/Palatino-Italic differ diff --git a/fonts/Palatino-Roman b/fonts/Palatino-Roman new file mode 100644 index 0000000000..4101b73358 Binary files /dev/null and b/fonts/Palatino-Roman differ diff --git a/fonts/Symbol b/fonts/Symbol new file mode 100644 index 0000000000..d0505e46cd Binary files /dev/null and b/fonts/Symbol differ diff --git a/fonts/Times-Bold b/fonts/Times-Bold new file mode 100644 index 0000000000..47f8fd57da Binary files /dev/null and b/fonts/Times-Bold differ diff --git a/fonts/Times-BoldItalic b/fonts/Times-BoldItalic new file mode 100644 index 0000000000..2d19d942ea Binary files /dev/null and b/fonts/Times-BoldItalic differ diff --git a/fonts/Times-Italic b/fonts/Times-Italic new file mode 100644 index 0000000000..aa9ff5f8ac Binary files /dev/null and b/fonts/Times-Italic differ diff --git a/fonts/Times-Roman b/fonts/Times-Roman new file mode 100644 index 0000000000..cbae7ed157 Binary files /dev/null and b/fonts/Times-Roman differ diff --git a/fonts/Utopia-Bold b/fonts/Utopia-Bold new file mode 100644 index 0000000000..06b91085a4 Binary files /dev/null and b/fonts/Utopia-Bold differ diff --git a/fonts/Utopia-BoldItalic b/fonts/Utopia-BoldItalic new file mode 100644 index 0000000000..c36689694d Binary files /dev/null and b/fonts/Utopia-BoldItalic differ diff --git a/fonts/Utopia-Italic b/fonts/Utopia-Italic new file mode 100644 index 0000000000..e33f16af90 Binary files /dev/null and b/fonts/Utopia-Italic differ diff --git a/fonts/Utopia-Regular b/fonts/Utopia-Regular new file mode 100644 index 0000000000..1772a3a0b7 Binary files /dev/null and b/fonts/Utopia-Regular differ diff --git a/fonts/ZapfChancery-MediumItalic b/fonts/ZapfChancery-MediumItalic new file mode 100644 index 0000000000..28443517d3 Binary files /dev/null and b/fonts/ZapfChancery-MediumItalic differ diff --git a/fonts/ZapfDingbats b/fonts/ZapfDingbats new file mode 100644 index 0000000000..4a3c386d29 Binary files /dev/null and b/fonts/ZapfDingbats differ diff --git a/locale/C/cups_C b/locale/C/cups_C new file mode 100644 index 0000000000..5b5a28de9c --- /dev/null +++ b/locale/C/cups_C @@ -0,0 +1,133 @@ +iso-8859-1 +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. +426 An upgrade to a secure connection is required. If you are seeing this message in a web browser then it does not support HTTP encryption upgrades. +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..676f16c141 --- /dev/null +++ b/locale/Makefile @@ -0,0 +1,80 @@ +# +# "$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) $(LOCALEDIR) + $(CHMOD) ugo+rx $(LOCALEDIR) + for dir in $(LOCALES) ; do \ + if test ! -d $(LOCALEDIR)/$$dir ; then \ + $(MKDIR) $(LOCALEDIR)/$$dir ; \ + $(CHMOD) ugo+rx $(LOCALEDIR)/$$dir ; \ + fi ; \ + $(INSTALL_DATA) $$dir/cups_$$dir $(LOCALEDIR)/$$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) + 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..f2f4b2c612 --- /dev/null +++ b/locale/de/cups_de @@ -0,0 +1,134 @@ +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. +426 An upgrade to a secure connection is required. If you are seeing this message in a web browser then it does not support HTTP encryption upgrades. +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..6bf035d0a6 --- /dev/null +++ b/locale/en/cups_en @@ -0,0 +1,133 @@ +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. +426 An upgrade to a secure connection is required. If you are seeing this message in a web browser then it does not support HTTP encryption upgrades. +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..51c9314b49 --- /dev/null +++ b/locale/es/cups_es @@ -0,0 +1,133 @@ +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. +426 An upgrade to a secure connection is required. If you are seeing this message in a web browser then it does not support HTTP encryption upgrades. +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..9461b5009b --- /dev/null +++ b/locale/fr/cups_fr @@ -0,0 +1,133 @@ +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. +426 An upgrade to a secure connection is required. If you are seeing this message in a web browser then it does not support HTTP encryption upgrades. +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..7b7fcb4bf1 --- /dev/null +++ b/locale/it/cups_it @@ -0,0 +1,133 @@ +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. +426 An upgrade to a secure connection is required. If you are seeing this message in a web browser then it does not support HTTP encryption upgrades. +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..e86ff9bdeb --- /dev/null +++ b/man/Makefile @@ -0,0 +1,104 @@ +# +# "$Id$" +# +# Man page makefile for the Common UNIX Printing System (CUPS). +# +# Copyright 1993-1999 by Easy Software Products. +# +# These coded instructions, statements, and computer programs are the +# property of Easy Software Products and are protected by Federal +# copyright law. Distribution and use rights are outlined in the file +# "LICENSE.txt" which should have been included with this file. If this +# file is missing or damaged please contact Easy Software Products +# at: +# +# Attn: CUPS Licensing Information +# Easy Software Products +# 44141 Airport View Drive, Suite 204 +# Hollywood, Maryland 20636-3111 USA +# +# Voice: (301) 373-9603 +# EMail: cups-info@cups.org +# WWW: http://www.cups.org +# + +include ../Makedefs + +# +# Man pages... +# + +MAN1 = backend.man filter.man lp.man lpoptions.man lpq.man lprm.man \ + lpr.man lpstat.man +MAN5 = classes.conf.man cupsd.conf.man mime.convs.man mime.types.man \ + printers.conf.man +MAN8 = accept.man cups-lpd.man cups-polld.man cupsd.man enable.man \ + lpadmin.man lpinfo.man lpmove.man lpc.man + +CAT1 = $(MAN1:.man=.$(CAT1EXT)) +CAT5 = $(MAN5:.man=.$(CAT1EXT)) +CAT8 = $(MAN8:.man=.$(CAT1EXT)) + + +# +# Make everything... +# + +all: $(CAT1) $(CAT5) $(CAT8) + + +# +# Clean all config and object files... +# + +clean: + $(RM) $(CAT1) $(CAT5) $(CAT8) + + +# +# Install files... +# + +install: + -$(MKDIR) $(MANDIR)/man1 + -$(CHMOD) ugo+rx $(MANDIR) + -$(CHMOD) ugo+rx $(MANDIR)/man1 + for file in $(MAN1); do \ + $(INSTALL_MAN) $$file $(MANDIR)/man1/`basename $$file man`1; \ + done + $(RM) $(MANDIR)/man1/cancel.1 + $(LN) lp.1 $(MANDIR)/man1/cancel.1 + -$(MKDIR) $(MANDIR)/man5 + -$(CHMOD) ugo+rx $(MANDIR)/man5 + for file in $(MAN5); do \ + $(INSTALL_MAN) $$file $(MANDIR)/man5/`basename $$file man`5; \ + done + -$(MKDIR) $(MANDIR)/man8 + -$(CHMOD) ugo+rx $(MANDIR)/man8 + for file in $(MAN8); do \ + $(INSTALL_MAN) $$file $(MANDIR)/man8/`basename $$file man`8; \ + done + $(RM) $(MANDIR)/man8/reject.8 + $(LN) accept.8 $(MANDIR)/man8/reject.8 + $(RM) $(MANDIR)/man8/disable.8 + $(LN) enable.8 $(MANDIR)/man8/disable.8 + -$(MKDIR) $(MANDIR)/cat1 + -$(CHMOD) ugo+rx $(MANDIR)/cat1 + $(INSTALL_MAN) $(CAT1) $(MANDIR)/cat1 + $(RM) $(MANDIR)/cat1/cancel.$(CAT1EXT) + $(LN) lp.$(CAT1EXT) $(MANDIR)/cat1/cancel.$(CAT1EXT) + -$(MKDIR) $(MANDIR)/cat5 + -$(CHMOD) ugo+rx $(MANDIR)/cat5 + $(INSTALL_MAN) $(CAT5) $(MANDIR)/cat5 + -$(MKDIR) $(MANDIR)/cat8 + -$(CHMOD) ugo+rx $(MANDIR)/cat8 + $(INSTALL_MAN) $(CAT8) $(MANDIR)/cat8 + $(RM) $(MANDIR)/cat8/reject.$(CAT1EXT) + $(LN) accept.$(CAT1EXT) $(MANDIR)/cat8/reject.$(CAT1EXT) + $(RM) $(MANDIR)/cat8/disable.$(CAT1EXT) + $(LN) enable.$(CAT1EXT) $(MANDIR)/cat8/disable.$(CAT1EXT) + + +# +# End of "$Id$". +# diff --git a/man/accept.man b/man/accept.man new file mode 100644 index 0000000000..ec1ec74e89 --- /dev/null +++ b/man/accept.man @@ -0,0 +1,58 @@ +.\" +.\" "$Id: accept.man 1231 2000-07-20 17:10:57Z 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, +http://localhost:631/documentation.html +.SH COPYRIGHT +Copyright 1993-2000 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: accept.man 1231 2000-07-20 17:10:57Z mike $". +.\" diff --git a/man/backend.man b/man/backend.man new file mode 100644 index 0000000000..561ba11411 --- /dev/null +++ b/man/backend.man @@ -0,0 +1,109 @@ +.\" +.\" "$Id: backend.man 1231 2000-07-20 17:10:57Z 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 June 2000" "Easy Software Products" +.SH NAME +backend \- cups 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 the standard input to a temporary file +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 +CUPS_DATADIR +.br +The directory where data files can be found. +.TP 5 +CUPS_SERVERROOT +.br +The root directory of the server. +.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 +SOFTWARE +.br +The name and version number of the server (typically CUPS/1.1). +.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 Interface Design Description, +CUPS Software Administrators Manual, +CUPS Software Programmers Manual, +http://localhost:631/documentation.html +.SH COPYRIGHT +Copyright 1993-2000 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: backend.man 1231 2000-07-20 17:10:57Z mike $". +.\" diff --git a/man/classes.conf.man b/man/classes.conf.man new file mode 100644 index 0000000000..85f3ea58b5 --- /dev/null +++ b/man/classes.conf.man @@ -0,0 +1,72 @@ +.\" +.\" "$Id: classes.conf.man 1231 2000-07-20 17:10:57Z 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 June 2000" "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 located in the \fI/etc/cups\fR directory and +is generated automatically by the \fIcupsd(8)\fR program when printer +classes are added or deleted. +.LP +Each line in the file can be a configuration directive, a blank line, +or a comment. Comment lines start with the # character. +.SH DIRECTIVES +.TP 5 + ... +.br +Defines a specific printer class. +.TP 5 +Accepting +.br +Specifies whether or not the printer class is accepting new jobs. +.TP 5 +Info +.br +Specifies human-readable text describing the printer class. +.TP 5 +Location +.br +Specifies human-readable text describing the location of the printer class. +.TP 5 +Printer +.br +Specifies a printer that is a member of the printer class. +.TP 5 +State +.br +Specifies the initial state of the printer class (Idle or Stopped) +.TP 5 +StateMessage +.br +Specifies the message associated with the state. +.SH SEE ALSO +cupsd(8), cupsd.conf(5), mime.convs(5), mime.types(5), printers.conf(5), +CUPS Software Administrators Manual, +http://localhost:631/documentation.html +.SH COPYRIGHT +Copyright 1993-2000 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: classes.conf.man 1231 2000-07-20 17:10:57Z mike $". +.\" diff --git a/man/cups-lpd.man b/man/cups-lpd.man new file mode 100644 index 0000000000..e02fe77c05 --- /dev/null +++ b/man/cups-lpd.man @@ -0,0 +1,58 @@ +.\" +.\" "$Id: cups-lpd.man 1231 2000-07-20 17:10:57Z mike $" +.\" +.\" cups-lpd 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 cups-lpd 8 "Common UNIX Printing System" "10 May 2000" "Easy Software Products" +.SH NAME +cups-lpd \- receive print jobs and report printer status to lpd clients +.SH SYNOPSIS +.B cups-lpd +.SH DESCRIPTION +\fBcups-lpd\fR is the CUPS Line Printer Daemon ("LPD") mini-server that +supports legacy client systems that use the LPD protocol. +\fBcups-lpd\fR does not act as a standalone network daemon but instead +operates using the Internet "super-server" \fBinetd(8)\fR. Add the +following line to the \fBinetd.conf\fR file to enable the +\fBcups-lpd\fR daemon: +.br +.nf + +printer stream tcp nowait lp /usr/lib/cups/daemon/cups-lpd cups-lpd +.fi +.SH COMPATIBILITY +\fBcups-lpd\fR does not enforce the restricted source port number specified +in RFC 1179, as using restricted ports does not prevent determined users +from submitting print jobs. While this behavior is different than standard +Berkeley LPD implementations, it should not affect normal client operations. +.LP +The output of the status requests follows RFC 2569, Mapping between +LPD and IPP Protocols. Since many LPD implementations stray from this +definition, remote status reporting to LPD clients may be unreliable. +.SH SEE ALSO +inetd(8), +CUPS Software Administrators Manual, +http://localhost:631/documentation.html +.SH COPYRIGHT +Copyright 1993-2000 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: cups-lpd.man 1231 2000-07-20 17:10:57Z mike $". +.\" diff --git a/man/cups-polld.man b/man/cups-polld.man new file mode 100644 index 0000000000..d89f6d4806 --- /dev/null +++ b/man/cups-polld.man @@ -0,0 +1,46 @@ +.\" +.\" "$Id: cups-polld.man 1231 2000-07-20 17:10:57Z mike $" +.\" +.\" cups-polld 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 cups-polld 8 "Common UNIX Printing System" "10 May 2000" "Easy Software Products" +.SH NAME +cups-polld \- cups printer polling daemon +.SH SYNOPSIS +.B cups-polld +.I address ipp-port interval browse-port +.SH DESCRIPTION +\fBcups-polld\fR polls remote servers for a list of available printers +and printer classes every \fIinterval\fR seconds. Printer and class +information is then broadcast to the localhost interface (127.0.0.1) +for reception by \fBcupsd(8)\fR. +.PP +This program is started automatically by \fBcupsd\fR for each +BrowsePoll directive found in the \fBcupsd.conf\fR file. +.SH SEE ALSO +cupsd.conf(5), +CUPS Software Administrators Manual, +http://localhost:631/documentation.html +.SH COPYRIGHT +Copyright 1993-2000 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: cups-polld.man 1231 2000-07-20 17:10:57Z mike $". +.\" diff --git a/man/cupsd.conf.man b/man/cupsd.conf.man new file mode 100644 index 0000000000..d10a67fca0 --- /dev/null +++ b/man/cupsd.conf.man @@ -0,0 +1,246 @@ +.\" +.\" "$Id: cupsd.conf.man 1231 2000-07-20 17:10:57Z 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 June 2000" "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. It +is normally located in the \fI/etc/cups\fR directory. +.LP +Each line in the file can be a configuration directive, a blank line, +or a comment. Comment lines start with the # character. The +configuration directives are intentionally similar to those used by the +popular Apache web server software and are described below. +.SH DIRECTIVES +The following directives are understood by \fIcupsd\fR. Consult the CUPS +Software Administrators Manual for a detailed description: +.TP 5 +AccessLog +.br +Defines the access log filename. +.TP 5 +Allow +.br +Allows access from the named hosts or addresses. +.TP 5 +AuthClass +.br +Specifies the authentication class (User, Group, System) +.TP 5 +AuthType +.br +Specifies the authentication type (None, Basic, Digest) +.TP 5 +BrowseAddress +.br +Specifies a broadcast address for outgoing printer information packets. +.TP 5 +BrowseAllow +.br +Allows incoming printer information packets from the named host or address. +.TP 5 +BrowseDeny +.br +Denies incoming printer information packets from the named host or address. +.TP 5 +BrowseInterval +.br +Specifies the maximum interval between printer information broadcasts. +.TP 5 +BrowseOrder +.br +Specifies the order of printer information access control (allow,deny or deny,allow) +.TP 5 +BrowsePoll +.br +Specifies a server to poll for printer information. +.TP 5 +BrowsePort +.br +Specifies the port to listen to for printer information packets. +.TP 5 +BrowseRelay +.br +Specifies that printer information packets should be relayed from one host or +network to another. +.TP 5 +BrowseShortNames +.br +Specifies whether remote printers will use short names ("printer") or not +("printer@server"). This option is ignored if more than one remote printer +exists with the same name. +.TP 5 +BrowseTimeout +.br +Specifies the maximum interval between printer information updates before +remote printers will be removed from the list of available printers. +.TP 5 +Browsing +.br +Specifies whether or not remote printer browsing should be enabled. +.TP 5 +DataDir +.br +Specified the directory where data files can be found. +.TP 5 +DefaultCharset +.br +Specifies the default character set to use for text. +.TP 5 +DefaultLanguage +.br +Specifies the default language to use for text and web content. +.TP 5 +Deny +.br +Denies access to the named host or address. +.TP 5 +DocumentRoot +.br +Specifies the root directory for the internal web server documents. +.TP 5 +ErrorLog +.br +Specifies the error log filename. +.TP 5 +Group +.br +Specifies the group name or ID that will be used when executing +external programs. +.TP 5 +HostNameLookups +.br +Specifies whether or not to do reverse lookups on client addresses. +.TP 5 +ImplicitClasses +.br +Specifies whether or not to create implicit classes from identical +remote printers. +.TP 5 +KeepAlive +.br +Specifies whether or not to support HTTP Keep-Alive. +.TP 5 +KeepAliveTimeout +.br +Specifies the connection timeout for HTTP Keep-Alive. +.TP 5 + ... +.br +Specifies access control for the named location. +.TP 5 +LogLevel +.br +Specifies the logging level (none, warn, error, info, or debug) +.TP 5 +MaxClients +.br +Specifies the maximum number of simultaneous clients to support. +.TP 5 +MaxLogSize +.br +Specifies the maximum size of the log files before they are +rotated (0 to disable rotation) +.TP 5 +MaxRequestSize +.br +Specifies the maximum request/file size in bytes (0 for no limit) +.TP 5 +Order +.br +Specifies the order of HTTP access control (allow,deny or deny,allow) +.TP 5 +PageLog +.br +Specifies the page log filename. +.TP 5 +Port +.br +Specifies a port number to listen to for HTTP requests. +.TP 5 +PreserveJobFiles +.br +Specifies whether or not to preserve job files after they are printed. +.TP 5 +PreserveJobHistory +.br +Specifies whether or not to preserve the job history after they are +printed. +.TP 5 +Printcap +.br +Specifies the filename for a printcap file that is updated automatically +with a list of available printers (needed for legacy applications) +.TP 5 +RIPCache +.br +Specifies the maximum amount of memory to use when converting images +and PostScript files to bitmaps for a printer. +.TP 5 +RequestRoot +.br +Specifies the directory to store print jobs and other HTTP request +data. +.TP 5 +ServerAdmin +.br +Specifies the email address of the server administrator. +.TP 5 +ServerBin +.br +Specifies the directory where backends, CGIs, daemons, and filters may +be found. +.TP 5 +ServerName +.br +Specifies the fully-qualified hostname of the server. +.TP 5 +ServerRoot +.br +Specifies the directory where the server configuration files can be found. +.TP 5 +SystemGroup +.br +Specifies the group to use for System class authentication. +.TP 5 +TempDir +.br +Specifies the directory where temporary files are stored. +.TP 5 +Timeout +.br +Specifies the HTTP request timeout in seconds. +.TP 5 +User +.br +Specifies the user name or ID that is used when running external programs. +.SH SEE ALSO +classes.conf(5), cupsd(8), mime.convs(5), mime.types(5), printers.conf(5), +CUPS Software Administrators Manual, +http://localhost:631/documentation.html +.SH COPYRIGHT +Copyright 1993-2000 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: cupsd.conf.man 1231 2000-07-20 17:10:57Z mike $". +.\" diff --git a/man/cupsd.man b/man/cupsd.man new file mode 100644 index 0000000000..729911b297 --- /dev/null +++ b/man/cupsd.man @@ -0,0 +1,56 @@ +.\" +.\" "$Id: cupsd.man 1417 2000-10-19 13:16:37Z 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" "19 October 2000" "Easy Software Products" +.SH NAME +cupsd \- common unix printing system daemon +.SH SYNOPSIS +.B cupsd +[ \-c +.I config-file +] [ \-f ] +.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.1. If no options are specified on the command-line then the +default configuration file (usually \fI/etc/cups/cupsd.conf\fR) will be +used. +.PP +The \fI-f\fR option forces \fIcupsd\fR to run in the foreground; the +default is to run in the background as a "daemon". +.SH COMPATIBILITY +\fIcupsd\fR implements all of the required IPP/1.1 attributes and +operations. It also implements 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 Implementation of IPP, +CUPS Interface Design Description, +CUPS Software Administrators Manual, +http://localhost:631/documentation.html +.SH COPYRIGHT +Copyright 1993-2000 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: cupsd.man 1417 2000-10-19 13:16:37Z mike $". +.\" diff --git a/man/enable.man b/man/enable.man new file mode 100644 index 0000000000..86ac155095 --- /dev/null +++ b/man/enable.man @@ -0,0 +1,65 @@ +.\" +.\" "$Id: enable.man 1231 2000-07-20 17:10:57Z 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, +http://localhost:631/documentation.html +.SH COPYRIGHT +Copyright 1993-2000 by Easy Software Products, All Rights Reserved. + +.\" +.\" End of "$Id: enable.man 1231 2000-07-20 17:10:57Z mike $". +.\" diff --git a/man/filter.man b/man/filter.man new file mode 100644 index 0000000000..9942e1dc17 --- /dev/null +++ b/man/filter.man @@ -0,0 +1,116 @@ +.\" +.\" "$Id: filter.man 1231 2000-07-20 17:10:57Z 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 June 2000" "Easy Software Products" +.SH NAME +filter \- cups 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 the standard input to a temporary +file as required by the file format. All output must be sent to the +standard output. +.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 +CUPS_DATADIR +.br +The directory where data files can be found. +.TP 5 +CUPS_SERVERROOT +.br +The root directory of the server. +.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 +SOFTWARE +.br +The name and version number of the server (typically CUPS/1.1). +.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 Interface Design Description, +CUPS Software Administrators Manual, +CUPS Software Programmers Manual, +http://localhost:631/documentation.html +.SH COPYRIGHT +Copyright 1993-2000 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: filter.man 1231 2000-07-20 17:10:57Z mike $". +.\" diff --git a/man/lp.man b/man/lp.man new file mode 100644 index 0000000000..26f6bcee72 --- /dev/null +++ b/man/lp.man @@ -0,0 +1,135 @@ +.\" +.\" "$Id: lp.man 1444 2000-11-11 19:56:24Z 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" "11 November 2000" "Easy Software Products" +.SH NAME +lp \- print files +.br +cancel \- cancel jobs +.SH SYNOPSIS +.B lp +[ \-c ] [ \-d +.I destination +] [ \-h +.I server +] [ \-i +.I job-id +] [ \-m ] [ \-n +.I num-copies +[ \-o +.I option +] [ \-p/q +.I priority +] [ \-s ] [ \-t +.I title +] [ \-H +.I handling +] [ \-P +.I page-list +] [ +.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 +\-i \fIjob-id\fR +.br +Specifies an existing job to modify. +.TP 5 +\-m +.br +Send email when the job is completed (not supported CUPS 1.1.) +.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. +.TP 5 +\-H \fIhandling\fR +.br +Specifies when the job should be printed. A value of +\fIimmediate\fR will print the file immediately, a value of +\fIhold\fR will hold the job indefinitely, and a time value +(HH:MM) will hold the job until the specified time. Use a value +of \fIresume\fR with the \fI-i\fR option to resume a held job. +.TP 5 +\-P \fIpage-list\fR +.br +Specifies which pages to print in the document. The list can contain a +list of numbers and ranges (#-#) separated by commas (e.g. 1,3-5,16). +.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.1. +.SH SEE ALSO +lpstat(1), +CUPS Software Users Manual, +http://localhost:631/documentation.html +.SH COPYRIGHT +Copyright 1993-2000 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: lp.man 1444 2000-11-11 19:56:24Z mike $". +.\" diff --git a/man/lpadmin.man b/man/lpadmin.man new file mode 100644 index 0000000000..e40614961e --- /dev/null +++ b/man/lpadmin.man @@ -0,0 +1,125 @@ +.\" +.\" "$Id: lpadmin.man 1231 2000-07-20 17:10:57Z 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, +http://localhost:631/documentation.html +.SH COPYRIGHT +Copyright 1993-2000 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: lpadmin.man 1231 2000-07-20 17:10:57Z mike $". +.\" diff --git a/man/lpc.man b/man/lpc.man new file mode 100644 index 0000000000..4ce0b44944 --- /dev/null +++ b/man/lpc.man @@ -0,0 +1,80 @@ +.\" +.\" "$Id: lpc.man 1231 2000-07-20 17:10:57Z 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, +http://localhost:631/documentation.html +.SH COPYRIGHT +Copyright 1993-2000 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: lpc.man 1231 2000-07-20 17:10:57Z mike $". +.\" diff --git a/man/lpinfo.man b/man/lpinfo.man new file mode 100644 index 0000000000..00b7886f99 --- /dev/null +++ b/man/lpinfo.man @@ -0,0 +1,56 @@ +.\" +.\" "$Id: lpinfo.man 1231 2000-07-20 17:10:57Z mike $" +.\" +.\" lpinfo 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 lpinfo 8 "Common UNIX Printing System" "10 May 2000" "Easy Software Products" +.SH NAME +lpinfo \- show available devices or drivers +.SH SYNOPSIS +.B lpinfo +[ -l ] [ -m ] [ -v ] +.SH DESCRIPTION +\fBlpinfo\fR lists the available devices or drivers known to the CUPS +server. One of the \fI-m\fR or \fI-v\fR options must be specified to +get any output: +.TP 5 +\-l +.br +Shows a "long" listing of devices or drivers. +.TP 5 +\-m +.br +Shows the available printer drivers on the system. +.TP 5 +\-v +.br +Shows the available printer devices on the system. +.SH COMPATIBILITY +The \fBlpinfo\fR command is unique to CUPS. +.SH SEE ALSO +lpadmin(8), +CUPS Software Administrators Manual, +http://localhost:631/documentation.html +.SH COPYRIGHT +Copyright 1993-2000 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: lpinfo.man 1231 2000-07-20 17:10:57Z mike $". +.\" diff --git a/man/lpmove.man b/man/lpmove.man new file mode 100644 index 0000000000..0882991e3d --- /dev/null +++ b/man/lpmove.man @@ -0,0 +1,50 @@ +.\" +.\" "$Id: lpmove.man 1231 2000-07-20 17:10:57Z mike $" +.\" +.\" lpmove 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 lpmove 8 "Common UNIX Printing System" "10 May 2000" "Easy Software Products" +.SH NAME +lpmove \- move a job to a new destination +.SH SYNOPSIS +.B lpmove +.I job destination +.SH DESCRIPTION +\fBlpmove\fR moves the specified \fIjob\fR to \fIdestination\fR. \fIjob\fR +can be the job ID number or the old destination and job ID: +.br +.nf + + lpmove 123 newprinter + lpmove oldprinter-123 newprinter +.fi +.SH COMPATIBILITY +The System V version of this command also allows moving of all jobs from one +queue to another. This functionality is currently not supported by CUPS. +.SH SEE ALSO +cancel(1), lp(1), +CUPS Software Users Manual, +http://localhost:631/documentation.html +.SH COPYRIGHT +Copyright 1993-2000 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: lpmove.man 1231 2000-07-20 17:10:57Z mike $". +.\" diff --git a/man/lpoptions.man b/man/lpoptions.man new file mode 100644 index 0000000000..1b8593a563 --- /dev/null +++ b/man/lpoptions.man @@ -0,0 +1,116 @@ +.\" +.\" "$Id: lpoptions.man 1337 2000-09-05 20:50:23Z mike $" +.\" +.\" lpoptions 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 lpoptions 1 "Common UNIX Printing System" "5 September 2000" "Easy Software Products" +.SH NAME +lpoptions \- display or set printer options and defaults +.SH SYNOPSIS +.B lpoptions +[ -h +.I server +] -d +.I dest[/instance] +[ -o +.I option=value +] ... [ -o +.I option=value +] +.br +.B lpoptions +[ -h +.I server +] [ -p +.I dest[/instance] +] -l +.br +.B lpoptions +[ -h +.I server +] [ -o +.I option=value +] ... [ -o +.I option=value +] -p +.I dest[/instance] +] -r +.I option +] +.br +.B lpoptions +[ -h +.I server +] -x +.I dest[/instance] +.SH DESCRIPTION +\fBlpoptions\fR displays or sets printer options and defaults. +\fBlpoptions\fR shows the default printer options when run with no +arguments. Other options include: +.TP 5 +\-d \fIdest[/instance]\fR +.br +Sets the default printer to \fIdest\fR. If \fIinstance\fR is supplied then +that particular instance is used. This option overrides the system default +printer for the current user. +.TP 5 +\-h \fIserver\fR +.br +Specifies the CUPS server to communicate with. +.TP 5 +\-l +.br +Lists the printer specific options and their current settings. +.TP 5 +\-o \fIoption=value\fR +.br +Specifies a new option for the named destination. +.TP 5 +\-p \fIdest[/instance]\fR +.br +Sets the destination and instance, if specified, for any options that follow. +If the named instance does not exist then it is created. +.TP 5 +\-r \fIoption\fR +.br +Removes the specified option for the named destination. +.TP 5 +\-x \fIdest[/instance]\fR +.br +Removes the options for the named destination and instance, if specified. +If the named instance does not exist then this does nothing. +.LP +If no options are specified using the \fI-o\fR option then the current +options for the named printer are reported on the standard output. +.LP +Options set with the \fBlpoptions\fR command are used by the \fBlp(1)\fR +and \fBlpr(1)\fR commands when submitting jobs. +.SH COMPATIBILITY +The \fBlpoptions\fR command is unique to CUPS. +.SH SEE ALSO +cancel(1), lp(1), +CUPS Software Users Manual, +http://localhost:631/documentation.html +.SH COPYRIGHT +Copyright 1993-2000 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: lpoptions.man 1337 2000-09-05 20:50:23Z mike $". +.\" diff --git a/man/lpq.man b/man/lpq.man new file mode 100644 index 0000000000..8342f9018d --- /dev/null +++ b/man/lpq.man @@ -0,0 +1,53 @@ +.\" +.\" "$Id: lpq.man 1231 2000-07-20 17:10:57Z 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, +http://localhost:631/documentation.html +.SH COPYRIGHT +Copyright 1993-2000 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: lpq.man 1231 2000-07-20 17:10:57Z mike $". +.\" diff --git a/man/lpr.man b/man/lpr.man new file mode 100644 index 0000000000..07767516b8 --- /dev/null +++ b/man/lpr.man @@ -0,0 +1,97 @@ +.\" +.\" "$Id: lpr.man 1231 2000-07-20 17:10:57Z 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, +http://localhost:631/documentation.html +.SH COPYRIGHT +Copyright 1993-2000 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: lpr.man 1231 2000-07-20 17:10:57Z mike $". +.\" diff --git a/man/lprm.man b/man/lprm.man new file mode 100644 index 0000000000..e5f6a54c3e --- /dev/null +++ b/man/lprm.man @@ -0,0 +1,52 @@ +.\" +.\" "$Id: lprm.man 1231 2000-07-20 17:10:57Z 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, +http://localhost:631/documentation.html +.SH COPYRIGHT +Copyright 1993-2000 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: lprm.man 1231 2000-07-20 17:10:57Z mike $". +.\" diff --git a/man/lpstat.man b/man/lpstat.man new file mode 100644 index 0000000000..5028aff180 --- /dev/null +++ b/man/lpstat.man @@ -0,0 +1,126 @@ +.\" +.\" "$Id: lpstat.man 1231 2000-07-20 17:10:57Z 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" "1 May 2000" "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 +] [ -l ] [ -o [ +.I destination(s) +] ] [ -p [ +.I printer(s) +] ] [ -r ] [ -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 +\-l +.br +Shows a long listing of printers, classes, or jobs. +.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 +\-R +.br +Shows the ranking of print jobs. +.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. +.LP +The Solaris "-f", "-P", and "-S" options are silently ignored. +.SH SEE ALSO +cancel(1), lp(1), +CUPS Software Users Manual, +http://localhost:631/documentation.html +.SH COPYRIGHT +Copyright 1993-2000 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: lpstat.man 1231 2000-07-20 17:10:57Z mike $". +.\" diff --git a/man/mime.convs.man b/man/mime.convs.man new file mode 100644 index 0000000000..34ad2fa67a --- /dev/null +++ b/man/mime.convs.man @@ -0,0 +1,54 @@ +.\" +.\" "$Id: mime.convs.man 1231 2000-07-20 17:10:57Z 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 June 2000" "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/etc/cups\fR) with +the extension ".convs". +.LP +Each line in the \fImime.types\fR file is a comment, blank, or filter +line. Comment lines start with the # character. Filter lines specify +the source and destination MIME types along with a relative cost +associated with the filter and the filter to run: +.br +.nf + +super/type super/type cost filter +application/postscript application/vnd.cups-raster 50 pstoraster +.fi +.SH SEE ALSO +classes.conf(5), cupsd(8), cupsd.conf(5), mime.types(5), printers.conf(5), +CUPS Software Administrators Manual, +http://localhost:631/documentation.html +.SH COPYRIGHT +Copyright 1993-2000 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: mime.convs.man 1231 2000-07-20 17:10:57Z mike $". +.\" diff --git a/man/mime.types.man b/man/mime.types.man new file mode 100644 index 0000000000..7d2c3e2882 --- /dev/null +++ b/man/mime.types.man @@ -0,0 +1,98 @@ +.\" +.\" "$Id: mime.types.man 1231 2000-07-20 17:10:57Z 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 June 2000" "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/etc/cups\fR with the extension +".types". +.LP +Each line in the \fImime.types\fR file is a comment, blank, or rule +line. Comment lines start with the # character. Rule lines start with +the MIME type name and are optionally followed by a series of file +recognition rules that are used to automatically identify print and web +files: +.br +.nf + + super/type rule [ ... ruleN] +.fi +The rules may be grouped using parenthesis, joined using "+" for a +logical AND and "," or whitespace for a logical OR, and negated using +"!". +.SH RULES +Rules take two forms - a filename extension by itself and functions with test +values inside parenthesis. The following functions are available: +.TP 5 +match("pattern") +.br +Pattern match on filename +.TP 5 +ascii(offset,length) +.br +True if bytes are valid printable ASCII (CR, NL, TAB, BS, 32-126) +.TP 5 +printable(offset,length) +.br +True if bytes are printable 8-bit chars (CR, NL, TAB, BS, 32-126, 128-254) +.TP 5 +string(offset,"string") +.br +True if bytes are identical to string +.TP 5 +char(offset,value) +.br +True if byte is identical +.TP 5 +short(offset,value) +.br +True if 16-bit integer is identical +.TP 5 +int(offset,value) +.br +True if 32-bit integer is identical +.TP 5 +locale("string") +.br +True if current locale matches string +.TP 5 +contains(offset,range,"string") +.br +True if the range contains the string +.SH STRING CONSTANTS +String constants can be specified inside quotes ("") for strings +containing whitespace and angle brackets (<>) for hexadecimal +strings. +.SH SEE ALSO +classes.conf(5), cupsd(8), cupsd.conf(5), mime.convs(5), printers.conf(5), +CUPS Software Administrators Manual, +http://localhost:631/documentation.html +.SH COPYRIGHT +Copyright 1993-2000 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: mime.types.man 1231 2000-07-20 17:10:57Z mike $". +.\" diff --git a/man/printers.conf.man b/man/printers.conf.man new file mode 100644 index 0000000000..d4ebf658ca --- /dev/null +++ b/man/printers.conf.man @@ -0,0 +1,73 @@ +.\" +.\" "$Id: printers.conf.man 1231 2000-07-20 17:10:57Z 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 June 2000" "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 located in the \fI/etc/cups\fR directory and +is generated automatically by the \fIcupsd(8)\fR program when printers +are added or deleted. +.LP +Each line in the file can be a configuration directive, a blank line, +or a comment. Comment lines start with the # character. +.SH DIRECTIVES +.TP 5 +Accepting +.br +Specifies whether or not the printer is accepting new jobs. +.TP 5 +Info +.br +Specifies human-readable text describing the printer. +.TP 5 +Location +.br +Specifies human-readable text describing the location of the printer. +.TP 5 +DeviceURI +.br +Specifies the device URI for a printer. +.TP 5 + ... +.br +Defines a specific printer. +.TP 5 +State +.br +Specifies the initial state of the printer (Idle or Stopped) +.TP 5 +StateMessage +.br +Specifies the message associated with the state. +.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, +http://localhost:631/documentation.html +.SH COPYRIGHT +Copyright 1993-2000 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: printers.conf.man 1231 2000-07-20 17:10:57Z mike $". +.\" diff --git a/pdftops/Array.cxx b/pdftops/Array.cxx new file mode 100644 index 0000000000..9681b6854c --- /dev/null +++ b/pdftops/Array.cxx @@ -0,0 +1,51 @@ +//======================================================================== +// +// Array.cc +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include +#include "gmem.h" +#include "Object.h" +#include "Array.h" + +//------------------------------------------------------------------------ +// Array +//------------------------------------------------------------------------ + +Array::Array() { + elems = NULL; + size = length = 0; + ref = 1; +} + +Array::~Array() { + int i; + + for (i = 0; i < length; ++i) + elems[i].free(); + gfree(elems); +} + +void Array::add(Object *elem) { + if (length + 1 > size) { + size += 8; + elems = (Object *)grealloc(elems, size * sizeof(Object)); + } + elems[length] = *elem; + ++length; +} + +Object *Array::get(int i, Object *obj) { + return elems[i].fetch(obj); +} + +Object *Array::getNF(int i, Object *obj) { + return elems[i].copy(obj); +} diff --git a/pdftops/Array.h b/pdftops/Array.h new file mode 100644 index 0000000000..ecf2eea6fd --- /dev/null +++ b/pdftops/Array.h @@ -0,0 +1,53 @@ +//======================================================================== +// +// Array.h +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#ifndef ARRAY_H +#define ARRAY_H + +#ifdef __GNUC__ +#pragma interface +#endif + +#include "Object.h" + +//------------------------------------------------------------------------ +// Array +//------------------------------------------------------------------------ + +class Array { +public: + + // Constructor. + Array(); + + // Destructor. + ~Array(); + + // Reference counting. + int incRef() { return ++ref; } + int decRef() { return --ref; } + + // Get number of elements. + int getLength() { return length; } + + // Add an element. + void add(Object *elem); + + // Accessors. + Object *get(int i, Object *obj); + Object *getNF(int i, Object *obj); + +private: + + Object *elems; // array of elements + int size; // size of array + int length; // number of elements in array + int ref; // reference count +}; + +#endif diff --git a/pdftops/COPYING b/pdftops/COPYING new file mode 100644 index 0000000000..a43ea2126f --- /dev/null +++ b/pdftops/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, 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 + + 0. 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. + + 1. 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. + + 2. 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: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) 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. + + c) 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. + + 3. 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: + + a) 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, + + b) 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, + + c) 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. + + 4. 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. + + 5. 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. + + 6. 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. + + 7. 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. + + 8. 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. + + 9. 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. + + 10. 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 + + 11. 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. + + 12. 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 + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/pdftops/Catalog.cxx b/pdftops/Catalog.cxx new file mode 100644 index 0000000000..815cca3ae0 --- /dev/null +++ b/pdftops/Catalog.cxx @@ -0,0 +1,301 @@ +//======================================================================== +// +// Catalog.cc +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include +#include "gmem.h" +#include "Object.h" +#include "Array.h" +#include "Dict.h" +#include "Page.h" +#include "Error.h" +#include "Link.h" +#include "Catalog.h" + +//------------------------------------------------------------------------ +// Catalog +//------------------------------------------------------------------------ + +Catalog::Catalog(Object *catDict) { + Object pagesDict; + Object obj, obj2; + int numPages0; + int i; + + ok = gTrue; + pages = NULL; + pageRefs = NULL; + numPages = pagesSize = 0; + + if (!catDict->isDict()) { + error(-1, "Catalog object is wrong type (%s)", catDict->getTypeName()); + goto err1; + } + + // read page tree + catDict->dictLookup("Pages", &pagesDict); + // This should really be isDict("Pages"), but I've seen at least one + // PDF file where the /Type entry is missing. + if (!pagesDict.isDict()) { + error(-1, "Top-level pages object is wrong type (%s)", + pagesDict.getTypeName()); + goto err2; + } + pagesDict.dictLookup("Count", &obj); + if (!obj.isInt()) { + error(-1, "Page count in top-level pages object is wrong type (%s)", + obj.getTypeName()); + goto err3; + } + pagesSize = numPages0 = obj.getInt(); + obj.free(); + pages = (Page **)gmalloc(pagesSize * sizeof(Page *)); + pageRefs = (Ref *)gmalloc(pagesSize * sizeof(Ref)); + for (i = 0; i < pagesSize; ++i) { + pages[i] = NULL; + pageRefs[i].num = -1; + pageRefs[i].gen = -1; + } + numPages = readPageTree(pagesDict.getDict(), NULL, 0); + if (numPages != numPages0) { + error(-1, "Page count in top-level pages object is incorrect"); + } + pagesDict.free(); + + // read named destination dictionary + catDict->dictLookup("Dests", &dests); + + // read root of named destination tree + if (catDict->dictLookup("Names", &obj)->isDict()) + obj.dictLookup("Dests", &nameTree); + else + nameTree.initNull(); + obj.free(); + + // read base URI + baseURI = NULL; + if (catDict->dictLookup("URI", &obj)->isDict()) { + if (obj.dictLookup("Base", &obj2)->isString()) { + baseURI = obj2.getString()->copy(); + } + obj2.free(); + } + obj.free(); + + return; + + err3: + obj.free(); + err2: + pagesDict.free(); + err1: + dests.initNull(); + nameTree.initNull(); + ok = gFalse; +} + +Catalog::~Catalog() { + int i; + + if (pages) { + for (i = 0; i < pagesSize; ++i) { + if (pages[i]) { + delete pages[i]; + } + } + gfree(pages); + gfree(pageRefs); + } + dests.free(); + nameTree.free(); + if (baseURI) { + delete baseURI; + } +} + +int Catalog::readPageTree(Dict *pagesDict, PageAttrs *attrs, int start) { + Object kids; + Object kid; + Object kidRef; + PageAttrs *attrs1, *attrs2; + Page *page; + int i, j; + + attrs1 = new PageAttrs(attrs, pagesDict); + pagesDict->lookup("Kids", &kids); + if (!kids.isArray()) { + error(-1, "Kids object (page %d) is wrong type (%s)", + start+1, kids.getTypeName()); + goto err1; + } + for (i = 0; i < kids.arrayGetLength(); ++i) { + kids.arrayGet(i, &kid); + if (kid.isDict("Page")) { + attrs2 = new PageAttrs(attrs1, kid.getDict()); + page = new Page(start+1, kid.getDict(), attrs2); + if (!page->isOk()) { + ++start; + goto err3; + } + if (start >= pagesSize) { + pagesSize += 32; + pages = (Page **)grealloc(pages, pagesSize * sizeof(Page *)); + pageRefs = (Ref *)grealloc(pageRefs, pagesSize * sizeof(Ref)); + for (j = pagesSize - 32; j < pagesSize; ++j) { + pages[j] = NULL; + pageRefs[j].num = -1; + pageRefs[j].gen = -1; + } + } + pages[start] = page; + kids.arrayGetNF(i, &kidRef); + if (kidRef.isRef()) { + pageRefs[start].num = kidRef.getRefNum(); + pageRefs[start].gen = kidRef.getRefGen(); + } + kidRef.free(); + ++start; + // This should really be isDict("Pages"), but I've seen at least one + // PDF file where the /Type entry is missing. + } else if (kid.isDict()) { + if ((start = readPageTree(kid.getDict(), attrs1, start)) < 0) + goto err2; + } else { + error(-1, "Kid object (page %d) is wrong type (%s)", + start+1, kid.getTypeName()); + goto err2; + } + kid.free(); + } + delete attrs1; + kids.free(); + return start; + + err3: + delete page; + err2: + kid.free(); + err1: + kids.free(); + delete attrs1; + ok = gFalse; + return -1; +} + +int Catalog::findPage(int num, int gen) { + int i; + + for (i = 0; i < numPages; ++i) { + if (pageRefs[i].num == num && pageRefs[i].gen == gen) + return i + 1; + } + return 0; +} + +LinkDest *Catalog::findDest(GString *name) { + LinkDest *dest; + Object obj1, obj2; + GBool found; + + // try named destination dictionary then name tree + found = gFalse; + if (dests.isDict()) { + if (!dests.dictLookup(name->getCString(), &obj1)->isNull()) + found = gTrue; + else + obj1.free(); + } + if (!found && nameTree.isDict()) { + if (!findDestInTree(&nameTree, name, &obj1)->isNull()) + found = gTrue; + else + obj1.free(); + } + if (!found) + return NULL; + + // construct LinkDest + dest = NULL; + if (obj1.isArray()) { + dest = new LinkDest(obj1.getArray(), gTrue); + } else if (obj1.isDict()) { + if (obj1.dictLookup("D", &obj2)->isArray()) + dest = new LinkDest(obj2.getArray(), gTrue); + else + error(-1, "Bad named destination value"); + obj2.free(); + } else { + error(-1, "Bad named destination value"); + } + obj1.free(); + + return dest; +} + +Object *Catalog::findDestInTree(Object *tree, GString *name, Object *obj) { + Object names, name1; + Object kids, kid, limits, low, high; + GBool done, found; + int cmp, i; + + // leaf node + if (tree->dictLookup("Names", &names)->isArray()) { + done = found = gFalse; + for (i = 0; !done && i < names.arrayGetLength(); i += 2) { + if (names.arrayGet(i, &name1)->isString()) { + cmp = name->cmp(name1.getString()); + if (cmp == 0) { + names.arrayGet(i+1, obj); + found = gTrue; + done = gTrue; + } else if (cmp < 0) { + done = gTrue; + } + name1.free(); + } + } + names.free(); + if (!found) + obj->initNull(); + return obj; + } + names.free(); + + // root or intermediate node + done = gFalse; + if (tree->dictLookup("Kids", &kids)->isArray()) { + for (i = 0; !done && i < kids.arrayGetLength(); ++i) { + if (kids.arrayGet(i, &kid)->isDict()) { + if (kid.dictLookup("Limits", &limits)->isArray()) { + if (limits.arrayGet(0, &low)->isString() && + name->cmp(low.getString()) >= 0) { + if (limits.arrayGet(1, &high)->isString() && + name->cmp(high.getString()) <= 0) { + findDestInTree(&kid, name, obj); + done = gTrue; + } + high.free(); + } + low.free(); + } + limits.free(); + } + kid.free(); + } + } + kids.free(); + + // name was outside of ranges of all kids + if (!done) + obj->initNull(); + + return obj; +} diff --git a/pdftops/Catalog.h b/pdftops/Catalog.h new file mode 100644 index 0000000000..b0f3143233 --- /dev/null +++ b/pdftops/Catalog.h @@ -0,0 +1,73 @@ +//======================================================================== +// +// Catalog.h +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#ifndef CATALOG_H +#define CATALOG_H + +#ifdef __GNUC__ +#pragma interface +#endif + +class Object; +class Page; +class PageAttrs; +struct Ref; +class LinkDest; + +//------------------------------------------------------------------------ +// Catalog +//------------------------------------------------------------------------ + +class Catalog { +public: + + // Constructor. + Catalog(Object *catDict); + + // Destructor. + ~Catalog(); + + // Is catalog valid? + GBool isOk() { return ok; } + + // Get number of pages. + int getNumPages() { return numPages; } + + // Get a page. + Page *getPage(int i) { return pages[i-1]; } + + // Get the reference for a page object. + Ref *getPageRef(int i) { return &pageRefs[i-1]; } + + // Return base URI, or NULL if none. + GString *getBaseURI() { return baseURI; } + + // Find a page, given its object ID. Returns page number, or 0 if + // not found. + int findPage(int num, int gen); + + // Find a named destination. Returns the link destination, or + // NULL if is not a destination. + LinkDest *findDest(GString *name); + +private: + + Page **pages; // array of pages + Ref *pageRefs; // object ID for each page + int numPages; // number of pages + int pagesSize; // size of pages array + Object dests; // named destination dictionary + Object nameTree; // name tree + GString *baseURI; // base URI for URI-type links + GBool ok; // true if catalog is valid + + int readPageTree(Dict *pages, PageAttrs *attrs, int start); + Object *findDestInTree(Object *tree, GString *name, Object *obj); +}; + +#endif diff --git a/pdftops/CompactFontInfo.h b/pdftops/CompactFontInfo.h new file mode 100644 index 0000000000..c642660297 --- /dev/null +++ b/pdftops/CompactFontInfo.h @@ -0,0 +1,464 @@ +//======================================================================== +// +// CompactFontInfo.h +// +// Copyright 1999 Derek B. Noonburg +// +//======================================================================== + +#ifndef COMPACTFONTINFO_H +#define COMPACTFONTINFO_H + +static char *type1CStdStrings[391] = { + ".notdef", + "space", + "exclam", + "quotedbl", + "numbersign", + "dollar", + "percent", + "ampersand", + "quoteright", + "parenleft", + "parenright", + "asterisk", + "plus", + "comma", + "hyphen", + "period", + "slash", + "zero", + "one", + "two", + "three", + "four", + "five", + "six", + "seven", + "eight", + "nine", + "colon", + "semicolon", + "less", + "equal", + "greater", + "question", + "at", + "A", + "B", + "C", + "D", + "E", + "F", + "G", + "H", + "I", + "J", + "K", + "L", + "M", + "N", + "O", + "P", + "Q", + "R", + "S", + "T", + "U", + "V", + "W", + "X", + "Y", + "Z", + "bracketleft", + "backslash", + "bracketright", + "asciicircum", + "underscore", + "quoteleft", + "a", + "b", + "c", + "d", + "e", + "f", + "g", + "h", + "i", + "j", + "k", + "l", + "m", + "n", + "o", + "p", + "q", + "r", + "s", + "t", + "u", + "v", + "w", + "x", + "y", + "z", + "braceleft", + "bar", + "braceright", + "asciitilde", + "exclamdown", + "cent", + "sterling", + "fraction", + "yen", + "florin", + "section", + "currency", + "quotesingle", + "quotedblleft", + "guillemotleft", + "guilsinglleft", + "guilsinglright", + "fi", + "fl", + "endash", + "dagger", + "daggerdbl", + "periodcentered", + "paragraph", + "bullet", + "quotesinglbase", + "quotedblbase", + "quotedblright", + "guillemotright", + "ellipsis", + "perthousand", + "questiondown", + "grave", + "acute", + "circumflex", + "tilde", + "macron", + "breve", + "dotaccent", + "dieresis", + "ring", + "cedilla", + "hungarumlaut", + "ogonek", + "caron", + "emdash", + "AE", + "ordfeminine", + "Lslash", + "Oslash", + "OE", + "ordmasculine", + "ae", + "dotlessi", + "lslash", + "oslash", + "oe", + "germandbls", + "onesuperior", + "logicalnot", + "mu", + "trademark", + "Eth", + "onehalf", + "plusminus", + "Thorn", + "onequarter", + "divide", + "brokenbar", + "degree", + "thorn", + "threequarters", + "twosuperior", + "registered", + "minus", + "eth", + "multiply", + "threesuperior", + "copyright", + "Aacute", + "Acircumflex", + "Adieresis", + "Agrave", + "Aring", + "Atilde", + "Ccedilla", + "Eacute", + "Ecircumflex", + "Edieresis", + "Egrave", + "Iacute", + "Icircumflex", + "Idieresis", + "Igrave", + "Ntilde", + "Oacute", + "Ocircumflex", + "Odieresis", + "Ograve", + "Otilde", + "Scaron", + "Uacute", + "Ucircumflex", + "Udieresis", + "Ugrave", + "Yacute", + "Ydieresis", + "Zcaron", + "aacute", + "acircumflex", + "adieresis", + "agrave", + "aring", + "atilde", + "ccedilla", + "eacute", + "ecircumflex", + "edieresis", + "egrave", + "iacute", + "icircumflex", + "idieresis", + "igrave", + "ntilde", + "oacute", + "ocircumflex", + "odieresis", + "ograve", + "otilde", + "scaron", + "uacute", + "ucircumflex", + "udieresis", + "ugrave", + "yacute", + "ydieresis", + "zcaron", + "exclamsmall", + "Hungarumlautsmall", + "dollaroldstyle", + "dollarsuperior", + "ampersandsmall", + "Acutesmall", + "parenleftsuperior", + "parenrightsuperior", + "twodotenleader", + "onedotenleader", + "zerooldstyle", + "oneoldstyle", + "twooldstyle", + "threeoldstyle", + "fouroldstyle", + "fiveoldstyle", + "sixoldstyle", + "sevenoldstyle", + "eightoldstyle", + "nineoldstyle", + "commasuperior", + "threequartersemdash", + "periodsuperior", + "questionsmall", + "asuperior", + "bsuperior", + "centsuperior", + "dsuperior", + "esuperior", + "isuperior", + "lsuperior", + "msuperior", + "nsuperior", + "osuperior", + "rsuperior", + "ssuperior", + "tsuperior", + "ff", + "ffi", + "ffl", + "parenleftinferior", + "parenrightinferior", + "Circumflexsmall", + "hyphensuperior", + "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", + "exclamdownsmall", + "centoldstyle", + "Lslashsmall", + "Scaronsmall", + "Zcaronsmall", + "Dieresissmall", + "Brevesmall", + "Caronsmall", + "Dotaccentsmall", + "Macronsmall", + "figuredash", + "hypheninferior", + "Ogoneksmall", + "Ringsmall", + "Cedillasmall", + "questiondownsmall", + "oneeighth", + "threeeighths", + "fiveeighths", + "seveneighths", + "onethird", + "twothirds", + "zerosuperior", + "foursuperior", + "fivesuperior", + "sixsuperior", + "sevensuperior", + "eightsuperior", + "ninesuperior", + "zeroinferior", + "oneinferior", + "twoinferior", + "threeinferior", + "fourinferior", + "fiveinferior", + "sixinferior", + "seveninferior", + "eightinferior", + "nineinferior", + "centinferior", + "dollarinferior", + "periodinferior", + "commainferior", + "Agravesmall", + "Aacutesmall", + "Acircumflexsmall", + "Atildesmall", + "Adieresissmall", + "Aringsmall", + "AEsmall", + "Ccedillasmall", + "Egravesmall", + "Eacutesmall", + "Ecircumflexsmall", + "Edieresissmall", + "Igravesmall", + "Iacutesmall", + "Icircumflexsmall", + "Idieresissmall", + "Ethsmall", + "Ntildesmall", + "Ogravesmall", + "Oacutesmall", + "Ocircumflexsmall", + "Otildesmall", + "Odieresissmall", + "OEsmall", + "Oslashsmall", + "Ugravesmall", + "Uacutesmall", + "Ucircumflexsmall", + "Udieresissmall", + "Yacutesmall", + "Thornsmall", + "Ydieresissmall", + "001.000", + "001.001", + "001.002", + "001.003", + "Black", + "Bold", + "Book", + "Light", + "Medium", + "Regular", + "Roman", + "Semibold" +}; + +static Gushort type1CISOAdobeCharset[229] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, + 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, + 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, + 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, + 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, + 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, + 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, + 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, + 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, + 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, + 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, + 220, 221, 222, 223, 224, 225, 226, 227, 228 +}; + +static Gushort type1CExpertCharset[166] = { + 0, 1, 229, 230, 231, 232, 233, 234, 235, 236, + 237, 238, 13, 14, 15, 99, 239, 240, 241, 242, + 243, 244, 245, 246, 247, 248, 27, 28, 249, 250, + 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 263, 264, 265, 266, 109, 110, 267, 268, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, + 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, + 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, + 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, + 158, 155, 163, 319, 320, 321, 322, 323, 324, 325, + 326, 150, 164, 169, 327, 328, 329, 330, 331, 332, + 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, + 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, + 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, + 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, + 373, 374, 375, 376, 377, 378 +}; + +static Gushort type1CExpertSubsetCharset[87] = { + 0, 1, 231, 232, 235, 236, 237, 238, 13, 14, + 15, 99, 239, 240, 241, 242, 243, 244, 245, 246, + 247, 248, 27, 28, 249, 250, 251, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + 266, 109, 110, 267, 268, 269, 270, 272, 300, 301, + 302, 305, 314, 315, 158, 155, 163, 320, 321, 322, + 323, 324, 325, 326, 150, 164, 169, 327, 328, 329, + 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, + 340, 341, 342, 343, 344, 345, 346 +}; + +#endif diff --git a/pdftops/Decrypt.cxx b/pdftops/Decrypt.cxx new file mode 100644 index 0000000000..ae9b73239d --- /dev/null +++ b/pdftops/Decrypt.cxx @@ -0,0 +1,304 @@ +//======================================================================== +// +// Decrypt.cc +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include "gmem.h" +#include "Decrypt.h" + +static void rc4InitKey(Guchar *key, int keyLen, Guchar *state); +static Guchar rc4DecryptByte(Guchar *state, Guchar *x, Guchar *y, Guchar c); +static void md5(Guchar *msg, int msgLen, Guchar *digest); + +static Guchar passwordPad[32] = { + 0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41, + 0x64, 0x00, 0x4e, 0x56, 0xff, 0xfa, 0x01, 0x08, + 0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, 0x3e, 0x80, + 0x2f, 0x0c, 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a +}; + +//------------------------------------------------------------------------ +// Decrypt +//------------------------------------------------------------------------ + +Decrypt::Decrypt(Guchar *fileKey, int objNum, int objGen) { + // construct object key + objKey[0] = fileKey[0]; + objKey[1] = fileKey[1]; + objKey[2] = fileKey[2]; + objKey[3] = fileKey[3]; + objKey[4] = fileKey[4]; + objKey[5] = objNum & 0xff; + objKey[6] = (objNum >> 8) & 0xff; + objKey[7] = (objNum >> 16) & 0xff; + objKey[8] = objGen & 0xff; + objKey[9] = (objGen >> 8) & 0xff; + md5(objKey, 10, objKey); + + // set up for decryption + x = y = 0; + rc4InitKey(objKey, 10, state); +} + +void Decrypt::reset() { + x = y = 0; + rc4InitKey(objKey, 10, state); +} + +Guchar Decrypt::decryptByte(Guchar c) { + return rc4DecryptByte(state, &x, &y, c); +} + +GBool Decrypt::makeFileKey(GString *ownerKey, GString *userKey, + int permissions, GString *fileID, + GString *userPassword, Guchar *fileKey) { + Guchar *buf; + Guchar userTest[32]; + Guchar fState[256]; + Guchar fx, fy; + int len, i; + GBool ok; + + // generate file key + buf = (Guchar *)gmalloc(68 + fileID->getLength()); + if (userPassword) { + len = userPassword->getLength(); + if (len < 32) { + memcpy(buf, userPassword->getCString(), len); + memcpy(buf + len, passwordPad, 32 - len); + } else { + memcpy(buf, userPassword->getCString(), 32); + } + } else { + memcpy(buf, passwordPad, 32); + } + memcpy(buf + 32, ownerKey->getCString(), 32); + buf[64] = permissions & 0xff; + buf[65] = (permissions >> 8) & 0xff; + buf[66] = (permissions >> 16) & 0xff; + buf[67] = (permissions >> 24) & 0xff; + memcpy(buf + 68, fileID->getCString(), fileID->getLength()); + md5(buf, 68 + fileID->getLength(), fileKey); + + // test user key + fx = fy = 0; + rc4InitKey(fileKey, 5, fState); + for (i = 0; i < 32; ++i) { + userTest[i] = rc4DecryptByte(fState, &fx, &fy, userKey->getChar(i)); + } + ok = memcmp(userTest, passwordPad, 32) == 0; + gfree(buf); + + return ok; +} + +//------------------------------------------------------------------------ +// RC4-compatible decryption +//------------------------------------------------------------------------ + +static void rc4InitKey(Guchar *key, int keyLen, Guchar *state) { + Guchar index1, index2; + Guchar t; + int i; + + for (i = 0; i < 256; ++i) + state[i] = i; + index1 = index2 = 0; + for (i = 0; i < 256; ++i) { + index2 = (key[index1] + state[i] + index2) % 256; + t = state[i]; + state[i] = state[index2]; + state[index2] = t; + index1 = (index1 + 1) % keyLen; + } +} + +static Guchar rc4DecryptByte(Guchar *state, Guchar *x, Guchar *y, Guchar c) { + Guchar x1, y1, tx, ty; + + x1 = *x = (*x + 1) % 256; + y1 = *y = (state[*x] + *y) % 256; + tx = state[x1]; + ty = state[y1]; + state[x1] = ty; + state[y1] = tx; + return c ^ state[(tx + ty) % 256]; +} + +//------------------------------------------------------------------------ +// MD5 message digest +//------------------------------------------------------------------------ + +static inline Gulong rotateLeft(Gulong x, int r) { + x &= 0xffffffff; + return ((x << r) | (x >> (32 - r))) & 0xffffffff; +} + +static inline Gulong md5Round1(Gulong a, Gulong b, Gulong c, Gulong d, + Gulong Xk, Gulong s, Gulong Ti) { + return b + rotateLeft((a + ((b & c) | (~b & d)) + Xk + Ti), s); +} + +static inline Gulong md5Round2(Gulong a, Gulong b, Gulong c, Gulong d, + Gulong Xk, Gulong s, Gulong Ti) { + return b + rotateLeft((a + ((b & d) | (c & ~d)) + Xk + Ti), s); +} + +static inline Gulong md5Round3(Gulong a, Gulong b, Gulong c, Gulong d, + Gulong Xk, Gulong s, Gulong Ti) { + return b + rotateLeft((a + (b ^ c ^ d) + Xk + Ti), s); +} + +static inline Gulong md5Round4(Gulong a, Gulong b, Gulong c, Gulong d, + Gulong Xk, Gulong s, Gulong Ti) { + return b + rotateLeft((a + (c ^ (b | ~d)) + Xk + Ti), s); +} + +static void md5(Guchar *msg, int msgLen, Guchar *digest) { + Gulong x[16]; + Gulong a, b, c, d, aa, bb, cc, dd; + int n64; + int i, j, k; + + // compute number of 64-byte blocks + // (length + pad byte (0x80) + 8 bytes for length) + n64 = (msgLen + 1 + 8 + 63) / 64; + + // initialize a, b, c, d + a = 0x67452301; + b = 0xefcdab89; + c = 0x98badcfe; + d = 0x10325476; + + // loop through blocks + k = 0; + for (i = 0; i < n64; ++i) { + + // grab a 64-byte block + for (j = 0; j < 16 && k < msgLen - 3; ++j, k += 4) + x[j] = (((((msg[k+3] << 8) + msg[k+2]) << 8) + msg[k+1]) << 8) + msg[k]; + if (i == n64 - 1) { + if (k == msgLen - 3) + x[j] = 0x80000000 + (((msg[k+2] << 8) + msg[k+1]) << 8) + msg[k]; + else if (k == msgLen - 2) + x[j] = 0x800000 + (msg[k+1] << 8) + msg[k]; + else if (k == msgLen - 1) + x[j] = 0x8000 + msg[k]; + else + x[j] = 0x80; + ++j; + while (j < 16) + x[j++] = 0; + x[14] = msgLen << 3; + } + + // save a, b, c, d + aa = a; + bb = b; + cc = c; + dd = d; + + // round 1 + a = md5Round1(a, b, c, d, x[0], 7, 0xd76aa478); + d = md5Round1(d, a, b, c, x[1], 12, 0xe8c7b756); + c = md5Round1(c, d, a, b, x[2], 17, 0x242070db); + b = md5Round1(b, c, d, a, x[3], 22, 0xc1bdceee); + a = md5Round1(a, b, c, d, x[4], 7, 0xf57c0faf); + d = md5Round1(d, a, b, c, x[5], 12, 0x4787c62a); + c = md5Round1(c, d, a, b, x[6], 17, 0xa8304613); + b = md5Round1(b, c, d, a, x[7], 22, 0xfd469501); + a = md5Round1(a, b, c, d, x[8], 7, 0x698098d8); + d = md5Round1(d, a, b, c, x[9], 12, 0x8b44f7af); + c = md5Round1(c, d, a, b, x[10], 17, 0xffff5bb1); + b = md5Round1(b, c, d, a, x[11], 22, 0x895cd7be); + a = md5Round1(a, b, c, d, x[12], 7, 0x6b901122); + d = md5Round1(d, a, b, c, x[13], 12, 0xfd987193); + c = md5Round1(c, d, a, b, x[14], 17, 0xa679438e); + b = md5Round1(b, c, d, a, x[15], 22, 0x49b40821); + + // round 2 + a = md5Round2(a, b, c, d, x[1], 5, 0xf61e2562); + d = md5Round2(d, a, b, c, x[6], 9, 0xc040b340); + c = md5Round2(c, d, a, b, x[11], 14, 0x265e5a51); + b = md5Round2(b, c, d, a, x[0], 20, 0xe9b6c7aa); + a = md5Round2(a, b, c, d, x[5], 5, 0xd62f105d); + d = md5Round2(d, a, b, c, x[10], 9, 0x02441453); + c = md5Round2(c, d, a, b, x[15], 14, 0xd8a1e681); + b = md5Round2(b, c, d, a, x[4], 20, 0xe7d3fbc8); + a = md5Round2(a, b, c, d, x[9], 5, 0x21e1cde6); + d = md5Round2(d, a, b, c, x[14], 9, 0xc33707d6); + c = md5Round2(c, d, a, b, x[3], 14, 0xf4d50d87); + b = md5Round2(b, c, d, a, x[8], 20, 0x455a14ed); + a = md5Round2(a, b, c, d, x[13], 5, 0xa9e3e905); + d = md5Round2(d, a, b, c, x[2], 9, 0xfcefa3f8); + c = md5Round2(c, d, a, b, x[7], 14, 0x676f02d9); + b = md5Round2(b, c, d, a, x[12], 20, 0x8d2a4c8a); + + // round 3 + a = md5Round3(a, b, c, d, x[5], 4, 0xfffa3942); + d = md5Round3(d, a, b, c, x[8], 11, 0x8771f681); + c = md5Round3(c, d, a, b, x[11], 16, 0x6d9d6122); + b = md5Round3(b, c, d, a, x[14], 23, 0xfde5380c); + a = md5Round3(a, b, c, d, x[1], 4, 0xa4beea44); + d = md5Round3(d, a, b, c, x[4], 11, 0x4bdecfa9); + c = md5Round3(c, d, a, b, x[7], 16, 0xf6bb4b60); + b = md5Round3(b, c, d, a, x[10], 23, 0xbebfbc70); + a = md5Round3(a, b, c, d, x[13], 4, 0x289b7ec6); + d = md5Round3(d, a, b, c, x[0], 11, 0xeaa127fa); + c = md5Round3(c, d, a, b, x[3], 16, 0xd4ef3085); + b = md5Round3(b, c, d, a, x[6], 23, 0x04881d05); + a = md5Round3(a, b, c, d, x[9], 4, 0xd9d4d039); + d = md5Round3(d, a, b, c, x[12], 11, 0xe6db99e5); + c = md5Round3(c, d, a, b, x[15], 16, 0x1fa27cf8); + b = md5Round3(b, c, d, a, x[2], 23, 0xc4ac5665); + + // round 4 + a = md5Round4(a, b, c, d, x[0], 6, 0xf4292244); + d = md5Round4(d, a, b, c, x[7], 10, 0x432aff97); + c = md5Round4(c, d, a, b, x[14], 15, 0xab9423a7); + b = md5Round4(b, c, d, a, x[5], 21, 0xfc93a039); + a = md5Round4(a, b, c, d, x[12], 6, 0x655b59c3); + d = md5Round4(d, a, b, c, x[3], 10, 0x8f0ccc92); + c = md5Round4(c, d, a, b, x[10], 15, 0xffeff47d); + b = md5Round4(b, c, d, a, x[1], 21, 0x85845dd1); + a = md5Round4(a, b, c, d, x[8], 6, 0x6fa87e4f); + d = md5Round4(d, a, b, c, x[15], 10, 0xfe2ce6e0); + c = md5Round4(c, d, a, b, x[6], 15, 0xa3014314); + b = md5Round4(b, c, d, a, x[13], 21, 0x4e0811a1); + a = md5Round4(a, b, c, d, x[4], 6, 0xf7537e82); + d = md5Round4(d, a, b, c, x[11], 10, 0xbd3af235); + c = md5Round4(c, d, a, b, x[2], 15, 0x2ad7d2bb); + b = md5Round4(b, c, d, a, x[9], 21, 0xeb86d391); + + // increment a, b, c, d + a += aa; + b += bb; + c += cc; + d += dd; + } + + // break digest into bytes + digest[0] = a & 0xff; + digest[1] = (a >>= 8) & 0xff; + digest[2] = (a >>= 8) & 0xff; + digest[3] = (a >>= 8) & 0xff; + digest[4] = b & 0xff; + digest[5] = (b >>= 8) & 0xff; + digest[6] = (b >>= 8) & 0xff; + digest[7] = (b >>= 8) & 0xff; + digest[8] = c & 0xff; + digest[9] = (c >>= 8) & 0xff; + digest[10] = (c >>= 8) & 0xff; + digest[11] = (c >>= 8) & 0xff; + digest[12] = d & 0xff; + digest[13] = (d >>= 8) & 0xff; + digest[14] = (d >>= 8) & 0xff; + digest[15] = (d >>= 8) & 0xff; +} diff --git a/pdftops/Decrypt.h b/pdftops/Decrypt.h new file mode 100644 index 0000000000..3ea43741dc --- /dev/null +++ b/pdftops/Decrypt.h @@ -0,0 +1,49 @@ +//======================================================================== +// +// Decrypt.h +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#ifndef DECRYPT_H +#define DECRYPT_H + +#ifdef __GNUC__ +#pragma interface +#endif + +#include "gtypes.h" +#include "GString.h" + +//------------------------------------------------------------------------ +// Decrypt +//------------------------------------------------------------------------ + +class Decrypt { +public: + + // Initialize the decryptor object. + Decrypt(Guchar *fileKey, int objNum, int objGen); + + // Reset decryption. + void reset(); + + // Decrypt one byte. + Guchar decryptByte(Guchar c); + + // Generate a file key. The buffer must have space for + // at least 16 bytes. Checks user key and returns gTrue if okay. + // may be NULL. + static GBool makeFileKey(GString *ownerKey, GString *userKey, + int permissions, GString *fileID, + GString *userPassword, Guchar *fileKey); + +private: + + Guchar objKey[16]; + Guchar state[256]; + Guchar x, y; +}; + +#endif diff --git a/pdftops/Dict.cxx b/pdftops/Dict.cxx new file mode 100644 index 0000000000..c9f4feca69 --- /dev/null +++ b/pdftops/Dict.cxx @@ -0,0 +1,88 @@ +//======================================================================== +// +// Dict.cc +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include +#include +#include "gmem.h" +#include "Object.h" +#include "XRef.h" +#include "Dict.h" + +//------------------------------------------------------------------------ +// Dict +//------------------------------------------------------------------------ + +Dict::Dict() { + entries = NULL; + size = length = 0; + ref = 1; +} + +Dict::~Dict() { + int i; + + for (i = 0; i < length; ++i) { + gfree(entries[i].key); + entries[i].val.free(); + } + gfree(entries); +} + +void Dict::add(char *key, Object *val) { + if (length + 1 > size) { + size += 8; + entries = (DictEntry *)grealloc(entries, size * sizeof(DictEntry)); + } + entries[length].key = key; + entries[length].val = *val; + ++length; +} + +inline DictEntry *Dict::find(char *key) { + int i; + + for (i = 0; i < length; ++i) { + if (!strcmp(key, entries[i].key)) + return &entries[i]; + } + return NULL; +} + +GBool Dict::is(char *type) { + DictEntry *e; + + return (e = find("Type")) && e->val.isName(type); +} + +Object *Dict::lookup(char *key, Object *obj) { + DictEntry *e; + + return (e = find(key)) ? e->val.fetch(obj) : obj->initNull(); +} + +Object *Dict::lookupNF(char *key, Object *obj) { + DictEntry *e; + + return (e = find(key)) ? e->val.copy(obj) : obj->initNull(); +} + +char *Dict::getKey(int i) { + return entries[i].key; +} + +Object *Dict::getVal(int i, Object *obj) { + return entries[i].val.fetch(obj); +} + +Object *Dict::getValNF(int i, Object *obj) { + return entries[i].val.copy(obj); +} diff --git a/pdftops/Dict.h b/pdftops/Dict.h new file mode 100644 index 0000000000..cfc64d3b22 --- /dev/null +++ b/pdftops/Dict.h @@ -0,0 +1,69 @@ +//======================================================================== +// +// Dict.h +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#ifndef DICT_H +#define DICT_H + +#ifdef __GNUC__ +#pragma interface +#endif + +#include "Object.h" + +//------------------------------------------------------------------------ +// Dict +//------------------------------------------------------------------------ + +struct DictEntry { + char *key; + Object val; +}; + +class Dict { +public: + + // Constructor. + Dict(); + + // Destructor. + ~Dict(); + + // Reference counting. + int incRef() { return ++ref; } + int decRef() { return --ref; } + + // Get number of entries. + int getLength() { return length; } + + // Add an entry. NB: does not copy key. + void add(char *key, Object *val); + + // Check if dictionary is of specified type. + GBool is(char *type); + + // Look up an entry and return the value. Returns a null object + // if is not in the dictionary. + Object *lookup(char *key, Object *obj); + Object *lookupNF(char *key, Object *obj); + + // Iterative accessors. + char *getKey(int i); + Object *getVal(int i, Object *obj); + Object *getValNF(int i, Object *obj); + +private: + + DictEntry *entries; // array of entries + int size; // size of array + int length; // number of entries in dictionary + int ref; // reference count + + DictEntry *find(char *key); +}; + +#endif diff --git a/pdftops/Error.cxx b/pdftops/Error.cxx new file mode 100644 index 0000000000..4594516a6b --- /dev/null +++ b/pdftops/Error.cxx @@ -0,0 +1,46 @@ +//======================================================================== +// +// Error.cc +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include +#include +#include +#include "gtypes.h" +#include "Params.h" +#include "Error.h" + +FILE *errFile; +GBool errQuiet; + +void errorInit() { + errFile = stderr; +} + +void CDECL error(int pos, char *msg, ...) { + va_list args; + + if (errQuiet) { + return; + } + if (printCommands) { + fflush(stdout); + } + if (pos >= 0) { + fprintf(errFile, "ERROR: (%d): ", pos); + } else { + fprintf(errFile, "ERROR: "); + } + va_start(args, msg); + vfprintf(errFile, msg, args); + va_end(args); + fprintf(errFile, "\n"); + fflush(errFile); +} diff --git a/pdftops/Error.h b/pdftops/Error.h new file mode 100644 index 0000000000..f651678c85 --- /dev/null +++ b/pdftops/Error.h @@ -0,0 +1,26 @@ +//======================================================================== +// +// Error.h +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#ifndef ERROR_H +#define ERROR_H + +#ifdef __GNUC__ +#pragma interface +#endif + +#include +#include "config.h" + +// File to send error (and other) messages to. +extern FILE *errFile; + +extern void errorInit(); + +extern void CDECL error(int pos, char *msg, ...); + +#endif diff --git a/pdftops/FontEncoding.cxx b/pdftops/FontEncoding.cxx new file mode 100644 index 0000000000..ac852c4581 --- /dev/null +++ b/pdftops/FontEncoding.cxx @@ -0,0 +1,143 @@ +//======================================================================== +// +// FontEncoding.cc +// +// Copyright 1999 Derek B. Noonburg +// +//======================================================================== + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include +#include +#include +#include +#include "gmem.h" +#include "FontEncoding.h" + +//------------------------------------------------------------------------ +// FontEncoding +//------------------------------------------------------------------------ + +inline int FontEncoding::hash(char *name) { + Guint h; + + h = (Guint)name[0] & 0xff; + if (h && name[1]) + h = h * 61 + ((Guint)name[1] & 0xff); + return (int)(h % (Guint)fontEncHashSize); +} + +FontEncoding::FontEncoding() { + int i; + + encoding = (char **)gmalloc(256 * sizeof(char *)); + size = 256; + freeEnc = gTrue; + for (i = 0; i < 256; ++i) + encoding[i] = NULL; + for (i = 0; i < fontEncHashSize; ++i) + hashTab[i] = -1; +} + +FontEncoding::FontEncoding(char **encoding, int size) { + int i; + + this->encoding = encoding; + this->size = size; + freeEnc = gFalse; + for (i = 0; i < fontEncHashSize; ++i) + hashTab[i] = -1; + for (i = 0; i < size; ++i) { + if (encoding[i]) + addChar1(i, encoding[i]); + } +} + +FontEncoding::FontEncoding(FontEncoding *fontEnc) { + int i; + + encoding = (char **)gmalloc(fontEnc->size * sizeof(char *)); + size = fontEnc->size; + freeEnc = gTrue; + for (i = 0; i < size; ++i) { + encoding[i] = + fontEnc->encoding[i] ? copyString(fontEnc->encoding[i]) : NULL; + } + memcpy(hashTab, fontEnc->hashTab, fontEncHashSize * sizeof(short)); +} + +void FontEncoding::addChar(int code, char *name) { + int h, i; + + // replace character associated with code + if (encoding[code]) { + h = hash(encoding[code]); + for (i = 0; i < fontEncHashSize; ++i) { + if (hashTab[h] == code) { + hashTab[h] = -2; + break; + } + if (++h == fontEncHashSize) + h = 0; + } + gfree(encoding[code]); + } + + // associate name with code + encoding[code] = name; + + // insert name in hash table + addChar1(code, name); +} + +void FontEncoding::addChar1(int code, char *name) { + int h, i, code2; + + // insert name in hash table + h = hash(name); + for (i = 0; i < fontEncHashSize; ++i) { + code2 = hashTab[h]; + if (code2 < 0) { + hashTab[h] = code; + break; + } else if (encoding[code2] && !strcmp(encoding[code2], name)) { + // keep the highest code for each char -- this is needed because + // X won't display chars with codes < 32 + if (code > code2) + hashTab[h] = code; + break; + } + if (++h == fontEncHashSize) + h = 0; + } +} + +FontEncoding::~FontEncoding() { + int i; + + if (freeEnc) { + for (i = 0; i < size; ++i) { + if (encoding[i]) + gfree(encoding[i]); + } + gfree(encoding); + } +} + +int FontEncoding::getCharCode(char *name) { + int h, i, code; + + h = hash(name); + for (i = 0; i < fontEncHashSize; ++i) { + code = hashTab[h]; + if (code == -1 || + (code >= 0 && encoding[code] && !strcmp(encoding[code], name))) + return code; + if (++h >= fontEncHashSize) + h = 0; + } + return -1; +} diff --git a/pdftops/FontEncoding.h b/pdftops/FontEncoding.h new file mode 100644 index 0000000000..7c811536a8 --- /dev/null +++ b/pdftops/FontEncoding.h @@ -0,0 +1,64 @@ +//======================================================================== +// +// FontEncoding.h +// +// Copyright 1999 Derek B. Noonburg +// +//======================================================================== + +#ifndef FONTENCODING_H +#define FONTENCODING_H + +#ifdef __GNUC__ +#pragma interface +#endif + +#include "gtypes.h" + +//------------------------------------------------------------------------ +// FontEncoding +//------------------------------------------------------------------------ + +#define fontEncHashSize 419 + +class FontEncoding { +public: + + // Construct an empty encoding. + FontEncoding(); + + // Construct an encoding from an array of char names. + FontEncoding(char **encoding, int size); + + // Destructor. + ~FontEncoding(); + + // Create a copy of the encoding. + FontEncoding *copy() { return new FontEncoding(this); } + + // Return number of codes in encoding, i.e., max code + 1. + int getSize() { return size; } + + // Add a char to the encoding. + void addChar(int code, char *name); + + // Return the character name associated with . + char *getCharName(int code) { return encoding[code]; } + + // Return the code associated with . + int getCharCode(char *name); + +private: + + FontEncoding(FontEncoding *fontEnc); + int hash(char *name); + void addChar1(int code, char *name); + + char **encoding; // code --> name mapping + int size; // number of codes + GBool freeEnc; // should we free the encoding array? + short // name --> code hash table + hashTab[fontEncHashSize]; +}; + +#endif diff --git a/pdftops/FontFile.cxx b/pdftops/FontFile.cxx new file mode 100644 index 0000000000..a0ab63af5d --- /dev/null +++ b/pdftops/FontFile.cxx @@ -0,0 +1,1624 @@ +//======================================================================== +// +// FontFile.cc +// +// Copyright 1999 Derek B. Noonburg +// +//======================================================================== + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include +#include +#include +#include +#include +#include "gmem.h" +#include "Error.h" +#include "FontFile.h" + +#include "StdFontInfo.h" +#include "CompactFontInfo.h" + +//------------------------------------------------------------------------ + +static Guint getWord(Guchar *ptr, int size); +static double getNum(Guchar **ptr, GBool *fp); +static char *getString(int sid, Guchar *stringIdxPtr, + Guchar *stringStartPtr, int stringOffSize, + char *buf); + +//------------------------------------------------------------------------ + +static inline char *nextLine(char *line, char *end) { + while (line < end && *line != '\n' && *line != '\r') + ++line; + while (line < end && *line == '\n' || *line == '\r') + ++line; + return line; +} + +static char hexChars[17] = "0123456789ABCDEF"; + +//------------------------------------------------------------------------ +// FontFile +//------------------------------------------------------------------------ + +FontFile::FontFile() { +} + +FontFile::~FontFile() { +} + +//------------------------------------------------------------------------ +// Type1FontFile +//------------------------------------------------------------------------ + +Type1FontFile::Type1FontFile(char *file, int len) { + char *line, *line1, *p; + char buf[256]; + int n, code, i; + + name = NULL; + encoding = NULL; + freeEnc = gTrue; + + for (i = 1, line = file; i <= 100 && line < file + len && !encoding; ++i) { + + // get font name + if (!strncmp(line, "/FontName", 9)) { + strncpy(buf, line, 255); + buf[255] = '\0'; + if ((p = strchr(buf+9, '/')) && + (p = strtok(p+1, " \t\n\r"))) + name = copyString(p); + line = nextLine(line, file + len); + + // get encoding + } else if (!strncmp(line, "/Encoding StandardEncoding def", 30)) { + encoding = type1StdEncoding.copy(); + } else if (!strncmp(line, "/Encoding 256 array", 19)) { + encoding = new FontEncoding(); + for (i = 0; i < 300; ++i) { + line1 = nextLine(line, file + len); + if ((n = line1 - line) > 255) + n = 255; + strncpy(buf, line, n); + buf[n] = '\0'; + p = strtok(buf, " \t"); + if (p && !strcmp(p, "dup")) { + if ((p = strtok(NULL, " \t"))) { + if ((code = atoi(p)) < 256) { + if ((p = strtok(NULL, " \t"))) { + if (p[0] == '/') { + encoding->addChar(code, copyString(p+1)); + } + } + } + } + } else { + if ((p = strtok(NULL, " \t\n\r")) && !strcmp(p, "def")) { + break; + } + } + line = line1; + } + //~ check for getinterval/putinterval junk + + } else { + line = nextLine(line, file + len); + } + } +} + +Type1FontFile::~Type1FontFile() { + if (name) + gfree(name); + if (encoding && freeEnc) + delete encoding; +} + +FontEncoding *Type1FontFile::getEncoding(GBool taken) { + if (taken) + freeEnc = gFalse; + return encoding; +} + +//------------------------------------------------------------------------ +// Type1CFontFile +//------------------------------------------------------------------------ + +Type1CFontFile::Type1CFontFile(char *file, int len) { + char buf[256]; + Guchar *topPtr, *idxStartPtr, *idxPtr0, *idxPtr1; + Guchar *stringIdxPtr, *stringStartPtr; + int topOffSize, idxOffSize, stringOffSize; + int nFonts, nStrings, nGlyphs; + int nCodes, nRanges, nLeft, nSups; + Gushort *glyphNames; + int charset, enc, charstrings; + int charsetFormat, encFormat; + int c, sid; + double op[48]; + double x; + GBool isFP; + int key; + int i, j, n; + + name = NULL; + encoding = NULL; + freeEnc = gTrue; + + // read header + topPtr = (Guchar *)file + (file[2] & 0xff); + topOffSize = file[3] & 0xff; + + // read name index (first font only) + nFonts = getWord(topPtr, 2); + idxOffSize = topPtr[2]; + topPtr += 3; + idxStartPtr = topPtr + (nFonts + 1) * idxOffSize - 1; + idxPtr0 = idxStartPtr + getWord(topPtr, idxOffSize); + idxPtr1 = idxStartPtr + getWord(topPtr + idxOffSize, idxOffSize); + if ((n = idxPtr1 - idxPtr0) > 255) + n = 255; + strncpy(buf, (char *)idxPtr0, n); + buf[n] = '\0'; + name = copyString(buf); + topPtr = idxStartPtr + getWord(topPtr + nFonts * idxOffSize, idxOffSize); + + // read top dict index (first font only) + nFonts = getWord(topPtr, 2); + idxOffSize = topPtr[2]; + topPtr += 3; + idxStartPtr = topPtr + (nFonts + 1) * idxOffSize - 1; + idxPtr0 = idxStartPtr + getWord(topPtr, idxOffSize); + idxPtr1 = idxStartPtr + getWord(topPtr + idxOffSize, idxOffSize); + charset = 0; + enc = 0; + charstrings = 0; + i = 0; + while (idxPtr0 < idxPtr1) { + if (*idxPtr0 <= 27 || *idxPtr0 == 31) { + key = *idxPtr0++; + if (key == 0x0c) + key = (key << 8) | *idxPtr0++; + if (key == 0x0f) { // charset + charset = (int)op[0]; + } else if (key == 0x10) { // encoding + enc = (int)op[0]; + } else if (key == 0x11) { // charstrings + charstrings = (int)op[0]; + } + i = 0; + } else { + x = getNum(&idxPtr0, &isFP); + if (i < 48) + op[i++] = x; + } + } + topPtr = idxStartPtr + getWord(topPtr + nFonts * idxOffSize, idxOffSize); + + // read string index + nStrings = getWord(topPtr, 2); + stringOffSize = topPtr[2]; + topPtr += 3; + stringIdxPtr = topPtr; + stringStartPtr = topPtr + (nStrings + 1) * stringOffSize - 1; + topPtr = stringStartPtr + getWord(topPtr + nStrings * stringOffSize, + stringOffSize); + + // get number of glyphs from charstrings index + topPtr = (Guchar *)file + charstrings; + nGlyphs = getWord(topPtr, 2); + + // read charset + if (charset == 0) { + glyphNames = type1CISOAdobeCharset; + } else if (charset == 1) { + glyphNames = type1CExpertCharset; + } else if (charset == 2) { + glyphNames = type1CExpertSubsetCharset; + } else { + glyphNames = (Gushort *)gmalloc(nGlyphs * sizeof(Gushort)); + glyphNames[0] = 0; + topPtr = (Guchar *)file + charset; + charsetFormat = *topPtr++; + if (charsetFormat == 0) { + for (i = 1; i < nGlyphs; ++i) { + glyphNames[i] = getWord(topPtr, 2); + topPtr += 2; + } + } else if (charsetFormat == 1) { + i = 1; + while (i < nGlyphs) { + c = getWord(topPtr, 2); + topPtr += 2; + nLeft = *topPtr++; + for (j = 0; j <= nLeft; ++j) + glyphNames[i++] = c++; + } + } else if (charsetFormat == 2) { + i = 1; + while (i < nGlyphs) { + c = getWord(topPtr, 2); + topPtr += 2; + nLeft = getWord(topPtr, 2); + topPtr += 2; + for (j = 0; j <= nLeft; ++j) + glyphNames[i++] = c++; + } + } + } + + // read encoding (glyph -> code mapping) + if (enc == 0) { + encoding = type1StdEncoding.copy(); + } else if (enc == 1) { + encoding = type1ExpertEncoding.copy(); + } else { + encoding = new FontEncoding(); + topPtr = (Guchar *)file + enc; + encFormat = *topPtr++; + if ((encFormat & 0x7f) == 0) { + nCodes = 1 + *topPtr++; + if (nCodes > nGlyphs) { + nCodes = nGlyphs; + } + for (i = 1; i < nCodes; ++i) { + c = *topPtr++; + getString(glyphNames[i], stringIdxPtr, stringStartPtr, + stringOffSize, buf); + encoding->addChar(c, copyString(buf)); + } + } else if ((encFormat & 0x7f) == 1) { + nRanges = *topPtr++; + nCodes = 1; + for (i = 0; i < nRanges; ++i) { + c = *topPtr++; + nLeft = *topPtr++; + for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) { + getString(glyphNames[nCodes], stringIdxPtr, stringStartPtr, + stringOffSize, buf); + encoding->addChar(c, copyString(buf)); + ++nCodes; + ++c; + } + } + } + if (encFormat & 0x80) { + nSups = *topPtr++; + for (i = 0; i < nSups; ++i) { + c = *topPtr++; + sid = getWord(topPtr, 2); + topPtr += 2; + getString(sid, stringIdxPtr, stringStartPtr, + stringOffSize, buf); + encoding->addChar(c, copyString(buf)); + } + } + } + + if (charset > 2) + gfree(glyphNames); +} + +Type1CFontFile::~Type1CFontFile() { + if (name) + gfree(name); + if (encoding && freeEnc) + delete encoding; +} + +FontEncoding *Type1CFontFile::getEncoding(GBool taken) { + if (taken) + freeEnc = gFalse; + return encoding; +} + +static Guint getWord(Guchar *ptr, int size) { + Guint x; + int i; + + x = 0; + for (i = 0; i < size; ++i) + x = (x << 8) + *ptr++; + return x; +} + +static double getNum(Guchar **ptr, GBool *fp) { + static char nybChars[16] = "0123456789.ee -"; + int b0, b, nyb0, nyb1; + double x; + char buf[65]; + int i; + + x = 0; + *fp = gFalse; + b0 = (*ptr)[0]; + if (b0 < 28) { + x = 0; + } else if (b0 == 28) { + x = ((*ptr)[1] << 8) + (*ptr)[2]; + *ptr += 3; + } else if (b0 == 29) { + x = ((*ptr)[1] << 24) + ((*ptr)[2] << 16) + ((*ptr)[3] << 8) + (*ptr)[4]; + *ptr += 5; + } else if (b0 == 30) { + *ptr += 1; + i = 0; + do { + b = *(*ptr)++; + nyb0 = b >> 4; + nyb1 = b & 0x0f; + if (nyb0 == 0xf) + break; + buf[i++] = nybChars[nyb0]; + if (i == 64) + break; + if (nyb0 == 0xc) + buf[i++] = '-'; + if (i == 64) + break; + if (nyb1 == 0xf) + break; + buf[i++] = nybChars[nyb1]; + if (i == 64) + break; + if (nyb1 == 0xc) + buf[i++] = '-'; + } while (i < 64); + buf[i] = '\0'; + x = atof(buf); + *fp = gTrue; + } else if (b0 == 31) { + x = 0; + } else if (b0 < 247) { + x = b0 - 139; + *ptr += 1; + } else if (b0 < 251) { + x = ((b0 - 247) << 8) + (*ptr)[1] + 108; + *ptr += 2; + } else { + x = -((b0 - 251) << 8) - (*ptr)[1] - 108; + *ptr += 2; + } + return x; +} + +static char *getString(int sid, Guchar *stringIdxPtr, + Guchar *stringStartPtr, int stringOffSize, + char *buf) { + Guchar *idxPtr0, *idxPtr1; + int len; + + if (sid < 391) { + strcpy(buf, type1CStdStrings[sid]); + } else { + sid -= 391; + idxPtr0 = stringStartPtr + getWord(stringIdxPtr + sid * stringOffSize, + stringOffSize); + idxPtr1 = stringStartPtr + getWord(stringIdxPtr + (sid+1) * stringOffSize, + stringOffSize); + if ((len = idxPtr1 - idxPtr0) > 255) + len = 255; + strncpy(buf, (char *)idxPtr0, len); + buf[len] = '\0'; + } + return buf; +} + +//------------------------------------------------------------------------ +// Type1CFontConverter +//------------------------------------------------------------------------ + +Type1CFontConverter::Type1CFontConverter(char *file, int len, FILE *out) { + this->file = file; + this->len = len; + this->out = out; + r1 = 55665; + line = 0; +} + +Type1CFontConverter::~Type1CFontConverter() { +} + +void Type1CFontConverter::convert() { + char *fontName; + struct { + int version; + int notice; + int copyright; + int fullName; + int familyName; + int weight; + int isFixedPitch; + double italicAngle; + double underlinePosition; + double underlineThickness; + int paintType; + int charstringType; //~ ??? + double fontMatrix[6]; + int uniqueID; + double fontBBox[4]; + double strokeWidth; //~ ??? + int charset; + int encoding; + int charStrings; + int privateSize; + int privateOffset; + } dict; + char buf[256], eBuf[256]; + Guchar *topPtr, *idxStartPtr, *idxPtr0, *idxPtr1; + Guchar *stringIdxPtr, *stringStartPtr; + int topOffSize, idxOffSize, stringOffSize; + int nFonts, nStrings, nGlyphs; + int nCodes, nRanges, nLeft, nSups; + Gushort *glyphNames; + int charsetFormat, encFormat; + int subrsOffset, nSubrs; + int nCharStrings; + int c, sid; + double x; + GBool isFP; + int key; + int i, j, n; + + // read header + topPtr = (Guchar *)file + (file[2] & 0xff); + topOffSize = file[3] & 0xff; + + // read name (first font only) + nFonts = getWord(topPtr, 2); + idxOffSize = topPtr[2]; + topPtr += 3; + idxStartPtr = topPtr + (nFonts + 1) * idxOffSize - 1; + idxPtr0 = idxStartPtr + getWord(topPtr, idxOffSize); + idxPtr1 = idxStartPtr + getWord(topPtr + idxOffSize, idxOffSize); + if ((n = idxPtr1 - idxPtr0) > 255) + n = 255; + strncpy(buf, (char *)idxPtr0, n); + buf[n] = '\0'; + fontName = copyString(buf); + topPtr = idxStartPtr + getWord(topPtr + nFonts * idxOffSize, idxOffSize); + + // read top dict (first font only) + nFonts = getWord(topPtr, 2); + idxOffSize = topPtr[2]; + topPtr += 3; + idxStartPtr = topPtr + (nFonts + 1) * idxOffSize - 1; + idxPtr0 = idxStartPtr + getWord(topPtr, idxOffSize); + idxPtr1 = idxStartPtr + getWord(topPtr + idxOffSize, idxOffSize); + dict.version = 0; + dict.notice = 0; + dict.copyright = 0; + dict.fullName = 0; + dict.familyName = 0; + dict.weight = 0; + dict.isFixedPitch = 0; + dict.italicAngle = 0; + dict.underlinePosition = -100; + dict.underlineThickness = 50; + dict.paintType = 0; + dict.charstringType = 2; + dict.fontMatrix[0] = 0.001; + dict.fontMatrix[1] = 0; + dict.fontMatrix[2] = 0; + dict.fontMatrix[3] = 0.001; + dict.fontMatrix[4] = 0; + dict.fontMatrix[5] = 0; + dict.uniqueID = 0; + dict.fontBBox[0] = 0; + dict.fontBBox[1] = 0; + dict.fontBBox[2] = 0; + dict.fontBBox[3] = 0; + dict.strokeWidth = 0; + dict.charset = 0; + dict.encoding = 0; + dict.charStrings = 0; + dict.privateSize = 0; + dict.privateOffset = 0; + i = 0; + while (idxPtr0 < idxPtr1) { + if (*idxPtr0 <= 27 || *idxPtr0 == 31) { + key = *idxPtr0++; + if (key == 0x0c) + key = (key << 8) | *idxPtr0++; + switch (key) { + case 0x0000: dict.version = (int)op[0]; break; + case 0x0001: dict.notice = (int)op[0]; break; + case 0x0c00: dict.copyright = (int)op[0]; break; + case 0x0002: dict.fullName = (int)op[0]; break; + case 0x0003: dict.familyName = (int)op[0]; break; + case 0x0004: dict.weight = (int)op[0]; break; + case 0x0c01: dict.isFixedPitch = (int)op[0]; break; + case 0x0c02: dict.italicAngle = op[0]; break; + case 0x0c03: dict.underlinePosition = op[0]; break; + case 0x0c04: dict.underlineThickness = op[0]; break; + case 0x0c05: dict.paintType = (int)op[0]; break; + case 0x0c06: dict.charstringType = (int)op[0]; break; + case 0x0c07: dict.fontMatrix[0] = op[0]; + dict.fontMatrix[1] = op[1]; + dict.fontMatrix[2] = op[2]; + dict.fontMatrix[3] = op[3]; + dict.fontMatrix[4] = op[4]; + dict.fontMatrix[5] = op[5]; break; + case 0x000d: dict.uniqueID = (int)op[0]; break; + case 0x0005: dict.fontBBox[0] = op[0]; + dict.fontBBox[1] = op[1]; + dict.fontBBox[2] = op[2]; + dict.fontBBox[3] = op[3]; break; + case 0x0c08: dict.strokeWidth = op[0]; break; + case 0x000f: dict.charset = (int)op[0]; break; + case 0x0010: dict.encoding = (int)op[0]; break; + case 0x0011: dict.charStrings = (int)op[0]; break; + case 0x0012: dict.privateSize = (int)op[0]; + dict.privateOffset = (int)op[1]; break; + } + i = 0; + } else { + x = getNum(&idxPtr0, &isFP); + if (i < 48) { + op[i] = x; + fp[i++] = isFP; + } + } + } + topPtr = idxStartPtr + getWord(topPtr + nFonts * idxOffSize, idxOffSize); + + // read string index + nStrings = getWord(topPtr, 2); + stringOffSize = topPtr[2]; + topPtr += 3; + stringIdxPtr = topPtr; + stringStartPtr = topPtr + (nStrings + 1) * stringOffSize - 1; + topPtr = stringStartPtr + getWord(topPtr + nStrings * stringOffSize, + stringOffSize); + +#if 1 //~ + // get global subrs + int nGSubrs; + int gSubrOffSize; + + nGSubrs = getWord(topPtr, 2); + gSubrOffSize = topPtr[2]; + topPtr += 3; +#endif + + // write header and font dictionary, up to encoding + fprintf(out, "%%!FontType1-1.0: %s", fontName); + if (dict.version != 0) { + fprintf(out, "%s", + getString(dict.version, stringIdxPtr, stringStartPtr, + stringOffSize, buf)); + } + fprintf(out, "\n"); + fprintf(out, "11 dict begin\n"); + fprintf(out, "/FontInfo 10 dict dup begin\n"); + if (dict.version != 0) { + fprintf(out, "/version (%s) readonly def\n", + getString(dict.version, stringIdxPtr, stringStartPtr, + stringOffSize, buf)); + } + if (dict.notice != 0) { + fprintf(out, "/Notice (%s) readonly def\n", + getString(dict.notice, stringIdxPtr, stringStartPtr, + stringOffSize, buf)); + } + if (dict.copyright != 0) { + fprintf(out, "/Copyright (%s) readonly def\n", + getString(dict.copyright, stringIdxPtr, stringStartPtr, + stringOffSize, buf)); + } + if (dict.fullName != 0) { + fprintf(out, "/FullName (%s) readonly def\n", + getString(dict.fullName, stringIdxPtr, stringStartPtr, + stringOffSize, buf)); + } + if (dict.familyName != 0) { + fprintf(out, "/FamilyName (%s) readonly def\n", + getString(dict.familyName, stringIdxPtr, stringStartPtr, + stringOffSize, buf)); + } + if (dict.weight != 0) { + fprintf(out, "/Weight (%s) readonly def\n", + getString(dict.weight, stringIdxPtr, stringStartPtr, + stringOffSize, buf)); + } + fprintf(out, "/isFixedPitch %s def\n", dict.isFixedPitch ? "true" : "false"); + fprintf(out, "/ItalicAngle %g def\n", dict.italicAngle); + fprintf(out, "/UnderlinePosition %g def\n", dict.underlinePosition); + fprintf(out, "/UnderlineThickness %g def\n", dict.underlineThickness); + fprintf(out, "end readonly def\n"); + fprintf(out, "/FontName /%s def\n", fontName); + fprintf(out, "/PaintType %d def\n", dict.paintType); + fprintf(out, "/FontType 1 def\n"); + fprintf(out, "/FontMatrix [%g %g %g %g %g %g] readonly def\n", + dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2], + dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]); + fprintf(out, "/FontBBox [%g %g %g %g] readonly def\n", + dict.fontBBox[0], dict.fontBBox[1], + dict.fontBBox[2], dict.fontBBox[3]); + if (dict.uniqueID != 0) { + fprintf(out, "/UniqueID %d def\n", dict.uniqueID); + } + + // get number of glyphs from charstrings index + topPtr = (Guchar *)file + dict.charStrings; + nGlyphs = getWord(topPtr, 2); + + // read charset + if (dict.charset == 0) { + glyphNames = type1CISOAdobeCharset; + } else if (dict.charset == 1) { + glyphNames = type1CExpertCharset; + } else if (dict.charset == 2) { + glyphNames = type1CExpertSubsetCharset; + } else { + glyphNames = (Gushort *)gmalloc(nGlyphs * sizeof(Gushort)); + glyphNames[0] = 0; + topPtr = (Guchar *)file + dict.charset; + charsetFormat = *topPtr++; + if (charsetFormat == 0) { + for (i = 1; i < nGlyphs; ++i) { + glyphNames[i] = getWord(topPtr, 2); + topPtr += 2; + } + } else if (charsetFormat == 1) { + i = 1; + while (i < nGlyphs) { + c = getWord(topPtr, 2); + topPtr += 2; + nLeft = *topPtr++; + for (j = 0; j <= nLeft; ++j) + glyphNames[i++] = c++; + } + } else if (charsetFormat == 2) { + i = 1; + while (i < nGlyphs) { + c = getWord(topPtr, 2); + topPtr += 2; + nLeft = getWord(topPtr, 2); + topPtr += 2; + for (j = 0; j <= nLeft; ++j) + glyphNames[i++] = c++; + } + } + } + + // read encoding (glyph -> code mapping), write Type 1 encoding + fprintf(out, "/Encoding "); + if (dict.encoding == 0) { + fprintf(out, "StandardEncoding def\n"); + } else { + fprintf(out, "256 array\n"); + fprintf(out, "0 1 255 {1 index exch /.notdef put} for\n"); + if (dict.encoding == 1) { + for (i = 0; i < 256; ++i) { + if (type1ExpertEncodingNames[i]) + fprintf(out, "dup %d /%s put\n", i, type1ExpertEncodingNames[i]); + } + } else { + topPtr = (Guchar *)file + dict.encoding; + encFormat = *topPtr++; + if ((encFormat & 0x7f) == 0) { + nCodes = 1 + *topPtr++; + if (nCodes > nGlyphs) { + nCodes = nGlyphs; + } + for (i = 1; i < nCodes; ++i) { + c = *topPtr++; + fprintf(out, "dup %d /%s put\n", c, + getString(glyphNames[i], stringIdxPtr, stringStartPtr, + stringOffSize, buf)); + } + } else if ((encFormat & 0x7f) == 1) { + nRanges = *topPtr++; + nCodes = 1; + for (i = 0; i < nRanges; ++i) { + c = *topPtr++; + nLeft = *topPtr++; + for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) { + fprintf(out, "dup %d /%s put\n", c, + getString(glyphNames[nCodes], stringIdxPtr, stringStartPtr, + stringOffSize, buf)); + ++nCodes; + ++c; + } + } + } + if (encFormat & 0x80) { + nSups = *topPtr++; + for (i = 0; i < nSups; ++i) { + c = *topPtr++; + sid = getWord(topPtr, 2); + topPtr += 2; + fprintf(out, "dup %d /%s put\n", c, + getString(sid, stringIdxPtr, stringStartPtr, + stringOffSize, buf)); + } + } + } + fprintf(out, "readonly def\n"); + } + fprintf(out, "currentdict end\n"); + fprintf(out, "currentfile eexec\n"); + + // get private dictionary + eexecWrite("\x83\xca\x73\xd5"); + eexecWrite("dup /Private 32 dict dup begin\n"); + eexecWrite("/RD {string currentfile exch readstring pop} executeonly def\n"); + eexecWrite("/ND {noaccess def} executeonly def\n"); + eexecWrite("/NP {noaccess put} executeonly def\n"); + eexecWrite("/MinFeature {16 16} ND\n"); + eexecWrite("/password 5839 def\n"); + subrsOffset = 0; + defaultWidthX = 0; + nominalWidthX = 0; + topPtr = (Guchar *)file + dict.privateOffset; + idxPtr0 = topPtr; + idxPtr1 = idxPtr0 + dict.privateSize; + i = 0; + while (idxPtr0 < idxPtr1) { + if (*idxPtr0 <= 27 || *idxPtr0 == 31) { + key = *idxPtr0++; + if (key == 0x0c) + key = (key << 8) | *idxPtr0++; + switch (key) { + case 0x0006: + getDeltaInt(eBuf, "BlueValues", op, i); + eexecWrite(eBuf); + break; + case 0x0007: + getDeltaInt(eBuf, "OtherBlues", op, i); + eexecWrite(eBuf); + break; + case 0x0008: + getDeltaInt(eBuf, "FamilyBlues", op, i); + eexecWrite(eBuf); + break; + case 0x0009: + getDeltaInt(eBuf, "FamilyOtherBlues", op, i); + eexecWrite(eBuf); + break; + case 0x0c09: + sprintf(eBuf, "/BlueScale %g def\n", op[0]); + eexecWrite(eBuf); + break; + case 0x0c0a: + sprintf(eBuf, "/BlueShift %d def\n", (int)op[0]); + eexecWrite(eBuf); + break; + case 0x0c0b: + sprintf(eBuf, "/BlueFuzz %d def\n", (int)op[0]); + eexecWrite(eBuf); + break; + case 0x000a: + sprintf(eBuf, "/StdHW [%g] def\n", op[0]); + eexecWrite(eBuf); + break; + case 0x000b: + sprintf(eBuf, "/StdVW [%g] def\n", op[0]); + eexecWrite(eBuf); + break; + case 0x0c0c: + getDeltaReal(eBuf, "StemSnapH", op, i); + eexecWrite(eBuf); + break; + case 0x0c0d: + getDeltaReal(eBuf, "StemSnapV", op, i); + eexecWrite(eBuf); + break; + case 0x0c0e: + sprintf(eBuf, "/ForceBold %s def\n", op[0] ? "true" : "false"); + eexecWrite(eBuf); + break; + case 0x0c0f: + sprintf(eBuf, "/ForceBoldThreshold %g def\n", op[0]); + eexecWrite(eBuf); + break; + case 0x0c11: + sprintf(eBuf, "/LanguageGroup %d def\n", (int)op[0]); + eexecWrite(eBuf); + break; + case 0x0c12: + sprintf(eBuf, "/ExpansionFactor %g def\n", op[0]); + eexecWrite(eBuf); + break; + case 0x0c13: + error(-1, "Got Type 1C InitialRandomSeed"); + break; + case 0x0013: + subrsOffset = (int)op[0]; + break; + case 0x0014: + defaultWidthX = op[0]; + defaultWidthXFP = fp[0]; + break; + case 0x0015: + nominalWidthX = op[0]; + nominalWidthXFP = fp[0]; + break; + default: + error(-1, "Uknown Type 1C private dict entry %04x", key); + break; + } + i = 0; + } else { + x = getNum(&idxPtr0, &isFP); + if (i < 48) { + op[i] = x; + fp[i++] = isFP; + } + } + } + + // get subrs + if (subrsOffset != 0) { + topPtr += subrsOffset; + nSubrs = getWord(topPtr, 2); + idxOffSize = topPtr[2]; + topPtr += 3; + sprintf(eBuf, "/Subrs %d array\n", nSubrs); + eexecWrite(eBuf); + idxStartPtr = topPtr + (nSubrs + 1) * idxOffSize - 1; + idxPtr1 = idxStartPtr + getWord(topPtr, idxOffSize); + for (i = 0; i < nSubrs; ++i) { + idxPtr0 = idxPtr1; + idxPtr1 = idxStartPtr + getWord(topPtr + (i+1)*idxOffSize, idxOffSize); + n = idxPtr1 - idxPtr0; +#if 1 //~ + error(-1, "Unimplemented Type 2 subrs"); +#else + sprintf(eBuf, "dup %d %d RD ", i, n); + eexecWrite(eBuf); + cvtGlyph(idxPtr0, n); + eexecWrite(" NP\n"); +#endif + } + eexecWrite("ND\n"); + } + + // get CharStrings + topPtr = (Guchar *)file + dict.charStrings; + nCharStrings = getWord(topPtr, 2); + idxOffSize = topPtr[2]; + topPtr += 3; + sprintf(eBuf, "2 index /CharStrings %d dict dup begin\n", nCharStrings); + eexecWrite(eBuf); + idxStartPtr = topPtr + (nCharStrings + 1) * idxOffSize - 1; + idxPtr1 = idxStartPtr + getWord(topPtr, idxOffSize); + for (i = 0; i < nCharStrings; ++i) { + idxPtr0 = idxPtr1; + idxPtr1 = idxStartPtr + getWord(topPtr + (i+1)*idxOffSize, idxOffSize); + n = idxPtr1 - idxPtr0; + cvtGlyph(getString(glyphNames[i], stringIdxPtr, stringStartPtr, + stringOffSize, buf), + idxPtr0, n); + } + eexecWrite("end\n"); + eexecWrite("end\n"); + eexecWrite("readonly put\n"); + eexecWrite("noaccess put\n"); + eexecWrite("dup /FontName get exch definefont pop\n"); + eexecWrite("mark currentfile closefile\n"); + + // trailer + if (line > 0) + fputc('\n', out); + for (i = 0; i < 8; ++i) { + fprintf(out, "0000000000000000000000000000000000000000000000000000000000000000\n"); + } + fprintf(out, "cleartomark\n"); + + // clean up + if (dict.charset > 2) + gfree(glyphNames); + gfree(fontName); +} + +void Type1CFontConverter::eexecWrite(char *s) { + Guchar *p; + Guchar x; + + for (p = (Guchar *)s; *p; ++p) { + x = *p ^ (r1 >> 8); + r1 = (x + r1) * 52845 + 22719; + fputc(hexChars[x >> 4], out); + fputc(hexChars[x & 0x0f], out); + line += 2; + if (line == 64) { + fputc('\n', out); + line = 0; + } + } +} + +void Type1CFontConverter::cvtGlyph(char *name, Guchar *s, int n) { + int nHints; + int x; + GBool first = gTrue; + char eBuf[256]; + double d, dx, dy; + GBool dFP; + int i, k; + + charBuf = new GString(); + charBuf->append((char)73); + charBuf->append((char)58); + charBuf->append((char)147); + charBuf->append((char)134); + + i = 0; + nOps = 0; + nHints = 0; + while (i < n) { + if (s[i] == 12) { + switch (s[i+1]) { + case 0: // dotsection (should be Type 1 only?) + //~ ignored + break; + case 34: // hflex + if (nOps != 7) { + error(-1, "Wrong number of args (%d) to Type 2 hflex", nOps); + } + eexecDumpNum(op[0], fp[0]); + eexecDumpNum(0, gFalse); + eexecDumpNum(op[1], fp[1]); + eexecDumpNum(op[2], fp[2]); + eexecDumpNum(op[3], fp[3]); + eexecDumpNum(0, gFalse); + eexecDumpOp1(8); + eexecDumpNum(op[4], fp[4]); + eexecDumpNum(0, gFalse); + eexecDumpNum(op[5], fp[5]); + eexecDumpNum(-op[2], fp[2]); + eexecDumpNum(op[6], fp[6]); + eexecDumpNum(0, gFalse); + eexecDumpOp1(8); + break; + case 35: // flex + if (nOps != 13) { + error(-1, "Wrong number of args (%d) to Type 2 flex", nOps); + } + eexecDumpNum(op[0], fp[0]); + eexecDumpNum(op[1], fp[1]); + eexecDumpNum(op[2], fp[2]); + eexecDumpNum(op[3], fp[3]); + eexecDumpNum(op[4], fp[4]); + eexecDumpNum(op[5], fp[5]); + eexecDumpOp1(8); + eexecDumpNum(op[6], fp[6]); + eexecDumpNum(op[7], fp[7]); + eexecDumpNum(op[8], fp[8]); + eexecDumpNum(op[9], fp[9]); + eexecDumpNum(op[10], fp[10]); + eexecDumpNum(op[11], fp[11]); + eexecDumpOp1(8); + break; + case 36: // hflex1 + if (nOps != 9) { + error(-1, "Wrong number of args (%d) to Type 2 hflex1", nOps); + } + eexecDumpNum(op[0], fp[0]); + eexecDumpNum(op[1], fp[1]); + eexecDumpNum(op[2], fp[2]); + eexecDumpNum(op[3], fp[3]); + eexecDumpNum(op[4], fp[4]); + eexecDumpNum(0, gFalse); + eexecDumpOp1(8); + eexecDumpNum(op[5], fp[5]); + eexecDumpNum(0, gFalse); + eexecDumpNum(op[6], fp[6]); + eexecDumpNum(op[7], fp[7]); + eexecDumpNum(op[8], fp[8]); + eexecDumpNum(-(op[1] + op[3] + op[7]), fp[1] | fp[3] | fp[7]); + eexecDumpOp1(8); + break; + case 37: // flex1 + if (nOps != 11) { + error(-1, "Wrong number of args (%d) to Type 2 flex1", nOps); + } + eexecDumpNum(op[0], fp[0]); + eexecDumpNum(op[1], fp[1]); + eexecDumpNum(op[2], fp[2]); + eexecDumpNum(op[3], fp[3]); + eexecDumpNum(op[4], fp[4]); + eexecDumpNum(op[5], fp[5]); + eexecDumpOp1(8); + eexecDumpNum(op[6], fp[6]); + eexecDumpNum(op[7], fp[7]); + eexecDumpNum(op[8], fp[8]); + eexecDumpNum(op[9], fp[9]); + dx = op[0] + op[2] + op[4] + op[6] + op[8]; + dy = op[1] + op[3] + op[5] + op[7] + op[9]; + if (fabs(dx) > fabs(dy)) { + eexecDumpNum(op[10], fp[10]); + eexecDumpNum(-dy, fp[1] | fp[3] | fp[5] | fp[7] | fp[9]); + } else { + eexecDumpNum(-dx, fp[0] | fp[2] | fp[4] | fp[6] | fp[8]); + eexecDumpNum(op[10], fp[10]); + } + eexecDumpOp1(8); + break; + case 3: // and + case 4: // or + case 5: // not + case 8: // store + case 9: // abs + case 10: // add + case 11: // sub + case 12: // div + case 13: // load + case 14: // neg + case 15: // eq + case 18: // drop + case 20: // put + case 21: // get + case 22: // ifelse + case 23: // random + case 24: // mul + case 26: // sqrt + case 27: // dup + case 28: // exch + case 29: // index + case 30: // roll + error(-1, "Unimplemented Type 2 charstring op: 12.%d", s[i+1]); + break; + default: + error(-1, "Illegal Type 2 charstring op: 12.%d", s[i+1]); + break; + } + i += 2; + nOps = 0; + } else if (s[i] == 19) { // hintmask + //~ ignored + if (first) { + cvtGlyphWidth(nOps == 1); + first = gFalse; + } + if (nOps > 0) { + if (nOps & 1) { + error(-1, "Wrong number of args (%d) to Type 2 hintmask/vstemhm", + nOps); + } + nHints += nOps / 2; + } + i += 1 + ((nHints + 7) >> 3); + nOps = 0; + } else if (s[i] == 20) { // cntrmask + //~ ignored + if (first) { + cvtGlyphWidth(nOps == 1); + first = gFalse; + } + if (nOps > 0) { + if (nOps & 1) { + error(-1, "Wrong number of args (%d) to Type 2 cntrmask/vstemhm", + nOps); + } + nHints += nOps / 2; + } + i += 1 + ((nHints + 7) >> 3); + nOps = 0; + } else if (s[i] == 28) { + x = (s[i+1] << 8) + s[i+2]; + if (x & 0x8000) + x |= -1 << 15; + if (nOps < 48) { + fp[nOps] = gFalse; + op[nOps++] = x; + } + i += 3; + } else if (s[i] <= 31) { + switch (s[i]) { + case 4: // vmoveto + if (first) { + cvtGlyphWidth(nOps == 2); + first = gFalse; + } + if (nOps != 1) + error(-1, "Wrong number of args (%d) to Type 2 vmoveto", nOps); + eexecDumpNum(op[0], fp[0]); + eexecDumpOp1(4); + break; + case 5: // rlineto + if (nOps < 2 || nOps % 2 != 0) + error(-1, "Wrong number of args (%d) to Type 2 rlineto", nOps); + for (k = 0; k < nOps; k += 2) { + eexecDumpNum(op[k], fp[k]); + eexecDumpNum(op[k+1], fp[k+1]); + eexecDumpOp1(5); + } + break; + case 6: // hlineto + if (nOps < 1) + error(-1, "Wrong number of args (%d) to Type 2 hlineto", nOps); + for (k = 0; k < nOps; ++k) { + eexecDumpNum(op[k], fp[k]); + eexecDumpOp1((k & 1) ? 7 : 6); + } + break; + case 7: // vlineto + if (nOps < 1) + error(-1, "Wrong number of args (%d) to Type 2 vlineto", nOps); + for (k = 0; k < nOps; ++k) { + eexecDumpNum(op[k], fp[k]); + eexecDumpOp1((k & 1) ? 6 : 7); + } + break; + case 8: // rrcurveto + if (nOps < 6 || nOps % 6 != 0) + error(-1, "Wrong number of args (%d) to Type 2 rrcurveto", nOps); + for (k = 0; k < nOps; k += 6) { + eexecDumpNum(op[k], fp[k]); + eexecDumpNum(op[k+1], fp[k+1]); + eexecDumpNum(op[k+2], fp[k+2]); + eexecDumpNum(op[k+3], fp[k+3]); + eexecDumpNum(op[k+4], fp[k+4]); + eexecDumpNum(op[k+5], fp[k+5]); + eexecDumpOp1(8); + } + break; + case 14: // endchar / seac + if (first) { + cvtGlyphWidth(nOps == 1 || nOps == 5); + first = gFalse; + } + if (nOps == 4) { + eexecDumpNum(0, 0); + eexecDumpNum(op[0], fp[0]); + eexecDumpNum(op[1], fp[1]); + eexecDumpNum(op[2], fp[2]); + eexecDumpNum(op[3], fp[3]); + eexecDumpOp2(6); + } else if (nOps == 0) { + eexecDumpOp1(14); + } else { + error(-1, "Wrong number of args (%d) to Type 2 endchar", nOps); + } + break; + case 21: // rmoveto + if (first) { + cvtGlyphWidth(nOps == 3); + first = gFalse; + } + if (nOps != 2) + error(-1, "Wrong number of args (%d) to Type 2 rmoveto", nOps); + eexecDumpNum(op[0], fp[0]); + eexecDumpNum(op[1], fp[1]); + eexecDumpOp1(21); + break; + case 22: // hmoveto + if (first) { + cvtGlyphWidth(nOps == 2); + first = gFalse; + } + if (nOps != 1) + error(-1, "Wrong number of args (%d) to Type 2 hmoveto", nOps); + eexecDumpNum(op[0], fp[0]); + eexecDumpOp1(22); + break; + case 24: // rcurveline + if (nOps < 8 || (nOps - 2) % 6 != 0) + error(-1, "Wrong number of args (%d) to Type 2 rcurveline", nOps); + for (k = 0; k < nOps - 2; k += 6) { + eexecDumpNum(op[k], fp[k]); + eexecDumpNum(op[k+1], fp[k+1]); + eexecDumpNum(op[k+2], fp[k+2]); + eexecDumpNum(op[k+3], fp[k+3]); + eexecDumpNum(op[k+4], fp[k+4]); + eexecDumpNum(op[k+5], fp[k+5]); + eexecDumpOp1(8); + } + eexecDumpNum(op[k], fp[k]); + eexecDumpNum(op[k+1], fp[k]); + eexecDumpOp1(5); + break; + case 25: // rlinecurve + if (nOps < 8 || (nOps - 6) % 2 != 0) + error(-1, "Wrong number of args (%d) to Type 2 rlinecurve", nOps); + for (k = 0; k < nOps - 6; k += 2) { + eexecDumpNum(op[k], fp[k]); + eexecDumpNum(op[k+1], fp[k]); + eexecDumpOp1(5); + } + eexecDumpNum(op[k], fp[k]); + eexecDumpNum(op[k+1], fp[k+1]); + eexecDumpNum(op[k+2], fp[k+2]); + eexecDumpNum(op[k+3], fp[k+3]); + eexecDumpNum(op[k+4], fp[k+4]); + eexecDumpNum(op[k+5], fp[k+5]); + eexecDumpOp1(8); + break; + case 26: // vvcurveto + if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) + error(-1, "Wrong number of args (%d) to Type 2 vvcurveto", nOps); + if (nOps % 2 == 1) { + eexecDumpNum(op[0], fp[0]); + eexecDumpNum(op[1], fp[1]); + eexecDumpNum(op[2], fp[2]); + eexecDumpNum(op[3], fp[3]); + eexecDumpNum(0, gFalse); + eexecDumpNum(op[4], fp[4]); + eexecDumpOp1(8); + k = 5; + } else { + k = 0; + } + for (; k < nOps; k += 4) { + eexecDumpNum(0, gFalse); + eexecDumpNum(op[k], fp[k]); + eexecDumpNum(op[k+1], fp[k+1]); + eexecDumpNum(op[k+2], fp[k+2]); + eexecDumpNum(0, gFalse); + eexecDumpNum(op[k+3], fp[k+3]); + eexecDumpOp1(8); + } + break; + case 27: // hhcurveto + if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) + error(-1, "Wrong number of args (%d) to Type 2 hhcurveto", nOps); + if (nOps % 2 == 1) { + eexecDumpNum(op[1], fp[1]); + eexecDumpNum(op[0], fp[0]); + eexecDumpNum(op[2], fp[2]); + eexecDumpNum(op[3], fp[3]); + eexecDumpNum(op[4], fp[4]); + eexecDumpNum(0, gFalse); + eexecDumpOp1(8); + k = 5; + } else { + k = 0; + } + for (; k < nOps; k += 4) { + eexecDumpNum(op[k], fp[k]); + eexecDumpNum(0, gFalse); + eexecDumpNum(op[k+1], fp[k+1]); + eexecDumpNum(op[k+2], fp[k+2]); + eexecDumpNum(op[k+3], fp[k+3]); + eexecDumpNum(0, gFalse); + eexecDumpOp1(8); + } + break; + case 30: // vhcurveto + if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) + error(-1, "Wrong number of args (%d) to Type 2 vhcurveto", nOps); + for (k = 0; k < nOps && k != nOps-5; k += 4) { + if (k % 8 == 0) { + eexecDumpNum(op[k], fp[k]); + eexecDumpNum(op[k+1], fp[k+1]); + eexecDumpNum(op[k+2], fp[k+2]); + eexecDumpNum(op[k+3], fp[k+3]); + eexecDumpOp1(30); + } else { + eexecDumpNum(op[k], fp[k]); + eexecDumpNum(op[k+1], fp[k+1]); + eexecDumpNum(op[k+2], fp[k+2]); + eexecDumpNum(op[k+3], fp[k+3]); + eexecDumpOp1(31); + } + } + if (k == nOps-5) { + if (k % 8 == 0) { + eexecDumpNum(0, gFalse); + eexecDumpNum(op[k], fp[k]); + eexecDumpNum(op[k+1], fp[k+1]); + eexecDumpNum(op[k+2], fp[k+2]); + eexecDumpNum(op[k+3], fp[k+3]); + eexecDumpNum(op[k+4], fp[k+4]); + } else { + eexecDumpNum(op[k], fp[k]); + eexecDumpNum(0, gFalse); + eexecDumpNum(op[k+1], fp[k+1]); + eexecDumpNum(op[k+2], fp[k+2]); + eexecDumpNum(op[k+4], fp[k+4]); + eexecDumpNum(op[k+3], fp[k+3]); + } + eexecDumpOp1(8); + } + break; + case 31: // hvcurveto + if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) + error(-1, "Wrong number of args (%d) to Type 2 hvcurveto", nOps); + for (k = 0; k < nOps && k != nOps-5; k += 4) { + if (k % 8 == 0) { + eexecDumpNum(op[k], fp[k]); + eexecDumpNum(op[k+1], fp[k+1]); + eexecDumpNum(op[k+2], fp[k+2]); + eexecDumpNum(op[k+3], fp[k+3]); + eexecDumpOp1(31); + } else { + eexecDumpNum(op[k], fp[k]); + eexecDumpNum(op[k+1], fp[k+1]); + eexecDumpNum(op[k+2], fp[k+2]); + eexecDumpNum(op[k+3], fp[k+3]); + eexecDumpOp1(30); + } + } + if (k == nOps-5) { + if (k % 8 == 0) { + eexecDumpNum(op[k], fp[k]); + eexecDumpNum(0, gFalse); + eexecDumpNum(op[k+1], fp[k+1]); + eexecDumpNum(op[k+2], fp[k+2]); + eexecDumpNum(op[k+4], fp[k+4]); + eexecDumpNum(op[k+3], fp[k+3]); + } else { + eexecDumpNum(0, gFalse); + eexecDumpNum(op[k], fp[k]); + eexecDumpNum(op[k+1], fp[k+1]); + eexecDumpNum(op[k+2], fp[k+2]); + eexecDumpNum(op[k+3], fp[k+3]); + eexecDumpNum(op[k+4], fp[k+4]); + } + eexecDumpOp1(8); + } + break; + case 1: // hstem + if (first) { + cvtGlyphWidth(nOps & 1); + first = gFalse; + } + if (nOps & 1) { + error(-1, "Wrong number of args (%d) to Type 2 hstem", nOps); + } + d = 0; + dFP = gFalse; + for (k = 0; k < nOps; k += 2) { + if (op[k+1] < 0) { + d += op[k] + op[k+1]; + dFP |= fp[k] | fp[k+1]; + eexecDumpNum(d, dFP); + eexecDumpNum(-op[k+1], fp[k+1]); + } else { + d += op[k]; + dFP |= fp[k]; + eexecDumpNum(d, dFP); + eexecDumpNum(op[k+1], fp[k+1]); + d += op[k+1]; + dFP |= fp[k+1]; + } + eexecDumpOp1(1); + } + nHints += nOps / 2; + break; + case 3: // vstem + if (first) { + cvtGlyphWidth(nOps & 1); + first = gFalse; + } + if (nOps & 1) { + error(-1, "Wrong number of args (%d) to Type 2 vstem", nOps); + } + d = 0; + dFP = gFalse; + for (k = 0; k < nOps; k += 2) { + if (op[k+1] < 0) { + d += op[k] + op[k+1]; + dFP |= fp[k] | fp[k+1]; + eexecDumpNum(d, dFP); + eexecDumpNum(-op[k+1], fp[k+1]); + } else { + d += op[k]; + dFP |= fp[k]; + eexecDumpNum(d, dFP); + eexecDumpNum(op[k+1], fp[k+1]); + d += op[k+1]; + dFP |= fp[k+1]; + } + eexecDumpOp1(3); + } + nHints += nOps / 2; + break; + case 18: // hstemhm + //~ ignored + if (first) { + cvtGlyphWidth(nOps & 1); + first = gFalse; + } + if (nOps & 1) { + error(-1, "Wrong number of args (%d) to Type 2 hstemhm", nOps); + } + nHints += nOps / 2; + break; + case 23: // vstemhm + //~ ignored + if (first) { + cvtGlyphWidth(nOps & 1); + first = gFalse; + } + if (nOps & 1) { + error(-1, "Wrong number of args (%d) to Type 2 vstemhm", nOps); + } + nHints += nOps / 2; + break; + case 10: // callsubr + case 11: // return + case 16: // blend + case 29: // callgsubr + error(-1, "Unimplemented Type 2 charstring op: %d", s[i]); + break; + default: + error(-1, "Illegal Type 2 charstring op: %d", s[i]); + break; + } + ++i; + nOps = 0; + } else if (s[i] <= 246) { + if (nOps < 48) { + fp[nOps] = gFalse; + op[nOps++] = (int)s[i] - 139; + } + ++i; + } else if (s[i] <= 250) { + if (nOps < 48) { + fp[nOps] = gFalse; + op[nOps++] = (((int)s[i] - 247) << 8) + (int)s[i+1] + 108; + } + i += 2; + } else if (s[i] <= 254) { + if (nOps < 48) { + fp[nOps] = gFalse; + op[nOps++] = -(((int)s[i] - 251) << 8) - (int)s[i+1] - 108; + } + i += 2; + } else { + x = (s[i+1] << 24) | (s[i+2] << 16) | (s[i+3] << 8) | s[i+4]; + if (x & 0x80000000) + x |= -1 << 31; + if (nOps < 48) { + fp[nOps] = gTrue; + op[nOps++] = (double)x / 65536.0; + } + i += 5; + } + } + + sprintf(eBuf, "/%s %d RD ", name, charBuf->getLength()); + eexecWrite(eBuf); + eexecWriteCharstring((Guchar *)charBuf->getCString(), charBuf->getLength()); + eexecWrite(" ND\n"); + delete charBuf; +} + +void Type1CFontConverter::cvtGlyphWidth(GBool useOp) { + double w; + GBool wFP; + int i; + + if (useOp) { + w = nominalWidthX + op[0]; + wFP = nominalWidthXFP | fp[0]; + for (i = 1; i < nOps; ++i) { + op[i-1] = op[i]; + fp[i-1] = fp[i]; + } + --nOps; + } else { + w = defaultWidthX; + wFP = defaultWidthXFP; + } + eexecDumpNum(0, gFalse); + eexecDumpNum(w, wFP); + eexecDumpOp1(13); +} + +void Type1CFontConverter::eexecDumpNum(double x, GBool fp) { + Guchar buf[12]; + int y, n; + + n = 0; + if (fp) { + if (x >= -32768 && x < 32768) { + y = (int)(x * 256.0); + buf[0] = 255; + buf[1] = (Guchar)(y >> 24); + buf[2] = (Guchar)(y >> 16); + buf[3] = (Guchar)(y >> 8); + buf[4] = (Guchar)y; + buf[5] = 255; + buf[6] = 0; + buf[7] = 0; + buf[8] = 1; + buf[9] = 0; + buf[10] = 12; + buf[11] = 12; + n = 12; + } else { + error(-1, "Type 2 fixed point constant out of range"); + } + } else { + y = (int)x; + if (y >= -107 && y <= 107) { + buf[0] = (Guchar)(y + 139); + n = 1; + } else if (y > 107 && y <= 1131) { + y -= 108; + buf[0] = (Guchar)((y >> 8) + 247); + buf[1] = (Guchar)(y & 0xff); + n = 2; + } else if (y < -107 && y >= -1131) { + y = -y - 108; + buf[0] = (Guchar)((y >> 8) + 251); + buf[1] = (Guchar)(y & 0xff); + n = 2; + } else { + buf[0] = 255; + buf[1] = (Guchar)(y >> 24); + buf[2] = (Guchar)(y >> 16); + buf[3] = (Guchar)(y >> 8); + buf[4] = (Guchar)y; + n = 5; + } + } + charBuf->append((char *)buf, n); +} + +void Type1CFontConverter::eexecDumpOp1(int op) { + charBuf->append((char)op); +} + +void Type1CFontConverter::eexecDumpOp2(int op) { + charBuf->append((char)12); + charBuf->append((char)op); +} + +void Type1CFontConverter::eexecWriteCharstring(Guchar *s, int n) { + Gushort r2; + Guchar x; + int i; + + r2 = 4330; + + for (i = 0; i < n; ++i) { + // charstring encryption + x = s[i]; + x ^= (r2 >> 8); + r2 = (x + r2) * 52845 + 22719; + + // eexec encryption + x ^= (r1 >> 8); + r1 = (x + r1) * 52845 + 22719; + fputc(hexChars[x >> 4], out); + fputc(hexChars[x & 0x0f], out); + line += 2; + if (line == 64) { + fputc('\n', out); + line = 0; + } + } +} + +void Type1CFontConverter::getDeltaInt(char *buf, char *name, double *op, + int n) { + int x, i; + + sprintf(buf, "/%s [", name); + buf += strlen(buf); + x = 0; + for (i = 0; i < n; ++i) { + x += (int)op[i]; + sprintf(buf, "%s%d", i > 0 ? " " : "", x); + buf += strlen(buf); + } + sprintf(buf, "] def\n"); +} + +void Type1CFontConverter::getDeltaReal(char *buf, char *name, double *op, + int n) { + double x; + int i; + + sprintf(buf, "/%s [", name); + buf += strlen(buf); + x = 0; + for (i = 0; i < n; ++i) { + x += op[i]; + sprintf(buf, "%s%g", i > 0 ? " " : "", x); + buf += strlen(buf); + } + sprintf(buf, "] def\n"); +} diff --git a/pdftops/FontFile.h b/pdftops/FontFile.h new file mode 100644 index 0000000000..ec625ef28b --- /dev/null +++ b/pdftops/FontFile.h @@ -0,0 +1,117 @@ +//======================================================================== +// +// FontFile.h +// +// Copyright 1999 Derek B. Noonburg +// +//======================================================================== + +#ifndef FONTFILE_H +#define FONTFILE_H + +#ifdef __GNUC__ +#pragma interface +#endif + +#include +#include "gtypes.h" +#include "GString.h" +#include "FontEncoding.h" + +//------------------------------------------------------------------------ +// FontFile +//------------------------------------------------------------------------ + +class FontFile { +public: + + FontFile(); + virtual ~FontFile(); + + // Returns the font name, as specified internally by the font file. + // Returns NULL if no name is available. + virtual char *getName() = 0; + + // Returns the custom font encoding, or NULL if the encoding is + // not available. If is set, the caller of this function + // will be responsible for freeing the encoding object. + virtual FontEncoding *getEncoding(GBool taken) = 0; +}; + +//------------------------------------------------------------------------ +// Type1FontFile +//------------------------------------------------------------------------ + +class Type1FontFile: public FontFile { +public: + + Type1FontFile(char *file, int len); + virtual ~Type1FontFile(); + virtual char *getName() { return name; } + virtual FontEncoding *getEncoding(GBool taken); + +private: + + char *name; + FontEncoding *encoding; + GBool freeEnc; +}; + +//------------------------------------------------------------------------ +// Type1CFontFile +//------------------------------------------------------------------------ + +class Type1CFontFile: public FontFile { +public: + + Type1CFontFile(char *file, int len); + virtual ~Type1CFontFile(); + virtual char *getName() { return name; } + virtual FontEncoding *getEncoding(GBool taken); + +private: + + char *name; + FontEncoding *encoding; + GBool freeEnc; +}; + +//------------------------------------------------------------------------ +// Type1CFontConverter +//------------------------------------------------------------------------ + +class Type1CFontConverter { +public: + + Type1CFontConverter(char *file, int len, FILE *out); + ~Type1CFontConverter(); + void convert(); + +private: + + void eexecWrite(char *s); + void cvtGlyph(char *name, Guchar *s, int n); + void cvtGlyphWidth(GBool useOp); + void eexecDumpNum(double x, GBool fp); + void eexecDumpOp1(int op); + void eexecDumpOp2(int op); + void eexecWriteCharstring(Guchar *s, int n); + void getDeltaInt(char *buf, char *name, double *op, int n); + void getDeltaReal(char *buf, char *name, double *op, int n); + + char *file; + int len; + FILE *out; + double op[48]; // operands + GBool fp[48]; // true if operand is fixed point + int nOps; // number of operands + double defaultWidthX; // default glyph width + double nominalWidthX; // nominal glyph width + GBool defaultWidthXFP; // true if defaultWidthX is fixed point + GBool nominalWidthXFP; // true if nominalWidthX is fixed point + Gushort r1; // eexec encryption key + GString *charBuf; // charstring output buffer + int line; // number of eexec chars on current line +}; + +#endif diff --git a/pdftops/FontInfo.h b/pdftops/FontInfo.h new file mode 100644 index 0000000000..ee85b95b49 --- /dev/null +++ b/pdftops/FontInfo.h @@ -0,0 +1,2068 @@ +//======================================================================== +// +// FontInfo.h +// +// This file was automatically generated by makeFontInfo. +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#ifndef FONTINFO_H +#define FONTINFO_H + +//------------------------------------------------------------------------ +// Character encodings. +//------------------------------------------------------------------------ + +#define standardEncodingSize 335 +static char *standardEncodingNames[standardEncodingSize] = { + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "space", + "exclam", + "quotedbl", + "numbersign", + "dollar", + "percent", + "ampersand", + "quoteright", + "parenleft", + "parenright", + "asterisk", + "plus", + "comma", + "hyphen", + "period", + "slash", + "zero", + "one", + "two", + "three", + "four", + "five", + "six", + "seven", + "eight", + "nine", + "colon", + "semicolon", + "less", + "equal", + "greater", + "question", + "at", + "A", + "B", + "C", + "D", + "E", + "F", + "G", + "H", + "I", + "J", + "K", + "L", + "M", + "N", + "O", + "P", + "Q", + "R", + "S", + "T", + "U", + "V", + "W", + "X", + "Y", + "Z", + "bracketleft", + "backslash", + "bracketright", + "asciicircum", + "underscore", + "quoteleft", + "a", + "b", + "c", + "d", + "e", + "f", + "g", + "h", + "i", + "j", + "k", + "l", + "m", + "n", + "o", + "p", + "q", + "r", + "s", + "t", + "u", + "v", + "w", + "x", + "y", + "z", + "braceleft", + "bar", + "braceright", + "asciitilde", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "exclamdown", + "cent", + "sterling", + "fraction", + "yen", + "florin", + "section", + "currency", + "quotesingle", + "quotedblleft", + "guillemotleft", + "guilsinglleft", + "guilsinglright", + "fi", + "fl", + NULL, + "endash", + "dagger", + "daggerdbl", + "periodcentered", + NULL, + "paragraph", + "bullet", + "quotesinglbase", + "quotedblbase", + "quotedblright", + "guillemotright", + "ellipsis", + "perthousand", + NULL, + "questiondown", + NULL, + "grave", + "acute", + "circumflex", + "tilde", + "macron", + "breve", + "dotaccent", + "dieresis", + NULL, + "ring", + "cedilla", + NULL, + "hungarumlaut", + "ogonek", + "caron", + "emdash", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "AE", + NULL, + "ordfeminine", + NULL, + NULL, + NULL, + NULL, + "Lslash", + "Oslash", + "OE", + "ordmasculine", + NULL, + NULL, + NULL, + NULL, + NULL, + "ae", + NULL, + NULL, + NULL, + "dotlessi", + NULL, + NULL, + "lslash", + "oslash", + "oe", + "germandbls", + NULL, + NULL, + NULL, + NULL, + "Aacute", + "Acircumflex", + "Adieresis", + "Agrave", + "Aring", + "Atilde", + "Ccedilla", + "Eacute", + "Ecircumflex", + "Edieresis", + "Egrave", + "Eth", + "Iacute", + "Icircumflex", + "Idieresis", + "Igrave", + "Ntilde", + "Oacute", + "Ocircumflex", + "Odieresis", + "Ograve", + "Otilde", + "Scaron", + "Thorn", + "Uacute", + "Ucircumflex", + "Udieresis", + "Ugrave", + "Yacute", + "Ydieresis", + "Zcaron", + "aacute", + "acircumflex", + "adieresis", + "agrave", + "aring", + "atilde", + "brokenbar", + "ccedilla", + "copyright", + "degree", + "divide", + "eacute", + "ecircumflex", + "edieresis", + "egrave", + "eth", + "iacute", + "icircumflex", + "idieresis", + "igrave", + "logicalnot", + "minus", + "mu", + "multiply", + "ntilde", + "oacute", + "ocircumflex", + "odieresis", + "ograve", + "onehalf", + "onequarter", + "onesuperior", + "otilde", + "plusminus", + "registered", + "scaron", + "thorn", + "threequarters", + "threesuperior", + "trademark", + "twosuperior", + "uacute", + "ucircumflex", + "udieresis", + "ugrave", + "yacute", + "ydieresis", + "zcaron" +}; +static FontEncoding standardEncoding(standardEncodingNames, + standardEncodingSize); + +#define symbolEncodingSize 257 +static char *symbolEncodingNames[symbolEncodingSize] = { + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "space", + "exclam", + "universal", + "numbersign", + "existential", + "percent", + "ampersand", + "suchthat", + "parenleft", + "parenright", + "asteriskmath", + "plus", + "comma", + "minus", + "period", + "slash", + "zero", + "one", + "two", + "three", + "four", + "five", + "six", + "seven", + "eight", + "nine", + "colon", + "semicolon", + "less", + "equal", + "greater", + "question", + "congruent", + "Alpha", + "Beta", + "Chi", + "Delta", + "Epsilon", + "Phi", + "Gamma", + "Eta", + "Iota", + "theta1", + "Kappa", + "Lambda", + "Mu", + "Nu", + "Omicron", + "Pi", + "Theta", + "Rho", + "Sigma", + "Tau", + "Upsilon", + "sigma1", + "Omega", + "Xi", + "Psi", + "Zeta", + "bracketleft", + "therefore", + "bracketright", + "perpendicular", + "underscore", + "radicalex", + "alpha", + "beta", + "chi", + "delta", + "epsilon", + "phi", + "gamma", + "eta", + "iota", + "phi1", + "kappa", + "lambda", + "mu", + "nu", + "omicron", + "pi", + "theta", + "rho", + "sigma", + "tau", + "upsilon", + "omega1", + "omega", + "xi", + "psi", + "zeta", + "braceleft", + "bar", + "braceright", + "similar", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "Upsilon1", + "minute", + "lessequal", + "fraction", + "infinity", + "florin", + "club", + "diamond", + "heart", + "spade", + "arrowboth", + "arrowleft", + "arrowup", + "arrowright", + "arrowdown", + "degree", + "plusminus", + "second", + "greaterequal", + "multiply", + "proportional", + "partialdiff", + "bullet", + "divide", + "notequal", + "equivalence", + "approxequal", + "ellipsis", + "arrowvertex", + "arrowhorizex", + "carriagereturn", + "aleph", + "Ifraktur", + "Rfraktur", + "weierstrass", + "circlemultiply", + "circleplus", + "emptyset", + "intersection", + "union", + "propersuperset", + "reflexsuperset", + "notsubset", + "propersubset", + "reflexsubset", + "element", + "notelement", + "angle", + "gradient", + "registerserif", + "copyrightserif", + "trademarkserif", + "product", + "radical", + "dotmath", + "logicalnot", + "logicaland", + "logicalor", + "arrowdblboth", + "arrowdblleft", + "arrowdblup", + "arrowdblright", + "arrowdbldown", + "lozenge", + "angleleft", + "registersans", + "copyrightsans", + "trademarksans", + "summation", + "parenlefttp", + "parenleftex", + "parenleftbt", + "bracketlefttp", + "bracketleftex", + "bracketleftbt", + "bracelefttp", + "braceleftmid", + "braceleftbt", + "braceex", + NULL, + "angleright", + "integral", + "integraltp", + "integralex", + "integralbt", + "parenrighttp", + "parenrightex", + "parenrightbt", + "bracketrighttp", + "bracketrightex", + "bracketrightbt", + "bracerighttp", + "bracerightmid", + "bracerightbt", + NULL, + "apple" +}; +static FontEncoding symbolEncoding(symbolEncodingNames, + symbolEncodingSize); + +#define zapfDingbatsEncodingSize 270 +static char *zapfDingbatsEncodingNames[zapfDingbatsEncodingSize] = { + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "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", + "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", + "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", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "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", + "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", + "a171", + "a172", + "a173", + "a162", + "a174", + "a175", + "a176", + "a177", + "a178", + "a179", + "a193", + "a180", + "a199", + "a181", + "a200", + "a182", + NULL, + "a201", + "a183", + "a184", + "a197", + "a185", + "a194", + "a198", + "a186", + "a195", + "a187", + "a188", + "a189", + "a190", + "a191", + NULL, + "a205", + "a206", + "a85", + "a86", + "a87", + "a88", + "a89", + "a90", + "a91", + "a92", + "a93", + "a94", + "a95", + "a96" +}; +static FontEncoding zapfDingbatsEncoding(zapfDingbatsEncodingNames, + zapfDingbatsEncodingSize); + +#define macRomanEncodingSize 256 +static char *macRomanEncodingNames[macRomanEncodingSize] = { + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "space", + "exclam", + "quotedbl", + "numbersign", + "dollar", + "percent", + "ampersand", + "quotesingle", + "parenleft", + "parenright", + "asterisk", + "plus", + "comma", + "hyphen", + "period", + "slash", + "zero", + "one", + "two", + "three", + "four", + "five", + "six", + "seven", + "eight", + "nine", + "colon", + "semicolon", + "less", + "equal", + "greater", + "question", + "at", + "A", + "B", + "C", + "D", + "E", + "F", + "G", + "H", + "I", + "J", + "K", + "L", + "M", + "N", + "O", + "P", + "Q", + "R", + "S", + "T", + "U", + "V", + "W", + "X", + "Y", + "Z", + "bracketleft", + "backslash", + "bracketright", + "asciicircum", + "underscore", + "grave", + "a", + "b", + "c", + "d", + "e", + "f", + "g", + "h", + "i", + "j", + "k", + "l", + "m", + "n", + "o", + "p", + "q", + "r", + "s", + "t", + "u", + "v", + "w", + "x", + "y", + "z", + "braceleft", + "bar", + "braceright", + "asciitilde", + NULL, + "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", + "dagger", + "degree", + "cent", + "sterling", + "section", + "bullet", + "paragraph", + "germandbls", + "registered", + "copyright", + "trademark", + "acute", + "dieresis", + NULL, + "AE", + "Oslash", + NULL, + "plusminus", + NULL, + NULL, + "yen", + "mu", + NULL, + NULL, + NULL, + NULL, + NULL, + "ordfeminine", + "ordmasculine", + NULL, + "ae", + "oslash", + "questiondown", + "exclamdown", + "logicalnot", + NULL, + "florin", + NULL, + NULL, + "guillemotleft", + "guillemotright", + "ellipsis", + "space", + "Agrave", + "Atilde", + "Otilde", + "OE", + "oe", + "endash", + "emdash", + "quotedblleft", + "quotedblright", + "quoteleft", + "quoteright", + "divide", + NULL, + "ydieresis", + "Ydieresis", + "fraction", + "currency", + "guilsinglleft", + "guilsinglright", + "fi", + "fl", + "daggerdbl", + "periodcentered", + "quotesinglbase", + "quotedblbase", + "perthousand", + "Acircumflex", + "Ecircumflex", + "Aacute", + "Edieresis", + "Egrave", + "Iacute", + "Icircumflex", + "Idieresis", + "Igrave", + "Oacute", + "Ocircumflex", + NULL, + "Ograve", + "Uacute", + "Ucircumflex", + "Ugrave", + "dotlessi", + "circumflex", + "tilde", + "macron", + "breve", + "dotaccent", + "ring", + "cedilla", + "hungarumlaut", + "ogonek", + "caron" +}; +static FontEncoding macRomanEncoding(macRomanEncodingNames, + macRomanEncodingSize); + +#define winAnsiEncodingSize 256 +static char *winAnsiEncodingNames[winAnsiEncodingSize] = { + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "space", + "exclam", + "quotedbl", + "numbersign", + "dollar", + "percent", + "ampersand", + "quotesingle", + "parenleft", + "parenright", + "asterisk", + "plus", + "comma", + "hyphen", + "period", + "slash", + "zero", + "one", + "two", + "three", + "four", + "five", + "six", + "seven", + "eight", + "nine", + "colon", + "semicolon", + "less", + "equal", + "greater", + "question", + "at", + "A", + "B", + "C", + "D", + "E", + "F", + "G", + "H", + "I", + "J", + "K", + "L", + "M", + "N", + "O", + "P", + "Q", + "R", + "S", + "T", + "U", + "V", + "W", + "X", + "Y", + "Z", + "bracketleft", + "backslash", + "bracketright", + "asciicircum", + "underscore", + "grave", + "a", + "b", + "c", + "d", + "e", + "f", + "g", + "h", + "i", + "j", + "k", + "l", + "m", + "n", + "o", + "p", + "q", + "r", + "s", + "t", + "u", + "v", + "w", + "x", + "y", + "z", + "braceleft", + "bar", + "braceright", + "asciitilde", + "bullet", + "bullet", + "bullet", + "quotesinglbase", + "florin", + "quotedblbase", + "ellipsis", + "dagger", + "daggerdbl", + "circumflex", + "perthousand", + "Scaron", + "guilsinglleft", + "OE", + "bullet", + "bullet", + "bullet", + "bullet", + "quoteleft", + "quoteright", + "quotedblleft", + "quotedblright", + "bullet", + "endash", + "emdash", + "tilde", + "trademark", + "scaron", + "guilsinglright", + "oe", + "bullet", + "bullet", + "Ydieresis", + "space", + "exclamdown", + "cent", + "sterling", + "currency", + "yen", + "brokenbar", + "section", + "dieresis", + "copyright", + "ordfeminine", + "guillemotleft", + "logicalnot", + "hyphen", + "registered", + "macron", + "degree", + "plusminus", + "twosuperior", + "threesuperior", + "acute", + "mu", + "paragraph", + "periodcentered", + "cedilla", + "onesuperior", + "ordmasculine", + "guillemotright", + "onequarter", + "onehalf", + "threequarters", + "questiondown", + "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", + "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" +}; +static FontEncoding winAnsiEncoding(winAnsiEncodingNames, + winAnsiEncodingSize); + +//------------------------------------------------------------------------ +// Character widths for built-in fonts. +//------------------------------------------------------------------------ + +static Gushort courierWidths[335] = { + 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, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 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, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 0, 600, 600, 600, 600, 0, 600, 600, + 600, 600, 600, 600, 600, 600, 0, 600, + 0, 600, 600, 600, 600, 600, 600, 600, + 600, 0, 600, 600, 0, 600, 600, 600, + 600, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 600, 0, 600, 0, 0, 0, 0, + 600, 600, 600, 600, 0, 0, 0, 0, + 0, 600, 0, 0, 0, 600, 0, 0, + 600, 600, 600, 600, 0, 0, 0, 0, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600 +}; + +static Gushort courierBoldWidths[335] = { + 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, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 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, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 0, 600, 600, 600, 600, 0, 600, 600, + 600, 600, 600, 600, 600, 600, 0, 600, + 0, 600, 600, 600, 600, 600, 600, 600, + 600, 0, 600, 600, 0, 600, 600, 600, + 600, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 600, 0, 600, 0, 0, 0, 0, + 600, 600, 600, 600, 0, 0, 0, 0, + 0, 600, 0, 0, 0, 600, 0, 0, + 600, 600, 600, 600, 0, 0, 0, 0, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600 +}; + +static Gushort courierBoldObliqueWidths[335] = { + 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, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 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, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 0, 600, 600, 600, 600, 0, 600, 600, + 600, 600, 600, 600, 600, 600, 0, 600, + 0, 600, 600, 600, 600, 600, 600, 600, + 600, 0, 600, 600, 0, 600, 600, 600, + 600, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 600, 0, 600, 0, 0, 0, 0, + 600, 600, 600, 600, 0, 0, 0, 0, + 0, 600, 0, 0, 0, 600, 0, 0, + 600, 600, 600, 600, 0, 0, 0, 0, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600 +}; + +static Gushort courierObliqueWidths[335] = { + 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, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 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, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 0, 600, 600, 600, 600, 0, 600, 600, + 600, 600, 600, 600, 600, 600, 0, 600, + 0, 600, 600, 600, 600, 600, 600, 600, + 600, 0, 600, 600, 0, 600, 600, 600, + 600, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 600, 0, 600, 0, 0, 0, 0, + 600, 600, 600, 600, 0, 0, 0, 0, + 0, 600, 0, 0, 0, 600, 0, 0, + 600, 600, 600, 600, 0, 0, 0, 0, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600 +}; + +static Gushort helveticaWidths[335] = { + 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, + 278, 278, 355, 556, 556, 889, 667, 222, + 333, 333, 389, 584, 278, 333, 278, 278, + 556, 556, 556, 556, 556, 556, 556, 556, + 556, 556, 278, 278, 584, 584, 584, 556, + 1015, 667, 667, 722, 722, 667, 611, 778, + 722, 278, 500, 667, 556, 833, 722, 778, + 667, 778, 722, 667, 611, 722, 667, 944, + 667, 667, 611, 278, 278, 278, 469, 556, + 222, 556, 556, 500, 556, 556, 278, 556, + 556, 222, 222, 500, 222, 833, 556, 556, + 556, 556, 333, 500, 278, 556, 500, 722, + 500, 500, 500, 334, 260, 334, 584, 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, 333, 556, 556, 167, 556, 556, 556, + 556, 191, 333, 556, 333, 333, 500, 500, + 0, 556, 556, 556, 278, 0, 537, 350, + 222, 333, 333, 556, 1000, 1000, 0, 611, + 0, 333, 333, 333, 333, 333, 333, 333, + 333, 0, 333, 333, 0, 333, 333, 333, + 1000, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1000, 0, 370, 0, 0, 0, 0, + 556, 778, 1000, 365, 0, 0, 0, 0, + 0, 889, 0, 0, 0, 278, 0, 0, + 222, 611, 944, 611, 0, 0, 0, 0, + 667, 667, 667, 667, 667, 667, 722, 667, + 667, 667, 667, 722, 278, 278, 278, 278, + 722, 778, 778, 778, 778, 778, 667, 667, + 722, 722, 722, 722, 667, 667, 611, 556, + 556, 556, 556, 556, 556, 260, 500, 737, + 400, 584, 556, 556, 556, 556, 556, 278, + 278, 278, 278, 584, 584, 556, 584, 556, + 556, 556, 556, 556, 834, 834, 333, 556, + 584, 737, 500, 556, 834, 333, 1000, 333, + 556, 556, 556, 556, 500, 500, 500 +}; + +static Gushort helveticaBoldWidths[335] = { + 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, + 278, 333, 474, 556, 556, 889, 722, 278, + 333, 333, 389, 584, 278, 333, 278, 278, + 556, 556, 556, 556, 556, 556, 556, 556, + 556, 556, 333, 333, 584, 584, 584, 611, + 975, 722, 722, 722, 722, 667, 611, 778, + 722, 278, 556, 722, 611, 833, 722, 778, + 667, 778, 722, 667, 611, 722, 667, 944, + 667, 667, 611, 333, 278, 333, 584, 556, + 278, 556, 611, 556, 611, 556, 333, 611, + 611, 278, 278, 556, 278, 889, 611, 611, + 611, 611, 389, 556, 333, 611, 556, 778, + 556, 556, 500, 389, 280, 389, 584, 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, 333, 556, 556, 167, 556, 556, 556, + 556, 238, 500, 556, 333, 333, 611, 611, + 0, 556, 556, 556, 278, 0, 556, 350, + 278, 500, 500, 556, 1000, 1000, 0, 611, + 0, 333, 333, 333, 333, 333, 333, 333, + 333, 0, 333, 333, 0, 333, 333, 333, + 1000, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1000, 0, 370, 0, 0, 0, 0, + 611, 778, 1000, 365, 0, 0, 0, 0, + 0, 889, 0, 0, 0, 278, 0, 0, + 278, 611, 944, 611, 0, 0, 0, 0, + 722, 722, 722, 722, 722, 722, 722, 667, + 667, 667, 667, 722, 278, 278, 278, 278, + 722, 778, 778, 778, 778, 778, 667, 667, + 722, 722, 722, 722, 667, 667, 611, 556, + 556, 556, 556, 556, 556, 280, 556, 737, + 400, 584, 556, 556, 556, 556, 611, 278, + 278, 278, 278, 584, 584, 611, 584, 611, + 611, 611, 611, 611, 834, 834, 333, 611, + 584, 737, 556, 611, 834, 333, 1000, 333, + 611, 611, 611, 611, 556, 556, 500 +}; + +static Gushort helveticaBoldObliqueWidths[335] = { + 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, + 278, 333, 474, 556, 556, 889, 722, 278, + 333, 333, 389, 584, 278, 333, 278, 278, + 556, 556, 556, 556, 556, 556, 556, 556, + 556, 556, 333, 333, 584, 584, 584, 611, + 975, 722, 722, 722, 722, 667, 611, 778, + 722, 278, 556, 722, 611, 833, 722, 778, + 667, 778, 722, 667, 611, 722, 667, 944, + 667, 667, 611, 333, 278, 333, 584, 556, + 278, 556, 611, 556, 611, 556, 333, 611, + 611, 278, 278, 556, 278, 889, 611, 611, + 611, 611, 389, 556, 333, 611, 556, 778, + 556, 556, 500, 389, 280, 389, 584, 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, 333, 556, 556, 167, 556, 556, 556, + 556, 238, 500, 556, 333, 333, 611, 611, + 0, 556, 556, 556, 278, 0, 556, 350, + 278, 500, 500, 556, 1000, 1000, 0, 611, + 0, 333, 333, 333, 333, 333, 333, 333, + 333, 0, 333, 333, 0, 333, 333, 333, + 1000, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1000, 0, 370, 0, 0, 0, 0, + 611, 778, 1000, 365, 0, 0, 0, 0, + 0, 889, 0, 0, 0, 278, 0, 0, + 278, 611, 944, 611, 0, 0, 0, 0, + 722, 722, 722, 722, 722, 722, 722, 667, + 667, 667, 667, 722, 278, 278, 278, 278, + 722, 778, 778, 778, 778, 778, 667, 667, + 722, 722, 722, 722, 667, 667, 611, 556, + 556, 556, 556, 556, 556, 280, 556, 737, + 400, 584, 556, 556, 556, 556, 611, 278, + 278, 278, 278, 584, 584, 611, 584, 611, + 611, 611, 611, 611, 834, 834, 333, 611, + 584, 737, 556, 611, 834, 333, 1000, 333, + 611, 611, 611, 611, 556, 556, 500 +}; + +static Gushort helveticaObliqueWidths[335] = { + 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, + 278, 278, 355, 556, 556, 889, 667, 222, + 333, 333, 389, 584, 278, 333, 278, 278, + 556, 556, 556, 556, 556, 556, 556, 556, + 556, 556, 278, 278, 584, 584, 584, 556, + 1015, 667, 667, 722, 722, 667, 611, 778, + 722, 278, 500, 667, 556, 833, 722, 778, + 667, 778, 722, 667, 611, 722, 667, 944, + 667, 667, 611, 278, 278, 278, 469, 556, + 222, 556, 556, 500, 556, 556, 278, 556, + 556, 222, 222, 500, 222, 833, 556, 556, + 556, 556, 333, 500, 278, 556, 500, 722, + 500, 500, 500, 334, 260, 334, 584, 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, 333, 556, 556, 167, 556, 556, 556, + 556, 191, 333, 556, 333, 333, 500, 500, + 0, 556, 556, 556, 278, 0, 537, 350, + 222, 333, 333, 556, 1000, 1000, 0, 611, + 0, 333, 333, 333, 333, 333, 333, 333, + 333, 0, 333, 333, 0, 333, 333, 333, + 1000, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1000, 0, 370, 0, 0, 0, 0, + 556, 778, 1000, 365, 0, 0, 0, 0, + 0, 889, 0, 0, 0, 278, 0, 0, + 222, 611, 944, 611, 0, 0, 0, 0, + 667, 667, 667, 667, 667, 667, 722, 667, + 667, 667, 667, 722, 278, 278, 278, 278, + 722, 778, 778, 778, 778, 778, 667, 667, + 722, 722, 722, 722, 667, 667, 611, 556, + 556, 556, 556, 556, 556, 260, 500, 737, + 400, 584, 556, 556, 556, 556, 556, 278, + 278, 278, 278, 584, 584, 556, 584, 556, + 556, 556, 556, 556, 834, 834, 333, 556, + 584, 737, 500, 556, 834, 333, 1000, 333, + 556, 556, 556, 556, 500, 500, 500 +}; + +static Gushort symbolWidths[257] = { + 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, + 250, 333, 713, 500, 549, 833, 778, 439, + 333, 333, 500, 549, 250, 549, 250, 278, + 500, 500, 500, 500, 500, 500, 500, 500, + 500, 500, 278, 278, 549, 549, 549, 444, + 549, 722, 667, 722, 612, 611, 763, 603, + 722, 333, 631, 722, 686, 889, 722, 722, + 768, 741, 556, 592, 611, 690, 439, 768, + 645, 795, 611, 333, 863, 333, 658, 500, + 500, 631, 549, 549, 494, 439, 521, 411, + 603, 329, 603, 549, 549, 576, 521, 549, + 549, 521, 549, 603, 439, 576, 713, 686, + 493, 686, 494, 480, 200, 480, 549, 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, 620, 247, 549, 167, 713, 500, 753, + 753, 753, 753, 1042, 987, 603, 987, 603, + 400, 549, 411, 549, 549, 713, 494, 460, + 549, 549, 549, 549, 1000, 603, 1000, 658, + 823, 686, 795, 987, 768, 768, 823, 768, + 768, 713, 713, 713, 713, 713, 713, 713, + 768, 713, 790, 790, 890, 823, 549, 250, + 713, 603, 603, 1042, 987, 603, 987, 603, + 494, 329, 790, 790, 786, 713, 384, 384, + 384, 384, 384, 384, 494, 494, 494, 494, + 0, 329, 274, 686, 686, 686, 384, 384, + 384, 384, 384, 384, 494, 494, 494, 0, + 790 +}; + +static Gushort timesBoldWidths[335] = { + 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, + 250, 333, 555, 500, 500, 1000, 833, 333, + 333, 333, 500, 570, 250, 333, 250, 278, + 500, 500, 500, 500, 500, 500, 500, 500, + 500, 500, 333, 333, 570, 570, 570, 500, + 930, 722, 667, 722, 722, 667, 611, 778, + 778, 389, 500, 778, 667, 944, 722, 778, + 611, 778, 722, 556, 667, 722, 722, 1000, + 722, 722, 667, 333, 278, 333, 581, 500, + 333, 500, 556, 444, 556, 444, 333, 500, + 556, 278, 333, 556, 278, 833, 556, 500, + 556, 556, 444, 389, 333, 556, 500, 722, + 500, 500, 444, 394, 220, 394, 520, 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, 333, 500, 500, 167, 500, 500, 500, + 500, 278, 500, 500, 333, 333, 556, 556, + 0, 500, 500, 500, 250, 0, 540, 350, + 333, 500, 500, 500, 1000, 1000, 0, 500, + 0, 333, 333, 333, 333, 333, 333, 333, + 333, 0, 333, 333, 0, 333, 333, 333, + 1000, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1000, 0, 300, 0, 0, 0, 0, + 667, 778, 1000, 330, 0, 0, 0, 0, + 0, 722, 0, 0, 0, 278, 0, 0, + 278, 500, 722, 556, 0, 0, 0, 0, + 722, 722, 722, 722, 722, 722, 722, 667, + 667, 667, 667, 722, 389, 389, 389, 389, + 722, 778, 778, 778, 778, 778, 556, 611, + 722, 722, 722, 722, 722, 722, 667, 500, + 500, 500, 500, 500, 500, 220, 444, 747, + 400, 570, 444, 444, 444, 444, 500, 278, + 278, 278, 278, 570, 570, 556, 570, 556, + 500, 500, 500, 500, 750, 750, 300, 500, + 570, 747, 389, 556, 750, 300, 1000, 300, + 556, 556, 556, 556, 500, 500, 444 +}; + +static Gushort timesBoldItalicWidths[335] = { + 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, + 250, 389, 555, 500, 500, 833, 778, 333, + 333, 333, 500, 570, 250, 333, 250, 278, + 500, 500, 500, 500, 500, 500, 500, 500, + 500, 500, 333, 333, 570, 570, 570, 500, + 832, 667, 667, 667, 722, 667, 667, 722, + 778, 389, 500, 667, 611, 889, 722, 722, + 611, 722, 667, 556, 611, 722, 667, 889, + 667, 611, 611, 333, 278, 333, 570, 500, + 333, 500, 500, 444, 500, 444, 333, 500, + 556, 278, 278, 500, 278, 778, 556, 500, + 500, 500, 389, 389, 278, 556, 444, 667, + 500, 444, 389, 348, 220, 348, 570, 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, 389, 500, 500, 167, 500, 500, 500, + 500, 278, 500, 500, 333, 333, 556, 556, + 0, 500, 500, 500, 250, 0, 500, 350, + 333, 500, 500, 500, 1000, 1000, 0, 500, + 0, 333, 333, 333, 333, 333, 333, 333, + 333, 0, 333, 333, 0, 333, 333, 333, + 1000, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 944, 0, 266, 0, 0, 0, 0, + 611, 722, 944, 300, 0, 0, 0, 0, + 0, 722, 0, 0, 0, 278, 0, 0, + 278, 500, 722, 500, 0, 0, 0, 0, + 667, 667, 667, 667, 667, 667, 667, 667, + 667, 667, 667, 722, 389, 389, 389, 389, + 722, 722, 722, 722, 722, 722, 556, 611, + 722, 722, 722, 722, 611, 611, 611, 500, + 500, 500, 500, 500, 500, 220, 444, 747, + 400, 570, 444, 444, 444, 444, 500, 278, + 278, 278, 278, 606, 606, 576, 570, 556, + 500, 500, 500, 500, 750, 750, 300, 500, + 570, 747, 389, 500, 750, 300, 1000, 300, + 556, 556, 556, 556, 444, 444, 389 +}; + +static Gushort timesItalicWidths[335] = { + 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, + 250, 333, 420, 500, 500, 833, 778, 333, + 333, 333, 500, 675, 250, 333, 250, 278, + 500, 500, 500, 500, 500, 500, 500, 500, + 500, 500, 333, 333, 675, 675, 675, 500, + 920, 611, 611, 667, 722, 611, 611, 722, + 722, 333, 444, 667, 556, 833, 667, 722, + 611, 722, 611, 500, 556, 722, 611, 833, + 611, 556, 556, 389, 278, 389, 422, 500, + 333, 500, 500, 444, 500, 444, 278, 500, + 500, 278, 278, 444, 278, 722, 500, 500, + 500, 500, 389, 389, 278, 500, 444, 667, + 444, 444, 389, 400, 275, 400, 541, 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, 389, 500, 500, 167, 500, 500, 500, + 500, 214, 556, 500, 333, 333, 500, 500, + 0, 500, 500, 500, 250, 0, 523, 350, + 333, 556, 556, 500, 889, 1000, 0, 500, + 0, 333, 333, 333, 333, 333, 333, 333, + 333, 0, 333, 333, 0, 333, 333, 333, + 889, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 889, 0, 276, 0, 0, 0, 0, + 556, 722, 944, 310, 0, 0, 0, 0, + 0, 667, 0, 0, 0, 278, 0, 0, + 278, 500, 667, 500, 0, 0, 0, 0, + 611, 611, 611, 611, 611, 611, 667, 611, + 611, 611, 611, 722, 333, 333, 333, 333, + 667, 722, 722, 722, 722, 722, 500, 611, + 722, 722, 722, 722, 556, 556, 556, 500, + 500, 500, 500, 500, 500, 275, 444, 760, + 400, 675, 444, 444, 444, 444, 500, 278, + 278, 278, 278, 675, 675, 500, 675, 500, + 500, 500, 500, 500, 750, 750, 300, 500, + 675, 760, 389, 500, 750, 300, 980, 300, + 500, 500, 500, 500, 444, 444, 389 +}; + +static Gushort timesRomanWidths[335] = { + 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, + 250, 333, 408, 500, 500, 833, 778, 333, + 333, 333, 500, 564, 250, 333, 250, 278, + 500, 500, 500, 500, 500, 500, 500, 500, + 500, 500, 278, 278, 564, 564, 564, 444, + 921, 722, 667, 667, 722, 611, 556, 722, + 722, 333, 389, 722, 611, 889, 722, 722, + 556, 722, 667, 556, 611, 722, 722, 944, + 722, 722, 611, 333, 278, 333, 469, 500, + 333, 444, 500, 444, 500, 444, 333, 500, + 500, 278, 278, 500, 278, 778, 500, 500, + 500, 500, 333, 389, 278, 500, 500, 722, + 500, 500, 444, 480, 200, 480, 541, 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, 333, 500, 500, 167, 500, 500, 500, + 500, 180, 444, 500, 333, 333, 556, 556, + 0, 500, 500, 500, 250, 0, 453, 350, + 333, 444, 444, 500, 1000, 1000, 0, 444, + 0, 333, 333, 333, 333, 333, 333, 333, + 333, 0, 333, 333, 0, 333, 333, 333, + 1000, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 889, 0, 276, 0, 0, 0, 0, + 611, 722, 889, 310, 0, 0, 0, 0, + 0, 667, 0, 0, 0, 278, 0, 0, + 278, 500, 722, 500, 0, 0, 0, 0, + 722, 722, 722, 722, 722, 722, 667, 611, + 611, 611, 611, 722, 333, 333, 333, 333, + 722, 722, 722, 722, 722, 722, 556, 556, + 722, 722, 722, 722, 722, 722, 611, 444, + 444, 444, 444, 444, 444, 200, 444, 760, + 400, 564, 444, 444, 444, 444, 500, 278, + 278, 278, 278, 564, 564, 500, 564, 500, + 500, 500, 500, 500, 750, 750, 300, 500, + 564, 760, 389, 500, 750, 300, 980, 300, + 500, 500, 500, 500, 500, 500, 444 +}; + +static Gushort zapfDingbatsWidths[270] = { + 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, + 278, 974, 961, 974, 980, 719, 789, 790, + 791, 690, 960, 939, 549, 855, 911, 933, + 911, 945, 974, 755, 846, 762, 761, 571, + 677, 763, 760, 759, 754, 494, 552, 537, + 577, 692, 786, 788, 788, 790, 793, 794, + 816, 823, 789, 841, 823, 833, 816, 831, + 923, 744, 723, 749, 790, 792, 695, 776, + 768, 792, 759, 707, 708, 682, 701, 826, + 815, 789, 789, 707, 687, 696, 689, 786, + 787, 713, 791, 785, 791, 873, 761, 762, + 762, 759, 759, 892, 892, 788, 784, 438, + 138, 277, 415, 392, 392, 668, 668, 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, 732, 544, 544, 910, 667, 760, 760, + 776, 595, 694, 626, 788, 788, 788, 788, + 788, 788, 788, 788, 788, 788, 788, 788, + 788, 788, 788, 788, 788, 788, 788, 788, + 788, 788, 788, 788, 788, 788, 788, 788, + 788, 788, 788, 788, 788, 788, 788, 788, + 788, 788, 788, 788, 894, 838, 1016, 458, + 748, 924, 748, 918, 927, 928, 928, 834, + 873, 828, 924, 924, 917, 930, 931, 463, + 883, 836, 836, 867, 867, 696, 696, 874, + 0, 874, 760, 946, 771, 865, 771, 888, + 967, 888, 831, 873, 927, 970, 918, 0, + 509, 410, 509, 410, 234, 234, 390, 390, + 276, 276, 317, 317, 334, 334 +}; + +//------------------------------------------------------------------------ +// Built-in font table. +//------------------------------------------------------------------------ + +struct BuiltinFont { + char *name; + Gushort *widths; + FontEncoding *encoding; +}; + +#define numBuiltinFonts ((int)(sizeof(builtinFonts)/sizeof(BuiltinFont))) + +static BuiltinFont builtinFonts[] = { + {"Courier", courierWidths, &standardEncoding}, + {"Courier-Bold", courierBoldWidths, &standardEncoding}, + {"Courier-BoldOblique", courierBoldObliqueWidths, &standardEncoding}, + {"Courier-Oblique", courierObliqueWidths, &standardEncoding}, + {"Helvetica", helveticaWidths, &standardEncoding}, + {"Helvetica-Bold", helveticaBoldWidths, &standardEncoding}, + {"Helvetica-BoldOblique", helveticaBoldObliqueWidths, &standardEncoding}, + {"Helvetica-Oblique", helveticaObliqueWidths, &standardEncoding}, + {"Symbol", symbolWidths, &symbolEncoding}, + {"Times-Bold", timesBoldWidths, &standardEncoding}, + {"Times-BoldItalic", timesBoldItalicWidths, &standardEncoding}, + {"Times-Italic", timesItalicWidths, &standardEncoding}, + {"Times-Roman", timesRomanWidths, &standardEncoding}, + {"ZapfDingbats", zapfDingbatsWidths, &zapfDingbatsEncoding} +}; + +#endif diff --git a/pdftops/FormWidget.cxx b/pdftops/FormWidget.cxx new file mode 100644 index 0000000000..f9ec94fa25 --- /dev/null +++ b/pdftops/FormWidget.cxx @@ -0,0 +1,116 @@ +//======================================================================== +// +// FormWidget.cc +// +// Copyright 2000 Derek B. Noonburg +// +//======================================================================== + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include "gmem.h" +#include "Object.h" +#include "Gfx.h" +#include "FormWidget.h" + +//------------------------------------------------------------------------ +// FormWidget +//------------------------------------------------------------------------ + +FormWidget::FormWidget(Dict *dict) { + Object obj1, obj2; + + ok = gFalse; + + if (dict->lookup("AP", &obj1)->isDict()) { + obj1.dictLookupNF("N", &obj2); + //~ this doesn't handle appearances with multiple states -- + //~ need to look at AS key to get state and then get the + //~ corresponding entry from the N dict + if (obj2.isRef()) { + obj2.copy(&appearance); + ok = gTrue; + } + obj2.free(); + } + obj1.free(); + + if (dict->lookup("Rect", &obj1)->isArray() && + obj1.arrayGetLength() == 4) { + //~ should check object types here + obj1.arrayGet(0, &obj2); + xMin = obj2.getNum(); + obj2.free(); + obj1.arrayGet(1, &obj2); + yMin = obj2.getNum(); + obj2.free(); + obj1.arrayGet(2, &obj2); + xMax = obj2.getNum(); + obj2.free(); + obj1.arrayGet(3, &obj2); + yMax = obj2.getNum(); + obj2.free(); + } + obj1.free(); +} + +FormWidget::~FormWidget() { + appearance.free(); +} + +void FormWidget::draw(Gfx *gfx) { + Object obj; + + if (appearance.fetch(&obj)->isStream()) { + gfx->doWidgetForm(&obj, xMin, yMin); + } + obj.free(); +} + +//------------------------------------------------------------------------ +// FormWidgets +//------------------------------------------------------------------------ + +FormWidgets::FormWidgets(Object *annots) { + FormWidget *widget; + Object obj1, obj2; + int size; + int i; + + widgets = NULL; + size = 0; + nWidgets = 0; + + if (annots->isArray()) { + for (i = 0; i < annots->arrayGetLength(); ++i) { + if (annots->arrayGet(i, &obj1)->isDict()) { + if (obj1.dictLookup("Subtype", &obj2)->isName("Widget")) { + widget = new FormWidget(obj1.getDict()); + if (widget->isOk()) { + if (nWidgets >= size) { + size += 16; + widgets = (FormWidget **)grealloc(widgets, + size * sizeof(FormWidget *)); + } + widgets[nWidgets++] = widget; + } else { + delete widget; + } + } + obj2.free(); + } + obj1.free(); + } + } +} + +FormWidgets::~FormWidgets() { + int i; + + for (i = 0; i < nWidgets; ++i) { + delete widgets[i]; + } + gfree(widgets); +} diff --git a/pdftops/FormWidget.h b/pdftops/FormWidget.h new file mode 100644 index 0000000000..d746083bf4 --- /dev/null +++ b/pdftops/FormWidget.h @@ -0,0 +1,65 @@ +//======================================================================== +// +// FormWidget.h +// +// Copyright 2000 Derek B. Noonburg +// +//======================================================================== + +#ifndef FORMWIDGET_H +#define FORMWIDGET_H + +#ifdef __GNUC__ +#pragma interface +#endif + +class Gfx; + +//------------------------------------------------------------------------ +// FormWidget +//------------------------------------------------------------------------ + +class FormWidget { +public: + + FormWidget(Dict *dict); + ~FormWidget(); + GBool isOk() { return ok; } + + void draw(Gfx *gfx); + + // Get appearance object. + Object *getAppearance(Object *obj) { return appearance.fetch(obj); } + +private: + + Object appearance; // a reference to the Form XObject stream + // for the normal appearance + double xMin, yMin, // widget rectangle + xMax, yMax; + GBool ok; +}; + +//------------------------------------------------------------------------ +// FormWidgets +//------------------------------------------------------------------------ + +class FormWidgets { +public: + + // Extract widgets from array of annotations. + FormWidgets(Object *annots); + + ~FormWidgets(); + + // Iterate through list of widgets. + int getNumWidgets() { return nWidgets; } + FormWidget *getWidget(int i) { return widgets[i]; } + +private: + + FormWidget **widgets; + int nWidgets; +}; + +#endif diff --git a/pdftops/GB12CMapInfo.h b/pdftops/GB12CMapInfo.h new file mode 100644 index 0000000000..880375737d --- /dev/null +++ b/pdftops/GB12CMapInfo.h @@ -0,0 +1,50880 @@ +//======================================================================== +// +// GB12CMapInfo.h +// +// This file was automatically generated by makeCMapInfo. +// +// Copyright 1998 Derek B. Noonburg +// +//======================================================================== + +#ifndef GB12CMAPINFO_H +#define GB12CMAPINFO_H + +static Gushort gb12AdobeGB10Map2[66] = { + 0x0000, 0x0000, + 0x0000, 0x0000, + 0x0100, 0x0100, + 0x0200, 0x0200, + 0x0300, 0x0300, + 0x0400, 0x0400, + 0x0500, 0x0500, + 0x0600, 0x0600, + 0x0700, 0x0700, + 0x0800, 0x0800, + 0x0900, 0x0900, + 0x0a00, 0x0a00, + 0x0b00, 0x0b00, + 0x0c00, 0x0c00, + 0x0d00, 0x0d00, + 0x0e00, 0x0e00, + 0x0f00, 0x0f00, + 0x1000, 0x1000, + 0x1100, 0x1100, + 0x1200, 0x1200, + 0x1300, 0x1300, + 0x1400, 0x1400, + 0x1500, 0x1500, + 0x1600, 0x1600, + 0x1700, 0x1700, + 0x1800, 0x1800, + 0x1900, 0x1900, + 0x1a00, 0x1a00, + 0x1b00, 0x1b00, + 0x1c00, 0x1c00, + 0x1d00, 0x1d00, + 0x1e00, 0x1e00, + 0xffff, 0x0000 +}; + +static GfxFontEncoding16 gb12AdobeGB10Enc16 = { + 0, + { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, + gb12AdobeGB10Map2, 33 +}; + +static Gushort gb12AdobeGB11Map2[82] = { + 0x0000, 0x0000, + 0x0000, 0x0000, + 0x0100, 0x0100, + 0x0200, 0x0200, + 0x0300, 0x0300, + 0x0400, 0x0400, + 0x0500, 0x0500, + 0x0600, 0x0600, + 0x0700, 0x0700, + 0x0800, 0x0800, + 0x0900, 0x0900, + 0x0a00, 0x0a00, + 0x0b00, 0x0b00, + 0x0c00, 0x0c00, + 0x0d00, 0x0d00, + 0x0e00, 0x0e00, + 0x0f00, 0x0f00, + 0x1000, 0x1000, + 0x1100, 0x1100, + 0x1200, 0x1200, + 0x1300, 0x1300, + 0x1400, 0x1400, + 0x1500, 0x1500, + 0x1600, 0x1600, + 0x1700, 0x1700, + 0x1800, 0x1800, + 0x1900, 0x1900, + 0x1a00, 0x1a00, + 0x1b00, 0x1b00, + 0x1c00, 0x1c00, + 0x1d00, 0x1d00, + 0x1e00, 0x1e00, + 0x1f00, 0x1f00, + 0x2000, 0x2000, + 0x2100, 0x2100, + 0x2200, 0x2200, + 0x2300, 0x2300, + 0x2400, 0x2400, + 0x2500, 0x2500, + 0x2600, 0x2600, + 0xffff, 0x0000 +}; + +static GfxFontEncoding16 gb12AdobeGB11Enc16 = { + 0, + { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, + gb12AdobeGB11Map2, 41 +}; + +static Gushort gb12AdobeGB12Map2[178] = { + 0x0000, 0x0000, + 0x0000, 0x0000, + 0x0100, 0x0100, + 0x0200, 0x0200, + 0x0300, 0x0300, + 0x0400, 0x0400, + 0x0500, 0x0500, + 0x0600, 0x0600, + 0x0700, 0x0700, + 0x0800, 0x0800, + 0x0900, 0x0900, + 0x0a00, 0x0a00, + 0x0b00, 0x0b00, + 0x0c00, 0x0c00, + 0x0d00, 0x0d00, + 0x0e00, 0x0e00, + 0x0f00, 0x0f00, + 0x1000, 0x1000, + 0x1100, 0x1100, + 0x1200, 0x1200, + 0x1300, 0x1300, + 0x1400, 0x1400, + 0x1500, 0x1500, + 0x1600, 0x1600, + 0x1700, 0x1700, + 0x1800, 0x1800, + 0x1900, 0x1900, + 0x1a00, 0x1a00, + 0x1b00, 0x1b00, + 0x1c00, 0x1c00, + 0x1d00, 0x1d00, + 0x1e00, 0x1e00, + 0x1f00, 0x1f00, + 0x2000, 0x2000, + 0x2100, 0x2100, + 0x2200, 0x2200, + 0x2300, 0x2300, + 0x2400, 0x2400, + 0x2500, 0x2500, + 0x2600, 0x2600, + 0x2700, 0x2700, + 0x2800, 0x2800, + 0x2900, 0x2900, + 0x2a00, 0x2a00, + 0x2b00, 0x2b00, + 0x2c00, 0x2c00, + 0x2d00, 0x2d00, + 0x2e00, 0x2e00, + 0x2f00, 0x2f00, + 0x3000, 0x3000, + 0x3100, 0x3100, + 0x3200, 0x3200, + 0x3300, 0x3300, + 0x3400, 0x3400, + 0x3500, 0x3500, + 0x3600, 0x3600, + 0x3700, 0x3700, + 0x3800, 0x3800, + 0x3900, 0x3900, + 0x3a00, 0x3a00, + 0x3b00, 0x3b00, + 0x3c00, 0x3c00, + 0x3d00, 0x3d00, + 0x3e00, 0x3e00, + 0x3f00, 0x3f00, + 0x4000, 0x4000, + 0x4100, 0x4100, + 0x4200, 0x4200, + 0x4300, 0x4300, + 0x4400, 0x4400, + 0x4500, 0x4500, + 0x4600, 0x4600, + 0x4700, 0x4700, + 0x4800, 0x4800, + 0x4900, 0x4900, + 0x4a00, 0x4a00, + 0x4b00, 0x4b00, + 0x4c00, 0x4c00, + 0x4d00, 0x4d00, + 0x4e00, 0x4e00, + 0x4f00, 0x4f00, + 0x5000, 0x5000, + 0x5100, 0x5100, + 0x5200, 0x5200, + 0x5300, 0x5300, + 0x5400, 0x5400, + 0x5500, 0x5500, + 0x5600, 0x5600, + 0xffff, 0x0000 +}; + +static GfxFontEncoding16 gb12AdobeGB12Enc16 = { + 0, + { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, + gb12AdobeGB12Map2, 89 +}; + +static Gushort gb12GBEUCHMap2[180] = { + 0x0000, 0x0000, + 0xa1a1, 0x0060, + 0xa2b1, 0x00be, + 0xa2e5, 0x00f0, + 0xa2f1, 0x00fa, + 0xa3a1, 0x0106, + 0xa4a1, 0x0164, + 0xa5a1, 0x01b7, + 0xa6a1, 0x020d, + 0xa6c1, 0x0225, + 0xa7a1, 0x025a, + 0xa7d1, 0x027b, + 0xa8a1, 0x029c, + 0xa8c5, 0x02bc, + 0xa9a4, 0x02e2, + 0xaaa1, 0x032e, + 0xaba1, 0x038c, + 0xb0a1, 0x03ac, + 0xb1a1, 0x040a, + 0xb2a1, 0x0468, + 0xb3a1, 0x04c6, + 0xb4a1, 0x0524, + 0xb5a1, 0x0582, + 0xb6a1, 0x05e0, + 0xb7a1, 0x063e, + 0xb8a1, 0x069c, + 0xb9a1, 0x06fa, + 0xbaa1, 0x0758, + 0xbba1, 0x07b6, + 0xbca1, 0x0814, + 0xbda1, 0x0872, + 0xbea1, 0x08d0, + 0xbfa1, 0x092e, + 0xc0a1, 0x098c, + 0xc1a1, 0x09ea, + 0xc2a1, 0x0a48, + 0xc3a1, 0x0aa6, + 0xc4a1, 0x0b04, + 0xc5a1, 0x0b62, + 0xc6a1, 0x0bc0, + 0xc7a1, 0x0c1e, + 0xc8a1, 0x0c7c, + 0xc9a1, 0x0cda, + 0xcaa1, 0x0d38, + 0xcba1, 0x0d96, + 0xcca1, 0x0df4, + 0xcda1, 0x0e52, + 0xcea1, 0x0eb0, + 0xcfa1, 0x0f0e, + 0xd0a1, 0x0f6c, + 0xd1a1, 0x0fca, + 0xd2a1, 0x1028, + 0xd3a1, 0x1086, + 0xd4a1, 0x10e4, + 0xd5a1, 0x1142, + 0xd6a1, 0x11a0, + 0xd7a1, 0x11fe, + 0xd8a1, 0x1257, + 0xd9a1, 0x12b5, + 0xdaa1, 0x1313, + 0xdba1, 0x1371, + 0xdca1, 0x13cf, + 0xdda1, 0x142d, + 0xdea1, 0x148b, + 0xdfa1, 0x14e9, + 0xe0a1, 0x1547, + 0xe1a1, 0x15a5, + 0xe2a1, 0x1603, + 0xe3a1, 0x1661, + 0xe4a1, 0x16bf, + 0xe5a1, 0x171d, + 0xe6a1, 0x177b, + 0xe7a1, 0x17d9, + 0xe8a1, 0x1837, + 0xe9a1, 0x1895, + 0xeaa1, 0x18f3, + 0xeba1, 0x1951, + 0xeca1, 0x19af, + 0xeda1, 0x1a0d, + 0xeea1, 0x1a6b, + 0xefa1, 0x1ac9, + 0xf0a1, 0x1b27, + 0xf1a1, 0x1b85, + 0xf2a1, 0x1be3, + 0xf3a1, 0x1c41, + 0xf4a1, 0x1c9f, + 0xf5a1, 0x1cfd, + 0xf6a1, 0x1d5b, + 0xf7a1, 0x1db9, + 0xffff, 0x0000 +}; + +static GfxFontEncoding16 gb12GBEUCHEnc16 = { + 0, + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 }, + { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1e24, 0x032e, 0x032f, 0x0330, 0x0331, 0x0332, 0x0333, 0x0334, + 0x0335, 0x0336, 0x0337, 0x0338, 0x0339, 0x033a, 0x033b, 0x033c, + 0x033d, 0x033e, 0x033f, 0x0340, 0x0341, 0x0342, 0x0343, 0x0344, + 0x0345, 0x0346, 0x0347, 0x0348, 0x0349, 0x034a, 0x034b, 0x034c, + 0x034d, 0x034e, 0x034f, 0x0350, 0x0351, 0x0352, 0x0353, 0x0354, + 0x0355, 0x0356, 0x0357, 0x0358, 0x0359, 0x035a, 0x035b, 0x035c, + 0x035d, 0x035e, 0x035f, 0x0360, 0x0361, 0x0362, 0x0363, 0x0364, + 0x0365, 0x0366, 0x0367, 0x0368, 0x0369, 0x036a, 0x036b, 0x036c, + 0x036d, 0x036e, 0x036f, 0x0370, 0x0371, 0x0372, 0x0373, 0x0374, + 0x0375, 0x0376, 0x0377, 0x0378, 0x0379, 0x037a, 0x037b, 0x037c, + 0x037d, 0x037e, 0x037f, 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, + 0x0385, 0x0386, 0x0387, 0x0388, 0x0389, 0x038a, 0x038b, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, + gb12GBEUCHMap2, 90 +}; + +static Gushort gb12GBEUCVMap2[220] = { + 0x0000, 0x0000, + 0xa1a1, 0x0060, + 0xa2b1, 0x00be, + 0xa2e5, 0x00f0, + 0xa2f1, 0x00fa, + 0xa3a1, 0x0106, + 0xa4a1, 0x0164, + 0xa5a1, 0x01b7, + 0xa6a1, 0x020d, + 0xa6c1, 0x0225, + 0xa7a1, 0x025a, + 0xa7d1, 0x027b, + 0xa8a1, 0x029c, + 0xa8c5, 0x02bc, + 0xa9a4, 0x02e2, + 0xaaa1, 0x032e, + 0xaba1, 0x038c, + 0xb0a1, 0x03ac, + 0xb1a1, 0x040a, + 0xb2a1, 0x0468, + 0xb3a1, 0x04c6, + 0xb4a1, 0x0524, + 0xb5a1, 0x0582, + 0xb6a1, 0x05e0, + 0xb7a1, 0x063e, + 0xb8a1, 0x069c, + 0xb9a1, 0x06fa, + 0xbaa1, 0x0758, + 0xbba1, 0x07b6, + 0xbca1, 0x0814, + 0xbda1, 0x0872, + 0xbea1, 0x08d0, + 0xbfa1, 0x092e, + 0xc0a1, 0x098c, + 0xc1a1, 0x09ea, + 0xc2a1, 0x0a48, + 0xc3a1, 0x0aa6, + 0xc4a1, 0x0b04, + 0xc5a1, 0x0b62, + 0xc6a1, 0x0bc0, + 0xc7a1, 0x0c1e, + 0xc8a1, 0x0c7c, + 0xc9a1, 0x0cda, + 0xcaa1, 0x0d38, + 0xcba1, 0x0d96, + 0xcca1, 0x0df4, + 0xcda1, 0x0e52, + 0xcea1, 0x0eb0, + 0xcfa1, 0x0f0e, + 0xd0a1, 0x0f6c, + 0xd1a1, 0x0fca, + 0xd2a1, 0x1028, + 0xd3a1, 0x1086, + 0xd4a1, 0x10e4, + 0xd5a1, 0x1142, + 0xd6a1, 0x11a0, + 0xd7a1, 0x11fe, + 0xd8a1, 0x1257, + 0xd9a1, 0x12b5, + 0xdaa1, 0x1313, + 0xdba1, 0x1371, + 0xdca1, 0x13cf, + 0xdda1, 0x142d, + 0xdea1, 0x148b, + 0xdfa1, 0x14e9, + 0xe0a1, 0x1547, + 0xe1a1, 0x15a5, + 0xe2a1, 0x1603, + 0xe3a1, 0x1661, + 0xe4a1, 0x16bf, + 0xe5a1, 0x171d, + 0xe6a1, 0x177b, + 0xe7a1, 0x17d9, + 0xe8a1, 0x1837, + 0xe9a1, 0x1895, + 0xeaa1, 0x18f3, + 0xeba1, 0x1951, + 0xeca1, 0x19af, + 0xeda1, 0x1a0d, + 0xeea1, 0x1a6b, + 0xefa1, 0x1ac9, + 0xf0a1, 0x1b27, + 0xf1a1, 0x1b85, + 0xf2a1, 0x1be3, + 0xf3a1, 0x1c41, + 0xf4a1, 0x1c9f, + 0xf5a1, 0x1cfd, + 0xf6a1, 0x1d5b, + 0xf7a1, 0x1db9, + 0xa1a2, 0x023f, + 0xa1a3, 0x023e, + 0xa1aa, 0x0256, + 0xa1ab, 0x1e18, + 0xa1ad, 0x0257, + 0xa1b2, 0x0246, + 0xa1fe, 0x1e1a, + 0xa3a1, 0x0242, + 0xa3a8, 0x0244, + 0xa3ac, 0x023d, + 0xa3ae, 0x1e1b, + 0xa3ba, 0x0240, + 0xa3bd, 0x1e1c, + 0xa3bf, 0x0243, + 0xa3db, 0x1e1d, + 0xa3dd, 0x1e1e, + 0xa3df, 0x0258, + 0xa3fb, 0x0254, + 0xa3fd, 0x0255, + 0xa3fe, 0x1e1f, + 0xffff, 0x0000 +}; + +static GfxFontEncoding16 gb12GBEUCVEnc16 = { + 1, + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 }, + { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1e24, 0x032e, 0x032f, 0x0330, 0x0331, 0x0332, 0x0333, 0x0334, + 0x0335, 0x0336, 0x0337, 0x0338, 0x0339, 0x033a, 0x033b, 0x033c, + 0x033d, 0x033e, 0x033f, 0x0340, 0x0341, 0x0342, 0x0343, 0x0344, + 0x0345, 0x0346, 0x0347, 0x0348, 0x0349, 0x034a, 0x034b, 0x034c, + 0x034d, 0x034e, 0x034f, 0x0350, 0x0351, 0x0352, 0x0353, 0x0354, + 0x0355, 0x0356, 0x0357, 0x0358, 0x0359, 0x035a, 0x035b, 0x035c, + 0x035d, 0x035e, 0x035f, 0x0360, 0x0361, 0x0362, 0x0363, 0x0364, + 0x0365, 0x0366, 0x0367, 0x0368, 0x0369, 0x036a, 0x036b, 0x036c, + 0x036d, 0x036e, 0x036f, 0x0370, 0x0371, 0x0372, 0x0373, 0x0374, + 0x0375, 0x0376, 0x0377, 0x0378, 0x0379, 0x037a, 0x037b, 0x037c, + 0x037d, 0x037e, 0x037f, 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, + 0x0385, 0x0386, 0x0387, 0x0388, 0x0389, 0x038a, 0x038b, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, + gb12GBEUCVMap2, 110 +}; + +static Gushort gb12GBHMap2[180] = { + 0x0000, 0x0000, + 0x2121, 0x0060, + 0x2231, 0x00be, + 0x2265, 0x00f0, + 0x2271, 0x00fa, + 0x2321, 0x0106, + 0x2421, 0x0164, + 0x2521, 0x01b7, + 0x2621, 0x020d, + 0x2641, 0x0225, + 0x2721, 0x025a, + 0x2751, 0x027b, + 0x2821, 0x029c, + 0x2845, 0x02bc, + 0x2924, 0x02e2, + 0x2a21, 0x032e, + 0x2b21, 0x038c, + 0x3021, 0x03ac, + 0x3121, 0x040a, + 0x3221, 0x0468, + 0x3321, 0x04c6, + 0x3421, 0x0524, + 0x3521, 0x0582, + 0x3621, 0x05e0, + 0x3721, 0x063e, + 0x3821, 0x069c, + 0x3921, 0x06fa, + 0x3a21, 0x0758, + 0x3b21, 0x07b6, + 0x3c21, 0x0814, + 0x3d21, 0x0872, + 0x3e21, 0x08d0, + 0x3f21, 0x092e, + 0x4021, 0x098c, + 0x4121, 0x09ea, + 0x4221, 0x0a48, + 0x4321, 0x0aa6, + 0x4421, 0x0b04, + 0x4521, 0x0b62, + 0x4621, 0x0bc0, + 0x4721, 0x0c1e, + 0x4821, 0x0c7c, + 0x4921, 0x0cda, + 0x4a21, 0x0d38, + 0x4b21, 0x0d96, + 0x4c21, 0x0df4, + 0x4d21, 0x0e52, + 0x4e21, 0x0eb0, + 0x4f21, 0x0f0e, + 0x5021, 0x0f6c, + 0x5121, 0x0fca, + 0x5221, 0x1028, + 0x5321, 0x1086, + 0x5421, 0x10e4, + 0x5521, 0x1142, + 0x5621, 0x11a0, + 0x5721, 0x11fe, + 0x5821, 0x1257, + 0x5921, 0x12b5, + 0x5a21, 0x1313, + 0x5b21, 0x1371, + 0x5c21, 0x13cf, + 0x5d21, 0x142d, + 0x5e21, 0x148b, + 0x5f21, 0x14e9, + 0x6021, 0x1547, + 0x6121, 0x15a5, + 0x6221, 0x1603, + 0x6321, 0x1661, + 0x6421, 0x16bf, + 0x6521, 0x171d, + 0x6621, 0x177b, + 0x6721, 0x17d9, + 0x6821, 0x1837, + 0x6921, 0x1895, + 0x6a21, 0x18f3, + 0x6b21, 0x1951, + 0x6c21, 0x19af, + 0x6d21, 0x1a0d, + 0x6e21, 0x1a6b, + 0x6f21, 0x1ac9, + 0x7021, 0x1b27, + 0x7121, 0x1b85, + 0x7221, 0x1be3, + 0x7321, 0x1c41, + 0x7421, 0x1c9f, + 0x7521, 0x1cfd, + 0x7621, 0x1d5b, + 0x7721, 0x1db9, + 0xffff, 0x0000 +}; + +static GfxFontEncoding16 gb12GBHEnc16 = { + 0, + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, + gb12GBHMap2, 90 +}; + +static Gushort gb12GBVMap2[220] = { + 0x0000, 0x0000, + 0x2121, 0x0060, + 0x2231, 0x00be, + 0x2265, 0x00f0, + 0x2271, 0x00fa, + 0x2321, 0x0106, + 0x2421, 0x0164, + 0x2521, 0x01b7, + 0x2621, 0x020d, + 0x2641, 0x0225, + 0x2721, 0x025a, + 0x2751, 0x027b, + 0x2821, 0x029c, + 0x2845, 0x02bc, + 0x2924, 0x02e2, + 0x2a21, 0x032e, + 0x2b21, 0x038c, + 0x3021, 0x03ac, + 0x3121, 0x040a, + 0x3221, 0x0468, + 0x3321, 0x04c6, + 0x3421, 0x0524, + 0x3521, 0x0582, + 0x3621, 0x05e0, + 0x3721, 0x063e, + 0x3821, 0x069c, + 0x3921, 0x06fa, + 0x3a21, 0x0758, + 0x3b21, 0x07b6, + 0x3c21, 0x0814, + 0x3d21, 0x0872, + 0x3e21, 0x08d0, + 0x3f21, 0x092e, + 0x4021, 0x098c, + 0x4121, 0x09ea, + 0x4221, 0x0a48, + 0x4321, 0x0aa6, + 0x4421, 0x0b04, + 0x4521, 0x0b62, + 0x4621, 0x0bc0, + 0x4721, 0x0c1e, + 0x4821, 0x0c7c, + 0x4921, 0x0cda, + 0x4a21, 0x0d38, + 0x4b21, 0x0d96, + 0x4c21, 0x0df4, + 0x4d21, 0x0e52, + 0x4e21, 0x0eb0, + 0x4f21, 0x0f0e, + 0x5021, 0x0f6c, + 0x5121, 0x0fca, + 0x5221, 0x1028, + 0x5321, 0x1086, + 0x5421, 0x10e4, + 0x5521, 0x1142, + 0x5621, 0x11a0, + 0x5721, 0x11fe, + 0x5821, 0x1257, + 0x5921, 0x12b5, + 0x5a21, 0x1313, + 0x5b21, 0x1371, + 0x5c21, 0x13cf, + 0x5d21, 0x142d, + 0x5e21, 0x148b, + 0x5f21, 0x14e9, + 0x6021, 0x1547, + 0x6121, 0x15a5, + 0x6221, 0x1603, + 0x6321, 0x1661, + 0x6421, 0x16bf, + 0x6521, 0x171d, + 0x6621, 0x177b, + 0x6721, 0x17d9, + 0x6821, 0x1837, + 0x6921, 0x1895, + 0x6a21, 0x18f3, + 0x6b21, 0x1951, + 0x6c21, 0x19af, + 0x6d21, 0x1a0d, + 0x6e21, 0x1a6b, + 0x6f21, 0x1ac9, + 0x7021, 0x1b27, + 0x7121, 0x1b85, + 0x7221, 0x1be3, + 0x7321, 0x1c41, + 0x7421, 0x1c9f, + 0x7521, 0x1cfd, + 0x7621, 0x1d5b, + 0x7721, 0x1db9, + 0x2122, 0x023f, + 0x2123, 0x023e, + 0x212a, 0x0256, + 0x212b, 0x1e18, + 0x212d, 0x0257, + 0x2132, 0x0246, + 0x217e, 0x1e1a, + 0x2321, 0x0242, + 0x2328, 0x0244, + 0x232c, 0x023d, + 0x232e, 0x1e1b, + 0x233a, 0x0240, + 0x233d, 0x1e1c, + 0x233f, 0x0243, + 0x235b, 0x1e1d, + 0x235d, 0x1e1e, + 0x235f, 0x0258, + 0x237b, 0x0254, + 0x237d, 0x0255, + 0x237e, 0x1e1f, + 0xffff, 0x0000 +}; + +static GfxFontEncoding16 gb12GBVEnc16 = { + 1, + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, + gb12GBVMap2, 110 +}; + +static Gushort gb12GBKEUCHMap2[8142] = { + 0x0000, 0x0000, + 0x8140, 0x2758, + 0x8179, 0x2059, + 0x817a, 0x2791, + 0x8180, 0x2796, + 0x8186, 0x21f1, + 0x8187, 0x279c, + 0x81ed, 0x1ff2, + 0x81ee, 0x2802, + 0x81f6, 0x205d, + 0x81f7, 0x280a, + 0x8240, 0x2812, + 0x8253, 0x269c, + 0x8254, 0x2825, + 0x8262, 0x21b5, + 0x8263, 0x2833, + 0x8274, 0x22cc, + 0x8275, 0x2844, + 0x827a, 0x2016, + 0x827b, 0x2849, + 0x827d, 0x1e62, + 0x827e, 0x284b, + 0x8280, 0x1f20, + 0x8281, 0x284c, + 0x8283, 0x207f, + 0x8284, 0x284e, + 0x8290, 0x205c, + 0x8291, 0x285a, + 0x82a5, 0x2194, + 0x82a6, 0x286e, + 0x82c8, 0x1e65, + 0x82c9, 0x2281, + 0x82ca, 0x2890, + 0x82e1, 0x22cd, + 0x82e2, 0x28a7, + 0x82e3, 0x210a, + 0x82e4, 0x1e3e, + 0x82e5, 0x28a8, + 0x82ed, 0x267f, + 0x82ee, 0x28b0, + 0x82f2, 0x222e, + 0x82f3, 0x28b4, + 0x82f7, 0x1e96, + 0x82f8, 0x22cb, + 0x82f9, 0x226c, + 0x82fa, 0x28b8, + 0x82fb, 0x2117, + 0x82fc, 0x28b9, + 0x8340, 0x28bc, + 0x8341, 0x20e8, + 0x8342, 0x28bd, + 0x8345, 0x22d4, + 0x8346, 0x28c0, + 0x8348, 0x1fb9, + 0x8349, 0x28c2, + 0x834c, 0x22d8, + 0x834d, 0x28c5, + 0x8353, 0x20df, + 0x8354, 0x28cb, + 0x8357, 0x20c2, + 0x8358, 0x28ce, + 0x835e, 0x2195, + 0x835f, 0x28d4, + 0x8365, 0x1fac, + 0x8366, 0x22d3, + 0x8367, 0x28da, + 0x8372, 0x1f81, + 0x8373, 0x28e5, + 0x8378, 0x2210, + 0x8379, 0x28ea, + 0x837a, 0x22cf, + 0x837b, 0x28eb, + 0x837c, 0x2213, + 0x837d, 0x28ec, + 0x837e, 0x1fe4, + 0x8380, 0x1f90, + 0x8381, 0x28ed, + 0x8386, 0x22d6, + 0x8387, 0x28f2, + 0x8389, 0x22d0, + 0x838a, 0x22ce, + 0x838b, 0x28f4, + 0x838d, 0x2681, + 0x838e, 0x28f6, + 0x8394, 0x1e76, + 0x8395, 0x28fc, + 0x839e, 0x2231, + 0x839f, 0x2905, + 0x83a6, 0x1e93, + 0x83a7, 0x290c, + 0x83ab, 0x22d2, + 0x83ac, 0x2910, + 0x83ae, 0x22d7, + 0x83af, 0x22d5, + 0x83b0, 0x22d1, + 0x83b1, 0x2912, + 0x83ba, 0x1ee5, + 0x83bb, 0x291b, + 0x83c9, 0x2025, + 0x83ca, 0x2929, + 0x83f6, 0x1ecf, + 0x83f7, 0x2955, + 0x8440, 0x295d, + 0x8450, 0x1fd9, + 0x8451, 0x296d, + 0x8471, 0x22c8, + 0x8472, 0x298d, + 0x8474, 0x2263, + 0x8475, 0x298f, + 0x8477, 0x2683, + 0x8478, 0x2991, + 0x8480, 0x2998, + 0x8482, 0x1f17, + 0x8483, 0x299a, + 0x848e, 0x1f2b, + 0x848f, 0x29a5, + 0x8492, 0x22ca, + 0x8493, 0x1e99, + 0x8494, 0x29a8, + 0x849d, 0x1f4f, + 0x849e, 0x29b1, + 0x84a1, 0x1fcf, + 0x84a2, 0x2036, + 0x84a3, 0x1f3a, + 0x84a4, 0x29b4, + 0x84a5, 0x22c9, + 0x84a6, 0x1f99, + 0x84a7, 0x29b5, + 0x84a9, 0x1f75, + 0x84aa, 0x29b7, + 0x84c5, 0x1fbe, + 0x84c6, 0x29d2, + 0x84d3, 0x1ecd, + 0x84d4, 0x29df, + 0x84d5, 0x21a9, + 0x84d6, 0x29e0, + 0x84d7, 0x21e6, + 0x84d8, 0x29e1, + 0x84d9, 0x2127, + 0x84da, 0x2003, + 0x84db, 0x29e2, + 0x84dd, 0x2132, + 0x84de, 0x29e4, + 0x84ea, 0x2323, + 0x84eb, 0x29f0, + 0x84ee, 0x2011, + 0x84ef, 0x29f3, + 0x84f1, 0x20f5, + 0x84f2, 0x29f5, + 0x8540, 0x2a02, + 0x8551, 0x22c5, + 0x8552, 0x1f5e, + 0x8553, 0x2a13, + 0x8554, 0x22c6, + 0x8555, 0x2a14, + 0x855e, 0x20ef, + 0x855f, 0x2a1d, + 0x8566, 0x21d0, + 0x8567, 0x2a24, + 0x8580, 0x2a3c, + 0x8587, 0x22c1, + 0x8588, 0x2a43, + 0x858b, 0x1e64, + 0x858c, 0x2a46, + 0x8592, 0x21f9, + 0x8593, 0x2a4c, + 0x8596, 0x2010, + 0x8597, 0x2a4f, + 0x8598, 0x22c2, + 0x8599, 0x2a50, + 0x85a2, 0x1e5a, + 0x85a3, 0x2a59, + 0x85b2, 0x1ea2, + 0x85b3, 0x2a68, + 0x8640, 0x2ab4, + 0x864a, 0x236d, + 0x864b, 0x2abe, + 0x8654, 0x2247, + 0x8655, 0x2ac7, + 0x8668, 0x236c, + 0x8669, 0x2ada, + 0x8680, 0x2af0, + 0x8696, 0x219c, + 0x8697, 0x2b06, + 0x8699, 0x20c9, + 0x869a, 0x2b08, + 0x86a1, 0x21f0, + 0x86a2, 0x2b0f, + 0x86ca, 0x210b, + 0x86cb, 0x2b37, + 0x86cc, 0x20de, + 0x86cd, 0x2b38, + 0x86ce, 0x1eaa, + 0x86cf, 0x2b39, + 0x86d1, 0x222c, + 0x86d2, 0x2b3b, + 0x86dc, 0x20d8, + 0x86dd, 0x22c0, + 0x86de, 0x2b45, + 0x86e1, 0x206f, + 0x86e2, 0x2b48, + 0x86e8, 0x21a1, + 0x86e9, 0x2b4e, + 0x86ee, 0x2379, + 0x86ef, 0x2b53, + 0x86f4, 0x2372, + 0x86f5, 0x2b58, + 0x8740, 0x216a, + 0x8741, 0x2b62, + 0x8744, 0x237c, + 0x8745, 0x2b65, + 0x8749, 0x20b0, + 0x874a, 0x2b69, + 0x874b, 0x237a, + 0x874c, 0x1e74, + 0x874d, 0x2b6a, + 0x874f, 0x2377, + 0x8750, 0x2b6c, + 0x8757, 0x1f4c, + 0x8758, 0x2b73, + 0x875a, 0x2378, + 0x875b, 0x21cf, + 0x875c, 0x2368, + 0x875d, 0x2b75, + 0x875e, 0x2371, + 0x875f, 0x2b76, + 0x8760, 0x2369, + 0x8761, 0x2b77, + 0x8766, 0x2674, + 0x8767, 0x2b7c, + 0x877a, 0x236f, + 0x877b, 0x2b8f, + 0x877d, 0x2370, + 0x877e, 0x2b91, + 0x8780, 0x2b92, + 0x8781, 0x2376, + 0x8782, 0x2373, + 0x8783, 0x2b93, + 0x8786, 0x237f, + 0x8787, 0x2b96, + 0x8788, 0x2374, + 0x8789, 0x2b97, + 0x878a, 0x20b5, + 0x878b, 0x2b98, + 0x878d, 0x1edb, + 0x878e, 0x2672, + 0x878f, 0x2b9a, + 0x8793, 0x236e, + 0x8794, 0x2b9e, + 0x8798, 0x21b7, + 0x8799, 0x2ba2, + 0x879d, 0x2375, + 0x879e, 0x2ba6, + 0x87a3, 0x2382, + 0x87a4, 0x2bab, + 0x87a7, 0x209e, + 0x87a8, 0x2bae, + 0x87b3, 0x236b, + 0x87b4, 0x2bb9, + 0x87b5, 0x2039, + 0x87b6, 0x2bba, + 0x87bb, 0x269f, + 0x87bc, 0x2bbf, + 0x87bf, 0x237d, + 0x87c0, 0x21f5, + 0x87c1, 0x2bc2, + 0x87c2, 0x2381, + 0x87c3, 0x2bc3, + 0x87ca, 0x237b, + 0x87cb, 0x237e, + 0x87cc, 0x21cc, + 0x87cd, 0x2bca, + 0x87cf, 0x22db, + 0x87d0, 0x2bcc, + 0x87d2, 0x236a, + 0x87d3, 0x2689, + 0x87d4, 0x2bce, + 0x87d5, 0x2697, + 0x87d6, 0x2bcf, + 0x87da, 0x22a1, + 0x87db, 0x2bd3, + 0x87f7, 0x2383, + 0x87f8, 0x1f3d, + 0x87f9, 0x2bef, + 0x87fa, 0x218f, + 0x87fb, 0x2bf0, + 0x8840, 0x2246, + 0x8841, 0x2248, + 0x8842, 0x2bf4, + 0x8844, 0x217e, + 0x8845, 0x2bf6, + 0x8846, 0x2180, + 0x8847, 0x2bf7, + 0x8880, 0x2c2f, + 0x88ba, 0x232a, + 0x88bb, 0x2c69, + 0x88cc, 0x228b, + 0x88cd, 0x2c7a, + 0x88d4, 0x1f85, + 0x88d5, 0x2c81, + 0x88d7, 0x2325, + 0x88d8, 0x2c83, + 0x88df, 0x232c, + 0x88e0, 0x2c8a, + 0x88e5, 0x232e, + 0x88e6, 0x2c8f, + 0x88f2, 0x2205, + 0x88f3, 0x1e38, + 0x88f4, 0x2c9b, + 0x88f6, 0x1e73, + 0x88f7, 0x2c9d, + 0x8940, 0x2ca5, + 0x894b, 0x1fe3, + 0x894c, 0x2339, + 0x894d, 0x2cb0, + 0x894e, 0x232b, + 0x894f, 0x2cb1, + 0x8950, 0x232d, + 0x8951, 0x2cb2, + 0x8954, 0x217f, + 0x8955, 0x2cb5, + 0x895d, 0x21a7, + 0x895e, 0x2cbd, + 0x895f, 0x232f, + 0x8960, 0x2cbe, + 0x896d, 0x1e7d, + 0x896e, 0x2ccb, + 0x8971, 0x20d6, + 0x8972, 0x2cce, + 0x897c, 0x1ec2, + 0x897d, 0x2cd8, + 0x8980, 0x2cda, + 0x898b, 0x22b2, + 0x898c, 0x2ce5, + 0x8999, 0x1edf, + 0x899a, 0x2cf2, + 0x899e, 0x1ef9, + 0x899f, 0x2cf6, + 0x89a6, 0x20d9, + 0x89a7, 0x2cfd, + 0x89a8, 0x1fdd, + 0x89a9, 0x2cfe, + 0x89af, 0x2167, + 0x89b0, 0x2d04, + 0x89ba, 0x21ed, + 0x89bb, 0x2d0e, + 0x89be, 0x2007, + 0x89bf, 0x2326, + 0x89c0, 0x2329, + 0x89c1, 0x2d11, + 0x89c4, 0x1f52, + 0x89c5, 0x203b, + 0x89c6, 0x2328, + 0x89c7, 0x2d14, + 0x89c8, 0x2327, + 0x89c9, 0x2d15, + 0x89ce, 0x1e2b, + 0x89cf, 0x2d1a, + 0x89d1, 0x22ae, + 0x89d2, 0x2d1c, + 0x89d8, 0x1f49, + 0x89d9, 0x2d22, + 0x89db, 0x2138, + 0x89dc, 0x2d24, + 0x89f4, 0x2081, + 0x89f5, 0x2d3c, + 0x8a40, 0x2d46, + 0x8a41, 0x1f7c, + 0x8a42, 0x2d47, + 0x8a59, 0x235b, + 0x8a5a, 0x1ede, + 0x8a5b, 0x2d5e, + 0x8a5c, 0x1fa2, + 0x8a5d, 0x2d5f, + 0x8a5e, 0x1efa, + 0x8a5f, 0x2d60, + 0x8a79, 0x22ad, + 0x8a7a, 0x2d7a, + 0x8a80, 0x2d7f, + 0x8ae4, 0x203f, + 0x8ae5, 0x2de3, + 0x8b40, 0x2dfd, + 0x8b44, 0x1f0e, + 0x8b45, 0x2e01, + 0x8b49, 0x23f9, + 0x8b4a, 0x2e05, + 0x8b7a, 0x23fc, + 0x8b7b, 0x2e35, + 0x8b80, 0x2e39, + 0x8b8c, 0x2069, + 0x8b8d, 0x2e45, + 0x8b9e, 0x23f7, + 0x8b9f, 0x2e56, + 0x8bb3, 0x23f6, + 0x8bb4, 0x2e6a, + 0x8bb9, 0x23fd, + 0x8bba, 0x2e6f, + 0x8bbe, 0x23f8, + 0x8bbf, 0x2e73, + 0x8bc6, 0x23fa, + 0x8bc7, 0x2e7a, + 0x8bc8, 0x23fe, + 0x8bc9, 0x1fa8, + 0x8bca, 0x2e7b, + 0x8bd4, 0x2401, + 0x8bd5, 0x2e85, + 0x8bdc, 0x23ff, + 0x8bdd, 0x2e8c, + 0x8be5, 0x2400, + 0x8be6, 0x2e94, + 0x8beb, 0x2221, + 0x8bec, 0x2e99, + 0x8bf0, 0x2122, + 0x8bf1, 0x2e9d, + 0x8c40, 0x2eab, + 0x8c44, 0x23fb, + 0x8c45, 0x2eaf, + 0x8c4f, 0x215a, + 0x8c50, 0x2eb9, + 0x8c57, 0x21e5, + 0x8c58, 0x2ec0, + 0x8c5c, 0x2057, + 0x8c5d, 0x2ec4, + 0x8c80, 0x2ee6, + 0x8c8b, 0x20e5, + 0x8c8c, 0x2ef1, + 0x8c8d, 0x212f, + 0x8c8e, 0x20a3, + 0x8c8f, 0x2121, + 0x8c90, 0x2ef2, + 0x8c91, 0x21d4, + 0x8c92, 0x1fe5, + 0x8c93, 0x2ef3, + 0x8c99, 0x1e8a, + 0x8c9a, 0x1e37, + 0x8c9b, 0x2ef9, + 0x8ca2, 0x1f9e, + 0x8ca3, 0x22a6, + 0x8ca4, 0x21e8, + 0x8ca5, 0x2f00, + 0x8ca6, 0x1eda, + 0x8ca7, 0x1eb9, + 0x8ca8, 0x2f01, + 0x8cc0, 0x235c, + 0x8cc1, 0x2f19, + 0x8cd2, 0x2050, + 0x8cd3, 0x1e67, + 0x8cd4, 0x2f2a, + 0x8cd5, 0x23f4, + 0x8cd6, 0x2f2b, + 0x8cd9, 0x213e, + 0x8cda, 0x2f2e, + 0x8cf9, 0x1f16, + 0x8cfa, 0x2f4d, + 0x8d40, 0x2f52, + 0x8d73, 0x2389, + 0x8d74, 0x2f85, + 0x8d75, 0x1eb7, + 0x8d76, 0x2f86, + 0x8d7b, 0x21b4, + 0x8d7c, 0x2f8b, + 0x8d80, 0x2f8e, + 0x8d88, 0x238f, + 0x8d89, 0x2f96, + 0x8d8f, 0x1f1a, + 0x8d90, 0x2f9c, + 0x8d9e, 0x238b, + 0x8d9f, 0x2faa, + 0x8db9, 0x238a, + 0x8dba, 0x2fc4, + 0x8de2, 0x2391, + 0x8de3, 0x2fec, + 0x8de4, 0x2271, + 0x8de5, 0x2fed, + 0x8de7, 0x2388, + 0x8de8, 0x2fef, + 0x8df7, 0x238e, + 0x8df8, 0x2ffe, + 0x8dfe, 0x238d, + 0x8e40, 0x3004, + 0x8e46, 0x238c, + 0x8e47, 0x300a, + 0x8e56, 0x2390, + 0x8e57, 0x3019, + 0x8e58, 0x2033, + 0x8e59, 0x301a, + 0x8e5a, 0x223c, + 0x8e5b, 0x301b, + 0x8e68, 0x1fe9, + 0x8e69, 0x3028, + 0x8e6e, 0x2055, + 0x8e6f, 0x302d, + 0x8e70, 0x2392, + 0x8e71, 0x302e, + 0x8e80, 0x2324, + 0x8e81, 0x303c, + 0x8e9b, 0x2143, + 0x8e9c, 0x3056, + 0x8e9f, 0x2129, + 0x8ea0, 0x3059, + 0x8ea4, 0x2277, + 0x8ea5, 0x305d, + 0x8ea7, 0x1ea7, + 0x8ea8, 0x305f, + 0x8eac, 0x2285, + 0x8ead, 0x3063, + 0x8eae, 0x2384, + 0x8eaf, 0x3064, + 0x8ebd, 0x2387, + 0x8ebe, 0x2386, + 0x8ebf, 0x3072, + 0x8ec3, 0x2290, + 0x8ec4, 0x3076, + 0x8ec5, 0x1e44, + 0x8ec6, 0x3077, + 0x8ecd, 0x1e32, + 0x8ece, 0x2385, + 0x8ecf, 0x307e, + 0x8ed6, 0x1f13, + 0x8ed7, 0x1f73, + 0x8ed8, 0x3085, + 0x8eec, 0x1fe0, + 0x8eed, 0x3099, + 0x8f40, 0x30ab, + 0x8f52, 0x2087, + 0x8f53, 0x1e78, + 0x8f54, 0x23ae, + 0x8f55, 0x1ef6, + 0x8f56, 0x1f31, + 0x8f57, 0x30bd, + 0x8f5d, 0x2045, + 0x8f5e, 0x30c3, + 0x8f64, 0x2178, + 0x8f65, 0x30c9, + 0x8f80, 0x30e3, + 0x8f86, 0x23f5, + 0x8f87, 0x30e9, + 0x8f88, 0x2275, + 0x8f89, 0x30ea, + 0x8f95, 0x266e, + 0x8f96, 0x30f6, + 0x8f97, 0x1eb0, + 0x8f98, 0x30f7, + 0x8f9b, 0x2083, + 0x8f9c, 0x30fa, + 0x8f9d, 0x2188, + 0x8f9e, 0x30fb, + 0x8fa1, 0x267c, + 0x8fa2, 0x30fe, + 0x8fbd, 0x1fc5, + 0x8fbe, 0x3119, + 0x8fc4, 0x1ea1, + 0x8fc5, 0x311f, + 0x8fc6, 0x2393, + 0x8fc7, 0x3120, + 0x8fcd, 0x1f0b, + 0x8fce, 0x3126, + 0x8fd8, 0x1e7c, + 0x8fd9, 0x3130, + 0x9040, 0x3156, + 0x9080, 0x3195, + 0x909d, 0x23b4, + 0x909e, 0x207e, + 0x909f, 0x31b2, + 0x90ba, 0x1ee3, + 0x90bb, 0x31cd, + 0x90c0, 0x2095, + 0x90c1, 0x23bb, + 0x90c2, 0x31d2, + 0x90c5, 0x23b9, + 0x90c6, 0x31d5, + 0x90db, 0x1e28, + 0x90dc, 0x23bd, + 0x90dd, 0x31ea, + 0x90ed, 0x23b5, + 0x90ee, 0x31fa, + 0x90f0, 0x23ba, + 0x90f1, 0x31fc, + 0x90f7, 0x23b3, + 0x90f8, 0x3202, + 0x9140, 0x3209, + 0x9142, 0x2162, + 0x9143, 0x320b, + 0x914b, 0x1e5e, + 0x914c, 0x3213, + 0x914d, 0x1e5d, + 0x914e, 0x3214, + 0x9151, 0x23b7, + 0x9152, 0x3217, + 0x9154, 0x1f2f, + 0x9155, 0x24df, + 0x9156, 0x3219, + 0x9159, 0x23b2, + 0x915a, 0x214e, + 0x915b, 0x321c, + 0x915d, 0x2052, + 0x915e, 0x321e, + 0x9161, 0x23bc, + 0x9162, 0x3221, + 0x9163, 0x20eb, + 0x9164, 0x3222, + 0x916e, 0x2232, + 0x916f, 0x322c, + 0x9176, 0x1e3f, + 0x9177, 0x3233, + 0x917a, 0x201b, + 0x917b, 0x20bc, + 0x917c, 0x23be, + 0x917d, 0x3236, + 0x9180, 0x3238, + 0x9184, 0x1eae, + 0x9185, 0x323c, + 0x918d, 0x1efb, + 0x918e, 0x3244, + 0x9191, 0x2089, + 0x9192, 0x3247, + 0x9193, 0x23b1, + 0x9194, 0x3248, + 0x9197, 0x21c4, + 0x9198, 0x324b, + 0x919b, 0x2214, + 0x919c, 0x324e, + 0x91a9, 0x1fde, + 0x91aa, 0x2223, + 0x91ab, 0x23b6, + 0x91ac, 0x325b, + 0x91ba, 0x268c, + 0x91bb, 0x24de, + 0x91bc, 0x3269, + 0x91bf, 0x24e0, + 0x91c0, 0x326c, + 0x91c3, 0x23b8, + 0x91c4, 0x326f, + 0x91cd, 0x1e81, + 0x91ce, 0x3278, + 0x91d0, 0x1ffe, + 0x91d1, 0x1f51, + 0x91d2, 0x21e1, + 0x91d3, 0x327a, + 0x91d4, 0x23b0, + 0x91d5, 0x327b, + 0x91d6, 0x1fce, + 0x91d7, 0x327c, + 0x91d8, 0x211e, + 0x91d9, 0x2021, + 0x91da, 0x327d, + 0x91df, 0x24e1, + 0x91e0, 0x3282, + 0x91e2, 0x24a3, + 0x91e3, 0x3284, + 0x91ea, 0x24a4, + 0x91eb, 0x328b, + 0x91f0, 0x2273, + 0x91f1, 0x3290, + 0x91f2, 0x21b0, + 0x91f3, 0x3291, + 0x9240, 0x329d, + 0x9280, 0x32dc, + 0x92b6, 0x21d1, + 0x92b7, 0x3312, + 0x92ce, 0x211c, + 0x92cf, 0x3329, + 0x92d0, 0x235d, + 0x92d1, 0x332a, + 0x92d4, 0x2682, + 0x92d5, 0x332d, + 0x92df, 0x210d, + 0x92e0, 0x205a, + 0x92e1, 0x3337, + 0x92fe, 0x1f8d, + 0x9340, 0x3354, + 0x9350, 0x21ff, + 0x9351, 0x3364, + 0x935d, 0x1f58, + 0x935e, 0x3370, + 0x9370, 0x215b, + 0x9371, 0x3382, + 0x9376, 0x1eb6, + 0x9377, 0x3387, + 0x9380, 0x338f, + 0x938c, 0x20db, + 0x938d, 0x339b, + 0x939d, 0x2360, + 0x939e, 0x33ab, + 0x93a5, 0x2361, + 0x93a6, 0x33b2, + 0x93a7, 0x2040, + 0x93a8, 0x33b3, + 0x93b4, 0x228e, + 0x93b5, 0x33bf, + 0x93b8, 0x1fdf, + 0x93b9, 0x33c2, + 0x93bb, 0x235e, + 0x93bc, 0x33c4, + 0x93bd, 0x1e6a, + 0x93be, 0x33c5, + 0x93c6, 0x2002, + 0x93c7, 0x33cd, + 0x93cf, 0x2093, + 0x93d0, 0x33d5, + 0x93d7, 0x235f, + 0x93d8, 0x33dc, + 0x93db, 0x1eac, + 0x93dc, 0x1e54, + 0x93dd, 0x33df, + 0x93e1, 0x1f08, + 0x93e2, 0x33e3, + 0x93e4, 0x20c0, + 0x93e5, 0x2362, + 0x93e6, 0x33e5, + 0x93e9, 0x2160, + 0x93ea, 0x33e8, + 0x93eb, 0x219d, + 0x93ec, 0x1f8e, + 0x93ed, 0x222d, + 0x93ee, 0x33e9, + 0x93ef, 0x2047, + 0x93f0, 0x33ea, + 0x93f1, 0x2262, + 0x93f2, 0x33eb, + 0x93f4, 0x1f67, + 0x93f5, 0x1eb2, + 0x93f6, 0x33ed, + 0x93fa, 0x1ea9, + 0x93fb, 0x33f1, + 0x93fe, 0x1fcc, + 0x9440, 0x33f4, + 0x9444, 0x1f72, + 0x9445, 0x33f8, + 0x944d, 0x2098, + 0x944e, 0x3400, + 0x9450, 0x1e52, + 0x9451, 0x20a4, + 0x9452, 0x1f1c, + 0x9453, 0x228f, + 0x9454, 0x3402, + 0x9455, 0x1fed, + 0x9456, 0x3403, + 0x9458, 0x2365, + 0x9459, 0x3405, + 0x945b, 0x1e2d, + 0x945c, 0x2152, + 0x945d, 0x2366, + 0x945e, 0x3407, + 0x945f, 0x20fa, + 0x9460, 0x3408, + 0x9464, 0x2363, + 0x9465, 0x340c, + 0x9466, 0x209a, + 0x9467, 0x340d, + 0x946e, 0x203c, + 0x946f, 0x3414, + 0x9472, 0x1ff6, + 0x9473, 0x3417, + 0x9474, 0x2364, + 0x9475, 0x3418, + 0x9476, 0x1e69, + 0x9477, 0x3419, + 0x9478, 0x2367, + 0x9479, 0x341a, + 0x947a, 0x211d, + 0x947b, 0x341b, + 0x9480, 0x2259, + 0x9481, 0x2056, + 0x9482, 0x2163, + 0x9483, 0x341f, + 0x9487, 0x1fa9, + 0x9488, 0x1ffc, + 0x9489, 0x3423, + 0x94a1, 0x1e2e, + 0x94a2, 0x343b, + 0x94b3, 0x1ebc, + 0x94b4, 0x344c, + 0x94b5, 0x2142, + 0x94b6, 0x344d, + 0x94bf, 0x201e, + 0x94c0, 0x1e43, + 0x94c1, 0x3456, + 0x94cc, 0x24d4, + 0x94cd, 0x3461, + 0x94d8, 0x226f, + 0x94d9, 0x346c, + 0x94e0, 0x1ed7, + 0x94e1, 0x3473, + 0x9540, 0x3491, + 0x9572, 0x212d, + 0x9573, 0x34c3, + 0x9580, 0x34cf, + 0x9583, 0x229b, + 0x9584, 0x34d2, + 0x959e, 0x2256, + 0x959f, 0x24a8, + 0x95a0, 0x34ec, + 0x95b3, 0x1e79, + 0x95b4, 0x34ff, + 0x95ba, 0x225a, + 0x95bb, 0x3505, + 0x95cf, 0x24a7, + 0x95d0, 0x3519, + 0x95d1, 0x2686, + 0x95d2, 0x24a6, + 0x95d3, 0x351a, + 0x95d4, 0x21ce, + 0x95d5, 0x351b, + 0x95e1, 0x24a9, + 0x95e2, 0x3527, + 0x95e7, 0x1fe7, + 0x95e8, 0x352c, + 0x95f1, 0x2112, + 0x95f2, 0x3535, + 0x95f8, 0x213c, + 0x95f9, 0x353b, + 0x95fe, 0x1f5c, + 0x9640, 0x3540, + 0x9656, 0x24c4, + 0x9657, 0x3556, + 0x967c, 0x1ecc, + 0x967d, 0x357b, + 0x9680, 0x357d, + 0x9740, 0x35fc, + 0x9767, 0x246a, + 0x9768, 0x3623, + 0x976c, 0x2175, + 0x976d, 0x3627, + 0x976e, 0x246d, + 0x976f, 0x3628, + 0x9780, 0x3638, + 0x9796, 0x246b, + 0x9797, 0x225f, + 0x9798, 0x364e, + 0x979d, 0x1ece, + 0x979e, 0x3653, + 0x97a3, 0x2272, + 0x97a4, 0x3658, + 0x97bf, 0x2473, + 0x97c0, 0x3673, + 0x97ee, 0x21fe, + 0x97ef, 0x36a1, + 0x97f7, 0x1efe, + 0x97f8, 0x36a9, + 0x9840, 0x36b0, + 0x9845, 0x2475, + 0x9846, 0x36b5, + 0x9849, 0x220a, + 0x984a, 0x36b8, + 0x984f, 0x1f6f, + 0x9850, 0x36bd, + 0x9871, 0x2468, + 0x9872, 0x36de, + 0x9873, 0x2100, + 0x9874, 0x36df, + 0x9880, 0x36ea, + 0x9881, 0x2476, + 0x9882, 0x36eb, + 0x988b, 0x1f27, + 0x988c, 0x20d7, + 0x988d, 0x36f4, + 0x98a0, 0x247c, + 0x98a1, 0x3707, + 0x98aa, 0x1fa1, + 0x98ab, 0x3710, + 0x98b6, 0x22aa, + 0x98b7, 0x2005, + 0x98b8, 0x371b, + 0x98ba, 0x246c, + 0x98bb, 0x371d, + 0x98c7, 0x203e, + 0x98c8, 0x3729, + 0x98cb, 0x1e4c, + 0x98cc, 0x372c, + 0x98d0, 0x213a, + 0x98d1, 0x3730, + 0x98d3, 0x2204, + 0x98d4, 0x3732, + 0x98e3, 0x20c3, + 0x98e4, 0x2140, + 0x98e5, 0x2477, + 0x98e6, 0x3741, + 0x98ef, 0x2474, + 0x98f0, 0x374a, + 0x98f2, 0x20dd, + 0x98f3, 0x374c, + 0x9940, 0x3758, + 0x9943, 0x1f68, + 0x9944, 0x375b, + 0x9945, 0x2185, + 0x9946, 0x375c, + 0x9966, 0x2472, + 0x9967, 0x377c, + 0x996e, 0x1eb5, + 0x996f, 0x3783, + 0x9975, 0x2478, + 0x9976, 0x3789, + 0x997a, 0x1f8b, + 0x997b, 0x2484, + 0x997c, 0x378d, + 0x9980, 0x3790, + 0x9985, 0x2699, + 0x9986, 0x3795, + 0x9989, 0x2482, + 0x998a, 0x3798, + 0x998e, 0x20a1, + 0x998f, 0x379c, + 0x9991, 0x1f92, + 0x9992, 0x379e, + 0x9999, 0x1f38, + 0x999a, 0x37a5, + 0x99a9, 0x2485, + 0x99aa, 0x37b4, + 0x99b0, 0x2480, + 0x99b1, 0x246e, + 0x99b2, 0x37ba, + 0x99b3, 0x247b, + 0x99b4, 0x2486, + 0x99b5, 0x2471, + 0x99b6, 0x37bb, + 0x99bd, 0x2483, + 0x99be, 0x2470, + 0x99bf, 0x37c2, + 0x99c0, 0x2469, + 0x99c1, 0x37c3, + 0x99c2, 0x247f, + 0x99c3, 0x37c4, + 0x99c9, 0x246f, + 0x99ca, 0x37ca, + 0x99ce, 0x2481, + 0x99cf, 0x37ce, + 0x99d1, 0x2220, + 0x99d2, 0x37d0, + 0x99da, 0x1ff5, + 0x99db, 0x37d8, + 0x99e0, 0x20f4, + 0x99e1, 0x37dd, + 0x99e5, 0x247d, + 0x99e6, 0x37e1, + 0x99e8, 0x2479, + 0x99e9, 0x37e3, + 0x99ec, 0x247e, + 0x99ed, 0x37e6, + 0x99f4, 0x247a, + 0x99f5, 0x37ed, + 0x9a40, 0x37f7, + 0x9a4a, 0x20e3, + 0x9a4b, 0x3801, + 0x9a57, 0x20ad, + 0x9a58, 0x380d, + 0x9a65, 0x24cb, + 0x9a66, 0x381a, + 0x9a67, 0x1f53, + 0x9a68, 0x381b, + 0x9a71, 0x2159, + 0x9a72, 0x3824, + 0x9a76, 0x2013, + 0x9a77, 0x1f33, + 0x9a78, 0x3828, + 0x9a80, 0x382f, + 0x9a88, 0x1e5c, + 0x9a89, 0x3837, + 0x9a8c, 0x2488, + 0x9a8d, 0x383a, + 0x9a91, 0x2487, + 0x9a92, 0x383e, + 0x9a97, 0x248a, + 0x9a98, 0x3843, + 0x9a9a, 0x2489, + 0x9a9b, 0x248b, + 0x9a9c, 0x3845, + 0x9a9e, 0x1f83, + 0x9a9f, 0x3847, + 0x9aa2, 0x210f, + 0x9aa3, 0x1fdb, + 0x9aa4, 0x384a, + 0x9aaa, 0x20af, + 0x9aab, 0x3850, + 0x9ad0, 0x24c0, + 0x9ad1, 0x3875, + 0x9ad6, 0x226d, + 0x9ad7, 0x387a, + 0x9ada, 0x24c1, + 0x9adb, 0x387d, + 0x9ae2, 0x20ca, + 0x9ae3, 0x3884, + 0x9ae4, 0x20e7, + 0x9ae5, 0x24c2, + 0x9ae6, 0x3885, + 0x9b40, 0x389e, + 0x9b80, 0x38dd, + 0x9bd1, 0x23dc, + 0x9bd2, 0x392e, + 0x9bdc, 0x23db, + 0x9bdd, 0x3938, + 0x9c40, 0x395a, + 0x9c53, 0x205e, + 0x9c54, 0x396d, + 0x9c59, 0x2244, + 0x9c5a, 0x23e2, + 0x9c5b, 0x3972, + 0x9c5c, 0x20d4, + 0x9c5d, 0x3973, + 0x9c75, 0x219f, + 0x9c76, 0x398b, + 0x9c79, 0x1e66, + 0x9c7a, 0x398e, + 0x9c80, 0x3993, + 0x9c86, 0x1f63, + 0x9c87, 0x3999, + 0x9c9d, 0x23dd, + 0x9c9e, 0x39af, + 0x9cab, 0x216b, + 0x9cac, 0x39bc, + 0x9cca, 0x22b5, + 0x9ccb, 0x39da, + 0x9ccf, 0x1f26, + 0x9cd0, 0x39de, + 0x9ce6, 0x1e63, + 0x9ce7, 0x2088, + 0x9ce8, 0x39f4, + 0x9cec, 0x1ebd, + 0x9ced, 0x39f8, + 0x9cee, 0x2341, + 0x9cef, 0x39f9, + 0x9cfb, 0x1f4b, + 0x9cfc, 0x3a05, + 0x9cfe, 0x2292, + 0x9d40, 0x3a07, + 0x9d42, 0x2124, + 0x9d43, 0x3a09, + 0x9d46, 0x2048, + 0x9d47, 0x23e0, + 0x9d48, 0x3a0c, + 0x9d4d, 0x2077, + 0x9d4e, 0x3a11, + 0x9d4f, 0x223a, + 0x9d50, 0x3a12, + 0x9d61, 0x20b1, + 0x9d62, 0x3a23, + 0x9d68, 0x1f41, + 0x9d69, 0x201c, + 0x9d6a, 0x3a29, + 0x9d6e, 0x22b8, + 0x9d6f, 0x3a2d, + 0x9d71, 0x2276, + 0x9d72, 0x3a2f, + 0x9d75, 0x1f9b, + 0x9d76, 0x3a32, + 0x9d7b, 0x1f9f, + 0x9d7c, 0x3a37, + 0x9d7d, 0x25ca, + 0x9d7e, 0x3a38, + 0x9d80, 0x3a39, + 0x9d8a, 0x20be, + 0x9d8b, 0x3a43, + 0x9d8d, 0x1fb4, + 0x9d8e, 0x3a45, + 0x9d91, 0x23d7, + 0x9d92, 0x3a48, + 0x9d99, 0x2105, + 0x9d9a, 0x3a4f, + 0x9da1, 0x23e1, + 0x9da2, 0x1fec, + 0x9da3, 0x3a56, + 0x9da7, 0x23ea, + 0x9da8, 0x3a5a, + 0x9dac, 0x23e3, + 0x9dad, 0x210e, + 0x9dae, 0x3a5e, + 0x9db2, 0x1fa6, + 0x9db3, 0x2004, + 0x9db4, 0x3a62, + 0x9dbe, 0x1f9d, + 0x9dbf, 0x3a6c, + 0x9dc6, 0x23e5, + 0x9dc7, 0x3a73, + 0x9dc9, 0x2264, + 0x9dca, 0x3a75, + 0x9dcd, 0x24e2, + 0x9dce, 0x3a78, + 0x9dd2, 0x23de, + 0x9dd3, 0x3a7c, + 0x9dd5, 0x1ec4, + 0x9dd6, 0x3a7e, + 0x9de1, 0x22b6, + 0x9de2, 0x20a9, + 0x9de3, 0x3a89, + 0x9df1, 0x212b, + 0x9df2, 0x3a97, + 0x9df4, 0x20a5, + 0x9df5, 0x3a99, + 0x9df7, 0x268b, + 0x9df8, 0x3a9b, + 0x9dfa, 0x1f76, + 0x9dfb, 0x3a9d, + 0x9dfd, 0x216d, + 0x9dfe, 0x3a9f, + 0x9e40, 0x3aa0, + 0x9e45, 0x2001, + 0x9e46, 0x3aa5, + 0x9e48, 0x2191, + 0x9e49, 0x1e50, + 0x9e4a, 0x3aa7, + 0x9e52, 0x1f9c, + 0x9e53, 0x3aaf, + 0x9e54, 0x23da, + 0x9e55, 0x3ab0, + 0x9e56, 0x2053, + 0x9e57, 0x3ab1, + 0x9e5d, 0x23e9, + 0x9e5e, 0x23e4, + 0x9e5f, 0x3ab7, + 0x9e61, 0x21d5, + 0x9e62, 0x3ab9, + 0x9e63, 0x23e6, + 0x9e64, 0x3aba, + 0x9e67, 0x23df, + 0x9e68, 0x3abd, + 0x9e6c, 0x1e4f, + 0x9e6d, 0x3ac1, + 0x9e6f, 0x23d9, + 0x9e70, 0x3ac3, + 0x9e72, 0x2014, + 0x9e73, 0x3ac5, + 0x9e74, 0x23ec, + 0x9e75, 0x23eb, + 0x9e76, 0x3ac6, + 0x9e7b, 0x23d8, + 0x9e7c, 0x23ee, + 0x9e7d, 0x3acb, + 0x9e80, 0x3acd, + 0x9e85, 0x268e, + 0x9e86, 0x3ad2, + 0x9e87, 0x23ed, + 0x9e88, 0x3ad3, + 0x9e91, 0x1ffa, + 0x9e92, 0x3adc, + 0x9e96, 0x23d6, + 0x9e97, 0x23e8, + 0x9e98, 0x3ae0, + 0x9ea2, 0x2106, + 0x9ea3, 0x3aea, + 0x9ea6, 0x200b, + 0x9ea7, 0x3aed, + 0x9ea9, 0x2166, + 0x9eaa, 0x3aef, + 0x9eae, 0x23ef, + 0x9eaf, 0x3af3, + 0x9eb3, 0x2189, + 0x9eb4, 0x2058, + 0x9eb5, 0x3af7, + 0x9eb7, 0x23e7, + 0x9eb8, 0x3af9, + 0x9ef5, 0x21a3, + 0x9ef6, 0x3b36, + 0x9f40, 0x3b3f, + 0x9f4e, 0x217a, + 0x9f4f, 0x3b4d, + 0x9f6f, 0x21a5, + 0x9f70, 0x3b6d, + 0x9f80, 0x3b7c, + 0x9f92, 0x2022, + 0x9f93, 0x3b8e, + 0x9f98, 0x24d6, + 0x9f99, 0x3b93, + 0x9fa6, 0x233a, + 0x9fa7, 0x3ba0, + 0x9fa9, 0x1eee, + 0x9faa, 0x3ba2, + 0x9fac, 0x24d5, + 0x9fad, 0x3ba4, + 0x9fc9, 0x2228, + 0x9fca, 0x3bc0, + 0x9fcd, 0x24d7, + 0x9fce, 0x3bc3, + 0x9fe1, 0x20fc, + 0x9fe2, 0x3bd6, + 0x9feb, 0x1e87, + 0x9fec, 0x3bdf, + 0x9fee, 0x24d8, + 0x9fef, 0x3be1, + 0x9ff4, 0x1eba, + 0x9ff5, 0x3be6, + 0x9ffd, 0x2119, + 0x9ffe, 0x3bee, + 0xa040, 0x3bef, + 0xa043, 0x216c, + 0xa044, 0x3bf2, + 0xa046, 0x24d9, + 0xa047, 0x3bf4, + 0xa049, 0x2227, + 0xa04a, 0x3bf6, + 0xa04e, 0x1e5f, + 0xa04f, 0x3bfa, + 0xa054, 0x229f, + 0xa055, 0x3bff, + 0xa05a, 0x1f5d, + 0xa05b, 0x3c04, + 0xa061, 0x1fbc, + 0xa062, 0x3c0a, + 0xa063, 0x24da, + 0xa064, 0x3c0b, + 0xa071, 0x2149, + 0xa072, 0x3c18, + 0xa074, 0x2046, + 0xa075, 0x3c1a, + 0xa080, 0x2000, + 0xa081, 0x3c24, + 0xa091, 0x2190, + 0xa092, 0x3c34, + 0xa094, 0x2208, + 0xa095, 0x3c36, + 0xa096, 0x1ee6, + 0xa097, 0x3c37, + 0xa0a9, 0x24c3, + 0xa0aa, 0x3c49, + 0xa0bf, 0x20cc, + 0xa0c0, 0x3c5e, + 0xa0ce, 0x2340, + 0xa0cf, 0x3c6c, + 0xa0d9, 0x1ed1, + 0xa0da, 0x3c76, + 0xa0de, 0x21ac, + 0xa0df, 0x3c7a, + 0xa0ee, 0x22af, + 0xa0ef, 0x3c89, + 0xa1a1, 0x0060, + 0xa2a1, 0x26a9, + 0xa2b1, 0x00be, + 0xa2e5, 0x00f0, + 0xa2f1, 0x00fa, + 0xa3a1, 0x0106, + 0xa4a1, 0x0164, + 0xa5a1, 0x01b7, + 0xa6a1, 0x020d, + 0xa6c1, 0x0225, + 0xa7a1, 0x025a, + 0xa7d1, 0x027b, + 0xa840, 0x26b3, + 0xa880, 0x26f2, + 0xa8a1, 0x029c, + 0xa8c5, 0x02bc, + 0xa940, 0x2708, + 0xa959, 0x2720, + 0xa95c, 0x2722, + 0xa960, 0x2723, + 0xa980, 0x2742, + 0xa996, 0x1e17, + 0xa9a4, 0x02e2, + 0xaa40, 0x3c99, + 0xaa4d, 0x21b6, + 0xaa4e, 0x1e3d, + 0xaa4f, 0x3ca6, + 0xaa71, 0x2235, + 0xaa72, 0x3cc8, + 0xaa73, 0x2397, + 0xaa74, 0x3cc9, + 0xaa77, 0x2395, + 0xaa78, 0x3ccc, + 0xaa7a, 0x223f, + 0xaa7b, 0x212a, + 0xaa7c, 0x3cce, + 0xaa80, 0x3cd1, + 0xaa9a, 0x1ed2, + 0xaa9b, 0x3ceb, + 0xaa9c, 0x2396, + 0xaa9d, 0x2398, + 0xaa9e, 0x3cec, + 0xaa9f, 0x20a2, + 0xaaa0, 0x3ced, + 0xaaa1, 0x032e, + 0xab40, 0x1f64, + 0xab41, 0x3cee, + 0xab43, 0x202b, + 0xab44, 0x3cf0, + 0xab45, 0x2394, + 0xab46, 0x2139, + 0xab47, 0x3cf1, + 0xab48, 0x215f, + 0xab49, 0x21c1, + 0xab4a, 0x239a, + 0xab4b, 0x3cf2, + 0xab4d, 0x2399, + 0xab4e, 0x3cf4, + 0xab80, 0x3d25, + 0xaba1, 0x038c, + 0xac40, 0x3d46, + 0xac46, 0x21c0, + 0xac47, 0x3d4c, + 0xac71, 0x2460, + 0xac72, 0x3d76, + 0xac7c, 0x245c, + 0xac7d, 0x3d80, + 0xac80, 0x3d82, + 0xac8d, 0x215d, + 0xac8e, 0x3d8f, + 0xac93, 0x2225, + 0xac94, 0x206a, + 0xac95, 0x3d94, + 0xad40, 0x3da0, + 0xad49, 0x2461, + 0xad4a, 0x3da9, + 0xad5e, 0x245b, + 0xad5f, 0x3dbd, + 0xad61, 0x2462, + 0xad62, 0x3dbf, + 0xad68, 0x1f54, + 0xad69, 0x3dc5, + 0xad74, 0x245f, + 0xad75, 0x3dd0, + 0xad80, 0x3dda, + 0xad82, 0x20ec, + 0xad83, 0x3ddc, + 0xad87, 0x245d, + 0xad88, 0x3de0, + 0xad8b, 0x2463, + 0xad8c, 0x3de3, + 0xad91, 0x2464, + 0xad92, 0x3de8, + 0xae40, 0x3df7, + 0xae54, 0x24a5, + 0xae55, 0x3e0b, + 0xae62, 0x1e70, + 0xae63, 0x3e18, + 0xae80, 0x208f, + 0xae81, 0x3e34, + 0xae85, 0x1e42, + 0xae86, 0x3e38, + 0xae8b, 0x1f4e, + 0xae8c, 0x3e3d, + 0xae94, 0x1eb1, + 0xae95, 0x3e45, + 0xaea0, 0x1e8b, + 0xaf40, 0x3e50, + 0xaf64, 0x1fc6, + 0xaf65, 0x3e74, + 0xaf7b, 0x25ae, + 0xaf7c, 0x3e8a, + 0xaf80, 0x3e8d, + 0xaf82, 0x1f01, + 0xaf83, 0x2200, + 0xaf84, 0x3e8f, + 0xaf8e, 0x25b2, + 0xaf8f, 0x1e97, + 0xaf90, 0x3e99, + 0xaf91, 0x20ab, + 0xaf92, 0x3e9a, + 0xaf9c, 0x25b3, + 0xaf9d, 0x3ea4, + 0xaf9f, 0x2028, + 0xafa0, 0x3ea6, + 0xb040, 0x3ea7, + 0xb041, 0x25af, + 0xb043, 0x3ea8, + 0xb044, 0x25b1, + 0xb045, 0x3ea9, + 0xb04f, 0x25ac, + 0xb050, 0x3eb3, + 0xb054, 0x1e4e, + 0xb055, 0x3eb7, + 0xb057, 0x2202, + 0xb058, 0x25ab, + 0xb059, 0x2286, + 0xb05a, 0x3eb9, + 0xb05b, 0x25ad, + 0xb05c, 0x3eba, + 0xb05d, 0x25b6, + 0xb05e, 0x3ebb, + 0xb05f, 0x21e3, + 0xb060, 0x25b4, + 0xb062, 0x222f, + 0xb063, 0x2165, + 0xb064, 0x25b7, + 0xb065, 0x3ebc, + 0xb06c, 0x1ee9, + 0xb06d, 0x3ec3, + 0xb07d, 0x1e25, + 0xb07e, 0x3ed3, + 0xb080, 0x3ed4, + 0xb097, 0x25c0, + 0xb098, 0x3eeb, + 0xb099, 0x229a, + 0xb09a, 0x3eec, + 0xb0a1, 0x03ac, + 0xb140, 0x3ef3, + 0xb14b, 0x226e, + 0xb14c, 0x3efe, + 0xb14d, 0x1fbd, + 0xb14e, 0x3eff, + 0xb14f, 0x1f84, + 0xb150, 0x20b2, + 0xb151, 0x3f00, + 0xb152, 0x2043, + 0xb153, 0x3f01, + 0xb180, 0x3f2d, + 0xb197, 0x2684, + 0xb198, 0x3f44, + 0xb1a1, 0x040a, + 0xb240, 0x3f4d, + 0xb241, 0x24ef, + 0xb242, 0x3f4e, + 0xb267, 0x24ee, + 0xb268, 0x3f73, + 0xb26d, 0x2074, + 0xb26e, 0x3f78, + 0xb274, 0x2687, + 0xb275, 0x3f7e, + 0xb280, 0x24f0, + 0xb281, 0x3f88, + 0xb289, 0x268d, + 0xb28a, 0x3f90, + 0xb29a, 0x22a0, + 0xb29b, 0x3fa0, + 0xb2a1, 0x0468, + 0xb340, 0x3fa6, + 0xb343, 0x1fab, + 0xb344, 0x3fa9, + 0xb370, 0x26a8, + 0xb371, 0x3fd5, + 0xb380, 0x3fe3, + 0xb388, 0x24e9, + 0xb389, 0x3feb, + 0xb38c, 0x24e5, + 0xb38d, 0x3fee, + 0xb38e, 0x21fa, + 0xb38f, 0x3fef, + 0xb3a1, 0x04c6, + 0xb440, 0x4001, + 0xb454, 0x2148, + 0xb455, 0x4015, + 0xb458, 0x24e4, + 0xb459, 0x4018, + 0xb45e, 0x24e6, + 0xb45f, 0x20f7, + 0xb460, 0x401d, + 0xb461, 0x206b, + 0xb462, 0x401e, + 0xb475, 0x22a7, + 0xb476, 0x4031, + 0xb47e, 0x24ec, + 0xb480, 0x4039, + 0xb483, 0x24eb, + 0xb484, 0x403c, + 0xb489, 0x24e3, + 0xb48a, 0x4041, + 0xb493, 0x24ea, + 0xb494, 0x404a, + 0xb4a1, 0x0524, + 0xb540, 0x4057, + 0xb541, 0x1e92, + 0xb542, 0x4058, + 0xb54b, 0x1e27, + 0xb54c, 0x4061, + 0xb556, 0x1fe6, + 0xb557, 0x406b, + 0xb55a, 0x24e7, + 0xb55b, 0x2012, + 0xb55c, 0x1eec, + 0xb55d, 0x406e, + 0xb561, 0x24e8, + 0xb562, 0x4072, + 0xb580, 0x408f, + 0xb59c, 0x1f66, + 0xb59d, 0x24dc, + 0xb59e, 0x40ab, + 0xb5a1, 0x0582, + 0xb640, 0x40ae, + 0xb652, 0x26a2, + 0xb653, 0x40c0, + 0xb655, 0x24dd, + 0xb656, 0x40c2, + 0xb659, 0x200e, + 0xb65a, 0x40c5, + 0xb65b, 0x24db, + 0xb65c, 0x1eb8, + 0xb65d, 0x40c6, + 0xb680, 0x40e8, + 0xb6a1, 0x05e0, + 0xb740, 0x4109, + 0xb74e, 0x2295, + 0xb74f, 0x4117, + 0xb751, 0x1e80, + 0xb752, 0x4119, + 0xb759, 0x2677, + 0xb75a, 0x4120, + 0xb764, 0x2624, + 0xb765, 0x1f69, + 0xb766, 0x222b, + 0xb767, 0x412a, + 0xb777, 0x257f, + 0xb778, 0x1f5b, + 0xb779, 0x413a, + 0xb780, 0x219b, + 0xb781, 0x4140, + 0xb782, 0x267d, + 0xb783, 0x4141, + 0xb7a1, 0x063e, + 0xb840, 0x415f, + 0xb843, 0x21a0, + 0xb844, 0x2186, + 0xb845, 0x4162, + 0xb846, 0x20ed, + 0xb847, 0x4163, + 0xb84d, 0x25b9, + 0xb84e, 0x4169, + 0xb851, 0x1fea, + 0xb852, 0x416c, + 0xb85a, 0x1ea4, + 0xb85b, 0x20e1, + 0xb85c, 0x4174, + 0xb85d, 0x25b8, + 0xb85e, 0x2260, + 0xb85f, 0x4175, + 0xb860, 0x20e2, + 0xb861, 0x4176, + 0xb877, 0x2141, + 0xb878, 0x418c, + 0xb880, 0x4193, + 0xb882, 0x1fc7, + 0xb883, 0x4195, + 0xb8a1, 0x069c, + 0xb940, 0x41b3, + 0xb950, 0x1e41, + 0xb951, 0x41c3, + 0xb961, 0x25e4, + 0xb962, 0x41d3, + 0xb97b, 0x1f86, + 0xb97c, 0x41ec, + 0xb980, 0x41ef, + 0xb99d, 0x1fb3, + 0xb99e, 0x420c, + 0xb9a0, 0x1eef, + 0xb9a1, 0x06fa, + 0xba40, 0x420e, + 0xba42, 0x22a4, + 0xba43, 0x4210, + 0xba44, 0x25e8, + 0xba45, 0x4211, + 0xba56, 0x25e3, + 0xba57, 0x4222, + 0xba59, 0x2111, + 0xba5a, 0x4224, + 0xba60, 0x25e6, + 0xba61, 0x422a, + 0xba6a, 0x25e7, + 0xba6b, 0x4233, + 0xba74, 0x2041, + 0xba75, 0x423c, + 0xba80, 0x4246, + 0xba84, 0x25ea, + 0xba85, 0x424a, + 0xba86, 0x1f8f, + 0xba87, 0x424b, + 0xba88, 0x25ec, + 0xba89, 0x424c, + 0xba8d, 0x25eb, + 0xba8e, 0x4250, + 0xba9e, 0x20d0, + 0xba9f, 0x201d, + 0xbaa0, 0x4260, + 0xbaa1, 0x0758, + 0xbb40, 0x1ff7, + 0xbb41, 0x4261, + 0xbb49, 0x1e8d, + 0xbb4a, 0x4269, + 0xbb58, 0x25e9, + 0xbb59, 0x4277, + 0xbb5b, 0x25ee, + 0xbb5c, 0x203a, + 0xbb5d, 0x4279, + 0xbb60, 0x2693, + 0xbb61, 0x427c, + 0xbb65, 0x25e5, + 0xbb66, 0x25ed, + 0xbb67, 0x4280, + 0xbb68, 0x2009, + 0xbb69, 0x4281, + 0xbb6a, 0x2065, + 0xbb6b, 0x4282, + 0xbb6e, 0x26a3, + 0xbb6f, 0x4285, + 0xbb80, 0x4295, + 0xbba1, 0x07b6, + 0xbc40, 0x42b6, + 0xbc52, 0x25f5, + 0xbc53, 0x1efc, + 0xbc54, 0x42c8, + 0xbc5a, 0x2024, + 0xbc5b, 0x42ce, + 0xbc61, 0x269b, + 0xbc62, 0x42d4, + 0xbc63, 0x25f3, + 0xbc64, 0x42d5, + 0xbc65, 0x22d9, + 0xbc66, 0x42d6, + 0xbc67, 0x25f4, + 0xbc68, 0x42d7, + 0xbc69, 0x241b, + 0xbc6a, 0x42d8, + 0xbc6d, 0x1fc8, + 0xbc6e, 0x42db, + 0xbc6f, 0x1f7b, + 0xbc70, 0x42dc, + 0xbc71, 0x241d, + 0xbc72, 0x42dd, + 0xbc73, 0x224c, + 0xbc74, 0x1f48, + 0xbc75, 0x241c, + 0xbc76, 0x241e, + 0xbc78, 0x20ff, + 0xbc79, 0x219a, + 0xbc7a, 0x42de, + 0xbc7b, 0x2091, + 0xbc7c, 0x42df, + 0xbc7e, 0x20a7, + 0xbc80, 0x42e1, + 0xbc82, 0x2423, + 0xbc83, 0x1e9b, + 0xbc84, 0x2422, + 0xbc85, 0x42e3, + 0xbc86, 0x2110, + 0xbc87, 0x42e4, + 0xbc88, 0x228d, + 0xbc89, 0x1f71, + 0xbc8a, 0x1ef8, + 0xbc8b, 0x2421, + 0xbc8c, 0x42e5, + 0xbc8f, 0x1ef3, + 0xbc90, 0x42e8, + 0xbc9a, 0x21b1, + 0xbc9b, 0x2426, + 0xbc9c, 0x2425, + 0xbc9d, 0x2120, + 0xbc9e, 0x42f2, + 0xbca1, 0x0814, + 0xbd40, 0x42f5, + 0xbd42, 0x211a, + 0xbd43, 0x2424, + 0xbd44, 0x42f7, + 0xbd45, 0x2428, + 0xbd46, 0x42f8, + 0xbd48, 0x242a, + 0xbd49, 0x2429, + 0xbd4a, 0x42fa, + 0xbd4b, 0x2294, + 0xbd4c, 0x42fb, + 0xbd4d, 0x22be, + 0xbd4e, 0x42fc, + 0xbd4f, 0x1e31, + 0xbd50, 0x42fd, + 0xbd57, 0x242c, + 0xbd58, 0x4304, + 0xbd59, 0x1fb5, + 0xbd5a, 0x4305, + 0xbd66, 0x242b, + 0xbd67, 0x1faf, + 0xbd68, 0x4311, + 0xbd6a, 0x2068, + 0xbd6b, 0x21e4, + 0xbd6c, 0x4313, + 0xbd6f, 0x1f21, + 0xbd70, 0x4316, + 0xbd71, 0x2101, + 0xbd72, 0x4317, + 0xbd79, 0x217c, + 0xbd7a, 0x214a, + 0xbd7b, 0x242d, + 0xbd7c, 0x431e, + 0xbd7e, 0x1fd4, + 0xbd80, 0x4320, + 0xbd81, 0x1fd1, + 0xbd82, 0x4321, + 0xbd89, 0x1e33, + 0xbd8a, 0x4328, + 0xbd8b, 0x242f, + 0xbd8c, 0x4329, + 0xbd8e, 0x242e, + 0xbd8f, 0x432b, + 0xbd90, 0x2430, + 0xbd91, 0x21db, + 0xbd92, 0x432c, + 0xbd97, 0x2158, + 0xbd98, 0x4331, + 0xbd9b, 0x1fc2, + 0xbd9c, 0x4334, + 0xbda1, 0x0872, + 0xbe40, 0x4339, + 0xbe43, 0x22b9, + 0xbe44, 0x433c, + 0xbe45, 0x2436, + 0xbe46, 0x433d, + 0xbe49, 0x1e8e, + 0xbe4a, 0x2439, + 0xbe4b, 0x4340, + 0xbe51, 0x21c5, + 0xbe52, 0x2437, + 0xbe53, 0x2192, + 0xbe54, 0x4346, + 0xbe55, 0x243a, + 0xbe56, 0x1f19, + 0xbe57, 0x218c, + 0xbe58, 0x1e40, + 0xbe59, 0x22b3, + 0xbe5a, 0x4347, + 0xbe5d, 0x205f, + 0xbe5e, 0x2438, + 0xbe5f, 0x2432, + 0xbe60, 0x2274, + 0xbe61, 0x434a, + 0xbe62, 0x1e9c, + 0xbe63, 0x2431, + 0xbe64, 0x2085, + 0xbe65, 0x434b, + 0xbe69, 0x2435, + 0xbe6a, 0x434f, + 0xbe6c, 0x243b, + 0xbe6d, 0x4351, + 0xbe6f, 0x1fb7, + 0xbe70, 0x2433, + 0xbe71, 0x4353, + 0xbe76, 0x2054, + 0xbe77, 0x21de, + 0xbe78, 0x4358, + 0xbe79, 0x2434, + 0xbe7a, 0x4359, + 0xbe7c, 0x243d, + 0xbe7d, 0x1f89, + 0xbe7e, 0x243c, + 0xbe80, 0x435b, + 0xbe83, 0x1f6e, + 0xbe84, 0x1ed8, + 0xbe85, 0x435e, + 0xbe86, 0x1ebf, + 0xbe87, 0x2445, + 0xbe88, 0x435f, + 0xbe89, 0x2249, + 0xbe8a, 0x4360, + 0xbe8c, 0x2441, + 0xbe8d, 0x4362, + 0xbe8e, 0x1e47, + 0xbe8f, 0x1f56, + 0xbe90, 0x4363, + 0xbe92, 0x2086, + 0xbe93, 0x4365, + 0xbe95, 0x2196, + 0xbe96, 0x4367, + 0xbe97, 0x2443, + 0xbe98, 0x243f, + 0xbe99, 0x4368, + 0xbe9a, 0x2023, + 0xbe9b, 0x4369, + 0xbe9c, 0x2442, + 0xbe9d, 0x436a, + 0xbe9f, 0x243e, + 0xbea0, 0x436c, + 0xbea1, 0x08d0, + 0xbf40, 0x26a6, + 0xbf41, 0x436d, + 0xbf4d, 0x234e, + 0xbf4e, 0x2446, + 0xbf4f, 0x244b, + 0xbf50, 0x2444, + 0xbf51, 0x4379, + 0xbf55, 0x2427, + 0xbf56, 0x244c, + 0xbf57, 0x437d, + 0xbf60, 0x1f0f, + 0xbf61, 0x4386, + 0xbf62, 0x2447, + 0xbf63, 0x2449, + 0xbf64, 0x2448, + 0xbf65, 0x4387, + 0xbf68, 0x21c2, + 0xbf69, 0x438a, + 0xbf6c, 0x216e, + 0xbf6d, 0x438d, + 0xbf70, 0x1f03, + 0xbf71, 0x4390, + 0xbf72, 0x244a, + 0xbf73, 0x215c, + 0xbf74, 0x4391, + 0xbf76, 0x22bb, + 0xbf77, 0x2450, + 0xbf78, 0x4393, + 0xbf79, 0x2694, + 0xbf7a, 0x244f, + 0xbf7b, 0x25f6, + 0xbf7c, 0x2051, + 0xbf7d, 0x4394, + 0xbf7e, 0x244e, + 0xbf80, 0x4395, + 0xbf82, 0x22ba, + 0xbf83, 0x1f6d, + 0xbf84, 0x4397, + 0xbf89, 0x2452, + 0xbf8a, 0x2451, + 0xbf8b, 0x439c, + 0xbf95, 0x2455, + 0xbf96, 0x43a6, + 0xbf97, 0x2289, + 0xbf98, 0x2116, + 0xbf99, 0x43a7, + 0xbf9d, 0x2454, + 0xbf9e, 0x43ab, + 0xbfa1, 0x092e, + 0xc040, 0x20fb, + 0xc041, 0x43ae, + 0xc044, 0x2440, + 0xc045, 0x43b1, + 0xc04b, 0x2126, + 0xc04c, 0x1f61, + 0xc04d, 0x269d, + 0xc04e, 0x43b7, + 0xc04f, 0x1f8a, + 0xc050, 0x2456, + 0xc051, 0x2459, + 0xc052, 0x2458, + 0xc053, 0x43b8, + 0xc055, 0x1fae, + 0xc056, 0x43ba, + 0xc05b, 0x221a, + 0xc05c, 0x43bf, + 0xc05e, 0x1f7a, + 0xc05f, 0x244d, + 0xc060, 0x2457, + 0xc061, 0x43c1, + 0xc069, 0x2453, + 0xc06a, 0x43c9, + 0xc06b, 0x2420, + 0xc06c, 0x43ca, + 0xc06d, 0x21df, + 0xc06e, 0x2685, + 0xc06f, 0x43cb, + 0xc070, 0x1e6e, + 0xc071, 0x43cc, + 0xc074, 0x2224, + 0xc075, 0x2670, + 0xc076, 0x43cf, + 0xc077, 0x21ba, + 0xc078, 0x43d0, + 0xc079, 0x245a, + 0xc07a, 0x43d1, + 0xc07c, 0x1fff, + 0xc07d, 0x43d3, + 0xc080, 0x43d5, + 0xc09b, 0x25e2, + 0xc09c, 0x43f0, + 0xc09d, 0x269a, + 0xc09e, 0x43f1, + 0xc0a1, 0x098c, + 0xc140, 0x43f4, + 0xc150, 0x1eea, + 0xc151, 0x4404, + 0xc154, 0x1e2c, + 0xc155, 0x4407, + 0xc15f, 0x2062, + 0xc160, 0x24f1, + 0xc161, 0x4411, + 0xc162, 0x24f2, + 0xc163, 0x4412, + 0xc175, 0x25f2, + 0xc176, 0x4424, + 0xc178, 0x2215, + 0xc179, 0x4426, + 0xc180, 0x442c, + 0xc195, 0x21ae, + 0xc196, 0x4441, + 0xc1a1, 0x09ea, + 0xc240, 0x444c, + 0xc24e, 0x20e0, + 0xc24f, 0x445a, + 0xc265, 0x25c2, + 0xc266, 0x4470, + 0xc267, 0x25c1, + 0xc268, 0x4471, + 0xc27d, 0x2128, + 0xc27e, 0x4486, + 0xc280, 0x4487, + 0xc284, 0x2199, + 0xc285, 0x448b, + 0xc293, 0x2017, + 0xc294, 0x1ea0, + 0xc295, 0x2125, + 0xc296, 0x214d, + 0xc297, 0x4499, + 0xc298, 0x25c4, + 0xc299, 0x209d, + 0xc29a, 0x228a, + 0xc29b, 0x449a, + 0xc29c, 0x25c3, + 0xc29d, 0x449b, + 0xc2a0, 0x2179, + 0xc2a1, 0x0a48, + 0xc340, 0x2038, + 0xc341, 0x449e, + 0xc343, 0x2155, + 0xc344, 0x44a0, + 0xc37b, 0x21d2, + 0xc37c, 0x44d7, + 0xc380, 0x44da, + 0xc384, 0x24c7, + 0xc385, 0x44de, + 0xc39b, 0x2279, + 0xc39c, 0x44f4, + 0xc3a1, 0x0aa6, + 0xc440, 0x44f9, + 0xc449, 0x2123, + 0xc44a, 0x4502, + 0xc44c, 0x24c5, + 0xc44d, 0x4504, + 0xc454, 0x24c9, + 0xc455, 0x450b, + 0xc458, 0x2094, + 0xc459, 0x450e, + 0xc45b, 0x2296, + 0xc45c, 0x4510, + 0xc463, 0x1e77, + 0xc464, 0x4517, + 0xc477, 0x1f06, + 0xc478, 0x452a, + 0xc47a, 0x1fa5, + 0xc47b, 0x452c, + 0xc480, 0x4530, + 0xc481, 0x2099, + 0xc482, 0x4531, + 0xc491, 0x1ead, + 0xc492, 0x24c8, + 0xc493, 0x20a8, + 0xc494, 0x4540, + 0xc498, 0x201f, + 0xc499, 0x4544, + 0xc49a, 0x20c5, + 0xc49b, 0x4545, + 0xc49c, 0x24ca, + 0xc49d, 0x4546, + 0xc4a1, 0x0b04, + 0xc540, 0x454a, + 0xc544, 0x1ff0, + 0xc545, 0x454e, + 0xc546, 0x24c6, + 0xc547, 0x454f, + 0xc54b, 0x225d, + 0xc54c, 0x22de, + 0xc54d, 0x4553, + 0xc552, 0x202c, + 0xc553, 0x4558, + 0xc55f, 0x2161, + 0xc560, 0x4564, + 0xc563, 0x223b, + 0xc564, 0x21d9, + 0xc565, 0x1fcb, + 0xc566, 0x1fc9, + 0xc567, 0x4567, + 0xc580, 0x457f, + 0xc593, 0x1e61, + 0xc594, 0x4592, + 0xc59c, 0x25ef, + 0xc59d, 0x459a, + 0xc59e, 0x1f98, + 0xc59f, 0x459b, + 0xc5a1, 0x0b62, + 0xc640, 0x459d, + 0xc641, 0x25f0, + 0xc642, 0x459e, + 0xc644, 0x1f88, + 0xc645, 0x45a0, + 0xc647, 0x21f8, + 0xc648, 0x45a2, + 0xc663, 0x2322, + 0xc664, 0x45bd, + 0xc672, 0x2336, + 0xc673, 0x45cb, + 0xc680, 0x45d7, + 0xc6a1, 0x0bc0, + 0xc740, 0x45f8, + 0xc766, 0x22ab, + 0xc767, 0x461e, + 0xc76f, 0x1fbf, + 0xc770, 0x4626, + 0xc776, 0x1f7d, + 0xc777, 0x462c, + 0xc77b, 0x2333, + 0xc77c, 0x4630, + 0xc780, 0x4633, + 0xc7a1, 0x0c1e, + 0xc840, 0x4654, + 0xc841, 0x1f4d, + 0xc842, 0x4655, + 0xc84f, 0x2334, + 0xc850, 0x4662, + 0xc852, 0x1ff1, + 0xc853, 0x4664, + 0xc866, 0x218b, + 0xc867, 0x4677, + 0xc86e, 0x2349, + 0xc86f, 0x467e, + 0xc87e, 0x220b, + 0xc880, 0x468d, + 0xc887, 0x2346, + 0xc888, 0x4694, + 0xc892, 0x2347, + 0xc893, 0x469e, + 0xc894, 0x2193, + 0xc895, 0x469f, + 0xc899, 0x26a1, + 0xc89a, 0x46a3, + 0xc89d, 0x1f62, + 0xc89e, 0x46a6, + 0xc8a1, 0x0c7c, + 0xc940, 0x46a9, + 0xc94f, 0x234d, + 0xc950, 0x2348, + 0xc951, 0x46b8, + 0xc96e, 0x1e60, + 0xc96f, 0x46d5, + 0xc970, 0x2345, + 0xc971, 0x46d6, + 0xc977, 0x1f12, + 0xc978, 0x46dc, + 0xc980, 0x46e3, + 0xc98f, 0x2018, + 0xc990, 0x2335, + 0xc991, 0x46f2, + 0xc99c, 0x233c, + 0xc99d, 0x46fd, + 0xc9a1, 0x0cda, + 0xca40, 0x4701, + 0xca4e, 0x266f, + 0xca4f, 0x470f, + 0xca56, 0x2351, + 0xca57, 0x4716, + 0xca59, 0x1fa0, + 0xca5a, 0x4718, + 0xca5c, 0x2338, + 0xca5d, 0x471a, + 0xca61, 0x221b, + 0xca62, 0x471e, + 0xca6e, 0x2342, + 0xca6f, 0x472a, + 0xca72, 0x234f, + 0xca73, 0x472d, + 0xca77, 0x233d, + 0xca78, 0x4731, + 0xca7b, 0x2344, + 0xca7c, 0x2331, + 0xca7d, 0x4734, + 0xca7e, 0x234b, + 0xca80, 0x4735, + 0xca81, 0x233b, + 0xca82, 0x4736, + 0xca89, 0x2350, + 0xca8a, 0x473d, + 0xca8e, 0x1eb4, + 0xca8f, 0x21a6, + 0xca90, 0x4741, + 0xca92, 0x21cb, + 0xca93, 0x4743, + 0xca9a, 0x2355, + 0xca9b, 0x474a, + 0xcaa1, 0x0d38, + 0xcb40, 0x4750, + 0xcb43, 0x233e, + 0xcb44, 0x4753, + 0xcb45, 0x1f74, + 0xcb46, 0x4754, + 0xcb47, 0x2330, + 0xcb48, 0x4755, + 0xcb4b, 0x2680, + 0xcb4c, 0x4758, + 0xcb4e, 0x20da, + 0xcb4f, 0x475a, + 0xcb57, 0x234a, + 0xcb58, 0x4762, + 0xcb5d, 0x1f91, + 0xcb5e, 0x4767, + 0xcb5f, 0x2107, + 0xcb60, 0x4768, + 0xcb6a, 0x233f, + 0xcb6b, 0x4772, + 0xcb7b, 0x1ff4, + 0xcb7c, 0x2343, + 0xcb7d, 0x4782, + 0xcb80, 0x4784, + 0xcb87, 0x2212, + 0xcb88, 0x478b, + 0xcb8e, 0x2207, + 0xcb8f, 0x4791, + 0xcb92, 0x2359, + 0xcb93, 0x4794, + 0xcb9c, 0x2254, + 0xcb9d, 0x479d, + 0xcb9e, 0x2332, + 0xcb9f, 0x479e, + 0xcba1, 0x0d96, + 0xcc40, 0x1e26, + 0xcc41, 0x2357, + 0xcc42, 0x47a0, + 0xcc49, 0x2358, + 0xcc4a, 0x2042, + 0xcc4b, 0x2153, + 0xcc4c, 0x47a7, + 0xcc4f, 0x20bb, + 0xcc50, 0x47aa, + 0xcc5c, 0x235a, + 0xcc5d, 0x47b6, + 0xcc60, 0x2356, + 0xcc61, 0x47b9, + 0xcc64, 0x2337, + 0xcc65, 0x47bc, + 0xcc6d, 0x1ff9, + 0xcc6e, 0x47c4, + 0xcc79, 0x2353, + 0xcc7a, 0x47cf, + 0xcc7d, 0x2061, + 0xcc7e, 0x47d2, + 0xcc80, 0x47d3, + 0xcc8e, 0x1e95, + 0xcc8f, 0x47e1, + 0xcc94, 0x2049, + 0xcc95, 0x47e6, + 0xcc96, 0x1f42, + 0xcc97, 0x47e7, + 0xcc9d, 0x1fe8, + 0xcc9e, 0x47ed, + 0xcca1, 0x0df4, + 0xcd40, 0x47f0, + 0xcd80, 0x482f, + 0xcd90, 0x25da, + 0xcd91, 0x483f, + 0xcd98, 0x25d7, + 0xcd99, 0x4846, + 0xcda1, 0x0e52, + 0xce40, 0x484e, + 0xce67, 0x212e, + 0xce68, 0x4875, + 0xce72, 0x21b2, + 0xce73, 0x487f, + 0xce80, 0x488b, + 0xce81, 0x219e, + 0xce82, 0x488c, + 0xce87, 0x25dc, + 0xce88, 0x4891, + 0xce9b, 0x206c, + 0xce9c, 0x48a4, + 0xce9e, 0x2226, + 0xce9f, 0x48a6, + 0xcea1, 0x0eb0, + 0xcf40, 0x48a8, + 0xcf4e, 0x25e0, + 0xcf4f, 0x48b6, + 0xcf55, 0x227b, + 0xcf56, 0x48bc, + 0xcf58, 0x25de, + 0xcf59, 0x48be, + 0xcf5c, 0x25e1, + 0xcf5d, 0x48c1, + 0xcf6c, 0x25d5, + 0xcf6d, 0x48d0, + 0xcf73, 0x1e6b, + 0xcf74, 0x48d6, + 0xcf75, 0x25db, + 0xcf76, 0x48d7, + 0xcf78, 0x1e89, + 0xcf79, 0x48d9, + 0xcf7c, 0x25d9, + 0xcf7d, 0x48dc, + 0xcf80, 0x48de, + 0xcf81, 0x2211, + 0xcf82, 0x48df, + 0xcf89, 0x2229, + 0xcf8a, 0x25d6, + 0xcf8b, 0x48e6, + 0xcf93, 0x25dd, + 0xcf94, 0x25df, + 0xcf95, 0x48ee, + 0xcf9e, 0x1fef, + 0xcf9f, 0x48f7, + 0xcfa0, 0x25d8, + 0xcfa1, 0x0f0e, + 0xd040, 0x48f8, + 0xd04d, 0x1f29, + 0xd04e, 0x4905, + 0xd051, 0x1e5b, + 0xd052, 0x4908, + 0xd055, 0x2076, + 0xd056, 0x490b, + 0xd05c, 0x2297, + 0xd05d, 0x4911, + 0xd060, 0x2690, + 0xd061, 0x4914, + 0xd067, 0x213f, + 0xd068, 0x491a, + 0xd06c, 0x2198, + 0xd06d, 0x491e, + 0xd06e, 0x1e88, + 0xd06f, 0x491f, + 0xd07d, 0x228c, + 0xd07e, 0x492d, + 0xd080, 0x492e, + 0xd0a1, 0x0f6c, + 0xd140, 0x494f, + 0xd155, 0x25f1, + 0xd156, 0x4964, + 0xd159, 0x200c, + 0xd15a, 0x4967, + 0xd161, 0x1e58, + 0xd162, 0x22ac, + 0xd163, 0x496e, + 0xd175, 0x26a7, + 0xd176, 0x4980, + 0xd17d, 0x2676, + 0xd17e, 0x4987, + 0xd180, 0x4988, + 0xd19d, 0x1fe1, + 0xd19e, 0x25bb, + 0xd19f, 0x49a5, + 0xd1a1, 0x0fca, + 0xd240, 0x25be, + 0xd241, 0x49a7, + 0xd243, 0x22dd, + 0xd244, 0x49a9, + 0xd24d, 0x25bd, + 0xd24e, 0x49b2, + 0xd25c, 0x1e2a, + 0xd25d, 0x49c0, + 0xd263, 0x25bc, + 0xd264, 0x25ba, + 0xd265, 0x49c6, + 0xd268, 0x25bf, + 0xd269, 0x49c9, + 0xd26d, 0x2187, + 0xd26e, 0x49cd, + 0xd26f, 0x266b, + 0xd270, 0x49ce, + 0xd272, 0x1e7f, + 0xd273, 0x49d0, + 0xd275, 0x21ad, + 0xd276, 0x49d2, + 0xd280, 0x49db, + 0xd28a, 0x1f96, + 0xd28b, 0x49e5, + 0xd28e, 0x1f32, + 0xd28f, 0x49e8, + 0xd292, 0x2084, + 0xd293, 0x49eb, + 0xd295, 0x2136, + 0xd296, 0x49ed, + 0xd297, 0x24b8, + 0xd298, 0x49ee, + 0xd2a0, 0x24ba, + 0xd2a1, 0x1028, + 0xd340, 0x49f6, + 0xd344, 0x24bc, + 0xd345, 0x49fa, + 0xd348, 0x20e4, + 0xd349, 0x49fd, + 0xd34a, 0x24b9, + 0xd34b, 0x49fe, + 0xd34d, 0x24bd, + 0xd34e, 0x4a00, + 0xd350, 0x24be, + 0xd351, 0x4a02, + 0xd355, 0x24bf, + 0xd356, 0x4a06, + 0xd358, 0x1fd2, + 0xd359, 0x4a08, + 0xd35b, 0x1ffd, + 0xd35c, 0x4a0a, + 0xd35d, 0x24bb, + 0xd35e, 0x1f2d, + 0xd35f, 0x4a0b, + 0xd378, 0x2609, + 0xd379, 0x4a24, + 0xd37a, 0x260a, + 0xd37b, 0x4a25, + 0xd37c, 0x1e94, + 0xd37d, 0x4a26, + 0xd380, 0x4a28, + 0xd385, 0x22df, + 0xd386, 0x1ecb, + 0xd387, 0x1f0d, + 0xd388, 0x4a2d, + 0xd38b, 0x1f77, + 0xd38c, 0x4a30, + 0xd38d, 0x21eb, + 0xd38e, 0x4a31, + 0xd38f, 0x22e1, + 0xd390, 0x4a32, + 0xd391, 0x216f, + 0xd392, 0x4a33, + 0xd393, 0x22e0, + 0xd394, 0x4a34, + 0xd396, 0x21ea, + 0xd397, 0x4a36, + 0xd398, 0x22e2, + 0xd399, 0x20cb, + 0xd39a, 0x4a37, + 0xd39b, 0x1f78, + 0xd39c, 0x4a38, + 0xd39e, 0x1ee2, + 0xd39f, 0x4a3a, + 0xd3a0, 0x21f2, + 0xd3a1, 0x1086, + 0xd440, 0x4a3b, + 0xd441, 0x2150, + 0xd442, 0x4a3c, + 0xd445, 0x1fd3, + 0xd446, 0x4a3f, + 0xd447, 0x22e5, + 0xd448, 0x4a40, + 0xd44c, 0x1ef2, + 0xd44d, 0x4a44, + 0xd44f, 0x211f, + 0xd450, 0x4a46, + 0xd453, 0x21dd, + 0xd454, 0x4a49, + 0xd456, 0x2154, + 0xd457, 0x4a4b, + 0xd458, 0x22e7, + 0xd459, 0x4a4c, + 0xd45c, 0x2282, + 0xd45d, 0x4a4f, + 0xd462, 0x22e6, + 0xd463, 0x4a54, + 0xd467, 0x22e8, + 0xd468, 0x4a58, + 0xd46e, 0x22e4, + 0xd46f, 0x4a5e, + 0xd470, 0x226a, + 0xd471, 0x4a5f, + 0xd472, 0x22eb, + 0xd473, 0x4a60, + 0xd474, 0x22e9, + 0xd475, 0x20bd, + 0xd476, 0x4a61, + 0xd478, 0x22ea, + 0xd479, 0x4a63, + 0xd47b, 0x22bd, + 0xd47c, 0x4a65, + 0xd47e, 0x1e9e, + 0xd480, 0x4a67, + 0xd482, 0x22f6, + 0xd483, 0x21e7, + 0xd484, 0x2216, + 0xd485, 0x4a69, + 0xd487, 0x2137, + 0xd488, 0x4a6b, + 0xd48a, 0x212c, + 0xd48b, 0x4a6d, + 0xd48c, 0x1e68, + 0xd48d, 0x22f2, + 0xd48e, 0x1f37, + 0xd48f, 0x22f3, + 0xd490, 0x4a6e, + 0xd491, 0x22ef, + 0xd492, 0x1f50, + 0xd493, 0x1f10, + 0xd494, 0x21c8, + 0xd495, 0x4a6f, + 0xd496, 0x22f1, + 0xd497, 0x4a70, + 0xd49c, 0x22f0, + 0xd49d, 0x4a75, + 0xd49f, 0x22ee, + 0xd4a0, 0x4a77, + 0xd4a1, 0x10e4, + 0xd540, 0x4a78, + 0xd543, 0x22ed, + 0xd544, 0x229e, + 0xd545, 0x22ec, + 0xd546, 0x1fe2, + 0xd547, 0x4a7b, + 0xd54a, 0x20fe, + 0xd54b, 0x4a7e, + 0xd54e, 0x22f9, + 0xd550, 0x4a81, + 0xd551, 0x1eaf, + 0xd552, 0x4a82, + 0xd554, 0x2236, + 0xd555, 0x4a84, + 0xd556, 0x22f7, + 0xd557, 0x4a85, + 0xd55a, 0x223d, + 0xd55b, 0x4a88, + 0xd55c, 0x1e82, + 0xd55d, 0x1fb6, + 0xd55e, 0x4a89, + 0xd55f, 0x21a4, + 0xd560, 0x21aa, + 0xd561, 0x22f8, + 0xd562, 0x2151, + 0xd563, 0x4a8a, + 0xd564, 0x1f60, + 0xd565, 0x4a8b, + 0xd568, 0x2147, + 0xd569, 0x4a8e, + 0xd56c, 0x2145, + 0xd56d, 0x4a91, + 0xd56e, 0x1fdc, + 0xd56f, 0x4a92, + 0xd572, 0x2301, + 0xd573, 0x4a95, + 0xd575, 0x1ef5, + 0xd576, 0x4a97, + 0xd578, 0x2218, + 0xd579, 0x4a99, + 0xd57b, 0x1ec6, + 0xd57c, 0x4a9b, + 0xd57e, 0x2300, + 0xd580, 0x4a9d, + 0xd581, 0x22b4, + 0xd582, 0x4a9e, + 0xd584, 0x2169, + 0xd585, 0x4aa0, + 0xd586, 0x22fd, + 0xd587, 0x4aa1, + 0xd588, 0x20ea, + 0xd589, 0x4aa2, + 0xd58a, 0x22f4, + 0xd58b, 0x4aa3, + 0xd58c, 0x22fb, + 0xd58d, 0x4aa4, + 0xd58e, 0x22fc, + 0xd58f, 0x2027, + 0xd590, 0x4aa5, + 0xd593, 0x2060, + 0xd594, 0x22ff, + 0xd595, 0x4aa8, + 0xd598, 0x22fe, + 0xd599, 0x1ec7, + 0xd59a, 0x4aab, + 0xd59b, 0x230c, + 0xd59c, 0x4aac, + 0xd59f, 0x22f5, + 0xd5a0, 0x4aaf, + 0xd5a1, 0x1142, + 0xd640, 0x2306, + 0xd641, 0x4ab0, + 0xd642, 0x230a, + 0xd643, 0x21d3, + 0xd644, 0x4ab1, + 0xd647, 0x2303, + 0xd648, 0x4ab4, + 0xd649, 0x2307, + 0xd64a, 0x230b, + 0xd64b, 0x4ab5, + 0xd64d, 0x1f5f, + 0xd64e, 0x4ab7, + 0xd64f, 0x2309, + 0xd650, 0x4ab8, + 0xd652, 0x2302, + 0xd653, 0x1f04, + 0xd654, 0x229d, + 0xd655, 0x4aba, + 0xd656, 0x21fb, + 0xd657, 0x4abb, + 0xd658, 0x2308, + 0xd659, 0x4abc, + 0xd65a, 0x20ac, + 0xd65b, 0x4abd, + 0xd65c, 0x208e, + 0xd65d, 0x2305, + 0xd65e, 0x2197, + 0xd65f, 0x4abe, + 0xd660, 0x2171, + 0xd661, 0x2298, + 0xd662, 0x4abf, + 0xd665, 0x1f57, + 0xd666, 0x4ac2, + 0xd669, 0x2082, + 0xd66a, 0x4ac5, + 0xd66b, 0x2311, + 0xd66c, 0x4ac6, + 0xd66f, 0x2304, + 0xd670, 0x4ac9, + 0xd671, 0x230f, + 0xd672, 0x1e35, + 0xd673, 0x4aca, + 0xd674, 0x20d1, + 0xd675, 0x2310, + 0xd676, 0x1fa3, + 0xd677, 0x4acb, + 0xd678, 0x21d6, + 0xd679, 0x4acc, + 0xd67c, 0x2206, + 0xd67d, 0x4acf, + 0xd680, 0x4ad1, + 0xd683, 0x230d, + 0xd684, 0x4ad4, + 0xd686, 0x2312, + 0xd687, 0x208d, + 0xd688, 0x2313, + 0xd689, 0x4ad6, + 0xd68e, 0x22e3, + 0xd68f, 0x4adb, + 0xd694, 0x1fba, + 0xd695, 0x4ae0, + 0xd699, 0x2078, + 0xd69a, 0x4ae4, + 0xd6a1, 0x11a0, + 0xd740, 0x4aeb, + 0xd743, 0x2288, + 0xd744, 0x4aee, + 0xd748, 0x2316, + 0xd749, 0x1f6b, + 0xd74a, 0x4af2, + 0xd750, 0x2314, + 0xd751, 0x4af8, + 0xd752, 0x2130, + 0xd753, 0x2315, + 0xd754, 0x2168, + 0xd755, 0x4af9, + 0xd756, 0x20c4, + 0xd757, 0x4afa, + 0xd764, 0x2318, + 0xd765, 0x4b07, + 0xd767, 0x2219, + 0xd768, 0x2217, + 0xd769, 0x4b09, + 0xd76c, 0x20d5, + 0xd76d, 0x4b0c, + 0xd76f, 0x1f4a, + 0xd770, 0x4b0e, + 0xd775, 0x2240, + 0xd776, 0x4b13, + 0xd778, 0x1ed3, + 0xd779, 0x4b15, + 0xd780, 0x4b1b, + 0xd783, 0x1e49, + 0xd784, 0x4b1e, + 0xd787, 0x261b, + 0xd788, 0x4b21, + 0xd78b, 0x1e6d, + 0xd78c, 0x20f8, + 0xd78d, 0x4b24, + 0xd78e, 0x1ffb, + 0xd78f, 0x2319, + 0xd790, 0x4b25, + 0xd795, 0x230e, + 0xd796, 0x4b2a, + 0xd797, 0x2317, + 0xd798, 0x4b2b, + 0xd7a1, 0x11fe, + 0xd840, 0x4b34, + 0xd84d, 0x20c8, + 0xd84e, 0x4b41, + 0xd853, 0x1efd, + 0xd854, 0x4b46, + 0xd880, 0x4b71, + 0xd890, 0x1e3b, + 0xd891, 0x227f, + 0xd892, 0x4b81, + 0xd893, 0x1f0c, + 0xd894, 0x1e59, + 0xd895, 0x1f24, + 0xd896, 0x4b82, + 0xd89a, 0x20ba, + 0xd89b, 0x1f65, + 0xd89c, 0x1ef0, + 0xd89d, 0x2164, + 0xd89e, 0x1f30, + 0xd89f, 0x2261, + 0xd8a0, 0x4b86, + 0xd8a1, 0x1257, + 0xd940, 0x4b87, + 0xd941, 0x22a2, + 0xd942, 0x24ab, + 0xd943, 0x4b88, + 0xd944, 0x24af, + 0xd945, 0x1ee8, + 0xd946, 0x1f39, + 0xd947, 0x4b89, + 0xd948, 0x1e48, + 0xd949, 0x2070, + 0xd94a, 0x1ea8, + 0xd94b, 0x4b8a, + 0xd94c, 0x24ac, + 0xd94d, 0x1ef7, + 0xd94e, 0x2176, + 0xd94f, 0x24ad, + 0xd950, 0x4b8b, + 0xd951, 0x207b, + 0xd952, 0x1f45, + 0xd953, 0x24aa, + 0xd954, 0x204b, + 0xd955, 0x202f, + 0xd956, 0x1f5a, + 0xd957, 0x24b0, + 0xd958, 0x4b8c, + 0xd959, 0x22b7, + 0xd95a, 0x1f7f, + 0xd95b, 0x4b8d, + 0xd95c, 0x2265, + 0xd95d, 0x4b8e, + 0xd963, 0x24b2, + 0xd964, 0x211b, + 0xd965, 0x1e51, + 0xd966, 0x4b94, + 0xd967, 0x24b4, + 0xd968, 0x4b95, + 0xd96c, 0x24b3, + 0xd96d, 0x4b99, + 0xd96e, 0x1e9f, + 0xd96f, 0x4b9a, + 0xd970, 0x2118, + 0xd971, 0x4b9b, + 0xd972, 0x20b4, + 0xd973, 0x23af, + 0xd974, 0x21bb, + 0xd975, 0x2072, + 0xd976, 0x1f95, + 0xd977, 0x4b9c, + 0xd978, 0x1f0a, + 0xd979, 0x24b6, + 0xd97a, 0x4b9d, + 0xd97c, 0x2291, + 0xd97d, 0x24b5, + 0xd97e, 0x2278, + 0xd980, 0x1ed4, + 0xd981, 0x4b9f, + 0xd987, 0x1ff3, + 0xd988, 0x4ba5, + 0xd98d, 0x22a9, + 0xd98e, 0x24b7, + 0xd98f, 0x1f28, + 0xd990, 0x2109, + 0xd991, 0x22c7, + 0xd992, 0x4baa, + 0xd997, 0x24ae, + 0xd998, 0x22b1, + 0xd999, 0x4baf, + 0xd99b, 0x2266, + 0xd99c, 0x4bb1, + 0xd99d, 0x225b, + 0xd99e, 0x22c4, + 0xd99f, 0x4bb2, + 0xd9a0, 0x2115, + 0xd9a1, 0x12b5, + 0xda40, 0x4bb3, + 0xda41, 0x222a, + 0xda42, 0x24b1, + 0xda43, 0x4bb4, + 0xda48, 0x213d, + 0xda49, 0x4bb9, + 0xda4d, 0x1f15, + 0xda4e, 0x225c, + 0xda4f, 0x4bbd, + 0xda73, 0x1f14, + 0xda74, 0x4be1, + 0xda77, 0x227a, + 0xda78, 0x4be4, + 0xda80, 0x4beb, + 0xda85, 0x20ee, + 0xda86, 0x4bf0, + 0xda8e, 0x25f8, + 0xda8f, 0x4bf8, + 0xdaa1, 0x1313, + 0xdb40, 0x4c0a, + 0xdb60, 0x1f94, + 0xdb61, 0x4c2a, + 0xdb78, 0x2230, + 0xdb79, 0x4c41, + 0xdb80, 0x4c47, + 0xdb84, 0x25fd, + 0xdb85, 0x4c4b, + 0xdb8b, 0x2600, + 0xdb8c, 0x4c51, + 0xdb98, 0x2606, + 0xdb99, 0x4c5d, + 0xdba1, 0x1371, + 0xdc40, 0x4c65, + 0xdc45, 0x25ff, + 0xdc46, 0x4c6a, + 0xdc4f, 0x25fc, + 0xdc50, 0x1e8c, + 0xdc51, 0x2602, + 0xdc52, 0x4c73, + 0xdc53, 0x224d, + 0xdc54, 0x4c74, + 0xdc55, 0x2604, + 0xdc56, 0x25fe, + 0xdc57, 0x2603, + 0xdc58, 0x4c75, + 0xdc5d, 0x2601, + 0xdc5e, 0x4c7a, + 0xdc62, 0x2605, + 0xdc63, 0x4c7e, + 0xdc66, 0x1ea3, + 0xdc67, 0x2608, + 0xdc68, 0x4c81, + 0xdc6b, 0x2607, + 0xdc6c, 0x4c84, + 0xdc7c, 0x20f0, + 0xdc7d, 0x4c94, + 0xdc80, 0x4c96, + 0xdc87, 0x1e7b, + 0xdc88, 0x2267, + 0xdc89, 0x1f36, + 0xdc8a, 0x1fd6, + 0xdc8b, 0x4c9d, + 0xdc8e, 0x21e0, + 0xdc8f, 0x4ca0, + 0xdc90, 0x248c, + 0xdc91, 0x4ca1, + 0xdc97, 0x248d, + 0xdc98, 0x4ca7, + 0xdc9b, 0x2102, + 0xdc9c, 0x4caa, + 0xdca0, 0x2494, + 0xdca1, 0x13cf, + 0xdd40, 0x4cae, + 0xdd46, 0x2493, + 0xdd47, 0x4cb4, + 0xdd4d, 0x248e, + 0xdd4e, 0x4cba, + 0xdd53, 0x2299, + 0xdd54, 0x2491, + 0xdd55, 0x2496, + 0xdd56, 0x248f, + 0xdd57, 0x2492, + 0xdd58, 0x4cbf, + 0xdd59, 0x2497, + 0xdd5a, 0x4cc0, + 0xdd5e, 0x1fb1, + 0xdd5f, 0x4cc4, + 0xdd60, 0x249a, + 0xdd61, 0x4cc5, + 0xdd62, 0x2499, + 0xdd63, 0x4cc6, + 0xdd64, 0x2258, + 0xdd65, 0x2498, + 0xdd66, 0x4cc7, + 0xdd6d, 0x249b, + 0xdd6e, 0x4cce, + 0xdd6f, 0x1f09, + 0xdd70, 0x20e6, + 0xdd71, 0x4ccf, + 0xdd76, 0x2026, + 0xdd77, 0x249f, + 0xdd78, 0x1f59, + 0xdd79, 0x249d, + 0xdd7b, 0x4cd4, + 0xdd80, 0x4cd8, + 0xdd81, 0x1f3b, + 0xdd82, 0x249c, + 0xdd83, 0x4cd9, + 0xdd85, 0x1e3a, + 0xdd86, 0x205b, + 0xdd87, 0x4cdb, + 0xdd8b, 0x1f70, + 0xdd8c, 0x4cdf, + 0xdd8f, 0x24a0, + 0xdd90, 0x4ce2, + 0xdd94, 0x213b, + 0xdd95, 0x4ce6, + 0xdd97, 0x1f07, + 0xdd98, 0x4ce8, + 0xdd9a, 0x2270, + 0xdd9b, 0x2237, + 0xdd9c, 0x4cea, + 0xdd9e, 0x24d2, + 0xdd9f, 0x4cec, + 0xdda0, 0x21b3, + 0xdda1, 0x142d, + 0xde40, 0x2245, + 0xde41, 0x24a1, + 0xde42, 0x4ced, + 0xde44, 0x22a8, + 0xde45, 0x4cef, + 0xde48, 0x227c, + 0xde49, 0x1fb0, + 0xde4a, 0x4cf2, + 0xde4f, 0x24a2, + 0xde50, 0x4cf7, + 0xde5a, 0x1f46, + 0xde5b, 0x4d01, + 0xde5c, 0x2380, + 0xde5d, 0x2495, + 0xde5e, 0x4d02, + 0xde5f, 0x2490, + 0xde60, 0x4d03, + 0xde6b, 0x1e30, + 0xde6c, 0x4d0e, + 0xde6f, 0x1e9d, + 0xde70, 0x1e4b, + 0xde71, 0x1e4a, + 0xde72, 0x20aa, + 0xde73, 0x4d11, + 0xde80, 0x4d1d, + 0xde92, 0x267b, + 0xde93, 0x4d2f, + 0xde9f, 0x23f2, + 0xdea0, 0x4d3b, + 0xdea1, 0x148b, + 0xdf40, 0x227e, + 0xdf41, 0x4d3c, + 0xdf42, 0x2019, + 0xdf43, 0x4d3d, + 0xdf4d, 0x1fbb, + 0xdf4e, 0x4d47, + 0xdf5c, 0x2253, + 0xdf5d, 0x4d55, + 0xdf5e, 0x1f3e, + 0xdf5f, 0x1ea6, + 0xdf60, 0x218e, + 0xdf61, 0x4d56, + 0xdf64, 0x21ec, + 0xdf65, 0x4d59, + 0xdf66, 0x1ebe, + 0xdf67, 0x4d5a, + 0xdf68, 0x224a, + 0xdf69, 0x4d5b, + 0xdf6d, 0x2133, + 0xdf6e, 0x4d5f, + 0xdf74, 0x1e84, + 0xdf75, 0x4d65, + 0xdf77, 0x20cf, + 0xdf78, 0x21e2, + 0xdf79, 0x4d67, + 0xdf7a, 0x220f, + 0xdf7b, 0x4d68, + 0xdf7c, 0x2029, + 0xdf7d, 0x4d69, + 0xdf7e, 0x2073, + 0xdf80, 0x1f55, + 0xdf81, 0x4d6a, + 0xdf83, 0x23f1, + 0xdf84, 0x4d6c, + 0xdf85, 0x1e46, + 0xdf86, 0x4d6d, + 0xdf89, 0x2063, + 0xdf8a, 0x23f3, + 0xdf8b, 0x4d70, + 0xdfa1, 0x14e9, + 0xe040, 0x4d86, + 0xe050, 0x231e, + 0xe051, 0x4d96, + 0xe05d, 0x2233, + 0xe05e, 0x4da2, + 0xe069, 0x2320, + 0xe06a, 0x4dad, + 0xe06c, 0x21c7, + 0xe06d, 0x4daf, + 0xe075, 0x22bc, + 0xe076, 0x4db7, + 0xe077, 0x231c, + 0xe078, 0x4db8, + 0xe079, 0x2251, + 0xe07a, 0x4db9, + 0xe080, 0x4dbe, + 0xe087, 0x1ebb, + 0xe088, 0x4dc5, + 0xe08d, 0x2287, + 0xe08e, 0x4dca, + 0xe08f, 0x202d, + 0xe090, 0x1eab, + 0xe091, 0x4dcb, + 0xe092, 0x231d, + 0xe093, 0x4dcc, + 0xe094, 0x231f, + 0xe095, 0x4dcd, + 0xe097, 0x231b, + 0xe098, 0x4dcf, + 0xe0a1, 0x1547, + 0xe140, 0x4dd8, + 0xe142, 0x2321, + 0xe143, 0x4dda, + 0xe164, 0x2255, + 0xe165, 0x4dfb, + 0xe168, 0x1e8f, + 0xe169, 0x4dfe, + 0xe174, 0x220c, + 0xe175, 0x1fa4, + 0xe176, 0x4e09, + 0xe180, 0x4e12, + 0xe184, 0x209b, + 0xe185, 0x21d8, + 0xe186, 0x4e16, + 0xe187, 0x25fa, + 0xe188, 0x4e17, + 0xe189, 0x25f9, + 0xe18a, 0x4e18, + 0xe18c, 0x2134, + 0xe18d, 0x4e1a, + 0xe18e, 0x24f3, + 0xe191, 0x24f8, + 0xe192, 0x4e1b, + 0xe193, 0x24f7, + 0xe194, 0x1ec8, + 0xe195, 0x24f6, + 0xe196, 0x4e1c, + 0xe198, 0x2280, + 0xe199, 0x4e1e, + 0xe19e, 0x1ec5, + 0xe19f, 0x24fb, + 0xe1a0, 0x4e23, + 0xe1a1, 0x15a5, + 0xe240, 0x4e24, + 0xe241, 0x24fa, + 0xe242, 0x4e25, + 0xe243, 0x1eed, + 0xe244, 0x4e26, + 0xe24f, 0x24fd, + 0xe250, 0x4e31, + 0xe251, 0x24f9, + 0xe252, 0x4e32, + 0xe253, 0x24fe, + 0xe254, 0x20cd, + 0xe255, 0x4e33, + 0xe25a, 0x2508, + 0xe25b, 0x2504, + 0xe25c, 0x4e38, + 0xe25e, 0x2506, + 0xe25f, 0x4e3a, + 0xe262, 0x24ff, + 0xe263, 0x2090, + 0xe264, 0x4e3d, + 0xe267, 0x1edd, + 0xe268, 0x1f25, + 0xe269, 0x4e40, + 0xe26a, 0x2503, + 0xe26b, 0x2502, + 0xe26c, 0x4e41, + 0xe26e, 0x1e7a, + 0xe26f, 0x20a6, + 0xe270, 0x4e43, + 0xe278, 0x1fd5, + 0xe279, 0x4e4b, + 0xe27d, 0x1f11, + 0xe27e, 0x4e4f, + 0xe280, 0x2507, + 0xe281, 0x2500, + 0xe282, 0x2505, + 0xe283, 0x4e50, + 0xe289, 0x2519, + 0xe28a, 0x4e56, + 0xe28b, 0x2515, + 0xe28c, 0x4e57, + 0xe28e, 0x250c, + 0xe28f, 0x2031, + 0xe290, 0x4e59, + 0xe292, 0x250b, + 0xe293, 0x250f, + 0xe294, 0x251a, + 0xe295, 0x2509, + 0xe296, 0x4e5b, + 0xe298, 0x250e, + 0xe299, 0x2234, + 0xe29a, 0x2513, + 0xe29b, 0x1f80, + 0xe29c, 0x4e5d, + 0xe2a0, 0x2501, + 0xe2a1, 0x1603, + 0xe340, 0x4e61, + 0xe342, 0x2517, + 0xe343, 0x2516, + 0xe344, 0x4e63, + 0xe347, 0x2518, + 0xe348, 0x4e66, + 0xe34b, 0x1e56, + 0xe34c, 0x4e69, + 0xe34f, 0x250d, + 0xe350, 0x4e6c, + 0xe351, 0x20d3, + 0xe352, 0x4e6d, + 0xe354, 0x207a, + 0xe355, 0x20ce, + 0xe356, 0x4e6f, + 0xe358, 0x2510, + 0xe359, 0x4e71, + 0xe35c, 0x1e55, + 0xe35d, 0x4e74, + 0xe360, 0x250a, + 0xe361, 0x4e77, + 0xe366, 0x2511, + 0xe368, 0x4e7c, + 0xe371, 0x1faa, + 0xe372, 0x4e85, + 0xe373, 0x251e, + 0xe374, 0x1f1f, + 0xe375, 0x4e86, + 0xe378, 0x252d, + 0xe379, 0x221d, + 0xe37a, 0x4e89, + 0xe37c, 0x2532, + 0xe37d, 0x4e8b, + 0xe37e, 0x217b, + 0xe380, 0x4e8c, + 0xe38a, 0x21af, + 0xe38b, 0x4e96, + 0xe38c, 0x252c, + 0xe38d, 0x4e97, + 0xe38f, 0x2528, + 0xe390, 0x4e99, + 0xe391, 0x208c, + 0xe392, 0x4e9a, + 0xe393, 0x252f, + 0xe394, 0x4e9b, + 0xe395, 0x21bc, + 0xe396, 0x4e9c, + 0xe399, 0x251d, + 0xe39a, 0x4e9f, + 0xe39c, 0x2535, + 0xe39d, 0x4ea1, + 0xe39e, 0x220d, + 0xe39f, 0x2526, + 0xe3a0, 0x4ea2, + 0xe3a1, 0x1661, + 0xe440, 0x2534, + 0xe441, 0x252a, + 0xe442, 0x251f, + 0xe443, 0x2531, + 0xe444, 0x251c, + 0xe445, 0x4ea3, + 0xe448, 0x2525, + 0xe449, 0x4ea6, + 0xe44e, 0x21cd, + 0xe44f, 0x4eab, + 0xe450, 0x21da, + 0xe451, 0x4eac, + 0xe452, 0x2172, + 0xe453, 0x253e, + 0xe454, 0x4ead, + 0xe458, 0x204f, + 0xe459, 0x4eb1, + 0xe45a, 0x2543, + 0xe45b, 0x4eb2, + 0xe45c, 0x21d7, + 0xe45d, 0x4eb3, + 0xe45e, 0x1e3c, + 0xe45f, 0x4eb4, + 0xe462, 0x2529, + 0xe463, 0x4eb7, + 0xe465, 0x2521, + 0xe466, 0x4eb9, + 0xe468, 0x1eff, + 0xe469, 0x4ebb, + 0xe473, 0x253f, + 0xe474, 0x4ec5, + 0xe475, 0x2544, + 0xe476, 0x4ec6, + 0xe479, 0x2523, + 0xe47a, 0x1e90, + 0xe47b, 0x253a, + 0xe47c, 0x2545, + 0xe47d, 0x4ec9, + 0xe47e, 0x253d, + 0xe480, 0x4eca, + 0xe481, 0x20c1, + 0xe482, 0x4ecb, + 0xe484, 0x2103, + 0xe485, 0x2520, + 0xe486, 0x253c, + 0xe487, 0x253b, + 0xe488, 0x2538, + 0xe489, 0x4ecd, + 0xe48d, 0x2540, + 0xe48e, 0x4ed1, + 0xe48f, 0x1fcd, + 0xe490, 0x4ed2, + 0xe493, 0x1f18, + 0xe494, 0x4ed5, + 0xe498, 0x254b, + 0xe499, 0x4ed9, + 0xe49d, 0x2547, + 0xe49e, 0x254f, + 0xe4a0, 0x4edd, + 0xe4a1, 0x16bf, + 0xe540, 0x4ede, + 0xe546, 0x22b0, + 0xe547, 0x4ee4, + 0xe548, 0x2546, + 0xe549, 0x4ee5, + 0xe54b, 0x254c, + 0xe54c, 0x4ee7, + 0xe54e, 0x1e9a, + 0xe54f, 0x2552, + 0xe550, 0x2530, + 0xe551, 0x2549, + 0xe552, 0x4ee9, + 0xe555, 0x2551, + 0xe556, 0x1eca, + 0xe557, 0x4eec, + 0xe558, 0x20d2, + 0xe559, 0x4eed, + 0xe55c, 0x1fb8, + 0xe55d, 0x4ef0, + 0xe55e, 0x2079, + 0xe55f, 0x4ef1, + 0xe561, 0x21ab, + 0xe562, 0x4ef3, + 0xe564, 0x254d, + 0xe565, 0x1ea5, + 0xe566, 0x4ef5, + 0xe568, 0x204c, + 0xe569, 0x2080, + 0xe56a, 0x4ef7, + 0xe56c, 0x266d, + 0xe56d, 0x4ef9, + 0xe56e, 0x2537, + 0xe56f, 0x4efa, + 0xe575, 0x254a, + 0xe576, 0x21b8, + 0xe577, 0x4f00, + 0xe578, 0x254e, + 0xe579, 0x4f01, + 0xe57b, 0x24fc, + 0xe57c, 0x2554, + 0xe57d, 0x4f03, + 0xe580, 0x4f05, + 0xe581, 0x1f3c, + 0xe582, 0x4f06, + 0xe583, 0x1ed5, + 0xe584, 0x4f07, + 0xe58a, 0x2556, + 0xe58b, 0x4f0d, + 0xe58e, 0x2268, + 0xe58f, 0x4f10, + 0xe591, 0x1ed6, + 0xe592, 0x4f12, + 0xe59a, 0x2557, + 0xe59b, 0x2553, + 0xe59c, 0x4f1a, + 0xe59f, 0x2548, + 0xe5a0, 0x4f1d, + 0xe5a1, 0x171d, + 0xe640, 0x20dc, + 0xe641, 0x4f1e, + 0xe644, 0x2559, + 0xe645, 0x4f21, + 0xe649, 0x1f97, + 0xe64a, 0x2555, + 0xe64b, 0x4f25, + 0xe64e, 0x227d, + 0xe64f, 0x4f28, + 0xe652, 0x257e, + 0xe653, 0x4f2b, + 0xe656, 0x207c, + 0xe657, 0x4f2e, + 0xe658, 0x255a, + 0xe659, 0x4f2f, + 0xe65b, 0x255e, + 0xe65c, 0x4f31, + 0xe65e, 0x1e34, + 0xe65f, 0x4f33, + 0xe669, 0x215e, + 0xe66a, 0x4f3d, + 0xe66b, 0x2560, + 0xe66c, 0x4f3e, + 0xe675, 0x21a2, + 0xe676, 0x2354, + 0xe677, 0x4f47, + 0xe679, 0x2563, + 0xe67a, 0x2527, + 0xe67b, 0x4f49, + 0xe67c, 0x252e, + 0xe67d, 0x2558, + 0xe67e, 0x4f4a, + 0xe680, 0x1f1b, + 0xe681, 0x4f4b, + 0xe682, 0x2283, + 0xe683, 0x4f4c, + 0xe684, 0x2564, + 0xe685, 0x4f4d, + 0xe687, 0x20a0, + 0xe688, 0x4f4f, + 0xe689, 0x2565, + 0xe68a, 0x4f50, + 0xe68c, 0x2561, + 0xe68d, 0x4f52, + 0xe693, 0x2562, + 0xe694, 0x4f58, + 0xe697, 0x256c, + 0xe698, 0x4f5b, + 0xe69b, 0x256d, + 0xe69c, 0x2020, + 0xe69d, 0x4f5e, + 0xe69f, 0x255f, + 0xe6a0, 0x256a, + 0xe6a1, 0x177b, + 0xe740, 0x4f60, + 0xe743, 0x256e, + 0xe744, 0x4f63, + 0xe748, 0x2539, + 0xe749, 0x255c, + 0xe74a, 0x4f67, + 0xe74d, 0x2568, + 0xe74f, 0x256b, + 0xe750, 0x1e6f, + 0xe751, 0x4f6a, + 0xe752, 0x1fc4, + 0xe753, 0x2567, + 0xe754, 0x4f6b, + 0xe755, 0x255b, + 0xe756, 0x4f6c, + 0xe759, 0x261d, + 0xe75a, 0x4f6f, + 0xe766, 0x252b, + 0xe767, 0x4f7b, + 0xe768, 0x2571, + 0xe769, 0x4f7c, + 0xe76a, 0x2577, + 0xe76b, 0x4f7d, + 0xe774, 0x2522, + 0xe775, 0x4f86, + 0xe77c, 0x2533, + 0xe77d, 0x4f8d, + 0xe780, 0x4f8f, + 0xe782, 0x202a, + 0xe783, 0x4f91, + 0xe784, 0x2536, + 0xe785, 0x2573, + 0xe786, 0x256f, + 0xe787, 0x4f92, + 0xe78a, 0x2293, + 0xe78b, 0x2578, + 0xe78c, 0x4f95, + 0xe78f, 0x2570, + 0xe790, 0x4f98, + 0xe792, 0x2575, + 0xe793, 0x4f9a, + 0xe798, 0x2541, + 0xe79a, 0x255d, + 0xe79b, 0x4f9f, + 0xe7a0, 0x201a, + 0xe7a1, 0x17d9, + 0xe840, 0x4fa4, + 0xe843, 0x257a, + 0xe844, 0x2006, + 0xe845, 0x4fa7, + 0xe846, 0x2177, + 0xe847, 0x4fa8, + 0xe849, 0x251b, + 0xe84a, 0x4faa, + 0xe84b, 0x2524, + 0xe84c, 0x4fab, + 0xe84f, 0x257b, + 0xe850, 0x4fae, + 0xe854, 0x22a3, + 0xe855, 0x4fb2, + 0xe85a, 0x2579, + 0xe85b, 0x4fb7, + 0xe85c, 0x2566, + 0xe85d, 0x4fb8, + 0xe862, 0x1f93, + 0xe863, 0x4fbd, + 0xe864, 0x257c, + 0xe865, 0x4fbe, + 0xe870, 0x2514, + 0xe871, 0x4fc9, + 0xe873, 0x257d, + 0xe874, 0x4fcb, + 0xe875, 0x2572, + 0xe876, 0x4fcc, + 0xe87c, 0x2574, + 0xe87d, 0x4fd2, + 0xe880, 0x224e, + 0xe881, 0x4fd4, + 0xe882, 0x21c6, + 0xe883, 0x4fd5, + 0xe887, 0x209f, + 0xe888, 0x4fd9, + 0xe889, 0x2576, + 0xe88a, 0x4fda, + 0xe88c, 0x2064, + 0xe88d, 0x22bf, + 0xe88e, 0x261c, + 0xe88f, 0x225e, + 0xe890, 0x4fdc, + 0xe8a1, 0x1837, + 0xe940, 0x4fed, + 0xe94c, 0x1e75, + 0xe94d, 0x4ff9, + 0xe954, 0x207d, + 0xe955, 0x5000, + 0xe956, 0x23bf, + 0xe957, 0x2113, + 0xe958, 0x5001, + 0xe95a, 0x23c0, + 0xe95b, 0x5003, + 0xe95d, 0x1e45, + 0xe95e, 0x5005, + 0xe95f, 0x1fd8, + 0xe960, 0x23c4, + 0xe961, 0x5006, + 0xe962, 0x23c2, + 0xe963, 0x2104, + 0xe964, 0x5007, + 0xe965, 0x21bd, + 0xe966, 0x5008, + 0xe967, 0x1f87, + 0xe968, 0x23c3, + 0xe969, 0x5009, + 0xe96c, 0x2269, + 0xe96d, 0x500c, + 0xe975, 0x1f43, + 0xe976, 0x5014, + 0xe977, 0x1f1e, + 0xe978, 0x2679, + 0xe979, 0x1eeb, + 0xe97a, 0x5015, + 0xe97c, 0x1f35, + 0xe97d, 0x208a, + 0xe97e, 0x5017, + 0xe980, 0x23c7, + 0xe981, 0x23c9, + 0xe982, 0x23c6, + 0xe983, 0x5018, + 0xe987, 0x224f, + 0xe988, 0x501c, + 0xe98b, 0x23cb, + 0xe98c, 0x501f, + 0xe98e, 0x21f3, + 0xe98f, 0x5021, + 0xe990, 0x21f7, + 0xe991, 0x23cf, + 0xe992, 0x23ce, + 0xe993, 0x23ca, + 0xe994, 0x23cd, + 0xe995, 0x5022, + 0xe998, 0x23d0, + 0xe999, 0x5025, + 0xe99b, 0x266c, + 0xe99c, 0x5027, + 0xe99d, 0x23c1, + 0xe99e, 0x5028, + 0xe99f, 0x1fee, + 0xe9a0, 0x23d1, + 0xe9a1, 0x1895, + 0xea40, 0x1ff8, + 0xea41, 0x5029, + 0xea44, 0x23d3, + 0xea45, 0x502c, + 0xea48, 0x23d2, + 0xea49, 0x23d4, + 0xea4a, 0x1e98, + 0xea4b, 0x502f, + 0xea50, 0x1f2c, + 0xea51, 0x5034, + 0xea52, 0x23d5, + 0xea53, 0x5035, + 0xea55, 0x1e71, + 0xea56, 0x2691, + 0xea57, 0x5037, + 0xea59, 0x23c5, + 0xea5a, 0x5039, + 0xea80, 0x231a, + 0xea81, 0x505e, + 0xea84, 0x2114, + 0xea85, 0x5061, + 0xea87, 0x2284, + 0xea88, 0x5063, + 0xea8e, 0x221c, + 0xea8f, 0x5069, + 0xea90, 0x1e7e, + 0xea91, 0x204d, + 0xea92, 0x506a, + 0xea96, 0x2201, + 0xea97, 0x506e, + 0xeaa0, 0x1ed9, + 0xeaa1, 0x18f3, + 0xeb40, 0x5077, + 0xeb41, 0x1fb2, + 0xeb42, 0x5078, + 0xeb45, 0x2252, + 0xeb46, 0x507b, + 0xeb48, 0x1f79, + 0xeb49, 0x507d, + 0xeb53, 0x2157, + 0xeb54, 0x5087, + 0xeb55, 0x21bf, + 0xeb56, 0x5088, + 0xeb5b, 0x221f, + 0xeb5c, 0x508d, + 0xeb5d, 0x203d, + 0xeb5e, 0x508e, + 0xeb60, 0x2015, + 0xeb61, 0x5090, + 0xeb62, 0x26a5, + 0xeb63, 0x5091, + 0xeb6d, 0x2156, + 0xeb6e, 0x509b, + 0xeb70, 0x2144, + 0xeb71, 0x509d, + 0xeb72, 0x1e91, + 0xeb73, 0x2257, + 0xeb74, 0x509e, + 0xeb78, 0x200a, + 0xeb79, 0x2092, + 0xeb7a, 0x50a2, + 0xeb80, 0x50a7, + 0xeb85, 0x2250, + 0xeb86, 0x50ac, + 0xeb8a, 0x1ec3, + 0xeb8b, 0x50b0, + 0xeba1, 0x1951, + 0xec40, 0x50c6, + 0xec46, 0x21a8, + 0xec47, 0x50cc, + 0xec56, 0x260d, + 0xec57, 0x50db, + 0xec5a, 0x260c, + 0xec5b, 0x50de, + 0xec5c, 0x260e, + 0xec5d, 0x50df, + 0xec60, 0x2032, + 0xec61, 0x50e2, + 0xec6e, 0x260b, + 0xec6f, 0x50ef, + 0xec76, 0x22c3, + 0xec77, 0x50f6, + 0xec80, 0x50fe, + 0xec96, 0x1f23, + 0xec97, 0x5114, + 0xeca1, 0x19af, + 0xed40, 0x511e, + 0xed46, 0x2695, + 0xed47, 0x5124, + 0xed58, 0x265e, + 0xed59, 0x5135, + 0xed5e, 0x265d, + 0xed5f, 0x513a, + 0xed61, 0x2692, + 0xed62, 0x513c, + 0xed64, 0x265f, + 0xed65, 0x513e, + 0xed66, 0x218d, + 0xed67, 0x20fd, + 0xed68, 0x513f, + 0xed6e, 0x1f40, + 0xed6f, 0x5145, + 0xed74, 0x2465, + 0xed75, 0x514a, + 0xed77, 0x2467, + 0xed78, 0x514c, + 0xed79, 0x2466, + 0xed7a, 0x514d, + 0xed80, 0x5152, + 0xed91, 0x21c9, + 0xed92, 0x5163, + 0xed93, 0x2209, + 0xed94, 0x1ec9, + 0xed95, 0x20e9, + 0xed96, 0x5164, + 0xed97, 0x21ca, + 0xed98, 0x2146, + 0xed99, 0x25c5, + 0xed9a, 0x21dc, + 0xed9b, 0x5165, + 0xed9c, 0x245e, + 0xed9d, 0x5166, + 0xed9e, 0x214f, + 0xed9f, 0x5167, + 0xeda0, 0x25c6, + 0xeda1, 0x1a0d, + 0xee40, 0x25c7, + 0xee41, 0x2241, + 0xee42, 0x218a, + 0xee43, 0x1e2f, + 0xee44, 0x1edc, + 0xee45, 0x5168, + 0xee48, 0x20bf, + 0xee49, 0x2034, + 0xee4a, 0x516b, + 0xee4d, 0x25c9, + 0xee4e, 0x516e, + 0xee52, 0x25c8, + 0xee53, 0x5172, + 0xee55, 0x220e, + 0xee56, 0x5174, + 0xee57, 0x25cb, + 0xee58, 0x5175, + 0xee5e, 0x217d, + 0xee5f, 0x517b, + 0xee61, 0x1f7e, + 0xee62, 0x517d, + 0xee68, 0x25cc, + 0xee69, 0x1fc3, + 0xee6a, 0x5183, + 0xee6c, 0x20b9, + 0xee6d, 0x5185, + 0xee6e, 0x2181, + 0xee6f, 0x5186, + 0xee77, 0x1fda, + 0xee78, 0x518e, + 0xee7d, 0x2173, + 0xee7e, 0x1ee1, + 0xee80, 0x25cd, + 0xee81, 0x5193, + 0xee85, 0x25ce, + 0xee86, 0x21f6, + 0xee87, 0x5197, + 0xee8a, 0x224b, + 0xee8b, 0x25d1, + 0xee8c, 0x519a, + 0xee8d, 0x1ec0, + 0xee8e, 0x519b, + 0xee90, 0x2008, + 0xee91, 0x519d, + 0xee94, 0x25d0, + 0xee95, 0x51a0, + 0xee97, 0x25d2, + 0xee98, 0x51a2, + 0xee99, 0x1f2a, + 0xee9a, 0x51a3, + 0xee9d, 0x1e72, + 0xee9e, 0x25d3, + 0xee9f, 0x51a6, + 0xeea1, 0x1a6b, + 0xef40, 0x21be, + 0xef41, 0x25d4, + 0xef42, 0x2044, + 0xef43, 0x51a8, + 0xef44, 0x25cf, + 0xef45, 0x20f3, + 0xef46, 0x51a9, + 0xef4c, 0x1f00, + 0xef4d, 0x51af, + 0xef52, 0x24cc, + 0xef54, 0x51b4, + 0xef55, 0x2698, + 0xef56, 0x51b5, + 0xef57, 0x2678, + 0xef58, 0x51b6, + 0xef5a, 0x24ce, + 0xef5b, 0x51b8, + 0xef60, 0x24cf, + 0xef61, 0x51bd, + 0xef68, 0x20b8, + 0xef69, 0x51c4, + 0xef6a, 0x24d0, + 0xef6b, 0x51c5, + 0xef6c, 0x24d1, + 0xef6d, 0x51c6, + 0xef77, 0x1ef4, + 0xef78, 0x51d0, + 0xef7a, 0x239b, + 0xef7b, 0x51d2, + 0xef7c, 0x267e, + 0xef7d, 0x51d3, + 0xef80, 0x51d5, + 0xef82, 0x239d, + 0xef83, 0x239f, + 0xef85, 0x51d7, + 0xef86, 0x23a1, + 0xef87, 0x51d8, + 0xef88, 0x1ef1, + 0xef89, 0x51d9, + 0xef8b, 0x221e, + 0xef8c, 0x51db, + 0xef8d, 0x23a2, + 0xef8e, 0x51dc, + 0xef95, 0x214b, + 0xef96, 0x1e36, + 0xef97, 0x2135, + 0xef98, 0x51e3, + 0xef9c, 0x1fad, + 0xef9d, 0x51e7, + 0xef9e, 0x1e53, + 0xef9f, 0x51e8, + 0xefa1, 0x1ac9, + 0xf040, 0x51ea, + 0xf041, 0x23a3, + 0xf042, 0x2203, + 0xf043, 0x51eb, + 0xf044, 0x1ee7, + 0xf045, 0x51ec, + 0xf047, 0x23a4, + 0xf048, 0x2097, + 0xf049, 0x1ee4, + 0xf04a, 0x51ee, + 0xf04e, 0x2238, + 0xf04f, 0x51f2, + 0xf051, 0x23a5, + 0xf052, 0x51f4, + 0xf054, 0x1f9a, + 0xf055, 0x51f6, + 0xf057, 0x21c3, + 0xf058, 0x51f8, + 0xf05e, 0x1f2e, + 0xf05f, 0x51fe, + 0xf068, 0x239c, + 0xf069, 0x5207, + 0xf06c, 0x23a6, + 0xf06d, 0x520a, + 0xf071, 0x239e, + 0xf072, 0x520e, + 0xf073, 0x2035, + 0xf074, 0x23a7, + 0xf075, 0x520f, + 0xf078, 0x23a8, + 0xf079, 0x5212, + 0xf07a, 0x2075, + 0xf07b, 0x5213, + 0xf07d, 0x23a9, + 0xf080, 0x23ab, + 0xf081, 0x1feb, + 0xf082, 0x23ac, + 0xf083, 0x5215, + 0xf087, 0x1f6a, + 0xf088, 0x20f9, + 0xf089, 0x5219, + 0xf08b, 0x2666, + 0xf08c, 0x521b, + 0xf090, 0x2667, + 0xf091, 0x521f, + 0xf092, 0x1e6c, + 0xf093, 0x5220, + 0xf096, 0x23ad, + 0xf097, 0x5223, + 0xf0a1, 0x1b27, + 0xf140, 0x522d, + 0xf152, 0x206d, + 0xf153, 0x2242, + 0xf154, 0x1f02, + 0xf155, 0x523f, + 0xf157, 0x2183, + 0xf158, 0x5241, + 0xf159, 0x1e85, + 0xf15a, 0x21e9, + 0xf15b, 0x5242, + 0xf167, 0x1e57, + 0xf168, 0x524e, + 0xf176, 0x22a5, + 0xf177, 0x2407, + 0xf178, 0x1fca, + 0xf179, 0x525c, + 0xf17a, 0x2402, + 0xf17b, 0x1f82, + 0xf17c, 0x525d, + 0xf17e, 0x2408, + 0xf180, 0x2404, + 0xf181, 0x525f, + 0xf182, 0x2131, + 0xf183, 0x5260, + 0xf184, 0x2184, + 0xf185, 0x5261, + 0xf186, 0x2403, + 0xf187, 0x5262, + 0xf188, 0x206e, + 0xf189, 0x240b, + 0xf18a, 0x5263, + 0xf194, 0x1f3f, + 0xf195, 0x526d, + 0xf198, 0x2067, + 0xf199, 0x5270, + 0xf1a1, 0x1b85, + 0xf240, 0x5278, + 0xf245, 0x1fd7, + 0xf246, 0x527d, + 0xf247, 0x1e83, + 0xf248, 0x527e, + 0xf24b, 0x240f, + 0xf24c, 0x5281, + 0xf253, 0x240e, + 0xf254, 0x20c7, + 0xf255, 0x240d, + 0xf256, 0x5288, + 0xf25c, 0x2412, + 0xf25d, 0x528e, + 0xf25f, 0x20b7, + 0xf260, 0x5290, + 0xf271, 0x23f0, + 0xf272, 0x52a1, + 0xf273, 0x2411, + 0xf274, 0x2414, + 0xf275, 0x52a2, + 0xf276, 0x2170, + 0xf277, 0x52a3, + 0xf27c, 0x2405, + 0xf27d, 0x210c, + 0xf27e, 0x2415, + 0xf280, 0x52a8, + 0xf285, 0x2066, + 0xf286, 0x52ad, + 0xf287, 0x2352, + 0xf288, 0x2413, + 0xf289, 0x2410, + 0xf28a, 0x2416, + 0xf28c, 0x20f1, + 0xf28d, 0x52ae, + 0xf291, 0x240a, + 0xf292, 0x52b2, + 0xf294, 0x2409, + 0xf295, 0x52b4, + 0xf296, 0x2418, + 0xf297, 0x52b5, + 0xf29c, 0x1fa7, + 0xf29d, 0x52ba, + 0xf29e, 0x21fc, + 0xf29f, 0x52bb, + 0xf2a1, 0x1be3, + 0xf340, 0x1fc1, + 0xf341, 0x2406, + 0xf342, 0x52bd, + 0xf345, 0x229c, + 0xf346, 0x52c0, + 0xf348, 0x204e, + 0xf349, 0x52c2, + 0xf34a, 0x241a, + 0xf34b, 0x2419, + 0xf34c, 0x52c3, + 0xf350, 0x240c, + 0xf351, 0x52c7, + 0xf361, 0x1e29, + 0xf362, 0x52d7, + 0xf374, 0x2661, + 0xf375, 0x52e9, + 0xf376, 0x26a4, + 0xf377, 0x2174, + 0xf378, 0x2663, + 0xf379, 0x2662, + 0xf37a, 0x52ea, + 0xf380, 0x52ef, + 0xf38c, 0x2675, + 0xf38d, 0x52fb, + 0xf3a0, 0x214c, + 0xf3a1, 0x1c41, + 0xf440, 0x530e, + 0xf445, 0x267a, + 0xf446, 0x5313, + 0xf450, 0x26a0, + 0xf451, 0x531d, + 0xf457, 0x2668, + 0xf458, 0x5323, + 0xf459, 0x1ed0, + 0xf45a, 0x5324, + 0xf45b, 0x2096, + 0xf45c, 0x5325, + 0xf45d, 0x23cc, + 0xf45e, 0x5326, + 0xf462, 0x23c8, + 0xf463, 0x532a, + 0xf464, 0x223e, + 0xf465, 0x532b, + 0xf475, 0x2665, + 0xf476, 0x533b, + 0xf47c, 0x2664, + 0xf47d, 0x5341, + 0xf47e, 0x2239, + 0xf480, 0x5342, + 0xf494, 0x204a, + 0xf495, 0x5356, + 0xf499, 0x261f, + 0xf49a, 0x535a, + 0xf49c, 0x261e, + 0xf49d, 0x535c, + 0xf4a1, 0x1c9f, + 0xf540, 0x5360, + 0xf545, 0x2620, + 0xf546, 0x5365, + 0xf547, 0x2621, + 0xf548, 0x5366, + 0xf552, 0x2622, + 0xf553, 0x5370, + 0xf554, 0x2627, + 0xf555, 0x1e39, + 0xf556, 0x2625, + 0xf557, 0x5371, + 0xf55e, 0x2629, + 0xf55f, 0x5378, + 0xf561, 0x262e, + 0xf562, 0x262b, + 0xf563, 0x537a, + 0xf56e, 0x262a, + 0xf56f, 0x262d, + 0xf570, 0x5385, + 0xf571, 0x2628, + 0xf572, 0x21b9, + 0xf573, 0x5386, + 0xf580, 0x5392, + 0xf585, 0x2636, + 0xf586, 0x2630, + 0xf587, 0x5397, + 0xf58c, 0x2638, + 0xf58d, 0x539c, + 0xf58e, 0x200d, + 0xf58f, 0x2637, + 0xf590, 0x539d, + 0xf599, 0x2645, + 0xf59a, 0x53a6, + 0xf59b, 0x263a, + 0xf59c, 0x53a7, + 0xf5a0, 0x2643, + 0xf5a1, 0x1cfd, + 0xf640, 0x53ab, + 0xf641, 0x2640, + 0xf642, 0x53ac, + 0xf645, 0x263d, + 0xf646, 0x2641, + 0xf647, 0x53af, + 0xf648, 0x263e, + 0xf649, 0x53b0, + 0xf64b, 0x263f, + 0xf64c, 0x1fc0, + 0xf64d, 0x53b2, + 0xf64e, 0x263b, + 0xf650, 0x53b3, + 0xf654, 0x2642, + 0xf655, 0x53b7, + 0xf658, 0x2644, + 0xf659, 0x53ba, + 0xf661, 0x2639, + 0xf662, 0x53c2, + 0xf663, 0x264c, + 0xf664, 0x53c3, + 0xf66c, 0x2647, + 0xf66d, 0x264b, + 0xf66e, 0x53cb, + 0xf671, 0x2649, + 0xf672, 0x53ce, + 0xf674, 0x2648, + 0xf675, 0x53d0, + 0xf676, 0x264a, + 0xf677, 0x2108, + 0xf678, 0x53d1, + 0xf680, 0x53d8, + 0xf685, 0x264d, + 0xf686, 0x53dd, + 0xf688, 0x2634, + 0xf689, 0x53df, + 0xf68a, 0x2651, + 0xf68b, 0x53e0, + 0xf68d, 0x2650, + 0xf68e, 0x2652, + 0xf68f, 0x53e2, + 0xf692, 0x264f, + 0xf693, 0x53e5, + 0xf696, 0x2632, + 0xf697, 0x264e, + 0xf698, 0x2653, + 0xf699, 0x53e8, + 0xf69a, 0x2657, + 0xf69b, 0x53e9, + 0xf69c, 0x2635, + 0xf69d, 0x53ea, + 0xf69e, 0x2633, + 0xf69f, 0x53eb, + 0xf6a0, 0x2656, + 0xf6a1, 0x1d5b, + 0xf740, 0x53ec, + 0xf742, 0x2654, + 0xf743, 0x53ee, + 0xf749, 0x2658, + 0xf74a, 0x53f4, + 0xf74c, 0x2655, + 0xf74d, 0x1e4d, + 0xf74e, 0x53f6, + 0xf756, 0x265b, + 0xf757, 0x53fe, + 0xf758, 0x265a, + 0xf759, 0x53ff, + 0xf75a, 0x2659, + 0xf75b, 0x202e, + 0xf75c, 0x262f, + 0xf75d, 0x5400, + 0xf761, 0x2646, + 0xf762, 0x5404, + 0xf763, 0x2626, + 0xf764, 0x5405, + 0xf76b, 0x265c, + 0xf76c, 0x540c, + 0xf771, 0x262c, + 0xf772, 0x5411, + 0xf77c, 0x2623, + 0xf77d, 0x541b, + 0xf77e, 0x2631, + 0xf780, 0x541c, + 0xf7a1, 0x1db9, + 0xf840, 0x543d, + 0xf842, 0x209c, + 0xf843, 0x543f, + 0xf846, 0x2580, + 0xf847, 0x5442, + 0xf849, 0x22dc, + 0xf84a, 0x5444, + 0xf850, 0x1f05, + 0xf851, 0x208b, + 0xf852, 0x544a, + 0xf853, 0x2581, + 0xf854, 0x544b, + 0xf863, 0x2583, + 0xf864, 0x2582, + 0xf865, 0x545a, + 0xf866, 0x21ee, + 0xf867, 0x545b, + 0xf872, 0x2182, + 0xf873, 0x5466, + 0xf878, 0x2243, + 0xf879, 0x546b, + 0xf87a, 0x2587, + 0xf87b, 0x546c, + 0xf87c, 0x2588, + 0xf87d, 0x546d, + 0xf880, 0x546f, + 0xf881, 0x2584, + 0xf882, 0x5470, + 0xf884, 0x21fd, + 0xf885, 0x5472, + 0xf886, 0x21ef, + 0xf887, 0x5473, + 0xf88d, 0x258a, + 0xf88e, 0x258c, + 0xf88f, 0x5479, + 0xf899, 0x1f47, + 0xf89a, 0x5483, + 0xf89d, 0x1f1d, + 0xf89e, 0x5486, + 0xf8a0, 0x258d, + 0xf940, 0x5488, + 0xf94e, 0x1fd0, + 0xf94f, 0x2592, + 0xf950, 0x258f, + 0xf951, 0x5496, + 0xf959, 0x2594, + 0xf95a, 0x1ee0, + 0xf95b, 0x549e, + 0xf95d, 0x2591, + 0xf95e, 0x2595, + 0xf95f, 0x54a0, + 0xf967, 0x2597, + 0xf968, 0x54a8, + 0xf969, 0x20b6, + 0xf96a, 0x54a9, + 0xf96c, 0x2598, + 0xf96d, 0x54ab, + 0xf96f, 0x20f6, + 0xf970, 0x54ad, + 0xf980, 0x54bc, + 0xf985, 0x2585, + 0xf986, 0x54c1, + 0xf987, 0x2599, + 0xf988, 0x54c2, + 0xf991, 0x2596, + 0xf992, 0x54cb, + 0xf996, 0x259a, + 0xf997, 0x54cf, + 0xf998, 0x259b, + 0xf999, 0x54d0, + 0xfa40, 0x54d8, + 0xfa42, 0x259d, + 0xfa43, 0x54da, + 0xfa46, 0x259e, + 0xfa47, 0x54dd, + 0xfa4c, 0x234c, + 0xfa4d, 0x54e2, + 0xfa51, 0x1f44, + 0xfa52, 0x54e6, + 0xfa58, 0x2660, + 0xfa59, 0x25a0, + 0xfa5a, 0x54ec, + 0xfa5d, 0x259c, + 0xfa5e, 0x54ef, + 0xfa5f, 0x259f, + 0xfa60, 0x54f0, + 0xfa61, 0x1f6c, + 0xfa62, 0x54f1, + 0xfa70, 0x25a2, + 0xfa71, 0x54ff, + 0xfa74, 0x20ae, + 0xfa75, 0x5502, + 0xfa76, 0x258b, + 0xfa77, 0x25a3, + 0xfa78, 0x5503, + 0xfa80, 0x550a, + 0xfa83, 0x2589, + 0xfa84, 0x25a5, + 0xfa85, 0x550d, + 0xfa8d, 0x25a4, + 0xfa8e, 0x5515, + 0xfa90, 0x25a6, + 0xfa91, 0x2593, + 0xfa92, 0x5517, + 0xfa96, 0x25a7, + 0xfa97, 0x2222, + 0xfa98, 0x25a9, + 0xfa99, 0x551b, + 0xfb40, 0x5523, + 0xfb49, 0x25a8, + 0xfb4a, 0x552c, + 0xfb52, 0x2586, + 0xfb53, 0x5534, + 0xfb57, 0x25a1, + 0xfb58, 0x25aa, + 0xfb59, 0x5538, + 0xfb5a, 0x2590, + 0xfb5b, 0x258e, + 0xfb5c, 0x5539, + 0xfb75, 0x2688, + 0xfb76, 0x5552, + 0xfb79, 0x269e, + 0xfb7a, 0x25fb, + 0xfb7b, 0x5555, + 0xfb7c, 0x1f8c, + 0xfb7d, 0x21f4, + 0xfb7e, 0x5556, + 0xfb80, 0x5557, + 0xfb90, 0x200f, + 0xfb91, 0x5567, + 0xfb9c, 0x2071, + 0xfb9d, 0x5572, + 0xfb9f, 0x25f7, + 0xfba0, 0x5574, + 0xfc40, 0x5575, + 0xfc44, 0x2696, + 0xfc45, 0x5579, + 0xfc49, 0x268f, + 0xfc4a, 0x557d, + 0xfc5a, 0x22da, + 0xfc5b, 0x558d, + 0xfc63, 0x1ec1, + 0xfc64, 0x5595, + 0xfc68, 0x1eb3, + 0xfc69, 0x5599, + 0xfc6f, 0x266a, + 0xfc70, 0x559f, + 0xfc71, 0x268a, + 0xfc72, 0x55a0, + 0xfc74, 0x2669, + 0xfc75, 0x55a2, + 0xfc77, 0x2618, + 0xfc79, 0x55a4, + 0xfc80, 0x55aa, + 0xfc83, 0x261a, + 0xfc84, 0x55ad, + 0xfc8a, 0x2673, + 0xfc8b, 0x55b3, + 0xfd40, 0x55c9, + 0xfd52, 0x20c6, + 0xfd53, 0x226b, + 0xfd54, 0x55db, + 0xfd57, 0x24d3, + 0xfd58, 0x1e86, + 0xfd59, 0x55de, + 0xfd5a, 0x260f, + 0xfd5b, 0x55df, + 0xfd5f, 0x2611, + 0xfd60, 0x55e3, + 0xfd62, 0x2613, + 0xfd63, 0x55e5, + 0xfd65, 0x2610, + 0xfd66, 0x2612, + 0xfd67, 0x2030, + 0xfd68, 0x55e7, + 0xfd69, 0x2671, + 0xfd6a, 0x55e8, + 0xfd6c, 0x2614, + 0xfd6d, 0x55ea, + 0xfd70, 0x2616, + 0xfd71, 0x55ed, + 0xfd72, 0x2615, + 0xfd73, 0x55ee, + 0xfd78, 0x20f2, + 0xfd79, 0x55f3, + 0xfd7d, 0x2617, + 0xfd7e, 0x55f7, + 0xfd80, 0x55f8, + 0xfd88, 0x2037, + 0xfd89, 0x5600, + 0xfd8b, 0x20b3, + 0xfd8c, 0x5602, + 0xfd8f, 0x1f22, + 0xfd90, 0x24ed, + 0xfd91, 0x5605, + 0xfd94, 0x1f34, + 0xfd95, 0x5608, + 0xfd9d, 0x0a02, + 0xfd9e, 0x40d3, + 0xfd9f, 0x200c, + 0xfda0, 0x5083, + 0xfe40, 0x1259, + 0xfe41, 0x5610, + 0xfe80, 0x564e, + 0xffff, 0x0000 +}; + +static GfxFontEncoding16 gb12GBKEUCHEnc16 = { + 0, + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 }, + { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1e24, 0x032e, 0x032f, 0x0330, 0x0331, 0x0332, 0x0333, 0x0334, + 0x0335, 0x0336, 0x0337, 0x0338, 0x0339, 0x033a, 0x033b, 0x033c, + 0x033d, 0x033e, 0x033f, 0x0340, 0x0341, 0x0342, 0x0343, 0x0344, + 0x0345, 0x0346, 0x0347, 0x0348, 0x0349, 0x034a, 0x034b, 0x034c, + 0x034d, 0x034e, 0x034f, 0x0350, 0x0351, 0x0352, 0x0353, 0x0354, + 0x0355, 0x0356, 0x0357, 0x0358, 0x0359, 0x035a, 0x035b, 0x035c, + 0x035d, 0x035e, 0x035f, 0x0360, 0x0361, 0x0362, 0x0363, 0x0364, + 0x0365, 0x0366, 0x0367, 0x0368, 0x0369, 0x036a, 0x036b, 0x036c, + 0x036d, 0x036e, 0x036f, 0x0370, 0x0371, 0x0372, 0x0373, 0x0374, + 0x0375, 0x0376, 0x0377, 0x0378, 0x0379, 0x037a, 0x037b, 0x037c, + 0x037d, 0x037e, 0x037f, 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, + 0x0385, 0x0386, 0x0387, 0x0388, 0x0389, 0x038a, 0x038b, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, + gb12GBKEUCHMap2, 4071 +}; + +static Gushort gb12GBKEUCVMap2[8182] = { + 0x0000, 0x0000, + 0x8140, 0x2758, + 0x8179, 0x2059, + 0x817a, 0x2791, + 0x8180, 0x2796, + 0x8186, 0x21f1, + 0x8187, 0x279c, + 0x81ed, 0x1ff2, + 0x81ee, 0x2802, + 0x81f6, 0x205d, + 0x81f7, 0x280a, + 0x8240, 0x2812, + 0x8253, 0x269c, + 0x8254, 0x2825, + 0x8262, 0x21b5, + 0x8263, 0x2833, + 0x8274, 0x22cc, + 0x8275, 0x2844, + 0x827a, 0x2016, + 0x827b, 0x2849, + 0x827d, 0x1e62, + 0x827e, 0x284b, + 0x8280, 0x1f20, + 0x8281, 0x284c, + 0x8283, 0x207f, + 0x8284, 0x284e, + 0x8290, 0x205c, + 0x8291, 0x285a, + 0x82a5, 0x2194, + 0x82a6, 0x286e, + 0x82c8, 0x1e65, + 0x82c9, 0x2281, + 0x82ca, 0x2890, + 0x82e1, 0x22cd, + 0x82e2, 0x28a7, + 0x82e3, 0x210a, + 0x82e4, 0x1e3e, + 0x82e5, 0x28a8, + 0x82ed, 0x267f, + 0x82ee, 0x28b0, + 0x82f2, 0x222e, + 0x82f3, 0x28b4, + 0x82f7, 0x1e96, + 0x82f8, 0x22cb, + 0x82f9, 0x226c, + 0x82fa, 0x28b8, + 0x82fb, 0x2117, + 0x82fc, 0x28b9, + 0x8340, 0x28bc, + 0x8341, 0x20e8, + 0x8342, 0x28bd, + 0x8345, 0x22d4, + 0x8346, 0x28c0, + 0x8348, 0x1fb9, + 0x8349, 0x28c2, + 0x834c, 0x22d8, + 0x834d, 0x28c5, + 0x8353, 0x20df, + 0x8354, 0x28cb, + 0x8357, 0x20c2, + 0x8358, 0x28ce, + 0x835e, 0x2195, + 0x835f, 0x28d4, + 0x8365, 0x1fac, + 0x8366, 0x22d3, + 0x8367, 0x28da, + 0x8372, 0x1f81, + 0x8373, 0x28e5, + 0x8378, 0x2210, + 0x8379, 0x28ea, + 0x837a, 0x22cf, + 0x837b, 0x28eb, + 0x837c, 0x2213, + 0x837d, 0x28ec, + 0x837e, 0x1fe4, + 0x8380, 0x1f90, + 0x8381, 0x28ed, + 0x8386, 0x22d6, + 0x8387, 0x28f2, + 0x8389, 0x22d0, + 0x838a, 0x22ce, + 0x838b, 0x28f4, + 0x838d, 0x2681, + 0x838e, 0x28f6, + 0x8394, 0x1e76, + 0x8395, 0x28fc, + 0x839e, 0x2231, + 0x839f, 0x2905, + 0x83a6, 0x1e93, + 0x83a7, 0x290c, + 0x83ab, 0x22d2, + 0x83ac, 0x2910, + 0x83ae, 0x22d7, + 0x83af, 0x22d5, + 0x83b0, 0x22d1, + 0x83b1, 0x2912, + 0x83ba, 0x1ee5, + 0x83bb, 0x291b, + 0x83c9, 0x2025, + 0x83ca, 0x2929, + 0x83f6, 0x1ecf, + 0x83f7, 0x2955, + 0x8440, 0x295d, + 0x8450, 0x1fd9, + 0x8451, 0x296d, + 0x8471, 0x22c8, + 0x8472, 0x298d, + 0x8474, 0x2263, + 0x8475, 0x298f, + 0x8477, 0x2683, + 0x8478, 0x2991, + 0x8480, 0x2998, + 0x8482, 0x1f17, + 0x8483, 0x299a, + 0x848e, 0x1f2b, + 0x848f, 0x29a5, + 0x8492, 0x22ca, + 0x8493, 0x1e99, + 0x8494, 0x29a8, + 0x849d, 0x1f4f, + 0x849e, 0x29b1, + 0x84a1, 0x1fcf, + 0x84a2, 0x2036, + 0x84a3, 0x1f3a, + 0x84a4, 0x29b4, + 0x84a5, 0x22c9, + 0x84a6, 0x1f99, + 0x84a7, 0x29b5, + 0x84a9, 0x1f75, + 0x84aa, 0x29b7, + 0x84c5, 0x1fbe, + 0x84c6, 0x29d2, + 0x84d3, 0x1ecd, + 0x84d4, 0x29df, + 0x84d5, 0x21a9, + 0x84d6, 0x29e0, + 0x84d7, 0x21e6, + 0x84d8, 0x29e1, + 0x84d9, 0x2127, + 0x84da, 0x2003, + 0x84db, 0x29e2, + 0x84dd, 0x2132, + 0x84de, 0x29e4, + 0x84ea, 0x2323, + 0x84eb, 0x29f0, + 0x84ee, 0x2011, + 0x84ef, 0x29f3, + 0x84f1, 0x20f5, + 0x84f2, 0x29f5, + 0x8540, 0x2a02, + 0x8551, 0x22c5, + 0x8552, 0x1f5e, + 0x8553, 0x2a13, + 0x8554, 0x22c6, + 0x8555, 0x2a14, + 0x855e, 0x20ef, + 0x855f, 0x2a1d, + 0x8566, 0x21d0, + 0x8567, 0x2a24, + 0x8580, 0x2a3c, + 0x8587, 0x22c1, + 0x8588, 0x2a43, + 0x858b, 0x1e64, + 0x858c, 0x2a46, + 0x8592, 0x21f9, + 0x8593, 0x2a4c, + 0x8596, 0x2010, + 0x8597, 0x2a4f, + 0x8598, 0x22c2, + 0x8599, 0x2a50, + 0x85a2, 0x1e5a, + 0x85a3, 0x2a59, + 0x85b2, 0x1ea2, + 0x85b3, 0x2a68, + 0x8640, 0x2ab4, + 0x864a, 0x236d, + 0x864b, 0x2abe, + 0x8654, 0x2247, + 0x8655, 0x2ac7, + 0x8668, 0x236c, + 0x8669, 0x2ada, + 0x8680, 0x2af0, + 0x8696, 0x219c, + 0x8697, 0x2b06, + 0x8699, 0x20c9, + 0x869a, 0x2b08, + 0x86a1, 0x21f0, + 0x86a2, 0x2b0f, + 0x86ca, 0x210b, + 0x86cb, 0x2b37, + 0x86cc, 0x20de, + 0x86cd, 0x2b38, + 0x86ce, 0x1eaa, + 0x86cf, 0x2b39, + 0x86d1, 0x222c, + 0x86d2, 0x2b3b, + 0x86dc, 0x20d8, + 0x86dd, 0x22c0, + 0x86de, 0x2b45, + 0x86e1, 0x206f, + 0x86e2, 0x2b48, + 0x86e8, 0x21a1, + 0x86e9, 0x2b4e, + 0x86ee, 0x2379, + 0x86ef, 0x2b53, + 0x86f4, 0x2372, + 0x86f5, 0x2b58, + 0x8740, 0x216a, + 0x8741, 0x2b62, + 0x8744, 0x237c, + 0x8745, 0x2b65, + 0x8749, 0x20b0, + 0x874a, 0x2b69, + 0x874b, 0x237a, + 0x874c, 0x1e74, + 0x874d, 0x2b6a, + 0x874f, 0x2377, + 0x8750, 0x2b6c, + 0x8757, 0x1f4c, + 0x8758, 0x2b73, + 0x875a, 0x2378, + 0x875b, 0x21cf, + 0x875c, 0x2368, + 0x875d, 0x2b75, + 0x875e, 0x2371, + 0x875f, 0x2b76, + 0x8760, 0x2369, + 0x8761, 0x2b77, + 0x8766, 0x2674, + 0x8767, 0x2b7c, + 0x877a, 0x236f, + 0x877b, 0x2b8f, + 0x877d, 0x2370, + 0x877e, 0x2b91, + 0x8780, 0x2b92, + 0x8781, 0x2376, + 0x8782, 0x2373, + 0x8783, 0x2b93, + 0x8786, 0x237f, + 0x8787, 0x2b96, + 0x8788, 0x2374, + 0x8789, 0x2b97, + 0x878a, 0x20b5, + 0x878b, 0x2b98, + 0x878d, 0x1edb, + 0x878e, 0x2672, + 0x878f, 0x2b9a, + 0x8793, 0x236e, + 0x8794, 0x2b9e, + 0x8798, 0x21b7, + 0x8799, 0x2ba2, + 0x879d, 0x2375, + 0x879e, 0x2ba6, + 0x87a3, 0x2382, + 0x87a4, 0x2bab, + 0x87a7, 0x209e, + 0x87a8, 0x2bae, + 0x87b3, 0x236b, + 0x87b4, 0x2bb9, + 0x87b5, 0x2039, + 0x87b6, 0x2bba, + 0x87bb, 0x269f, + 0x87bc, 0x2bbf, + 0x87bf, 0x237d, + 0x87c0, 0x21f5, + 0x87c1, 0x2bc2, + 0x87c2, 0x2381, + 0x87c3, 0x2bc3, + 0x87ca, 0x237b, + 0x87cb, 0x237e, + 0x87cc, 0x21cc, + 0x87cd, 0x2bca, + 0x87cf, 0x22db, + 0x87d0, 0x2bcc, + 0x87d2, 0x236a, + 0x87d3, 0x2689, + 0x87d4, 0x2bce, + 0x87d5, 0x2697, + 0x87d6, 0x2bcf, + 0x87da, 0x22a1, + 0x87db, 0x2bd3, + 0x87f7, 0x2383, + 0x87f8, 0x1f3d, + 0x87f9, 0x2bef, + 0x87fa, 0x218f, + 0x87fb, 0x2bf0, + 0x8840, 0x2246, + 0x8841, 0x2248, + 0x8842, 0x2bf4, + 0x8844, 0x217e, + 0x8845, 0x2bf6, + 0x8846, 0x2180, + 0x8847, 0x2bf7, + 0x8880, 0x2c2f, + 0x88ba, 0x232a, + 0x88bb, 0x2c69, + 0x88cc, 0x228b, + 0x88cd, 0x2c7a, + 0x88d4, 0x1f85, + 0x88d5, 0x2c81, + 0x88d7, 0x2325, + 0x88d8, 0x2c83, + 0x88df, 0x232c, + 0x88e0, 0x2c8a, + 0x88e5, 0x232e, + 0x88e6, 0x2c8f, + 0x88f2, 0x2205, + 0x88f3, 0x1e38, + 0x88f4, 0x2c9b, + 0x88f6, 0x1e73, + 0x88f7, 0x2c9d, + 0x8940, 0x2ca5, + 0x894b, 0x1fe3, + 0x894c, 0x2339, + 0x894d, 0x2cb0, + 0x894e, 0x232b, + 0x894f, 0x2cb1, + 0x8950, 0x232d, + 0x8951, 0x2cb2, + 0x8954, 0x217f, + 0x8955, 0x2cb5, + 0x895d, 0x21a7, + 0x895e, 0x2cbd, + 0x895f, 0x232f, + 0x8960, 0x2cbe, + 0x896d, 0x1e7d, + 0x896e, 0x2ccb, + 0x8971, 0x20d6, + 0x8972, 0x2cce, + 0x897c, 0x1ec2, + 0x897d, 0x2cd8, + 0x8980, 0x2cda, + 0x898b, 0x22b2, + 0x898c, 0x2ce5, + 0x8999, 0x1edf, + 0x899a, 0x2cf2, + 0x899e, 0x1ef9, + 0x899f, 0x2cf6, + 0x89a6, 0x20d9, + 0x89a7, 0x2cfd, + 0x89a8, 0x1fdd, + 0x89a9, 0x2cfe, + 0x89af, 0x2167, + 0x89b0, 0x2d04, + 0x89ba, 0x21ed, + 0x89bb, 0x2d0e, + 0x89be, 0x2007, + 0x89bf, 0x2326, + 0x89c0, 0x2329, + 0x89c1, 0x2d11, + 0x89c4, 0x1f52, + 0x89c5, 0x203b, + 0x89c6, 0x2328, + 0x89c7, 0x2d14, + 0x89c8, 0x2327, + 0x89c9, 0x2d15, + 0x89ce, 0x1e2b, + 0x89cf, 0x2d1a, + 0x89d1, 0x22ae, + 0x89d2, 0x2d1c, + 0x89d8, 0x1f49, + 0x89d9, 0x2d22, + 0x89db, 0x2138, + 0x89dc, 0x2d24, + 0x89f4, 0x2081, + 0x89f5, 0x2d3c, + 0x8a40, 0x2d46, + 0x8a41, 0x1f7c, + 0x8a42, 0x2d47, + 0x8a59, 0x235b, + 0x8a5a, 0x1ede, + 0x8a5b, 0x2d5e, + 0x8a5c, 0x1fa2, + 0x8a5d, 0x2d5f, + 0x8a5e, 0x1efa, + 0x8a5f, 0x2d60, + 0x8a79, 0x22ad, + 0x8a7a, 0x2d7a, + 0x8a80, 0x2d7f, + 0x8ae4, 0x203f, + 0x8ae5, 0x2de3, + 0x8b40, 0x2dfd, + 0x8b44, 0x1f0e, + 0x8b45, 0x2e01, + 0x8b49, 0x23f9, + 0x8b4a, 0x2e05, + 0x8b7a, 0x23fc, + 0x8b7b, 0x2e35, + 0x8b80, 0x2e39, + 0x8b8c, 0x2069, + 0x8b8d, 0x2e45, + 0x8b9e, 0x23f7, + 0x8b9f, 0x2e56, + 0x8bb3, 0x23f6, + 0x8bb4, 0x2e6a, + 0x8bb9, 0x23fd, + 0x8bba, 0x2e6f, + 0x8bbe, 0x23f8, + 0x8bbf, 0x2e73, + 0x8bc6, 0x23fa, + 0x8bc7, 0x2e7a, + 0x8bc8, 0x23fe, + 0x8bc9, 0x1fa8, + 0x8bca, 0x2e7b, + 0x8bd4, 0x2401, + 0x8bd5, 0x2e85, + 0x8bdc, 0x23ff, + 0x8bdd, 0x2e8c, + 0x8be5, 0x2400, + 0x8be6, 0x2e94, + 0x8beb, 0x2221, + 0x8bec, 0x2e99, + 0x8bf0, 0x2122, + 0x8bf1, 0x2e9d, + 0x8c40, 0x2eab, + 0x8c44, 0x23fb, + 0x8c45, 0x2eaf, + 0x8c4f, 0x215a, + 0x8c50, 0x2eb9, + 0x8c57, 0x21e5, + 0x8c58, 0x2ec0, + 0x8c5c, 0x2057, + 0x8c5d, 0x2ec4, + 0x8c80, 0x2ee6, + 0x8c8b, 0x20e5, + 0x8c8c, 0x2ef1, + 0x8c8d, 0x212f, + 0x8c8e, 0x20a3, + 0x8c8f, 0x2121, + 0x8c90, 0x2ef2, + 0x8c91, 0x21d4, + 0x8c92, 0x1fe5, + 0x8c93, 0x2ef3, + 0x8c99, 0x1e8a, + 0x8c9a, 0x1e37, + 0x8c9b, 0x2ef9, + 0x8ca2, 0x1f9e, + 0x8ca3, 0x22a6, + 0x8ca4, 0x21e8, + 0x8ca5, 0x2f00, + 0x8ca6, 0x1eda, + 0x8ca7, 0x1eb9, + 0x8ca8, 0x2f01, + 0x8cc0, 0x235c, + 0x8cc1, 0x2f19, + 0x8cd2, 0x2050, + 0x8cd3, 0x1e67, + 0x8cd4, 0x2f2a, + 0x8cd5, 0x23f4, + 0x8cd6, 0x2f2b, + 0x8cd9, 0x213e, + 0x8cda, 0x2f2e, + 0x8cf9, 0x1f16, + 0x8cfa, 0x2f4d, + 0x8d40, 0x2f52, + 0x8d73, 0x2389, + 0x8d74, 0x2f85, + 0x8d75, 0x1eb7, + 0x8d76, 0x2f86, + 0x8d7b, 0x21b4, + 0x8d7c, 0x2f8b, + 0x8d80, 0x2f8e, + 0x8d88, 0x238f, + 0x8d89, 0x2f96, + 0x8d8f, 0x1f1a, + 0x8d90, 0x2f9c, + 0x8d9e, 0x238b, + 0x8d9f, 0x2faa, + 0x8db9, 0x238a, + 0x8dba, 0x2fc4, + 0x8de2, 0x2391, + 0x8de3, 0x2fec, + 0x8de4, 0x2271, + 0x8de5, 0x2fed, + 0x8de7, 0x2388, + 0x8de8, 0x2fef, + 0x8df7, 0x238e, + 0x8df8, 0x2ffe, + 0x8dfe, 0x238d, + 0x8e40, 0x3004, + 0x8e46, 0x238c, + 0x8e47, 0x300a, + 0x8e56, 0x2390, + 0x8e57, 0x3019, + 0x8e58, 0x2033, + 0x8e59, 0x301a, + 0x8e5a, 0x223c, + 0x8e5b, 0x301b, + 0x8e68, 0x1fe9, + 0x8e69, 0x3028, + 0x8e6e, 0x2055, + 0x8e6f, 0x302d, + 0x8e70, 0x2392, + 0x8e71, 0x302e, + 0x8e80, 0x2324, + 0x8e81, 0x303c, + 0x8e9b, 0x2143, + 0x8e9c, 0x3056, + 0x8e9f, 0x2129, + 0x8ea0, 0x3059, + 0x8ea4, 0x2277, + 0x8ea5, 0x305d, + 0x8ea7, 0x1ea7, + 0x8ea8, 0x305f, + 0x8eac, 0x2285, + 0x8ead, 0x3063, + 0x8eae, 0x2384, + 0x8eaf, 0x3064, + 0x8ebd, 0x2387, + 0x8ebe, 0x2386, + 0x8ebf, 0x3072, + 0x8ec3, 0x2290, + 0x8ec4, 0x3076, + 0x8ec5, 0x1e44, + 0x8ec6, 0x3077, + 0x8ecd, 0x1e32, + 0x8ece, 0x2385, + 0x8ecf, 0x307e, + 0x8ed6, 0x1f13, + 0x8ed7, 0x1f73, + 0x8ed8, 0x3085, + 0x8eec, 0x1fe0, + 0x8eed, 0x3099, + 0x8f40, 0x30ab, + 0x8f52, 0x2087, + 0x8f53, 0x1e78, + 0x8f54, 0x23ae, + 0x8f55, 0x1ef6, + 0x8f56, 0x1f31, + 0x8f57, 0x30bd, + 0x8f5d, 0x2045, + 0x8f5e, 0x30c3, + 0x8f64, 0x2178, + 0x8f65, 0x30c9, + 0x8f80, 0x30e3, + 0x8f86, 0x23f5, + 0x8f87, 0x30e9, + 0x8f88, 0x2275, + 0x8f89, 0x30ea, + 0x8f95, 0x266e, + 0x8f96, 0x30f6, + 0x8f97, 0x1eb0, + 0x8f98, 0x30f7, + 0x8f9b, 0x2083, + 0x8f9c, 0x30fa, + 0x8f9d, 0x2188, + 0x8f9e, 0x30fb, + 0x8fa1, 0x267c, + 0x8fa2, 0x30fe, + 0x8fbd, 0x1fc5, + 0x8fbe, 0x3119, + 0x8fc4, 0x1ea1, + 0x8fc5, 0x311f, + 0x8fc6, 0x2393, + 0x8fc7, 0x3120, + 0x8fcd, 0x1f0b, + 0x8fce, 0x3126, + 0x8fd8, 0x1e7c, + 0x8fd9, 0x3130, + 0x9040, 0x3156, + 0x9080, 0x3195, + 0x909d, 0x23b4, + 0x909e, 0x207e, + 0x909f, 0x31b2, + 0x90ba, 0x1ee3, + 0x90bb, 0x31cd, + 0x90c0, 0x2095, + 0x90c1, 0x23bb, + 0x90c2, 0x31d2, + 0x90c5, 0x23b9, + 0x90c6, 0x31d5, + 0x90db, 0x1e28, + 0x90dc, 0x23bd, + 0x90dd, 0x31ea, + 0x90ed, 0x23b5, + 0x90ee, 0x31fa, + 0x90f0, 0x23ba, + 0x90f1, 0x31fc, + 0x90f7, 0x23b3, + 0x90f8, 0x3202, + 0x9140, 0x3209, + 0x9142, 0x2162, + 0x9143, 0x320b, + 0x914b, 0x1e5e, + 0x914c, 0x3213, + 0x914d, 0x1e5d, + 0x914e, 0x3214, + 0x9151, 0x23b7, + 0x9152, 0x3217, + 0x9154, 0x1f2f, + 0x9155, 0x24df, + 0x9156, 0x3219, + 0x9159, 0x23b2, + 0x915a, 0x214e, + 0x915b, 0x321c, + 0x915d, 0x2052, + 0x915e, 0x321e, + 0x9161, 0x23bc, + 0x9162, 0x3221, + 0x9163, 0x20eb, + 0x9164, 0x3222, + 0x916e, 0x2232, + 0x916f, 0x322c, + 0x9176, 0x1e3f, + 0x9177, 0x3233, + 0x917a, 0x201b, + 0x917b, 0x20bc, + 0x917c, 0x23be, + 0x917d, 0x3236, + 0x9180, 0x3238, + 0x9184, 0x1eae, + 0x9185, 0x323c, + 0x918d, 0x1efb, + 0x918e, 0x3244, + 0x9191, 0x2089, + 0x9192, 0x3247, + 0x9193, 0x23b1, + 0x9194, 0x3248, + 0x9197, 0x21c4, + 0x9198, 0x324b, + 0x919b, 0x2214, + 0x919c, 0x324e, + 0x91a9, 0x1fde, + 0x91aa, 0x2223, + 0x91ab, 0x23b6, + 0x91ac, 0x325b, + 0x91ba, 0x268c, + 0x91bb, 0x24de, + 0x91bc, 0x3269, + 0x91bf, 0x24e0, + 0x91c0, 0x326c, + 0x91c3, 0x23b8, + 0x91c4, 0x326f, + 0x91cd, 0x1e81, + 0x91ce, 0x3278, + 0x91d0, 0x1ffe, + 0x91d1, 0x1f51, + 0x91d2, 0x21e1, + 0x91d3, 0x327a, + 0x91d4, 0x23b0, + 0x91d5, 0x327b, + 0x91d6, 0x1fce, + 0x91d7, 0x327c, + 0x91d8, 0x211e, + 0x91d9, 0x2021, + 0x91da, 0x327d, + 0x91df, 0x24e1, + 0x91e0, 0x3282, + 0x91e2, 0x24a3, + 0x91e3, 0x3284, + 0x91ea, 0x24a4, + 0x91eb, 0x328b, + 0x91f0, 0x2273, + 0x91f1, 0x3290, + 0x91f2, 0x21b0, + 0x91f3, 0x3291, + 0x9240, 0x329d, + 0x9280, 0x32dc, + 0x92b6, 0x21d1, + 0x92b7, 0x3312, + 0x92ce, 0x211c, + 0x92cf, 0x3329, + 0x92d0, 0x235d, + 0x92d1, 0x332a, + 0x92d4, 0x2682, + 0x92d5, 0x332d, + 0x92df, 0x210d, + 0x92e0, 0x205a, + 0x92e1, 0x3337, + 0x92fe, 0x1f8d, + 0x9340, 0x3354, + 0x9350, 0x21ff, + 0x9351, 0x3364, + 0x935d, 0x1f58, + 0x935e, 0x3370, + 0x9370, 0x215b, + 0x9371, 0x3382, + 0x9376, 0x1eb6, + 0x9377, 0x3387, + 0x9380, 0x338f, + 0x938c, 0x20db, + 0x938d, 0x339b, + 0x939d, 0x2360, + 0x939e, 0x33ab, + 0x93a5, 0x2361, + 0x93a6, 0x33b2, + 0x93a7, 0x2040, + 0x93a8, 0x33b3, + 0x93b4, 0x228e, + 0x93b5, 0x33bf, + 0x93b8, 0x1fdf, + 0x93b9, 0x33c2, + 0x93bb, 0x235e, + 0x93bc, 0x33c4, + 0x93bd, 0x1e6a, + 0x93be, 0x33c5, + 0x93c6, 0x2002, + 0x93c7, 0x33cd, + 0x93cf, 0x2093, + 0x93d0, 0x33d5, + 0x93d7, 0x235f, + 0x93d8, 0x33dc, + 0x93db, 0x1eac, + 0x93dc, 0x1e54, + 0x93dd, 0x33df, + 0x93e1, 0x1f08, + 0x93e2, 0x33e3, + 0x93e4, 0x20c0, + 0x93e5, 0x2362, + 0x93e6, 0x33e5, + 0x93e9, 0x2160, + 0x93ea, 0x33e8, + 0x93eb, 0x219d, + 0x93ec, 0x1f8e, + 0x93ed, 0x222d, + 0x93ee, 0x33e9, + 0x93ef, 0x2047, + 0x93f0, 0x33ea, + 0x93f1, 0x2262, + 0x93f2, 0x33eb, + 0x93f4, 0x1f67, + 0x93f5, 0x1eb2, + 0x93f6, 0x33ed, + 0x93fa, 0x1ea9, + 0x93fb, 0x33f1, + 0x93fe, 0x1fcc, + 0x9440, 0x33f4, + 0x9444, 0x1f72, + 0x9445, 0x33f8, + 0x944d, 0x2098, + 0x944e, 0x3400, + 0x9450, 0x1e52, + 0x9451, 0x20a4, + 0x9452, 0x1f1c, + 0x9453, 0x228f, + 0x9454, 0x3402, + 0x9455, 0x1fed, + 0x9456, 0x3403, + 0x9458, 0x2365, + 0x9459, 0x3405, + 0x945b, 0x1e2d, + 0x945c, 0x2152, + 0x945d, 0x2366, + 0x945e, 0x3407, + 0x945f, 0x20fa, + 0x9460, 0x3408, + 0x9464, 0x2363, + 0x9465, 0x340c, + 0x9466, 0x209a, + 0x9467, 0x340d, + 0x946e, 0x203c, + 0x946f, 0x3414, + 0x9472, 0x1ff6, + 0x9473, 0x3417, + 0x9474, 0x2364, + 0x9475, 0x3418, + 0x9476, 0x1e69, + 0x9477, 0x3419, + 0x9478, 0x2367, + 0x9479, 0x341a, + 0x947a, 0x211d, + 0x947b, 0x341b, + 0x9480, 0x2259, + 0x9481, 0x2056, + 0x9482, 0x2163, + 0x9483, 0x341f, + 0x9487, 0x1fa9, + 0x9488, 0x1ffc, + 0x9489, 0x3423, + 0x94a1, 0x1e2e, + 0x94a2, 0x343b, + 0x94b3, 0x1ebc, + 0x94b4, 0x344c, + 0x94b5, 0x2142, + 0x94b6, 0x344d, + 0x94bf, 0x201e, + 0x94c0, 0x1e43, + 0x94c1, 0x3456, + 0x94cc, 0x24d4, + 0x94cd, 0x3461, + 0x94d8, 0x226f, + 0x94d9, 0x346c, + 0x94e0, 0x1ed7, + 0x94e1, 0x3473, + 0x9540, 0x3491, + 0x9572, 0x212d, + 0x9573, 0x34c3, + 0x9580, 0x34cf, + 0x9583, 0x229b, + 0x9584, 0x34d2, + 0x959e, 0x2256, + 0x959f, 0x24a8, + 0x95a0, 0x34ec, + 0x95b3, 0x1e79, + 0x95b4, 0x34ff, + 0x95ba, 0x225a, + 0x95bb, 0x3505, + 0x95cf, 0x24a7, + 0x95d0, 0x3519, + 0x95d1, 0x2686, + 0x95d2, 0x24a6, + 0x95d3, 0x351a, + 0x95d4, 0x21ce, + 0x95d5, 0x351b, + 0x95e1, 0x24a9, + 0x95e2, 0x3527, + 0x95e7, 0x1fe7, + 0x95e8, 0x352c, + 0x95f1, 0x2112, + 0x95f2, 0x3535, + 0x95f8, 0x213c, + 0x95f9, 0x353b, + 0x95fe, 0x1f5c, + 0x9640, 0x3540, + 0x9656, 0x24c4, + 0x9657, 0x3556, + 0x967c, 0x1ecc, + 0x967d, 0x357b, + 0x9680, 0x357d, + 0x9740, 0x35fc, + 0x9767, 0x246a, + 0x9768, 0x3623, + 0x976c, 0x2175, + 0x976d, 0x3627, + 0x976e, 0x246d, + 0x976f, 0x3628, + 0x9780, 0x3638, + 0x9796, 0x246b, + 0x9797, 0x225f, + 0x9798, 0x364e, + 0x979d, 0x1ece, + 0x979e, 0x3653, + 0x97a3, 0x2272, + 0x97a4, 0x3658, + 0x97bf, 0x2473, + 0x97c0, 0x3673, + 0x97ee, 0x21fe, + 0x97ef, 0x36a1, + 0x97f7, 0x1efe, + 0x97f8, 0x36a9, + 0x9840, 0x36b0, + 0x9845, 0x2475, + 0x9846, 0x36b5, + 0x9849, 0x220a, + 0x984a, 0x36b8, + 0x984f, 0x1f6f, + 0x9850, 0x36bd, + 0x9871, 0x2468, + 0x9872, 0x36de, + 0x9873, 0x2100, + 0x9874, 0x36df, + 0x9880, 0x36ea, + 0x9881, 0x2476, + 0x9882, 0x36eb, + 0x988b, 0x1f27, + 0x988c, 0x20d7, + 0x988d, 0x36f4, + 0x98a0, 0x247c, + 0x98a1, 0x3707, + 0x98aa, 0x1fa1, + 0x98ab, 0x3710, + 0x98b6, 0x22aa, + 0x98b7, 0x2005, + 0x98b8, 0x371b, + 0x98ba, 0x246c, + 0x98bb, 0x371d, + 0x98c7, 0x203e, + 0x98c8, 0x3729, + 0x98cb, 0x1e4c, + 0x98cc, 0x372c, + 0x98d0, 0x213a, + 0x98d1, 0x3730, + 0x98d3, 0x2204, + 0x98d4, 0x3732, + 0x98e3, 0x20c3, + 0x98e4, 0x2140, + 0x98e5, 0x2477, + 0x98e6, 0x3741, + 0x98ef, 0x2474, + 0x98f0, 0x374a, + 0x98f2, 0x20dd, + 0x98f3, 0x374c, + 0x9940, 0x3758, + 0x9943, 0x1f68, + 0x9944, 0x375b, + 0x9945, 0x2185, + 0x9946, 0x375c, + 0x9966, 0x2472, + 0x9967, 0x377c, + 0x996e, 0x1eb5, + 0x996f, 0x3783, + 0x9975, 0x2478, + 0x9976, 0x3789, + 0x997a, 0x1f8b, + 0x997b, 0x2484, + 0x997c, 0x378d, + 0x9980, 0x3790, + 0x9985, 0x2699, + 0x9986, 0x3795, + 0x9989, 0x2482, + 0x998a, 0x3798, + 0x998e, 0x20a1, + 0x998f, 0x379c, + 0x9991, 0x1f92, + 0x9992, 0x379e, + 0x9999, 0x1f38, + 0x999a, 0x37a5, + 0x99a9, 0x2485, + 0x99aa, 0x37b4, + 0x99b0, 0x2480, + 0x99b1, 0x246e, + 0x99b2, 0x37ba, + 0x99b3, 0x247b, + 0x99b4, 0x2486, + 0x99b5, 0x2471, + 0x99b6, 0x37bb, + 0x99bd, 0x2483, + 0x99be, 0x2470, + 0x99bf, 0x37c2, + 0x99c0, 0x2469, + 0x99c1, 0x37c3, + 0x99c2, 0x247f, + 0x99c3, 0x37c4, + 0x99c9, 0x246f, + 0x99ca, 0x37ca, + 0x99ce, 0x2481, + 0x99cf, 0x37ce, + 0x99d1, 0x2220, + 0x99d2, 0x37d0, + 0x99da, 0x1ff5, + 0x99db, 0x37d8, + 0x99e0, 0x20f4, + 0x99e1, 0x37dd, + 0x99e5, 0x247d, + 0x99e6, 0x37e1, + 0x99e8, 0x2479, + 0x99e9, 0x37e3, + 0x99ec, 0x247e, + 0x99ed, 0x37e6, + 0x99f4, 0x247a, + 0x99f5, 0x37ed, + 0x9a40, 0x37f7, + 0x9a4a, 0x20e3, + 0x9a4b, 0x3801, + 0x9a57, 0x20ad, + 0x9a58, 0x380d, + 0x9a65, 0x24cb, + 0x9a66, 0x381a, + 0x9a67, 0x1f53, + 0x9a68, 0x381b, + 0x9a71, 0x2159, + 0x9a72, 0x3824, + 0x9a76, 0x2013, + 0x9a77, 0x1f33, + 0x9a78, 0x3828, + 0x9a80, 0x382f, + 0x9a88, 0x1e5c, + 0x9a89, 0x3837, + 0x9a8c, 0x2488, + 0x9a8d, 0x383a, + 0x9a91, 0x2487, + 0x9a92, 0x383e, + 0x9a97, 0x248a, + 0x9a98, 0x3843, + 0x9a9a, 0x2489, + 0x9a9b, 0x248b, + 0x9a9c, 0x3845, + 0x9a9e, 0x1f83, + 0x9a9f, 0x3847, + 0x9aa2, 0x210f, + 0x9aa3, 0x1fdb, + 0x9aa4, 0x384a, + 0x9aaa, 0x20af, + 0x9aab, 0x3850, + 0x9ad0, 0x24c0, + 0x9ad1, 0x3875, + 0x9ad6, 0x226d, + 0x9ad7, 0x387a, + 0x9ada, 0x24c1, + 0x9adb, 0x387d, + 0x9ae2, 0x20ca, + 0x9ae3, 0x3884, + 0x9ae4, 0x20e7, + 0x9ae5, 0x24c2, + 0x9ae6, 0x3885, + 0x9b40, 0x389e, + 0x9b80, 0x38dd, + 0x9bd1, 0x23dc, + 0x9bd2, 0x392e, + 0x9bdc, 0x23db, + 0x9bdd, 0x3938, + 0x9c40, 0x395a, + 0x9c53, 0x205e, + 0x9c54, 0x396d, + 0x9c59, 0x2244, + 0x9c5a, 0x23e2, + 0x9c5b, 0x3972, + 0x9c5c, 0x20d4, + 0x9c5d, 0x3973, + 0x9c75, 0x219f, + 0x9c76, 0x398b, + 0x9c79, 0x1e66, + 0x9c7a, 0x398e, + 0x9c80, 0x3993, + 0x9c86, 0x1f63, + 0x9c87, 0x3999, + 0x9c9d, 0x23dd, + 0x9c9e, 0x39af, + 0x9cab, 0x216b, + 0x9cac, 0x39bc, + 0x9cca, 0x22b5, + 0x9ccb, 0x39da, + 0x9ccf, 0x1f26, + 0x9cd0, 0x39de, + 0x9ce6, 0x1e63, + 0x9ce7, 0x2088, + 0x9ce8, 0x39f4, + 0x9cec, 0x1ebd, + 0x9ced, 0x39f8, + 0x9cee, 0x2341, + 0x9cef, 0x39f9, + 0x9cfb, 0x1f4b, + 0x9cfc, 0x3a05, + 0x9cfe, 0x2292, + 0x9d40, 0x3a07, + 0x9d42, 0x2124, + 0x9d43, 0x3a09, + 0x9d46, 0x2048, + 0x9d47, 0x23e0, + 0x9d48, 0x3a0c, + 0x9d4d, 0x2077, + 0x9d4e, 0x3a11, + 0x9d4f, 0x223a, + 0x9d50, 0x3a12, + 0x9d61, 0x20b1, + 0x9d62, 0x3a23, + 0x9d68, 0x1f41, + 0x9d69, 0x201c, + 0x9d6a, 0x3a29, + 0x9d6e, 0x22b8, + 0x9d6f, 0x3a2d, + 0x9d71, 0x2276, + 0x9d72, 0x3a2f, + 0x9d75, 0x1f9b, + 0x9d76, 0x3a32, + 0x9d7b, 0x1f9f, + 0x9d7c, 0x3a37, + 0x9d7d, 0x25ca, + 0x9d7e, 0x3a38, + 0x9d80, 0x3a39, + 0x9d8a, 0x20be, + 0x9d8b, 0x3a43, + 0x9d8d, 0x1fb4, + 0x9d8e, 0x3a45, + 0x9d91, 0x23d7, + 0x9d92, 0x3a48, + 0x9d99, 0x2105, + 0x9d9a, 0x3a4f, + 0x9da1, 0x23e1, + 0x9da2, 0x1fec, + 0x9da3, 0x3a56, + 0x9da7, 0x23ea, + 0x9da8, 0x3a5a, + 0x9dac, 0x23e3, + 0x9dad, 0x210e, + 0x9dae, 0x3a5e, + 0x9db2, 0x1fa6, + 0x9db3, 0x2004, + 0x9db4, 0x3a62, + 0x9dbe, 0x1f9d, + 0x9dbf, 0x3a6c, + 0x9dc6, 0x23e5, + 0x9dc7, 0x3a73, + 0x9dc9, 0x2264, + 0x9dca, 0x3a75, + 0x9dcd, 0x24e2, + 0x9dce, 0x3a78, + 0x9dd2, 0x23de, + 0x9dd3, 0x3a7c, + 0x9dd5, 0x1ec4, + 0x9dd6, 0x3a7e, + 0x9de1, 0x22b6, + 0x9de2, 0x20a9, + 0x9de3, 0x3a89, + 0x9df1, 0x212b, + 0x9df2, 0x3a97, + 0x9df4, 0x20a5, + 0x9df5, 0x3a99, + 0x9df7, 0x268b, + 0x9df8, 0x3a9b, + 0x9dfa, 0x1f76, + 0x9dfb, 0x3a9d, + 0x9dfd, 0x216d, + 0x9dfe, 0x3a9f, + 0x9e40, 0x3aa0, + 0x9e45, 0x2001, + 0x9e46, 0x3aa5, + 0x9e48, 0x2191, + 0x9e49, 0x1e50, + 0x9e4a, 0x3aa7, + 0x9e52, 0x1f9c, + 0x9e53, 0x3aaf, + 0x9e54, 0x23da, + 0x9e55, 0x3ab0, + 0x9e56, 0x2053, + 0x9e57, 0x3ab1, + 0x9e5d, 0x23e9, + 0x9e5e, 0x23e4, + 0x9e5f, 0x3ab7, + 0x9e61, 0x21d5, + 0x9e62, 0x3ab9, + 0x9e63, 0x23e6, + 0x9e64, 0x3aba, + 0x9e67, 0x23df, + 0x9e68, 0x3abd, + 0x9e6c, 0x1e4f, + 0x9e6d, 0x3ac1, + 0x9e6f, 0x23d9, + 0x9e70, 0x3ac3, + 0x9e72, 0x2014, + 0x9e73, 0x3ac5, + 0x9e74, 0x23ec, + 0x9e75, 0x23eb, + 0x9e76, 0x3ac6, + 0x9e7b, 0x23d8, + 0x9e7c, 0x23ee, + 0x9e7d, 0x3acb, + 0x9e80, 0x3acd, + 0x9e85, 0x268e, + 0x9e86, 0x3ad2, + 0x9e87, 0x23ed, + 0x9e88, 0x3ad3, + 0x9e91, 0x1ffa, + 0x9e92, 0x3adc, + 0x9e96, 0x23d6, + 0x9e97, 0x23e8, + 0x9e98, 0x3ae0, + 0x9ea2, 0x2106, + 0x9ea3, 0x3aea, + 0x9ea6, 0x200b, + 0x9ea7, 0x3aed, + 0x9ea9, 0x2166, + 0x9eaa, 0x3aef, + 0x9eae, 0x23ef, + 0x9eaf, 0x3af3, + 0x9eb3, 0x2189, + 0x9eb4, 0x2058, + 0x9eb5, 0x3af7, + 0x9eb7, 0x23e7, + 0x9eb8, 0x3af9, + 0x9ef5, 0x21a3, + 0x9ef6, 0x3b36, + 0x9f40, 0x3b3f, + 0x9f4e, 0x217a, + 0x9f4f, 0x3b4d, + 0x9f6f, 0x21a5, + 0x9f70, 0x3b6d, + 0x9f80, 0x3b7c, + 0x9f92, 0x2022, + 0x9f93, 0x3b8e, + 0x9f98, 0x24d6, + 0x9f99, 0x3b93, + 0x9fa6, 0x233a, + 0x9fa7, 0x3ba0, + 0x9fa9, 0x1eee, + 0x9faa, 0x3ba2, + 0x9fac, 0x24d5, + 0x9fad, 0x3ba4, + 0x9fc9, 0x2228, + 0x9fca, 0x3bc0, + 0x9fcd, 0x24d7, + 0x9fce, 0x3bc3, + 0x9fe1, 0x20fc, + 0x9fe2, 0x3bd6, + 0x9feb, 0x1e87, + 0x9fec, 0x3bdf, + 0x9fee, 0x24d8, + 0x9fef, 0x3be1, + 0x9ff4, 0x1eba, + 0x9ff5, 0x3be6, + 0x9ffd, 0x2119, + 0x9ffe, 0x3bee, + 0xa040, 0x3bef, + 0xa043, 0x216c, + 0xa044, 0x3bf2, + 0xa046, 0x24d9, + 0xa047, 0x3bf4, + 0xa049, 0x2227, + 0xa04a, 0x3bf6, + 0xa04e, 0x1e5f, + 0xa04f, 0x3bfa, + 0xa054, 0x229f, + 0xa055, 0x3bff, + 0xa05a, 0x1f5d, + 0xa05b, 0x3c04, + 0xa061, 0x1fbc, + 0xa062, 0x3c0a, + 0xa063, 0x24da, + 0xa064, 0x3c0b, + 0xa071, 0x2149, + 0xa072, 0x3c18, + 0xa074, 0x2046, + 0xa075, 0x3c1a, + 0xa080, 0x2000, + 0xa081, 0x3c24, + 0xa091, 0x2190, + 0xa092, 0x3c34, + 0xa094, 0x2208, + 0xa095, 0x3c36, + 0xa096, 0x1ee6, + 0xa097, 0x3c37, + 0xa0a9, 0x24c3, + 0xa0aa, 0x3c49, + 0xa0bf, 0x20cc, + 0xa0c0, 0x3c5e, + 0xa0ce, 0x2340, + 0xa0cf, 0x3c6c, + 0xa0d9, 0x1ed1, + 0xa0da, 0x3c76, + 0xa0de, 0x21ac, + 0xa0df, 0x3c7a, + 0xa0ee, 0x22af, + 0xa0ef, 0x3c89, + 0xa1a1, 0x0060, + 0xa2a1, 0x26a9, + 0xa2b1, 0x00be, + 0xa2e5, 0x00f0, + 0xa2f1, 0x00fa, + 0xa3a1, 0x0106, + 0xa4a1, 0x0164, + 0xa5a1, 0x01b7, + 0xa6a1, 0x020d, + 0xa6c1, 0x0225, + 0xa7a1, 0x025a, + 0xa7d1, 0x027b, + 0xa840, 0x26b3, + 0xa880, 0x26f2, + 0xa8a1, 0x029c, + 0xa8c5, 0x02bc, + 0xa940, 0x2708, + 0xa959, 0x2720, + 0xa95c, 0x2722, + 0xa960, 0x2723, + 0xa980, 0x2742, + 0xa996, 0x1e17, + 0xa9a4, 0x02e2, + 0xaa40, 0x3c99, + 0xaa4d, 0x21b6, + 0xaa4e, 0x1e3d, + 0xaa4f, 0x3ca6, + 0xaa71, 0x2235, + 0xaa72, 0x3cc8, + 0xaa73, 0x2397, + 0xaa74, 0x3cc9, + 0xaa77, 0x2395, + 0xaa78, 0x3ccc, + 0xaa7a, 0x223f, + 0xaa7b, 0x212a, + 0xaa7c, 0x3cce, + 0xaa80, 0x3cd1, + 0xaa9a, 0x1ed2, + 0xaa9b, 0x3ceb, + 0xaa9c, 0x2396, + 0xaa9d, 0x2398, + 0xaa9e, 0x3cec, + 0xaa9f, 0x20a2, + 0xaaa0, 0x3ced, + 0xaaa1, 0x032e, + 0xab40, 0x1f64, + 0xab41, 0x3cee, + 0xab43, 0x202b, + 0xab44, 0x3cf0, + 0xab45, 0x2394, + 0xab46, 0x2139, + 0xab47, 0x3cf1, + 0xab48, 0x215f, + 0xab49, 0x21c1, + 0xab4a, 0x239a, + 0xab4b, 0x3cf2, + 0xab4d, 0x2399, + 0xab4e, 0x3cf4, + 0xab80, 0x3d25, + 0xaba1, 0x038c, + 0xac40, 0x3d46, + 0xac46, 0x21c0, + 0xac47, 0x3d4c, + 0xac71, 0x2460, + 0xac72, 0x3d76, + 0xac7c, 0x245c, + 0xac7d, 0x3d80, + 0xac80, 0x3d82, + 0xac8d, 0x215d, + 0xac8e, 0x3d8f, + 0xac93, 0x2225, + 0xac94, 0x206a, + 0xac95, 0x3d94, + 0xad40, 0x3da0, + 0xad49, 0x2461, + 0xad4a, 0x3da9, + 0xad5e, 0x245b, + 0xad5f, 0x3dbd, + 0xad61, 0x2462, + 0xad62, 0x3dbf, + 0xad68, 0x1f54, + 0xad69, 0x3dc5, + 0xad74, 0x245f, + 0xad75, 0x3dd0, + 0xad80, 0x3dda, + 0xad82, 0x20ec, + 0xad83, 0x3ddc, + 0xad87, 0x245d, + 0xad88, 0x3de0, + 0xad8b, 0x2463, + 0xad8c, 0x3de3, + 0xad91, 0x2464, + 0xad92, 0x3de8, + 0xae40, 0x3df7, + 0xae54, 0x24a5, + 0xae55, 0x3e0b, + 0xae62, 0x1e70, + 0xae63, 0x3e18, + 0xae80, 0x208f, + 0xae81, 0x3e34, + 0xae85, 0x1e42, + 0xae86, 0x3e38, + 0xae8b, 0x1f4e, + 0xae8c, 0x3e3d, + 0xae94, 0x1eb1, + 0xae95, 0x3e45, + 0xaea0, 0x1e8b, + 0xaf40, 0x3e50, + 0xaf64, 0x1fc6, + 0xaf65, 0x3e74, + 0xaf7b, 0x25ae, + 0xaf7c, 0x3e8a, + 0xaf80, 0x3e8d, + 0xaf82, 0x1f01, + 0xaf83, 0x2200, + 0xaf84, 0x3e8f, + 0xaf8e, 0x25b2, + 0xaf8f, 0x1e97, + 0xaf90, 0x3e99, + 0xaf91, 0x20ab, + 0xaf92, 0x3e9a, + 0xaf9c, 0x25b3, + 0xaf9d, 0x3ea4, + 0xaf9f, 0x2028, + 0xafa0, 0x3ea6, + 0xb040, 0x3ea7, + 0xb041, 0x25af, + 0xb043, 0x3ea8, + 0xb044, 0x25b1, + 0xb045, 0x3ea9, + 0xb04f, 0x25ac, + 0xb050, 0x3eb3, + 0xb054, 0x1e4e, + 0xb055, 0x3eb7, + 0xb057, 0x2202, + 0xb058, 0x25ab, + 0xb059, 0x2286, + 0xb05a, 0x3eb9, + 0xb05b, 0x25ad, + 0xb05c, 0x3eba, + 0xb05d, 0x25b6, + 0xb05e, 0x3ebb, + 0xb05f, 0x21e3, + 0xb060, 0x25b4, + 0xb062, 0x222f, + 0xb063, 0x2165, + 0xb064, 0x25b7, + 0xb065, 0x3ebc, + 0xb06c, 0x1ee9, + 0xb06d, 0x3ec3, + 0xb07d, 0x1e25, + 0xb07e, 0x3ed3, + 0xb080, 0x3ed4, + 0xb097, 0x25c0, + 0xb098, 0x3eeb, + 0xb099, 0x229a, + 0xb09a, 0x3eec, + 0xb0a1, 0x03ac, + 0xb140, 0x3ef3, + 0xb14b, 0x226e, + 0xb14c, 0x3efe, + 0xb14d, 0x1fbd, + 0xb14e, 0x3eff, + 0xb14f, 0x1f84, + 0xb150, 0x20b2, + 0xb151, 0x3f00, + 0xb152, 0x2043, + 0xb153, 0x3f01, + 0xb180, 0x3f2d, + 0xb197, 0x2684, + 0xb198, 0x3f44, + 0xb1a1, 0x040a, + 0xb240, 0x3f4d, + 0xb241, 0x24ef, + 0xb242, 0x3f4e, + 0xb267, 0x24ee, + 0xb268, 0x3f73, + 0xb26d, 0x2074, + 0xb26e, 0x3f78, + 0xb274, 0x2687, + 0xb275, 0x3f7e, + 0xb280, 0x24f0, + 0xb281, 0x3f88, + 0xb289, 0x268d, + 0xb28a, 0x3f90, + 0xb29a, 0x22a0, + 0xb29b, 0x3fa0, + 0xb2a1, 0x0468, + 0xb340, 0x3fa6, + 0xb343, 0x1fab, + 0xb344, 0x3fa9, + 0xb370, 0x26a8, + 0xb371, 0x3fd5, + 0xb380, 0x3fe3, + 0xb388, 0x24e9, + 0xb389, 0x3feb, + 0xb38c, 0x24e5, + 0xb38d, 0x3fee, + 0xb38e, 0x21fa, + 0xb38f, 0x3fef, + 0xb3a1, 0x04c6, + 0xb440, 0x4001, + 0xb454, 0x2148, + 0xb455, 0x4015, + 0xb458, 0x24e4, + 0xb459, 0x4018, + 0xb45e, 0x24e6, + 0xb45f, 0x20f7, + 0xb460, 0x401d, + 0xb461, 0x206b, + 0xb462, 0x401e, + 0xb475, 0x22a7, + 0xb476, 0x4031, + 0xb47e, 0x24ec, + 0xb480, 0x4039, + 0xb483, 0x24eb, + 0xb484, 0x403c, + 0xb489, 0x24e3, + 0xb48a, 0x4041, + 0xb493, 0x24ea, + 0xb494, 0x404a, + 0xb4a1, 0x0524, + 0xb540, 0x4057, + 0xb541, 0x1e92, + 0xb542, 0x4058, + 0xb54b, 0x1e27, + 0xb54c, 0x4061, + 0xb556, 0x1fe6, + 0xb557, 0x406b, + 0xb55a, 0x24e7, + 0xb55b, 0x2012, + 0xb55c, 0x1eec, + 0xb55d, 0x406e, + 0xb561, 0x24e8, + 0xb562, 0x4072, + 0xb580, 0x408f, + 0xb59c, 0x1f66, + 0xb59d, 0x24dc, + 0xb59e, 0x40ab, + 0xb5a1, 0x0582, + 0xb640, 0x40ae, + 0xb652, 0x26a2, + 0xb653, 0x40c0, + 0xb655, 0x24dd, + 0xb656, 0x40c2, + 0xb659, 0x200e, + 0xb65a, 0x40c5, + 0xb65b, 0x24db, + 0xb65c, 0x1eb8, + 0xb65d, 0x40c6, + 0xb680, 0x40e8, + 0xb6a1, 0x05e0, + 0xb740, 0x4109, + 0xb74e, 0x2295, + 0xb74f, 0x4117, + 0xb751, 0x1e80, + 0xb752, 0x4119, + 0xb759, 0x2677, + 0xb75a, 0x4120, + 0xb764, 0x2624, + 0xb765, 0x1f69, + 0xb766, 0x222b, + 0xb767, 0x412a, + 0xb777, 0x257f, + 0xb778, 0x1f5b, + 0xb779, 0x413a, + 0xb780, 0x219b, + 0xb781, 0x4140, + 0xb782, 0x267d, + 0xb783, 0x4141, + 0xb7a1, 0x063e, + 0xb840, 0x415f, + 0xb843, 0x21a0, + 0xb844, 0x2186, + 0xb845, 0x4162, + 0xb846, 0x20ed, + 0xb847, 0x4163, + 0xb84d, 0x25b9, + 0xb84e, 0x4169, + 0xb851, 0x1fea, + 0xb852, 0x416c, + 0xb85a, 0x1ea4, + 0xb85b, 0x20e1, + 0xb85c, 0x4174, + 0xb85d, 0x25b8, + 0xb85e, 0x2260, + 0xb85f, 0x4175, + 0xb860, 0x20e2, + 0xb861, 0x4176, + 0xb877, 0x2141, + 0xb878, 0x418c, + 0xb880, 0x4193, + 0xb882, 0x1fc7, + 0xb883, 0x4195, + 0xb8a1, 0x069c, + 0xb940, 0x41b3, + 0xb950, 0x1e41, + 0xb951, 0x41c3, + 0xb961, 0x25e4, + 0xb962, 0x41d3, + 0xb97b, 0x1f86, + 0xb97c, 0x41ec, + 0xb980, 0x41ef, + 0xb99d, 0x1fb3, + 0xb99e, 0x420c, + 0xb9a0, 0x1eef, + 0xb9a1, 0x06fa, + 0xba40, 0x420e, + 0xba42, 0x22a4, + 0xba43, 0x4210, + 0xba44, 0x25e8, + 0xba45, 0x4211, + 0xba56, 0x25e3, + 0xba57, 0x4222, + 0xba59, 0x2111, + 0xba5a, 0x4224, + 0xba60, 0x25e6, + 0xba61, 0x422a, + 0xba6a, 0x25e7, + 0xba6b, 0x4233, + 0xba74, 0x2041, + 0xba75, 0x423c, + 0xba80, 0x4246, + 0xba84, 0x25ea, + 0xba85, 0x424a, + 0xba86, 0x1f8f, + 0xba87, 0x424b, + 0xba88, 0x25ec, + 0xba89, 0x424c, + 0xba8d, 0x25eb, + 0xba8e, 0x4250, + 0xba9e, 0x20d0, + 0xba9f, 0x201d, + 0xbaa0, 0x4260, + 0xbaa1, 0x0758, + 0xbb40, 0x1ff7, + 0xbb41, 0x4261, + 0xbb49, 0x1e8d, + 0xbb4a, 0x4269, + 0xbb58, 0x25e9, + 0xbb59, 0x4277, + 0xbb5b, 0x25ee, + 0xbb5c, 0x203a, + 0xbb5d, 0x4279, + 0xbb60, 0x2693, + 0xbb61, 0x427c, + 0xbb65, 0x25e5, + 0xbb66, 0x25ed, + 0xbb67, 0x4280, + 0xbb68, 0x2009, + 0xbb69, 0x4281, + 0xbb6a, 0x2065, + 0xbb6b, 0x4282, + 0xbb6e, 0x26a3, + 0xbb6f, 0x4285, + 0xbb80, 0x4295, + 0xbba1, 0x07b6, + 0xbc40, 0x42b6, + 0xbc52, 0x25f5, + 0xbc53, 0x1efc, + 0xbc54, 0x42c8, + 0xbc5a, 0x2024, + 0xbc5b, 0x42ce, + 0xbc61, 0x269b, + 0xbc62, 0x42d4, + 0xbc63, 0x25f3, + 0xbc64, 0x42d5, + 0xbc65, 0x22d9, + 0xbc66, 0x42d6, + 0xbc67, 0x25f4, + 0xbc68, 0x42d7, + 0xbc69, 0x241b, + 0xbc6a, 0x42d8, + 0xbc6d, 0x1fc8, + 0xbc6e, 0x42db, + 0xbc6f, 0x1f7b, + 0xbc70, 0x42dc, + 0xbc71, 0x241d, + 0xbc72, 0x42dd, + 0xbc73, 0x224c, + 0xbc74, 0x1f48, + 0xbc75, 0x241c, + 0xbc76, 0x241e, + 0xbc78, 0x20ff, + 0xbc79, 0x219a, + 0xbc7a, 0x42de, + 0xbc7b, 0x2091, + 0xbc7c, 0x42df, + 0xbc7e, 0x20a7, + 0xbc80, 0x42e1, + 0xbc82, 0x2423, + 0xbc83, 0x1e9b, + 0xbc84, 0x2422, + 0xbc85, 0x42e3, + 0xbc86, 0x2110, + 0xbc87, 0x42e4, + 0xbc88, 0x228d, + 0xbc89, 0x1f71, + 0xbc8a, 0x1ef8, + 0xbc8b, 0x2421, + 0xbc8c, 0x42e5, + 0xbc8f, 0x1ef3, + 0xbc90, 0x42e8, + 0xbc9a, 0x21b1, + 0xbc9b, 0x2426, + 0xbc9c, 0x2425, + 0xbc9d, 0x2120, + 0xbc9e, 0x42f2, + 0xbca1, 0x0814, + 0xbd40, 0x42f5, + 0xbd42, 0x211a, + 0xbd43, 0x2424, + 0xbd44, 0x42f7, + 0xbd45, 0x2428, + 0xbd46, 0x42f8, + 0xbd48, 0x242a, + 0xbd49, 0x2429, + 0xbd4a, 0x42fa, + 0xbd4b, 0x2294, + 0xbd4c, 0x42fb, + 0xbd4d, 0x22be, + 0xbd4e, 0x42fc, + 0xbd4f, 0x1e31, + 0xbd50, 0x42fd, + 0xbd57, 0x242c, + 0xbd58, 0x4304, + 0xbd59, 0x1fb5, + 0xbd5a, 0x4305, + 0xbd66, 0x242b, + 0xbd67, 0x1faf, + 0xbd68, 0x4311, + 0xbd6a, 0x2068, + 0xbd6b, 0x21e4, + 0xbd6c, 0x4313, + 0xbd6f, 0x1f21, + 0xbd70, 0x4316, + 0xbd71, 0x2101, + 0xbd72, 0x4317, + 0xbd79, 0x217c, + 0xbd7a, 0x214a, + 0xbd7b, 0x242d, + 0xbd7c, 0x431e, + 0xbd7e, 0x1fd4, + 0xbd80, 0x4320, + 0xbd81, 0x1fd1, + 0xbd82, 0x4321, + 0xbd89, 0x1e33, + 0xbd8a, 0x4328, + 0xbd8b, 0x242f, + 0xbd8c, 0x4329, + 0xbd8e, 0x242e, + 0xbd8f, 0x432b, + 0xbd90, 0x2430, + 0xbd91, 0x21db, + 0xbd92, 0x432c, + 0xbd97, 0x2158, + 0xbd98, 0x4331, + 0xbd9b, 0x1fc2, + 0xbd9c, 0x4334, + 0xbda1, 0x0872, + 0xbe40, 0x4339, + 0xbe43, 0x22b9, + 0xbe44, 0x433c, + 0xbe45, 0x2436, + 0xbe46, 0x433d, + 0xbe49, 0x1e8e, + 0xbe4a, 0x2439, + 0xbe4b, 0x4340, + 0xbe51, 0x21c5, + 0xbe52, 0x2437, + 0xbe53, 0x2192, + 0xbe54, 0x4346, + 0xbe55, 0x243a, + 0xbe56, 0x1f19, + 0xbe57, 0x218c, + 0xbe58, 0x1e40, + 0xbe59, 0x22b3, + 0xbe5a, 0x4347, + 0xbe5d, 0x205f, + 0xbe5e, 0x2438, + 0xbe5f, 0x2432, + 0xbe60, 0x2274, + 0xbe61, 0x434a, + 0xbe62, 0x1e9c, + 0xbe63, 0x2431, + 0xbe64, 0x2085, + 0xbe65, 0x434b, + 0xbe69, 0x2435, + 0xbe6a, 0x434f, + 0xbe6c, 0x243b, + 0xbe6d, 0x4351, + 0xbe6f, 0x1fb7, + 0xbe70, 0x2433, + 0xbe71, 0x4353, + 0xbe76, 0x2054, + 0xbe77, 0x21de, + 0xbe78, 0x4358, + 0xbe79, 0x2434, + 0xbe7a, 0x4359, + 0xbe7c, 0x243d, + 0xbe7d, 0x1f89, + 0xbe7e, 0x243c, + 0xbe80, 0x435b, + 0xbe83, 0x1f6e, + 0xbe84, 0x1ed8, + 0xbe85, 0x435e, + 0xbe86, 0x1ebf, + 0xbe87, 0x2445, + 0xbe88, 0x435f, + 0xbe89, 0x2249, + 0xbe8a, 0x4360, + 0xbe8c, 0x2441, + 0xbe8d, 0x4362, + 0xbe8e, 0x1e47, + 0xbe8f, 0x1f56, + 0xbe90, 0x4363, + 0xbe92, 0x2086, + 0xbe93, 0x4365, + 0xbe95, 0x2196, + 0xbe96, 0x4367, + 0xbe97, 0x2443, + 0xbe98, 0x243f, + 0xbe99, 0x4368, + 0xbe9a, 0x2023, + 0xbe9b, 0x4369, + 0xbe9c, 0x2442, + 0xbe9d, 0x436a, + 0xbe9f, 0x243e, + 0xbea0, 0x436c, + 0xbea1, 0x08d0, + 0xbf40, 0x26a6, + 0xbf41, 0x436d, + 0xbf4d, 0x234e, + 0xbf4e, 0x2446, + 0xbf4f, 0x244b, + 0xbf50, 0x2444, + 0xbf51, 0x4379, + 0xbf55, 0x2427, + 0xbf56, 0x244c, + 0xbf57, 0x437d, + 0xbf60, 0x1f0f, + 0xbf61, 0x4386, + 0xbf62, 0x2447, + 0xbf63, 0x2449, + 0xbf64, 0x2448, + 0xbf65, 0x4387, + 0xbf68, 0x21c2, + 0xbf69, 0x438a, + 0xbf6c, 0x216e, + 0xbf6d, 0x438d, + 0xbf70, 0x1f03, + 0xbf71, 0x4390, + 0xbf72, 0x244a, + 0xbf73, 0x215c, + 0xbf74, 0x4391, + 0xbf76, 0x22bb, + 0xbf77, 0x2450, + 0xbf78, 0x4393, + 0xbf79, 0x2694, + 0xbf7a, 0x244f, + 0xbf7b, 0x25f6, + 0xbf7c, 0x2051, + 0xbf7d, 0x4394, + 0xbf7e, 0x244e, + 0xbf80, 0x4395, + 0xbf82, 0x22ba, + 0xbf83, 0x1f6d, + 0xbf84, 0x4397, + 0xbf89, 0x2452, + 0xbf8a, 0x2451, + 0xbf8b, 0x439c, + 0xbf95, 0x2455, + 0xbf96, 0x43a6, + 0xbf97, 0x2289, + 0xbf98, 0x2116, + 0xbf99, 0x43a7, + 0xbf9d, 0x2454, + 0xbf9e, 0x43ab, + 0xbfa1, 0x092e, + 0xc040, 0x20fb, + 0xc041, 0x43ae, + 0xc044, 0x2440, + 0xc045, 0x43b1, + 0xc04b, 0x2126, + 0xc04c, 0x1f61, + 0xc04d, 0x269d, + 0xc04e, 0x43b7, + 0xc04f, 0x1f8a, + 0xc050, 0x2456, + 0xc051, 0x2459, + 0xc052, 0x2458, + 0xc053, 0x43b8, + 0xc055, 0x1fae, + 0xc056, 0x43ba, + 0xc05b, 0x221a, + 0xc05c, 0x43bf, + 0xc05e, 0x1f7a, + 0xc05f, 0x244d, + 0xc060, 0x2457, + 0xc061, 0x43c1, + 0xc069, 0x2453, + 0xc06a, 0x43c9, + 0xc06b, 0x2420, + 0xc06c, 0x43ca, + 0xc06d, 0x21df, + 0xc06e, 0x2685, + 0xc06f, 0x43cb, + 0xc070, 0x1e6e, + 0xc071, 0x43cc, + 0xc074, 0x2224, + 0xc075, 0x2670, + 0xc076, 0x43cf, + 0xc077, 0x21ba, + 0xc078, 0x43d0, + 0xc079, 0x245a, + 0xc07a, 0x43d1, + 0xc07c, 0x1fff, + 0xc07d, 0x43d3, + 0xc080, 0x43d5, + 0xc09b, 0x25e2, + 0xc09c, 0x43f0, + 0xc09d, 0x269a, + 0xc09e, 0x43f1, + 0xc0a1, 0x098c, + 0xc140, 0x43f4, + 0xc150, 0x1eea, + 0xc151, 0x4404, + 0xc154, 0x1e2c, + 0xc155, 0x4407, + 0xc15f, 0x2062, + 0xc160, 0x24f1, + 0xc161, 0x4411, + 0xc162, 0x24f2, + 0xc163, 0x4412, + 0xc175, 0x25f2, + 0xc176, 0x4424, + 0xc178, 0x2215, + 0xc179, 0x4426, + 0xc180, 0x442c, + 0xc195, 0x21ae, + 0xc196, 0x4441, + 0xc1a1, 0x09ea, + 0xc240, 0x444c, + 0xc24e, 0x20e0, + 0xc24f, 0x445a, + 0xc265, 0x25c2, + 0xc266, 0x4470, + 0xc267, 0x25c1, + 0xc268, 0x4471, + 0xc27d, 0x2128, + 0xc27e, 0x4486, + 0xc280, 0x4487, + 0xc284, 0x2199, + 0xc285, 0x448b, + 0xc293, 0x2017, + 0xc294, 0x1ea0, + 0xc295, 0x2125, + 0xc296, 0x214d, + 0xc297, 0x4499, + 0xc298, 0x25c4, + 0xc299, 0x209d, + 0xc29a, 0x228a, + 0xc29b, 0x449a, + 0xc29c, 0x25c3, + 0xc29d, 0x449b, + 0xc2a0, 0x2179, + 0xc2a1, 0x0a48, + 0xc340, 0x2038, + 0xc341, 0x449e, + 0xc343, 0x2155, + 0xc344, 0x44a0, + 0xc37b, 0x21d2, + 0xc37c, 0x44d7, + 0xc380, 0x44da, + 0xc384, 0x24c7, + 0xc385, 0x44de, + 0xc39b, 0x2279, + 0xc39c, 0x44f4, + 0xc3a1, 0x0aa6, + 0xc440, 0x44f9, + 0xc449, 0x2123, + 0xc44a, 0x4502, + 0xc44c, 0x24c5, + 0xc44d, 0x4504, + 0xc454, 0x24c9, + 0xc455, 0x450b, + 0xc458, 0x2094, + 0xc459, 0x450e, + 0xc45b, 0x2296, + 0xc45c, 0x4510, + 0xc463, 0x1e77, + 0xc464, 0x4517, + 0xc477, 0x1f06, + 0xc478, 0x452a, + 0xc47a, 0x1fa5, + 0xc47b, 0x452c, + 0xc480, 0x4530, + 0xc481, 0x2099, + 0xc482, 0x4531, + 0xc491, 0x1ead, + 0xc492, 0x24c8, + 0xc493, 0x20a8, + 0xc494, 0x4540, + 0xc498, 0x201f, + 0xc499, 0x4544, + 0xc49a, 0x20c5, + 0xc49b, 0x4545, + 0xc49c, 0x24ca, + 0xc49d, 0x4546, + 0xc4a1, 0x0b04, + 0xc540, 0x454a, + 0xc544, 0x1ff0, + 0xc545, 0x454e, + 0xc546, 0x24c6, + 0xc547, 0x454f, + 0xc54b, 0x225d, + 0xc54c, 0x22de, + 0xc54d, 0x4553, + 0xc552, 0x202c, + 0xc553, 0x4558, + 0xc55f, 0x2161, + 0xc560, 0x4564, + 0xc563, 0x223b, + 0xc564, 0x21d9, + 0xc565, 0x1fcb, + 0xc566, 0x1fc9, + 0xc567, 0x4567, + 0xc580, 0x457f, + 0xc593, 0x1e61, + 0xc594, 0x4592, + 0xc59c, 0x25ef, + 0xc59d, 0x459a, + 0xc59e, 0x1f98, + 0xc59f, 0x459b, + 0xc5a1, 0x0b62, + 0xc640, 0x459d, + 0xc641, 0x25f0, + 0xc642, 0x459e, + 0xc644, 0x1f88, + 0xc645, 0x45a0, + 0xc647, 0x21f8, + 0xc648, 0x45a2, + 0xc663, 0x2322, + 0xc664, 0x45bd, + 0xc672, 0x2336, + 0xc673, 0x45cb, + 0xc680, 0x45d7, + 0xc6a1, 0x0bc0, + 0xc740, 0x45f8, + 0xc766, 0x22ab, + 0xc767, 0x461e, + 0xc76f, 0x1fbf, + 0xc770, 0x4626, + 0xc776, 0x1f7d, + 0xc777, 0x462c, + 0xc77b, 0x2333, + 0xc77c, 0x4630, + 0xc780, 0x4633, + 0xc7a1, 0x0c1e, + 0xc840, 0x4654, + 0xc841, 0x1f4d, + 0xc842, 0x4655, + 0xc84f, 0x2334, + 0xc850, 0x4662, + 0xc852, 0x1ff1, + 0xc853, 0x4664, + 0xc866, 0x218b, + 0xc867, 0x4677, + 0xc86e, 0x2349, + 0xc86f, 0x467e, + 0xc87e, 0x220b, + 0xc880, 0x468d, + 0xc887, 0x2346, + 0xc888, 0x4694, + 0xc892, 0x2347, + 0xc893, 0x469e, + 0xc894, 0x2193, + 0xc895, 0x469f, + 0xc899, 0x26a1, + 0xc89a, 0x46a3, + 0xc89d, 0x1f62, + 0xc89e, 0x46a6, + 0xc8a1, 0x0c7c, + 0xc940, 0x46a9, + 0xc94f, 0x234d, + 0xc950, 0x2348, + 0xc951, 0x46b8, + 0xc96e, 0x1e60, + 0xc96f, 0x46d5, + 0xc970, 0x2345, + 0xc971, 0x46d6, + 0xc977, 0x1f12, + 0xc978, 0x46dc, + 0xc980, 0x46e3, + 0xc98f, 0x2018, + 0xc990, 0x2335, + 0xc991, 0x46f2, + 0xc99c, 0x233c, + 0xc99d, 0x46fd, + 0xc9a1, 0x0cda, + 0xca40, 0x4701, + 0xca4e, 0x266f, + 0xca4f, 0x470f, + 0xca56, 0x2351, + 0xca57, 0x4716, + 0xca59, 0x1fa0, + 0xca5a, 0x4718, + 0xca5c, 0x2338, + 0xca5d, 0x471a, + 0xca61, 0x221b, + 0xca62, 0x471e, + 0xca6e, 0x2342, + 0xca6f, 0x472a, + 0xca72, 0x234f, + 0xca73, 0x472d, + 0xca77, 0x233d, + 0xca78, 0x4731, + 0xca7b, 0x2344, + 0xca7c, 0x2331, + 0xca7d, 0x4734, + 0xca7e, 0x234b, + 0xca80, 0x4735, + 0xca81, 0x233b, + 0xca82, 0x4736, + 0xca89, 0x2350, + 0xca8a, 0x473d, + 0xca8e, 0x1eb4, + 0xca8f, 0x21a6, + 0xca90, 0x4741, + 0xca92, 0x21cb, + 0xca93, 0x4743, + 0xca9a, 0x2355, + 0xca9b, 0x474a, + 0xcaa1, 0x0d38, + 0xcb40, 0x4750, + 0xcb43, 0x233e, + 0xcb44, 0x4753, + 0xcb45, 0x1f74, + 0xcb46, 0x4754, + 0xcb47, 0x2330, + 0xcb48, 0x4755, + 0xcb4b, 0x2680, + 0xcb4c, 0x4758, + 0xcb4e, 0x20da, + 0xcb4f, 0x475a, + 0xcb57, 0x234a, + 0xcb58, 0x4762, + 0xcb5d, 0x1f91, + 0xcb5e, 0x4767, + 0xcb5f, 0x2107, + 0xcb60, 0x4768, + 0xcb6a, 0x233f, + 0xcb6b, 0x4772, + 0xcb7b, 0x1ff4, + 0xcb7c, 0x2343, + 0xcb7d, 0x4782, + 0xcb80, 0x4784, + 0xcb87, 0x2212, + 0xcb88, 0x478b, + 0xcb8e, 0x2207, + 0xcb8f, 0x4791, + 0xcb92, 0x2359, + 0xcb93, 0x4794, + 0xcb9c, 0x2254, + 0xcb9d, 0x479d, + 0xcb9e, 0x2332, + 0xcb9f, 0x479e, + 0xcba1, 0x0d96, + 0xcc40, 0x1e26, + 0xcc41, 0x2357, + 0xcc42, 0x47a0, + 0xcc49, 0x2358, + 0xcc4a, 0x2042, + 0xcc4b, 0x2153, + 0xcc4c, 0x47a7, + 0xcc4f, 0x20bb, + 0xcc50, 0x47aa, + 0xcc5c, 0x235a, + 0xcc5d, 0x47b6, + 0xcc60, 0x2356, + 0xcc61, 0x47b9, + 0xcc64, 0x2337, + 0xcc65, 0x47bc, + 0xcc6d, 0x1ff9, + 0xcc6e, 0x47c4, + 0xcc79, 0x2353, + 0xcc7a, 0x47cf, + 0xcc7d, 0x2061, + 0xcc7e, 0x47d2, + 0xcc80, 0x47d3, + 0xcc8e, 0x1e95, + 0xcc8f, 0x47e1, + 0xcc94, 0x2049, + 0xcc95, 0x47e6, + 0xcc96, 0x1f42, + 0xcc97, 0x47e7, + 0xcc9d, 0x1fe8, + 0xcc9e, 0x47ed, + 0xcca1, 0x0df4, + 0xcd40, 0x47f0, + 0xcd80, 0x482f, + 0xcd90, 0x25da, + 0xcd91, 0x483f, + 0xcd98, 0x25d7, + 0xcd99, 0x4846, + 0xcda1, 0x0e52, + 0xce40, 0x484e, + 0xce67, 0x212e, + 0xce68, 0x4875, + 0xce72, 0x21b2, + 0xce73, 0x487f, + 0xce80, 0x488b, + 0xce81, 0x219e, + 0xce82, 0x488c, + 0xce87, 0x25dc, + 0xce88, 0x4891, + 0xce9b, 0x206c, + 0xce9c, 0x48a4, + 0xce9e, 0x2226, + 0xce9f, 0x48a6, + 0xcea1, 0x0eb0, + 0xcf40, 0x48a8, + 0xcf4e, 0x25e0, + 0xcf4f, 0x48b6, + 0xcf55, 0x227b, + 0xcf56, 0x48bc, + 0xcf58, 0x25de, + 0xcf59, 0x48be, + 0xcf5c, 0x25e1, + 0xcf5d, 0x48c1, + 0xcf6c, 0x25d5, + 0xcf6d, 0x48d0, + 0xcf73, 0x1e6b, + 0xcf74, 0x48d6, + 0xcf75, 0x25db, + 0xcf76, 0x48d7, + 0xcf78, 0x1e89, + 0xcf79, 0x48d9, + 0xcf7c, 0x25d9, + 0xcf7d, 0x48dc, + 0xcf80, 0x48de, + 0xcf81, 0x2211, + 0xcf82, 0x48df, + 0xcf89, 0x2229, + 0xcf8a, 0x25d6, + 0xcf8b, 0x48e6, + 0xcf93, 0x25dd, + 0xcf94, 0x25df, + 0xcf95, 0x48ee, + 0xcf9e, 0x1fef, + 0xcf9f, 0x48f7, + 0xcfa0, 0x25d8, + 0xcfa1, 0x0f0e, + 0xd040, 0x48f8, + 0xd04d, 0x1f29, + 0xd04e, 0x4905, + 0xd051, 0x1e5b, + 0xd052, 0x4908, + 0xd055, 0x2076, + 0xd056, 0x490b, + 0xd05c, 0x2297, + 0xd05d, 0x4911, + 0xd060, 0x2690, + 0xd061, 0x4914, + 0xd067, 0x213f, + 0xd068, 0x491a, + 0xd06c, 0x2198, + 0xd06d, 0x491e, + 0xd06e, 0x1e88, + 0xd06f, 0x491f, + 0xd07d, 0x228c, + 0xd07e, 0x492d, + 0xd080, 0x492e, + 0xd0a1, 0x0f6c, + 0xd140, 0x494f, + 0xd155, 0x25f1, + 0xd156, 0x4964, + 0xd159, 0x200c, + 0xd15a, 0x4967, + 0xd161, 0x1e58, + 0xd162, 0x22ac, + 0xd163, 0x496e, + 0xd175, 0x26a7, + 0xd176, 0x4980, + 0xd17d, 0x2676, + 0xd17e, 0x4987, + 0xd180, 0x4988, + 0xd19d, 0x1fe1, + 0xd19e, 0x25bb, + 0xd19f, 0x49a5, + 0xd1a1, 0x0fca, + 0xd240, 0x25be, + 0xd241, 0x49a7, + 0xd243, 0x22dd, + 0xd244, 0x49a9, + 0xd24d, 0x25bd, + 0xd24e, 0x49b2, + 0xd25c, 0x1e2a, + 0xd25d, 0x49c0, + 0xd263, 0x25bc, + 0xd264, 0x25ba, + 0xd265, 0x49c6, + 0xd268, 0x25bf, + 0xd269, 0x49c9, + 0xd26d, 0x2187, + 0xd26e, 0x49cd, + 0xd26f, 0x266b, + 0xd270, 0x49ce, + 0xd272, 0x1e7f, + 0xd273, 0x49d0, + 0xd275, 0x21ad, + 0xd276, 0x49d2, + 0xd280, 0x49db, + 0xd28a, 0x1f96, + 0xd28b, 0x49e5, + 0xd28e, 0x1f32, + 0xd28f, 0x49e8, + 0xd292, 0x2084, + 0xd293, 0x49eb, + 0xd295, 0x2136, + 0xd296, 0x49ed, + 0xd297, 0x24b8, + 0xd298, 0x49ee, + 0xd2a0, 0x24ba, + 0xd2a1, 0x1028, + 0xd340, 0x49f6, + 0xd344, 0x24bc, + 0xd345, 0x49fa, + 0xd348, 0x20e4, + 0xd349, 0x49fd, + 0xd34a, 0x24b9, + 0xd34b, 0x49fe, + 0xd34d, 0x24bd, + 0xd34e, 0x4a00, + 0xd350, 0x24be, + 0xd351, 0x4a02, + 0xd355, 0x24bf, + 0xd356, 0x4a06, + 0xd358, 0x1fd2, + 0xd359, 0x4a08, + 0xd35b, 0x1ffd, + 0xd35c, 0x4a0a, + 0xd35d, 0x24bb, + 0xd35e, 0x1f2d, + 0xd35f, 0x4a0b, + 0xd378, 0x2609, + 0xd379, 0x4a24, + 0xd37a, 0x260a, + 0xd37b, 0x4a25, + 0xd37c, 0x1e94, + 0xd37d, 0x4a26, + 0xd380, 0x4a28, + 0xd385, 0x22df, + 0xd386, 0x1ecb, + 0xd387, 0x1f0d, + 0xd388, 0x4a2d, + 0xd38b, 0x1f77, + 0xd38c, 0x4a30, + 0xd38d, 0x21eb, + 0xd38e, 0x4a31, + 0xd38f, 0x22e1, + 0xd390, 0x4a32, + 0xd391, 0x216f, + 0xd392, 0x4a33, + 0xd393, 0x22e0, + 0xd394, 0x4a34, + 0xd396, 0x21ea, + 0xd397, 0x4a36, + 0xd398, 0x22e2, + 0xd399, 0x20cb, + 0xd39a, 0x4a37, + 0xd39b, 0x1f78, + 0xd39c, 0x4a38, + 0xd39e, 0x1ee2, + 0xd39f, 0x4a3a, + 0xd3a0, 0x21f2, + 0xd3a1, 0x1086, + 0xd440, 0x4a3b, + 0xd441, 0x2150, + 0xd442, 0x4a3c, + 0xd445, 0x1fd3, + 0xd446, 0x4a3f, + 0xd447, 0x22e5, + 0xd448, 0x4a40, + 0xd44c, 0x1ef2, + 0xd44d, 0x4a44, + 0xd44f, 0x211f, + 0xd450, 0x4a46, + 0xd453, 0x21dd, + 0xd454, 0x4a49, + 0xd456, 0x2154, + 0xd457, 0x4a4b, + 0xd458, 0x22e7, + 0xd459, 0x4a4c, + 0xd45c, 0x2282, + 0xd45d, 0x4a4f, + 0xd462, 0x22e6, + 0xd463, 0x4a54, + 0xd467, 0x22e8, + 0xd468, 0x4a58, + 0xd46e, 0x22e4, + 0xd46f, 0x4a5e, + 0xd470, 0x226a, + 0xd471, 0x4a5f, + 0xd472, 0x22eb, + 0xd473, 0x4a60, + 0xd474, 0x22e9, + 0xd475, 0x20bd, + 0xd476, 0x4a61, + 0xd478, 0x22ea, + 0xd479, 0x4a63, + 0xd47b, 0x22bd, + 0xd47c, 0x4a65, + 0xd47e, 0x1e9e, + 0xd480, 0x4a67, + 0xd482, 0x22f6, + 0xd483, 0x21e7, + 0xd484, 0x2216, + 0xd485, 0x4a69, + 0xd487, 0x2137, + 0xd488, 0x4a6b, + 0xd48a, 0x212c, + 0xd48b, 0x4a6d, + 0xd48c, 0x1e68, + 0xd48d, 0x22f2, + 0xd48e, 0x1f37, + 0xd48f, 0x22f3, + 0xd490, 0x4a6e, + 0xd491, 0x22ef, + 0xd492, 0x1f50, + 0xd493, 0x1f10, + 0xd494, 0x21c8, + 0xd495, 0x4a6f, + 0xd496, 0x22f1, + 0xd497, 0x4a70, + 0xd49c, 0x22f0, + 0xd49d, 0x4a75, + 0xd49f, 0x22ee, + 0xd4a0, 0x4a77, + 0xd4a1, 0x10e4, + 0xd540, 0x4a78, + 0xd543, 0x22ed, + 0xd544, 0x229e, + 0xd545, 0x22ec, + 0xd546, 0x1fe2, + 0xd547, 0x4a7b, + 0xd54a, 0x20fe, + 0xd54b, 0x4a7e, + 0xd54e, 0x22f9, + 0xd550, 0x4a81, + 0xd551, 0x1eaf, + 0xd552, 0x4a82, + 0xd554, 0x2236, + 0xd555, 0x4a84, + 0xd556, 0x22f7, + 0xd557, 0x4a85, + 0xd55a, 0x223d, + 0xd55b, 0x4a88, + 0xd55c, 0x1e82, + 0xd55d, 0x1fb6, + 0xd55e, 0x4a89, + 0xd55f, 0x21a4, + 0xd560, 0x21aa, + 0xd561, 0x22f8, + 0xd562, 0x2151, + 0xd563, 0x4a8a, + 0xd564, 0x1f60, + 0xd565, 0x4a8b, + 0xd568, 0x2147, + 0xd569, 0x4a8e, + 0xd56c, 0x2145, + 0xd56d, 0x4a91, + 0xd56e, 0x1fdc, + 0xd56f, 0x4a92, + 0xd572, 0x2301, + 0xd573, 0x4a95, + 0xd575, 0x1ef5, + 0xd576, 0x4a97, + 0xd578, 0x2218, + 0xd579, 0x4a99, + 0xd57b, 0x1ec6, + 0xd57c, 0x4a9b, + 0xd57e, 0x2300, + 0xd580, 0x4a9d, + 0xd581, 0x22b4, + 0xd582, 0x4a9e, + 0xd584, 0x2169, + 0xd585, 0x4aa0, + 0xd586, 0x22fd, + 0xd587, 0x4aa1, + 0xd588, 0x20ea, + 0xd589, 0x4aa2, + 0xd58a, 0x22f4, + 0xd58b, 0x4aa3, + 0xd58c, 0x22fb, + 0xd58d, 0x4aa4, + 0xd58e, 0x22fc, + 0xd58f, 0x2027, + 0xd590, 0x4aa5, + 0xd593, 0x2060, + 0xd594, 0x22ff, + 0xd595, 0x4aa8, + 0xd598, 0x22fe, + 0xd599, 0x1ec7, + 0xd59a, 0x4aab, + 0xd59b, 0x230c, + 0xd59c, 0x4aac, + 0xd59f, 0x22f5, + 0xd5a0, 0x4aaf, + 0xd5a1, 0x1142, + 0xd640, 0x2306, + 0xd641, 0x4ab0, + 0xd642, 0x230a, + 0xd643, 0x21d3, + 0xd644, 0x4ab1, + 0xd647, 0x2303, + 0xd648, 0x4ab4, + 0xd649, 0x2307, + 0xd64a, 0x230b, + 0xd64b, 0x4ab5, + 0xd64d, 0x1f5f, + 0xd64e, 0x4ab7, + 0xd64f, 0x2309, + 0xd650, 0x4ab8, + 0xd652, 0x2302, + 0xd653, 0x1f04, + 0xd654, 0x229d, + 0xd655, 0x4aba, + 0xd656, 0x21fb, + 0xd657, 0x4abb, + 0xd658, 0x2308, + 0xd659, 0x4abc, + 0xd65a, 0x20ac, + 0xd65b, 0x4abd, + 0xd65c, 0x208e, + 0xd65d, 0x2305, + 0xd65e, 0x2197, + 0xd65f, 0x4abe, + 0xd660, 0x2171, + 0xd661, 0x2298, + 0xd662, 0x4abf, + 0xd665, 0x1f57, + 0xd666, 0x4ac2, + 0xd669, 0x2082, + 0xd66a, 0x4ac5, + 0xd66b, 0x2311, + 0xd66c, 0x4ac6, + 0xd66f, 0x2304, + 0xd670, 0x4ac9, + 0xd671, 0x230f, + 0xd672, 0x1e35, + 0xd673, 0x4aca, + 0xd674, 0x20d1, + 0xd675, 0x2310, + 0xd676, 0x1fa3, + 0xd677, 0x4acb, + 0xd678, 0x21d6, + 0xd679, 0x4acc, + 0xd67c, 0x2206, + 0xd67d, 0x4acf, + 0xd680, 0x4ad1, + 0xd683, 0x230d, + 0xd684, 0x4ad4, + 0xd686, 0x2312, + 0xd687, 0x208d, + 0xd688, 0x2313, + 0xd689, 0x4ad6, + 0xd68e, 0x22e3, + 0xd68f, 0x4adb, + 0xd694, 0x1fba, + 0xd695, 0x4ae0, + 0xd699, 0x2078, + 0xd69a, 0x4ae4, + 0xd6a1, 0x11a0, + 0xd740, 0x4aeb, + 0xd743, 0x2288, + 0xd744, 0x4aee, + 0xd748, 0x2316, + 0xd749, 0x1f6b, + 0xd74a, 0x4af2, + 0xd750, 0x2314, + 0xd751, 0x4af8, + 0xd752, 0x2130, + 0xd753, 0x2315, + 0xd754, 0x2168, + 0xd755, 0x4af9, + 0xd756, 0x20c4, + 0xd757, 0x4afa, + 0xd764, 0x2318, + 0xd765, 0x4b07, + 0xd767, 0x2219, + 0xd768, 0x2217, + 0xd769, 0x4b09, + 0xd76c, 0x20d5, + 0xd76d, 0x4b0c, + 0xd76f, 0x1f4a, + 0xd770, 0x4b0e, + 0xd775, 0x2240, + 0xd776, 0x4b13, + 0xd778, 0x1ed3, + 0xd779, 0x4b15, + 0xd780, 0x4b1b, + 0xd783, 0x1e49, + 0xd784, 0x4b1e, + 0xd787, 0x261b, + 0xd788, 0x4b21, + 0xd78b, 0x1e6d, + 0xd78c, 0x20f8, + 0xd78d, 0x4b24, + 0xd78e, 0x1ffb, + 0xd78f, 0x2319, + 0xd790, 0x4b25, + 0xd795, 0x230e, + 0xd796, 0x4b2a, + 0xd797, 0x2317, + 0xd798, 0x4b2b, + 0xd7a1, 0x11fe, + 0xd840, 0x4b34, + 0xd84d, 0x20c8, + 0xd84e, 0x4b41, + 0xd853, 0x1efd, + 0xd854, 0x4b46, + 0xd880, 0x4b71, + 0xd890, 0x1e3b, + 0xd891, 0x227f, + 0xd892, 0x4b81, + 0xd893, 0x1f0c, + 0xd894, 0x1e59, + 0xd895, 0x1f24, + 0xd896, 0x4b82, + 0xd89a, 0x20ba, + 0xd89b, 0x1f65, + 0xd89c, 0x1ef0, + 0xd89d, 0x2164, + 0xd89e, 0x1f30, + 0xd89f, 0x2261, + 0xd8a0, 0x4b86, + 0xd8a1, 0x1257, + 0xd940, 0x4b87, + 0xd941, 0x22a2, + 0xd942, 0x24ab, + 0xd943, 0x4b88, + 0xd944, 0x24af, + 0xd945, 0x1ee8, + 0xd946, 0x1f39, + 0xd947, 0x4b89, + 0xd948, 0x1e48, + 0xd949, 0x2070, + 0xd94a, 0x1ea8, + 0xd94b, 0x4b8a, + 0xd94c, 0x24ac, + 0xd94d, 0x1ef7, + 0xd94e, 0x2176, + 0xd94f, 0x24ad, + 0xd950, 0x4b8b, + 0xd951, 0x207b, + 0xd952, 0x1f45, + 0xd953, 0x24aa, + 0xd954, 0x204b, + 0xd955, 0x202f, + 0xd956, 0x1f5a, + 0xd957, 0x24b0, + 0xd958, 0x4b8c, + 0xd959, 0x22b7, + 0xd95a, 0x1f7f, + 0xd95b, 0x4b8d, + 0xd95c, 0x2265, + 0xd95d, 0x4b8e, + 0xd963, 0x24b2, + 0xd964, 0x211b, + 0xd965, 0x1e51, + 0xd966, 0x4b94, + 0xd967, 0x24b4, + 0xd968, 0x4b95, + 0xd96c, 0x24b3, + 0xd96d, 0x4b99, + 0xd96e, 0x1e9f, + 0xd96f, 0x4b9a, + 0xd970, 0x2118, + 0xd971, 0x4b9b, + 0xd972, 0x20b4, + 0xd973, 0x23af, + 0xd974, 0x21bb, + 0xd975, 0x2072, + 0xd976, 0x1f95, + 0xd977, 0x4b9c, + 0xd978, 0x1f0a, + 0xd979, 0x24b6, + 0xd97a, 0x4b9d, + 0xd97c, 0x2291, + 0xd97d, 0x24b5, + 0xd97e, 0x2278, + 0xd980, 0x1ed4, + 0xd981, 0x4b9f, + 0xd987, 0x1ff3, + 0xd988, 0x4ba5, + 0xd98d, 0x22a9, + 0xd98e, 0x24b7, + 0xd98f, 0x1f28, + 0xd990, 0x2109, + 0xd991, 0x22c7, + 0xd992, 0x4baa, + 0xd997, 0x24ae, + 0xd998, 0x22b1, + 0xd999, 0x4baf, + 0xd99b, 0x2266, + 0xd99c, 0x4bb1, + 0xd99d, 0x225b, + 0xd99e, 0x22c4, + 0xd99f, 0x4bb2, + 0xd9a0, 0x2115, + 0xd9a1, 0x12b5, + 0xda40, 0x4bb3, + 0xda41, 0x222a, + 0xda42, 0x24b1, + 0xda43, 0x4bb4, + 0xda48, 0x213d, + 0xda49, 0x4bb9, + 0xda4d, 0x1f15, + 0xda4e, 0x225c, + 0xda4f, 0x4bbd, + 0xda73, 0x1f14, + 0xda74, 0x4be1, + 0xda77, 0x227a, + 0xda78, 0x4be4, + 0xda80, 0x4beb, + 0xda85, 0x20ee, + 0xda86, 0x4bf0, + 0xda8e, 0x25f8, + 0xda8f, 0x4bf8, + 0xdaa1, 0x1313, + 0xdb40, 0x4c0a, + 0xdb60, 0x1f94, + 0xdb61, 0x4c2a, + 0xdb78, 0x2230, + 0xdb79, 0x4c41, + 0xdb80, 0x4c47, + 0xdb84, 0x25fd, + 0xdb85, 0x4c4b, + 0xdb8b, 0x2600, + 0xdb8c, 0x4c51, + 0xdb98, 0x2606, + 0xdb99, 0x4c5d, + 0xdba1, 0x1371, + 0xdc40, 0x4c65, + 0xdc45, 0x25ff, + 0xdc46, 0x4c6a, + 0xdc4f, 0x25fc, + 0xdc50, 0x1e8c, + 0xdc51, 0x2602, + 0xdc52, 0x4c73, + 0xdc53, 0x224d, + 0xdc54, 0x4c74, + 0xdc55, 0x2604, + 0xdc56, 0x25fe, + 0xdc57, 0x2603, + 0xdc58, 0x4c75, + 0xdc5d, 0x2601, + 0xdc5e, 0x4c7a, + 0xdc62, 0x2605, + 0xdc63, 0x4c7e, + 0xdc66, 0x1ea3, + 0xdc67, 0x2608, + 0xdc68, 0x4c81, + 0xdc6b, 0x2607, + 0xdc6c, 0x4c84, + 0xdc7c, 0x20f0, + 0xdc7d, 0x4c94, + 0xdc80, 0x4c96, + 0xdc87, 0x1e7b, + 0xdc88, 0x2267, + 0xdc89, 0x1f36, + 0xdc8a, 0x1fd6, + 0xdc8b, 0x4c9d, + 0xdc8e, 0x21e0, + 0xdc8f, 0x4ca0, + 0xdc90, 0x248c, + 0xdc91, 0x4ca1, + 0xdc97, 0x248d, + 0xdc98, 0x4ca7, + 0xdc9b, 0x2102, + 0xdc9c, 0x4caa, + 0xdca0, 0x2494, + 0xdca1, 0x13cf, + 0xdd40, 0x4cae, + 0xdd46, 0x2493, + 0xdd47, 0x4cb4, + 0xdd4d, 0x248e, + 0xdd4e, 0x4cba, + 0xdd53, 0x2299, + 0xdd54, 0x2491, + 0xdd55, 0x2496, + 0xdd56, 0x248f, + 0xdd57, 0x2492, + 0xdd58, 0x4cbf, + 0xdd59, 0x2497, + 0xdd5a, 0x4cc0, + 0xdd5e, 0x1fb1, + 0xdd5f, 0x4cc4, + 0xdd60, 0x249a, + 0xdd61, 0x4cc5, + 0xdd62, 0x2499, + 0xdd63, 0x4cc6, + 0xdd64, 0x2258, + 0xdd65, 0x2498, + 0xdd66, 0x4cc7, + 0xdd6d, 0x249b, + 0xdd6e, 0x4cce, + 0xdd6f, 0x1f09, + 0xdd70, 0x20e6, + 0xdd71, 0x4ccf, + 0xdd76, 0x2026, + 0xdd77, 0x249f, + 0xdd78, 0x1f59, + 0xdd79, 0x249d, + 0xdd7b, 0x4cd4, + 0xdd80, 0x4cd8, + 0xdd81, 0x1f3b, + 0xdd82, 0x249c, + 0xdd83, 0x4cd9, + 0xdd85, 0x1e3a, + 0xdd86, 0x205b, + 0xdd87, 0x4cdb, + 0xdd8b, 0x1f70, + 0xdd8c, 0x4cdf, + 0xdd8f, 0x24a0, + 0xdd90, 0x4ce2, + 0xdd94, 0x213b, + 0xdd95, 0x4ce6, + 0xdd97, 0x1f07, + 0xdd98, 0x4ce8, + 0xdd9a, 0x2270, + 0xdd9b, 0x2237, + 0xdd9c, 0x4cea, + 0xdd9e, 0x24d2, + 0xdd9f, 0x4cec, + 0xdda0, 0x21b3, + 0xdda1, 0x142d, + 0xde40, 0x2245, + 0xde41, 0x24a1, + 0xde42, 0x4ced, + 0xde44, 0x22a8, + 0xde45, 0x4cef, + 0xde48, 0x227c, + 0xde49, 0x1fb0, + 0xde4a, 0x4cf2, + 0xde4f, 0x24a2, + 0xde50, 0x4cf7, + 0xde5a, 0x1f46, + 0xde5b, 0x4d01, + 0xde5c, 0x2380, + 0xde5d, 0x2495, + 0xde5e, 0x4d02, + 0xde5f, 0x2490, + 0xde60, 0x4d03, + 0xde6b, 0x1e30, + 0xde6c, 0x4d0e, + 0xde6f, 0x1e9d, + 0xde70, 0x1e4b, + 0xde71, 0x1e4a, + 0xde72, 0x20aa, + 0xde73, 0x4d11, + 0xde80, 0x4d1d, + 0xde92, 0x267b, + 0xde93, 0x4d2f, + 0xde9f, 0x23f2, + 0xdea0, 0x4d3b, + 0xdea1, 0x148b, + 0xdf40, 0x227e, + 0xdf41, 0x4d3c, + 0xdf42, 0x2019, + 0xdf43, 0x4d3d, + 0xdf4d, 0x1fbb, + 0xdf4e, 0x4d47, + 0xdf5c, 0x2253, + 0xdf5d, 0x4d55, + 0xdf5e, 0x1f3e, + 0xdf5f, 0x1ea6, + 0xdf60, 0x218e, + 0xdf61, 0x4d56, + 0xdf64, 0x21ec, + 0xdf65, 0x4d59, + 0xdf66, 0x1ebe, + 0xdf67, 0x4d5a, + 0xdf68, 0x224a, + 0xdf69, 0x4d5b, + 0xdf6d, 0x2133, + 0xdf6e, 0x4d5f, + 0xdf74, 0x1e84, + 0xdf75, 0x4d65, + 0xdf77, 0x20cf, + 0xdf78, 0x21e2, + 0xdf79, 0x4d67, + 0xdf7a, 0x220f, + 0xdf7b, 0x4d68, + 0xdf7c, 0x2029, + 0xdf7d, 0x4d69, + 0xdf7e, 0x2073, + 0xdf80, 0x1f55, + 0xdf81, 0x4d6a, + 0xdf83, 0x23f1, + 0xdf84, 0x4d6c, + 0xdf85, 0x1e46, + 0xdf86, 0x4d6d, + 0xdf89, 0x2063, + 0xdf8a, 0x23f3, + 0xdf8b, 0x4d70, + 0xdfa1, 0x14e9, + 0xe040, 0x4d86, + 0xe050, 0x231e, + 0xe051, 0x4d96, + 0xe05d, 0x2233, + 0xe05e, 0x4da2, + 0xe069, 0x2320, + 0xe06a, 0x4dad, + 0xe06c, 0x21c7, + 0xe06d, 0x4daf, + 0xe075, 0x22bc, + 0xe076, 0x4db7, + 0xe077, 0x231c, + 0xe078, 0x4db8, + 0xe079, 0x2251, + 0xe07a, 0x4db9, + 0xe080, 0x4dbe, + 0xe087, 0x1ebb, + 0xe088, 0x4dc5, + 0xe08d, 0x2287, + 0xe08e, 0x4dca, + 0xe08f, 0x202d, + 0xe090, 0x1eab, + 0xe091, 0x4dcb, + 0xe092, 0x231d, + 0xe093, 0x4dcc, + 0xe094, 0x231f, + 0xe095, 0x4dcd, + 0xe097, 0x231b, + 0xe098, 0x4dcf, + 0xe0a1, 0x1547, + 0xe140, 0x4dd8, + 0xe142, 0x2321, + 0xe143, 0x4dda, + 0xe164, 0x2255, + 0xe165, 0x4dfb, + 0xe168, 0x1e8f, + 0xe169, 0x4dfe, + 0xe174, 0x220c, + 0xe175, 0x1fa4, + 0xe176, 0x4e09, + 0xe180, 0x4e12, + 0xe184, 0x209b, + 0xe185, 0x21d8, + 0xe186, 0x4e16, + 0xe187, 0x25fa, + 0xe188, 0x4e17, + 0xe189, 0x25f9, + 0xe18a, 0x4e18, + 0xe18c, 0x2134, + 0xe18d, 0x4e1a, + 0xe18e, 0x24f3, + 0xe191, 0x24f8, + 0xe192, 0x4e1b, + 0xe193, 0x24f7, + 0xe194, 0x1ec8, + 0xe195, 0x24f6, + 0xe196, 0x4e1c, + 0xe198, 0x2280, + 0xe199, 0x4e1e, + 0xe19e, 0x1ec5, + 0xe19f, 0x24fb, + 0xe1a0, 0x4e23, + 0xe1a1, 0x15a5, + 0xe240, 0x4e24, + 0xe241, 0x24fa, + 0xe242, 0x4e25, + 0xe243, 0x1eed, + 0xe244, 0x4e26, + 0xe24f, 0x24fd, + 0xe250, 0x4e31, + 0xe251, 0x24f9, + 0xe252, 0x4e32, + 0xe253, 0x24fe, + 0xe254, 0x20cd, + 0xe255, 0x4e33, + 0xe25a, 0x2508, + 0xe25b, 0x2504, + 0xe25c, 0x4e38, + 0xe25e, 0x2506, + 0xe25f, 0x4e3a, + 0xe262, 0x24ff, + 0xe263, 0x2090, + 0xe264, 0x4e3d, + 0xe267, 0x1edd, + 0xe268, 0x1f25, + 0xe269, 0x4e40, + 0xe26a, 0x2503, + 0xe26b, 0x2502, + 0xe26c, 0x4e41, + 0xe26e, 0x1e7a, + 0xe26f, 0x20a6, + 0xe270, 0x4e43, + 0xe278, 0x1fd5, + 0xe279, 0x4e4b, + 0xe27d, 0x1f11, + 0xe27e, 0x4e4f, + 0xe280, 0x2507, + 0xe281, 0x2500, + 0xe282, 0x2505, + 0xe283, 0x4e50, + 0xe289, 0x2519, + 0xe28a, 0x4e56, + 0xe28b, 0x2515, + 0xe28c, 0x4e57, + 0xe28e, 0x250c, + 0xe28f, 0x2031, + 0xe290, 0x4e59, + 0xe292, 0x250b, + 0xe293, 0x250f, + 0xe294, 0x251a, + 0xe295, 0x2509, + 0xe296, 0x4e5b, + 0xe298, 0x250e, + 0xe299, 0x2234, + 0xe29a, 0x2513, + 0xe29b, 0x1f80, + 0xe29c, 0x4e5d, + 0xe2a0, 0x2501, + 0xe2a1, 0x1603, + 0xe340, 0x4e61, + 0xe342, 0x2517, + 0xe343, 0x2516, + 0xe344, 0x4e63, + 0xe347, 0x2518, + 0xe348, 0x4e66, + 0xe34b, 0x1e56, + 0xe34c, 0x4e69, + 0xe34f, 0x250d, + 0xe350, 0x4e6c, + 0xe351, 0x20d3, + 0xe352, 0x4e6d, + 0xe354, 0x207a, + 0xe355, 0x20ce, + 0xe356, 0x4e6f, + 0xe358, 0x2510, + 0xe359, 0x4e71, + 0xe35c, 0x1e55, + 0xe35d, 0x4e74, + 0xe360, 0x250a, + 0xe361, 0x4e77, + 0xe366, 0x2511, + 0xe368, 0x4e7c, + 0xe371, 0x1faa, + 0xe372, 0x4e85, + 0xe373, 0x251e, + 0xe374, 0x1f1f, + 0xe375, 0x4e86, + 0xe378, 0x252d, + 0xe379, 0x221d, + 0xe37a, 0x4e89, + 0xe37c, 0x2532, + 0xe37d, 0x4e8b, + 0xe37e, 0x217b, + 0xe380, 0x4e8c, + 0xe38a, 0x21af, + 0xe38b, 0x4e96, + 0xe38c, 0x252c, + 0xe38d, 0x4e97, + 0xe38f, 0x2528, + 0xe390, 0x4e99, + 0xe391, 0x208c, + 0xe392, 0x4e9a, + 0xe393, 0x252f, + 0xe394, 0x4e9b, + 0xe395, 0x21bc, + 0xe396, 0x4e9c, + 0xe399, 0x251d, + 0xe39a, 0x4e9f, + 0xe39c, 0x2535, + 0xe39d, 0x4ea1, + 0xe39e, 0x220d, + 0xe39f, 0x2526, + 0xe3a0, 0x4ea2, + 0xe3a1, 0x1661, + 0xe440, 0x2534, + 0xe441, 0x252a, + 0xe442, 0x251f, + 0xe443, 0x2531, + 0xe444, 0x251c, + 0xe445, 0x4ea3, + 0xe448, 0x2525, + 0xe449, 0x4ea6, + 0xe44e, 0x21cd, + 0xe44f, 0x4eab, + 0xe450, 0x21da, + 0xe451, 0x4eac, + 0xe452, 0x2172, + 0xe453, 0x253e, + 0xe454, 0x4ead, + 0xe458, 0x204f, + 0xe459, 0x4eb1, + 0xe45a, 0x2543, + 0xe45b, 0x4eb2, + 0xe45c, 0x21d7, + 0xe45d, 0x4eb3, + 0xe45e, 0x1e3c, + 0xe45f, 0x4eb4, + 0xe462, 0x2529, + 0xe463, 0x4eb7, + 0xe465, 0x2521, + 0xe466, 0x4eb9, + 0xe468, 0x1eff, + 0xe469, 0x4ebb, + 0xe473, 0x253f, + 0xe474, 0x4ec5, + 0xe475, 0x2544, + 0xe476, 0x4ec6, + 0xe479, 0x2523, + 0xe47a, 0x1e90, + 0xe47b, 0x253a, + 0xe47c, 0x2545, + 0xe47d, 0x4ec9, + 0xe47e, 0x253d, + 0xe480, 0x4eca, + 0xe481, 0x20c1, + 0xe482, 0x4ecb, + 0xe484, 0x2103, + 0xe485, 0x2520, + 0xe486, 0x253c, + 0xe487, 0x253b, + 0xe488, 0x2538, + 0xe489, 0x4ecd, + 0xe48d, 0x2540, + 0xe48e, 0x4ed1, + 0xe48f, 0x1fcd, + 0xe490, 0x4ed2, + 0xe493, 0x1f18, + 0xe494, 0x4ed5, + 0xe498, 0x254b, + 0xe499, 0x4ed9, + 0xe49d, 0x2547, + 0xe49e, 0x254f, + 0xe4a0, 0x4edd, + 0xe4a1, 0x16bf, + 0xe540, 0x4ede, + 0xe546, 0x22b0, + 0xe547, 0x4ee4, + 0xe548, 0x2546, + 0xe549, 0x4ee5, + 0xe54b, 0x254c, + 0xe54c, 0x4ee7, + 0xe54e, 0x1e9a, + 0xe54f, 0x2552, + 0xe550, 0x2530, + 0xe551, 0x2549, + 0xe552, 0x4ee9, + 0xe555, 0x2551, + 0xe556, 0x1eca, + 0xe557, 0x4eec, + 0xe558, 0x20d2, + 0xe559, 0x4eed, + 0xe55c, 0x1fb8, + 0xe55d, 0x4ef0, + 0xe55e, 0x2079, + 0xe55f, 0x4ef1, + 0xe561, 0x21ab, + 0xe562, 0x4ef3, + 0xe564, 0x254d, + 0xe565, 0x1ea5, + 0xe566, 0x4ef5, + 0xe568, 0x204c, + 0xe569, 0x2080, + 0xe56a, 0x4ef7, + 0xe56c, 0x266d, + 0xe56d, 0x4ef9, + 0xe56e, 0x2537, + 0xe56f, 0x4efa, + 0xe575, 0x254a, + 0xe576, 0x21b8, + 0xe577, 0x4f00, + 0xe578, 0x254e, + 0xe579, 0x4f01, + 0xe57b, 0x24fc, + 0xe57c, 0x2554, + 0xe57d, 0x4f03, + 0xe580, 0x4f05, + 0xe581, 0x1f3c, + 0xe582, 0x4f06, + 0xe583, 0x1ed5, + 0xe584, 0x4f07, + 0xe58a, 0x2556, + 0xe58b, 0x4f0d, + 0xe58e, 0x2268, + 0xe58f, 0x4f10, + 0xe591, 0x1ed6, + 0xe592, 0x4f12, + 0xe59a, 0x2557, + 0xe59b, 0x2553, + 0xe59c, 0x4f1a, + 0xe59f, 0x2548, + 0xe5a0, 0x4f1d, + 0xe5a1, 0x171d, + 0xe640, 0x20dc, + 0xe641, 0x4f1e, + 0xe644, 0x2559, + 0xe645, 0x4f21, + 0xe649, 0x1f97, + 0xe64a, 0x2555, + 0xe64b, 0x4f25, + 0xe64e, 0x227d, + 0xe64f, 0x4f28, + 0xe652, 0x257e, + 0xe653, 0x4f2b, + 0xe656, 0x207c, + 0xe657, 0x4f2e, + 0xe658, 0x255a, + 0xe659, 0x4f2f, + 0xe65b, 0x255e, + 0xe65c, 0x4f31, + 0xe65e, 0x1e34, + 0xe65f, 0x4f33, + 0xe669, 0x215e, + 0xe66a, 0x4f3d, + 0xe66b, 0x2560, + 0xe66c, 0x4f3e, + 0xe675, 0x21a2, + 0xe676, 0x2354, + 0xe677, 0x4f47, + 0xe679, 0x2563, + 0xe67a, 0x2527, + 0xe67b, 0x4f49, + 0xe67c, 0x252e, + 0xe67d, 0x2558, + 0xe67e, 0x4f4a, + 0xe680, 0x1f1b, + 0xe681, 0x4f4b, + 0xe682, 0x2283, + 0xe683, 0x4f4c, + 0xe684, 0x2564, + 0xe685, 0x4f4d, + 0xe687, 0x20a0, + 0xe688, 0x4f4f, + 0xe689, 0x2565, + 0xe68a, 0x4f50, + 0xe68c, 0x2561, + 0xe68d, 0x4f52, + 0xe693, 0x2562, + 0xe694, 0x4f58, + 0xe697, 0x256c, + 0xe698, 0x4f5b, + 0xe69b, 0x256d, + 0xe69c, 0x2020, + 0xe69d, 0x4f5e, + 0xe69f, 0x255f, + 0xe6a0, 0x256a, + 0xe6a1, 0x177b, + 0xe740, 0x4f60, + 0xe743, 0x256e, + 0xe744, 0x4f63, + 0xe748, 0x2539, + 0xe749, 0x255c, + 0xe74a, 0x4f67, + 0xe74d, 0x2568, + 0xe74f, 0x256b, + 0xe750, 0x1e6f, + 0xe751, 0x4f6a, + 0xe752, 0x1fc4, + 0xe753, 0x2567, + 0xe754, 0x4f6b, + 0xe755, 0x255b, + 0xe756, 0x4f6c, + 0xe759, 0x261d, + 0xe75a, 0x4f6f, + 0xe766, 0x252b, + 0xe767, 0x4f7b, + 0xe768, 0x2571, + 0xe769, 0x4f7c, + 0xe76a, 0x2577, + 0xe76b, 0x4f7d, + 0xe774, 0x2522, + 0xe775, 0x4f86, + 0xe77c, 0x2533, + 0xe77d, 0x4f8d, + 0xe780, 0x4f8f, + 0xe782, 0x202a, + 0xe783, 0x4f91, + 0xe784, 0x2536, + 0xe785, 0x2573, + 0xe786, 0x256f, + 0xe787, 0x4f92, + 0xe78a, 0x2293, + 0xe78b, 0x2578, + 0xe78c, 0x4f95, + 0xe78f, 0x2570, + 0xe790, 0x4f98, + 0xe792, 0x2575, + 0xe793, 0x4f9a, + 0xe798, 0x2541, + 0xe79a, 0x255d, + 0xe79b, 0x4f9f, + 0xe7a0, 0x201a, + 0xe7a1, 0x17d9, + 0xe840, 0x4fa4, + 0xe843, 0x257a, + 0xe844, 0x2006, + 0xe845, 0x4fa7, + 0xe846, 0x2177, + 0xe847, 0x4fa8, + 0xe849, 0x251b, + 0xe84a, 0x4faa, + 0xe84b, 0x2524, + 0xe84c, 0x4fab, + 0xe84f, 0x257b, + 0xe850, 0x4fae, + 0xe854, 0x22a3, + 0xe855, 0x4fb2, + 0xe85a, 0x2579, + 0xe85b, 0x4fb7, + 0xe85c, 0x2566, + 0xe85d, 0x4fb8, + 0xe862, 0x1f93, + 0xe863, 0x4fbd, + 0xe864, 0x257c, + 0xe865, 0x4fbe, + 0xe870, 0x2514, + 0xe871, 0x4fc9, + 0xe873, 0x257d, + 0xe874, 0x4fcb, + 0xe875, 0x2572, + 0xe876, 0x4fcc, + 0xe87c, 0x2574, + 0xe87d, 0x4fd2, + 0xe880, 0x224e, + 0xe881, 0x4fd4, + 0xe882, 0x21c6, + 0xe883, 0x4fd5, + 0xe887, 0x209f, + 0xe888, 0x4fd9, + 0xe889, 0x2576, + 0xe88a, 0x4fda, + 0xe88c, 0x2064, + 0xe88d, 0x22bf, + 0xe88e, 0x261c, + 0xe88f, 0x225e, + 0xe890, 0x4fdc, + 0xe8a1, 0x1837, + 0xe940, 0x4fed, + 0xe94c, 0x1e75, + 0xe94d, 0x4ff9, + 0xe954, 0x207d, + 0xe955, 0x5000, + 0xe956, 0x23bf, + 0xe957, 0x2113, + 0xe958, 0x5001, + 0xe95a, 0x23c0, + 0xe95b, 0x5003, + 0xe95d, 0x1e45, + 0xe95e, 0x5005, + 0xe95f, 0x1fd8, + 0xe960, 0x23c4, + 0xe961, 0x5006, + 0xe962, 0x23c2, + 0xe963, 0x2104, + 0xe964, 0x5007, + 0xe965, 0x21bd, + 0xe966, 0x5008, + 0xe967, 0x1f87, + 0xe968, 0x23c3, + 0xe969, 0x5009, + 0xe96c, 0x2269, + 0xe96d, 0x500c, + 0xe975, 0x1f43, + 0xe976, 0x5014, + 0xe977, 0x1f1e, + 0xe978, 0x2679, + 0xe979, 0x1eeb, + 0xe97a, 0x5015, + 0xe97c, 0x1f35, + 0xe97d, 0x208a, + 0xe97e, 0x5017, + 0xe980, 0x23c7, + 0xe981, 0x23c9, + 0xe982, 0x23c6, + 0xe983, 0x5018, + 0xe987, 0x224f, + 0xe988, 0x501c, + 0xe98b, 0x23cb, + 0xe98c, 0x501f, + 0xe98e, 0x21f3, + 0xe98f, 0x5021, + 0xe990, 0x21f7, + 0xe991, 0x23cf, + 0xe992, 0x23ce, + 0xe993, 0x23ca, + 0xe994, 0x23cd, + 0xe995, 0x5022, + 0xe998, 0x23d0, + 0xe999, 0x5025, + 0xe99b, 0x266c, + 0xe99c, 0x5027, + 0xe99d, 0x23c1, + 0xe99e, 0x5028, + 0xe99f, 0x1fee, + 0xe9a0, 0x23d1, + 0xe9a1, 0x1895, + 0xea40, 0x1ff8, + 0xea41, 0x5029, + 0xea44, 0x23d3, + 0xea45, 0x502c, + 0xea48, 0x23d2, + 0xea49, 0x23d4, + 0xea4a, 0x1e98, + 0xea4b, 0x502f, + 0xea50, 0x1f2c, + 0xea51, 0x5034, + 0xea52, 0x23d5, + 0xea53, 0x5035, + 0xea55, 0x1e71, + 0xea56, 0x2691, + 0xea57, 0x5037, + 0xea59, 0x23c5, + 0xea5a, 0x5039, + 0xea80, 0x231a, + 0xea81, 0x505e, + 0xea84, 0x2114, + 0xea85, 0x5061, + 0xea87, 0x2284, + 0xea88, 0x5063, + 0xea8e, 0x221c, + 0xea8f, 0x5069, + 0xea90, 0x1e7e, + 0xea91, 0x204d, + 0xea92, 0x506a, + 0xea96, 0x2201, + 0xea97, 0x506e, + 0xeaa0, 0x1ed9, + 0xeaa1, 0x18f3, + 0xeb40, 0x5077, + 0xeb41, 0x1fb2, + 0xeb42, 0x5078, + 0xeb45, 0x2252, + 0xeb46, 0x507b, + 0xeb48, 0x1f79, + 0xeb49, 0x507d, + 0xeb53, 0x2157, + 0xeb54, 0x5087, + 0xeb55, 0x21bf, + 0xeb56, 0x5088, + 0xeb5b, 0x221f, + 0xeb5c, 0x508d, + 0xeb5d, 0x203d, + 0xeb5e, 0x508e, + 0xeb60, 0x2015, + 0xeb61, 0x5090, + 0xeb62, 0x26a5, + 0xeb63, 0x5091, + 0xeb6d, 0x2156, + 0xeb6e, 0x509b, + 0xeb70, 0x2144, + 0xeb71, 0x509d, + 0xeb72, 0x1e91, + 0xeb73, 0x2257, + 0xeb74, 0x509e, + 0xeb78, 0x200a, + 0xeb79, 0x2092, + 0xeb7a, 0x50a2, + 0xeb80, 0x50a7, + 0xeb85, 0x2250, + 0xeb86, 0x50ac, + 0xeb8a, 0x1ec3, + 0xeb8b, 0x50b0, + 0xeba1, 0x1951, + 0xec40, 0x50c6, + 0xec46, 0x21a8, + 0xec47, 0x50cc, + 0xec56, 0x260d, + 0xec57, 0x50db, + 0xec5a, 0x260c, + 0xec5b, 0x50de, + 0xec5c, 0x260e, + 0xec5d, 0x50df, + 0xec60, 0x2032, + 0xec61, 0x50e2, + 0xec6e, 0x260b, + 0xec6f, 0x50ef, + 0xec76, 0x22c3, + 0xec77, 0x50f6, + 0xec80, 0x50fe, + 0xec96, 0x1f23, + 0xec97, 0x5114, + 0xeca1, 0x19af, + 0xed40, 0x511e, + 0xed46, 0x2695, + 0xed47, 0x5124, + 0xed58, 0x265e, + 0xed59, 0x5135, + 0xed5e, 0x265d, + 0xed5f, 0x513a, + 0xed61, 0x2692, + 0xed62, 0x513c, + 0xed64, 0x265f, + 0xed65, 0x513e, + 0xed66, 0x218d, + 0xed67, 0x20fd, + 0xed68, 0x513f, + 0xed6e, 0x1f40, + 0xed6f, 0x5145, + 0xed74, 0x2465, + 0xed75, 0x514a, + 0xed77, 0x2467, + 0xed78, 0x514c, + 0xed79, 0x2466, + 0xed7a, 0x514d, + 0xed80, 0x5152, + 0xed91, 0x21c9, + 0xed92, 0x5163, + 0xed93, 0x2209, + 0xed94, 0x1ec9, + 0xed95, 0x20e9, + 0xed96, 0x5164, + 0xed97, 0x21ca, + 0xed98, 0x2146, + 0xed99, 0x25c5, + 0xed9a, 0x21dc, + 0xed9b, 0x5165, + 0xed9c, 0x245e, + 0xed9d, 0x5166, + 0xed9e, 0x214f, + 0xed9f, 0x5167, + 0xeda0, 0x25c6, + 0xeda1, 0x1a0d, + 0xee40, 0x25c7, + 0xee41, 0x2241, + 0xee42, 0x218a, + 0xee43, 0x1e2f, + 0xee44, 0x1edc, + 0xee45, 0x5168, + 0xee48, 0x20bf, + 0xee49, 0x2034, + 0xee4a, 0x516b, + 0xee4d, 0x25c9, + 0xee4e, 0x516e, + 0xee52, 0x25c8, + 0xee53, 0x5172, + 0xee55, 0x220e, + 0xee56, 0x5174, + 0xee57, 0x25cb, + 0xee58, 0x5175, + 0xee5e, 0x217d, + 0xee5f, 0x517b, + 0xee61, 0x1f7e, + 0xee62, 0x517d, + 0xee68, 0x25cc, + 0xee69, 0x1fc3, + 0xee6a, 0x5183, + 0xee6c, 0x20b9, + 0xee6d, 0x5185, + 0xee6e, 0x2181, + 0xee6f, 0x5186, + 0xee77, 0x1fda, + 0xee78, 0x518e, + 0xee7d, 0x2173, + 0xee7e, 0x1ee1, + 0xee80, 0x25cd, + 0xee81, 0x5193, + 0xee85, 0x25ce, + 0xee86, 0x21f6, + 0xee87, 0x5197, + 0xee8a, 0x224b, + 0xee8b, 0x25d1, + 0xee8c, 0x519a, + 0xee8d, 0x1ec0, + 0xee8e, 0x519b, + 0xee90, 0x2008, + 0xee91, 0x519d, + 0xee94, 0x25d0, + 0xee95, 0x51a0, + 0xee97, 0x25d2, + 0xee98, 0x51a2, + 0xee99, 0x1f2a, + 0xee9a, 0x51a3, + 0xee9d, 0x1e72, + 0xee9e, 0x25d3, + 0xee9f, 0x51a6, + 0xeea1, 0x1a6b, + 0xef40, 0x21be, + 0xef41, 0x25d4, + 0xef42, 0x2044, + 0xef43, 0x51a8, + 0xef44, 0x25cf, + 0xef45, 0x20f3, + 0xef46, 0x51a9, + 0xef4c, 0x1f00, + 0xef4d, 0x51af, + 0xef52, 0x24cc, + 0xef54, 0x51b4, + 0xef55, 0x2698, + 0xef56, 0x51b5, + 0xef57, 0x2678, + 0xef58, 0x51b6, + 0xef5a, 0x24ce, + 0xef5b, 0x51b8, + 0xef60, 0x24cf, + 0xef61, 0x51bd, + 0xef68, 0x20b8, + 0xef69, 0x51c4, + 0xef6a, 0x24d0, + 0xef6b, 0x51c5, + 0xef6c, 0x24d1, + 0xef6d, 0x51c6, + 0xef77, 0x1ef4, + 0xef78, 0x51d0, + 0xef7a, 0x239b, + 0xef7b, 0x51d2, + 0xef7c, 0x267e, + 0xef7d, 0x51d3, + 0xef80, 0x51d5, + 0xef82, 0x239d, + 0xef83, 0x239f, + 0xef85, 0x51d7, + 0xef86, 0x23a1, + 0xef87, 0x51d8, + 0xef88, 0x1ef1, + 0xef89, 0x51d9, + 0xef8b, 0x221e, + 0xef8c, 0x51db, + 0xef8d, 0x23a2, + 0xef8e, 0x51dc, + 0xef95, 0x214b, + 0xef96, 0x1e36, + 0xef97, 0x2135, + 0xef98, 0x51e3, + 0xef9c, 0x1fad, + 0xef9d, 0x51e7, + 0xef9e, 0x1e53, + 0xef9f, 0x51e8, + 0xefa1, 0x1ac9, + 0xf040, 0x51ea, + 0xf041, 0x23a3, + 0xf042, 0x2203, + 0xf043, 0x51eb, + 0xf044, 0x1ee7, + 0xf045, 0x51ec, + 0xf047, 0x23a4, + 0xf048, 0x2097, + 0xf049, 0x1ee4, + 0xf04a, 0x51ee, + 0xf04e, 0x2238, + 0xf04f, 0x51f2, + 0xf051, 0x23a5, + 0xf052, 0x51f4, + 0xf054, 0x1f9a, + 0xf055, 0x51f6, + 0xf057, 0x21c3, + 0xf058, 0x51f8, + 0xf05e, 0x1f2e, + 0xf05f, 0x51fe, + 0xf068, 0x239c, + 0xf069, 0x5207, + 0xf06c, 0x23a6, + 0xf06d, 0x520a, + 0xf071, 0x239e, + 0xf072, 0x520e, + 0xf073, 0x2035, + 0xf074, 0x23a7, + 0xf075, 0x520f, + 0xf078, 0x23a8, + 0xf079, 0x5212, + 0xf07a, 0x2075, + 0xf07b, 0x5213, + 0xf07d, 0x23a9, + 0xf080, 0x23ab, + 0xf081, 0x1feb, + 0xf082, 0x23ac, + 0xf083, 0x5215, + 0xf087, 0x1f6a, + 0xf088, 0x20f9, + 0xf089, 0x5219, + 0xf08b, 0x2666, + 0xf08c, 0x521b, + 0xf090, 0x2667, + 0xf091, 0x521f, + 0xf092, 0x1e6c, + 0xf093, 0x5220, + 0xf096, 0x23ad, + 0xf097, 0x5223, + 0xf0a1, 0x1b27, + 0xf140, 0x522d, + 0xf152, 0x206d, + 0xf153, 0x2242, + 0xf154, 0x1f02, + 0xf155, 0x523f, + 0xf157, 0x2183, + 0xf158, 0x5241, + 0xf159, 0x1e85, + 0xf15a, 0x21e9, + 0xf15b, 0x5242, + 0xf167, 0x1e57, + 0xf168, 0x524e, + 0xf176, 0x22a5, + 0xf177, 0x2407, + 0xf178, 0x1fca, + 0xf179, 0x525c, + 0xf17a, 0x2402, + 0xf17b, 0x1f82, + 0xf17c, 0x525d, + 0xf17e, 0x2408, + 0xf180, 0x2404, + 0xf181, 0x525f, + 0xf182, 0x2131, + 0xf183, 0x5260, + 0xf184, 0x2184, + 0xf185, 0x5261, + 0xf186, 0x2403, + 0xf187, 0x5262, + 0xf188, 0x206e, + 0xf189, 0x240b, + 0xf18a, 0x5263, + 0xf194, 0x1f3f, + 0xf195, 0x526d, + 0xf198, 0x2067, + 0xf199, 0x5270, + 0xf1a1, 0x1b85, + 0xf240, 0x5278, + 0xf245, 0x1fd7, + 0xf246, 0x527d, + 0xf247, 0x1e83, + 0xf248, 0x527e, + 0xf24b, 0x240f, + 0xf24c, 0x5281, + 0xf253, 0x240e, + 0xf254, 0x20c7, + 0xf255, 0x240d, + 0xf256, 0x5288, + 0xf25c, 0x2412, + 0xf25d, 0x528e, + 0xf25f, 0x20b7, + 0xf260, 0x5290, + 0xf271, 0x23f0, + 0xf272, 0x52a1, + 0xf273, 0x2411, + 0xf274, 0x2414, + 0xf275, 0x52a2, + 0xf276, 0x2170, + 0xf277, 0x52a3, + 0xf27c, 0x2405, + 0xf27d, 0x210c, + 0xf27e, 0x2415, + 0xf280, 0x52a8, + 0xf285, 0x2066, + 0xf286, 0x52ad, + 0xf287, 0x2352, + 0xf288, 0x2413, + 0xf289, 0x2410, + 0xf28a, 0x2416, + 0xf28c, 0x20f1, + 0xf28d, 0x52ae, + 0xf291, 0x240a, + 0xf292, 0x52b2, + 0xf294, 0x2409, + 0xf295, 0x52b4, + 0xf296, 0x2418, + 0xf297, 0x52b5, + 0xf29c, 0x1fa7, + 0xf29d, 0x52ba, + 0xf29e, 0x21fc, + 0xf29f, 0x52bb, + 0xf2a1, 0x1be3, + 0xf340, 0x1fc1, + 0xf341, 0x2406, + 0xf342, 0x52bd, + 0xf345, 0x229c, + 0xf346, 0x52c0, + 0xf348, 0x204e, + 0xf349, 0x52c2, + 0xf34a, 0x241a, + 0xf34b, 0x2419, + 0xf34c, 0x52c3, + 0xf350, 0x240c, + 0xf351, 0x52c7, + 0xf361, 0x1e29, + 0xf362, 0x52d7, + 0xf374, 0x2661, + 0xf375, 0x52e9, + 0xf376, 0x26a4, + 0xf377, 0x2174, + 0xf378, 0x2663, + 0xf379, 0x2662, + 0xf37a, 0x52ea, + 0xf380, 0x52ef, + 0xf38c, 0x2675, + 0xf38d, 0x52fb, + 0xf3a0, 0x214c, + 0xf3a1, 0x1c41, + 0xf440, 0x530e, + 0xf445, 0x267a, + 0xf446, 0x5313, + 0xf450, 0x26a0, + 0xf451, 0x531d, + 0xf457, 0x2668, + 0xf458, 0x5323, + 0xf459, 0x1ed0, + 0xf45a, 0x5324, + 0xf45b, 0x2096, + 0xf45c, 0x5325, + 0xf45d, 0x23cc, + 0xf45e, 0x5326, + 0xf462, 0x23c8, + 0xf463, 0x532a, + 0xf464, 0x223e, + 0xf465, 0x532b, + 0xf475, 0x2665, + 0xf476, 0x533b, + 0xf47c, 0x2664, + 0xf47d, 0x5341, + 0xf47e, 0x2239, + 0xf480, 0x5342, + 0xf494, 0x204a, + 0xf495, 0x5356, + 0xf499, 0x261f, + 0xf49a, 0x535a, + 0xf49c, 0x261e, + 0xf49d, 0x535c, + 0xf4a1, 0x1c9f, + 0xf540, 0x5360, + 0xf545, 0x2620, + 0xf546, 0x5365, + 0xf547, 0x2621, + 0xf548, 0x5366, + 0xf552, 0x2622, + 0xf553, 0x5370, + 0xf554, 0x2627, + 0xf555, 0x1e39, + 0xf556, 0x2625, + 0xf557, 0x5371, + 0xf55e, 0x2629, + 0xf55f, 0x5378, + 0xf561, 0x262e, + 0xf562, 0x262b, + 0xf563, 0x537a, + 0xf56e, 0x262a, + 0xf56f, 0x262d, + 0xf570, 0x5385, + 0xf571, 0x2628, + 0xf572, 0x21b9, + 0xf573, 0x5386, + 0xf580, 0x5392, + 0xf585, 0x2636, + 0xf586, 0x2630, + 0xf587, 0x5397, + 0xf58c, 0x2638, + 0xf58d, 0x539c, + 0xf58e, 0x200d, + 0xf58f, 0x2637, + 0xf590, 0x539d, + 0xf599, 0x2645, + 0xf59a, 0x53a6, + 0xf59b, 0x263a, + 0xf59c, 0x53a7, + 0xf5a0, 0x2643, + 0xf5a1, 0x1cfd, + 0xf640, 0x53ab, + 0xf641, 0x2640, + 0xf642, 0x53ac, + 0xf645, 0x263d, + 0xf646, 0x2641, + 0xf647, 0x53af, + 0xf648, 0x263e, + 0xf649, 0x53b0, + 0xf64b, 0x263f, + 0xf64c, 0x1fc0, + 0xf64d, 0x53b2, + 0xf64e, 0x263b, + 0xf650, 0x53b3, + 0xf654, 0x2642, + 0xf655, 0x53b7, + 0xf658, 0x2644, + 0xf659, 0x53ba, + 0xf661, 0x2639, + 0xf662, 0x53c2, + 0xf663, 0x264c, + 0xf664, 0x53c3, + 0xf66c, 0x2647, + 0xf66d, 0x264b, + 0xf66e, 0x53cb, + 0xf671, 0x2649, + 0xf672, 0x53ce, + 0xf674, 0x2648, + 0xf675, 0x53d0, + 0xf676, 0x264a, + 0xf677, 0x2108, + 0xf678, 0x53d1, + 0xf680, 0x53d8, + 0xf685, 0x264d, + 0xf686, 0x53dd, + 0xf688, 0x2634, + 0xf689, 0x53df, + 0xf68a, 0x2651, + 0xf68b, 0x53e0, + 0xf68d, 0x2650, + 0xf68e, 0x2652, + 0xf68f, 0x53e2, + 0xf692, 0x264f, + 0xf693, 0x53e5, + 0xf696, 0x2632, + 0xf697, 0x264e, + 0xf698, 0x2653, + 0xf699, 0x53e8, + 0xf69a, 0x2657, + 0xf69b, 0x53e9, + 0xf69c, 0x2635, + 0xf69d, 0x53ea, + 0xf69e, 0x2633, + 0xf69f, 0x53eb, + 0xf6a0, 0x2656, + 0xf6a1, 0x1d5b, + 0xf740, 0x53ec, + 0xf742, 0x2654, + 0xf743, 0x53ee, + 0xf749, 0x2658, + 0xf74a, 0x53f4, + 0xf74c, 0x2655, + 0xf74d, 0x1e4d, + 0xf74e, 0x53f6, + 0xf756, 0x265b, + 0xf757, 0x53fe, + 0xf758, 0x265a, + 0xf759, 0x53ff, + 0xf75a, 0x2659, + 0xf75b, 0x202e, + 0xf75c, 0x262f, + 0xf75d, 0x5400, + 0xf761, 0x2646, + 0xf762, 0x5404, + 0xf763, 0x2626, + 0xf764, 0x5405, + 0xf76b, 0x265c, + 0xf76c, 0x540c, + 0xf771, 0x262c, + 0xf772, 0x5411, + 0xf77c, 0x2623, + 0xf77d, 0x541b, + 0xf77e, 0x2631, + 0xf780, 0x541c, + 0xf7a1, 0x1db9, + 0xf840, 0x543d, + 0xf842, 0x209c, + 0xf843, 0x543f, + 0xf846, 0x2580, + 0xf847, 0x5442, + 0xf849, 0x22dc, + 0xf84a, 0x5444, + 0xf850, 0x1f05, + 0xf851, 0x208b, + 0xf852, 0x544a, + 0xf853, 0x2581, + 0xf854, 0x544b, + 0xf863, 0x2583, + 0xf864, 0x2582, + 0xf865, 0x545a, + 0xf866, 0x21ee, + 0xf867, 0x545b, + 0xf872, 0x2182, + 0xf873, 0x5466, + 0xf878, 0x2243, + 0xf879, 0x546b, + 0xf87a, 0x2587, + 0xf87b, 0x546c, + 0xf87c, 0x2588, + 0xf87d, 0x546d, + 0xf880, 0x546f, + 0xf881, 0x2584, + 0xf882, 0x5470, + 0xf884, 0x21fd, + 0xf885, 0x5472, + 0xf886, 0x21ef, + 0xf887, 0x5473, + 0xf88d, 0x258a, + 0xf88e, 0x258c, + 0xf88f, 0x5479, + 0xf899, 0x1f47, + 0xf89a, 0x5483, + 0xf89d, 0x1f1d, + 0xf89e, 0x5486, + 0xf8a0, 0x258d, + 0xf940, 0x5488, + 0xf94e, 0x1fd0, + 0xf94f, 0x2592, + 0xf950, 0x258f, + 0xf951, 0x5496, + 0xf959, 0x2594, + 0xf95a, 0x1ee0, + 0xf95b, 0x549e, + 0xf95d, 0x2591, + 0xf95e, 0x2595, + 0xf95f, 0x54a0, + 0xf967, 0x2597, + 0xf968, 0x54a8, + 0xf969, 0x20b6, + 0xf96a, 0x54a9, + 0xf96c, 0x2598, + 0xf96d, 0x54ab, + 0xf96f, 0x20f6, + 0xf970, 0x54ad, + 0xf980, 0x54bc, + 0xf985, 0x2585, + 0xf986, 0x54c1, + 0xf987, 0x2599, + 0xf988, 0x54c2, + 0xf991, 0x2596, + 0xf992, 0x54cb, + 0xf996, 0x259a, + 0xf997, 0x54cf, + 0xf998, 0x259b, + 0xf999, 0x54d0, + 0xfa40, 0x54d8, + 0xfa42, 0x259d, + 0xfa43, 0x54da, + 0xfa46, 0x259e, + 0xfa47, 0x54dd, + 0xfa4c, 0x234c, + 0xfa4d, 0x54e2, + 0xfa51, 0x1f44, + 0xfa52, 0x54e6, + 0xfa58, 0x2660, + 0xfa59, 0x25a0, + 0xfa5a, 0x54ec, + 0xfa5d, 0x259c, + 0xfa5e, 0x54ef, + 0xfa5f, 0x259f, + 0xfa60, 0x54f0, + 0xfa61, 0x1f6c, + 0xfa62, 0x54f1, + 0xfa70, 0x25a2, + 0xfa71, 0x54ff, + 0xfa74, 0x20ae, + 0xfa75, 0x5502, + 0xfa76, 0x258b, + 0xfa77, 0x25a3, + 0xfa78, 0x5503, + 0xfa80, 0x550a, + 0xfa83, 0x2589, + 0xfa84, 0x25a5, + 0xfa85, 0x550d, + 0xfa8d, 0x25a4, + 0xfa8e, 0x5515, + 0xfa90, 0x25a6, + 0xfa91, 0x2593, + 0xfa92, 0x5517, + 0xfa96, 0x25a7, + 0xfa97, 0x2222, + 0xfa98, 0x25a9, + 0xfa99, 0x551b, + 0xfb40, 0x5523, + 0xfb49, 0x25a8, + 0xfb4a, 0x552c, + 0xfb52, 0x2586, + 0xfb53, 0x5534, + 0xfb57, 0x25a1, + 0xfb58, 0x25aa, + 0xfb59, 0x5538, + 0xfb5a, 0x2590, + 0xfb5b, 0x258e, + 0xfb5c, 0x5539, + 0xfb75, 0x2688, + 0xfb76, 0x5552, + 0xfb79, 0x269e, + 0xfb7a, 0x25fb, + 0xfb7b, 0x5555, + 0xfb7c, 0x1f8c, + 0xfb7d, 0x21f4, + 0xfb7e, 0x5556, + 0xfb80, 0x5557, + 0xfb90, 0x200f, + 0xfb91, 0x5567, + 0xfb9c, 0x2071, + 0xfb9d, 0x5572, + 0xfb9f, 0x25f7, + 0xfba0, 0x5574, + 0xfc40, 0x5575, + 0xfc44, 0x2696, + 0xfc45, 0x5579, + 0xfc49, 0x268f, + 0xfc4a, 0x557d, + 0xfc5a, 0x22da, + 0xfc5b, 0x558d, + 0xfc63, 0x1ec1, + 0xfc64, 0x5595, + 0xfc68, 0x1eb3, + 0xfc69, 0x5599, + 0xfc6f, 0x266a, + 0xfc70, 0x559f, + 0xfc71, 0x268a, + 0xfc72, 0x55a0, + 0xfc74, 0x2669, + 0xfc75, 0x55a2, + 0xfc77, 0x2618, + 0xfc79, 0x55a4, + 0xfc80, 0x55aa, + 0xfc83, 0x261a, + 0xfc84, 0x55ad, + 0xfc8a, 0x2673, + 0xfc8b, 0x55b3, + 0xfd40, 0x55c9, + 0xfd52, 0x20c6, + 0xfd53, 0x226b, + 0xfd54, 0x55db, + 0xfd57, 0x24d3, + 0xfd58, 0x1e86, + 0xfd59, 0x55de, + 0xfd5a, 0x260f, + 0xfd5b, 0x55df, + 0xfd5f, 0x2611, + 0xfd60, 0x55e3, + 0xfd62, 0x2613, + 0xfd63, 0x55e5, + 0xfd65, 0x2610, + 0xfd66, 0x2612, + 0xfd67, 0x2030, + 0xfd68, 0x55e7, + 0xfd69, 0x2671, + 0xfd6a, 0x55e8, + 0xfd6c, 0x2614, + 0xfd6d, 0x55ea, + 0xfd70, 0x2616, + 0xfd71, 0x55ed, + 0xfd72, 0x2615, + 0xfd73, 0x55ee, + 0xfd78, 0x20f2, + 0xfd79, 0x55f3, + 0xfd7d, 0x2617, + 0xfd7e, 0x55f7, + 0xfd80, 0x55f8, + 0xfd88, 0x2037, + 0xfd89, 0x5600, + 0xfd8b, 0x20b3, + 0xfd8c, 0x5602, + 0xfd8f, 0x1f22, + 0xfd90, 0x24ed, + 0xfd91, 0x5605, + 0xfd94, 0x1f34, + 0xfd95, 0x5608, + 0xfd9d, 0x0a02, + 0xfd9e, 0x40d3, + 0xfd9f, 0x200c, + 0xfda0, 0x5083, + 0xfe40, 0x1259, + 0xfe41, 0x5610, + 0xfe80, 0x564e, + 0xa1a2, 0x023f, + 0xa1a3, 0x023e, + 0xa1aa, 0x0256, + 0xa1ab, 0x1e18, + 0xa1ad, 0x0257, + 0xa1b2, 0x0246, + 0xa1fe, 0x1e1a, + 0xa3a1, 0x0242, + 0xa3a8, 0x0244, + 0xa3ac, 0x023d, + 0xa3ae, 0x1e1b, + 0xa3ba, 0x0240, + 0xa3bd, 0x1e1c, + 0xa3bf, 0x0243, + 0xa3db, 0x1e1d, + 0xa3dd, 0x1e1e, + 0xa3df, 0x0258, + 0xa3fb, 0x0254, + 0xa3fd, 0x0255, + 0xa3fe, 0x1e1f, + 0xffff, 0x0000 +}; + +static GfxFontEncoding16 gb12GBKEUCVEnc16 = { + 1, + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 }, + { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1e24, 0x032e, 0x032f, 0x0330, 0x0331, 0x0332, 0x0333, 0x0334, + 0x0335, 0x0336, 0x0337, 0x0338, 0x0339, 0x033a, 0x033b, 0x033c, + 0x033d, 0x033e, 0x033f, 0x0340, 0x0341, 0x0342, 0x0343, 0x0344, + 0x0345, 0x0346, 0x0347, 0x0348, 0x0349, 0x034a, 0x034b, 0x034c, + 0x034d, 0x034e, 0x034f, 0x0350, 0x0351, 0x0352, 0x0353, 0x0354, + 0x0355, 0x0356, 0x0357, 0x0358, 0x0359, 0x035a, 0x035b, 0x035c, + 0x035d, 0x035e, 0x035f, 0x0360, 0x0361, 0x0362, 0x0363, 0x0364, + 0x0365, 0x0366, 0x0367, 0x0368, 0x0369, 0x036a, 0x036b, 0x036c, + 0x036d, 0x036e, 0x036f, 0x0370, 0x0371, 0x0372, 0x0373, 0x0374, + 0x0375, 0x0376, 0x0377, 0x0378, 0x0379, 0x037a, 0x037b, 0x037c, + 0x037d, 0x037e, 0x037f, 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, + 0x0385, 0x0386, 0x0387, 0x0388, 0x0389, 0x038a, 0x038b, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, + gb12GBKEUCVMap2, 4091 +}; + +static Gushort gb12GBTEUCHMap2[4566] = { + 0x0000, 0x0000, + 0xa1a1, 0x0060, + 0xa2b1, 0x00be, + 0xa2e5, 0x00f0, + 0xa2f1, 0x00fa, + 0xa3a1, 0x0106, + 0xa4a1, 0x0164, + 0xa5a1, 0x01b7, + 0xa6a1, 0x020d, + 0xa6c1, 0x0225, + 0xa7a1, 0x025a, + 0xa7d1, 0x027b, + 0xa8a1, 0x029c, + 0xa8c5, 0x02bc, + 0xa9a4, 0x02e2, + 0xaaa1, 0x032e, + 0xaba1, 0x038c, + 0xb0a1, 0x03ac, + 0xb0a8, 0x1e25, + 0xb0a9, 0x03b4, + 0xb0aa, 0x1e26, + 0xb0ab, 0x03b6, + 0xb0ad, 0x1e27, + 0xb0af, 0x03ba, + 0xb0b9, 0x1e29, + 0xb0ba, 0x03c5, + 0xb0c0, 0x1e2a, + 0xb0c1, 0x03cc, + 0xb0d3, 0x1e2b, + 0xb0d4, 0x03df, + 0xb0d5, 0x1e2c, + 0xb0d6, 0x03e1, + 0xb0da, 0x1e2d, + 0xb0db, 0x03e6, + 0xb0dc, 0x1e2e, + 0xb0dd, 0x03e8, + 0xb0e4, 0x1e2f, + 0xb0e5, 0x03f0, + 0xb0ec, 0x1e30, + 0xb0ee, 0x03f9, + 0xb0ef, 0x1e32, + 0xb0f0, 0x03fb, + 0xb0f3, 0x1e33, + 0xb0f4, 0x03ff, + 0xb0f7, 0x1e34, + 0xb0f8, 0x0403, + 0xb0f9, 0x1e35, + 0xb0fa, 0x0405, + 0xb1a1, 0x040a, + 0xb1a5, 0x1e36, + 0xb1a7, 0x0410, + 0xb1a8, 0x1e38, + 0xb1a9, 0x0412, + 0xb1ab, 0x1e39, + 0xb1ac, 0x0415, + 0xb1b2, 0x1e3a, + 0xb1b3, 0x041c, + 0xb1b4, 0x1e3b, + 0xb1b6, 0x041f, + 0xb1b7, 0x1e3d, + 0xb1ba, 0x0423, + 0xb1c1, 0x1e40, + 0xb1c2, 0x042b, + 0xb1ca, 0x1e41, + 0xb1cb, 0x0434, + 0xb1cf, 0x1e42, + 0xb1d1, 0x043a, + 0xb1d2, 0x1e44, + 0xb1d3, 0x043c, + 0xb1d5, 0x1e45, + 0xb1d6, 0x043f, + 0xb1df, 0x1e46, + 0xb1e2, 0x044b, + 0xb1e4, 0x1e49, + 0xb1e5, 0x044e, + 0xb1e7, 0x1e4a, + 0xb1e9, 0x0452, + 0xb1ea, 0x1e4c, + 0xb1eb, 0x0454, + 0xb1ee, 0x1e4d, + 0xb1ef, 0x0458, + 0xb1f1, 0x1e4e, + 0xb1f2, 0x045b, + 0xb1f4, 0x1e4f, + 0xb1f8, 0x0461, + 0xb1fd, 0x1e53, + 0xb1fe, 0x0467, + 0xb2a1, 0x0468, + 0xb2a6, 0x1e54, + 0xb2a8, 0x046f, + 0xb2ac, 0x1e56, + 0xb2ad, 0x0474, + 0xb2b5, 0x1e57, + 0xb2b6, 0x047d, + 0xb2b9, 0x1e58, + 0xb2ba, 0x0481, + 0xb2c6, 0x1e59, + 0xb2c7, 0x048e, + 0xb2ce, 0x1e5a, + 0xb2d8, 0x049f, + 0xb2de, 0x1e64, + 0xb2df, 0x04a6, + 0xb2e0, 0x1e65, + 0xb2e1, 0x04a8, + 0xb2e2, 0x1e66, + 0xb2e4, 0x04ab, + 0xb2ef, 0x1e68, + 0xb2f0, 0x04b7, + 0xb2f3, 0x1e69, + 0xb2fd, 0x04c4, + 0xb3a1, 0x1e73, + 0xb3a3, 0x04c8, + 0xb3a4, 0x1e75, + 0xb3a8, 0x04cd, + 0xb3a9, 0x1e79, + 0xb3aa, 0x04cf, + 0xb3ae, 0x1e7a, + 0xb3af, 0x04d4, + 0xb3b5, 0x1e7b, + 0xb3b6, 0x04db, + 0xb3b9, 0x1e7c, + 0xb3ba, 0x04df, + 0xb3be, 0x1e7d, + 0xb3bf, 0x04e4, + 0xb3c2, 0x1e7e, + 0xb3c3, 0x04e8, + 0xb3c4, 0x1e7f, + 0xb3c5, 0x04ea, + 0xb3c6, 0x1e80, + 0xb3c7, 0x04ec, + 0xb3cd, 0x1e81, + 0xb3ce, 0x04f3, + 0xb3cf, 0x1e82, + 0xb3d0, 0x04f5, + 0xb3d2, 0x1e83, + 0xb3d3, 0x04f8, + 0xb3d9, 0x1e84, + 0xb3da, 0x04ff, + 0xb3db, 0x1e85, + 0xb3dc, 0x0501, + 0xb3dd, 0x1e86, + 0xb3de, 0x0503, + 0xb3e3, 0x1e87, + 0xb3e4, 0x0509, + 0xb3e5, 0x1e88, + 0xb3e7, 0x050c, + 0xb3e8, 0x1e8a, + 0xb3e9, 0x050e, + 0xb3eb, 0x1e8b, + 0xb3ed, 0x0512, + 0xb3ef, 0x1e8d, + 0xb3f0, 0x0515, + 0xb3f1, 0x1e8e, + 0xb3f2, 0x0517, + 0xb3f3, 0x1e8f, + 0xb3f4, 0x0519, + 0xb3fa, 0x1e90, + 0xb3fc, 0x0521, + 0xb4a1, 0x1e92, + 0xb4a3, 0x0526, + 0xb4a5, 0x1e94, + 0xb4a7, 0x052a, + 0xb4ab, 0x1e96, + 0xb4ac, 0x052f, + 0xb4af, 0x1e97, + 0xb4b0, 0x0533, + 0xb4b3, 0x1e98, + 0xb4b5, 0x0538, + 0xb4b8, 0x1e9a, + 0xb4b9, 0x053c, + 0xb4bf, 0x1e9b, + 0xb4c0, 0x0543, + 0xb4c2, 0x1e9c, + 0xb4c3, 0x0546, + 0xb4c7, 0x1e9d, + 0xb4c8, 0x054b, + 0xb4ca, 0x1e9e, + 0xb4cb, 0x054e, + 0xb4cd, 0x1e9f, + 0xb4ce, 0x0551, + 0xb4cf, 0x1ea0, + 0xb4d0, 0x0553, + 0xb4d3, 0x1ea1, + 0xb4d5, 0x0558, + 0xb4da, 0x1ea3, + 0xb4db, 0x055e, + 0xb4dc, 0x1ea4, + 0xb4dd, 0x0560, + 0xb4ed, 0x1ea5, + 0xb4ee, 0x0571, + 0xb4ef, 0x1ea6, + 0xb4f0, 0x0573, + 0xb4f8, 0x1ea7, + 0xb4f9, 0x057c, + 0xb4fb, 0x1ea8, + 0xb4fc, 0x057f, + 0xb5a1, 0x0582, + 0xb5a3, 0x1ea9, + 0xb5a4, 0x0585, + 0xb5a5, 0x1eaa, + 0xb5a9, 0x058a, + 0xb5ac, 0x1eae, + 0xb5ad, 0x058e, + 0xb5ae, 0x1eaf, + 0xb5b0, 0x0591, + 0xb5b1, 0x1eb1, + 0xb5b6, 0x0597, + 0xb5b7, 0x1eb6, + 0xb5b8, 0x0599, + 0xb5ba, 0x1eb7, + 0xb5bd, 0x059e, + 0xb5c6, 0x1eba, + 0xb5c7, 0x05a8, + 0xb5cb, 0x1ebb, + 0xb5cc, 0x05ad, + 0xb5d0, 0x1ebc, + 0xb5d1, 0x05b2, + 0xb5d3, 0x1ebd, + 0xb5d4, 0x05b5, + 0xb5dd, 0x1ebe, + 0xb5e0, 0x05c1, + 0xb5e3, 0x1ec1, + 0xb5e4, 0x05c5, + 0xb5e6, 0x1ec2, + 0xb5e8, 0x05c9, + 0xb5ed, 0x1ec4, + 0xb5ee, 0x05cf, + 0xb5f6, 0x1ec5, + 0xb5f8, 0x05d9, + 0xb5fd, 0x1ec7, + 0xb5fe, 0x05df, + 0xb6a1, 0x05e0, + 0xb6a4, 0x1ec8, + 0xb6a6, 0x05e5, + 0xb6a7, 0x1eca, + 0xb6a8, 0x05e7, + 0xb6a9, 0x1ecb, + 0xb6aa, 0x05e9, + 0xb6ab, 0x1ecc, + 0xb6ac, 0x05eb, + 0xb6af, 0x1ecd, + 0xb6b1, 0x05f0, + 0xb6b3, 0x1ecf, + 0xb6b4, 0x05f3, + 0xb6b7, 0x1ed0, + 0xb6b8, 0x05f7, + 0xb6bf, 0x1ed1, + 0xb6c2, 0x0601, + 0xb6c4, 0x1ed4, + 0xb6c5, 0x0604, + 0xb6c6, 0x1ed5, + 0xb6c7, 0x0606, + 0xb6cd, 0x1ed6, + 0xb6ce, 0x060d, + 0xb6cf, 0x1ed7, + 0xb6d1, 0x0610, + 0xb6d3, 0x1ed9, + 0xb6d5, 0x0614, + 0xb6d6, 0x1edb, + 0xb6d7, 0x0616, + 0xb6d9, 0x1edc, + 0xb6da, 0x0619, + 0xb6db, 0x1edd, + 0xb6dc, 0x061b, + 0xb6e1, 0x1ede, + 0xb6e2, 0x0621, + 0xb6e9, 0x1edf, + 0xb6ea, 0x0629, + 0xb6ec, 0x1ee0, + 0xb6ed, 0x062c, + 0xb6ee, 0x1ee1, + 0xb6f0, 0x062f, + 0xb6f1, 0x1ee3, + 0xb6f2, 0x0631, + 0xb6f6, 0x1ee4, + 0xb6f7, 0x0636, + 0xb6f9, 0x1ee5, + 0xb6fa, 0x0639, + 0xb6fb, 0x1ee6, + 0xb6fd, 0x063c, + 0xb7a1, 0x1ee8, + 0xb7a4, 0x0641, + 0xb7a7, 0x1eeb, + 0xb7a8, 0x0645, + 0xb7af, 0x1eec, + 0xb7b1, 0x064e, + 0xb7b3, 0x1eee, + 0xb7b4, 0x0651, + 0xb7b6, 0x1eef, + 0xb7b8, 0x0655, + 0xb7b9, 0x1ef1, + 0xb7ba, 0x0657, + 0xb7c3, 0x1ef2, + 0xb7c5, 0x0662, + 0xb7c9, 0x1ef4, + 0xb7ca, 0x0667, + 0xb7cc, 0x1ef5, + 0xb7cd, 0x066a, + 0xb7cf, 0x1ef6, + 0xb7d0, 0x066d, + 0xb7d1, 0x1ef7, + 0xb7d2, 0x066f, + 0xb7d7, 0x1ef8, + 0xb7d9, 0x0676, + 0xb7dc, 0x1efa, + 0xb7dd, 0x067a, + 0xb7df, 0x1efb, + 0xb7e2, 0x067f, + 0xb7e3, 0x1efe, + 0xb7e4, 0x0681, + 0xb7e6, 0x1eff, + 0xb7e9, 0x0686, + 0xb7eb, 0x1f02, + 0xb7ee, 0x068b, + 0xb7ef, 0x1f05, + 0xb7f0, 0x068d, + 0xb7f4, 0x1f06, + 0xb7f5, 0x0692, + 0xb7f8, 0x1f07, + 0xb7f9, 0x0696, + 0xb8a1, 0x069c, + 0xb8a7, 0x1f08, + 0xb8a9, 0x06a4, + 0xb8b3, 0x1f0a, + 0xb8b5, 0x06b0, + 0xb8ba, 0x1f0c, + 0xb8bb, 0x06b6, + 0xb8bc, 0x1f0d, + 0xb8bd, 0x06b8, + 0xb8be, 0x1f0e, + 0xb8c0, 0x06bb, + 0xb8c3, 0x1f10, + 0xb8c4, 0x06bf, + 0xb8c6, 0x1f11, + 0xb8c8, 0x06c3, + 0xb8c9, 0x1f13, + 0xb8ca, 0x06c5, + 0xb8cf, 0x1f14, + 0xb8d0, 0x06cb, + 0xb8d3, 0x1f15, + 0xb8d7, 0x06d2, + 0xb8d9, 0x1f19, + 0xb8db, 0x06d6, + 0xb8e4, 0x1f1b, + 0xb8e5, 0x06e0, + 0xb8e9, 0x1f1c, + 0xb8ea, 0x06e5, + 0xb8eb, 0x1f1d, + 0xb8ec, 0x06e7, + 0xb8f3, 0x1f1e, + 0xb8f4, 0x06ef, + 0xb8f5, 0x1f1f, + 0xb8f7, 0x06f2, + 0xb8f8, 0x1f21, + 0xb8f9, 0x06f4, + 0xb9a1, 0x06fa, + 0xb9a8, 0x1f22, + 0xb9a9, 0x0702, + 0xb9ae, 0x1f23, + 0xb9af, 0x0708, + 0xb9b1, 0x1f24, + 0xb9b2, 0x070b, + 0xb9b3, 0x1f25, + 0xb9b4, 0x070d, + 0xb9b5, 0x1f26, + 0xb9b6, 0x070f, + 0xb9b9, 0x1f27, + 0xb9bb, 0x0714, + 0xb9c6, 0x1f29, + 0xb9c7, 0x0720, + 0xb9cb, 0x1f2a, + 0xb9cc, 0x0725, + 0xb9d0, 0x1f2b, + 0xb9d1, 0x072a, + 0xb9d8, 0x1f2c, + 0xb9d9, 0x0732, + 0xb9db, 0x1f2d, + 0xb9dc, 0x0735, + 0xb9dd, 0x1f2e, + 0xb9de, 0x0737, + 0xb9df, 0x1f2f, + 0xb9e0, 0x0739, + 0xb9e1, 0x1f30, + 0xb9e2, 0x073b, + 0xb9e3, 0x1f31, + 0xb9e4, 0x073d, + 0xb9e6, 0x1f32, + 0xb9e7, 0x0740, + 0xb9e9, 0x1f33, + 0xb9ed, 0x0746, + 0xb9ee, 0x1f37, + 0xb9ef, 0x0748, + 0xb9f1, 0x1f38, + 0xb9f2, 0x074b, + 0xb9f3, 0x1f39, + 0xb9f6, 0x074f, + 0xb9f8, 0x1f3c, + 0xb9f9, 0x0752, + 0xb9fa, 0x1f3d, + 0xb9fb, 0x0754, + 0xb9fd, 0x1f3e, + 0xb9fe, 0x0757, + 0xbaa1, 0x0758, + 0xbaa7, 0x1f3f, + 0xbaa8, 0x075f, + 0xbaab, 0x1f40, + 0xbaac, 0x0763, + 0xbaba, 0x1f41, + 0xbabb, 0x0772, + 0xbac5, 0x1f42, + 0xbac6, 0x077d, + 0xbad2, 0x1f43, + 0xbad3, 0x078a, + 0xbad7, 0x1f44, + 0xbad9, 0x0790, + 0xbae4, 0x1f46, + 0xbae5, 0x079c, + 0xbae8, 0x1f47, + 0xbae9, 0x07a0, + 0xbaec, 0x1f48, + 0xbaed, 0x07a4, + 0xbaf3, 0x15e5, + 0xbaf4, 0x07ab, + 0xbaf8, 0x1f49, + 0xbaf9, 0x07b0, + 0xbba1, 0x07b6, + 0xbba4, 0x1f4a, + 0xbba5, 0x07ba, + 0xbba6, 0x1f4b, + 0xbba7, 0x07bc, + 0xbba9, 0x1f4c, + 0xbbab, 0x07c0, + 0xbbad, 0x1f4e, + 0xbbaf, 0x07c4, + 0xbbb0, 0x1f50, + 0xbbb1, 0x07c6, + 0xbbb3, 0x1f51, + 0xbbb4, 0x07c9, + 0xbbb5, 0x1f52, + 0xbbb8, 0x07cd, + 0xbbb9, 0x1f55, + 0xbbbb, 0x07d0, + 0xbbd1, 0x1f57, + 0xbbd2, 0x07e7, + 0xbbd3, 0x1f58, + 0xbbd5, 0x07ea, + 0xbbdf, 0x1f5a, + 0xbbe8, 0x07fd, + 0xbbeb, 0x1f63, + 0xbbec, 0x0801, + 0xbbf1, 0x1f64, + 0xbbf2, 0x0807, + 0xbbf5, 0x1f65, + 0xbbf8, 0x080d, + 0xbbfa, 0x1f68, + 0xbbfb, 0x0810, + 0xbbfd, 0x1f69, + 0xbbfe, 0x0813, + 0xbca1, 0x0814, + 0xbca2, 0x1f6a, + 0xbca3, 0x0816, + 0xbca5, 0x1f6b, + 0xbca7, 0x081a, + 0xbca8, 0x1f6d, + 0xbcaa, 0x081d, + 0xbcab, 0x1f6f, + 0xbcac, 0x081f, + 0xbcad, 0x1f70, + 0xbcae, 0x0821, + 0xbcb6, 0x1f71, + 0xbcb9, 0x082c, + 0xbcbb, 0x1f74, + 0xbcbc, 0x082f, + 0xbcc1, 0x1f75, + 0xbcc2, 0x0835, + 0xbcc3, 0x1f76, + 0xbcc4, 0x0837, + 0xbcc6, 0x1f77, + 0xbcc8, 0x083b, + 0xbcca, 0x1f79, + 0xbccb, 0x083e, + 0xbccc, 0x1f7a, + 0xbcce, 0x0841, + 0xbcd0, 0x1f7c, + 0xbcd1, 0x0844, + 0xbcd4, 0x1f7d, + 0xbcd7, 0x084a, + 0xbcd8, 0x1f80, + 0xbcd9, 0x084c, + 0xbcdb, 0x1f81, + 0xbcdc, 0x084f, + 0xbcdd, 0x1f82, + 0xbcde, 0x0851, + 0xbcdf, 0x1f83, + 0xbce2, 0x0855, + 0xbce3, 0x1f86, + 0xbce5, 0x0858, + 0xbce8, 0x1f88, + 0xbce9, 0x085c, + 0xbcea, 0x1f89, + 0xbced, 0x0860, + 0xbcef, 0x1f8c, + 0xbcf4, 0x0867, + 0xbcf6, 0x1f91, + 0xbcfd, 0x0870, + 0xbda1, 0x0872, + 0xbda2, 0x1f98, + 0xbda8, 0x0879, + 0xbdab, 0x1f9e, + 0xbdad, 0x087e, + 0xbdaf, 0x1fa0, + 0xbdb3, 0x0884, + 0xbdb4, 0x1fa4, + 0xbdb5, 0x0886, + 0xbdba, 0x1fa5, + 0xbdbb, 0x088c, + 0xbdbd, 0x1fa6, + 0xbdc0, 0x0891, + 0xbdc1, 0x1fa9, + 0xbdc5, 0x0896, + 0xbdc8, 0x1fad, + 0xbdcb, 0x089c, + 0xbdce, 0x1fb0, + 0xbdd0, 0x08a1, + 0xbdd7, 0x1fb2, + 0xbdd8, 0x08a9, + 0xbdda, 0x1fb3, + 0xbddb, 0x08ac, + 0xbde0, 0x1fb4, + 0xbde2, 0x08b3, + 0xbdeb, 0x1fb6, + 0xbdec, 0x08bd, + 0xbdf4, 0x1fb7, + 0xbdf9, 0x08ca, + 0xbdfd, 0x1fbc, + 0xbdfe, 0x08cf, + 0xbea1, 0x1fbd, + 0xbea3, 0x08d2, + 0xbea5, 0x1fbf, + 0xbea6, 0x08d5, + 0xbea8, 0x1fc0, + 0xbea9, 0x08d8, + 0xbeaa, 0x1fc1, + 0xbeab, 0x08da, + 0xbead, 0x1fc2, + 0xbeae, 0x08dd, + 0xbeb1, 0x1fc3, + 0xbeb2, 0x08e1, + 0xbeb5, 0x1fc4, + 0xbeb8, 0x08e7, + 0xbeba, 0x1fc7, + 0xbebb, 0x08ea, + 0xbec0, 0x1fc8, + 0xbec1, 0x08f0, + 0xbec9, 0x1fc9, + 0xbeca, 0x08f9, + 0xbed4, 0x1fca, + 0xbed5, 0x0904, + 0xbed9, 0x1fcb, + 0xbeda, 0x0909, + 0xbedd, 0x1fcc, + 0xbede, 0x090d, + 0xbee2, 0x1fcd, + 0xbee3, 0x0912, + 0xbee5, 0x1fce, + 0xbee6, 0x0915, + 0xbee7, 0x1fcf, + 0xbee8, 0x0917, + 0xbee9, 0x1fd0, + 0xbeea, 0x0919, + 0xbeee, 0x1fd1, + 0xbeef, 0x091e, + 0xbef5, 0x1fd2, + 0xbef6, 0x0925, + 0xbef7, 0x1fd3, + 0xbef9, 0x0928, + 0xbefb, 0x1fd5, + 0xbefd, 0x092c, + 0xbfa1, 0x092e, + 0xbfa5, 0x1fd7, + 0xbfa6, 0x0933, + 0xbfaa, 0x1fd8, + 0xbfab, 0x0938, + 0xbfad, 0x1fd9, + 0xbfae, 0x093b, + 0xbfc5, 0x1fda, + 0xbfc6, 0x0953, + 0xbfc7, 0x1fdb, + 0xbfc8, 0x0955, + 0xbfce, 0x1fdc, + 0xbfcf, 0x095c, + 0xbfd1, 0x1fdd, + 0xbfd3, 0x0960, + 0xbfd9, 0x1fdf, + 0xbfda, 0x0967, + 0xbfe2, 0x1fe0, + 0xbfe5, 0x0972, + 0xbfe9, 0x1fe3, + 0xbfea, 0x0977, + 0xbfeb, 0x1fe4, + 0xbfec, 0x0979, + 0xbfed, 0x1fe5, + 0xbfee, 0x097b, + 0xbff3, 0x1fe6, + 0xbff4, 0x0981, + 0xbff5, 0x1fe7, + 0xbff6, 0x0983, + 0xbff7, 0x1fe8, + 0xbff8, 0x0985, + 0xbff9, 0x1fe9, + 0xbffb, 0x0988, + 0xc0a1, 0x1feb, + 0xc0a2, 0x098d, + 0xc0a3, 0x1fec, + 0xc0a4, 0x098f, + 0xc0a9, 0x1fed, + 0xc0aa, 0x0995, + 0xc0ab, 0x1fee, + 0xc0ac, 0x0997, + 0xc0af, 0x1fef, + 0xc0b1, 0x099c, + 0xc0b3, 0x1ff1, + 0xc0b7, 0x09a2, + 0xc0b8, 0x1ff5, + 0xc0c5, 0x09b0, + 0xc0cc, 0x2002, + 0xc0ce, 0x09b9, + 0xc0d4, 0x2004, + 0xc0d5, 0x09c0, + 0xc0d6, 0x2005, + 0xc0d7, 0x09c2, + 0xc0d8, 0x2006, + 0xc0d9, 0x09c4, + 0xc0dd, 0x2007, + 0xc0de, 0x09c9, + 0xc0e0, 0x2008, + 0xc0e1, 0x09cc, + 0xc0e9, 0x2009, + 0xc0ea, 0x09d5, + 0xc0eb, 0x200a, + 0xc0ed, 0x09d8, + 0xc0ef, 0x200c, + 0xc0f2, 0x09dd, + 0xc0f6, 0x200f, + 0xc0fb, 0x09e6, + 0xc1a1, 0x09ea, + 0xc1a4, 0x2014, + 0xc1a6, 0x09ef, + 0xc1a9, 0x2016, + 0xc1ae, 0x09f7, + 0xc1af, 0x201b, + 0xc1b9, 0x0a02, + 0xc1bd, 0x2025, + 0xc1bf, 0x0a08, + 0xc1c2, 0x2027, + 0xc1c3, 0x0a0c, + 0xc1c6, 0x2028, + 0xc1c7, 0x0a10, + 0xc1c9, 0x2029, + 0xc1ca, 0x0a13, + 0xc1cd, 0x202a, + 0xc1ce, 0x0a17, + 0xc1d4, 0x202b, + 0xc1d5, 0x0a1e, + 0xc1d9, 0x202c, + 0xc1dc, 0x0a25, + 0xc1de, 0x202f, + 0xc1df, 0x0a28, + 0xc1e4, 0x2030, + 0xc1e6, 0x0a2f, + 0xc1e9, 0x2032, + 0xc1ea, 0x0a33, + 0xc1eb, 0x2033, + 0xc1ed, 0x0a36, + 0xc1f3, 0x2035, + 0xc1f4, 0x0a3d, + 0xc1f5, 0x2036, + 0xc1f6, 0x0a3f, + 0xc1fa, 0x2037, + 0xc1fe, 0x0a47, + 0xc2a1, 0x0a48, + 0xc2a2, 0x203b, + 0xc2a9, 0x0a50, + 0xc2ab, 0x2042, + 0xc2b4, 0x0a5b, + 0xc2b8, 0x204b, + 0xc2b9, 0x0a60, + 0xc2bc, 0x204c, + 0xc2be, 0x0a65, + 0xc2bf, 0x204e, + 0xc2c0, 0x0a67, + 0xc2c1, 0x204f, + 0xc2c2, 0x0a69, + 0xc2c5, 0x2050, + 0xc2c8, 0x0a6f, + 0xc2cb, 0x2053, + 0xc2d1, 0x0a78, + 0xc2d2, 0x2059, + 0xc2d3, 0x0a7a, + 0xc2d5, 0x205a, + 0xc2dd, 0x0a84, + 0xc2de, 0x2062, + 0xc2e3, 0x0a8a, + 0xc2e6, 0x2067, + 0xc2e9, 0x0a90, + 0xc2ea, 0x206a, + 0xc2ef, 0x0a96, + 0xc2f0, 0x206f, + 0xc2f1, 0x0a98, + 0xc2f2, 0x2070, + 0xc2f6, 0x0a9d, + 0xc2f7, 0x2074, + 0xc2fb, 0x0aa2, + 0xc3a1, 0x2078, + 0xc3a2, 0x0aa7, + 0xc3aa, 0x2079, + 0xc3ab, 0x0ab0, + 0xc3ad, 0x207a, + 0xc3ae, 0x0ab3, + 0xc3b3, 0x207b, + 0xc3b4, 0x1df9, + 0xc3b5, 0x0aba, + 0xc3be, 0x207c, + 0xc3bf, 0x0ac4, + 0xc3c5, 0x207d, + 0xc3c8, 0x0acd, + 0xc3cc, 0x2080, + 0xc3cd, 0x0ad2, + 0xc3ce, 0x2081, + 0xc3cf, 0x0ad4, + 0xc3d5, 0x2082, + 0xc3d7, 0x0adc, + 0xc3d9, 0x2084, + 0xc3da, 0x0adf, + 0xc3e0, 0x2085, + 0xc3e1, 0x0ae6, + 0xc3e5, 0x2086, + 0xc3e6, 0x0aeb, + 0xc3ed, 0x2087, + 0xc3ee, 0x0af3, + 0xc3f0, 0x2088, + 0xc3f1, 0x0af6, + 0xc3f5, 0x2089, + 0xc3f7, 0x0afc, + 0xc3f9, 0x208b, + 0xc3fb, 0x0b00, + 0xc3fd, 0x208d, + 0xc3fe, 0x0b03, + 0xc4a1, 0x0b04, + 0xc4b1, 0x208e, + 0xc4b2, 0x0b15, + 0xc4b6, 0x208f, + 0xc4b7, 0x0b1a, + 0xc4c6, 0x2090, + 0xc4c7, 0x0b2a, + 0xc4c9, 0x2091, + 0xc4ca, 0x0b2d, + 0xc4d1, 0x2092, + 0xc4d2, 0x0b35, + 0xc4d3, 0x2093, + 0xc4d7, 0x0b3a, + 0xc4d9, 0x2097, + 0xc4da, 0x0b3d, + 0xc4e2, 0x2098, + 0xc4e3, 0x0b46, + 0xc4e5, 0x2099, + 0xc4e6, 0x0b49, + 0xc4ec, 0x209a, + 0xc4ed, 0x0b50, + 0xc4f0, 0x209b, + 0xc4f2, 0x0b55, + 0xc4f4, 0x209d, + 0xc4f5, 0x0b58, + 0xc4f6, 0x209e, + 0xc4f9, 0x0b5c, + 0xc4fb, 0x20a1, + 0xc4fd, 0x0b60, + 0xc4fe, 0x20a3, + 0xc5a1, 0x20a4, + 0xc5a3, 0x0b64, + 0xc5a5, 0x20a6, + 0xc5aa, 0x0b6b, + 0xc5b1, 0x20ab, + 0xc5b2, 0x0b73, + 0xc5b5, 0x20ac, + 0xc5b6, 0x0b77, + 0xc5b7, 0x20ad, + 0xc5ba, 0x0b7b, + 0xc5bb, 0x20b0, + 0xc5bc, 0x0b7d, + 0xc5bd, 0x20b1, + 0xc5be, 0x0b7f, + 0xc5cc, 0x20b2, + 0xc5cd, 0x0b8e, + 0xc5d3, 0x20b3, + 0xc5d4, 0x0b95, + 0xc5e2, 0x20b4, + 0xc5e3, 0x0ba4, + 0xc5e7, 0x20b5, + 0xc5e8, 0x0ba9, + 0xc5f4, 0x20b6, + 0xc5f5, 0x0bb6, + 0xc6a1, 0x0bc0, + 0xc6ad, 0x20b7, + 0xc6af, 0x0bce, + 0xc6b5, 0x20b9, + 0xc6b7, 0x0bd6, + 0xc6bb, 0x20bb, + 0xc6bc, 0x0bdb, + 0xc6be, 0x20bc, + 0xc6bf, 0x0bde, + 0xc6c0, 0x20bd, + 0xc6c1, 0x0be0, + 0xc6c3, 0x20be, + 0xc6c5, 0x0be4, + 0xc6cb, 0x20c0, + 0xc6ce, 0x0bed, + 0xc6d3, 0x20c3, + 0xc6d4, 0x0bf3, + 0xc6d7, 0x20c4, + 0xc6d8, 0x0bf7, + 0xc6ea, 0x20c5, + 0xc6ec, 0x0c0b, + 0xc6ef, 0x20c7, + 0xc6f0, 0x0c0f, + 0xc6f1, 0x20c8, + 0xc6f2, 0x0c11, + 0xc6f4, 0x20c9, + 0xc6f5, 0x0c14, + 0xc6f8, 0x20ca, + 0xc6f9, 0x0c18, + 0xc6fd, 0x20cb, + 0xc6fe, 0x0c1d, + 0xc7a1, 0x0c1e, + 0xc7a3, 0x20cc, + 0xc7a4, 0x0c21, + 0xc7a5, 0x20cd, + 0xc7a7, 0x0c24, + 0xc7a8, 0x20cf, + 0xc7aa, 0x0c27, + 0xc7ab, 0x20d1, + 0xc7ac, 0x0c29, + 0xc7ae, 0x20d2, + 0xc7b0, 0x0c2d, + 0xc7b3, 0x20d4, + 0xc7b6, 0x0c33, + 0xc7b9, 0x20d7, + 0xc7bb, 0x0c38, + 0xc7bd, 0x20d9, + 0xc7bf, 0x0c3c, + 0xc7c0, 0x20db, + 0xc7c1, 0x0c3e, + 0xc7c2, 0x20dc, + 0xc7c3, 0x0c40, + 0xc7c5, 0x20dd, + 0xc7c6, 0x0c43, + 0xc7c7, 0x20de, + 0xc7c9, 0x0c46, + 0xc7cc, 0x20e0, + 0xc7cd, 0x0c4a, + 0xc7cf, 0x20e1, + 0xc7d0, 0x0c4d, + 0xc7d4, 0x20e2, + 0xc7d6, 0x0c53, + 0xc7d7, 0x20e4, + 0xc7d8, 0x0c55, + 0xc7de, 0x20e5, + 0xc7df, 0x0c5c, + 0xc7e1, 0x20e6, + 0xc7e4, 0x0c61, + 0xc7ea, 0x20e9, + 0xc7ef, 0x0c6c, + 0xc7f7, 0x20ee, + 0xc7f9, 0x0c76, + 0xc7fb, 0x20f0, + 0xc7fc, 0x0c79, + 0xc7fd, 0x20f1, + 0xc7fe, 0x0c7b, + 0xc8a1, 0x0c7c, + 0xc8a3, 0x20f2, + 0xc8a4, 0x0c7f, + 0xc8a7, 0x20f3, + 0xc8a9, 0x0c84, + 0xc8b0, 0x20f5, + 0xc8b1, 0x0c8c, + 0xc8b5, 0x20f6, + 0xc8b6, 0x0c91, + 0xc8b7, 0x20f7, + 0xc8b8, 0x0c93, + 0xc8c3, 0x20f8, + 0xc8c7, 0x0ca2, + 0xc8c8, 0x20fc, + 0xc8c9, 0x0ca4, + 0xc8cd, 0x20fd, + 0xc8ce, 0x0ca9, + 0xc8cf, 0x20fe, + 0xc8d0, 0x0cab, + 0xc8d2, 0x20ff, + 0xc8d3, 0x0cae, + 0xc8d9, 0x2100, + 0xc8da, 0x0cb5, + 0xc8de, 0x2101, + 0xc8df, 0x0cba, + 0xc8ed, 0x2102, + 0xc8ee, 0x0cc9, + 0xc8f1, 0x2103, + 0xc8f4, 0x0ccf, + 0xc8f7, 0x2106, + 0xc8f9, 0x0cd4, + 0xc8fa, 0x2108, + 0xc8fb, 0x0cd6, + 0xc8fc, 0x2109, + 0xc8fd, 0x0cd8, + 0xc9a1, 0x210a, + 0xc9a2, 0x0cdb, + 0xc9a5, 0x210b, + 0xc9a6, 0x0cdf, + 0xc9a7, 0x210c, + 0xc9a9, 0x0ce2, + 0xc9ac, 0x210e, + 0xc9ad, 0x0ce6, + 0xc9b1, 0x210f, + 0xc9b2, 0x0ceb, + 0xc9b4, 0x2110, + 0xc9b5, 0x0cee, + 0xc9b8, 0x2111, + 0xc9ba, 0x0cf3, + 0xc9c1, 0x2113, + 0xc9c3, 0x0cfc, + 0xc9c4, 0x2115, + 0xc9c5, 0x0cfe, + 0xc9c9, 0x2116, + 0xc9ca, 0x0d03, + 0xc9cb, 0x2117, + 0xc9cc, 0x0d05, + 0xc9cd, 0x2118, + 0xc9ce, 0x0d07, + 0xc9d5, 0x2119, + 0xc9d6, 0x0d0f, + 0xc9dc, 0x211a, + 0xc9dd, 0x0d16, + 0xc9de, 0x211b, + 0xc9df, 0x0d18, + 0xc9e1, 0x211c, + 0xc9e2, 0x0d1b, + 0xc9e3, 0x211d, + 0xc9e4, 0x0d1d, + 0xc9e5, 0x211e, + 0xc9e6, 0x0d1f, + 0xc9e8, 0x211f, + 0xc9e9, 0x0d22, + 0xc9f0, 0x2120, + 0xc9f1, 0x0d2a, + 0xc9f3, 0x2121, + 0xc9f5, 0x0d2e, + 0xc9f6, 0x2123, + 0xc9f7, 0x0d30, + 0xc9f8, 0x2124, + 0xc9fa, 0x0d33, + 0xc9fe, 0x2126, + 0xcaa1, 0x0d38, + 0xcaa4, 0x2127, + 0xcaa7, 0x0d3e, + 0xcaa8, 0x212a, + 0xcaa9, 0x0d40, + 0xcaaa, 0x212b, + 0xcaac, 0x0d43, + 0xcab1, 0x212d, + 0xcab2, 0x0d49, + 0xcab4, 0x212e, + 0xcab7, 0x0d4e, + 0xcabb, 0x2131, + 0xcabc, 0x0d53, + 0xcac6, 0x2132, + 0xcac7, 0x0d5e, + 0xcaca, 0x2133, + 0xcacb, 0x0d62, + 0xcacd, 0x2134, + 0xcacf, 0x0d66, + 0xcad3, 0x2136, + 0xcad5, 0x0d6c, + 0xcad9, 0x2138, + 0xcada, 0x0d71, + 0xcade, 0x2139, + 0xcadf, 0x0d76, + 0xcae0, 0x213a, + 0xcae1, 0x0d78, + 0xcae4, 0x213b, + 0xcae5, 0x0d7c, + 0xcae9, 0x213c, + 0xcaeb, 0x0d82, + 0xcaf4, 0x213e, + 0xcaf6, 0x0d8d, + 0xcaf7, 0x2140, + 0xcaf8, 0x0d8f, + 0xcafa, 0x2141, + 0xcafb, 0x0d92, + 0xcafd, 0x2142, + 0xcafe, 0x0d95, + 0xcba1, 0x0d96, + 0xcba7, 0x2143, + 0xcba8, 0x0d9d, + 0xcbab, 0x2144, + 0xcbac, 0x0da1, + 0xcbad, 0x2145, + 0xcbae, 0x0da3, + 0xcbb3, 0x2146, + 0xcbb4, 0x0da9, + 0xcbb5, 0x2147, + 0xcbb7, 0x0dac, + 0xcbb8, 0x2149, + 0xcbb9, 0x0dae, + 0xcbbf, 0x214a, + 0xcbc0, 0x0db5, + 0xcbc7, 0x214b, + 0xcbc8, 0x0dbd, + 0xcbc9, 0x214c, + 0xcbcd, 0x0dc2, + 0xcbcf, 0x2150, + 0xcbd1, 0x0dc6, + 0xcbd3, 0x2152, + 0xcbd4, 0x0dc9, + 0xcbd5, 0x2153, + 0xcbd6, 0x0dcb, + 0xcbdf, 0x2154, + 0xcbe1, 0x0dd6, + 0xcbe4, 0x2156, + 0xcbe5, 0x0dda, + 0xcbe6, 0x2157, + 0xcbe8, 0x0ddd, + 0xcbea, 0x2159, + 0xcbeb, 0x0de0, + 0xcbef, 0x215a, + 0xcbf1, 0x0de6, + 0xcbf5, 0x215c, + 0xcbf7, 0x0dec, + 0xcbf8, 0x215e, + 0xcbf9, 0x0dee, + 0xcca1, 0x215f, + 0xcca3, 0x0df6, + 0xcca8, 0x2161, + 0xcca9, 0x0dfc, + 0xccac, 0x2162, + 0xccad, 0x0e00, + 0xccaf, 0x2163, + 0xccb4, 0x0e07, + 0xccb7, 0x2168, + 0xccb9, 0x0e0c, + 0xccbe, 0x216a, + 0xccbf, 0x0e12, + 0xccc0, 0x216b, + 0xccc1, 0x0e14, + 0xcccc, 0x216c, + 0xcccd, 0x0e20, + 0xccce, 0x216d, + 0xcccf, 0x0e22, + 0xccd0, 0x216e, + 0xccd1, 0x0e24, + 0xccd6, 0x216f, + 0xccd7, 0x0e2a, + 0xccda, 0x2170, + 0xccdb, 0x0e2e, + 0xccdc, 0x2171, + 0xccdd, 0x0e30, + 0xcce0, 0x2172, + 0xcce1, 0x0e34, + 0xcce2, 0x2173, + 0xcce3, 0x0e36, + 0xcce5, 0x2174, + 0xcce6, 0x0e39, + 0xccf5, 0x2175, + 0xccf6, 0x0e49, + 0xccf9, 0x2176, + 0xccfb, 0x0e4e, + 0xccfc, 0x2178, + 0xcda1, 0x0e52, + 0xcdad, 0x217b, + 0xcdae, 0x0e5f, + 0xcdb3, 0x217c, + 0xcdb4, 0x0e65, + 0xcdb7, 0x217d, + 0xcdb8, 0x0e69, + 0xcdbc, 0x217e, + 0xcdbd, 0x0e6e, + 0xcdbf, 0x217f, + 0xcdc0, 0x0e71, + 0xcdc5, 0x2180, + 0xcdc6, 0x0e77, + 0xcdc7, 0x2181, + 0xcdc8, 0x0e79, + 0xcdd2, 0x2182, + 0xcdd3, 0x0e84, + 0xcdd4, 0x2183, + 0xcdd7, 0x0e88, + 0xcddd, 0x2186, + 0xcdde, 0x0e8f, + 0xcde0, 0x2187, + 0xcde1, 0x0e92, + 0xcde4, 0x2188, + 0xcde6, 0x0e97, + 0xcde7, 0x218a, + 0xcde8, 0x0e99, + 0xcdf2, 0x218b, + 0xcdf3, 0x0ea4, + 0xcdf8, 0x218c, + 0xcdf9, 0x0eaa, + 0xcea1, 0x0eb0, + 0xcea4, 0x218d, + 0xcea6, 0x0eb5, + 0xcea7, 0x218f, + 0xcea8, 0x0eb7, + 0xceaa, 0x2190, + 0xceae, 0x0ebd, + 0xceb0, 0x2194, + 0xceb2, 0x0ec1, + 0xceb3, 0x2196, + 0xceb4, 0x0ec3, + 0xcebd, 0x2197, + 0xcebe, 0x0ecd, + 0xcec0, 0x2198, + 0xcec1, 0x0ed0, + 0xcec5, 0x2199, + 0xcec7, 0x0ed6, + 0xcec8, 0x219b, + 0xcec9, 0x0ed8, + 0xceca, 0x219c, + 0xcecb, 0x0eda, + 0xcece, 0x219d, + 0xced2, 0x0ee1, + 0xced8, 0x21a1, + 0xcedb, 0x0eea, + 0xcedc, 0x21a4, + 0xcedd, 0x0eec, + 0xcede, 0x21a5, + 0xcee0, 0x0eef, + 0xceeb, 0x21a7, + 0xceec, 0x0efb, + 0xceed, 0x21a8, + 0xceee, 0x0efd, + 0xcef1, 0x21a9, + 0xcef2, 0x0f01, + 0xcef3, 0x21aa, + 0xcef4, 0x0f03, + 0xcefd, 0x21ab, + 0xcfa1, 0x0f0e, + 0xcfae, 0x21ad, + 0xcfaf, 0x0f1c, + 0xcfb0, 0x21ae, + 0xcfb1, 0x0f1e, + 0xcfb3, 0x21af, + 0xcfb4, 0x0f21, + 0xcfb7, 0x21b0, + 0xcfb9, 0x0f26, + 0xcfba, 0x21b2, + 0xcfbb, 0x0f28, + 0xcfbd, 0x21b3, + 0xcfbe, 0x0f2b, + 0xcfbf, 0x21b4, + 0xcfc2, 0x0f2f, + 0xcfc5, 0x21b7, + 0xcfc6, 0x0f33, + 0xcfc7, 0x21b8, + 0xcfc8, 0x0f35, + 0xcfca, 0x21b9, + 0xcfcc, 0x0f39, + 0xcfcd, 0x21bb, + 0xcfcf, 0x0f3c, + 0xcfd0, 0x21bd, + 0xcfd1, 0x0f3e, + 0xcfd4, 0x21be, + 0xcfd9, 0x0f46, + 0xcfda, 0x21c3, + 0xcfdb, 0x0f48, + 0xcfdc, 0x21c4, + 0xcfdd, 0x0f4a, + 0xcfdf, 0x21c5, + 0xcfe0, 0x0f4d, + 0xcfe2, 0x21c6, + 0xcfe3, 0x0f50, + 0xcfe7, 0x21c7, + 0xcfe8, 0x0f55, + 0xcfea, 0x21c8, + 0xcfeb, 0x0f58, + 0xcfec, 0x21c9, + 0xcfed, 0x0f5a, + 0xcfee, 0x21ca, + 0xcfef, 0x0f5c, + 0xcff4, 0x21cb, + 0xcff5, 0x0f62, + 0xcff9, 0x21cc, + 0xcffb, 0x0f68, + 0xcffe, 0x21ce, + 0xd0a1, 0x0f6c, + 0xd0a5, 0x21cf, + 0xd0a6, 0x0f71, + 0xd0ad, 0x21d0, + 0xd0af, 0x0f7a, + 0xd0b2, 0x21d2, + 0xd0b5, 0x0f80, + 0xd0ba, 0x21d5, + 0xd0bc, 0x0f87, + 0xd0bf, 0x21d7, + 0xd0c0, 0x0f8b, + 0xd0c6, 0x21d8, + 0xd0c7, 0x0f92, + 0xd0cb, 0x21d9, + 0xd0cc, 0x0f97, + 0xd0e2, 0x21da, + 0xd0e3, 0x0fae, + 0xd0e5, 0x21db, + 0xd0e6, 0x0fb1, + 0xd0eb, 0x21dc, + 0xd0ec, 0x0fb7, + 0xd0ed, 0x21dd, + 0xd0ee, 0x0fb9, + 0xd0f7, 0x21de, + 0xd0fa, 0x0fc5, + 0xd0fc, 0x21e1, + 0xd0fd, 0x0fc8, + 0xd1a1, 0x21e2, + 0xd1a3, 0x0fcc, + 0xd1a4, 0x21e4, + 0xd1a5, 0x0fce, + 0xd1a7, 0x21e5, + 0xd1a8, 0x0fd1, + 0xd1ab, 0x21e6, + 0xd1ac, 0x0fd5, + 0xd1af, 0x21e7, + 0xd1b2, 0x0fdb, + 0xd1b5, 0x21ea, + 0xd1b8, 0x0fe1, + 0xd1b9, 0x21ed, + 0xd1ba, 0x0fe3, + 0xd1bb, 0x21ee, + 0xd1bd, 0x0fe6, + 0xd1c6, 0x21f0, + 0xd1c9, 0x0ff2, + 0xd1cb, 0x21f3, + 0xd1cc, 0x0ff5, + 0xd1ce, 0x21f4, + 0xd1d0, 0x0ff9, + 0xd1d5, 0x21f6, + 0xd1d7, 0x1000, + 0xd1de, 0x21f8, + 0xd1df, 0x1008, + 0xd1e1, 0x21f9, + 0xd1e3, 0x100c, + 0xd1e8, 0x21fb, + 0xd1ea, 0x1013, + 0xd1ec, 0x21fd, + 0xd1ed, 0x1016, + 0xd1ee, 0x21fe, + 0xd1f0, 0x1019, + 0xd1f1, 0x2200, + 0xd1f2, 0x101b, + 0xd1f4, 0x2201, + 0xd1f5, 0x101e, + 0xd1f7, 0x2202, + 0xd1fa, 0x1023, + 0xd2a1, 0x1028, + 0xd2a2, 0x2205, + 0xd2a3, 0x102a, + 0xd2a5, 0x2206, + 0xd2a6, 0x102d, + 0xd2a9, 0x2207, + 0xd2aa, 0x1031, + 0xd2af, 0x2208, + 0xd2b0, 0x1037, + 0xd2b3, 0x2209, + 0xd2b4, 0x103b, + 0xd2b5, 0x220a, + 0xd2b7, 0x103e, + 0xd2bd, 0x220c, + 0xd2be, 0x1045, + 0xd2bf, 0x220d, + 0xd2c0, 0x1047, + 0xd2c3, 0x220e, + 0xd2c4, 0x104b, + 0xd2c5, 0x220f, + 0xd2c6, 0x104d, + 0xd2c7, 0x2210, + 0xd2c8, 0x104f, + 0xd2cf, 0x2211, + 0xd2d0, 0x1057, + 0xd2d5, 0x2212, + 0xd2d6, 0x105d, + 0xd2da, 0x2213, + 0xd2db, 0x1062, + 0xd2e4, 0x2214, + 0xd2e6, 0x106d, + 0xd2e8, 0x2216, + 0xd2ec, 0x1073, + 0xd2ef, 0x221a, + 0xd2f0, 0x1077, + 0xd2f1, 0x221b, + 0xd2f2, 0x1079, + 0xd2f5, 0x221c, + 0xd2f6, 0x107d, + 0xd2f8, 0x221d, + 0xd2f9, 0x1080, + 0xd2fb, 0x221e, + 0xd2fc, 0x1083, + 0xd2fe, 0x221f, + 0xd3a1, 0x1086, + 0xd3a3, 0x2220, + 0xd3ad, 0x1092, + 0xd3ae, 0x222a, + 0xd3af, 0x1094, + 0xd3b1, 0x222b, + 0xd3b2, 0x1097, + 0xd3b4, 0x222c, + 0xd3b7, 0x109c, + 0xd3b8, 0x222f, + 0xd3b9, 0x109e, + 0xd3bb, 0x2230, + 0xd3bc, 0x10a1, + 0xd3c5, 0x2231, + 0xd3c6, 0x10ab, + 0xd3c7, 0x2232, + 0xd3c8, 0x10ad, + 0xd3ca, 0x2233, + 0xd3cd, 0x10b2, + 0xd3d5, 0x2236, + 0xd3d6, 0x10bb, + 0xd3df, 0x2237, + 0xd3e1, 0x10c6, + 0xd3e3, 0x2239, + 0xd3e4, 0x10c9, + 0xd3e6, 0x223a, + 0xd3e7, 0x10cc, + 0xd3eb, 0x223b, + 0xd3ed, 0x10d2, + 0xd3ef, 0x223d, + 0xd3f0, 0x10d5, + 0xd3f4, 0x223e, + 0xd3f5, 0x10da, + 0xd3fc, 0x223f, + 0xd3fd, 0x10e2, + 0xd3fe, 0x2240, + 0xd4a1, 0x10e4, + 0xd4a4, 0x2241, + 0xd4a5, 0x10e8, + 0xd4a6, 0x2242, + 0xd4a9, 0x10ec, + 0xd4af, 0x2245, + 0xd4b3, 0x10f6, + 0xd4b5, 0x2249, + 0xd4b7, 0x10fa, + 0xd4b8, 0x224b, + 0xd4b9, 0x10fc, + 0xd4bc, 0x224c, + 0xd4bd, 0x1100, + 0xd4be, 0x224d, + 0xd4c0, 0x1103, + 0xd4c4, 0x224f, + 0xd4c5, 0x1108, + 0xd4c6, 0x2250, + 0xd4c8, 0x110b, + 0xd4c9, 0x2252, + 0xd4ca, 0x110d, + 0xd4cb, 0x2253, + 0xd4cf, 0x1112, + 0xd4d3, 0x2257, + 0xd4d4, 0x1117, + 0xd4d8, 0x2258, + 0xd4d9, 0x111c, + 0xd4dc, 0x2259, + 0xd4e1, 0x1124, + 0xd4e4, 0x225e, + 0xd4e5, 0x1128, + 0xd4e6, 0x225f, + 0xd4e7, 0x112a, + 0xd4ee, 0x2260, + 0xd4ef, 0x1132, + 0xd4f0, 0x2261, + 0xd4f5, 0x1138, + 0xd4f9, 0x2266, + 0xd4fa, 0x113d, + 0xd4fe, 0x2267, + 0xd5a1, 0x2268, + 0xd5a3, 0x1144, + 0xd5a9, 0x226a, + 0xd5aa, 0x114b, + 0xd5ab, 0x226b, + 0xd5ac, 0x114d, + 0xd5ae, 0x226c, + 0xd5af, 0x1150, + 0xd5b1, 0x226d, + 0xd5b2, 0x1153, + 0xd5b5, 0x226e, + 0xd5b9, 0x115a, + 0xd5bb, 0x2272, + 0xd5bc, 0x115d, + 0xd5bd, 0x2273, + 0xd5be, 0x115f, + 0xd5c0, 0x2274, + 0xd5c1, 0x1162, + 0xd5c5, 0x2275, + 0xd5c6, 0x1167, + 0xd5c7, 0x2276, + 0xd5c8, 0x1169, + 0xd5ca, 0x2277, + 0xd5cc, 0x116d, + 0xd5cd, 0x2279, + 0xd5ce, 0x116f, + 0xd5d4, 0x227a, + 0xd5d5, 0x1176, + 0xd5dd, 0x227b, + 0xd5df, 0x1180, + 0xd5e0, 0x227d, + 0xd5e1, 0x1182, + 0xd5e2, 0x227e, + 0xd5e3, 0x1184, + 0xd5ea, 0x227f, + 0xd5ed, 0x118e, + 0xd5ef, 0x2282, + 0xd5f0, 0x1191, + 0xd5f2, 0x2283, + 0xd5f4, 0x1195, + 0xd5f7, 0x15eb, + 0xd5f8, 0x1199, + 0xd6a1, 0x2285, + 0xd6a5, 0x11a4, + 0xd6af, 0x2289, + 0xd6b1, 0x11b0, + 0xd6b4, 0x228b, + 0xd6b5, 0x11b4, + 0xd6bb, 0x228c, + 0xd6bc, 0x11bb, + 0xd6bd, 0x228d, + 0xd6be, 0x11bd, + 0xd6bf, 0x228e, + 0xd6c1, 0x11c0, + 0xd6c4, 0x2290, + 0xd6c5, 0x11c4, + 0xd6ca, 0x2291, + 0xd6cb, 0x11ca, + 0xd6cd, 0x2292, + 0xd6ce, 0x11cd, + 0xd6d3, 0x2293, + 0xd6d4, 0x11d3, + 0xd6d5, 0x2294, + 0xd6d8, 0x11d7, + 0xd6da, 0x2297, + 0xd6db, 0x11da, + 0xd6df, 0x2298, + 0xd6e0, 0x11df, + 0xd6e1, 0x2299, + 0xd6e2, 0x11e1, + 0xd6e5, 0x229a, + 0xd6e6, 0x11e5, + 0xd6e7, 0x229b, + 0xd6e9, 0x11e8, + 0xd6ee, 0x229d, + 0xd6f0, 0x11ef, + 0xd6f2, 0x229f, + 0xd6f3, 0x11f2, + 0xd6f5, 0x22a0, + 0xd6f7, 0x11f6, + 0xd6fc, 0x22a2, + 0xd7a1, 0x11fe, + 0xd7a4, 0x22a5, + 0xd7a5, 0x1202, + 0xd7a8, 0x22a6, + 0xd7ab, 0x1208, + 0xd7ac, 0x22a9, + 0xd7ad, 0x120a, + 0xd7ae, 0x22aa, + 0xd7b2, 0x120f, + 0xd7b3, 0x22ae, + 0xd7b5, 0x1212, + 0xd7b6, 0x22b0, + 0xd7b7, 0x1214, + 0xd7b8, 0x22b1, + 0xd7bd, 0x121a, + 0xd7c7, 0x22b6, + 0xd7c8, 0x1225, + 0xd7ca, 0x22b7, + 0xd7cb, 0x1228, + 0xd7d5, 0x22b8, + 0xd7d6, 0x1233, + 0xd7db, 0x22b9, + 0xd7df, 0x123c, + 0xd7e7, 0x22bd, + 0xd7e8, 0x1245, + 0xd7e9, 0x22be, + 0xd7eb, 0x1248, + 0xd8a1, 0x1257, + 0xd8c4, 0x22c0, + 0xd8c5, 0x127b, + 0xd8c7, 0x22c1, + 0xd8c8, 0x127e, + 0xd8c9, 0x22c2, + 0xd8ca, 0x1280, + 0xd8cc, 0x22c3, + 0xd8ce, 0x1284, + 0xd8d0, 0x22c5, + 0xd8d2, 0x1288, + 0xd8d3, 0x22c7, + 0xd8d4, 0x128a, + 0xd8d9, 0x22c8, + 0xd8da, 0x1290, + 0xd8db, 0x22c9, + 0xd8dd, 0x1293, + 0xd8f1, 0x22cb, + 0xd8f2, 0x12a8, + 0xd8f6, 0x22cc, + 0xd8f8, 0x12ae, + 0xd9a1, 0x12b5, + 0xd9ad, 0x22ce, + 0xd9ae, 0x12c2, + 0xd9af, 0x22cf, + 0xd9b0, 0x12c4, + 0xd9b1, 0x22d0, + 0xd9b4, 0x12c8, + 0xd9c7, 0x22d3, + 0xd9c8, 0x12dc, + 0xd9cd, 0x22d4, + 0xd9d1, 0x12e5, + 0xd9dd, 0x22d8, + 0xd9de, 0x12f2, + 0xd9e1, 0x22d9, + 0xd9e2, 0x12f6, + 0xd9e4, 0x22da, + 0xd9e5, 0x12f9, + 0xd9e6, 0x22db, + 0xd9e7, 0x12fb, + 0xd9ec, 0x22dc, + 0xd9ed, 0x1301, + 0xd9f4, 0x22dd, + 0xd9f6, 0x130a, + 0xdaa1, 0x1313, + 0xdaa5, 0x22df, + 0xdae0, 0x1352, + 0xdaea, 0x231a, + 0xdaeb, 0x135d, + 0xdaf7, 0x231b, + 0xdaf8, 0x136a, + 0xdaf9, 0x231c, + 0xdafa, 0x136c, + 0xdafe, 0x231d, + 0xdba1, 0x1371, + 0xdba3, 0x231e, + 0xdba4, 0x1374, + 0xdba6, 0x231f, + 0xdba7, 0x1377, + 0xdba9, 0x2320, + 0xdbab, 0x137b, + 0xdbbb, 0x2322, + 0xdbbc, 0x138c, + 0xdbbd, 0x2323, + 0xdbbe, 0x138e, + 0xdbcf, 0x2324, + 0xdbd0, 0x13a0, + 0xdbd1, 0x2325, + 0xdbd2, 0x13a2, + 0xdbdb, 0x2326, + 0xdbdc, 0x13ac, + 0xdbde, 0x2327, + 0xdbdf, 0x13af, + 0xdbe2, 0x2328, + 0xdbe3, 0x13b3, + 0xdbe4, 0x2329, + 0xdbe5, 0x13b5, + 0xdbeb, 0x232a, + 0xdbec, 0x13bc, + 0xdbee, 0x232b, + 0xdbef, 0x13bf, + 0xdbf1, 0x232c, + 0xdbf2, 0x13c2, + 0xdbf5, 0x232d, + 0xdbf8, 0x13c8, + 0xdca1, 0x13cf, + 0xdcbc, 0x2330, + 0xdcbd, 0x13eb, + 0xdcbf, 0x2331, + 0xdcc0, 0x13ee, + 0xdcc2, 0x2332, + 0xdcc3, 0x13f1, + 0xdcc8, 0x2333, + 0xdccb, 0x13f9, + 0xdcd1, 0x2336, + 0xdcd2, 0x1400, + 0xdcd7, 0x2337, + 0xdcd8, 0x1406, + 0xdce0, 0x2338, + 0xdce1, 0x140f, + 0xdce3, 0x2339, + 0xdce5, 0x1413, + 0xdce9, 0x233b, + 0xdceb, 0x1419, + 0xdcf1, 0x233d, + 0xdcf2, 0x1420, + 0xdcf6, 0x233e, + 0xdcf7, 0x1425, + 0xdcf9, 0x233f, + 0xdcfa, 0x1428, + 0xdcfd, 0x2340, + 0xdda1, 0x2342, + 0xdda2, 0x142e, + 0xdda3, 0x2343, + 0xdda8, 0x1434, + 0xddaa, 0x2348, + 0xddac, 0x1438, + 0xddb2, 0x234a, + 0xddb3, 0x143f, + 0xddb5, 0x234b, + 0xddb6, 0x1442, + 0xddba, 0x234c, + 0xddbc, 0x1448, + 0xddd3, 0x234e, + 0xddd4, 0x1460, + 0xdddb, 0x234f, + 0xdddc, 0x1468, + 0xddde, 0x2350, + 0xdddf, 0x146b, + 0xdde4, 0x2351, + 0xdde5, 0x1471, + 0xddeb, 0x2352, + 0xddec, 0x1478, + 0xddf1, 0x2353, + 0xddf2, 0x147e, + 0xddf6, 0x2354, + 0xddf8, 0x1484, + 0xddfc, 0x2356, + 0xddfd, 0x1489, + 0xddfe, 0x2357, + 0xdea1, 0x148b, + 0xdead, 0x2358, + 0xdeae, 0x1498, + 0xdeb4, 0x2359, + 0xdeb5, 0x149f, + 0xdeba, 0x235a, + 0xdebb, 0x14a5, + 0xdec6, 0x235b, + 0xdec7, 0x14b1, + 0xdecf, 0x235c, + 0xded0, 0x14ba, + 0xded1, 0x235d, + 0xded3, 0x14bd, + 0xded8, 0x235f, + 0xded9, 0x14c3, + 0xdee2, 0x2360, + 0xdee3, 0x14cd, + 0xdee8, 0x2361, + 0xdee9, 0x14d3, + 0xdeec, 0x2362, + 0xdeed, 0x14d7, + 0xdef3, 0x2363, + 0xdef4, 0x14de, + 0xdefc, 0x2364, + 0xdefd, 0x14e7, + 0xdfa1, 0x14e9, + 0xdfa2, 0x2365, + 0xdfa4, 0x14ec, + 0xdfa5, 0x2367, + 0xdfa6, 0x14ee, + 0xdfb4, 0x2368, + 0xdfb5, 0x14fd, + 0xdfbc, 0x2369, + 0xdfbe, 0x1506, + 0xdfbf, 0x236b, + 0xdfc0, 0x1508, + 0xdfc2, 0x236c, + 0xdfc4, 0x150c, + 0xdfcc, 0x236e, + 0xdfcd, 0x1515, + 0xdfd0, 0x236f, + 0xdfd1, 0x1519, + 0xdfd5, 0x2370, + 0xdfd6, 0x151e, + 0xdfd8, 0x2371, + 0xdfda, 0x1522, + 0xdfdc, 0x2373, + 0xdfdd, 0x1525, + 0xdfe0, 0x2374, + 0xdfe1, 0x1529, + 0xdfe2, 0x2375, + 0xdfe3, 0x152b, + 0xdfe6, 0x2376, + 0xdfe7, 0x152f, + 0xdfe9, 0x2377, + 0xdfea, 0x1532, + 0xdfeb, 0x2378, + 0xdfec, 0x1534, + 0xdfef, 0x2379, + 0xdff0, 0x1538, + 0xdff5, 0x237a, + 0xdff6, 0x153e, + 0xdff9, 0x237b, + 0xdffa, 0x1542, + 0xe0a1, 0x1547, + 0xe0b6, 0x237c, + 0xe0b8, 0x155e, + 0xe0bf, 0x237e, + 0xe0c0, 0x1566, + 0xe0c8, 0x237f, + 0xe0c9, 0x156f, + 0xe0ce, 0x2380, + 0xe0cf, 0x1575, + 0xe0d3, 0x2381, + 0xe0d4, 0x157a, + 0xe0e0, 0x2382, + 0xe0e1, 0x1587, + 0xe0f0, 0x2383, + 0xe0f1, 0x1597, + 0xe0f8, 0x2384, + 0xe0f9, 0x159f, + 0xe0fc, 0x2385, + 0xe1a1, 0x15a5, + 0xe1ab, 0x2388, + 0xe1ac, 0x15b0, + 0xe1ad, 0x2389, + 0xe1ae, 0x15b2, + 0xe1b0, 0x238a, + 0xe1b1, 0x15b5, + 0xe1b4, 0x238b, + 0xe1b5, 0x15b9, + 0xe1bb, 0x238c, + 0xe1bc, 0x15c0, + 0xe1bd, 0x238d, + 0xe1be, 0x15c2, + 0xe1c0, 0x238e, + 0xe1c2, 0x15c6, + 0xe1c9, 0x2390, + 0xe1ca, 0x15ce, + 0xe1d0, 0x2391, + 0xe1d1, 0x15d5, + 0xe1db, 0x2392, + 0xe1dc, 0x15e0, + 0xe1e1, 0x07aa, + 0xe1e2, 0x2393, + 0xe1e3, 0x15e7, + 0xe1e7, 0x1198, + 0xe1e8, 0x15ec, + 0xe1ee, 0x2394, + 0xe1f0, 0x15f4, + 0xe1f6, 0x2396, + 0xe1f7, 0x15fb, + 0xe1f8, 0x2397, + 0xe1f9, 0x15fd, + 0xe1fd, 0x2398, + 0xe1fe, 0x1602, + 0xe2a1, 0x1603, + 0xe2a4, 0x2399, + 0xe2a5, 0x1607, + 0xe2a8, 0x239a, + 0xe2a9, 0x160b, + 0xe2bb, 0x239b, + 0xe2c5, 0x10c5, + 0xe2c6, 0x23a5, + 0xe2cf, 0x1631, + 0xe2d0, 0x23ae, + 0xe2d1, 0x1633, + 0xe2d9, 0x23af, + 0xe2da, 0x163c, + 0xe2e3, 0x23b0, + 0xe2e5, 0x1647, + 0xe2e6, 0x23b2, + 0xe2e7, 0x1649, + 0xe2e9, 0x23b3, + 0xe2ec, 0x164e, + 0xe2f8, 0x23b6, + 0xe2f9, 0x165b, + 0xe2fa, 0x23b7, + 0xe2fe, 0x1660, + 0xe3a1, 0x1661, + 0xe3a2, 0x23bb, + 0xe3a3, 0x1663, + 0xe3a5, 0x23bc, + 0xe3a6, 0x1666, + 0xe3ab, 0x23bd, + 0xe3ac, 0x166c, + 0xe3b4, 0x23be, + 0xe3b5, 0x1675, + 0xe3c5, 0x23bf, + 0xe3dc, 0x169c, + 0xe3e3, 0x23d6, + 0xe3e4, 0x16a4, + 0xe3ed, 0x23d7, + 0xe3ee, 0x16ae, + 0xe3f1, 0x23d8, + 0xe3f3, 0x16b3, + 0xe3f8, 0x23da, + 0xe3f9, 0x16b9, + 0xe3fe, 0x23db, + 0xe4a1, 0x16bf, + 0xe4a4, 0x23dc, + 0xe4a6, 0x16c4, + 0xe4ab, 0x23de, + 0xe4ac, 0x16ca, + 0xe4af, 0x23df, + 0xe4b2, 0x16d0, + 0xe4b5, 0x23e2, + 0xe4b7, 0x16d5, + 0xe4c2, 0x23e4, + 0xe4c3, 0x16e1, + 0xe4c5, 0x23e5, + 0xe4c6, 0x16e4, + 0xe4c9, 0x23e6, + 0xe4ca, 0x16e8, + 0xe4d9, 0x23e7, + 0xe4da, 0x16f8, + 0xe4dc, 0x23e8, + 0xe4dd, 0x16fb, + 0xe4de, 0x23e9, + 0xe4df, 0x16fd, + 0xe4e4, 0x23ea, + 0xe4e5, 0x1703, + 0xe4eb, 0x23eb, + 0xe4ed, 0x170b, + 0xe4f2, 0x23ed, + 0xe4f3, 0x1711, + 0xe4fe, 0x23ee, + 0xe5a1, 0x171d, + 0xe5b0, 0x23ef, + 0xe5b1, 0x172d, + 0xe5b9, 0x23f0, + 0xe5ba, 0x1736, + 0xe5c7, 0x23f1, + 0xe5c8, 0x1744, + 0xe5c9, 0x23f2, + 0xe5ca, 0x1746, + 0xe5ce, 0x23f3, + 0xe5cf, 0x174b, + 0xe5f0, 0x23f4, + 0xe5f1, 0x176d, + 0xe5f2, 0x23f5, + 0xe5f3, 0x176f, + 0xe5fc, 0x23f6, + 0xe5fe, 0x177a, + 0xe6a1, 0x177b, + 0xe6a3, 0x23f8, + 0xe6a4, 0x177e, + 0xe6ab, 0x23f9, + 0xe6ad, 0x1787, + 0xe6ae, 0x23fb, + 0xe6af, 0x1789, + 0xe6b4, 0x23fc, + 0xe6b6, 0x1790, + 0xe6bf, 0x23fe, + 0xe6c0, 0x179a, + 0xe6c8, 0x23ff, + 0xe6ca, 0x17a4, + 0xe6cd, 0x2401, + 0xe6ce, 0x17a8, + 0xe6e0, 0x2402, + 0xe7a1, 0x2421, + 0xe7db, 0x1813, + 0xe7e1, 0x245b, + 0xe7e3, 0x181b, + 0xe7e7, 0x245d, + 0xe7e8, 0x1820, + 0xe7ef, 0x245e, + 0xe7f0, 0x1828, + 0xe7f4, 0x245f, + 0xe7f7, 0x182f, + 0xe8a1, 0x1837, + 0xe8a8, 0x2462, + 0xe8a9, 0x183f, + 0xe8ac, 0x2463, + 0xe8ad, 0x1843, + 0xe8b6, 0x2464, + 0xe8b7, 0x184d, + 0xe8b8, 0x2465, + 0xe8bb, 0x1851, + 0xe8bf, 0x2468, + 0xe8c1, 0x1857, + 0xe8c5, 0x246a, + 0xe8c6, 0x185c, + 0xe8c7, 0x246b, + 0xe8ca, 0x1860, + 0xe8ce, 0x246e, + 0xe8cf, 0x1865, + 0xe8d0, 0x246f, + 0xe8d1, 0x1867, + 0xe8d3, 0x2470, + 0xe8d4, 0x186a, + 0xe8dd, 0x2471, + 0xe8de, 0x1874, + 0xe8df, 0x2472, + 0xe8e0, 0x1876, + 0xe8e2, 0x2473, + 0xe8e4, 0x187a, + 0xe8e5, 0x2475, + 0xe8e6, 0x187c, + 0xe8e7, 0x2476, + 0xe8e8, 0x187e, + 0xe8eb, 0x2477, + 0xe8ec, 0x1882, + 0xe8ed, 0x2478, + 0xe8ee, 0x1884, + 0xe8ef, 0x2479, + 0xe8f0, 0x1886, + 0xe8f9, 0x247a, + 0xe8fa, 0x1890, + 0xe8fc, 0x247b, + 0xe8fe, 0x1894, + 0xe9a1, 0x247d, + 0xe9a2, 0x1896, + 0xe9ad, 0x247e, + 0xe9ae, 0x18a2, + 0xe9b4, 0x247f, + 0xe9b6, 0x18aa, + 0xe9b7, 0x2481, + 0xe9b8, 0x18ac, + 0xe9c4, 0x2482, + 0xe9c5, 0x18b9, + 0xe9c6, 0x2483, + 0xe9c7, 0x18bb, + 0xe9c9, 0x2484, + 0xe9ca, 0x18be, + 0xe9d6, 0x2485, + 0xe9d7, 0x18cb, + 0xe9da, 0x2486, + 0xe9db, 0x18cf, + 0xe9e4, 0x2487, + 0xe9e5, 0x18d9, + 0xe9e6, 0x2488, + 0xe9e8, 0x18dc, + 0xe9e9, 0x248a, + 0xe9ea, 0x18de, + 0xe9eb, 0x248b, + 0xe9ec, 0x18e0, + 0xe9ed, 0x248c, + 0xeaa1, 0x249e, + 0xeaa6, 0x18f8, + 0xeaa7, 0x24a3, + 0xeaa9, 0x18fb, + 0xeab1, 0x24a5, + 0xeab2, 0x1904, + 0xeabc, 0x24a6, + 0xeabd, 0x190f, + 0xeaca, 0x24a7, + 0xeacb, 0x191d, + 0xeacd, 0x24a8, + 0xeace, 0x1920, + 0xead3, 0x24a9, + 0xead4, 0x1926, + 0xeada, 0x24aa, + 0xeaf0, 0x1942, + 0xeba1, 0x1951, + 0xeba7, 0x24c0, + 0xeba8, 0x1958, + 0xebaa, 0x24c1, + 0xebab, 0x195b, + 0xebb2, 0x24c2, + 0xebb3, 0x1963, + 0xebb9, 0x24c3, + 0xebba, 0x196a, + 0xebca, 0x24c4, + 0xebcc, 0x197c, + 0xebcd, 0x24c6, + 0xebce, 0x197e, + 0xebd6, 0x24c7, + 0xebd7, 0x1987, + 0xebda, 0x24c8, + 0xebdb, 0x198b, + 0xebe1, 0x24c9, + 0xebe2, 0x1992, + 0xebf7, 0x24ca, + 0xebf8, 0x19a8, + 0xeca1, 0x19af, + 0xeca3, 0x24cb, + 0xeca4, 0x19b2, + 0xeca9, 0x24cc, + 0xecaf, 0x19bd, + 0xecb1, 0x24d2, + 0xecb2, 0x19c0, + 0xecb4, 0x24d3, + 0xecb6, 0x19c4, + 0xecbe, 0x24d5, + 0xecc0, 0x19ce, + 0xecc1, 0x24d7, + 0xecc2, 0x19d0, + 0xecc7, 0x24d8, + 0xecc8, 0x19d6, + 0xeccb, 0x24d9, + 0xeccc, 0x19da, + 0xece2, 0x24da, + 0xece3, 0x19f1, + 0xecf2, 0x24db, + 0xecf3, 0x1a01, + 0xecf5, 0x24dc, + 0xecf6, 0x1a04, + 0xecf8, 0x24dd, + 0xecf9, 0x1a07, + 0xeda1, 0x24de, + 0xeda2, 0x1a0e, + 0xeda8, 0x24df, + 0xeda9, 0x1a15, + 0xedaf, 0x24e0, + 0xedb1, 0x1a1d, + 0xedb4, 0x24e2, + 0xedb5, 0x1a21, + 0xedb6, 0x24e3, + 0xedb7, 0x1a23, + 0xedb8, 0x24e4, + 0xedb9, 0x1a25, + 0xedba, 0x24e5, + 0xedbb, 0x1a27, + 0xedbf, 0x24e6, + 0xedc0, 0x1a2c, + 0xedc2, 0x24e7, + 0xedc4, 0x1a30, + 0xedcc, 0x24e9, + 0xedce, 0x1a3a, + 0xedd3, 0x24eb, + 0xedd4, 0x1a40, + 0xedd7, 0x24ec, + 0xedd8, 0x1a44, + 0xede8, 0x24ed, + 0xede9, 0x1a55, + 0xedee, 0x24ee, + 0xedef, 0x1a5b, + 0xedf9, 0x24ef, + 0xedfb, 0x1a67, + 0xeea1, 0x1a6b, + 0xeebc, 0x24f1, + 0xeebd, 0x1a87, + 0xeebf, 0x24f2, + 0xeec0, 0x1a8a, + 0xeec4, 0x24f3, + 0xefa1, 0x252e, + 0xeff2, 0x1b1a, + 0xf0a1, 0x1b27, + 0xf0a3, 0x257f, + 0xf0a4, 0x1b2a, + 0xf0af, 0x2580, + 0xf0da, 0x1b60, + 0xf0dc, 0x25ab, + 0xf0de, 0x1b64, + 0xf0df, 0x25ad, + 0xf0e0, 0x1b66, + 0xf0e9, 0x25ae, + 0xf0ea, 0x1b70, + 0xf0ec, 0x25af, + 0xf0ed, 0x1b73, + 0xf0ef, 0x25b0, + 0xf0f0, 0x1b76, + 0xf0f7, 0x25b1, + 0xf0f8, 0x1b7e, + 0xf0f9, 0x25b2, + 0xf0fa, 0x1b80, + 0xf0fc, 0x25b3, + 0xf0fd, 0x1b83, + 0xf1a1, 0x1b85, + 0xf1a8, 0x25b4, + 0xf1a9, 0x1b8d, + 0xf1ab, 0x25b5, + 0xf1ac, 0x1b90, + 0xf1ae, 0x25b6, + 0xf1af, 0x1b93, + 0xf1b2, 0x25b7, + 0xf1b3, 0x1b97, + 0xf1bc, 0x25b8, + 0xf1bd, 0x1ba1, + 0xf1c0, 0x25b9, + 0xf1c1, 0x1ba5, + 0xf1c9, 0x25ba, + 0xf1ca, 0x1bae, + 0xf1cd, 0x25bb, + 0xf1ce, 0x1bb2, + 0xf1cf, 0x25bc, + 0xf1d1, 0x1bb5, + 0xf1da, 0x25be, + 0xf1db, 0x1bbf, + 0xf1dc, 0x25bf, + 0xf1dd, 0x1bc1, + 0xf1e4, 0x25c0, + 0xf1e5, 0x1bc9, + 0xf1ec, 0x25c1, + 0xf1ed, 0x1bd1, + 0xf1ef, 0x25c2, + 0xf1f0, 0x1bd4, + 0xf1f7, 0x25c3, + 0xf1f8, 0x1bdc, + 0xf1f9, 0x25c4, + 0xf1fa, 0x1bde, + 0xf1fc, 0x25c5, + 0xf2a1, 0x25c8, + 0xf2ae, 0x1bf0, + 0xf2b1, 0x25d5, + 0xf2b3, 0x1bf5, + 0xf2b9, 0x25d7, + 0xf2ba, 0x1bfc, + 0xf2c3, 0x25d8, + 0xf2c4, 0x1c06, + 0xf2c9, 0x25d9, + 0xf2ca, 0x1c0c, + 0xf2cc, 0x25da, + 0xf2ce, 0x1c10, + 0xf2cf, 0x25dc, + 0xf2d0, 0x1c12, + 0xf2d3, 0x25dd, + 0xf2d4, 0x1c16, + 0xf2e5, 0x25de, + 0xf2e6, 0x1c28, + 0xf2ee, 0x25df, + 0xf2ef, 0x1c31, + 0xf2f7, 0x25e0, + 0xf2f8, 0x1c3a, + 0xf2fd, 0x25e1, + 0xf2fe, 0x1c40, + 0xf3a1, 0x1c41, + 0xf3bf, 0x25e2, + 0xf3c0, 0x1c60, + 0xf3c6, 0x25e3, + 0xf3c7, 0x1c67, + 0xf3c8, 0x25e4, + 0xf3c9, 0x1c69, + 0xf3d6, 0x25e5, + 0xf3d7, 0x1c77, + 0xf3d9, 0x25e6, + 0xf3da, 0x1c7a, + 0xf3e5, 0x25e7, + 0xf3e7, 0x1c87, + 0xf3ea, 0x25e9, + 0xf3eb, 0x1c8b, + 0xf3ec, 0x25ea, + 0xf3ed, 0x1c8d, + 0xf3ef, 0x25eb, + 0xf3f0, 0x1c90, + 0xf3f1, 0x25ec, + 0xf3f2, 0x1c92, + 0xf3fd, 0x25ed, + 0xf3fe, 0x1c9e, + 0xf4a1, 0x1c9f, + 0xf4a5, 0x25ee, + 0xf4a6, 0x1ca4, + 0xf4af, 0x25ef, + 0xf4b0, 0x1cae, + 0xf4b5, 0x25f0, + 0xf4b6, 0x1cb4, + 0xf4c1, 0x25f1, + 0xf4c2, 0x1cc0, + 0xf4c7, 0x25f2, + 0xf4c8, 0x1cc6, + 0xf4cf, 0x25f3, + 0xf4d1, 0x1ccf, + 0xf4d6, 0x25f5, + 0xf4d7, 0x1cd5, + 0xf4ea, 0x25f6, + 0xf4eb, 0x1ce9, + 0xf4ef, 0x25f7, + 0xf4f0, 0x1cee, + 0xf4f5, 0x25f8, + 0xf4f6, 0x1cf4, + 0xf5a1, 0x1cfd, + 0xf5a6, 0x25f9, + 0xf5a8, 0x1d04, + 0xf5ba, 0x25fb, + 0xf5bc, 0x1d18, + 0xf5c4, 0x25fd, + 0xf5c5, 0x1d21, + 0xf5c8, 0x25fe, + 0xf5c9, 0x1d25, + 0xf5ce, 0x25ff, + 0xf5d0, 0x1d2c, + 0xf5d1, 0x2601, + 0xf5d3, 0x1d2f, + 0xf5d9, 0x2603, + 0xf5da, 0x1d36, + 0xf5dc, 0x2604, + 0xf5dd, 0x1d39, + 0xf5e6, 0x2605, + 0xf5e8, 0x1d44, + 0xf5ef, 0x2607, + 0xf5f0, 0x1d4c, + 0xf5f2, 0x2608, + 0xf5f3, 0x1d4f, + 0xf5fc, 0x2609, + 0xf5fd, 0x1d59, + 0xf6a1, 0x1d5b, + 0xf6a3, 0x260a, + 0xf6a4, 0x1d5e, + 0xf6a6, 0x260b, + 0xf6a7, 0x1d61, + 0xf6a8, 0x260c, + 0xf6a9, 0x1d63, + 0xf6ab, 0x260d, + 0xf6ac, 0x1d66, + 0xf6b0, 0x260e, + 0xf6b1, 0x1d6b, + 0xf6b3, 0x260f, + 0xf6bf, 0x1d79, + 0xf6c5, 0x261b, + 0xf6c6, 0x1d80, + 0xf6c7, 0x261c, + 0xf6c8, 0x1d82, + 0xf6c9, 0x261d, + 0xf6ca, 0x1d84, + 0xf6cf, 0x261e, + 0xf7a1, 0x264e, + 0xf7b0, 0x1dc8, + 0xf7b2, 0x265d, + 0xf7b4, 0x1dcc, + 0xf7b5, 0x265f, + 0xf7b6, 0x1dce, + 0xf7bd, 0x2660, + 0xf7be, 0x1dd6, + 0xf7c3, 0x2661, + 0xf7c4, 0x1ddc, + 0xf7c5, 0x2662, + 0xf7c7, 0x1ddf, + 0xf7ca, 0x2664, + 0xf7cc, 0x1de4, + 0xf7cf, 0x2666, + 0xf7d1, 0x1de9, + 0xf7de, 0x2668, + 0xf7df, 0x1df7, + 0xf7e1, 0x0ab9, + 0xf7e2, 0x1dfa, + 0xf7f2, 0x2669, + 0xf7f3, 0x1e0b, + 0xf7f5, 0x266a, + 0xf7f6, 0x1e0e, + 0xf8a1, 0x266b, + 0xf8a7, 0x04cc, + 0xf8a8, 0x050a, + 0xf8a9, 0x0518, + 0xf8aa, 0x2671, + 0xf8ac, 0x0594, + 0xf8ad, 0x05ce, + 0xf8ae, 0x2673, + 0xf8af, 0x05f6, + 0xf8b0, 0x2674, + 0xf8b2, 0x0653, + 0xf8b3, 0x067e, + 0xf8b4, 0x2676, + 0xf8b5, 0x06c4, + 0xf8b6, 0x2677, + 0xf8b8, 0x073c, + 0xf8b9, 0x2679, + 0xf8bb, 0x07c3, + 0xf8bc, 0x267b, + 0xf8c0, 0x082b, + 0xf8c1, 0x267f, + 0xf8c2, 0x084e, + 0xf8c3, 0x0869, + 0xf8c4, 0x2680, + 0xf8c6, 0x090c, + 0xf8c7, 0x2682, + 0xf8c9, 0x0971, + 0xf8ca, 0x2684, + 0xf8cb, 0x099a, + 0xf8cd, 0x2685, + 0xf8ce, 0x09da, + 0xf8cf, 0x2686, + 0xf8d0, 0x09fa, + 0xf8d1, 0x2687, + 0xf8dc, 0x0bda, + 0xf8dd, 0x0bdd, + 0xf8de, 0x0bea, + 0xf8df, 0x0bec, + 0xf8e0, 0x0bf2, + 0xf8e1, 0x2692, + 0xf8e6, 0x0c92, + 0xf8e7, 0x0d1a, + 0xf8e8, 0x0d8c, + 0xf8e9, 0x0dbe, + 0xf8ea, 0x2697, + 0xf8eb, 0x0dfb, + 0xf8ec, 0x2698, + 0xf8ef, 0x0e70, + 0xf8f0, 0x269b, + 0xf8f1, 0x0ea3, + 0xf8f2, 0x269c, + 0xf8f8, 0x103d, + 0xf8f9, 0x10d9, + 0xf8fa, 0x26a2, + 0xf8fc, 0x10fb, + 0xf8fd, 0x1109, + 0xf8fe, 0x26a4, + 0xf9a1, 0x11a1, + 0xf9a2, 0x26a5, + 0xf9a3, 0x11ba, + 0xf9a4, 0x26a6, + 0xf9a6, 0x11d5, + 0xf9a7, 0x26a8, + 0xf9a8, 0x11fd, + 0xf9a9, 0x1219, + 0xffff, 0x0000 +}; + +static GfxFontEncoding16 gb12GBTEUCHEnc16 = { + 0, + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 }, + { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1e24, 0x032e, 0x032f, 0x0330, 0x0331, 0x0332, 0x0333, 0x0334, + 0x0335, 0x0336, 0x0337, 0x0338, 0x0339, 0x033a, 0x033b, 0x033c, + 0x033d, 0x033e, 0x033f, 0x0340, 0x0341, 0x0342, 0x0343, 0x0344, + 0x0345, 0x0346, 0x0347, 0x0348, 0x0349, 0x034a, 0x034b, 0x034c, + 0x034d, 0x034e, 0x034f, 0x0350, 0x0351, 0x0352, 0x0353, 0x0354, + 0x0355, 0x0356, 0x0357, 0x0358, 0x0359, 0x035a, 0x035b, 0x035c, + 0x035d, 0x035e, 0x035f, 0x0360, 0x0361, 0x0362, 0x0363, 0x0364, + 0x0365, 0x0366, 0x0367, 0x0368, 0x0369, 0x036a, 0x036b, 0x036c, + 0x036d, 0x036e, 0x036f, 0x0370, 0x0371, 0x0372, 0x0373, 0x0374, + 0x0375, 0x0376, 0x0377, 0x0378, 0x0379, 0x037a, 0x037b, 0x037c, + 0x037d, 0x037e, 0x037f, 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, + 0x0385, 0x0386, 0x0387, 0x0388, 0x0389, 0x038a, 0x038b, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, + gb12GBTEUCHMap2, 2283 +}; + +static Gushort gb12GBTEUCVMap2[4606] = { + 0x0000, 0x0000, + 0xa1a1, 0x0060, + 0xa2b1, 0x00be, + 0xa2e5, 0x00f0, + 0xa2f1, 0x00fa, + 0xa3a1, 0x0106, + 0xa4a1, 0x0164, + 0xa5a1, 0x01b7, + 0xa6a1, 0x020d, + 0xa6c1, 0x0225, + 0xa7a1, 0x025a, + 0xa7d1, 0x027b, + 0xa8a1, 0x029c, + 0xa8c5, 0x02bc, + 0xa9a4, 0x02e2, + 0xaaa1, 0x032e, + 0xaba1, 0x038c, + 0xb0a1, 0x03ac, + 0xb0a8, 0x1e25, + 0xb0a9, 0x03b4, + 0xb0aa, 0x1e26, + 0xb0ab, 0x03b6, + 0xb0ad, 0x1e27, + 0xb0af, 0x03ba, + 0xb0b9, 0x1e29, + 0xb0ba, 0x03c5, + 0xb0c0, 0x1e2a, + 0xb0c1, 0x03cc, + 0xb0d3, 0x1e2b, + 0xb0d4, 0x03df, + 0xb0d5, 0x1e2c, + 0xb0d6, 0x03e1, + 0xb0da, 0x1e2d, + 0xb0db, 0x03e6, + 0xb0dc, 0x1e2e, + 0xb0dd, 0x03e8, + 0xb0e4, 0x1e2f, + 0xb0e5, 0x03f0, + 0xb0ec, 0x1e30, + 0xb0ee, 0x03f9, + 0xb0ef, 0x1e32, + 0xb0f0, 0x03fb, + 0xb0f3, 0x1e33, + 0xb0f4, 0x03ff, + 0xb0f7, 0x1e34, + 0xb0f8, 0x0403, + 0xb0f9, 0x1e35, + 0xb0fa, 0x0405, + 0xb1a1, 0x040a, + 0xb1a5, 0x1e36, + 0xb1a7, 0x0410, + 0xb1a8, 0x1e38, + 0xb1a9, 0x0412, + 0xb1ab, 0x1e39, + 0xb1ac, 0x0415, + 0xb1b2, 0x1e3a, + 0xb1b3, 0x041c, + 0xb1b4, 0x1e3b, + 0xb1b6, 0x041f, + 0xb1b7, 0x1e3d, + 0xb1ba, 0x0423, + 0xb1c1, 0x1e40, + 0xb1c2, 0x042b, + 0xb1ca, 0x1e41, + 0xb1cb, 0x0434, + 0xb1cf, 0x1e42, + 0xb1d1, 0x043a, + 0xb1d2, 0x1e44, + 0xb1d3, 0x043c, + 0xb1d5, 0x1e45, + 0xb1d6, 0x043f, + 0xb1df, 0x1e46, + 0xb1e2, 0x044b, + 0xb1e4, 0x1e49, + 0xb1e5, 0x044e, + 0xb1e7, 0x1e4a, + 0xb1e9, 0x0452, + 0xb1ea, 0x1e4c, + 0xb1eb, 0x0454, + 0xb1ee, 0x1e4d, + 0xb1ef, 0x0458, + 0xb1f1, 0x1e4e, + 0xb1f2, 0x045b, + 0xb1f4, 0x1e4f, + 0xb1f8, 0x0461, + 0xb1fd, 0x1e53, + 0xb1fe, 0x0467, + 0xb2a1, 0x0468, + 0xb2a6, 0x1e54, + 0xb2a8, 0x046f, + 0xb2ac, 0x1e56, + 0xb2ad, 0x0474, + 0xb2b5, 0x1e57, + 0xb2b6, 0x047d, + 0xb2b9, 0x1e58, + 0xb2ba, 0x0481, + 0xb2c6, 0x1e59, + 0xb2c7, 0x048e, + 0xb2ce, 0x1e5a, + 0xb2d8, 0x049f, + 0xb2de, 0x1e64, + 0xb2df, 0x04a6, + 0xb2e0, 0x1e65, + 0xb2e1, 0x04a8, + 0xb2e2, 0x1e66, + 0xb2e4, 0x04ab, + 0xb2ef, 0x1e68, + 0xb2f0, 0x04b7, + 0xb2f3, 0x1e69, + 0xb2fd, 0x04c4, + 0xb3a1, 0x1e73, + 0xb3a3, 0x04c8, + 0xb3a4, 0x1e75, + 0xb3a8, 0x04cd, + 0xb3a9, 0x1e79, + 0xb3aa, 0x04cf, + 0xb3ae, 0x1e7a, + 0xb3af, 0x04d4, + 0xb3b5, 0x1e7b, + 0xb3b6, 0x04db, + 0xb3b9, 0x1e7c, + 0xb3ba, 0x04df, + 0xb3be, 0x1e7d, + 0xb3bf, 0x04e4, + 0xb3c2, 0x1e7e, + 0xb3c3, 0x04e8, + 0xb3c4, 0x1e7f, + 0xb3c5, 0x04ea, + 0xb3c6, 0x1e80, + 0xb3c7, 0x04ec, + 0xb3cd, 0x1e81, + 0xb3ce, 0x04f3, + 0xb3cf, 0x1e82, + 0xb3d0, 0x04f5, + 0xb3d2, 0x1e83, + 0xb3d3, 0x04f8, + 0xb3d9, 0x1e84, + 0xb3da, 0x04ff, + 0xb3db, 0x1e85, + 0xb3dc, 0x0501, + 0xb3dd, 0x1e86, + 0xb3de, 0x0503, + 0xb3e3, 0x1e87, + 0xb3e4, 0x0509, + 0xb3e5, 0x1e88, + 0xb3e7, 0x050c, + 0xb3e8, 0x1e8a, + 0xb3e9, 0x050e, + 0xb3eb, 0x1e8b, + 0xb3ed, 0x0512, + 0xb3ef, 0x1e8d, + 0xb3f0, 0x0515, + 0xb3f1, 0x1e8e, + 0xb3f2, 0x0517, + 0xb3f3, 0x1e8f, + 0xb3f4, 0x0519, + 0xb3fa, 0x1e90, + 0xb3fc, 0x0521, + 0xb4a1, 0x1e92, + 0xb4a3, 0x0526, + 0xb4a5, 0x1e94, + 0xb4a7, 0x052a, + 0xb4ab, 0x1e96, + 0xb4ac, 0x052f, + 0xb4af, 0x1e97, + 0xb4b0, 0x0533, + 0xb4b3, 0x1e98, + 0xb4b5, 0x0538, + 0xb4b8, 0x1e9a, + 0xb4b9, 0x053c, + 0xb4bf, 0x1e9b, + 0xb4c0, 0x0543, + 0xb4c2, 0x1e9c, + 0xb4c3, 0x0546, + 0xb4c7, 0x1e9d, + 0xb4c8, 0x054b, + 0xb4ca, 0x1e9e, + 0xb4cb, 0x054e, + 0xb4cd, 0x1e9f, + 0xb4ce, 0x0551, + 0xb4cf, 0x1ea0, + 0xb4d0, 0x0553, + 0xb4d3, 0x1ea1, + 0xb4d5, 0x0558, + 0xb4da, 0x1ea3, + 0xb4db, 0x055e, + 0xb4dc, 0x1ea4, + 0xb4dd, 0x0560, + 0xb4ed, 0x1ea5, + 0xb4ee, 0x0571, + 0xb4ef, 0x1ea6, + 0xb4f0, 0x0573, + 0xb4f8, 0x1ea7, + 0xb4f9, 0x057c, + 0xb4fb, 0x1ea8, + 0xb4fc, 0x057f, + 0xb5a1, 0x0582, + 0xb5a3, 0x1ea9, + 0xb5a4, 0x0585, + 0xb5a5, 0x1eaa, + 0xb5a9, 0x058a, + 0xb5ac, 0x1eae, + 0xb5ad, 0x058e, + 0xb5ae, 0x1eaf, + 0xb5b0, 0x0591, + 0xb5b1, 0x1eb1, + 0xb5b6, 0x0597, + 0xb5b7, 0x1eb6, + 0xb5b8, 0x0599, + 0xb5ba, 0x1eb7, + 0xb5bd, 0x059e, + 0xb5c6, 0x1eba, + 0xb5c7, 0x05a8, + 0xb5cb, 0x1ebb, + 0xb5cc, 0x05ad, + 0xb5d0, 0x1ebc, + 0xb5d1, 0x05b2, + 0xb5d3, 0x1ebd, + 0xb5d4, 0x05b5, + 0xb5dd, 0x1ebe, + 0xb5e0, 0x05c1, + 0xb5e3, 0x1ec1, + 0xb5e4, 0x05c5, + 0xb5e6, 0x1ec2, + 0xb5e8, 0x05c9, + 0xb5ed, 0x1ec4, + 0xb5ee, 0x05cf, + 0xb5f6, 0x1ec5, + 0xb5f8, 0x05d9, + 0xb5fd, 0x1ec7, + 0xb5fe, 0x05df, + 0xb6a1, 0x05e0, + 0xb6a4, 0x1ec8, + 0xb6a6, 0x05e5, + 0xb6a7, 0x1eca, + 0xb6a8, 0x05e7, + 0xb6a9, 0x1ecb, + 0xb6aa, 0x05e9, + 0xb6ab, 0x1ecc, + 0xb6ac, 0x05eb, + 0xb6af, 0x1ecd, + 0xb6b1, 0x05f0, + 0xb6b3, 0x1ecf, + 0xb6b4, 0x05f3, + 0xb6b7, 0x1ed0, + 0xb6b8, 0x05f7, + 0xb6bf, 0x1ed1, + 0xb6c2, 0x0601, + 0xb6c4, 0x1ed4, + 0xb6c5, 0x0604, + 0xb6c6, 0x1ed5, + 0xb6c7, 0x0606, + 0xb6cd, 0x1ed6, + 0xb6ce, 0x060d, + 0xb6cf, 0x1ed7, + 0xb6d1, 0x0610, + 0xb6d3, 0x1ed9, + 0xb6d5, 0x0614, + 0xb6d6, 0x1edb, + 0xb6d7, 0x0616, + 0xb6d9, 0x1edc, + 0xb6da, 0x0619, + 0xb6db, 0x1edd, + 0xb6dc, 0x061b, + 0xb6e1, 0x1ede, + 0xb6e2, 0x0621, + 0xb6e9, 0x1edf, + 0xb6ea, 0x0629, + 0xb6ec, 0x1ee0, + 0xb6ed, 0x062c, + 0xb6ee, 0x1ee1, + 0xb6f0, 0x062f, + 0xb6f1, 0x1ee3, + 0xb6f2, 0x0631, + 0xb6f6, 0x1ee4, + 0xb6f7, 0x0636, + 0xb6f9, 0x1ee5, + 0xb6fa, 0x0639, + 0xb6fb, 0x1ee6, + 0xb6fd, 0x063c, + 0xb7a1, 0x1ee8, + 0xb7a4, 0x0641, + 0xb7a7, 0x1eeb, + 0xb7a8, 0x0645, + 0xb7af, 0x1eec, + 0xb7b1, 0x064e, + 0xb7b3, 0x1eee, + 0xb7b4, 0x0651, + 0xb7b6, 0x1eef, + 0xb7b8, 0x0655, + 0xb7b9, 0x1ef1, + 0xb7ba, 0x0657, + 0xb7c3, 0x1ef2, + 0xb7c5, 0x0662, + 0xb7c9, 0x1ef4, + 0xb7ca, 0x0667, + 0xb7cc, 0x1ef5, + 0xb7cd, 0x066a, + 0xb7cf, 0x1ef6, + 0xb7d0, 0x066d, + 0xb7d1, 0x1ef7, + 0xb7d2, 0x066f, + 0xb7d7, 0x1ef8, + 0xb7d9, 0x0676, + 0xb7dc, 0x1efa, + 0xb7dd, 0x067a, + 0xb7df, 0x1efb, + 0xb7e2, 0x067f, + 0xb7e3, 0x1efe, + 0xb7e4, 0x0681, + 0xb7e6, 0x1eff, + 0xb7e9, 0x0686, + 0xb7eb, 0x1f02, + 0xb7ee, 0x068b, + 0xb7ef, 0x1f05, + 0xb7f0, 0x068d, + 0xb7f4, 0x1f06, + 0xb7f5, 0x0692, + 0xb7f8, 0x1f07, + 0xb7f9, 0x0696, + 0xb8a1, 0x069c, + 0xb8a7, 0x1f08, + 0xb8a9, 0x06a4, + 0xb8b3, 0x1f0a, + 0xb8b5, 0x06b0, + 0xb8ba, 0x1f0c, + 0xb8bb, 0x06b6, + 0xb8bc, 0x1f0d, + 0xb8bd, 0x06b8, + 0xb8be, 0x1f0e, + 0xb8c0, 0x06bb, + 0xb8c3, 0x1f10, + 0xb8c4, 0x06bf, + 0xb8c6, 0x1f11, + 0xb8c8, 0x06c3, + 0xb8c9, 0x1f13, + 0xb8ca, 0x06c5, + 0xb8cf, 0x1f14, + 0xb8d0, 0x06cb, + 0xb8d3, 0x1f15, + 0xb8d7, 0x06d2, + 0xb8d9, 0x1f19, + 0xb8db, 0x06d6, + 0xb8e4, 0x1f1b, + 0xb8e5, 0x06e0, + 0xb8e9, 0x1f1c, + 0xb8ea, 0x06e5, + 0xb8eb, 0x1f1d, + 0xb8ec, 0x06e7, + 0xb8f3, 0x1f1e, + 0xb8f4, 0x06ef, + 0xb8f5, 0x1f1f, + 0xb8f7, 0x06f2, + 0xb8f8, 0x1f21, + 0xb8f9, 0x06f4, + 0xb9a1, 0x06fa, + 0xb9a8, 0x1f22, + 0xb9a9, 0x0702, + 0xb9ae, 0x1f23, + 0xb9af, 0x0708, + 0xb9b1, 0x1f24, + 0xb9b2, 0x070b, + 0xb9b3, 0x1f25, + 0xb9b4, 0x070d, + 0xb9b5, 0x1f26, + 0xb9b6, 0x070f, + 0xb9b9, 0x1f27, + 0xb9bb, 0x0714, + 0xb9c6, 0x1f29, + 0xb9c7, 0x0720, + 0xb9cb, 0x1f2a, + 0xb9cc, 0x0725, + 0xb9d0, 0x1f2b, + 0xb9d1, 0x072a, + 0xb9d8, 0x1f2c, + 0xb9d9, 0x0732, + 0xb9db, 0x1f2d, + 0xb9dc, 0x0735, + 0xb9dd, 0x1f2e, + 0xb9de, 0x0737, + 0xb9df, 0x1f2f, + 0xb9e0, 0x0739, + 0xb9e1, 0x1f30, + 0xb9e2, 0x073b, + 0xb9e3, 0x1f31, + 0xb9e4, 0x073d, + 0xb9e6, 0x1f32, + 0xb9e7, 0x0740, + 0xb9e9, 0x1f33, + 0xb9ed, 0x0746, + 0xb9ee, 0x1f37, + 0xb9ef, 0x0748, + 0xb9f1, 0x1f38, + 0xb9f2, 0x074b, + 0xb9f3, 0x1f39, + 0xb9f6, 0x074f, + 0xb9f8, 0x1f3c, + 0xb9f9, 0x0752, + 0xb9fa, 0x1f3d, + 0xb9fb, 0x0754, + 0xb9fd, 0x1f3e, + 0xb9fe, 0x0757, + 0xbaa1, 0x0758, + 0xbaa7, 0x1f3f, + 0xbaa8, 0x075f, + 0xbaab, 0x1f40, + 0xbaac, 0x0763, + 0xbaba, 0x1f41, + 0xbabb, 0x0772, + 0xbac5, 0x1f42, + 0xbac6, 0x077d, + 0xbad2, 0x1f43, + 0xbad3, 0x078a, + 0xbad7, 0x1f44, + 0xbad9, 0x0790, + 0xbae4, 0x1f46, + 0xbae5, 0x079c, + 0xbae8, 0x1f47, + 0xbae9, 0x07a0, + 0xbaec, 0x1f48, + 0xbaed, 0x07a4, + 0xbaf3, 0x15e5, + 0xbaf4, 0x07ab, + 0xbaf8, 0x1f49, + 0xbaf9, 0x07b0, + 0xbba1, 0x07b6, + 0xbba4, 0x1f4a, + 0xbba5, 0x07ba, + 0xbba6, 0x1f4b, + 0xbba7, 0x07bc, + 0xbba9, 0x1f4c, + 0xbbab, 0x07c0, + 0xbbad, 0x1f4e, + 0xbbaf, 0x07c4, + 0xbbb0, 0x1f50, + 0xbbb1, 0x07c6, + 0xbbb3, 0x1f51, + 0xbbb4, 0x07c9, + 0xbbb5, 0x1f52, + 0xbbb8, 0x07cd, + 0xbbb9, 0x1f55, + 0xbbbb, 0x07d0, + 0xbbd1, 0x1f57, + 0xbbd2, 0x07e7, + 0xbbd3, 0x1f58, + 0xbbd5, 0x07ea, + 0xbbdf, 0x1f5a, + 0xbbe8, 0x07fd, + 0xbbeb, 0x1f63, + 0xbbec, 0x0801, + 0xbbf1, 0x1f64, + 0xbbf2, 0x0807, + 0xbbf5, 0x1f65, + 0xbbf8, 0x080d, + 0xbbfa, 0x1f68, + 0xbbfb, 0x0810, + 0xbbfd, 0x1f69, + 0xbbfe, 0x0813, + 0xbca1, 0x0814, + 0xbca2, 0x1f6a, + 0xbca3, 0x0816, + 0xbca5, 0x1f6b, + 0xbca7, 0x081a, + 0xbca8, 0x1f6d, + 0xbcaa, 0x081d, + 0xbcab, 0x1f6f, + 0xbcac, 0x081f, + 0xbcad, 0x1f70, + 0xbcae, 0x0821, + 0xbcb6, 0x1f71, + 0xbcb9, 0x082c, + 0xbcbb, 0x1f74, + 0xbcbc, 0x082f, + 0xbcc1, 0x1f75, + 0xbcc2, 0x0835, + 0xbcc3, 0x1f76, + 0xbcc4, 0x0837, + 0xbcc6, 0x1f77, + 0xbcc8, 0x083b, + 0xbcca, 0x1f79, + 0xbccb, 0x083e, + 0xbccc, 0x1f7a, + 0xbcce, 0x0841, + 0xbcd0, 0x1f7c, + 0xbcd1, 0x0844, + 0xbcd4, 0x1f7d, + 0xbcd7, 0x084a, + 0xbcd8, 0x1f80, + 0xbcd9, 0x084c, + 0xbcdb, 0x1f81, + 0xbcdc, 0x084f, + 0xbcdd, 0x1f82, + 0xbcde, 0x0851, + 0xbcdf, 0x1f83, + 0xbce2, 0x0855, + 0xbce3, 0x1f86, + 0xbce5, 0x0858, + 0xbce8, 0x1f88, + 0xbce9, 0x085c, + 0xbcea, 0x1f89, + 0xbced, 0x0860, + 0xbcef, 0x1f8c, + 0xbcf4, 0x0867, + 0xbcf6, 0x1f91, + 0xbcfd, 0x0870, + 0xbda1, 0x0872, + 0xbda2, 0x1f98, + 0xbda8, 0x0879, + 0xbdab, 0x1f9e, + 0xbdad, 0x087e, + 0xbdaf, 0x1fa0, + 0xbdb3, 0x0884, + 0xbdb4, 0x1fa4, + 0xbdb5, 0x0886, + 0xbdba, 0x1fa5, + 0xbdbb, 0x088c, + 0xbdbd, 0x1fa6, + 0xbdc0, 0x0891, + 0xbdc1, 0x1fa9, + 0xbdc5, 0x0896, + 0xbdc8, 0x1fad, + 0xbdcb, 0x089c, + 0xbdce, 0x1fb0, + 0xbdd0, 0x08a1, + 0xbdd7, 0x1fb2, + 0xbdd8, 0x08a9, + 0xbdda, 0x1fb3, + 0xbddb, 0x08ac, + 0xbde0, 0x1fb4, + 0xbde2, 0x08b3, + 0xbdeb, 0x1fb6, + 0xbdec, 0x08bd, + 0xbdf4, 0x1fb7, + 0xbdf9, 0x08ca, + 0xbdfd, 0x1fbc, + 0xbdfe, 0x08cf, + 0xbea1, 0x1fbd, + 0xbea3, 0x08d2, + 0xbea5, 0x1fbf, + 0xbea6, 0x08d5, + 0xbea8, 0x1fc0, + 0xbea9, 0x08d8, + 0xbeaa, 0x1fc1, + 0xbeab, 0x08da, + 0xbead, 0x1fc2, + 0xbeae, 0x08dd, + 0xbeb1, 0x1fc3, + 0xbeb2, 0x08e1, + 0xbeb5, 0x1fc4, + 0xbeb8, 0x08e7, + 0xbeba, 0x1fc7, + 0xbebb, 0x08ea, + 0xbec0, 0x1fc8, + 0xbec1, 0x08f0, + 0xbec9, 0x1fc9, + 0xbeca, 0x08f9, + 0xbed4, 0x1fca, + 0xbed5, 0x0904, + 0xbed9, 0x1fcb, + 0xbeda, 0x0909, + 0xbedd, 0x1fcc, + 0xbede, 0x090d, + 0xbee2, 0x1fcd, + 0xbee3, 0x0912, + 0xbee5, 0x1fce, + 0xbee6, 0x0915, + 0xbee7, 0x1fcf, + 0xbee8, 0x0917, + 0xbee9, 0x1fd0, + 0xbeea, 0x0919, + 0xbeee, 0x1fd1, + 0xbeef, 0x091e, + 0xbef5, 0x1fd2, + 0xbef6, 0x0925, + 0xbef7, 0x1fd3, + 0xbef9, 0x0928, + 0xbefb, 0x1fd5, + 0xbefd, 0x092c, + 0xbfa1, 0x092e, + 0xbfa5, 0x1fd7, + 0xbfa6, 0x0933, + 0xbfaa, 0x1fd8, + 0xbfab, 0x0938, + 0xbfad, 0x1fd9, + 0xbfae, 0x093b, + 0xbfc5, 0x1fda, + 0xbfc6, 0x0953, + 0xbfc7, 0x1fdb, + 0xbfc8, 0x0955, + 0xbfce, 0x1fdc, + 0xbfcf, 0x095c, + 0xbfd1, 0x1fdd, + 0xbfd3, 0x0960, + 0xbfd9, 0x1fdf, + 0xbfda, 0x0967, + 0xbfe2, 0x1fe0, + 0xbfe5, 0x0972, + 0xbfe9, 0x1fe3, + 0xbfea, 0x0977, + 0xbfeb, 0x1fe4, + 0xbfec, 0x0979, + 0xbfed, 0x1fe5, + 0xbfee, 0x097b, + 0xbff3, 0x1fe6, + 0xbff4, 0x0981, + 0xbff5, 0x1fe7, + 0xbff6, 0x0983, + 0xbff7, 0x1fe8, + 0xbff8, 0x0985, + 0xbff9, 0x1fe9, + 0xbffb, 0x0988, + 0xc0a1, 0x1feb, + 0xc0a2, 0x098d, + 0xc0a3, 0x1fec, + 0xc0a4, 0x098f, + 0xc0a9, 0x1fed, + 0xc0aa, 0x0995, + 0xc0ab, 0x1fee, + 0xc0ac, 0x0997, + 0xc0af, 0x1fef, + 0xc0b1, 0x099c, + 0xc0b3, 0x1ff1, + 0xc0b7, 0x09a2, + 0xc0b8, 0x1ff5, + 0xc0c5, 0x09b0, + 0xc0cc, 0x2002, + 0xc0ce, 0x09b9, + 0xc0d4, 0x2004, + 0xc0d5, 0x09c0, + 0xc0d6, 0x2005, + 0xc0d7, 0x09c2, + 0xc0d8, 0x2006, + 0xc0d9, 0x09c4, + 0xc0dd, 0x2007, + 0xc0de, 0x09c9, + 0xc0e0, 0x2008, + 0xc0e1, 0x09cc, + 0xc0e9, 0x2009, + 0xc0ea, 0x09d5, + 0xc0eb, 0x200a, + 0xc0ed, 0x09d8, + 0xc0ef, 0x200c, + 0xc0f2, 0x09dd, + 0xc0f6, 0x200f, + 0xc0fb, 0x09e6, + 0xc1a1, 0x09ea, + 0xc1a4, 0x2014, + 0xc1a6, 0x09ef, + 0xc1a9, 0x2016, + 0xc1ae, 0x09f7, + 0xc1af, 0x201b, + 0xc1b9, 0x0a02, + 0xc1bd, 0x2025, + 0xc1bf, 0x0a08, + 0xc1c2, 0x2027, + 0xc1c3, 0x0a0c, + 0xc1c6, 0x2028, + 0xc1c7, 0x0a10, + 0xc1c9, 0x2029, + 0xc1ca, 0x0a13, + 0xc1cd, 0x202a, + 0xc1ce, 0x0a17, + 0xc1d4, 0x202b, + 0xc1d5, 0x0a1e, + 0xc1d9, 0x202c, + 0xc1dc, 0x0a25, + 0xc1de, 0x202f, + 0xc1df, 0x0a28, + 0xc1e4, 0x2030, + 0xc1e6, 0x0a2f, + 0xc1e9, 0x2032, + 0xc1ea, 0x0a33, + 0xc1eb, 0x2033, + 0xc1ed, 0x0a36, + 0xc1f3, 0x2035, + 0xc1f4, 0x0a3d, + 0xc1f5, 0x2036, + 0xc1f6, 0x0a3f, + 0xc1fa, 0x2037, + 0xc1fe, 0x0a47, + 0xc2a1, 0x0a48, + 0xc2a2, 0x203b, + 0xc2a9, 0x0a50, + 0xc2ab, 0x2042, + 0xc2b4, 0x0a5b, + 0xc2b8, 0x204b, + 0xc2b9, 0x0a60, + 0xc2bc, 0x204c, + 0xc2be, 0x0a65, + 0xc2bf, 0x204e, + 0xc2c0, 0x0a67, + 0xc2c1, 0x204f, + 0xc2c2, 0x0a69, + 0xc2c5, 0x2050, + 0xc2c8, 0x0a6f, + 0xc2cb, 0x2053, + 0xc2d1, 0x0a78, + 0xc2d2, 0x2059, + 0xc2d3, 0x0a7a, + 0xc2d5, 0x205a, + 0xc2dd, 0x0a84, + 0xc2de, 0x2062, + 0xc2e3, 0x0a8a, + 0xc2e6, 0x2067, + 0xc2e9, 0x0a90, + 0xc2ea, 0x206a, + 0xc2ef, 0x0a96, + 0xc2f0, 0x206f, + 0xc2f1, 0x0a98, + 0xc2f2, 0x2070, + 0xc2f6, 0x0a9d, + 0xc2f7, 0x2074, + 0xc2fb, 0x0aa2, + 0xc3a1, 0x2078, + 0xc3a2, 0x0aa7, + 0xc3aa, 0x2079, + 0xc3ab, 0x0ab0, + 0xc3ad, 0x207a, + 0xc3ae, 0x0ab3, + 0xc3b3, 0x207b, + 0xc3b4, 0x1df9, + 0xc3b5, 0x0aba, + 0xc3be, 0x207c, + 0xc3bf, 0x0ac4, + 0xc3c5, 0x207d, + 0xc3c8, 0x0acd, + 0xc3cc, 0x2080, + 0xc3cd, 0x0ad2, + 0xc3ce, 0x2081, + 0xc3cf, 0x0ad4, + 0xc3d5, 0x2082, + 0xc3d7, 0x0adc, + 0xc3d9, 0x2084, + 0xc3da, 0x0adf, + 0xc3e0, 0x2085, + 0xc3e1, 0x0ae6, + 0xc3e5, 0x2086, + 0xc3e6, 0x0aeb, + 0xc3ed, 0x2087, + 0xc3ee, 0x0af3, + 0xc3f0, 0x2088, + 0xc3f1, 0x0af6, + 0xc3f5, 0x2089, + 0xc3f7, 0x0afc, + 0xc3f9, 0x208b, + 0xc3fb, 0x0b00, + 0xc3fd, 0x208d, + 0xc3fe, 0x0b03, + 0xc4a1, 0x0b04, + 0xc4b1, 0x208e, + 0xc4b2, 0x0b15, + 0xc4b6, 0x208f, + 0xc4b7, 0x0b1a, + 0xc4c6, 0x2090, + 0xc4c7, 0x0b2a, + 0xc4c9, 0x2091, + 0xc4ca, 0x0b2d, + 0xc4d1, 0x2092, + 0xc4d2, 0x0b35, + 0xc4d3, 0x2093, + 0xc4d7, 0x0b3a, + 0xc4d9, 0x2097, + 0xc4da, 0x0b3d, + 0xc4e2, 0x2098, + 0xc4e3, 0x0b46, + 0xc4e5, 0x2099, + 0xc4e6, 0x0b49, + 0xc4ec, 0x209a, + 0xc4ed, 0x0b50, + 0xc4f0, 0x209b, + 0xc4f2, 0x0b55, + 0xc4f4, 0x209d, + 0xc4f5, 0x0b58, + 0xc4f6, 0x209e, + 0xc4f9, 0x0b5c, + 0xc4fb, 0x20a1, + 0xc4fd, 0x0b60, + 0xc4fe, 0x20a3, + 0xc5a1, 0x20a4, + 0xc5a3, 0x0b64, + 0xc5a5, 0x20a6, + 0xc5aa, 0x0b6b, + 0xc5b1, 0x20ab, + 0xc5b2, 0x0b73, + 0xc5b5, 0x20ac, + 0xc5b6, 0x0b77, + 0xc5b7, 0x20ad, + 0xc5ba, 0x0b7b, + 0xc5bb, 0x20b0, + 0xc5bc, 0x0b7d, + 0xc5bd, 0x20b1, + 0xc5be, 0x0b7f, + 0xc5cc, 0x20b2, + 0xc5cd, 0x0b8e, + 0xc5d3, 0x20b3, + 0xc5d4, 0x0b95, + 0xc5e2, 0x20b4, + 0xc5e3, 0x0ba4, + 0xc5e7, 0x20b5, + 0xc5e8, 0x0ba9, + 0xc5f4, 0x20b6, + 0xc5f5, 0x0bb6, + 0xc6a1, 0x0bc0, + 0xc6ad, 0x20b7, + 0xc6af, 0x0bce, + 0xc6b5, 0x20b9, + 0xc6b7, 0x0bd6, + 0xc6bb, 0x20bb, + 0xc6bc, 0x0bdb, + 0xc6be, 0x20bc, + 0xc6bf, 0x0bde, + 0xc6c0, 0x20bd, + 0xc6c1, 0x0be0, + 0xc6c3, 0x20be, + 0xc6c5, 0x0be4, + 0xc6cb, 0x20c0, + 0xc6ce, 0x0bed, + 0xc6d3, 0x20c3, + 0xc6d4, 0x0bf3, + 0xc6d7, 0x20c4, + 0xc6d8, 0x0bf7, + 0xc6ea, 0x20c5, + 0xc6ec, 0x0c0b, + 0xc6ef, 0x20c7, + 0xc6f0, 0x0c0f, + 0xc6f1, 0x20c8, + 0xc6f2, 0x0c11, + 0xc6f4, 0x20c9, + 0xc6f5, 0x0c14, + 0xc6f8, 0x20ca, + 0xc6f9, 0x0c18, + 0xc6fd, 0x20cb, + 0xc6fe, 0x0c1d, + 0xc7a1, 0x0c1e, + 0xc7a3, 0x20cc, + 0xc7a4, 0x0c21, + 0xc7a5, 0x20cd, + 0xc7a7, 0x0c24, + 0xc7a8, 0x20cf, + 0xc7aa, 0x0c27, + 0xc7ab, 0x20d1, + 0xc7ac, 0x0c29, + 0xc7ae, 0x20d2, + 0xc7b0, 0x0c2d, + 0xc7b3, 0x20d4, + 0xc7b6, 0x0c33, + 0xc7b9, 0x20d7, + 0xc7bb, 0x0c38, + 0xc7bd, 0x20d9, + 0xc7bf, 0x0c3c, + 0xc7c0, 0x20db, + 0xc7c1, 0x0c3e, + 0xc7c2, 0x20dc, + 0xc7c3, 0x0c40, + 0xc7c5, 0x20dd, + 0xc7c6, 0x0c43, + 0xc7c7, 0x20de, + 0xc7c9, 0x0c46, + 0xc7cc, 0x20e0, + 0xc7cd, 0x0c4a, + 0xc7cf, 0x20e1, + 0xc7d0, 0x0c4d, + 0xc7d4, 0x20e2, + 0xc7d6, 0x0c53, + 0xc7d7, 0x20e4, + 0xc7d8, 0x0c55, + 0xc7de, 0x20e5, + 0xc7df, 0x0c5c, + 0xc7e1, 0x20e6, + 0xc7e4, 0x0c61, + 0xc7ea, 0x20e9, + 0xc7ef, 0x0c6c, + 0xc7f7, 0x20ee, + 0xc7f9, 0x0c76, + 0xc7fb, 0x20f0, + 0xc7fc, 0x0c79, + 0xc7fd, 0x20f1, + 0xc7fe, 0x0c7b, + 0xc8a1, 0x0c7c, + 0xc8a3, 0x20f2, + 0xc8a4, 0x0c7f, + 0xc8a7, 0x20f3, + 0xc8a9, 0x0c84, + 0xc8b0, 0x20f5, + 0xc8b1, 0x0c8c, + 0xc8b5, 0x20f6, + 0xc8b6, 0x0c91, + 0xc8b7, 0x20f7, + 0xc8b8, 0x0c93, + 0xc8c3, 0x20f8, + 0xc8c7, 0x0ca2, + 0xc8c8, 0x20fc, + 0xc8c9, 0x0ca4, + 0xc8cd, 0x20fd, + 0xc8ce, 0x0ca9, + 0xc8cf, 0x20fe, + 0xc8d0, 0x0cab, + 0xc8d2, 0x20ff, + 0xc8d3, 0x0cae, + 0xc8d9, 0x2100, + 0xc8da, 0x0cb5, + 0xc8de, 0x2101, + 0xc8df, 0x0cba, + 0xc8ed, 0x2102, + 0xc8ee, 0x0cc9, + 0xc8f1, 0x2103, + 0xc8f4, 0x0ccf, + 0xc8f7, 0x2106, + 0xc8f9, 0x0cd4, + 0xc8fa, 0x2108, + 0xc8fb, 0x0cd6, + 0xc8fc, 0x2109, + 0xc8fd, 0x0cd8, + 0xc9a1, 0x210a, + 0xc9a2, 0x0cdb, + 0xc9a5, 0x210b, + 0xc9a6, 0x0cdf, + 0xc9a7, 0x210c, + 0xc9a9, 0x0ce2, + 0xc9ac, 0x210e, + 0xc9ad, 0x0ce6, + 0xc9b1, 0x210f, + 0xc9b2, 0x0ceb, + 0xc9b4, 0x2110, + 0xc9b5, 0x0cee, + 0xc9b8, 0x2111, + 0xc9ba, 0x0cf3, + 0xc9c1, 0x2113, + 0xc9c3, 0x0cfc, + 0xc9c4, 0x2115, + 0xc9c5, 0x0cfe, + 0xc9c9, 0x2116, + 0xc9ca, 0x0d03, + 0xc9cb, 0x2117, + 0xc9cc, 0x0d05, + 0xc9cd, 0x2118, + 0xc9ce, 0x0d07, + 0xc9d5, 0x2119, + 0xc9d6, 0x0d0f, + 0xc9dc, 0x211a, + 0xc9dd, 0x0d16, + 0xc9de, 0x211b, + 0xc9df, 0x0d18, + 0xc9e1, 0x211c, + 0xc9e2, 0x0d1b, + 0xc9e3, 0x211d, + 0xc9e4, 0x0d1d, + 0xc9e5, 0x211e, + 0xc9e6, 0x0d1f, + 0xc9e8, 0x211f, + 0xc9e9, 0x0d22, + 0xc9f0, 0x2120, + 0xc9f1, 0x0d2a, + 0xc9f3, 0x2121, + 0xc9f5, 0x0d2e, + 0xc9f6, 0x2123, + 0xc9f7, 0x0d30, + 0xc9f8, 0x2124, + 0xc9fa, 0x0d33, + 0xc9fe, 0x2126, + 0xcaa1, 0x0d38, + 0xcaa4, 0x2127, + 0xcaa7, 0x0d3e, + 0xcaa8, 0x212a, + 0xcaa9, 0x0d40, + 0xcaaa, 0x212b, + 0xcaac, 0x0d43, + 0xcab1, 0x212d, + 0xcab2, 0x0d49, + 0xcab4, 0x212e, + 0xcab7, 0x0d4e, + 0xcabb, 0x2131, + 0xcabc, 0x0d53, + 0xcac6, 0x2132, + 0xcac7, 0x0d5e, + 0xcaca, 0x2133, + 0xcacb, 0x0d62, + 0xcacd, 0x2134, + 0xcacf, 0x0d66, + 0xcad3, 0x2136, + 0xcad5, 0x0d6c, + 0xcad9, 0x2138, + 0xcada, 0x0d71, + 0xcade, 0x2139, + 0xcadf, 0x0d76, + 0xcae0, 0x213a, + 0xcae1, 0x0d78, + 0xcae4, 0x213b, + 0xcae5, 0x0d7c, + 0xcae9, 0x213c, + 0xcaeb, 0x0d82, + 0xcaf4, 0x213e, + 0xcaf6, 0x0d8d, + 0xcaf7, 0x2140, + 0xcaf8, 0x0d8f, + 0xcafa, 0x2141, + 0xcafb, 0x0d92, + 0xcafd, 0x2142, + 0xcafe, 0x0d95, + 0xcba1, 0x0d96, + 0xcba7, 0x2143, + 0xcba8, 0x0d9d, + 0xcbab, 0x2144, + 0xcbac, 0x0da1, + 0xcbad, 0x2145, + 0xcbae, 0x0da3, + 0xcbb3, 0x2146, + 0xcbb4, 0x0da9, + 0xcbb5, 0x2147, + 0xcbb7, 0x0dac, + 0xcbb8, 0x2149, + 0xcbb9, 0x0dae, + 0xcbbf, 0x214a, + 0xcbc0, 0x0db5, + 0xcbc7, 0x214b, + 0xcbc8, 0x0dbd, + 0xcbc9, 0x214c, + 0xcbcd, 0x0dc2, + 0xcbcf, 0x2150, + 0xcbd1, 0x0dc6, + 0xcbd3, 0x2152, + 0xcbd4, 0x0dc9, + 0xcbd5, 0x2153, + 0xcbd6, 0x0dcb, + 0xcbdf, 0x2154, + 0xcbe1, 0x0dd6, + 0xcbe4, 0x2156, + 0xcbe5, 0x0dda, + 0xcbe6, 0x2157, + 0xcbe8, 0x0ddd, + 0xcbea, 0x2159, + 0xcbeb, 0x0de0, + 0xcbef, 0x215a, + 0xcbf1, 0x0de6, + 0xcbf5, 0x215c, + 0xcbf7, 0x0dec, + 0xcbf8, 0x215e, + 0xcbf9, 0x0dee, + 0xcca1, 0x215f, + 0xcca3, 0x0df6, + 0xcca8, 0x2161, + 0xcca9, 0x0dfc, + 0xccac, 0x2162, + 0xccad, 0x0e00, + 0xccaf, 0x2163, + 0xccb4, 0x0e07, + 0xccb7, 0x2168, + 0xccb9, 0x0e0c, + 0xccbe, 0x216a, + 0xccbf, 0x0e12, + 0xccc0, 0x216b, + 0xccc1, 0x0e14, + 0xcccc, 0x216c, + 0xcccd, 0x0e20, + 0xccce, 0x216d, + 0xcccf, 0x0e22, + 0xccd0, 0x216e, + 0xccd1, 0x0e24, + 0xccd6, 0x216f, + 0xccd7, 0x0e2a, + 0xccda, 0x2170, + 0xccdb, 0x0e2e, + 0xccdc, 0x2171, + 0xccdd, 0x0e30, + 0xcce0, 0x2172, + 0xcce1, 0x0e34, + 0xcce2, 0x2173, + 0xcce3, 0x0e36, + 0xcce5, 0x2174, + 0xcce6, 0x0e39, + 0xccf5, 0x2175, + 0xccf6, 0x0e49, + 0xccf9, 0x2176, + 0xccfb, 0x0e4e, + 0xccfc, 0x2178, + 0xcda1, 0x0e52, + 0xcdad, 0x217b, + 0xcdae, 0x0e5f, + 0xcdb3, 0x217c, + 0xcdb4, 0x0e65, + 0xcdb7, 0x217d, + 0xcdb8, 0x0e69, + 0xcdbc, 0x217e, + 0xcdbd, 0x0e6e, + 0xcdbf, 0x217f, + 0xcdc0, 0x0e71, + 0xcdc5, 0x2180, + 0xcdc6, 0x0e77, + 0xcdc7, 0x2181, + 0xcdc8, 0x0e79, + 0xcdd2, 0x2182, + 0xcdd3, 0x0e84, + 0xcdd4, 0x2183, + 0xcdd7, 0x0e88, + 0xcddd, 0x2186, + 0xcdde, 0x0e8f, + 0xcde0, 0x2187, + 0xcde1, 0x0e92, + 0xcde4, 0x2188, + 0xcde6, 0x0e97, + 0xcde7, 0x218a, + 0xcde8, 0x0e99, + 0xcdf2, 0x218b, + 0xcdf3, 0x0ea4, + 0xcdf8, 0x218c, + 0xcdf9, 0x0eaa, + 0xcea1, 0x0eb0, + 0xcea4, 0x218d, + 0xcea6, 0x0eb5, + 0xcea7, 0x218f, + 0xcea8, 0x0eb7, + 0xceaa, 0x2190, + 0xceae, 0x0ebd, + 0xceb0, 0x2194, + 0xceb2, 0x0ec1, + 0xceb3, 0x2196, + 0xceb4, 0x0ec3, + 0xcebd, 0x2197, + 0xcebe, 0x0ecd, + 0xcec0, 0x2198, + 0xcec1, 0x0ed0, + 0xcec5, 0x2199, + 0xcec7, 0x0ed6, + 0xcec8, 0x219b, + 0xcec9, 0x0ed8, + 0xceca, 0x219c, + 0xcecb, 0x0eda, + 0xcece, 0x219d, + 0xced2, 0x0ee1, + 0xced8, 0x21a1, + 0xcedb, 0x0eea, + 0xcedc, 0x21a4, + 0xcedd, 0x0eec, + 0xcede, 0x21a5, + 0xcee0, 0x0eef, + 0xceeb, 0x21a7, + 0xceec, 0x0efb, + 0xceed, 0x21a8, + 0xceee, 0x0efd, + 0xcef1, 0x21a9, + 0xcef2, 0x0f01, + 0xcef3, 0x21aa, + 0xcef4, 0x0f03, + 0xcefd, 0x21ab, + 0xcfa1, 0x0f0e, + 0xcfae, 0x21ad, + 0xcfaf, 0x0f1c, + 0xcfb0, 0x21ae, + 0xcfb1, 0x0f1e, + 0xcfb3, 0x21af, + 0xcfb4, 0x0f21, + 0xcfb7, 0x21b0, + 0xcfb9, 0x0f26, + 0xcfba, 0x21b2, + 0xcfbb, 0x0f28, + 0xcfbd, 0x21b3, + 0xcfbe, 0x0f2b, + 0xcfbf, 0x21b4, + 0xcfc2, 0x0f2f, + 0xcfc5, 0x21b7, + 0xcfc6, 0x0f33, + 0xcfc7, 0x21b8, + 0xcfc8, 0x0f35, + 0xcfca, 0x21b9, + 0xcfcc, 0x0f39, + 0xcfcd, 0x21bb, + 0xcfcf, 0x0f3c, + 0xcfd0, 0x21bd, + 0xcfd1, 0x0f3e, + 0xcfd4, 0x21be, + 0xcfd9, 0x0f46, + 0xcfda, 0x21c3, + 0xcfdb, 0x0f48, + 0xcfdc, 0x21c4, + 0xcfdd, 0x0f4a, + 0xcfdf, 0x21c5, + 0xcfe0, 0x0f4d, + 0xcfe2, 0x21c6, + 0xcfe3, 0x0f50, + 0xcfe7, 0x21c7, + 0xcfe8, 0x0f55, + 0xcfea, 0x21c8, + 0xcfeb, 0x0f58, + 0xcfec, 0x21c9, + 0xcfed, 0x0f5a, + 0xcfee, 0x21ca, + 0xcfef, 0x0f5c, + 0xcff4, 0x21cb, + 0xcff5, 0x0f62, + 0xcff9, 0x21cc, + 0xcffb, 0x0f68, + 0xcffe, 0x21ce, + 0xd0a1, 0x0f6c, + 0xd0a5, 0x21cf, + 0xd0a6, 0x0f71, + 0xd0ad, 0x21d0, + 0xd0af, 0x0f7a, + 0xd0b2, 0x21d2, + 0xd0b5, 0x0f80, + 0xd0ba, 0x21d5, + 0xd0bc, 0x0f87, + 0xd0bf, 0x21d7, + 0xd0c0, 0x0f8b, + 0xd0c6, 0x21d8, + 0xd0c7, 0x0f92, + 0xd0cb, 0x21d9, + 0xd0cc, 0x0f97, + 0xd0e2, 0x21da, + 0xd0e3, 0x0fae, + 0xd0e5, 0x21db, + 0xd0e6, 0x0fb1, + 0xd0eb, 0x21dc, + 0xd0ec, 0x0fb7, + 0xd0ed, 0x21dd, + 0xd0ee, 0x0fb9, + 0xd0f7, 0x21de, + 0xd0fa, 0x0fc5, + 0xd0fc, 0x21e1, + 0xd0fd, 0x0fc8, + 0xd1a1, 0x21e2, + 0xd1a3, 0x0fcc, + 0xd1a4, 0x21e4, + 0xd1a5, 0x0fce, + 0xd1a7, 0x21e5, + 0xd1a8, 0x0fd1, + 0xd1ab, 0x21e6, + 0xd1ac, 0x0fd5, + 0xd1af, 0x21e7, + 0xd1b2, 0x0fdb, + 0xd1b5, 0x21ea, + 0xd1b8, 0x0fe1, + 0xd1b9, 0x21ed, + 0xd1ba, 0x0fe3, + 0xd1bb, 0x21ee, + 0xd1bd, 0x0fe6, + 0xd1c6, 0x21f0, + 0xd1c9, 0x0ff2, + 0xd1cb, 0x21f3, + 0xd1cc, 0x0ff5, + 0xd1ce, 0x21f4, + 0xd1d0, 0x0ff9, + 0xd1d5, 0x21f6, + 0xd1d7, 0x1000, + 0xd1de, 0x21f8, + 0xd1df, 0x1008, + 0xd1e1, 0x21f9, + 0xd1e3, 0x100c, + 0xd1e8, 0x21fb, + 0xd1ea, 0x1013, + 0xd1ec, 0x21fd, + 0xd1ed, 0x1016, + 0xd1ee, 0x21fe, + 0xd1f0, 0x1019, + 0xd1f1, 0x2200, + 0xd1f2, 0x101b, + 0xd1f4, 0x2201, + 0xd1f5, 0x101e, + 0xd1f7, 0x2202, + 0xd1fa, 0x1023, + 0xd2a1, 0x1028, + 0xd2a2, 0x2205, + 0xd2a3, 0x102a, + 0xd2a5, 0x2206, + 0xd2a6, 0x102d, + 0xd2a9, 0x2207, + 0xd2aa, 0x1031, + 0xd2af, 0x2208, + 0xd2b0, 0x1037, + 0xd2b3, 0x2209, + 0xd2b4, 0x103b, + 0xd2b5, 0x220a, + 0xd2b7, 0x103e, + 0xd2bd, 0x220c, + 0xd2be, 0x1045, + 0xd2bf, 0x220d, + 0xd2c0, 0x1047, + 0xd2c3, 0x220e, + 0xd2c4, 0x104b, + 0xd2c5, 0x220f, + 0xd2c6, 0x104d, + 0xd2c7, 0x2210, + 0xd2c8, 0x104f, + 0xd2cf, 0x2211, + 0xd2d0, 0x1057, + 0xd2d5, 0x2212, + 0xd2d6, 0x105d, + 0xd2da, 0x2213, + 0xd2db, 0x1062, + 0xd2e4, 0x2214, + 0xd2e6, 0x106d, + 0xd2e8, 0x2216, + 0xd2ec, 0x1073, + 0xd2ef, 0x221a, + 0xd2f0, 0x1077, + 0xd2f1, 0x221b, + 0xd2f2, 0x1079, + 0xd2f5, 0x221c, + 0xd2f6, 0x107d, + 0xd2f8, 0x221d, + 0xd2f9, 0x1080, + 0xd2fb, 0x221e, + 0xd2fc, 0x1083, + 0xd2fe, 0x221f, + 0xd3a1, 0x1086, + 0xd3a3, 0x2220, + 0xd3ad, 0x1092, + 0xd3ae, 0x222a, + 0xd3af, 0x1094, + 0xd3b1, 0x222b, + 0xd3b2, 0x1097, + 0xd3b4, 0x222c, + 0xd3b7, 0x109c, + 0xd3b8, 0x222f, + 0xd3b9, 0x109e, + 0xd3bb, 0x2230, + 0xd3bc, 0x10a1, + 0xd3c5, 0x2231, + 0xd3c6, 0x10ab, + 0xd3c7, 0x2232, + 0xd3c8, 0x10ad, + 0xd3ca, 0x2233, + 0xd3cd, 0x10b2, + 0xd3d5, 0x2236, + 0xd3d6, 0x10bb, + 0xd3df, 0x2237, + 0xd3e1, 0x10c6, + 0xd3e3, 0x2239, + 0xd3e4, 0x10c9, + 0xd3e6, 0x223a, + 0xd3e7, 0x10cc, + 0xd3eb, 0x223b, + 0xd3ed, 0x10d2, + 0xd3ef, 0x223d, + 0xd3f0, 0x10d5, + 0xd3f4, 0x223e, + 0xd3f5, 0x10da, + 0xd3fc, 0x223f, + 0xd3fd, 0x10e2, + 0xd3fe, 0x2240, + 0xd4a1, 0x10e4, + 0xd4a4, 0x2241, + 0xd4a5, 0x10e8, + 0xd4a6, 0x2242, + 0xd4a9, 0x10ec, + 0xd4af, 0x2245, + 0xd4b3, 0x10f6, + 0xd4b5, 0x2249, + 0xd4b7, 0x10fa, + 0xd4b8, 0x224b, + 0xd4b9, 0x10fc, + 0xd4bc, 0x224c, + 0xd4bd, 0x1100, + 0xd4be, 0x224d, + 0xd4c0, 0x1103, + 0xd4c4, 0x224f, + 0xd4c5, 0x1108, + 0xd4c6, 0x2250, + 0xd4c8, 0x110b, + 0xd4c9, 0x2252, + 0xd4ca, 0x110d, + 0xd4cb, 0x2253, + 0xd4cf, 0x1112, + 0xd4d3, 0x2257, + 0xd4d4, 0x1117, + 0xd4d8, 0x2258, + 0xd4d9, 0x111c, + 0xd4dc, 0x2259, + 0xd4e1, 0x1124, + 0xd4e4, 0x225e, + 0xd4e5, 0x1128, + 0xd4e6, 0x225f, + 0xd4e7, 0x112a, + 0xd4ee, 0x2260, + 0xd4ef, 0x1132, + 0xd4f0, 0x2261, + 0xd4f5, 0x1138, + 0xd4f9, 0x2266, + 0xd4fa, 0x113d, + 0xd4fe, 0x2267, + 0xd5a1, 0x2268, + 0xd5a3, 0x1144, + 0xd5a9, 0x226a, + 0xd5aa, 0x114b, + 0xd5ab, 0x226b, + 0xd5ac, 0x114d, + 0xd5ae, 0x226c, + 0xd5af, 0x1150, + 0xd5b1, 0x226d, + 0xd5b2, 0x1153, + 0xd5b5, 0x226e, + 0xd5b9, 0x115a, + 0xd5bb, 0x2272, + 0xd5bc, 0x115d, + 0xd5bd, 0x2273, + 0xd5be, 0x115f, + 0xd5c0, 0x2274, + 0xd5c1, 0x1162, + 0xd5c5, 0x2275, + 0xd5c6, 0x1167, + 0xd5c7, 0x2276, + 0xd5c8, 0x1169, + 0xd5ca, 0x2277, + 0xd5cc, 0x116d, + 0xd5cd, 0x2279, + 0xd5ce, 0x116f, + 0xd5d4, 0x227a, + 0xd5d5, 0x1176, + 0xd5dd, 0x227b, + 0xd5df, 0x1180, + 0xd5e0, 0x227d, + 0xd5e1, 0x1182, + 0xd5e2, 0x227e, + 0xd5e3, 0x1184, + 0xd5ea, 0x227f, + 0xd5ed, 0x118e, + 0xd5ef, 0x2282, + 0xd5f0, 0x1191, + 0xd5f2, 0x2283, + 0xd5f4, 0x1195, + 0xd5f7, 0x15eb, + 0xd5f8, 0x1199, + 0xd6a1, 0x2285, + 0xd6a5, 0x11a4, + 0xd6af, 0x2289, + 0xd6b1, 0x11b0, + 0xd6b4, 0x228b, + 0xd6b5, 0x11b4, + 0xd6bb, 0x228c, + 0xd6bc, 0x11bb, + 0xd6bd, 0x228d, + 0xd6be, 0x11bd, + 0xd6bf, 0x228e, + 0xd6c1, 0x11c0, + 0xd6c4, 0x2290, + 0xd6c5, 0x11c4, + 0xd6ca, 0x2291, + 0xd6cb, 0x11ca, + 0xd6cd, 0x2292, + 0xd6ce, 0x11cd, + 0xd6d3, 0x2293, + 0xd6d4, 0x11d3, + 0xd6d5, 0x2294, + 0xd6d8, 0x11d7, + 0xd6da, 0x2297, + 0xd6db, 0x11da, + 0xd6df, 0x2298, + 0xd6e0, 0x11df, + 0xd6e1, 0x2299, + 0xd6e2, 0x11e1, + 0xd6e5, 0x229a, + 0xd6e6, 0x11e5, + 0xd6e7, 0x229b, + 0xd6e9, 0x11e8, + 0xd6ee, 0x229d, + 0xd6f0, 0x11ef, + 0xd6f2, 0x229f, + 0xd6f3, 0x11f2, + 0xd6f5, 0x22a0, + 0xd6f7, 0x11f6, + 0xd6fc, 0x22a2, + 0xd7a1, 0x11fe, + 0xd7a4, 0x22a5, + 0xd7a5, 0x1202, + 0xd7a8, 0x22a6, + 0xd7ab, 0x1208, + 0xd7ac, 0x22a9, + 0xd7ad, 0x120a, + 0xd7ae, 0x22aa, + 0xd7b2, 0x120f, + 0xd7b3, 0x22ae, + 0xd7b5, 0x1212, + 0xd7b6, 0x22b0, + 0xd7b7, 0x1214, + 0xd7b8, 0x22b1, + 0xd7bd, 0x121a, + 0xd7c7, 0x22b6, + 0xd7c8, 0x1225, + 0xd7ca, 0x22b7, + 0xd7cb, 0x1228, + 0xd7d5, 0x22b8, + 0xd7d6, 0x1233, + 0xd7db, 0x22b9, + 0xd7df, 0x123c, + 0xd7e7, 0x22bd, + 0xd7e8, 0x1245, + 0xd7e9, 0x22be, + 0xd7eb, 0x1248, + 0xd8a1, 0x1257, + 0xd8c4, 0x22c0, + 0xd8c5, 0x127b, + 0xd8c7, 0x22c1, + 0xd8c8, 0x127e, + 0xd8c9, 0x22c2, + 0xd8ca, 0x1280, + 0xd8cc, 0x22c3, + 0xd8ce, 0x1284, + 0xd8d0, 0x22c5, + 0xd8d2, 0x1288, + 0xd8d3, 0x22c7, + 0xd8d4, 0x128a, + 0xd8d9, 0x22c8, + 0xd8da, 0x1290, + 0xd8db, 0x22c9, + 0xd8dd, 0x1293, + 0xd8f1, 0x22cb, + 0xd8f2, 0x12a8, + 0xd8f6, 0x22cc, + 0xd8f8, 0x12ae, + 0xd9a1, 0x12b5, + 0xd9ad, 0x22ce, + 0xd9ae, 0x12c2, + 0xd9af, 0x22cf, + 0xd9b0, 0x12c4, + 0xd9b1, 0x22d0, + 0xd9b4, 0x12c8, + 0xd9c7, 0x22d3, + 0xd9c8, 0x12dc, + 0xd9cd, 0x22d4, + 0xd9d1, 0x12e5, + 0xd9dd, 0x22d8, + 0xd9de, 0x12f2, + 0xd9e1, 0x22d9, + 0xd9e2, 0x12f6, + 0xd9e4, 0x22da, + 0xd9e5, 0x12f9, + 0xd9e6, 0x22db, + 0xd9e7, 0x12fb, + 0xd9ec, 0x22dc, + 0xd9ed, 0x1301, + 0xd9f4, 0x22dd, + 0xd9f6, 0x130a, + 0xdaa1, 0x1313, + 0xdaa5, 0x22df, + 0xdae0, 0x1352, + 0xdaea, 0x231a, + 0xdaeb, 0x135d, + 0xdaf7, 0x231b, + 0xdaf8, 0x136a, + 0xdaf9, 0x231c, + 0xdafa, 0x136c, + 0xdafe, 0x231d, + 0xdba1, 0x1371, + 0xdba3, 0x231e, + 0xdba4, 0x1374, + 0xdba6, 0x231f, + 0xdba7, 0x1377, + 0xdba9, 0x2320, + 0xdbab, 0x137b, + 0xdbbb, 0x2322, + 0xdbbc, 0x138c, + 0xdbbd, 0x2323, + 0xdbbe, 0x138e, + 0xdbcf, 0x2324, + 0xdbd0, 0x13a0, + 0xdbd1, 0x2325, + 0xdbd2, 0x13a2, + 0xdbdb, 0x2326, + 0xdbdc, 0x13ac, + 0xdbde, 0x2327, + 0xdbdf, 0x13af, + 0xdbe2, 0x2328, + 0xdbe3, 0x13b3, + 0xdbe4, 0x2329, + 0xdbe5, 0x13b5, + 0xdbeb, 0x232a, + 0xdbec, 0x13bc, + 0xdbee, 0x232b, + 0xdbef, 0x13bf, + 0xdbf1, 0x232c, + 0xdbf2, 0x13c2, + 0xdbf5, 0x232d, + 0xdbf8, 0x13c8, + 0xdca1, 0x13cf, + 0xdcbc, 0x2330, + 0xdcbd, 0x13eb, + 0xdcbf, 0x2331, + 0xdcc0, 0x13ee, + 0xdcc2, 0x2332, + 0xdcc3, 0x13f1, + 0xdcc8, 0x2333, + 0xdccb, 0x13f9, + 0xdcd1, 0x2336, + 0xdcd2, 0x1400, + 0xdcd7, 0x2337, + 0xdcd8, 0x1406, + 0xdce0, 0x2338, + 0xdce1, 0x140f, + 0xdce3, 0x2339, + 0xdce5, 0x1413, + 0xdce9, 0x233b, + 0xdceb, 0x1419, + 0xdcf1, 0x233d, + 0xdcf2, 0x1420, + 0xdcf6, 0x233e, + 0xdcf7, 0x1425, + 0xdcf9, 0x233f, + 0xdcfa, 0x1428, + 0xdcfd, 0x2340, + 0xdda1, 0x2342, + 0xdda2, 0x142e, + 0xdda3, 0x2343, + 0xdda8, 0x1434, + 0xddaa, 0x2348, + 0xddac, 0x1438, + 0xddb2, 0x234a, + 0xddb3, 0x143f, + 0xddb5, 0x234b, + 0xddb6, 0x1442, + 0xddba, 0x234c, + 0xddbc, 0x1448, + 0xddd3, 0x234e, + 0xddd4, 0x1460, + 0xdddb, 0x234f, + 0xdddc, 0x1468, + 0xddde, 0x2350, + 0xdddf, 0x146b, + 0xdde4, 0x2351, + 0xdde5, 0x1471, + 0xddeb, 0x2352, + 0xddec, 0x1478, + 0xddf1, 0x2353, + 0xddf2, 0x147e, + 0xddf6, 0x2354, + 0xddf8, 0x1484, + 0xddfc, 0x2356, + 0xddfd, 0x1489, + 0xddfe, 0x2357, + 0xdea1, 0x148b, + 0xdead, 0x2358, + 0xdeae, 0x1498, + 0xdeb4, 0x2359, + 0xdeb5, 0x149f, + 0xdeba, 0x235a, + 0xdebb, 0x14a5, + 0xdec6, 0x235b, + 0xdec7, 0x14b1, + 0xdecf, 0x235c, + 0xded0, 0x14ba, + 0xded1, 0x235d, + 0xded3, 0x14bd, + 0xded8, 0x235f, + 0xded9, 0x14c3, + 0xdee2, 0x2360, + 0xdee3, 0x14cd, + 0xdee8, 0x2361, + 0xdee9, 0x14d3, + 0xdeec, 0x2362, + 0xdeed, 0x14d7, + 0xdef3, 0x2363, + 0xdef4, 0x14de, + 0xdefc, 0x2364, + 0xdefd, 0x14e7, + 0xdfa1, 0x14e9, + 0xdfa2, 0x2365, + 0xdfa4, 0x14ec, + 0xdfa5, 0x2367, + 0xdfa6, 0x14ee, + 0xdfb4, 0x2368, + 0xdfb5, 0x14fd, + 0xdfbc, 0x2369, + 0xdfbe, 0x1506, + 0xdfbf, 0x236b, + 0xdfc0, 0x1508, + 0xdfc2, 0x236c, + 0xdfc4, 0x150c, + 0xdfcc, 0x236e, + 0xdfcd, 0x1515, + 0xdfd0, 0x236f, + 0xdfd1, 0x1519, + 0xdfd5, 0x2370, + 0xdfd6, 0x151e, + 0xdfd8, 0x2371, + 0xdfda, 0x1522, + 0xdfdc, 0x2373, + 0xdfdd, 0x1525, + 0xdfe0, 0x2374, + 0xdfe1, 0x1529, + 0xdfe2, 0x2375, + 0xdfe3, 0x152b, + 0xdfe6, 0x2376, + 0xdfe7, 0x152f, + 0xdfe9, 0x2377, + 0xdfea, 0x1532, + 0xdfeb, 0x2378, + 0xdfec, 0x1534, + 0xdfef, 0x2379, + 0xdff0, 0x1538, + 0xdff5, 0x237a, + 0xdff6, 0x153e, + 0xdff9, 0x237b, + 0xdffa, 0x1542, + 0xe0a1, 0x1547, + 0xe0b6, 0x237c, + 0xe0b8, 0x155e, + 0xe0bf, 0x237e, + 0xe0c0, 0x1566, + 0xe0c8, 0x237f, + 0xe0c9, 0x156f, + 0xe0ce, 0x2380, + 0xe0cf, 0x1575, + 0xe0d3, 0x2381, + 0xe0d4, 0x157a, + 0xe0e0, 0x2382, + 0xe0e1, 0x1587, + 0xe0f0, 0x2383, + 0xe0f1, 0x1597, + 0xe0f8, 0x2384, + 0xe0f9, 0x159f, + 0xe0fc, 0x2385, + 0xe1a1, 0x15a5, + 0xe1ab, 0x2388, + 0xe1ac, 0x15b0, + 0xe1ad, 0x2389, + 0xe1ae, 0x15b2, + 0xe1b0, 0x238a, + 0xe1b1, 0x15b5, + 0xe1b4, 0x238b, + 0xe1b5, 0x15b9, + 0xe1bb, 0x238c, + 0xe1bc, 0x15c0, + 0xe1bd, 0x238d, + 0xe1be, 0x15c2, + 0xe1c0, 0x238e, + 0xe1c2, 0x15c6, + 0xe1c9, 0x2390, + 0xe1ca, 0x15ce, + 0xe1d0, 0x2391, + 0xe1d1, 0x15d5, + 0xe1db, 0x2392, + 0xe1dc, 0x15e0, + 0xe1e1, 0x07aa, + 0xe1e2, 0x2393, + 0xe1e3, 0x15e7, + 0xe1e7, 0x1198, + 0xe1e8, 0x15ec, + 0xe1ee, 0x2394, + 0xe1f0, 0x15f4, + 0xe1f6, 0x2396, + 0xe1f7, 0x15fb, + 0xe1f8, 0x2397, + 0xe1f9, 0x15fd, + 0xe1fd, 0x2398, + 0xe1fe, 0x1602, + 0xe2a1, 0x1603, + 0xe2a4, 0x2399, + 0xe2a5, 0x1607, + 0xe2a8, 0x239a, + 0xe2a9, 0x160b, + 0xe2bb, 0x239b, + 0xe2c5, 0x10c5, + 0xe2c6, 0x23a5, + 0xe2cf, 0x1631, + 0xe2d0, 0x23ae, + 0xe2d1, 0x1633, + 0xe2d9, 0x23af, + 0xe2da, 0x163c, + 0xe2e3, 0x23b0, + 0xe2e5, 0x1647, + 0xe2e6, 0x23b2, + 0xe2e7, 0x1649, + 0xe2e9, 0x23b3, + 0xe2ec, 0x164e, + 0xe2f8, 0x23b6, + 0xe2f9, 0x165b, + 0xe2fa, 0x23b7, + 0xe2fe, 0x1660, + 0xe3a1, 0x1661, + 0xe3a2, 0x23bb, + 0xe3a3, 0x1663, + 0xe3a5, 0x23bc, + 0xe3a6, 0x1666, + 0xe3ab, 0x23bd, + 0xe3ac, 0x166c, + 0xe3b4, 0x23be, + 0xe3b5, 0x1675, + 0xe3c5, 0x23bf, + 0xe3dc, 0x169c, + 0xe3e3, 0x23d6, + 0xe3e4, 0x16a4, + 0xe3ed, 0x23d7, + 0xe3ee, 0x16ae, + 0xe3f1, 0x23d8, + 0xe3f3, 0x16b3, + 0xe3f8, 0x23da, + 0xe3f9, 0x16b9, + 0xe3fe, 0x23db, + 0xe4a1, 0x16bf, + 0xe4a4, 0x23dc, + 0xe4a6, 0x16c4, + 0xe4ab, 0x23de, + 0xe4ac, 0x16ca, + 0xe4af, 0x23df, + 0xe4b2, 0x16d0, + 0xe4b5, 0x23e2, + 0xe4b7, 0x16d5, + 0xe4c2, 0x23e4, + 0xe4c3, 0x16e1, + 0xe4c5, 0x23e5, + 0xe4c6, 0x16e4, + 0xe4c9, 0x23e6, + 0xe4ca, 0x16e8, + 0xe4d9, 0x23e7, + 0xe4da, 0x16f8, + 0xe4dc, 0x23e8, + 0xe4dd, 0x16fb, + 0xe4de, 0x23e9, + 0xe4df, 0x16fd, + 0xe4e4, 0x23ea, + 0xe4e5, 0x1703, + 0xe4eb, 0x23eb, + 0xe4ed, 0x170b, + 0xe4f2, 0x23ed, + 0xe4f3, 0x1711, + 0xe4fe, 0x23ee, + 0xe5a1, 0x171d, + 0xe5b0, 0x23ef, + 0xe5b1, 0x172d, + 0xe5b9, 0x23f0, + 0xe5ba, 0x1736, + 0xe5c7, 0x23f1, + 0xe5c8, 0x1744, + 0xe5c9, 0x23f2, + 0xe5ca, 0x1746, + 0xe5ce, 0x23f3, + 0xe5cf, 0x174b, + 0xe5f0, 0x23f4, + 0xe5f1, 0x176d, + 0xe5f2, 0x23f5, + 0xe5f3, 0x176f, + 0xe5fc, 0x23f6, + 0xe5fe, 0x177a, + 0xe6a1, 0x177b, + 0xe6a3, 0x23f8, + 0xe6a4, 0x177e, + 0xe6ab, 0x23f9, + 0xe6ad, 0x1787, + 0xe6ae, 0x23fb, + 0xe6af, 0x1789, + 0xe6b4, 0x23fc, + 0xe6b6, 0x1790, + 0xe6bf, 0x23fe, + 0xe6c0, 0x179a, + 0xe6c8, 0x23ff, + 0xe6ca, 0x17a4, + 0xe6cd, 0x2401, + 0xe6ce, 0x17a8, + 0xe6e0, 0x2402, + 0xe7a1, 0x2421, + 0xe7db, 0x1813, + 0xe7e1, 0x245b, + 0xe7e3, 0x181b, + 0xe7e7, 0x245d, + 0xe7e8, 0x1820, + 0xe7ef, 0x245e, + 0xe7f0, 0x1828, + 0xe7f4, 0x245f, + 0xe7f7, 0x182f, + 0xe8a1, 0x1837, + 0xe8a8, 0x2462, + 0xe8a9, 0x183f, + 0xe8ac, 0x2463, + 0xe8ad, 0x1843, + 0xe8b6, 0x2464, + 0xe8b7, 0x184d, + 0xe8b8, 0x2465, + 0xe8bb, 0x1851, + 0xe8bf, 0x2468, + 0xe8c1, 0x1857, + 0xe8c5, 0x246a, + 0xe8c6, 0x185c, + 0xe8c7, 0x246b, + 0xe8ca, 0x1860, + 0xe8ce, 0x246e, + 0xe8cf, 0x1865, + 0xe8d0, 0x246f, + 0xe8d1, 0x1867, + 0xe8d3, 0x2470, + 0xe8d4, 0x186a, + 0xe8dd, 0x2471, + 0xe8de, 0x1874, + 0xe8df, 0x2472, + 0xe8e0, 0x1876, + 0xe8e2, 0x2473, + 0xe8e4, 0x187a, + 0xe8e5, 0x2475, + 0xe8e6, 0x187c, + 0xe8e7, 0x2476, + 0xe8e8, 0x187e, + 0xe8eb, 0x2477, + 0xe8ec, 0x1882, + 0xe8ed, 0x2478, + 0xe8ee, 0x1884, + 0xe8ef, 0x2479, + 0xe8f0, 0x1886, + 0xe8f9, 0x247a, + 0xe8fa, 0x1890, + 0xe8fc, 0x247b, + 0xe8fe, 0x1894, + 0xe9a1, 0x247d, + 0xe9a2, 0x1896, + 0xe9ad, 0x247e, + 0xe9ae, 0x18a2, + 0xe9b4, 0x247f, + 0xe9b6, 0x18aa, + 0xe9b7, 0x2481, + 0xe9b8, 0x18ac, + 0xe9c4, 0x2482, + 0xe9c5, 0x18b9, + 0xe9c6, 0x2483, + 0xe9c7, 0x18bb, + 0xe9c9, 0x2484, + 0xe9ca, 0x18be, + 0xe9d6, 0x2485, + 0xe9d7, 0x18cb, + 0xe9da, 0x2486, + 0xe9db, 0x18cf, + 0xe9e4, 0x2487, + 0xe9e5, 0x18d9, + 0xe9e6, 0x2488, + 0xe9e8, 0x18dc, + 0xe9e9, 0x248a, + 0xe9ea, 0x18de, + 0xe9eb, 0x248b, + 0xe9ec, 0x18e0, + 0xe9ed, 0x248c, + 0xeaa1, 0x249e, + 0xeaa6, 0x18f8, + 0xeaa7, 0x24a3, + 0xeaa9, 0x18fb, + 0xeab1, 0x24a5, + 0xeab2, 0x1904, + 0xeabc, 0x24a6, + 0xeabd, 0x190f, + 0xeaca, 0x24a7, + 0xeacb, 0x191d, + 0xeacd, 0x24a8, + 0xeace, 0x1920, + 0xead3, 0x24a9, + 0xead4, 0x1926, + 0xeada, 0x24aa, + 0xeaf0, 0x1942, + 0xeba1, 0x1951, + 0xeba7, 0x24c0, + 0xeba8, 0x1958, + 0xebaa, 0x24c1, + 0xebab, 0x195b, + 0xebb2, 0x24c2, + 0xebb3, 0x1963, + 0xebb9, 0x24c3, + 0xebba, 0x196a, + 0xebca, 0x24c4, + 0xebcc, 0x197c, + 0xebcd, 0x24c6, + 0xebce, 0x197e, + 0xebd6, 0x24c7, + 0xebd7, 0x1987, + 0xebda, 0x24c8, + 0xebdb, 0x198b, + 0xebe1, 0x24c9, + 0xebe2, 0x1992, + 0xebf7, 0x24ca, + 0xebf8, 0x19a8, + 0xeca1, 0x19af, + 0xeca3, 0x24cb, + 0xeca4, 0x19b2, + 0xeca9, 0x24cc, + 0xecaf, 0x19bd, + 0xecb1, 0x24d2, + 0xecb2, 0x19c0, + 0xecb4, 0x24d3, + 0xecb6, 0x19c4, + 0xecbe, 0x24d5, + 0xecc0, 0x19ce, + 0xecc1, 0x24d7, + 0xecc2, 0x19d0, + 0xecc7, 0x24d8, + 0xecc8, 0x19d6, + 0xeccb, 0x24d9, + 0xeccc, 0x19da, + 0xece2, 0x24da, + 0xece3, 0x19f1, + 0xecf2, 0x24db, + 0xecf3, 0x1a01, + 0xecf5, 0x24dc, + 0xecf6, 0x1a04, + 0xecf8, 0x24dd, + 0xecf9, 0x1a07, + 0xeda1, 0x24de, + 0xeda2, 0x1a0e, + 0xeda8, 0x24df, + 0xeda9, 0x1a15, + 0xedaf, 0x24e0, + 0xedb1, 0x1a1d, + 0xedb4, 0x24e2, + 0xedb5, 0x1a21, + 0xedb6, 0x24e3, + 0xedb7, 0x1a23, + 0xedb8, 0x24e4, + 0xedb9, 0x1a25, + 0xedba, 0x24e5, + 0xedbb, 0x1a27, + 0xedbf, 0x24e6, + 0xedc0, 0x1a2c, + 0xedc2, 0x24e7, + 0xedc4, 0x1a30, + 0xedcc, 0x24e9, + 0xedce, 0x1a3a, + 0xedd3, 0x24eb, + 0xedd4, 0x1a40, + 0xedd7, 0x24ec, + 0xedd8, 0x1a44, + 0xede8, 0x24ed, + 0xede9, 0x1a55, + 0xedee, 0x24ee, + 0xedef, 0x1a5b, + 0xedf9, 0x24ef, + 0xedfb, 0x1a67, + 0xeea1, 0x1a6b, + 0xeebc, 0x24f1, + 0xeebd, 0x1a87, + 0xeebf, 0x24f2, + 0xeec0, 0x1a8a, + 0xeec4, 0x24f3, + 0xefa1, 0x252e, + 0xeff2, 0x1b1a, + 0xf0a1, 0x1b27, + 0xf0a3, 0x257f, + 0xf0a4, 0x1b2a, + 0xf0af, 0x2580, + 0xf0da, 0x1b60, + 0xf0dc, 0x25ab, + 0xf0de, 0x1b64, + 0xf0df, 0x25ad, + 0xf0e0, 0x1b66, + 0xf0e9, 0x25ae, + 0xf0ea, 0x1b70, + 0xf0ec, 0x25af, + 0xf0ed, 0x1b73, + 0xf0ef, 0x25b0, + 0xf0f0, 0x1b76, + 0xf0f7, 0x25b1, + 0xf0f8, 0x1b7e, + 0xf0f9, 0x25b2, + 0xf0fa, 0x1b80, + 0xf0fc, 0x25b3, + 0xf0fd, 0x1b83, + 0xf1a1, 0x1b85, + 0xf1a8, 0x25b4, + 0xf1a9, 0x1b8d, + 0xf1ab, 0x25b5, + 0xf1ac, 0x1b90, + 0xf1ae, 0x25b6, + 0xf1af, 0x1b93, + 0xf1b2, 0x25b7, + 0xf1b3, 0x1b97, + 0xf1bc, 0x25b8, + 0xf1bd, 0x1ba1, + 0xf1c0, 0x25b9, + 0xf1c1, 0x1ba5, + 0xf1c9, 0x25ba, + 0xf1ca, 0x1bae, + 0xf1cd, 0x25bb, + 0xf1ce, 0x1bb2, + 0xf1cf, 0x25bc, + 0xf1d1, 0x1bb5, + 0xf1da, 0x25be, + 0xf1db, 0x1bbf, + 0xf1dc, 0x25bf, + 0xf1dd, 0x1bc1, + 0xf1e4, 0x25c0, + 0xf1e5, 0x1bc9, + 0xf1ec, 0x25c1, + 0xf1ed, 0x1bd1, + 0xf1ef, 0x25c2, + 0xf1f0, 0x1bd4, + 0xf1f7, 0x25c3, + 0xf1f8, 0x1bdc, + 0xf1f9, 0x25c4, + 0xf1fa, 0x1bde, + 0xf1fc, 0x25c5, + 0xf2a1, 0x25c8, + 0xf2ae, 0x1bf0, + 0xf2b1, 0x25d5, + 0xf2b3, 0x1bf5, + 0xf2b9, 0x25d7, + 0xf2ba, 0x1bfc, + 0xf2c3, 0x25d8, + 0xf2c4, 0x1c06, + 0xf2c9, 0x25d9, + 0xf2ca, 0x1c0c, + 0xf2cc, 0x25da, + 0xf2ce, 0x1c10, + 0xf2cf, 0x25dc, + 0xf2d0, 0x1c12, + 0xf2d3, 0x25dd, + 0xf2d4, 0x1c16, + 0xf2e5, 0x25de, + 0xf2e6, 0x1c28, + 0xf2ee, 0x25df, + 0xf2ef, 0x1c31, + 0xf2f7, 0x25e0, + 0xf2f8, 0x1c3a, + 0xf2fd, 0x25e1, + 0xf2fe, 0x1c40, + 0xf3a1, 0x1c41, + 0xf3bf, 0x25e2, + 0xf3c0, 0x1c60, + 0xf3c6, 0x25e3, + 0xf3c7, 0x1c67, + 0xf3c8, 0x25e4, + 0xf3c9, 0x1c69, + 0xf3d6, 0x25e5, + 0xf3d7, 0x1c77, + 0xf3d9, 0x25e6, + 0xf3da, 0x1c7a, + 0xf3e5, 0x25e7, + 0xf3e7, 0x1c87, + 0xf3ea, 0x25e9, + 0xf3eb, 0x1c8b, + 0xf3ec, 0x25ea, + 0xf3ed, 0x1c8d, + 0xf3ef, 0x25eb, + 0xf3f0, 0x1c90, + 0xf3f1, 0x25ec, + 0xf3f2, 0x1c92, + 0xf3fd, 0x25ed, + 0xf3fe, 0x1c9e, + 0xf4a1, 0x1c9f, + 0xf4a5, 0x25ee, + 0xf4a6, 0x1ca4, + 0xf4af, 0x25ef, + 0xf4b0, 0x1cae, + 0xf4b5, 0x25f0, + 0xf4b6, 0x1cb4, + 0xf4c1, 0x25f1, + 0xf4c2, 0x1cc0, + 0xf4c7, 0x25f2, + 0xf4c8, 0x1cc6, + 0xf4cf, 0x25f3, + 0xf4d1, 0x1ccf, + 0xf4d6, 0x25f5, + 0xf4d7, 0x1cd5, + 0xf4ea, 0x25f6, + 0xf4eb, 0x1ce9, + 0xf4ef, 0x25f7, + 0xf4f0, 0x1cee, + 0xf4f5, 0x25f8, + 0xf4f6, 0x1cf4, + 0xf5a1, 0x1cfd, + 0xf5a6, 0x25f9, + 0xf5a8, 0x1d04, + 0xf5ba, 0x25fb, + 0xf5bc, 0x1d18, + 0xf5c4, 0x25fd, + 0xf5c5, 0x1d21, + 0xf5c8, 0x25fe, + 0xf5c9, 0x1d25, + 0xf5ce, 0x25ff, + 0xf5d0, 0x1d2c, + 0xf5d1, 0x2601, + 0xf5d3, 0x1d2f, + 0xf5d9, 0x2603, + 0xf5da, 0x1d36, + 0xf5dc, 0x2604, + 0xf5dd, 0x1d39, + 0xf5e6, 0x2605, + 0xf5e8, 0x1d44, + 0xf5ef, 0x2607, + 0xf5f0, 0x1d4c, + 0xf5f2, 0x2608, + 0xf5f3, 0x1d4f, + 0xf5fc, 0x2609, + 0xf5fd, 0x1d59, + 0xf6a1, 0x1d5b, + 0xf6a3, 0x260a, + 0xf6a4, 0x1d5e, + 0xf6a6, 0x260b, + 0xf6a7, 0x1d61, + 0xf6a8, 0x260c, + 0xf6a9, 0x1d63, + 0xf6ab, 0x260d, + 0xf6ac, 0x1d66, + 0xf6b0, 0x260e, + 0xf6b1, 0x1d6b, + 0xf6b3, 0x260f, + 0xf6bf, 0x1d79, + 0xf6c5, 0x261b, + 0xf6c6, 0x1d80, + 0xf6c7, 0x261c, + 0xf6c8, 0x1d82, + 0xf6c9, 0x261d, + 0xf6ca, 0x1d84, + 0xf6cf, 0x261e, + 0xf7a1, 0x264e, + 0xf7b0, 0x1dc8, + 0xf7b2, 0x265d, + 0xf7b4, 0x1dcc, + 0xf7b5, 0x265f, + 0xf7b6, 0x1dce, + 0xf7bd, 0x2660, + 0xf7be, 0x1dd6, + 0xf7c3, 0x2661, + 0xf7c4, 0x1ddc, + 0xf7c5, 0x2662, + 0xf7c7, 0x1ddf, + 0xf7ca, 0x2664, + 0xf7cc, 0x1de4, + 0xf7cf, 0x2666, + 0xf7d1, 0x1de9, + 0xf7de, 0x2668, + 0xf7df, 0x1df7, + 0xf7e1, 0x0ab9, + 0xf7e2, 0x1dfa, + 0xf7f2, 0x2669, + 0xf7f3, 0x1e0b, + 0xf7f5, 0x266a, + 0xf7f6, 0x1e0e, + 0xf8a1, 0x266b, + 0xf8a7, 0x04cc, + 0xf8a8, 0x050a, + 0xf8a9, 0x0518, + 0xf8aa, 0x2671, + 0xf8ac, 0x0594, + 0xf8ad, 0x05ce, + 0xf8ae, 0x2673, + 0xf8af, 0x05f6, + 0xf8b0, 0x2674, + 0xf8b2, 0x0653, + 0xf8b3, 0x067e, + 0xf8b4, 0x2676, + 0xf8b5, 0x06c4, + 0xf8b6, 0x2677, + 0xf8b8, 0x073c, + 0xf8b9, 0x2679, + 0xf8bb, 0x07c3, + 0xf8bc, 0x267b, + 0xf8c0, 0x082b, + 0xf8c1, 0x267f, + 0xf8c2, 0x084e, + 0xf8c3, 0x0869, + 0xf8c4, 0x2680, + 0xf8c6, 0x090c, + 0xf8c7, 0x2682, + 0xf8c9, 0x0971, + 0xf8ca, 0x2684, + 0xf8cb, 0x099a, + 0xf8cd, 0x2685, + 0xf8ce, 0x09da, + 0xf8cf, 0x2686, + 0xf8d0, 0x09fa, + 0xf8d1, 0x2687, + 0xf8dc, 0x0bda, + 0xf8dd, 0x0bdd, + 0xf8de, 0x0bea, + 0xf8df, 0x0bec, + 0xf8e0, 0x0bf2, + 0xf8e1, 0x2692, + 0xf8e6, 0x0c92, + 0xf8e7, 0x0d1a, + 0xf8e8, 0x0d8c, + 0xf8e9, 0x0dbe, + 0xf8ea, 0x2697, + 0xf8eb, 0x0dfb, + 0xf8ec, 0x2698, + 0xf8ef, 0x0e70, + 0xf8f0, 0x269b, + 0xf8f1, 0x0ea3, + 0xf8f2, 0x269c, + 0xf8f8, 0x103d, + 0xf8f9, 0x10d9, + 0xf8fa, 0x26a2, + 0xf8fc, 0x10fb, + 0xf8fd, 0x1109, + 0xf8fe, 0x26a4, + 0xf9a1, 0x11a1, + 0xf9a2, 0x26a5, + 0xf9a3, 0x11ba, + 0xf9a4, 0x26a6, + 0xf9a6, 0x11d5, + 0xf9a7, 0x26a8, + 0xf9a8, 0x11fd, + 0xf9a9, 0x1219, + 0xa1a2, 0x023f, + 0xa1a3, 0x023e, + 0xa1aa, 0x0256, + 0xa1ab, 0x1e18, + 0xa1ad, 0x0257, + 0xa1b2, 0x0246, + 0xa1fe, 0x1e1a, + 0xa3a1, 0x0242, + 0xa3a8, 0x0244, + 0xa3ac, 0x023d, + 0xa3ae, 0x1e1b, + 0xa3ba, 0x0240, + 0xa3bd, 0x1e1c, + 0xa3bf, 0x0243, + 0xa3db, 0x1e1d, + 0xa3dd, 0x1e1e, + 0xa3df, 0x0258, + 0xa3fb, 0x0254, + 0xa3fd, 0x0255, + 0xa3fe, 0x1e1f, + 0xffff, 0x0000 +}; + +static GfxFontEncoding16 gb12GBTEUCVEnc16 = { + 1, + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 }, + { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1e24, 0x032e, 0x032f, 0x0330, 0x0331, 0x0332, 0x0333, 0x0334, + 0x0335, 0x0336, 0x0337, 0x0338, 0x0339, 0x033a, 0x033b, 0x033c, + 0x033d, 0x033e, 0x033f, 0x0340, 0x0341, 0x0342, 0x0343, 0x0344, + 0x0345, 0x0346, 0x0347, 0x0348, 0x0349, 0x034a, 0x034b, 0x034c, + 0x034d, 0x034e, 0x034f, 0x0350, 0x0351, 0x0352, 0x0353, 0x0354, + 0x0355, 0x0356, 0x0357, 0x0358, 0x0359, 0x035a, 0x035b, 0x035c, + 0x035d, 0x035e, 0x035f, 0x0360, 0x0361, 0x0362, 0x0363, 0x0364, + 0x0365, 0x0366, 0x0367, 0x0368, 0x0369, 0x036a, 0x036b, 0x036c, + 0x036d, 0x036e, 0x036f, 0x0370, 0x0371, 0x0372, 0x0373, 0x0374, + 0x0375, 0x0376, 0x0377, 0x0378, 0x0379, 0x037a, 0x037b, 0x037c, + 0x037d, 0x037e, 0x037f, 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, + 0x0385, 0x0386, 0x0387, 0x0388, 0x0389, 0x038a, 0x038b, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, + gb12GBTEUCVMap2, 2303 +}; + +static Gushort gb12GBTHMap2[4566] = { + 0x0000, 0x0000, + 0x2121, 0x0060, + 0x2231, 0x00be, + 0x2265, 0x00f0, + 0x2271, 0x00fa, + 0x2321, 0x0106, + 0x2421, 0x0164, + 0x2521, 0x01b7, + 0x2621, 0x020d, + 0x2641, 0x0225, + 0x2721, 0x025a, + 0x2751, 0x027b, + 0x2821, 0x029c, + 0x2845, 0x02bc, + 0x2924, 0x02e2, + 0x2a21, 0x032e, + 0x2b21, 0x038c, + 0x3021, 0x03ac, + 0x3028, 0x1e25, + 0x3029, 0x03b4, + 0x302a, 0x1e26, + 0x302b, 0x03b6, + 0x302d, 0x1e27, + 0x302f, 0x03ba, + 0x3039, 0x1e29, + 0x303a, 0x03c5, + 0x3040, 0x1e2a, + 0x3041, 0x03cc, + 0x3053, 0x1e2b, + 0x3054, 0x03df, + 0x3055, 0x1e2c, + 0x3056, 0x03e1, + 0x305a, 0x1e2d, + 0x305b, 0x03e6, + 0x305c, 0x1e2e, + 0x305d, 0x03e8, + 0x3064, 0x1e2f, + 0x3065, 0x03f0, + 0x306c, 0x1e30, + 0x306e, 0x03f9, + 0x306f, 0x1e32, + 0x3070, 0x03fb, + 0x3073, 0x1e33, + 0x3074, 0x03ff, + 0x3077, 0x1e34, + 0x3078, 0x0403, + 0x3079, 0x1e35, + 0x307a, 0x0405, + 0x3121, 0x040a, + 0x3125, 0x1e36, + 0x3127, 0x0410, + 0x3128, 0x1e38, + 0x3129, 0x0412, + 0x312b, 0x1e39, + 0x312c, 0x0415, + 0x3132, 0x1e3a, + 0x3133, 0x041c, + 0x3134, 0x1e3b, + 0x3136, 0x041f, + 0x3137, 0x1e3d, + 0x313a, 0x0423, + 0x3141, 0x1e40, + 0x3142, 0x042b, + 0x314a, 0x1e41, + 0x314b, 0x0434, + 0x314f, 0x1e42, + 0x3151, 0x043a, + 0x3152, 0x1e44, + 0x3153, 0x043c, + 0x3155, 0x1e45, + 0x3156, 0x043f, + 0x315f, 0x1e46, + 0x3162, 0x044b, + 0x3164, 0x1e49, + 0x3165, 0x044e, + 0x3167, 0x1e4a, + 0x3169, 0x0452, + 0x316a, 0x1e4c, + 0x316b, 0x0454, + 0x316e, 0x1e4d, + 0x316f, 0x0458, + 0x3171, 0x1e4e, + 0x3172, 0x045b, + 0x3174, 0x1e4f, + 0x3178, 0x0461, + 0x317d, 0x1e53, + 0x317e, 0x0467, + 0x3221, 0x0468, + 0x3226, 0x1e54, + 0x3228, 0x046f, + 0x322c, 0x1e56, + 0x322d, 0x0474, + 0x3235, 0x1e57, + 0x3236, 0x047d, + 0x3239, 0x1e58, + 0x323a, 0x0481, + 0x3246, 0x1e59, + 0x3247, 0x048e, + 0x324e, 0x1e5a, + 0x3258, 0x049f, + 0x325e, 0x1e64, + 0x325f, 0x04a6, + 0x3260, 0x1e65, + 0x3261, 0x04a8, + 0x3262, 0x1e66, + 0x3264, 0x04ab, + 0x326f, 0x1e68, + 0x3270, 0x04b7, + 0x3273, 0x1e69, + 0x327d, 0x04c4, + 0x3321, 0x1e73, + 0x3323, 0x04c8, + 0x3324, 0x1e75, + 0x3328, 0x04cd, + 0x3329, 0x1e79, + 0x332a, 0x04cf, + 0x332e, 0x1e7a, + 0x332f, 0x04d4, + 0x3335, 0x1e7b, + 0x3336, 0x04db, + 0x3339, 0x1e7c, + 0x333a, 0x04df, + 0x333e, 0x1e7d, + 0x333f, 0x04e4, + 0x3342, 0x1e7e, + 0x3343, 0x04e8, + 0x3344, 0x1e7f, + 0x3345, 0x04ea, + 0x3346, 0x1e80, + 0x3347, 0x04ec, + 0x334d, 0x1e81, + 0x334e, 0x04f3, + 0x334f, 0x1e82, + 0x3350, 0x04f5, + 0x3352, 0x1e83, + 0x3353, 0x04f8, + 0x3359, 0x1e84, + 0x335a, 0x04ff, + 0x335b, 0x1e85, + 0x335c, 0x0501, + 0x335d, 0x1e86, + 0x335e, 0x0503, + 0x3363, 0x1e87, + 0x3364, 0x0509, + 0x3365, 0x1e88, + 0x3367, 0x050c, + 0x3368, 0x1e8a, + 0x3369, 0x050e, + 0x336b, 0x1e8b, + 0x336d, 0x0512, + 0x336f, 0x1e8d, + 0x3370, 0x0515, + 0x3371, 0x1e8e, + 0x3372, 0x0517, + 0x3373, 0x1e8f, + 0x3374, 0x0519, + 0x337a, 0x1e90, + 0x337c, 0x0521, + 0x3421, 0x1e92, + 0x3423, 0x0526, + 0x3425, 0x1e94, + 0x3427, 0x052a, + 0x342b, 0x1e96, + 0x342c, 0x052f, + 0x342f, 0x1e97, + 0x3430, 0x0533, + 0x3433, 0x1e98, + 0x3435, 0x0538, + 0x3438, 0x1e9a, + 0x3439, 0x053c, + 0x343f, 0x1e9b, + 0x3440, 0x0543, + 0x3442, 0x1e9c, + 0x3443, 0x0546, + 0x3447, 0x1e9d, + 0x3448, 0x054b, + 0x344a, 0x1e9e, + 0x344b, 0x054e, + 0x344d, 0x1e9f, + 0x344e, 0x0551, + 0x344f, 0x1ea0, + 0x3450, 0x0553, + 0x3453, 0x1ea1, + 0x3455, 0x0558, + 0x345a, 0x1ea3, + 0x345b, 0x055e, + 0x345c, 0x1ea4, + 0x345d, 0x0560, + 0x346d, 0x1ea5, + 0x346e, 0x0571, + 0x346f, 0x1ea6, + 0x3470, 0x0573, + 0x3478, 0x1ea7, + 0x3479, 0x057c, + 0x347b, 0x1ea8, + 0x347c, 0x057f, + 0x3521, 0x0582, + 0x3523, 0x1ea9, + 0x3524, 0x0585, + 0x3525, 0x1eaa, + 0x3529, 0x058a, + 0x352c, 0x1eae, + 0x352d, 0x058e, + 0x352e, 0x1eaf, + 0x3530, 0x0591, + 0x3531, 0x1eb1, + 0x3536, 0x0597, + 0x3537, 0x1eb6, + 0x3538, 0x0599, + 0x353a, 0x1eb7, + 0x353d, 0x059e, + 0x3546, 0x1eba, + 0x3547, 0x05a8, + 0x354b, 0x1ebb, + 0x354c, 0x05ad, + 0x3550, 0x1ebc, + 0x3551, 0x05b2, + 0x3553, 0x1ebd, + 0x3554, 0x05b5, + 0x355d, 0x1ebe, + 0x3560, 0x05c1, + 0x3563, 0x1ec1, + 0x3564, 0x05c5, + 0x3566, 0x1ec2, + 0x3568, 0x05c9, + 0x356d, 0x1ec4, + 0x356e, 0x05cf, + 0x3576, 0x1ec5, + 0x3578, 0x05d9, + 0x357d, 0x1ec7, + 0x357e, 0x05df, + 0x3621, 0x05e0, + 0x3624, 0x1ec8, + 0x3626, 0x05e5, + 0x3627, 0x1eca, + 0x3628, 0x05e7, + 0x3629, 0x1ecb, + 0x362a, 0x05e9, + 0x362b, 0x1ecc, + 0x362c, 0x05eb, + 0x362f, 0x1ecd, + 0x3631, 0x05f0, + 0x3633, 0x1ecf, + 0x3634, 0x05f3, + 0x3637, 0x1ed0, + 0x3638, 0x05f7, + 0x363f, 0x1ed1, + 0x3642, 0x0601, + 0x3644, 0x1ed4, + 0x3645, 0x0604, + 0x3646, 0x1ed5, + 0x3647, 0x0606, + 0x364d, 0x1ed6, + 0x364e, 0x060d, + 0x364f, 0x1ed7, + 0x3651, 0x0610, + 0x3653, 0x1ed9, + 0x3655, 0x0614, + 0x3656, 0x1edb, + 0x3657, 0x0616, + 0x3659, 0x1edc, + 0x365a, 0x0619, + 0x365b, 0x1edd, + 0x365c, 0x061b, + 0x3661, 0x1ede, + 0x3662, 0x0621, + 0x3669, 0x1edf, + 0x366a, 0x0629, + 0x366c, 0x1ee0, + 0x366d, 0x062c, + 0x366e, 0x1ee1, + 0x3670, 0x062f, + 0x3671, 0x1ee3, + 0x3672, 0x0631, + 0x3676, 0x1ee4, + 0x3677, 0x0636, + 0x3679, 0x1ee5, + 0x367a, 0x0639, + 0x367b, 0x1ee6, + 0x367d, 0x063c, + 0x3721, 0x1ee8, + 0x3724, 0x0641, + 0x3727, 0x1eeb, + 0x3728, 0x0645, + 0x372f, 0x1eec, + 0x3731, 0x064e, + 0x3733, 0x1eee, + 0x3734, 0x0651, + 0x3736, 0x1eef, + 0x3738, 0x0655, + 0x3739, 0x1ef1, + 0x373a, 0x0657, + 0x3743, 0x1ef2, + 0x3745, 0x0662, + 0x3749, 0x1ef4, + 0x374a, 0x0667, + 0x374c, 0x1ef5, + 0x374d, 0x066a, + 0x374f, 0x1ef6, + 0x3750, 0x066d, + 0x3751, 0x1ef7, + 0x3752, 0x066f, + 0x3757, 0x1ef8, + 0x3759, 0x0676, + 0x375c, 0x1efa, + 0x375d, 0x067a, + 0x375f, 0x1efb, + 0x3762, 0x067f, + 0x3763, 0x1efe, + 0x3764, 0x0681, + 0x3766, 0x1eff, + 0x3769, 0x0686, + 0x376b, 0x1f02, + 0x376e, 0x068b, + 0x376f, 0x1f05, + 0x3770, 0x068d, + 0x3774, 0x1f06, + 0x3775, 0x0692, + 0x3778, 0x1f07, + 0x3779, 0x0696, + 0x3821, 0x069c, + 0x3827, 0x1f08, + 0x3829, 0x06a4, + 0x3833, 0x1f0a, + 0x3835, 0x06b0, + 0x383a, 0x1f0c, + 0x383b, 0x06b6, + 0x383c, 0x1f0d, + 0x383d, 0x06b8, + 0x383e, 0x1f0e, + 0x3840, 0x06bb, + 0x3843, 0x1f10, + 0x3844, 0x06bf, + 0x3846, 0x1f11, + 0x3848, 0x06c3, + 0x3849, 0x1f13, + 0x384a, 0x06c5, + 0x384f, 0x1f14, + 0x3850, 0x06cb, + 0x3853, 0x1f15, + 0x3857, 0x06d2, + 0x3859, 0x1f19, + 0x385b, 0x06d6, + 0x3864, 0x1f1b, + 0x3865, 0x06e0, + 0x3869, 0x1f1c, + 0x386a, 0x06e5, + 0x386b, 0x1f1d, + 0x386c, 0x06e7, + 0x3873, 0x1f1e, + 0x3874, 0x06ef, + 0x3875, 0x1f1f, + 0x3877, 0x06f2, + 0x3878, 0x1f21, + 0x3879, 0x06f4, + 0x3921, 0x06fa, + 0x3928, 0x1f22, + 0x3929, 0x0702, + 0x392e, 0x1f23, + 0x392f, 0x0708, + 0x3931, 0x1f24, + 0x3932, 0x070b, + 0x3933, 0x1f25, + 0x3934, 0x070d, + 0x3935, 0x1f26, + 0x3936, 0x070f, + 0x3939, 0x1f27, + 0x393b, 0x0714, + 0x3946, 0x1f29, + 0x3947, 0x0720, + 0x394b, 0x1f2a, + 0x394c, 0x0725, + 0x3950, 0x1f2b, + 0x3951, 0x072a, + 0x3958, 0x1f2c, + 0x3959, 0x0732, + 0x395b, 0x1f2d, + 0x395c, 0x0735, + 0x395d, 0x1f2e, + 0x395e, 0x0737, + 0x395f, 0x1f2f, + 0x3960, 0x0739, + 0x3961, 0x1f30, + 0x3962, 0x073b, + 0x3963, 0x1f31, + 0x3964, 0x073d, + 0x3966, 0x1f32, + 0x3967, 0x0740, + 0x3969, 0x1f33, + 0x396d, 0x0746, + 0x396e, 0x1f37, + 0x396f, 0x0748, + 0x3971, 0x1f38, + 0x3972, 0x074b, + 0x3973, 0x1f39, + 0x3976, 0x074f, + 0x3978, 0x1f3c, + 0x3979, 0x0752, + 0x397a, 0x1f3d, + 0x397b, 0x0754, + 0x397d, 0x1f3e, + 0x397e, 0x0757, + 0x3a21, 0x0758, + 0x3a27, 0x1f3f, + 0x3a28, 0x075f, + 0x3a2b, 0x1f40, + 0x3a2c, 0x0763, + 0x3a3a, 0x1f41, + 0x3a3b, 0x0772, + 0x3a45, 0x1f42, + 0x3a46, 0x077d, + 0x3a52, 0x1f43, + 0x3a53, 0x078a, + 0x3a57, 0x1f44, + 0x3a59, 0x0790, + 0x3a64, 0x1f46, + 0x3a65, 0x079c, + 0x3a68, 0x1f47, + 0x3a69, 0x07a0, + 0x3a6c, 0x1f48, + 0x3a6d, 0x07a4, + 0x3a73, 0x15e5, + 0x3a74, 0x07ab, + 0x3a78, 0x1f49, + 0x3a79, 0x07b0, + 0x3b21, 0x07b6, + 0x3b24, 0x1f4a, + 0x3b25, 0x07ba, + 0x3b26, 0x1f4b, + 0x3b27, 0x07bc, + 0x3b29, 0x1f4c, + 0x3b2b, 0x07c0, + 0x3b2d, 0x1f4e, + 0x3b2f, 0x07c4, + 0x3b30, 0x1f50, + 0x3b31, 0x07c6, + 0x3b33, 0x1f51, + 0x3b34, 0x07c9, + 0x3b35, 0x1f52, + 0x3b38, 0x07cd, + 0x3b39, 0x1f55, + 0x3b3b, 0x07d0, + 0x3b51, 0x1f57, + 0x3b52, 0x07e7, + 0x3b53, 0x1f58, + 0x3b55, 0x07ea, + 0x3b5f, 0x1f5a, + 0x3b68, 0x07fd, + 0x3b6b, 0x1f63, + 0x3b6c, 0x0801, + 0x3b71, 0x1f64, + 0x3b72, 0x0807, + 0x3b75, 0x1f65, + 0x3b78, 0x080d, + 0x3b7a, 0x1f68, + 0x3b7b, 0x0810, + 0x3b7d, 0x1f69, + 0x3b7e, 0x0813, + 0x3c21, 0x0814, + 0x3c22, 0x1f6a, + 0x3c23, 0x0816, + 0x3c25, 0x1f6b, + 0x3c27, 0x081a, + 0x3c28, 0x1f6d, + 0x3c2a, 0x081d, + 0x3c2b, 0x1f6f, + 0x3c2c, 0x081f, + 0x3c2d, 0x1f70, + 0x3c2e, 0x0821, + 0x3c36, 0x1f71, + 0x3c39, 0x082c, + 0x3c3b, 0x1f74, + 0x3c3c, 0x082f, + 0x3c41, 0x1f75, + 0x3c42, 0x0835, + 0x3c43, 0x1f76, + 0x3c44, 0x0837, + 0x3c46, 0x1f77, + 0x3c48, 0x083b, + 0x3c4a, 0x1f79, + 0x3c4b, 0x083e, + 0x3c4c, 0x1f7a, + 0x3c4e, 0x0841, + 0x3c50, 0x1f7c, + 0x3c51, 0x0844, + 0x3c54, 0x1f7d, + 0x3c57, 0x084a, + 0x3c58, 0x1f80, + 0x3c59, 0x084c, + 0x3c5b, 0x1f81, + 0x3c5c, 0x084f, + 0x3c5d, 0x1f82, + 0x3c5e, 0x0851, + 0x3c5f, 0x1f83, + 0x3c62, 0x0855, + 0x3c63, 0x1f86, + 0x3c65, 0x0858, + 0x3c68, 0x1f88, + 0x3c69, 0x085c, + 0x3c6a, 0x1f89, + 0x3c6d, 0x0860, + 0x3c6f, 0x1f8c, + 0x3c74, 0x0867, + 0x3c76, 0x1f91, + 0x3c7d, 0x0870, + 0x3d21, 0x0872, + 0x3d22, 0x1f98, + 0x3d28, 0x0879, + 0x3d2b, 0x1f9e, + 0x3d2d, 0x087e, + 0x3d2f, 0x1fa0, + 0x3d33, 0x0884, + 0x3d34, 0x1fa4, + 0x3d35, 0x0886, + 0x3d3a, 0x1fa5, + 0x3d3b, 0x088c, + 0x3d3d, 0x1fa6, + 0x3d40, 0x0891, + 0x3d41, 0x1fa9, + 0x3d45, 0x0896, + 0x3d48, 0x1fad, + 0x3d4b, 0x089c, + 0x3d4e, 0x1fb0, + 0x3d50, 0x08a1, + 0x3d57, 0x1fb2, + 0x3d58, 0x08a9, + 0x3d5a, 0x1fb3, + 0x3d5b, 0x08ac, + 0x3d60, 0x1fb4, + 0x3d62, 0x08b3, + 0x3d6b, 0x1fb6, + 0x3d6c, 0x08bd, + 0x3d74, 0x1fb7, + 0x3d79, 0x08ca, + 0x3d7d, 0x1fbc, + 0x3d7e, 0x08cf, + 0x3e21, 0x1fbd, + 0x3e23, 0x08d2, + 0x3e25, 0x1fbf, + 0x3e26, 0x08d5, + 0x3e28, 0x1fc0, + 0x3e29, 0x08d8, + 0x3e2a, 0x1fc1, + 0x3e2b, 0x08da, + 0x3e2d, 0x1fc2, + 0x3e2e, 0x08dd, + 0x3e31, 0x1fc3, + 0x3e32, 0x08e1, + 0x3e35, 0x1fc4, + 0x3e38, 0x08e7, + 0x3e3a, 0x1fc7, + 0x3e3b, 0x08ea, + 0x3e40, 0x1fc8, + 0x3e41, 0x08f0, + 0x3e49, 0x1fc9, + 0x3e4a, 0x08f9, + 0x3e54, 0x1fca, + 0x3e55, 0x0904, + 0x3e59, 0x1fcb, + 0x3e5a, 0x0909, + 0x3e5d, 0x1fcc, + 0x3e5e, 0x090d, + 0x3e62, 0x1fcd, + 0x3e63, 0x0912, + 0x3e65, 0x1fce, + 0x3e66, 0x0915, + 0x3e67, 0x1fcf, + 0x3e68, 0x0917, + 0x3e69, 0x1fd0, + 0x3e6a, 0x0919, + 0x3e6e, 0x1fd1, + 0x3e6f, 0x091e, + 0x3e75, 0x1fd2, + 0x3e76, 0x0925, + 0x3e77, 0x1fd3, + 0x3e79, 0x0928, + 0x3e7b, 0x1fd5, + 0x3e7d, 0x092c, + 0x3f21, 0x092e, + 0x3f25, 0x1fd7, + 0x3f26, 0x0933, + 0x3f2a, 0x1fd8, + 0x3f2b, 0x0938, + 0x3f2d, 0x1fd9, + 0x3f2e, 0x093b, + 0x3f45, 0x1fda, + 0x3f46, 0x0953, + 0x3f47, 0x1fdb, + 0x3f48, 0x0955, + 0x3f4e, 0x1fdc, + 0x3f4f, 0x095c, + 0x3f51, 0x1fdd, + 0x3f53, 0x0960, + 0x3f59, 0x1fdf, + 0x3f5a, 0x0967, + 0x3f62, 0x1fe0, + 0x3f65, 0x0972, + 0x3f69, 0x1fe3, + 0x3f6a, 0x0977, + 0x3f6b, 0x1fe4, + 0x3f6c, 0x0979, + 0x3f6d, 0x1fe5, + 0x3f6e, 0x097b, + 0x3f73, 0x1fe6, + 0x3f74, 0x0981, + 0x3f75, 0x1fe7, + 0x3f76, 0x0983, + 0x3f77, 0x1fe8, + 0x3f78, 0x0985, + 0x3f79, 0x1fe9, + 0x3f7b, 0x0988, + 0x4021, 0x1feb, + 0x4022, 0x098d, + 0x4023, 0x1fec, + 0x4024, 0x098f, + 0x4029, 0x1fed, + 0x402a, 0x0995, + 0x402b, 0x1fee, + 0x402c, 0x0997, + 0x402f, 0x1fef, + 0x4031, 0x099c, + 0x4033, 0x1ff1, + 0x4037, 0x09a2, + 0x4038, 0x1ff5, + 0x4045, 0x09b0, + 0x404c, 0x2002, + 0x404e, 0x09b9, + 0x4054, 0x2004, + 0x4055, 0x09c0, + 0x4056, 0x2005, + 0x4057, 0x09c2, + 0x4058, 0x2006, + 0x4059, 0x09c4, + 0x405d, 0x2007, + 0x405e, 0x09c9, + 0x4060, 0x2008, + 0x4061, 0x09cc, + 0x4069, 0x2009, + 0x406a, 0x09d5, + 0x406b, 0x200a, + 0x406d, 0x09d8, + 0x406f, 0x200c, + 0x4072, 0x09dd, + 0x4076, 0x200f, + 0x407b, 0x09e6, + 0x4121, 0x09ea, + 0x4124, 0x2014, + 0x4126, 0x09ef, + 0x4129, 0x2016, + 0x412e, 0x09f7, + 0x412f, 0x201b, + 0x4139, 0x0a02, + 0x413d, 0x2025, + 0x413f, 0x0a08, + 0x4142, 0x2027, + 0x4143, 0x0a0c, + 0x4146, 0x2028, + 0x4147, 0x0a10, + 0x4149, 0x2029, + 0x414a, 0x0a13, + 0x414d, 0x202a, + 0x414e, 0x0a17, + 0x4154, 0x202b, + 0x4155, 0x0a1e, + 0x4159, 0x202c, + 0x415c, 0x0a25, + 0x415e, 0x202f, + 0x415f, 0x0a28, + 0x4164, 0x2030, + 0x4166, 0x0a2f, + 0x4169, 0x2032, + 0x416a, 0x0a33, + 0x416b, 0x2033, + 0x416d, 0x0a36, + 0x4173, 0x2035, + 0x4174, 0x0a3d, + 0x4175, 0x2036, + 0x4176, 0x0a3f, + 0x417a, 0x2037, + 0x417e, 0x0a47, + 0x4221, 0x0a48, + 0x4222, 0x203b, + 0x4229, 0x0a50, + 0x422b, 0x2042, + 0x4234, 0x0a5b, + 0x4238, 0x204b, + 0x4239, 0x0a60, + 0x423c, 0x204c, + 0x423e, 0x0a65, + 0x423f, 0x204e, + 0x4240, 0x0a67, + 0x4241, 0x204f, + 0x4242, 0x0a69, + 0x4245, 0x2050, + 0x4248, 0x0a6f, + 0x424b, 0x2053, + 0x4251, 0x0a78, + 0x4252, 0x2059, + 0x4253, 0x0a7a, + 0x4255, 0x205a, + 0x425d, 0x0a84, + 0x425e, 0x2062, + 0x4263, 0x0a8a, + 0x4266, 0x2067, + 0x4269, 0x0a90, + 0x426a, 0x206a, + 0x426f, 0x0a96, + 0x4270, 0x206f, + 0x4271, 0x0a98, + 0x4272, 0x2070, + 0x4276, 0x0a9d, + 0x4277, 0x2074, + 0x427b, 0x0aa2, + 0x4321, 0x2078, + 0x4322, 0x0aa7, + 0x432a, 0x2079, + 0x432b, 0x0ab0, + 0x432d, 0x207a, + 0x432e, 0x0ab3, + 0x4333, 0x207b, + 0x4334, 0x1df9, + 0x4335, 0x0aba, + 0x433e, 0x207c, + 0x433f, 0x0ac4, + 0x4345, 0x207d, + 0x4348, 0x0acd, + 0x434c, 0x2080, + 0x434d, 0x0ad2, + 0x434e, 0x2081, + 0x434f, 0x0ad4, + 0x4355, 0x2082, + 0x4357, 0x0adc, + 0x4359, 0x2084, + 0x435a, 0x0adf, + 0x4360, 0x2085, + 0x4361, 0x0ae6, + 0x4365, 0x2086, + 0x4366, 0x0aeb, + 0x436d, 0x2087, + 0x436e, 0x0af3, + 0x4370, 0x2088, + 0x4371, 0x0af6, + 0x4375, 0x2089, + 0x4377, 0x0afc, + 0x4379, 0x208b, + 0x437b, 0x0b00, + 0x437d, 0x208d, + 0x437e, 0x0b03, + 0x4421, 0x0b04, + 0x4431, 0x208e, + 0x4432, 0x0b15, + 0x4436, 0x208f, + 0x4437, 0x0b1a, + 0x4446, 0x2090, + 0x4447, 0x0b2a, + 0x4449, 0x2091, + 0x444a, 0x0b2d, + 0x4451, 0x2092, + 0x4452, 0x0b35, + 0x4453, 0x2093, + 0x4457, 0x0b3a, + 0x4459, 0x2097, + 0x445a, 0x0b3d, + 0x4462, 0x2098, + 0x4463, 0x0b46, + 0x4465, 0x2099, + 0x4466, 0x0b49, + 0x446c, 0x209a, + 0x446d, 0x0b50, + 0x4470, 0x209b, + 0x4472, 0x0b55, + 0x4474, 0x209d, + 0x4475, 0x0b58, + 0x4476, 0x209e, + 0x4479, 0x0b5c, + 0x447b, 0x20a1, + 0x447d, 0x0b60, + 0x447e, 0x20a3, + 0x4521, 0x20a4, + 0x4523, 0x0b64, + 0x4525, 0x20a6, + 0x452a, 0x0b6b, + 0x4531, 0x20ab, + 0x4532, 0x0b73, + 0x4535, 0x20ac, + 0x4536, 0x0b77, + 0x4537, 0x20ad, + 0x453a, 0x0b7b, + 0x453b, 0x20b0, + 0x453c, 0x0b7d, + 0x453d, 0x20b1, + 0x453e, 0x0b7f, + 0x454c, 0x20b2, + 0x454d, 0x0b8e, + 0x4553, 0x20b3, + 0x4554, 0x0b95, + 0x4562, 0x20b4, + 0x4563, 0x0ba4, + 0x4567, 0x20b5, + 0x4568, 0x0ba9, + 0x4574, 0x20b6, + 0x4575, 0x0bb6, + 0x4621, 0x0bc0, + 0x462d, 0x20b7, + 0x462f, 0x0bce, + 0x4635, 0x20b9, + 0x4637, 0x0bd6, + 0x463b, 0x20bb, + 0x463c, 0x0bdb, + 0x463e, 0x20bc, + 0x463f, 0x0bde, + 0x4640, 0x20bd, + 0x4641, 0x0be0, + 0x4643, 0x20be, + 0x4645, 0x0be4, + 0x464b, 0x20c0, + 0x464e, 0x0bed, + 0x4653, 0x20c3, + 0x4654, 0x0bf3, + 0x4657, 0x20c4, + 0x4658, 0x0bf7, + 0x466a, 0x20c5, + 0x466c, 0x0c0b, + 0x466f, 0x20c7, + 0x4670, 0x0c0f, + 0x4671, 0x20c8, + 0x4672, 0x0c11, + 0x4674, 0x20c9, + 0x4675, 0x0c14, + 0x4678, 0x20ca, + 0x4679, 0x0c18, + 0x467d, 0x20cb, + 0x467e, 0x0c1d, + 0x4721, 0x0c1e, + 0x4723, 0x20cc, + 0x4724, 0x0c21, + 0x4725, 0x20cd, + 0x4727, 0x0c24, + 0x4728, 0x20cf, + 0x472a, 0x0c27, + 0x472b, 0x20d1, + 0x472c, 0x0c29, + 0x472e, 0x20d2, + 0x4730, 0x0c2d, + 0x4733, 0x20d4, + 0x4736, 0x0c33, + 0x4739, 0x20d7, + 0x473b, 0x0c38, + 0x473d, 0x20d9, + 0x473f, 0x0c3c, + 0x4740, 0x20db, + 0x4741, 0x0c3e, + 0x4742, 0x20dc, + 0x4743, 0x0c40, + 0x4745, 0x20dd, + 0x4746, 0x0c43, + 0x4747, 0x20de, + 0x4749, 0x0c46, + 0x474c, 0x20e0, + 0x474d, 0x0c4a, + 0x474f, 0x20e1, + 0x4750, 0x0c4d, + 0x4754, 0x20e2, + 0x4756, 0x0c53, + 0x4757, 0x20e4, + 0x4758, 0x0c55, + 0x475e, 0x20e5, + 0x475f, 0x0c5c, + 0x4761, 0x20e6, + 0x4764, 0x0c61, + 0x476a, 0x20e9, + 0x476f, 0x0c6c, + 0x4777, 0x20ee, + 0x4779, 0x0c76, + 0x477b, 0x20f0, + 0x477c, 0x0c79, + 0x477d, 0x20f1, + 0x477e, 0x0c7b, + 0x4821, 0x0c7c, + 0x4823, 0x20f2, + 0x4824, 0x0c7f, + 0x4827, 0x20f3, + 0x4829, 0x0c84, + 0x4830, 0x20f5, + 0x4831, 0x0c8c, + 0x4835, 0x20f6, + 0x4836, 0x0c91, + 0x4837, 0x20f7, + 0x4838, 0x0c93, + 0x4843, 0x20f8, + 0x4847, 0x0ca2, + 0x4848, 0x20fc, + 0x4849, 0x0ca4, + 0x484d, 0x20fd, + 0x484e, 0x0ca9, + 0x484f, 0x20fe, + 0x4850, 0x0cab, + 0x4852, 0x20ff, + 0x4853, 0x0cae, + 0x4859, 0x2100, + 0x485a, 0x0cb5, + 0x485e, 0x2101, + 0x485f, 0x0cba, + 0x486d, 0x2102, + 0x486e, 0x0cc9, + 0x4871, 0x2103, + 0x4874, 0x0ccf, + 0x4877, 0x2106, + 0x4879, 0x0cd4, + 0x487a, 0x2108, + 0x487b, 0x0cd6, + 0x487c, 0x2109, + 0x487d, 0x0cd8, + 0x4921, 0x210a, + 0x4922, 0x0cdb, + 0x4925, 0x210b, + 0x4926, 0x0cdf, + 0x4927, 0x210c, + 0x4929, 0x0ce2, + 0x492c, 0x210e, + 0x492d, 0x0ce6, + 0x4931, 0x210f, + 0x4932, 0x0ceb, + 0x4934, 0x2110, + 0x4935, 0x0cee, + 0x4938, 0x2111, + 0x493a, 0x0cf3, + 0x4941, 0x2113, + 0x4943, 0x0cfc, + 0x4944, 0x2115, + 0x4945, 0x0cfe, + 0x4949, 0x2116, + 0x494a, 0x0d03, + 0x494b, 0x2117, + 0x494c, 0x0d05, + 0x494d, 0x2118, + 0x494e, 0x0d07, + 0x4955, 0x2119, + 0x4956, 0x0d0f, + 0x495c, 0x211a, + 0x495d, 0x0d16, + 0x495e, 0x211b, + 0x495f, 0x0d18, + 0x4961, 0x211c, + 0x4962, 0x0d1b, + 0x4963, 0x211d, + 0x4964, 0x0d1d, + 0x4965, 0x211e, + 0x4966, 0x0d1f, + 0x4968, 0x211f, + 0x4969, 0x0d22, + 0x4970, 0x2120, + 0x4971, 0x0d2a, + 0x4973, 0x2121, + 0x4975, 0x0d2e, + 0x4976, 0x2123, + 0x4977, 0x0d30, + 0x4978, 0x2124, + 0x497a, 0x0d33, + 0x497e, 0x2126, + 0x4a21, 0x0d38, + 0x4a24, 0x2127, + 0x4a27, 0x0d3e, + 0x4a28, 0x212a, + 0x4a29, 0x0d40, + 0x4a2a, 0x212b, + 0x4a2c, 0x0d43, + 0x4a31, 0x212d, + 0x4a32, 0x0d49, + 0x4a34, 0x212e, + 0x4a37, 0x0d4e, + 0x4a3b, 0x2131, + 0x4a3c, 0x0d53, + 0x4a46, 0x2132, + 0x4a47, 0x0d5e, + 0x4a4a, 0x2133, + 0x4a4b, 0x0d62, + 0x4a4d, 0x2134, + 0x4a4f, 0x0d66, + 0x4a53, 0x2136, + 0x4a55, 0x0d6c, + 0x4a59, 0x2138, + 0x4a5a, 0x0d71, + 0x4a5e, 0x2139, + 0x4a5f, 0x0d76, + 0x4a60, 0x213a, + 0x4a61, 0x0d78, + 0x4a64, 0x213b, + 0x4a65, 0x0d7c, + 0x4a69, 0x213c, + 0x4a6b, 0x0d82, + 0x4a74, 0x213e, + 0x4a76, 0x0d8d, + 0x4a77, 0x2140, + 0x4a78, 0x0d8f, + 0x4a7a, 0x2141, + 0x4a7b, 0x0d92, + 0x4a7d, 0x2142, + 0x4a7e, 0x0d95, + 0x4b21, 0x0d96, + 0x4b27, 0x2143, + 0x4b28, 0x0d9d, + 0x4b2b, 0x2144, + 0x4b2c, 0x0da1, + 0x4b2d, 0x2145, + 0x4b2e, 0x0da3, + 0x4b33, 0x2146, + 0x4b34, 0x0da9, + 0x4b35, 0x2147, + 0x4b37, 0x0dac, + 0x4b38, 0x2149, + 0x4b39, 0x0dae, + 0x4b3f, 0x214a, + 0x4b40, 0x0db5, + 0x4b47, 0x214b, + 0x4b48, 0x0dbd, + 0x4b49, 0x214c, + 0x4b4d, 0x0dc2, + 0x4b4f, 0x2150, + 0x4b51, 0x0dc6, + 0x4b53, 0x2152, + 0x4b54, 0x0dc9, + 0x4b55, 0x2153, + 0x4b56, 0x0dcb, + 0x4b5f, 0x2154, + 0x4b61, 0x0dd6, + 0x4b64, 0x2156, + 0x4b65, 0x0dda, + 0x4b66, 0x2157, + 0x4b68, 0x0ddd, + 0x4b6a, 0x2159, + 0x4b6b, 0x0de0, + 0x4b6f, 0x215a, + 0x4b71, 0x0de6, + 0x4b75, 0x215c, + 0x4b77, 0x0dec, + 0x4b78, 0x215e, + 0x4b79, 0x0dee, + 0x4c21, 0x215f, + 0x4c23, 0x0df6, + 0x4c28, 0x2161, + 0x4c29, 0x0dfc, + 0x4c2c, 0x2162, + 0x4c2d, 0x0e00, + 0x4c2f, 0x2163, + 0x4c34, 0x0e07, + 0x4c37, 0x2168, + 0x4c39, 0x0e0c, + 0x4c3e, 0x216a, + 0x4c3f, 0x0e12, + 0x4c40, 0x216b, + 0x4c41, 0x0e14, + 0x4c4c, 0x216c, + 0x4c4d, 0x0e20, + 0x4c4e, 0x216d, + 0x4c4f, 0x0e22, + 0x4c50, 0x216e, + 0x4c51, 0x0e24, + 0x4c56, 0x216f, + 0x4c57, 0x0e2a, + 0x4c5a, 0x2170, + 0x4c5b, 0x0e2e, + 0x4c5c, 0x2171, + 0x4c5d, 0x0e30, + 0x4c60, 0x2172, + 0x4c61, 0x0e34, + 0x4c62, 0x2173, + 0x4c63, 0x0e36, + 0x4c65, 0x2174, + 0x4c66, 0x0e39, + 0x4c75, 0x2175, + 0x4c76, 0x0e49, + 0x4c79, 0x2176, + 0x4c7b, 0x0e4e, + 0x4c7c, 0x2178, + 0x4d21, 0x0e52, + 0x4d2d, 0x217b, + 0x4d2e, 0x0e5f, + 0x4d33, 0x217c, + 0x4d34, 0x0e65, + 0x4d37, 0x217d, + 0x4d38, 0x0e69, + 0x4d3c, 0x217e, + 0x4d3d, 0x0e6e, + 0x4d3f, 0x217f, + 0x4d40, 0x0e71, + 0x4d45, 0x2180, + 0x4d46, 0x0e77, + 0x4d47, 0x2181, + 0x4d48, 0x0e79, + 0x4d52, 0x2182, + 0x4d53, 0x0e84, + 0x4d54, 0x2183, + 0x4d57, 0x0e88, + 0x4d5d, 0x2186, + 0x4d5e, 0x0e8f, + 0x4d60, 0x2187, + 0x4d61, 0x0e92, + 0x4d64, 0x2188, + 0x4d66, 0x0e97, + 0x4d67, 0x218a, + 0x4d68, 0x0e99, + 0x4d72, 0x218b, + 0x4d73, 0x0ea4, + 0x4d78, 0x218c, + 0x4d79, 0x0eaa, + 0x4e21, 0x0eb0, + 0x4e24, 0x218d, + 0x4e26, 0x0eb5, + 0x4e27, 0x218f, + 0x4e28, 0x0eb7, + 0x4e2a, 0x2190, + 0x4e2e, 0x0ebd, + 0x4e30, 0x2194, + 0x4e32, 0x0ec1, + 0x4e33, 0x2196, + 0x4e34, 0x0ec3, + 0x4e3d, 0x2197, + 0x4e3e, 0x0ecd, + 0x4e40, 0x2198, + 0x4e41, 0x0ed0, + 0x4e45, 0x2199, + 0x4e47, 0x0ed6, + 0x4e48, 0x219b, + 0x4e49, 0x0ed8, + 0x4e4a, 0x219c, + 0x4e4b, 0x0eda, + 0x4e4e, 0x219d, + 0x4e52, 0x0ee1, + 0x4e58, 0x21a1, + 0x4e5b, 0x0eea, + 0x4e5c, 0x21a4, + 0x4e5d, 0x0eec, + 0x4e5e, 0x21a5, + 0x4e60, 0x0eef, + 0x4e6b, 0x21a7, + 0x4e6c, 0x0efb, + 0x4e6d, 0x21a8, + 0x4e6e, 0x0efd, + 0x4e71, 0x21a9, + 0x4e72, 0x0f01, + 0x4e73, 0x21aa, + 0x4e74, 0x0f03, + 0x4e7d, 0x21ab, + 0x4f21, 0x0f0e, + 0x4f2e, 0x21ad, + 0x4f2f, 0x0f1c, + 0x4f30, 0x21ae, + 0x4f31, 0x0f1e, + 0x4f33, 0x21af, + 0x4f34, 0x0f21, + 0x4f37, 0x21b0, + 0x4f39, 0x0f26, + 0x4f3a, 0x21b2, + 0x4f3b, 0x0f28, + 0x4f3d, 0x21b3, + 0x4f3e, 0x0f2b, + 0x4f3f, 0x21b4, + 0x4f42, 0x0f2f, + 0x4f45, 0x21b7, + 0x4f46, 0x0f33, + 0x4f47, 0x21b8, + 0x4f48, 0x0f35, + 0x4f4a, 0x21b9, + 0x4f4c, 0x0f39, + 0x4f4d, 0x21bb, + 0x4f4f, 0x0f3c, + 0x4f50, 0x21bd, + 0x4f51, 0x0f3e, + 0x4f54, 0x21be, + 0x4f59, 0x0f46, + 0x4f5a, 0x21c3, + 0x4f5b, 0x0f48, + 0x4f5c, 0x21c4, + 0x4f5d, 0x0f4a, + 0x4f5f, 0x21c5, + 0x4f60, 0x0f4d, + 0x4f62, 0x21c6, + 0x4f63, 0x0f50, + 0x4f67, 0x21c7, + 0x4f68, 0x0f55, + 0x4f6a, 0x21c8, + 0x4f6b, 0x0f58, + 0x4f6c, 0x21c9, + 0x4f6d, 0x0f5a, + 0x4f6e, 0x21ca, + 0x4f6f, 0x0f5c, + 0x4f74, 0x21cb, + 0x4f75, 0x0f62, + 0x4f79, 0x21cc, + 0x4f7b, 0x0f68, + 0x4f7e, 0x21ce, + 0x5021, 0x0f6c, + 0x5025, 0x21cf, + 0x5026, 0x0f71, + 0x502d, 0x21d0, + 0x502f, 0x0f7a, + 0x5032, 0x21d2, + 0x5035, 0x0f80, + 0x503a, 0x21d5, + 0x503c, 0x0f87, + 0x503f, 0x21d7, + 0x5040, 0x0f8b, + 0x5046, 0x21d8, + 0x5047, 0x0f92, + 0x504b, 0x21d9, + 0x504c, 0x0f97, + 0x5062, 0x21da, + 0x5063, 0x0fae, + 0x5065, 0x21db, + 0x5066, 0x0fb1, + 0x506b, 0x21dc, + 0x506c, 0x0fb7, + 0x506d, 0x21dd, + 0x506e, 0x0fb9, + 0x5077, 0x21de, + 0x507a, 0x0fc5, + 0x507c, 0x21e1, + 0x507d, 0x0fc8, + 0x5121, 0x21e2, + 0x5123, 0x0fcc, + 0x5124, 0x21e4, + 0x5125, 0x0fce, + 0x5127, 0x21e5, + 0x5128, 0x0fd1, + 0x512b, 0x21e6, + 0x512c, 0x0fd5, + 0x512f, 0x21e7, + 0x5132, 0x0fdb, + 0x5135, 0x21ea, + 0x5138, 0x0fe1, + 0x5139, 0x21ed, + 0x513a, 0x0fe3, + 0x513b, 0x21ee, + 0x513d, 0x0fe6, + 0x5146, 0x21f0, + 0x5149, 0x0ff2, + 0x514b, 0x21f3, + 0x514c, 0x0ff5, + 0x514e, 0x21f4, + 0x5150, 0x0ff9, + 0x5155, 0x21f6, + 0x5157, 0x1000, + 0x515e, 0x21f8, + 0x515f, 0x1008, + 0x5161, 0x21f9, + 0x5163, 0x100c, + 0x5168, 0x21fb, + 0x516a, 0x1013, + 0x516c, 0x21fd, + 0x516d, 0x1016, + 0x516e, 0x21fe, + 0x5170, 0x1019, + 0x5171, 0x2200, + 0x5172, 0x101b, + 0x5174, 0x2201, + 0x5175, 0x101e, + 0x5177, 0x2202, + 0x517a, 0x1023, + 0x5221, 0x1028, + 0x5222, 0x2205, + 0x5223, 0x102a, + 0x5225, 0x2206, + 0x5226, 0x102d, + 0x5229, 0x2207, + 0x522a, 0x1031, + 0x522f, 0x2208, + 0x5230, 0x1037, + 0x5233, 0x2209, + 0x5234, 0x103b, + 0x5235, 0x220a, + 0x5237, 0x103e, + 0x523d, 0x220c, + 0x523e, 0x1045, + 0x523f, 0x220d, + 0x5240, 0x1047, + 0x5243, 0x220e, + 0x5244, 0x104b, + 0x5245, 0x220f, + 0x5246, 0x104d, + 0x5247, 0x2210, + 0x5248, 0x104f, + 0x524f, 0x2211, + 0x5250, 0x1057, + 0x5255, 0x2212, + 0x5256, 0x105d, + 0x525a, 0x2213, + 0x525b, 0x1062, + 0x5264, 0x2214, + 0x5266, 0x106d, + 0x5268, 0x2216, + 0x526c, 0x1073, + 0x526f, 0x221a, + 0x5270, 0x1077, + 0x5271, 0x221b, + 0x5272, 0x1079, + 0x5275, 0x221c, + 0x5276, 0x107d, + 0x5278, 0x221d, + 0x5279, 0x1080, + 0x527b, 0x221e, + 0x527c, 0x1083, + 0x527e, 0x221f, + 0x5321, 0x1086, + 0x5323, 0x2220, + 0x532d, 0x1092, + 0x532e, 0x222a, + 0x532f, 0x1094, + 0x5331, 0x222b, + 0x5332, 0x1097, + 0x5334, 0x222c, + 0x5337, 0x109c, + 0x5338, 0x222f, + 0x5339, 0x109e, + 0x533b, 0x2230, + 0x533c, 0x10a1, + 0x5345, 0x2231, + 0x5346, 0x10ab, + 0x5347, 0x2232, + 0x5348, 0x10ad, + 0x534a, 0x2233, + 0x534d, 0x10b2, + 0x5355, 0x2236, + 0x5356, 0x10bb, + 0x535f, 0x2237, + 0x5361, 0x10c6, + 0x5363, 0x2239, + 0x5364, 0x10c9, + 0x5366, 0x223a, + 0x5367, 0x10cc, + 0x536b, 0x223b, + 0x536d, 0x10d2, + 0x536f, 0x223d, + 0x5370, 0x10d5, + 0x5374, 0x223e, + 0x5375, 0x10da, + 0x537c, 0x223f, + 0x537d, 0x10e2, + 0x537e, 0x2240, + 0x5421, 0x10e4, + 0x5424, 0x2241, + 0x5425, 0x10e8, + 0x5426, 0x2242, + 0x5429, 0x10ec, + 0x542f, 0x2245, + 0x5433, 0x10f6, + 0x5435, 0x2249, + 0x5437, 0x10fa, + 0x5438, 0x224b, + 0x5439, 0x10fc, + 0x543c, 0x224c, + 0x543d, 0x1100, + 0x543e, 0x224d, + 0x5440, 0x1103, + 0x5444, 0x224f, + 0x5445, 0x1108, + 0x5446, 0x2250, + 0x5448, 0x110b, + 0x5449, 0x2252, + 0x544a, 0x110d, + 0x544b, 0x2253, + 0x544f, 0x1112, + 0x5453, 0x2257, + 0x5454, 0x1117, + 0x5458, 0x2258, + 0x5459, 0x111c, + 0x545c, 0x2259, + 0x5461, 0x1124, + 0x5464, 0x225e, + 0x5465, 0x1128, + 0x5466, 0x225f, + 0x5467, 0x112a, + 0x546e, 0x2260, + 0x546f, 0x1132, + 0x5470, 0x2261, + 0x5475, 0x1138, + 0x5479, 0x2266, + 0x547a, 0x113d, + 0x547e, 0x2267, + 0x5521, 0x2268, + 0x5523, 0x1144, + 0x5529, 0x226a, + 0x552a, 0x114b, + 0x552b, 0x226b, + 0x552c, 0x114d, + 0x552e, 0x226c, + 0x552f, 0x1150, + 0x5531, 0x226d, + 0x5532, 0x1153, + 0x5535, 0x226e, + 0x5539, 0x115a, + 0x553b, 0x2272, + 0x553c, 0x115d, + 0x553d, 0x2273, + 0x553e, 0x115f, + 0x5540, 0x2274, + 0x5541, 0x1162, + 0x5545, 0x2275, + 0x5546, 0x1167, + 0x5547, 0x2276, + 0x5548, 0x1169, + 0x554a, 0x2277, + 0x554c, 0x116d, + 0x554d, 0x2279, + 0x554e, 0x116f, + 0x5554, 0x227a, + 0x5555, 0x1176, + 0x555d, 0x227b, + 0x555f, 0x1180, + 0x5560, 0x227d, + 0x5561, 0x1182, + 0x5562, 0x227e, + 0x5563, 0x1184, + 0x556a, 0x227f, + 0x556d, 0x118e, + 0x556f, 0x2282, + 0x5570, 0x1191, + 0x5572, 0x2283, + 0x5574, 0x1195, + 0x5577, 0x15eb, + 0x5578, 0x1199, + 0x5621, 0x2285, + 0x5625, 0x11a4, + 0x562f, 0x2289, + 0x5631, 0x11b0, + 0x5634, 0x228b, + 0x5635, 0x11b4, + 0x563b, 0x228c, + 0x563c, 0x11bb, + 0x563d, 0x228d, + 0x563e, 0x11bd, + 0x563f, 0x228e, + 0x5641, 0x11c0, + 0x5644, 0x2290, + 0x5645, 0x11c4, + 0x564a, 0x2291, + 0x564b, 0x11ca, + 0x564d, 0x2292, + 0x564e, 0x11cd, + 0x5653, 0x2293, + 0x5654, 0x11d3, + 0x5655, 0x2294, + 0x5658, 0x11d7, + 0x565a, 0x2297, + 0x565b, 0x11da, + 0x565f, 0x2298, + 0x5660, 0x11df, + 0x5661, 0x2299, + 0x5662, 0x11e1, + 0x5665, 0x229a, + 0x5666, 0x11e5, + 0x5667, 0x229b, + 0x5669, 0x11e8, + 0x566e, 0x229d, + 0x5670, 0x11ef, + 0x5672, 0x229f, + 0x5673, 0x11f2, + 0x5675, 0x22a0, + 0x5677, 0x11f6, + 0x567c, 0x22a2, + 0x5721, 0x11fe, + 0x5724, 0x22a5, + 0x5725, 0x1202, + 0x5728, 0x22a6, + 0x572b, 0x1208, + 0x572c, 0x22a9, + 0x572d, 0x120a, + 0x572e, 0x22aa, + 0x5732, 0x120f, + 0x5733, 0x22ae, + 0x5735, 0x1212, + 0x5736, 0x22b0, + 0x5737, 0x1214, + 0x5738, 0x22b1, + 0x573d, 0x121a, + 0x5747, 0x22b6, + 0x5748, 0x1225, + 0x574a, 0x22b7, + 0x574b, 0x1228, + 0x5755, 0x22b8, + 0x5756, 0x1233, + 0x575b, 0x22b9, + 0x575f, 0x123c, + 0x5767, 0x22bd, + 0x5768, 0x1245, + 0x5769, 0x22be, + 0x576b, 0x1248, + 0x5821, 0x1257, + 0x5844, 0x22c0, + 0x5845, 0x127b, + 0x5847, 0x22c1, + 0x5848, 0x127e, + 0x5849, 0x22c2, + 0x584a, 0x1280, + 0x584c, 0x22c3, + 0x584e, 0x1284, + 0x5850, 0x22c5, + 0x5852, 0x1288, + 0x5853, 0x22c7, + 0x5854, 0x128a, + 0x5859, 0x22c8, + 0x585a, 0x1290, + 0x585b, 0x22c9, + 0x585d, 0x1293, + 0x5871, 0x22cb, + 0x5872, 0x12a8, + 0x5876, 0x22cc, + 0x5878, 0x12ae, + 0x5921, 0x12b5, + 0x592d, 0x22ce, + 0x592e, 0x12c2, + 0x592f, 0x22cf, + 0x5930, 0x12c4, + 0x5931, 0x22d0, + 0x5934, 0x12c8, + 0x5947, 0x22d3, + 0x5948, 0x12dc, + 0x594d, 0x22d4, + 0x5951, 0x12e5, + 0x595d, 0x22d8, + 0x595e, 0x12f2, + 0x5961, 0x22d9, + 0x5962, 0x12f6, + 0x5964, 0x22da, + 0x5965, 0x12f9, + 0x5966, 0x22db, + 0x5967, 0x12fb, + 0x596c, 0x22dc, + 0x596d, 0x1301, + 0x5974, 0x22dd, + 0x5976, 0x130a, + 0x5a21, 0x1313, + 0x5a25, 0x22df, + 0x5a60, 0x1352, + 0x5a6a, 0x231a, + 0x5a6b, 0x135d, + 0x5a77, 0x231b, + 0x5a78, 0x136a, + 0x5a79, 0x231c, + 0x5a7a, 0x136c, + 0x5a7e, 0x231d, + 0x5b21, 0x1371, + 0x5b23, 0x231e, + 0x5b24, 0x1374, + 0x5b26, 0x231f, + 0x5b27, 0x1377, + 0x5b29, 0x2320, + 0x5b2b, 0x137b, + 0x5b3b, 0x2322, + 0x5b3c, 0x138c, + 0x5b3d, 0x2323, + 0x5b3e, 0x138e, + 0x5b4f, 0x2324, + 0x5b50, 0x13a0, + 0x5b51, 0x2325, + 0x5b52, 0x13a2, + 0x5b5b, 0x2326, + 0x5b5c, 0x13ac, + 0x5b5e, 0x2327, + 0x5b5f, 0x13af, + 0x5b62, 0x2328, + 0x5b63, 0x13b3, + 0x5b64, 0x2329, + 0x5b65, 0x13b5, + 0x5b6b, 0x232a, + 0x5b6c, 0x13bc, + 0x5b6e, 0x232b, + 0x5b6f, 0x13bf, + 0x5b71, 0x232c, + 0x5b72, 0x13c2, + 0x5b75, 0x232d, + 0x5b78, 0x13c8, + 0x5c21, 0x13cf, + 0x5c3c, 0x2330, + 0x5c3d, 0x13eb, + 0x5c3f, 0x2331, + 0x5c40, 0x13ee, + 0x5c42, 0x2332, + 0x5c43, 0x13f1, + 0x5c48, 0x2333, + 0x5c4b, 0x13f9, + 0x5c51, 0x2336, + 0x5c52, 0x1400, + 0x5c57, 0x2337, + 0x5c58, 0x1406, + 0x5c60, 0x2338, + 0x5c61, 0x140f, + 0x5c63, 0x2339, + 0x5c65, 0x1413, + 0x5c69, 0x233b, + 0x5c6b, 0x1419, + 0x5c71, 0x233d, + 0x5c72, 0x1420, + 0x5c76, 0x233e, + 0x5c77, 0x1425, + 0x5c79, 0x233f, + 0x5c7a, 0x1428, + 0x5c7d, 0x2340, + 0x5d21, 0x2342, + 0x5d22, 0x142e, + 0x5d23, 0x2343, + 0x5d28, 0x1434, + 0x5d2a, 0x2348, + 0x5d2c, 0x1438, + 0x5d32, 0x234a, + 0x5d33, 0x143f, + 0x5d35, 0x234b, + 0x5d36, 0x1442, + 0x5d3a, 0x234c, + 0x5d3c, 0x1448, + 0x5d53, 0x234e, + 0x5d54, 0x1460, + 0x5d5b, 0x234f, + 0x5d5c, 0x1468, + 0x5d5e, 0x2350, + 0x5d5f, 0x146b, + 0x5d64, 0x2351, + 0x5d65, 0x1471, + 0x5d6b, 0x2352, + 0x5d6c, 0x1478, + 0x5d71, 0x2353, + 0x5d72, 0x147e, + 0x5d76, 0x2354, + 0x5d78, 0x1484, + 0x5d7c, 0x2356, + 0x5d7d, 0x1489, + 0x5d7e, 0x2357, + 0x5e21, 0x148b, + 0x5e2d, 0x2358, + 0x5e2e, 0x1498, + 0x5e34, 0x2359, + 0x5e35, 0x149f, + 0x5e3a, 0x235a, + 0x5e3b, 0x14a5, + 0x5e46, 0x235b, + 0x5e47, 0x14b1, + 0x5e4f, 0x235c, + 0x5e50, 0x14ba, + 0x5e51, 0x235d, + 0x5e53, 0x14bd, + 0x5e58, 0x235f, + 0x5e59, 0x14c3, + 0x5e62, 0x2360, + 0x5e63, 0x14cd, + 0x5e68, 0x2361, + 0x5e69, 0x14d3, + 0x5e6c, 0x2362, + 0x5e6d, 0x14d7, + 0x5e73, 0x2363, + 0x5e74, 0x14de, + 0x5e7c, 0x2364, + 0x5e7d, 0x14e7, + 0x5f21, 0x14e9, + 0x5f22, 0x2365, + 0x5f24, 0x14ec, + 0x5f25, 0x2367, + 0x5f26, 0x14ee, + 0x5f34, 0x2368, + 0x5f35, 0x14fd, + 0x5f3c, 0x2369, + 0x5f3e, 0x1506, + 0x5f3f, 0x236b, + 0x5f40, 0x1508, + 0x5f42, 0x236c, + 0x5f44, 0x150c, + 0x5f4c, 0x236e, + 0x5f4d, 0x1515, + 0x5f50, 0x236f, + 0x5f51, 0x1519, + 0x5f55, 0x2370, + 0x5f56, 0x151e, + 0x5f58, 0x2371, + 0x5f5a, 0x1522, + 0x5f5c, 0x2373, + 0x5f5d, 0x1525, + 0x5f60, 0x2374, + 0x5f61, 0x1529, + 0x5f62, 0x2375, + 0x5f63, 0x152b, + 0x5f66, 0x2376, + 0x5f67, 0x152f, + 0x5f69, 0x2377, + 0x5f6a, 0x1532, + 0x5f6b, 0x2378, + 0x5f6c, 0x1534, + 0x5f6f, 0x2379, + 0x5f70, 0x1538, + 0x5f75, 0x237a, + 0x5f76, 0x153e, + 0x5f79, 0x237b, + 0x5f7a, 0x1542, + 0x6021, 0x1547, + 0x6036, 0x237c, + 0x6038, 0x155e, + 0x603f, 0x237e, + 0x6040, 0x1566, + 0x6048, 0x237f, + 0x6049, 0x156f, + 0x604e, 0x2380, + 0x604f, 0x1575, + 0x6053, 0x2381, + 0x6054, 0x157a, + 0x6060, 0x2382, + 0x6061, 0x1587, + 0x6070, 0x2383, + 0x6071, 0x1597, + 0x6078, 0x2384, + 0x6079, 0x159f, + 0x607c, 0x2385, + 0x6121, 0x15a5, + 0x612b, 0x2388, + 0x612c, 0x15b0, + 0x612d, 0x2389, + 0x612e, 0x15b2, + 0x6130, 0x238a, + 0x6131, 0x15b5, + 0x6134, 0x238b, + 0x6135, 0x15b9, + 0x613b, 0x238c, + 0x613c, 0x15c0, + 0x613d, 0x238d, + 0x613e, 0x15c2, + 0x6140, 0x238e, + 0x6142, 0x15c6, + 0x6149, 0x2390, + 0x614a, 0x15ce, + 0x6150, 0x2391, + 0x6151, 0x15d5, + 0x615b, 0x2392, + 0x615c, 0x15e0, + 0x6161, 0x07aa, + 0x6162, 0x2393, + 0x6163, 0x15e7, + 0x6167, 0x1198, + 0x6168, 0x15ec, + 0x616e, 0x2394, + 0x6170, 0x15f4, + 0x6176, 0x2396, + 0x6177, 0x15fb, + 0x6178, 0x2397, + 0x6179, 0x15fd, + 0x617d, 0x2398, + 0x617e, 0x1602, + 0x6221, 0x1603, + 0x6224, 0x2399, + 0x6225, 0x1607, + 0x6228, 0x239a, + 0x6229, 0x160b, + 0x623b, 0x239b, + 0x6245, 0x10c5, + 0x6246, 0x23a5, + 0x624f, 0x1631, + 0x6250, 0x23ae, + 0x6251, 0x1633, + 0x6259, 0x23af, + 0x625a, 0x163c, + 0x6263, 0x23b0, + 0x6265, 0x1647, + 0x6266, 0x23b2, + 0x6267, 0x1649, + 0x6269, 0x23b3, + 0x626c, 0x164e, + 0x6278, 0x23b6, + 0x6279, 0x165b, + 0x627a, 0x23b7, + 0x627e, 0x1660, + 0x6321, 0x1661, + 0x6322, 0x23bb, + 0x6323, 0x1663, + 0x6325, 0x23bc, + 0x6326, 0x1666, + 0x632b, 0x23bd, + 0x632c, 0x166c, + 0x6334, 0x23be, + 0x6335, 0x1675, + 0x6345, 0x23bf, + 0x635c, 0x169c, + 0x6363, 0x23d6, + 0x6364, 0x16a4, + 0x636d, 0x23d7, + 0x636e, 0x16ae, + 0x6371, 0x23d8, + 0x6373, 0x16b3, + 0x6378, 0x23da, + 0x6379, 0x16b9, + 0x637e, 0x23db, + 0x6421, 0x16bf, + 0x6424, 0x23dc, + 0x6426, 0x16c4, + 0x642b, 0x23de, + 0x642c, 0x16ca, + 0x642f, 0x23df, + 0x6432, 0x16d0, + 0x6435, 0x23e2, + 0x6437, 0x16d5, + 0x6442, 0x23e4, + 0x6443, 0x16e1, + 0x6445, 0x23e5, + 0x6446, 0x16e4, + 0x6449, 0x23e6, + 0x644a, 0x16e8, + 0x6459, 0x23e7, + 0x645a, 0x16f8, + 0x645c, 0x23e8, + 0x645d, 0x16fb, + 0x645e, 0x23e9, + 0x645f, 0x16fd, + 0x6464, 0x23ea, + 0x6465, 0x1703, + 0x646b, 0x23eb, + 0x646d, 0x170b, + 0x6472, 0x23ed, + 0x6473, 0x1711, + 0x647e, 0x23ee, + 0x6521, 0x171d, + 0x6530, 0x23ef, + 0x6531, 0x172d, + 0x6539, 0x23f0, + 0x653a, 0x1736, + 0x6547, 0x23f1, + 0x6548, 0x1744, + 0x6549, 0x23f2, + 0x654a, 0x1746, + 0x654e, 0x23f3, + 0x654f, 0x174b, + 0x6570, 0x23f4, + 0x6571, 0x176d, + 0x6572, 0x23f5, + 0x6573, 0x176f, + 0x657c, 0x23f6, + 0x657e, 0x177a, + 0x6621, 0x177b, + 0x6623, 0x23f8, + 0x6624, 0x177e, + 0x662b, 0x23f9, + 0x662d, 0x1787, + 0x662e, 0x23fb, + 0x662f, 0x1789, + 0x6634, 0x23fc, + 0x6636, 0x1790, + 0x663f, 0x23fe, + 0x6640, 0x179a, + 0x6648, 0x23ff, + 0x664a, 0x17a4, + 0x664d, 0x2401, + 0x664e, 0x17a8, + 0x6660, 0x2402, + 0x6721, 0x2421, + 0x675b, 0x1813, + 0x6761, 0x245b, + 0x6763, 0x181b, + 0x6767, 0x245d, + 0x6768, 0x1820, + 0x676f, 0x245e, + 0x6770, 0x1828, + 0x6774, 0x245f, + 0x6777, 0x182f, + 0x6821, 0x1837, + 0x6828, 0x2462, + 0x6829, 0x183f, + 0x682c, 0x2463, + 0x682d, 0x1843, + 0x6836, 0x2464, + 0x6837, 0x184d, + 0x6838, 0x2465, + 0x683b, 0x1851, + 0x683f, 0x2468, + 0x6841, 0x1857, + 0x6845, 0x246a, + 0x6846, 0x185c, + 0x6847, 0x246b, + 0x684a, 0x1860, + 0x684e, 0x246e, + 0x684f, 0x1865, + 0x6850, 0x246f, + 0x6851, 0x1867, + 0x6853, 0x2470, + 0x6854, 0x186a, + 0x685d, 0x2471, + 0x685e, 0x1874, + 0x685f, 0x2472, + 0x6860, 0x1876, + 0x6862, 0x2473, + 0x6864, 0x187a, + 0x6865, 0x2475, + 0x6866, 0x187c, + 0x6867, 0x2476, + 0x6868, 0x187e, + 0x686b, 0x2477, + 0x686c, 0x1882, + 0x686d, 0x2478, + 0x686e, 0x1884, + 0x686f, 0x2479, + 0x6870, 0x1886, + 0x6879, 0x247a, + 0x687a, 0x1890, + 0x687c, 0x247b, + 0x687e, 0x1894, + 0x6921, 0x247d, + 0x6922, 0x1896, + 0x692d, 0x247e, + 0x692e, 0x18a2, + 0x6934, 0x247f, + 0x6936, 0x18aa, + 0x6937, 0x2481, + 0x6938, 0x18ac, + 0x6944, 0x2482, + 0x6945, 0x18b9, + 0x6946, 0x2483, + 0x6947, 0x18bb, + 0x6949, 0x2484, + 0x694a, 0x18be, + 0x6956, 0x2485, + 0x6957, 0x18cb, + 0x695a, 0x2486, + 0x695b, 0x18cf, + 0x6964, 0x2487, + 0x6965, 0x18d9, + 0x6966, 0x2488, + 0x6968, 0x18dc, + 0x6969, 0x248a, + 0x696a, 0x18de, + 0x696b, 0x248b, + 0x696c, 0x18e0, + 0x696d, 0x248c, + 0x6a21, 0x249e, + 0x6a26, 0x18f8, + 0x6a27, 0x24a3, + 0x6a29, 0x18fb, + 0x6a31, 0x24a5, + 0x6a32, 0x1904, + 0x6a3c, 0x24a6, + 0x6a3d, 0x190f, + 0x6a4a, 0x24a7, + 0x6a4b, 0x191d, + 0x6a4d, 0x24a8, + 0x6a4e, 0x1920, + 0x6a53, 0x24a9, + 0x6a54, 0x1926, + 0x6a5a, 0x24aa, + 0x6a70, 0x1942, + 0x6b21, 0x1951, + 0x6b27, 0x24c0, + 0x6b28, 0x1958, + 0x6b2a, 0x24c1, + 0x6b2b, 0x195b, + 0x6b32, 0x24c2, + 0x6b33, 0x1963, + 0x6b39, 0x24c3, + 0x6b3a, 0x196a, + 0x6b4a, 0x24c4, + 0x6b4c, 0x197c, + 0x6b4d, 0x24c6, + 0x6b4e, 0x197e, + 0x6b56, 0x24c7, + 0x6b57, 0x1987, + 0x6b5a, 0x24c8, + 0x6b5b, 0x198b, + 0x6b61, 0x24c9, + 0x6b62, 0x1992, + 0x6b77, 0x24ca, + 0x6b78, 0x19a8, + 0x6c21, 0x19af, + 0x6c23, 0x24cb, + 0x6c24, 0x19b2, + 0x6c29, 0x24cc, + 0x6c2f, 0x19bd, + 0x6c31, 0x24d2, + 0x6c32, 0x19c0, + 0x6c34, 0x24d3, + 0x6c36, 0x19c4, + 0x6c3e, 0x24d5, + 0x6c40, 0x19ce, + 0x6c41, 0x24d7, + 0x6c42, 0x19d0, + 0x6c47, 0x24d8, + 0x6c48, 0x19d6, + 0x6c4b, 0x24d9, + 0x6c4c, 0x19da, + 0x6c62, 0x24da, + 0x6c63, 0x19f1, + 0x6c72, 0x24db, + 0x6c73, 0x1a01, + 0x6c75, 0x24dc, + 0x6c76, 0x1a04, + 0x6c78, 0x24dd, + 0x6c79, 0x1a07, + 0x6d21, 0x24de, + 0x6d22, 0x1a0e, + 0x6d28, 0x24df, + 0x6d29, 0x1a15, + 0x6d2f, 0x24e0, + 0x6d31, 0x1a1d, + 0x6d34, 0x24e2, + 0x6d35, 0x1a21, + 0x6d36, 0x24e3, + 0x6d37, 0x1a23, + 0x6d38, 0x24e4, + 0x6d39, 0x1a25, + 0x6d3a, 0x24e5, + 0x6d3b, 0x1a27, + 0x6d3f, 0x24e6, + 0x6d40, 0x1a2c, + 0x6d42, 0x24e7, + 0x6d44, 0x1a30, + 0x6d4c, 0x24e9, + 0x6d4e, 0x1a3a, + 0x6d53, 0x24eb, + 0x6d54, 0x1a40, + 0x6d57, 0x24ec, + 0x6d58, 0x1a44, + 0x6d68, 0x24ed, + 0x6d69, 0x1a55, + 0x6d6e, 0x24ee, + 0x6d6f, 0x1a5b, + 0x6d79, 0x24ef, + 0x6d7b, 0x1a67, + 0x6e21, 0x1a6b, + 0x6e3c, 0x24f1, + 0x6e3d, 0x1a87, + 0x6e3f, 0x24f2, + 0x6e40, 0x1a8a, + 0x6e44, 0x24f3, + 0x6f21, 0x252e, + 0x6f72, 0x1b1a, + 0x7021, 0x1b27, + 0x7023, 0x257f, + 0x7024, 0x1b2a, + 0x702f, 0x2580, + 0x705a, 0x1b60, + 0x705c, 0x25ab, + 0x705e, 0x1b64, + 0x705f, 0x25ad, + 0x7060, 0x1b66, + 0x7069, 0x25ae, + 0x706a, 0x1b70, + 0x706c, 0x25af, + 0x706d, 0x1b73, + 0x706f, 0x25b0, + 0x7070, 0x1b76, + 0x7077, 0x25b1, + 0x7078, 0x1b7e, + 0x7079, 0x25b2, + 0x707a, 0x1b80, + 0x707c, 0x25b3, + 0x707d, 0x1b83, + 0x7121, 0x1b85, + 0x7128, 0x25b4, + 0x7129, 0x1b8d, + 0x712b, 0x25b5, + 0x712c, 0x1b90, + 0x712e, 0x25b6, + 0x712f, 0x1b93, + 0x7132, 0x25b7, + 0x7133, 0x1b97, + 0x713c, 0x25b8, + 0x713d, 0x1ba1, + 0x7140, 0x25b9, + 0x7141, 0x1ba5, + 0x7149, 0x25ba, + 0x714a, 0x1bae, + 0x714d, 0x25bb, + 0x714e, 0x1bb2, + 0x714f, 0x25bc, + 0x7151, 0x1bb5, + 0x715a, 0x25be, + 0x715b, 0x1bbf, + 0x715c, 0x25bf, + 0x715d, 0x1bc1, + 0x7164, 0x25c0, + 0x7165, 0x1bc9, + 0x716c, 0x25c1, + 0x716d, 0x1bd1, + 0x716f, 0x25c2, + 0x7170, 0x1bd4, + 0x7177, 0x25c3, + 0x7178, 0x1bdc, + 0x7179, 0x25c4, + 0x717a, 0x1bde, + 0x717c, 0x25c5, + 0x7221, 0x25c8, + 0x722e, 0x1bf0, + 0x7231, 0x25d5, + 0x7233, 0x1bf5, + 0x7239, 0x25d7, + 0x723a, 0x1bfc, + 0x7243, 0x25d8, + 0x7244, 0x1c06, + 0x7249, 0x25d9, + 0x724a, 0x1c0c, + 0x724c, 0x25da, + 0x724e, 0x1c10, + 0x724f, 0x25dc, + 0x7250, 0x1c12, + 0x7253, 0x25dd, + 0x7254, 0x1c16, + 0x7265, 0x25de, + 0x7266, 0x1c28, + 0x726e, 0x25df, + 0x726f, 0x1c31, + 0x7277, 0x25e0, + 0x7278, 0x1c3a, + 0x727d, 0x25e1, + 0x727e, 0x1c40, + 0x7321, 0x1c41, + 0x733f, 0x25e2, + 0x7340, 0x1c60, + 0x7346, 0x25e3, + 0x7347, 0x1c67, + 0x7348, 0x25e4, + 0x7349, 0x1c69, + 0x7356, 0x25e5, + 0x7357, 0x1c77, + 0x7359, 0x25e6, + 0x735a, 0x1c7a, + 0x7365, 0x25e7, + 0x7367, 0x1c87, + 0x736a, 0x25e9, + 0x736b, 0x1c8b, + 0x736c, 0x25ea, + 0x736d, 0x1c8d, + 0x736f, 0x25eb, + 0x7370, 0x1c90, + 0x7371, 0x25ec, + 0x7372, 0x1c92, + 0x737d, 0x25ed, + 0x737e, 0x1c9e, + 0x7421, 0x1c9f, + 0x7425, 0x25ee, + 0x7426, 0x1ca4, + 0x742f, 0x25ef, + 0x7430, 0x1cae, + 0x7435, 0x25f0, + 0x7436, 0x1cb4, + 0x7441, 0x25f1, + 0x7442, 0x1cc0, + 0x7447, 0x25f2, + 0x7448, 0x1cc6, + 0x744f, 0x25f3, + 0x7451, 0x1ccf, + 0x7456, 0x25f5, + 0x7457, 0x1cd5, + 0x746a, 0x25f6, + 0x746b, 0x1ce9, + 0x746f, 0x25f7, + 0x7470, 0x1cee, + 0x7475, 0x25f8, + 0x7476, 0x1cf4, + 0x7521, 0x1cfd, + 0x7526, 0x25f9, + 0x7528, 0x1d04, + 0x753a, 0x25fb, + 0x753c, 0x1d18, + 0x7544, 0x25fd, + 0x7545, 0x1d21, + 0x7548, 0x25fe, + 0x7549, 0x1d25, + 0x754e, 0x25ff, + 0x7550, 0x1d2c, + 0x7551, 0x2601, + 0x7553, 0x1d2f, + 0x7559, 0x2603, + 0x755a, 0x1d36, + 0x755c, 0x2604, + 0x755d, 0x1d39, + 0x7566, 0x2605, + 0x7568, 0x1d44, + 0x756f, 0x2607, + 0x7570, 0x1d4c, + 0x7572, 0x2608, + 0x7573, 0x1d4f, + 0x757c, 0x2609, + 0x757d, 0x1d59, + 0x7621, 0x1d5b, + 0x7623, 0x260a, + 0x7624, 0x1d5e, + 0x7626, 0x260b, + 0x7627, 0x1d61, + 0x7628, 0x260c, + 0x7629, 0x1d63, + 0x762b, 0x260d, + 0x762c, 0x1d66, + 0x7630, 0x260e, + 0x7631, 0x1d6b, + 0x7633, 0x260f, + 0x763f, 0x1d79, + 0x7645, 0x261b, + 0x7646, 0x1d80, + 0x7647, 0x261c, + 0x7648, 0x1d82, + 0x7649, 0x261d, + 0x764a, 0x1d84, + 0x764f, 0x261e, + 0x7721, 0x264e, + 0x7730, 0x1dc8, + 0x7732, 0x265d, + 0x7734, 0x1dcc, + 0x7735, 0x265f, + 0x7736, 0x1dce, + 0x773d, 0x2660, + 0x773e, 0x1dd6, + 0x7743, 0x2661, + 0x7744, 0x1ddc, + 0x7745, 0x2662, + 0x7747, 0x1ddf, + 0x774a, 0x2664, + 0x774c, 0x1de4, + 0x774f, 0x2666, + 0x7751, 0x1de9, + 0x775e, 0x2668, + 0x775f, 0x1df7, + 0x7761, 0x0ab9, + 0x7762, 0x1dfa, + 0x7772, 0x2669, + 0x7773, 0x1e0b, + 0x7775, 0x266a, + 0x7776, 0x1e0e, + 0x7821, 0x266b, + 0x7827, 0x04cc, + 0x7828, 0x050a, + 0x7829, 0x0518, + 0x782a, 0x2671, + 0x782c, 0x0594, + 0x782d, 0x05ce, + 0x782e, 0x2673, + 0x782f, 0x05f6, + 0x7830, 0x2674, + 0x7832, 0x0653, + 0x7833, 0x067e, + 0x7834, 0x2676, + 0x7835, 0x06c4, + 0x7836, 0x2677, + 0x7838, 0x073c, + 0x7839, 0x2679, + 0x783b, 0x07c3, + 0x783c, 0x267b, + 0x7840, 0x082b, + 0x7841, 0x267f, + 0x7842, 0x084e, + 0x7843, 0x0869, + 0x7844, 0x2680, + 0x7846, 0x090c, + 0x7847, 0x2682, + 0x7849, 0x0971, + 0x784a, 0x2684, + 0x784b, 0x099a, + 0x784d, 0x2685, + 0x784e, 0x09da, + 0x784f, 0x2686, + 0x7850, 0x09fa, + 0x7851, 0x2687, + 0x785c, 0x0bda, + 0x785d, 0x0bdd, + 0x785e, 0x0bea, + 0x785f, 0x0bec, + 0x7860, 0x0bf2, + 0x7861, 0x2692, + 0x7866, 0x0c92, + 0x7867, 0x0d1a, + 0x7868, 0x0d8c, + 0x7869, 0x0dbe, + 0x786a, 0x2697, + 0x786b, 0x0dfb, + 0x786c, 0x2698, + 0x786f, 0x0e70, + 0x7870, 0x269b, + 0x7871, 0x0ea3, + 0x7872, 0x269c, + 0x7878, 0x103d, + 0x7879, 0x10d9, + 0x787a, 0x26a2, + 0x787c, 0x10fb, + 0x787d, 0x1109, + 0x787e, 0x26a4, + 0x7921, 0x11a1, + 0x7922, 0x26a5, + 0x7923, 0x11ba, + 0x7924, 0x26a6, + 0x7926, 0x11d5, + 0x7927, 0x26a8, + 0x7928, 0x11fd, + 0x7929, 0x1219, + 0xffff, 0x0000 +}; + +static GfxFontEncoding16 gb12GBTHEnc16 = { + 0, + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, + gb12GBTHMap2, 2283 +}; + +static Gushort gb12GBTVMap2[4606] = { + 0x0000, 0x0000, + 0x2121, 0x0060, + 0x2231, 0x00be, + 0x2265, 0x00f0, + 0x2271, 0x00fa, + 0x2321, 0x0106, + 0x2421, 0x0164, + 0x2521, 0x01b7, + 0x2621, 0x020d, + 0x2641, 0x0225, + 0x2721, 0x025a, + 0x2751, 0x027b, + 0x2821, 0x029c, + 0x2845, 0x02bc, + 0x2924, 0x02e2, + 0x2a21, 0x032e, + 0x2b21, 0x038c, + 0x3021, 0x03ac, + 0x3028, 0x1e25, + 0x3029, 0x03b4, + 0x302a, 0x1e26, + 0x302b, 0x03b6, + 0x302d, 0x1e27, + 0x302f, 0x03ba, + 0x3039, 0x1e29, + 0x303a, 0x03c5, + 0x3040, 0x1e2a, + 0x3041, 0x03cc, + 0x3053, 0x1e2b, + 0x3054, 0x03df, + 0x3055, 0x1e2c, + 0x3056, 0x03e1, + 0x305a, 0x1e2d, + 0x305b, 0x03e6, + 0x305c, 0x1e2e, + 0x305d, 0x03e8, + 0x3064, 0x1e2f, + 0x3065, 0x03f0, + 0x306c, 0x1e30, + 0x306e, 0x03f9, + 0x306f, 0x1e32, + 0x3070, 0x03fb, + 0x3073, 0x1e33, + 0x3074, 0x03ff, + 0x3077, 0x1e34, + 0x3078, 0x0403, + 0x3079, 0x1e35, + 0x307a, 0x0405, + 0x3121, 0x040a, + 0x3125, 0x1e36, + 0x3127, 0x0410, + 0x3128, 0x1e38, + 0x3129, 0x0412, + 0x312b, 0x1e39, + 0x312c, 0x0415, + 0x3132, 0x1e3a, + 0x3133, 0x041c, + 0x3134, 0x1e3b, + 0x3136, 0x041f, + 0x3137, 0x1e3d, + 0x313a, 0x0423, + 0x3141, 0x1e40, + 0x3142, 0x042b, + 0x314a, 0x1e41, + 0x314b, 0x0434, + 0x314f, 0x1e42, + 0x3151, 0x043a, + 0x3152, 0x1e44, + 0x3153, 0x043c, + 0x3155, 0x1e45, + 0x3156, 0x043f, + 0x315f, 0x1e46, + 0x3162, 0x044b, + 0x3164, 0x1e49, + 0x3165, 0x044e, + 0x3167, 0x1e4a, + 0x3169, 0x0452, + 0x316a, 0x1e4c, + 0x316b, 0x0454, + 0x316e, 0x1e4d, + 0x316f, 0x0458, + 0x3171, 0x1e4e, + 0x3172, 0x045b, + 0x3174, 0x1e4f, + 0x3178, 0x0461, + 0x317d, 0x1e53, + 0x317e, 0x0467, + 0x3221, 0x0468, + 0x3226, 0x1e54, + 0x3228, 0x046f, + 0x322c, 0x1e56, + 0x322d, 0x0474, + 0x3235, 0x1e57, + 0x3236, 0x047d, + 0x3239, 0x1e58, + 0x323a, 0x0481, + 0x3246, 0x1e59, + 0x3247, 0x048e, + 0x324e, 0x1e5a, + 0x3258, 0x049f, + 0x325e, 0x1e64, + 0x325f, 0x04a6, + 0x3260, 0x1e65, + 0x3261, 0x04a8, + 0x3262, 0x1e66, + 0x3264, 0x04ab, + 0x326f, 0x1e68, + 0x3270, 0x04b7, + 0x3273, 0x1e69, + 0x327d, 0x04c4, + 0x3321, 0x1e73, + 0x3323, 0x04c8, + 0x3324, 0x1e75, + 0x3328, 0x04cd, + 0x3329, 0x1e79, + 0x332a, 0x04cf, + 0x332e, 0x1e7a, + 0x332f, 0x04d4, + 0x3335, 0x1e7b, + 0x3336, 0x04db, + 0x3339, 0x1e7c, + 0x333a, 0x04df, + 0x333e, 0x1e7d, + 0x333f, 0x04e4, + 0x3342, 0x1e7e, + 0x3343, 0x04e8, + 0x3344, 0x1e7f, + 0x3345, 0x04ea, + 0x3346, 0x1e80, + 0x3347, 0x04ec, + 0x334d, 0x1e81, + 0x334e, 0x04f3, + 0x334f, 0x1e82, + 0x3350, 0x04f5, + 0x3352, 0x1e83, + 0x3353, 0x04f8, + 0x3359, 0x1e84, + 0x335a, 0x04ff, + 0x335b, 0x1e85, + 0x335c, 0x0501, + 0x335d, 0x1e86, + 0x335e, 0x0503, + 0x3363, 0x1e87, + 0x3364, 0x0509, + 0x3365, 0x1e88, + 0x3367, 0x050c, + 0x3368, 0x1e8a, + 0x3369, 0x050e, + 0x336b, 0x1e8b, + 0x336d, 0x0512, + 0x336f, 0x1e8d, + 0x3370, 0x0515, + 0x3371, 0x1e8e, + 0x3372, 0x0517, + 0x3373, 0x1e8f, + 0x3374, 0x0519, + 0x337a, 0x1e90, + 0x337c, 0x0521, + 0x3421, 0x1e92, + 0x3423, 0x0526, + 0x3425, 0x1e94, + 0x3427, 0x052a, + 0x342b, 0x1e96, + 0x342c, 0x052f, + 0x342f, 0x1e97, + 0x3430, 0x0533, + 0x3433, 0x1e98, + 0x3435, 0x0538, + 0x3438, 0x1e9a, + 0x3439, 0x053c, + 0x343f, 0x1e9b, + 0x3440, 0x0543, + 0x3442, 0x1e9c, + 0x3443, 0x0546, + 0x3447, 0x1e9d, + 0x3448, 0x054b, + 0x344a, 0x1e9e, + 0x344b, 0x054e, + 0x344d, 0x1e9f, + 0x344e, 0x0551, + 0x344f, 0x1ea0, + 0x3450, 0x0553, + 0x3453, 0x1ea1, + 0x3455, 0x0558, + 0x345a, 0x1ea3, + 0x345b, 0x055e, + 0x345c, 0x1ea4, + 0x345d, 0x0560, + 0x346d, 0x1ea5, + 0x346e, 0x0571, + 0x346f, 0x1ea6, + 0x3470, 0x0573, + 0x3478, 0x1ea7, + 0x3479, 0x057c, + 0x347b, 0x1ea8, + 0x347c, 0x057f, + 0x3521, 0x0582, + 0x3523, 0x1ea9, + 0x3524, 0x0585, + 0x3525, 0x1eaa, + 0x3529, 0x058a, + 0x352c, 0x1eae, + 0x352d, 0x058e, + 0x352e, 0x1eaf, + 0x3530, 0x0591, + 0x3531, 0x1eb1, + 0x3536, 0x0597, + 0x3537, 0x1eb6, + 0x3538, 0x0599, + 0x353a, 0x1eb7, + 0x353d, 0x059e, + 0x3546, 0x1eba, + 0x3547, 0x05a8, + 0x354b, 0x1ebb, + 0x354c, 0x05ad, + 0x3550, 0x1ebc, + 0x3551, 0x05b2, + 0x3553, 0x1ebd, + 0x3554, 0x05b5, + 0x355d, 0x1ebe, + 0x3560, 0x05c1, + 0x3563, 0x1ec1, + 0x3564, 0x05c5, + 0x3566, 0x1ec2, + 0x3568, 0x05c9, + 0x356d, 0x1ec4, + 0x356e, 0x05cf, + 0x3576, 0x1ec5, + 0x3578, 0x05d9, + 0x357d, 0x1ec7, + 0x357e, 0x05df, + 0x3621, 0x05e0, + 0x3624, 0x1ec8, + 0x3626, 0x05e5, + 0x3627, 0x1eca, + 0x3628, 0x05e7, + 0x3629, 0x1ecb, + 0x362a, 0x05e9, + 0x362b, 0x1ecc, + 0x362c, 0x05eb, + 0x362f, 0x1ecd, + 0x3631, 0x05f0, + 0x3633, 0x1ecf, + 0x3634, 0x05f3, + 0x3637, 0x1ed0, + 0x3638, 0x05f7, + 0x363f, 0x1ed1, + 0x3642, 0x0601, + 0x3644, 0x1ed4, + 0x3645, 0x0604, + 0x3646, 0x1ed5, + 0x3647, 0x0606, + 0x364d, 0x1ed6, + 0x364e, 0x060d, + 0x364f, 0x1ed7, + 0x3651, 0x0610, + 0x3653, 0x1ed9, + 0x3655, 0x0614, + 0x3656, 0x1edb, + 0x3657, 0x0616, + 0x3659, 0x1edc, + 0x365a, 0x0619, + 0x365b, 0x1edd, + 0x365c, 0x061b, + 0x3661, 0x1ede, + 0x3662, 0x0621, + 0x3669, 0x1edf, + 0x366a, 0x0629, + 0x366c, 0x1ee0, + 0x366d, 0x062c, + 0x366e, 0x1ee1, + 0x3670, 0x062f, + 0x3671, 0x1ee3, + 0x3672, 0x0631, + 0x3676, 0x1ee4, + 0x3677, 0x0636, + 0x3679, 0x1ee5, + 0x367a, 0x0639, + 0x367b, 0x1ee6, + 0x367d, 0x063c, + 0x3721, 0x1ee8, + 0x3724, 0x0641, + 0x3727, 0x1eeb, + 0x3728, 0x0645, + 0x372f, 0x1eec, + 0x3731, 0x064e, + 0x3733, 0x1eee, + 0x3734, 0x0651, + 0x3736, 0x1eef, + 0x3738, 0x0655, + 0x3739, 0x1ef1, + 0x373a, 0x0657, + 0x3743, 0x1ef2, + 0x3745, 0x0662, + 0x3749, 0x1ef4, + 0x374a, 0x0667, + 0x374c, 0x1ef5, + 0x374d, 0x066a, + 0x374f, 0x1ef6, + 0x3750, 0x066d, + 0x3751, 0x1ef7, + 0x3752, 0x066f, + 0x3757, 0x1ef8, + 0x3759, 0x0676, + 0x375c, 0x1efa, + 0x375d, 0x067a, + 0x375f, 0x1efb, + 0x3762, 0x067f, + 0x3763, 0x1efe, + 0x3764, 0x0681, + 0x3766, 0x1eff, + 0x3769, 0x0686, + 0x376b, 0x1f02, + 0x376e, 0x068b, + 0x376f, 0x1f05, + 0x3770, 0x068d, + 0x3774, 0x1f06, + 0x3775, 0x0692, + 0x3778, 0x1f07, + 0x3779, 0x0696, + 0x3821, 0x069c, + 0x3827, 0x1f08, + 0x3829, 0x06a4, + 0x3833, 0x1f0a, + 0x3835, 0x06b0, + 0x383a, 0x1f0c, + 0x383b, 0x06b6, + 0x383c, 0x1f0d, + 0x383d, 0x06b8, + 0x383e, 0x1f0e, + 0x3840, 0x06bb, + 0x3843, 0x1f10, + 0x3844, 0x06bf, + 0x3846, 0x1f11, + 0x3848, 0x06c3, + 0x3849, 0x1f13, + 0x384a, 0x06c5, + 0x384f, 0x1f14, + 0x3850, 0x06cb, + 0x3853, 0x1f15, + 0x3857, 0x06d2, + 0x3859, 0x1f19, + 0x385b, 0x06d6, + 0x3864, 0x1f1b, + 0x3865, 0x06e0, + 0x3869, 0x1f1c, + 0x386a, 0x06e5, + 0x386b, 0x1f1d, + 0x386c, 0x06e7, + 0x3873, 0x1f1e, + 0x3874, 0x06ef, + 0x3875, 0x1f1f, + 0x3877, 0x06f2, + 0x3878, 0x1f21, + 0x3879, 0x06f4, + 0x3921, 0x06fa, + 0x3928, 0x1f22, + 0x3929, 0x0702, + 0x392e, 0x1f23, + 0x392f, 0x0708, + 0x3931, 0x1f24, + 0x3932, 0x070b, + 0x3933, 0x1f25, + 0x3934, 0x070d, + 0x3935, 0x1f26, + 0x3936, 0x070f, + 0x3939, 0x1f27, + 0x393b, 0x0714, + 0x3946, 0x1f29, + 0x3947, 0x0720, + 0x394b, 0x1f2a, + 0x394c, 0x0725, + 0x3950, 0x1f2b, + 0x3951, 0x072a, + 0x3958, 0x1f2c, + 0x3959, 0x0732, + 0x395b, 0x1f2d, + 0x395c, 0x0735, + 0x395d, 0x1f2e, + 0x395e, 0x0737, + 0x395f, 0x1f2f, + 0x3960, 0x0739, + 0x3961, 0x1f30, + 0x3962, 0x073b, + 0x3963, 0x1f31, + 0x3964, 0x073d, + 0x3966, 0x1f32, + 0x3967, 0x0740, + 0x3969, 0x1f33, + 0x396d, 0x0746, + 0x396e, 0x1f37, + 0x396f, 0x0748, + 0x3971, 0x1f38, + 0x3972, 0x074b, + 0x3973, 0x1f39, + 0x3976, 0x074f, + 0x3978, 0x1f3c, + 0x3979, 0x0752, + 0x397a, 0x1f3d, + 0x397b, 0x0754, + 0x397d, 0x1f3e, + 0x397e, 0x0757, + 0x3a21, 0x0758, + 0x3a27, 0x1f3f, + 0x3a28, 0x075f, + 0x3a2b, 0x1f40, + 0x3a2c, 0x0763, + 0x3a3a, 0x1f41, + 0x3a3b, 0x0772, + 0x3a45, 0x1f42, + 0x3a46, 0x077d, + 0x3a52, 0x1f43, + 0x3a53, 0x078a, + 0x3a57, 0x1f44, + 0x3a59, 0x0790, + 0x3a64, 0x1f46, + 0x3a65, 0x079c, + 0x3a68, 0x1f47, + 0x3a69, 0x07a0, + 0x3a6c, 0x1f48, + 0x3a6d, 0x07a4, + 0x3a73, 0x15e5, + 0x3a74, 0x07ab, + 0x3a78, 0x1f49, + 0x3a79, 0x07b0, + 0x3b21, 0x07b6, + 0x3b24, 0x1f4a, + 0x3b25, 0x07ba, + 0x3b26, 0x1f4b, + 0x3b27, 0x07bc, + 0x3b29, 0x1f4c, + 0x3b2b, 0x07c0, + 0x3b2d, 0x1f4e, + 0x3b2f, 0x07c4, + 0x3b30, 0x1f50, + 0x3b31, 0x07c6, + 0x3b33, 0x1f51, + 0x3b34, 0x07c9, + 0x3b35, 0x1f52, + 0x3b38, 0x07cd, + 0x3b39, 0x1f55, + 0x3b3b, 0x07d0, + 0x3b51, 0x1f57, + 0x3b52, 0x07e7, + 0x3b53, 0x1f58, + 0x3b55, 0x07ea, + 0x3b5f, 0x1f5a, + 0x3b68, 0x07fd, + 0x3b6b, 0x1f63, + 0x3b6c, 0x0801, + 0x3b71, 0x1f64, + 0x3b72, 0x0807, + 0x3b75, 0x1f65, + 0x3b78, 0x080d, + 0x3b7a, 0x1f68, + 0x3b7b, 0x0810, + 0x3b7d, 0x1f69, + 0x3b7e, 0x0813, + 0x3c21, 0x0814, + 0x3c22, 0x1f6a, + 0x3c23, 0x0816, + 0x3c25, 0x1f6b, + 0x3c27, 0x081a, + 0x3c28, 0x1f6d, + 0x3c2a, 0x081d, + 0x3c2b, 0x1f6f, + 0x3c2c, 0x081f, + 0x3c2d, 0x1f70, + 0x3c2e, 0x0821, + 0x3c36, 0x1f71, + 0x3c39, 0x082c, + 0x3c3b, 0x1f74, + 0x3c3c, 0x082f, + 0x3c41, 0x1f75, + 0x3c42, 0x0835, + 0x3c43, 0x1f76, + 0x3c44, 0x0837, + 0x3c46, 0x1f77, + 0x3c48, 0x083b, + 0x3c4a, 0x1f79, + 0x3c4b, 0x083e, + 0x3c4c, 0x1f7a, + 0x3c4e, 0x0841, + 0x3c50, 0x1f7c, + 0x3c51, 0x0844, + 0x3c54, 0x1f7d, + 0x3c57, 0x084a, + 0x3c58, 0x1f80, + 0x3c59, 0x084c, + 0x3c5b, 0x1f81, + 0x3c5c, 0x084f, + 0x3c5d, 0x1f82, + 0x3c5e, 0x0851, + 0x3c5f, 0x1f83, + 0x3c62, 0x0855, + 0x3c63, 0x1f86, + 0x3c65, 0x0858, + 0x3c68, 0x1f88, + 0x3c69, 0x085c, + 0x3c6a, 0x1f89, + 0x3c6d, 0x0860, + 0x3c6f, 0x1f8c, + 0x3c74, 0x0867, + 0x3c76, 0x1f91, + 0x3c7d, 0x0870, + 0x3d21, 0x0872, + 0x3d22, 0x1f98, + 0x3d28, 0x0879, + 0x3d2b, 0x1f9e, + 0x3d2d, 0x087e, + 0x3d2f, 0x1fa0, + 0x3d33, 0x0884, + 0x3d34, 0x1fa4, + 0x3d35, 0x0886, + 0x3d3a, 0x1fa5, + 0x3d3b, 0x088c, + 0x3d3d, 0x1fa6, + 0x3d40, 0x0891, + 0x3d41, 0x1fa9, + 0x3d45, 0x0896, + 0x3d48, 0x1fad, + 0x3d4b, 0x089c, + 0x3d4e, 0x1fb0, + 0x3d50, 0x08a1, + 0x3d57, 0x1fb2, + 0x3d58, 0x08a9, + 0x3d5a, 0x1fb3, + 0x3d5b, 0x08ac, + 0x3d60, 0x1fb4, + 0x3d62, 0x08b3, + 0x3d6b, 0x1fb6, + 0x3d6c, 0x08bd, + 0x3d74, 0x1fb7, + 0x3d79, 0x08ca, + 0x3d7d, 0x1fbc, + 0x3d7e, 0x08cf, + 0x3e21, 0x1fbd, + 0x3e23, 0x08d2, + 0x3e25, 0x1fbf, + 0x3e26, 0x08d5, + 0x3e28, 0x1fc0, + 0x3e29, 0x08d8, + 0x3e2a, 0x1fc1, + 0x3e2b, 0x08da, + 0x3e2d, 0x1fc2, + 0x3e2e, 0x08dd, + 0x3e31, 0x1fc3, + 0x3e32, 0x08e1, + 0x3e35, 0x1fc4, + 0x3e38, 0x08e7, + 0x3e3a, 0x1fc7, + 0x3e3b, 0x08ea, + 0x3e40, 0x1fc8, + 0x3e41, 0x08f0, + 0x3e49, 0x1fc9, + 0x3e4a, 0x08f9, + 0x3e54, 0x1fca, + 0x3e55, 0x0904, + 0x3e59, 0x1fcb, + 0x3e5a, 0x0909, + 0x3e5d, 0x1fcc, + 0x3e5e, 0x090d, + 0x3e62, 0x1fcd, + 0x3e63, 0x0912, + 0x3e65, 0x1fce, + 0x3e66, 0x0915, + 0x3e67, 0x1fcf, + 0x3e68, 0x0917, + 0x3e69, 0x1fd0, + 0x3e6a, 0x0919, + 0x3e6e, 0x1fd1, + 0x3e6f, 0x091e, + 0x3e75, 0x1fd2, + 0x3e76, 0x0925, + 0x3e77, 0x1fd3, + 0x3e79, 0x0928, + 0x3e7b, 0x1fd5, + 0x3e7d, 0x092c, + 0x3f21, 0x092e, + 0x3f25, 0x1fd7, + 0x3f26, 0x0933, + 0x3f2a, 0x1fd8, + 0x3f2b, 0x0938, + 0x3f2d, 0x1fd9, + 0x3f2e, 0x093b, + 0x3f45, 0x1fda, + 0x3f46, 0x0953, + 0x3f47, 0x1fdb, + 0x3f48, 0x0955, + 0x3f4e, 0x1fdc, + 0x3f4f, 0x095c, + 0x3f51, 0x1fdd, + 0x3f53, 0x0960, + 0x3f59, 0x1fdf, + 0x3f5a, 0x0967, + 0x3f62, 0x1fe0, + 0x3f65, 0x0972, + 0x3f69, 0x1fe3, + 0x3f6a, 0x0977, + 0x3f6b, 0x1fe4, + 0x3f6c, 0x0979, + 0x3f6d, 0x1fe5, + 0x3f6e, 0x097b, + 0x3f73, 0x1fe6, + 0x3f74, 0x0981, + 0x3f75, 0x1fe7, + 0x3f76, 0x0983, + 0x3f77, 0x1fe8, + 0x3f78, 0x0985, + 0x3f79, 0x1fe9, + 0x3f7b, 0x0988, + 0x4021, 0x1feb, + 0x4022, 0x098d, + 0x4023, 0x1fec, + 0x4024, 0x098f, + 0x4029, 0x1fed, + 0x402a, 0x0995, + 0x402b, 0x1fee, + 0x402c, 0x0997, + 0x402f, 0x1fef, + 0x4031, 0x099c, + 0x4033, 0x1ff1, + 0x4037, 0x09a2, + 0x4038, 0x1ff5, + 0x4045, 0x09b0, + 0x404c, 0x2002, + 0x404e, 0x09b9, + 0x4054, 0x2004, + 0x4055, 0x09c0, + 0x4056, 0x2005, + 0x4057, 0x09c2, + 0x4058, 0x2006, + 0x4059, 0x09c4, + 0x405d, 0x2007, + 0x405e, 0x09c9, + 0x4060, 0x2008, + 0x4061, 0x09cc, + 0x4069, 0x2009, + 0x406a, 0x09d5, + 0x406b, 0x200a, + 0x406d, 0x09d8, + 0x406f, 0x200c, + 0x4072, 0x09dd, + 0x4076, 0x200f, + 0x407b, 0x09e6, + 0x4121, 0x09ea, + 0x4124, 0x2014, + 0x4126, 0x09ef, + 0x4129, 0x2016, + 0x412e, 0x09f7, + 0x412f, 0x201b, + 0x4139, 0x0a02, + 0x413d, 0x2025, + 0x413f, 0x0a08, + 0x4142, 0x2027, + 0x4143, 0x0a0c, + 0x4146, 0x2028, + 0x4147, 0x0a10, + 0x4149, 0x2029, + 0x414a, 0x0a13, + 0x414d, 0x202a, + 0x414e, 0x0a17, + 0x4154, 0x202b, + 0x4155, 0x0a1e, + 0x4159, 0x202c, + 0x415c, 0x0a25, + 0x415e, 0x202f, + 0x415f, 0x0a28, + 0x4164, 0x2030, + 0x4166, 0x0a2f, + 0x4169, 0x2032, + 0x416a, 0x0a33, + 0x416b, 0x2033, + 0x416d, 0x0a36, + 0x4173, 0x2035, + 0x4174, 0x0a3d, + 0x4175, 0x2036, + 0x4176, 0x0a3f, + 0x417a, 0x2037, + 0x417e, 0x0a47, + 0x4221, 0x0a48, + 0x4222, 0x203b, + 0x4229, 0x0a50, + 0x422b, 0x2042, + 0x4234, 0x0a5b, + 0x4238, 0x204b, + 0x4239, 0x0a60, + 0x423c, 0x204c, + 0x423e, 0x0a65, + 0x423f, 0x204e, + 0x4240, 0x0a67, + 0x4241, 0x204f, + 0x4242, 0x0a69, + 0x4245, 0x2050, + 0x4248, 0x0a6f, + 0x424b, 0x2053, + 0x4251, 0x0a78, + 0x4252, 0x2059, + 0x4253, 0x0a7a, + 0x4255, 0x205a, + 0x425d, 0x0a84, + 0x425e, 0x2062, + 0x4263, 0x0a8a, + 0x4266, 0x2067, + 0x4269, 0x0a90, + 0x426a, 0x206a, + 0x426f, 0x0a96, + 0x4270, 0x206f, + 0x4271, 0x0a98, + 0x4272, 0x2070, + 0x4276, 0x0a9d, + 0x4277, 0x2074, + 0x427b, 0x0aa2, + 0x4321, 0x2078, + 0x4322, 0x0aa7, + 0x432a, 0x2079, + 0x432b, 0x0ab0, + 0x432d, 0x207a, + 0x432e, 0x0ab3, + 0x4333, 0x207b, + 0x4334, 0x1df9, + 0x4335, 0x0aba, + 0x433e, 0x207c, + 0x433f, 0x0ac4, + 0x4345, 0x207d, + 0x4348, 0x0acd, + 0x434c, 0x2080, + 0x434d, 0x0ad2, + 0x434e, 0x2081, + 0x434f, 0x0ad4, + 0x4355, 0x2082, + 0x4357, 0x0adc, + 0x4359, 0x2084, + 0x435a, 0x0adf, + 0x4360, 0x2085, + 0x4361, 0x0ae6, + 0x4365, 0x2086, + 0x4366, 0x0aeb, + 0x436d, 0x2087, + 0x436e, 0x0af3, + 0x4370, 0x2088, + 0x4371, 0x0af6, + 0x4375, 0x2089, + 0x4377, 0x0afc, + 0x4379, 0x208b, + 0x437b, 0x0b00, + 0x437d, 0x208d, + 0x437e, 0x0b03, + 0x4421, 0x0b04, + 0x4431, 0x208e, + 0x4432, 0x0b15, + 0x4436, 0x208f, + 0x4437, 0x0b1a, + 0x4446, 0x2090, + 0x4447, 0x0b2a, + 0x4449, 0x2091, + 0x444a, 0x0b2d, + 0x4451, 0x2092, + 0x4452, 0x0b35, + 0x4453, 0x2093, + 0x4457, 0x0b3a, + 0x4459, 0x2097, + 0x445a, 0x0b3d, + 0x4462, 0x2098, + 0x4463, 0x0b46, + 0x4465, 0x2099, + 0x4466, 0x0b49, + 0x446c, 0x209a, + 0x446d, 0x0b50, + 0x4470, 0x209b, + 0x4472, 0x0b55, + 0x4474, 0x209d, + 0x4475, 0x0b58, + 0x4476, 0x209e, + 0x4479, 0x0b5c, + 0x447b, 0x20a1, + 0x447d, 0x0b60, + 0x447e, 0x20a3, + 0x4521, 0x20a4, + 0x4523, 0x0b64, + 0x4525, 0x20a6, + 0x452a, 0x0b6b, + 0x4531, 0x20ab, + 0x4532, 0x0b73, + 0x4535, 0x20ac, + 0x4536, 0x0b77, + 0x4537, 0x20ad, + 0x453a, 0x0b7b, + 0x453b, 0x20b0, + 0x453c, 0x0b7d, + 0x453d, 0x20b1, + 0x453e, 0x0b7f, + 0x454c, 0x20b2, + 0x454d, 0x0b8e, + 0x4553, 0x20b3, + 0x4554, 0x0b95, + 0x4562, 0x20b4, + 0x4563, 0x0ba4, + 0x4567, 0x20b5, + 0x4568, 0x0ba9, + 0x4574, 0x20b6, + 0x4575, 0x0bb6, + 0x4621, 0x0bc0, + 0x462d, 0x20b7, + 0x462f, 0x0bce, + 0x4635, 0x20b9, + 0x4637, 0x0bd6, + 0x463b, 0x20bb, + 0x463c, 0x0bdb, + 0x463e, 0x20bc, + 0x463f, 0x0bde, + 0x4640, 0x20bd, + 0x4641, 0x0be0, + 0x4643, 0x20be, + 0x4645, 0x0be4, + 0x464b, 0x20c0, + 0x464e, 0x0bed, + 0x4653, 0x20c3, + 0x4654, 0x0bf3, + 0x4657, 0x20c4, + 0x4658, 0x0bf7, + 0x466a, 0x20c5, + 0x466c, 0x0c0b, + 0x466f, 0x20c7, + 0x4670, 0x0c0f, + 0x4671, 0x20c8, + 0x4672, 0x0c11, + 0x4674, 0x20c9, + 0x4675, 0x0c14, + 0x4678, 0x20ca, + 0x4679, 0x0c18, + 0x467d, 0x20cb, + 0x467e, 0x0c1d, + 0x4721, 0x0c1e, + 0x4723, 0x20cc, + 0x4724, 0x0c21, + 0x4725, 0x20cd, + 0x4727, 0x0c24, + 0x4728, 0x20cf, + 0x472a, 0x0c27, + 0x472b, 0x20d1, + 0x472c, 0x0c29, + 0x472e, 0x20d2, + 0x4730, 0x0c2d, + 0x4733, 0x20d4, + 0x4736, 0x0c33, + 0x4739, 0x20d7, + 0x473b, 0x0c38, + 0x473d, 0x20d9, + 0x473f, 0x0c3c, + 0x4740, 0x20db, + 0x4741, 0x0c3e, + 0x4742, 0x20dc, + 0x4743, 0x0c40, + 0x4745, 0x20dd, + 0x4746, 0x0c43, + 0x4747, 0x20de, + 0x4749, 0x0c46, + 0x474c, 0x20e0, + 0x474d, 0x0c4a, + 0x474f, 0x20e1, + 0x4750, 0x0c4d, + 0x4754, 0x20e2, + 0x4756, 0x0c53, + 0x4757, 0x20e4, + 0x4758, 0x0c55, + 0x475e, 0x20e5, + 0x475f, 0x0c5c, + 0x4761, 0x20e6, + 0x4764, 0x0c61, + 0x476a, 0x20e9, + 0x476f, 0x0c6c, + 0x4777, 0x20ee, + 0x4779, 0x0c76, + 0x477b, 0x20f0, + 0x477c, 0x0c79, + 0x477d, 0x20f1, + 0x477e, 0x0c7b, + 0x4821, 0x0c7c, + 0x4823, 0x20f2, + 0x4824, 0x0c7f, + 0x4827, 0x20f3, + 0x4829, 0x0c84, + 0x4830, 0x20f5, + 0x4831, 0x0c8c, + 0x4835, 0x20f6, + 0x4836, 0x0c91, + 0x4837, 0x20f7, + 0x4838, 0x0c93, + 0x4843, 0x20f8, + 0x4847, 0x0ca2, + 0x4848, 0x20fc, + 0x4849, 0x0ca4, + 0x484d, 0x20fd, + 0x484e, 0x0ca9, + 0x484f, 0x20fe, + 0x4850, 0x0cab, + 0x4852, 0x20ff, + 0x4853, 0x0cae, + 0x4859, 0x2100, + 0x485a, 0x0cb5, + 0x485e, 0x2101, + 0x485f, 0x0cba, + 0x486d, 0x2102, + 0x486e, 0x0cc9, + 0x4871, 0x2103, + 0x4874, 0x0ccf, + 0x4877, 0x2106, + 0x4879, 0x0cd4, + 0x487a, 0x2108, + 0x487b, 0x0cd6, + 0x487c, 0x2109, + 0x487d, 0x0cd8, + 0x4921, 0x210a, + 0x4922, 0x0cdb, + 0x4925, 0x210b, + 0x4926, 0x0cdf, + 0x4927, 0x210c, + 0x4929, 0x0ce2, + 0x492c, 0x210e, + 0x492d, 0x0ce6, + 0x4931, 0x210f, + 0x4932, 0x0ceb, + 0x4934, 0x2110, + 0x4935, 0x0cee, + 0x4938, 0x2111, + 0x493a, 0x0cf3, + 0x4941, 0x2113, + 0x4943, 0x0cfc, + 0x4944, 0x2115, + 0x4945, 0x0cfe, + 0x4949, 0x2116, + 0x494a, 0x0d03, + 0x494b, 0x2117, + 0x494c, 0x0d05, + 0x494d, 0x2118, + 0x494e, 0x0d07, + 0x4955, 0x2119, + 0x4956, 0x0d0f, + 0x495c, 0x211a, + 0x495d, 0x0d16, + 0x495e, 0x211b, + 0x495f, 0x0d18, + 0x4961, 0x211c, + 0x4962, 0x0d1b, + 0x4963, 0x211d, + 0x4964, 0x0d1d, + 0x4965, 0x211e, + 0x4966, 0x0d1f, + 0x4968, 0x211f, + 0x4969, 0x0d22, + 0x4970, 0x2120, + 0x4971, 0x0d2a, + 0x4973, 0x2121, + 0x4975, 0x0d2e, + 0x4976, 0x2123, + 0x4977, 0x0d30, + 0x4978, 0x2124, + 0x497a, 0x0d33, + 0x497e, 0x2126, + 0x4a21, 0x0d38, + 0x4a24, 0x2127, + 0x4a27, 0x0d3e, + 0x4a28, 0x212a, + 0x4a29, 0x0d40, + 0x4a2a, 0x212b, + 0x4a2c, 0x0d43, + 0x4a31, 0x212d, + 0x4a32, 0x0d49, + 0x4a34, 0x212e, + 0x4a37, 0x0d4e, + 0x4a3b, 0x2131, + 0x4a3c, 0x0d53, + 0x4a46, 0x2132, + 0x4a47, 0x0d5e, + 0x4a4a, 0x2133, + 0x4a4b, 0x0d62, + 0x4a4d, 0x2134, + 0x4a4f, 0x0d66, + 0x4a53, 0x2136, + 0x4a55, 0x0d6c, + 0x4a59, 0x2138, + 0x4a5a, 0x0d71, + 0x4a5e, 0x2139, + 0x4a5f, 0x0d76, + 0x4a60, 0x213a, + 0x4a61, 0x0d78, + 0x4a64, 0x213b, + 0x4a65, 0x0d7c, + 0x4a69, 0x213c, + 0x4a6b, 0x0d82, + 0x4a74, 0x213e, + 0x4a76, 0x0d8d, + 0x4a77, 0x2140, + 0x4a78, 0x0d8f, + 0x4a7a, 0x2141, + 0x4a7b, 0x0d92, + 0x4a7d, 0x2142, + 0x4a7e, 0x0d95, + 0x4b21, 0x0d96, + 0x4b27, 0x2143, + 0x4b28, 0x0d9d, + 0x4b2b, 0x2144, + 0x4b2c, 0x0da1, + 0x4b2d, 0x2145, + 0x4b2e, 0x0da3, + 0x4b33, 0x2146, + 0x4b34, 0x0da9, + 0x4b35, 0x2147, + 0x4b37, 0x0dac, + 0x4b38, 0x2149, + 0x4b39, 0x0dae, + 0x4b3f, 0x214a, + 0x4b40, 0x0db5, + 0x4b47, 0x214b, + 0x4b48, 0x0dbd, + 0x4b49, 0x214c, + 0x4b4d, 0x0dc2, + 0x4b4f, 0x2150, + 0x4b51, 0x0dc6, + 0x4b53, 0x2152, + 0x4b54, 0x0dc9, + 0x4b55, 0x2153, + 0x4b56, 0x0dcb, + 0x4b5f, 0x2154, + 0x4b61, 0x0dd6, + 0x4b64, 0x2156, + 0x4b65, 0x0dda, + 0x4b66, 0x2157, + 0x4b68, 0x0ddd, + 0x4b6a, 0x2159, + 0x4b6b, 0x0de0, + 0x4b6f, 0x215a, + 0x4b71, 0x0de6, + 0x4b75, 0x215c, + 0x4b77, 0x0dec, + 0x4b78, 0x215e, + 0x4b79, 0x0dee, + 0x4c21, 0x215f, + 0x4c23, 0x0df6, + 0x4c28, 0x2161, + 0x4c29, 0x0dfc, + 0x4c2c, 0x2162, + 0x4c2d, 0x0e00, + 0x4c2f, 0x2163, + 0x4c34, 0x0e07, + 0x4c37, 0x2168, + 0x4c39, 0x0e0c, + 0x4c3e, 0x216a, + 0x4c3f, 0x0e12, + 0x4c40, 0x216b, + 0x4c41, 0x0e14, + 0x4c4c, 0x216c, + 0x4c4d, 0x0e20, + 0x4c4e, 0x216d, + 0x4c4f, 0x0e22, + 0x4c50, 0x216e, + 0x4c51, 0x0e24, + 0x4c56, 0x216f, + 0x4c57, 0x0e2a, + 0x4c5a, 0x2170, + 0x4c5b, 0x0e2e, + 0x4c5c, 0x2171, + 0x4c5d, 0x0e30, + 0x4c60, 0x2172, + 0x4c61, 0x0e34, + 0x4c62, 0x2173, + 0x4c63, 0x0e36, + 0x4c65, 0x2174, + 0x4c66, 0x0e39, + 0x4c75, 0x2175, + 0x4c76, 0x0e49, + 0x4c79, 0x2176, + 0x4c7b, 0x0e4e, + 0x4c7c, 0x2178, + 0x4d21, 0x0e52, + 0x4d2d, 0x217b, + 0x4d2e, 0x0e5f, + 0x4d33, 0x217c, + 0x4d34, 0x0e65, + 0x4d37, 0x217d, + 0x4d38, 0x0e69, + 0x4d3c, 0x217e, + 0x4d3d, 0x0e6e, + 0x4d3f, 0x217f, + 0x4d40, 0x0e71, + 0x4d45, 0x2180, + 0x4d46, 0x0e77, + 0x4d47, 0x2181, + 0x4d48, 0x0e79, + 0x4d52, 0x2182, + 0x4d53, 0x0e84, + 0x4d54, 0x2183, + 0x4d57, 0x0e88, + 0x4d5d, 0x2186, + 0x4d5e, 0x0e8f, + 0x4d60, 0x2187, + 0x4d61, 0x0e92, + 0x4d64, 0x2188, + 0x4d66, 0x0e97, + 0x4d67, 0x218a, + 0x4d68, 0x0e99, + 0x4d72, 0x218b, + 0x4d73, 0x0ea4, + 0x4d78, 0x218c, + 0x4d79, 0x0eaa, + 0x4e21, 0x0eb0, + 0x4e24, 0x218d, + 0x4e26, 0x0eb5, + 0x4e27, 0x218f, + 0x4e28, 0x0eb7, + 0x4e2a, 0x2190, + 0x4e2e, 0x0ebd, + 0x4e30, 0x2194, + 0x4e32, 0x0ec1, + 0x4e33, 0x2196, + 0x4e34, 0x0ec3, + 0x4e3d, 0x2197, + 0x4e3e, 0x0ecd, + 0x4e40, 0x2198, + 0x4e41, 0x0ed0, + 0x4e45, 0x2199, + 0x4e47, 0x0ed6, + 0x4e48, 0x219b, + 0x4e49, 0x0ed8, + 0x4e4a, 0x219c, + 0x4e4b, 0x0eda, + 0x4e4e, 0x219d, + 0x4e52, 0x0ee1, + 0x4e58, 0x21a1, + 0x4e5b, 0x0eea, + 0x4e5c, 0x21a4, + 0x4e5d, 0x0eec, + 0x4e5e, 0x21a5, + 0x4e60, 0x0eef, + 0x4e6b, 0x21a7, + 0x4e6c, 0x0efb, + 0x4e6d, 0x21a8, + 0x4e6e, 0x0efd, + 0x4e71, 0x21a9, + 0x4e72, 0x0f01, + 0x4e73, 0x21aa, + 0x4e74, 0x0f03, + 0x4e7d, 0x21ab, + 0x4f21, 0x0f0e, + 0x4f2e, 0x21ad, + 0x4f2f, 0x0f1c, + 0x4f30, 0x21ae, + 0x4f31, 0x0f1e, + 0x4f33, 0x21af, + 0x4f34, 0x0f21, + 0x4f37, 0x21b0, + 0x4f39, 0x0f26, + 0x4f3a, 0x21b2, + 0x4f3b, 0x0f28, + 0x4f3d, 0x21b3, + 0x4f3e, 0x0f2b, + 0x4f3f, 0x21b4, + 0x4f42, 0x0f2f, + 0x4f45, 0x21b7, + 0x4f46, 0x0f33, + 0x4f47, 0x21b8, + 0x4f48, 0x0f35, + 0x4f4a, 0x21b9, + 0x4f4c, 0x0f39, + 0x4f4d, 0x21bb, + 0x4f4f, 0x0f3c, + 0x4f50, 0x21bd, + 0x4f51, 0x0f3e, + 0x4f54, 0x21be, + 0x4f59, 0x0f46, + 0x4f5a, 0x21c3, + 0x4f5b, 0x0f48, + 0x4f5c, 0x21c4, + 0x4f5d, 0x0f4a, + 0x4f5f, 0x21c5, + 0x4f60, 0x0f4d, + 0x4f62, 0x21c6, + 0x4f63, 0x0f50, + 0x4f67, 0x21c7, + 0x4f68, 0x0f55, + 0x4f6a, 0x21c8, + 0x4f6b, 0x0f58, + 0x4f6c, 0x21c9, + 0x4f6d, 0x0f5a, + 0x4f6e, 0x21ca, + 0x4f6f, 0x0f5c, + 0x4f74, 0x21cb, + 0x4f75, 0x0f62, + 0x4f79, 0x21cc, + 0x4f7b, 0x0f68, + 0x4f7e, 0x21ce, + 0x5021, 0x0f6c, + 0x5025, 0x21cf, + 0x5026, 0x0f71, + 0x502d, 0x21d0, + 0x502f, 0x0f7a, + 0x5032, 0x21d2, + 0x5035, 0x0f80, + 0x503a, 0x21d5, + 0x503c, 0x0f87, + 0x503f, 0x21d7, + 0x5040, 0x0f8b, + 0x5046, 0x21d8, + 0x5047, 0x0f92, + 0x504b, 0x21d9, + 0x504c, 0x0f97, + 0x5062, 0x21da, + 0x5063, 0x0fae, + 0x5065, 0x21db, + 0x5066, 0x0fb1, + 0x506b, 0x21dc, + 0x506c, 0x0fb7, + 0x506d, 0x21dd, + 0x506e, 0x0fb9, + 0x5077, 0x21de, + 0x507a, 0x0fc5, + 0x507c, 0x21e1, + 0x507d, 0x0fc8, + 0x5121, 0x21e2, + 0x5123, 0x0fcc, + 0x5124, 0x21e4, + 0x5125, 0x0fce, + 0x5127, 0x21e5, + 0x5128, 0x0fd1, + 0x512b, 0x21e6, + 0x512c, 0x0fd5, + 0x512f, 0x21e7, + 0x5132, 0x0fdb, + 0x5135, 0x21ea, + 0x5138, 0x0fe1, + 0x5139, 0x21ed, + 0x513a, 0x0fe3, + 0x513b, 0x21ee, + 0x513d, 0x0fe6, + 0x5146, 0x21f0, + 0x5149, 0x0ff2, + 0x514b, 0x21f3, + 0x514c, 0x0ff5, + 0x514e, 0x21f4, + 0x5150, 0x0ff9, + 0x5155, 0x21f6, + 0x5157, 0x1000, + 0x515e, 0x21f8, + 0x515f, 0x1008, + 0x5161, 0x21f9, + 0x5163, 0x100c, + 0x5168, 0x21fb, + 0x516a, 0x1013, + 0x516c, 0x21fd, + 0x516d, 0x1016, + 0x516e, 0x21fe, + 0x5170, 0x1019, + 0x5171, 0x2200, + 0x5172, 0x101b, + 0x5174, 0x2201, + 0x5175, 0x101e, + 0x5177, 0x2202, + 0x517a, 0x1023, + 0x5221, 0x1028, + 0x5222, 0x2205, + 0x5223, 0x102a, + 0x5225, 0x2206, + 0x5226, 0x102d, + 0x5229, 0x2207, + 0x522a, 0x1031, + 0x522f, 0x2208, + 0x5230, 0x1037, + 0x5233, 0x2209, + 0x5234, 0x103b, + 0x5235, 0x220a, + 0x5237, 0x103e, + 0x523d, 0x220c, + 0x523e, 0x1045, + 0x523f, 0x220d, + 0x5240, 0x1047, + 0x5243, 0x220e, + 0x5244, 0x104b, + 0x5245, 0x220f, + 0x5246, 0x104d, + 0x5247, 0x2210, + 0x5248, 0x104f, + 0x524f, 0x2211, + 0x5250, 0x1057, + 0x5255, 0x2212, + 0x5256, 0x105d, + 0x525a, 0x2213, + 0x525b, 0x1062, + 0x5264, 0x2214, + 0x5266, 0x106d, + 0x5268, 0x2216, + 0x526c, 0x1073, + 0x526f, 0x221a, + 0x5270, 0x1077, + 0x5271, 0x221b, + 0x5272, 0x1079, + 0x5275, 0x221c, + 0x5276, 0x107d, + 0x5278, 0x221d, + 0x5279, 0x1080, + 0x527b, 0x221e, + 0x527c, 0x1083, + 0x527e, 0x221f, + 0x5321, 0x1086, + 0x5323, 0x2220, + 0x532d, 0x1092, + 0x532e, 0x222a, + 0x532f, 0x1094, + 0x5331, 0x222b, + 0x5332, 0x1097, + 0x5334, 0x222c, + 0x5337, 0x109c, + 0x5338, 0x222f, + 0x5339, 0x109e, + 0x533b, 0x2230, + 0x533c, 0x10a1, + 0x5345, 0x2231, + 0x5346, 0x10ab, + 0x5347, 0x2232, + 0x5348, 0x10ad, + 0x534a, 0x2233, + 0x534d, 0x10b2, + 0x5355, 0x2236, + 0x5356, 0x10bb, + 0x535f, 0x2237, + 0x5361, 0x10c6, + 0x5363, 0x2239, + 0x5364, 0x10c9, + 0x5366, 0x223a, + 0x5367, 0x10cc, + 0x536b, 0x223b, + 0x536d, 0x10d2, + 0x536f, 0x223d, + 0x5370, 0x10d5, + 0x5374, 0x223e, + 0x5375, 0x10da, + 0x537c, 0x223f, + 0x537d, 0x10e2, + 0x537e, 0x2240, + 0x5421, 0x10e4, + 0x5424, 0x2241, + 0x5425, 0x10e8, + 0x5426, 0x2242, + 0x5429, 0x10ec, + 0x542f, 0x2245, + 0x5433, 0x10f6, + 0x5435, 0x2249, + 0x5437, 0x10fa, + 0x5438, 0x224b, + 0x5439, 0x10fc, + 0x543c, 0x224c, + 0x543d, 0x1100, + 0x543e, 0x224d, + 0x5440, 0x1103, + 0x5444, 0x224f, + 0x5445, 0x1108, + 0x5446, 0x2250, + 0x5448, 0x110b, + 0x5449, 0x2252, + 0x544a, 0x110d, + 0x544b, 0x2253, + 0x544f, 0x1112, + 0x5453, 0x2257, + 0x5454, 0x1117, + 0x5458, 0x2258, + 0x5459, 0x111c, + 0x545c, 0x2259, + 0x5461, 0x1124, + 0x5464, 0x225e, + 0x5465, 0x1128, + 0x5466, 0x225f, + 0x5467, 0x112a, + 0x546e, 0x2260, + 0x546f, 0x1132, + 0x5470, 0x2261, + 0x5475, 0x1138, + 0x5479, 0x2266, + 0x547a, 0x113d, + 0x547e, 0x2267, + 0x5521, 0x2268, + 0x5523, 0x1144, + 0x5529, 0x226a, + 0x552a, 0x114b, + 0x552b, 0x226b, + 0x552c, 0x114d, + 0x552e, 0x226c, + 0x552f, 0x1150, + 0x5531, 0x226d, + 0x5532, 0x1153, + 0x5535, 0x226e, + 0x5539, 0x115a, + 0x553b, 0x2272, + 0x553c, 0x115d, + 0x553d, 0x2273, + 0x553e, 0x115f, + 0x5540, 0x2274, + 0x5541, 0x1162, + 0x5545, 0x2275, + 0x5546, 0x1167, + 0x5547, 0x2276, + 0x5548, 0x1169, + 0x554a, 0x2277, + 0x554c, 0x116d, + 0x554d, 0x2279, + 0x554e, 0x116f, + 0x5554, 0x227a, + 0x5555, 0x1176, + 0x555d, 0x227b, + 0x555f, 0x1180, + 0x5560, 0x227d, + 0x5561, 0x1182, + 0x5562, 0x227e, + 0x5563, 0x1184, + 0x556a, 0x227f, + 0x556d, 0x118e, + 0x556f, 0x2282, + 0x5570, 0x1191, + 0x5572, 0x2283, + 0x5574, 0x1195, + 0x5577, 0x15eb, + 0x5578, 0x1199, + 0x5621, 0x2285, + 0x5625, 0x11a4, + 0x562f, 0x2289, + 0x5631, 0x11b0, + 0x5634, 0x228b, + 0x5635, 0x11b4, + 0x563b, 0x228c, + 0x563c, 0x11bb, + 0x563d, 0x228d, + 0x563e, 0x11bd, + 0x563f, 0x228e, + 0x5641, 0x11c0, + 0x5644, 0x2290, + 0x5645, 0x11c4, + 0x564a, 0x2291, + 0x564b, 0x11ca, + 0x564d, 0x2292, + 0x564e, 0x11cd, + 0x5653, 0x2293, + 0x5654, 0x11d3, + 0x5655, 0x2294, + 0x5658, 0x11d7, + 0x565a, 0x2297, + 0x565b, 0x11da, + 0x565f, 0x2298, + 0x5660, 0x11df, + 0x5661, 0x2299, + 0x5662, 0x11e1, + 0x5665, 0x229a, + 0x5666, 0x11e5, + 0x5667, 0x229b, + 0x5669, 0x11e8, + 0x566e, 0x229d, + 0x5670, 0x11ef, + 0x5672, 0x229f, + 0x5673, 0x11f2, + 0x5675, 0x22a0, + 0x5677, 0x11f6, + 0x567c, 0x22a2, + 0x5721, 0x11fe, + 0x5724, 0x22a5, + 0x5725, 0x1202, + 0x5728, 0x22a6, + 0x572b, 0x1208, + 0x572c, 0x22a9, + 0x572d, 0x120a, + 0x572e, 0x22aa, + 0x5732, 0x120f, + 0x5733, 0x22ae, + 0x5735, 0x1212, + 0x5736, 0x22b0, + 0x5737, 0x1214, + 0x5738, 0x22b1, + 0x573d, 0x121a, + 0x5747, 0x22b6, + 0x5748, 0x1225, + 0x574a, 0x22b7, + 0x574b, 0x1228, + 0x5755, 0x22b8, + 0x5756, 0x1233, + 0x575b, 0x22b9, + 0x575f, 0x123c, + 0x5767, 0x22bd, + 0x5768, 0x1245, + 0x5769, 0x22be, + 0x576b, 0x1248, + 0x5821, 0x1257, + 0x5844, 0x22c0, + 0x5845, 0x127b, + 0x5847, 0x22c1, + 0x5848, 0x127e, + 0x5849, 0x22c2, + 0x584a, 0x1280, + 0x584c, 0x22c3, + 0x584e, 0x1284, + 0x5850, 0x22c5, + 0x5852, 0x1288, + 0x5853, 0x22c7, + 0x5854, 0x128a, + 0x5859, 0x22c8, + 0x585a, 0x1290, + 0x585b, 0x22c9, + 0x585d, 0x1293, + 0x5871, 0x22cb, + 0x5872, 0x12a8, + 0x5876, 0x22cc, + 0x5878, 0x12ae, + 0x5921, 0x12b5, + 0x592d, 0x22ce, + 0x592e, 0x12c2, + 0x592f, 0x22cf, + 0x5930, 0x12c4, + 0x5931, 0x22d0, + 0x5934, 0x12c8, + 0x5947, 0x22d3, + 0x5948, 0x12dc, + 0x594d, 0x22d4, + 0x5951, 0x12e5, + 0x595d, 0x22d8, + 0x595e, 0x12f2, + 0x5961, 0x22d9, + 0x5962, 0x12f6, + 0x5964, 0x22da, + 0x5965, 0x12f9, + 0x5966, 0x22db, + 0x5967, 0x12fb, + 0x596c, 0x22dc, + 0x596d, 0x1301, + 0x5974, 0x22dd, + 0x5976, 0x130a, + 0x5a21, 0x1313, + 0x5a25, 0x22df, + 0x5a60, 0x1352, + 0x5a6a, 0x231a, + 0x5a6b, 0x135d, + 0x5a77, 0x231b, + 0x5a78, 0x136a, + 0x5a79, 0x231c, + 0x5a7a, 0x136c, + 0x5a7e, 0x231d, + 0x5b21, 0x1371, + 0x5b23, 0x231e, + 0x5b24, 0x1374, + 0x5b26, 0x231f, + 0x5b27, 0x1377, + 0x5b29, 0x2320, + 0x5b2b, 0x137b, + 0x5b3b, 0x2322, + 0x5b3c, 0x138c, + 0x5b3d, 0x2323, + 0x5b3e, 0x138e, + 0x5b4f, 0x2324, + 0x5b50, 0x13a0, + 0x5b51, 0x2325, + 0x5b52, 0x13a2, + 0x5b5b, 0x2326, + 0x5b5c, 0x13ac, + 0x5b5e, 0x2327, + 0x5b5f, 0x13af, + 0x5b62, 0x2328, + 0x5b63, 0x13b3, + 0x5b64, 0x2329, + 0x5b65, 0x13b5, + 0x5b6b, 0x232a, + 0x5b6c, 0x13bc, + 0x5b6e, 0x232b, + 0x5b6f, 0x13bf, + 0x5b71, 0x232c, + 0x5b72, 0x13c2, + 0x5b75, 0x232d, + 0x5b78, 0x13c8, + 0x5c21, 0x13cf, + 0x5c3c, 0x2330, + 0x5c3d, 0x13eb, + 0x5c3f, 0x2331, + 0x5c40, 0x13ee, + 0x5c42, 0x2332, + 0x5c43, 0x13f1, + 0x5c48, 0x2333, + 0x5c4b, 0x13f9, + 0x5c51, 0x2336, + 0x5c52, 0x1400, + 0x5c57, 0x2337, + 0x5c58, 0x1406, + 0x5c60, 0x2338, + 0x5c61, 0x140f, + 0x5c63, 0x2339, + 0x5c65, 0x1413, + 0x5c69, 0x233b, + 0x5c6b, 0x1419, + 0x5c71, 0x233d, + 0x5c72, 0x1420, + 0x5c76, 0x233e, + 0x5c77, 0x1425, + 0x5c79, 0x233f, + 0x5c7a, 0x1428, + 0x5c7d, 0x2340, + 0x5d21, 0x2342, + 0x5d22, 0x142e, + 0x5d23, 0x2343, + 0x5d28, 0x1434, + 0x5d2a, 0x2348, + 0x5d2c, 0x1438, + 0x5d32, 0x234a, + 0x5d33, 0x143f, + 0x5d35, 0x234b, + 0x5d36, 0x1442, + 0x5d3a, 0x234c, + 0x5d3c, 0x1448, + 0x5d53, 0x234e, + 0x5d54, 0x1460, + 0x5d5b, 0x234f, + 0x5d5c, 0x1468, + 0x5d5e, 0x2350, + 0x5d5f, 0x146b, + 0x5d64, 0x2351, + 0x5d65, 0x1471, + 0x5d6b, 0x2352, + 0x5d6c, 0x1478, + 0x5d71, 0x2353, + 0x5d72, 0x147e, + 0x5d76, 0x2354, + 0x5d78, 0x1484, + 0x5d7c, 0x2356, + 0x5d7d, 0x1489, + 0x5d7e, 0x2357, + 0x5e21, 0x148b, + 0x5e2d, 0x2358, + 0x5e2e, 0x1498, + 0x5e34, 0x2359, + 0x5e35, 0x149f, + 0x5e3a, 0x235a, + 0x5e3b, 0x14a5, + 0x5e46, 0x235b, + 0x5e47, 0x14b1, + 0x5e4f, 0x235c, + 0x5e50, 0x14ba, + 0x5e51, 0x235d, + 0x5e53, 0x14bd, + 0x5e58, 0x235f, + 0x5e59, 0x14c3, + 0x5e62, 0x2360, + 0x5e63, 0x14cd, + 0x5e68, 0x2361, + 0x5e69, 0x14d3, + 0x5e6c, 0x2362, + 0x5e6d, 0x14d7, + 0x5e73, 0x2363, + 0x5e74, 0x14de, + 0x5e7c, 0x2364, + 0x5e7d, 0x14e7, + 0x5f21, 0x14e9, + 0x5f22, 0x2365, + 0x5f24, 0x14ec, + 0x5f25, 0x2367, + 0x5f26, 0x14ee, + 0x5f34, 0x2368, + 0x5f35, 0x14fd, + 0x5f3c, 0x2369, + 0x5f3e, 0x1506, + 0x5f3f, 0x236b, + 0x5f40, 0x1508, + 0x5f42, 0x236c, + 0x5f44, 0x150c, + 0x5f4c, 0x236e, + 0x5f4d, 0x1515, + 0x5f50, 0x236f, + 0x5f51, 0x1519, + 0x5f55, 0x2370, + 0x5f56, 0x151e, + 0x5f58, 0x2371, + 0x5f5a, 0x1522, + 0x5f5c, 0x2373, + 0x5f5d, 0x1525, + 0x5f60, 0x2374, + 0x5f61, 0x1529, + 0x5f62, 0x2375, + 0x5f63, 0x152b, + 0x5f66, 0x2376, + 0x5f67, 0x152f, + 0x5f69, 0x2377, + 0x5f6a, 0x1532, + 0x5f6b, 0x2378, + 0x5f6c, 0x1534, + 0x5f6f, 0x2379, + 0x5f70, 0x1538, + 0x5f75, 0x237a, + 0x5f76, 0x153e, + 0x5f79, 0x237b, + 0x5f7a, 0x1542, + 0x6021, 0x1547, + 0x6036, 0x237c, + 0x6038, 0x155e, + 0x603f, 0x237e, + 0x6040, 0x1566, + 0x6048, 0x237f, + 0x6049, 0x156f, + 0x604e, 0x2380, + 0x604f, 0x1575, + 0x6053, 0x2381, + 0x6054, 0x157a, + 0x6060, 0x2382, + 0x6061, 0x1587, + 0x6070, 0x2383, + 0x6071, 0x1597, + 0x6078, 0x2384, + 0x6079, 0x159f, + 0x607c, 0x2385, + 0x6121, 0x15a5, + 0x612b, 0x2388, + 0x612c, 0x15b0, + 0x612d, 0x2389, + 0x612e, 0x15b2, + 0x6130, 0x238a, + 0x6131, 0x15b5, + 0x6134, 0x238b, + 0x6135, 0x15b9, + 0x613b, 0x238c, + 0x613c, 0x15c0, + 0x613d, 0x238d, + 0x613e, 0x15c2, + 0x6140, 0x238e, + 0x6142, 0x15c6, + 0x6149, 0x2390, + 0x614a, 0x15ce, + 0x6150, 0x2391, + 0x6151, 0x15d5, + 0x615b, 0x2392, + 0x615c, 0x15e0, + 0x6161, 0x07aa, + 0x6162, 0x2393, + 0x6163, 0x15e7, + 0x6167, 0x1198, + 0x6168, 0x15ec, + 0x616e, 0x2394, + 0x6170, 0x15f4, + 0x6176, 0x2396, + 0x6177, 0x15fb, + 0x6178, 0x2397, + 0x6179, 0x15fd, + 0x617d, 0x2398, + 0x617e, 0x1602, + 0x6221, 0x1603, + 0x6224, 0x2399, + 0x6225, 0x1607, + 0x6228, 0x239a, + 0x6229, 0x160b, + 0x623b, 0x239b, + 0x6245, 0x10c5, + 0x6246, 0x23a5, + 0x624f, 0x1631, + 0x6250, 0x23ae, + 0x6251, 0x1633, + 0x6259, 0x23af, + 0x625a, 0x163c, + 0x6263, 0x23b0, + 0x6265, 0x1647, + 0x6266, 0x23b2, + 0x6267, 0x1649, + 0x6269, 0x23b3, + 0x626c, 0x164e, + 0x6278, 0x23b6, + 0x6279, 0x165b, + 0x627a, 0x23b7, + 0x627e, 0x1660, + 0x6321, 0x1661, + 0x6322, 0x23bb, + 0x6323, 0x1663, + 0x6325, 0x23bc, + 0x6326, 0x1666, + 0x632b, 0x23bd, + 0x632c, 0x166c, + 0x6334, 0x23be, + 0x6335, 0x1675, + 0x6345, 0x23bf, + 0x635c, 0x169c, + 0x6363, 0x23d6, + 0x6364, 0x16a4, + 0x636d, 0x23d7, + 0x636e, 0x16ae, + 0x6371, 0x23d8, + 0x6373, 0x16b3, + 0x6378, 0x23da, + 0x6379, 0x16b9, + 0x637e, 0x23db, + 0x6421, 0x16bf, + 0x6424, 0x23dc, + 0x6426, 0x16c4, + 0x642b, 0x23de, + 0x642c, 0x16ca, + 0x642f, 0x23df, + 0x6432, 0x16d0, + 0x6435, 0x23e2, + 0x6437, 0x16d5, + 0x6442, 0x23e4, + 0x6443, 0x16e1, + 0x6445, 0x23e5, + 0x6446, 0x16e4, + 0x6449, 0x23e6, + 0x644a, 0x16e8, + 0x6459, 0x23e7, + 0x645a, 0x16f8, + 0x645c, 0x23e8, + 0x645d, 0x16fb, + 0x645e, 0x23e9, + 0x645f, 0x16fd, + 0x6464, 0x23ea, + 0x6465, 0x1703, + 0x646b, 0x23eb, + 0x646d, 0x170b, + 0x6472, 0x23ed, + 0x6473, 0x1711, + 0x647e, 0x23ee, + 0x6521, 0x171d, + 0x6530, 0x23ef, + 0x6531, 0x172d, + 0x6539, 0x23f0, + 0x653a, 0x1736, + 0x6547, 0x23f1, + 0x6548, 0x1744, + 0x6549, 0x23f2, + 0x654a, 0x1746, + 0x654e, 0x23f3, + 0x654f, 0x174b, + 0x6570, 0x23f4, + 0x6571, 0x176d, + 0x6572, 0x23f5, + 0x6573, 0x176f, + 0x657c, 0x23f6, + 0x657e, 0x177a, + 0x6621, 0x177b, + 0x6623, 0x23f8, + 0x6624, 0x177e, + 0x662b, 0x23f9, + 0x662d, 0x1787, + 0x662e, 0x23fb, + 0x662f, 0x1789, + 0x6634, 0x23fc, + 0x6636, 0x1790, + 0x663f, 0x23fe, + 0x6640, 0x179a, + 0x6648, 0x23ff, + 0x664a, 0x17a4, + 0x664d, 0x2401, + 0x664e, 0x17a8, + 0x6660, 0x2402, + 0x6721, 0x2421, + 0x675b, 0x1813, + 0x6761, 0x245b, + 0x6763, 0x181b, + 0x6767, 0x245d, + 0x6768, 0x1820, + 0x676f, 0x245e, + 0x6770, 0x1828, + 0x6774, 0x245f, + 0x6777, 0x182f, + 0x6821, 0x1837, + 0x6828, 0x2462, + 0x6829, 0x183f, + 0x682c, 0x2463, + 0x682d, 0x1843, + 0x6836, 0x2464, + 0x6837, 0x184d, + 0x6838, 0x2465, + 0x683b, 0x1851, + 0x683f, 0x2468, + 0x6841, 0x1857, + 0x6845, 0x246a, + 0x6846, 0x185c, + 0x6847, 0x246b, + 0x684a, 0x1860, + 0x684e, 0x246e, + 0x684f, 0x1865, + 0x6850, 0x246f, + 0x6851, 0x1867, + 0x6853, 0x2470, + 0x6854, 0x186a, + 0x685d, 0x2471, + 0x685e, 0x1874, + 0x685f, 0x2472, + 0x6860, 0x1876, + 0x6862, 0x2473, + 0x6864, 0x187a, + 0x6865, 0x2475, + 0x6866, 0x187c, + 0x6867, 0x2476, + 0x6868, 0x187e, + 0x686b, 0x2477, + 0x686c, 0x1882, + 0x686d, 0x2478, + 0x686e, 0x1884, + 0x686f, 0x2479, + 0x6870, 0x1886, + 0x6879, 0x247a, + 0x687a, 0x1890, + 0x687c, 0x247b, + 0x687e, 0x1894, + 0x6921, 0x247d, + 0x6922, 0x1896, + 0x692d, 0x247e, + 0x692e, 0x18a2, + 0x6934, 0x247f, + 0x6936, 0x18aa, + 0x6937, 0x2481, + 0x6938, 0x18ac, + 0x6944, 0x2482, + 0x6945, 0x18b9, + 0x6946, 0x2483, + 0x6947, 0x18bb, + 0x6949, 0x2484, + 0x694a, 0x18be, + 0x6956, 0x2485, + 0x6957, 0x18cb, + 0x695a, 0x2486, + 0x695b, 0x18cf, + 0x6964, 0x2487, + 0x6965, 0x18d9, + 0x6966, 0x2488, + 0x6968, 0x18dc, + 0x6969, 0x248a, + 0x696a, 0x18de, + 0x696b, 0x248b, + 0x696c, 0x18e0, + 0x696d, 0x248c, + 0x6a21, 0x249e, + 0x6a26, 0x18f8, + 0x6a27, 0x24a3, + 0x6a29, 0x18fb, + 0x6a31, 0x24a5, + 0x6a32, 0x1904, + 0x6a3c, 0x24a6, + 0x6a3d, 0x190f, + 0x6a4a, 0x24a7, + 0x6a4b, 0x191d, + 0x6a4d, 0x24a8, + 0x6a4e, 0x1920, + 0x6a53, 0x24a9, + 0x6a54, 0x1926, + 0x6a5a, 0x24aa, + 0x6a70, 0x1942, + 0x6b21, 0x1951, + 0x6b27, 0x24c0, + 0x6b28, 0x1958, + 0x6b2a, 0x24c1, + 0x6b2b, 0x195b, + 0x6b32, 0x24c2, + 0x6b33, 0x1963, + 0x6b39, 0x24c3, + 0x6b3a, 0x196a, + 0x6b4a, 0x24c4, + 0x6b4c, 0x197c, + 0x6b4d, 0x24c6, + 0x6b4e, 0x197e, + 0x6b56, 0x24c7, + 0x6b57, 0x1987, + 0x6b5a, 0x24c8, + 0x6b5b, 0x198b, + 0x6b61, 0x24c9, + 0x6b62, 0x1992, + 0x6b77, 0x24ca, + 0x6b78, 0x19a8, + 0x6c21, 0x19af, + 0x6c23, 0x24cb, + 0x6c24, 0x19b2, + 0x6c29, 0x24cc, + 0x6c2f, 0x19bd, + 0x6c31, 0x24d2, + 0x6c32, 0x19c0, + 0x6c34, 0x24d3, + 0x6c36, 0x19c4, + 0x6c3e, 0x24d5, + 0x6c40, 0x19ce, + 0x6c41, 0x24d7, + 0x6c42, 0x19d0, + 0x6c47, 0x24d8, + 0x6c48, 0x19d6, + 0x6c4b, 0x24d9, + 0x6c4c, 0x19da, + 0x6c62, 0x24da, + 0x6c63, 0x19f1, + 0x6c72, 0x24db, + 0x6c73, 0x1a01, + 0x6c75, 0x24dc, + 0x6c76, 0x1a04, + 0x6c78, 0x24dd, + 0x6c79, 0x1a07, + 0x6d21, 0x24de, + 0x6d22, 0x1a0e, + 0x6d28, 0x24df, + 0x6d29, 0x1a15, + 0x6d2f, 0x24e0, + 0x6d31, 0x1a1d, + 0x6d34, 0x24e2, + 0x6d35, 0x1a21, + 0x6d36, 0x24e3, + 0x6d37, 0x1a23, + 0x6d38, 0x24e4, + 0x6d39, 0x1a25, + 0x6d3a, 0x24e5, + 0x6d3b, 0x1a27, + 0x6d3f, 0x24e6, + 0x6d40, 0x1a2c, + 0x6d42, 0x24e7, + 0x6d44, 0x1a30, + 0x6d4c, 0x24e9, + 0x6d4e, 0x1a3a, + 0x6d53, 0x24eb, + 0x6d54, 0x1a40, + 0x6d57, 0x24ec, + 0x6d58, 0x1a44, + 0x6d68, 0x24ed, + 0x6d69, 0x1a55, + 0x6d6e, 0x24ee, + 0x6d6f, 0x1a5b, + 0x6d79, 0x24ef, + 0x6d7b, 0x1a67, + 0x6e21, 0x1a6b, + 0x6e3c, 0x24f1, + 0x6e3d, 0x1a87, + 0x6e3f, 0x24f2, + 0x6e40, 0x1a8a, + 0x6e44, 0x24f3, + 0x6f21, 0x252e, + 0x6f72, 0x1b1a, + 0x7021, 0x1b27, + 0x7023, 0x257f, + 0x7024, 0x1b2a, + 0x702f, 0x2580, + 0x705a, 0x1b60, + 0x705c, 0x25ab, + 0x705e, 0x1b64, + 0x705f, 0x25ad, + 0x7060, 0x1b66, + 0x7069, 0x25ae, + 0x706a, 0x1b70, + 0x706c, 0x25af, + 0x706d, 0x1b73, + 0x706f, 0x25b0, + 0x7070, 0x1b76, + 0x7077, 0x25b1, + 0x7078, 0x1b7e, + 0x7079, 0x25b2, + 0x707a, 0x1b80, + 0x707c, 0x25b3, + 0x707d, 0x1b83, + 0x7121, 0x1b85, + 0x7128, 0x25b4, + 0x7129, 0x1b8d, + 0x712b, 0x25b5, + 0x712c, 0x1b90, + 0x712e, 0x25b6, + 0x712f, 0x1b93, + 0x7132, 0x25b7, + 0x7133, 0x1b97, + 0x713c, 0x25b8, + 0x713d, 0x1ba1, + 0x7140, 0x25b9, + 0x7141, 0x1ba5, + 0x7149, 0x25ba, + 0x714a, 0x1bae, + 0x714d, 0x25bb, + 0x714e, 0x1bb2, + 0x714f, 0x25bc, + 0x7151, 0x1bb5, + 0x715a, 0x25be, + 0x715b, 0x1bbf, + 0x715c, 0x25bf, + 0x715d, 0x1bc1, + 0x7164, 0x25c0, + 0x7165, 0x1bc9, + 0x716c, 0x25c1, + 0x716d, 0x1bd1, + 0x716f, 0x25c2, + 0x7170, 0x1bd4, + 0x7177, 0x25c3, + 0x7178, 0x1bdc, + 0x7179, 0x25c4, + 0x717a, 0x1bde, + 0x717c, 0x25c5, + 0x7221, 0x25c8, + 0x722e, 0x1bf0, + 0x7231, 0x25d5, + 0x7233, 0x1bf5, + 0x7239, 0x25d7, + 0x723a, 0x1bfc, + 0x7243, 0x25d8, + 0x7244, 0x1c06, + 0x7249, 0x25d9, + 0x724a, 0x1c0c, + 0x724c, 0x25da, + 0x724e, 0x1c10, + 0x724f, 0x25dc, + 0x7250, 0x1c12, + 0x7253, 0x25dd, + 0x7254, 0x1c16, + 0x7265, 0x25de, + 0x7266, 0x1c28, + 0x726e, 0x25df, + 0x726f, 0x1c31, + 0x7277, 0x25e0, + 0x7278, 0x1c3a, + 0x727d, 0x25e1, + 0x727e, 0x1c40, + 0x7321, 0x1c41, + 0x733f, 0x25e2, + 0x7340, 0x1c60, + 0x7346, 0x25e3, + 0x7347, 0x1c67, + 0x7348, 0x25e4, + 0x7349, 0x1c69, + 0x7356, 0x25e5, + 0x7357, 0x1c77, + 0x7359, 0x25e6, + 0x735a, 0x1c7a, + 0x7365, 0x25e7, + 0x7367, 0x1c87, + 0x736a, 0x25e9, + 0x736b, 0x1c8b, + 0x736c, 0x25ea, + 0x736d, 0x1c8d, + 0x736f, 0x25eb, + 0x7370, 0x1c90, + 0x7371, 0x25ec, + 0x7372, 0x1c92, + 0x737d, 0x25ed, + 0x737e, 0x1c9e, + 0x7421, 0x1c9f, + 0x7425, 0x25ee, + 0x7426, 0x1ca4, + 0x742f, 0x25ef, + 0x7430, 0x1cae, + 0x7435, 0x25f0, + 0x7436, 0x1cb4, + 0x7441, 0x25f1, + 0x7442, 0x1cc0, + 0x7447, 0x25f2, + 0x7448, 0x1cc6, + 0x744f, 0x25f3, + 0x7451, 0x1ccf, + 0x7456, 0x25f5, + 0x7457, 0x1cd5, + 0x746a, 0x25f6, + 0x746b, 0x1ce9, + 0x746f, 0x25f7, + 0x7470, 0x1cee, + 0x7475, 0x25f8, + 0x7476, 0x1cf4, + 0x7521, 0x1cfd, + 0x7526, 0x25f9, + 0x7528, 0x1d04, + 0x753a, 0x25fb, + 0x753c, 0x1d18, + 0x7544, 0x25fd, + 0x7545, 0x1d21, + 0x7548, 0x25fe, + 0x7549, 0x1d25, + 0x754e, 0x25ff, + 0x7550, 0x1d2c, + 0x7551, 0x2601, + 0x7553, 0x1d2f, + 0x7559, 0x2603, + 0x755a, 0x1d36, + 0x755c, 0x2604, + 0x755d, 0x1d39, + 0x7566, 0x2605, + 0x7568, 0x1d44, + 0x756f, 0x2607, + 0x7570, 0x1d4c, + 0x7572, 0x2608, + 0x7573, 0x1d4f, + 0x757c, 0x2609, + 0x757d, 0x1d59, + 0x7621, 0x1d5b, + 0x7623, 0x260a, + 0x7624, 0x1d5e, + 0x7626, 0x260b, + 0x7627, 0x1d61, + 0x7628, 0x260c, + 0x7629, 0x1d63, + 0x762b, 0x260d, + 0x762c, 0x1d66, + 0x7630, 0x260e, + 0x7631, 0x1d6b, + 0x7633, 0x260f, + 0x763f, 0x1d79, + 0x7645, 0x261b, + 0x7646, 0x1d80, + 0x7647, 0x261c, + 0x7648, 0x1d82, + 0x7649, 0x261d, + 0x764a, 0x1d84, + 0x764f, 0x261e, + 0x7721, 0x264e, + 0x7730, 0x1dc8, + 0x7732, 0x265d, + 0x7734, 0x1dcc, + 0x7735, 0x265f, + 0x7736, 0x1dce, + 0x773d, 0x2660, + 0x773e, 0x1dd6, + 0x7743, 0x2661, + 0x7744, 0x1ddc, + 0x7745, 0x2662, + 0x7747, 0x1ddf, + 0x774a, 0x2664, + 0x774c, 0x1de4, + 0x774f, 0x2666, + 0x7751, 0x1de9, + 0x775e, 0x2668, + 0x775f, 0x1df7, + 0x7761, 0x0ab9, + 0x7762, 0x1dfa, + 0x7772, 0x2669, + 0x7773, 0x1e0b, + 0x7775, 0x266a, + 0x7776, 0x1e0e, + 0x7821, 0x266b, + 0x7827, 0x04cc, + 0x7828, 0x050a, + 0x7829, 0x0518, + 0x782a, 0x2671, + 0x782c, 0x0594, + 0x782d, 0x05ce, + 0x782e, 0x2673, + 0x782f, 0x05f6, + 0x7830, 0x2674, + 0x7832, 0x0653, + 0x7833, 0x067e, + 0x7834, 0x2676, + 0x7835, 0x06c4, + 0x7836, 0x2677, + 0x7838, 0x073c, + 0x7839, 0x2679, + 0x783b, 0x07c3, + 0x783c, 0x267b, + 0x7840, 0x082b, + 0x7841, 0x267f, + 0x7842, 0x084e, + 0x7843, 0x0869, + 0x7844, 0x2680, + 0x7846, 0x090c, + 0x7847, 0x2682, + 0x7849, 0x0971, + 0x784a, 0x2684, + 0x784b, 0x099a, + 0x784d, 0x2685, + 0x784e, 0x09da, + 0x784f, 0x2686, + 0x7850, 0x09fa, + 0x7851, 0x2687, + 0x785c, 0x0bda, + 0x785d, 0x0bdd, + 0x785e, 0x0bea, + 0x785f, 0x0bec, + 0x7860, 0x0bf2, + 0x7861, 0x2692, + 0x7866, 0x0c92, + 0x7867, 0x0d1a, + 0x7868, 0x0d8c, + 0x7869, 0x0dbe, + 0x786a, 0x2697, + 0x786b, 0x0dfb, + 0x786c, 0x2698, + 0x786f, 0x0e70, + 0x7870, 0x269b, + 0x7871, 0x0ea3, + 0x7872, 0x269c, + 0x7878, 0x103d, + 0x7879, 0x10d9, + 0x787a, 0x26a2, + 0x787c, 0x10fb, + 0x787d, 0x1109, + 0x787e, 0x26a4, + 0x7921, 0x11a1, + 0x7922, 0x26a5, + 0x7923, 0x11ba, + 0x7924, 0x26a6, + 0x7926, 0x11d5, + 0x7927, 0x26a8, + 0x7928, 0x11fd, + 0x7929, 0x1219, + 0x2122, 0x023f, + 0x2123, 0x023e, + 0x212a, 0x0256, + 0x212b, 0x1e18, + 0x212d, 0x0257, + 0x2132, 0x0246, + 0x217e, 0x1e1a, + 0x2321, 0x0242, + 0x2328, 0x0244, + 0x232c, 0x023d, + 0x232e, 0x1e1b, + 0x233a, 0x0240, + 0x233d, 0x1e1c, + 0x233f, 0x0243, + 0x235b, 0x1e1d, + 0x235d, 0x1e1e, + 0x235f, 0x0258, + 0x237b, 0x0254, + 0x237d, 0x0255, + 0x237e, 0x1e1f, + 0xffff, 0x0000 +}; + +static GfxFontEncoding16 gb12GBTVEnc16 = { + 1, + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, + gb12GBTVMap2, 2303 +}; + +static Gushort gb12GBTpcEUCHMap2[4566] = { + 0x0000, 0x0000, + 0xa1a1, 0x0060, + 0xa2b1, 0x00be, + 0xa2e5, 0x00f0, + 0xa2f1, 0x00fa, + 0xa3a1, 0x0106, + 0xa4a1, 0x0164, + 0xa5a1, 0x01b7, + 0xa6a1, 0x020d, + 0xa6c1, 0x0225, + 0xa7a1, 0x025a, + 0xa7d1, 0x027b, + 0xa8a1, 0x029c, + 0xa8c5, 0x02bc, + 0xa9a4, 0x02e2, + 0xaaa1, 0x032e, + 0xaba1, 0x038c, + 0xb0a1, 0x03ac, + 0xb0a8, 0x1e25, + 0xb0a9, 0x03b4, + 0xb0aa, 0x1e26, + 0xb0ab, 0x03b6, + 0xb0ad, 0x1e27, + 0xb0af, 0x03ba, + 0xb0b9, 0x1e29, + 0xb0ba, 0x03c5, + 0xb0c0, 0x1e2a, + 0xb0c1, 0x03cc, + 0xb0d3, 0x1e2b, + 0xb0d4, 0x03df, + 0xb0d5, 0x1e2c, + 0xb0d6, 0x03e1, + 0xb0da, 0x1e2d, + 0xb0db, 0x03e6, + 0xb0dc, 0x1e2e, + 0xb0dd, 0x03e8, + 0xb0e4, 0x1e2f, + 0xb0e5, 0x03f0, + 0xb0ec, 0x1e30, + 0xb0ee, 0x03f9, + 0xb0ef, 0x1e32, + 0xb0f0, 0x03fb, + 0xb0f3, 0x1e33, + 0xb0f4, 0x03ff, + 0xb0f7, 0x1e34, + 0xb0f8, 0x0403, + 0xb0f9, 0x1e35, + 0xb0fa, 0x0405, + 0xb1a1, 0x040a, + 0xb1a5, 0x1e36, + 0xb1a7, 0x0410, + 0xb1a8, 0x1e38, + 0xb1a9, 0x0412, + 0xb1ab, 0x1e39, + 0xb1ac, 0x0415, + 0xb1b2, 0x1e3a, + 0xb1b3, 0x041c, + 0xb1b4, 0x1e3b, + 0xb1b6, 0x041f, + 0xb1b7, 0x1e3d, + 0xb1ba, 0x0423, + 0xb1c1, 0x1e40, + 0xb1c2, 0x042b, + 0xb1ca, 0x1e41, + 0xb1cb, 0x0434, + 0xb1cf, 0x1e42, + 0xb1d1, 0x043a, + 0xb1d2, 0x1e44, + 0xb1d3, 0x043c, + 0xb1d5, 0x1e45, + 0xb1d6, 0x043f, + 0xb1df, 0x1e46, + 0xb1e2, 0x044b, + 0xb1e4, 0x1e49, + 0xb1e5, 0x044e, + 0xb1e7, 0x1e4a, + 0xb1e9, 0x0452, + 0xb1ea, 0x1e4c, + 0xb1eb, 0x0454, + 0xb1ee, 0x1e4d, + 0xb1ef, 0x0458, + 0xb1f1, 0x1e4e, + 0xb1f2, 0x045b, + 0xb1f4, 0x1e4f, + 0xb1f8, 0x0461, + 0xb1fd, 0x1e53, + 0xb1fe, 0x0467, + 0xb2a1, 0x0468, + 0xb2a6, 0x1e54, + 0xb2a8, 0x046f, + 0xb2ac, 0x1e56, + 0xb2ad, 0x0474, + 0xb2b5, 0x1e57, + 0xb2b6, 0x047d, + 0xb2b9, 0x1e58, + 0xb2ba, 0x0481, + 0xb2c6, 0x1e59, + 0xb2c7, 0x048e, + 0xb2ce, 0x1e5a, + 0xb2d8, 0x049f, + 0xb2de, 0x1e64, + 0xb2df, 0x04a6, + 0xb2e0, 0x1e65, + 0xb2e1, 0x04a8, + 0xb2e2, 0x1e66, + 0xb2e4, 0x04ab, + 0xb2ef, 0x1e68, + 0xb2f0, 0x04b7, + 0xb2f3, 0x1e69, + 0xb2fd, 0x04c4, + 0xb3a1, 0x1e73, + 0xb3a3, 0x04c8, + 0xb3a4, 0x1e75, + 0xb3a8, 0x04cd, + 0xb3a9, 0x1e79, + 0xb3aa, 0x04cf, + 0xb3ae, 0x1e7a, + 0xb3af, 0x04d4, + 0xb3b5, 0x1e7b, + 0xb3b6, 0x04db, + 0xb3b9, 0x1e7c, + 0xb3ba, 0x04df, + 0xb3be, 0x1e7d, + 0xb3bf, 0x04e4, + 0xb3c2, 0x1e7e, + 0xb3c3, 0x04e8, + 0xb3c4, 0x1e7f, + 0xb3c5, 0x04ea, + 0xb3c6, 0x1e80, + 0xb3c7, 0x04ec, + 0xb3cd, 0x1e81, + 0xb3ce, 0x04f3, + 0xb3cf, 0x1e82, + 0xb3d0, 0x04f5, + 0xb3d2, 0x1e83, + 0xb3d3, 0x04f8, + 0xb3d9, 0x1e84, + 0xb3da, 0x04ff, + 0xb3db, 0x1e85, + 0xb3dc, 0x0501, + 0xb3dd, 0x1e86, + 0xb3de, 0x0503, + 0xb3e3, 0x1e87, + 0xb3e4, 0x0509, + 0xb3e5, 0x1e88, + 0xb3e7, 0x050c, + 0xb3e8, 0x1e8a, + 0xb3e9, 0x050e, + 0xb3eb, 0x1e8b, + 0xb3ed, 0x0512, + 0xb3ef, 0x1e8d, + 0xb3f0, 0x0515, + 0xb3f1, 0x1e8e, + 0xb3f2, 0x0517, + 0xb3f3, 0x1e8f, + 0xb3f4, 0x0519, + 0xb3fa, 0x1e90, + 0xb3fc, 0x0521, + 0xb4a1, 0x1e92, + 0xb4a3, 0x0526, + 0xb4a5, 0x1e94, + 0xb4a7, 0x052a, + 0xb4ab, 0x1e96, + 0xb4ac, 0x052f, + 0xb4af, 0x1e97, + 0xb4b0, 0x0533, + 0xb4b3, 0x1e98, + 0xb4b5, 0x0538, + 0xb4b8, 0x1e9a, + 0xb4b9, 0x053c, + 0xb4bf, 0x1e9b, + 0xb4c0, 0x0543, + 0xb4c2, 0x1e9c, + 0xb4c3, 0x0546, + 0xb4c7, 0x1e9d, + 0xb4c8, 0x054b, + 0xb4ca, 0x1e9e, + 0xb4cb, 0x054e, + 0xb4cd, 0x1e9f, + 0xb4ce, 0x0551, + 0xb4cf, 0x1ea0, + 0xb4d0, 0x0553, + 0xb4d3, 0x1ea1, + 0xb4d5, 0x0558, + 0xb4da, 0x1ea3, + 0xb4db, 0x055e, + 0xb4dc, 0x1ea4, + 0xb4dd, 0x0560, + 0xb4ed, 0x1ea5, + 0xb4ee, 0x0571, + 0xb4ef, 0x1ea6, + 0xb4f0, 0x0573, + 0xb4f8, 0x1ea7, + 0xb4f9, 0x057c, + 0xb4fb, 0x1ea8, + 0xb4fc, 0x057f, + 0xb5a1, 0x0582, + 0xb5a3, 0x1ea9, + 0xb5a4, 0x0585, + 0xb5a5, 0x1eaa, + 0xb5a9, 0x058a, + 0xb5ac, 0x1eae, + 0xb5ad, 0x058e, + 0xb5ae, 0x1eaf, + 0xb5b0, 0x0591, + 0xb5b1, 0x1eb1, + 0xb5b6, 0x0597, + 0xb5b7, 0x1eb6, + 0xb5b8, 0x0599, + 0xb5ba, 0x1eb7, + 0xb5bd, 0x059e, + 0xb5c6, 0x1eba, + 0xb5c7, 0x05a8, + 0xb5cb, 0x1ebb, + 0xb5cc, 0x05ad, + 0xb5d0, 0x1ebc, + 0xb5d1, 0x05b2, + 0xb5d3, 0x1ebd, + 0xb5d4, 0x05b5, + 0xb5dd, 0x1ebe, + 0xb5e0, 0x05c1, + 0xb5e3, 0x1ec1, + 0xb5e4, 0x05c5, + 0xb5e6, 0x1ec2, + 0xb5e8, 0x05c9, + 0xb5ed, 0x1ec4, + 0xb5ee, 0x05cf, + 0xb5f6, 0x1ec5, + 0xb5f8, 0x05d9, + 0xb5fd, 0x1ec7, + 0xb5fe, 0x05df, + 0xb6a1, 0x05e0, + 0xb6a4, 0x1ec8, + 0xb6a6, 0x05e5, + 0xb6a7, 0x1eca, + 0xb6a8, 0x05e7, + 0xb6a9, 0x1ecb, + 0xb6aa, 0x05e9, + 0xb6ab, 0x1ecc, + 0xb6ac, 0x05eb, + 0xb6af, 0x1ecd, + 0xb6b1, 0x05f0, + 0xb6b3, 0x1ecf, + 0xb6b4, 0x05f3, + 0xb6b7, 0x1ed0, + 0xb6b8, 0x05f7, + 0xb6bf, 0x1ed1, + 0xb6c2, 0x0601, + 0xb6c4, 0x1ed4, + 0xb6c5, 0x0604, + 0xb6c6, 0x1ed5, + 0xb6c7, 0x0606, + 0xb6cd, 0x1ed6, + 0xb6ce, 0x060d, + 0xb6cf, 0x1ed7, + 0xb6d1, 0x0610, + 0xb6d3, 0x1ed9, + 0xb6d5, 0x0614, + 0xb6d6, 0x1edb, + 0xb6d7, 0x0616, + 0xb6d9, 0x1edc, + 0xb6da, 0x0619, + 0xb6db, 0x1edd, + 0xb6dc, 0x061b, + 0xb6e1, 0x1ede, + 0xb6e2, 0x0621, + 0xb6e9, 0x1edf, + 0xb6ea, 0x0629, + 0xb6ec, 0x1ee0, + 0xb6ed, 0x062c, + 0xb6ee, 0x1ee1, + 0xb6f0, 0x062f, + 0xb6f1, 0x1ee3, + 0xb6f2, 0x0631, + 0xb6f6, 0x1ee4, + 0xb6f7, 0x0636, + 0xb6f9, 0x1ee5, + 0xb6fa, 0x0639, + 0xb6fb, 0x1ee6, + 0xb6fd, 0x063c, + 0xb7a1, 0x1ee8, + 0xb7a4, 0x0641, + 0xb7a7, 0x1eeb, + 0xb7a8, 0x0645, + 0xb7af, 0x1eec, + 0xb7b1, 0x064e, + 0xb7b3, 0x1eee, + 0xb7b4, 0x0651, + 0xb7b6, 0x1eef, + 0xb7b8, 0x0655, + 0xb7b9, 0x1ef1, + 0xb7ba, 0x0657, + 0xb7c3, 0x1ef2, + 0xb7c5, 0x0662, + 0xb7c9, 0x1ef4, + 0xb7ca, 0x0667, + 0xb7cc, 0x1ef5, + 0xb7cd, 0x066a, + 0xb7cf, 0x1ef6, + 0xb7d0, 0x066d, + 0xb7d1, 0x1ef7, + 0xb7d2, 0x066f, + 0xb7d7, 0x1ef8, + 0xb7d9, 0x0676, + 0xb7dc, 0x1efa, + 0xb7dd, 0x067a, + 0xb7df, 0x1efb, + 0xb7e2, 0x067f, + 0xb7e3, 0x1efe, + 0xb7e4, 0x0681, + 0xb7e6, 0x1eff, + 0xb7e9, 0x0686, + 0xb7eb, 0x1f02, + 0xb7ee, 0x068b, + 0xb7ef, 0x1f05, + 0xb7f0, 0x068d, + 0xb7f4, 0x1f06, + 0xb7f5, 0x0692, + 0xb7f8, 0x1f07, + 0xb7f9, 0x0696, + 0xb8a1, 0x069c, + 0xb8a7, 0x1f08, + 0xb8a9, 0x06a4, + 0xb8b3, 0x1f0a, + 0xb8b5, 0x06b0, + 0xb8ba, 0x1f0c, + 0xb8bb, 0x06b6, + 0xb8bc, 0x1f0d, + 0xb8bd, 0x06b8, + 0xb8be, 0x1f0e, + 0xb8c0, 0x06bb, + 0xb8c3, 0x1f10, + 0xb8c4, 0x06bf, + 0xb8c6, 0x1f11, + 0xb8c8, 0x06c3, + 0xb8c9, 0x1f13, + 0xb8ca, 0x06c5, + 0xb8cf, 0x1f14, + 0xb8d0, 0x06cb, + 0xb8d3, 0x1f15, + 0xb8d7, 0x06d2, + 0xb8d9, 0x1f19, + 0xb8db, 0x06d6, + 0xb8e4, 0x1f1b, + 0xb8e5, 0x06e0, + 0xb8e9, 0x1f1c, + 0xb8ea, 0x06e5, + 0xb8eb, 0x1f1d, + 0xb8ec, 0x06e7, + 0xb8f3, 0x1f1e, + 0xb8f4, 0x06ef, + 0xb8f5, 0x1f1f, + 0xb8f7, 0x06f2, + 0xb8f8, 0x1f21, + 0xb8f9, 0x06f4, + 0xb9a1, 0x06fa, + 0xb9a8, 0x1f22, + 0xb9a9, 0x0702, + 0xb9ae, 0x1f23, + 0xb9af, 0x0708, + 0xb9b1, 0x1f24, + 0xb9b2, 0x070b, + 0xb9b3, 0x1f25, + 0xb9b4, 0x070d, + 0xb9b5, 0x1f26, + 0xb9b6, 0x070f, + 0xb9b9, 0x1f27, + 0xb9bb, 0x0714, + 0xb9c6, 0x1f29, + 0xb9c7, 0x0720, + 0xb9cb, 0x1f2a, + 0xb9cc, 0x0725, + 0xb9d0, 0x1f2b, + 0xb9d1, 0x072a, + 0xb9d8, 0x1f2c, + 0xb9d9, 0x0732, + 0xb9db, 0x1f2d, + 0xb9dc, 0x0735, + 0xb9dd, 0x1f2e, + 0xb9de, 0x0737, + 0xb9df, 0x1f2f, + 0xb9e0, 0x0739, + 0xb9e1, 0x1f30, + 0xb9e2, 0x073b, + 0xb9e3, 0x1f31, + 0xb9e4, 0x073d, + 0xb9e6, 0x1f32, + 0xb9e7, 0x0740, + 0xb9e9, 0x1f33, + 0xb9ed, 0x0746, + 0xb9ee, 0x1f37, + 0xb9ef, 0x0748, + 0xb9f1, 0x1f38, + 0xb9f2, 0x074b, + 0xb9f3, 0x1f39, + 0xb9f6, 0x074f, + 0xb9f8, 0x1f3c, + 0xb9f9, 0x0752, + 0xb9fa, 0x1f3d, + 0xb9fb, 0x0754, + 0xb9fd, 0x1f3e, + 0xb9fe, 0x0757, + 0xbaa1, 0x0758, + 0xbaa7, 0x1f3f, + 0xbaa8, 0x075f, + 0xbaab, 0x1f40, + 0xbaac, 0x0763, + 0xbaba, 0x1f41, + 0xbabb, 0x0772, + 0xbac5, 0x1f42, + 0xbac6, 0x077d, + 0xbad2, 0x1f43, + 0xbad3, 0x078a, + 0xbad7, 0x1f44, + 0xbad9, 0x0790, + 0xbae4, 0x1f46, + 0xbae5, 0x079c, + 0xbae8, 0x1f47, + 0xbae9, 0x07a0, + 0xbaec, 0x1f48, + 0xbaed, 0x07a4, + 0xbaf3, 0x15e5, + 0xbaf4, 0x07ab, + 0xbaf8, 0x1f49, + 0xbaf9, 0x07b0, + 0xbba1, 0x07b6, + 0xbba4, 0x1f4a, + 0xbba5, 0x07ba, + 0xbba6, 0x1f4b, + 0xbba7, 0x07bc, + 0xbba9, 0x1f4c, + 0xbbab, 0x07c0, + 0xbbad, 0x1f4e, + 0xbbaf, 0x07c4, + 0xbbb0, 0x1f50, + 0xbbb1, 0x07c6, + 0xbbb3, 0x1f51, + 0xbbb4, 0x07c9, + 0xbbb5, 0x1f52, + 0xbbb8, 0x07cd, + 0xbbb9, 0x1f55, + 0xbbbb, 0x07d0, + 0xbbd1, 0x1f57, + 0xbbd2, 0x07e7, + 0xbbd3, 0x1f58, + 0xbbd5, 0x07ea, + 0xbbdf, 0x1f5a, + 0xbbe8, 0x07fd, + 0xbbeb, 0x1f63, + 0xbbec, 0x0801, + 0xbbf1, 0x1f64, + 0xbbf2, 0x0807, + 0xbbf5, 0x1f65, + 0xbbf8, 0x080d, + 0xbbfa, 0x1f68, + 0xbbfb, 0x0810, + 0xbbfd, 0x1f69, + 0xbbfe, 0x0813, + 0xbca1, 0x0814, + 0xbca2, 0x1f6a, + 0xbca3, 0x0816, + 0xbca5, 0x1f6b, + 0xbca7, 0x081a, + 0xbca8, 0x1f6d, + 0xbcaa, 0x081d, + 0xbcab, 0x1f6f, + 0xbcac, 0x081f, + 0xbcad, 0x1f70, + 0xbcae, 0x0821, + 0xbcb6, 0x1f71, + 0xbcb9, 0x082c, + 0xbcbb, 0x1f74, + 0xbcbc, 0x082f, + 0xbcc1, 0x1f75, + 0xbcc2, 0x0835, + 0xbcc3, 0x1f76, + 0xbcc4, 0x0837, + 0xbcc6, 0x1f77, + 0xbcc8, 0x083b, + 0xbcca, 0x1f79, + 0xbccb, 0x083e, + 0xbccc, 0x1f7a, + 0xbcce, 0x0841, + 0xbcd0, 0x1f7c, + 0xbcd1, 0x0844, + 0xbcd4, 0x1f7d, + 0xbcd7, 0x084a, + 0xbcd8, 0x1f80, + 0xbcd9, 0x084c, + 0xbcdb, 0x1f81, + 0xbcdc, 0x084f, + 0xbcdd, 0x1f82, + 0xbcde, 0x0851, + 0xbcdf, 0x1f83, + 0xbce2, 0x0855, + 0xbce3, 0x1f86, + 0xbce5, 0x0858, + 0xbce8, 0x1f88, + 0xbce9, 0x085c, + 0xbcea, 0x1f89, + 0xbced, 0x0860, + 0xbcef, 0x1f8c, + 0xbcf4, 0x0867, + 0xbcf6, 0x1f91, + 0xbcfd, 0x0870, + 0xbda1, 0x0872, + 0xbda2, 0x1f98, + 0xbda8, 0x0879, + 0xbdab, 0x1f9e, + 0xbdad, 0x087e, + 0xbdaf, 0x1fa0, + 0xbdb3, 0x0884, + 0xbdb4, 0x1fa4, + 0xbdb5, 0x0886, + 0xbdba, 0x1fa5, + 0xbdbb, 0x088c, + 0xbdbd, 0x1fa6, + 0xbdc0, 0x0891, + 0xbdc1, 0x1fa9, + 0xbdc5, 0x0896, + 0xbdc8, 0x1fad, + 0xbdcb, 0x089c, + 0xbdce, 0x1fb0, + 0xbdd0, 0x08a1, + 0xbdd7, 0x1fb2, + 0xbdd8, 0x08a9, + 0xbdda, 0x1fb3, + 0xbddb, 0x08ac, + 0xbde0, 0x1fb4, + 0xbde2, 0x08b3, + 0xbdeb, 0x1fb6, + 0xbdec, 0x08bd, + 0xbdf4, 0x1fb7, + 0xbdf9, 0x08ca, + 0xbdfd, 0x1fbc, + 0xbdfe, 0x08cf, + 0xbea1, 0x1fbd, + 0xbea3, 0x08d2, + 0xbea5, 0x1fbf, + 0xbea6, 0x08d5, + 0xbea8, 0x1fc0, + 0xbea9, 0x08d8, + 0xbeaa, 0x1fc1, + 0xbeab, 0x08da, + 0xbead, 0x1fc2, + 0xbeae, 0x08dd, + 0xbeb1, 0x1fc3, + 0xbeb2, 0x08e1, + 0xbeb5, 0x1fc4, + 0xbeb8, 0x08e7, + 0xbeba, 0x1fc7, + 0xbebb, 0x08ea, + 0xbec0, 0x1fc8, + 0xbec1, 0x08f0, + 0xbec9, 0x1fc9, + 0xbeca, 0x08f9, + 0xbed4, 0x1fca, + 0xbed5, 0x0904, + 0xbed9, 0x1fcb, + 0xbeda, 0x0909, + 0xbedd, 0x1fcc, + 0xbede, 0x090d, + 0xbee2, 0x1fcd, + 0xbee3, 0x0912, + 0xbee5, 0x1fce, + 0xbee6, 0x0915, + 0xbee7, 0x1fcf, + 0xbee8, 0x0917, + 0xbee9, 0x1fd0, + 0xbeea, 0x0919, + 0xbeee, 0x1fd1, + 0xbeef, 0x091e, + 0xbef5, 0x1fd2, + 0xbef6, 0x0925, + 0xbef7, 0x1fd3, + 0xbef9, 0x0928, + 0xbefb, 0x1fd5, + 0xbefd, 0x092c, + 0xbfa1, 0x092e, + 0xbfa5, 0x1fd7, + 0xbfa6, 0x0933, + 0xbfaa, 0x1fd8, + 0xbfab, 0x0938, + 0xbfad, 0x1fd9, + 0xbfae, 0x093b, + 0xbfc5, 0x1fda, + 0xbfc6, 0x0953, + 0xbfc7, 0x1fdb, + 0xbfc8, 0x0955, + 0xbfce, 0x1fdc, + 0xbfcf, 0x095c, + 0xbfd1, 0x1fdd, + 0xbfd3, 0x0960, + 0xbfd9, 0x1fdf, + 0xbfda, 0x0967, + 0xbfe2, 0x1fe0, + 0xbfe5, 0x0972, + 0xbfe9, 0x1fe3, + 0xbfea, 0x0977, + 0xbfeb, 0x1fe4, + 0xbfec, 0x0979, + 0xbfed, 0x1fe5, + 0xbfee, 0x097b, + 0xbff3, 0x1fe6, + 0xbff4, 0x0981, + 0xbff5, 0x1fe7, + 0xbff6, 0x0983, + 0xbff7, 0x1fe8, + 0xbff8, 0x0985, + 0xbff9, 0x1fe9, + 0xbffb, 0x0988, + 0xc0a1, 0x1feb, + 0xc0a2, 0x098d, + 0xc0a3, 0x1fec, + 0xc0a4, 0x098f, + 0xc0a9, 0x1fed, + 0xc0aa, 0x0995, + 0xc0ab, 0x1fee, + 0xc0ac, 0x0997, + 0xc0af, 0x1fef, + 0xc0b1, 0x099c, + 0xc0b3, 0x1ff1, + 0xc0b7, 0x09a2, + 0xc0b8, 0x1ff5, + 0xc0c5, 0x09b0, + 0xc0cc, 0x2002, + 0xc0ce, 0x09b9, + 0xc0d4, 0x2004, + 0xc0d5, 0x09c0, + 0xc0d6, 0x2005, + 0xc0d7, 0x09c2, + 0xc0d8, 0x2006, + 0xc0d9, 0x09c4, + 0xc0dd, 0x2007, + 0xc0de, 0x09c9, + 0xc0e0, 0x2008, + 0xc0e1, 0x09cc, + 0xc0e9, 0x2009, + 0xc0ea, 0x09d5, + 0xc0eb, 0x200a, + 0xc0ed, 0x09d8, + 0xc0ef, 0x200c, + 0xc0f2, 0x09dd, + 0xc0f6, 0x200f, + 0xc0fb, 0x09e6, + 0xc1a1, 0x09ea, + 0xc1a4, 0x2014, + 0xc1a6, 0x09ef, + 0xc1a9, 0x2016, + 0xc1ae, 0x09f7, + 0xc1af, 0x201b, + 0xc1b9, 0x0a02, + 0xc1bd, 0x2025, + 0xc1bf, 0x0a08, + 0xc1c2, 0x2027, + 0xc1c3, 0x0a0c, + 0xc1c6, 0x2028, + 0xc1c7, 0x0a10, + 0xc1c9, 0x2029, + 0xc1ca, 0x0a13, + 0xc1cd, 0x202a, + 0xc1ce, 0x0a17, + 0xc1d4, 0x202b, + 0xc1d5, 0x0a1e, + 0xc1d9, 0x202c, + 0xc1dc, 0x0a25, + 0xc1de, 0x202f, + 0xc1df, 0x0a28, + 0xc1e4, 0x2030, + 0xc1e6, 0x0a2f, + 0xc1e9, 0x2032, + 0xc1ea, 0x0a33, + 0xc1eb, 0x2033, + 0xc1ed, 0x0a36, + 0xc1f3, 0x2035, + 0xc1f4, 0x0a3d, + 0xc1f5, 0x2036, + 0xc1f6, 0x0a3f, + 0xc1fa, 0x2037, + 0xc1fe, 0x0a47, + 0xc2a1, 0x0a48, + 0xc2a2, 0x203b, + 0xc2a9, 0x0a50, + 0xc2ab, 0x2042, + 0xc2b4, 0x0a5b, + 0xc2b8, 0x204b, + 0xc2b9, 0x0a60, + 0xc2bc, 0x204c, + 0xc2be, 0x0a65, + 0xc2bf, 0x204e, + 0xc2c0, 0x0a67, + 0xc2c1, 0x204f, + 0xc2c2, 0x0a69, + 0xc2c5, 0x2050, + 0xc2c8, 0x0a6f, + 0xc2cb, 0x2053, + 0xc2d1, 0x0a78, + 0xc2d2, 0x2059, + 0xc2d3, 0x0a7a, + 0xc2d5, 0x205a, + 0xc2dd, 0x0a84, + 0xc2de, 0x2062, + 0xc2e3, 0x0a8a, + 0xc2e6, 0x2067, + 0xc2e9, 0x0a90, + 0xc2ea, 0x206a, + 0xc2ef, 0x0a96, + 0xc2f0, 0x206f, + 0xc2f1, 0x0a98, + 0xc2f2, 0x2070, + 0xc2f6, 0x0a9d, + 0xc2f7, 0x2074, + 0xc2fb, 0x0aa2, + 0xc3a1, 0x2078, + 0xc3a2, 0x0aa7, + 0xc3aa, 0x2079, + 0xc3ab, 0x0ab0, + 0xc3ad, 0x207a, + 0xc3ae, 0x0ab3, + 0xc3b3, 0x207b, + 0xc3b4, 0x1df9, + 0xc3b5, 0x0aba, + 0xc3be, 0x207c, + 0xc3bf, 0x0ac4, + 0xc3c5, 0x207d, + 0xc3c8, 0x0acd, + 0xc3cc, 0x2080, + 0xc3cd, 0x0ad2, + 0xc3ce, 0x2081, + 0xc3cf, 0x0ad4, + 0xc3d5, 0x2082, + 0xc3d7, 0x0adc, + 0xc3d9, 0x2084, + 0xc3da, 0x0adf, + 0xc3e0, 0x2085, + 0xc3e1, 0x0ae6, + 0xc3e5, 0x2086, + 0xc3e6, 0x0aeb, + 0xc3ed, 0x2087, + 0xc3ee, 0x0af3, + 0xc3f0, 0x2088, + 0xc3f1, 0x0af6, + 0xc3f5, 0x2089, + 0xc3f7, 0x0afc, + 0xc3f9, 0x208b, + 0xc3fb, 0x0b00, + 0xc3fd, 0x208d, + 0xc3fe, 0x0b03, + 0xc4a1, 0x0b04, + 0xc4b1, 0x208e, + 0xc4b2, 0x0b15, + 0xc4b6, 0x208f, + 0xc4b7, 0x0b1a, + 0xc4c6, 0x2090, + 0xc4c7, 0x0b2a, + 0xc4c9, 0x2091, + 0xc4ca, 0x0b2d, + 0xc4d1, 0x2092, + 0xc4d2, 0x0b35, + 0xc4d3, 0x2093, + 0xc4d7, 0x0b3a, + 0xc4d9, 0x2097, + 0xc4da, 0x0b3d, + 0xc4e2, 0x2098, + 0xc4e3, 0x0b46, + 0xc4e5, 0x2099, + 0xc4e6, 0x0b49, + 0xc4ec, 0x209a, + 0xc4ed, 0x0b50, + 0xc4f0, 0x209b, + 0xc4f2, 0x0b55, + 0xc4f4, 0x209d, + 0xc4f5, 0x0b58, + 0xc4f6, 0x209e, + 0xc4f9, 0x0b5c, + 0xc4fb, 0x20a1, + 0xc4fd, 0x0b60, + 0xc4fe, 0x20a3, + 0xc5a1, 0x20a4, + 0xc5a3, 0x0b64, + 0xc5a5, 0x20a6, + 0xc5aa, 0x0b6b, + 0xc5b1, 0x20ab, + 0xc5b2, 0x0b73, + 0xc5b5, 0x20ac, + 0xc5b6, 0x0b77, + 0xc5b7, 0x20ad, + 0xc5ba, 0x0b7b, + 0xc5bb, 0x20b0, + 0xc5bc, 0x0b7d, + 0xc5bd, 0x20b1, + 0xc5be, 0x0b7f, + 0xc5cc, 0x20b2, + 0xc5cd, 0x0b8e, + 0xc5d3, 0x20b3, + 0xc5d4, 0x0b95, + 0xc5e2, 0x20b4, + 0xc5e3, 0x0ba4, + 0xc5e7, 0x20b5, + 0xc5e8, 0x0ba9, + 0xc5f4, 0x20b6, + 0xc5f5, 0x0bb6, + 0xc6a1, 0x0bc0, + 0xc6ad, 0x20b7, + 0xc6af, 0x0bce, + 0xc6b5, 0x20b9, + 0xc6b7, 0x0bd6, + 0xc6bb, 0x20bb, + 0xc6bc, 0x0bdb, + 0xc6be, 0x20bc, + 0xc6bf, 0x0bde, + 0xc6c0, 0x20bd, + 0xc6c1, 0x0be0, + 0xc6c3, 0x20be, + 0xc6c5, 0x0be4, + 0xc6cb, 0x20c0, + 0xc6ce, 0x0bed, + 0xc6d3, 0x20c3, + 0xc6d4, 0x0bf3, + 0xc6d7, 0x20c4, + 0xc6d8, 0x0bf7, + 0xc6ea, 0x20c5, + 0xc6ec, 0x0c0b, + 0xc6ef, 0x20c7, + 0xc6f0, 0x0c0f, + 0xc6f1, 0x20c8, + 0xc6f2, 0x0c11, + 0xc6f4, 0x20c9, + 0xc6f5, 0x0c14, + 0xc6f8, 0x20ca, + 0xc6f9, 0x0c18, + 0xc6fd, 0x20cb, + 0xc6fe, 0x0c1d, + 0xc7a1, 0x0c1e, + 0xc7a3, 0x20cc, + 0xc7a4, 0x0c21, + 0xc7a5, 0x20cd, + 0xc7a7, 0x0c24, + 0xc7a8, 0x20cf, + 0xc7aa, 0x0c27, + 0xc7ab, 0x20d1, + 0xc7ac, 0x0c29, + 0xc7ae, 0x20d2, + 0xc7b0, 0x0c2d, + 0xc7b3, 0x20d4, + 0xc7b6, 0x0c33, + 0xc7b9, 0x20d7, + 0xc7bb, 0x0c38, + 0xc7bd, 0x20d9, + 0xc7bf, 0x0c3c, + 0xc7c0, 0x20db, + 0xc7c1, 0x0c3e, + 0xc7c2, 0x20dc, + 0xc7c3, 0x0c40, + 0xc7c5, 0x20dd, + 0xc7c6, 0x0c43, + 0xc7c7, 0x20de, + 0xc7c9, 0x0c46, + 0xc7cc, 0x20e0, + 0xc7cd, 0x0c4a, + 0xc7cf, 0x20e1, + 0xc7d0, 0x0c4d, + 0xc7d4, 0x20e2, + 0xc7d6, 0x0c53, + 0xc7d7, 0x20e4, + 0xc7d8, 0x0c55, + 0xc7de, 0x20e5, + 0xc7df, 0x0c5c, + 0xc7e1, 0x20e6, + 0xc7e4, 0x0c61, + 0xc7ea, 0x20e9, + 0xc7ef, 0x0c6c, + 0xc7f7, 0x20ee, + 0xc7f9, 0x0c76, + 0xc7fb, 0x20f0, + 0xc7fc, 0x0c79, + 0xc7fd, 0x20f1, + 0xc7fe, 0x0c7b, + 0xc8a1, 0x0c7c, + 0xc8a3, 0x20f2, + 0xc8a4, 0x0c7f, + 0xc8a7, 0x20f3, + 0xc8a9, 0x0c84, + 0xc8b0, 0x20f5, + 0xc8b1, 0x0c8c, + 0xc8b5, 0x20f6, + 0xc8b6, 0x0c91, + 0xc8b7, 0x20f7, + 0xc8b8, 0x0c93, + 0xc8c3, 0x20f8, + 0xc8c7, 0x0ca2, + 0xc8c8, 0x20fc, + 0xc8c9, 0x0ca4, + 0xc8cd, 0x20fd, + 0xc8ce, 0x0ca9, + 0xc8cf, 0x20fe, + 0xc8d0, 0x0cab, + 0xc8d2, 0x20ff, + 0xc8d3, 0x0cae, + 0xc8d9, 0x2100, + 0xc8da, 0x0cb5, + 0xc8de, 0x2101, + 0xc8df, 0x0cba, + 0xc8ed, 0x2102, + 0xc8ee, 0x0cc9, + 0xc8f1, 0x2103, + 0xc8f4, 0x0ccf, + 0xc8f7, 0x2106, + 0xc8f9, 0x0cd4, + 0xc8fa, 0x2108, + 0xc8fb, 0x0cd6, + 0xc8fc, 0x2109, + 0xc8fd, 0x0cd8, + 0xc9a1, 0x210a, + 0xc9a2, 0x0cdb, + 0xc9a5, 0x210b, + 0xc9a6, 0x0cdf, + 0xc9a7, 0x210c, + 0xc9a9, 0x0ce2, + 0xc9ac, 0x210e, + 0xc9ad, 0x0ce6, + 0xc9b1, 0x210f, + 0xc9b2, 0x0ceb, + 0xc9b4, 0x2110, + 0xc9b5, 0x0cee, + 0xc9b8, 0x2111, + 0xc9ba, 0x0cf3, + 0xc9c1, 0x2113, + 0xc9c3, 0x0cfc, + 0xc9c4, 0x2115, + 0xc9c5, 0x0cfe, + 0xc9c9, 0x2116, + 0xc9ca, 0x0d03, + 0xc9cb, 0x2117, + 0xc9cc, 0x0d05, + 0xc9cd, 0x2118, + 0xc9ce, 0x0d07, + 0xc9d5, 0x2119, + 0xc9d6, 0x0d0f, + 0xc9dc, 0x211a, + 0xc9dd, 0x0d16, + 0xc9de, 0x211b, + 0xc9df, 0x0d18, + 0xc9e1, 0x211c, + 0xc9e2, 0x0d1b, + 0xc9e3, 0x211d, + 0xc9e4, 0x0d1d, + 0xc9e5, 0x211e, + 0xc9e6, 0x0d1f, + 0xc9e8, 0x211f, + 0xc9e9, 0x0d22, + 0xc9f0, 0x2120, + 0xc9f1, 0x0d2a, + 0xc9f3, 0x2121, + 0xc9f5, 0x0d2e, + 0xc9f6, 0x2123, + 0xc9f7, 0x0d30, + 0xc9f8, 0x2124, + 0xc9fa, 0x0d33, + 0xc9fe, 0x2126, + 0xcaa1, 0x0d38, + 0xcaa4, 0x2127, + 0xcaa7, 0x0d3e, + 0xcaa8, 0x212a, + 0xcaa9, 0x0d40, + 0xcaaa, 0x212b, + 0xcaac, 0x0d43, + 0xcab1, 0x212d, + 0xcab2, 0x0d49, + 0xcab4, 0x212e, + 0xcab7, 0x0d4e, + 0xcabb, 0x2131, + 0xcabc, 0x0d53, + 0xcac6, 0x2132, + 0xcac7, 0x0d5e, + 0xcaca, 0x2133, + 0xcacb, 0x0d62, + 0xcacd, 0x2134, + 0xcacf, 0x0d66, + 0xcad3, 0x2136, + 0xcad5, 0x0d6c, + 0xcad9, 0x2138, + 0xcada, 0x0d71, + 0xcade, 0x2139, + 0xcadf, 0x0d76, + 0xcae0, 0x213a, + 0xcae1, 0x0d78, + 0xcae4, 0x213b, + 0xcae5, 0x0d7c, + 0xcae9, 0x213c, + 0xcaeb, 0x0d82, + 0xcaf4, 0x213e, + 0xcaf6, 0x0d8d, + 0xcaf7, 0x2140, + 0xcaf8, 0x0d8f, + 0xcafa, 0x2141, + 0xcafb, 0x0d92, + 0xcafd, 0x2142, + 0xcafe, 0x0d95, + 0xcba1, 0x0d96, + 0xcba7, 0x2143, + 0xcba8, 0x0d9d, + 0xcbab, 0x2144, + 0xcbac, 0x0da1, + 0xcbad, 0x2145, + 0xcbae, 0x0da3, + 0xcbb3, 0x2146, + 0xcbb4, 0x0da9, + 0xcbb5, 0x2147, + 0xcbb7, 0x0dac, + 0xcbb8, 0x2149, + 0xcbb9, 0x0dae, + 0xcbbf, 0x214a, + 0xcbc0, 0x0db5, + 0xcbc7, 0x214b, + 0xcbc8, 0x0dbd, + 0xcbc9, 0x214c, + 0xcbcd, 0x0dc2, + 0xcbcf, 0x2150, + 0xcbd1, 0x0dc6, + 0xcbd3, 0x2152, + 0xcbd4, 0x0dc9, + 0xcbd5, 0x2153, + 0xcbd6, 0x0dcb, + 0xcbdf, 0x2154, + 0xcbe1, 0x0dd6, + 0xcbe4, 0x2156, + 0xcbe5, 0x0dda, + 0xcbe6, 0x2157, + 0xcbe8, 0x0ddd, + 0xcbea, 0x2159, + 0xcbeb, 0x0de0, + 0xcbef, 0x215a, + 0xcbf1, 0x0de6, + 0xcbf5, 0x215c, + 0xcbf7, 0x0dec, + 0xcbf8, 0x215e, + 0xcbf9, 0x0dee, + 0xcca1, 0x215f, + 0xcca3, 0x0df6, + 0xcca8, 0x2161, + 0xcca9, 0x0dfc, + 0xccac, 0x2162, + 0xccad, 0x0e00, + 0xccaf, 0x2163, + 0xccb4, 0x0e07, + 0xccb7, 0x2168, + 0xccb9, 0x0e0c, + 0xccbe, 0x216a, + 0xccbf, 0x0e12, + 0xccc0, 0x216b, + 0xccc1, 0x0e14, + 0xcccc, 0x216c, + 0xcccd, 0x0e20, + 0xccce, 0x216d, + 0xcccf, 0x0e22, + 0xccd0, 0x216e, + 0xccd1, 0x0e24, + 0xccd6, 0x216f, + 0xccd7, 0x0e2a, + 0xccda, 0x2170, + 0xccdb, 0x0e2e, + 0xccdc, 0x2171, + 0xccdd, 0x0e30, + 0xcce0, 0x2172, + 0xcce1, 0x0e34, + 0xcce2, 0x2173, + 0xcce3, 0x0e36, + 0xcce5, 0x2174, + 0xcce6, 0x0e39, + 0xccf5, 0x2175, + 0xccf6, 0x0e49, + 0xccf9, 0x2176, + 0xccfb, 0x0e4e, + 0xccfc, 0x2178, + 0xcda1, 0x0e52, + 0xcdad, 0x217b, + 0xcdae, 0x0e5f, + 0xcdb3, 0x217c, + 0xcdb4, 0x0e65, + 0xcdb7, 0x217d, + 0xcdb8, 0x0e69, + 0xcdbc, 0x217e, + 0xcdbd, 0x0e6e, + 0xcdbf, 0x217f, + 0xcdc0, 0x0e71, + 0xcdc5, 0x2180, + 0xcdc6, 0x0e77, + 0xcdc7, 0x2181, + 0xcdc8, 0x0e79, + 0xcdd2, 0x2182, + 0xcdd3, 0x0e84, + 0xcdd4, 0x2183, + 0xcdd7, 0x0e88, + 0xcddd, 0x2186, + 0xcdde, 0x0e8f, + 0xcde0, 0x2187, + 0xcde1, 0x0e92, + 0xcde4, 0x2188, + 0xcde6, 0x0e97, + 0xcde7, 0x218a, + 0xcde8, 0x0e99, + 0xcdf2, 0x218b, + 0xcdf3, 0x0ea4, + 0xcdf8, 0x218c, + 0xcdf9, 0x0eaa, + 0xcea1, 0x0eb0, + 0xcea4, 0x218d, + 0xcea6, 0x0eb5, + 0xcea7, 0x218f, + 0xcea8, 0x0eb7, + 0xceaa, 0x2190, + 0xceae, 0x0ebd, + 0xceb0, 0x2194, + 0xceb2, 0x0ec1, + 0xceb3, 0x2196, + 0xceb4, 0x0ec3, + 0xcebd, 0x2197, + 0xcebe, 0x0ecd, + 0xcec0, 0x2198, + 0xcec1, 0x0ed0, + 0xcec5, 0x2199, + 0xcec7, 0x0ed6, + 0xcec8, 0x219b, + 0xcec9, 0x0ed8, + 0xceca, 0x219c, + 0xcecb, 0x0eda, + 0xcece, 0x219d, + 0xced2, 0x0ee1, + 0xced8, 0x21a1, + 0xcedb, 0x0eea, + 0xcedc, 0x21a4, + 0xcedd, 0x0eec, + 0xcede, 0x21a5, + 0xcee0, 0x0eef, + 0xceeb, 0x21a7, + 0xceec, 0x0efb, + 0xceed, 0x21a8, + 0xceee, 0x0efd, + 0xcef1, 0x21a9, + 0xcef2, 0x0f01, + 0xcef3, 0x21aa, + 0xcef4, 0x0f03, + 0xcefd, 0x21ab, + 0xcfa1, 0x0f0e, + 0xcfae, 0x21ad, + 0xcfaf, 0x0f1c, + 0xcfb0, 0x21ae, + 0xcfb1, 0x0f1e, + 0xcfb3, 0x21af, + 0xcfb4, 0x0f21, + 0xcfb7, 0x21b0, + 0xcfb9, 0x0f26, + 0xcfba, 0x21b2, + 0xcfbb, 0x0f28, + 0xcfbd, 0x21b3, + 0xcfbe, 0x0f2b, + 0xcfbf, 0x21b4, + 0xcfc2, 0x0f2f, + 0xcfc5, 0x21b7, + 0xcfc6, 0x0f33, + 0xcfc7, 0x21b8, + 0xcfc8, 0x0f35, + 0xcfca, 0x21b9, + 0xcfcc, 0x0f39, + 0xcfcd, 0x21bb, + 0xcfcf, 0x0f3c, + 0xcfd0, 0x21bd, + 0xcfd1, 0x0f3e, + 0xcfd4, 0x21be, + 0xcfd9, 0x0f46, + 0xcfda, 0x21c3, + 0xcfdb, 0x0f48, + 0xcfdc, 0x21c4, + 0xcfdd, 0x0f4a, + 0xcfdf, 0x21c5, + 0xcfe0, 0x0f4d, + 0xcfe2, 0x21c6, + 0xcfe3, 0x0f50, + 0xcfe7, 0x21c7, + 0xcfe8, 0x0f55, + 0xcfea, 0x21c8, + 0xcfeb, 0x0f58, + 0xcfec, 0x21c9, + 0xcfed, 0x0f5a, + 0xcfee, 0x21ca, + 0xcfef, 0x0f5c, + 0xcff4, 0x21cb, + 0xcff5, 0x0f62, + 0xcff9, 0x21cc, + 0xcffb, 0x0f68, + 0xcffe, 0x21ce, + 0xd0a1, 0x0f6c, + 0xd0a5, 0x21cf, + 0xd0a6, 0x0f71, + 0xd0ad, 0x21d0, + 0xd0af, 0x0f7a, + 0xd0b2, 0x21d2, + 0xd0b5, 0x0f80, + 0xd0ba, 0x21d5, + 0xd0bc, 0x0f87, + 0xd0bf, 0x21d7, + 0xd0c0, 0x0f8b, + 0xd0c6, 0x21d8, + 0xd0c7, 0x0f92, + 0xd0cb, 0x21d9, + 0xd0cc, 0x0f97, + 0xd0e2, 0x21da, + 0xd0e3, 0x0fae, + 0xd0e5, 0x21db, + 0xd0e6, 0x0fb1, + 0xd0eb, 0x21dc, + 0xd0ec, 0x0fb7, + 0xd0ed, 0x21dd, + 0xd0ee, 0x0fb9, + 0xd0f7, 0x21de, + 0xd0fa, 0x0fc5, + 0xd0fc, 0x21e1, + 0xd0fd, 0x0fc8, + 0xd1a1, 0x21e2, + 0xd1a3, 0x0fcc, + 0xd1a4, 0x21e4, + 0xd1a5, 0x0fce, + 0xd1a7, 0x21e5, + 0xd1a8, 0x0fd1, + 0xd1ab, 0x21e6, + 0xd1ac, 0x0fd5, + 0xd1af, 0x21e7, + 0xd1b2, 0x0fdb, + 0xd1b5, 0x21ea, + 0xd1b8, 0x0fe1, + 0xd1b9, 0x21ed, + 0xd1ba, 0x0fe3, + 0xd1bb, 0x21ee, + 0xd1bd, 0x0fe6, + 0xd1c6, 0x21f0, + 0xd1c9, 0x0ff2, + 0xd1cb, 0x21f3, + 0xd1cc, 0x0ff5, + 0xd1ce, 0x21f4, + 0xd1d0, 0x0ff9, + 0xd1d5, 0x21f6, + 0xd1d7, 0x1000, + 0xd1de, 0x21f8, + 0xd1df, 0x1008, + 0xd1e1, 0x21f9, + 0xd1e3, 0x100c, + 0xd1e8, 0x21fb, + 0xd1ea, 0x1013, + 0xd1ec, 0x21fd, + 0xd1ed, 0x1016, + 0xd1ee, 0x21fe, + 0xd1f0, 0x1019, + 0xd1f1, 0x2200, + 0xd1f2, 0x101b, + 0xd1f4, 0x2201, + 0xd1f5, 0x101e, + 0xd1f7, 0x2202, + 0xd1fa, 0x1023, + 0xd2a1, 0x1028, + 0xd2a2, 0x2205, + 0xd2a3, 0x102a, + 0xd2a5, 0x2206, + 0xd2a6, 0x102d, + 0xd2a9, 0x2207, + 0xd2aa, 0x1031, + 0xd2af, 0x2208, + 0xd2b0, 0x1037, + 0xd2b3, 0x2209, + 0xd2b4, 0x103b, + 0xd2b5, 0x220a, + 0xd2b7, 0x103e, + 0xd2bd, 0x220c, + 0xd2be, 0x1045, + 0xd2bf, 0x220d, + 0xd2c0, 0x1047, + 0xd2c3, 0x220e, + 0xd2c4, 0x104b, + 0xd2c5, 0x220f, + 0xd2c6, 0x104d, + 0xd2c7, 0x2210, + 0xd2c8, 0x104f, + 0xd2cf, 0x2211, + 0xd2d0, 0x1057, + 0xd2d5, 0x2212, + 0xd2d6, 0x105d, + 0xd2da, 0x2213, + 0xd2db, 0x1062, + 0xd2e4, 0x2214, + 0xd2e6, 0x106d, + 0xd2e8, 0x2216, + 0xd2ec, 0x1073, + 0xd2ef, 0x221a, + 0xd2f0, 0x1077, + 0xd2f1, 0x221b, + 0xd2f2, 0x1079, + 0xd2f5, 0x221c, + 0xd2f6, 0x107d, + 0xd2f8, 0x221d, + 0xd2f9, 0x1080, + 0xd2fb, 0x221e, + 0xd2fc, 0x1083, + 0xd2fe, 0x221f, + 0xd3a1, 0x1086, + 0xd3a3, 0x2220, + 0xd3ad, 0x1092, + 0xd3ae, 0x222a, + 0xd3af, 0x1094, + 0xd3b1, 0x222b, + 0xd3b2, 0x1097, + 0xd3b4, 0x222c, + 0xd3b7, 0x109c, + 0xd3b8, 0x222f, + 0xd3b9, 0x109e, + 0xd3bb, 0x2230, + 0xd3bc, 0x10a1, + 0xd3c5, 0x2231, + 0xd3c6, 0x10ab, + 0xd3c7, 0x2232, + 0xd3c8, 0x10ad, + 0xd3ca, 0x2233, + 0xd3cd, 0x10b2, + 0xd3d5, 0x2236, + 0xd3d6, 0x10bb, + 0xd3df, 0x2237, + 0xd3e1, 0x10c6, + 0xd3e3, 0x2239, + 0xd3e4, 0x10c9, + 0xd3e6, 0x223a, + 0xd3e7, 0x10cc, + 0xd3eb, 0x223b, + 0xd3ed, 0x10d2, + 0xd3ef, 0x223d, + 0xd3f0, 0x10d5, + 0xd3f4, 0x223e, + 0xd3f5, 0x10da, + 0xd3fc, 0x223f, + 0xd3fd, 0x10e2, + 0xd3fe, 0x2240, + 0xd4a1, 0x10e4, + 0xd4a4, 0x2241, + 0xd4a5, 0x10e8, + 0xd4a6, 0x2242, + 0xd4a9, 0x10ec, + 0xd4af, 0x2245, + 0xd4b3, 0x10f6, + 0xd4b5, 0x2249, + 0xd4b7, 0x10fa, + 0xd4b8, 0x224b, + 0xd4b9, 0x10fc, + 0xd4bc, 0x224c, + 0xd4bd, 0x1100, + 0xd4be, 0x224d, + 0xd4c0, 0x1103, + 0xd4c4, 0x224f, + 0xd4c5, 0x1108, + 0xd4c6, 0x2250, + 0xd4c8, 0x110b, + 0xd4c9, 0x2252, + 0xd4ca, 0x110d, + 0xd4cb, 0x2253, + 0xd4cf, 0x1112, + 0xd4d3, 0x2257, + 0xd4d4, 0x1117, + 0xd4d8, 0x2258, + 0xd4d9, 0x111c, + 0xd4dc, 0x2259, + 0xd4e1, 0x1124, + 0xd4e4, 0x225e, + 0xd4e5, 0x1128, + 0xd4e6, 0x225f, + 0xd4e7, 0x112a, + 0xd4ee, 0x2260, + 0xd4ef, 0x1132, + 0xd4f0, 0x2261, + 0xd4f5, 0x1138, + 0xd4f9, 0x2266, + 0xd4fa, 0x113d, + 0xd4fe, 0x2267, + 0xd5a1, 0x2268, + 0xd5a3, 0x1144, + 0xd5a9, 0x226a, + 0xd5aa, 0x114b, + 0xd5ab, 0x226b, + 0xd5ac, 0x114d, + 0xd5ae, 0x226c, + 0xd5af, 0x1150, + 0xd5b1, 0x226d, + 0xd5b2, 0x1153, + 0xd5b5, 0x226e, + 0xd5b9, 0x115a, + 0xd5bb, 0x2272, + 0xd5bc, 0x115d, + 0xd5bd, 0x2273, + 0xd5be, 0x115f, + 0xd5c0, 0x2274, + 0xd5c1, 0x1162, + 0xd5c5, 0x2275, + 0xd5c6, 0x1167, + 0xd5c7, 0x2276, + 0xd5c8, 0x1169, + 0xd5ca, 0x2277, + 0xd5cc, 0x116d, + 0xd5cd, 0x2279, + 0xd5ce, 0x116f, + 0xd5d4, 0x227a, + 0xd5d5, 0x1176, + 0xd5dd, 0x227b, + 0xd5df, 0x1180, + 0xd5e0, 0x227d, + 0xd5e1, 0x1182, + 0xd5e2, 0x227e, + 0xd5e3, 0x1184, + 0xd5ea, 0x227f, + 0xd5ed, 0x118e, + 0xd5ef, 0x2282, + 0xd5f0, 0x1191, + 0xd5f2, 0x2283, + 0xd5f4, 0x1195, + 0xd5f7, 0x15eb, + 0xd5f8, 0x1199, + 0xd6a1, 0x2285, + 0xd6a5, 0x11a4, + 0xd6af, 0x2289, + 0xd6b1, 0x11b0, + 0xd6b4, 0x228b, + 0xd6b5, 0x11b4, + 0xd6bb, 0x228c, + 0xd6bc, 0x11bb, + 0xd6bd, 0x228d, + 0xd6be, 0x11bd, + 0xd6bf, 0x228e, + 0xd6c1, 0x11c0, + 0xd6c4, 0x2290, + 0xd6c5, 0x11c4, + 0xd6ca, 0x2291, + 0xd6cb, 0x11ca, + 0xd6cd, 0x2292, + 0xd6ce, 0x11cd, + 0xd6d3, 0x2293, + 0xd6d4, 0x11d3, + 0xd6d5, 0x2294, + 0xd6d8, 0x11d7, + 0xd6da, 0x2297, + 0xd6db, 0x11da, + 0xd6df, 0x2298, + 0xd6e0, 0x11df, + 0xd6e1, 0x2299, + 0xd6e2, 0x11e1, + 0xd6e5, 0x229a, + 0xd6e6, 0x11e5, + 0xd6e7, 0x229b, + 0xd6e9, 0x11e8, + 0xd6ee, 0x229d, + 0xd6f0, 0x11ef, + 0xd6f2, 0x229f, + 0xd6f3, 0x11f2, + 0xd6f5, 0x22a0, + 0xd6f7, 0x11f6, + 0xd6fc, 0x22a2, + 0xd7a1, 0x11fe, + 0xd7a4, 0x22a5, + 0xd7a5, 0x1202, + 0xd7a8, 0x22a6, + 0xd7ab, 0x1208, + 0xd7ac, 0x22a9, + 0xd7ad, 0x120a, + 0xd7ae, 0x22aa, + 0xd7b2, 0x120f, + 0xd7b3, 0x22ae, + 0xd7b5, 0x1212, + 0xd7b6, 0x22b0, + 0xd7b7, 0x1214, + 0xd7b8, 0x22b1, + 0xd7bd, 0x121a, + 0xd7c7, 0x22b6, + 0xd7c8, 0x1225, + 0xd7ca, 0x22b7, + 0xd7cb, 0x1228, + 0xd7d5, 0x22b8, + 0xd7d6, 0x1233, + 0xd7db, 0x22b9, + 0xd7df, 0x123c, + 0xd7e7, 0x22bd, + 0xd7e8, 0x1245, + 0xd7e9, 0x22be, + 0xd7eb, 0x1248, + 0xd8a1, 0x1257, + 0xd8c4, 0x22c0, + 0xd8c5, 0x127b, + 0xd8c7, 0x22c1, + 0xd8c8, 0x127e, + 0xd8c9, 0x22c2, + 0xd8ca, 0x1280, + 0xd8cc, 0x22c3, + 0xd8ce, 0x1284, + 0xd8d0, 0x22c5, + 0xd8d2, 0x1288, + 0xd8d3, 0x22c7, + 0xd8d4, 0x128a, + 0xd8d9, 0x22c8, + 0xd8da, 0x1290, + 0xd8db, 0x22c9, + 0xd8dd, 0x1293, + 0xd8f1, 0x22cb, + 0xd8f2, 0x12a8, + 0xd8f6, 0x22cc, + 0xd8f8, 0x12ae, + 0xd9a1, 0x12b5, + 0xd9ad, 0x22ce, + 0xd9ae, 0x12c2, + 0xd9af, 0x22cf, + 0xd9b0, 0x12c4, + 0xd9b1, 0x22d0, + 0xd9b4, 0x12c8, + 0xd9c7, 0x22d3, + 0xd9c8, 0x12dc, + 0xd9cd, 0x22d4, + 0xd9d1, 0x12e5, + 0xd9dd, 0x22d8, + 0xd9de, 0x12f2, + 0xd9e1, 0x22d9, + 0xd9e2, 0x12f6, + 0xd9e4, 0x22da, + 0xd9e5, 0x12f9, + 0xd9e6, 0x22db, + 0xd9e7, 0x12fb, + 0xd9ec, 0x22dc, + 0xd9ed, 0x1301, + 0xd9f4, 0x22dd, + 0xd9f6, 0x130a, + 0xdaa1, 0x1313, + 0xdaa5, 0x22df, + 0xdae0, 0x1352, + 0xdaea, 0x231a, + 0xdaeb, 0x135d, + 0xdaf7, 0x231b, + 0xdaf8, 0x136a, + 0xdaf9, 0x231c, + 0xdafa, 0x136c, + 0xdafe, 0x231d, + 0xdba1, 0x1371, + 0xdba3, 0x231e, + 0xdba4, 0x1374, + 0xdba6, 0x231f, + 0xdba7, 0x1377, + 0xdba9, 0x2320, + 0xdbab, 0x137b, + 0xdbbb, 0x2322, + 0xdbbc, 0x138c, + 0xdbbd, 0x2323, + 0xdbbe, 0x138e, + 0xdbcf, 0x2324, + 0xdbd0, 0x13a0, + 0xdbd1, 0x2325, + 0xdbd2, 0x13a2, + 0xdbdb, 0x2326, + 0xdbdc, 0x13ac, + 0xdbde, 0x2327, + 0xdbdf, 0x13af, + 0xdbe2, 0x2328, + 0xdbe3, 0x13b3, + 0xdbe4, 0x2329, + 0xdbe5, 0x13b5, + 0xdbeb, 0x232a, + 0xdbec, 0x13bc, + 0xdbee, 0x232b, + 0xdbef, 0x13bf, + 0xdbf1, 0x232c, + 0xdbf2, 0x13c2, + 0xdbf5, 0x232d, + 0xdbf8, 0x13c8, + 0xdca1, 0x13cf, + 0xdcbc, 0x2330, + 0xdcbd, 0x13eb, + 0xdcbf, 0x2331, + 0xdcc0, 0x13ee, + 0xdcc2, 0x2332, + 0xdcc3, 0x13f1, + 0xdcc8, 0x2333, + 0xdccb, 0x13f9, + 0xdcd1, 0x2336, + 0xdcd2, 0x1400, + 0xdcd7, 0x2337, + 0xdcd8, 0x1406, + 0xdce0, 0x2338, + 0xdce1, 0x140f, + 0xdce3, 0x2339, + 0xdce5, 0x1413, + 0xdce9, 0x233b, + 0xdceb, 0x1419, + 0xdcf1, 0x233d, + 0xdcf2, 0x1420, + 0xdcf6, 0x233e, + 0xdcf7, 0x1425, + 0xdcf9, 0x233f, + 0xdcfa, 0x1428, + 0xdcfd, 0x2340, + 0xdda1, 0x2342, + 0xdda2, 0x142e, + 0xdda3, 0x2343, + 0xdda8, 0x1434, + 0xddaa, 0x2348, + 0xddac, 0x1438, + 0xddb2, 0x234a, + 0xddb3, 0x143f, + 0xddb5, 0x234b, + 0xddb6, 0x1442, + 0xddba, 0x234c, + 0xddbc, 0x1448, + 0xddd3, 0x234e, + 0xddd4, 0x1460, + 0xdddb, 0x234f, + 0xdddc, 0x1468, + 0xddde, 0x2350, + 0xdddf, 0x146b, + 0xdde4, 0x2351, + 0xdde5, 0x1471, + 0xddeb, 0x2352, + 0xddec, 0x1478, + 0xddf1, 0x2353, + 0xddf2, 0x147e, + 0xddf6, 0x2354, + 0xddf8, 0x1484, + 0xddfc, 0x2356, + 0xddfd, 0x1489, + 0xddfe, 0x2357, + 0xdea1, 0x148b, + 0xdead, 0x2358, + 0xdeae, 0x1498, + 0xdeb4, 0x2359, + 0xdeb5, 0x149f, + 0xdeba, 0x235a, + 0xdebb, 0x14a5, + 0xdec6, 0x235b, + 0xdec7, 0x14b1, + 0xdecf, 0x235c, + 0xded0, 0x14ba, + 0xded1, 0x235d, + 0xded3, 0x14bd, + 0xded8, 0x235f, + 0xded9, 0x14c3, + 0xdee2, 0x2360, + 0xdee3, 0x14cd, + 0xdee8, 0x2361, + 0xdee9, 0x14d3, + 0xdeec, 0x2362, + 0xdeed, 0x14d7, + 0xdef3, 0x2363, + 0xdef4, 0x14de, + 0xdefc, 0x2364, + 0xdefd, 0x14e7, + 0xdfa1, 0x14e9, + 0xdfa2, 0x2365, + 0xdfa4, 0x14ec, + 0xdfa5, 0x2367, + 0xdfa6, 0x14ee, + 0xdfb4, 0x2368, + 0xdfb5, 0x14fd, + 0xdfbc, 0x2369, + 0xdfbe, 0x1506, + 0xdfbf, 0x236b, + 0xdfc0, 0x1508, + 0xdfc2, 0x236c, + 0xdfc4, 0x150c, + 0xdfcc, 0x236e, + 0xdfcd, 0x1515, + 0xdfd0, 0x236f, + 0xdfd1, 0x1519, + 0xdfd5, 0x2370, + 0xdfd6, 0x151e, + 0xdfd8, 0x2371, + 0xdfda, 0x1522, + 0xdfdc, 0x2373, + 0xdfdd, 0x1525, + 0xdfe0, 0x2374, + 0xdfe1, 0x1529, + 0xdfe2, 0x2375, + 0xdfe3, 0x152b, + 0xdfe6, 0x2376, + 0xdfe7, 0x152f, + 0xdfe9, 0x2377, + 0xdfea, 0x1532, + 0xdfeb, 0x2378, + 0xdfec, 0x1534, + 0xdfef, 0x2379, + 0xdff0, 0x1538, + 0xdff5, 0x237a, + 0xdff6, 0x153e, + 0xdff9, 0x237b, + 0xdffa, 0x1542, + 0xe0a1, 0x1547, + 0xe0b6, 0x237c, + 0xe0b8, 0x155e, + 0xe0bf, 0x237e, + 0xe0c0, 0x1566, + 0xe0c8, 0x237f, + 0xe0c9, 0x156f, + 0xe0ce, 0x2380, + 0xe0cf, 0x1575, + 0xe0d3, 0x2381, + 0xe0d4, 0x157a, + 0xe0e0, 0x2382, + 0xe0e1, 0x1587, + 0xe0f0, 0x2383, + 0xe0f1, 0x1597, + 0xe0f8, 0x2384, + 0xe0f9, 0x159f, + 0xe0fc, 0x2385, + 0xe1a1, 0x15a5, + 0xe1ab, 0x2388, + 0xe1ac, 0x15b0, + 0xe1ad, 0x2389, + 0xe1ae, 0x15b2, + 0xe1b0, 0x238a, + 0xe1b1, 0x15b5, + 0xe1b4, 0x238b, + 0xe1b5, 0x15b9, + 0xe1bb, 0x238c, + 0xe1bc, 0x15c0, + 0xe1bd, 0x238d, + 0xe1be, 0x15c2, + 0xe1c0, 0x238e, + 0xe1c2, 0x15c6, + 0xe1c9, 0x2390, + 0xe1ca, 0x15ce, + 0xe1d0, 0x2391, + 0xe1d1, 0x15d5, + 0xe1db, 0x2392, + 0xe1dc, 0x15e0, + 0xe1e1, 0x07aa, + 0xe1e2, 0x2393, + 0xe1e3, 0x15e7, + 0xe1e7, 0x1198, + 0xe1e8, 0x15ec, + 0xe1ee, 0x2394, + 0xe1f0, 0x15f4, + 0xe1f6, 0x2396, + 0xe1f7, 0x15fb, + 0xe1f8, 0x2397, + 0xe1f9, 0x15fd, + 0xe1fd, 0x2398, + 0xe1fe, 0x1602, + 0xe2a1, 0x1603, + 0xe2a4, 0x2399, + 0xe2a5, 0x1607, + 0xe2a8, 0x239a, + 0xe2a9, 0x160b, + 0xe2bb, 0x239b, + 0xe2c5, 0x10c5, + 0xe2c6, 0x23a5, + 0xe2cf, 0x1631, + 0xe2d0, 0x23ae, + 0xe2d1, 0x1633, + 0xe2d9, 0x23af, + 0xe2da, 0x163c, + 0xe2e3, 0x23b0, + 0xe2e5, 0x1647, + 0xe2e6, 0x23b2, + 0xe2e7, 0x1649, + 0xe2e9, 0x23b3, + 0xe2ec, 0x164e, + 0xe2f8, 0x23b6, + 0xe2f9, 0x165b, + 0xe2fa, 0x23b7, + 0xe2fe, 0x1660, + 0xe3a1, 0x1661, + 0xe3a2, 0x23bb, + 0xe3a3, 0x1663, + 0xe3a5, 0x23bc, + 0xe3a6, 0x1666, + 0xe3ab, 0x23bd, + 0xe3ac, 0x166c, + 0xe3b4, 0x23be, + 0xe3b5, 0x1675, + 0xe3c5, 0x23bf, + 0xe3dc, 0x169c, + 0xe3e3, 0x23d6, + 0xe3e4, 0x16a4, + 0xe3ed, 0x23d7, + 0xe3ee, 0x16ae, + 0xe3f1, 0x23d8, + 0xe3f3, 0x16b3, + 0xe3f8, 0x23da, + 0xe3f9, 0x16b9, + 0xe3fe, 0x23db, + 0xe4a1, 0x16bf, + 0xe4a4, 0x23dc, + 0xe4a6, 0x16c4, + 0xe4ab, 0x23de, + 0xe4ac, 0x16ca, + 0xe4af, 0x23df, + 0xe4b2, 0x16d0, + 0xe4b5, 0x23e2, + 0xe4b7, 0x16d5, + 0xe4c2, 0x23e4, + 0xe4c3, 0x16e1, + 0xe4c5, 0x23e5, + 0xe4c6, 0x16e4, + 0xe4c9, 0x23e6, + 0xe4ca, 0x16e8, + 0xe4d9, 0x23e7, + 0xe4da, 0x16f8, + 0xe4dc, 0x23e8, + 0xe4dd, 0x16fb, + 0xe4de, 0x23e9, + 0xe4df, 0x16fd, + 0xe4e4, 0x23ea, + 0xe4e5, 0x1703, + 0xe4eb, 0x23eb, + 0xe4ed, 0x170b, + 0xe4f2, 0x23ed, + 0xe4f3, 0x1711, + 0xe4fe, 0x23ee, + 0xe5a1, 0x171d, + 0xe5b0, 0x23ef, + 0xe5b1, 0x172d, + 0xe5b9, 0x23f0, + 0xe5ba, 0x1736, + 0xe5c7, 0x23f1, + 0xe5c8, 0x1744, + 0xe5c9, 0x23f2, + 0xe5ca, 0x1746, + 0xe5ce, 0x23f3, + 0xe5cf, 0x174b, + 0xe5f0, 0x23f4, + 0xe5f1, 0x176d, + 0xe5f2, 0x23f5, + 0xe5f3, 0x176f, + 0xe5fc, 0x23f6, + 0xe5fe, 0x177a, + 0xe6a1, 0x177b, + 0xe6a3, 0x23f8, + 0xe6a4, 0x177e, + 0xe6ab, 0x23f9, + 0xe6ad, 0x1787, + 0xe6ae, 0x23fb, + 0xe6af, 0x1789, + 0xe6b4, 0x23fc, + 0xe6b6, 0x1790, + 0xe6bf, 0x23fe, + 0xe6c0, 0x179a, + 0xe6c8, 0x23ff, + 0xe6ca, 0x17a4, + 0xe6cd, 0x2401, + 0xe6ce, 0x17a8, + 0xe6e0, 0x2402, + 0xe7a1, 0x2421, + 0xe7db, 0x1813, + 0xe7e1, 0x245b, + 0xe7e3, 0x181b, + 0xe7e7, 0x245d, + 0xe7e8, 0x1820, + 0xe7ef, 0x245e, + 0xe7f0, 0x1828, + 0xe7f4, 0x245f, + 0xe7f7, 0x182f, + 0xe8a1, 0x1837, + 0xe8a8, 0x2462, + 0xe8a9, 0x183f, + 0xe8ac, 0x2463, + 0xe8ad, 0x1843, + 0xe8b6, 0x2464, + 0xe8b7, 0x184d, + 0xe8b8, 0x2465, + 0xe8bb, 0x1851, + 0xe8bf, 0x2468, + 0xe8c1, 0x1857, + 0xe8c5, 0x246a, + 0xe8c6, 0x185c, + 0xe8c7, 0x246b, + 0xe8ca, 0x1860, + 0xe8ce, 0x246e, + 0xe8cf, 0x1865, + 0xe8d0, 0x246f, + 0xe8d1, 0x1867, + 0xe8d3, 0x2470, + 0xe8d4, 0x186a, + 0xe8dd, 0x2471, + 0xe8de, 0x1874, + 0xe8df, 0x2472, + 0xe8e0, 0x1876, + 0xe8e2, 0x2473, + 0xe8e4, 0x187a, + 0xe8e5, 0x2475, + 0xe8e6, 0x187c, + 0xe8e7, 0x2476, + 0xe8e8, 0x187e, + 0xe8eb, 0x2477, + 0xe8ec, 0x1882, + 0xe8ed, 0x2478, + 0xe8ee, 0x1884, + 0xe8ef, 0x2479, + 0xe8f0, 0x1886, + 0xe8f9, 0x247a, + 0xe8fa, 0x1890, + 0xe8fc, 0x247b, + 0xe8fe, 0x1894, + 0xe9a1, 0x247d, + 0xe9a2, 0x1896, + 0xe9ad, 0x247e, + 0xe9ae, 0x18a2, + 0xe9b4, 0x247f, + 0xe9b6, 0x18aa, + 0xe9b7, 0x2481, + 0xe9b8, 0x18ac, + 0xe9c4, 0x2482, + 0xe9c5, 0x18b9, + 0xe9c6, 0x2483, + 0xe9c7, 0x18bb, + 0xe9c9, 0x2484, + 0xe9ca, 0x18be, + 0xe9d6, 0x2485, + 0xe9d7, 0x18cb, + 0xe9da, 0x2486, + 0xe9db, 0x18cf, + 0xe9e4, 0x2487, + 0xe9e5, 0x18d9, + 0xe9e6, 0x2488, + 0xe9e8, 0x18dc, + 0xe9e9, 0x248a, + 0xe9ea, 0x18de, + 0xe9eb, 0x248b, + 0xe9ec, 0x18e0, + 0xe9ed, 0x248c, + 0xeaa1, 0x249e, + 0xeaa6, 0x18f8, + 0xeaa7, 0x24a3, + 0xeaa9, 0x18fb, + 0xeab1, 0x24a5, + 0xeab2, 0x1904, + 0xeabc, 0x24a6, + 0xeabd, 0x190f, + 0xeaca, 0x24a7, + 0xeacb, 0x191d, + 0xeacd, 0x24a8, + 0xeace, 0x1920, + 0xead3, 0x24a9, + 0xead4, 0x1926, + 0xeada, 0x24aa, + 0xeaf0, 0x1942, + 0xeba1, 0x1951, + 0xeba7, 0x24c0, + 0xeba8, 0x1958, + 0xebaa, 0x24c1, + 0xebab, 0x195b, + 0xebb2, 0x24c2, + 0xebb3, 0x1963, + 0xebb9, 0x24c3, + 0xebba, 0x196a, + 0xebca, 0x24c4, + 0xebcc, 0x197c, + 0xebcd, 0x24c6, + 0xebce, 0x197e, + 0xebd6, 0x24c7, + 0xebd7, 0x1987, + 0xebda, 0x24c8, + 0xebdb, 0x198b, + 0xebe1, 0x24c9, + 0xebe2, 0x1992, + 0xebf7, 0x24ca, + 0xebf8, 0x19a8, + 0xeca1, 0x19af, + 0xeca3, 0x24cb, + 0xeca4, 0x19b2, + 0xeca9, 0x24cc, + 0xecaf, 0x19bd, + 0xecb1, 0x24d2, + 0xecb2, 0x19c0, + 0xecb4, 0x24d3, + 0xecb6, 0x19c4, + 0xecbe, 0x24d5, + 0xecc0, 0x19ce, + 0xecc1, 0x24d7, + 0xecc2, 0x19d0, + 0xecc7, 0x24d8, + 0xecc8, 0x19d6, + 0xeccb, 0x24d9, + 0xeccc, 0x19da, + 0xece2, 0x24da, + 0xece3, 0x19f1, + 0xecf2, 0x24db, + 0xecf3, 0x1a01, + 0xecf5, 0x24dc, + 0xecf6, 0x1a04, + 0xecf8, 0x24dd, + 0xecf9, 0x1a07, + 0xeda1, 0x24de, + 0xeda2, 0x1a0e, + 0xeda8, 0x24df, + 0xeda9, 0x1a15, + 0xedaf, 0x24e0, + 0xedb1, 0x1a1d, + 0xedb4, 0x24e2, + 0xedb5, 0x1a21, + 0xedb6, 0x24e3, + 0xedb7, 0x1a23, + 0xedb8, 0x24e4, + 0xedb9, 0x1a25, + 0xedba, 0x24e5, + 0xedbb, 0x1a27, + 0xedbf, 0x24e6, + 0xedc0, 0x1a2c, + 0xedc2, 0x24e7, + 0xedc4, 0x1a30, + 0xedcc, 0x24e9, + 0xedce, 0x1a3a, + 0xedd3, 0x24eb, + 0xedd4, 0x1a40, + 0xedd7, 0x24ec, + 0xedd8, 0x1a44, + 0xede8, 0x24ed, + 0xede9, 0x1a55, + 0xedee, 0x24ee, + 0xedef, 0x1a5b, + 0xedf9, 0x24ef, + 0xedfb, 0x1a67, + 0xeea1, 0x1a6b, + 0xeebc, 0x24f1, + 0xeebd, 0x1a87, + 0xeebf, 0x24f2, + 0xeec0, 0x1a8a, + 0xeec4, 0x24f3, + 0xefa1, 0x252e, + 0xeff2, 0x1b1a, + 0xf0a1, 0x1b27, + 0xf0a3, 0x257f, + 0xf0a4, 0x1b2a, + 0xf0af, 0x2580, + 0xf0da, 0x1b60, + 0xf0dc, 0x25ab, + 0xf0de, 0x1b64, + 0xf0df, 0x25ad, + 0xf0e0, 0x1b66, + 0xf0e9, 0x25ae, + 0xf0ea, 0x1b70, + 0xf0ec, 0x25af, + 0xf0ed, 0x1b73, + 0xf0ef, 0x25b0, + 0xf0f0, 0x1b76, + 0xf0f7, 0x25b1, + 0xf0f8, 0x1b7e, + 0xf0f9, 0x25b2, + 0xf0fa, 0x1b80, + 0xf0fc, 0x25b3, + 0xf0fd, 0x1b83, + 0xf1a1, 0x1b85, + 0xf1a8, 0x25b4, + 0xf1a9, 0x1b8d, + 0xf1ab, 0x25b5, + 0xf1ac, 0x1b90, + 0xf1ae, 0x25b6, + 0xf1af, 0x1b93, + 0xf1b2, 0x25b7, + 0xf1b3, 0x1b97, + 0xf1bc, 0x25b8, + 0xf1bd, 0x1ba1, + 0xf1c0, 0x25b9, + 0xf1c1, 0x1ba5, + 0xf1c9, 0x25ba, + 0xf1ca, 0x1bae, + 0xf1cd, 0x25bb, + 0xf1ce, 0x1bb2, + 0xf1cf, 0x25bc, + 0xf1d1, 0x1bb5, + 0xf1da, 0x25be, + 0xf1db, 0x1bbf, + 0xf1dc, 0x25bf, + 0xf1dd, 0x1bc1, + 0xf1e4, 0x25c0, + 0xf1e5, 0x1bc9, + 0xf1ec, 0x25c1, + 0xf1ed, 0x1bd1, + 0xf1ef, 0x25c2, + 0xf1f0, 0x1bd4, + 0xf1f7, 0x25c3, + 0xf1f8, 0x1bdc, + 0xf1f9, 0x25c4, + 0xf1fa, 0x1bde, + 0xf1fc, 0x25c5, + 0xf2a1, 0x25c8, + 0xf2ae, 0x1bf0, + 0xf2b1, 0x25d5, + 0xf2b3, 0x1bf5, + 0xf2b9, 0x25d7, + 0xf2ba, 0x1bfc, + 0xf2c3, 0x25d8, + 0xf2c4, 0x1c06, + 0xf2c9, 0x25d9, + 0xf2ca, 0x1c0c, + 0xf2cc, 0x25da, + 0xf2ce, 0x1c10, + 0xf2cf, 0x25dc, + 0xf2d0, 0x1c12, + 0xf2d3, 0x25dd, + 0xf2d4, 0x1c16, + 0xf2e5, 0x25de, + 0xf2e6, 0x1c28, + 0xf2ee, 0x25df, + 0xf2ef, 0x1c31, + 0xf2f7, 0x25e0, + 0xf2f8, 0x1c3a, + 0xf2fd, 0x25e1, + 0xf2fe, 0x1c40, + 0xf3a1, 0x1c41, + 0xf3bf, 0x25e2, + 0xf3c0, 0x1c60, + 0xf3c6, 0x25e3, + 0xf3c7, 0x1c67, + 0xf3c8, 0x25e4, + 0xf3c9, 0x1c69, + 0xf3d6, 0x25e5, + 0xf3d7, 0x1c77, + 0xf3d9, 0x25e6, + 0xf3da, 0x1c7a, + 0xf3e5, 0x25e7, + 0xf3e7, 0x1c87, + 0xf3ea, 0x25e9, + 0xf3eb, 0x1c8b, + 0xf3ec, 0x25ea, + 0xf3ed, 0x1c8d, + 0xf3ef, 0x25eb, + 0xf3f0, 0x1c90, + 0xf3f1, 0x25ec, + 0xf3f2, 0x1c92, + 0xf3fd, 0x25ed, + 0xf3fe, 0x1c9e, + 0xf4a1, 0x1c9f, + 0xf4a5, 0x25ee, + 0xf4a6, 0x1ca4, + 0xf4af, 0x25ef, + 0xf4b0, 0x1cae, + 0xf4b5, 0x25f0, + 0xf4b6, 0x1cb4, + 0xf4c1, 0x25f1, + 0xf4c2, 0x1cc0, + 0xf4c7, 0x25f2, + 0xf4c8, 0x1cc6, + 0xf4cf, 0x25f3, + 0xf4d1, 0x1ccf, + 0xf4d6, 0x25f5, + 0xf4d7, 0x1cd5, + 0xf4ea, 0x25f6, + 0xf4eb, 0x1ce9, + 0xf4ef, 0x25f7, + 0xf4f0, 0x1cee, + 0xf4f5, 0x25f8, + 0xf4f6, 0x1cf4, + 0xf5a1, 0x1cfd, + 0xf5a6, 0x25f9, + 0xf5a8, 0x1d04, + 0xf5ba, 0x25fb, + 0xf5bc, 0x1d18, + 0xf5c4, 0x25fd, + 0xf5c5, 0x1d21, + 0xf5c8, 0x25fe, + 0xf5c9, 0x1d25, + 0xf5ce, 0x25ff, + 0xf5d0, 0x1d2c, + 0xf5d1, 0x2601, + 0xf5d3, 0x1d2f, + 0xf5d9, 0x2603, + 0xf5da, 0x1d36, + 0xf5dc, 0x2604, + 0xf5dd, 0x1d39, + 0xf5e6, 0x2605, + 0xf5e8, 0x1d44, + 0xf5ef, 0x2607, + 0xf5f0, 0x1d4c, + 0xf5f2, 0x2608, + 0xf5f3, 0x1d4f, + 0xf5fc, 0x2609, + 0xf5fd, 0x1d59, + 0xf6a1, 0x1d5b, + 0xf6a3, 0x260a, + 0xf6a4, 0x1d5e, + 0xf6a6, 0x260b, + 0xf6a7, 0x1d61, + 0xf6a8, 0x260c, + 0xf6a9, 0x1d63, + 0xf6ab, 0x260d, + 0xf6ac, 0x1d66, + 0xf6b0, 0x260e, + 0xf6b1, 0x1d6b, + 0xf6b3, 0x260f, + 0xf6bf, 0x1d79, + 0xf6c5, 0x261b, + 0xf6c6, 0x1d80, + 0xf6c7, 0x261c, + 0xf6c8, 0x1d82, + 0xf6c9, 0x261d, + 0xf6ca, 0x1d84, + 0xf6cf, 0x261e, + 0xf7a1, 0x264e, + 0xf7b0, 0x1dc8, + 0xf7b2, 0x265d, + 0xf7b4, 0x1dcc, + 0xf7b5, 0x265f, + 0xf7b6, 0x1dce, + 0xf7bd, 0x2660, + 0xf7be, 0x1dd6, + 0xf7c3, 0x2661, + 0xf7c4, 0x1ddc, + 0xf7c5, 0x2662, + 0xf7c7, 0x1ddf, + 0xf7ca, 0x2664, + 0xf7cc, 0x1de4, + 0xf7cf, 0x2666, + 0xf7d1, 0x1de9, + 0xf7de, 0x2668, + 0xf7df, 0x1df7, + 0xf7e1, 0x0ab9, + 0xf7e2, 0x1dfa, + 0xf7f2, 0x2669, + 0xf7f3, 0x1e0b, + 0xf7f5, 0x266a, + 0xf7f6, 0x1e0e, + 0xf8a1, 0x266b, + 0xf8a7, 0x04cc, + 0xf8a8, 0x050a, + 0xf8a9, 0x0518, + 0xf8aa, 0x2671, + 0xf8ac, 0x0594, + 0xf8ad, 0x05ce, + 0xf8ae, 0x2673, + 0xf8af, 0x05f6, + 0xf8b0, 0x2674, + 0xf8b2, 0x0653, + 0xf8b3, 0x067e, + 0xf8b4, 0x2676, + 0xf8b5, 0x06c4, + 0xf8b6, 0x2677, + 0xf8b8, 0x073c, + 0xf8b9, 0x2679, + 0xf8bb, 0x07c3, + 0xf8bc, 0x267b, + 0xf8c0, 0x082b, + 0xf8c1, 0x267f, + 0xf8c2, 0x084e, + 0xf8c3, 0x0869, + 0xf8c4, 0x2680, + 0xf8c6, 0x090c, + 0xf8c7, 0x2682, + 0xf8c9, 0x0971, + 0xf8ca, 0x2684, + 0xf8cb, 0x099a, + 0xf8cd, 0x2685, + 0xf8ce, 0x09da, + 0xf8cf, 0x2686, + 0xf8d0, 0x09fa, + 0xf8d1, 0x2687, + 0xf8dc, 0x0bda, + 0xf8dd, 0x0bdd, + 0xf8de, 0x0bea, + 0xf8df, 0x0bec, + 0xf8e0, 0x0bf2, + 0xf8e1, 0x2692, + 0xf8e6, 0x0c92, + 0xf8e7, 0x0d1a, + 0xf8e8, 0x0d8c, + 0xf8e9, 0x0dbe, + 0xf8ea, 0x2697, + 0xf8eb, 0x0dfb, + 0xf8ec, 0x2698, + 0xf8ef, 0x0e70, + 0xf8f0, 0x269b, + 0xf8f1, 0x0ea3, + 0xf8f2, 0x269c, + 0xf8f8, 0x103d, + 0xf8f9, 0x10d9, + 0xf8fa, 0x26a2, + 0xf8fc, 0x10fb, + 0xf8fd, 0x1109, + 0xf8fe, 0x26a4, + 0xf9a1, 0x11a1, + 0xf9a2, 0x26a5, + 0xf9a3, 0x11ba, + 0xf9a4, 0x26a6, + 0xf9a6, 0x11d5, + 0xf9a7, 0x26a8, + 0xf9a8, 0x11fd, + 0xf9a9, 0x1219, + 0xffff, 0x0000 +}; + +static GfxFontEncoding16 gb12GBTpcEUCHEnc16 = { + 0, + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1 }, + { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, + 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010, + 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, + 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, 0x0020, + 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, + 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, 0x0030, + 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, + 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040, + 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, + 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050, + 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, + 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0000, + 0x1e20, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1e21, 0x1e22, 0x1e23 }, + gb12GBTpcEUCHMap2, 2283 +}; + +static Gushort gb12GBTpcEUCVMap2[4606] = { + 0x0000, 0x0000, + 0xa1a1, 0x0060, + 0xa2b1, 0x00be, + 0xa2e5, 0x00f0, + 0xa2f1, 0x00fa, + 0xa3a1, 0x0106, + 0xa4a1, 0x0164, + 0xa5a1, 0x01b7, + 0xa6a1, 0x020d, + 0xa6c1, 0x0225, + 0xa7a1, 0x025a, + 0xa7d1, 0x027b, + 0xa8a1, 0x029c, + 0xa8c5, 0x02bc, + 0xa9a4, 0x02e2, + 0xaaa1, 0x032e, + 0xaba1, 0x038c, + 0xb0a1, 0x03ac, + 0xb0a8, 0x1e25, + 0xb0a9, 0x03b4, + 0xb0aa, 0x1e26, + 0xb0ab, 0x03b6, + 0xb0ad, 0x1e27, + 0xb0af, 0x03ba, + 0xb0b9, 0x1e29, + 0xb0ba, 0x03c5, + 0xb0c0, 0x1e2a, + 0xb0c1, 0x03cc, + 0xb0d3, 0x1e2b, + 0xb0d4, 0x03df, + 0xb0d5, 0x1e2c, + 0xb0d6, 0x03e1, + 0xb0da, 0x1e2d, + 0xb0db, 0x03e6, + 0xb0dc, 0x1e2e, + 0xb0dd, 0x03e8, + 0xb0e4, 0x1e2f, + 0xb0e5, 0x03f0, + 0xb0ec, 0x1e30, + 0xb0ee, 0x03f9, + 0xb0ef, 0x1e32, + 0xb0f0, 0x03fb, + 0xb0f3, 0x1e33, + 0xb0f4, 0x03ff, + 0xb0f7, 0x1e34, + 0xb0f8, 0x0403, + 0xb0f9, 0x1e35, + 0xb0fa, 0x0405, + 0xb1a1, 0x040a, + 0xb1a5, 0x1e36, + 0xb1a7, 0x0410, + 0xb1a8, 0x1e38, + 0xb1a9, 0x0412, + 0xb1ab, 0x1e39, + 0xb1ac, 0x0415, + 0xb1b2, 0x1e3a, + 0xb1b3, 0x041c, + 0xb1b4, 0x1e3b, + 0xb1b6, 0x041f, + 0xb1b7, 0x1e3d, + 0xb1ba, 0x0423, + 0xb1c1, 0x1e40, + 0xb1c2, 0x042b, + 0xb1ca, 0x1e41, + 0xb1cb, 0x0434, + 0xb1cf, 0x1e42, + 0xb1d1, 0x043a, + 0xb1d2, 0x1e44, + 0xb1d3, 0x043c, + 0xb1d5, 0x1e45, + 0xb1d6, 0x043f, + 0xb1df, 0x1e46, + 0xb1e2, 0x044b, + 0xb1e4, 0x1e49, + 0xb1e5, 0x044e, + 0xb1e7, 0x1e4a, + 0xb1e9, 0x0452, + 0xb1ea, 0x1e4c, + 0xb1eb, 0x0454, + 0xb1ee, 0x1e4d, + 0xb1ef, 0x0458, + 0xb1f1, 0x1e4e, + 0xb1f2, 0x045b, + 0xb1f4, 0x1e4f, + 0xb1f8, 0x0461, + 0xb1fd, 0x1e53, + 0xb1fe, 0x0467, + 0xb2a1, 0x0468, + 0xb2a6, 0x1e54, + 0xb2a8, 0x046f, + 0xb2ac, 0x1e56, + 0xb2ad, 0x0474, + 0xb2b5, 0x1e57, + 0xb2b6, 0x047d, + 0xb2b9, 0x1e58, + 0xb2ba, 0x0481, + 0xb2c6, 0x1e59, + 0xb2c7, 0x048e, + 0xb2ce, 0x1e5a, + 0xb2d8, 0x049f, + 0xb2de, 0x1e64, + 0xb2df, 0x04a6, + 0xb2e0, 0x1e65, + 0xb2e1, 0x04a8, + 0xb2e2, 0x1e66, + 0xb2e4, 0x04ab, + 0xb2ef, 0x1e68, + 0xb2f0, 0x04b7, + 0xb2f3, 0x1e69, + 0xb2fd, 0x04c4, + 0xb3a1, 0x1e73, + 0xb3a3, 0x04c8, + 0xb3a4, 0x1e75, + 0xb3a8, 0x04cd, + 0xb3a9, 0x1e79, + 0xb3aa, 0x04cf, + 0xb3ae, 0x1e7a, + 0xb3af, 0x04d4, + 0xb3b5, 0x1e7b, + 0xb3b6, 0x04db, + 0xb3b9, 0x1e7c, + 0xb3ba, 0x04df, + 0xb3be, 0x1e7d, + 0xb3bf, 0x04e4, + 0xb3c2, 0x1e7e, + 0xb3c3, 0x04e8, + 0xb3c4, 0x1e7f, + 0xb3c5, 0x04ea, + 0xb3c6, 0x1e80, + 0xb3c7, 0x04ec, + 0xb3cd, 0x1e81, + 0xb3ce, 0x04f3, + 0xb3cf, 0x1e82, + 0xb3d0, 0x04f5, + 0xb3d2, 0x1e83, + 0xb3d3, 0x04f8, + 0xb3d9, 0x1e84, + 0xb3da, 0x04ff, + 0xb3db, 0x1e85, + 0xb3dc, 0x0501, + 0xb3dd, 0x1e86, + 0xb3de, 0x0503, + 0xb3e3, 0x1e87, + 0xb3e4, 0x0509, + 0xb3e5, 0x1e88, + 0xb3e7, 0x050c, + 0xb3e8, 0x1e8a, + 0xb3e9, 0x050e, + 0xb3eb, 0x1e8b, + 0xb3ed, 0x0512, + 0xb3ef, 0x1e8d, + 0xb3f0, 0x0515, + 0xb3f1, 0x1e8e, + 0xb3f2, 0x0517, + 0xb3f3, 0x1e8f, + 0xb3f4, 0x0519, + 0xb3fa, 0x1e90, + 0xb3fc, 0x0521, + 0xb4a1, 0x1e92, + 0xb4a3, 0x0526, + 0xb4a5, 0x1e94, + 0xb4a7, 0x052a, + 0xb4ab, 0x1e96, + 0xb4ac, 0x052f, + 0xb4af, 0x1e97, + 0xb4b0, 0x0533, + 0xb4b3, 0x1e98, + 0xb4b5, 0x0538, + 0xb4b8, 0x1e9a, + 0xb4b9, 0x053c, + 0xb4bf, 0x1e9b, + 0xb4c0, 0x0543, + 0xb4c2, 0x1e9c, + 0xb4c3, 0x0546, + 0xb4c7, 0x1e9d, + 0xb4c8, 0x054b, + 0xb4ca, 0x1e9e, + 0xb4cb, 0x054e, + 0xb4cd, 0x1e9f, + 0xb4ce, 0x0551, + 0xb4cf, 0x1ea0, + 0xb4d0, 0x0553, + 0xb4d3, 0x1ea1, + 0xb4d5, 0x0558, + 0xb4da, 0x1ea3, + 0xb4db, 0x055e, + 0xb4dc, 0x1ea4, + 0xb4dd, 0x0560, + 0xb4ed, 0x1ea5, + 0xb4ee, 0x0571, + 0xb4ef, 0x1ea6, + 0xb4f0, 0x0573, + 0xb4f8, 0x1ea7, + 0xb4f9, 0x057c, + 0xb4fb, 0x1ea8, + 0xb4fc, 0x057f, + 0xb5a1, 0x0582, + 0xb5a3, 0x1ea9, + 0xb5a4, 0x0585, + 0xb5a5, 0x1eaa, + 0xb5a9, 0x058a, + 0xb5ac, 0x1eae, + 0xb5ad, 0x058e, + 0xb5ae, 0x1eaf, + 0xb5b0, 0x0591, + 0xb5b1, 0x1eb1, + 0xb5b6, 0x0597, + 0xb5b7, 0x1eb6, + 0xb5b8, 0x0599, + 0xb5ba, 0x1eb7, + 0xb5bd, 0x059e, + 0xb5c6, 0x1eba, + 0xb5c7, 0x05a8, + 0xb5cb, 0x1ebb, + 0xb5cc, 0x05ad, + 0xb5d0, 0x1ebc, + 0xb5d1, 0x05b2, + 0xb5d3, 0x1ebd, + 0xb5d4, 0x05b5, + 0xb5dd, 0x1ebe, + 0xb5e0, 0x05c1, + 0xb5e3, 0x1ec1, + 0xb5e4, 0x05c5, + 0xb5e6, 0x1ec2, + 0xb5e8, 0x05c9, + 0xb5ed, 0x1ec4, + 0xb5ee, 0x05cf, + 0xb5f6, 0x1ec5, + 0xb5f8, 0x05d9, + 0xb5fd, 0x1ec7, + 0xb5fe, 0x05df, + 0xb6a1, 0x05e0, + 0xb6a4, 0x1ec8, + 0xb6a6, 0x05e5, + 0xb6a7, 0x1eca, + 0xb6a8, 0x05e7, + 0xb6a9, 0x1ecb, + 0xb6aa, 0x05e9, + 0xb6ab, 0x1ecc, + 0xb6ac, 0x05eb, + 0xb6af, 0x1ecd, + 0xb6b1, 0x05f0, + 0xb6b3, 0x1ecf, + 0xb6b4, 0x05f3, + 0xb6b7, 0x1ed0, + 0xb6b8, 0x05f7, + 0xb6bf, 0x1ed1, + 0xb6c2, 0x0601, + 0xb6c4, 0x1ed4, + 0xb6c5, 0x0604, + 0xb6c6, 0x1ed5, + 0xb6c7, 0x0606, + 0xb6cd, 0x1ed6, + 0xb6ce, 0x060d, + 0xb6cf, 0x1ed7, + 0xb6d1, 0x0610, + 0xb6d3, 0x1ed9, + 0xb6d5, 0x0614, + 0xb6d6, 0x1edb, + 0xb6d7, 0x0616, + 0xb6d9, 0x1edc, + 0xb6da, 0x0619, + 0xb6db, 0x1edd, + 0xb6dc, 0x061b, + 0xb6e1, 0x1ede, + 0xb6e2, 0x0621, + 0xb6e9, 0x1edf, + 0xb6ea, 0x0629, + 0xb6ec, 0x1ee0, + 0xb6ed, 0x062c, + 0xb6ee, 0x1ee1, + 0xb6f0, 0x062f, + 0xb6f1, 0x1ee3, + 0xb6f2, 0x0631, + 0xb6f6, 0x1ee4, + 0xb6f7, 0x0636, + 0xb6f9, 0x1ee5, + 0xb6fa, 0x0639, + 0xb6fb, 0x1ee6, + 0xb6fd, 0x063c, + 0xb7a1, 0x1ee8, + 0xb7a4, 0x0641, + 0xb7a7, 0x1eeb, + 0xb7a8, 0x0645, + 0xb7af, 0x1eec, + 0xb7b1, 0x064e, + 0xb7b3, 0x1eee, + 0xb7b4, 0x0651, + 0xb7b6, 0x1eef, + 0xb7b8, 0x0655, + 0xb7b9, 0x1ef1, + 0xb7ba, 0x0657, + 0xb7c3, 0x1ef2, + 0xb7c5, 0x0662, + 0xb7c9, 0x1ef4, + 0xb7ca, 0x0667, + 0xb7cc, 0x1ef5, + 0xb7cd, 0x066a, + 0xb7cf, 0x1ef6, + 0xb7d0, 0x066d, + 0xb7d1, 0x1ef7, + 0xb7d2, 0x066f, + 0xb7d7, 0x1ef8, + 0xb7d9, 0x0676, + 0xb7dc, 0x1efa, + 0xb7dd, 0x067a, + 0xb7df, 0x1efb, + 0xb7e2, 0x067f, + 0xb7e3, 0x1efe, + 0xb7e4, 0x0681, + 0xb7e6, 0x1eff, + 0xb7e9, 0x0686, + 0xb7eb, 0x1f02, + 0xb7ee, 0x068b, + 0xb7ef, 0x1f05, + 0xb7f0, 0x068d, + 0xb7f4, 0x1f06, + 0xb7f5, 0x0692, + 0xb7f8, 0x1f07, + 0xb7f9, 0x0696, + 0xb8a1, 0x069c, + 0xb8a7, 0x1f08, + 0xb8a9, 0x06a4, + 0xb8b3, 0x1f0a, + 0xb8b5, 0x06b0, + 0xb8ba, 0x1f0c, + 0xb8bb, 0x06b6, + 0xb8bc, 0x1f0d, + 0xb8bd, 0x06b8, + 0xb8be, 0x1f0e, + 0xb8c0, 0x06bb, + 0xb8c3, 0x1f10, + 0xb8c4, 0x06bf, + 0xb8c6, 0x1f11, + 0xb8c8, 0x06c3, + 0xb8c9, 0x1f13, + 0xb8ca, 0x06c5, + 0xb8cf, 0x1f14, + 0xb8d0, 0x06cb, + 0xb8d3, 0x1f15, + 0xb8d7, 0x06d2, + 0xb8d9, 0x1f19, + 0xb8db, 0x06d6, + 0xb8e4, 0x1f1b, + 0xb8e5, 0x06e0, + 0xb8e9, 0x1f1c, + 0xb8ea, 0x06e5, + 0xb8eb, 0x1f1d, + 0xb8ec, 0x06e7, + 0xb8f3, 0x1f1e, + 0xb8f4, 0x06ef, + 0xb8f5, 0x1f1f, + 0xb8f7, 0x06f2, + 0xb8f8, 0x1f21, + 0xb8f9, 0x06f4, + 0xb9a1, 0x06fa, + 0xb9a8, 0x1f22, + 0xb9a9, 0x0702, + 0xb9ae, 0x1f23, + 0xb9af, 0x0708, + 0xb9b1, 0x1f24, + 0xb9b2, 0x070b, + 0xb9b3, 0x1f25, + 0xb9b4, 0x070d, + 0xb9b5, 0x1f26, + 0xb9b6, 0x070f, + 0xb9b9, 0x1f27, + 0xb9bb, 0x0714, + 0xb9c6, 0x1f29, + 0xb9c7, 0x0720, + 0xb9cb, 0x1f2a, + 0xb9cc, 0x0725, + 0xb9d0, 0x1f2b, + 0xb9d1, 0x072a, + 0xb9d8, 0x1f2c, + 0xb9d9, 0x0732, + 0xb9db, 0x1f2d, + 0xb9dc, 0x0735, + 0xb9dd, 0x1f2e, + 0xb9de, 0x0737, + 0xb9df, 0x1f2f, + 0xb9e0, 0x0739, + 0xb9e1, 0x1f30, + 0xb9e2, 0x073b, + 0xb9e3, 0x1f31, + 0xb9e4, 0x073d, + 0xb9e6, 0x1f32, + 0xb9e7, 0x0740, + 0xb9e9, 0x1f33, + 0xb9ed, 0x0746, + 0xb9ee, 0x1f37, + 0xb9ef, 0x0748, + 0xb9f1, 0x1f38, + 0xb9f2, 0x074b, + 0xb9f3, 0x1f39, + 0xb9f6, 0x074f, + 0xb9f8, 0x1f3c, + 0xb9f9, 0x0752, + 0xb9fa, 0x1f3d, + 0xb9fb, 0x0754, + 0xb9fd, 0x1f3e, + 0xb9fe, 0x0757, + 0xbaa1, 0x0758, + 0xbaa7, 0x1f3f, + 0xbaa8, 0x075f, + 0xbaab, 0x1f40, + 0xbaac, 0x0763, + 0xbaba, 0x1f41, + 0xbabb, 0x0772, + 0xbac5, 0x1f42, + 0xbac6, 0x077d, + 0xbad2, 0x1f43, + 0xbad3, 0x078a, + 0xbad7, 0x1f44, + 0xbad9, 0x0790, + 0xbae4, 0x1f46, + 0xbae5, 0x079c, + 0xbae8, 0x1f47, + 0xbae9, 0x07a0, + 0xbaec, 0x1f48, + 0xbaed, 0x07a4, + 0xbaf3, 0x15e5, + 0xbaf4, 0x07ab, + 0xbaf8, 0x1f49, + 0xbaf9, 0x07b0, + 0xbba1, 0x07b6, + 0xbba4, 0x1f4a, + 0xbba5, 0x07ba, + 0xbba6, 0x1f4b, + 0xbba7, 0x07bc, + 0xbba9, 0x1f4c, + 0xbbab, 0x07c0, + 0xbbad, 0x1f4e, + 0xbbaf, 0x07c4, + 0xbbb0, 0x1f50, + 0xbbb1, 0x07c6, + 0xbbb3, 0x1f51, + 0xbbb4, 0x07c9, + 0xbbb5, 0x1f52, + 0xbbb8, 0x07cd, + 0xbbb9, 0x1f55, + 0xbbbb, 0x07d0, + 0xbbd1, 0x1f57, + 0xbbd2, 0x07e7, + 0xbbd3, 0x1f58, + 0xbbd5, 0x07ea, + 0xbbdf, 0x1f5a, + 0xbbe8, 0x07fd, + 0xbbeb, 0x1f63, + 0xbbec, 0x0801, + 0xbbf1, 0x1f64, + 0xbbf2, 0x0807, + 0xbbf5, 0x1f65, + 0xbbf8, 0x080d, + 0xbbfa, 0x1f68, + 0xbbfb, 0x0810, + 0xbbfd, 0x1f69, + 0xbbfe, 0x0813, + 0xbca1, 0x0814, + 0xbca2, 0x1f6a, + 0xbca3, 0x0816, + 0xbca5, 0x1f6b, + 0xbca7, 0x081a, + 0xbca8, 0x1f6d, + 0xbcaa, 0x081d, + 0xbcab, 0x1f6f, + 0xbcac, 0x081f, + 0xbcad, 0x1f70, + 0xbcae, 0x0821, + 0xbcb6, 0x1f71, + 0xbcb9, 0x082c, + 0xbcbb, 0x1f74, + 0xbcbc, 0x082f, + 0xbcc1, 0x1f75, + 0xbcc2, 0x0835, + 0xbcc3, 0x1f76, + 0xbcc4, 0x0837, + 0xbcc6, 0x1f77, + 0xbcc8, 0x083b, + 0xbcca, 0x1f79, + 0xbccb, 0x083e, + 0xbccc, 0x1f7a, + 0xbcce, 0x0841, + 0xbcd0, 0x1f7c, + 0xbcd1, 0x0844, + 0xbcd4, 0x1f7d, + 0xbcd7, 0x084a, + 0xbcd8, 0x1f80, + 0xbcd9, 0x084c, + 0xbcdb, 0x1f81, + 0xbcdc, 0x084f, + 0xbcdd, 0x1f82, + 0xbcde, 0x0851, + 0xbcdf, 0x1f83, + 0xbce2, 0x0855, + 0xbce3, 0x1f86, + 0xbce5, 0x0858, + 0xbce8, 0x1f88, + 0xbce9, 0x085c, + 0xbcea, 0x1f89, + 0xbced, 0x0860, + 0xbcef, 0x1f8c, + 0xbcf4, 0x0867, + 0xbcf6, 0x1f91, + 0xbcfd, 0x0870, + 0xbda1, 0x0872, + 0xbda2, 0x1f98, + 0xbda8, 0x0879, + 0xbdab, 0x1f9e, + 0xbdad, 0x087e, + 0xbdaf, 0x1fa0, + 0xbdb3, 0x0884, + 0xbdb4, 0x1fa4, + 0xbdb5, 0x0886, + 0xbdba, 0x1fa5, + 0xbdbb, 0x088c, + 0xbdbd, 0x1fa6, + 0xbdc0, 0x0891, + 0xbdc1, 0x1fa9, + 0xbdc5, 0x0896, + 0xbdc8, 0x1fad, + 0xbdcb, 0x089c, + 0xbdce, 0x1fb0, + 0xbdd0, 0x08a1, + 0xbdd7, 0x1fb2, + 0xbdd8, 0x08a9, + 0xbdda, 0x1fb3, + 0xbddb, 0x08ac, + 0xbde0, 0x1fb4, + 0xbde2, 0x08b3, + 0xbdeb, 0x1fb6, + 0xbdec, 0x08bd, + 0xbdf4, 0x1fb7, + 0xbdf9, 0x08ca, + 0xbdfd, 0x1fbc, + 0xbdfe, 0x08cf, + 0xbea1, 0x1fbd, + 0xbea3, 0x08d2, + 0xbea5, 0x1fbf, + 0xbea6, 0x08d5, + 0xbea8, 0x1fc0, + 0xbea9, 0x08d8, + 0xbeaa, 0x1fc1, + 0xbeab, 0x08da, + 0xbead, 0x1fc2, + 0xbeae, 0x08dd, + 0xbeb1, 0x1fc3, + 0xbeb2, 0x08e1, + 0xbeb5, 0x1fc4, + 0xbeb8, 0x08e7, + 0xbeba, 0x1fc7, + 0xbebb, 0x08ea, + 0xbec0, 0x1fc8, + 0xbec1, 0x08f0, + 0xbec9, 0x1fc9, + 0xbeca, 0x08f9, + 0xbed4, 0x1fca, + 0xbed5, 0x0904, + 0xbed9, 0x1fcb, + 0xbeda, 0x0909, + 0xbedd, 0x1fcc, + 0xbede, 0x090d, + 0xbee2, 0x1fcd, + 0xbee3, 0x0912, + 0xbee5, 0x1fce, + 0xbee6, 0x0915, + 0xbee7, 0x1fcf, + 0xbee8, 0x0917, + 0xbee9, 0x1fd0, + 0xbeea, 0x0919, + 0xbeee, 0x1fd1, + 0xbeef, 0x091e, + 0xbef5, 0x1fd2, + 0xbef6, 0x0925, + 0xbef7, 0x1fd3, + 0xbef9, 0x0928, + 0xbefb, 0x1fd5, + 0xbefd, 0x092c, + 0xbfa1, 0x092e, + 0xbfa5, 0x1fd7, + 0xbfa6, 0x0933, + 0xbfaa, 0x1fd8, + 0xbfab, 0x0938, + 0xbfad, 0x1fd9, + 0xbfae, 0x093b, + 0xbfc5, 0x1fda, + 0xbfc6, 0x0953, + 0xbfc7, 0x1fdb, + 0xbfc8, 0x0955, + 0xbfce, 0x1fdc, + 0xbfcf, 0x095c, + 0xbfd1, 0x1fdd, + 0xbfd3, 0x0960, + 0xbfd9, 0x1fdf, + 0xbfda, 0x0967, + 0xbfe2, 0x1fe0, + 0xbfe5, 0x0972, + 0xbfe9, 0x1fe3, + 0xbfea, 0x0977, + 0xbfeb, 0x1fe4, + 0xbfec, 0x0979, + 0xbfed, 0x1fe5, + 0xbfee, 0x097b, + 0xbff3, 0x1fe6, + 0xbff4, 0x0981, + 0xbff5, 0x1fe7, + 0xbff6, 0x0983, + 0xbff7, 0x1fe8, + 0xbff8, 0x0985, + 0xbff9, 0x1fe9, + 0xbffb, 0x0988, + 0xc0a1, 0x1feb, + 0xc0a2, 0x098d, + 0xc0a3, 0x1fec, + 0xc0a4, 0x098f, + 0xc0a9, 0x1fed, + 0xc0aa, 0x0995, + 0xc0ab, 0x1fee, + 0xc0ac, 0x0997, + 0xc0af, 0x1fef, + 0xc0b1, 0x099c, + 0xc0b3, 0x1ff1, + 0xc0b7, 0x09a2, + 0xc0b8, 0x1ff5, + 0xc0c5, 0x09b0, + 0xc0cc, 0x2002, + 0xc0ce, 0x09b9, + 0xc0d4, 0x2004, + 0xc0d5, 0x09c0, + 0xc0d6, 0x2005, + 0xc0d7, 0x09c2, + 0xc0d8, 0x2006, + 0xc0d9, 0x09c4, + 0xc0dd, 0x2007, + 0xc0de, 0x09c9, + 0xc0e0, 0x2008, + 0xc0e1, 0x09cc, + 0xc0e9, 0x2009, + 0xc0ea, 0x09d5, + 0xc0eb, 0x200a, + 0xc0ed, 0x09d8, + 0xc0ef, 0x200c, + 0xc0f2, 0x09dd, + 0xc0f6, 0x200f, + 0xc0fb, 0x09e6, + 0xc1a1, 0x09ea, + 0xc1a4, 0x2014, + 0xc1a6, 0x09ef, + 0xc1a9, 0x2016, + 0xc1ae, 0x09f7, + 0xc1af, 0x201b, + 0xc1b9, 0x0a02, + 0xc1bd, 0x2025, + 0xc1bf, 0x0a08, + 0xc1c2, 0x2027, + 0xc1c3, 0x0a0c, + 0xc1c6, 0x2028, + 0xc1c7, 0x0a10, + 0xc1c9, 0x2029, + 0xc1ca, 0x0a13, + 0xc1cd, 0x202a, + 0xc1ce, 0x0a17, + 0xc1d4, 0x202b, + 0xc1d5, 0x0a1e, + 0xc1d9, 0x202c, + 0xc1dc, 0x0a25, + 0xc1de, 0x202f, + 0xc1df, 0x0a28, + 0xc1e4, 0x2030, + 0xc1e6, 0x0a2f, + 0xc1e9, 0x2032, + 0xc1ea, 0x0a33, + 0xc1eb, 0x2033, + 0xc1ed, 0x0a36, + 0xc1f3, 0x2035, + 0xc1f4, 0x0a3d, + 0xc1f5, 0x2036, + 0xc1f6, 0x0a3f, + 0xc1fa, 0x2037, + 0xc1fe, 0x0a47, + 0xc2a1, 0x0a48, + 0xc2a2, 0x203b, + 0xc2a9, 0x0a50, + 0xc2ab, 0x2042, + 0xc2b4, 0x0a5b, + 0xc2b8, 0x204b, + 0xc2b9, 0x0a60, + 0xc2bc, 0x204c, + 0xc2be, 0x0a65, + 0xc2bf, 0x204e, + 0xc2c0, 0x0a67, + 0xc2c1, 0x204f, + 0xc2c2, 0x0a69, + 0xc2c5, 0x2050, + 0xc2c8, 0x0a6f, + 0xc2cb, 0x2053, + 0xc2d1, 0x0a78, + 0xc2d2, 0x2059, + 0xc2d3, 0x0a7a, + 0xc2d5, 0x205a, + 0xc2dd, 0x0a84, + 0xc2de, 0x2062, + 0xc2e3, 0x0a8a, + 0xc2e6, 0x2067, + 0xc2e9, 0x0a90, + 0xc2ea, 0x206a, + 0xc2ef, 0x0a96, + 0xc2f0, 0x206f, + 0xc2f1, 0x0a98, + 0xc2f2, 0x2070, + 0xc2f6, 0x0a9d, + 0xc2f7, 0x2074, + 0xc2fb, 0x0aa2, + 0xc3a1, 0x2078, + 0xc3a2, 0x0aa7, + 0xc3aa, 0x2079, + 0xc3ab, 0x0ab0, + 0xc3ad, 0x207a, + 0xc3ae, 0x0ab3, + 0xc3b3, 0x207b, + 0xc3b4, 0x1df9, + 0xc3b5, 0x0aba, + 0xc3be, 0x207c, + 0xc3bf, 0x0ac4, + 0xc3c5, 0x207d, + 0xc3c8, 0x0acd, + 0xc3cc, 0x2080, + 0xc3cd, 0x0ad2, + 0xc3ce, 0x2081, + 0xc3cf, 0x0ad4, + 0xc3d5, 0x2082, + 0xc3d7, 0x0adc, + 0xc3d9, 0x2084, + 0xc3da, 0x0adf, + 0xc3e0, 0x2085, + 0xc3e1, 0x0ae6, + 0xc3e5, 0x2086, + 0xc3e6, 0x0aeb, + 0xc3ed, 0x2087, + 0xc3ee, 0x0af3, + 0xc3f0, 0x2088, + 0xc3f1, 0x0af6, + 0xc3f5, 0x2089, + 0xc3f7, 0x0afc, + 0xc3f9, 0x208b, + 0xc3fb, 0x0b00, + 0xc3fd, 0x208d, + 0xc3fe, 0x0b03, + 0xc4a1, 0x0b04, + 0xc4b1, 0x208e, + 0xc4b2, 0x0b15, + 0xc4b6, 0x208f, + 0xc4b7, 0x0b1a, + 0xc4c6, 0x2090, + 0xc4c7, 0x0b2a, + 0xc4c9, 0x2091, + 0xc4ca, 0x0b2d, + 0xc4d1, 0x2092, + 0xc4d2, 0x0b35, + 0xc4d3, 0x2093, + 0xc4d7, 0x0b3a, + 0xc4d9, 0x2097, + 0xc4da, 0x0b3d, + 0xc4e2, 0x2098, + 0xc4e3, 0x0b46, + 0xc4e5, 0x2099, + 0xc4e6, 0x0b49, + 0xc4ec, 0x209a, + 0xc4ed, 0x0b50, + 0xc4f0, 0x209b, + 0xc4f2, 0x0b55, + 0xc4f4, 0x209d, + 0xc4f5, 0x0b58, + 0xc4f6, 0x209e, + 0xc4f9, 0x0b5c, + 0xc4fb, 0x20a1, + 0xc4fd, 0x0b60, + 0xc4fe, 0x20a3, + 0xc5a1, 0x20a4, + 0xc5a3, 0x0b64, + 0xc5a5, 0x20a6, + 0xc5aa, 0x0b6b, + 0xc5b1, 0x20ab, + 0xc5b2, 0x0b73, + 0xc5b5, 0x20ac, + 0xc5b6, 0x0b77, + 0xc5b7, 0x20ad, + 0xc5ba, 0x0b7b, + 0xc5bb, 0x20b0, + 0xc5bc, 0x0b7d, + 0xc5bd, 0x20b1, + 0xc5be, 0x0b7f, + 0xc5cc, 0x20b2, + 0xc5cd, 0x0b8e, + 0xc5d3, 0x20b3, + 0xc5d4, 0x0b95, + 0xc5e2, 0x20b4, + 0xc5e3, 0x0ba4, + 0xc5e7, 0x20b5, + 0xc5e8, 0x0ba9, + 0xc5f4, 0x20b6, + 0xc5f5, 0x0bb6, + 0xc6a1, 0x0bc0, + 0xc6ad, 0x20b7, + 0xc6af, 0x0bce, + 0xc6b5, 0x20b9, + 0xc6b7, 0x0bd6, + 0xc6bb, 0x20bb, + 0xc6bc, 0x0bdb, + 0xc6be, 0x20bc, + 0xc6bf, 0x0bde, + 0xc6c0, 0x20bd, + 0xc6c1, 0x0be0, + 0xc6c3, 0x20be, + 0xc6c5, 0x0be4, + 0xc6cb, 0x20c0, + 0xc6ce, 0x0bed, + 0xc6d3, 0x20c3, + 0xc6d4, 0x0bf3, + 0xc6d7, 0x20c4, + 0xc6d8, 0x0bf7, + 0xc6ea, 0x20c5, + 0xc6ec, 0x0c0b, + 0xc6ef, 0x20c7, + 0xc6f0, 0x0c0f, + 0xc6f1, 0x20c8, + 0xc6f2, 0x0c11, + 0xc6f4, 0x20c9, + 0xc6f5, 0x0c14, + 0xc6f8, 0x20ca, + 0xc6f9, 0x0c18, + 0xc6fd, 0x20cb, + 0xc6fe, 0x0c1d, + 0xc7a1, 0x0c1e, + 0xc7a3, 0x20cc, + 0xc7a4, 0x0c21, + 0xc7a5, 0x20cd, + 0xc7a7, 0x0c24, + 0xc7a8, 0x20cf, + 0xc7aa, 0x0c27, + 0xc7ab, 0x20d1, + 0xc7ac, 0x0c29, + 0xc7ae, 0x20d2, + 0xc7b0, 0x0c2d, + 0xc7b3, 0x20d4, + 0xc7b6, 0x0c33, + 0xc7b9, 0x20d7, + 0xc7bb, 0x0c38, + 0xc7bd, 0x20d9, + 0xc7bf, 0x0c3c, + 0xc7c0, 0x20db, + 0xc7c1, 0x0c3e, + 0xc7c2, 0x20dc, + 0xc7c3, 0x0c40, + 0xc7c5, 0x20dd, + 0xc7c6, 0x0c43, + 0xc7c7, 0x20de, + 0xc7c9, 0x0c46, + 0xc7cc, 0x20e0, + 0xc7cd, 0x0c4a, + 0xc7cf, 0x20e1, + 0xc7d0, 0x0c4d, + 0xc7d4, 0x20e2, + 0xc7d6, 0x0c53, + 0xc7d7, 0x20e4, + 0xc7d8, 0x0c55, + 0xc7de, 0x20e5, + 0xc7df, 0x0c5c, + 0xc7e1, 0x20e6, + 0xc7e4, 0x0c61, + 0xc7ea, 0x20e9, + 0xc7ef, 0x0c6c, + 0xc7f7, 0x20ee, + 0xc7f9, 0x0c76, + 0xc7fb, 0x20f0, + 0xc7fc, 0x0c79, + 0xc7fd, 0x20f1, + 0xc7fe, 0x0c7b, + 0xc8a1, 0x0c7c, + 0xc8a3, 0x20f2, + 0xc8a4, 0x0c7f, + 0xc8a7, 0x20f3, + 0xc8a9, 0x0c84, + 0xc8b0, 0x20f5, + 0xc8b1, 0x0c8c, + 0xc8b5, 0x20f6, + 0xc8b6, 0x0c91, + 0xc8b7, 0x20f7, + 0xc8b8, 0x0c93, + 0xc8c3, 0x20f8, + 0xc8c7, 0x0ca2, + 0xc8c8, 0x20fc, + 0xc8c9, 0x0ca4, + 0xc8cd, 0x20fd, + 0xc8ce, 0x0ca9, + 0xc8cf, 0x20fe, + 0xc8d0, 0x0cab, + 0xc8d2, 0x20ff, + 0xc8d3, 0x0cae, + 0xc8d9, 0x2100, + 0xc8da, 0x0cb5, + 0xc8de, 0x2101, + 0xc8df, 0x0cba, + 0xc8ed, 0x2102, + 0xc8ee, 0x0cc9, + 0xc8f1, 0x2103, + 0xc8f4, 0x0ccf, + 0xc8f7, 0x2106, + 0xc8f9, 0x0cd4, + 0xc8fa, 0x2108, + 0xc8fb, 0x0cd6, + 0xc8fc, 0x2109, + 0xc8fd, 0x0cd8, + 0xc9a1, 0x210a, + 0xc9a2, 0x0cdb, + 0xc9a5, 0x210b, + 0xc9a6, 0x0cdf, + 0xc9a7, 0x210c, + 0xc9a9, 0x0ce2, + 0xc9ac, 0x210e, + 0xc9ad, 0x0ce6, + 0xc9b1, 0x210f, + 0xc9b2, 0x0ceb, + 0xc9b4, 0x2110, + 0xc9b5, 0x0cee, + 0xc9b8, 0x2111, + 0xc9ba, 0x0cf3, + 0xc9c1, 0x2113, + 0xc9c3, 0x0cfc, + 0xc9c4, 0x2115, + 0xc9c5, 0x0cfe, + 0xc9c9, 0x2116, + 0xc9ca, 0x0d03, + 0xc9cb, 0x2117, + 0xc9cc, 0x0d05, + 0xc9cd, 0x2118, + 0xc9ce, 0x0d07, + 0xc9d5, 0x2119, + 0xc9d6, 0x0d0f, + 0xc9dc, 0x211a, + 0xc9dd, 0x0d16, + 0xc9de, 0x211b, + 0xc9df, 0x0d18, + 0xc9e1, 0x211c, + 0xc9e2, 0x0d1b, + 0xc9e3, 0x211d, + 0xc9e4, 0x0d1d, + 0xc9e5, 0x211e, + 0xc9e6, 0x0d1f, + 0xc9e8, 0x211f, + 0xc9e9, 0x0d22, + 0xc9f0, 0x2120, + 0xc9f1, 0x0d2a, + 0xc9f3, 0x2121, + 0xc9f5, 0x0d2e, + 0xc9f6, 0x2123, + 0xc9f7, 0x0d30, + 0xc9f8, 0x2124, + 0xc9fa, 0x0d33, + 0xc9fe, 0x2126, + 0xcaa1, 0x0d38, + 0xcaa4, 0x2127, + 0xcaa7, 0x0d3e, + 0xcaa8, 0x212a, + 0xcaa9, 0x0d40, + 0xcaaa, 0x212b, + 0xcaac, 0x0d43, + 0xcab1, 0x212d, + 0xcab2, 0x0d49, + 0xcab4, 0x212e, + 0xcab7, 0x0d4e, + 0xcabb, 0x2131, + 0xcabc, 0x0d53, + 0xcac6, 0x2132, + 0xcac7, 0x0d5e, + 0xcaca, 0x2133, + 0xcacb, 0x0d62, + 0xcacd, 0x2134, + 0xcacf, 0x0d66, + 0xcad3, 0x2136, + 0xcad5, 0x0d6c, + 0xcad9, 0x2138, + 0xcada, 0x0d71, + 0xcade, 0x2139, + 0xcadf, 0x0d76, + 0xcae0, 0x213a, + 0xcae1, 0x0d78, + 0xcae4, 0x213b, + 0xcae5, 0x0d7c, + 0xcae9, 0x213c, + 0xcaeb, 0x0d82, + 0xcaf4, 0x213e, + 0xcaf6, 0x0d8d, + 0xcaf7, 0x2140, + 0xcaf8, 0x0d8f, + 0xcafa, 0x2141, + 0xcafb, 0x0d92, + 0xcafd, 0x2142, + 0xcafe, 0x0d95, + 0xcba1, 0x0d96, + 0xcba7, 0x2143, + 0xcba8, 0x0d9d, + 0xcbab, 0x2144, + 0xcbac, 0x0da1, + 0xcbad, 0x2145, + 0xcbae, 0x0da3, + 0xcbb3, 0x2146, + 0xcbb4, 0x0da9, + 0xcbb5, 0x2147, + 0xcbb7, 0x0dac, + 0xcbb8, 0x2149, + 0xcbb9, 0x0dae, + 0xcbbf, 0x214a, + 0xcbc0, 0x0db5, + 0xcbc7, 0x214b, + 0xcbc8, 0x0dbd, + 0xcbc9, 0x214c, + 0xcbcd, 0x0dc2, + 0xcbcf, 0x2150, + 0xcbd1, 0x0dc6, + 0xcbd3, 0x2152, + 0xcbd4, 0x0dc9, + 0xcbd5, 0x2153, + 0xcbd6, 0x0dcb, + 0xcbdf, 0x2154, + 0xcbe1, 0x0dd6, + 0xcbe4, 0x2156, + 0xcbe5, 0x0dda, + 0xcbe6, 0x2157, + 0xcbe8, 0x0ddd, + 0xcbea, 0x2159, + 0xcbeb, 0x0de0, + 0xcbef, 0x215a, + 0xcbf1, 0x0de6, + 0xcbf5, 0x215c, + 0xcbf7, 0x0dec, + 0xcbf8, 0x215e, + 0xcbf9, 0x0dee, + 0xcca1, 0x215f, + 0xcca3, 0x0df6, + 0xcca8, 0x2161, + 0xcca9, 0x0dfc, + 0xccac, 0x2162, + 0xccad, 0x0e00, + 0xccaf, 0x2163, + 0xccb4, 0x0e07, + 0xccb7, 0x2168, + 0xccb9, 0x0e0c, + 0xccbe, 0x216a, + 0xccbf, 0x0e12, + 0xccc0, 0x216b, + 0xccc1, 0x0e14, + 0xcccc, 0x216c, + 0xcccd, 0x0e20, + 0xccce, 0x216d, + 0xcccf, 0x0e22, + 0xccd0, 0x216e, + 0xccd1, 0x0e24, + 0xccd6, 0x216f, + 0xccd7, 0x0e2a, + 0xccda, 0x2170, + 0xccdb, 0x0e2e, + 0xccdc, 0x2171, + 0xccdd, 0x0e30, + 0xcce0, 0x2172, + 0xcce1, 0x0e34, + 0xcce2, 0x2173, + 0xcce3, 0x0e36, + 0xcce5, 0x2174, + 0xcce6, 0x0e39, + 0xccf5, 0x2175, + 0xccf6, 0x0e49, + 0xccf9, 0x2176, + 0xccfb, 0x0e4e, + 0xccfc, 0x2178, + 0xcda1, 0x0e52, + 0xcdad, 0x217b, + 0xcdae, 0x0e5f, + 0xcdb3, 0x217c, + 0xcdb4, 0x0e65, + 0xcdb7, 0x217d, + 0xcdb8, 0x0e69, + 0xcdbc, 0x217e, + 0xcdbd, 0x0e6e, + 0xcdbf, 0x217f, + 0xcdc0, 0x0e71, + 0xcdc5, 0x2180, + 0xcdc6, 0x0e77, + 0xcdc7, 0x2181, + 0xcdc8, 0x0e79, + 0xcdd2, 0x2182, + 0xcdd3, 0x0e84, + 0xcdd4, 0x2183, + 0xcdd7, 0x0e88, + 0xcddd, 0x2186, + 0xcdde, 0x0e8f, + 0xcde0, 0x2187, + 0xcde1, 0x0e92, + 0xcde4, 0x2188, + 0xcde6, 0x0e97, + 0xcde7, 0x218a, + 0xcde8, 0x0e99, + 0xcdf2, 0x218b, + 0xcdf3, 0x0ea4, + 0xcdf8, 0x218c, + 0xcdf9, 0x0eaa, + 0xcea1, 0x0eb0, + 0xcea4, 0x218d, + 0xcea6, 0x0eb5, + 0xcea7, 0x218f, + 0xcea8, 0x0eb7, + 0xceaa, 0x2190, + 0xceae, 0x0ebd, + 0xceb0, 0x2194, + 0xceb2, 0x0ec1, + 0xceb3, 0x2196, + 0xceb4, 0x0ec3, + 0xcebd, 0x2197, + 0xcebe, 0x0ecd, + 0xcec0, 0x2198, + 0xcec1, 0x0ed0, + 0xcec5, 0x2199, + 0xcec7, 0x0ed6, + 0xcec8, 0x219b, + 0xcec9, 0x0ed8, + 0xceca, 0x219c, + 0xcecb, 0x0eda, + 0xcece, 0x219d, + 0xced2, 0x0ee1, + 0xced8, 0x21a1, + 0xcedb, 0x0eea, + 0xcedc, 0x21a4, + 0xcedd, 0x0eec, + 0xcede, 0x21a5, + 0xcee0, 0x0eef, + 0xceeb, 0x21a7, + 0xceec, 0x0efb, + 0xceed, 0x21a8, + 0xceee, 0x0efd, + 0xcef1, 0x21a9, + 0xcef2, 0x0f01, + 0xcef3, 0x21aa, + 0xcef4, 0x0f03, + 0xcefd, 0x21ab, + 0xcfa1, 0x0f0e, + 0xcfae, 0x21ad, + 0xcfaf, 0x0f1c, + 0xcfb0, 0x21ae, + 0xcfb1, 0x0f1e, + 0xcfb3, 0x21af, + 0xcfb4, 0x0f21, + 0xcfb7, 0x21b0, + 0xcfb9, 0x0f26, + 0xcfba, 0x21b2, + 0xcfbb, 0x0f28, + 0xcfbd, 0x21b3, + 0xcfbe, 0x0f2b, + 0xcfbf, 0x21b4, + 0xcfc2, 0x0f2f, + 0xcfc5, 0x21b7, + 0xcfc6, 0x0f33, + 0xcfc7, 0x21b8, + 0xcfc8, 0x0f35, + 0xcfca, 0x21b9, + 0xcfcc, 0x0f39, + 0xcfcd, 0x21bb, + 0xcfcf, 0x0f3c, + 0xcfd0, 0x21bd, + 0xcfd1, 0x0f3e, + 0xcfd4, 0x21be, + 0xcfd9, 0x0f46, + 0xcfda, 0x21c3, + 0xcfdb, 0x0f48, + 0xcfdc, 0x21c4, + 0xcfdd, 0x0f4a, + 0xcfdf, 0x21c5, + 0xcfe0, 0x0f4d, + 0xcfe2, 0x21c6, + 0xcfe3, 0x0f50, + 0xcfe7, 0x21c7, + 0xcfe8, 0x0f55, + 0xcfea, 0x21c8, + 0xcfeb, 0x0f58, + 0xcfec, 0x21c9, + 0xcfed, 0x0f5a, + 0xcfee, 0x21ca, + 0xcfef, 0x0f5c, + 0xcff4, 0x21cb, + 0xcff5, 0x0f62, + 0xcff9, 0x21cc, + 0xcffb, 0x0f68, + 0xcffe, 0x21ce, + 0xd0a1, 0x0f6c, + 0xd0a5, 0x21cf, + 0xd0a6, 0x0f71, + 0xd0ad, 0x21d0, + 0xd0af, 0x0f7a, + 0xd0b2, 0x21d2, + 0xd0b5, 0x0f80, + 0xd0ba, 0x21d5, + 0xd0bc, 0x0f87, + 0xd0bf, 0x21d7, + 0xd0c0, 0x0f8b, + 0xd0c6, 0x21d8, + 0xd0c7, 0x0f92, + 0xd0cb, 0x21d9, + 0xd0cc, 0x0f97, + 0xd0e2, 0x21da, + 0xd0e3, 0x0fae, + 0xd0e5, 0x21db, + 0xd0e6, 0x0fb1, + 0xd0eb, 0x21dc, + 0xd0ec, 0x0fb7, + 0xd0ed, 0x21dd, + 0xd0ee, 0x0fb9, + 0xd0f7, 0x21de, + 0xd0fa, 0x0fc5, + 0xd0fc, 0x21e1, + 0xd0fd, 0x0fc8, + 0xd1a1, 0x21e2, + 0xd1a3, 0x0fcc, + 0xd1a4, 0x21e4, + 0xd1a5, 0x0fce, + 0xd1a7, 0x21e5, + 0xd1a8, 0x0fd1, + 0xd1ab, 0x21e6, + 0xd1ac, 0x0fd5, + 0xd1af, 0x21e7, + 0xd1b2, 0x0fdb, + 0xd1b5, 0x21ea, + 0xd1b8, 0x0fe1, + 0xd1b9, 0x21ed, + 0xd1ba, 0x0fe3, + 0xd1bb, 0x21ee, + 0xd1bd, 0x0fe6, + 0xd1c6, 0x21f0, + 0xd1c9, 0x0ff2, + 0xd1cb, 0x21f3, + 0xd1cc, 0x0ff5, + 0xd1ce, 0x21f4, + 0xd1d0, 0x0ff9, + 0xd1d5, 0x21f6, + 0xd1d7, 0x1000, + 0xd1de, 0x21f8, + 0xd1df, 0x1008, + 0xd1e1, 0x21f9, + 0xd1e3, 0x100c, + 0xd1e8, 0x21fb, + 0xd1ea, 0x1013, + 0xd1ec, 0x21fd, + 0xd1ed, 0x1016, + 0xd1ee, 0x21fe, + 0xd1f0, 0x1019, + 0xd1f1, 0x2200, + 0xd1f2, 0x101b, + 0xd1f4, 0x2201, + 0xd1f5, 0x101e, + 0xd1f7, 0x2202, + 0xd1fa, 0x1023, + 0xd2a1, 0x1028, + 0xd2a2, 0x2205, + 0xd2a3, 0x102a, + 0xd2a5, 0x2206, + 0xd2a6, 0x102d, + 0xd2a9, 0x2207, + 0xd2aa, 0x1031, + 0xd2af, 0x2208, + 0xd2b0, 0x1037, + 0xd2b3, 0x2209, + 0xd2b4, 0x103b, + 0xd2b5, 0x220a, + 0xd2b7, 0x103e, + 0xd2bd, 0x220c, + 0xd2be, 0x1045, + 0xd2bf, 0x220d, + 0xd2c0, 0x1047, + 0xd2c3, 0x220e, + 0xd2c4, 0x104b, + 0xd2c5, 0x220f, + 0xd2c6, 0x104d, + 0xd2c7, 0x2210, + 0xd2c8, 0x104f, + 0xd2cf, 0x2211, + 0xd2d0, 0x1057, + 0xd2d5, 0x2212, + 0xd2d6, 0x105d, + 0xd2da, 0x2213, + 0xd2db, 0x1062, + 0xd2e4, 0x2214, + 0xd2e6, 0x106d, + 0xd2e8, 0x2216, + 0xd2ec, 0x1073, + 0xd2ef, 0x221a, + 0xd2f0, 0x1077, + 0xd2f1, 0x221b, + 0xd2f2, 0x1079, + 0xd2f5, 0x221c, + 0xd2f6, 0x107d, + 0xd2f8, 0x221d, + 0xd2f9, 0x1080, + 0xd2fb, 0x221e, + 0xd2fc, 0x1083, + 0xd2fe, 0x221f, + 0xd3a1, 0x1086, + 0xd3a3, 0x2220, + 0xd3ad, 0x1092, + 0xd3ae, 0x222a, + 0xd3af, 0x1094, + 0xd3b1, 0x222b, + 0xd3b2, 0x1097, + 0xd3b4, 0x222c, + 0xd3b7, 0x109c, + 0xd3b8, 0x222f, + 0xd3b9, 0x109e, + 0xd3bb, 0x2230, + 0xd3bc, 0x10a1, + 0xd3c5, 0x2231, + 0xd3c6, 0x10ab, + 0xd3c7, 0x2232, + 0xd3c8, 0x10ad, + 0xd3ca, 0x2233, + 0xd3cd, 0x10b2, + 0xd3d5, 0x2236, + 0xd3d6, 0x10bb, + 0xd3df, 0x2237, + 0xd3e1, 0x10c6, + 0xd3e3, 0x2239, + 0xd3e4, 0x10c9, + 0xd3e6, 0x223a, + 0xd3e7, 0x10cc, + 0xd3eb, 0x223b, + 0xd3ed, 0x10d2, + 0xd3ef, 0x223d, + 0xd3f0, 0x10d5, + 0xd3f4, 0x223e, + 0xd3f5, 0x10da, + 0xd3fc, 0x223f, + 0xd3fd, 0x10e2, + 0xd3fe, 0x2240, + 0xd4a1, 0x10e4, + 0xd4a4, 0x2241, + 0xd4a5, 0x10e8, + 0xd4a6, 0x2242, + 0xd4a9, 0x10ec, + 0xd4af, 0x2245, + 0xd4b3, 0x10f6, + 0xd4b5, 0x2249, + 0xd4b7, 0x10fa, + 0xd4b8, 0x224b, + 0xd4b9, 0x10fc, + 0xd4bc, 0x224c, + 0xd4bd, 0x1100, + 0xd4be, 0x224d, + 0xd4c0, 0x1103, + 0xd4c4, 0x224f, + 0xd4c5, 0x1108, + 0xd4c6, 0x2250, + 0xd4c8, 0x110b, + 0xd4c9, 0x2252, + 0xd4ca, 0x110d, + 0xd4cb, 0x2253, + 0xd4cf, 0x1112, + 0xd4d3, 0x2257, + 0xd4d4, 0x1117, + 0xd4d8, 0x2258, + 0xd4d9, 0x111c, + 0xd4dc, 0x2259, + 0xd4e1, 0x1124, + 0xd4e4, 0x225e, + 0xd4e5, 0x1128, + 0xd4e6, 0x225f, + 0xd4e7, 0x112a, + 0xd4ee, 0x2260, + 0xd4ef, 0x1132, + 0xd4f0, 0x2261, + 0xd4f5, 0x1138, + 0xd4f9, 0x2266, + 0xd4fa, 0x113d, + 0xd4fe, 0x2267, + 0xd5a1, 0x2268, + 0xd5a3, 0x1144, + 0xd5a9, 0x226a, + 0xd5aa, 0x114b, + 0xd5ab, 0x226b, + 0xd5ac, 0x114d, + 0xd5ae, 0x226c, + 0xd5af, 0x1150, + 0xd5b1, 0x226d, + 0xd5b2, 0x1153, + 0xd5b5, 0x226e, + 0xd5b9, 0x115a, + 0xd5bb, 0x2272, + 0xd5bc, 0x115d, + 0xd5bd, 0x2273, + 0xd5be, 0x115f, + 0xd5c0, 0x2274, + 0xd5c1, 0x1162, + 0xd5c5, 0x2275, + 0xd5c6, 0x1167, + 0xd5c7, 0x2276, + 0xd5c8, 0x1169, + 0xd5ca, 0x2277, + 0xd5cc, 0x116d, + 0xd5cd, 0x2279, + 0xd5ce, 0x116f, + 0xd5d4, 0x227a, + 0xd5d5, 0x1176, + 0xd5dd, 0x227b, + 0xd5df, 0x1180, + 0xd5e0, 0x227d, + 0xd5e1, 0x1182, + 0xd5e2, 0x227e, + 0xd5e3, 0x1184, + 0xd5ea, 0x227f, + 0xd5ed, 0x118e, + 0xd5ef, 0x2282, + 0xd5f0, 0x1191, + 0xd5f2, 0x2283, + 0xd5f4, 0x1195, + 0xd5f7, 0x15eb, + 0xd5f8, 0x1199, + 0xd6a1, 0x2285, + 0xd6a5, 0x11a4, + 0xd6af, 0x2289, + 0xd6b1, 0x11b0, + 0xd6b4, 0x228b, + 0xd6b5, 0x11b4, + 0xd6bb, 0x228c, + 0xd6bc, 0x11bb, + 0xd6bd, 0x228d, + 0xd6be, 0x11bd, + 0xd6bf, 0x228e, + 0xd6c1, 0x11c0, + 0xd6c4, 0x2290, + 0xd6c5, 0x11c4, + 0xd6ca, 0x2291, + 0xd6cb, 0x11ca, + 0xd6cd, 0x2292, + 0xd6ce, 0x11cd, + 0xd6d3, 0x2293, + 0xd6d4, 0x11d3, + 0xd6d5, 0x2294, + 0xd6d8, 0x11d7, + 0xd6da, 0x2297, + 0xd6db, 0x11da, + 0xd6df, 0x2298, + 0xd6e0, 0x11df, + 0xd6e1, 0x2299, + 0xd6e2, 0x11e1, + 0xd6e5, 0x229a, + 0xd6e6, 0x11e5, + 0xd6e7, 0x229b, + 0xd6e9, 0x11e8, + 0xd6ee, 0x229d, + 0xd6f0, 0x11ef, + 0xd6f2, 0x229f, + 0xd6f3, 0x11f2, + 0xd6f5, 0x22a0, + 0xd6f7, 0x11f6, + 0xd6fc, 0x22a2, + 0xd7a1, 0x11fe, + 0xd7a4, 0x22a5, + 0xd7a5, 0x1202, + 0xd7a8, 0x22a6, + 0xd7ab, 0x1208, + 0xd7ac, 0x22a9, + 0xd7ad, 0x120a, + 0xd7ae, 0x22aa, + 0xd7b2, 0x120f, + 0xd7b3, 0x22ae, + 0xd7b5, 0x1212, + 0xd7b6, 0x22b0, + 0xd7b7, 0x1214, + 0xd7b8, 0x22b1, + 0xd7bd, 0x121a, + 0xd7c7, 0x22b6, + 0xd7c8, 0x1225, + 0xd7ca, 0x22b7, + 0xd7cb, 0x1228, + 0xd7d5, 0x22b8, + 0xd7d6, 0x1233, + 0xd7db, 0x22b9, + 0xd7df, 0x123c, + 0xd7e7, 0x22bd, + 0xd7e8, 0x1245, + 0xd7e9, 0x22be, + 0xd7eb, 0x1248, + 0xd8a1, 0x1257, + 0xd8c4, 0x22c0, + 0xd8c5, 0x127b, + 0xd8c7, 0x22c1, + 0xd8c8, 0x127e, + 0xd8c9, 0x22c2, + 0xd8ca, 0x1280, + 0xd8cc, 0x22c3, + 0xd8ce, 0x1284, + 0xd8d0, 0x22c5, + 0xd8d2, 0x1288, + 0xd8d3, 0x22c7, + 0xd8d4, 0x128a, + 0xd8d9, 0x22c8, + 0xd8da, 0x1290, + 0xd8db, 0x22c9, + 0xd8dd, 0x1293, + 0xd8f1, 0x22cb, + 0xd8f2, 0x12a8, + 0xd8f6, 0x22cc, + 0xd8f8, 0x12ae, + 0xd9a1, 0x12b5, + 0xd9ad, 0x22ce, + 0xd9ae, 0x12c2, + 0xd9af, 0x22cf, + 0xd9b0, 0x12c4, + 0xd9b1, 0x22d0, + 0xd9b4, 0x12c8, + 0xd9c7, 0x22d3, + 0xd9c8, 0x12dc, + 0xd9cd, 0x22d4, + 0xd9d1, 0x12e5, + 0xd9dd, 0x22d8, + 0xd9de, 0x12f2, + 0xd9e1, 0x22d9, + 0xd9e2, 0x12f6, + 0xd9e4, 0x22da, + 0xd9e5, 0x12f9, + 0xd9e6, 0x22db, + 0xd9e7, 0x12fb, + 0xd9ec, 0x22dc, + 0xd9ed, 0x1301, + 0xd9f4, 0x22dd, + 0xd9f6, 0x130a, + 0xdaa1, 0x1313, + 0xdaa5, 0x22df, + 0xdae0, 0x1352, + 0xdaea, 0x231a, + 0xdaeb, 0x135d, + 0xdaf7, 0x231b, + 0xdaf8, 0x136a, + 0xdaf9, 0x231c, + 0xdafa, 0x136c, + 0xdafe, 0x231d, + 0xdba1, 0x1371, + 0xdba3, 0x231e, + 0xdba4, 0x1374, + 0xdba6, 0x231f, + 0xdba7, 0x1377, + 0xdba9, 0x2320, + 0xdbab, 0x137b, + 0xdbbb, 0x2322, + 0xdbbc, 0x138c, + 0xdbbd, 0x2323, + 0xdbbe, 0x138e, + 0xdbcf, 0x2324, + 0xdbd0, 0x13a0, + 0xdbd1, 0x2325, + 0xdbd2, 0x13a2, + 0xdbdb, 0x2326, + 0xdbdc, 0x13ac, + 0xdbde, 0x2327, + 0xdbdf, 0x13af, + 0xdbe2, 0x2328, + 0xdbe3, 0x13b3, + 0xdbe4, 0x2329, + 0xdbe5, 0x13b5, + 0xdbeb, 0x232a, + 0xdbec, 0x13bc, + 0xdbee, 0x232b, + 0xdbef, 0x13bf, + 0xdbf1, 0x232c, + 0xdbf2, 0x13c2, + 0xdbf5, 0x232d, + 0xdbf8, 0x13c8, + 0xdca1, 0x13cf, + 0xdcbc, 0x2330, + 0xdcbd, 0x13eb, + 0xdcbf, 0x2331, + 0xdcc0, 0x13ee, + 0xdcc2, 0x2332, + 0xdcc3, 0x13f1, + 0xdcc8, 0x2333, + 0xdccb, 0x13f9, + 0xdcd1, 0x2336, + 0xdcd2, 0x1400, + 0xdcd7, 0x2337, + 0xdcd8, 0x1406, + 0xdce0, 0x2338, + 0xdce1, 0x140f, + 0xdce3, 0x2339, + 0xdce5, 0x1413, + 0xdce9, 0x233b, + 0xdceb, 0x1419, + 0xdcf1, 0x233d, + 0xdcf2, 0x1420, + 0xdcf6, 0x233e, + 0xdcf7, 0x1425, + 0xdcf9, 0x233f, + 0xdcfa, 0x1428, + 0xdcfd, 0x2340, + 0xdda1, 0x2342, + 0xdda2, 0x142e, + 0xdda3, 0x2343, + 0xdda8, 0x1434, + 0xddaa, 0x2348, + 0xddac, 0x1438, + 0xddb2, 0x234a, + 0xddb3, 0x143f, + 0xddb5, 0x234b, + 0xddb6, 0x1442, + 0xddba, 0x234c, + 0xddbc, 0x1448, + 0xddd3, 0x234e, + 0xddd4, 0x1460, + 0xdddb, 0x234f, + 0xdddc, 0x1468, + 0xddde, 0x2350, + 0xdddf, 0x146b, + 0xdde4, 0x2351, + 0xdde5, 0x1471, + 0xddeb, 0x2352, + 0xddec, 0x1478, + 0xddf1, 0x2353, + 0xddf2, 0x147e, + 0xddf6, 0x2354, + 0xddf8, 0x1484, + 0xddfc, 0x2356, + 0xddfd, 0x1489, + 0xddfe, 0x2357, + 0xdea1, 0x148b, + 0xdead, 0x2358, + 0xdeae, 0x1498, + 0xdeb4, 0x2359, + 0xdeb5, 0x149f, + 0xdeba, 0x235a, + 0xdebb, 0x14a5, + 0xdec6, 0x235b, + 0xdec7, 0x14b1, + 0xdecf, 0x235c, + 0xded0, 0x14ba, + 0xded1, 0x235d, + 0xded3, 0x14bd, + 0xded8, 0x235f, + 0xded9, 0x14c3, + 0xdee2, 0x2360, + 0xdee3, 0x14cd, + 0xdee8, 0x2361, + 0xdee9, 0x14d3, + 0xdeec, 0x2362, + 0xdeed, 0x14d7, + 0xdef3, 0x2363, + 0xdef4, 0x14de, + 0xdefc, 0x2364, + 0xdefd, 0x14e7, + 0xdfa1, 0x14e9, + 0xdfa2, 0x2365, + 0xdfa4, 0x14ec, + 0xdfa5, 0x2367, + 0xdfa6, 0x14ee, + 0xdfb4, 0x2368, + 0xdfb5, 0x14fd, + 0xdfbc, 0x2369, + 0xdfbe, 0x1506, + 0xdfbf, 0x236b, + 0xdfc0, 0x1508, + 0xdfc2, 0x236c, + 0xdfc4, 0x150c, + 0xdfcc, 0x236e, + 0xdfcd, 0x1515, + 0xdfd0, 0x236f, + 0xdfd1, 0x1519, + 0xdfd5, 0x2370, + 0xdfd6, 0x151e, + 0xdfd8, 0x2371, + 0xdfda, 0x1522, + 0xdfdc, 0x2373, + 0xdfdd, 0x1525, + 0xdfe0, 0x2374, + 0xdfe1, 0x1529, + 0xdfe2, 0x2375, + 0xdfe3, 0x152b, + 0xdfe6, 0x2376, + 0xdfe7, 0x152f, + 0xdfe9, 0x2377, + 0xdfea, 0x1532, + 0xdfeb, 0x2378, + 0xdfec, 0x1534, + 0xdfef, 0x2379, + 0xdff0, 0x1538, + 0xdff5, 0x237a, + 0xdff6, 0x153e, + 0xdff9, 0x237b, + 0xdffa, 0x1542, + 0xe0a1, 0x1547, + 0xe0b6, 0x237c, + 0xe0b8, 0x155e, + 0xe0bf, 0x237e, + 0xe0c0, 0x1566, + 0xe0c8, 0x237f, + 0xe0c9, 0x156f, + 0xe0ce, 0x2380, + 0xe0cf, 0x1575, + 0xe0d3, 0x2381, + 0xe0d4, 0x157a, + 0xe0e0, 0x2382, + 0xe0e1, 0x1587, + 0xe0f0, 0x2383, + 0xe0f1, 0x1597, + 0xe0f8, 0x2384, + 0xe0f9, 0x159f, + 0xe0fc, 0x2385, + 0xe1a1, 0x15a5, + 0xe1ab, 0x2388, + 0xe1ac, 0x15b0, + 0xe1ad, 0x2389, + 0xe1ae, 0x15b2, + 0xe1b0, 0x238a, + 0xe1b1, 0x15b5, + 0xe1b4, 0x238b, + 0xe1b5, 0x15b9, + 0xe1bb, 0x238c, + 0xe1bc, 0x15c0, + 0xe1bd, 0x238d, + 0xe1be, 0x15c2, + 0xe1c0, 0x238e, + 0xe1c2, 0x15c6, + 0xe1c9, 0x2390, + 0xe1ca, 0x15ce, + 0xe1d0, 0x2391, + 0xe1d1, 0x15d5, + 0xe1db, 0x2392, + 0xe1dc, 0x15e0, + 0xe1e1, 0x07aa, + 0xe1e2, 0x2393, + 0xe1e3, 0x15e7, + 0xe1e7, 0x1198, + 0xe1e8, 0x15ec, + 0xe1ee, 0x2394, + 0xe1f0, 0x15f4, + 0xe1f6, 0x2396, + 0xe1f7, 0x15fb, + 0xe1f8, 0x2397, + 0xe1f9, 0x15fd, + 0xe1fd, 0x2398, + 0xe1fe, 0x1602, + 0xe2a1, 0x1603, + 0xe2a4, 0x2399, + 0xe2a5, 0x1607, + 0xe2a8, 0x239a, + 0xe2a9, 0x160b, + 0xe2bb, 0x239b, + 0xe2c5, 0x10c5, + 0xe2c6, 0x23a5, + 0xe2cf, 0x1631, + 0xe2d0, 0x23ae, + 0xe2d1, 0x1633, + 0xe2d9, 0x23af, + 0xe2da, 0x163c, + 0xe2e3, 0x23b0, + 0xe2e5, 0x1647, + 0xe2e6, 0x23b2, + 0xe2e7, 0x1649, + 0xe2e9, 0x23b3, + 0xe2ec, 0x164e, + 0xe2f8, 0x23b6, + 0xe2f9, 0x165b, + 0xe2fa, 0x23b7, + 0xe2fe, 0x1660, + 0xe3a1, 0x1661, + 0xe3a2, 0x23bb, + 0xe3a3, 0x1663, + 0xe3a5, 0x23bc, + 0xe3a6, 0x1666, + 0xe3ab, 0x23bd, + 0xe3ac, 0x166c, + 0xe3b4, 0x23be, + 0xe3b5, 0x1675, + 0xe3c5, 0x23bf, + 0xe3dc, 0x169c, + 0xe3e3, 0x23d6, + 0xe3e4, 0x16a4, + 0xe3ed, 0x23d7, + 0xe3ee, 0x16ae, + 0xe3f1, 0x23d8, + 0xe3f3, 0x16b3, + 0xe3f8, 0x23da, + 0xe3f9, 0x16b9, + 0xe3fe, 0x23db, + 0xe4a1, 0x16bf, + 0xe4a4, 0x23dc, + 0xe4a6, 0x16c4, + 0xe4ab, 0x23de, + 0xe4ac, 0x16ca, + 0xe4af, 0x23df, + 0xe4b2, 0x16d0, + 0xe4b5, 0x23e2, + 0xe4b7, 0x16d5, + 0xe4c2, 0x23e4, + 0xe4c3, 0x16e1, + 0xe4c5, 0x23e5, + 0xe4c6, 0x16e4, + 0xe4c9, 0x23e6, + 0xe4ca, 0x16e8, + 0xe4d9, 0x23e7, + 0xe4da, 0x16f8, + 0xe4dc, 0x23e8, + 0xe4dd, 0x16fb, + 0xe4de, 0x23e9, + 0xe4df, 0x16fd, + 0xe4e4, 0x23ea, + 0xe4e5, 0x1703, + 0xe4eb, 0x23eb, + 0xe4ed, 0x170b, + 0xe4f2, 0x23ed, + 0xe4f3, 0x1711, + 0xe4fe, 0x23ee, + 0xe5a1, 0x171d, + 0xe5b0, 0x23ef, + 0xe5b1, 0x172d, + 0xe5b9, 0x23f0, + 0xe5ba, 0x1736, + 0xe5c7, 0x23f1, + 0xe5c8, 0x1744, + 0xe5c9, 0x23f2, + 0xe5ca, 0x1746, + 0xe5ce, 0x23f3, + 0xe5cf, 0x174b, + 0xe5f0, 0x23f4, + 0xe5f1, 0x176d, + 0xe5f2, 0x23f5, + 0xe5f3, 0x176f, + 0xe5fc, 0x23f6, + 0xe5fe, 0x177a, + 0xe6a1, 0x177b, + 0xe6a3, 0x23f8, + 0xe6a4, 0x177e, + 0xe6ab, 0x23f9, + 0xe6ad, 0x1787, + 0xe6ae, 0x23fb, + 0xe6af, 0x1789, + 0xe6b4, 0x23fc, + 0xe6b6, 0x1790, + 0xe6bf, 0x23fe, + 0xe6c0, 0x179a, + 0xe6c8, 0x23ff, + 0xe6ca, 0x17a4, + 0xe6cd, 0x2401, + 0xe6ce, 0x17a8, + 0xe6e0, 0x2402, + 0xe7a1, 0x2421, + 0xe7db, 0x1813, + 0xe7e1, 0x245b, + 0xe7e3, 0x181b, + 0xe7e7, 0x245d, + 0xe7e8, 0x1820, + 0xe7ef, 0x245e, + 0xe7f0, 0x1828, + 0xe7f4, 0x245f, + 0xe7f7, 0x182f, + 0xe8a1, 0x1837, + 0xe8a8, 0x2462, + 0xe8a9, 0x183f, + 0xe8ac, 0x2463, + 0xe8ad, 0x1843, + 0xe8b6, 0x2464, + 0xe8b7, 0x184d, + 0xe8b8, 0x2465, + 0xe8bb, 0x1851, + 0xe8bf, 0x2468, + 0xe8c1, 0x1857, + 0xe8c5, 0x246a, + 0xe8c6, 0x185c, + 0xe8c7, 0x246b, + 0xe8ca, 0x1860, + 0xe8ce, 0x246e, + 0xe8cf, 0x1865, + 0xe8d0, 0x246f, + 0xe8d1, 0x1867, + 0xe8d3, 0x2470, + 0xe8d4, 0x186a, + 0xe8dd, 0x2471, + 0xe8de, 0x1874, + 0xe8df, 0x2472, + 0xe8e0, 0x1876, + 0xe8e2, 0x2473, + 0xe8e4, 0x187a, + 0xe8e5, 0x2475, + 0xe8e6, 0x187c, + 0xe8e7, 0x2476, + 0xe8e8, 0x187e, + 0xe8eb, 0x2477, + 0xe8ec, 0x1882, + 0xe8ed, 0x2478, + 0xe8ee, 0x1884, + 0xe8ef, 0x2479, + 0xe8f0, 0x1886, + 0xe8f9, 0x247a, + 0xe8fa, 0x1890, + 0xe8fc, 0x247b, + 0xe8fe, 0x1894, + 0xe9a1, 0x247d, + 0xe9a2, 0x1896, + 0xe9ad, 0x247e, + 0xe9ae, 0x18a2, + 0xe9b4, 0x247f, + 0xe9b6, 0x18aa, + 0xe9b7, 0x2481, + 0xe9b8, 0x18ac, + 0xe9c4, 0x2482, + 0xe9c5, 0x18b9, + 0xe9c6, 0x2483, + 0xe9c7, 0x18bb, + 0xe9c9, 0x2484, + 0xe9ca, 0x18be, + 0xe9d6, 0x2485, + 0xe9d7, 0x18cb, + 0xe9da, 0x2486, + 0xe9db, 0x18cf, + 0xe9e4, 0x2487, + 0xe9e5, 0x18d9, + 0xe9e6, 0x2488, + 0xe9e8, 0x18dc, + 0xe9e9, 0x248a, + 0xe9ea, 0x18de, + 0xe9eb, 0x248b, + 0xe9ec, 0x18e0, + 0xe9ed, 0x248c, + 0xeaa1, 0x249e, + 0xeaa6, 0x18f8, + 0xeaa7, 0x24a3, + 0xeaa9, 0x18fb, + 0xeab1, 0x24a5, + 0xeab2, 0x1904, + 0xeabc, 0x24a6, + 0xeabd, 0x190f, + 0xeaca, 0x24a7, + 0xeacb, 0x191d, + 0xeacd, 0x24a8, + 0xeace, 0x1920, + 0xead3, 0x24a9, + 0xead4, 0x1926, + 0xeada, 0x24aa, + 0xeaf0, 0x1942, + 0xeba1, 0x1951, + 0xeba7, 0x24c0, + 0xeba8, 0x1958, + 0xebaa, 0x24c1, + 0xebab, 0x195b, + 0xebb2, 0x24c2, + 0xebb3, 0x1963, + 0xebb9, 0x24c3, + 0xebba, 0x196a, + 0xebca, 0x24c4, + 0xebcc, 0x197c, + 0xebcd, 0x24c6, + 0xebce, 0x197e, + 0xebd6, 0x24c7, + 0xebd7, 0x1987, + 0xebda, 0x24c8, + 0xebdb, 0x198b, + 0xebe1, 0x24c9, + 0xebe2, 0x1992, + 0xebf7, 0x24ca, + 0xebf8, 0x19a8, + 0xeca1, 0x19af, + 0xeca3, 0x24cb, + 0xeca4, 0x19b2, + 0xeca9, 0x24cc, + 0xecaf, 0x19bd, + 0xecb1, 0x24d2, + 0xecb2, 0x19c0, + 0xecb4, 0x24d3, + 0xecb6, 0x19c4, + 0xecbe, 0x24d5, + 0xecc0, 0x19ce, + 0xecc1, 0x24d7, + 0xecc2, 0x19d0, + 0xecc7, 0x24d8, + 0xecc8, 0x19d6, + 0xeccb, 0x24d9, + 0xeccc, 0x19da, + 0xece2, 0x24da, + 0xece3, 0x19f1, + 0xecf2, 0x24db, + 0xecf3, 0x1a01, + 0xecf5, 0x24dc, + 0xecf6, 0x1a04, + 0xecf8, 0x24dd, + 0xecf9, 0x1a07, + 0xeda1, 0x24de, + 0xeda2, 0x1a0e, + 0xeda8, 0x24df, + 0xeda9, 0x1a15, + 0xedaf, 0x24e0, + 0xedb1, 0x1a1d, + 0xedb4, 0x24e2, + 0xedb5, 0x1a21, + 0xedb6, 0x24e3, + 0xedb7, 0x1a23, + 0xedb8, 0x24e4, + 0xedb9, 0x1a25, + 0xedba, 0x24e5, + 0xedbb, 0x1a27, + 0xedbf, 0x24e6, + 0xedc0, 0x1a2c, + 0xedc2, 0x24e7, + 0xedc4, 0x1a30, + 0xedcc, 0x24e9, + 0xedce, 0x1a3a, + 0xedd3, 0x24eb, + 0xedd4, 0x1a40, + 0xedd7, 0x24ec, + 0xedd8, 0x1a44, + 0xede8, 0x24ed, + 0xede9, 0x1a55, + 0xedee, 0x24ee, + 0xedef, 0x1a5b, + 0xedf9, 0x24ef, + 0xedfb, 0x1a67, + 0xeea1, 0x1a6b, + 0xeebc, 0x24f1, + 0xeebd, 0x1a87, + 0xeebf, 0x24f2, + 0xeec0, 0x1a8a, + 0xeec4, 0x24f3, + 0xefa1, 0x252e, + 0xeff2, 0x1b1a, + 0xf0a1, 0x1b27, + 0xf0a3, 0x257f, + 0xf0a4, 0x1b2a, + 0xf0af, 0x2580, + 0xf0da, 0x1b60, + 0xf0dc, 0x25ab, + 0xf0de, 0x1b64, + 0xf0df, 0x25ad, + 0xf0e0, 0x1b66, + 0xf0e9, 0x25ae, + 0xf0ea, 0x1b70, + 0xf0ec, 0x25af, + 0xf0ed, 0x1b73, + 0xf0ef, 0x25b0, + 0xf0f0, 0x1b76, + 0xf0f7, 0x25b1, + 0xf0f8, 0x1b7e, + 0xf0f9, 0x25b2, + 0xf0fa, 0x1b80, + 0xf0fc, 0x25b3, + 0xf0fd, 0x1b83, + 0xf1a1, 0x1b85, + 0xf1a8, 0x25b4, + 0xf1a9, 0x1b8d, + 0xf1ab, 0x25b5, + 0xf1ac, 0x1b90, + 0xf1ae, 0x25b6, + 0xf1af, 0x1b93, + 0xf1b2, 0x25b7, + 0xf1b3, 0x1b97, + 0xf1bc, 0x25b8, + 0xf1bd, 0x1ba1, + 0xf1c0, 0x25b9, + 0xf1c1, 0x1ba5, + 0xf1c9, 0x25ba, + 0xf1ca, 0x1bae, + 0xf1cd, 0x25bb, + 0xf1ce, 0x1bb2, + 0xf1cf, 0x25bc, + 0xf1d1, 0x1bb5, + 0xf1da, 0x25be, + 0xf1db, 0x1bbf, + 0xf1dc, 0x25bf, + 0xf1dd, 0x1bc1, + 0xf1e4, 0x25c0, + 0xf1e5, 0x1bc9, + 0xf1ec, 0x25c1, + 0xf1ed, 0x1bd1, + 0xf1ef, 0x25c2, + 0xf1f0, 0x1bd4, + 0xf1f7, 0x25c3, + 0xf1f8, 0x1bdc, + 0xf1f9, 0x25c4, + 0xf1fa, 0x1bde, + 0xf1fc, 0x25c5, + 0xf2a1, 0x25c8, + 0xf2ae, 0x1bf0, + 0xf2b1, 0x25d5, + 0xf2b3, 0x1bf5, + 0xf2b9, 0x25d7, + 0xf2ba, 0x1bfc, + 0xf2c3, 0x25d8, + 0xf2c4, 0x1c06, + 0xf2c9, 0x25d9, + 0xf2ca, 0x1c0c, + 0xf2cc, 0x25da, + 0xf2ce, 0x1c10, + 0xf2cf, 0x25dc, + 0xf2d0, 0x1c12, + 0xf2d3, 0x25dd, + 0xf2d4, 0x1c16, + 0xf2e5, 0x25de, + 0xf2e6, 0x1c28, + 0xf2ee, 0x25df, + 0xf2ef, 0x1c31, + 0xf2f7, 0x25e0, + 0xf2f8, 0x1c3a, + 0xf2fd, 0x25e1, + 0xf2fe, 0x1c40, + 0xf3a1, 0x1c41, + 0xf3bf, 0x25e2, + 0xf3c0, 0x1c60, + 0xf3c6, 0x25e3, + 0xf3c7, 0x1c67, + 0xf3c8, 0x25e4, + 0xf3c9, 0x1c69, + 0xf3d6, 0x25e5, + 0xf3d7, 0x1c77, + 0xf3d9, 0x25e6, + 0xf3da, 0x1c7a, + 0xf3e5, 0x25e7, + 0xf3e7, 0x1c87, + 0xf3ea, 0x25e9, + 0xf3eb, 0x1c8b, + 0xf3ec, 0x25ea, + 0xf3ed, 0x1c8d, + 0xf3ef, 0x25eb, + 0xf3f0, 0x1c90, + 0xf3f1, 0x25ec, + 0xf3f2, 0x1c92, + 0xf3fd, 0x25ed, + 0xf3fe, 0x1c9e, + 0xf4a1, 0x1c9f, + 0xf4a5, 0x25ee, + 0xf4a6, 0x1ca4, + 0xf4af, 0x25ef, + 0xf4b0, 0x1cae, + 0xf4b5, 0x25f0, + 0xf4b6, 0x1cb4, + 0xf4c1, 0x25f1, + 0xf4c2, 0x1cc0, + 0xf4c7, 0x25f2, + 0xf4c8, 0x1cc6, + 0xf4cf, 0x25f3, + 0xf4d1, 0x1ccf, + 0xf4d6, 0x25f5, + 0xf4d7, 0x1cd5, + 0xf4ea, 0x25f6, + 0xf4eb, 0x1ce9, + 0xf4ef, 0x25f7, + 0xf4f0, 0x1cee, + 0xf4f5, 0x25f8, + 0xf4f6, 0x1cf4, + 0xf5a1, 0x1cfd, + 0xf5a6, 0x25f9, + 0xf5a8, 0x1d04, + 0xf5ba, 0x25fb, + 0xf5bc, 0x1d18, + 0xf5c4, 0x25fd, + 0xf5c5, 0x1d21, + 0xf5c8, 0x25fe, + 0xf5c9, 0x1d25, + 0xf5ce, 0x25ff, + 0xf5d0, 0x1d2c, + 0xf5d1, 0x2601, + 0xf5d3, 0x1d2f, + 0xf5d9, 0x2603, + 0xf5da, 0x1d36, + 0xf5dc, 0x2604, + 0xf5dd, 0x1d39, + 0xf5e6, 0x2605, + 0xf5e8, 0x1d44, + 0xf5ef, 0x2607, + 0xf5f0, 0x1d4c, + 0xf5f2, 0x2608, + 0xf5f3, 0x1d4f, + 0xf5fc, 0x2609, + 0xf5fd, 0x1d59, + 0xf6a1, 0x1d5b, + 0xf6a3, 0x260a, + 0xf6a4, 0x1d5e, + 0xf6a6, 0x260b, + 0xf6a7, 0x1d61, + 0xf6a8, 0x260c, + 0xf6a9, 0x1d63, + 0xf6ab, 0x260d, + 0xf6ac, 0x1d66, + 0xf6b0, 0x260e, + 0xf6b1, 0x1d6b, + 0xf6b3, 0x260f, + 0xf6bf, 0x1d79, + 0xf6c5, 0x261b, + 0xf6c6, 0x1d80, + 0xf6c7, 0x261c, + 0xf6c8, 0x1d82, + 0xf6c9, 0x261d, + 0xf6ca, 0x1d84, + 0xf6cf, 0x261e, + 0xf7a1, 0x264e, + 0xf7b0, 0x1dc8, + 0xf7b2, 0x265d, + 0xf7b4, 0x1dcc, + 0xf7b5, 0x265f, + 0xf7b6, 0x1dce, + 0xf7bd, 0x2660, + 0xf7be, 0x1dd6, + 0xf7c3, 0x2661, + 0xf7c4, 0x1ddc, + 0xf7c5, 0x2662, + 0xf7c7, 0x1ddf, + 0xf7ca, 0x2664, + 0xf7cc, 0x1de4, + 0xf7cf, 0x2666, + 0xf7d1, 0x1de9, + 0xf7de, 0x2668, + 0xf7df, 0x1df7, + 0xf7e1, 0x0ab9, + 0xf7e2, 0x1dfa, + 0xf7f2, 0x2669, + 0xf7f3, 0x1e0b, + 0xf7f5, 0x266a, + 0xf7f6, 0x1e0e, + 0xf8a1, 0x266b, + 0xf8a7, 0x04cc, + 0xf8a8, 0x050a, + 0xf8a9, 0x0518, + 0xf8aa, 0x2671, + 0xf8ac, 0x0594, + 0xf8ad, 0x05ce, + 0xf8ae, 0x2673, + 0xf8af, 0x05f6, + 0xf8b0, 0x2674, + 0xf8b2, 0x0653, + 0xf8b3, 0x067e, + 0xf8b4, 0x2676, + 0xf8b5, 0x06c4, + 0xf8b6, 0x2677, + 0xf8b8, 0x073c, + 0xf8b9, 0x2679, + 0xf8bb, 0x07c3, + 0xf8bc, 0x267b, + 0xf8c0, 0x082b, + 0xf8c1, 0x267f, + 0xf8c2, 0x084e, + 0xf8c3, 0x0869, + 0xf8c4, 0x2680, + 0xf8c6, 0x090c, + 0xf8c7, 0x2682, + 0xf8c9, 0x0971, + 0xf8ca, 0x2684, + 0xf8cb, 0x099a, + 0xf8cd, 0x2685, + 0xf8ce, 0x09da, + 0xf8cf, 0x2686, + 0xf8d0, 0x09fa, + 0xf8d1, 0x2687, + 0xf8dc, 0x0bda, + 0xf8dd, 0x0bdd, + 0xf8de, 0x0bea, + 0xf8df, 0x0bec, + 0xf8e0, 0x0bf2, + 0xf8e1, 0x2692, + 0xf8e6, 0x0c92, + 0xf8e7, 0x0d1a, + 0xf8e8, 0x0d8c, + 0xf8e9, 0x0dbe, + 0xf8ea, 0x2697, + 0xf8eb, 0x0dfb, + 0xf8ec, 0x2698, + 0xf8ef, 0x0e70, + 0xf8f0, 0x269b, + 0xf8f1, 0x0ea3, + 0xf8f2, 0x269c, + 0xf8f8, 0x103d, + 0xf8f9, 0x10d9, + 0xf8fa, 0x26a2, + 0xf8fc, 0x10fb, + 0xf8fd, 0x1109, + 0xf8fe, 0x26a4, + 0xf9a1, 0x11a1, + 0xf9a2, 0x26a5, + 0xf9a3, 0x11ba, + 0xf9a4, 0x26a6, + 0xf9a6, 0x11d5, + 0xf9a7, 0x26a8, + 0xf9a8, 0x11fd, + 0xf9a9, 0x1219, + 0xa1a2, 0x023f, + 0xa1a3, 0x023e, + 0xa1aa, 0x0256, + 0xa1ab, 0x1e18, + 0xa1ad, 0x0257, + 0xa1b2, 0x0246, + 0xa1fe, 0x1e1a, + 0xa3a1, 0x0242, + 0xa3a8, 0x0244, + 0xa3ac, 0x023d, + 0xa3ae, 0x1e1b, + 0xa3ba, 0x0240, + 0xa3bd, 0x1e1c, + 0xa3bf, 0x0243, + 0xa3db, 0x1e1d, + 0xa3dd, 0x1e1e, + 0xa3df, 0x0258, + 0xa3fb, 0x0254, + 0xa3fd, 0x0255, + 0xa3fe, 0x1e1f, + 0xffff, 0x0000 +}; + +static GfxFontEncoding16 gb12GBTpcEUCVEnc16 = { + 1, + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1 }, + { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, + 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010, + 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, + 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, 0x0020, + 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, + 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, 0x0030, + 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, + 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040, + 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, + 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050, + 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, + 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0000, + 0x1e20, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1e21, 0x1e22, 0x1e23 }, + gb12GBTpcEUCVMap2, 2303 +}; + +static Gushort gb12GBpcEUCHMap2[180] = { + 0x0000, 0x0000, + 0xa1a1, 0x0060, + 0xa2b1, 0x00be, + 0xa2e5, 0x00f0, + 0xa2f1, 0x00fa, + 0xa3a1, 0x0106, + 0xa4a1, 0x0164, + 0xa5a1, 0x01b7, + 0xa6a1, 0x020d, + 0xa6c1, 0x0225, + 0xa7a1, 0x025a, + 0xa7d1, 0x027b, + 0xa8a1, 0x029c, + 0xa8c5, 0x02bc, + 0xa9a4, 0x02e2, + 0xaaa1, 0x032e, + 0xaba1, 0x038c, + 0xb0a1, 0x03ac, + 0xb1a1, 0x040a, + 0xb2a1, 0x0468, + 0xb3a1, 0x04c6, + 0xb4a1, 0x0524, + 0xb5a1, 0x0582, + 0xb6a1, 0x05e0, + 0xb7a1, 0x063e, + 0xb8a1, 0x069c, + 0xb9a1, 0x06fa, + 0xbaa1, 0x0758, + 0xbba1, 0x07b6, + 0xbca1, 0x0814, + 0xbda1, 0x0872, + 0xbea1, 0x08d0, + 0xbfa1, 0x092e, + 0xc0a1, 0x098c, + 0xc1a1, 0x09ea, + 0xc2a1, 0x0a48, + 0xc3a1, 0x0aa6, + 0xc4a1, 0x0b04, + 0xc5a1, 0x0b62, + 0xc6a1, 0x0bc0, + 0xc7a1, 0x0c1e, + 0xc8a1, 0x0c7c, + 0xc9a1, 0x0cda, + 0xcaa1, 0x0d38, + 0xcba1, 0x0d96, + 0xcca1, 0x0df4, + 0xcda1, 0x0e52, + 0xcea1, 0x0eb0, + 0xcfa1, 0x0f0e, + 0xd0a1, 0x0f6c, + 0xd1a1, 0x0fca, + 0xd2a1, 0x1028, + 0xd3a1, 0x1086, + 0xd4a1, 0x10e4, + 0xd5a1, 0x1142, + 0xd6a1, 0x11a0, + 0xd7a1, 0x11fe, + 0xd8a1, 0x1257, + 0xd9a1, 0x12b5, + 0xdaa1, 0x1313, + 0xdba1, 0x1371, + 0xdca1, 0x13cf, + 0xdda1, 0x142d, + 0xdea1, 0x148b, + 0xdfa1, 0x14e9, + 0xe0a1, 0x1547, + 0xe1a1, 0x15a5, + 0xe2a1, 0x1603, + 0xe3a1, 0x1661, + 0xe4a1, 0x16bf, + 0xe5a1, 0x171d, + 0xe6a1, 0x177b, + 0xe7a1, 0x17d9, + 0xe8a1, 0x1837, + 0xe9a1, 0x1895, + 0xeaa1, 0x18f3, + 0xeba1, 0x1951, + 0xeca1, 0x19af, + 0xeda1, 0x1a0d, + 0xeea1, 0x1a6b, + 0xefa1, 0x1ac9, + 0xf0a1, 0x1b27, + 0xf1a1, 0x1b85, + 0xf2a1, 0x1be3, + 0xf3a1, 0x1c41, + 0xf4a1, 0x1c9f, + 0xf5a1, 0x1cfd, + 0xf6a1, 0x1d5b, + 0xf7a1, 0x1db9, + 0xffff, 0x0000 +}; + +static GfxFontEncoding16 gb12GBpcEUCHEnc16 = { + 0, + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1 }, + { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, + 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010, + 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, + 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, 0x0020, + 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, + 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, 0x0030, + 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, + 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040, + 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, + 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050, + 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, + 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0000, + 0x1e20, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1e21, 0x1e22, 0x1e23 }, + gb12GBpcEUCHMap2, 90 +}; + +static Gushort gb12GBpcEUCVMap2[220] = { + 0x0000, 0x0000, + 0xa1a1, 0x0060, + 0xa2b1, 0x00be, + 0xa2e5, 0x00f0, + 0xa2f1, 0x00fa, + 0xa3a1, 0x0106, + 0xa4a1, 0x0164, + 0xa5a1, 0x01b7, + 0xa6a1, 0x020d, + 0xa6c1, 0x0225, + 0xa7a1, 0x025a, + 0xa7d1, 0x027b, + 0xa8a1, 0x029c, + 0xa8c5, 0x02bc, + 0xa9a4, 0x02e2, + 0xaaa1, 0x032e, + 0xaba1, 0x038c, + 0xb0a1, 0x03ac, + 0xb1a1, 0x040a, + 0xb2a1, 0x0468, + 0xb3a1, 0x04c6, + 0xb4a1, 0x0524, + 0xb5a1, 0x0582, + 0xb6a1, 0x05e0, + 0xb7a1, 0x063e, + 0xb8a1, 0x069c, + 0xb9a1, 0x06fa, + 0xbaa1, 0x0758, + 0xbba1, 0x07b6, + 0xbca1, 0x0814, + 0xbda1, 0x0872, + 0xbea1, 0x08d0, + 0xbfa1, 0x092e, + 0xc0a1, 0x098c, + 0xc1a1, 0x09ea, + 0xc2a1, 0x0a48, + 0xc3a1, 0x0aa6, + 0xc4a1, 0x0b04, + 0xc5a1, 0x0b62, + 0xc6a1, 0x0bc0, + 0xc7a1, 0x0c1e, + 0xc8a1, 0x0c7c, + 0xc9a1, 0x0cda, + 0xcaa1, 0x0d38, + 0xcba1, 0x0d96, + 0xcca1, 0x0df4, + 0xcda1, 0x0e52, + 0xcea1, 0x0eb0, + 0xcfa1, 0x0f0e, + 0xd0a1, 0x0f6c, + 0xd1a1, 0x0fca, + 0xd2a1, 0x1028, + 0xd3a1, 0x1086, + 0xd4a1, 0x10e4, + 0xd5a1, 0x1142, + 0xd6a1, 0x11a0, + 0xd7a1, 0x11fe, + 0xd8a1, 0x1257, + 0xd9a1, 0x12b5, + 0xdaa1, 0x1313, + 0xdba1, 0x1371, + 0xdca1, 0x13cf, + 0xdda1, 0x142d, + 0xdea1, 0x148b, + 0xdfa1, 0x14e9, + 0xe0a1, 0x1547, + 0xe1a1, 0x15a5, + 0xe2a1, 0x1603, + 0xe3a1, 0x1661, + 0xe4a1, 0x16bf, + 0xe5a1, 0x171d, + 0xe6a1, 0x177b, + 0xe7a1, 0x17d9, + 0xe8a1, 0x1837, + 0xe9a1, 0x1895, + 0xeaa1, 0x18f3, + 0xeba1, 0x1951, + 0xeca1, 0x19af, + 0xeda1, 0x1a0d, + 0xeea1, 0x1a6b, + 0xefa1, 0x1ac9, + 0xf0a1, 0x1b27, + 0xf1a1, 0x1b85, + 0xf2a1, 0x1be3, + 0xf3a1, 0x1c41, + 0xf4a1, 0x1c9f, + 0xf5a1, 0x1cfd, + 0xf6a1, 0x1d5b, + 0xf7a1, 0x1db9, + 0xa1a2, 0x023f, + 0xa1a3, 0x023e, + 0xa1aa, 0x0256, + 0xa1ab, 0x1e18, + 0xa1ad, 0x0257, + 0xa1b2, 0x0246, + 0xa1fe, 0x1e1a, + 0xa3a1, 0x0242, + 0xa3a8, 0x0244, + 0xa3ac, 0x023d, + 0xa3ae, 0x1e1b, + 0xa3ba, 0x0240, + 0xa3bd, 0x1e1c, + 0xa3bf, 0x0243, + 0xa3db, 0x1e1d, + 0xa3dd, 0x1e1e, + 0xa3df, 0x0258, + 0xa3fb, 0x0254, + 0xa3fd, 0x0255, + 0xa3fe, 0x1e1f, + 0xffff, 0x0000 +}; + +static GfxFontEncoding16 gb12GBpcEUCVEnc16 = { + 1, + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1 }, + { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, + 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010, + 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, + 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, 0x0020, + 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, + 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, 0x0030, + 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, + 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040, + 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, + 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050, + 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, + 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0000, + 0x1e20, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1e21, 0x1e22, 0x1e23 }, + gb12GBpcEUCVMap2, 110 +}; + +static Gushort gb12UniGBUCS2HMap2[26922] = { + 0x0000, 0x0000, + 0x0020, 0x0001, + 0x00a4, 0x00a7, + 0x00a7, 0x00ab, + 0x00a8, 0x0066, + 0x00b0, 0x00a2, + 0x00b1, 0x007f, + 0x00d7, 0x0080, + 0x00e0, 0x029f, + 0x00e1, 0x029d, + 0x00e8, 0x02a3, + 0x00e9, 0x02a1, + 0x00ea, 0x02b5, + 0x00ec, 0x02a7, + 0x00ed, 0x02a5, + 0x00f2, 0x02ab, + 0x00f3, 0x02a9, + 0x00f7, 0x0081, + 0x00f9, 0x02af, + 0x00fa, 0x02ad, + 0x00fc, 0x02b4, + 0x0101, 0x029c, + 0x0113, 0x02a0, + 0x011b, 0x02a2, + 0x012b, 0x02a4, + 0x014d, 0x02a8, + 0x016b, 0x02ac, + 0x01ce, 0x029e, + 0x01d0, 0x02a6, + 0x01d2, 0x02aa, + 0x01d4, 0x02ae, + 0x01d6, 0x02b0, + 0x01d8, 0x02b1, + 0x01da, 0x02b2, + 0x01dc, 0x02b3, + 0x02c7, 0x0065, + 0x02c9, 0x0064, + 0x02ca, 0x26b3, + 0x02d9, 0x26b5, + 0x0391, 0x020d, + 0x03a3, 0x021e, + 0x03b1, 0x0225, + 0x03c3, 0x0236, + 0x0401, 0x0260, + 0x0410, 0x025a, + 0x0416, 0x0261, + 0x0436, 0x0282, + 0x0451, 0x0281, + 0x1e3f, 0x02b7, + 0x2010, 0x2722, + 0x2013, 0x26b6, + 0x2014, 0x0069, + 0x2015, 0x26b7, + 0x2016, 0x006b, + 0x2018, 0x006d, + 0x201c, 0x006f, + 0x2025, 0x26b8, + 0x2026, 0x006c, + 0x2030, 0x00aa, + 0x2032, 0x00a3, + 0x2035, 0x26b9, + 0x203b, 0x00b8, + 0x2103, 0x00a5, + 0x2105, 0x26ba, + 0x2109, 0x26bb, + 0x2116, 0x00ac, + 0x2121, 0x2720, + 0x2160, 0x00fa, + 0x2170, 0x26a9, + 0x2190, 0x00ba, + 0x2192, 0x00b9, + 0x2193, 0x00bc, + 0x2196, 0x26bc, + 0x2208, 0x0089, + 0x220f, 0x0086, + 0x2211, 0x0085, + 0x2215, 0x26c0, + 0x221a, 0x008b, + 0x221d, 0x0097, + 0x221e, 0x009d, + 0x221f, 0x26c1, + 0x2220, 0x008e, + 0x2223, 0x26c2, + 0x2225, 0x008d, + 0x2227, 0x0083, + 0x2229, 0x0088, + 0x222a, 0x0087, + 0x222b, 0x0091, + 0x222e, 0x0092, + 0x2234, 0x009f, + 0x2235, 0x009e, + 0x2236, 0x0082, + 0x2237, 0x008a, + 0x223d, 0x0096, + 0x2248, 0x0095, + 0x224c, 0x0094, + 0x2252, 0x26c3, + 0x2260, 0x0098, + 0x2261, 0x0093, + 0x2264, 0x009b, + 0x2266, 0x26c4, + 0x226e, 0x0099, + 0x2295, 0x2704, + 0x2299, 0x0090, + 0x22a5, 0x008c, + 0x22bf, 0x26c6, + 0x22ef, 0x006c, + 0x2312, 0x008f, + 0x2460, 0x00e6, + 0x2474, 0x00d2, + 0x2488, 0x00be, + 0x2500, 0x02e2, + 0x2550, 0x26c7, + 0x2581, 0x26eb, + 0x2593, 0x26fa, + 0x25a0, 0x00b5, + 0x25a1, 0x00b4, + 0x25b2, 0x00b7, + 0x25b3, 0x00b6, + 0x25bc, 0x26fd, + 0x25c6, 0x00b3, + 0x25c7, 0x00b2, + 0x25cb, 0x00af, + 0x25ce, 0x00b1, + 0x25cf, 0x00b0, + 0x25e2, 0x26ff, + 0x2605, 0x00ae, + 0x2606, 0x00ad, + 0x2609, 0x2703, + 0x2640, 0x00a1, + 0x2642, 0x00a0, + 0x3000, 0x0060, + 0x3003, 0x0067, + 0x3005, 0x0068, + 0x3006, 0x2728, + 0x3007, 0x1e17, + 0x3008, 0x0073, + 0x3010, 0x007d, + 0x3012, 0x2705, + 0x3013, 0x00bd, + 0x3014, 0x0071, + 0x3016, 0x007b, + 0x301d, 0x2706, + 0x3021, 0x2708, + 0x3041, 0x0164, + 0x309b, 0x2724, + 0x309d, 0x2729, + 0x30a1, 0x01b7, + 0x30fb, 0x0063, + 0x30fc, 0x2723, + 0x30fd, 0x2726, + 0x3105, 0x02bc, + 0x3220, 0x00f0, + 0x3231, 0x2721, + 0x32a3, 0x2711, + 0x338e, 0x2712, + 0x339c, 0x2714, + 0x33a1, 0x2717, + 0x33c4, 0x2718, + 0x33ce, 0x2719, + 0x33d1, 0x271a, + 0x33d5, 0x271c, + 0x4e00, 0x1042, + 0x4e01, 0x05e0, + 0x4e02, 0x2758, + 0x4e03, 0x0bfe, + 0x4e04, 0x2759, + 0x4e07, 0x0ea3, + 0x4e08, 0x116a, + 0x4e09, 0x0cd8, + 0x4e0a, 0x0d08, + 0x4e0b, 0x0f2f, + 0x4e0c, 0x1258, + 0x4e0d, 0x0482, + 0x4e0e, 0x10d0, + 0x4e0f, 0x275c, + 0x4e10, 0x125a, + 0x4e11, 0x0518, + 0x4e12, 0x275d, + 0x4e13, 0x1205, + 0x4e14, 0x0c4f, + 0x4e15, 0x125d, + 0x4e16, 0x0d57, + 0x4e17, 0x275e, + 0x4e18, 0x0c6d, + 0x4e19, 0x0464, + 0x4e1a, 0x103c, + 0x4e1b, 0x0557, + 0x4e1c, 0x05ea, + 0x4e1d, 0x0db4, + 0x4e1e, 0x125f, + 0x4e1f, 0x275f, + 0x4e22, 0x05e9, + 0x4e23, 0x2762, + 0x4e24, 0x0a06, + 0x4e25, 0x0ff8, + 0x4e26, 0x2763, + 0x4e27, 0x0cde, + 0x4e28, 0x1263, + 0x4e29, 0x2764, + 0x4e2a, 0x06f1, + 0x4e2b, 0x0fe7, + 0x4e2c, 0x169c, + 0x4e2d, 0x11cf, + 0x4e2e, 0x2765, + 0x4e30, 0x067e, + 0x4e31, 0x2767, + 0x4e32, 0x0531, + 0x4e33, 0x2768, + 0x4e34, 0x0a22, + 0x4e35, 0x2769, + 0x4e36, 0x1272, + 0x4e37, 0x276a, + 0x4e38, 0x0e99, + 0x4e39, 0x0585, + 0x4e3a, 0x0eb9, + 0x4e3b, 0x11f6, + 0x4e3c, 0x276b, + 0x4e3d, 0x09e1, + 0x4e3e, 0x0908, + 0x4e3f, 0x1265, + 0x4e40, 0x276c, + 0x4e43, 0x0b2e, + 0x4e44, 0x276f, + 0x4e45, 0x08f2, + 0x4e46, 0x2770, + 0x4e47, 0x1267, + 0x4e48, 0x0ab9, + 0x4e49, 0x106c, + 0x4e4a, 0x2771, + 0x4e4b, 0x11ad, + 0x4e4c, 0x0ee9, + 0x4e4d, 0x1148, + 0x4e4e, 0x07ac, + 0x4e4f, 0x0643, + 0x4e50, 0x09c1, + 0x4e51, 0x2772, + 0x4e52, 0x0bd8, + 0x4e53, 0x0b93, + 0x4e54, 0x0c44, + 0x4e55, 0x2773, + 0x4e56, 0x072d, + 0x4e57, 0x2774, + 0x4e58, 0x04f0, + 0x4e59, 0x1059, + 0x4e5a, 0x2775, + 0x4e5c, 0x1275, + 0x4e5d, 0x08f4, + 0x4e5e, 0x0c11, + 0x4e5f, 0x1039, + 0x4e60, 0x0f1d, + 0x4e61, 0x0f54, + 0x4e62, 0x2777, + 0x4e66, 0x0d80, + 0x4e67, 0x277b, + 0x4e69, 0x1276, + 0x4e6a, 0x277d, + 0x4e70, 0x0a99, + 0x4e71, 0x0a79, + 0x4e72, 0x2783, + 0x4e73, 0x0cc4, + 0x4e74, 0x2784, + 0x4e7e, 0x0c29, + 0x4e7f, 0x278e, + 0x4e82, 0x2059, + 0x4e83, 0x2791, + 0x4e86, 0x0a14, + 0x4e87, 0x2794, + 0x4e88, 0x10cd, + 0x4e89, 0x119a, + 0x4e8a, 0x2795, + 0x4e8b, 0x0d59, + 0x4e8c, 0x063d, + 0x4e8d, 0x1257, + 0x4e8e, 0x10bf, + 0x4e8f, 0x0984, + 0x4e90, 0x2796, + 0x4e91, 0x1109, + 0x4e92, 0x07ba, + 0x4e93, 0x1277, + 0x4e94, 0x0ef4, + 0x4e95, 0x08dd, + 0x4e96, 0x2797, + 0x4e98, 0x125e, + 0x4e99, 0x2799, + 0x4e9a, 0x0ff0, + 0x4e9b, 0x0f74, + 0x4e9c, 0x279a, + 0x4e9e, 0x21f1, + 0x4e9f, 0x1273, + 0x4ea0, 0x1303, + 0x4ea1, 0x0ea7, + 0x4ea2, 0x0947, + 0x4ea3, 0x279c, + 0x4ea4, 0x088c, + 0x4ea5, 0x075c, + 0x4ea6, 0x1067, + 0x4ea7, 0x04c1, + 0x4ea8, 0x0797, + 0x4ea9, 0x0b19, + 0x4eaa, 0x279d, + 0x4eab, 0x0f5a, + 0x4eac, 0x08d8, + 0x4ead, 0x0e55, + 0x4eae, 0x0a0a, + 0x4eaf, 0x279e, + 0x4eb2, 0x0c54, + 0x4eb3, 0x1305, + 0x4eb4, 0x27a1, + 0x4eb5, 0x1308, + 0x4eb6, 0x27a2, + 0x4eba, 0x0ca6, + 0x4ebb, 0x129f, + 0x4ebc, 0x27a6, + 0x4ebf, 0x1061, + 0x4ec0, 0x0d49, + 0x4ec1, 0x0ca5, + 0x4ec2, 0x12a2, + 0x4ec3, 0x12a0, + 0x4ec4, 0x127c, + 0x4ec5, 0x08c7, + 0x4ec6, 0x0bec, + 0x4ec7, 0x0515, + 0x4ec8, 0x27a9, + 0x4ec9, 0x12a1, + 0x4eca, 0x08c2, + 0x4ecb, 0x08ba, + 0x4ecc, 0x27aa, + 0x4ecd, 0x0caf, + 0x4ece, 0x0556, + 0x4ecf, 0x27ab, + 0x4ed1, 0x0a7f, + 0x4ed2, 0x27ad, + 0x4ed3, 0x049d, + 0x4ed4, 0x122d, + 0x4ed5, 0x0d62, + 0x4ed6, 0x0df0, + 0x4ed7, 0x116d, + 0x4ed8, 0x06b1, + 0x4ed9, 0x0f36, + 0x4eda, 0x27ae, + 0x4edd, 0x12ee, + 0x4ede, 0x12a6, + 0x4edf, 0x0c27, + 0x4ee0, 0x27b1, + 0x4ee1, 0x12a4, + 0x4ee2, 0x27b2, + 0x4ee3, 0x057d, + 0x4ee4, 0x0a37, + 0x4ee5, 0x105b, + 0x4ee6, 0x27b3, + 0x4ee8, 0x12a3, + 0x4ee9, 0x27b5, + 0x4eea, 0x104e, + 0x4eeb, 0x12a5, + 0x4eec, 0x0acc, + 0x4eed, 0x27b6, + 0x4ef0, 0x101f, + 0x4ef1, 0x27b9, + 0x4ef2, 0x11d8, + 0x4ef3, 0x12a8, + 0x4ef4, 0x27ba, + 0x4ef5, 0x12ab, + 0x4ef6, 0x0871, + 0x4ef7, 0x084e, + 0x4ef8, 0x27bb, + 0x4efb, 0x0ca9, + 0x4efc, 0x27be, + 0x4efd, 0x067a, + 0x4efe, 0x27bf, + 0x4eff, 0x065f, + 0x4f00, 0x27c0, + 0x4f01, 0x0c12, + 0x4f02, 0x27c1, + 0x4f09, 0x12ae, + 0x4f0a, 0x1048, + 0x4f0b, 0x27c8, + 0x4f0d, 0x0ef8, + 0x4f0e, 0x0832, + 0x4f0f, 0x0699, + 0x4f10, 0x0642, + 0x4f11, 0x0fa8, + 0x4f12, 0x27ca, + 0x4f17, 0x11d9, + 0x4f18, 0x10aa, + 0x4f19, 0x0804, + 0x4f1a, 0x07f6, + 0x4f1b, 0x12a7, + 0x4f1c, 0x27cf, + 0x4f1e, 0x0cda, + 0x4f1f, 0x0ebf, + 0x4f20, 0x052e, + 0x4f21, 0x27d1, + 0x4f22, 0x12a9, + 0x4f23, 0x27d2, + 0x4f24, 0x0d04, + 0x4f25, 0x12ac, + 0x4f26, 0x0a7e, + 0x4f27, 0x12ad, + 0x4f28, 0x27d3, + 0x4f2a, 0x0ec0, + 0x4f2b, 0x12af, + 0x4f2c, 0x27d5, + 0x4f2f, 0x0475, + 0x4f30, 0x0719, + 0x4f31, 0x27d8, + 0x4f32, 0x12b7, + 0x4f33, 0x27d9, + 0x4f34, 0x03f4, + 0x4f35, 0x27da, + 0x4f36, 0x0a2f, + 0x4f37, 0x27db, + 0x4f38, 0x0d25, + 0x4f39, 0x27dc, + 0x4f3a, 0x0dba, + 0x4f3b, 0x27dd, + 0x4f3c, 0x0dbb, + 0x4f3d, 0x12b8, + 0x4f3e, 0x27de, + 0x4f43, 0x05c9, + 0x4f44, 0x27e3, + 0x4f46, 0x058c, + 0x4f47, 0x27e5, + 0x4f4d, 0x0eca, + 0x4f4e, 0x05ae, + 0x4f4f, 0x11fe, + 0x4f50, 0x1251, + 0x4f51, 0x10b8, + 0x4f52, 0x27eb, + 0x4f53, 0x0e38, + 0x4f54, 0x27ec, + 0x4f55, 0x0785, + 0x4f56, 0x27ed, + 0x4f57, 0x12b6, + 0x4f58, 0x12f0, + 0x4f59, 0x10c5, + 0x4f5a, 0x12b3, + 0x4f5b, 0x068d, + 0x4f5c, 0x1254, + 0x4f5d, 0x12b4, + 0x4f5e, 0x12b0, + 0x4f5f, 0x12b5, + 0x4f60, 0x0b46, + 0x4f61, 0x27ee, + 0x4f63, 0x109b, + 0x4f64, 0x12aa, + 0x4f65, 0x12f1, + 0x4f66, 0x27f0, + 0x4f67, 0x12b1, + 0x4f68, 0x27f1, + 0x4f69, 0x0ba6, + 0x4f6a, 0x27f2, + 0x4f6c, 0x09bb, + 0x4f6d, 0x27f4, + 0x4f6f, 0x1019, + 0x4f70, 0x03e6, + 0x4f71, 0x27f6, + 0x4f73, 0x0844, + 0x4f74, 0x12ba, + 0x4f75, 0x27f8, + 0x4f76, 0x12b9, + 0x4f77, 0x27f9, + 0x4f7b, 0x12c0, + 0x4f7c, 0x12c2, + 0x4f7d, 0x27fd, + 0x4f7e, 0x12bf, + 0x4f7f, 0x0d50, + 0x4f80, 0x27fe, + 0x4f83, 0x12bd, + 0x4f84, 0x11b5, + 0x4f85, 0x2801, + 0x4f86, 0x1ff2, + 0x4f87, 0x2802, + 0x4f88, 0x0503, + 0x4f89, 0x12bc, + 0x4f8a, 0x2803, + 0x4f8b, 0x09e8, + 0x4f8c, 0x2804, + 0x4f8d, 0x0d63, + 0x4f8e, 0x2805, + 0x4f8f, 0x12be, + 0x4f90, 0x2806, + 0x4f91, 0x12bb, + 0x4f92, 0x2807, + 0x4f94, 0x12c4, + 0x4f95, 0x2809, + 0x4f96, 0x205d, + 0x4f97, 0x05f0, + 0x4f98, 0x280a, + 0x4f9b, 0x0702, + 0x4f9c, 0x280d, + 0x4f9d, 0x1047, + 0x4f9e, 0x280e, + 0x4fa0, 0x0f2d, + 0x4fa1, 0x2810, + 0x4fa3, 0x0a69, + 0x4fa4, 0x2812, + 0x4fa5, 0x0895, + 0x4fa6, 0x118d, + 0x4fa7, 0x04a7, + 0x4fa8, 0x0c45, + 0x4fa9, 0x0978, + 0x4faa, 0x12c1, + 0x4fab, 0x2813, + 0x4fac, 0x12c3, + 0x4fad, 0x2814, + 0x4fae, 0x0ef9, + 0x4faf, 0x07a5, + 0x4fb0, 0x2815, + 0x4fb5, 0x0c53, + 0x4fb6, 0x281a, + 0x4fbf, 0x044c, + 0x4fc0, 0x2823, + 0x4fc2, 0x269c, + 0x4fc3, 0x055c, + 0x4fc4, 0x062c, + 0x4fc5, 0x12c8, + 0x4fc6, 0x2825, + 0x4fca, 0x092e, + 0x4fcb, 0x2829, + 0x4fce, 0x12f2, + 0x4fcf, 0x0c4b, + 0x4fd0, 0x09e9, + 0x4fd1, 0x12cc, + 0x4fd2, 0x282c, + 0x4fd7, 0x0dcc, + 0x4fd8, 0x069a, + 0x4fd9, 0x2831, + 0x4fda, 0x12c9, + 0x4fdb, 0x2832, + 0x4fdc, 0x12cb, + 0x4fdd, 0x040c, + 0x4fde, 0x10c6, + 0x4fdf, 0x12cd, + 0x4fe0, 0x21b5, + 0x4fe1, 0x0f90, + 0x4fe2, 0x2833, + 0x4fe3, 0x12ca, + 0x4fe4, 0x2834, + 0x4fe6, 0x12c5, + 0x4fe7, 0x2836, + 0x4fe8, 0x12c6, + 0x4fe9, 0x09f2, + 0x4fea, 0x12c7, + 0x4feb, 0x2837, + 0x4fed, 0x0866, + 0x4fee, 0x0fa9, + 0x4fef, 0x06a4, + 0x4ff0, 0x2839, + 0x4ff1, 0x0912, + 0x4ff2, 0x283a, + 0x4ff3, 0x12d1, + 0x4ff4, 0x283b, + 0x4ff8, 0x12ce, + 0x4ff9, 0x283f, + 0x4ffa, 0x03be, + 0x4ffb, 0x2840, + 0x4ffe, 0x12d6, + 0x4fff, 0x2843, + 0x5000, 0x22cc, + 0x5001, 0x2844, + 0x5006, 0x2016, + 0x5007, 0x2849, + 0x5009, 0x1e62, + 0x500a, 0x284b, + 0x500b, 0x1f20, + 0x500c, 0x12d8, + 0x500d, 0x041f, + 0x500e, 0x284c, + 0x500f, 0x12d3, + 0x5010, 0x284d, + 0x5011, 0x207f, + 0x5012, 0x059a, + 0x5013, 0x284e, + 0x5014, 0x0922, + 0x5015, 0x284f, + 0x5018, 0x0e1b, + 0x5019, 0x07a9, + 0x501a, 0x1057, + 0x501b, 0x2852, + 0x501c, 0x12d7, + 0x501d, 0x2853, + 0x501f, 0x08b9, + 0x5020, 0x2855, + 0x5021, 0x04d0, + 0x5022, 0x2856, + 0x5025, 0x12d9, + 0x5026, 0x091a, + 0x5027, 0x2859, + 0x5028, 0x12da, + 0x5029, 0x12cf, + 0x502a, 0x0b42, + 0x502b, 0x205c, + 0x502c, 0x12d2, + 0x502d, 0x12d5, + 0x502e, 0x12d4, + 0x502f, 0x285a, + 0x503a, 0x114f, + 0x503b, 0x2865, + 0x503c, 0x11b4, + 0x503d, 0x2866, + 0x503e, 0x0c60, + 0x503f, 0x2867, + 0x5043, 0x12dc, + 0x5044, 0x286b, + 0x5047, 0x084c, + 0x5048, 0x12de, + 0x5049, 0x2194, + 0x504a, 0x286e, + 0x504c, 0x12d0, + 0x504d, 0x2870, + 0x504e, 0x12df, + 0x504f, 0x0bca, + 0x5050, 0x2871, + 0x5055, 0x12dd, + 0x5056, 0x2876, + 0x505a, 0x1253, + 0x505b, 0x287a, + 0x505c, 0x0e54, + 0x505d, 0x287b, + 0x5065, 0x0872, + 0x5066, 0x2883, + 0x506c, 0x12e0, + 0x506d, 0x2889, + 0x5074, 0x1e65, + 0x5075, 0x2281, + 0x5076, 0x0b7d, + 0x5077, 0x0e66, + 0x5078, 0x2890, + 0x507b, 0x12e1, + 0x507c, 0x2893, + 0x507e, 0x12db, + 0x507f, 0x04ca, + 0x5080, 0x098b, + 0x5081, 0x2895, + 0x5085, 0x06b0, + 0x5086, 0x2899, + 0x5088, 0x09e7, + 0x5089, 0x289b, + 0x508d, 0x0403, + 0x508e, 0x289f, + 0x5096, 0x22cd, + 0x5097, 0x28a7, + 0x5098, 0x210a, + 0x5099, 0x1e3e, + 0x509a, 0x28a8, + 0x50a2, 0x267f, + 0x50a3, 0x0579, + 0x50a4, 0x28b0, + 0x50a5, 0x12e2, + 0x50a6, 0x28b1, + 0x50a7, 0x12e3, + 0x50a8, 0x0525, + 0x50a9, 0x12e4, + 0x50aa, 0x28b2, + 0x50ac, 0x0562, + 0x50ad, 0x222e, + 0x50ae, 0x28b4, + 0x50b2, 0x03cc, + 0x50b3, 0x1e96, + 0x50b4, 0x22cb, + 0x50b5, 0x226c, + 0x50b6, 0x28b8, + 0x50b7, 0x2117, + 0x50b8, 0x28b9, + 0x50ba, 0x12e5, + 0x50bb, 0x0cee, + 0x50bc, 0x28bb, + 0x50be, 0x20e8, + 0x50bf, 0x28bd, + 0x50c2, 0x22d4, + 0x50c3, 0x28c0, + 0x50c5, 0x1fb9, + 0x50c6, 0x28c2, + 0x50c9, 0x22d8, + 0x50ca, 0x28c5, + 0x50cf, 0x0f5e, + 0x50d0, 0x28ca, + 0x50d1, 0x20df, + 0x50d2, 0x28cb, + 0x50d5, 0x20c2, + 0x50d6, 0x12e6, + 0x50d7, 0x28ce, + 0x50da, 0x0a0e, + 0x50db, 0x28d1, + 0x50de, 0x2195, + 0x50df, 0x28d4, + 0x50e5, 0x1fac, + 0x50e6, 0x12ea, + 0x50e7, 0x0ce7, + 0x50e8, 0x22d3, + 0x50e9, 0x28da, + 0x50ec, 0x12e9, + 0x50ed, 0x12e8, + 0x50ee, 0x12eb, + 0x50ef, 0x28dd, + 0x50f3, 0x0dd0, + 0x50f4, 0x28e1, + 0x50f5, 0x087a, + 0x50f6, 0x28e2, + 0x50f9, 0x1f81, + 0x50fa, 0x28e5, + 0x50fb, 0x0bc6, + 0x50fc, 0x28e6, + 0x5100, 0x2210, + 0x5101, 0x28ea, + 0x5102, 0x22cf, + 0x5103, 0x28eb, + 0x5104, 0x2213, + 0x5105, 0x28ec, + 0x5106, 0x12e7, + 0x5107, 0x12ec, + 0x5108, 0x1fe4, + 0x5109, 0x1f90, + 0x510a, 0x28ed, + 0x510b, 0x12ed, + 0x510c, 0x28ee, + 0x5110, 0x22d6, + 0x5111, 0x28f2, + 0x5112, 0x0cc0, + 0x5113, 0x28f3, + 0x5114, 0x22d0, + 0x5115, 0x22ce, + 0x5116, 0x28f4, + 0x5118, 0x2681, + 0x5119, 0x28f6, + 0x511f, 0x1e76, + 0x5120, 0x28fc, + 0x5121, 0x09c7, + 0x5122, 0x28fd, + 0x512a, 0x2231, + 0x512b, 0x2905, + 0x5132, 0x1e93, + 0x5133, 0x290c, + 0x5137, 0x22d2, + 0x5138, 0x2910, + 0x513a, 0x22d7, + 0x513b, 0x22d5, + 0x513c, 0x22d1, + 0x513d, 0x2912, + 0x513f, 0x0638, + 0x5140, 0x1259, + 0x5141, 0x110d, + 0x5142, 0x2914, + 0x5143, 0x10ed, + 0x5144, 0x0fa1, + 0x5145, 0x0509, + 0x5146, 0x1178, + 0x5147, 0x2915, + 0x5148, 0x0f35, + 0x5149, 0x073b, + 0x514a, 0x2916, + 0x514b, 0x0958, + 0x514c, 0x2917, + 0x514d, 0x0ae7, + 0x514e, 0x2918, + 0x5151, 0x0611, + 0x5152, 0x1ee5, + 0x5153, 0x291b, + 0x5154, 0x0e74, + 0x5155, 0x1302, + 0x5156, 0x1304, + 0x5157, 0x291c, + 0x515a, 0x0594, + 0x515b, 0x291f, + 0x515c, 0x05f4, + 0x515d, 0x2920, + 0x5162, 0x08d3, + 0x5163, 0x2925, + 0x5165, 0x0cc6, + 0x5166, 0x2927, + 0x5168, 0x0c86, + 0x5169, 0x2025, + 0x516a, 0x2929, + 0x516b, 0x03d6, + 0x516c, 0x0704, + 0x516d, 0x0a42, + 0x516e, 0x12f6, + 0x516f, 0x292a, + 0x5170, 0x09a7, + 0x5171, 0x070b, + 0x5172, 0x292b, + 0x5173, 0x0731, + 0x5174, 0x0f96, + 0x5175, 0x0461, + 0x5176, 0x0c03, + 0x5177, 0x090e, + 0x5178, 0x05c5, + 0x5179, 0x1225, + 0x517a, 0x292c, + 0x517b, 0x1021, + 0x517c, 0x0859, + 0x517d, 0x0d75, + 0x517e, 0x292d, + 0x5180, 0x0830, + 0x5181, 0x12fa, + 0x5182, 0x129d, + 0x5183, 0x292f, + 0x5185, 0x0b3d, + 0x5186, 0x2931, + 0x5188, 0x06cf, + 0x5189, 0x0c98, + 0x518a, 0x2933, + 0x518c, 0x04a8, + 0x518d, 0x111c, + 0x518e, 0x2935, + 0x5192, 0x0ab5, + 0x5193, 0x2939, + 0x5195, 0x0ae6, + 0x5196, 0x1314, + 0x5197, 0x0cba, + 0x5198, 0x293b, + 0x5199, 0x0f7f, + 0x519a, 0x293c, + 0x519b, 0x092b, + 0x519c, 0x0b6a, + 0x519d, 0x293d, + 0x51a0, 0x0733, + 0x51a1, 0x2940, + 0x51a2, 0x1315, + 0x51a3, 0x2941, + 0x51a4, 0x10ec, + 0x51a5, 0x1316, + 0x51a6, 0x2942, + 0x51ab, 0x130f, + 0x51ac, 0x05eb, + 0x51ad, 0x2947, + 0x51af, 0x0688, + 0x51b0, 0x0462, + 0x51b1, 0x1310, + 0x51b2, 0x050a, + 0x51b3, 0x0925, + 0x51b4, 0x2949, + 0x51b5, 0x0983, + 0x51b6, 0x1038, + 0x51b7, 0x09cf, + 0x51b8, 0x294a, + 0x51bb, 0x05f2, + 0x51bc, 0x1312, + 0x51bd, 0x1311, + 0x51be, 0x294d, + 0x51c0, 0x08ea, + 0x51c1, 0x294f, + 0x51c4, 0x0bff, + 0x51c5, 0x2952, + 0x51c6, 0x1219, + 0x51c7, 0x1313, + 0x51c8, 0x2953, + 0x51c9, 0x0a02, + 0x51ca, 0x2954, + 0x51cb, 0x05d3, + 0x51cc, 0x0a31, + 0x51cd, 0x1ecf, + 0x51ce, 0x2955, + 0x51cf, 0x0868, + 0x51d0, 0x2956, + 0x51d1, 0x0558, + 0x51d2, 0x2957, + 0x51db, 0x0a26, + 0x51dc, 0x2960, + 0x51dd, 0x0b60, + 0x51de, 0x2961, + 0x51e0, 0x082b, + 0x51e1, 0x064f, + 0x51e2, 0x2963, + 0x51e4, 0x068c, + 0x51e5, 0x2965, + 0x51eb, 0x1300, + 0x51ec, 0x296b, + 0x51ed, 0x0bdd, + 0x51ee, 0x296c, + 0x51ef, 0x093a, + 0x51f0, 0x07e0, + 0x51f1, 0x1fd9, + 0x51f2, 0x296d, + 0x51f3, 0x05ab, + 0x51f4, 0x296e, + 0x51f5, 0x1399, + 0x51f6, 0x0fa2, + 0x51f7, 0x296f, + 0x51f8, 0x0e6a, + 0x51f9, 0x03c7, + 0x51fa, 0x051b, + 0x51fb, 0x080c, + 0x51fc, 0x139a, + 0x51fd, 0x0766, + 0x51fe, 0x2970, + 0x51ff, 0x1127, + 0x5200, 0x0597, + 0x5201, 0x05d4, + 0x5202, 0x128c, + 0x5203, 0x0cab, + 0x5204, 0x2971, + 0x5206, 0x0673, + 0x5207, 0x0c4d, + 0x5208, 0x128d, + 0x5209, 0x2973, + 0x520a, 0x093c, + 0x520b, 0x2974, + 0x520d, 0x138b, + 0x520e, 0x128e, + 0x520f, 0x2976, + 0x5211, 0x0f97, + 0x5212, 0x07c3, + 0x5213, 0x2978, + 0x5216, 0x196e, + 0x5217, 0x0a19, + 0x5218, 0x0a3e, + 0x5219, 0x1135, + 0x521a, 0x06d0, + 0x521b, 0x0537, + 0x521c, 0x297b, + 0x521d, 0x051a, + 0x521e, 0x297c, + 0x5220, 0x0cf7, + 0x5221, 0x297e, + 0x5224, 0x0b91, + 0x5225, 0x2981, + 0x5228, 0x0b9a, + 0x5229, 0x09e6, + 0x522a, 0x2984, + 0x522b, 0x0459, + 0x522c, 0x2985, + 0x522d, 0x128f, + 0x522e, 0x0727, + 0x522f, 0x2986, + 0x5230, 0x059e, + 0x5231, 0x2987, + 0x5233, 0x1290, + 0x5234, 0x2989, + 0x5236, 0x11c5, + 0x5237, 0x0d97, + 0x5238, 0x0c8a, + 0x5239, 0x0ceb, + 0x523a, 0x054f, + 0x523b, 0x0959, + 0x523c, 0x298b, + 0x523d, 0x074d, + 0x523e, 0x298c, + 0x523f, 0x1291, + 0x5241, 0x0626, + 0x5242, 0x0834, + 0x5243, 0x0e3d, + 0x5244, 0x22c8, + 0x5245, 0x298d, + 0x5247, 0x2263, + 0x5248, 0x298f, + 0x524a, 0x0f64, + 0x524b, 0x2683, + 0x524c, 0x1293, + 0x524d, 0x0c2d, + 0x524e, 0x2991, + 0x5250, 0x0729, + 0x5251, 0x0874, + 0x5252, 0x2993, + 0x5254, 0x0e31, + 0x5255, 0x2995, + 0x5256, 0x0be9, + 0x5257, 0x2996, + 0x525b, 0x1f17, + 0x525c, 0x1296, + 0x525d, 0x299a, + 0x525e, 0x1294, + 0x525f, 0x299b, + 0x5261, 0x1295, + 0x5262, 0x299d, + 0x5265, 0x0409, + 0x5266, 0x29a0, + 0x5267, 0x0916, + 0x5268, 0x29a1, + 0x5269, 0x0d3a, + 0x526a, 0x0867, + 0x526b, 0x29a2, + 0x526e, 0x1f2b, + 0x526f, 0x06ac, + 0x5270, 0x29a5, + 0x5272, 0x06e9, + 0x5273, 0x29a7, + 0x5274, 0x22ca, + 0x5275, 0x1e99, + 0x5276, 0x29a8, + 0x527d, 0x1298, + 0x527e, 0x29af, + 0x527f, 0x089c, + 0x5280, 0x29b0, + 0x5281, 0x129a, + 0x5282, 0x1299, + 0x5283, 0x1f4f, + 0x5284, 0x29b1, + 0x5287, 0x1fcf, + 0x5288, 0x0bbd, + 0x5289, 0x2036, + 0x528a, 0x1f3a, + 0x528b, 0x29b4, + 0x528c, 0x22c9, + 0x528d, 0x1f99, + 0x528e, 0x29b5, + 0x5290, 0x129b, + 0x5291, 0x1f75, + 0x5292, 0x29b7, + 0x5293, 0x129c, + 0x5294, 0x29b8, + 0x529b, 0x09ef, + 0x529c, 0x29bf, + 0x529d, 0x0c8b, + 0x529e, 0x03f7, + 0x529f, 0x06ff, + 0x52a0, 0x0846, + 0x52a1, 0x0f00, + 0x52a2, 0x138d, + 0x52a3, 0x0a1c, + 0x52a4, 0x29c0, + 0x52a8, 0x05ee, + 0x52a9, 0x11f9, + 0x52aa, 0x0b6d, + 0x52ab, 0x08aa, + 0x52ac, 0x138e, + 0x52ae, 0x29c4, + 0x52b1, 0x09e3, + 0x52b2, 0x08d1, + 0x52b3, 0x09b8, + 0x52b4, 0x29c7, + 0x52be, 0x1390, + 0x52bf, 0x0d5d, + 0x52c0, 0x29d1, + 0x52c1, 0x1fbe, + 0x52c2, 0x29d2, + 0x52c3, 0x0471, + 0x52c4, 0x29d3, + 0x52c7, 0x10a7, + 0x52c8, 0x29d6, + 0x52c9, 0x0ae8, + 0x52ca, 0x29d7, + 0x52cb, 0x0fd4, + 0x52cc, 0x29d8, + 0x52d0, 0x1392, + 0x52d1, 0x29dc, + 0x52d2, 0x09c0, + 0x52d3, 0x29dd, + 0x52d5, 0x1ecd, + 0x52d6, 0x1393, + 0x52d7, 0x29df, + 0x52d8, 0x093e, + 0x52d9, 0x21a9, + 0x52da, 0x29e0, + 0x52db, 0x21e6, + 0x52dc, 0x29e1, + 0x52dd, 0x2127, + 0x52de, 0x2003, + 0x52df, 0x0b1f, + 0x52e0, 0x29e2, + 0x52e2, 0x2132, + 0x52e3, 0x29e4, + 0x52e4, 0x0c57, + 0x52e5, 0x29e5, + 0x52f0, 0x1394, + 0x52f1, 0x2323, + 0x52f2, 0x29f0, + 0x52f5, 0x2011, + 0x52f6, 0x29f3, + 0x52f8, 0x20f5, + 0x52f9, 0x12fc, + 0x52fa, 0x0d10, + 0x52fb, 0x29f5, + 0x52fe, 0x070d, + 0x52ff, 0x0eff, + 0x5300, 0x110b, + 0x5301, 0x29f8, + 0x5305, 0x0407, + 0x5306, 0x0555, + 0x5307, 0x29fc, + 0x5308, 0x0fa4, + 0x5309, 0x29fd, + 0x530d, 0x12fd, + 0x530e, 0x2a01, + 0x530f, 0x14b5, + 0x5310, 0x12ff, + 0x5311, 0x2a02, + 0x5315, 0x1266, + 0x5316, 0x07c4, + 0x5317, 0x041a, + 0x5318, 0x2a06, + 0x5319, 0x04fc, + 0x531a, 0x1284, + 0x531b, 0x2a07, + 0x531d, 0x1114, + 0x531e, 0x2a09, + 0x5320, 0x0884, + 0x5321, 0x097c, + 0x5322, 0x2a0b, + 0x5323, 0x0f28, + 0x5324, 0x2a0c, + 0x5326, 0x1286, + 0x5327, 0x2a0e, + 0x532a, 0x0668, + 0x532b, 0x2a11, + 0x532d, 0x22c5, + 0x532e, 0x1287, + 0x532f, 0x1f5e, + 0x5330, 0x2a13, + 0x5331, 0x22c6, + 0x5332, 0x2a14, + 0x5339, 0x0bc4, + 0x533a, 0x0c75, + 0x533b, 0x1044, + 0x533c, 0x2a1b, + 0x533e, 0x1288, + 0x533f, 0x0b47, + 0x5340, 0x20ef, + 0x5341, 0x0d45, + 0x5342, 0x2a1d, + 0x5343, 0x0c24, + 0x5344, 0x2a1e, + 0x5345, 0x125c, + 0x5346, 0x2a1f, + 0x5347, 0x0d36, + 0x5348, 0x0ef6, + 0x5349, 0x07f1, + 0x534a, 0x03f6, + 0x534b, 0x2a20, + 0x534e, 0x07bf, + 0x534f, 0x0f78, + 0x5350, 0x2a23, + 0x5351, 0x0419, + 0x5352, 0x1241, + 0x5353, 0x121c, + 0x5354, 0x21d0, + 0x5355, 0x0586, + 0x5356, 0x0a9b, + 0x5357, 0x0b32, + 0x5358, 0x2a24, + 0x535a, 0x0470, + 0x535b, 0x2a26, + 0x535c, 0x047e, + 0x535d, 0x2a27, + 0x535e, 0x044e, + 0x535f, 0x14fa, + 0x5360, 0x115d, + 0x5361, 0x0935, + 0x5362, 0x0a53, + 0x5363, 0x128b, + 0x5364, 0x0a58, + 0x5365, 0x2a28, + 0x5366, 0x128a, + 0x5367, 0x0ee3, + 0x5368, 0x2a29, + 0x5369, 0x1352, + 0x536a, 0x2a2a, + 0x536b, 0x0ecf, + 0x536c, 0x2a2b, + 0x536e, 0x126a, + 0x536f, 0x0ab3, + 0x5370, 0x1086, + 0x5371, 0x0eb2, + 0x5372, 0x2a2d, + 0x5373, 0x0827, + 0x5374, 0x0c8f, + 0x5375, 0x0a78, + 0x5376, 0x2a2e, + 0x5377, 0x091c, + 0x5378, 0x0f81, + 0x5379, 0x2a2f, + 0x537a, 0x1353, + 0x537b, 0x2a30, + 0x537f, 0x0c61, + 0x5380, 0x2a34, + 0x5382, 0x04cc, + 0x5383, 0x2a36, + 0x5384, 0x0631, + 0x5385, 0x0e4f, + 0x5386, 0x09e5, + 0x5387, 0x2a37, + 0x5389, 0x09e2, + 0x538a, 0x2a39, + 0x538b, 0x0fe2, + 0x538c, 0x100a, + 0x538d, 0x127d, + 0x538e, 0x2a3a, + 0x5395, 0x04a5, + 0x5396, 0x2a41, + 0x5398, 0x09d0, + 0x5399, 0x22c1, + 0x539a, 0x07a8, + 0x539b, 0x2a43, + 0x539d, 0x127e, + 0x539e, 0x2a45, + 0x539f, 0x10f0, + 0x53a0, 0x1e64, + 0x53a1, 0x2a46, + 0x53a2, 0x0f4e, + 0x53a3, 0x127f, + 0x53a4, 0x2a47, + 0x53a5, 0x1280, + 0x53a6, 0x0f30, + 0x53a7, 0x2a48, + 0x53a8, 0x051d, + 0x53a9, 0x08f6, + 0x53aa, 0x2a49, + 0x53ad, 0x21f9, + 0x53ae, 0x1281, + 0x53af, 0x2a4c, + 0x53b2, 0x2010, + 0x53b3, 0x2a4f, + 0x53b4, 0x22c2, + 0x53b5, 0x2a50, + 0x53b6, 0x139c, + 0x53b7, 0x2a51, + 0x53bb, 0x0c80, + 0x53bc, 0x2a55, + 0x53bf, 0x0f45, + 0x53c0, 0x2a58, + 0x53c1, 0x0cd9, + 0x53c2, 0x0495, + 0x53c3, 0x1e5a, + 0x53c4, 0x2a59, + 0x53c8, 0x10bb, + 0x53c9, 0x04ad, + 0x53ca, 0x0823, + 0x53cb, 0x10b6, + 0x53cc, 0x0da0, + 0x53cd, 0x0651, + 0x53ce, 0x2a5d, + 0x53d1, 0x063f, + 0x53d2, 0x2a60, + 0x53d4, 0x0d7c, + 0x53d5, 0x2a62, + 0x53d6, 0x0c7c, + 0x53d7, 0x0d73, + 0x53d8, 0x044d, + 0x53d9, 0x0fbb, + 0x53da, 0x2a63, + 0x53db, 0x0b92, + 0x53dc, 0x2a64, + 0x53df, 0x1395, + 0x53e0, 0x05df, + 0x53e1, 0x2a67, + 0x53e2, 0x1ea2, + 0x53e3, 0x0967, + 0x53e4, 0x071e, + 0x53e5, 0x0913, + 0x53e6, 0x0a36, + 0x53e7, 0x2a68, + 0x53e8, 0x14fe, + 0x53e9, 0x14fd, + 0x53ea, 0x11ba, + 0x53eb, 0x08a1, + 0x53ec, 0x117a, + 0x53ed, 0x03d3, + 0x53ee, 0x05e2, + 0x53ef, 0x0956, + 0x53f0, 0x0dfb, + 0x53f1, 0x14fb, + 0x53f2, 0x0d4e, + 0x53f3, 0x10b7, + 0x53f4, 0x2a69, + 0x53f5, 0x1285, + 0x53f6, 0x103d, + 0x53f7, 0x077c, + 0x53f8, 0x0db3, + 0x53f9, 0x0e11, + 0x53fa, 0x2a6a, + 0x53fb, 0x14ff, + 0x53fc, 0x05d1, + 0x53fd, 0x14fc, + 0x53fe, 0x2a6b, + 0x5400, 0x2a6d, + 0x5401, 0x10da, + 0x5402, 0x2a6e, + 0x5403, 0x04f9, + 0x5404, 0x06f2, + 0x5405, 0x2a6f, + 0x5406, 0x1502, + 0x5407, 0x2a70, + 0x5408, 0x0786, + 0x5409, 0x081d, + 0x540a, 0x05d6, + 0x540b, 0x2a71, + 0x540c, 0x0e5d, + 0x540d, 0x0b00, + 0x540e, 0x07aa, + 0x540f, 0x09df, + 0x5410, 0x0e73, + 0x5411, 0x0f5f, + 0x5412, 0x1500, + 0x5413, 0x0f32, + 0x5414, 0x2a72, + 0x5415, 0x0a67, + 0x5416, 0x1501, + 0x5417, 0x0a97, + 0x5418, 0x2a73, + 0x541b, 0x092c, + 0x541c, 0x2a76, + 0x541d, 0x0a28, + 0x541e, 0x0e7d, + 0x541f, 0x107e, + 0x5420, 0x066a, + 0x5421, 0x1509, + 0x5422, 0x2a77, + 0x5423, 0x150c, + 0x5424, 0x2a78, + 0x5426, 0x068e, + 0x5427, 0x03d4, + 0x5428, 0x0615, + 0x5429, 0x0671, + 0x542a, 0x2a7a, + 0x542b, 0x0763, + 0x542c, 0x0e50, + 0x542d, 0x0961, + 0x542e, 0x0da6, + 0x542f, 0x0c13, + 0x5430, 0x2a7b, + 0x5431, 0x11a7, + 0x5432, 0x150d, + 0x5433, 0x2a7c, + 0x5434, 0x0ef1, + 0x5435, 0x04d8, + 0x5436, 0x2a7d, + 0x5438, 0x0f0b, + 0x5439, 0x0538, + 0x543a, 0x2a7f, + 0x543b, 0x0ed6, + 0x543c, 0x07a7, + 0x543d, 0x2a80, + 0x543e, 0x0ef0, + 0x543f, 0x2a81, + 0x5440, 0x0fe6, + 0x5441, 0x2a82, + 0x5443, 0x1508, + 0x5444, 0x2a84, + 0x5446, 0x0577, + 0x5447, 0x2a86, + 0x5448, 0x04ef, + 0x5449, 0x2a87, + 0x544a, 0x06e1, + 0x544b, 0x1503, + 0x544c, 0x2a88, + 0x5450, 0x0b28, + 0x5451, 0x2a8c, + 0x5452, 0x1504, + 0x5455, 0x0b7c, + 0x5456, 0x1507, + 0x5457, 0x150a, + 0x5458, 0x10f4, + 0x5459, 0x150b, + 0x545a, 0x2a8d, + 0x545b, 0x0c37, + 0x545c, 0x0ee7, + 0x545d, 0x2a8e, + 0x5462, 0x0b3b, + 0x5463, 0x2a93, + 0x5464, 0x1512, + 0x5465, 0x2a94, + 0x5466, 0x1517, + 0x5467, 0x2a95, + 0x5468, 0x11db, + 0x5469, 0x2a96, + 0x5471, 0x1511, + 0x5472, 0x1522, + 0x5473, 0x0ec5, + 0x5474, 0x2a9e, + 0x5475, 0x077e, + 0x5476, 0x1516, + 0x5477, 0x1510, + 0x5478, 0x0b9f, + 0x5479, 0x2a9f, + 0x547b, 0x0d24, + 0x547c, 0x07ab, + 0x547d, 0x0b01, + 0x547e, 0x2aa1, + 0x5480, 0x0906, + 0x5481, 0x2aa3, + 0x5482, 0x150e, + 0x5483, 0x2aa4, + 0x5484, 0x1515, + 0x5485, 0x2aa5, + 0x5486, 0x0b99, + 0x5487, 0x2aa6, + 0x548b, 0x1147, + 0x548c, 0x0784, + 0x548d, 0x2aaa, + 0x548e, 0x08fb, + 0x548f, 0x10a2, + 0x5490, 0x06bb, + 0x5491, 0x2aab, + 0x5492, 0x11e3, + 0x5493, 0x2aac, + 0x5494, 0x150f, + 0x5495, 0x0717, + 0x5496, 0x0934, + 0x5497, 0x2aad, + 0x5499, 0x0a45, + 0x549a, 0x1513, + 0x549c, 0x2aaf, + 0x549d, 0x1518, + 0x549e, 0x2ab0, + 0x54a3, 0x1523, + 0x54a4, 0x152d, + 0x54a5, 0x2ab5, + 0x54a6, 0x151f, + 0x54a7, 0x151e, + 0x54a8, 0x1226, + 0x54a9, 0x152b, + 0x54ab, 0x1767, + 0x54ac, 0x102e, + 0x54ad, 0x151a, + 0x54ae, 0x2ab6, + 0x54af, 0x0936, + 0x54b0, 0x2ab7, + 0x54b1, 0x111e, + 0x54b2, 0x2ab8, + 0x54b3, 0x0955, + 0x54b4, 0x151c, + 0x54b5, 0x2ab9, + 0x54b8, 0x0f39, + 0x54b9, 0x2abc, + 0x54bb, 0x1525, + 0x54bc, 0x236d, + 0x54bd, 0x0ff3, + 0x54be, 0x2abe, + 0x54bf, 0x1526, + 0x54c0, 0x03b2, + 0x54c1, 0x0bd6, + 0x54c2, 0x151b, + 0x54c3, 0x2abf, + 0x54c4, 0x079c, + 0x54c5, 0x2ac0, + 0x54c6, 0x061e, + 0x54c7, 0x0e8c, + 0x54c8, 0x0757, + 0x54c9, 0x1118, + 0x54ca, 0x2ac1, + 0x54cc, 0x1527, + 0x54cd, 0x0f59, + 0x54ce, 0x03b0, + 0x54cf, 0x152f, + 0x54d0, 0x1519, + 0x54d1, 0x0fef, + 0x54d2, 0x151d, + 0x54d3, 0x1520, + 0x54d5, 0x1524, + 0x54d6, 0x2ac3, + 0x54d7, 0x07be, + 0x54d8, 0x2ac4, + 0x54d9, 0x1528, + 0x54db, 0x2ac5, + 0x54dc, 0x152a, + 0x54dd, 0x152e, + 0x54de, 0x1530, + 0x54df, 0x1099, + 0x54e0, 0x2ac6, + 0x54e1, 0x2247, + 0x54e2, 0x2ac7, + 0x54e5, 0x06e2, + 0x54e6, 0x0b77, + 0x54e7, 0x1532, + 0x54e8, 0x0d13, + 0x54e9, 0x09f1, + 0x54ea, 0x0b27, + 0x54eb, 0x2aca, + 0x54ed, 0x096b, + 0x54ee, 0x0f65, + 0x54ef, 0x2acc, + 0x54f2, 0x117d, + 0x54f3, 0x1536, + 0x54f4, 0x2acf, + 0x54fa, 0x047f, + 0x54fb, 0x2ad5, + 0x54fc, 0x0796, + 0x54fd, 0x1534, + 0x54fe, 0x2ad6, + 0x54ff, 0x1391, + 0x5500, 0x2ad7, + 0x5501, 0x100d, + 0x5502, 0x2ad8, + 0x5504, 0x236c, + 0x5505, 0x2ada, + 0x5506, 0x0de9, + 0x5507, 0x0540, + 0x5508, 0x2adb, + 0x5509, 0x03b1, + 0x550a, 0x2adc, + 0x550f, 0x1539, + 0x5510, 0x0e19, + 0x5511, 0x153a, + 0x5512, 0x2ae1, + 0x5514, 0x1535, + 0x5515, 0x2ae3, + 0x551b, 0x1531, + 0x551c, 0x2ae9, + 0x5520, 0x1533, + 0x5521, 0x2aed, + 0x5522, 0x1537, + 0x5524, 0x07d2, + 0x5525, 0x2aee, + 0x5527, 0x153b, + 0x5528, 0x2af0, + 0x552a, 0x153c, + 0x552b, 0x2af2, + 0x552c, 0x07b8, + 0x552d, 0x2af3, + 0x552e, 0x0d72, + 0x552f, 0x0eb7, + 0x5530, 0x154d, + 0x5531, 0x04cf, + 0x5532, 0x2af4, + 0x5533, 0x154c, + 0x5534, 0x2af5, + 0x5537, 0x1547, + 0x5538, 0x2af8, + 0x553c, 0x1546, + 0x553d, 0x2afc, + 0x553e, 0x0e8a, + 0x553f, 0x1544, + 0x5540, 0x2afd, + 0x5541, 0x1542, + 0x5542, 0x2afe, + 0x5543, 0x095d, + 0x5544, 0x1221, + 0x5545, 0x2aff, + 0x5546, 0x0d05, + 0x5547, 0x2b00, + 0x5549, 0x1540, + 0x554a, 0x03ac, + 0x554b, 0x2b02, + 0x554f, 0x219c, + 0x5550, 0x1545, + 0x5551, 0x2b06, + 0x5553, 0x20c9, + 0x5554, 0x2b08, + 0x5555, 0x1543, + 0x5556, 0x1548, + 0x5557, 0x2b09, + 0x555c, 0x154e, + 0x555d, 0x2b0e, + 0x555e, 0x21f0, + 0x555f, 0x2b0f, + 0x5561, 0x0665, + 0x5562, 0x2b11, + 0x5564, 0x0bc0, + 0x5565, 0x0cef, + 0x5566, 0x099d, + 0x5567, 0x153d, + 0x5568, 0x2b13, + 0x556a, 0x0b7f, + 0x556b, 0x2b15, + 0x556c, 0x127a, + 0x556d, 0x1541, + 0x556e, 0x0b59, + 0x556f, 0x2b16, + 0x5575, 0x1549, + 0x5578, 0x0f70, + 0x5579, 0x2b1c, + 0x557b, 0x155a, + 0x557c, 0x0e37, + 0x557d, 0x2b1e, + 0x557e, 0x1557, + 0x557f, 0x2b1f, + 0x5580, 0x0933, + 0x5581, 0x1555, + 0x5582, 0x0ec8, + 0x5583, 0x1551, + 0x5584, 0x0cff, + 0x5585, 0x2b20, + 0x5587, 0x0999, + 0x5588, 0x1554, + 0x5589, 0x07a4, + 0x558a, 0x0767, + 0x558b, 0x154f, + 0x558c, 0x2b22, + 0x558f, 0x153e, + 0x5590, 0x2b25, + 0x5591, 0x1559, + 0x5592, 0x2b26, + 0x5594, 0x155e, + 0x5595, 0x2b28, + 0x5598, 0x0530, + 0x5599, 0x155f, + 0x559a, 0x2b2b, + 0x559c, 0x0f1f, + 0x559d, 0x077f, + 0x559e, 0x2b2d, + 0x559f, 0x1556, + 0x55a0, 0x2b2e, + 0x55a7, 0x0fc5, + 0x55a8, 0x2b35, + 0x55aa, 0x210b, + 0x55ab, 0x2b37, + 0x55ac, 0x20de, + 0x55ad, 0x2b38, + 0x55ae, 0x1eaa, + 0x55af, 0x2b39, + 0x55b1, 0x1552, + 0x55b2, 0x222c, + 0x55b3, 0x113e, + 0x55b4, 0x2b3b, + 0x55b5, 0x153f, + 0x55b6, 0x2b3c, + 0x55b7, 0x0ba8, + 0x55b8, 0x2b3d, + 0x55b9, 0x1553, + 0x55ba, 0x2b3e, + 0x55bb, 0x10dc, + 0x55bc, 0x2b3f, + 0x55bd, 0x155c, + 0x55bf, 0x2b40, + 0x55c4, 0x156a, + 0x55c5, 0x0fac, + 0x55c6, 0x20d8, + 0x55c7, 0x22c0, + 0x55c8, 0x2b45, + 0x55c9, 0x1562, + 0x55ca, 0x2b46, + 0x55cc, 0x156f, + 0x55ce, 0x206f, + 0x55cf, 0x2b48, + 0x55d1, 0x1564, + 0x55d2, 0x1550, + 0x55d3, 0x0cdd, + 0x55d4, 0x1567, + 0x55d5, 0x2b4a, + 0x55d6, 0x1558, + 0x55d7, 0x2b4b, + 0x55da, 0x21a1, + 0x55db, 0x2b4e, + 0x55dc, 0x0d5f, + 0x55dd, 0x1569, + 0x55de, 0x2b4f, + 0x55df, 0x155b, + 0x55e0, 0x2b50, + 0x55e1, 0x0eda, + 0x55e2, 0x2b51, + 0x55e3, 0x0db8, + 0x55e4, 0x1573, + 0x55e5, 0x156c, + 0x55e6, 0x1568, + 0x55e7, 0x2b52, + 0x55e8, 0x1571, + 0x55e9, 0x2379, + 0x55ea, 0x1560, + 0x55eb, 0x1565, + 0x55ed, 0x2b53, + 0x55ef, 0x156b, + 0x55f0, 0x2b55, + 0x55f2, 0x156d, + 0x55f4, 0x2b57, + 0x55f5, 0x1572, + 0x55f6, 0x2372, + 0x55f7, 0x1561, + 0x55f8, 0x2b58, + 0x55fd, 0x0dc9, + 0x55fe, 0x157b, + 0x55ff, 0x2b5d, + 0x5600, 0x157c, + 0x5601, 0x1578, + 0x5602, 0x2b5e, + 0x5606, 0x216a, + 0x5607, 0x2b62, + 0x5608, 0x1576, + 0x5609, 0x0841, + 0x560a, 0x2b63, + 0x560c, 0x1577, + 0x560d, 0x237c, + 0x560e, 0x06bd, + 0x560f, 0x127b, + 0x5610, 0x2b65, + 0x5614, 0x20b0, + 0x5615, 0x2b69, + 0x5616, 0x237a, + 0x5617, 0x1e74, + 0x5618, 0x0fb5, + 0x5619, 0x2b6a, + 0x561b, 0x0a96, + 0x561c, 0x2377, + 0x561d, 0x2b6c, + 0x561e, 0x1575, + 0x561f, 0x1563, + 0x5620, 0x2b6d, + 0x5623, 0x157a, + 0x5624, 0x1579, + 0x5625, 0x2b70, + 0x5627, 0x157d, + 0x5628, 0x2b72, + 0x5629, 0x1f4c, + 0x562a, 0x2b73, + 0x562c, 0x1582, + 0x562d, 0x157e, + 0x562e, 0x2378, + 0x562f, 0x21cf, + 0x5630, 0x2368, + 0x5631, 0x11f5, + 0x5632, 0x04d5, + 0x5633, 0x2b75, + 0x5634, 0x1249, + 0x5635, 0x2371, + 0x5636, 0x0db0, + 0x5637, 0x2b76, + 0x5638, 0x2369, + 0x5639, 0x1580, + 0x563a, 0x2b77, + 0x563b, 0x0f0a, + 0x563c, 0x2b78, + 0x563f, 0x0790, + 0x5640, 0x2b7b, + 0x5641, 0x2674, + 0x5642, 0x2b7c, + 0x564c, 0x1587, + 0x564d, 0x1583, + 0x564e, 0x1034, + 0x564f, 0x2b86, + 0x5654, 0x1588, + 0x5655, 0x2b8b, + 0x5657, 0x1581, + 0x5658, 0x157f, + 0x5659, 0x1585, + 0x565a, 0x2b8d, + 0x565c, 0x1586, + 0x565d, 0x236f, + 0x565e, 0x2b8f, + 0x5660, 0x2370, + 0x5661, 0x2b91, + 0x5662, 0x1584, + 0x5663, 0x2b92, + 0x5664, 0x158a, + 0x5665, 0x2376, + 0x5666, 0x2373, + 0x5667, 0x2b93, + 0x5668, 0x0c16, + 0x5669, 0x1262, + 0x566a, 0x112e, + 0x566b, 0x158c, + 0x566c, 0x0d60, + 0x566d, 0x2b94, + 0x566f, 0x237f, + 0x5670, 0x2b96, + 0x5671, 0x158b, + 0x5672, 0x2374, + 0x5673, 0x2b97, + 0x5674, 0x20b5, + 0x5675, 0x2b98, + 0x5676, 0x06bc, + 0x5677, 0x2b99, + 0x5678, 0x1edb, + 0x5679, 0x2672, + 0x567a, 0x2b9a, + 0x567b, 0x158d, + 0x567d, 0x2b9b, + 0x5680, 0x236e, + 0x5681, 0x2b9e, + 0x5685, 0x158f, + 0x5686, 0x1589, + 0x5687, 0x21b7, + 0x5688, 0x2ba2, + 0x568c, 0x2375, + 0x568d, 0x2ba6, + 0x568e, 0x0776, + 0x568f, 0x0e3a, + 0x5690, 0x2ba7, + 0x5693, 0x1590, + 0x5694, 0x2baa, + 0x5695, 0x2382, + 0x5696, 0x2bab, + 0x5699, 0x209e, + 0x569a, 0x2bae, + 0x56a3, 0x0f66, + 0x56a4, 0x2bb7, + 0x56a6, 0x236b, + 0x56a7, 0x2bb9, + 0x56a8, 0x2039, + 0x56a9, 0x2bba, + 0x56ae, 0x269f, + 0x56af, 0x1591, + 0x56b0, 0x2bbf, + 0x56b3, 0x237d, + 0x56b4, 0x21f5, + 0x56b5, 0x2bc2, + 0x56b6, 0x2381, + 0x56b7, 0x0c9d, + 0x56b8, 0x2bc3, + 0x56bc, 0x0891, + 0x56bd, 0x2bc7, + 0x56c0, 0x237b, + 0x56c1, 0x237e, + 0x56c2, 0x21cc, + 0x56c3, 0x2bca, + 0x56c5, 0x22db, + 0x56c6, 0x2bcc, + 0x56c8, 0x236a, + 0x56c9, 0x2689, + 0x56ca, 0x0b35, + 0x56cb, 0x2bce, + 0x56cc, 0x2697, + 0x56cd, 0x2bcf, + 0x56d1, 0x22a1, + 0x56d2, 0x2bd3, + 0x56d4, 0x1592, + 0x56d5, 0x2bd5, + 0x56d7, 0x1593, + 0x56d8, 0x2bd7, + 0x56da, 0x0c71, + 0x56db, 0x0db9, + 0x56dc, 0x2bd9, + 0x56dd, 0x1594, + 0x56de, 0x07ed, + 0x56df, 0x126c, + 0x56e0, 0x1079, + 0x56e1, 0x1595, + 0x56e2, 0x0e76, + 0x56e3, 0x2bda, + 0x56e4, 0x0619, + 0x56e5, 0x2bdb, + 0x56eb, 0x1597, + 0x56ec, 0x2be1, + 0x56ed, 0x10f3, + 0x56ee, 0x2be2, + 0x56f0, 0x0992, + 0x56f1, 0x0554, + 0x56f2, 0x2be4, + 0x56f4, 0x0eb6, + 0x56f5, 0x1596, + 0x56f6, 0x2be6, + 0x56f9, 0x1598, + 0x56fa, 0x0725, + 0x56fb, 0x2be9, + 0x56fd, 0x0753, + 0x56fe, 0x0e6d, + 0x56ff, 0x1599, + 0x5700, 0x2beb, + 0x5703, 0x0bf3, + 0x5704, 0x159a, + 0x5705, 0x2bee, + 0x5706, 0x10f5, + 0x5707, 0x2383, + 0x5708, 0x0c81, + 0x5709, 0x159c, + 0x570a, 0x159b, + 0x570b, 0x1f3d, + 0x570c, 0x2bef, + 0x570d, 0x218f, + 0x570e, 0x2bf0, + 0x5712, 0x2246, + 0x5713, 0x2248, + 0x5714, 0x2bf4, + 0x5716, 0x217e, + 0x5717, 0x2bf6, + 0x5718, 0x2180, + 0x5719, 0x2bf7, + 0x571c, 0x159d, + 0x571d, 0x2bfa, + 0x571f, 0x0e72, + 0x5720, 0x2bfc, + 0x5723, 0x0d3c, + 0x5724, 0x2bff, + 0x5728, 0x111d, + 0x5729, 0x13a7, + 0x572a, 0x13a9, + 0x572b, 0x2c03, + 0x572c, 0x13a8, + 0x572d, 0x0740, + 0x572e, 0x13ac, + 0x5730, 0x05b9, + 0x5731, 0x2c04, + 0x5733, 0x13aa, + 0x5734, 0x2c06, + 0x5739, 0x13ab, + 0x573a, 0x04c6, + 0x573b, 0x13af, + 0x573c, 0x2c0b, + 0x573e, 0x080d, + 0x573f, 0x2c0d, + 0x5740, 0x11b6, + 0x5741, 0x2c0e, + 0x5742, 0x13b0, + 0x5743, 0x2c0f, + 0x5747, 0x0928, + 0x5748, 0x2c13, + 0x574a, 0x0658, + 0x574b, 0x2c15, + 0x574c, 0x13a0, + 0x574d, 0x0e01, + 0x574e, 0x093f, + 0x574f, 0x07ca, + 0x5750, 0x1255, + 0x5751, 0x0960, + 0x5752, 0x2c16, + 0x5757, 0x0976, + 0x5758, 0x2c1b, + 0x575a, 0x0854, + 0x575b, 0x0e06, + 0x575c, 0x13ae, + 0x575d, 0x03de, + 0x575e, 0x0efa, + 0x575f, 0x0675, + 0x5760, 0x1216, + 0x5761, 0x0be1, + 0x5762, 0x2c1d, + 0x5764, 0x098f, + 0x5765, 0x2c1f, + 0x5766, 0x0e0c, + 0x5767, 0x2c20, + 0x5768, 0x13b7, + 0x5769, 0x13b1, + 0x576a, 0x0bd9, + 0x576b, 0x13b3, + 0x576c, 0x2c21, + 0x576d, 0x13b8, + 0x576e, 0x2c22, + 0x576f, 0x0bb8, + 0x5770, 0x2c23, + 0x5773, 0x13ba, + 0x5774, 0x2c26, + 0x5776, 0x13b9, + 0x5777, 0x094d, + 0x5778, 0x2c28, + 0x577b, 0x13b6, + 0x577c, 0x13b5, + 0x577d, 0x2c2b, + 0x5782, 0x053c, + 0x5783, 0x0997, + 0x5784, 0x0a49, + 0x5785, 0x13b2, + 0x5786, 0x13b4, + 0x5787, 0x2c30, + 0x578b, 0x0f98, + 0x578c, 0x13bd, + 0x578d, 0x2c34, + 0x5792, 0x09c8, + 0x5793, 0x13c2, + 0x5794, 0x2c39, + 0x579b, 0x0621, + 0x579c, 0x2c40, + 0x57a0, 0x13c3, + 0x57a1, 0x13a2, + 0x57a2, 0x0711, + 0x57a3, 0x10ee, + 0x57a4, 0x13bc, + 0x57a5, 0x2c44, + 0x57a6, 0x095e, + 0x57a7, 0x13c0, + 0x57a8, 0x2c45, + 0x57a9, 0x13a1, + 0x57aa, 0x2c46, + 0x57ab, 0x05c7, + 0x57ac, 0x2c47, + 0x57ad, 0x13bb, + 0x57ae, 0x0972, + 0x57af, 0x2c48, + 0x57b2, 0x13be, + 0x57b3, 0x2c4b, + 0x57b4, 0x13c1, + 0x57b5, 0x2c4c, + 0x57b8, 0x13c9, + 0x57b9, 0x2c4f, + 0x57c2, 0x06fa, + 0x57c3, 0x03ae, + 0x57c4, 0x2c58, + 0x57cb, 0x0a98, + 0x57cc, 0x2c5f, + 0x57ce, 0x04ec, + 0x57cf, 0x13bf, + 0x57d0, 0x2c61, + 0x57d2, 0x13c8, + 0x57d3, 0x2c63, + 0x57d4, 0x0bf1, + 0x57d5, 0x13c4, + 0x57d6, 0x2c64, + 0x57d8, 0x13c5, + 0x57d9, 0x13c7, + 0x57da, 0x13c6, + 0x57db, 0x2c66, + 0x57dd, 0x13ce, + 0x57de, 0x2c68, + 0x57df, 0x10d7, + 0x57e0, 0x0481, + 0x57e1, 0x232a, + 0x57e2, 0x2c69, + 0x57e4, 0x13cd, + 0x57e5, 0x2c6b, + 0x57ed, 0x13d2, + 0x57ee, 0x2c73, + 0x57ef, 0x13cb, + 0x57f0, 0x2c74, + 0x57f4, 0x13ca, + 0x57f5, 0x2c78, + 0x57f7, 0x228b, + 0x57f8, 0x13cc, + 0x57f9, 0x0ba1, + 0x57fa, 0x080e, + 0x57fb, 0x2c7a, + 0x57fd, 0x13d1, + 0x57fe, 0x2c7c, + 0x5800, 0x13d3, + 0x5801, 0x2c7e, + 0x5802, 0x0e16, + 0x5803, 0x2c7f, + 0x5805, 0x1f85, + 0x5806, 0x0610, + 0x5807, 0x144c, + 0x5808, 0x2c81, + 0x580a, 0x2325, + 0x580b, 0x13cf, + 0x580c, 0x2c83, + 0x580d, 0x13d0, + 0x580e, 0x2c84, + 0x5811, 0x0c32, + 0x5812, 0x2c87, + 0x5815, 0x0628, + 0x5816, 0x232c, + 0x5817, 0x2c8a, + 0x5819, 0x13d5, + 0x581a, 0x2c8c, + 0x581d, 0x232e, + 0x581e, 0x13d4, + 0x581f, 0x2c8f, + 0x5820, 0x13d7, + 0x5821, 0x040d, + 0x5822, 0x2c90, + 0x5824, 0x05ad, + 0x5825, 0x2c92, + 0x582a, 0x093d, + 0x582b, 0x2c97, + 0x582f, 0x2205, + 0x5830, 0x1008, + 0x5831, 0x1e38, + 0x5832, 0x2c9b, + 0x5834, 0x1e73, + 0x5835, 0x0601, + 0x5836, 0x2c9d, + 0x5844, 0x13d6, + 0x5845, 0x2cab, + 0x584a, 0x1fe3, + 0x584b, 0x2339, + 0x584c, 0x0def, + 0x584d, 0x19a3, + 0x584e, 0x2cb0, + 0x584f, 0x232b, + 0x5850, 0x2cb1, + 0x5851, 0x0dd1, + 0x5852, 0x232d, + 0x5853, 0x2cb2, + 0x5854, 0x0df3, + 0x5855, 0x2cb3, + 0x5857, 0x217f, + 0x5858, 0x0e14, + 0x5859, 0x2cb5, + 0x585e, 0x0cd6, + 0x585f, 0x2cba, + 0x5862, 0x21a7, + 0x5863, 0x2cbd, + 0x5864, 0x232f, + 0x5865, 0x13d8, + 0x5866, 0x2cbe, + 0x586b, 0x0e41, + 0x586c, 0x13d9, + 0x586d, 0x2cc3, + 0x5875, 0x1e7d, + 0x5876, 0x2ccb, + 0x5879, 0x20d6, + 0x587a, 0x2cce, + 0x587e, 0x13a3, + 0x587f, 0x2cd2, + 0x5880, 0x13dd, + 0x5881, 0x13da, + 0x5882, 0x2cd3, + 0x5883, 0x08e2, + 0x5884, 0x2cd4, + 0x5885, 0x0d92, + 0x5886, 0x2cd5, + 0x5889, 0x13db, + 0x588a, 0x1ec2, + 0x588b, 0x2cd8, + 0x5892, 0x0d03, + 0x5893, 0x0b1c, + 0x5894, 0x2cdf, + 0x5899, 0x0c3a, + 0x589a, 0x13dc, + 0x589b, 0x2ce4, + 0x589c, 0x22b2, + 0x589d, 0x2ce5, + 0x589e, 0x1139, + 0x589f, 0x0fb1, + 0x58a0, 0x2ce6, + 0x58a8, 0x0b0e, + 0x58a9, 0x0614, + 0x58aa, 0x2cee, + 0x58ae, 0x1edf, + 0x58af, 0x2cf2, + 0x58b3, 0x1ef9, + 0x58b4, 0x2cf6, + 0x58bb, 0x20d9, + 0x58bc, 0x13a4, + 0x58bd, 0x2cfd, + 0x58be, 0x1fdd, + 0x58bf, 0x2cfe, + 0x58c1, 0x0443, + 0x58c2, 0x2d00, + 0x58c5, 0x13a5, + 0x58c6, 0x2d03, + 0x58c7, 0x2167, + 0x58c8, 0x2d04, + 0x58d1, 0x13a6, + 0x58d2, 0x2d0d, + 0x58d3, 0x21ed, + 0x58d4, 0x2d0e, + 0x58d5, 0x0775, + 0x58d6, 0x2d0f, + 0x58d8, 0x2007, + 0x58d9, 0x2326, + 0x58da, 0x2329, + 0x58db, 0x2d11, + 0x58de, 0x1f52, + 0x58df, 0x203b, + 0x58e0, 0x2328, + 0x58e1, 0x2d14, + 0x58e2, 0x2327, + 0x58e3, 0x2d15, + 0x58e4, 0x0c9b, + 0x58e5, 0x2d16, + 0x58e9, 0x1e2b, + 0x58ea, 0x2d1a, + 0x58eb, 0x0d56, + 0x58ec, 0x0ca4, + 0x58ed, 0x2d1b, + 0x58ee, 0x1210, + 0x58ef, 0x22ae, + 0x58f0, 0x0d32, + 0x58f1, 0x2d1c, + 0x58f3, 0x0954, + 0x58f4, 0x2d1e, + 0x58f6, 0x07af, + 0x58f7, 0x2d20, + 0x58f9, 0x1043, + 0x58fa, 0x1f49, + 0x58fb, 0x2d22, + 0x58fd, 0x2138, + 0x58fe, 0x2d24, + 0x5900, 0x2d26, + 0x5902, 0x161c, + 0x5903, 0x2d28, + 0x5904, 0x0529, + 0x5905, 0x2d29, + 0x5907, 0x0421, + 0x5908, 0x2d2b, + 0x590d, 0x06af, + 0x590e, 0x2d30, + 0x590f, 0x0f31, + 0x5910, 0x2d31, + 0x5914, 0x12fb, + 0x5915, 0x0f13, + 0x5916, 0x0e93, + 0x5917, 0x2d35, + 0x5919, 0x1301, + 0x591a, 0x061f, + 0x591b, 0x2d37, + 0x591c, 0x1040, + 0x591d, 0x2d38, + 0x591f, 0x0714, + 0x5920, 0x2d3a, + 0x5922, 0x2081, + 0x5923, 0x2d3c, + 0x5924, 0x161b, + 0x5925, 0x1619, + 0x5926, 0x2d3d, + 0x5927, 0x0576, + 0x5928, 0x2d3e, + 0x5929, 0x0e3f, + 0x592a, 0x0dfe, + 0x592b, 0x068f, + 0x592c, 0x2d3f, + 0x592d, 0x1268, + 0x592e, 0x1014, + 0x592f, 0x0772, + 0x5930, 0x2d40, + 0x5931, 0x0d3e, + 0x5932, 0x2d41, + 0x5934, 0x0e68, + 0x5935, 0x2d43, + 0x5937, 0x104b, + 0x5938, 0x0971, + 0x5939, 0x0843, + 0x593a, 0x0620, + 0x593b, 0x2d45, + 0x593c, 0x14af, + 0x593d, 0x2d46, + 0x593e, 0x1f7c, + 0x593f, 0x2d47, + 0x5941, 0x14b0, + 0x5942, 0x138c, + 0x5943, 0x2d49, + 0x5944, 0x1002, + 0x5945, 0x2d4a, + 0x5947, 0x0c05, + 0x5948, 0x0b31, + 0x5949, 0x068b, + 0x594a, 0x2d4c, + 0x594b, 0x0679, + 0x594c, 0x2d4d, + 0x594e, 0x0989, + 0x594f, 0x123d, + 0x5950, 0x2d4f, + 0x5951, 0x0c14, + 0x5952, 0x2d50, + 0x5954, 0x0425, + 0x5955, 0x14b2, + 0x5956, 0x0882, + 0x5957, 0x0e2a, + 0x5958, 0x14b4, + 0x5959, 0x2d52, + 0x595a, 0x14b3, + 0x595b, 0x2d53, + 0x5960, 0x05cd, + 0x5961, 0x2d58, + 0x5962, 0x0d16, + 0x5963, 0x2d59, + 0x5965, 0x03cd, + 0x5966, 0x2d5b, + 0x5969, 0x235b, + 0x596a, 0x1ede, + 0x596b, 0x2d5e, + 0x596c, 0x1fa2, + 0x596d, 0x2d5f, + 0x596e, 0x1efa, + 0x596f, 0x2d60, + 0x5973, 0x0b6f, + 0x5974, 0x0b6c, + 0x5975, 0x2d64, + 0x5976, 0x0b2f, + 0x5977, 0x2d65, + 0x5978, 0x085c, + 0x5979, 0x0df2, + 0x597a, 0x2d66, + 0x597d, 0x077a, + 0x597e, 0x2d69, + 0x5981, 0x1775, + 0x5982, 0x0cc2, + 0x5983, 0x1776, + 0x5984, 0x0eae, + 0x5985, 0x2d6c, + 0x5986, 0x120e, + 0x5987, 0x06b9, + 0x5988, 0x0a8f, + 0x5989, 0x2d6d, + 0x598a, 0x0cac, + 0x598b, 0x2d6e, + 0x598d, 0x1777, + 0x598e, 0x2d70, + 0x5992, 0x0609, + 0x5993, 0x083e, + 0x5994, 0x2d74, + 0x5996, 0x1026, + 0x5997, 0x177b, + 0x5998, 0x2d76, + 0x5999, 0x0af3, + 0x599a, 0x2d77, + 0x599d, 0x22ad, + 0x599e, 0x177e, + 0x599f, 0x2d7a, + 0x59a3, 0x177a, + 0x59a4, 0x177f, + 0x59a5, 0x0e88, + 0x59a6, 0x2d7e, + 0x59a8, 0x065e, + 0x59a9, 0x1778, + 0x59ab, 0x177d, + 0x59ac, 0x2d80, + 0x59ae, 0x0b40, + 0x59af, 0x1782, + 0x59b0, 0x2d82, + 0x59b2, 0x1781, + 0x59b3, 0x2d84, + 0x59b9, 0x0ac8, + 0x59ba, 0x2d8a, + 0x59bb, 0x0bfd, + 0x59bc, 0x2d8b, + 0x59be, 0x1784, + 0x59bf, 0x2d8d, + 0x59c6, 0x0b1a, + 0x59c7, 0x2d94, + 0x59ca, 0x177c, + 0x59cb, 0x0d53, + 0x59cc, 0x2d97, + 0x59d0, 0x08b4, + 0x59d1, 0x071c, + 0x59d2, 0x1780, + 0x59d3, 0x0fa0, + 0x59d4, 0x0ebe, + 0x59d5, 0x2d9b, + 0x59d7, 0x1783, + 0x59d8, 0x178a, + 0x59d9, 0x2d9d, + 0x59da, 0x102d, + 0x59db, 0x2d9e, + 0x59dc, 0x087b, + 0x59dd, 0x1787, + 0x59de, 0x2d9f, + 0x59e3, 0x1789, + 0x59e4, 0x2da4, + 0x59e5, 0x09bc, + 0x59e6, 0x2da5, + 0x59e8, 0x1053, + 0x59e9, 0x2da7, + 0x59ec, 0x081a, + 0x59ed, 0x2daa, + 0x59f9, 0x178b, + 0x59fa, 0x2db6, + 0x59fb, 0x107d, + 0x59fc, 0x2db7, + 0x59ff, 0x1228, + 0x5a00, 0x2dba, + 0x5a01, 0x0eaf, + 0x5a02, 0x2dbb, + 0x5a03, 0x0e8f, + 0x5a04, 0x0a4d, + 0x5a05, 0x1785, + 0x5a07, 0x0890, + 0x5a08, 0x1788, + 0x5a09, 0x178d, + 0x5a0a, 0x2dbc, + 0x5a0c, 0x178c, + 0x5a0d, 0x2dbe, + 0x5a11, 0x1790, + 0x5a12, 0x2dc2, + 0x5a13, 0x1792, + 0x5a14, 0x2dc3, + 0x5a18, 0x0b52, + 0x5a19, 0x2dc7, + 0x5a1c, 0x0b2b, + 0x5a1d, 0x2dca, + 0x5a1f, 0x0919, + 0x5a20, 0x0d28, + 0x5a21, 0x2dcc, + 0x5a23, 0x1791, + 0x5a24, 0x2dce, + 0x5a25, 0x062f, + 0x5a26, 0x2dcf, + 0x5a29, 0x0ae9, + 0x5a2a, 0x2dd2, + 0x5a31, 0x10ce, + 0x5a32, 0x178e, + 0x5a33, 0x2dd9, + 0x5a34, 0x178f, + 0x5a35, 0x2dda, + 0x5a36, 0x0c7d, + 0x5a37, 0x2ddb, + 0x5a3c, 0x1797, + 0x5a3d, 0x2de0, + 0x5a40, 0x1793, + 0x5a41, 0x203f, + 0x5a42, 0x2de3, + 0x5a46, 0x0be4, + 0x5a47, 0x2de7, + 0x5a49, 0x0ea2, + 0x5a4a, 0x1795, + 0x5a4b, 0x2de9, + 0x5a55, 0x1796, + 0x5a56, 0x2df3, + 0x5a5a, 0x07fe, + 0x5a5b, 0x2df7, + 0x5a62, 0x1798, + 0x5a63, 0x2dfe, + 0x5a66, 0x1f0e, + 0x5a67, 0x1794, + 0x5a68, 0x2e01, + 0x5a6a, 0x09a2, + 0x5a6b, 0x2e03, + 0x5a6d, 0x23f9, + 0x5a6e, 0x2e05, + 0x5a74, 0x1089, + 0x5a75, 0x1799, + 0x5a76, 0x0d2d, + 0x5a77, 0x179d, + 0x5a78, 0x2e0b, + 0x5a7a, 0x179e, + 0x5a7b, 0x2e0d, + 0x5a7f, 0x0fc1, + 0x5a80, 0x2e11, + 0x5a92, 0x0ac2, + 0x5a93, 0x2e23, + 0x5a9a, 0x0ac9, + 0x5a9b, 0x179c, + 0x5a9c, 0x2e2a, + 0x5aa7, 0x23fc, + 0x5aa8, 0x2e35, + 0x5aaa, 0x179b, + 0x5aab, 0x2e37, + 0x5ab2, 0x17a1, + 0x5ab3, 0x0f1e, + 0x5ab4, 0x2e3e, + 0x5ab5, 0x19a4, + 0x5ab6, 0x2e3f, + 0x5ab8, 0x17a4, + 0x5ab9, 0x2e41, + 0x5abd, 0x2069, + 0x5abe, 0x179f, + 0x5abf, 0x2e45, + 0x5ac1, 0x0851, + 0x5ac2, 0x0ce2, + 0x5ac3, 0x2e47, + 0x5ac9, 0x0828, + 0x5aca, 0x2e4d, + 0x5acc, 0x0f40, + 0x5acd, 0x2e4f, + 0x5ad2, 0x17a2, + 0x5ad3, 0x2e54, + 0x5ad4, 0x17a3, + 0x5ad5, 0x2e55, + 0x5ad6, 0x17a8, + 0x5ad7, 0x23f7, + 0x5ad8, 0x17aa, + 0x5ad9, 0x2e56, + 0x5adc, 0x17ab, + 0x5add, 0x2e59, + 0x5ae0, 0x17a5, + 0x5ae1, 0x05b6, + 0x5ae2, 0x2e5c, + 0x5ae3, 0x17a6, + 0x5ae4, 0x2e5d, + 0x5ae6, 0x17a9, + 0x5ae7, 0x2e5f, + 0x5ae9, 0x0b3e, + 0x5aea, 0x2e61, + 0x5aeb, 0x17a0, + 0x5aec, 0x2e62, + 0x5af1, 0x17a7, + 0x5af2, 0x2e67, + 0x5af5, 0x23f6, + 0x5af6, 0x2e6a, + 0x5afb, 0x23fd, + 0x5afc, 0x2e6f, + 0x5b00, 0x23f8, + 0x5b01, 0x2e73, + 0x5b08, 0x23fa, + 0x5b09, 0x17ac, + 0x5b0a, 0x2e7a, + 0x5b0b, 0x23fe, + 0x5b0c, 0x1fa8, + 0x5b0d, 0x2e7b, + 0x5b16, 0x17ae, + 0x5b17, 0x17ad, + 0x5b18, 0x2e84, + 0x5b19, 0x2401, + 0x5b1a, 0x2e85, + 0x5b21, 0x23ff, + 0x5b22, 0x2e8c, + 0x5b2a, 0x2400, + 0x5b2b, 0x2e94, + 0x5b30, 0x2221, + 0x5b31, 0x2e99, + 0x5b32, 0x17af, + 0x5b33, 0x2e9a, + 0x5b34, 0x130c, + 0x5b35, 0x2e9b, + 0x5b37, 0x17b0, + 0x5b38, 0x2122, + 0x5b39, 0x2e9d, + 0x5b40, 0x17b1, + 0x5b41, 0x2ea4, + 0x5b4c, 0x23fb, + 0x5b4d, 0x2eaf, + 0x5b50, 0x1230, + 0x5b51, 0x17b7, + 0x5b52, 0x2eb2, + 0x5b53, 0x17b8, + 0x5b54, 0x0964, + 0x5b55, 0x1113, + 0x5b56, 0x2eb3, + 0x5b57, 0x1233, + 0x5b58, 0x0569, + 0x5b59, 0x0de4, + 0x5b5a, 0x17b4, + 0x5b5b, 0x1279, + 0x5b5c, 0x122b, + 0x5b5d, 0x0f6d, + 0x5b5e, 0x2eb4, + 0x5b5f, 0x0ad4, + 0x5b60, 0x2eb5, + 0x5b62, 0x17b9, + 0x5b63, 0x0831, + 0x5b64, 0x071b, + 0x5b65, 0x17b5, + 0x5b66, 0x0fd0, + 0x5b67, 0x2eb7, + 0x5b69, 0x0759, + 0x5b6a, 0x0a76, + 0x5b6b, 0x215a, + 0x5b6c, 0x1261, + 0x5b6d, 0x2eb9, + 0x5b70, 0x0d82, + 0x5b71, 0x176a, + 0x5b72, 0x2ebc, + 0x5b73, 0x17b6, + 0x5b74, 0x2ebd, + 0x5b75, 0x0692, + 0x5b76, 0x2ebe, + 0x5b78, 0x21e5, + 0x5b79, 0x2ec0, + 0x5b7a, 0x0cc1, + 0x5b7b, 0x2ec1, + 0x5b7d, 0x0b58, + 0x5b7e, 0x2ec3, + 0x5b7f, 0x2057, + 0x5b80, 0x172e, + 0x5b81, 0x0b61, + 0x5b82, 0x2ec4, + 0x5b83, 0x0df1, + 0x5b84, 0x172f, + 0x5b85, 0x114d, + 0x5b86, 0x2ec5, + 0x5b87, 0x10d3, + 0x5b88, 0x0d6f, + 0x5b89, 0x03bd, + 0x5b8a, 0x2ec6, + 0x5b8b, 0x0dc3, + 0x5b8c, 0x0e9b, + 0x5b8d, 0x2ec7, + 0x5b8f, 0x07a1, + 0x5b90, 0x2ec9, + 0x5b93, 0x1731, + 0x5b94, 0x2ecc, + 0x5b95, 0x1730, + 0x5b96, 0x2ecd, + 0x5b97, 0x1237, + 0x5b98, 0x0732, + 0x5b99, 0x11e5, + 0x5b9a, 0x05e7, + 0x5b9b, 0x0ea1, + 0x5b9c, 0x1052, + 0x5b9d, 0x040f, + 0x5b9e, 0x0d4c, + 0x5b9f, 0x2ece, + 0x5ba0, 0x050d, + 0x5ba1, 0x0d2c, + 0x5ba2, 0x095a, + 0x5ba3, 0x0fc6, + 0x5ba4, 0x0d69, + 0x5ba5, 0x1732, + 0x5ba6, 0x07d7, + 0x5ba7, 0x2ecf, + 0x5baa, 0x0f49, + 0x5bab, 0x0705, + 0x5bac, 0x2ed2, + 0x5bb0, 0x111a, + 0x5bb1, 0x2ed6, + 0x5bb3, 0x075d, + 0x5bb4, 0x1010, + 0x5bb5, 0x0f69, + 0x5bb6, 0x0845, + 0x5bb7, 0x2ed8, + 0x5bb8, 0x1733, + 0x5bb9, 0x0cb8, + 0x5bba, 0x2ed9, + 0x5bbd, 0x097a, + 0x5bbe, 0x045f, + 0x5bbf, 0x0dd3, + 0x5bc0, 0x2edc, + 0x5bc2, 0x0838, + 0x5bc3, 0x2ede, + 0x5bc4, 0x0837, + 0x5bc5, 0x1081, + 0x5bc6, 0x0ae1, + 0x5bc7, 0x0969, + 0x5bc8, 0x2edf, + 0x5bcc, 0x06b6, + 0x5bcd, 0x2ee3, + 0x5bd0, 0x0ac7, + 0x5bd1, 0x2ee6, + 0x5bd2, 0x0765, + 0x5bd3, 0x10e5, + 0x5bd4, 0x2ee7, + 0x5bdd, 0x0c5b, + 0x5bde, 0x0b12, + 0x5bdf, 0x04b3, + 0x5be0, 0x2ef0, + 0x5be1, 0x072a, + 0x5be2, 0x20e5, + 0x5be3, 0x2ef1, + 0x5be4, 0x1737, + 0x5be5, 0x0a11, + 0x5be6, 0x212f, + 0x5be7, 0x20a3, + 0x5be8, 0x1150, + 0x5be9, 0x2121, + 0x5bea, 0x2ef2, + 0x5beb, 0x21d4, + 0x5bec, 0x1fe5, + 0x5bed, 0x2ef3, + 0x5bee, 0x1738, + 0x5bef, 0x2ef4, + 0x5bf0, 0x173a, + 0x5bf1, 0x2ef5, + 0x5bf5, 0x1e8a, + 0x5bf6, 0x1e37, + 0x5bf7, 0x2ef9, + 0x5bf8, 0x056a, + 0x5bf9, 0x0613, + 0x5bfa, 0x0db7, + 0x5bfb, 0x0fd9, + 0x5bfc, 0x059d, + 0x5bfd, 0x2efa, + 0x5bff, 0x0d70, + 0x5c00, 0x2efc, + 0x5c01, 0x067f, + 0x5c02, 0x2efd, + 0x5c04, 0x0d1d, + 0x5c05, 0x2eff, + 0x5c06, 0x087c, + 0x5c07, 0x1f9e, + 0x5c08, 0x22a6, + 0x5c09, 0x0ecd, + 0x5c0a, 0x124d, + 0x5c0b, 0x21e8, + 0x5c0c, 0x2f00, + 0x5c0d, 0x1eda, + 0x5c0e, 0x1eb9, + 0x5c0f, 0x0f6c, + 0x5c10, 0x2f01, + 0x5c11, 0x0d12, + 0x5c12, 0x2f02, + 0x5c14, 0x063a, + 0x5c15, 0x17b2, + 0x5c16, 0x0855, + 0x5c17, 0x2f04, + 0x5c18, 0x04e3, + 0x5c19, 0x2f05, + 0x5c1a, 0x0d09, + 0x5c1b, 0x2f06, + 0x5c1c, 0x17b3, + 0x5c1d, 0x04c7, + 0x5c1e, 0x2f07, + 0x5c22, 0x14b6, + 0x5c23, 0x2f0b, + 0x5c24, 0x10ad, + 0x5c25, 0x14b7, + 0x5c26, 0x2f0c, + 0x5c27, 0x1029, + 0x5c28, 0x2f0d, + 0x5c2c, 0x14b8, + 0x5c2d, 0x2f11, + 0x5c31, 0x08fc, + 0x5c32, 0x2f15, + 0x5c34, 0x14b9, + 0x5c35, 0x2f17, + 0x5c37, 0x235c, + 0x5c38, 0x0d43, + 0x5c39, 0x1083, + 0x5c3a, 0x0504, + 0x5c3b, 0x1766, + 0x5c3c, 0x0b44, + 0x5c3d, 0x08d0, + 0x5c3e, 0x0ec1, + 0x5c3f, 0x0b55, + 0x5c40, 0x0905, + 0x5c41, 0x0bc7, + 0x5c42, 0x04aa, + 0x5c43, 0x2f19, + 0x5c45, 0x0902, + 0x5c46, 0x2f1b, + 0x5c48, 0x0c79, + 0x5c49, 0x0e3e, + 0x5c4a, 0x08bd, + 0x5c4b, 0x0eec, + 0x5c4c, 0x2f1d, + 0x5c4e, 0x0d51, + 0x5c4f, 0x0be0, + 0x5c50, 0x1768, + 0x5c51, 0x0f87, + 0x5c52, 0x2f1f, + 0x5c55, 0x115a, + 0x5c56, 0x2f22, + 0x5c59, 0x1769, + 0x5c5a, 0x2f25, + 0x5c5e, 0x0d8b, + 0x5c5f, 0x2f29, + 0x5c60, 0x0e71, + 0x5c61, 0x0a6c, + 0x5c62, 0x2050, + 0x5c63, 0x176b, + 0x5c64, 0x1e67, + 0x5c65, 0x0a6b, + 0x5c66, 0x176c, + 0x5c67, 0x2f2a, + 0x5c68, 0x23f4, + 0x5c69, 0x2f2b, + 0x5c6c, 0x213e, + 0x5c6d, 0x2f2e, + 0x5c6e, 0x1774, + 0x5c6f, 0x0e7e, + 0x5c70, 0x2f2f, + 0x5c71, 0x0cf6, + 0x5c72, 0x2f30, + 0x5c79, 0x1060, + 0x5c7a, 0x15ac, + 0x5c7b, 0x2f37, + 0x5c7f, 0x10d1, + 0x5c80, 0x2f3b, + 0x5c81, 0x0ddf, + 0x5c82, 0x0c10, + 0x5c83, 0x2f3c, + 0x5c88, 0x15b0, + 0x5c89, 0x2f41, + 0x5c8c, 0x15ab, + 0x5c8d, 0x15ad, + 0x5c8e, 0x2f44, + 0x5c90, 0x15ae, + 0x5c91, 0x15b3, + 0x5c92, 0x2f46, + 0x5c94, 0x04b4, + 0x5c95, 0x2f48, + 0x5c96, 0x15af, + 0x5c97, 0x06d5, + 0x5c98, 0x15b1, + 0x5c9a, 0x15b4, + 0x5c9b, 0x059b, + 0x5c9c, 0x15b5, + 0x5c9d, 0x2f49, + 0x5ca1, 0x1f16, + 0x5ca2, 0x15b7, + 0x5ca3, 0x15bc, + 0x5ca4, 0x2f4d, + 0x5ca9, 0x0ffb, + 0x5caa, 0x2f52, + 0x5cab, 0x15ba, + 0x5cac, 0x15b9, + 0x5cad, 0x0a34, + 0x5cae, 0x2f53, + 0x5cb1, 0x15bb, + 0x5cb2, 0x2f56, + 0x5cb3, 0x1103, + 0x5cb4, 0x2f57, + 0x5cb5, 0x15b6, + 0x5cb6, 0x2f58, + 0x5cb7, 0x15be, + 0x5cb8, 0x03c1, + 0x5cb9, 0x2f59, + 0x5cbd, 0x15b8, + 0x5cbe, 0x2f5d, + 0x5cbf, 0x0986, + 0x5cc0, 0x2f5e, + 0x5cc1, 0x15bd, + 0x5cc2, 0x2f5f, + 0x5cc4, 0x15bf, + 0x5cc5, 0x2f61, + 0x5ccb, 0x15c2, + 0x5ccc, 0x2f67, + 0x5cd2, 0x15c0, + 0x5cd3, 0x2f6d, + 0x5cd9, 0x11c4, + 0x5cda, 0x2f73, + 0x5ce1, 0x0f2c, + 0x5ce2, 0x2f7a, + 0x5ce4, 0x15c1, + 0x5ce5, 0x15c3, + 0x5ce6, 0x0a74, + 0x5ce7, 0x2f7c, + 0x5ce8, 0x062a, + 0x5ce9, 0x2f7d, + 0x5cea, 0x10dd, + 0x5ceb, 0x2f7e, + 0x5ced, 0x0c4a, + 0x5cee, 0x2f80, + 0x5cf0, 0x0682, + 0x5cf1, 0x2f82, + 0x5cf4, 0x2389, + 0x5cf5, 0x2f85, + 0x5cf6, 0x1eb7, + 0x5cf7, 0x2f86, + 0x5cfb, 0x092d, + 0x5cfc, 0x2f8a, + 0x5cfd, 0x21b4, + 0x5cfe, 0x2f8b, + 0x5d00, 0x2f8d, + 0x5d02, 0x15c4, + 0x5d04, 0x2f8f, + 0x5d06, 0x15cb, + 0x5d07, 0x050c, + 0x5d08, 0x2f91, + 0x5d0d, 0x238f, + 0x5d0e, 0x0c08, + 0x5d0f, 0x2f96, + 0x5d14, 0x0561, + 0x5d15, 0x2f9b, + 0x5d16, 0x0feb, + 0x5d17, 0x1f1a, + 0x5d18, 0x2f9c, + 0x5d1b, 0x15cc, + 0x5d1c, 0x2f9f, + 0x5d1e, 0x15ca, + 0x5d1f, 0x2fa1, + 0x5d24, 0x15c9, + 0x5d25, 0x2fa6, + 0x5d26, 0x15c7, + 0x5d27, 0x15c6, + 0x5d28, 0x2fa7, + 0x5d29, 0x0429, + 0x5d2a, 0x2fa8, + 0x5d2c, 0x238b, + 0x5d2d, 0x1159, + 0x5d2e, 0x15c8, + 0x5d2f, 0x2faa, + 0x5d34, 0x15cf, + 0x5d35, 0x2faf, + 0x5d3d, 0x15d0, + 0x5d3e, 0x15ce, + 0x5d3f, 0x2fb7, + 0x5d47, 0x1b22, + 0x5d48, 0x2fbf, + 0x5d4a, 0x15d7, + 0x5d4b, 0x15d6, + 0x5d4c, 0x0c33, + 0x5d4d, 0x2fc1, + 0x5d50, 0x238a, + 0x5d51, 0x2fc4, + 0x5d58, 0x15cd, + 0x5d59, 0x2fcb, + 0x5d5b, 0x15d2, + 0x5d5c, 0x2fcd, + 0x5d5d, 0x15d4, + 0x5d5e, 0x2fce, + 0x5d69, 0x15d8, + 0x5d6a, 0x2fd9, + 0x5d6b, 0x15d5, + 0x5d6c, 0x15d1, + 0x5d6d, 0x2fda, + 0x5d6f, 0x15d3, + 0x5d70, 0x2fdc, + 0x5d74, 0x15d9, + 0x5d75, 0x2fe0, + 0x5d81, 0x2391, + 0x5d82, 0x15da, + 0x5d83, 0x2fec, + 0x5d84, 0x2271, + 0x5d85, 0x2fed, + 0x5d87, 0x2388, + 0x5d88, 0x2fef, + 0x5d97, 0x238e, + 0x5d98, 0x2ffe, + 0x5d99, 0x15db, + 0x5d9a, 0x2fff, + 0x5d9d, 0x15dc, + 0x5d9e, 0x3002, + 0x5da0, 0x238d, + 0x5da1, 0x3004, + 0x5da7, 0x238c, + 0x5da8, 0x300a, + 0x5db7, 0x15de, + 0x5db8, 0x2390, + 0x5db9, 0x3019, + 0x5dba, 0x2033, + 0x5dbb, 0x301a, + 0x5dbc, 0x223c, + 0x5dbd, 0x301b, + 0x5dc5, 0x15df, + 0x5dc6, 0x3023, + 0x5dcb, 0x1fe9, + 0x5dcc, 0x3028, + 0x5dcd, 0x0eb0, + 0x5dce, 0x3029, + 0x5dd2, 0x2055, + 0x5dd3, 0x302d, + 0x5dd4, 0x2392, + 0x5dd5, 0x302e, + 0x5ddb, 0x1815, + 0x5ddc, 0x3034, + 0x5ddd, 0x052b, + 0x5dde, 0x11dc, + 0x5ddf, 0x3035, + 0x5de1, 0x0fdb, + 0x5de2, 0x04d7, + 0x5de3, 0x3037, + 0x5de5, 0x06fd, + 0x5de6, 0x1250, + 0x5de7, 0x0c46, + 0x5de8, 0x090d, + 0x5de9, 0x0707, + 0x5dea, 0x3039, + 0x5deb, 0x0ee6, + 0x5dec, 0x303a, + 0x5dee, 0x04b5, + 0x5def, 0x139f, + 0x5df0, 0x2324, + 0x5df1, 0x082d, + 0x5df2, 0x1058, + 0x5df3, 0x0dbd, + 0x5df4, 0x03d8, + 0x5df5, 0x303c, + 0x5df7, 0x0f5c, + 0x5df8, 0x303e, + 0x5dfd, 0x12f7, + 0x5dfe, 0x08be, + 0x5dff, 0x3043, + 0x5e00, 0x3044, + 0x5e01, 0x043b, + 0x5e02, 0x0d67, + 0x5e03, 0x0483, + 0x5e04, 0x3045, + 0x5e05, 0x0d9c, + 0x5e06, 0x0648, + 0x5e07, 0x3046, + 0x5e08, 0x0d3d, + 0x5e09, 0x3047, + 0x5e0c, 0x0f10, + 0x5e0d, 0x304a, + 0x5e0f, 0x159e, + 0x5e10, 0x116b, + 0x5e11, 0x15a1, + 0x5e12, 0x304c, + 0x5e14, 0x15a0, + 0x5e15, 0x0b82, + 0x5e16, 0x0e4e, + 0x5e17, 0x304e, + 0x5e18, 0x09fa, + 0x5e19, 0x159f, + 0x5e1a, 0x11e2, + 0x5e1b, 0x0476, + 0x5e1c, 0x11c3, + 0x5e1d, 0x05bc, + 0x5e1e, 0x304f, + 0x5e25, 0x2143, + 0x5e26, 0x057b, + 0x5e27, 0x11a0, + 0x5e28, 0x3056, + 0x5e2b, 0x2129, + 0x5e2c, 0x3059, + 0x5e2d, 0x0f1c, + 0x5e2e, 0x03fa, + 0x5e2f, 0x305a, + 0x5e31, 0x15a2, + 0x5e32, 0x305c, + 0x5e33, 0x2277, + 0x5e34, 0x305d, + 0x5e36, 0x1ea7, + 0x5e37, 0x15a5, + 0x5e38, 0x04c8, + 0x5e39, 0x305f, + 0x5e3b, 0x15a3, + 0x5e3d, 0x0ab6, + 0x5e3e, 0x3061, + 0x5e40, 0x2285, + 0x5e41, 0x3063, + 0x5e42, 0x0ae2, + 0x5e43, 0x2384, + 0x5e44, 0x15a6, + 0x5e45, 0x0696, + 0x5e46, 0x3064, + 0x5e4c, 0x07e4, + 0x5e4d, 0x306a, + 0x5e54, 0x15a7, + 0x5e55, 0x0b1e, + 0x5e56, 0x3071, + 0x5e57, 0x2387, + 0x5e58, 0x2386, + 0x5e59, 0x3072, + 0x5e5b, 0x15a8, + 0x5e5c, 0x3074, + 0x5e5e, 0x15a9, + 0x5e5f, 0x2290, + 0x5e60, 0x3076, + 0x5e61, 0x15aa, + 0x5e62, 0x0534, + 0x5e63, 0x1e44, + 0x5e64, 0x3077, + 0x5e6b, 0x1e32, + 0x5e6c, 0x2385, + 0x5e6d, 0x307e, + 0x5e72, 0x06c4, + 0x5e73, 0x0bdc, + 0x5e74, 0x0b4d, + 0x5e75, 0x3083, + 0x5e76, 0x0469, + 0x5e77, 0x3084, + 0x5e78, 0x0f9d, + 0x5e79, 0x1f13, + 0x5e7a, 0x1813, + 0x5e7b, 0x07d8, + 0x5e7c, 0x10bc, + 0x5e7d, 0x10a9, + 0x5e7e, 0x1f73, + 0x5e7f, 0x073c, + 0x5e80, 0x1631, + 0x5e81, 0x3085, + 0x5e84, 0x120c, + 0x5e85, 0x3088, + 0x5e86, 0x0c69, + 0x5e87, 0x043c, + 0x5e88, 0x3089, + 0x5e8a, 0x0535, + 0x5e8b, 0x1633, + 0x5e8c, 0x308b, + 0x5e8f, 0x0fbd, + 0x5e90, 0x0a55, + 0x5e91, 0x1632, + 0x5e92, 0x308e, + 0x5e93, 0x096f, + 0x5e94, 0x108b, + 0x5e95, 0x05b8, + 0x5e96, 0x1634, + 0x5e97, 0x05cb, + 0x5e98, 0x308f, + 0x5e99, 0x0af2, + 0x5e9a, 0x06f8, + 0x5e9b, 0x3090, + 0x5e9c, 0x06a9, + 0x5e9d, 0x3091, + 0x5e9e, 0x0b94, + 0x5e9f, 0x066c, + 0x5ea0, 0x1636, + 0x5ea1, 0x3092, + 0x5ea5, 0x1635, + 0x5ea6, 0x0607, + 0x5ea7, 0x1256, + 0x5ea8, 0x3096, + 0x5eab, 0x1fe0, + 0x5eac, 0x3099, + 0x5ead, 0x0e56, + 0x5eae, 0x309a, + 0x5eb3, 0x163a, + 0x5eb4, 0x309f, + 0x5eb5, 0x1638, + 0x5eb6, 0x0d93, + 0x5eb7, 0x0942, + 0x5eb8, 0x109e, + 0x5eb9, 0x1637, + 0x5eba, 0x30a0, + 0x5ebe, 0x1639, + 0x5ebf, 0x30a4, + 0x5ec9, 0x09f7, + 0x5eca, 0x09b3, + 0x5ecb, 0x30ae, + 0x5ed1, 0x163d, + 0x5ed2, 0x163c, + 0x5ed3, 0x0995, + 0x5ed4, 0x30b4, + 0x5ed6, 0x0a17, + 0x5ed7, 0x30b6, + 0x5edb, 0x163e, + 0x5edc, 0x30ba, + 0x5edf, 0x2087, + 0x5ee0, 0x1e78, + 0x5ee1, 0x23ae, + 0x5ee2, 0x1ef6, + 0x5ee3, 0x1f31, + 0x5ee4, 0x30bd, + 0x5ee8, 0x163f, + 0x5ee9, 0x30c1, + 0x5eea, 0x1640, + 0x5eeb, 0x30c2, + 0x5eec, 0x2045, + 0x5eed, 0x30c3, + 0x5ef3, 0x2178, + 0x5ef4, 0x1398, + 0x5ef5, 0x30c9, + 0x5ef6, 0x0ffc, + 0x5ef7, 0x0e53, + 0x5ef8, 0x30ca, + 0x5efa, 0x0879, + 0x5efb, 0x30cc, + 0x5efe, 0x14ad, + 0x5eff, 0x125b, + 0x5f00, 0x0937, + 0x5f01, 0x139d, + 0x5f02, 0x1073, + 0x5f03, 0x0c19, + 0x5f04, 0x0b6b, + 0x5f05, 0x30cf, + 0x5f08, 0x14ae, + 0x5f09, 0x30d2, + 0x5f0a, 0x0440, + 0x5f0b, 0x14f6, + 0x5f0c, 0x30d3, + 0x5f0f, 0x0d54, + 0x5f10, 0x30d6, + 0x5f11, 0x14f9, + 0x5f12, 0x30d7, + 0x5f13, 0x0706, + 0x5f14, 0x30d8, + 0x5f15, 0x1084, + 0x5f16, 0x30d9, + 0x5f17, 0x06a0, + 0x5f18, 0x07a2, + 0x5f19, 0x30da, + 0x5f1b, 0x04ff, + 0x5f1c, 0x30dc, + 0x5f1f, 0x05bd, + 0x5f20, 0x1166, + 0x5f21, 0x30df, + 0x5f25, 0x0adb, + 0x5f26, 0x0f3f, + 0x5f27, 0x07b6, + 0x5f28, 0x30e3, + 0x5f29, 0x176f, + 0x5f2a, 0x176e, + 0x5f2b, 0x30e4, + 0x5f2d, 0x1770, + 0x5f2e, 0x30e6, + 0x5f2f, 0x0e95, + 0x5f30, 0x30e7, + 0x5f31, 0x0cd0, + 0x5f32, 0x30e8, + 0x5f33, 0x23f5, + 0x5f34, 0x30e9, + 0x5f35, 0x2275, + 0x5f36, 0x30ea, + 0x5f39, 0x0590, + 0x5f3a, 0x0c3c, + 0x5f3b, 0x30ed, + 0x5f3c, 0x1772, + 0x5f3d, 0x30ee, + 0x5f40, 0x19be, + 0x5f41, 0x30f1, + 0x5f46, 0x266e, + 0x5f47, 0x30f6, + 0x5f48, 0x1eb0, + 0x5f49, 0x30f7, + 0x5f4c, 0x2083, + 0x5f4d, 0x30fa, + 0x5f4e, 0x2188, + 0x5f4f, 0x30fb, + 0x5f50, 0x1762, + 0x5f51, 0x30fc, + 0x5f52, 0x0742, + 0x5f53, 0x0592, + 0x5f54, 0x30fd, + 0x5f55, 0x0a63, + 0x5f56, 0x1764, + 0x5f57, 0x1763, + 0x5f58, 0x1765, + 0x5f59, 0x267c, + 0x5f5a, 0x30fe, + 0x5f5d, 0x1054, + 0x5f5e, 0x3101, + 0x5f61, 0x15ee, + 0x5f62, 0x0f99, + 0x5f63, 0x3104, + 0x5f64, 0x0e5f, + 0x5f65, 0x3105, + 0x5f66, 0x100e, + 0x5f67, 0x3106, + 0x5f69, 0x0491, + 0x5f6a, 0x0454, + 0x5f6b, 0x3108, + 0x5f6c, 0x045b, + 0x5f6d, 0x0bae, + 0x5f6e, 0x3109, + 0x5f70, 0x1164, + 0x5f71, 0x1095, + 0x5f72, 0x310b, + 0x5f73, 0x15e0, + 0x5f74, 0x310c, + 0x5f77, 0x15e1, + 0x5f78, 0x310f, + 0x5f79, 0x1062, + 0x5f7a, 0x3110, + 0x5f7b, 0x04de, + 0x5f7c, 0x0434, + 0x5f7d, 0x3111, + 0x5f80, 0x0eaa, + 0x5f81, 0x1198, + 0x5f82, 0x15e2, + 0x5f83, 0x3114, + 0x5f84, 0x08e5, + 0x5f85, 0x0580, + 0x5f86, 0x3115, + 0x5f87, 0x15e3, + 0x5f88, 0x0793, + 0x5f89, 0x15e4, + 0x5f8a, 0x07c7, + 0x5f8b, 0x0a70, + 0x5f8c, 0x15e5, + 0x5f8d, 0x3116, + 0x5f90, 0x0fb7, + 0x5f91, 0x1fc5, + 0x5f92, 0x0e6e, + 0x5f93, 0x3119, + 0x5f95, 0x15e6, + 0x5f96, 0x311b, + 0x5f97, 0x05a4, + 0x5f98, 0x0b88, + 0x5f99, 0x15e7, + 0x5f9a, 0x311c, + 0x5f9c, 0x15e8, + 0x5f9d, 0x311e, + 0x5f9e, 0x1ea1, + 0x5f9f, 0x311f, + 0x5fa0, 0x2393, + 0x5fa1, 0x10de, + 0x5fa2, 0x3120, + 0x5fa8, 0x15e9, + 0x5fa9, 0x1f0b, + 0x5faa, 0x0fd6, + 0x5fab, 0x3126, + 0x5fad, 0x15ea, + 0x5fae, 0x0eb1, + 0x5faf, 0x3128, + 0x5fb5, 0x15eb, + 0x5fb6, 0x312e, + 0x5fb7, 0x05a3, + 0x5fb8, 0x312f, + 0x5fb9, 0x1e7c, + 0x5fba, 0x3130, + 0x5fbc, 0x15ec, + 0x5fbd, 0x07ea, + 0x5fbe, 0x3132, + 0x5fc3, 0x0f8f, + 0x5fc4, 0x1642, + 0x5fc5, 0x0441, + 0x5fc6, 0x106b, + 0x5fc7, 0x3137, + 0x5fc9, 0x1643, + 0x5fca, 0x3139, + 0x5fcc, 0x083c, + 0x5fcd, 0x0ca7, + 0x5fce, 0x313b, + 0x5fcf, 0x1645, + 0x5fd0, 0x1a0c, + 0x5fd1, 0x1a0b, + 0x5fd2, 0x14f7, + 0x5fd3, 0x313c, + 0x5fd6, 0x1644, + 0x5fd7, 0x11bd, + 0x5fd8, 0x0ead, + 0x5fd9, 0x0aab, + 0x5fda, 0x313f, + 0x5fdd, 0x1683, + 0x5fde, 0x3142, + 0x5fe0, 0x11d1, + 0x5fe1, 0x1649, + 0x5fe2, 0x3144, + 0x5fe4, 0x164a, + 0x5fe5, 0x3146, + 0x5fe7, 0x10ac, + 0x5fe8, 0x3148, + 0x5fea, 0x164e, + 0x5feb, 0x0979, + 0x5fec, 0x314a, + 0x5fed, 0x164f, + 0x5fee, 0x1647, + 0x5fef, 0x314b, + 0x5ff1, 0x04e5, + 0x5ff2, 0x314d, + 0x5ff5, 0x0b51, + 0x5ff6, 0x3150, + 0x5ff8, 0x1650, + 0x5ff9, 0x3152, + 0x5ffb, 0x0f8e, + 0x5ffc, 0x3154, + 0x5ffd, 0x07ad, + 0x5ffe, 0x164b, + 0x5fff, 0x067b, + 0x6000, 0x07c8, + 0x6001, 0x0dff, + 0x6002, 0x0dc0, + 0x6003, 0x1646, + 0x6004, 0x1648, + 0x6005, 0x164c, + 0x6007, 0x3155, + 0x600a, 0x1659, + 0x600b, 0x3158, + 0x600d, 0x1656, + 0x600e, 0x1138, + 0x600f, 0x1655, + 0x6010, 0x315a, + 0x6012, 0x0b6e, + 0x6013, 0x315c, + 0x6014, 0x119b, + 0x6015, 0x0b83, + 0x6016, 0x0487, + 0x6017, 0x315d, + 0x6019, 0x1651, + 0x601a, 0x315f, + 0x601b, 0x1654, + 0x601c, 0x09f8, + 0x601d, 0x0db1, + 0x601e, 0x3160, + 0x6020, 0x0582, + 0x6021, 0x165b, + 0x6022, 0x3162, + 0x6025, 0x0824, + 0x6026, 0x1653, + 0x6027, 0x0f9f, + 0x6028, 0x10fc, + 0x6029, 0x1657, + 0x602a, 0x072f, + 0x602b, 0x1658, + 0x602c, 0x3165, + 0x602f, 0x0c50, + 0x6030, 0x3168, + 0x6035, 0x1652, + 0x6036, 0x316d, + 0x603b, 0x1239, + 0x603c, 0x1a0d, + 0x603d, 0x3172, + 0x603f, 0x165a, + 0x6040, 0x3174, + 0x6041, 0x1a11, + 0x6042, 0x1660, + 0x6043, 0x0d68, + 0x6044, 0x3175, + 0x604b, 0x09fe, + 0x604c, 0x317c, + 0x604d, 0x07e5, + 0x604e, 0x317d, + 0x6050, 0x0963, + 0x6051, 0x317f, + 0x6052, 0x079a, + 0x6053, 0x3180, + 0x6055, 0x0d96, + 0x6056, 0x3182, + 0x6059, 0x1a12, + 0x605a, 0x1a0f, + 0x605b, 0x3185, + 0x605d, 0x1a0e, + 0x605e, 0x3187, + 0x6062, 0x07eb, + 0x6063, 0x1a13, + 0x6064, 0x0fbf, + 0x6065, 0x318b, + 0x6067, 0x1a10, + 0x6068, 0x0795, + 0x6069, 0x0636, + 0x606a, 0x1661, + 0x606b, 0x05f1, + 0x606c, 0x0e44, + 0x606d, 0x0700, + 0x606e, 0x318d, + 0x606f, 0x0f0f, + 0x6070, 0x0c1e, + 0x6071, 0x318e, + 0x6073, 0x095f, + 0x6074, 0x3190, + 0x6076, 0x0630, + 0x6077, 0x3192, + 0x6078, 0x165c, + 0x607a, 0x165f, + 0x607b, 0x165e, + 0x607c, 0x0b38, + 0x607d, 0x1662, + 0x607e, 0x3193, + 0x607f, 0x10a6, + 0x6080, 0x3194, + 0x6083, 0x1667, + 0x6084, 0x0c41, + 0x6085, 0x3197, + 0x6089, 0x0f11, + 0x608a, 0x319b, + 0x608c, 0x1669, + 0x608d, 0x076e, + 0x608e, 0x319d, + 0x6092, 0x1668, + 0x6093, 0x31a1, + 0x6094, 0x07ef, + 0x6095, 0x31a2, + 0x6096, 0x1663, + 0x6097, 0x31a3, + 0x609a, 0x1664, + 0x609b, 0x166a, + 0x609c, 0x31a6, + 0x609d, 0x1666, + 0x609e, 0x31a7, + 0x609f, 0x0f01, + 0x60a0, 0x10ab, + 0x60a1, 0x31a8, + 0x60a3, 0x07d1, + 0x60a4, 0x31aa, + 0x60a6, 0x1106, + 0x60a7, 0x31ac, + 0x60a8, 0x0b5d, + 0x60a9, 0x31ad, + 0x60ab, 0x1a14, + 0x60ac, 0x0fc7, + 0x60ad, 0x1665, + 0x60ae, 0x31af, + 0x60af, 0x0afa, + 0x60b0, 0x31b0, + 0x60b1, 0x166d, + 0x60b2, 0x0418, + 0x60b3, 0x31b1, + 0x60b4, 0x1672, + 0x60b5, 0x23b4, + 0x60b6, 0x207e, + 0x60b7, 0x31b2, + 0x60b8, 0x0835, + 0x60b9, 0x31b3, + 0x60bb, 0x166c, + 0x60bc, 0x05a0, + 0x60bd, 0x31b5, + 0x60c5, 0x0c66, + 0x60c6, 0x1670, + 0x60c7, 0x31bd, + 0x60ca, 0x08d9, + 0x60cb, 0x0ea0, + 0x60cc, 0x31c0, + 0x60d1, 0x0808, + 0x60d2, 0x31c5, + 0x60d5, 0x0e3b, + 0x60d6, 0x31c8, + 0x60d8, 0x166f, + 0x60d9, 0x31ca, + 0x60da, 0x1671, + 0x60db, 0x31cb, + 0x60dc, 0x0f14, + 0x60dd, 0x166e, + 0x60de, 0x31cc, + 0x60df, 0x0eb8, + 0x60e0, 0x07f2, + 0x60e1, 0x1ee3, + 0x60e2, 0x31cd, + 0x60e6, 0x05cc, + 0x60e7, 0x0914, + 0x60e8, 0x0499, + 0x60e9, 0x04f2, + 0x60ea, 0x31d1, + 0x60eb, 0x0422, + 0x60ec, 0x166b, + 0x60ed, 0x0498, + 0x60ee, 0x058d, + 0x60ef, 0x0738, + 0x60f0, 0x0627, + 0x60f1, 0x2095, + 0x60f2, 0x23bb, + 0x60f3, 0x0f58, + 0x60f4, 0x1677, + 0x60f5, 0x31d2, + 0x60f6, 0x07e1, + 0x60f7, 0x31d3, + 0x60f9, 0x0ca2, + 0x60fa, 0x0f95, + 0x60fb, 0x23b9, + 0x60fc, 0x31d5, + 0x6100, 0x1678, + 0x6101, 0x0513, + 0x6102, 0x31d9, + 0x6106, 0x1a15, + 0x6107, 0x31dd, + 0x6108, 0x10df, + 0x6109, 0x10c9, + 0x610a, 0x31de, + 0x610d, 0x1a16, + 0x610e, 0x1679, + 0x610f, 0x1069, + 0x6110, 0x31e1, + 0x6115, 0x1675, + 0x6116, 0x31e6, + 0x611a, 0x10c3, + 0x611b, 0x1e28, + 0x611c, 0x23bd, + 0x611d, 0x31ea, + 0x611f, 0x06cb, + 0x6120, 0x1673, + 0x6121, 0x31ec, + 0x6123, 0x1676, + 0x6124, 0x067c, + 0x6125, 0x31ee, + 0x6126, 0x1674, + 0x6127, 0x098d, + 0x6128, 0x31ef, + 0x612b, 0x167a, + 0x612c, 0x31f2, + 0x6134, 0x23b5, + 0x6135, 0x31fa, + 0x6137, 0x23ba, + 0x6138, 0x31fc, + 0x613e, 0x23b3, + 0x613f, 0x10fb, + 0x6140, 0x3202, + 0x6148, 0x054b, + 0x6149, 0x320a, + 0x614a, 0x167b, + 0x614b, 0x2162, + 0x614c, 0x07da, + 0x614d, 0x320b, + 0x614e, 0x0d30, + 0x614f, 0x320c, + 0x6151, 0x0d1e, + 0x6152, 0x320e, + 0x6155, 0x0b20, + 0x6156, 0x3211, + 0x6158, 0x1e5e, + 0x6159, 0x3213, + 0x615a, 0x1e5d, + 0x615b, 0x3214, + 0x615d, 0x1a17, + 0x615e, 0x3216, + 0x615f, 0x23b7, + 0x6160, 0x3217, + 0x6162, 0x0aa4, + 0x6163, 0x1f2f, + 0x6164, 0x24df, + 0x6165, 0x3219, + 0x6167, 0x07f0, + 0x6168, 0x093b, + 0x6169, 0x321b, + 0x616a, 0x23b2, + 0x616b, 0x214e, + 0x616c, 0x321c, + 0x616e, 0x2052, + 0x616f, 0x321e, + 0x6170, 0x0ece, + 0x6171, 0x321f, + 0x6173, 0x23bc, + 0x6174, 0x3221, + 0x6175, 0x167c, + 0x6176, 0x20eb, + 0x6177, 0x0943, + 0x6178, 0x3222, + 0x6182, 0x2232, + 0x6183, 0x322c, + 0x618a, 0x1e3f, + 0x618b, 0x0458, + 0x618c, 0x3233, + 0x618e, 0x113a, + 0x618f, 0x3235, + 0x6190, 0x201b, + 0x6191, 0x20bc, + 0x6192, 0x23be, + 0x6193, 0x3236, + 0x6194, 0x167e, + 0x6195, 0x3237, + 0x619a, 0x1eae, + 0x619b, 0x323c, + 0x619d, 0x1a19, + 0x619e, 0x323e, + 0x61a4, 0x1efb, + 0x61a5, 0x3244, + 0x61a7, 0x167f, + 0x61a8, 0x0760, + 0x61a9, 0x1a18, + 0x61aa, 0x3246, + 0x61ab, 0x2089, + 0x61ac, 0x167d, + 0x61ad, 0x3247, + 0x61ae, 0x23b1, + 0x61af, 0x3248, + 0x61b2, 0x21c4, + 0x61b3, 0x324b, + 0x61b6, 0x2214, + 0x61b7, 0x1680, + 0x61b8, 0x324e, + 0x61be, 0x076d, + 0x61bf, 0x3254, + 0x61c2, 0x05ed, + 0x61c3, 0x3257, + 0x61c7, 0x1fde, + 0x61c8, 0x0f83, + 0x61c9, 0x2223, + 0x61ca, 0x03ce, + 0x61cb, 0x1a1a, + 0x61cc, 0x23b6, + 0x61cd, 0x325b, + 0x61d1, 0x1a1b, + 0x61d2, 0x09ac, + 0x61d3, 0x325f, + 0x61d4, 0x1681, + 0x61d5, 0x3260, + 0x61de, 0x268c, + 0x61df, 0x24de, + 0x61e0, 0x3269, + 0x61e3, 0x24e0, + 0x61e4, 0x326c, + 0x61e6, 0x0b74, + 0x61e7, 0x326e, + 0x61e8, 0x23b8, + 0x61e9, 0x326f, + 0x61f2, 0x1e81, + 0x61f3, 0x3278, + 0x61f5, 0x1682, + 0x61f6, 0x1ffe, + 0x61f7, 0x1f51, + 0x61f8, 0x21e1, + 0x61f9, 0x327a, + 0x61fa, 0x23b0, + 0x61fb, 0x327b, + 0x61fc, 0x1fce, + 0x61fd, 0x327c, + 0x61fe, 0x211e, + 0x61ff, 0x13e0, + 0x6200, 0x2021, + 0x6201, 0x327d, + 0x6206, 0x1a1c, + 0x6207, 0x24e1, + 0x6208, 0x06e5, + 0x6209, 0x3282, + 0x620a, 0x0efb, + 0x620b, 0x18f9, + 0x620c, 0x0fb2, + 0x620d, 0x0d90, + 0x620e, 0x0cb1, + 0x620f, 0x0f24, + 0x6210, 0x04ee, + 0x6211, 0x0ee1, + 0x6212, 0x08b5, + 0x6213, 0x3283, + 0x6214, 0x24a3, + 0x6215, 0x169e, + 0x6216, 0x0807, + 0x6217, 0x18fa, + 0x6218, 0x115e, + 0x6219, 0x3284, + 0x621a, 0x0bfc, + 0x621b, 0x18fb, + 0x621c, 0x3285, + 0x621f, 0x18fc, + 0x6220, 0x3288, + 0x6221, 0x18fe, + 0x6222, 0x18fd, + 0x6223, 0x3289, + 0x6224, 0x1900, + 0x6225, 0x18ff, + 0x6226, 0x328a, + 0x6227, 0x24a4, + 0x6228, 0x328b, + 0x622a, 0x08a9, + 0x622b, 0x328d, + 0x622c, 0x1901, + 0x622d, 0x328e, + 0x622e, 0x0a65, + 0x622f, 0x328f, + 0x6230, 0x2273, + 0x6231, 0x3290, + 0x6232, 0x21b0, + 0x6233, 0x0544, + 0x6234, 0x057a, + 0x6235, 0x3291, + 0x6237, 0x07bc, + 0x6238, 0x3293, + 0x623d, 0x19f4, + 0x623e, 0x19f3, + 0x623f, 0x065c, + 0x6240, 0x0dee, + 0x6241, 0x044b, + 0x6242, 0x3298, + 0x6243, 0x19f5, + 0x6244, 0x3299, + 0x6247, 0x0d01, + 0x6248, 0x19f6, + 0x624a, 0x329c, + 0x624b, 0x0d6d, + 0x624c, 0x14ba, + 0x624d, 0x048c, + 0x624e, 0x113d, + 0x624f, 0x329d, + 0x6251, 0x0bea, + 0x6252, 0x03d2, + 0x6253, 0x0575, + 0x6254, 0x0cae, + 0x6255, 0x329f, + 0x6258, 0x0e81, + 0x6259, 0x32a2, + 0x625b, 0x0945, + 0x625c, 0x32a4, + 0x6263, 0x0968, + 0x6264, 0x32ab, + 0x6266, 0x0c21, + 0x6267, 0x11b3, + 0x6268, 0x32ad, + 0x6269, 0x0994, + 0x626a, 0x14bb, + 0x626b, 0x0ce1, + 0x626c, 0x1018, + 0x626d, 0x0b65, + 0x626e, 0x03f2, + 0x626f, 0x04db, + 0x6270, 0x0ca0, + 0x6271, 0x32ae, + 0x6273, 0x03ed, + 0x6274, 0x32b0, + 0x6276, 0x0693, + 0x6277, 0x32b2, + 0x6279, 0x0bbb, + 0x627a, 0x32b4, + 0x627c, 0x0632, + 0x627d, 0x32b6, + 0x627e, 0x1173, + 0x627f, 0x04f5, + 0x6280, 0x082f, + 0x6281, 0x32b7, + 0x6284, 0x04d2, + 0x6285, 0x32ba, + 0x6289, 0x0920, + 0x628a, 0x03dc, + 0x628b, 0x32be, + 0x6291, 0x105d, + 0x6292, 0x0d7a, + 0x6293, 0x1202, + 0x6294, 0x32c4, + 0x6295, 0x0e67, + 0x6296, 0x05f5, + 0x6297, 0x0946, + 0x6298, 0x117c, + 0x6299, 0x32c5, + 0x629a, 0x06a2, + 0x629b, 0x0b98, + 0x629c, 0x32c6, + 0x629f, 0x14bc, + 0x62a0, 0x0966, + 0x62a1, 0x0a7c, + 0x62a2, 0x0c3d, + 0x62a3, 0x32c9, + 0x62a4, 0x07b9, + 0x62a5, 0x0411, + 0x62a6, 0x32ca, + 0x62a8, 0x0bab, + 0x62a9, 0x32cc, + 0x62ab, 0x0bbc, + 0x62ac, 0x0dfa, + 0x62ad, 0x32ce, + 0x62b1, 0x0410, + 0x62b2, 0x32d2, + 0x62b5, 0x05b7, + 0x62b6, 0x32d5, + 0x62b9, 0x0b0b, + 0x62ba, 0x32d8, + 0x62bb, 0x14bd, + 0x62bc, 0x0fe3, + 0x62bd, 0x050e, + 0x62be, 0x32d9, + 0x62bf, 0x0af7, + 0x62c0, 0x32da, + 0x62c2, 0x0694, + 0x62c3, 0x32dc, + 0x62c4, 0x11f3, + 0x62c5, 0x0584, + 0x62c6, 0x04b7, + 0x62c7, 0x0b17, + 0x62c8, 0x0b4c, + 0x62c9, 0x0998, + 0x62ca, 0x14be, + 0x62cb, 0x32dd, + 0x62cc, 0x03f3, + 0x62cd, 0x0b85, + 0x62ce, 0x0a29, + 0x62cf, 0x32de, + 0x62d0, 0x072e, + 0x62d1, 0x32df, + 0x62d2, 0x090b, + 0x62d3, 0x0e89, + 0x62d4, 0x03d9, + 0x62d5, 0x32e0, + 0x62d6, 0x0e80, + 0x62d7, 0x14c0, + 0x62d8, 0x08ff, + 0x62d9, 0x121b, + 0x62da, 0x14bf, + 0x62db, 0x1171, + 0x62dc, 0x03e8, + 0x62dd, 0x32e1, + 0x62df, 0x0b45, + 0x62e0, 0x32e3, + 0x62e2, 0x0a4a, + 0x62e3, 0x0863, + 0x62e4, 0x32e5, + 0x62e5, 0x109a, + 0x62e6, 0x09a4, + 0x62e7, 0x0b62, + 0x62e8, 0x046d, + 0x62e9, 0x1134, + 0x62ea, 0x32e6, + 0x62ec, 0x0993, + 0x62ed, 0x0d5a, + 0x62ee, 0x14c1, + 0x62ef, 0x119d, + 0x62f0, 0x32e8, + 0x62f1, 0x0709, + 0x62f2, 0x32e9, + 0x62f3, 0x0c88, + 0x62f4, 0x0d9e, + 0x62f5, 0x32ea, + 0x62f6, 0x14c3, + 0x62f7, 0x094a, + 0x62f8, 0x32eb, + 0x62fc, 0x0bd3, + 0x62fd, 0x1204, + 0x62fe, 0x0d47, + 0x62ff, 0x0b26, + 0x6300, 0x32ef, + 0x6301, 0x04fb, + 0x6302, 0x072b, + 0x6303, 0x32f0, + 0x6307, 0x11b7, + 0x6308, 0x194e, + 0x6309, 0x03bf, + 0x630a, 0x32f4, + 0x630e, 0x0973, + 0x630f, 0x32f8, + 0x6311, 0x0e47, + 0x6312, 0x32fa, + 0x6316, 0x0e8b, + 0x6317, 0x32fe, + 0x631a, 0x11be, + 0x631b, 0x0a75, + 0x631c, 0x3301, + 0x631d, 0x0edd, + 0x631e, 0x0df5, + 0x631f, 0x0f79, + 0x6320, 0x0b36, + 0x6321, 0x0593, + 0x6322, 0x14c2, + 0x6323, 0x1196, + 0x6324, 0x082a, + 0x6325, 0x07e8, + 0x6326, 0x3302, + 0x6328, 0x03af, + 0x6329, 0x3304, + 0x632a, 0x0b73, + 0x632b, 0x056f, + 0x632c, 0x3305, + 0x632f, 0x1192, + 0x6330, 0x3308, + 0x6332, 0x194f, + 0x6333, 0x330a, + 0x6339, 0x14c4, + 0x633a, 0x0e57, + 0x633b, 0x3310, + 0x633d, 0x0e9d, + 0x633e, 0x21d1, + 0x633f, 0x3312, + 0x6342, 0x0ef5, + 0x6343, 0x14c6, + 0x6344, 0x3315, + 0x6345, 0x0e62, + 0x6346, 0x0991, + 0x6347, 0x3316, + 0x6349, 0x121a, + 0x634a, 0x3318, + 0x634b, 0x14c5, + 0x634c, 0x03d1, + 0x634d, 0x076b, + 0x634e, 0x0d0c, + 0x634f, 0x0b56, + 0x6350, 0x0917, + 0x6351, 0x3319, + 0x6355, 0x047d, + 0x6356, 0x331d, + 0x635e, 0x09b7, + 0x635f, 0x0de5, + 0x6360, 0x3325, + 0x6361, 0x0864, + 0x6362, 0x07d0, + 0x6363, 0x0598, + 0x6364, 0x3326, + 0x6367, 0x0bb6, + 0x6368, 0x211c, + 0x6369, 0x14d0, + 0x636a, 0x3329, + 0x636b, 0x235d, + 0x636c, 0x332a, + 0x636d, 0x14cd, + 0x636e, 0x090c, + 0x636f, 0x332b, + 0x6371, 0x14c9, + 0x6372, 0x2682, + 0x6373, 0x332d, + 0x6376, 0x053a, + 0x6377, 0x08ae, + 0x6378, 0x3330, + 0x637a, 0x14ca, + 0x637b, 0x0b50, + 0x637c, 0x3332, + 0x6380, 0x0f33, + 0x6381, 0x3336, + 0x6382, 0x05c1, + 0x6383, 0x210d, + 0x6384, 0x205a, + 0x6385, 0x3337, + 0x6387, 0x061d, + 0x6388, 0x0d71, + 0x6389, 0x05d5, + 0x638a, 0x14cf, + 0x638b, 0x3339, + 0x638c, 0x1167, + 0x638d, 0x333a, + 0x638e, 0x14cb, + 0x638f, 0x0e20, + 0x6390, 0x0c1d, + 0x6391, 0x333b, + 0x6392, 0x0b86, + 0x6393, 0x333c, + 0x6396, 0x103b, + 0x6397, 0x333f, + 0x6398, 0x0921, + 0x6399, 0x3340, + 0x63a0, 0x0a7a, + 0x63a1, 0x3347, + 0x63a2, 0x0e10, + 0x63a3, 0x04dd, + 0x63a4, 0x3348, + 0x63a5, 0x08a4, + 0x63a6, 0x3349, + 0x63a7, 0x0965, + 0x63a8, 0x0e77, + 0x63a9, 0x1003, + 0x63aa, 0x056e, + 0x63ab, 0x334a, + 0x63ac, 0x14ce, + 0x63ad, 0x14c7, + 0x63ae, 0x14d1, + 0x63af, 0x334b, + 0x63b0, 0x1950, + 0x63b1, 0x334c, + 0x63b3, 0x0a57, + 0x63b4, 0x14cc, + 0x63b5, 0x334e, + 0x63b7, 0x11bf, + 0x63b8, 0x0588, + 0x63b9, 0x3350, + 0x63ba, 0x04bb, + 0x63bb, 0x3351, + 0x63bc, 0x14d2, + 0x63bd, 0x3352, + 0x63be, 0x14dc, + 0x63bf, 0x3353, + 0x63c0, 0x1f8d, + 0x63c1, 0x3354, + 0x63c4, 0x14d7, + 0x63c5, 0x3357, + 0x63c6, 0x14db, + 0x63c7, 0x3358, + 0x63c9, 0x0cbb, + 0x63ca, 0x335a, + 0x63cd, 0x123e, + 0x63ce, 0x14d9, + 0x63cf, 0x0aed, + 0x63d0, 0x0e34, + 0x63d1, 0x335d, + 0x63d2, 0x04ac, + 0x63d3, 0x335e, + 0x63d6, 0x1045, + 0x63d7, 0x3361, + 0x63da, 0x21ff, + 0x63db, 0x3364, + 0x63de, 0x14d8, + 0x63df, 0x3367, + 0x63e0, 0x14d5, + 0x63e1, 0x0ee4, + 0x63e2, 0x3368, + 0x63e3, 0x052a, + 0x63e4, 0x3369, + 0x63e9, 0x0938, + 0x63ea, 0x08ed, + 0x63eb, 0x336e, + 0x63ed, 0x08a3, + 0x63ee, 0x1f58, + 0x63ef, 0x3370, + 0x63f2, 0x14d3, + 0x63f3, 0x3373, + 0x63f4, 0x10f1, + 0x63f5, 0x3374, + 0x63f6, 0x14c8, + 0x63f7, 0x3375, + 0x63f8, 0x14d4, + 0x63f9, 0x3376, + 0x63fd, 0x09aa, + 0x63fe, 0x337a, + 0x63ff, 0x14d6, + 0x6400, 0x04ba, + 0x6401, 0x06e4, + 0x6402, 0x0a4e, + 0x6403, 0x337b, + 0x6405, 0x0892, + 0x6406, 0x337d, + 0x640b, 0x14df, + 0x640c, 0x14e2, + 0x640d, 0x215b, + 0x640e, 0x3382, + 0x640f, 0x0472, + 0x6410, 0x0527, + 0x6411, 0x3383, + 0x6413, 0x056d, + 0x6414, 0x0cdf, + 0x6415, 0x3385, + 0x6417, 0x1eb6, + 0x6418, 0x3387, + 0x641b, 0x14e0, + 0x641c, 0x0dc6, + 0x641d, 0x338a, + 0x641e, 0x06de, + 0x641f, 0x338b, + 0x6420, 0x14e1, + 0x6421, 0x14e4, + 0x6422, 0x338c, + 0x6426, 0x14e3, + 0x6427, 0x3390, + 0x642a, 0x0e15, + 0x642b, 0x3393, + 0x642c, 0x03ec, + 0x642d, 0x0571, + 0x642e, 0x3394, + 0x6434, 0x1736, + 0x6435, 0x339a, + 0x6436, 0x20db, + 0x6437, 0x339b, + 0x643a, 0x0f7a, + 0x643b, 0x339e, + 0x643d, 0x04b2, + 0x643e, 0x33a0, + 0x643f, 0x1951, + 0x6440, 0x33a1, + 0x6441, 0x14de, + 0x6442, 0x33a2, + 0x6444, 0x0d1c, + 0x6445, 0x14dd, + 0x6446, 0x03e5, + 0x6447, 0x1028, + 0x6448, 0x0460, + 0x6449, 0x33a4, + 0x644a, 0x0e02, + 0x644b, 0x33a5, + 0x6451, 0x2360, + 0x6452, 0x14da, + 0x6453, 0x33ab, + 0x6454, 0x0d99, + 0x6455, 0x33ac, + 0x6458, 0x114b, + 0x6459, 0x33af, + 0x645c, 0x2361, + 0x645d, 0x33b2, + 0x645e, 0x14e5, + 0x645f, 0x2040, + 0x6460, 0x33b3, + 0x6467, 0x0560, + 0x6468, 0x33ba, + 0x6469, 0x0b09, + 0x646a, 0x33bb, + 0x646d, 0x14e7, + 0x646e, 0x33be, + 0x646f, 0x228e, + 0x6470, 0x33bf, + 0x6473, 0x1fdf, + 0x6474, 0x33c2, + 0x6476, 0x235e, + 0x6477, 0x33c4, + 0x6478, 0x0b03, + 0x647a, 0x14e9, + 0x647b, 0x1e6a, + 0x647c, 0x33c5, + 0x6482, 0x0a15, + 0x6483, 0x33cb, + 0x6484, 0x14e6, + 0x6485, 0x091e, + 0x6486, 0x33cc, + 0x6487, 0x0bd1, + 0x6488, 0x2002, + 0x6489, 0x33cd, + 0x6491, 0x04ea, + 0x6492, 0x0cd1, + 0x6493, 0x2093, + 0x6494, 0x33d5, + 0x6495, 0x0daf, + 0x6496, 0x14e8, + 0x6497, 0x33d6, + 0x6499, 0x14ec, + 0x649a, 0x33d8, + 0x649e, 0x120f, + 0x649f, 0x235f, + 0x64a0, 0x33dc, + 0x64a3, 0x1eac, + 0x64a4, 0x04dc, + 0x64a5, 0x1e54, + 0x64a6, 0x33df, + 0x64a9, 0x0a0c, + 0x64aa, 0x33e2, + 0x64ab, 0x1f08, + 0x64ac, 0x0c48, + 0x64ad, 0x046c, + 0x64ae, 0x056c, + 0x64af, 0x33e3, + 0x64b0, 0x1208, + 0x64b1, 0x33e4, + 0x64b2, 0x20c0, + 0x64b3, 0x2362, + 0x64b4, 0x33e5, + 0x64b5, 0x0b4f, + 0x64b6, 0x33e6, + 0x64b7, 0x14ea, + 0x64b9, 0x33e7, + 0x64ba, 0x14ed, + 0x64bb, 0x2160, + 0x64bc, 0x076a, + 0x64bd, 0x33e8, + 0x64be, 0x219d, + 0x64bf, 0x1f8e, + 0x64c0, 0x14ee, + 0x64c1, 0x222d, + 0x64c2, 0x09c9, + 0x64c3, 0x33e9, + 0x64c4, 0x2047, + 0x64c5, 0x0cfc, + 0x64c6, 0x33ea, + 0x64c7, 0x2262, + 0x64c8, 0x33eb, + 0x64ca, 0x1f67, + 0x64cb, 0x1eb2, + 0x64cc, 0x33ed, + 0x64cd, 0x04a0, + 0x64ce, 0x0c63, + 0x64cf, 0x33ee, + 0x64d0, 0x14ef, + 0x64d1, 0x33ef, + 0x64d2, 0x0c59, + 0x64d3, 0x33f0, + 0x64d4, 0x1ea9, + 0x64d5, 0x33f1, + 0x64d7, 0x14f0, + 0x64d8, 0x1952, + 0x64d9, 0x33f3, + 0x64da, 0x1fcc, + 0x64db, 0x33f4, + 0x64de, 0x0dc8, + 0x64df, 0x33f7, + 0x64e0, 0x1f72, + 0x64e1, 0x33f8, + 0x64e2, 0x14f2, + 0x64e3, 0x33f9, + 0x64e4, 0x14f1, + 0x64e5, 0x33fa, + 0x64e6, 0x0488, + 0x64e7, 0x33fb, + 0x64ec, 0x2098, + 0x64ed, 0x3400, + 0x64ef, 0x1e52, + 0x64f0, 0x20a4, + 0x64f1, 0x1f1c, + 0x64f2, 0x228f, + 0x64f3, 0x3402, + 0x64f4, 0x1fed, + 0x64f5, 0x3403, + 0x64f7, 0x2365, + 0x64f8, 0x3405, + 0x64fa, 0x1e2d, + 0x64fb, 0x2152, + 0x64fc, 0x2366, + 0x64fd, 0x3407, + 0x64fe, 0x20fa, + 0x64ff, 0x3408, + 0x6500, 0x0b8b, + 0x6501, 0x3409, + 0x6504, 0x2363, + 0x6505, 0x340c, + 0x6506, 0x209a, + 0x6507, 0x340d, + 0x6509, 0x14f3, + 0x650a, 0x340f, + 0x650f, 0x203c, + 0x6510, 0x3414, + 0x6512, 0x111f, + 0x6513, 0x3416, + 0x6514, 0x1ff6, + 0x6515, 0x3417, + 0x6516, 0x2364, + 0x6517, 0x3418, + 0x6518, 0x0c9c, + 0x6519, 0x1e69, + 0x651a, 0x3419, + 0x651b, 0x2367, + 0x651c, 0x341a, + 0x651d, 0x211d, + 0x651e, 0x341b, + 0x6522, 0x2259, + 0x6523, 0x2056, + 0x6524, 0x2163, + 0x6525, 0x14f4, + 0x6526, 0x341f, + 0x652a, 0x1fa9, + 0x652b, 0x091f, + 0x652c, 0x1ffc, + 0x652d, 0x3423, + 0x652e, 0x14f5, + 0x652f, 0x11a6, + 0x6530, 0x3424, + 0x6534, 0x1909, + 0x6535, 0x1966, + 0x6536, 0x0d6c, + 0x6537, 0x3428, + 0x6538, 0x12b2, + 0x6539, 0x06bf, + 0x653a, 0x3429, + 0x653b, 0x06fe, + 0x653c, 0x342a, + 0x653e, 0x0662, + 0x653f, 0x119f, + 0x6540, 0x342c, + 0x6545, 0x0723, + 0x6546, 0x3431, + 0x6548, 0x0f72, + 0x6549, 0x1ccb, + 0x654a, 0x3433, + 0x654c, 0x05b1, + 0x654d, 0x3435, + 0x654f, 0x0af9, + 0x6550, 0x3437, + 0x6551, 0x08f7, + 0x6552, 0x3438, + 0x6555, 0x1967, + 0x6556, 0x03c8, + 0x6557, 0x1e2e, + 0x6558, 0x343b, + 0x6559, 0x089d, + 0x655a, 0x343c, + 0x655b, 0x09fb, + 0x655c, 0x343d, + 0x655d, 0x043f, + 0x655e, 0x04cd, + 0x655f, 0x343e, + 0x6562, 0x06cd, + 0x6563, 0x0cdb, + 0x6564, 0x3441, + 0x6566, 0x0617, + 0x6567, 0x3443, + 0x656b, 0x1968, + 0x656c, 0x08e3, + 0x656d, 0x3447, + 0x6570, 0x0d94, + 0x6571, 0x344a, + 0x6572, 0x0c40, + 0x6573, 0x344b, + 0x6574, 0x119c, + 0x6575, 0x1ebc, + 0x6576, 0x344c, + 0x6577, 0x0690, + 0x6578, 0x2142, + 0x6579, 0x344d, + 0x6582, 0x201e, + 0x6583, 0x1e43, + 0x6584, 0x3456, + 0x6587, 0x0ed3, + 0x6588, 0x3459, + 0x658b, 0x114c, + 0x658c, 0x045c, + 0x658d, 0x345c, + 0x6590, 0x19c1, + 0x6591, 0x03ea, + 0x6592, 0x345f, + 0x6593, 0x19c3, + 0x6594, 0x3460, + 0x6595, 0x24d4, + 0x6596, 0x3461, + 0x6597, 0x05f6, + 0x6598, 0x3462, + 0x6599, 0x0a18, + 0x659a, 0x3463, + 0x659b, 0x1d56, + 0x659c, 0x0f7c, + 0x659d, 0x3464, + 0x659f, 0x1186, + 0x65a0, 0x3466, + 0x65a1, 0x0ee2, + 0x65a2, 0x3467, + 0x65a4, 0x08c0, + 0x65a5, 0x0507, + 0x65a6, 0x3469, + 0x65a7, 0x06a6, + 0x65a8, 0x346a, + 0x65a9, 0x1157, + 0x65aa, 0x346b, + 0x65ab, 0x1a29, + 0x65ac, 0x226f, + 0x65ad, 0x060e, + 0x65ae, 0x346c, + 0x65af, 0x0dae, + 0x65b0, 0x0f8d, + 0x65b1, 0x346d, + 0x65b7, 0x1ed7, + 0x65b8, 0x3473, + 0x65b9, 0x065a, + 0x65ba, 0x3474, + 0x65bc, 0x19c4, + 0x65bd, 0x0d40, + 0x65be, 0x3476, + 0x65c1, 0x0b95, + 0x65c2, 0x3479, + 0x65c3, 0x19c7, + 0x65c4, 0x19c6, + 0x65c5, 0x0a6a, + 0x65c6, 0x19c5, + 0x65c7, 0x347a, + 0x65cb, 0x0fc8, + 0x65cc, 0x19c8, + 0x65cd, 0x347e, + 0x65ce, 0x19c9, + 0x65cf, 0x1242, + 0x65d0, 0x347f, + 0x65d2, 0x19ca, + 0x65d3, 0x3481, + 0x65d6, 0x19cb, + 0x65d7, 0x0c0b, + 0x65d8, 0x3484, + 0x65e0, 0x0eed, + 0x65e1, 0x348c, + 0x65e2, 0x083b, + 0x65e3, 0x348d, + 0x65e5, 0x0cb0, + 0x65e6, 0x058a, + 0x65e7, 0x08f8, + 0x65e8, 0x11bb, + 0x65e9, 0x112a, + 0x65ea, 0x348f, + 0x65ec, 0x0fd7, + 0x65ed, 0x0fbc, + 0x65ee, 0x190a, + 0x65f1, 0x076c, + 0x65f2, 0x3491, + 0x65f6, 0x0d48, + 0x65f7, 0x0982, + 0x65f8, 0x3495, + 0x65fa, 0x0eab, + 0x65fb, 0x3497, + 0x6600, 0x1912, + 0x6601, 0x349c, + 0x6602, 0x03c5, + 0x6603, 0x1910, + 0x6604, 0x349d, + 0x6606, 0x0990, + 0x6607, 0x349f, + 0x660a, 0x190d, + 0x660b, 0x34a2, + 0x660c, 0x04c4, + 0x660d, 0x34a3, + 0x660e, 0x0afc, + 0x660f, 0x07fd, + 0x6610, 0x34a4, + 0x6613, 0x105e, + 0x6614, 0x0f03, + 0x6615, 0x1911, + 0x6616, 0x34a7, + 0x6619, 0x190e, + 0x661a, 0x34aa, + 0x661d, 0x1915, + 0x661e, 0x34ad, + 0x661f, 0x0f92, + 0x6620, 0x1098, + 0x6621, 0x34ae, + 0x6625, 0x053d, + 0x6626, 0x34b2, + 0x6627, 0x0ac6, + 0x6628, 0x124f, + 0x6629, 0x34b3, + 0x662d, 0x1172, + 0x662e, 0x34b7, + 0x662f, 0x0d5e, + 0x6630, 0x34b8, + 0x6631, 0x1917, + 0x6632, 0x34b9, + 0x6634, 0x1916, + 0x6635, 0x1919, + 0x6636, 0x1918, + 0x6637, 0x34bb, + 0x663c, 0x11e6, + 0x663d, 0x34c0, + 0x663e, 0x0f41, + 0x663f, 0x34c1, + 0x6641, 0x191d, + 0x6642, 0x212d, + 0x6643, 0x07e3, + 0x6644, 0x34c3, + 0x664b, 0x08cb, + 0x664c, 0x0d07, + 0x664d, 0x34ca, + 0x664f, 0x191e, + 0x6650, 0x34cc, + 0x6652, 0x0cf2, + 0x6653, 0x0f6b, + 0x6654, 0x191c, + 0x6655, 0x1111, + 0x6656, 0x191f, + 0x6657, 0x1921, + 0x6658, 0x34ce, + 0x665a, 0x0e9e, + 0x665b, 0x34d0, + 0x665d, 0x229b, + 0x665e, 0x34d2, + 0x665f, 0x191b, + 0x6660, 0x34d3, + 0x6661, 0x1920, + 0x6662, 0x34d4, + 0x6664, 0x0efd, + 0x6665, 0x34d6, + 0x6666, 0x07f3, + 0x6667, 0x34d7, + 0x6668, 0x04e4, + 0x6669, 0x34d8, + 0x666e, 0x0bf4, + 0x666f, 0x08df, + 0x6670, 0x0f09, + 0x6671, 0x34dd, + 0x6674, 0x0c64, + 0x6675, 0x34e0, + 0x6676, 0x08d6, + 0x6677, 0x1922, + 0x6678, 0x34e1, + 0x667a, 0x11c6, + 0x667b, 0x34e3, + 0x667e, 0x0a09, + 0x667f, 0x34e6, + 0x6682, 0x1120, + 0x6683, 0x34e9, + 0x6684, 0x1923, + 0x6685, 0x34ea, + 0x6687, 0x0f2b, + 0x6688, 0x2256, + 0x6689, 0x24a8, + 0x668a, 0x34ec, + 0x668c, 0x1924, + 0x668d, 0x34ee, + 0x6691, 0x0d85, + 0x6692, 0x34f2, + 0x6696, 0x0b70, + 0x6697, 0x03c0, + 0x6698, 0x34f6, + 0x669d, 0x1926, + 0x669e, 0x34fb, + 0x66a2, 0x1e79, + 0x66a3, 0x34ff, + 0x66a7, 0x1925, + 0x66a8, 0x1cdd, + 0x66a9, 0x3503, + 0x66ab, 0x225a, + 0x66ac, 0x3505, + 0x66ae, 0x0b1d, + 0x66af, 0x3507, + 0x66b4, 0x0412, + 0x66b5, 0x350c, + 0x66b9, 0x175b, + 0x66ba, 0x3510, + 0x66be, 0x1927, + 0x66bf, 0x3514, + 0x66c4, 0x24a7, + 0x66c5, 0x3519, + 0x66c6, 0x2686, + 0x66c7, 0x24a6, + 0x66c8, 0x351a, + 0x66c9, 0x21ce, + 0x66ca, 0x351b, + 0x66d6, 0x24a9, + 0x66d7, 0x3527, + 0x66d9, 0x0d86, + 0x66da, 0x3529, + 0x66db, 0x1928, + 0x66dd, 0x0bf7, + 0x66de, 0x352a, + 0x66e0, 0x1fe7, + 0x66e1, 0x352c, + 0x66e6, 0x192a, + 0x66e7, 0x3531, + 0x66e9, 0x192b, + 0x66ea, 0x3533, + 0x66ec, 0x2112, + 0x66ed, 0x3535, + 0x66f0, 0x10fe, + 0x66f1, 0x3538, + 0x66f2, 0x0c77, + 0x66f3, 0x103e, + 0x66f4, 0x06f7, + 0x66f5, 0x3539, + 0x66f7, 0x1914, + 0x66f8, 0x213c, + 0x66f9, 0x04a3, + 0x66fa, 0x353b, + 0x66fc, 0x0aa3, + 0x66fd, 0x353d, + 0x66fe, 0x113b, + 0x66ff, 0x0e39, + 0x6700, 0x124b, + 0x6701, 0x353e, + 0x6703, 0x1f5c, + 0x6704, 0x3540, + 0x6708, 0x1105, + 0x6709, 0x10b5, + 0x670a, 0x1973, + 0x670b, 0x0bb4, + 0x670c, 0x3544, + 0x670d, 0x069b, + 0x670e, 0x3545, + 0x6710, 0x1984, + 0x6711, 0x3547, + 0x6714, 0x0dac, + 0x6715, 0x198e, + 0x6716, 0x354a, + 0x6717, 0x09b5, + 0x6718, 0x354b, + 0x671b, 0x0eac, + 0x671c, 0x354e, + 0x671d, 0x04d4, + 0x671e, 0x354f, + 0x671f, 0x0bf9, + 0x6720, 0x3550, + 0x6726, 0x19ac, + 0x6727, 0x24c4, + 0x6728, 0x0b21, + 0x6729, 0x3556, + 0x672a, 0x0ec3, + 0x672b, 0x0b0c, + 0x672c, 0x0427, + 0x672d, 0x1140, + 0x672e, 0x3557, + 0x672f, 0x0d8c, + 0x6730, 0x3558, + 0x6731, 0x11eb, + 0x6732, 0x3559, + 0x6734, 0x0bf2, + 0x6735, 0x0623, + 0x6736, 0x355b, + 0x673a, 0x080f, + 0x673b, 0x355f, + 0x673d, 0x0fab, + 0x673e, 0x3561, + 0x6740, 0x0cea, + 0x6741, 0x3563, + 0x6742, 0x1116, + 0x6743, 0x0c83, + 0x6744, 0x3564, + 0x6746, 0x06c6, + 0x6747, 0x3566, + 0x6748, 0x1854, + 0x6749, 0x0cf5, + 0x674a, 0x3567, + 0x674c, 0x1851, + 0x674d, 0x3569, + 0x674e, 0x09d9, + 0x674f, 0x0f9e, + 0x6750, 0x048b, + 0x6751, 0x0568, + 0x6752, 0x356a, + 0x6753, 0x1852, + 0x6754, 0x356b, + 0x6756, 0x1169, + 0x6757, 0x356d, + 0x675c, 0x0604, + 0x675d, 0x3572, + 0x675e, 0x1853, + 0x675f, 0x0d8f, + 0x6760, 0x06d7, + 0x6761, 0x0e48, + 0x6762, 0x3573, + 0x6765, 0x099f, + 0x6766, 0x3576, + 0x6768, 0x1017, + 0x6769, 0x1855, + 0x676a, 0x1858, + 0x676b, 0x3578, + 0x676d, 0x0773, + 0x676e, 0x357a, + 0x676f, 0x0416, + 0x6770, 0x08ad, + 0x6771, 0x1ecc, + 0x6772, 0x190f, + 0x6773, 0x1859, + 0x6774, 0x357b, + 0x6775, 0x185c, + 0x6776, 0x357c, + 0x6777, 0x1861, + 0x6778, 0x357d, + 0x677c, 0x1862, + 0x677d, 0x3581, + 0x677e, 0x0dbe, + 0x677f, 0x03f0, + 0x6780, 0x3582, + 0x6781, 0x081e, + 0x6782, 0x3583, + 0x6784, 0x0712, + 0x6785, 0x3585, + 0x6787, 0x1857, + 0x6788, 0x3587, + 0x6789, 0x0ea8, + 0x678a, 0x3588, + 0x678b, 0x1860, + 0x678c, 0x3589, + 0x6790, 0x0f05, + 0x6791, 0x358d, + 0x6795, 0x118e, + 0x6796, 0x3591, + 0x6797, 0x0a1f, + 0x6798, 0x185a, + 0x6799, 0x3592, + 0x679a, 0x0abb, + 0x679b, 0x3593, + 0x679c, 0x0754, + 0x679d, 0x11a5, + 0x679e, 0x185e, + 0x679f, 0x3594, + 0x67a2, 0x0d77, + 0x67a3, 0x1129, + 0x67a4, 0x3597, + 0x67a5, 0x1856, + 0x67a6, 0x3598, + 0x67a7, 0x185b, + 0x67a8, 0x185d, + 0x67a9, 0x3599, + 0x67aa, 0x0c36, + 0x67ab, 0x0680, + 0x67ac, 0x359a, + 0x67ad, 0x185f, + 0x67ae, 0x359b, + 0x67af, 0x096a, + 0x67b0, 0x1868, + 0x67b1, 0x359c, + 0x67b3, 0x186d, + 0x67b4, 0x359e, + 0x67b5, 0x186b, + 0x67b6, 0x084f, + 0x67b7, 0x0842, + 0x67b8, 0x1871, + 0x67b9, 0x359f, + 0x67c1, 0x1874, + 0x67c2, 0x35a7, + 0x67c3, 0x1870, + 0x67c4, 0x0463, + 0x67c5, 0x35a8, + 0x67cf, 0x03e3, + 0x67d0, 0x0b16, + 0x67d1, 0x06c7, + 0x67d2, 0x0c01, + 0x67d3, 0x0c99, + 0x67d4, 0x0cbc, + 0x67d5, 0x35b2, + 0x67d8, 0x1865, + 0x67d9, 0x186a, + 0x67da, 0x186c, + 0x67db, 0x35b5, + 0x67dc, 0x074a, + 0x67dd, 0x186e, + 0x67de, 0x1252, + 0x67df, 0x35b6, + 0x67e0, 0x0b5e, + 0x67e1, 0x35b7, + 0x67e2, 0x1872, + 0x67e3, 0x35b8, + 0x67e5, 0x04b0, + 0x67e6, 0x35ba, + 0x67e9, 0x1867, + 0x67ea, 0x35bd, + 0x67ec, 0x0860, + 0x67ed, 0x35bf, + 0x67ef, 0x094f, + 0x67f0, 0x1863, + 0x67f1, 0x11f8, + 0x67f2, 0x35c1, + 0x67f3, 0x0a41, + 0x67f4, 0x04b8, + 0x67f5, 0x35c2, + 0x67fd, 0x1875, + 0x67fe, 0x35ca, + 0x67ff, 0x0d58, + 0x6800, 0x186f, + 0x6801, 0x35cb, + 0x6805, 0x1145, + 0x6806, 0x35cf, + 0x6807, 0x0453, + 0x6808, 0x115c, + 0x6809, 0x1864, + 0x680a, 0x1866, + 0x680b, 0x05ef, + 0x680c, 0x1869, + 0x680d, 0x35d0, + 0x680e, 0x1873, + 0x680f, 0x09a3, + 0x6810, 0x35d1, + 0x6811, 0x0d8e, + 0x6812, 0x35d2, + 0x6813, 0x0d9d, + 0x6814, 0x35d3, + 0x6816, 0x0bfb, + 0x6817, 0x09e0, + 0x6818, 0x35d5, + 0x681d, 0x187f, + 0x681e, 0x35da, + 0x6821, 0x0f6e, + 0x6822, 0x35dd, + 0x6829, 0x1888, + 0x682a, 0x11e9, + 0x682b, 0x35e4, + 0x6832, 0x1876, + 0x6834, 0x35eb, + 0x6837, 0x1022, + 0x6838, 0x0782, + 0x6839, 0x06f4, + 0x683a, 0x35ee, + 0x683c, 0x06ec, + 0x683d, 0x1117, + 0x683e, 0x1885, + 0x683f, 0x35f0, + 0x6840, 0x1884, + 0x6841, 0x1882, + 0x6842, 0x0749, + 0x6843, 0x0e25, + 0x6844, 0x187c, + 0x6845, 0x0eb5, + 0x6846, 0x097f, + 0x6847, 0x35f1, + 0x6848, 0x03c3, + 0x6849, 0x1887, + 0x684a, 0x1886, + 0x684b, 0x35f2, + 0x684c, 0x121d, + 0x684d, 0x35f3, + 0x684e, 0x187a, + 0x684f, 0x35f4, + 0x6850, 0x0e5a, + 0x6851, 0x0cdc, + 0x6852, 0x35f5, + 0x6853, 0x07cd, + 0x6854, 0x08ac, + 0x6855, 0x1880, + 0x6856, 0x35f6, + 0x6860, 0x1878, + 0x6862, 0x187b, + 0x6863, 0x0596, + 0x6864, 0x187d, + 0x6865, 0x0c42, + 0x6866, 0x1881, + 0x6867, 0x1883, + 0x6868, 0x0881, + 0x6869, 0x120b, + 0x686a, 0x3600, + 0x686b, 0x188e, + 0x686c, 0x3601, + 0x6874, 0x188b, + 0x6875, 0x3609, + 0x6876, 0x0e61, + 0x6877, 0x188c, + 0x6878, 0x360a, + 0x6881, 0x0a03, + 0x6882, 0x3613, + 0x6883, 0x187e, + 0x6884, 0x3614, + 0x6885, 0x0abc, + 0x6886, 0x03fb, + 0x6887, 0x3615, + 0x688f, 0x188a, + 0x6890, 0x361d, + 0x6893, 0x188d, + 0x6894, 0x3620, + 0x6897, 0x06fc, + 0x6898, 0x246a, + 0x6899, 0x3623, + 0x689d, 0x2175, + 0x689e, 0x3627, + 0x689f, 0x246d, + 0x68a0, 0x3628, + 0x68a2, 0x0d0b, + 0x68a3, 0x362a, + 0x68a6, 0x0ad3, + 0x68a7, 0x0eef, + 0x68a8, 0x09d1, + 0x68a9, 0x362d, + 0x68ad, 0x0de8, + 0x68ae, 0x3631, + 0x68af, 0x0e30, + 0x68b0, 0x0f80, + 0x68b1, 0x3632, + 0x68b3, 0x0d78, + 0x68b4, 0x3634, + 0x68b5, 0x1889, + 0x68b6, 0x3635, + 0x68c0, 0x085f, + 0x68c1, 0x363f, + 0x68c2, 0x188f, + 0x68c3, 0x3640, + 0x68c9, 0x0ae3, + 0x68ca, 0x3646, + 0x68cb, 0x0c04, + 0x68cc, 0x3647, + 0x68cd, 0x0750, + 0x68ce, 0x3648, + 0x68d2, 0x03ff, + 0x68d3, 0x364c, + 0x68d5, 0x1235, + 0x68d6, 0x246b, + 0x68d7, 0x225f, + 0x68d8, 0x081f, + 0x68d9, 0x364e, + 0x68da, 0x0bb0, + 0x68db, 0x364f, + 0x68df, 0x1ece, + 0x68e0, 0x0e17, + 0x68e1, 0x3653, + 0x68e3, 0x189a, + 0x68e4, 0x3655, + 0x68e7, 0x2272, + 0x68e8, 0x3658, + 0x68ee, 0x0ce6, + 0x68ef, 0x365e, + 0x68f0, 0x1896, + 0x68f1, 0x09cd, + 0x68f2, 0x365f, + 0x68f5, 0x0950, + 0x68f6, 0x3662, + 0x68f9, 0x1894, + 0x68fa, 0x0730, + 0x68fb, 0x3665, + 0x68fc, 0x1891, + 0x68fd, 0x3666, + 0x6900, 0x3669, + 0x6901, 0x1898, + 0x6902, 0x366a, + 0x6905, 0x1055, + 0x6906, 0x366d, + 0x690b, 0x1897, + 0x690c, 0x3672, + 0x690d, 0x11b1, + 0x690e, 0x1212, + 0x690f, 0x2473, + 0x6910, 0x189b, + 0x6911, 0x3673, + 0x6912, 0x0888, + 0x6913, 0x3674, + 0x691f, 0x1892, + 0x6921, 0x3680, + 0x6924, 0x1895, + 0x6925, 0x3683, + 0x692d, 0x0e87, + 0x692e, 0x368b, + 0x6930, 0x1033, + 0x6931, 0x368d, + 0x6934, 0x18a6, + 0x6935, 0x3690, + 0x6939, 0x189d, + 0x693a, 0x3694, + 0x693d, 0x052d, + 0x693e, 0x3697, + 0x693f, 0x053e, + 0x6940, 0x3698, + 0x6942, 0x189f, + 0x6943, 0x369a, + 0x694a, 0x21fe, + 0x694b, 0x36a1, + 0x6953, 0x1efe, + 0x6954, 0x0f73, + 0x6955, 0x36a9, + 0x6957, 0x1899, + 0x6958, 0x36ab, + 0x695a, 0x0523, + 0x695b, 0x36ad, + 0x695d, 0x18a0, + 0x695e, 0x09ce, + 0x695f, 0x36af, + 0x6960, 0x189e, + 0x6961, 0x36b0, + 0x6963, 0x18ad, + 0x6964, 0x36b2, + 0x6966, 0x18ac, + 0x6967, 0x36b4, + 0x6968, 0x2475, + 0x6969, 0x36b5, + 0x696b, 0x18a2, + 0x696c, 0x36b7, + 0x696d, 0x220a, + 0x696e, 0x1890, + 0x696f, 0x36b8, + 0x6971, 0x189c, + 0x6972, 0x36ba, + 0x6975, 0x1f6f, + 0x6976, 0x36bd, + 0x6977, 0x0939, + 0x6978, 0x18a5, + 0x6979, 0x18ae, + 0x697a, 0x36be, + 0x697c, 0x0a4c, + 0x697d, 0x36c0, + 0x6980, 0x18a3, + 0x6981, 0x36c3, + 0x6982, 0x06c0, + 0x6983, 0x36c4, + 0x6984, 0x18a1, + 0x6985, 0x36c5, + 0x6986, 0x10c1, + 0x6987, 0x18a8, + 0x6989, 0x18ab, + 0x698a, 0x36c6, + 0x698d, 0x18bb, + 0x698e, 0x36c9, + 0x6994, 0x09b1, + 0x6995, 0x18b9, + 0x6996, 0x36cf, + 0x6998, 0x18a4, + 0x6999, 0x36d1, + 0x699b, 0x18af, + 0x699c, 0x03fc, + 0x699d, 0x36d3, + 0x69a7, 0x18b0, + 0x69a8, 0x1146, + 0x69a9, 0x36dd, + 0x69aa, 0x2468, + 0x69ab, 0x18b2, + 0x69ac, 0x36de, + 0x69ad, 0x18b3, + 0x69ae, 0x2100, + 0x69af, 0x36df, + 0x69b1, 0x18b5, + 0x69b2, 0x36e1, + 0x69b4, 0x0a3a, + 0x69b5, 0x36e3, + 0x69b7, 0x0c91, + 0x69b8, 0x36e5, + 0x69bb, 0x18b1, + 0x69bc, 0x36e8, + 0x69bf, 0x2476, + 0x69c0, 0x36eb, + 0x69c1, 0x18b6, + 0x69c2, 0x36ec, + 0x69ca, 0x18b7, + 0x69cb, 0x1f27, + 0x69cc, 0x18a7, + 0x69cd, 0x20d7, + 0x69ce, 0x18aa, + 0x69cf, 0x36f4, + 0x69d0, 0x07c6, + 0x69d1, 0x36f5, + 0x69d4, 0x18b4, + 0x69d5, 0x36f8, + 0x69db, 0x086a, + 0x69dc, 0x36fe, + 0x69df, 0x18b8, + 0x69e0, 0x18ba, + 0x69e1, 0x3701, + 0x69e7, 0x247c, + 0x69e8, 0x3707, + 0x69ed, 0x18be, + 0x69ee, 0x370c, + 0x69f2, 0x18c2, + 0x69f3, 0x1fa1, + 0x69f4, 0x3710, + 0x69fd, 0x04a2, + 0x69fe, 0x3719, + 0x69ff, 0x18bc, + 0x6a00, 0x371a, + 0x6a01, 0x22aa, + 0x6a02, 0x2005, + 0x6a03, 0x371b, + 0x6a05, 0x246c, + 0x6a06, 0x371d, + 0x6a0a, 0x064b, + 0x6a0b, 0x3721, + 0x6a13, 0x203e, + 0x6a14, 0x3729, + 0x6a17, 0x18bf, + 0x6a19, 0x1e4c, + 0x6a1a, 0x372c, + 0x6a1e, 0x213a, + 0x6a1f, 0x1162, + 0x6a20, 0x3730, + 0x6a21, 0x0b06, + 0x6a22, 0x3731, + 0x6a23, 0x2204, + 0x6a24, 0x3732, + 0x6a28, 0x18cc, + 0x6a29, 0x3736, + 0x6a2a, 0x0798, + 0x6a2b, 0x3737, + 0x6a2f, 0x18bd, + 0x6a30, 0x373b, + 0x6a31, 0x1088, + 0x6a32, 0x373c, + 0x6a35, 0x18c8, + 0x6a36, 0x373f, + 0x6a38, 0x20c3, + 0x6a39, 0x2140, + 0x6a3a, 0x2477, + 0x6a3b, 0x3741, + 0x6a3d, 0x18cb, + 0x6a3e, 0x18c4, + 0x6a3f, 0x3743, + 0x6a44, 0x18c3, + 0x6a45, 0x3748, + 0x6a47, 0x0c3e, + 0x6a48, 0x2474, + 0x6a49, 0x374a, + 0x6a4b, 0x20dd, + 0x6a4c, 0x374c, + 0x6a50, 0x18c6, + 0x6a51, 0x3750, + 0x6a58, 0x18cd, + 0x6a59, 0x04ed, + 0x6a5a, 0x3757, + 0x6a5b, 0x18c7, + 0x6a5c, 0x3758, + 0x6a5f, 0x1f68, + 0x6a60, 0x375b, + 0x6a61, 0x0f5d, + 0x6a62, 0x2185, + 0x6a63, 0x375c, + 0x6a65, 0x18c1, + 0x6a66, 0x375e, + 0x6a71, 0x051c, + 0x6a72, 0x3769, + 0x6a79, 0x18ca, + 0x6a7a, 0x3770, + 0x6a7c, 0x18ce, + 0x6a7d, 0x3772, + 0x6a80, 0x0e07, + 0x6a81, 0x3775, + 0x6a84, 0x0f1a, + 0x6a85, 0x3778, + 0x6a89, 0x2472, + 0x6a8a, 0x377c, + 0x6a8e, 0x18c9, + 0x6a8f, 0x3780, + 0x6a90, 0x18d0, + 0x6a91, 0x18cf, + 0x6a92, 0x3781, + 0x6a94, 0x1eb5, + 0x6a95, 0x3783, + 0x6a97, 0x18d2, + 0x6a98, 0x3785, + 0x6a9c, 0x2478, + 0x6a9d, 0x3789, + 0x6aa0, 0x18c5, + 0x6aa1, 0x378c, + 0x6aa2, 0x1f8b, + 0x6aa3, 0x2484, + 0x6aa4, 0x378d, + 0x6aa9, 0x18d1, + 0x6aaa, 0x3792, + 0x6aab, 0x18d3, + 0x6aac, 0x0acf, + 0x6aad, 0x3793, + 0x6aaf, 0x2699, + 0x6ab0, 0x3795, + 0x6ab3, 0x2482, + 0x6ab4, 0x3798, + 0x6ab8, 0x20a1, + 0x6ab9, 0x379c, + 0x6abb, 0x1f92, + 0x6abc, 0x379e, + 0x6ac3, 0x1f38, + 0x6ac4, 0x37a5, + 0x6ad3, 0x2485, + 0x6ad4, 0x37b4, + 0x6ada, 0x2480, + 0x6adb, 0x246e, + 0x6adc, 0x37ba, + 0x6add, 0x247b, + 0x6ade, 0x2486, + 0x6adf, 0x2471, + 0x6ae0, 0x37bb, + 0x6ae7, 0x2483, + 0x6ae8, 0x2470, + 0x6ae9, 0x37c2, + 0x6aea, 0x2469, + 0x6aeb, 0x37c3, + 0x6aec, 0x247f, + 0x6aed, 0x37c4, + 0x6af3, 0x246f, + 0x6af4, 0x37ca, + 0x6af8, 0x2481, + 0x6af9, 0x37ce, + 0x6afb, 0x2220, + 0x6afc, 0x37d0, + 0x6b00, 0x37d4, + 0x6b04, 0x1ff5, + 0x6b05, 0x37d8, + 0x6b0a, 0x20f4, + 0x6b0b, 0x37dd, + 0x6b0f, 0x247d, + 0x6b10, 0x37e1, + 0x6b12, 0x2479, + 0x6b13, 0x37e3, + 0x6b16, 0x247e, + 0x6b17, 0x37e6, + 0x6b1e, 0x247a, + 0x6b1f, 0x37ed, + 0x6b20, 0x0c34, + 0x6b21, 0x0551, + 0x6b22, 0x07cb, + 0x6b23, 0x0f8b, + 0x6b24, 0x19b1, + 0x6b25, 0x37ee, + 0x6b27, 0x0b78, + 0x6b28, 0x37f0, + 0x6b32, 0x10e0, + 0x6b33, 0x37fa, + 0x6b37, 0x19b2, + 0x6b38, 0x37fe, + 0x6b39, 0x19b3, + 0x6b3a, 0x0bfa, + 0x6b3b, 0x37ff, + 0x6b3d, 0x20e3, + 0x6b3e, 0x097b, + 0x6b3f, 0x3801, + 0x6b43, 0x19b4, + 0x6b44, 0x3805, + 0x6b46, 0x19b5, + 0x6b47, 0x0f75, + 0x6b48, 0x3807, + 0x6b49, 0x0c35, + 0x6b4a, 0x3808, + 0x6b4c, 0x06e3, + 0x6b4d, 0x380a, + 0x6b50, 0x20ad, + 0x6b51, 0x380d, + 0x6b59, 0x19b6, + 0x6b5a, 0x3815, + 0x6b5f, 0x24cb, + 0x6b60, 0x381a, + 0x6b61, 0x1f53, + 0x6b62, 0x11b8, + 0x6b63, 0x119e, + 0x6b64, 0x054e, + 0x6b65, 0x0484, + 0x6b66, 0x0ef3, + 0x6b67, 0x0c06, + 0x6b68, 0x381b, + 0x6b6a, 0x0e92, + 0x6b6b, 0x381d, + 0x6b72, 0x2159, + 0x6b73, 0x3824, + 0x6b77, 0x2013, + 0x6b78, 0x1f33, + 0x6b79, 0x0578, + 0x6b7a, 0x3828, + 0x6b7b, 0x0db5, + 0x6b7c, 0x0852, + 0x6b7d, 0x3829, + 0x6b81, 0x18d6, + 0x6b83, 0x1013, + 0x6b84, 0x18d9, + 0x6b85, 0x382d, + 0x6b86, 0x057c, + 0x6b87, 0x18d8, + 0x6b88, 0x382e, + 0x6b89, 0x0fdc, + 0x6b8a, 0x0d79, + 0x6b8b, 0x0497, + 0x6b8c, 0x382f, + 0x6b8d, 0x18dc, + 0x6b8e, 0x3830, + 0x6b92, 0x18da, + 0x6b94, 0x3834, + 0x6b96, 0x11b2, + 0x6b97, 0x3836, + 0x6b98, 0x1e5c, + 0x6b99, 0x3837, + 0x6b9a, 0x18dd, + 0x6b9c, 0x3838, + 0x6b9e, 0x2488, + 0x6b9f, 0x383a, + 0x6ba1, 0x18df, + 0x6ba2, 0x383c, + 0x6ba4, 0x2487, + 0x6ba5, 0x383e, + 0x6baa, 0x18e0, + 0x6bab, 0x248a, + 0x6bac, 0x3843, + 0x6bae, 0x2489, + 0x6baf, 0x248b, + 0x6bb0, 0x3845, + 0x6bb2, 0x1f83, + 0x6bb3, 0x19bd, + 0x6bb4, 0x0b7a, + 0x6bb5, 0x060d, + 0x6bb6, 0x3847, + 0x6bb7, 0x107a, + 0x6bb8, 0x3848, + 0x6bba, 0x210f, + 0x6bbb, 0x1fdb, + 0x6bbc, 0x384a, + 0x6bbf, 0x05cf, + 0x6bc0, 0x384d, + 0x6bc1, 0x07ee, + 0x6bc2, 0x19bf, + 0x6bc3, 0x384e, + 0x6bc5, 0x106a, + 0x6bc6, 0x20af, + 0x6bc7, 0x3850, + 0x6bcb, 0x0ef2, + 0x6bcc, 0x3854, + 0x6bcd, 0x0b1b, + 0x6bce, 0x3855, + 0x6bcf, 0x0ac4, + 0x6bd0, 0x3856, + 0x6bd2, 0x05fd, + 0x6bd3, 0x126f, + 0x6bd4, 0x0431, + 0x6bd5, 0x0438, + 0x6bd6, 0x043a, + 0x6bd7, 0x0bbf, + 0x6bd8, 0x3858, + 0x6bd9, 0x0439, + 0x6bda, 0x3859, + 0x6bdb, 0x0ab0, + 0x6bdc, 0x385a, + 0x6be1, 0x1152, + 0x6be2, 0x385f, + 0x6bea, 0x1954, + 0x6beb, 0x0778, + 0x6bec, 0x3867, + 0x6bef, 0x0e0d, + 0x6bf0, 0x386a, + 0x6bf3, 0x1955, + 0x6bf4, 0x386d, + 0x6bf5, 0x1957, + 0x6bf6, 0x386e, + 0x6bf9, 0x1958, + 0x6bfa, 0x3871, + 0x6bfd, 0x1956, + 0x6bfe, 0x3874, + 0x6bff, 0x24c0, + 0x6c00, 0x3875, + 0x6c05, 0x1959, + 0x6c06, 0x195b, + 0x6c07, 0x195a, + 0x6c08, 0x226d, + 0x6c09, 0x387a, + 0x6c0c, 0x24c1, + 0x6c0d, 0x195c, + 0x6c0e, 0x387d, + 0x6c0f, 0x0d66, + 0x6c10, 0x126b, + 0x6c11, 0x0af6, + 0x6c12, 0x387e, + 0x6c13, 0x0aaa, + 0x6c14, 0x0c17, + 0x6c15, 0x195d, + 0x6c16, 0x0b2d, + 0x6c17, 0x387f, + 0x6c18, 0x195e, + 0x6c1b, 0x0672, + 0x6c1c, 0x3880, + 0x6c1f, 0x0697, + 0x6c20, 0x3883, + 0x6c21, 0x1961, + 0x6c22, 0x0c5f, + 0x6c23, 0x20ca, + 0x6c24, 0x1963, + 0x6c25, 0x3884, + 0x6c26, 0x075b, + 0x6c27, 0x101e, + 0x6c28, 0x03bc, + 0x6c29, 0x1962, + 0x6c2a, 0x1964, + 0x6c2b, 0x20e7, + 0x6c2c, 0x24c2, + 0x6c2d, 0x3885, + 0x6c2e, 0x058b, + 0x6c2f, 0x0a6f, + 0x6c30, 0x0c65, + 0x6c31, 0x3886, + 0x6c32, 0x1965, + 0x6c33, 0x3887, + 0x6c34, 0x0da3, + 0x6c35, 0x169f, + 0x6c36, 0x3888, + 0x6c38, 0x10a5, + 0x6c39, 0x388a, + 0x6c3d, 0x12ef, + 0x6c3e, 0x388e, + 0x6c40, 0x0e52, + 0x6c41, 0x11ac, + 0x6c42, 0x0c70, + 0x6c43, 0x3890, + 0x6c46, 0x12f4, + 0x6c47, 0x07f8, + 0x6c48, 0x3893, + 0x6c49, 0x0771, + 0x6c4a, 0x16a2, + 0x6c4b, 0x3894, + 0x6c50, 0x0f18, + 0x6c51, 0x3899, + 0x6c54, 0x16a0, + 0x6c55, 0x0d00, + 0x6c56, 0x389c, + 0x6c57, 0x0770, + 0x6c58, 0x389d, + 0x6c5b, 0x0fdd, + 0x6c5c, 0x16a1, + 0x6c5d, 0x0cc5, + 0x6c5e, 0x0708, + 0x6c5f, 0x087e, + 0x6c60, 0x04fd, + 0x6c61, 0x0eea, + 0x6c62, 0x38a0, + 0x6c64, 0x0e13, + 0x6c65, 0x38a2, + 0x6c68, 0x16a8, + 0x6c6a, 0x0ea5, + 0x6c6b, 0x38a5, + 0x6c70, 0x0e00, + 0x6c71, 0x38aa, + 0x6c72, 0x0826, + 0x6c73, 0x38ab, + 0x6c74, 0x16aa, + 0x6c75, 0x38ac, + 0x6c76, 0x16ab, + 0x6c77, 0x38ad, + 0x6c79, 0x0fa5, + 0x6c7a, 0x38af, + 0x6c7d, 0x0c1a, + 0x6c7e, 0x0677, + 0x6c7f, 0x38b2, + 0x6c81, 0x0c5c, + 0x6c82, 0x1051, + 0x6c83, 0x0ee5, + 0x6c84, 0x38b4, + 0x6c85, 0x16a4, + 0x6c86, 0x16ac, + 0x6c87, 0x38b5, + 0x6c88, 0x0d2b, + 0x6c89, 0x04e6, + 0x6c8a, 0x38b6, + 0x6c8c, 0x16a7, + 0x6c8d, 0x38b8, + 0x6c8f, 0x0c02, + 0x6c90, 0x16a5, + 0x6c91, 0x38ba, + 0x6c93, 0x1a1f, + 0x6c94, 0x16a6, + 0x6c95, 0x38bc, + 0x6c99, 0x0cec, + 0x6c9a, 0x38c0, + 0x6c9b, 0x0ba7, + 0x6c9c, 0x38c1, + 0x6c9f, 0x070e, + 0x6ca0, 0x38c4, + 0x6ca1, 0x0ac0, + 0x6ca2, 0x38c5, + 0x6ca3, 0x16a3, + 0x6ca4, 0x0b7e, + 0x6ca5, 0x09ed, + 0x6ca6, 0x0a80, + 0x6ca7, 0x049e, + 0x6ca8, 0x38c6, + 0x6ca9, 0x16ad, + 0x6caa, 0x07bb, + 0x6cab, 0x0b10, + 0x6cac, 0x38c7, + 0x6cad, 0x16b0, + 0x6cae, 0x0909, + 0x6caf, 0x38c8, + 0x6cb1, 0x16bb, + 0x6cb2, 0x16b5, + 0x6cb3, 0x078a, + 0x6cb4, 0x38ca, + 0x6cb8, 0x066d, + 0x6cb9, 0x10b2, + 0x6cba, 0x38ce, + 0x6cbb, 0x11cd, + 0x6cbc, 0x1174, + 0x6cbd, 0x071a, + 0x6cbe, 0x1155, + 0x6cbf, 0x1001, + 0x6cc0, 0x38cf, + 0x6cc4, 0x0f84, + 0x6cc5, 0x0c73, + 0x6cc6, 0x38d3, + 0x6cc9, 0x0c85, + 0x6cca, 0x047b, + 0x6ccb, 0x38d6, + 0x6ccc, 0x0adf, + 0x6ccd, 0x38d7, + 0x6cd0, 0x16ae, + 0x6cd1, 0x38da, + 0x6cd3, 0x16bc, + 0x6cd4, 0x16af, + 0x6cd5, 0x0645, + 0x6cd6, 0x16b7, + 0x6cd7, 0x16b4, + 0x6cd8, 0x38dc, + 0x6cdb, 0x0657, + 0x6cdc, 0x38df, + 0x6cde, 0x0b63, + 0x6cdf, 0x38e1, + 0x6ce0, 0x16b6, + 0x6ce1, 0x0b9e, + 0x6ce2, 0x046f, + 0x6ce3, 0x0c1b, + 0x6ce4, 0x38e2, + 0x6ce5, 0x0b43, + 0x6ce6, 0x38e3, + 0x6ce8, 0x11ff, + 0x6ce9, 0x38e5, + 0x6cea, 0x09cc, + 0x6ceb, 0x16b9, + 0x6cec, 0x38e6, + 0x6cee, 0x16ba, + 0x6cef, 0x16bd, + 0x6cf0, 0x0dfc, + 0x6cf1, 0x16b3, + 0x6cf2, 0x38e8, + 0x6cf3, 0x10a3, + 0x6cf4, 0x38e9, + 0x6cf5, 0x042c, + 0x6cf6, 0x1a20, + 0x6cf7, 0x16b1, + 0x6cf9, 0x38ea, + 0x6cfa, 0x16b8, + 0x6cfb, 0x0f85, + 0x6cfc, 0x0be2, + 0x6cfd, 0x1136, + 0x6cfe, 0x16be, + 0x6cff, 0x38eb, + 0x6d00, 0x38ec, + 0x6d01, 0x08b1, + 0x6d02, 0x38ed, + 0x6d04, 0x16c5, + 0x6d05, 0x38ef, + 0x6d07, 0x16c4, + 0x6d08, 0x38f1, + 0x6d0b, 0x101c, + 0x6d0c, 0x16c1, + 0x6d0d, 0x38f4, + 0x6d0e, 0x16c7, + 0x6d0f, 0x38f5, + 0x6d12, 0x0cd2, + 0x6d13, 0x38f8, + 0x6d17, 0x0f21, + 0x6d18, 0x38fc, + 0x6d19, 0x16c6, + 0x6d1a, 0x16cc, + 0x6d1b, 0x0a8c, + 0x6d1c, 0x38fd, + 0x6d1e, 0x05f3, + 0x6d1f, 0x38ff, + 0x6d25, 0x08c3, + 0x6d26, 0x3905, + 0x6d27, 0x16c0, + 0x6d28, 0x3906, + 0x6d2a, 0x07a0, + 0x6d2b, 0x16c8, + 0x6d2c, 0x3908, + 0x6d2e, 0x16ca, + 0x6d2f, 0x390a, + 0x6d31, 0x063c, + 0x6d32, 0x11dd, + 0x6d33, 0x16d0, + 0x6d34, 0x390c, + 0x6d35, 0x16cb, + 0x6d36, 0x390d, + 0x6d39, 0x16bf, + 0x6d3a, 0x3910, + 0x6d3b, 0x0803, + 0x6d3c, 0x0e8e, + 0x6d3d, 0x0c1f, + 0x6d3e, 0x0b8a, + 0x6d3f, 0x3911, + 0x6d41, 0x0a40, + 0x6d42, 0x3913, + 0x6d43, 0x16c2, + 0x6d44, 0x3914, + 0x6d45, 0x0c30, + 0x6d46, 0x087d, + 0x6d47, 0x088e, + 0x6d48, 0x16c3, + 0x6d49, 0x3915, + 0x6d4a, 0x1224, + 0x6d4b, 0x04a9, + 0x6d4c, 0x3916, + 0x6d4d, 0x16c9, + 0x6d4e, 0x0836, + 0x6d4f, 0x16cd, + 0x6d50, 0x3917, + 0x6d51, 0x0800, + 0x6d52, 0x16ce, + 0x6d53, 0x0b69, + 0x6d54, 0x16cf, + 0x6d55, 0x3918, + 0x6d59, 0x1184, + 0x6d5a, 0x0930, + 0x6d5b, 0x391c, + 0x6d5c, 0x16d8, + 0x6d5d, 0x391d, + 0x6d5e, 0x16d5, + 0x6d5f, 0x391e, + 0x6d60, 0x16d9, + 0x6d61, 0x391f, + 0x6d63, 0x16db, + 0x6d64, 0x3921, + 0x6d66, 0x0bf5, + 0x6d67, 0x3923, + 0x6d69, 0x077d, + 0x6d6a, 0x09b6, + 0x6d6b, 0x3925, + 0x6d6e, 0x069c, + 0x6d6f, 0x16d2, + 0x6d70, 0x3928, + 0x6d74, 0x10e4, + 0x6d75, 0x392c, + 0x6d77, 0x075a, + 0x6d78, 0x08cf, + 0x6d79, 0x23dc, + 0x6d7a, 0x392e, + 0x6d7c, 0x16da, + 0x6d7d, 0x3930, + 0x6d82, 0x0e70, + 0x6d83, 0x3935, + 0x6d85, 0x0b5c, + 0x6d86, 0x3937, + 0x6d87, 0x23db, + 0x6d88, 0x0f68, + 0x6d89, 0x0d1f, + 0x6d8a, 0x3938, + 0x6d8c, 0x10a4, + 0x6d8d, 0x393a, + 0x6d8e, 0x0f3e, + 0x6d8f, 0x393b, + 0x6d91, 0x16d1, + 0x6d92, 0x393d, + 0x6d93, 0x16d6, + 0x6d95, 0x0e3c, + 0x6d96, 0x393e, + 0x6d9b, 0x0e21, + 0x6d9c, 0x3943, + 0x6d9d, 0x09bf, + 0x6d9e, 0x16d3, + 0x6d9f, 0x09f9, + 0x6da0, 0x16d4, + 0x6da1, 0x0edf, + 0x6da2, 0x3944, + 0x6da3, 0x07d6, + 0x6da4, 0x05b4, + 0x6da5, 0x3945, + 0x6da6, 0x0cce, + 0x6da7, 0x0878, + 0x6da8, 0x1168, + 0x6da9, 0x0ce5, + 0x6daa, 0x069d, + 0x6dab, 0x16e8, + 0x6dac, 0x3946, + 0x6dae, 0x16ea, + 0x6daf, 0x0fed, + 0x6db0, 0x3948, + 0x6db2, 0x1041, + 0x6db3, 0x394a, + 0x6db5, 0x0764, + 0x6db6, 0x394c, + 0x6db8, 0x078b, + 0x6db9, 0x394e, + 0x6dbf, 0x16e1, + 0x6dc0, 0x05ce, + 0x6dc1, 0x3954, + 0x6dc4, 0x122a, + 0x6dc5, 0x16de, + 0x6dc6, 0x0f6a, + 0x6dc7, 0x16dd, + 0x6dc8, 0x3957, + 0x6dcb, 0x0a25, + 0x6dcc, 0x0e1d, + 0x6dcd, 0x395a, + 0x6dd1, 0x0d7e, + 0x6dd2, 0x395e, + 0x6dd6, 0x0b3a, + 0x6dd7, 0x3962, + 0x6dd8, 0x0e27, + 0x6dd9, 0x16e6, + 0x6dda, 0x3963, + 0x6ddd, 0x16e5, + 0x6dde, 0x16df, + 0x6ddf, 0x3966, + 0x6de0, 0x16e2, + 0x6de1, 0x058e, + 0x6de2, 0x3967, + 0x6de4, 0x10be, + 0x6de5, 0x3969, + 0x6de6, 0x16e4, + 0x6de7, 0x396a, + 0x6dea, 0x205e, + 0x6deb, 0x1080, + 0x6dec, 0x0566, + 0x6ded, 0x396d, + 0x6dee, 0x07c9, + 0x6def, 0x396e, + 0x6df1, 0x0d27, + 0x6df2, 0x3970, + 0x6df3, 0x0541, + 0x6df4, 0x3971, + 0x6df5, 0x2244, + 0x6df6, 0x23e2, + 0x6df7, 0x0801, + 0x6df8, 0x3972, + 0x6df9, 0x0ff6, + 0x6dfa, 0x20d4, + 0x6dfb, 0x0e40, + 0x6dfc, 0x1a21, + 0x6dfd, 0x3973, + 0x6e00, 0x3976, + 0x6e05, 0x0c62, + 0x6e06, 0x397b, + 0x6e0a, 0x10eb, + 0x6e0b, 0x397f, + 0x6e0c, 0x16e9, + 0x6e0d, 0x1232, + 0x6e0e, 0x16e0, + 0x6e0f, 0x3980, + 0x6e10, 0x0876, + 0x6e11, 0x16e3, + 0x6e12, 0x3981, + 0x6e14, 0x10cb, + 0x6e15, 0x3983, + 0x6e16, 0x16e7, + 0x6e17, 0x0d31, + 0x6e18, 0x3984, + 0x6e1a, 0x16dc, + 0x6e1b, 0x3986, + 0x6e1d, 0x10ca, + 0x6e1e, 0x3988, + 0x6e20, 0x0c7b, + 0x6e21, 0x0608, + 0x6e22, 0x398a, + 0x6e23, 0x113f, + 0x6e24, 0x047a, + 0x6e25, 0x16f5, + 0x6e26, 0x219f, + 0x6e27, 0x398b, + 0x6e29, 0x0ed1, + 0x6e2a, 0x398d, + 0x6e2b, 0x16eb, + 0x6e2c, 0x1e66, + 0x6e2d, 0x0ecb, + 0x6e2e, 0x398e, + 0x6e2f, 0x06d6, + 0x6e30, 0x398f, + 0x6e32, 0x16f4, + 0x6e33, 0x3991, + 0x6e34, 0x0957, + 0x6e35, 0x3992, + 0x6e38, 0x10b3, + 0x6e39, 0x3995, + 0x6e3a, 0x0af1, + 0x6e3b, 0x3996, + 0x6e3e, 0x1f63, + 0x6e3f, 0x3999, + 0x6e43, 0x0b89, + 0x6e44, 0x16f6, + 0x6e45, 0x399d, + 0x6e4d, 0x0e75, + 0x6e4e, 0x16ed, + 0x6e4f, 0x39a5, + 0x6e53, 0x16f2, + 0x6e55, 0x39a9, + 0x6e56, 0x07b5, + 0x6e57, 0x39aa, + 0x6e58, 0x0f53, + 0x6e59, 0x39ab, + 0x6e5b, 0x1160, + 0x6e5c, 0x39ad, + 0x6e5e, 0x23dd, + 0x6e5f, 0x16f0, + 0x6e60, 0x39af, + 0x6e6b, 0x16ee, + 0x6e6c, 0x39ba, + 0x6e6e, 0x16ec, + 0x6e6f, 0x216b, + 0x6e70, 0x39bc, + 0x6e7e, 0x0e96, + 0x6e7f, 0x0d41, + 0x6e80, 0x39ca, + 0x6e83, 0x098e, + 0x6e84, 0x39cd, + 0x6e85, 0x0877, + 0x6e86, 0x16f1, + 0x6e87, 0x39ce, + 0x6e89, 0x06c3, + 0x6e8a, 0x39d0, + 0x6e8f, 0x1705, + 0x6e90, 0x10f7, + 0x6e91, 0x39d5, + 0x6e96, 0x22b5, + 0x6e97, 0x39da, + 0x6e98, 0x16f9, + 0x6e99, 0x39db, + 0x6e9c, 0x0a38, + 0x6e9d, 0x1f26, + 0x6e9e, 0x39de, + 0x6e9f, 0x1707, + 0x6ea0, 0x39df, + 0x6ea2, 0x106e, + 0x6ea3, 0x39e1, + 0x6ea5, 0x16fd, + 0x6ea6, 0x39e3, + 0x6ea7, 0x16fe, + 0x6ea8, 0x39e4, + 0x6eaa, 0x0f17, + 0x6eab, 0x39e6, + 0x6eaf, 0x0dd2, + 0x6eb0, 0x39ea, + 0x6eb1, 0x16f8, + 0x6eb2, 0x16ef, + 0x6eb3, 0x39eb, + 0x6eb4, 0x1703, + 0x6eb5, 0x39ec, + 0x6eb6, 0x0cb7, + 0x6eb7, 0x1701, + 0x6eb8, 0x39ed, + 0x6eba, 0x0b4a, + 0x6ebb, 0x1700, + 0x6ebc, 0x39ef, + 0x6ebd, 0x16ff, + 0x6ebe, 0x39f0, + 0x6ec1, 0x0521, + 0x6ec2, 0x1706, + 0x6ec3, 0x39f3, + 0x6ec4, 0x1e63, + 0x6ec5, 0x2088, + 0x6ec6, 0x39f4, + 0x6ec7, 0x05c2, + 0x6ec8, 0x39f5, + 0x6ecb, 0x1229, + 0x6ecc, 0x1ebd, + 0x6ecd, 0x39f8, + 0x6ece, 0x2341, + 0x6ecf, 0x1704, + 0x6ed0, 0x39f9, + 0x6ed1, 0x07c1, + 0x6ed2, 0x39fa, + 0x6ed3, 0x122f, + 0x6ed4, 0x0e22, + 0x6ed5, 0x19a8, + 0x6ed6, 0x39fb, + 0x6ed7, 0x1702, + 0x6ed8, 0x39fc, + 0x6eda, 0x074f, + 0x6edb, 0x39fe, + 0x6ede, 0x11cc, + 0x6edf, 0x16f7, + 0x6ee0, 0x16fa, + 0x6ee1, 0x0aa1, + 0x6ee2, 0x16fc, + 0x6ee3, 0x3a01, + 0x6ee4, 0x0a72, + 0x6ee5, 0x09af, + 0x6ee6, 0x0a77, + 0x6ee7, 0x3a02, + 0x6ee8, 0x045e, + 0x6ee9, 0x0e05, + 0x6eea, 0x3a03, + 0x6eec, 0x1f4b, + 0x6eed, 0x3a05, + 0x6eef, 0x2292, + 0x6ef0, 0x3a07, + 0x6ef2, 0x2124, + 0x6ef3, 0x3a09, + 0x6ef4, 0x05af, + 0x6ef5, 0x3a0a, + 0x6ef7, 0x2048, + 0x6ef8, 0x23e0, + 0x6ef9, 0x170d, + 0x6efa, 0x3a0c, + 0x6eff, 0x2077, + 0x6f00, 0x3a11, + 0x6f01, 0x223a, + 0x6f02, 0x0bce, + 0x6f03, 0x3a12, + 0x6f06, 0x0c00, + 0x6f07, 0x3a15, + 0x6f09, 0x1713, + 0x6f0a, 0x3a17, + 0x6f0f, 0x0a50, + 0x6f10, 0x3a1c, + 0x6f13, 0x09d7, + 0x6f14, 0x1006, + 0x6f15, 0x170c, + 0x6f16, 0x3a1f, + 0x6f1a, 0x20b1, + 0x6f1b, 0x3a23, + 0x6f20, 0x0b11, + 0x6f21, 0x3a28, + 0x6f22, 0x1f41, + 0x6f23, 0x201c, + 0x6f24, 0x170b, + 0x6f25, 0x3a29, + 0x6f29, 0x1714, + 0x6f2a, 0x1712, + 0x6f2b, 0x0aa5, + 0x6f2c, 0x22b8, + 0x6f2d, 0x16fb, + 0x6f2e, 0x3a2d, + 0x6f2f, 0x170e, + 0x6f30, 0x3a2e, + 0x6f31, 0x0d95, + 0x6f32, 0x2276, + 0x6f33, 0x1165, + 0x6f34, 0x3a2f, + 0x6f36, 0x170f, + 0x6f37, 0x3a31, + 0x6f38, 0x1f9b, + 0x6f39, 0x3a32, + 0x6f3e, 0x1023, + 0x6f3f, 0x1f9f, + 0x6f40, 0x3a37, + 0x6f41, 0x25ca, + 0x6f42, 0x3a38, + 0x6f46, 0x1709, + 0x6f48, 0x3a3c, + 0x6f4b, 0x1710, + 0x6f4c, 0x3a3f, + 0x6f4d, 0x0eba, + 0x6f4e, 0x3a40, + 0x6f51, 0x20be, + 0x6f52, 0x3a43, + 0x6f54, 0x1fb4, + 0x6f55, 0x3a45, + 0x6f58, 0x0b8c, + 0x6f59, 0x23d7, + 0x6f5a, 0x3a48, + 0x6f5c, 0x0c2e, + 0x6f5d, 0x3a4a, + 0x6f5e, 0x0a61, + 0x6f5f, 0x3a4b, + 0x6f62, 0x1708, + 0x6f63, 0x3a4e, + 0x6f64, 0x2105, + 0x6f65, 0x3a4f, + 0x6f66, 0x0a13, + 0x6f67, 0x3a50, + 0x6f6d, 0x0e09, + 0x6f6e, 0x04d6, + 0x6f6f, 0x23e1, + 0x6f70, 0x1fec, + 0x6f71, 0x3a56, + 0x6f72, 0x1719, + 0x6f73, 0x3a57, + 0x6f74, 0x1711, + 0x6f75, 0x3a58, + 0x6f77, 0x23ea, + 0x6f78, 0x1718, + 0x6f79, 0x3a5a, + 0x6f7a, 0x171b, + 0x6f7b, 0x3a5b, + 0x6f7c, 0x171a, + 0x6f7d, 0x3a5c, + 0x6f7f, 0x23e3, + 0x6f80, 0x210e, + 0x6f81, 0x3a5e, + 0x6f84, 0x04f3, + 0x6f85, 0x3a61, + 0x6f86, 0x1fa6, + 0x6f87, 0x2004, + 0x6f88, 0x04df, + 0x6f89, 0x1715, + 0x6f8a, 0x3a62, + 0x6f8c, 0x1717, + 0x6f8d, 0x1716, + 0x6f8e, 0x0bad, + 0x6f8f, 0x3a64, + 0x6f97, 0x1f9d, + 0x6f98, 0x3a6c, + 0x6f9c, 0x09a8, + 0x6f9d, 0x3a70, + 0x6fa0, 0x23e5, + 0x6fa1, 0x112b, + 0x6fa2, 0x3a73, + 0x6fa4, 0x2264, + 0x6fa5, 0x3a75, + 0x6fa7, 0x171e, + 0x6fa8, 0x3a77, + 0x6fa9, 0x24e2, + 0x6faa, 0x3a78, + 0x6fae, 0x23de, + 0x6faf, 0x3a7c, + 0x6fb1, 0x1ec4, + 0x6fb2, 0x3a7e, + 0x6fb3, 0x03cf, + 0x6fb4, 0x3a7f, + 0x6fb6, 0x1720, + 0x6fb7, 0x3a81, + 0x6fb9, 0x171f, + 0x6fba, 0x3a83, + 0x6fc0, 0x0817, + 0x6fc1, 0x22b6, + 0x6fc2, 0x1721, + 0x6fc3, 0x20a9, + 0x6fc4, 0x3a89, + 0x6fc9, 0x171d, + 0x6fca, 0x3a8e, + 0x6fd1, 0x171c, + 0x6fd2, 0x045d, + 0x6fd3, 0x3a95, + 0x6fd5, 0x212b, + 0x6fd6, 0x3a97, + 0x6fd8, 0x20a5, + 0x6fd9, 0x3a99, + 0x6fdb, 0x268b, + 0x6fdc, 0x3a9b, + 0x6fde, 0x1724, + 0x6fdf, 0x1f76, + 0x6fe0, 0x1725, + 0x6fe1, 0x1722, + 0x6fe2, 0x3a9d, + 0x6fe4, 0x216d, + 0x6fe5, 0x3a9f, + 0x6feb, 0x2001, + 0x6fec, 0x3aa5, + 0x6fee, 0x1723, + 0x6fef, 0x1726, + 0x6ff0, 0x2191, + 0x6ff1, 0x1e50, + 0x6ff2, 0x3aa7, + 0x6ffa, 0x1f9c, + 0x6ffb, 0x3aaf, + 0x6ffc, 0x23da, + 0x6ffd, 0x3ab0, + 0x6ffe, 0x2053, + 0x6fff, 0x3ab1, + 0x7000, 0x3ab2, + 0x7005, 0x23e9, + 0x7006, 0x23e4, + 0x7007, 0x3ab7, + 0x7009, 0x21d5, + 0x700a, 0x3ab9, + 0x700b, 0x23e6, + 0x700c, 0x3aba, + 0x700f, 0x23df, + 0x7010, 0x3abd, + 0x7011, 0x0bf8, + 0x7012, 0x3abe, + 0x7015, 0x1e4f, + 0x7016, 0x3ac1, + 0x7018, 0x23d9, + 0x7019, 0x3ac3, + 0x701a, 0x1727, + 0x701b, 0x1729, + 0x701c, 0x3ac4, + 0x701d, 0x2014, + 0x701e, 0x3ac5, + 0x701f, 0x23ec, + 0x7020, 0x23eb, + 0x7021, 0x3ac6, + 0x7023, 0x1728, + 0x7024, 0x3ac8, + 0x7027, 0x23d8, + 0x7028, 0x23ee, + 0x7029, 0x3acb, + 0x7030, 0x268e, + 0x7031, 0x3ad2, + 0x7032, 0x23ed, + 0x7033, 0x3ad3, + 0x7035, 0x172b, + 0x7036, 0x3ad5, + 0x7039, 0x172a, + 0x703a, 0x3ad8, + 0x703e, 0x1ffa, + 0x703f, 0x3adc, + 0x7043, 0x23d6, + 0x7044, 0x23e8, + 0x7045, 0x3ae0, + 0x704c, 0x0739, + 0x704d, 0x3ae7, + 0x704f, 0x172c, + 0x7050, 0x3ae9, + 0x7051, 0x2106, + 0x7052, 0x3aea, + 0x7055, 0x200b, + 0x7056, 0x3aed, + 0x7058, 0x2166, + 0x7059, 0x3aef, + 0x705d, 0x23ef, + 0x705e, 0x172d, + 0x705f, 0x3af3, + 0x7063, 0x2189, + 0x7064, 0x2058, + 0x7065, 0x3af7, + 0x7067, 0x23e7, + 0x7068, 0x3af9, + 0x706b, 0x0805, + 0x706c, 0x19ef, + 0x706d, 0x0af5, + 0x706e, 0x3afc, + 0x706f, 0x05a7, + 0x7070, 0x07e7, + 0x7071, 0x3afd, + 0x7075, 0x0a32, + 0x7076, 0x1131, + 0x7077, 0x3b01, + 0x7078, 0x08f3, + 0x7079, 0x3b02, + 0x707c, 0x1223, + 0x707d, 0x3b05, + 0x707e, 0x1119, + 0x707f, 0x049a, + 0x7080, 0x19cc, + 0x7081, 0x3b06, + 0x7085, 0x1913, + 0x7086, 0x3b0a, + 0x7089, 0x0a56, + 0x708a, 0x0539, + 0x708b, 0x3b0d, + 0x708e, 0x1000, + 0x708f, 0x3b10, + 0x7092, 0x04d9, + 0x7093, 0x3b13, + 0x7094, 0x0c8d, + 0x7095, 0x0948, + 0x7096, 0x19ce, + 0x7097, 0x3b14, + 0x7099, 0x11ca, + 0x709a, 0x3b16, + 0x709c, 0x19cd, + 0x709d, 0x19cf, + 0x709e, 0x3b18, + 0x70ab, 0x19d3, + 0x70ac, 0x0915, + 0x70ad, 0x0e12, + 0x70ae, 0x0b9b, + 0x70af, 0x08eb, + 0x70b0, 0x3b25, + 0x70b1, 0x19d4, + 0x70b2, 0x3b26, + 0x70b3, 0x0467, + 0x70b4, 0x3b27, + 0x70b7, 0x19d2, + 0x70b8, 0x1149, + 0x70b9, 0x05c4, + 0x70ba, 0x3b2a, + 0x70bb, 0x19d0, + 0x70bc, 0x09ff, + 0x70bd, 0x0508, + 0x70be, 0x3b2b, + 0x70c0, 0x19d1, + 0x70c1, 0x0dad, + 0x70c2, 0x09ae, + 0x70c3, 0x0e51, + 0x70c4, 0x3b2d, + 0x70c8, 0x0a1b, + 0x70c9, 0x3b31, + 0x70ca, 0x19d6, + 0x70cb, 0x3b32, + 0x70cf, 0x21a3, + 0x70d0, 0x3b36, + 0x70d8, 0x079d, + 0x70d9, 0x09be, + 0x70da, 0x3b3e, + 0x70db, 0x11f1, + 0x70dc, 0x3b3f, + 0x70df, 0x0ff5, + 0x70e0, 0x3b42, + 0x70e4, 0x094b, + 0x70e5, 0x3b46, + 0x70e6, 0x0650, + 0x70e7, 0x0d0e, + 0x70e8, 0x19d5, + 0x70e9, 0x07f7, + 0x70ea, 0x3b47, + 0x70eb, 0x0e1f, + 0x70ec, 0x08ce, + 0x70ed, 0x0ca3, + 0x70ee, 0x3b48, + 0x70ef, 0x0f16, + 0x70f0, 0x3b49, + 0x70f4, 0x217a, + 0x70f5, 0x3b4d, + 0x70f7, 0x0e9a, + 0x70f8, 0x3b4f, + 0x70f9, 0x0bac, + 0x70fa, 0x3b50, + 0x70fd, 0x0686, + 0x70fe, 0x3b53, + 0x7100, 0x3b55, + 0x7109, 0x0ff2, + 0x710a, 0x076f, + 0x710b, 0x3b5e, + 0x7110, 0x19d7, + 0x7111, 0x3b63, + 0x7113, 0x19d8, + 0x7114, 0x3b65, + 0x7115, 0x07d5, + 0x7116, 0x19d9, + 0x7117, 0x3b66, + 0x7118, 0x19f0, + 0x7119, 0x0423, + 0x711a, 0x0676, + 0x711b, 0x3b67, + 0x7121, 0x21a5, + 0x7122, 0x3b6d, + 0x7126, 0x088a, + 0x7127, 0x3b71, + 0x712f, 0x19da, + 0x7130, 0x100f, + 0x7131, 0x19db, + 0x7132, 0x3b79, + 0x7136, 0x0c96, + 0x7137, 0x3b7d, + 0x7145, 0x19df, + 0x7146, 0x3b8b, + 0x7149, 0x2022, + 0x714a, 0x19e1, + 0x714b, 0x3b8e, + 0x714c, 0x07e2, + 0x714d, 0x3b8f, + 0x714e, 0x0858, + 0x714f, 0x3b90, + 0x7152, 0x24d6, + 0x7153, 0x3b93, + 0x715c, 0x19dd, + 0x715d, 0x3b9c, + 0x715e, 0x0cf0, + 0x715f, 0x3b9d, + 0x7162, 0x233a, + 0x7163, 0x3ba0, + 0x7164, 0x0abf, + 0x7165, 0x3ba1, + 0x7166, 0x19f1, + 0x7167, 0x1176, + 0x7168, 0x19de, + 0x7169, 0x1eee, + 0x716a, 0x3ba2, + 0x716c, 0x24d5, + 0x716d, 0x3ba4, + 0x716e, 0x11f2, + 0x716f, 0x3ba5, + 0x7172, 0x19e0, + 0x7173, 0x19dc, + 0x7174, 0x3ba8, + 0x7178, 0x19e2, + 0x7179, 0x3bac, + 0x717a, 0x19e3, + 0x717b, 0x3bad, + 0x717d, 0x0cf8, + 0x717e, 0x3baf, + 0x7184, 0x0f15, + 0x7185, 0x3bb5, + 0x718a, 0x0fa7, + 0x718b, 0x3bba, + 0x718f, 0x0fd5, + 0x7190, 0x3bbe, + 0x7192, 0x2228, + 0x7193, 0x3bc0, + 0x7194, 0x0cb6, + 0x7195, 0x3bc1, + 0x7197, 0x24d7, + 0x7198, 0x19e4, + 0x7199, 0x0f04, + 0x719a, 0x3bc3, + 0x719f, 0x0d83, + 0x71a0, 0x19e8, + 0x71a1, 0x3bc8, + 0x71a8, 0x19e7, + 0x71a9, 0x3bcf, + 0x71ac, 0x03c9, + 0x71ad, 0x3bd2, + 0x71b1, 0x20fc, + 0x71b2, 0x3bd6, + 0x71b3, 0x19e5, + 0x71b4, 0x3bd7, + 0x71b5, 0x19e6, + 0x71b6, 0x3bd8, + 0x71b9, 0x19f2, + 0x71ba, 0x3bdb, + 0x71be, 0x1e87, + 0x71bf, 0x3bdf, + 0x71c1, 0x24d8, + 0x71c2, 0x3be1, + 0x71c3, 0x0c97, + 0x71c4, 0x3be2, + 0x71c8, 0x1eba, + 0x71c9, 0x3be6, + 0x71ce, 0x0a10, + 0x71cf, 0x3beb, + 0x71d2, 0x2119, + 0x71d3, 0x3bee, + 0x71d4, 0x19ea, + 0x71d5, 0x1009, + 0x71d6, 0x3bef, + 0x71d9, 0x216c, + 0x71da, 0x3bf2, + 0x71dc, 0x24d9, + 0x71dd, 0x3bf4, + 0x71df, 0x2227, + 0x71e0, 0x19e9, + 0x71e1, 0x3bf6, + 0x71e5, 0x1132, + 0x71e6, 0x1e5f, + 0x71e7, 0x19eb, + 0x71e8, 0x3bfa, + 0x71ed, 0x229f, + 0x71ee, 0x1396, + 0x71ef, 0x3bff, + 0x71f4, 0x1f5d, + 0x71f5, 0x3c04, + 0x71f9, 0x19ec, + 0x71fa, 0x3c08, + 0x71fc, 0x1fbc, + 0x71fd, 0x3c0a, + 0x71fe, 0x24da, + 0x71ff, 0x3c0b, + 0x7200, 0x3c0c, + 0x7206, 0x0415, + 0x7207, 0x3c12, + 0x720d, 0x2149, + 0x720e, 0x3c18, + 0x7210, 0x2046, + 0x7211, 0x3c1a, + 0x721b, 0x2000, + 0x721c, 0x3c24, + 0x721d, 0x19ed, + 0x721e, 0x3c25, + 0x7228, 0x19ee, + 0x7229, 0x3c2f, + 0x722a, 0x1203, + 0x722b, 0x3c30, + 0x722c, 0x0b81, + 0x722d, 0x3c31, + 0x7230, 0x196c, + 0x7231, 0x03b9, + 0x7232, 0x2190, + 0x7233, 0x3c34, + 0x7235, 0x0923, + 0x7236, 0x06b3, + 0x7237, 0x1036, + 0x7238, 0x03e1, + 0x7239, 0x05da, + 0x723a, 0x2208, + 0x723b, 0x1269, + 0x723c, 0x3c36, + 0x723d, 0x0da1, + 0x723e, 0x1ee6, + 0x723f, 0x169d, + 0x7240, 0x3c37, + 0x7247, 0x0bcb, + 0x7248, 0x03f1, + 0x7249, 0x3c3e, + 0x724c, 0x0b87, + 0x724d, 0x1969, + 0x724e, 0x3c41, + 0x7252, 0x196a, + 0x7253, 0x3c45, + 0x7256, 0x196b, + 0x7257, 0x3c48, + 0x7258, 0x24c3, + 0x7259, 0x0fe9, + 0x725a, 0x3c49, + 0x725b, 0x0b64, + 0x725c, 0x3c4a, + 0x725d, 0x1944, + 0x725e, 0x3c4b, + 0x725f, 0x0b15, + 0x7260, 0x3c4c, + 0x7261, 0x0b18, + 0x7262, 0x09b9, + 0x7263, 0x3c4d, + 0x7266, 0x1945, + 0x7267, 0x0b24, + 0x7268, 0x3c50, + 0x7269, 0x0efe, + 0x726a, 0x3c51, + 0x726e, 0x1942, + 0x726f, 0x1946, + 0x7270, 0x3c55, + 0x7272, 0x0d35, + 0x7273, 0x3c57, + 0x7275, 0x0c20, + 0x7276, 0x3c59, + 0x7279, 0x0e2b, + 0x727a, 0x0f0d, + 0x727b, 0x3c5c, + 0x727d, 0x20cc, + 0x727e, 0x1947, + 0x7280, 0x0f19, + 0x7281, 0x09d2, + 0x7282, 0x3c5e, + 0x7284, 0x1949, + 0x7285, 0x3c60, + 0x728a, 0x05fe, + 0x728b, 0x194a, + 0x728c, 0x3c65, + 0x728d, 0x194b, + 0x728e, 0x3c66, + 0x728f, 0x194c, + 0x7290, 0x3c67, + 0x7292, 0x194d, + 0x7293, 0x3c69, + 0x7296, 0x2340, + 0x7297, 0x3c6c, + 0x729f, 0x1943, + 0x72a0, 0x3c74, + 0x72a2, 0x1ed1, + 0x72a3, 0x3c76, + 0x72a7, 0x21ac, + 0x72a8, 0x3c7a, + 0x72ac, 0x0c89, + 0x72ad, 0x15ef, + 0x72ae, 0x3c7e, + 0x72af, 0x0655, + 0x72b0, 0x15f0, + 0x72b1, 0x3c7f, + 0x72b4, 0x15f1, + 0x72b5, 0x3c82, + 0x72b6, 0x1211, + 0x72b7, 0x15f2, + 0x72b9, 0x10b1, + 0x72ba, 0x3c83, + 0x72c0, 0x22af, + 0x72c1, 0x15f5, + 0x72c2, 0x097e, + 0x72c3, 0x15f4, + 0x72c4, 0x05b3, + 0x72c5, 0x3c89, + 0x72c8, 0x0420, + 0x72c9, 0x3c8c, + 0x72cd, 0x15f7, + 0x72ce, 0x15f6, + 0x72cf, 0x3c90, + 0x72d0, 0x07b3, + 0x72d1, 0x3c91, + 0x72d2, 0x15f8, + 0x72d3, 0x3c92, + 0x72d7, 0x0710, + 0x72d8, 0x3c96, + 0x72d9, 0x0900, + 0x72da, 0x3c97, + 0x72de, 0x0b5f, + 0x72df, 0x3c9b, + 0x72e0, 0x0794, + 0x72e1, 0x0897, + 0x72e2, 0x3c9c, + 0x72e8, 0x15f9, + 0x72e9, 0x15fb, + 0x72ea, 0x3ca2, + 0x72ec, 0x05ff, + 0x72ed, 0x0f2e, + 0x72ee, 0x0d3f, + 0x72ef, 0x15fa, + 0x72f0, 0x1199, + 0x72f1, 0x10e1, + 0x72f2, 0x15fc, + 0x72f3, 0x1600, + 0x72f4, 0x15fd, + 0x72f5, 0x3ca4, + 0x72f7, 0x15fe, + 0x72f8, 0x09d5, + 0x72f9, 0x21b6, + 0x72fa, 0x1602, + 0x72fc, 0x09b2, + 0x72fd, 0x1e3d, + 0x72fe, 0x3ca6, + 0x7300, 0x3ca8, + 0x7301, 0x15ff, + 0x7302, 0x3ca9, + 0x7303, 0x1601, + 0x7304, 0x3caa, + 0x730a, 0x1607, + 0x730b, 0x3cb0, + 0x730e, 0x0a1d, + 0x730f, 0x3cb3, + 0x7313, 0x1605, + 0x7314, 0x3cb7, + 0x7315, 0x160a, + 0x7316, 0x04c5, + 0x7317, 0x1604, + 0x7318, 0x3cb8, + 0x731b, 0x0ad2, + 0x731c, 0x0489, + 0x731d, 0x1609, + 0x731e, 0x1608, + 0x731f, 0x3cbb, + 0x7321, 0x1606, + 0x7322, 0x160b, + 0x7323, 0x3cbd, + 0x7325, 0x160d, + 0x7326, 0x3cbf, + 0x7329, 0x0f94, + 0x732a, 0x11ec, + 0x732b, 0x0aad, + 0x732c, 0x160e, + 0x732d, 0x3cc2, + 0x732e, 0x0f44, + 0x732f, 0x3cc3, + 0x7331, 0x1610, + 0x7332, 0x3cc5, + 0x7334, 0x07a6, + 0x7335, 0x3cc7, + 0x7336, 0x2235, + 0x7337, 0x18d4, + 0x7338, 0x160f, + 0x7339, 0x160c, + 0x733a, 0x3cc8, + 0x733b, 0x2397, + 0x733c, 0x3cc9, + 0x733e, 0x07c0, + 0x733f, 0x10f6, + 0x7340, 0x3ccb, + 0x7341, 0x2395, + 0x7342, 0x3ccc, + 0x7344, 0x223f, + 0x7345, 0x212a, + 0x7346, 0x3cce, + 0x734d, 0x1612, + 0x734e, 0x3cd5, + 0x7350, 0x1611, + 0x7351, 0x3cd7, + 0x7352, 0x18d5, + 0x7353, 0x3cd8, + 0x7357, 0x1613, + 0x7358, 0x3cdc, + 0x7360, 0x1614, + 0x7361, 0x3ce4, + 0x7368, 0x1ed2, + 0x7369, 0x3ceb, + 0x736a, 0x2396, + 0x736b, 0x2398, + 0x736c, 0x1615, + 0x736d, 0x0df4, + 0x736e, 0x3cec, + 0x736f, 0x1616, + 0x7370, 0x20a2, + 0x7371, 0x3ced, + 0x7372, 0x1f64, + 0x7373, 0x3cee, + 0x7375, 0x202b, + 0x7376, 0x3cf0, + 0x7377, 0x2394, + 0x7378, 0x2139, + 0x7379, 0x3cf1, + 0x737a, 0x215f, + 0x737b, 0x21c1, + 0x737c, 0x239a, + 0x737d, 0x3cf2, + 0x737e, 0x1617, + 0x737f, 0x3cf3, + 0x7380, 0x2399, + 0x7381, 0x3cf4, + 0x7384, 0x0fc9, + 0x7385, 0x3cf7, + 0x7387, 0x0a71, + 0x7388, 0x3cf9, + 0x7389, 0x10d6, + 0x738a, 0x3cfa, + 0x738b, 0x0ea6, + 0x738c, 0x3cfb, + 0x738e, 0x1818, + 0x738f, 0x3cfd, + 0x7391, 0x1819, + 0x7392, 0x3cff, + 0x7396, 0x08f0, + 0x7397, 0x3d03, + 0x739b, 0x0a91, + 0x739c, 0x3d07, + 0x739f, 0x181c, + 0x73a0, 0x3d0a, + 0x73a2, 0x181b, + 0x73a3, 0x3d0c, + 0x73a9, 0x0e97, + 0x73aa, 0x3d12, + 0x73ab, 0x0aba, + 0x73ac, 0x3d13, + 0x73ae, 0x181a, + 0x73af, 0x07cc, + 0x73b0, 0x0f43, + 0x73b1, 0x3d15, + 0x73b2, 0x0a2a, + 0x73b3, 0x1821, + 0x73b4, 0x3d16, + 0x73b7, 0x1820, + 0x73b8, 0x3d19, + 0x73ba, 0x182c, + 0x73bb, 0x046a, + 0x73bc, 0x3d1b, + 0x73c0, 0x1822, + 0x73c1, 0x3d1f, + 0x73c2, 0x181e, + 0x73c3, 0x3d20, + 0x73c8, 0x1824, + 0x73c9, 0x1823, + 0x73ca, 0x0cf3, + 0x73cb, 0x3d25, + 0x73cd, 0x1185, + 0x73ce, 0x3d27, + 0x73cf, 0x181d, + 0x73d0, 0x0646, + 0x73d1, 0x181f, + 0x73d2, 0x3d28, + 0x73d9, 0x1826, + 0x73da, 0x3d2f, + 0x73de, 0x182b, + 0x73df, 0x3d33, + 0x73e0, 0x11e8, + 0x73e1, 0x3d34, + 0x73e5, 0x1825, + 0x73e6, 0x3d38, + 0x73e7, 0x182a, + 0x73e8, 0x3d39, + 0x73e9, 0x1829, + 0x73ea, 0x3d3a, + 0x73ed, 0x03eb, + 0x73ee, 0x3d3d, + 0x73f2, 0x182d, + 0x73f3, 0x3d41, + 0x73fe, 0x21c0, + 0x73ff, 0x3d4c, + 0x7400, 0x3d4d, + 0x7403, 0x0c6f, + 0x7404, 0x3d50, + 0x7405, 0x09b0, + 0x7406, 0x09d8, + 0x7407, 0x3d51, + 0x7409, 0x0a39, + 0x740a, 0x1828, + 0x740b, 0x3d53, + 0x740f, 0x182e, + 0x7410, 0x0deb, + 0x7411, 0x3d57, + 0x741a, 0x1838, + 0x741b, 0x1837, + 0x741c, 0x3d60, + 0x7422, 0x121e, + 0x7423, 0x3d66, + 0x7425, 0x1832, + 0x7426, 0x1831, + 0x7427, 0x3d68, + 0x7428, 0x1833, + 0x7429, 0x3d69, + 0x742a, 0x182f, + 0x742b, 0x3d6a, + 0x742c, 0x1836, + 0x742d, 0x3d6b, + 0x742e, 0x1835, + 0x742f, 0x3d6c, + 0x7430, 0x1834, + 0x7431, 0x3d6d, + 0x7433, 0x0a1e, + 0x7434, 0x0c56, + 0x7435, 0x0bbe, + 0x7436, 0x0b84, + 0x7437, 0x3d6f, + 0x743c, 0x0c6a, + 0x743d, 0x3d74, + 0x743f, 0x2460, + 0x7440, 0x3d76, + 0x7441, 0x1839, + 0x7442, 0x3d77, + 0x744b, 0x245c, + 0x744c, 0x3d80, + 0x7455, 0x183c, + 0x7456, 0x3d89, + 0x7457, 0x183b, + 0x7458, 0x3d8a, + 0x7459, 0x183d, + 0x745a, 0x07ae, + 0x745b, 0x1830, + 0x745c, 0x183a, + 0x745d, 0x3d8b, + 0x745e, 0x0ccb, + 0x745f, 0x0ce3, + 0x7460, 0x3d8c, + 0x7463, 0x215d, + 0x7464, 0x3d8f, + 0x7469, 0x2225, + 0x746a, 0x206a, + 0x746b, 0x3d94, + 0x746d, 0x183f, + 0x746e, 0x3d96, + 0x7470, 0x073e, + 0x7471, 0x3d98, + 0x7476, 0x1027, + 0x7477, 0x183e, + 0x7478, 0x3d9d, + 0x747e, 0x1840, + 0x747f, 0x3da3, + 0x7480, 0x1843, + 0x7482, 0x3da4, + 0x7483, 0x09f0, + 0x7484, 0x3da5, + 0x7487, 0x1845, + 0x7488, 0x3da8, + 0x7489, 0x2461, + 0x748a, 0x3da9, + 0x748b, 0x1846, + 0x748c, 0x3daa, + 0x748e, 0x1842, + 0x748f, 0x3dac, + 0x7490, 0x184a, + 0x7491, 0x3dad, + 0x749c, 0x1841, + 0x749d, 0x3db8, + 0x749e, 0x1847, + 0x749f, 0x3db9, + 0x74a3, 0x245b, + 0x74a4, 0x3dbd, + 0x74a6, 0x2462, + 0x74a7, 0x184b, + 0x74a8, 0x1848, + 0x74aa, 0x3dbf, + 0x74b0, 0x1f54, + 0x74b1, 0x3dc5, + 0x74ba, 0x184d, + 0x74bb, 0x3dce, + 0x74bd, 0x245f, + 0x74be, 0x3dd0, + 0x74ca, 0x20ec, + 0x74cb, 0x3ddc, + 0x74cf, 0x245d, + 0x74d0, 0x3de0, + 0x74d2, 0x184c, + 0x74d3, 0x3de2, + 0x74d4, 0x2463, + 0x74d5, 0x3de3, + 0x74da, 0x2464, + 0x74db, 0x3de8, + 0x74dc, 0x0728, + 0x74dd, 0x3de9, + 0x74de, 0x1b32, + 0x74df, 0x3dea, + 0x74e0, 0x1b33, + 0x74e1, 0x3deb, + 0x74e2, 0x0bcf, + 0x74e3, 0x03f5, + 0x74e4, 0x0c9a, + 0x74e5, 0x3dec, + 0x74e6, 0x0e90, + 0x74e7, 0x3ded, + 0x74ee, 0x0edc, + 0x74ef, 0x1903, + 0x74f0, 0x3df4, + 0x74f4, 0x1904, + 0x74f5, 0x3df8, + 0x74f6, 0x0bde, + 0x74f7, 0x054c, + 0x74f8, 0x3df9, + 0x74ff, 0x1905, + 0x7500, 0x3e00, + 0x7504, 0x1188, + 0x7505, 0x3e04, + 0x750c, 0x24a5, + 0x750d, 0x1485, + 0x750e, 0x3e0b, + 0x750f, 0x1906, + 0x7510, 0x3e0c, + 0x7511, 0x1907, + 0x7512, 0x3e0d, + 0x7513, 0x1908, + 0x7514, 0x3e0e, + 0x7518, 0x06c5, + 0x7519, 0x14f8, + 0x751a, 0x0d2e, + 0x751b, 0x3e12, + 0x751c, 0x0e43, + 0x751d, 0x3e13, + 0x751f, 0x0d33, + 0x7520, 0x3e15, + 0x7523, 0x1e70, + 0x7524, 0x3e18, + 0x7525, 0x0d34, + 0x7526, 0x3e19, + 0x7528, 0x10a8, + 0x7529, 0x0d9b, + 0x752a, 0x3e1b, + 0x752b, 0x06a1, + 0x752c, 0x1b34, + 0x752d, 0x042b, + 0x752e, 0x3e1c, + 0x752f, 0x1734, + 0x7530, 0x0e42, + 0x7531, 0x10ae, + 0x7532, 0x084a, + 0x7533, 0x0d23, + 0x7534, 0x3e1d, + 0x7535, 0x05c8, + 0x7536, 0x3e1e, + 0x7537, 0x0b33, + 0x7538, 0x05ca, + 0x7539, 0x3e1f, + 0x753a, 0x1a78, + 0x753b, 0x07c2, + 0x753c, 0x3e20, + 0x753e, 0x1816, + 0x753f, 0x3e22, + 0x7540, 0x1a79, + 0x7541, 0x3e23, + 0x7545, 0x04ce, + 0x7546, 0x3e27, + 0x7548, 0x1a7c, + 0x7549, 0x3e29, + 0x754b, 0x1a7b, + 0x754c, 0x08b8, + 0x754d, 0x3e2b, + 0x754e, 0x1a7a, + 0x754f, 0x0ec6, + 0x7550, 0x3e2c, + 0x7554, 0x0b90, + 0x7555, 0x3e30, + 0x7559, 0x0a3d, + 0x755a, 0x139e, + 0x755b, 0x1a7d, + 0x755c, 0x0fbe, + 0x755d, 0x208f, + 0x755e, 0x3e34, + 0x7562, 0x1e42, + 0x7563, 0x3e38, + 0x7565, 0x0a7b, + 0x7566, 0x0c07, + 0x7567, 0x3e3a, + 0x756a, 0x0649, + 0x756b, 0x1f4e, + 0x756c, 0x3e3d, + 0x7572, 0x1a7e, + 0x7573, 0x3e43, + 0x7574, 0x0510, + 0x7575, 0x3e44, + 0x7576, 0x1eb1, + 0x7577, 0x3e45, + 0x7578, 0x0810, + 0x7579, 0x1a7f, + 0x757a, 0x3e46, + 0x757f, 0x1814, + 0x7580, 0x3e4b, + 0x7583, 0x1a80, + 0x7584, 0x3e4e, + 0x7586, 0x087f, + 0x7587, 0x1e8b, + 0x7588, 0x3e50, + 0x758b, 0x1bc6, + 0x758c, 0x3e53, + 0x758f, 0x0d7f, + 0x7590, 0x3e56, + 0x7591, 0x1050, + 0x7592, 0x1b60, + 0x7593, 0x3e57, + 0x7594, 0x1b61, + 0x7595, 0x3e58, + 0x7596, 0x1b62, + 0x7597, 0x0a0f, + 0x7598, 0x3e59, + 0x7599, 0x06e8, + 0x759a, 0x08fd, + 0x759b, 0x3e5a, + 0x759d, 0x1b64, + 0x759e, 0x3e5c, + 0x759f, 0x0b72, + 0x75a0, 0x1b63, + 0x75a1, 0x101a, + 0x75a2, 0x3e5d, + 0x75a3, 0x1b66, + 0x75a4, 0x03d7, + 0x75a5, 0x08bb, + 0x75a6, 0x3e5e, + 0x75ab, 0x1066, + 0x75ac, 0x1b65, + 0x75ad, 0x3e63, + 0x75ae, 0x0532, + 0x75af, 0x0685, + 0x75b0, 0x1b6c, + 0x75b1, 0x1b6b, + 0x75b2, 0x0bc2, + 0x75b3, 0x1b67, + 0x75b5, 0x0546, + 0x75b6, 0x3e64, + 0x75b8, 0x1b69, + 0x75b9, 0x118f, + 0x75ba, 0x3e66, + 0x75bc, 0x0e2e, + 0x75bd, 0x0901, + 0x75be, 0x0825, + 0x75bf, 0x3e68, + 0x75c2, 0x1b6e, + 0x75c3, 0x1b6d, + 0x75c4, 0x1b6a, + 0x75c5, 0x0468, + 0x75c6, 0x3e6b, + 0x75c7, 0x11a1, + 0x75c8, 0x109d, + 0x75c9, 0x08e6, + 0x75ca, 0x0c87, + 0x75cb, 0x3e6c, + 0x75cd, 0x1b70, + 0x75ce, 0x3e6e, + 0x75d2, 0x1020, + 0x75d3, 0x3e72, + 0x75d4, 0x11cb, + 0x75d5, 0x0792, + 0x75d6, 0x1b6f, + 0x75d7, 0x3e73, + 0x75d8, 0x05fa, + 0x75d9, 0x1fc6, + 0x75da, 0x3e74, + 0x75db, 0x0e65, + 0x75dc, 0x3e75, + 0x75de, 0x0bc5, + 0x75df, 0x3e77, + 0x75e2, 0x09ea, + 0x75e3, 0x1b71, + 0x75e4, 0x1b74, + 0x75e5, 0x3e7a, + 0x75e6, 0x1b73, + 0x75e7, 0x1b76, + 0x75e8, 0x1b72, + 0x75e9, 0x3e7b, + 0x75ea, 0x07d3, + 0x75eb, 0x1b75, + 0x75ec, 0x3e7c, + 0x75f0, 0x0e08, + 0x75f1, 0x1b78, + 0x75f2, 0x3e80, + 0x75f4, 0x04fa, + 0x75f5, 0x3e82, + 0x75f9, 0x043d, + 0x75fa, 0x3e86, + 0x75fc, 0x1b79, + 0x75fd, 0x3e88, + 0x75ff, 0x1b7a, + 0x7600, 0x1b7c, + 0x7601, 0x0564, + 0x7602, 0x25ae, + 0x7603, 0x1b77, + 0x7604, 0x3e8a, + 0x7605, 0x1b7d, + 0x7606, 0x3e8b, + 0x760a, 0x1b80, + 0x760b, 0x1f01, + 0x760c, 0x1b7e, + 0x760d, 0x2200, + 0x760e, 0x3e8f, + 0x7610, 0x1b7b, + 0x7611, 0x3e91, + 0x7615, 0x1b83, + 0x7616, 0x3e95, + 0x7617, 0x1b7f, + 0x7618, 0x1b82, + 0x7619, 0x1b84, + 0x761a, 0x3e96, + 0x761b, 0x1b85, + 0x761c, 0x3e97, + 0x761e, 0x25b2, + 0x761f, 0x0ed0, + 0x7620, 0x1b88, + 0x7621, 0x1e97, + 0x7622, 0x1b87, + 0x7623, 0x3e99, + 0x7624, 0x0a3f, + 0x7625, 0x1b81, + 0x7626, 0x0d74, + 0x7627, 0x20ab, + 0x7628, 0x3e9a, + 0x7629, 0x0574, + 0x762a, 0x045a, + 0x762b, 0x0e04, + 0x762c, 0x3e9b, + 0x762d, 0x1b8a, + 0x762e, 0x3e9c, + 0x7630, 0x1b8b, + 0x7631, 0x3e9e, + 0x7633, 0x1b90, + 0x7634, 0x116f, + 0x7635, 0x1b8d, + 0x7636, 0x3ea0, + 0x7638, 0x0c8e, + 0x7639, 0x3ea2, + 0x763b, 0x25b3, + 0x763c, 0x1b86, + 0x763d, 0x3ea4, + 0x763e, 0x1b8f, + 0x763f, 0x1b8c, + 0x7640, 0x1b89, + 0x7641, 0x3ea5, + 0x7642, 0x2028, + 0x7643, 0x1b8e, + 0x7644, 0x3ea6, + 0x7646, 0x25af, + 0x7648, 0x3ea8, + 0x7649, 0x25b1, + 0x764a, 0x3ea9, + 0x764c, 0x03b4, + 0x764d, 0x1b91, + 0x764e, 0x3eab, + 0x7654, 0x1b93, + 0x7655, 0x3eb1, + 0x7656, 0x1b95, + 0x7657, 0x3eb2, + 0x7658, 0x25ac, + 0x7659, 0x3eb3, + 0x765c, 0x1b94, + 0x765d, 0x3eb6, + 0x765e, 0x1b92, + 0x765f, 0x1e4e, + 0x7660, 0x3eb7, + 0x7662, 0x2202, + 0x7663, 0x0fcb, + 0x7664, 0x25ab, + 0x7665, 0x2286, + 0x7666, 0x3eb9, + 0x7667, 0x25ad, + 0x7668, 0x3eba, + 0x7669, 0x25b6, + 0x766a, 0x3ebb, + 0x766b, 0x1b96, + 0x766c, 0x21e3, + 0x766d, 0x25b4, + 0x766f, 0x1b97, + 0x7670, 0x222f, + 0x7671, 0x2165, + 0x7672, 0x25b7, + 0x7673, 0x3ebc, + 0x7678, 0x0748, + 0x7679, 0x3ec1, + 0x767b, 0x05a8, + 0x767c, 0x1ee9, + 0x767d, 0x03e2, + 0x767e, 0x03e4, + 0x767f, 0x3ec3, + 0x7682, 0x1130, + 0x7683, 0x3ec6, + 0x7684, 0x05a5, + 0x7685, 0x3ec7, + 0x7686, 0x08a5, + 0x7687, 0x07df, + 0x7688, 0x1b2d, + 0x7689, 0x3ec8, + 0x768b, 0x06d9, + 0x768c, 0x3eca, + 0x768e, 0x1b2e, + 0x768f, 0x3ecc, + 0x7691, 0x03b3, + 0x7692, 0x3ece, + 0x7693, 0x1b2f, + 0x7694, 0x3ecf, + 0x7696, 0x0e9f, + 0x7697, 0x3ed1, + 0x7699, 0x1b30, + 0x769a, 0x1e25, + 0x769b, 0x3ed3, + 0x76a4, 0x1b31, + 0x76a5, 0x3edc, + 0x76ae, 0x0bc3, + 0x76af, 0x3ee5, + 0x76b1, 0x11e4, + 0x76b2, 0x1bc8, + 0x76b3, 0x3ee7, + 0x76b4, 0x1bc9, + 0x76b5, 0x3ee8, + 0x76b8, 0x25c0, + 0x76b9, 0x3eeb, + 0x76ba, 0x229a, + 0x76bb, 0x3eec, + 0x76bf, 0x0af8, + 0x76c0, 0x3ef0, + 0x76c2, 0x10c0, + 0x76c3, 0x3ef2, + 0x76c5, 0x11d0, + 0x76c6, 0x0ba9, + 0x76c7, 0x3ef4, + 0x76c8, 0x1094, + 0x76c9, 0x3ef5, + 0x76ca, 0x106d, + 0x76cb, 0x3ef6, + 0x76cd, 0x1a8b, + 0x76ce, 0x03c6, + 0x76cf, 0x1156, + 0x76d0, 0x0ff7, + 0x76d1, 0x0853, + 0x76d2, 0x0787, + 0x76d3, 0x3ef8, + 0x76d4, 0x0985, + 0x76d5, 0x3ef9, + 0x76d6, 0x06c2, + 0x76d7, 0x05a2, + 0x76d8, 0x0b8d, + 0x76d9, 0x3efa, + 0x76db, 0x0d39, + 0x76dc, 0x3efc, + 0x76de, 0x226e, + 0x76df, 0x0ad0, + 0x76e0, 0x3efe, + 0x76e1, 0x1fbd, + 0x76e2, 0x3eff, + 0x76e3, 0x1f84, + 0x76e4, 0x20b2, + 0x76e5, 0x1a8c, + 0x76e6, 0x3f00, + 0x76e7, 0x2043, + 0x76e8, 0x3f01, + 0x76ee, 0x0b22, + 0x76ef, 0x05e1, + 0x76f0, 0x3f07, + 0x76f1, 0x1a58, + 0x76f2, 0x0aa9, + 0x76f3, 0x3f08, + 0x76f4, 0x11b0, + 0x76f5, 0x3f09, + 0x76f8, 0x0f4d, + 0x76f9, 0x1a5b, + 0x76fa, 0x3f0c, + 0x76fc, 0x0b8f, + 0x76fd, 0x3f0e, + 0x76fe, 0x061b, + 0x76ff, 0x3f0f, + 0x7700, 0x3f10, + 0x7701, 0x0d38, + 0x7702, 0x3f11, + 0x7704, 0x1a59, + 0x7705, 0x3f13, + 0x7707, 0x1a5c, + 0x7709, 0x0ac1, + 0x770a, 0x3f15, + 0x770b, 0x0941, + 0x770c, 0x3f16, + 0x770d, 0x1a5a, + 0x770e, 0x3f17, + 0x7719, 0x1a60, + 0x771a, 0x1a5e, + 0x771b, 0x3f22, + 0x771f, 0x1187, + 0x7720, 0x0ae4, + 0x7721, 0x3f26, + 0x7722, 0x1a5f, + 0x7723, 0x3f27, + 0x7726, 0x1a62, + 0x7727, 0x3f2a, + 0x7728, 0x1144, + 0x7729, 0x0fcc, + 0x772a, 0x3f2b, + 0x772d, 0x1a61, + 0x772e, 0x3f2e, + 0x772f, 0x0ad5, + 0x7730, 0x3f2f, + 0x7735, 0x1a63, + 0x7736, 0x0981, + 0x7737, 0x091b, + 0x7738, 0x1a64, + 0x7739, 0x3f34, + 0x773a, 0x0e4a, + 0x773b, 0x3f35, + 0x773c, 0x1004, + 0x773d, 0x3f36, + 0x7740, 0x1222, + 0x7741, 0x1197, + 0x7742, 0x3f39, + 0x7743, 0x1a68, + 0x7744, 0x3f3a, + 0x7747, 0x1a67, + 0x7748, 0x3f3d, + 0x774f, 0x2684, + 0x7750, 0x1a65, + 0x7752, 0x3f44, + 0x775a, 0x1a69, + 0x775b, 0x08d5, + 0x775c, 0x3f4c, + 0x775e, 0x24ef, + 0x775f, 0x3f4e, + 0x7761, 0x0da4, + 0x7762, 0x1a6b, + 0x7763, 0x05fc, + 0x7764, 0x3f50, + 0x7765, 0x1a6c, + 0x7766, 0x0b23, + 0x7767, 0x3f51, + 0x7768, 0x1a6a, + 0x7769, 0x3f52, + 0x776b, 0x08af, + 0x776c, 0x048e, + 0x776d, 0x3f54, + 0x7779, 0x0602, + 0x777a, 0x3f60, + 0x777d, 0x1a6f, + 0x777e, 0x1270, + 0x777f, 0x1a6d, + 0x7780, 0x1a70, + 0x7781, 0x3f63, + 0x7784, 0x0aee, + 0x7785, 0x0517, + 0x7786, 0x3f66, + 0x778c, 0x1a71, + 0x778d, 0x1a6e, + 0x778e, 0x0f26, + 0x778f, 0x3f6c, + 0x7791, 0x1a72, + 0x7792, 0x0a9e, + 0x7793, 0x3f6e, + 0x7798, 0x24ee, + 0x7799, 0x3f73, + 0x779e, 0x2074, + 0x779f, 0x1a73, + 0x77a1, 0x3f78, + 0x77a2, 0x1495, + 0x77a3, 0x3f79, + 0x77a5, 0x0bd2, + 0x77a6, 0x3f7b, + 0x77a7, 0x0c43, + 0x77a8, 0x3f7c, + 0x77a9, 0x11f4, + 0x77aa, 0x05aa, + 0x77ab, 0x3f7d, + 0x77ac, 0x0da7, + 0x77ad, 0x2687, + 0x77ae, 0x3f7e, + 0x77b0, 0x1a75, + 0x77b1, 0x3f80, + 0x77b3, 0x0e5c, + 0x77b4, 0x3f82, + 0x77b5, 0x1a76, + 0x77b6, 0x3f83, + 0x77bb, 0x1151, + 0x77bc, 0x24f0, + 0x77bd, 0x1a77, + 0x77be, 0x3f88, + 0x77bf, 0x1d7e, + 0x77c0, 0x3f89, + 0x77c7, 0x268d, + 0x77c8, 0x3f90, + 0x77cd, 0x1397, + 0x77ce, 0x3f95, + 0x77d7, 0x0526, + 0x77d8, 0x3f9e, + 0x77da, 0x22a0, + 0x77db, 0x0ab1, + 0x77dc, 0x1bca, + 0x77dd, 0x3fa0, + 0x77e2, 0x0d4f, + 0x77e3, 0x105a, + 0x77e4, 0x3fa5, + 0x77e5, 0x11a9, + 0x77e6, 0x3fa6, + 0x77e7, 0x1b1a, + 0x77e8, 0x3fa7, + 0x77e9, 0x0907, + 0x77ea, 0x3fa8, + 0x77eb, 0x0894, + 0x77ec, 0x1b1b, + 0x77ed, 0x060b, + 0x77ee, 0x03b6, + 0x77ef, 0x1fab, + 0x77f0, 0x3fa9, + 0x77f3, 0x0d46, + 0x77f4, 0x3fac, + 0x77f6, 0x1a22, + 0x77f7, 0x3fae, + 0x77f8, 0x1a23, + 0x77f9, 0x3faf, + 0x77fd, 0x0f08, + 0x77fe, 0x064c, + 0x77ff, 0x0980, + 0x7800, 0x1a24, + 0x7801, 0x0a92, + 0x7802, 0x0ce9, + 0x7803, 0x3fb3, + 0x7809, 0x1a25, + 0x780a, 0x3fb9, + 0x780c, 0x0c15, + 0x780d, 0x0940, + 0x780e, 0x3fbb, + 0x7811, 0x1a28, + 0x7812, 0x0bb9, + 0x7813, 0x3fbe, + 0x7814, 0x0ff9, + 0x7815, 0x3fbf, + 0x7816, 0x1206, + 0x7817, 0x1a26, + 0x7819, 0x3fc0, + 0x781a, 0x100b, + 0x781b, 0x3fc1, + 0x781c, 0x1a2b, + 0x781e, 0x3fc2, + 0x781f, 0x1a30, + 0x7820, 0x3fc3, + 0x7823, 0x1a34, + 0x7824, 0x3fc6, + 0x7825, 0x1a32, + 0x7826, 0x1a3a, + 0x7827, 0x1189, + 0x7828, 0x3fc7, + 0x7829, 0x1a35, + 0x782a, 0x3fc8, + 0x782c, 0x1a33, + 0x782d, 0x1a2a, + 0x782e, 0x3fca, + 0x7830, 0x0baa, + 0x7831, 0x3fcc, + 0x7834, 0x0be5, + 0x7835, 0x3fcf, + 0x7837, 0x0d22, + 0x7838, 0x1115, + 0x7839, 0x1a2d, + 0x783c, 0x1a31, + 0x783d, 0x3fd1, + 0x783e, 0x09e4, + 0x783f, 0x3fd2, + 0x7840, 0x0524, + 0x7841, 0x3fd3, + 0x7843, 0x26a8, + 0x7844, 0x3fd5, + 0x7845, 0x0741, + 0x7846, 0x3fd6, + 0x7847, 0x1a3c, + 0x7848, 0x3fd7, + 0x784c, 0x1a3d, + 0x784d, 0x3fdb, + 0x784e, 0x1a36, + 0x784f, 0x3fdc, + 0x7850, 0x1a3b, + 0x7851, 0x3fdd, + 0x7852, 0x0f07, + 0x7853, 0x3fde, + 0x7855, 0x0dab, + 0x7856, 0x1a38, + 0x7858, 0x3fe0, + 0x785d, 0x0f62, + 0x785e, 0x3fe5, + 0x7864, 0x24e9, + 0x7865, 0x3feb, + 0x7868, 0x24e5, + 0x7869, 0x3fee, + 0x786a, 0x1a3e, + 0x786b, 0x0a3b, + 0x786c, 0x1097, + 0x786d, 0x1a37, + 0x786e, 0x0c92, + 0x786f, 0x21fa, + 0x7870, 0x3fef, + 0x7877, 0x0862, + 0x7878, 0x3ff6, + 0x787c, 0x0bb1, + 0x787d, 0x3ffa, + 0x7887, 0x1a42, + 0x7888, 0x4004, + 0x7889, 0x05d0, + 0x788a, 0x4005, + 0x788c, 0x0a5c, + 0x788d, 0x03b8, + 0x788e, 0x0dde, + 0x788f, 0x4007, + 0x7891, 0x0417, + 0x7892, 0x4009, + 0x7893, 0x1a40, + 0x7894, 0x400a, + 0x7897, 0x0e9c, + 0x7898, 0x05c3, + 0x7899, 0x400d, + 0x789a, 0x1a41, + 0x789b, 0x1a3f, + 0x789c, 0x1a43, + 0x789d, 0x400e, + 0x789f, 0x05db, + 0x78a0, 0x4010, + 0x78a1, 0x1a44, + 0x78a2, 0x4011, + 0x78a3, 0x1a45, + 0x78a4, 0x4012, + 0x78a5, 0x1a48, + 0x78a6, 0x4013, + 0x78a7, 0x0435, + 0x78a8, 0x4014, + 0x78a9, 0x2148, + 0x78aa, 0x4015, + 0x78ad, 0x24e4, + 0x78ae, 0x4018, + 0x78b0, 0x0bb7, + 0x78b1, 0x0861, + 0x78b2, 0x1a46, + 0x78b3, 0x0e0f, + 0x78b4, 0x04b1, + 0x78b5, 0x401a, + 0x78b8, 0x24e6, + 0x78b9, 0x1a47, + 0x78ba, 0x20f7, + 0x78bb, 0x401d, + 0x78bc, 0x206b, + 0x78bd, 0x401e, + 0x78be, 0x0b4e, + 0x78bf, 0x401f, + 0x78c1, 0x0548, + 0x78c2, 0x4021, + 0x78c5, 0x0400, + 0x78c6, 0x4024, + 0x78c9, 0x1a4b, + 0x78ca, 0x09c5, + 0x78cb, 0x056b, + 0x78cc, 0x4027, + 0x78d0, 0x0b8e, + 0x78d1, 0x402b, + 0x78d4, 0x1a49, + 0x78d5, 0x0951, + 0x78d6, 0x402e, + 0x78d9, 0x1a4a, + 0x78da, 0x22a7, + 0x78db, 0x4031, + 0x78e3, 0x24ec, + 0x78e4, 0x4039, + 0x78e7, 0x24eb, + 0x78e8, 0x0b08, + 0x78e9, 0x403c, + 0x78ec, 0x1a4c, + 0x78ed, 0x403f, + 0x78ef, 0x24e3, + 0x78f0, 0x4041, + 0x78f2, 0x1a4d, + 0x78f3, 0x4043, + 0x78f4, 0x1a4f, + 0x78f5, 0x4044, + 0x78f7, 0x0a20, + 0x78f8, 0x4046, + 0x78fa, 0x07dc, + 0x78fb, 0x4048, + 0x78fd, 0x24ea, + 0x78fe, 0x404a, + 0x7900, 0x404c, + 0x7901, 0x0889, + 0x7902, 0x404d, + 0x7905, 0x1a4e, + 0x7906, 0x4050, + 0x790e, 0x1e92, + 0x790f, 0x4058, + 0x7913, 0x1a50, + 0x7914, 0x405c, + 0x7919, 0x1e27, + 0x791a, 0x4061, + 0x791e, 0x1a52, + 0x791f, 0x4065, + 0x7924, 0x1a51, + 0x7925, 0x406a, + 0x7926, 0x1fe6, + 0x7927, 0x406b, + 0x792a, 0x24e7, + 0x792b, 0x2012, + 0x792c, 0x1eec, + 0x792d, 0x406e, + 0x7931, 0x24e8, + 0x7932, 0x4072, + 0x7934, 0x1a53, + 0x7935, 0x4074, + 0x793a, 0x0d55, + 0x793b, 0x19f8, + 0x793c, 0x09dc, + 0x793d, 0x4079, + 0x793e, 0x0d20, + 0x793f, 0x407a, + 0x7940, 0x19f9, + 0x7941, 0x0c0d, + 0x7942, 0x407b, + 0x7946, 0x19fa, + 0x7947, 0x407f, + 0x7948, 0x0c0c, + 0x7949, 0x19fb, + 0x794a, 0x4080, + 0x7953, 0x19fe, + 0x7954, 0x4089, + 0x7956, 0x1243, + 0x7957, 0x1a01, + 0x7958, 0x408b, + 0x795a, 0x19ff, + 0x795b, 0x19fc, + 0x795d, 0x1200, + 0x795e, 0x0d2a, + 0x795f, 0x0de3, + 0x7960, 0x1a02, + 0x7961, 0x408d, + 0x7962, 0x1a00, + 0x7963, 0x408e, + 0x7965, 0x0f56, + 0x7966, 0x4090, + 0x7967, 0x1a04, + 0x7968, 0x0bd0, + 0x7969, 0x4091, + 0x796d, 0x0833, + 0x796e, 0x4095, + 0x796f, 0x1a03, + 0x7970, 0x4096, + 0x7977, 0x059c, + 0x7978, 0x080b, + 0x7979, 0x409d, + 0x797a, 0x1a05, + 0x797b, 0x409e, + 0x7980, 0x130b, + 0x7981, 0x08cc, + 0x7982, 0x40a3, + 0x7984, 0x0a62, + 0x7985, 0x1a06, + 0x7986, 0x40a5, + 0x798a, 0x1a07, + 0x798b, 0x40a9, + 0x798d, 0x1f66, + 0x798e, 0x24dc, + 0x798f, 0x069e, + 0x7990, 0x40ab, + 0x799a, 0x1a08, + 0x799b, 0x40b5, + 0x79a6, 0x26a2, + 0x79a7, 0x1a09, + 0x79a8, 0x40c0, + 0x79aa, 0x24dd, + 0x79ab, 0x40c2, + 0x79ae, 0x200e, + 0x79af, 0x40c5, + 0x79b0, 0x24db, + 0x79b1, 0x1eb8, + 0x79b2, 0x40c6, + 0x79b3, 0x1a0a, + 0x79b4, 0x40c7, + 0x79b9, 0x10d2, + 0x79ba, 0x1264, + 0x79bb, 0x09d6, + 0x79bc, 0x40cc, + 0x79bd, 0x0c5a, + 0x79be, 0x0783, + 0x79bf, 0x40cd, + 0x79c0, 0x0fae, + 0x79c1, 0x0db2, + 0x79c2, 0x40ce, + 0x79c3, 0x0e6b, + 0x79c4, 0x40cf, + 0x79c6, 0x06cc, + 0x79c7, 0x40d1, + 0x79c9, 0x0465, + 0x79ca, 0x40d3, + 0x79cb, 0x0c6c, + 0x79cc, 0x40d4, + 0x79cd, 0x11d5, + 0x79ce, 0x40d5, + 0x79d1, 0x0953, + 0x79d2, 0x0af0, + 0x79d3, 0x40d8, + 0x79d5, 0x1b1d, + 0x79d6, 0x40da, + 0x79d8, 0x0add, + 0x79d9, 0x40dc, + 0x79df, 0x123f, + 0x79e0, 0x40e2, + 0x79e3, 0x1b1f, + 0x79e4, 0x04f8, + 0x79e5, 0x40e5, + 0x79e6, 0x0c55, + 0x79e7, 0x1016, + 0x79e8, 0x40e6, + 0x79e9, 0x11c7, + 0x79ea, 0x40e7, + 0x79eb, 0x1b20, + 0x79ec, 0x40e8, + 0x79ed, 0x1b1e, + 0x79ee, 0x40e9, + 0x79ef, 0x0812, + 0x79f0, 0x04eb, + 0x79f1, 0x40ea, + 0x79f8, 0x08a6, + 0x79f9, 0x40f1, + 0x79fb, 0x104d, + 0x79fc, 0x40f3, + 0x79fd, 0x07f5, + 0x79fe, 0x40f4, + 0x7a00, 0x0f0e, + 0x7a01, 0x40f6, + 0x7a02, 0x1b24, + 0x7a03, 0x1b23, + 0x7a04, 0x40f7, + 0x7a06, 0x1b21, + 0x7a07, 0x40f9, + 0x7a0b, 0x04f1, + 0x7a0c, 0x40fd, + 0x7a0d, 0x0d0d, + 0x7a0e, 0x0da5, + 0x7a0f, 0x40fe, + 0x7a14, 0x1b26, + 0x7a15, 0x4103, + 0x7a17, 0x03e9, + 0x7a18, 0x4105, + 0x7a1a, 0x11c8, + 0x7a1b, 0x4107, + 0x7a1e, 0x1b25, + 0x7a1f, 0x410a, + 0x7a20, 0x0512, + 0x7a21, 0x410b, + 0x7a23, 0x1d8f, + 0x7a24, 0x410d, + 0x7a2e, 0x2295, + 0x7a2f, 0x4117, + 0x7a31, 0x1e80, + 0x7a32, 0x4119, + 0x7a33, 0x0ed7, + 0x7a34, 0x411a, + 0x7a37, 0x1b28, + 0x7a38, 0x411d, + 0x7a39, 0x1b27, + 0x7a3a, 0x411e, + 0x7a3b, 0x059f, + 0x7a3c, 0x084d, + 0x7a3d, 0x0811, + 0x7a3e, 0x411f, + 0x7a3f, 0x06e0, + 0x7a40, 0x2677, + 0x7a41, 0x4120, + 0x7a46, 0x0b25, + 0x7a47, 0x4125, + 0x7a4c, 0x2624, + 0x7a4d, 0x1f69, + 0x7a4e, 0x222b, + 0x7a4f, 0x412a, + 0x7a51, 0x1b29, + 0x7a52, 0x412c, + 0x7a57, 0x0de0, + 0x7a58, 0x4131, + 0x7a61, 0x257f, + 0x7a62, 0x1f5b, + 0x7a63, 0x413a, + 0x7a69, 0x219b, + 0x7a6a, 0x4140, + 0x7a6b, 0x267d, + 0x7a6c, 0x4141, + 0x7a70, 0x1b2c, + 0x7a71, 0x4145, + 0x7a74, 0x0fd1, + 0x7a75, 0x4148, + 0x7a76, 0x08ee, + 0x7a77, 0x0c6b, + 0x7a78, 0x1b9a, + 0x7a7a, 0x0962, + 0x7a7b, 0x4149, + 0x7a7f, 0x052c, + 0x7a80, 0x1b9c, + 0x7a81, 0x0e6c, + 0x7a82, 0x414d, + 0x7a83, 0x0c51, + 0x7a84, 0x114e, + 0x7a85, 0x414e, + 0x7a86, 0x1b9d, + 0x7a87, 0x414f, + 0x7a88, 0x1b9e, + 0x7a89, 0x4150, + 0x7a8d, 0x0c4c, + 0x7a8e, 0x4154, + 0x7a91, 0x102b, + 0x7a92, 0x11ce, + 0x7a93, 0x4157, + 0x7a95, 0x1b9f, + 0x7a96, 0x08a2, + 0x7a97, 0x0533, + 0x7a98, 0x08ec, + 0x7a99, 0x4159, + 0x7a9c, 0x055f, + 0x7a9d, 0x0ee0, + 0x7a9e, 0x415c, + 0x7a9f, 0x096c, + 0x7aa0, 0x1ba1, + 0x7aa1, 0x415d, + 0x7aa5, 0x0987, + 0x7aa6, 0x1ba0, + 0x7aa7, 0x4161, + 0x7aa8, 0x1ba3, + 0x7aa9, 0x21a0, + 0x7aaa, 0x2186, + 0x7aab, 0x4162, + 0x7aac, 0x1ba2, + 0x7aad, 0x1ba4, + 0x7aae, 0x20ed, + 0x7aaf, 0x4163, + 0x7ab3, 0x1ba5, + 0x7ab4, 0x4167, + 0x7ab6, 0x25b9, + 0x7ab7, 0x4169, + 0x7aba, 0x1fea, + 0x7abb, 0x416c, + 0x7abf, 0x0a47, + 0x7ac0, 0x4170, + 0x7ac4, 0x1ea4, + 0x7ac5, 0x20e1, + 0x7ac6, 0x4174, + 0x7ac7, 0x25b8, + 0x7ac8, 0x2260, + 0x7ac9, 0x4175, + 0x7aca, 0x20e2, + 0x7acb, 0x09eb, + 0x7acc, 0x4176, + 0x7ad6, 0x0d91, + 0x7ad7, 0x4180, + 0x7ad9, 0x115f, + 0x7ada, 0x4182, + 0x7ade, 0x08e9, + 0x7adf, 0x08e8, + 0x7ae0, 0x1163, + 0x7ae1, 0x4186, + 0x7ae3, 0x092f, + 0x7ae4, 0x4188, + 0x7ae5, 0x0e60, + 0x7ae6, 0x1b99, + 0x7ae7, 0x4189, + 0x7aea, 0x2141, + 0x7aeb, 0x418c, + 0x7aed, 0x08b0, + 0x7aee, 0x418e, + 0x7aef, 0x060a, + 0x7af0, 0x418f, + 0x7af6, 0x1fc7, + 0x7af7, 0x4195, + 0x7af9, 0x11f0, + 0x7afa, 0x1c63, + 0x7afb, 0x4197, + 0x7afd, 0x1c64, + 0x7afe, 0x4199, + 0x7aff, 0x06c8, + 0x7b00, 0x419a, + 0x7b03, 0x1c66, + 0x7b05, 0x419d, + 0x7b06, 0x03d5, + 0x7b07, 0x419e, + 0x7b08, 0x1c65, + 0x7b09, 0x419f, + 0x7b0a, 0x1c69, + 0x7b0b, 0x0de6, + 0x7b0c, 0x41a0, + 0x7b0f, 0x1c6b, + 0x7b10, 0x41a3, + 0x7b11, 0x0f71, + 0x7b12, 0x41a4, + 0x7b14, 0x0433, + 0x7b15, 0x1c68, + 0x7b16, 0x41a6, + 0x7b19, 0x1c6f, + 0x7b1a, 0x41a9, + 0x7b1b, 0x05b2, + 0x7b1c, 0x41aa, + 0x7b1e, 0x1c77, + 0x7b1f, 0x41ac, + 0x7b20, 0x1c72, + 0x7b21, 0x41ad, + 0x7b24, 0x1c74, + 0x7b25, 0x1c73, + 0x7b26, 0x0698, + 0x7b27, 0x41b0, + 0x7b28, 0x0428, + 0x7b29, 0x41b1, + 0x7b2a, 0x1c6e, + 0x7b2b, 0x1c6a, + 0x7b2c, 0x05bb, + 0x7b2d, 0x41b2, + 0x7b2e, 0x1c70, + 0x7b2f, 0x41b3, + 0x7b31, 0x1c71, + 0x7b32, 0x41b5, + 0x7b33, 0x1c75, + 0x7b34, 0x41b6, + 0x7b38, 0x1c6d, + 0x7b39, 0x41ba, + 0x7b3a, 0x0856, + 0x7b3b, 0x41bb, + 0x7b3c, 0x0a46, + 0x7b3d, 0x41bc, + 0x7b3e, 0x1c76, + 0x7b3f, 0x41bd, + 0x7b45, 0x1c7a, + 0x7b46, 0x1e41, + 0x7b47, 0x1c6c, + 0x7b48, 0x41c3, + 0x7b49, 0x05a9, + 0x7b4a, 0x41c4, + 0x7b4b, 0x08bf, + 0x7b4c, 0x1c7c, + 0x7b4d, 0x41c5, + 0x7b4f, 0x0641, + 0x7b50, 0x097d, + 0x7b51, 0x11fd, + 0x7b52, 0x0e63, + 0x7b53, 0x41c7, + 0x7b54, 0x0573, + 0x7b55, 0x41c8, + 0x7b56, 0x04a6, + 0x7b57, 0x41c9, + 0x7b58, 0x1c78, + 0x7b59, 0x41ca, + 0x7b5a, 0x1c79, + 0x7b5b, 0x0cf1, + 0x7b5c, 0x41cb, + 0x7b5d, 0x1c7d, + 0x7b5e, 0x41cc, + 0x7b60, 0x1c7e, + 0x7b61, 0x41ce, + 0x7b62, 0x1c81, + 0x7b63, 0x41cf, + 0x7b67, 0x25e4, + 0x7b68, 0x41d3, + 0x7b6e, 0x1c7f, + 0x7b6f, 0x41d9, + 0x7b71, 0x1c83, + 0x7b72, 0x1c82, + 0x7b73, 0x41db, + 0x7b75, 0x1c7b, + 0x7b76, 0x41dd, + 0x7b77, 0x0977, + 0x7b78, 0x41de, + 0x7b79, 0x0514, + 0x7b7a, 0x41df, + 0x7b7b, 0x1c80, + 0x7b7c, 0x41e0, + 0x7b7e, 0x0c26, + 0x7b7f, 0x41e2, + 0x7b80, 0x0865, + 0x7b81, 0x41e3, + 0x7b85, 0x1c8b, + 0x7b86, 0x41e7, + 0x7b8b, 0x1f86, + 0x7b8c, 0x41ec, + 0x7b8d, 0x0718, + 0x7b8e, 0x41ed, + 0x7b90, 0x1c84, + 0x7b91, 0x41ef, + 0x7b94, 0x0474, + 0x7b95, 0x0813, + 0x7b96, 0x41f2, + 0x7b97, 0x0dd8, + 0x7b98, 0x41f3, + 0x7b9c, 0x1c8d, + 0x7b9d, 0x1c89, + 0x7b9e, 0x41f7, + 0x7ba1, 0x0735, + 0x7ba2, 0x1c8e, + 0x7ba3, 0x41fa, + 0x7ba6, 0x1c85, + 0x7ba8, 0x1c8a, + 0x7ba9, 0x0a88, + 0x7baa, 0x1c8c, + 0x7bab, 0x1c8f, + 0x7bac, 0x1c88, + 0x7bad, 0x0870, + 0x7bae, 0x41fd, + 0x7bb1, 0x0f51, + 0x7bb2, 0x4200, + 0x7bb4, 0x1c90, + 0x7bb5, 0x4202, + 0x7bb8, 0x1c87, + 0x7bb9, 0x4205, + 0x7bc0, 0x1fb3, + 0x7bc1, 0x1c92, + 0x7bc2, 0x420c, + 0x7bc4, 0x1eef, + 0x7bc5, 0x420e, + 0x7bc6, 0x120a, + 0x7bc7, 0x0bc9, + 0x7bc8, 0x420f, + 0x7bc9, 0x22a4, + 0x7bca, 0x4210, + 0x7bcb, 0x25e8, + 0x7bcc, 0x1c93, + 0x7bcd, 0x4211, + 0x7bd1, 0x1c91, + 0x7bd2, 0x4215, + 0x7bd3, 0x0a4f, + 0x7bd4, 0x4216, + 0x7bd9, 0x06d8, + 0x7bda, 0x1c95, + 0x7bdb, 0x421b, + 0x7bdd, 0x1c94, + 0x7bde, 0x421d, + 0x7be1, 0x055e, + 0x7be2, 0x4220, + 0x7be4, 0x25e3, + 0x7be5, 0x1c96, + 0x7be7, 0x4222, + 0x7be9, 0x2111, + 0x7bea, 0x1c98, + 0x7beb, 0x4224, + 0x7bee, 0x09a5, + 0x7bef, 0x4227, + 0x7bf1, 0x09d4, + 0x7bf2, 0x4229, + 0x7bf3, 0x25e6, + 0x7bf4, 0x422a, + 0x7bf7, 0x0bb2, + 0x7bf8, 0x422d, + 0x7bfc, 0x1c9b, + 0x7bfd, 0x4231, + 0x7bfe, 0x1c9a, + 0x7bff, 0x4232, + 0x7c00, 0x25e7, + 0x7c01, 0x4233, + 0x7c07, 0x055b, + 0x7c08, 0x4239, + 0x7c0b, 0x1c9e, + 0x7c0c, 0x1c99, + 0x7c0d, 0x2041, + 0x7c0e, 0x423c, + 0x7c0f, 0x1c9c, + 0x7c10, 0x423d, + 0x7c16, 0x1c9d, + 0x7c17, 0x4243, + 0x7c1e, 0x25ea, + 0x7c1f, 0x1c9f, + 0x7c20, 0x424a, + 0x7c21, 0x1f8f, + 0x7c22, 0x424b, + 0x7c23, 0x25ec, + 0x7c24, 0x424c, + 0x7c26, 0x1ca1, + 0x7c27, 0x07de, + 0x7c28, 0x424e, + 0x7c2a, 0x1ca0, + 0x7c2b, 0x25eb, + 0x7c2c, 0x4250, + 0x7c38, 0x1ca2, + 0x7c39, 0x425c, + 0x7c3d, 0x20d0, + 0x7c3e, 0x201d, + 0x7c3f, 0x0485, + 0x7c40, 0x1ca4, + 0x7c41, 0x1ca3, + 0x7c42, 0x4260, + 0x7c43, 0x1ff7, + 0x7c44, 0x4261, + 0x7c4c, 0x1e8d, + 0x7c4d, 0x0821, + 0x7c4e, 0x4269, + 0x7c5c, 0x25e9, + 0x7c5d, 0x4277, + 0x7c5f, 0x25ee, + 0x7c60, 0x203a, + 0x7c61, 0x4279, + 0x7c64, 0x2693, + 0x7c65, 0x427c, + 0x7c69, 0x25e5, + 0x7c6a, 0x25ed, + 0x7c6b, 0x4280, + 0x7c6c, 0x2009, + 0x7c6d, 0x4281, + 0x7c6e, 0x2065, + 0x7c6f, 0x4282, + 0x7c72, 0x26a3, + 0x7c73, 0x0adc, + 0x7c74, 0x12f5, + 0x7c75, 0x4285, + 0x7c7b, 0x09cb, + 0x7c7c, 0x1cca, + 0x7c7d, 0x122e, + 0x7c7e, 0x428b, + 0x7c89, 0x0678, + 0x7c8a, 0x4296, + 0x7c91, 0x1ccc, + 0x7c92, 0x09ec, + 0x7c93, 0x429d, + 0x7c95, 0x0be8, + 0x7c96, 0x429f, + 0x7c97, 0x0559, + 0x7c98, 0x1154, + 0x7c99, 0x42a0, + 0x7c9c, 0x1cce, + 0x7c9d, 0x1ccd, + 0x7c9e, 0x1ccf, + 0x7c9f, 0x0dcf, + 0x7ca0, 0x42a3, + 0x7ca2, 0x1cd0, + 0x7ca3, 0x42a5, + 0x7ca4, 0x1104, + 0x7ca5, 0x11df, + 0x7ca6, 0x42a6, + 0x7caa, 0x067d, + 0x7cab, 0x42aa, + 0x7cae, 0x0a01, + 0x7caf, 0x42ad, + 0x7cb1, 0x0a04, + 0x7cb2, 0x1cd1, + 0x7cb3, 0x08db, + 0x7cb4, 0x42af, + 0x7cb9, 0x0565, + 0x7cba, 0x42b4, + 0x7cbc, 0x1cd2, + 0x7cbe, 0x08da, + 0x7cbf, 0x42b6, + 0x7cc1, 0x1cd4, + 0x7cc2, 0x42b8, + 0x7cc5, 0x1cd9, + 0x7cc6, 0x42bb, + 0x7cc7, 0x1cd5, + 0x7cc8, 0x1cd8, + 0x7cc9, 0x42bc, + 0x7cca, 0x07b4, + 0x7ccb, 0x42bd, + 0x7ccc, 0x1cd6, + 0x7cce, 0x42be, + 0x7cd5, 0x06dd, + 0x7cd6, 0x0e1a, + 0x7cd7, 0x1cda, + 0x7cd8, 0x42c5, + 0x7cd9, 0x04a1, + 0x7cda, 0x42c6, + 0x7cdc, 0x0ad8, + 0x7cdd, 0x25f5, + 0x7cde, 0x1efc, + 0x7cdf, 0x1126, + 0x7ce0, 0x0944, + 0x7ce1, 0x42c8, + 0x7ce7, 0x2024, + 0x7ce8, 0x1cdb, + 0x7ce9, 0x42ce, + 0x7cef, 0x0b75, + 0x7cf0, 0x269b, + 0x7cf1, 0x42d4, + 0x7cf2, 0x25f3, + 0x7cf3, 0x42d5, + 0x7cf4, 0x22d9, + 0x7cf5, 0x42d6, + 0x7cf6, 0x25f4, + 0x7cf7, 0x42d7, + 0x7cf8, 0x1ce7, + 0x7cf9, 0x241b, + 0x7cfa, 0x42d8, + 0x7cfb, 0x0f22, + 0x7cfc, 0x42d9, + 0x7cfe, 0x1fc8, + 0x7cff, 0x42db, + 0x7d00, 0x1f7b, + 0x7d01, 0x42dc, + 0x7d02, 0x241d, + 0x7d03, 0x42dd, + 0x7d04, 0x224c, + 0x7d05, 0x1f48, + 0x7d06, 0x241c, + 0x7d07, 0x241e, + 0x7d09, 0x20ff, + 0x7d0a, 0x0ed8, + 0x7d0b, 0x219a, + 0x7d0c, 0x42de, + 0x7d0d, 0x2091, + 0x7d0e, 0x42df, + 0x7d10, 0x20a7, + 0x7d11, 0x42e1, + 0x7d13, 0x2423, + 0x7d14, 0x1e9b, + 0x7d15, 0x2422, + 0x7d16, 0x42e3, + 0x7d17, 0x2110, + 0x7d18, 0x42e4, + 0x7d19, 0x228d, + 0x7d1a, 0x1f71, + 0x7d1b, 0x1ef8, + 0x7d1c, 0x2421, + 0x7d1d, 0x42e5, + 0x7d20, 0x0dcd, + 0x7d21, 0x1ef3, + 0x7d22, 0x0dec, + 0x7d23, 0x42e8, + 0x7d27, 0x08c5, + 0x7d28, 0x42ec, + 0x7d2b, 0x122c, + 0x7d2c, 0x42ef, + 0x7d2f, 0x09c6, + 0x7d30, 0x21b1, + 0x7d31, 0x2426, + 0x7d32, 0x2425, + 0x7d33, 0x2120, + 0x7d34, 0x42f2, + 0x7d39, 0x211a, + 0x7d3a, 0x2424, + 0x7d3b, 0x42f7, + 0x7d3c, 0x2428, + 0x7d3d, 0x42f8, + 0x7d3f, 0x242a, + 0x7d40, 0x2429, + 0x7d41, 0x42fa, + 0x7d42, 0x2294, + 0x7d43, 0x42fb, + 0x7d44, 0x22be, + 0x7d45, 0x42fc, + 0x7d46, 0x1e31, + 0x7d47, 0x42fd, + 0x7d4e, 0x242c, + 0x7d4f, 0x4304, + 0x7d50, 0x1fb5, + 0x7d51, 0x4305, + 0x7d5d, 0x242b, + 0x7d5e, 0x1faf, + 0x7d5f, 0x4311, + 0x7d61, 0x2068, + 0x7d62, 0x21e4, + 0x7d63, 0x4313, + 0x7d66, 0x1f21, + 0x7d67, 0x4316, + 0x7d68, 0x2101, + 0x7d69, 0x4317, + 0x7d6e, 0x0fc0, + 0x7d6f, 0x431c, + 0x7d71, 0x217c, + 0x7d72, 0x214a, + 0x7d73, 0x242d, + 0x7d74, 0x431e, + 0x7d76, 0x1fd4, + 0x7d77, 0x1ce8, + 0x7d78, 0x4320, + 0x7d79, 0x1fd1, + 0x7d7a, 0x4321, + 0x7d81, 0x1e33, + 0x7d82, 0x4328, + 0x7d83, 0x242f, + 0x7d84, 0x4329, + 0x7d86, 0x242e, + 0x7d87, 0x432b, + 0x7d88, 0x2430, + 0x7d89, 0x21db, + 0x7d8a, 0x432c, + 0x7d8f, 0x2158, + 0x7d90, 0x4331, + 0x7d93, 0x1fc2, + 0x7d94, 0x4334, + 0x7d9c, 0x22b9, + 0x7d9d, 0x433c, + 0x7d9e, 0x2436, + 0x7d9f, 0x433d, + 0x7da2, 0x1e8e, + 0x7da3, 0x2439, + 0x7da4, 0x4340, + 0x7da6, 0x1ce9, + 0x7da7, 0x4342, + 0x7dab, 0x21c5, + 0x7dac, 0x2437, + 0x7dad, 0x2192, + 0x7dae, 0x1cea, + 0x7daf, 0x4346, + 0x7db0, 0x243a, + 0x7db1, 0x1f19, + 0x7db2, 0x218c, + 0x7db3, 0x1e40, + 0x7db4, 0x22b3, + 0x7db5, 0x4347, + 0x7db8, 0x205f, + 0x7db9, 0x2438, + 0x7dba, 0x2432, + 0x7dbb, 0x2274, + 0x7dbc, 0x434a, + 0x7dbd, 0x1e9c, + 0x7dbe, 0x2431, + 0x7dbf, 0x2085, + 0x7dc0, 0x434b, + 0x7dc4, 0x2435, + 0x7dc5, 0x434f, + 0x7dc7, 0x243b, + 0x7dc8, 0x4351, + 0x7dca, 0x1fb7, + 0x7dcb, 0x2433, + 0x7dcc, 0x4353, + 0x7dd1, 0x2054, + 0x7dd2, 0x21de, + 0x7dd3, 0x4358, + 0x7dd4, 0x2434, + 0x7dd5, 0x4359, + 0x7dd7, 0x243d, + 0x7dd8, 0x1f89, + 0x7dd9, 0x243c, + 0x7dda, 0x435b, + 0x7ddd, 0x1f6e, + 0x7dde, 0x1ed8, + 0x7ddf, 0x435e, + 0x7de0, 0x1ebf, + 0x7de1, 0x2445, + 0x7de2, 0x435f, + 0x7de3, 0x2249, + 0x7de4, 0x4360, + 0x7de6, 0x2441, + 0x7de7, 0x4362, + 0x7de8, 0x1e47, + 0x7de9, 0x1f56, + 0x7dea, 0x4363, + 0x7dec, 0x2086, + 0x7ded, 0x4365, + 0x7def, 0x2196, + 0x7df0, 0x4367, + 0x7df1, 0x2443, + 0x7df2, 0x243f, + 0x7df3, 0x4368, + 0x7df4, 0x2023, + 0x7df5, 0x4369, + 0x7df6, 0x2442, + 0x7df7, 0x436a, + 0x7df9, 0x243e, + 0x7dfa, 0x436c, + 0x7dfb, 0x26a6, + 0x7dfc, 0x436d, + 0x7e00, 0x4371, + 0x7e08, 0x234e, + 0x7e09, 0x2446, + 0x7e0a, 0x244b, + 0x7e0b, 0x2444, + 0x7e0c, 0x4379, + 0x7e10, 0x2427, + 0x7e11, 0x244c, + 0x7e12, 0x437d, + 0x7e1b, 0x1f0f, + 0x7e1c, 0x4386, + 0x7e1d, 0x2447, + 0x7e1e, 0x2449, + 0x7e1f, 0x2448, + 0x7e20, 0x4387, + 0x7e23, 0x21c2, + 0x7e24, 0x438a, + 0x7e27, 0x216e, + 0x7e28, 0x438d, + 0x7e2b, 0x1f03, + 0x7e2c, 0x4390, + 0x7e2d, 0x244a, + 0x7e2e, 0x215c, + 0x7e2f, 0x4391, + 0x7e31, 0x22bb, + 0x7e32, 0x2450, + 0x7e33, 0x4393, + 0x7e34, 0x2694, + 0x7e35, 0x244f, + 0x7e36, 0x25f6, + 0x7e37, 0x2051, + 0x7e38, 0x4394, + 0x7e39, 0x244e, + 0x7e3a, 0x4395, + 0x7e3b, 0x1dfb, + 0x7e3c, 0x4396, + 0x7e3d, 0x22ba, + 0x7e3e, 0x1f6d, + 0x7e3f, 0x4397, + 0x7e41, 0x064e, + 0x7e42, 0x4399, + 0x7e45, 0x2452, + 0x7e46, 0x2451, + 0x7e47, 0x1ceb, + 0x7e48, 0x439c, + 0x7e52, 0x2455, + 0x7e53, 0x43a6, + 0x7e54, 0x2289, + 0x7e55, 0x2116, + 0x7e56, 0x43a7, + 0x7e5a, 0x2454, + 0x7e5b, 0x43ab, + 0x7e5e, 0x20fb, + 0x7e5f, 0x43ae, + 0x7e62, 0x2440, + 0x7e63, 0x43b1, + 0x7e69, 0x2126, + 0x7e6a, 0x1f61, + 0x7e6b, 0x269d, + 0x7e6c, 0x43b7, + 0x7e6d, 0x1f8a, + 0x7e6e, 0x2456, + 0x7e6f, 0x2459, + 0x7e70, 0x2458, + 0x7e71, 0x43b8, + 0x7e73, 0x1fae, + 0x7e74, 0x43ba, + 0x7e79, 0x221a, + 0x7e7a, 0x43bf, + 0x7e7c, 0x1f7a, + 0x7e7d, 0x244d, + 0x7e7e, 0x2457, + 0x7e7f, 0x43c1, + 0x7e82, 0x1248, + 0x7e83, 0x43c4, + 0x7e88, 0x2453, + 0x7e89, 0x43c9, + 0x7e8a, 0x2420, + 0x7e8b, 0x43ca, + 0x7e8c, 0x21df, + 0x7e8d, 0x2685, + 0x7e8e, 0x43cb, + 0x7e8f, 0x1e6e, + 0x7e90, 0x43cc, + 0x7e93, 0x2224, + 0x7e94, 0x2670, + 0x7e95, 0x43cf, + 0x7e96, 0x21ba, + 0x7e97, 0x43d0, + 0x7e98, 0x245a, + 0x7e99, 0x43d1, + 0x7e9b, 0x1cec, + 0x7e9c, 0x1fff, + 0x7e9d, 0x43d3, + 0x7e9f, 0x17d3, + 0x7ea0, 0x08ef, + 0x7ea1, 0x17d4, + 0x7ea2, 0x07a3, + 0x7ea3, 0x17d5, + 0x7ea4, 0x0f38, + 0x7ea5, 0x17d6, + 0x7ea6, 0x10ff, + 0x7ea7, 0x0829, + 0x7ea8, 0x17d7, + 0x7eaa, 0x0840, + 0x7eab, 0x0cad, + 0x7eac, 0x0ec2, + 0x7ead, 0x17d9, + 0x7eae, 0x43d5, + 0x7eaf, 0x0542, + 0x7eb0, 0x17da, + 0x7eb1, 0x0ced, + 0x7eb2, 0x06d4, + 0x7eb3, 0x0b2c, + 0x7eb4, 0x43d6, + 0x7eb5, 0x123a, + 0x7eb6, 0x0a81, + 0x7eb7, 0x0674, + 0x7eb8, 0x11bc, + 0x7eb9, 0x0ed5, + 0x7eba, 0x0661, + 0x7ebb, 0x43d7, + 0x7ebd, 0x0b67, + 0x7ebe, 0x17db, + 0x7ebf, 0x0f4c, + 0x7ec0, 0x17dc, + 0x7ec3, 0x0a00, + 0x7ec4, 0x1246, + 0x7ec5, 0x0d29, + 0x7ec6, 0x0f25, + 0x7ec7, 0x11ae, + 0x7ec8, 0x11d4, + 0x7ec9, 0x17df, + 0x7eca, 0x03f8, + 0x7ecb, 0x17e0, + 0x7ecd, 0x0d15, + 0x7ece, 0x1076, + 0x7ecf, 0x08dc, + 0x7ed0, 0x17e2, + 0x7ed1, 0x03fe, + 0x7ed2, 0x0cb9, + 0x7ed3, 0x08b2, + 0x7ed4, 0x17e3, + 0x7ed5, 0x0ca1, + 0x7ed6, 0x43d9, + 0x7ed7, 0x17e4, + 0x7ed8, 0x07fb, + 0x7ed9, 0x06f3, + 0x7eda, 0x0fcd, + 0x7edb, 0x17e5, + 0x7edc, 0x0a8e, + 0x7edd, 0x0927, + 0x7ede, 0x089b, + 0x7edf, 0x0e64, + 0x7ee0, 0x17e6, + 0x7ee2, 0x091d, + 0x7ee3, 0x0fb0, + 0x7ee4, 0x43da, + 0x7ee5, 0x0ddc, + 0x7ee6, 0x0e23, + 0x7ee7, 0x083f, + 0x7ee8, 0x17e8, + 0x7ee9, 0x081b, + 0x7eea, 0x0fc2, + 0x7eeb, 0x17e9, + 0x7eec, 0x43db, + 0x7eed, 0x0fc3, + 0x7eee, 0x17ea, + 0x7ef0, 0x0545, + 0x7ef1, 0x17ec, + 0x7ef3, 0x0d37, + 0x7ef4, 0x0ebb, + 0x7ef5, 0x0ae5, + 0x7ef6, 0x17ef, + 0x7ef7, 0x042a, + 0x7ef8, 0x0516, + 0x7ef9, 0x43dc, + 0x7efa, 0x17f0, + 0x7efc, 0x1238, + 0x7efd, 0x1161, + 0x7efe, 0x17f2, + 0x7eff, 0x0a73, + 0x7f00, 0x1217, + 0x7f01, 0x17f3, + 0x7f04, 0x085d, + 0x7f05, 0x0aea, + 0x7f06, 0x09ad, + 0x7f07, 0x17f6, + 0x7f09, 0x081c, + 0x7f0a, 0x43dd, + 0x7f0b, 0x17f8, + 0x7f0d, 0x17ee, + 0x7f0e, 0x060f, + 0x7f0f, 0x17fa, + 0x7f10, 0x43de, + 0x7f11, 0x17fb, + 0x7f13, 0x07cf, + 0x7f14, 0x05bf, + 0x7f15, 0x0a6d, + 0x7f16, 0x0449, + 0x7f17, 0x17fd, + 0x7f18, 0x10f8, + 0x7f19, 0x17fe, + 0x7f1a, 0x06ba, + 0x7f1b, 0x1800, + 0x7f1c, 0x17ff, + 0x7f1d, 0x0689, + 0x7f1e, 0x43df, + 0x7f1f, 0x1801, + 0x7f20, 0x04bf, + 0x7f21, 0x1802, + 0x7f28, 0x108c, + 0x7f29, 0x0dea, + 0x7f2a, 0x1809, + 0x7f2e, 0x0d02, + 0x7f2f, 0x180d, + 0x7f34, 0x089a, + 0x7f35, 0x1812, + 0x7f36, 0x1c5e, + 0x7f37, 0x43e0, + 0x7f38, 0x06d2, + 0x7f39, 0x43e1, + 0x7f3a, 0x0c8c, + 0x7f3b, 0x43e2, + 0x7f42, 0x1c5f, + 0x7f43, 0x43e9, + 0x7f44, 0x1c60, + 0x7f46, 0x43ea, + 0x7f4c, 0x25e2, + 0x7f4d, 0x43f0, + 0x7f4e, 0x269a, + 0x7f4f, 0x43f1, + 0x7f50, 0x0737, + 0x7f51, 0x0ea9, + 0x7f52, 0x43f2, + 0x7f54, 0x129e, + 0x7f55, 0x0768, + 0x7f56, 0x43f4, + 0x7f57, 0x0a85, + 0x7f58, 0x1a81, + 0x7f59, 0x43f5, + 0x7f5a, 0x0640, + 0x7f5b, 0x43f6, + 0x7f5f, 0x1a83, + 0x7f60, 0x43fa, + 0x7f61, 0x1a82, + 0x7f62, 0x03e0, + 0x7f63, 0x43fb, + 0x7f68, 0x1a85, + 0x7f69, 0x1177, + 0x7f6a, 0x124c, + 0x7f6b, 0x4400, + 0x7f6e, 0x11c2, + 0x7f6f, 0x4403, + 0x7f70, 0x1eea, + 0x7f71, 0x1a87, + 0x7f72, 0x0d87, + 0x7f73, 0x4404, + 0x7f74, 0x1a86, + 0x7f75, 0x4405, + 0x7f77, 0x1e2c, + 0x7f78, 0x4407, + 0x7f79, 0x1a88, + 0x7f7a, 0x4408, + 0x7f7e, 0x1a8a, + 0x7f7f, 0x440c, + 0x7f81, 0x1a89, + 0x7f82, 0x440e, + 0x7f85, 0x2062, + 0x7f86, 0x24f1, + 0x7f87, 0x4411, + 0x7f88, 0x24f2, + 0x7f89, 0x4412, + 0x7f8a, 0x101b, + 0x7f8b, 0x4413, + 0x7f8c, 0x0c39, + 0x7f8d, 0x4414, + 0x7f8e, 0x0ac5, + 0x7f8f, 0x4415, + 0x7f94, 0x06dc, + 0x7f95, 0x441a, + 0x7f9a, 0x0a30, + 0x7f9b, 0x441f, + 0x7f9d, 0x1cc4, + 0x7f9e, 0x0faa, + 0x7f9f, 0x1cc5, + 0x7fa0, 0x4421, + 0x7fa1, 0x0f48, + 0x7fa2, 0x4422, + 0x7fa4, 0x0c95, + 0x7fa5, 0x25f2, + 0x7fa6, 0x4424, + 0x7fa7, 0x1cc6, + 0x7fa8, 0x4425, + 0x7fa9, 0x2215, + 0x7faa, 0x4426, + 0x7faf, 0x1cc7, + 0x7fb1, 0x442b, + 0x7fb2, 0x1cc9, + 0x7fb3, 0x442c, + 0x7fb8, 0x130e, + 0x7fb9, 0x06f9, + 0x7fba, 0x4431, + 0x7fbc, 0x176d, + 0x7fbd, 0x10d5, + 0x7fbe, 0x4433, + 0x7fbf, 0x1cde, + 0x7fc0, 0x4434, + 0x7fc1, 0x0edb, + 0x7fc2, 0x4435, + 0x7fc5, 0x0506, + 0x7fc6, 0x4438, + 0x7fca, 0x1b98, + 0x7fcb, 0x443c, + 0x7fcc, 0x1075, + 0x7fcd, 0x443d, + 0x7fce, 0x1cdf, + 0x7fcf, 0x443e, + 0x7fd2, 0x21ae, + 0x7fd3, 0x4441, + 0x7fd4, 0x0f55, + 0x7fd5, 0x1ce0, + 0x7fd6, 0x4442, + 0x7fd8, 0x0c49, + 0x7fd9, 0x4444, + 0x7fdf, 0x05b5, + 0x7fe0, 0x0567, + 0x7fe1, 0x1ce2, + 0x7fe2, 0x444a, + 0x7fe5, 0x1ce1, + 0x7fe6, 0x1ce3, + 0x7fe7, 0x444d, + 0x7fe9, 0x1ce4, + 0x7fea, 0x444f, + 0x7fee, 0x1ce5, + 0x7fef, 0x4453, + 0x7ff0, 0x0769, + 0x7ff1, 0x03ca, + 0x7ff2, 0x4454, + 0x7ff3, 0x1ce6, + 0x7ff4, 0x4455, + 0x7ff9, 0x20e0, + 0x7ffa, 0x445a, + 0x7ffb, 0x064a, + 0x7ffc, 0x1074, + 0x7ffd, 0x445b, + 0x8000, 0x1032, + 0x8001, 0x09ba, + 0x8002, 0x445e, + 0x8003, 0x0949, + 0x8004, 0x1953, + 0x8005, 0x1180, + 0x8006, 0x191a, + 0x8007, 0x445f, + 0x800b, 0x1bd7, + 0x800c, 0x0637, + 0x800d, 0x0d98, + 0x800e, 0x4463, + 0x8010, 0x0b30, + 0x8011, 0x4465, + 0x8012, 0x1bcb, + 0x8013, 0x4466, + 0x8014, 0x1bcc, + 0x8015, 0x06f6, + 0x8016, 0x1bcd, + 0x8017, 0x077b, + 0x8018, 0x1108, + 0x8019, 0x03dd, + 0x801a, 0x4467, + 0x801c, 0x1bce, + 0x801d, 0x4469, + 0x8020, 0x1bcf, + 0x8021, 0x446c, + 0x8022, 0x1bd0, + 0x8023, 0x446d, + 0x8025, 0x1bd1, + 0x8028, 0x1bd5, + 0x8029, 0x1bd4, + 0x802a, 0x0b96, + 0x802b, 0x446f, + 0x802c, 0x25c2, + 0x802d, 0x4470, + 0x802e, 0x25c1, + 0x802f, 0x4471, + 0x8031, 0x1bd6, + 0x8032, 0x4473, + 0x8033, 0x0639, + 0x8034, 0x4474, + 0x8035, 0x1bd8, + 0x8036, 0x1035, + 0x8037, 0x14b1, + 0x8038, 0x0dbf, + 0x8039, 0x4475, + 0x803b, 0x0501, + 0x803c, 0x4477, + 0x803d, 0x0583, + 0x803e, 0x4478, + 0x803f, 0x06fb, + 0x8040, 0x4479, + 0x8042, 0x0b57, + 0x8043, 0x1bd9, + 0x8044, 0x447b, + 0x8046, 0x1bda, + 0x8047, 0x447d, + 0x804a, 0x0a0d, + 0x804b, 0x0a44, + 0x804c, 0x11af, + 0x804d, 0x1bdb, + 0x804e, 0x4480, + 0x8052, 0x1bdc, + 0x8053, 0x4484, + 0x8054, 0x09f3, + 0x8055, 0x4485, + 0x8056, 0x2128, + 0x8057, 0x4486, + 0x8058, 0x0bd7, + 0x8059, 0x4487, + 0x805a, 0x090a, + 0x805b, 0x4488, + 0x805e, 0x2199, + 0x805f, 0x448b, + 0x8069, 0x1bdd, + 0x806a, 0x0552, + 0x806b, 0x4495, + 0x806f, 0x2017, + 0x8070, 0x1ea0, + 0x8071, 0x1bde, + 0x8072, 0x2125, + 0x8073, 0x214d, + 0x8074, 0x4499, + 0x8075, 0x25c4, + 0x8076, 0x209d, + 0x8077, 0x228a, + 0x8078, 0x449a, + 0x8079, 0x25c3, + 0x807a, 0x449b, + 0x807d, 0x2179, + 0x807e, 0x2038, + 0x807f, 0x1a1e, + 0x8080, 0x1a1d, + 0x8081, 0x449e, + 0x8083, 0x0dd5, + 0x8084, 0x1065, + 0x8085, 0x2155, + 0x8086, 0x0db6, + 0x8087, 0x1179, + 0x8088, 0x44a0, + 0x8089, 0x0cbd, + 0x808a, 0x44a1, + 0x808b, 0x09ca, + 0x808c, 0x0814, + 0x808d, 0x44a2, + 0x8093, 0x1971, + 0x8094, 0x44a8, + 0x8096, 0x0f6f, + 0x8097, 0x44aa, + 0x8098, 0x11e1, + 0x8099, 0x44ab, + 0x809a, 0x0606, + 0x809b, 0x06d3, + 0x809c, 0x1970, + 0x809d, 0x06c9, + 0x809e, 0x44ac, + 0x809f, 0x196f, + 0x80a0, 0x04cb, + 0x80a1, 0x0722, + 0x80a2, 0x11aa, + 0x80a3, 0x44ad, + 0x80a4, 0x0691, + 0x80a5, 0x0667, + 0x80a6, 0x44ae, + 0x80a9, 0x085a, + 0x80aa, 0x065b, + 0x80ab, 0x1976, + 0x80ac, 0x44b1, + 0x80ad, 0x1977, + 0x80ae, 0x03c4, + 0x80af, 0x095c, + 0x80b0, 0x44b2, + 0x80b1, 0x1975, + 0x80b2, 0x10e2, + 0x80b3, 0x44b3, + 0x80b4, 0x1978, + 0x80b5, 0x44b4, + 0x80b7, 0x1979, + 0x80b8, 0x44b6, + 0x80ba, 0x066b, + 0x80bb, 0x44b8, + 0x80bc, 0x1972, + 0x80bd, 0x1974, + 0x80be, 0x0d2f, + 0x80bf, 0x11d6, + 0x80c0, 0x116e, + 0x80c1, 0x0f7d, + 0x80c2, 0x197f, + 0x80c3, 0x0ec7, + 0x80c4, 0x1980, + 0x80c5, 0x44b9, + 0x80c6, 0x0589, + 0x80c7, 0x44ba, + 0x80cc, 0x041c, + 0x80cd, 0x1982, + 0x80ce, 0x0df8, + 0x80cf, 0x44bf, + 0x80d6, 0x0b97, + 0x80d7, 0x1983, + 0x80d8, 0x44c6, + 0x80d9, 0x1981, + 0x80da, 0x0ba0, + 0x80db, 0x197e, + 0x80dc, 0x0d3b, + 0x80dd, 0x1985, + 0x80de, 0x0406, + 0x80df, 0x44c7, + 0x80e1, 0x07b1, + 0x80e2, 0x44c9, + 0x80e4, 0x126d, + 0x80e5, 0x1bc7, + 0x80e6, 0x44cb, + 0x80e7, 0x197a, + 0x80eb, 0x1986, + 0x80ec, 0x179a, + 0x80ed, 0x1989, + 0x80ee, 0x44cc, + 0x80ef, 0x0975, + 0x80f0, 0x104f, + 0x80f1, 0x1987, + 0x80f2, 0x198c, + 0x80f3, 0x06e7, + 0x80f4, 0x1988, + 0x80f5, 0x44cd, + 0x80f6, 0x088b, + 0x80f7, 0x44ce, + 0x80f8, 0x0fa3, + 0x80f9, 0x44cf, + 0x80fa, 0x03c2, + 0x80fb, 0x44d0, + 0x80fc, 0x198d, + 0x80fd, 0x0b3f, + 0x80fe, 0x44d1, + 0x8100, 0x44d3, + 0x8102, 0x11ab, + 0x8103, 0x44d5, + 0x8105, 0x21d2, + 0x8106, 0x0563, + 0x8107, 0x44d7, + 0x8109, 0x0a9d, + 0x810a, 0x082c, + 0x810b, 0x44d9, + 0x810d, 0x198a, + 0x810f, 0x1123, + 0x8110, 0x0c09, + 0x8111, 0x0b37, + 0x8112, 0x198f, + 0x8113, 0x0b68, + 0x8114, 0x1309, + 0x8115, 0x44db, + 0x8116, 0x0478, + 0x8117, 0x44dc, + 0x8118, 0x1994, + 0x8119, 0x44dd, + 0x811a, 0x0896, + 0x811b, 0x24c7, + 0x811c, 0x44de, + 0x811e, 0x1992, + 0x811f, 0x44e0, + 0x812c, 0x1993, + 0x812d, 0x44ed, + 0x812f, 0x06a7, + 0x8130, 0x44ef, + 0x8131, 0x0e82, + 0x8132, 0x1995, + 0x8133, 0x44f0, + 0x8136, 0x1991, + 0x8137, 0x44f3, + 0x8138, 0x09fc, + 0x8139, 0x2279, + 0x813a, 0x44f4, + 0x813e, 0x0bc1, + 0x813f, 0x44f8, + 0x8146, 0x0e46, + 0x8147, 0x44ff, + 0x8148, 0x1996, + 0x8149, 0x4500, + 0x814a, 0x099b, + 0x814b, 0x103f, + 0x814c, 0x1997, + 0x814d, 0x4501, + 0x814e, 0x2123, + 0x814f, 0x4502, + 0x8150, 0x06aa, + 0x8151, 0x06a8, + 0x8152, 0x4503, + 0x8153, 0x1998, + 0x8154, 0x0c38, + 0x8155, 0x0ea4, + 0x8156, 0x24c5, + 0x8157, 0x4504, + 0x8159, 0x199a, + 0x815b, 0x4506, + 0x8160, 0x199d, + 0x8161, 0x24c9, + 0x8162, 0x450b, + 0x8165, 0x0f93, + 0x8166, 0x2094, + 0x8167, 0x19a2, + 0x8168, 0x450e, + 0x8169, 0x199e, + 0x816a, 0x450f, + 0x816b, 0x2296, + 0x816c, 0x4510, + 0x816d, 0x19a1, + 0x816e, 0x0cd4, + 0x816f, 0x4511, + 0x8170, 0x1025, + 0x8171, 0x199c, + 0x8172, 0x4512, + 0x8174, 0x1999, + 0x8175, 0x4514, + 0x8178, 0x1e77, + 0x8179, 0x06b4, + 0x817a, 0x0f46, + 0x817b, 0x0b48, + 0x817c, 0x199f, + 0x817e, 0x0e2d, + 0x817f, 0x0e79, + 0x8180, 0x03fd, + 0x8181, 0x4517, + 0x8182, 0x19a6, + 0x8183, 0x4518, + 0x8188, 0x19a5, + 0x8189, 0x451d, + 0x818a, 0x0479, + 0x818b, 0x451e, + 0x818f, 0x06db, + 0x8190, 0x4522, + 0x8191, 0x19a7, + 0x8192, 0x4523, + 0x8198, 0x0455, + 0x8199, 0x4529, + 0x819a, 0x1f06, + 0x819b, 0x0e18, + 0x819c, 0x0b07, + 0x819d, 0x0f12, + 0x819e, 0x452a, + 0x81a0, 0x1fa5, + 0x81a1, 0x452c, + 0x81a3, 0x19a9, + 0x81a4, 0x452e, + 0x81a6, 0x19b0, + 0x81a7, 0x4530, + 0x81a8, 0x0bb3, + 0x81a9, 0x2099, + 0x81aa, 0x19aa, + 0x81ab, 0x4531, + 0x81b3, 0x0cfe, + 0x81b4, 0x4539, + 0x81ba, 0x1641, + 0x81bb, 0x19ae, + 0x81bc, 0x453f, + 0x81bd, 0x1ead, + 0x81be, 0x24c8, + 0x81bf, 0x20a8, + 0x81c0, 0x0e7f, + 0x81c1, 0x19af, + 0x81c2, 0x0444, + 0x81c3, 0x109c, + 0x81c4, 0x4540, + 0x81c6, 0x1063, + 0x81c7, 0x4542, + 0x81c9, 0x201f, + 0x81ca, 0x19ad, + 0x81cb, 0x4544, + 0x81cc, 0x19ab, + 0x81cd, 0x20c5, + 0x81ce, 0x4545, + 0x81cf, 0x24ca, + 0x81d0, 0x4546, + 0x81d8, 0x1ff0, + 0x81d9, 0x454e, + 0x81da, 0x24c6, + 0x81db, 0x454f, + 0x81df, 0x225d, + 0x81e0, 0x22de, + 0x81e1, 0x4553, + 0x81e3, 0x04e1, + 0x81e4, 0x4555, + 0x81e7, 0x1902, + 0x81e8, 0x202c, + 0x81e9, 0x4558, + 0x81ea, 0x1231, + 0x81eb, 0x4559, + 0x81ec, 0x1ca9, + 0x81ed, 0x0519, + 0x81ee, 0x455a, + 0x81f3, 0x11c0, + 0x81f5, 0x455f, + 0x81fa, 0x2161, + 0x81fb, 0x118a, + 0x81fc, 0x08f9, + 0x81fd, 0x4564, + 0x81fe, 0x1ca5, + 0x81ff, 0x4565, + 0x8200, 0x102f, + 0x8201, 0x1ca6, + 0x8203, 0x4566, + 0x8204, 0x1ca8, + 0x8205, 0x08fa, + 0x8206, 0x10c4, + 0x8207, 0x223b, + 0x8208, 0x21d9, + 0x8209, 0x1fcb, + 0x820a, 0x1fc9, + 0x820b, 0x4567, + 0x820c, 0x0d19, + 0x820e, 0x4568, + 0x8210, 0x1c62, + 0x8211, 0x456a, + 0x8212, 0x0d7d, + 0x8213, 0x456b, + 0x8214, 0x0e45, + 0x8215, 0x456c, + 0x821b, 0x1618, + 0x821c, 0x0da9, + 0x821d, 0x4572, + 0x821e, 0x0ef7, + 0x821f, 0x11da, + 0x8220, 0x4573, + 0x8221, 0x1cab, + 0x8224, 0x4574, + 0x8228, 0x1cb0, + 0x8229, 0x4578, + 0x822a, 0x0774, + 0x822b, 0x1cb1, + 0x822c, 0x03ee, + 0x822d, 0x1cae, + 0x822e, 0x4579, + 0x822f, 0x1caf, + 0x8230, 0x0873, + 0x8231, 0x049c, + 0x8232, 0x457a, + 0x8233, 0x1cb4, + 0x8235, 0x0625, + 0x8236, 0x0477, + 0x8237, 0x0f3c, + 0x8238, 0x1cb2, + 0x8239, 0x052f, + 0x823a, 0x457b, + 0x823b, 0x1cb3, + 0x823c, 0x457c, + 0x823e, 0x1cb6, + 0x823f, 0x457e, + 0x8244, 0x1cb7, + 0x8245, 0x4583, + 0x8247, 0x0e58, + 0x8248, 0x4585, + 0x8249, 0x1cb8, + 0x824a, 0x4586, + 0x824b, 0x1cb9, + 0x824c, 0x4587, + 0x824f, 0x1cba, + 0x8250, 0x458a, + 0x8258, 0x0dc7, + 0x8259, 0x1e61, + 0x825a, 0x1cbb, + 0x825b, 0x4592, + 0x825f, 0x1cbc, + 0x8260, 0x4596, + 0x8264, 0x25ef, + 0x8265, 0x459a, + 0x8266, 0x1f98, + 0x8267, 0x459b, + 0x8268, 0x1cbd, + 0x8269, 0x459c, + 0x826b, 0x25f0, + 0x826c, 0x459e, + 0x826e, 0x1cdc, + 0x826f, 0x0a05, + 0x8270, 0x085b, + 0x8271, 0x1f88, + 0x8272, 0x0ce4, + 0x8273, 0x1007, + 0x8274, 0x1771, + 0x8275, 0x45a0, + 0x8277, 0x21f8, + 0x8278, 0x45a2, + 0x8279, 0x13e1, + 0x827a, 0x105c, + 0x827b, 0x45a3, + 0x827d, 0x13e2, + 0x827e, 0x03b7, + 0x827f, 0x13e3, + 0x8280, 0x45a5, + 0x8282, 0x08ab, + 0x8283, 0x45a7, + 0x8284, 0x13e7, + 0x8285, 0x45a8, + 0x8288, 0x1278, + 0x8289, 0x45ab, + 0x828a, 0x13e5, + 0x828b, 0x10d8, + 0x828c, 0x45ac, + 0x828d, 0x0d0f, + 0x828e, 0x13e8, + 0x828f, 0x13e4, + 0x8290, 0x45ad, + 0x8291, 0x13e9, + 0x8292, 0x0aa7, + 0x8293, 0x45ae, + 0x8297, 0x13ea, + 0x8298, 0x13f3, + 0x8299, 0x13eb, + 0x829a, 0x45b2, + 0x829c, 0x0eee, + 0x829d, 0x11a4, + 0x829e, 0x45b4, + 0x829f, 0x13fd, + 0x82a0, 0x45b5, + 0x82a1, 0x13fb, + 0x82a2, 0x45b6, + 0x82a4, 0x1400, + 0x82a5, 0x08b7, + 0x82a6, 0x0a52, + 0x82a7, 0x45b8, + 0x82a8, 0x13e6, + 0x82a9, 0x13f9, + 0x82aa, 0x13fc, + 0x82ab, 0x13ec, + 0x82ac, 0x066f, + 0x82ad, 0x03d0, + 0x82ae, 0x13f5, + 0x82af, 0x0f89, + 0x82b0, 0x13ef, + 0x82b1, 0x07bd, + 0x82b2, 0x45b9, + 0x82b3, 0x0659, + 0x82b4, 0x13fa, + 0x82b5, 0x45ba, + 0x82b7, 0x13f4, + 0x82b8, 0x13ed, + 0x82b9, 0x0c58, + 0x82ba, 0x45bc, + 0x82bb, 0x2322, + 0x82bc, 0x45bd, + 0x82bd, 0x0fe8, + 0x82be, 0x13ee, + 0x82bf, 0x45be, + 0x82c1, 0x13f8, + 0x82c2, 0x45c0, + 0x82c4, 0x13fe, + 0x82c5, 0x45c2, + 0x82c7, 0x0ebc, + 0x82c8, 0x13f0, + 0x82c9, 0x45c4, + 0x82ca, 0x13f1, + 0x82cb, 0x13f6, + 0x82cd, 0x049b, + 0x82ce, 0x13ff, + 0x82cf, 0x0dca, + 0x82d0, 0x45c5, + 0x82d1, 0x10fa, + 0x82d2, 0x1409, + 0x82d3, 0x140d, + 0x82d4, 0x0df9, + 0x82d5, 0x1414, + 0x82d6, 0x45c6, + 0x82d7, 0x0aec, + 0x82d8, 0x140a, + 0x82d9, 0x45c7, + 0x82db, 0x094e, + 0x82dc, 0x1407, + 0x82dd, 0x45c9, + 0x82de, 0x0405, + 0x82df, 0x070f, + 0x82e0, 0x1413, + 0x82e1, 0x1401, + 0x82e2, 0x45ca, + 0x82e3, 0x13f2, + 0x82e4, 0x1404, + 0x82e5, 0x0ccf, + 0x82e6, 0x096d, + 0x82e7, 0x2336, + 0x82e8, 0x45cb, + 0x82eb, 0x0cf4, + 0x82ec, 0x45ce, + 0x82ef, 0x0426, + 0x82f0, 0x45d1, + 0x82f1, 0x1087, + 0x82f2, 0x45d2, + 0x82f4, 0x1408, + 0x82f5, 0x45d4, + 0x82f7, 0x1403, + 0x82f8, 0x45d6, + 0x82f9, 0x0bda, + 0x82fa, 0x45d7, + 0x82fb, 0x140c, + 0x82fc, 0x45d8, + 0x8300, 0x45dc, + 0x8301, 0x121f, + 0x8302, 0x0ab4, + 0x8303, 0x0653, + 0x8304, 0x0c4e, + 0x8305, 0x0aae, + 0x8306, 0x1410, + 0x8307, 0x1406, + 0x8308, 0x1419, + 0x8309, 0x1402, + 0x830a, 0x45dd, + 0x830c, 0x140b, + 0x830d, 0x45df, + 0x830e, 0x08d4, + 0x830f, 0x1405, + 0x8310, 0x45e0, + 0x8311, 0x140e, + 0x8312, 0x45e1, + 0x8314, 0x1411, + 0x8316, 0x45e3, + 0x8317, 0x1426, + 0x8318, 0x45e4, + 0x831a, 0x140f, + 0x831b, 0x142e, + 0x831c, 0x1415, + 0x831d, 0x45e6, + 0x8327, 0x085e, + 0x8328, 0x0547, + 0x8329, 0x45f0, + 0x832b, 0x0aa8, + 0x832c, 0x04ae, + 0x832d, 0x1428, + 0x832e, 0x45f2, + 0x832f, 0x1420, + 0x8330, 0x45f3, + 0x8331, 0x141d, + 0x8332, 0x45f4, + 0x8333, 0x142a, + 0x8334, 0x141c, + 0x8335, 0x1077, + 0x8336, 0x04af, + 0x8337, 0x45f5, + 0x8338, 0x0cb2, + 0x8339, 0x0cbe, + 0x833a, 0x1429, + 0x833b, 0x45f6, + 0x833c, 0x141b, + 0x833d, 0x45f7, + 0x8340, 0x1425, + 0x8341, 0x45fa, + 0x8343, 0x1423, + 0x8344, 0x45fc, + 0x8346, 0x08d2, + 0x8347, 0x1422, + 0x8348, 0x45fe, + 0x8349, 0x04a4, + 0x834a, 0x45ff, + 0x834f, 0x1421, + 0x8350, 0x0869, + 0x8351, 0x1416, + 0x8352, 0x07d9, + 0x8353, 0x4604, + 0x8354, 0x09de, + 0x8355, 0x4605, + 0x835a, 0x0847, + 0x835b, 0x1417, + 0x835d, 0x460a, + 0x835e, 0x141f, + 0x835f, 0x1424, + 0x8360, 0x1427, + 0x8361, 0x0595, + 0x8362, 0x460b, + 0x8363, 0x0cb4, + 0x8364, 0x07fc, + 0x8365, 0x142c, + 0x8366, 0x142b, + 0x8367, 0x1090, + 0x8368, 0x142d, + 0x8369, 0x142f, + 0x836a, 0x1431, + 0x836b, 0x1078, + 0x836c, 0x1430, + 0x836d, 0x1432, + 0x836f, 0x1030, + 0x8370, 0x460c, + 0x8377, 0x0780, + 0x8378, 0x1435, + 0x8379, 0x4613, + 0x837b, 0x1442, + 0x837c, 0x143d, + 0x837d, 0x1440, + 0x837e, 0x4615, + 0x8385, 0x143c, + 0x8386, 0x0bed, + 0x8387, 0x461c, + 0x8389, 0x09dd, + 0x838a, 0x22ab, + 0x838b, 0x461e, + 0x838e, 0x0ce8, + 0x838f, 0x4621, + 0x8392, 0x141a, + 0x8393, 0x143a, + 0x8394, 0x4624, + 0x8396, 0x1fbf, + 0x8397, 0x4626, + 0x8398, 0x1443, + 0x8399, 0x4627, + 0x839b, 0x141e, + 0x839c, 0x143b, + 0x839d, 0x4629, + 0x839e, 0x1444, + 0x839f, 0x462a, + 0x83a0, 0x1438, + 0x83a1, 0x462b, + 0x83a2, 0x1f7d, + 0x83a3, 0x462c, + 0x83a7, 0x2333, + 0x83a8, 0x1445, + 0x83a9, 0x143f, + 0x83aa, 0x1439, + 0x83ab, 0x0b0d, + 0x83ac, 0x4630, + 0x83b0, 0x1434, + 0x83b1, 0x099e, + 0x83b2, 0x09f4, + 0x83b3, 0x1436, + 0x83b5, 0x4634, + 0x83b6, 0x143e, + 0x83b7, 0x0806, + 0x83b8, 0x1441, + 0x83b9, 0x108d, + 0x83ba, 0x1446, + 0x83bb, 0x4635, + 0x83bc, 0x1447, + 0x83bd, 0x0aac, + 0x83be, 0x4636, + 0x83c0, 0x145e, + 0x83c1, 0x1448, + 0x83c2, 0x4638, + 0x83c5, 0x145d, + 0x83c6, 0x463b, + 0x83c7, 0x0716, + 0x83c8, 0x463c, + 0x83ca, 0x0904, + 0x83cb, 0x463e, + 0x83cc, 0x0929, + 0x83cd, 0x463f, + 0x83cf, 0x0781, + 0x83d0, 0x4641, + 0x83d4, 0x1456, + 0x83d5, 0x4645, + 0x83d6, 0x1451, + 0x83d7, 0x4646, + 0x83d8, 0x144b, + 0x83d9, 0x4647, + 0x83dc, 0x0492, + 0x83dd, 0x144f, + 0x83de, 0x464a, + 0x83df, 0x1457, + 0x83e0, 0x046b, + 0x83e1, 0x1461, + 0x83e2, 0x464b, + 0x83e5, 0x144a, + 0x83e6, 0x464e, + 0x83e9, 0x0bef, + 0x83ea, 0x145c, + 0x83eb, 0x4651, + 0x83ef, 0x1f4d, + 0x83f0, 0x1460, + 0x83f1, 0x0a2b, + 0x83f2, 0x0663, + 0x83f3, 0x4655, + 0x83f8, 0x145a, + 0x83fa, 0x465a, + 0x83fd, 0x1450, + 0x83fe, 0x465d, + 0x8400, 0x465f, + 0x8401, 0x1449, + 0x8402, 0x4660, + 0x8403, 0x1459, + 0x8404, 0x0e24, + 0x8405, 0x4661, + 0x8406, 0x1455, + 0x8407, 0x2334, + 0x8408, 0x4662, + 0x840a, 0x1ff1, + 0x840b, 0x144e, + 0x840c, 0x0acd, + 0x840d, 0x0bdb, + 0x840e, 0x0ebd, + 0x840f, 0x1458, + 0x8410, 0x4664, + 0x8411, 0x1454, + 0x8412, 0x4665, + 0x8418, 0x144d, + 0x8419, 0x466b, + 0x841c, 0x1452, + 0x841d, 0x0a83, + 0x841e, 0x466e, + 0x8424, 0x108e, + 0x8426, 0x145f, + 0x8427, 0x0f61, + 0x8428, 0x0cd3, + 0x8429, 0x4674, + 0x842c, 0x218b, + 0x842d, 0x4677, + 0x8431, 0x1472, + 0x8432, 0x467b, + 0x8435, 0x2349, + 0x8436, 0x467e, + 0x8438, 0x1453, + 0x8439, 0x4680, + 0x843c, 0x146c, + 0x843d, 0x0a8b, + 0x843e, 0x4683, + 0x8446, 0x146d, + 0x8447, 0x468b, + 0x8449, 0x220b, + 0x844a, 0x468d, + 0x8451, 0x1463, + 0x8452, 0x2346, + 0x8453, 0x4694, + 0x8457, 0x11f7, + 0x8458, 0x4698, + 0x8459, 0x1465, + 0x845a, 0x1464, + 0x845b, 0x06eb, + 0x845c, 0x1462, + 0x845d, 0x4699, + 0x8461, 0x0bee, + 0x8462, 0x469d, + 0x8463, 0x05ec, + 0x8464, 0x2347, + 0x8465, 0x469e, + 0x8466, 0x2193, + 0x8467, 0x469f, + 0x8469, 0x146e, + 0x846a, 0x46a1, + 0x846b, 0x07b0, + 0x846c, 0x1124, + 0x846d, 0x1473, + 0x846e, 0x46a2, + 0x846f, 0x26a1, + 0x8470, 0x46a3, + 0x8471, 0x0553, + 0x8472, 0x46a4, + 0x8473, 0x1466, + 0x8474, 0x46a5, + 0x8475, 0x0988, + 0x8476, 0x146f, + 0x8477, 0x1f62, + 0x8478, 0x146b, + 0x8479, 0x46a6, + 0x847a, 0x1469, + 0x847b, 0x46a7, + 0x8482, 0x05ba, + 0x8483, 0x46ae, + 0x8487, 0x1467, + 0x8489, 0x146a, + 0x848a, 0x46b2, + 0x848b, 0x0880, + 0x848c, 0x1470, + 0x848d, 0x46b3, + 0x848e, 0x1471, + 0x848f, 0x46b4, + 0x8493, 0x234d, + 0x8494, 0x2348, + 0x8495, 0x46b8, + 0x8497, 0x1481, + 0x8498, 0x46ba, + 0x8499, 0x0ace, + 0x849a, 0x46bb, + 0x849c, 0x0dd7, + 0x849d, 0x46bd, + 0x84a1, 0x147e, + 0x84a2, 0x46c1, + 0x84af, 0x1297, + 0x84b0, 0x46ce, + 0x84b2, 0x0bf0, + 0x84b3, 0x46d0, + 0x84b4, 0x1480, + 0x84b5, 0x46d1, + 0x84b8, 0x1195, + 0x84b9, 0x147f, + 0x84ba, 0x147c, + 0x84bb, 0x46d4, + 0x84bc, 0x1e60, + 0x84bd, 0x1478, + 0x84be, 0x46d5, + 0x84bf, 0x147b, + 0x84c0, 0x2345, + 0x84c1, 0x1474, + 0x84c2, 0x46d6, + 0x84c4, 0x0fb9, + 0x84c5, 0x46d8, + 0x84c9, 0x0cb3, + 0x84ca, 0x147a, + 0x84cb, 0x1f12, + 0x84cc, 0x46dc, + 0x84cd, 0x1475, + 0x84ce, 0x46dd, + 0x84d0, 0x1476, + 0x84d1, 0x0de7, + 0x84d2, 0x46df, + 0x84d3, 0x1479, + 0x84d4, 0x46e0, + 0x84d6, 0x0436, + 0x84d7, 0x46e2, + 0x84dd, 0x09a1, + 0x84de, 0x46e8, + 0x84df, 0x082e, + 0x84e0, 0x147d, + 0x84e1, 0x46e9, + 0x84e3, 0x1483, + 0x84e4, 0x46eb, + 0x84e5, 0x1482, + 0x84e6, 0x1477, + 0x84e7, 0x46ec, + 0x84ec, 0x0baf, + 0x84ed, 0x46f1, + 0x84ee, 0x2018, + 0x84ef, 0x2335, + 0x84f0, 0x1487, + 0x84f1, 0x46f2, + 0x84fc, 0x148e, + 0x84fd, 0x233c, + 0x84fe, 0x46fd, + 0x84ff, 0x148d, + 0x8500, 0x46fe, + 0x850c, 0x1484, + 0x850d, 0x470a, + 0x8511, 0x0af4, + 0x8512, 0x470e, + 0x8513, 0x0aa2, + 0x8514, 0x266f, + 0x8515, 0x470f, + 0x8517, 0x1182, + 0x8518, 0x4711, + 0x851a, 0x0ec4, + 0x851b, 0x4713, + 0x851e, 0x2351, + 0x851f, 0x1489, + 0x8520, 0x4716, + 0x8521, 0x0493, + 0x8522, 0x4717, + 0x8523, 0x1fa0, + 0x8524, 0x4718, + 0x8526, 0x2338, + 0x8527, 0x471a, + 0x852b, 0x0b4b, + 0x852c, 0x0d76, + 0x852d, 0x221b, + 0x852e, 0x471e, + 0x8537, 0x0c3b, + 0x8538, 0x1486, + 0x8539, 0x1488, + 0x853a, 0x148a, + 0x853b, 0x148c, + 0x853c, 0x03b5, + 0x853d, 0x0437, + 0x853e, 0x4727, + 0x8541, 0x2342, + 0x8542, 0x472a, + 0x8543, 0x1496, + 0x8544, 0x472b, + 0x8546, 0x234f, + 0x8547, 0x472d, + 0x8548, 0x1490, + 0x8549, 0x0887, + 0x854a, 0x0cca, + 0x854b, 0x472e, + 0x854e, 0x233d, + 0x854f, 0x4731, + 0x8552, 0x2344, + 0x8553, 0x2331, + 0x8554, 0x4734, + 0x8555, 0x234b, + 0x8556, 0x148b, + 0x8557, 0x4735, + 0x8558, 0x233b, + 0x8559, 0x148f, + 0x855a, 0x4736, + 0x855e, 0x1493, + 0x855f, 0x473a, + 0x8562, 0x2350, + 0x8563, 0x473d, + 0x8564, 0x1492, + 0x8565, 0x473e, + 0x8568, 0x1491, + 0x8569, 0x1eb4, + 0x856a, 0x21a6, + 0x856b, 0x4741, + 0x856d, 0x21cb, + 0x856e, 0x4743, + 0x8572, 0x1497, + 0x8573, 0x4747, + 0x8574, 0x110f, + 0x8575, 0x4748, + 0x8577, 0x2355, + 0x8578, 0x474a, + 0x8579, 0x149d, + 0x857a, 0x1494, + 0x857b, 0x1498, + 0x857c, 0x474b, + 0x857e, 0x09c4, + 0x857f, 0x474d, + 0x8584, 0x040a, + 0x8585, 0x14a0, + 0x8586, 0x4752, + 0x8587, 0x149b, + 0x8588, 0x233e, + 0x8589, 0x4753, + 0x858a, 0x1f74, + 0x858b, 0x4754, + 0x858c, 0x2330, + 0x858d, 0x4755, + 0x858f, 0x149c, + 0x8590, 0x4757, + 0x8591, 0x2680, + 0x8592, 0x4758, + 0x8594, 0x20da, + 0x8595, 0x475a, + 0x859b, 0x0fcf, + 0x859c, 0x149f, + 0x859d, 0x4760, + 0x859f, 0x234a, + 0x85a0, 0x4762, + 0x85a4, 0x1499, + 0x85a5, 0x4766, + 0x85a6, 0x1f91, + 0x85a7, 0x4767, + 0x85a8, 0x149a, + 0x85a9, 0x2107, + 0x85aa, 0x0f88, + 0x85ab, 0x4768, + 0x85ae, 0x149e, + 0x85af, 0x0d84, + 0x85b0, 0x14a3, + 0x85b1, 0x476b, + 0x85b7, 0x14a2, + 0x85b8, 0x4771, + 0x85b9, 0x14a1, + 0x85ba, 0x233f, + 0x85bb, 0x4772, + 0x85c1, 0x14a5, + 0x85c2, 0x4778, + 0x85c9, 0x08b6, + 0x85ca, 0x477f, + 0x85cd, 0x1ff4, + 0x85ce, 0x2343, + 0x85cf, 0x049f, + 0x85d0, 0x0aef, + 0x85d1, 0x4782, + 0x85d3, 0x14a4, + 0x85d4, 0x4784, + 0x85d5, 0x0b7b, + 0x85d6, 0x4785, + 0x85dc, 0x14a6, + 0x85dd, 0x2212, + 0x85de, 0x478b, + 0x85e4, 0x0e2c, + 0x85e5, 0x2207, + 0x85e6, 0x4791, + 0x85e9, 0x0647, + 0x85ea, 0x2359, + 0x85eb, 0x4794, + 0x85f4, 0x2254, + 0x85f5, 0x479d, + 0x85f6, 0x2332, + 0x85f7, 0x479e, + 0x85f9, 0x1e26, + 0x85fa, 0x2357, + 0x85fb, 0x1128, + 0x85fc, 0x47a0, + 0x85ff, 0x14a7, + 0x8600, 0x47a3, + 0x8604, 0x2358, + 0x8605, 0x14a9, + 0x8606, 0x2042, + 0x8607, 0x2153, + 0x8608, 0x47a7, + 0x860b, 0x20bb, + 0x860c, 0x47aa, + 0x8611, 0x0b05, + 0x8612, 0x47af, + 0x8616, 0x14ab, + 0x8617, 0x47b3, + 0x861a, 0x235a, + 0x861b, 0x47b6, + 0x861e, 0x2356, + 0x861f, 0x47b9, + 0x8622, 0x2337, + 0x8623, 0x47bc, + 0x8627, 0x14a8, + 0x8628, 0x47c0, + 0x8629, 0x14aa, + 0x862a, 0x47c1, + 0x862d, 0x1ff9, + 0x862e, 0x47c4, + 0x8638, 0x115b, + 0x8639, 0x47ce, + 0x863a, 0x2353, + 0x863b, 0x47cf, + 0x863c, 0x14ac, + 0x863d, 0x47d0, + 0x863f, 0x2061, + 0x8640, 0x47d2, + 0x864d, 0x1bf0, + 0x864e, 0x07b7, + 0x864f, 0x0a59, + 0x8650, 0x0b71, + 0x8651, 0x0a6e, + 0x8652, 0x47df, + 0x8654, 0x1bf1, + 0x8655, 0x1e95, + 0x8656, 0x47e1, + 0x865a, 0x0fb4, + 0x865b, 0x47e5, + 0x865c, 0x2049, + 0x865d, 0x47e6, + 0x865e, 0x10c2, + 0x865f, 0x1f42, + 0x8660, 0x47e7, + 0x8662, 0x196d, + 0x8663, 0x47e9, + 0x8667, 0x1fe8, + 0x8668, 0x47ed, + 0x866b, 0x050b, + 0x866c, 0x1bf2, + 0x866d, 0x47f0, + 0x866e, 0x1bf3, + 0x866f, 0x47f1, + 0x8671, 0x0d44, + 0x8672, 0x47f3, + 0x8679, 0x079e, + 0x867a, 0x1bf5, + 0x867b, 0x1bf7, + 0x867c, 0x1bf6, + 0x867d, 0x0dd9, + 0x867e, 0x0f27, + 0x867f, 0x1bf4, + 0x8680, 0x0d4b, + 0x8681, 0x1056, + 0x8682, 0x0a93, + 0x8683, 0x47fa, + 0x868a, 0x0ed2, + 0x868b, 0x1bfa, + 0x868c, 0x0401, + 0x868d, 0x1bf9, + 0x868e, 0x4801, + 0x8693, 0x1c00, + 0x8694, 0x4806, + 0x8695, 0x0496, + 0x8696, 0x4807, + 0x869c, 0x0fea, + 0x869d, 0x1bfc, + 0x869e, 0x480d, + 0x86a3, 0x1bfe, + 0x86a4, 0x112c, + 0x86a5, 0x4812, + 0x86a7, 0x1bfd, + 0x86a8, 0x1bf8, + 0x86a9, 0x1c01, + 0x86aa, 0x1bff, + 0x86ab, 0x4814, + 0x86ac, 0x1bfb, + 0x86ad, 0x4815, + 0x86af, 0x1c09, + 0x86b0, 0x1c06, + 0x86b1, 0x1c08, + 0x86b2, 0x4817, + 0x86b4, 0x1c0c, + 0x86b5, 0x1c04, + 0x86b6, 0x1c02, + 0x86b7, 0x4819, + 0x86ba, 0x1c07, + 0x86bb, 0x481c, + 0x86c0, 0x11fa, + 0x86c1, 0x4821, + 0x86c4, 0x1c03, + 0x86c5, 0x4824, + 0x86c6, 0x0c76, + 0x86c7, 0x0d18, + 0x86c8, 0x4825, + 0x86c9, 0x1c0a, + 0x86ca, 0x071f, + 0x86cb, 0x0591, + 0x86cc, 0x4826, + 0x86ce, 0x1c05, + 0x86cf, 0x1c0b, + 0x86d0, 0x1c12, + 0x86d1, 0x1c18, + 0x86d2, 0x4828, + 0x86d4, 0x07ec, + 0x86d5, 0x482a, + 0x86d8, 0x1c17, + 0x86d9, 0x0e8d, + 0x86da, 0x482d, + 0x86db, 0x11ea, + 0x86dc, 0x482e, + 0x86de, 0x1c14, + 0x86df, 0x1c16, + 0x86e0, 0x4830, + 0x86e4, 0x06ed, + 0x86e5, 0x4834, + 0x86e9, 0x1c0d, + 0x86ea, 0x4838, + 0x86ed, 0x1c10, + 0x86ee, 0x0aa0, + 0x86ef, 0x483b, + 0x86f0, 0x117e, + 0x86f1, 0x1c0e, + 0x86f3, 0x1c11, + 0x86f4, 0x1c15, + 0x86f5, 0x483c, + 0x86f8, 0x1c1b, + 0x86f9, 0x10a1, + 0x86fa, 0x25da, + 0x86fb, 0x483f, + 0x86fe, 0x0629, + 0x86ff, 0x4842, + 0x8700, 0x0d88, + 0x8701, 0x4843, + 0x8702, 0x0681, + 0x8703, 0x1c19, + 0x8704, 0x4844, + 0x8706, 0x25d7, + 0x8707, 0x1c1a, + 0x8708, 0x1c1c, + 0x8709, 0x1c1f, + 0x870a, 0x1c1d, + 0x870b, 0x4846, + 0x870d, 0x1c1e, + 0x870e, 0x4848, + 0x8712, 0x0ffa, + 0x8713, 0x1c13, + 0x8714, 0x484c, + 0x8715, 0x0e7a, + 0x8716, 0x484d, + 0x8717, 0x0ede, + 0x8718, 0x11a8, + 0x8719, 0x484e, + 0x871a, 0x1c25, + 0x871b, 0x484f, + 0x871c, 0x0ae0, + 0x871d, 0x4850, + 0x871e, 0x1c22, + 0x871f, 0x4851, + 0x8721, 0x099a, + 0x8722, 0x1c2e, + 0x8723, 0x1c20, + 0x8724, 0x4853, + 0x8725, 0x1c23, + 0x8726, 0x4854, + 0x8729, 0x1c2a, + 0x872a, 0x4857, + 0x872e, 0x1c24, + 0x872f, 0x485b, + 0x8731, 0x1c29, + 0x8732, 0x485d, + 0x8734, 0x1c28, + 0x8735, 0x485f, + 0x8737, 0x1c2b, + 0x8738, 0x4861, + 0x873b, 0x1c21, + 0x873c, 0x4864, + 0x873e, 0x1c26, + 0x873f, 0x1c2c, + 0x8740, 0x4866, + 0x8747, 0x1091, + 0x8748, 0x1c27, + 0x8749, 0x04bc, + 0x874a, 0x486d, + 0x874c, 0x1c34, + 0x874d, 0x486f, + 0x874e, 0x0f76, + 0x874f, 0x4870, + 0x8753, 0x1c37, + 0x8754, 0x4874, + 0x8755, 0x212e, + 0x8756, 0x4875, + 0x8757, 0x07dd, + 0x8758, 0x4876, + 0x8759, 0x1c3b, + 0x875a, 0x4877, + 0x8760, 0x1c32, + 0x8761, 0x487d, + 0x8763, 0x1c38, + 0x8764, 0x1c3a, + 0x8765, 0x1c3c, + 0x8766, 0x21b2, + 0x8767, 0x487f, + 0x876e, 0x1c35, + 0x876f, 0x4886, + 0x8770, 0x1c33, + 0x8771, 0x4887, + 0x8774, 0x07b2, + 0x8775, 0x488a, + 0x8776, 0x05dc, + 0x8777, 0x488b, + 0x8778, 0x219e, + 0x8779, 0x488c, + 0x877b, 0x1c31, + 0x877c, 0x1c39, + 0x877d, 0x1c2f, + 0x877f, 0x488e, + 0x8782, 0x1c2d, + 0x8783, 0x1c46, + 0x8784, 0x25dc, + 0x8785, 0x1c43, + 0x8786, 0x4891, + 0x8788, 0x1c42, + 0x8789, 0x4893, + 0x878b, 0x1c36, + 0x878c, 0x4895, + 0x878d, 0x0cb5, + 0x878e, 0x4896, + 0x8793, 0x1c3d, + 0x8794, 0x489b, + 0x8797, 0x1c45, + 0x8798, 0x489e, + 0x879e, 0x206c, + 0x879f, 0x0afd, + 0x87a0, 0x48a4, + 0x87a2, 0x2226, + 0x87a3, 0x48a6, + 0x87a8, 0x1c3f, + 0x87a9, 0x48ab, + 0x87ab, 0x1c47, + 0x87ac, 0x1c49, + 0x87ad, 0x1c44, + 0x87ae, 0x48ad, + 0x87af, 0x1c3e, + 0x87b0, 0x48ae, + 0x87b3, 0x1c4b, + 0x87b4, 0x48b1, + 0x87b5, 0x1c4a, + 0x87b6, 0x48b2, + 0x87ba, 0x0a84, + 0x87bb, 0x25e0, + 0x87bc, 0x48b6, + 0x87bd, 0x1c4e, + 0x87be, 0x48b7, + 0x87c0, 0x1c50, + 0x87c1, 0x48b9, + 0x87c4, 0x227b, + 0x87c5, 0x48bc, + 0x87c6, 0x1c41, + 0x87c7, 0x48bd, + 0x87c8, 0x25de, + 0x87c9, 0x48be, + 0x87ca, 0x1c51, + 0x87cb, 0x1c4c, + 0x87cc, 0x48bf, + 0x87ce, 0x25e1, + 0x87cf, 0x48c1, + 0x87d1, 0x1c4f, + 0x87d2, 0x1c40, + 0x87d3, 0x1c4d, + 0x87d4, 0x48c3, + 0x87db, 0x1c52, + 0x87dc, 0x48ca, + 0x87e0, 0x1c54, + 0x87e1, 0x48ce, + 0x87e3, 0x25d5, + 0x87e4, 0x48d0, + 0x87e5, 0x1c48, + 0x87e6, 0x48d1, + 0x87ea, 0x1c53, + 0x87eb, 0x48d5, + 0x87ec, 0x1e6b, + 0x87ed, 0x48d6, + 0x87ee, 0x1c55, + 0x87ef, 0x25db, + 0x87f0, 0x48d7, + 0x87f2, 0x1e89, + 0x87f3, 0x48d9, + 0x87f6, 0x25d9, + 0x87f7, 0x48dc, + 0x87f9, 0x0f82, + 0x87fa, 0x48de, + 0x87fb, 0x2211, + 0x87fc, 0x48df, + 0x87fe, 0x1c58, + 0x87ff, 0x48e1, + 0x8800, 0x48e2, + 0x8803, 0x130d, + 0x8804, 0x48e5, + 0x8805, 0x2229, + 0x8806, 0x25d6, + 0x8807, 0x48e6, + 0x880a, 0x1c59, + 0x880b, 0x48e9, + 0x8810, 0x25dd, + 0x8811, 0x25df, + 0x8812, 0x48ee, + 0x8813, 0x1c57, + 0x8814, 0x48ef, + 0x8815, 0x0cbf, + 0x8816, 0x1c56, + 0x8817, 0x48f0, + 0x881b, 0x1c5a, + 0x881c, 0x48f4, + 0x881f, 0x1fef, + 0x8820, 0x48f7, + 0x8821, 0x1c5b, + 0x8822, 0x0543, + 0x8823, 0x25d8, + 0x8824, 0x48f8, + 0x8831, 0x1f29, + 0x8832, 0x1a8d, + 0x8833, 0x4905, + 0x8836, 0x1e5b, + 0x8837, 0x4908, + 0x8839, 0x1c5c, + 0x883a, 0x490a, + 0x883b, 0x2076, + 0x883c, 0x1c5d, + 0x883d, 0x490b, + 0x8840, 0x0fd3, + 0x8841, 0x490e, + 0x8844, 0x1caa, + 0x8845, 0x0f91, + 0x8846, 0x2297, + 0x8847, 0x4911, + 0x884a, 0x2690, + 0x884b, 0x4914, + 0x884c, 0x0f9b, + 0x884d, 0x1005, + 0x884e, 0x4915, + 0x8853, 0x213f, + 0x8854, 0x0f3b, + 0x8855, 0x491a, + 0x8857, 0x08a7, + 0x8858, 0x491c, + 0x8859, 0x0fec, + 0x885a, 0x491d, + 0x885b, 0x2198, + 0x885c, 0x491e, + 0x885d, 0x1e88, + 0x885e, 0x491f, + 0x8861, 0x0799, + 0x8862, 0x15ed, + 0x8863, 0x1049, + 0x8864, 0x1ba6, + 0x8865, 0x0480, + 0x8866, 0x4922, + 0x8868, 0x0456, + 0x8869, 0x1ba7, + 0x886a, 0x4924, + 0x886b, 0x0cf9, + 0x886c, 0x04e9, + 0x886d, 0x4925, + 0x886e, 0x1306, + 0x886f, 0x4926, + 0x8870, 0x0d9a, + 0x8871, 0x4927, + 0x8872, 0x1ba8, + 0x8873, 0x4928, + 0x8877, 0x11d3, + 0x8878, 0x492c, + 0x8879, 0x228c, + 0x887a, 0x492d, + 0x887d, 0x1ba9, + 0x887e, 0x1cbe, + 0x887f, 0x1baa, + 0x8880, 0x4930, + 0x8881, 0x10ef, + 0x8882, 0x1bab, + 0x8883, 0x4931, + 0x8884, 0x03cb, + 0x8885, 0x1cbf, + 0x8886, 0x4932, + 0x8888, 0x1cc0, + 0x8889, 0x4934, + 0x888b, 0x057f, + 0x888c, 0x4936, + 0x888d, 0x0b9c, + 0x888e, 0x4937, + 0x8892, 0x0e0e, + 0x8893, 0x493b, + 0x8896, 0x0faf, + 0x8897, 0x493e, + 0x889c, 0x0e91, + 0x889d, 0x4943, + 0x88a2, 0x1bac, + 0x88a3, 0x4948, + 0x88a4, 0x1307, + 0x88a5, 0x4949, + 0x88ab, 0x0424, + 0x88ac, 0x494f, + 0x88ad, 0x0f1b, + 0x88ae, 0x4950, + 0x88b1, 0x069f, + 0x88b2, 0x4953, + 0x88b7, 0x1bae, + 0x88b8, 0x4958, + 0x88bc, 0x1baf, + 0x88bd, 0x495c, + 0x88c1, 0x048a, + 0x88c2, 0x0a1a, + 0x88c3, 0x4960, + 0x88c5, 0x120d, + 0x88c6, 0x1bad, + 0x88c7, 0x4962, + 0x88c9, 0x1bb0, + 0x88ca, 0x25f1, + 0x88cb, 0x4964, + 0x88ce, 0x1bb2, + 0x88cf, 0x200c, + 0x88d0, 0x4967, + 0x88d2, 0x130a, + 0x88d3, 0x4969, + 0x88d4, 0x1068, + 0x88d5, 0x10e6, + 0x88d6, 0x496a, + 0x88d8, 0x1cc1, + 0x88d9, 0x0c94, + 0x88da, 0x496c, + 0x88dc, 0x1e58, + 0x88dd, 0x22ac, + 0x88de, 0x496e, + 0x88df, 0x1cc2, + 0x88e0, 0x496f, + 0x88e2, 0x1bb1, + 0x88e3, 0x1bb3, + 0x88e4, 0x0970, + 0x88e5, 0x1bb4, + 0x88e6, 0x4971, + 0x88e8, 0x1bb8, + 0x88e9, 0x4973, + 0x88f0, 0x1bba, + 0x88f1, 0x1bb5, + 0x88f2, 0x497a, + 0x88f3, 0x0d0a, + 0x88f4, 0x0ba2, + 0x88f5, 0x497b, + 0x88f8, 0x0a8a, + 0x88f9, 0x0755, + 0x88fa, 0x497e, + 0x88fc, 0x1bb7, + 0x88fd, 0x26a7, + 0x88fe, 0x1bb9, + 0x88ff, 0x4980, + 0x8900, 0x4981, + 0x8902, 0x072c, + 0x8903, 0x4983, + 0x8907, 0x2676, + 0x8908, 0x4987, + 0x890a, 0x1bbf, + 0x890b, 0x4989, + 0x8910, 0x078d, + 0x8911, 0x498e, + 0x8912, 0x0408, + 0x8913, 0x1bbd, + 0x8914, 0x498f, + 0x8919, 0x1bbc, + 0x891a, 0x1bb6, + 0x891b, 0x1bbe, + 0x891c, 0x4994, + 0x8921, 0x1bbb, + 0x8922, 0x4999, + 0x8925, 0x0cc7, + 0x8926, 0x499c, + 0x892a, 0x0e7b, + 0x892b, 0x1bc1, + 0x892c, 0x49a0, + 0x8930, 0x1739, + 0x8931, 0x49a4, + 0x8932, 0x1fe1, + 0x8933, 0x25bb, + 0x8934, 0x1bc0, + 0x8935, 0x49a5, + 0x8936, 0x1bc2, + 0x8937, 0x49a6, + 0x8938, 0x25be, + 0x8939, 0x49a7, + 0x893b, 0x22dd, + 0x893c, 0x49a9, + 0x8941, 0x1bc3, + 0x8942, 0x49ae, + 0x8944, 0x0f52, + 0x8945, 0x49b0, + 0x8947, 0x25bd, + 0x8948, 0x49b2, + 0x8956, 0x1e2a, + 0x8957, 0x49c0, + 0x895d, 0x25bc, + 0x895e, 0x1cc3, + 0x895f, 0x08c4, + 0x8960, 0x25ba, + 0x8961, 0x49c6, + 0x8964, 0x25bf, + 0x8965, 0x49c9, + 0x8966, 0x1bc4, + 0x8967, 0x49ca, + 0x896a, 0x2187, + 0x896b, 0x49cd, + 0x896c, 0x266b, + 0x896d, 0x49ce, + 0x896f, 0x1e7f, + 0x8970, 0x49d0, + 0x8972, 0x21ad, + 0x8973, 0x49d2, + 0x897b, 0x1bc5, + 0x897c, 0x49da, + 0x897f, 0x0f06, + 0x8980, 0x49dd, + 0x8981, 0x1031, + 0x8982, 0x49de, + 0x8983, 0x1bdf, + 0x8984, 0x49df, + 0x8986, 0x06ad, + 0x8987, 0x49e1, + 0x898b, 0x1f96, + 0x898c, 0x49e5, + 0x898f, 0x1f32, + 0x8990, 0x49e8, + 0x8993, 0x2084, + 0x8994, 0x49eb, + 0x8996, 0x2136, + 0x8997, 0x49ed, + 0x8998, 0x24b8, + 0x8999, 0x49ee, + 0x89a1, 0x24ba, + 0x89a2, 0x49f6, + 0x89a6, 0x24bc, + 0x89a7, 0x49fa, + 0x89aa, 0x20e4, + 0x89ab, 0x49fd, + 0x89ac, 0x24b9, + 0x89ad, 0x49fe, + 0x89af, 0x24bd, + 0x89b0, 0x4a00, + 0x89b2, 0x24be, + 0x89b3, 0x4a02, + 0x89b7, 0x24bf, + 0x89b8, 0x4a06, + 0x89ba, 0x1fd2, + 0x89bb, 0x4a08, + 0x89bd, 0x1ffd, + 0x89be, 0x4a0a, + 0x89bf, 0x24bb, + 0x89c0, 0x1f2d, + 0x89c1, 0x086e, + 0x89c2, 0x0734, + 0x89c3, 0x4a0b, + 0x89c4, 0x073f, + 0x89c5, 0x0ade, + 0x89c6, 0x0d6a, + 0x89c7, 0x193a, + 0x89c8, 0x09ab, + 0x89c9, 0x0924, + 0x89ca, 0x193b, + 0x89cd, 0x4a0c, + 0x89ce, 0x193e, + 0x89d2, 0x0898, + 0x89d3, 0x4a0d, + 0x89d6, 0x1d57, + 0x89d7, 0x4a10, + 0x89da, 0x1d59, + 0x89db, 0x4a13, + 0x89dc, 0x1d5a, + 0x89dd, 0x4a14, + 0x89de, 0x1d58, + 0x89df, 0x4a15, + 0x89e3, 0x08b3, + 0x89e4, 0x4a19, + 0x89e5, 0x1d5b, + 0x89e6, 0x0528, + 0x89e7, 0x4a1a, + 0x89eb, 0x1d5c, + 0x89ec, 0x4a1e, + 0x89ef, 0x1d5d, + 0x89f0, 0x4a21, + 0x89f3, 0x19c0, + 0x89f4, 0x2609, + 0x89f5, 0x4a24, + 0x89f6, 0x260a, + 0x89f7, 0x4a25, + 0x89f8, 0x1e94, + 0x89f9, 0x4a26, + 0x8a00, 0x0ffd, + 0x8a01, 0x22df, + 0x8a02, 0x1ecb, + 0x8a03, 0x1f0d, + 0x8a04, 0x4a2d, + 0x8a07, 0x12fe, + 0x8a08, 0x1f77, + 0x8a09, 0x4a30, + 0x8a0a, 0x21eb, + 0x8a0b, 0x4a31, + 0x8a0c, 0x22e1, + 0x8a0d, 0x4a32, + 0x8a0e, 0x216f, + 0x8a0f, 0x4a33, + 0x8a10, 0x22e0, + 0x8a11, 0x4a34, + 0x8a13, 0x21ea, + 0x8a14, 0x4a36, + 0x8a15, 0x22e2, + 0x8a16, 0x20cb, + 0x8a17, 0x4a37, + 0x8a18, 0x1f78, + 0x8a19, 0x4a38, + 0x8a1b, 0x1ee2, + 0x8a1c, 0x4a3a, + 0x8a1d, 0x21f2, + 0x8a1e, 0x4a3b, + 0x8a1f, 0x2150, + 0x8a20, 0x4a3c, + 0x8a23, 0x1fd3, + 0x8a24, 0x4a3f, + 0x8a25, 0x22e5, + 0x8a26, 0x4a40, + 0x8a2a, 0x1ef2, + 0x8a2b, 0x4a44, + 0x8a2d, 0x211f, + 0x8a2e, 0x4a46, + 0x8a31, 0x21dd, + 0x8a32, 0x4a49, + 0x8a34, 0x2154, + 0x8a35, 0x4a4b, + 0x8a36, 0x22e7, + 0x8a37, 0x4a4c, + 0x8a3a, 0x2282, + 0x8a3b, 0x4a4f, + 0x8a3e, 0x1d5e, + 0x8a3f, 0x4a52, + 0x8a41, 0x22e6, + 0x8a42, 0x4a54, + 0x8a46, 0x22e8, + 0x8a47, 0x4a58, + 0x8a48, 0x1a84, + 0x8a49, 0x4a59, + 0x8a4e, 0x22e4, + 0x8a4f, 0x4a5e, + 0x8a50, 0x226a, + 0x8a51, 0x4a5f, + 0x8a52, 0x22eb, + 0x8a53, 0x4a60, + 0x8a54, 0x22e9, + 0x8a55, 0x20bd, + 0x8a56, 0x4a61, + 0x8a58, 0x22ea, + 0x8a59, 0x4a63, + 0x8a5b, 0x22bd, + 0x8a5c, 0x4a65, + 0x8a5e, 0x1e9e, + 0x8a5f, 0x4a67, + 0x8a61, 0x22f6, + 0x8a62, 0x21e7, + 0x8a63, 0x2216, + 0x8a64, 0x4a69, + 0x8a66, 0x2137, + 0x8a67, 0x4a6b, + 0x8a69, 0x212c, + 0x8a6a, 0x4a6d, + 0x8a6b, 0x1e68, + 0x8a6c, 0x22f2, + 0x8a6d, 0x1f37, + 0x8a6e, 0x22f3, + 0x8a6f, 0x4a6e, + 0x8a70, 0x22ef, + 0x8a71, 0x1f50, + 0x8a72, 0x1f10, + 0x8a73, 0x21c8, + 0x8a74, 0x4a6f, + 0x8a75, 0x22f1, + 0x8a76, 0x4a70, + 0x8a79, 0x1153, + 0x8a7a, 0x4a73, + 0x8a7c, 0x22f0, + 0x8a7d, 0x4a75, + 0x8a7f, 0x22ee, + 0x8a80, 0x4a77, + 0x8a84, 0x22ed, + 0x8a85, 0x229e, + 0x8a86, 0x22ec, + 0x8a87, 0x1fe2, + 0x8a88, 0x4a7b, + 0x8a89, 0x10e3, + 0x8a8a, 0x0e2f, + 0x8a8b, 0x4a7c, + 0x8a8d, 0x20fe, + 0x8a8e, 0x4a7e, + 0x8a91, 0x22f9, + 0x8a93, 0x0d5b, + 0x8a94, 0x4a81, + 0x8a95, 0x1eaf, + 0x8a96, 0x4a82, + 0x8a98, 0x2236, + 0x8a99, 0x4a84, + 0x8a9a, 0x22f7, + 0x8a9b, 0x4a85, + 0x8a9e, 0x223d, + 0x8a9f, 0x4a88, + 0x8aa0, 0x1e82, + 0x8aa1, 0x1fb6, + 0x8aa2, 0x4a89, + 0x8aa3, 0x21a4, + 0x8aa4, 0x21aa, + 0x8aa5, 0x22f8, + 0x8aa6, 0x2151, + 0x8aa7, 0x4a8a, + 0x8aa8, 0x1f60, + 0x8aa9, 0x4a8b, + 0x8aac, 0x2147, + 0x8aad, 0x4a8e, + 0x8ab0, 0x2145, + 0x8ab1, 0x4a91, + 0x8ab2, 0x1fdc, + 0x8ab3, 0x4a92, + 0x8ab6, 0x2301, + 0x8ab7, 0x4a95, + 0x8ab9, 0x1ef5, + 0x8aba, 0x4a97, + 0x8abc, 0x2218, + 0x8abd, 0x4a99, + 0x8abf, 0x1ec6, + 0x8ac0, 0x4a9b, + 0x8ac2, 0x2300, + 0x8ac3, 0x4a9d, + 0x8ac4, 0x22b4, + 0x8ac5, 0x4a9e, + 0x8ac7, 0x2169, + 0x8ac8, 0x4aa0, + 0x8ac9, 0x22fd, + 0x8aca, 0x4aa1, + 0x8acb, 0x20ea, + 0x8acc, 0x4aa2, + 0x8acd, 0x22f4, + 0x8ace, 0x4aa3, + 0x8acf, 0x22fb, + 0x8ad0, 0x4aa4, + 0x8ad1, 0x22fc, + 0x8ad2, 0x2027, + 0x8ad3, 0x4aa5, + 0x8ad6, 0x2060, + 0x8ad7, 0x22ff, + 0x8ad8, 0x4aa8, + 0x8adb, 0x22fe, + 0x8adc, 0x1ec7, + 0x8add, 0x4aab, + 0x8ade, 0x230c, + 0x8adf, 0x4aac, + 0x8ae2, 0x22f5, + 0x8ae3, 0x4aaf, + 0x8ae4, 0x2306, + 0x8ae5, 0x4ab0, + 0x8ae6, 0x230a, + 0x8ae7, 0x21d3, + 0x8ae8, 0x4ab1, + 0x8aeb, 0x2303, + 0x8aec, 0x4ab4, + 0x8aed, 0x2307, + 0x8aee, 0x230b, + 0x8aef, 0x4ab5, + 0x8af1, 0x1f5f, + 0x8af2, 0x4ab7, + 0x8af3, 0x2309, + 0x8af4, 0x4ab8, + 0x8af6, 0x2302, + 0x8af7, 0x1f04, + 0x8af8, 0x229d, + 0x8af9, 0x4aba, + 0x8afa, 0x21fb, + 0x8afb, 0x4abb, + 0x8afc, 0x2308, + 0x8afd, 0x4abc, + 0x8afe, 0x20ac, + 0x8aff, 0x4abd, + 0x8b00, 0x208e, + 0x8b01, 0x2305, + 0x8b02, 0x2197, + 0x8b03, 0x4abe, + 0x8b04, 0x2171, + 0x8b05, 0x2298, + 0x8b06, 0x4abf, + 0x8b07, 0x173c, + 0x8b08, 0x4ac0, + 0x8b0a, 0x1f57, + 0x8b0b, 0x4ac2, + 0x8b0e, 0x2082, + 0x8b0f, 0x4ac5, + 0x8b10, 0x2311, + 0x8b11, 0x4ac6, + 0x8b14, 0x2304, + 0x8b15, 0x4ac9, + 0x8b16, 0x230f, + 0x8b17, 0x1e35, + 0x8b18, 0x4aca, + 0x8b19, 0x20d1, + 0x8b1a, 0x2310, + 0x8b1b, 0x1fa3, + 0x8b1c, 0x4acb, + 0x8b1d, 0x21d6, + 0x8b1e, 0x4acc, + 0x8b21, 0x2206, + 0x8b22, 0x4acf, + 0x8b26, 0x1d5f, + 0x8b27, 0x4ad3, + 0x8b28, 0x230d, + 0x8b29, 0x4ad4, + 0x8b2b, 0x2312, + 0x8b2c, 0x208d, + 0x8b2d, 0x2313, + 0x8b2e, 0x4ad6, + 0x8b33, 0x22e3, + 0x8b34, 0x4adb, + 0x8b39, 0x1fba, + 0x8b3a, 0x4ae0, + 0x8b3e, 0x2078, + 0x8b3f, 0x4ae4, + 0x8b49, 0x2288, + 0x8b4a, 0x4aee, + 0x8b4e, 0x2316, + 0x8b4f, 0x1f6b, + 0x8b50, 0x4af2, + 0x8b56, 0x2314, + 0x8b57, 0x4af8, + 0x8b58, 0x2130, + 0x8b59, 0x2315, + 0x8b5a, 0x2168, + 0x8b5b, 0x4af9, + 0x8b5c, 0x20c4, + 0x8b5d, 0x4afa, + 0x8b66, 0x08de, + 0x8b67, 0x4b03, + 0x8b6b, 0x2318, + 0x8b6c, 0x0bc8, + 0x8b6d, 0x4b07, + 0x8b6f, 0x2219, + 0x8b70, 0x2217, + 0x8b71, 0x4b09, + 0x8b74, 0x20d5, + 0x8b75, 0x4b0c, + 0x8b77, 0x1f4a, + 0x8b78, 0x4b0e, + 0x8b7d, 0x2240, + 0x8b7e, 0x4b13, + 0x8b80, 0x1ed3, + 0x8b81, 0x4b15, + 0x8b8a, 0x1e49, + 0x8b8b, 0x4b1e, + 0x8b8e, 0x261b, + 0x8b8f, 0x4b21, + 0x8b92, 0x1e6d, + 0x8b93, 0x20f8, + 0x8b94, 0x4b24, + 0x8b95, 0x1ffb, + 0x8b96, 0x2319, + 0x8b97, 0x4b25, + 0x8b9c, 0x230e, + 0x8b9d, 0x4b2a, + 0x8b9e, 0x2317, + 0x8b9f, 0x4b2b, + 0x8ba0, 0x1317, + 0x8ba1, 0x0839, + 0x8ba2, 0x05e8, + 0x8ba3, 0x06b7, + 0x8ba4, 0x0caa, + 0x8ba5, 0x0818, + 0x8ba6, 0x1318, + 0x8ba8, 0x0e29, + 0x8ba9, 0x0c9e, + 0x8baa, 0x131a, + 0x8bab, 0x0c1c, + 0x8bac, 0x4b2c, + 0x8bad, 0x0fde, + 0x8bae, 0x1070, + 0x8baf, 0x0fdf, + 0x8bb0, 0x083a, + 0x8bb1, 0x4b2d, + 0x8bb2, 0x0883, + 0x8bb3, 0x07f9, + 0x8bb4, 0x131b, + 0x8bb6, 0x0ff1, + 0x8bb7, 0x131d, + 0x8bb8, 0x0fb8, + 0x8bb9, 0x062e, + 0x8bba, 0x0a82, + 0x8bbb, 0x4b2e, + 0x8bbc, 0x0dc4, + 0x8bbd, 0x068a, + 0x8bbe, 0x0d21, + 0x8bbf, 0x0660, + 0x8bc0, 0x0926, + 0x8bc1, 0x11a3, + 0x8bc2, 0x131e, + 0x8bc4, 0x0bdf, + 0x8bc5, 0x1244, + 0x8bc6, 0x0d4d, + 0x8bc7, 0x4b2f, + 0x8bc8, 0x114a, + 0x8bc9, 0x0dd4, + 0x8bca, 0x1190, + 0x8bcb, 0x1320, + 0x8bcc, 0x11de, + 0x8bcd, 0x054d, + 0x8bce, 0x1322, + 0x8bcf, 0x1321, + 0x8bd0, 0x4b30, + 0x8bd1, 0x1072, + 0x8bd2, 0x1323, + 0x8bd5, 0x0d6b, + 0x8bd6, 0x1326, + 0x8bd7, 0x0d42, + 0x8bd8, 0x1327, + 0x8bda, 0x04f4, + 0x8bdb, 0x11ee, + 0x8bdc, 0x1329, + 0x8bdd, 0x07c5, + 0x8bde, 0x058f, + 0x8bdf, 0x132a, + 0x8be1, 0x0747, + 0x8be2, 0x0fd8, + 0x8be3, 0x106f, + 0x8be4, 0x132c, + 0x8be5, 0x06be, + 0x8be6, 0x0f57, + 0x8be7, 0x04b6, + 0x8be8, 0x132d, + 0x8bea, 0x4b31, + 0x8beb, 0x08bc, + 0x8bec, 0x0eeb, + 0x8bed, 0x10d4, + 0x8bee, 0x132f, + 0x8bef, 0x0f02, + 0x8bf0, 0x1330, + 0x8bf1, 0x10ba, + 0x8bf2, 0x07fa, + 0x8bf3, 0x1331, + 0x8bf4, 0x0daa, + 0x8bf5, 0x0dc5, + 0x8bf6, 0x1332, + 0x8bf7, 0x0c68, + 0x8bf8, 0x11ed, + 0x8bf9, 0x1333, + 0x8bfa, 0x0b76, + 0x8bfb, 0x0600, + 0x8bfc, 0x1334, + 0x8bfd, 0x0669, + 0x8bfe, 0x095b, + 0x8bff, 0x1335, + 0x8c00, 0x1336, + 0x8c01, 0x0da2, + 0x8c02, 0x1337, + 0x8c03, 0x05d8, + 0x8c04, 0x1338, + 0x8c05, 0x0a0b, + 0x8c06, 0x1218, + 0x8c07, 0x1339, + 0x8c08, 0x0e0b, + 0x8c09, 0x4b32, + 0x8c0a, 0x1071, + 0x8c0b, 0x0b14, + 0x8c0c, 0x133a, + 0x8c0d, 0x05de, + 0x8c0e, 0x07e6, + 0x8c0f, 0x133b, + 0x8c10, 0x0f7e, + 0x8c11, 0x133c, + 0x8c13, 0x0ecc, + 0x8c14, 0x133e, + 0x8c17, 0x04be, + 0x8c18, 0x1343, + 0x8c19, 0x1341, + 0x8c1a, 0x1011, + 0x8c1b, 0x1342, + 0x8c1c, 0x0ada, + 0x8c1d, 0x1344, + 0x8c1e, 0x4b33, + 0x8c1f, 0x1345, + 0x8c22, 0x0f86, + 0x8c23, 0x102c, + 0x8c24, 0x0404, + 0x8c25, 0x1348, + 0x8c26, 0x0c28, + 0x8c27, 0x1349, + 0x8c28, 0x08c8, + 0x8c29, 0x0aa6, + 0x8c2a, 0x134a, + 0x8c2c, 0x0b02, + 0x8c2d, 0x0e0a, + 0x8c2e, 0x134c, + 0x8c30, 0x09a9, + 0x8c31, 0x0bf6, + 0x8c32, 0x134e, + 0x8c34, 0x0c31, + 0x8c35, 0x1350, + 0x8c37, 0x0721, + 0x8c38, 0x4b34, + 0x8c41, 0x0802, + 0x8c42, 0x4b3d, + 0x8c46, 0x05f8, + 0x8c47, 0x1cf6, + 0x8c48, 0x20c8, + 0x8c49, 0x1cf7, + 0x8c4a, 0x4b41, + 0x8c4c, 0x0e94, + 0x8c4d, 0x4b43, + 0x8c50, 0x1efd, + 0x8c51, 0x4b46, + 0x8c55, 0x1d15, + 0x8c56, 0x4b4a, + 0x8c5a, 0x1990, + 0x8c5b, 0x4b4e, + 0x8c61, 0x0f60, + 0x8c62, 0x07d4, + 0x8c63, 0x4b54, + 0x8c6a, 0x0777, + 0x8c6b, 0x10e8, + 0x8c6c, 0x4b5b, + 0x8c73, 0x15dd, + 0x8c74, 0x4b62, + 0x8c78, 0x1d50, + 0x8c79, 0x0413, + 0x8c7a, 0x04b9, + 0x8c7b, 0x4b66, + 0x8c82, 0x1d51, + 0x8c83, 0x4b6d, + 0x8c85, 0x1d53, + 0x8c86, 0x4b6f, + 0x8c89, 0x0788, + 0x8c8a, 0x1d52, + 0x8c8b, 0x4b72, + 0x8c8c, 0x0ab7, + 0x8c8d, 0x4b73, + 0x8c94, 0x1d55, + 0x8c95, 0x4b7a, + 0x8c98, 0x1d54, + 0x8c99, 0x4b7d, + 0x8c9d, 0x1e3b, + 0x8c9e, 0x227f, + 0x8c9f, 0x4b81, + 0x8ca0, 0x1f0c, + 0x8ca1, 0x1e59, + 0x8ca2, 0x1f24, + 0x8ca3, 0x4b82, + 0x8ca7, 0x20ba, + 0x8ca8, 0x1f65, + 0x8ca9, 0x1ef0, + 0x8caa, 0x2164, + 0x8cab, 0x1f30, + 0x8cac, 0x2261, + 0x8cad, 0x4b86, + 0x8caf, 0x22a2, + 0x8cb0, 0x24ab, + 0x8cb1, 0x4b88, + 0x8cb2, 0x24af, + 0x8cb3, 0x1ee8, + 0x8cb4, 0x1f39, + 0x8cb5, 0x4b89, + 0x8cb6, 0x1e48, + 0x8cb7, 0x2070, + 0x8cb8, 0x1ea8, + 0x8cb9, 0x4b8a, + 0x8cba, 0x24ac, + 0x8cbb, 0x1ef7, + 0x8cbc, 0x2176, + 0x8cbd, 0x24ad, + 0x8cbe, 0x4b8b, + 0x8cbf, 0x207b, + 0x8cc0, 0x1f45, + 0x8cc1, 0x24aa, + 0x8cc2, 0x204b, + 0x8cc3, 0x202f, + 0x8cc4, 0x1f5a, + 0x8cc5, 0x24b0, + 0x8cc6, 0x4b8c, + 0x8cc7, 0x22b7, + 0x8cc8, 0x1f7f, + 0x8cc9, 0x4b8d, + 0x8cca, 0x2265, + 0x8ccb, 0x4b8e, + 0x8cd1, 0x24b2, + 0x8cd2, 0x211b, + 0x8cd3, 0x1e51, + 0x8cd4, 0x4b94, + 0x8cd5, 0x24b4, + 0x8cd6, 0x4b95, + 0x8cda, 0x24b3, + 0x8cdb, 0x4b99, + 0x8cdc, 0x1e9f, + 0x8cdd, 0x4b9a, + 0x8cde, 0x2118, + 0x8cdf, 0x4b9b, + 0x8ce0, 0x20b4, + 0x8ce1, 0x23af, + 0x8ce2, 0x21bb, + 0x8ce3, 0x2072, + 0x8ce4, 0x1f95, + 0x8ce5, 0x4b9c, + 0x8ce6, 0x1f0a, + 0x8ce7, 0x24b6, + 0x8ce8, 0x4b9d, + 0x8cea, 0x2291, + 0x8ceb, 0x24b5, + 0x8cec, 0x2278, + 0x8ced, 0x1ed4, + 0x8cee, 0x4b9f, + 0x8cf4, 0x1ff3, + 0x8cf5, 0x4ba5, + 0x8cfa, 0x22a9, + 0x8cfb, 0x24b7, + 0x8cfc, 0x1f28, + 0x8cfd, 0x2109, + 0x8cfe, 0x22c7, + 0x8cff, 0x4baa, + 0x8d00, 0x4bab, + 0x8d04, 0x24ae, + 0x8d05, 0x22b1, + 0x8d06, 0x4baf, + 0x8d08, 0x2266, + 0x8d09, 0x4bb1, + 0x8d0a, 0x225b, + 0x8d0b, 0x22c4, + 0x8d0c, 0x4bb2, + 0x8d0d, 0x2115, + 0x8d0e, 0x4bb3, + 0x8d0f, 0x222a, + 0x8d10, 0x24b1, + 0x8d11, 0x4bb4, + 0x8d16, 0x213d, + 0x8d17, 0x4bb9, + 0x8d1b, 0x1f15, + 0x8d1c, 0x225c, + 0x8d1d, 0x041d, + 0x8d1e, 0x118b, + 0x8d1f, 0x06b5, + 0x8d20, 0x4bbd, + 0x8d21, 0x070a, + 0x8d22, 0x048d, + 0x8d23, 0x1133, + 0x8d24, 0x0f3a, + 0x8d25, 0x03e7, + 0x8d26, 0x116c, + 0x8d27, 0x080a, + 0x8d28, 0x11c9, + 0x8d29, 0x0654, + 0x8d2a, 0x0e03, + 0x8d2b, 0x0bd5, + 0x8d2c, 0x044a, + 0x8d2d, 0x0713, + 0x8d2e, 0x11fb, + 0x8d2f, 0x073a, + 0x8d30, 0x063e, + 0x8d31, 0x086d, + 0x8d32, 0x192c, + 0x8d34, 0x0e4c, + 0x8d35, 0x074c, + 0x8d36, 0x192e, + 0x8d37, 0x057e, + 0x8d38, 0x0ab8, + 0x8d39, 0x066e, + 0x8d3a, 0x078f, + 0x8d3b, 0x192f, + 0x8d3c, 0x1137, + 0x8d3d, 0x1930, + 0x8d3e, 0x0849, + 0x8d3f, 0x07f4, + 0x8d40, 0x1931, + 0x8d41, 0x0a27, + 0x8d42, 0x0a5f, + 0x8d43, 0x1122, + 0x8d44, 0x1227, + 0x8d45, 0x1932, + 0x8d47, 0x1936, + 0x8d48, 0x1934, + 0x8d4a, 0x0d17, + 0x8d4b, 0x06ae, + 0x8d4c, 0x0603, + 0x8d4d, 0x1937, + 0x8d4e, 0x0d81, + 0x8d4f, 0x0d06, + 0x8d50, 0x0550, + 0x8d51, 0x4bbe, + 0x8d53, 0x163b, + 0x8d54, 0x0ba3, + 0x8d55, 0x1938, + 0x8d56, 0x09a0, + 0x8d57, 0x4bc0, + 0x8d58, 0x1215, + 0x8d59, 0x1939, + 0x8d5a, 0x1209, + 0x8d5b, 0x0cd7, + 0x8d5c, 0x1289, + 0x8d5d, 0x1283, + 0x8d5e, 0x1121, + 0x8d5f, 0x4bc1, + 0x8d60, 0x113c, + 0x8d61, 0x0cfd, + 0x8d62, 0x1093, + 0x8d63, 0x06ce, + 0x8d64, 0x0505, + 0x8d65, 0x4bc2, + 0x8d66, 0x0d1b, + 0x8d67, 0x1cf4, + 0x8d68, 0x4bc3, + 0x8d6b, 0x078c, + 0x8d6c, 0x4bc6, + 0x8d6d, 0x1cf5, + 0x8d6e, 0x4bc7, + 0x8d70, 0x123c, + 0x8d71, 0x4bc9, + 0x8d73, 0x1cef, + 0x8d74, 0x06ab, + 0x8d75, 0x1175, + 0x8d76, 0x06ca, + 0x8d77, 0x0c0f, + 0x8d78, 0x4bcb, + 0x8d81, 0x04e8, + 0x8d82, 0x4bd4, + 0x8d84, 0x1cf0, + 0x8d85, 0x04d1, + 0x8d86, 0x4bd6, + 0x8d8a, 0x1100, + 0x8d8b, 0x0c74, + 0x8d8c, 0x4bda, + 0x8d91, 0x1cf2, + 0x8d92, 0x4bdf, + 0x8d94, 0x1cf1, + 0x8d95, 0x1f14, + 0x8d96, 0x4be1, + 0x8d99, 0x227a, + 0x8d9a, 0x4be4, + 0x8d9f, 0x0e1e, + 0x8da0, 0x4be9, + 0x8da3, 0x0c7f, + 0x8da4, 0x4bec, + 0x8da8, 0x20ee, + 0x8da9, 0x4bf0, + 0x8db1, 0x1cf3, + 0x8db2, 0x25f8, + 0x8db3, 0x1240, + 0x8db4, 0x0b80, + 0x8db5, 0x1d1c, + 0x8db6, 0x4bf8, + 0x8db8, 0x1d17, + 0x8db9, 0x4bfa, + 0x8dba, 0x1d1f, + 0x8dbb, 0x4bfb, + 0x8dbc, 0x1d1e, + 0x8dbd, 0x4bfc, + 0x8dbe, 0x11b9, + 0x8dbf, 0x1d1d, + 0x8dc0, 0x4bfd, + 0x8dc3, 0x1101, + 0x8dc4, 0x1d20, + 0x8dc5, 0x4c00, + 0x8dc6, 0x1d28, + 0x8dc7, 0x4c01, + 0x8dcb, 0x03da, + 0x8dcc, 0x05d9, + 0x8dcd, 0x4c05, + 0x8dce, 0x1d25, + 0x8dd0, 0x4c06, + 0x8dd1, 0x0b9d, + 0x8dd2, 0x4c07, + 0x8dd6, 0x1d21, + 0x8dd8, 0x4c0b, + 0x8dda, 0x1d23, + 0x8ddb, 0x1d27, + 0x8ddc, 0x4c0d, + 0x8ddd, 0x090f, + 0x8dde, 0x1d24, + 0x8ddf, 0x06f5, + 0x8de0, 0x4c0e, + 0x8de3, 0x1d2c, + 0x8de4, 0x1d2f, + 0x8de5, 0x4c11, + 0x8de8, 0x0974, + 0x8de9, 0x4c14, + 0x8dea, 0x074b, + 0x8deb, 0x1d18, + 0x8dec, 0x1d29, + 0x8ded, 0x4c15, + 0x8def, 0x0a5e, + 0x8df0, 0x4c17, + 0x8df3, 0x0e4b, + 0x8df4, 0x4c1a, + 0x8df5, 0x086c, + 0x8df6, 0x4c1b, + 0x8df7, 0x1d2a, + 0x8df9, 0x1d2d, + 0x8dfa, 0x0624, + 0x8dfb, 0x1d2e, + 0x8dfc, 0x4c1c, + 0x8dfd, 0x1d31, + 0x8dfe, 0x4c1d, + 0x8e00, 0x4c1f, + 0x8e05, 0x1d19, + 0x8e06, 0x4c24, + 0x8e09, 0x1d30, + 0x8e0a, 0x10a0, + 0x8e0b, 0x4c27, + 0x8e0c, 0x0511, + 0x8e0d, 0x4c28, + 0x8e0f, 0x0df7, + 0x8e10, 0x1f94, + 0x8e11, 0x4c2a, + 0x8e14, 0x1d32, + 0x8e15, 0x4c2d, + 0x8e1d, 0x1d33, + 0x8e1e, 0x0910, + 0x8e1f, 0x1d34, + 0x8e20, 0x4c35, + 0x8e22, 0x0e32, + 0x8e23, 0x1d37, + 0x8e24, 0x4c37, + 0x8e29, 0x048f, + 0x8e2a, 0x1236, + 0x8e2b, 0x4c3c, + 0x8e2c, 0x1d35, + 0x8e2d, 0x4c3d, + 0x8e2e, 0x1d36, + 0x8e2f, 0x1d38, + 0x8e30, 0x4c3e, + 0x8e31, 0x1d3e, + 0x8e32, 0x4c3f, + 0x8e34, 0x2230, + 0x8e35, 0x1d3c, + 0x8e36, 0x4c41, + 0x8e39, 0x1d3b, + 0x8e3a, 0x1d39, + 0x8e3b, 0x4c44, + 0x8e3d, 0x1d3d, + 0x8e3e, 0x4c46, + 0x8e40, 0x1d3a, + 0x8e41, 0x1d40, + 0x8e43, 0x4c48, + 0x8e44, 0x0e36, + 0x8e45, 0x4c49, + 0x8e47, 0x173b, + 0x8e48, 0x0599, + 0x8e49, 0x1d3f, + 0x8e4a, 0x1d44, + 0x8e4b, 0x0df6, + 0x8e4c, 0x25fd, + 0x8e4d, 0x4c4b, + 0x8e51, 0x1d42, + 0x8e53, 0x4c4f, + 0x8e55, 0x2600, + 0x8e56, 0x4c51, + 0x8e59, 0x1d1a, + 0x8e5a, 0x4c54, + 0x8e63, 0x2606, + 0x8e64, 0x4c5d, + 0x8e66, 0x042d, + 0x8e67, 0x4c5f, + 0x8e69, 0x1d1b, + 0x8e6a, 0x4c61, + 0x8e6c, 0x05a6, + 0x8e6d, 0x04ab, + 0x8e6e, 0x4c63, + 0x8e6f, 0x1d48, + 0x8e70, 0x1d45, + 0x8e71, 0x4c64, + 0x8e72, 0x0616, + 0x8e73, 0x4c65, + 0x8e74, 0x1d49, + 0x8e75, 0x4c66, + 0x8e76, 0x1d46, + 0x8e77, 0x4c67, + 0x8e7a, 0x25ff, + 0x8e7b, 0x4c6a, + 0x8e7c, 0x1d47, + 0x8e7d, 0x4c6b, + 0x8e7f, 0x055d, + 0x8e80, 0x4c6d, + 0x8e81, 0x112d, + 0x8e82, 0x4c6e, + 0x8e85, 0x1d4a, + 0x8e86, 0x4c71, + 0x8e87, 0x051e, + 0x8e88, 0x4c72, + 0x8e89, 0x25fc, + 0x8e8a, 0x1e8c, + 0x8e8b, 0x2602, + 0x8e8c, 0x4c73, + 0x8e8d, 0x224d, + 0x8e8e, 0x4c74, + 0x8e8f, 0x1d4b, + 0x8e90, 0x1d4d, + 0x8e91, 0x2604, + 0x8e92, 0x25fe, + 0x8e93, 0x2603, + 0x8e94, 0x1d4c, + 0x8e95, 0x4c75, + 0x8e9a, 0x2601, + 0x8e9b, 0x4c7a, + 0x8e9c, 0x1d4e, + 0x8e9d, 0x4c7b, + 0x8e9e, 0x1d4f, + 0x8e9f, 0x4c7c, + 0x8ea1, 0x2605, + 0x8ea2, 0x4c7e, + 0x8ea5, 0x1ea3, + 0x8ea6, 0x2608, + 0x8ea7, 0x4c81, + 0x8eaa, 0x2607, + 0x8eab, 0x0d26, + 0x8eac, 0x0703, + 0x8ead, 0x4c84, + 0x8eaf, 0x0c78, + 0x8eb0, 0x4c86, + 0x8eb2, 0x0622, + 0x8eb3, 0x4c88, + 0x8eba, 0x0e1c, + 0x8ebb, 0x4c8f, + 0x8ec0, 0x20f0, + 0x8ec1, 0x4c94, + 0x8eca, 0x1e7b, + 0x8ecb, 0x2267, + 0x8ecc, 0x1f36, + 0x8ecd, 0x1fd6, + 0x8ece, 0x18f8, + 0x8ecf, 0x4c9d, + 0x8ed2, 0x21e0, + 0x8ed3, 0x4ca0, + 0x8ed4, 0x248c, + 0x8ed5, 0x4ca1, + 0x8edb, 0x248d, + 0x8edc, 0x4ca7, + 0x8edf, 0x2102, + 0x8ee0, 0x4caa, + 0x8ee4, 0x2494, + 0x8ee5, 0x4cae, + 0x8eeb, 0x2493, + 0x8eec, 0x4cb4, + 0x8ef2, 0x248e, + 0x8ef3, 0x4cba, + 0x8ef8, 0x2299, + 0x8ef9, 0x2491, + 0x8efa, 0x2496, + 0x8efb, 0x248f, + 0x8efc, 0x2492, + 0x8efd, 0x4cbf, + 0x8efe, 0x2497, + 0x8eff, 0x4cc0, + 0x8f00, 0x4cc1, + 0x8f03, 0x1fb1, + 0x8f04, 0x4cc4, + 0x8f05, 0x249a, + 0x8f06, 0x4cc5, + 0x8f07, 0x2499, + 0x8f08, 0x4cc6, + 0x8f09, 0x2258, + 0x8f0a, 0x2498, + 0x8f0b, 0x4cc7, + 0x8f12, 0x249b, + 0x8f13, 0x4cce, + 0x8f14, 0x1f09, + 0x8f15, 0x20e6, + 0x8f16, 0x4ccf, + 0x8f1b, 0x2026, + 0x8f1c, 0x249f, + 0x8f1d, 0x1f59, + 0x8f1e, 0x249d, + 0x8f20, 0x4cd4, + 0x8f25, 0x1f3b, + 0x8f26, 0x249c, + 0x8f27, 0x4cd9, + 0x8f29, 0x1e3a, + 0x8f2a, 0x205b, + 0x8f2b, 0x4cdb, + 0x8f2f, 0x1f70, + 0x8f30, 0x4cdf, + 0x8f33, 0x24a0, + 0x8f34, 0x4ce2, + 0x8f38, 0x213b, + 0x8f39, 0x4ce6, + 0x8f3b, 0x1f07, + 0x8f3c, 0x4ce8, + 0x8f3e, 0x2270, + 0x8f3f, 0x2237, + 0x8f40, 0x4cea, + 0x8f42, 0x24d2, + 0x8f43, 0x4cec, + 0x8f44, 0x21b3, + 0x8f45, 0x2245, + 0x8f46, 0x24a1, + 0x8f47, 0x4ced, + 0x8f49, 0x22a8, + 0x8f4a, 0x4cef, + 0x8f4d, 0x227c, + 0x8f4e, 0x1fb0, + 0x8f4f, 0x4cf2, + 0x8f54, 0x24a2, + 0x8f55, 0x4cf7, + 0x8f5f, 0x1f46, + 0x8f60, 0x4d01, + 0x8f61, 0x2380, + 0x8f62, 0x2495, + 0x8f63, 0x4d02, + 0x8f64, 0x2490, + 0x8f65, 0x4d03, + 0x8f66, 0x04da, + 0x8f67, 0x1141, + 0x8f68, 0x0745, + 0x8f69, 0x0fc4, + 0x8f6a, 0x4d04, + 0x8f6b, 0x18e1, + 0x8f6c, 0x1207, + 0x8f6d, 0x18e2, + 0x8f6e, 0x0a7d, + 0x8f6f, 0x0cc8, + 0x8f70, 0x079b, + 0x8f71, 0x18e3, + 0x8f74, 0x11e0, + 0x8f75, 0x18e6, + 0x8f77, 0x18e9, + 0x8f78, 0x18e8, + 0x8f79, 0x18ea, + 0x8f7b, 0x0c5e, + 0x8f7c, 0x18ec, + 0x8f7d, 0x111b, + 0x8f7e, 0x18ed, + 0x8f7f, 0x089f, + 0x8f80, 0x4d05, + 0x8f81, 0x18ee, + 0x8f83, 0x08a0, + 0x8f84, 0x18f0, + 0x8f85, 0x06a3, + 0x8f86, 0x0a07, + 0x8f87, 0x18f1, + 0x8f88, 0x041b, + 0x8f89, 0x07e9, + 0x8f8a, 0x074e, + 0x8f8b, 0x18f2, + 0x8f8c, 0x4d06, + 0x8f8d, 0x18f3, + 0x8f90, 0x0695, + 0x8f91, 0x0820, + 0x8f92, 0x4d07, + 0x8f93, 0x0d7b, + 0x8f94, 0x1574, + 0x8f95, 0x10f2, + 0x8f96, 0x0f2a, + 0x8f97, 0x1158, + 0x8f98, 0x18f6, + 0x8f99, 0x117f, + 0x8f9a, 0x18f7, + 0x8f9b, 0x0f8c, + 0x8f9c, 0x0715, + 0x8f9d, 0x4d08, + 0x8f9e, 0x054a, + 0x8f9f, 0x0442, + 0x8fa0, 0x4d09, + 0x8fa3, 0x099c, + 0x8fa4, 0x4d0c, + 0x8fa6, 0x1e30, + 0x8fa7, 0x4d0e, + 0x8fa8, 0x044f, + 0x8faa, 0x4d0f, + 0x8fab, 0x0451, + 0x8fac, 0x4d10, + 0x8fad, 0x1e9d, + 0x8fae, 0x1e4b, + 0x8faf, 0x1e4a, + 0x8fb0, 0x04e2, + 0x8fb1, 0x0cc3, + 0x8fb2, 0x20aa, + 0x8fb3, 0x4d11, + 0x8fb6, 0x173d, + 0x8fb7, 0x4d14, + 0x8fb9, 0x0448, + 0x8fba, 0x4d16, + 0x8fbd, 0x0a12, + 0x8fbe, 0x0572, + 0x8fbf, 0x4d19, + 0x8fc1, 0x0c25, + 0x8fc2, 0x10bd, + 0x8fc3, 0x4d1b, + 0x8fc4, 0x0c18, + 0x8fc5, 0x0fe1, + 0x8fc6, 0x4d1c, + 0x8fc7, 0x0756, + 0x8fc8, 0x0a9c, + 0x8fc9, 0x4d1d, + 0x8fce, 0x1092, + 0x8fcf, 0x4d22, + 0x8fd0, 0x110e, + 0x8fd1, 0x08cd, + 0x8fd2, 0x4d23, + 0x8fd3, 0x173e, + 0x8fd4, 0x0652, + 0x8fd5, 0x173f, + 0x8fd6, 0x4d24, + 0x8fd8, 0x07ce, + 0x8fd9, 0x1183, + 0x8fda, 0x4d26, + 0x8fdb, 0x08c9, + 0x8fdc, 0x10f9, + 0x8fdd, 0x0eb4, + 0x8fde, 0x09f5, + 0x8fdf, 0x04fe, + 0x8fe0, 0x4d27, + 0x8fe2, 0x0e49, + 0x8fe3, 0x4d29, + 0x8fe4, 0x1742, + 0x8fe5, 0x1740, + 0x8fe6, 0x1744, + 0x8fe7, 0x4d2a, + 0x8fe8, 0x1746, + 0x8fe9, 0x1743, + 0x8fea, 0x05b0, + 0x8feb, 0x0be7, + 0x8fec, 0x4d2b, + 0x8fed, 0x05dd, + 0x8fee, 0x1741, + 0x8fef, 0x4d2c, + 0x8ff0, 0x0d8d, + 0x8ff1, 0x4d2d, + 0x8ff3, 0x1745, + 0x8ff4, 0x267b, + 0x8ff5, 0x4d2f, + 0x8ff7, 0x0ad9, + 0x8ff8, 0x042e, + 0x8ff9, 0x0816, + 0x8ffa, 0x4d31, + 0x8ffd, 0x1214, + 0x8ffe, 0x4d34, + 0x9000, 0x0e7c, + 0x9001, 0x0dc2, + 0x9002, 0x0d61, + 0x9003, 0x0e26, + 0x9004, 0x1748, + 0x9005, 0x1747, + 0x9006, 0x0b49, + 0x9007, 0x4d36, + 0x9009, 0x0fca, + 0x900a, 0x0fe0, + 0x900b, 0x1749, + 0x900c, 0x4d38, + 0x900d, 0x174c, + 0x900e, 0x4d39, + 0x900f, 0x0e69, + 0x9010, 0x11ef, + 0x9011, 0x174b, + 0x9012, 0x05be, + 0x9013, 0x4d3a, + 0x9014, 0x0e6f, + 0x9015, 0x23f2, + 0x9016, 0x174d, + 0x9017, 0x05f9, + 0x9018, 0x4d3b, + 0x9019, 0x227e, + 0x901a, 0x0e59, + 0x901b, 0x073d, + 0x901c, 0x4d3c, + 0x901d, 0x0d5c, + 0x901e, 0x04f6, + 0x901f, 0x0dce, + 0x9020, 0x112f, + 0x9021, 0x174e, + 0x9022, 0x0687, + 0x9023, 0x2019, + 0x9024, 0x4d3d, + 0x9026, 0x174a, + 0x9027, 0x4d3f, + 0x902d, 0x1751, + 0x902e, 0x0581, + 0x902f, 0x1752, + 0x9030, 0x4d45, + 0x9032, 0x1fbb, + 0x9033, 0x4d47, + 0x9035, 0x174f, + 0x9037, 0x4d49, + 0x9038, 0x1064, + 0x9039, 0x4d4a, + 0x903b, 0x0a86, + 0x903c, 0x042f, + 0x903d, 0x4d4c, + 0x903e, 0x10c7, + 0x903f, 0x4d4d, + 0x9041, 0x061c, + 0x9042, 0x0de1, + 0x9043, 0x4d4f, + 0x9044, 0x1753, + 0x9045, 0x4d50, + 0x9047, 0x10db, + 0x9048, 0x4d52, + 0x904b, 0x2253, + 0x904c, 0x4d55, + 0x904d, 0x0452, + 0x904e, 0x1f3e, + 0x904f, 0x0633, + 0x9050, 0x1756, + 0x9051, 0x1754, + 0x9053, 0x05a1, + 0x9054, 0x1ea6, + 0x9055, 0x218e, + 0x9056, 0x4d56, + 0x9057, 0x104c, + 0x9058, 0x1758, + 0x9059, 0x4d57, + 0x905b, 0x175a, + 0x905c, 0x21ec, + 0x905d, 0x4d59, + 0x905e, 0x1ebe, + 0x905f, 0x4d5a, + 0x9060, 0x224a, + 0x9061, 0x4d5b, + 0x9062, 0x1759, + 0x9063, 0x0c2f, + 0x9064, 0x4d5c, + 0x9065, 0x102a, + 0x9066, 0x4d5d, + 0x9068, 0x1757, + 0x9069, 0x2133, + 0x906a, 0x4d5f, + 0x906d, 0x1125, + 0x906e, 0x117b, + 0x906f, 0x4d62, + 0x9072, 0x1e84, + 0x9073, 0x4d65, + 0x9074, 0x175c, + 0x9075, 0x124e, + 0x9076, 0x4d66, + 0x9077, 0x20cf, + 0x9078, 0x21e2, + 0x9079, 0x4d67, + 0x907a, 0x220f, + 0x907b, 0x4d68, + 0x907c, 0x2029, + 0x907d, 0x175d, + 0x907e, 0x4d69, + 0x907f, 0x0445, + 0x9080, 0x1024, + 0x9081, 0x2073, + 0x9082, 0x175e, + 0x9083, 0x1760, + 0x9084, 0x1f55, + 0x9085, 0x4d6a, + 0x9087, 0x23f1, + 0x9088, 0x175f, + 0x9089, 0x4d6c, + 0x908a, 0x1e46, + 0x908b, 0x1761, + 0x908c, 0x4d6d, + 0x908f, 0x2063, + 0x9090, 0x23f3, + 0x9091, 0x105f, + 0x9092, 0x4d70, + 0x9093, 0x05ac, + 0x9094, 0x4d71, + 0x9095, 0x1817, + 0x9096, 0x4d72, + 0x9097, 0x1367, + 0x9098, 0x4d73, + 0x9099, 0x136a, + 0x909a, 0x4d74, + 0x909b, 0x1368, + 0x909c, 0x4d75, + 0x909d, 0x1369, + 0x909e, 0x4d76, + 0x90a1, 0x136c, + 0x90a2, 0x0f9a, + 0x90a3, 0x0b2a, + 0x90a4, 0x4d79, + 0x90a6, 0x03f9, + 0x90a7, 0x4d7b, + 0x90aa, 0x0f7b, + 0x90ab, 0x4d7e, + 0x90ac, 0x136b, + 0x90ad, 0x4d7f, + 0x90ae, 0x10af, + 0x90af, 0x0761, + 0x90b0, 0x1372, + 0x90b1, 0x0c6e, + 0x90b2, 0x4d80, + 0x90b3, 0x136e, + 0x90b4, 0x136d, + 0x90b5, 0x0d14, + 0x90b6, 0x136f, + 0x90b7, 0x4d81, + 0x90b8, 0x1371, + 0x90b9, 0x123b, + 0x90ba, 0x1370, + 0x90bb, 0x0a23, + 0x90bc, 0x4d82, + 0x90be, 0x1375, + 0x90bf, 0x4d84, + 0x90c1, 0x10d9, + 0x90c2, 0x4d86, + 0x90c4, 0x1377, + 0x90c5, 0x1374, + 0x90c6, 0x4d88, + 0x90c7, 0x1378, + 0x90c8, 0x4d89, + 0x90ca, 0x088d, + 0x90cb, 0x4d8b, + 0x90ce, 0x09b4, + 0x90cf, 0x1373, + 0x90d0, 0x1376, + 0x90d1, 0x11a2, + 0x90d2, 0x4d8e, + 0x90d3, 0x1379, + 0x90d4, 0x4d8f, + 0x90d7, 0x137d, + 0x90d8, 0x4d92, + 0x90db, 0x137e, + 0x90dc, 0x137c, + 0x90dd, 0x0779, + 0x90de, 0x4d95, + 0x90df, 0x231e, + 0x90e0, 0x4d96, + 0x90e1, 0x0931, + 0x90e2, 0x137b, + 0x90e3, 0x4d97, + 0x90e6, 0x137a, + 0x90e7, 0x110a, + 0x90e8, 0x0486, + 0x90e9, 0x4d9a, + 0x90eb, 0x137f, + 0x90ec, 0x4d9c, + 0x90ed, 0x0752, + 0x90ee, 0x4d9d, + 0x90ef, 0x1380, + 0x90f0, 0x4d9e, + 0x90f4, 0x04e0, + 0x90f5, 0x2233, + 0x90f6, 0x4da2, + 0x90f8, 0x0587, + 0x90f9, 0x4da4, + 0x90fd, 0x05fb, + 0x90fe, 0x1381, + 0x90ff, 0x4da8, + 0x9100, 0x4da9, + 0x9102, 0x0634, + 0x9103, 0x4dab, + 0x9104, 0x1382, + 0x9105, 0x4dac, + 0x9106, 0x2320, + 0x9107, 0x4dad, + 0x9109, 0x21c7, + 0x910a, 0x4daf, + 0x9112, 0x22bc, + 0x9113, 0x4db7, + 0x9114, 0x231c, + 0x9115, 0x4db8, + 0x9116, 0x2251, + 0x9117, 0x4db9, + 0x9119, 0x0432, + 0x911a, 0x4dbb, + 0x911e, 0x1384, + 0x911f, 0x4dbf, + 0x9122, 0x1383, + 0x9123, 0x1385, + 0x9124, 0x4dc2, + 0x9127, 0x1ebb, + 0x9128, 0x4dc5, + 0x912d, 0x2287, + 0x912e, 0x4dca, + 0x912f, 0x1387, + 0x9130, 0x202d, + 0x9131, 0x1386, + 0x9132, 0x1eab, + 0x9133, 0x4dcb, + 0x9134, 0x231d, + 0x9135, 0x4dcc, + 0x9136, 0x231f, + 0x9137, 0x4dcd, + 0x9139, 0x1388, + 0x913a, 0x231b, + 0x913b, 0x4dcf, + 0x9143, 0x1389, + 0x9144, 0x4dd7, + 0x9146, 0x138a, + 0x9147, 0x4dd9, + 0x9148, 0x2321, + 0x9149, 0x10b4, + 0x914a, 0x1cf8, + 0x914b, 0x0c72, + 0x914c, 0x1220, + 0x914d, 0x0ba5, + 0x914e, 0x1cfa, + 0x9150, 0x1cf9, + 0x9151, 0x4dda, + 0x9152, 0x08f5, + 0x9153, 0x4ddb, + 0x9157, 0x0fba, + 0x9158, 0x4ddf, + 0x915a, 0x0670, + 0x915b, 0x4de1, + 0x915d, 0x1110, + 0x915e, 0x0dfd, + 0x915f, 0x4de3, + 0x9161, 0x1cfe, + 0x9162, 0x1cfd, + 0x9163, 0x075f, + 0x9164, 0x1cfc, + 0x9165, 0x0dcb, + 0x9166, 0x4de5, + 0x9169, 0x1d00, + 0x916a, 0x09bd, + 0x916b, 0x4de8, + 0x916c, 0x050f, + 0x916d, 0x4de9, + 0x916e, 0x0e5b, + 0x916f, 0x1d01, + 0x9170, 0x1cff, + 0x9171, 0x0885, + 0x9172, 0x1d04, + 0x9173, 0x4dea, + 0x9174, 0x1d05, + 0x9175, 0x089e, + 0x9176, 0x0abd, + 0x9177, 0x096e, + 0x9178, 0x0dd6, + 0x9179, 0x1d06, + 0x917a, 0x4deb, + 0x917d, 0x1d02, + 0x917f, 0x0b53, + 0x9180, 0x4dee, + 0x9185, 0x1d08, + 0x9186, 0x4df3, + 0x9187, 0x053f, + 0x9188, 0x4df4, + 0x9189, 0x124a, + 0x918a, 0x4df5, + 0x918b, 0x055a, + 0x918c, 0x1d07, + 0x918d, 0x1d0a, + 0x918e, 0x4df6, + 0x9190, 0x1d09, + 0x9191, 0x1d0b, + 0x9192, 0x0f9c, + 0x9193, 0x4df8, + 0x9196, 0x2255, + 0x9197, 0x4dfb, + 0x919a, 0x0ad6, + 0x919b, 0x0c84, + 0x919c, 0x1e8f, + 0x919d, 0x4dfe, + 0x91a2, 0x1d0c, + 0x91a4, 0x4e03, + 0x91aa, 0x1d0e, + 0x91ab, 0x220c, + 0x91ac, 0x1fa4, + 0x91ad, 0x1d0f, + 0x91b0, 0x4e09, + 0x91b4, 0x1d13, + 0x91b5, 0x1d12, + 0x91b6, 0x4e0d, + 0x91ba, 0x1d14, + 0x91bb, 0x4e11, + 0x91c0, 0x209b, + 0x91c1, 0x21d8, + 0x91c2, 0x4e16, + 0x91c3, 0x25fa, + 0x91c4, 0x4e17, + 0x91c5, 0x25f9, + 0x91c6, 0x4e18, + 0x91c7, 0x0490, + 0x91c8, 0x4e19, + 0x91c9, 0x10b9, + 0x91ca, 0x0d64, + 0x91cb, 0x2134, + 0x91cc, 0x09da, + 0x91cd, 0x11d7, + 0x91ce, 0x1037, + 0x91cf, 0x0a08, + 0x91d0, 0x4e1a, + 0x91d1, 0x08c1, + 0x91d2, 0x24f3, + 0x91d5, 0x24f8, + 0x91d6, 0x4e1b, + 0x91d7, 0x24f7, + 0x91d8, 0x1ec8, + 0x91d9, 0x24f6, + 0x91da, 0x4e1c, + 0x91dc, 0x06a5, + 0x91dd, 0x2280, + 0x91de, 0x4e1e, + 0x91e3, 0x1ec5, + 0x91e4, 0x24fb, + 0x91e5, 0x4e23, + 0x91e7, 0x24fa, + 0x91e8, 0x4e25, + 0x91e9, 0x1eed, + 0x91ea, 0x4e26, + 0x91f5, 0x24fd, + 0x91f6, 0x4e31, + 0x91f7, 0x24f9, + 0x91f8, 0x4e32, + 0x91f9, 0x24fe, + 0x91fa, 0x20cd, + 0x91fb, 0x4e33, + 0x9200, 0x2508, + 0x9201, 0x2504, + 0x9202, 0x4e38, + 0x9204, 0x2506, + 0x9205, 0x4e3a, + 0x9208, 0x24ff, + 0x9209, 0x2090, + 0x920a, 0x4e3d, + 0x920d, 0x1edd, + 0x920e, 0x1f25, + 0x920f, 0x4e40, + 0x9210, 0x2503, + 0x9211, 0x2502, + 0x9212, 0x4e41, + 0x9214, 0x1e7a, + 0x9215, 0x20a6, + 0x9216, 0x4e43, + 0x921e, 0x1fd5, + 0x921f, 0x4e4b, + 0x9223, 0x1f11, + 0x9224, 0x4e4f, + 0x9225, 0x2507, + 0x9226, 0x2500, + 0x9227, 0x2505, + 0x9228, 0x4e50, + 0x922e, 0x2519, + 0x922f, 0x4e56, + 0x9230, 0x2515, + 0x9231, 0x4e57, + 0x9233, 0x250c, + 0x9234, 0x2031, + 0x9235, 0x4e59, + 0x9237, 0x250b, + 0x9238, 0x250f, + 0x9239, 0x251a, + 0x923a, 0x2509, + 0x923b, 0x4e5b, + 0x923d, 0x250e, + 0x923e, 0x2234, + 0x923f, 0x2513, + 0x9240, 0x1f80, + 0x9241, 0x4e5d, + 0x9245, 0x2501, + 0x9246, 0x4e61, + 0x9248, 0x2517, + 0x9249, 0x2516, + 0x924a, 0x4e63, + 0x924d, 0x2518, + 0x924e, 0x4e66, + 0x9251, 0x1e56, + 0x9252, 0x4e69, + 0x9255, 0x250d, + 0x9256, 0x4e6c, + 0x9257, 0x20d3, + 0x9258, 0x4e6d, + 0x925a, 0x207a, + 0x925b, 0x20ce, + 0x925c, 0x4e6f, + 0x925e, 0x2510, + 0x925f, 0x4e71, + 0x9262, 0x1e55, + 0x9263, 0x4e74, + 0x9266, 0x250a, + 0x9267, 0x4e77, + 0x926c, 0x2511, + 0x926e, 0x4e7c, + 0x9274, 0x086b, + 0x9275, 0x4e82, + 0x9278, 0x1faa, + 0x9279, 0x4e85, + 0x927a, 0x251e, + 0x927b, 0x1f1f, + 0x927c, 0x4e86, + 0x927f, 0x252d, + 0x9280, 0x221d, + 0x9281, 0x4e89, + 0x9283, 0x2532, + 0x9284, 0x4e8b, + 0x9285, 0x217b, + 0x9286, 0x4e8c, + 0x928e, 0x1d80, + 0x928f, 0x4e94, + 0x9291, 0x21af, + 0x9292, 0x4e96, + 0x9293, 0x252c, + 0x9294, 0x4e97, + 0x9296, 0x2528, + 0x9297, 0x4e99, + 0x9298, 0x208c, + 0x9299, 0x4e9a, + 0x929a, 0x252f, + 0x929b, 0x4e9b, + 0x929c, 0x21bc, + 0x929d, 0x4e9c, + 0x92a0, 0x251d, + 0x92a1, 0x4e9f, + 0x92a3, 0x2535, + 0x92a4, 0x4ea1, + 0x92a5, 0x220d, + 0x92a6, 0x2526, + 0x92a7, 0x4ea2, + 0x92a8, 0x2534, + 0x92a9, 0x252a, + 0x92aa, 0x251f, + 0x92ab, 0x2531, + 0x92ac, 0x251c, + 0x92ad, 0x4ea3, + 0x92ae, 0x1d81, + 0x92af, 0x4ea4, + 0x92b1, 0x2525, + 0x92b2, 0x4ea6, + 0x92b7, 0x21cd, + 0x92b8, 0x4eab, + 0x92b9, 0x21da, + 0x92ba, 0x4eac, + 0x92bb, 0x2172, + 0x92bc, 0x253e, + 0x92bd, 0x4ead, + 0x92c1, 0x204f, + 0x92c2, 0x4eb1, + 0x92c3, 0x2543, + 0x92c4, 0x4eb2, + 0x92c5, 0x21d7, + 0x92c6, 0x4eb3, + 0x92c7, 0x1e3c, + 0x92c8, 0x1d82, + 0x92c9, 0x4eb4, + 0x92cc, 0x2529, + 0x92cd, 0x4eb7, + 0x92cf, 0x2521, + 0x92d0, 0x4eb9, + 0x92d2, 0x1eff, + 0x92d3, 0x4ebb, + 0x92dd, 0x253f, + 0x92de, 0x4ec5, + 0x92df, 0x2544, + 0x92e0, 0x4ec6, + 0x92e3, 0x2523, + 0x92e4, 0x1e90, + 0x92e5, 0x253a, + 0x92e6, 0x2545, + 0x92e7, 0x4ec9, + 0x92e8, 0x253d, + 0x92e9, 0x4eca, + 0x92ea, 0x20c1, + 0x92eb, 0x4ecb, + 0x92ed, 0x2103, + 0x92ee, 0x2520, + 0x92ef, 0x253c, + 0x92f0, 0x253b, + 0x92f1, 0x2538, + 0x92f2, 0x4ecd, + 0x92f6, 0x2540, + 0x92f7, 0x4ed1, + 0x92f8, 0x1fcd, + 0x92f9, 0x4ed2, + 0x92fc, 0x1f18, + 0x92fd, 0x4ed5, + 0x9300, 0x4ed8, + 0x9301, 0x254b, + 0x9302, 0x4ed9, + 0x9306, 0x2547, + 0x9307, 0x254f, + 0x9309, 0x4edd, + 0x9310, 0x22b0, + 0x9311, 0x4ee4, + 0x9312, 0x2546, + 0x9313, 0x4ee5, + 0x9315, 0x254c, + 0x9316, 0x4ee7, + 0x9318, 0x1e9a, + 0x9319, 0x2552, + 0x931a, 0x2530, + 0x931b, 0x2549, + 0x931c, 0x4ee9, + 0x931f, 0x2551, + 0x9320, 0x1eca, + 0x9321, 0x4eec, + 0x9322, 0x20d2, + 0x9323, 0x4eed, + 0x9326, 0x1fb8, + 0x9327, 0x4ef0, + 0x9328, 0x2079, + 0x9329, 0x4ef1, + 0x932b, 0x21ab, + 0x932c, 0x4ef3, + 0x932e, 0x254d, + 0x932f, 0x1ea5, + 0x9330, 0x4ef5, + 0x9332, 0x204c, + 0x9333, 0x2080, + 0x9334, 0x4ef7, + 0x9336, 0x266d, + 0x9337, 0x4ef9, + 0x9338, 0x2537, + 0x9339, 0x4efa, + 0x933e, 0x1d83, + 0x933f, 0x4eff, + 0x9340, 0x254a, + 0x9341, 0x21b8, + 0x9342, 0x4f00, + 0x9343, 0x254e, + 0x9344, 0x4f01, + 0x9346, 0x24fc, + 0x9347, 0x2554, + 0x9348, 0x4f03, + 0x934b, 0x1f3c, + 0x934c, 0x4f06, + 0x934d, 0x1ed5, + 0x934e, 0x4f07, + 0x9354, 0x2556, + 0x9355, 0x4f0d, + 0x9358, 0x2268, + 0x9359, 0x4f10, + 0x935b, 0x1ed6, + 0x935c, 0x4f12, + 0x9364, 0x2557, + 0x9365, 0x2553, + 0x9366, 0x4f1a, + 0x9369, 0x2548, + 0x936a, 0x1d84, + 0x936b, 0x4f1d, + 0x936c, 0x20dc, + 0x936d, 0x4f1e, + 0x9370, 0x2559, + 0x9371, 0x4f21, + 0x9375, 0x1f97, + 0x9376, 0x2555, + 0x9377, 0x4f25, + 0x937a, 0x227d, + 0x937b, 0x4f28, + 0x937e, 0x257e, + 0x937f, 0x4f2b, + 0x9382, 0x207c, + 0x9383, 0x4f2e, + 0x9384, 0x255a, + 0x9385, 0x4f2f, + 0x9387, 0x255e, + 0x9388, 0x4f31, + 0x938a, 0x1e34, + 0x938b, 0x4f33, + 0x938f, 0x1d86, + 0x9390, 0x4f37, + 0x9396, 0x215e, + 0x9397, 0x4f3d, + 0x9398, 0x2560, + 0x9399, 0x4f3e, + 0x93a2, 0x21a2, + 0x93a3, 0x2354, + 0x93a4, 0x4f47, + 0x93a6, 0x2563, + 0x93a7, 0x2527, + 0x93a8, 0x4f49, + 0x93a9, 0x252e, + 0x93aa, 0x2558, + 0x93ab, 0x4f4a, + 0x93ac, 0x1f1b, + 0x93ad, 0x4f4b, + 0x93ae, 0x2283, + 0x93af, 0x4f4c, + 0x93b0, 0x2564, + 0x93b1, 0x4f4d, + 0x93b3, 0x20a0, + 0x93b4, 0x4f4f, + 0x93b5, 0x2565, + 0x93b6, 0x4f50, + 0x93b8, 0x2561, + 0x93b9, 0x4f52, + 0x93bf, 0x2562, + 0x93c0, 0x4f58, + 0x93c3, 0x256c, + 0x93c4, 0x4f5b, + 0x93c7, 0x256d, + 0x93c8, 0x2020, + 0x93c9, 0x4f5e, + 0x93ca, 0x1d85, + 0x93cb, 0x4f5f, + 0x93cc, 0x255f, + 0x93cd, 0x256a, + 0x93ce, 0x4f60, + 0x93d1, 0x256e, + 0x93d2, 0x4f63, + 0x93d6, 0x1e01, + 0x93d7, 0x2539, + 0x93d8, 0x255c, + 0x93d9, 0x4f67, + 0x93dc, 0x2568, + 0x93de, 0x256b, + 0x93df, 0x1e6f, + 0x93e0, 0x4f6a, + 0x93e1, 0x1fc4, + 0x93e2, 0x2567, + 0x93e3, 0x4f6b, + 0x93e4, 0x255b, + 0x93e5, 0x4f6c, + 0x93e8, 0x261d, + 0x93e9, 0x4f6f, + 0x93f5, 0x252b, + 0x93f6, 0x4f7b, + 0x93f7, 0x2571, + 0x93f8, 0x4f7c, + 0x93f9, 0x2577, + 0x93fa, 0x4f7d, + 0x9400, 0x4f83, + 0x9403, 0x2522, + 0x9404, 0x4f86, + 0x940b, 0x2533, + 0x940c, 0x4f8d, + 0x9410, 0x202a, + 0x9411, 0x4f91, + 0x9412, 0x2536, + 0x9413, 0x2573, + 0x9414, 0x256f, + 0x9415, 0x4f92, + 0x9418, 0x2293, + 0x9419, 0x2578, + 0x941a, 0x4f95, + 0x941d, 0x2570, + 0x941e, 0x4f98, + 0x9420, 0x2575, + 0x9421, 0x4f9a, + 0x9426, 0x2541, + 0x9428, 0x255d, + 0x9429, 0x4f9f, + 0x942e, 0x201a, + 0x942f, 0x4fa4, + 0x9432, 0x257a, + 0x9433, 0x2006, + 0x9434, 0x4fa7, + 0x9435, 0x2177, + 0x9436, 0x4fa8, + 0x9438, 0x251b, + 0x9439, 0x4faa, + 0x943a, 0x2524, + 0x943b, 0x4fab, + 0x943e, 0x1d87, + 0x943f, 0x257b, + 0x9440, 0x4fae, + 0x9444, 0x22a3, + 0x9445, 0x4fb2, + 0x944a, 0x2579, + 0x944b, 0x4fb7, + 0x944c, 0x2566, + 0x944d, 0x4fb8, + 0x9452, 0x1f93, + 0x9453, 0x4fbd, + 0x9454, 0x257c, + 0x9455, 0x4fbe, + 0x9460, 0x2514, + 0x9461, 0x4fc9, + 0x9463, 0x257d, + 0x9464, 0x4fcb, + 0x9465, 0x2572, + 0x9466, 0x4fcc, + 0x946b, 0x1d88, + 0x946c, 0x4fd1, + 0x946d, 0x2574, + 0x946e, 0x4fd2, + 0x9470, 0x224e, + 0x9471, 0x4fd4, + 0x9472, 0x21c6, + 0x9473, 0x4fd5, + 0x9477, 0x209f, + 0x9478, 0x4fd9, + 0x9479, 0x2576, + 0x947a, 0x4fda, + 0x947c, 0x2064, + 0x947d, 0x22bf, + 0x947e, 0x261c, + 0x947f, 0x225e, + 0x9480, 0x4fdc, + 0x9485, 0x1a8e, + 0x9488, 0x118c, + 0x9489, 0x05e3, + 0x948a, 0x1a92, + 0x948b, 0x1a91, + 0x948c, 0x1a93, + 0x948e, 0x0c22, + 0x948f, 0x1a95, + 0x9491, 0x4fe1, + 0x9492, 0x064d, + 0x9493, 0x05d7, + 0x9494, 0x1a97, + 0x9495, 0x1a99, + 0x9496, 0x4fe2, + 0x9497, 0x1a98, + 0x9498, 0x4fe3, + 0x9499, 0x06c1, + 0x949a, 0x1a9a, + 0x949d, 0x061a, + 0x949e, 0x04d3, + 0x949f, 0x11d2, + 0x94a0, 0x0b29, + 0x94a1, 0x041e, + 0x94a2, 0x06d1, + 0x94a3, 0x1a9d, + 0x94a5, 0x1102, + 0x94a6, 0x0c52, + 0x94a7, 0x092a, + 0x94a8, 0x0ee8, + 0x94a9, 0x070c, + 0x94aa, 0x1aa0, + 0x94ab, 0x1a9f, + 0x94ac, 0x1aa2, + 0x94ad, 0x1aa1, + 0x94ae, 0x0b66, + 0x94af, 0x1aa3, + 0x94b1, 0x0c2b, + 0x94b2, 0x1aa5, + 0x94b3, 0x0c2c, + 0x94b4, 0x1aa6, + 0x94b5, 0x046e, + 0x94b6, 0x1aa7, + 0x94bb, 0x1247, + 0x94bc, 0x1aac, + 0x94be, 0x084b, + 0x94bf, 0x1aae, + 0x94c0, 0x10b0, + 0x94c1, 0x0e4d, + 0x94c2, 0x0473, + 0x94c3, 0x0a2e, + 0x94c4, 0x1aaf, + 0x94c5, 0x0c23, + 0x94c6, 0x0ab2, + 0x94c7, 0x4fe4, + 0x94c8, 0x1ab0, + 0x94cf, 0x4fe5, + 0x94d0, 0x1ab7, + 0x94d3, 0x4fe6, + 0x94d5, 0x1aba, + 0x94d8, 0x1abe, + 0x94d9, 0x1abd, + 0x94da, 0x4fe8, + 0x94db, 0x1abf, + 0x94dc, 0x0e5e, + 0x94dd, 0x0a68, + 0x94de, 0x1ac0, + 0x94e1, 0x1142, + 0x94e2, 0x1ac3, + 0x94e3, 0x0f20, + 0x94e4, 0x1ac4, + 0x94e6, 0x4fe9, + 0x94e7, 0x1ac6, + 0x94e9, 0x1ac9, + 0x94ea, 0x1ac8, + 0x94eb, 0x1aca, + 0x94ec, 0x06f0, + 0x94ed, 0x0aff, + 0x94ee, 0x1acb, + 0x94f0, 0x0893, + 0x94f1, 0x1046, + 0x94f2, 0x04c0, + 0x94f3, 0x1acd, + 0x94f6, 0x107f, + 0x94f7, 0x1ad0, + 0x94f8, 0x11fc, + 0x94f9, 0x1ad1, + 0x94fa, 0x0beb, + 0x94fb, 0x4fea, + 0x94fc, 0x1ad2, + 0x94fe, 0x09fd, + 0x94ff, 0x1ad4, + 0x9500, 0x0f67, + 0x9501, 0x0ded, + 0x9502, 0x1ad6, + 0x9503, 0x1ad5, + 0x9504, 0x051f, + 0x9505, 0x0751, + 0x9506, 0x1ad7, + 0x9508, 0x0fad, + 0x9509, 0x1ad9, + 0x950b, 0x0683, + 0x950c, 0x0f8a, + 0x950d, 0x1adb, + 0x9510, 0x0ccc, + 0x9511, 0x0e33, + 0x9512, 0x1ade, + 0x9517, 0x1181, + 0x9518, 0x1ae3, + 0x9519, 0x0570, + 0x951a, 0x0aaf, + 0x951b, 0x1ae4, + 0x951c, 0x4feb, + 0x951d, 0x1ae5, + 0x9520, 0x4fec, + 0x9521, 0x0f0c, + 0x9522, 0x1ae8, + 0x9523, 0x0a87, + 0x9524, 0x053b, + 0x9525, 0x1213, + 0x9526, 0x08c6, + 0x9527, 0x4fed, + 0x9528, 0x0f34, + 0x9529, 0x1aeb, + 0x952a, 0x1ae9, + 0x952c, 0x1aec, + 0x952d, 0x05e6, + 0x952e, 0x086f, + 0x952f, 0x0911, + 0x9530, 0x0ad1, + 0x9531, 0x1aed, + 0x9533, 0x4fee, + 0x9534, 0x1aef, + 0x9535, 0x1af7, + 0x9536, 0x1af0, + 0x9539, 0x0c3f, + 0x953a, 0x1b19, + 0x953b, 0x060c, + 0x953c, 0x1af3, + 0x953d, 0x4fef, + 0x953e, 0x1af4, + 0x9540, 0x0605, + 0x9541, 0x0ac3, + 0x9542, 0x1af6, + 0x9543, 0x4ff0, + 0x9544, 0x1af8, + 0x9547, 0x1193, + 0x9548, 0x4ff1, + 0x9549, 0x1afb, + 0x954a, 0x0b5a, + 0x954b, 0x4ff2, + 0x954c, 0x1afc, + 0x954d, 0x0b5b, + 0x954e, 0x1afd, + 0x9550, 0x06df, + 0x9551, 0x0402, + 0x9552, 0x1aff, + 0x9555, 0x4ff3, + 0x9556, 0x1b02, + 0x955a, 0x4ff4, + 0x955b, 0x1b06, + 0x955c, 0x08e4, + 0x955d, 0x1b09, + 0x955e, 0x1b07, + 0x9560, 0x4ff5, + 0x9561, 0x1b0a, + 0x9563, 0x0a16, + 0x9564, 0x1b0c, + 0x956d, 0x09c3, + 0x956e, 0x4ff6, + 0x956f, 0x1b15, + 0x9570, 0x09f6, + 0x9571, 0x1b16, + 0x9574, 0x4ff7, + 0x9576, 0x0f4f, + 0x9577, 0x1e75, + 0x9578, 0x4ff9, + 0x957f, 0x04c9, + 0x9580, 0x207d, + 0x9581, 0x5000, + 0x9582, 0x23bf, + 0x9583, 0x2113, + 0x9584, 0x5001, + 0x9586, 0x23c0, + 0x9587, 0x5003, + 0x9589, 0x1e45, + 0x958a, 0x5005, + 0x958b, 0x1fd8, + 0x958c, 0x23c4, + 0x958d, 0x5006, + 0x958e, 0x23c2, + 0x958f, 0x2104, + 0x9590, 0x5007, + 0x9591, 0x21bd, + 0x9592, 0x5008, + 0x9593, 0x1f87, + 0x9594, 0x23c3, + 0x9595, 0x5009, + 0x9598, 0x2269, + 0x9599, 0x500c, + 0x95a1, 0x1f43, + 0x95a2, 0x5014, + 0x95a3, 0x1f1e, + 0x95a4, 0x2679, + 0x95a5, 0x1eeb, + 0x95a6, 0x5015, + 0x95a8, 0x1f35, + 0x95a9, 0x208a, + 0x95aa, 0x5017, + 0x95ab, 0x23c7, + 0x95ac, 0x23c9, + 0x95ad, 0x23c6, + 0x95ae, 0x5018, + 0x95b2, 0x224f, + 0x95b3, 0x501c, + 0x95b6, 0x23cb, + 0x95b7, 0x501f, + 0x95b9, 0x21f3, + 0x95ba, 0x5021, + 0x95bb, 0x21f7, + 0x95bc, 0x23cf, + 0x95bd, 0x23ce, + 0x95be, 0x23ca, + 0x95bf, 0x23cd, + 0x95c0, 0x5022, + 0x95c3, 0x23d0, + 0x95c4, 0x5025, + 0x95c6, 0x266c, + 0x95c7, 0x5027, + 0x95c8, 0x23c1, + 0x95c9, 0x5028, + 0x95ca, 0x1fee, + 0x95cb, 0x23d1, + 0x95cc, 0x1ff8, + 0x95cd, 0x5029, + 0x95d0, 0x23d3, + 0x95d1, 0x502c, + 0x95d4, 0x23d2, + 0x95d5, 0x23d4, + 0x95d6, 0x1e98, + 0x95d7, 0x502f, + 0x95dc, 0x1f2c, + 0x95dd, 0x5034, + 0x95de, 0x23d5, + 0x95df, 0x5035, + 0x95e1, 0x1e71, + 0x95e2, 0x2691, + 0x95e3, 0x5037, + 0x95e5, 0x23c5, + 0x95e6, 0x5039, + 0x95e8, 0x0aca, + 0x95e9, 0x1685, + 0x95ea, 0x0cfa, + 0x95eb, 0x1686, + 0x95ec, 0x503b, + 0x95ed, 0x043e, + 0x95ee, 0x0ed9, + 0x95ef, 0x0536, + 0x95f0, 0x0ccd, + 0x95f1, 0x1687, + 0x95f2, 0x0f3d, + 0x95f3, 0x1688, + 0x95f4, 0x0857, + 0x95f5, 0x1689, + 0x95f7, 0x0acb, + 0x95f8, 0x1143, + 0x95f9, 0x0b39, + 0x95fa, 0x0744, + 0x95fb, 0x0ed4, + 0x95fc, 0x168b, + 0x95fd, 0x0afb, + 0x95fe, 0x168c, + 0x95ff, 0x503c, + 0x9600, 0x0644, + 0x9601, 0x06ee, + 0x9602, 0x0789, + 0x9603, 0x168d, + 0x9605, 0x1107, + 0x9606, 0x168f, + 0x9607, 0x503d, + 0x9608, 0x1690, + 0x9609, 0x0ff4, + 0x960a, 0x1691, + 0x960e, 0x0fff, + 0x960f, 0x1695, + 0x9610, 0x04c2, + 0x9611, 0x09a6, + 0x9612, 0x1696, + 0x9613, 0x503e, + 0x9614, 0x0996, + 0x9615, 0x1697, + 0x9618, 0x503f, + 0x9619, 0x169a, + 0x961b, 0x5040, + 0x961c, 0x06b2, + 0x961d, 0x1354, + 0x961e, 0x5041, + 0x961f, 0x0612, + 0x9620, 0x5042, + 0x9621, 0x1356, + 0x9622, 0x1355, + 0x9623, 0x5043, + 0x962a, 0x1358, + 0x962b, 0x504a, + 0x962e, 0x0cc9, + 0x962f, 0x504d, + 0x9631, 0x1357, + 0x9632, 0x065d, + 0x9633, 0x101d, + 0x9634, 0x107c, + 0x9635, 0x1194, + 0x9636, 0x08a8, + 0x9637, 0x504f, + 0x963b, 0x1245, + 0x963c, 0x135a, + 0x963d, 0x1359, + 0x963e, 0x5053, + 0x963f, 0x03ad, + 0x9640, 0x0e84, + 0x9641, 0x5054, + 0x9642, 0x135b, + 0x9643, 0x5055, + 0x9644, 0x06b8, + 0x9645, 0x083d, + 0x9646, 0x0a64, + 0x9647, 0x0a4b, + 0x9648, 0x04e7, + 0x9649, 0x135c, + 0x964a, 0x5056, + 0x964b, 0x0a51, + 0x964c, 0x0b13, + 0x964d, 0x0886, + 0x964e, 0x5057, + 0x9650, 0x0f4b, + 0x9651, 0x5059, + 0x9654, 0x135d, + 0x9655, 0x0cfb, + 0x9656, 0x505c, + 0x9658, 0x231a, + 0x9659, 0x505e, + 0x965b, 0x0446, + 0x965c, 0x5060, + 0x965d, 0x2114, + 0x965e, 0x5061, + 0x965f, 0x135e, + 0x9660, 0x5062, + 0x9661, 0x05f7, + 0x9662, 0x10fd, + 0x9663, 0x2284, + 0x9664, 0x0522, + 0x9665, 0x5063, + 0x9667, 0x135f, + 0x9668, 0x110c, + 0x9669, 0x0f42, + 0x966a, 0x0ba4, + 0x966b, 0x5065, + 0x966c, 0x1360, + 0x966d, 0x5066, + 0x9670, 0x221c, + 0x9671, 0x5069, + 0x9672, 0x1361, + 0x9673, 0x1e7e, + 0x9674, 0x1362, + 0x9675, 0x0a33, + 0x9676, 0x0e28, + 0x9677, 0x0f4a, + 0x9678, 0x204d, + 0x9679, 0x506a, + 0x967d, 0x2201, + 0x967e, 0x506e, + 0x9685, 0x10cc, + 0x9686, 0x0a48, + 0x9687, 0x5075, + 0x9688, 0x1363, + 0x9689, 0x5076, + 0x968a, 0x1ed9, + 0x968b, 0x0dda, + 0x968c, 0x5077, + 0x968d, 0x1364, + 0x968e, 0x1fb2, + 0x968f, 0x0ddb, + 0x9690, 0x1085, + 0x9691, 0x5078, + 0x9694, 0x06ef, + 0x9695, 0x2252, + 0x9696, 0x507b, + 0x9697, 0x1365, + 0x9698, 0x03ba, + 0x9699, 0x0f23, + 0x969a, 0x507c, + 0x969b, 0x1f79, + 0x969c, 0x1170, + 0x969d, 0x507d, + 0x96a7, 0x0de2, + 0x96a8, 0x2157, + 0x96a9, 0x5087, + 0x96aa, 0x21bf, + 0x96ab, 0x5088, + 0x96b0, 0x1366, + 0x96b1, 0x221f, + 0x96b2, 0x508d, + 0x96b3, 0x1684, + 0x96b4, 0x203d, + 0x96b5, 0x508e, + 0x96b6, 0x09ee, + 0x96b7, 0x508f, + 0x96b8, 0x2015, + 0x96b9, 0x1d79, + 0x96ba, 0x5090, + 0x96bb, 0x26a5, + 0x96bc, 0x1d7a, + 0x96be, 0x0b34, + 0x96bf, 0x5091, + 0x96c0, 0x0c93, + 0x96c1, 0x100c, + 0x96c2, 0x5092, + 0x96c4, 0x0fa6, + 0x96c5, 0x0fee, + 0x96c6, 0x0822, + 0x96c7, 0x0726, + 0x96c8, 0x5094, + 0x96c9, 0x1b1c, + 0x96ca, 0x5095, + 0x96cc, 0x0549, + 0x96cd, 0x109f, + 0x96ce, 0x1d7c, + 0x96cf, 0x0520, + 0x96d0, 0x5097, + 0x96d2, 0x1d7d, + 0x96d3, 0x5099, + 0x96d5, 0x05d2, + 0x96d6, 0x2156, + 0x96d7, 0x509b, + 0x96d9, 0x2144, + 0x96da, 0x509d, + 0x96db, 0x1e91, + 0x96dc, 0x2257, + 0x96dd, 0x509e, + 0x96e0, 0x1d7f, + 0x96e1, 0x50a1, + 0x96e2, 0x200a, + 0x96e3, 0x2092, + 0x96e4, 0x50a2, + 0x96e8, 0x10cf, + 0x96e9, 0x1d61, + 0x96ea, 0x0fd2, + 0x96eb, 0x50a6, + 0x96ef, 0x1d63, + 0x96f0, 0x50aa, + 0x96f2, 0x2250, + 0x96f3, 0x1d62, + 0x96f4, 0x50ac, + 0x96f6, 0x0a2c, + 0x96f7, 0x09c2, + 0x96f8, 0x50ae, + 0x96f9, 0x040b, + 0x96fa, 0x50af, + 0x96fb, 0x1ec3, + 0x96fc, 0x50b0, + 0x96fe, 0x0efc, + 0x96ff, 0x50b2, + 0x9700, 0x0fb3, + 0x9701, 0x1d65, + 0x9702, 0x50b3, + 0x9704, 0x0f63, + 0x9705, 0x50b5, + 0x9706, 0x1d64, + 0x9707, 0x1191, + 0x9708, 0x1d66, + 0x9709, 0x0abe, + 0x970a, 0x50b6, + 0x970d, 0x0809, + 0x970e, 0x1d68, + 0x970f, 0x1d67, + 0x9710, 0x50b9, + 0x9713, 0x0b41, + 0x9714, 0x50bc, + 0x9716, 0x0a21, + 0x9717, 0x50be, + 0x971c, 0x0d9f, + 0x971d, 0x50c3, + 0x971e, 0x0f29, + 0x971f, 0x50c4, + 0x9727, 0x21a8, + 0x9728, 0x50cc, + 0x972a, 0x1d69, + 0x972b, 0x50ce, + 0x972d, 0x1d6a, + 0x972e, 0x50d0, + 0x9730, 0x1d6b, + 0x9731, 0x50d2, + 0x9732, 0x0a5d, + 0x9733, 0x50d3, + 0x9738, 0x03df, + 0x9739, 0x0bba, + 0x973a, 0x50d8, + 0x973d, 0x260d, + 0x973e, 0x1d6c, + 0x973f, 0x50db, + 0x9742, 0x260c, + 0x9743, 0x50de, + 0x9744, 0x260e, + 0x9745, 0x50df, + 0x9748, 0x2032, + 0x9749, 0x50e2, + 0x9752, 0x0c5d, + 0x9753, 0x1d60, + 0x9754, 0x50eb, + 0x9756, 0x08e7, + 0x9757, 0x50ed, + 0x9759, 0x08e1, + 0x975a, 0x260b, + 0x975b, 0x05c6, + 0x975c, 0x50ef, + 0x975e, 0x0664, + 0x975f, 0x50f1, + 0x9760, 0x094c, + 0x9761, 0x0ad7, + 0x9762, 0x0aeb, + 0x9763, 0x50f2, + 0x9765, 0x1282, + 0x9766, 0x50f4, + 0x9768, 0x22c3, + 0x9769, 0x06ea, + 0x976a, 0x50f6, + 0x9773, 0x08ca, + 0x9774, 0x0fce, + 0x9775, 0x50ff, + 0x9776, 0x03db, + 0x9777, 0x5100, + 0x977c, 0x1dc8, + 0x977d, 0x5105, + 0x9785, 0x1dc9, + 0x9786, 0x510d, + 0x978b, 0x0f77, + 0x978c, 0x5112, + 0x978d, 0x03bb, + 0x978e, 0x5113, + 0x978f, 0x1f23, + 0x9790, 0x5114, + 0x9791, 0x1dca, + 0x9793, 0x5115, + 0x9794, 0x1dcc, + 0x9795, 0x5116, + 0x9798, 0x0c47, + 0x9799, 0x5119, + 0x97a0, 0x08fe, + 0x97a1, 0x5120, + 0x97a3, 0x1dcf, + 0x97a4, 0x5122, + 0x97a6, 0x2695, + 0x97a7, 0x5124, + 0x97ab, 0x1dce, + 0x97ac, 0x5128, + 0x97ad, 0x0447, + 0x97ae, 0x5129, + 0x97af, 0x1dcd, + 0x97b0, 0x512a, + 0x97b2, 0x1dd0, + 0x97b3, 0x512c, + 0x97b4, 0x1dd1, + 0x97b5, 0x512d, + 0x97bd, 0x265e, + 0x97be, 0x5135, + 0x97c3, 0x265d, + 0x97c4, 0x513a, + 0x97c6, 0x2692, + 0x97c7, 0x513c, + 0x97c9, 0x265f, + 0x97ca, 0x513e, + 0x97cb, 0x218d, + 0x97cc, 0x20fd, + 0x97cd, 0x513f, + 0x97d3, 0x1f40, + 0x97d4, 0x5145, + 0x97d9, 0x2465, + 0x97da, 0x514a, + 0x97dc, 0x2467, + 0x97dd, 0x514c, + 0x97de, 0x2466, + 0x97df, 0x514d, + 0x97e6, 0x0eb3, + 0x97e7, 0x0ca8, + 0x97e8, 0x5154, + 0x97e9, 0x0762, + 0x97ea, 0x184e, + 0x97ed, 0x08f1, + 0x97ee, 0x5155, + 0x97f3, 0x107b, + 0x97f4, 0x515a, + 0x97f5, 0x1112, + 0x97f6, 0x0d11, + 0x97f7, 0x515b, + 0x97ff, 0x21c9, + 0x9800, 0x5163, + 0x9801, 0x2209, + 0x9802, 0x1ec9, + 0x9803, 0x20e9, + 0x9804, 0x5164, + 0x9805, 0x21ca, + 0x9806, 0x2146, + 0x9807, 0x25c5, + 0x9808, 0x21dc, + 0x9809, 0x5165, + 0x980a, 0x245e, + 0x980b, 0x5166, + 0x980c, 0x214f, + 0x980d, 0x5167, + 0x980e, 0x25c6, + 0x9810, 0x2241, + 0x9811, 0x218a, + 0x9812, 0x1e2f, + 0x9813, 0x1edc, + 0x9814, 0x5168, + 0x9817, 0x20bf, + 0x9818, 0x2034, + 0x9819, 0x516b, + 0x981c, 0x25c9, + 0x981d, 0x516e, + 0x9821, 0x25c8, + 0x9822, 0x5172, + 0x9824, 0x220e, + 0x9825, 0x5174, + 0x9826, 0x25cb, + 0x9827, 0x5175, + 0x982d, 0x217d, + 0x982e, 0x517b, + 0x9830, 0x1f7e, + 0x9831, 0x517d, + 0x9837, 0x25cc, + 0x9838, 0x1fc3, + 0x9839, 0x5183, + 0x983b, 0x20b9, + 0x983c, 0x5185, + 0x983d, 0x2181, + 0x983e, 0x5186, + 0x9846, 0x1fda, + 0x9847, 0x518e, + 0x984c, 0x2173, + 0x984d, 0x1ee1, + 0x984e, 0x25cd, + 0x984f, 0x5193, + 0x9853, 0x25ce, + 0x9854, 0x21f6, + 0x9855, 0x5197, + 0x9858, 0x224b, + 0x9859, 0x25d1, + 0x985a, 0x519a, + 0x985b, 0x1ec0, + 0x985c, 0x519b, + 0x985e, 0x2008, + 0x985f, 0x519d, + 0x9862, 0x25d0, + 0x9863, 0x51a0, + 0x9865, 0x25d2, + 0x9866, 0x51a2, + 0x9867, 0x1f2a, + 0x9868, 0x51a3, + 0x986b, 0x1e72, + 0x986c, 0x25d3, + 0x986d, 0x51a6, + 0x986f, 0x21be, + 0x9870, 0x25d4, + 0x9871, 0x2044, + 0x9872, 0x51a8, + 0x9873, 0x25cf, + 0x9874, 0x20f3, + 0x9875, 0x103a, + 0x9876, 0x05e4, + 0x9877, 0x0c67, + 0x9878, 0x1be0, + 0x9879, 0x0f5b, + 0x987a, 0x0da8, + 0x987b, 0x0fb6, + 0x987c, 0x1827, + 0x987d, 0x0e98, + 0x987e, 0x0724, + 0x987f, 0x0618, + 0x9880, 0x1be1, + 0x9881, 0x03ef, + 0x9882, 0x0dc1, + 0x9883, 0x1be2, + 0x9884, 0x10e7, + 0x9885, 0x0a54, + 0x9886, 0x0a35, + 0x9887, 0x0be3, + 0x9888, 0x08e0, + 0x9889, 0x1be3, + 0x988a, 0x0848, + 0x988b, 0x51a9, + 0x988c, 0x1be4, + 0x988e, 0x51aa, + 0x988f, 0x1be6, + 0x9890, 0x104a, + 0x9891, 0x0bd4, + 0x9892, 0x51ab, + 0x9893, 0x0e78, + 0x9894, 0x1be7, + 0x9895, 0x51ac, + 0x9896, 0x1096, + 0x9897, 0x0952, + 0x9898, 0x0e35, + 0x9899, 0x51ad, + 0x989a, 0x1be8, + 0x989c, 0x0ffe, + 0x989d, 0x062d, + 0x989e, 0x1bea, + 0x98a0, 0x05c0, + 0x98a1, 0x1bec, + 0x98a3, 0x51ae, + 0x98a4, 0x04c3, + 0x98a5, 0x1bee, + 0x98a7, 0x0c82, + 0x98a8, 0x1f00, + 0x98a9, 0x51af, + 0x98ae, 0x24cc, + 0x98b0, 0x51b4, + 0x98b1, 0x2698, + 0x98b2, 0x51b5, + 0x98b3, 0x2678, + 0x98b4, 0x51b6, + 0x98b6, 0x24ce, + 0x98b7, 0x51b8, + 0x98bc, 0x24cf, + 0x98bd, 0x51bd, + 0x98c4, 0x20b8, + 0x98c5, 0x51c4, + 0x98c6, 0x24d0, + 0x98c7, 0x51c5, + 0x98c8, 0x24d1, + 0x98c9, 0x51c6, + 0x98ce, 0x0684, + 0x98cf, 0x51cb, + 0x98d1, 0x19b7, + 0x98d4, 0x51cd, + 0x98d5, 0x19ba, + 0x98d6, 0x51ce, + 0x98d8, 0x0bcd, + 0x98d9, 0x19bb, + 0x98db, 0x1ef4, + 0x98dc, 0x51d0, + 0x98de, 0x0666, + 0x98df, 0x0d4a, + 0x98e0, 0x239b, + 0x98e1, 0x51d2, + 0x98e2, 0x267e, + 0x98e3, 0x51d3, + 0x98e7, 0x161a, + 0x98e8, 0x1de7, + 0x98e9, 0x239d, + 0x98ea, 0x239f, + 0x98ec, 0x51d7, + 0x98ed, 0x23a1, + 0x98ee, 0x51d8, + 0x98ef, 0x1ef1, + 0x98f0, 0x51d9, + 0x98f2, 0x221e, + 0x98f3, 0x51db, + 0x98f4, 0x23a2, + 0x98f5, 0x51dc, + 0x98fc, 0x214b, + 0x98fd, 0x1e36, + 0x98fe, 0x2135, + 0x98ff, 0x51e3, + 0x9900, 0x51e4, + 0x9903, 0x1fad, + 0x9904, 0x51e7, + 0x9905, 0x1e53, + 0x9906, 0x51e8, + 0x9909, 0x23a3, + 0x990a, 0x2203, + 0x990b, 0x51eb, + 0x990c, 0x1ee7, + 0x990d, 0x1de8, + 0x990e, 0x51ec, + 0x9910, 0x0494, + 0x9911, 0x23a4, + 0x9912, 0x2097, + 0x9913, 0x1ee4, + 0x9914, 0x51ee, + 0x9918, 0x2238, + 0x9919, 0x51f2, + 0x991b, 0x23a5, + 0x991c, 0x51f4, + 0x991e, 0x1f9a, + 0x991f, 0x51f6, + 0x9921, 0x21c3, + 0x9922, 0x51f8, + 0x9928, 0x1f2e, + 0x9929, 0x51fe, + 0x992e, 0x1de9, + 0x992f, 0x5203, + 0x9933, 0x239c, + 0x9934, 0x5207, + 0x9937, 0x23a6, + 0x9938, 0x520a, + 0x993c, 0x239e, + 0x993d, 0x520e, + 0x993e, 0x2035, + 0x993f, 0x23a7, + 0x9940, 0x520f, + 0x9943, 0x23a8, + 0x9944, 0x5212, + 0x9945, 0x2075, + 0x9946, 0x5213, + 0x9948, 0x23a9, + 0x994b, 0x1feb, + 0x994c, 0x23ac, + 0x994d, 0x5215, + 0x9951, 0x1f6a, + 0x9952, 0x20f9, + 0x9953, 0x5219, + 0x9954, 0x1deb, + 0x9955, 0x1dea, + 0x9956, 0x521a, + 0x9957, 0x2666, + 0x9958, 0x521b, + 0x995c, 0x2667, + 0x995d, 0x521f, + 0x995e, 0x1e6c, + 0x995f, 0x5220, + 0x9962, 0x23ad, + 0x9963, 0x161d, + 0x9964, 0x5223, + 0x9965, 0x0815, + 0x9966, 0x5224, + 0x9967, 0x161e, + 0x996d, 0x0656, + 0x996e, 0x1082, + 0x996f, 0x0875, + 0x9970, 0x0d65, + 0x9971, 0x040e, + 0x9972, 0x0dbc, + 0x9973, 0x5225, + 0x9974, 0x1624, + 0x9975, 0x063b, + 0x9976, 0x0c9f, + 0x9977, 0x1625, + 0x9978, 0x5226, + 0x997a, 0x0899, + 0x997b, 0x5228, + 0x997c, 0x0466, + 0x997d, 0x1626, + 0x997e, 0x5229, + 0x997f, 0x0635, + 0x9980, 0x1627, + 0x9981, 0x0b3c, + 0x9982, 0x522a, + 0x9984, 0x1628, + 0x9985, 0x0f47, + 0x9986, 0x0736, + 0x9987, 0x1629, + 0x9988, 0x098c, + 0x9989, 0x522c, + 0x998a, 0x162a, + 0x998b, 0x04bd, + 0x998c, 0x522d, + 0x998d, 0x162b, + 0x998e, 0x522e, + 0x998f, 0x0a3c, + 0x9990, 0x162c, + 0x9992, 0x0a9f, + 0x9993, 0x162e, + 0x9996, 0x0d6e, + 0x9997, 0x126e, + 0x9998, 0x12f9, + 0x9999, 0x0f50, + 0x999a, 0x522f, + 0x99a5, 0x1b2b, + 0x99a6, 0x523a, + 0x99a8, 0x13de, + 0x99a9, 0x523c, + 0x99ac, 0x206d, + 0x99ad, 0x2242, + 0x99ae, 0x1f02, + 0x99af, 0x523f, + 0x99b1, 0x2183, + 0x99b2, 0x5241, + 0x99b3, 0x1e85, + 0x99b4, 0x21e9, + 0x99b5, 0x5242, + 0x99c1, 0x1e57, + 0x99c2, 0x524e, + 0x99d0, 0x22a5, + 0x99d1, 0x2407, + 0x99d2, 0x1fca, + 0x99d3, 0x525c, + 0x99d4, 0x2402, + 0x99d5, 0x1f82, + 0x99d6, 0x525d, + 0x99d8, 0x2408, + 0x99d9, 0x2404, + 0x99da, 0x525f, + 0x99db, 0x2131, + 0x99dc, 0x5260, + 0x99dd, 0x2184, + 0x99de, 0x5261, + 0x99df, 0x2403, + 0x99e0, 0x5262, + 0x99e1, 0x206e, + 0x99e2, 0x240b, + 0x99e3, 0x5263, + 0x99ed, 0x1f3f, + 0x99ee, 0x526d, + 0x99f1, 0x2067, + 0x99f2, 0x5270, + 0x99ff, 0x1fd7, + 0x9a00, 0x527d, + 0x9a01, 0x1e83, + 0x9a02, 0x527e, + 0x9a05, 0x240f, + 0x9a06, 0x5281, + 0x9a0d, 0x240e, + 0x9a0e, 0x20c7, + 0x9a0f, 0x240d, + 0x9a10, 0x5288, + 0x9a16, 0x2412, + 0x9a17, 0x528e, + 0x9a19, 0x20b7, + 0x9a1a, 0x5290, + 0x9a2b, 0x23f0, + 0x9a2c, 0x52a1, + 0x9a2d, 0x2411, + 0x9a2e, 0x2414, + 0x9a2f, 0x52a2, + 0x9a30, 0x2170, + 0x9a31, 0x52a3, + 0x9a36, 0x2405, + 0x9a37, 0x210c, + 0x9a38, 0x2415, + 0x9a39, 0x52a8, + 0x9a3e, 0x2066, + 0x9a3f, 0x52ad, + 0x9a40, 0x2352, + 0x9a41, 0x2413, + 0x9a42, 0x2410, + 0x9a43, 0x2416, + 0x9a45, 0x20f1, + 0x9a46, 0x52ae, + 0x9a4a, 0x240a, + 0x9a4b, 0x52b2, + 0x9a4d, 0x2409, + 0x9a4e, 0x52b4, + 0x9a4f, 0x2418, + 0x9a50, 0x52b5, + 0x9a55, 0x1fa7, + 0x9a56, 0x52ba, + 0x9a57, 0x21fc, + 0x9a58, 0x52bb, + 0x9a5a, 0x1fc1, + 0x9a5b, 0x2406, + 0x9a5c, 0x52bd, + 0x9a5f, 0x229c, + 0x9a60, 0x52c0, + 0x9a62, 0x204e, + 0x9a63, 0x52c2, + 0x9a64, 0x241a, + 0x9a65, 0x2419, + 0x9a66, 0x52c3, + 0x9a6a, 0x240c, + 0x9a6b, 0x52c7, + 0x9a6c, 0x0a94, + 0x9a6d, 0x10e9, + 0x9a6e, 0x0e85, + 0x9a6f, 0x0fda, + 0x9a70, 0x0500, + 0x9a71, 0x0c7a, + 0x9a72, 0x52c8, + 0x9a73, 0x047c, + 0x9a74, 0x0a66, + 0x9a75, 0x17ba, + 0x9a76, 0x0d52, + 0x9a77, 0x17bb, + 0x9a79, 0x0903, + 0x9a7a, 0x17bd, + 0x9a7b, 0x1201, + 0x9a7c, 0x0e86, + 0x9a7d, 0x17bf, + 0x9a7e, 0x0850, + 0x9a7f, 0x17be, + 0x9a80, 0x17c0, + 0x9a82, 0x0a95, + 0x9a83, 0x52c9, + 0x9a84, 0x088f, + 0x9a85, 0x17c2, + 0x9a86, 0x0a8d, + 0x9a87, 0x075e, + 0x9a88, 0x17c3, + 0x9a89, 0x52ca, + 0x9a8a, 0x17c4, + 0x9a8b, 0x04f7, + 0x9a8c, 0x1012, + 0x9a8d, 0x52cb, + 0x9a8f, 0x0932, + 0x9a90, 0x17c5, + 0x9a91, 0x0c0e, + 0x9a92, 0x17c6, + 0x9a94, 0x52cd, + 0x9a96, 0x17c8, + 0x9a97, 0x0bcc, + 0x9a98, 0x17c9, + 0x9a99, 0x52cf, + 0x9a9a, 0x0ce0, + 0x9a9b, 0x17ca, + 0x9a9e, 0x1735, + 0x9a9f, 0x17cd, + 0x9aa1, 0x0a89, + 0x9aa2, 0x17cf, + 0x9aa4, 0x11e7, + 0x9aa5, 0x17d1, + 0x9aa6, 0x52d0, + 0x9aa7, 0x17d2, + 0x9aa8, 0x0720, + 0x9aa9, 0x52d1, + 0x9aaf, 0x1e29, + 0x9ab0, 0x1dd3, + 0x9ab1, 0x1dd2, + 0x9ab2, 0x52d7, + 0x9ab6, 0x1dd6, + 0x9ab7, 0x1dd4, + 0x9ab8, 0x0758, + 0x9ab9, 0x52db, + 0x9aba, 0x1dd7, + 0x9abb, 0x52dc, + 0x9abc, 0x1dd8, + 0x9abd, 0x52dd, + 0x9ac0, 0x1dda, + 0x9ac1, 0x1dd9, + 0x9ac2, 0x1ddc, + 0x9ac3, 0x52e0, + 0x9ac5, 0x1ddb, + 0x9ac6, 0x52e2, + 0x9acb, 0x1ddd, + 0x9acd, 0x52e7, + 0x9acf, 0x2661, + 0x9ad0, 0x52e9, + 0x9ad1, 0x1ddf, + 0x9ad2, 0x26a4, + 0x9ad3, 0x0ddd, + 0x9ad4, 0x2174, + 0x9ad5, 0x2663, + 0x9ad6, 0x2662, + 0x9ad7, 0x52ea, + 0x9ad8, 0x06da, + 0x9ad9, 0x52eb, + 0x9adf, 0x1dec, + 0x9ae0, 0x52f1, + 0x9ae1, 0x1ded, + 0x9ae2, 0x52f2, + 0x9ae6, 0x1dee, + 0x9ae7, 0x52f6, + 0x9aeb, 0x1df0, + 0x9aec, 0x52fa, + 0x9aed, 0x1df2, + 0x9aee, 0x2675, + 0x9aef, 0x1def, + 0x9af0, 0x52fb, + 0x9af9, 0x1df3, + 0x9afa, 0x5304, + 0x9afb, 0x1df1, + 0x9afc, 0x5305, + 0x9b00, 0x5309, + 0x9b03, 0x1234, + 0x9b04, 0x530c, + 0x9b06, 0x214c, + 0x9b07, 0x530e, + 0x9b08, 0x1df4, + 0x9b09, 0x530f, + 0x9b0d, 0x267a, + 0x9b0e, 0x5313, + 0x9b0f, 0x1df5, + 0x9b10, 0x5314, + 0x9b13, 0x1df6, + 0x9b14, 0x5317, + 0x9b1a, 0x26a0, + 0x9b1b, 0x531d, + 0x9b1f, 0x1df7, + 0x9b20, 0x5321, + 0x9b22, 0x2668, + 0x9b23, 0x1df8, + 0x9b24, 0x5323, + 0x9b25, 0x1ed0, + 0x9b26, 0x5324, + 0x9b27, 0x2096, + 0x9b28, 0x5325, + 0x9b29, 0x23cc, + 0x9b2a, 0x5326, + 0x9b2e, 0x23c8, + 0x9b2f, 0x139b, + 0x9b30, 0x532a, + 0x9b31, 0x223e, + 0x9b32, 0x1260, + 0x9b33, 0x532b, + 0x9b3b, 0x1773, + 0x9b3c, 0x0746, + 0x9b3d, 0x5333, + 0x9b41, 0x098a, + 0x9b42, 0x07ff, + 0x9b43, 0x1de1, + 0x9b44, 0x0be6, + 0x9b45, 0x1de0, + 0x9b46, 0x5337, + 0x9b47, 0x1de2, + 0x9b48, 0x1de4, + 0x9b49, 0x1de3, + 0x9b4a, 0x5338, + 0x9b4d, 0x1de5, + 0x9b4e, 0x2665, + 0x9b4f, 0x0ec9, + 0x9b50, 0x533b, + 0x9b51, 0x1de6, + 0x9b52, 0x533c, + 0x9b54, 0x0b0a, + 0x9b55, 0x533e, + 0x9b58, 0x2664, + 0x9b59, 0x5341, + 0x9b5a, 0x2239, + 0x9b5b, 0x5342, + 0x9b6f, 0x204a, + 0x9b70, 0x5356, + 0x9b74, 0x261f, + 0x9b75, 0x535a, + 0x9b77, 0x261e, + 0x9b78, 0x535c, + 0x9b81, 0x2620, + 0x9b82, 0x5365, + 0x9b83, 0x2621, + 0x9b84, 0x5366, + 0x9b8e, 0x2622, + 0x9b8f, 0x5370, + 0x9b90, 0x2627, + 0x9b91, 0x1e39, + 0x9b92, 0x2625, + 0x9b93, 0x5371, + 0x9b9a, 0x2629, + 0x9b9b, 0x5378, + 0x9b9d, 0x262e, + 0x9b9e, 0x262b, + 0x9b9f, 0x537a, + 0x9baa, 0x262a, + 0x9bab, 0x262d, + 0x9bac, 0x5385, + 0x9bad, 0x2628, + 0x9bae, 0x21b9, + 0x9baf, 0x5386, + 0x9bc0, 0x2636, + 0x9bc1, 0x2630, + 0x9bc2, 0x5397, + 0x9bc7, 0x2638, + 0x9bc8, 0x539c, + 0x9bc9, 0x200d, + 0x9bca, 0x2637, + 0x9bcb, 0x539d, + 0x9bd4, 0x2645, + 0x9bd5, 0x53a6, + 0x9bd6, 0x263a, + 0x9bd7, 0x53a7, + 0x9bdb, 0x2643, + 0x9bdc, 0x53ab, + 0x9bdd, 0x2640, + 0x9bde, 0x53ac, + 0x9be1, 0x263d, + 0x9be2, 0x2641, + 0x9be3, 0x53af, + 0x9be4, 0x263e, + 0x9be5, 0x53b0, + 0x9be7, 0x263f, + 0x9be8, 0x1fc0, + 0x9be9, 0x53b2, + 0x9bea, 0x263b, + 0x9bec, 0x53b3, + 0x9bf0, 0x2642, + 0x9bf1, 0x53b7, + 0x9bf4, 0x2644, + 0x9bf5, 0x53ba, + 0x9bfd, 0x2639, + 0x9bfe, 0x53c2, + 0x9bff, 0x264c, + 0x9c00, 0x53c3, + 0x9c08, 0x2647, + 0x9c09, 0x264b, + 0x9c0a, 0x53cb, + 0x9c0d, 0x2649, + 0x9c0e, 0x53ce, + 0x9c10, 0x2648, + 0x9c11, 0x53d0, + 0x9c12, 0x264a, + 0x9c13, 0x2108, + 0x9c14, 0x53d1, + 0x9c20, 0x264d, + 0x9c21, 0x53dd, + 0x9c23, 0x2634, + 0x9c24, 0x53df, + 0x9c25, 0x2651, + 0x9c26, 0x53e0, + 0x9c28, 0x2650, + 0x9c29, 0x2652, + 0x9c2a, 0x53e2, + 0x9c2d, 0x264f, + 0x9c2e, 0x53e5, + 0x9c31, 0x2632, + 0x9c32, 0x264e, + 0x9c33, 0x2653, + 0x9c34, 0x53e8, + 0x9c35, 0x2657, + 0x9c36, 0x53e9, + 0x9c37, 0x2635, + 0x9c38, 0x53ea, + 0x9c39, 0x2633, + 0x9c3a, 0x53eb, + 0x9c3b, 0x2656, + 0x9c3c, 0x53ec, + 0x9c3e, 0x2654, + 0x9c3f, 0x53ee, + 0x9c45, 0x2658, + 0x9c46, 0x53f4, + 0x9c48, 0x2655, + 0x9c49, 0x1e4d, + 0x9c4a, 0x53f6, + 0x9c52, 0x265b, + 0x9c53, 0x53fe, + 0x9c54, 0x265a, + 0x9c55, 0x53ff, + 0x9c56, 0x2659, + 0x9c57, 0x202e, + 0x9c58, 0x262f, + 0x9c59, 0x5400, + 0x9c5d, 0x2646, + 0x9c5e, 0x5404, + 0x9c5f, 0x2626, + 0x9c60, 0x5405, + 0x9c67, 0x265c, + 0x9c68, 0x540c, + 0x9c6d, 0x262c, + 0x9c6e, 0x5411, + 0x9c78, 0x2623, + 0x9c79, 0x541b, + 0x9c7a, 0x2631, + 0x9c7b, 0x541c, + 0x9c7c, 0x10c8, + 0x9c7d, 0x541d, + 0x9c7f, 0x1d89, + 0x9c80, 0x541f, + 0x9c81, 0x0a5a, + 0x9c82, 0x1d8a, + 0x9c83, 0x5420, + 0x9c85, 0x1d8b, + 0x9c89, 0x5422, + 0x9c8b, 0x1d90, + 0x9c8c, 0x5424, + 0x9c8d, 0x0414, + 0x9c8e, 0x1d91, + 0x9c8f, 0x5425, + 0x9c90, 0x1d92, + 0x9c93, 0x5426, + 0x9c94, 0x1d95, + 0x9c96, 0x5427, + 0x9c9a, 0x1d97, + 0x9c9c, 0x0f37, + 0x9c9d, 0x542b, + 0x9c9e, 0x1d99, + 0x9ca4, 0x09db, + 0x9ca5, 0x1d9f, + 0x9caa, 0x542c, + 0x9cab, 0x1da4, + 0x9cac, 0x542d, + 0x9cad, 0x1da5, + 0x9caf, 0x542e, + 0x9cb0, 0x1da7, + 0x9cb8, 0x08d7, + 0x9cb9, 0x542f, + 0x9cba, 0x1daf, + 0x9cbe, 0x5430, + 0x9cc3, 0x0cd5, + 0x9cc4, 0x1db3, + 0x9cc8, 0x5435, + 0x9cca, 0x1db7, + 0x9cd1, 0x5437, + 0x9cd3, 0x1dbe, + 0x9cd6, 0x0457, + 0x9cd7, 0x1dc1, + 0x9cda, 0x5439, + 0x9cdc, 0x1dc4, + 0x9cde, 0x0a24, + 0x9cdf, 0x1dc6, + 0x9ce0, 0x543b, + 0x9ce2, 0x1dc7, + 0x9ce3, 0x543d, + 0x9ce5, 0x209c, + 0x9ce6, 0x543f, + 0x9ce9, 0x2580, + 0x9cea, 0x5442, + 0x9cec, 0x22dc, + 0x9ced, 0x5444, + 0x9cf3, 0x1f05, + 0x9cf4, 0x208b, + 0x9cf5, 0x544a, + 0x9cf6, 0x2581, + 0x9cf7, 0x544b, + 0x9d00, 0x5454, + 0x9d06, 0x2583, + 0x9d07, 0x2582, + 0x9d08, 0x545a, + 0x9d09, 0x21ee, + 0x9d0a, 0x545b, + 0x9d15, 0x2182, + 0x9d16, 0x5466, + 0x9d1b, 0x2243, + 0x9d1c, 0x546b, + 0x9d1d, 0x2587, + 0x9d1e, 0x546c, + 0x9d1f, 0x2588, + 0x9d20, 0x546d, + 0x9d23, 0x2584, + 0x9d24, 0x5470, + 0x9d26, 0x21fd, + 0x9d27, 0x5472, + 0x9d28, 0x21ef, + 0x9d29, 0x5473, + 0x9d2f, 0x258a, + 0x9d30, 0x258c, + 0x9d31, 0x5479, + 0x9d3b, 0x1f47, + 0x9d3c, 0x5483, + 0x9d3f, 0x1f1d, + 0x9d40, 0x5486, + 0x9d42, 0x258d, + 0x9d43, 0x5488, + 0x9d51, 0x1fd0, + 0x9d52, 0x2592, + 0x9d53, 0x258f, + 0x9d54, 0x5496, + 0x9d5c, 0x2594, + 0x9d5d, 0x1ee0, + 0x9d5e, 0x549e, + 0x9d60, 0x2591, + 0x9d61, 0x2595, + 0x9d62, 0x54a0, + 0x9d6a, 0x2597, + 0x9d6b, 0x54a8, + 0x9d6c, 0x20b6, + 0x9d6d, 0x54a9, + 0x9d6f, 0x2598, + 0x9d70, 0x54ab, + 0x9d72, 0x20f6, + 0x9d73, 0x54ad, + 0x9d87, 0x2585, + 0x9d88, 0x54c1, + 0x9d89, 0x2599, + 0x9d8a, 0x54c2, + 0x9d93, 0x2596, + 0x9d94, 0x54cb, + 0x9d98, 0x259a, + 0x9d99, 0x54cf, + 0x9d9a, 0x259b, + 0x9d9b, 0x54d0, + 0x9da5, 0x259d, + 0x9da6, 0x54da, + 0x9da9, 0x259e, + 0x9daa, 0x54dd, + 0x9daf, 0x234c, + 0x9db0, 0x54e2, + 0x9db4, 0x1f44, + 0x9db5, 0x54e6, + 0x9dbb, 0x2660, + 0x9dbc, 0x25a0, + 0x9dbd, 0x54ec, + 0x9dc0, 0x259c, + 0x9dc1, 0x54ef, + 0x9dc2, 0x259f, + 0x9dc3, 0x54f0, + 0x9dc4, 0x1f6c, + 0x9dc5, 0x54f1, + 0x9dd3, 0x25a2, + 0x9dd4, 0x54ff, + 0x9dd7, 0x20ae, + 0x9dd8, 0x5502, + 0x9dd9, 0x258b, + 0x9dda, 0x25a3, + 0x9ddb, 0x5503, + 0x9de5, 0x2589, + 0x9de6, 0x25a5, + 0x9de7, 0x550d, + 0x9def, 0x25a4, + 0x9df0, 0x5515, + 0x9df2, 0x25a6, + 0x9df3, 0x2593, + 0x9df4, 0x5517, + 0x9df8, 0x25a7, + 0x9df9, 0x2222, + 0x9dfa, 0x25a9, + 0x9dfb, 0x551b, + 0x9e00, 0x5520, + 0x9e0c, 0x25a8, + 0x9e0d, 0x552c, + 0x9e15, 0x2586, + 0x9e16, 0x5534, + 0x9e1a, 0x25a1, + 0x9e1b, 0x25aa, + 0x9e1c, 0x5538, + 0x9e1d, 0x2590, + 0x9e1e, 0x258e, + 0x9e1f, 0x0b54, + 0x9e20, 0x1b35, + 0x9e21, 0x0819, + 0x9e22, 0x1b36, + 0x9e23, 0x0afe, + 0x9e24, 0x5539, + 0x9e25, 0x0b79, + 0x9e26, 0x0fe4, + 0x9e27, 0x553a, + 0x9e28, 0x1b37, + 0x9e2d, 0x0fe5, + 0x9e2e, 0x553b, + 0x9e2f, 0x1015, + 0x9e30, 0x553c, + 0x9e31, 0x1b3d, + 0x9e32, 0x1b3c, + 0x9e33, 0x10ea, + 0x9e34, 0x553d, + 0x9e35, 0x0e83, + 0x9e36, 0x1b3e, + 0x9e37, 0x1b40, + 0x9e38, 0x1b3f, + 0x9e39, 0x1b41, + 0x9e3b, 0x553e, + 0x9e3d, 0x06e6, + 0x9e3e, 0x1b43, + 0x9e3f, 0x079f, + 0x9e40, 0x5540, + 0x9e41, 0x1b44, + 0x9e43, 0x0918, + 0x9e44, 0x1b46, + 0x9e45, 0x062b, + 0x9e46, 0x1b47, + 0x9e4a, 0x0c90, + 0x9e4b, 0x1b4b, + 0x9e4d, 0x5541, + 0x9e4e, 0x1b4d, + 0x9e4f, 0x0bb5, + 0x9e50, 0x5542, + 0x9e51, 0x1b4e, + 0x9e52, 0x5543, + 0x9e55, 0x1b4f, + 0x9e56, 0x5546, + 0x9e57, 0x1b50, + 0x9e58, 0x1dd5, + 0x9e59, 0x5547, + 0x9e5a, 0x1b51, + 0x9e5d, 0x5548, + 0x9e5e, 0x1b54, + 0x9e5f, 0x5549, + 0x9e63, 0x1b55, + 0x9e64, 0x078e, + 0x9e65, 0x554d, + 0x9e66, 0x1b56, + 0x9e6d, 0x1b5e, + 0x9e6e, 0x554e, + 0x9e70, 0x108a, + 0x9e71, 0x1b5d, + 0x9e72, 0x5550, + 0x9e73, 0x1b5f, + 0x9e74, 0x5551, + 0x9e75, 0x2688, + 0x9e76, 0x5552, + 0x9e79, 0x269e, + 0x9e7a, 0x25fb, + 0x9e7b, 0x5555, + 0x9e7c, 0x1f8c, + 0x9e7d, 0x21f4, + 0x9e7e, 0x1d16, + 0x9e7f, 0x0a60, + 0x9e80, 0x5556, + 0x9e82, 0x1dfc, + 0x9e83, 0x5558, + 0x9e87, 0x1dfd, + 0x9e89, 0x555c, + 0x9e8b, 0x1dff, + 0x9e8c, 0x555e, + 0x9e92, 0x1e00, + 0x9e93, 0x0a5b, + 0x9e94, 0x5564, + 0x9e97, 0x200f, + 0x9e98, 0x5567, + 0x9e9d, 0x1e02, + 0x9e9e, 0x556c, + 0x9e9f, 0x1e03, + 0x9ea0, 0x556d, + 0x9ea5, 0x2071, + 0x9ea6, 0x0a9a, + 0x9ea7, 0x5572, + 0x9ea9, 0x25f7, + 0x9eaa, 0x5574, + 0x9eaf, 0x2696, + 0x9eb0, 0x5579, + 0x9eb4, 0x1cee, + 0x9eb5, 0x268f, + 0x9eb6, 0x557d, + 0x9eb8, 0x1ced, + 0x9eb9, 0x557f, + 0x9ebb, 0x0a90, + 0x9ebc, 0x5581, + 0x9ebd, 0x1df9, + 0x9ebf, 0x5582, + 0x9ec4, 0x07db, + 0x9ec5, 0x5587, + 0x9ec9, 0x12f8, + 0x9eca, 0x558b, + 0x9ecc, 0x22da, + 0x9ecd, 0x0d89, + 0x9ece, 0x09d3, + 0x9ecf, 0x1b2a, + 0x9ed0, 0x558d, + 0x9ed1, 0x0791, + 0x9ed2, 0x558e, + 0x9ed4, 0x0c2a, + 0x9ed5, 0x5590, + 0x9ed8, 0x0b0f, + 0x9ed9, 0x5593, + 0x9edb, 0x1e04, + 0x9ede, 0x1ec1, + 0x9edf, 0x1e08, + 0x9ee0, 0x1e07, + 0x9ee1, 0x5595, + 0x9ee2, 0x1e09, + 0x9ee3, 0x5596, + 0x9ee5, 0x1e0c, + 0x9ee6, 0x5598, + 0x9ee7, 0x1e0b, + 0x9ee8, 0x1eb3, + 0x9ee9, 0x1e0a, + 0x9eea, 0x1e0d, + 0x9eeb, 0x5599, + 0x9eef, 0x1e0e, + 0x9ef0, 0x559d, + 0x9ef2, 0x266a, + 0x9ef3, 0x559f, + 0x9ef4, 0x268a, + 0x9ef5, 0x55a0, + 0x9ef7, 0x2669, + 0x9ef8, 0x55a2, + 0x9ef9, 0x1a55, + 0x9efa, 0x55a3, + 0x9efb, 0x1a56, + 0x9efd, 0x2618, + 0x9efe, 0x1d76, + 0x9eff, 0x2619, + 0x9f00, 0x55a4, + 0x9f09, 0x261a, + 0x9f0a, 0x55ad, + 0x9f0b, 0x1d77, + 0x9f0c, 0x55ae, + 0x9f0d, 0x1d78, + 0x9f0e, 0x05e5, + 0x9f0f, 0x55af, + 0x9f10, 0x1274, + 0x9f11, 0x55b0, + 0x9f13, 0x071d, + 0x9f14, 0x55b2, + 0x9f15, 0x2673, + 0x9f16, 0x55b3, + 0x9f17, 0x1271, + 0x9f18, 0x55b4, + 0x9f19, 0x13df, + 0x9f1a, 0x55b5, + 0x9f20, 0x0d8a, + 0x9f21, 0x55bb, + 0x9f22, 0x1e0f, + 0x9f23, 0x55bc, + 0x9f2c, 0x1e10, + 0x9f2d, 0x55c5, + 0x9f2f, 0x1e11, + 0x9f30, 0x55c7, + 0x9f37, 0x1e13, + 0x9f38, 0x55ce, + 0x9f39, 0x1e12, + 0x9f3a, 0x55cf, + 0x9f3b, 0x0430, + 0x9f3c, 0x55d0, + 0x9f3d, 0x1e14, + 0x9f3f, 0x55d1, + 0x9f44, 0x1e16, + 0x9f45, 0x55d6, + 0x9f4a, 0x20c6, + 0x9f4b, 0x226b, + 0x9f4c, 0x55db, + 0x9f4f, 0x24d3, + 0x9f50, 0x0c0a, + 0x9f51, 0x19c2, + 0x9f52, 0x1e86, + 0x9f53, 0x55de, + 0x9f54, 0x260f, + 0x9f55, 0x55df, + 0x9f59, 0x2611, + 0x9f5a, 0x55e3, + 0x9f5c, 0x2613, + 0x9f5d, 0x55e5, + 0x9f5f, 0x2610, + 0x9f60, 0x2612, + 0x9f61, 0x2030, + 0x9f62, 0x55e7, + 0x9f63, 0x2671, + 0x9f64, 0x55e8, + 0x9f66, 0x2614, + 0x9f67, 0x55ea, + 0x9f6a, 0x2616, + 0x9f6b, 0x55ed, + 0x9f6c, 0x2615, + 0x9f6d, 0x55ee, + 0x9f72, 0x20f2, + 0x9f73, 0x55f3, + 0x9f77, 0x2617, + 0x9f78, 0x55f7, + 0x9f7f, 0x0502, + 0x9f80, 0x1d6d, + 0x9f81, 0x55fe, + 0x9f83, 0x1d6e, + 0x9f84, 0x0a2d, + 0x9f85, 0x1d6f, + 0x9f8b, 0x0c7e, + 0x9f8c, 0x1d75, + 0x9f8d, 0x2037, + 0x9f8e, 0x5600, + 0x9f90, 0x20b3, + 0x9f91, 0x5602, + 0x9f94, 0x1f22, + 0x9f95, 0x24ed, + 0x9f96, 0x5605, + 0x9f99, 0x0a43, + 0x9f9a, 0x0701, + 0x9f9b, 0x1a54, + 0x9f9c, 0x1f34, + 0x9f9d, 0x5608, + 0x9f9f, 0x0743, + 0x9fa0, 0x12f3, + 0x9fa1, 0x560a, + 0xe7e7, 0x274b, + 0xe815, 0x561f, + 0xf92c, 0x560f, + 0xfa0d, 0x5610, + 0xfa11, 0x5613, + 0xfa13, 0x5614, + 0xfa18, 0x5616, + 0xfa1f, 0x5617, + 0xfa23, 0x561a, + 0xfa27, 0x561c, + 0xfe30, 0x271d, + 0xfe49, 0x272b, + 0xfe54, 0x2735, + 0xfe59, 0x2739, + 0xfe68, 0x2747, + 0xff01, 0x0106, + 0xff04, 0x00a6, + 0xff05, 0x010a, + 0xff5e, 0x006a, + 0xffe0, 0x00a8, + 0xffe2, 0x271e, + 0xffe3, 0x0163, + 0xffe4, 0x271f, + 0xffe5, 0x0109, + 0xffff, 0x0000 +}; + +static GfxFontEncoding16 gb12UniGBUCS2HEnc16 = { + 0, + { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }, + { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, + gb12UniGBUCS2HMap2, 13461 +}; + +static Gushort gb12UniGBUCS2VMap2[26970] = { + 0x0000, 0x0000, + 0x0020, 0x0001, + 0x00a4, 0x00a7, + 0x00a7, 0x00ab, + 0x00a8, 0x0066, + 0x00b0, 0x00a2, + 0x00b1, 0x007f, + 0x00d7, 0x0080, + 0x00e0, 0x029f, + 0x00e1, 0x029d, + 0x00e8, 0x02a3, + 0x00e9, 0x02a1, + 0x00ea, 0x02b5, + 0x00ec, 0x02a7, + 0x00ed, 0x02a5, + 0x00f2, 0x02ab, + 0x00f3, 0x02a9, + 0x00f7, 0x0081, + 0x00f9, 0x02af, + 0x00fa, 0x02ad, + 0x00fc, 0x02b4, + 0x0101, 0x029c, + 0x0113, 0x02a0, + 0x011b, 0x02a2, + 0x012b, 0x02a4, + 0x014d, 0x02a8, + 0x016b, 0x02ac, + 0x01ce, 0x029e, + 0x01d0, 0x02a6, + 0x01d2, 0x02aa, + 0x01d4, 0x02ae, + 0x01d6, 0x02b0, + 0x01d8, 0x02b1, + 0x01da, 0x02b2, + 0x01dc, 0x02b3, + 0x02c7, 0x0065, + 0x02c9, 0x0064, + 0x02ca, 0x26b3, + 0x02d9, 0x26b5, + 0x0391, 0x020d, + 0x03a3, 0x021e, + 0x03b1, 0x0225, + 0x03c3, 0x0236, + 0x0401, 0x0260, + 0x0410, 0x025a, + 0x0416, 0x0261, + 0x0436, 0x0282, + 0x0451, 0x0281, + 0x1e3f, 0x02b7, + 0x2010, 0x2722, + 0x2013, 0x26b6, + 0x2014, 0x0069, + 0x2015, 0x26b7, + 0x2016, 0x006b, + 0x2018, 0x006d, + 0x201c, 0x006f, + 0x2025, 0x26b8, + 0x2026, 0x006c, + 0x2030, 0x00aa, + 0x2032, 0x00a3, + 0x2035, 0x26b9, + 0x203b, 0x00b8, + 0x2103, 0x00a5, + 0x2105, 0x26ba, + 0x2109, 0x26bb, + 0x2116, 0x00ac, + 0x2121, 0x2720, + 0x2160, 0x00fa, + 0x2170, 0x26a9, + 0x2190, 0x00ba, + 0x2192, 0x00b9, + 0x2193, 0x00bc, + 0x2196, 0x26bc, + 0x2208, 0x0089, + 0x220f, 0x0086, + 0x2211, 0x0085, + 0x2215, 0x26c0, + 0x221a, 0x008b, + 0x221d, 0x0097, + 0x221e, 0x009d, + 0x221f, 0x26c1, + 0x2220, 0x008e, + 0x2223, 0x26c2, + 0x2225, 0x008d, + 0x2227, 0x0083, + 0x2229, 0x0088, + 0x222a, 0x0087, + 0x222b, 0x0091, + 0x222e, 0x0092, + 0x2234, 0x009f, + 0x2235, 0x009e, + 0x2236, 0x0082, + 0x2237, 0x008a, + 0x223d, 0x0096, + 0x2248, 0x0095, + 0x224c, 0x0094, + 0x2252, 0x26c3, + 0x2260, 0x0098, + 0x2261, 0x0093, + 0x2264, 0x009b, + 0x2266, 0x26c4, + 0x226e, 0x0099, + 0x2295, 0x2704, + 0x2299, 0x0090, + 0x22a5, 0x008c, + 0x22bf, 0x26c6, + 0x22ef, 0x006c, + 0x2312, 0x008f, + 0x2460, 0x00e6, + 0x2474, 0x00d2, + 0x2488, 0x00be, + 0x2500, 0x02e2, + 0x2550, 0x26c7, + 0x2581, 0x26eb, + 0x2593, 0x26fa, + 0x25a0, 0x00b5, + 0x25a1, 0x00b4, + 0x25b2, 0x00b7, + 0x25b3, 0x00b6, + 0x25bc, 0x26fd, + 0x25c6, 0x00b3, + 0x25c7, 0x00b2, + 0x25cb, 0x00af, + 0x25ce, 0x00b1, + 0x25cf, 0x00b0, + 0x25e2, 0x26ff, + 0x2605, 0x00ae, + 0x2606, 0x00ad, + 0x2609, 0x2703, + 0x2640, 0x00a1, + 0x2642, 0x00a0, + 0x3000, 0x0060, + 0x3003, 0x0067, + 0x3005, 0x0068, + 0x3006, 0x2728, + 0x3007, 0x1e17, + 0x3008, 0x0073, + 0x3010, 0x007d, + 0x3012, 0x2705, + 0x3013, 0x00bd, + 0x3014, 0x0071, + 0x3016, 0x007b, + 0x301d, 0x2706, + 0x3021, 0x2708, + 0x3041, 0x0164, + 0x309b, 0x2724, + 0x309d, 0x2729, + 0x30a1, 0x01b7, + 0x30fb, 0x0063, + 0x30fc, 0x2723, + 0x30fd, 0x2726, + 0x3105, 0x02bc, + 0x3220, 0x00f0, + 0x3231, 0x2721, + 0x32a3, 0x2711, + 0x338e, 0x2712, + 0x339c, 0x2714, + 0x33a1, 0x2717, + 0x33c4, 0x2718, + 0x33ce, 0x2719, + 0x33d1, 0x271a, + 0x33d5, 0x271c, + 0x4e00, 0x1042, + 0x4e01, 0x05e0, + 0x4e02, 0x2758, + 0x4e03, 0x0bfe, + 0x4e04, 0x2759, + 0x4e07, 0x0ea3, + 0x4e08, 0x116a, + 0x4e09, 0x0cd8, + 0x4e0a, 0x0d08, + 0x4e0b, 0x0f2f, + 0x4e0c, 0x1258, + 0x4e0d, 0x0482, + 0x4e0e, 0x10d0, + 0x4e0f, 0x275c, + 0x4e10, 0x125a, + 0x4e11, 0x0518, + 0x4e12, 0x275d, + 0x4e13, 0x1205, + 0x4e14, 0x0c4f, + 0x4e15, 0x125d, + 0x4e16, 0x0d57, + 0x4e17, 0x275e, + 0x4e18, 0x0c6d, + 0x4e19, 0x0464, + 0x4e1a, 0x103c, + 0x4e1b, 0x0557, + 0x4e1c, 0x05ea, + 0x4e1d, 0x0db4, + 0x4e1e, 0x125f, + 0x4e1f, 0x275f, + 0x4e22, 0x05e9, + 0x4e23, 0x2762, + 0x4e24, 0x0a06, + 0x4e25, 0x0ff8, + 0x4e26, 0x2763, + 0x4e27, 0x0cde, + 0x4e28, 0x1263, + 0x4e29, 0x2764, + 0x4e2a, 0x06f1, + 0x4e2b, 0x0fe7, + 0x4e2c, 0x169c, + 0x4e2d, 0x11cf, + 0x4e2e, 0x2765, + 0x4e30, 0x067e, + 0x4e31, 0x2767, + 0x4e32, 0x0531, + 0x4e33, 0x2768, + 0x4e34, 0x0a22, + 0x4e35, 0x2769, + 0x4e36, 0x1272, + 0x4e37, 0x276a, + 0x4e38, 0x0e99, + 0x4e39, 0x0585, + 0x4e3a, 0x0eb9, + 0x4e3b, 0x11f6, + 0x4e3c, 0x276b, + 0x4e3d, 0x09e1, + 0x4e3e, 0x0908, + 0x4e3f, 0x1265, + 0x4e40, 0x276c, + 0x4e43, 0x0b2e, + 0x4e44, 0x276f, + 0x4e45, 0x08f2, + 0x4e46, 0x2770, + 0x4e47, 0x1267, + 0x4e48, 0x0ab9, + 0x4e49, 0x106c, + 0x4e4a, 0x2771, + 0x4e4b, 0x11ad, + 0x4e4c, 0x0ee9, + 0x4e4d, 0x1148, + 0x4e4e, 0x07ac, + 0x4e4f, 0x0643, + 0x4e50, 0x09c1, + 0x4e51, 0x2772, + 0x4e52, 0x0bd8, + 0x4e53, 0x0b93, + 0x4e54, 0x0c44, + 0x4e55, 0x2773, + 0x4e56, 0x072d, + 0x4e57, 0x2774, + 0x4e58, 0x04f0, + 0x4e59, 0x1059, + 0x4e5a, 0x2775, + 0x4e5c, 0x1275, + 0x4e5d, 0x08f4, + 0x4e5e, 0x0c11, + 0x4e5f, 0x1039, + 0x4e60, 0x0f1d, + 0x4e61, 0x0f54, + 0x4e62, 0x2777, + 0x4e66, 0x0d80, + 0x4e67, 0x277b, + 0x4e69, 0x1276, + 0x4e6a, 0x277d, + 0x4e70, 0x0a99, + 0x4e71, 0x0a79, + 0x4e72, 0x2783, + 0x4e73, 0x0cc4, + 0x4e74, 0x2784, + 0x4e7e, 0x0c29, + 0x4e7f, 0x278e, + 0x4e82, 0x2059, + 0x4e83, 0x2791, + 0x4e86, 0x0a14, + 0x4e87, 0x2794, + 0x4e88, 0x10cd, + 0x4e89, 0x119a, + 0x4e8a, 0x2795, + 0x4e8b, 0x0d59, + 0x4e8c, 0x063d, + 0x4e8d, 0x1257, + 0x4e8e, 0x10bf, + 0x4e8f, 0x0984, + 0x4e90, 0x2796, + 0x4e91, 0x1109, + 0x4e92, 0x07ba, + 0x4e93, 0x1277, + 0x4e94, 0x0ef4, + 0x4e95, 0x08dd, + 0x4e96, 0x2797, + 0x4e98, 0x125e, + 0x4e99, 0x2799, + 0x4e9a, 0x0ff0, + 0x4e9b, 0x0f74, + 0x4e9c, 0x279a, + 0x4e9e, 0x21f1, + 0x4e9f, 0x1273, + 0x4ea0, 0x1303, + 0x4ea1, 0x0ea7, + 0x4ea2, 0x0947, + 0x4ea3, 0x279c, + 0x4ea4, 0x088c, + 0x4ea5, 0x075c, + 0x4ea6, 0x1067, + 0x4ea7, 0x04c1, + 0x4ea8, 0x0797, + 0x4ea9, 0x0b19, + 0x4eaa, 0x279d, + 0x4eab, 0x0f5a, + 0x4eac, 0x08d8, + 0x4ead, 0x0e55, + 0x4eae, 0x0a0a, + 0x4eaf, 0x279e, + 0x4eb2, 0x0c54, + 0x4eb3, 0x1305, + 0x4eb4, 0x27a1, + 0x4eb5, 0x1308, + 0x4eb6, 0x27a2, + 0x4eba, 0x0ca6, + 0x4ebb, 0x129f, + 0x4ebc, 0x27a6, + 0x4ebf, 0x1061, + 0x4ec0, 0x0d49, + 0x4ec1, 0x0ca5, + 0x4ec2, 0x12a2, + 0x4ec3, 0x12a0, + 0x4ec4, 0x127c, + 0x4ec5, 0x08c7, + 0x4ec6, 0x0bec, + 0x4ec7, 0x0515, + 0x4ec8, 0x27a9, + 0x4ec9, 0x12a1, + 0x4eca, 0x08c2, + 0x4ecb, 0x08ba, + 0x4ecc, 0x27aa, + 0x4ecd, 0x0caf, + 0x4ece, 0x0556, + 0x4ecf, 0x27ab, + 0x4ed1, 0x0a7f, + 0x4ed2, 0x27ad, + 0x4ed3, 0x049d, + 0x4ed4, 0x122d, + 0x4ed5, 0x0d62, + 0x4ed6, 0x0df0, + 0x4ed7, 0x116d, + 0x4ed8, 0x06b1, + 0x4ed9, 0x0f36, + 0x4eda, 0x27ae, + 0x4edd, 0x12ee, + 0x4ede, 0x12a6, + 0x4edf, 0x0c27, + 0x4ee0, 0x27b1, + 0x4ee1, 0x12a4, + 0x4ee2, 0x27b2, + 0x4ee3, 0x057d, + 0x4ee4, 0x0a37, + 0x4ee5, 0x105b, + 0x4ee6, 0x27b3, + 0x4ee8, 0x12a3, + 0x4ee9, 0x27b5, + 0x4eea, 0x104e, + 0x4eeb, 0x12a5, + 0x4eec, 0x0acc, + 0x4eed, 0x27b6, + 0x4ef0, 0x101f, + 0x4ef1, 0x27b9, + 0x4ef2, 0x11d8, + 0x4ef3, 0x12a8, + 0x4ef4, 0x27ba, + 0x4ef5, 0x12ab, + 0x4ef6, 0x0871, + 0x4ef7, 0x084e, + 0x4ef8, 0x27bb, + 0x4efb, 0x0ca9, + 0x4efc, 0x27be, + 0x4efd, 0x067a, + 0x4efe, 0x27bf, + 0x4eff, 0x065f, + 0x4f00, 0x27c0, + 0x4f01, 0x0c12, + 0x4f02, 0x27c1, + 0x4f09, 0x12ae, + 0x4f0a, 0x1048, + 0x4f0b, 0x27c8, + 0x4f0d, 0x0ef8, + 0x4f0e, 0x0832, + 0x4f0f, 0x0699, + 0x4f10, 0x0642, + 0x4f11, 0x0fa8, + 0x4f12, 0x27ca, + 0x4f17, 0x11d9, + 0x4f18, 0x10aa, + 0x4f19, 0x0804, + 0x4f1a, 0x07f6, + 0x4f1b, 0x12a7, + 0x4f1c, 0x27cf, + 0x4f1e, 0x0cda, + 0x4f1f, 0x0ebf, + 0x4f20, 0x052e, + 0x4f21, 0x27d1, + 0x4f22, 0x12a9, + 0x4f23, 0x27d2, + 0x4f24, 0x0d04, + 0x4f25, 0x12ac, + 0x4f26, 0x0a7e, + 0x4f27, 0x12ad, + 0x4f28, 0x27d3, + 0x4f2a, 0x0ec0, + 0x4f2b, 0x12af, + 0x4f2c, 0x27d5, + 0x4f2f, 0x0475, + 0x4f30, 0x0719, + 0x4f31, 0x27d8, + 0x4f32, 0x12b7, + 0x4f33, 0x27d9, + 0x4f34, 0x03f4, + 0x4f35, 0x27da, + 0x4f36, 0x0a2f, + 0x4f37, 0x27db, + 0x4f38, 0x0d25, + 0x4f39, 0x27dc, + 0x4f3a, 0x0dba, + 0x4f3b, 0x27dd, + 0x4f3c, 0x0dbb, + 0x4f3d, 0x12b8, + 0x4f3e, 0x27de, + 0x4f43, 0x05c9, + 0x4f44, 0x27e3, + 0x4f46, 0x058c, + 0x4f47, 0x27e5, + 0x4f4d, 0x0eca, + 0x4f4e, 0x05ae, + 0x4f4f, 0x11fe, + 0x4f50, 0x1251, + 0x4f51, 0x10b8, + 0x4f52, 0x27eb, + 0x4f53, 0x0e38, + 0x4f54, 0x27ec, + 0x4f55, 0x0785, + 0x4f56, 0x27ed, + 0x4f57, 0x12b6, + 0x4f58, 0x12f0, + 0x4f59, 0x10c5, + 0x4f5a, 0x12b3, + 0x4f5b, 0x068d, + 0x4f5c, 0x1254, + 0x4f5d, 0x12b4, + 0x4f5e, 0x12b0, + 0x4f5f, 0x12b5, + 0x4f60, 0x0b46, + 0x4f61, 0x27ee, + 0x4f63, 0x109b, + 0x4f64, 0x12aa, + 0x4f65, 0x12f1, + 0x4f66, 0x27f0, + 0x4f67, 0x12b1, + 0x4f68, 0x27f1, + 0x4f69, 0x0ba6, + 0x4f6a, 0x27f2, + 0x4f6c, 0x09bb, + 0x4f6d, 0x27f4, + 0x4f6f, 0x1019, + 0x4f70, 0x03e6, + 0x4f71, 0x27f6, + 0x4f73, 0x0844, + 0x4f74, 0x12ba, + 0x4f75, 0x27f8, + 0x4f76, 0x12b9, + 0x4f77, 0x27f9, + 0x4f7b, 0x12c0, + 0x4f7c, 0x12c2, + 0x4f7d, 0x27fd, + 0x4f7e, 0x12bf, + 0x4f7f, 0x0d50, + 0x4f80, 0x27fe, + 0x4f83, 0x12bd, + 0x4f84, 0x11b5, + 0x4f85, 0x2801, + 0x4f86, 0x1ff2, + 0x4f87, 0x2802, + 0x4f88, 0x0503, + 0x4f89, 0x12bc, + 0x4f8a, 0x2803, + 0x4f8b, 0x09e8, + 0x4f8c, 0x2804, + 0x4f8d, 0x0d63, + 0x4f8e, 0x2805, + 0x4f8f, 0x12be, + 0x4f90, 0x2806, + 0x4f91, 0x12bb, + 0x4f92, 0x2807, + 0x4f94, 0x12c4, + 0x4f95, 0x2809, + 0x4f96, 0x205d, + 0x4f97, 0x05f0, + 0x4f98, 0x280a, + 0x4f9b, 0x0702, + 0x4f9c, 0x280d, + 0x4f9d, 0x1047, + 0x4f9e, 0x280e, + 0x4fa0, 0x0f2d, + 0x4fa1, 0x2810, + 0x4fa3, 0x0a69, + 0x4fa4, 0x2812, + 0x4fa5, 0x0895, + 0x4fa6, 0x118d, + 0x4fa7, 0x04a7, + 0x4fa8, 0x0c45, + 0x4fa9, 0x0978, + 0x4faa, 0x12c1, + 0x4fab, 0x2813, + 0x4fac, 0x12c3, + 0x4fad, 0x2814, + 0x4fae, 0x0ef9, + 0x4faf, 0x07a5, + 0x4fb0, 0x2815, + 0x4fb5, 0x0c53, + 0x4fb6, 0x281a, + 0x4fbf, 0x044c, + 0x4fc0, 0x2823, + 0x4fc2, 0x269c, + 0x4fc3, 0x055c, + 0x4fc4, 0x062c, + 0x4fc5, 0x12c8, + 0x4fc6, 0x2825, + 0x4fca, 0x092e, + 0x4fcb, 0x2829, + 0x4fce, 0x12f2, + 0x4fcf, 0x0c4b, + 0x4fd0, 0x09e9, + 0x4fd1, 0x12cc, + 0x4fd2, 0x282c, + 0x4fd7, 0x0dcc, + 0x4fd8, 0x069a, + 0x4fd9, 0x2831, + 0x4fda, 0x12c9, + 0x4fdb, 0x2832, + 0x4fdc, 0x12cb, + 0x4fdd, 0x040c, + 0x4fde, 0x10c6, + 0x4fdf, 0x12cd, + 0x4fe0, 0x21b5, + 0x4fe1, 0x0f90, + 0x4fe2, 0x2833, + 0x4fe3, 0x12ca, + 0x4fe4, 0x2834, + 0x4fe6, 0x12c5, + 0x4fe7, 0x2836, + 0x4fe8, 0x12c6, + 0x4fe9, 0x09f2, + 0x4fea, 0x12c7, + 0x4feb, 0x2837, + 0x4fed, 0x0866, + 0x4fee, 0x0fa9, + 0x4fef, 0x06a4, + 0x4ff0, 0x2839, + 0x4ff1, 0x0912, + 0x4ff2, 0x283a, + 0x4ff3, 0x12d1, + 0x4ff4, 0x283b, + 0x4ff8, 0x12ce, + 0x4ff9, 0x283f, + 0x4ffa, 0x03be, + 0x4ffb, 0x2840, + 0x4ffe, 0x12d6, + 0x4fff, 0x2843, + 0x5000, 0x22cc, + 0x5001, 0x2844, + 0x5006, 0x2016, + 0x5007, 0x2849, + 0x5009, 0x1e62, + 0x500a, 0x284b, + 0x500b, 0x1f20, + 0x500c, 0x12d8, + 0x500d, 0x041f, + 0x500e, 0x284c, + 0x500f, 0x12d3, + 0x5010, 0x284d, + 0x5011, 0x207f, + 0x5012, 0x059a, + 0x5013, 0x284e, + 0x5014, 0x0922, + 0x5015, 0x284f, + 0x5018, 0x0e1b, + 0x5019, 0x07a9, + 0x501a, 0x1057, + 0x501b, 0x2852, + 0x501c, 0x12d7, + 0x501d, 0x2853, + 0x501f, 0x08b9, + 0x5020, 0x2855, + 0x5021, 0x04d0, + 0x5022, 0x2856, + 0x5025, 0x12d9, + 0x5026, 0x091a, + 0x5027, 0x2859, + 0x5028, 0x12da, + 0x5029, 0x12cf, + 0x502a, 0x0b42, + 0x502b, 0x205c, + 0x502c, 0x12d2, + 0x502d, 0x12d5, + 0x502e, 0x12d4, + 0x502f, 0x285a, + 0x503a, 0x114f, + 0x503b, 0x2865, + 0x503c, 0x11b4, + 0x503d, 0x2866, + 0x503e, 0x0c60, + 0x503f, 0x2867, + 0x5043, 0x12dc, + 0x5044, 0x286b, + 0x5047, 0x084c, + 0x5048, 0x12de, + 0x5049, 0x2194, + 0x504a, 0x286e, + 0x504c, 0x12d0, + 0x504d, 0x2870, + 0x504e, 0x12df, + 0x504f, 0x0bca, + 0x5050, 0x2871, + 0x5055, 0x12dd, + 0x5056, 0x2876, + 0x505a, 0x1253, + 0x505b, 0x287a, + 0x505c, 0x0e54, + 0x505d, 0x287b, + 0x5065, 0x0872, + 0x5066, 0x2883, + 0x506c, 0x12e0, + 0x506d, 0x2889, + 0x5074, 0x1e65, + 0x5075, 0x2281, + 0x5076, 0x0b7d, + 0x5077, 0x0e66, + 0x5078, 0x2890, + 0x507b, 0x12e1, + 0x507c, 0x2893, + 0x507e, 0x12db, + 0x507f, 0x04ca, + 0x5080, 0x098b, + 0x5081, 0x2895, + 0x5085, 0x06b0, + 0x5086, 0x2899, + 0x5088, 0x09e7, + 0x5089, 0x289b, + 0x508d, 0x0403, + 0x508e, 0x289f, + 0x5096, 0x22cd, + 0x5097, 0x28a7, + 0x5098, 0x210a, + 0x5099, 0x1e3e, + 0x509a, 0x28a8, + 0x50a2, 0x267f, + 0x50a3, 0x0579, + 0x50a4, 0x28b0, + 0x50a5, 0x12e2, + 0x50a6, 0x28b1, + 0x50a7, 0x12e3, + 0x50a8, 0x0525, + 0x50a9, 0x12e4, + 0x50aa, 0x28b2, + 0x50ac, 0x0562, + 0x50ad, 0x222e, + 0x50ae, 0x28b4, + 0x50b2, 0x03cc, + 0x50b3, 0x1e96, + 0x50b4, 0x22cb, + 0x50b5, 0x226c, + 0x50b6, 0x28b8, + 0x50b7, 0x2117, + 0x50b8, 0x28b9, + 0x50ba, 0x12e5, + 0x50bb, 0x0cee, + 0x50bc, 0x28bb, + 0x50be, 0x20e8, + 0x50bf, 0x28bd, + 0x50c2, 0x22d4, + 0x50c3, 0x28c0, + 0x50c5, 0x1fb9, + 0x50c6, 0x28c2, + 0x50c9, 0x22d8, + 0x50ca, 0x28c5, + 0x50cf, 0x0f5e, + 0x50d0, 0x28ca, + 0x50d1, 0x20df, + 0x50d2, 0x28cb, + 0x50d5, 0x20c2, + 0x50d6, 0x12e6, + 0x50d7, 0x28ce, + 0x50da, 0x0a0e, + 0x50db, 0x28d1, + 0x50de, 0x2195, + 0x50df, 0x28d4, + 0x50e5, 0x1fac, + 0x50e6, 0x12ea, + 0x50e7, 0x0ce7, + 0x50e8, 0x22d3, + 0x50e9, 0x28da, + 0x50ec, 0x12e9, + 0x50ed, 0x12e8, + 0x50ee, 0x12eb, + 0x50ef, 0x28dd, + 0x50f3, 0x0dd0, + 0x50f4, 0x28e1, + 0x50f5, 0x087a, + 0x50f6, 0x28e2, + 0x50f9, 0x1f81, + 0x50fa, 0x28e5, + 0x50fb, 0x0bc6, + 0x50fc, 0x28e6, + 0x5100, 0x2210, + 0x5101, 0x28ea, + 0x5102, 0x22cf, + 0x5103, 0x28eb, + 0x5104, 0x2213, + 0x5105, 0x28ec, + 0x5106, 0x12e7, + 0x5107, 0x12ec, + 0x5108, 0x1fe4, + 0x5109, 0x1f90, + 0x510a, 0x28ed, + 0x510b, 0x12ed, + 0x510c, 0x28ee, + 0x5110, 0x22d6, + 0x5111, 0x28f2, + 0x5112, 0x0cc0, + 0x5113, 0x28f3, + 0x5114, 0x22d0, + 0x5115, 0x22ce, + 0x5116, 0x28f4, + 0x5118, 0x2681, + 0x5119, 0x28f6, + 0x511f, 0x1e76, + 0x5120, 0x28fc, + 0x5121, 0x09c7, + 0x5122, 0x28fd, + 0x512a, 0x2231, + 0x512b, 0x2905, + 0x5132, 0x1e93, + 0x5133, 0x290c, + 0x5137, 0x22d2, + 0x5138, 0x2910, + 0x513a, 0x22d7, + 0x513b, 0x22d5, + 0x513c, 0x22d1, + 0x513d, 0x2912, + 0x513f, 0x0638, + 0x5140, 0x1259, + 0x5141, 0x110d, + 0x5142, 0x2914, + 0x5143, 0x10ed, + 0x5144, 0x0fa1, + 0x5145, 0x0509, + 0x5146, 0x1178, + 0x5147, 0x2915, + 0x5148, 0x0f35, + 0x5149, 0x073b, + 0x514a, 0x2916, + 0x514b, 0x0958, + 0x514c, 0x2917, + 0x514d, 0x0ae7, + 0x514e, 0x2918, + 0x5151, 0x0611, + 0x5152, 0x1ee5, + 0x5153, 0x291b, + 0x5154, 0x0e74, + 0x5155, 0x1302, + 0x5156, 0x1304, + 0x5157, 0x291c, + 0x515a, 0x0594, + 0x515b, 0x291f, + 0x515c, 0x05f4, + 0x515d, 0x2920, + 0x5162, 0x08d3, + 0x5163, 0x2925, + 0x5165, 0x0cc6, + 0x5166, 0x2927, + 0x5168, 0x0c86, + 0x5169, 0x2025, + 0x516a, 0x2929, + 0x516b, 0x03d6, + 0x516c, 0x0704, + 0x516d, 0x0a42, + 0x516e, 0x12f6, + 0x516f, 0x292a, + 0x5170, 0x09a7, + 0x5171, 0x070b, + 0x5172, 0x292b, + 0x5173, 0x0731, + 0x5174, 0x0f96, + 0x5175, 0x0461, + 0x5176, 0x0c03, + 0x5177, 0x090e, + 0x5178, 0x05c5, + 0x5179, 0x1225, + 0x517a, 0x292c, + 0x517b, 0x1021, + 0x517c, 0x0859, + 0x517d, 0x0d75, + 0x517e, 0x292d, + 0x5180, 0x0830, + 0x5181, 0x12fa, + 0x5182, 0x129d, + 0x5183, 0x292f, + 0x5185, 0x0b3d, + 0x5186, 0x2931, + 0x5188, 0x06cf, + 0x5189, 0x0c98, + 0x518a, 0x2933, + 0x518c, 0x04a8, + 0x518d, 0x111c, + 0x518e, 0x2935, + 0x5192, 0x0ab5, + 0x5193, 0x2939, + 0x5195, 0x0ae6, + 0x5196, 0x1314, + 0x5197, 0x0cba, + 0x5198, 0x293b, + 0x5199, 0x0f7f, + 0x519a, 0x293c, + 0x519b, 0x092b, + 0x519c, 0x0b6a, + 0x519d, 0x293d, + 0x51a0, 0x0733, + 0x51a1, 0x2940, + 0x51a2, 0x1315, + 0x51a3, 0x2941, + 0x51a4, 0x10ec, + 0x51a5, 0x1316, + 0x51a6, 0x2942, + 0x51ab, 0x130f, + 0x51ac, 0x05eb, + 0x51ad, 0x2947, + 0x51af, 0x0688, + 0x51b0, 0x0462, + 0x51b1, 0x1310, + 0x51b2, 0x050a, + 0x51b3, 0x0925, + 0x51b4, 0x2949, + 0x51b5, 0x0983, + 0x51b6, 0x1038, + 0x51b7, 0x09cf, + 0x51b8, 0x294a, + 0x51bb, 0x05f2, + 0x51bc, 0x1312, + 0x51bd, 0x1311, + 0x51be, 0x294d, + 0x51c0, 0x08ea, + 0x51c1, 0x294f, + 0x51c4, 0x0bff, + 0x51c5, 0x2952, + 0x51c6, 0x1219, + 0x51c7, 0x1313, + 0x51c8, 0x2953, + 0x51c9, 0x0a02, + 0x51ca, 0x2954, + 0x51cb, 0x05d3, + 0x51cc, 0x0a31, + 0x51cd, 0x1ecf, + 0x51ce, 0x2955, + 0x51cf, 0x0868, + 0x51d0, 0x2956, + 0x51d1, 0x0558, + 0x51d2, 0x2957, + 0x51db, 0x0a26, + 0x51dc, 0x2960, + 0x51dd, 0x0b60, + 0x51de, 0x2961, + 0x51e0, 0x082b, + 0x51e1, 0x064f, + 0x51e2, 0x2963, + 0x51e4, 0x068c, + 0x51e5, 0x2965, + 0x51eb, 0x1300, + 0x51ec, 0x296b, + 0x51ed, 0x0bdd, + 0x51ee, 0x296c, + 0x51ef, 0x093a, + 0x51f0, 0x07e0, + 0x51f1, 0x1fd9, + 0x51f2, 0x296d, + 0x51f3, 0x05ab, + 0x51f4, 0x296e, + 0x51f5, 0x1399, + 0x51f6, 0x0fa2, + 0x51f7, 0x296f, + 0x51f8, 0x0e6a, + 0x51f9, 0x03c7, + 0x51fa, 0x051b, + 0x51fb, 0x080c, + 0x51fc, 0x139a, + 0x51fd, 0x0766, + 0x51fe, 0x2970, + 0x51ff, 0x1127, + 0x5200, 0x0597, + 0x5201, 0x05d4, + 0x5202, 0x128c, + 0x5203, 0x0cab, + 0x5204, 0x2971, + 0x5206, 0x0673, + 0x5207, 0x0c4d, + 0x5208, 0x128d, + 0x5209, 0x2973, + 0x520a, 0x093c, + 0x520b, 0x2974, + 0x520d, 0x138b, + 0x520e, 0x128e, + 0x520f, 0x2976, + 0x5211, 0x0f97, + 0x5212, 0x07c3, + 0x5213, 0x2978, + 0x5216, 0x196e, + 0x5217, 0x0a19, + 0x5218, 0x0a3e, + 0x5219, 0x1135, + 0x521a, 0x06d0, + 0x521b, 0x0537, + 0x521c, 0x297b, + 0x521d, 0x051a, + 0x521e, 0x297c, + 0x5220, 0x0cf7, + 0x5221, 0x297e, + 0x5224, 0x0b91, + 0x5225, 0x2981, + 0x5228, 0x0b9a, + 0x5229, 0x09e6, + 0x522a, 0x2984, + 0x522b, 0x0459, + 0x522c, 0x2985, + 0x522d, 0x128f, + 0x522e, 0x0727, + 0x522f, 0x2986, + 0x5230, 0x059e, + 0x5231, 0x2987, + 0x5233, 0x1290, + 0x5234, 0x2989, + 0x5236, 0x11c5, + 0x5237, 0x0d97, + 0x5238, 0x0c8a, + 0x5239, 0x0ceb, + 0x523a, 0x054f, + 0x523b, 0x0959, + 0x523c, 0x298b, + 0x523d, 0x074d, + 0x523e, 0x298c, + 0x523f, 0x1291, + 0x5241, 0x0626, + 0x5242, 0x0834, + 0x5243, 0x0e3d, + 0x5244, 0x22c8, + 0x5245, 0x298d, + 0x5247, 0x2263, + 0x5248, 0x298f, + 0x524a, 0x0f64, + 0x524b, 0x2683, + 0x524c, 0x1293, + 0x524d, 0x0c2d, + 0x524e, 0x2991, + 0x5250, 0x0729, + 0x5251, 0x0874, + 0x5252, 0x2993, + 0x5254, 0x0e31, + 0x5255, 0x2995, + 0x5256, 0x0be9, + 0x5257, 0x2996, + 0x525b, 0x1f17, + 0x525c, 0x1296, + 0x525d, 0x299a, + 0x525e, 0x1294, + 0x525f, 0x299b, + 0x5261, 0x1295, + 0x5262, 0x299d, + 0x5265, 0x0409, + 0x5266, 0x29a0, + 0x5267, 0x0916, + 0x5268, 0x29a1, + 0x5269, 0x0d3a, + 0x526a, 0x0867, + 0x526b, 0x29a2, + 0x526e, 0x1f2b, + 0x526f, 0x06ac, + 0x5270, 0x29a5, + 0x5272, 0x06e9, + 0x5273, 0x29a7, + 0x5274, 0x22ca, + 0x5275, 0x1e99, + 0x5276, 0x29a8, + 0x527d, 0x1298, + 0x527e, 0x29af, + 0x527f, 0x089c, + 0x5280, 0x29b0, + 0x5281, 0x129a, + 0x5282, 0x1299, + 0x5283, 0x1f4f, + 0x5284, 0x29b1, + 0x5287, 0x1fcf, + 0x5288, 0x0bbd, + 0x5289, 0x2036, + 0x528a, 0x1f3a, + 0x528b, 0x29b4, + 0x528c, 0x22c9, + 0x528d, 0x1f99, + 0x528e, 0x29b5, + 0x5290, 0x129b, + 0x5291, 0x1f75, + 0x5292, 0x29b7, + 0x5293, 0x129c, + 0x5294, 0x29b8, + 0x529b, 0x09ef, + 0x529c, 0x29bf, + 0x529d, 0x0c8b, + 0x529e, 0x03f7, + 0x529f, 0x06ff, + 0x52a0, 0x0846, + 0x52a1, 0x0f00, + 0x52a2, 0x138d, + 0x52a3, 0x0a1c, + 0x52a4, 0x29c0, + 0x52a8, 0x05ee, + 0x52a9, 0x11f9, + 0x52aa, 0x0b6d, + 0x52ab, 0x08aa, + 0x52ac, 0x138e, + 0x52ae, 0x29c4, + 0x52b1, 0x09e3, + 0x52b2, 0x08d1, + 0x52b3, 0x09b8, + 0x52b4, 0x29c7, + 0x52be, 0x1390, + 0x52bf, 0x0d5d, + 0x52c0, 0x29d1, + 0x52c1, 0x1fbe, + 0x52c2, 0x29d2, + 0x52c3, 0x0471, + 0x52c4, 0x29d3, + 0x52c7, 0x10a7, + 0x52c8, 0x29d6, + 0x52c9, 0x0ae8, + 0x52ca, 0x29d7, + 0x52cb, 0x0fd4, + 0x52cc, 0x29d8, + 0x52d0, 0x1392, + 0x52d1, 0x29dc, + 0x52d2, 0x09c0, + 0x52d3, 0x29dd, + 0x52d5, 0x1ecd, + 0x52d6, 0x1393, + 0x52d7, 0x29df, + 0x52d8, 0x093e, + 0x52d9, 0x21a9, + 0x52da, 0x29e0, + 0x52db, 0x21e6, + 0x52dc, 0x29e1, + 0x52dd, 0x2127, + 0x52de, 0x2003, + 0x52df, 0x0b1f, + 0x52e0, 0x29e2, + 0x52e2, 0x2132, + 0x52e3, 0x29e4, + 0x52e4, 0x0c57, + 0x52e5, 0x29e5, + 0x52f0, 0x1394, + 0x52f1, 0x2323, + 0x52f2, 0x29f0, + 0x52f5, 0x2011, + 0x52f6, 0x29f3, + 0x52f8, 0x20f5, + 0x52f9, 0x12fc, + 0x52fa, 0x0d10, + 0x52fb, 0x29f5, + 0x52fe, 0x070d, + 0x52ff, 0x0eff, + 0x5300, 0x110b, + 0x5301, 0x29f8, + 0x5305, 0x0407, + 0x5306, 0x0555, + 0x5307, 0x29fc, + 0x5308, 0x0fa4, + 0x5309, 0x29fd, + 0x530d, 0x12fd, + 0x530e, 0x2a01, + 0x530f, 0x14b5, + 0x5310, 0x12ff, + 0x5311, 0x2a02, + 0x5315, 0x1266, + 0x5316, 0x07c4, + 0x5317, 0x041a, + 0x5318, 0x2a06, + 0x5319, 0x04fc, + 0x531a, 0x1284, + 0x531b, 0x2a07, + 0x531d, 0x1114, + 0x531e, 0x2a09, + 0x5320, 0x0884, + 0x5321, 0x097c, + 0x5322, 0x2a0b, + 0x5323, 0x0f28, + 0x5324, 0x2a0c, + 0x5326, 0x1286, + 0x5327, 0x2a0e, + 0x532a, 0x0668, + 0x532b, 0x2a11, + 0x532d, 0x22c5, + 0x532e, 0x1287, + 0x532f, 0x1f5e, + 0x5330, 0x2a13, + 0x5331, 0x22c6, + 0x5332, 0x2a14, + 0x5339, 0x0bc4, + 0x533a, 0x0c75, + 0x533b, 0x1044, + 0x533c, 0x2a1b, + 0x533e, 0x1288, + 0x533f, 0x0b47, + 0x5340, 0x20ef, + 0x5341, 0x0d45, + 0x5342, 0x2a1d, + 0x5343, 0x0c24, + 0x5344, 0x2a1e, + 0x5345, 0x125c, + 0x5346, 0x2a1f, + 0x5347, 0x0d36, + 0x5348, 0x0ef6, + 0x5349, 0x07f1, + 0x534a, 0x03f6, + 0x534b, 0x2a20, + 0x534e, 0x07bf, + 0x534f, 0x0f78, + 0x5350, 0x2a23, + 0x5351, 0x0419, + 0x5352, 0x1241, + 0x5353, 0x121c, + 0x5354, 0x21d0, + 0x5355, 0x0586, + 0x5356, 0x0a9b, + 0x5357, 0x0b32, + 0x5358, 0x2a24, + 0x535a, 0x0470, + 0x535b, 0x2a26, + 0x535c, 0x047e, + 0x535d, 0x2a27, + 0x535e, 0x044e, + 0x535f, 0x14fa, + 0x5360, 0x115d, + 0x5361, 0x0935, + 0x5362, 0x0a53, + 0x5363, 0x128b, + 0x5364, 0x0a58, + 0x5365, 0x2a28, + 0x5366, 0x128a, + 0x5367, 0x0ee3, + 0x5368, 0x2a29, + 0x5369, 0x1352, + 0x536a, 0x2a2a, + 0x536b, 0x0ecf, + 0x536c, 0x2a2b, + 0x536e, 0x126a, + 0x536f, 0x0ab3, + 0x5370, 0x1086, + 0x5371, 0x0eb2, + 0x5372, 0x2a2d, + 0x5373, 0x0827, + 0x5374, 0x0c8f, + 0x5375, 0x0a78, + 0x5376, 0x2a2e, + 0x5377, 0x091c, + 0x5378, 0x0f81, + 0x5379, 0x2a2f, + 0x537a, 0x1353, + 0x537b, 0x2a30, + 0x537f, 0x0c61, + 0x5380, 0x2a34, + 0x5382, 0x04cc, + 0x5383, 0x2a36, + 0x5384, 0x0631, + 0x5385, 0x0e4f, + 0x5386, 0x09e5, + 0x5387, 0x2a37, + 0x5389, 0x09e2, + 0x538a, 0x2a39, + 0x538b, 0x0fe2, + 0x538c, 0x100a, + 0x538d, 0x127d, + 0x538e, 0x2a3a, + 0x5395, 0x04a5, + 0x5396, 0x2a41, + 0x5398, 0x09d0, + 0x5399, 0x22c1, + 0x539a, 0x07a8, + 0x539b, 0x2a43, + 0x539d, 0x127e, + 0x539e, 0x2a45, + 0x539f, 0x10f0, + 0x53a0, 0x1e64, + 0x53a1, 0x2a46, + 0x53a2, 0x0f4e, + 0x53a3, 0x127f, + 0x53a4, 0x2a47, + 0x53a5, 0x1280, + 0x53a6, 0x0f30, + 0x53a7, 0x2a48, + 0x53a8, 0x051d, + 0x53a9, 0x08f6, + 0x53aa, 0x2a49, + 0x53ad, 0x21f9, + 0x53ae, 0x1281, + 0x53af, 0x2a4c, + 0x53b2, 0x2010, + 0x53b3, 0x2a4f, + 0x53b4, 0x22c2, + 0x53b5, 0x2a50, + 0x53b6, 0x139c, + 0x53b7, 0x2a51, + 0x53bb, 0x0c80, + 0x53bc, 0x2a55, + 0x53bf, 0x0f45, + 0x53c0, 0x2a58, + 0x53c1, 0x0cd9, + 0x53c2, 0x0495, + 0x53c3, 0x1e5a, + 0x53c4, 0x2a59, + 0x53c8, 0x10bb, + 0x53c9, 0x04ad, + 0x53ca, 0x0823, + 0x53cb, 0x10b6, + 0x53cc, 0x0da0, + 0x53cd, 0x0651, + 0x53ce, 0x2a5d, + 0x53d1, 0x063f, + 0x53d2, 0x2a60, + 0x53d4, 0x0d7c, + 0x53d5, 0x2a62, + 0x53d6, 0x0c7c, + 0x53d7, 0x0d73, + 0x53d8, 0x044d, + 0x53d9, 0x0fbb, + 0x53da, 0x2a63, + 0x53db, 0x0b92, + 0x53dc, 0x2a64, + 0x53df, 0x1395, + 0x53e0, 0x05df, + 0x53e1, 0x2a67, + 0x53e2, 0x1ea2, + 0x53e3, 0x0967, + 0x53e4, 0x071e, + 0x53e5, 0x0913, + 0x53e6, 0x0a36, + 0x53e7, 0x2a68, + 0x53e8, 0x14fe, + 0x53e9, 0x14fd, + 0x53ea, 0x11ba, + 0x53eb, 0x08a1, + 0x53ec, 0x117a, + 0x53ed, 0x03d3, + 0x53ee, 0x05e2, + 0x53ef, 0x0956, + 0x53f0, 0x0dfb, + 0x53f1, 0x14fb, + 0x53f2, 0x0d4e, + 0x53f3, 0x10b7, + 0x53f4, 0x2a69, + 0x53f5, 0x1285, + 0x53f6, 0x103d, + 0x53f7, 0x077c, + 0x53f8, 0x0db3, + 0x53f9, 0x0e11, + 0x53fa, 0x2a6a, + 0x53fb, 0x14ff, + 0x53fc, 0x05d1, + 0x53fd, 0x14fc, + 0x53fe, 0x2a6b, + 0x5400, 0x2a6d, + 0x5401, 0x10da, + 0x5402, 0x2a6e, + 0x5403, 0x04f9, + 0x5404, 0x06f2, + 0x5405, 0x2a6f, + 0x5406, 0x1502, + 0x5407, 0x2a70, + 0x5408, 0x0786, + 0x5409, 0x081d, + 0x540a, 0x05d6, + 0x540b, 0x2a71, + 0x540c, 0x0e5d, + 0x540d, 0x0b00, + 0x540e, 0x07aa, + 0x540f, 0x09df, + 0x5410, 0x0e73, + 0x5411, 0x0f5f, + 0x5412, 0x1500, + 0x5413, 0x0f32, + 0x5414, 0x2a72, + 0x5415, 0x0a67, + 0x5416, 0x1501, + 0x5417, 0x0a97, + 0x5418, 0x2a73, + 0x541b, 0x092c, + 0x541c, 0x2a76, + 0x541d, 0x0a28, + 0x541e, 0x0e7d, + 0x541f, 0x107e, + 0x5420, 0x066a, + 0x5421, 0x1509, + 0x5422, 0x2a77, + 0x5423, 0x150c, + 0x5424, 0x2a78, + 0x5426, 0x068e, + 0x5427, 0x03d4, + 0x5428, 0x0615, + 0x5429, 0x0671, + 0x542a, 0x2a7a, + 0x542b, 0x0763, + 0x542c, 0x0e50, + 0x542d, 0x0961, + 0x542e, 0x0da6, + 0x542f, 0x0c13, + 0x5430, 0x2a7b, + 0x5431, 0x11a7, + 0x5432, 0x150d, + 0x5433, 0x2a7c, + 0x5434, 0x0ef1, + 0x5435, 0x04d8, + 0x5436, 0x2a7d, + 0x5438, 0x0f0b, + 0x5439, 0x0538, + 0x543a, 0x2a7f, + 0x543b, 0x0ed6, + 0x543c, 0x07a7, + 0x543d, 0x2a80, + 0x543e, 0x0ef0, + 0x543f, 0x2a81, + 0x5440, 0x0fe6, + 0x5441, 0x2a82, + 0x5443, 0x1508, + 0x5444, 0x2a84, + 0x5446, 0x0577, + 0x5447, 0x2a86, + 0x5448, 0x04ef, + 0x5449, 0x2a87, + 0x544a, 0x06e1, + 0x544b, 0x1503, + 0x544c, 0x2a88, + 0x5450, 0x0b28, + 0x5451, 0x2a8c, + 0x5452, 0x1504, + 0x5455, 0x0b7c, + 0x5456, 0x1507, + 0x5457, 0x150a, + 0x5458, 0x10f4, + 0x5459, 0x150b, + 0x545a, 0x2a8d, + 0x545b, 0x0c37, + 0x545c, 0x0ee7, + 0x545d, 0x2a8e, + 0x5462, 0x0b3b, + 0x5463, 0x2a93, + 0x5464, 0x1512, + 0x5465, 0x2a94, + 0x5466, 0x1517, + 0x5467, 0x2a95, + 0x5468, 0x11db, + 0x5469, 0x2a96, + 0x5471, 0x1511, + 0x5472, 0x1522, + 0x5473, 0x0ec5, + 0x5474, 0x2a9e, + 0x5475, 0x077e, + 0x5476, 0x1516, + 0x5477, 0x1510, + 0x5478, 0x0b9f, + 0x5479, 0x2a9f, + 0x547b, 0x0d24, + 0x547c, 0x07ab, + 0x547d, 0x0b01, + 0x547e, 0x2aa1, + 0x5480, 0x0906, + 0x5481, 0x2aa3, + 0x5482, 0x150e, + 0x5483, 0x2aa4, + 0x5484, 0x1515, + 0x5485, 0x2aa5, + 0x5486, 0x0b99, + 0x5487, 0x2aa6, + 0x548b, 0x1147, + 0x548c, 0x0784, + 0x548d, 0x2aaa, + 0x548e, 0x08fb, + 0x548f, 0x10a2, + 0x5490, 0x06bb, + 0x5491, 0x2aab, + 0x5492, 0x11e3, + 0x5493, 0x2aac, + 0x5494, 0x150f, + 0x5495, 0x0717, + 0x5496, 0x0934, + 0x5497, 0x2aad, + 0x5499, 0x0a45, + 0x549a, 0x1513, + 0x549c, 0x2aaf, + 0x549d, 0x1518, + 0x549e, 0x2ab0, + 0x54a3, 0x1523, + 0x54a4, 0x152d, + 0x54a5, 0x2ab5, + 0x54a6, 0x151f, + 0x54a7, 0x151e, + 0x54a8, 0x1226, + 0x54a9, 0x152b, + 0x54ab, 0x1767, + 0x54ac, 0x102e, + 0x54ad, 0x151a, + 0x54ae, 0x2ab6, + 0x54af, 0x0936, + 0x54b0, 0x2ab7, + 0x54b1, 0x111e, + 0x54b2, 0x2ab8, + 0x54b3, 0x0955, + 0x54b4, 0x151c, + 0x54b5, 0x2ab9, + 0x54b8, 0x0f39, + 0x54b9, 0x2abc, + 0x54bb, 0x1525, + 0x54bc, 0x236d, + 0x54bd, 0x0ff3, + 0x54be, 0x2abe, + 0x54bf, 0x1526, + 0x54c0, 0x03b2, + 0x54c1, 0x0bd6, + 0x54c2, 0x151b, + 0x54c3, 0x2abf, + 0x54c4, 0x079c, + 0x54c5, 0x2ac0, + 0x54c6, 0x061e, + 0x54c7, 0x0e8c, + 0x54c8, 0x0757, + 0x54c9, 0x1118, + 0x54ca, 0x2ac1, + 0x54cc, 0x1527, + 0x54cd, 0x0f59, + 0x54ce, 0x03b0, + 0x54cf, 0x152f, + 0x54d0, 0x1519, + 0x54d1, 0x0fef, + 0x54d2, 0x151d, + 0x54d3, 0x1520, + 0x54d5, 0x1524, + 0x54d6, 0x2ac3, + 0x54d7, 0x07be, + 0x54d8, 0x2ac4, + 0x54d9, 0x1528, + 0x54db, 0x2ac5, + 0x54dc, 0x152a, + 0x54dd, 0x152e, + 0x54de, 0x1530, + 0x54df, 0x1099, + 0x54e0, 0x2ac6, + 0x54e1, 0x2247, + 0x54e2, 0x2ac7, + 0x54e5, 0x06e2, + 0x54e6, 0x0b77, + 0x54e7, 0x1532, + 0x54e8, 0x0d13, + 0x54e9, 0x09f1, + 0x54ea, 0x0b27, + 0x54eb, 0x2aca, + 0x54ed, 0x096b, + 0x54ee, 0x0f65, + 0x54ef, 0x2acc, + 0x54f2, 0x117d, + 0x54f3, 0x1536, + 0x54f4, 0x2acf, + 0x54fa, 0x047f, + 0x54fb, 0x2ad5, + 0x54fc, 0x0796, + 0x54fd, 0x1534, + 0x54fe, 0x2ad6, + 0x54ff, 0x1391, + 0x5500, 0x2ad7, + 0x5501, 0x100d, + 0x5502, 0x2ad8, + 0x5504, 0x236c, + 0x5505, 0x2ada, + 0x5506, 0x0de9, + 0x5507, 0x0540, + 0x5508, 0x2adb, + 0x5509, 0x03b1, + 0x550a, 0x2adc, + 0x550f, 0x1539, + 0x5510, 0x0e19, + 0x5511, 0x153a, + 0x5512, 0x2ae1, + 0x5514, 0x1535, + 0x5515, 0x2ae3, + 0x551b, 0x1531, + 0x551c, 0x2ae9, + 0x5520, 0x1533, + 0x5521, 0x2aed, + 0x5522, 0x1537, + 0x5524, 0x07d2, + 0x5525, 0x2aee, + 0x5527, 0x153b, + 0x5528, 0x2af0, + 0x552a, 0x153c, + 0x552b, 0x2af2, + 0x552c, 0x07b8, + 0x552d, 0x2af3, + 0x552e, 0x0d72, + 0x552f, 0x0eb7, + 0x5530, 0x154d, + 0x5531, 0x04cf, + 0x5532, 0x2af4, + 0x5533, 0x154c, + 0x5534, 0x2af5, + 0x5537, 0x1547, + 0x5538, 0x2af8, + 0x553c, 0x1546, + 0x553d, 0x2afc, + 0x553e, 0x0e8a, + 0x553f, 0x1544, + 0x5540, 0x2afd, + 0x5541, 0x1542, + 0x5542, 0x2afe, + 0x5543, 0x095d, + 0x5544, 0x1221, + 0x5545, 0x2aff, + 0x5546, 0x0d05, + 0x5547, 0x2b00, + 0x5549, 0x1540, + 0x554a, 0x03ac, + 0x554b, 0x2b02, + 0x554f, 0x219c, + 0x5550, 0x1545, + 0x5551, 0x2b06, + 0x5553, 0x20c9, + 0x5554, 0x2b08, + 0x5555, 0x1543, + 0x5556, 0x1548, + 0x5557, 0x2b09, + 0x555c, 0x154e, + 0x555d, 0x2b0e, + 0x555e, 0x21f0, + 0x555f, 0x2b0f, + 0x5561, 0x0665, + 0x5562, 0x2b11, + 0x5564, 0x0bc0, + 0x5565, 0x0cef, + 0x5566, 0x099d, + 0x5567, 0x153d, + 0x5568, 0x2b13, + 0x556a, 0x0b7f, + 0x556b, 0x2b15, + 0x556c, 0x127a, + 0x556d, 0x1541, + 0x556e, 0x0b59, + 0x556f, 0x2b16, + 0x5575, 0x1549, + 0x5578, 0x0f70, + 0x5579, 0x2b1c, + 0x557b, 0x155a, + 0x557c, 0x0e37, + 0x557d, 0x2b1e, + 0x557e, 0x1557, + 0x557f, 0x2b1f, + 0x5580, 0x0933, + 0x5581, 0x1555, + 0x5582, 0x0ec8, + 0x5583, 0x1551, + 0x5584, 0x0cff, + 0x5585, 0x2b20, + 0x5587, 0x0999, + 0x5588, 0x1554, + 0x5589, 0x07a4, + 0x558a, 0x0767, + 0x558b, 0x154f, + 0x558c, 0x2b22, + 0x558f, 0x153e, + 0x5590, 0x2b25, + 0x5591, 0x1559, + 0x5592, 0x2b26, + 0x5594, 0x155e, + 0x5595, 0x2b28, + 0x5598, 0x0530, + 0x5599, 0x155f, + 0x559a, 0x2b2b, + 0x559c, 0x0f1f, + 0x559d, 0x077f, + 0x559e, 0x2b2d, + 0x559f, 0x1556, + 0x55a0, 0x2b2e, + 0x55a7, 0x0fc5, + 0x55a8, 0x2b35, + 0x55aa, 0x210b, + 0x55ab, 0x2b37, + 0x55ac, 0x20de, + 0x55ad, 0x2b38, + 0x55ae, 0x1eaa, + 0x55af, 0x2b39, + 0x55b1, 0x1552, + 0x55b2, 0x222c, + 0x55b3, 0x113e, + 0x55b4, 0x2b3b, + 0x55b5, 0x153f, + 0x55b6, 0x2b3c, + 0x55b7, 0x0ba8, + 0x55b8, 0x2b3d, + 0x55b9, 0x1553, + 0x55ba, 0x2b3e, + 0x55bb, 0x10dc, + 0x55bc, 0x2b3f, + 0x55bd, 0x155c, + 0x55bf, 0x2b40, + 0x55c4, 0x156a, + 0x55c5, 0x0fac, + 0x55c6, 0x20d8, + 0x55c7, 0x22c0, + 0x55c8, 0x2b45, + 0x55c9, 0x1562, + 0x55ca, 0x2b46, + 0x55cc, 0x156f, + 0x55ce, 0x206f, + 0x55cf, 0x2b48, + 0x55d1, 0x1564, + 0x55d2, 0x1550, + 0x55d3, 0x0cdd, + 0x55d4, 0x1567, + 0x55d5, 0x2b4a, + 0x55d6, 0x1558, + 0x55d7, 0x2b4b, + 0x55da, 0x21a1, + 0x55db, 0x2b4e, + 0x55dc, 0x0d5f, + 0x55dd, 0x1569, + 0x55de, 0x2b4f, + 0x55df, 0x155b, + 0x55e0, 0x2b50, + 0x55e1, 0x0eda, + 0x55e2, 0x2b51, + 0x55e3, 0x0db8, + 0x55e4, 0x1573, + 0x55e5, 0x156c, + 0x55e6, 0x1568, + 0x55e7, 0x2b52, + 0x55e8, 0x1571, + 0x55e9, 0x2379, + 0x55ea, 0x1560, + 0x55eb, 0x1565, + 0x55ed, 0x2b53, + 0x55ef, 0x156b, + 0x55f0, 0x2b55, + 0x55f2, 0x156d, + 0x55f4, 0x2b57, + 0x55f5, 0x1572, + 0x55f6, 0x2372, + 0x55f7, 0x1561, + 0x55f8, 0x2b58, + 0x55fd, 0x0dc9, + 0x55fe, 0x157b, + 0x55ff, 0x2b5d, + 0x5600, 0x157c, + 0x5601, 0x1578, + 0x5602, 0x2b5e, + 0x5606, 0x216a, + 0x5607, 0x2b62, + 0x5608, 0x1576, + 0x5609, 0x0841, + 0x560a, 0x2b63, + 0x560c, 0x1577, + 0x560d, 0x237c, + 0x560e, 0x06bd, + 0x560f, 0x127b, + 0x5610, 0x2b65, + 0x5614, 0x20b0, + 0x5615, 0x2b69, + 0x5616, 0x237a, + 0x5617, 0x1e74, + 0x5618, 0x0fb5, + 0x5619, 0x2b6a, + 0x561b, 0x0a96, + 0x561c, 0x2377, + 0x561d, 0x2b6c, + 0x561e, 0x1575, + 0x561f, 0x1563, + 0x5620, 0x2b6d, + 0x5623, 0x157a, + 0x5624, 0x1579, + 0x5625, 0x2b70, + 0x5627, 0x157d, + 0x5628, 0x2b72, + 0x5629, 0x1f4c, + 0x562a, 0x2b73, + 0x562c, 0x1582, + 0x562d, 0x157e, + 0x562e, 0x2378, + 0x562f, 0x21cf, + 0x5630, 0x2368, + 0x5631, 0x11f5, + 0x5632, 0x04d5, + 0x5633, 0x2b75, + 0x5634, 0x1249, + 0x5635, 0x2371, + 0x5636, 0x0db0, + 0x5637, 0x2b76, + 0x5638, 0x2369, + 0x5639, 0x1580, + 0x563a, 0x2b77, + 0x563b, 0x0f0a, + 0x563c, 0x2b78, + 0x563f, 0x0790, + 0x5640, 0x2b7b, + 0x5641, 0x2674, + 0x5642, 0x2b7c, + 0x564c, 0x1587, + 0x564d, 0x1583, + 0x564e, 0x1034, + 0x564f, 0x2b86, + 0x5654, 0x1588, + 0x5655, 0x2b8b, + 0x5657, 0x1581, + 0x5658, 0x157f, + 0x5659, 0x1585, + 0x565a, 0x2b8d, + 0x565c, 0x1586, + 0x565d, 0x236f, + 0x565e, 0x2b8f, + 0x5660, 0x2370, + 0x5661, 0x2b91, + 0x5662, 0x1584, + 0x5663, 0x2b92, + 0x5664, 0x158a, + 0x5665, 0x2376, + 0x5666, 0x2373, + 0x5667, 0x2b93, + 0x5668, 0x0c16, + 0x5669, 0x1262, + 0x566a, 0x112e, + 0x566b, 0x158c, + 0x566c, 0x0d60, + 0x566d, 0x2b94, + 0x566f, 0x237f, + 0x5670, 0x2b96, + 0x5671, 0x158b, + 0x5672, 0x2374, + 0x5673, 0x2b97, + 0x5674, 0x20b5, + 0x5675, 0x2b98, + 0x5676, 0x06bc, + 0x5677, 0x2b99, + 0x5678, 0x1edb, + 0x5679, 0x2672, + 0x567a, 0x2b9a, + 0x567b, 0x158d, + 0x567d, 0x2b9b, + 0x5680, 0x236e, + 0x5681, 0x2b9e, + 0x5685, 0x158f, + 0x5686, 0x1589, + 0x5687, 0x21b7, + 0x5688, 0x2ba2, + 0x568c, 0x2375, + 0x568d, 0x2ba6, + 0x568e, 0x0776, + 0x568f, 0x0e3a, + 0x5690, 0x2ba7, + 0x5693, 0x1590, + 0x5694, 0x2baa, + 0x5695, 0x2382, + 0x5696, 0x2bab, + 0x5699, 0x209e, + 0x569a, 0x2bae, + 0x56a3, 0x0f66, + 0x56a4, 0x2bb7, + 0x56a6, 0x236b, + 0x56a7, 0x2bb9, + 0x56a8, 0x2039, + 0x56a9, 0x2bba, + 0x56ae, 0x269f, + 0x56af, 0x1591, + 0x56b0, 0x2bbf, + 0x56b3, 0x237d, + 0x56b4, 0x21f5, + 0x56b5, 0x2bc2, + 0x56b6, 0x2381, + 0x56b7, 0x0c9d, + 0x56b8, 0x2bc3, + 0x56bc, 0x0891, + 0x56bd, 0x2bc7, + 0x56c0, 0x237b, + 0x56c1, 0x237e, + 0x56c2, 0x21cc, + 0x56c3, 0x2bca, + 0x56c5, 0x22db, + 0x56c6, 0x2bcc, + 0x56c8, 0x236a, + 0x56c9, 0x2689, + 0x56ca, 0x0b35, + 0x56cb, 0x2bce, + 0x56cc, 0x2697, + 0x56cd, 0x2bcf, + 0x56d1, 0x22a1, + 0x56d2, 0x2bd3, + 0x56d4, 0x1592, + 0x56d5, 0x2bd5, + 0x56d7, 0x1593, + 0x56d8, 0x2bd7, + 0x56da, 0x0c71, + 0x56db, 0x0db9, + 0x56dc, 0x2bd9, + 0x56dd, 0x1594, + 0x56de, 0x07ed, + 0x56df, 0x126c, + 0x56e0, 0x1079, + 0x56e1, 0x1595, + 0x56e2, 0x0e76, + 0x56e3, 0x2bda, + 0x56e4, 0x0619, + 0x56e5, 0x2bdb, + 0x56eb, 0x1597, + 0x56ec, 0x2be1, + 0x56ed, 0x10f3, + 0x56ee, 0x2be2, + 0x56f0, 0x0992, + 0x56f1, 0x0554, + 0x56f2, 0x2be4, + 0x56f4, 0x0eb6, + 0x56f5, 0x1596, + 0x56f6, 0x2be6, + 0x56f9, 0x1598, + 0x56fa, 0x0725, + 0x56fb, 0x2be9, + 0x56fd, 0x0753, + 0x56fe, 0x0e6d, + 0x56ff, 0x1599, + 0x5700, 0x2beb, + 0x5703, 0x0bf3, + 0x5704, 0x159a, + 0x5705, 0x2bee, + 0x5706, 0x10f5, + 0x5707, 0x2383, + 0x5708, 0x0c81, + 0x5709, 0x159c, + 0x570a, 0x159b, + 0x570b, 0x1f3d, + 0x570c, 0x2bef, + 0x570d, 0x218f, + 0x570e, 0x2bf0, + 0x5712, 0x2246, + 0x5713, 0x2248, + 0x5714, 0x2bf4, + 0x5716, 0x217e, + 0x5717, 0x2bf6, + 0x5718, 0x2180, + 0x5719, 0x2bf7, + 0x571c, 0x159d, + 0x571d, 0x2bfa, + 0x571f, 0x0e72, + 0x5720, 0x2bfc, + 0x5723, 0x0d3c, + 0x5724, 0x2bff, + 0x5728, 0x111d, + 0x5729, 0x13a7, + 0x572a, 0x13a9, + 0x572b, 0x2c03, + 0x572c, 0x13a8, + 0x572d, 0x0740, + 0x572e, 0x13ac, + 0x5730, 0x05b9, + 0x5731, 0x2c04, + 0x5733, 0x13aa, + 0x5734, 0x2c06, + 0x5739, 0x13ab, + 0x573a, 0x04c6, + 0x573b, 0x13af, + 0x573c, 0x2c0b, + 0x573e, 0x080d, + 0x573f, 0x2c0d, + 0x5740, 0x11b6, + 0x5741, 0x2c0e, + 0x5742, 0x13b0, + 0x5743, 0x2c0f, + 0x5747, 0x0928, + 0x5748, 0x2c13, + 0x574a, 0x0658, + 0x574b, 0x2c15, + 0x574c, 0x13a0, + 0x574d, 0x0e01, + 0x574e, 0x093f, + 0x574f, 0x07ca, + 0x5750, 0x1255, + 0x5751, 0x0960, + 0x5752, 0x2c16, + 0x5757, 0x0976, + 0x5758, 0x2c1b, + 0x575a, 0x0854, + 0x575b, 0x0e06, + 0x575c, 0x13ae, + 0x575d, 0x03de, + 0x575e, 0x0efa, + 0x575f, 0x0675, + 0x5760, 0x1216, + 0x5761, 0x0be1, + 0x5762, 0x2c1d, + 0x5764, 0x098f, + 0x5765, 0x2c1f, + 0x5766, 0x0e0c, + 0x5767, 0x2c20, + 0x5768, 0x13b7, + 0x5769, 0x13b1, + 0x576a, 0x0bd9, + 0x576b, 0x13b3, + 0x576c, 0x2c21, + 0x576d, 0x13b8, + 0x576e, 0x2c22, + 0x576f, 0x0bb8, + 0x5770, 0x2c23, + 0x5773, 0x13ba, + 0x5774, 0x2c26, + 0x5776, 0x13b9, + 0x5777, 0x094d, + 0x5778, 0x2c28, + 0x577b, 0x13b6, + 0x577c, 0x13b5, + 0x577d, 0x2c2b, + 0x5782, 0x053c, + 0x5783, 0x0997, + 0x5784, 0x0a49, + 0x5785, 0x13b2, + 0x5786, 0x13b4, + 0x5787, 0x2c30, + 0x578b, 0x0f98, + 0x578c, 0x13bd, + 0x578d, 0x2c34, + 0x5792, 0x09c8, + 0x5793, 0x13c2, + 0x5794, 0x2c39, + 0x579b, 0x0621, + 0x579c, 0x2c40, + 0x57a0, 0x13c3, + 0x57a1, 0x13a2, + 0x57a2, 0x0711, + 0x57a3, 0x10ee, + 0x57a4, 0x13bc, + 0x57a5, 0x2c44, + 0x57a6, 0x095e, + 0x57a7, 0x13c0, + 0x57a8, 0x2c45, + 0x57a9, 0x13a1, + 0x57aa, 0x2c46, + 0x57ab, 0x05c7, + 0x57ac, 0x2c47, + 0x57ad, 0x13bb, + 0x57ae, 0x0972, + 0x57af, 0x2c48, + 0x57b2, 0x13be, + 0x57b3, 0x2c4b, + 0x57b4, 0x13c1, + 0x57b5, 0x2c4c, + 0x57b8, 0x13c9, + 0x57b9, 0x2c4f, + 0x57c2, 0x06fa, + 0x57c3, 0x03ae, + 0x57c4, 0x2c58, + 0x57cb, 0x0a98, + 0x57cc, 0x2c5f, + 0x57ce, 0x04ec, + 0x57cf, 0x13bf, + 0x57d0, 0x2c61, + 0x57d2, 0x13c8, + 0x57d3, 0x2c63, + 0x57d4, 0x0bf1, + 0x57d5, 0x13c4, + 0x57d6, 0x2c64, + 0x57d8, 0x13c5, + 0x57d9, 0x13c7, + 0x57da, 0x13c6, + 0x57db, 0x2c66, + 0x57dd, 0x13ce, + 0x57de, 0x2c68, + 0x57df, 0x10d7, + 0x57e0, 0x0481, + 0x57e1, 0x232a, + 0x57e2, 0x2c69, + 0x57e4, 0x13cd, + 0x57e5, 0x2c6b, + 0x57ed, 0x13d2, + 0x57ee, 0x2c73, + 0x57ef, 0x13cb, + 0x57f0, 0x2c74, + 0x57f4, 0x13ca, + 0x57f5, 0x2c78, + 0x57f7, 0x228b, + 0x57f8, 0x13cc, + 0x57f9, 0x0ba1, + 0x57fa, 0x080e, + 0x57fb, 0x2c7a, + 0x57fd, 0x13d1, + 0x57fe, 0x2c7c, + 0x5800, 0x13d3, + 0x5801, 0x2c7e, + 0x5802, 0x0e16, + 0x5803, 0x2c7f, + 0x5805, 0x1f85, + 0x5806, 0x0610, + 0x5807, 0x144c, + 0x5808, 0x2c81, + 0x580a, 0x2325, + 0x580b, 0x13cf, + 0x580c, 0x2c83, + 0x580d, 0x13d0, + 0x580e, 0x2c84, + 0x5811, 0x0c32, + 0x5812, 0x2c87, + 0x5815, 0x0628, + 0x5816, 0x232c, + 0x5817, 0x2c8a, + 0x5819, 0x13d5, + 0x581a, 0x2c8c, + 0x581d, 0x232e, + 0x581e, 0x13d4, + 0x581f, 0x2c8f, + 0x5820, 0x13d7, + 0x5821, 0x040d, + 0x5822, 0x2c90, + 0x5824, 0x05ad, + 0x5825, 0x2c92, + 0x582a, 0x093d, + 0x582b, 0x2c97, + 0x582f, 0x2205, + 0x5830, 0x1008, + 0x5831, 0x1e38, + 0x5832, 0x2c9b, + 0x5834, 0x1e73, + 0x5835, 0x0601, + 0x5836, 0x2c9d, + 0x5844, 0x13d6, + 0x5845, 0x2cab, + 0x584a, 0x1fe3, + 0x584b, 0x2339, + 0x584c, 0x0def, + 0x584d, 0x19a3, + 0x584e, 0x2cb0, + 0x584f, 0x232b, + 0x5850, 0x2cb1, + 0x5851, 0x0dd1, + 0x5852, 0x232d, + 0x5853, 0x2cb2, + 0x5854, 0x0df3, + 0x5855, 0x2cb3, + 0x5857, 0x217f, + 0x5858, 0x0e14, + 0x5859, 0x2cb5, + 0x585e, 0x0cd6, + 0x585f, 0x2cba, + 0x5862, 0x21a7, + 0x5863, 0x2cbd, + 0x5864, 0x232f, + 0x5865, 0x13d8, + 0x5866, 0x2cbe, + 0x586b, 0x0e41, + 0x586c, 0x13d9, + 0x586d, 0x2cc3, + 0x5875, 0x1e7d, + 0x5876, 0x2ccb, + 0x5879, 0x20d6, + 0x587a, 0x2cce, + 0x587e, 0x13a3, + 0x587f, 0x2cd2, + 0x5880, 0x13dd, + 0x5881, 0x13da, + 0x5882, 0x2cd3, + 0x5883, 0x08e2, + 0x5884, 0x2cd4, + 0x5885, 0x0d92, + 0x5886, 0x2cd5, + 0x5889, 0x13db, + 0x588a, 0x1ec2, + 0x588b, 0x2cd8, + 0x5892, 0x0d03, + 0x5893, 0x0b1c, + 0x5894, 0x2cdf, + 0x5899, 0x0c3a, + 0x589a, 0x13dc, + 0x589b, 0x2ce4, + 0x589c, 0x22b2, + 0x589d, 0x2ce5, + 0x589e, 0x1139, + 0x589f, 0x0fb1, + 0x58a0, 0x2ce6, + 0x58a8, 0x0b0e, + 0x58a9, 0x0614, + 0x58aa, 0x2cee, + 0x58ae, 0x1edf, + 0x58af, 0x2cf2, + 0x58b3, 0x1ef9, + 0x58b4, 0x2cf6, + 0x58bb, 0x20d9, + 0x58bc, 0x13a4, + 0x58bd, 0x2cfd, + 0x58be, 0x1fdd, + 0x58bf, 0x2cfe, + 0x58c1, 0x0443, + 0x58c2, 0x2d00, + 0x58c5, 0x13a5, + 0x58c6, 0x2d03, + 0x58c7, 0x2167, + 0x58c8, 0x2d04, + 0x58d1, 0x13a6, + 0x58d2, 0x2d0d, + 0x58d3, 0x21ed, + 0x58d4, 0x2d0e, + 0x58d5, 0x0775, + 0x58d6, 0x2d0f, + 0x58d8, 0x2007, + 0x58d9, 0x2326, + 0x58da, 0x2329, + 0x58db, 0x2d11, + 0x58de, 0x1f52, + 0x58df, 0x203b, + 0x58e0, 0x2328, + 0x58e1, 0x2d14, + 0x58e2, 0x2327, + 0x58e3, 0x2d15, + 0x58e4, 0x0c9b, + 0x58e5, 0x2d16, + 0x58e9, 0x1e2b, + 0x58ea, 0x2d1a, + 0x58eb, 0x0d56, + 0x58ec, 0x0ca4, + 0x58ed, 0x2d1b, + 0x58ee, 0x1210, + 0x58ef, 0x22ae, + 0x58f0, 0x0d32, + 0x58f1, 0x2d1c, + 0x58f3, 0x0954, + 0x58f4, 0x2d1e, + 0x58f6, 0x07af, + 0x58f7, 0x2d20, + 0x58f9, 0x1043, + 0x58fa, 0x1f49, + 0x58fb, 0x2d22, + 0x58fd, 0x2138, + 0x58fe, 0x2d24, + 0x5900, 0x2d26, + 0x5902, 0x161c, + 0x5903, 0x2d28, + 0x5904, 0x0529, + 0x5905, 0x2d29, + 0x5907, 0x0421, + 0x5908, 0x2d2b, + 0x590d, 0x06af, + 0x590e, 0x2d30, + 0x590f, 0x0f31, + 0x5910, 0x2d31, + 0x5914, 0x12fb, + 0x5915, 0x0f13, + 0x5916, 0x0e93, + 0x5917, 0x2d35, + 0x5919, 0x1301, + 0x591a, 0x061f, + 0x591b, 0x2d37, + 0x591c, 0x1040, + 0x591d, 0x2d38, + 0x591f, 0x0714, + 0x5920, 0x2d3a, + 0x5922, 0x2081, + 0x5923, 0x2d3c, + 0x5924, 0x161b, + 0x5925, 0x1619, + 0x5926, 0x2d3d, + 0x5927, 0x0576, + 0x5928, 0x2d3e, + 0x5929, 0x0e3f, + 0x592a, 0x0dfe, + 0x592b, 0x068f, + 0x592c, 0x2d3f, + 0x592d, 0x1268, + 0x592e, 0x1014, + 0x592f, 0x0772, + 0x5930, 0x2d40, + 0x5931, 0x0d3e, + 0x5932, 0x2d41, + 0x5934, 0x0e68, + 0x5935, 0x2d43, + 0x5937, 0x104b, + 0x5938, 0x0971, + 0x5939, 0x0843, + 0x593a, 0x0620, + 0x593b, 0x2d45, + 0x593c, 0x14af, + 0x593d, 0x2d46, + 0x593e, 0x1f7c, + 0x593f, 0x2d47, + 0x5941, 0x14b0, + 0x5942, 0x138c, + 0x5943, 0x2d49, + 0x5944, 0x1002, + 0x5945, 0x2d4a, + 0x5947, 0x0c05, + 0x5948, 0x0b31, + 0x5949, 0x068b, + 0x594a, 0x2d4c, + 0x594b, 0x0679, + 0x594c, 0x2d4d, + 0x594e, 0x0989, + 0x594f, 0x123d, + 0x5950, 0x2d4f, + 0x5951, 0x0c14, + 0x5952, 0x2d50, + 0x5954, 0x0425, + 0x5955, 0x14b2, + 0x5956, 0x0882, + 0x5957, 0x0e2a, + 0x5958, 0x14b4, + 0x5959, 0x2d52, + 0x595a, 0x14b3, + 0x595b, 0x2d53, + 0x5960, 0x05cd, + 0x5961, 0x2d58, + 0x5962, 0x0d16, + 0x5963, 0x2d59, + 0x5965, 0x03cd, + 0x5966, 0x2d5b, + 0x5969, 0x235b, + 0x596a, 0x1ede, + 0x596b, 0x2d5e, + 0x596c, 0x1fa2, + 0x596d, 0x2d5f, + 0x596e, 0x1efa, + 0x596f, 0x2d60, + 0x5973, 0x0b6f, + 0x5974, 0x0b6c, + 0x5975, 0x2d64, + 0x5976, 0x0b2f, + 0x5977, 0x2d65, + 0x5978, 0x085c, + 0x5979, 0x0df2, + 0x597a, 0x2d66, + 0x597d, 0x077a, + 0x597e, 0x2d69, + 0x5981, 0x1775, + 0x5982, 0x0cc2, + 0x5983, 0x1776, + 0x5984, 0x0eae, + 0x5985, 0x2d6c, + 0x5986, 0x120e, + 0x5987, 0x06b9, + 0x5988, 0x0a8f, + 0x5989, 0x2d6d, + 0x598a, 0x0cac, + 0x598b, 0x2d6e, + 0x598d, 0x1777, + 0x598e, 0x2d70, + 0x5992, 0x0609, + 0x5993, 0x083e, + 0x5994, 0x2d74, + 0x5996, 0x1026, + 0x5997, 0x177b, + 0x5998, 0x2d76, + 0x5999, 0x0af3, + 0x599a, 0x2d77, + 0x599d, 0x22ad, + 0x599e, 0x177e, + 0x599f, 0x2d7a, + 0x59a3, 0x177a, + 0x59a4, 0x177f, + 0x59a5, 0x0e88, + 0x59a6, 0x2d7e, + 0x59a8, 0x065e, + 0x59a9, 0x1778, + 0x59ab, 0x177d, + 0x59ac, 0x2d80, + 0x59ae, 0x0b40, + 0x59af, 0x1782, + 0x59b0, 0x2d82, + 0x59b2, 0x1781, + 0x59b3, 0x2d84, + 0x59b9, 0x0ac8, + 0x59ba, 0x2d8a, + 0x59bb, 0x0bfd, + 0x59bc, 0x2d8b, + 0x59be, 0x1784, + 0x59bf, 0x2d8d, + 0x59c6, 0x0b1a, + 0x59c7, 0x2d94, + 0x59ca, 0x177c, + 0x59cb, 0x0d53, + 0x59cc, 0x2d97, + 0x59d0, 0x08b4, + 0x59d1, 0x071c, + 0x59d2, 0x1780, + 0x59d3, 0x0fa0, + 0x59d4, 0x0ebe, + 0x59d5, 0x2d9b, + 0x59d7, 0x1783, + 0x59d8, 0x178a, + 0x59d9, 0x2d9d, + 0x59da, 0x102d, + 0x59db, 0x2d9e, + 0x59dc, 0x087b, + 0x59dd, 0x1787, + 0x59de, 0x2d9f, + 0x59e3, 0x1789, + 0x59e4, 0x2da4, + 0x59e5, 0x09bc, + 0x59e6, 0x2da5, + 0x59e8, 0x1053, + 0x59e9, 0x2da7, + 0x59ec, 0x081a, + 0x59ed, 0x2daa, + 0x59f9, 0x178b, + 0x59fa, 0x2db6, + 0x59fb, 0x107d, + 0x59fc, 0x2db7, + 0x59ff, 0x1228, + 0x5a00, 0x2dba, + 0x5a01, 0x0eaf, + 0x5a02, 0x2dbb, + 0x5a03, 0x0e8f, + 0x5a04, 0x0a4d, + 0x5a05, 0x1785, + 0x5a07, 0x0890, + 0x5a08, 0x1788, + 0x5a09, 0x178d, + 0x5a0a, 0x2dbc, + 0x5a0c, 0x178c, + 0x5a0d, 0x2dbe, + 0x5a11, 0x1790, + 0x5a12, 0x2dc2, + 0x5a13, 0x1792, + 0x5a14, 0x2dc3, + 0x5a18, 0x0b52, + 0x5a19, 0x2dc7, + 0x5a1c, 0x0b2b, + 0x5a1d, 0x2dca, + 0x5a1f, 0x0919, + 0x5a20, 0x0d28, + 0x5a21, 0x2dcc, + 0x5a23, 0x1791, + 0x5a24, 0x2dce, + 0x5a25, 0x062f, + 0x5a26, 0x2dcf, + 0x5a29, 0x0ae9, + 0x5a2a, 0x2dd2, + 0x5a31, 0x10ce, + 0x5a32, 0x178e, + 0x5a33, 0x2dd9, + 0x5a34, 0x178f, + 0x5a35, 0x2dda, + 0x5a36, 0x0c7d, + 0x5a37, 0x2ddb, + 0x5a3c, 0x1797, + 0x5a3d, 0x2de0, + 0x5a40, 0x1793, + 0x5a41, 0x203f, + 0x5a42, 0x2de3, + 0x5a46, 0x0be4, + 0x5a47, 0x2de7, + 0x5a49, 0x0ea2, + 0x5a4a, 0x1795, + 0x5a4b, 0x2de9, + 0x5a55, 0x1796, + 0x5a56, 0x2df3, + 0x5a5a, 0x07fe, + 0x5a5b, 0x2df7, + 0x5a62, 0x1798, + 0x5a63, 0x2dfe, + 0x5a66, 0x1f0e, + 0x5a67, 0x1794, + 0x5a68, 0x2e01, + 0x5a6a, 0x09a2, + 0x5a6b, 0x2e03, + 0x5a6d, 0x23f9, + 0x5a6e, 0x2e05, + 0x5a74, 0x1089, + 0x5a75, 0x1799, + 0x5a76, 0x0d2d, + 0x5a77, 0x179d, + 0x5a78, 0x2e0b, + 0x5a7a, 0x179e, + 0x5a7b, 0x2e0d, + 0x5a7f, 0x0fc1, + 0x5a80, 0x2e11, + 0x5a92, 0x0ac2, + 0x5a93, 0x2e23, + 0x5a9a, 0x0ac9, + 0x5a9b, 0x179c, + 0x5a9c, 0x2e2a, + 0x5aa7, 0x23fc, + 0x5aa8, 0x2e35, + 0x5aaa, 0x179b, + 0x5aab, 0x2e37, + 0x5ab2, 0x17a1, + 0x5ab3, 0x0f1e, + 0x5ab4, 0x2e3e, + 0x5ab5, 0x19a4, + 0x5ab6, 0x2e3f, + 0x5ab8, 0x17a4, + 0x5ab9, 0x2e41, + 0x5abd, 0x2069, + 0x5abe, 0x179f, + 0x5abf, 0x2e45, + 0x5ac1, 0x0851, + 0x5ac2, 0x0ce2, + 0x5ac3, 0x2e47, + 0x5ac9, 0x0828, + 0x5aca, 0x2e4d, + 0x5acc, 0x0f40, + 0x5acd, 0x2e4f, + 0x5ad2, 0x17a2, + 0x5ad3, 0x2e54, + 0x5ad4, 0x17a3, + 0x5ad5, 0x2e55, + 0x5ad6, 0x17a8, + 0x5ad7, 0x23f7, + 0x5ad8, 0x17aa, + 0x5ad9, 0x2e56, + 0x5adc, 0x17ab, + 0x5add, 0x2e59, + 0x5ae0, 0x17a5, + 0x5ae1, 0x05b6, + 0x5ae2, 0x2e5c, + 0x5ae3, 0x17a6, + 0x5ae4, 0x2e5d, + 0x5ae6, 0x17a9, + 0x5ae7, 0x2e5f, + 0x5ae9, 0x0b3e, + 0x5aea, 0x2e61, + 0x5aeb, 0x17a0, + 0x5aec, 0x2e62, + 0x5af1, 0x17a7, + 0x5af2, 0x2e67, + 0x5af5, 0x23f6, + 0x5af6, 0x2e6a, + 0x5afb, 0x23fd, + 0x5afc, 0x2e6f, + 0x5b00, 0x23f8, + 0x5b01, 0x2e73, + 0x5b08, 0x23fa, + 0x5b09, 0x17ac, + 0x5b0a, 0x2e7a, + 0x5b0b, 0x23fe, + 0x5b0c, 0x1fa8, + 0x5b0d, 0x2e7b, + 0x5b16, 0x17ae, + 0x5b17, 0x17ad, + 0x5b18, 0x2e84, + 0x5b19, 0x2401, + 0x5b1a, 0x2e85, + 0x5b21, 0x23ff, + 0x5b22, 0x2e8c, + 0x5b2a, 0x2400, + 0x5b2b, 0x2e94, + 0x5b30, 0x2221, + 0x5b31, 0x2e99, + 0x5b32, 0x17af, + 0x5b33, 0x2e9a, + 0x5b34, 0x130c, + 0x5b35, 0x2e9b, + 0x5b37, 0x17b0, + 0x5b38, 0x2122, + 0x5b39, 0x2e9d, + 0x5b40, 0x17b1, + 0x5b41, 0x2ea4, + 0x5b4c, 0x23fb, + 0x5b4d, 0x2eaf, + 0x5b50, 0x1230, + 0x5b51, 0x17b7, + 0x5b52, 0x2eb2, + 0x5b53, 0x17b8, + 0x5b54, 0x0964, + 0x5b55, 0x1113, + 0x5b56, 0x2eb3, + 0x5b57, 0x1233, + 0x5b58, 0x0569, + 0x5b59, 0x0de4, + 0x5b5a, 0x17b4, + 0x5b5b, 0x1279, + 0x5b5c, 0x122b, + 0x5b5d, 0x0f6d, + 0x5b5e, 0x2eb4, + 0x5b5f, 0x0ad4, + 0x5b60, 0x2eb5, + 0x5b62, 0x17b9, + 0x5b63, 0x0831, + 0x5b64, 0x071b, + 0x5b65, 0x17b5, + 0x5b66, 0x0fd0, + 0x5b67, 0x2eb7, + 0x5b69, 0x0759, + 0x5b6a, 0x0a76, + 0x5b6b, 0x215a, + 0x5b6c, 0x1261, + 0x5b6d, 0x2eb9, + 0x5b70, 0x0d82, + 0x5b71, 0x176a, + 0x5b72, 0x2ebc, + 0x5b73, 0x17b6, + 0x5b74, 0x2ebd, + 0x5b75, 0x0692, + 0x5b76, 0x2ebe, + 0x5b78, 0x21e5, + 0x5b79, 0x2ec0, + 0x5b7a, 0x0cc1, + 0x5b7b, 0x2ec1, + 0x5b7d, 0x0b58, + 0x5b7e, 0x2ec3, + 0x5b7f, 0x2057, + 0x5b80, 0x172e, + 0x5b81, 0x0b61, + 0x5b82, 0x2ec4, + 0x5b83, 0x0df1, + 0x5b84, 0x172f, + 0x5b85, 0x114d, + 0x5b86, 0x2ec5, + 0x5b87, 0x10d3, + 0x5b88, 0x0d6f, + 0x5b89, 0x03bd, + 0x5b8a, 0x2ec6, + 0x5b8b, 0x0dc3, + 0x5b8c, 0x0e9b, + 0x5b8d, 0x2ec7, + 0x5b8f, 0x07a1, + 0x5b90, 0x2ec9, + 0x5b93, 0x1731, + 0x5b94, 0x2ecc, + 0x5b95, 0x1730, + 0x5b96, 0x2ecd, + 0x5b97, 0x1237, + 0x5b98, 0x0732, + 0x5b99, 0x11e5, + 0x5b9a, 0x05e7, + 0x5b9b, 0x0ea1, + 0x5b9c, 0x1052, + 0x5b9d, 0x040f, + 0x5b9e, 0x0d4c, + 0x5b9f, 0x2ece, + 0x5ba0, 0x050d, + 0x5ba1, 0x0d2c, + 0x5ba2, 0x095a, + 0x5ba3, 0x0fc6, + 0x5ba4, 0x0d69, + 0x5ba5, 0x1732, + 0x5ba6, 0x07d7, + 0x5ba7, 0x2ecf, + 0x5baa, 0x0f49, + 0x5bab, 0x0705, + 0x5bac, 0x2ed2, + 0x5bb0, 0x111a, + 0x5bb1, 0x2ed6, + 0x5bb3, 0x075d, + 0x5bb4, 0x1010, + 0x5bb5, 0x0f69, + 0x5bb6, 0x0845, + 0x5bb7, 0x2ed8, + 0x5bb8, 0x1733, + 0x5bb9, 0x0cb8, + 0x5bba, 0x2ed9, + 0x5bbd, 0x097a, + 0x5bbe, 0x045f, + 0x5bbf, 0x0dd3, + 0x5bc0, 0x2edc, + 0x5bc2, 0x0838, + 0x5bc3, 0x2ede, + 0x5bc4, 0x0837, + 0x5bc5, 0x1081, + 0x5bc6, 0x0ae1, + 0x5bc7, 0x0969, + 0x5bc8, 0x2edf, + 0x5bcc, 0x06b6, + 0x5bcd, 0x2ee3, + 0x5bd0, 0x0ac7, + 0x5bd1, 0x2ee6, + 0x5bd2, 0x0765, + 0x5bd3, 0x10e5, + 0x5bd4, 0x2ee7, + 0x5bdd, 0x0c5b, + 0x5bde, 0x0b12, + 0x5bdf, 0x04b3, + 0x5be0, 0x2ef0, + 0x5be1, 0x072a, + 0x5be2, 0x20e5, + 0x5be3, 0x2ef1, + 0x5be4, 0x1737, + 0x5be5, 0x0a11, + 0x5be6, 0x212f, + 0x5be7, 0x20a3, + 0x5be8, 0x1150, + 0x5be9, 0x2121, + 0x5bea, 0x2ef2, + 0x5beb, 0x21d4, + 0x5bec, 0x1fe5, + 0x5bed, 0x2ef3, + 0x5bee, 0x1738, + 0x5bef, 0x2ef4, + 0x5bf0, 0x173a, + 0x5bf1, 0x2ef5, + 0x5bf5, 0x1e8a, + 0x5bf6, 0x1e37, + 0x5bf7, 0x2ef9, + 0x5bf8, 0x056a, + 0x5bf9, 0x0613, + 0x5bfa, 0x0db7, + 0x5bfb, 0x0fd9, + 0x5bfc, 0x059d, + 0x5bfd, 0x2efa, + 0x5bff, 0x0d70, + 0x5c00, 0x2efc, + 0x5c01, 0x067f, + 0x5c02, 0x2efd, + 0x5c04, 0x0d1d, + 0x5c05, 0x2eff, + 0x5c06, 0x087c, + 0x5c07, 0x1f9e, + 0x5c08, 0x22a6, + 0x5c09, 0x0ecd, + 0x5c0a, 0x124d, + 0x5c0b, 0x21e8, + 0x5c0c, 0x2f00, + 0x5c0d, 0x1eda, + 0x5c0e, 0x1eb9, + 0x5c0f, 0x0f6c, + 0x5c10, 0x2f01, + 0x5c11, 0x0d12, + 0x5c12, 0x2f02, + 0x5c14, 0x063a, + 0x5c15, 0x17b2, + 0x5c16, 0x0855, + 0x5c17, 0x2f04, + 0x5c18, 0x04e3, + 0x5c19, 0x2f05, + 0x5c1a, 0x0d09, + 0x5c1b, 0x2f06, + 0x5c1c, 0x17b3, + 0x5c1d, 0x04c7, + 0x5c1e, 0x2f07, + 0x5c22, 0x14b6, + 0x5c23, 0x2f0b, + 0x5c24, 0x10ad, + 0x5c25, 0x14b7, + 0x5c26, 0x2f0c, + 0x5c27, 0x1029, + 0x5c28, 0x2f0d, + 0x5c2c, 0x14b8, + 0x5c2d, 0x2f11, + 0x5c31, 0x08fc, + 0x5c32, 0x2f15, + 0x5c34, 0x14b9, + 0x5c35, 0x2f17, + 0x5c37, 0x235c, + 0x5c38, 0x0d43, + 0x5c39, 0x1083, + 0x5c3a, 0x0504, + 0x5c3b, 0x1766, + 0x5c3c, 0x0b44, + 0x5c3d, 0x08d0, + 0x5c3e, 0x0ec1, + 0x5c3f, 0x0b55, + 0x5c40, 0x0905, + 0x5c41, 0x0bc7, + 0x5c42, 0x04aa, + 0x5c43, 0x2f19, + 0x5c45, 0x0902, + 0x5c46, 0x2f1b, + 0x5c48, 0x0c79, + 0x5c49, 0x0e3e, + 0x5c4a, 0x08bd, + 0x5c4b, 0x0eec, + 0x5c4c, 0x2f1d, + 0x5c4e, 0x0d51, + 0x5c4f, 0x0be0, + 0x5c50, 0x1768, + 0x5c51, 0x0f87, + 0x5c52, 0x2f1f, + 0x5c55, 0x115a, + 0x5c56, 0x2f22, + 0x5c59, 0x1769, + 0x5c5a, 0x2f25, + 0x5c5e, 0x0d8b, + 0x5c5f, 0x2f29, + 0x5c60, 0x0e71, + 0x5c61, 0x0a6c, + 0x5c62, 0x2050, + 0x5c63, 0x176b, + 0x5c64, 0x1e67, + 0x5c65, 0x0a6b, + 0x5c66, 0x176c, + 0x5c67, 0x2f2a, + 0x5c68, 0x23f4, + 0x5c69, 0x2f2b, + 0x5c6c, 0x213e, + 0x5c6d, 0x2f2e, + 0x5c6e, 0x1774, + 0x5c6f, 0x0e7e, + 0x5c70, 0x2f2f, + 0x5c71, 0x0cf6, + 0x5c72, 0x2f30, + 0x5c79, 0x1060, + 0x5c7a, 0x15ac, + 0x5c7b, 0x2f37, + 0x5c7f, 0x10d1, + 0x5c80, 0x2f3b, + 0x5c81, 0x0ddf, + 0x5c82, 0x0c10, + 0x5c83, 0x2f3c, + 0x5c88, 0x15b0, + 0x5c89, 0x2f41, + 0x5c8c, 0x15ab, + 0x5c8d, 0x15ad, + 0x5c8e, 0x2f44, + 0x5c90, 0x15ae, + 0x5c91, 0x15b3, + 0x5c92, 0x2f46, + 0x5c94, 0x04b4, + 0x5c95, 0x2f48, + 0x5c96, 0x15af, + 0x5c97, 0x06d5, + 0x5c98, 0x15b1, + 0x5c9a, 0x15b4, + 0x5c9b, 0x059b, + 0x5c9c, 0x15b5, + 0x5c9d, 0x2f49, + 0x5ca1, 0x1f16, + 0x5ca2, 0x15b7, + 0x5ca3, 0x15bc, + 0x5ca4, 0x2f4d, + 0x5ca9, 0x0ffb, + 0x5caa, 0x2f52, + 0x5cab, 0x15ba, + 0x5cac, 0x15b9, + 0x5cad, 0x0a34, + 0x5cae, 0x2f53, + 0x5cb1, 0x15bb, + 0x5cb2, 0x2f56, + 0x5cb3, 0x1103, + 0x5cb4, 0x2f57, + 0x5cb5, 0x15b6, + 0x5cb6, 0x2f58, + 0x5cb7, 0x15be, + 0x5cb8, 0x03c1, + 0x5cb9, 0x2f59, + 0x5cbd, 0x15b8, + 0x5cbe, 0x2f5d, + 0x5cbf, 0x0986, + 0x5cc0, 0x2f5e, + 0x5cc1, 0x15bd, + 0x5cc2, 0x2f5f, + 0x5cc4, 0x15bf, + 0x5cc5, 0x2f61, + 0x5ccb, 0x15c2, + 0x5ccc, 0x2f67, + 0x5cd2, 0x15c0, + 0x5cd3, 0x2f6d, + 0x5cd9, 0x11c4, + 0x5cda, 0x2f73, + 0x5ce1, 0x0f2c, + 0x5ce2, 0x2f7a, + 0x5ce4, 0x15c1, + 0x5ce5, 0x15c3, + 0x5ce6, 0x0a74, + 0x5ce7, 0x2f7c, + 0x5ce8, 0x062a, + 0x5ce9, 0x2f7d, + 0x5cea, 0x10dd, + 0x5ceb, 0x2f7e, + 0x5ced, 0x0c4a, + 0x5cee, 0x2f80, + 0x5cf0, 0x0682, + 0x5cf1, 0x2f82, + 0x5cf4, 0x2389, + 0x5cf5, 0x2f85, + 0x5cf6, 0x1eb7, + 0x5cf7, 0x2f86, + 0x5cfb, 0x092d, + 0x5cfc, 0x2f8a, + 0x5cfd, 0x21b4, + 0x5cfe, 0x2f8b, + 0x5d00, 0x2f8d, + 0x5d02, 0x15c4, + 0x5d04, 0x2f8f, + 0x5d06, 0x15cb, + 0x5d07, 0x050c, + 0x5d08, 0x2f91, + 0x5d0d, 0x238f, + 0x5d0e, 0x0c08, + 0x5d0f, 0x2f96, + 0x5d14, 0x0561, + 0x5d15, 0x2f9b, + 0x5d16, 0x0feb, + 0x5d17, 0x1f1a, + 0x5d18, 0x2f9c, + 0x5d1b, 0x15cc, + 0x5d1c, 0x2f9f, + 0x5d1e, 0x15ca, + 0x5d1f, 0x2fa1, + 0x5d24, 0x15c9, + 0x5d25, 0x2fa6, + 0x5d26, 0x15c7, + 0x5d27, 0x15c6, + 0x5d28, 0x2fa7, + 0x5d29, 0x0429, + 0x5d2a, 0x2fa8, + 0x5d2c, 0x238b, + 0x5d2d, 0x1159, + 0x5d2e, 0x15c8, + 0x5d2f, 0x2faa, + 0x5d34, 0x15cf, + 0x5d35, 0x2faf, + 0x5d3d, 0x15d0, + 0x5d3e, 0x15ce, + 0x5d3f, 0x2fb7, + 0x5d47, 0x1b22, + 0x5d48, 0x2fbf, + 0x5d4a, 0x15d7, + 0x5d4b, 0x15d6, + 0x5d4c, 0x0c33, + 0x5d4d, 0x2fc1, + 0x5d50, 0x238a, + 0x5d51, 0x2fc4, + 0x5d58, 0x15cd, + 0x5d59, 0x2fcb, + 0x5d5b, 0x15d2, + 0x5d5c, 0x2fcd, + 0x5d5d, 0x15d4, + 0x5d5e, 0x2fce, + 0x5d69, 0x15d8, + 0x5d6a, 0x2fd9, + 0x5d6b, 0x15d5, + 0x5d6c, 0x15d1, + 0x5d6d, 0x2fda, + 0x5d6f, 0x15d3, + 0x5d70, 0x2fdc, + 0x5d74, 0x15d9, + 0x5d75, 0x2fe0, + 0x5d81, 0x2391, + 0x5d82, 0x15da, + 0x5d83, 0x2fec, + 0x5d84, 0x2271, + 0x5d85, 0x2fed, + 0x5d87, 0x2388, + 0x5d88, 0x2fef, + 0x5d97, 0x238e, + 0x5d98, 0x2ffe, + 0x5d99, 0x15db, + 0x5d9a, 0x2fff, + 0x5d9d, 0x15dc, + 0x5d9e, 0x3002, + 0x5da0, 0x238d, + 0x5da1, 0x3004, + 0x5da7, 0x238c, + 0x5da8, 0x300a, + 0x5db7, 0x15de, + 0x5db8, 0x2390, + 0x5db9, 0x3019, + 0x5dba, 0x2033, + 0x5dbb, 0x301a, + 0x5dbc, 0x223c, + 0x5dbd, 0x301b, + 0x5dc5, 0x15df, + 0x5dc6, 0x3023, + 0x5dcb, 0x1fe9, + 0x5dcc, 0x3028, + 0x5dcd, 0x0eb0, + 0x5dce, 0x3029, + 0x5dd2, 0x2055, + 0x5dd3, 0x302d, + 0x5dd4, 0x2392, + 0x5dd5, 0x302e, + 0x5ddb, 0x1815, + 0x5ddc, 0x3034, + 0x5ddd, 0x052b, + 0x5dde, 0x11dc, + 0x5ddf, 0x3035, + 0x5de1, 0x0fdb, + 0x5de2, 0x04d7, + 0x5de3, 0x3037, + 0x5de5, 0x06fd, + 0x5de6, 0x1250, + 0x5de7, 0x0c46, + 0x5de8, 0x090d, + 0x5de9, 0x0707, + 0x5dea, 0x3039, + 0x5deb, 0x0ee6, + 0x5dec, 0x303a, + 0x5dee, 0x04b5, + 0x5def, 0x139f, + 0x5df0, 0x2324, + 0x5df1, 0x082d, + 0x5df2, 0x1058, + 0x5df3, 0x0dbd, + 0x5df4, 0x03d8, + 0x5df5, 0x303c, + 0x5df7, 0x0f5c, + 0x5df8, 0x303e, + 0x5dfd, 0x12f7, + 0x5dfe, 0x08be, + 0x5dff, 0x3043, + 0x5e00, 0x3044, + 0x5e01, 0x043b, + 0x5e02, 0x0d67, + 0x5e03, 0x0483, + 0x5e04, 0x3045, + 0x5e05, 0x0d9c, + 0x5e06, 0x0648, + 0x5e07, 0x3046, + 0x5e08, 0x0d3d, + 0x5e09, 0x3047, + 0x5e0c, 0x0f10, + 0x5e0d, 0x304a, + 0x5e0f, 0x159e, + 0x5e10, 0x116b, + 0x5e11, 0x15a1, + 0x5e12, 0x304c, + 0x5e14, 0x15a0, + 0x5e15, 0x0b82, + 0x5e16, 0x0e4e, + 0x5e17, 0x304e, + 0x5e18, 0x09fa, + 0x5e19, 0x159f, + 0x5e1a, 0x11e2, + 0x5e1b, 0x0476, + 0x5e1c, 0x11c3, + 0x5e1d, 0x05bc, + 0x5e1e, 0x304f, + 0x5e25, 0x2143, + 0x5e26, 0x057b, + 0x5e27, 0x11a0, + 0x5e28, 0x3056, + 0x5e2b, 0x2129, + 0x5e2c, 0x3059, + 0x5e2d, 0x0f1c, + 0x5e2e, 0x03fa, + 0x5e2f, 0x305a, + 0x5e31, 0x15a2, + 0x5e32, 0x305c, + 0x5e33, 0x2277, + 0x5e34, 0x305d, + 0x5e36, 0x1ea7, + 0x5e37, 0x15a5, + 0x5e38, 0x04c8, + 0x5e39, 0x305f, + 0x5e3b, 0x15a3, + 0x5e3d, 0x0ab6, + 0x5e3e, 0x3061, + 0x5e40, 0x2285, + 0x5e41, 0x3063, + 0x5e42, 0x0ae2, + 0x5e43, 0x2384, + 0x5e44, 0x15a6, + 0x5e45, 0x0696, + 0x5e46, 0x3064, + 0x5e4c, 0x07e4, + 0x5e4d, 0x306a, + 0x5e54, 0x15a7, + 0x5e55, 0x0b1e, + 0x5e56, 0x3071, + 0x5e57, 0x2387, + 0x5e58, 0x2386, + 0x5e59, 0x3072, + 0x5e5b, 0x15a8, + 0x5e5c, 0x3074, + 0x5e5e, 0x15a9, + 0x5e5f, 0x2290, + 0x5e60, 0x3076, + 0x5e61, 0x15aa, + 0x5e62, 0x0534, + 0x5e63, 0x1e44, + 0x5e64, 0x3077, + 0x5e6b, 0x1e32, + 0x5e6c, 0x2385, + 0x5e6d, 0x307e, + 0x5e72, 0x06c4, + 0x5e73, 0x0bdc, + 0x5e74, 0x0b4d, + 0x5e75, 0x3083, + 0x5e76, 0x0469, + 0x5e77, 0x3084, + 0x5e78, 0x0f9d, + 0x5e79, 0x1f13, + 0x5e7a, 0x1813, + 0x5e7b, 0x07d8, + 0x5e7c, 0x10bc, + 0x5e7d, 0x10a9, + 0x5e7e, 0x1f73, + 0x5e7f, 0x073c, + 0x5e80, 0x1631, + 0x5e81, 0x3085, + 0x5e84, 0x120c, + 0x5e85, 0x3088, + 0x5e86, 0x0c69, + 0x5e87, 0x043c, + 0x5e88, 0x3089, + 0x5e8a, 0x0535, + 0x5e8b, 0x1633, + 0x5e8c, 0x308b, + 0x5e8f, 0x0fbd, + 0x5e90, 0x0a55, + 0x5e91, 0x1632, + 0x5e92, 0x308e, + 0x5e93, 0x096f, + 0x5e94, 0x108b, + 0x5e95, 0x05b8, + 0x5e96, 0x1634, + 0x5e97, 0x05cb, + 0x5e98, 0x308f, + 0x5e99, 0x0af2, + 0x5e9a, 0x06f8, + 0x5e9b, 0x3090, + 0x5e9c, 0x06a9, + 0x5e9d, 0x3091, + 0x5e9e, 0x0b94, + 0x5e9f, 0x066c, + 0x5ea0, 0x1636, + 0x5ea1, 0x3092, + 0x5ea5, 0x1635, + 0x5ea6, 0x0607, + 0x5ea7, 0x1256, + 0x5ea8, 0x3096, + 0x5eab, 0x1fe0, + 0x5eac, 0x3099, + 0x5ead, 0x0e56, + 0x5eae, 0x309a, + 0x5eb3, 0x163a, + 0x5eb4, 0x309f, + 0x5eb5, 0x1638, + 0x5eb6, 0x0d93, + 0x5eb7, 0x0942, + 0x5eb8, 0x109e, + 0x5eb9, 0x1637, + 0x5eba, 0x30a0, + 0x5ebe, 0x1639, + 0x5ebf, 0x30a4, + 0x5ec9, 0x09f7, + 0x5eca, 0x09b3, + 0x5ecb, 0x30ae, + 0x5ed1, 0x163d, + 0x5ed2, 0x163c, + 0x5ed3, 0x0995, + 0x5ed4, 0x30b4, + 0x5ed6, 0x0a17, + 0x5ed7, 0x30b6, + 0x5edb, 0x163e, + 0x5edc, 0x30ba, + 0x5edf, 0x2087, + 0x5ee0, 0x1e78, + 0x5ee1, 0x23ae, + 0x5ee2, 0x1ef6, + 0x5ee3, 0x1f31, + 0x5ee4, 0x30bd, + 0x5ee8, 0x163f, + 0x5ee9, 0x30c1, + 0x5eea, 0x1640, + 0x5eeb, 0x30c2, + 0x5eec, 0x2045, + 0x5eed, 0x30c3, + 0x5ef3, 0x2178, + 0x5ef4, 0x1398, + 0x5ef5, 0x30c9, + 0x5ef6, 0x0ffc, + 0x5ef7, 0x0e53, + 0x5ef8, 0x30ca, + 0x5efa, 0x0879, + 0x5efb, 0x30cc, + 0x5efe, 0x14ad, + 0x5eff, 0x125b, + 0x5f00, 0x0937, + 0x5f01, 0x139d, + 0x5f02, 0x1073, + 0x5f03, 0x0c19, + 0x5f04, 0x0b6b, + 0x5f05, 0x30cf, + 0x5f08, 0x14ae, + 0x5f09, 0x30d2, + 0x5f0a, 0x0440, + 0x5f0b, 0x14f6, + 0x5f0c, 0x30d3, + 0x5f0f, 0x0d54, + 0x5f10, 0x30d6, + 0x5f11, 0x14f9, + 0x5f12, 0x30d7, + 0x5f13, 0x0706, + 0x5f14, 0x30d8, + 0x5f15, 0x1084, + 0x5f16, 0x30d9, + 0x5f17, 0x06a0, + 0x5f18, 0x07a2, + 0x5f19, 0x30da, + 0x5f1b, 0x04ff, + 0x5f1c, 0x30dc, + 0x5f1f, 0x05bd, + 0x5f20, 0x1166, + 0x5f21, 0x30df, + 0x5f25, 0x0adb, + 0x5f26, 0x0f3f, + 0x5f27, 0x07b6, + 0x5f28, 0x30e3, + 0x5f29, 0x176f, + 0x5f2a, 0x176e, + 0x5f2b, 0x30e4, + 0x5f2d, 0x1770, + 0x5f2e, 0x30e6, + 0x5f2f, 0x0e95, + 0x5f30, 0x30e7, + 0x5f31, 0x0cd0, + 0x5f32, 0x30e8, + 0x5f33, 0x23f5, + 0x5f34, 0x30e9, + 0x5f35, 0x2275, + 0x5f36, 0x30ea, + 0x5f39, 0x0590, + 0x5f3a, 0x0c3c, + 0x5f3b, 0x30ed, + 0x5f3c, 0x1772, + 0x5f3d, 0x30ee, + 0x5f40, 0x19be, + 0x5f41, 0x30f1, + 0x5f46, 0x266e, + 0x5f47, 0x30f6, + 0x5f48, 0x1eb0, + 0x5f49, 0x30f7, + 0x5f4c, 0x2083, + 0x5f4d, 0x30fa, + 0x5f4e, 0x2188, + 0x5f4f, 0x30fb, + 0x5f50, 0x1762, + 0x5f51, 0x30fc, + 0x5f52, 0x0742, + 0x5f53, 0x0592, + 0x5f54, 0x30fd, + 0x5f55, 0x0a63, + 0x5f56, 0x1764, + 0x5f57, 0x1763, + 0x5f58, 0x1765, + 0x5f59, 0x267c, + 0x5f5a, 0x30fe, + 0x5f5d, 0x1054, + 0x5f5e, 0x3101, + 0x5f61, 0x15ee, + 0x5f62, 0x0f99, + 0x5f63, 0x3104, + 0x5f64, 0x0e5f, + 0x5f65, 0x3105, + 0x5f66, 0x100e, + 0x5f67, 0x3106, + 0x5f69, 0x0491, + 0x5f6a, 0x0454, + 0x5f6b, 0x3108, + 0x5f6c, 0x045b, + 0x5f6d, 0x0bae, + 0x5f6e, 0x3109, + 0x5f70, 0x1164, + 0x5f71, 0x1095, + 0x5f72, 0x310b, + 0x5f73, 0x15e0, + 0x5f74, 0x310c, + 0x5f77, 0x15e1, + 0x5f78, 0x310f, + 0x5f79, 0x1062, + 0x5f7a, 0x3110, + 0x5f7b, 0x04de, + 0x5f7c, 0x0434, + 0x5f7d, 0x3111, + 0x5f80, 0x0eaa, + 0x5f81, 0x1198, + 0x5f82, 0x15e2, + 0x5f83, 0x3114, + 0x5f84, 0x08e5, + 0x5f85, 0x0580, + 0x5f86, 0x3115, + 0x5f87, 0x15e3, + 0x5f88, 0x0793, + 0x5f89, 0x15e4, + 0x5f8a, 0x07c7, + 0x5f8b, 0x0a70, + 0x5f8c, 0x15e5, + 0x5f8d, 0x3116, + 0x5f90, 0x0fb7, + 0x5f91, 0x1fc5, + 0x5f92, 0x0e6e, + 0x5f93, 0x3119, + 0x5f95, 0x15e6, + 0x5f96, 0x311b, + 0x5f97, 0x05a4, + 0x5f98, 0x0b88, + 0x5f99, 0x15e7, + 0x5f9a, 0x311c, + 0x5f9c, 0x15e8, + 0x5f9d, 0x311e, + 0x5f9e, 0x1ea1, + 0x5f9f, 0x311f, + 0x5fa0, 0x2393, + 0x5fa1, 0x10de, + 0x5fa2, 0x3120, + 0x5fa8, 0x15e9, + 0x5fa9, 0x1f0b, + 0x5faa, 0x0fd6, + 0x5fab, 0x3126, + 0x5fad, 0x15ea, + 0x5fae, 0x0eb1, + 0x5faf, 0x3128, + 0x5fb5, 0x15eb, + 0x5fb6, 0x312e, + 0x5fb7, 0x05a3, + 0x5fb8, 0x312f, + 0x5fb9, 0x1e7c, + 0x5fba, 0x3130, + 0x5fbc, 0x15ec, + 0x5fbd, 0x07ea, + 0x5fbe, 0x3132, + 0x5fc3, 0x0f8f, + 0x5fc4, 0x1642, + 0x5fc5, 0x0441, + 0x5fc6, 0x106b, + 0x5fc7, 0x3137, + 0x5fc9, 0x1643, + 0x5fca, 0x3139, + 0x5fcc, 0x083c, + 0x5fcd, 0x0ca7, + 0x5fce, 0x313b, + 0x5fcf, 0x1645, + 0x5fd0, 0x1a0c, + 0x5fd1, 0x1a0b, + 0x5fd2, 0x14f7, + 0x5fd3, 0x313c, + 0x5fd6, 0x1644, + 0x5fd7, 0x11bd, + 0x5fd8, 0x0ead, + 0x5fd9, 0x0aab, + 0x5fda, 0x313f, + 0x5fdd, 0x1683, + 0x5fde, 0x3142, + 0x5fe0, 0x11d1, + 0x5fe1, 0x1649, + 0x5fe2, 0x3144, + 0x5fe4, 0x164a, + 0x5fe5, 0x3146, + 0x5fe7, 0x10ac, + 0x5fe8, 0x3148, + 0x5fea, 0x164e, + 0x5feb, 0x0979, + 0x5fec, 0x314a, + 0x5fed, 0x164f, + 0x5fee, 0x1647, + 0x5fef, 0x314b, + 0x5ff1, 0x04e5, + 0x5ff2, 0x314d, + 0x5ff5, 0x0b51, + 0x5ff6, 0x3150, + 0x5ff8, 0x1650, + 0x5ff9, 0x3152, + 0x5ffb, 0x0f8e, + 0x5ffc, 0x3154, + 0x5ffd, 0x07ad, + 0x5ffe, 0x164b, + 0x5fff, 0x067b, + 0x6000, 0x07c8, + 0x6001, 0x0dff, + 0x6002, 0x0dc0, + 0x6003, 0x1646, + 0x6004, 0x1648, + 0x6005, 0x164c, + 0x6007, 0x3155, + 0x600a, 0x1659, + 0x600b, 0x3158, + 0x600d, 0x1656, + 0x600e, 0x1138, + 0x600f, 0x1655, + 0x6010, 0x315a, + 0x6012, 0x0b6e, + 0x6013, 0x315c, + 0x6014, 0x119b, + 0x6015, 0x0b83, + 0x6016, 0x0487, + 0x6017, 0x315d, + 0x6019, 0x1651, + 0x601a, 0x315f, + 0x601b, 0x1654, + 0x601c, 0x09f8, + 0x601d, 0x0db1, + 0x601e, 0x3160, + 0x6020, 0x0582, + 0x6021, 0x165b, + 0x6022, 0x3162, + 0x6025, 0x0824, + 0x6026, 0x1653, + 0x6027, 0x0f9f, + 0x6028, 0x10fc, + 0x6029, 0x1657, + 0x602a, 0x072f, + 0x602b, 0x1658, + 0x602c, 0x3165, + 0x602f, 0x0c50, + 0x6030, 0x3168, + 0x6035, 0x1652, + 0x6036, 0x316d, + 0x603b, 0x1239, + 0x603c, 0x1a0d, + 0x603d, 0x3172, + 0x603f, 0x165a, + 0x6040, 0x3174, + 0x6041, 0x1a11, + 0x6042, 0x1660, + 0x6043, 0x0d68, + 0x6044, 0x3175, + 0x604b, 0x09fe, + 0x604c, 0x317c, + 0x604d, 0x07e5, + 0x604e, 0x317d, + 0x6050, 0x0963, + 0x6051, 0x317f, + 0x6052, 0x079a, + 0x6053, 0x3180, + 0x6055, 0x0d96, + 0x6056, 0x3182, + 0x6059, 0x1a12, + 0x605a, 0x1a0f, + 0x605b, 0x3185, + 0x605d, 0x1a0e, + 0x605e, 0x3187, + 0x6062, 0x07eb, + 0x6063, 0x1a13, + 0x6064, 0x0fbf, + 0x6065, 0x318b, + 0x6067, 0x1a10, + 0x6068, 0x0795, + 0x6069, 0x0636, + 0x606a, 0x1661, + 0x606b, 0x05f1, + 0x606c, 0x0e44, + 0x606d, 0x0700, + 0x606e, 0x318d, + 0x606f, 0x0f0f, + 0x6070, 0x0c1e, + 0x6071, 0x318e, + 0x6073, 0x095f, + 0x6074, 0x3190, + 0x6076, 0x0630, + 0x6077, 0x3192, + 0x6078, 0x165c, + 0x607a, 0x165f, + 0x607b, 0x165e, + 0x607c, 0x0b38, + 0x607d, 0x1662, + 0x607e, 0x3193, + 0x607f, 0x10a6, + 0x6080, 0x3194, + 0x6083, 0x1667, + 0x6084, 0x0c41, + 0x6085, 0x3197, + 0x6089, 0x0f11, + 0x608a, 0x319b, + 0x608c, 0x1669, + 0x608d, 0x076e, + 0x608e, 0x319d, + 0x6092, 0x1668, + 0x6093, 0x31a1, + 0x6094, 0x07ef, + 0x6095, 0x31a2, + 0x6096, 0x1663, + 0x6097, 0x31a3, + 0x609a, 0x1664, + 0x609b, 0x166a, + 0x609c, 0x31a6, + 0x609d, 0x1666, + 0x609e, 0x31a7, + 0x609f, 0x0f01, + 0x60a0, 0x10ab, + 0x60a1, 0x31a8, + 0x60a3, 0x07d1, + 0x60a4, 0x31aa, + 0x60a6, 0x1106, + 0x60a7, 0x31ac, + 0x60a8, 0x0b5d, + 0x60a9, 0x31ad, + 0x60ab, 0x1a14, + 0x60ac, 0x0fc7, + 0x60ad, 0x1665, + 0x60ae, 0x31af, + 0x60af, 0x0afa, + 0x60b0, 0x31b0, + 0x60b1, 0x166d, + 0x60b2, 0x0418, + 0x60b3, 0x31b1, + 0x60b4, 0x1672, + 0x60b5, 0x23b4, + 0x60b6, 0x207e, + 0x60b7, 0x31b2, + 0x60b8, 0x0835, + 0x60b9, 0x31b3, + 0x60bb, 0x166c, + 0x60bc, 0x05a0, + 0x60bd, 0x31b5, + 0x60c5, 0x0c66, + 0x60c6, 0x1670, + 0x60c7, 0x31bd, + 0x60ca, 0x08d9, + 0x60cb, 0x0ea0, + 0x60cc, 0x31c0, + 0x60d1, 0x0808, + 0x60d2, 0x31c5, + 0x60d5, 0x0e3b, + 0x60d6, 0x31c8, + 0x60d8, 0x166f, + 0x60d9, 0x31ca, + 0x60da, 0x1671, + 0x60db, 0x31cb, + 0x60dc, 0x0f14, + 0x60dd, 0x166e, + 0x60de, 0x31cc, + 0x60df, 0x0eb8, + 0x60e0, 0x07f2, + 0x60e1, 0x1ee3, + 0x60e2, 0x31cd, + 0x60e6, 0x05cc, + 0x60e7, 0x0914, + 0x60e8, 0x0499, + 0x60e9, 0x04f2, + 0x60ea, 0x31d1, + 0x60eb, 0x0422, + 0x60ec, 0x166b, + 0x60ed, 0x0498, + 0x60ee, 0x058d, + 0x60ef, 0x0738, + 0x60f0, 0x0627, + 0x60f1, 0x2095, + 0x60f2, 0x23bb, + 0x60f3, 0x0f58, + 0x60f4, 0x1677, + 0x60f5, 0x31d2, + 0x60f6, 0x07e1, + 0x60f7, 0x31d3, + 0x60f9, 0x0ca2, + 0x60fa, 0x0f95, + 0x60fb, 0x23b9, + 0x60fc, 0x31d5, + 0x6100, 0x1678, + 0x6101, 0x0513, + 0x6102, 0x31d9, + 0x6106, 0x1a15, + 0x6107, 0x31dd, + 0x6108, 0x10df, + 0x6109, 0x10c9, + 0x610a, 0x31de, + 0x610d, 0x1a16, + 0x610e, 0x1679, + 0x610f, 0x1069, + 0x6110, 0x31e1, + 0x6115, 0x1675, + 0x6116, 0x31e6, + 0x611a, 0x10c3, + 0x611b, 0x1e28, + 0x611c, 0x23bd, + 0x611d, 0x31ea, + 0x611f, 0x06cb, + 0x6120, 0x1673, + 0x6121, 0x31ec, + 0x6123, 0x1676, + 0x6124, 0x067c, + 0x6125, 0x31ee, + 0x6126, 0x1674, + 0x6127, 0x098d, + 0x6128, 0x31ef, + 0x612b, 0x167a, + 0x612c, 0x31f2, + 0x6134, 0x23b5, + 0x6135, 0x31fa, + 0x6137, 0x23ba, + 0x6138, 0x31fc, + 0x613e, 0x23b3, + 0x613f, 0x10fb, + 0x6140, 0x3202, + 0x6148, 0x054b, + 0x6149, 0x320a, + 0x614a, 0x167b, + 0x614b, 0x2162, + 0x614c, 0x07da, + 0x614d, 0x320b, + 0x614e, 0x0d30, + 0x614f, 0x320c, + 0x6151, 0x0d1e, + 0x6152, 0x320e, + 0x6155, 0x0b20, + 0x6156, 0x3211, + 0x6158, 0x1e5e, + 0x6159, 0x3213, + 0x615a, 0x1e5d, + 0x615b, 0x3214, + 0x615d, 0x1a17, + 0x615e, 0x3216, + 0x615f, 0x23b7, + 0x6160, 0x3217, + 0x6162, 0x0aa4, + 0x6163, 0x1f2f, + 0x6164, 0x24df, + 0x6165, 0x3219, + 0x6167, 0x07f0, + 0x6168, 0x093b, + 0x6169, 0x321b, + 0x616a, 0x23b2, + 0x616b, 0x214e, + 0x616c, 0x321c, + 0x616e, 0x2052, + 0x616f, 0x321e, + 0x6170, 0x0ece, + 0x6171, 0x321f, + 0x6173, 0x23bc, + 0x6174, 0x3221, + 0x6175, 0x167c, + 0x6176, 0x20eb, + 0x6177, 0x0943, + 0x6178, 0x3222, + 0x6182, 0x2232, + 0x6183, 0x322c, + 0x618a, 0x1e3f, + 0x618b, 0x0458, + 0x618c, 0x3233, + 0x618e, 0x113a, + 0x618f, 0x3235, + 0x6190, 0x201b, + 0x6191, 0x20bc, + 0x6192, 0x23be, + 0x6193, 0x3236, + 0x6194, 0x167e, + 0x6195, 0x3237, + 0x619a, 0x1eae, + 0x619b, 0x323c, + 0x619d, 0x1a19, + 0x619e, 0x323e, + 0x61a4, 0x1efb, + 0x61a5, 0x3244, + 0x61a7, 0x167f, + 0x61a8, 0x0760, + 0x61a9, 0x1a18, + 0x61aa, 0x3246, + 0x61ab, 0x2089, + 0x61ac, 0x167d, + 0x61ad, 0x3247, + 0x61ae, 0x23b1, + 0x61af, 0x3248, + 0x61b2, 0x21c4, + 0x61b3, 0x324b, + 0x61b6, 0x2214, + 0x61b7, 0x1680, + 0x61b8, 0x324e, + 0x61be, 0x076d, + 0x61bf, 0x3254, + 0x61c2, 0x05ed, + 0x61c3, 0x3257, + 0x61c7, 0x1fde, + 0x61c8, 0x0f83, + 0x61c9, 0x2223, + 0x61ca, 0x03ce, + 0x61cb, 0x1a1a, + 0x61cc, 0x23b6, + 0x61cd, 0x325b, + 0x61d1, 0x1a1b, + 0x61d2, 0x09ac, + 0x61d3, 0x325f, + 0x61d4, 0x1681, + 0x61d5, 0x3260, + 0x61de, 0x268c, + 0x61df, 0x24de, + 0x61e0, 0x3269, + 0x61e3, 0x24e0, + 0x61e4, 0x326c, + 0x61e6, 0x0b74, + 0x61e7, 0x326e, + 0x61e8, 0x23b8, + 0x61e9, 0x326f, + 0x61f2, 0x1e81, + 0x61f3, 0x3278, + 0x61f5, 0x1682, + 0x61f6, 0x1ffe, + 0x61f7, 0x1f51, + 0x61f8, 0x21e1, + 0x61f9, 0x327a, + 0x61fa, 0x23b0, + 0x61fb, 0x327b, + 0x61fc, 0x1fce, + 0x61fd, 0x327c, + 0x61fe, 0x211e, + 0x61ff, 0x13e0, + 0x6200, 0x2021, + 0x6201, 0x327d, + 0x6206, 0x1a1c, + 0x6207, 0x24e1, + 0x6208, 0x06e5, + 0x6209, 0x3282, + 0x620a, 0x0efb, + 0x620b, 0x18f9, + 0x620c, 0x0fb2, + 0x620d, 0x0d90, + 0x620e, 0x0cb1, + 0x620f, 0x0f24, + 0x6210, 0x04ee, + 0x6211, 0x0ee1, + 0x6212, 0x08b5, + 0x6213, 0x3283, + 0x6214, 0x24a3, + 0x6215, 0x169e, + 0x6216, 0x0807, + 0x6217, 0x18fa, + 0x6218, 0x115e, + 0x6219, 0x3284, + 0x621a, 0x0bfc, + 0x621b, 0x18fb, + 0x621c, 0x3285, + 0x621f, 0x18fc, + 0x6220, 0x3288, + 0x6221, 0x18fe, + 0x6222, 0x18fd, + 0x6223, 0x3289, + 0x6224, 0x1900, + 0x6225, 0x18ff, + 0x6226, 0x328a, + 0x6227, 0x24a4, + 0x6228, 0x328b, + 0x622a, 0x08a9, + 0x622b, 0x328d, + 0x622c, 0x1901, + 0x622d, 0x328e, + 0x622e, 0x0a65, + 0x622f, 0x328f, + 0x6230, 0x2273, + 0x6231, 0x3290, + 0x6232, 0x21b0, + 0x6233, 0x0544, + 0x6234, 0x057a, + 0x6235, 0x3291, + 0x6237, 0x07bc, + 0x6238, 0x3293, + 0x623d, 0x19f4, + 0x623e, 0x19f3, + 0x623f, 0x065c, + 0x6240, 0x0dee, + 0x6241, 0x044b, + 0x6242, 0x3298, + 0x6243, 0x19f5, + 0x6244, 0x3299, + 0x6247, 0x0d01, + 0x6248, 0x19f6, + 0x624a, 0x329c, + 0x624b, 0x0d6d, + 0x624c, 0x14ba, + 0x624d, 0x048c, + 0x624e, 0x113d, + 0x624f, 0x329d, + 0x6251, 0x0bea, + 0x6252, 0x03d2, + 0x6253, 0x0575, + 0x6254, 0x0cae, + 0x6255, 0x329f, + 0x6258, 0x0e81, + 0x6259, 0x32a2, + 0x625b, 0x0945, + 0x625c, 0x32a4, + 0x6263, 0x0968, + 0x6264, 0x32ab, + 0x6266, 0x0c21, + 0x6267, 0x11b3, + 0x6268, 0x32ad, + 0x6269, 0x0994, + 0x626a, 0x14bb, + 0x626b, 0x0ce1, + 0x626c, 0x1018, + 0x626d, 0x0b65, + 0x626e, 0x03f2, + 0x626f, 0x04db, + 0x6270, 0x0ca0, + 0x6271, 0x32ae, + 0x6273, 0x03ed, + 0x6274, 0x32b0, + 0x6276, 0x0693, + 0x6277, 0x32b2, + 0x6279, 0x0bbb, + 0x627a, 0x32b4, + 0x627c, 0x0632, + 0x627d, 0x32b6, + 0x627e, 0x1173, + 0x627f, 0x04f5, + 0x6280, 0x082f, + 0x6281, 0x32b7, + 0x6284, 0x04d2, + 0x6285, 0x32ba, + 0x6289, 0x0920, + 0x628a, 0x03dc, + 0x628b, 0x32be, + 0x6291, 0x105d, + 0x6292, 0x0d7a, + 0x6293, 0x1202, + 0x6294, 0x32c4, + 0x6295, 0x0e67, + 0x6296, 0x05f5, + 0x6297, 0x0946, + 0x6298, 0x117c, + 0x6299, 0x32c5, + 0x629a, 0x06a2, + 0x629b, 0x0b98, + 0x629c, 0x32c6, + 0x629f, 0x14bc, + 0x62a0, 0x0966, + 0x62a1, 0x0a7c, + 0x62a2, 0x0c3d, + 0x62a3, 0x32c9, + 0x62a4, 0x07b9, + 0x62a5, 0x0411, + 0x62a6, 0x32ca, + 0x62a8, 0x0bab, + 0x62a9, 0x32cc, + 0x62ab, 0x0bbc, + 0x62ac, 0x0dfa, + 0x62ad, 0x32ce, + 0x62b1, 0x0410, + 0x62b2, 0x32d2, + 0x62b5, 0x05b7, + 0x62b6, 0x32d5, + 0x62b9, 0x0b0b, + 0x62ba, 0x32d8, + 0x62bb, 0x14bd, + 0x62bc, 0x0fe3, + 0x62bd, 0x050e, + 0x62be, 0x32d9, + 0x62bf, 0x0af7, + 0x62c0, 0x32da, + 0x62c2, 0x0694, + 0x62c3, 0x32dc, + 0x62c4, 0x11f3, + 0x62c5, 0x0584, + 0x62c6, 0x04b7, + 0x62c7, 0x0b17, + 0x62c8, 0x0b4c, + 0x62c9, 0x0998, + 0x62ca, 0x14be, + 0x62cb, 0x32dd, + 0x62cc, 0x03f3, + 0x62cd, 0x0b85, + 0x62ce, 0x0a29, + 0x62cf, 0x32de, + 0x62d0, 0x072e, + 0x62d1, 0x32df, + 0x62d2, 0x090b, + 0x62d3, 0x0e89, + 0x62d4, 0x03d9, + 0x62d5, 0x32e0, + 0x62d6, 0x0e80, + 0x62d7, 0x14c0, + 0x62d8, 0x08ff, + 0x62d9, 0x121b, + 0x62da, 0x14bf, + 0x62db, 0x1171, + 0x62dc, 0x03e8, + 0x62dd, 0x32e1, + 0x62df, 0x0b45, + 0x62e0, 0x32e3, + 0x62e2, 0x0a4a, + 0x62e3, 0x0863, + 0x62e4, 0x32e5, + 0x62e5, 0x109a, + 0x62e6, 0x09a4, + 0x62e7, 0x0b62, + 0x62e8, 0x046d, + 0x62e9, 0x1134, + 0x62ea, 0x32e6, + 0x62ec, 0x0993, + 0x62ed, 0x0d5a, + 0x62ee, 0x14c1, + 0x62ef, 0x119d, + 0x62f0, 0x32e8, + 0x62f1, 0x0709, + 0x62f2, 0x32e9, + 0x62f3, 0x0c88, + 0x62f4, 0x0d9e, + 0x62f5, 0x32ea, + 0x62f6, 0x14c3, + 0x62f7, 0x094a, + 0x62f8, 0x32eb, + 0x62fc, 0x0bd3, + 0x62fd, 0x1204, + 0x62fe, 0x0d47, + 0x62ff, 0x0b26, + 0x6300, 0x32ef, + 0x6301, 0x04fb, + 0x6302, 0x072b, + 0x6303, 0x32f0, + 0x6307, 0x11b7, + 0x6308, 0x194e, + 0x6309, 0x03bf, + 0x630a, 0x32f4, + 0x630e, 0x0973, + 0x630f, 0x32f8, + 0x6311, 0x0e47, + 0x6312, 0x32fa, + 0x6316, 0x0e8b, + 0x6317, 0x32fe, + 0x631a, 0x11be, + 0x631b, 0x0a75, + 0x631c, 0x3301, + 0x631d, 0x0edd, + 0x631e, 0x0df5, + 0x631f, 0x0f79, + 0x6320, 0x0b36, + 0x6321, 0x0593, + 0x6322, 0x14c2, + 0x6323, 0x1196, + 0x6324, 0x082a, + 0x6325, 0x07e8, + 0x6326, 0x3302, + 0x6328, 0x03af, + 0x6329, 0x3304, + 0x632a, 0x0b73, + 0x632b, 0x056f, + 0x632c, 0x3305, + 0x632f, 0x1192, + 0x6330, 0x3308, + 0x6332, 0x194f, + 0x6333, 0x330a, + 0x6339, 0x14c4, + 0x633a, 0x0e57, + 0x633b, 0x3310, + 0x633d, 0x0e9d, + 0x633e, 0x21d1, + 0x633f, 0x3312, + 0x6342, 0x0ef5, + 0x6343, 0x14c6, + 0x6344, 0x3315, + 0x6345, 0x0e62, + 0x6346, 0x0991, + 0x6347, 0x3316, + 0x6349, 0x121a, + 0x634a, 0x3318, + 0x634b, 0x14c5, + 0x634c, 0x03d1, + 0x634d, 0x076b, + 0x634e, 0x0d0c, + 0x634f, 0x0b56, + 0x6350, 0x0917, + 0x6351, 0x3319, + 0x6355, 0x047d, + 0x6356, 0x331d, + 0x635e, 0x09b7, + 0x635f, 0x0de5, + 0x6360, 0x3325, + 0x6361, 0x0864, + 0x6362, 0x07d0, + 0x6363, 0x0598, + 0x6364, 0x3326, + 0x6367, 0x0bb6, + 0x6368, 0x211c, + 0x6369, 0x14d0, + 0x636a, 0x3329, + 0x636b, 0x235d, + 0x636c, 0x332a, + 0x636d, 0x14cd, + 0x636e, 0x090c, + 0x636f, 0x332b, + 0x6371, 0x14c9, + 0x6372, 0x2682, + 0x6373, 0x332d, + 0x6376, 0x053a, + 0x6377, 0x08ae, + 0x6378, 0x3330, + 0x637a, 0x14ca, + 0x637b, 0x0b50, + 0x637c, 0x3332, + 0x6380, 0x0f33, + 0x6381, 0x3336, + 0x6382, 0x05c1, + 0x6383, 0x210d, + 0x6384, 0x205a, + 0x6385, 0x3337, + 0x6387, 0x061d, + 0x6388, 0x0d71, + 0x6389, 0x05d5, + 0x638a, 0x14cf, + 0x638b, 0x3339, + 0x638c, 0x1167, + 0x638d, 0x333a, + 0x638e, 0x14cb, + 0x638f, 0x0e20, + 0x6390, 0x0c1d, + 0x6391, 0x333b, + 0x6392, 0x0b86, + 0x6393, 0x333c, + 0x6396, 0x103b, + 0x6397, 0x333f, + 0x6398, 0x0921, + 0x6399, 0x3340, + 0x63a0, 0x0a7a, + 0x63a1, 0x3347, + 0x63a2, 0x0e10, + 0x63a3, 0x04dd, + 0x63a4, 0x3348, + 0x63a5, 0x08a4, + 0x63a6, 0x3349, + 0x63a7, 0x0965, + 0x63a8, 0x0e77, + 0x63a9, 0x1003, + 0x63aa, 0x056e, + 0x63ab, 0x334a, + 0x63ac, 0x14ce, + 0x63ad, 0x14c7, + 0x63ae, 0x14d1, + 0x63af, 0x334b, + 0x63b0, 0x1950, + 0x63b1, 0x334c, + 0x63b3, 0x0a57, + 0x63b4, 0x14cc, + 0x63b5, 0x334e, + 0x63b7, 0x11bf, + 0x63b8, 0x0588, + 0x63b9, 0x3350, + 0x63ba, 0x04bb, + 0x63bb, 0x3351, + 0x63bc, 0x14d2, + 0x63bd, 0x3352, + 0x63be, 0x14dc, + 0x63bf, 0x3353, + 0x63c0, 0x1f8d, + 0x63c1, 0x3354, + 0x63c4, 0x14d7, + 0x63c5, 0x3357, + 0x63c6, 0x14db, + 0x63c7, 0x3358, + 0x63c9, 0x0cbb, + 0x63ca, 0x335a, + 0x63cd, 0x123e, + 0x63ce, 0x14d9, + 0x63cf, 0x0aed, + 0x63d0, 0x0e34, + 0x63d1, 0x335d, + 0x63d2, 0x04ac, + 0x63d3, 0x335e, + 0x63d6, 0x1045, + 0x63d7, 0x3361, + 0x63da, 0x21ff, + 0x63db, 0x3364, + 0x63de, 0x14d8, + 0x63df, 0x3367, + 0x63e0, 0x14d5, + 0x63e1, 0x0ee4, + 0x63e2, 0x3368, + 0x63e3, 0x052a, + 0x63e4, 0x3369, + 0x63e9, 0x0938, + 0x63ea, 0x08ed, + 0x63eb, 0x336e, + 0x63ed, 0x08a3, + 0x63ee, 0x1f58, + 0x63ef, 0x3370, + 0x63f2, 0x14d3, + 0x63f3, 0x3373, + 0x63f4, 0x10f1, + 0x63f5, 0x3374, + 0x63f6, 0x14c8, + 0x63f7, 0x3375, + 0x63f8, 0x14d4, + 0x63f9, 0x3376, + 0x63fd, 0x09aa, + 0x63fe, 0x337a, + 0x63ff, 0x14d6, + 0x6400, 0x04ba, + 0x6401, 0x06e4, + 0x6402, 0x0a4e, + 0x6403, 0x337b, + 0x6405, 0x0892, + 0x6406, 0x337d, + 0x640b, 0x14df, + 0x640c, 0x14e2, + 0x640d, 0x215b, + 0x640e, 0x3382, + 0x640f, 0x0472, + 0x6410, 0x0527, + 0x6411, 0x3383, + 0x6413, 0x056d, + 0x6414, 0x0cdf, + 0x6415, 0x3385, + 0x6417, 0x1eb6, + 0x6418, 0x3387, + 0x641b, 0x14e0, + 0x641c, 0x0dc6, + 0x641d, 0x338a, + 0x641e, 0x06de, + 0x641f, 0x338b, + 0x6420, 0x14e1, + 0x6421, 0x14e4, + 0x6422, 0x338c, + 0x6426, 0x14e3, + 0x6427, 0x3390, + 0x642a, 0x0e15, + 0x642b, 0x3393, + 0x642c, 0x03ec, + 0x642d, 0x0571, + 0x642e, 0x3394, + 0x6434, 0x1736, + 0x6435, 0x339a, + 0x6436, 0x20db, + 0x6437, 0x339b, + 0x643a, 0x0f7a, + 0x643b, 0x339e, + 0x643d, 0x04b2, + 0x643e, 0x33a0, + 0x643f, 0x1951, + 0x6440, 0x33a1, + 0x6441, 0x14de, + 0x6442, 0x33a2, + 0x6444, 0x0d1c, + 0x6445, 0x14dd, + 0x6446, 0x03e5, + 0x6447, 0x1028, + 0x6448, 0x0460, + 0x6449, 0x33a4, + 0x644a, 0x0e02, + 0x644b, 0x33a5, + 0x6451, 0x2360, + 0x6452, 0x14da, + 0x6453, 0x33ab, + 0x6454, 0x0d99, + 0x6455, 0x33ac, + 0x6458, 0x114b, + 0x6459, 0x33af, + 0x645c, 0x2361, + 0x645d, 0x33b2, + 0x645e, 0x14e5, + 0x645f, 0x2040, + 0x6460, 0x33b3, + 0x6467, 0x0560, + 0x6468, 0x33ba, + 0x6469, 0x0b09, + 0x646a, 0x33bb, + 0x646d, 0x14e7, + 0x646e, 0x33be, + 0x646f, 0x228e, + 0x6470, 0x33bf, + 0x6473, 0x1fdf, + 0x6474, 0x33c2, + 0x6476, 0x235e, + 0x6477, 0x33c4, + 0x6478, 0x0b03, + 0x647a, 0x14e9, + 0x647b, 0x1e6a, + 0x647c, 0x33c5, + 0x6482, 0x0a15, + 0x6483, 0x33cb, + 0x6484, 0x14e6, + 0x6485, 0x091e, + 0x6486, 0x33cc, + 0x6487, 0x0bd1, + 0x6488, 0x2002, + 0x6489, 0x33cd, + 0x6491, 0x04ea, + 0x6492, 0x0cd1, + 0x6493, 0x2093, + 0x6494, 0x33d5, + 0x6495, 0x0daf, + 0x6496, 0x14e8, + 0x6497, 0x33d6, + 0x6499, 0x14ec, + 0x649a, 0x33d8, + 0x649e, 0x120f, + 0x649f, 0x235f, + 0x64a0, 0x33dc, + 0x64a3, 0x1eac, + 0x64a4, 0x04dc, + 0x64a5, 0x1e54, + 0x64a6, 0x33df, + 0x64a9, 0x0a0c, + 0x64aa, 0x33e2, + 0x64ab, 0x1f08, + 0x64ac, 0x0c48, + 0x64ad, 0x046c, + 0x64ae, 0x056c, + 0x64af, 0x33e3, + 0x64b0, 0x1208, + 0x64b1, 0x33e4, + 0x64b2, 0x20c0, + 0x64b3, 0x2362, + 0x64b4, 0x33e5, + 0x64b5, 0x0b4f, + 0x64b6, 0x33e6, + 0x64b7, 0x14ea, + 0x64b9, 0x33e7, + 0x64ba, 0x14ed, + 0x64bb, 0x2160, + 0x64bc, 0x076a, + 0x64bd, 0x33e8, + 0x64be, 0x219d, + 0x64bf, 0x1f8e, + 0x64c0, 0x14ee, + 0x64c1, 0x222d, + 0x64c2, 0x09c9, + 0x64c3, 0x33e9, + 0x64c4, 0x2047, + 0x64c5, 0x0cfc, + 0x64c6, 0x33ea, + 0x64c7, 0x2262, + 0x64c8, 0x33eb, + 0x64ca, 0x1f67, + 0x64cb, 0x1eb2, + 0x64cc, 0x33ed, + 0x64cd, 0x04a0, + 0x64ce, 0x0c63, + 0x64cf, 0x33ee, + 0x64d0, 0x14ef, + 0x64d1, 0x33ef, + 0x64d2, 0x0c59, + 0x64d3, 0x33f0, + 0x64d4, 0x1ea9, + 0x64d5, 0x33f1, + 0x64d7, 0x14f0, + 0x64d8, 0x1952, + 0x64d9, 0x33f3, + 0x64da, 0x1fcc, + 0x64db, 0x33f4, + 0x64de, 0x0dc8, + 0x64df, 0x33f7, + 0x64e0, 0x1f72, + 0x64e1, 0x33f8, + 0x64e2, 0x14f2, + 0x64e3, 0x33f9, + 0x64e4, 0x14f1, + 0x64e5, 0x33fa, + 0x64e6, 0x0488, + 0x64e7, 0x33fb, + 0x64ec, 0x2098, + 0x64ed, 0x3400, + 0x64ef, 0x1e52, + 0x64f0, 0x20a4, + 0x64f1, 0x1f1c, + 0x64f2, 0x228f, + 0x64f3, 0x3402, + 0x64f4, 0x1fed, + 0x64f5, 0x3403, + 0x64f7, 0x2365, + 0x64f8, 0x3405, + 0x64fa, 0x1e2d, + 0x64fb, 0x2152, + 0x64fc, 0x2366, + 0x64fd, 0x3407, + 0x64fe, 0x20fa, + 0x64ff, 0x3408, + 0x6500, 0x0b8b, + 0x6501, 0x3409, + 0x6504, 0x2363, + 0x6505, 0x340c, + 0x6506, 0x209a, + 0x6507, 0x340d, + 0x6509, 0x14f3, + 0x650a, 0x340f, + 0x650f, 0x203c, + 0x6510, 0x3414, + 0x6512, 0x111f, + 0x6513, 0x3416, + 0x6514, 0x1ff6, + 0x6515, 0x3417, + 0x6516, 0x2364, + 0x6517, 0x3418, + 0x6518, 0x0c9c, + 0x6519, 0x1e69, + 0x651a, 0x3419, + 0x651b, 0x2367, + 0x651c, 0x341a, + 0x651d, 0x211d, + 0x651e, 0x341b, + 0x6522, 0x2259, + 0x6523, 0x2056, + 0x6524, 0x2163, + 0x6525, 0x14f4, + 0x6526, 0x341f, + 0x652a, 0x1fa9, + 0x652b, 0x091f, + 0x652c, 0x1ffc, + 0x652d, 0x3423, + 0x652e, 0x14f5, + 0x652f, 0x11a6, + 0x6530, 0x3424, + 0x6534, 0x1909, + 0x6535, 0x1966, + 0x6536, 0x0d6c, + 0x6537, 0x3428, + 0x6538, 0x12b2, + 0x6539, 0x06bf, + 0x653a, 0x3429, + 0x653b, 0x06fe, + 0x653c, 0x342a, + 0x653e, 0x0662, + 0x653f, 0x119f, + 0x6540, 0x342c, + 0x6545, 0x0723, + 0x6546, 0x3431, + 0x6548, 0x0f72, + 0x6549, 0x1ccb, + 0x654a, 0x3433, + 0x654c, 0x05b1, + 0x654d, 0x3435, + 0x654f, 0x0af9, + 0x6550, 0x3437, + 0x6551, 0x08f7, + 0x6552, 0x3438, + 0x6555, 0x1967, + 0x6556, 0x03c8, + 0x6557, 0x1e2e, + 0x6558, 0x343b, + 0x6559, 0x089d, + 0x655a, 0x343c, + 0x655b, 0x09fb, + 0x655c, 0x343d, + 0x655d, 0x043f, + 0x655e, 0x04cd, + 0x655f, 0x343e, + 0x6562, 0x06cd, + 0x6563, 0x0cdb, + 0x6564, 0x3441, + 0x6566, 0x0617, + 0x6567, 0x3443, + 0x656b, 0x1968, + 0x656c, 0x08e3, + 0x656d, 0x3447, + 0x6570, 0x0d94, + 0x6571, 0x344a, + 0x6572, 0x0c40, + 0x6573, 0x344b, + 0x6574, 0x119c, + 0x6575, 0x1ebc, + 0x6576, 0x344c, + 0x6577, 0x0690, + 0x6578, 0x2142, + 0x6579, 0x344d, + 0x6582, 0x201e, + 0x6583, 0x1e43, + 0x6584, 0x3456, + 0x6587, 0x0ed3, + 0x6588, 0x3459, + 0x658b, 0x114c, + 0x658c, 0x045c, + 0x658d, 0x345c, + 0x6590, 0x19c1, + 0x6591, 0x03ea, + 0x6592, 0x345f, + 0x6593, 0x19c3, + 0x6594, 0x3460, + 0x6595, 0x24d4, + 0x6596, 0x3461, + 0x6597, 0x05f6, + 0x6598, 0x3462, + 0x6599, 0x0a18, + 0x659a, 0x3463, + 0x659b, 0x1d56, + 0x659c, 0x0f7c, + 0x659d, 0x3464, + 0x659f, 0x1186, + 0x65a0, 0x3466, + 0x65a1, 0x0ee2, + 0x65a2, 0x3467, + 0x65a4, 0x08c0, + 0x65a5, 0x0507, + 0x65a6, 0x3469, + 0x65a7, 0x06a6, + 0x65a8, 0x346a, + 0x65a9, 0x1157, + 0x65aa, 0x346b, + 0x65ab, 0x1a29, + 0x65ac, 0x226f, + 0x65ad, 0x060e, + 0x65ae, 0x346c, + 0x65af, 0x0dae, + 0x65b0, 0x0f8d, + 0x65b1, 0x346d, + 0x65b7, 0x1ed7, + 0x65b8, 0x3473, + 0x65b9, 0x065a, + 0x65ba, 0x3474, + 0x65bc, 0x19c4, + 0x65bd, 0x0d40, + 0x65be, 0x3476, + 0x65c1, 0x0b95, + 0x65c2, 0x3479, + 0x65c3, 0x19c7, + 0x65c4, 0x19c6, + 0x65c5, 0x0a6a, + 0x65c6, 0x19c5, + 0x65c7, 0x347a, + 0x65cb, 0x0fc8, + 0x65cc, 0x19c8, + 0x65cd, 0x347e, + 0x65ce, 0x19c9, + 0x65cf, 0x1242, + 0x65d0, 0x347f, + 0x65d2, 0x19ca, + 0x65d3, 0x3481, + 0x65d6, 0x19cb, + 0x65d7, 0x0c0b, + 0x65d8, 0x3484, + 0x65e0, 0x0eed, + 0x65e1, 0x348c, + 0x65e2, 0x083b, + 0x65e3, 0x348d, + 0x65e5, 0x0cb0, + 0x65e6, 0x058a, + 0x65e7, 0x08f8, + 0x65e8, 0x11bb, + 0x65e9, 0x112a, + 0x65ea, 0x348f, + 0x65ec, 0x0fd7, + 0x65ed, 0x0fbc, + 0x65ee, 0x190a, + 0x65f1, 0x076c, + 0x65f2, 0x3491, + 0x65f6, 0x0d48, + 0x65f7, 0x0982, + 0x65f8, 0x3495, + 0x65fa, 0x0eab, + 0x65fb, 0x3497, + 0x6600, 0x1912, + 0x6601, 0x349c, + 0x6602, 0x03c5, + 0x6603, 0x1910, + 0x6604, 0x349d, + 0x6606, 0x0990, + 0x6607, 0x349f, + 0x660a, 0x190d, + 0x660b, 0x34a2, + 0x660c, 0x04c4, + 0x660d, 0x34a3, + 0x660e, 0x0afc, + 0x660f, 0x07fd, + 0x6610, 0x34a4, + 0x6613, 0x105e, + 0x6614, 0x0f03, + 0x6615, 0x1911, + 0x6616, 0x34a7, + 0x6619, 0x190e, + 0x661a, 0x34aa, + 0x661d, 0x1915, + 0x661e, 0x34ad, + 0x661f, 0x0f92, + 0x6620, 0x1098, + 0x6621, 0x34ae, + 0x6625, 0x053d, + 0x6626, 0x34b2, + 0x6627, 0x0ac6, + 0x6628, 0x124f, + 0x6629, 0x34b3, + 0x662d, 0x1172, + 0x662e, 0x34b7, + 0x662f, 0x0d5e, + 0x6630, 0x34b8, + 0x6631, 0x1917, + 0x6632, 0x34b9, + 0x6634, 0x1916, + 0x6635, 0x1919, + 0x6636, 0x1918, + 0x6637, 0x34bb, + 0x663c, 0x11e6, + 0x663d, 0x34c0, + 0x663e, 0x0f41, + 0x663f, 0x34c1, + 0x6641, 0x191d, + 0x6642, 0x212d, + 0x6643, 0x07e3, + 0x6644, 0x34c3, + 0x664b, 0x08cb, + 0x664c, 0x0d07, + 0x664d, 0x34ca, + 0x664f, 0x191e, + 0x6650, 0x34cc, + 0x6652, 0x0cf2, + 0x6653, 0x0f6b, + 0x6654, 0x191c, + 0x6655, 0x1111, + 0x6656, 0x191f, + 0x6657, 0x1921, + 0x6658, 0x34ce, + 0x665a, 0x0e9e, + 0x665b, 0x34d0, + 0x665d, 0x229b, + 0x665e, 0x34d2, + 0x665f, 0x191b, + 0x6660, 0x34d3, + 0x6661, 0x1920, + 0x6662, 0x34d4, + 0x6664, 0x0efd, + 0x6665, 0x34d6, + 0x6666, 0x07f3, + 0x6667, 0x34d7, + 0x6668, 0x04e4, + 0x6669, 0x34d8, + 0x666e, 0x0bf4, + 0x666f, 0x08df, + 0x6670, 0x0f09, + 0x6671, 0x34dd, + 0x6674, 0x0c64, + 0x6675, 0x34e0, + 0x6676, 0x08d6, + 0x6677, 0x1922, + 0x6678, 0x34e1, + 0x667a, 0x11c6, + 0x667b, 0x34e3, + 0x667e, 0x0a09, + 0x667f, 0x34e6, + 0x6682, 0x1120, + 0x6683, 0x34e9, + 0x6684, 0x1923, + 0x6685, 0x34ea, + 0x6687, 0x0f2b, + 0x6688, 0x2256, + 0x6689, 0x24a8, + 0x668a, 0x34ec, + 0x668c, 0x1924, + 0x668d, 0x34ee, + 0x6691, 0x0d85, + 0x6692, 0x34f2, + 0x6696, 0x0b70, + 0x6697, 0x03c0, + 0x6698, 0x34f6, + 0x669d, 0x1926, + 0x669e, 0x34fb, + 0x66a2, 0x1e79, + 0x66a3, 0x34ff, + 0x66a7, 0x1925, + 0x66a8, 0x1cdd, + 0x66a9, 0x3503, + 0x66ab, 0x225a, + 0x66ac, 0x3505, + 0x66ae, 0x0b1d, + 0x66af, 0x3507, + 0x66b4, 0x0412, + 0x66b5, 0x350c, + 0x66b9, 0x175b, + 0x66ba, 0x3510, + 0x66be, 0x1927, + 0x66bf, 0x3514, + 0x66c4, 0x24a7, + 0x66c5, 0x3519, + 0x66c6, 0x2686, + 0x66c7, 0x24a6, + 0x66c8, 0x351a, + 0x66c9, 0x21ce, + 0x66ca, 0x351b, + 0x66d6, 0x24a9, + 0x66d7, 0x3527, + 0x66d9, 0x0d86, + 0x66da, 0x3529, + 0x66db, 0x1928, + 0x66dd, 0x0bf7, + 0x66de, 0x352a, + 0x66e0, 0x1fe7, + 0x66e1, 0x352c, + 0x66e6, 0x192a, + 0x66e7, 0x3531, + 0x66e9, 0x192b, + 0x66ea, 0x3533, + 0x66ec, 0x2112, + 0x66ed, 0x3535, + 0x66f0, 0x10fe, + 0x66f1, 0x3538, + 0x66f2, 0x0c77, + 0x66f3, 0x103e, + 0x66f4, 0x06f7, + 0x66f5, 0x3539, + 0x66f7, 0x1914, + 0x66f8, 0x213c, + 0x66f9, 0x04a3, + 0x66fa, 0x353b, + 0x66fc, 0x0aa3, + 0x66fd, 0x353d, + 0x66fe, 0x113b, + 0x66ff, 0x0e39, + 0x6700, 0x124b, + 0x6701, 0x353e, + 0x6703, 0x1f5c, + 0x6704, 0x3540, + 0x6708, 0x1105, + 0x6709, 0x10b5, + 0x670a, 0x1973, + 0x670b, 0x0bb4, + 0x670c, 0x3544, + 0x670d, 0x069b, + 0x670e, 0x3545, + 0x6710, 0x1984, + 0x6711, 0x3547, + 0x6714, 0x0dac, + 0x6715, 0x198e, + 0x6716, 0x354a, + 0x6717, 0x09b5, + 0x6718, 0x354b, + 0x671b, 0x0eac, + 0x671c, 0x354e, + 0x671d, 0x04d4, + 0x671e, 0x354f, + 0x671f, 0x0bf9, + 0x6720, 0x3550, + 0x6726, 0x19ac, + 0x6727, 0x24c4, + 0x6728, 0x0b21, + 0x6729, 0x3556, + 0x672a, 0x0ec3, + 0x672b, 0x0b0c, + 0x672c, 0x0427, + 0x672d, 0x1140, + 0x672e, 0x3557, + 0x672f, 0x0d8c, + 0x6730, 0x3558, + 0x6731, 0x11eb, + 0x6732, 0x3559, + 0x6734, 0x0bf2, + 0x6735, 0x0623, + 0x6736, 0x355b, + 0x673a, 0x080f, + 0x673b, 0x355f, + 0x673d, 0x0fab, + 0x673e, 0x3561, + 0x6740, 0x0cea, + 0x6741, 0x3563, + 0x6742, 0x1116, + 0x6743, 0x0c83, + 0x6744, 0x3564, + 0x6746, 0x06c6, + 0x6747, 0x3566, + 0x6748, 0x1854, + 0x6749, 0x0cf5, + 0x674a, 0x3567, + 0x674c, 0x1851, + 0x674d, 0x3569, + 0x674e, 0x09d9, + 0x674f, 0x0f9e, + 0x6750, 0x048b, + 0x6751, 0x0568, + 0x6752, 0x356a, + 0x6753, 0x1852, + 0x6754, 0x356b, + 0x6756, 0x1169, + 0x6757, 0x356d, + 0x675c, 0x0604, + 0x675d, 0x3572, + 0x675e, 0x1853, + 0x675f, 0x0d8f, + 0x6760, 0x06d7, + 0x6761, 0x0e48, + 0x6762, 0x3573, + 0x6765, 0x099f, + 0x6766, 0x3576, + 0x6768, 0x1017, + 0x6769, 0x1855, + 0x676a, 0x1858, + 0x676b, 0x3578, + 0x676d, 0x0773, + 0x676e, 0x357a, + 0x676f, 0x0416, + 0x6770, 0x08ad, + 0x6771, 0x1ecc, + 0x6772, 0x190f, + 0x6773, 0x1859, + 0x6774, 0x357b, + 0x6775, 0x185c, + 0x6776, 0x357c, + 0x6777, 0x1861, + 0x6778, 0x357d, + 0x677c, 0x1862, + 0x677d, 0x3581, + 0x677e, 0x0dbe, + 0x677f, 0x03f0, + 0x6780, 0x3582, + 0x6781, 0x081e, + 0x6782, 0x3583, + 0x6784, 0x0712, + 0x6785, 0x3585, + 0x6787, 0x1857, + 0x6788, 0x3587, + 0x6789, 0x0ea8, + 0x678a, 0x3588, + 0x678b, 0x1860, + 0x678c, 0x3589, + 0x6790, 0x0f05, + 0x6791, 0x358d, + 0x6795, 0x118e, + 0x6796, 0x3591, + 0x6797, 0x0a1f, + 0x6798, 0x185a, + 0x6799, 0x3592, + 0x679a, 0x0abb, + 0x679b, 0x3593, + 0x679c, 0x0754, + 0x679d, 0x11a5, + 0x679e, 0x185e, + 0x679f, 0x3594, + 0x67a2, 0x0d77, + 0x67a3, 0x1129, + 0x67a4, 0x3597, + 0x67a5, 0x1856, + 0x67a6, 0x3598, + 0x67a7, 0x185b, + 0x67a8, 0x185d, + 0x67a9, 0x3599, + 0x67aa, 0x0c36, + 0x67ab, 0x0680, + 0x67ac, 0x359a, + 0x67ad, 0x185f, + 0x67ae, 0x359b, + 0x67af, 0x096a, + 0x67b0, 0x1868, + 0x67b1, 0x359c, + 0x67b3, 0x186d, + 0x67b4, 0x359e, + 0x67b5, 0x186b, + 0x67b6, 0x084f, + 0x67b7, 0x0842, + 0x67b8, 0x1871, + 0x67b9, 0x359f, + 0x67c1, 0x1874, + 0x67c2, 0x35a7, + 0x67c3, 0x1870, + 0x67c4, 0x0463, + 0x67c5, 0x35a8, + 0x67cf, 0x03e3, + 0x67d0, 0x0b16, + 0x67d1, 0x06c7, + 0x67d2, 0x0c01, + 0x67d3, 0x0c99, + 0x67d4, 0x0cbc, + 0x67d5, 0x35b2, + 0x67d8, 0x1865, + 0x67d9, 0x186a, + 0x67da, 0x186c, + 0x67db, 0x35b5, + 0x67dc, 0x074a, + 0x67dd, 0x186e, + 0x67de, 0x1252, + 0x67df, 0x35b6, + 0x67e0, 0x0b5e, + 0x67e1, 0x35b7, + 0x67e2, 0x1872, + 0x67e3, 0x35b8, + 0x67e5, 0x04b0, + 0x67e6, 0x35ba, + 0x67e9, 0x1867, + 0x67ea, 0x35bd, + 0x67ec, 0x0860, + 0x67ed, 0x35bf, + 0x67ef, 0x094f, + 0x67f0, 0x1863, + 0x67f1, 0x11f8, + 0x67f2, 0x35c1, + 0x67f3, 0x0a41, + 0x67f4, 0x04b8, + 0x67f5, 0x35c2, + 0x67fd, 0x1875, + 0x67fe, 0x35ca, + 0x67ff, 0x0d58, + 0x6800, 0x186f, + 0x6801, 0x35cb, + 0x6805, 0x1145, + 0x6806, 0x35cf, + 0x6807, 0x0453, + 0x6808, 0x115c, + 0x6809, 0x1864, + 0x680a, 0x1866, + 0x680b, 0x05ef, + 0x680c, 0x1869, + 0x680d, 0x35d0, + 0x680e, 0x1873, + 0x680f, 0x09a3, + 0x6810, 0x35d1, + 0x6811, 0x0d8e, + 0x6812, 0x35d2, + 0x6813, 0x0d9d, + 0x6814, 0x35d3, + 0x6816, 0x0bfb, + 0x6817, 0x09e0, + 0x6818, 0x35d5, + 0x681d, 0x187f, + 0x681e, 0x35da, + 0x6821, 0x0f6e, + 0x6822, 0x35dd, + 0x6829, 0x1888, + 0x682a, 0x11e9, + 0x682b, 0x35e4, + 0x6832, 0x1876, + 0x6834, 0x35eb, + 0x6837, 0x1022, + 0x6838, 0x0782, + 0x6839, 0x06f4, + 0x683a, 0x35ee, + 0x683c, 0x06ec, + 0x683d, 0x1117, + 0x683e, 0x1885, + 0x683f, 0x35f0, + 0x6840, 0x1884, + 0x6841, 0x1882, + 0x6842, 0x0749, + 0x6843, 0x0e25, + 0x6844, 0x187c, + 0x6845, 0x0eb5, + 0x6846, 0x097f, + 0x6847, 0x35f1, + 0x6848, 0x03c3, + 0x6849, 0x1887, + 0x684a, 0x1886, + 0x684b, 0x35f2, + 0x684c, 0x121d, + 0x684d, 0x35f3, + 0x684e, 0x187a, + 0x684f, 0x35f4, + 0x6850, 0x0e5a, + 0x6851, 0x0cdc, + 0x6852, 0x35f5, + 0x6853, 0x07cd, + 0x6854, 0x08ac, + 0x6855, 0x1880, + 0x6856, 0x35f6, + 0x6860, 0x1878, + 0x6862, 0x187b, + 0x6863, 0x0596, + 0x6864, 0x187d, + 0x6865, 0x0c42, + 0x6866, 0x1881, + 0x6867, 0x1883, + 0x6868, 0x0881, + 0x6869, 0x120b, + 0x686a, 0x3600, + 0x686b, 0x188e, + 0x686c, 0x3601, + 0x6874, 0x188b, + 0x6875, 0x3609, + 0x6876, 0x0e61, + 0x6877, 0x188c, + 0x6878, 0x360a, + 0x6881, 0x0a03, + 0x6882, 0x3613, + 0x6883, 0x187e, + 0x6884, 0x3614, + 0x6885, 0x0abc, + 0x6886, 0x03fb, + 0x6887, 0x3615, + 0x688f, 0x188a, + 0x6890, 0x361d, + 0x6893, 0x188d, + 0x6894, 0x3620, + 0x6897, 0x06fc, + 0x6898, 0x246a, + 0x6899, 0x3623, + 0x689d, 0x2175, + 0x689e, 0x3627, + 0x689f, 0x246d, + 0x68a0, 0x3628, + 0x68a2, 0x0d0b, + 0x68a3, 0x362a, + 0x68a6, 0x0ad3, + 0x68a7, 0x0eef, + 0x68a8, 0x09d1, + 0x68a9, 0x362d, + 0x68ad, 0x0de8, + 0x68ae, 0x3631, + 0x68af, 0x0e30, + 0x68b0, 0x0f80, + 0x68b1, 0x3632, + 0x68b3, 0x0d78, + 0x68b4, 0x3634, + 0x68b5, 0x1889, + 0x68b6, 0x3635, + 0x68c0, 0x085f, + 0x68c1, 0x363f, + 0x68c2, 0x188f, + 0x68c3, 0x3640, + 0x68c9, 0x0ae3, + 0x68ca, 0x3646, + 0x68cb, 0x0c04, + 0x68cc, 0x3647, + 0x68cd, 0x0750, + 0x68ce, 0x3648, + 0x68d2, 0x03ff, + 0x68d3, 0x364c, + 0x68d5, 0x1235, + 0x68d6, 0x246b, + 0x68d7, 0x225f, + 0x68d8, 0x081f, + 0x68d9, 0x364e, + 0x68da, 0x0bb0, + 0x68db, 0x364f, + 0x68df, 0x1ece, + 0x68e0, 0x0e17, + 0x68e1, 0x3653, + 0x68e3, 0x189a, + 0x68e4, 0x3655, + 0x68e7, 0x2272, + 0x68e8, 0x3658, + 0x68ee, 0x0ce6, + 0x68ef, 0x365e, + 0x68f0, 0x1896, + 0x68f1, 0x09cd, + 0x68f2, 0x365f, + 0x68f5, 0x0950, + 0x68f6, 0x3662, + 0x68f9, 0x1894, + 0x68fa, 0x0730, + 0x68fb, 0x3665, + 0x68fc, 0x1891, + 0x68fd, 0x3666, + 0x6900, 0x3669, + 0x6901, 0x1898, + 0x6902, 0x366a, + 0x6905, 0x1055, + 0x6906, 0x366d, + 0x690b, 0x1897, + 0x690c, 0x3672, + 0x690d, 0x11b1, + 0x690e, 0x1212, + 0x690f, 0x2473, + 0x6910, 0x189b, + 0x6911, 0x3673, + 0x6912, 0x0888, + 0x6913, 0x3674, + 0x691f, 0x1892, + 0x6921, 0x3680, + 0x6924, 0x1895, + 0x6925, 0x3683, + 0x692d, 0x0e87, + 0x692e, 0x368b, + 0x6930, 0x1033, + 0x6931, 0x368d, + 0x6934, 0x18a6, + 0x6935, 0x3690, + 0x6939, 0x189d, + 0x693a, 0x3694, + 0x693d, 0x052d, + 0x693e, 0x3697, + 0x693f, 0x053e, + 0x6940, 0x3698, + 0x6942, 0x189f, + 0x6943, 0x369a, + 0x694a, 0x21fe, + 0x694b, 0x36a1, + 0x6953, 0x1efe, + 0x6954, 0x0f73, + 0x6955, 0x36a9, + 0x6957, 0x1899, + 0x6958, 0x36ab, + 0x695a, 0x0523, + 0x695b, 0x36ad, + 0x695d, 0x18a0, + 0x695e, 0x09ce, + 0x695f, 0x36af, + 0x6960, 0x189e, + 0x6961, 0x36b0, + 0x6963, 0x18ad, + 0x6964, 0x36b2, + 0x6966, 0x18ac, + 0x6967, 0x36b4, + 0x6968, 0x2475, + 0x6969, 0x36b5, + 0x696b, 0x18a2, + 0x696c, 0x36b7, + 0x696d, 0x220a, + 0x696e, 0x1890, + 0x696f, 0x36b8, + 0x6971, 0x189c, + 0x6972, 0x36ba, + 0x6975, 0x1f6f, + 0x6976, 0x36bd, + 0x6977, 0x0939, + 0x6978, 0x18a5, + 0x6979, 0x18ae, + 0x697a, 0x36be, + 0x697c, 0x0a4c, + 0x697d, 0x36c0, + 0x6980, 0x18a3, + 0x6981, 0x36c3, + 0x6982, 0x06c0, + 0x6983, 0x36c4, + 0x6984, 0x18a1, + 0x6985, 0x36c5, + 0x6986, 0x10c1, + 0x6987, 0x18a8, + 0x6989, 0x18ab, + 0x698a, 0x36c6, + 0x698d, 0x18bb, + 0x698e, 0x36c9, + 0x6994, 0x09b1, + 0x6995, 0x18b9, + 0x6996, 0x36cf, + 0x6998, 0x18a4, + 0x6999, 0x36d1, + 0x699b, 0x18af, + 0x699c, 0x03fc, + 0x699d, 0x36d3, + 0x69a7, 0x18b0, + 0x69a8, 0x1146, + 0x69a9, 0x36dd, + 0x69aa, 0x2468, + 0x69ab, 0x18b2, + 0x69ac, 0x36de, + 0x69ad, 0x18b3, + 0x69ae, 0x2100, + 0x69af, 0x36df, + 0x69b1, 0x18b5, + 0x69b2, 0x36e1, + 0x69b4, 0x0a3a, + 0x69b5, 0x36e3, + 0x69b7, 0x0c91, + 0x69b8, 0x36e5, + 0x69bb, 0x18b1, + 0x69bc, 0x36e8, + 0x69bf, 0x2476, + 0x69c0, 0x36eb, + 0x69c1, 0x18b6, + 0x69c2, 0x36ec, + 0x69ca, 0x18b7, + 0x69cb, 0x1f27, + 0x69cc, 0x18a7, + 0x69cd, 0x20d7, + 0x69ce, 0x18aa, + 0x69cf, 0x36f4, + 0x69d0, 0x07c6, + 0x69d1, 0x36f5, + 0x69d4, 0x18b4, + 0x69d5, 0x36f8, + 0x69db, 0x086a, + 0x69dc, 0x36fe, + 0x69df, 0x18b8, + 0x69e0, 0x18ba, + 0x69e1, 0x3701, + 0x69e7, 0x247c, + 0x69e8, 0x3707, + 0x69ed, 0x18be, + 0x69ee, 0x370c, + 0x69f2, 0x18c2, + 0x69f3, 0x1fa1, + 0x69f4, 0x3710, + 0x69fd, 0x04a2, + 0x69fe, 0x3719, + 0x69ff, 0x18bc, + 0x6a00, 0x371a, + 0x6a01, 0x22aa, + 0x6a02, 0x2005, + 0x6a03, 0x371b, + 0x6a05, 0x246c, + 0x6a06, 0x371d, + 0x6a0a, 0x064b, + 0x6a0b, 0x3721, + 0x6a13, 0x203e, + 0x6a14, 0x3729, + 0x6a17, 0x18bf, + 0x6a19, 0x1e4c, + 0x6a1a, 0x372c, + 0x6a1e, 0x213a, + 0x6a1f, 0x1162, + 0x6a20, 0x3730, + 0x6a21, 0x0b06, + 0x6a22, 0x3731, + 0x6a23, 0x2204, + 0x6a24, 0x3732, + 0x6a28, 0x18cc, + 0x6a29, 0x3736, + 0x6a2a, 0x0798, + 0x6a2b, 0x3737, + 0x6a2f, 0x18bd, + 0x6a30, 0x373b, + 0x6a31, 0x1088, + 0x6a32, 0x373c, + 0x6a35, 0x18c8, + 0x6a36, 0x373f, + 0x6a38, 0x20c3, + 0x6a39, 0x2140, + 0x6a3a, 0x2477, + 0x6a3b, 0x3741, + 0x6a3d, 0x18cb, + 0x6a3e, 0x18c4, + 0x6a3f, 0x3743, + 0x6a44, 0x18c3, + 0x6a45, 0x3748, + 0x6a47, 0x0c3e, + 0x6a48, 0x2474, + 0x6a49, 0x374a, + 0x6a4b, 0x20dd, + 0x6a4c, 0x374c, + 0x6a50, 0x18c6, + 0x6a51, 0x3750, + 0x6a58, 0x18cd, + 0x6a59, 0x04ed, + 0x6a5a, 0x3757, + 0x6a5b, 0x18c7, + 0x6a5c, 0x3758, + 0x6a5f, 0x1f68, + 0x6a60, 0x375b, + 0x6a61, 0x0f5d, + 0x6a62, 0x2185, + 0x6a63, 0x375c, + 0x6a65, 0x18c1, + 0x6a66, 0x375e, + 0x6a71, 0x051c, + 0x6a72, 0x3769, + 0x6a79, 0x18ca, + 0x6a7a, 0x3770, + 0x6a7c, 0x18ce, + 0x6a7d, 0x3772, + 0x6a80, 0x0e07, + 0x6a81, 0x3775, + 0x6a84, 0x0f1a, + 0x6a85, 0x3778, + 0x6a89, 0x2472, + 0x6a8a, 0x377c, + 0x6a8e, 0x18c9, + 0x6a8f, 0x3780, + 0x6a90, 0x18d0, + 0x6a91, 0x18cf, + 0x6a92, 0x3781, + 0x6a94, 0x1eb5, + 0x6a95, 0x3783, + 0x6a97, 0x18d2, + 0x6a98, 0x3785, + 0x6a9c, 0x2478, + 0x6a9d, 0x3789, + 0x6aa0, 0x18c5, + 0x6aa1, 0x378c, + 0x6aa2, 0x1f8b, + 0x6aa3, 0x2484, + 0x6aa4, 0x378d, + 0x6aa9, 0x18d1, + 0x6aaa, 0x3792, + 0x6aab, 0x18d3, + 0x6aac, 0x0acf, + 0x6aad, 0x3793, + 0x6aaf, 0x2699, + 0x6ab0, 0x3795, + 0x6ab3, 0x2482, + 0x6ab4, 0x3798, + 0x6ab8, 0x20a1, + 0x6ab9, 0x379c, + 0x6abb, 0x1f92, + 0x6abc, 0x379e, + 0x6ac3, 0x1f38, + 0x6ac4, 0x37a5, + 0x6ad3, 0x2485, + 0x6ad4, 0x37b4, + 0x6ada, 0x2480, + 0x6adb, 0x246e, + 0x6adc, 0x37ba, + 0x6add, 0x247b, + 0x6ade, 0x2486, + 0x6adf, 0x2471, + 0x6ae0, 0x37bb, + 0x6ae7, 0x2483, + 0x6ae8, 0x2470, + 0x6ae9, 0x37c2, + 0x6aea, 0x2469, + 0x6aeb, 0x37c3, + 0x6aec, 0x247f, + 0x6aed, 0x37c4, + 0x6af3, 0x246f, + 0x6af4, 0x37ca, + 0x6af8, 0x2481, + 0x6af9, 0x37ce, + 0x6afb, 0x2220, + 0x6afc, 0x37d0, + 0x6b00, 0x37d4, + 0x6b04, 0x1ff5, + 0x6b05, 0x37d8, + 0x6b0a, 0x20f4, + 0x6b0b, 0x37dd, + 0x6b0f, 0x247d, + 0x6b10, 0x37e1, + 0x6b12, 0x2479, + 0x6b13, 0x37e3, + 0x6b16, 0x247e, + 0x6b17, 0x37e6, + 0x6b1e, 0x247a, + 0x6b1f, 0x37ed, + 0x6b20, 0x0c34, + 0x6b21, 0x0551, + 0x6b22, 0x07cb, + 0x6b23, 0x0f8b, + 0x6b24, 0x19b1, + 0x6b25, 0x37ee, + 0x6b27, 0x0b78, + 0x6b28, 0x37f0, + 0x6b32, 0x10e0, + 0x6b33, 0x37fa, + 0x6b37, 0x19b2, + 0x6b38, 0x37fe, + 0x6b39, 0x19b3, + 0x6b3a, 0x0bfa, + 0x6b3b, 0x37ff, + 0x6b3d, 0x20e3, + 0x6b3e, 0x097b, + 0x6b3f, 0x3801, + 0x6b43, 0x19b4, + 0x6b44, 0x3805, + 0x6b46, 0x19b5, + 0x6b47, 0x0f75, + 0x6b48, 0x3807, + 0x6b49, 0x0c35, + 0x6b4a, 0x3808, + 0x6b4c, 0x06e3, + 0x6b4d, 0x380a, + 0x6b50, 0x20ad, + 0x6b51, 0x380d, + 0x6b59, 0x19b6, + 0x6b5a, 0x3815, + 0x6b5f, 0x24cb, + 0x6b60, 0x381a, + 0x6b61, 0x1f53, + 0x6b62, 0x11b8, + 0x6b63, 0x119e, + 0x6b64, 0x054e, + 0x6b65, 0x0484, + 0x6b66, 0x0ef3, + 0x6b67, 0x0c06, + 0x6b68, 0x381b, + 0x6b6a, 0x0e92, + 0x6b6b, 0x381d, + 0x6b72, 0x2159, + 0x6b73, 0x3824, + 0x6b77, 0x2013, + 0x6b78, 0x1f33, + 0x6b79, 0x0578, + 0x6b7a, 0x3828, + 0x6b7b, 0x0db5, + 0x6b7c, 0x0852, + 0x6b7d, 0x3829, + 0x6b81, 0x18d6, + 0x6b83, 0x1013, + 0x6b84, 0x18d9, + 0x6b85, 0x382d, + 0x6b86, 0x057c, + 0x6b87, 0x18d8, + 0x6b88, 0x382e, + 0x6b89, 0x0fdc, + 0x6b8a, 0x0d79, + 0x6b8b, 0x0497, + 0x6b8c, 0x382f, + 0x6b8d, 0x18dc, + 0x6b8e, 0x3830, + 0x6b92, 0x18da, + 0x6b94, 0x3834, + 0x6b96, 0x11b2, + 0x6b97, 0x3836, + 0x6b98, 0x1e5c, + 0x6b99, 0x3837, + 0x6b9a, 0x18dd, + 0x6b9c, 0x3838, + 0x6b9e, 0x2488, + 0x6b9f, 0x383a, + 0x6ba1, 0x18df, + 0x6ba2, 0x383c, + 0x6ba4, 0x2487, + 0x6ba5, 0x383e, + 0x6baa, 0x18e0, + 0x6bab, 0x248a, + 0x6bac, 0x3843, + 0x6bae, 0x2489, + 0x6baf, 0x248b, + 0x6bb0, 0x3845, + 0x6bb2, 0x1f83, + 0x6bb3, 0x19bd, + 0x6bb4, 0x0b7a, + 0x6bb5, 0x060d, + 0x6bb6, 0x3847, + 0x6bb7, 0x107a, + 0x6bb8, 0x3848, + 0x6bba, 0x210f, + 0x6bbb, 0x1fdb, + 0x6bbc, 0x384a, + 0x6bbf, 0x05cf, + 0x6bc0, 0x384d, + 0x6bc1, 0x07ee, + 0x6bc2, 0x19bf, + 0x6bc3, 0x384e, + 0x6bc5, 0x106a, + 0x6bc6, 0x20af, + 0x6bc7, 0x3850, + 0x6bcb, 0x0ef2, + 0x6bcc, 0x3854, + 0x6bcd, 0x0b1b, + 0x6bce, 0x3855, + 0x6bcf, 0x0ac4, + 0x6bd0, 0x3856, + 0x6bd2, 0x05fd, + 0x6bd3, 0x126f, + 0x6bd4, 0x0431, + 0x6bd5, 0x0438, + 0x6bd6, 0x043a, + 0x6bd7, 0x0bbf, + 0x6bd8, 0x3858, + 0x6bd9, 0x0439, + 0x6bda, 0x3859, + 0x6bdb, 0x0ab0, + 0x6bdc, 0x385a, + 0x6be1, 0x1152, + 0x6be2, 0x385f, + 0x6bea, 0x1954, + 0x6beb, 0x0778, + 0x6bec, 0x3867, + 0x6bef, 0x0e0d, + 0x6bf0, 0x386a, + 0x6bf3, 0x1955, + 0x6bf4, 0x386d, + 0x6bf5, 0x1957, + 0x6bf6, 0x386e, + 0x6bf9, 0x1958, + 0x6bfa, 0x3871, + 0x6bfd, 0x1956, + 0x6bfe, 0x3874, + 0x6bff, 0x24c0, + 0x6c00, 0x3875, + 0x6c05, 0x1959, + 0x6c06, 0x195b, + 0x6c07, 0x195a, + 0x6c08, 0x226d, + 0x6c09, 0x387a, + 0x6c0c, 0x24c1, + 0x6c0d, 0x195c, + 0x6c0e, 0x387d, + 0x6c0f, 0x0d66, + 0x6c10, 0x126b, + 0x6c11, 0x0af6, + 0x6c12, 0x387e, + 0x6c13, 0x0aaa, + 0x6c14, 0x0c17, + 0x6c15, 0x195d, + 0x6c16, 0x0b2d, + 0x6c17, 0x387f, + 0x6c18, 0x195e, + 0x6c1b, 0x0672, + 0x6c1c, 0x3880, + 0x6c1f, 0x0697, + 0x6c20, 0x3883, + 0x6c21, 0x1961, + 0x6c22, 0x0c5f, + 0x6c23, 0x20ca, + 0x6c24, 0x1963, + 0x6c25, 0x3884, + 0x6c26, 0x075b, + 0x6c27, 0x101e, + 0x6c28, 0x03bc, + 0x6c29, 0x1962, + 0x6c2a, 0x1964, + 0x6c2b, 0x20e7, + 0x6c2c, 0x24c2, + 0x6c2d, 0x3885, + 0x6c2e, 0x058b, + 0x6c2f, 0x0a6f, + 0x6c30, 0x0c65, + 0x6c31, 0x3886, + 0x6c32, 0x1965, + 0x6c33, 0x3887, + 0x6c34, 0x0da3, + 0x6c35, 0x169f, + 0x6c36, 0x3888, + 0x6c38, 0x10a5, + 0x6c39, 0x388a, + 0x6c3d, 0x12ef, + 0x6c3e, 0x388e, + 0x6c40, 0x0e52, + 0x6c41, 0x11ac, + 0x6c42, 0x0c70, + 0x6c43, 0x3890, + 0x6c46, 0x12f4, + 0x6c47, 0x07f8, + 0x6c48, 0x3893, + 0x6c49, 0x0771, + 0x6c4a, 0x16a2, + 0x6c4b, 0x3894, + 0x6c50, 0x0f18, + 0x6c51, 0x3899, + 0x6c54, 0x16a0, + 0x6c55, 0x0d00, + 0x6c56, 0x389c, + 0x6c57, 0x0770, + 0x6c58, 0x389d, + 0x6c5b, 0x0fdd, + 0x6c5c, 0x16a1, + 0x6c5d, 0x0cc5, + 0x6c5e, 0x0708, + 0x6c5f, 0x087e, + 0x6c60, 0x04fd, + 0x6c61, 0x0eea, + 0x6c62, 0x38a0, + 0x6c64, 0x0e13, + 0x6c65, 0x38a2, + 0x6c68, 0x16a8, + 0x6c6a, 0x0ea5, + 0x6c6b, 0x38a5, + 0x6c70, 0x0e00, + 0x6c71, 0x38aa, + 0x6c72, 0x0826, + 0x6c73, 0x38ab, + 0x6c74, 0x16aa, + 0x6c75, 0x38ac, + 0x6c76, 0x16ab, + 0x6c77, 0x38ad, + 0x6c79, 0x0fa5, + 0x6c7a, 0x38af, + 0x6c7d, 0x0c1a, + 0x6c7e, 0x0677, + 0x6c7f, 0x38b2, + 0x6c81, 0x0c5c, + 0x6c82, 0x1051, + 0x6c83, 0x0ee5, + 0x6c84, 0x38b4, + 0x6c85, 0x16a4, + 0x6c86, 0x16ac, + 0x6c87, 0x38b5, + 0x6c88, 0x0d2b, + 0x6c89, 0x04e6, + 0x6c8a, 0x38b6, + 0x6c8c, 0x16a7, + 0x6c8d, 0x38b8, + 0x6c8f, 0x0c02, + 0x6c90, 0x16a5, + 0x6c91, 0x38ba, + 0x6c93, 0x1a1f, + 0x6c94, 0x16a6, + 0x6c95, 0x38bc, + 0x6c99, 0x0cec, + 0x6c9a, 0x38c0, + 0x6c9b, 0x0ba7, + 0x6c9c, 0x38c1, + 0x6c9f, 0x070e, + 0x6ca0, 0x38c4, + 0x6ca1, 0x0ac0, + 0x6ca2, 0x38c5, + 0x6ca3, 0x16a3, + 0x6ca4, 0x0b7e, + 0x6ca5, 0x09ed, + 0x6ca6, 0x0a80, + 0x6ca7, 0x049e, + 0x6ca8, 0x38c6, + 0x6ca9, 0x16ad, + 0x6caa, 0x07bb, + 0x6cab, 0x0b10, + 0x6cac, 0x38c7, + 0x6cad, 0x16b0, + 0x6cae, 0x0909, + 0x6caf, 0x38c8, + 0x6cb1, 0x16bb, + 0x6cb2, 0x16b5, + 0x6cb3, 0x078a, + 0x6cb4, 0x38ca, + 0x6cb8, 0x066d, + 0x6cb9, 0x10b2, + 0x6cba, 0x38ce, + 0x6cbb, 0x11cd, + 0x6cbc, 0x1174, + 0x6cbd, 0x071a, + 0x6cbe, 0x1155, + 0x6cbf, 0x1001, + 0x6cc0, 0x38cf, + 0x6cc4, 0x0f84, + 0x6cc5, 0x0c73, + 0x6cc6, 0x38d3, + 0x6cc9, 0x0c85, + 0x6cca, 0x047b, + 0x6ccb, 0x38d6, + 0x6ccc, 0x0adf, + 0x6ccd, 0x38d7, + 0x6cd0, 0x16ae, + 0x6cd1, 0x38da, + 0x6cd3, 0x16bc, + 0x6cd4, 0x16af, + 0x6cd5, 0x0645, + 0x6cd6, 0x16b7, + 0x6cd7, 0x16b4, + 0x6cd8, 0x38dc, + 0x6cdb, 0x0657, + 0x6cdc, 0x38df, + 0x6cde, 0x0b63, + 0x6cdf, 0x38e1, + 0x6ce0, 0x16b6, + 0x6ce1, 0x0b9e, + 0x6ce2, 0x046f, + 0x6ce3, 0x0c1b, + 0x6ce4, 0x38e2, + 0x6ce5, 0x0b43, + 0x6ce6, 0x38e3, + 0x6ce8, 0x11ff, + 0x6ce9, 0x38e5, + 0x6cea, 0x09cc, + 0x6ceb, 0x16b9, + 0x6cec, 0x38e6, + 0x6cee, 0x16ba, + 0x6cef, 0x16bd, + 0x6cf0, 0x0dfc, + 0x6cf1, 0x16b3, + 0x6cf2, 0x38e8, + 0x6cf3, 0x10a3, + 0x6cf4, 0x38e9, + 0x6cf5, 0x042c, + 0x6cf6, 0x1a20, + 0x6cf7, 0x16b1, + 0x6cf9, 0x38ea, + 0x6cfa, 0x16b8, + 0x6cfb, 0x0f85, + 0x6cfc, 0x0be2, + 0x6cfd, 0x1136, + 0x6cfe, 0x16be, + 0x6cff, 0x38eb, + 0x6d00, 0x38ec, + 0x6d01, 0x08b1, + 0x6d02, 0x38ed, + 0x6d04, 0x16c5, + 0x6d05, 0x38ef, + 0x6d07, 0x16c4, + 0x6d08, 0x38f1, + 0x6d0b, 0x101c, + 0x6d0c, 0x16c1, + 0x6d0d, 0x38f4, + 0x6d0e, 0x16c7, + 0x6d0f, 0x38f5, + 0x6d12, 0x0cd2, + 0x6d13, 0x38f8, + 0x6d17, 0x0f21, + 0x6d18, 0x38fc, + 0x6d19, 0x16c6, + 0x6d1a, 0x16cc, + 0x6d1b, 0x0a8c, + 0x6d1c, 0x38fd, + 0x6d1e, 0x05f3, + 0x6d1f, 0x38ff, + 0x6d25, 0x08c3, + 0x6d26, 0x3905, + 0x6d27, 0x16c0, + 0x6d28, 0x3906, + 0x6d2a, 0x07a0, + 0x6d2b, 0x16c8, + 0x6d2c, 0x3908, + 0x6d2e, 0x16ca, + 0x6d2f, 0x390a, + 0x6d31, 0x063c, + 0x6d32, 0x11dd, + 0x6d33, 0x16d0, + 0x6d34, 0x390c, + 0x6d35, 0x16cb, + 0x6d36, 0x390d, + 0x6d39, 0x16bf, + 0x6d3a, 0x3910, + 0x6d3b, 0x0803, + 0x6d3c, 0x0e8e, + 0x6d3d, 0x0c1f, + 0x6d3e, 0x0b8a, + 0x6d3f, 0x3911, + 0x6d41, 0x0a40, + 0x6d42, 0x3913, + 0x6d43, 0x16c2, + 0x6d44, 0x3914, + 0x6d45, 0x0c30, + 0x6d46, 0x087d, + 0x6d47, 0x088e, + 0x6d48, 0x16c3, + 0x6d49, 0x3915, + 0x6d4a, 0x1224, + 0x6d4b, 0x04a9, + 0x6d4c, 0x3916, + 0x6d4d, 0x16c9, + 0x6d4e, 0x0836, + 0x6d4f, 0x16cd, + 0x6d50, 0x3917, + 0x6d51, 0x0800, + 0x6d52, 0x16ce, + 0x6d53, 0x0b69, + 0x6d54, 0x16cf, + 0x6d55, 0x3918, + 0x6d59, 0x1184, + 0x6d5a, 0x0930, + 0x6d5b, 0x391c, + 0x6d5c, 0x16d8, + 0x6d5d, 0x391d, + 0x6d5e, 0x16d5, + 0x6d5f, 0x391e, + 0x6d60, 0x16d9, + 0x6d61, 0x391f, + 0x6d63, 0x16db, + 0x6d64, 0x3921, + 0x6d66, 0x0bf5, + 0x6d67, 0x3923, + 0x6d69, 0x077d, + 0x6d6a, 0x09b6, + 0x6d6b, 0x3925, + 0x6d6e, 0x069c, + 0x6d6f, 0x16d2, + 0x6d70, 0x3928, + 0x6d74, 0x10e4, + 0x6d75, 0x392c, + 0x6d77, 0x075a, + 0x6d78, 0x08cf, + 0x6d79, 0x23dc, + 0x6d7a, 0x392e, + 0x6d7c, 0x16da, + 0x6d7d, 0x3930, + 0x6d82, 0x0e70, + 0x6d83, 0x3935, + 0x6d85, 0x0b5c, + 0x6d86, 0x3937, + 0x6d87, 0x23db, + 0x6d88, 0x0f68, + 0x6d89, 0x0d1f, + 0x6d8a, 0x3938, + 0x6d8c, 0x10a4, + 0x6d8d, 0x393a, + 0x6d8e, 0x0f3e, + 0x6d8f, 0x393b, + 0x6d91, 0x16d1, + 0x6d92, 0x393d, + 0x6d93, 0x16d6, + 0x6d95, 0x0e3c, + 0x6d96, 0x393e, + 0x6d9b, 0x0e21, + 0x6d9c, 0x3943, + 0x6d9d, 0x09bf, + 0x6d9e, 0x16d3, + 0x6d9f, 0x09f9, + 0x6da0, 0x16d4, + 0x6da1, 0x0edf, + 0x6da2, 0x3944, + 0x6da3, 0x07d6, + 0x6da4, 0x05b4, + 0x6da5, 0x3945, + 0x6da6, 0x0cce, + 0x6da7, 0x0878, + 0x6da8, 0x1168, + 0x6da9, 0x0ce5, + 0x6daa, 0x069d, + 0x6dab, 0x16e8, + 0x6dac, 0x3946, + 0x6dae, 0x16ea, + 0x6daf, 0x0fed, + 0x6db0, 0x3948, + 0x6db2, 0x1041, + 0x6db3, 0x394a, + 0x6db5, 0x0764, + 0x6db6, 0x394c, + 0x6db8, 0x078b, + 0x6db9, 0x394e, + 0x6dbf, 0x16e1, + 0x6dc0, 0x05ce, + 0x6dc1, 0x3954, + 0x6dc4, 0x122a, + 0x6dc5, 0x16de, + 0x6dc6, 0x0f6a, + 0x6dc7, 0x16dd, + 0x6dc8, 0x3957, + 0x6dcb, 0x0a25, + 0x6dcc, 0x0e1d, + 0x6dcd, 0x395a, + 0x6dd1, 0x0d7e, + 0x6dd2, 0x395e, + 0x6dd6, 0x0b3a, + 0x6dd7, 0x3962, + 0x6dd8, 0x0e27, + 0x6dd9, 0x16e6, + 0x6dda, 0x3963, + 0x6ddd, 0x16e5, + 0x6dde, 0x16df, + 0x6ddf, 0x3966, + 0x6de0, 0x16e2, + 0x6de1, 0x058e, + 0x6de2, 0x3967, + 0x6de4, 0x10be, + 0x6de5, 0x3969, + 0x6de6, 0x16e4, + 0x6de7, 0x396a, + 0x6dea, 0x205e, + 0x6deb, 0x1080, + 0x6dec, 0x0566, + 0x6ded, 0x396d, + 0x6dee, 0x07c9, + 0x6def, 0x396e, + 0x6df1, 0x0d27, + 0x6df2, 0x3970, + 0x6df3, 0x0541, + 0x6df4, 0x3971, + 0x6df5, 0x2244, + 0x6df6, 0x23e2, + 0x6df7, 0x0801, + 0x6df8, 0x3972, + 0x6df9, 0x0ff6, + 0x6dfa, 0x20d4, + 0x6dfb, 0x0e40, + 0x6dfc, 0x1a21, + 0x6dfd, 0x3973, + 0x6e00, 0x3976, + 0x6e05, 0x0c62, + 0x6e06, 0x397b, + 0x6e0a, 0x10eb, + 0x6e0b, 0x397f, + 0x6e0c, 0x16e9, + 0x6e0d, 0x1232, + 0x6e0e, 0x16e0, + 0x6e0f, 0x3980, + 0x6e10, 0x0876, + 0x6e11, 0x16e3, + 0x6e12, 0x3981, + 0x6e14, 0x10cb, + 0x6e15, 0x3983, + 0x6e16, 0x16e7, + 0x6e17, 0x0d31, + 0x6e18, 0x3984, + 0x6e1a, 0x16dc, + 0x6e1b, 0x3986, + 0x6e1d, 0x10ca, + 0x6e1e, 0x3988, + 0x6e20, 0x0c7b, + 0x6e21, 0x0608, + 0x6e22, 0x398a, + 0x6e23, 0x113f, + 0x6e24, 0x047a, + 0x6e25, 0x16f5, + 0x6e26, 0x219f, + 0x6e27, 0x398b, + 0x6e29, 0x0ed1, + 0x6e2a, 0x398d, + 0x6e2b, 0x16eb, + 0x6e2c, 0x1e66, + 0x6e2d, 0x0ecb, + 0x6e2e, 0x398e, + 0x6e2f, 0x06d6, + 0x6e30, 0x398f, + 0x6e32, 0x16f4, + 0x6e33, 0x3991, + 0x6e34, 0x0957, + 0x6e35, 0x3992, + 0x6e38, 0x10b3, + 0x6e39, 0x3995, + 0x6e3a, 0x0af1, + 0x6e3b, 0x3996, + 0x6e3e, 0x1f63, + 0x6e3f, 0x3999, + 0x6e43, 0x0b89, + 0x6e44, 0x16f6, + 0x6e45, 0x399d, + 0x6e4d, 0x0e75, + 0x6e4e, 0x16ed, + 0x6e4f, 0x39a5, + 0x6e53, 0x16f2, + 0x6e55, 0x39a9, + 0x6e56, 0x07b5, + 0x6e57, 0x39aa, + 0x6e58, 0x0f53, + 0x6e59, 0x39ab, + 0x6e5b, 0x1160, + 0x6e5c, 0x39ad, + 0x6e5e, 0x23dd, + 0x6e5f, 0x16f0, + 0x6e60, 0x39af, + 0x6e6b, 0x16ee, + 0x6e6c, 0x39ba, + 0x6e6e, 0x16ec, + 0x6e6f, 0x216b, + 0x6e70, 0x39bc, + 0x6e7e, 0x0e96, + 0x6e7f, 0x0d41, + 0x6e80, 0x39ca, + 0x6e83, 0x098e, + 0x6e84, 0x39cd, + 0x6e85, 0x0877, + 0x6e86, 0x16f1, + 0x6e87, 0x39ce, + 0x6e89, 0x06c3, + 0x6e8a, 0x39d0, + 0x6e8f, 0x1705, + 0x6e90, 0x10f7, + 0x6e91, 0x39d5, + 0x6e96, 0x22b5, + 0x6e97, 0x39da, + 0x6e98, 0x16f9, + 0x6e99, 0x39db, + 0x6e9c, 0x0a38, + 0x6e9d, 0x1f26, + 0x6e9e, 0x39de, + 0x6e9f, 0x1707, + 0x6ea0, 0x39df, + 0x6ea2, 0x106e, + 0x6ea3, 0x39e1, + 0x6ea5, 0x16fd, + 0x6ea6, 0x39e3, + 0x6ea7, 0x16fe, + 0x6ea8, 0x39e4, + 0x6eaa, 0x0f17, + 0x6eab, 0x39e6, + 0x6eaf, 0x0dd2, + 0x6eb0, 0x39ea, + 0x6eb1, 0x16f8, + 0x6eb2, 0x16ef, + 0x6eb3, 0x39eb, + 0x6eb4, 0x1703, + 0x6eb5, 0x39ec, + 0x6eb6, 0x0cb7, + 0x6eb7, 0x1701, + 0x6eb8, 0x39ed, + 0x6eba, 0x0b4a, + 0x6ebb, 0x1700, + 0x6ebc, 0x39ef, + 0x6ebd, 0x16ff, + 0x6ebe, 0x39f0, + 0x6ec1, 0x0521, + 0x6ec2, 0x1706, + 0x6ec3, 0x39f3, + 0x6ec4, 0x1e63, + 0x6ec5, 0x2088, + 0x6ec6, 0x39f4, + 0x6ec7, 0x05c2, + 0x6ec8, 0x39f5, + 0x6ecb, 0x1229, + 0x6ecc, 0x1ebd, + 0x6ecd, 0x39f8, + 0x6ece, 0x2341, + 0x6ecf, 0x1704, + 0x6ed0, 0x39f9, + 0x6ed1, 0x07c1, + 0x6ed2, 0x39fa, + 0x6ed3, 0x122f, + 0x6ed4, 0x0e22, + 0x6ed5, 0x19a8, + 0x6ed6, 0x39fb, + 0x6ed7, 0x1702, + 0x6ed8, 0x39fc, + 0x6eda, 0x074f, + 0x6edb, 0x39fe, + 0x6ede, 0x11cc, + 0x6edf, 0x16f7, + 0x6ee0, 0x16fa, + 0x6ee1, 0x0aa1, + 0x6ee2, 0x16fc, + 0x6ee3, 0x3a01, + 0x6ee4, 0x0a72, + 0x6ee5, 0x09af, + 0x6ee6, 0x0a77, + 0x6ee7, 0x3a02, + 0x6ee8, 0x045e, + 0x6ee9, 0x0e05, + 0x6eea, 0x3a03, + 0x6eec, 0x1f4b, + 0x6eed, 0x3a05, + 0x6eef, 0x2292, + 0x6ef0, 0x3a07, + 0x6ef2, 0x2124, + 0x6ef3, 0x3a09, + 0x6ef4, 0x05af, + 0x6ef5, 0x3a0a, + 0x6ef7, 0x2048, + 0x6ef8, 0x23e0, + 0x6ef9, 0x170d, + 0x6efa, 0x3a0c, + 0x6eff, 0x2077, + 0x6f00, 0x3a11, + 0x6f01, 0x223a, + 0x6f02, 0x0bce, + 0x6f03, 0x3a12, + 0x6f06, 0x0c00, + 0x6f07, 0x3a15, + 0x6f09, 0x1713, + 0x6f0a, 0x3a17, + 0x6f0f, 0x0a50, + 0x6f10, 0x3a1c, + 0x6f13, 0x09d7, + 0x6f14, 0x1006, + 0x6f15, 0x170c, + 0x6f16, 0x3a1f, + 0x6f1a, 0x20b1, + 0x6f1b, 0x3a23, + 0x6f20, 0x0b11, + 0x6f21, 0x3a28, + 0x6f22, 0x1f41, + 0x6f23, 0x201c, + 0x6f24, 0x170b, + 0x6f25, 0x3a29, + 0x6f29, 0x1714, + 0x6f2a, 0x1712, + 0x6f2b, 0x0aa5, + 0x6f2c, 0x22b8, + 0x6f2d, 0x16fb, + 0x6f2e, 0x3a2d, + 0x6f2f, 0x170e, + 0x6f30, 0x3a2e, + 0x6f31, 0x0d95, + 0x6f32, 0x2276, + 0x6f33, 0x1165, + 0x6f34, 0x3a2f, + 0x6f36, 0x170f, + 0x6f37, 0x3a31, + 0x6f38, 0x1f9b, + 0x6f39, 0x3a32, + 0x6f3e, 0x1023, + 0x6f3f, 0x1f9f, + 0x6f40, 0x3a37, + 0x6f41, 0x25ca, + 0x6f42, 0x3a38, + 0x6f46, 0x1709, + 0x6f48, 0x3a3c, + 0x6f4b, 0x1710, + 0x6f4c, 0x3a3f, + 0x6f4d, 0x0eba, + 0x6f4e, 0x3a40, + 0x6f51, 0x20be, + 0x6f52, 0x3a43, + 0x6f54, 0x1fb4, + 0x6f55, 0x3a45, + 0x6f58, 0x0b8c, + 0x6f59, 0x23d7, + 0x6f5a, 0x3a48, + 0x6f5c, 0x0c2e, + 0x6f5d, 0x3a4a, + 0x6f5e, 0x0a61, + 0x6f5f, 0x3a4b, + 0x6f62, 0x1708, + 0x6f63, 0x3a4e, + 0x6f64, 0x2105, + 0x6f65, 0x3a4f, + 0x6f66, 0x0a13, + 0x6f67, 0x3a50, + 0x6f6d, 0x0e09, + 0x6f6e, 0x04d6, + 0x6f6f, 0x23e1, + 0x6f70, 0x1fec, + 0x6f71, 0x3a56, + 0x6f72, 0x1719, + 0x6f73, 0x3a57, + 0x6f74, 0x1711, + 0x6f75, 0x3a58, + 0x6f77, 0x23ea, + 0x6f78, 0x1718, + 0x6f79, 0x3a5a, + 0x6f7a, 0x171b, + 0x6f7b, 0x3a5b, + 0x6f7c, 0x171a, + 0x6f7d, 0x3a5c, + 0x6f7f, 0x23e3, + 0x6f80, 0x210e, + 0x6f81, 0x3a5e, + 0x6f84, 0x04f3, + 0x6f85, 0x3a61, + 0x6f86, 0x1fa6, + 0x6f87, 0x2004, + 0x6f88, 0x04df, + 0x6f89, 0x1715, + 0x6f8a, 0x3a62, + 0x6f8c, 0x1717, + 0x6f8d, 0x1716, + 0x6f8e, 0x0bad, + 0x6f8f, 0x3a64, + 0x6f97, 0x1f9d, + 0x6f98, 0x3a6c, + 0x6f9c, 0x09a8, + 0x6f9d, 0x3a70, + 0x6fa0, 0x23e5, + 0x6fa1, 0x112b, + 0x6fa2, 0x3a73, + 0x6fa4, 0x2264, + 0x6fa5, 0x3a75, + 0x6fa7, 0x171e, + 0x6fa8, 0x3a77, + 0x6fa9, 0x24e2, + 0x6faa, 0x3a78, + 0x6fae, 0x23de, + 0x6faf, 0x3a7c, + 0x6fb1, 0x1ec4, + 0x6fb2, 0x3a7e, + 0x6fb3, 0x03cf, + 0x6fb4, 0x3a7f, + 0x6fb6, 0x1720, + 0x6fb7, 0x3a81, + 0x6fb9, 0x171f, + 0x6fba, 0x3a83, + 0x6fc0, 0x0817, + 0x6fc1, 0x22b6, + 0x6fc2, 0x1721, + 0x6fc3, 0x20a9, + 0x6fc4, 0x3a89, + 0x6fc9, 0x171d, + 0x6fca, 0x3a8e, + 0x6fd1, 0x171c, + 0x6fd2, 0x045d, + 0x6fd3, 0x3a95, + 0x6fd5, 0x212b, + 0x6fd6, 0x3a97, + 0x6fd8, 0x20a5, + 0x6fd9, 0x3a99, + 0x6fdb, 0x268b, + 0x6fdc, 0x3a9b, + 0x6fde, 0x1724, + 0x6fdf, 0x1f76, + 0x6fe0, 0x1725, + 0x6fe1, 0x1722, + 0x6fe2, 0x3a9d, + 0x6fe4, 0x216d, + 0x6fe5, 0x3a9f, + 0x6feb, 0x2001, + 0x6fec, 0x3aa5, + 0x6fee, 0x1723, + 0x6fef, 0x1726, + 0x6ff0, 0x2191, + 0x6ff1, 0x1e50, + 0x6ff2, 0x3aa7, + 0x6ffa, 0x1f9c, + 0x6ffb, 0x3aaf, + 0x6ffc, 0x23da, + 0x6ffd, 0x3ab0, + 0x6ffe, 0x2053, + 0x6fff, 0x3ab1, + 0x7000, 0x3ab2, + 0x7005, 0x23e9, + 0x7006, 0x23e4, + 0x7007, 0x3ab7, + 0x7009, 0x21d5, + 0x700a, 0x3ab9, + 0x700b, 0x23e6, + 0x700c, 0x3aba, + 0x700f, 0x23df, + 0x7010, 0x3abd, + 0x7011, 0x0bf8, + 0x7012, 0x3abe, + 0x7015, 0x1e4f, + 0x7016, 0x3ac1, + 0x7018, 0x23d9, + 0x7019, 0x3ac3, + 0x701a, 0x1727, + 0x701b, 0x1729, + 0x701c, 0x3ac4, + 0x701d, 0x2014, + 0x701e, 0x3ac5, + 0x701f, 0x23ec, + 0x7020, 0x23eb, + 0x7021, 0x3ac6, + 0x7023, 0x1728, + 0x7024, 0x3ac8, + 0x7027, 0x23d8, + 0x7028, 0x23ee, + 0x7029, 0x3acb, + 0x7030, 0x268e, + 0x7031, 0x3ad2, + 0x7032, 0x23ed, + 0x7033, 0x3ad3, + 0x7035, 0x172b, + 0x7036, 0x3ad5, + 0x7039, 0x172a, + 0x703a, 0x3ad8, + 0x703e, 0x1ffa, + 0x703f, 0x3adc, + 0x7043, 0x23d6, + 0x7044, 0x23e8, + 0x7045, 0x3ae0, + 0x704c, 0x0739, + 0x704d, 0x3ae7, + 0x704f, 0x172c, + 0x7050, 0x3ae9, + 0x7051, 0x2106, + 0x7052, 0x3aea, + 0x7055, 0x200b, + 0x7056, 0x3aed, + 0x7058, 0x2166, + 0x7059, 0x3aef, + 0x705d, 0x23ef, + 0x705e, 0x172d, + 0x705f, 0x3af3, + 0x7063, 0x2189, + 0x7064, 0x2058, + 0x7065, 0x3af7, + 0x7067, 0x23e7, + 0x7068, 0x3af9, + 0x706b, 0x0805, + 0x706c, 0x19ef, + 0x706d, 0x0af5, + 0x706e, 0x3afc, + 0x706f, 0x05a7, + 0x7070, 0x07e7, + 0x7071, 0x3afd, + 0x7075, 0x0a32, + 0x7076, 0x1131, + 0x7077, 0x3b01, + 0x7078, 0x08f3, + 0x7079, 0x3b02, + 0x707c, 0x1223, + 0x707d, 0x3b05, + 0x707e, 0x1119, + 0x707f, 0x049a, + 0x7080, 0x19cc, + 0x7081, 0x3b06, + 0x7085, 0x1913, + 0x7086, 0x3b0a, + 0x7089, 0x0a56, + 0x708a, 0x0539, + 0x708b, 0x3b0d, + 0x708e, 0x1000, + 0x708f, 0x3b10, + 0x7092, 0x04d9, + 0x7093, 0x3b13, + 0x7094, 0x0c8d, + 0x7095, 0x0948, + 0x7096, 0x19ce, + 0x7097, 0x3b14, + 0x7099, 0x11ca, + 0x709a, 0x3b16, + 0x709c, 0x19cd, + 0x709d, 0x19cf, + 0x709e, 0x3b18, + 0x70ab, 0x19d3, + 0x70ac, 0x0915, + 0x70ad, 0x0e12, + 0x70ae, 0x0b9b, + 0x70af, 0x08eb, + 0x70b0, 0x3b25, + 0x70b1, 0x19d4, + 0x70b2, 0x3b26, + 0x70b3, 0x0467, + 0x70b4, 0x3b27, + 0x70b7, 0x19d2, + 0x70b8, 0x1149, + 0x70b9, 0x05c4, + 0x70ba, 0x3b2a, + 0x70bb, 0x19d0, + 0x70bc, 0x09ff, + 0x70bd, 0x0508, + 0x70be, 0x3b2b, + 0x70c0, 0x19d1, + 0x70c1, 0x0dad, + 0x70c2, 0x09ae, + 0x70c3, 0x0e51, + 0x70c4, 0x3b2d, + 0x70c8, 0x0a1b, + 0x70c9, 0x3b31, + 0x70ca, 0x19d6, + 0x70cb, 0x3b32, + 0x70cf, 0x21a3, + 0x70d0, 0x3b36, + 0x70d8, 0x079d, + 0x70d9, 0x09be, + 0x70da, 0x3b3e, + 0x70db, 0x11f1, + 0x70dc, 0x3b3f, + 0x70df, 0x0ff5, + 0x70e0, 0x3b42, + 0x70e4, 0x094b, + 0x70e5, 0x3b46, + 0x70e6, 0x0650, + 0x70e7, 0x0d0e, + 0x70e8, 0x19d5, + 0x70e9, 0x07f7, + 0x70ea, 0x3b47, + 0x70eb, 0x0e1f, + 0x70ec, 0x08ce, + 0x70ed, 0x0ca3, + 0x70ee, 0x3b48, + 0x70ef, 0x0f16, + 0x70f0, 0x3b49, + 0x70f4, 0x217a, + 0x70f5, 0x3b4d, + 0x70f7, 0x0e9a, + 0x70f8, 0x3b4f, + 0x70f9, 0x0bac, + 0x70fa, 0x3b50, + 0x70fd, 0x0686, + 0x70fe, 0x3b53, + 0x7100, 0x3b55, + 0x7109, 0x0ff2, + 0x710a, 0x076f, + 0x710b, 0x3b5e, + 0x7110, 0x19d7, + 0x7111, 0x3b63, + 0x7113, 0x19d8, + 0x7114, 0x3b65, + 0x7115, 0x07d5, + 0x7116, 0x19d9, + 0x7117, 0x3b66, + 0x7118, 0x19f0, + 0x7119, 0x0423, + 0x711a, 0x0676, + 0x711b, 0x3b67, + 0x7121, 0x21a5, + 0x7122, 0x3b6d, + 0x7126, 0x088a, + 0x7127, 0x3b71, + 0x712f, 0x19da, + 0x7130, 0x100f, + 0x7131, 0x19db, + 0x7132, 0x3b79, + 0x7136, 0x0c96, + 0x7137, 0x3b7d, + 0x7145, 0x19df, + 0x7146, 0x3b8b, + 0x7149, 0x2022, + 0x714a, 0x19e1, + 0x714b, 0x3b8e, + 0x714c, 0x07e2, + 0x714d, 0x3b8f, + 0x714e, 0x0858, + 0x714f, 0x3b90, + 0x7152, 0x24d6, + 0x7153, 0x3b93, + 0x715c, 0x19dd, + 0x715d, 0x3b9c, + 0x715e, 0x0cf0, + 0x715f, 0x3b9d, + 0x7162, 0x233a, + 0x7163, 0x3ba0, + 0x7164, 0x0abf, + 0x7165, 0x3ba1, + 0x7166, 0x19f1, + 0x7167, 0x1176, + 0x7168, 0x19de, + 0x7169, 0x1eee, + 0x716a, 0x3ba2, + 0x716c, 0x24d5, + 0x716d, 0x3ba4, + 0x716e, 0x11f2, + 0x716f, 0x3ba5, + 0x7172, 0x19e0, + 0x7173, 0x19dc, + 0x7174, 0x3ba8, + 0x7178, 0x19e2, + 0x7179, 0x3bac, + 0x717a, 0x19e3, + 0x717b, 0x3bad, + 0x717d, 0x0cf8, + 0x717e, 0x3baf, + 0x7184, 0x0f15, + 0x7185, 0x3bb5, + 0x718a, 0x0fa7, + 0x718b, 0x3bba, + 0x718f, 0x0fd5, + 0x7190, 0x3bbe, + 0x7192, 0x2228, + 0x7193, 0x3bc0, + 0x7194, 0x0cb6, + 0x7195, 0x3bc1, + 0x7197, 0x24d7, + 0x7198, 0x19e4, + 0x7199, 0x0f04, + 0x719a, 0x3bc3, + 0x719f, 0x0d83, + 0x71a0, 0x19e8, + 0x71a1, 0x3bc8, + 0x71a8, 0x19e7, + 0x71a9, 0x3bcf, + 0x71ac, 0x03c9, + 0x71ad, 0x3bd2, + 0x71b1, 0x20fc, + 0x71b2, 0x3bd6, + 0x71b3, 0x19e5, + 0x71b4, 0x3bd7, + 0x71b5, 0x19e6, + 0x71b6, 0x3bd8, + 0x71b9, 0x19f2, + 0x71ba, 0x3bdb, + 0x71be, 0x1e87, + 0x71bf, 0x3bdf, + 0x71c1, 0x24d8, + 0x71c2, 0x3be1, + 0x71c3, 0x0c97, + 0x71c4, 0x3be2, + 0x71c8, 0x1eba, + 0x71c9, 0x3be6, + 0x71ce, 0x0a10, + 0x71cf, 0x3beb, + 0x71d2, 0x2119, + 0x71d3, 0x3bee, + 0x71d4, 0x19ea, + 0x71d5, 0x1009, + 0x71d6, 0x3bef, + 0x71d9, 0x216c, + 0x71da, 0x3bf2, + 0x71dc, 0x24d9, + 0x71dd, 0x3bf4, + 0x71df, 0x2227, + 0x71e0, 0x19e9, + 0x71e1, 0x3bf6, + 0x71e5, 0x1132, + 0x71e6, 0x1e5f, + 0x71e7, 0x19eb, + 0x71e8, 0x3bfa, + 0x71ed, 0x229f, + 0x71ee, 0x1396, + 0x71ef, 0x3bff, + 0x71f4, 0x1f5d, + 0x71f5, 0x3c04, + 0x71f9, 0x19ec, + 0x71fa, 0x3c08, + 0x71fc, 0x1fbc, + 0x71fd, 0x3c0a, + 0x71fe, 0x24da, + 0x71ff, 0x3c0b, + 0x7200, 0x3c0c, + 0x7206, 0x0415, + 0x7207, 0x3c12, + 0x720d, 0x2149, + 0x720e, 0x3c18, + 0x7210, 0x2046, + 0x7211, 0x3c1a, + 0x721b, 0x2000, + 0x721c, 0x3c24, + 0x721d, 0x19ed, + 0x721e, 0x3c25, + 0x7228, 0x19ee, + 0x7229, 0x3c2f, + 0x722a, 0x1203, + 0x722b, 0x3c30, + 0x722c, 0x0b81, + 0x722d, 0x3c31, + 0x7230, 0x196c, + 0x7231, 0x03b9, + 0x7232, 0x2190, + 0x7233, 0x3c34, + 0x7235, 0x0923, + 0x7236, 0x06b3, + 0x7237, 0x1036, + 0x7238, 0x03e1, + 0x7239, 0x05da, + 0x723a, 0x2208, + 0x723b, 0x1269, + 0x723c, 0x3c36, + 0x723d, 0x0da1, + 0x723e, 0x1ee6, + 0x723f, 0x169d, + 0x7240, 0x3c37, + 0x7247, 0x0bcb, + 0x7248, 0x03f1, + 0x7249, 0x3c3e, + 0x724c, 0x0b87, + 0x724d, 0x1969, + 0x724e, 0x3c41, + 0x7252, 0x196a, + 0x7253, 0x3c45, + 0x7256, 0x196b, + 0x7257, 0x3c48, + 0x7258, 0x24c3, + 0x7259, 0x0fe9, + 0x725a, 0x3c49, + 0x725b, 0x0b64, + 0x725c, 0x3c4a, + 0x725d, 0x1944, + 0x725e, 0x3c4b, + 0x725f, 0x0b15, + 0x7260, 0x3c4c, + 0x7261, 0x0b18, + 0x7262, 0x09b9, + 0x7263, 0x3c4d, + 0x7266, 0x1945, + 0x7267, 0x0b24, + 0x7268, 0x3c50, + 0x7269, 0x0efe, + 0x726a, 0x3c51, + 0x726e, 0x1942, + 0x726f, 0x1946, + 0x7270, 0x3c55, + 0x7272, 0x0d35, + 0x7273, 0x3c57, + 0x7275, 0x0c20, + 0x7276, 0x3c59, + 0x7279, 0x0e2b, + 0x727a, 0x0f0d, + 0x727b, 0x3c5c, + 0x727d, 0x20cc, + 0x727e, 0x1947, + 0x7280, 0x0f19, + 0x7281, 0x09d2, + 0x7282, 0x3c5e, + 0x7284, 0x1949, + 0x7285, 0x3c60, + 0x728a, 0x05fe, + 0x728b, 0x194a, + 0x728c, 0x3c65, + 0x728d, 0x194b, + 0x728e, 0x3c66, + 0x728f, 0x194c, + 0x7290, 0x3c67, + 0x7292, 0x194d, + 0x7293, 0x3c69, + 0x7296, 0x2340, + 0x7297, 0x3c6c, + 0x729f, 0x1943, + 0x72a0, 0x3c74, + 0x72a2, 0x1ed1, + 0x72a3, 0x3c76, + 0x72a7, 0x21ac, + 0x72a8, 0x3c7a, + 0x72ac, 0x0c89, + 0x72ad, 0x15ef, + 0x72ae, 0x3c7e, + 0x72af, 0x0655, + 0x72b0, 0x15f0, + 0x72b1, 0x3c7f, + 0x72b4, 0x15f1, + 0x72b5, 0x3c82, + 0x72b6, 0x1211, + 0x72b7, 0x15f2, + 0x72b9, 0x10b1, + 0x72ba, 0x3c83, + 0x72c0, 0x22af, + 0x72c1, 0x15f5, + 0x72c2, 0x097e, + 0x72c3, 0x15f4, + 0x72c4, 0x05b3, + 0x72c5, 0x3c89, + 0x72c8, 0x0420, + 0x72c9, 0x3c8c, + 0x72cd, 0x15f7, + 0x72ce, 0x15f6, + 0x72cf, 0x3c90, + 0x72d0, 0x07b3, + 0x72d1, 0x3c91, + 0x72d2, 0x15f8, + 0x72d3, 0x3c92, + 0x72d7, 0x0710, + 0x72d8, 0x3c96, + 0x72d9, 0x0900, + 0x72da, 0x3c97, + 0x72de, 0x0b5f, + 0x72df, 0x3c9b, + 0x72e0, 0x0794, + 0x72e1, 0x0897, + 0x72e2, 0x3c9c, + 0x72e8, 0x15f9, + 0x72e9, 0x15fb, + 0x72ea, 0x3ca2, + 0x72ec, 0x05ff, + 0x72ed, 0x0f2e, + 0x72ee, 0x0d3f, + 0x72ef, 0x15fa, + 0x72f0, 0x1199, + 0x72f1, 0x10e1, + 0x72f2, 0x15fc, + 0x72f3, 0x1600, + 0x72f4, 0x15fd, + 0x72f5, 0x3ca4, + 0x72f7, 0x15fe, + 0x72f8, 0x09d5, + 0x72f9, 0x21b6, + 0x72fa, 0x1602, + 0x72fc, 0x09b2, + 0x72fd, 0x1e3d, + 0x72fe, 0x3ca6, + 0x7300, 0x3ca8, + 0x7301, 0x15ff, + 0x7302, 0x3ca9, + 0x7303, 0x1601, + 0x7304, 0x3caa, + 0x730a, 0x1607, + 0x730b, 0x3cb0, + 0x730e, 0x0a1d, + 0x730f, 0x3cb3, + 0x7313, 0x1605, + 0x7314, 0x3cb7, + 0x7315, 0x160a, + 0x7316, 0x04c5, + 0x7317, 0x1604, + 0x7318, 0x3cb8, + 0x731b, 0x0ad2, + 0x731c, 0x0489, + 0x731d, 0x1609, + 0x731e, 0x1608, + 0x731f, 0x3cbb, + 0x7321, 0x1606, + 0x7322, 0x160b, + 0x7323, 0x3cbd, + 0x7325, 0x160d, + 0x7326, 0x3cbf, + 0x7329, 0x0f94, + 0x732a, 0x11ec, + 0x732b, 0x0aad, + 0x732c, 0x160e, + 0x732d, 0x3cc2, + 0x732e, 0x0f44, + 0x732f, 0x3cc3, + 0x7331, 0x1610, + 0x7332, 0x3cc5, + 0x7334, 0x07a6, + 0x7335, 0x3cc7, + 0x7336, 0x2235, + 0x7337, 0x18d4, + 0x7338, 0x160f, + 0x7339, 0x160c, + 0x733a, 0x3cc8, + 0x733b, 0x2397, + 0x733c, 0x3cc9, + 0x733e, 0x07c0, + 0x733f, 0x10f6, + 0x7340, 0x3ccb, + 0x7341, 0x2395, + 0x7342, 0x3ccc, + 0x7344, 0x223f, + 0x7345, 0x212a, + 0x7346, 0x3cce, + 0x734d, 0x1612, + 0x734e, 0x3cd5, + 0x7350, 0x1611, + 0x7351, 0x3cd7, + 0x7352, 0x18d5, + 0x7353, 0x3cd8, + 0x7357, 0x1613, + 0x7358, 0x3cdc, + 0x7360, 0x1614, + 0x7361, 0x3ce4, + 0x7368, 0x1ed2, + 0x7369, 0x3ceb, + 0x736a, 0x2396, + 0x736b, 0x2398, + 0x736c, 0x1615, + 0x736d, 0x0df4, + 0x736e, 0x3cec, + 0x736f, 0x1616, + 0x7370, 0x20a2, + 0x7371, 0x3ced, + 0x7372, 0x1f64, + 0x7373, 0x3cee, + 0x7375, 0x202b, + 0x7376, 0x3cf0, + 0x7377, 0x2394, + 0x7378, 0x2139, + 0x7379, 0x3cf1, + 0x737a, 0x215f, + 0x737b, 0x21c1, + 0x737c, 0x239a, + 0x737d, 0x3cf2, + 0x737e, 0x1617, + 0x737f, 0x3cf3, + 0x7380, 0x2399, + 0x7381, 0x3cf4, + 0x7384, 0x0fc9, + 0x7385, 0x3cf7, + 0x7387, 0x0a71, + 0x7388, 0x3cf9, + 0x7389, 0x10d6, + 0x738a, 0x3cfa, + 0x738b, 0x0ea6, + 0x738c, 0x3cfb, + 0x738e, 0x1818, + 0x738f, 0x3cfd, + 0x7391, 0x1819, + 0x7392, 0x3cff, + 0x7396, 0x08f0, + 0x7397, 0x3d03, + 0x739b, 0x0a91, + 0x739c, 0x3d07, + 0x739f, 0x181c, + 0x73a0, 0x3d0a, + 0x73a2, 0x181b, + 0x73a3, 0x3d0c, + 0x73a9, 0x0e97, + 0x73aa, 0x3d12, + 0x73ab, 0x0aba, + 0x73ac, 0x3d13, + 0x73ae, 0x181a, + 0x73af, 0x07cc, + 0x73b0, 0x0f43, + 0x73b1, 0x3d15, + 0x73b2, 0x0a2a, + 0x73b3, 0x1821, + 0x73b4, 0x3d16, + 0x73b7, 0x1820, + 0x73b8, 0x3d19, + 0x73ba, 0x182c, + 0x73bb, 0x046a, + 0x73bc, 0x3d1b, + 0x73c0, 0x1822, + 0x73c1, 0x3d1f, + 0x73c2, 0x181e, + 0x73c3, 0x3d20, + 0x73c8, 0x1824, + 0x73c9, 0x1823, + 0x73ca, 0x0cf3, + 0x73cb, 0x3d25, + 0x73cd, 0x1185, + 0x73ce, 0x3d27, + 0x73cf, 0x181d, + 0x73d0, 0x0646, + 0x73d1, 0x181f, + 0x73d2, 0x3d28, + 0x73d9, 0x1826, + 0x73da, 0x3d2f, + 0x73de, 0x182b, + 0x73df, 0x3d33, + 0x73e0, 0x11e8, + 0x73e1, 0x3d34, + 0x73e5, 0x1825, + 0x73e6, 0x3d38, + 0x73e7, 0x182a, + 0x73e8, 0x3d39, + 0x73e9, 0x1829, + 0x73ea, 0x3d3a, + 0x73ed, 0x03eb, + 0x73ee, 0x3d3d, + 0x73f2, 0x182d, + 0x73f3, 0x3d41, + 0x73fe, 0x21c0, + 0x73ff, 0x3d4c, + 0x7400, 0x3d4d, + 0x7403, 0x0c6f, + 0x7404, 0x3d50, + 0x7405, 0x09b0, + 0x7406, 0x09d8, + 0x7407, 0x3d51, + 0x7409, 0x0a39, + 0x740a, 0x1828, + 0x740b, 0x3d53, + 0x740f, 0x182e, + 0x7410, 0x0deb, + 0x7411, 0x3d57, + 0x741a, 0x1838, + 0x741b, 0x1837, + 0x741c, 0x3d60, + 0x7422, 0x121e, + 0x7423, 0x3d66, + 0x7425, 0x1832, + 0x7426, 0x1831, + 0x7427, 0x3d68, + 0x7428, 0x1833, + 0x7429, 0x3d69, + 0x742a, 0x182f, + 0x742b, 0x3d6a, + 0x742c, 0x1836, + 0x742d, 0x3d6b, + 0x742e, 0x1835, + 0x742f, 0x3d6c, + 0x7430, 0x1834, + 0x7431, 0x3d6d, + 0x7433, 0x0a1e, + 0x7434, 0x0c56, + 0x7435, 0x0bbe, + 0x7436, 0x0b84, + 0x7437, 0x3d6f, + 0x743c, 0x0c6a, + 0x743d, 0x3d74, + 0x743f, 0x2460, + 0x7440, 0x3d76, + 0x7441, 0x1839, + 0x7442, 0x3d77, + 0x744b, 0x245c, + 0x744c, 0x3d80, + 0x7455, 0x183c, + 0x7456, 0x3d89, + 0x7457, 0x183b, + 0x7458, 0x3d8a, + 0x7459, 0x183d, + 0x745a, 0x07ae, + 0x745b, 0x1830, + 0x745c, 0x183a, + 0x745d, 0x3d8b, + 0x745e, 0x0ccb, + 0x745f, 0x0ce3, + 0x7460, 0x3d8c, + 0x7463, 0x215d, + 0x7464, 0x3d8f, + 0x7469, 0x2225, + 0x746a, 0x206a, + 0x746b, 0x3d94, + 0x746d, 0x183f, + 0x746e, 0x3d96, + 0x7470, 0x073e, + 0x7471, 0x3d98, + 0x7476, 0x1027, + 0x7477, 0x183e, + 0x7478, 0x3d9d, + 0x747e, 0x1840, + 0x747f, 0x3da3, + 0x7480, 0x1843, + 0x7482, 0x3da4, + 0x7483, 0x09f0, + 0x7484, 0x3da5, + 0x7487, 0x1845, + 0x7488, 0x3da8, + 0x7489, 0x2461, + 0x748a, 0x3da9, + 0x748b, 0x1846, + 0x748c, 0x3daa, + 0x748e, 0x1842, + 0x748f, 0x3dac, + 0x7490, 0x184a, + 0x7491, 0x3dad, + 0x749c, 0x1841, + 0x749d, 0x3db8, + 0x749e, 0x1847, + 0x749f, 0x3db9, + 0x74a3, 0x245b, + 0x74a4, 0x3dbd, + 0x74a6, 0x2462, + 0x74a7, 0x184b, + 0x74a8, 0x1848, + 0x74aa, 0x3dbf, + 0x74b0, 0x1f54, + 0x74b1, 0x3dc5, + 0x74ba, 0x184d, + 0x74bb, 0x3dce, + 0x74bd, 0x245f, + 0x74be, 0x3dd0, + 0x74ca, 0x20ec, + 0x74cb, 0x3ddc, + 0x74cf, 0x245d, + 0x74d0, 0x3de0, + 0x74d2, 0x184c, + 0x74d3, 0x3de2, + 0x74d4, 0x2463, + 0x74d5, 0x3de3, + 0x74da, 0x2464, + 0x74db, 0x3de8, + 0x74dc, 0x0728, + 0x74dd, 0x3de9, + 0x74de, 0x1b32, + 0x74df, 0x3dea, + 0x74e0, 0x1b33, + 0x74e1, 0x3deb, + 0x74e2, 0x0bcf, + 0x74e3, 0x03f5, + 0x74e4, 0x0c9a, + 0x74e5, 0x3dec, + 0x74e6, 0x0e90, + 0x74e7, 0x3ded, + 0x74ee, 0x0edc, + 0x74ef, 0x1903, + 0x74f0, 0x3df4, + 0x74f4, 0x1904, + 0x74f5, 0x3df8, + 0x74f6, 0x0bde, + 0x74f7, 0x054c, + 0x74f8, 0x3df9, + 0x74ff, 0x1905, + 0x7500, 0x3e00, + 0x7504, 0x1188, + 0x7505, 0x3e04, + 0x750c, 0x24a5, + 0x750d, 0x1485, + 0x750e, 0x3e0b, + 0x750f, 0x1906, + 0x7510, 0x3e0c, + 0x7511, 0x1907, + 0x7512, 0x3e0d, + 0x7513, 0x1908, + 0x7514, 0x3e0e, + 0x7518, 0x06c5, + 0x7519, 0x14f8, + 0x751a, 0x0d2e, + 0x751b, 0x3e12, + 0x751c, 0x0e43, + 0x751d, 0x3e13, + 0x751f, 0x0d33, + 0x7520, 0x3e15, + 0x7523, 0x1e70, + 0x7524, 0x3e18, + 0x7525, 0x0d34, + 0x7526, 0x3e19, + 0x7528, 0x10a8, + 0x7529, 0x0d9b, + 0x752a, 0x3e1b, + 0x752b, 0x06a1, + 0x752c, 0x1b34, + 0x752d, 0x042b, + 0x752e, 0x3e1c, + 0x752f, 0x1734, + 0x7530, 0x0e42, + 0x7531, 0x10ae, + 0x7532, 0x084a, + 0x7533, 0x0d23, + 0x7534, 0x3e1d, + 0x7535, 0x05c8, + 0x7536, 0x3e1e, + 0x7537, 0x0b33, + 0x7538, 0x05ca, + 0x7539, 0x3e1f, + 0x753a, 0x1a78, + 0x753b, 0x07c2, + 0x753c, 0x3e20, + 0x753e, 0x1816, + 0x753f, 0x3e22, + 0x7540, 0x1a79, + 0x7541, 0x3e23, + 0x7545, 0x04ce, + 0x7546, 0x3e27, + 0x7548, 0x1a7c, + 0x7549, 0x3e29, + 0x754b, 0x1a7b, + 0x754c, 0x08b8, + 0x754d, 0x3e2b, + 0x754e, 0x1a7a, + 0x754f, 0x0ec6, + 0x7550, 0x3e2c, + 0x7554, 0x0b90, + 0x7555, 0x3e30, + 0x7559, 0x0a3d, + 0x755a, 0x139e, + 0x755b, 0x1a7d, + 0x755c, 0x0fbe, + 0x755d, 0x208f, + 0x755e, 0x3e34, + 0x7562, 0x1e42, + 0x7563, 0x3e38, + 0x7565, 0x0a7b, + 0x7566, 0x0c07, + 0x7567, 0x3e3a, + 0x756a, 0x0649, + 0x756b, 0x1f4e, + 0x756c, 0x3e3d, + 0x7572, 0x1a7e, + 0x7573, 0x3e43, + 0x7574, 0x0510, + 0x7575, 0x3e44, + 0x7576, 0x1eb1, + 0x7577, 0x3e45, + 0x7578, 0x0810, + 0x7579, 0x1a7f, + 0x757a, 0x3e46, + 0x757f, 0x1814, + 0x7580, 0x3e4b, + 0x7583, 0x1a80, + 0x7584, 0x3e4e, + 0x7586, 0x087f, + 0x7587, 0x1e8b, + 0x7588, 0x3e50, + 0x758b, 0x1bc6, + 0x758c, 0x3e53, + 0x758f, 0x0d7f, + 0x7590, 0x3e56, + 0x7591, 0x1050, + 0x7592, 0x1b60, + 0x7593, 0x3e57, + 0x7594, 0x1b61, + 0x7595, 0x3e58, + 0x7596, 0x1b62, + 0x7597, 0x0a0f, + 0x7598, 0x3e59, + 0x7599, 0x06e8, + 0x759a, 0x08fd, + 0x759b, 0x3e5a, + 0x759d, 0x1b64, + 0x759e, 0x3e5c, + 0x759f, 0x0b72, + 0x75a0, 0x1b63, + 0x75a1, 0x101a, + 0x75a2, 0x3e5d, + 0x75a3, 0x1b66, + 0x75a4, 0x03d7, + 0x75a5, 0x08bb, + 0x75a6, 0x3e5e, + 0x75ab, 0x1066, + 0x75ac, 0x1b65, + 0x75ad, 0x3e63, + 0x75ae, 0x0532, + 0x75af, 0x0685, + 0x75b0, 0x1b6c, + 0x75b1, 0x1b6b, + 0x75b2, 0x0bc2, + 0x75b3, 0x1b67, + 0x75b5, 0x0546, + 0x75b6, 0x3e64, + 0x75b8, 0x1b69, + 0x75b9, 0x118f, + 0x75ba, 0x3e66, + 0x75bc, 0x0e2e, + 0x75bd, 0x0901, + 0x75be, 0x0825, + 0x75bf, 0x3e68, + 0x75c2, 0x1b6e, + 0x75c3, 0x1b6d, + 0x75c4, 0x1b6a, + 0x75c5, 0x0468, + 0x75c6, 0x3e6b, + 0x75c7, 0x11a1, + 0x75c8, 0x109d, + 0x75c9, 0x08e6, + 0x75ca, 0x0c87, + 0x75cb, 0x3e6c, + 0x75cd, 0x1b70, + 0x75ce, 0x3e6e, + 0x75d2, 0x1020, + 0x75d3, 0x3e72, + 0x75d4, 0x11cb, + 0x75d5, 0x0792, + 0x75d6, 0x1b6f, + 0x75d7, 0x3e73, + 0x75d8, 0x05fa, + 0x75d9, 0x1fc6, + 0x75da, 0x3e74, + 0x75db, 0x0e65, + 0x75dc, 0x3e75, + 0x75de, 0x0bc5, + 0x75df, 0x3e77, + 0x75e2, 0x09ea, + 0x75e3, 0x1b71, + 0x75e4, 0x1b74, + 0x75e5, 0x3e7a, + 0x75e6, 0x1b73, + 0x75e7, 0x1b76, + 0x75e8, 0x1b72, + 0x75e9, 0x3e7b, + 0x75ea, 0x07d3, + 0x75eb, 0x1b75, + 0x75ec, 0x3e7c, + 0x75f0, 0x0e08, + 0x75f1, 0x1b78, + 0x75f2, 0x3e80, + 0x75f4, 0x04fa, + 0x75f5, 0x3e82, + 0x75f9, 0x043d, + 0x75fa, 0x3e86, + 0x75fc, 0x1b79, + 0x75fd, 0x3e88, + 0x75ff, 0x1b7a, + 0x7600, 0x1b7c, + 0x7601, 0x0564, + 0x7602, 0x25ae, + 0x7603, 0x1b77, + 0x7604, 0x3e8a, + 0x7605, 0x1b7d, + 0x7606, 0x3e8b, + 0x760a, 0x1b80, + 0x760b, 0x1f01, + 0x760c, 0x1b7e, + 0x760d, 0x2200, + 0x760e, 0x3e8f, + 0x7610, 0x1b7b, + 0x7611, 0x3e91, + 0x7615, 0x1b83, + 0x7616, 0x3e95, + 0x7617, 0x1b7f, + 0x7618, 0x1b82, + 0x7619, 0x1b84, + 0x761a, 0x3e96, + 0x761b, 0x1b85, + 0x761c, 0x3e97, + 0x761e, 0x25b2, + 0x761f, 0x0ed0, + 0x7620, 0x1b88, + 0x7621, 0x1e97, + 0x7622, 0x1b87, + 0x7623, 0x3e99, + 0x7624, 0x0a3f, + 0x7625, 0x1b81, + 0x7626, 0x0d74, + 0x7627, 0x20ab, + 0x7628, 0x3e9a, + 0x7629, 0x0574, + 0x762a, 0x045a, + 0x762b, 0x0e04, + 0x762c, 0x3e9b, + 0x762d, 0x1b8a, + 0x762e, 0x3e9c, + 0x7630, 0x1b8b, + 0x7631, 0x3e9e, + 0x7633, 0x1b90, + 0x7634, 0x116f, + 0x7635, 0x1b8d, + 0x7636, 0x3ea0, + 0x7638, 0x0c8e, + 0x7639, 0x3ea2, + 0x763b, 0x25b3, + 0x763c, 0x1b86, + 0x763d, 0x3ea4, + 0x763e, 0x1b8f, + 0x763f, 0x1b8c, + 0x7640, 0x1b89, + 0x7641, 0x3ea5, + 0x7642, 0x2028, + 0x7643, 0x1b8e, + 0x7644, 0x3ea6, + 0x7646, 0x25af, + 0x7648, 0x3ea8, + 0x7649, 0x25b1, + 0x764a, 0x3ea9, + 0x764c, 0x03b4, + 0x764d, 0x1b91, + 0x764e, 0x3eab, + 0x7654, 0x1b93, + 0x7655, 0x3eb1, + 0x7656, 0x1b95, + 0x7657, 0x3eb2, + 0x7658, 0x25ac, + 0x7659, 0x3eb3, + 0x765c, 0x1b94, + 0x765d, 0x3eb6, + 0x765e, 0x1b92, + 0x765f, 0x1e4e, + 0x7660, 0x3eb7, + 0x7662, 0x2202, + 0x7663, 0x0fcb, + 0x7664, 0x25ab, + 0x7665, 0x2286, + 0x7666, 0x3eb9, + 0x7667, 0x25ad, + 0x7668, 0x3eba, + 0x7669, 0x25b6, + 0x766a, 0x3ebb, + 0x766b, 0x1b96, + 0x766c, 0x21e3, + 0x766d, 0x25b4, + 0x766f, 0x1b97, + 0x7670, 0x222f, + 0x7671, 0x2165, + 0x7672, 0x25b7, + 0x7673, 0x3ebc, + 0x7678, 0x0748, + 0x7679, 0x3ec1, + 0x767b, 0x05a8, + 0x767c, 0x1ee9, + 0x767d, 0x03e2, + 0x767e, 0x03e4, + 0x767f, 0x3ec3, + 0x7682, 0x1130, + 0x7683, 0x3ec6, + 0x7684, 0x05a5, + 0x7685, 0x3ec7, + 0x7686, 0x08a5, + 0x7687, 0x07df, + 0x7688, 0x1b2d, + 0x7689, 0x3ec8, + 0x768b, 0x06d9, + 0x768c, 0x3eca, + 0x768e, 0x1b2e, + 0x768f, 0x3ecc, + 0x7691, 0x03b3, + 0x7692, 0x3ece, + 0x7693, 0x1b2f, + 0x7694, 0x3ecf, + 0x7696, 0x0e9f, + 0x7697, 0x3ed1, + 0x7699, 0x1b30, + 0x769a, 0x1e25, + 0x769b, 0x3ed3, + 0x76a4, 0x1b31, + 0x76a5, 0x3edc, + 0x76ae, 0x0bc3, + 0x76af, 0x3ee5, + 0x76b1, 0x11e4, + 0x76b2, 0x1bc8, + 0x76b3, 0x3ee7, + 0x76b4, 0x1bc9, + 0x76b5, 0x3ee8, + 0x76b8, 0x25c0, + 0x76b9, 0x3eeb, + 0x76ba, 0x229a, + 0x76bb, 0x3eec, + 0x76bf, 0x0af8, + 0x76c0, 0x3ef0, + 0x76c2, 0x10c0, + 0x76c3, 0x3ef2, + 0x76c5, 0x11d0, + 0x76c6, 0x0ba9, + 0x76c7, 0x3ef4, + 0x76c8, 0x1094, + 0x76c9, 0x3ef5, + 0x76ca, 0x106d, + 0x76cb, 0x3ef6, + 0x76cd, 0x1a8b, + 0x76ce, 0x03c6, + 0x76cf, 0x1156, + 0x76d0, 0x0ff7, + 0x76d1, 0x0853, + 0x76d2, 0x0787, + 0x76d3, 0x3ef8, + 0x76d4, 0x0985, + 0x76d5, 0x3ef9, + 0x76d6, 0x06c2, + 0x76d7, 0x05a2, + 0x76d8, 0x0b8d, + 0x76d9, 0x3efa, + 0x76db, 0x0d39, + 0x76dc, 0x3efc, + 0x76de, 0x226e, + 0x76df, 0x0ad0, + 0x76e0, 0x3efe, + 0x76e1, 0x1fbd, + 0x76e2, 0x3eff, + 0x76e3, 0x1f84, + 0x76e4, 0x20b2, + 0x76e5, 0x1a8c, + 0x76e6, 0x3f00, + 0x76e7, 0x2043, + 0x76e8, 0x3f01, + 0x76ee, 0x0b22, + 0x76ef, 0x05e1, + 0x76f0, 0x3f07, + 0x76f1, 0x1a58, + 0x76f2, 0x0aa9, + 0x76f3, 0x3f08, + 0x76f4, 0x11b0, + 0x76f5, 0x3f09, + 0x76f8, 0x0f4d, + 0x76f9, 0x1a5b, + 0x76fa, 0x3f0c, + 0x76fc, 0x0b8f, + 0x76fd, 0x3f0e, + 0x76fe, 0x061b, + 0x76ff, 0x3f0f, + 0x7700, 0x3f10, + 0x7701, 0x0d38, + 0x7702, 0x3f11, + 0x7704, 0x1a59, + 0x7705, 0x3f13, + 0x7707, 0x1a5c, + 0x7709, 0x0ac1, + 0x770a, 0x3f15, + 0x770b, 0x0941, + 0x770c, 0x3f16, + 0x770d, 0x1a5a, + 0x770e, 0x3f17, + 0x7719, 0x1a60, + 0x771a, 0x1a5e, + 0x771b, 0x3f22, + 0x771f, 0x1187, + 0x7720, 0x0ae4, + 0x7721, 0x3f26, + 0x7722, 0x1a5f, + 0x7723, 0x3f27, + 0x7726, 0x1a62, + 0x7727, 0x3f2a, + 0x7728, 0x1144, + 0x7729, 0x0fcc, + 0x772a, 0x3f2b, + 0x772d, 0x1a61, + 0x772e, 0x3f2e, + 0x772f, 0x0ad5, + 0x7730, 0x3f2f, + 0x7735, 0x1a63, + 0x7736, 0x0981, + 0x7737, 0x091b, + 0x7738, 0x1a64, + 0x7739, 0x3f34, + 0x773a, 0x0e4a, + 0x773b, 0x3f35, + 0x773c, 0x1004, + 0x773d, 0x3f36, + 0x7740, 0x1222, + 0x7741, 0x1197, + 0x7742, 0x3f39, + 0x7743, 0x1a68, + 0x7744, 0x3f3a, + 0x7747, 0x1a67, + 0x7748, 0x3f3d, + 0x774f, 0x2684, + 0x7750, 0x1a65, + 0x7752, 0x3f44, + 0x775a, 0x1a69, + 0x775b, 0x08d5, + 0x775c, 0x3f4c, + 0x775e, 0x24ef, + 0x775f, 0x3f4e, + 0x7761, 0x0da4, + 0x7762, 0x1a6b, + 0x7763, 0x05fc, + 0x7764, 0x3f50, + 0x7765, 0x1a6c, + 0x7766, 0x0b23, + 0x7767, 0x3f51, + 0x7768, 0x1a6a, + 0x7769, 0x3f52, + 0x776b, 0x08af, + 0x776c, 0x048e, + 0x776d, 0x3f54, + 0x7779, 0x0602, + 0x777a, 0x3f60, + 0x777d, 0x1a6f, + 0x777e, 0x1270, + 0x777f, 0x1a6d, + 0x7780, 0x1a70, + 0x7781, 0x3f63, + 0x7784, 0x0aee, + 0x7785, 0x0517, + 0x7786, 0x3f66, + 0x778c, 0x1a71, + 0x778d, 0x1a6e, + 0x778e, 0x0f26, + 0x778f, 0x3f6c, + 0x7791, 0x1a72, + 0x7792, 0x0a9e, + 0x7793, 0x3f6e, + 0x7798, 0x24ee, + 0x7799, 0x3f73, + 0x779e, 0x2074, + 0x779f, 0x1a73, + 0x77a1, 0x3f78, + 0x77a2, 0x1495, + 0x77a3, 0x3f79, + 0x77a5, 0x0bd2, + 0x77a6, 0x3f7b, + 0x77a7, 0x0c43, + 0x77a8, 0x3f7c, + 0x77a9, 0x11f4, + 0x77aa, 0x05aa, + 0x77ab, 0x3f7d, + 0x77ac, 0x0da7, + 0x77ad, 0x2687, + 0x77ae, 0x3f7e, + 0x77b0, 0x1a75, + 0x77b1, 0x3f80, + 0x77b3, 0x0e5c, + 0x77b4, 0x3f82, + 0x77b5, 0x1a76, + 0x77b6, 0x3f83, + 0x77bb, 0x1151, + 0x77bc, 0x24f0, + 0x77bd, 0x1a77, + 0x77be, 0x3f88, + 0x77bf, 0x1d7e, + 0x77c0, 0x3f89, + 0x77c7, 0x268d, + 0x77c8, 0x3f90, + 0x77cd, 0x1397, + 0x77ce, 0x3f95, + 0x77d7, 0x0526, + 0x77d8, 0x3f9e, + 0x77da, 0x22a0, + 0x77db, 0x0ab1, + 0x77dc, 0x1bca, + 0x77dd, 0x3fa0, + 0x77e2, 0x0d4f, + 0x77e3, 0x105a, + 0x77e4, 0x3fa5, + 0x77e5, 0x11a9, + 0x77e6, 0x3fa6, + 0x77e7, 0x1b1a, + 0x77e8, 0x3fa7, + 0x77e9, 0x0907, + 0x77ea, 0x3fa8, + 0x77eb, 0x0894, + 0x77ec, 0x1b1b, + 0x77ed, 0x060b, + 0x77ee, 0x03b6, + 0x77ef, 0x1fab, + 0x77f0, 0x3fa9, + 0x77f3, 0x0d46, + 0x77f4, 0x3fac, + 0x77f6, 0x1a22, + 0x77f7, 0x3fae, + 0x77f8, 0x1a23, + 0x77f9, 0x3faf, + 0x77fd, 0x0f08, + 0x77fe, 0x064c, + 0x77ff, 0x0980, + 0x7800, 0x1a24, + 0x7801, 0x0a92, + 0x7802, 0x0ce9, + 0x7803, 0x3fb3, + 0x7809, 0x1a25, + 0x780a, 0x3fb9, + 0x780c, 0x0c15, + 0x780d, 0x0940, + 0x780e, 0x3fbb, + 0x7811, 0x1a28, + 0x7812, 0x0bb9, + 0x7813, 0x3fbe, + 0x7814, 0x0ff9, + 0x7815, 0x3fbf, + 0x7816, 0x1206, + 0x7817, 0x1a26, + 0x7819, 0x3fc0, + 0x781a, 0x100b, + 0x781b, 0x3fc1, + 0x781c, 0x1a2b, + 0x781e, 0x3fc2, + 0x781f, 0x1a30, + 0x7820, 0x3fc3, + 0x7823, 0x1a34, + 0x7824, 0x3fc6, + 0x7825, 0x1a32, + 0x7826, 0x1a3a, + 0x7827, 0x1189, + 0x7828, 0x3fc7, + 0x7829, 0x1a35, + 0x782a, 0x3fc8, + 0x782c, 0x1a33, + 0x782d, 0x1a2a, + 0x782e, 0x3fca, + 0x7830, 0x0baa, + 0x7831, 0x3fcc, + 0x7834, 0x0be5, + 0x7835, 0x3fcf, + 0x7837, 0x0d22, + 0x7838, 0x1115, + 0x7839, 0x1a2d, + 0x783c, 0x1a31, + 0x783d, 0x3fd1, + 0x783e, 0x09e4, + 0x783f, 0x3fd2, + 0x7840, 0x0524, + 0x7841, 0x3fd3, + 0x7843, 0x26a8, + 0x7844, 0x3fd5, + 0x7845, 0x0741, + 0x7846, 0x3fd6, + 0x7847, 0x1a3c, + 0x7848, 0x3fd7, + 0x784c, 0x1a3d, + 0x784d, 0x3fdb, + 0x784e, 0x1a36, + 0x784f, 0x3fdc, + 0x7850, 0x1a3b, + 0x7851, 0x3fdd, + 0x7852, 0x0f07, + 0x7853, 0x3fde, + 0x7855, 0x0dab, + 0x7856, 0x1a38, + 0x7858, 0x3fe0, + 0x785d, 0x0f62, + 0x785e, 0x3fe5, + 0x7864, 0x24e9, + 0x7865, 0x3feb, + 0x7868, 0x24e5, + 0x7869, 0x3fee, + 0x786a, 0x1a3e, + 0x786b, 0x0a3b, + 0x786c, 0x1097, + 0x786d, 0x1a37, + 0x786e, 0x0c92, + 0x786f, 0x21fa, + 0x7870, 0x3fef, + 0x7877, 0x0862, + 0x7878, 0x3ff6, + 0x787c, 0x0bb1, + 0x787d, 0x3ffa, + 0x7887, 0x1a42, + 0x7888, 0x4004, + 0x7889, 0x05d0, + 0x788a, 0x4005, + 0x788c, 0x0a5c, + 0x788d, 0x03b8, + 0x788e, 0x0dde, + 0x788f, 0x4007, + 0x7891, 0x0417, + 0x7892, 0x4009, + 0x7893, 0x1a40, + 0x7894, 0x400a, + 0x7897, 0x0e9c, + 0x7898, 0x05c3, + 0x7899, 0x400d, + 0x789a, 0x1a41, + 0x789b, 0x1a3f, + 0x789c, 0x1a43, + 0x789d, 0x400e, + 0x789f, 0x05db, + 0x78a0, 0x4010, + 0x78a1, 0x1a44, + 0x78a2, 0x4011, + 0x78a3, 0x1a45, + 0x78a4, 0x4012, + 0x78a5, 0x1a48, + 0x78a6, 0x4013, + 0x78a7, 0x0435, + 0x78a8, 0x4014, + 0x78a9, 0x2148, + 0x78aa, 0x4015, + 0x78ad, 0x24e4, + 0x78ae, 0x4018, + 0x78b0, 0x0bb7, + 0x78b1, 0x0861, + 0x78b2, 0x1a46, + 0x78b3, 0x0e0f, + 0x78b4, 0x04b1, + 0x78b5, 0x401a, + 0x78b8, 0x24e6, + 0x78b9, 0x1a47, + 0x78ba, 0x20f7, + 0x78bb, 0x401d, + 0x78bc, 0x206b, + 0x78bd, 0x401e, + 0x78be, 0x0b4e, + 0x78bf, 0x401f, + 0x78c1, 0x0548, + 0x78c2, 0x4021, + 0x78c5, 0x0400, + 0x78c6, 0x4024, + 0x78c9, 0x1a4b, + 0x78ca, 0x09c5, + 0x78cb, 0x056b, + 0x78cc, 0x4027, + 0x78d0, 0x0b8e, + 0x78d1, 0x402b, + 0x78d4, 0x1a49, + 0x78d5, 0x0951, + 0x78d6, 0x402e, + 0x78d9, 0x1a4a, + 0x78da, 0x22a7, + 0x78db, 0x4031, + 0x78e3, 0x24ec, + 0x78e4, 0x4039, + 0x78e7, 0x24eb, + 0x78e8, 0x0b08, + 0x78e9, 0x403c, + 0x78ec, 0x1a4c, + 0x78ed, 0x403f, + 0x78ef, 0x24e3, + 0x78f0, 0x4041, + 0x78f2, 0x1a4d, + 0x78f3, 0x4043, + 0x78f4, 0x1a4f, + 0x78f5, 0x4044, + 0x78f7, 0x0a20, + 0x78f8, 0x4046, + 0x78fa, 0x07dc, + 0x78fb, 0x4048, + 0x78fd, 0x24ea, + 0x78fe, 0x404a, + 0x7900, 0x404c, + 0x7901, 0x0889, + 0x7902, 0x404d, + 0x7905, 0x1a4e, + 0x7906, 0x4050, + 0x790e, 0x1e92, + 0x790f, 0x4058, + 0x7913, 0x1a50, + 0x7914, 0x405c, + 0x7919, 0x1e27, + 0x791a, 0x4061, + 0x791e, 0x1a52, + 0x791f, 0x4065, + 0x7924, 0x1a51, + 0x7925, 0x406a, + 0x7926, 0x1fe6, + 0x7927, 0x406b, + 0x792a, 0x24e7, + 0x792b, 0x2012, + 0x792c, 0x1eec, + 0x792d, 0x406e, + 0x7931, 0x24e8, + 0x7932, 0x4072, + 0x7934, 0x1a53, + 0x7935, 0x4074, + 0x793a, 0x0d55, + 0x793b, 0x19f8, + 0x793c, 0x09dc, + 0x793d, 0x4079, + 0x793e, 0x0d20, + 0x793f, 0x407a, + 0x7940, 0x19f9, + 0x7941, 0x0c0d, + 0x7942, 0x407b, + 0x7946, 0x19fa, + 0x7947, 0x407f, + 0x7948, 0x0c0c, + 0x7949, 0x19fb, + 0x794a, 0x4080, + 0x7953, 0x19fe, + 0x7954, 0x4089, + 0x7956, 0x1243, + 0x7957, 0x1a01, + 0x7958, 0x408b, + 0x795a, 0x19ff, + 0x795b, 0x19fc, + 0x795d, 0x1200, + 0x795e, 0x0d2a, + 0x795f, 0x0de3, + 0x7960, 0x1a02, + 0x7961, 0x408d, + 0x7962, 0x1a00, + 0x7963, 0x408e, + 0x7965, 0x0f56, + 0x7966, 0x4090, + 0x7967, 0x1a04, + 0x7968, 0x0bd0, + 0x7969, 0x4091, + 0x796d, 0x0833, + 0x796e, 0x4095, + 0x796f, 0x1a03, + 0x7970, 0x4096, + 0x7977, 0x059c, + 0x7978, 0x080b, + 0x7979, 0x409d, + 0x797a, 0x1a05, + 0x797b, 0x409e, + 0x7980, 0x130b, + 0x7981, 0x08cc, + 0x7982, 0x40a3, + 0x7984, 0x0a62, + 0x7985, 0x1a06, + 0x7986, 0x40a5, + 0x798a, 0x1a07, + 0x798b, 0x40a9, + 0x798d, 0x1f66, + 0x798e, 0x24dc, + 0x798f, 0x069e, + 0x7990, 0x40ab, + 0x799a, 0x1a08, + 0x799b, 0x40b5, + 0x79a6, 0x26a2, + 0x79a7, 0x1a09, + 0x79a8, 0x40c0, + 0x79aa, 0x24dd, + 0x79ab, 0x40c2, + 0x79ae, 0x200e, + 0x79af, 0x40c5, + 0x79b0, 0x24db, + 0x79b1, 0x1eb8, + 0x79b2, 0x40c6, + 0x79b3, 0x1a0a, + 0x79b4, 0x40c7, + 0x79b9, 0x10d2, + 0x79ba, 0x1264, + 0x79bb, 0x09d6, + 0x79bc, 0x40cc, + 0x79bd, 0x0c5a, + 0x79be, 0x0783, + 0x79bf, 0x40cd, + 0x79c0, 0x0fae, + 0x79c1, 0x0db2, + 0x79c2, 0x40ce, + 0x79c3, 0x0e6b, + 0x79c4, 0x40cf, + 0x79c6, 0x06cc, + 0x79c7, 0x40d1, + 0x79c9, 0x0465, + 0x79ca, 0x40d3, + 0x79cb, 0x0c6c, + 0x79cc, 0x40d4, + 0x79cd, 0x11d5, + 0x79ce, 0x40d5, + 0x79d1, 0x0953, + 0x79d2, 0x0af0, + 0x79d3, 0x40d8, + 0x79d5, 0x1b1d, + 0x79d6, 0x40da, + 0x79d8, 0x0add, + 0x79d9, 0x40dc, + 0x79df, 0x123f, + 0x79e0, 0x40e2, + 0x79e3, 0x1b1f, + 0x79e4, 0x04f8, + 0x79e5, 0x40e5, + 0x79e6, 0x0c55, + 0x79e7, 0x1016, + 0x79e8, 0x40e6, + 0x79e9, 0x11c7, + 0x79ea, 0x40e7, + 0x79eb, 0x1b20, + 0x79ec, 0x40e8, + 0x79ed, 0x1b1e, + 0x79ee, 0x40e9, + 0x79ef, 0x0812, + 0x79f0, 0x04eb, + 0x79f1, 0x40ea, + 0x79f8, 0x08a6, + 0x79f9, 0x40f1, + 0x79fb, 0x104d, + 0x79fc, 0x40f3, + 0x79fd, 0x07f5, + 0x79fe, 0x40f4, + 0x7a00, 0x0f0e, + 0x7a01, 0x40f6, + 0x7a02, 0x1b24, + 0x7a03, 0x1b23, + 0x7a04, 0x40f7, + 0x7a06, 0x1b21, + 0x7a07, 0x40f9, + 0x7a0b, 0x04f1, + 0x7a0c, 0x40fd, + 0x7a0d, 0x0d0d, + 0x7a0e, 0x0da5, + 0x7a0f, 0x40fe, + 0x7a14, 0x1b26, + 0x7a15, 0x4103, + 0x7a17, 0x03e9, + 0x7a18, 0x4105, + 0x7a1a, 0x11c8, + 0x7a1b, 0x4107, + 0x7a1e, 0x1b25, + 0x7a1f, 0x410a, + 0x7a20, 0x0512, + 0x7a21, 0x410b, + 0x7a23, 0x1d8f, + 0x7a24, 0x410d, + 0x7a2e, 0x2295, + 0x7a2f, 0x4117, + 0x7a31, 0x1e80, + 0x7a32, 0x4119, + 0x7a33, 0x0ed7, + 0x7a34, 0x411a, + 0x7a37, 0x1b28, + 0x7a38, 0x411d, + 0x7a39, 0x1b27, + 0x7a3a, 0x411e, + 0x7a3b, 0x059f, + 0x7a3c, 0x084d, + 0x7a3d, 0x0811, + 0x7a3e, 0x411f, + 0x7a3f, 0x06e0, + 0x7a40, 0x2677, + 0x7a41, 0x4120, + 0x7a46, 0x0b25, + 0x7a47, 0x4125, + 0x7a4c, 0x2624, + 0x7a4d, 0x1f69, + 0x7a4e, 0x222b, + 0x7a4f, 0x412a, + 0x7a51, 0x1b29, + 0x7a52, 0x412c, + 0x7a57, 0x0de0, + 0x7a58, 0x4131, + 0x7a61, 0x257f, + 0x7a62, 0x1f5b, + 0x7a63, 0x413a, + 0x7a69, 0x219b, + 0x7a6a, 0x4140, + 0x7a6b, 0x267d, + 0x7a6c, 0x4141, + 0x7a70, 0x1b2c, + 0x7a71, 0x4145, + 0x7a74, 0x0fd1, + 0x7a75, 0x4148, + 0x7a76, 0x08ee, + 0x7a77, 0x0c6b, + 0x7a78, 0x1b9a, + 0x7a7a, 0x0962, + 0x7a7b, 0x4149, + 0x7a7f, 0x052c, + 0x7a80, 0x1b9c, + 0x7a81, 0x0e6c, + 0x7a82, 0x414d, + 0x7a83, 0x0c51, + 0x7a84, 0x114e, + 0x7a85, 0x414e, + 0x7a86, 0x1b9d, + 0x7a87, 0x414f, + 0x7a88, 0x1b9e, + 0x7a89, 0x4150, + 0x7a8d, 0x0c4c, + 0x7a8e, 0x4154, + 0x7a91, 0x102b, + 0x7a92, 0x11ce, + 0x7a93, 0x4157, + 0x7a95, 0x1b9f, + 0x7a96, 0x08a2, + 0x7a97, 0x0533, + 0x7a98, 0x08ec, + 0x7a99, 0x4159, + 0x7a9c, 0x055f, + 0x7a9d, 0x0ee0, + 0x7a9e, 0x415c, + 0x7a9f, 0x096c, + 0x7aa0, 0x1ba1, + 0x7aa1, 0x415d, + 0x7aa5, 0x0987, + 0x7aa6, 0x1ba0, + 0x7aa7, 0x4161, + 0x7aa8, 0x1ba3, + 0x7aa9, 0x21a0, + 0x7aaa, 0x2186, + 0x7aab, 0x4162, + 0x7aac, 0x1ba2, + 0x7aad, 0x1ba4, + 0x7aae, 0x20ed, + 0x7aaf, 0x4163, + 0x7ab3, 0x1ba5, + 0x7ab4, 0x4167, + 0x7ab6, 0x25b9, + 0x7ab7, 0x4169, + 0x7aba, 0x1fea, + 0x7abb, 0x416c, + 0x7abf, 0x0a47, + 0x7ac0, 0x4170, + 0x7ac4, 0x1ea4, + 0x7ac5, 0x20e1, + 0x7ac6, 0x4174, + 0x7ac7, 0x25b8, + 0x7ac8, 0x2260, + 0x7ac9, 0x4175, + 0x7aca, 0x20e2, + 0x7acb, 0x09eb, + 0x7acc, 0x4176, + 0x7ad6, 0x0d91, + 0x7ad7, 0x4180, + 0x7ad9, 0x115f, + 0x7ada, 0x4182, + 0x7ade, 0x08e9, + 0x7adf, 0x08e8, + 0x7ae0, 0x1163, + 0x7ae1, 0x4186, + 0x7ae3, 0x092f, + 0x7ae4, 0x4188, + 0x7ae5, 0x0e60, + 0x7ae6, 0x1b99, + 0x7ae7, 0x4189, + 0x7aea, 0x2141, + 0x7aeb, 0x418c, + 0x7aed, 0x08b0, + 0x7aee, 0x418e, + 0x7aef, 0x060a, + 0x7af0, 0x418f, + 0x7af6, 0x1fc7, + 0x7af7, 0x4195, + 0x7af9, 0x11f0, + 0x7afa, 0x1c63, + 0x7afb, 0x4197, + 0x7afd, 0x1c64, + 0x7afe, 0x4199, + 0x7aff, 0x06c8, + 0x7b00, 0x419a, + 0x7b03, 0x1c66, + 0x7b05, 0x419d, + 0x7b06, 0x03d5, + 0x7b07, 0x419e, + 0x7b08, 0x1c65, + 0x7b09, 0x419f, + 0x7b0a, 0x1c69, + 0x7b0b, 0x0de6, + 0x7b0c, 0x41a0, + 0x7b0f, 0x1c6b, + 0x7b10, 0x41a3, + 0x7b11, 0x0f71, + 0x7b12, 0x41a4, + 0x7b14, 0x0433, + 0x7b15, 0x1c68, + 0x7b16, 0x41a6, + 0x7b19, 0x1c6f, + 0x7b1a, 0x41a9, + 0x7b1b, 0x05b2, + 0x7b1c, 0x41aa, + 0x7b1e, 0x1c77, + 0x7b1f, 0x41ac, + 0x7b20, 0x1c72, + 0x7b21, 0x41ad, + 0x7b24, 0x1c74, + 0x7b25, 0x1c73, + 0x7b26, 0x0698, + 0x7b27, 0x41b0, + 0x7b28, 0x0428, + 0x7b29, 0x41b1, + 0x7b2a, 0x1c6e, + 0x7b2b, 0x1c6a, + 0x7b2c, 0x05bb, + 0x7b2d, 0x41b2, + 0x7b2e, 0x1c70, + 0x7b2f, 0x41b3, + 0x7b31, 0x1c71, + 0x7b32, 0x41b5, + 0x7b33, 0x1c75, + 0x7b34, 0x41b6, + 0x7b38, 0x1c6d, + 0x7b39, 0x41ba, + 0x7b3a, 0x0856, + 0x7b3b, 0x41bb, + 0x7b3c, 0x0a46, + 0x7b3d, 0x41bc, + 0x7b3e, 0x1c76, + 0x7b3f, 0x41bd, + 0x7b45, 0x1c7a, + 0x7b46, 0x1e41, + 0x7b47, 0x1c6c, + 0x7b48, 0x41c3, + 0x7b49, 0x05a9, + 0x7b4a, 0x41c4, + 0x7b4b, 0x08bf, + 0x7b4c, 0x1c7c, + 0x7b4d, 0x41c5, + 0x7b4f, 0x0641, + 0x7b50, 0x097d, + 0x7b51, 0x11fd, + 0x7b52, 0x0e63, + 0x7b53, 0x41c7, + 0x7b54, 0x0573, + 0x7b55, 0x41c8, + 0x7b56, 0x04a6, + 0x7b57, 0x41c9, + 0x7b58, 0x1c78, + 0x7b59, 0x41ca, + 0x7b5a, 0x1c79, + 0x7b5b, 0x0cf1, + 0x7b5c, 0x41cb, + 0x7b5d, 0x1c7d, + 0x7b5e, 0x41cc, + 0x7b60, 0x1c7e, + 0x7b61, 0x41ce, + 0x7b62, 0x1c81, + 0x7b63, 0x41cf, + 0x7b67, 0x25e4, + 0x7b68, 0x41d3, + 0x7b6e, 0x1c7f, + 0x7b6f, 0x41d9, + 0x7b71, 0x1c83, + 0x7b72, 0x1c82, + 0x7b73, 0x41db, + 0x7b75, 0x1c7b, + 0x7b76, 0x41dd, + 0x7b77, 0x0977, + 0x7b78, 0x41de, + 0x7b79, 0x0514, + 0x7b7a, 0x41df, + 0x7b7b, 0x1c80, + 0x7b7c, 0x41e0, + 0x7b7e, 0x0c26, + 0x7b7f, 0x41e2, + 0x7b80, 0x0865, + 0x7b81, 0x41e3, + 0x7b85, 0x1c8b, + 0x7b86, 0x41e7, + 0x7b8b, 0x1f86, + 0x7b8c, 0x41ec, + 0x7b8d, 0x0718, + 0x7b8e, 0x41ed, + 0x7b90, 0x1c84, + 0x7b91, 0x41ef, + 0x7b94, 0x0474, + 0x7b95, 0x0813, + 0x7b96, 0x41f2, + 0x7b97, 0x0dd8, + 0x7b98, 0x41f3, + 0x7b9c, 0x1c8d, + 0x7b9d, 0x1c89, + 0x7b9e, 0x41f7, + 0x7ba1, 0x0735, + 0x7ba2, 0x1c8e, + 0x7ba3, 0x41fa, + 0x7ba6, 0x1c85, + 0x7ba8, 0x1c8a, + 0x7ba9, 0x0a88, + 0x7baa, 0x1c8c, + 0x7bab, 0x1c8f, + 0x7bac, 0x1c88, + 0x7bad, 0x0870, + 0x7bae, 0x41fd, + 0x7bb1, 0x0f51, + 0x7bb2, 0x4200, + 0x7bb4, 0x1c90, + 0x7bb5, 0x4202, + 0x7bb8, 0x1c87, + 0x7bb9, 0x4205, + 0x7bc0, 0x1fb3, + 0x7bc1, 0x1c92, + 0x7bc2, 0x420c, + 0x7bc4, 0x1eef, + 0x7bc5, 0x420e, + 0x7bc6, 0x120a, + 0x7bc7, 0x0bc9, + 0x7bc8, 0x420f, + 0x7bc9, 0x22a4, + 0x7bca, 0x4210, + 0x7bcb, 0x25e8, + 0x7bcc, 0x1c93, + 0x7bcd, 0x4211, + 0x7bd1, 0x1c91, + 0x7bd2, 0x4215, + 0x7bd3, 0x0a4f, + 0x7bd4, 0x4216, + 0x7bd9, 0x06d8, + 0x7bda, 0x1c95, + 0x7bdb, 0x421b, + 0x7bdd, 0x1c94, + 0x7bde, 0x421d, + 0x7be1, 0x055e, + 0x7be2, 0x4220, + 0x7be4, 0x25e3, + 0x7be5, 0x1c96, + 0x7be7, 0x4222, + 0x7be9, 0x2111, + 0x7bea, 0x1c98, + 0x7beb, 0x4224, + 0x7bee, 0x09a5, + 0x7bef, 0x4227, + 0x7bf1, 0x09d4, + 0x7bf2, 0x4229, + 0x7bf3, 0x25e6, + 0x7bf4, 0x422a, + 0x7bf7, 0x0bb2, + 0x7bf8, 0x422d, + 0x7bfc, 0x1c9b, + 0x7bfd, 0x4231, + 0x7bfe, 0x1c9a, + 0x7bff, 0x4232, + 0x7c00, 0x25e7, + 0x7c01, 0x4233, + 0x7c07, 0x055b, + 0x7c08, 0x4239, + 0x7c0b, 0x1c9e, + 0x7c0c, 0x1c99, + 0x7c0d, 0x2041, + 0x7c0e, 0x423c, + 0x7c0f, 0x1c9c, + 0x7c10, 0x423d, + 0x7c16, 0x1c9d, + 0x7c17, 0x4243, + 0x7c1e, 0x25ea, + 0x7c1f, 0x1c9f, + 0x7c20, 0x424a, + 0x7c21, 0x1f8f, + 0x7c22, 0x424b, + 0x7c23, 0x25ec, + 0x7c24, 0x424c, + 0x7c26, 0x1ca1, + 0x7c27, 0x07de, + 0x7c28, 0x424e, + 0x7c2a, 0x1ca0, + 0x7c2b, 0x25eb, + 0x7c2c, 0x4250, + 0x7c38, 0x1ca2, + 0x7c39, 0x425c, + 0x7c3d, 0x20d0, + 0x7c3e, 0x201d, + 0x7c3f, 0x0485, + 0x7c40, 0x1ca4, + 0x7c41, 0x1ca3, + 0x7c42, 0x4260, + 0x7c43, 0x1ff7, + 0x7c44, 0x4261, + 0x7c4c, 0x1e8d, + 0x7c4d, 0x0821, + 0x7c4e, 0x4269, + 0x7c5c, 0x25e9, + 0x7c5d, 0x4277, + 0x7c5f, 0x25ee, + 0x7c60, 0x203a, + 0x7c61, 0x4279, + 0x7c64, 0x2693, + 0x7c65, 0x427c, + 0x7c69, 0x25e5, + 0x7c6a, 0x25ed, + 0x7c6b, 0x4280, + 0x7c6c, 0x2009, + 0x7c6d, 0x4281, + 0x7c6e, 0x2065, + 0x7c6f, 0x4282, + 0x7c72, 0x26a3, + 0x7c73, 0x0adc, + 0x7c74, 0x12f5, + 0x7c75, 0x4285, + 0x7c7b, 0x09cb, + 0x7c7c, 0x1cca, + 0x7c7d, 0x122e, + 0x7c7e, 0x428b, + 0x7c89, 0x0678, + 0x7c8a, 0x4296, + 0x7c91, 0x1ccc, + 0x7c92, 0x09ec, + 0x7c93, 0x429d, + 0x7c95, 0x0be8, + 0x7c96, 0x429f, + 0x7c97, 0x0559, + 0x7c98, 0x1154, + 0x7c99, 0x42a0, + 0x7c9c, 0x1cce, + 0x7c9d, 0x1ccd, + 0x7c9e, 0x1ccf, + 0x7c9f, 0x0dcf, + 0x7ca0, 0x42a3, + 0x7ca2, 0x1cd0, + 0x7ca3, 0x42a5, + 0x7ca4, 0x1104, + 0x7ca5, 0x11df, + 0x7ca6, 0x42a6, + 0x7caa, 0x067d, + 0x7cab, 0x42aa, + 0x7cae, 0x0a01, + 0x7caf, 0x42ad, + 0x7cb1, 0x0a04, + 0x7cb2, 0x1cd1, + 0x7cb3, 0x08db, + 0x7cb4, 0x42af, + 0x7cb9, 0x0565, + 0x7cba, 0x42b4, + 0x7cbc, 0x1cd2, + 0x7cbe, 0x08da, + 0x7cbf, 0x42b6, + 0x7cc1, 0x1cd4, + 0x7cc2, 0x42b8, + 0x7cc5, 0x1cd9, + 0x7cc6, 0x42bb, + 0x7cc7, 0x1cd5, + 0x7cc8, 0x1cd8, + 0x7cc9, 0x42bc, + 0x7cca, 0x07b4, + 0x7ccb, 0x42bd, + 0x7ccc, 0x1cd6, + 0x7cce, 0x42be, + 0x7cd5, 0x06dd, + 0x7cd6, 0x0e1a, + 0x7cd7, 0x1cda, + 0x7cd8, 0x42c5, + 0x7cd9, 0x04a1, + 0x7cda, 0x42c6, + 0x7cdc, 0x0ad8, + 0x7cdd, 0x25f5, + 0x7cde, 0x1efc, + 0x7cdf, 0x1126, + 0x7ce0, 0x0944, + 0x7ce1, 0x42c8, + 0x7ce7, 0x2024, + 0x7ce8, 0x1cdb, + 0x7ce9, 0x42ce, + 0x7cef, 0x0b75, + 0x7cf0, 0x269b, + 0x7cf1, 0x42d4, + 0x7cf2, 0x25f3, + 0x7cf3, 0x42d5, + 0x7cf4, 0x22d9, + 0x7cf5, 0x42d6, + 0x7cf6, 0x25f4, + 0x7cf7, 0x42d7, + 0x7cf8, 0x1ce7, + 0x7cf9, 0x241b, + 0x7cfa, 0x42d8, + 0x7cfb, 0x0f22, + 0x7cfc, 0x42d9, + 0x7cfe, 0x1fc8, + 0x7cff, 0x42db, + 0x7d00, 0x1f7b, + 0x7d01, 0x42dc, + 0x7d02, 0x241d, + 0x7d03, 0x42dd, + 0x7d04, 0x224c, + 0x7d05, 0x1f48, + 0x7d06, 0x241c, + 0x7d07, 0x241e, + 0x7d09, 0x20ff, + 0x7d0a, 0x0ed8, + 0x7d0b, 0x219a, + 0x7d0c, 0x42de, + 0x7d0d, 0x2091, + 0x7d0e, 0x42df, + 0x7d10, 0x20a7, + 0x7d11, 0x42e1, + 0x7d13, 0x2423, + 0x7d14, 0x1e9b, + 0x7d15, 0x2422, + 0x7d16, 0x42e3, + 0x7d17, 0x2110, + 0x7d18, 0x42e4, + 0x7d19, 0x228d, + 0x7d1a, 0x1f71, + 0x7d1b, 0x1ef8, + 0x7d1c, 0x2421, + 0x7d1d, 0x42e5, + 0x7d20, 0x0dcd, + 0x7d21, 0x1ef3, + 0x7d22, 0x0dec, + 0x7d23, 0x42e8, + 0x7d27, 0x08c5, + 0x7d28, 0x42ec, + 0x7d2b, 0x122c, + 0x7d2c, 0x42ef, + 0x7d2f, 0x09c6, + 0x7d30, 0x21b1, + 0x7d31, 0x2426, + 0x7d32, 0x2425, + 0x7d33, 0x2120, + 0x7d34, 0x42f2, + 0x7d39, 0x211a, + 0x7d3a, 0x2424, + 0x7d3b, 0x42f7, + 0x7d3c, 0x2428, + 0x7d3d, 0x42f8, + 0x7d3f, 0x242a, + 0x7d40, 0x2429, + 0x7d41, 0x42fa, + 0x7d42, 0x2294, + 0x7d43, 0x42fb, + 0x7d44, 0x22be, + 0x7d45, 0x42fc, + 0x7d46, 0x1e31, + 0x7d47, 0x42fd, + 0x7d4e, 0x242c, + 0x7d4f, 0x4304, + 0x7d50, 0x1fb5, + 0x7d51, 0x4305, + 0x7d5d, 0x242b, + 0x7d5e, 0x1faf, + 0x7d5f, 0x4311, + 0x7d61, 0x2068, + 0x7d62, 0x21e4, + 0x7d63, 0x4313, + 0x7d66, 0x1f21, + 0x7d67, 0x4316, + 0x7d68, 0x2101, + 0x7d69, 0x4317, + 0x7d6e, 0x0fc0, + 0x7d6f, 0x431c, + 0x7d71, 0x217c, + 0x7d72, 0x214a, + 0x7d73, 0x242d, + 0x7d74, 0x431e, + 0x7d76, 0x1fd4, + 0x7d77, 0x1ce8, + 0x7d78, 0x4320, + 0x7d79, 0x1fd1, + 0x7d7a, 0x4321, + 0x7d81, 0x1e33, + 0x7d82, 0x4328, + 0x7d83, 0x242f, + 0x7d84, 0x4329, + 0x7d86, 0x242e, + 0x7d87, 0x432b, + 0x7d88, 0x2430, + 0x7d89, 0x21db, + 0x7d8a, 0x432c, + 0x7d8f, 0x2158, + 0x7d90, 0x4331, + 0x7d93, 0x1fc2, + 0x7d94, 0x4334, + 0x7d9c, 0x22b9, + 0x7d9d, 0x433c, + 0x7d9e, 0x2436, + 0x7d9f, 0x433d, + 0x7da2, 0x1e8e, + 0x7da3, 0x2439, + 0x7da4, 0x4340, + 0x7da6, 0x1ce9, + 0x7da7, 0x4342, + 0x7dab, 0x21c5, + 0x7dac, 0x2437, + 0x7dad, 0x2192, + 0x7dae, 0x1cea, + 0x7daf, 0x4346, + 0x7db0, 0x243a, + 0x7db1, 0x1f19, + 0x7db2, 0x218c, + 0x7db3, 0x1e40, + 0x7db4, 0x22b3, + 0x7db5, 0x4347, + 0x7db8, 0x205f, + 0x7db9, 0x2438, + 0x7dba, 0x2432, + 0x7dbb, 0x2274, + 0x7dbc, 0x434a, + 0x7dbd, 0x1e9c, + 0x7dbe, 0x2431, + 0x7dbf, 0x2085, + 0x7dc0, 0x434b, + 0x7dc4, 0x2435, + 0x7dc5, 0x434f, + 0x7dc7, 0x243b, + 0x7dc8, 0x4351, + 0x7dca, 0x1fb7, + 0x7dcb, 0x2433, + 0x7dcc, 0x4353, + 0x7dd1, 0x2054, + 0x7dd2, 0x21de, + 0x7dd3, 0x4358, + 0x7dd4, 0x2434, + 0x7dd5, 0x4359, + 0x7dd7, 0x243d, + 0x7dd8, 0x1f89, + 0x7dd9, 0x243c, + 0x7dda, 0x435b, + 0x7ddd, 0x1f6e, + 0x7dde, 0x1ed8, + 0x7ddf, 0x435e, + 0x7de0, 0x1ebf, + 0x7de1, 0x2445, + 0x7de2, 0x435f, + 0x7de3, 0x2249, + 0x7de4, 0x4360, + 0x7de6, 0x2441, + 0x7de7, 0x4362, + 0x7de8, 0x1e47, + 0x7de9, 0x1f56, + 0x7dea, 0x4363, + 0x7dec, 0x2086, + 0x7ded, 0x4365, + 0x7def, 0x2196, + 0x7df0, 0x4367, + 0x7df1, 0x2443, + 0x7df2, 0x243f, + 0x7df3, 0x4368, + 0x7df4, 0x2023, + 0x7df5, 0x4369, + 0x7df6, 0x2442, + 0x7df7, 0x436a, + 0x7df9, 0x243e, + 0x7dfa, 0x436c, + 0x7dfb, 0x26a6, + 0x7dfc, 0x436d, + 0x7e00, 0x4371, + 0x7e08, 0x234e, + 0x7e09, 0x2446, + 0x7e0a, 0x244b, + 0x7e0b, 0x2444, + 0x7e0c, 0x4379, + 0x7e10, 0x2427, + 0x7e11, 0x244c, + 0x7e12, 0x437d, + 0x7e1b, 0x1f0f, + 0x7e1c, 0x4386, + 0x7e1d, 0x2447, + 0x7e1e, 0x2449, + 0x7e1f, 0x2448, + 0x7e20, 0x4387, + 0x7e23, 0x21c2, + 0x7e24, 0x438a, + 0x7e27, 0x216e, + 0x7e28, 0x438d, + 0x7e2b, 0x1f03, + 0x7e2c, 0x4390, + 0x7e2d, 0x244a, + 0x7e2e, 0x215c, + 0x7e2f, 0x4391, + 0x7e31, 0x22bb, + 0x7e32, 0x2450, + 0x7e33, 0x4393, + 0x7e34, 0x2694, + 0x7e35, 0x244f, + 0x7e36, 0x25f6, + 0x7e37, 0x2051, + 0x7e38, 0x4394, + 0x7e39, 0x244e, + 0x7e3a, 0x4395, + 0x7e3b, 0x1dfb, + 0x7e3c, 0x4396, + 0x7e3d, 0x22ba, + 0x7e3e, 0x1f6d, + 0x7e3f, 0x4397, + 0x7e41, 0x064e, + 0x7e42, 0x4399, + 0x7e45, 0x2452, + 0x7e46, 0x2451, + 0x7e47, 0x1ceb, + 0x7e48, 0x439c, + 0x7e52, 0x2455, + 0x7e53, 0x43a6, + 0x7e54, 0x2289, + 0x7e55, 0x2116, + 0x7e56, 0x43a7, + 0x7e5a, 0x2454, + 0x7e5b, 0x43ab, + 0x7e5e, 0x20fb, + 0x7e5f, 0x43ae, + 0x7e62, 0x2440, + 0x7e63, 0x43b1, + 0x7e69, 0x2126, + 0x7e6a, 0x1f61, + 0x7e6b, 0x269d, + 0x7e6c, 0x43b7, + 0x7e6d, 0x1f8a, + 0x7e6e, 0x2456, + 0x7e6f, 0x2459, + 0x7e70, 0x2458, + 0x7e71, 0x43b8, + 0x7e73, 0x1fae, + 0x7e74, 0x43ba, + 0x7e79, 0x221a, + 0x7e7a, 0x43bf, + 0x7e7c, 0x1f7a, + 0x7e7d, 0x244d, + 0x7e7e, 0x2457, + 0x7e7f, 0x43c1, + 0x7e82, 0x1248, + 0x7e83, 0x43c4, + 0x7e88, 0x2453, + 0x7e89, 0x43c9, + 0x7e8a, 0x2420, + 0x7e8b, 0x43ca, + 0x7e8c, 0x21df, + 0x7e8d, 0x2685, + 0x7e8e, 0x43cb, + 0x7e8f, 0x1e6e, + 0x7e90, 0x43cc, + 0x7e93, 0x2224, + 0x7e94, 0x2670, + 0x7e95, 0x43cf, + 0x7e96, 0x21ba, + 0x7e97, 0x43d0, + 0x7e98, 0x245a, + 0x7e99, 0x43d1, + 0x7e9b, 0x1cec, + 0x7e9c, 0x1fff, + 0x7e9d, 0x43d3, + 0x7e9f, 0x17d3, + 0x7ea0, 0x08ef, + 0x7ea1, 0x17d4, + 0x7ea2, 0x07a3, + 0x7ea3, 0x17d5, + 0x7ea4, 0x0f38, + 0x7ea5, 0x17d6, + 0x7ea6, 0x10ff, + 0x7ea7, 0x0829, + 0x7ea8, 0x17d7, + 0x7eaa, 0x0840, + 0x7eab, 0x0cad, + 0x7eac, 0x0ec2, + 0x7ead, 0x17d9, + 0x7eae, 0x43d5, + 0x7eaf, 0x0542, + 0x7eb0, 0x17da, + 0x7eb1, 0x0ced, + 0x7eb2, 0x06d4, + 0x7eb3, 0x0b2c, + 0x7eb4, 0x43d6, + 0x7eb5, 0x123a, + 0x7eb6, 0x0a81, + 0x7eb7, 0x0674, + 0x7eb8, 0x11bc, + 0x7eb9, 0x0ed5, + 0x7eba, 0x0661, + 0x7ebb, 0x43d7, + 0x7ebd, 0x0b67, + 0x7ebe, 0x17db, + 0x7ebf, 0x0f4c, + 0x7ec0, 0x17dc, + 0x7ec3, 0x0a00, + 0x7ec4, 0x1246, + 0x7ec5, 0x0d29, + 0x7ec6, 0x0f25, + 0x7ec7, 0x11ae, + 0x7ec8, 0x11d4, + 0x7ec9, 0x17df, + 0x7eca, 0x03f8, + 0x7ecb, 0x17e0, + 0x7ecd, 0x0d15, + 0x7ece, 0x1076, + 0x7ecf, 0x08dc, + 0x7ed0, 0x17e2, + 0x7ed1, 0x03fe, + 0x7ed2, 0x0cb9, + 0x7ed3, 0x08b2, + 0x7ed4, 0x17e3, + 0x7ed5, 0x0ca1, + 0x7ed6, 0x43d9, + 0x7ed7, 0x17e4, + 0x7ed8, 0x07fb, + 0x7ed9, 0x06f3, + 0x7eda, 0x0fcd, + 0x7edb, 0x17e5, + 0x7edc, 0x0a8e, + 0x7edd, 0x0927, + 0x7ede, 0x089b, + 0x7edf, 0x0e64, + 0x7ee0, 0x17e6, + 0x7ee2, 0x091d, + 0x7ee3, 0x0fb0, + 0x7ee4, 0x43da, + 0x7ee5, 0x0ddc, + 0x7ee6, 0x0e23, + 0x7ee7, 0x083f, + 0x7ee8, 0x17e8, + 0x7ee9, 0x081b, + 0x7eea, 0x0fc2, + 0x7eeb, 0x17e9, + 0x7eec, 0x43db, + 0x7eed, 0x0fc3, + 0x7eee, 0x17ea, + 0x7ef0, 0x0545, + 0x7ef1, 0x17ec, + 0x7ef3, 0x0d37, + 0x7ef4, 0x0ebb, + 0x7ef5, 0x0ae5, + 0x7ef6, 0x17ef, + 0x7ef7, 0x042a, + 0x7ef8, 0x0516, + 0x7ef9, 0x43dc, + 0x7efa, 0x17f0, + 0x7efc, 0x1238, + 0x7efd, 0x1161, + 0x7efe, 0x17f2, + 0x7eff, 0x0a73, + 0x7f00, 0x1217, + 0x7f01, 0x17f3, + 0x7f04, 0x085d, + 0x7f05, 0x0aea, + 0x7f06, 0x09ad, + 0x7f07, 0x17f6, + 0x7f09, 0x081c, + 0x7f0a, 0x43dd, + 0x7f0b, 0x17f8, + 0x7f0d, 0x17ee, + 0x7f0e, 0x060f, + 0x7f0f, 0x17fa, + 0x7f10, 0x43de, + 0x7f11, 0x17fb, + 0x7f13, 0x07cf, + 0x7f14, 0x05bf, + 0x7f15, 0x0a6d, + 0x7f16, 0x0449, + 0x7f17, 0x17fd, + 0x7f18, 0x10f8, + 0x7f19, 0x17fe, + 0x7f1a, 0x06ba, + 0x7f1b, 0x1800, + 0x7f1c, 0x17ff, + 0x7f1d, 0x0689, + 0x7f1e, 0x43df, + 0x7f1f, 0x1801, + 0x7f20, 0x04bf, + 0x7f21, 0x1802, + 0x7f28, 0x108c, + 0x7f29, 0x0dea, + 0x7f2a, 0x1809, + 0x7f2e, 0x0d02, + 0x7f2f, 0x180d, + 0x7f34, 0x089a, + 0x7f35, 0x1812, + 0x7f36, 0x1c5e, + 0x7f37, 0x43e0, + 0x7f38, 0x06d2, + 0x7f39, 0x43e1, + 0x7f3a, 0x0c8c, + 0x7f3b, 0x43e2, + 0x7f42, 0x1c5f, + 0x7f43, 0x43e9, + 0x7f44, 0x1c60, + 0x7f46, 0x43ea, + 0x7f4c, 0x25e2, + 0x7f4d, 0x43f0, + 0x7f4e, 0x269a, + 0x7f4f, 0x43f1, + 0x7f50, 0x0737, + 0x7f51, 0x0ea9, + 0x7f52, 0x43f2, + 0x7f54, 0x129e, + 0x7f55, 0x0768, + 0x7f56, 0x43f4, + 0x7f57, 0x0a85, + 0x7f58, 0x1a81, + 0x7f59, 0x43f5, + 0x7f5a, 0x0640, + 0x7f5b, 0x43f6, + 0x7f5f, 0x1a83, + 0x7f60, 0x43fa, + 0x7f61, 0x1a82, + 0x7f62, 0x03e0, + 0x7f63, 0x43fb, + 0x7f68, 0x1a85, + 0x7f69, 0x1177, + 0x7f6a, 0x124c, + 0x7f6b, 0x4400, + 0x7f6e, 0x11c2, + 0x7f6f, 0x4403, + 0x7f70, 0x1eea, + 0x7f71, 0x1a87, + 0x7f72, 0x0d87, + 0x7f73, 0x4404, + 0x7f74, 0x1a86, + 0x7f75, 0x4405, + 0x7f77, 0x1e2c, + 0x7f78, 0x4407, + 0x7f79, 0x1a88, + 0x7f7a, 0x4408, + 0x7f7e, 0x1a8a, + 0x7f7f, 0x440c, + 0x7f81, 0x1a89, + 0x7f82, 0x440e, + 0x7f85, 0x2062, + 0x7f86, 0x24f1, + 0x7f87, 0x4411, + 0x7f88, 0x24f2, + 0x7f89, 0x4412, + 0x7f8a, 0x101b, + 0x7f8b, 0x4413, + 0x7f8c, 0x0c39, + 0x7f8d, 0x4414, + 0x7f8e, 0x0ac5, + 0x7f8f, 0x4415, + 0x7f94, 0x06dc, + 0x7f95, 0x441a, + 0x7f9a, 0x0a30, + 0x7f9b, 0x441f, + 0x7f9d, 0x1cc4, + 0x7f9e, 0x0faa, + 0x7f9f, 0x1cc5, + 0x7fa0, 0x4421, + 0x7fa1, 0x0f48, + 0x7fa2, 0x4422, + 0x7fa4, 0x0c95, + 0x7fa5, 0x25f2, + 0x7fa6, 0x4424, + 0x7fa7, 0x1cc6, + 0x7fa8, 0x4425, + 0x7fa9, 0x2215, + 0x7faa, 0x4426, + 0x7faf, 0x1cc7, + 0x7fb1, 0x442b, + 0x7fb2, 0x1cc9, + 0x7fb3, 0x442c, + 0x7fb8, 0x130e, + 0x7fb9, 0x06f9, + 0x7fba, 0x4431, + 0x7fbc, 0x176d, + 0x7fbd, 0x10d5, + 0x7fbe, 0x4433, + 0x7fbf, 0x1cde, + 0x7fc0, 0x4434, + 0x7fc1, 0x0edb, + 0x7fc2, 0x4435, + 0x7fc5, 0x0506, + 0x7fc6, 0x4438, + 0x7fca, 0x1b98, + 0x7fcb, 0x443c, + 0x7fcc, 0x1075, + 0x7fcd, 0x443d, + 0x7fce, 0x1cdf, + 0x7fcf, 0x443e, + 0x7fd2, 0x21ae, + 0x7fd3, 0x4441, + 0x7fd4, 0x0f55, + 0x7fd5, 0x1ce0, + 0x7fd6, 0x4442, + 0x7fd8, 0x0c49, + 0x7fd9, 0x4444, + 0x7fdf, 0x05b5, + 0x7fe0, 0x0567, + 0x7fe1, 0x1ce2, + 0x7fe2, 0x444a, + 0x7fe5, 0x1ce1, + 0x7fe6, 0x1ce3, + 0x7fe7, 0x444d, + 0x7fe9, 0x1ce4, + 0x7fea, 0x444f, + 0x7fee, 0x1ce5, + 0x7fef, 0x4453, + 0x7ff0, 0x0769, + 0x7ff1, 0x03ca, + 0x7ff2, 0x4454, + 0x7ff3, 0x1ce6, + 0x7ff4, 0x4455, + 0x7ff9, 0x20e0, + 0x7ffa, 0x445a, + 0x7ffb, 0x064a, + 0x7ffc, 0x1074, + 0x7ffd, 0x445b, + 0x8000, 0x1032, + 0x8001, 0x09ba, + 0x8002, 0x445e, + 0x8003, 0x0949, + 0x8004, 0x1953, + 0x8005, 0x1180, + 0x8006, 0x191a, + 0x8007, 0x445f, + 0x800b, 0x1bd7, + 0x800c, 0x0637, + 0x800d, 0x0d98, + 0x800e, 0x4463, + 0x8010, 0x0b30, + 0x8011, 0x4465, + 0x8012, 0x1bcb, + 0x8013, 0x4466, + 0x8014, 0x1bcc, + 0x8015, 0x06f6, + 0x8016, 0x1bcd, + 0x8017, 0x077b, + 0x8018, 0x1108, + 0x8019, 0x03dd, + 0x801a, 0x4467, + 0x801c, 0x1bce, + 0x801d, 0x4469, + 0x8020, 0x1bcf, + 0x8021, 0x446c, + 0x8022, 0x1bd0, + 0x8023, 0x446d, + 0x8025, 0x1bd1, + 0x8028, 0x1bd5, + 0x8029, 0x1bd4, + 0x802a, 0x0b96, + 0x802b, 0x446f, + 0x802c, 0x25c2, + 0x802d, 0x4470, + 0x802e, 0x25c1, + 0x802f, 0x4471, + 0x8031, 0x1bd6, + 0x8032, 0x4473, + 0x8033, 0x0639, + 0x8034, 0x4474, + 0x8035, 0x1bd8, + 0x8036, 0x1035, + 0x8037, 0x14b1, + 0x8038, 0x0dbf, + 0x8039, 0x4475, + 0x803b, 0x0501, + 0x803c, 0x4477, + 0x803d, 0x0583, + 0x803e, 0x4478, + 0x803f, 0x06fb, + 0x8040, 0x4479, + 0x8042, 0x0b57, + 0x8043, 0x1bd9, + 0x8044, 0x447b, + 0x8046, 0x1bda, + 0x8047, 0x447d, + 0x804a, 0x0a0d, + 0x804b, 0x0a44, + 0x804c, 0x11af, + 0x804d, 0x1bdb, + 0x804e, 0x4480, + 0x8052, 0x1bdc, + 0x8053, 0x4484, + 0x8054, 0x09f3, + 0x8055, 0x4485, + 0x8056, 0x2128, + 0x8057, 0x4486, + 0x8058, 0x0bd7, + 0x8059, 0x4487, + 0x805a, 0x090a, + 0x805b, 0x4488, + 0x805e, 0x2199, + 0x805f, 0x448b, + 0x8069, 0x1bdd, + 0x806a, 0x0552, + 0x806b, 0x4495, + 0x806f, 0x2017, + 0x8070, 0x1ea0, + 0x8071, 0x1bde, + 0x8072, 0x2125, + 0x8073, 0x214d, + 0x8074, 0x4499, + 0x8075, 0x25c4, + 0x8076, 0x209d, + 0x8077, 0x228a, + 0x8078, 0x449a, + 0x8079, 0x25c3, + 0x807a, 0x449b, + 0x807d, 0x2179, + 0x807e, 0x2038, + 0x807f, 0x1a1e, + 0x8080, 0x1a1d, + 0x8081, 0x449e, + 0x8083, 0x0dd5, + 0x8084, 0x1065, + 0x8085, 0x2155, + 0x8086, 0x0db6, + 0x8087, 0x1179, + 0x8088, 0x44a0, + 0x8089, 0x0cbd, + 0x808a, 0x44a1, + 0x808b, 0x09ca, + 0x808c, 0x0814, + 0x808d, 0x44a2, + 0x8093, 0x1971, + 0x8094, 0x44a8, + 0x8096, 0x0f6f, + 0x8097, 0x44aa, + 0x8098, 0x11e1, + 0x8099, 0x44ab, + 0x809a, 0x0606, + 0x809b, 0x06d3, + 0x809c, 0x1970, + 0x809d, 0x06c9, + 0x809e, 0x44ac, + 0x809f, 0x196f, + 0x80a0, 0x04cb, + 0x80a1, 0x0722, + 0x80a2, 0x11aa, + 0x80a3, 0x44ad, + 0x80a4, 0x0691, + 0x80a5, 0x0667, + 0x80a6, 0x44ae, + 0x80a9, 0x085a, + 0x80aa, 0x065b, + 0x80ab, 0x1976, + 0x80ac, 0x44b1, + 0x80ad, 0x1977, + 0x80ae, 0x03c4, + 0x80af, 0x095c, + 0x80b0, 0x44b2, + 0x80b1, 0x1975, + 0x80b2, 0x10e2, + 0x80b3, 0x44b3, + 0x80b4, 0x1978, + 0x80b5, 0x44b4, + 0x80b7, 0x1979, + 0x80b8, 0x44b6, + 0x80ba, 0x066b, + 0x80bb, 0x44b8, + 0x80bc, 0x1972, + 0x80bd, 0x1974, + 0x80be, 0x0d2f, + 0x80bf, 0x11d6, + 0x80c0, 0x116e, + 0x80c1, 0x0f7d, + 0x80c2, 0x197f, + 0x80c3, 0x0ec7, + 0x80c4, 0x1980, + 0x80c5, 0x44b9, + 0x80c6, 0x0589, + 0x80c7, 0x44ba, + 0x80cc, 0x041c, + 0x80cd, 0x1982, + 0x80ce, 0x0df8, + 0x80cf, 0x44bf, + 0x80d6, 0x0b97, + 0x80d7, 0x1983, + 0x80d8, 0x44c6, + 0x80d9, 0x1981, + 0x80da, 0x0ba0, + 0x80db, 0x197e, + 0x80dc, 0x0d3b, + 0x80dd, 0x1985, + 0x80de, 0x0406, + 0x80df, 0x44c7, + 0x80e1, 0x07b1, + 0x80e2, 0x44c9, + 0x80e4, 0x126d, + 0x80e5, 0x1bc7, + 0x80e6, 0x44cb, + 0x80e7, 0x197a, + 0x80eb, 0x1986, + 0x80ec, 0x179a, + 0x80ed, 0x1989, + 0x80ee, 0x44cc, + 0x80ef, 0x0975, + 0x80f0, 0x104f, + 0x80f1, 0x1987, + 0x80f2, 0x198c, + 0x80f3, 0x06e7, + 0x80f4, 0x1988, + 0x80f5, 0x44cd, + 0x80f6, 0x088b, + 0x80f7, 0x44ce, + 0x80f8, 0x0fa3, + 0x80f9, 0x44cf, + 0x80fa, 0x03c2, + 0x80fb, 0x44d0, + 0x80fc, 0x198d, + 0x80fd, 0x0b3f, + 0x80fe, 0x44d1, + 0x8100, 0x44d3, + 0x8102, 0x11ab, + 0x8103, 0x44d5, + 0x8105, 0x21d2, + 0x8106, 0x0563, + 0x8107, 0x44d7, + 0x8109, 0x0a9d, + 0x810a, 0x082c, + 0x810b, 0x44d9, + 0x810d, 0x198a, + 0x810f, 0x1123, + 0x8110, 0x0c09, + 0x8111, 0x0b37, + 0x8112, 0x198f, + 0x8113, 0x0b68, + 0x8114, 0x1309, + 0x8115, 0x44db, + 0x8116, 0x0478, + 0x8117, 0x44dc, + 0x8118, 0x1994, + 0x8119, 0x44dd, + 0x811a, 0x0896, + 0x811b, 0x24c7, + 0x811c, 0x44de, + 0x811e, 0x1992, + 0x811f, 0x44e0, + 0x812c, 0x1993, + 0x812d, 0x44ed, + 0x812f, 0x06a7, + 0x8130, 0x44ef, + 0x8131, 0x0e82, + 0x8132, 0x1995, + 0x8133, 0x44f0, + 0x8136, 0x1991, + 0x8137, 0x44f3, + 0x8138, 0x09fc, + 0x8139, 0x2279, + 0x813a, 0x44f4, + 0x813e, 0x0bc1, + 0x813f, 0x44f8, + 0x8146, 0x0e46, + 0x8147, 0x44ff, + 0x8148, 0x1996, + 0x8149, 0x4500, + 0x814a, 0x099b, + 0x814b, 0x103f, + 0x814c, 0x1997, + 0x814d, 0x4501, + 0x814e, 0x2123, + 0x814f, 0x4502, + 0x8150, 0x06aa, + 0x8151, 0x06a8, + 0x8152, 0x4503, + 0x8153, 0x1998, + 0x8154, 0x0c38, + 0x8155, 0x0ea4, + 0x8156, 0x24c5, + 0x8157, 0x4504, + 0x8159, 0x199a, + 0x815b, 0x4506, + 0x8160, 0x199d, + 0x8161, 0x24c9, + 0x8162, 0x450b, + 0x8165, 0x0f93, + 0x8166, 0x2094, + 0x8167, 0x19a2, + 0x8168, 0x450e, + 0x8169, 0x199e, + 0x816a, 0x450f, + 0x816b, 0x2296, + 0x816c, 0x4510, + 0x816d, 0x19a1, + 0x816e, 0x0cd4, + 0x816f, 0x4511, + 0x8170, 0x1025, + 0x8171, 0x199c, + 0x8172, 0x4512, + 0x8174, 0x1999, + 0x8175, 0x4514, + 0x8178, 0x1e77, + 0x8179, 0x06b4, + 0x817a, 0x0f46, + 0x817b, 0x0b48, + 0x817c, 0x199f, + 0x817e, 0x0e2d, + 0x817f, 0x0e79, + 0x8180, 0x03fd, + 0x8181, 0x4517, + 0x8182, 0x19a6, + 0x8183, 0x4518, + 0x8188, 0x19a5, + 0x8189, 0x451d, + 0x818a, 0x0479, + 0x818b, 0x451e, + 0x818f, 0x06db, + 0x8190, 0x4522, + 0x8191, 0x19a7, + 0x8192, 0x4523, + 0x8198, 0x0455, + 0x8199, 0x4529, + 0x819a, 0x1f06, + 0x819b, 0x0e18, + 0x819c, 0x0b07, + 0x819d, 0x0f12, + 0x819e, 0x452a, + 0x81a0, 0x1fa5, + 0x81a1, 0x452c, + 0x81a3, 0x19a9, + 0x81a4, 0x452e, + 0x81a6, 0x19b0, + 0x81a7, 0x4530, + 0x81a8, 0x0bb3, + 0x81a9, 0x2099, + 0x81aa, 0x19aa, + 0x81ab, 0x4531, + 0x81b3, 0x0cfe, + 0x81b4, 0x4539, + 0x81ba, 0x1641, + 0x81bb, 0x19ae, + 0x81bc, 0x453f, + 0x81bd, 0x1ead, + 0x81be, 0x24c8, + 0x81bf, 0x20a8, + 0x81c0, 0x0e7f, + 0x81c1, 0x19af, + 0x81c2, 0x0444, + 0x81c3, 0x109c, + 0x81c4, 0x4540, + 0x81c6, 0x1063, + 0x81c7, 0x4542, + 0x81c9, 0x201f, + 0x81ca, 0x19ad, + 0x81cb, 0x4544, + 0x81cc, 0x19ab, + 0x81cd, 0x20c5, + 0x81ce, 0x4545, + 0x81cf, 0x24ca, + 0x81d0, 0x4546, + 0x81d8, 0x1ff0, + 0x81d9, 0x454e, + 0x81da, 0x24c6, + 0x81db, 0x454f, + 0x81df, 0x225d, + 0x81e0, 0x22de, + 0x81e1, 0x4553, + 0x81e3, 0x04e1, + 0x81e4, 0x4555, + 0x81e7, 0x1902, + 0x81e8, 0x202c, + 0x81e9, 0x4558, + 0x81ea, 0x1231, + 0x81eb, 0x4559, + 0x81ec, 0x1ca9, + 0x81ed, 0x0519, + 0x81ee, 0x455a, + 0x81f3, 0x11c0, + 0x81f5, 0x455f, + 0x81fa, 0x2161, + 0x81fb, 0x118a, + 0x81fc, 0x08f9, + 0x81fd, 0x4564, + 0x81fe, 0x1ca5, + 0x81ff, 0x4565, + 0x8200, 0x102f, + 0x8201, 0x1ca6, + 0x8203, 0x4566, + 0x8204, 0x1ca8, + 0x8205, 0x08fa, + 0x8206, 0x10c4, + 0x8207, 0x223b, + 0x8208, 0x21d9, + 0x8209, 0x1fcb, + 0x820a, 0x1fc9, + 0x820b, 0x4567, + 0x820c, 0x0d19, + 0x820e, 0x4568, + 0x8210, 0x1c62, + 0x8211, 0x456a, + 0x8212, 0x0d7d, + 0x8213, 0x456b, + 0x8214, 0x0e45, + 0x8215, 0x456c, + 0x821b, 0x1618, + 0x821c, 0x0da9, + 0x821d, 0x4572, + 0x821e, 0x0ef7, + 0x821f, 0x11da, + 0x8220, 0x4573, + 0x8221, 0x1cab, + 0x8224, 0x4574, + 0x8228, 0x1cb0, + 0x8229, 0x4578, + 0x822a, 0x0774, + 0x822b, 0x1cb1, + 0x822c, 0x03ee, + 0x822d, 0x1cae, + 0x822e, 0x4579, + 0x822f, 0x1caf, + 0x8230, 0x0873, + 0x8231, 0x049c, + 0x8232, 0x457a, + 0x8233, 0x1cb4, + 0x8235, 0x0625, + 0x8236, 0x0477, + 0x8237, 0x0f3c, + 0x8238, 0x1cb2, + 0x8239, 0x052f, + 0x823a, 0x457b, + 0x823b, 0x1cb3, + 0x823c, 0x457c, + 0x823e, 0x1cb6, + 0x823f, 0x457e, + 0x8244, 0x1cb7, + 0x8245, 0x4583, + 0x8247, 0x0e58, + 0x8248, 0x4585, + 0x8249, 0x1cb8, + 0x824a, 0x4586, + 0x824b, 0x1cb9, + 0x824c, 0x4587, + 0x824f, 0x1cba, + 0x8250, 0x458a, + 0x8258, 0x0dc7, + 0x8259, 0x1e61, + 0x825a, 0x1cbb, + 0x825b, 0x4592, + 0x825f, 0x1cbc, + 0x8260, 0x4596, + 0x8264, 0x25ef, + 0x8265, 0x459a, + 0x8266, 0x1f98, + 0x8267, 0x459b, + 0x8268, 0x1cbd, + 0x8269, 0x459c, + 0x826b, 0x25f0, + 0x826c, 0x459e, + 0x826e, 0x1cdc, + 0x826f, 0x0a05, + 0x8270, 0x085b, + 0x8271, 0x1f88, + 0x8272, 0x0ce4, + 0x8273, 0x1007, + 0x8274, 0x1771, + 0x8275, 0x45a0, + 0x8277, 0x21f8, + 0x8278, 0x45a2, + 0x8279, 0x13e1, + 0x827a, 0x105c, + 0x827b, 0x45a3, + 0x827d, 0x13e2, + 0x827e, 0x03b7, + 0x827f, 0x13e3, + 0x8280, 0x45a5, + 0x8282, 0x08ab, + 0x8283, 0x45a7, + 0x8284, 0x13e7, + 0x8285, 0x45a8, + 0x8288, 0x1278, + 0x8289, 0x45ab, + 0x828a, 0x13e5, + 0x828b, 0x10d8, + 0x828c, 0x45ac, + 0x828d, 0x0d0f, + 0x828e, 0x13e8, + 0x828f, 0x13e4, + 0x8290, 0x45ad, + 0x8291, 0x13e9, + 0x8292, 0x0aa7, + 0x8293, 0x45ae, + 0x8297, 0x13ea, + 0x8298, 0x13f3, + 0x8299, 0x13eb, + 0x829a, 0x45b2, + 0x829c, 0x0eee, + 0x829d, 0x11a4, + 0x829e, 0x45b4, + 0x829f, 0x13fd, + 0x82a0, 0x45b5, + 0x82a1, 0x13fb, + 0x82a2, 0x45b6, + 0x82a4, 0x1400, + 0x82a5, 0x08b7, + 0x82a6, 0x0a52, + 0x82a7, 0x45b8, + 0x82a8, 0x13e6, + 0x82a9, 0x13f9, + 0x82aa, 0x13fc, + 0x82ab, 0x13ec, + 0x82ac, 0x066f, + 0x82ad, 0x03d0, + 0x82ae, 0x13f5, + 0x82af, 0x0f89, + 0x82b0, 0x13ef, + 0x82b1, 0x07bd, + 0x82b2, 0x45b9, + 0x82b3, 0x0659, + 0x82b4, 0x13fa, + 0x82b5, 0x45ba, + 0x82b7, 0x13f4, + 0x82b8, 0x13ed, + 0x82b9, 0x0c58, + 0x82ba, 0x45bc, + 0x82bb, 0x2322, + 0x82bc, 0x45bd, + 0x82bd, 0x0fe8, + 0x82be, 0x13ee, + 0x82bf, 0x45be, + 0x82c1, 0x13f8, + 0x82c2, 0x45c0, + 0x82c4, 0x13fe, + 0x82c5, 0x45c2, + 0x82c7, 0x0ebc, + 0x82c8, 0x13f0, + 0x82c9, 0x45c4, + 0x82ca, 0x13f1, + 0x82cb, 0x13f6, + 0x82cd, 0x049b, + 0x82ce, 0x13ff, + 0x82cf, 0x0dca, + 0x82d0, 0x45c5, + 0x82d1, 0x10fa, + 0x82d2, 0x1409, + 0x82d3, 0x140d, + 0x82d4, 0x0df9, + 0x82d5, 0x1414, + 0x82d6, 0x45c6, + 0x82d7, 0x0aec, + 0x82d8, 0x140a, + 0x82d9, 0x45c7, + 0x82db, 0x094e, + 0x82dc, 0x1407, + 0x82dd, 0x45c9, + 0x82de, 0x0405, + 0x82df, 0x070f, + 0x82e0, 0x1413, + 0x82e1, 0x1401, + 0x82e2, 0x45ca, + 0x82e3, 0x13f2, + 0x82e4, 0x1404, + 0x82e5, 0x0ccf, + 0x82e6, 0x096d, + 0x82e7, 0x2336, + 0x82e8, 0x45cb, + 0x82eb, 0x0cf4, + 0x82ec, 0x45ce, + 0x82ef, 0x0426, + 0x82f0, 0x45d1, + 0x82f1, 0x1087, + 0x82f2, 0x45d2, + 0x82f4, 0x1408, + 0x82f5, 0x45d4, + 0x82f7, 0x1403, + 0x82f8, 0x45d6, + 0x82f9, 0x0bda, + 0x82fa, 0x45d7, + 0x82fb, 0x140c, + 0x82fc, 0x45d8, + 0x8300, 0x45dc, + 0x8301, 0x121f, + 0x8302, 0x0ab4, + 0x8303, 0x0653, + 0x8304, 0x0c4e, + 0x8305, 0x0aae, + 0x8306, 0x1410, + 0x8307, 0x1406, + 0x8308, 0x1419, + 0x8309, 0x1402, + 0x830a, 0x45dd, + 0x830c, 0x140b, + 0x830d, 0x45df, + 0x830e, 0x08d4, + 0x830f, 0x1405, + 0x8310, 0x45e0, + 0x8311, 0x140e, + 0x8312, 0x45e1, + 0x8314, 0x1411, + 0x8316, 0x45e3, + 0x8317, 0x1426, + 0x8318, 0x45e4, + 0x831a, 0x140f, + 0x831b, 0x142e, + 0x831c, 0x1415, + 0x831d, 0x45e6, + 0x8327, 0x085e, + 0x8328, 0x0547, + 0x8329, 0x45f0, + 0x832b, 0x0aa8, + 0x832c, 0x04ae, + 0x832d, 0x1428, + 0x832e, 0x45f2, + 0x832f, 0x1420, + 0x8330, 0x45f3, + 0x8331, 0x141d, + 0x8332, 0x45f4, + 0x8333, 0x142a, + 0x8334, 0x141c, + 0x8335, 0x1077, + 0x8336, 0x04af, + 0x8337, 0x45f5, + 0x8338, 0x0cb2, + 0x8339, 0x0cbe, + 0x833a, 0x1429, + 0x833b, 0x45f6, + 0x833c, 0x141b, + 0x833d, 0x45f7, + 0x8340, 0x1425, + 0x8341, 0x45fa, + 0x8343, 0x1423, + 0x8344, 0x45fc, + 0x8346, 0x08d2, + 0x8347, 0x1422, + 0x8348, 0x45fe, + 0x8349, 0x04a4, + 0x834a, 0x45ff, + 0x834f, 0x1421, + 0x8350, 0x0869, + 0x8351, 0x1416, + 0x8352, 0x07d9, + 0x8353, 0x4604, + 0x8354, 0x09de, + 0x8355, 0x4605, + 0x835a, 0x0847, + 0x835b, 0x1417, + 0x835d, 0x460a, + 0x835e, 0x141f, + 0x835f, 0x1424, + 0x8360, 0x1427, + 0x8361, 0x0595, + 0x8362, 0x460b, + 0x8363, 0x0cb4, + 0x8364, 0x07fc, + 0x8365, 0x142c, + 0x8366, 0x142b, + 0x8367, 0x1090, + 0x8368, 0x142d, + 0x8369, 0x142f, + 0x836a, 0x1431, + 0x836b, 0x1078, + 0x836c, 0x1430, + 0x836d, 0x1432, + 0x836f, 0x1030, + 0x8370, 0x460c, + 0x8377, 0x0780, + 0x8378, 0x1435, + 0x8379, 0x4613, + 0x837b, 0x1442, + 0x837c, 0x143d, + 0x837d, 0x1440, + 0x837e, 0x4615, + 0x8385, 0x143c, + 0x8386, 0x0bed, + 0x8387, 0x461c, + 0x8389, 0x09dd, + 0x838a, 0x22ab, + 0x838b, 0x461e, + 0x838e, 0x0ce8, + 0x838f, 0x4621, + 0x8392, 0x141a, + 0x8393, 0x143a, + 0x8394, 0x4624, + 0x8396, 0x1fbf, + 0x8397, 0x4626, + 0x8398, 0x1443, + 0x8399, 0x4627, + 0x839b, 0x141e, + 0x839c, 0x143b, + 0x839d, 0x4629, + 0x839e, 0x1444, + 0x839f, 0x462a, + 0x83a0, 0x1438, + 0x83a1, 0x462b, + 0x83a2, 0x1f7d, + 0x83a3, 0x462c, + 0x83a7, 0x2333, + 0x83a8, 0x1445, + 0x83a9, 0x143f, + 0x83aa, 0x1439, + 0x83ab, 0x0b0d, + 0x83ac, 0x4630, + 0x83b0, 0x1434, + 0x83b1, 0x099e, + 0x83b2, 0x09f4, + 0x83b3, 0x1436, + 0x83b5, 0x4634, + 0x83b6, 0x143e, + 0x83b7, 0x0806, + 0x83b8, 0x1441, + 0x83b9, 0x108d, + 0x83ba, 0x1446, + 0x83bb, 0x4635, + 0x83bc, 0x1447, + 0x83bd, 0x0aac, + 0x83be, 0x4636, + 0x83c0, 0x145e, + 0x83c1, 0x1448, + 0x83c2, 0x4638, + 0x83c5, 0x145d, + 0x83c6, 0x463b, + 0x83c7, 0x0716, + 0x83c8, 0x463c, + 0x83ca, 0x0904, + 0x83cb, 0x463e, + 0x83cc, 0x0929, + 0x83cd, 0x463f, + 0x83cf, 0x0781, + 0x83d0, 0x4641, + 0x83d4, 0x1456, + 0x83d5, 0x4645, + 0x83d6, 0x1451, + 0x83d7, 0x4646, + 0x83d8, 0x144b, + 0x83d9, 0x4647, + 0x83dc, 0x0492, + 0x83dd, 0x144f, + 0x83de, 0x464a, + 0x83df, 0x1457, + 0x83e0, 0x046b, + 0x83e1, 0x1461, + 0x83e2, 0x464b, + 0x83e5, 0x144a, + 0x83e6, 0x464e, + 0x83e9, 0x0bef, + 0x83ea, 0x145c, + 0x83eb, 0x4651, + 0x83ef, 0x1f4d, + 0x83f0, 0x1460, + 0x83f1, 0x0a2b, + 0x83f2, 0x0663, + 0x83f3, 0x4655, + 0x83f8, 0x145a, + 0x83fa, 0x465a, + 0x83fd, 0x1450, + 0x83fe, 0x465d, + 0x8400, 0x465f, + 0x8401, 0x1449, + 0x8402, 0x4660, + 0x8403, 0x1459, + 0x8404, 0x0e24, + 0x8405, 0x4661, + 0x8406, 0x1455, + 0x8407, 0x2334, + 0x8408, 0x4662, + 0x840a, 0x1ff1, + 0x840b, 0x144e, + 0x840c, 0x0acd, + 0x840d, 0x0bdb, + 0x840e, 0x0ebd, + 0x840f, 0x1458, + 0x8410, 0x4664, + 0x8411, 0x1454, + 0x8412, 0x4665, + 0x8418, 0x144d, + 0x8419, 0x466b, + 0x841c, 0x1452, + 0x841d, 0x0a83, + 0x841e, 0x466e, + 0x8424, 0x108e, + 0x8426, 0x145f, + 0x8427, 0x0f61, + 0x8428, 0x0cd3, + 0x8429, 0x4674, + 0x842c, 0x218b, + 0x842d, 0x4677, + 0x8431, 0x1472, + 0x8432, 0x467b, + 0x8435, 0x2349, + 0x8436, 0x467e, + 0x8438, 0x1453, + 0x8439, 0x4680, + 0x843c, 0x146c, + 0x843d, 0x0a8b, + 0x843e, 0x4683, + 0x8446, 0x146d, + 0x8447, 0x468b, + 0x8449, 0x220b, + 0x844a, 0x468d, + 0x8451, 0x1463, + 0x8452, 0x2346, + 0x8453, 0x4694, + 0x8457, 0x11f7, + 0x8458, 0x4698, + 0x8459, 0x1465, + 0x845a, 0x1464, + 0x845b, 0x06eb, + 0x845c, 0x1462, + 0x845d, 0x4699, + 0x8461, 0x0bee, + 0x8462, 0x469d, + 0x8463, 0x05ec, + 0x8464, 0x2347, + 0x8465, 0x469e, + 0x8466, 0x2193, + 0x8467, 0x469f, + 0x8469, 0x146e, + 0x846a, 0x46a1, + 0x846b, 0x07b0, + 0x846c, 0x1124, + 0x846d, 0x1473, + 0x846e, 0x46a2, + 0x846f, 0x26a1, + 0x8470, 0x46a3, + 0x8471, 0x0553, + 0x8472, 0x46a4, + 0x8473, 0x1466, + 0x8474, 0x46a5, + 0x8475, 0x0988, + 0x8476, 0x146f, + 0x8477, 0x1f62, + 0x8478, 0x146b, + 0x8479, 0x46a6, + 0x847a, 0x1469, + 0x847b, 0x46a7, + 0x8482, 0x05ba, + 0x8483, 0x46ae, + 0x8487, 0x1467, + 0x8489, 0x146a, + 0x848a, 0x46b2, + 0x848b, 0x0880, + 0x848c, 0x1470, + 0x848d, 0x46b3, + 0x848e, 0x1471, + 0x848f, 0x46b4, + 0x8493, 0x234d, + 0x8494, 0x2348, + 0x8495, 0x46b8, + 0x8497, 0x1481, + 0x8498, 0x46ba, + 0x8499, 0x0ace, + 0x849a, 0x46bb, + 0x849c, 0x0dd7, + 0x849d, 0x46bd, + 0x84a1, 0x147e, + 0x84a2, 0x46c1, + 0x84af, 0x1297, + 0x84b0, 0x46ce, + 0x84b2, 0x0bf0, + 0x84b3, 0x46d0, + 0x84b4, 0x1480, + 0x84b5, 0x46d1, + 0x84b8, 0x1195, + 0x84b9, 0x147f, + 0x84ba, 0x147c, + 0x84bb, 0x46d4, + 0x84bc, 0x1e60, + 0x84bd, 0x1478, + 0x84be, 0x46d5, + 0x84bf, 0x147b, + 0x84c0, 0x2345, + 0x84c1, 0x1474, + 0x84c2, 0x46d6, + 0x84c4, 0x0fb9, + 0x84c5, 0x46d8, + 0x84c9, 0x0cb3, + 0x84ca, 0x147a, + 0x84cb, 0x1f12, + 0x84cc, 0x46dc, + 0x84cd, 0x1475, + 0x84ce, 0x46dd, + 0x84d0, 0x1476, + 0x84d1, 0x0de7, + 0x84d2, 0x46df, + 0x84d3, 0x1479, + 0x84d4, 0x46e0, + 0x84d6, 0x0436, + 0x84d7, 0x46e2, + 0x84dd, 0x09a1, + 0x84de, 0x46e8, + 0x84df, 0x082e, + 0x84e0, 0x147d, + 0x84e1, 0x46e9, + 0x84e3, 0x1483, + 0x84e4, 0x46eb, + 0x84e5, 0x1482, + 0x84e6, 0x1477, + 0x84e7, 0x46ec, + 0x84ec, 0x0baf, + 0x84ed, 0x46f1, + 0x84ee, 0x2018, + 0x84ef, 0x2335, + 0x84f0, 0x1487, + 0x84f1, 0x46f2, + 0x84fc, 0x148e, + 0x84fd, 0x233c, + 0x84fe, 0x46fd, + 0x84ff, 0x148d, + 0x8500, 0x46fe, + 0x850c, 0x1484, + 0x850d, 0x470a, + 0x8511, 0x0af4, + 0x8512, 0x470e, + 0x8513, 0x0aa2, + 0x8514, 0x266f, + 0x8515, 0x470f, + 0x8517, 0x1182, + 0x8518, 0x4711, + 0x851a, 0x0ec4, + 0x851b, 0x4713, + 0x851e, 0x2351, + 0x851f, 0x1489, + 0x8520, 0x4716, + 0x8521, 0x0493, + 0x8522, 0x4717, + 0x8523, 0x1fa0, + 0x8524, 0x4718, + 0x8526, 0x2338, + 0x8527, 0x471a, + 0x852b, 0x0b4b, + 0x852c, 0x0d76, + 0x852d, 0x221b, + 0x852e, 0x471e, + 0x8537, 0x0c3b, + 0x8538, 0x1486, + 0x8539, 0x1488, + 0x853a, 0x148a, + 0x853b, 0x148c, + 0x853c, 0x03b5, + 0x853d, 0x0437, + 0x853e, 0x4727, + 0x8541, 0x2342, + 0x8542, 0x472a, + 0x8543, 0x1496, + 0x8544, 0x472b, + 0x8546, 0x234f, + 0x8547, 0x472d, + 0x8548, 0x1490, + 0x8549, 0x0887, + 0x854a, 0x0cca, + 0x854b, 0x472e, + 0x854e, 0x233d, + 0x854f, 0x4731, + 0x8552, 0x2344, + 0x8553, 0x2331, + 0x8554, 0x4734, + 0x8555, 0x234b, + 0x8556, 0x148b, + 0x8557, 0x4735, + 0x8558, 0x233b, + 0x8559, 0x148f, + 0x855a, 0x4736, + 0x855e, 0x1493, + 0x855f, 0x473a, + 0x8562, 0x2350, + 0x8563, 0x473d, + 0x8564, 0x1492, + 0x8565, 0x473e, + 0x8568, 0x1491, + 0x8569, 0x1eb4, + 0x856a, 0x21a6, + 0x856b, 0x4741, + 0x856d, 0x21cb, + 0x856e, 0x4743, + 0x8572, 0x1497, + 0x8573, 0x4747, + 0x8574, 0x110f, + 0x8575, 0x4748, + 0x8577, 0x2355, + 0x8578, 0x474a, + 0x8579, 0x149d, + 0x857a, 0x1494, + 0x857b, 0x1498, + 0x857c, 0x474b, + 0x857e, 0x09c4, + 0x857f, 0x474d, + 0x8584, 0x040a, + 0x8585, 0x14a0, + 0x8586, 0x4752, + 0x8587, 0x149b, + 0x8588, 0x233e, + 0x8589, 0x4753, + 0x858a, 0x1f74, + 0x858b, 0x4754, + 0x858c, 0x2330, + 0x858d, 0x4755, + 0x858f, 0x149c, + 0x8590, 0x4757, + 0x8591, 0x2680, + 0x8592, 0x4758, + 0x8594, 0x20da, + 0x8595, 0x475a, + 0x859b, 0x0fcf, + 0x859c, 0x149f, + 0x859d, 0x4760, + 0x859f, 0x234a, + 0x85a0, 0x4762, + 0x85a4, 0x1499, + 0x85a5, 0x4766, + 0x85a6, 0x1f91, + 0x85a7, 0x4767, + 0x85a8, 0x149a, + 0x85a9, 0x2107, + 0x85aa, 0x0f88, + 0x85ab, 0x4768, + 0x85ae, 0x149e, + 0x85af, 0x0d84, + 0x85b0, 0x14a3, + 0x85b1, 0x476b, + 0x85b7, 0x14a2, + 0x85b8, 0x4771, + 0x85b9, 0x14a1, + 0x85ba, 0x233f, + 0x85bb, 0x4772, + 0x85c1, 0x14a5, + 0x85c2, 0x4778, + 0x85c9, 0x08b6, + 0x85ca, 0x477f, + 0x85cd, 0x1ff4, + 0x85ce, 0x2343, + 0x85cf, 0x049f, + 0x85d0, 0x0aef, + 0x85d1, 0x4782, + 0x85d3, 0x14a4, + 0x85d4, 0x4784, + 0x85d5, 0x0b7b, + 0x85d6, 0x4785, + 0x85dc, 0x14a6, + 0x85dd, 0x2212, + 0x85de, 0x478b, + 0x85e4, 0x0e2c, + 0x85e5, 0x2207, + 0x85e6, 0x4791, + 0x85e9, 0x0647, + 0x85ea, 0x2359, + 0x85eb, 0x4794, + 0x85f4, 0x2254, + 0x85f5, 0x479d, + 0x85f6, 0x2332, + 0x85f7, 0x479e, + 0x85f9, 0x1e26, + 0x85fa, 0x2357, + 0x85fb, 0x1128, + 0x85fc, 0x47a0, + 0x85ff, 0x14a7, + 0x8600, 0x47a3, + 0x8604, 0x2358, + 0x8605, 0x14a9, + 0x8606, 0x2042, + 0x8607, 0x2153, + 0x8608, 0x47a7, + 0x860b, 0x20bb, + 0x860c, 0x47aa, + 0x8611, 0x0b05, + 0x8612, 0x47af, + 0x8616, 0x14ab, + 0x8617, 0x47b3, + 0x861a, 0x235a, + 0x861b, 0x47b6, + 0x861e, 0x2356, + 0x861f, 0x47b9, + 0x8622, 0x2337, + 0x8623, 0x47bc, + 0x8627, 0x14a8, + 0x8628, 0x47c0, + 0x8629, 0x14aa, + 0x862a, 0x47c1, + 0x862d, 0x1ff9, + 0x862e, 0x47c4, + 0x8638, 0x115b, + 0x8639, 0x47ce, + 0x863a, 0x2353, + 0x863b, 0x47cf, + 0x863c, 0x14ac, + 0x863d, 0x47d0, + 0x863f, 0x2061, + 0x8640, 0x47d2, + 0x864d, 0x1bf0, + 0x864e, 0x07b7, + 0x864f, 0x0a59, + 0x8650, 0x0b71, + 0x8651, 0x0a6e, + 0x8652, 0x47df, + 0x8654, 0x1bf1, + 0x8655, 0x1e95, + 0x8656, 0x47e1, + 0x865a, 0x0fb4, + 0x865b, 0x47e5, + 0x865c, 0x2049, + 0x865d, 0x47e6, + 0x865e, 0x10c2, + 0x865f, 0x1f42, + 0x8660, 0x47e7, + 0x8662, 0x196d, + 0x8663, 0x47e9, + 0x8667, 0x1fe8, + 0x8668, 0x47ed, + 0x866b, 0x050b, + 0x866c, 0x1bf2, + 0x866d, 0x47f0, + 0x866e, 0x1bf3, + 0x866f, 0x47f1, + 0x8671, 0x0d44, + 0x8672, 0x47f3, + 0x8679, 0x079e, + 0x867a, 0x1bf5, + 0x867b, 0x1bf7, + 0x867c, 0x1bf6, + 0x867d, 0x0dd9, + 0x867e, 0x0f27, + 0x867f, 0x1bf4, + 0x8680, 0x0d4b, + 0x8681, 0x1056, + 0x8682, 0x0a93, + 0x8683, 0x47fa, + 0x868a, 0x0ed2, + 0x868b, 0x1bfa, + 0x868c, 0x0401, + 0x868d, 0x1bf9, + 0x868e, 0x4801, + 0x8693, 0x1c00, + 0x8694, 0x4806, + 0x8695, 0x0496, + 0x8696, 0x4807, + 0x869c, 0x0fea, + 0x869d, 0x1bfc, + 0x869e, 0x480d, + 0x86a3, 0x1bfe, + 0x86a4, 0x112c, + 0x86a5, 0x4812, + 0x86a7, 0x1bfd, + 0x86a8, 0x1bf8, + 0x86a9, 0x1c01, + 0x86aa, 0x1bff, + 0x86ab, 0x4814, + 0x86ac, 0x1bfb, + 0x86ad, 0x4815, + 0x86af, 0x1c09, + 0x86b0, 0x1c06, + 0x86b1, 0x1c08, + 0x86b2, 0x4817, + 0x86b4, 0x1c0c, + 0x86b5, 0x1c04, + 0x86b6, 0x1c02, + 0x86b7, 0x4819, + 0x86ba, 0x1c07, + 0x86bb, 0x481c, + 0x86c0, 0x11fa, + 0x86c1, 0x4821, + 0x86c4, 0x1c03, + 0x86c5, 0x4824, + 0x86c6, 0x0c76, + 0x86c7, 0x0d18, + 0x86c8, 0x4825, + 0x86c9, 0x1c0a, + 0x86ca, 0x071f, + 0x86cb, 0x0591, + 0x86cc, 0x4826, + 0x86ce, 0x1c05, + 0x86cf, 0x1c0b, + 0x86d0, 0x1c12, + 0x86d1, 0x1c18, + 0x86d2, 0x4828, + 0x86d4, 0x07ec, + 0x86d5, 0x482a, + 0x86d8, 0x1c17, + 0x86d9, 0x0e8d, + 0x86da, 0x482d, + 0x86db, 0x11ea, + 0x86dc, 0x482e, + 0x86de, 0x1c14, + 0x86df, 0x1c16, + 0x86e0, 0x4830, + 0x86e4, 0x06ed, + 0x86e5, 0x4834, + 0x86e9, 0x1c0d, + 0x86ea, 0x4838, + 0x86ed, 0x1c10, + 0x86ee, 0x0aa0, + 0x86ef, 0x483b, + 0x86f0, 0x117e, + 0x86f1, 0x1c0e, + 0x86f3, 0x1c11, + 0x86f4, 0x1c15, + 0x86f5, 0x483c, + 0x86f8, 0x1c1b, + 0x86f9, 0x10a1, + 0x86fa, 0x25da, + 0x86fb, 0x483f, + 0x86fe, 0x0629, + 0x86ff, 0x4842, + 0x8700, 0x0d88, + 0x8701, 0x4843, + 0x8702, 0x0681, + 0x8703, 0x1c19, + 0x8704, 0x4844, + 0x8706, 0x25d7, + 0x8707, 0x1c1a, + 0x8708, 0x1c1c, + 0x8709, 0x1c1f, + 0x870a, 0x1c1d, + 0x870b, 0x4846, + 0x870d, 0x1c1e, + 0x870e, 0x4848, + 0x8712, 0x0ffa, + 0x8713, 0x1c13, + 0x8714, 0x484c, + 0x8715, 0x0e7a, + 0x8716, 0x484d, + 0x8717, 0x0ede, + 0x8718, 0x11a8, + 0x8719, 0x484e, + 0x871a, 0x1c25, + 0x871b, 0x484f, + 0x871c, 0x0ae0, + 0x871d, 0x4850, + 0x871e, 0x1c22, + 0x871f, 0x4851, + 0x8721, 0x099a, + 0x8722, 0x1c2e, + 0x8723, 0x1c20, + 0x8724, 0x4853, + 0x8725, 0x1c23, + 0x8726, 0x4854, + 0x8729, 0x1c2a, + 0x872a, 0x4857, + 0x872e, 0x1c24, + 0x872f, 0x485b, + 0x8731, 0x1c29, + 0x8732, 0x485d, + 0x8734, 0x1c28, + 0x8735, 0x485f, + 0x8737, 0x1c2b, + 0x8738, 0x4861, + 0x873b, 0x1c21, + 0x873c, 0x4864, + 0x873e, 0x1c26, + 0x873f, 0x1c2c, + 0x8740, 0x4866, + 0x8747, 0x1091, + 0x8748, 0x1c27, + 0x8749, 0x04bc, + 0x874a, 0x486d, + 0x874c, 0x1c34, + 0x874d, 0x486f, + 0x874e, 0x0f76, + 0x874f, 0x4870, + 0x8753, 0x1c37, + 0x8754, 0x4874, + 0x8755, 0x212e, + 0x8756, 0x4875, + 0x8757, 0x07dd, + 0x8758, 0x4876, + 0x8759, 0x1c3b, + 0x875a, 0x4877, + 0x8760, 0x1c32, + 0x8761, 0x487d, + 0x8763, 0x1c38, + 0x8764, 0x1c3a, + 0x8765, 0x1c3c, + 0x8766, 0x21b2, + 0x8767, 0x487f, + 0x876e, 0x1c35, + 0x876f, 0x4886, + 0x8770, 0x1c33, + 0x8771, 0x4887, + 0x8774, 0x07b2, + 0x8775, 0x488a, + 0x8776, 0x05dc, + 0x8777, 0x488b, + 0x8778, 0x219e, + 0x8779, 0x488c, + 0x877b, 0x1c31, + 0x877c, 0x1c39, + 0x877d, 0x1c2f, + 0x877f, 0x488e, + 0x8782, 0x1c2d, + 0x8783, 0x1c46, + 0x8784, 0x25dc, + 0x8785, 0x1c43, + 0x8786, 0x4891, + 0x8788, 0x1c42, + 0x8789, 0x4893, + 0x878b, 0x1c36, + 0x878c, 0x4895, + 0x878d, 0x0cb5, + 0x878e, 0x4896, + 0x8793, 0x1c3d, + 0x8794, 0x489b, + 0x8797, 0x1c45, + 0x8798, 0x489e, + 0x879e, 0x206c, + 0x879f, 0x0afd, + 0x87a0, 0x48a4, + 0x87a2, 0x2226, + 0x87a3, 0x48a6, + 0x87a8, 0x1c3f, + 0x87a9, 0x48ab, + 0x87ab, 0x1c47, + 0x87ac, 0x1c49, + 0x87ad, 0x1c44, + 0x87ae, 0x48ad, + 0x87af, 0x1c3e, + 0x87b0, 0x48ae, + 0x87b3, 0x1c4b, + 0x87b4, 0x48b1, + 0x87b5, 0x1c4a, + 0x87b6, 0x48b2, + 0x87ba, 0x0a84, + 0x87bb, 0x25e0, + 0x87bc, 0x48b6, + 0x87bd, 0x1c4e, + 0x87be, 0x48b7, + 0x87c0, 0x1c50, + 0x87c1, 0x48b9, + 0x87c4, 0x227b, + 0x87c5, 0x48bc, + 0x87c6, 0x1c41, + 0x87c7, 0x48bd, + 0x87c8, 0x25de, + 0x87c9, 0x48be, + 0x87ca, 0x1c51, + 0x87cb, 0x1c4c, + 0x87cc, 0x48bf, + 0x87ce, 0x25e1, + 0x87cf, 0x48c1, + 0x87d1, 0x1c4f, + 0x87d2, 0x1c40, + 0x87d3, 0x1c4d, + 0x87d4, 0x48c3, + 0x87db, 0x1c52, + 0x87dc, 0x48ca, + 0x87e0, 0x1c54, + 0x87e1, 0x48ce, + 0x87e3, 0x25d5, + 0x87e4, 0x48d0, + 0x87e5, 0x1c48, + 0x87e6, 0x48d1, + 0x87ea, 0x1c53, + 0x87eb, 0x48d5, + 0x87ec, 0x1e6b, + 0x87ed, 0x48d6, + 0x87ee, 0x1c55, + 0x87ef, 0x25db, + 0x87f0, 0x48d7, + 0x87f2, 0x1e89, + 0x87f3, 0x48d9, + 0x87f6, 0x25d9, + 0x87f7, 0x48dc, + 0x87f9, 0x0f82, + 0x87fa, 0x48de, + 0x87fb, 0x2211, + 0x87fc, 0x48df, + 0x87fe, 0x1c58, + 0x87ff, 0x48e1, + 0x8800, 0x48e2, + 0x8803, 0x130d, + 0x8804, 0x48e5, + 0x8805, 0x2229, + 0x8806, 0x25d6, + 0x8807, 0x48e6, + 0x880a, 0x1c59, + 0x880b, 0x48e9, + 0x8810, 0x25dd, + 0x8811, 0x25df, + 0x8812, 0x48ee, + 0x8813, 0x1c57, + 0x8814, 0x48ef, + 0x8815, 0x0cbf, + 0x8816, 0x1c56, + 0x8817, 0x48f0, + 0x881b, 0x1c5a, + 0x881c, 0x48f4, + 0x881f, 0x1fef, + 0x8820, 0x48f7, + 0x8821, 0x1c5b, + 0x8822, 0x0543, + 0x8823, 0x25d8, + 0x8824, 0x48f8, + 0x8831, 0x1f29, + 0x8832, 0x1a8d, + 0x8833, 0x4905, + 0x8836, 0x1e5b, + 0x8837, 0x4908, + 0x8839, 0x1c5c, + 0x883a, 0x490a, + 0x883b, 0x2076, + 0x883c, 0x1c5d, + 0x883d, 0x490b, + 0x8840, 0x0fd3, + 0x8841, 0x490e, + 0x8844, 0x1caa, + 0x8845, 0x0f91, + 0x8846, 0x2297, + 0x8847, 0x4911, + 0x884a, 0x2690, + 0x884b, 0x4914, + 0x884c, 0x0f9b, + 0x884d, 0x1005, + 0x884e, 0x4915, + 0x8853, 0x213f, + 0x8854, 0x0f3b, + 0x8855, 0x491a, + 0x8857, 0x08a7, + 0x8858, 0x491c, + 0x8859, 0x0fec, + 0x885a, 0x491d, + 0x885b, 0x2198, + 0x885c, 0x491e, + 0x885d, 0x1e88, + 0x885e, 0x491f, + 0x8861, 0x0799, + 0x8862, 0x15ed, + 0x8863, 0x1049, + 0x8864, 0x1ba6, + 0x8865, 0x0480, + 0x8866, 0x4922, + 0x8868, 0x0456, + 0x8869, 0x1ba7, + 0x886a, 0x4924, + 0x886b, 0x0cf9, + 0x886c, 0x04e9, + 0x886d, 0x4925, + 0x886e, 0x1306, + 0x886f, 0x4926, + 0x8870, 0x0d9a, + 0x8871, 0x4927, + 0x8872, 0x1ba8, + 0x8873, 0x4928, + 0x8877, 0x11d3, + 0x8878, 0x492c, + 0x8879, 0x228c, + 0x887a, 0x492d, + 0x887d, 0x1ba9, + 0x887e, 0x1cbe, + 0x887f, 0x1baa, + 0x8880, 0x4930, + 0x8881, 0x10ef, + 0x8882, 0x1bab, + 0x8883, 0x4931, + 0x8884, 0x03cb, + 0x8885, 0x1cbf, + 0x8886, 0x4932, + 0x8888, 0x1cc0, + 0x8889, 0x4934, + 0x888b, 0x057f, + 0x888c, 0x4936, + 0x888d, 0x0b9c, + 0x888e, 0x4937, + 0x8892, 0x0e0e, + 0x8893, 0x493b, + 0x8896, 0x0faf, + 0x8897, 0x493e, + 0x889c, 0x0e91, + 0x889d, 0x4943, + 0x88a2, 0x1bac, + 0x88a3, 0x4948, + 0x88a4, 0x1307, + 0x88a5, 0x4949, + 0x88ab, 0x0424, + 0x88ac, 0x494f, + 0x88ad, 0x0f1b, + 0x88ae, 0x4950, + 0x88b1, 0x069f, + 0x88b2, 0x4953, + 0x88b7, 0x1bae, + 0x88b8, 0x4958, + 0x88bc, 0x1baf, + 0x88bd, 0x495c, + 0x88c1, 0x048a, + 0x88c2, 0x0a1a, + 0x88c3, 0x4960, + 0x88c5, 0x120d, + 0x88c6, 0x1bad, + 0x88c7, 0x4962, + 0x88c9, 0x1bb0, + 0x88ca, 0x25f1, + 0x88cb, 0x4964, + 0x88ce, 0x1bb2, + 0x88cf, 0x200c, + 0x88d0, 0x4967, + 0x88d2, 0x130a, + 0x88d3, 0x4969, + 0x88d4, 0x1068, + 0x88d5, 0x10e6, + 0x88d6, 0x496a, + 0x88d8, 0x1cc1, + 0x88d9, 0x0c94, + 0x88da, 0x496c, + 0x88dc, 0x1e58, + 0x88dd, 0x22ac, + 0x88de, 0x496e, + 0x88df, 0x1cc2, + 0x88e0, 0x496f, + 0x88e2, 0x1bb1, + 0x88e3, 0x1bb3, + 0x88e4, 0x0970, + 0x88e5, 0x1bb4, + 0x88e6, 0x4971, + 0x88e8, 0x1bb8, + 0x88e9, 0x4973, + 0x88f0, 0x1bba, + 0x88f1, 0x1bb5, + 0x88f2, 0x497a, + 0x88f3, 0x0d0a, + 0x88f4, 0x0ba2, + 0x88f5, 0x497b, + 0x88f8, 0x0a8a, + 0x88f9, 0x0755, + 0x88fa, 0x497e, + 0x88fc, 0x1bb7, + 0x88fd, 0x26a7, + 0x88fe, 0x1bb9, + 0x88ff, 0x4980, + 0x8900, 0x4981, + 0x8902, 0x072c, + 0x8903, 0x4983, + 0x8907, 0x2676, + 0x8908, 0x4987, + 0x890a, 0x1bbf, + 0x890b, 0x4989, + 0x8910, 0x078d, + 0x8911, 0x498e, + 0x8912, 0x0408, + 0x8913, 0x1bbd, + 0x8914, 0x498f, + 0x8919, 0x1bbc, + 0x891a, 0x1bb6, + 0x891b, 0x1bbe, + 0x891c, 0x4994, + 0x8921, 0x1bbb, + 0x8922, 0x4999, + 0x8925, 0x0cc7, + 0x8926, 0x499c, + 0x892a, 0x0e7b, + 0x892b, 0x1bc1, + 0x892c, 0x49a0, + 0x8930, 0x1739, + 0x8931, 0x49a4, + 0x8932, 0x1fe1, + 0x8933, 0x25bb, + 0x8934, 0x1bc0, + 0x8935, 0x49a5, + 0x8936, 0x1bc2, + 0x8937, 0x49a6, + 0x8938, 0x25be, + 0x8939, 0x49a7, + 0x893b, 0x22dd, + 0x893c, 0x49a9, + 0x8941, 0x1bc3, + 0x8942, 0x49ae, + 0x8944, 0x0f52, + 0x8945, 0x49b0, + 0x8947, 0x25bd, + 0x8948, 0x49b2, + 0x8956, 0x1e2a, + 0x8957, 0x49c0, + 0x895d, 0x25bc, + 0x895e, 0x1cc3, + 0x895f, 0x08c4, + 0x8960, 0x25ba, + 0x8961, 0x49c6, + 0x8964, 0x25bf, + 0x8965, 0x49c9, + 0x8966, 0x1bc4, + 0x8967, 0x49ca, + 0x896a, 0x2187, + 0x896b, 0x49cd, + 0x896c, 0x266b, + 0x896d, 0x49ce, + 0x896f, 0x1e7f, + 0x8970, 0x49d0, + 0x8972, 0x21ad, + 0x8973, 0x49d2, + 0x897b, 0x1bc5, + 0x897c, 0x49da, + 0x897f, 0x0f06, + 0x8980, 0x49dd, + 0x8981, 0x1031, + 0x8982, 0x49de, + 0x8983, 0x1bdf, + 0x8984, 0x49df, + 0x8986, 0x06ad, + 0x8987, 0x49e1, + 0x898b, 0x1f96, + 0x898c, 0x49e5, + 0x898f, 0x1f32, + 0x8990, 0x49e8, + 0x8993, 0x2084, + 0x8994, 0x49eb, + 0x8996, 0x2136, + 0x8997, 0x49ed, + 0x8998, 0x24b8, + 0x8999, 0x49ee, + 0x89a1, 0x24ba, + 0x89a2, 0x49f6, + 0x89a6, 0x24bc, + 0x89a7, 0x49fa, + 0x89aa, 0x20e4, + 0x89ab, 0x49fd, + 0x89ac, 0x24b9, + 0x89ad, 0x49fe, + 0x89af, 0x24bd, + 0x89b0, 0x4a00, + 0x89b2, 0x24be, + 0x89b3, 0x4a02, + 0x89b7, 0x24bf, + 0x89b8, 0x4a06, + 0x89ba, 0x1fd2, + 0x89bb, 0x4a08, + 0x89bd, 0x1ffd, + 0x89be, 0x4a0a, + 0x89bf, 0x24bb, + 0x89c0, 0x1f2d, + 0x89c1, 0x086e, + 0x89c2, 0x0734, + 0x89c3, 0x4a0b, + 0x89c4, 0x073f, + 0x89c5, 0x0ade, + 0x89c6, 0x0d6a, + 0x89c7, 0x193a, + 0x89c8, 0x09ab, + 0x89c9, 0x0924, + 0x89ca, 0x193b, + 0x89cd, 0x4a0c, + 0x89ce, 0x193e, + 0x89d2, 0x0898, + 0x89d3, 0x4a0d, + 0x89d6, 0x1d57, + 0x89d7, 0x4a10, + 0x89da, 0x1d59, + 0x89db, 0x4a13, + 0x89dc, 0x1d5a, + 0x89dd, 0x4a14, + 0x89de, 0x1d58, + 0x89df, 0x4a15, + 0x89e3, 0x08b3, + 0x89e4, 0x4a19, + 0x89e5, 0x1d5b, + 0x89e6, 0x0528, + 0x89e7, 0x4a1a, + 0x89eb, 0x1d5c, + 0x89ec, 0x4a1e, + 0x89ef, 0x1d5d, + 0x89f0, 0x4a21, + 0x89f3, 0x19c0, + 0x89f4, 0x2609, + 0x89f5, 0x4a24, + 0x89f6, 0x260a, + 0x89f7, 0x4a25, + 0x89f8, 0x1e94, + 0x89f9, 0x4a26, + 0x8a00, 0x0ffd, + 0x8a01, 0x22df, + 0x8a02, 0x1ecb, + 0x8a03, 0x1f0d, + 0x8a04, 0x4a2d, + 0x8a07, 0x12fe, + 0x8a08, 0x1f77, + 0x8a09, 0x4a30, + 0x8a0a, 0x21eb, + 0x8a0b, 0x4a31, + 0x8a0c, 0x22e1, + 0x8a0d, 0x4a32, + 0x8a0e, 0x216f, + 0x8a0f, 0x4a33, + 0x8a10, 0x22e0, + 0x8a11, 0x4a34, + 0x8a13, 0x21ea, + 0x8a14, 0x4a36, + 0x8a15, 0x22e2, + 0x8a16, 0x20cb, + 0x8a17, 0x4a37, + 0x8a18, 0x1f78, + 0x8a19, 0x4a38, + 0x8a1b, 0x1ee2, + 0x8a1c, 0x4a3a, + 0x8a1d, 0x21f2, + 0x8a1e, 0x4a3b, + 0x8a1f, 0x2150, + 0x8a20, 0x4a3c, + 0x8a23, 0x1fd3, + 0x8a24, 0x4a3f, + 0x8a25, 0x22e5, + 0x8a26, 0x4a40, + 0x8a2a, 0x1ef2, + 0x8a2b, 0x4a44, + 0x8a2d, 0x211f, + 0x8a2e, 0x4a46, + 0x8a31, 0x21dd, + 0x8a32, 0x4a49, + 0x8a34, 0x2154, + 0x8a35, 0x4a4b, + 0x8a36, 0x22e7, + 0x8a37, 0x4a4c, + 0x8a3a, 0x2282, + 0x8a3b, 0x4a4f, + 0x8a3e, 0x1d5e, + 0x8a3f, 0x4a52, + 0x8a41, 0x22e6, + 0x8a42, 0x4a54, + 0x8a46, 0x22e8, + 0x8a47, 0x4a58, + 0x8a48, 0x1a84, + 0x8a49, 0x4a59, + 0x8a4e, 0x22e4, + 0x8a4f, 0x4a5e, + 0x8a50, 0x226a, + 0x8a51, 0x4a5f, + 0x8a52, 0x22eb, + 0x8a53, 0x4a60, + 0x8a54, 0x22e9, + 0x8a55, 0x20bd, + 0x8a56, 0x4a61, + 0x8a58, 0x22ea, + 0x8a59, 0x4a63, + 0x8a5b, 0x22bd, + 0x8a5c, 0x4a65, + 0x8a5e, 0x1e9e, + 0x8a5f, 0x4a67, + 0x8a61, 0x22f6, + 0x8a62, 0x21e7, + 0x8a63, 0x2216, + 0x8a64, 0x4a69, + 0x8a66, 0x2137, + 0x8a67, 0x4a6b, + 0x8a69, 0x212c, + 0x8a6a, 0x4a6d, + 0x8a6b, 0x1e68, + 0x8a6c, 0x22f2, + 0x8a6d, 0x1f37, + 0x8a6e, 0x22f3, + 0x8a6f, 0x4a6e, + 0x8a70, 0x22ef, + 0x8a71, 0x1f50, + 0x8a72, 0x1f10, + 0x8a73, 0x21c8, + 0x8a74, 0x4a6f, + 0x8a75, 0x22f1, + 0x8a76, 0x4a70, + 0x8a79, 0x1153, + 0x8a7a, 0x4a73, + 0x8a7c, 0x22f0, + 0x8a7d, 0x4a75, + 0x8a7f, 0x22ee, + 0x8a80, 0x4a77, + 0x8a84, 0x22ed, + 0x8a85, 0x229e, + 0x8a86, 0x22ec, + 0x8a87, 0x1fe2, + 0x8a88, 0x4a7b, + 0x8a89, 0x10e3, + 0x8a8a, 0x0e2f, + 0x8a8b, 0x4a7c, + 0x8a8d, 0x20fe, + 0x8a8e, 0x4a7e, + 0x8a91, 0x22f9, + 0x8a93, 0x0d5b, + 0x8a94, 0x4a81, + 0x8a95, 0x1eaf, + 0x8a96, 0x4a82, + 0x8a98, 0x2236, + 0x8a99, 0x4a84, + 0x8a9a, 0x22f7, + 0x8a9b, 0x4a85, + 0x8a9e, 0x223d, + 0x8a9f, 0x4a88, + 0x8aa0, 0x1e82, + 0x8aa1, 0x1fb6, + 0x8aa2, 0x4a89, + 0x8aa3, 0x21a4, + 0x8aa4, 0x21aa, + 0x8aa5, 0x22f8, + 0x8aa6, 0x2151, + 0x8aa7, 0x4a8a, + 0x8aa8, 0x1f60, + 0x8aa9, 0x4a8b, + 0x8aac, 0x2147, + 0x8aad, 0x4a8e, + 0x8ab0, 0x2145, + 0x8ab1, 0x4a91, + 0x8ab2, 0x1fdc, + 0x8ab3, 0x4a92, + 0x8ab6, 0x2301, + 0x8ab7, 0x4a95, + 0x8ab9, 0x1ef5, + 0x8aba, 0x4a97, + 0x8abc, 0x2218, + 0x8abd, 0x4a99, + 0x8abf, 0x1ec6, + 0x8ac0, 0x4a9b, + 0x8ac2, 0x2300, + 0x8ac3, 0x4a9d, + 0x8ac4, 0x22b4, + 0x8ac5, 0x4a9e, + 0x8ac7, 0x2169, + 0x8ac8, 0x4aa0, + 0x8ac9, 0x22fd, + 0x8aca, 0x4aa1, + 0x8acb, 0x20ea, + 0x8acc, 0x4aa2, + 0x8acd, 0x22f4, + 0x8ace, 0x4aa3, + 0x8acf, 0x22fb, + 0x8ad0, 0x4aa4, + 0x8ad1, 0x22fc, + 0x8ad2, 0x2027, + 0x8ad3, 0x4aa5, + 0x8ad6, 0x2060, + 0x8ad7, 0x22ff, + 0x8ad8, 0x4aa8, + 0x8adb, 0x22fe, + 0x8adc, 0x1ec7, + 0x8add, 0x4aab, + 0x8ade, 0x230c, + 0x8adf, 0x4aac, + 0x8ae2, 0x22f5, + 0x8ae3, 0x4aaf, + 0x8ae4, 0x2306, + 0x8ae5, 0x4ab0, + 0x8ae6, 0x230a, + 0x8ae7, 0x21d3, + 0x8ae8, 0x4ab1, + 0x8aeb, 0x2303, + 0x8aec, 0x4ab4, + 0x8aed, 0x2307, + 0x8aee, 0x230b, + 0x8aef, 0x4ab5, + 0x8af1, 0x1f5f, + 0x8af2, 0x4ab7, + 0x8af3, 0x2309, + 0x8af4, 0x4ab8, + 0x8af6, 0x2302, + 0x8af7, 0x1f04, + 0x8af8, 0x229d, + 0x8af9, 0x4aba, + 0x8afa, 0x21fb, + 0x8afb, 0x4abb, + 0x8afc, 0x2308, + 0x8afd, 0x4abc, + 0x8afe, 0x20ac, + 0x8aff, 0x4abd, + 0x8b00, 0x208e, + 0x8b01, 0x2305, + 0x8b02, 0x2197, + 0x8b03, 0x4abe, + 0x8b04, 0x2171, + 0x8b05, 0x2298, + 0x8b06, 0x4abf, + 0x8b07, 0x173c, + 0x8b08, 0x4ac0, + 0x8b0a, 0x1f57, + 0x8b0b, 0x4ac2, + 0x8b0e, 0x2082, + 0x8b0f, 0x4ac5, + 0x8b10, 0x2311, + 0x8b11, 0x4ac6, + 0x8b14, 0x2304, + 0x8b15, 0x4ac9, + 0x8b16, 0x230f, + 0x8b17, 0x1e35, + 0x8b18, 0x4aca, + 0x8b19, 0x20d1, + 0x8b1a, 0x2310, + 0x8b1b, 0x1fa3, + 0x8b1c, 0x4acb, + 0x8b1d, 0x21d6, + 0x8b1e, 0x4acc, + 0x8b21, 0x2206, + 0x8b22, 0x4acf, + 0x8b26, 0x1d5f, + 0x8b27, 0x4ad3, + 0x8b28, 0x230d, + 0x8b29, 0x4ad4, + 0x8b2b, 0x2312, + 0x8b2c, 0x208d, + 0x8b2d, 0x2313, + 0x8b2e, 0x4ad6, + 0x8b33, 0x22e3, + 0x8b34, 0x4adb, + 0x8b39, 0x1fba, + 0x8b3a, 0x4ae0, + 0x8b3e, 0x2078, + 0x8b3f, 0x4ae4, + 0x8b49, 0x2288, + 0x8b4a, 0x4aee, + 0x8b4e, 0x2316, + 0x8b4f, 0x1f6b, + 0x8b50, 0x4af2, + 0x8b56, 0x2314, + 0x8b57, 0x4af8, + 0x8b58, 0x2130, + 0x8b59, 0x2315, + 0x8b5a, 0x2168, + 0x8b5b, 0x4af9, + 0x8b5c, 0x20c4, + 0x8b5d, 0x4afa, + 0x8b66, 0x08de, + 0x8b67, 0x4b03, + 0x8b6b, 0x2318, + 0x8b6c, 0x0bc8, + 0x8b6d, 0x4b07, + 0x8b6f, 0x2219, + 0x8b70, 0x2217, + 0x8b71, 0x4b09, + 0x8b74, 0x20d5, + 0x8b75, 0x4b0c, + 0x8b77, 0x1f4a, + 0x8b78, 0x4b0e, + 0x8b7d, 0x2240, + 0x8b7e, 0x4b13, + 0x8b80, 0x1ed3, + 0x8b81, 0x4b15, + 0x8b8a, 0x1e49, + 0x8b8b, 0x4b1e, + 0x8b8e, 0x261b, + 0x8b8f, 0x4b21, + 0x8b92, 0x1e6d, + 0x8b93, 0x20f8, + 0x8b94, 0x4b24, + 0x8b95, 0x1ffb, + 0x8b96, 0x2319, + 0x8b97, 0x4b25, + 0x8b9c, 0x230e, + 0x8b9d, 0x4b2a, + 0x8b9e, 0x2317, + 0x8b9f, 0x4b2b, + 0x8ba0, 0x1317, + 0x8ba1, 0x0839, + 0x8ba2, 0x05e8, + 0x8ba3, 0x06b7, + 0x8ba4, 0x0caa, + 0x8ba5, 0x0818, + 0x8ba6, 0x1318, + 0x8ba8, 0x0e29, + 0x8ba9, 0x0c9e, + 0x8baa, 0x131a, + 0x8bab, 0x0c1c, + 0x8bac, 0x4b2c, + 0x8bad, 0x0fde, + 0x8bae, 0x1070, + 0x8baf, 0x0fdf, + 0x8bb0, 0x083a, + 0x8bb1, 0x4b2d, + 0x8bb2, 0x0883, + 0x8bb3, 0x07f9, + 0x8bb4, 0x131b, + 0x8bb6, 0x0ff1, + 0x8bb7, 0x131d, + 0x8bb8, 0x0fb8, + 0x8bb9, 0x062e, + 0x8bba, 0x0a82, + 0x8bbb, 0x4b2e, + 0x8bbc, 0x0dc4, + 0x8bbd, 0x068a, + 0x8bbe, 0x0d21, + 0x8bbf, 0x0660, + 0x8bc0, 0x0926, + 0x8bc1, 0x11a3, + 0x8bc2, 0x131e, + 0x8bc4, 0x0bdf, + 0x8bc5, 0x1244, + 0x8bc6, 0x0d4d, + 0x8bc7, 0x4b2f, + 0x8bc8, 0x114a, + 0x8bc9, 0x0dd4, + 0x8bca, 0x1190, + 0x8bcb, 0x1320, + 0x8bcc, 0x11de, + 0x8bcd, 0x054d, + 0x8bce, 0x1322, + 0x8bcf, 0x1321, + 0x8bd0, 0x4b30, + 0x8bd1, 0x1072, + 0x8bd2, 0x1323, + 0x8bd5, 0x0d6b, + 0x8bd6, 0x1326, + 0x8bd7, 0x0d42, + 0x8bd8, 0x1327, + 0x8bda, 0x04f4, + 0x8bdb, 0x11ee, + 0x8bdc, 0x1329, + 0x8bdd, 0x07c5, + 0x8bde, 0x058f, + 0x8bdf, 0x132a, + 0x8be1, 0x0747, + 0x8be2, 0x0fd8, + 0x8be3, 0x106f, + 0x8be4, 0x132c, + 0x8be5, 0x06be, + 0x8be6, 0x0f57, + 0x8be7, 0x04b6, + 0x8be8, 0x132d, + 0x8bea, 0x4b31, + 0x8beb, 0x08bc, + 0x8bec, 0x0eeb, + 0x8bed, 0x10d4, + 0x8bee, 0x132f, + 0x8bef, 0x0f02, + 0x8bf0, 0x1330, + 0x8bf1, 0x10ba, + 0x8bf2, 0x07fa, + 0x8bf3, 0x1331, + 0x8bf4, 0x0daa, + 0x8bf5, 0x0dc5, + 0x8bf6, 0x1332, + 0x8bf7, 0x0c68, + 0x8bf8, 0x11ed, + 0x8bf9, 0x1333, + 0x8bfa, 0x0b76, + 0x8bfb, 0x0600, + 0x8bfc, 0x1334, + 0x8bfd, 0x0669, + 0x8bfe, 0x095b, + 0x8bff, 0x1335, + 0x8c00, 0x1336, + 0x8c01, 0x0da2, + 0x8c02, 0x1337, + 0x8c03, 0x05d8, + 0x8c04, 0x1338, + 0x8c05, 0x0a0b, + 0x8c06, 0x1218, + 0x8c07, 0x1339, + 0x8c08, 0x0e0b, + 0x8c09, 0x4b32, + 0x8c0a, 0x1071, + 0x8c0b, 0x0b14, + 0x8c0c, 0x133a, + 0x8c0d, 0x05de, + 0x8c0e, 0x07e6, + 0x8c0f, 0x133b, + 0x8c10, 0x0f7e, + 0x8c11, 0x133c, + 0x8c13, 0x0ecc, + 0x8c14, 0x133e, + 0x8c17, 0x04be, + 0x8c18, 0x1343, + 0x8c19, 0x1341, + 0x8c1a, 0x1011, + 0x8c1b, 0x1342, + 0x8c1c, 0x0ada, + 0x8c1d, 0x1344, + 0x8c1e, 0x4b33, + 0x8c1f, 0x1345, + 0x8c22, 0x0f86, + 0x8c23, 0x102c, + 0x8c24, 0x0404, + 0x8c25, 0x1348, + 0x8c26, 0x0c28, + 0x8c27, 0x1349, + 0x8c28, 0x08c8, + 0x8c29, 0x0aa6, + 0x8c2a, 0x134a, + 0x8c2c, 0x0b02, + 0x8c2d, 0x0e0a, + 0x8c2e, 0x134c, + 0x8c30, 0x09a9, + 0x8c31, 0x0bf6, + 0x8c32, 0x134e, + 0x8c34, 0x0c31, + 0x8c35, 0x1350, + 0x8c37, 0x0721, + 0x8c38, 0x4b34, + 0x8c41, 0x0802, + 0x8c42, 0x4b3d, + 0x8c46, 0x05f8, + 0x8c47, 0x1cf6, + 0x8c48, 0x20c8, + 0x8c49, 0x1cf7, + 0x8c4a, 0x4b41, + 0x8c4c, 0x0e94, + 0x8c4d, 0x4b43, + 0x8c50, 0x1efd, + 0x8c51, 0x4b46, + 0x8c55, 0x1d15, + 0x8c56, 0x4b4a, + 0x8c5a, 0x1990, + 0x8c5b, 0x4b4e, + 0x8c61, 0x0f60, + 0x8c62, 0x07d4, + 0x8c63, 0x4b54, + 0x8c6a, 0x0777, + 0x8c6b, 0x10e8, + 0x8c6c, 0x4b5b, + 0x8c73, 0x15dd, + 0x8c74, 0x4b62, + 0x8c78, 0x1d50, + 0x8c79, 0x0413, + 0x8c7a, 0x04b9, + 0x8c7b, 0x4b66, + 0x8c82, 0x1d51, + 0x8c83, 0x4b6d, + 0x8c85, 0x1d53, + 0x8c86, 0x4b6f, + 0x8c89, 0x0788, + 0x8c8a, 0x1d52, + 0x8c8b, 0x4b72, + 0x8c8c, 0x0ab7, + 0x8c8d, 0x4b73, + 0x8c94, 0x1d55, + 0x8c95, 0x4b7a, + 0x8c98, 0x1d54, + 0x8c99, 0x4b7d, + 0x8c9d, 0x1e3b, + 0x8c9e, 0x227f, + 0x8c9f, 0x4b81, + 0x8ca0, 0x1f0c, + 0x8ca1, 0x1e59, + 0x8ca2, 0x1f24, + 0x8ca3, 0x4b82, + 0x8ca7, 0x20ba, + 0x8ca8, 0x1f65, + 0x8ca9, 0x1ef0, + 0x8caa, 0x2164, + 0x8cab, 0x1f30, + 0x8cac, 0x2261, + 0x8cad, 0x4b86, + 0x8caf, 0x22a2, + 0x8cb0, 0x24ab, + 0x8cb1, 0x4b88, + 0x8cb2, 0x24af, + 0x8cb3, 0x1ee8, + 0x8cb4, 0x1f39, + 0x8cb5, 0x4b89, + 0x8cb6, 0x1e48, + 0x8cb7, 0x2070, + 0x8cb8, 0x1ea8, + 0x8cb9, 0x4b8a, + 0x8cba, 0x24ac, + 0x8cbb, 0x1ef7, + 0x8cbc, 0x2176, + 0x8cbd, 0x24ad, + 0x8cbe, 0x4b8b, + 0x8cbf, 0x207b, + 0x8cc0, 0x1f45, + 0x8cc1, 0x24aa, + 0x8cc2, 0x204b, + 0x8cc3, 0x202f, + 0x8cc4, 0x1f5a, + 0x8cc5, 0x24b0, + 0x8cc6, 0x4b8c, + 0x8cc7, 0x22b7, + 0x8cc8, 0x1f7f, + 0x8cc9, 0x4b8d, + 0x8cca, 0x2265, + 0x8ccb, 0x4b8e, + 0x8cd1, 0x24b2, + 0x8cd2, 0x211b, + 0x8cd3, 0x1e51, + 0x8cd4, 0x4b94, + 0x8cd5, 0x24b4, + 0x8cd6, 0x4b95, + 0x8cda, 0x24b3, + 0x8cdb, 0x4b99, + 0x8cdc, 0x1e9f, + 0x8cdd, 0x4b9a, + 0x8cde, 0x2118, + 0x8cdf, 0x4b9b, + 0x8ce0, 0x20b4, + 0x8ce1, 0x23af, + 0x8ce2, 0x21bb, + 0x8ce3, 0x2072, + 0x8ce4, 0x1f95, + 0x8ce5, 0x4b9c, + 0x8ce6, 0x1f0a, + 0x8ce7, 0x24b6, + 0x8ce8, 0x4b9d, + 0x8cea, 0x2291, + 0x8ceb, 0x24b5, + 0x8cec, 0x2278, + 0x8ced, 0x1ed4, + 0x8cee, 0x4b9f, + 0x8cf4, 0x1ff3, + 0x8cf5, 0x4ba5, + 0x8cfa, 0x22a9, + 0x8cfb, 0x24b7, + 0x8cfc, 0x1f28, + 0x8cfd, 0x2109, + 0x8cfe, 0x22c7, + 0x8cff, 0x4baa, + 0x8d00, 0x4bab, + 0x8d04, 0x24ae, + 0x8d05, 0x22b1, + 0x8d06, 0x4baf, + 0x8d08, 0x2266, + 0x8d09, 0x4bb1, + 0x8d0a, 0x225b, + 0x8d0b, 0x22c4, + 0x8d0c, 0x4bb2, + 0x8d0d, 0x2115, + 0x8d0e, 0x4bb3, + 0x8d0f, 0x222a, + 0x8d10, 0x24b1, + 0x8d11, 0x4bb4, + 0x8d16, 0x213d, + 0x8d17, 0x4bb9, + 0x8d1b, 0x1f15, + 0x8d1c, 0x225c, + 0x8d1d, 0x041d, + 0x8d1e, 0x118b, + 0x8d1f, 0x06b5, + 0x8d20, 0x4bbd, + 0x8d21, 0x070a, + 0x8d22, 0x048d, + 0x8d23, 0x1133, + 0x8d24, 0x0f3a, + 0x8d25, 0x03e7, + 0x8d26, 0x116c, + 0x8d27, 0x080a, + 0x8d28, 0x11c9, + 0x8d29, 0x0654, + 0x8d2a, 0x0e03, + 0x8d2b, 0x0bd5, + 0x8d2c, 0x044a, + 0x8d2d, 0x0713, + 0x8d2e, 0x11fb, + 0x8d2f, 0x073a, + 0x8d30, 0x063e, + 0x8d31, 0x086d, + 0x8d32, 0x192c, + 0x8d34, 0x0e4c, + 0x8d35, 0x074c, + 0x8d36, 0x192e, + 0x8d37, 0x057e, + 0x8d38, 0x0ab8, + 0x8d39, 0x066e, + 0x8d3a, 0x078f, + 0x8d3b, 0x192f, + 0x8d3c, 0x1137, + 0x8d3d, 0x1930, + 0x8d3e, 0x0849, + 0x8d3f, 0x07f4, + 0x8d40, 0x1931, + 0x8d41, 0x0a27, + 0x8d42, 0x0a5f, + 0x8d43, 0x1122, + 0x8d44, 0x1227, + 0x8d45, 0x1932, + 0x8d47, 0x1936, + 0x8d48, 0x1934, + 0x8d4a, 0x0d17, + 0x8d4b, 0x06ae, + 0x8d4c, 0x0603, + 0x8d4d, 0x1937, + 0x8d4e, 0x0d81, + 0x8d4f, 0x0d06, + 0x8d50, 0x0550, + 0x8d51, 0x4bbe, + 0x8d53, 0x163b, + 0x8d54, 0x0ba3, + 0x8d55, 0x1938, + 0x8d56, 0x09a0, + 0x8d57, 0x4bc0, + 0x8d58, 0x1215, + 0x8d59, 0x1939, + 0x8d5a, 0x1209, + 0x8d5b, 0x0cd7, + 0x8d5c, 0x1289, + 0x8d5d, 0x1283, + 0x8d5e, 0x1121, + 0x8d5f, 0x4bc1, + 0x8d60, 0x113c, + 0x8d61, 0x0cfd, + 0x8d62, 0x1093, + 0x8d63, 0x06ce, + 0x8d64, 0x0505, + 0x8d65, 0x4bc2, + 0x8d66, 0x0d1b, + 0x8d67, 0x1cf4, + 0x8d68, 0x4bc3, + 0x8d6b, 0x078c, + 0x8d6c, 0x4bc6, + 0x8d6d, 0x1cf5, + 0x8d6e, 0x4bc7, + 0x8d70, 0x123c, + 0x8d71, 0x4bc9, + 0x8d73, 0x1cef, + 0x8d74, 0x06ab, + 0x8d75, 0x1175, + 0x8d76, 0x06ca, + 0x8d77, 0x0c0f, + 0x8d78, 0x4bcb, + 0x8d81, 0x04e8, + 0x8d82, 0x4bd4, + 0x8d84, 0x1cf0, + 0x8d85, 0x04d1, + 0x8d86, 0x4bd6, + 0x8d8a, 0x1100, + 0x8d8b, 0x0c74, + 0x8d8c, 0x4bda, + 0x8d91, 0x1cf2, + 0x8d92, 0x4bdf, + 0x8d94, 0x1cf1, + 0x8d95, 0x1f14, + 0x8d96, 0x4be1, + 0x8d99, 0x227a, + 0x8d9a, 0x4be4, + 0x8d9f, 0x0e1e, + 0x8da0, 0x4be9, + 0x8da3, 0x0c7f, + 0x8da4, 0x4bec, + 0x8da8, 0x20ee, + 0x8da9, 0x4bf0, + 0x8db1, 0x1cf3, + 0x8db2, 0x25f8, + 0x8db3, 0x1240, + 0x8db4, 0x0b80, + 0x8db5, 0x1d1c, + 0x8db6, 0x4bf8, + 0x8db8, 0x1d17, + 0x8db9, 0x4bfa, + 0x8dba, 0x1d1f, + 0x8dbb, 0x4bfb, + 0x8dbc, 0x1d1e, + 0x8dbd, 0x4bfc, + 0x8dbe, 0x11b9, + 0x8dbf, 0x1d1d, + 0x8dc0, 0x4bfd, + 0x8dc3, 0x1101, + 0x8dc4, 0x1d20, + 0x8dc5, 0x4c00, + 0x8dc6, 0x1d28, + 0x8dc7, 0x4c01, + 0x8dcb, 0x03da, + 0x8dcc, 0x05d9, + 0x8dcd, 0x4c05, + 0x8dce, 0x1d25, + 0x8dd0, 0x4c06, + 0x8dd1, 0x0b9d, + 0x8dd2, 0x4c07, + 0x8dd6, 0x1d21, + 0x8dd8, 0x4c0b, + 0x8dda, 0x1d23, + 0x8ddb, 0x1d27, + 0x8ddc, 0x4c0d, + 0x8ddd, 0x090f, + 0x8dde, 0x1d24, + 0x8ddf, 0x06f5, + 0x8de0, 0x4c0e, + 0x8de3, 0x1d2c, + 0x8de4, 0x1d2f, + 0x8de5, 0x4c11, + 0x8de8, 0x0974, + 0x8de9, 0x4c14, + 0x8dea, 0x074b, + 0x8deb, 0x1d18, + 0x8dec, 0x1d29, + 0x8ded, 0x4c15, + 0x8def, 0x0a5e, + 0x8df0, 0x4c17, + 0x8df3, 0x0e4b, + 0x8df4, 0x4c1a, + 0x8df5, 0x086c, + 0x8df6, 0x4c1b, + 0x8df7, 0x1d2a, + 0x8df9, 0x1d2d, + 0x8dfa, 0x0624, + 0x8dfb, 0x1d2e, + 0x8dfc, 0x4c1c, + 0x8dfd, 0x1d31, + 0x8dfe, 0x4c1d, + 0x8e00, 0x4c1f, + 0x8e05, 0x1d19, + 0x8e06, 0x4c24, + 0x8e09, 0x1d30, + 0x8e0a, 0x10a0, + 0x8e0b, 0x4c27, + 0x8e0c, 0x0511, + 0x8e0d, 0x4c28, + 0x8e0f, 0x0df7, + 0x8e10, 0x1f94, + 0x8e11, 0x4c2a, + 0x8e14, 0x1d32, + 0x8e15, 0x4c2d, + 0x8e1d, 0x1d33, + 0x8e1e, 0x0910, + 0x8e1f, 0x1d34, + 0x8e20, 0x4c35, + 0x8e22, 0x0e32, + 0x8e23, 0x1d37, + 0x8e24, 0x4c37, + 0x8e29, 0x048f, + 0x8e2a, 0x1236, + 0x8e2b, 0x4c3c, + 0x8e2c, 0x1d35, + 0x8e2d, 0x4c3d, + 0x8e2e, 0x1d36, + 0x8e2f, 0x1d38, + 0x8e30, 0x4c3e, + 0x8e31, 0x1d3e, + 0x8e32, 0x4c3f, + 0x8e34, 0x2230, + 0x8e35, 0x1d3c, + 0x8e36, 0x4c41, + 0x8e39, 0x1d3b, + 0x8e3a, 0x1d39, + 0x8e3b, 0x4c44, + 0x8e3d, 0x1d3d, + 0x8e3e, 0x4c46, + 0x8e40, 0x1d3a, + 0x8e41, 0x1d40, + 0x8e43, 0x4c48, + 0x8e44, 0x0e36, + 0x8e45, 0x4c49, + 0x8e47, 0x173b, + 0x8e48, 0x0599, + 0x8e49, 0x1d3f, + 0x8e4a, 0x1d44, + 0x8e4b, 0x0df6, + 0x8e4c, 0x25fd, + 0x8e4d, 0x4c4b, + 0x8e51, 0x1d42, + 0x8e53, 0x4c4f, + 0x8e55, 0x2600, + 0x8e56, 0x4c51, + 0x8e59, 0x1d1a, + 0x8e5a, 0x4c54, + 0x8e63, 0x2606, + 0x8e64, 0x4c5d, + 0x8e66, 0x042d, + 0x8e67, 0x4c5f, + 0x8e69, 0x1d1b, + 0x8e6a, 0x4c61, + 0x8e6c, 0x05a6, + 0x8e6d, 0x04ab, + 0x8e6e, 0x4c63, + 0x8e6f, 0x1d48, + 0x8e70, 0x1d45, + 0x8e71, 0x4c64, + 0x8e72, 0x0616, + 0x8e73, 0x4c65, + 0x8e74, 0x1d49, + 0x8e75, 0x4c66, + 0x8e76, 0x1d46, + 0x8e77, 0x4c67, + 0x8e7a, 0x25ff, + 0x8e7b, 0x4c6a, + 0x8e7c, 0x1d47, + 0x8e7d, 0x4c6b, + 0x8e7f, 0x055d, + 0x8e80, 0x4c6d, + 0x8e81, 0x112d, + 0x8e82, 0x4c6e, + 0x8e85, 0x1d4a, + 0x8e86, 0x4c71, + 0x8e87, 0x051e, + 0x8e88, 0x4c72, + 0x8e89, 0x25fc, + 0x8e8a, 0x1e8c, + 0x8e8b, 0x2602, + 0x8e8c, 0x4c73, + 0x8e8d, 0x224d, + 0x8e8e, 0x4c74, + 0x8e8f, 0x1d4b, + 0x8e90, 0x1d4d, + 0x8e91, 0x2604, + 0x8e92, 0x25fe, + 0x8e93, 0x2603, + 0x8e94, 0x1d4c, + 0x8e95, 0x4c75, + 0x8e9a, 0x2601, + 0x8e9b, 0x4c7a, + 0x8e9c, 0x1d4e, + 0x8e9d, 0x4c7b, + 0x8e9e, 0x1d4f, + 0x8e9f, 0x4c7c, + 0x8ea1, 0x2605, + 0x8ea2, 0x4c7e, + 0x8ea5, 0x1ea3, + 0x8ea6, 0x2608, + 0x8ea7, 0x4c81, + 0x8eaa, 0x2607, + 0x8eab, 0x0d26, + 0x8eac, 0x0703, + 0x8ead, 0x4c84, + 0x8eaf, 0x0c78, + 0x8eb0, 0x4c86, + 0x8eb2, 0x0622, + 0x8eb3, 0x4c88, + 0x8eba, 0x0e1c, + 0x8ebb, 0x4c8f, + 0x8ec0, 0x20f0, + 0x8ec1, 0x4c94, + 0x8eca, 0x1e7b, + 0x8ecb, 0x2267, + 0x8ecc, 0x1f36, + 0x8ecd, 0x1fd6, + 0x8ece, 0x18f8, + 0x8ecf, 0x4c9d, + 0x8ed2, 0x21e0, + 0x8ed3, 0x4ca0, + 0x8ed4, 0x248c, + 0x8ed5, 0x4ca1, + 0x8edb, 0x248d, + 0x8edc, 0x4ca7, + 0x8edf, 0x2102, + 0x8ee0, 0x4caa, + 0x8ee4, 0x2494, + 0x8ee5, 0x4cae, + 0x8eeb, 0x2493, + 0x8eec, 0x4cb4, + 0x8ef2, 0x248e, + 0x8ef3, 0x4cba, + 0x8ef8, 0x2299, + 0x8ef9, 0x2491, + 0x8efa, 0x2496, + 0x8efb, 0x248f, + 0x8efc, 0x2492, + 0x8efd, 0x4cbf, + 0x8efe, 0x2497, + 0x8eff, 0x4cc0, + 0x8f00, 0x4cc1, + 0x8f03, 0x1fb1, + 0x8f04, 0x4cc4, + 0x8f05, 0x249a, + 0x8f06, 0x4cc5, + 0x8f07, 0x2499, + 0x8f08, 0x4cc6, + 0x8f09, 0x2258, + 0x8f0a, 0x2498, + 0x8f0b, 0x4cc7, + 0x8f12, 0x249b, + 0x8f13, 0x4cce, + 0x8f14, 0x1f09, + 0x8f15, 0x20e6, + 0x8f16, 0x4ccf, + 0x8f1b, 0x2026, + 0x8f1c, 0x249f, + 0x8f1d, 0x1f59, + 0x8f1e, 0x249d, + 0x8f20, 0x4cd4, + 0x8f25, 0x1f3b, + 0x8f26, 0x249c, + 0x8f27, 0x4cd9, + 0x8f29, 0x1e3a, + 0x8f2a, 0x205b, + 0x8f2b, 0x4cdb, + 0x8f2f, 0x1f70, + 0x8f30, 0x4cdf, + 0x8f33, 0x24a0, + 0x8f34, 0x4ce2, + 0x8f38, 0x213b, + 0x8f39, 0x4ce6, + 0x8f3b, 0x1f07, + 0x8f3c, 0x4ce8, + 0x8f3e, 0x2270, + 0x8f3f, 0x2237, + 0x8f40, 0x4cea, + 0x8f42, 0x24d2, + 0x8f43, 0x4cec, + 0x8f44, 0x21b3, + 0x8f45, 0x2245, + 0x8f46, 0x24a1, + 0x8f47, 0x4ced, + 0x8f49, 0x22a8, + 0x8f4a, 0x4cef, + 0x8f4d, 0x227c, + 0x8f4e, 0x1fb0, + 0x8f4f, 0x4cf2, + 0x8f54, 0x24a2, + 0x8f55, 0x4cf7, + 0x8f5f, 0x1f46, + 0x8f60, 0x4d01, + 0x8f61, 0x2380, + 0x8f62, 0x2495, + 0x8f63, 0x4d02, + 0x8f64, 0x2490, + 0x8f65, 0x4d03, + 0x8f66, 0x04da, + 0x8f67, 0x1141, + 0x8f68, 0x0745, + 0x8f69, 0x0fc4, + 0x8f6a, 0x4d04, + 0x8f6b, 0x18e1, + 0x8f6c, 0x1207, + 0x8f6d, 0x18e2, + 0x8f6e, 0x0a7d, + 0x8f6f, 0x0cc8, + 0x8f70, 0x079b, + 0x8f71, 0x18e3, + 0x8f74, 0x11e0, + 0x8f75, 0x18e6, + 0x8f77, 0x18e9, + 0x8f78, 0x18e8, + 0x8f79, 0x18ea, + 0x8f7b, 0x0c5e, + 0x8f7c, 0x18ec, + 0x8f7d, 0x111b, + 0x8f7e, 0x18ed, + 0x8f7f, 0x089f, + 0x8f80, 0x4d05, + 0x8f81, 0x18ee, + 0x8f83, 0x08a0, + 0x8f84, 0x18f0, + 0x8f85, 0x06a3, + 0x8f86, 0x0a07, + 0x8f87, 0x18f1, + 0x8f88, 0x041b, + 0x8f89, 0x07e9, + 0x8f8a, 0x074e, + 0x8f8b, 0x18f2, + 0x8f8c, 0x4d06, + 0x8f8d, 0x18f3, + 0x8f90, 0x0695, + 0x8f91, 0x0820, + 0x8f92, 0x4d07, + 0x8f93, 0x0d7b, + 0x8f94, 0x1574, + 0x8f95, 0x10f2, + 0x8f96, 0x0f2a, + 0x8f97, 0x1158, + 0x8f98, 0x18f6, + 0x8f99, 0x117f, + 0x8f9a, 0x18f7, + 0x8f9b, 0x0f8c, + 0x8f9c, 0x0715, + 0x8f9d, 0x4d08, + 0x8f9e, 0x054a, + 0x8f9f, 0x0442, + 0x8fa0, 0x4d09, + 0x8fa3, 0x099c, + 0x8fa4, 0x4d0c, + 0x8fa6, 0x1e30, + 0x8fa7, 0x4d0e, + 0x8fa8, 0x044f, + 0x8faa, 0x4d0f, + 0x8fab, 0x0451, + 0x8fac, 0x4d10, + 0x8fad, 0x1e9d, + 0x8fae, 0x1e4b, + 0x8faf, 0x1e4a, + 0x8fb0, 0x04e2, + 0x8fb1, 0x0cc3, + 0x8fb2, 0x20aa, + 0x8fb3, 0x4d11, + 0x8fb6, 0x173d, + 0x8fb7, 0x4d14, + 0x8fb9, 0x0448, + 0x8fba, 0x4d16, + 0x8fbd, 0x0a12, + 0x8fbe, 0x0572, + 0x8fbf, 0x4d19, + 0x8fc1, 0x0c25, + 0x8fc2, 0x10bd, + 0x8fc3, 0x4d1b, + 0x8fc4, 0x0c18, + 0x8fc5, 0x0fe1, + 0x8fc6, 0x4d1c, + 0x8fc7, 0x0756, + 0x8fc8, 0x0a9c, + 0x8fc9, 0x4d1d, + 0x8fce, 0x1092, + 0x8fcf, 0x4d22, + 0x8fd0, 0x110e, + 0x8fd1, 0x08cd, + 0x8fd2, 0x4d23, + 0x8fd3, 0x173e, + 0x8fd4, 0x0652, + 0x8fd5, 0x173f, + 0x8fd6, 0x4d24, + 0x8fd8, 0x07ce, + 0x8fd9, 0x1183, + 0x8fda, 0x4d26, + 0x8fdb, 0x08c9, + 0x8fdc, 0x10f9, + 0x8fdd, 0x0eb4, + 0x8fde, 0x09f5, + 0x8fdf, 0x04fe, + 0x8fe0, 0x4d27, + 0x8fe2, 0x0e49, + 0x8fe3, 0x4d29, + 0x8fe4, 0x1742, + 0x8fe5, 0x1740, + 0x8fe6, 0x1744, + 0x8fe7, 0x4d2a, + 0x8fe8, 0x1746, + 0x8fe9, 0x1743, + 0x8fea, 0x05b0, + 0x8feb, 0x0be7, + 0x8fec, 0x4d2b, + 0x8fed, 0x05dd, + 0x8fee, 0x1741, + 0x8fef, 0x4d2c, + 0x8ff0, 0x0d8d, + 0x8ff1, 0x4d2d, + 0x8ff3, 0x1745, + 0x8ff4, 0x267b, + 0x8ff5, 0x4d2f, + 0x8ff7, 0x0ad9, + 0x8ff8, 0x042e, + 0x8ff9, 0x0816, + 0x8ffa, 0x4d31, + 0x8ffd, 0x1214, + 0x8ffe, 0x4d34, + 0x9000, 0x0e7c, + 0x9001, 0x0dc2, + 0x9002, 0x0d61, + 0x9003, 0x0e26, + 0x9004, 0x1748, + 0x9005, 0x1747, + 0x9006, 0x0b49, + 0x9007, 0x4d36, + 0x9009, 0x0fca, + 0x900a, 0x0fe0, + 0x900b, 0x1749, + 0x900c, 0x4d38, + 0x900d, 0x174c, + 0x900e, 0x4d39, + 0x900f, 0x0e69, + 0x9010, 0x11ef, + 0x9011, 0x174b, + 0x9012, 0x05be, + 0x9013, 0x4d3a, + 0x9014, 0x0e6f, + 0x9015, 0x23f2, + 0x9016, 0x174d, + 0x9017, 0x05f9, + 0x9018, 0x4d3b, + 0x9019, 0x227e, + 0x901a, 0x0e59, + 0x901b, 0x073d, + 0x901c, 0x4d3c, + 0x901d, 0x0d5c, + 0x901e, 0x04f6, + 0x901f, 0x0dce, + 0x9020, 0x112f, + 0x9021, 0x174e, + 0x9022, 0x0687, + 0x9023, 0x2019, + 0x9024, 0x4d3d, + 0x9026, 0x174a, + 0x9027, 0x4d3f, + 0x902d, 0x1751, + 0x902e, 0x0581, + 0x902f, 0x1752, + 0x9030, 0x4d45, + 0x9032, 0x1fbb, + 0x9033, 0x4d47, + 0x9035, 0x174f, + 0x9037, 0x4d49, + 0x9038, 0x1064, + 0x9039, 0x4d4a, + 0x903b, 0x0a86, + 0x903c, 0x042f, + 0x903d, 0x4d4c, + 0x903e, 0x10c7, + 0x903f, 0x4d4d, + 0x9041, 0x061c, + 0x9042, 0x0de1, + 0x9043, 0x4d4f, + 0x9044, 0x1753, + 0x9045, 0x4d50, + 0x9047, 0x10db, + 0x9048, 0x4d52, + 0x904b, 0x2253, + 0x904c, 0x4d55, + 0x904d, 0x0452, + 0x904e, 0x1f3e, + 0x904f, 0x0633, + 0x9050, 0x1756, + 0x9051, 0x1754, + 0x9053, 0x05a1, + 0x9054, 0x1ea6, + 0x9055, 0x218e, + 0x9056, 0x4d56, + 0x9057, 0x104c, + 0x9058, 0x1758, + 0x9059, 0x4d57, + 0x905b, 0x175a, + 0x905c, 0x21ec, + 0x905d, 0x4d59, + 0x905e, 0x1ebe, + 0x905f, 0x4d5a, + 0x9060, 0x224a, + 0x9061, 0x4d5b, + 0x9062, 0x1759, + 0x9063, 0x0c2f, + 0x9064, 0x4d5c, + 0x9065, 0x102a, + 0x9066, 0x4d5d, + 0x9068, 0x1757, + 0x9069, 0x2133, + 0x906a, 0x4d5f, + 0x906d, 0x1125, + 0x906e, 0x117b, + 0x906f, 0x4d62, + 0x9072, 0x1e84, + 0x9073, 0x4d65, + 0x9074, 0x175c, + 0x9075, 0x124e, + 0x9076, 0x4d66, + 0x9077, 0x20cf, + 0x9078, 0x21e2, + 0x9079, 0x4d67, + 0x907a, 0x220f, + 0x907b, 0x4d68, + 0x907c, 0x2029, + 0x907d, 0x175d, + 0x907e, 0x4d69, + 0x907f, 0x0445, + 0x9080, 0x1024, + 0x9081, 0x2073, + 0x9082, 0x175e, + 0x9083, 0x1760, + 0x9084, 0x1f55, + 0x9085, 0x4d6a, + 0x9087, 0x23f1, + 0x9088, 0x175f, + 0x9089, 0x4d6c, + 0x908a, 0x1e46, + 0x908b, 0x1761, + 0x908c, 0x4d6d, + 0x908f, 0x2063, + 0x9090, 0x23f3, + 0x9091, 0x105f, + 0x9092, 0x4d70, + 0x9093, 0x05ac, + 0x9094, 0x4d71, + 0x9095, 0x1817, + 0x9096, 0x4d72, + 0x9097, 0x1367, + 0x9098, 0x4d73, + 0x9099, 0x136a, + 0x909a, 0x4d74, + 0x909b, 0x1368, + 0x909c, 0x4d75, + 0x909d, 0x1369, + 0x909e, 0x4d76, + 0x90a1, 0x136c, + 0x90a2, 0x0f9a, + 0x90a3, 0x0b2a, + 0x90a4, 0x4d79, + 0x90a6, 0x03f9, + 0x90a7, 0x4d7b, + 0x90aa, 0x0f7b, + 0x90ab, 0x4d7e, + 0x90ac, 0x136b, + 0x90ad, 0x4d7f, + 0x90ae, 0x10af, + 0x90af, 0x0761, + 0x90b0, 0x1372, + 0x90b1, 0x0c6e, + 0x90b2, 0x4d80, + 0x90b3, 0x136e, + 0x90b4, 0x136d, + 0x90b5, 0x0d14, + 0x90b6, 0x136f, + 0x90b7, 0x4d81, + 0x90b8, 0x1371, + 0x90b9, 0x123b, + 0x90ba, 0x1370, + 0x90bb, 0x0a23, + 0x90bc, 0x4d82, + 0x90be, 0x1375, + 0x90bf, 0x4d84, + 0x90c1, 0x10d9, + 0x90c2, 0x4d86, + 0x90c4, 0x1377, + 0x90c5, 0x1374, + 0x90c6, 0x4d88, + 0x90c7, 0x1378, + 0x90c8, 0x4d89, + 0x90ca, 0x088d, + 0x90cb, 0x4d8b, + 0x90ce, 0x09b4, + 0x90cf, 0x1373, + 0x90d0, 0x1376, + 0x90d1, 0x11a2, + 0x90d2, 0x4d8e, + 0x90d3, 0x1379, + 0x90d4, 0x4d8f, + 0x90d7, 0x137d, + 0x90d8, 0x4d92, + 0x90db, 0x137e, + 0x90dc, 0x137c, + 0x90dd, 0x0779, + 0x90de, 0x4d95, + 0x90df, 0x231e, + 0x90e0, 0x4d96, + 0x90e1, 0x0931, + 0x90e2, 0x137b, + 0x90e3, 0x4d97, + 0x90e6, 0x137a, + 0x90e7, 0x110a, + 0x90e8, 0x0486, + 0x90e9, 0x4d9a, + 0x90eb, 0x137f, + 0x90ec, 0x4d9c, + 0x90ed, 0x0752, + 0x90ee, 0x4d9d, + 0x90ef, 0x1380, + 0x90f0, 0x4d9e, + 0x90f4, 0x04e0, + 0x90f5, 0x2233, + 0x90f6, 0x4da2, + 0x90f8, 0x0587, + 0x90f9, 0x4da4, + 0x90fd, 0x05fb, + 0x90fe, 0x1381, + 0x90ff, 0x4da8, + 0x9100, 0x4da9, + 0x9102, 0x0634, + 0x9103, 0x4dab, + 0x9104, 0x1382, + 0x9105, 0x4dac, + 0x9106, 0x2320, + 0x9107, 0x4dad, + 0x9109, 0x21c7, + 0x910a, 0x4daf, + 0x9112, 0x22bc, + 0x9113, 0x4db7, + 0x9114, 0x231c, + 0x9115, 0x4db8, + 0x9116, 0x2251, + 0x9117, 0x4db9, + 0x9119, 0x0432, + 0x911a, 0x4dbb, + 0x911e, 0x1384, + 0x911f, 0x4dbf, + 0x9122, 0x1383, + 0x9123, 0x1385, + 0x9124, 0x4dc2, + 0x9127, 0x1ebb, + 0x9128, 0x4dc5, + 0x912d, 0x2287, + 0x912e, 0x4dca, + 0x912f, 0x1387, + 0x9130, 0x202d, + 0x9131, 0x1386, + 0x9132, 0x1eab, + 0x9133, 0x4dcb, + 0x9134, 0x231d, + 0x9135, 0x4dcc, + 0x9136, 0x231f, + 0x9137, 0x4dcd, + 0x9139, 0x1388, + 0x913a, 0x231b, + 0x913b, 0x4dcf, + 0x9143, 0x1389, + 0x9144, 0x4dd7, + 0x9146, 0x138a, + 0x9147, 0x4dd9, + 0x9148, 0x2321, + 0x9149, 0x10b4, + 0x914a, 0x1cf8, + 0x914b, 0x0c72, + 0x914c, 0x1220, + 0x914d, 0x0ba5, + 0x914e, 0x1cfa, + 0x9150, 0x1cf9, + 0x9151, 0x4dda, + 0x9152, 0x08f5, + 0x9153, 0x4ddb, + 0x9157, 0x0fba, + 0x9158, 0x4ddf, + 0x915a, 0x0670, + 0x915b, 0x4de1, + 0x915d, 0x1110, + 0x915e, 0x0dfd, + 0x915f, 0x4de3, + 0x9161, 0x1cfe, + 0x9162, 0x1cfd, + 0x9163, 0x075f, + 0x9164, 0x1cfc, + 0x9165, 0x0dcb, + 0x9166, 0x4de5, + 0x9169, 0x1d00, + 0x916a, 0x09bd, + 0x916b, 0x4de8, + 0x916c, 0x050f, + 0x916d, 0x4de9, + 0x916e, 0x0e5b, + 0x916f, 0x1d01, + 0x9170, 0x1cff, + 0x9171, 0x0885, + 0x9172, 0x1d04, + 0x9173, 0x4dea, + 0x9174, 0x1d05, + 0x9175, 0x089e, + 0x9176, 0x0abd, + 0x9177, 0x096e, + 0x9178, 0x0dd6, + 0x9179, 0x1d06, + 0x917a, 0x4deb, + 0x917d, 0x1d02, + 0x917f, 0x0b53, + 0x9180, 0x4dee, + 0x9185, 0x1d08, + 0x9186, 0x4df3, + 0x9187, 0x053f, + 0x9188, 0x4df4, + 0x9189, 0x124a, + 0x918a, 0x4df5, + 0x918b, 0x055a, + 0x918c, 0x1d07, + 0x918d, 0x1d0a, + 0x918e, 0x4df6, + 0x9190, 0x1d09, + 0x9191, 0x1d0b, + 0x9192, 0x0f9c, + 0x9193, 0x4df8, + 0x9196, 0x2255, + 0x9197, 0x4dfb, + 0x919a, 0x0ad6, + 0x919b, 0x0c84, + 0x919c, 0x1e8f, + 0x919d, 0x4dfe, + 0x91a2, 0x1d0c, + 0x91a4, 0x4e03, + 0x91aa, 0x1d0e, + 0x91ab, 0x220c, + 0x91ac, 0x1fa4, + 0x91ad, 0x1d0f, + 0x91b0, 0x4e09, + 0x91b4, 0x1d13, + 0x91b5, 0x1d12, + 0x91b6, 0x4e0d, + 0x91ba, 0x1d14, + 0x91bb, 0x4e11, + 0x91c0, 0x209b, + 0x91c1, 0x21d8, + 0x91c2, 0x4e16, + 0x91c3, 0x25fa, + 0x91c4, 0x4e17, + 0x91c5, 0x25f9, + 0x91c6, 0x4e18, + 0x91c7, 0x0490, + 0x91c8, 0x4e19, + 0x91c9, 0x10b9, + 0x91ca, 0x0d64, + 0x91cb, 0x2134, + 0x91cc, 0x09da, + 0x91cd, 0x11d7, + 0x91ce, 0x1037, + 0x91cf, 0x0a08, + 0x91d0, 0x4e1a, + 0x91d1, 0x08c1, + 0x91d2, 0x24f3, + 0x91d5, 0x24f8, + 0x91d6, 0x4e1b, + 0x91d7, 0x24f7, + 0x91d8, 0x1ec8, + 0x91d9, 0x24f6, + 0x91da, 0x4e1c, + 0x91dc, 0x06a5, + 0x91dd, 0x2280, + 0x91de, 0x4e1e, + 0x91e3, 0x1ec5, + 0x91e4, 0x24fb, + 0x91e5, 0x4e23, + 0x91e7, 0x24fa, + 0x91e8, 0x4e25, + 0x91e9, 0x1eed, + 0x91ea, 0x4e26, + 0x91f5, 0x24fd, + 0x91f6, 0x4e31, + 0x91f7, 0x24f9, + 0x91f8, 0x4e32, + 0x91f9, 0x24fe, + 0x91fa, 0x20cd, + 0x91fb, 0x4e33, + 0x9200, 0x2508, + 0x9201, 0x2504, + 0x9202, 0x4e38, + 0x9204, 0x2506, + 0x9205, 0x4e3a, + 0x9208, 0x24ff, + 0x9209, 0x2090, + 0x920a, 0x4e3d, + 0x920d, 0x1edd, + 0x920e, 0x1f25, + 0x920f, 0x4e40, + 0x9210, 0x2503, + 0x9211, 0x2502, + 0x9212, 0x4e41, + 0x9214, 0x1e7a, + 0x9215, 0x20a6, + 0x9216, 0x4e43, + 0x921e, 0x1fd5, + 0x921f, 0x4e4b, + 0x9223, 0x1f11, + 0x9224, 0x4e4f, + 0x9225, 0x2507, + 0x9226, 0x2500, + 0x9227, 0x2505, + 0x9228, 0x4e50, + 0x922e, 0x2519, + 0x922f, 0x4e56, + 0x9230, 0x2515, + 0x9231, 0x4e57, + 0x9233, 0x250c, + 0x9234, 0x2031, + 0x9235, 0x4e59, + 0x9237, 0x250b, + 0x9238, 0x250f, + 0x9239, 0x251a, + 0x923a, 0x2509, + 0x923b, 0x4e5b, + 0x923d, 0x250e, + 0x923e, 0x2234, + 0x923f, 0x2513, + 0x9240, 0x1f80, + 0x9241, 0x4e5d, + 0x9245, 0x2501, + 0x9246, 0x4e61, + 0x9248, 0x2517, + 0x9249, 0x2516, + 0x924a, 0x4e63, + 0x924d, 0x2518, + 0x924e, 0x4e66, + 0x9251, 0x1e56, + 0x9252, 0x4e69, + 0x9255, 0x250d, + 0x9256, 0x4e6c, + 0x9257, 0x20d3, + 0x9258, 0x4e6d, + 0x925a, 0x207a, + 0x925b, 0x20ce, + 0x925c, 0x4e6f, + 0x925e, 0x2510, + 0x925f, 0x4e71, + 0x9262, 0x1e55, + 0x9263, 0x4e74, + 0x9266, 0x250a, + 0x9267, 0x4e77, + 0x926c, 0x2511, + 0x926e, 0x4e7c, + 0x9274, 0x086b, + 0x9275, 0x4e82, + 0x9278, 0x1faa, + 0x9279, 0x4e85, + 0x927a, 0x251e, + 0x927b, 0x1f1f, + 0x927c, 0x4e86, + 0x927f, 0x252d, + 0x9280, 0x221d, + 0x9281, 0x4e89, + 0x9283, 0x2532, + 0x9284, 0x4e8b, + 0x9285, 0x217b, + 0x9286, 0x4e8c, + 0x928e, 0x1d80, + 0x928f, 0x4e94, + 0x9291, 0x21af, + 0x9292, 0x4e96, + 0x9293, 0x252c, + 0x9294, 0x4e97, + 0x9296, 0x2528, + 0x9297, 0x4e99, + 0x9298, 0x208c, + 0x9299, 0x4e9a, + 0x929a, 0x252f, + 0x929b, 0x4e9b, + 0x929c, 0x21bc, + 0x929d, 0x4e9c, + 0x92a0, 0x251d, + 0x92a1, 0x4e9f, + 0x92a3, 0x2535, + 0x92a4, 0x4ea1, + 0x92a5, 0x220d, + 0x92a6, 0x2526, + 0x92a7, 0x4ea2, + 0x92a8, 0x2534, + 0x92a9, 0x252a, + 0x92aa, 0x251f, + 0x92ab, 0x2531, + 0x92ac, 0x251c, + 0x92ad, 0x4ea3, + 0x92ae, 0x1d81, + 0x92af, 0x4ea4, + 0x92b1, 0x2525, + 0x92b2, 0x4ea6, + 0x92b7, 0x21cd, + 0x92b8, 0x4eab, + 0x92b9, 0x21da, + 0x92ba, 0x4eac, + 0x92bb, 0x2172, + 0x92bc, 0x253e, + 0x92bd, 0x4ead, + 0x92c1, 0x204f, + 0x92c2, 0x4eb1, + 0x92c3, 0x2543, + 0x92c4, 0x4eb2, + 0x92c5, 0x21d7, + 0x92c6, 0x4eb3, + 0x92c7, 0x1e3c, + 0x92c8, 0x1d82, + 0x92c9, 0x4eb4, + 0x92cc, 0x2529, + 0x92cd, 0x4eb7, + 0x92cf, 0x2521, + 0x92d0, 0x4eb9, + 0x92d2, 0x1eff, + 0x92d3, 0x4ebb, + 0x92dd, 0x253f, + 0x92de, 0x4ec5, + 0x92df, 0x2544, + 0x92e0, 0x4ec6, + 0x92e3, 0x2523, + 0x92e4, 0x1e90, + 0x92e5, 0x253a, + 0x92e6, 0x2545, + 0x92e7, 0x4ec9, + 0x92e8, 0x253d, + 0x92e9, 0x4eca, + 0x92ea, 0x20c1, + 0x92eb, 0x4ecb, + 0x92ed, 0x2103, + 0x92ee, 0x2520, + 0x92ef, 0x253c, + 0x92f0, 0x253b, + 0x92f1, 0x2538, + 0x92f2, 0x4ecd, + 0x92f6, 0x2540, + 0x92f7, 0x4ed1, + 0x92f8, 0x1fcd, + 0x92f9, 0x4ed2, + 0x92fc, 0x1f18, + 0x92fd, 0x4ed5, + 0x9300, 0x4ed8, + 0x9301, 0x254b, + 0x9302, 0x4ed9, + 0x9306, 0x2547, + 0x9307, 0x254f, + 0x9309, 0x4edd, + 0x9310, 0x22b0, + 0x9311, 0x4ee4, + 0x9312, 0x2546, + 0x9313, 0x4ee5, + 0x9315, 0x254c, + 0x9316, 0x4ee7, + 0x9318, 0x1e9a, + 0x9319, 0x2552, + 0x931a, 0x2530, + 0x931b, 0x2549, + 0x931c, 0x4ee9, + 0x931f, 0x2551, + 0x9320, 0x1eca, + 0x9321, 0x4eec, + 0x9322, 0x20d2, + 0x9323, 0x4eed, + 0x9326, 0x1fb8, + 0x9327, 0x4ef0, + 0x9328, 0x2079, + 0x9329, 0x4ef1, + 0x932b, 0x21ab, + 0x932c, 0x4ef3, + 0x932e, 0x254d, + 0x932f, 0x1ea5, + 0x9330, 0x4ef5, + 0x9332, 0x204c, + 0x9333, 0x2080, + 0x9334, 0x4ef7, + 0x9336, 0x266d, + 0x9337, 0x4ef9, + 0x9338, 0x2537, + 0x9339, 0x4efa, + 0x933e, 0x1d83, + 0x933f, 0x4eff, + 0x9340, 0x254a, + 0x9341, 0x21b8, + 0x9342, 0x4f00, + 0x9343, 0x254e, + 0x9344, 0x4f01, + 0x9346, 0x24fc, + 0x9347, 0x2554, + 0x9348, 0x4f03, + 0x934b, 0x1f3c, + 0x934c, 0x4f06, + 0x934d, 0x1ed5, + 0x934e, 0x4f07, + 0x9354, 0x2556, + 0x9355, 0x4f0d, + 0x9358, 0x2268, + 0x9359, 0x4f10, + 0x935b, 0x1ed6, + 0x935c, 0x4f12, + 0x9364, 0x2557, + 0x9365, 0x2553, + 0x9366, 0x4f1a, + 0x9369, 0x2548, + 0x936a, 0x1d84, + 0x936b, 0x4f1d, + 0x936c, 0x20dc, + 0x936d, 0x4f1e, + 0x9370, 0x2559, + 0x9371, 0x4f21, + 0x9375, 0x1f97, + 0x9376, 0x2555, + 0x9377, 0x4f25, + 0x937a, 0x227d, + 0x937b, 0x4f28, + 0x937e, 0x257e, + 0x937f, 0x4f2b, + 0x9382, 0x207c, + 0x9383, 0x4f2e, + 0x9384, 0x255a, + 0x9385, 0x4f2f, + 0x9387, 0x255e, + 0x9388, 0x4f31, + 0x938a, 0x1e34, + 0x938b, 0x4f33, + 0x938f, 0x1d86, + 0x9390, 0x4f37, + 0x9396, 0x215e, + 0x9397, 0x4f3d, + 0x9398, 0x2560, + 0x9399, 0x4f3e, + 0x93a2, 0x21a2, + 0x93a3, 0x2354, + 0x93a4, 0x4f47, + 0x93a6, 0x2563, + 0x93a7, 0x2527, + 0x93a8, 0x4f49, + 0x93a9, 0x252e, + 0x93aa, 0x2558, + 0x93ab, 0x4f4a, + 0x93ac, 0x1f1b, + 0x93ad, 0x4f4b, + 0x93ae, 0x2283, + 0x93af, 0x4f4c, + 0x93b0, 0x2564, + 0x93b1, 0x4f4d, + 0x93b3, 0x20a0, + 0x93b4, 0x4f4f, + 0x93b5, 0x2565, + 0x93b6, 0x4f50, + 0x93b8, 0x2561, + 0x93b9, 0x4f52, + 0x93bf, 0x2562, + 0x93c0, 0x4f58, + 0x93c3, 0x256c, + 0x93c4, 0x4f5b, + 0x93c7, 0x256d, + 0x93c8, 0x2020, + 0x93c9, 0x4f5e, + 0x93ca, 0x1d85, + 0x93cb, 0x4f5f, + 0x93cc, 0x255f, + 0x93cd, 0x256a, + 0x93ce, 0x4f60, + 0x93d1, 0x256e, + 0x93d2, 0x4f63, + 0x93d6, 0x1e01, + 0x93d7, 0x2539, + 0x93d8, 0x255c, + 0x93d9, 0x4f67, + 0x93dc, 0x2568, + 0x93de, 0x256b, + 0x93df, 0x1e6f, + 0x93e0, 0x4f6a, + 0x93e1, 0x1fc4, + 0x93e2, 0x2567, + 0x93e3, 0x4f6b, + 0x93e4, 0x255b, + 0x93e5, 0x4f6c, + 0x93e8, 0x261d, + 0x93e9, 0x4f6f, + 0x93f5, 0x252b, + 0x93f6, 0x4f7b, + 0x93f7, 0x2571, + 0x93f8, 0x4f7c, + 0x93f9, 0x2577, + 0x93fa, 0x4f7d, + 0x9400, 0x4f83, + 0x9403, 0x2522, + 0x9404, 0x4f86, + 0x940b, 0x2533, + 0x940c, 0x4f8d, + 0x9410, 0x202a, + 0x9411, 0x4f91, + 0x9412, 0x2536, + 0x9413, 0x2573, + 0x9414, 0x256f, + 0x9415, 0x4f92, + 0x9418, 0x2293, + 0x9419, 0x2578, + 0x941a, 0x4f95, + 0x941d, 0x2570, + 0x941e, 0x4f98, + 0x9420, 0x2575, + 0x9421, 0x4f9a, + 0x9426, 0x2541, + 0x9428, 0x255d, + 0x9429, 0x4f9f, + 0x942e, 0x201a, + 0x942f, 0x4fa4, + 0x9432, 0x257a, + 0x9433, 0x2006, + 0x9434, 0x4fa7, + 0x9435, 0x2177, + 0x9436, 0x4fa8, + 0x9438, 0x251b, + 0x9439, 0x4faa, + 0x943a, 0x2524, + 0x943b, 0x4fab, + 0x943e, 0x1d87, + 0x943f, 0x257b, + 0x9440, 0x4fae, + 0x9444, 0x22a3, + 0x9445, 0x4fb2, + 0x944a, 0x2579, + 0x944b, 0x4fb7, + 0x944c, 0x2566, + 0x944d, 0x4fb8, + 0x9452, 0x1f93, + 0x9453, 0x4fbd, + 0x9454, 0x257c, + 0x9455, 0x4fbe, + 0x9460, 0x2514, + 0x9461, 0x4fc9, + 0x9463, 0x257d, + 0x9464, 0x4fcb, + 0x9465, 0x2572, + 0x9466, 0x4fcc, + 0x946b, 0x1d88, + 0x946c, 0x4fd1, + 0x946d, 0x2574, + 0x946e, 0x4fd2, + 0x9470, 0x224e, + 0x9471, 0x4fd4, + 0x9472, 0x21c6, + 0x9473, 0x4fd5, + 0x9477, 0x209f, + 0x9478, 0x4fd9, + 0x9479, 0x2576, + 0x947a, 0x4fda, + 0x947c, 0x2064, + 0x947d, 0x22bf, + 0x947e, 0x261c, + 0x947f, 0x225e, + 0x9480, 0x4fdc, + 0x9485, 0x1a8e, + 0x9488, 0x118c, + 0x9489, 0x05e3, + 0x948a, 0x1a92, + 0x948b, 0x1a91, + 0x948c, 0x1a93, + 0x948e, 0x0c22, + 0x948f, 0x1a95, + 0x9491, 0x4fe1, + 0x9492, 0x064d, + 0x9493, 0x05d7, + 0x9494, 0x1a97, + 0x9495, 0x1a99, + 0x9496, 0x4fe2, + 0x9497, 0x1a98, + 0x9498, 0x4fe3, + 0x9499, 0x06c1, + 0x949a, 0x1a9a, + 0x949d, 0x061a, + 0x949e, 0x04d3, + 0x949f, 0x11d2, + 0x94a0, 0x0b29, + 0x94a1, 0x041e, + 0x94a2, 0x06d1, + 0x94a3, 0x1a9d, + 0x94a5, 0x1102, + 0x94a6, 0x0c52, + 0x94a7, 0x092a, + 0x94a8, 0x0ee8, + 0x94a9, 0x070c, + 0x94aa, 0x1aa0, + 0x94ab, 0x1a9f, + 0x94ac, 0x1aa2, + 0x94ad, 0x1aa1, + 0x94ae, 0x0b66, + 0x94af, 0x1aa3, + 0x94b1, 0x0c2b, + 0x94b2, 0x1aa5, + 0x94b3, 0x0c2c, + 0x94b4, 0x1aa6, + 0x94b5, 0x046e, + 0x94b6, 0x1aa7, + 0x94bb, 0x1247, + 0x94bc, 0x1aac, + 0x94be, 0x084b, + 0x94bf, 0x1aae, + 0x94c0, 0x10b0, + 0x94c1, 0x0e4d, + 0x94c2, 0x0473, + 0x94c3, 0x0a2e, + 0x94c4, 0x1aaf, + 0x94c5, 0x0c23, + 0x94c6, 0x0ab2, + 0x94c7, 0x4fe4, + 0x94c8, 0x1ab0, + 0x94cf, 0x4fe5, + 0x94d0, 0x1ab7, + 0x94d3, 0x4fe6, + 0x94d5, 0x1aba, + 0x94d8, 0x1abe, + 0x94d9, 0x1abd, + 0x94da, 0x4fe8, + 0x94db, 0x1abf, + 0x94dc, 0x0e5e, + 0x94dd, 0x0a68, + 0x94de, 0x1ac0, + 0x94e1, 0x1142, + 0x94e2, 0x1ac3, + 0x94e3, 0x0f20, + 0x94e4, 0x1ac4, + 0x94e6, 0x4fe9, + 0x94e7, 0x1ac6, + 0x94e9, 0x1ac9, + 0x94ea, 0x1ac8, + 0x94eb, 0x1aca, + 0x94ec, 0x06f0, + 0x94ed, 0x0aff, + 0x94ee, 0x1acb, + 0x94f0, 0x0893, + 0x94f1, 0x1046, + 0x94f2, 0x04c0, + 0x94f3, 0x1acd, + 0x94f6, 0x107f, + 0x94f7, 0x1ad0, + 0x94f8, 0x11fc, + 0x94f9, 0x1ad1, + 0x94fa, 0x0beb, + 0x94fb, 0x4fea, + 0x94fc, 0x1ad2, + 0x94fe, 0x09fd, + 0x94ff, 0x1ad4, + 0x9500, 0x0f67, + 0x9501, 0x0ded, + 0x9502, 0x1ad6, + 0x9503, 0x1ad5, + 0x9504, 0x051f, + 0x9505, 0x0751, + 0x9506, 0x1ad7, + 0x9508, 0x0fad, + 0x9509, 0x1ad9, + 0x950b, 0x0683, + 0x950c, 0x0f8a, + 0x950d, 0x1adb, + 0x9510, 0x0ccc, + 0x9511, 0x0e33, + 0x9512, 0x1ade, + 0x9517, 0x1181, + 0x9518, 0x1ae3, + 0x9519, 0x0570, + 0x951a, 0x0aaf, + 0x951b, 0x1ae4, + 0x951c, 0x4feb, + 0x951d, 0x1ae5, + 0x9520, 0x4fec, + 0x9521, 0x0f0c, + 0x9522, 0x1ae8, + 0x9523, 0x0a87, + 0x9524, 0x053b, + 0x9525, 0x1213, + 0x9526, 0x08c6, + 0x9527, 0x4fed, + 0x9528, 0x0f34, + 0x9529, 0x1aeb, + 0x952a, 0x1ae9, + 0x952c, 0x1aec, + 0x952d, 0x05e6, + 0x952e, 0x086f, + 0x952f, 0x0911, + 0x9530, 0x0ad1, + 0x9531, 0x1aed, + 0x9533, 0x4fee, + 0x9534, 0x1aef, + 0x9535, 0x1af7, + 0x9536, 0x1af0, + 0x9539, 0x0c3f, + 0x953a, 0x1b19, + 0x953b, 0x060c, + 0x953c, 0x1af3, + 0x953d, 0x4fef, + 0x953e, 0x1af4, + 0x9540, 0x0605, + 0x9541, 0x0ac3, + 0x9542, 0x1af6, + 0x9543, 0x4ff0, + 0x9544, 0x1af8, + 0x9547, 0x1193, + 0x9548, 0x4ff1, + 0x9549, 0x1afb, + 0x954a, 0x0b5a, + 0x954b, 0x4ff2, + 0x954c, 0x1afc, + 0x954d, 0x0b5b, + 0x954e, 0x1afd, + 0x9550, 0x06df, + 0x9551, 0x0402, + 0x9552, 0x1aff, + 0x9555, 0x4ff3, + 0x9556, 0x1b02, + 0x955a, 0x4ff4, + 0x955b, 0x1b06, + 0x955c, 0x08e4, + 0x955d, 0x1b09, + 0x955e, 0x1b07, + 0x9560, 0x4ff5, + 0x9561, 0x1b0a, + 0x9563, 0x0a16, + 0x9564, 0x1b0c, + 0x956d, 0x09c3, + 0x956e, 0x4ff6, + 0x956f, 0x1b15, + 0x9570, 0x09f6, + 0x9571, 0x1b16, + 0x9574, 0x4ff7, + 0x9576, 0x0f4f, + 0x9577, 0x1e75, + 0x9578, 0x4ff9, + 0x957f, 0x04c9, + 0x9580, 0x207d, + 0x9581, 0x5000, + 0x9582, 0x23bf, + 0x9583, 0x2113, + 0x9584, 0x5001, + 0x9586, 0x23c0, + 0x9587, 0x5003, + 0x9589, 0x1e45, + 0x958a, 0x5005, + 0x958b, 0x1fd8, + 0x958c, 0x23c4, + 0x958d, 0x5006, + 0x958e, 0x23c2, + 0x958f, 0x2104, + 0x9590, 0x5007, + 0x9591, 0x21bd, + 0x9592, 0x5008, + 0x9593, 0x1f87, + 0x9594, 0x23c3, + 0x9595, 0x5009, + 0x9598, 0x2269, + 0x9599, 0x500c, + 0x95a1, 0x1f43, + 0x95a2, 0x5014, + 0x95a3, 0x1f1e, + 0x95a4, 0x2679, + 0x95a5, 0x1eeb, + 0x95a6, 0x5015, + 0x95a8, 0x1f35, + 0x95a9, 0x208a, + 0x95aa, 0x5017, + 0x95ab, 0x23c7, + 0x95ac, 0x23c9, + 0x95ad, 0x23c6, + 0x95ae, 0x5018, + 0x95b2, 0x224f, + 0x95b3, 0x501c, + 0x95b6, 0x23cb, + 0x95b7, 0x501f, + 0x95b9, 0x21f3, + 0x95ba, 0x5021, + 0x95bb, 0x21f7, + 0x95bc, 0x23cf, + 0x95bd, 0x23ce, + 0x95be, 0x23ca, + 0x95bf, 0x23cd, + 0x95c0, 0x5022, + 0x95c3, 0x23d0, + 0x95c4, 0x5025, + 0x95c6, 0x266c, + 0x95c7, 0x5027, + 0x95c8, 0x23c1, + 0x95c9, 0x5028, + 0x95ca, 0x1fee, + 0x95cb, 0x23d1, + 0x95cc, 0x1ff8, + 0x95cd, 0x5029, + 0x95d0, 0x23d3, + 0x95d1, 0x502c, + 0x95d4, 0x23d2, + 0x95d5, 0x23d4, + 0x95d6, 0x1e98, + 0x95d7, 0x502f, + 0x95dc, 0x1f2c, + 0x95dd, 0x5034, + 0x95de, 0x23d5, + 0x95df, 0x5035, + 0x95e1, 0x1e71, + 0x95e2, 0x2691, + 0x95e3, 0x5037, + 0x95e5, 0x23c5, + 0x95e6, 0x5039, + 0x95e8, 0x0aca, + 0x95e9, 0x1685, + 0x95ea, 0x0cfa, + 0x95eb, 0x1686, + 0x95ec, 0x503b, + 0x95ed, 0x043e, + 0x95ee, 0x0ed9, + 0x95ef, 0x0536, + 0x95f0, 0x0ccd, + 0x95f1, 0x1687, + 0x95f2, 0x0f3d, + 0x95f3, 0x1688, + 0x95f4, 0x0857, + 0x95f5, 0x1689, + 0x95f7, 0x0acb, + 0x95f8, 0x1143, + 0x95f9, 0x0b39, + 0x95fa, 0x0744, + 0x95fb, 0x0ed4, + 0x95fc, 0x168b, + 0x95fd, 0x0afb, + 0x95fe, 0x168c, + 0x95ff, 0x503c, + 0x9600, 0x0644, + 0x9601, 0x06ee, + 0x9602, 0x0789, + 0x9603, 0x168d, + 0x9605, 0x1107, + 0x9606, 0x168f, + 0x9607, 0x503d, + 0x9608, 0x1690, + 0x9609, 0x0ff4, + 0x960a, 0x1691, + 0x960e, 0x0fff, + 0x960f, 0x1695, + 0x9610, 0x04c2, + 0x9611, 0x09a6, + 0x9612, 0x1696, + 0x9613, 0x503e, + 0x9614, 0x0996, + 0x9615, 0x1697, + 0x9618, 0x503f, + 0x9619, 0x169a, + 0x961b, 0x5040, + 0x961c, 0x06b2, + 0x961d, 0x1354, + 0x961e, 0x5041, + 0x961f, 0x0612, + 0x9620, 0x5042, + 0x9621, 0x1356, + 0x9622, 0x1355, + 0x9623, 0x5043, + 0x962a, 0x1358, + 0x962b, 0x504a, + 0x962e, 0x0cc9, + 0x962f, 0x504d, + 0x9631, 0x1357, + 0x9632, 0x065d, + 0x9633, 0x101d, + 0x9634, 0x107c, + 0x9635, 0x1194, + 0x9636, 0x08a8, + 0x9637, 0x504f, + 0x963b, 0x1245, + 0x963c, 0x135a, + 0x963d, 0x1359, + 0x963e, 0x5053, + 0x963f, 0x03ad, + 0x9640, 0x0e84, + 0x9641, 0x5054, + 0x9642, 0x135b, + 0x9643, 0x5055, + 0x9644, 0x06b8, + 0x9645, 0x083d, + 0x9646, 0x0a64, + 0x9647, 0x0a4b, + 0x9648, 0x04e7, + 0x9649, 0x135c, + 0x964a, 0x5056, + 0x964b, 0x0a51, + 0x964c, 0x0b13, + 0x964d, 0x0886, + 0x964e, 0x5057, + 0x9650, 0x0f4b, + 0x9651, 0x5059, + 0x9654, 0x135d, + 0x9655, 0x0cfb, + 0x9656, 0x505c, + 0x9658, 0x231a, + 0x9659, 0x505e, + 0x965b, 0x0446, + 0x965c, 0x5060, + 0x965d, 0x2114, + 0x965e, 0x5061, + 0x965f, 0x135e, + 0x9660, 0x5062, + 0x9661, 0x05f7, + 0x9662, 0x10fd, + 0x9663, 0x2284, + 0x9664, 0x0522, + 0x9665, 0x5063, + 0x9667, 0x135f, + 0x9668, 0x110c, + 0x9669, 0x0f42, + 0x966a, 0x0ba4, + 0x966b, 0x5065, + 0x966c, 0x1360, + 0x966d, 0x5066, + 0x9670, 0x221c, + 0x9671, 0x5069, + 0x9672, 0x1361, + 0x9673, 0x1e7e, + 0x9674, 0x1362, + 0x9675, 0x0a33, + 0x9676, 0x0e28, + 0x9677, 0x0f4a, + 0x9678, 0x204d, + 0x9679, 0x506a, + 0x967d, 0x2201, + 0x967e, 0x506e, + 0x9685, 0x10cc, + 0x9686, 0x0a48, + 0x9687, 0x5075, + 0x9688, 0x1363, + 0x9689, 0x5076, + 0x968a, 0x1ed9, + 0x968b, 0x0dda, + 0x968c, 0x5077, + 0x968d, 0x1364, + 0x968e, 0x1fb2, + 0x968f, 0x0ddb, + 0x9690, 0x1085, + 0x9691, 0x5078, + 0x9694, 0x06ef, + 0x9695, 0x2252, + 0x9696, 0x507b, + 0x9697, 0x1365, + 0x9698, 0x03ba, + 0x9699, 0x0f23, + 0x969a, 0x507c, + 0x969b, 0x1f79, + 0x969c, 0x1170, + 0x969d, 0x507d, + 0x96a7, 0x0de2, + 0x96a8, 0x2157, + 0x96a9, 0x5087, + 0x96aa, 0x21bf, + 0x96ab, 0x5088, + 0x96b0, 0x1366, + 0x96b1, 0x221f, + 0x96b2, 0x508d, + 0x96b3, 0x1684, + 0x96b4, 0x203d, + 0x96b5, 0x508e, + 0x96b6, 0x09ee, + 0x96b7, 0x508f, + 0x96b8, 0x2015, + 0x96b9, 0x1d79, + 0x96ba, 0x5090, + 0x96bb, 0x26a5, + 0x96bc, 0x1d7a, + 0x96be, 0x0b34, + 0x96bf, 0x5091, + 0x96c0, 0x0c93, + 0x96c1, 0x100c, + 0x96c2, 0x5092, + 0x96c4, 0x0fa6, + 0x96c5, 0x0fee, + 0x96c6, 0x0822, + 0x96c7, 0x0726, + 0x96c8, 0x5094, + 0x96c9, 0x1b1c, + 0x96ca, 0x5095, + 0x96cc, 0x0549, + 0x96cd, 0x109f, + 0x96ce, 0x1d7c, + 0x96cf, 0x0520, + 0x96d0, 0x5097, + 0x96d2, 0x1d7d, + 0x96d3, 0x5099, + 0x96d5, 0x05d2, + 0x96d6, 0x2156, + 0x96d7, 0x509b, + 0x96d9, 0x2144, + 0x96da, 0x509d, + 0x96db, 0x1e91, + 0x96dc, 0x2257, + 0x96dd, 0x509e, + 0x96e0, 0x1d7f, + 0x96e1, 0x50a1, + 0x96e2, 0x200a, + 0x96e3, 0x2092, + 0x96e4, 0x50a2, + 0x96e8, 0x10cf, + 0x96e9, 0x1d61, + 0x96ea, 0x0fd2, + 0x96eb, 0x50a6, + 0x96ef, 0x1d63, + 0x96f0, 0x50aa, + 0x96f2, 0x2250, + 0x96f3, 0x1d62, + 0x96f4, 0x50ac, + 0x96f6, 0x0a2c, + 0x96f7, 0x09c2, + 0x96f8, 0x50ae, + 0x96f9, 0x040b, + 0x96fa, 0x50af, + 0x96fb, 0x1ec3, + 0x96fc, 0x50b0, + 0x96fe, 0x0efc, + 0x96ff, 0x50b2, + 0x9700, 0x0fb3, + 0x9701, 0x1d65, + 0x9702, 0x50b3, + 0x9704, 0x0f63, + 0x9705, 0x50b5, + 0x9706, 0x1d64, + 0x9707, 0x1191, + 0x9708, 0x1d66, + 0x9709, 0x0abe, + 0x970a, 0x50b6, + 0x970d, 0x0809, + 0x970e, 0x1d68, + 0x970f, 0x1d67, + 0x9710, 0x50b9, + 0x9713, 0x0b41, + 0x9714, 0x50bc, + 0x9716, 0x0a21, + 0x9717, 0x50be, + 0x971c, 0x0d9f, + 0x971d, 0x50c3, + 0x971e, 0x0f29, + 0x971f, 0x50c4, + 0x9727, 0x21a8, + 0x9728, 0x50cc, + 0x972a, 0x1d69, + 0x972b, 0x50ce, + 0x972d, 0x1d6a, + 0x972e, 0x50d0, + 0x9730, 0x1d6b, + 0x9731, 0x50d2, + 0x9732, 0x0a5d, + 0x9733, 0x50d3, + 0x9738, 0x03df, + 0x9739, 0x0bba, + 0x973a, 0x50d8, + 0x973d, 0x260d, + 0x973e, 0x1d6c, + 0x973f, 0x50db, + 0x9742, 0x260c, + 0x9743, 0x50de, + 0x9744, 0x260e, + 0x9745, 0x50df, + 0x9748, 0x2032, + 0x9749, 0x50e2, + 0x9752, 0x0c5d, + 0x9753, 0x1d60, + 0x9754, 0x50eb, + 0x9756, 0x08e7, + 0x9757, 0x50ed, + 0x9759, 0x08e1, + 0x975a, 0x260b, + 0x975b, 0x05c6, + 0x975c, 0x50ef, + 0x975e, 0x0664, + 0x975f, 0x50f1, + 0x9760, 0x094c, + 0x9761, 0x0ad7, + 0x9762, 0x0aeb, + 0x9763, 0x50f2, + 0x9765, 0x1282, + 0x9766, 0x50f4, + 0x9768, 0x22c3, + 0x9769, 0x06ea, + 0x976a, 0x50f6, + 0x9773, 0x08ca, + 0x9774, 0x0fce, + 0x9775, 0x50ff, + 0x9776, 0x03db, + 0x9777, 0x5100, + 0x977c, 0x1dc8, + 0x977d, 0x5105, + 0x9785, 0x1dc9, + 0x9786, 0x510d, + 0x978b, 0x0f77, + 0x978c, 0x5112, + 0x978d, 0x03bb, + 0x978e, 0x5113, + 0x978f, 0x1f23, + 0x9790, 0x5114, + 0x9791, 0x1dca, + 0x9793, 0x5115, + 0x9794, 0x1dcc, + 0x9795, 0x5116, + 0x9798, 0x0c47, + 0x9799, 0x5119, + 0x97a0, 0x08fe, + 0x97a1, 0x5120, + 0x97a3, 0x1dcf, + 0x97a4, 0x5122, + 0x97a6, 0x2695, + 0x97a7, 0x5124, + 0x97ab, 0x1dce, + 0x97ac, 0x5128, + 0x97ad, 0x0447, + 0x97ae, 0x5129, + 0x97af, 0x1dcd, + 0x97b0, 0x512a, + 0x97b2, 0x1dd0, + 0x97b3, 0x512c, + 0x97b4, 0x1dd1, + 0x97b5, 0x512d, + 0x97bd, 0x265e, + 0x97be, 0x5135, + 0x97c3, 0x265d, + 0x97c4, 0x513a, + 0x97c6, 0x2692, + 0x97c7, 0x513c, + 0x97c9, 0x265f, + 0x97ca, 0x513e, + 0x97cb, 0x218d, + 0x97cc, 0x20fd, + 0x97cd, 0x513f, + 0x97d3, 0x1f40, + 0x97d4, 0x5145, + 0x97d9, 0x2465, + 0x97da, 0x514a, + 0x97dc, 0x2467, + 0x97dd, 0x514c, + 0x97de, 0x2466, + 0x97df, 0x514d, + 0x97e6, 0x0eb3, + 0x97e7, 0x0ca8, + 0x97e8, 0x5154, + 0x97e9, 0x0762, + 0x97ea, 0x184e, + 0x97ed, 0x08f1, + 0x97ee, 0x5155, + 0x97f3, 0x107b, + 0x97f4, 0x515a, + 0x97f5, 0x1112, + 0x97f6, 0x0d11, + 0x97f7, 0x515b, + 0x97ff, 0x21c9, + 0x9800, 0x5163, + 0x9801, 0x2209, + 0x9802, 0x1ec9, + 0x9803, 0x20e9, + 0x9804, 0x5164, + 0x9805, 0x21ca, + 0x9806, 0x2146, + 0x9807, 0x25c5, + 0x9808, 0x21dc, + 0x9809, 0x5165, + 0x980a, 0x245e, + 0x980b, 0x5166, + 0x980c, 0x214f, + 0x980d, 0x5167, + 0x980e, 0x25c6, + 0x9810, 0x2241, + 0x9811, 0x218a, + 0x9812, 0x1e2f, + 0x9813, 0x1edc, + 0x9814, 0x5168, + 0x9817, 0x20bf, + 0x9818, 0x2034, + 0x9819, 0x516b, + 0x981c, 0x25c9, + 0x981d, 0x516e, + 0x9821, 0x25c8, + 0x9822, 0x5172, + 0x9824, 0x220e, + 0x9825, 0x5174, + 0x9826, 0x25cb, + 0x9827, 0x5175, + 0x982d, 0x217d, + 0x982e, 0x517b, + 0x9830, 0x1f7e, + 0x9831, 0x517d, + 0x9837, 0x25cc, + 0x9838, 0x1fc3, + 0x9839, 0x5183, + 0x983b, 0x20b9, + 0x983c, 0x5185, + 0x983d, 0x2181, + 0x983e, 0x5186, + 0x9846, 0x1fda, + 0x9847, 0x518e, + 0x984c, 0x2173, + 0x984d, 0x1ee1, + 0x984e, 0x25cd, + 0x984f, 0x5193, + 0x9853, 0x25ce, + 0x9854, 0x21f6, + 0x9855, 0x5197, + 0x9858, 0x224b, + 0x9859, 0x25d1, + 0x985a, 0x519a, + 0x985b, 0x1ec0, + 0x985c, 0x519b, + 0x985e, 0x2008, + 0x985f, 0x519d, + 0x9862, 0x25d0, + 0x9863, 0x51a0, + 0x9865, 0x25d2, + 0x9866, 0x51a2, + 0x9867, 0x1f2a, + 0x9868, 0x51a3, + 0x986b, 0x1e72, + 0x986c, 0x25d3, + 0x986d, 0x51a6, + 0x986f, 0x21be, + 0x9870, 0x25d4, + 0x9871, 0x2044, + 0x9872, 0x51a8, + 0x9873, 0x25cf, + 0x9874, 0x20f3, + 0x9875, 0x103a, + 0x9876, 0x05e4, + 0x9877, 0x0c67, + 0x9878, 0x1be0, + 0x9879, 0x0f5b, + 0x987a, 0x0da8, + 0x987b, 0x0fb6, + 0x987c, 0x1827, + 0x987d, 0x0e98, + 0x987e, 0x0724, + 0x987f, 0x0618, + 0x9880, 0x1be1, + 0x9881, 0x03ef, + 0x9882, 0x0dc1, + 0x9883, 0x1be2, + 0x9884, 0x10e7, + 0x9885, 0x0a54, + 0x9886, 0x0a35, + 0x9887, 0x0be3, + 0x9888, 0x08e0, + 0x9889, 0x1be3, + 0x988a, 0x0848, + 0x988b, 0x51a9, + 0x988c, 0x1be4, + 0x988e, 0x51aa, + 0x988f, 0x1be6, + 0x9890, 0x104a, + 0x9891, 0x0bd4, + 0x9892, 0x51ab, + 0x9893, 0x0e78, + 0x9894, 0x1be7, + 0x9895, 0x51ac, + 0x9896, 0x1096, + 0x9897, 0x0952, + 0x9898, 0x0e35, + 0x9899, 0x51ad, + 0x989a, 0x1be8, + 0x989c, 0x0ffe, + 0x989d, 0x062d, + 0x989e, 0x1bea, + 0x98a0, 0x05c0, + 0x98a1, 0x1bec, + 0x98a3, 0x51ae, + 0x98a4, 0x04c3, + 0x98a5, 0x1bee, + 0x98a7, 0x0c82, + 0x98a8, 0x1f00, + 0x98a9, 0x51af, + 0x98ae, 0x24cc, + 0x98b0, 0x51b4, + 0x98b1, 0x2698, + 0x98b2, 0x51b5, + 0x98b3, 0x2678, + 0x98b4, 0x51b6, + 0x98b6, 0x24ce, + 0x98b7, 0x51b8, + 0x98bc, 0x24cf, + 0x98bd, 0x51bd, + 0x98c4, 0x20b8, + 0x98c5, 0x51c4, + 0x98c6, 0x24d0, + 0x98c7, 0x51c5, + 0x98c8, 0x24d1, + 0x98c9, 0x51c6, + 0x98ce, 0x0684, + 0x98cf, 0x51cb, + 0x98d1, 0x19b7, + 0x98d4, 0x51cd, + 0x98d5, 0x19ba, + 0x98d6, 0x51ce, + 0x98d8, 0x0bcd, + 0x98d9, 0x19bb, + 0x98db, 0x1ef4, + 0x98dc, 0x51d0, + 0x98de, 0x0666, + 0x98df, 0x0d4a, + 0x98e0, 0x239b, + 0x98e1, 0x51d2, + 0x98e2, 0x267e, + 0x98e3, 0x51d3, + 0x98e7, 0x161a, + 0x98e8, 0x1de7, + 0x98e9, 0x239d, + 0x98ea, 0x239f, + 0x98ec, 0x51d7, + 0x98ed, 0x23a1, + 0x98ee, 0x51d8, + 0x98ef, 0x1ef1, + 0x98f0, 0x51d9, + 0x98f2, 0x221e, + 0x98f3, 0x51db, + 0x98f4, 0x23a2, + 0x98f5, 0x51dc, + 0x98fc, 0x214b, + 0x98fd, 0x1e36, + 0x98fe, 0x2135, + 0x98ff, 0x51e3, + 0x9900, 0x51e4, + 0x9903, 0x1fad, + 0x9904, 0x51e7, + 0x9905, 0x1e53, + 0x9906, 0x51e8, + 0x9909, 0x23a3, + 0x990a, 0x2203, + 0x990b, 0x51eb, + 0x990c, 0x1ee7, + 0x990d, 0x1de8, + 0x990e, 0x51ec, + 0x9910, 0x0494, + 0x9911, 0x23a4, + 0x9912, 0x2097, + 0x9913, 0x1ee4, + 0x9914, 0x51ee, + 0x9918, 0x2238, + 0x9919, 0x51f2, + 0x991b, 0x23a5, + 0x991c, 0x51f4, + 0x991e, 0x1f9a, + 0x991f, 0x51f6, + 0x9921, 0x21c3, + 0x9922, 0x51f8, + 0x9928, 0x1f2e, + 0x9929, 0x51fe, + 0x992e, 0x1de9, + 0x992f, 0x5203, + 0x9933, 0x239c, + 0x9934, 0x5207, + 0x9937, 0x23a6, + 0x9938, 0x520a, + 0x993c, 0x239e, + 0x993d, 0x520e, + 0x993e, 0x2035, + 0x993f, 0x23a7, + 0x9940, 0x520f, + 0x9943, 0x23a8, + 0x9944, 0x5212, + 0x9945, 0x2075, + 0x9946, 0x5213, + 0x9948, 0x23a9, + 0x994b, 0x1feb, + 0x994c, 0x23ac, + 0x994d, 0x5215, + 0x9951, 0x1f6a, + 0x9952, 0x20f9, + 0x9953, 0x5219, + 0x9954, 0x1deb, + 0x9955, 0x1dea, + 0x9956, 0x521a, + 0x9957, 0x2666, + 0x9958, 0x521b, + 0x995c, 0x2667, + 0x995d, 0x521f, + 0x995e, 0x1e6c, + 0x995f, 0x5220, + 0x9962, 0x23ad, + 0x9963, 0x161d, + 0x9964, 0x5223, + 0x9965, 0x0815, + 0x9966, 0x5224, + 0x9967, 0x161e, + 0x996d, 0x0656, + 0x996e, 0x1082, + 0x996f, 0x0875, + 0x9970, 0x0d65, + 0x9971, 0x040e, + 0x9972, 0x0dbc, + 0x9973, 0x5225, + 0x9974, 0x1624, + 0x9975, 0x063b, + 0x9976, 0x0c9f, + 0x9977, 0x1625, + 0x9978, 0x5226, + 0x997a, 0x0899, + 0x997b, 0x5228, + 0x997c, 0x0466, + 0x997d, 0x1626, + 0x997e, 0x5229, + 0x997f, 0x0635, + 0x9980, 0x1627, + 0x9981, 0x0b3c, + 0x9982, 0x522a, + 0x9984, 0x1628, + 0x9985, 0x0f47, + 0x9986, 0x0736, + 0x9987, 0x1629, + 0x9988, 0x098c, + 0x9989, 0x522c, + 0x998a, 0x162a, + 0x998b, 0x04bd, + 0x998c, 0x522d, + 0x998d, 0x162b, + 0x998e, 0x522e, + 0x998f, 0x0a3c, + 0x9990, 0x162c, + 0x9992, 0x0a9f, + 0x9993, 0x162e, + 0x9996, 0x0d6e, + 0x9997, 0x126e, + 0x9998, 0x12f9, + 0x9999, 0x0f50, + 0x999a, 0x522f, + 0x99a5, 0x1b2b, + 0x99a6, 0x523a, + 0x99a8, 0x13de, + 0x99a9, 0x523c, + 0x99ac, 0x206d, + 0x99ad, 0x2242, + 0x99ae, 0x1f02, + 0x99af, 0x523f, + 0x99b1, 0x2183, + 0x99b2, 0x5241, + 0x99b3, 0x1e85, + 0x99b4, 0x21e9, + 0x99b5, 0x5242, + 0x99c1, 0x1e57, + 0x99c2, 0x524e, + 0x99d0, 0x22a5, + 0x99d1, 0x2407, + 0x99d2, 0x1fca, + 0x99d3, 0x525c, + 0x99d4, 0x2402, + 0x99d5, 0x1f82, + 0x99d6, 0x525d, + 0x99d8, 0x2408, + 0x99d9, 0x2404, + 0x99da, 0x525f, + 0x99db, 0x2131, + 0x99dc, 0x5260, + 0x99dd, 0x2184, + 0x99de, 0x5261, + 0x99df, 0x2403, + 0x99e0, 0x5262, + 0x99e1, 0x206e, + 0x99e2, 0x240b, + 0x99e3, 0x5263, + 0x99ed, 0x1f3f, + 0x99ee, 0x526d, + 0x99f1, 0x2067, + 0x99f2, 0x5270, + 0x99ff, 0x1fd7, + 0x9a00, 0x527d, + 0x9a01, 0x1e83, + 0x9a02, 0x527e, + 0x9a05, 0x240f, + 0x9a06, 0x5281, + 0x9a0d, 0x240e, + 0x9a0e, 0x20c7, + 0x9a0f, 0x240d, + 0x9a10, 0x5288, + 0x9a16, 0x2412, + 0x9a17, 0x528e, + 0x9a19, 0x20b7, + 0x9a1a, 0x5290, + 0x9a2b, 0x23f0, + 0x9a2c, 0x52a1, + 0x9a2d, 0x2411, + 0x9a2e, 0x2414, + 0x9a2f, 0x52a2, + 0x9a30, 0x2170, + 0x9a31, 0x52a3, + 0x9a36, 0x2405, + 0x9a37, 0x210c, + 0x9a38, 0x2415, + 0x9a39, 0x52a8, + 0x9a3e, 0x2066, + 0x9a3f, 0x52ad, + 0x9a40, 0x2352, + 0x9a41, 0x2413, + 0x9a42, 0x2410, + 0x9a43, 0x2416, + 0x9a45, 0x20f1, + 0x9a46, 0x52ae, + 0x9a4a, 0x240a, + 0x9a4b, 0x52b2, + 0x9a4d, 0x2409, + 0x9a4e, 0x52b4, + 0x9a4f, 0x2418, + 0x9a50, 0x52b5, + 0x9a55, 0x1fa7, + 0x9a56, 0x52ba, + 0x9a57, 0x21fc, + 0x9a58, 0x52bb, + 0x9a5a, 0x1fc1, + 0x9a5b, 0x2406, + 0x9a5c, 0x52bd, + 0x9a5f, 0x229c, + 0x9a60, 0x52c0, + 0x9a62, 0x204e, + 0x9a63, 0x52c2, + 0x9a64, 0x241a, + 0x9a65, 0x2419, + 0x9a66, 0x52c3, + 0x9a6a, 0x240c, + 0x9a6b, 0x52c7, + 0x9a6c, 0x0a94, + 0x9a6d, 0x10e9, + 0x9a6e, 0x0e85, + 0x9a6f, 0x0fda, + 0x9a70, 0x0500, + 0x9a71, 0x0c7a, + 0x9a72, 0x52c8, + 0x9a73, 0x047c, + 0x9a74, 0x0a66, + 0x9a75, 0x17ba, + 0x9a76, 0x0d52, + 0x9a77, 0x17bb, + 0x9a79, 0x0903, + 0x9a7a, 0x17bd, + 0x9a7b, 0x1201, + 0x9a7c, 0x0e86, + 0x9a7d, 0x17bf, + 0x9a7e, 0x0850, + 0x9a7f, 0x17be, + 0x9a80, 0x17c0, + 0x9a82, 0x0a95, + 0x9a83, 0x52c9, + 0x9a84, 0x088f, + 0x9a85, 0x17c2, + 0x9a86, 0x0a8d, + 0x9a87, 0x075e, + 0x9a88, 0x17c3, + 0x9a89, 0x52ca, + 0x9a8a, 0x17c4, + 0x9a8b, 0x04f7, + 0x9a8c, 0x1012, + 0x9a8d, 0x52cb, + 0x9a8f, 0x0932, + 0x9a90, 0x17c5, + 0x9a91, 0x0c0e, + 0x9a92, 0x17c6, + 0x9a94, 0x52cd, + 0x9a96, 0x17c8, + 0x9a97, 0x0bcc, + 0x9a98, 0x17c9, + 0x9a99, 0x52cf, + 0x9a9a, 0x0ce0, + 0x9a9b, 0x17ca, + 0x9a9e, 0x1735, + 0x9a9f, 0x17cd, + 0x9aa1, 0x0a89, + 0x9aa2, 0x17cf, + 0x9aa4, 0x11e7, + 0x9aa5, 0x17d1, + 0x9aa6, 0x52d0, + 0x9aa7, 0x17d2, + 0x9aa8, 0x0720, + 0x9aa9, 0x52d1, + 0x9aaf, 0x1e29, + 0x9ab0, 0x1dd3, + 0x9ab1, 0x1dd2, + 0x9ab2, 0x52d7, + 0x9ab6, 0x1dd6, + 0x9ab7, 0x1dd4, + 0x9ab8, 0x0758, + 0x9ab9, 0x52db, + 0x9aba, 0x1dd7, + 0x9abb, 0x52dc, + 0x9abc, 0x1dd8, + 0x9abd, 0x52dd, + 0x9ac0, 0x1dda, + 0x9ac1, 0x1dd9, + 0x9ac2, 0x1ddc, + 0x9ac3, 0x52e0, + 0x9ac5, 0x1ddb, + 0x9ac6, 0x52e2, + 0x9acb, 0x1ddd, + 0x9acd, 0x52e7, + 0x9acf, 0x2661, + 0x9ad0, 0x52e9, + 0x9ad1, 0x1ddf, + 0x9ad2, 0x26a4, + 0x9ad3, 0x0ddd, + 0x9ad4, 0x2174, + 0x9ad5, 0x2663, + 0x9ad6, 0x2662, + 0x9ad7, 0x52ea, + 0x9ad8, 0x06da, + 0x9ad9, 0x52eb, + 0x9adf, 0x1dec, + 0x9ae0, 0x52f1, + 0x9ae1, 0x1ded, + 0x9ae2, 0x52f2, + 0x9ae6, 0x1dee, + 0x9ae7, 0x52f6, + 0x9aeb, 0x1df0, + 0x9aec, 0x52fa, + 0x9aed, 0x1df2, + 0x9aee, 0x2675, + 0x9aef, 0x1def, + 0x9af0, 0x52fb, + 0x9af9, 0x1df3, + 0x9afa, 0x5304, + 0x9afb, 0x1df1, + 0x9afc, 0x5305, + 0x9b00, 0x5309, + 0x9b03, 0x1234, + 0x9b04, 0x530c, + 0x9b06, 0x214c, + 0x9b07, 0x530e, + 0x9b08, 0x1df4, + 0x9b09, 0x530f, + 0x9b0d, 0x267a, + 0x9b0e, 0x5313, + 0x9b0f, 0x1df5, + 0x9b10, 0x5314, + 0x9b13, 0x1df6, + 0x9b14, 0x5317, + 0x9b1a, 0x26a0, + 0x9b1b, 0x531d, + 0x9b1f, 0x1df7, + 0x9b20, 0x5321, + 0x9b22, 0x2668, + 0x9b23, 0x1df8, + 0x9b24, 0x5323, + 0x9b25, 0x1ed0, + 0x9b26, 0x5324, + 0x9b27, 0x2096, + 0x9b28, 0x5325, + 0x9b29, 0x23cc, + 0x9b2a, 0x5326, + 0x9b2e, 0x23c8, + 0x9b2f, 0x139b, + 0x9b30, 0x532a, + 0x9b31, 0x223e, + 0x9b32, 0x1260, + 0x9b33, 0x532b, + 0x9b3b, 0x1773, + 0x9b3c, 0x0746, + 0x9b3d, 0x5333, + 0x9b41, 0x098a, + 0x9b42, 0x07ff, + 0x9b43, 0x1de1, + 0x9b44, 0x0be6, + 0x9b45, 0x1de0, + 0x9b46, 0x5337, + 0x9b47, 0x1de2, + 0x9b48, 0x1de4, + 0x9b49, 0x1de3, + 0x9b4a, 0x5338, + 0x9b4d, 0x1de5, + 0x9b4e, 0x2665, + 0x9b4f, 0x0ec9, + 0x9b50, 0x533b, + 0x9b51, 0x1de6, + 0x9b52, 0x533c, + 0x9b54, 0x0b0a, + 0x9b55, 0x533e, + 0x9b58, 0x2664, + 0x9b59, 0x5341, + 0x9b5a, 0x2239, + 0x9b5b, 0x5342, + 0x9b6f, 0x204a, + 0x9b70, 0x5356, + 0x9b74, 0x261f, + 0x9b75, 0x535a, + 0x9b77, 0x261e, + 0x9b78, 0x535c, + 0x9b81, 0x2620, + 0x9b82, 0x5365, + 0x9b83, 0x2621, + 0x9b84, 0x5366, + 0x9b8e, 0x2622, + 0x9b8f, 0x5370, + 0x9b90, 0x2627, + 0x9b91, 0x1e39, + 0x9b92, 0x2625, + 0x9b93, 0x5371, + 0x9b9a, 0x2629, + 0x9b9b, 0x5378, + 0x9b9d, 0x262e, + 0x9b9e, 0x262b, + 0x9b9f, 0x537a, + 0x9baa, 0x262a, + 0x9bab, 0x262d, + 0x9bac, 0x5385, + 0x9bad, 0x2628, + 0x9bae, 0x21b9, + 0x9baf, 0x5386, + 0x9bc0, 0x2636, + 0x9bc1, 0x2630, + 0x9bc2, 0x5397, + 0x9bc7, 0x2638, + 0x9bc8, 0x539c, + 0x9bc9, 0x200d, + 0x9bca, 0x2637, + 0x9bcb, 0x539d, + 0x9bd4, 0x2645, + 0x9bd5, 0x53a6, + 0x9bd6, 0x263a, + 0x9bd7, 0x53a7, + 0x9bdb, 0x2643, + 0x9bdc, 0x53ab, + 0x9bdd, 0x2640, + 0x9bde, 0x53ac, + 0x9be1, 0x263d, + 0x9be2, 0x2641, + 0x9be3, 0x53af, + 0x9be4, 0x263e, + 0x9be5, 0x53b0, + 0x9be7, 0x263f, + 0x9be8, 0x1fc0, + 0x9be9, 0x53b2, + 0x9bea, 0x263b, + 0x9bec, 0x53b3, + 0x9bf0, 0x2642, + 0x9bf1, 0x53b7, + 0x9bf4, 0x2644, + 0x9bf5, 0x53ba, + 0x9bfd, 0x2639, + 0x9bfe, 0x53c2, + 0x9bff, 0x264c, + 0x9c00, 0x53c3, + 0x9c08, 0x2647, + 0x9c09, 0x264b, + 0x9c0a, 0x53cb, + 0x9c0d, 0x2649, + 0x9c0e, 0x53ce, + 0x9c10, 0x2648, + 0x9c11, 0x53d0, + 0x9c12, 0x264a, + 0x9c13, 0x2108, + 0x9c14, 0x53d1, + 0x9c20, 0x264d, + 0x9c21, 0x53dd, + 0x9c23, 0x2634, + 0x9c24, 0x53df, + 0x9c25, 0x2651, + 0x9c26, 0x53e0, + 0x9c28, 0x2650, + 0x9c29, 0x2652, + 0x9c2a, 0x53e2, + 0x9c2d, 0x264f, + 0x9c2e, 0x53e5, + 0x9c31, 0x2632, + 0x9c32, 0x264e, + 0x9c33, 0x2653, + 0x9c34, 0x53e8, + 0x9c35, 0x2657, + 0x9c36, 0x53e9, + 0x9c37, 0x2635, + 0x9c38, 0x53ea, + 0x9c39, 0x2633, + 0x9c3a, 0x53eb, + 0x9c3b, 0x2656, + 0x9c3c, 0x53ec, + 0x9c3e, 0x2654, + 0x9c3f, 0x53ee, + 0x9c45, 0x2658, + 0x9c46, 0x53f4, + 0x9c48, 0x2655, + 0x9c49, 0x1e4d, + 0x9c4a, 0x53f6, + 0x9c52, 0x265b, + 0x9c53, 0x53fe, + 0x9c54, 0x265a, + 0x9c55, 0x53ff, + 0x9c56, 0x2659, + 0x9c57, 0x202e, + 0x9c58, 0x262f, + 0x9c59, 0x5400, + 0x9c5d, 0x2646, + 0x9c5e, 0x5404, + 0x9c5f, 0x2626, + 0x9c60, 0x5405, + 0x9c67, 0x265c, + 0x9c68, 0x540c, + 0x9c6d, 0x262c, + 0x9c6e, 0x5411, + 0x9c78, 0x2623, + 0x9c79, 0x541b, + 0x9c7a, 0x2631, + 0x9c7b, 0x541c, + 0x9c7c, 0x10c8, + 0x9c7d, 0x541d, + 0x9c7f, 0x1d89, + 0x9c80, 0x541f, + 0x9c81, 0x0a5a, + 0x9c82, 0x1d8a, + 0x9c83, 0x5420, + 0x9c85, 0x1d8b, + 0x9c89, 0x5422, + 0x9c8b, 0x1d90, + 0x9c8c, 0x5424, + 0x9c8d, 0x0414, + 0x9c8e, 0x1d91, + 0x9c8f, 0x5425, + 0x9c90, 0x1d92, + 0x9c93, 0x5426, + 0x9c94, 0x1d95, + 0x9c96, 0x5427, + 0x9c9a, 0x1d97, + 0x9c9c, 0x0f37, + 0x9c9d, 0x542b, + 0x9c9e, 0x1d99, + 0x9ca4, 0x09db, + 0x9ca5, 0x1d9f, + 0x9caa, 0x542c, + 0x9cab, 0x1da4, + 0x9cac, 0x542d, + 0x9cad, 0x1da5, + 0x9caf, 0x542e, + 0x9cb0, 0x1da7, + 0x9cb8, 0x08d7, + 0x9cb9, 0x542f, + 0x9cba, 0x1daf, + 0x9cbe, 0x5430, + 0x9cc3, 0x0cd5, + 0x9cc4, 0x1db3, + 0x9cc8, 0x5435, + 0x9cca, 0x1db7, + 0x9cd1, 0x5437, + 0x9cd3, 0x1dbe, + 0x9cd6, 0x0457, + 0x9cd7, 0x1dc1, + 0x9cda, 0x5439, + 0x9cdc, 0x1dc4, + 0x9cde, 0x0a24, + 0x9cdf, 0x1dc6, + 0x9ce0, 0x543b, + 0x9ce2, 0x1dc7, + 0x9ce3, 0x543d, + 0x9ce5, 0x209c, + 0x9ce6, 0x543f, + 0x9ce9, 0x2580, + 0x9cea, 0x5442, + 0x9cec, 0x22dc, + 0x9ced, 0x5444, + 0x9cf3, 0x1f05, + 0x9cf4, 0x208b, + 0x9cf5, 0x544a, + 0x9cf6, 0x2581, + 0x9cf7, 0x544b, + 0x9d00, 0x5454, + 0x9d06, 0x2583, + 0x9d07, 0x2582, + 0x9d08, 0x545a, + 0x9d09, 0x21ee, + 0x9d0a, 0x545b, + 0x9d15, 0x2182, + 0x9d16, 0x5466, + 0x9d1b, 0x2243, + 0x9d1c, 0x546b, + 0x9d1d, 0x2587, + 0x9d1e, 0x546c, + 0x9d1f, 0x2588, + 0x9d20, 0x546d, + 0x9d23, 0x2584, + 0x9d24, 0x5470, + 0x9d26, 0x21fd, + 0x9d27, 0x5472, + 0x9d28, 0x21ef, + 0x9d29, 0x5473, + 0x9d2f, 0x258a, + 0x9d30, 0x258c, + 0x9d31, 0x5479, + 0x9d3b, 0x1f47, + 0x9d3c, 0x5483, + 0x9d3f, 0x1f1d, + 0x9d40, 0x5486, + 0x9d42, 0x258d, + 0x9d43, 0x5488, + 0x9d51, 0x1fd0, + 0x9d52, 0x2592, + 0x9d53, 0x258f, + 0x9d54, 0x5496, + 0x9d5c, 0x2594, + 0x9d5d, 0x1ee0, + 0x9d5e, 0x549e, + 0x9d60, 0x2591, + 0x9d61, 0x2595, + 0x9d62, 0x54a0, + 0x9d6a, 0x2597, + 0x9d6b, 0x54a8, + 0x9d6c, 0x20b6, + 0x9d6d, 0x54a9, + 0x9d6f, 0x2598, + 0x9d70, 0x54ab, + 0x9d72, 0x20f6, + 0x9d73, 0x54ad, + 0x9d87, 0x2585, + 0x9d88, 0x54c1, + 0x9d89, 0x2599, + 0x9d8a, 0x54c2, + 0x9d93, 0x2596, + 0x9d94, 0x54cb, + 0x9d98, 0x259a, + 0x9d99, 0x54cf, + 0x9d9a, 0x259b, + 0x9d9b, 0x54d0, + 0x9da5, 0x259d, + 0x9da6, 0x54da, + 0x9da9, 0x259e, + 0x9daa, 0x54dd, + 0x9daf, 0x234c, + 0x9db0, 0x54e2, + 0x9db4, 0x1f44, + 0x9db5, 0x54e6, + 0x9dbb, 0x2660, + 0x9dbc, 0x25a0, + 0x9dbd, 0x54ec, + 0x9dc0, 0x259c, + 0x9dc1, 0x54ef, + 0x9dc2, 0x259f, + 0x9dc3, 0x54f0, + 0x9dc4, 0x1f6c, + 0x9dc5, 0x54f1, + 0x9dd3, 0x25a2, + 0x9dd4, 0x54ff, + 0x9dd7, 0x20ae, + 0x9dd8, 0x5502, + 0x9dd9, 0x258b, + 0x9dda, 0x25a3, + 0x9ddb, 0x5503, + 0x9de5, 0x2589, + 0x9de6, 0x25a5, + 0x9de7, 0x550d, + 0x9def, 0x25a4, + 0x9df0, 0x5515, + 0x9df2, 0x25a6, + 0x9df3, 0x2593, + 0x9df4, 0x5517, + 0x9df8, 0x25a7, + 0x9df9, 0x2222, + 0x9dfa, 0x25a9, + 0x9dfb, 0x551b, + 0x9e00, 0x5520, + 0x9e0c, 0x25a8, + 0x9e0d, 0x552c, + 0x9e15, 0x2586, + 0x9e16, 0x5534, + 0x9e1a, 0x25a1, + 0x9e1b, 0x25aa, + 0x9e1c, 0x5538, + 0x9e1d, 0x2590, + 0x9e1e, 0x258e, + 0x9e1f, 0x0b54, + 0x9e20, 0x1b35, + 0x9e21, 0x0819, + 0x9e22, 0x1b36, + 0x9e23, 0x0afe, + 0x9e24, 0x5539, + 0x9e25, 0x0b79, + 0x9e26, 0x0fe4, + 0x9e27, 0x553a, + 0x9e28, 0x1b37, + 0x9e2d, 0x0fe5, + 0x9e2e, 0x553b, + 0x9e2f, 0x1015, + 0x9e30, 0x553c, + 0x9e31, 0x1b3d, + 0x9e32, 0x1b3c, + 0x9e33, 0x10ea, + 0x9e34, 0x553d, + 0x9e35, 0x0e83, + 0x9e36, 0x1b3e, + 0x9e37, 0x1b40, + 0x9e38, 0x1b3f, + 0x9e39, 0x1b41, + 0x9e3b, 0x553e, + 0x9e3d, 0x06e6, + 0x9e3e, 0x1b43, + 0x9e3f, 0x079f, + 0x9e40, 0x5540, + 0x9e41, 0x1b44, + 0x9e43, 0x0918, + 0x9e44, 0x1b46, + 0x9e45, 0x062b, + 0x9e46, 0x1b47, + 0x9e4a, 0x0c90, + 0x9e4b, 0x1b4b, + 0x9e4d, 0x5541, + 0x9e4e, 0x1b4d, + 0x9e4f, 0x0bb5, + 0x9e50, 0x5542, + 0x9e51, 0x1b4e, + 0x9e52, 0x5543, + 0x9e55, 0x1b4f, + 0x9e56, 0x5546, + 0x9e57, 0x1b50, + 0x9e58, 0x1dd5, + 0x9e59, 0x5547, + 0x9e5a, 0x1b51, + 0x9e5d, 0x5548, + 0x9e5e, 0x1b54, + 0x9e5f, 0x5549, + 0x9e63, 0x1b55, + 0x9e64, 0x078e, + 0x9e65, 0x554d, + 0x9e66, 0x1b56, + 0x9e6d, 0x1b5e, + 0x9e6e, 0x554e, + 0x9e70, 0x108a, + 0x9e71, 0x1b5d, + 0x9e72, 0x5550, + 0x9e73, 0x1b5f, + 0x9e74, 0x5551, + 0x9e75, 0x2688, + 0x9e76, 0x5552, + 0x9e79, 0x269e, + 0x9e7a, 0x25fb, + 0x9e7b, 0x5555, + 0x9e7c, 0x1f8c, + 0x9e7d, 0x21f4, + 0x9e7e, 0x1d16, + 0x9e7f, 0x0a60, + 0x9e80, 0x5556, + 0x9e82, 0x1dfc, + 0x9e83, 0x5558, + 0x9e87, 0x1dfd, + 0x9e89, 0x555c, + 0x9e8b, 0x1dff, + 0x9e8c, 0x555e, + 0x9e92, 0x1e00, + 0x9e93, 0x0a5b, + 0x9e94, 0x5564, + 0x9e97, 0x200f, + 0x9e98, 0x5567, + 0x9e9d, 0x1e02, + 0x9e9e, 0x556c, + 0x9e9f, 0x1e03, + 0x9ea0, 0x556d, + 0x9ea5, 0x2071, + 0x9ea6, 0x0a9a, + 0x9ea7, 0x5572, + 0x9ea9, 0x25f7, + 0x9eaa, 0x5574, + 0x9eaf, 0x2696, + 0x9eb0, 0x5579, + 0x9eb4, 0x1cee, + 0x9eb5, 0x268f, + 0x9eb6, 0x557d, + 0x9eb8, 0x1ced, + 0x9eb9, 0x557f, + 0x9ebb, 0x0a90, + 0x9ebc, 0x5581, + 0x9ebd, 0x1df9, + 0x9ebf, 0x5582, + 0x9ec4, 0x07db, + 0x9ec5, 0x5587, + 0x9ec9, 0x12f8, + 0x9eca, 0x558b, + 0x9ecc, 0x22da, + 0x9ecd, 0x0d89, + 0x9ece, 0x09d3, + 0x9ecf, 0x1b2a, + 0x9ed0, 0x558d, + 0x9ed1, 0x0791, + 0x9ed2, 0x558e, + 0x9ed4, 0x0c2a, + 0x9ed5, 0x5590, + 0x9ed8, 0x0b0f, + 0x9ed9, 0x5593, + 0x9edb, 0x1e04, + 0x9ede, 0x1ec1, + 0x9edf, 0x1e08, + 0x9ee0, 0x1e07, + 0x9ee1, 0x5595, + 0x9ee2, 0x1e09, + 0x9ee3, 0x5596, + 0x9ee5, 0x1e0c, + 0x9ee6, 0x5598, + 0x9ee7, 0x1e0b, + 0x9ee8, 0x1eb3, + 0x9ee9, 0x1e0a, + 0x9eea, 0x1e0d, + 0x9eeb, 0x5599, + 0x9eef, 0x1e0e, + 0x9ef0, 0x559d, + 0x9ef2, 0x266a, + 0x9ef3, 0x559f, + 0x9ef4, 0x268a, + 0x9ef5, 0x55a0, + 0x9ef7, 0x2669, + 0x9ef8, 0x55a2, + 0x9ef9, 0x1a55, + 0x9efa, 0x55a3, + 0x9efb, 0x1a56, + 0x9efd, 0x2618, + 0x9efe, 0x1d76, + 0x9eff, 0x2619, + 0x9f00, 0x55a4, + 0x9f09, 0x261a, + 0x9f0a, 0x55ad, + 0x9f0b, 0x1d77, + 0x9f0c, 0x55ae, + 0x9f0d, 0x1d78, + 0x9f0e, 0x05e5, + 0x9f0f, 0x55af, + 0x9f10, 0x1274, + 0x9f11, 0x55b0, + 0x9f13, 0x071d, + 0x9f14, 0x55b2, + 0x9f15, 0x2673, + 0x9f16, 0x55b3, + 0x9f17, 0x1271, + 0x9f18, 0x55b4, + 0x9f19, 0x13df, + 0x9f1a, 0x55b5, + 0x9f20, 0x0d8a, + 0x9f21, 0x55bb, + 0x9f22, 0x1e0f, + 0x9f23, 0x55bc, + 0x9f2c, 0x1e10, + 0x9f2d, 0x55c5, + 0x9f2f, 0x1e11, + 0x9f30, 0x55c7, + 0x9f37, 0x1e13, + 0x9f38, 0x55ce, + 0x9f39, 0x1e12, + 0x9f3a, 0x55cf, + 0x9f3b, 0x0430, + 0x9f3c, 0x55d0, + 0x9f3d, 0x1e14, + 0x9f3f, 0x55d1, + 0x9f44, 0x1e16, + 0x9f45, 0x55d6, + 0x9f4a, 0x20c6, + 0x9f4b, 0x226b, + 0x9f4c, 0x55db, + 0x9f4f, 0x24d3, + 0x9f50, 0x0c0a, + 0x9f51, 0x19c2, + 0x9f52, 0x1e86, + 0x9f53, 0x55de, + 0x9f54, 0x260f, + 0x9f55, 0x55df, + 0x9f59, 0x2611, + 0x9f5a, 0x55e3, + 0x9f5c, 0x2613, + 0x9f5d, 0x55e5, + 0x9f5f, 0x2610, + 0x9f60, 0x2612, + 0x9f61, 0x2030, + 0x9f62, 0x55e7, + 0x9f63, 0x2671, + 0x9f64, 0x55e8, + 0x9f66, 0x2614, + 0x9f67, 0x55ea, + 0x9f6a, 0x2616, + 0x9f6b, 0x55ed, + 0x9f6c, 0x2615, + 0x9f6d, 0x55ee, + 0x9f72, 0x20f2, + 0x9f73, 0x55f3, + 0x9f77, 0x2617, + 0x9f78, 0x55f7, + 0x9f7f, 0x0502, + 0x9f80, 0x1d6d, + 0x9f81, 0x55fe, + 0x9f83, 0x1d6e, + 0x9f84, 0x0a2d, + 0x9f85, 0x1d6f, + 0x9f8b, 0x0c7e, + 0x9f8c, 0x1d75, + 0x9f8d, 0x2037, + 0x9f8e, 0x5600, + 0x9f90, 0x20b3, + 0x9f91, 0x5602, + 0x9f94, 0x1f22, + 0x9f95, 0x24ed, + 0x9f96, 0x5605, + 0x9f99, 0x0a43, + 0x9f9a, 0x0701, + 0x9f9b, 0x1a54, + 0x9f9c, 0x1f34, + 0x9f9d, 0x5608, + 0x9f9f, 0x0743, + 0x9fa0, 0x12f3, + 0x9fa1, 0x560a, + 0xe7e7, 0x274b, + 0xe815, 0x561f, + 0xf92c, 0x560f, + 0xfa0d, 0x5610, + 0xfa11, 0x5613, + 0xfa13, 0x5614, + 0xfa18, 0x5616, + 0xfa1f, 0x5617, + 0xfa23, 0x561a, + 0xfa27, 0x561c, + 0xfe30, 0x271d, + 0xfe49, 0x272b, + 0xfe54, 0x2735, + 0xfe59, 0x2739, + 0xfe68, 0x2747, + 0xff01, 0x0106, + 0xff04, 0x00a6, + 0xff05, 0x010a, + 0xff5e, 0x006a, + 0xffe0, 0x00a8, + 0xffe2, 0x271e, + 0xffe3, 0x0163, + 0xffe4, 0x271f, + 0xffe5, 0x0109, + 0x2014, 0x0256, + 0x2026, 0x0257, + 0x2225, 0x1e1c, + 0x3001, 0x023f, + 0x3002, 0x023e, + 0x3008, 0x0248, + 0x3010, 0x0252, + 0x3013, 0x1e1a, + 0x3014, 0x0246, + 0x3016, 0x0250, + 0xff01, 0x0242, + 0xff08, 0x0244, + 0xff0c, 0x023d, + 0xff0e, 0x1e1b, + 0xff1a, 0x0240, + 0xff1d, 0x1e1c, + 0xff1f, 0x0243, + 0xff3b, 0x1e1d, + 0xff3d, 0x1e1e, + 0xff3f, 0x0258, + 0xff5b, 0x0254, + 0xff5d, 0x0255, + 0xff5e, 0x1e18, + 0xffe3, 0x1e1f, + 0xffff, 0x0000 +}; + +static GfxFontEncoding16 gb12UniGBUCS2VEnc16 = { + 1, + { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }, + { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, + gb12UniGBUCS2VMap2, 13485 +}; + +static Gushort gb12AdobeGB12VMap2[178] = { + 0x0000, 0x0000, + 0x0000, 0x0000, + 0x0100, 0x0100, + 0x0200, 0x0200, + 0x0300, 0x0300, + 0x0400, 0x0400, + 0x0500, 0x0500, + 0x0600, 0x0600, + 0x0700, 0x0700, + 0x0800, 0x0800, + 0x0900, 0x0900, + 0x0a00, 0x0a00, + 0x0b00, 0x0b00, + 0x0c00, 0x0c00, + 0x0d00, 0x0d00, + 0x0e00, 0x0e00, + 0x0f00, 0x0f00, + 0x1000, 0x1000, + 0x1100, 0x1100, + 0x1200, 0x1200, + 0x1300, 0x1300, + 0x1400, 0x1400, + 0x1500, 0x1500, + 0x1600, 0x1600, + 0x1700, 0x1700, + 0x1800, 0x1800, + 0x1900, 0x1900, + 0x1a00, 0x1a00, + 0x1b00, 0x1b00, + 0x1c00, 0x1c00, + 0x1d00, 0x1d00, + 0x1e00, 0x1e00, + 0x1f00, 0x1f00, + 0x2000, 0x2000, + 0x2100, 0x2100, + 0x2200, 0x2200, + 0x2300, 0x2300, + 0x2400, 0x2400, + 0x2500, 0x2500, + 0x2600, 0x2600, + 0x2700, 0x2700, + 0x2800, 0x2800, + 0x2900, 0x2900, + 0x2a00, 0x2a00, + 0x2b00, 0x2b00, + 0x2c00, 0x2c00, + 0x2d00, 0x2d00, + 0x2e00, 0x2e00, + 0x2f00, 0x2f00, + 0x3000, 0x3000, + 0x3100, 0x3100, + 0x3200, 0x3200, + 0x3300, 0x3300, + 0x3400, 0x3400, + 0x3500, 0x3500, + 0x3600, 0x3600, + 0x3700, 0x3700, + 0x3800, 0x3800, + 0x3900, 0x3900, + 0x3a00, 0x3a00, + 0x3b00, 0x3b00, + 0x3c00, 0x3c00, + 0x3d00, 0x3d00, + 0x3e00, 0x3e00, + 0x3f00, 0x3f00, + 0x4000, 0x4000, + 0x4100, 0x4100, + 0x4200, 0x4200, + 0x4300, 0x4300, + 0x4400, 0x4400, + 0x4500, 0x4500, + 0x4600, 0x4600, + 0x4700, 0x4700, + 0x4800, 0x4800, + 0x4900, 0x4900, + 0x4a00, 0x4a00, + 0x4b00, 0x4b00, + 0x4c00, 0x4c00, + 0x4d00, 0x4d00, + 0x4e00, 0x4e00, + 0x4f00, 0x4f00, + 0x5000, 0x5000, + 0x5100, 0x5100, + 0x5200, 0x5200, + 0x5300, 0x5300, + 0x5400, 0x5400, + 0x5500, 0x5500, + 0x5600, 0x5600, + 0xffff, 0x0000 +}; + +static GfxFontEncoding16 gb12AdobeGB12VEnc16 = { + 1, + { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, + gb12AdobeGB12VMap2, 89 +}; + +static struct { + char *name; + GfxFontEncoding16 *enc; +} gfxGB12Tab[] = { + { "Adobe-GB1-0", &gb12AdobeGB10Enc16 }, + { "Adobe-GB1-1", &gb12AdobeGB11Enc16 }, + { "Adobe-GB1-2", &gb12AdobeGB12Enc16 }, + { "GB-EUC-H", &gb12GBEUCHEnc16 }, + { "GB-EUC-V", &gb12GBEUCVEnc16 }, + { "GB-H", &gb12GBHEnc16 }, + { "GB-V", &gb12GBVEnc16 }, + { "GBK-EUC-H", &gb12GBKEUCHEnc16 }, + { "GBK-EUC-V", &gb12GBKEUCVEnc16 }, + { "GBT-EUC-H", &gb12GBTEUCHEnc16 }, + { "GBT-EUC-V", &gb12GBTEUCVEnc16 }, + { "GBT-H", &gb12GBTHEnc16 }, + { "GBT-V", &gb12GBTVEnc16 }, + { "GBTpc-EUC-H", &gb12GBTpcEUCHEnc16 }, + { "GBTpc-EUC-V", &gb12GBTpcEUCVEnc16 }, + { "GBpc-EUC-H", &gb12GBpcEUCHEnc16 }, + { "GBpc-EUC-V", &gb12GBpcEUCVEnc16 }, + { "UniGB-UCS2-H", &gb12UniGBUCS2HEnc16 }, + { "UniGB-UCS2-V", &gb12UniGBUCS2VEnc16 }, + { "Identity-H", &gb12AdobeGB12Enc16 }, + { "Identity-V", &gb12AdobeGB12VEnc16 }, + { NULL, NULL } +}; + +#endif diff --git a/pdftops/GString.cxx b/pdftops/GString.cxx new file mode 100644 index 0000000000..7b8f271840 --- /dev/null +++ b/pdftops/GString.cxx @@ -0,0 +1,223 @@ +//======================================================================== +// +// GString.cc +// +// Simple variable-length string type. +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include +#include +#include +#include +#include "gtypes.h" +#include "GString.h" + +static inline int size(int len) { + int delta; + + delta = len < 256 ? 7 : 255; + return ((len + 1) + delta) & ~delta; +} + +inline void GString::resize(int length1) { + char *s1; + + if (!s) { + s = new char[size(length1)]; + } else if (size(length1) != size(length)) { + s1 = new char[size(length1)]; + memcpy(s1, s, length + 1); + delete[] s; + s = s1; + } +} + +GString::GString() { + s = NULL; + resize(length = 0); + s[0] = '\0'; +} + +GString::GString(const char *s1) { + int n = strlen(s1); + + s = NULL; + resize(length = n); + memcpy(s, s1, n + 1); +} + +GString::GString(const char *s1, int length1) { + s = NULL; + resize(length = length1); + memcpy(s, s1, length * sizeof(char)); + s[length] = '\0'; +} + +GString::GString(GString *str) { + s = NULL; + resize(length = str->getLength()); + memcpy(s, str->getCString(), length + 1); +} + +GString::GString(GString *str1, GString *str2) { + int n1 = str1->getLength(); + int n2 = str2->getLength(); + + s = NULL; + resize(length = n1 + n2); + memcpy(s, str1->getCString(), n1); + memcpy(s + n1, str2->getCString(), n2 + 1); +} + +GString *GString::fromInt(int x) { + char buf[24]; // enough space for 64-bit ints plus a little extra + GBool neg; + Guint y; + int i; + + i = 24; + if (x == 0) { + buf[--i] = '0'; + } else { + if ((neg = x < 0)) { + y = (Guint)-x; + } else { + y = (Guint)x; + } + while (i > 0 && y > 0) { + buf[--i] = '0' + y % 10; + y /= 10; + } + if (neg && i > 0) { + buf[--i] = '-'; + } + } + return new GString(buf + i, 24 - i); +} + +GString::~GString() { + delete[] s; +} + +GString *GString::clear() { + s[length = 0] = '\0'; + resize(0); + return this; +} + +GString *GString::append(char c) { + resize(length + 1); + s[length++] = c; + s[length] = '\0'; + return this; +} + +GString *GString::append(GString *str) { + int n = str->getLength(); + + resize(length + n); + memcpy(s + length, str->getCString(), n + 1); + length += n; + return this; +} + +GString *GString::append(const char *str) { + int n = strlen(str); + + resize(length + n); + memcpy(s + length, str, n + 1); + length += n; + return this; +} + +GString *GString::append(const char *str, int length1) { + resize(length + length1); + memcpy(s + length, str, length1); + length += length1; + s[length] = '\0'; + return this; +} + +GString *GString::insert(int i, char c) { + int j; + + resize(length + 1); + for (j = length + 1; j > i; --j) + s[j] = s[j-1]; + s[i] = c; + ++length; + return this; +} + +GString *GString::insert(int i, GString *str) { + int n = str->getLength(); + int j; + + resize(length + n); + for (j = length; j >= i; --j) + s[j+n] = s[j]; + memcpy(s+i, str->getCString(), n); + length += n; + return this; +} + +GString *GString::insert(int i, const char *str) { + int n = strlen(str); + int j; + + resize(length + n); + for (j = length; j >= i; --j) + s[j+n] = s[j]; + memcpy(s+i, str, n); + length += n; + return this; +} + +GString *GString::insert(int i, const char *str, int length1) { + int j; + + resize(length + length1); + for (j = length; j >= i; --j) + s[j+length1] = s[j]; + memcpy(s+i, str, length1); + length += length1; + return this; +} + +GString *GString::del(int i, int n) { + int j; + + if (n > 0) { + for (j = i; j <= length - n; ++j) + s[j] = s[j + n]; + resize(length -= n); + } + return this; +} + +GString *GString::upperCase() { + int i; + + for (i = 0; i < length; ++i) { + if (islower(s[i])) + s[i] = toupper(s[i]); + } + return this; +} + +GString *GString::lowerCase() { + int i; + + for (i = 0; i < length; ++i) { + if (isupper(s[i])) + s[i] = tolower(s[i]); + } + return this; +} diff --git a/pdftops/GString.h b/pdftops/GString.h new file mode 100644 index 0000000000..4c3b95f347 --- /dev/null +++ b/pdftops/GString.h @@ -0,0 +1,95 @@ +//======================================================================== +// +// GString.h +// +// Simple variable-length string type. +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#ifndef GSTRING_H +#define GSTRING_H + +#ifdef __GNUC__ +#pragma interface +#endif + +#include + +class GString { +public: + + // Create an empty string. + GString(); + + // Create a string from a C string. + GString(const char *s1); + + // Create a string from chars at . This string + // can contain null characters. + GString (const char *s1, int length1); + + // Copy a string. + GString(GString *str); + GString *copy() { return new GString(this); } + + // Concatenate two strings. + GString(GString *str1, GString *str2); + + // Convert an integer to a string. + static GString *fromInt(int x); + + // Destructor. + ~GString(); + + // Get length. + int getLength() { return length; } + + // Get C string. + char *getCString() { return s; } + + // Get th character. + char getChar(int i) { return s[i]; } + + // Change th character. + void setChar(int i, char c) { s[i] = c; } + + // Clear string to zero length. + GString *clear(); + + // Append a character or string. + GString *append(char c); + GString *append(GString *str); + GString *append(const char *str); + GString *append(const char *str, int length1); + + // Insert a character or string. + GString *insert(int i, char c); + GString *insert(int i, GString *str); + GString *insert(int i, const char *str); + GString *insert(int i, const char *str, int length1); + + // Delete a character or range of characters. + GString *del(int i, int n = 1); + + // Convert string to all-upper/all-lower case. + GString *upperCase(); + GString *lowerCase(); + + // Compare two strings: -1:< 0:= +1:> + // These functions assume the strings do not contain null characters. + int cmp(GString *str) { return strcmp(s, str->getCString()); } + int cmpN(GString *str, int n) { return strncmp(s, str->getCString(), n); } + int cmp(const char *s1) { return strcmp(s, s1); } + int cmpN(const char *s1, int n) { return strncmp(s, s1, n); } + +private: + + int length; + char *s; + + void resize(int length1); +}; + +#endif diff --git a/pdftops/Gfx.cxx b/pdftops/Gfx.cxx new file mode 100644 index 0000000000..9ec60bbc71 --- /dev/null +++ b/pdftops/Gfx.cxx @@ -0,0 +1,1723 @@ +//======================================================================== +// +// Gfx.cc +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include +#include +#include +#include "gmem.h" +#include "Object.h" +#include "Array.h" +#include "Dict.h" +#include "Stream.h" +#include "Lexer.h" +#include "Parser.h" +#include "GfxFont.h" +#include "GfxState.h" +#include "OutputDev.h" +#include "Params.h" +#include "Error.h" +#include "Gfx.h" + +//------------------------------------------------------------------------ +// Operator table +//------------------------------------------------------------------------ + +Operator Gfx::opTab[] = { + {"\"", 3, {tchkNum, tchkNum, tchkString}, + &Gfx::opMoveSetShowText}, + {"'", 1, {tchkString}, + &Gfx::opMoveShowText}, + {"B", 0, {tchkNone}, + &Gfx::opFillStroke}, + {"B*", 0, {tchkNone}, + &Gfx::opEOFillStroke}, + {"BDC", 2, {tchkName, tchkProps}, + &Gfx::opBeginMarkedContent}, + {"BI", 0, {tchkNone}, + &Gfx::opBeginImage}, + {"BMC", 1, {tchkName}, + &Gfx::opBeginMarkedContent}, + {"BT", 0, {tchkNone}, + &Gfx::opBeginText}, + {"BX", 0, {tchkNone}, + &Gfx::opBeginIgnoreUndef}, + {"CS", 1, {tchkName}, + &Gfx::opSetStrokeColorSpace}, + {"DP", 2, {tchkName, tchkProps}, + &Gfx::opMarkPoint}, + {"Do", 1, {tchkName}, + &Gfx::opXObject}, + {"EI", 0, {tchkNone}, + &Gfx::opEndImage}, + {"EMC", 0, {tchkNone}, + &Gfx::opEndMarkedContent}, + {"ET", 0, {tchkNone}, + &Gfx::opEndText}, + {"EX", 0, {tchkNone}, + &Gfx::opEndIgnoreUndef}, + {"F", 0, {tchkNone}, + &Gfx::opFill}, + {"G", 1, {tchkNum}, + &Gfx::opSetStrokeGray}, + {"ID", 0, {tchkNone}, + &Gfx::opImageData}, + {"J", 1, {tchkInt}, + &Gfx::opSetLineCap}, + {"K", 4, {tchkNum, tchkNum, tchkNum, tchkNum}, + &Gfx::opSetStrokeCMYKColor}, + {"M", 1, {tchkNum}, + &Gfx::opSetMiterLimit}, + {"MP", 1, {tchkName}, + &Gfx::opMarkPoint}, + {"Q", 0, {tchkNone}, + &Gfx::opRestore}, + {"RG", 3, {tchkNum, tchkNum, tchkNum}, + &Gfx::opSetStrokeRGBColor}, + {"S", 0, {tchkNone}, + &Gfx::opStroke}, + {"SC", -4, {tchkNum, tchkNum, tchkNum, tchkNum}, + &Gfx::opSetStrokeColor}, + {"SCN", -5, {tchkSCN, tchkSCN, tchkSCN, tchkSCN, + tchkSCN}, + &Gfx::opSetStrokeColorN}, + {"T*", 0, {tchkNone}, + &Gfx::opTextNextLine}, + {"TD", 2, {tchkNum, tchkNum}, + &Gfx::opTextMoveSet}, + {"TJ", 1, {tchkArray}, + &Gfx::opShowSpaceText}, + {"TL", 1, {tchkNum}, + &Gfx::opSetTextLeading}, + {"Tc", 1, {tchkNum}, + &Gfx::opSetCharSpacing}, + {"Td", 2, {tchkNum, tchkNum}, + &Gfx::opTextMove}, + {"Tf", 2, {tchkName, tchkNum}, + &Gfx::opSetFont}, + {"Tj", 1, {tchkString}, + &Gfx::opShowText}, + {"Tm", 6, {tchkNum, tchkNum, tchkNum, tchkNum, + tchkNum, tchkNum}, + &Gfx::opSetTextMatrix}, + {"Tr", 1, {tchkInt}, + &Gfx::opSetTextRender}, + {"Ts", 1, {tchkNum}, + &Gfx::opSetTextRise}, + {"Tw", 1, {tchkNum}, + &Gfx::opSetWordSpacing}, + {"Tz", 1, {tchkNum}, + &Gfx::opSetHorizScaling}, + {"W", 0, {tchkNone}, + &Gfx::opClip}, + {"W*", 0, {tchkNone}, + &Gfx::opEOClip}, + {"b", 0, {tchkNone}, + &Gfx::opCloseFillStroke}, + {"b*", 0, {tchkNone}, + &Gfx::opCloseEOFillStroke}, + {"c", 6, {tchkNum, tchkNum, tchkNum, tchkNum, + tchkNum, tchkNum}, + &Gfx::opCurveTo}, + {"cm", 6, {tchkNum, tchkNum, tchkNum, tchkNum, + tchkNum, tchkNum}, + &Gfx::opConcat}, + {"cs", 1, {tchkName}, + &Gfx::opSetFillColorSpace}, + {"d", 2, {tchkArray, tchkNum}, + &Gfx::opSetDash}, + {"d0", 2, {tchkNum, tchkNum}, + &Gfx::opSetCharWidth}, + {"d1", 6, {tchkNum, tchkNum, tchkNum, tchkNum, + tchkNum, tchkNum}, + &Gfx::opSetCacheDevice}, + {"f", 0, {tchkNone}, + &Gfx::opFill}, + {"f*", 0, {tchkNone}, + &Gfx::opEOFill}, + {"g", 1, {tchkNum}, + &Gfx::opSetFillGray}, + {"gs", 1, {tchkName}, + &Gfx::opSetExtGState}, + {"h", 0, {tchkNone}, + &Gfx::opClosePath}, + {"i", 1, {tchkNum}, + &Gfx::opSetFlat}, + {"j", 1, {tchkInt}, + &Gfx::opSetLineJoin}, + {"k", 4, {tchkNum, tchkNum, tchkNum, tchkNum}, + &Gfx::opSetFillCMYKColor}, + {"l", 2, {tchkNum, tchkNum}, + &Gfx::opLineTo}, + {"m", 2, {tchkNum, tchkNum}, + &Gfx::opMoveTo}, + {"n", 0, {tchkNone}, + &Gfx::opEndPath}, + {"q", 0, {tchkNone}, + &Gfx::opSave}, + {"re", 4, {tchkNum, tchkNum, tchkNum, tchkNum}, + &Gfx::opRectangle}, + {"rg", 3, {tchkNum, tchkNum, tchkNum}, + &Gfx::opSetFillRGBColor}, + {"ri", 1, {tchkName}, + &Gfx::opSetRenderingIntent}, + {"s", 0, {tchkNone}, + &Gfx::opCloseStroke}, + {"sc", -4, {tchkNum, tchkNum, tchkNum, tchkNum}, + &Gfx::opSetFillColor}, + {"scn", -5, {tchkSCN, tchkSCN, tchkSCN, tchkSCN, + tchkSCN}, + &Gfx::opSetFillColorN}, + {"sh", 1, {tchkName}, + &Gfx::opShFill}, + {"v", 4, {tchkNum, tchkNum, tchkNum, tchkNum}, + &Gfx::opCurveTo1}, + {"w", 1, {tchkNum}, + &Gfx::opSetLineWidth}, + {"y", 4, {tchkNum, tchkNum, tchkNum, tchkNum}, + &Gfx::opCurveTo2}, +}; + +#define numOps (sizeof(opTab) / sizeof(Operator)) + +//------------------------------------------------------------------------ + +GBool printCommands = gFalse; + +//------------------------------------------------------------------------ +// Gfx +//------------------------------------------------------------------------ + +Gfx::Gfx(OutputDev *out1, int pageNum, Dict *resDict, + int dpi, double x1, double y1, double x2, double y2, GBool crop, + double cropX1, double cropY1, double cropX2, double cropY2, + int rotate) { + Object obj1; + + // start the resource stack + res = new GfxResources(NULL); + + // build font dictionary + res->fonts = NULL; + if (resDict) { + resDict->lookup("Font", &obj1); + if (obj1.isDict()) + res->fonts = new GfxFontDict(obj1.getDict()); + obj1.free(); + } + + // get XObject dictionary + if (resDict) + resDict->lookup("XObject", &res->xObjDict); + else + res->xObjDict.initNull(); + + // get colorspace dictionary + if (resDict) + resDict->lookup("ColorSpace", &res->colorSpaceDict); + else + res->colorSpaceDict.initNull(); + + // initialize + out = out1; + state = new GfxState(dpi, x1, y1, x2, y2, rotate, out->upsideDown()); + fontChanged = gFalse; + clip = clipNone; + ignoreUndef = 0; + out->startPage(pageNum, state); + out->setDefaultCTM(state->getCTM()); + out->updateAll(state); + + // set crop box + if (crop) { + state->moveTo(cropX1, cropY1); + state->lineTo(cropX2, cropY1); + state->lineTo(cropX2, cropY2); + state->lineTo(cropX1, cropY2); + state->closePath(); + out->clip(state); + state->clearPath(); + } +} + +Gfx::~Gfx() { + GfxResources *resPtr; + + while (state->hasSaves()) { + state = state->restore(); + out->restoreState(state); + } + out->endPage(); + while (res) { + resPtr = res->next; + delete res; + res = resPtr; + } + if (state) + delete state; +} + +GfxResources::~GfxResources() { + if (fonts) + delete fonts; + xObjDict.free(); + colorSpaceDict.free(); +} + +void Gfx::display(Object *obj) { + Object obj2; + int i; + + if (obj->isArray()) { + for (i = 0; i < obj->arrayGetLength(); ++i) { + obj->arrayGet(i, &obj2); + if (!obj2.isStream()) { + error(-1, "Weird page contents"); + obj2.free(); + return; + } + obj2.free(); + } + } else if (!obj->isStream()) { + error(-1, "Weird page contents"); + return; + } + parser = new Parser(new Lexer(obj)); + go(); + delete parser; + parser = NULL; +} + +void Gfx::go() { + Object obj; + Object args[maxArgs]; + int numCmds, numArgs; + int i; + + // scan a sequence of objects + numCmds = 0; + numArgs = 0; + parser->getObj(&obj); + while (!obj.isEOF()) { + + // got a command - execute it + if (obj.isCmd()) { + if (printCommands) { + obj.print(stdout); + for (i = 0; i < numArgs; ++i) { + printf(" "); + args[i].print(stdout); + } + printf("\n"); + } + execOp(&obj, args, numArgs); + obj.free(); + for (i = 0; i < numArgs; ++i) + args[i].free(); + numArgs = 0; + + // periodically update display + if (++numCmds == 200) { + out->dump(); + numCmds = 0; + } + + // got an argument - save it + } else if (numArgs < maxArgs) { + args[numArgs++] = obj; + + // too many arguments - something is wrong + } else { + error(getPos(), "Too many args in content stream"); + if (printCommands) { + printf("throwing away arg: "); + obj.print(stdout); + printf("\n"); + } + obj.free(); + } + + // grab the next object + parser->getObj(&obj); + } + obj.free(); + + // args at end with no command + if (numArgs > 0) { + error(getPos(), "Leftover args in content stream"); + if (printCommands) { + printf("%d leftovers:", numArgs); + for (i = 0; i < numArgs; ++i) { + printf(" "); + args[i].print(stdout); + } + printf("\n"); + } + for (i = 0; i < numArgs; ++i) + args[i].free(); + } + + // update display + if (numCmds > 0) + out->dump(); + + // clean up + if (printCommands) + fflush(stdout); +} + +void Gfx::execOp(Object *cmd, Object args[], int numArgs) { + Operator *op; + char *name; + int i; + + // find operator + name = cmd->getName(); + if (!(op = findOp(name))) { + if (ignoreUndef == 0) + error(getPos(), "Unknown operator '%s'", name); + return; + } + + // type check args + if (op->numArgs >= 0) { + if (numArgs != op->numArgs) { + error(getPos(), "Wrong number (%d) of args to '%s' operator", + numArgs, name); + return; + } + } else { + if (numArgs > -op->numArgs) { + error(getPos(), "Too many (%d) args to '%s' operator", + numArgs, name); + return; + } + } + for (i = 0; i < numArgs; ++i) { + if (!checkArg(&args[i], op->tchk[i])) { + error(getPos(), "Arg #%d to '%s' operator is wrong type (%s)", + i, name, args[i].getTypeName()); + return; + } + } + + // do it + (this->*op->func)(args, numArgs); +} + +Operator *Gfx::findOp(char *name) { + int a, b, m, cmp; + + a = -1; + b = numOps; + // invariant: opTab[a] < name < opTab[b] + while (b - a > 1) { + m = (a + b) / 2; + cmp = strcmp(opTab[m].name, name); + if (cmp < 0) + a = m; + else if (cmp > 0) + b = m; + else + a = b = m; + } + if (cmp != 0) + return NULL; + return &opTab[a]; +} + +GBool Gfx::checkArg(Object *arg, TchkType type) { + switch (type) { + case tchkBool: return arg->isBool(); + case tchkInt: return arg->isInt(); + case tchkNum: return arg->isNum(); + case tchkString: return arg->isString(); + case tchkName: return arg->isName(); + case tchkArray: return arg->isArray(); + case tchkProps: return arg->isDict() || arg->isName(); + case tchkSCN: return arg->isNum() || arg->isName(); + case tchkNone: return gFalse; + } + return gFalse; +} + +int Gfx::getPos() { + return parser ? parser->getPos() : -1; +} + +GfxFont *Gfx::lookupFont(char *name) { + GfxFont *font; + GfxResources *resPtr; + + for (resPtr = res; resPtr; resPtr = resPtr->next) { + if (resPtr->fonts) { + if ((font = resPtr->fonts->lookup(name))) + return font; + } + } + error(getPos(), "unknown font tag '%s'", name); + return NULL; +} + +GBool Gfx::lookupXObject(char *name, Object *obj) { + GfxResources *resPtr; + + for (resPtr = res; resPtr; resPtr = resPtr->next) { + if (resPtr->xObjDict.isDict()) { + if (!resPtr->xObjDict.dictLookup(name, obj)->isNull()) + return gTrue; + obj->free(); + } + } + error(getPos(), "XObject '%s' is unknown", name); + return gFalse; +} + +void Gfx::lookupColorSpace(char *name, Object *obj) { + GfxResources *resPtr; + + for (resPtr = res; resPtr; resPtr = resPtr->next) { + if (resPtr->colorSpaceDict.isDict()) { + if (!resPtr->colorSpaceDict.dictLookup(name, obj)->isNull()) + return; + obj->free(); + } + } + obj->initNull(); +} + +//------------------------------------------------------------------------ +// graphics state operators +//------------------------------------------------------------------------ + +void Gfx::opSave(Object args[], int numArgs) { + out->saveState(state); + state = state->save(); +} + +void Gfx::opRestore(Object args[], int numArgs) { + state = state->restore(); + out->restoreState(state); + + // Some PDF producers (Macromedia FreeHand) generate a save (q) and + // restore (Q) inside a path sequence. The PDF spec seems to imply + // that this is illegal. Calling clearPath() here implements the + // behavior apparently expected by this software. + state->clearPath(); +} + +void Gfx::opConcat(Object args[], int numArgs) { + state->concatCTM(args[0].getNum(), args[1].getNum(), + args[2].getNum(), args[3].getNum(), + args[4].getNum(), args[5].getNum()); + out->updateCTM(state, args[0].getNum(), args[1].getNum(), + args[2].getNum(), args[3].getNum(), + args[4].getNum(), args[5].getNum()); + fontChanged = gTrue; +} + +void Gfx::opSetDash(Object args[], int numArgs) { + Array *a; + int length; + Object obj; + double *dash; + int i; + + a = args[0].getArray(); + length = a->getLength(); + if (length == 0) { + dash = NULL; + } else { + dash = (double *)gmalloc(length * sizeof(double)); + for (i = 0; i < length; ++i) { + dash[i] = a->get(i, &obj)->getNum(); + obj.free(); + } + } + state->setLineDash(dash, length, args[1].getNum()); + out->updateLineDash(state); +} + +void Gfx::opSetFlat(Object args[], int numArgs) { + state->setFlatness((int)args[0].getNum()); + out->updateFlatness(state); +} + +void Gfx::opSetLineJoin(Object args[], int numArgs) { + state->setLineJoin(args[0].getInt()); + out->updateLineJoin(state); +} + +void Gfx::opSetLineCap(Object args[], int numArgs) { + state->setLineCap(args[0].getInt()); + out->updateLineCap(state); +} + +void Gfx::opSetMiterLimit(Object args[], int numArgs) { + state->setMiterLimit(args[0].getNum()); + out->updateMiterLimit(state); +} + +void Gfx::opSetLineWidth(Object args[], int numArgs) { + state->setLineWidth(args[0].getNum()); + out->updateLineWidth(state); +} + +void Gfx::opSetExtGState(Object args[], int numArgs) { +} + +void Gfx::opSetRenderingIntent(Object args[], int numArgs) { +} + +//------------------------------------------------------------------------ +// color operators +//------------------------------------------------------------------------ + +void Gfx::opSetFillGray(Object args[], int numArgs) { + state->setFillColorSpace(new GfxColorSpace(colorGray)); + state->setFillGray(args[0].getNum()); + out->updateFillColor(state); +} + +void Gfx::opSetStrokeGray(Object args[], int numArgs) { + state->setStrokeColorSpace(new GfxColorSpace(colorGray)); + state->setStrokeGray(args[0].getNum()); + out->updateStrokeColor(state); +} + +void Gfx::opSetFillCMYKColor(Object args[], int numArgs) { + state->setFillColorSpace(new GfxColorSpace(colorCMYK)); + state->setFillCMYK(args[0].getNum(), args[1].getNum(), + args[2].getNum(), args[3].getNum()); + out->updateFillColor(state); +} + +void Gfx::opSetStrokeCMYKColor(Object args[], int numArgs) { + state->setStrokeColorSpace(new GfxColorSpace(colorCMYK)); + state->setStrokeCMYK(args[0].getNum(), args[1].getNum(), + args[2].getNum(), args[3].getNum()); + out->updateStrokeColor(state); +} + +void Gfx::opSetFillRGBColor(Object args[], int numArgs) { + state->setFillColorSpace(new GfxColorSpace(colorRGB)); + state->setFillRGB(args[0].getNum(), args[1].getNum(), args[2].getNum()); + out->updateFillColor(state); +} + +void Gfx::opSetStrokeRGBColor(Object args[], int numArgs) { + state->setStrokeColorSpace(new GfxColorSpace(colorRGB)); + state->setStrokeRGB(args[0].getNum(), args[1].getNum(), args[2].getNum()); + out->updateStrokeColor(state); +} + +void Gfx::opSetFillColorSpace(Object args[], int numArgs) { + Object obj; + GfxColorSpace *colorSpace; + double x[4]; + + lookupColorSpace(args[0].getName(), &obj); + if (obj.isNull()) + colorSpace = new GfxColorSpace(&args[0]); + else + colorSpace = new GfxColorSpace(&obj); + obj.free(); + if (colorSpace->isOk()) { + state->setFillColorSpace(colorSpace); + } else { + delete colorSpace; + error(getPos(), "Bad colorspace"); + } + x[0] = x[1] = x[2] = x[3] = 0; + state->setFillColor(x); + out->updateFillColor(state); +} + +void Gfx::opSetStrokeColorSpace(Object args[], int numArgs) { + Object obj; + GfxColorSpace *colorSpace; + double x[4]; + + lookupColorSpace(args[0].getName(), &obj); + if (obj.isNull()) + colorSpace = new GfxColorSpace(&args[0]); + else + colorSpace = new GfxColorSpace(&obj); + obj.free(); + if (colorSpace->isOk()) { + state->setStrokeColorSpace(colorSpace); + } else { + delete colorSpace; + error(getPos(), "Bad colorspace"); + } + x[0] = x[1] = x[2] = x[3] = 0; + state->setStrokeColor(x); + out->updateStrokeColor(state); +} + +void Gfx::opSetFillColor(Object args[], int numArgs) { + double x[4]; + int i; + + x[0] = x[1] = x[2] = x[3] = 0; + for (i = 0; i < numArgs; ++i) + x[i] = args[i].getNum(); + state->setFillColor(x); + out->updateFillColor(state); +} + +void Gfx::opSetStrokeColor(Object args[], int numArgs) { + double x[4]; + int i; + + x[0] = x[1] = x[2] = x[3] = 0; + for (i = 0; i < numArgs; ++i) + x[i] = args[i].getNum(); + state->setStrokeColor(x); + out->updateStrokeColor(state); +} + +void Gfx::opSetFillColorN(Object args[], int numArgs) { + double x[4]; + int i; + + x[0] = x[1] = x[2] = x[3] = 0; + for (i = 0; i < numArgs && i < 4; ++i) { + if (args[i].isNum()) + x[i] = args[i].getNum(); + else + break; + } + state->setFillColor(x); + out->updateFillColor(state); +} + +void Gfx::opSetStrokeColorN(Object args[], int numArgs) { + double x[4]; + int i; + + x[0] = x[1] = x[2] = x[3] = 0; + for (i = 0; i < numArgs && i < 4; ++i) { + if (args[i].isNum()) + x[i] = args[i].getNum(); + else + break; + } + state->setStrokeColor(x); + out->updateStrokeColor(state); +} + +//------------------------------------------------------------------------ +// path segment operators +//------------------------------------------------------------------------ + +void Gfx::opMoveTo(Object args[], int numArgs) { + state->moveTo(args[0].getNum(), args[1].getNum()); +} + +void Gfx::opLineTo(Object args[], int numArgs) { + if (!state->isCurPt()) { + error(getPos(), "No current point in lineto"); + return; + } + state->lineTo(args[0].getNum(), args[1].getNum()); +} + +void Gfx::opCurveTo(Object args[], int numArgs) { + double x1, y1, x2, y2, x3, y3; + + if (!state->isCurPt()) { + error(getPos(), "No current point in curveto"); + return; + } + x1 = args[0].getNum(); + y1 = args[1].getNum(); + x2 = args[2].getNum(); + y2 = args[3].getNum(); + x3 = args[4].getNum(); + y3 = args[5].getNum(); + state->curveTo(x1, y1, x2, y2, x3, y3); +} + +void Gfx::opCurveTo1(Object args[], int numArgs) { + double x1, y1, x2, y2, x3, y3; + + if (!state->isCurPt()) { + error(getPos(), "No current point in curveto1"); + return; + } + x1 = state->getCurX(); + y1 = state->getCurY(); + x2 = args[0].getNum(); + y2 = args[1].getNum(); + x3 = args[2].getNum(); + y3 = args[3].getNum(); + state->curveTo(x1, y1, x2, y2, x3, y3); +} + +void Gfx::opCurveTo2(Object args[], int numArgs) { + double x1, y1, x2, y2, x3, y3; + + if (!state->isCurPt()) { + error(getPos(), "No current point in curveto2"); + return; + } + x1 = args[0].getNum(); + y1 = args[1].getNum(); + x2 = args[2].getNum(); + y2 = args[3].getNum(); + x3 = x2; + y3 = y2; + state->curveTo(x1, y1, x2, y2, x3, y3); +} + +void Gfx::opRectangle(Object args[], int numArgs) { + double x, y, w, h; + + x = args[0].getNum(); + y = args[1].getNum(); + w = args[2].getNum(); + h = args[3].getNum(); + state->moveTo(x, y); + state->lineTo(x + w, y); + state->lineTo(x + w, y + h); + state->lineTo(x, y + h); + state->closePath(); +} + +void Gfx::opClosePath(Object args[], int numArgs) { + if (!state->isPath()) { + error(getPos(), "No current point in closepath"); + return; + } + state->closePath(); +} + +//------------------------------------------------------------------------ +// path painting operators +//------------------------------------------------------------------------ + +void Gfx::opEndPath(Object args[], int numArgs) { + doEndPath(); +} + +void Gfx::opStroke(Object args[], int numArgs) { + if (!state->isCurPt()) { + //error(getPos(), "No path in stroke"); + return; + } + if (state->isPath()) + out->stroke(state); + doEndPath(); +} + +void Gfx::opCloseStroke(Object args[], int numArgs) { + if (!state->isCurPt()) { + //error(getPos(), "No path in closepath/stroke"); + return; + } + if (state->isPath()) { + state->closePath(); + out->stroke(state); + } + doEndPath(); +} + +void Gfx::opFill(Object args[], int numArgs) { + if (!state->isCurPt()) { + //error(getPos(), "No path in fill"); + return; + } + if (state->isPath()) + out->fill(state); + doEndPath(); +} + +void Gfx::opEOFill(Object args[], int numArgs) { + if (!state->isCurPt()) { + //error(getPos(), "No path in eofill"); + return; + } + if (state->isPath()) + out->eoFill(state); + doEndPath(); +} + +void Gfx::opFillStroke(Object args[], int numArgs) { + if (!state->isCurPt()) { + //error(getPos(), "No path in fill/stroke"); + return; + } + if (state->isPath()) { + out->fill(state); + out->stroke(state); + } + doEndPath(); +} + +void Gfx::opCloseFillStroke(Object args[], int numArgs) { + if (!state->isCurPt()) { + //error(getPos(), "No path in closepath/fill/stroke"); + return; + } + if (state->isPath()) { + state->closePath(); + out->fill(state); + out->stroke(state); + } + doEndPath(); +} + +void Gfx::opEOFillStroke(Object args[], int numArgs) { + if (!state->isCurPt()) { + //error(getPos(), "No path in eofill/stroke"); + return; + } + if (state->isPath()) { + out->eoFill(state); + out->stroke(state); + } + doEndPath(); +} + +void Gfx::opCloseEOFillStroke(Object args[], int numArgs) { + if (!state->isCurPt()) { + //error(getPos(), "No path in closepath/eofill/stroke"); + return; + } + if (state->isPath()) { + state->closePath(); + out->eoFill(state); + out->stroke(state); + } + doEndPath(); +} + +void Gfx::opShFill(Object args[], int numArgs) { +} + +void Gfx::doEndPath() { + if (state->isPath()) { + if (clip == clipNormal) + out->clip(state); + else if (clip == clipEO) + out->eoClip(state); + } + clip = clipNone; + state->clearPath(); +} + +//------------------------------------------------------------------------ +// path clipping operators +//------------------------------------------------------------------------ + +void Gfx::opClip(Object args[], int numArgs) { + clip = clipNormal; +} + +void Gfx::opEOClip(Object args[], int numArgs) { + clip = clipEO; +} + +//------------------------------------------------------------------------ +// text object operators +//------------------------------------------------------------------------ + +void Gfx::opBeginText(Object args[], int numArgs) { + state->setTextMat(1, 0, 0, 1, 0, 0); + state->textMoveTo(0, 0); + out->updateTextMat(state); + out->updateTextPos(state); + fontChanged = gTrue; +} + +void Gfx::opEndText(Object args[], int numArgs) { +} + +//------------------------------------------------------------------------ +// text state operators +//------------------------------------------------------------------------ + +void Gfx::opSetCharSpacing(Object args[], int numArgs) { + state->setCharSpace(args[0].getNum()); + out->updateCharSpace(state); +} + +void Gfx::opSetFont(Object args[], int numArgs) { + GfxFont *font; + + if (!(font = lookupFont(args[0].getName()))) + return; + if (printCommands) { + printf(" font: '%s' %g\n", + font->getName() ? font->getName()->getCString() : "???", + args[1].getNum()); + } + state->setFont(font, args[1].getNum()); + fontChanged = gTrue; +} + +void Gfx::opSetTextLeading(Object args[], int numArgs) { + state->setLeading(args[0].getNum()); +} + +void Gfx::opSetTextRender(Object args[], int numArgs) { + state->setRender(args[0].getInt()); + out->updateRender(state); +} + +void Gfx::opSetTextRise(Object args[], int numArgs) { + state->setRise(args[0].getNum()); + out->updateRise(state); +} + +void Gfx::opSetWordSpacing(Object args[], int numArgs) { + state->setWordSpace(args[0].getNum()); + out->updateWordSpace(state); +} + +void Gfx::opSetHorizScaling(Object args[], int numArgs) { + state->setHorizScaling(args[0].getNum()); + out->updateHorizScaling(state); +} + +//------------------------------------------------------------------------ +// text positioning operators +//------------------------------------------------------------------------ + +void Gfx::opTextMove(Object args[], int numArgs) { + double tx, ty; + + tx = state->getLineX() + args[0].getNum(); + ty = state->getLineY() + args[1].getNum(); + state->textMoveTo(tx, ty); + out->updateTextPos(state); +} + +void Gfx::opTextMoveSet(Object args[], int numArgs) { + double tx, ty; + + tx = state->getLineX() + args[0].getNum(); + ty = args[1].getNum(); + state->setLeading(-ty); + ty += state->getLineY(); + state->textMoveTo(tx, ty); + out->updateTextPos(state); +} + +void Gfx::opSetTextMatrix(Object args[], int numArgs) { + state->setTextMat(args[0].getNum(), args[1].getNum(), + args[2].getNum(), args[3].getNum(), + args[4].getNum(), args[5].getNum()); + state->textMoveTo(0, 0); + out->updateTextMat(state); + out->updateTextPos(state); + fontChanged = gTrue; +} + +void Gfx::opTextNextLine(Object args[], int numArgs) { + double tx, ty; + + tx = state->getLineX(); + ty = state->getLineY() - state->getLeading(); + state->textMoveTo(tx, ty); + out->updateTextPos(state); +} + +//------------------------------------------------------------------------ +// text string operators +//------------------------------------------------------------------------ + +void Gfx::opShowText(Object args[], int numArgs) { + if (!state->getFont()) { + error(getPos(), "No font in show"); + return; + } + doShowText(args[0].getString()); +} + +void Gfx::opMoveShowText(Object args[], int numArgs) { + double tx, ty; + + if (!state->getFont()) { + error(getPos(), "No font in move/show"); + return; + } + tx = state->getLineX(); + ty = state->getLineY() - state->getLeading(); + state->textMoveTo(tx, ty); + out->updateTextPos(state); + doShowText(args[0].getString()); +} + +void Gfx::opMoveSetShowText(Object args[], int numArgs) { + double tx, ty; + + if (!state->getFont()) { + error(getPos(), "No font in move/set/show"); + return; + } + state->setWordSpace(args[0].getNum()); + state->setCharSpace(args[1].getNum()); + tx = state->getLineX(); + ty = state->getLineY() - state->getLeading(); + state->textMoveTo(tx, ty); + out->updateWordSpace(state); + out->updateCharSpace(state); + out->updateTextPos(state); + doShowText(args[2].getString()); +} + +void Gfx::opShowSpaceText(Object args[], int numArgs) { + Array *a; + Object obj; + int i; + + if (!state->getFont()) { + error(getPos(), "No font in show/space"); + return; + } + a = args[0].getArray(); + for (i = 0; i < a->getLength(); ++i) { + a->get(i, &obj); + if (obj.isNum()) { + state->textShift(-obj.getNum() * 0.001 * state->getFontSize()); + out->updateTextShift(state, obj.getNum()); + } else if (obj.isString()) { + doShowText(obj.getString()); + } else { + error(getPos(), "Element of show/space array must be number or string"); + } + obj.free(); + } +} + +void Gfx::doShowText(GString *s) { + GfxFont *font; + GfxFontEncoding16 *enc; + Guchar *p; + Guchar c8; + int c16; + GString *s16; + char s16a[2]; + int m, n; +#if 0 //~type3 + double dx, dy, width, height, w, h, x, y; + double oldCTM[6], newCTM[6]; + double *mat; + Object charProc; + Parser *oldParser; + int i; +#else + double dx, dy, width, height, w, h, sWidth, sHeight; +#endif + + if (fontChanged) { + out->updateFont(state); + fontChanged = gFalse; + } + font = state->getFont(); + + //----- 16-bit font + if (font->is16Bit()) { + enc = font->getEncoding16(); + if (out->useDrawChar()) { + out->beginString(state, s); + s16 = NULL; + } else { + s16 = new GString(); + } + sWidth = sHeight = 0; + state->textTransformDelta(0, state->getRise(), &dx, &dy); + p = (Guchar *)s->getCString(); + n = s->getLength(); + while (n > 0) { + m = getNextChar16(enc, p, &c16); + if (enc->wMode == 0) { + width = state->getFontSize() * state->getHorizScaling() * + font->getWidth16(c16) + + state->getCharSpace(); + if (c16 == ' ') { + width += state->getWordSpace(); + } + height = 0; + } else { + width = 0; + height = state->getFontSize() * font->getHeight16(c16); + } + state->textTransformDelta(width, height, &w, &h); + if (out->useDrawChar()) { + out->drawChar16(state, state->getCurX() + dx, state->getCurY() + dy, + w, h, c16); + state->textShift(width, height); + } else { + s16a[0] = (char)(c16 >> 8); + s16a[1] = (char)c16; + s16->append(s16a, 2); + sWidth += w; + sHeight += h; + } + n -= m; + p += m; + } + if (out->useDrawChar()) { + out->endString(state); + } else { + out->drawString16(state, s16); + delete s16; + state->textShift(sWidth, sHeight); + } + + //----- 8-bit font + } else { +#if 0 //~type3 + //~ also check out->renderType3() + if (font->getType() == fontType3) { + out->beginString(state, s); + mat = state->getCTM(); + for (i = 0; i < 6; ++i) { + oldCTM[i] = mat[i]; + } + mat = state->getTextMat(); + newCTM[0] = mat[0] * oldCTM[0] + mat[1] * oldCTM[2]; + newCTM[1] = mat[0] * oldCTM[1] + mat[1] * oldCTM[3]; + newCTM[2] = mat[2] * oldCTM[0] + mat[3] * oldCTM[2]; + newCTM[3] = mat[2] * oldCTM[1] + mat[3] * oldCTM[3]; + mat = font->getFontMatrix(); + newCTM[0] = mat[0] * newCTM[0] + mat[1] * newCTM[2]; + newCTM[1] = mat[0] * newCTM[1] + mat[1] * newCTM[3]; + newCTM[2] = mat[2] * newCTM[0] + mat[3] * newCTM[2]; + newCTM[3] = mat[2] * newCTM[1] + mat[3] * newCTM[3]; + newCTM[0] *= state->getFontSize(); + newCTM[3] *= state->getFontSize(); + newCTM[0] *= state->getHorizScaling(); + newCTM[2] *= state->getHorizScaling(); + state->textTransformDelta(0, state->getRise(), &dx, &dy); + oldParser = parser; + for (p = (Guchar *)s->getCString(), n = s->getLength(); n; ++p, --n) { + c8 = *p; + font->getCharProc(c8, &charProc); + state->transform(state->getCurX() + dx, state->getCurY() + dy, &x, &y); + state->setCTM(newCTM[0], newCTM[1], newCTM[2], newCTM[3], x, y); + //~ out->updateCTM(???) + if (charProc.isStream()) { + display(&charProc); + } else { + error(getPos(), "Missing or bad Type3 CharProc entry"); + } + state->setCTM(oldCTM[0], oldCTM[1], oldCTM[2], + oldCTM[3], oldCTM[4], oldCTM[5]); + //~ out->updateCTM(???) - use gsave/grestore instead? + charProc.free(); + width = state->getFontSize() * state->getHorizScaling() * + font->getWidth(c8) + + state->getCharSpace(); + if (c8 == ' ') { + width += state->getWordSpace(); + } + state->textShift(width); + } + parser = oldParser; + out->endString(state); + } else +#endif + if (out->useDrawChar()) { + out->beginString(state, s); + state->textTransformDelta(0, state->getRise(), &dx, &dy); + for (p = (Guchar *)s->getCString(), n = s->getLength(); n; ++p, --n) { + c8 = *p; + width = state->getFontSize() * state->getHorizScaling() * + font->getWidth(c8) + + state->getCharSpace(); + if (c8 == ' ') + width += state->getWordSpace(); + state->textTransformDelta(width, 0, &w, &h); + out->drawChar(state, state->getCurX() + dx, state->getCurY() + dy, + w, h, c8); + state->textShift(width); + } + out->endString(state); + } else { + out->drawString(state, s); + width = state->getFontSize() * state->getHorizScaling() * + font->getWidth(s) + + s->getLength() * state->getCharSpace(); + for (p = (Guchar *)s->getCString(), n = s->getLength(); n; ++p, --n) { + if (*p == ' ') + width += state->getWordSpace(); + } + state->textShift(width); + } + } +} + +int Gfx::getNextChar16(GfxFontEncoding16 *enc, Guchar *p, int *c16) { + int n; + int code; + int a, b, m; + + n = enc->codeLen[*p]; + if (n == 1) { + *c16 = enc->map1[*p]; + } else { + code = (p[0] << 8) + p[1]; + a = 0; + b = enc->map2Len; + // invariant: map2[2*a] <= code < map2[2*b] + while (b - a > 1) { + m = (a + b) / 2; + if (enc->map2[2*m] <= code) + a = m; + else if (enc->map2[2*m] > code) + b = m; + else + break; + } + *c16 = enc->map2[2*a+1] + (code - enc->map2[2*a]); + } + return n; +} + +//------------------------------------------------------------------------ +// XObject operators +//------------------------------------------------------------------------ + +void Gfx::opXObject(Object args[], int numArgs) { + Object obj1, obj2; +#if OPI_SUPPORT + Object opiDict; +#endif + + if (!lookupXObject(args[0].getName(), &obj1)) + return; + if (!obj1.isStream()) { + error(getPos(), "XObject '%s' is wrong type", args[0].getName()); + obj1.free(); + return; + } +#if OPI_SUPPORT + obj1.streamGetDict()->lookup("OPI", &opiDict); + if (opiDict.isDict()) { + out->opiBegin(state, opiDict.getDict()); + } +#endif + obj1.streamGetDict()->lookup("Subtype", &obj2); + if (obj2.isName("Image")) + doImage(obj1.getStream(), gFalse); + else if (obj2.isName("Form")) + doForm(&obj1); + else if (obj2.isName()) + error(getPos(), "Unknown XObject subtype '%s'", obj2.getName()); + else + error(getPos(), "XObject subtype is missing or wrong type"); + obj2.free(); +#if OPI_SUPPORT + if (opiDict.isDict()) { + out->opiEnd(state, opiDict.getDict()); + } + opiDict.free(); +#endif + obj1.free(); +} + +void Gfx::doImage(Stream *str, GBool inlineImg) { + Dict *dict; + Object obj1, obj2; + int width, height; + int bits; + GBool mask; + GfxColorSpace *colorSpace; + GfxImageColorMap *colorMap; + GBool invert; + + // get stream dict + dict = str->getDict(); + + // get size + dict->lookup("Width", &obj1); + if (obj1.isNull()) { + obj1.free(); + dict->lookup("W", &obj1); + } + if (!obj1.isInt()) + goto err2; + width = obj1.getInt(); + obj1.free(); + dict->lookup("Height", &obj1); + if (obj1.isNull()) { + obj1.free(); + dict->lookup("H", &obj1); + } + if (!obj1.isInt()) + goto err2; + height = obj1.getInt(); + obj1.free(); + + // image or mask? + dict->lookup("ImageMask", &obj1); + if (obj1.isNull()) { + obj1.free(); + dict->lookup("IM", &obj1); + } + mask = gFalse; + if (obj1.isBool()) + mask = obj1.getBool(); + else if (!obj1.isNull()) + goto err2; + obj1.free(); + + // bit depth + dict->lookup("BitsPerComponent", &obj1); + if (obj1.isNull()) { + obj1.free(); + dict->lookup("BPC", &obj1); + } + if (!obj1.isInt()) + goto err2; + bits = obj1.getInt(); + obj1.free(); + + // display a mask + if (mask) { + + // check for inverted mask + if (bits != 1) + goto err1; + invert = gFalse; + dict->lookup("Decode", &obj1); + if (obj1.isNull()) { + obj1.free(); + dict->lookup("D", &obj1); + } + if (obj1.isArray()) { + obj1.arrayGet(0, &obj2); + if (obj2.isInt() && obj2.getInt() == 1) + invert = gTrue; + obj2.free(); + } else if (!obj1.isNull()) { + goto err2; + } + obj1.free(); + + // draw it + out->drawImageMask(state, str, width, height, invert, inlineImg); + + } else { + + // get color space and color map + dict->lookup("ColorSpace", &obj1); + if (obj1.isNull()) { + obj1.free(); + dict->lookup("CS", &obj1); + } + if (obj1.isName()) { + lookupColorSpace(obj1.getName(), &obj2); + if (!obj2.isNull()) { + obj1.free(); + obj1 = obj2; + } else { + obj2.free(); + } + } + colorSpace = new GfxColorSpace(&obj1); + obj1.free(); + if (!colorSpace->isOk()) { + delete colorSpace; + goto err1; + } + dict->lookup("Decode", &obj1); + if (obj1.isNull()) { + obj1.free(); + dict->lookup("D", &obj1); + } + colorMap = new GfxImageColorMap(bits, &obj1, colorSpace); + obj1.free(); + if (!colorMap->isOk()) { + delete colorSpace; + goto err1; + } + + // draw it + out->drawImage(state, str, width, height, colorMap, inlineImg); + delete colorMap; + } + + return; + + err2: + obj1.free(); + err1: + error(getPos(), "Bad image parameters"); +} + +void Gfx::doForm(Object *str) { + Dict *dict; + Object matrixObj, bboxObj; + Object obj1; + + // get stream dict + dict = str->streamGetDict(); + + // check form type + dict->lookup("FormType", &obj1); + if (!(obj1.isInt() && obj1.getInt() == 1)) { + error(getPos(), "Unknown form type"); + } + obj1.free(); + + // get matrix and bounding box + dict->lookup("Matrix", &matrixObj); + if (!matrixObj.isArray()) { + matrixObj.free(); + error(getPos(), "Bad form matrix"); + return; + } + dict->lookup("BBox", &bboxObj); + if (!bboxObj.isArray()) { + matrixObj.free(); + bboxObj.free(); + error(getPos(), "Bad form bounding box"); + return; + } + + doForm1(str, dict, &matrixObj, &bboxObj); + + matrixObj.free(); + bboxObj.free(); +} + +void Gfx::doWidgetForm(Object *str, double x, double y) { + Dict *dict; + Object matrixObj, bboxObj; + Object obj1; + + // get stream dict + dict = str->streamGetDict(); + + // get bounding box + dict->lookup("BBox", &bboxObj); + if (!bboxObj.isArray()) { + bboxObj.free(); + error(getPos(), "Bad form bounding box"); + return; + } + + // construct matrix + matrixObj.initArray(); + obj1.initReal(1); + matrixObj.arrayAdd(&obj1); + obj1.initReal(0); + matrixObj.arrayAdd(&obj1); + obj1.initReal(0); + matrixObj.arrayAdd(&obj1); + obj1.initReal(1); + matrixObj.arrayAdd(&obj1); + obj1.initReal(x); + matrixObj.arrayAdd(&obj1); + obj1.initReal(y); + matrixObj.arrayAdd(&obj1); + + doForm1(str, dict, &matrixObj, &bboxObj); + + matrixObj.free(); + bboxObj.free(); +} + +void Gfx::doForm1(Object *str, Dict *dict, + Object *matrixObj, Object *bboxObj) { + Parser *oldParser; + GfxResources *resPtr; + Dict *resDict; + double m[6]; + Object obj1, obj2; + int i; + + // push new resources on stack + res = new GfxResources(res); + dict->lookup("Resources", &obj1); + if (obj1.isDict()) { + resDict = obj1.getDict(); + res->fonts = NULL; + resDict->lookup("Font", &obj2); + if (obj2.isDict()) + res->fonts = new GfxFontDict(obj2.getDict()); + obj2.free(); + resDict->lookup("XObject", &res->xObjDict); + resDict->lookup("ColorSpace", &res->colorSpaceDict); + obj1.free(); + } + + // save current graphics state + out->saveState(state); + state = state->save(); + + // save current parser + oldParser = parser; + + // set form transformation matrix + for (i = 0; i < 6; ++i) { + matrixObj->arrayGet(i, &obj1); + m[i] = obj1.getNum(); + obj1.free(); + } + state->concatCTM(m[0], m[1], m[2], m[3], m[4], m[5]); + out->updateCTM(state, m[0], m[1], m[2], m[3], m[4], m[5]); + + // set form bounding box + for (i = 0; i < 4; ++i) { + bboxObj->arrayGet(i, &obj1); + m[i] = obj1.getNum(); + obj1.free(); + } + state->moveTo(m[0], m[1]); + state->lineTo(m[2], m[1]); + state->lineTo(m[2], m[3]); + state->lineTo(m[0], m[3]); + state->closePath(); + out->clip(state); + state->clearPath(); + + // draw the form + display(str); + + // restore parser + parser = oldParser; + + // restore graphics state + state = state->restore(); + out->restoreState(state); + + // pop resource stack + resPtr = res->next; + delete res; + res = resPtr; + + return; +} + +//------------------------------------------------------------------------ +// in-line image operators +//------------------------------------------------------------------------ + +void Gfx::opBeginImage(Object args[], int numArgs) { + Stream *str; + int c1, c2; + + // build dict/stream + str = buildImageStream(); + + // display the image + if (str) { + doImage(str, gTrue); + + // skip 'EI' tag + c1 = str->getBaseStream()->getChar(); + c2 = str->getBaseStream()->getChar(); + while (!(c1 == 'E' && c2 == 'I') && c2 != EOF) { + c1 = c2; + c2 = str->getBaseStream()->getChar(); + } + delete str; + } +} + +Stream *Gfx::buildImageStream() { + Object dict; + Object obj; + char *key; + Stream *str; + + // build dictionary + dict.initDict(); + parser->getObj(&obj); + while (!obj.isCmd("ID") && !obj.isEOF()) { + if (!obj.isName()) { + error(getPos(), "Inline image dictionary key must be a name object"); + obj.free(); + parser->getObj(&obj); + } else { + key = copyString(obj.getName()); + obj.free(); + parser->getObj(&obj); + if (obj.isEOF() || obj.isError()) + break; + dict.dictAdd(key, &obj); + } + parser->getObj(&obj); + } + if (obj.isEOF()) + error(getPos(), "End of file in inline image"); + obj.free(); + + // make stream + str = new EmbedStream(parser->getStream(), &dict); + str = str->addFilters(&dict); + + return str; +} + +void Gfx::opImageData(Object args[], int numArgs) { + error(getPos(), "Internal: got 'ID' operator"); +} + +void Gfx::opEndImage(Object args[], int numArgs) { + error(getPos(), "Internal: got 'EI' operator"); +} + +//------------------------------------------------------------------------ +// type 3 font operators +//------------------------------------------------------------------------ + +void Gfx::opSetCharWidth(Object args[], int numArgs) { + error(getPos(), "Encountered 'd0' operator in content stream"); +} + +void Gfx::opSetCacheDevice(Object args[], int numArgs) { + error(getPos(), "Encountered 'd1' operator in content stream"); +} + +//------------------------------------------------------------------------ +// compatibility operators +//------------------------------------------------------------------------ + +void Gfx::opBeginIgnoreUndef(Object args[], int numArgs) { + ++ignoreUndef; +} + +void Gfx::opEndIgnoreUndef(Object args[], int numArgs) { + if (ignoreUndef > 0) + --ignoreUndef; +} + +//------------------------------------------------------------------------ +// marked content operators +//------------------------------------------------------------------------ + +void Gfx::opBeginMarkedContent(Object args[], int numArgs) { + if (printCommands) { + printf(" marked content: %s ", args[0].getName()); + if (numArgs == 2) + args[2].print(stdout); + printf("\n"); + } +} + +void Gfx::opEndMarkedContent(Object args[], int numArgs) { +} + +void Gfx::opMarkPoint(Object args[], int numArgs) { + if (printCommands) { + printf(" mark point: %s ", args[0].getName()); + if (numArgs == 2) + args[2].print(stdout); + printf("\n"); + } +} diff --git a/pdftops/Gfx.h b/pdftops/Gfx.h new file mode 100644 index 0000000000..239c1a1876 --- /dev/null +++ b/pdftops/Gfx.h @@ -0,0 +1,220 @@ +//======================================================================== +// +// Gfx.h +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#ifndef GFX_H +#define GFX_H + +#ifdef __GNUC__ +#pragma interface +#endif + +#include "gtypes.h" + +class GString; +class Array; +class Stream; +class Parser; +class Dict; +class OutputDev; +class GfxFontDict; +class GfxFont; +struct GfxFontEncoding16; +class GfxState; +class Gfx; + +//------------------------------------------------------------------------ +// Gfx +//------------------------------------------------------------------------ + +enum GfxClipType { + clipNone, + clipNormal, + clipEO +}; + +enum TchkType { + tchkBool, // boolean + tchkInt, // integer + tchkNum, // number (integer or real) + tchkString, // string + tchkName, // name + tchkArray, // array + tchkProps, // properties (dictionary or name) + tchkSCN, // scn/SCN args (number of name) + tchkNone // used to avoid empty initializer lists +}; + +#define maxArgs 8 + +struct Operator { + char name[4]; + int numArgs; + TchkType tchk[maxArgs]; + void (Gfx::*func)(Object args[], int numArgs); +}; + +class GfxResources { +public: + + GfxResources(GfxResources *next1) { fonts = NULL; next = next1; } + ~GfxResources(); + + GfxFontDict *fonts; + Object xObjDict; + Object colorSpaceDict; + GfxResources *next; +}; + +class Gfx { +public: + + // Constructor for regular output. + Gfx(OutputDev *out1, int pageNum, Dict *resDict, + int dpi, double x1, double y1, double x2, double y2, GBool crop, + double cropX1, double cropY1, double cropX2, double cropY2, + int rotate); + + // Destructor. + ~Gfx(); + + // Interpret a stream or array of streams. + void display(Object *obj); + + void doWidgetForm(Object *str, double x, double y); + +private: + + OutputDev *out; // output device + GfxResources *res; // resource stack + + GfxState *state; // current graphics state + GBool fontChanged; // set if font or text matrix has changed + GfxClipType clip; // do a clip? + int ignoreUndef; // current BX/EX nesting level + + Parser *parser; // parser for page content stream(s) + + static Operator opTab[]; // table of operators + + void go(); + void execOp(Object *cmd, Object args[], int numArgs); + Operator *findOp(char *name); + GBool checkArg(Object *arg, TchkType type); + int getPos(); + GfxFont *lookupFont(char *name); + GBool lookupXObject(char *name, Object *obj); + void lookupColorSpace(char *name, Object *obj); + + // graphics state operators + void opSave(Object args[], int numArgs); + void opRestore(Object args[], int numArgs); + void opConcat(Object args[], int numArgs); + void opSetDash(Object args[], int numArgs); + void opSetFlat(Object args[], int numArgs); + void opSetLineJoin(Object args[], int numArgs); + void opSetLineCap(Object args[], int numArgs); + void opSetMiterLimit(Object args[], int numArgs); + void opSetLineWidth(Object args[], int numArgs); + void opSetExtGState(Object args[], int numArgs); + void opSetRenderingIntent(Object args[], int numArgs); + + // color operators + void opSetFillGray(Object args[], int numArgs); + void opSetStrokeGray(Object args[], int numArgs); + void opSetFillCMYKColor(Object args[], int numArgs); + void opSetStrokeCMYKColor(Object args[], int numArgs); + void opSetFillRGBColor(Object args[], int numArgs); + void opSetStrokeRGBColor(Object args[], int numArgs); + void opSetFillColorSpace(Object args[], int numArgs); + void opSetStrokeColorSpace(Object args[], int numArgs); + void opSetFillColor(Object args[], int numArgs); + void opSetStrokeColor(Object args[], int numArgs); + void opSetFillColorN(Object args[], int numArgs); + void opSetStrokeColorN(Object args[], int numArgs); + + // path segment operators + void opMoveTo(Object args[], int numArgs); + void opLineTo(Object args[], int numArgs); + void opCurveTo(Object args[], int numArgs); + void opCurveTo1(Object args[], int numArgs); + void opCurveTo2(Object args[], int numArgs); + void opRectangle(Object args[], int numArgs); + void opClosePath(Object args[], int numArgs); + + // path painting operators + void opEndPath(Object args[], int numArgs); + void opStroke(Object args[], int numArgs); + void opCloseStroke(Object args[], int numArgs); + void opFill(Object args[], int numArgs); + void opEOFill(Object args[], int numArgs); + void opFillStroke(Object args[], int numArgs); + void opCloseFillStroke(Object args[], int numArgs); + void opEOFillStroke(Object args[], int numArgs); + void opCloseEOFillStroke(Object args[], int numArgs); + void opShFill(Object args[], int numArgs); + void doEndPath(); + + // path clipping operators + void opClip(Object args[], int numArgs); + void opEOClip(Object args[], int numArgs); + + // text object operators + void opBeginText(Object args[], int numArgs); + void opEndText(Object args[], int numArgs); + + // text state operators + void opSetCharSpacing(Object args[], int numArgs); + void opSetFont(Object args[], int numArgs); + void opSetTextLeading(Object args[], int numArgs); + void opSetTextRender(Object args[], int numArgs); + void opSetTextRise(Object args[], int numArgs); + void opSetWordSpacing(Object args[], int numArgs); + void opSetHorizScaling(Object args[], int numArgs); + + // text positioning operators + void opTextMove(Object args[], int numArgs); + void opTextMoveSet(Object args[], int numArgs); + void opSetTextMatrix(Object args[], int numArgs); + void opTextNextLine(Object args[], int numArgs); + + // text string operators + void opShowText(Object args[], int numArgs); + void opMoveShowText(Object args[], int numArgs); + void opMoveSetShowText(Object args[], int numArgs); + void opShowSpaceText(Object args[], int numArgs); + void doShowText(GString *s); + int getNextChar16(GfxFontEncoding16 *enc, Guchar *p, int *c16); + + // XObject operators + void opXObject(Object args[], int numArgs); + void doImage(Stream *str, GBool inlineImg); + void doForm(Object *str); + void doForm1(Object *str, Dict *dict, + Object *matrixObj, Object *bboxObj); + + // in-line image operators + void opBeginImage(Object args[], int numArgs); + Stream *buildImageStream(); + void opImageData(Object args[], int numArgs); + void opEndImage(Object args[], int numArgs); + + // type 3 font operators + void opSetCharWidth(Object args[], int numArgs); + void opSetCacheDevice(Object args[], int numArgs); + + // compatibility operators + void opBeginIgnoreUndef(Object args[], int numArgs); + void opEndIgnoreUndef(Object args[], int numArgs); + + // marked content operators + void opBeginMarkedContent(Object args[], int numArgs); + void opEndMarkedContent(Object args[], int numArgs); + void opMarkPoint(Object args[], int numArgs); +}; + +#endif diff --git a/pdftops/GfxFont.cxx b/pdftops/GfxFont.cxx new file mode 100644 index 0000000000..b6085729b4 --- /dev/null +++ b/pdftops/GfxFont.cxx @@ -0,0 +1,991 @@ +//======================================================================== +// +// GfxFont.cc +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include +#include +#include +#include +#include +#include "GString.h" +#include "gmem.h" +#include "gfile.h" +#include "config.h" +#include "Object.h" +#include "Array.h" +#include "Dict.h" +#include "Error.h" +#include "Params.h" +#include "FontFile.h" +#include "GfxFont.h" + +#include "FontInfo.h" +#if JAPANESE_SUPPORT +#include "Japan12CMapInfo.h" +#endif +#if CHINESE_SUPPORT +#include "GB12CMapInfo.h" +#endif + +//------------------------------------------------------------------------ + +static int CDECL cmpWidthExcep(const void *w1, const void *w2); +static int CDECL cmpWidthExcepV(const void *w1, const void *w2); + +//------------------------------------------------------------------------ + +static Gushort *defCharWidths[12] = { + courierWidths, + courierObliqueWidths, + courierBoldWidths, + courierBoldObliqueWidths, + helveticaWidths, + helveticaObliqueWidths, + helveticaBoldWidths, + helveticaBoldObliqueWidths, + timesRomanWidths, + timesItalicWidths, + timesBoldWidths, + timesBoldItalicWidths +}; + +//------------------------------------------------------------------------ +// GfxFont +//------------------------------------------------------------------------ + +GfxFont::GfxFont(char *tag1, Ref id1, Dict *fontDict) { + BuiltinFont *builtinFont; + Object obj1, obj2, obj3, obj4; + int missingWidth; + char *name2, *p; + int i; + + // get font tag and ID + tag = new GString(tag1); + id = id1; + + // get base font name + name = NULL; + fontDict->lookup("BaseFont", &obj1); + if (obj1.isName()) + name = new GString(obj1.getName()); + obj1.free(); + + // is it a built-in font? + builtinFont = NULL; + if (name) { + for (i = 0; i < numBuiltinFonts; ++i) { + if (!strcmp(builtinFonts[i].name, name->getCString())) { + builtinFont = &builtinFonts[i]; + break; + } + } + } + + // get font type + type = fontUnknownType; + fontDict->lookup("Subtype", &obj1); + if (obj1.isName("Type1")) + type = fontType1; + else if (obj1.isName("Type1C")) + type = fontType1C; + else if (obj1.isName("Type3")) + type = fontType3; + else if (obj1.isName("TrueType")) + type = fontTrueType; + else if (obj1.isName("Type0")) + type = fontType0; + obj1.free(); + is16 = gFalse; + + // assume Times-Roman by default (for substitution purposes) + flags = fontSerif; + + // Newer Adobe tools are using Base14-compatible TrueType fonts + // without embedding them, so munge the names into the equivalent + // PostScript names. This is a kludge -- it would be nice if Adobe + // followed their own spec. + if (type == fontTrueType) { + p = name->getCString(); + name2 = NULL; + if (!strncmp(p, "Arial", 5)) { + if (!strcmp(p+5, ",Bold")) { + name2 = "Helvetica-Bold"; + } else if (!strcmp(p+5, "Italic")) { + name2 = "Helvetica-Oblique"; + } else if (!strcmp(p+5, "BoldItalic")) { + name2 = "Helvetica-BoldOblique"; + } else { + name2 = "Helvetica"; + } + } else if (!strncmp(p, "TimesNewRoman", 13)) { + if (!strcmp(p+5, ",Bold")) { + name2 = "Times-Bold"; + } else if (!strcmp(p+5, "Italic")) { + name2 = "Times-Italic"; + } else if (!strcmp(p+5, "BoldItalic")) { + name2 = "Times-BoldItalic"; + } else { + name2 = "Times-Roman"; + } + } else if (!strncmp(p, "CourierNew", 10)) { + if (!strcmp(p+5, ",Bold")) { + name2 = "Courier-Bold"; + } else if (!strcmp(p+5, "Italic")) { + name2 = "Courier-Oblique"; + } else if (!strcmp(p+5, "BoldItalic")) { + name2 = "Courier-BoldOblique"; + } else { + name2 = "Courier"; + } + } + if (name2) { + delete name; + name = new GString(name2); + } + } + + // get info from font descriptor + embFontName = NULL; + embFontID.num = -1; + embFontID.gen = -1; + missingWidth = 0; + fontDict->lookup("FontDescriptor", &obj1); + if (obj1.isDict()) { + + // get flags + obj1.dictLookup("Flags", &obj2); + if (obj2.isInt()) + flags = obj2.getInt(); + obj2.free(); + + // get name + obj1.dictLookup("FontName", &obj2); + if (obj2.isName()) + embFontName = new GString(obj2.getName()); + obj2.free(); + + // look for embedded font file + if (type == fontType1) { + obj1.dictLookupNF("FontFile", &obj2); + if (obj2.isRef()) + embFontID = obj2.getRef(); + obj2.free(); + } + if (embFontID.num == -1 && type == fontTrueType) { + obj1.dictLookupNF("FontFile2", &obj2); + if (obj2.isRef()) + embFontID = obj2.getRef(); + obj2.free(); + } + if (embFontID.num == -1) { + obj1.dictLookupNF("FontFile3", &obj2); + if (obj2.isRef()) { + embFontID = obj2.getRef(); + obj2.fetch(&obj3); + if (obj3.isStream()) { + obj3.streamGetDict()->lookup("Subtype", &obj4); + if (obj4.isName("Type1")) + type = fontType1; + else if (obj4.isName("Type1C")) + type = fontType1C; + else if (obj4.isName("Type3")) + type = fontType3; + else if (obj4.isName("TrueType")) + type = fontTrueType; + else if (obj4.isName("Type0")) + type = fontType0; + obj4.free(); + } + obj3.free(); + } + obj2.free(); + } + + // look for MissingWidth + obj1.dictLookup("MissingWidth", &obj2); + if (obj2.isInt()) { + missingWidth = obj2.getInt(); + } + obj2.free(); + } + obj1.free(); + + // get Type3 font definition + if (type == fontType3) { + fontDict->lookup("CharProcs", &charProcs); + if (!charProcs.isDict()) { + error(-1, "Missing or invalid CharProcs dictionary in Type 3 font"); + charProcs.free(); + } + } + + // look for an external font file + extFontFile = NULL; + if (type == fontType1 && name) + findExtFontFile(); + + // get font matrix + fontMat[0] = fontMat[3] = 1; + fontMat[1] = fontMat[2] = fontMat[4] = fontMat[5] = 0; + if (fontDict->lookup("FontMatrix", &obj1)->isArray()) { + for (i = 0; i < 6 && i < obj1.arrayGetLength(); ++i) { + if (obj1.arrayGet(i, &obj2)->isNum()) + fontMat[i] = obj2.getNum(); + obj2.free(); + } + } + obj1.free(); + + // get encoding and character widths + if (type == fontType0) { + getType0EncAndWidths(fontDict); + } else { + getEncAndWidths(fontDict, builtinFont, missingWidth); + } +} + +GfxFont::~GfxFont() { + delete tag; + if (name) { + delete name; + } + if (!is16 && encoding) { + delete encoding; + } + if (embFontName) { + delete embFontName; + } + if (extFontFile) { + delete extFontFile; + } + if (charProcs.isDict()) { + charProcs.free(); + } + if (is16) { + gfree(widths16.exceps); + gfree(widths16.excepsV); + } +} + +double GfxFont::getWidth(GString *s) { + double w; + int i; + + w = 0; + for (i = 0; i < s->getLength(); ++i) + w += widths[s->getChar(i) & 0xff]; + return w; +} + +double GfxFont::getWidth16(int c) { + double w; + int a, b, m; + + w = widths16.defWidth; + a = -1; + b = widths16.numExceps; + // invariant: widths16.exceps[a].last < c < widths16.exceps[b].first + while (b - a > 1) { + m = (a + b) / 2; + if (widths16.exceps[m].last < c) { + a = m; + } else if (c < widths16.exceps[m].first) { + b = m; + } else { + w = widths16.exceps[m].width; + break; + } + } + return w; +} + +double GfxFont::getHeight16(int c) { + double h; + int a, b, m; + + h = widths16.defHeight; + a = -1; + b = widths16.numExcepsV; + // invariant: widths16.excepsV[a].last < c < widths16.excepsV[b].first + while (b - a > 1) { + m = (a + b) / 2; + if (widths16.excepsV[m].last < c) { + a = m; + } else if (c < widths16.excepsV[m].first) { + b = m; + } else { + h = widths16.excepsV[m].height; + break; + } + } + return h; +} + +double GfxFont::getOriginX16(int c) { + double vx; + int a, b, m; + + vx = widths16.defWidth / 2; + a = -1; + b = widths16.numExcepsV; + // invariant: widths16.excepsV[a].last < c < widths16.excepsV[b].first + while (b - a > 1) { + m = (a + b) / 2; + if (widths16.excepsV[m].last < c) { + a = m; + } else if (c < widths16.excepsV[m].first) { + b = m; + } else { + vx = widths16.excepsV[m].vx; + break; + } + } + return vx; +} + +double GfxFont::getOriginY16(int c) { + double vy; + int a, b, m; + + vy = widths16.defVY; + a = -1; + b = widths16.numExcepsV; + // invariant: widths16.excepsV[a].last < c < widths16.excepsV[b].first + while (b - a > 1) { + m = (a + b) / 2; + if (widths16.excepsV[m].last < c) { + a = m; + } else if (c < widths16.excepsV[m].first) { + b = m; + } else { + vy = widths16.excepsV[m].vy; + break; + } + } + return vy; +} + +Object *GfxFont::getCharProc(int code, Object *proc) { + if (charProcs.isDict()) { + charProcs.dictLookup(encoding->getCharName(code), proc); + } else { + proc->initNull(); + } + return proc; +} + +void GfxFont::getEncAndWidths(Dict *fontDict, BuiltinFont *builtinFont, + int missingWidth) { + Object obj1, obj2, obj3; + char *buf; + int len; + FontFile *fontFile; + int code, i; + + // Encodings start with a base encoding, which can come from + // (in order of priority): + // 1. FontDict.Encoding or FontDict.Encoding.BaseEncoding + // - MacRoman / WinAnsi / Standard + // 2. embedded font file + // 3. default: + // - builtin --> builtin encoding + // - TrueType --> MacRomanEncoding + // - others --> StandardEncoding + // and then add a list of differences from + // FontDict.Encoding.Differences. + + // check FontDict for base encoding + encoding = NULL; + fontDict->lookup("Encoding", &obj1); + if (obj1.isDict()) { + obj1.dictLookup("BaseEncoding", &obj2); + if (obj2.isName("MacRomanEncoding")) { + encoding = macRomanEncoding.copy(); + } else if (obj2.isName("WinAnsiEncoding")) { + encoding = winAnsiEncoding.copy(); + } else if (obj2.isName("StandardEncoding")) { + encoding = standardEncoding.copy(); + } + obj2.free(); + } else if (obj1.isName("MacRomanEncoding")) { + encoding = macRomanEncoding.copy(); + } else if (obj1.isName("WinAnsiEncoding")) { + encoding = winAnsiEncoding.copy(); + } else if (obj1.isName("StandardEncoding")) { + encoding = standardEncoding.copy(); + } + obj1.free(); + + // check embedded or external font file for base encoding + if ((type == fontType1 || type == fontType1C) && + (extFontFile || embFontID.num >= 0)) { + if (extFontFile) + buf = readExtFontFile(&len); + else + buf = readEmbFontFile(&len); + if (buf) { + if (type == fontType1) + fontFile = new Type1FontFile(buf, len); + else + fontFile = new Type1CFontFile(buf, len); + if (fontFile->getName()) { + if (embFontName) + delete embFontName; + embFontName = new GString(fontFile->getName()); + } + if (!encoding) + encoding = fontFile->getEncoding(gTrue); + delete fontFile; + gfree(buf); + } + } + + // get default base encoding + if (!encoding) { + if (builtinFont) + encoding = builtinFont->encoding->copy(); + else if (type == fontTrueType) + encoding = macRomanEncoding.copy(); + else + encoding = standardEncoding.copy(); + } + + // merge differences into encoding + fontDict->lookup("Encoding", &obj1); + if (obj1.isDict()) { + obj1.dictLookup("Differences", &obj2); + if (obj2.isArray()) { + code = 0; + for (i = 0; i < obj2.arrayGetLength(); ++i) { + obj2.arrayGet(i, &obj3); + if (obj3.isInt()) { + code = obj3.getInt(); + } else if (obj3.isName()) { + if (code < 256) + encoding->addChar(code, copyString(obj3.getName())); + ++code; + } else { + error(-1, "Wrong type in font encoding resource differences (%s)", + obj3.getTypeName()); + } + obj3.free(); + } + } + obj2.free(); + } + obj1.free(); + + // get character widths + if (builtinFont) + makeWidths(fontDict, builtinFont->encoding, builtinFont->widths, + missingWidth); + else + makeWidths(fontDict, NULL, NULL, missingWidth); +} + +void GfxFont::findExtFontFile() { + char **path; + FILE *f; + + for (path = fontPath; *path; ++path) { + extFontFile = appendToPath(new GString(*path), name->getCString()); + f = fopen(extFontFile->getCString(), "rb"); + if (!f) { + extFontFile->append(".pfb"); + f = fopen(extFontFile->getCString(), "rb"); + } + if (!f) { + extFontFile->del(extFontFile->getLength() - 4, 4); + extFontFile->append(".pfa"); + f = fopen(extFontFile->getCString(), "rb"); + } + if (f) { + fclose(f); + break; + } + delete extFontFile; + extFontFile = NULL; + } +} + +char *GfxFont::readExtFontFile(int *len) { + FILE *f; + char *buf; + + if (!(f = fopen(extFontFile->getCString(), "rb"))) { + error(-1, "Internal: external font file '%s' vanished", extFontFile); + return NULL; + } + fseek(f, 0, SEEK_END); + *len = (int)ftell(f); + fseek(f, 0, SEEK_SET); + buf = (char *)gmalloc(*len); + if ((int)fread(buf, 1, *len, f) != *len) + error(-1, "Error reading external font file '%s'", extFontFile); + fclose(f); + return buf; +} + +char *GfxFont::readEmbFontFile(int *len) { + char *buf; + Object obj1, obj2; + Stream *str; + int c; + int size, i; + + obj1.initRef(embFontID.num, embFontID.gen); + obj1.fetch(&obj2); + if (!obj2.isStream()) { + error(-1, "Embedded font file is not a stream"); + obj2.free(); + obj1.free(); + embFontID.num = -1; + return NULL; + } + str = obj2.getStream(); + + buf = NULL; + i = size = 0; + str->reset(); + while ((c = str->getChar()) != EOF) { + if (i == size) { + size += 4096; + buf = (char *)grealloc(buf, size); + } + buf[i++] = c; + } + *len = i; + + obj2.free(); + obj1.free(); + + return buf; +} + +void GfxFont::makeWidths(Dict *fontDict, FontEncoding *builtinEncoding, + Gushort *builtinWidths, int missingWidth) { + Object obj1, obj2; + int firstChar, lastChar; + int code, code2; + char *charName; + Gushort *defWidths; + int index; + double mult; + + // initialize all widths + for (code = 0; code < 256; ++code) { + widths[code] = missingWidth * 0.001; + } + + // use widths from built-in font + if (builtinEncoding) { + code2 = 0; // to make gcc happy + for (code = 0; code < 256; ++code) { + if ((charName = encoding->getCharName(code)) && + (code2 = builtinEncoding->getCharCode(charName)) >= 0) + widths[code] = builtinWidths[code2] * 0.001; + } + + // get widths from font dict + } else { + fontDict->lookup("FirstChar", &obj1); + firstChar = obj1.isInt() ? obj1.getInt() : 0; + obj1.free(); + fontDict->lookup("LastChar", &obj1); + lastChar = obj1.isInt() ? obj1.getInt() : 255; + obj1.free(); + if (type == fontType3) + mult = fontMat[0]; + else + mult = 0.001; + fontDict->lookup("Widths", &obj1); + if (obj1.isArray()) { + for (code = firstChar; code <= lastChar; ++code) { + obj1.arrayGet(code - firstChar, &obj2); + if (obj2.isNum()) + widths[code] = obj2.getNum() * mult; + obj2.free(); + } + } else { + + // couldn't find widths -- use defaults +#if 0 //~ + //~ certain PDF generators apparently don't include widths + //~ for Arial and TimesNewRoman -- and this error message + //~ is a nuisance + error(-1, "No character widths resource for non-builtin font"); +#endif + if (isFixedWidth()) + index = 0; + else if (isSerif()) + index = 8; + else + index = 4; + if (isBold()) + index += 2; + if (isItalic()) + index += 1; + defWidths = defCharWidths[index]; + code2 = 0; // to make gcc happy + for (code = 0; code < 256; ++code) { + if ((charName = encoding->getCharName(code)) && + (code2 = standardEncoding.getCharCode(charName)) >= 0) + widths[code] = defWidths[code2] * 0.001; + } + } + obj1.free(); + } +} + +void GfxFont::getType0EncAndWidths(Dict *fontDict) { + Object obj1, obj2, obj3, obj4, obj5, obj6, obj7, obj8; + int excepsSize; + int i, j, k, n; + + widths16.exceps = NULL; + widths16.excepsV = NULL; + + // get the CIDFont + fontDict->lookup("DescendantFonts", &obj1); + if (!obj1.isArray() || obj1.arrayGetLength() != 1) { + error(-1, "Bad DescendantFonts entry for Type 0 font"); + goto err1; + } + obj1.arrayGet(0, &obj2); + if (!obj2.isDict()) { + error(-1, "Bad descendant font of Type 0 font"); + goto err2; + } + + // get font info + obj2.dictLookup("CIDSystemInfo", &obj3); + if (!obj3.isDict()) { + error(-1, "Bad CIDSystemInfo in Type 0 font descendant"); + goto err3; + } + obj3.dictLookup("Registry", &obj4); + obj3.dictLookup("Ordering", &obj5); + if (obj4.isString() && obj5.isString()) { + if (obj4.getString()->cmp("Adobe") == 0 && + obj5.getString()->cmp("Japan1") == 0) { +#if JAPANESE_SUPPORT + is16 = gTrue; + enc16.charSet = font16AdobeJapan12; +#else + error(-1, "Xpdf was compiled without Japanese font support"); + goto err4; +#endif + } else if (obj4.getString()->cmp("Adobe") == 0 && + obj5.getString()->cmp("GB1") == 0) { +#if CHINESE_SUPPORT + is16 = gTrue; + enc16.charSet = font16AdobeGB12; +#else + error(-1, "Xpdf was compiled without Chinese font support"); + goto err4; +#endif + } else { + error(-1, "Uknown Type 0 character set: %s-%s", + obj4.getString()->getCString(), obj5.getString()->getCString()); + goto err4; + } + } else { + error(-1, "Unknown Type 0 character set"); + goto err4; + } + obj5.free(); + obj4.free(); + obj3.free(); + + // get default char width + obj2.dictLookup("DW", &obj3); + if (obj3.isInt()) + widths16.defWidth = obj3.getInt() * 0.001; + else + widths16.defWidth = 1.0; + obj3.free(); + + // get default char metrics for vertical font + obj2.dictLookup("DW2", &obj3); + widths16.defVY = 0.880; + widths16.defHeight = -1; + if (obj3.isArray() && obj3.arrayGetLength() == 2) { + obj3.arrayGet(0, &obj4); + if (obj4.isInt()) { + widths16.defVY = obj4.getInt() * 0.001; + } + obj4.free(); + obj3.arrayGet(1, &obj4); + if (obj4.isInt()) { + widths16.defHeight = obj4.getInt() * 0.001; + } + obj4.free(); + } + obj3.free(); + + // get char width exceptions + widths16.exceps = NULL; + widths16.numExceps = 0; + obj2.dictLookup("W", &obj3); + if (obj3.isArray()) { + excepsSize = 0; + k = 0; + i = 0; + while (i+1 < obj3.arrayGetLength()) { + obj3.arrayGet(i, &obj4); + obj3.arrayGet(i+1, &obj5); + if (obj4.isInt() && obj5.isInt()) { + obj3.arrayGet(i+2, &obj6); + if (!obj6.isNum()) { + error(-1, "Bad widths array in Type 0 font"); + obj6.free(); + obj5.free(); + obj4.free(); + break; + } + if (k == excepsSize) { + excepsSize += 16; + widths16.exceps = (GfxFontWidthExcep *) + grealloc(widths16.exceps, + excepsSize * sizeof(GfxFontWidthExcep)); + } + widths16.exceps[k].first = obj4.getInt(); + widths16.exceps[k].last = obj5.getInt(); + widths16.exceps[k].width = obj6.getNum() * 0.001; + obj6.free(); + ++k; + i += 3; + } else if (obj4.isInt() && obj5.isArray()) { + if (k + obj5.arrayGetLength() >= excepsSize) { + excepsSize = (k + obj5.arrayGetLength() + 15) & ~15; + widths16.exceps = (GfxFontWidthExcep *) + grealloc(widths16.exceps, + excepsSize * sizeof(GfxFontWidthExcep)); + } + n = obj4.getInt(); + for (j = 0; j < obj5.arrayGetLength(); ++j) { + obj5.arrayGet(j, &obj6); + if (!obj6.isNum()) { + error(-1, "Bad widths array in Type 0 font"); + obj6.free(); + break; + } + widths16.exceps[k].first = widths16.exceps[k].last = n++; + widths16.exceps[k].width = obj6.getNum() * 0.001; + obj6.free(); + ++k; + } + i += 2; + } else { + error(-1, "Bad widths array in Type 0 font"); + obj6.free(); + obj5.free(); + obj4.free(); + break; + } + obj5.free(); + obj4.free(); + } + widths16.numExceps = k; + if (k > 0) + qsort(widths16.exceps, k, sizeof(GfxFontWidthExcep), &cmpWidthExcep); + } + obj3.free(); + + // get char metric exceptions for vertical font + widths16.excepsV = NULL; + widths16.numExcepsV = 0; + obj2.dictLookup("W2", &obj3); + if (obj3.isArray()) { + excepsSize = 0; + k = 0; + i = 0; + while (i+1 < obj3.arrayGetLength()) { + obj3.arrayGet(i, &obj4); + obj3.arrayGet(i+1, &obj5); + if (obj4.isInt() && obj5.isInt()) { + obj3.arrayGet(i+2, &obj6); + obj3.arrayGet(i+3, &obj7); + obj3.arrayGet(i+4, &obj8); + if (!obj6.isNum() || !obj7.isNum() || !obj8.isNum()) { + error(-1, "Bad widths (W2) array in Type 0 font"); + obj8.free(); + obj7.free(); + obj6.free(); + obj5.free(); + obj4.free(); + break; + } + if (k == excepsSize) { + excepsSize += 16; + widths16.excepsV = (GfxFontWidthExcepV *) + grealloc(widths16.excepsV, + excepsSize * sizeof(GfxFontWidthExcepV)); + } + widths16.excepsV[k].first = obj4.getInt(); + widths16.excepsV[k].last = obj5.getInt(); + widths16.excepsV[k].height = obj6.getNum() * 0.001; + widths16.excepsV[k].vx = obj7.getNum() * 0.001; + widths16.excepsV[k].vy = obj8.getNum() * 0.001; + obj8.free(); + obj7.free(); + obj6.free(); + ++k; + i += 5; + } else if (obj4.isInt() && obj5.isArray()) { + if (k + obj5.arrayGetLength() / 3 >= excepsSize) { + excepsSize = (k + obj5.arrayGetLength() / 3 + 15) & ~15; + widths16.excepsV = (GfxFontWidthExcepV *) + grealloc(widths16.excepsV, + excepsSize * sizeof(GfxFontWidthExcepV)); + } + n = obj4.getInt(); + for (j = 0; j < obj5.arrayGetLength(); j += 3) { + obj5.arrayGet(j, &obj6); + obj5.arrayGet(j+1, &obj7); + obj5.arrayGet(j+1, &obj8); + if (!obj6.isNum() || !obj7.isNum() || !obj8.isNum()) { + error(-1, "Bad widths (W2) array in Type 0 font"); + obj6.free(); + break; + } + widths16.excepsV[k].first = widths16.exceps[k].last = n++; + widths16.excepsV[k].height = obj6.getNum() * 0.001; + widths16.excepsV[k].vx = obj7.getNum() * 0.001; + widths16.excepsV[k].vy = obj8.getNum() * 0.001; + obj8.free(); + obj7.free(); + obj6.free(); + ++k; + } + i += 2; + } else { + error(-1, "Bad widths array in Type 0 font"); + obj5.free(); + obj4.free(); + break; + } + obj5.free(); + obj4.free(); + } + widths16.numExcepsV = k; + if (k > 0) { + qsort(widths16.excepsV, k, sizeof(GfxFontWidthExcepV), &cmpWidthExcepV); + } + } + obj3.free(); + + obj2.free(); + obj1.free(); + + // get encoding (CMap) + fontDict->lookup("Encoding", &obj1); + if (!obj1.isName()) { + error(-1, "Bad encoding for Type 0 font"); + goto err1; + } +#if JAPANESE_SUPPORT + if (enc16.charSet == font16AdobeJapan12) { + for (i = 0; gfxJapan12Tab[i].name; ++i) { + if (!strcmp(obj1.getName(), gfxJapan12Tab[i].name)) + break; + } + if (!gfxJapan12Tab[i].name) { + error(-1, "Unknown encoding '%s' for Adobe-Japan1-2 font", + obj1.getName()); + goto err1; + } + enc16.enc = gfxJapan12Tab[i].enc; + } +#endif +#if CHINESE_SUPPORT + if (enc16.charSet == font16AdobeGB12) { + for (i = 0; gfxGB12Tab[i].name; ++i) { + if (!strcmp(obj1.getName(), gfxGB12Tab[i].name)) + break; + } + if (!gfxGB12Tab[i].name) { + error(-1, "Unknown encoding '%s' for Adobe-GB1-2 font", + obj1.getName()); + goto err1; + } + enc16.enc = gfxGB12Tab[i].enc; + } +#endif + obj1.free(); + + return; + + err4: + obj5.free(); + obj4.free(); + err3: + obj3.free(); + err2: + obj2.free(); + err1: + obj1.free(); + //~ fix this --> add 16-bit font support to FontFile + encoding = new FontEncoding(); + makeWidths(fontDict, NULL, NULL, 0); +} + +static int CDECL cmpWidthExcep(const void *w1, const void *w2) { + return ((GfxFontWidthExcep *)w1)->first - ((GfxFontWidthExcep *)w2)->first; +} + +static int CDECL cmpWidthExcepV(const void *w1, const void *w2) { + return ((GfxFontWidthExcepV *)w1)->first - ((GfxFontWidthExcepV *)w2)->first; +} + +//------------------------------------------------------------------------ +// GfxFontDict +//------------------------------------------------------------------------ + +GfxFontDict::GfxFontDict(Dict *fontDict) { + int i; + Object obj1, obj2; + + numFonts = fontDict->getLength(); + fonts = (GfxFont **)gmalloc(numFonts * sizeof(GfxFont *)); + for (i = 0; i < numFonts; ++i) { + fontDict->getValNF(i, &obj1); + obj1.fetch(&obj2); + if (obj1.isRef() && obj2.isDict()) { + fonts[i] = new GfxFont(fontDict->getKey(i), obj1.getRef(), + obj2.getDict()); + } else { + error(-1, "font resource is not a dictionary"); + fonts[i] = NULL; + } + obj1.free(); + obj2.free(); + } +} + +GfxFontDict::~GfxFontDict() { + int i; + + for (i = 0; i < numFonts; ++i) + delete fonts[i]; + gfree(fonts); +} + +GfxFont *GfxFontDict::lookup(char *tag) { + int i; + + for (i = 0; i < numFonts; ++i) { + if (fonts[i]->matches(tag)) + return fonts[i]; + } + return NULL; +} diff --git a/pdftops/GfxFont.h b/pdftops/GfxFont.h new file mode 100644 index 0000000000..524a8ad535 --- /dev/null +++ b/pdftops/GfxFont.h @@ -0,0 +1,239 @@ +//======================================================================== +// +// GfxFont.h +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#ifndef GFXFONT_H +#define GFXFONT_H + +#ifdef __GNUC__ +#pragma interface +#endif + +#include "gtypes.h" +#include "GString.h" +#include "Object.h" +#include "FontEncoding.h" + +class Dict; +struct BuiltinFont; + +//------------------------------------------------------------------------ +// GfxFontCharSet16 +//------------------------------------------------------------------------ + +enum GfxFontCharSet16 { + font16AdobeJapan12, // Adobe-Japan1-2 + font16AdobeGB12 // Adobe-GB1-2 (Chinese) +}; + +//------------------------------------------------------------------------ +// GfxFontEncoding16 +//------------------------------------------------------------------------ + +struct GfxFontEncoding16 { + int wMode; // writing mode (0=horizontal, 1=vertical) + Guchar codeLen[256]; // length of codes, in bytes, indexed by + // first byte of code + Gushort map1[256]; // one-byte code mapping: + // map1[code] --> 16-bit char selector + Gushort *map2; // two-byte code mapping + // map2[2*i] --> first code in range + // map2[2*i+1] --> 16-bit char selector + // for map2[2*i] + int map2Len; // length of map2 array (divided by 2) +}; + +//------------------------------------------------------------------------ +// GfxFontWidths16 +//------------------------------------------------------------------------ + +struct GfxFontWidthExcep { + int first; // this record applies to + int last; // chars .. + double width; // char width +}; + +struct GfxFontWidthExcepV { + int first; // this record applies to + int last; // chars .. + double height; // char height + double vx, vy; // origin position +}; + +struct GfxFontWidths16 { + double defWidth; // default char width + double defHeight; // default char height + double defVY; // default origin position + GfxFontWidthExcep *exceps; // exceptions + int numExceps; // number of valid entries in exceps + GfxFontWidthExcepV *excepsV; // exceptions for vertical font + int numExcepsV; // number of valid entries in excepsV +}; + +//------------------------------------------------------------------------ +// GfxFont +//------------------------------------------------------------------------ + +#define fontFixedWidth (1 << 0) +#define fontSerif (1 << 1) +#define fontSymbolic (1 << 2) +#define fontItalic (1 << 6) +#define fontBold (1 << 18) + +enum GfxFontType { + fontUnknownType, + fontType1, + fontType1C, + fontType3, + fontTrueType, + fontType0 +}; + +class GfxFont { +public: + + // Constructor. + GfxFont(char *tag1, Ref id1, Dict *fontDict); + + // Destructor. + ~GfxFont(); + + // Get font tag. + GString *getTag() { return tag; } + + // Get font dictionary ID. + Ref getID() { return id; } + + // Does this font match the tag? + GBool matches(char *tag1) { return !tag->cmp(tag1); } + + // Get base font name. + GString *getName() { return name; } + + // Get font type. + GfxFontType getType() { return type; } + + // Does this font use 16-bit characters? + GBool is16Bit() { return is16; } + + // Get embedded font ID, i.e., a ref for the font file stream. + // Returns false if there is no embedded font. + GBool getEmbeddedFontID(Ref *embID) + { *embID = embFontID; return embFontID.num >= 0; } + + // Get the PostScript font name for the embedded font. Returns + // NULL if there is no embedded font. + char *getEmbeddedFontName() + { return embFontName ? embFontName->getCString() : (char *)NULL; } + + // Get the name of the external font file. Returns NULL if there + // is no external font file. + GString *getExtFontFile() { return extFontFile; } + + // Get font descriptor flags. + GBool isFixedWidth() { return flags & fontFixedWidth; } + GBool isSerif() { return flags & fontSerif; } + GBool isSymbolic() { return flags & fontSymbolic; } + GBool isItalic() { return flags & fontItalic; } + GBool isBold() { return flags & fontBold; } + + // Get width of a character or string. + double getWidth(Guchar c) { return widths[c]; } + double getWidth(GString *s); + + // Get character metrics for 16-bit font. + double getWidth16(int c); + double getHeight16(int c); + double getOriginX16(int c); + double getOriginY16(int c); + + // Return the encoding. + FontEncoding *getEncoding() { return encoding; } + + // Return the character name associated with . + char *getCharName(int code) { return encoding->getCharName(code); } + + // Return the code associated with . + int getCharCode(char *charName) { return encoding->getCharCode(charName); } + + // Return the Type 3 CharProc for the character associated with . + Object *getCharProc(int code, Object *proc); + + // Return the 16-bit character set and encoding. + GfxFontCharSet16 getCharSet16() { return enc16.charSet; } + GfxFontEncoding16 *getEncoding16() { return enc16.enc; } + + // Get the writing mode (0=horizontal, 1=vertical). + int getWMode16() { return enc16.enc->wMode; } + + // Return the font matrix. + double *getFontMatrix() { return fontMat; } + + // Read an external or embedded font file into a buffer. + char *readExtFontFile(int *len); + char *readEmbFontFile(int *len); + +private: + + void getEncAndWidths(Dict *fontDict, BuiltinFont *builtinFont, + int missingWidth); + void findExtFontFile(); + void makeWidths(Dict *fontDict, FontEncoding *builtinEncoding, + Gushort *builtinWidths, int missingWidth); + void getType0EncAndWidths(Dict *fontDict); + + GString *tag; // PDF font tag + Ref id; // reference (used as unique ID) + GString *name; // font name + int flags; // font descriptor flags + GfxFontType type; // type of font + GBool is16; // set if font uses 16-bit chars + GString *embFontName; // name of embedded font + Ref embFontID; // ref to embedded font file stream + GString *extFontFile; // external font file name + Object charProcs; // Type3 CharProcs dictionary + double fontMat[6]; // font matrix + union { + FontEncoding *encoding; // 8-bit font encoding + struct { + GfxFontCharSet16 charSet; // 16-bit character set + GfxFontEncoding16 *enc; // 16-bit encoding (CMap) + } enc16; + }; + union { + double widths[256]; // width of each char for 8-bit font + GfxFontWidths16 widths16; // char widths for 16-bit font + }; +}; + +//------------------------------------------------------------------------ +// GfxFontDict +//------------------------------------------------------------------------ + +class GfxFontDict { +public: + + // Build the font dictionary, given the PDF font dictionary. + GfxFontDict(Dict *fontDict); + + // Destructor. + ~GfxFontDict(); + + // Get the specified font. + GfxFont *lookup(char *tag); + + // Iterative access. + int getNumFonts() { return numFonts; } + GfxFont *getFont(int i) { return fonts[i]; } + +private: + + GfxFont **fonts; // list of fonts + int numFonts; // number of fonts +}; + +#endif diff --git a/pdftops/GfxState.cxx b/pdftops/GfxState.cxx new file mode 100644 index 0000000000..0d191eaa0d --- /dev/null +++ b/pdftops/GfxState.cxx @@ -0,0 +1,1220 @@ +//======================================================================== +// +// GfxState.cc +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include +#include +#include // for memcpy() +#include "gmem.h" +#include "Error.h" +#include "Object.h" +#include "GfxState.h" + +//------------------------------------------------------------------------ +// GfxColor +//------------------------------------------------------------------------ + +void GfxColor::setGray(double gray) { + if (gray < 0) { + r = g = b = 0; + } else if (gray > 1) { + r = g = b = 1; + } else { + r = g = b = gray; + } +} + +void GfxColor::setCMYK(double c, double m, double y, double k) { + if ((r = 1 - (c + k)) < 0) { + r = 0; + } else if (r > 1) { + r = 1; + } + if ((g = 1 - (m + k)) < 0) { + g = 0; + } else if (g > 1) { + g = 1; + } + if ((b = 1 - (y + k)) < 0) { + b = 0; + } else if (b > 1) { + b = 1; + } +} + +void GfxColor::setRGB(double r1, double g1, double b1) { + if (r1 < 0) { + r = 0; + } else if (r1 > 1) { + r = 1; + } else { + r = r1; + } + if (g1 < 0) { + g = 0; + } else if (g1 > 1) { + g = 1; + } else { + g = g1; + } + if (b1 < 0) { + b = 0; + } else if (b1 > 1) { + b = 1; + } else { + b = b1; + } +} + +// Handle colors in the L*a*b* color space. +void GfxColor::setLab(double L, double a, double bb, LabParams *params) { + double X, Y, Z; + double t1, t2; + + // convert L*a*b* to CIE 1931 XYZ color space + // (This ignores the white point parameter, because I don't + // understand exactly how it should work.) + t1 = (L + 16) / 116; + t2 = t1 + a / 500; + if (t2 >= (6.0 / 29.0)) { + X = t2 * t2 * t2; + } else { + X = (108.0 / 841.0) * (t2 - (4.0 / 29.0)); + } +#if 0 //~ + X *= params->whiteX; +#endif + if (t1 >= (6.0 / 29.0)) { + Y = t1 * t1 * t1; + } else { + Y = (108.0 / 841.0) * (t1 - (4.0 / 29.0)); + } +#if 0 //~ + Y *= params->whiteY; +#endif + t2 = t1 - bb / 200; + if (t2 >= (6.0 / 29.0)) { + Z = t2 * t2 * t2; + } else { + Z = (108.0 / 841.0) * (t2 - (4.0 / 29.0)); + } +#if 0 //~ + Z *= params->whiteZ; +#endif + + // convert XYZ to RGB +#if 0 //~ + X *= 0.9505; + Z *= 1.0890; +#endif + r = 3.240479 * X - 1.537150 * Y - 0.498535 * Z; + g = -0.969256 * X + 1.875992 * Y + 0.041556 * Z; + b = 0.055648 * X - 0.204043 * Y + 1.057311 * Z; + + // clip RGB + if (r < 0) { + r = 0; + } else if (r > 1) { + r = 1; + } + if (g < 0) { + g = 0; + } else if (g > 1) { + g = 1; + } + if (b < 0) { + b = 0; + } else if (b > 1) { + b = 1; + } +} + +//------------------------------------------------------------------------ +// GfxColorSpace +//------------------------------------------------------------------------ + +GfxColorSpace::GfxColorSpace(Object *colorSpace) { + Object csObj; + Object obj, obj2, obj3; + Dict *dict; + char *s; + int x; + int i, j; + + ok = gTrue; + lookup = NULL; + + // check for Separation, DeviceN, ICCBased, and Pattern colorspaces + colorSpace->copy(&csObj); + sepFunc = NULL; + if (colorSpace->isArray()) { + colorSpace->arrayGet(0, &obj); + if (obj.isName("Separation") || obj.isName("DeviceN")) { + csObj.free(); + colorSpace->arrayGet(2, &csObj); + sepFunc = new Function(colorSpace->arrayGet(3, &obj2)); + obj2.free(); + if (!sepFunc->isOk()) { + delete sepFunc; + sepFunc = NULL; + } + } else if (obj.isName("ICCBased")) { + colorSpace->arrayGet(1, &obj2); + if (obj2.isStream()) { + if ((dict = obj2.streamGetDict())) { + dict->lookup("Alternate", &obj3); + if (!obj3.isNull()) { + csObj.free(); + csObj = obj3; + } else { + obj3.free(); + dict->lookup("N", &obj3); + if (!obj3.isNull()) { + csObj.free(); + if (obj3.getInt() == 4) { + csObj.initName("DeviceCMYK"); + } else if (obj3.getInt() == 3) { + csObj.initName("DeviceRGB"); + } else { + csObj.initName("DeviceGray"); + } + } + obj3.free(); + } + } + } + obj2.free(); + } else if (obj.isName("Pattern")) { + csObj.free(); + colorSpace->arrayGet(1, &csObj); + } + obj.free(); + } + + // get mode + indexed = gFalse; + if (csObj.isName()) { + setMode(&csObj); + } else if (csObj.isArray()) { + csObj.arrayGet(0, &obj); + if (obj.isName("Indexed") || obj.isName("I")) { + indexed = gTrue; + setMode(csObj.arrayGet(1, &obj2)); + obj2.free(); + } else { + setMode(&csObj); + } + obj.free(); + } else { + goto err1; + } + if (!ok) { + goto err1; + } + + // get lookup table for indexed colorspace + if (indexed) { + csObj.arrayGet(2, &obj); + if (!obj.isInt()) + goto err2; + indexHigh = obj.getInt(); + obj.free(); + lookup = (Guchar (*)[4])gmalloc((indexHigh + 1) * 4 * sizeof(Guchar)); + csObj.arrayGet(3, &obj); + if (obj.isStream()) { + obj.streamReset(); + for (i = 0; i <= indexHigh; ++i) { + for (j = 0; j < numComps; ++j) { + if ((x = obj.streamGetChar()) == EOF) + goto err2; + lookup[i][j] = (Guchar)x; + } + } + } else if (obj.isString()) { + s = obj.getString()->getCString(); + for (i = 0; i <= indexHigh; ++i) + for (j = 0; j < numComps; ++j) + lookup[i][j] = (Guchar)*s++; + } else { + goto err2; + } + obj.free(); + } + + csObj.free(); + return; + + err2: + obj.free(); + err1: + csObj.free(); + ok = gFalse; +} + +GfxColorSpace::GfxColorSpace(GfxColorMode mode1) { + sepFunc = NULL; + mode = mode1; + indexed = gFalse; + switch (mode) { + case colorGray: numComps = 1; break; + case colorCMYK: numComps = 4; break; + case colorRGB: numComps = 3; break; + case colorLab: numComps = 3; break; + } + lookup = NULL; + ok = gTrue; +} + +GfxColorSpace::~GfxColorSpace() { + if (sepFunc) + delete sepFunc; + gfree(lookup); +} + +GfxColorSpace::GfxColorSpace(GfxColorSpace *colorSpace) { + int size; + + if (colorSpace->sepFunc) + sepFunc = colorSpace->sepFunc->copy(); + else + sepFunc = NULL; + mode = colorSpace->mode; + indexed = colorSpace->indexed; + numComps = colorSpace->numComps; + indexHigh = colorSpace->indexHigh; + if (indexed) { + size = (indexHigh + 1) * 4 * sizeof(Guchar); + lookup = (Guchar (*)[4])gmalloc(size); + memcpy(lookup, colorSpace->lookup, size); + } else { + lookup = NULL; + } + ok = gTrue; +} + +void GfxColorSpace::setMode(Object *colorSpace) { + Object obj1, obj2, obj3, obj4; + + if (colorSpace->isName("DeviceGray") || colorSpace->isName("G")) { + mode = colorGray; + numComps = 1; + } else if (colorSpace->isName("DeviceRGB") || colorSpace->isName("RGB")) { + mode = colorRGB; + numComps = 3; + } else if (colorSpace->isName("DeviceCMYK") || colorSpace->isName("CMYK")) { + mode = colorCMYK; + numComps = 4; + } else if (colorSpace->isArray()) { + colorSpace->arrayGet(0, &obj1); + if (obj1.isName("CalGray")) { + mode = colorGray; + numComps = 1; + } else if (obj1.isName("CalRGB")) { + mode = colorRGB; + numComps = 3; + } else if (obj1.isName("CalCMYK")) { + mode = colorCMYK; + numComps = 4; + } else if (obj1.isName("Lab")) { + mode = colorLab; + numComps = 3; + labParams.whiteX = 0.9505; + labParams.whiteY = 1; + labParams.whiteZ = 1.0890; + labParams.aMin = -100; + labParams.aMax = 100; + labParams.bMin = -100; + labParams.bMax = 100; + colorSpace->arrayGet(1, &obj2); + if (obj2.isDict()) { + obj2.dictLookup("WhitePoint", &obj3); + if (obj3.isArray() && obj3.arrayGetLength() == 3) { + obj3.arrayGet(0, &obj4); + if (obj4.isNum()) { + labParams.whiteX = obj4.getNum(); + } + obj4.free(); + obj3.arrayGet(1, &obj4); + if (obj4.isNum()) { + labParams.whiteY = obj4.getNum(); + } + obj4.free(); + obj3.arrayGet(2, &obj4); + if (obj4.isNum()) { + labParams.whiteZ = obj4.getNum(); + } + obj4.free(); + } + obj3.free(); + obj2.dictLookup("Range", &obj3); + if (obj3.isArray() && obj3.arrayGetLength() == 4) { + obj3.arrayGet(0, &obj4); + if (obj4.isNum()) { + labParams.aMin = obj4.getNum(); + } + obj4.free(); + obj3.arrayGet(1, &obj4); + if (obj4.isNum()) { + labParams.aMax = obj4.getNum(); + } + obj4.free(); + obj3.arrayGet(2, &obj4); + if (obj4.isNum()) { + labParams.bMin = obj4.getNum(); + } + obj4.free(); + obj3.arrayGet(3, &obj4); + if (obj4.isNum()) { + labParams.bMax = obj4.getNum(); + } + obj4.free(); + } + obj3.free(); + } + obj2.free(); + } else { + ok = gFalse; + } + obj1.free(); + } else { + ok = gFalse; + } +} + +void GfxColorSpace::getDefaultRanges(double *decodeLow, double *decodeRange, + int maxPixel) { + int i; + + if (indexed) { + decodeLow[0] = 0; + decodeRange[0] = maxPixel; + } else if (mode == colorLab) { + decodeLow[0] = 0; + decodeRange[0] = 100; + decodeLow[1] = labParams.aMin; + decodeRange[1] = labParams.aMax - labParams.aMin; + decodeLow[2] = labParams.bMin; + decodeRange[2] = labParams.bMax - labParams.bMin; + } else { + for (i = 0; i < numComps; ++i) { + decodeLow[i] = 0; + decodeRange[i] = 1; + } + } +} + +void GfxColorSpace::getColor(double x[4], GfxColor *color) { + double y[4]; + Guchar *p; + + if (sepFunc) { + sepFunc->transform(x, y); + } else { + y[0] = x[0]; + y[1] = x[1]; + y[2] = x[2]; + y[3] = x[3]; + } + if (indexed) { + p = lookup[(int)(y[0] + 0.5)]; + switch (mode) { + case colorGray: + color->setGray(p[0] / 255.0); + break; + case colorCMYK: + color->setCMYK(p[0] / 255.0, p[1] / 255.0, p[2] / 255.0, p[3] / 255.0); + break; + case colorRGB: + color->setRGB(p[0] / 255.0, p[1] / 255.0, p[2] / 255.0); + break; + case colorLab: + color->setLab(p[0] / 255.0, p[1] / 255.0, p[2] / 255.0, &labParams); + break; + } + } else { + switch (mode) { + case colorGray: + color->setGray(y[0]); + break; + case colorCMYK: + color->setCMYK(y[0], y[1], y[2], y[3]); + break; + case colorRGB: + color->setRGB(y[0], y[1], y[2]); + break; + case colorLab: + color->setLab(y[0], y[1], y[2], &labParams); + break; + } + } +} + +//------------------------------------------------------------------------ +// Function +//------------------------------------------------------------------------ + +Function::Function(Object *funcObj) { + Stream *str; + Dict *dict; + int nSamples, sampleBits; + double sampleMul; + Object obj1, obj2; + Guint buf, bitMask; + int bits; + int s; + int i; + + ok = gFalse; + samples = NULL; + + if (!funcObj->isStream()) { + error(-1, "Expected function dictionary"); + goto err3; + } + str = funcObj->getStream(); + dict = str->getDict(); + + //----- FunctionType + if (!dict->lookup("FunctionType", &obj1)->isInt() || + obj1.getInt() != 0) { + error(-1, "Unknown function type"); + goto err2; + } + obj1.free(); + + //----- Domain + if (!dict->lookup("Domain", &obj1)->isArray()) { + error(-1, "Function is missing domain"); + goto err2; + } + m = obj1.arrayGetLength() / 2; + if (m > 1) { + error(-1, "Functions with more than 1 input are unsupported"); + goto err2; + } + for (i = 0; i < m; ++i) { + obj1.arrayGet(2*i, &obj2); + if (!obj2.isNum()) { + error(-1, "Illegal value in function domain array"); + goto err1; + } + domain[i][0] = obj2.getNum(); + obj2.free(); + obj1.arrayGet(2*i+1, &obj2); + if (!obj2.isNum()) { + error(-1, "Illegal value in function domain array"); + goto err1; + } + domain[i][1] = obj2.getNum(); + obj2.free(); + } + obj1.free(); + + //----- Range + if (!dict->lookup("Range", &obj1)->isArray()) { + error(-1, "Function is missing range"); + goto err2; + } + n = obj1.arrayGetLength() / 2; + if (n > 4) { + error(-1, "Functions with more than 4 outputs are unsupported"); + goto err2; + } + for (i = 0; i < n; ++i) { + obj1.arrayGet(2*i, &obj2); + if (!obj2.isNum()) { + error(-1, "Illegal value in function range array"); + goto err1; + } + range[i][0] = obj2.getNum(); + obj2.free(); + obj1.arrayGet(2*i+1, &obj2); + if (!obj2.isNum()) { + error(-1, "Illegal value in function range array"); + goto err1; + } + range[i][1] = obj2.getNum(); + obj2.free(); + } + obj1.free(); + + //----- Size + if (!dict->lookup("Size", &obj1)->isArray() || + obj1.arrayGetLength() != m) { + error(-1, "Function has missing or invalid size array"); + goto err2; + } + for (i = 0; i < m; ++i) { + obj1.arrayGet(i, &obj2); + if (!obj2.isInt()) { + error(-1, "Illegal value in function size array"); + goto err1; + } + sampleSize[i] = obj2.getInt(); + obj2.free(); + } + obj1.free(); + + //----- BitsPerSample + if (!dict->lookup("BitsPerSample", &obj1)->isInt()) { + error(-1, "Function has missing or invalid BitsPerSample"); + goto err2; + } + sampleBits = obj1.getInt(); + sampleMul = 1.0 / (double)((1 << sampleBits) - 1); + obj1.free(); + + //----- Encode + if (dict->lookup("Encode", &obj1)->isArray() && + obj1.arrayGetLength() == 2*m) { + for (i = 0; i < m; ++i) { + obj1.arrayGet(2*i, &obj2); + if (!obj2.isNum()) { + error(-1, "Illegal value in function encode array"); + goto err1; + } + encode[i][0] = obj2.getNum(); + obj2.free(); + obj1.arrayGet(2*i+1, &obj2); + if (!obj2.isNum()) { + error(-1, "Illegal value in function encode array"); + goto err1; + } + encode[i][1] = obj2.getNum(); + obj2.free(); + } + } else { + for (i = 0; i < m; ++i) { + encode[i][0] = 0; + encode[i][1] = sampleSize[i] - 1; + } + } + obj1.free(); + + //----- Decode + if (dict->lookup("Decode", &obj1)->isArray() && + obj1.arrayGetLength() == 2*n) { + for (i = 0; i < n; ++i) { + obj1.arrayGet(2*i, &obj2); + if (!obj2.isNum()) { + error(-1, "Illegal value in function decode array"); + goto err1; + } + decode[i][0] = obj2.getNum(); + obj2.free(); + obj1.arrayGet(2*i+1, &obj2); + if (!obj2.isNum()) { + error(-1, "Illegal value in function decode array"); + goto err1; + } + decode[i][1] = obj2.getNum(); + obj2.free(); + } + } else { + for (i = 0; i < n; ++i) { + decode[i][0] = range[i][0]; + decode[i][1] = range[i][1]; + } + } + obj1.free(); + + //----- samples + nSamples = n; + for (i = 0; i < m; ++i) + nSamples *= sampleSize[i]; + samples = (double *)gmalloc(nSamples * sizeof(double)); + buf = 0; + bits = 0; + bitMask = (1 << sampleBits) - 1; + str->reset(); + for (i = 0; i < nSamples; ++i) { + if (sampleBits == 8) { + s = str->getChar(); + } else if (sampleBits == 16) { + s = str->getChar(); + s = (s << 8) + str->getChar(); + } else if (sampleBits == 32) { + s = str->getChar(); + s = (s << 8) + str->getChar(); + s = (s << 8) + str->getChar(); + s = (s << 8) + str->getChar(); + } else { + while (bits < sampleBits) { + buf = (buf << 8) | (str->getChar() & 0xff); + bits += 8; + } + s = (buf >> (bits - sampleBits)) & bitMask; + bits -= sampleBits; + } + samples[i] = (double)s * sampleMul; + } + + ok = gTrue; + return; + + err1: + obj2.free(); + err2: + obj1.free(); + err3: + return; +} + +Function::Function(Function *func) { + int nSamples, i; + + m = func->m; + n = func->n; + memcpy(domain, func->domain, sizeof(domain)); + memcpy(range, func->range, sizeof(range)); + memcpy(sampleSize, func->sampleSize, sizeof(sampleSize)); + memcpy(encode, func->encode, sizeof(encode)); + memcpy(decode, func->decode, sizeof(decode)); + + nSamples = n; + for (i = 0; i < m; ++i) + nSamples *= sampleSize[i]; + samples = (double *)gmalloc(nSamples * sizeof(double)); + memcpy(samples, func->samples, nSamples * sizeof(double)); + + ok = gTrue; +} + +Function::~Function() { + if (samples) + gfree(samples); +} + +void Function::transform(double *in, double *out) { + double e[4]; + double s; + double x0, x1; + int e0, e1; + double efrac; + int i; + + // map input values into sample array + for (i = 0; i < m; ++i) { + e[i] = ((in[i] - domain[i][0]) / (domain[i][1] - domain[i][0])) * + (encode[i][1] - encode[i][0]) + encode[i][0]; + if (e[i] < 0) + e[i] = 0; + else if (e[i] > sampleSize[i] - 1) + e[i] = sampleSize[i] - 1; + } + + for (i = 0; i < n; ++i) { + + // m-linear interpolation + // (only m=1 is currently supported) + e0 = (int)floor(e[0]); + e1 = (int)ceil(e[0]); + efrac = e[0] - e0; + x0 = samples[e0 * n + i]; + x1 = samples[e1 * n + i]; + s = (1 - efrac) * x0 + efrac * x1; + + // map output values to range + out[i] = s * (decode[i][1] - decode[i][0]) + decode[i][0]; + if (out[i] < range[i][0]) + out[i] = range[i][0]; + else if (out[i] > range[i][1]) + out[i] = range[i][1]; + } +} + +//------------------------------------------------------------------------ +// GfxImageColorMap +//------------------------------------------------------------------------ + +GfxImageColorMap::GfxImageColorMap(int bits1, Object *decode, + GfxColorSpace *colorSpace1) { + GfxColor color; + double x[4]; + int maxPixel; + Object obj; + int i, j; + + ok = gTrue; + + // bits per component and colorspace + bits = bits1; + maxPixel = (1 << bits) - 1; + colorSpace = colorSpace1; + mode = colorSpace->getMode(); + + // get decode map + indexed = colorSpace->isIndexed(); + sep = colorSpace->isSeparation(); + if (decode->isNull()) { + numComps = colorSpace->getNumPixelComps(); + colorSpace->getDefaultRanges(decodeLow, decodeRange, maxPixel); + } else if (decode->isArray()) { + numComps = decode->arrayGetLength() / 2; + if (numComps != colorSpace->getNumPixelComps()) + goto err1; + indexed = colorSpace->isIndexed(); + for (i = 0; i < numComps; ++i) { + decode->arrayGet(2*i, &obj); + if (!obj.isNum()) + goto err2; + decodeLow[i] = obj.getNum(); + obj.free(); + decode->arrayGet(2*i+1, &obj); + if (!obj.isNum()) + goto err2; + decodeRange[i] = obj.getNum() - decodeLow[i]; + obj.free(); + } + } else { + goto err1; + } + + // handle the case where fewer than 2^n palette entries of an n-bit + // indexed color space are populated (this happens, e.g., in files + // optimized by Distiller) + if (colorSpace->isIndexed() && maxPixel > colorSpace->getIndexHigh()) { + maxPixel = colorSpace->getIndexHigh(); + } + + // handle the case where fewer than 2^n palette entries of an n-bit + // indexed color space are populated (this happens, e.g., in files + // optimized by Distiller) + if (indexed && maxPixel > colorSpace->getIndexHigh()) { + maxPixel = colorSpace->getIndexHigh(); + } + + // construct lookup table + lookup = (double (*)[4])gmalloc((maxPixel + 1) * 4 * sizeof(double)); + if (sep) { + for (i = 0; i <= maxPixel; ++i) { + x[0] = (double)i / (double)maxPixel; + colorSpace->getColor(x, &color); + lookup[i][0] = color.getR(); + lookup[i][1] = color.getG(); + lookup[i][2] = color.getB(); + } + } else if (indexed) { + for (i = 0; i <= maxPixel; ++i) { + x[0] = (double)i; + colorSpace->getColor(x, &color); + lookup[i][0] = color.getR(); + lookup[i][1] = color.getG(); + lookup[i][2] = color.getB(); + } + } else { + for (i = 0; i <= maxPixel; ++i) + for (j = 0; j < numComps; ++j) + lookup[i][j] = decodeLow[j] + (i * decodeRange[j]) / maxPixel; + } + + return; + + err2: + obj.free(); + err1: + ok = gFalse; +} + +GfxImageColorMap::~GfxImageColorMap() { + delete colorSpace; + gfree(lookup); +} + +void GfxImageColorMap::getColor(Guchar x[4], GfxColor *color) { + double *p; + + if (sep || indexed) { + p = lookup[x[0]]; + color->setRGB(p[0], p[1], p[2]); + } else { + switch (mode) { + case colorGray: + color->setGray(lookup[x[0]][0]); + break; + case colorCMYK: + color->setCMYK(lookup[x[0]][0], lookup[x[1]][1], + lookup[x[2]][2], lookup[x[3]][3]); + break; + case colorRGB: + color->setRGB(lookup[x[0]][0], lookup[x[1]][1], lookup[x[2]][2]); + break; + case colorLab: + color->setLab(lookup[x[0]][0], lookup[x[1]][1], lookup[x[2]][2], + colorSpace->getLabParams()); + break; + } + } +} + +//------------------------------------------------------------------------ +// GfxSubpath and GfxPath +//------------------------------------------------------------------------ + +GfxSubpath::GfxSubpath(double x1, double y1) { + size = 16; + x = (double *)gmalloc(size * sizeof(double)); + y = (double *)gmalloc(size * sizeof(double)); + curve = (GBool *)gmalloc(size * sizeof(GBool)); + n = 1; + x[0] = x1; + y[0] = y1; + curve[0] = gFalse; + closed = gFalse; +} + +GfxSubpath::~GfxSubpath() { + gfree(x); + gfree(y); + gfree(curve); +} + +// Used for copy(). +GfxSubpath::GfxSubpath(GfxSubpath *subpath) { + size = subpath->size; + n = subpath->n; + x = (double *)gmalloc(size * sizeof(double)); + y = (double *)gmalloc(size * sizeof(double)); + curve = (GBool *)gmalloc(size * sizeof(GBool)); + memcpy(x, subpath->x, n * sizeof(double)); + memcpy(y, subpath->y, n * sizeof(double)); + memcpy(curve, subpath->curve, n * sizeof(GBool)); + closed = subpath->closed; +} + +void GfxSubpath::lineTo(double x1, double y1) { + if (n >= size) { + size += 16; + x = (double *)grealloc(x, size * sizeof(double)); + y = (double *)grealloc(y, size * sizeof(double)); + curve = (GBool *)grealloc(curve, size * sizeof(GBool)); + } + x[n] = x1; + y[n] = y1; + curve[n] = gFalse; + ++n; +} + +void GfxSubpath::curveTo(double x1, double y1, double x2, double y2, + double x3, double y3) { + if (n+3 > size) { + size += 16; + x = (double *)grealloc(x, size * sizeof(double)); + y = (double *)grealloc(y, size * sizeof(double)); + curve = (GBool *)grealloc(curve, size * sizeof(GBool)); + } + x[n] = x1; + y[n] = y1; + x[n+1] = x2; + y[n+1] = y2; + x[n+2] = x3; + y[n+2] = y3; + curve[n] = curve[n+1] = gTrue; + curve[n+2] = gFalse; + n += 3; +} + +void GfxSubpath::close() { + if (x[n-1] != x[0] || y[n-1] != y[0]) { + lineTo(x[0], y[0]); + } + closed = gTrue; +} + +GfxPath::GfxPath() { + justMoved = gFalse; + size = 16; + n = 0; + firstX = firstY = 0; + subpaths = (GfxSubpath **)gmalloc(size * sizeof(GfxSubpath *)); +} + +GfxPath::~GfxPath() { + int i; + + for (i = 0; i < n; ++i) + delete subpaths[i]; + gfree(subpaths); +} + +// Used for copy(). +GfxPath::GfxPath(GBool justMoved1, double firstX1, double firstY1, + GfxSubpath **subpaths1, int n1, int size1) { + int i; + + justMoved = justMoved1; + firstX = firstX1; + firstY = firstY1; + size = size1; + n = n1; + subpaths = (GfxSubpath **)gmalloc(size * sizeof(GfxSubpath *)); + for (i = 0; i < n; ++i) + subpaths[i] = subpaths1[i]->copy(); +} + +void GfxPath::moveTo(double x, double y) { + justMoved = gTrue; + firstX = x; + firstY = y; +} + +void GfxPath::lineTo(double x, double y) { + if (justMoved) { + if (n >= size) { + size += 16; + subpaths = (GfxSubpath **) + grealloc(subpaths, size * sizeof(GfxSubpath *)); + } + subpaths[n] = new GfxSubpath(firstX, firstY); + ++n; + justMoved = gFalse; + } + subpaths[n-1]->lineTo(x, y); +} + +void GfxPath::curveTo(double x1, double y1, double x2, double y2, + double x3, double y3) { + if (justMoved) { + if (n >= size) { + size += 16; + subpaths = (GfxSubpath **) + grealloc(subpaths, size * sizeof(GfxSubpath *)); + } + subpaths[n] = new GfxSubpath(firstX, firstY); + ++n; + justMoved = gFalse; + } + subpaths[n-1]->curveTo(x1, y1, x2, y2, x3, y3); +} + + +//------------------------------------------------------------------------ +// GfxState +//------------------------------------------------------------------------ + +GfxState::GfxState(int dpi, double px1a, double py1a, double px2a, double py2a, + int rotate, GBool upsideDown) { + double k; + + px1 = px1a; + py1 = py1a; + px2 = px2a; + py2 = py2a; + k = (double)dpi / 72.0; + if (rotate == 90) { + ctm[0] = 0; + ctm[1] = upsideDown ? k : -k; + ctm[2] = k; + ctm[3] = 0; + ctm[4] = -k * py1; + ctm[5] = k * (upsideDown ? -px1 : px2); + pageWidth = k * (py2 - py1); + pageHeight = k * (px2 - px1); + } else if (rotate == 180) { + ctm[0] = -k; + ctm[1] = 0; + ctm[2] = 0; + ctm[3] = upsideDown ? k : -k; + ctm[4] = k * px2; + ctm[5] = k * (upsideDown ? -py1 : py2); + pageWidth = k * (px2 - px1); + pageHeight = k * (py2 - py1); + } else if (rotate == 270) { + ctm[0] = 0; + ctm[1] = upsideDown ? -k : k; + ctm[2] = -k; + ctm[3] = 0; + ctm[4] = k * py2; + ctm[5] = k * (upsideDown ? px2 : -px1); + pageWidth = k * (py2 - py1); + pageHeight = k * (px2 - px1); + } else { + ctm[0] = k; + ctm[1] = 0; + ctm[2] = 0; + ctm[3] = upsideDown ? -k : k; + ctm[4] = -k * px1; + ctm[5] = k * (upsideDown ? py2 : -py1); + pageWidth = k * (px2 - px1); + pageHeight = k * (py2 - py1); + } + + fillColorSpace = new GfxColorSpace(colorGray); + strokeColorSpace = new GfxColorSpace(colorGray); + fillColor.setGray(0); + strokeColor.setGray(0); + + lineWidth = 1; + lineDash = NULL; + lineDashLength = 0; + lineDashStart = 0; + flatness = 0; + lineJoin = 0; + lineCap = 0; + miterLimit = 10; + + font = NULL; + fontSize = 0; + textMat[0] = 1; textMat[1] = 0; + textMat[2] = 0; textMat[3] = 1; + textMat[4] = 0; textMat[5] = 0; + charSpace = 0; + wordSpace = 0; + horizScaling = 1; + leading = 0; + rise = 0; + render = 0; + + path = new GfxPath(); + curX = curY = 0; + lineX = lineY = 0; + + saved = NULL; +} + +GfxState::~GfxState() { + if (fillColorSpace) + delete fillColorSpace; + if (strokeColorSpace) + delete strokeColorSpace; + gfree(lineDash); + delete path; + if (saved) + delete saved; +} + +// Used for copy(); +GfxState::GfxState(GfxState *state) { + memcpy(this, state, sizeof(GfxState)); + if (fillColorSpace) + fillColorSpace = state->fillColorSpace->copy(); + if (strokeColorSpace) + strokeColorSpace = state->strokeColorSpace->copy(); + if (lineDashLength > 0) { + lineDash = (double *)gmalloc(lineDashLength * sizeof(double)); + memcpy(lineDash, state->lineDash, lineDashLength * sizeof(double)); + } + path = state->path->copy(); + saved = NULL; +} + +double GfxState::transformWidth(double w) { + double x, y; + + x = ctm[0] + ctm[2]; + y = ctm[1] + ctm[3]; + return w * sqrt(0.5 * (x * x + y * y)); +} + +double GfxState::getTransformedFontSize() { + double x1, y1, x2, y2; + + x1 = textMat[2] * fontSize; + y1 = textMat[3] * fontSize; + x2 = ctm[0] * x1 + ctm[2] * y1; + y2 = ctm[1] * x1 + ctm[3] * y1; + return sqrt(x2 * x2 + y2 * y2); +} + +void GfxState::getFontTransMat(double *m11, double *m12, + double *m21, double *m22) { + *m11 = (textMat[0] * ctm[0] + textMat[1] * ctm[2]) * fontSize; + *m12 = (textMat[0] * ctm[1] + textMat[1] * ctm[3]) * fontSize; + *m21 = (textMat[2] * ctm[0] + textMat[3] * ctm[2]) * fontSize; + *m22 = (textMat[2] * ctm[1] + textMat[3] * ctm[3]) * fontSize; +} + +void GfxState::setCTM(double a, double b, double c, + double d, double e, double f) { + ctm[0] = a; + ctm[1] = b; + ctm[2] = c; + ctm[3] = d; + ctm[4] = e; + ctm[5] = f; +} + +void GfxState::concatCTM(double a, double b, double c, + double d, double e, double f) { + double a1 = ctm[0]; + double b1 = ctm[1]; + double c1 = ctm[2]; + double d1 = ctm[3]; + + ctm[0] = a * a1 + b * c1; + ctm[1] = a * b1 + b * d1; + ctm[2] = c * a1 + d * c1; + ctm[3] = c * b1 + d * d1; + ctm[4] = e * a1 + f * c1 + ctm[4]; + ctm[5] = e * b1 + f * d1 + ctm[5]; +} + +void GfxState::setFillColorSpace(GfxColorSpace *colorSpace) { + if (fillColorSpace) + delete fillColorSpace; + fillColorSpace = colorSpace; +} + +void GfxState::setStrokeColorSpace(GfxColorSpace *colorSpace) { + if (strokeColorSpace) + delete strokeColorSpace; + strokeColorSpace = colorSpace; +} + +void GfxState::setLineDash(double *dash, int length, double start) { + if (lineDash) + gfree(lineDash); + lineDash = dash; + lineDashLength = length; + lineDashStart = start; +} + +void GfxState::clearPath() { + delete path; + path = new GfxPath(); +} + +void GfxState::textShift(double tx) { + double dx, dy; + + textTransformDelta(tx, 0, &dx, &dy); + curX += dx; + curY += dy; +} + +void GfxState::textShift(double tx, double ty) { + double dx, dy; + + textTransformDelta(tx, ty, &dx, &dy); + curX += dx; + curY += dy; +} + +GfxState *GfxState::save() { + GfxState *newState; + + newState = copy(); + newState->saved = this; + return newState; +} + +GfxState *GfxState::restore() { + GfxState *oldState; + + if (saved) { + oldState = saved; + saved = NULL; + delete this; + } else { + oldState = this; + } + return oldState; +} diff --git a/pdftops/GfxState.h b/pdftops/GfxState.h new file mode 100644 index 0000000000..83fd69ddcc --- /dev/null +++ b/pdftops/GfxState.h @@ -0,0 +1,496 @@ +//======================================================================== +// +// GfxState.h +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#ifndef GFXSTATE_H +#define GFXSTATE_H + +#ifdef __GNUC__ +#pragma interface +#endif + +#include "gtypes.h" + +class Object; +class Function; +class GfxFont; + +//------------------------------------------------------------------------ +// LabParams +//------------------------------------------------------------------------ + +// Parameters for L*a*b* color spaces. +struct LabParams { + double whiteX, whiteY, whiteZ; + double aMin, aMax, bMin, bMax; +}; + +//------------------------------------------------------------------------ +// GfxColor +//------------------------------------------------------------------------ + +class GfxColor { +public: + + GfxColor(): r(0), g(0), b(0) {} + + // Set color. + void setGray(double gray); + void setCMYK(double c, double m, double y, double k); + void setRGB(double r1, double g1, double b1); + void setLab(double L, double a, double bb, LabParams *params); + + // Accessors. + double getR() { return r; } + double getG() { return g; } + double getB() { return b; } + double getGray() { return 0.299 * r + 0.587 * g + 0.114 * b; } + +private: + + double r, g, b; +}; + +//------------------------------------------------------------------------ +// GfxColorSpace +//------------------------------------------------------------------------ + +enum GfxColorMode { + colorGray, colorCMYK, colorRGB, colorLab +}; + +class GfxColorSpace { +public: + + // Construct a colorspace. + GfxColorSpace(Object *colorSpace); + + // Construct a simple colorspace: DeviceGray, DeviceCMYK, or + // DeviceRGB. + GfxColorSpace(GfxColorMode mode1); + + // Destructor. + ~GfxColorSpace(); + + // Copy. + GfxColorSpace *copy() { return new GfxColorSpace(this); } + + // Is color space valid? + GBool isOk() { return ok; } + + // Get the color mode. + GfxColorMode getMode() { return mode; } + + // Get number of components in pixels of this colorspace. + int getNumPixelComps() { return (sepFunc || indexed) ? 1 : numComps; } + + // Get number of components in colors of this colorspace. + int getNumColorComps() { return numComps; } + + // Return true if colorspace is indexed. + GBool isIndexed() { return indexed; } + + // Return true for a separation colorspace. + GBool isSeparation() { return sepFunc ? gTrue : gFalse; } + + // Get default ranges for the components. + void getDefaultRanges(double *decodeLow, double *decodeRange, int maxPixel); + + // Get lookup table (only for indexed colorspaces). + int getIndexHigh() { return indexHigh; } + Guchar *getLookupVal(int i) { return lookup[i]; } + + // Convert a pixel to a color. + void getColor(double x[4], GfxColor *color); + + // Get the L*a*b* color space parameters. + LabParams *getLabParams() { return &labParams; } + +private: + + Function *sepFunc; // separation tint transform function + GfxColorMode mode; // color mode + GBool indexed; // set for indexed colorspaces + int numComps; // number of components in colors + int indexHigh; // max pixel for indexed colorspace + Guchar (*lookup)[4]; // lookup table (only for indexed + // colorspaces) + LabParams labParams; // parameters for L*a*b* color space + GBool ok; // is color space valid? + + GfxColorSpace(GfxColorSpace *colorSpace); + void setMode(Object *colorSpace); +}; + +//------------------------------------------------------------------------ +// Function +//------------------------------------------------------------------------ + +class Function { +public: + + // Create a PDF function object. + Function(Object *funcObj); + + ~Function(); + + Function *copy() { return new Function(this); } + + GBool isOk() { return ok; } + + // Return size of input and output tuples. + int getInputSize() { return m; } + int getOutputSize() { return n; } + + // Transform an input tuple into an output tuple. + void transform(double *in, double *out); + +private: + + Function(Function *func); + + int m, n; // size of input and output tuples + double domain[1][2]; // min and max values for function domain + double range[4][2]; // min and max values for function range + int sampleSize[1]; // number of samples for each domain element + double encode[1][2]; // min and max values for domain encoder + double decode[4][2]; // min and max values for range decoder + double *samples; // the samples + GBool ok; +}; + +//------------------------------------------------------------------------ +// GfxImageColorMap +//------------------------------------------------------------------------ + +class GfxImageColorMap { +public: + + // Constructor. + GfxImageColorMap(int bits1, Object *decode, GfxColorSpace *colorSpace1); + + // Destructor. + ~GfxImageColorMap(); + + // Is color map valid? + GBool isOk() { return ok; } + + // Get the color space. + GfxColorSpace *getColorSpace() { return colorSpace; } + + // Get stream decoding info. + int getNumPixelComps() { return numComps; } + int getBits() { return bits; } + + // Get decode table. + double getDecodeLow(int i) { return decodeLow[i]; } + double getDecodeHigh(int i) { return decodeLow[i] + decodeRange[i]; } + + // Convert a pixel to a color. + void getColor(Guchar x[4], GfxColor *color); + +private: + + GfxColorSpace *colorSpace; // the image colorspace + int bits; // bits per component + int numComps; // number of components in a pixel + GBool indexed; // set for indexed color space + GBool sep; // set for separation colorspaces + GfxColorMode mode; // color mode + double (*lookup)[4]; // lookup table + double decodeLow[4]; // minimum values for each component + double decodeRange[4]; // max - min value for each component + GBool ok; +}; + +//------------------------------------------------------------------------ +// GfxSubpath and GfxPath +//------------------------------------------------------------------------ + +class GfxSubpath { +public: + + // Constructor. + GfxSubpath(double x1, double y1); + + // Destructor. + ~GfxSubpath(); + + // Copy. + GfxSubpath *copy() { return new GfxSubpath(this); } + + // Get points. + int getNumPoints() { return n; } + double getX(int i) { return x[i]; } + double getY(int i) { return y[i]; } + GBool getCurve(int i) { return curve[i]; } + + // Get last point. + double getLastX() { return x[n-1]; } + double getLastY() { return y[n-1]; } + + // Add a line segment. + void lineTo(double x1, double y1); + + // Add a Bezier curve. + void curveTo(double x1, double y1, double x2, double y2, + double x3, double y3); + + // Close the subpath. + void close(); + GBool isClosed() { return closed; } + +private: + + double *x, *y; // points + GBool *curve; // curve[i] => point i is a control point + // for a Bezier curve + int n; // number of points + int size; // size of x/y arrays + GBool closed; // set if path is closed + + GfxSubpath(GfxSubpath *subpath); +}; + +class GfxPath { +public: + + // Constructor. + GfxPath(); + + // Destructor. + ~GfxPath(); + + // Copy. + GfxPath *copy() + { return new GfxPath(justMoved, firstX, firstY, subpaths, n, size); } + + // Is there a current point? + GBool isCurPt() { return n > 0 || justMoved; } + + // Is the path non-empty, i.e., is there at least one segment? + GBool isPath() { return n > 0; } + + // Get subpaths. + int getNumSubpaths() { return n; } + GfxSubpath *getSubpath(int i) { return subpaths[i]; } + + // Get last point on last subpath. + double getLastX() { return subpaths[n-1]->getLastX(); } + double getLastY() { return subpaths[n-1]->getLastY(); } + + // Move the current point. + void moveTo(double x, double y); + + // Add a segment to the last subpath. + void lineTo(double x, double y); + + // Add a Bezier curve to the last subpath + void curveTo(double x1, double y1, double x2, double y2, + double x3, double y3); + + // Close the last subpath. + void close() { subpaths[n-1]->close(); } + +private: + + GBool justMoved; // set if a new subpath was just started + double firstX, firstY; // first point in new subpath + GfxSubpath **subpaths; // subpaths + int n; // number of subpaths + int size; // size of subpaths array + + GfxPath(GBool justMoved1, double firstX1, double firstY1, + GfxSubpath **subpaths1, int n1, int size1); +}; + +//------------------------------------------------------------------------ +// GfxState +//------------------------------------------------------------------------ + +class GfxState { +public: + + // Construct a default GfxState, for a device with resolution , + // page box (,)-(,), page rotation , and + // coordinate system specified by . + GfxState(int dpi, double px1a, double py1a, double px2a, double py2a, + int rotate, GBool upsideDown); + + // Destructor. + ~GfxState(); + + // Copy. + GfxState *copy() { return new GfxState(this); } + + // Accessors. + double *getCTM() { return ctm; } + double getX1() { return px1; } + double getY1() { return py1; } + double getX2() { return px2; } + double getY2() { return py2; } + double getPageWidth() { return pageWidth; } + double getPageHeight() { return pageHeight; } + GfxColor *getFillColor() { return &fillColor; } + GfxColor *getStrokeColor() { return &strokeColor; } + double getLineWidth() { return lineWidth; } + void getLineDash(double **dash, int *length, double *start) + { *dash = lineDash; *length = lineDashLength; *start = lineDashStart; } + int getFlatness() { return flatness; } + int getLineJoin() { return lineJoin; } + int getLineCap() { return lineCap; } + double getMiterLimit() { return miterLimit; } + GfxFont *getFont() { return font; } + double getFontSize() { return fontSize; } + double *getTextMat() { return textMat; } + double getCharSpace() { return charSpace; } + double getWordSpace() { return wordSpace; } + double getHorizScaling() { return horizScaling; } + double getLeading() { return leading; } + double getRise() { return rise; } + int getRender() { return render; } + GfxPath *getPath() { return path; } + double getCurX() { return curX; } + double getCurY() { return curY; } + double getLineX() { return lineX; } + double getLineY() { return lineY; } + + // Is there a current point/path? + GBool isCurPt() { return path->isCurPt(); } + GBool isPath() { return path->isPath(); } + + // Transforms. + void transform(double x1, double y1, double *x2, double *y2) + { *x2 = ctm[0] * x1 + ctm[2] * y1 + ctm[4]; + *y2 = ctm[1] * x1 + ctm[3] * y1 + ctm[5]; } + void transformDelta(double x1, double y1, double *x2, double *y2) + { *x2 = ctm[0] * x1 + ctm[2] * y1; + *y2 = ctm[1] * x1 + ctm[3] * y1; } + void textTransform(double x1, double y1, double *x2, double *y2) + { *x2 = textMat[0] * x1 + textMat[2] * y1 + textMat[4]; + *y2 = textMat[1] * x1 + textMat[3] * y1 + textMat[5]; } + void textTransformDelta(double x1, double y1, double *x2, double *y2) + { *x2 = textMat[0] * x1 + textMat[2] * y1; + *y2 = textMat[1] * x1 + textMat[3] * y1; } + double transformWidth(double w); + double getTransformedLineWidth() + { return transformWidth(lineWidth); } + double getTransformedFontSize(); + void getFontTransMat(double *m11, double *m12, double *m21, double *m22); + + // Change state parameters. + void setCTM(double a, double b, double c, + double d, double e, double f); + void concatCTM(double a, double b, double c, + double d, double e, double f); + void setFillGray(double gray) + { fillColor.setGray(gray); } + void setFillCMYK(double c, double m, double y, double k) + { fillColor.setCMYK(c, m, y, k); } + void setFillRGB(double r, double g, double b) + { fillColor.setRGB(r, g, b); } + void setStrokeGray(double gray) + { strokeColor.setGray(gray); } + void setStrokeCMYK(double c, double m, double y, double k) + { strokeColor.setCMYK(c, m, y, k); } + void setStrokeRGB(double r, double g, double b) + { strokeColor.setRGB(r, g, b); } + void setFillColorSpace(GfxColorSpace *colorSpace); + void setStrokeColorSpace(GfxColorSpace *colorSpace); + void setFillColor(double x[4]) + { fillColorSpace->getColor(x, &fillColor); } + void setStrokeColor(double x[4]) + { strokeColorSpace->getColor(x, &strokeColor); } + void setLineWidth(double width) + { lineWidth = width; } + void setLineDash(double *dash, int length, double start); + void setFlatness(int flatness1) { flatness = flatness1; } + void setLineJoin(int lineJoin1) { lineJoin = lineJoin1; } + void setLineCap(int lineCap1) { lineCap = lineCap1; } + void setMiterLimit(double miterLimit1) { miterLimit = miterLimit1; } + void setFont(GfxFont *font1, double fontSize1) + { font = font1; fontSize = fontSize1; } + void setTextMat(double a, double b, double c, + double d, double e, double f) + { textMat[0] = a; textMat[1] = b; textMat[2] = c; + textMat[3] = d; textMat[4] = e; textMat[5] = f; } + void setCharSpace(double space) + { charSpace = space; } + void setWordSpace(double space) + { wordSpace = space; } + void setHorizScaling(double scale) + { horizScaling = 0.01 * scale; } + void setLeading(double leading1) + { leading = leading1; } + void setRise(double rise1) + { rise = rise1; } + void setRender(int render1) + { render = render1; } + + // Add to path. + void moveTo(double x, double y) + { path->moveTo(curX = x, curY = y); } + void lineTo(double x, double y) + { path->lineTo(curX = x, curY = y); } + void curveTo(double x1, double y1, double x2, double y2, + double x3, double y3) + { path->curveTo(x1, y1, x2, y2, curX = x3, curY = y3); } + void closePath() + { path->close(); curX = path->getLastX(); curY = path->getLastY(); } + void clearPath(); + + // Text position. + void textMoveTo(double tx, double ty) + { lineX = tx; lineY = ty; textTransform(tx, ty, &curX, &curY); } + void textShift(double tx); + void textShift(double tx, double ty); + + // Push/pop GfxState on/off stack. + GfxState *save(); + GfxState *restore(); + GBool hasSaves() { return saved != NULL; } + +private: + + double ctm[6]; // coord transform matrix + double px1, py1, px2, py2; // page corners (user coords) + double pageWidth, pageHeight; // page size (pixels) + + GfxColorSpace *fillColorSpace; // fill color space + GfxColorSpace *strokeColorSpace; // stroke color space + GfxColor fillColor; // fill color + GfxColor strokeColor; // stroke color + + double lineWidth; // line width + double *lineDash; // line dash + int lineDashLength; + double lineDashStart; + int flatness; // curve flatness + int lineJoin; // line join style + int lineCap; // line cap style + double miterLimit; // line miter limit + + GfxFont *font; // font + double fontSize; // font size + double textMat[6]; // text matrix + double charSpace; // character spacing + double wordSpace; // word spacing + double horizScaling; // horizontal scaling + double leading; // text leading + double rise; // text rise + int render; // text rendering mode + + GfxPath *path; // array of path elements + double curX, curY; // current point (user coords) + double lineX, lineY; // start of current text line (text coords) + + GfxState *saved; // next GfxState on stack + + GfxState(GfxState *state); +}; + +#endif diff --git a/pdftops/ImageOutputDev.cxx b/pdftops/ImageOutputDev.cxx new file mode 100644 index 0000000000..93d1c31237 --- /dev/null +++ b/pdftops/ImageOutputDev.cxx @@ -0,0 +1,155 @@ +//======================================================================== +// +// ImageOutputDev.cc +// +// Copyright 1998 Derek B. Noonburg +// +//======================================================================== + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include +#include +#include +#include +#include "gmem.h" +#include "config.h" +#include "Error.h" +#include "GfxState.h" +#include "Object.h" +#include "Stream.h" +#include "ImageOutputDev.h" + +ImageOutputDev::ImageOutputDev(char *fileRoot1, GBool dumpJPEG1) { + fileRoot = copyString(fileRoot1); + fileName = (char *)gmalloc(strlen(fileRoot) + 20); + dumpJPEG = dumpJPEG1; + imgNum = 0; + ok = gTrue; +} + +ImageOutputDev::~ImageOutputDev() { + gfree(fileName); + gfree(fileRoot); +} + +void ImageOutputDev::drawImageMask(GfxState *state, Stream *str, + int width, int height, GBool invert, + GBool inlineImg) { + FILE *f; + int c; + + // dump JPEG file + if (dumpJPEG && str->getKind() == strDCT) { + + // open the image file + sprintf(fileName, "%s-%03d.jpg", fileRoot, imgNum); + ++imgNum; + if (!(f = fopen(fileName, "wb"))) { + error(-1, "Couldn't open image file '%s'", fileName); + return; + } + + // initialize stream + str = ((DCTStream *)str)->getRawStream(); + str->reset(); + + // copy the stream + while ((c = str->getChar()) != EOF) + fputc(c, f); + + fclose(f); + + // dump PBM file + } else { + + // open the image file and write the PBM header + sprintf(fileName, "%s-%03d.pbm", fileRoot, imgNum); + ++imgNum; + if (!(f = fopen(fileName, "wb"))) { + error(-1, "Couldn't open image file '%s'", fileName); + return; + } + fprintf(f, "P4\n"); + fprintf(f, "%d %d\n", width, height); + + // initialize stream + str->reset(); + + // copy the stream + while ((c = str->getChar()) != EOF) + fputc(c, f); + + fclose(f); + } +} + +void ImageOutputDev::drawImage(GfxState *state, Stream *str, int width, + int height, GfxImageColorMap *colorMap, + GBool inlineImg) { + FILE *f; + ImageStream *imgStr; + Guchar pixBuf[4]; + GfxColor color; + int x, y; + int c; + + // dump JPEG file + if (dumpJPEG && str->getKind() == strDCT) { + + // open the image file + sprintf(fileName, "%s-%03d.jpg", fileRoot, imgNum); + ++imgNum; + if (!(f = fopen(fileName, "wb"))) { + error(-1, "Couldn't open image file '%s'", fileName); + return; + } + + // initialize stream + str = ((DCTStream *)str)->getRawStream(); + str->reset(); + + // copy the stream + while ((c = str->getChar()) != EOF) + fputc(c, f); + + fclose(f); + + // dump PPM file + } else { + + // open the image file and write the PPM header + sprintf(fileName, "%s-%03d.ppm", fileRoot, imgNum); + ++imgNum; + if (!(f = fopen(fileName, "wb"))) { + error(-1, "Couldn't open image file '%s'", fileName); + return; + } + fprintf(f, "P6\n"); + fprintf(f, "%d %d\n", width, height); + fprintf(f, "255\n"); + + // initialize stream + imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(), + colorMap->getBits()); + imgStr->reset(); + + // for each line... + for (y = 0; y < height; ++y) { + + // write the line + for (x = 0; x < width; ++x) { + imgStr->getPixel(pixBuf); + colorMap->getColor(pixBuf, &color); + fputc((int)(color.getR() * 255 + 0.5), f); + fputc((int)(color.getG() * 255 + 0.5), f); + fputc((int)(color.getB() * 255 + 0.5), f); + } + } + delete imgStr; + + fclose(f); + } +} diff --git a/pdftops/ImageOutputDev.h b/pdftops/ImageOutputDev.h new file mode 100644 index 0000000000..84766dd1f0 --- /dev/null +++ b/pdftops/ImageOutputDev.h @@ -0,0 +1,67 @@ +//======================================================================== +// +// ImageOutputDev.h +// +// Copyright 1998 Derek B. Noonburg +// +//======================================================================== + +#ifndef IMAGEOUTPUTDEV_H +#define IMAGEOUTPUTDEV_H + +#ifdef __GNUC__ +#pragma interface +#endif + +#include +#include "gtypes.h" +#include "OutputDev.h" + +class GfxState; + +//------------------------------------------------------------------------ +// ImageOutputDev +//------------------------------------------------------------------------ + +class ImageOutputDev: public OutputDev { +public: + + // Create an OutputDev which will write images to files named + // -NNN.. Normally, all images are written as PBM + // (.pbm) or PPM (.ppm) files. If is set, JPEG images are + // written as JPEG (.jpg) files. + ImageOutputDev(char *fileRoot1, GBool dumpJPEG1); + + // Destructor. + virtual ~ImageOutputDev(); + + // Check if file was successfully created. + virtual GBool isOk() { return ok; } + + //---- get info about output device + + // Does this device use upside-down coordinates? + // (Upside-down means (0,0) is the top left corner of the page.) + virtual GBool upsideDown() { return gTrue; } + + // Does this device use drawChar() or drawString()? + virtual GBool useDrawChar() { return gFalse; } + + //----- image drawing + virtual void drawImageMask(GfxState *state, Stream *str, + int width, int height, GBool invert, + GBool inlineImg); + virtual void drawImage(GfxState *state, Stream *str, int width, + int height, GfxImageColorMap *colorMap, + GBool inlineImg); + +private: + + char *fileRoot; // root of output file names + char *fileName; // buffer for output file names + GBool dumpJPEG; // set to dump native JPEG files + int imgNum; // current image number + GBool ok; // set up ok? +}; + +#endif diff --git a/pdftops/Lexer.cxx b/pdftops/Lexer.cxx new file mode 100644 index 0000000000..302a024873 --- /dev/null +++ b/pdftops/Lexer.cxx @@ -0,0 +1,453 @@ +//======================================================================== +// +// Lexer.cc +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include +#include +#include +#include +#include "Lexer.h" +#include "Error.h" + +//------------------------------------------------------------------------ + +// A '1' in this array means the corresponding character ends a name +// or command. +static char endOfNameChars[128] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, // 0x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x + 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, // 2x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, // 3x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, // 5x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0 // 7x +}; + +//------------------------------------------------------------------------ +// Lexer +//------------------------------------------------------------------------ + +Lexer::Lexer(Stream *str) { + Object obj; + + curStr.initStream(str); + streams = new Array(); + streams->add(curStr.copy(&obj)); + strPtr = 0; + freeArray = gTrue; + curStr.streamReset(); +} + +Lexer::Lexer(Object *obj) { + Object obj2; + + if (obj->isStream()) { + streams = new Array(); + freeArray = gTrue; + streams->add(obj->copy(&obj2)); + } else { + streams = obj->getArray(); + freeArray = gFalse; + } + strPtr = 0; + if (streams->getLength() > 0) { + streams->get(strPtr, &curStr); + curStr.streamReset(); + } +} + +Lexer::~Lexer() { + if (!curStr.isNone()) + curStr.free(); + if (freeArray) + delete streams; +} + +int Lexer::getChar() { + int c; + + c = EOF; + while (!curStr.isNone() && (c = curStr.streamGetChar()) == EOF) { + curStr.free(); + ++strPtr; + if (strPtr < streams->getLength()) { + streams->get(strPtr, &curStr); + curStr.streamReset(); + } + } + return c; +} + +int Lexer::lookChar() { + int c; + + c = EOF; + while (!curStr.isNone() && (c = curStr.streamLookChar()) == EOF) { + curStr.free(); + ++strPtr; + if (strPtr < streams->getLength()) { + streams->get(strPtr, &curStr); + curStr.streamReset(); + } + } + return c; +} + +Object *Lexer::getObj(Object *obj) { + char *p; + int c, c2; + GBool comment, neg, done; + int numParen; + int xi; + double xf, scale; + GString *s; + int n, m; + + // skip whitespace and comments + comment = gFalse; + while (1) { + if ((c = getChar()) == EOF) + return obj->initEOF(); + if (comment) { + if (c == '\r' || c == '\n') + comment = gFalse; + } else if (c == '%') { + comment = gTrue; + } else if (!isspace(c)) { + break; + } + } + + // start reading token + switch (c) { + + // number + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case '-': case '.': + neg = gFalse; + xi = 0; + if (c == '-') { + neg = gTrue; + } else if (c == '.') { + goto doReal; + } else { + xi = c - '0'; + } + while (1) { + c = lookChar(); + if (isdigit(c)) { + getChar(); + xi = xi * 10 + (c - '0'); + } else if (c == '.') { + getChar(); + goto doReal; + } else { + break; + } + } + if (neg) + xi = -xi; + obj->initInt(xi); + break; + doReal: + xf = xi; + scale = 0.1; + while (1) { + c = lookChar(); + if (!isdigit(c)) + break; + getChar(); + xf = xf + scale * (c - '0'); + scale *= 0.1; + } + if (neg) + xf = -xf; + obj->initReal(xf); + break; + + // string + case '(': + p = tokBuf; + n = 0; + numParen = 1; + done = gFalse; + s = NULL; + do { + c2 = EOF; + switch (c = getChar()) { + + case EOF: + case '\r': + case '\n': + error(getPos(), "Unterminated string"); + done = gTrue; + break; + + case '(': + ++numParen; + break; + + case ')': + if (--numParen == 0) + done = gTrue; + break; + + case '\\': + switch (c = getChar()) { + case 'n': + c2 = '\n'; + break; + case 'r': + c2 = '\r'; + break; + case 't': + c2 = '\t'; + break; + case 'b': + c2 = '\b'; + break; + case 'f': + c2 = '\f'; + break; + case '\\': + case '(': + case ')': + c2 = c; + break; + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + c2 = c - '0'; + c = lookChar(); + if (c >= '0' && c <= '7') { + getChar(); + c2 = (c2 << 3) + (c - '0'); + c = lookChar(); + if (c >= '0' && c <= '7') { + getChar(); + c2 = (c2 << 3) + (c - '0'); + } + } + break; + case '\r': + c = lookChar(); + if (c == '\n') + getChar(); + break; + case '\n': + break; + case EOF: + error(getPos(), "Unterminated string"); + done = gTrue; + break; + default: + c2 = c; + break; + } + break; + + default: + c2 = c; + break; + } + + if (c2 != EOF) { + if (n == tokBufSize) { + if (!s) + s = new GString(tokBuf, tokBufSize); + else + s->append(tokBuf, tokBufSize); + p = tokBuf; + n = 0; + } + *p++ = (char)c2; + ++n; + } + } while (!done); + if (!s) + s = new GString(tokBuf, n); + else + s->append(tokBuf, n); + obj->initString(s); + break; + + // name + case '/': + p = tokBuf; + n = 0; + while ((c = lookChar()) != EOF && !(c < 128 && endOfNameChars[c])) { + getChar(); + if (c == '#') { + c2 = lookChar(); + if (c2 >= '0' && c2 <= '9') + c = c2 - '0'; + else if (c2 >= 'A' && c2 <= 'F') + c = c2 - 'A' + 10; + else if (c2 >= 'a' && c2 <= 'f') + c = c2 - 'a' + 10; + else + goto notEscChar; + getChar(); + c <<= 4; + c2 = getChar(); + if (c2 >= '0' && c2 <= '9') + c += c2 - '0'; + else if (c2 >= 'A' && c2 <= 'F') + c += c2 - 'A' + 10; + else if (c2 >= 'a' && c2 <= 'f') + c += c2 - 'a' + 10; + else + error(getPos(), "Illegal digit in hex char in name"); + } + notEscChar: + if (++n == tokBufSize) { + error(getPos(), "Name token too long"); + break; + } + *p++ = c; + } + *p = '\0'; + obj->initName(tokBuf); + break; + + // array punctuation + case '[': + case ']': + tokBuf[0] = c; + tokBuf[1] = '\0'; + obj->initCmd(tokBuf); + break; + + // hex string or dict punctuation + case '<': + c = lookChar(); + + // dict punctuation + if (c == '<') { + getChar(); + tokBuf[0] = tokBuf[1] = '<'; + tokBuf[2] = '\0'; + obj->initCmd(tokBuf); + + // hex string + } else { + p = tokBuf; + m = n = 0; + c2 = 0; + s = NULL; + while (1) { + c = getChar(); + if (c == '>') { + break; + } else if (c == EOF) { + error(getPos(), "Unterminated hex string"); + break; + } else if (!isspace(c)) { + c2 = c2 << 4; + if (c >= '0' && c <= '9') + c2 += c - '0'; + else if (c >= 'A' && c <= 'F') + c2 += c - 'A' + 10; + else if (c >= 'a' && c <= 'f') + c2 += c - 'a' + 10; + else + error(getPos(), "Illegal character <%02x> in hex string", c); + if (++m == 2) { + if (n == tokBufSize) { + if (!s) + s = new GString(tokBuf, tokBufSize); + else + s->append(tokBuf, tokBufSize); + p = tokBuf; + n = 0; + } + *p++ = (char)c2; + ++n; + c2 = 0; + m = 0; + } + } + } + if (!s) + s = new GString(tokBuf, n); + else + s->append(tokBuf, n); + if (m == 1) + s->append((char)(c2 << 4)); + obj->initString(s); + } + break; + + // dict punctuation + case '>': + c = lookChar(); + if (c == '>') { + getChar(); + tokBuf[0] = tokBuf[1] = '>'; + tokBuf[2] = '\0'; + obj->initCmd(tokBuf); + } else { + error(getPos(), "Illegal character '>'"); + obj->initError(); + } + break; + + // error + case ')': + case '{': + case '}': + error(getPos(), "Illegal character '%c'", c); + obj->initError(); + break; + + // command + default: + p = tokBuf; + *p++ = c; + n = 1; + while ((c = lookChar()) != EOF && !(c < 128 && endOfNameChars[c])) { + getChar(); + if (++n == tokBufSize) { + error(getPos(), "Command token too long"); + break; + } + *p++ = c; + } + *p = '\0'; + if (tokBuf[0] == 't' && !strcmp(tokBuf, "true")) + obj->initBool(gTrue); + else if (tokBuf[0] == 'f' && !strcmp(tokBuf, "false")) + obj->initBool(gFalse); + else if (tokBuf[0] == 'n' && !strcmp(tokBuf, "null")) + obj->initNull(); + else + obj->initCmd(tokBuf); + break; + } + + return obj; +} + +void Lexer::skipToNextLine() { + int c; + + while (1) { + c = getChar(); + if (c == EOF || c == '\n') + return; + if (c == '\r') { + if ((c = lookChar()) == '\n') + getChar(); + return; + } + } +} diff --git a/pdftops/Lexer.h b/pdftops/Lexer.h new file mode 100644 index 0000000000..70144b86bc --- /dev/null +++ b/pdftops/Lexer.h @@ -0,0 +1,72 @@ +//======================================================================== +// +// Lexer.h +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#ifndef LEXER_H +#define LEXER_H + +#ifdef __GNUC__ +#pragma interface +#endif + +#include "Object.h" +#include "Stream.h" + +#define tokBufSize 128 // size of token buffer + +//------------------------------------------------------------------------ +// Lexer +//------------------------------------------------------------------------ + +class Lexer { +public: + + // Construct a lexer for a single stream. Deletes the stream when + // lexer is deleted. + Lexer(Stream *str); + + // Construct a lexer for a stream or array of streams (assumes obj + // is either a stream or array of streams). + Lexer(Object *obj); + + // Destructor. + ~Lexer(); + + // Get the next object from the input stream. + Object *getObj(Object *obj); + + // Skip to the beginning of the next line in the input stream. + void skipToNextLine(); + + // Skip over one character. + void skipChar() { getChar(); } + + // Get stream. + Stream *getStream() + { return curStr.isNone() ? (Stream *)NULL : curStr.getStream(); } + + // Get current position in file. + int getPos() + { return curStr.isNone() ? -1 : curStr.streamGetPos(); } + + // Set position in file. + void setPos(int pos) + { if (!curStr.isNone()) curStr.streamSetPos(pos); } + +private: + + int getChar(); + int lookChar(); + + Array *streams; // array of input streams + int strPtr; // index of current stream + Object curStr; // current stream + GBool freeArray; // should lexer free the streams array? + char tokBuf[tokBufSize]; // temporary token buffer +}; + +#endif diff --git a/pdftops/Link.cxx b/pdftops/Link.cxx new file mode 100644 index 0000000000..837cc9b33d --- /dev/null +++ b/pdftops/Link.cxx @@ -0,0 +1,607 @@ +//======================================================================== +// +// Link.cc +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include +#include +#include "gmem.h" +#include "GString.h" +#include "Error.h" +#include "Object.h" +#include "Array.h" +#include "Dict.h" +#include "Link.h" + +//------------------------------------------------------------------------ + +static GString *getFileSpecName(Object *fileSpecObj); + +//------------------------------------------------------------------------ +// LinkDest +//------------------------------------------------------------------------ + +LinkDest::LinkDest(Array *a, GBool pageIsRef1) { + Object obj1, obj2; + + // initialize fields + pageIsRef = pageIsRef1; + left = bottom = right = top = zoom = 0; + ok = gFalse; + + // get page + if (pageIsRef) { + if (!a->getNF(0, &obj1)->isRef()) { + error(-1, "Bad annotation destination"); + goto err2; + } + pageRef.num = obj1.getRefNum(); + pageRef.gen = obj1.getRefGen(); + obj1.free(); + } else { + if (!a->get(0, &obj1)->isInt()) { + error(-1, "Bad annotation destination"); + goto err2; + } + pageNum = obj1.getInt() + 1; + obj1.free(); + } + + // get destination type + a->get(1, &obj1); + + // XYZ link + if (obj1.isName("XYZ")) { + kind = destXYZ; + a->get(2, &obj2); + if (obj2.isNull()) { + changeLeft = gFalse; + } else if (obj2.isNum()) { + changeLeft = gTrue; + left = obj2.getNum(); + } else { + error(-1, "Bad annotation destination position"); + goto err1; + } + obj2.free(); + a->get(3, &obj2); + if (obj2.isNull()) { + changeTop = gFalse; + } else if (obj2.isNum()) { + changeTop = gTrue; + top = obj2.getNum(); + } else { + error(-1, "Bad annotation destination position"); + goto err1; + } + obj2.free(); + a->get(4, &obj2); + if (obj2.isNull()) { + changeZoom = gFalse; + } else if (obj2.isNum()) { + changeZoom = gTrue; + zoom = obj2.getNum(); + } else { + error(-1, "Bad annotation destination position"); + goto err1; + } + obj2.free(); + + // Fit link + } else if (obj1.isName("Fit")) { + kind = destFit; + + // FitH link + } else if (obj1.isName("FitH")) { + kind = destFitH; + if (!a->get(2, &obj2)->isNum()) { + error(-1, "Bad annotation destination position"); + goto err1; + } + top = obj2.getNum(); + obj2.free(); + + // FitV link + } else if (obj1.isName("FitV")) { + kind = destFitV; + if (!a->get(2, &obj2)->isNum()) { + error(-1, "Bad annotation destination position"); + goto err1; + } + left = obj2.getNum(); + obj2.free(); + + // FitR link + } else if (obj1.isName("FitR")) { + kind = destFitR; + if (!a->get(2, &obj2)->isNum()) { + error(-1, "Bad annotation destination position"); + goto err1; + } + left = obj2.getNum(); + obj2.free(); + if (!a->get(3, &obj2)->isNum()) { + error(-1, "Bad annotation destination position"); + goto err1; + } + bottom = obj2.getNum(); + obj2.free(); + if (!a->get(4, &obj2)->isNum()) { + error(-1, "Bad annotation destination position"); + goto err1; + } + right = obj2.getNum(); + obj2.free(); + if (!a->get(5, &obj2)->isNum()) { + error(-1, "Bad annotation destination position"); + goto err1; + } + top = obj2.getNum(); + obj2.free(); + + // FitB link + } else if (obj1.isName("FitB")) { + kind = destFitB; + + // FitBH link + } else if (obj1.isName("FitBH")) { + kind = destFitBH; + if (!a->get(2, &obj2)->isNum()) { + error(-1, "Bad annotation destination position"); + goto err1; + } + top = obj2.getNum(); + obj2.free(); + + // FitBV link + } else if (obj1.isName("FitBV")) { + kind = destFitBV; + if (!a->get(2, &obj2)->isNum()) { + error(-1, "Bad annotation destination position"); + goto err1; + } + left = obj2.getNum(); + obj2.free(); + + // unknown link kind + } else { + error(-1, "Unknown annotation destination type"); + goto err2; + } + + obj1.free(); + ok = gTrue; + return; + + err1: + obj2.free(); + err2: + obj1.free(); +} + +LinkDest::LinkDest(LinkDest *dest) { + kind = dest->kind; + pageIsRef = dest->pageIsRef; + if (pageIsRef) + pageRef = dest->pageRef; + else + pageNum = dest->pageNum; + left = dest->left; + bottom = dest->bottom; + right = dest->right; + top = dest->top; + zoom = dest->zoom; + changeLeft = dest->changeLeft; + changeTop = dest->changeTop; + changeZoom = dest->changeZoom; + ok = gTrue; +} + +//------------------------------------------------------------------------ +// LinkGoTo +//------------------------------------------------------------------------ + +LinkGoTo::LinkGoTo(Object *destObj) { + dest = NULL; + namedDest = NULL; + + // named destination + if (destObj->isName()) { + namedDest = new GString(destObj->getName()); + } else if (destObj->isString()) { + namedDest = destObj->getString()->copy(); + + // destination dictionary + } else if (destObj->isArray()) { + dest = new LinkDest(destObj->getArray(), gTrue); + if (!dest->isOk()) { + delete dest; + dest = NULL; + } + + // error + } else { + error(-1, "Illegal annotation destination"); + } +} + +LinkGoTo::~LinkGoTo() { + if (dest) + delete dest; + if (namedDest) + delete namedDest; +} + +//------------------------------------------------------------------------ +// LinkGoToR +//------------------------------------------------------------------------ + +LinkGoToR::LinkGoToR(Object *fileSpecObj, Object *destObj) { + dest = NULL; + namedDest = NULL; + + // get file name + fileName = getFileSpecName(fileSpecObj); + + // named destination + if (destObj->isName()) { + namedDest = new GString(destObj->getName()); + } else if (destObj->isString()) { + namedDest = destObj->getString()->copy(); + + // destination dictionary + } else if (destObj->isArray()) { + dest = new LinkDest(destObj->getArray(), gFalse); + if (!dest->isOk()) { + delete dest; + dest = NULL; + } + + // error + } else { + error(-1, "Illegal annotation destination"); + } +} + +LinkGoToR::~LinkGoToR() { + if (fileName) + delete fileName; + if (dest) + delete dest; + if (namedDest) + delete namedDest; +} + + +//------------------------------------------------------------------------ +// LinkLaunch +//------------------------------------------------------------------------ + +LinkLaunch::LinkLaunch(Object *actionObj) { + Object obj1, obj2; + + fileName = NULL; + params = NULL; + + if (actionObj->isDict()) { + if (!actionObj->dictLookup("F", &obj1)->isNull()) { + fileName = getFileSpecName(&obj1); + } else { + obj1.free(); + //~ This hasn't been defined by Adobe yet, so assume it looks + //~ just like the Win dictionary until they say otherwise. + if (actionObj->dictLookup("Unix", &obj1)->isDict()) { + obj1.dictLookup("F", &obj2); + fileName = getFileSpecName(&obj2); + obj2.free(); + if (obj1.dictLookup("P", &obj2)->isString()) + params = obj2.getString()->copy(); + obj2.free(); + } else { + error(-1, "Bad launch-type link action"); + } + } + obj1.free(); + } +} + +LinkLaunch::~LinkLaunch() { + if (fileName) + delete fileName; + if (params) + delete params; +} + +//------------------------------------------------------------------------ +// LinkURI +//------------------------------------------------------------------------ + +LinkURI::LinkURI(Object *uriObj, GString *baseURI) { + GString *uri2; + int n; + char c; + + uri = NULL; + if (uriObj->isString()) { + uri2 = uriObj->getString()->copy(); + if (baseURI) { + n = strcspn(uri2->getCString(), "/:"); + if (n == uri2->getLength() || uri2->getChar(n) == '/') { + uri = baseURI->copy(); + c = uri->getChar(uri->getLength() - 1); + if (c == '/' || c == '?') { + if (uri2->getChar(0) == '/') { + uri2->del(0); + } + } else { + if (uri2->getChar(0) != '/') { + uri->append('/'); + } + } + uri->append(uri2); + delete uri2; + } else { + uri = uri2; + } + } else { + uri = uri2; + } + } else { + error(-1, "Illegal URI-type link"); + } +} + +LinkURI::~LinkURI() { + if (uri) + delete uri; +} + +//------------------------------------------------------------------------ +// LinkUnknown +//------------------------------------------------------------------------ + +LinkUnknown::LinkUnknown(char *action1) { + action = new GString(action1); +} + +LinkUnknown::~LinkUnknown() { + delete action; +} + +//------------------------------------------------------------------------ +// Link +//------------------------------------------------------------------------ + +Link::Link(Dict *dict, GString *baseURI) { + Object obj1, obj2, obj3, obj4; + double t; + + action = NULL; + ok = gFalse; + + // get rectangle + if (!dict->lookup("Rect", &obj1)->isArray()) { + error(-1, "Annotation rectangle is wrong type"); + goto err2; + } + if (!obj1.arrayGet(0, &obj2)->isNum()) { + error(-1, "Bad annotation rectangle"); + goto err1; + } + x1 = obj2.getNum(); + obj2.free(); + if (!obj1.arrayGet(1, &obj2)->isNum()) { + error(-1, "Bad annotation rectangle"); + goto err1; + } + y1 = obj2.getNum(); + obj2.free(); + if (!obj1.arrayGet(2, &obj2)->isNum()) { + error(-1, "Bad annotation rectangle"); + goto err1; + } + x2 = obj2.getNum(); + obj2.free(); + if (!obj1.arrayGet(3, &obj2)->isNum()) { + error(-1, "Bad annotation rectangle"); + goto err1; + } + y2 = obj2.getNum(); + obj2.free(); + obj1.free(); + if (x1 > x2) { + t = x1; + x1 = x2; + x2 = t; + } + if (y1 > y2) { + t = y1; + y1 = y2; + y2 = t; + } + + // get border + borderW = 0; + if (!dict->lookup("Border", &obj1)->isNull()) { + if (obj1.isArray() && obj1.arrayGet(2, &obj2)->isNum()) + borderW = obj2.getNum(); + else + error(-1, "Bad annotation border"); + obj2.free(); + } + obj1.free(); + + // look for destination + if (!dict->lookup("Dest", &obj1)->isNull()) { + action = new LinkGoTo(&obj1); + + // look for action + } else { + obj1.free(); + if (dict->lookup("A", &obj1)->isDict()) { + obj1.dictLookup("S", &obj2); + + // GoTo action + if (obj2.isName("GoTo")) { + obj1.dictLookup("D", &obj3); + action = new LinkGoTo(&obj3); + obj3.free(); + + // GoToR action + } else if (obj2.isName("GoToR")) { + obj1.dictLookup("F", &obj3); + obj1.dictLookup("D", &obj4); + action = new LinkGoToR(&obj3, &obj4); + obj3.free(); + obj4.free(); + + // Launch action + } else if (obj2.isName("Launch")) { + action = new LinkLaunch(&obj1); + + // URI action + } else if (obj2.isName("URI")) { + obj1.dictLookup("URI", &obj3); + action = new LinkURI(&obj3, baseURI); + obj3.free(); + + // unknown action + } else if (obj2.isName()) { + action = new LinkUnknown(obj2.getName()); + + // action is missing or wrong type + } else { + error(-1, "Bad annotation action"); + action = NULL; + } + + obj2.free(); + + } else { + error(-1, "Missing annotation destination/action"); + action = NULL; + } + } + obj1.free(); + + // check for bad action + if (action && action->isOk()) + ok = gTrue; + + return; + + err1: + obj2.free(); + err2: + obj1.free(); +} + +Link::~Link() { + if (action) + delete action; +} + +//------------------------------------------------------------------------ +// Links +//------------------------------------------------------------------------ + +Links::Links(Object *annots, GString *baseURI) { + Link *link; + Object obj1, obj2; + int size; + int i; + + links = NULL; + size = 0; + numLinks = 0; + + if (annots->isArray()) { + for (i = 0; i < annots->arrayGetLength(); ++i) { + if (annots->arrayGet(i, &obj1)->isDict()) { + if (obj1.dictLookup("Subtype", &obj2)->isName("Link")) { + link = new Link(obj1.getDict(), baseURI); + if (link->isOk()) { + if (numLinks >= size) { + size += 16; + links = (Link **)grealloc(links, size * sizeof(Link *)); + } + links[numLinks++] = link; + } else { + delete link; + } + } + obj2.free(); + } + obj1.free(); + } + } +} + +Links::~Links() { + int i; + + for (i = 0; i < numLinks; ++i) + delete links[i]; + gfree(links); +} + +LinkAction *Links::find(double x, double y) { + int i; + + for (i = 0; i < numLinks; ++i) { + if (links[i]->inRect(x, y)) { + return links[i]->getAction(); + } + } + return NULL; +} + +GBool Links::onLink(double x, double y) { + int i; + + for (i = 0; i < numLinks; ++i) { + if (links[i]->inRect(x, y)) + return gTrue; + } + return gFalse; +} + +//------------------------------------------------------------------------ + +// Extract a file name from a file specification (string or dictionary). +static GString *getFileSpecName(Object *fileSpecObj) { + GString *name; + Object obj1; + + name = NULL; + + // string + if (fileSpecObj->isString()) { + name = fileSpecObj->getString()->copy(); + + // dictionary + } else if (fileSpecObj->isDict()) { + if (!fileSpecObj->dictLookup("Unix", &obj1)->isString()) { + obj1.free(); + fileSpecObj->dictLookup("F", &obj1); + } + if (obj1.isString()) + name = obj1.getString()->copy(); + else + error(-1, "Illegal file spec in link"); + obj1.free(); + + // error + } else { + error(-1, "Illegal file spec in link"); + } + + return name; +} diff --git a/pdftops/Link.h b/pdftops/Link.h new file mode 100644 index 0000000000..71ad0c5cd1 --- /dev/null +++ b/pdftops/Link.h @@ -0,0 +1,313 @@ +//======================================================================== +// +// Link.h +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#ifndef LINK_H +#define LINK_H + +#ifdef __GNUC__ +#pragma interface +#endif + +#include "Object.h" + +class GString; +class Array; +class Dict; + +//------------------------------------------------------------------------ +// LinkAction +//------------------------------------------------------------------------ + +enum LinkActionKind { + actionGoTo, // go to destination + actionGoToR, // go to destination in new file + actionLaunch, // launch app (or open document) + actionURI, // URI + actionUnknown // anything else +}; + +class LinkAction { +public: + + // Destructor. + virtual ~LinkAction() {} + + // Was the LinkAction created successfully? + virtual GBool isOk() = 0; + + // Check link action type. + virtual LinkActionKind getKind() = 0; +}; + +//------------------------------------------------------------------------ +// LinkDest +//------------------------------------------------------------------------ + +enum LinkDestKind { + destXYZ, + destFit, + destFitH, + destFitV, + destFitR, + destFitB, + destFitBH, + destFitBV +}; + +class LinkDest { +public: + + // Build a LinkDest from the array. If is true, the + // page is specified by an object reference; otherwise the page is + // specified by a (zero-relative) page number. + LinkDest(Array *a, GBool pageIsRef1); + + // Copy a LinkDest. + LinkDest *copy() { return new LinkDest(this); } + + // Was the LinkDest created successfully? + GBool isOk() { return ok; } + + // Accessors. + LinkDestKind getKind() { return kind; } + GBool isPageRef() { return pageIsRef; } + int getPageNum() { return pageNum; } + Ref getPageRef() { return pageRef; } + double getLeft() { return left; } + double getBottom() { return bottom; } + double getRight() { return right; } + double getTop() { return top; } + double getZoom() { return zoom; } + GBool getChangeLeft() { return changeLeft; } + GBool getChangeTop() { return changeTop; } + GBool getChangeZoom() { return changeZoom; } + +private: + + LinkDestKind kind; // destination type + GBool pageIsRef; // is the page a reference or number? + union { + Ref pageRef; // reference to page + int pageNum; // one-relative page number + }; + double left, bottom; // position + double right, top; + double zoom; // zoom factor + GBool changeLeft, changeTop; // for destXYZ links, which position + GBool changeZoom; // components to change + GBool ok; // set if created successfully + + LinkDest(LinkDest *dest); +}; + +//------------------------------------------------------------------------ +// LinkGoTo +//------------------------------------------------------------------------ + +class LinkGoTo: public LinkAction { +public: + + // Build a LinkGoTo from a destination (dictionary, name, or string). + LinkGoTo(Object *destObj); + + // Destructor. + virtual ~LinkGoTo(); + + // Was the LinkGoTo created successfully? + virtual GBool isOk() { return dest || namedDest; } + + // Accessors. + virtual LinkActionKind getKind() { return actionGoTo; } + LinkDest *getDest() { return dest; } + GString *getNamedDest() { return namedDest; } + +private: + + LinkDest *dest; // regular destination (NULL for remote + // link with bad destination) + GString *namedDest; // named destination (only one of dest and + // and namedDest may be non-NULL) +}; + +//------------------------------------------------------------------------ +// LinkGoToR +//------------------------------------------------------------------------ + +class LinkGoToR: public LinkAction { +public: + + // Build a LinkGoToR from a file spec (dictionary) and destination + // (dictionary, name, or string). + LinkGoToR(Object *fileSpecObj, Object *destObj); + + // Destructor. + virtual ~LinkGoToR(); + + // Was the LinkGoToR created successfully? + virtual GBool isOk() { return fileName && (dest || namedDest); } + + // Accessors. + virtual LinkActionKind getKind() { return actionGoToR; } + GString *getFileName() { return fileName; } + LinkDest *getDest() { return dest; } + GString *getNamedDest() { return namedDest; } + +private: + + GString *fileName; // file name + LinkDest *dest; // regular destination (NULL for remote + // link with bad destination) + GString *namedDest; // named destination (only one of dest and + // and namedDest may be non-NULL) +}; + +//------------------------------------------------------------------------ +// LinkLaunch +//------------------------------------------------------------------------ + +class LinkLaunch: public LinkAction { +public: + + // Build a LinkLaunch from an action dictionary. + LinkLaunch(Object *actionObj); + + // Destructor. + virtual ~LinkLaunch(); + + // Was the LinkLaunch created successfully? + virtual GBool isOk() { return fileName != NULL; } + + // Accessors. + virtual LinkActionKind getKind() { return actionLaunch; } + GString *getFileName() { return fileName; } + GString *getParams() { return params; } + +private: + + GString *fileName; // file name + GString *params; // parameters +}; + +//------------------------------------------------------------------------ +// LinkURI +//------------------------------------------------------------------------ + +class LinkURI: public LinkAction { +public: + + // Build a LinkURI given the URI (string) and base URI. + LinkURI(Object *uriObj, GString *baseURI); + + // Destructor. + virtual ~LinkURI(); + + // Was the LinkURI created successfully? + virtual GBool isOk() { return uri != NULL; } + + // Accessors. + virtual LinkActionKind getKind() { return actionURI; } + GString *getURI() { return uri; } + +private: + + GString *uri; // the URI +}; + +//------------------------------------------------------------------------ +// LinkUnknown +//------------------------------------------------------------------------ + +class LinkUnknown: public LinkAction { +public: + + // Build a LinkUnknown with the specified action type. + LinkUnknown(char *action1); + + // Destructor. + virtual ~LinkUnknown(); + + // Was the LinkUnknown create successfully? + virtual GBool isOk() { return action != NULL; } + + // Accessors. + virtual LinkActionKind getKind() { return actionUnknown; } + GString *getAction() { return action; } + +private: + + GString *action; // action subtype +}; + +//------------------------------------------------------------------------ +// Link +//------------------------------------------------------------------------ + +class Link { +public: + + // Construct a link, given its dictionary. + Link(Dict *dict, GString *baseURI); + + // Destructor. + ~Link(); + + // Was the link created successfully? + GBool isOk() { return ok; } + + // Check if point is inside the link rectangle. + GBool inRect(double x, double y) + { return x1 <= x && x <= x2 && y1 <= y && y <= y2; } + + // Get action. + LinkAction *getAction() { return action; } + + // Get border corners and width. + void getBorder(double *xa1, double *ya1, double *xa2, double *ya2, + double *wa) + { *xa1 = x1; *ya1 = y1; *xa2 = x2; *ya2 = y2; *wa = borderW; } + +private: + + double x1, y1; // lower left corner + double x2, y2; // upper right corner + double borderW; // border width + LinkAction *action; // action + GBool ok; // is link valid? +}; + +//------------------------------------------------------------------------ +// Links +//------------------------------------------------------------------------ + +class Links { +public: + + // Extract links from array of annotations. + Links(Object *annots, GString *baseURI); + + // Destructor. + ~Links(); + + // Iterate through list of links. + int getNumLinks() { return numLinks; } + Link *getLink(int i) { return links[i]; } + + // If point , is in a link, return the associated action; + // else return NULL. + LinkAction *find(double x, double y); + + // Return true if , is in a link. + GBool onLink(double x, double y); + +private: + + Link **links; + int numLinks; +}; + +#endif diff --git a/pdftops/Makefile b/pdftops/Makefile new file mode 100644 index 0000000000..99e9064322 --- /dev/null +++ b/pdftops/Makefile @@ -0,0 +1,134 @@ +# +# "$Id$" +# +# pdftops filter Makefile for the Common UNIX Printing System (CUPS). +# +# CUPS filter changes Copyright 2000 by Easy Software Products. +# Xpdf code Copyright 1996-1999 by Derek B. Noonburg +# + + +include ../Makedefs + +# +# Object files... +# + +LIBOBJS = Decrypt.o GString.o gfile.o gmempp.o gmem.o parseargs.o \ + Array.o Catalog.o Dict.o Error.o FontEncoding.o \ + FontFile.o FormWidget.o Gfx.o GfxFont.o GfxState.o \ + Lexer.o Link.o Object.o OutputDev.o Page.o Params.o \ + Parser.o PDFDoc.o PSOutputDev.o Stream.o XRef.o +OBJS = pdftops.o $(LIBOBJS) + +# +# Make everything... +# + +all: pdftops + + +# +# Clean all object files... +# + +clean: + $(RM) $(OBJS) + $(RM) libxpdf.a + $(RM) pdftops + + +# +# Install the filter... +# + +install: + $(MKDIR) $(SERVERBIN)/filter + $(CHMOD) ugo+rx $(SERVERBIN) + $(CHMOD) ugo+rx $(SERVERBIN)/filter + $(RM) $(SERVERBIN)/filter/pdftops + $(INSTALL_BIN) pdftops $(SERVERBIN)/filter + + +# +# pdftops +# + +pdftops: libxpdf.a pdftops.o ../cups/$(LIBCUPS) + echo Linking $@... + $(CXX) $(LDFLAGS) -o $@ pdftops.o libxpdf.a $(LIBS) -lm + +pdftops.o: parseargs.h gtypes.h GString.h gmem.h Object.h Array.h \ + Dict.h Stream.h XRef.h Catalog.h Page.h PDFDoc.h Link.h \ + PSOutputDev.h config.h OutputDev.h Params.h Error.h + + +# +# libxpdf.a +# + +libxpdf.a: $(LIBOBJS) + echo Archiving $@... + $(RM) $@ + $(AR) $(ARFLAGS) $@ $(LIBOBJS) + $(RANLIB) $@ + +GString.o: GString.h +gmempp.o: gmem.h +gfile.o: GString.h gfile.h gtypes.h +gmem.o: gmem.h +parseargs.o: parseargs.h gtypes.h +Array.o: gmem.h Object.h gtypes.h GString.h Array.h Dict.h Stream.h +Catalog.o: gmem.h Object.h gtypes.h GString.h Array.h Dict.h Stream.h \ + Page.h Error.h config.h Link.h Catalog.h +Decrypt.o: gmem.h Decrypt.h gtypes.h GString.h +Dict.o: gmem.h Object.h gtypes.h GString.h Array.h Dict.h Stream.h \ + XRef.h +Error.o: gtypes.h Params.h Error.h config.h +FontEncoding.o: gmem.h FontEncoding.h gtypes.h +FontFile.o: gmem.h Error.h config.h FontFile.h gtypes.h GString.h \ + FontEncoding.h StdFontInfo.h CompactFontInfo.h +FormWidget.o: FormWidget.h gmem.h Object.h Gfx.h +Gfx.o: gmem.h Object.h gtypes.h GString.h Array.h Dict.h Stream.h \ + Lexer.h Parser.h GfxFont.h FontEncoding.h GfxState.h \ + OutputDev.h Params.h Error.h config.h Gfx.h +GfxFont.o: GString.h gmem.h gfile.h gtypes.h config.h Object.h Array.h \ + Dict.h Stream.h Error.h Params.h FontFile.h FontEncoding.h \ + GfxFont.h FontInfo.h +GfxState.o: gmem.h Error.h config.h Object.h gtypes.h GString.h Array.h \ + Dict.h Stream.h GfxState.h +ImageOutputDev.o: gmem.h config.h Error.h GfxState.h gtypes.h Object.h \ + GString.h Array.h Dict.h Stream.h ImageOutputDev.h OutputDev.h +Lexer.o: Lexer.h Object.h gtypes.h gmem.h GString.h Array.h Dict.h \ + Stream.h Error.h config.h +Link.o: gmem.h GString.h Error.h config.h Object.h gtypes.h Array.h \ + Dict.h Stream.h Link.h +Object.o: Object.h gtypes.h gmem.h GString.h Array.h Dict.h Stream.h \ + Error.h config.h XRef.h +OutputDev.o: Object.h gtypes.h gmem.h GString.h Array.h Dict.h Stream.h \ + GfxState.h OutputDev.h +Page.o: Object.h gtypes.h gmem.h GString.h Array.h Dict.h Stream.h \ + XRef.h OutputDev.h Gfx.h Error.h config.h Params.h Page.h +Params.o: gtypes.h gmem.h GString.h gfile.h Params.h +Parser.o: Object.h gtypes.h gmem.h GString.h Array.h Dict.h Stream.h \ + Parser.h Lexer.h Error.h config.h +PDFDoc.o: GString.h config.h Page.h Object.h gtypes.h gmem.h Array.h \ + Dict.h Stream.h Catalog.h XRef.h Link.h OutputDev.h Params.h \ + Error.h PDFDoc.h +PSOutputDev.o: GString.h config.h Object.h gtypes.h gmem.h Array.h Dict.h \ + Stream.h Error.h GfxState.h GfxFont.h FontEncoding.h \ + FontFile.h Catalog.h Page.h PSOutputDev.h OutputDev.h +SFont.o: SFont.h gtypes.h +Stream.o: gmem.h config.h Error.h Object.h gtypes.h GString.h Array.h \ + Dict.h Stream.h Stream-CCITT.h +T1Font.o: T1Font.h gmem.h FontEncoding.h +TTFont.o: TTFont.h gmem.h FontEncoding.h +XRef.o: gmem.h Object.h gtypes.h GString.h Array.h Dict.h Stream.h \ + Lexer.h Parser.h Error.h config.h XRef.h + + +$(OBJS): ../config.h ../Makedefs + +# +# End of "$Id$". +# diff --git a/pdftops/Object.cxx b/pdftops/Object.cxx new file mode 100644 index 0000000000..f9c10674d8 --- /dev/null +++ b/pdftops/Object.cxx @@ -0,0 +1,220 @@ +//======================================================================== +// +// Object.cc +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include +#include "Object.h" +#include "Array.h" +#include "Dict.h" +#include "Error.h" +#include "Stream.h" +#include "XRef.h" + +//------------------------------------------------------------------------ +// Object +//------------------------------------------------------------------------ + +char *objTypeNames[numObjTypes] = { + "boolean", + "integer", + "real", + "string", + "name", + "null", + "array", + "dictionary", + "stream", + "ref", + "cmd", + "error", + "eof", + "none" +}; + +#ifdef DEBUG_MEM +int Object::numAlloc[numObjTypes] = + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +#endif + +Object *Object::initArray() { + initObj(objArray); + array = new Array(); + return this; +} + +Object *Object::initDict() { + initObj(objDict); + dict = new Dict(); + return this; +} + +Object *Object::initStream(Stream *stream1) { + initObj(objStream); + stream = stream1; + return this; +} + +Object *Object::copy(Object *obj) { + *obj = *this; + switch (type) { + case objString: + obj->string = string->copy(); + break; + case objName: + obj->name = copyString(name); + break; + case objArray: + array->incRef(); + break; + case objDict: + dict->incRef(); + break; + case objStream: + stream->incRef(); + break; + case objCmd: + obj->cmd = copyString(cmd); + break; + default: + break; + } +#ifdef DEBUG_MEM + ++numAlloc[type]; +#endif + return obj; +} + +Object *Object::fetch(Object *obj) { + return (type == objRef && xref) ? + xref->fetch(ref.num, ref.gen, obj) : copy(obj); +} + +void Object::free() { + switch (type) { + case objString: + delete string; + break; + case objName: + gfree(name); + break; + case objArray: + if (!array->decRef()) { + delete array; + } + break; + case objDict: + if (!dict->decRef()) { + delete dict; + } + break; + case objStream: + if (!stream->decRef()) { + delete stream; + } + break; + case objCmd: + gfree(cmd); + break; + default: + break; + } +#ifdef DEBUG_MEM + --numAlloc[type]; +#endif + type = objNone; +} + +char *Object::getTypeName() { + return objTypeNames[type]; +} + +void Object::print(FILE *f) { + Object obj; + int i; + + switch (type) { + case objBool: + fprintf(f, "%s", booln ? "true" : "false"); + break; + case objInt: + fprintf(f, "%d", intg); + break; + case objReal: + fprintf(f, "%g", real); + break; + case objString: + fprintf(f, "(%s)", string->getCString()); + break; + case objName: + fprintf(f, "/%s", name); + break; + case objNull: + fprintf(f, "null"); + break; + case objArray: + fprintf(f, "["); + for (i = 0; i < arrayGetLength(); ++i) { + if (i > 0) + fprintf(f, " "); + arrayGetNF(i, &obj); + obj.print(f); + obj.free(); + } + fprintf(f, "]"); + break; + case objDict: + fprintf(f, "<<"); + for (i = 0; i < dictGetLength(); ++i) { + fprintf(f, " /%s ", dictGetKey(i)); + dictGetValNF(i, &obj); + obj.print(f); + obj.free(); + } + fprintf(f, " >>"); + break; + case objStream: + fprintf(f, ""); + break; + case objRef: + fprintf(f, "%d %d R", ref.num, ref.gen); + break; + case objCmd: + fprintf(f, "%s", cmd); + break; + case objError: + fprintf(f, ""); + break; + case objEOF: + fprintf(f, ""); + break; + case objNone: + fprintf(f, ""); + break; + } +} + +void Object::memCheck(FILE *f) { +#ifdef DEBUG_MEM + int i; + int t; + + t = 0; + for (i = 0; i < numObjTypes; ++i) + t += numAlloc[i]; + if (t > 0) { + fprintf(f, "Allocated objects:\n"); + for (i = 0; i < numObjTypes; ++i) { + if (numAlloc[i] > 0) + fprintf(f, " %-20s: %6d\n", objTypeNames[i], numAlloc[i]); + } + } +#endif +} diff --git a/pdftops/Object.h b/pdftops/Object.h new file mode 100644 index 0000000000..f63f219dc9 --- /dev/null +++ b/pdftops/Object.h @@ -0,0 +1,296 @@ +//======================================================================== +// +// Object.h +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#ifndef OBJECT_H +#define OBJECT_H + +#ifdef __GNUC__ +#pragma interface +#endif + +#include +#include +#include "gtypes.h" +#include "gmem.h" +#include "GString.h" + +class Array; +class Dict; +class Stream; + +//------------------------------------------------------------------------ +// Ref +//------------------------------------------------------------------------ + +struct Ref { + int num; // object number + int gen; // generation number +}; + +//------------------------------------------------------------------------ +// object types +//------------------------------------------------------------------------ + +enum ObjType { + // simple objects + objBool, // boolean + objInt, // integer + objReal, // real + objString, // string + objName, // name + objNull, // null + + // complex objects + objArray, // array + objDict, // dictionary + objStream, // stream + objRef, // indirect reference + + // special objects + objCmd, // command name + objError, // error return from Lexer + objEOF, // end of file return from Lexer + objNone // uninitialized object +}; + +#define numObjTypes 14 // total number of object types + +//------------------------------------------------------------------------ +// Object +//------------------------------------------------------------------------ + +#ifdef DEBUG_MEM +#define initObj(t) ++numAlloc[type = t] +#else +#define initObj(t) type = t +#endif + +class Object { +public: + + // Default constructor. + Object(): + type(objNone) {} + + // Initialize an object. + Object *initBool(GBool booln1) + { initObj(objBool); booln = booln1; return this; } + Object *initInt(int intg1) + { initObj(objInt); intg = intg1; return this; } + Object *initReal(double real1) + { initObj(objReal); real = real1; return this; } + Object *initString(GString *string1) + { initObj(objString); string = string1; return this; } + Object *initName(char *name1) + { initObj(objName); name = copyString(name1); return this; } + Object *initNull() + { initObj(objNull); return this; } + Object *initArray(); + Object *initDict(); + Object *initDict(Dict *dict1) + { initObj(objDict); dict = dict1; return this; } + Object *initStream(Stream *stream1); + Object *initRef(int num1, int gen1) + { initObj(objRef); ref.num = num1; ref.gen = gen1; return this; } + Object *initCmd(char *cmd1) + { initObj(objCmd); cmd = copyString(cmd1); return this; } + Object *initError() + { initObj(objError); return this; } + Object *initEOF() + { initObj(objEOF); return this; } + + // Copy an object. + Object *copy(Object *obj); + + // If object is a Ref, fetch and return the referenced object. + // Otherwise, return a copy of the object. + Object *fetch(Object *obj); + + // Free object contents. + void free(); + + // Type checking. + ObjType getType() { return type; } + GBool isBool() { return type == objBool; } + GBool isInt() { return type == objInt; } + GBool isReal() { return type == objReal; } + GBool isNum() { return type == objInt || type == objReal; } + GBool isString() { return type == objString; } + GBool isName() { return type == objName; } + GBool isNull() { return type == objNull; } + GBool isArray() { return type == objArray; } + GBool isDict() { return type == objDict; } + GBool isStream() { return type == objStream; } + GBool isRef() { return type == objRef; } + GBool isCmd() { return type == objCmd; } + GBool isError() { return type == objError; } + GBool isEOF() { return type == objEOF; } + GBool isNone() { return type == objNone; } + + // Special type checking. + GBool isName(char *name1) + { return type == objName && !strcmp(name, name1); } + GBool isDict(char *dictType); + GBool isStream(char *dictType); + GBool isCmd(char *cmd1) + { return type == objCmd && !strcmp(cmd, cmd1); } + + // Accessors. NB: these assume object is of correct type. + GBool getBool() { return booln; } + int getInt() { return intg; } + double getReal() { return real; } + double getNum() { return type == objInt ? (double)intg : real; } + GString *getString() { return string; } + char *getName() { return name; } + Array *getArray() { return array; } + Dict *getDict() { return dict; } + Stream *getStream() { return stream; } + Ref getRef() { return ref; } + int getRefNum() { return ref.num; } + int getRefGen() { return ref.gen; } + + // Array accessors. + int arrayGetLength(); + void arrayAdd(Object *elem); + Object *arrayGet(int i, Object *obj); + Object *arrayGetNF(int i, Object *obj); + + // Dict accessors. + int dictGetLength(); + void dictAdd(char *key, Object *val); + GBool dictIs(char *dictType); + Object *dictLookup(char *key, Object *obj); + Object *dictLookupNF(char *key, Object *obj); + char *dictGetKey(int i); + Object *dictGetVal(int i, Object *obj); + Object *dictGetValNF(int i, Object *obj); + + // Stream accessors. + GBool streamIs(char *dictType); + void streamReset(); + int streamGetChar(); + int streamLookChar(); + char *streamGetLine(char *buf, int size); + int streamGetPos(); + void streamSetPos(int pos); + Dict *streamGetDict(); + + // Output. + char *getTypeName(); + void print(FILE *f = stdout); + + // Memory testing. + static void memCheck(FILE *f); + +private: + + ObjType type; // object type + union { // value for each type: + GBool booln; // boolean + int intg; // integer + double real; // real + GString *string; // string + char *name; // name + Array *array; // array + Dict *dict; // dictionary + Stream *stream; // stream + Ref ref; // indirect reference + char *cmd; // command + }; + +#ifdef DEBUG_MEM + static int // number of each type of object + numAlloc[numObjTypes]; // currently allocated +#endif +}; + +//------------------------------------------------------------------------ +// Array accessors. +//------------------------------------------------------------------------ + +#include "Array.h" + +inline int Object::arrayGetLength() + { return array->getLength(); } + +inline void Object::arrayAdd(Object *elem) + { array->add(elem); } + +inline Object *Object::arrayGet(int i, Object *obj) + { return array->get(i, obj); } + +inline Object *Object::arrayGetNF(int i, Object *obj) + { return array->getNF(i, obj); } + +//------------------------------------------------------------------------ +// Dict accessors. +//------------------------------------------------------------------------ + +#include "Dict.h" + +inline int Object::dictGetLength() + { return dict->getLength(); } + +inline void Object::dictAdd(char *key, Object *val) + { dict->add(key, val); } + +inline GBool Object::dictIs(char *dictType) + { return dict->is(dictType); } + +inline GBool Object::isDict(char *dictType) + { return type == objDict && dictIs(dictType); } + +inline Object *Object::dictLookup(char *key, Object *obj) + { return dict->lookup(key, obj); } + +inline Object *Object::dictLookupNF(char *key, Object *obj) + { return dict->lookupNF(key, obj); } + +inline char *Object::dictGetKey(int i) + { return dict->getKey(i); } + +inline Object *Object::dictGetVal(int i, Object *obj) + { return dict->getVal(i, obj); } + +inline Object *Object::dictGetValNF(int i, Object *obj) + { return dict->getValNF(i, obj); } + +//------------------------------------------------------------------------ +// Stream accessors. +//------------------------------------------------------------------------ + +#include "Stream.h" + +inline GBool Object::streamIs(char *dictType) + { return stream->getDict()->is(dictType); } + +inline GBool Object::isStream(char *dictType) + { return type == objStream && streamIs(dictType); } + +inline void Object::streamReset() + { stream->reset(); } + +inline int Object::streamGetChar() + { return stream->getChar(); } + +inline int Object::streamLookChar() + { return stream->lookChar(); } + +inline char *Object::streamGetLine(char *buf, int size) + { return stream->getLine(buf, size); } + +inline int Object::streamGetPos() + { return stream->getPos(); } + +inline void Object::streamSetPos(int pos) + { stream->setPos(pos); } + +inline Dict *Object::streamGetDict() + { return stream->getDict(); } + +#endif diff --git a/pdftops/OutputDev.cxx b/pdftops/OutputDev.cxx new file mode 100644 index 0000000000..16e0ad96d9 --- /dev/null +++ b/pdftops/OutputDev.cxx @@ -0,0 +1,93 @@ +//======================================================================== +// +// OutputDev.cc +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include +#include "Object.h" +#include "Stream.h" +#include "GfxState.h" +#include "OutputDev.h" + +//------------------------------------------------------------------------ +// OutputDev +//------------------------------------------------------------------------ + +void OutputDev::setDefaultCTM(double *ctm1) { + int i; + double det; + + for (i = 0; i < 6; ++i) + ctm[i] = ctm1[i]; + det = 1 / (ctm[0] * ctm[3] - ctm[1] * ctm[2]); + ictm[0] = ctm[3] * det; + ictm[1] = -ctm[1] * det; + ictm[2] = -ctm[2] * det; + ictm[3] = ctm[0] * det; + ictm[4] = (ctm[2] * ctm[5] - ctm[3] * ctm[4]) * det; + ictm[5] = (ctm[1] * ctm[4] - ctm[0] * ctm[5]) * det; +} + +void OutputDev::cvtDevToUser(int dx, int dy, double *ux, double *uy) { + *ux = ictm[0] * dx + ictm[2] * dy + ictm[4]; + *uy = ictm[1] * dx + ictm[3] * dy + ictm[5]; +} + +void OutputDev::cvtUserToDev(double ux, double uy, int *dx, int *dy) { + *dx = (int)(ctm[0] * ux + ctm[2] * uy + ctm[4] + 0.5); + *dy = (int)(ctm[1] * ux + ctm[3] * uy + ctm[5] + 0.5); +} + +void OutputDev::updateAll(GfxState *state) { + updateLineDash(state); + updateFlatness(state); + updateLineJoin(state); + updateLineCap(state); + updateMiterLimit(state); + updateLineWidth(state); + updateFillColor(state); + updateStrokeColor(state); + updateFont(state); +} + +void OutputDev::drawImageMask(GfxState *state, Stream *str, + int width, int height, GBool invert, + GBool inlineImg) { + int i, j; + + if (inlineImg) { + str->reset(); + j = height * ((width + 7) / 8); + for (i = 0; i < j; ++i) + str->getChar(); + } +} + +void OutputDev::drawImage(GfxState *state, Stream *str, int width, + int height, GfxImageColorMap *colorMap, + GBool inlineImg) { + int i, j; + + if (inlineImg) { + str->reset(); + j = height * ((width * colorMap->getNumPixelComps() * + colorMap->getBits() + 7) / 8); + for (i = 0; i < j; ++i) + str->getChar(); + } +} + +#if OPI_SUPPORT +void OutputDev::opiBegin(GfxState *state, Dict *opiDict) { +} + +void OutputDev::opiEnd(GfxState *state, Dict *opiDict) { +} +#endif diff --git a/pdftops/OutputDev.h b/pdftops/OutputDev.h new file mode 100644 index 0000000000..6d11ae8e59 --- /dev/null +++ b/pdftops/OutputDev.h @@ -0,0 +1,138 @@ +//======================================================================== +// +// OutputDev.h +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#ifndef OUTPUTDEV_H +#define OUTPUTDEV_H + +#ifdef __GNUC__ +#pragma interface +#endif + +#include "gtypes.h" + +class GString; +class GfxState; +class GfxColorSpace; +class GfxImageColorMap; +class Stream; +class Link; +class Catalog; + +//------------------------------------------------------------------------ +// OutputDev +//------------------------------------------------------------------------ + +class OutputDev { +public: + + // Constructor. + OutputDev() {} + + // Destructor. + virtual ~OutputDev() {} + + //----- get info about output device + + // Does this device use upside-down coordinates? + // (Upside-down means (0,0) is the top left corner of the page.) + virtual GBool upsideDown() = 0; + + // Does this device use drawChar() or drawString()? + virtual GBool useDrawChar() = 0; + + //----- initialization and control + + // Set default transform matrix. + virtual void setDefaultCTM(double *ctm1); + + // Start a page. + virtual void startPage(int pageNum, GfxState *state) {} + + // End a page. + virtual void endPage() {} + + // Dump page contents to display. + virtual void dump() {} + + //----- coordinate conversion + + // Convert between device and user coordinates. + virtual void cvtDevToUser(int dx, int dy, double *ux, double *uy); + virtual void cvtUserToDev(double ux, double uy, int *dx, int *dy); + + //----- link borders + virtual void drawLink(Link *link, Catalog *catalog) {} + + //----- save/restore graphics state + virtual void saveState(GfxState *state) {} + virtual void restoreState(GfxState *state) {} + + //----- update graphics state + virtual void updateAll(GfxState *state); + virtual void updateCTM(GfxState *state, double m11, double m12, + double m21, double m22, double m31, double m32) {} + virtual void updateLineDash(GfxState *state) {} + virtual void updateFlatness(GfxState *state) {} + virtual void updateLineJoin(GfxState *state) {} + virtual void updateLineCap(GfxState *state) {} + virtual void updateMiterLimit(GfxState *state) {} + virtual void updateLineWidth(GfxState *state) {} + virtual void updateFillColor(GfxState *state) {} + virtual void updateStrokeColor(GfxState *state) {} + + //----- update text state + virtual void updateFont(GfxState *state) {} + virtual void updateTextMat(GfxState *state) {} + virtual void updateCharSpace(GfxState *state) {} + virtual void updateRender(GfxState *state) {} + virtual void updateRise(GfxState *state) {} + virtual void updateWordSpace(GfxState *state) {} + virtual void updateHorizScaling(GfxState *state) {} + virtual void updateTextPos(GfxState *state) {} + virtual void updateTextShift(GfxState *state, double shift) {} + + //----- path painting + virtual void stroke(GfxState *state) {} + virtual void fill(GfxState *state) {} + virtual void eoFill(GfxState *state) {} + + //----- path clipping + virtual void clip(GfxState *state) {} + virtual void eoClip(GfxState *state) {} + + //----- text drawing + virtual void beginString(GfxState *state, GString *s) {} + virtual void endString(GfxState *state) {} + virtual void drawChar(GfxState *state, double x, double y, + double dx, double dy, Guchar c) {} + virtual void drawChar16(GfxState *state, double x, double y, + double dx, double dy, int c) {} + virtual void drawString(GfxState *state, GString *s) {} + virtual void drawString16(GfxState *state, GString *s) {} + + //----- image drawing + virtual void drawImageMask(GfxState *state, Stream *str, + int width, int height, GBool invert, + GBool inlineImg); + virtual void drawImage(GfxState *state, Stream *str, int width, + int height, GfxImageColorMap *colorMap, + GBool inlineImg); + +#if OPI_SUPPORT + //----- OPI functions + virtual void opiBegin(GfxState *state, Dict *opiDict); + virtual void opiEnd(GfxState *state, Dict *opiDict); +#endif + +private: + + double ctm[6]; // coordinate transform matrix + double ictm[6]; // inverse CTM +}; + +#endif diff --git a/pdftops/PDFDoc.cxx b/pdftops/PDFDoc.cxx new file mode 100644 index 0000000000..8d62450d1a --- /dev/null +++ b/pdftops/PDFDoc.cxx @@ -0,0 +1,250 @@ +//======================================================================== +// +// PDFDoc.cc +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include +#include +#include +#include +#include "GString.h" +#include "config.h" +#include "Page.h" +#include "Catalog.h" +#include "Stream.h" +#include "XRef.h" +#include "Link.h" +#include "OutputDev.h" +#include "Params.h" +#include "Error.h" +#include "Lexer.h" +#include "Parser.h" +#include "PDFDoc.h" + +//------------------------------------------------------------------------ + +#define headerSearchSize 1024 // read this many bytes at beginning of + // file to look for '%PDF' + +//------------------------------------------------------------------------ +// PDFDoc +//------------------------------------------------------------------------ + +PDFDoc::PDFDoc(GString *fileName1, GString *userPassword) { + Object obj; + GString *fileName2; + + ok = gFalse; + + file = NULL; + str = NULL; + xref = NULL; + catalog = NULL; + links = NULL; + + // try to open file + fileName = fileName1; + fileName2 = NULL; +#ifdef VMS + if (!(file = fopen(fileName->getCString(), "rb", "ctx=stm"))) { + error(-1, "Couldn't open file '%s'", fileName->getCString()); + return; + } +#else + if (!(file = fopen(fileName->getCString(), "rb"))) { + fileName2 = fileName->copy(); + fileName2->lowerCase(); + if (!(file = fopen(fileName2->getCString(), "rb"))) { + fileName2->upperCase(); + if (!(file = fopen(fileName2->getCString(), "rb"))) { + error(-1, "Couldn't open file '%s'", fileName->getCString()); + delete fileName2; + return; + } + } + delete fileName2; + } +#endif + + // create stream + obj.initNull(); + str = new FileStream(file, 0, -1, &obj); + + ok = setup(userPassword); +} + +PDFDoc::PDFDoc(BaseStream *str, GString *userPassword) { + ok = gFalse; + fileName = NULL; + file = NULL; + this->str = str; + xref = NULL; + catalog = NULL; + links = NULL; + ok = setup(userPassword); +} + +GBool PDFDoc::setup(GString *userPassword) { + Object catObj; + + // check header + checkHeader(); + + // read xref table + xref = new XRef(str, userPassword); + if (!xref->isOk()) { + error(-1, "Couldn't read xref table"); + return gFalse; + } + + // read catalog + catalog = new Catalog(xref->getCatalog(&catObj)); + catObj.free(); + if (!catalog->isOk()) { + error(-1, "Couldn't read page catalog"); + return gFalse; + } + + // done + return gTrue; +} + +PDFDoc::~PDFDoc() { + if (catalog) { + delete catalog; + } + if (xref) { + delete xref; + } + if (str) { + delete str; + } + if (file) { + fclose(file); + } + if (fileName) { + delete fileName; + } + if (links) { + delete links; + } +} + +// Check for a PDF header on this stream. Skip past some garbage +// if necessary. +void PDFDoc::checkHeader() { + char hdrBuf[headerSearchSize+1]; + char *p; + int i; + + pdfVersion = 0; + for (i = 0; i < headerSearchSize; ++i) { + hdrBuf[i] = str->getChar(); + } + hdrBuf[headerSearchSize] = '\0'; + for (i = 0; i < headerSearchSize - 5; ++i) { + if (!strncmp(&hdrBuf[i], "%PDF-", 5)) { + break; + } + } + if (i >= headerSearchSize - 5) { + error(-1, "May not be a PDF file (continuing anyway)"); + return; + } + str->moveStart(i); + p = strtok(&hdrBuf[i+5], " \t\n\r"); + pdfVersion = atof(p); + if (!(hdrBuf[i+5] >= '0' && hdrBuf[i+5] <= '9') || + pdfVersion > supportedPDFVersionNum + 0.0001) { + error(-1, "PDF version %s -- xpdf supports version %s" + " (continuing anyway)", p, supportedPDFVersionStr); + } +} + +void PDFDoc::displayPage(OutputDev *out, int page, int zoom, int rotate, + GBool doLinks) { + Page *p; + + if (printCommands) { + printf("***** page %d *****\n", page); + } + p = catalog->getPage(page); + if (doLinks) { + if (links) { + delete links; + } + getLinks(p); + p->display(out, zoom, rotate, links, catalog); + } else { + p->display(out, zoom, rotate, NULL, catalog); + } +} + +void PDFDoc::displayPages(OutputDev *out, int firstPage, int lastPage, + int zoom, int rotate, GBool doLinks) { + int page; + + for (page = firstPage; page <= lastPage; ++page) { + displayPage(out, page, zoom, rotate, doLinks); + } +} + +GBool PDFDoc::isLinearized() { + Parser *parser; + Object obj1, obj2, obj3, obj4, obj5; + GBool lin; + + lin = gFalse; + obj1.initNull(); + parser = new Parser(new Lexer(str->makeSubStream(str->getStart(), + -1, &obj1))); + parser->getObj(&obj1); + parser->getObj(&obj2); + parser->getObj(&obj3); + parser->getObj(&obj4); + if (obj1.isInt() && obj2.isInt() && obj3.isCmd("obj") && + obj4.isDict()) { + obj4.dictLookup("Linearized", &obj5); + if (obj5.isNum() && obj5.getNum() > 0) { + lin = gTrue; + } + obj5.free(); + } + obj4.free(); + obj3.free(); + obj2.free(); + obj1.free(); + delete parser; + return lin; +} + +GBool PDFDoc::saveAs(GString *name) { + FILE *f; + int c; + + if (!(f = fopen(name->getCString(), "wb"))) { + error(-1, "Couldn't open file '%s'", name->getCString()); + return gFalse; + } + str->reset(); + while ((c = str->getChar()) != EOF) { + fputc(c, f); + } + fclose(f); + return gTrue; +} + +void PDFDoc::getLinks(Page *page) { + Object obj; + + links = new Links(page->getAnnots(&obj), catalog->getBaseURI()); + obj.free(); +} + diff --git a/pdftops/PDFDoc.h b/pdftops/PDFDoc.h new file mode 100644 index 0000000000..eb2c9581e6 --- /dev/null +++ b/pdftops/PDFDoc.h @@ -0,0 +1,125 @@ +//======================================================================== +// +// PDFDoc.h +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#ifndef PDFDOC_H +#define PDFDOC_H + +#ifdef __GNUC__ +#pragma interface +#endif + +#include +#include "Link.h" +#include "Catalog.h" +#include "Page.h" + +class GString; +class BaseStream; +class XRef; +class OutputDev; +class Links; +class LinkAction; +class LinkDest; + +//------------------------------------------------------------------------ +// PDFDoc +//------------------------------------------------------------------------ + +class PDFDoc { +public: + + PDFDoc(GString *fileName1, GString *userPassword = NULL); + PDFDoc(BaseStream *str, GString *userPassword = NULL); + ~PDFDoc(); + + // Was PDF document successfully opened? + GBool isOk() { return ok; } + + // Get file name. + GString *getFileName() { return fileName; } + + // Get catalog. + Catalog *getCatalog() { return catalog; } + + // Get base stream. + BaseStream *getBaseStream() { return str; } + + // Get page parameters. + double getPageWidth(int page) + { return catalog->getPage(page)->getWidth(); } + double getPageHeight(int page) + { return catalog->getPage(page)->getHeight(); } + int getPageRotate(int page) + { return catalog->getPage(page)->getRotate(); } + + // Get number of pages. + int getNumPages() { return catalog->getNumPages(); } + + // Display a page. + void displayPage(OutputDev *out, int page, int zoom, int rotate, + GBool doLinks); + + // Display a range of pages. + void displayPages(OutputDev *out, int firstPage, int lastPage, + int zoom, int rotate, GBool doLinks); + + // Find a page, given its object ID. Returns page number, or 0 if + // not found. + int findPage(int num, int gen) { return catalog->findPage(num, gen); } + + // If point , is in a link, return the associated action; + // else return NULL. + LinkAction *findLink(double x, double y) { return links->find(x, y); } + + // Return true if , is in a link. + GBool onLink(double x, double y) { return links->onLink(x, y); } + + // Find a named destination. Returns the link destination, or + // NULL if is not a destination. + LinkDest *findDest(GString *name) + { return catalog->findDest(name); } + + // Is the file encrypted? + GBool isEncrypted() { return xref->isEncrypted(); } + + // Check various permissions. + GBool okToPrint() { return xref->okToPrint(); } + GBool okToChange() { return xref->okToChange(); } + GBool okToCopy() { return xref->okToCopy(); } + GBool okToAddNotes() { return xref->okToAddNotes(); } + + // Is this document linearized? + GBool isLinearized(); + + // Return the document's Info dictionary (if any). + Object *getDocInfo(Object *obj) { return xref->getDocInfo(obj); } + + // Return the PDF version specified by the file. + double getPDFVersion() { return pdfVersion; } + + // Save this file with another name. + GBool saveAs(GString *name); + +private: + + GBool setup(GString *userPassword); + void checkHeader(); + void getLinks(Page *page); + + GString *fileName; + FILE *file; + BaseStream *str; + double pdfVersion; + XRef *xref; + Catalog *catalog; + Links *links; + + GBool ok; +}; + +#endif diff --git a/pdftops/PSOutputDev.cxx b/pdftops/PSOutputDev.cxx new file mode 100644 index 0000000000..982f582b87 --- /dev/null +++ b/pdftops/PSOutputDev.cxx @@ -0,0 +1,1919 @@ +//======================================================================== +// +// PSOutputDev.cc +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include +#include +#include +#include +#include +#include "GString.h" +#include "config.h" +#include "Object.h" +#include "Error.h" +#include "GfxState.h" +#include "GfxFont.h" +#include "FontFile.h" +#include "Catalog.h" +#include "Page.h" +#include "Stream.h" +#include "FormWidget.h" +#include "PSOutputDev.h" + +#if JAPANESE_SUPPORT +#include "Japan12ToRKSJ.h" +#endif + +#ifdef MACOS +// needed for setting type/creator of MacOS files +#include "ICSupport.h" +#endif + +//------------------------------------------------------------------------ +// Parameters +//------------------------------------------------------------------------ + +// Generate Level 1 PostScript? +GBool psOutLevel1 = gFalse; + +// Generate Encapsulated PostScript? +GBool psOutEPS = gFalse; + +#if OPI_SUPPORT +// Generate OPI comments? +GBool psOutOPI = gFalse; +#endif + +int paperWidth = 612; +int paperHeight = 792; + +//------------------------------------------------------------------------ +// PostScript prolog and setup +//------------------------------------------------------------------------ + +static char *prolog[] = { + "/xpdf 75 dict def xpdf begin", + "% PDF special state", + "/pdfDictSize 14 def", +#if 0 // Not used for CUPS - the pstops filter handles this... + "/pdfSetup {", + " 2 array astore", + " /setpagedevice where {", + " pop 3 dict dup begin", + " exch /PageSize exch def", + " /ImagingBBox null def", + " /Policies 1 dict dup begin /PageSize 3 def end def", + " end setpagedevice", + " } {", + " pop", + " } ifelse", + "} def", +#endif // 0 + "/pdfStartPage {", + " pdfDictSize dict begin", + " /pdfFill [0] def", + " /pdfStroke [0] def", + " /pdfLastFill false def", + " /pdfLastStroke false def", + " /pdfTextMat [1 0 0 1 0 0] def", + " /pdfFontSize 0 def", + " /pdfCharSpacing 0 def", + " /pdfTextRender 0 def", + " /pdfTextRise 0 def", + " /pdfWordSpacing 0 def", + " /pdfHorizScaling 1 def", + "} def", + "/pdfEndPage { end } def", + "/sCol { pdfLastStroke not {", + " pdfStroke aload length", + " 1 eq { setgray } { setrgbcolor} ifelse", + " /pdfLastStroke true def /pdfLastFill false def", + " } if } def", + "/fCol { pdfLastFill not {", + " pdfFill aload length", + " 1 eq { setgray } { setrgbcolor } ifelse", + " /pdfLastFill true def /pdfLastStroke false def", + " } if } def", + "% build a font", + "/pdfMakeFont {", + " 4 3 roll findfont", + " 4 2 roll matrix scale makefont", + " dup length dict begin", + " { 1 index /FID ne { def } { pop pop } ifelse } forall", + " /Encoding exch def", + " currentdict", + " end", + " definefont pop", + "} def", + "/pdfMakeFont16 { findfont definefont pop } def", + "% graphics state operators", + "/q { gsave pdfDictSize dict begin } def", + "/Q { end grestore } def", + "/cm { concat } def", + "/d { setdash } def", + "/i { setflat } def", + "/j { setlinejoin } def", + "/J { setlinecap } def", + "/M { setmiterlimit } def", + "/w { setlinewidth } def", + "% color operators", + "/g { dup 1 array astore /pdfFill exch def setgray", + " /pdfLastFill true def /pdfLastStroke false def } def", + "/G { dup 1 array astore /pdfStroke exch def setgray", + " /pdfLastStroke true def /pdfLastFill false def } def", + "/rg { 3 copy 3 array astore /pdfFill exch def setrgbcolor", + " /pdfLastFill true def /pdfLastStroke false def } def", + "/RG { 3 copy 3 array astore /pdfStroke exch def setrgbcolor", + " /pdfLastStroke true def /pdfLastFill false def } def", + "% path segment operators", + "/m { moveto } def", + "/l { lineto } def", + "/c { curveto } def", + "/re { 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto", + " neg 0 rlineto closepath } def", + "/h { closepath } def", + "% path painting operators", + "/S { sCol stroke } def", + "/f { fCol fill } def", + "/f* { fCol eofill } def", + "% clipping operators", + "/W { clip newpath } def", + "/W* { eoclip newpath } def", + "% text state operators", + "/Tc { /pdfCharSpacing exch def } def", + "/Tf { dup /pdfFontSize exch def", + " dup pdfHorizScaling mul exch matrix scale", + " pdfTextMat matrix concatmatrix dup 4 0 put dup 5 0 put", + " exch findfont exch makefont setfont } def", + "/Tr { /pdfTextRender exch def } def", + "/Ts { /pdfTextRise exch def } def", + "/Tw { /pdfWordSpacing exch def } def", + "/Tz { /pdfHorizScaling exch def } def", + "% text positioning operators", + "/Td { pdfTextMat transform moveto } def", + "/Tm { /pdfTextMat exch def } def", + "% text string operators", + "/Tj { pdfTextRender 1 and 0 eq { fCol } { sCol } ifelse", + " 0 pdfTextRise pdfTextMat dtransform rmoveto", + " pdfFontSize mul pdfHorizScaling mul", + " 1 index stringwidth pdfTextMat idtransform pop", + " sub 1 index length dup 0 ne { div } { pop pop 0 } ifelse", + " pdfWordSpacing 0 pdfTextMat dtransform 32", + " 4 3 roll pdfCharSpacing add 0 pdfTextMat dtransform", + " 6 5 roll awidthshow", + " 0 pdfTextRise neg pdfTextMat dtransform rmoveto } def", + "/TJm { pdfFontSize 0.001 mul mul neg 0", + " pdfTextMat dtransform rmoveto } def", + "% Level 1 image operators", + "/pdfIm1 {", + " /pdfImBuf1 4 index string def", + " { currentfile pdfImBuf1 readhexstring pop } image", + "} def", + "/pdfImM1 {", + " /pdfImBuf1 4 index 7 add 8 idiv string def", + " { currentfile pdfImBuf1 readhexstring pop } imagemask", + "} def", + "% Level 2 image operators", + "/pdfImBuf 100 string def", + "/pdfIm {", + " image", + " { currentfile pdfImBuf readline", + " not { pop exit } if", + " (%-EOD-) eq { exit } if } loop", + "} def", + "/pdfImM {", + " fCol imagemask", + " { currentfile pdfImBuf readline", + " not { pop exit } if", + " (%-EOD-) eq { exit } if } loop", + "} def", + "end", + NULL +}; + +//------------------------------------------------------------------------ +// Fonts +//------------------------------------------------------------------------ + +struct PSFont { + char *name; // PDF name + char *psName; // PostScript name +}; + +struct PSSubstFont { + char *psName; // PostScript name + double mWidth; // width of 'm' character +}; + +static PSFont psFonts[] = { + {"Courier", "Courier"}, + {"Courier-Bold", "Courier-Bold"}, + {"Courier-Oblique", "Courier-Bold"}, + {"Courier-BoldOblique", "Courier-BoldOblique"}, + {"Helvetica", "Helvetica"}, + {"Helvetica-Bold", "Helvetica-Bold"}, + {"Helvetica-Oblique", "Helvetica-Oblique"}, + {"Helvetica-BoldOblique", "Helvetica-BoldOblique"}, + {"Symbol", "Symbol"}, + {"Times-Roman", "Times-Roman"}, + {"Times-Bold", "Times-Bold"}, + {"Times-Italic", "Times-Italic"}, + {"Times-BoldItalic", "Times-BoldItalic"}, + {"ZapfDingbats", "ZapfDingbats"}, + {NULL} +}; + +static PSSubstFont psSubstFonts[] = { + {"Helvetica", 0.833}, + {"Helvetica-Oblique", 0.833}, + {"Helvetica-Bold", 0.889}, + {"Helvetica-BoldOblique", 0.889}, + {"Times-Roman", 0.788}, + {"Times-Italic", 0.722}, + {"Times-Bold", 0.833}, + {"Times-BoldItalic", 0.778}, + {"Courier", 0.600}, + {"Courier-Oblique", 0.600}, + {"Courier-Bold", 0.600}, + {"Courier-BoldOblique", 0.600} +}; + +//------------------------------------------------------------------------ +// PSOutputDev +//------------------------------------------------------------------------ + +PSOutputDev::PSOutputDev(char *fileName, Catalog *catalog, + int firstPage, int lastPage, + GBool embedType11, GBool doForm1) { + Page *page; + Dict *resDict; + FormWidgets *formWidgets; + char **p; + int pg; + Object obj1, obj2; + int i; + + // initialize + embedType1 = embedType11; + doForm = doForm1; + fontIDs = NULL; + fontFileIDs = NULL; + fontFileNames = NULL; + embFontList = NULL; + f = NULL; + if (doForm) + lastPage = firstPage; + + // open file or pipe + ok = gTrue; + if (!strcmp(fileName, "-")) { + fileType = psStdout; + f = stdout; + } else if (fileName[0] == '|') { + fileType = psPipe; +#ifdef HAVE_POPEN +#ifndef WIN32 + signal(SIGPIPE, (void (*)(int))SIG_IGN); +#endif + if (!(f = popen(fileName + 1, "w"))) { + error(-1, "Couldn't run print command '%s'", fileName); + ok = gFalse; + return; + } +#else + error(-1, "Print commands are not supported ('%s')", fileName); + ok = gFalse; + return; +#endif + } else { + fileType = psFile; + if (!(f = fopen(fileName, "w"))) { + error(-1, "Couldn't open PostScript file '%s'", fileName); + ok = gFalse; + return; + } + } + + // initialize fontIDs, fontFileIDs, and fontFileNames lists + fontIDSize = 64; + fontIDLen = 0; + fontIDs = (Ref *)gmalloc(fontIDSize * sizeof(Ref)); + fontFileIDSize = 64; + fontFileIDLen = 0; + fontFileIDs = (Ref *)gmalloc(fontFileIDSize * sizeof(Ref)); + fontFileNameSize = 64; + fontFileNameLen = 0; + fontFileNames = (GString **)gmalloc(fontFileNameSize * sizeof(GString *)); + + // initialize embedded font resource comment list + embFontList = new GString(); + + // write header + if (doForm) { + writePS("%%!PS-Adobe-3.0 Resource-Form\n"); + writePS("%%%%Creator: xpdf/pdftops %s\n", xpdfVersion); + writePS("%%%%LanguageLevel: %d\n", psOutLevel1 ? 1 : 2); + writePS("%%%%EndComments\n"); + } else if (psOutEPS) { + writePS("%%!PS-Adobe-3.0 EPSF-3.0\n"); + writePS("%%%%Creator: xpdf/pdftops %s\n", xpdfVersion); + writePS("%%%%LanguageLevel: %d\n", psOutLevel1 ? 1 : 2); + page = catalog->getPage(firstPage); + writePS("%%%%BoundingBox: %d %d %d %d\n", + (int)floor(page->getX1()), (int)floor(page->getY1()), + (int)ceil(page->getX2()), (int)ceil(page->getY2())); + if (floor(page->getX1()) != ceil(page->getX1()) || + floor(page->getY1()) != ceil(page->getY1()) || + floor(page->getX2()) != ceil(page->getX2()) || + floor(page->getY2()) != ceil(page->getY2())) { + writePS("%%%%HiResBoundingBox: %g %g %g %g\n", + page->getX1(), page->getY1(), + page->getX2(), page->getY2()); + } + writePS("%%%%DocumentSuppliedResources:\n"); + writePS("%%%%+ font: (atend)\n"); + writePS("%%%%EndComments\n"); + } else { + writePS("%%!PS-Adobe-3.0\n"); + writePS("%%%%Creator: xpdf/pdftops %s\n", xpdfVersion); + writePS("%%%%LanguageLevel: %d\n", psOutLevel1 ? 1 : 2); + writePS("%%%%DocumentMedia: plain %d %d 0 () ()\n", + paperWidth, paperHeight); + writePS("%%%%Pages: %d\n", lastPage - firstPage + 1); + writePS("%%%%EndComments\n"); + writePS("%%%%BeginDefaults\n"); + writePS("%%%%PageMedia: plain\n"); + writePS("%%%%EndDefaults\n"); + } + + // write prolog + if (!doForm) + writePS("%%%%BeginProlog\n"); + writePS("%%%%BeginResource: xpdf %s\n", xpdfVersion); + for (p = prolog; *p; ++p) + writePS("%s\n", *p); + writePS("%%%%EndResource\n"); + if (!doForm) + writePS("%%%%EndProlog\n"); + + // set up fonts + if (!doForm) + writePS("%%%%BeginSetup\n"); + writePS("xpdf begin\n"); + for (pg = firstPage; pg <= lastPage; ++pg) { + page = catalog->getPage(pg); + if ((resDict = page->getResourceDict())) { + setupFonts(resDict); + } + formWidgets = new FormWidgets(page->getAnnots(&obj1)); + obj1.free(); + for (i = 0; i < formWidgets->getNumWidgets(); ++i) { + if (formWidgets->getWidget(i)->getAppearance(&obj1)->isStream()) { + obj1.streamGetDict()->lookup("Resources", &obj2); + if (obj2.isDict()) { + setupFonts(obj2.getDict()); + } + obj2.free(); + } + obj1.free(); + } + delete formWidgets; + } + if (doForm) { + writePS("end\n"); + } else { +#if OPI_SUPPORT + if (psOutOPI) { + writePS("/opiMatrix matrix currentmatrix def\n"); + } +#endif + if (!psOutEPS) { +// pdfSetup not used for CUPS filter... +// writePS("%d %d pdfSetup\n", paperWidth, paperHeight); + } + writePS("%%%%EndSetup\n"); + } + + // write form header + if (doForm) { + page = catalog->getPage(firstPage); + writePS("4 dict dup begin\n"); + writePS("/BBox [%d %d %d %d] def\n", + (int)page->getX1(), (int)page->getY1(), + (int)page->getX2(), (int)page->getY2()); + writePS("/FormType 1 def\n"); + writePS("/Matrix [1 0 0 1 0 0] def\n"); + } + + // initialize sequential page number + seqPage = 1; + +#if OPI_SUPPORT + // initialize OPI nesting levels + opi13Nest = 0; + opi20Nest = 0; +#endif +} + +PSOutputDev::~PSOutputDev() { + int i; + + if (f) { + if (doForm) { + writePS("end\n"); + writePS("/Foo exch /Form defineresource pop\n"); + } else if (psOutEPS) { + writePS("%%%%Trailer\n"); + writePS("end\n"); + writePS("%%%%DocumentSuppliedResources:\n"); + writePS("%s", embFontList->getCString()); + writePS("%%%%EOF\n"); + } else { + writePS("%%%%Trailer\n"); + writePS("end\n"); + writePS("%%%%EOF\n"); + } + if (fileType == psFile) { +#ifdef MACOS + ICS_MapRefNumAndAssign((short)f->handle); +#endif + fclose(f); + } +#ifdef HAVE_POPEN + else if (fileType == psPipe) { + pclose(f); +#ifndef WIN32 + signal(SIGPIPE, (void (*)(int))SIG_DFL); +#endif + } +#endif + } + if (embFontList) { + delete embFontList; + } + if (fontIDs) { + gfree(fontIDs); + } + if (fontFileIDs) { + gfree(fontFileIDs); + } + if (fontFileNames) { + for (i = 0; i < fontFileNameLen; ++i) { + delete fontFileNames[i]; + } + gfree(fontFileNames); + } +} + +void PSOutputDev::setupFonts(Dict *resDict) { + Object fontDict, xObjDict, xObj, resObj; + GfxFontDict *gfxFontDict; + GfxFont *font; + int i; + + resDict->lookup("Font", &fontDict); + if (fontDict.isDict()) { + gfxFontDict = new GfxFontDict(fontDict.getDict()); + for (i = 0; i < gfxFontDict->getNumFonts(); ++i) { + font = gfxFontDict->getFont(i); + setupFont(font); + } + delete gfxFontDict; + } + fontDict.free(); + + resDict->lookup("XObject", &xObjDict); + if (xObjDict.isDict()) { + for (i = 0; i < xObjDict.dictGetLength(); ++i) { + xObjDict.dictGetVal(i, &xObj); + if (xObj.isStream()) { + xObj.streamGetDict()->lookup("Resources", &resObj); + if (resObj.isDict()) + setupFonts(resObj.getDict()); + resObj.free(); + } + xObj.free(); + } + } + xObjDict.free(); +} + +void PSOutputDev::setupFont(GfxFont *font) { + Ref fontFileID; + GString *name; + char *psName; + char *charName; + double xs, ys; + GBool do16Bit; + int code; + double w1, w2; + double *fm; + int i, j; + + // check if font is already set up + for (i = 0; i < fontIDLen; ++i) { + if (fontIDs[i].num == font->getID().num && + fontIDs[i].gen == font->getID().gen) + return; + } + + // add entry to fontIDs list + if (fontIDLen >= fontIDSize) { + fontIDSize += 64; + fontIDs = (Ref *)grealloc(fontIDs, fontIDSize * sizeof(Ref)); + } + fontIDs[fontIDLen++] = font->getID(); + + xs = ys = 1; + do16Bit = gFalse; + + // check for embedded Type 1 font + if (embedType1 && font->getType() == fontType1 && + font->getEmbeddedFontID(&fontFileID)) { + psName = font->getEmbeddedFontName(); + setupEmbeddedType1Font(&fontFileID, psName); + + // check for external Type 1 font file + } else if (embedType1 && font->getType() == fontType1 && + font->getExtFontFile()) { + // this assumes that the PS font name matches the PDF font name + psName = font->getName()->getCString(); + setupEmbeddedType1Font(font->getExtFontFile(), psName); + + // check for embedded Type 1C font + } else if (embedType1 && font->getType() == fontType1C && + font->getEmbeddedFontID(&fontFileID)) { + psName = font->getEmbeddedFontName(); + setupEmbeddedType1CFont(font, &fontFileID, psName); + + } else if (font->is16Bit() && font->getCharSet16() == font16AdobeJapan12) { + psName = "Ryumin-Light-RKSJ"; + do16Bit = gTrue; + + // do font substitution + } else { + name = font->getName(); + psName = NULL; + if (name) { + for (i = 0; psFonts[i].name; ++i) { + if (name->cmp(psFonts[i].name) == 0) { + psName = psFonts[i].psName; + break; + } + } + } + if (!psName) { + if (font->isFixedWidth()) + i = 8; + else if (font->isSerif()) + i = 4; + else + i = 0; + if (font->isBold()) + i += 2; + if (font->isItalic()) + i += 1; + psName = psSubstFonts[i].psName; + if ((code = font->getCharCode("m")) >= 0) { + w1 = font->getWidth(code); + } else { + w1 = 0; + } + w2 = psSubstFonts[i].mWidth; + xs = w1 / w2; + if (xs < 0.1) { + xs = 1; + } + if (font->getType() == fontType3) { + // This is a hack which makes it possible to substitute for some + // Type 3 fonts. The problem is that it's impossible to know what + // the base coordinate system used in the font is without actually + // rendering the font. + ys = xs; + fm = font->getFontMatrix(); + if (fm[0] != 0) { + ys *= fm[3] / fm[0]; + } + } else { + ys = 1; + } + } + } + + // generate PostScript code to set up the font + if (do16Bit) { + writePS("/F%d_%d /%s pdfMakeFont16\n", + font->getID().num, font->getID().gen, psName); + } else { + writePS("/F%d_%d /%s %g %g\n", + font->getID().num, font->getID().gen, psName, xs, ys); + for (i = 0; i < 256; i += 8) { + writePS((i == 0) ? "[ " : " "); + for (j = 0; j < 8; ++j) { + charName = font->getCharName(i+j); + writePS("/%s", charName ? charName : ".notdef"); + } + writePS((i == 256-8) ? "]\n" : "\n"); + } + writePS("pdfMakeFont\n"); + } +} + +void PSOutputDev::setupEmbeddedType1Font(Ref *id, char *psName) { + static char hexChar[17] = "0123456789abcdef"; + Object refObj, strObj, obj1, obj2; + Dict *dict; + int length1, length2; + int c; + int start[4]; + GBool binMode; + int i; + + // check if font is already embedded + for (i = 0; i < fontFileIDLen; ++i) { + if (fontFileIDs[i].num == id->num && + fontFileIDs[i].gen == id->gen) + return; + } + + // add entry to fontFileIDs list + if (fontFileIDLen >= fontFileIDSize) { + fontFileIDSize += 64; + fontFileIDs = (Ref *)grealloc(fontFileIDs, fontFileIDSize * sizeof(Ref)); + } + fontFileIDs[fontFileIDLen++] = *id; + + // get the font stream and info + refObj.initRef(id->num, id->gen); + refObj.fetch(&strObj); + refObj.free(); + if (!strObj.isStream()) { + error(-1, "Embedded font file object is not a stream"); + goto err1; + } + if (!(dict = strObj.streamGetDict())) { + error(-1, "Embedded font stream is missing its dictionary"); + goto err1; + } + dict->lookup("Length1", &obj1); + dict->lookup("Length2", &obj2); + if (!obj1.isInt() || !obj2.isInt()) { + error(-1, "Missing length fields in embedded font stream dictionary"); + obj1.free(); + obj2.free(); + goto err1; + } + length1 = obj1.getInt(); + length2 = obj2.getInt(); + obj1.free(); + obj2.free(); + + // beginning comment + if (psOutEPS) { + writePS("%%%%BeginResource: font %s\n", psName); + embFontList->append("%%+ font "); + embFontList->append(psName); + embFontList->append("\n"); + } + + // copy ASCII portion of font + strObj.streamReset(); + for (i = 0; i < length1 && (c = strObj.streamGetChar()) != EOF; ++i) + fputc(c, f); + + // figure out if encrypted portion is binary or ASCII + binMode = gFalse; + for (i = 0; i < 4; ++i) { + start[i] = strObj.streamGetChar(); + if (start[i] == EOF) { + error(-1, "Unexpected end of file in embedded font stream"); + goto err1; + } + if (!((start[i] >= '0' && start[i] <= '9') || + (start[i] >= 'A' && start[i] <= 'F') || + (start[i] >= 'a' && start[i] <= 'f'))) + binMode = gTrue; + } + + // convert binary data to ASCII + if (binMode) { + for (i = 0; i < 4; ++i) { + fputc(hexChar[(start[i] >> 4) & 0x0f], f); + fputc(hexChar[start[i] & 0x0f], f); + } + while (i < length2) { + if ((c = strObj.streamGetChar()) == EOF) + break; + fputc(hexChar[(c >> 4) & 0x0f], f); + fputc(hexChar[c & 0x0f], f); + if (++i % 32 == 0) + fputc('\n', f); + } + if (i % 32 > 0) + fputc('\n', f); + + // already in ASCII format -- just copy it + } else { + for (i = 0; i < 4; ++i) + fputc(start[i], f); + for (i = 4; i < length2; ++i) { + if ((c = strObj.streamGetChar()) == EOF) + break; + fputc(c, f); + } + } + + // write padding and "cleartomark" + for (i = 0; i < 8; ++i) + writePS("00000000000000000000000000000000" + "00000000000000000000000000000000\n"); + writePS("cleartomark\n"); + + // ending comment + if (psOutEPS) { + writePS("%%%%EndResource\n"); + } + + err1: + strObj.free(); +} + +//~ This doesn't handle .pfb files or binary eexec data (which only +//~ happens in pfb files?). +void PSOutputDev::setupEmbeddedType1Font(GString *fileName, char *psName) { + FILE *fontFile; + int c; + int i; + + // check if font is already embedded + for (i = 0; i < fontFileNameLen; ++i) { + if (!fontFileNames[i]->cmp(fileName)) { + return; + } + } + + // add entry to fontFileNames list + if (fontFileNameLen >= fontFileNameSize) { + fontFileNameSize += 64; + fontFileNames = (GString **)grealloc(fontFileNames, + fontFileNameSize * sizeof(GString *)); + } + fontFileNames[fontFileNameLen++] = fileName->copy(); + + // beginning comment + if (psOutEPS) { + writePS("%%%%BeginResource: font %s\n", psName); + embFontList->append("%%+ font "); + embFontList->append(psName); + embFontList->append("\n"); + } + + // copy the font file + if (!(fontFile = fopen(fileName->getCString(), "rb"))) { + error(-1, "Couldn't open external font file"); + return; + } + while ((c = fgetc(fontFile)) != EOF) + fputc(c, f); + fclose(fontFile); + + // ending comment + if (psOutEPS) { + writePS("%%%%EndResource\n"); + } +} + +void PSOutputDev::setupEmbeddedType1CFont(GfxFont *font, Ref *id, + char *psName) { + char *fontBuf; + int fontLen; + Type1CFontConverter *cvt; + int i; + + // check if font is already embedded + for (i = 0; i < fontFileIDLen; ++i) { + if (fontFileIDs[i].num == id->num && + fontFileIDs[i].gen == id->gen) + return; + } + + // add entry to fontFileIDs list + if (fontFileIDLen >= fontFileIDSize) { + fontFileIDSize += 64; + fontFileIDs = (Ref *)grealloc(fontFileIDs, fontFileIDSize * sizeof(Ref)); + } + fontFileIDs[fontFileIDLen++] = *id; + + // beginning comment + if (psOutEPS) { + writePS("%%%%BeginResource: font %s\n", psName); + embFontList->append("%%+ font "); + embFontList->append(psName); + embFontList->append("\n"); + } + + // convert it to a Type 1 font + fontBuf = font->readEmbFontFile(&fontLen); + cvt = new Type1CFontConverter(fontBuf, fontLen, f); + cvt->convert(); + delete cvt; + gfree(fontBuf); + + // ending comment + if (psOutEPS) { + writePS("%%%%EndResource\n"); + } +} + +void PSOutputDev::startPage(int pageNum, GfxState *state) { + int x1, y1, x2, y2, width, height, t; + + if (doForm) { + + writePS("/PaintProc {\n"); + writePS("begin xpdf begin\n"); + writePS("pdfStartPage\n"); + tx = ty = 0; + xScale = yScale = 1; + landscape = gFalse; + + } else if (psOutEPS) { + + writePS("pdfStartPage\n"); + tx = ty = 0; + xScale = yScale = 1; + landscape = gFalse; + + } else { + + writePS("%%%%Page: %d %d\n", pageNum, seqPage); + writePS("%%%%BeginPageSetup\n"); + + // rotate, translate, and scale page + x1 = (int)(state->getX1() + 0.5); + y1 = (int)(state->getY1() + 0.5); + x2 = (int)(state->getX2() + 0.5); + y2 = (int)(state->getY2() + 0.5); + width = x2 - x1; + height = y2 - y1; + if (width > height && width > paperWidth) { + landscape = gTrue; + writePS("%%%%PageOrientation: Landscape\n"); + writePS("pdfStartPage\n"); + writePS("90 rotate\n"); + tx = -x1; + ty = -(y1 + paperWidth); + t = width; + width = height; + height = t; + } else { + landscape = gFalse; + writePS("%%%%PageOrientation: Portrait\n"); + writePS("pdfStartPage\n"); + tx = -x1; + ty = -y1; + } + if (width < paperWidth) { + tx += (paperWidth - width) / 2; + } + if (height < paperHeight) { + ty += (paperHeight - height) / 2; + } + if (tx != 0 || ty != 0) { + writePS("%g %g translate\n", tx, ty); + } + if (width > paperWidth || height > paperHeight) { + xScale = (double)paperWidth / (double)width; + yScale = (double)paperHeight / (double)height; + if (yScale < xScale) { + xScale = yScale; + } + writePS("%0.4f %0.4f scale\n", xScale, xScale); + } else { + xScale = yScale = 1; + } + + writePS("%%%%EndPageSetup\n"); + ++seqPage; + } +} + +void PSOutputDev::endPage() { + if (doForm) { + writePS("pdfEndPage\n"); + writePS("end end\n"); + writePS("} def\n"); + } else { + writePS("showpage\n"); + writePS("%%%%PageTrailer\n"); + writePS("pdfEndPage\n"); + } +} + +void PSOutputDev::saveState(GfxState *state) { + writePS("q\n"); +} + +void PSOutputDev::restoreState(GfxState *state) { + writePS("Q\n"); +} + +void PSOutputDev::updateCTM(GfxState *state, double m11, double m12, + double m21, double m22, double m31, double m32) { + writePS("[%g %g %g %g %g %g] cm\n", m11, m12, m21, m22, m31, m32); +} + +void PSOutputDev::updateLineDash(GfxState *state) { + double *dash; + double start; + int length, i; + + state->getLineDash(&dash, &length, &start); + writePS("["); + for (i = 0; i < length; ++i) + writePS("%g%s", dash[i], (i == length-1) ? "" : " "); + writePS("] %g d\n", start); +} + +void PSOutputDev::updateFlatness(GfxState *state) { + writePS("%d i\n", state->getFlatness()); +} + +void PSOutputDev::updateLineJoin(GfxState *state) { + writePS("%d j\n", state->getLineJoin()); +} + +void PSOutputDev::updateLineCap(GfxState *state) { + writePS("%d J\n", state->getLineCap()); +} + +void PSOutputDev::updateMiterLimit(GfxState *state) { + writePS("%g M\n", state->getMiterLimit()); +} + +void PSOutputDev::updateLineWidth(GfxState *state) { + writePS("%g w\n", state->getLineWidth()); +} + +void PSOutputDev::updateFillColor(GfxState *state) { + GfxColor *color; + double r, g, b; + + color = state->getFillColor(); + r = color->getR(); + g = color->getG(); + b = color->getB(); + if (r == g && g == b) + writePS("%g g\n", r); + else + writePS("%g %g %g rg\n", r, g, b); +} + +void PSOutputDev::updateStrokeColor(GfxState *state) { + GfxColor *color; + double r, g, b; + + color = state->getStrokeColor(); + r = color->getR(); + g = color->getG(); + b = color->getB(); + if (r == g && g == b) + writePS("%g G\n", r); + else + writePS("%g %g %g RG\n", r, g, b); +} + +void PSOutputDev::updateFont(GfxState *state) { + if (state->getFont()) { + writePS("/F%d_%d %g Tf\n", + state->getFont()->getID().num, state->getFont()->getID().gen, + state->getFontSize()); + } +} + +void PSOutputDev::updateTextMat(GfxState *state) { + double *mat; + + mat = state->getTextMat(); + writePS("[%g %g %g %g %g %g] Tm\n", + mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]); +} + +void PSOutputDev::updateCharSpace(GfxState *state) { + writePS("%g Tc\n", state->getCharSpace()); +} + +void PSOutputDev::updateRender(GfxState *state) { + writePS("%d Tr\n", state->getRender()); +} + +void PSOutputDev::updateRise(GfxState *state) { + writePS("%g Ts\n", state->getRise()); +} + +void PSOutputDev::updateWordSpace(GfxState *state) { + writePS("%g Tw\n", state->getWordSpace()); +} + +void PSOutputDev::updateHorizScaling(GfxState *state) { + writePS("%g Tz\n", state->getHorizScaling()); +} + +void PSOutputDev::updateTextPos(GfxState *state) { + writePS("%g %g Td\n", state->getLineX(), state->getLineY()); +} + +void PSOutputDev::updateTextShift(GfxState *state, double shift) { + writePS("%g TJm\n", shift); +} + +void PSOutputDev::stroke(GfxState *state) { + doPath(state->getPath()); + writePS("S\n"); +} + +void PSOutputDev::fill(GfxState *state) { + doPath(state->getPath()); + writePS("f\n"); +} + +void PSOutputDev::eoFill(GfxState *state) { + doPath(state->getPath()); + writePS("f*\n"); +} + +void PSOutputDev::clip(GfxState *state) { + doPath(state->getPath()); + writePS("W\n"); +} + +void PSOutputDev::eoClip(GfxState *state) { + doPath(state->getPath()); + writePS("W*\n"); +} + +void PSOutputDev::doPath(GfxPath *path) { + GfxSubpath *subpath; + double x0, y0, x1, y1, x2, y2, x3, y3, x4, y4; + int n, m, i, j; + + n = path->getNumSubpaths(); + + if (n == 1 && path->getSubpath(0)->getNumPoints() == 5) { + subpath = path->getSubpath(0); + x0 = subpath->getX(0); + y0 = subpath->getY(0); + x4 = subpath->getX(4); + y4 = subpath->getY(4); + if (x4 == x0 && y4 == y0) { + x1 = subpath->getX(1); + y1 = subpath->getY(1); + x2 = subpath->getX(2); + y2 = subpath->getY(2); + x3 = subpath->getX(3); + y3 = subpath->getY(3); + if (x0 == x1 && x2 == x3 && y0 == y3 && y1 == y2) { + writePS("%g %g %g %g re\n", + x0 < x2 ? x0 : x2, y0 < y1 ? y0 : y1, + fabs(x2 - x0), fabs(y1 - y0)); + return; + } else if (x0 == x3 && x1 == x2 && y0 == y1 && y2 == y3) { + writePS("%g %g %g %g re\n", + x0 < x1 ? x0 : x1, y0 < y2 ? y0 : y2, + fabs(x1 - x0), fabs(y2 - y0)); + return; + } + } + } + + for (i = 0; i < n; ++i) { + subpath = path->getSubpath(i); + m = subpath->getNumPoints(); + writePS("%g %g m\n", subpath->getX(0), subpath->getY(0)); + j = 1; + while (j < m) { + if (subpath->getCurve(j)) { + writePS("%g %g %g %g %g %g c\n", subpath->getX(j), subpath->getY(j), + subpath->getX(j+1), subpath->getY(j+1), + subpath->getX(j+2), subpath->getY(j+2)); + j += 3; + } else { + writePS("%g %g l\n", subpath->getX(j), subpath->getY(j)); + ++j; + } + } + if (subpath->isClosed()) { + writePS("h\n"); + } + } +} + +void PSOutputDev::drawString(GfxState *state, GString *s) { + // check for invisible text -- this is used by Acrobat Capture + if ((state->getRender() & 3) == 3) + return; + + writePSString(s); + writePS(" %g Tj\n", state->getFont()->getWidth(s)); +} + +void PSOutputDev::drawString16(GfxState *state, GString *s) { + int c1, c2; + double w; + int i; + + // check for invisible text -- this is used by Acrobat Capture + if ((state->getRender() & 3) == 3) + return; + + switch (state->getFont()->getCharSet16()) { + + case font16AdobeJapan12: +#if JAPANESE_SUPPORT + writePS("<"); + w = 0; + for (i = 0; i < s->getLength(); i += 2) { + c1 = ((s->getChar(i) & 0xff) << 8) + (s->getChar(i+1) & 0xff); + if (c1 <= 8285) { + c2 = japan12ToRKSJ[c1]; + } else { + c2 = 0x20; + } + if (c2 <= 0xff) { + writePS("%02x", c2); + } else { + writePS("%02x%02x", c2 >> 8, c2 & 0xff); + } + w += state->getFont()->getWidth16(c1); + } + writePS("> %g Tj\n", w); +#endif + break; + + case font16AdobeGB12: + break; + } +} + +void PSOutputDev::drawImageMask(GfxState *state, Stream *str, + int width, int height, GBool invert, + GBool inlineImg) { + int len; + + len = height * ((width + 7) / 8); + if (psOutLevel1) + doImageL1(NULL, invert, inlineImg, str, width, height, len); + else + doImage(NULL, invert, inlineImg, str, width, height, len); +} + +void PSOutputDev::drawImage(GfxState *state, Stream *str, int width, + int height, GfxImageColorMap *colorMap, + GBool inlineImg) { + int len; + + len = height * ((width * colorMap->getNumPixelComps() * + colorMap->getBits() + 7) / 8); + if (psOutLevel1) + doImageL1(colorMap, gFalse, inlineImg, str, width, height, len); + else + doImage(colorMap, gFalse, inlineImg, str, width, height, len); +} + +void PSOutputDev::doImageL1(GfxImageColorMap *colorMap, + GBool invert, GBool inlineImg, + Stream *str, int width, int height, int len) { + ImageStream *imgStr; + Guchar pixBuf[4]; + GfxColor color; + int x, y, i; + + // width, height, matrix, bits per component + if (colorMap) { + writePS("%d %d 8 [%d 0 0 %d 0 %d] pdfIm1\n", + width, height, + width, -height, height); + } else { + writePS("%d %d %s [%d 0 0 %d 0 %d] pdfImM1\n", + width, height, invert ? "true" : "false", + width, -height, height); + } + + // image + if (colorMap) { + + // set up to process the data stream + imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(), + colorMap->getBits()); + imgStr->reset(); + + // process the data stream + i = 0; + for (y = 0; y < height; ++y) { + + // write the line + for (x = 0; x < width; ++x) { + imgStr->getPixel(pixBuf); + colorMap->getColor(pixBuf, &color); + fprintf(f, "%02x", (int)(color.getGray() * 255 + 0.5)); + if (++i == 32) { + fputc('\n', f); + i = 0; + } + } + } + if (i != 0) + fputc('\n', f); + delete imgStr; + + // imagemask + } else { + str->reset(); + i = 0; + for (y = 0; y < height; ++y) { + for (x = 0; x < width; x += 8) { + fprintf(f, "%02x", str->getChar() & 0xff); + if (++i == 32) { + fputc('\n', f); + i = 0; + } + } + } + if (i != 0) + fputc('\n', f); + } +} + +void PSOutputDev::doImage(GfxImageColorMap *colorMap, + GBool invert, GBool inlineImg, + Stream *str, int width, int height, int len) { + GfxColorSpace *colorSpace; + LabParams *labParams; + GString *s; + int n, numComps; + Guchar *color; + Guchar x[4]; + GfxColor rgb; + GBool useRLE, useA85; + int c; + int i, j, k; + + // color space + if (colorMap) { + colorSpace = colorMap->getColorSpace(); + if (colorSpace->isSeparation()) { + //~ this is a kludge -- the correct thing would be to output + //~ a separation color space + n = (1 << colorMap->getBits()) - 1; + writePS("[/Indexed /DeviceRGB %d <", n); + for (i = 0; i <= n; i += 8) { + writePS(" "); + for (j = i; j < i+8 && j <= n; ++j) { + x[0] = j; + colorMap->getColor(x, &rgb); + writePS("%02x%02x%02x", + (int)(255 * rgb.getR() + 0.5), + (int)(255 * rgb.getG() + 0.5), + (int)(255 * rgb.getB() + 0.5)); + } + writePS("\n"); + } + writePS("> ] setcolorspace\n"); + } else { + if (colorSpace->isIndexed()) { + writePS("[/Indexed "); + } + switch (colorSpace->getMode()) { + case colorGray: + writePS("/DeviceGray "); + break; + case colorCMYK: + writePS("/DeviceCMYK "); + break; + case colorRGB: + writePS("/DeviceRGB "); + break; + case colorLab: + labParams = colorSpace->getLabParams(); + writePS("[/CIEBasedABC <<\n"); + writePS(" /RangeABC [0 100 %g %g %g %g]\n", + labParams->aMin, labParams->aMax, + labParams->bMin, labParams->bMax); + writePS(" /DecodeABC [{16 add 116 div} bind {500 div} bind {200 div} bind]\n"); + writePS(" /MatrixABC [1 1 1 1 0 0 0 0 -1]\n"); + writePS(" /DecodeLMN\n"); + writePS(" [{dup 6 29 div ge {dup dup mul mul}\n"); + writePS(" {4 29 div sub 108 841 div mul } ifelse %g mul} bind\n", + labParams->whiteX); + writePS(" {dup 6 29 div ge {dup dup mul mul}\n"); + writePS(" {4 29 div sub 108 841 div mul } ifelse %g mul} bind\n", + labParams->whiteY); + writePS(" {dup 6 29 div ge {dup dup mul mul}\n"); + writePS(" {4 29 div sub 108 841 div mul } ifelse %g mul} bind]\n", + labParams->whiteZ); + writePS(" /WhitePoint [%g %g %g]\n", + labParams->whiteX, labParams->whiteY, labParams->whiteZ); + writePS(">>] "); + break; + } + if (colorSpace->isIndexed()) { + n = colorSpace->getIndexHigh(); + numComps = colorSpace->getNumColorComps(); + writePS("%d <\n", n); + for (i = 0; i <= n; i += 8) { + writePS(" "); + for (j = i; j < i+8 && j <= n; ++j) { + color = colorSpace->getLookupVal(j); + for (k = 0; k < numComps; ++k) { + writePS("%02x", color[k]); + } + } + writePS("\n"); + } + writePS("> ] setcolorspace\n"); + } else { + writePS("setcolorspace\n"); + } + } + } + + // image dictionary + writePS("<<\n /ImageType 1\n"); + + // width, height, matrix, bits per component + writePS(" /Width %d\n", width); + writePS(" /Height %d\n", height); + writePS(" /ImageMatrix [%d 0 0 %d 0 %d]\n", width, -height, height); + writePS(" /BitsPerComponent %d\n", + colorMap ? colorMap->getBits() : 1); + + // decode + if (colorMap) { + writePS(" /Decode ["); + if (colorMap->getColorSpace()->isSeparation()) { + //~ this is a kludge -- the correct thing would be to output + //~ a separation color space + n = (1 << colorMap->getBits()) - 1; + writePS("%g %g", colorMap->getDecodeLow(0) * n, + colorMap->getDecodeHigh(0) * n); + } else { + numComps = colorMap->getNumPixelComps(); + for (i = 0; i < numComps; ++i) { + if (i > 0) { + writePS(" "); + } + writePS("%g %g", colorMap->getDecodeLow(i), + colorMap->getDecodeHigh(i)); + } + } + writePS("]\n"); + } else { + writePS(" /Decode [%d %d]\n", invert ? 1 : 0, invert ? 0 : 1); + } + + if (doForm) { + + // data source + writePS(" /DataSource <~\n"); + + // write image data stream, using ASCII85 encode filter + if (inlineImg) { + str = new FixedLengthEncoder(str, len); + } + str = new ASCII85Encoder(str); + str->reset(); + while ((c = str->getChar()) != EOF) + fputc(c, f); + fputc('\n', f); + delete str; + + // end of image dictionary + writePS(">>\n%s\n", colorMap ? "image" : "imagemask"); + + } else { + + // data source + writePS(" /DataSource currentfile\n"); + s = str->getPSFilter(" "); + if (inlineImg || !s) { + useRLE = gTrue; + useA85 = gTrue; + } else { + useRLE = gFalse; + useA85 = str->isBinary(); + } + if (useA85) + writePS(" /ASCII85Decode filter\n"); + if (useRLE) + writePS(" /RunLengthDecode filter\n"); + else + writePS("%s", s->getCString()); + if (s) + delete s; + + // cut off inline image streams at appropriate length + if (inlineImg) + str = new FixedLengthEncoder(str, len); + else if (!useRLE) + str = str->getBaseStream(); + + // add RunLengthEncode and ASCII85 encode filters + if (useRLE) + str = new RunLengthEncoder(str); + if (useA85) + str = new ASCII85Encoder(str); + + // end of image dictionary + writePS(">>\n"); +#if OPI_SUPPORT + if (opi13Nest) { + if (inlineImg) { + // this can't happen -- OPI dictionaries are in XObjects + error(-1, "Internal: OPI in inline image"); + n = 0; + } else { + // need to read the stream to count characters -- the length + // is data-dependent (because of A85 and RLE filters) + str->reset(); + n = 0; + while ((c = str->getChar()) != EOF) { + ++n; + } + } + // +6/7 for "pdfIm\n" / "pdfImM\n" + // +8 for newline + trailer + n += colorMap ? 14 : 15; + writePS("%%%%BeginData: %d Hex Bytes\n", n); + } +#endif + writePS("%s\n", colorMap ? "pdfIm" : "pdfImM"); + + // copy the stream data + str->reset(); + while ((c = str->getChar()) != EOF) + fputc(c, f); + + // add newline and trailer to the end + fputc('\n', f); + fputs("%-EOD-\n", f); +#if OPI_SUPPORT + if (opi13Nest) { + writePS("%%%%EndData\n"); + } +#endif + + // delete encoders + if (useRLE || useA85) + delete str; + } +} + +#if OPI_SUPPORT +void PSOutputDev::opiBegin(GfxState *state, Dict *opiDict) { + Object dict; + + if (psOutOPI) { + opiDict->lookup("2.0", &dict); + if (dict.isDict()) { + opiBegin20(state, dict.getDict()); + dict.free(); + } else { + dict.free(); + opiDict->lookup("1.3", &dict); + if (dict.isDict()) { + opiBegin13(state, dict.getDict()); + } + dict.free(); + } + } +} + +void PSOutputDev::opiBegin20(GfxState *state, Dict *dict) { + Object obj1, obj2, obj3, obj4; + double width, height, left, right, top, bottom; + int w, h; + int i; + + writePS("%%%%BeginOPI: 2.0\n"); + writePS("%%%%Distilled\n"); + + dict->lookup("F", &obj1); + if (getFileSpec(&obj1, &obj2)) { + writePS("%%%%ImageFileName: %s\n", + obj2.getString()->getCString()); + obj2.free(); + } + obj1.free(); + + dict->lookup("MainImage", &obj1); + if (obj1.isString()) { + writePS("%%%%MainImage: %s\n", obj1.getString()->getCString()); + } + obj1.free(); + + //~ ignoring 'Tags' entry + //~ need to use writePSString() and deal with >255-char lines + + dict->lookup("Size", &obj1); + if (obj1.isArray() && obj1.arrayGetLength() == 2) { + obj1.arrayGet(0, &obj2); + width = obj2.getNum(); + obj2.free(); + obj1.arrayGet(1, &obj2); + height = obj2.getNum(); + obj2.free(); + writePS("%%%%ImageDimensions: %g %g\n", width, height); + } + obj1.free(); + + dict->lookup("CropRect", &obj1); + if (obj1.isArray() && obj1.arrayGetLength() == 4) { + obj1.arrayGet(0, &obj2); + left = obj2.getNum(); + obj2.free(); + obj1.arrayGet(1, &obj2); + top = obj2.getNum(); + obj2.free(); + obj1.arrayGet(2, &obj2); + right = obj2.getNum(); + obj2.free(); + obj1.arrayGet(3, &obj2); + bottom = obj2.getNum(); + obj2.free(); + writePS("%%%%ImageCropRect: %g %g %g %g\n", left, top, right, bottom); + } + obj1.free(); + + dict->lookup("Overprint", &obj1); + if (obj1.isBool()) { + writePS("%%%%ImageOverprint: %s\n", obj1.getBool() ? "true" : "false"); + } + obj1.free(); + + dict->lookup("Inks", &obj1); + if (obj1.isName()) { + writePS("%%%%ImageInks: %s\n", obj1.getName()); + } else if (obj1.isArray() && obj1.arrayGetLength() >= 1) { + obj1.arrayGet(0, &obj2); + if (obj2.isName()) { + writePS("%%%%ImageInks: %s %d", + obj2.getName(), (obj1.arrayGetLength() - 1) / 2); + for (i = 1; i+1 < obj1.arrayGetLength(); i += 2) { + obj1.arrayGet(i, &obj3); + obj1.arrayGet(i+1, &obj4); + if (obj3.isString() && obj4.isNum()) { + writePS(" "); + writePSString(obj3.getString()); + writePS(" %g", obj4.getNum()); + } + obj3.free(); + obj4.free(); + } + writePS("\n"); + } + obj2.free(); + } + obj1.free(); + + writePS("gsave\n"); + + writePS("%%%%BeginIncludedImage\n"); + + dict->lookup("IncludedImageDimensions", &obj1); + if (obj1.isArray() && obj1.arrayGetLength() == 2) { + obj1.arrayGet(0, &obj2); + w = obj2.getInt(); + obj2.free(); + obj1.arrayGet(1, &obj2); + h = obj2.getInt(); + obj2.free(); + writePS("%%%%IncludedImageDimensions: %d %d\n", w, h); + } + obj1.free(); + + dict->lookup("IncludedImageQuality", &obj1); + if (obj1.isNum()) { + writePS("%%%%IncludedImageQuality: %g\n", obj1.getNum()); + } + obj1.free(); + + ++opi20Nest; +} + +void PSOutputDev::opiBegin13(GfxState *state, Dict *dict) { + Object obj1, obj2; + int left, right, top, bottom, samples, bits, width, height; + double c, m, y, k; + double llx, lly, ulx, uly, urx, ury, lrx, lry; + double tllx, tlly, tulx, tuly, turx, tury, tlrx, tlry; + double horiz, vert; + int i, j; + + writePS("save\n"); + writePS("/opiMatrix2 matrix currentmatrix def\n"); + writePS("opiMatrix setmatrix\n"); + + dict->lookup("F", &obj1); + if (getFileSpec(&obj1, &obj2)) { + writePS("%%ALDImageFileName: %s\n", + obj2.getString()->getCString()); + obj2.free(); + } + obj1.free(); + + dict->lookup("CropRect", &obj1); + if (obj1.isArray() && obj1.arrayGetLength() == 4) { + obj1.arrayGet(0, &obj2); + left = obj2.getInt(); + obj2.free(); + obj1.arrayGet(1, &obj2); + top = obj2.getInt(); + obj2.free(); + obj1.arrayGet(2, &obj2); + right = obj2.getInt(); + obj2.free(); + obj1.arrayGet(3, &obj2); + bottom = obj2.getInt(); + obj2.free(); + writePS("%%ALDImageCropRect: %d %d %d %d\n", left, top, right, bottom); + } + obj1.free(); + + dict->lookup("Color", &obj1); + if (obj1.isArray() && obj1.arrayGetLength() == 5) { + obj1.arrayGet(0, &obj2); + c = obj2.getNum(); + obj2.free(); + obj1.arrayGet(1, &obj2); + m = obj2.getNum(); + obj2.free(); + obj1.arrayGet(2, &obj2); + y = obj2.getNum(); + obj2.free(); + obj1.arrayGet(3, &obj2); + k = obj2.getNum(); + obj2.free(); + obj1.arrayGet(4, &obj2); + if (obj2.isString()) { + writePS("%%ALDImageColor: %g %g %g %g ", c, m, y, k); + writePSString(obj2.getString()); + writePS("\n"); + } + obj2.free(); + } + obj1.free(); + + dict->lookup("ColorType", &obj1); + if (obj1.isName()) { + writePS("%%ALDImageColorType: %s\n", obj1.getName()); + } + obj1.free(); + + //~ ignores 'Comments' entry + //~ need to handle multiple lines + + dict->lookup("CropFixed", &obj1); + if (obj1.isArray()) { + obj1.arrayGet(0, &obj2); + ulx = obj2.getNum(); + obj2.free(); + obj1.arrayGet(1, &obj2); + uly = obj2.getNum(); + obj2.free(); + obj1.arrayGet(2, &obj2); + lrx = obj2.getNum(); + obj2.free(); + obj1.arrayGet(3, &obj2); + lry = obj2.getNum(); + obj2.free(); + writePS("%%ALDImageCropFixed: %g %g %g %g\n", ulx, uly, lrx, lry); + } + obj1.free(); + + dict->lookup("GrayMap", &obj1); + if (obj1.isArray()) { + writePS("%%ALDImageGrayMap:"); + for (i = 0; i < obj1.arrayGetLength(); i += 16) { + if (i > 0) { + writePS("\n%%%%+"); + } + for (j = 0; j < 16 && i+j < obj1.arrayGetLength(); ++j) { + obj1.arrayGet(i+j, &obj2); + writePS(" %d", obj2.getInt()); + obj2.free(); + } + } + writePS("\n"); + } + obj1.free(); + + dict->lookup("ID", &obj1); + if (obj1.isString()) { + writePS("%%ALDImageID: %s\n", obj1.getString()->getCString()); + } + obj1.free(); + + dict->lookup("ImageType", &obj1); + if (obj1.isArray() && obj1.arrayGetLength() == 2) { + obj1.arrayGet(0, &obj2); + samples = obj2.getInt(); + obj2.free(); + obj1.arrayGet(1, &obj2); + bits = obj2.getInt(); + obj2.free(); + writePS("%%ALDImageType: %d %d\n", samples, bits); + } + obj1.free(); + + dict->lookup("Overprint", &obj1); + if (obj1.isBool()) { + writePS("%%ALDImageOverprint: %s\n", obj1.getBool() ? "true" : "false"); + } + obj1.free(); + + dict->lookup("Position", &obj1); + if (obj1.isArray() && obj1.arrayGetLength() == 8) { + obj1.arrayGet(0, &obj2); + llx = obj2.getNum(); + obj2.free(); + obj1.arrayGet(1, &obj2); + lly = obj2.getNum(); + obj2.free(); + obj1.arrayGet(2, &obj2); + ulx = obj2.getNum(); + obj2.free(); + obj1.arrayGet(3, &obj2); + uly = obj2.getNum(); + obj2.free(); + obj1.arrayGet(4, &obj2); + urx = obj2.getNum(); + obj2.free(); + obj1.arrayGet(5, &obj2); + ury = obj2.getNum(); + obj2.free(); + obj1.arrayGet(6, &obj2); + lrx = obj2.getNum(); + obj2.free(); + obj1.arrayGet(7, &obj2); + lry = obj2.getNum(); + obj2.free(); + opiTransform(state, llx, lly, &tllx, &tlly); + opiTransform(state, ulx, uly, &tulx, &tuly); + opiTransform(state, urx, ury, &turx, &tury); + opiTransform(state, lrx, lry, &tlrx, &tlry); + writePS("%%ALDImagePosition: %g %g %g %g %g %g %g %g\n", + tllx, tlly, tulx, tuly, turx, tury, tlrx, tlry); + obj2.free(); + } + obj1.free(); + + dict->lookup("Resolution", &obj1); + if (obj1.isArray() && obj1.arrayGetLength() == 2) { + obj1.arrayGet(0, &obj2); + horiz = obj2.getNum(); + obj2.free(); + obj1.arrayGet(1, &obj2); + vert = obj2.getNum(); + obj2.free(); + writePS("%%ALDImageResoution: %g %g\n", horiz, vert); + obj2.free(); + } + obj1.free(); + + dict->lookup("Size", &obj1); + if (obj1.isArray() && obj1.arrayGetLength() == 2) { + obj1.arrayGet(0, &obj2); + width = obj2.getInt(); + obj2.free(); + obj1.arrayGet(1, &obj2); + height = obj2.getInt(); + obj2.free(); + writePS("%%ALDImageSize: %d %d\n", width, height); + } + obj1.free(); + + //~ ignoring 'Tags' entry + //~ need to use writePSString() and deal with >255-char lines + + dict->lookup("Tint", &obj1); + if (obj1.isNum()) { + writePS("%%ALDImageTint: %g\n", obj1.getNum()); + } + obj1.free(); + + dict->lookup("Transparency", &obj1); + if (obj1.isBool()) { + writePS("%%ALDImageTransparency: %s\n", obj1.getBool() ? "true" : "false"); + } + obj1.free(); + + writePS("%%%%BeginObject: image\n"); + writePS("opiMatrix2 setmatrix\n"); + ++opi13Nest; +} + +// Convert PDF user space coordinates to PostScript default user space +// coordinates. This has to account for both the PDF CTM and the +// PSOutputDev page-fitting transform. +void PSOutputDev::opiTransform(GfxState *state, double x0, double y0, + double *x1, double *y1) { + double t; + + state->transform(x0, y0, x1, y1); + *x1 += tx; + *y1 += ty; + if (landscape) { + t = *x1; + *x1 = -*y1; + *y1 = t; + } + *x1 *= xScale; + *y1 *= yScale; +} + +void PSOutputDev::opiEnd(GfxState *state, Dict *opiDict) { + Object dict; + + if (psOutOPI) { + opiDict->lookup("2.0", &dict); + if (dict.isDict()) { + writePS("%%%%EndIncludedImage\n"); + writePS("%%%%EndOPI\n"); + writePS("grestore\n"); + --opi20Nest; + dict.free(); + } else { + dict.free(); + opiDict->lookup("1.3", &dict); + if (dict.isDict()) { + writePS("%%%%EndObject\n"); + writePS("restore\n"); + --opi13Nest; + } + dict.free(); + } + } +} + +GBool PSOutputDev::getFileSpec(Object *fileSpec, Object *fileName) { + if (fileSpec->isString()) { + fileSpec->copy(fileName); + return gTrue; + } + if (fileSpec->isDict()) { + fileSpec->dictLookup("DOS", fileName); + if (fileName->isString()) { + return gTrue; + } + fileName->free(); + fileSpec->dictLookup("Mac", fileName); + if (fileName->isString()) { + return gTrue; + } + fileName->free(); + fileSpec->dictLookup("Unix", fileName); + if (fileName->isString()) { + return gTrue; + } + fileName->free(); + fileSpec->dictLookup("F", fileName); + if (fileName->isString()) { + return gTrue; + } + fileName->free(); + } + return gFalse; +} +#endif // OPI_SUPPORT + +void PSOutputDev::writePS(const char *fmt, ...) { + va_list args; + + va_start(args, fmt); + vfprintf(f, fmt, args); + va_end(args); +} + +void PSOutputDev::writePSString(GString *s) { + Guchar *p; + int n; + + fputc('(', f); + for (p = (Guchar *)s->getCString(), n = s->getLength(); n; ++p, --n) { + if (*p == '(' || *p == ')' || *p == '\\') + fprintf(f, "\\%c", *p); + else if (*p < 0x20 || *p >= 0x80) + fprintf(f, "\\%03o", *p); + else + fputc(*p, f); + } + fputc(')', f); +} diff --git a/pdftops/PSOutputDev.h b/pdftops/PSOutputDev.h new file mode 100644 index 0000000000..43d45ee0e3 --- /dev/null +++ b/pdftops/PSOutputDev.h @@ -0,0 +1,191 @@ +//======================================================================== +// +// PSOutputDev.h +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#ifndef PSOUTPUTDEV_H +#define PSOUTPUTDEV_H + +#ifdef __GNUC__ +#pragma interface +#endif + +#include +#include "config.h" +#include "Object.h" +#include "OutputDev.h" + +class GfxPath; +class GfxFont; + +//------------------------------------------------------------------------ +// Parameters +//------------------------------------------------------------------------ + +// Generate Level 1 PostScript? +extern GBool psOutLevel1; + +// Generate Encapsulated PostScript? +extern GBool psOutEPS; + +#if OPI_SUPPORT +// Generate OPI comments? +extern GBool psOutOPI; +#endif + +// Paper size. +extern int paperWidth; +extern int paperHeight; + +//------------------------------------------------------------------------ +// PSOutputDev +//------------------------------------------------------------------------ + +enum PSFileType { + psFile, // write to file + psPipe, // write to pipe + psStdout // write to stdout +}; + +class PSOutputDev: public OutputDev { +public: + + // Open a PostScript output file, and write the prolog. + PSOutputDev(char *fileName, Catalog *catalog, + int firstPage, int lastPage, + GBool embedType11, GBool doForm1); + + // Destructor -- writes the trailer and closes the file. + virtual ~PSOutputDev(); + + // Check if file was successfully created. + virtual GBool isOk() { return ok; } + + //---- get info about output device + + // Does this device use upside-down coordinates? + // (Upside-down means (0,0) is the top left corner of the page.) + virtual GBool upsideDown() { return gFalse; } + + // Does this device use drawChar() or drawString()? + virtual GBool useDrawChar() { return gFalse; } + + //----- initialization and control + + // Start a page. + virtual void startPage(int pageNum, GfxState *state); + + // End a page. + virtual void endPage(); + + //----- save/restore graphics state + virtual void saveState(GfxState *state); + virtual void restoreState(GfxState *state); + + //----- update graphics state + virtual void updateCTM(GfxState *state, double m11, double m12, + double m21, double m22, double m31, double m32); + virtual void updateLineDash(GfxState *state); + virtual void updateFlatness(GfxState *state); + virtual void updateLineJoin(GfxState *state); + virtual void updateLineCap(GfxState *state); + virtual void updateMiterLimit(GfxState *state); + virtual void updateLineWidth(GfxState *state); + virtual void updateFillColor(GfxState *state); + virtual void updateStrokeColor(GfxState *state); + + //----- update text state + virtual void updateFont(GfxState *state); + virtual void updateTextMat(GfxState *state); + virtual void updateCharSpace(GfxState *state); + virtual void updateRender(GfxState *state); + virtual void updateRise(GfxState *state); + virtual void updateWordSpace(GfxState *state); + virtual void updateHorizScaling(GfxState *state); + virtual void updateTextPos(GfxState *state); + virtual void updateTextShift(GfxState *state, double shift); + + //----- path painting + virtual void stroke(GfxState *state); + virtual void fill(GfxState *state); + virtual void eoFill(GfxState *state); + + //----- path clipping + virtual void clip(GfxState *state); + virtual void eoClip(GfxState *state); + + //----- text drawing + virtual void drawString(GfxState *state, GString *s); + virtual void drawString16(GfxState *state, GString *s); + + //----- image drawing + virtual void drawImageMask(GfxState *state, Stream *str, + int width, int height, GBool invert, + GBool inlineImg); + virtual void drawImage(GfxState *state, Stream *str, int width, + int height, GfxImageColorMap *colorMap, + GBool inlineImg); + +#if OPI_SUPPORT + //----- OPI functions + virtual void opiBegin(GfxState *state, Dict *opiDict); + virtual void opiEnd(GfxState *state, Dict *opiDict); +#endif + +private: + + void setupFonts(Dict *resDict); + void setupFont(GfxFont *font); + void setupEmbeddedType1Font(Ref *id, char *psName); + void setupEmbeddedType1Font(GString *fileName, char *psName); + void setupEmbeddedType1CFont(GfxFont *font, Ref *id, char *psName); + void doPath(GfxPath *path); + void doImageL1(GfxImageColorMap *colorMap, + GBool invert, GBool inlineImg, + Stream *str, int width, int height, int len); + void doImage(GfxImageColorMap *colorMap, + GBool invert, GBool inlineImg, + Stream *str, int width, int height, int len); + void opiBegin20(GfxState *state, Dict *dict); + void opiBegin13(GfxState *state, Dict *dict); + void opiTransform(GfxState *state, double x0, double y0, + double *x1, double *y1); + GBool getFileSpec(Object *fileSpec, Object *fileName); + void writePS(const char *fmt, ...); + void writePSString(GString *s); + + GBool embedType1; // embed Type 1 fonts? + GBool doForm; // generate a form? + + FILE *f; // PostScript file + PSFileType fileType; // file / pipe / stdout + int seqPage; // current sequential page number + + Ref *fontIDs; // list of object IDs of all used fonts + int fontIDLen; // number of entries in fontIDs array + int fontIDSize; // size of fontIDs array + Ref *fontFileIDs; // list of object IDs of all embedded fonts + int fontFileIDLen; // number of entries in fontFileIDs array + int fontFileIDSize; // size of fontFileIDs array + GString **fontFileNames; // list of names of all embedded external fonts + int fontFileNameLen; // number of entries in fontFileNames array + int fontFileNameSize; // size of fontFileNames array + + double tx, ty; // global translation + double xScale, yScale; // global scaling + GBool landscape; // true for landscape, false for portrait + + GString *embFontList; // resource comments for embedded fonts + +#if OPI_SUPPORT + int opi13Nest; // nesting level of OPI 1.3 objects + int opi20Nest; // nesting level of OPI 2.0 objects +#endif + + GBool ok; // set up ok? +}; + +#endif diff --git a/pdftops/Page.cxx b/pdftops/Page.cxx new file mode 100644 index 0000000000..2f4d2796c7 --- /dev/null +++ b/pdftops/Page.cxx @@ -0,0 +1,242 @@ +//======================================================================== +// +// Page.cc +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include +#include "Object.h" +#include "Array.h" +#include "Dict.h" +#include "XRef.h" +#include "Link.h" +#include "OutputDev.h" +#ifndef PDF_PARSER_ONLY +#include "Gfx.h" +#include "FormWidget.h" +#endif +#include "Error.h" + +#include "Params.h" +#include "Page.h" + +//------------------------------------------------------------------------ +// PageAttrs +//------------------------------------------------------------------------ + +PageAttrs::PageAttrs(PageAttrs *attrs, Dict *dict) { + Object obj1, obj2; + double w, h; + + // get old/default values + if (attrs) { + x1 = attrs->x1; + y1 = attrs->y1; + x2 = attrs->x2; + y2 = attrs->y2; + cropX1 = attrs->cropX1; + cropY1 = attrs->cropY1; + cropX2 = attrs->cropX2; + cropY2 = attrs->cropY2; + rotate = attrs->rotate; + attrs->resources.copy(&resources); + } else { + // set default MediaBox to 8.5" x 11" -- this shouldn't be necessary + // but some (non-compliant) PDF files don't specify a MediaBox + x1 = 0; + y1 = 0; + x2 = 612; + y2 = 792; + cropX1 = cropY1 = cropX2 = cropY2 = 0; + rotate = 0; + resources.initNull(); + } + + // media box + dict->lookup("MediaBox", &obj1); + if (obj1.isArray() && obj1.arrayGetLength() == 4) { + obj1.arrayGet(0, &obj2); + if (obj2.isNum()) + x1 = obj2.getNum(); + obj2.free(); + obj1.arrayGet(1, &obj2); + if (obj2.isNum()) + y1 = obj2.getNum(); + obj2.free(); + obj1.arrayGet(2, &obj2); + if (obj2.isNum()) + x2 = obj2.getNum(); + obj2.free(); + obj1.arrayGet(3, &obj2); + if (obj2.isNum()) + y2 = obj2.getNum(); + obj2.free(); + } + obj1.free(); + + // crop box + dict->lookup("CropBox", &obj1); + if (obj1.isArray() && obj1.arrayGetLength() == 4) { + obj1.arrayGet(0, &obj2); + if (obj2.isNum()) + cropX1 = obj2.getNum(); + obj2.free(); + obj1.arrayGet(1, &obj2); + if (obj2.isNum()) + cropY1 = obj2.getNum(); + obj2.free(); + obj1.arrayGet(2, &obj2); + if (obj2.isNum()) + cropX2 = obj2.getNum(); + obj2.free(); + obj1.arrayGet(3, &obj2); + if (obj2.isNum()) + cropY2 = obj2.getNum(); + obj2.free(); + } + obj1.free(); + + // if the MediaBox is excessively larger than the CropBox, + // just use the CropBox + limitToCropBox = gFalse; + w = 0.25 * (cropX2 - cropX1); + h = 0.25 * (cropY2 - cropY1); + if (cropX2 > cropX1 && + ((cropX1 - x1) + (x2 - cropX2) > w || + (cropY1 - y1) + (y2 - cropY2) > h)) { + limitToCropBox = gTrue; + } + + // rotate + dict->lookup("Rotate", &obj1); + if (obj1.isInt()) + rotate = obj1.getInt(); + obj1.free(); + while (rotate < 0) + rotate += 360; + while (rotate >= 360) + rotate -= 360; + + // resource dictionary + dict->lookup("Resources", &obj1); + if (obj1.isDict()) { + resources.free(); + obj1.copy(&resources); + } + obj1.free(); +} + +PageAttrs::~PageAttrs() { + resources.free(); +} + +//------------------------------------------------------------------------ +// Page +//------------------------------------------------------------------------ + +Page::Page(int num1, Dict *pageDict, PageAttrs *attrs1) { + + ok = gTrue; + num = num1; + + // get attributes + attrs = attrs1; + + // annotations + pageDict->lookupNF("Annots", &annots); + if (!(annots.isRef() || annots.isArray() || annots.isNull())) { + error(-1, "Page annotations object (page %d) is wrong type (%s)", + num, annots.getTypeName()); + annots.free(); + goto err2; + } + + // contents + pageDict->lookupNF("Contents", &contents); + if (!(contents.isRef() || contents.isArray() || + contents.isNull())) { + error(-1, "Page contents object (page %d) is wrong type (%s)", + num, contents.getTypeName()); + contents.free(); + goto err1; + } + + return; + + err2: + annots.initNull(); + err1: + contents.initNull(); + ok = gFalse; +} + +Page::~Page() { + delete attrs; + annots.free(); + contents.free(); +} + +void Page::display(OutputDev *out, int dpi, int rotate, + Links *links, Catalog *catalog) { +#ifndef PDF_PARSER_ONLY + Gfx *gfx; + Object obj; + Link *link; + int i; + FormWidgets *formWidgets; + + if (printCommands) { + printf("***** MediaBox = ll:%g,%g ur:%g,%g\n", + getX1(), getY1(), getX2(), getY2()); + if (isCropped()) { + printf("***** CropBox = ll:%g,%g ur:%g,%g\n", + getCropX1(), getCropY1(), getCropX2(), getCropY2()); + } + printf("***** Rotate = %d\n", attrs->getRotate()); + } + + rotate += getRotate(); + if (rotate >= 360) { + rotate -= 360; + } else if (rotate < 0) { + rotate += 360; + } + gfx = new Gfx(out, num, attrs->getResourceDict(), + dpi, getX1(), getY1(), getX2(), getY2(), isCropped(), + getCropX1(), getCropY1(), getCropX2(), getCropY2(), rotate); + contents.fetch(&obj); + if (!obj.isNull()) { + gfx->display(&obj); + } + obj.free(); + + // draw links + if (links) { + for (i = 0; i < links->getNumLinks(); ++i) { + link = links->getLink(i); + out->drawLink(link, catalog); + } + out->dump(); + } + + // draw AcroForm widgets + //~ need to reset CTM ??? + formWidgets = new FormWidgets(annots.fetch(&obj)); + obj.free(); + if (printCommands && formWidgets->getNumWidgets() > 0) { + printf("***** AcroForm widgets\n"); + } + for (i = 0; i < formWidgets->getNumWidgets(); ++i) { + formWidgets->getWidget(i)->draw(gfx); + } + delete formWidgets; + + delete gfx; +#endif +} diff --git a/pdftops/Page.h b/pdftops/Page.h new file mode 100644 index 0000000000..94f63daac6 --- /dev/null +++ b/pdftops/Page.h @@ -0,0 +1,114 @@ +//======================================================================== +// +// Page.h +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#ifndef PAGE_H +#define PAGE_H + +#ifdef __GNUC__ +#pragma interface +#endif + +#include "Object.h" + +class Dict; +class XRef; +class OutputDev; +class Links; +class Catalog; + +//------------------------------------------------------------------------ +// PageAttrs +//------------------------------------------------------------------------ + +class PageAttrs { +public: + + // Construct a new PageAttrs object by merging a dictionary + // (of type Pages or Page) into another PageAttrs object. If + // is NULL, uses defaults. + PageAttrs(PageAttrs *attrs, Dict *dict); + + // Destructor. + ~PageAttrs(); + + // Accessors. + double getX1() { return limitToCropBox ? cropX1 : x1; } + double getY1() { return limitToCropBox ? cropY1 : y1; } + double getX2() { return limitToCropBox ? cropX2 : x2; } + double getY2() { return limitToCropBox ? cropY2 : y2; } + GBool isCropped() { return cropX2 > cropX1; } + double getCropX1() { return cropX1; } + double getCropY1() { return cropY1; } + double getCropX2() { return cropX2; } + double getCropY2() { return cropY2; } + int getRotate() { return rotate; } + Dict *getResourceDict() + { return resources.isDict() ? resources.getDict() : (Dict *)NULL; } + +private: + + double x1, y1, x2, y2; + double cropX1, cropY1, cropX2, cropY2; + GBool limitToCropBox; + int rotate; + Object resources; +}; + +//------------------------------------------------------------------------ +// Page +//------------------------------------------------------------------------ + +class Page { +public: + + // Constructor. + Page(int num1, Dict *pageDict, PageAttrs *attrs1); + + // Destructor. + ~Page(); + + // Is page valid? + GBool isOk() { return ok; } + + // Get page parameters. + double getX1() { return attrs->getX1(); } + double getY1() { return attrs->getY1(); } + double getX2() { return attrs->getX2(); } + double getY2() { return attrs->getY2(); } + GBool isCropped() { return attrs->isCropped(); } + double getCropX1() { return attrs->getCropX1(); } + double getCropY1() { return attrs->getCropY1(); } + double getCropX2() { return attrs->getCropX2(); } + double getCropY2() { return attrs->getCropY2(); } + double getWidth() { return attrs->getX2() - attrs->getX1(); } + double getHeight() { return attrs->getY2() - attrs->getY1(); } + int getRotate() { return attrs->getRotate(); } + + // Get resource dictionary. + Dict *getResourceDict() { return attrs->getResourceDict(); } + + // Get annotations array. + Object *getAnnots(Object *obj) { return annots.fetch(obj); } + + // Get contents. + Object *getContents(Object *obj) { return contents.fetch(obj); } + + // Display a page. + void display(OutputDev *out, int dpi, int rotate, + Links *links, Catalog *catalog); + +private: + + int num; // page number + PageAttrs *attrs; // page attributes + Object annots; // annotations array + Object contents; // page contents + GBool ok; // true if page is valid +}; + +#endif diff --git a/pdftops/Params.cxx b/pdftops/Params.cxx new file mode 100644 index 0000000000..35adfdfe00 --- /dev/null +++ b/pdftops/Params.cxx @@ -0,0 +1,87 @@ +//======================================================================== +// +// Params.cc +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#include +#include +#include +#include +#include "gtypes.h" +#include "gmem.h" +#include "GString.h" +#include "gfile.h" +#include "Params.h" + +char **fontPath = NULL; +static int fontPathLen, fontPathSize; + +DevFontMapEntry *devFontMap = NULL; +static int devFontMapLen, devFontMapSize; + +void initParams(char *configFile) { + GString *fileName; + FILE *f; + char buf[256]; + char *p, *q; + + // initialize font path and font map + fontPath = (char **)gmalloc((fontPathSize = 8) * sizeof(char *)); + fontPath[fontPathLen = 0] = NULL; + devFontMap = (DevFontMapEntry *)gmalloc((devFontMapSize = 8) * + sizeof(DevFontMapEntry)); + devFontMap[devFontMapLen = 0].pdfFont = NULL; + + // read config file + fileName = appendToPath(getHomeDir(), configFile); + if ((f = fopen(fileName->getCString(), "r"))) { + while (fgets(buf, sizeof(buf)-1, f)) { + buf[sizeof(buf)-1] = '\0'; + p = strtok(buf, " \t\n\r"); + if (p && !strcmp(p, "fontpath")) { + if (fontPathLen+1 >= fontPathSize) + fontPath = (char **) + grealloc(fontPath, (fontPathSize += 8) * sizeof(char *)); + p = strtok(NULL, " \t\n\r"); + fontPath[fontPathLen++] = copyString(p); + } else if (p && !strcmp(p, "fontmap")) { + if (devFontMapLen+1 >= devFontMapSize) + devFontMap = (DevFontMapEntry *) + grealloc(devFontMap, + (devFontMapSize += 8) * sizeof(DevFontMapEntry)); + p = strtok(NULL, " \t\n\r"); + devFontMap[devFontMapLen].pdfFont = copyString(p); + p = strtok(NULL, "\t\n\r"); + while (*p == ' ') + ++p; + for (q = p + strlen(p) - 1; q >= p && *q == ' '; --q) ; + q[1] = '\0'; + devFontMap[devFontMapLen++].devFont = copyString(p); + } + } + fclose(f); + fontPath[fontPathLen] = NULL; + devFontMap[devFontMapLen].pdfFont = NULL; + } + delete fileName; +} + +void freeParams() { + int i; + + if (fontPath) { + for (i = 0; i < fontPathLen; ++i) + gfree(fontPath[i]); + gfree(fontPath); + } + if (devFontMap) { + for (i = 0; i < devFontMapLen; ++i) { + gfree(devFontMap[i].pdfFont); + gfree(devFontMap[i].devFont); + } + gfree(devFontMap); + } +} diff --git a/pdftops/Params.h b/pdftops/Params.h new file mode 100644 index 0000000000..ea8536fa1e --- /dev/null +++ b/pdftops/Params.h @@ -0,0 +1,37 @@ +//======================================================================== +// +// Params.h +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#ifndef PARAMS_H +#define PARAMS_H + +// Print commands as they're executed. +extern GBool printCommands; + +// If this is set, error messages will be silently discarded. +extern GBool errQuiet; + +// Font search path. +extern char **fontPath; + +// Mapping from PDF font name to device font name. +struct DevFontMapEntry { + char *pdfFont; + char *devFont; +}; +extern DevFontMapEntry *devFontMap; + +//------------------------------------------------------------------------ + +// Initialize font path and font map, and read configuration file, +// if present. +extern void initParams(char *configFile); + +// Free memory used for font path and font map. +extern void freeParams(); + +#endif diff --git a/pdftops/Parser.cxx b/pdftops/Parser.cxx new file mode 100644 index 0000000000..9fce596e4f --- /dev/null +++ b/pdftops/Parser.cxx @@ -0,0 +1,203 @@ +//======================================================================== +// +// Parser.cc +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include +#include "Object.h" +#include "Array.h" +#include "Dict.h" +#include "Parser.h" +#include "Error.h" +#ifndef NO_DECRYPTION +#include "Decrypt.h" +#endif + +Parser::Parser(Lexer *lexer1) { + lexer = lexer1; + inlineImg = 0; + lexer->getObj(&buf1); + lexer->getObj(&buf2); +} + +Parser::~Parser() { + buf1.free(); + buf2.free(); + delete lexer; +} + +#ifndef NO_DECRYPTION +Object *Parser::getObj(Object *obj, + Guchar *fileKey, int objNum, int objGen) { +#else +Object *Parser::getObj(Object *obj) { +#endif + char *key; + Stream *str; + Object obj2; + int num; +#ifndef NO_DECRYPTION + Decrypt *decrypt; + GString *s; + char *p; + int i; +#endif + + // refill buffer after inline image data + if (inlineImg == 2) { + buf1.free(); + buf2.free(); + lexer->getObj(&buf1); + lexer->getObj(&buf2); + inlineImg = 0; + } + + // array + if (buf1.isCmd("[")) { + shift(); + obj->initArray(); + while (!buf1.isCmd("]") && !buf1.isEOF()) +#ifndef NO_DECRYPTION + obj->arrayAdd(getObj(&obj2, fileKey, objNum, objGen)); +#else + obj->arrayAdd(getObj(&obj2)); +#endif + if (buf1.isEOF()) + error(getPos(), "End of file inside array"); + shift(); + + // dictionary or stream + } else if (buf1.isCmd("<<")) { + shift(); + obj->initDict(); + while (!buf1.isCmd(">>") && !buf1.isEOF()) { + if (!buf1.isName()) { + error(getPos(), "Dictionary key must be a name object"); + shift(); + } else { + key = copyString(buf1.getName()); + shift(); + if (buf1.isEOF() || buf1.isError()) + break; +#ifndef NO_DECRYPTION + obj->dictAdd(key, getObj(&obj2, fileKey, objNum, objGen)); +#else + obj->dictAdd(key, getObj(&obj2)); +#endif + } + } + if (buf1.isEOF()) + error(getPos(), "End of file inside dictionary"); + if (buf2.isCmd("stream")) { + if ((str = makeStream(obj))) { + obj->initStream(str); +#ifndef NO_DECRYPTION + if (fileKey) { + str->getBaseStream()->doDecryption(fileKey, objNum, objGen); + } +#endif + } else { + obj->free(); + obj->initError(); + } + } else { + shift(); + } + + // indirect reference or integer + } else if (buf1.isInt()) { + num = buf1.getInt(); + shift(); + if (buf1.isInt() && buf2.isCmd("R")) { + obj->initRef(num, buf1.getInt()); + shift(); + shift(); + } else { + obj->initInt(num); + } + +#ifndef NO_DECRYPTION + // string + } else if (buf1.isString() && fileKey) { + buf1.copy(obj); + s = obj->getString(); + decrypt = new Decrypt(fileKey, objNum, objGen); + for (i = 0, p = obj->getString()->getCString(); + i < s->getLength(); + ++i, ++p) { + *p = decrypt->decryptByte(*p); + } + delete decrypt; + shift(); +#endif + + // simple object + } else { + buf1.copy(obj); + shift(); + } + + return obj; +} + +Stream *Parser::makeStream(Object *dict) { + Object obj; + Stream *str; + int pos, length; + + // get stream start position + lexer->skipToNextLine(); + pos = lexer->getPos(); + + // get length + dict->dictLookup("Length", &obj); + if (obj.isInt()) { + length = obj.getInt(); + obj.free(); + } else { + error(getPos(), "Bad 'Length' attribute in stream"); + obj.free(); + return NULL; + } + + // make base stream + str = lexer->getStream()->getBaseStream()->makeSubStream(pos, length, dict); + + // get filters + str = str->addFilters(dict); + + // skip over stream data + lexer->setPos(pos + length); + + // refill token buffers and check for 'endstream' + shift(); // kill '>>' + shift(); // kill 'stream' + if (buf1.isCmd("endstream")) + shift(); + else + error(getPos(), "Missing 'endstream'"); + + return str; +} + +void Parser::shift() { + if (inlineImg > 0) { + ++inlineImg; + } else if (buf2.isCmd("ID")) { + lexer->skipChar(); // skip char after 'ID' command + inlineImg = 1; + } + buf1.free(); + buf1 = buf2; + if (inlineImg > 0) // don't buffer inline image data + buf2.initNull(); + else + lexer->getObj(&buf2); +} diff --git a/pdftops/Parser.h b/pdftops/Parser.h new file mode 100644 index 0000000000..6e6184499e --- /dev/null +++ b/pdftops/Parser.h @@ -0,0 +1,56 @@ +//======================================================================== +// +// Parser.h +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#ifndef PARSER_H +#define PARSER_H + +#ifdef __GNUC__ +#pragma interface +#endif + +#include "Lexer.h" + +//------------------------------------------------------------------------ +// Parser +//------------------------------------------------------------------------ + +class Parser { +public: + + // Constructor. + Parser(Lexer *lexer1); + + // Destructor. + ~Parser(); + + // Get the next object from the input stream. +#ifndef NO_DECRYPTION + Object *getObj(Object *obj, + Guchar *fileKey = NULL, int objNum = 0, int objGen = 0); +#else + Object *getObj(Object *obj); +#endif + + // Get stream. + Stream *getStream() { return lexer->getStream(); } + + // Get current position in file. + int getPos() { return lexer->getPos(); } + +private: + + Lexer *lexer; // input stream + Object buf1, buf2; // next two tokens + int inlineImg; // set when inline image data is encountered + + Stream *makeStream(Object *dict); + void shift(); +}; + +#endif + diff --git a/pdftops/README b/pdftops/README new file mode 100644 index 0000000000..f6bc9ebee0 --- /dev/null +++ b/pdftops/README @@ -0,0 +1,348 @@ +xpdf +==== + +version 0.90 +99-aug-02 + +The xpdf software and documentation are +copyright 1996-1999 Derek B. Noonburg. + +Email: derekn@foolabs.com +WWW: http://www.foolabs.com/xpdf/ + +The PDF data structures, operators, and specification are +copyright 1995 Adobe Systems Inc. + + +What is xpdf? +------------- + +Xpdf is a viewer for Portable Document Format (PDF) files. (These are +also sometimes also called 'Acrobat' files, from the name of Adobe's +PDF software.) Xpdf runs under the X Window System on UNIX, VMS, and +OS/2. The non-X components of the package (pdftops, pdftotext, etc.) +also run on Win32 systems and should run on pretty much any system +with a decent C++ compiler. + +Xpdf is designed to be small and efficient. It does not use the Motif +or Xt libraries. It can use standard X fonts. + + +Distribution +------------ + +Xpdf is licensed under the GNU General Public License (GPL), version +2. In my opinion, the GPL is a convoluted, confusing, ambiguous mess. +But it's also pervasive, and I'm sick of arguing. And even if it is +confusing, the basic idea is good. + +In order to cut down on the confusion a little bit, here are some +informal clarifications: + +- I don't mind if you redistribute xpdf in source and/or binary form, + as long as you include all of the documentation: README, man pages + (or help files), and COPYING. (Note that the README file contains a + pointer to a web page with the source code.) + +- Selling a CD-ROM that contains xpdf is fine with me, as long as it + includes the documentation. I wouldn't mind receiving a sample + copy, but it's not necessary. + +- If you make useful changes to xpdf, please make the source code + available -- post it on a web site, email it to me, whatever. + +If you're interested in commercial licensing, please contact me by +email: derekn@foolabs.com . + + +Compatibility +------------- + +Xpdf is developed and tested on a Linux 2.0 x86 system. + +In addition, it has been compiled by others on Solaris, AIX, HP-UX, +SCO UnixWare, Digital Unix, Irix, and numerous other Unix +implementations, as well as VMS and OS/2. It should work on pretty +much any system which runs X11 and has Unix-like libraries. You'll +need ANSI C++ and C compilers to compile it. + +The non-X components of xpdf (pdftops, pdftotext, pdfinfo, pdfimages) +can also be compiled on Win32 systems. See the xpdf web page for +details. + +If you compiled xpdf for a system not listed on the web page, please +let me know. If you're willing to make your binary available by ftp +or on the web, I'll be happy to add a link from the xpdf web page. I +have decided not to host any binaries I didn't compile myself (for +disk space and support reasons). + +If you can't get xpdf to compile on your system, send me email and +I'll try to help. + +Xpdf has been ported to the Acorn, Amiga, and BeOS. See the xpdf web +page for links. + + +Getting xpdf +------------ + +The latest version is available from: + + http://www.foolabs.com/xpdf/ + +or: + + ftp://ftp.foolabs.com/pub/xpdf/ + +Source code and several precompiled executables are available. + +Announcements of new versions are posted to several newsgroups +(comp.text.pdf, comp.os.linux.announce, and others) and emailed to a +list of people. If you'd like to receive email notification of new +versions, just let me know. + + +Running xpdf +------------ + +To run xpdf, simply type: + + xpdf file.pdf + +To generate a PostScript file, hit the "print" button in xpdf, or run +pdftops: + + pdftops file.pdf + +To generate a plain text file, run pdftotext: + + pdftotext file.pdf + +There are three additional utilities (which are fully described in +their man pages): + + pdfinfo -- dumps a PDF file's Info dictionary (plus some other + useful information) + pdftopbm -- converts a PDF file to a series of PBM-format bitmaps + pdfimages -- extracts the images from a PDF file + +Command line options and many other details are described in the man +pages (xpdf.1, etc.) and the VMS help files (xpdf.hlp, etc.). + + +Fonts +----- + +Xpdf uses X server fonts. It requires the following fonts: + +* Courier: medium-r, bold-r, medium-o, and bold-o +* Helvetica: medium-r, bold-r, medium-o, and bold-o +* Times: medium-r, bold-r, medium-i, and bold-i +* Symbol: medium-r +* Zapf Dingbats: medium-r + +Most X installations should already have all of these fonts, except +Zapf Dingbats. You can install a Type 1 Zapf Dingbats font -- see the +mkfontdir(1) man page for details. Use this font descriptor in your +fonts.scale file: + + -itc-zapfdingbats-medium-r-normal--0-0-0-0-p-0-adobe-fontspecific + +You can get a Type 1 font file from the ghostscript 4.x distribution +(look for d050000l.pfb). + +X servers, starting at R5, support font scaling. Xpdf will +automatically take advantage of this. There are two types of scaling. +The first type uses standard bitmap fonts: if a font doesn't exist in +the requested size, the server will scale the bitmapped characters. +This is reasonably fast, and the results are readable but not very +pretty. X servers can also handle true scalable, e.g., Type 1, fonts. +(See the mkfontdir(1) man page for details on setting these up.) +Scalable fonts are slower, especially since PDF documents tend to use +lots of fonts, but they look much nicer. + +Some X servers also support font rotation. Xpdf will use this feature +if available. + +For Japanese support, you will need a Japanese font of the form: + + -*-fixed-medium-r-normal-*-NN-*-*-*-*-*-jisx0208.1983-0 + +and an X server that can handle 16-bit fonts. + +If compiled with t1lib support, xpdf will use t1lib to render embedded +Type 1 and Type 1C fonts. In addition, xpdf can be configured to use +t1lib for the base 14 fonts and for substituted fonts. To enable this +feature, you must set an X resource for each Type 1 font file. For +example: + + xpdf.t1TimesRoman: /usr/local/fonts/Times-Roman.pfa + xpdf.t1TimesItalic: /usr/local/fonts/Times-Italic.pfa + xpdf.t1TimesBold: /usr/local/fonts/Times-Bold.pfa + xpdf.t1TimesBoldItalic: /usr/local/fonts/Times-BoldItalic.pfa + xpdf.t1Helvetica: /usr/local/fonts/Helvetica.pfa + xpdf.t1HelveticaOblique: /usr/local/fonts/Helvetica-Oblique.pfa + xpdf.t1HelveticaBold: /usr/local/fonts/Helvetica-Bold.pfa + xpdf.t1HelveticaBoldOblique: /usr/local/fonts/Helvetica-BoldOblique.pfa + xpdf.t1Courier: /usr/local/fonts/Courier.pfa + xpdf.t1CourierOblique: /usr/local/fonts/Courier-Oblique.pfa + xpdf.t1CourierBold: /usr/local/fonts/Courier-Bold.pfa + xpdf.t1CourierBoldOblique: /usr/local/fonts/Courier-BoldOblique.pfa + xpdf.t1Symbol: /usr/local/fonts/Symbol.pfa + xpdf.t1ZapfDingbats: /usr/local/fonts/ZapfDingbats.pfa + + +The Unisys LZW Patent +--------------------- + +Nearly all PDF files include data which has been compressed with the +LZW compression algorithm. Unfortunately, LZW is covered by a +software patent which is owned by Unisys Corporation. Unisys refuses +to license this patent for PDF-related use in software such as xpdf +which is released for free and which may be freely redistributed. +(This is same algorithm which is used by GIF. However, Unisys is not +doing licensing for free PDF viwers in the same way as for free GIF +viewers.) + +As a workaround, xpdf converts PDF-format LZW data to compress-format +LZW data. (The standard UNIX compress utility also uses LZW, but with +a slightly different file format.) This conversion does *not* +decompress the data; it simply converts it to a different file format. +Xpdf then calls uncompress to actually decompress the data. + +I have been told by several notable people that the LZW patent covers +compression only, and does not cover decompression. This seems pretty +fuzzy to me, so I'm going to stick with my workaround, at least for +now. + +For Unisys's slant on things (mostly regarding GIF), see + and +. These pages mention +an email address for feedback. + + +Compiling xpdf +-------------- + +See the separate file, INSTALL. + + +Bugs +---- + +This release of xpdf should improve the situation with embedded +fonts. However, Type 3 and TrueType fonts are still not handled. + +If you find a bug in xpdf, i.e., if it prints an error message, +crashes, or incorrectly displays a document, and you don't see that +bug listed here, please send me email, with a pointer (URL, ftp site, +etc.) to the PDF file. + + +Acknowledgments +--------------- + +Thanks to: + +* Patrick Voigt for help with the remote server code. +* Patrick Moreau and Martin P.J. Zinser for the VMS port. +* David Boldt and Rick Rodgers for sample man pages. +* Brendan Miller for the icon idea. +* Olly Betts for help testing pdftotext. +* Peter Ganten for the OS/2 port. +* Michael Richmond for the Win32 port of pdftops and pdftotext. +* Frank M. Siegert for improvements in the PostScript code. +* Leo Smiers for the decryption patches. +* Rainer Menzner for creating t1lib, and for helping me adapt it to + xpdf. + + +References +---------- + +Adobe Systems Inc., _Portable Document Format Reference Manual_. +Addison-Wesley, 1993, ISBN 0-201-62628-4. +[The printed manual for PDF version 1.0.] + +Adobe Systems Inc., _Portable Document Format Reference Manual_, +Version 1.3. March 11, 1999. +http://partners.adobe.com/asn/developer/PDFS/TN/PDFSPEC.PDF +[Updated manual for PDF 1.3.] + +Adobe Systems Inc., _PostScript Language Reference Manual_, 2nd ed. +Addison-Wesley, 1990, ISBN 0-201-18127-4. +[The official PostScript manual.] + +Adobe Systems, Inc., _Adobe CMap and CIDFont Files Specification_, +Adobe Developer Support Technical Specification #5014. 1995. +http://www.adobe.com/supportservice/devrelations/PDFS/TN/5014.CIDFont_Spec.pdf +[CMap file format needed for Japanese font support.] + +Adobe Systems, Inc., _Adobe-Japan1-2 Character Collection for +CID-Keyed Fonts_ (Bitmap Character Image Version), Adobe Developer +Support Technical Note #5078-b. 1994. +http://www.adobe.com/supportservice/devrelations/PDFS/TN/5078b.pdf +[The complete Adobe Japanese character set.] + +Adobe Systems Inc., _Supporting the DCT Filters in PostScript Level +2_, Adobe Developer Support Technical Note #5116. 1992. +http://www.adobe.com/supportservice/devrelations/PDFS/TN/5116.PS2_DCT.PDF +[Description of the DCTDecode filter parameters.] + +Anonymous, RC4 source code. +ftp://ftp.ox.ac.uk/pub/crypto/misc/rc4.tar.gz +ftp://idea.sec.dsi.unimi.it/pub/crypt/code/rc4.tar.gz +[This is the algorithm used to encrypt PDF files.] + +CCITT, _Blue Book_, Volume VII Fascicle 3: "Terminal Equipment and +Protocols for Telematic Services", Recommendations T.4 and T.6. +ftp://ftp.uu.net/doc/standards/ccitt/1988/7_3_01.ps +ftp://ftp.uu.net/doc/standards/ccitt/1988/7_3_02.ps +[The official Group 3 and 4 fax standards. The online copies are +unfortunately misformatted.] + +L. Peter Deutsch, "ZLIB Compressed Data Format Specification version +3.3". RFC 1950. +[Information on the general format used in FlateDecode streams.] + +L. Peter Deutsch, "DEFLATE Compressed Data Format Specification +version 1.3". RFC 1951. +[The definition of the compression algorithm used in FlateDecode +streams.] + +Jim Flowers, "X Logical Font Description Conventions", Version 1.5, X +Consortium Standard, X Version 11, Release 6.1. +ftp://ftp.x.org/pub/R6.1/xc/doc/hardcopy/XLFD/xlfd.PS.Z +[The official specification of X font descriptors, including font +transformation matrices.] + +Foley, van Dam, Feiner, and Hughes, _Computer Graphics: Principles and +Practice_, 2nd ed. Addison-Wesley, 1990, ISBN 0-201-12110-7. +[Colorspace conversion functions, Bezier spline math.] + +Robert L. Hummel, _Programmer's Technical Reference: Data and Fax +Communications_. Ziff-Davis Press, 1993, ISBN 1-56276-077-7. +[CCITT Group 3 and 4 fax decoding.] + +Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz, "Practical +Fast 1-D DCT Algorithms with 11 Multiplications". IEEE Intl. Conf. on +Acoustics, Speech & Signal Processing, 1989, 988-991. +[The fast IDCT algorithm used in the DCTDecode filter.] + +R. Rivest, "The MD5 Message-Digest Algorithm". RFC 1321. +[MD5 is used in PDF document encryption.] + +Gregory K. Wallace, "The JPEG Still Picture Compression Standard". +ftp://ftp.uu.net/graphics/jpeg/wallace.ps.gz +[Good description of the JPEG standard. Also published in CACM, April +1991, and submitted to IEEE Transactions on Consumer Electronics.] + +W3C Recommendation, "PNG (Portable Network Graphics) Specification +Version 1.0". +http://www.w3.org/Graphics/PNG/ +[Defines the PNG image predictor.] + +"ISO 8859-2 (Latin 2) Resources". +http://sizif.mf.uni-lj.si/linux/cee/iso8859-2.html +[This is a web page with all sorts of useful Latin-2 character set and +font information.] diff --git a/pdftops/SFont.h b/pdftops/SFont.h new file mode 100644 index 0000000000..4758664fa1 --- /dev/null +++ b/pdftops/SFont.h @@ -0,0 +1,127 @@ +//======================================================================== +// +// SFont.h +// +// Base class for font rasterizers. +// +//======================================================================== + +#ifndef SFONT_H +#define SFONT_H + +#ifdef __GNUC__ +#pragma interface +#endif + +#include +#include +#include "gtypes.h" + +//------------------------------------------------------------------------ + +class SFontEngine { +public: + + SFontEngine(Display *display, Visual *visual, int depth, + Colormap colormap); + virtual ~SFontEngine(); + + // Use a TrueColor visual. Pixel values are computed as: + // + // (r << rShift) + (g << gShift) + (b << bShift) + // + // where r, g, and b are scaled to the ranges [0,rMax], [0,gMax], + // and [0,bMax], respectively. + virtual void useTrueColor(int rMax, int rShift, int gMax, int gShift, + int bMax, int bShift); + + // Use an RGB color cube. is an array containing + // ** pixel values in red,green,blue order, e.g., + // for =2, there will be 8 entries: + // + // |--- colors[i] ---| + // i red green blue + // - ----- ----- ----- + // 0 0000 0000 0000 + // 1 0000 0000 ffff + // 2 0000 ffff 0000 + // 3 0000 ffff ffff + // 4 ffff 0000 0000 + // 5 ffff 0000 ffff + // 6 ffff ffff 0000 + // 7 ffff ffff ffff + // + // The array is not copied and must remain valid for the + // lifetime of this SFont object. + virtual void useColorCube(Gulong *colors, int nRGB); + +protected: + + // Find the closest match to (,,). + Gulong findColor(int r, int g, int b); + + //----- X parameters + Display *display; + Visual *visual; + int depth; + Colormap colormap; + + GBool trueColor; // true for TrueColor, false for RGB cube + + //----- TrueColor parameters + int rMax, gMax, bMax; + int rShift, gShift, bShift; + + //----- RGB color cube parameters + Gulong *colors; + int nRGB; +}; + +//------------------------------------------------------------------------ + +class SFontFile { +public: + + // A typical subclass will provide a constructor along the lines of: + // + // SomeFontFile(SomeFontEngine *engine, char *fontFileName); + SFontFile(); + + virtual ~SFontFile(); + +private: +}; + +//------------------------------------------------------------------------ + +class SFont { +public: + + // A typical subclass will provide a constructor along the lines of: + // + // SomeFont(SomeFontFile *fontFile, double *m); + // + // where is a transform matrix consisting of four elements, + // using the PostScript ordering conventions (without any + // translation): + // + // [x' y'] = [x y] * [m0 m1] + // [m2 m3] + // + // This is the level at which fonts are cached, and so the font + // cannot be transformed after it is created. + SFont(); + + virtual ~SFont(); + + // Draw a character at , in color (,,). The RGB + // values should each be in the range [0,65535]. Draws into , + // clipped to the rectangle (0,0)-(-1,-1). Returns true if + // the character was drawn successfully. + virtual GBool drawChar(Drawable d, int w, int h, GC gc, + int x, int y, int r, int g, int b, Gushort c) = 0; + +protected: +}; + +#endif diff --git a/pdftops/StdFontInfo.h b/pdftops/StdFontInfo.h new file mode 100644 index 0000000000..0db033f6bd --- /dev/null +++ b/pdftops/StdFontInfo.h @@ -0,0 +1,546 @@ +//======================================================================== +// +// StdFontInfo.h +// +// This file was automatically generated by makeFontInfo. +// +// Copyright 1999 Derek B. Noonburg +// +//======================================================================== + +#ifndef STDFONTINFO_H +#define STDFONTINFO_H + +//------------------------------------------------------------------------ +// type1StdEncoding -- Adobe Type 1 StandardEncoding +//------------------------------------------------------------------------ + +#define type1StdEncodingSize 256 +static char *type1StdEncodingNames[type1StdEncodingSize] = { + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "space", + "exclam", + "quotedbl", + "numbersign", + "dollar", + "percent", + "ampersand", + "quoteright", + "parenleft", + "parenright", + "asterisk", + "plus", + "comma", + "hyphen", + "period", + "slash", + "zero", + "one", + "two", + "three", + "four", + "five", + "six", + "seven", + "eight", + "nine", + "colon", + "semicolon", + "less", + "equal", + "greater", + "question", + "at", + "A", + "B", + "C", + "D", + "E", + "F", + "G", + "H", + "I", + "J", + "K", + "L", + "M", + "N", + "O", + "P", + "Q", + "R", + "S", + "T", + "U", + "V", + "W", + "X", + "Y", + "Z", + "bracketleft", + "backslash", + "bracketright", + "asciicircum", + "underscore", + "quoteleft", + "a", + "b", + "c", + "d", + "e", + "f", + "g", + "h", + "i", + "j", + "k", + "l", + "m", + "n", + "o", + "p", + "q", + "r", + "s", + "t", + "u", + "v", + "w", + "x", + "y", + "z", + "braceleft", + "bar", + "braceright", + "asciitilde", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "exclamdown", + "cent", + "sterling", + "fraction", + "yen", + "florin", + "section", + "currency", + "quotesingle", + "quotedblleft", + "guillemotleft", + "guilsinglleft", + "guilsinglright", + "fi", + "fl", + NULL, + "endash", + "dagger", + "daggerdbl", + "periodcentered", + NULL, + "paragraph", + "bullet", + "quotesinglbase", + "quotedblbase", + "quotedblright", + "guillemotright", + "ellipsis", + "perthousand", + NULL, + "questiondown", + NULL, + "grave", + "acute", + "circumflex", + "tilde", + "macron", + "breve", + "dotaccent", + "dieresis", + NULL, + "ring", + "cedilla", + NULL, + "hungarumlaut", + "ogonek", + "caron", + "emdash", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "AE", + NULL, + "ordfeminine", + NULL, + NULL, + NULL, + NULL, + "Lslash", + "Oslash", + "OE", + "ordmasculine", + NULL, + NULL, + NULL, + NULL, + NULL, + "ae", + NULL, + NULL, + NULL, + "dotlessi", + NULL, + NULL, + "lslash", + "oslash", + "oe", + "germandbls", + NULL, + NULL, + NULL, + NULL +}; +static FontEncoding type1StdEncoding(type1StdEncodingNames, + type1StdEncodingSize); + +//------------------------------------------------------------------------ +// type1ExpertEncoding -- Adobe Type 1 ExpertEncoding +//------------------------------------------------------------------------ + +#define type1ExpertEncodingSize 256 +static char *type1ExpertEncodingNames[type1ExpertEncodingSize] = { + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "space", + "exclamsmall", + "Hungarumlautsmall", + NULL, + "dollaroldstyle", + "dollarsuperior", + "ampersandsmall", + "Acutesmall", + "parenleftsuperior", + "parenrightsuperior", + "twodotenleader", + "onedotenleader", + "comma", + "hyphen", + "period", + "fraction", + "zerooldstyle", + "oneoldstyle", + "twooldstyle", + "threeoldstyle", + "fouroldstyle", + "fiveoldstyle", + "sixoldstyle", + "sevenoldstyle", + "eightoldstyle", + "nineoldstyle", + "colon", + "semicolon", + "commasuperior", + "threequartersemdash", + "periodsuperior", + "questionsmall", + NULL, + "asuperior", + "bsuperior", + "centsuperior", + "dsuperior", + "esuperior", + NULL, + NULL, + NULL, + "isuperior", + NULL, + NULL, + "lsuperior", + "msuperior", + "nsuperior", + "osuperior", + NULL, + NULL, + "rsuperior", + "ssuperior", + "tsuperior", + NULL, + "ff", + "fi", + "fl", + "ffi", + "ffl", + "parenleftinferior", + NULL, + "parenrightinferior", + "Circumflexsmall", + "hyphensuperior", + "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", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "exclamdownsmall", + "centoldstyle", + "Lslashsmall", + NULL, + NULL, + "Scaronsmall", + "Zcaronsmall", + "Dieresissmall", + "Brevesmall", + "Caronsmall", + NULL, + "Dotaccentsmall", + NULL, + NULL, + "Macronsmall", + NULL, + NULL, + "figuredash", + "hypheninferior", + NULL, + NULL, + "Ogoneksmall", + "Ringsmall", + "Cedillasmall", + NULL, + NULL, + NULL, + "onequarter", + "onehalf", + "threequarters", + "questiondownsmall", + "oneeighth", + "threeeighths", + "fiveeighths", + "seveneighths", + "onethird", + "twothirds", + NULL, + NULL, + "zerosuperior", + "onesuperior", + "twosuperior", + "threesuperior", + "foursuperior", + "fivesuperior", + "sixsuperior", + "sevensuperior", + "eightsuperior", + "ninesuperior", + "zeroinferior", + "oneinferior", + "twoinferior", + "threeinferior", + "fourinferior", + "fiveinferior", + "sixinferior", + "seveninferior", + "eightinferior", + "nineinferior", + "centinferior", + "dollarinferior", + "periodinferior", + "commainferior", + "Agravesmall", + "Aacutesmall", + "Acircumflexsmall", + "Atildesmall", + "Adieresissmall", + "Aringsmall", + "AEsmall", + "Ccedillasmall", + "Egravesmall", + "Eacutesmall", + "Ecircumflexsmall", + "Edieresissmall", + "Igravesmall", + "Iacutesmall", + "Icircumflexsmall", + "Idieresissmall", + "Ethsmall", + "Ntildesmall", + "Ogravesmall", + "Oacutesmall", + "Ocircumflexsmall", + "Otildesmall", + "Odieresissmall", + "OEsmall", + "Oslashsmall", + "Ugravesmall", + "Uacutesmall", + "Ucircumflexsmall", + "Udieresissmall", + "Yacutesmall", + "Thornsmall", + "Ydieresissmall" +}; +static FontEncoding type1ExpertEncoding(type1ExpertEncodingNames, + type1ExpertEncodingSize); + +#endif diff --git a/pdftops/Stream-CCITT.h b/pdftops/Stream-CCITT.h new file mode 100644 index 0000000000..1af874225d --- /dev/null +++ b/pdftops/Stream-CCITT.h @@ -0,0 +1,459 @@ +//======================================================================== +// +// Stream-CCITT.h +// +// Tables for CCITT Fax decoding. +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +struct CCITTCode { + short bits; + short n; +}; + +#define ccittEOL -2 + +//------------------------------------------------------------------------ +// 2D codes +//------------------------------------------------------------------------ + +#define twoDimPass 0 +#define twoDimHoriz 1 +#define twoDimVert0 2 +#define twoDimVertR1 3 +#define twoDimVertL1 4 +#define twoDimVertR2 5 +#define twoDimVertL2 6 +#define twoDimVertR3 7 +#define twoDimVertL3 8 + +// 1-7 bit codes +static CCITTCode twoDimTab1[128] = { + {-1, -1}, {-1, -1}, // 000000x + {7, twoDimVertL3}, // 0000010 + {7, twoDimVertR3}, // 0000011 + {6, twoDimVertL2}, {6, twoDimVertL2}, // 000010x + {6, twoDimVertR2}, {6, twoDimVertR2}, // 000011x + {4, twoDimPass}, {4, twoDimPass}, // 0001xxx + {4, twoDimPass}, {4, twoDimPass}, + {4, twoDimPass}, {4, twoDimPass}, + {4, twoDimPass}, {4, twoDimPass}, + {3, twoDimHoriz}, {3, twoDimHoriz}, // 001xxxx + {3, twoDimHoriz}, {3, twoDimHoriz}, + {3, twoDimHoriz}, {3, twoDimHoriz}, + {3, twoDimHoriz}, {3, twoDimHoriz}, + {3, twoDimHoriz}, {3, twoDimHoriz}, + {3, twoDimHoriz}, {3, twoDimHoriz}, + {3, twoDimHoriz}, {3, twoDimHoriz}, + {3, twoDimHoriz}, {3, twoDimHoriz}, + {3, twoDimVertL1}, {3, twoDimVertL1}, // 010xxxx + {3, twoDimVertL1}, {3, twoDimVertL1}, + {3, twoDimVertL1}, {3, twoDimVertL1}, + {3, twoDimVertL1}, {3, twoDimVertL1}, + {3, twoDimVertL1}, {3, twoDimVertL1}, + {3, twoDimVertL1}, {3, twoDimVertL1}, + {3, twoDimVertL1}, {3, twoDimVertL1}, + {3, twoDimVertL1}, {3, twoDimVertL1}, + {3, twoDimVertR1}, {3, twoDimVertR1}, // 011xxxx + {3, twoDimVertR1}, {3, twoDimVertR1}, + {3, twoDimVertR1}, {3, twoDimVertR1}, + {3, twoDimVertR1}, {3, twoDimVertR1}, + {3, twoDimVertR1}, {3, twoDimVertR1}, + {3, twoDimVertR1}, {3, twoDimVertR1}, + {3, twoDimVertR1}, {3, twoDimVertR1}, + {3, twoDimVertR1}, {3, twoDimVertR1}, + {1, twoDimVert0}, {1, twoDimVert0}, // 1xxxxxx + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0} +}; + +//------------------------------------------------------------------------ +// white run lengths +//------------------------------------------------------------------------ + +// 11-12 bit codes (upper 7 bits are 0) +static CCITTCode whiteTab1[32] = { + {-1, -1}, // 00000 + {12, ccittEOL}, // 00001 + {-1, -1}, {-1, -1}, // 0001x + {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 001xx + {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 010xx + {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 011xx + {11, 1792}, {11, 1792}, // 1000x + {12, 1984}, // 10010 + {12, 2048}, // 10011 + {12, 2112}, // 10100 + {12, 2176}, // 10101 + {12, 2240}, // 10110 + {12, 2304}, // 10111 + {11, 1856}, {11, 1856}, // 1100x + {11, 1920}, {11, 1920}, // 1101x + {12, 2368}, // 11100 + {12, 2432}, // 11101 + {12, 2496}, // 11110 + {12, 2560} // 11111 +}; + +// 1-9 bit codes +static CCITTCode whiteTab2[512] = { + {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 0000000xx + {8, 29}, {8, 29}, // 00000010x + {8, 30}, {8, 30}, // 00000011x + {8, 45}, {8, 45}, // 00000100x + {8, 46}, {8, 46}, // 00000101x + {7, 22}, {7, 22}, {7, 22}, {7, 22}, // 0000011xx + {7, 23}, {7, 23}, {7, 23}, {7, 23}, // 0000100xx + {8, 47}, {8, 47}, // 00001010x + {8, 48}, {8, 48}, // 00001011x + {6, 13}, {6, 13}, {6, 13}, {6, 13}, // 000011xxx + {6, 13}, {6, 13}, {6, 13}, {6, 13}, + {7, 20}, {7, 20}, {7, 20}, {7, 20}, // 0001000xx + {8, 33}, {8, 33}, // 00010010x + {8, 34}, {8, 34}, // 00010011x + {8, 35}, {8, 35}, // 00010100x + {8, 36}, {8, 36}, // 00010101x + {8, 37}, {8, 37}, // 00010110x + {8, 38}, {8, 38}, // 00010111x + {7, 19}, {7, 19}, {7, 19}, {7, 19}, // 0001100xx + {8, 31}, {8, 31}, // 00011010x + {8, 32}, {8, 32}, // 00011011x + {6, 1}, {6, 1}, {6, 1}, {6, 1}, // 000111xxx + {6, 1}, {6, 1}, {6, 1}, {6, 1}, + {6, 12}, {6, 12}, {6, 12}, {6, 12}, // 001000xxx + {6, 12}, {6, 12}, {6, 12}, {6, 12}, + {8, 53}, {8, 53}, // 00100100x + {8, 54}, {8, 54}, // 00100101x + {7, 26}, {7, 26}, {7, 26}, {7, 26}, // 0010011xx + {8, 39}, {8, 39}, // 00101000x + {8, 40}, {8, 40}, // 00101001x + {8, 41}, {8, 41}, // 00101010x + {8, 42}, {8, 42}, // 00101011x + {8, 43}, {8, 43}, // 00101100x + {8, 44}, {8, 44}, // 00101101x + {7, 21}, {7, 21}, {7, 21}, {7, 21}, // 0010111xx + {7, 28}, {7, 28}, {7, 28}, {7, 28}, // 0011000xx + {8, 61}, {8, 61}, // 00110010x + {8, 62}, {8, 62}, // 00110011x + {8, 63}, {8, 63}, // 00110100x + {8, 0}, {8, 0}, // 00110101x + {8, 320}, {8, 320}, // 00110110x + {8, 384}, {8, 384}, // 00110111x + {5, 10}, {5, 10}, {5, 10}, {5, 10}, // 00111xxxx + {5, 10}, {5, 10}, {5, 10}, {5, 10}, + {5, 10}, {5, 10}, {5, 10}, {5, 10}, + {5, 10}, {5, 10}, {5, 10}, {5, 10}, + {5, 11}, {5, 11}, {5, 11}, {5, 11}, // 01000xxxx + {5, 11}, {5, 11}, {5, 11}, {5, 11}, + {5, 11}, {5, 11}, {5, 11}, {5, 11}, + {5, 11}, {5, 11}, {5, 11}, {5, 11}, + {7, 27}, {7, 27}, {7, 27}, {7, 27}, // 0100100xx + {8, 59}, {8, 59}, // 01001010x + {8, 60}, {8, 60}, // 01001011x + {9, 1472}, // 010011000 + {9, 1536}, // 010011001 + {9, 1600}, // 010011010 + {9, 1728}, // 010011011 + {7, 18}, {7, 18}, {7, 18}, {7, 18}, // 0100111xx + {7, 24}, {7, 24}, {7, 24}, {7, 24}, // 0101000xx + {8, 49}, {8, 49}, // 01010010x + {8, 50}, {8, 50}, // 01010011x + {8, 51}, {8, 51}, // 01010100x + {8, 52}, {8, 52}, // 01010101x + {7, 25}, {7, 25}, {7, 25}, {7, 25}, // 0101011xx + {8, 55}, {8, 55}, // 01011000x + {8, 56}, {8, 56}, // 01011001x + {8, 57}, {8, 57}, // 01011010x + {8, 58}, {8, 58}, // 01011011x + {6, 192}, {6, 192}, {6, 192}, {6, 192}, // 010111xxx + {6, 192}, {6, 192}, {6, 192}, {6, 192}, + {6, 1664}, {6, 1664}, {6, 1664}, {6, 1664}, // 011000xxx + {6, 1664}, {6, 1664}, {6, 1664}, {6, 1664}, + {8, 448}, {8, 448}, // 01100100x + {8, 512}, {8, 512}, // 01100101x + {9, 704}, // 011001100 + {9, 768}, // 011001101 + {8, 640}, {8, 640}, // 01100111x + {8, 576}, {8, 576}, // 01101000x + {9, 832}, // 011010010 + {9, 896}, // 011010011 + {9, 960}, // 011010100 + {9, 1024}, // 011010101 + {9, 1088}, // 011010110 + {9, 1152}, // 011010111 + {9, 1216}, // 011011000 + {9, 1280}, // 011011001 + {9, 1344}, // 011011010 + {9, 1408}, // 011011011 + {7, 256}, {7, 256}, {7, 256}, {7, 256}, // 0110111xx + {4, 2}, {4, 2}, {4, 2}, {4, 2}, // 0111xxxxx + {4, 2}, {4, 2}, {4, 2}, {4, 2}, + {4, 2}, {4, 2}, {4, 2}, {4, 2}, + {4, 2}, {4, 2}, {4, 2}, {4, 2}, + {4, 2}, {4, 2}, {4, 2}, {4, 2}, + {4, 2}, {4, 2}, {4, 2}, {4, 2}, + {4, 2}, {4, 2}, {4, 2}, {4, 2}, + {4, 2}, {4, 2}, {4, 2}, {4, 2}, + {4, 3}, {4, 3}, {4, 3}, {4, 3}, // 1000xxxxx + {4, 3}, {4, 3}, {4, 3}, {4, 3}, + {4, 3}, {4, 3}, {4, 3}, {4, 3}, + {4, 3}, {4, 3}, {4, 3}, {4, 3}, + {4, 3}, {4, 3}, {4, 3}, {4, 3}, + {4, 3}, {4, 3}, {4, 3}, {4, 3}, + {4, 3}, {4, 3}, {4, 3}, {4, 3}, + {4, 3}, {4, 3}, {4, 3}, {4, 3}, + {5, 128}, {5, 128}, {5, 128}, {5, 128}, // 10010xxxx + {5, 128}, {5, 128}, {5, 128}, {5, 128}, + {5, 128}, {5, 128}, {5, 128}, {5, 128}, + {5, 128}, {5, 128}, {5, 128}, {5, 128}, + {5, 8}, {5, 8}, {5, 8}, {5, 8}, // 10011xxxx + {5, 8}, {5, 8}, {5, 8}, {5, 8}, + {5, 8}, {5, 8}, {5, 8}, {5, 8}, + {5, 8}, {5, 8}, {5, 8}, {5, 8}, + {5, 9}, {5, 9}, {5, 9}, {5, 9}, // 10100xxxx + {5, 9}, {5, 9}, {5, 9}, {5, 9}, + {5, 9}, {5, 9}, {5, 9}, {5, 9}, + {5, 9}, {5, 9}, {5, 9}, {5, 9}, + {6, 16}, {6, 16}, {6, 16}, {6, 16}, // 101010xxx + {6, 16}, {6, 16}, {6, 16}, {6, 16}, + {6, 17}, {6, 17}, {6, 17}, {6, 17}, // 101011xxx + {6, 17}, {6, 17}, {6, 17}, {6, 17}, + {4, 4}, {4, 4}, {4, 4}, {4, 4}, // 1011xxxxx + {4, 4}, {4, 4}, {4, 4}, {4, 4}, + {4, 4}, {4, 4}, {4, 4}, {4, 4}, + {4, 4}, {4, 4}, {4, 4}, {4, 4}, + {4, 4}, {4, 4}, {4, 4}, {4, 4}, + {4, 4}, {4, 4}, {4, 4}, {4, 4}, + {4, 4}, {4, 4}, {4, 4}, {4, 4}, + {4, 4}, {4, 4}, {4, 4}, {4, 4}, + {4, 5}, {4, 5}, {4, 5}, {4, 5}, // 1100xxxxx + {4, 5}, {4, 5}, {4, 5}, {4, 5}, + {4, 5}, {4, 5}, {4, 5}, {4, 5}, + {4, 5}, {4, 5}, {4, 5}, {4, 5}, + {4, 5}, {4, 5}, {4, 5}, {4, 5}, + {4, 5}, {4, 5}, {4, 5}, {4, 5}, + {4, 5}, {4, 5}, {4, 5}, {4, 5}, + {4, 5}, {4, 5}, {4, 5}, {4, 5}, + {6, 14}, {6, 14}, {6, 14}, {6, 14}, // 110100xxx + {6, 14}, {6, 14}, {6, 14}, {6, 14}, + {6, 15}, {6, 15}, {6, 15}, {6, 15}, // 110101xxx + {6, 15}, {6, 15}, {6, 15}, {6, 15}, + {5, 64}, {5, 64}, {5, 64}, {5, 64}, // 11011xxxx + {5, 64}, {5, 64}, {5, 64}, {5, 64}, + {5, 64}, {5, 64}, {5, 64}, {5, 64}, + {5, 64}, {5, 64}, {5, 64}, {5, 64}, + {4, 6}, {4, 6}, {4, 6}, {4, 6}, // 1110xxxxx + {4, 6}, {4, 6}, {4, 6}, {4, 6}, + {4, 6}, {4, 6}, {4, 6}, {4, 6}, + {4, 6}, {4, 6}, {4, 6}, {4, 6}, + {4, 6}, {4, 6}, {4, 6}, {4, 6}, + {4, 6}, {4, 6}, {4, 6}, {4, 6}, + {4, 6}, {4, 6}, {4, 6}, {4, 6}, + {4, 6}, {4, 6}, {4, 6}, {4, 6}, + {4, 7}, {4, 7}, {4, 7}, {4, 7}, // 1111xxxxx + {4, 7}, {4, 7}, {4, 7}, {4, 7}, + {4, 7}, {4, 7}, {4, 7}, {4, 7}, + {4, 7}, {4, 7}, {4, 7}, {4, 7}, + {4, 7}, {4, 7}, {4, 7}, {4, 7}, + {4, 7}, {4, 7}, {4, 7}, {4, 7}, + {4, 7}, {4, 7}, {4, 7}, {4, 7}, + {4, 7}, {4, 7}, {4, 7}, {4, 7} +}; + +//------------------------------------------------------------------------ +// black run lengths +//------------------------------------------------------------------------ + +// 10-13 bit codes (upper 6 bits are 0) +static CCITTCode blackTab1[128] = { + {-1, -1}, {-1, -1}, // 000000000000x + {12, ccittEOL}, {12, ccittEOL}, // 000000000001x + {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 00000000001xx + {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 00000000010xx + {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 00000000011xx + {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 00000000100xx + {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 00000000101xx + {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 00000000110xx + {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 00000000111xx + {11, 1792}, {11, 1792}, {11, 1792}, {11, 1792}, // 00000001000xx + {12, 1984}, {12, 1984}, // 000000010010x + {12, 2048}, {12, 2048}, // 000000010011x + {12, 2112}, {12, 2112}, // 000000010100x + {12, 2176}, {12, 2176}, // 000000010101x + {12, 2240}, {12, 2240}, // 000000010110x + {12, 2304}, {12, 2304}, // 000000010111x + {11, 1856}, {11, 1856}, {11, 1856}, {11, 1856}, // 00000001100xx + {11, 1920}, {11, 1920}, {11, 1920}, {11, 1920}, // 00000001101xx + {12, 2368}, {12, 2368}, // 000000011100x + {12, 2432}, {12, 2432}, // 000000011101x + {12, 2496}, {12, 2496}, // 000000011110x + {12, 2560}, {12, 2560}, // 000000011111x + {10, 18}, {10, 18}, {10, 18}, {10, 18}, // 0000001000xxx + {10, 18}, {10, 18}, {10, 18}, {10, 18}, + {12, 52}, {12, 52}, // 000000100100x + {13, 640}, // 0000001001010 + {13, 704}, // 0000001001011 + {13, 768}, // 0000001001100 + {13, 832}, // 0000001001101 + {12, 55}, {12, 55}, // 000000100111x + {12, 56}, {12, 56}, // 000000101000x + {13, 1280}, // 0000001010010 + {13, 1344}, // 0000001010011 + {13, 1408}, // 0000001010100 + {13, 1472}, // 0000001010101 + {12, 59}, {12, 59}, // 000000101011x + {12, 60}, {12, 60}, // 000000101100x + {13, 1536}, // 0000001011010 + {13, 1600}, // 0000001011011 + {11, 24}, {11, 24}, {11, 24}, {11, 24}, // 00000010111xx + {11, 25}, {11, 25}, {11, 25}, {11, 25}, // 00000011000xx + {13, 1664}, // 0000001100100 + {13, 1728}, // 0000001100101 + {12, 320}, {12, 320}, // 000000110011x + {12, 384}, {12, 384}, // 000000110100x + {12, 448}, {12, 448}, // 000000110101x + {13, 512}, // 0000001101100 + {13, 576}, // 0000001101101 + {12, 53}, {12, 53}, // 000000110111x + {12, 54}, {12, 54}, // 000000111000x + {13, 896}, // 0000001110010 + {13, 960}, // 0000001110011 + {13, 1024}, // 0000001110100 + {13, 1088}, // 0000001110101 + {13, 1152}, // 0000001110110 + {13, 1216}, // 0000001110111 + {10, 64}, {10, 64}, {10, 64}, {10, 64}, // 0000001111xxx + {10, 64}, {10, 64}, {10, 64}, {10, 64} +}; + +// 7-12 bit codes (upper 4 bits are 0) +static CCITTCode blackTab2[192] = { + {8, 13}, {8, 13}, {8, 13}, {8, 13}, // 00000100xxxx + {8, 13}, {8, 13}, {8, 13}, {8, 13}, + {8, 13}, {8, 13}, {8, 13}, {8, 13}, + {8, 13}, {8, 13}, {8, 13}, {8, 13}, + {11, 23}, {11, 23}, // 00000101000x + {12, 50}, // 000001010010 + {12, 51}, // 000001010011 + {12, 44}, // 000001010100 + {12, 45}, // 000001010101 + {12, 46}, // 000001010110 + {12, 47}, // 000001010111 + {12, 57}, // 000001011000 + {12, 58}, // 000001011001 + {12, 61}, // 000001011010 + {12, 256}, // 000001011011 + {10, 16}, {10, 16}, {10, 16}, {10, 16}, // 0000010111xx + {10, 17}, {10, 17}, {10, 17}, {10, 17}, // 0000011000xx + {12, 48}, // 000001100100 + {12, 49}, // 000001100101 + {12, 62}, // 000001100110 + {12, 63}, // 000001100111 + {12, 30}, // 000001101000 + {12, 31}, // 000001101001 + {12, 32}, // 000001101010 + {12, 33}, // 000001101011 + {12, 40}, // 000001101100 + {12, 41}, // 000001101101 + {11, 22}, {11, 22}, // 00000110111x + {8, 14}, {8, 14}, {8, 14}, {8, 14}, // 00000111xxxx + {8, 14}, {8, 14}, {8, 14}, {8, 14}, + {8, 14}, {8, 14}, {8, 14}, {8, 14}, + {8, 14}, {8, 14}, {8, 14}, {8, 14}, + {7, 10}, {7, 10}, {7, 10}, {7, 10}, // 0000100xxxxx + {7, 10}, {7, 10}, {7, 10}, {7, 10}, + {7, 10}, {7, 10}, {7, 10}, {7, 10}, + {7, 10}, {7, 10}, {7, 10}, {7, 10}, + {7, 10}, {7, 10}, {7, 10}, {7, 10}, + {7, 10}, {7, 10}, {7, 10}, {7, 10}, + {7, 10}, {7, 10}, {7, 10}, {7, 10}, + {7, 10}, {7, 10}, {7, 10}, {7, 10}, + {7, 11}, {7, 11}, {7, 11}, {7, 11}, // 0000101xxxxx + {7, 11}, {7, 11}, {7, 11}, {7, 11}, + {7, 11}, {7, 11}, {7, 11}, {7, 11}, + {7, 11}, {7, 11}, {7, 11}, {7, 11}, + {7, 11}, {7, 11}, {7, 11}, {7, 11}, + {7, 11}, {7, 11}, {7, 11}, {7, 11}, + {7, 11}, {7, 11}, {7, 11}, {7, 11}, + {7, 11}, {7, 11}, {7, 11}, {7, 11}, + {9, 15}, {9, 15}, {9, 15}, {9, 15}, // 000011000xxx + {9, 15}, {9, 15}, {9, 15}, {9, 15}, + {12, 128}, // 000011001000 + {12, 192}, // 000011001001 + {12, 26}, // 000011001010 + {12, 27}, // 000011001011 + {12, 28}, // 000011001100 + {12, 29}, // 000011001101 + {11, 19}, {11, 19}, // 00001100111x + {11, 20}, {11, 20}, // 00001101000x + {12, 34}, // 000011010010 + {12, 35}, // 000011010011 + {12, 36}, // 000011010100 + {12, 37}, // 000011010101 + {12, 38}, // 000011010110 + {12, 39}, // 000011010111 + {11, 21}, {11, 21}, // 00001101100x + {12, 42}, // 000011011010 + {12, 43}, // 000011011011 + {10, 0}, {10, 0}, {10, 0}, {10, 0}, // 0000110111xx + {7, 12}, {7, 12}, {7, 12}, {7, 12}, // 0000111xxxxx + {7, 12}, {7, 12}, {7, 12}, {7, 12}, + {7, 12}, {7, 12}, {7, 12}, {7, 12}, + {7, 12}, {7, 12}, {7, 12}, {7, 12}, + {7, 12}, {7, 12}, {7, 12}, {7, 12}, + {7, 12}, {7, 12}, {7, 12}, {7, 12}, + {7, 12}, {7, 12}, {7, 12}, {7, 12}, + {7, 12}, {7, 12}, {7, 12}, {7, 12} +}; + +// 2-6 bit codes +static CCITTCode blackTab3[64] = { + {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 0000xx + {6, 9}, // 000100 + {6, 8}, // 000101 + {5, 7}, {5, 7}, // 00011x + {4, 6}, {4, 6}, {4, 6}, {4, 6}, // 0010xx + {4, 5}, {4, 5}, {4, 5}, {4, 5}, // 0011xx + {3, 1}, {3, 1}, {3, 1}, {3, 1}, // 010xxx + {3, 1}, {3, 1}, {3, 1}, {3, 1}, + {3, 4}, {3, 4}, {3, 4}, {3, 4}, // 011xxx + {3, 4}, {3, 4}, {3, 4}, {3, 4}, + {2, 3}, {2, 3}, {2, 3}, {2, 3}, // 10xxxx + {2, 3}, {2, 3}, {2, 3}, {2, 3}, + {2, 3}, {2, 3}, {2, 3}, {2, 3}, + {2, 3}, {2, 3}, {2, 3}, {2, 3}, + {2, 2}, {2, 2}, {2, 2}, {2, 2}, // 11xxxx + {2, 2}, {2, 2}, {2, 2}, {2, 2}, + {2, 2}, {2, 2}, {2, 2}, {2, 2}, + {2, 2}, {2, 2}, {2, 2}, {2, 2} +}; diff --git a/pdftops/Stream.cxx b/pdftops/Stream.cxx new file mode 100644 index 0000000000..5beaf98df0 --- /dev/null +++ b/pdftops/Stream.cxx @@ -0,0 +1,3415 @@ +//======================================================================== +// +// Stream.cc +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include +#include +#include +#ifndef WIN32 +#include +#endif +#include +#include +#include "gmem.h" +#include "gfile.h" +#include "config.h" +#include "Error.h" +#include "Object.h" +#ifndef NO_DECRYPTION +#include "Decrypt.h" +#endif +#include "Stream.h" +#include "Stream-CCITT.h" + +#ifdef __DJGPP__ +static GBool setDJSYSFLAGS = gFalse; +#endif + +#ifdef VMS +#if (__VMS_VER < 70000000) +extern "C" int unlink(char *filename); +#endif +#ifdef __GNUC__ +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 +#endif +#endif + +#ifdef MACOS +#include "StuffItEngineLib.h" +#endif + +//------------------------------------------------------------------------ +// Stream (base class) +//------------------------------------------------------------------------ + +Stream::Stream() { + ref = 1; +} + +Stream::~Stream() { +} + +int Stream::getRawChar() { + error(-1, "Internal: called getRawChar() on non-predictor stream"); + return EOF; +} + +char *Stream::getLine(char *buf, int size) { + int i; + int c; + + if (lookChar() == EOF) + return NULL; + for (i = 0; i < size - 1; ++i) { + c = getChar(); + if (c == EOF || c == '\n') + break; + if (c == '\r') { + if ((c = lookChar()) == '\n') + getChar(); + break; + } + buf[i] = c; + } + buf[i] = '\0'; + return buf; +} + +GString *Stream::getPSFilter(char *indent) { + return new GString(); +} + +Stream *Stream::addFilters(Object *dict) { + Object obj, obj2; + Object params, params2; + Stream *str; + int i; + + str = this; + dict->dictLookup("Filter", &obj); + if (obj.isNull()) { + obj.free(); + dict->dictLookup("F", &obj); + } + dict->dictLookup("DecodeParms", ¶ms); + if (params.isNull()) { + params.free(); + dict->dictLookup("DP", ¶ms); + } + if (obj.isName()) { + str = makeFilter(obj.getName(), str, ¶ms); + } else if (obj.isArray()) { + for (i = 0; i < obj.arrayGetLength(); ++i) { + obj.arrayGet(i, &obj2); + if (params.isArray()) + params.arrayGet(i, ¶ms2); + else + params2.initNull(); + if (obj2.isName()) { + str = makeFilter(obj2.getName(), str, ¶ms2); + } else { + error(getPos(), "Bad filter name"); + str = new EOFStream(str); + } + obj2.free(); + params2.free(); + } + } else if (!obj.isNull()) { + error(getPos(), "Bad 'Filter' attribute in stream"); + } + obj.free(); + params.free(); + + return str; +} + +Stream *Stream::makeFilter(char *name, Stream *str, Object *params) { + int pred; // parameters + int colors; + int bits; + int early; + int encoding; + GBool endOfLine, byteAlign, endOfBlock, black; + int columns, rows; + Object obj; + + if (!strcmp(name, "ASCIIHexDecode") || !strcmp(name, "AHx")) { + str = new ASCIIHexStream(str); + } else if (!strcmp(name, "ASCII85Decode") || !strcmp(name, "A85")) { + str = new ASCII85Stream(str); + } else if (!strcmp(name, "LZWDecode") || !strcmp(name, "LZW")) { + pred = 1; + columns = 1; + colors = 1; + bits = 8; + early = 1; + if (params->isDict()) { + params->dictLookup("Predictor", &obj); + if (obj.isInt()) + pred = obj.getInt(); + obj.free(); + params->dictLookup("Columns", &obj); + if (obj.isInt()) + columns = obj.getInt(); + obj.free(); + params->dictLookup("Colors", &obj); + if (obj.isInt()) + colors = obj.getInt(); + obj.free(); + params->dictLookup("BitsPerComponent", &obj); + if (obj.isInt()) + bits = obj.getInt(); + obj.free(); + params->dictLookup("EarlyChange", &obj); + if (obj.isInt()) + early = obj.getInt(); + obj.free(); + } + str = new LZWStream(str, pred, columns, colors, bits, early); + } else if (!strcmp(name, "RunLengthDecode") || !strcmp(name, "RL")) { + str = new RunLengthStream(str); + } else if (!strcmp(name, "CCITTFaxDecode") || !strcmp(name, "CCF")) { + encoding = 0; + endOfLine = gFalse; + byteAlign = gFalse; + columns = 1728; + rows = 0; + endOfBlock = gTrue; + black = gFalse; + if (params->isDict()) { + params->dictLookup("K", &obj); + if (obj.isInt()) { + encoding = obj.getInt(); + } + obj.free(); + params->dictLookup("EndOfLine", &obj); + if (obj.isBool()) { + endOfLine = obj.getBool(); + } + obj.free(); + params->dictLookup("EncodedByteAlign", &obj); + if (obj.isBool()) { + byteAlign = obj.getBool(); + } + obj.free(); + params->dictLookup("Columns", &obj); + if (obj.isInt()) { + columns = obj.getInt(); + } + obj.free(); + params->dictLookup("Rows", &obj); + if (obj.isInt()) { + rows = obj.getInt(); + } + obj.free(); + params->dictLookup("EndOfBlock", &obj); + if (obj.isBool()) { + endOfBlock = obj.getBool(); + } + obj.free(); + params->dictLookup("BlackIs1", &obj); + if (obj.isBool()) { + black = obj.getBool(); + } + obj.free(); + } + str = new CCITTFaxStream(str, encoding, endOfLine, byteAlign, + columns, rows, endOfBlock, black); + } else if (!strcmp(name, "DCTDecode") || !strcmp(name, "DCT")) { + str = new DCTStream(str); + } else if (!strcmp(name, "FlateDecode") || !strcmp(name, "Fl")) { + pred = 1; + columns = 1; + colors = 1; + bits = 8; + if (params->isDict()) { + params->dictLookup("Predictor", &obj); + if (obj.isInt()) + pred = obj.getInt(); + obj.free(); + params->dictLookup("Columns", &obj); + if (obj.isInt()) + columns = obj.getInt(); + obj.free(); + params->dictLookup("Colors", &obj); + if (obj.isInt()) + colors = obj.getInt(); + obj.free(); + params->dictLookup("BitsPerComponent", &obj); + if (obj.isInt()) + bits = obj.getInt(); + obj.free(); + } + str = new FlateStream(str, pred, columns, colors, bits); + } else { + error(getPos(), "Unknown filter '%s'", name); + str = new EOFStream(str); + } + return str; +} + +//------------------------------------------------------------------------ +// BaseStream +//------------------------------------------------------------------------ + +BaseStream::BaseStream(Object *dict) { + this->dict = *dict; +#ifndef NO_DECRYPTION + decrypt = NULL; +#endif +} + +BaseStream::~BaseStream() { + dict.free(); +#ifndef NO_DECRYPTION + if (decrypt) + delete decrypt; +#endif +} + +#ifndef NO_DECRYPTION +void BaseStream::doDecryption(Guchar *fileKey, int objNum, int objGen) { + decrypt = new Decrypt(fileKey, objNum, objGen); +} +#endif + +//------------------------------------------------------------------------ +// FilterStream +//------------------------------------------------------------------------ + +FilterStream::FilterStream(Stream *str) { + this->str = str; +} + +FilterStream::~FilterStream() { +} + +void FilterStream::setPos(int pos) { + error(-1, "Internal: called setPos() on FilterStream"); +} + +//------------------------------------------------------------------------ +// ImageStream +//------------------------------------------------------------------------ + +ImageStream::ImageStream(Stream *str, int width, int nComps, int nBits) { + int imgLineSize; + + this->str = str; + this->width = width; + this->nComps = nComps; + this->nBits = nBits; + + nVals = width * nComps; + if (nBits == 1) { + imgLineSize = (nVals + 7) & ~7; + } else { + imgLineSize = nVals; + } + imgLine = (Guchar *)gmalloc(imgLineSize * sizeof(Guchar)); + imgIdx = nVals; +} + +ImageStream::~ImageStream() { + gfree(imgLine); +} + +void ImageStream::reset() { + str->reset(); +} + +GBool ImageStream::getPixel(Guchar *pix) { + Gulong buf, bitMask; + int bits; + int c; + int i; + + if (imgIdx >= nVals) { + + // read one line of image pixels + if (nBits == 1) { + for (i = 0; i < nVals; i += 8) { + c = str->getChar(); + imgLine[i+0] = (Guchar)((c >> 7) & 1); + imgLine[i+1] = (Guchar)((c >> 6) & 1); + imgLine[i+2] = (Guchar)((c >> 5) & 1); + imgLine[i+3] = (Guchar)((c >> 4) & 1); + imgLine[i+4] = (Guchar)((c >> 3) & 1); + imgLine[i+5] = (Guchar)((c >> 2) & 1); + imgLine[i+6] = (Guchar)((c >> 1) & 1); + imgLine[i+7] = (Guchar)(c & 1); + } + } else if (nBits == 8) { + for (i = 0; i < nVals; ++i) { + imgLine[i] = str->getChar(); + } + } else { + bitMask = (1 << nBits) - 1; + buf = 0; + bits = 0; + for (i = 0; i < nVals; ++i) { + if (bits < nBits) { + buf = (buf << 8) | (str->getChar() & 0xff); + bits += 8; + } + imgLine[i] = (Guchar)((buf >> (bits - nBits)) & bitMask); + bits -= nBits; + } + } + + // reset to start of line + imgIdx = 0; + } + + for (i = 0; i < nComps; ++i) + pix[i] = imgLine[imgIdx++]; + return gTrue; +} + +void ImageStream::skipLine() { + int n, i; + + n = (nVals * nBits + 7) >> 3; + for (i = 0; i < n; ++i) { + str->getChar(); + } +} + +//------------------------------------------------------------------------ +// StreamPredictor +//------------------------------------------------------------------------ + +StreamPredictor::StreamPredictor(Stream *str, int predictor, + int width, int nComps, int nBits) { + this->str = str; + this->predictor = predictor; + this->width = width; + this->nComps = nComps; + this->nBits = nBits; + + nVals = width * nComps; + pixBytes = (nComps * nBits + 7) >> 3; + rowBytes = ((nVals * nBits + 7) >> 3) + pixBytes; + predLine = (Guchar *)gmalloc(rowBytes); + memset(predLine, 0, rowBytes); + predIdx = rowBytes; +} + +StreamPredictor::~StreamPredictor() { + gfree(predLine); +} + +int StreamPredictor::lookChar() { + if (predIdx >= rowBytes) { + if (!getNextLine()) { + return EOF; + } + } + return predLine[predIdx]; +} + +int StreamPredictor::getChar() { + if (predIdx >= rowBytes) { + if (!getNextLine()) { + return EOF; + } + } + return predLine[predIdx++]; +} + +GBool StreamPredictor::getNextLine() { + int curPred; + Guchar upLeftBuf[4]; + int left, up, upLeft, p, pa, pb, pc; + int c; + Gulong inBuf, outBuf, bitMask; + int inBits, outBits; + int i, j, k; + + // get PNG optimum predictor number + if (predictor == 15) { + if ((curPred = str->getRawChar()) == EOF) { + return gFalse; + } + curPred += 10; + } else { + curPred = predictor; + } + + // read the raw line, apply PNG (byte) predictor + upLeftBuf[0] = upLeftBuf[1] = upLeftBuf[2] = upLeftBuf[3] = 0; + for (i = pixBytes; i < rowBytes; ++i) { + upLeftBuf[3] = upLeftBuf[2]; + upLeftBuf[2] = upLeftBuf[1]; + upLeftBuf[1] = upLeftBuf[0]; + upLeftBuf[0] = predLine[i]; + if ((c = str->getRawChar()) == EOF) { + break; + } + switch (curPred) { + case 11: // PNG sub + predLine[i] = predLine[i - pixBytes] + (Guchar)c; + break; + case 12: // PNG up + predLine[i] = predLine[i] + (Guchar)c; + break; + case 13: // PNG average + predLine[i] = ((predLine[i - pixBytes] + predLine[i]) >> 1) + + (Guchar)c; + break; + case 14: // PNG Paeth + left = predLine[i - pixBytes]; + up = predLine[i]; + upLeft = upLeftBuf[pixBytes]; + p = left + up - upLeft; + if ((pa = p - left) < 0) + pa = -pa; + if ((pb = p - up) < 0) + pb = -pb; + if ((pc = p - upLeft) < 0) + pc = -pc; + if (pa <= pb && pa <= pc) + predLine[i] = pa + (Guchar)c; + else if (pb <= pc) + predLine[i] = pb + (Guchar)c; + else + predLine[i] = pc + (Guchar)c; + break; + case 10: // PNG none + default: // no predictor or TIFF predictor + predLine[i] = (Guchar)c; + break; + } + } + + // apply TIFF (component) predictor + //~ this is completely untested + if (predictor == 2) { + if (nBits == 1) { + inBuf = predLine[pixBytes - 1]; + for (i = pixBytes; i < rowBytes; i += 8) { + // 1-bit add is just xor + inBuf = (inBuf << 8) | predLine[i]; + predLine[i] ^= inBuf >> nComps; + } + } else if (nBits == 8) { + for (i = pixBytes; i < rowBytes; ++i) { + predLine[i] += predLine[i - nComps]; + } + } else { + upLeftBuf[0] = upLeftBuf[1] = upLeftBuf[2] = upLeftBuf[3] = 0; + bitMask = (1 << nBits) - 1; + inBuf = outBuf = 0; + inBits = outBits = 0; + j = k = pixBytes; + for (i = 0; i < nVals; ++i) { + if (inBits < nBits) { + inBuf = (inBuf << 8) | (predLine[j++] & 0xff); + inBits += 8; + } + upLeftBuf[3] = upLeftBuf[2]; + upLeftBuf[2] = upLeftBuf[1]; + upLeftBuf[1] = upLeftBuf[0]; + upLeftBuf[0] = (upLeftBuf[nComps] + + (inBuf >> (inBits - nBits))) & bitMask; + outBuf = (outBuf << nBits) | upLeftBuf[0]; + inBits -= nBits; + outBits += nBits; + if (outBits > 8) { + predLine[k++] = (Guchar)(outBuf >> (outBits - 8)); + } + } + if (outBits > 0) { + predLine[k++] = (Guchar)(outBuf << (8 - outBits)); + } + } + } + + // reset to start of line + predIdx = pixBytes; + + return gTrue; +} + +//------------------------------------------------------------------------ +// FileStream +//------------------------------------------------------------------------ + +FileStream::FileStream(FILE *f, int start, int length, Object *dict): + BaseStream(dict) { + this->f = f; + this->start = start; + this->length = length; + bufPtr = bufEnd = buf; + bufPos = start; + savePos = -1; +} + +FileStream::~FileStream() { + if (savePos >= 0) { + fseek(f, savePos, SEEK_SET); + } +} + +Stream *FileStream::makeSubStream(int start, int length, Object *dict) { + return new FileStream(f, start, length, dict); +} + +void FileStream::reset() { + savePos = (int)ftell(f); + fseek(f, start, SEEK_SET); + bufPtr = bufEnd = buf; + bufPos = start; +#ifndef NO_DECRYPTION + if (decrypt) + decrypt->reset(); +#endif +} + +GBool FileStream::fillBuf() { + int n; +#ifndef NO_DECRYPTION + char *p; +#endif + + bufPos += bufEnd - buf; + bufPtr = bufEnd = buf; + if (length >= 0 && bufPos >= start + length) + return gFalse; + if (length >= 0 && bufPos + 256 > start + length) + n = start + length - bufPos; + else + n = 256; + n = fread(buf, 1, n, f); + bufEnd = buf + n; + if (bufPtr >= bufEnd) + return gFalse; +#ifndef NO_DECRYPTION + if (decrypt) { + for (p = buf; p < bufEnd; ++p) + *p = (char)decrypt->decryptByte((Guchar)*p); + } +#endif + return gTrue; +} + +void FileStream::setPos(int pos1) { + long size; + + if (pos1 >= 0) { + fseek(f, pos1, SEEK_SET); + bufPos = pos1; + } else { + fseek(f, 0, SEEK_END); + size = ftell(f); + if (pos1 < -size) + pos1 = (int)(-size); + fseek(f, pos1, SEEK_END); + bufPos = (int)ftell(f); + } + bufPtr = bufEnd = buf; +} + +void FileStream::moveStart(int delta) { + this->start += delta; + bufPtr = bufEnd = buf; + bufPos = start; +} + +//------------------------------------------------------------------------ +// EmbedStream +//------------------------------------------------------------------------ + +EmbedStream::EmbedStream(Stream *str, Object *dict): + BaseStream(dict) { + this->str = str; +} + +EmbedStream::~EmbedStream() { +} + +Stream *EmbedStream::makeSubStream(int start, int length, Object *dict) { + error(-1, "Internal: called makeSubStream() on EmbedStream"); + return NULL; +} + +void EmbedStream::setPos(int pos) { + error(-1, "Internal: called setPos() on EmbedStream"); +} + +int EmbedStream::getStart() { + error(-1, "Internal: called getStart() on EmbedStream"); + return 0; +} + +void EmbedStream::moveStart(int start) { + error(-1, "Internal: called moveStart() on EmbedStream"); +} + +//------------------------------------------------------------------------ +// ASCIIHexStream +//------------------------------------------------------------------------ + +ASCIIHexStream::ASCIIHexStream(Stream *str): + FilterStream(str) { + buf = EOF; + eof = gFalse; +} + +ASCIIHexStream::~ASCIIHexStream() { + delete str; +} + +void ASCIIHexStream::reset() { + str->reset(); + buf = EOF; + eof = gFalse; +} + +int ASCIIHexStream::lookChar() { + int c1, c2, x; + + if (buf != EOF) + return buf; + if (eof) { + buf = EOF; + return EOF; + } + do { + c1 = str->getChar(); + } while (isspace(c1)); + if (c1 == '>') { + eof = gTrue; + buf = EOF; + return buf; + } + do { + c2 = str->getChar(); + } while (isspace(c2)); + if (c2 == '>') { + eof = gTrue; + c2 = '0'; + } + if (c1 >= '0' && c1 <= '9') { + x = (c1 - '0') << 4; + } else if (c1 >= 'A' && c1 <= 'F') { + x = (c1 - 'A' + 10) << 4; + } else if (c1 >= 'a' && c1 <= 'f') { + x = (c1 - 'a' + 10) << 4; + } else if (c1 == EOF) { + eof = gTrue; + x = 0; + } else { + error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c1); + x = 0; + } + if (c2 >= '0' && c2 <= '9') { + x += c2 - '0'; + } else if (c2 >= 'A' && c2 <= 'F') { + x += c2 - 'A' + 10; + } else if (c2 >= 'a' && c2 <= 'f') { + x += c2 - 'a' + 10; + } else if (c2 == EOF) { + eof = gTrue; + x = 0; + } else { + error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c2); + } + buf = x & 0xff; + return buf; +} + +GString *ASCIIHexStream::getPSFilter(char *indent) { + GString *s; + + s = str->getPSFilter(indent); + s->append(indent)->append("/ASCIIHexDecode filter\n"); + return s; +} + +GBool ASCIIHexStream::isBinary(GBool last) { + return str->isBinary(gFalse); +} + +//------------------------------------------------------------------------ +// ASCII85Stream +//------------------------------------------------------------------------ + +ASCII85Stream::ASCII85Stream(Stream *str): + FilterStream(str) { + index = n = 0; + eof = gFalse; +} + +ASCII85Stream::~ASCII85Stream() { + delete str; +} + +void ASCII85Stream::reset() { + str->reset(); + index = n = 0; + eof = gFalse; +} + +int ASCII85Stream::lookChar() { + int k; + Gulong t; + + if (index >= n) { + if (eof) + return EOF; + index = 0; + do { + c[0] = str->getChar(); + } while (c[0] == '\n' || c[0] == '\r'); + if (c[0] == '~' || c[0] == EOF) { + eof = gTrue; + n = 0; + return EOF; + } else if (c[0] == 'z') { + b[0] = b[1] = b[2] = b[3] = 0; + n = 4; + } else { + for (k = 1; k < 5; ++k) { + do { + c[k] = str->getChar(); + } while (c[k] == '\n' || c[k] == '\r'); + if (c[k] == '~' || c[k] == EOF) + break; + } + n = k - 1; + if (k < 5 && (c[k] == '~' || c[k] == EOF)) { + for (++k; k < 5; ++k) + c[k] = 0x21 + 84; + eof = gTrue; + } + t = 0; + for (k = 0; k < 5; ++k) + t = t * 85 + (c[k] - 0x21); + for (k = 3; k >= 0; --k) { + b[k] = (int)(t & 0xff); + t >>= 8; + } + } + } + return b[index]; +} + +GString *ASCII85Stream::getPSFilter(char *indent) { + GString *s; + + s = str->getPSFilter(indent); + s->append(indent)->append("/ASCII85Decode filter\n"); + return s; +} + +GBool ASCII85Stream::isBinary(GBool last) { + return str->isBinary(gFalse); +} + +//------------------------------------------------------------------------ +// LZWStream +//------------------------------------------------------------------------ + +LZWStream::LZWStream(Stream *str, int predictor1, int columns1, int colors1, + int bits1, int early1): + FilterStream(str) { + if (predictor1 != 1) { + pred = new StreamPredictor(this, predictor1, columns1, colors1, bits1); + } else { + pred = NULL; + } + early = early1; + zPipe = NULL; + bufPtr = bufEnd = buf; +} + +LZWStream::~LZWStream() { + if (zPipe) { +#ifdef HAVE_POPEN + pclose(zPipe); +#else + fclose(zPipe); +#endif + zPipe = NULL; + unlink(zName->getCString()); + delete zName; + } + if (pred) { + delete pred; + } + delete str; +} + +int LZWStream::getChar() { + if (pred) { + return pred->getChar(); + } + return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); +} + +int LZWStream::lookChar() { + if (pred) { + return pred->lookChar(); + } + return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); +} + +int LZWStream::getRawChar() { + return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); +} + +void LZWStream::reset() { + FILE *f; + GString *zCmd; + + //----- close old LZW stream + if (zPipe) { +#ifdef HAVE_POPEN + pclose(zPipe); +#else + fclose(zPipe); +#endif + zPipe = NULL; + unlink(zName->getCString()); + delete zName; + } + + //----- tell Delorie runtime to spawn a new instance of COMMAND.COM + // to run gzip +#if __DJGPP__ + if (!setDJSYSFLAGS) { + setenv("DJSYSFLAGS", "0x0002", 0); + setDJSYSFLAGS = gTrue; + } +#endif + + //----- create the .Z file + if (!openTempFile(&zName, &f, "wb", ".Z")) { + error(getPos(), "Couldn't create temporary file for LZW stream"); + return; + } + dumpFile(f); + fclose(f); + + //----- execute uncompress / gzip + zCmd = new GString(uncompressCmd); + zCmd->append(' '); + zCmd->append(zName); +#if defined(MACOS) + long magicCookie; + // first we open the engine up + OSErr err = OpenSITEngine(kUseExternalEngine, &magicCookie); + // if we found it - let's use it! + if (!err && magicCookie) { + // make sure we have the correct version of the Engine + if (GetSITEngineVersion(magicCookie) >= kFirstSupportedEngine) { + FSSpec myFSS; + Str255 pName; + strcpy((char *)pName, zName->getCString()); + c2pstr((char *)pName); + FSMakeFSSpec(0, 0, pName, &myFSS); + short ftype = DetermineFileType(magicCookie, &myFSS); + OSErr expandErr = ExpandFSSpec(magicCookie, ftype, &myFSS, + NULL, NULL, kCreateFolderNever, + kDeleteOriginal, kTextConvertSmart); + } + } +#elif defined(HAVE_POPEN) + if (!(zPipe = popen(zCmd->getCString(), POPEN_READ_MODE))) { + error(getPos(), "Couldn't popen '%s'", zCmd->getCString()); + unlink(zName->getCString()); + delete zName; + return; + } +#else // HAVE_POPEN +#ifdef VMS + if (!system(zCmd->getCString())) { +#else + if (system(zCmd->getCString())) { +#endif + error(getPos(), "Couldn't execute '%s'", zCmd->getCString()); + unlink(zName->getCString()); + delete zName; + return; + } + zName->del(zName->getLength() - 2, 2); + if (!(zPipe = fopen(zName->getCString(), "rb"))) { + error(getPos(), "Couldn't open uncompress file '%s'", zName->getCString()); + unlink(zName->getCString()); + delete zName; + return; + } +#endif // HAVE_POPEN + + //----- clean up + delete zCmd; + + //----- initialize buffer + bufPtr = bufEnd = buf; +} + +void LZWStream::dumpFile(FILE *f) { + int outCodeBits; // size of output code + int outBits; // max output code + int outBuf[8]; // output buffer + int outData; // temporary output buffer + int inCode, outCode; // input and output codes + int nextCode; // next code index + GBool eof; // set when EOF is reached + GBool clear; // set if table needs to be cleared + GBool first; // indicates first code word after clear + int i, j; + + str->reset(); + + // magic number + fputc(0x1f, f); + fputc(0x9d, f); + + // max code length, block mode flag + fputc(0x8c, f); + + // init input side + inCodeBits = 9; + inputBuf = 0; + inputBits = 0; + eof = gFalse; + + // init output side + outCodeBits = 9; + + // clear table + first = gTrue; + nextCode = 258; + + clear = gFalse; + do { + for (i = 0; i < 8; ++i) { + // check for table overflow + if (nextCode + early > 0x1001) { + inCode = 256; + + // read input code + } else { + do { + inCode = getCode(); + if (inCode == EOF) { + eof = gTrue; + inCode = 0; + } + } while (first && inCode == 256); + } + + // compute output code + if (inCode < 256) { + outCode = inCode; + } else if (inCode == 256) { + outCode = 256; + clear = gTrue; + } else if (inCode == 257) { + outCode = 0; + eof = gTrue; + } else { + outCode = inCode - 1; + } + outBuf[i] = outCode; + + // next code index + if (first) + first = gFalse; + else + ++nextCode; + + // check input code size + if (nextCode + early == 0x200) + inCodeBits = 10; + else if (nextCode + early == 0x400) { + inCodeBits = 11; + } else if (nextCode + early == 0x800) { + inCodeBits = 12; + } + + // check for eof/clear + if (eof) + break; + if (clear) { + i = 8; + break; + } + } + + // write output block + outData = 0; + outBits = 0; + j = 0; + while (j < i || outBits > 0) { + if (outBits < 8 && j < i) { + outData = outData | (outBuf[j++] << outBits); + outBits += outCodeBits; + } + fputc(outData & 0xff, f); + outData >>= 8; + outBits -= 8; + } + + // check output code size + if (nextCode - 1 == 512 || + nextCode - 1 == 1024 || + nextCode - 1 == 2048 || + nextCode - 1 == 4096) { + outCodeBits = inCodeBits; + } + + // clear table if necessary + if (clear) { + inCodeBits = 9; + outCodeBits = 9; + first = gTrue; + nextCode = 258; + clear = gFalse; + } + } while (!eof); +} + +int LZWStream::getCode() { + int c; + int code; + + while (inputBits < inCodeBits) { + if ((c = str->getChar()) == EOF) + return EOF; + inputBuf = (inputBuf << 8) | (c & 0xff); + inputBits += 8; + } + code = (inputBuf >> (inputBits - inCodeBits)) & ((1 << inCodeBits) - 1); + inputBits -= inCodeBits; + return code; +} + +GBool LZWStream::fillBuf() { + int n; + + if (!zPipe) + return gFalse; + if ((n = fread(buf, 1, 256, zPipe)) < 256) { +#ifdef HAVE_POPEN + pclose(zPipe); +#else + fclose(zPipe); +#endif + zPipe = NULL; + unlink(zName->getCString()); + delete zName; + } + bufPtr = buf; + bufEnd = buf + n; + return n > 0; +} + +GString *LZWStream::getPSFilter(char *indent) { + GString *s; + + if (pred) { + return NULL; + } + s = str->getPSFilter(indent); + s->append(indent)->append("/LZWDecode filter\n"); + return s; +} + +GBool LZWStream::isBinary(GBool last) { + return str->isBinary(gTrue); +} + +//------------------------------------------------------------------------ +// RunLengthStream +//------------------------------------------------------------------------ + +RunLengthStream::RunLengthStream(Stream *str): + FilterStream(str) { + bufPtr = bufEnd = buf; + eof = gFalse; +} + +RunLengthStream::~RunLengthStream() { + delete str; +} + +void RunLengthStream::reset() { + str->reset(); + bufPtr = bufEnd = buf; + eof = gFalse; +} + +GString *RunLengthStream::getPSFilter(char *indent) { + GString *s; + + s = str->getPSFilter(indent); + s->append(indent)->append("/RunLengthDecode filter\n"); + return s; +} + +GBool RunLengthStream::isBinary(GBool last) { + return str->isBinary(gTrue); +} + +GBool RunLengthStream::fillBuf() { + int c; + int n, i; + + if (eof) + return gFalse; + c = str->getChar(); + if (c == 0x80 || c == EOF) { + eof = gTrue; + return gFalse; + } + if (c < 0x80) { + n = c + 1; + for (i = 0; i < n; ++i) + buf[i] = (char)str->getChar(); + } else { + n = 0x101 - c; + c = str->getChar(); + for (i = 0; i < n; ++i) + buf[i] = (char)c; + } + bufPtr = buf; + bufEnd = buf + n; + return gTrue; +} + +//------------------------------------------------------------------------ +// CCITTFaxStream +//------------------------------------------------------------------------ + +CCITTFaxStream::CCITTFaxStream(Stream *str, int encoding, GBool endOfLine, + GBool byteAlign, int columns, int rows, + GBool endOfBlock, GBool black): + FilterStream(str) { + this->encoding = encoding; + this->endOfLine = endOfLine; + this->byteAlign = byteAlign; + this->columns = columns; + this->rows = rows; + this->endOfBlock = endOfBlock; + this->black = black; + refLine = (short *)gmalloc((columns + 3) * sizeof(short)); + codingLine = (short *)gmalloc((columns + 2) * sizeof(short)); + + eof = gFalse; + row = 0; + nextLine2D = encoding < 0; + inputBits = 0; + codingLine[0] = 0; + codingLine[1] = refLine[2] = columns; + a0 = 1; + + buf = EOF; +} + +CCITTFaxStream::~CCITTFaxStream() { + delete str; + gfree(refLine); + gfree(codingLine); +} + +void CCITTFaxStream::reset() { + int n; + + str->reset(); + eof = gFalse; + row = 0; + nextLine2D = encoding < 0; + inputBits = 0; + codingLine[0] = 0; + codingLine[1] = refLine[2] = columns; + a0 = 1; + buf = EOF; + + // get initial end-of-line marker and 2D encoding tag + if (endOfBlock) { + if (lookBits(12) == 0x001) { + eatBits(12); + } + } else { + for (n = 0; n < 11 && lookBits(n) == 0; ++n) ; + if (n == 11 && lookBits(12) == 0x001) { + eatBits(12); + } + } + if (encoding > 0) { + nextLine2D = !lookBits(1); + eatBits(1); + } +} + +int CCITTFaxStream::lookChar() { + short code1, code2, code3; + int a0New; +#if 0 //~ + GBool err; +#endif + int ret; + int bits, i, n; + + // if at eof just return EOF + if (eof && codingLine[a0] >= columns) { + return EOF; + } + + // read the next row +#if 0 //~ + err = gFalse; +#endif + if (codingLine[a0] >= columns) { + + // 2-D encoding + if (nextLine2D) { + for (i = 0; codingLine[i] < columns; ++i) + refLine[i] = codingLine[i]; + refLine[i] = refLine[i + 1] = columns; + b1 = 1; + a0New = codingLine[a0 = 0] = 0; + do { + code1 = getTwoDimCode(); + switch (code1) { + case twoDimPass: + if (refLine[b1] < columns) { + a0New = refLine[b1 + 1]; + b1 += 2; + } + break; + case twoDimHoriz: + if ((a0 & 1) == 0) { + code1 = code2 = 0; + do { + code1 += code3 = getWhiteCode(); + } while (code3 >= 64); + do { + code2 += code3 = getBlackCode(); + } while (code3 >= 64); + } else { + code1 = code2 = 0; + do { + code1 += code3 = getBlackCode(); + } while (code3 >= 64); + do { + code2 += code3 = getWhiteCode(); + } while (code3 >= 64); + } + codingLine[a0 + 1] = a0New + code1; + ++a0; + a0New = codingLine[a0 + 1] = codingLine[a0] + code2; + ++a0; + while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns) + b1 += 2; + break; + case twoDimVert0: + a0New = codingLine[++a0] = refLine[b1]; + if (refLine[b1] < columns) { + ++b1; + while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns) + b1 += 2; + } + break; + case twoDimVertR1: + a0New = codingLine[++a0] = refLine[b1] + 1; + if (refLine[b1] < columns) { + ++b1; + while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns) + b1 += 2; + } + break; + case twoDimVertL1: + a0New = codingLine[++a0] = refLine[b1] - 1; + --b1; + while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns) + b1 += 2; + break; + case twoDimVertR2: + a0New = codingLine[++a0] = refLine[b1] + 2; + if (refLine[b1] < columns) { + ++b1; + while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns) + b1 += 2; + } + break; + case twoDimVertL2: + a0New = codingLine[++a0] = refLine[b1] - 2; + --b1; + while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns) + b1 += 2; + break; + case twoDimVertR3: + a0New = codingLine[++a0] = refLine[b1] + 3; + if (refLine[b1] < columns) { + ++b1; + while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns) + b1 += 2; + } + break; + case twoDimVertL3: + a0New = codingLine[++a0] = refLine[b1] - 3; + --b1; + while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns) + b1 += 2; + break; + case EOF: + eof = gTrue; + codingLine[a0 = 0] = columns; + return EOF; + default: + error(getPos(), "Bad 2D code %04x in CCITTFax stream", code1); +#if 0 //~ + err = gTrue; + break; +#else + eof = gTrue; + return EOF; +#endif + } + } while (codingLine[a0] < columns); + + // 1-D encoding + } else { + codingLine[a0 = 0] = 0; + while (1) { + code1 = 0; + do { + code1 += code3 = getWhiteCode(); + } while (code3 >= 64); + codingLine[a0+1] = codingLine[a0] + code1; + ++a0; + if (codingLine[a0] >= columns) + break; + code2 = 0; + do { + code2 += code3 = getBlackCode(); + } while (code3 >= 64); + codingLine[a0+1] = codingLine[a0] + code2; + ++a0; + if (codingLine[a0] >= columns) + break; + } + } + + if (codingLine[a0] != columns) { + error(getPos(), "CCITTFax row is wrong length (%d)", codingLine[a0]); +#if 0 //~ + err = gTrue; +#endif + } + + // byte-align the row + if (byteAlign) { + inputBits &= ~7; + } + + // check for end-of-line marker, end-of-block marker, and + // 2D encoding tag + if (endOfBlock) { + code1 = lookBits(12); + if (code1 == EOF) { + eof = gTrue; + } else if (code1 == 0x001) { + eatBits(12); + if (encoding > 0) { + nextLine2D = !lookBits(1); + eatBits(1); + } + code1 = lookBits(12); + if (code1 == 0x001) { + eatBits(12); + if (encoding > 0) { + lookBits(1); + eatBits(1); + } + if (encoding >= 0) { + for (i = 0; i < 4; ++i) { + code1 = lookBits(12); + if (code1 != 0x001) { + error(getPos(), "Bad RTC code in CCITTFax stream"); + } + eatBits(12); + if (encoding > 0) { + lookBits(1); + eatBits(1); + } + } + } + eof = gTrue; + } + } else { + if (encoding > 0) { + nextLine2D = !lookBits(1); + eatBits(1); + } + } + } else { + if (row == rows - 1) { + eof = gTrue; + } else { + for (n = 0; n < 11 && lookBits(n) == 0; ++n) ; + if (n == 11 && lookBits(12) == 0x001) { + eatBits(12); + } + if (encoding > 0) { + nextLine2D = !lookBits(1); + eatBits(1); + } + } + } + +#if 0 //~ + // This looks for an end-of-line marker after an error, however + // some (most?) CCITT streams in PDF files don't use end-of-line + // markers, and the just-plow-on technique works better in those + // cases. + else if (err) { + do { + if (code1 == EOF) { + eof = gTrue; + return EOF; + } + eatBits(1); + code1 = look13Bits(); + } while ((code1 >> 1) != 0x001); + eatBits(12); + codingLine[++a0] = columns; + if (encoding > 0) { + eatBits(1); + nextLine2D = !(code1 & 1); + } + } +#endif + + a0 = 0; + outputBits = codingLine[1] - codingLine[0]; + if (outputBits == 0) { + a0 = 1; + outputBits = codingLine[2] - codingLine[1]; + } + + ++row; + } + + // get a byte + if (outputBits >= 8) { + ret = ((a0 & 1) == 0) ? 0xff : 0x00; + if ((outputBits -= 8) == 0) { + ++a0; + if (codingLine[a0] < columns) { + outputBits = codingLine[a0 + 1] - codingLine[a0]; + } + } + } else { + bits = 8; + ret = 0; + do { + if (outputBits > bits) { + i = bits; + bits = 0; + if ((a0 & 1) == 0) { + ret |= 0xff >> (8 - i); + } + outputBits -= i; + } else { + i = outputBits; + bits -= outputBits; + if ((a0 & 1) == 0) { + ret |= (0xff >> (8 - i)) << bits; + } + outputBits = 0; + ++a0; + if (codingLine[a0] < columns) { + outputBits = codingLine[a0 + 1] - codingLine[a0]; + } + } + } while (bits > 0 && codingLine[a0] < columns); + } + buf = black ? (ret ^ 0xff) : ret; + return buf; +} + +short CCITTFaxStream::getTwoDimCode() { + short code; + CCITTCode *p; + int n; + + code = 0; // make gcc happy + if (endOfBlock) { + code = lookBits(7); + p = &twoDimTab1[code]; + if (p->bits > 0) { + eatBits(p->bits); + return p->n; + } + } else { + for (n = 1; n <= 7; ++n) { + code = lookBits(n); + if (n < 7) { + code <<= 7 - n; + } + p = &twoDimTab1[code]; + if (p->bits == n) { + eatBits(n); + return p->n; + } + } + } + error(getPos(), "Bad two dim code (%04x) in CCITTFax stream", code); + return EOF; +} + +short CCITTFaxStream::getWhiteCode() { + short code; + CCITTCode *p; + int n; + + code = 0; // make gcc happy + if (endOfBlock) { + code = lookBits(12); + if ((code >> 5) == 0) + p = &whiteTab1[code]; + else + p = &whiteTab2[code >> 3]; + if (p->bits > 0) { + eatBits(p->bits); + return p->n; + } + } else { + for (n = 1; n <= 9; ++n) { + code = lookBits(n); + if (n < 9) { + code <<= 9 - n; + } + p = &whiteTab2[code]; + if (p->bits == n) { + eatBits(n); + return p->n; + } + } + for (n = 11; n <= 12; ++n) { + code = lookBits(n); + if (n < 12) { + code <<= 12 - n; + } + p = &whiteTab1[code]; + if (p->bits == n) { + eatBits(n); + return p->n; + } + } + } + error(getPos(), "Bad white code (%04x) in CCITTFax stream", code); + return EOF; +} + +short CCITTFaxStream::getBlackCode() { + short code; + CCITTCode *p; + int n; + + code = 0; // make gcc happy + if (endOfBlock) { + code = lookBits(13); + if ((code >> 7) == 0) + p = &blackTab1[code]; + else if ((code >> 9) == 0) + p = &blackTab2[(code >> 1) - 64]; + else + p = &blackTab3[code >> 7]; + if (p->bits > 0) { + eatBits(p->bits); + return p->n; + } + } else { + for (n = 2; n <= 6; ++n) { + code = lookBits(n); + if (n < 6) { + code <<= 6 - n; + } + p = &blackTab3[code]; + if (p->bits == n) { + eatBits(n); + return p->n; + } + } + for (n = 7; n <= 12; ++n) { + code = lookBits(n); + if (n < 12) { + code <<= 12 - n; + } + if (code >= 64) { + p = &blackTab2[code - 64]; + if (p->bits == n) { + eatBits(n); + return p->n; + } + } + } + for (n = 10; n <= 13; ++n) { + code = lookBits(n); + if (n < 13) { + code <<= 13 - n; + } + p = &blackTab1[code]; + if (p->bits == n) { + eatBits(n); + return p->n; + } + } + } + error(getPos(), "Bad black code (%04x) in CCITTFax stream", code); + return EOF; +} + +short CCITTFaxStream::lookBits(int n) { + int c; + + while (inputBits < n) { + if ((c = str->getChar()) == EOF) { + if (inputBits == 0) + return EOF; + c = 0; + } + inputBuf = (inputBuf << 8) + c; + inputBits += 8; + } + return (inputBuf >> (inputBits - n)) & (0xffff >> (16 - n)); +} + +GString *CCITTFaxStream::getPSFilter(char *indent) { + GString *s; + char s1[50]; + + s = str->getPSFilter(indent); + s->append(indent)->append("<< "); + if (encoding != 0) { + sprintf(s1, "/K %d ", encoding); + s->append(s1); + } + if (endOfLine) { + s->append("/EndOfLine true "); + } + if (byteAlign) { + s->append("/EncodedByteAlign true "); + } + sprintf(s1, "/Columns %d ", columns); + s->append(s1); + if (rows != 0) { + sprintf(s1, "/Rows %d ", rows); + s->append(s1); + } + if (!endOfBlock) { + s->append("/EndOfBlock false "); + } + if (black) { + s->append("/BlackIs1 true "); + } + s->append(">> /CCITTFaxDecode filter\n"); + return s; +} + +GBool CCITTFaxStream::isBinary(GBool last) { + return str->isBinary(gTrue); +} + +//------------------------------------------------------------------------ +// DCTStream +//------------------------------------------------------------------------ + +// IDCT constants (20.12 fixed point format) +#ifndef FP_IDCT +#define dctCos1 4017 // cos(pi/16) +#define dctSin1 799 // sin(pi/16) +#define dctCos3 3406 // cos(3*pi/16) +#define dctSin3 2276 // sin(3*pi/16) +#define dctCos6 1567 // cos(6*pi/16) +#define dctSin6 3784 // sin(6*pi/16) +#define dctSqrt2 5793 // sqrt(2) +#define dctSqrt1d2 2896 // sqrt(2) / 2 +#endif + +// IDCT constants +#ifdef FP_IDCT +#define dctCos1 0.98078528 // cos(pi/16) +#define dctSin1 0.19509032 // sin(pi/16) +#define dctCos3 0.83146961 // cos(3*pi/16) +#define dctSin3 0.55557023 // sin(3*pi/16) +#define dctCos6 0.38268343 // cos(6*pi/16) +#define dctSin6 0.92387953 // sin(6*pi/16) +#define dctSqrt2 1.41421356 // sqrt(2) +#define dctSqrt1d2 0.70710678 // sqrt(2) / 2 +#endif + +// color conversion parameters (16.16 fixed point format) +#define dctCrToR 91881 // 1.4020 +#define dctCbToG -22553 // -0.3441363 +#define dctCrToG -46802 // -0.71413636 +#define dctCbToB 116130 // 1.772 + +// clip [-256,511] --> [0,255] +#define dctClipOffset 256 +static Guchar dctClip[768]; +static int dctClipInit = 0; + +// zig zag decode map +static int dctZigZag[64] = { + 0, + 1, 8, + 16, 9, 2, + 3, 10, 17, 24, + 32, 25, 18, 11, 4, + 5, 12, 19, 26, 33, 40, + 48, 41, 34, 27, 20, 13, 6, + 7, 14, 21, 28, 35, 42, 49, 56, + 57, 50, 43, 36, 29, 22, 15, + 23, 30, 37, 44, 51, 58, + 59, 52, 45, 38, 31, + 39, 46, 53, 60, + 61, 54, 47, + 55, 62, + 63 +}; + +DCTStream::DCTStream(Stream *str): + FilterStream(str) { + int i, j; + + width = height = 0; + mcuWidth = mcuHeight = 0; + numComps = 0; + comp = 0; + x = y = dy = 0; + for (i = 0; i < 4; ++i) + for (j = 0; j < 32; ++j) + rowBuf[i][j] = NULL; + + if (!dctClipInit) { + for (i = -256; i < 0; ++i) + dctClip[dctClipOffset + i] = 0; + for (i = 0; i < 256; ++i) + dctClip[dctClipOffset + i] = i; + for (i = 256; i < 512; ++i) + dctClip[dctClipOffset + i] = 255; + dctClipInit = 1; + } +} + +DCTStream::~DCTStream() { + int i, j; + + delete str; + for (i = 0; i < numComps; ++i) + for (j = 0; j < mcuHeight; ++j) + gfree(rowBuf[i][j]); +} + +void DCTStream::reset() { + str->reset(); + if (!readHeader()) { + y = height; + return; + } + restartMarker = 0xd0; + restart(); +} + +int DCTStream::getChar() { + int c; + + c = lookChar(); + if (c == EOF) + return EOF; + if (++comp == numComps) { + comp = 0; + if (++x == width) { + x = 0; + ++y; + ++dy; + } + } + if (y == height) + readTrailer(); + return c; +} + +int DCTStream::lookChar() { + if (y >= height) + return EOF; + if (dy >= mcuHeight) { + if (!readMCURow()) { + y = height; + return EOF; + } + comp = 0; + x = 0; + dy = 0; + } + return rowBuf[comp][dy][x]; +} + +void DCTStream::restart() { + int i; + + inputBits = 0; + restartCtr = restartInterval; + for (i = 0; i < numComps; ++i) + compInfo[i].prevDC = 0; +} + +GBool DCTStream::readMCURow() { + Guchar data[64]; + Guchar *p1, *p2; + int pY, pCb, pCr, pR, pG, pB; + int h, v, horiz, vert, hSub, vSub; + int x1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i; + int c; + + for (x1 = 0; x1 < width; x1 += mcuWidth) { + + // deal with restart marker + if (restartInterval > 0 && restartCtr == 0) { + c = readMarker(); + if (c != restartMarker) { + error(getPos(), "Bad DCT data: incorrect restart marker"); + return gFalse; + } + if (++restartMarker == 0xd8) + restartMarker = 0xd0; + restart(); + } + + // read one MCU + for (cc = 0; cc < numComps; ++cc) { + h = compInfo[cc].hSample; + v = compInfo[cc].vSample; + horiz = mcuWidth / h; + vert = mcuHeight / v; + hSub = horiz / 8; + vSub = vert / 8; + for (y2 = 0; y2 < mcuHeight; y2 += vert) { + for (x2 = 0; x2 < mcuWidth; x2 += horiz) { + if (!readDataUnit(&dcHuffTables[compInfo[cc].dcHuffTable], + &acHuffTables[compInfo[cc].acHuffTable], + quantTables[compInfo[cc].quantTable], + &compInfo[cc].prevDC, + data)) + return gFalse; + if (hSub == 1 && vSub == 1) { + for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) { + p1 = &rowBuf[cc][y2+y3][x1+x2]; + p1[0] = data[i]; + p1[1] = data[i+1]; + p1[2] = data[i+2]; + p1[3] = data[i+3]; + p1[4] = data[i+4]; + p1[5] = data[i+5]; + p1[6] = data[i+6]; + p1[7] = data[i+7]; + } + } else if (hSub == 2 && vSub == 2) { + for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) { + p1 = &rowBuf[cc][y2+y3][x1+x2]; + p2 = &rowBuf[cc][y2+y3+1][x1+x2]; + p1[0] = p1[1] = p2[0] = p2[1] = data[i]; + p1[2] = p1[3] = p2[2] = p2[3] = data[i+1]; + p1[4] = p1[5] = p2[4] = p2[5] = data[i+2]; + p1[6] = p1[7] = p2[6] = p2[7] = data[i+3]; + p1[8] = p1[9] = p2[8] = p2[9] = data[i+4]; + p1[10] = p1[11] = p2[10] = p2[11] = data[i+5]; + p1[12] = p1[13] = p2[12] = p2[13] = data[i+6]; + p1[14] = p1[15] = p2[14] = p2[15] = data[i+7]; + } + } else { + i = 0; + for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) { + for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) { + for (y5 = 0; y5 < vSub; ++y5) + for (x5 = 0; x5 < hSub; ++x5) + rowBuf[cc][y2+y4+y5][x1+x2+x4+x5] = data[i]; + ++i; + } + } + } + } + } + } + --restartCtr; + + // color space conversion + if (colorXform) { + // convert YCbCr to RGB + if (numComps == 3) { + for (y2 = 0; y2 < mcuHeight; ++y2) { + for (x2 = 0; x2 < mcuWidth; ++x2) { + pY = rowBuf[0][y2][x1+x2]; + pCb = rowBuf[1][y2][x1+x2] - 128; + pCr = rowBuf[2][y2][x1+x2] - 128; + pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16; + rowBuf[0][y2][x1+x2] = dctClip[dctClipOffset + pR]; + pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16; + rowBuf[1][y2][x1+x2] = dctClip[dctClipOffset + pG]; + pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16; + rowBuf[2][y2][x1+x2] = dctClip[dctClipOffset + pB]; + } + } + // convert YCbCrK to CMYK (K is passed through unchanged) + } else if (numComps == 4) { + for (y2 = 0; y2 < mcuHeight; ++y2) { + for (x2 = 0; x2 < mcuWidth; ++x2) { + pY = rowBuf[0][y2][x1+x2]; + pCb = rowBuf[1][y2][x1+x2] - 128; + pCr = rowBuf[2][y2][x1+x2] - 128; + pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16; + rowBuf[0][y2][x1+x2] = 255 - dctClip[dctClipOffset + pR]; + pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32678) >> 16; + rowBuf[1][y2][x1+x2] = 255 - dctClip[dctClipOffset + pG]; + pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16; + rowBuf[2][y2][x1+x2] = 255 - dctClip[dctClipOffset + pB]; + } + } + } + } + } + return gTrue; +} + +// This IDCT algorithm is taken from: +// Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz, +// "Practical Fast 1-D DCT Algorithms with 11 Multiplications", +// IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989, +// 988-991. +// The stage numbers mentioned in the comments refer to Figure 1 in this +// paper. +#ifndef FP_IDCT +GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable, + DCTHuffTable *acHuffTable, + Guchar quantTable[64], int *prevDC, + Guchar data[64]) { + int tmp1[64]; + int v0, v1, v2, v3, v4, v5, v6, v7, t; + int run, size, amp; + int c; + int i, j; + + // Huffman decode and dequantize + size = readHuffSym(dcHuffTable); + if (size == 9999) + return gFalse; + if (size > 0) { + amp = readAmp(size); + if (amp == 9999) + return gFalse; + } else { + amp = 0; + } + tmp1[0] = (*prevDC += amp) * quantTable[0]; + for (i = 1; i < 64; ++i) + tmp1[i] = 0; + i = 1; + while (i < 64) { + run = 0; + while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30) + run += 0x10; + if (c == 9999) + return gFalse; + if (c == 0x00) { + break; + } else { + run += (c >> 4) & 0x0f; + size = c & 0x0f; + amp = readAmp(size); + if (amp == 9999) + return gFalse; + i += run; + j = dctZigZag[i++]; + tmp1[j] = amp * quantTable[j]; + } + } + + // inverse DCT on rows + for (i = 0; i < 64; i += 8) { + + // stage 4 + v0 = (dctSqrt2 * tmp1[i+0] + 128) >> 8; + v1 = (dctSqrt2 * tmp1[i+4] + 128) >> 8; + v2 = tmp1[i+2]; + v3 = tmp1[i+6]; + v4 = (dctSqrt1d2 * (tmp1[i+1] - tmp1[i+7]) + 128) >> 8; + v7 = (dctSqrt1d2 * (tmp1[i+1] + tmp1[i+7]) + 128) >> 8; + v5 = tmp1[i+3] << 4; + v6 = tmp1[i+5] << 4; + + // stage 3 + t = (v0 - v1+ 1) >> 1; + v0 = (v0 + v1 + 1) >> 1; + v1 = t; + t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8; + v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8; + v3 = t; + t = (v4 - v6 + 1) >> 1; + v4 = (v4 + v6 + 1) >> 1; + v6 = t; + t = (v7 + v5 + 1) >> 1; + v5 = (v7 - v5 + 1) >> 1; + v7 = t; + + // stage 2 + t = (v0 - v3 + 1) >> 1; + v0 = (v0 + v3 + 1) >> 1; + v3 = t; + t = (v1 - v2 + 1) >> 1; + v1 = (v1 + v2 + 1) >> 1; + v2 = t; + t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12; + v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12; + v7 = t; + t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12; + v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12; + v6 = t; + + // stage 1 + tmp1[i+0] = v0 + v7; + tmp1[i+7] = v0 - v7; + tmp1[i+1] = v1 + v6; + tmp1[i+6] = v1 - v6; + tmp1[i+2] = v2 + v5; + tmp1[i+5] = v2 - v5; + tmp1[i+3] = v3 + v4; + tmp1[i+4] = v3 - v4; + } + + // inverse DCT on columns + for (i = 0; i < 8; ++i) { + + // stage 4 + v0 = (dctSqrt2 * tmp1[0*8+i] + 2048) >> 12; + v1 = (dctSqrt2 * tmp1[4*8+i] + 2048) >> 12; + v2 = tmp1[2*8+i]; + v3 = tmp1[6*8+i]; + v4 = (dctSqrt1d2 * (tmp1[1*8+i] - tmp1[7*8+i]) + 2048) >> 12; + v7 = (dctSqrt1d2 * (tmp1[1*8+i] + tmp1[7*8+i]) + 2048) >> 12; + v5 = tmp1[3*8+i]; + v6 = tmp1[5*8+i]; + + // stage 3 + t = (v0 - v1 + 1) >> 1; + v0 = (v0 + v1 + 1) >> 1; + v1 = t; + t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12; + v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12; + v3 = t; + t = (v4 - v6 + 1) >> 1; + v4 = (v4 + v6 + 1) >> 1; + v6 = t; + t = (v7 + v5 + 1) >> 1; + v5 = (v7 - v5 + 1) >> 1; + v7 = t; + + // stage 2 + t = (v0 - v3 + 1) >> 1; + v0 = (v0 + v3 + 1) >> 1; + v3 = t; + t = (v1 - v2 + 1) >> 1; + v1 = (v1 + v2 + 1) >> 1; + v2 = t; + t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12; + v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12; + v7 = t; + t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12; + v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12; + v6 = t; + + // stage 1 + tmp1[0*8+i] = v0 + v7; + tmp1[7*8+i] = v0 - v7; + tmp1[1*8+i] = v1 + v6; + tmp1[6*8+i] = v1 - v6; + tmp1[2*8+i] = v2 + v5; + tmp1[5*8+i] = v2 - v5; + tmp1[3*8+i] = v3 + v4; + tmp1[4*8+i] = v3 - v4; + } + + // convert to 8-bit integers + for (i = 0; i < 64; ++i) + data[i] = dctClip[dctClipOffset + 128 + ((tmp1[i] + 8) >> 4)]; + + return gTrue; +} +#endif + +#ifdef FP_IDCT +GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable, + DCTHuffTable *acHuffTable, + Guchar quantTable[64], int *prevDC, + Guchar data[64]) { + double tmp1[64]; + double v0, v1, v2, v3, v4, v5, v6, v7, t; + int run, size, amp; + int c; + int i, j; + + // Huffman decode and dequantize + size = readHuffSym(dcHuffTable); + if (size == 9999) + return gFalse; + if (size > 0) { + amp = readAmp(size); + if (amp == 9999) + return gFalse; + } else { + amp = 0; + } + tmp1[0] = (*prevDC += amp) * quantTable[0]; + for (i = 1; i < 64; ++i) + tmp1[i] = 0; + i = 1; + while (i < 64) { + run = 0; + while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30) + run += 0x10; + if (c == 9999) + return gFalse; + if (c == 0x00) { + break; + } else { + run += (c >> 4) & 0x0f; + size = c & 0x0f; + amp = readAmp(size); + if (amp == 9999) + return gFalse; + i += run; + j = dctZigZag[i++]; + tmp1[j] = amp * quantTable[j]; + } + } + + // inverse DCT on rows + for (i = 0; i < 64; i += 8) { + + // stage 4 + v0 = dctSqrt2 * tmp1[i+0]; + v1 = dctSqrt2 * tmp1[i+4]; + v2 = tmp1[i+2]; + v3 = tmp1[i+6]; + v4 = dctSqrt1d2 * (tmp1[i+1] - tmp1[i+7]); + v7 = dctSqrt1d2 * (tmp1[i+1] + tmp1[i+7]); + v5 = tmp1[i+3]; + v6 = tmp1[i+5]; + + // stage 3 + t = 0.5 * (v0 - v1); + v0 = 0.5 * (v0 + v1); + v1 = t; + t = v2 * dctSin6 + v3 * dctCos6; + v2 = v2 * dctCos6 - v3 * dctSin6; + v3 = t; + t = 0.5 * (v4 - v6); + v4 = 0.5 * (v4 + v6); + v6 = t; + t = 0.5 * (v7 + v5); + v5 = 0.5 * (v7 - v5); + v7 = t; + + // stage 2 + t = 0.5 * (v0 - v3); + v0 = 0.5 * (v0 + v3); + v3 = t; + t = 0.5 * (v1 - v2); + v1 = 0.5 * (v1 + v2); + v2 = t; + t = v4 * dctSin3 + v7 * dctCos3; + v4 = v4 * dctCos3 - v7 * dctSin3; + v7 = t; + t = v5 * dctSin1 + v6 * dctCos1; + v5 = v5 * dctCos1 - v6 * dctSin1; + v6 = t; + + // stage 1 + tmp1[i+0] = v0 + v7; + tmp1[i+7] = v0 - v7; + tmp1[i+1] = v1 + v6; + tmp1[i+6] = v1 - v6; + tmp1[i+2] = v2 + v5; + tmp1[i+5] = v2 - v5; + tmp1[i+3] = v3 + v4; + tmp1[i+4] = v3 - v4; + } + + // inverse DCT on columns + for (i = 0; i < 8; ++i) { + + // stage 4 + v0 = dctSqrt2 * tmp1[0*8+i]; + v1 = dctSqrt2 * tmp1[4*8+i]; + v2 = tmp1[2*8+i]; + v3 = tmp1[6*8+i]; + v4 = dctSqrt1d2 * (tmp1[1*8+i] - tmp1[7*8+i]); + v7 = dctSqrt1d2 * (tmp1[1*8+i] + tmp1[7*8+i]); + v5 = tmp1[3*8+i]; + v6 = tmp1[5*8+i]; + + // stage 3 + t = 0.5 * (v0 - v1); + v0 = 0.5 * (v0 + v1); + v1 = t; + t = v2 * dctSin6 + v3 * dctCos6; + v2 = v2 * dctCos6 - v3 * dctSin6; + v3 = t; + t = 0.5 * (v4 - v6); + v4 = 0.5 * (v4 + v6); + v6 = t; + t = 0.5 * (v7 + v5); + v5 = 0.5 * (v7 - v5); + v7 = t; + + // stage 2 + t = 0.5 * (v0 - v3); + v0 = 0.5 * (v0 + v3); + v3 = t; + t = 0.5 * (v1 - v2); + v1 = 0.5 * (v1 + v2); + v2 = t; + t = v4 * dctSin3 + v7 * dctCos3; + v4 = v4 * dctCos3 - v7 * dctSin3; + v7 = t; + t = v5 * dctSin1 + v6 * dctCos1; + v5 = v5 * dctCos1 - v6 * dctSin1; + v6 = t; + + // stage 1 + tmp1[0*8+i] = v0 + v7; + tmp1[7*8+i] = v0 - v7; + tmp1[1*8+i] = v1 + v6; + tmp1[6*8+i] = v1 - v6; + tmp1[2*8+i] = v2 + v5; + tmp1[5*8+i] = v2 - v5; + tmp1[3*8+i] = v3 + v4; + tmp1[4*8+i] = v3 - v4; + } + + // convert to 8-bit integers + for (i = 0; i < 64; ++i) + data[i] = dctClip[dctClipOffset + (int)(tmp1[i] + 128.5)]; + + return gTrue; +} +#endif + +int DCTStream::readHuffSym(DCTHuffTable *table) { + Gushort code; + int bit; + int codeBits; + + code = 0; + codeBits = 0; + do { + // add a bit to the code + if ((bit = readBit()) == EOF) + return 9999; + code = (code << 1) + bit; + ++codeBits; + + // look up code + if (code - table->firstCode[codeBits] < table->numCodes[codeBits]) { + code -= table->firstCode[codeBits]; + return table->sym[table->firstSym[codeBits] + code]; + } + } while (codeBits < 16); + + error(getPos(), "Bad Huffman code in DCT stream"); + return 9999; +} + +int DCTStream::readAmp(int size) { + int amp, bit; + int bits; + + amp = 0; + for (bits = 0; bits < size; ++bits) { + if ((bit = readBit()) == EOF) + return 9999; + amp = (amp << 1) + bit; + } + if (amp < (1 << (size - 1))) + amp -= (1 << size) - 1; + return amp; +} + +int DCTStream::readBit() { + int bit; + int c, c2; + + if (inputBits == 0) { + if ((c = str->getChar()) == EOF) + return EOF; + if (c == 0xff) { + do { + c2 = str->getChar(); + } while (c2 == 0xff); + if (c2 != 0x00) { + error(getPos(), "Bad DCT data: missing 00 after ff"); + return EOF; + } + } + inputBuf = c; + inputBits = 8; + } + bit = (inputBuf >> (inputBits - 1)) & 1; + --inputBits; + return bit; +} + +GBool DCTStream::readHeader() { + GBool doScan; + int minHSample, minVSample; + int bufWidth; + int n; + int c = 0; + int i, j; + + width = height = 0; + numComps = 0; + numQuantTables = 0; + numDCHuffTables = 0; + numACHuffTables = 0; + colorXform = 0; + gotAdobeMarker = gFalse; + restartInterval = 0; + + // read headers + doScan = gFalse; + while (!doScan) { + c = readMarker(); + switch (c) { + case 0xc0: // SOF0 + if (!readFrameInfo()) + return gFalse; + break; + case 0xc4: // DHT + if (!readHuffmanTables()) + return gFalse; + break; + case 0xd8: // SOI + break; + case 0xda: // SOS + if (!readScanInfo()) + return gFalse; + doScan = gTrue; + break; + case 0xdb: // DQT + if (!readQuantTables()) + return gFalse; + break; + case 0xdd: // DRI + if (!readRestartInterval()) + return gFalse; + break; + case 0xee: // APP14 + if (!readAdobeMarker()) + return gFalse; + break; + case EOF: + error(getPos(), "Bad DCT header"); + return gFalse; + default: + // skip APPn / COM / etc. + if (c >= 0xe0) { + n = read16() - 2; + for (i = 0; i < n; ++i) + str->getChar(); + } else { + error(getPos(), "Unknown DCT marker <%02x>", c); + return gFalse; + } + break; + } + } + + // compute MCU size + mcuWidth = minHSample = compInfo[0].hSample; + mcuHeight = minVSample = compInfo[0].vSample; + for (i = 1; i < numComps; ++i) { + if (compInfo[i].hSample < minHSample) + minHSample = compInfo[i].hSample; + if (compInfo[i].vSample < minVSample) + minVSample = compInfo[i].vSample; + if (compInfo[i].hSample > mcuWidth) + mcuWidth = compInfo[i].hSample; + if (compInfo[i].vSample > mcuHeight) + mcuHeight = compInfo[i].vSample; + } + for (i = 0; i < numComps; ++i) { + compInfo[i].hSample /= minHSample; + compInfo[i].vSample /= minVSample; + } + mcuWidth = (mcuWidth / minHSample) * 8; + mcuHeight = (mcuHeight / minVSample) * 8; + + // allocate buffers + bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth; + for (i = 0; i < numComps; ++i) + for (j = 0; j < mcuHeight; ++j) + rowBuf[i][j] = (Guchar *)gmalloc(bufWidth * sizeof(Guchar)); + + // figure out color transform + if (!gotAdobeMarker && numComps == 3) { + if (compInfo[0].id == 1 && compInfo[1].id == 2 && compInfo[2].id == 3) { + colorXform = 1; + } + } + + // initialize counters + comp = 0; + x = 0; + y = 0; + dy = mcuHeight; + + return gTrue; +} + +GBool DCTStream::readFrameInfo() { + int length; + int prec; + int i; + int c; + + length = read16() - 2; + prec = str->getChar(); + height = read16(); + width = read16(); + numComps = str->getChar(); + length -= 6; + if (prec != 8) { + error(getPos(), "Bad DCT precision %d", prec); + return gFalse; + } + for (i = 0; i < numComps; ++i) { + compInfo[i].id = str->getChar(); + compInfo[i].inScan = gFalse; + c = str->getChar(); + compInfo[i].hSample = (c >> 4) & 0x0f; + compInfo[i].vSample = c & 0x0f; + compInfo[i].quantTable = str->getChar(); + compInfo[i].dcHuffTable = 0; + compInfo[i].acHuffTable = 0; + } + return gTrue; +} + +GBool DCTStream::readScanInfo() { + int length; + int scanComps, id, c; + int i, j; + + length = read16() - 2; + scanComps = str->getChar(); + --length; + if (length != 2 * scanComps + 3) { + error(getPos(), "Bad DCT scan info block"); + return gFalse; + } + for (i = 0; i < scanComps; ++i) { + id = str->getChar(); + for (j = 0; j < numComps; ++j) { + if (id == compInfo[j].id) + break; + } + if (j == numComps) { + error(getPos(), "Bad DCT component ID in scan info block"); + return gFalse; + } + compInfo[j].inScan = gTrue; + c = str->getChar(); + compInfo[j].dcHuffTable = (c >> 4) & 0x0f; + compInfo[j].acHuffTable = c & 0x0f; + } + str->getChar(); + str->getChar(); + str->getChar(); + return gTrue; +} + +GBool DCTStream::readQuantTables() { + int length; + int i; + int index; + + length = read16() - 2; + while (length > 0) { + index = str->getChar(); + if ((index & 0xf0) || index >= 4) { + error(getPos(), "Bad DCT quantization table"); + return gFalse; + } + if (index == numQuantTables) + numQuantTables = index + 1; + for (i = 0; i < 64; ++i) + quantTables[index][dctZigZag[i]] = str->getChar(); + length -= 65; + } + return gTrue; +} + +GBool DCTStream::readHuffmanTables() { + DCTHuffTable *tbl; + int length; + int index; + Gushort code; + Guchar sym; + int i; + int c; + + length = read16() - 2; + while (length > 0) { + index = str->getChar(); + --length; + if ((index & 0x0f) >= 4) { + error(getPos(), "Bad DCT Huffman table"); + return gFalse; + } + if (index & 0x10) { + index &= 0x0f; + if (index >= numACHuffTables) + numACHuffTables = index+1; + tbl = &acHuffTables[index]; + } else { + if (index >= numDCHuffTables) + numDCHuffTables = index+1; + tbl = &dcHuffTables[index]; + } + sym = 0; + code = 0; + for (i = 1; i <= 16; ++i) { + c = str->getChar(); + tbl->firstSym[i] = sym; + tbl->firstCode[i] = code; + tbl->numCodes[i] = c; + sym += c; + code = (code + c) << 1; + } + length -= 16; + for (i = 0; i < sym; ++i) + tbl->sym[i] = str->getChar(); + length -= sym; + } + return gTrue; +} + +GBool DCTStream::readRestartInterval() { + int length; + + length = read16(); + if (length != 4) { + error(getPos(), "Bad DCT restart interval"); + return gFalse; + } + restartInterval = read16(); + return gTrue; +} + +GBool DCTStream::readAdobeMarker() { + int length, i; + char buf[12]; + int c; + + length = read16(); + if (length != 14) + goto err; + for (i = 0; i < 12; ++i) { + if ((c = str->getChar()) == EOF) + goto err; + buf[i] = c; + } + if (strncmp(buf, "Adobe", 5)) + goto err; + colorXform = buf[11]; + gotAdobeMarker = gTrue; + return gTrue; + + err: + error(getPos(), "Bad DCT Adobe APP14 marker"); + return gFalse; +} + +GBool DCTStream::readTrailer() { + int c; + + c = readMarker(); + if (c != 0xd9) { // EOI + error(getPos(), "Bad DCT trailer"); + return gFalse; + } + return gTrue; +} + +int DCTStream::readMarker() { + int c; + + do { + do { + c = str->getChar(); + } while (c != 0xff); + do { + c = str->getChar(); + } while (c == 0xff); + } while (c == 0x00); + return c; +} + +int DCTStream::read16() { + int c1, c2; + + if ((c1 = str->getChar()) == EOF) + return EOF; + if ((c2 = str->getChar()) == EOF) + return EOF; + return (c1 << 8) + c2; +} + +GString *DCTStream::getPSFilter(char *indent) { + GString *s; + + s = str->getPSFilter(indent); + s->append(indent)->append("<< >> /DCTDecode filter\n"); + return s; +} + +GBool DCTStream::isBinary(GBool last) { + return str->isBinary(gTrue); +} + +//------------------------------------------------------------------------ +// FlateStream +//------------------------------------------------------------------------ + +int FlateStream::codeLenCodeMap[flateMaxCodeLenCodes] = { + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 +}; + +FlateDecode FlateStream::lengthDecode[flateMaxLitCodes-257] = { + {0, 3}, + {0, 4}, + {0, 5}, + {0, 6}, + {0, 7}, + {0, 8}, + {0, 9}, + {0, 10}, + {1, 11}, + {1, 13}, + {1, 15}, + {1, 17}, + {2, 19}, + {2, 23}, + {2, 27}, + {2, 31}, + {3, 35}, + {3, 43}, + {3, 51}, + {3, 59}, + {4, 67}, + {4, 83}, + {4, 99}, + {4, 115}, + {5, 131}, + {5, 163}, + {5, 195}, + {5, 227}, + {0, 258} +}; + +FlateDecode FlateStream::distDecode[flateMaxDistCodes] = { + { 0, 1}, + { 0, 2}, + { 0, 3}, + { 0, 4}, + { 1, 5}, + { 1, 7}, + { 2, 9}, + { 2, 13}, + { 3, 17}, + { 3, 25}, + { 4, 33}, + { 4, 49}, + { 5, 65}, + { 5, 97}, + { 6, 129}, + { 6, 193}, + { 7, 257}, + { 7, 385}, + { 8, 513}, + { 8, 769}, + { 9, 1025}, + { 9, 1537}, + {10, 2049}, + {10, 3073}, + {11, 4097}, + {11, 6145}, + {12, 8193}, + {12, 12289}, + {13, 16385}, + {13, 24577} +}; + +FlateStream::FlateStream(Stream *str, int predictor1, int columns1, + int colors1, int bits1): + FilterStream(str) { + if (predictor1 != 1) { + pred = new StreamPredictor(this, predictor1, columns1, colors1, bits1); + } else { + pred = NULL; + } +} + +FlateStream::~FlateStream() { + if (pred) { + delete pred; + } + delete str; +} + +void FlateStream::reset() { + int cmf, flg; + + str->reset(); + + // read header + //~ need to look at window size? + endOfBlock = eof = gTrue; + cmf = str->getChar(); + flg = str->getChar(); + if (cmf == EOF || flg == EOF) + return; + if ((cmf & 0x0f) != 0x08) { + error(getPos(), "Unknown compression method in flate stream"); + return; + } + if ((((cmf << 8) + flg) % 31) != 0) { + error(getPos(), "Bad FCHECK in flate stream"); + return; + } + if (flg & 0x20) { + error(getPos(), "FDICT bit set in flate stream"); + return; + } + + // initialize + index = 0; + remain = 0; + codeBuf = 0; + codeSize = 0; + compressedBlock = gFalse; + endOfBlock = gTrue; + eof = gFalse; +} + +int FlateStream::getChar() { + int c; + + if (pred) { + return pred->getChar(); + } + while (remain == 0) { + if (endOfBlock && eof) + return EOF; + readSome(); + } + c = buf[index]; + index = (index + 1) & flateMask; + --remain; + return c; +} + +int FlateStream::lookChar() { + int c; + + if (pred) { + return pred->lookChar(); + } + while (remain == 0) { + if (endOfBlock && eof) + return EOF; + readSome(); + } + c = buf[index]; + return c; +} + +int FlateStream::getRawChar() { + int c; + + while (remain == 0) { + if (endOfBlock && eof) + return EOF; + readSome(); + } + c = buf[index]; + index = (index + 1) & flateMask; + --remain; + return c; +} + +GString *FlateStream::getPSFilter(char *indent) { + return NULL; +} + +GBool FlateStream::isBinary(GBool last) { + return str->isBinary(gTrue); +} + +void FlateStream::readSome() { + int code1, code2; + int len, dist; + int i, j, k; + int c; + + if (endOfBlock) { + if (!startBlock()) + return; + } + + if (compressedBlock) { + if ((code1 = getHuffmanCodeWord(&litCodeTab)) == EOF) + goto err; + if (code1 < 256) { + buf[index] = code1; + remain = 1; + } else if (code1 == 256) { + endOfBlock = gTrue; + remain = 0; + } else { + code1 -= 257; + code2 = lengthDecode[code1].bits; + if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF) + goto err; + len = lengthDecode[code1].first + code2; + if ((code1 = getHuffmanCodeWord(&distCodeTab)) == EOF) + goto err; + code2 = distDecode[code1].bits; + if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF) + goto err; + dist = distDecode[code1].first + code2; + i = index; + j = (index - dist) & flateMask; + for (k = 0; k < len; ++k) { + buf[i] = buf[j]; + i = (i + 1) & flateMask; + j = (j + 1) & flateMask; + } + remain = len; + } + + } else { + len = (blockLen < flateWindow) ? blockLen : flateWindow; + for (i = 0, j = index; i < len; ++i, j = (j + 1) & flateMask) { + if ((c = str->getChar()) == EOF) { + endOfBlock = eof = gTrue; + break; + } + buf[j] = c & 0xff; + } + remain = i; + blockLen -= len; + if (blockLen == 0) + endOfBlock = gTrue; + } + + return; + +err: + error(getPos(), "Unexpected end of file in flate stream"); + endOfBlock = eof = gTrue; + remain = 0; +} + +GBool FlateStream::startBlock() { + int blockHdr; + int c; + int check; + + // read block header + blockHdr = getCodeWord(3); + if (blockHdr & 1) + eof = gTrue; + blockHdr >>= 1; + + // uncompressed block + if (blockHdr == 0) { + compressedBlock = gFalse; + if ((c = str->getChar()) == EOF) + goto err; + blockLen = c & 0xff; + if ((c = str->getChar()) == EOF) + goto err; + blockLen |= (c & 0xff) << 8; + if ((c = str->getChar()) == EOF) + goto err; + check = c & 0xff; + if ((c = str->getChar()) == EOF) + goto err; + check |= (c & 0xff) << 8; + if (check != (~blockLen & 0xffff)) + error(getPos(), "Bad uncompressed block length in flate stream"); + codeBuf = 0; + codeSize = 0; + + // compressed block with fixed codes + } else if (blockHdr == 1) { + compressedBlock = gTrue; + loadFixedCodes(); + + // compressed block with dynamic codes + } else if (blockHdr == 2) { + compressedBlock = gTrue; + if (!readDynamicCodes()) + goto err; + + // unknown block type + } else { + goto err; + } + + endOfBlock = gFalse; + return gTrue; + +err: + error(getPos(), "Bad block header in flate stream"); + endOfBlock = eof = gTrue; + return gFalse; +} + +void FlateStream::loadFixedCodes() { + int i; + + // set up code arrays + litCodeTab.codes = allCodes; + distCodeTab.codes = allCodes + flateMaxLitCodes; + + // initialize literal code table + for (i = 0; i <= 143; ++i) + litCodeTab.codes[i].len = 8; + for (i = 144; i <= 255; ++i) + litCodeTab.codes[i].len = 9; + for (i = 256; i <= 279; ++i) + litCodeTab.codes[i].len = 7; + for (i = 280; i <= 287; ++i) + litCodeTab.codes[i].len = 8; + compHuffmanCodes(&litCodeTab, flateMaxLitCodes); + + // initialize distance code table + for (i = 0; i <= 5; ++i) { + distCodeTab.start[i] = 0; + } + for (i = 6; i <= flateMaxHuffman+1; ++i) { + distCodeTab.start[i] = flateMaxDistCodes; + } + for (i = 0; i < flateMaxDistCodes; ++i) { + distCodeTab.codes[i].len = 5; + distCodeTab.codes[i].code = i; + distCodeTab.codes[i].val = i; + } +} + +GBool FlateStream::readDynamicCodes() { + int numCodeLenCodes; + int numLitCodes; + int numDistCodes; + FlateCode codeLenCodes[flateMaxCodeLenCodes]; + FlateHuffmanTab codeLenCodeTab; + int len, repeat, code; + int i; + + // read lengths + if ((numLitCodes = getCodeWord(5)) == EOF) + goto err; + numLitCodes += 257; + if ((numDistCodes = getCodeWord(5)) == EOF) + goto err; + numDistCodes += 1; + if ((numCodeLenCodes = getCodeWord(4)) == EOF) + goto err; + numCodeLenCodes += 4; + if (numLitCodes > flateMaxLitCodes || + numDistCodes > flateMaxDistCodes || + numCodeLenCodes > flateMaxCodeLenCodes) + goto err; + + // read code length code table + codeLenCodeTab.codes = codeLenCodes; + for (i = 0; i < flateMaxCodeLenCodes; ++i) + codeLenCodes[i].len = 0; + for (i = 0; i < numCodeLenCodes; ++i) { + if ((codeLenCodes[codeLenCodeMap[i]].len = getCodeWord(3)) == -1) + goto err; + } + compHuffmanCodes(&codeLenCodeTab, flateMaxCodeLenCodes); + + // set up code arrays + litCodeTab.codes = allCodes; + distCodeTab.codes = allCodes + numLitCodes; + + // read literal and distance code tables + len = 0; + repeat = 0; + i = 0; + while (i < numLitCodes + numDistCodes) { + if ((code = getHuffmanCodeWord(&codeLenCodeTab)) == EOF) + goto err; + if (code == 16) { + if ((repeat = getCodeWord(2)) == EOF) + goto err; + for (repeat += 3; repeat > 0; --repeat) + allCodes[i++].len = len; + } else if (code == 17) { + if ((repeat = getCodeWord(3)) == EOF) + goto err; + len = 0; + for (repeat += 3; repeat > 0; --repeat) + allCodes[i++].len = 0; + } else if (code == 18) { + if ((repeat = getCodeWord(7)) == EOF) + goto err; + len = 0; + for (repeat += 11; repeat > 0; --repeat) + allCodes[i++].len = 0; + } else { + allCodes[i++].len = len = code; + } + } + compHuffmanCodes(&litCodeTab, numLitCodes); + compHuffmanCodes(&distCodeTab, numDistCodes); + + return gTrue; + +err: + error(getPos(), "Bad dynamic code table in flate stream"); + return gFalse; +} + +// On entry, the codes> array contains the lengths of each code, +// stored in code value order. This function computes the code words. +// The result is sorted in order of (1) code length and (2) code word. +// The length values are no longer valid. The start> array is +// filled with the indexes of the first code of each length. +void FlateStream::compHuffmanCodes(FlateHuffmanTab *tab, int n) { + int numLengths[flateMaxHuffman+1]; + int nextCode[flateMaxHuffman+1]; + int nextIndex[flateMaxHuffman+2]; + int code; + int i, j; + + // count number of codes for each code length + for (i = 0; i <= flateMaxHuffman; ++i) + numLengths[i] = 0; + for (i = 0; i < n; ++i) + ++numLengths[tab->codes[i].len]; + + // compute first index for each length + tab->start[0] = nextIndex[0] = 0; + for (i = 1; i <= flateMaxHuffman + 1; ++i) + tab->start[i] = nextIndex[i] = tab->start[i-1] + numLengths[i-1]; + + // compute first code for each length + code = 0; + numLengths[0] = 0; + for (i = 1; i <= flateMaxHuffman; ++i) { + code = (code + numLengths[i-1]) << 1; + nextCode[i] = code; + } + + // compute the codes -- this permutes the codes array from value + // order to length/code order + for (i = 0; i < n; ++i) { + j = nextIndex[tab->codes[i].len]++; + if (tab->codes[i].len == 0) + tab->codes[j].code = 0; + else + tab->codes[j].code = nextCode[tab->codes[i].len]++; + tab->codes[j].val = i; + } +} + +int FlateStream::getHuffmanCodeWord(FlateHuffmanTab *tab) { + int len; + int code; + int c; + int i, j; + + code = 0; + for (len = 1; len <= flateMaxHuffman; ++len) { + + // add a bit to the code + if (codeSize == 0) { + if ((c = str->getChar()) == EOF) + return EOF; + codeBuf = c & 0xff; + codeSize = 8; + } + code = (code << 1) | (codeBuf & 1); + codeBuf >>= 1; + --codeSize; + + // look for code + i = tab->start[len]; + j = tab->start[len + 1]; + if (i < j && code >= tab->codes[i].code && code <= tab->codes[j-1].code) { + i += code - tab->codes[i].code; + return tab->codes[i].val; + } + } + + // not found + error(getPos(), "Bad code (%04x) in flate stream", code); + return EOF; +} + +int FlateStream::getCodeWord(int bits) { + int c; + + while (codeSize < bits) { + if ((c = str->getChar()) == EOF) + return EOF; + codeBuf |= (c & 0xff) << codeSize; + codeSize += 8; + } + c = codeBuf & ((1 << bits) - 1); + codeBuf >>= bits; + codeSize -= bits; + return c; +} + +//------------------------------------------------------------------------ +// EOFStream +//------------------------------------------------------------------------ + +EOFStream::EOFStream(Stream *str): + FilterStream(str) { +} + +EOFStream::~EOFStream() { + delete str; +} + +//------------------------------------------------------------------------ +// FixedLengthEncoder +//------------------------------------------------------------------------ + +FixedLengthEncoder::FixedLengthEncoder(Stream *str, int length1): + FilterStream(str) { + length = length1; + count = 0; +} + +FixedLengthEncoder::~FixedLengthEncoder() { + if (str->isEncoder()) + delete str; +} + +void FixedLengthEncoder::reset() { + str->reset(); + count = 0; +} + +int FixedLengthEncoder::getChar() { + if (length >= 0 && count >= length) + return EOF; + ++count; + return str->getChar(); +} + +int FixedLengthEncoder::lookChar() { + if (length >= 0 && count >= length) + return EOF; + return str->getChar(); +} + +//------------------------------------------------------------------------ +// ASCII85Encoder +//------------------------------------------------------------------------ + +ASCII85Encoder::ASCII85Encoder(Stream *str): + FilterStream(str) { + bufPtr = bufEnd = buf; + lineLen = 0; + eof = gFalse; +} + +ASCII85Encoder::~ASCII85Encoder() { + if (str->isEncoder()) + delete str; +} + +void ASCII85Encoder::reset() { + str->reset(); + bufPtr = bufEnd = buf; + lineLen = 0; + eof = gFalse; +} + +GBool ASCII85Encoder::fillBuf() { + Gulong t; + char buf1[5]; + int c; + int n, i; + + if (eof) + return gFalse; + t = 0; + for (n = 0; n < 4; ++n) { + if ((c = str->getChar()) == EOF) + break; + t = (t << 8) + c; + } + bufPtr = bufEnd = buf; + if (n > 0) { + if (n == 4 && t == 0) { + *bufEnd++ = 'z'; + if (++lineLen == 65) { + *bufEnd++ = '\n'; + lineLen = 0; + } + } else { + if (n < 4) + t <<= 8 * (4 - n); + for (i = 4; i >= 0; --i) { + buf1[i] = (char)(t % 85 + 0x21); + t /= 85; + } + for (i = 0; i <= n; ++i) { + *bufEnd++ = buf1[i]; + if (++lineLen == 65) { + *bufEnd++ = '\n'; + lineLen = 0; + } + } + } + } + if (n < 4) { + *bufEnd++ = '~'; + *bufEnd++ = '>'; + eof = gTrue; + } + return bufPtr < bufEnd; +} + +//------------------------------------------------------------------------ +// RunLengthEncoder +//------------------------------------------------------------------------ + +RunLengthEncoder::RunLengthEncoder(Stream *str): + FilterStream(str) { + bufPtr = bufEnd = nextEnd = buf; + eof = gFalse; +} + +RunLengthEncoder::~RunLengthEncoder() { + if (str->isEncoder()) + delete str; +} + +void RunLengthEncoder::reset() { + str->reset(); + bufPtr = bufEnd = nextEnd = buf; + eof = gFalse; +} + +// +// When fillBuf finishes, buf[] looks like this: +// +-----+--------------+-----------------+-- +// + tag | ... data ... | next 0, 1, or 2 | +// +-----+--------------+-----------------+-- +// ^ ^ ^ +// bufPtr bufEnd nextEnd +// +GBool RunLengthEncoder::fillBuf() { + int c, c1, c2; + int n; + + // already hit EOF? + if (eof) + return gFalse; + + // grab two bytes + if (nextEnd < bufEnd + 1) { + if ((c1 = str->getChar()) == EOF) { + eof = gTrue; + return gFalse; + } + } else { + c1 = bufEnd[0] & 0xff; + } + if (nextEnd < bufEnd + 2) { + if ((c2 = str->getChar()) == EOF) { + eof = gTrue; + buf[0] = 0; + buf[1] = c1; + bufPtr = buf; + bufEnd = &buf[2]; + return gTrue; + } + } else { + c2 = bufEnd[1] & 0xff; + } + + // check for repeat + c = 0; // make gcc happy + if (c1 == c2) { + n = 2; + c = 0; // suppress bogus compiler warning + while (n < 128 && (c = str->getChar()) == c1) + ++n; + buf[0] = (char)(257 - n); + buf[1] = c1; + bufEnd = &buf[2]; + if (c == EOF) { + eof = gTrue; + } else if (n < 128) { + buf[2] = c; + nextEnd = &buf[3]; + } else { + nextEnd = bufEnd; + } + + // get up to 128 chars + } else { + buf[1] = c1; + buf[2] = c2; + n = 2; + while (n < 128) { + if ((c = str->getChar()) == EOF) { + eof = gTrue; + break; + } + ++n; + buf[n] = c; + if (buf[n] == buf[n-1]) + break; + } + if (buf[n] == buf[n-1]) { + buf[0] = (char)(n-2-1); + bufEnd = &buf[n-1]; + nextEnd = &buf[n+1]; + } else { + buf[0] = (char)(n-1); + bufEnd = nextEnd = &buf[n+1]; + } + } + bufPtr = buf; + return gTrue; +} diff --git a/pdftops/Stream.h b/pdftops/Stream.h new file mode 100644 index 0000000000..6413b5bd8a --- /dev/null +++ b/pdftops/Stream.h @@ -0,0 +1,713 @@ +//======================================================================== +// +// Stream.h +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#ifndef STREAM_H +#define STREAM_H + +#ifdef __GNUC__ +#pragma interface +#endif + +#include +#include "gtypes.h" +#include "Object.h" + +#ifndef NO_DECRYPTION +class Decrypt; +#endif +class BaseStream; + +//------------------------------------------------------------------------ + +enum StreamKind { + strFile, + strASCIIHex, + strASCII85, + strLZW, + strRunLength, + strCCITTFax, + strDCT, + strFlate, + strWeird // internal-use stream types +}; + +//------------------------------------------------------------------------ +// Stream (base class) +//------------------------------------------------------------------------ + +class Stream { +public: + + // Constructor. + Stream(); + + // Destructor. + virtual ~Stream(); + + // Reference counting. + int incRef() { return ++ref; } + int decRef() { return --ref; } + + // Get kind of stream. + virtual StreamKind getKind() = 0; + + // Reset stream to beginning. + virtual void reset() = 0; + + // Get next char from stream. + virtual int getChar() = 0; + + // Peek at next char in stream. + virtual int lookChar() = 0; + + // Get next char from stream without using the predictor. + // This is only used by StreamPredictor. + virtual int getRawChar(); + + // Get next line from stream. + virtual char *getLine(char *buf, int size); + + // Get current position in file. + virtual int getPos() = 0; + + // Go to a position in the stream. + virtual void setPos(int pos1) = 0; + + // Get PostScript command for the filter(s). + virtual GString *getPSFilter(char *indent); + + // Does this stream type potentially contain non-printable chars? + virtual GBool isBinary(GBool last = gTrue) = 0; + + // Get the BaseStream or EmbedStream of this stream. + virtual BaseStream *getBaseStream() = 0; + + // Get the dictionary associated with this stream. + virtual Dict *getDict() = 0; + + // Is this an encoding filter? + virtual GBool isEncoder() { return gFalse; } + + // Add filters to this stream according to the parameters in . + // Returns the new stream. + Stream *addFilters(Object *dict); + +private: + + Stream *makeFilter(char *name, Stream *str, Object *params); + + int ref; // reference count +}; + +//------------------------------------------------------------------------ +// BaseStream +// +// This is the base class for all streams that read directly from a file. +//------------------------------------------------------------------------ + +class BaseStream: public Stream { +public: + + BaseStream(Object *dict); + virtual ~BaseStream(); + virtual Stream *makeSubStream(int start, int length, Object *dict) = 0; + virtual void setPos(int pos1) = 0; + virtual BaseStream *getBaseStream() { return this; } + virtual Dict *getDict() { return dict.getDict(); } + + // Get/set position of first byte of stream within the file. + virtual int getStart() = 0; + virtual void moveStart(int delta) = 0; + +#ifndef NO_DECRYPTION + // Set decryption for this stream. + void doDecryption(Guchar *fileKey, int objNum, int objGen); +#endif + +#ifndef NO_DECRYPTION +protected: + + Decrypt *decrypt; +#endif + +private: + + Object dict; +}; + +//------------------------------------------------------------------------ +// FilterStream +// +// This is the base class for all streams that filter another stream. +//------------------------------------------------------------------------ + +class FilterStream: public Stream { +public: + + FilterStream(Stream *str); + virtual ~FilterStream(); + virtual int getPos() { return str->getPos(); } + virtual void setPos(int pos); + virtual BaseStream *getBaseStream() { return str->getBaseStream(); } + virtual Dict *getDict() { return str->getDict(); } + +protected: + + Stream *str; +}; + +//------------------------------------------------------------------------ +// ImageStream +//------------------------------------------------------------------------ + +class ImageStream { +public: + + // Create an image stream object for an image with the specified + // parameters. Note that these are the actual image parameters, + // which may be different from the predictor parameters. + ImageStream(Stream *str, int width, int nComps, int nBits); + + ~ImageStream(); + + // Reset the stream. + void reset(); + + // Gets the next pixel from the stream. should be able to hold + // at least nComps elements. Returns false at end of file. + GBool getPixel(Guchar *pix); + + // Skip an entire line from the image. + void skipLine(); + +private: + + Stream *str; // base stream + int width; // pixels per line + int nComps; // components per pixel + int nBits; // bits per component + int nVals; // components per line + Guchar *imgLine; // line buffer + int imgIdx; // current index in imgLine +}; + +//------------------------------------------------------------------------ +// StreamPredictor +//------------------------------------------------------------------------ + +class StreamPredictor { +public: + + // Create a predictor object. Note that the parameters are for the + // predictor, and may not match the actual image parameters. + StreamPredictor(Stream *str, int predictor, + int width, int nComps, int nBits); + + ~StreamPredictor(); + + int lookChar(); + int getChar(); + +private: + + GBool getNextLine(); + + Stream *str; // base stream + int predictor; // predictor + int width; // pixels per line + int nComps; // components per pixel + int nBits; // bits per component + int nVals; // components per line + int pixBytes; // bytes per pixel + int rowBytes; // bytes per line + Guchar *predLine; // line buffer + int predIdx; // current index in predLine +}; + +//------------------------------------------------------------------------ +// FileStream +//------------------------------------------------------------------------ + +class FileStream: public BaseStream { +public: + + FileStream(FILE *f, int start, int length, Object *dict); + virtual ~FileStream(); + virtual Stream *makeSubStream(int start, int length, Object *dict); + virtual StreamKind getKind() { return strFile; } + virtual void reset(); + virtual int getChar() + { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); } + virtual int lookChar() + { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); } + virtual int getPos() { return bufPos + (bufPtr - buf); } + virtual void setPos(int pos1); + virtual GBool isBinary(GBool last = gTrue) { return last; } + virtual int getStart() { return start; } + virtual void moveStart(int delta); + +private: + + GBool fillBuf(); + + FILE *f; + int start; + int length; + char buf[256]; + char *bufPtr; + char *bufEnd; + int bufPos; + int savePos; +}; + +//------------------------------------------------------------------------ +// EmbedStream +// +// This is a special stream type used for embedded streams (inline +// images). It reads directly from the base stream -- after the +// EmbedStream is deleted, reads from the base stream will proceed where +// the BaseStream left off. Note that this is very different behavior +// that creating a new FileStream (using makeSubStream). +//------------------------------------------------------------------------ + +class EmbedStream: public BaseStream { +public: + + EmbedStream(Stream *str, Object *dict); + virtual ~EmbedStream(); + virtual Stream *makeSubStream(int start, int length, Object *dict); + virtual StreamKind getKind() { return str->getKind(); } + virtual void reset() {} + virtual int getChar() { return str->getChar(); } + virtual int lookChar() { return str->lookChar(); } + virtual int getPos() { return str->getPos(); } + virtual void setPos(int pos); + virtual GBool isBinary(GBool last = gTrue) { return last; } + virtual int getStart(); + virtual void moveStart(int delta); + +private: + + Stream *str; +}; + +//------------------------------------------------------------------------ +// ASCIIHexStream +//------------------------------------------------------------------------ + +class ASCIIHexStream: public FilterStream { +public: + + ASCIIHexStream(Stream *str); + virtual ~ASCIIHexStream(); + virtual StreamKind getKind() { return strASCIIHex; } + virtual void reset(); + virtual int getChar() + { int c = lookChar(); buf = EOF; return c; } + virtual int lookChar(); + virtual GString *getPSFilter(char *indent); + virtual GBool isBinary(GBool last = gTrue); + +private: + + int buf; + GBool eof; +}; + +//------------------------------------------------------------------------ +// ASCII85Stream +//------------------------------------------------------------------------ + +class ASCII85Stream: public FilterStream { +public: + + ASCII85Stream(Stream *str); + virtual ~ASCII85Stream(); + virtual StreamKind getKind() { return strASCII85; } + virtual void reset(); + virtual int getChar() + { int ch = lookChar(); ++index; return ch; } + virtual int lookChar(); + virtual GString *getPSFilter(char *indent); + virtual GBool isBinary(GBool last = gTrue); + +private: + + int c[5]; + int b[4]; + int index, n; + GBool eof; +}; + +//------------------------------------------------------------------------ +// LZWStream +//------------------------------------------------------------------------ + +class LZWStream: public FilterStream { +public: + + LZWStream(Stream *str, int predictor1, int columns1, int colors1, + int bits1, int early1); + virtual ~LZWStream(); + virtual StreamKind getKind() { return strLZW; } + virtual void reset(); + virtual int getChar(); + virtual int lookChar(); + virtual int getRawChar(); + virtual GString *getPSFilter(char *indent); + virtual GBool isBinary(GBool last = gTrue); + +private: + + StreamPredictor *pred; // predictor + int early; // early parameter + FILE *zPipe; // uncompress pipe + GString *zName; // .Z file name + int inputBuf; // input buffer + int inputBits; // number of bits in input buffer + int inCodeBits; // size of input code + char buf[256]; // buffer + char *bufPtr; // next char to read + char *bufEnd; // end of buffer + + void dumpFile(FILE *f); + int getCode(); + GBool fillBuf(); +}; + +//------------------------------------------------------------------------ +// RunLengthStream +//------------------------------------------------------------------------ + +class RunLengthStream: public FilterStream { +public: + + RunLengthStream(Stream *str); + virtual ~RunLengthStream(); + virtual StreamKind getKind() { return strRunLength; } + virtual void reset(); + virtual int getChar() + { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); } + virtual int lookChar() + { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); } + virtual GString *getPSFilter(char *indent); + virtual GBool isBinary(GBool last = gTrue); + +private: + + char buf[128]; // buffer + char *bufPtr; // next char to read + char *bufEnd; // end of buffer + GBool eof; + + GBool fillBuf(); +}; + +//------------------------------------------------------------------------ +// CCITTFaxStream +//------------------------------------------------------------------------ + +struct CCITTCodeTable; + +class CCITTFaxStream: public FilterStream { +public: + + CCITTFaxStream(Stream *str, int encoding, GBool endOfLine, + GBool byteAlign, int columns, int rows, + GBool endOfBlock, GBool black); + virtual ~CCITTFaxStream(); + virtual StreamKind getKind() { return strCCITTFax; } + virtual void reset(); + virtual int getChar() + { int c = lookChar(); buf = EOF; return c; } + virtual int lookChar(); + virtual GString *getPSFilter(char *indent); + virtual GBool isBinary(GBool last = gTrue); + +private: + + int encoding; // 'K' parameter + GBool endOfLine; // 'EndOfLine' parameter + GBool byteAlign; // 'EncodedByteAlign' parameter + int columns; // 'Columns' parameter + int rows; // 'Rows' parameter + GBool endOfBlock; // 'EndOfBlock' parameter + GBool black; // 'BlackIs1' parameter + GBool eof; // true if at eof + GBool nextLine2D; // true if next line uses 2D encoding + int row; // current row + int inputBuf; // input buffer + int inputBits; // number of bits in input buffer + short *refLine; // reference line changing elements + int b1; // index into refLine + short *codingLine; // coding line changing elements + int a0; // index into codingLine + int outputBits; // remaining ouput bits + int buf; // character buffer + + short getTwoDimCode(); + short getWhiteCode(); + short getBlackCode(); + short lookBits(int n); + void eatBits(int n) { inputBits -= n; } +}; + +//------------------------------------------------------------------------ +// DCTStream +//------------------------------------------------------------------------ + +// DCT component info +struct DCTCompInfo { + int id; // component ID + GBool inScan; // is this component in the current scan? + int hSample, vSample; // horiz/vert sampling resolutions + int quantTable; // quantization table number + int dcHuffTable, acHuffTable; // Huffman table numbers + int prevDC; // DC coefficient accumulator +}; + +// DCT Huffman decoding table +struct DCTHuffTable { + Guchar firstSym[17]; // first symbol for this bit length + Gushort firstCode[17]; // first code for this bit length + Gushort numCodes[17]; // number of codes of this bit length + Guchar sym[256]; // symbols +}; + +class DCTStream: public FilterStream { +public: + + DCTStream(Stream *str); + virtual ~DCTStream(); + virtual StreamKind getKind() { return strDCT; } + virtual void reset(); + virtual int getChar(); + virtual int lookChar(); + virtual GString *getPSFilter(char *indent); + virtual GBool isBinary(GBool last = gTrue); + Stream *getRawStream() { return str; } + +private: + + int width, height; // image size + int mcuWidth, mcuHeight; // size of min coding unit, in data units + DCTCompInfo compInfo[4]; // info for each component + int numComps; // number of components in image + int colorXform; // need YCbCr-to-RGB transform? + GBool gotAdobeMarker; // set if APP14 Adobe marker was present + int restartInterval; // restart interval, in MCUs + Guchar quantTables[4][64]; // quantization tables + int numQuantTables; // number of quantization tables + DCTHuffTable dcHuffTables[4]; // DC Huffman tables + DCTHuffTable acHuffTables[4]; // AC Huffman tables + int numDCHuffTables; // number of DC Huffman tables + int numACHuffTables; // number of AC Huffman tables + Guchar *rowBuf[4][32]; // buffer for one MCU + int comp, x, y, dy; // current position within image/MCU + int restartCtr; // MCUs left until restart + int restartMarker; // next restart marker + int inputBuf; // input buffer for variable length codes + int inputBits; // number of valid bits in input buffer + + void restart(); + GBool readMCURow(); + GBool readDataUnit(DCTHuffTable *dcHuffTable, DCTHuffTable *acHuffTable, + Guchar quantTable[64], int *prevDC, Guchar data[64]); + int readHuffSym(DCTHuffTable *table); + int readAmp(int size); + int readBit(); + GBool readHeader(); + GBool readFrameInfo(); + GBool readScanInfo(); + GBool readQuantTables(); + GBool readHuffmanTables(); + GBool readRestartInterval(); + GBool readAdobeMarker(); + GBool readTrailer(); + int readMarker(); + int read16(); +}; + +//------------------------------------------------------------------------ +// FlateStream +//------------------------------------------------------------------------ + +#define flateWindow 32768 // buffer size +#define flateMask (flateWindow-1) +#define flateMaxHuffman 15 // max Huffman code length +#define flateMaxCodeLenCodes 19 // max # code length codes +#define flateMaxLitCodes 288 // max # literal codes +#define flateMaxDistCodes 30 // max # distance codes + +// Huffman code table entry +struct FlateCode { + int len; // code length in bits + int code; // code word + int val; // value represented by this code +}; + +// Huffman code table +struct FlateHuffmanTab { + int start[flateMaxHuffman+2]; // indexes of first code of each length + FlateCode *codes; // codes, sorted by length and code word +}; + +// Decoding info for length and distance code words +struct FlateDecode { + int bits; // # extra bits + int first; // first length/distance +}; + +class FlateStream: public FilterStream { +public: + + FlateStream(Stream *str, int predictor1, int columns1, + int colors1, int bits1); + virtual ~FlateStream(); + virtual StreamKind getKind() { return strFlate; } + virtual void reset(); + virtual int getChar(); + virtual int lookChar(); + virtual int getRawChar(); + virtual GString *getPSFilter(char *indent); + virtual GBool isBinary(GBool last = gTrue); + +private: + + StreamPredictor *pred; // predictor + Guchar buf[flateWindow]; // output data buffer + int index; // current index into output buffer + int remain; // number valid bytes in output buffer + int codeBuf; // input buffer + int codeSize; // number of bits in input buffer + FlateCode // literal and distance codes + allCodes[flateMaxLitCodes + flateMaxDistCodes]; + FlateHuffmanTab litCodeTab; // literal code table + FlateHuffmanTab distCodeTab; // distance code table + GBool compressedBlock; // set if reading a compressed block + int blockLen; // remaining length of uncompressed block + GBool endOfBlock; // set when end of block is reached + GBool eof; // set when end of stream is reached + + static int // code length code reordering + codeLenCodeMap[flateMaxCodeLenCodes]; + static FlateDecode // length decoding info + lengthDecode[flateMaxLitCodes-257]; + static FlateDecode // distance decoding info + distDecode[flateMaxDistCodes]; + + void readSome(); + GBool startBlock(); + void loadFixedCodes(); + GBool readDynamicCodes(); + void compHuffmanCodes(FlateHuffmanTab *tab, int n); + int getHuffmanCodeWord(FlateHuffmanTab *tab); + int getCodeWord(int bits); +}; + +//------------------------------------------------------------------------ +// EOFStream +//------------------------------------------------------------------------ + +class EOFStream: public FilterStream { +public: + + EOFStream(Stream *str); + virtual ~EOFStream(); + virtual StreamKind getKind() { return strWeird; } + virtual void reset() {} + virtual int getChar() { return EOF; } + virtual int lookChar() { return EOF; } + virtual GString *getPSFilter(char *indent) { return NULL; } + virtual GBool isBinary(GBool last = gTrue) { return gFalse; } +}; + +//------------------------------------------------------------------------ +// FixedLengthEncoder +//------------------------------------------------------------------------ + +class FixedLengthEncoder: public FilterStream { +public: + + FixedLengthEncoder(Stream *str, int length1); + ~FixedLengthEncoder(); + virtual StreamKind getKind() { return strWeird; } + virtual void reset(); + virtual int getChar(); + virtual int lookChar(); + virtual GString *getPSFilter(char *indent) { return NULL; } + virtual GBool isBinary(GBool last = gTrue) { return gFalse; } + virtual GBool isEncoder() { return gTrue; } + +private: + + int length; + int count; +}; + +//------------------------------------------------------------------------ +// ASCII85Encoder +//------------------------------------------------------------------------ + +class ASCII85Encoder: public FilterStream { +public: + + ASCII85Encoder(Stream *str); + virtual ~ASCII85Encoder(); + virtual StreamKind getKind() { return strWeird; } + virtual void reset(); + virtual int getChar() + { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); } + virtual int lookChar() + { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); } + virtual GString *getPSFilter(char *indent) { return NULL; } + virtual GBool isBinary(GBool last = gTrue) { return gFalse; } + virtual GBool isEncoder() { return gTrue; } + +private: + + char buf[8]; + char *bufPtr; + char *bufEnd; + int lineLen; + GBool eof; + + GBool fillBuf(); +}; + +//------------------------------------------------------------------------ +// RunLengthEncoder +//------------------------------------------------------------------------ + +class RunLengthEncoder: public FilterStream { +public: + + RunLengthEncoder(Stream *str); + virtual ~RunLengthEncoder(); + virtual StreamKind getKind() { return strWeird; } + virtual void reset(); + virtual int getChar() + { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); } + virtual int lookChar() + { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); } + virtual GString *getPSFilter(char *indent) { return NULL; } + virtual GBool isBinary(GBool last = gTrue) { return gFalse; } + virtual GBool isEncoder() { return gTrue; } + +private: + + char buf[131]; + char *bufPtr; + char *bufEnd; + char *nextEnd; + GBool eof; + + GBool fillBuf(); +}; + +#endif diff --git a/pdftops/T1Font.h b/pdftops/T1Font.h new file mode 100644 index 0000000000..9ead397f62 --- /dev/null +++ b/pdftops/T1Font.h @@ -0,0 +1,102 @@ +//======================================================================== +// +// T1Font.h +// +// An X wrapper for the t1lib Type 1 font rasterizer. +// +//======================================================================== + +#ifndef T1FONT_H +#define T1FONT_H + +#if HAVE_T1LIB_H + +#ifdef __GNUC__ +#pragma interface +#endif + +#include +#include +#include "SFont.h" + +class FontEncoding; + +//------------------------------------------------------------------------ + +class T1FontEngine: public SFontEngine { +public: + + T1FontEngine(Display *display, Visual *visual, int depth, + Colormap colormap, GBool aa, GBool aaHigh); + GBool isOk() { return ok; } + virtual ~T1FontEngine(); + +private: + + GBool aa; // use anti-aliasing? + GBool aaHigh; // use high-res anti-aliasing? + GBool bigEndian; + GBool ok; + + friend class T1FontFile; + friend class T1Font; +}; + +//------------------------------------------------------------------------ + +class T1FontFile: public SFontFile { +public: + + T1FontFile(T1FontEngine *engine, char *fontFileName, + FontEncoding *fontEnc); + GBool isOk() { return ok; } + virtual ~T1FontFile(); + +private: + + T1FontEngine *engine; + int id; // t1lib font ID + char **enc; + char *encStr; + GBool ok; + + friend class T1Font; +}; + +//------------------------------------------------------------------------ + +struct T1FontCacheTag { + Gushort code; + Gushort mru; // valid bit (0x8000) and MRU index + int x, y, w, h; // offset and size of glyph +}; + +class T1Font: public SFont { +public: + + T1Font(T1FontFile *fontFile, double *m); + GBool isOk() { return ok; } + virtual ~T1Font(); + virtual GBool drawChar(Drawable d, int w, int h, GC gc, + int x, int y, int r, int g, int b, Gushort c); + +private: + + Guchar *getGlyphPixmap(Gushort c, int *x, int *y, int *w, int *h); + + T1FontFile *fontFile; + int id; + float size; + XImage *image; + int glyphW, glyphH; // size of glyph pixmaps + int glyphSize; // size of glyph pixmaps, in bytes + Guchar *cache; // glyph pixmap cache + T1FontCacheTag *cacheTags; // cache tags, i.e., char codes + int cacheSets; // number of sets in cache + int cacheAssoc; // cache associativity (glyphs per set) + GBool ok; +}; + +#endif // HAVE_T1LIB_H + +#endif diff --git a/pdftops/TTFont.h b/pdftops/TTFont.h new file mode 100644 index 0000000000..68e5d97364 --- /dev/null +++ b/pdftops/TTFont.h @@ -0,0 +1,106 @@ +//======================================================================== +// +// TTFont.h +// +// An X wrapper for the FreeType TrueType font rasterizer. +// +//======================================================================== + +#ifndef TTFONT_H +#define TTFONT_H + +#if HAVE_FREETYPE_FREETYPE_H + +#ifdef __GNUC__ +#pragma interface +#endif + +#ifdef VMS +#include +#include +#else +//~ This will be going away; the configure script will add +//~ -I/freetype to CFLAGS. +#include +#include +#endif +#include "SFont.h" + +//------------------------------------------------------------------------ + +class TTFontEngine: public SFontEngine { +public: + + TTFontEngine(Display *display, Visual *visual, int depth, + Colormap colormap, GBool aa); + GBool isOk() { return ok; } + virtual ~TTFontEngine(); + +private: + + TT_Engine engine; + GBool aa; + Gulong palette[5]; + GBool ok; + + friend class TTFontFile; + friend class TTFont; +}; + +//------------------------------------------------------------------------ + +class TTFontFile: public SFontFile { +public: + + TTFontFile(TTFontEngine *engine, char *fontFileName); + GBool isOk() { return ok; } + virtual ~TTFontFile(); + +private: + + TTFontEngine *engine; + TT_Face face; + TT_CharMap charMap; + int charMapOffset; + GBool ok; + + friend class TTFont; +}; + +//------------------------------------------------------------------------ + +struct TTFontCacheTag { + Gushort code; + Gushort mru; // valid bit (0x8000) and MRU index +}; + +class TTFont: public SFont { +public: + + TTFont(TTFontFile *fontFile, double *m); + GBool isOk() { return ok; } + virtual ~TTFont(); + virtual GBool drawChar(Drawable d, int w, int h, GC gc, + int x, int y, int r, int g, int b, Gushort c); + +private: + + GBool getGlyphPixmap(Gushort c); + + TTFontFile *fontFile; + TT_Instance instance; + TT_Glyph glyph; + TT_Raster_Map ras; + XImage *image; + TT_Matrix matrix; + TT_F26Dot6 xOffset, yOffset; + Guchar *cache; // glyph pixmap cache + TTFontCacheTag *cacheTags; // cache tags, i.e., char codes + int cacheSets; // number of sets in cache + int cacheAssoc; // cache associativity (glyphs per set) + GBool ok; +}; + +#endif // HAVE_FREETYPE_FREETYPE_H + +#endif diff --git a/pdftops/XRef.cxx b/pdftops/XRef.cxx new file mode 100644 index 0000000000..2479818cde --- /dev/null +++ b/pdftops/XRef.cxx @@ -0,0 +1,555 @@ +//======================================================================== +// +// XRef.cc +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include +#include +#include +#include +#include "gmem.h" +#include "Object.h" +#include "Stream.h" +#include "Lexer.h" +#include "Parser.h" +#include "Dict.h" +#ifndef NO_DECRYPTION +#include "Decrypt.h" +#endif +#include "Error.h" +#include "XRef.h" + +//------------------------------------------------------------------------ + +#define xrefSearchSize 1024 // read this many bytes at end of file + // to look for 'startxref' + +#ifndef NO_DECRYPTION +//------------------------------------------------------------------------ +// Permission bits +//------------------------------------------------------------------------ + +#define permPrint (1<<2) +#define permChange (1<<3) +#define permCopy (1<<4) +#define permNotes (1<<5) +#define defPermFlags 0xfffc +#endif + +//------------------------------------------------------------------------ +// The global xref table +//------------------------------------------------------------------------ + +XRef *xref = NULL; + +//------------------------------------------------------------------------ +// XRef +//------------------------------------------------------------------------ + +XRef::XRef(BaseStream *str, GString *userPassword) { + XRef *oldXref; + int pos; + int i; + + ok = gTrue; + size = 0; + entries = NULL; + + // get rid of old xref (otherwise it will try to fetch the Root object + // in the new document, using the old xref) + oldXref = xref; + xref = NULL; + + // read the trailer + this->str = str; + start = str->getStart(); + pos = readTrailer(); + + // if there was a problem with the trailer, + // try to reconstruct the xref table + if (pos == 0) { + if (!(ok = constructXRef())) { + xref = oldXref; + return; + } + + // trailer is ok - read the xref table + } else { + entries = (XRefEntry *)gmalloc(size * sizeof(XRefEntry)); + for (i = 0; i < size; ++i) { + entries[i].offset = -1; + entries[i].used = gFalse; + } + while (readXRef(&pos)) ; + + // if there was a problem with the xref table, + // try to reconstruct it + if (!ok) { + gfree(entries); + size = 0; + entries = NULL; + if (!(ok = constructXRef())) { + xref = oldXref; + return; + } + } + } + + // set up new xref table + xref = this; + + // check for encryption +#ifndef NO_DECRYPTION + encrypted = gFalse; +#endif + if (checkEncrypted(userPassword)) { + ok = gFalse; + xref = oldXref; + return; + } +} + +XRef::~XRef() { + gfree(entries); + trailerDict.free(); +} + +// Read startxref position, xref table size, and root. Returns +// first xref position. +int XRef::readTrailer() { + Parser *parser; + Object obj; + char buf[xrefSearchSize+1]; + int n, pos, pos1; + char *p; + int c; + int i; + + // read last xrefSearchSize bytes + str->setPos(-xrefSearchSize); + for (n = 0; n < xrefSearchSize; ++n) { + if ((c = str->getChar()) == EOF) + break; + buf[n] = c; + } + buf[n] = '\0'; + + // find startxref + for (i = n - 9; i >= 0; --i) { + if (!strncmp(&buf[i], "startxref", 9)) + break; + } + if (i < 0) + return 0; + for (p = &buf[i+9]; isspace(*p); ++p) ; + pos = lastXRefPos = atoi(p); + + // find trailer dict by looking after first xref table + // (NB: we can't just use the trailer dict at the end of the file -- + // this won't work for linearized files.) + str->setPos(start + pos); + for (i = 0; i < 4; ++i) + buf[i] = str->getChar(); + if (strncmp(buf, "xref", 4)) + return 0; + pos1 = pos + 4; + while (1) { + str->setPos(start + pos1); + for (i = 0; i < 35; ++i) { + if ((c = str->getChar()) == EOF) + return 0; + buf[i] = c; + } + if (!strncmp(buf, "trailer", 7)) + break; + p = buf; + while (isspace(*p)) ++p; + while ('0' <= *p && *p <= '9') ++p; + while (isspace(*p)) ++p; + n = atoi(p); + while ('0' <= *p && *p <= '9') ++p; + while (isspace(*p)) ++p; + if (p == buf) + return 0; + pos1 += (p - buf) + n * 20; + } + pos1 += 7; + + // read trailer dict + obj.initNull(); + parser = new Parser(new Lexer(str->makeSubStream(start + pos1, -1, &obj))); + parser->getObj(&trailerDict); + if (trailerDict.isDict()) { + trailerDict.dictLookupNF("Size", &obj); + if (obj.isInt()) + size = obj.getInt(); + else + pos = 0; + obj.free(); + trailerDict.dictLookupNF("Root", &obj); + if (obj.isRef()) { + rootNum = obj.getRefNum(); + rootGen = obj.getRefGen(); + } else { + pos = 0; + } + obj.free(); + } else { + pos = 0; + } + delete parser; + + // return first xref position + return pos; +} + +// Read an xref table and the prev pointer from the trailer. +GBool XRef::readXRef(int *pos) { + Parser *parser; + Object obj, obj2; + char s[20]; + GBool more; + int first, n, i, j; + int c; + + // seek to xref in stream + str->setPos(start + *pos); + + // make sure it's an xref table + while ((c = str->getChar()) != EOF && isspace(c)) ; + s[0] = (char)c; + s[1] = (char)str->getChar(); + s[2] = (char)str->getChar(); + s[3] = (char)str->getChar(); + if (!(s[0] == 'x' && s[1] == 'r' && s[2] == 'e' && s[3] == 'f')) + goto err2; + + // read xref + while (1) { + while ((c = str->lookChar()) != EOF && isspace(c)) + str->getChar(); + if (c == 't') + break; + for (i = 0; (c = str->getChar()) != EOF && isdigit(c) && i < 20; ++i) + s[i] = (char)c; + if (i == 0) + goto err2; + s[i] = '\0'; + first = atoi(s); + while ((c = str->lookChar()) != EOF && isspace(c)) + str->getChar(); + for (i = 0; (c = str->getChar()) != EOF && isdigit(c) && i < 20; ++i) + s[i] = (char)c; + if (i == 0) + goto err2; + s[i] = '\0'; + n = atoi(s); + while ((c = str->lookChar()) != EOF && isspace(c)) + str->getChar(); + for (i = first; i < first + n; ++i) { + for (j = 0; j < 20; ++j) { + if ((c = str->getChar()) == EOF) + goto err2; + s[j] = (char)c; + } + if (entries[i].offset < 0) { + s[10] = '\0'; + entries[i].offset = atoi(s); + s[16] = '\0'; + entries[i].gen = atoi(&s[11]); + if (s[17] == 'n') + entries[i].used = gTrue; + else if (s[17] == 'f') + entries[i].used = gFalse; + else + goto err2; +#if 1 //~ + //~ PDF files of patents from the IBM Intellectual Property + //~ Network have a bug: the xref table claims to start at 1 + //~ instead of 0. + if (i == 1 && first == 1 && + entries[1].offset == 0 && entries[1].gen == 65535 && + !entries[1].used) { + i = first = 0; + entries[0] = entries[1]; + entries[1].offset = -1; + } +#endif + } + } + } + + // read prev pointer from trailer dictionary + obj.initNull(); + parser = new Parser(new Lexer(str->makeSubStream(str->getPos(), -1, &obj))); + parser->getObj(&obj); + if (!obj.isCmd("trailer")) + goto err1; + obj.free(); + parser->getObj(&obj); + if (!obj.isDict()) + goto err1; + obj.getDict()->lookupNF("Prev", &obj2); + if (obj2.isInt()) { + *pos = obj2.getInt(); + more = gTrue; + } else { + more = gFalse; + } + obj.free(); + obj2.free(); + + delete parser; + return more; + + err1: + obj.free(); + err2: + ok = gFalse; + return gFalse; +} + +// Attempt to construct an xref table for a damaged file. +GBool XRef::constructXRef() { + Parser *parser; + Object obj; + char buf[256]; + int pos; + int num, gen; + int newSize; + char *p; + int i; + GBool gotRoot; + + error(0, "PDF file is damaged - attempting to reconstruct xref table..."); + gotRoot = gFalse; + + str->reset(); + while (1) { + pos = str->getPos(); + if (!str->getLine(buf, 256)) + break; + p = buf; + + // got trailer dictionary + if (!strncmp(p, "trailer", 7)) { + obj.initNull(); + parser = new Parser(new Lexer( + str->makeSubStream(start + pos + 8, -1, &obj))); + if (!trailerDict.isNone()) + trailerDict.free(); + parser->getObj(&trailerDict); + if (trailerDict.isDict()) { + trailerDict.dictLookupNF("Root", &obj); + if (obj.isRef()) { + rootNum = obj.getRefNum(); + rootGen = obj.getRefGen(); + gotRoot = gTrue; + } + obj.free(); + } else { + pos = 0; + } + delete parser; + + // look for object + } else if (isdigit(*p)) { + num = atoi(p); + do { + ++p; + } while (*p && isdigit(*p)); + if (isspace(*p)) { + do { + ++p; + } while (*p && isspace(*p)); + if (isdigit(*p)) { + gen = atoi(p); + do { + ++p; + } while (*p && isdigit(*p)); + if (isspace(*p)) { + do { + ++p; + } while (*p && isspace(*p)); + if (!strncmp(p, "obj", 3)) { + if (num >= size) { + newSize = (num + 1 + 255) & ~255; + entries = (XRefEntry *) + grealloc(entries, newSize * sizeof(XRefEntry)); + for (i = size; i < newSize; ++i) { + entries[i].offset = -1; + entries[i].used = gFalse; + } + size = newSize; + } + if (!entries[num].used || gen >= entries[num].gen) { + entries[num].offset = pos - start; + entries[num].gen = gen; + entries[num].used = gTrue; + } + } + } + } + } + } + } + + if (gotRoot) + return gTrue; + + error(-1, "Couldn't find trailer dictionary"); + return gFalse; +} + +#ifndef NO_DECRYPTION +GBool XRef::checkEncrypted(GString *userPassword) { + Object encrypt, ownerKey, userKey, permissions, fileID, fileID1; + GBool encrypted1; + GBool ret; + + ret = gFalse; + + permFlags = defPermFlags; + trailerDict.dictLookup("Encrypt", &encrypt); + if ((encrypted1 = encrypt.isDict())) { + ret = gTrue; + encrypt.dictLookup("O", &ownerKey); + encrypt.dictLookup("U", &userKey); + encrypt.dictLookup("P", &permissions); + trailerDict.dictLookup("ID", &fileID); + if (ownerKey.isString() && ownerKey.getString()->getLength() == 32 && + userKey.isString() && userKey.getString()->getLength() == 32 && + permissions.isInt() && + fileID.isArray()) { + permFlags = permissions.getInt(); + fileID.arrayGet(0, &fileID1); + if (fileID1.isString()) { + if (Decrypt::makeFileKey(ownerKey.getString(), userKey.getString(), + permFlags, fileID1.getString(), + userPassword, fileKey)) { + ret = gFalse; + } else { + error(-1, "Incorrect user password"); + } + } else { + error(-1, "Weird encryption info"); + } + fileID1.free(); + } else { + error(-1, "Weird encryption info"); + } + ownerKey.free(); + userKey.free(); + permissions.free(); + fileID.free(); + } + encrypt.free(); + + // this flag has to be set *after* we read the O/U/P strings + encrypted = encrypted1; + + return ret; +} +#else +GBool XRef::checkEncrypted(GString *userPassword) { + Object obj; + GBool encrypted; + + trailerDict.dictLookup("Encrypt", &obj); + if ((encrypted = !obj.isNull())) { + error(-1, "PDF file is encrypted and cannot be displayed"); + error(-1, "* Decryption support is currently not included in xpdf"); + error(-1, "* due to legal restrictions: the U.S.A. still has bogus"); + error(-1, "* export controls on cryptography software."); + } + obj.free(); + return encrypted; +} +#endif + +GBool XRef::okToPrint() { +#ifndef NO_DECRYPTION + if (!(permFlags & permPrint)) { + return gFalse; + } +#endif + return gTrue; +} + +GBool XRef::okToChange() { +#ifndef NO_DECRYPTION + if (!(permFlags & permChange)) { + return gFalse; + } +#endif + return gTrue; +} + +GBool XRef::okToCopy() { +#ifndef NO_DECRYPTION + if (!(permFlags & permCopy)) { + return gFalse; + } +#endif + return gTrue; +} + +GBool XRef::okToAddNotes() { +#ifndef NO_DECRYPTION + if (!(permFlags & permNotes)) { + return gFalse; + } +#endif + return gTrue; +} + +Object *XRef::fetch(int num, int gen, Object *obj) { + XRefEntry *e; + Parser *parser; + Object obj1, obj2, obj3; + + // check for bogus ref - this can happen in corrupted PDF files + if (num < 0 || num >= size) { + obj->initNull(); + return obj; + } + + e = &entries[num]; + if (e->gen == gen && e->offset >= 0) { + obj1.initNull(); + parser = new Parser(new Lexer( + str->makeSubStream(start + e->offset, -1, &obj1))); + parser->getObj(&obj1); + parser->getObj(&obj2); + parser->getObj(&obj3); + if (obj1.isInt() && obj1.getInt() == num && + obj2.isInt() && obj2.getInt() == gen && + obj3.isCmd("obj")) { +#ifndef NO_DECRYPTION + parser->getObj(obj, encrypted ? fileKey : (Guchar *)NULL, num, gen); +#else + parser->getObj(obj); +#endif + } else { + obj->initNull(); + } + obj1.free(); + obj2.free(); + obj3.free(); + delete parser; + } else { + obj->initNull(); + } + return obj; +} + +Object *XRef::getDocInfo(Object *obj) { + return trailerDict.dictLookup("Info", obj); +} diff --git a/pdftops/XRef.h b/pdftops/XRef.h new file mode 100644 index 0000000000..28ef66cf98 --- /dev/null +++ b/pdftops/XRef.h @@ -0,0 +1,105 @@ +//======================================================================== +// +// XRef.h +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#ifndef XREF_H +#define XREF_H + +#ifdef __GNUC__ +#pragma interface +#endif + +#include "gtypes.h" +#include "Object.h" + +class Dict; +class Stream; + +//------------------------------------------------------------------------ +// XRef +//------------------------------------------------------------------------ + +struct XRefEntry { + int offset; + int gen; + GBool used; +}; + +class XRef { +public: + + // Constructor. Read xref table from stream. + XRef(BaseStream *str, GString *userPassword); + + // Destructor. + ~XRef(); + + // Is xref table valid? + GBool isOk() { return ok; } + + // Is the file encrypted? +#ifndef NO_DECRYPTION + GBool isEncrypted() { return encrypted; } +#else + GBool isEncrypted() { return gFalse; } +#endif + + // Check various permissions. + GBool okToPrint(); + GBool okToChange(); + GBool okToCopy(); + GBool okToAddNotes(); + + // Get catalog object. + Object *getCatalog(Object *obj) { return fetch(rootNum, rootGen, obj); } + + // Fetch an indirect reference. + Object *fetch(int num, int gen, Object *obj); + + // Return the document's Info dictionary (if any). + Object *getDocInfo(Object *obj); + + // Return the number of objects in the xref table. + int getNumObjects() { return size; } + + // Return the offset of the last xref table. + int getLastXRefPos() { return lastXRefPos; } + + // Return the catalog object reference. + int getRootNum() { return rootNum; } + int getRootGen() { return rootGen; } + +private: + + BaseStream *str; // input stream + int start; // offset in file (to allow for garbage + // at beginning of file) + XRefEntry *entries; // xref entries + int size; // size of array + int rootNum, rootGen; // catalog dict + GBool ok; // true if xref table is valid + Object trailerDict; // trailer dictionary + int lastXRefPos; // offset of last xref table +#ifndef NO_DECRYPTION + GBool encrypted; // true if file is encrypted + int permFlags; // permission bits + Guchar fileKey[16]; // file decryption key +#endif + + int readTrailer(); + GBool readXRef(int *pos); + GBool constructXRef(); + GBool checkEncrypted(GString *userPassword); +}; + +//------------------------------------------------------------------------ +// The global xref table +//------------------------------------------------------------------------ + +extern XRef *xref; + +#endif diff --git a/pdftops/config.h b/pdftops/config.h new file mode 100644 index 0000000000..7c0a615950 --- /dev/null +++ b/pdftops/config.h @@ -0,0 +1,65 @@ +//======================================================================== +// +// config.h +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#ifndef CONFIG_H +#define CONFIG_H + +//------------------------------------------------------------------------ +// general constants +//------------------------------------------------------------------------ + +// xpdf version +#define xpdfVersion "0.91" + +// supported PDF version +#define supportedPDFVersionStr "1.3" +#define supportedPDFVersionNum 1.3 + +// copyright notice +#define xpdfCopyright "Copyright 1996-2000 Derek B. Noonburg" + +//------------------------------------------------------------------------ +// uncompress program +//------------------------------------------------------------------------ + +#define HAVE_POPEN +#define uncompressCmd "uncompress -c" + +// number of TrueType (FreeType) fonts to cache +#define ttFontCacheSize 32 + +//------------------------------------------------------------------------ +// popen +//------------------------------------------------------------------------ + +#ifdef _MSC_VER +#define popen _popen +#define pclose _pclose +#endif + +#if defined(VMS) || defined(VMCMS) || defined(DOS) || defined(OS2) || defined(WIN32) || defined(__DJGPP__) || defined(__CYGWIN32) || defined(MACOS) +#define POPEN_READ_MODE "rb" +#else +#define POPEN_READ_MODE "r" +#endif + +//------------------------------------------------------------------------ +// Win32 stuff +//------------------------------------------------------------------------ + +#ifdef CDECL +#undef CDECL +#endif + +#ifdef _MSC_VER +#define CDECL __cdecl +#else +#define CDECL +#endif + +#endif diff --git a/pdftops/configure.in b/pdftops/configure.in new file mode 100644 index 0000000000..8ba7984758 --- /dev/null +++ b/pdftops/configure.in @@ -0,0 +1,203 @@ +dnl Process this file with autoconf to produce a configure script. +AC_INIT(xpdf/xpdf.cc) + +dnl ##### Optional features. +OPTIONS="" +AC_ARG_ENABLE(a4-paper, +[ --enable-a4-paper use A4 paper size instead of Letter for + PostScript output], +OPTIONS="$OPTIONS -DA4_PAPER") +AC_ARG_ENABLE(japanese, +[ --enable-japanese enable Japanese font support], +OPTIONS="$OPTIONS -DJAPANESE_SUPPORT") +AC_ARG_ENABLE(no-text-select, +[ --enable-no-text-select do not allow text selection], +OPTIONS="$OPTIONS -DNO_TEXT_SELECT") +AC_ARG_WITH(gzip, +[ --with-gzip use gzip instead of uncompress], +OPTIONS="$OPTIONS -DUSE_GZIP") +AC_SUBST(OPTIONS) + +dnl ##### Checks for programs. +AC_PROG_CC +AC_ISC_POSIX +AM_PROG_CC_STDC +#if test -z "$CXX" -a "$CC" = "gcc"; then +# CXX="gcc" +#fi +AC_PROG_CXX +AC_PROG_INSTALL +AC_PROG_RANLIB + +dnl ##### Default values for Unix. +EXE="" +LIBPREFIX="lib" +AR="ar rc" +UP_DIR="" + +dnl ##### Check for OS/2. +AC_CACHE_CHECK([for OS/2 (with EMX)], +xpdf_cv_sys_os2, +[AC_TRY_COMPILE([], +[__EMX__], +xpdf_cv_sys_os2=yes, xpdf_cv_sys_os2=no)]) +if test "$xpdf_cv_sys_os2" = yes; then + EXE=".exe" + LIBPREFIX="" + AR="ar -rc" +fi + +dnl ##### Check for DOS (with DJGPP). +AC_CACHE_CHECK([for DOS (with DJGPP)], +xpdf_cv_sys_dos, +[AC_TRY_COMPILE([], +[__DJGPP__], +xpdf_cv_sys_dos=yes, xpdf_cv_sys_dos=no)]) +if test "$xpdf_cv_sys_dos" = yes; then + EXE=".exe" + LIBPREFIX="lib" + AR="ar -rc" + UP_DIR="../" +fi + +dnl ##### Do substitutions. +AC_SUBST(EXE) +AC_SUBST(LIBPREFIX) +AC_SUBST(AR) +AC_SUBST(UP_DIR) + +dnl ##### Checks for header files. +AC_PATH_XTRA +AC_HEADER_DIRENT + +dnl ##### Look for header that defines fd_set. +AC_MSG_CHECKING([fd_set and sys/select.h or sys/bsdtypes.h]) +AC_TRY_COMPILE([#include ], + [fd_set fds;], xpdf_ok=yes, xpdf_ok=no) +if test $xpdf_ok = yes; then + AC_MSG_RESULT([not needed]) +else + AC_TRY_COMPILE([#include +#include ], + [fd_set fds;], xpdf_ok=yes, xpdf_ok=no) + if test $xpdf_ok = yes; then + AC_DEFINE(HAVE_SYS_SELECT_H) + AC_MSG_RESULT([need sys/select.h]) + else + AC_TRY_COMPILE([#include +#include ], + [fd_set fds;], xpdf_ok=yes, xpdf_ok=no) + if test $xpdf_ok = yes; then + AC_DEFINE(HAVE_SYS_BSDTYPES_H) + AC_MSG_RESULT([need sys/bsdtypes.h]) + else + AC_MSG_RESULT([problem]) + fi + fi +fi + +dnl ##### Look for header that defines FD_ZERO. +AC_MSG_CHECKING([FD_ZERO and strings.h or bstring.h]) +AC_TRY_COMPILE([#include +#ifdef HAVE_SYS_SELECT_H +#include +#endif], +[fd_set fds; FD_ZERO(&fds);], xpdf_ok=yes, xpdf_ok=no) +if test $xpdf_ok = yes; then + AC_MSG_RESULT([not needed]) +else + AC_TRY_COMPILE([#include +#include +#ifdef HAVE_SYS_SELECT_H +#include +#endif], + [fd_set fds; FD_ZERO(&fds);], xpdf_ok=yes, xpdf_ok=no) + if test $xpdf_ok = yes; then + AC_DEFINE(HAVE_STRINGS_H) + AC_MSG_RESULT([need strings.h]) + else + AC_TRY_COMPILE([#include +#include +#ifdef HAVE_SYS_SELECT_H +#include +#endif], + [fd_set fds; FD_ZERO(&fds);], xpdf_ok=yes, xpdf_ok=no) + if test $xpdf_ok = yes; then + AC_DEFINE(HAVE_BSTRING_H) + AC_MSG_RESULT([need bstring.h]) + else + AC_MSG_RESULT([problem]) + fi + fi +fi + +dnl ##### Look for rewinddir. +AC_CHECK_FUNCS(rewinddir) +if test $ac_cv_func_rewinddir = no; then + AC_CHECK_LIB(cposix, rewinddir) +fi + +dnl ##### Checks for library functions. +AC_CHECK_FUNCS(popen) + +dnl ##### Check select argument type: on HP-UX before version 10, select +dnl ##### takes (int *) instead of (fd_set *). +AC_LANG_CPLUSPLUS +AC_CACHE_CHECK([whether select takes fd_set arguments], +xpdf_cv_func_select_arg, +[AC_TRY_COMPILE([#include +#include +#ifdef HAVE_SYS_SELECT_H +#include +#endif], +[fd_set fds; +select(1, &fds, &fds, &fds, 0);], +xpdf_cv_func_select_arg=yes, xpdf_cv_func_select_arg=no)]) +if test "$xpdf_cv_func_select_arg" != yes; then + AC_DEFINE(SELECT_TAKES_INT) +fi +AC_LANG_C + +dnl ##### Check for libXpm. +if test -z "$no_x"; then + smr_CHECK_LIB(Xpm, Xpm, [pixmap library, used only for icon], + XpmCreatePixmapFromData, X11/xpm.h, + $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS, $X_CFLAGS) + AC_SUBST(Xpm_LIBS) + AC_SUBST(Xpm_CFLAGS) +fi + +dnl ##### Check for t1lib. +if test -z "$no_x"; then + smr_CHECK_LIB(t1, t1, [Type 1 font rasterizer], + T1_InitLib, t1lib.h, + $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS -lm, $X_CFLAGS) + AC_SUBST(t1_LIBS) + AC_SUBST(t1_CFLAGS) + smr_CHECK_LIB(t1x, t1x, [Type 1 font rasterizer], + T1_SetX11Params, t1libx.h, + $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS $t1_LIBS -lm, + $X_CFLAGS $t1_CFLAGS) + AC_SUBST(t1x_LIBS) + AC_SUBST(t1x_CFLAGS) +fi + +dnl ##### Disable X-specific stuff in top-level Makefile. +if test -n "$no_x"; then + X="#" + XPDF_TARGET="all-no-x" +else + X="" + XPDF_TARGET="all" +fi +AC_SUBST(X) +AC_SUBST(XPDF_TARGET) + +dnl ##### Write the makefiles. +AC_OUTPUT(Makefile xpdf/Makefile ltk/Makefile goo/Makefile) + +dnl ##### Warn user if X is missing. +if test -n "$no_x"; then + AC_MSG_WARN([Couldn't find X -- you will be able to compile + pdftops, pdftotext, pdfinfo, and pdfimages, but not xpdf]) +fi diff --git a/pdftops/gfile.cxx b/pdftops/gfile.cxx new file mode 100644 index 0000000000..2776be3f93 --- /dev/null +++ b/pdftops/gfile.cxx @@ -0,0 +1,636 @@ +//======================================================================== +// +// gfile.cc +// +// Miscellaneous file and directory name manipulation. +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#ifdef WIN32 + extern "C" { +# ifndef _MSC_VER +# include +# endif + } +#else // !WIN32 +# if defined(MACOS) +# include +# elif !defined(ACORN) +# include +# include +# include +# endif +# include +# include +# if !defined(VMS) && !defined(ACORN) && !defined(MACOS) +# include +# endif +# if defined(VMS) && (__DECCXX_VER < 50200000) +# include +# endif +#endif // WIN32 +#include "GString.h" +#include "gfile.h" + +// Some systems don't define this, so just make it something reasonably +// large. +#ifndef PATH_MAX +#define PATH_MAX 1024 +#endif + +//------------------------------------------------------------------------ + +GString *getHomeDir() { +#ifdef VMS + //---------- VMS ---------- + return new GString("SYS$LOGIN:"); + +#elif defined(__EMX__) || defined(WIN32) + //---------- OS/2+EMX and Win32 ---------- + char *s; + GString *ret; + + if ((s = getenv("HOME"))) + ret = new GString(s); + else + ret = new GString("."); + return ret; + +#elif defined(ACORN) + //---------- RISCOS ---------- + return new GString("@"); + +#elif defined(MACOS) + //---------- MacOS ---------- + return new GString(":"); + +#else + //---------- Unix ---------- + char *s; + struct passwd *pw; + GString *ret; + + if ((s = getenv("HOME"))) { + ret = new GString(s); + } else { + if ((s = getenv("USER"))) + pw = getpwnam(s); + else + pw = getpwuid(getuid()); + if (pw) + ret = new GString(pw->pw_dir); + else + ret = new GString("."); + } + return ret; +#endif +} + +GString *getCurrentDir() { + char buf[PATH_MAX+1]; + +#if defined(__EMX__) + if (_getcwd2(buf, sizeof(buf))) +#elif defined(WIN32) + if (GetCurrentDirectory(sizeof(buf), buf)) +#elif defined(ACORN) + if (strcpy(buf, "@")) +#elif defined(MACOS) + if (strcpy(buf, ":")) +#else + if (getcwd(buf, sizeof(buf))) +#endif + return new GString(buf); + return new GString(); +} + +GString *appendToPath(GString *path, char *fileName) { +#if defined(VMS) + //---------- VMS ---------- + //~ this should handle everything necessary for file + //~ requesters, but it's certainly not complete + char *p0, *p1, *p2; + char *q1; + + p0 = path->getCString(); + p1 = p0 + path->getLength() - 1; + if (!strcmp(fileName, "-")) { + if (*p1 == ']') { + for (p2 = p1; p2 > p0 && *p2 != '.' && *p2 != '['; --p2) ; + if (*p2 == '[') + ++p2; + path->del(p2 - p0, p1 - p2); + } else if (*p1 == ':') { + path->append("[-]"); + } else { + path->clear(); + path->append("[-]"); + } + } else if ((q1 = strrchr(fileName, '.')) && !strncmp(q1, ".DIR;", 5)) { + if (*p1 == ']') { + path->insert(p1 - p0, '.'); + path->insert(p1 - p0 + 1, fileName, q1 - fileName); + } else if (*p1 == ':') { + path->append('['); + path->append(']'); + path->append(fileName, q1 - fileName); + } else { + path->clear(); + path->append(fileName, q1 - fileName); + } + } else { + if (*p1 != ']' && *p1 != ':') + path->clear(); + path->append(fileName); + } + return path; + +#elif defined(WIN32) + //---------- Win32 ---------- + GString *tmp; + char buf[256]; + char *fp; + + tmp = new GString(path); + tmp->append('/'); + tmp->append(fileName); + GetFullPathName(tmp->getCString(), sizeof(buf), buf, &fp); + delete tmp; + path->clear(); + path->append(buf); + return path; + +#elif defined(ACORN) + //---------- RISCOS ---------- + char *p; + int i; + + path->append("."); + i = path->getLength(); + path->append(fileName); + for (p = path->getCString() + i; *p; ++p) { + if (*p == '/') { + *p = '.'; + } else if (*p == '.') { + *p = '/'; + } + } + return path; + +#elif defined(MACOS) + //---------- MacOS ---------- + char *p; + int i; + + path->append(":"); + i = path->getLength(); + path->append(fileName); + for (p = path->getCString() + i; *p; ++p) { + if (*p == '/') { + *p = ':'; + } else if (*p == '.') { + *p = ':'; + } + } + return path; + +#elif defined(__EMX__) + //---------- OS/2+EMX ---------- + int i; + + // appending "." does nothing + if (!strcmp(fileName, ".")) + return path; + + // appending ".." goes up one directory + if (!strcmp(fileName, "..")) { + for (i = path->getLength() - 2; i >= 0; --i) { + if (path->getChar(i) == '/' || path->getChar(i) == '\\' || + path->getChar(i) == ':') + break; + } + if (i <= 0) { + if (path->getChar(0) == '/' || path->getChar(0) == '\\') { + path->del(1, path->getLength() - 1); + } else if (path->getLength() >= 2 && path->getChar(1) == ':') { + path->del(2, path->getLength() - 2); + } else { + path->clear(); + path->append(".."); + } + } else { + if (path->getChar(i-1) == ':') + ++i; + path->del(i, path->getLength() - i); + } + return path; + } + + // otherwise, append "/" and new path component + if (path->getLength() > 0 && + path->getChar(path->getLength() - 1) != '/' && + path->getChar(path->getLength() - 1) != '\\') + path->append('/'); + path->append(fileName); + return path; + +#else + //---------- Unix ---------- + int i; + + // appending "." does nothing + if (!strcmp(fileName, ".")) + return path; + + // appending ".." goes up one directory + if (!strcmp(fileName, "..")) { + for (i = path->getLength() - 2; i >= 0; --i) { + if (path->getChar(i) == '/') + break; + } + if (i <= 0) { + if (path->getChar(0) == '/') { + path->del(1, path->getLength() - 1); + } else { + path->clear(); + path->append(".."); + } + } else { + path->del(i, path->getLength() - i); + } + return path; + } + + // otherwise, append "/" and new path component + if (path->getLength() > 0 && + path->getChar(path->getLength() - 1) != '/') + path->append('/'); + path->append(fileName); + return path; +#endif +} + +GString *grabPath(char *fileName) { +#ifdef VMS + //---------- VMS ---------- + char *p; + + if ((p = strrchr(fileName, ']'))) + return new GString(fileName, p + 1 - fileName); + if ((p = strrchr(fileName, ':'))) + return new GString(fileName, p + 1 - fileName); + return new GString(); + +#elif defined(__EMX__) || defined(WIN32) + //---------- OS/2+EMX and Win32 ---------- + char *p; + + if ((p = strrchr(fileName, '/'))) + return new GString(fileName, p - fileName); + if ((p = strrchr(fileName, '\\'))) + return new GString(fileName, p - fileName); + if ((p = strrchr(fileName, ':'))) + return new GString(fileName, p + 1 - fileName); + return new GString(); + +#elif defined(ACORN) + //---------- RISCOS ---------- + char *p; + + if ((p = strrchr(fileName, '.'))) + return new GString(fileName, p - fileName); + return new GString(); + +#elif defined(MACOS) + //---------- MacOS ---------- + char *p; + + if ((p = strrchr(fileName, ':'))) + return new GString(fileName, p - fileName); + return new GString(); + +#else + //---------- Unix ---------- + char *p; + + if ((p = strrchr(fileName, '/'))) + return new GString(fileName, p - fileName); + return new GString(); +#endif +} + +GBool isAbsolutePath(char *path) { +#ifdef VMS + //---------- VMS ---------- + return strchr(path, ':') || + (path[0] == '[' && path[1] != '.' && path[1] != '-'); + +#elif defined(__EMX__) || defined(WIN32) + //---------- OS/2+EMX and Win32 ---------- + return path[0] == '/' || path[0] == '\\' || path[1] == ':'; + +#elif defined(ACORN) + //---------- RISCOS ---------- + return path[0] == '$'; + +#elif defined(MACOS) + //---------- MacOS ---------- + return path[0] != ':'; + +#else + //---------- Unix ---------- + return path[0] == '/'; +#endif +} + +GString *makePathAbsolute(GString *path) { +#ifdef VMS + //---------- VMS ---------- + char buf[PATH_MAX+1]; + + if (!isAbsolutePath(path->getCString())) { + if (getcwd(buf, sizeof(buf))) { + path->insert(0, buf); + } + } + return path; + +#elif defined(WIN32) + //---------- Win32 ---------- + char buf[_MAX_PATH]; + char *fp; + + buf[0] = '\0'; + if (!GetFullPathName(path->getCString(), _MAX_PATH, buf, &fp)) { + path->clear(); + return path; + } + path->clear(); + path->append(buf); + return path; + +#elif defined(ACORN) + //---------- RISCOS ---------- + path->insert(0, '@'); + return path; + +#elif defined(MACOS) + //---------- MacOS ---------- + path->del(0, 1); + return path; + +#else + //---------- Unix and OS/2+EMX ---------- + struct passwd *pw; + char buf[PATH_MAX+1]; + GString *s; + char *p1, *p2; + int n; + + if (path->getChar(0) == '~') { + if (path->getChar(1) == '/' || +#ifdef __EMX__ + path->getChar(1) == '\\' || +#endif + path->getLength() == 1) { + path->del(0, 1); + s = getHomeDir(); + path->insert(0, s); + delete s; + } else { + p1 = path->getCString() + 1; +#ifdef __EMX__ + for (p2 = p1; *p2 && *p2 != '/' && *p2 != '\\'; ++p2) ; +#else + for (p2 = p1; *p2 && *p2 != '/'; ++p2) ; +#endif + if ((n = p2 - p1) > PATH_MAX) + n = PATH_MAX; + strncpy(buf, p1, n); + buf[n] = '\0'; + if ((pw = getpwnam(buf))) { + path->del(0, p2 - p1 + 1); + path->insert(0, pw->pw_dir); + } + } + } else if (!isAbsolutePath(path->getCString())) { + if (getcwd(buf, sizeof(buf))) { +#ifndef __EMX__ + path->insert(0, '/'); +#endif + path->insert(0, buf); + } + } + return path; +#endif +} + +time_t getModTime(char *fileName) { +#ifdef WIN32 + //~ should implement this, but it's (currently) only used in xpdf + return 0; +#else + struct stat statBuf; + + if (stat(fileName, &statBuf)) { + return 0; + } + return statBuf.st_mtime; +#endif +} + +GBool openTempFile(GString **name, FILE **f, char *mode, char *ext) { +#if defined(VMS) || defined(__EMX__) || defined(WIN32) || defined(ACORN) || defined(MACOS) + //---------- non-Unix ---------- + char *s; + + // There is a security hole here: an attacker can create a symlink + // with this file name after the tmpnam call and before the fopen + // call. I will happily accept fixes to this function for non-Unix + // OSs. + if (!(s = tmpnam(NULL))) { + return gFalse; + } + *name = new GString(s); + if (ext) { + (*name)->append(ext); + } + if (!(*f = fopen((*name)->getCString(), mode))) { + delete (*name); + return gFalse; + } + return gTrue; +#else + //---------- Unix ---------- + char *s, *p; + int fd; + + if (ext) { + if (!(s = tmpnam(NULL))) { + return gFalse; + } + *name = new GString(s); + s = (*name)->getCString(); + if ((p = strrchr(s, '.'))) { + (*name)->del(p - s, (*name)->getLength() - (p - s)); + } + (*name)->append(ext); + fd = open((*name)->getCString(), O_WRONLY | O_CREAT | O_EXCL, 0600); + } else { +#if HAVE_MKSTEMP + if ((s = getenv("TMPDIR"))) { + *name = new GString(s); + } else { + *name = new GString("/tmp"); + } + (*name)->append("/XXXXXX"); + fd = mkstemp((*name)->getCString()); +#else // HAVE_MKSTEMP + if (!(s = tmpnam(NULL))) { + return gFalse; + } + *name = new GString(s); + fd = open((*name)->getCString(), O_WRONLY | O_CREAT | O_EXCL, 0600); +#endif // HAVE_MKSTEMP + } + if (fd < 0 || !(*f = fdopen(fd, mode))) { + delete *name; + return gFalse; + } + return gTrue; +#endif +} + +//------------------------------------------------------------------------ +// GDir and GDirEntry +//------------------------------------------------------------------------ + +GDirEntry::GDirEntry(char *dirPath, char *name1, GBool doStat) { +#ifdef VMS + char *p; +#elif defined(WIN32) + int fa; + GString *s; +#elif defined(ACORN) +#else + struct stat st; + GString *s; +#endif + + name = new GString(name1); + dir = gFalse; + if (doStat) { +#ifdef VMS + if (!strcmp(name1, "-") || + ((p = strrchr(name1, '.')) && !strncmp(p, ".DIR;", 5))) + dir = gTrue; +#elif defined(ACORN) +#else + s = new GString(dirPath); + appendToPath(s, name1); +#ifdef WIN32 + fa = GetFileAttributes(s->getCString()); + dir = (fa != 0xFFFFFFFF && (fa & FILE_ATTRIBUTE_DIRECTORY)); +#else + if (stat(s->getCString(), &st) == 0) + dir = S_ISDIR(st.st_mode); +#endif + delete s; +#endif + } +} + +GDirEntry::~GDirEntry() { + delete name; +} + +GDir::GDir(char *name, GBool doStat1) { + path = new GString(name); + doStat = doStat1; +#if defined(WIN32) + GString *tmp; + + tmp = path->copy(); + tmp->append("/*.*"); + hnd = FindFirstFile(tmp->getCString(), &ffd); + delete tmp; +#elif defined(ACORN) +#elif defined(MACOS) +#else + dir = opendir(name); +#ifdef VMS + needParent = strchr(name, '[') != NULL; +#endif +#endif +} + +GDir::~GDir() { + delete path; +#if defined(WIN32) + if (hnd) { + FindClose(hnd); + hnd = NULL; + } +#elif defined(ACORN) +#elif defined(MACOS) +#else + if (dir) + closedir(dir); +#endif +} + +GDirEntry *GDir::getNextEntry() { + struct dirent *ent; + GDirEntry *e; + + e = NULL; +#if defined(WIN32) + e = new GDirEntry(path->getCString(), ffd.cFileName, doStat); + if (hnd && !FindNextFile(hnd, &ffd)) { + FindClose(hnd); + hnd = NULL; + } +#elif defined(ACORN) +#elif defined(MACOS) +#else + if (dir) { +#ifdef VMS + if (needParent) { + e = new GDirEntry(path->getCString(), "-", doStat); + needParent = gFalse; + return e; + } +#endif + ent = readdir(dir); +#ifndef VMS + if (ent && !strcmp(ent->d_name, ".")) + ent = readdir(dir); +#endif + if (ent) + e = new GDirEntry(path->getCString(), ent->d_name, doStat); + } +#endif + return e; +} + +void GDir::rewind() { +#ifdef WIN32 + GString *tmp; + + if (hnd) + FindClose(hnd); + tmp = path->copy(); + tmp->append("/*.*"); + hnd = FindFirstFile(tmp->getCString(), &ffd); +#elif defined(ACORN) +#elif defined(MACOS) +#else + if (dir) + rewinddir(dir); +#ifdef VMS + needParent = strchr(path->getCString(), '[') != NULL; +#endif +#endif +} diff --git a/pdftops/gfile.h b/pdftops/gfile.h new file mode 100644 index 0000000000..b7bd3c200f --- /dev/null +++ b/pdftops/gfile.h @@ -0,0 +1,131 @@ +//======================================================================== +// +// gfile.h +// +// Miscellaneous file and directory name manipulation. +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#ifndef GFILE_H +#define GFILE_H + +#include +#include +#include +#include +#if defined(WIN32) +# include +# ifdef FPTEX +# include +# else +# include +# endif +#elif defined(ACORN) +#elif defined(MACOS) +#else +# include +# include +# ifdef VMS +# include "vms_dirent.h" +# elif HAVE_DIRENT_H +# include +# define NAMLEN(d) strlen((d)->d_name) +# else +# define dirent direct +# define NAMLEN(d) (d)->d_namlen +# if HAVE_SYS_NDIR_H +# include +# endif +# if HAVE_SYS_DIR_H +# include +# endif +# if HAVE_NDIR_H +# include +# endif +# endif +#endif +#include "gtypes.h" + +class GString; + +//------------------------------------------------------------------------ + +// Get home directory path. +extern GString *getHomeDir(); + +// Get current directory. +extern GString *getCurrentDir(); + +// Append a file name to a path string. may be an empty +// string, denoting the current directory). Returns . +extern GString *appendToPath(GString *path, char *fileName); + +// Grab the path from the front of the file name. If there is no +// directory component in , returns an empty string. +extern GString *grabPath(char *fileName); + +// Is this an absolute path or file name? +extern GBool isAbsolutePath(char *path); + +// Make this path absolute by prepending current directory (if path is +// relative) or prepending user's directory (if path starts with '~'). +GString *makePathAbsolute(GString *path); + +// Get the modification time for . Returns 0 if there is an +// error. +time_t getModTime(char *fileName); + +// Create a temporary file and open it for writing. If is not +// NULL, it will be used as the file name extension. Returns both the +// name and the file pointer. For security reasons, all writing +// should be done to the returned file pointer; the file may be +// reopened later for reading, but not for writing. The string +// should be "w" or "wb". Returns true on success. +GBool openTempFile(GString **name, FILE **f, char *mode, char *ext); + +//------------------------------------------------------------------------ +// GDir and GDirEntry +//------------------------------------------------------------------------ + +class GDirEntry { +public: + + GDirEntry(char *dirPath, char *name1, GBool doStat); + ~GDirEntry(); + GString *getName() { return name; } + GBool isDir() { return dir; } + +private: + + GString *name; // dir/file name + GBool dir; // is it a directory? +}; + +class GDir { +public: + + GDir(char *name, GBool doStat1 = gTrue); + ~GDir(); + GDirEntry *getNextEntry(); + void rewind(); + +private: + + GString *path; // directory path + GBool doStat; // call stat() for each entry? +#if defined(WIN32) + WIN32_FIND_DATA ffd; + HANDLE hnd; +#elif defined(ACORN) +#elif defined(MACOS) +#else + DIR *dir; // the DIR structure from opendir() +#ifdef VMS + GBool needParent; // need to return an entry for [-] +#endif +#endif +}; + +#endif diff --git a/pdftops/gmem.c b/pdftops/gmem.c new file mode 100644 index 0000000000..cac386bc8a --- /dev/null +++ b/pdftops/gmem.c @@ -0,0 +1,203 @@ +/* + * gmem.c + * + * Memory routines with out-of-memory checking. + * + * Copyright 1996 Derek B. Noonburg + */ + +#include +#include +#include +#include +#include "gmem.h" + +#ifdef DEBUG_MEM + +typedef struct _GMemHdr { + int size; + int index; + struct _GMemHdr *next; +} GMemHdr; + +#define gMemHdrSize ((sizeof(GMemHdr) + 7) & ~7) +#define gMemTrlSize (sizeof(long)) + +#if gmemTrlSize==8 +#define gMemDeadVal 0xdeadbeefdeadbeef +#else +#define gMemDeadVal 0xdeadbeef +#endif + +/* round data size so trailer will be aligned */ +#define gMemDataSize(size) \ + ((((size) + gMemTrlSize - 1) / gMemTrlSize) * gMemTrlSize) + +#define gMemNLists 64 +#define gMemListShift 4 +#define gMemListMask (gMemNLists - 1) +static GMemHdr *gMemList[gMemNLists] = { + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +static int gMemIndex = 0; +static int gMemAlloc = 0; + +#endif /* DEBUG_MEM */ + +void *gmalloc(int size) { +#ifdef DEBUG_MEM + int size1; + char *mem; + GMemHdr *hdr; + void *data; + int lst; + long *trl, *p; + + if (size == 0) + return NULL; + size1 = gMemDataSize(size); + if (!(mem = (char *)malloc(size1 + gMemHdrSize + gMemTrlSize))) { + fprintf(stderr, "Out of memory\n"); + exit(1); + } + hdr = (GMemHdr *)mem; + data = (void *)(mem + gMemHdrSize); + trl = (long *)(mem + gMemHdrSize + size1); + hdr->size = size; + hdr->index = gMemIndex++; + lst = ((int)hdr >> gMemListShift) & gMemListMask; + hdr->next = gMemList[lst]; + gMemList[lst] = hdr; + ++gMemAlloc; + for (p = (long *)data; p <= trl; ++p) + *p = gMemDeadVal; + return data; +#else + void *p; + + if (size == 0) + return NULL; + if (!(p = malloc(size))) { + fprintf(stderr, "Out of memory\n"); + exit(1); + } + return p; +#endif +} + +void *grealloc(void *p, int size) { +#ifdef DEBUG_MEM + GMemHdr *hdr; + void *q; + int oldSize; + + if (size == 0) { + if (p) + gfree(p); + return NULL; + } + if (p) { + hdr = (GMemHdr *)((char *)p - gMemHdrSize); + oldSize = hdr->size; + q = gmalloc(size); + memcpy(q, p, size < oldSize ? size : oldSize); + gfree(p); + } else { + q = gmalloc(size); + } + return q; +#else + void *q; + + if (size == 0) { + if (p) + free(p); + return NULL; + } + if (p) + q = realloc(p, size); + else + q = malloc(size); + if (!q) { + fprintf(stderr, "Out of memory\n"); + exit(1); + } + return q; +#endif +} + +void gfree(void *p) { +#ifdef DEBUG_MEM + int size; + GMemHdr *hdr; + GMemHdr *prevHdr, *q; + int lst; + long *trl, *clr; + + if (p) { + hdr = (GMemHdr *)((char *)p - gMemHdrSize); + lst = ((int)hdr >> gMemListShift) & gMemListMask; + for (prevHdr = NULL, q = gMemList[lst]; q; prevHdr = q, q = q->next) { + if (q == hdr) + break; + } + if (q) { + if (prevHdr) + prevHdr->next = hdr->next; + else + gMemList[lst] = hdr->next; + --gMemAlloc; + size = gMemDataSize(hdr->size); + trl = (long *)((char *)hdr + gMemHdrSize + size); + if (*trl != gMemDeadVal) { + fprintf(stderr, "Overwrite past end of block %d at address %p\n", + hdr->index, p); + } + for (clr = (long *)hdr; clr <= trl; ++clr) + *clr = gMemDeadVal; + free(hdr); + } else { + fprintf(stderr, "Attempted to free bad address %p\n", p); + } + } +#else + if (p) + free(p); +#endif +} + +#ifdef DEBUG_MEM +void gMemReport(FILE *f) { + GMemHdr *p; + int lst; + + fprintf(f, "%d memory allocations in all\n", gMemIndex); + if (gMemAlloc > 0) { + fprintf(f, "%d memory blocks left allocated:\n", gMemAlloc); + fprintf(f, " index size\n"); + fprintf(f, "-------- --------\n"); + for (lst = 0; lst < gMemNLists; ++lst) { + for (p = gMemList[lst]; p; p = p->next) + fprintf(f, "%8d %8d\n", p->index, p->size); + } + } else { + fprintf(f, "No memory blocks left allocated\n"); + } +} +#endif + +char *copyString(char *s) { + char *s1; + + s1 = (char *)gmalloc(strlen(s) + 1); + strcpy(s1, s); + return s1; +} diff --git a/pdftops/gmem.h b/pdftops/gmem.h new file mode 100644 index 0000000000..7ab5ddbeb8 --- /dev/null +++ b/pdftops/gmem.h @@ -0,0 +1,53 @@ +/* + * gmem.h + * + * Memory routines with out-of-memory checking. + * + * Copyright 1996 Derek B. Noonburg + */ + +#ifndef GMEM_H +#define GMEM_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Same as malloc, but prints error message and exits if malloc() + * returns NULL. + */ +extern void *gmalloc(int size); + +/* + * Same as realloc, but prints error message and exits if realloc() + * returns NULL. If

is NULL, calls malloc instead of realloc(). + */ +extern void *grealloc(void *p, int size); + +/* + * Same as free, but checks for and ignores NULL pointers. + */ +extern void gfree(void *p); + +#ifdef DEBUG_MEM +/* + * Report on unfreed memory. + */ +extern void gMemReport(FILE *f); +#else +#define gMemReport(f) +#endif + +/* + * Allocate memory and copy a string into it. + */ +extern char *copyString(char *s); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/pdftops/gmempp.cxx b/pdftops/gmempp.cxx new file mode 100644 index 0000000000..6eb64948da --- /dev/null +++ b/pdftops/gmempp.cxx @@ -0,0 +1,31 @@ +//======================================================================== +// +// gmempp.cc +// +// Use gmalloc/gfree for C++ new/delete operators. +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#include "gmem.h" + +#ifdef DEBUG_MEM + +void *operator new(size_t size) { + return gmalloc((int)size); +} + +void *operator new[](size_t size) { + return gmalloc((int)size); +} + +void operator delete(void *p) { + gfree(p); +} + +void operator delete[](void *p) { + gfree(p); +} + +#endif diff --git a/pdftops/gtypes.h b/pdftops/gtypes.h new file mode 100644 index 0000000000..6593267414 --- /dev/null +++ b/pdftops/gtypes.h @@ -0,0 +1,29 @@ +/* + * gtypes.h + * + * Some useful simple types. + * + * Copyright 1996 Derek B. Noonburg + */ + +#ifndef GTYPES_H +#define GTYPES_H + +/* + * These have stupid names to avoid conflicts with some (but not all) + * C++ compilers which define them. + */ +typedef int GBool; +#define gTrue 1 +#define gFalse 0 + +/* + * These have stupid names to avoid conflicts with , + * which on various systems defines some random subset of these. + */ +typedef unsigned char Guchar; +typedef unsigned short Gushort; +typedef unsigned int Guint; +typedef unsigned long Gulong; + +#endif diff --git a/pdftops/parseargs.c b/pdftops/parseargs.c new file mode 100644 index 0000000000..ceba887796 --- /dev/null +++ b/pdftops/parseargs.c @@ -0,0 +1,190 @@ +/* + * parseargs.h + * + * Command line argument parser. + * + * Copyright 1996 Derek B. Noonburg + */ + +#include +#include +#include +#include +#include +#include "parseargs.h" + +static ArgDesc *findArg(ArgDesc *args, char *arg); +static GBool grabArg(ArgDesc *arg, int i, int *argc, char *argv[]); + +GBool parseArgs(ArgDesc *args, int *argc, char *argv[]) { + ArgDesc *arg; + int i, j; + GBool ok; + + ok = gTrue; + i = 1; + while (i < *argc) { + if (!strcmp(argv[i], "--")) { + --*argc; + for (j = i; j < *argc; ++j) + argv[j] = argv[j+1]; + break; + } else if ((arg = findArg(args, argv[i]))) { + if (!grabArg(arg, i, argc, argv)) + ok = gFalse; + } else { + ++i; + } + } + return ok; +} + +void printUsage(char *program, char *otherArgs, ArgDesc *args) { + ArgDesc *arg; + char *typ; + int w, w1; + + w = 0; + for (arg = args; arg->arg; ++arg) { + if ((w1 = strlen(arg->arg)) > w) + w = w1; + } + + fprintf(stderr, "Usage: %s [options]", program); + if (otherArgs) + fprintf(stderr, " %s", otherArgs); + fprintf(stderr, "\n"); + + for (arg = args; arg->arg; ++arg) { + fprintf(stderr, " %s", arg->arg); + w1 = 9 + w - strlen(arg->arg); + switch (arg->kind) { + case argInt: + case argIntDummy: + typ = " "; + break; + case argFP: + case argFPDummy: + typ = " "; + break; + case argString: + case argStringDummy: + typ = " "; + break; + case argFlag: + case argFlagDummy: + default: + typ = ""; + break; + } + fprintf(stderr, "%-*s", w1, typ); + if (arg->usage) + fprintf(stderr, ": %s", arg->usage); + fprintf(stderr, "\n"); + } +} + +static ArgDesc *findArg(ArgDesc *args, char *arg) { + ArgDesc *p; + + for (p = args; p->arg; ++p) { + if (p->kind < argFlagDummy && !strcmp(p->arg, arg)) + return p; + } + return NULL; +} + +static GBool grabArg(ArgDesc *arg, int i, int *argc, char *argv[]) { + int n; + int j; + GBool ok; + + ok = gTrue; + n = 0; + switch (arg->kind) { + case argFlag: + *(GBool *)arg->val = gTrue; + n = 1; + break; + case argInt: + if (i + 1 < *argc && isInt(argv[i+1])) { + *(int *)arg->val = atoi(argv[i+1]); + n = 2; + } else { + ok = gFalse; + n = 1; + } + break; + case argFP: + if (i + 1 < *argc && isFP(argv[i+1])) { + *(double *)arg->val = atof(argv[i+1]); + n = 2; + } else { + ok = gFalse; + n = 1; + } + break; + case argString: + if (i + 1 < *argc) { + strncpy((char *)arg->val, argv[i+1], arg->size - 1); + ((char *)arg->val)[arg->size - 1] = '\0'; + n = 2; + } else { + ok = gFalse; + n = 1; + } + break; + default: + fprintf(stderr, "Internal error in arg table\n"); + n = 1; + break; + } + if (n > 0) { + *argc -= n; + for (j = i; j < *argc; ++j) + argv[j] = argv[j+n]; + } + return ok; +} + +GBool isInt(char *s) { + if (*s == '-' || *s == '+') + ++s; + while (isdigit(*s)) + ++s; + if (*s) + return gFalse; + return gTrue; +} + +GBool isFP(char *s) { + int n; + + if (*s == '-' || *s == '+') + ++s; + n = 0; + while (isdigit(*s)) { + ++s; + ++n; + } + if (*s == '.') + ++s; + while (isdigit(*s)) { + ++s; + ++n; + } + if (n > 0 && (*s == 'e' || *s == 'E')) { + ++s; + if (*s == '-' || *s == '+') + ++s; + n = 0; + if (!isdigit(*s)) + return gFalse; + do { + ++s; + } while (isdigit(*s)); + } + if (*s) + return gFalse; + return gTrue; +} diff --git a/pdftops/parseargs.h b/pdftops/parseargs.h new file mode 100644 index 0000000000..e0aa2be33d --- /dev/null +++ b/pdftops/parseargs.h @@ -0,0 +1,71 @@ +/* + * parseargs.h + * + * Command line argument parser. + * + * Copyright 1996 Derek B. Noonburg + */ + +#ifndef PARSEARGS_H +#define PARSEARGS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "gtypes.h" + +/* + * Argument kinds. + */ +typedef enum { + argFlag, /* flag (present / not-present) */ + /* [val: GBool *] */ + argInt, /* integer arg */ + /* [val: int *] */ + argFP, /* floating point arg */ + /* [val: double *] */ + argString, /* string arg */ + /* [val: char *] */ + /* dummy entries -- these show up in the usage listing only; */ + /* useful for X args, for example */ + argFlagDummy, + argIntDummy, + argFPDummy, + argStringDummy +} ArgKind; + +/* + * Argument descriptor. + */ +typedef struct { + char *arg; /* the command line switch */ + ArgKind kind; /* kind of arg */ + void *val; /* place to store value */ + int size; /* for argString: size of string */ + char *usage; /* usage string */ +} ArgDesc; + +/* + * Parse command line. Removes all args which are found in the arg + * descriptor list . Stops parsing if "--" is found (and removes + * it). Returns gFalse if there was an error. + */ +extern GBool parseArgs(ArgDesc *args, int *argc, char *argv[]); + +/* + * Print usage message, based on arg descriptor list. + */ +extern void printUsage(char *program, char *otherArgs, ArgDesc *args); + +/* + * Check if a string is a valid integer or floating point number. + */ +extern GBool isInt(char *s); +extern GBool isFP(char *s); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/pdftops/pdftops.cxx b/pdftops/pdftops.cxx new file mode 100644 index 0000000000..affffd734a --- /dev/null +++ b/pdftops/pdftops.cxx @@ -0,0 +1,141 @@ +//======================================================================== +// +// pdftops.cc +// +// Copyright 1996 Derek B. Noonburg +// +//======================================================================== + +#include +#include +#include +#include +#include +#include "parseargs.h" +#include "GString.h" +#include "gmem.h" +#include "Object.h" +#include "Stream.h" +#include "Array.h" +#include "Dict.h" +#include "XRef.h" +#include "Catalog.h" +#include "Page.h" +#include "PDFDoc.h" +#include "PSOutputDev.h" +#include "Params.h" +#include "Error.h" +#include "config.h" +#include + + +int main(int argc, char *argv[]) { + PDFDoc *doc; + GString *fileName; + PSOutputDev *psOut; + int num_options; + cups_option_t *options; + ppd_file_t *ppd; + ppd_size_t *size; + FILE *fp; + char tempfile[1024]; + char buffer[8192]; + int bytes; + + + // Make sure we have the right number of arguments for CUPS! + if (argc < 6 || argc > 7) + { + fputs("Usage: pdftops job user title copies options [filename]\n", stderr); + return (1); + } + + // Copy stdin if needed... + if (argc == 6) + { + if ((fp = fopen(cupsTempFile(tempfile, sizeof(tempfile)), "w")) == NULL) + { + perror("ERROR: Unable to copy PDF file"); + return (1); + } + + fprintf(stderr, "DEBUG: pdftops - copying to temp print file \"%s\"\n", + tempfile); + + while ((bytes = fread(buffer, 1, sizeof(buffer), stdin)) > 0) + fwrite(buffer, 1, bytes, fp); + fclose(fp); + + fileName = new GString(tempfile); + } + else + { + fileName = new GString(argv[6]); + tempfile[0] = '\0'; + } + + // Get PPD and initialize options as needed... + if ((ppd = ppdOpenFile(getenv("PPD"))) != NULL) + { + fprintf(stderr, "DEBUG: pdftops - opened PPD file \"%s\"...\n", getenv("PPD")); + + ppdMarkDefaults(ppd); + num_options = cupsParseOptions(argv[5], 0, &options); + cupsMarkOptions(ppd, num_options, options); + cupsFreeOptions(num_options, options); + + if ((size = ppdPageSize(ppd, NULL)) != NULL) + { + paperWidth = (int)size->width; + paperHeight = (int)size->length; + } + + psOutLevel1 = ppd->language_level == 1; + + fprintf(stderr, "DEBUG: pstops - psOutLevel1 = %d, paperWidth = %d, paperHeight = %d\n", + psOutLevel1, paperWidth, paperHeight); + + ppdClose(ppd); + } + + // init error file + errorInit(); + + // read config file + initParams(CUPS_SERVERROOT "/xpdf.conf"); + + // open PDF file + xref = NULL; + doc = new PDFDoc(fileName, NULL); + if (!doc->isOk()) { + goto err1; + } + + // check for print permission + if (!doc->okToPrint()) { + error(-1, "Printing this document is not allowed."); + goto err1; + } + + // write PostScript file + psOut = new PSOutputDev("-", doc->getCatalog(), 1, doc->getNumPages(), 1, 0); + if (psOut->isOk()) + doc->displayPages(psOut, 1, doc->getNumPages(), 72, 0, gFalse); + + delete psOut; + + // clean up + delete doc; + err1: + freeParams(); + + // check for memory leaks + Object::memCheck(stderr); + gMemReport(stderr); + + // Remove temp file if needed... + if (tempfile[0]) + unlink(tempfile); + + return 0; +} diff --git a/ppd/Makefile b/ppd/Makefile new file mode 100644 index 0000000000..e31be5474c --- /dev/null +++ b/ppd/Makefile @@ -0,0 +1,57 @@ +# +# "$Id$" +# +# PPD file 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 + +# +# PPD files... +# + +FILES = deskjet.ppd epson9.ppd epson24.ppd laserjet.ppd \ + okidata9.ppd okidat24.ppd stcolor.ppd stphoto.ppd + +# +# Make everything... +# + +all: + +# +# Clean all config and object files... +# + +clean: + +# +# Install files... +# + +install: + -$(MKDIR) $(DATADIR)/model + $(CHMOD) ugo+rx $(DATADIR)/model + $(INSTALL_DATA) $(FILES) $(DATADIR)/model + +# +# End of "$Id$". +# diff --git a/ppd/deskjet.ppd b/ppd/deskjet.ppd new file mode 100644 index 0000000000..ae33eead3f --- /dev/null +++ b/ppd/deskjet.ppd @@ -0,0 +1,196 @@ +*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: "(3010.000) 550" +*LanguageLevel: "3" +*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 Tabloid *InputSlot Envelope +*UIConstraints: *PageSize A3 *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/US Letter: "<>setpagedevice" +*PageSize Legal/US Legal: "<>setpagedevice" +*PageSize Executive/US Executive: "<>setpagedevice" +*PageSize Tabloid/US Tabloid: "<>setpagedevice" +*PageSize A3/A3: "<>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/US Letter: "<>setpagedevice" +*PageRegion Legal/US Legal: "<>setpagedevice" +*PageRegion Executive/US Executive: "<>setpagedevice" +*PageRegion Tabloid/US Tabloid: "<>setpagedevice" +*PageRegion A3/A3: "<>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/US Executive: "18 36 504 684" +*ImageableArea Tabloid/US Tabloid: "18 36 774 1188" +*ImageableArea A3/A3: "18 36 824 1155" +*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/US Letter: "612 792" +*PaperDimension Legal/US Legal: "612 1008" +*PaperDimension Executive/US Executive: "522 756" +*PaperDimension Tabloid/US Tabloid: "792 1224" +*PaperDimension A3/A3: "842 1191" +*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/epson24.ppd b/ppd/epson24.ppd new file mode 100644 index 0000000000..4024a22d4f --- /dev/null +++ b/ppd/epson24.ppd @@ -0,0 +1,128 @@ +*PPD-Adobe: "4.3" +*% +*% "$Id$" +*% +*% Sample EPSON 24-Pin 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: "EPSON24.PPD" +*Manufacturer: "ESP" +*Product: "(CUPS v1.1)" +*cupsVersion: 1.1 +*cupsManualCopies: True +*cupsModelNumber: 1 +*cupsFilter: "application/vnd.cups-raster 0 rastertoepson" +*ModelName: "EPSON 24-Pin Series" +*ShortNickName: "EPSON 24-Pin Series" +*NickName: "EPSON 24-Pin Series CUPS v1.1" +*PSVersion: "(3010.000) 550" +*LanguageLevel: "3" +*ColorDevice: False +*DefaultColorSpace: Gray +*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" +*PageSize FanFoldUS: "<>setpagedevice" +*CloseUI: *PageSize + +*OpenUI *PageRegion: PickOne +*OrderDependency: 10 AnySetup *PageRegion +*DefaultPageRegion: Letter +*PageRegion Letter: "<>setpagedevice" +*PageRegion Legal: "<>setpagedevice" +*PageRegion A4: "<>setpagedevice" +*PageRegion FanFoldUS: "<>setpagedevice" +*CloseUI: *PageRegion + +*DefaultImageableArea: Letter +*ImageableArea Letter: "18.0 18.0 594.0 774.0" +*ImageableArea Legal: "18.0 18.0 594.0 990.0" +*ImageableArea A4: "18.0 18.0 577.0 824.0" +*ImageableArea FanFoldUS: "18.0 18.0 1053.0 774.0" + +*DefaultPaperDimension: Letter +*PaperDimension Letter: "612 792" +*PaperDimension Legal: "612 1008" +*PaperDimension A4: "595 842" +*PaperDimension FanFoldUS: "1071 792" + +*OpenUI *Resolution/Output Resolution: PickOne +*OrderDependency: 20 AnySetup *Resolution +*DefaultResolution: 120dpi +*Resolution 60dpi/60 DPI: "<>setpagedevice" +*Resolution 120dpi/120x60 DPI: "<>setpagedevice" +*Resolution 180dpi/180 DPI: "<>setpagedevice" +*Resolution 360x180dpi/360x180 DPI: "<>setpagedevice" +*Resolution 360dpi/360 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/epson9.ppd b/ppd/epson9.ppd new file mode 100644 index 0000000000..7bd9d6ac5c --- /dev/null +++ b/ppd/epson9.ppd @@ -0,0 +1,126 @@ +*PPD-Adobe: "4.3" +*% +*% "$Id$" +*% +*% Sample EPSON 9-Pin 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: "EPSON9.PPD" +*Manufacturer: "ESP" +*Product: "(CUPS v1.1)" +*cupsVersion: 1.1 +*cupsManualCopies: True +*cupsModelNumber: 0 +*cupsFilter: "application/vnd.cups-raster 0 rastertoepson" +*ModelName: "EPSON 9-Pin Series" +*ShortNickName: "EPSON 9-Pin Series" +*NickName: "EPSON 9-Pin Series CUPS v1.1" +*PSVersion: "(3010.000) 550" +*LanguageLevel: "3" +*ColorDevice: False +*DefaultColorSpace: Gray +*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" +*PageSize FanFoldUS: "<>setpagedevice" +*CloseUI: *PageSize + +*OpenUI *PageRegion: PickOne +*OrderDependency: 10 AnySetup *PageRegion +*DefaultPageRegion: Letter +*PageRegion Letter: "<>setpagedevice" +*PageRegion Legal: "<>setpagedevice" +*PageRegion A4: "<>setpagedevice" +*PageRegion FanFoldUS: "<>setpagedevice" +*CloseUI: *PageRegion + +*DefaultImageableArea: Letter +*ImageableArea Letter: "18.0 18.0 594.0 774.0" +*ImageableArea Legal: "18.0 18.0 594.0 990.0" +*ImageableArea A4: "18.0 18.0 577.0 824.0" +*ImageableArea FanFoldUS: "18.0 18.0 1053.0 774.0" + +*DefaultPaperDimension: Letter +*PaperDimension Letter: "612 792" +*PaperDimension Legal: "612 1008" +*PaperDimension A4: "595 842" +*PaperDimension FanFoldUS: "1071 792" + +*OpenUI *Resolution/Output Resolution: PickOne +*OrderDependency: 20 AnySetup *Resolution +*DefaultResolution: 120dpi +*Resolution 60dpi/60x72 DPI: "<>setpagedevice" +*Resolution 120dpi/120x72 DPI: "<>setpagedevice" +*Resolution 240dpi/240x72 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/laserjet.ppd b/ppd/laserjet.ppd new file mode 100644 index 0000000000..8d1d13b3c2 --- /dev/null +++ b/ppd/laserjet.ppd @@ -0,0 +1,199 @@ +*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: "(3010.000) 550" +*LanguageLevel: "3" +*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 Tabloid *InputSlot Envelope +*UIConstraints: *PageSize A3 *InputSlot Envelope +*UIConstraints: *PageSize A4 *InputSlot Envelope +*UIConstraints: *PageSize A5 *InputSlot Envelope +*UIConstraints: *PageSize B5 *InputSlot Envelope +*UIConstraints: *Duplex *Option1 False + +*OpenUI *PageSize/Media Size: PickOne +*OrderDependency: 10 AnySetup *PageSize +*DefaultPageSize: Letter +*PageSize Letter/US Letter: "<>setpagedevice" +*PageSize Legal/US Legal: "<>setpagedevice" +*PageSize Executive/US Executive: "<>setpagedevice" +*PageSize Tabloid/US Tabloid: "<>setpagedevice" +*PageSize A3/A3: "<>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/US Letter: "<>setpagedevice" +*PageRegion Legal/US Legal: "<>setpagedevice" +*PageRegion Executive/US Executive: "<>setpagedevice" +*PageRegion Tabloid/US Tabloid: "<>setpagedevice" +*PageRegion A3/A3: "<>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/US Executive: "18 36 504 684" +*ImageableArea Tabloid/US Tabloid: "18 36 774 1188" +*ImageableArea A3/A3: "18 36 824 1155" +*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/US Letter: "612 792" +*PaperDimension Legal/US Legal: "612 1008" +*PaperDimension Executive/US Executive: "522 756" +*PaperDimension Tabloid/US Tabloid: "792 1224" +*PaperDimension A3/A3: "842 1191" +*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 + +*OpenUI *Duplex/Double-Sided Printing: PickOne +*OrderDependency: 20 AnySetup *Duplex +*DefaultDuplex: None +*Duplex None/Off: "<>setpagedevice" +*Duplex DuplexNoTumble/Long Edge (Standard): "<>setpagedevice" +*Duplex DuplexTumble/Short Edge (Flip): "<>setpagedevice" +*CloseUI: *Duplex + +*OpenGroup: InstallableOptions +*OpenUI *Option1/Duplexer: Boolean +*DefaultOption1: False +*Option1 True/Installed: "" +*Option1 False/Not Installed: "" +*CloseUI *Option1 +*CloseGroup: InstallableOptions + +*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/okidat24.ppd b/ppd/okidat24.ppd new file mode 100644 index 0000000000..b34a1b2614 --- /dev/null +++ b/ppd/okidat24.ppd @@ -0,0 +1,128 @@ +*PPD-Adobe: "4.3" +*% +*% "$Id$" +*% +*% Sample OKIDATA 24-Pin 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: "OKIDAT24.PPD" +*Manufacturer: "ESP" +*Product: "(CUPS v1.1)" +*cupsVersion: 1.1 +*cupsManualCopies: True +*cupsModelNumber: 1 +*cupsFilter: "application/vnd.cups-raster 0 rastertoepson" +*ModelName: "OKIDATA 24-Pin Series" +*ShortNickName: "OKIDATA 24-Pin Series" +*NickName: "OKIDATA 24-Pin Series CUPS v1.1" +*PSVersion: "(3010.000) 550" +*LanguageLevel: "3" +*ColorDevice: False +*DefaultColorSpace: Gray +*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" +*PageSize FanFoldUS: "<>setpagedevice" +*CloseUI: *PageSize + +*OpenUI *PageRegion: PickOne +*OrderDependency: 10 AnySetup *PageRegion +*DefaultPageRegion: Letter +*PageRegion Letter: "<>setpagedevice" +*PageRegion Legal: "<>setpagedevice" +*PageRegion A4: "<>setpagedevice" +*PageRegion FanFoldUS: "<>setpagedevice" +*CloseUI: *PageRegion + +*DefaultImageableArea: Letter +*ImageableArea Letter: "18.0 18.0 594.0 774.0" +*ImageableArea Legal: "18.0 18.0 594.0 990.0" +*ImageableArea A4: "18.0 18.0 577.0 824.0" +*ImageableArea FanFoldUS: "18.0 18.0 1053.0 774.0" + +*DefaultPaperDimension: Letter +*PaperDimension Letter: "612 792" +*PaperDimension Legal: "612 1008" +*PaperDimension A4: "595 842" +*PaperDimension FanFoldUS: "1071 792" + +*OpenUI *Resolution/Output Resolution: PickOne +*OrderDependency: 20 AnySetup *Resolution +*DefaultResolution: 120dpi +*Resolution 60dpi/60 DPI: "<>setpagedevice" +*Resolution 120dpi/120x60 DPI: "<>setpagedevice" +*Resolution 180dpi/180 DPI: "<>setpagedevice" +*Resolution 360x180dpi/360x180 DPI: "<>setpagedevice" +*Resolution 360dpi/360 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/okidata9.ppd b/ppd/okidata9.ppd new file mode 100644 index 0000000000..a4238380f7 --- /dev/null +++ b/ppd/okidata9.ppd @@ -0,0 +1,126 @@ +*PPD-Adobe: "4.3" +*% +*% "$Id$" +*% +*% Sample OKIDATA 9-Pin 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: "OKIDATA9.PPD" +*Manufacturer: "ESP" +*Product: "(CUPS v1.1)" +*cupsVersion: 1.1 +*cupsManualCopies: True +*cupsModelNumber: 0 +*cupsFilter: "application/vnd.cups-raster 0 rastertoepson" +*ModelName: "OKIDATA 9-Pin Series" +*ShortNickName: "OKIDATA 9-Pin Series" +*NickName: "OKIDATA 9-Pin Series CUPS v1.1" +*PSVersion: "(3010.000) 550" +*LanguageLevel: "3" +*ColorDevice: False +*DefaultColorSpace: Gray +*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" +*PageSize FanFoldUS: "<>setpagedevice" +*CloseUI: *PageSize + +*OpenUI *PageRegion: PickOne +*OrderDependency: 10 AnySetup *PageRegion +*DefaultPageRegion: Letter +*PageRegion Letter: "<>setpagedevice" +*PageRegion Legal: "<>setpagedevice" +*PageRegion A4: "<>setpagedevice" +*PageRegion FanFoldUS: "<>setpagedevice" +*CloseUI: *PageRegion + +*DefaultImageableArea: Letter +*ImageableArea Letter: "18.0 18.0 594.0 774.0" +*ImageableArea Legal: "18.0 18.0 594.0 990.0" +*ImageableArea A4: "18.0 18.0 577.0 824.0" +*ImageableArea FanFoldUS: "18.0 18.0 1053.0 774.0" + +*DefaultPaperDimension: Letter +*PaperDimension Letter: "612 792" +*PaperDimension Legal: "612 1008" +*PaperDimension A4: "595 842" +*PaperDimension FanFoldUS: "1071 792" + +*OpenUI *Resolution/Output Resolution: PickOne +*OrderDependency: 20 AnySetup *Resolution +*DefaultResolution: 120dpi +*Resolution 60dpi/60x72 DPI: "<>setpagedevice" +*Resolution 120dpi/120x72 DPI: "<>setpagedevice" +*Resolution 240dpi/240x72 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..43c68f3970 --- /dev/null +++ b/ppd/stcolor.ppd @@ -0,0 +1,132 @@ +*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 +*cupsModelNumber: 2 +*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: "(3010.000) 550" +*LanguageLevel: "3" +*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..ec5c8a0f02 --- /dev/null +++ b/ppd/stphoto.ppd @@ -0,0 +1,132 @@ +*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 +*cupsModelNumber: 3 +*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: "(3010.000) 550" +*LanguageLevel: "3" +*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..2377b5fd23 --- /dev/null +++ b/pstoraster/Makefile @@ -0,0 +1,427 @@ +# +# "$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 = gconfig.o \ + gdevabuf.o \ + gdevbbox.o \ + gdevcups.o \ + gdevdbit.o \ + gdevddrw.o \ + gdevdflt.o \ + gdevdgbr.o \ + gdevhit.o \ + gdevm16.o \ + gdevm1.o \ + gdevm24.o \ + gdevm2.o \ + gdevm32.o \ + gdevm4.o \ + gdevm8.o \ + gdevmem.o \ + gdevmpla.o \ + gdevnfwd.o \ + gdevpipe.o \ + gdevprn.o \ + gp_getnv.o \ + gp_nofb.o \ + gp_nsync.o \ + gp_unifn.o \ + gp_unifs.o \ + gp_unix.o \ + gsalloc.o \ + gsalpha.o \ + gsargs.o \ + gsbitops.o \ + gsbittab.o \ + gscdefs.o \ + gscdevn.o \ + gschar0.o \ + gschar.o \ + gscie.o \ + gsclipsr.o \ + gscolor1.o \ + gscolor2.o \ + gscolor3.o \ + gscolor.o \ + gscoord.o \ + gscparam.o \ + gscpixel.o \ + gscrdp.o \ + gscrd.o \ + gscscie.o \ + gscsepr.o \ + gscspace.o \ + gsdevice.o \ + gsdevmem.o \ + gsdparam.o \ + gsdps1.o \ + gsdsrc.o \ + gsfcmap.o \ + gsfont0.o \ + gsfont.o \ + gsfunc0.o \ + gsfunc3.o \ + gsfunc.o \ + gshsb.o \ + gsht1.o \ + gshtscr.o \ + gsht.o \ + gsimage.o \ + gsimpath.o \ + gsinit.o \ + gsiodev.o \ + gsline.o \ + gsmalloc.o \ + gsmatrix.o \ + gsmemory.o \ + gsmisc.o \ + gsnorop.o \ + gspaint.o \ + gsparams.o \ + gsparam.o \ + gspath1.o \ + gspath.o \ + gspcolor.o \ + gsshade.o \ + gsstate.o \ + gstext.o \ + gstrap.o \ + gstype1.o \ + gstype2.o \ + gstype42.o \ + gsutil.o \ + gxacpath.o \ + gxbcache.o \ + gxccache.o \ + gxccman.o \ + gxcht.o \ + gxclbits.o \ + gxclimag.o \ + gxclip2.o \ + gxclipm.o \ + gxclip.o \ + gxclist.o \ + gxclmem.o \ + gxclpage.o \ + gxclpath.o \ + gxclrast.o \ + gxclread.o \ + gxclrect.o \ + gxclutil.o \ + gxclzlib.o \ + gxcmap.o \ + gxcpath.o \ + gxctable.o \ + gxdcconv.o \ + gxdcolor.o \ + gxdither.o \ + gxfill.o \ + gxhint1.o \ + gxhint2.o \ + gxhint3.o \ + gxht.o \ + gxi12bit.o \ + gxicolor.o \ + gxidata.o \ + gxifast.o \ + gxiinit.o \ + gximage3.o \ + gximage4.o \ + gximono.o \ + gxiscale.o \ + gxmclip.o \ + gxp1fill.o \ + gxpaint.o \ + gxpath2.o \ + gxpath.o \ + gxpcmap.o \ + gxpcopy.o \ + gxpdash.o \ + gxpflat.o \ + gxsample.o \ + gxshade1.o \ + gxshade4.o \ + gxshade6.o \ + gxshade.o \ + gxstroke.o \ + gxtype1.o \ + ialloc.o \ + ibnum.o \ + iccinit0.o \ + iconfig.o \ + icontext.o \ + idebug.o \ + idict.o \ + idparam.o \ + idstack.o \ + igcref.o \ + igcstr.o \ + igc.o \ + iinit.o \ + ilocate.o \ + imainarg.o \ + imain.o \ + iname.o \ + interp.o \ + iparam.o \ + ireclaim.o \ + isave.o \ + iscanbin.o \ + iscannum.o \ + iscan.o \ + istack.o \ + iutil2.o \ + iutil.o \ + sbcp.o \ + sbhc.o \ + sbwbs.o \ + scantab.o \ + scfdtab.o \ + scfd.o \ + scfetab.o \ + scfe.o \ + scfparam.o \ + sdcparam.o \ + sdctc.o \ + sdctd.o \ + sdcte.o \ + sddparam.o \ + sdeparam.o \ + seexec.o \ + sfilter1.o \ + sfilter2.o \ + sfxstdio.o \ + shcgen.o \ + shc.o \ + siscale.o \ + sjpegc.o \ + sjpegd.o \ + sjpegerr.o \ + sjpege.o \ + slzwce.o \ + slzwc.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 \ + zcfont.o \ + zchar1.o \ + zchar2.o \ + zchar32.o \ + zchar42.o \ + zcharout.o \ + zchar.o \ + zcid.o \ + zcie.o \ + zcolor1.o \ + zcolor2.o \ + zcolor.o \ + zcontrol.o \ + zcrd.o \ + zcsdevn.o \ + zcsindex.o \ + zcspixel.o \ + zcssepr.o \ + zdevcal.o \ + zdevice2.o \ + zdevice.o \ + zdict.o \ + zdps1.o \ + zfbcp.o \ + zfcmap.o \ + zfdctd.o \ + zfdcte.o \ + zfdecode.o \ + zfileio.o \ + zfile.o \ + zfilter2.o \ + zfilterx.o \ + zfilter.o \ + zfname.o \ + zfont0.o \ + zfont1.o \ + zfont2.o \ + zfont32.o \ + zfont42.o \ + zfont.o \ + zfproc.o \ + zfreuse.o \ + zfunc0.o \ + zfunc3.o \ + zfunc.o \ + zfzlib.o \ + zgeneric.o \ + zgstate.o \ + zhsb.o \ + zht1.o \ + zht2.o \ + zht.o \ + zimage2.o \ + zimage3.o \ + zimage.o \ + ziodev2.o \ + ziodev.o \ + zmath.o \ + zmatrix.o \ + zmedia2.o \ + zmisc1.o \ + zmisc2.o \ + zmisc3.o \ + zmisc.o \ + zpacked.o \ + zpaint.o \ + zpath1.o \ + zpath.o \ + zpcolor.o \ + zrelbit.o \ + zshade.o \ + zstack.o \ + zstring.o \ + zsysvm.o \ + ztoken.o \ + ztrap.o \ + ztype.o \ + zupath.o \ + zusparam.o \ + zvmem2.o \ + zvmem.o + +OBJS = $(LIBOBJS) genarch.o pstoraster.o + +# +# Data files... +# + +DFILES = Fontmap \ + gs_btokn.ps gs_ccfnt.ps gs_cff.ps gs_cidfn.ps \ + gs_cmap.ps gs_cmdl.ps gs_dbt_e.ps gs_diskf.ps \ + gs_dpnxt.ps gs_dps1.ps gs_dps2.ps gs_dps.ps gs_epsf.ps \ + gs_fform.ps gs_fonts.ps gs_init.ps gs_iso_e.ps \ + gs_kanji.ps gs_ksb_e.ps gs_lev2.ps gs_ll3.ps \ + gs_mex_e.ps gs_mro_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_typ32.ps gs_typ42.ps gs_type1.ps \ + gs_wan_e.ps gs_wl1_e.ps gs_wl2_e.ps gs_wl5_e.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 + $(CHMOD) ugo+rx $(SERVERBIN) + $(CHMOD) ugo+rx $(SERVERBIN)/filter + $(INSTALL_BIN) pstoraster $(SERVERBIN)/filter + -$(MKDIR) $(DATADIR)/pstoraster + $(CHMOD) ugo+rx $(DATADIR) + $(CHMOD) ugo+rx $(DATADIR)/pstoraster + $(INSTALL_DATA) $(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 +$(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 \ + $(LINKCUPSIMAGE) $(IMGLIBS) $(DSOLIBS) $(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..7adae17ded --- /dev/null +++ b/pstoraster/bfont.h @@ -0,0 +1,76 @@ +/* Copyright (C) 1992, 1995, 1996, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Interpreter internal routines and data needed for building fonts */ +/* Requires gxfont.h */ + +#ifndef bfont_INCLUDED +# define bfont_INCLUDED + +#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; + +/* Options for collecting parameters from a font dictionary. */ +/* The comment indicates where the option is tested. */ +typedef enum { + bf_options_none = 0, + bf_Encoding_optional = 1, /* build_gs_font */ + bf_FontBBox_required = 2, /* build_gs_simple_font */ + bf_UniqueID_ignored = 4, /* build_gs_simple_font */ + bf_CharStrings_optional = 8, /* build_gs_primitive_font */ + bf_notdef_required = 16 /* build_gs_primitive_font */ +} build_font_options_t; + +/* In zfont2.c */ +int build_proc_name_refs(P3(build_proc_refs * pbuild, + const char *bcstr, + const char *bgstr)); +int build_gs_font_procs(P2(os_ptr, build_proc_refs *)); +int build_gs_primitive_font(P6(os_ptr, gs_font_base **, font_type, + gs_memory_type_ptr_t, const build_proc_refs *, + build_font_options_t)); +int build_gs_simple_font(P6(os_ptr, gs_font_base **, font_type, + gs_memory_type_ptr_t, const build_proc_refs *, + build_font_options_t)); +void lookup_gs_simple_font_encoding(P1(gs_font_base *)); +int build_gs_font(P6(os_ptr, gs_font **, font_type, + gs_memory_type_ptr_t, const build_proc_refs *, + build_font_options_t)); +int define_gs_font(P1(gs_font *)); + +#endif /* bfont_INCLUDED */ 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..ac798ef9cf --- /dev/null +++ b/pstoraster/btoken.h @@ -0,0 +1,41 @@ +/* Copyright (C) 1990, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Definitions for Level 2 binary tokens */ + +#ifndef btoken_INCLUDED +# define btoken_INCLUDED + +/* Define accessors for pointers to the system and user name tables. */ +extern ref binary_token_names; /* array of size 2 */ + +#define system_names_p (binary_token_names.value.refs) +#define user_names_p (binary_token_names.value.refs + 1) + +/* Convert an object to its representation in a binary object sequence. */ +int encode_binary_token(P4(const ref * obj, long *ref_offset, long *char_offset, + byte * str)); + +#endif /* btoken_INCLUDED */ diff --git a/pstoraster/ctype_.h b/pstoraster/ctype_.h new file mode 100644 index 0000000000..c120d647fe --- /dev/null +++ b/pstoraster/ctype_.h @@ -0,0 +1,37 @@ +/* Copyright (C) 1993, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Wrapper for ctype.h */ + +#ifndef ctype__INCLUDED +# define ctype__INCLUDED + +/* 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 + +#endif /* ctype__INCLUDED */ diff --git a/pstoraster/dirent_.h b/pstoraster/dirent_.h new file mode 100644 index 0000000000..4248f12cf1 --- /dev/null +++ b/pstoraster/dirent_.h @@ -0,0 +1,60 @@ +/* + Copyright 1993-2000 by Easy Software Products. + Copyright 1993, 1997, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Generic substitute for Unix dirent.h */ + +#ifndef dirent__INCLUDED +# define dirent__INCLUDED + +/* 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 /* sys/ndir or ndir or sys/dir, i.e., no dirent */ +# ifdef HAVE_SYS_DIR_H +# include +# endif +# ifdef HAVE_SYS_NDIR_H +# include +# endif +# ifdef HAVE_NDIR_H +# include +# endif +typedef struct direct dir_entry; + +#endif /* sys/ndir or ndir or sys/dir */ + +#endif /* dirent__INCLUDED */ diff --git a/pstoraster/dstack.h b/pstoraster/dstack.h new file mode 100644 index 0000000000..a9480a9e98 --- /dev/null +++ b/pstoraster/dstack.h @@ -0,0 +1,236 @@ +/* Copyright (C) 1992, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Definitions for the interpreter's dictionary stack */ + +#ifndef dstack_INCLUDED +# define dstack_INCLUDED + +#include "idstack.h" + +/* Define the (currently static) dictionary stack instance. */ +extern dict_stack_t idict_stack; + +#define d_stack (idict_stack.stack) + +/* Define the interpreter-specific versions of the generic dstack API. */ +#define min_dstack_size (idict_stack.min_size) +#define dstack_userdict_index (idict_stack.userdict_index) +#define dsspace (idict_stack.def_space) +#define dtop_can_store(pvalue) ((int)r_space(pvalue) <= dsspace) +#define dtop_keys (idict_stack.top_keys) +#define dtop_npairs (idict_stack.top_npairs) +#define dtop_values (idict_stack.top_values) +#define dict_set_top() dstack_set_top(&idict_stack); +#define dict_is_permanent_on_dstack(pdict)\ + dstack_dict_is_permanent(&idict_stack, pdict) +#define dicts_gc_cleanup() dstack_gc_cleanup(&idict_stack) +#define systemdict (&idict_stack.system_dict) + +/* Define the dictionary stack pointers. */ +#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); } + +/* + * 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. + */ + +/* Name lookup */ +#define dict_find_name_by_index(nidx)\ + dstack_find_name_by_index(&idict_stack, nidx) +#define dict_find_name(pnref) dict_find_name_by_index(name_index(pnref)) +#define dict_find_name_by_index_inline(nidx, htemp)\ + dstack_find_name_by_index_inline(&idict_stack, nidx, htemp) +#define if_dict_find_name_by_index_top(nidx, htemp, pvslot)\ + if_dstack_find_name_by_index_top(&idict_stack, nidx, htemp, pvslot) + +/* + 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 + */ + +#endif /* dstack_INCLUDED */ diff --git a/pstoraster/errno_.h b/pstoraster/errno_.h new file mode 100644 index 0000000000..b2a2ae561b --- /dev/null +++ b/pstoraster/errno_.h @@ -0,0 +1,42 @@ +/* Copyright (C) 1993, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Generic substitute for Unix errno.h */ + +#ifndef errno__INCLUDED +# define errno__INCLUDED + +/* 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 + +#endif /* errno__INCLUDED */ diff --git a/pstoraster/errors.h b/pstoraster/errors.h new file mode 100644 index 0000000000..b5fd1844bc --- /dev/null +++ b/pstoraster/errors.h @@ -0,0 +1,148 @@ +/* Copyright (C) 1989, 1995, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Definition of error codes */ + +#ifndef errors_INCLUDED +# define errors_INCLUDED + +/* + * 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. + */ + +/* Define the error name table */ +extern const char *const gs_error_names[]; + + /* ------ PostScript Level 1 errors ------ */ + +#define e_unknownerror (-1) /* unknown error */ +#define e_dictfull (-2) +#define e_dictstackoverflow (-3) +#define e_dictstackunderflow (-4) +#define e_execstackoverflow (-5) +#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 +#define e_invalidaccess (-7) +#define e_invalidexit (-8) +#define e_invalidfileaccess (-9) +#define e_invalidfont (-10) +#define e_invalidrestore (-11) +#define e_ioerror (-12) +#define e_limitcheck (-13) +#define e_nocurrentpoint (-14) +#define e_rangecheck (-15) +#define e_stackoverflow (-16) +#define e_stackunderflow (-17) +#define e_syntaxerror (-18) +#define e_timeout (-19) +#define e_typecheck (-20) +#define e_undefined (-21) +#define e_undefinedfilename (-22) +#define e_undefinedresult (-23) +#define e_unmatchedmark (-24) +#define e_VMerror (-25) + +#define LEVEL1_ERROR_NAMES\ + "unknownerror", "dictfull", "dictstackoverflow", "dictstackunderflow",\ + "execstackoverflow", "interrupt", "invalidaccess", "invalidexit",\ + "invalidfileaccess", "invalidfont", "invalidrestore", "ioerror",\ + "limitcheck", "nocurrentpoint", "rangecheck", "stackoverflow",\ + "stackunderflow", "syntaxerror", "timeout", "typecheck", "undefined",\ + "undefinedfilename", "undefinedresult", "unmatchedmark", "VMerror" + + /* ------ Additional Level 2 and DPS errors ------ */ + +#define e_configurationerror (-26) +#define e_invalidcontext (-27) +#define e_undefinedresource (-28) +#define e_unregistered (-29) +/* invalidid is for the NeXT DPS extension. */ +#define e_invalidid (-30) + +#define LEVEL2_ERROR_NAMES\ + "configurationerror", "invalidcontext", "undefinedresource",\ + "unregistered", "invalidid" + +#define ERROR_NAMES LEVEL1_ERROR_NAMES, LEVEL2_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) + +#endif /* errors_INCLUDED */ diff --git a/pstoraster/estack.h b/pstoraster/estack.h new file mode 100644 index 0000000000..2c42beace7 --- /dev/null +++ b/pstoraster/estack.h @@ -0,0 +1,139 @@ +/* Copyright (C) 1989, 1992, 1993, 1994, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Definitions for the execution stack */ + +#ifndef estack_INCLUDED +# define estack_INCLUDED + +#include "iestack.h" + +/* There's only one exec stack right now.... */ +#define esfile (iexec_stack.current_file) +#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) + +/* Define the execution stack pointers. */ +extern exec_stack_t iexec_stack; + +#define e_stack (iexec_stack.stack) +#define esbot (e_stack.bot) +#define esp (e_stack.p) +#define estop (e_stack.top) + +/* + * 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 whatever state + * they need to save or keep track of and then 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 because of an error, stop, exit, + * or quit. (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 operators that need to be handled like + * looping operators -- for example, all the 'show' operators, 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) +#define set_estack_mark_index(ep, es_idx) r_set_size(ep, es_idx) + +/* 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 e-stack, must take this into account. These are: + * exit .stop .instopped countexecstack execstack currentfile + * .execn + * 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. + */ + +#endif /* estack_INCLUDED */ diff --git a/pstoraster/files.h b/pstoraster/files.h new file mode 100644 index 0000000000..bca695d4cd --- /dev/null +++ b/pstoraster/files.h @@ -0,0 +1,157 @@ +/* Copyright (C) 1989, 1995, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Requires stream.h */ + +#ifndef files_INCLUDED +# define files_INCLUDED + +/* + * 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; + +/* Export the stdio refs for switching contexts. */ +extern ref ref_stdio[3]; + +#define ref_stdin ref_stdio[0] +#define ref_stdout ref_stdio[1] +#define ref_stderr ref_stdio[2] +/* An invalid (closed) file. */ +extern stream *invalid_file_entry; + +/* + * Macros for checking file validity. + * NOTE: in order to work around a bug in the Borland 5.0 compiler, + * you must use file_is_invalid rather than !file_is_valid. + */ +#define file_is_valid(svar,op)\ + (svar = fptr(op), (svar->read_id | svar->write_id) == r_size(op)) +#define file_is_invalid(svar,op)\ + (svar = fptr(op), (svar->read_id | svar->write_id) != r_size(op)) +#define check_file(svar,op)\ + BEGIN\ + check_type(*(op), t_file);\ + if ( file_is_invalid(svar, op) ) return_error(e_invalidaccess);\ + END + +/* + * 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)\ + BEGIN\ + check_read_type(*(op), t_file);\ + check_read_known_file(svar, op, return);\ + END +#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)\ + BEGIN\ + 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 BEGIN invalid_action; END; /* closed or reopened file */\ + }\ + END +int file_switch_to_write(P1(const ref *)); + +#define check_write_file(svar,op)\ + BEGIN\ + check_write_type(*(op), t_file);\ + check_write_known_file(svar, op, return);\ + END +#define check_write_known_file(svar,op,error_return)\ + BEGIN\ + svar = fptr(op);\ + if ( svar->write_id != r_size(op) )\ + { int fcode = file_switch_to_write(op);\ + if ( fcode < 0 ) error_return(fcode);\ + }\ + END + +/* Data exported by zfile.c. */ + /* for zfilter.c and ziodev.c */ +extern const uint file_default_buffer_size; + +/* Procedures exported by zfile.c. */ + /* for imainarg.c */ +FILE *lib_fopen(P1(const char *)); + + /* for imain.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 *, + 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 zfproc.c, ziodev.c */ +stream *file_alloc_stream(P2(gs_memory_t *, client_name_t)); + +/* Procedures exported by zfileio.c. */ + /* for ziodev.c */ +int zreadline_from(P5(stream *, byte *, uint, uint *, bool *)); + +#endif /* files_INCLUDED */ diff --git a/pstoraster/fname.h b/pstoraster/fname.h new file mode 100644 index 0000000000..f6eeb8c73e --- /dev/null +++ b/pstoraster/fname.h @@ -0,0 +1,54 @@ +/* Copyright (C) 1993, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Requires gxiodev.h */ + +#ifndef fname_INCLUDED +# define fname_INCLUDED + +/* + * Define a structure for representing a parsed file name, consisting of + * an IODevice name in %'s, a file name, or both. Note that the file name + * may be either a gs_string (no terminator) or a C string (null terminator). + */ +typedef struct parsed_file_name_s { + gx_io_device *iodev; + const char *fname; + uint len; +} parsed_file_name; + +/* Parse a file name into device and individual name. */ +int parse_file_name(P2(const ref *, parsed_file_name *)); + +/* Parse a real (non-device) file name and convert to a C string. */ +int parse_real_file_name(P3(const ref *, parsed_file_name *, client_name_t)); + +/* Convert a file name to a C string by adding a null terminator. */ +int terminate_file_name(P2(parsed_file_name *, client_name_t)); + +/* Free a file name that was copied to a C string. */ +void free_file_name(P2(parsed_file_name *, client_name_t)); + +#endif /* fname_INCLUDED */ diff --git a/pstoraster/gconf.h b/pstoraster/gconf.h new file mode 100644 index 0000000000..0317aa9038 --- /dev/null +++ b/pstoraster/gconf.h @@ -0,0 +1,43 @@ +/* Copyright (C) 1997, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Wrapper for gconfig.h or a substitute. */ + +/* + * NOTA BENE: This file, unlike all other header files, must *not* have + * double-inclusion protection, since it is used in peculiar ways. + */ + +/* + * Since not all C preprocessors implement #include with a non-quoted + * argument, we arrange things so that we can still compile with such + * compilers as long as GCONFIG_H isn't defined. + */ + +#ifndef GCONFIG_H +# include "gconfig.h" +#else +# include GCONFIG_H +#endif diff --git a/pstoraster/gconfig.c b/pstoraster/gconfig.c new file mode 100644 index 0000000000..71d5b106fb --- /dev/null +++ b/pstoraster/gconfig.c @@ -0,0 +1,127 @@ +/* Copyright (C) 1989, 1995, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Configuration tables */ +#include "memory_.h" +#include "gx.h" +#include "gscdefs.h" /* interface */ +#include "gconf.h" /* for #defines */ +#include "gxdevice.h" +#include "gxiodev.h" + +/* + * The makefile generates the file gconfig.h, which consists of + * lines of the form + * device_(gs_xxx_device) + * or + * device2_(gs_xxx_device) + * for each installed device; + * emulator_("emulator", strlen("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", strlen("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 device2_(dev) extern const gx_device dev; +#define init_(proc) extern void proc(P1(gs_memory_t *)); +#define io_device_(iodev) extern const gx_io_device iodev; +#include "gconf.h" +#undef init_ +#undef io_device_ +#undef device2_ +#undef device_ + +/* Set up the initialization procedure table. */ +extern_gx_init_table(); +private void gconf_init(P1(gs_memory_t *)); +#define init_(proc) proc, +const gx_init_proc gx_init_table[] = { +#include "gconf.h" + gconf_init, + 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, +const gx_io_device *const gx_io_device_table[] = { + &gs_iodev_os, +#include "gconf.h" + 0 +}; +#undef io_device_ +const uint gx_io_device_table_count = countof(gx_io_device_table) - 1; + +/* Set up the device table. */ +#define device_(dev) (const gx_device *)&dev, +#define device2_(dev) &dev, +private const gx_device *const gx_device_list[] = { +#include "gconf.h" + 0 +}; +#undef device2_ +#undef device_ + +/* Allocate and initialize structure descriptors for the devices. */ +private gs_memory_struct_type_t gx_device_st_list[countof(gx_device_list) - 1]; +private void +gconf_init(gs_memory_t *mem) +{ + int i; + + for (i = 0; i < countof(gx_device_list) - 1; ++i) + gx_device_make_struct_type(&gx_device_st_list[i], gx_device_list[i]); +} + +/* 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 * const **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..9d451fdbec --- /dev/null +++ b/pstoraster/gconfig.h @@ -0,0 +1,243 @@ +/* + * "$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 device2_ +device2_(gs_cups_device) +device2_(gs_bbox_device) +/*device2_(gs_nullpage_device)*/ +#endif +#ifdef oper_ +oper_(zchar1_op_defs) +oper_(zfont1_op_defs) +oper_(zmisc1_op_defs) +#endif +#ifdef psfile_ +psfile_("gs_type1.ps",11) +#endif +#ifdef oper_ +oper_(zvmem2_op_defs) +oper_(zdps1_l2_op_defs) +#endif +#ifdef psfile_ +psfile_("gs_dps1.ps",10) +#endif +#ifdef oper_ +oper_(zusparam_op_defs) +oper_(zmisc2_op_defs) +#endif +#ifdef psfile_ +psfile_("gs_lev2.ps",10) +psfile_("gs_res.ps",9) +#endif +#ifdef oper_ +oper_(zchar42_op_defs) +oper_(zfont42_op_defs) +#endif +#ifdef psfile_ +psfile_("gs_typ42.ps",11) +psfile_("gs_cidfn.ps",11) +#endif +#ifdef oper_ +oper_(zcid_op_defs) +oper_(zcie_l2_op_defs) +oper_(zcrd_l2_op_defs) +oper_(zfcmap_op_defs) +#endif +#ifdef psfile_ +psfile_("gs_cmap.ps",10) +#endif +#ifdef oper_ +oper_(zcfont_op_defs) +oper_(zfont0_op_defs) +# ifdef HAVE_LIBJPEG +oper_(zfdcte_op_defs) +oper_(zfdctd_op_defs) +# endif /* HAVE_LIBJPEG */ +oper_(zbseq_l2_op_defs) +#endif +#ifdef psfile_ +psfile_("gs_btokn.ps",11) +#endif +#ifdef init_ +init_(gs_gxicolor_init) +#endif +#ifdef oper_ +oper_(zcolor1_op_defs) +oper_(zht1_op_defs) +oper_(zupath_l2_op_defs) +oper_(ireclaim_l2_op_defs) +oper_(zchar2_op_defs) +#endif +#ifdef psfile_ +psfile_("gs_dps2.ps",10) +#endif +#ifdef oper_ +oper_(zfdecode_op_defs) +oper_(zfilter2_op_defs) +oper_(ziodev2_l2_op_defs) +#endif +#ifdef io_device_ +io_device_(gs_iodev_null) +io_device_(gs_iodev_ram) +io_device_(gs_iodev_calendar) +#endif +#ifdef oper_ +oper_(zdevice2_l2_op_defs) +oper_(zmedia2_l2_op_defs) +#endif +#ifdef psfile_ +psfile_("gs_setpd.ps",11) +#endif +#ifdef oper_ +oper_(zpcolor_l2_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_(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_(zimage_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) +#endif +#ifdef init_ +init_(gs_gstype1_init) +#endif +#ifdef emulator_ +emulator_("PostScript",10) +emulator_("PostScriptLevel1",16) +#endif +#ifdef init_ +init_(gs_gxi12bit_init) +init_(gs_gxiscale_init) +#endif +#ifdef oper_ +oper_(zcolor2_l2_op_defs) +oper_(zcsindex_l2_op_defs) +oper_(zht2_l2_op_defs) +oper_(zimage2_l2_op_defs) +oper_(zcssepr_l2_op_defs) +oper_(zchar32_op_defs) +oper_(zfont32_op_defs) +#endif +#ifdef psfile_ +psfile_("gs_typ32.ps",11) +#endif +#ifdef oper_ +oper_(zfilterx_op_defs) +#endif +#ifdef emulator_ +emulator_("PostScriptLevel2",16) +#endif +#ifdef oper_ +oper_(zcspixel_op_defs) +oper_(zfunc_op_defs) +oper_(zfunc0_op_defs) +oper_(zcsdevn_op_defs) +oper_(zfreuse_op_defs) +oper_(zfunc3_op_defs) +oper_(zimage3_op_defs) +oper_(zmisc3_op_defs) +oper_(zshade_op_defs) +oper_(ztrap_op_defs) +#endif +#ifdef psfile_ +psfile_("gs_ll3.ps",9) +#endif +#ifdef oper_ +# ifdef HAVE_LIBZ +oper_(zfzlib_op_defs) +# endif /* HAVE_LIBZ */ +#endif +#ifdef psfile_ +psfile_("gs_mex_e.ps",11) +psfile_("gs_mro_e.ps",11) +psfile_("gs_wan_e.ps",11) +psfile_("gs_cff.ps",9) +psfile_("gs_ttf.ps",9) +#endif +#ifdef init_ +init_(gs_gstype2_init) +#endif +#ifdef io_device_ +io_device_(gs_iodev_pipe) +#endif +#ifdef psfile_ +psfile_("gs_epsf.ps",10) +#endif +#ifdef init_ +# ifdef HAVE_LIBZ +init_(gs_cl_zlib_init) +# endif /* HAVE_LIBZ */ +init_(gs_gshtscr_init) +init_(gs_gsutil_init) +init_(gs_gxcht_init) +init_(gs_gxifast_init) +init_(gs_gximono_init) +#endif +#define SEARCH_HERE_FIRST 1 + +/* + * End of "$Id$". + */ diff --git a/pstoraster/gconfig_.h b/pstoraster/gconfig_.h new file mode 100644 index 0000000000..518b790206 --- /dev/null +++ b/pstoraster/gconfig_.h @@ -0,0 +1,5 @@ +/* This file was generated automatically. */ +#define HAVE_DIRENT_H +#define HAVE_SYS_DIR_H +#define HAVE_SYS_TIME_H +#define HAVE_SYS_TIMES_H diff --git a/pstoraster/gconfigv.h b/pstoraster/gconfigv.h new file mode 100644 index 0000000000..a9ae98b88b --- /dev/null +++ b/pstoraster/gconfigv.h @@ -0,0 +1,4 @@ +#define USE_ASM (-0) +#define USE_FPU (1-0) +#define EXTEND_NAMES 0 +#define SYSTEM_CONSTANTS_ARE_WRITABLE 0 diff --git a/pstoraster/gdebug.h b/pstoraster/gdebug.h new file mode 100644 index 0000000000..9b14802488 --- /dev/null +++ b/pstoraster/gdebug.h @@ -0,0 +1,132 @@ +/* Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Debugging machinery definitions */ + +#ifndef gdebug_INCLUDED +# define gdebug_INCLUDED + +/* + * The compile-time DEBUG symbol determines whether debugging/tracing + * code is included in the compiled code. DEBUG may be set or not set + * independently for every compilation; however, a small amount of support + * machinery in gsmisc.c is always included in the executable, just + * in case *some* file was compiled with DEBUG set. + * + * When DEBUG is set, it does not cause debugging/tracing printout to occur. + * Rather, it includes code that produces such printout *if* (a) given + * one(s) of 128 debugging flags is set. In this way, one can selectively + * turn printout on and off during debugging. (In fact, we even provide a + * PostScript operator, .setdebug, that does this.) + * + * The debugging flags are normally indexed by character code. This is more + * than a convention: gs_debug_c, which tests whether a given flag is set, + * considers that if a flag named by a given upper-case letter is set, the + * flag named by the corresponding lower-case letter is also set. + * + * If the output selected by a given flag can be printed by a single + * printf, the conventional way to produce the output is + * if_debugN('x', "...format...", v1, ..., vN); + * Usually the flag appears in the output explicitly: + * if_debugN('x', "[x]...format...", v1, ..., vN); + * If the output is more complex, the conventional way to produce the + * output is + * if ( gs_debug_c('x') ) { + * ... start each line with dlprintfN(...) + * ... produce additional output within a line with dprintfN(...) + * } */ + +/* Define the array of debugging flags, indexed by character code. */ +extern char gs_debug[128]; +bool gs_debug_c(P1(int /*char */ )); + +/* + * 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 + +/* Debugging printout macros. */ +#ifdef DEBUG +# define if_debug0(c,s)\ + BEGIN if (gs_debug_c(c)) dlprintf(s); END +# define if_debug1(c,s,a1)\ + BEGIN if (gs_debug_c(c)) dlprintf1(s,a1); END +# define if_debug2(c,s,a1,a2)\ + BEGIN if (gs_debug_c(c)) dlprintf2(s,a1,a2); END +# define if_debug3(c,s,a1,a2,a3)\ + BEGIN if (gs_debug_c(c)) dlprintf3(s,a1,a2,a3); END +# define if_debug4(c,s,a1,a2,a3,a4)\ + BEGIN if (gs_debug_c(c)) dlprintf4(s,a1,a2,a3,a4); END +# define if_debug5(c,s,a1,a2,a3,a4,a5)\ + BEGIN if (gs_debug_c(c)) dlprintf5(s,a1,a2,a3,a4,a5); END +# define if_debug6(c,s,a1,a2,a3,a4,a5,a6)\ + BEGIN if (gs_debug_c(c)) dlprintf6(s,a1,a2,a3,a4,a5,a6); END +# define if_debug7(c,s,a1,a2,a3,a4,a5,a6,a7)\ + BEGIN if (gs_debug_c(c)) dlprintf7(s,a1,a2,a3,a4,a5,a6,a7); END +# define if_debug8(c,s,a1,a2,a3,a4,a5,a6,a7,a8)\ + BEGIN if (gs_debug_c(c)) dlprintf8(s,a1,a2,a3,a4,a5,a6,a7,a8); END +# define if_debug9(c,s,a1,a2,a3,a4,a5,a6,a7,a8,a9)\ + BEGIN if (gs_debug_c(c)) dlprintf9(s,a1,a2,a3,a4,a5,a6,a7,a8,a9); END +# define if_debug10(c,s,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)\ + BEGIN if (gs_debug_c(c)) dlprintf10(s,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10); END +# define if_debug11(c,s,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)\ + BEGIN if (gs_debug_c(c)) dlprintf11(s,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11); END +# define if_debug12(c,s,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12)\ + BEGIN if (gs_debug_c(c)) dlprintf12(s,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12); END +#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/gdev8bcm.h b/pstoraster/gdev8bcm.h new file mode 100644 index 0000000000..f9f6781142 --- /dev/null +++ b/pstoraster/gdev8bcm.h @@ -0,0 +1,78 @@ +/* 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 supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Requires gxdevice.h (for gx_color_value) */ + +#ifndef gdev8bcm_INCLUDED +# define gdev8bcm_INCLUDED + +/* + * The MS-DOS, MS Windows, and X Windows drivers all use (at least on + * some platforms) an 8-bit color map in which some fraction is reserved + * for a pre-allocated cube and some or all of the remainder is + * allocated dynamically. Since looking up colors in this map can be + * a major performance bottleneck, we provide an efficient implementation + * that can be shared among drivers. + * + * As a performance compromise, we only look up the top 5 bits of the + * RGB value in the color map. This compromises color quality very little, + * and allows substantial optimizations. + */ + +#define gx_8bit_map_size 323 +#define gx_8bit_map_spreader 123 /* approx. 323 - (1.618 * 323) */ +typedef struct gx_8bit_map_entry_s { + ushort rgb; /* key = 0rrrrrgggggbbbbb */ +#define gx_8bit_no_rgb ((ushort)0xffff) +#define gx_8bit_rgb_key(r, g, b)\ + (((r >> (gx_color_value_bits - 5)) << 10) +\ + ((g >> (gx_color_value_bits - 5)) << 5) +\ + (b >> (gx_color_value_bits - 5))) + short index; /* value */ +} gx_8bit_map_entry; +typedef struct gx_8bit_color_map_s { + int count; /* # of occupied entries */ + int max_count; /* max # of occupied entries */ + gx_8bit_map_entry map[gx_8bit_map_size + 1]; +} gx_8bit_color_map; + +/* Initialize an 8-bit color map. */ +void gx_8bit_map_init(P2(gx_8bit_color_map *, int)); + +/* Look up a color in an 8-bit color map. */ +/* Return -1 if not found. */ +int gx_8bit_map_rgb_color(P4(const gx_8bit_color_map *, gx_color_value, + gx_color_value, gx_color_value)); + +/* Test whether an 8-bit color map has room for more entries. */ +#define gx_8bit_map_is_full(pcm)\ + ((pcm)->count == (pcm)->max_count) + +/* Add a color to an 8-bit color map. */ +/* Return -1 if the map is full. */ +int gx_8bit_add_rgb_color(P4(gx_8bit_color_map *, gx_color_value, + gx_color_value, gx_color_value)); + +#endif /* gdev8bcm_INCLUDED */ diff --git a/pstoraster/gdevabuf.c b/pstoraster/gdevabuf.c new file mode 100644 index 0000000000..991584c04a --- /dev/null +++ b/pstoraster/gdevabuf.c @@ -0,0 +1,404 @@ +/* Copyright (C) 1994, 1995, 1996, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* 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_device_memory * const mdev = (gx_device_memory *)dev; + 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_device_memory * const mdev = (gx_device_memory *)dev; + 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) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + + 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); +private dev_proc_get_clipping_box(mem_abuf_get_clipping_box); + +/* The device descriptor. */ +private const gx_device_memory 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); + set_dev_proc(adev, get_clipping_box, mem_abuf_get_clipping_box); +} + +/* 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) +{ + gx_device_memory * const mdev = (gx_device_memory *)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) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + 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) +{ + gx_device_memory * const mdev = (gx_device_memory *)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) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + 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_xyw(dev, base, sourcex, sraster, id, x, y, w, h); /* don't limit h */ + if (w <= 0 || h <= 0) + return 0; + 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) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + y_transfer yt; + + x -= mdev->mapped_x; + fit_fill_xy(dev, x, y, w, h); + fit_fill_w(dev, x, w); /* 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; +} + +/* Get the clipping box. We must scale this up by the number of alpha bits. */ +private void +mem_abuf_get_clipping_box(gx_device * dev, gs_fixed_rect * pbox) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + gx_device *tdev = mdev->target; + + (*dev_proc(tdev, get_clipping_box)) (tdev, pbox); + pbox->p.x <<= mdev->log2_scale.x; + pbox->p.y <<= mdev->log2_scale.y; + pbox->q.x <<= mdev->log2_scale.x; + pbox->q.y <<= mdev->log2_scale.y; +} diff --git a/pstoraster/gdevbbox.c b/pstoraster/gdevbbox.c new file mode 100644 index 0000000000..5641b36752 --- /dev/null +++ b/pstoraster/gdevbbox.c @@ -0,0 +1,1069 @@ +/* Copyright (C) 1996, 1997, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Device for tracking bounding box */ +#include "math_.h" +#include "memory_.h" +#include "gx.h" +#include "gserrors.h" +#include "gsparam.h" +#include "gxdevice.h" +#include "gsdevice.h" /* requires gsmatrix.h */ +#include "gdevbbox.h" +#include "gxdcolor.h" /* for gx_device_black/white */ +#include "gxiparam.h" /* for image source size */ +#include "gxistate.h" +#include "gxpaint.h" +#include "gxpath.h" +#include "gxcpath.h" + +/* GC descriptor */ +public_st_device_bbox(); + +/* Device procedures */ +private dev_proc_open_device(bbox_open_device); +private dev_proc_close_device(bbox_close_device); +private dev_proc_output_page(bbox_output_page); +private dev_proc_fill_rectangle(bbox_fill_rectangle); +private dev_proc_copy_mono(bbox_copy_mono); +private dev_proc_copy_color(bbox_copy_color); +private dev_proc_get_params(bbox_get_params); +private dev_proc_put_params(bbox_put_params); +private dev_proc_copy_alpha(bbox_copy_alpha); +private dev_proc_fill_path(bbox_fill_path); +private dev_proc_stroke_path(bbox_stroke_path); +private dev_proc_fill_mask(bbox_fill_mask); +private dev_proc_fill_trapezoid(bbox_fill_trapezoid); +private dev_proc_fill_parallelogram(bbox_fill_parallelogram); +private dev_proc_fill_triangle(bbox_fill_triangle); +private dev_proc_draw_thin_line(bbox_draw_thin_line); +private dev_proc_strip_tile_rectangle(bbox_strip_tile_rectangle); +private dev_proc_strip_copy_rop(bbox_strip_copy_rop); +private dev_proc_begin_typed_image(bbox_begin_typed_image); +private dev_proc_create_compositor(bbox_create_compositor); +private dev_proc_text_begin(bbox_text_begin); + +/* The device prototype */ +/* + * Normally this would be private, but if the device is going to be used + * stand-alone, it has to be public. + */ +/*private */ const +/* + * The bbox device sets the resolution to some value R (currently 4000), and + * the page size in device pixels to slightly smaller than the largest + * representable values (around 500K), leaving a little room for stroke + * widths, rounding, etc. If an input file (or the command line) resets the + * resolution to a value R' > R, the page size in pixels will get multiplied + * by R'/R, and will thereby exceed the representable range, causing a + * limitcheck. That is why the bbox device must set the resolution to a + * value larger than that of any real device. A consequence of this is that + * the page size in inches is limited to the maximum representable pixel + * size divided by R, which gives a limit of about 120" in each dimension. + */ +#define max_coord (max_int_in_fixed - 1000) +#define max_resolution 4000 +gx_device_bbox far_data gs_bbox_device = +{ + std_device_std_body(gx_device_bbox, 0, "bbox", + max_coord, max_coord, + max_resolution, max_resolution), + {bbox_open_device, + NULL, /* get_initial_matrix */ + NULL, /* sync_output */ + bbox_output_page, + bbox_close_device, + NULL, /* map_rgb_color */ + NULL, /* map_color_rgb */ + bbox_fill_rectangle, + NULL, /* tile_rectangle */ + bbox_copy_mono, + bbox_copy_color, + NULL, /* draw_line */ + NULL, /* get_bits */ + bbox_get_params, + bbox_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 */ + bbox_copy_alpha, + NULL, /* get_band */ + NULL, /* copy_rop */ + bbox_fill_path, + bbox_stroke_path, + bbox_fill_mask, + bbox_fill_trapezoid, + bbox_fill_parallelogram, + bbox_fill_triangle, + bbox_draw_thin_line, + gx_default_begin_image, + NULL, /* image_data */ + NULL, /* end_image */ + bbox_strip_tile_rectangle, + bbox_strip_copy_rop, + NULL, /* get_clipping_box */ + bbox_begin_typed_image, + NULL, /* get_bits_rectangle */ + NULL, /* map_color_rgb_alpha */ + bbox_create_compositor, + NULL, /* get_hardware_params */ + bbox_text_begin + }, + 0, /* target */ + 1 /*true *//* free_standing */ +}; + +#undef max_coord +#undef max_resolution + +/* Copy device parameters back from the target. */ +private void +bbox_copy_params(gx_device_bbox * bdev, bool remap_white) +{ + gx_device *tdev = bdev->target; + + if (tdev != 0) + gx_device_copy_params((gx_device *)bdev, tdev); + if (remap_white) + bdev->white = gx_device_white((gx_device *)bdev); +} + +#define gx_dc_is_white(pdevc, bdev)\ + (gx_dc_is_pure(pdevc) && gx_dc_pure_color(pdevc) == (bdev)->white) + +private int +bbox_close_device(gx_device * dev) +{ + gx_device_bbox *const bdev = (gx_device_bbox *) dev; + gx_device *tdev = bdev->target; + + if ((gx_device *) bdev->box_device != dev) { + /* + * This device was created as a wrapper for a compositor. + * Just free the devices. + */ + int code = (*dev_proc(tdev, close_device)) (tdev); + + gs_free_object(dev->memory, dev, "bbox_close_device(composite)"); + return code; + } else { + return (tdev == 0 ? 0 : (*dev_proc(tdev, close_device)) (tdev)); + } +} + +/* Bounding box utilities */ + +private void near +bbox_initialize(gs_fixed_rect * pr) +{ + pr->p.x = pr->p.y = max_fixed; + pr->q.x = pr->q.y = min_fixed; +} + +private void near +bbox_add_rect(gs_fixed_rect * pr, fixed x0, fixed y0, fixed x1, fixed y1) +{ + if (x0 < pr->p.x) + pr->p.x = x0; + if (y0 < pr->p.y) + pr->p.y = y0; + if (x1 > pr->q.x) + pr->q.x = x1; + if (y1 > pr->q.y) + pr->q.y = y1; +} +private void near +bbox_add_point(gs_fixed_rect * pr, fixed x, fixed y) +{ + bbox_add_rect(pr, x, y, x, y); +} +private void near +bbox_add_int_rect(gs_fixed_rect * pr, int x0, int y0, int x1, int y1) +{ + bbox_add_rect(pr, int2fixed(x0), int2fixed(y0), int2fixed(x1), + int2fixed(y1)); +} + +#define rect_is_page(dev, x, y, w, h)\ + (x <= 0 && y <= 0 && w >= x + dev->width && h >= y + dev->height) + + /* ---------------- Open/close/page ---------------- */ + +/* Initialize a bounding box device. */ +void +gx_device_bbox_init(gx_device_bbox * dev, gx_device * target) +{ + gx_device_init((gx_device *) dev, (const gx_device *)&gs_bbox_device, + (target ? target->memory : NULL), true); + gx_device_forward_fill_in_procs((gx_device_forward *) dev); + dev->target = target; + dev->box_device = dev; + bbox_copy_params(dev, false); + dev->free_standing = false; /* being used as a component */ +} + +/* Read back the bounding box in 1/72" units. */ +void +gx_device_bbox_bbox(gx_device_bbox * dev, gs_rect * pbbox) +{ + const gx_device_bbox *bbdev = dev->box_device; + gs_matrix mat; + gs_rect dbox; + + gs_deviceinitialmatrix((gx_device *) dev, &mat); + dbox.p.x = fixed2float(bbdev->bbox.p.x); + dbox.p.y = fixed2float(bbdev->bbox.p.y); + dbox.q.x = fixed2float(bbdev->bbox.q.x); + dbox.q.y = fixed2float(bbdev->bbox.q.y); + gs_bbox_transform_inverse(&dbox, &mat, pbbox); +} + + +private int +bbox_open_device(gx_device * dev) +{ + gx_device_bbox *const bdev = (gx_device_bbox *) dev; + + if (bdev->free_standing) { + gx_device_forward_fill_in_procs((gx_device_forward *) dev); + bdev->box_device = bdev; + } + if (bdev->box_device == bdev) + bbox_initialize(&bdev->bbox); + /* gx_forward_open_device doesn't exist */ + { + gx_device *tdev = bdev->target; + int code = (tdev == 0 ? 0 : (*dev_proc(tdev, open_device)) (tdev)); + + bbox_copy_params(bdev, true); + return code; + } +} + +private int +bbox_output_page(gx_device * dev, int num_copies, int flush) +{ + gx_device_bbox *const bdev = (gx_device_bbox *) dev; + + if (bdev->free_standing) { + /* + * This is a free-standing device. Print the page bounding box. + */ + gs_rect bbox; + + gx_device_bbox_bbox(bdev, &bbox); + dlprintf4("%%%%BoundingBox: %d %d %d %d\n", + (int)floor(bbox.p.x), (int)floor(bbox.p.y), + (int)ceil(bbox.q.x), (int)ceil(bbox.q.y)); + dlprintf4("%%%%HiResBoundingBox: %f %f %f %f\n", + bbox.p.x, bbox.p.y, bbox.q.x, bbox.q.y); + } + /* + * Propagate the PageCount to the target, + * since it changes every time gs_output_page is called. + */ + if (bdev->target) + bdev->target->PageCount = dev->PageCount; + return gx_forward_output_page(dev, num_copies, flush); +} + +/* ---------------- Low-level drawing ---------------- */ + +private int +bbox_fill_rectangle(gx_device * dev, int x, int y, int w, int h, + gx_color_index color) +{ + gx_device_bbox *const bdev = (gx_device_bbox *) dev; + gx_device_bbox *bbdev = bdev->box_device; + + /* Check for erasing the entire page. */ + if (rect_is_page(dev, x, y, w, h)) + bbox_initialize(&bbdev->bbox); + else if (color != bdev->white) + bbox_add_int_rect(&bbdev->bbox, x, y, x + w, y + h); + /* gx_forward_fill_rectangle doesn't exist */ + { + gx_device *tdev = bdev->target; + + return (tdev == 0 ? 0 : + (*dev_proc(tdev, fill_rectangle)) (tdev, x, y, w, h, color)); + } +} + +private int +bbox_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) +{ + gx_device_bbox *const bdev = (gx_device_bbox *) dev; + gx_device_bbox *bbdev = bdev->box_device; + + if ((one != gx_no_color_index && one != bdev->white) || + (zero != gx_no_color_index && zero != bdev->white) + ) + bbox_add_int_rect(&bbdev->bbox, x, y, x + w, y + h); + /* gx_forward_copy_mono doesn't exist */ + { + gx_device *tdev = bdev->target; + + return (tdev == 0 ? 0 : + (*dev_proc(tdev, copy_mono)) + (tdev, data, dx, raster, id, x, y, w, h, zero, one)); + } +} + +private int +bbox_copy_color(gx_device * dev, const byte * data, + int dx, int raster, gx_bitmap_id id, int x, int y, int w, int h) +{ + gx_device_bbox *const bdev = (gx_device_bbox *) dev; + gx_device_bbox *bbdev = bdev->box_device; + + bbox_add_int_rect(&bbdev->bbox, x, y, x + w, y + h); + /* gx_forward_copy_color doesn't exist */ + { + gx_device *tdev = bdev->target; + + return (tdev == 0 ? 0 : + (*dev_proc(tdev, copy_color)) + (tdev, data, dx, raster, id, x, y, w, h)); + } +} + +private int +bbox_copy_alpha(gx_device * dev, const byte * data, int data_x, + int raster, gx_bitmap_id id, int x, int y, int w, int h, + gx_color_index color, int depth) +{ + gx_device_bbox *const bdev = (gx_device_bbox *) dev; + gx_device_bbox *bbdev = bdev->box_device; + + bbox_add_int_rect(&bbdev->bbox, x, y, x + w, y + h); + /* gx_forward_copy_alpha doesn't exist */ + { + gx_device *tdev = bdev->target; + + return (tdev == 0 ? 0 : + (*dev_proc(tdev, copy_alpha)) + (tdev, data, data_x, raster, id, x, y, w, h, color, depth)); + } +} + +private int +bbox_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_bbox *const bdev = (gx_device_bbox *) dev; + gx_device_bbox *bbdev = bdev->box_device; + + if (rect_is_page(dev, x, y, w, h)) + bbox_initialize(&bbdev->bbox); + else + bbox_add_int_rect(&bbdev->bbox, x, y, x + w, y + h); + /* Skip the call if there is no target. */ + { + gx_device *tdev = bdev->target; + + return (tdev == 0 ? 0 : + (*dev_proc(tdev, strip_tile_rectangle)) + (tdev, tiles, x, y, w, h, color0, color1, px, py)); + } +} + +private int +bbox_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 w, int h, + int phase_x, int phase_y, gs_logical_operation_t lop) +{ + gx_device_bbox *const bdev = (gx_device_bbox *) dev; + gx_device_bbox *bbdev = bdev->box_device; + + bbox_add_int_rect(&bbdev->bbox, x, y, x + w, y + h); + /* gx_forward_strip_copy_rop doesn't exist */ + { + gx_device *tdev = bdev->target; + + return (tdev == 0 ? 0 : + (*dev_proc(tdev, strip_copy_rop)) + (tdev, sdata, sourcex, sraster, id, scolors, + textures, tcolors, x, y, w, h, phase_x, phase_y, lop)); + } +} + +/* ---------------- Parameters ---------------- */ + +/* We implement get_params to provide a way to read out the bounding box. */ +private int +bbox_get_params(gx_device * dev, gs_param_list * plist) +{ + gx_device_bbox *const bdev = (gx_device_bbox *) dev; + const gx_device_bbox *bbdev = bdev->box_device; + int code = gx_forward_get_params(dev, plist); + gs_param_float_array bba; + float bbox[4]; + + if (code < 0) + return code; + /* + * We might be calling get_params before the device has been + * initialized: in this case, bbdev = 0. + */ + if (bbdev == 0) + bbdev = (const gx_device_bbox *)dev; + bbox[0] = fixed2float(bbdev->bbox.p.x); + bbox[1] = fixed2float(bbdev->bbox.p.y); + bbox[2] = fixed2float(bbdev->bbox.q.x); + bbox[3] = fixed2float(bbdev->bbox.q.y); + bba.data = bbox, bba.size = 4, bba.persistent = false; + return param_write_float_array(plist, "PageBoundingBox", &bba); +} + +/* We implement put_params to ensure that we keep the important */ +/* device parameters up to date, and to prevent an /undefined error */ +/* from PageBoundingBox. */ +private int +bbox_put_params(gx_device * dev, gs_param_list * plist) +{ + gx_device_bbox *const bdev = (gx_device_bbox *) dev; + int code; + int ecode = 0; + gs_param_name param_name; + gs_param_float_array bba; + + code = param_read_float_array(plist, (param_name = "PageBoundingBox"), + &bba); + switch (code) { + case 0: + if (bba.size != 4) { + ecode = gs_note_error(gs_error_rangecheck); + goto e; + } + break; + default: + ecode = code; + e:param_signal_error(plist, param_name, ecode); + case 1: + bba.data = 0; + } + + code = gx_forward_put_params(dev, plist); + if (ecode < 0) + code = ecode; + if (code >= 0 && bba.data != 0) { + gx_device_bbox *bbdev = bdev->box_device; + + bbdev->bbox.p.x = float2fixed(bba.data[0]); + bbdev->bbox.p.y = float2fixed(bba.data[1]); + bbdev->bbox.q.x = float2fixed(bba.data[2]); + bbdev->bbox.q.y = float2fixed(bba.data[3]); + } + bbox_copy_params(bdev, true); + return code; +} + +/* ---------------- Polygon drawing ---------------- */ + +private fixed +edge_x_at_y(const gs_fixed_edge * edge, fixed y) +{ + return fixed_mult_quo(edge->end.x - edge->start.x, + y - edge->start.y, + edge->end.y - edge->start.y) + edge->start.x; +} +private int +bbox_fill_trapezoid(gx_device * dev, + const gs_fixed_edge * left, const gs_fixed_edge * right, + fixed ybot, fixed ytop, bool swap_axes, + const gx_device_color * pdevc, gs_logical_operation_t lop) +{ + gx_device_bbox *const bdev = (gx_device_bbox *) dev; + + if (!gx_dc_is_white(pdevc, bdev)) { + gx_device_bbox *bbdev = bdev->box_device; + fixed x0l = + (left->start.y == ybot ? left->start.x : + edge_x_at_y(left, ybot)); + fixed x1l = + (left->end.y == ytop ? left->end.x : + edge_x_at_y(left, ytop)); + fixed x0r = + (right->start.y == ybot ? right->start.x : + edge_x_at_y(right, ybot)); + fixed x1r = + (right->end.y == ytop ? right->end.x : + edge_x_at_y(right, ytop)); + fixed xminl = min(x0l, x1l), xmaxl = max(x0l, x1l); + fixed xminr = min(x0r, x1r), xmaxr = max(x0r, x1r); + fixed x0 = min(xminl, xminr), x1 = max(xmaxl, xmaxr); + + if (swap_axes) + bbox_add_rect(&bbdev->bbox, ybot, x0, ytop, x1); + else + bbox_add_rect(&bbdev->bbox, x0, ybot, x1, ytop); + } + /* Skip the call if there is no target. */ + { + gx_device *tdev = bdev->target; + + return (tdev == 0 ? 0 : + (*dev_proc(tdev, fill_trapezoid)) + (tdev, left, right, ybot, ytop, swap_axes, pdevc, lop)); + } +} + +private int +bbox_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) +{ + gx_device_bbox *const bdev = (gx_device_bbox *) dev; + + if (!gx_dc_is_white(pdevc, bdev)) { + gx_device_bbox *bbdev = bdev->box_device; + fixed pax = px + ax, pay = py + ay; + + bbox_add_rect(&bbdev->bbox, px, py, px + bx, py + by); + bbox_add_rect(&bbdev->bbox, pax, pay, pax + bx, pay + by); + } + /* Skip the call if there is no target. */ + { + gx_device *tdev = bdev->target; + + return (tdev == 0 ? 0 : + (*dev_proc(tdev, fill_parallelogram)) + (tdev, px, py, ax, ay, bx, by, pdevc, lop)); + } +} + +private int +bbox_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) +{ + gx_device_bbox *const bdev = (gx_device_bbox *) dev; + + if (!gx_dc_is_white(pdevc, bdev)) { + gx_device_bbox *bbdev = bdev->box_device; + + bbox_add_rect(&bbdev->bbox, px, py, px + bx, py + by); + bbox_add_point(&bbdev->bbox, px + ax, py + ay); + } + /* Skip the call if there is no target. */ + { + gx_device *tdev = bdev->target; + + return (tdev == 0 ? 0 : + (*dev_proc(tdev, fill_triangle)) + (tdev, px, py, ax, ay, bx, by, pdevc, lop)); + } +} + +private int +bbox_draw_thin_line(gx_device * dev, + fixed fx0, fixed fy0, fixed fx1, fixed fy1, + const gx_device_color * pdevc, gs_logical_operation_t lop) +{ + gx_device_bbox *const bdev = (gx_device_bbox *) dev; + + if (!gx_dc_is_white(pdevc, bdev)) { + gx_device_bbox *bbdev = bdev->box_device; + + bbox_add_rect(&bbdev->bbox, fx0, fy0, fx1, fy1); + } + /* Skip the call if there is no target. */ + { + gx_device *tdev = bdev->target; + + return (tdev == 0 ? 0 : + (*dev_proc(tdev, draw_thin_line)) + (tdev, fx0, fy0, fx1, fy0, pdevc, lop)); + } +} + +/* ---------------- High-level drawing ---------------- */ + +#define adjust_box(pbox, adj)\ +((pbox)->p.x -= (adj).x, (pbox)->p.y -= (adj).y,\ + (pbox)->q.x += (adj).x, (pbox)->q.y += (adj).y) + +private int +bbox_fill_path(gx_device * dev, const gs_imager_state * pis, gx_path * ppath, + const gx_fill_params * params, const gx_device_color * pdevc, + const gx_clip_path * pcpath) +{ + gx_device_bbox *const bdev = (gx_device_bbox *) dev; + gx_device *tdev = bdev->target; + + if (!gx_dc_is_white(pdevc, bdev)) { + gs_fixed_rect ibox; + gs_fixed_point adjust; + + if (gx_path_bbox(ppath, &ibox) < 0) + return 0; + adjust = params->adjust; + if (params->fill_zero_width) + gx_adjust_if_empty(&ibox, &adjust); + adjust_box(&ibox, adjust); + if (pcpath != NULL && + !gx_cpath_includes_rectangle(pcpath, ibox.p.x, ibox.p.y, + ibox.q.x, ibox.q.y) + ) { + /* Let the target do the drawing, but break down the */ + /* fill path into pieces for computing the bounding box. */ + bdev->target = NULL; + gx_default_fill_path(dev, pis, ppath, params, pdevc, pcpath); + bdev->target = tdev; + } else { /* Just use the path bounding box. */ + bbox_add_rect(&bdev->bbox, ibox.p.x, ibox.p.y, ibox.q.x, + ibox.q.y); + } + } + /* Skip the call if there is no target. */ + return (tdev == 0 ? 0 : + (*dev_proc(tdev, fill_path)) + (tdev, pis, ppath, params, pdevc, pcpath)); +} + +private int +bbox_stroke_path(gx_device * dev, const gs_imager_state * pis, gx_path * ppath, + const gx_stroke_params * params, + const gx_drawing_color * pdevc, const gx_clip_path * pcpath) +{ + gx_device_bbox *const bdev = (gx_device_bbox *) dev; + gx_device *tdev = bdev->target; + + if (!gx_dc_is_white(pdevc, bdev)) { + gs_fixed_rect ibox; + gs_fixed_point expand; + + if (gx_path_bbox(ppath, &ibox) < 0) + return 0; + if (gx_stroke_path_expansion(pis, ppath, &expand) < 0) + ibox.p.x = ibox.p.y = min_fixed, ibox.q.x = ibox.q.y = max_fixed; + else + adjust_box(&ibox, expand); + if (pcpath != NULL && + !gx_cpath_includes_rectangle(pcpath, ibox.p.x, ibox.p.y, + ibox.q.x, ibox.q.y) + ) { + /* Let the target do the drawing, but break down the */ + /* fill path into pieces for computing the bounding box. */ + bdev->target = NULL; + gx_default_stroke_path(dev, pis, ppath, params, pdevc, pcpath); + bdev->target = tdev; + } else { + /* Just use the path bounding box. */ + gx_device_bbox *bbdev = bdev->box_device; + + bbox_add_rect(&bbdev->bbox, ibox.p.x, ibox.p.y, ibox.q.x, + ibox.q.y); + } + } + /* Skip the call if there is no target. */ + return (tdev == 0 ? 0 : + (*dev_proc(tdev, stroke_path)) + (tdev, pis, ppath, params, pdevc, pcpath)); +} + +private int +bbox_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_bbox *const bdev = (gx_device_bbox *) dev; + gx_device *tdev = bdev->target; + + if (pcpath != NULL && + !gx_cpath_includes_rectangle(pcpath, int2fixed(x), int2fixed(y), + int2fixed(x + w), + int2fixed(y + h)) + ) { + /* Let the target do the drawing, but break down the */ + /* image into pieces for computing the bounding box. */ + bdev->target = NULL; + gx_default_fill_mask(dev, data, dx, raster, id, x, y, w, h, + pdcolor, depth, lop, pcpath); + bdev->target = tdev; + } else { + /* Just use the mask bounding box. */ + gx_device_bbox *bbdev = bdev->box_device; + + bbox_add_int_rect(&bbdev->bbox, x, y, x + w, y + h); + } + /* Skip the call if there is no target. */ + return (tdev == 0 ? 0 : + (*dev_proc(tdev, fill_mask)) + (tdev, data, dx, raster, id, x, y, w, h, + pdcolor, depth, lop, pcpath)); +} + +/* ------ Bitmap imaging ------ */ + +typedef struct bbox_image_enum_s { + gx_image_enum_common; + gs_memory_t *memory; + gs_matrix matrix; /* map from image space to device space */ + const gx_clip_path *pcpath; + gx_image_enum_common_t *target_info; + int x0, x1; + int y, height; +} bbox_image_enum; + +gs_private_st_ptrs2(st_bbox_image_enum, bbox_image_enum, "bbox_image_enum", +bbox_image_enum_enum_ptrs, bbox_image_enum_reloc_ptrs, pcpath, target_info); + +private image_enum_proc_plane_data(bbox_image_plane_data); +private image_enum_proc_end_image(bbox_image_end_image); +private const gx_image_enum_procs_t bbox_image_enum_procs = +{ + bbox_image_plane_data, bbox_image_end_image +}; + +private int +bbox_image_begin(const gs_imager_state * pis, const gs_matrix * pmat, + const gs_image_common_t * pic, const gs_int_rect * prect, + const gx_clip_path * pcpath, gs_memory_t * memory, + bbox_image_enum ** ppbe) +{ + int code; + gs_matrix mat; + bbox_image_enum *pbe; + + if (pmat == 0) + pmat = &ctm_only(pis); + if ((code = gs_matrix_invert(&pic->ImageMatrix, &mat)) < 0 || + (code = gs_matrix_multiply(&mat, pmat, &mat)) < 0 + ) + return code; + pbe = gs_alloc_struct(memory, bbox_image_enum, &st_bbox_image_enum, + "bbox_image_begin"); + if (pbe == 0) + return_error(gs_error_VMerror); + pbe->memory = memory; + pbe->matrix = mat; + pbe->pcpath = pcpath; + pbe->target_info = 0; /* in case no target */ + if (prect) { + pbe->x0 = prect->p.x, pbe->x1 = prect->q.x; + pbe->y = prect->p.y, pbe->height = prect->q.y - prect->p.y; + } else { + gs_int_point size; + int code = (*pic->type->source_size) (pis, pic, &size); + + if (code < 0) { + gs_free_object(memory, pbe, "bbox_image_begin"); + return code; + } + pbe->x0 = 0, pbe->x1 = size.x; + pbe->y = 0, pbe->height = size.y; + } + *ppbe = pbe; + return 0; +} + +private void +bbox_image_copy_target_info(bbox_image_enum * pbe, gx_device_bbox * dev) +{ + const gx_image_enum_common_t *target_info = pbe->target_info; + + pbe->num_planes = target_info->num_planes; + memcpy(pbe->plane_depths, target_info->plane_depths, + pbe->num_planes * sizeof(pbe->plane_depths[0])); + if (dev->target == 0) { + gx_image_end(pbe->target_info, false); + pbe->target_info = 0; + } +} + +private int +bbox_begin_typed_image(gx_device * dev, + const gs_imager_state * pis, const gs_matrix * pmat, + const gs_image_common_t * pic, const gs_int_rect * prect, + const gx_drawing_color * pdcolor, + const gx_clip_path * pcpath, + gs_memory_t * memory, gx_image_enum_common_t ** pinfo) +{ + bbox_image_enum *pbe; + int code = + bbox_image_begin(pis, pmat, pic, prect, pcpath, memory, &pbe); + + if (code < 0) + return code; + /* We fill in num_planes and plane_depths later. */ + /* format is irrelevant. */ + code = gx_image_enum_common_init((gx_image_enum_common_t *) pbe, pic, + &bbox_image_enum_procs, dev, + 0, 0, gs_image_format_chunky); + if (code < 0) + return code; + *pinfo = (gx_image_enum_common_t *) pbe; + /* + * If there is no target, we still have to call default_begin_image + * to get the correct num_planes and plane_depths. + */ + { + gx_device_bbox *const bdev = (gx_device_bbox *) dev; + gx_device *tdev = bdev->target; + + dev_proc_begin_typed_image((*begin_typed_image)); + + if (tdev == 0) { + tdev = dev; + begin_typed_image = gx_default_begin_typed_image; + } else { + begin_typed_image = dev_proc(tdev, begin_typed_image); + } + code = (*begin_typed_image) + (tdev, pis, pmat, pic, prect, pdcolor, pcpath, memory, + &pbe->target_info); + if (code < 0) + return code; + bbox_image_copy_target_info(pbe, bdev); + } + return 0; +} + +private int +bbox_image_plane_data(gx_device * dev, + gx_image_enum_common_t * info, const gx_image_plane_t * planes, int height) +{ + + gx_device_bbox *const bdev = (gx_device_bbox *) dev; + gx_device *tdev = bdev->target; + bbox_image_enum *pbe = (bbox_image_enum *) info; + const gx_clip_path *pcpath = pbe->pcpath; + gs_rect sbox, dbox; + gs_point corners[4]; + gs_fixed_rect ibox; + + sbox.p.x = pbe->x0; + sbox.p.y = pbe->y; + sbox.q.x = pbe->x1; + sbox.q.y = pbe->y += height; + gs_bbox_transform_only(&sbox, &pbe->matrix, corners); + gs_points_bbox(corners, &dbox); + ibox.p.x = float2fixed(dbox.p.x); + ibox.p.y = float2fixed(dbox.p.y); + ibox.q.x = float2fixed(dbox.q.x); + ibox.q.y = float2fixed(dbox.q.y); + if (pcpath != NULL && + !gx_cpath_includes_rectangle(pcpath, ibox.p.x, ibox.p.y, + ibox.q.x, ibox.q.y) + ) { + /* Let the target do the drawing, but drive two triangles */ + /* through the clipping path to get an accurate bounding box. */ + gx_device_clip cdev; + gx_drawing_color devc; + fixed x0 = float2fixed(corners[0].x), y0 = float2fixed(corners[0].y); + fixed bx2 = float2fixed(corners[2].x) - x0, by2 = float2fixed(corners[2].y) - y0; + + gx_make_clip_path_device(&cdev, pcpath); + cdev.target = dev; + (*dev_proc(&cdev, open_device)) ((gx_device *) & cdev); + color_set_pure(&devc, 0); /* any color will do */ + bdev->target = NULL; + gx_default_fill_triangle((gx_device *) & cdev, x0, y0, + float2fixed(corners[1].x) - x0, + float2fixed(corners[1].y) - y0, + bx2, by2, &devc, lop_default); + gx_default_fill_triangle((gx_device *) & cdev, x0, y0, + float2fixed(corners[3].x) - x0, + float2fixed(corners[3].y) - y0, + bx2, by2, &devc, lop_default); + bdev->target = tdev; + } else { + /* Just use the bounding box. */ + gx_device_bbox *bbdev = bdev->box_device; + + bbox_add_rect(&bbdev->bbox, ibox.p.x, ibox.p.y, ibox.q.x, ibox.q.y); + } + /* Skip the call if there is no target. */ + return (tdev == 0 ? pbe->y >= pbe->height : + gx_image_plane_data(pbe->target_info, planes, height)); +} + +private int +bbox_image_end_image(gx_device * dev, gx_image_enum_common_t * info, + bool draw_last) +{ + gx_device_bbox *const bdev = (gx_device_bbox *) dev; + bbox_image_enum *pbe = (bbox_image_enum *) info; + void *target_info = pbe->target_info; + + /* Skip the call if there is no target. */ + gx_device *tdev = bdev->target; + int code = + (tdev == 0 ? 0 : gx_image_end(target_info, draw_last)); + + gs_free_object(pbe->memory, pbe, "bbox_end_image"); + return code; +} + +private int +bbox_create_compositor(gx_device * dev, + gx_device ** pcdev, const gs_composite_t * pcte, + const gs_imager_state * pis, gs_memory_t * memory) +{ + gx_device_bbox *const bdev = (gx_device_bbox *) dev; + gx_device *target = bdev->target; + + /* + * If there isn't a target, all we care about is the bounding box, + * so don't bother with actually compositing. + */ + if (target == 0) { + *pcdev = dev; + return 0; + } + /* + * Create a compositor for the target, and then wrap another + * bbox device around it, but still accumulating the bounding + * box in the same place. + */ + { + gx_device *cdev; + gx_device_bbox *bbcdev; + int code = (*dev_proc(target, create_compositor)) + (target, &cdev, pcte, pis, memory); + + if (code < 0) + return code; + bbcdev = gs_alloc_struct_immovable(memory, gx_device_bbox, + &st_device_bbox, + "bbox_create_compositor"); + if (bbcdev == 0) { + (*dev_proc(cdev, close_device)) (cdev); + return_error(gs_error_VMerror); + } + gx_device_bbox_init(bbcdev, target); + bbcdev->target = cdev; + bbcdev->box_device = bdev; + *pcdev = (gx_device *) bbcdev; + return 0; + } +} + +/* ------ Text imaging ------ */ + +extern_st(st_gs_text_enum); + +typedef struct bbox_text_enum_s { + gs_text_enum_common; + gs_text_enum_t *target_info; +} bbox_text_enum; + +gs_private_st_suffix_add1(st_bbox_text_enum, bbox_text_enum, "bbox_text_enum", + bbox_text_enum_enum_ptrs, bbox_text_enum_reloc_ptrs, + st_gs_text_enum, target_info); + +private text_enum_proc_process(bbox_text_process); +private text_enum_proc_set_cache(bbox_text_set_cache); +private rc_free_proc(bbox_text_free); + +private const gs_text_enum_procs_t bbox_text_procs = +{ + bbox_text_process, bbox_text_set_cache +}; + +private int +bbox_text_begin(gx_device * dev, gs_imager_state * pis, + const gs_text_params_t * text, const gs_font * font, +gx_path * path, const gx_device_color * pdcolor, const gx_clip_path * pcpath, + gs_memory_t * memory, gs_text_enum_t ** ppenum) +{ + gx_device_bbox *const bdev = (gx_device_bbox *) dev; + gx_device *tdev = bdev->target; + bbox_text_enum *pbte; + int code; + + if (tdev == 0) + return gx_default_text_begin(dev, pis, text, font, path, pdcolor, + pcpath, memory, ppenum); + rc_alloc_struct_1(pbte, bbox_text_enum, &st_bbox_text_enum, memory, + return_error(gs_error_VMerror), + "bbox_text_begin"); + pbte->rc.free = bbox_text_free; + code = + (*dev_proc(tdev, text_begin)) + (tdev, pis, text, font, path, pdcolor, pcpath, memory, + &pbte->target_info); + if (code < 0) { + gs_free_object(memory, pbte, "bbox_text_begin"); + return code; + } + *(gs_text_enum_t *) pbte = *pbte->target_info; /* copy common info */ + pbte->procs = &bbox_text_procs; + *ppenum = (gs_text_enum_t *) pbte; + return code; +} + +private int +bbox_text_process(gs_text_enum_t * pte) +{ + bbox_text_enum *const pbte = (bbox_text_enum *) pte; + int code = gs_text_process(pbte->target_info); + + if (code < 0) + return code; + /* Copy back the dynamic information for the client. */ + pte->index = pbte->target_info->index; + return code; +} + +private int +bbox_text_set_cache(gs_text_enum_t * pte, const double *values, + gs_text_cache_control_t control) +{ + bbox_text_enum *const pbte = (bbox_text_enum *) pte; + gs_text_enum_t *tpte = pbte->target_info; + int code = tpte->procs->set_cache(tpte, values, control); + + if (code < 0) + return code; + /* Copy back the dynamic information for the client. */ + pte->index = tpte->index; + return code; +} + +private void +bbox_text_free(gs_memory_t * memory, void *vpte, client_name_t cname) +{ + bbox_text_enum *const pbte = (bbox_text_enum *) vpte; + + gs_text_release(pbte->target_info, cname); + rc_free_struct_only(memory, vpte, cname); +} diff --git a/pstoraster/gdevbbox.h b/pstoraster/gdevbbox.h new file mode 100644 index 0000000000..5b647347b0 --- /dev/null +++ b/pstoraster/gdevbbox.h @@ -0,0 +1,100 @@ +/* Copyright (C) 1996, 1997, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Requires gxdevice.h */ + +#ifndef gdevbbox_INCLUDED +# define gdevbbox_INCLUDED + +/* + * This device keeps track of the per-page bounding box, and also optionally + * forwards all drawing commands to a target. It can be used either as a + * free-standing device or as a component (e.g., by the EPS writer). + * + * One way to use a bounding box device is simply to include bbox.dev in the + * value of DEVICE_DEVSn in the makefile. This produces a free-standing + * device named 'bbox' that can be selected in the usual way (-sDEVICE=bbox) + * and that prints out the bounding box at each showpage or copypage without + * doing any drawing. + * + * The other way to use a bounding box device is from C code as a component + * in a device pipeline. To set up a bounding box device that doesn't do + * any drawing: + * gx_device_bbox *bdev = + * gs_alloc_struct_immovable(some_memory, + * gx_device_bbox, &st_device_bbox, + * "some identifying string for debugging"); + * gx_device_bbox_init(bdev, NULL); + * Non-drawing bounding box devices have an "infinite" page size. + * + * To set up a bounding box device that draws to another device tdev: + * gx_device_bbox *bdev = + * gs_alloc_struct_immovable(some_memory, + * gx_device_bbox, &st_device_bbox, + * "some identifying string for debugging"); + * gx_device_bbox_init(bdev, tdev); + * Bounding box devices that draw to a real device appear to have the + * same page size as that device. + * + * To intercept the end-of-page to call a routine eop of your own, after + * setting up the device: + * dev_proc_output_page(eop); -- declare a prototype for eop + * ... + * set_dev_proc(bdev, output_page, eop); + * ... + * int eop(gx_device *dev, int num_copies, int flush) + * { gs_rect bbox; + * gx_device_bbox_bbox((gx_device_bbox *)dev, &bbox); + * << do whatever you want >> + * return gx_forward_output_page(dev, num_copies, flush); + * } + */ +#define gx_device_bbox_common\ + gx_device_forward_common;\ + bool free_standing;\ + /* In order to handle compositors, we provide a separate pointer */\ + /* to the bbox device instance that holds the actual box. */\ + gx_device_bbox *box_device;\ + /* The following are updated dynamically. */\ + gs_fixed_rect bbox;\ + gx_color_index white +typedef struct gx_device_bbox_s gx_device_bbox; +struct gx_device_bbox_s { + gx_device_bbox_common; +}; + +extern_st(st_device_bbox); +#define public_st_device_bbox() /* in gdevbbox.c */\ + gs_public_st_suffix_add1_final(st_device_bbox, gx_device_bbox,\ + "gx_device_bbox", device_bbox_enum_ptrs, device_bbox_reloc_ptrs,\ + gx_device_finalize, st_device_forward, box_device) + +/* Initialize a bounding box device. */ +void gx_device_bbox_init(P2(gx_device_bbox * dev, gx_device * target)); + +/* Read back the bounding box in 1/72" units. */ +void gx_device_bbox_bbox(P2(gx_device_bbox * dev, gs_rect * pbbox)); + +#endif /* gdevbbox_INCLUDED */ diff --git a/pstoraster/gdevcmap.h b/pstoraster/gdevcmap.h new file mode 100644 index 0000000000..abfa9266f7 --- /dev/null +++ b/pstoraster/gdevcmap.h @@ -0,0 +1,74 @@ +/* Copyright (C) 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Interface to special color mapping device */ + +#ifndef gdevcmap_INCLUDED +# define gdevcmap_INCLUDED + +/* Define the color mapping algorithms. */ +typedef enum { + + /* Don't change the color. */ + + device_cmap_identity = 0, + + /* Snap each RGB primary component to 0 or 1 individually. */ + + device_cmap_snap_to_primaries, + + /* Snap black to white, other colors to black. */ + + device_cmap_color_to_black_over_white, + + /* Convert to a gray shade of the correct brightness. */ + + device_cmap_monochrome + +} gx_device_color_mapping_method_t; + +#define device_cmap_max_method device_cmap_monochrome + +/* Define the color mapping forwarding device. */ +typedef struct gx_device_cmap_s { + gx_device_forward_common; + gx_device_color_mapping_method_t mapping_method; +} gx_device_cmap; + +extern_st(st_device_cmap); +#define public_st_device_cmap() /* in gdevcmap.c */\ + gs_public_st_suffix_add0_final(st_device_cmap, gx_device_cmap,\ + "gx_device_cmap", device_cmap_enum_ptrs, device_cmap_reloc_ptrs,\ + gx_device_finalize, st_device_forward) + +/* Initialize a color mapping device. Do this just once after allocation. */ +int gdev_cmap_init(P3(gx_device_cmap * dev, gx_device * target, + gx_device_color_mapping_method_t mapping_method)); + +/* Set the color mapping method. This may be called at any time. */ +int gdev_cmap_set_method(P2(gx_device_cmap * dev, + gx_device_color_mapping_method_t mapping_method)); + +#endif /* gdevcmap_INCLUDED */ diff --git a/pstoraster/gdevcups.c b/pstoraster/gdevcups.c new file mode 100644 index 0000000000..c7579776d2 --- /dev/null +++ b/pstoraster/gdevcups.c @@ -0,0 +1,3015 @@ +/* + * "$Id$" + * + * GNU Ghostscript raster output driver 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 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 "gsexit.h" + +#include +#include +#include +#include + +#undef private +#define private + + +/* + * 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_cmyk_color(cups_map_cmyk_color); +private dev_proc_map_color_rgb(cups_map_color_rgb); +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, /* 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 */ +}; + +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]; +static unsigned char rev_lower1[16] = + { + 0x00, 0x08, 0x04, 0x0c, 0x02, 0x0a, 0x06, 0x0e, + 0x01, 0x09, 0x05, 0x0d, 0x03, 0x0b, 0x07, 0x0f + }, + rev_upper1[16] = + { + 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, + 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0 + }, + rev_lower2[16] = /* 2-bit colors */ + { + 0x00, 0x04, 0x08, 0x0c, 0x01, 0x05, 0x09, 0x0d, + 0x02, 0x06, 0x0a, 0x0e, 0x03, 0x07, 0x0b, 0x0f + }, + rev_upper2[16] = /* 2-bit colors */ + { + 0x00, 0x40, 0x80, 0xc0, 0x10, 0x50, 0x90, 0xd0, + 0x20, 0x60, 0xa0, 0xe0, 0x30, 0x70, 0xb0, 0xf0 + }; + + +/* + * Local functions... + */ + +static void cups_print_chunked(gx_device_printer *, unsigned char *, + unsigned char *, int); +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(%p)\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(%p, %p)\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... + */ + + fprintf(stderr, "DEBUG: cups->header.Duplex = %d\n", cups->header.Duplex); + fprintf(stderr, "DEBUG: cups->ppd = %p\n", cups->ppd); + fprintf(stderr, "DEBUG: cups->ppd->flip_duplex = %d\n", cups->ppd->flip_duplex); + fprintf(stderr, "DEBUG: cups->page = %d\n", cups->page); + + if (cups->header.Duplex && cups->ppd && cups->ppd->flip_duplex && + !(cups->page & 1)) + { + 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[2] / 72.0; + pmat->ty = -(float)cups->header.HWResolution[1] * pdev->HWMargins[3] / 72.0; + } + else + { + 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; + } + + 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: HWMargins = [ %.3f %.3f %.3f %.3f ]\n", + pdev->HWMargins[0], pdev->HWMargins[1], pdev->HWMargins[2], + pdev->HWMargins[3]); + fprintf(stderr, "DEBUG: matrix = [ %.3f %.3f %.3f %.3f %.3f %.3f ]\n", + pmat->xx, pmat->xy, pmat->yx, pmat->yy, pmat->tx, pmat->ty); +} + + +/* + * '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 */ + gs_param_string s; /* Temporary string value */ + bool b; /* Temporary boolean value */ + + +#ifdef DEBUG + fprintf(stderr, "DEBUG: cups_get_params(%p, %p)\n", pdev, plist); +#endif /* DEBUG */ + + /* + * First process the "standard" page device parameters... + */ + +#ifdef DEBUG + fputs("DEBUG: before gdev_prn_get_params()\n", stderr); +#endif /* DEBUG */ + + if ((code = gdev_prn_get_params(pdev, plist)) < 0) + return (code); + +#ifdef DEBUG + fputs("DEBUG: after gdev_prn_get_params()\n", stderr); +#endif /* DEBUG */ + + /* + * Then write the CUPS parameters... + */ + +#ifdef DEBUG + fputs("DEBUG: MediaClass\n", stderr); +#endif /* DEBUG */ + + param_string_from_string(s, cups->header.MediaClass); + if ((code = param_write_string(plist, "MediaClass", &s)) < 0) + return (code); + +#ifdef DEBUG + fputs("DEBUG: AdvanceDistance\n", stderr); +#endif /* DEBUG */ + + if ((code = param_write_int(plist, "AdvanceDistance", + (int *)&(cups->header.AdvanceDistance))) < 0) + return (code); + +#ifdef DEBUG + fputs("DEBUG: AdvanceDistance\n", stderr); +#endif /* DEBUG */ + + if ((code = param_write_int(plist, "AdvanceMedia", + (int *)&(cups->header.AdvanceMedia))) < 0) + return (code); + +#ifdef DEBUG + fputs("DEBUG: Collate\n", stderr); +#endif /* DEBUG */ + + b = cups->header.Collate; + if ((code = param_write_bool(plist, "Collate", &b)) < 0) + return (code); + +#ifdef DEBUG + fputs("DEBUG: CutMedia\n", stderr); +#endif /* DEBUG */ + + if ((code = param_write_int(plist, "CutMedia", + (int *)&(cups->header.CutMedia))) < 0) + return (code); + +#ifdef DEBUG + fputs("DEBUG: InsertSheet\n", stderr); +#endif /* DEBUG */ + + b = cups->header.InsertSheet; + if ((code = param_write_bool(plist, "InsertSheet", &b)) < 0) + return (code); + +#ifdef DEBUG + fputs("DEBUG: Jog\n", stderr); +#endif /* DEBUG */ + + if ((code = param_write_int(plist, "Jog", + (int *)&(cups->header.Jog))) < 0) + return (code); + +#ifdef DEBUG + fputs("DEBUG: LeadingEdge\n", stderr); +#endif /* DEBUG */ + + if ((code = param_write_int(plist, "LeadingEdge", + (int *)&(cups->header.LeadingEdge))) < 0) + return (code); + +#ifdef DEBUG + fputs("DEBUG: ManualFeed\n", stderr); +#endif /* DEBUG */ + + b = cups->header.ManualFeed; + if ((code = param_write_bool(plist, "ManualFeed", &b)) < 0) + return (code); + +#ifdef DEBUG + fputs("DEBUG: MediaPosition\n", stderr); +#endif /* DEBUG */ + + if ((code = param_write_int(plist, "MediaPosition", + (int *)&(cups->header.MediaPosition))) < 0) + return (code); + +#ifdef DEBUG + fputs("DEBUG: MirrorPrint\n", stderr); +#endif /* DEBUG */ + + b = cups->header.MirrorPrint; + if ((code = param_write_bool(plist, "MirrorPrint", &b)) < 0) + return (code); + +#ifdef DEBUG + fputs("DEBUG: NegativePrint\n", stderr); +#endif /* DEBUG */ + + b = cups->header.NegativePrint; + if ((code = param_write_bool(plist, "NegativePrint", &b)) < 0) + return (code); + +#ifdef DEBUG + fputs("DEBUG: OutputFaceUp\n", stderr); +#endif /* DEBUG */ + + b = cups->header.OutputFaceUp; + if ((code = param_write_bool(plist, "OutputFaceUp", &b)) < 0) + return (code); + +#ifdef DEBUG + fputs("DEBUG: Separations\n", stderr); +#endif /* DEBUG */ + + b = cups->header.Separations; + if ((code = param_write_bool(plist, "Separations", &b)) < 0) + return (code); + +#ifdef DEBUG + fputs("DEBUG: TraySwitch\n", stderr); +#endif /* DEBUG */ + + b = cups->header.TraySwitch; + if ((code = param_write_bool(plist, "TraySwitch", &b)) < 0) + return (code); + +#ifdef DEBUG + fputs("DEBUG: Tumble\n", stderr); +#endif /* DEBUG */ + + b = cups->header.Tumble; + if ((code = param_write_bool(plist, "Tumble", &b)) < 0) + return (code); + +#ifdef DEBUG + fputs("DEBUG: cupsWidth\n", stderr); +#endif /* DEBUG */ + + if ((code = param_write_int(plist, "cupsWidth", + (int *)&(cups->header.cupsWidth))) < 0) + return (code); + +#ifdef DEBUG + fputs("DEBUG: cupsHeight\n", stderr); +#endif /* DEBUG */ + + if ((code = param_write_int(plist, "cupsHeight", + (int *)&(cups->header.cupsHeight))) < 0) + return (code); + +#ifdef DEBUG + fputs("DEBUG: cupsMediaType\n", stderr); +#endif /* DEBUG */ + + if ((code = param_write_int(plist, "cupsMediaType", + (int *)&(cups->header.cupsMediaType))) < 0) + return (code); + +#ifdef DEBUG + fputs("DEBUG: cupsBitsPerColor\n", stderr); +#endif /* DEBUG */ + + if ((code = param_write_int(plist, "cupsBitsPerColor", + (int *)&(cups->header.cupsBitsPerColor))) < 0) + return (code); + +#ifdef DEBUG + fputs("DEBUG: cupsBitsPerPixel\n", stderr); +#endif /* DEBUG */ + + if ((code = param_write_int(plist, "cupsBitsPerPixel", + (int *)&(cups->header.cupsBitsPerPixel))) < 0) + return (code); + +#ifdef DEBUG + fputs("DEBUG: cupsBytesPerLine\n", stderr); +#endif /* DEBUG */ + + if ((code = param_write_int(plist, "cupsBytesPerLine", + (int *)&(cups->header.cupsBytesPerLine))) < 0) + return (code); + +#ifdef DEBUG + fputs("DEBUG: cupsColorOrder\n", stderr); +#endif /* DEBUG */ + + if ((code = param_write_int(plist, "cupsColorOrder", + (int *)&(cups->header.cupsColorOrder))) < 0) + return (code); + +#ifdef DEBUG + fputs("DEBUG: cupsColorSpace\n", stderr); +#endif /* DEBUG */ + + if ((code = param_write_int(plist, "cupsColorSpace", + (int *)&(cups->header.cupsColorSpace))) < 0) + return (code); + +#ifdef DEBUG + fputs("DEBUG: cupsCompression\n", stderr); +#endif /* DEBUG */ + + if ((code = param_write_int(plist, "cupsCompression", + (int *)&(cups->header.cupsCompression))) < 0) + return (code); + +#ifdef DEBUG + fputs("DEBUG: cupsRowCount\n", stderr); +#endif /* DEBUG */ + + if ((code = param_write_int(plist, "cupsRowCount", + (int *)&(cups->header.cupsRowCount))) < 0) + return (code); + +#ifdef DEBUG + fputs("DEBUG: cupsRowFeed\n", stderr); +#endif /* DEBUG */ + + if ((code = param_write_int(plist, "cupsRowFeed", + (int *)&(cups->header.cupsRowFeed))) < 0) + return (code); + +#ifdef DEBUG + fputs("DEBUG: cupsRowStep\n", stderr); +#endif /* DEBUG */ + + if ((code = param_write_int(plist, "cupsRowStep", + (int *)&(cups->header.cupsRowStep))) < 0) + return (code); + +#ifdef DEBUG + fputs("DEBUG: Leaving cups_get_params()\n", stderr); +#endif /* DEBUG */ + + return (0); +} + + +/* + * 'cups_map_cmyk_color()' - Map a CMYK color to a color index. + * + * This function is only called when a 4 or 6 color colorspace is + * selected for output. CMYK colors are *not* corrected but *are* + * density adjusted. + */ + +private gx_color_index /* O - Color index */ +cups_map_cmyk_color(gx_device *pdev, /* I - Device info */ + gx_color_value c, /* I - Cyan value */ + gx_color_value m, /* I - Magenta value */ + gx_color_value y, /* I - Yellow value */ + gx_color_value k) /* I - Black value */ +{ + gx_color_index i; /* Temporary index */ + gx_color_value ic, im, iy, ik; /* Integral CMYK values */ + + +#ifdef DEBUG + fprintf(stderr, "DEBUG: cups_map_cmyk_color(%p, %d, %d, %d, %d)\n", pdev, + c, m, y, k); +#endif /* DEBUG */ + + /* + * Setup the color info data as needed... + */ + + if (pdev->color_info.num_components == 0) + cups_set_color_info(pdev); + + /* + * Density correct... + */ + + c = cupsDensity[c]; + m = cupsDensity[m]; + y = cupsDensity[y]; + k = cupsDensity[k]; + + ic = lut_rgb_color[c]; + im = lut_rgb_color[m]; + iy = lut_rgb_color[y]; + ik = lut_rgb_color[k]; + + /* + * Convert the CMYK color to a color index... + */ + + switch (cups->header.cupsColorSpace) + { + default : + switch (cups->header.cupsBitsPerColor) + { + default : + 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; + } + break; + + case CUPS_CSPACE_YMCK : + case CUPS_CSPACE_GMCK : + case CUPS_CSPACE_GMCS : + switch (cups->header.cupsBitsPerColor) + { + default : + 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) + { + if (ik) + i = 32; + else + i = 0; + + 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; + break; + } + + case CUPS_CSPACE_KCMY : + switch (cups->header.cupsBitsPerColor) + { + default : + 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; + } + + if (gs_log_errors > 1) + fprintf(stderr, "DEBUG: CMYK (%d,%d,%d,%d) -> CMYK %8x (%d,%d,%d,%d)\n", + c, m, y, k, i, ic, im, iy, ik); + + return (i); +} + + +/* + * '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(%p, %d, %8x)\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 %8x = ", color); +#endif /* DEBUG */ + + /* + * Extract the color components from the color index... + */ + + switch (cups->header.cupsBitsPerColor) + { + default : + 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; + c1 = 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_RGBA : + prgb[0] = lut_color_rgb[c0]; + prgb[1] = lut_color_rgb[c1]; + prgb[2] = lut_color_rgb[c2]; + 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 : + case CUPS_CSPACE_KCMYcm : + k = lut_color_rgb[c0]; + divk = gx_max_color_value - k; + if (divk == 0) + { + prgb[0] = 0; + prgb[1] = 0; + prgb[2] = 0; + } + else + { + prgb[0] = gx_max_color_value + divk - + gx_max_color_value * c1 / divk; + prgb[1] = gx_max_color_value + divk - + gx_max_color_value * c2 / divk; + prgb[2] = gx_max_color_value + divk - + gx_max_color_value * c3 / divk; + } + break; + + case CUPS_CSPACE_CMYK : + k = lut_color_rgb[c3]; + divk = gx_max_color_value - k; + if (divk == 0) + { + prgb[0] = 0; + prgb[1] = 0; + prgb[2] = 0; + } + else + { + prgb[0] = gx_max_color_value + divk - + gx_max_color_value * c0 / divk; + prgb[1] = gx_max_color_value + divk - + gx_max_color_value * c1 / divk; + prgb[2] = gx_max_color_value + divk - + gx_max_color_value * c2 / divk; + } + break; + + case CUPS_CSPACE_YMCK : + case CUPS_CSPACE_GMCK : + case CUPS_CSPACE_GMCS : + k = lut_color_rgb[c3]; + divk = gx_max_color_value - k; + if (divk == 0) + { + prgb[0] = 0; + prgb[1] = 0; + prgb[2] = 0; + } + else + { + prgb[0] = gx_max_color_value + divk - + gx_max_color_value * c2 / divk; + prgb[1] = gx_max_color_value + divk - + gx_max_color_value * c1 / divk; + prgb[2] = gx_max_color_value + divk - + gx_max_color_value * c0 / divk; + } + break; + } + +#ifdef DEBUG + fprintf(stderr, "%d,%d,%d\n", prgb[0], prgb[1], prgb[2]); +#endif /* DEBUG */ + + return (0); +} + + +/* + * 'cups_map_rgb_color()' - Map an RGB color to a color index. We map the + * RGB color to the output colorspace & bits (we + * figure out the format when we output a page). + */ + +private gx_color_index /* O - Color index */ +cups_map_rgb_color(gx_device *pdev, /* I - Device info */ + gx_color_value r, /* I - Red value */ + gx_color_value g, /* I - Green value */ + gx_color_value b) /* I - Blue value */ +{ + gx_color_index i; /* Temporary index */ + gx_color_value ic, im, iy, ik; /* Integral CMYK values */ + int tc, tm, ty; /* Temporary color values */ + + +#ifdef DEBUG + fprintf(stderr, "DEBUG: cups_map_rgb_color(%p, %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) + { + default : + 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_RGBA : + ic = lut_rgb_color[r]; + im = lut_rgb_color[g]; + iy = lut_rgb_color[b]; + + switch (cups->header.cupsBitsPerColor) + { + default : + i = (((((ic << 1) | im) << 1) | iy) << 1) | 0x01; + break; + case 2 : + i = (((((ic << 2) | im) << 2) | iy) << 2) | 0x03; + break; + case 4 : + i = (((((ic << 4) | im) << 4) | iy) << 4) | 0x0f; + break; + case 8 : + i = (((((ic << 8) | im) << 8) | iy) << 8) | 0xff; + break; + } + break; + + default : + 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) + { + default : + 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) + { + default : + 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)); + + 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) + { + default : + 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 %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)); + + 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) + { + default : + 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)); + + 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) + { + default : + 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 = %8x\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(%p)\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 */ + unsigned char *src, /* Scanline data */ + *dst; /* Bitmap data */ + + + (void)fp; /* reference unused file pointer to prevent compiler warning */ + +#ifdef DEBUG + fprintf(stderr, "DEBUG: cups_print_pages(%p, %p, %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); + + /* + * 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); + + /* + * See if the stream has been initialized yet... + */ + + if (cups->stream == NULL) + { + if ((cups->stream = cupsRasterOpen(1, CUPS_RASTER_WRITE)) == 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, dst, srcbytes); + else + switch (cups->header.cupsColorOrder) + { + case CUPS_ORDER_CHUNKED : + cups_print_chunked(pdev, src, dst, srcbytes); + 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"); + 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 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 */ + int old_depth; /* Old color depth */ + gdev_prn_space_params sp; /* Space parameter data */ + + +#ifdef DEBUG + fprintf(stderr, "DEBUG: cups_put_params(%p, %p)\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) \ + { \ + fprintf(stderr, "DEBUG: Setting %s to %d...\n", sname, intval); \ + 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]; \ + } + + old_depth = pdev->color_info.depth; + + 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) /* Compatibility */ + intoption(MediaPosition, "MediaPosition", 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(cupsMediaType, "cupsMediaType", unsigned) + intoption(cupsBitsPerColor, "cupsBitsPerColor", 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) + + cups_set_color_info(pdev); + + if (old_depth != pdev->color_info.depth) + { + fputs("DEBUG: Reallocating memory for new color depth...\n", stderr); + sp = ((gx_device_printer *)pdev)->space_params; + + if ((code = gdev_prn_reallocate_memory(pdev, &sp, pdev->width, + pdev->height)) < 0) + return (code); + } + + /* + * Compute the page margins... + */ + + if (cups->ppd != NULL) + { + /* + * Pull the margins from the first size entry; since the margins are not + * like the bounding box we have to adjust the top and right values + * accordingly. + */ + + for (i = cups->ppd->num_sizes, size = cups->ppd->sizes; + i > 0; + i --, size ++) + if ((fabs(cups->PageSize[1] - size->length) < 18.0 && + fabs(cups->PageSize[0] - size->width) < 18.0) || + (fabs(cups->PageSize[0] - size->length) < 18.0 && + fabs(cups->PageSize[1] - size->width) < 18.0)) + break; + + if (i == 0 && !cups->ppd->variable_sizes) + { + i = 1; + size = cups->ppd->sizes; + } + + if (i > 0) + { + /* + * Standard size... + */ + + fprintf(stderr, "DEBUG: size = %s\n", size->name); + + 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 + { + /* + * Custom size... + */ + + fputs("DEBUG: size = Custom\n", stderr); + + for (i = 0; i < 4; i ++) + margins[i] = cups->ppd->custom_margins[i] / 72.0; + } + + fprintf(stderr, "DEBUG: margins[] = [ %f %f %f %f ]\n", + margins[0], margins[1], margins[2], margins[3]); + } + else + { + /* + * Set default margins of 0.0... + */ + + memset(margins, 0, sizeof(margins)); + } + + /* + * Set the margins to update the bitmap size... + */ + + gx_device_set_margins(pdev, margins, false); + + /* + * 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->PageSize[0]; + cups->header.PageSize[1] = pdev->PageSize[1]; + +#ifdef DEBUG + fprintf(stderr, "DEBUG: ppd = %8x\n", cups->ppd); + fprintf(stderr, "DEBUG: PageSize = [ %.3f %.3f ]\n", + pdev->PageSize[0], pdev->PageSize[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 */ + + 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(%p)\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; + } + + /* + * Enable/disable CMYK color support... + */ + + if (cups->color_info.num_components == 4) + cups->procs.map_cmyk_color = cups_map_cmyk_color; + else + cups->procs.map_cmyk_color = NULL; + + /* + * 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 */ + unsigned char *dst, /* I - Bitmap buffer */ + int srcbytes) /* I - Number of bytes in src */ +{ + int y; /* Looping var */ + unsigned char *srcptr, /* Pointer to data */ + *dstptr; /* Pointer to bits */ + int count; /* Count for loop */ + int flip; /* Flip scanline? */ + + + if (cups->header.Duplex && cups->ppd && cups->ppd->flip_duplex && + !(cups->page & 1)) + flip = 1; + else + flip = 0; + + /* + * Loop through the page bitmap and write chunked pixels, reversing as + * needed... + */ + + 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); + } + + if (flip) + { + /* + * Flip the raster data before writing it... + */ + + if (srcptr[0] == 0 && memcmp(srcptr, srcptr + 1, srcbytes - 1) == 0) + memset(dst, 0, cups->header.cupsBytesPerLine); + else + { + dstptr = dst; + count = srcbytes; + + switch (cups->color_info.depth) + { + case 1 : /* B&W bitmap */ + for (srcptr += srcbytes - 1; + count > 0; + count --, srcptr --, dstptr ++) + { + *dstptr = rev_upper1[*srcptr & 15] | + rev_lower1[*srcptr >> 4]; + } + break; + + case 2 : /* 2-bit grayscale */ + for (srcptr += srcbytes - 1; + count > 0; + count --, srcptr --, dstptr ++) + { + *dstptr = rev_upper2[*srcptr & 15] | + rev_lower2[*srcptr >> 4]; + } + break; + + case 4 : /* 4-bit grayscale, or RGB, CMY, or CMYK bitmap */ + for (srcptr += srcbytes - 1; + count > 0; + count --, srcptr --, dstptr ++) + *dstptr = (*srcptr >> 4) | (*srcptr << 4); + break; + + case 8 : /* 8-bit grayscale, or 2-bit RGB, CMY, or CMYK image */ + for (srcptr += srcbytes - 1; + count > 0; + count --, srcptr --, dstptr ++) + *dstptr = *srcptr; + break; + + case 16 : /* 4-bit RGB, CMY or CMYK image */ + for (srcptr += srcbytes - 2; + count > 0; + count -= 2, srcptr -= 2, dstptr += 2) + { + dstptr[0] = srcptr[0]; + dstptr[1] = srcptr[1]; + } + break; + + case 24 : /* 8-bit RGB or CMY image */ + for (srcptr += srcbytes - 3; + count > 0; + count -= 3, srcptr -= 3, dstptr += 3) + { + dstptr[0] = srcptr[0]; + dstptr[1] = srcptr[1]; + dstptr[2] = srcptr[2]; + } + break; + + case 32 : /* 4-bit RGB, CMY or CMYK bitmap */ + for (srcptr += srcbytes - 4; + count > 0; + count -= 4, srcptr -= 4, dstptr += 4) + { + dstptr[0] = srcptr[0]; + dstptr[1] = srcptr[1]; + dstptr[2] = srcptr[2]; + dstptr[3] = srcptr[3]; + } + break; + } + } + + /* + * Write the bitmap data to the raster stream... + */ + + cupsRasterWritePixels(cups->stream, dst, cups->header.cupsBytesPerLine); + } + else + { + /* + * 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; /* ... */ + int flip; /* Flip scanline? */ + + + if (cups->header.Duplex && cups->ppd && cups->ppd->flip_duplex && + !(cups->page & 1)) + flip = 1; + else + flip = 0; + + /* + * 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 + { + if (flip) + cptr = dst + bandbytes - 1; + else + cptr = dst; + + mptr = cptr + bandbytes; + yptr = mptr + bandbytes; + kptr = yptr + bandbytes; + lcptr = yptr + bandbytes; + lmptr = lcptr + bandbytes; + + switch (cups->header.cupsBitsPerColor) + { + default : + memset(dst, 0, cups->header.cupsBytesPerLine); + + switch (cups->header.cupsColorSpace) + { + default : + for (x = cups->width, bit = flip ? 1 << (x & 7) : 128; + x > 0; + x --, srcptr ++) + { + if (*srcptr & 0x40) + *cptr |= bit; + if (*srcptr & 0x20) + *mptr |= bit; + if (*srcptr & 0x10) + *yptr |= bit; + + if (flip) + { + if (bit < 128) + bit <<= 1; + else + { + cptr --; + mptr --; + yptr --; + bit = 1; + } + } + else + bit >>= 1; + + x --; + if (x == 0) + break; + + if (*srcptr & 0x4) + *cptr |= bit; + if (*srcptr & 0x2) + *mptr |= bit; + if (*srcptr & 0x1) + *yptr |= bit; + + if (flip) + { + if (bit < 128) + bit <<= 1; + else + { + cptr --; + mptr --; + yptr --; + bit = 1; + } + } + else if (bit > 1) + bit >>= 1; + else + { + cptr ++; + mptr ++; + yptr ++; + bit = 128; + } + } + break; + case CUPS_CSPACE_GMCK : + case CUPS_CSPACE_GMCS : + case CUPS_CSPACE_RGBA : + case CUPS_CSPACE_CMYK : + case CUPS_CSPACE_YMCK : + case CUPS_CSPACE_KCMY : + for (x = cups->width, bit = flip ? 1 << (x & 7) : 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; + + if (flip) + { + if (bit < 128) + bit <<= 1; + else + { + cptr --; + mptr --; + yptr --; + kptr --; + bit = 1; + } + } + else + 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 (flip) + { + if (bit < 128) + bit <<= 1; + else + { + cptr --; + mptr --; + yptr --; + kptr --; + bit = 1; + } + } + else if (bit > 1) + bit >>= 1; + else + { + cptr ++; + mptr ++; + yptr ++; + kptr ++; + bit = 128; + } + } + break; + case CUPS_CSPACE_KCMYcm : + for (x = cups->width, bit = flip ? 1 << (x & 7) : 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 (flip) + { + if (bit < 128) + bit <<= 1; + else + { + cptr --; + mptr --; + yptr --; + kptr --; + lcptr --; + lmptr --; + bit = 1; + } + } + else 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) + { + default : + for (x = cups->width, bit = flip ? 3 << (2 * (x & 3)) : 0xc0; + x > 0; + x --, srcptr ++) + switch (bit) + { + case 0xc0 : + if ((temp = *srcptr & 0x30) != 0) + *cptr |= temp << 2; + if ((temp = *srcptr & 0x0c) != 0) + *mptr |= temp << 4; + if ((temp = *srcptr & 0x03) != 0) + *yptr |= temp << 6; + + if (flip) + { + bit = 0x03; + cptr --; + mptr --; + yptr --; + } + else + bit = 0x30; + break; + case 0x30 : + if ((temp = *srcptr & 0x30) != 0) + *cptr |= temp; + if ((temp = *srcptr & 0x0c) != 0) + *mptr |= temp << 2; + if ((temp = *srcptr & 0x03) != 0) + *yptr |= temp << 4; + + if (flip) + bit = 0xc0; + else + bit = 0x0c; + break; + case 0x0c : + if ((temp = *srcptr & 0x30) != 0) + *cptr |= temp >> 2; + if ((temp = *srcptr & 0x0c) != 0) + *mptr |= temp; + if ((temp = *srcptr & 0x03) != 0) + *yptr |= temp << 2; + + if (flip) + bit = 0x30; + else + bit = 0x03; + break; + case 0x03 : + if ((temp = *srcptr & 0x30) != 0) + *cptr |= temp >> 4; + if ((temp = *srcptr & 0x0c) != 0) + *mptr |= temp >> 2; + if ((temp = *srcptr & 0x03) != 0) + *yptr |= temp; + + if (flip) + bit = 0x0c; + else + { + bit = 0xc0; + cptr ++; + mptr ++; + yptr ++; + } + break; + } + break; + case CUPS_CSPACE_GMCK : + case CUPS_CSPACE_GMCS : + case CUPS_CSPACE_RGBA : + case CUPS_CSPACE_CMYK : + case CUPS_CSPACE_YMCK : + case CUPS_CSPACE_KCMY : + case CUPS_CSPACE_KCMYcm : + for (x = cups->width, bit = flip ? 3 << (2 * (x & 3)) : 0xc0; + x > 0; + x --, srcptr ++) + switch (bit) + { + case 0xc0 : + if ((temp = *srcptr & 0xc0) != 0) + *cptr |= temp; + if ((temp = *srcptr & 0x30) != 0) + *mptr |= temp << 2; + if ((temp = *srcptr & 0x0c) != 0) + *yptr |= temp << 4; + if ((temp = *srcptr & 0x03) != 0) + *kptr |= temp << 6; + + if (flip) + { + bit = 0x03; + cptr --; + mptr --; + yptr --; + kptr --; + } + else + bit = 0x30; + break; + case 0x30 : + if ((temp = *srcptr & 0xc0) != 0) + *cptr |= temp >> 2; + if ((temp = *srcptr & 0x30) != 0) + *mptr |= temp; + if ((temp = *srcptr & 0x0c) != 0) + *yptr |= temp << 2; + if ((temp = *srcptr & 0x03) != 0) + *kptr |= temp << 4; + + if (flip) + bit = 0xc0; + else + bit = 0x0c; + break; + case 0x0c : + if ((temp = *srcptr & 0xc0) != 0) + *cptr |= temp >> 4; + if ((temp = *srcptr & 0x30) != 0) + *mptr |= temp >> 2; + if ((temp = *srcptr & 0x0c) != 0) + *yptr |= temp; + if ((temp = *srcptr & 0x03) != 0) + *kptr |= temp << 2; + + if (flip) + bit = 0x30; + else + bit = 0x03; + break; + case 0x03 : + if ((temp = *srcptr & 0xc0) != 0) + *cptr |= temp >> 6; + if ((temp = *srcptr & 0x30) != 0) + *mptr |= temp >> 4; + if ((temp = *srcptr & 0x0c) != 0) + *yptr |= temp >> 2; + if ((temp = *srcptr & 0x03) != 0) + *kptr |= temp; + + if (flip) + bit = 0x0c; + else + { + bit = 0xc0; + cptr ++; + mptr ++; + yptr ++; + kptr ++; + } + break; + } + break; + } + break; + + case 4 : + memset(dst, 0, cups->header.cupsBytesPerLine); + + switch (cups->header.cupsColorSpace) + { + default : + for (x = cups->width, bit = flip && (x & 1) ? 0xf0 : 0x0f; + x > 0; + x --, srcptr += 2) + switch (bit) + { + case 0xf0 : + if ((temp = srcptr[0] & 0x0f) != 0) + *cptr |= temp << 4; + if ((temp = srcptr[1] & 0xf0) != 0) + *mptr |= temp; + if ((temp = srcptr[1] & 0x0f) != 0) + *yptr |= temp << 4; + + bit = 0x0f; + + if (flip) + { + cptr --; + mptr --; + yptr --; + } + break; + case 0x0f : + if ((temp = srcptr[0] & 0x0f) != 0) + *cptr |= temp; + if ((temp = srcptr[1] & 0xf0) != 0) + *mptr |= temp >> 4; + if ((temp = srcptr[1] & 0x0f) != 0) + *yptr |= temp; + + bit = 0xf0; + + if (!flip) + { + cptr ++; + mptr ++; + yptr ++; + } + break; + } + break; + case CUPS_CSPACE_GMCK : + case CUPS_CSPACE_GMCS : + case CUPS_CSPACE_RGBA : + case CUPS_CSPACE_CMYK : + case CUPS_CSPACE_YMCK : + case CUPS_CSPACE_KCMY : + case CUPS_CSPACE_KCMYcm : + for (x = cups->width, bit = flip && (x & 1) ? 0xf0 : 0x0f; + x > 0; + x --, srcptr += 2) + switch (bit) + { + case 0xf0 : + if ((temp = srcptr[0] & 0xf0) != 0) + *cptr |= temp; + if ((temp = srcptr[0] & 0x0f) != 0) + *mptr |= temp << 4; + if ((temp = srcptr[1] & 0xf0) != 0) + *yptr |= temp; + if ((temp = srcptr[1] & 0x0f) != 0) + *kptr |= temp << 4; + + bit = 0x0f; + + if (flip) + { + cptr --; + mptr --; + yptr --; + kptr --; + } + break; + case 0x0f : + if ((temp = srcptr[0] & 0xf0) != 0) + *cptr |= temp >> 4; + if ((temp = srcptr[0] & 0x0f) != 0) + *mptr |= temp; + if ((temp = srcptr[1] & 0xf0) != 0) + *yptr |= temp >> 4; + if ((temp = srcptr[1] & 0x0f) != 0) + *kptr |= temp; + + bit = 0xf0; + + if (!flip) + { + cptr ++; + mptr ++; + yptr ++; + kptr ++; + } + break; + } + break; + } + break; + + case 8 : + switch (cups->header.cupsColorSpace) + { + default : + if (flip) + for (x = cups->width; x > 0; x --) + { + *cptr-- = *srcptr++; + *mptr-- = *srcptr++; + *yptr-- = *srcptr++; + } + else + for (x = cups->width; x > 0; x --) + { + *cptr++ = *srcptr++; + *mptr++ = *srcptr++; + *yptr++ = *srcptr++; + } + break; + case CUPS_CSPACE_GMCK : + case CUPS_CSPACE_GMCS : + case CUPS_CSPACE_RGBA : + case CUPS_CSPACE_CMYK : + case CUPS_CSPACE_YMCK : + case CUPS_CSPACE_KCMY : + case CUPS_CSPACE_KCMYcm : + if (flip) + for (x = cups->width; x > 0; x --) + { + *cptr-- = *srcptr++; + *mptr-- = *srcptr++; + *yptr-- = *srcptr++; + *kptr-- = *srcptr++; + } + else + for (x = cups->width; 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 */ + + + /**** NOTE: Currently planar output doesn't support flipped duplex!!! ****/ + + /* + * 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) + { + default : + memset(dst, 0, cups->header.cupsBytesPerLine); + + switch (cups->header.cupsColorSpace) + { + default : + 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_GMCK : + case CUPS_CSPACE_GMCS : + case CUPS_CSPACE_RGBA : + 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) + { + default : + for (dstptr = dst, x = cups->width, srcbit = 48 >> (z * 2), + dstbit = 0xc0; + x > 0; + x --, srcptr ++) + { + if ((temp = *srcptr & srcbit) != 0) + { + 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_GMCK : + case CUPS_CSPACE_GMCS : + case CUPS_CSPACE_RGBA : + 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) != 0) + { + 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) + { + default : + 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) != 0) + { + 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_GMCK : + case CUPS_CSPACE_GMCS : + case CUPS_CSPACE_RGBA : + 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) != 0) + { + 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/gdevdbit.c b/pstoraster/gdevdbit.c new file mode 100644 index 0000000000..9b6ccecc58 --- /dev/null +++ b/pstoraster/gdevdbit.c @@ -0,0 +1,708 @@ +/* Copyright (C) 1997, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Default device bitmap copying implementation */ +#include "gx.h" +#include "gpcheck.h" +#include "gserrors.h" +#include "gsbittab.h" +#include "gsrect.h" +#include "gsropt.h" +#include "gxdcolor.h" +#include "gxdevice.h" +#include "gxdevmem.h" +#include "gdevmem.h" +#undef mdev +#include "gxcpath.h" + +/* 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) +{ + bool invert; + gx_color_index color; + gx_device_color devc; + + fit_copy(dev, data, dx, raster, id, x, y, w, h); + if (one != gx_no_color_index) { + invert = false; + color = one; + if (zero != gx_no_color_index) { + int code = (*dev_proc(dev, fill_rectangle)) + (dev, x, y, w, h, zero); + + if (code < 0) + return code; + } + } else { + invert = true; + color = zero; + } + color_set_pure(&devc, color); + return gx_dc_default_fill_masked + (&devc, data, dx, raster, id, x, y, w, h, dev, rop3_T, invert); +} + +/* 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_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 = dev->memory; + 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_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_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] = gx_device_white(dev); + scolors[1] = gx_device_black(dev); + if (tile == 0) + colors[0] = colors[1]; /* pure color */ + /* + * We want to write only where the mask is a 1, so enable source + * transparency. We have to include S in the operation, + * otherwise S_transparent will be ignored. + */ + 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 | (rop3_S | lop_S_transparent)); + } + 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 = data + (dx >> 3); + int dx_bit = dx & 7; + int wdx = w + dx_bit; + int iy; + + for (row = data, iy = 0; iy < h; row += raster, iy++) { + int ix; + + for (ix = dx_bit; ix < wdx;) { + int i0; + uint b; + uint len; + int code; + + /* Skip 0-bits. */ + b = row[ix >> 3]; + len = byte_bit_run_length[ix & 7][b ^ 0xff]; + if (len) { + ix += ((len - 1) & 7) + 1; + continue; + } + /* Scan 1-bits. */ + i0 = ix; + for (;;) { + b = row[ix >> 3]; + len = byte_bit_run_length[ix & 7][b]; + if (!len) + break; + ix += ((len - 1) & 7) + 1; + if (ix >= wdx) { + ix = wdx; + break; + } + if (len < 8) + break; + } + /* Now color the run from i0 to ix. */ + code = (*tile_proc) + (dev, tile, i0 - dx_bit + 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; + + fit_fill_xy(dev, x, y, w, h); + +#ifdef DEBUG + if (gs_debug_c('t')) { + int ptx, pty; + const byte *ptp = tiles->data; + + dlprintf3("[t]tile %dx%d raster=%d;", + tiles->size.x, tiles->size.y, tiles->raster); + dlprintf6(" x,y=%d,%d w,h=%d,%d p=%d,%d\n", + x, y, w, h, px, py); + dlputs(""); + for (pty = 0; pty < tiles->size.y; pty++) { + dprintf(" "); + for (ptx = 0; ptx < tiles->raster; ptx++) + dprintf1("%3x", *ptp++); + } + dputc('\n'); + } +#endif + + 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. */ + } { /* + * Note: we can't do the following computations until after + * the fit_fill_xy. + */ + 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; + + 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_debug5('t', " 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 */ +} + +/* ---------------- 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; 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 = alignment_mod(data, align_bitmap_mod); + 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/gdevddrw.c b/pstoraster/gdevddrw.c new file mode 100644 index 0000000000..7985876e74 --- /dev/null +++ b/pstoraster/gdevddrw.c @@ -0,0 +1,643 @@ +/* Copyright (C) 1989, 1995, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Default polygon and image drawing device procedures */ +#include "math_.h" +#include "memory_.h" +#include "gx.h" +#include "gpcheck.h" +#include "gserrors.h" +#include "gxfixed.h" +#include "gxmatrix.h" +#include "gxdcolor.h" +#include "gxdevice.h" +#include "gxiparam.h" +#include "gxistate.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); + } + else + { + cindex = 0; + fill_rect = 0; + } + + 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 that the 'a' line is to the left of + * the 'b' line. Testing ax <= bx is neither sufficient nor + * necessary: in general, we need to compare the slopes. + */ +#define swap(r, s) (t = r, r = s, s = t) + if ((ax ^ bx) < 0) { /* In this case, the test ax <= bx is sufficient. */ + if (ax > bx) + swap(ax, bx), swap(ay, by); + } else { /* + * Compare the slopes. We know that ay >= 0, by >= 0, + * and ax and bx have the same sign; the lines are in the + * correct order iff + * ay/ax >= by/bx, or + * ay*bx >= by*ax + * Eventually we can probably find a better way to test this, + * without using floating point. + */ + if ((double)ay * bx < (double)by * ax) + 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 ay <= by. */ +#define swap(r, s) (t = r, r = s, s = t) + if (ay > by) + swap(ax, bx), swap(ay, by); +#undef swap + /* + * Make a special check for a flat bottom or top, + * which we can handle with a single call on fill_trapezoid. + */ + left.start.x = right.start.x = px; + left.start.y = right.start.y = py; + if (ay == 0) { + /* Flat top */ + if (ax < 0) + left.start.x = px + ax; + else + right.start.x = px + ax; + left.end.x = right.end.x = px + bx; + left.end.y = right.end.y = py + by; + ym = py; + } else if (ay == by) { + /* Flat bottom */ + if (ax < bx) + left.end.x = px + ax, right.end.x = px + bx; + else + left.end.x = px + bx, right.end.x = px + ax; + left.end.y = right.end.y = py + by; + ym = py; + } else { + ym = py + ay; + if (fixed_mult_quo(bx, ay, by) < ax) { + /* The 'b' line is to the left of the 'a' line. */ + left.end.x = px + bx, left.end.y = py + by; + right.end.x = px + ax, right.end.y = py + ay; + code = (*fill_trapezoid) (dev, &left, &right, py, ym, + false, pdevc, lop); + right.start = right.end; + right.end = left.end; + } else { + /* The 'a' line is to the left of the 'b' line. */ + left.end.x = px + ax, left.end.y = py + ay; + right.end.x = px + bx, right.end.y = py + by; + code = (*fill_trapezoid) (dev, &left, &right, py, ym, + false, pdevc, lop); + left.start = left.end; + left.end = right.end; + } + if (code < 0) + return code; + } + 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) + ); + } { + 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; +} + +/* ---------------- Image drawing ---------------- */ + +/* GC structures for image enumerator */ +public_st_gx_image_enum_common(); + +#define eptr ((gx_image_enum_common_t *)vptr) + +private +ENUM_PTRS_BEGIN(image_enum_common_enum_ptrs) return 0; + +case 0: +return ENUM_OBJ(gx_device_enum_ptr(eptr->dev)); +ENUM_PTRS_END + +private RELOC_PTRS_BEGIN(image_enum_common_reloc_ptrs) +{ + eptr->dev = gx_device_reloc_ptr(eptr->dev, gcst); +} +RELOC_PTRS_END + +#undef eptr + +/* + * gx_default_begin_image is only invoked for ImageType 1 images. However, + * the argument types are different, and if the device provides a + * begin_typed_image procedure, we should use it. See gxdevice.h. + */ +private int +gx_no_begin_image(gx_device * dev, + const gs_imager_state * pis, const gs_image_t * pim, + gs_image_format_t format, const gs_int_rect * prect, + const gx_drawing_color * pdcolor, const gx_clip_path * pcpath, + gs_memory_t * memory, gx_image_enum_common_t ** pinfo) +{ + return -1; +} +int +gx_default_begin_image(gx_device * dev, + const gs_imager_state * pis, const gs_image_t * pim, + gs_image_format_t format, const gs_int_rect * prect, + const gx_drawing_color * pdcolor, const gx_clip_path * pcpath, + gs_memory_t * memory, gx_image_enum_common_t ** pinfo) +{ + /* + * Hand off to begin_typed_image, being careful to avoid a + * possible recursion loop. + */ + dev_proc_begin_image((*save_begin_image)) = dev_proc(dev, begin_image); + gs_image_t image; + const gs_image_t *ptim; + int code; + + set_dev_proc(dev, begin_image, gx_no_begin_image); + if (pim->format == format) + ptim = pim; + else { + image = *pim; + image.format = format; + ptim = ℑ + } + code = (*dev_proc(dev, begin_typed_image)) + (dev, pis, NULL, (const gs_image_common_t *)ptim, prect, pdcolor, + pcpath, memory, pinfo); + set_dev_proc(dev, begin_image, save_begin_image); + return code; +} + +int +gx_default_begin_typed_image(gx_device * dev, + const gs_imager_state * pis, const gs_matrix * pmat, + const gs_image_common_t * pic, const gs_int_rect * prect, + const gx_drawing_color * pdcolor, const gx_clip_path * pcpath, + gs_memory_t * memory, gx_image_enum_common_t ** pinfo) +{ /* + * If this is an ImageType 1 image using the imager's CTM, + * defer to begin_image. + */ + if (pic->type->begin_typed_image == gx_begin_image1) { + const gs_image_t *pim = (const gs_image_t *)pic; + + if (pmat == 0 || + (pis != 0 && !memcmp(pmat, &ctm_only(pis), sizeof(*pmat))) + ) { + int code = (*dev_proc(dev, begin_image)) + (dev, pis, pim, pim->format, prect, pdcolor, + pcpath, memory, pinfo); + + if (code >= 0) + return code; + } + } + return (*pic->type->begin_typed_image) + (dev, pis, pmat, pic, prect, pdcolor, pcpath, memory, pinfo); +} + +int +gx_image_data(gx_image_enum_common_t * info, const byte ** plane_data, + int data_x, uint raster, int height) +{ + int num_planes = info->num_planes; + gx_image_plane_t planes[gs_image_max_components]; + int i; + +#ifdef DEBUG + if (num_planes > gs_image_max_components) { + lprintf2("num_planes=%d > gs_image_max_components=%d!\n", + num_planes, gs_image_max_components); + return_error(gs_error_Fatal); + } +#endif + for (i = 0; i < num_planes; ++i) { + planes[i].data = plane_data[i]; + planes[i].data_x = data_x; + planes[i].raster = raster; + } + return gx_image_plane_data(info, planes, height); +} + +int +gx_image_plane_data(gx_image_enum_common_t * info, + const gx_image_plane_t * planes, int height) +{ + return info->procs->plane_data(info->dev, info, planes, height); +} + +int +gx_image_end(gx_image_enum_common_t * info, bool draw_last) +{ + return info->procs->end_image(info->dev, info, draw_last); +} + +/* Backward compatibility for obsolete driver procedures. */ + +int +gx_default_image_data(gx_device *dev, gx_image_enum_common_t * info, + const byte ** plane_data, + int data_x, uint raster, int height) +{ + return gx_image_data(info, plane_data, data_x, raster, height); +} + +int +gx_default_end_image(gx_device *dev, gx_image_enum_common_t * info, + bool draw_last) +{ + return gx_image_end(info, draw_last); +} diff --git a/pstoraster/gdevdflt.c b/pstoraster/gdevdflt.c new file mode 100644 index 0000000000..7633b7b43b --- /dev/null +++ b/pstoraster/gdevdflt.c @@ -0,0 +1,270 @@ +/* Copyright (C) 1995, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Default device implementation */ +#include "gx.h" +#include "gserrors.h" +#include "gsropt.h" +#include "gxcomp.h" +#include "gxdevice.h" +#include "gxdevmem.h" +#undef mdev + +/* ---------------- Default device procedures ---------------- */ + +/* 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, obsolete_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); + 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); + /* + * We always replace image_data and end_image with the new + * procedures, and, if in a DEBUG configuration, print a warning + * if the definitions aren't the default ones. + */ +#ifdef DEBUG +# define CHECK_NON_DEFAULT(proc, default, procname)\ + BEGIN\ + if ( dev_proc(dev, proc) != NULL && dev_proc(dev, proc) != default )\ + dprintf2("**** Warning: device %s implements obsolete procedure %s\n",\ + dev->dname, procname);\ + END +#else +# define CHECK_NON_DEFAULT(proc, default, procname)\ + DO_NOTHING +#endif + CHECK_NON_DEFAULT(image_data, gx_default_image_data, "image_data"); + set_dev_proc(dev, image_data, gx_default_image_data); + CHECK_NON_DEFAULT(end_image, gx_default_end_image, "end_image"); + set_dev_proc(dev, end_image, gx_default_end_image); +#undef CHECK_NON_DEFAULT + fill_dev_proc(dev, strip_tile_rectangle, gx_default_strip_tile_rectangle); + fill_dev_proc(dev, strip_copy_rop, gx_default_strip_copy_rop); + fill_dev_proc(dev, get_clipping_box, gx_default_get_clipping_box); + fill_dev_proc(dev, begin_typed_image, gx_default_begin_typed_image); + fill_dev_proc(dev, get_bits_rectangle, gx_default_get_bits_rectangle); + fill_dev_proc(dev, map_color_rgb_alpha, gx_default_map_color_rgb_alpha); + fill_dev_proc(dev, create_compositor, gx_default_create_compositor); + fill_dev_proc(dev, get_hardware_params, gx_default_get_hardware_params); + fill_dev_proc(dev, text_begin, gx_default_text_begin); +} + +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; +} + +const 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_default_get_band(gx_device * dev, int y, int *band_start) +{ + return 0; +} + +void +gx_default_get_clipping_box(gx_device * dev, gs_fixed_rect * pbox) +{ + pbox->p.x = 0; + pbox->p.y = 0; + pbox->q.x = int2fixed(dev->width); + pbox->q.y = int2fixed(dev->height); +} +void +gx_get_largest_clipping_box(gx_device * dev, gs_fixed_rect * pbox) +{ + pbox->p.x = min_fixed; + pbox->p.y = min_fixed; + pbox->q.x = max_fixed; + pbox->q.y = max_fixed; +} + +int +gx_no_create_compositor(gx_device * dev, gx_device ** pcdev, + const gs_composite_t * pcte, const gs_imager_state * pis, gs_memory_t * memory) +{ + return_error(gs_error_unknownerror); /* not implemented */ +} +int +gx_default_create_compositor(gx_device * dev, gx_device ** pcdev, + const gs_composite_t * pcte, const gs_imager_state * pis, gs_memory_t * memory) +{ + return (*pcte->type->procs.create_default_compositor) + (pcte, pcdev, dev, pis, memory); +} +int +gx_non_imaging_create_compositor(gx_device * dev, gx_device ** pcdev, + const gs_composite_t * pcte, const gs_imager_state * pis, gs_memory_t * memory) +{ + *pcdev = dev; + return 0; +} + +/* 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) + assign_dev_procs(mdev, mdproto); + 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); +} diff --git a/pstoraster/gdevdgbr.c b/pstoraster/gdevdgbr.c new file mode 100644 index 0000000000..c156696950 --- /dev/null +++ b/pstoraster/gdevdgbr.c @@ -0,0 +1,586 @@ +/* Copyright (C) 1997, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Default implementation of device get_bits[_rectangle] */ +#include "gx.h" +#include "gserrors.h" +#include "gxdevice.h" +#include "gxdevmem.h" +#include "gxgetbit.h" +#include "gxlum.h" +#include "gdevmem.h" + +int +gx_no_get_bits(gx_device * dev, int y, byte * data, byte ** actual_data) +{ + return_error(gs_error_unknownerror); +} +int +gx_default_get_bits(gx_device * dev, int y, byte * data, byte ** actual_data) +{ /* + * Hand off to get_bits_rectangle, being careful to avoid a + * possible recursion loop. + */ + dev_proc_get_bits((*save_get_bits)) = dev_proc(dev, get_bits); + gs_int_rect rect; + gs_get_bits_params_t params; + int code; + + rect.p.x = 0, rect.p.y = y; + rect.q.x = dev->width, rect.q.y = y + 1; + params.options = + (actual_data ? GB_RETURN_POINTER : 0) | GB_RETURN_COPY | + (GB_ALIGN_STANDARD | GB_OFFSET_0 | GB_RASTER_STANDARD | + /* No depth specified, we always use native colors. */ + GB_PACKING_CHUNKY | GB_COLORS_NATIVE | GB_ALPHA_NONE); + params.x_offset = 0; + params.raster = bitmap_raster(dev->width * dev->color_info.depth); + params.data[0] = data; + set_dev_proc(dev, get_bits, gx_no_get_bits); + code = (*dev_proc(dev, get_bits_rectangle)) + (dev, &rect, ¶ms, NULL); + if (actual_data) + *actual_data = params.data[0]; + set_dev_proc(dev, get_bits, save_get_bits); + return code; +} + +/* + * Determine whether we can satisfy a request by simply using the stored + * representation. + */ +private bool +requested_includes_stored(gs_get_bits_options_t requested, + gs_get_bits_options_t stored) +{ + gs_get_bits_options_t both = requested & stored; + + if (!(both & GB_PACKING_ALL)) + return false; + if (both & GB_COLORS_NATIVE) + return true; + if (both & GB_COLORS_STANDARD_ALL) { + if ((both & GB_ALPHA_ALL) && (both & GB_DEPTH_ALL)) + return true; + } + return false; +} + +/* + * Try to implement get_bits_rectangle by returning a pointer. + * Note that dev is used only for computing the default raster + * and for color_info.depth. + * This routine does not check x or h for validity. + */ +int +gx_get_bits_return_pointer(gx_device * dev, int x, int h, + gs_get_bits_params_t * params, gs_get_bits_options_t stored, + byte * stored_base) +{ + gs_get_bits_options_t options = params->options; + + if (!(options & GB_RETURN_POINTER) || + !requested_includes_stored(options, stored) + ) + return -1; + /* + * See whether we can return the bits in place. Note that even if + * offset_any isn't set, x_offset and x don't have to be equal: their + * bit offsets only have to match modulo align_bitmap_mod * 8 (to + * preserve alignment) if align_any isn't set, or mod 8 (since + * byte alignment is always required) if align_any is set. + */ + { + int depth = dev->color_info.depth; + uint dev_raster = gx_device_raster(dev, 1); + uint raster = + (options & (GB_RASTER_STANDARD | GB_RASTER_ANY) ? dev_raster : + params->raster); + + if (h <= 1 || raster == dev_raster) { + int x_offset = + (options & GB_OFFSET_ANY ? x : + options & GB_OFFSET_0 ? 0 : params->x_offset); + + if (x_offset == x) { + params->data[0] = stored_base; + params->x_offset = x; + } else { + uint align_mod = + (options & GB_ALIGN_ANY ? 8 : align_bitmap_mod * 8); + int bit_offset = x - x_offset; + int bytes; + + if (bit_offset & (align_mod - 1)) + return -1; /* can't align */ + if (depth & (depth - 1)) { + /* step = lcm(depth, align_mod) */ + int step = depth / igcd(depth, align_mod) * align_mod; + + bytes = bit_offset / step * step; + } else { + /* Use a faster algorithm if depth is a power of 2. */ + bytes = bit_offset & (-depth & -align_mod); + } + params->data[0] = stored_base + arith_rshift(bytes, 3); + params->x_offset = (bit_offset - bytes) / depth; + } + params->options = + GB_ALIGN_STANDARD | GB_RETURN_POINTER | GB_RASTER_STANDARD | + GB_PACKING_CHUNKY | stored | + (params->x_offset == 0 ? GB_OFFSET_0 : GB_OFFSET_SPECIFIED); + return 0; + } + } + return -1; +} + +/* + * Convert pixels between representations, primarily for get_bits_rectangle. + * stored indicates how the data are actually stored, and includes: + * - one option from the GB_PACKING group; + * - if h > 1, one option from the GB_RASTER group; + * - optionally (and normally), GB_COLORS_NATIVE; + * - optionally, one option each from the GB_COLORS_STANDARD, GB_DEPTH, + * and GB_ALPHA groups. + * Note that dev is used only for color mapping. This routine assumes that + * the stored data are aligned. + * + * Note: this routine does not check x, w, h for validity. + */ +int +gx_get_bits_copy(gx_device * dev, int x, int w, int h, + gs_get_bits_params_t * params, gs_get_bits_options_t stored, + const byte * src_base, uint dev_raster) +{ + gs_get_bits_options_t options = params->options; + byte *data = params->data[0]; + int depth = dev->color_info.depth; + int bit_x = x * depth; + const byte *src = src_base; + + /* + * If the stored representation matches a requested representation, + * we can copy the data without any transformations. + */ + bool direct_copy = requested_includes_stored(options, stored); + + /* + * The request must include GB_PACKING_CHUNKY, GB_RETURN_COPY, + * and an offset and raster specification. + */ + if ((~options & (GB_PACKING_CHUNKY | GB_RETURN_COPY)) || + !(options & (GB_OFFSET_0 | GB_OFFSET_SPECIFIED)) || + !(options & (GB_RASTER_STANDARD | GB_RASTER_SPECIFIED)) + ) + return_error(gs_error_rangecheck); + { + int x_offset = (options & GB_OFFSET_0 ? 0 : params->x_offset); + int end_bit = (x_offset + w) * depth; + uint std_raster = + (options & GB_ALIGN_STANDARD ? bitmap_raster(end_bit) : + (end_bit + 7) >> 3); + uint raster = + (options & GB_RASTER_STANDARD ? std_raster : params->raster); + int dest_bit_x = x_offset * depth; + int skew = bit_x - dest_bit_x; + + /* + * If the bit positions line up, use bytes_copy_rectangle. + * Since bytes_copy_rectangle doesn't require alignment, + * the bit positions only have to match within a byte, + * not within align_bitmap_mod bytes. + */ + if (!(skew & 7) && direct_copy) { + int bit_w = w * depth; + + bytes_copy_rectangle(data + (dest_bit_x >> 3), raster, + src + (bit_x >> 3), dev_raster, + ((bit_x + bit_w + 7) >> 3) - (bit_x >> 3), h); + } else if (direct_copy) { + /* + * Use the logic already in mem_mono_copy_mono to copy the + * bits to the destination. We do this one line at a time, + * to avoid having to allocate a line pointer table. + */ + gx_device_memory tdev; + byte *line_ptr = data; + + tdev.line_ptrs = &tdev.base; + for (; h > 0; line_ptr += raster, src += dev_raster, --h) { + /* Make sure the destination is aligned. */ + int align = alignment_mod(line_ptr, align_bitmap_mod); + + tdev.base = line_ptr - align; + (*dev_proc(&mem_mono_device, copy_mono)) + ((gx_device *) & tdev, src, bit_x, dev_raster, gx_no_bitmap_id, + dest_bit_x + (align << 3), 0, w, 1, + (gx_color_index) 0, (gx_color_index) 1); + } + } else if (options & ~stored & GB_COLORS_NATIVE) { + /* + * Convert standard colors to native. Note that the source + * may have depths other than 8 bits per component. + */ + int dest_bit_offset = x_offset * depth; + byte *dest_line = data + (dest_bit_offset >> 3); + int ncolors = + (stored & GB_COLORS_RGB ? 3 : stored & GB_COLORS_CMYK ? 4 : + stored & GB_COLORS_GRAY ? 1 : -1); + int ncomp = ncolors + + ((stored & (GB_ALPHA_FIRST | GB_ALPHA_LAST)) != 0); + int src_depth = GB_OPTIONS_DEPTH(stored); + int src_bit_offset = x * src_depth * ncomp; + const byte *src_line = src_base + (src_bit_offset >> 3); + gx_color_value src_max = (1 << src_depth) - 1; + +#define v2cv(value) ((ulong)(value) * gx_max_color_value / src_max) + gx_color_value alpha_default = src_max; + + options &= ~GB_COLORS_ALL | GB_COLORS_NATIVE; + for (; h > 0; dest_line += raster, src_line += dev_raster, --h) { + int i; + + sample_load_declare_setup(src, sbit, src_line, + src_bit_offset & 7, src_depth); + sample_store_declare_setup(dest, dbit, dbyte, dest_line, + dest_bit_offset & 7, depth); + + for (i = 0; i < w; ++i) { + int j; + gx_color_value v[4], va = alpha_default; + gx_color_index pixel; + + /* Fetch the source data. */ + if (stored & GB_ALPHA_FIRST) { + sample_load_next16(va, src, sbit, src_depth); + va = v2cv(va); + } + for (j = 0; j < ncolors; ++j) { + gx_color_value vj; + + sample_load_next16(vj, src, sbit, src_depth); + v[j] = v2cv(vj); + } + if (stored & GB_ALPHA_LAST) { + sample_load_next16(va, src, sbit, src_depth); + va = v2cv(va); + } + /* Convert and store the pixel value. */ + switch (ncolors) { + case 1: + v[2] = v[1] = v[0]; + case 3: + pixel = (*dev_proc(dev, map_rgb_alpha_color)) + (dev, v[0], v[1], v[2], va); + break; + case 4: + /****** NO ALPHA FOR CMYK ******/ + pixel = (*dev_proc(dev, map_cmyk_color)) + (dev, v[0], v[1], v[2], v[3]); + break; + default: + return_error(gs_error_rangecheck); + } + sample_store_next32(pixel, dest, dbit, depth, dbyte); + } + sample_store_flush(dest, dbit, depth, dbyte); + } + } else if (!(options & GB_DEPTH_8)) { + /* + * We don't support general depths yet, or conversion between + * different formats. Punt. + */ + return_error(gs_error_rangecheck); + } else { + /* + * We have to do some conversion to each pixel. This is the + * slowest, most general case. + */ + int src_bit_offset = x * depth; + const byte *src_line = src_base + (src_bit_offset >> 3); + int ncomp = + (options & (GB_ALPHA_FIRST | GB_ALPHA_LAST) ? 4 : 3); + byte *dest_line = data + x_offset * ncomp; + + /* Pick the representation that's most likely to be useful. */ + if (options & GB_COLORS_RGB) + options &= ~GB_COLORS_STANDARD_ALL | GB_COLORS_RGB; + else if (options & GB_COLORS_CMYK) + options &= ~GB_COLORS_STANDARD_ALL | GB_COLORS_CMYK; + else if (options & GB_COLORS_GRAY) + options &= ~GB_COLORS_STANDARD_ALL | GB_COLORS_GRAY; + else + return_error(gs_error_rangecheck); + for (; h > 0; dest_line += raster, src_line += dev_raster, --h) { + int i; + + sample_load_declare_setup(src, bit, src_line, src_bit_offset & 7, + depth); + byte *dest = dest_line; + + for (i = 0; i < w; ++i) { + gx_color_index pixel = 0; + gx_color_value rgba[4]; + + sample_load_next32(pixel, src, bit, depth); + (*dev_proc(dev, map_color_rgb_alpha)) (dev, pixel, rgba); + if (options & GB_ALPHA_FIRST) + *dest++ = gx_color_value_to_byte(rgba[3]); + /* Convert to the requested color space. */ + if (options & GB_COLORS_RGB) { + dest[0] = gx_color_value_to_byte(rgba[0]); + dest[1] = gx_color_value_to_byte(rgba[1]); + dest[2] = gx_color_value_to_byte(rgba[2]); + dest += 3; + } else if (options & GB_COLORS_CMYK) { + /* Use the standard RGB to CMYK algorithm, */ + /* with maximum black generation and undercolor removal. */ + gx_color_value white = max(rgba[0], max(rgba[1], rgba[2])); + + dest[0] = gx_color_value_to_byte(white - rgba[0]); + dest[1] = gx_color_value_to_byte(white - rgba[1]); + dest[2] = gx_color_value_to_byte(white - rgba[2]); + dest[3] = gx_color_value_to_byte(gx_max_color_value - white); + dest += 4; + } else { /* GB_COLORS_GRAY */ + /* Use the standard RGB to Gray algorithm. */ + *dest++ = gx_color_value_to_byte( + ((rgba[0] * (ulong) lum_red_weight) + + (rgba[1] * (ulong) lum_green_weight) + + (rgba[2] * (ulong) lum_blue_weight) + + (lum_all_weights / 2)) + / lum_all_weights); + } + if (options & GB_ALPHA_LAST) + *dest++ = gx_color_value_to_byte(rgba[3]); + } + } + } + params->options = + (options & (GB_COLORS_ALL | GB_ALPHA_ALL)) | GB_PACKING_CHUNKY | + (options & GB_COLORS_NATIVE ? 0 : options & GB_DEPTH_ALL) | + (options & GB_ALIGN_STANDARD ? GB_ALIGN_STANDARD : GB_ALIGN_ANY) | + GB_RETURN_COPY | + (x_offset == 0 ? GB_OFFSET_0 : GB_OFFSET_SPECIFIED) | + (raster == std_raster ? GB_RASTER_STANDARD : GB_RASTER_SPECIFIED); + } + return 0; +} + +int +gx_no_get_bits_rectangle(gx_device * dev, const gs_int_rect * prect, + gs_get_bits_params_t * params, gs_int_rect ** unread) +{ + return_error(gs_error_unknownerror); +} +int +gx_default_get_bits_rectangle(gx_device * dev, const gs_int_rect * prect, + gs_get_bits_params_t * params, gs_int_rect ** unread) +{ + dev_proc_get_bits_rectangle((*save_get_bits_rectangle)) = + dev_proc(dev, get_bits_rectangle); + int depth = dev->color_info.depth; + uint min_raster = (dev->width * depth + 7) >> 3; + gs_get_bits_options_t options = params->options; + int code; + + /* Avoid a recursion loop. */ + set_dev_proc(dev, get_bits_rectangle, gx_no_get_bits_rectangle); + /* + * If the parameters are right, try to call get_bits directly. Note + * that this may fail if a device only implements get_bits_rectangle + * (not get_bits) for a limited set of options. Note also that this + * must handle the case of the recursive call from within + * get_bits_rectangle (see below): because of this, and only because + * of this, it must handle partial scan lines. + */ + if (prect->q.y == prect->p.y + 1 && + !(~options & + (GB_RETURN_COPY | GB_PACKING_CHUNKY | GB_COLORS_NATIVE)) && + (options & (GB_ALIGN_STANDARD | GB_ALIGN_ANY)) && + ((options & (GB_OFFSET_0 | GB_OFFSET_ANY)) || + ((options & GB_OFFSET_SPECIFIED) && params->x_offset == 0)) && + ((options & (GB_RASTER_STANDARD | GB_RASTER_ANY)) || + ((options & GB_RASTER_SPECIFIED) && + params->raster >= min_raster)) && + unread == NULL + ) { + byte *data = params->data[0]; + byte *row = data; + + if (!(prect->p.x == 0 && prect->q.x == dev->width)) { + /* Allocate an intermediate row buffer. */ + row = gs_alloc_bytes(dev->memory, min_raster, + "gx_default_get_bits_rectangle"); + + if (row == 0) { + code = gs_note_error(gs_error_VMerror); + goto ret; + } + } + code = (*dev_proc(dev, get_bits)) + (dev, prect->p.y, row, ¶ms->data[0]); + if (code >= 0) { + if (row != data) { + if (prect->p.x == 0 && params->data[0] != row) { + /* + * get_bits returned an appropriate pointer: we can + * avoid doing any copying. + */ + DO_NOTHING; + } else { + /* Copy the partial row into the supplied buffer. */ + int width_bits = (prect->q.x - prect->p.x) * depth; + gx_device_memory tdev; + + tdev.width = width_bits; + tdev.height = 1; + tdev.line_ptrs = &tdev.base; + tdev.base = data; + code = (*dev_proc(&mem_mono_device, copy_mono)) + ((gx_device *) & tdev, params->data[0], prect->p.x * depth, + min_raster, gx_no_bitmap_id, 0, 0, width_bits, 1, + (gx_color_index) 0, (gx_color_index) 1); + params->data[0] = data; + } + gs_free_object(dev->memory, row, + "gx_default_get_bits_rectangle"); + } + params->options = + GB_ALIGN_STANDARD | GB_OFFSET_0 | GB_PACKING_CHUNKY | + GB_ALPHA_NONE | GB_COLORS_NATIVE | GB_RASTER_STANDARD | + (params->data[0] == data ? GB_RETURN_COPY : GB_RETURN_POINTER); + goto ret; + } + } { + /* Do the transfer row-by-row using a buffer. */ + int x = prect->p.x, w = prect->q.x - x; + int bits_per_pixel = depth; + byte *row; + + if (options & GB_COLORS_STANDARD_ALL) { + /* + * Make sure the row buffer can hold the standard color + * representation, in case the device decides to use it. + */ + int bpc = GB_OPTIONS_MAX_DEPTH(options); + int nc = + (options & GB_COLORS_CMYK ? 4 : + options & GB_COLORS_RGB ? 3 : 1) + + (options & (GB_ALPHA_ALL - GB_ALPHA_NONE) ? 1 : 0); + int bpp = bpc * nc; + + if (bpp > bits_per_pixel) + bits_per_pixel = bpp; + } + row = gs_alloc_bytes(dev->memory, (bits_per_pixel * w + 7) >> 3, + "gx_default_get_bits_rectangle"); + if (row == 0) { + code = gs_note_error(gs_error_VMerror); + } else { + uint dev_raster = gx_device_raster(dev, true); + uint raster = + (options & GB_RASTER_SPECIFIED ? params->raster : + options & GB_ALIGN_STANDARD ? bitmap_raster(depth * w) : + (depth * w + 7) >> 3); + gs_int_rect rect; + gs_get_bits_params_t copy_params; + gs_get_bits_options_t copy_options = + GB_ALIGN_ANY | (GB_RETURN_COPY | GB_RETURN_POINTER) | + (GB_OFFSET_0 | GB_OFFSET_ANY) | + (GB_RASTER_STANDARD | GB_RASTER_ANY) | GB_PACKING_CHUNKY | + GB_COLORS_NATIVE | (options & (GB_DEPTH_ALL | GB_COLORS_ALL)) | + GB_ALPHA_ALL; + byte *dest = params->data[0]; + int y; + + rect.p.x = x, rect.q.x = x + w; + code = 0; + for (y = prect->p.y; y < prect->q.y; ++y) { + rect.p.y = y, rect.q.y = y + 1; + copy_params.options = copy_options; + copy_params.data[0] = row; + code = (*save_get_bits_rectangle) + (dev, &rect, ©_params, NULL); + if (code < 0) + break; + if (copy_params.options & GB_OFFSET_0) + copy_params.x_offset = 0; + params->data[0] = dest + (y - prect->p.y) * raster; + code = gx_get_bits_copy(dev, copy_params.x_offset, w, 1, + params, copy_params.options, + copy_params.data[0], dev_raster); + if (code < 0) + break; + } + gs_free_object(dev->memory, row, "gx_default_get_bits_rectangle"); + params->data[0] = dest; + } + } + ret:set_dev_proc(dev, get_bits_rectangle, save_get_bits_rectangle); + return (code < 0 ? code : 0); +} + +/* ------ Debugging printout ------ */ + +#ifdef DEBUG + +void +debug_print_gb_options(gx_bitmap_format_t options) +{ + static const char *const option_names[] = + { + GX_BITMAP_FORMAT_NAMES + }; + const char *prev = " "; + int i; + + dlprintf1("0x%lx", (ulong) options); + for (i = 0; i < sizeof(options) * 8; ++i) + if ((options >> i) & 1) { + dprintf2("%c%s", + (!memcmp(prev, option_names[i], 3) ? '|' : ','), + option_names[i]); + prev = option_names[i]; + } + dputc('\n'); +} + +void +debug_print_gb_params(gs_get_bits_params_t * params) +{ + gs_get_bits_options_t options = params->options; + + debug_print_gb_options(options); + dprintf1("data[0]=0x%lx", (ulong) params->data[0]); + if (options & GB_OFFSET_SPECIFIED) + dprintf1(" x_offset=%d", params->x_offset); + if (options & GB_RASTER_SPECIFIED) + dprintf1(" raster=%u", params->raster); + dputc('\n'); +} + +#endif /* DEBUG */ diff --git a/pstoraster/gdevhit.c b/pstoraster/gdevhit.c new file mode 100644 index 0000000000..9e16a2a0d7 --- /dev/null +++ b/pstoraster/gdevhit.c @@ -0,0 +1,98 @@ +/* Copyright (C) 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Hit detection device */ +#include "std.h" +#include "gserror.h" +#include "gserrors.h" +#include "gstypes.h" +#include "gsmemory.h" +#include "gxdevice.h" + +/* Define the value returned for a detected hit. */ +const int gs_hit_detected = gs_error_hit_detected; + +/* + * Define a minimal device for insideness testing. + * It returns e_hit whenever it is asked to actually paint any pixels. + */ +private dev_proc_fill_rectangle(hit_fill_rectangle); +const gx_device gs_hit_device = +{std_device_std_body(gx_device, 0, "hit detector", + 0, 0, 1, 1), + {NULL, /* open_device */ + NULL, /* get_initial_matrix */ + NULL, /* sync_output */ + NULL, /* output_page */ + NULL, /* close_device */ + gx_default_map_rgb_color, + gx_default_map_color_rgb, + hit_fill_rectangle, + NULL, /* tile_rectangle */ + NULL, /* copy_mono */ + NULL, /* copy_color */ + gx_default_draw_line, + NULL, /* get_bits */ + NULL, /* get_params */ + NULL, /* put_params */ + gx_default_map_cmyk_color, + NULL, /* get_xfont_procs */ + NULL, /* get_xfont_device */ + gx_default_map_rgb_alpha_color, + gx_default_get_page_device, + gx_default_get_alpha_bits, + NULL, /* copy_alpha */ + gx_default_get_band, + NULL, /* copy_rop */ + gx_default_fill_path, + NULL, /* stroke_path */ + NULL, /* 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, + gx_default_strip_tile_rectangle, + gx_default_strip_copy_rop, + gx_get_largest_clipping_box, + gx_default_begin_typed_image, + NULL, /* get_bits_rectangle */ + gx_default_map_color_rgb_alpha, + gx_non_imaging_create_compositor, + NULL /* get_hardware_params */ + } +}; + +/* Test for a hit when filling a rectangle. */ +private int +hit_fill_rectangle(gx_device * dev, int x, int y, int w, int h, + gx_color_index color) +{ + if (w > 0 && h > 0) + return_error(gs_error_hit_detected); + return 0; +} diff --git a/pstoraster/gdevht.h b/pstoraster/gdevht.h new file mode 100644 index 0000000000..a2f665f12a --- /dev/null +++ b/pstoraster/gdevht.h @@ -0,0 +1,51 @@ +/* Copyright (C) 1995, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Requires gxdevice.h */ + +#ifndef gdevht_INCLUDED +# define gdevht_INCLUDED + +#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). + * We represent colors by packing the two colors being halftoned and the + * halftone level into a gx_color_index. + */ +typedef struct gx_device_ht_s { + gx_device_forward_common; + /* Following + target 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. */ + int color_shift; /* # of bits of color */ + int level_shift; /* = color_shift * 2 */ + gx_color_index color_mask; /* (1 << color_shift) - 1 */ + gs_int_point phase; /* halftone tile offset */ +} gx_device_ht; + +#endif /* gdevht_INCLUDED */ diff --git a/pstoraster/gdevm1.c b/pstoraster/gdevm1.c new file mode 100644 index 0000000000..d474967110 --- /dev/null +++ b/pstoraster/gdevm1.c @@ -0,0 +1,759 @@ +/* Copyright (C) 1989, 1995, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* 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 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, + gx_default_map_cmyk_color, gx_no_copy_alpha, + mem_mono_strip_tile_rectangle, mem_mono_strip_copy_rop, + mem_get_bits_rectangle); + +/* 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) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + + 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]) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + + 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) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + +#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. + * + * Since source and destination are both always big-endian, + * fetching an aligned chunk never requires byte swapping. + */ +#define CFETCH_ALIGNED(cptr)\ + (*(const chunk *)(cptr)) + +/* + * 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 + +typedef enum { + COPY_OR = 0, COPY_STORE, COPY_AND, COPY_FUNNY +} copy_function; +typedef struct { + uint invert; + copy_function op; +} copy_mode; + +/* + * Map from to copy_mode. + * Logically, this is a 2-D array. + * The indexing is (transparent, 0, 1, unused). */ +private const copy_mode copy_modes[16] = +{ + {~0, COPY_FUNNY}, /* NN */ + {~0, COPY_AND}, /* N0 */ + {0, COPY_OR}, /* N1 */ + {0, 0}, /* unused */ + {0, COPY_AND}, /* 0N */ + {0, COPY_FUNNY}, /* 00 */ + {0, COPY_STORE}, /* 01 */ + {0, 0}, /* unused */ + {~0, COPY_OR}, /* 1N */ + {~0, COPY_STORE}, /* 10 */ + {0, COPY_FUNNY}, /* 11 */ + {0, 0}, /* unused */ + {0, 0}, /* unused */ + {0, 0}, /* unused */ + {0, 0}, /* unused */ + {0, 0}, /* unused */ +}; + +/* Handle the funny cases that aren't supposed to happen. */ +#define FUNNY_CASE()\ + (invert ? gs_note_error(-1) :\ + mem_mono_fill_rectangle(dev, x, y, w, h, color0)) + +private int +mem_mono_copy_mono(gx_device * dev, + const byte * source_data, int source_x, int source_raster, gx_bitmap_id id, + int x, int y, int w, int h, gx_color_index color0, gx_color_index color1) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + +#ifdef USE_COPY_ROP + return mem_mono_copy_rop(dev, source_data, source_x, source_raster, + id, NULL, NULL, NULL, + x, y, w, h, 0, 0, + ((color0 == gx_no_color_index ? rop3_D : + color0 == 0 ? rop3_0 : rop3_1) & ~rop3_S) | + ((color1 == gx_no_color_index ? rop3_D : + color1 == 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; + + DECLARE_SCAN_PTR_VARS(dbptr, byte *, dest_raster); +#define optr ((chunk *)dbptr) + register int skew; + register uint invert; + + fit_copy(dev, source_data, source_x, source_raster, id, x, y, w, h); +#if gx_no_color_index_value != -1 /* hokey! */ + if (color0 == gx_no_color_index) + color0 = -1; + if (color1 == gx_no_color_index) + color1 = -1; +#endif + mode = copy_modes[((int)color0 << 2) + (int)color1 + 5]; + invert = mode.invert; /* load register */ + SETUP_RECT_VARS(dbptr, byte *, dest_raster); + bptr = source_data + ((source_x & ~chunk_align_bit_mask) >> 3); + dbit = x & chunk_align_bit_mask; + skew = dbit - (source_x & 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)\ + 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);\ + if ( --h == 0 ) break;\ + END_Y_LOOP(source_raster, dest_raster);\ + } + +#define WRITE1_LOOP(src)\ + switch ( mode.op ) {\ + 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: return FUNNY_CASE();\ + } + + 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);\ + if ( --h == 0 ) break;\ + END_Y_LOOP(source_raster, dest_raster);\ + } +#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);\ + if ( --h == 0 ) break;\ + END_Y_LOOP(source_raster, dest_raster);\ + } +#endif + + switch (mode.op) { + 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: + return FUNNY_CASE(); + } +#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 = source_raster - words; + uint dskip = dest_raster - 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); }\ + if ( --h == 0 ) break;\ + END_Y_LOOP(sskip, dskip);\ + } + + switch (mode.op) { + 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: + return FUNNY_CASE(); + } +#undef WRITE_ALIGNED + } else { /* not aligned */ + int cskew = -skew & chunk_bit_mask; + bool case_right = + (skew >= 0 ? true : + ((bptr += chunk_bytes), false)); + + skew &= chunk_bit_mask; + +#define WRITE_UNALIGNED(wr_op, wr_op_masked)\ + /* Prefetch partial word. */\ + bits =\ + (case_right ? CFETCH_RIGHT(bptr, skew, cskew) :\ + CFETCH2(bptr - chunk_bytes, cskew, skew));\ + 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 (mode.op) { + case COPY_OR: + for (;;) { + int count = wleft; + + WRITE_UNALIGNED(WRITE_OR, WRITE_OR_MASKED); + if (--h == 0) + break; + END_Y_LOOP(sskip, dskip); + } + break; + case COPY_STORE: + for (;;) { + int count = wleft; + + WRITE_UNALIGNED(WRITE_STORE, WRITE_STORE_MASKED); + if (--h == 0) + break; + END_Y_LOOP(sskip, dskip); + } + break; + case COPY_AND: + for (;;) { + int count = wleft; + + WRITE_UNALIGNED(WRITE_AND, WRITE_AND_MASKED); + if (--h == 0) + break; + END_Y_LOOP(sskip, dskip); + } + break; + default /*case COPY_FUNNY */ : + return FUNNY_CASE(); + } +#undef WRITE_UNALIGNED + } + } +#undef END_Y_LOOP +#undef NEXT_X_CHUNK + return 0; +#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) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + +#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 source_raster; + uint tile_bits_size; + const byte *source_data; + const byte *end; + int x, rw, w, h; + register const byte *bptr; /* actually chunk * */ + int dbit, wleft; + uint mask; + byte *dbase; + + DECLARE_SCAN_PTR_VARS(dbptr, byte *, dest_raster); +#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; + source_raster = tiles->raster; + source_data = tiles->data + ((y + py) % tiles->rep_height) * source_raster; + tile_bits_size = tiles->size.y * source_raster; + end = tiles->data + tile_bits_size; +#undef END_Y_LOOP +#define END_Y_LOOP(sdelta, ddelta)\ + if ( end - bptr <= sdelta ) /* wrap around */\ + bptr -= tile_bits_size;\ + bptr += sdelta; dbptr += ddelta + dest_raster = 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 source_x = 0. + */ + { + int source_x = (x + px) % tiles->rep_width; + + w = tiles->size.x - source_x; + bptr = source_data + ((source_x & ~chunk_align_bit_mask) >> 3); + dbit = x & chunk_align_bit_mask; + skew = dbit - (source_x & 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);\ + if ( --h == 0 ) break;\ + END_Y_LOOP(source_raster, dest_raster);\ + } + 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); + if (--h == 0) + break; + END_Y_LOOP(source_raster, dest_raster); + } +#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); + if (--h == 0) + break; + END_Y_LOOP(source_raster, dest_raster); + } +#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 = source_raster - words; + uint dskip = dest_raster - 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); + } + if (--h == 0) + break; + 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); + } + if (--h == 0) + break; + 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 = source_data; + 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 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, + gx_default_map_cmyk_color, gx_no_copy_alpha, + mem1_word_strip_tile_rectangle, gx_no_strip_copy_rop, + mem_word_get_bits_rectangle); + +/* 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) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + 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 * source_data, int source_x, int source_raster, gx_bitmap_id id, + int x, int y, int w, int h, gx_color_index color0, gx_color_index color1) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + byte *row; + uint raster; + bool store; + + fit_copy(dev, source_data, source_x, source_raster, id, x, y, w, h); + row = scan_line_base(mdev, y); + raster = mdev->raster; + store = (color0 != gx_no_color_index && color1 != gx_no_color_index); + mem_swap_byte_rect(row, raster, x, w, h, store); + mem_mono_copy_mono(dev, source_data, source_x, source_raster, id, + x, y, w, h, color0, color1); + 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..9a9413a94f --- /dev/null +++ b/pstoraster/gdevm16.c @@ -0,0 +1,168 @@ +/* Copyright (C) 1994, 1996, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* 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 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_default_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 >> 5) & 0x3f; + prgb[1] = ((value << 10) + (value << 4) + (value >> 2)) + >> (16 - gx_color_value_bits); + value = color & 0x1f; + 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) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; +#if arch_is_big_endian + const ushort color16 = (ushort)color; +#else + const ushort color16 = (ushort)((color << 8) | (color >> 8)); +#endif + declare_scan_ptr(dest); + fit_fill(dev, x, y, w, h); + setup_rect(dest); + while (h-- > 0) { + ushort *pptr = (ushort *) dest; + int cnt = w; + + do { + *pptr++ = color16; + } while (--cnt > 0); + inc_ptr(dest, draster); + } + return 0; +} + +/* 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) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; +#if arch_is_big_endian + const ushort zero16 = (ushort)zero; + const ushort 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; +} + +/* 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) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + + 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..12cf8ec9b8 --- /dev/null +++ b/pstoraster/gdevm2.c @@ -0,0 +1,259 @@ +/* Copyright (C) 1994, 1995, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* 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 */ + +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 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) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + + 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) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + 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 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, + gx_default_map_cmyk_color, gx_default_strip_tile_rectangle, + gx_no_strip_copy_rop, mem_word_get_bits_rectangle); + +/* 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) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + 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) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + 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..1e3a4b9328 --- /dev/null +++ b/pstoraster/gdevm24.c @@ -0,0 +1,526 @@ +/* Copyright (C) 1994, 1995, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* 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 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, + gx_default_map_cmyk_color, mem_true24_copy_alpha, + gx_default_strip_tile_rectangle, mem_true24_strip_copy_rop, + mem_get_bits_rectangle); + +/* 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) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + declare_unpack_color(r, g, b, color); + declare_scan_ptr(dest); + + /* + * In order to avoid testing w > 0 and h > 0 twice, we defer + * executing setup_rect, and use fit_fill_xywh instead of + * fit_fill. + */ + fit_fill_xywh(dev, x, y, w, h); + if (w >= 5) { + if (h <= 0) + return 0; + setup_rect(dest); + 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 */ + setup_rect(dest); + 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) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + 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) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + + 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) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + 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 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, + gx_default_map_cmyk_color, gx_default_strip_tile_rectangle, + gx_no_strip_copy_rop, mem_word_get_bits_rectangle); + +/* 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) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + 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) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + 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) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + 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..d354833236 --- /dev/null +++ b/pstoraster/gdevm32.c @@ -0,0 +1,249 @@ +/* Copyright (C) 1994, 1995, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* 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 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, + gx_default_cmyk_map_cmyk_color, gx_default_strip_tile_rectangle, + gx_default_strip_copy_rop, mem_get_bits_rectangle); + +/* 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) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + 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) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + 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) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + + 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 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, + gx_default_cmyk_map_cmyk_color, gx_default_strip_tile_rectangle, + gx_no_strip_copy_rop, mem_word_get_bits_rectangle); + +/* 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) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + 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..e0df0e13f6 --- /dev/null +++ b/pstoraster/gdevm4.c @@ -0,0 +1,319 @@ +/* Copyright (C) 1992, 1995, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* 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 */ + +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 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) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + + 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) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + const byte *line; + declare_scan_ptr(dest); + byte invert, bb; + + fit_copy(dev, base, sourcex, sraster, id, x, y, w, h); + setup_rect(dest); + line = base + (sourcex >> 3); + /* Divide into opaque and masked cases. */ + if (one == gx_no_color_index) { + if (zero == gx_no_color_index) + return 0; /* nothing to do */ + invert = 0xff; + bb = ((byte) zero << 4) | (byte) zero; + } else if (zero == gx_no_color_index) { + invert = 0; + bb = ((byte) one << 4) | (byte) one; + } else { + /* Opaque case. */ + int shift = ~(sourcex ^ x) & 1; + byte oz[4]; + + oz[0] = (byte)((zero << 4) | zero); + oz[1] = (byte)((zero << 4) | one); + oz[2] = (byte)((one << 4) | zero); + oz[3] = (byte)((one << 4) | one); + do { + register byte *dptr = (byte *) dest; + const byte *sptr = line; + register uint sbyte = *sptr++; + register int sbit = ~sourcex & 7; + int count = w; + + /* + * If the first source bit corresponds to an odd X in the + * destination, process it now. + */ + if (x & 1) { + *dptr = (*dptr & 0xf0) | + ((sbyte >> sbit) & 1 ? one : zero); + --count; /* may now be 0 */ + if (--sbit < 0) + sbit = 7, sbyte = *sptr++; + ++dptr; + } + /* + * Now we know the next destination X is even. We want to + * process 2 source bits at a time from now on, so set things up + * properly depending on whether the next source X (bit) is even + * or odd. In both even and odd cases, the active source bits + * are in bits 8..1 of sbyte. + */ + sbyte <<= shift; + sbit += shift - 1; + /* + * Now bit # sbit+1 is the most significant unprocessed bit + * in sbyte. -1 <= sbit <= 7; sbit is odd. + * Note that if sbit = -1, all of sbyte has been processed. + * + * Continue processing pairs of bits in the first source byte. + */ + while (count >= 2 && sbit >= 0) { + *dptr++ = oz[(sbyte >> sbit) & 3]; + sbit -= 2, count -= 2; + } + /* + * Now sbit = -1 iff we have processed the entire first source + * byte. + * + * Process full source bytes. + */ + if (shift) { + sbyte >>= 1; /* in case count < 8 */ + for (; count >= 8; dptr += 4, count -= 8) { + sbyte = *sptr++; + dptr[0] = oz[sbyte >> 6]; + dptr[1] = oz[(sbyte >> 4) & 3]; + dptr[2] = oz[(sbyte >> 2) & 3]; + dptr[3] = oz[sbyte & 3]; + } + sbyte <<= 1; + } else { + for (; count >= 8; dptr += 4, count -= 8) { + sbyte = (sbyte << 8) | *sptr++; + dptr[0] = oz[(sbyte >> 7) & 3]; + dptr[1] = oz[(sbyte >> 5) & 3]; + dptr[2] = oz[(sbyte >> 3) & 3]; + dptr[3] = oz[(sbyte >> 1) & 3]; + } + } + if (!count) + continue; + /* + * Process pairs of bits in the final source byte. Note that + * if sbit > 0, this is still the first source byte (the + * full-byte loop wasn't executed). + */ + if (sbit < 0) { + sbyte = (sbyte << 8) | (*sptr << shift); + sbit = 7; + } + while (count >= 2) { + *dptr++ = oz[(sbyte >> sbit) & 3]; + sbit -= 2, count -= 2; + } + /* + * If the final source bit corresponds to an even X value, + * process it now. + */ + if (count) { + *dptr = (*dptr & 0x0f) | + (((sbyte >> sbit) & 2 ? one : zero) << 4); + } + } while ((line += sraster, inc_ptr(dest, draster), --h) > 0); + return 0; + } + /* Masked case. */ + do { + register byte *dptr = (byte *) dest; + const byte *sptr = line; + register int sbyte = *sptr++ ^ invert; + register int sbit = 0x80 >> (sourcex & 7); + register byte mask = (x & 1 ? 0x0f : 0xf0); + int count = w; + + do { + if (sbyte & sbit) + *dptr = (*dptr & ~mask) | (bb & mask); + if ((sbit >>= 1) == 0) + sbit = 0x80, sbyte = *sptr++ ^ invert; + dptr += (mask = ~mask) >> 7; + } while (--count > 0); + line += sraster; + inc_ptr(dest, draster); + } while (--h > 0); + 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) +{ + /* Use monobit copy_mono. */ + int code; + + /* 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 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, + gx_default_map_cmyk_color, gx_default_strip_tile_rectangle, + gx_no_strip_copy_rop, mem_word_get_bits_rectangle); + +/* 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) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + 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) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + 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..875bcaddb8 --- /dev/null +++ b/pstoraster/gdevm8.c @@ -0,0 +1,247 @@ +/* Copyright (C) 1994, 1995, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* 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 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) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + + 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) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + 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 */ +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) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + + 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 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, + gx_default_map_cmyk_color, gx_default_strip_tile_rectangle, + gx_no_strip_copy_rop, mem_word_get_bits_rectangle); + +/* 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) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + 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) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + 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) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + 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..231e41920d --- /dev/null +++ b/pstoraster/gdevmem.c @@ -0,0 +1,498 @@ +/* Copyright (C) 1989, 1995, 1997, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Generic "memory" (stored bitmap) device */ +#include "memory_.h" +#include "gx.h" +#include "gserrors.h" +#include "gsrect.h" +#include "gsstruct.h" +#include "gxarith.h" +#include "gxdevice.h" +#include "gxgetbit.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 ENUM_USING(st_device_forward, vptr, sizeof(gx_device_forward), index - 2); +} +case 0: +ENUM_RETURN((mptr->foreign_bits ? NULL : (void *)mptr->base)); +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); + RELOC_USING(st_device_forward, vptr, sizeof(gx_device_forward)); +} +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) +{ + gx_device_init((gx_device *) dev, (const gx_device *)mdproto, + mem, true); + dev->stype = &st_device_memory; + switch (page_device) { + case -1: + set_dev_proc(dev, get_page_device, gx_default_get_page_device); + break; + case 1: + set_dev_proc(dev, 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) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + + *dev = mem_mono_device; + dev->memory = mem; + set_dev_proc(dev, get_page_device, gx_default_get_page_device); + mdev->target = target; + gdev_mem_mono_set_inverted(dev, true); + rc_init(dev, mem, 0); +} + + +/* 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, int width, int height) +{ + return round_up((ulong) height * + bitmap_raster(width * dev->color_info.depth), + max(align_bitmap_mod, arch_align_ptr_mod)); +} +ulong +gdev_mem_data_size(const gx_device_memory * dev, int width, int height) +{ + return mem_bitmap_bits_size(dev, width, height) + + (ulong) height *sizeof(byte *); + +} +/* + * Do the inverse computation: given a width (in pixels) and a buffer size, + * compute the maximum height. + */ +int +gdev_mem_max_height(const gx_device_memory * dev, int width, ulong size) +{ + ulong max_height = size / + (bitmap_raster(width * dev->color_info.depth) + sizeof(byte *)); + int height = (int)min(max_height, max_int); + + /* + * Because of alignment rounding, the just-computed height might + * be too large by a small amount. Adjust it the easy way. + */ + while (gdev_mem_data_size(dev, width, height) > size) + --height; + return height; +} + +/* Open a memory device, allocating the data area if appropriate, */ +/* and create the scan line table. */ +private void mem_set_line_ptrs(P4(gx_device_memory *, byte **, byte *, int)); +int +mem_open(gx_device * dev) +{ + return gdev_mem_open_scan_lines((gx_device_memory *)dev, dev->height); +} +int +gdev_mem_open_scan_lines(gx_device_memory *mdev, int setup_height) +{ + if (setup_height < 0 || setup_height > mdev->height) + return_error(gs_error_rangecheck); + 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->width, + mdev->height)), + mdev->base, setup_height); + return 0; +} +/* Set up the scan line pointers of a memory device. */ +/* Sets line_ptrs, base, raster; uses width, color_info.depth. */ +private void +mem_set_line_ptrs(gx_device_memory * mdev, byte ** line_ptrs, byte * base, + int count /* >= 0 */) +{ + byte **pptr = mdev->line_ptrs = line_ptrs; + byte **pend = pptr + count; + byte *scan_line = mdev->base = base; + uint raster = mdev->raster = gdev_mem_raster(mdev); + + 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) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + + 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) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + + if (mdev->bitmap_memory != 0) + gs_free_object(mdev->bitmap_memory, mdev->base, "mem_close"); + return 0; +} + +/* Copy bits to a client. */ +#undef chunk +#define chunk byte +int +mem_get_bits_rectangle(gx_device * dev, const gs_int_rect * prect, + gs_get_bits_params_t * params, gs_int_rect ** unread) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + gs_get_bits_options_t options = params->options; + int x = prect->p.x, w = prect->q.x - x, y = prect->p.y, h = prect->q.y - y; + + if (options == 0) { + params->options = + (GB_ALIGN_STANDARD | GB_ALIGN_ANY) | + (GB_RETURN_COPY | GB_RETURN_POINTER) | + (GB_OFFSET_0 | GB_OFFSET_SPECIFIED | GB_OFFSET_ANY) | + (GB_RASTER_STANDARD | GB_RASTER_SPECIFIED | GB_RASTER_ANY) | + GB_PACKING_CHUNKY | GB_COLORS_NATIVE | GB_ALPHA_NONE; + return_error(gs_error_rangecheck); + } + if ((w <= 0) | (h <= 0)) { + if ((w | h) < 0) + return_error(gs_error_rangecheck); + return 0; + } + if (x < 0 || w > dev->width - x || + y < 0 || h > dev->height - y + ) + return_error(gs_error_rangecheck); + { + byte *base = scan_line_base(mdev, y); + int code = gx_get_bits_return_pointer(dev, x, h, params, + GB_COLORS_NATIVE | GB_PACKING_CHUNKY | + GB_ALPHA_NONE, base); + + if (code >= 0) + return code; + return gx_get_bits_copy(dev, x, w, h, params, + GB_COLORS_NATIVE | GB_PACKING_CHUNKY | + GB_ALPHA_NONE, base, + gx_device_raster(dev, true)); + } +} + +#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. + * Note that the coordinates are specified in bits, not in terms of the + * actual device depth. + */ +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 rectangle to the client, swapping bytes as needed. */ +int +mem_word_get_bits_rectangle(gx_device * dev, const gs_int_rect * prect, + gs_get_bits_params_t * params, gs_int_rect ** unread) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + byte *src; + uint dev_raster = gx_device_raster(dev, 1); + int x = prect->p.x; + int w = prect->q.x - x; + int y = prect->p.y; + int h = prect->q.y - y; + int bit_x, bit_w; + int code; + + fit_fill_xywh(dev, x, y, w, h); + if (w <= 0 || h <= 0) { + /* + * It's easiest to just keep going with an empty rectangle. + * We pass the original rectangle to mem_get_bits_rectangle, + * so unread will be filled in correctly. + */ + x = y = w = h = 0; + } + bit_x = x * dev->color_info.depth; + bit_w = w * dev->color_info.depth; + src = scan_line_base(mdev, y); + mem_swap_byte_rect(src, dev_raster, bit_x, bit_w, h, false); + code = mem_get_bits_rectangle(dev, prect, params, unread); + mem_swap_byte_rect(src, dev_raster, bit_x, bit_w, h, false); + return code; +} + +#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) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + 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]) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + 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..17dc5c059e --- /dev/null +++ b/pstoraster/gdevmem.h @@ -0,0 +1,233 @@ +/* Copyright (C) 1991, 1995, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Private definitions for memory devices. */ + +#ifndef gdevmem_INCLUDED +# define gdevmem_INCLUDED + +#include "gxbitops.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_VARS(ptr, chunk *, draster) +#define DECLARE_SCAN_PTR_VARS(ptr, ptype, draster)\ + register ptype ptr;\ + uint draster +#define setup_rect(ptr)\ + SETUP_RECT_VARS(ptr, chunk *, draster) +#define SETUP_RECT_VARS(ptr, ptype, draster)\ + 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_rectangle(mem_get_bits_rectangle); +/* The following are for word-oriented devices. */ +#if arch_is_big_endian +# define mem_word_get_bits_rectangle mem_get_bits_rectangle +#else +dev_proc_get_bits_rectangle(mem_word_get_bits_rectangle); +#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, map_cmyk_color, copy_alpha, strip_tile_rectangle, strip_copy_rop, get_bits_rectangle)\ +{ 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,\ + gx_default_get_bits,\ + 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 */\ + gx_default_get_clipping_box,\ + gx_default_begin_typed_image,\ + get_bits_rectangle, /* differs */\ + gx_default_map_color_rgb_alpha,\ + gx_default_create_compositor,\ + gx_default_get_hardware_params,\ + gx_default_text_begin\ + },\ + 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, map_cmyk_color, strip_tile_rectangle, strip_copy_rop, get_bits_rectangle)\ + mem_full_alpha_device(name, rgb_depth, gray_depth, open, map_rgb_color,\ + map_color_rgb, copy_mono, copy_color, fill_rectangle,\ + map_cmyk_color, gx_default_copy_alpha,\ + strip_tile_rectangle, strip_copy_rop,\ + get_bits_rectangle) +#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,\ + gx_default_map_cmyk_color, gx_default_strip_tile_rectangle,\ + strip_copy_rop, mem_get_bits_rectangle) + +/* 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) + +/* ------ Implementations ------ */ + +extern const gx_device_memory mem_mono_device; +extern const gx_device_memory mem_mapped2_device; +extern const gx_device_memory mem_mapped4_device; +extern const gx_device_memory mem_mapped8_device; +extern const gx_device_memory mem_true16_device; +extern const gx_device_memory mem_true24_device; +extern const gx_device_memory mem_true32_device; +extern const gx_device_memory mem_planar_device; + +#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 mem_mono_word_device; +extern const gx_device_memory mem_mapped2_word_device; +extern const gx_device_memory mem_mapped4_word_device; +extern const gx_device_memory mem_mapped8_word_device; +extern const gx_device_memory mem_true24_word_device; +extern const gx_device_memory 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 */ + +#endif /* gdevmem_INCLUDED */ diff --git a/pstoraster/gdevmgr.h b/pstoraster/gdevmgr.h new file mode 100644 index 0000000000..0cab14414d --- /dev/null +++ b/pstoraster/gdevmgr.h @@ -0,0 +1,127 @@ +/* Copyright (C) 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 supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$*/ +/* Common header file for MGR devices */ + +#ifndef gdevmgr_INCLUDED +# define gdevmgr_INCLUDED + +#define MGR_RESERVEDCOLORS 16 + +/* Color mapping routines for 8-bit color (with a fixed palette). */ +dev_proc_map_rgb_color(mgr_8bit_map_rgb_color); +dev_proc_map_color_rgb(mgr_8bit_map_color_rgb); + + +/* extract from dump.h */ + +/* + * format for saved bitmaps + */ + +#define B_PUTHDR8(hdr, w, h, d) ( \ + (hdr)->magic[0] = 'y', (hdr)->magic[1] = 'z', \ + (hdr)->h_wide = (((w) >> 6) & 0x3f) + ' ', \ + (hdr)->l_wide = ((w) & 0x3f) + ' ', \ + (hdr)->h_high = (((h) >> 6) & 0x3f) + ' ', \ + (hdr)->l_high = ((h) & 0x3f) + ' ', \ + (hdr)->depth = ((d) & 0x3f) + ' ', \ + (hdr)->_reserved = ' ' ) + +struct b_header { + char magic[2]; /* magics */ + char h_wide; /* upper byte width (biased with 0x20) */ + char l_wide; /* lower byte width (biased with 0x20) */ + char h_high; /* upper byte height (biased with 0x20) */ + char l_high; /* lower byte height (biased with 0x20) */ + char depth; /* depth (biased with 0x20) */ + char _reserved; /* for alignment */ +}; + +/* + * Color lookup table information + */ +struct nclut { + unsigned short colnum; + unsigned short red, green, blue; +} ; + + +/* extract from color.h */ + +/* + * MGR Color Definitions + */ + +#define LUT_BW 0 +#define LUT_GREY 1 +#define LUT_BGREY 2 +#define LUT_VGA 3 +#define LUT_BCT 4 +#define LUT_USER 5 +#define LUT 6 +#define LUT_8 LUT + +#define RGB_RED 0 +#define RGB_GREEN 1 +#define RGB_BLUE 2 +#define RGB 3 + +#define LUTENTRIES 16 + +#define BW_RED 15, 0, 15, 0, 15, 0, 15, 0, 15, 0, 15, 0, 15, 0, 15, 0 +#define BW_GREEN BW_RED +#define BW_BLUE BW_RED + +#define GREY_RED 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 +#define GREY_GREEN GREY_RED +#define GREY_BLUE GREY_RED + +#define BGREY_RED 1, 0, 2, 8, 4, 3, 13, 11, 7, 6, 10, 12, 14, 5, 9, 15 +#define BGREY_GREEN BGREY_RED +#define BGREY_BLUE BGREY_RED + +#define VGA_RED 0, 0, 0, 0, 8, 8, 8, 12, 8, 0, 0, 0, 15, 15, 15, 15 +#define VGA_GREEN 0, 0, 8, 8, 0, 0, 8, 12, 8, 0, 15, 15, 0, 0, 15, 15 +#define VGA_BLUE 0, 8, 0, 8, 0, 8, 0, 12, 8, 15, 0, 15, 0, 15, 0, 15 + +#define BCT_RED 1, 7, 6, 15, 14, 3, 13, 11, 7, 13, 13, 15, 15, 5, 9, 15 +#define BCT_GREEN 1, 7, 13, 12, 5, 3, 13, 11, 7, 14, 15, 15, 14, 5, 9, 15 +#define BCT_BLUE 1, 14, 6, 8, 5, 3, 13, 11, 7, 15, 14, 12, 13, 5, 9, 15 + +#define USER_RED 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +#define USER_GREEN USER_RED +#define USER_BLUE USER_RED + +static char mgrlut[LUT][RGB][LUTENTRIES] = { + { { BW_RED }, { BW_GREEN }, { BW_BLUE } }, + { { GREY_RED }, { GREY_GREEN }, { GREY_BLUE } }, + { { BGREY_RED }, { BGREY_GREEN }, { BGREY_BLUE } }, + { { VGA_RED }, { VGA_GREEN }, { VGA_BLUE } }, + { { BCT_RED }, { BCT_GREEN }, { BCT_BLUE } }, + { { USER_RED }, { USER_GREEN }, { USER_BLUE } } +}; + +#endif /* gdevmgr_INCLUDED */ diff --git a/pstoraster/gdevmpla.c b/pstoraster/gdevmpla.c new file mode 100644 index 0000000000..239ffbcc8a --- /dev/null +++ b/pstoraster/gdevmpla.c @@ -0,0 +1,200 @@ +/* Copyright (C) 1993, 1994, 1997, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* 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_rectangle(mem_planar_get_bits_rectangle); +const gx_device_memory 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, + gx_default_map_cmyk_color, gx_default_strip_tile_rectangle, + gx_no_strip_copy_rop, mem_planar_get_bits_rectangle); + +/* 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) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + 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) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + 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) +{ + gx_device_memory * const mdev = (gx_device_memory *)dev; + 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_rectangle(gx_device * dev, const gs_int_rect * prect, + gs_get_bits_params_t * params, gs_int_rect ** unread) +{ + return_error(-1); +} diff --git a/pstoraster/gdevmrop.h b/pstoraster/gdevmrop.h new file mode 100644 index 0000000000..3c143c9212 --- /dev/null +++ b/pstoraster/gdevmrop.h @@ -0,0 +1,97 @@ +/* Copyright (C) 1995, 1996, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Definitions for device RasterOp implementations. */ +/* Requires gxdevmem.h, gsropt.h */ + +#ifndef gdevmrop_INCLUDED +# define gdevmrop_INCLUDED + +/* Define the table of RasterOp implementation procedures. */ +extern const rop_proc rop_proc_table[256]; + +/* Define the table of RasterOp operand usage. */ +extern const byte /*rop_usage_t */ rop_usage_table[256]; + +/* + * Compute the effective RasterOp for the 1-bit case, + * taking transparency into account. + */ +gs_rop3_t gs_transparent_rop(P1(gs_logical_operation_t lop)); + +#ifdef DEBUG +/* Trace a [strip_]copy_rop call. */ +void trace_copy_rop(P16(const char *cname, gx_device * dev, + const byte * sdata, int sourcex, uint sraster, + gx_bitmap_id id, const gx_color_index * scolors, + const gx_strip_bitmap * textures, + const gx_color_index * tcolors, + int x, int y, int width, int height, + int phase_x, int phase_y, gs_logical_operation_t lop)); +#endif + +/* + * PostScript colors normally act as the texture for RasterOp, with a null + * (all zeros) source. For images with CombineWithColor = true, we need + * a way to use the image data as the source. We implement this with a + * device that applies RasterOp with a specified texture to drawing + * operations, treating the drawing color as source rather than texture. + * The texture is a gx_device_color; it may be any type of color, even a + * pattern. + */ +#ifndef gx_device_color_DEFINED +# define gx_device_color_DEFINED +typedef struct gx_device_color_s gx_device_color; + +#endif + +#ifndef gx_device_rop_texture_DEFINED +# define gx_device_rop_texture_DEFINED +typedef struct gx_device_rop_texture_s gx_device_rop_texture; + +#endif + +struct gx_device_rop_texture_s { + gx_device_forward_common; + gs_logical_operation_t log_op; + gx_device_color texture; +}; + +#define private_st_device_rop_texture() /* in gdevrops.c */\ + gs_private_st_composite(st_device_rop_texture, gx_device_rop_texture,\ + "gx_device_rop_texture", device_rop_texture_enum_ptrs, device_rop_texture_reloc_ptrs) + +/* Create a RasterOp source device. */ +int gx_alloc_rop_texture_device(P3(gx_device_rop_texture ** prsdev, + gs_memory_t * mem, + client_name_t cname)); + +/* Initialize a RasterOp source device. */ +void gx_make_rop_texture_device(P4(gx_device_rop_texture * rsdev, + gx_device * target, + gs_logical_operation_t lop, + const gx_device_color * texture)); + +#endif /* gdevmrop_INCLUDED */ diff --git a/pstoraster/gdevnfwd.c b/pstoraster/gdevnfwd.c new file mode 100644 index 0000000000..e8cbb0fd92 --- /dev/null +++ b/pstoraster/gdevnfwd.c @@ -0,0 +1,797 @@ +/* Copyright (C) 1996, 1997, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Null and forwarding device implementation */ +#include "gx.h" +#include "gserrors.h" +#include "gxdevice.h" + +/* ---------------- Forwarding procedures ---------------- */ + +/* 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); + 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); + /* NOT image_data (OBSOLETE) */ + /* NOT end_image (OBSOLETE) */ + /* NOT strip_tile_rectangle */ + fill_dev_proc(dev, strip_copy_rop, gx_forward_strip_copy_rop); + fill_dev_proc(dev, get_clipping_box, gx_forward_get_clipping_box); + fill_dev_proc(dev, begin_typed_image, gx_forward_begin_typed_image); + fill_dev_proc(dev, get_bits_rectangle, gx_forward_get_bits_rectangle); + fill_dev_proc(dev, map_color_rgb_alpha, gx_forward_map_color_rgb_alpha); + fill_dev_proc(dev, create_compositor, gx_no_create_compositor); + fill_dev_proc(dev, get_hardware_params, gx_forward_get_hardware_params); + fill_dev_proc(dev, text_begin, gx_forward_text_begin); + 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); + set_dev_proc(dev, map_color_rgb_alpha, gx_forward_map_color_rgb_alpha); +} + +void +gx_forward_get_initial_matrix(gx_device * dev, gs_matrix * pmat) +{ + gx_device_forward * const fdev = (gx_device_forward *)dev; + 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_forward * const fdev = (gx_device_forward *)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_forward * const fdev = (gx_device_forward *)dev; + 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_forward * const fdev = (gx_device_forward *)dev; + 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_forward * const fdev = (gx_device_forward *)dev; + 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_fill_rectangle(gx_device * dev, int x, int y, int w, int h, + gx_color_index color) +{ + gx_device_forward * const fdev = (gx_device_forward *)dev; + gx_device *tdev = fdev->target; + + if (tdev == 0) + return_error(gs_error_Fatal); + return (*dev_proc(tdev, fill_rectangle)) (tdev, x, y, w, h, color); +} + +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_forward * const fdev = (gx_device_forward *)dev; + 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_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) +{ + gx_device_forward * const fdev = (gx_device_forward *)dev; + gx_device *tdev = fdev->target; + + if (tdev == 0) + return_error(gs_error_Fatal); + return (*dev_proc(tdev, copy_mono)) + (tdev, data, dx, raster, id, x, y, w, h, zero, one); +} + +int +gx_forward_copy_color(gx_device * dev, const byte * data, + int dx, int raster, gx_bitmap_id id, int x, int y, int w, int h) +{ + gx_device_forward * const fdev = (gx_device_forward *)dev; + gx_device *tdev = fdev->target; + + if (tdev == 0) + return_error(gs_error_Fatal); + return (*dev_proc(tdev, copy_color)) + (tdev, data, dx, raster, id, x, y, w, h); +} + +int +gx_forward_get_bits(gx_device * dev, int y, byte * data, byte ** actual_data) +{ + gx_device_forward * const fdev = (gx_device_forward *)dev; + 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_forward * const fdev = (gx_device_forward *)dev; + 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_forward * const fdev = (gx_device_forward *)dev; + 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_forward * const fdev = (gx_device_forward *)dev; + 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)); +} + +const gx_xfont_procs * +gx_forward_get_xfont_procs(gx_device * dev) +{ + gx_device_forward * const fdev = (gx_device_forward *)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_forward * const fdev = (gx_device_forward *)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_forward * const fdev = (gx_device_forward *)dev; + 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_forward * const fdev = (gx_device_forward *)dev; + gx_device *tdev = fdev->target; + gx_device *pdev; + + if (tdev == 0) + return gx_default_get_page_device(dev); + pdev = (*dev_proc(tdev, get_page_device)) (tdev); + return (pdev == tdev ? dev : pdev); +} + +int +gx_forward_get_alpha_bits(gx_device * dev, graphics_object_type type) +{ + gx_device_forward * const fdev = (gx_device_forward *)dev; + 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_forward * const fdev = (gx_device_forward *)dev; + 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_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_forward * const fdev = (gx_device_forward *)dev; + gx_device *tdev = fdev->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_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_forward * const fdev = (gx_device_forward *)dev; + 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_forward * const fdev = (gx_device_forward *)dev; + 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_forward * const fdev = (gx_device_forward *)dev; + 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) (tdev, 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_forward * const fdev = (gx_device_forward *)dev; + 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_forward * const fdev = (gx_device_forward *)dev; + 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_forward * const fdev = (gx_device_forward *)dev; + 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_forward * const fdev = (gx_device_forward *)dev; + 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, const gs_int_rect * prect, + const gx_drawing_color * pdcolor, const gx_clip_path * pcpath, + gs_memory_t * memory, gx_image_enum_common_t ** pinfo) +{ + gx_device_forward * const fdev = (gx_device_forward *)dev; + 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, prect, pdcolor, pcpath, + memory, pinfo); +} + +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_forward * const fdev = (gx_device_forward *)dev; + 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); +} + +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_forward * const fdev = (gx_device_forward *)dev; + gx_device *tdev = fdev->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); +} + +void +gx_forward_get_clipping_box(gx_device * dev, gs_fixed_rect * pbox) +{ + gx_device_forward * const fdev = (gx_device_forward *)dev; + gx_device *tdev = fdev->target; + + if (tdev == 0) + gx_default_get_clipping_box(dev, pbox); + else + (*dev_proc(tdev, get_clipping_box)) (tdev, pbox); +} + +int +gx_forward_begin_typed_image(gx_device * dev, + const gs_imager_state * pis, const gs_matrix * pmat, + const gs_image_common_t * pim, const gs_int_rect * prect, + const gx_drawing_color * pdcolor, const gx_clip_path * pcpath, + gs_memory_t * memory, gx_image_enum_common_t ** pinfo) +{ + gx_device_forward * const fdev = (gx_device_forward *)dev; + gx_device *tdev = fdev->target; + + dev_proc_begin_typed_image((*proc)); + + if (tdev == 0) + tdev = dev, proc = gx_default_begin_typed_image; + else + proc = dev_proc(tdev, begin_typed_image); + return (*proc) (tdev, pis, pmat, pim, prect, pdcolor, pcpath, + memory, pinfo); +} + +int +gx_forward_get_bits_rectangle(gx_device * dev, const gs_int_rect * prect, + gs_get_bits_params_t * params, gs_int_rect ** unread) +{ + gx_device_forward * const fdev = (gx_device_forward *)dev; + gx_device *tdev = fdev->target; + + dev_proc_get_bits_rectangle((*proc)); + + if (tdev == 0) + tdev = dev, proc = gx_default_get_bits_rectangle; + else + proc = dev_proc(tdev, get_bits_rectangle); + return (*proc) (tdev, prect, params, unread); +} + +int +gx_forward_map_color_rgb_alpha(gx_device * dev, gx_color_index color, + gx_color_value prgba[4]) +{ + gx_device_forward * const fdev = (gx_device_forward *)dev; + gx_device *tdev = fdev->target; + + return (tdev == 0 ? gx_default_map_color_rgb_alpha(dev, color, prgba) : + (*dev_proc(tdev, map_color_rgb_alpha)) (tdev, color, prgba)); +} + +int +gx_forward_get_hardware_params(gx_device * dev, gs_param_list * plist) +{ + gx_device_forward * const fdev = (gx_device_forward *)dev; + gx_device *tdev = fdev->target; + + return (tdev == 0 ? gx_default_get_hardware_params(dev, plist) : + (*dev_proc(tdev, get_hardware_params)) (tdev, plist)); +} + +int +gx_forward_text_begin(gx_device * dev, gs_imager_state * pis, + const gs_text_params_t * text, const gs_font * font, +gx_path * path, const gx_device_color * pdcolor, const gx_clip_path * pcpath, + gs_memory_t * memory, gs_text_enum_t ** ppenum) +{ + gx_device_forward * const fdev = (gx_device_forward *)dev; + gx_device *tdev = fdev->target; + + dev_proc_text_begin((*proc)); + + if (tdev == 0) + tdev = dev, proc = gx_default_text_begin; + else + proc = dev_proc(tdev, text_begin); + return (*proc) (tdev, pis, text, font, path, pdcolor, pcpath, + memory, ppenum); +} + +/* ---------------- 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); + +/* We would like to have null implementations of begin/data/end image, */ +/* but we can't do this, because image_data must keep track of the */ +/* Y position so it can return 1 when done. */ +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,\ + gx_default_begin_image,\ + gx_default_image_data,\ + gx_default_end_image,\ + gx_default_strip_tile_rectangle,\ + null_strip_copy_rop,\ + gx_default_get_clipping_box,\ + gx_default_begin_typed_image,\ + gx_default_get_bits_rectangle,\ + gx_forward_map_color_rgb_alpha,\ + gx_non_imaging_create_compositor,\ + gx_forward_get_hardware_params,\ + gx_default_text_begin\ +} + +const gx_device_null gs_null_device = +{ + std_device_std_body_type_open(gx_device_null, 0, "null", &st_device_null, + 0, 0, 72, 72), + null_procs(gx_default_get_page_device /* not a page device */ ), + 0 /* target */ +}; + +const gx_device_null gs_nullpage_device = +{ +std_device_std_body_type_open(gx_device_null, 0, "nullpage", &st_device_null, + 72 /*nominal */ , 72 /*nominal */ , 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) +{ + /* + * If this is not a page device, we must defeat attempts to reset + * the size; otherwise this is equivalent to gx_forward_put_params. + */ + gx_device_forward * const fdev = (gx_device_forward *)dev; + 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 || (*dev_proc(dev, get_page_device)) (dev) == dev) + 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_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; +} diff --git a/pstoraster/gdevpccm.h b/pstoraster/gdevpccm.h new file mode 100644 index 0000000000..1322594d24 --- /dev/null +++ b/pstoraster/gdevpccm.h @@ -0,0 +1,44 @@ +/* Copyright (C) 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 supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Requires gxdevice.h */ + +#ifndef gdevpccm_INCLUDED +# define gdevpccm_INCLUDED + +/* Color mapping routines for EGA/VGA-style color. */ +dev_proc_map_rgb_color(pc_4bit_map_rgb_color); +dev_proc_map_color_rgb(pc_4bit_map_color_rgb); +#define dci_pc_4bit { 3, 4, 3, 2, 4, 3 } + +/* Color mapping routines for 8-bit color (with a fixed palette). */ +dev_proc_map_rgb_color(pc_8bit_map_rgb_color); +dev_proc_map_color_rgb(pc_8bit_map_color_rgb); +#define dci_pc_8bit { 3, 8, 6, 6, 7, 7 } + +/* Write the palette on a file. */ +int pc_write_palette(P3(gx_device *, uint, FILE *)); + +#endif /* gdevpccm_INCLUDED */ diff --git a/pstoraster/gdevpcfb.h b/pstoraster/gdevpcfb.h new file mode 100644 index 0000000000..21bde1bb9a --- /dev/null +++ b/pstoraster/gdevpcfb.h @@ -0,0 +1,209 @@ +/* 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 supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* IBM PC frame buffer definitions */ + +#ifndef gdevpcfb_INCLUDED +# define gdevpcfb_INCLUDED + +#ifdef __MSDOS__ +# include "dos_.h" +typedef union REGS registers; + +#endif + +/* For testing, the 16-color display may be defined as a monochrome, */ +/* 8-color, or 16-color device. */ +#define ega_bits_of_color 2 /* 0, 1, or 2 */ +#define rgb_max ega_bits_of_color + +/* Define the short (integer) version of "transparent" color. */ +/* ****** Depends on gx_no_color_index being all 1's. ***** */ +#define no_color ((int)gx_no_color_index) + +/* Procedures */ + + /* See gxdevice.h for the definitions of the procedures. */ + +dev_proc_open_device(ega_open); +dev_proc_close_device(ega_close); +dev_proc_fill_rectangle(ega_fill_rectangle); +dev_proc_tile_rectangle(ega_tile_rectangle); +dev_proc_copy_mono(ega_copy_mono); +dev_proc_copy_color(ega_copy_color); +dev_proc_get_bits(ega_get_bits); + +/* Structure for saving state of BIOS variables. */ +typedef struct pcfb_bios_state_s { + int display_mode; /* must be first, see pcfb_save_state */ + /* in gdevpcfb.c */ + byte text_page; + uint text_cursor_mode; + uint text_font; + byte text_attribute; + byte border_color; +} pcfb_bios_state; + +/* Procedures used by gdevpcfb.c */ +void pcfb_set_signals(P1(gx_device *)); +void pcfb_get_state(P1(pcfb_bios_state *)); +void pcfb_set_mode(P1(int)); +void pcfb_set_state(P1(const pcfb_bios_state *)); + +/* Types for frame buffer pointers. */ +typedef byte *fb_ptr; +typedef volatile byte *volatile_fb_ptr; + +/* Define the nominal page height in inches. */ +#ifdef A4 +# define PAGE_HEIGHT_INCHES 11.69 +#else +# define PAGE_HEIGHT_INCHES 11.0 +#endif + +/* The device descriptor */ +typedef struct gx_device_ega_s gx_device_ega; +struct gx_device_ega_s { + gx_device_common; + int raster; /* frame buffer bytes per line */ + int fb_seg_mult; /* multiplier for segment part */ + /* of frame buffer pointer */ + int fb_byte_mult; /* multiplier for word part ditto */ +#define mk_fb_ptr(x, y)\ + (fb_dev->fb_byte_mult == 0 ?\ + (fb_ptr)MK_PTR(regen + (y) * (fb_dev->fb_seg_mult), (x) >> 3) :\ + (fb_ptr)MK_PTR(regen + ((y) >> 4) * (fb_dev->fb_seg_mult),\ + (((y) & 15) * fb_dev->fb_byte_mult) + ((x) >> 3))) + int video_mode; +}; + +/* Macro for creating instances */ +/* The initial parameters map an appropriate fraction of */ +/* the screen to a full-page coordinate space. */ +/* This may or may not be what is desired! */ +#define ega_device(dev_name, procs, fb_raster, screen_height, aspect_ratio, video_mode)\ + { std_device_dci_body(gx_device_ega, &procs, dev_name,\ + fb_raster * 8, screen_height,\ + (screen_height * (aspect_ratio)) / PAGE_HEIGHT_INCHES, /* x dpi */\ + screen_height / PAGE_HEIGHT_INCHES, /* y dpi */\ + (rgb_max ? 3 : 1), /* num_components */\ + 4, /* depth */\ + (rgb_max ? rgb_max : 1), /* max_gray */\ + rgb_max,\ + (rgb_max ? rgb_max + 1 : 2), /* dither_grays */\ + (rgb_max ? rgb_max + 1 : 0) /* dither_colors */\ + ),\ + { 0 }, /* std_procs */\ + fb_raster,\ + (fb_raster & 15 ? fb_raster : fb_raster >> 4),\ + (fb_raster & 15 ? fb_raster : 0),\ + video_mode\ + } + +/* Define the device port and register numbers, and the regen map base */ +#define seq_addr 0x3c4 +#define s_map 2 +#define set_s_map(mask) outport2(seq_addr, s_map, mask) +#define graph_addr 0x3ce +#define g_const 0 /* set/reset */ +#define set_g_const(color) outport2(graph_addr, g_const, color) +#define g_const_map 1 /* enable set/reset */ +#define set_g_const_map(map) outport2(graph_addr, g_const_map, map) +#define g_function 3 +# define gf_WRITE 0 +# define gf_AND 8 +# define gf_OR 0x10 +# define gf_XOR 0x18 +#define set_g_function(func) outport2(graph_addr, g_function, func) +#define g_read_plane 4 +#define set_g_read_plane(plane) outport2(graph_addr, g_read_plane, plane) +#define g_mode 5 +# define gm_DATA 0 +# define gm_FILL 2 +#define set_g_mode(mode) outport2(graph_addr, g_mode, mode) +#define g_mask 8 +#define set_g_mask(mask) outport2(graph_addr, g_mask, mask) +#define select_g_mask() outportb(graph_addr, g_mask) +#define out_g_mask(mask) outportb(graph_addr+1, mask) +#define regen 0xa000 + +/* Define access to the frame buffer and the video registers */ +/* according to whether we are on a DOS system or a Unix system. */ + +#if defined(M_UNIX) || defined(M_XENIX) || defined(UNIX) || defined(SYSV) || defined(__linux__) + + /* SCO Unix/Xenix, AT&T SVR4, or Linux. */ + +#undef outportb + +#if defined(__GNUC__) + /* Inline assembly version for gcc */ + /* Under SCO, requires installing the gnu assembler as "as" */ +static inline void +outportb(int port, int data) +{ + __asm__ volatile ("outb %0,%1":: + "a" ((unsigned char)data), + "d" ((unsigned short)port)); +} +static inline void +outport2(int port, int index, int data) +{ + __asm__ volatile ("movb %0,%%ah; movb %1,%%al; outw %%ax,%2":: + "qmi" ((unsigned char)data), + "qmi" ((unsigned char)index), + "d" ((unsigned short)port): + "eax"); +} +#else +void outportb(P2(uint, byte)); +void outport2(P3(uint, byte, byte)); + +#endif + +/* Redefine mk_fb_ptr -- no segmented addressing. */ + +#undef mk_fb_ptr +extern fb_ptr fb_addr; + +#define mk_fb_ptr(x, y) (fb_addr + (y) * (fb_dev->raster) + ((x) >> 3)) + +#else + + /* MS-DOS */ + +/* outportb is defined in dos_.h */ +#define outport2(port, index, data)\ + (outportb(port, index), outportb((port)+1, data)) + +#endif + +/* Fetch and discard a byte. Prevent the compiler from */ +/* optimizing this away. */ +static unsigned char byte_discard_; + +#define byte_discard(expr) byte_discard_ = (expr) + +#endif /* gdevpcfb_INCLUDED */ diff --git a/pstoraster/gdevpcl.h b/pstoraster/gdevpcl.h new file mode 100644 index 0000000000..b6954f159a --- /dev/null +++ b/pstoraster/gdevpcl.h @@ -0,0 +1,52 @@ +/* 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 supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Requires gdevprn.h */ + +#ifndef gdevpcl_INCLUDED +# define gdevpcl_INCLUDED + +/* Define the PCL paper size codes. */ +#define PAPER_SIZE_LETTER 2 +#define PAPER_SIZE_LEGAL 3 +#define PAPER_SIZE_A4 26 +#define PAPER_SIZE_A3 27 +#define PAPER_SIZE_A2 28 +#define PAPER_SIZE_A1 29 +#define PAPER_SIZE_A0 30 + +/* Get the paper size code, based on width and height. */ +int gdev_pcl_paper_size(P1(gx_device *)); + +/* Color mapping procedures for 3-bit-per-pixel RGB printers */ +dev_proc_map_rgb_color(gdev_pcl_3bit_map_rgb_color); +dev_proc_map_color_rgb(gdev_pcl_3bit_map_color_rgb); + +/* Row compression routines */ +typedef ulong word; +int gdev_pcl_mode2compress(P3(const word * row, const word * end_row, byte * compressed)), + gdev_pcl_mode3compress(P4(int bytecount, const byte * current, byte * previous, byte * compressed)); + +#endif /* gdevpcl_INCLUDED */ diff --git a/pstoraster/gdevpipe.c b/pstoraster/gdevpipe.c new file mode 100644 index 0000000000..03909db6a7 --- /dev/null +++ b/pstoraster/gdevpipe.c @@ -0,0 +1,72 @@ +/* Copyright (C) 1993, 1994, 1997, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* %pipe% IODevice */ +#include "errno_.h" +#include "pipe_.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" + +/* The pipe IODevice */ +private iodev_proc_fopen(pipe_fopen); +private iodev_proc_fclose(pipe_fclose); +const gx_io_device gs_iodev_pipe = +{ + "%pipe%", "FileSystem", + {iodev_no_init, iodev_no_open_device, + NULL /*iodev_os_open_file */ , pipe_fopen, pipe_fclose, + 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/gdevpm.h b/pstoraster/gdevpm.h new file mode 100644 index 0000000000..f1f7b3cd88 --- /dev/null +++ b/pstoraster/gdevpm.h @@ -0,0 +1,46 @@ +/* Copyright (C) 1992, 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 supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Defines common to gdevpm.c, gspmdrv.c and PM GSview */ + +#ifndef gdevpm_INCLUDED +# define gdevpm_INCLUDED + +#define SHARED_NAME "\\SHAREMEM\\%s" +#define SYNC_NAME "\\SEM32\\SYNC_%s" +#define NEXT_NAME "\\SEM32\\NEXT_%s" +#define MUTEX_NAME "\\SEM32\\MUTEX_%s" +#define QUEUE_NAME "\\QUEUES\\%s" + +#define GS_UPDATING 1 +#define GS_SYNC 2 +#define GS_PAGE 3 +#define GS_CLOSE 4 +#define GS_ERROR 5 +#define GS_PALCHANGE 6 +#define GS_BEGIN 7 +#define GS_END 8 + +#endif /* gdevpm_INCLUDED */ diff --git a/pstoraster/gdevprn.c b/pstoraster/gdevprn.c new file mode 100644 index 0000000000..657b05c404 --- /dev/null +++ b/pstoraster/gdevprn.c @@ -0,0 +1,837 @@ +/* + Copyright 1993-2000 by Easy Software Products. + Copyright 1990, 1995, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Generic printer driver support */ +#include "ctype_.h" +#include "gdevprn.h" +#include "gp.h" +#include "gsparam.h" +#include "gxclio.h" +#include + +/* ---------------- Standard device procedures ---------------- */ + +/* Define the standard printer procedure vector. */ +const gx_device_procs prn_std_procs = + prn_procs(gdev_prn_open, gdev_prn_output_page, gdev_prn_close); + +/* Forward references */ +int gdev_prn_maybe_reallocate_memory(P4(gx_device_printer *pdev, + gdev_prn_space_params *old_space, + int old_width, int old_height)); + +/* ------ Open/close ------ */ + +/* Open a generic printer device. */ +/* Specific devices may wish to extend this. */ +int +gdev_prn_open(gx_device * pdev) +{ + gx_device_printer * const ppdev = (gx_device_printer *)pdev; + int code; + + ppdev->file = NULL; + code = gdev_prn_allocate_memory(pdev, NULL, 0, 0); + if (code < 0) + return code; + if (ppdev->OpenOutputFile) + code = gdev_prn_open_printer(pdev, 1); + return code; +} + +/* Generic closing for the printer device. */ +/* Specific devices may wish to extend this. */ +int +gdev_prn_close(gx_device * pdev) +{ + gx_device_printer * const ppdev = (gx_device_printer *)pdev; + + gdev_prn_free_memory(pdev); + if (ppdev->file != NULL) { + if (ppdev->file != stdout) + gp_close_printer(ppdev->file, ppdev->fname); + ppdev->file = NULL; + } + return 0; +} + +private int /* returns 0 ok, else -ve error cde */ +gdev_prn_setup_as_command_list(gx_device *pdev, gs_memory_t *buffer_memory, + byte **the_memory, + const gdev_prn_space_params *space_params, + bool bufferSpace_is_exact) +{ + gx_device_printer * const ppdev = (gx_device_printer *)pdev; + uint space; + int code; + gx_device_clist *const pclist_dev = (gx_device_clist *)pdev; + gx_device_clist_common * const pcldev = &pclist_dev->common; + bool reallocate = *the_memory != 0; + byte *base; + + /* Try to allocate based simply on param-requested buffer size */ + for ( space = space_params->BufferSpace; ; ) { + base = (reallocate ? + gs_resize_object(buffer_memory, *the_memory, space, + "cmd list buffer") : + gs_alloc_bytes(buffer_memory, space, + "cmd list buffer")); + if (base != 0) + break; + if (bufferSpace_is_exact || (space >>= 1) < PRN_MIN_BUFFER_SPACE) + break; + } + if (base == 0) + return_error(gs_error_VMerror); + *the_memory = base; + + /* Try opening the command list, to see if we allocated */ + /* enough buffer space. */ +open_c: + ppdev->buf = base; + ppdev->buffer_space = space; + clist_init_params(pclist_dev, base, space, pdev, + ppdev->printer_procs.make_buffer_device, + space_params->band, ppdev->is_async_renderer, + (ppdev->bandlist_memory == 0 ? &gs_memory_default : + ppdev->bandlist_memory), + ppdev->free_up_bandlist_memory, + ppdev->clist_disable_mask); + 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 >= space_params->BufferSpace && + !bufferSpace_is_exact + ) { + space <<= 1; + if (reallocate) { + base = gs_resize_object(buffer_memory, + *the_memory, space, + "cmd list buf(retry open)"); + if (base != 0) + *the_memory = base; + } else { + gs_free_object(buffer_memory, base, + "cmd list buf(retry open)"); + *the_memory = base = + gs_alloc_bytes(buffer_memory, space, + "cmd list buf(retry open)"); + } + ppdev->buf = *the_memory; + if (base != 0) + goto open_c; + } + /* Failure. */ + if (!reallocate) { + gs_free_object(buffer_memory, base, "cmd list buf"); + ppdev->buffer_space = 0; + *the_memory = 0; + } + } + return code; +} + +private bool /* ret true if device was cmd list, else false */ +gdev_prn_tear_down(gx_device *pdev, byte **the_memory) +{ + gx_device_printer * const ppdev = (gx_device_printer *)pdev; + gx_device_memory * const pmemdev = (gx_device_memory *)pdev; + gx_device_clist *const pclist_dev = (gx_device_clist *)pdev; + gx_device_clist_common * const pcldev = &pclist_dev->common; + bool is_command_list; + + if (ppdev->buffer_space != 0) { + /* Close cmd list device & point to the storage */ + (*gs_clist_device_procs.close_device)( (gx_device *)pcldev ); + *the_memory = ppdev->buf; + ppdev->buf = 0; + ppdev->buffer_space = 0; + is_command_list = true; + } else { + /* point at the device bitmap, no need to close mem dev */ + *the_memory = pmemdev->base; + pmemdev->base = 0; + is_command_list = false; + } + + /* Reset device proc vector to default */ + if (ppdev->orig_procs.open_device != 0) + pdev->procs = ppdev->orig_procs; + ppdev->orig_procs.open_device = 0; /* prevent uninit'd restore of procs */ + + return is_command_list; +} + +private int +gdev_prn_allocate(gx_device *pdev, gdev_prn_space_params *new_space_params, + int new_width, int new_height, bool reallocate) +{ + gx_device_printer * const ppdev = (gx_device_printer *)pdev; + gx_device_memory * const pmemdev = (gx_device_memory *)pdev; + byte *the_memory = 0; + gdev_prn_space_params save_params; + int save_width = ppdev->width, save_height = ppdev->height; + bool is_command_list = false; + bool save_is_command_list = false; + int ecode = 0; + int pass; + gs_memory_t *buffer_memory = + (ppdev->buffer_memory == 0 ? &gs_memory_default : + ppdev->buffer_memory); + + /* If reallocate, find allocated memory & tear down buffer device */ + if (reallocate) + save_is_command_list = gdev_prn_tear_down(pdev, &the_memory); + + /* Re/allocate memory */ + ppdev->orig_procs = pdev->procs; + for ( pass = 1; pass <= (reallocate ? 2 : 1); ++pass ) { + ulong mem_space; + byte *base = 0; + bool bufferSpace_is_default = false; + gdev_prn_space_params space_params = ppdev->space_params; + + if (reallocate) + switch (pass) + { + case 1: + /* Setup device to get reallocated */ + save_params = ppdev->space_params; + ppdev->space_params = *new_space_params; + save_width = ppdev->width; + ppdev->width = new_width; + save_height = ppdev->height; + ppdev->height = new_height; + break; + case 2: /* only comes here if reallocate */ + /* Restore device to previous contents */ + ppdev->space_params = save_params; + ppdev->width = save_width; + ppdev->height = save_height; + break; + } + + /* Init clist/mem device-specific fields */ + memset(ppdev->skip, 0, sizeof(ppdev->skip)); + mem_space = gdev_mem_bitmap_size(pmemdev); + + /* Compute desired space params: never use the space_params as-is. */ + /* Rather, give the dev-specific driver a chance to adjust them. */ + space_params.BufferSpace = 0; + (*ppdev->printer_procs.get_space_params)(ppdev, &space_params); + if (ppdev->is_async_renderer && space_params.band.BandBufferSpace != 0) + space_params.BufferSpace = space_params.band.BandBufferSpace; + else if (space_params.BufferSpace == 0) { + if (space_params.band.BandBufferSpace > 0) + space_params.BufferSpace = space_params.band.BandBufferSpace; + else { + space_params.BufferSpace = ppdev->space_params.BufferSpace; + bufferSpace_is_default = true; + } + } + + /* Determine if we can use a full bitmap buffer, or have to use banding */ + if (pass > 1) + is_command_list = save_is_command_list; + else { + is_command_list = space_params.banding_type == BandingAlways || + mem_space >= space_params.MaxBitmap || + mem_space != (uint)mem_space; /* too big to allocate */ + } + if (!is_command_list) { + /* Try to allocate memory for full memory buffer */ + base = reallocate + ? gs_resize_object( buffer_memory, the_memory, + (uint)mem_space, "printer buffer" ) + : gs_alloc_bytes( buffer_memory, (uint)mem_space, + "printer_buffer" ); + if (base == 0) + is_command_list = true; + else + the_memory = base; + } + if (!is_command_list && pass == 1 && PRN_MIN_MEMORY_LEFT != 0 + && buffer_memory == &gs_memory_default) { + /* before using full memory buffer, ensure enough working mem left */ + byte * left = gs_alloc_bytes( buffer_memory, + PRN_MIN_MEMORY_LEFT, "printer mem left"); + if (left == 0) + is_command_list = true; + else + gs_free_object(buffer_memory, left, "printer mem left"); + } + + if (is_command_list) { + /* Buffer the image in a command list. */ + /* Release the buffer if we allocated it. */ + int code; + if (!reallocate) { + gs_free_object(buffer_memory, the_memory, + "printer buffer(open)"); + the_memory = 0; + } + if (space_params.banding_type == BandingNever) { + ecode = gs_note_error(gs_error_VMerror); + continue; + } + code = gdev_prn_setup_as_command_list(pdev, buffer_memory, + &the_memory, &space_params, + !bufferSpace_is_default); + if (ecode == 0) + ecode = code; + + if ( code >= 0 || (reallocate && pass > 1) ) + ppdev->procs = gs_clist_device_procs; + } else { + /* Render entirely in memory. */ + int code; + + ppdev->buffer_space = 0; + code = (*ppdev->printer_procs.make_buffer_device) + (pmemdev, pdev, buffer_memory, false); + if (code < 0) { /* Catastrophic. Shouldn't ever happen */ + gs_free_object(buffer_memory, base, "printer buffer"); + pdev->procs = ppdev->orig_procs; + ppdev->orig_procs.open_device = 0; /* prevent uninit'd restore of procs */ + return_error(code); + } + pmemdev->base = base; + } + if (ecode == 0) + break; + } + + if (ecode >= 0 || reallocate) { /* even if realloc failed */ + /* 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); + COPY_PROC(get_clipping_box); + COPY_PROC(map_color_rgb_alpha); + COPY_PROC(get_hardware_params); +#undef COPY_PROC + /* If using a command list, already opened the device. */ + if (is_command_list) + return ecode; + else + return (*dev_proc(pdev, open_device))(pdev); + } else { + pdev->procs = ppdev->orig_procs; + ppdev->orig_procs.open_device = 0; /* prevent uninit'd restore of procs */ + return ecode; + } +} + +int +gdev_prn_allocate_memory(gx_device *pdev, + gdev_prn_space_params *new_space_params, + int new_width, int new_height) +{ + return gdev_prn_allocate(pdev, new_space_params, + new_width, new_height, false); +} + +int +gdev_prn_reallocate_memory(gx_device *pdev, + gdev_prn_space_params *new_space_params, + int new_width, int new_height) +{ + return gdev_prn_allocate(pdev, new_space_params, + new_width, new_height, true); +} + +int +gdev_prn_free_memory(gx_device *pdev) +{ + gx_device_printer * const ppdev = (gx_device_printer *)pdev; + byte *the_memory = 0; + gs_memory_t *buffer_memory = + (ppdev->buffer_memory == 0 ? &gs_memory_default : + ppdev->buffer_memory); + + gdev_prn_tear_down(pdev, &the_memory); + gs_free_object(buffer_memory, the_memory, "gdev_prn_free_memory"); + return 0; +} + +/* ------------- Stubs related only to async rendering ------- */ + +int /* rets 0 ok, -ve error if couldn't start thread */ +gx_default_start_render_thread(gdev_prn_start_render_params *params) +{ + return gs_error_unknownerror; +} + +/* Open the renderer's copy of a device. */ +/* This is overriden in gdevprna.c */ +int +gx_default_open_render_device(gx_device_printer *pdev) +{ + return gs_error_unknownerror; +} + +/* Close the renderer's copy of a device. */ +int +gx_default_close_render_device(gx_device_printer *pdev) +{ + return gdev_prn_close( (gx_device *)pdev ); +} + +/* ------ 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) +{ + gx_device_printer * const ppdev = (gx_device_printer *)pdev; + int code = gx_default_get_params(pdev, plist); + + if (code < 0 || + (ppdev->Duplex_set >= 0 && + (code = (ppdev->Duplex_set ? + param_write_bool(plist, "Duplex", &ppdev->Duplex) : + param_write_null(plist, "Duplex"))) < 0) + ) + return code; + + return 0; +} + +/* Put parameters. */ +int +gdev_prn_put_params(gx_device * pdev, gs_param_list * plist) +{ + gx_device_printer * const ppdev = (gx_device_printer *)pdev; + int ecode = 0; + int code; + const char *param_name; + bool is_open = pdev->is_open; + bool oof = ppdev->OpenOutputFile; + bool rpp = ppdev->ReopenPerPage; + bool duplex; + int duplex_set = -1; + int width = pdev->width; + int height = pdev->height; + gdev_prn_space_params sp, save_sp; + gs_param_dict mdict; + + sp = ppdev->space_params; + save_sp = sp; + + 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; + } + + switch (code = param_read_bool(plist, (param_name = "ReopenPerPage"), &rpp)) { + 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: + ; + } +#define CHECK_PARAM_CASES(member, bad, label)\ + case 0:\ + if ((sp.params_are_read_only ? sp.member != save_sp.member : bad))\ + ecode = gs_error_rangecheck;\ + else\ + break;\ + goto label;\ + default:\ + ecode = code;\ +label:\ + param_signal_error(plist, param_name, ecode);\ + case 1:\ + 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->OpenOutputFile = oof; + ppdev->ReopenPerPage = rpp; + if (duplex_set >= 0) { + ppdev->Duplex = duplex; + ppdev->Duplex_set = duplex_set; + } + ppdev->space_params = sp; + + /* If necessary, free and reallocate the printer memory. */ + /* Formerly, would not reallocate if device is not open: */ + /* we had to patch this out (see News for 5.50). */ + code = gdev_prn_maybe_reallocate_memory(ppdev, &save_sp, width, height); + if (code < 0) + return code; + + return 0; +} + +/* ------ Others ------ */ + +#define TILE_SIZE 256 + +/* Default routine to override current space_params. */ +void +gdev_prn_default_get_space_params(const gx_device_printer *printer_dev, + gdev_prn_space_params *space_params) +{ + int cache_size; /* Size of tile cache in bytes */ + char *cache_env, /* Cache size environment variable */ + cache_units[255]; /* Cache size units */ + + + 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 * TILE_SIZE * TILE_SIZE; + break; + case 2 : + if (tolower(cache_units[0]) == 'g') + cache_size *= 1024 * 1024 * 1024; + else if (tolower(cache_units[0]) == 'm') + cache_size *= 1024 * 1024; + else if (tolower(cache_units[0]) == 'k') + cache_size *= 1024; + else if (tolower(cache_units[0]) == 't') + cache_size *= 4 * TILE_SIZE * TILE_SIZE; + break; + } + } + else + cache_size = 32 * 1024 * 1024; + + space_params->MaxBitmap = cache_size; +} + +/* Generic routine to send the page to the printer. */ +int /* 0 ok, -ve error, or 1 if successfully upgraded to buffer_page */ +gdev_prn_output_page(gx_device * pdev, int num_copies, int flush) +{ + gx_device_printer * const ppdev = (gx_device_printer *)pdev; + int outcode = 0, closecode = 0, errcode = 0, endcode; + bool upgraded_copypage = false; + + if (num_copies > 0 || !flush) { + int code = gdev_prn_open_printer(pdev, 1); + + if (code < 0) + return code; + + /* If copypage request, try to do it using buffer_page */ + if ( !flush && + (*ppdev->printer_procs.buffer_page) + (ppdev, ppdev->file, num_copies) >= 0 + ) { + upgraded_copypage = true; + flush = true; + } + else if (num_copies > 0) + /* Print the accumulated page description. */ + outcode = + (*ppdev->printer_procs.print_page_copies)(ppdev, ppdev->file, + num_copies); + if (ppdev->file) + { + fflush(ppdev->file); + errcode = + (ferror(ppdev->file) ? gs_note_error(gs_error_ioerror) : 0); + } + else + errcode = 0; + + if (!upgraded_copypage) + closecode = gdev_prn_close_printer(pdev); + } + endcode = (ppdev->buffer_space ? clist_finish_page(pdev, flush) : 0); + + if (outcode < 0) + return outcode; + if (errcode < 0) + return errcode; + if (closecode < 0) + return closecode; + if (endcode < 0) + return endcode; + return (upgraded_copypage ? 1 : 0); +} + +/* 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; +} + +/* + * Buffer a (partial) rasterized page & optionally print result multiple times. + * The default implementation returns error, since the driver needs to override + * this (in procedure vector) in configurations where this call may occur. + */ +int +gx_default_buffer_page(gx_device_printer *pdev, FILE *prn_stream, + int num_copies) +{ + return gs_error_unknownerror; +} + +/* ---------------- 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_positionable(gx_device *pdev, bool binary_mode, + bool positionable) +{ + gx_device_printer * const ppdev = (gx_device_printer *)pdev; + + if (ppdev->file != 0) { + ppdev->file_is_new = false; + return 0; + } + { + int code = gx_device_open_output_file(pdev, ppdev->fname, + binary_mode, positionable, + &ppdev->file); + if (code < 0) + return code; + } + ppdev->file_is_new = true; + return 0; +} +int +gdev_prn_open_printer(gx_device *pdev, bool binary_mode) +{ + return gdev_prn_open_printer_positionable(pdev, binary_mode, false); +} + +/* 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; +} + +/* Like get_bits, but accepts initial raster contents */ +int +gdev_prn_get_overlay_bits(gx_device_printer *pdev, int y, int lineCount, + byte *data) +{ + if (pdev->buffer_space) { + /* Command lists have built-in support for this function */ + return clist_get_overlay_bits(pdev, y, lineCount, data); + } else { + /* Memory devices cannot support this function. */ + return_error(gs_error_unknownerror); + } +} + +/* Find out where the band buffer for a given line is going to fall on the */ +/* next call to get_bits. */ +int /* rets # lines from y till end of buffer, or -ve error code */ +gdev_prn_locate_overlay_buffer(gx_device_printer *pdev, int y, byte **data) +{ + gx_device_printer * const ppdev = (gx_device_printer *)pdev; + + if (ppdev->buffer_space) { + /* Command lists have built-in support for this function */ + return clist_locate_overlay_buffer(pdev, y, data); + } else { + /* Memory devices cannot support this function. */ + return_error(gs_error_unknownerror); + } +} + +/* Close the current page. */ +int +gdev_prn_close_printer(gx_device * pdev) +{ + gx_device_printer * const ppdev = (gx_device_printer *)pdev; + + if (strchr(ppdev->fname, '%') /* file per page */ || + ppdev->ReopenPerPage /* close and reopen for each page */ + ) { + gp_close_printer(ppdev->file, ppdev->fname); + ppdev->file = NULL; + } + return 0; +} + +/* If necessary, free and reallocate the printer memory after changing params */ +int +gdev_prn_maybe_reallocate_memory(gx_device_printer *prdev, + gdev_prn_space_params *old_sp, + int old_width, int old_height) +{ + int code = 0; + gx_device *const pdev = (gx_device *)prdev; + gx_device_memory * const mdev = (gx_device_memory *)prdev; + + /* The first test here used to be prdev->open. See News for 5.50. */ + if (mdev->base != 0 && + (memcmp(&prdev->space_params, old_sp, sizeof(*old_sp)) != 0 || + prdev->width != old_width || prdev->height != old_height ) + ) { + int new_width = prdev->width; + int new_height = prdev->height; + gdev_prn_space_params new_sp = prdev->space_params; + + prdev->width = old_width; + prdev->height = old_height; + prdev->space_params = *old_sp; + code = gdev_prn_reallocate_memory(pdev, &new_sp, + new_width, new_height); + /* If this fails, device should be usable w/old params, but */ + /* band files may not be open. */ + } + return code; +} diff --git a/pstoraster/gdevprn.h b/pstoraster/gdevprn.h new file mode 100644 index 0000000000..68c09d6b5e --- /dev/null +++ b/pstoraster/gdevprn.h @@ -0,0 +1,560 @@ +/* Copyright (C) 1989, 1995, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Common header file for memory-buffered printers */ + +#ifndef gdevprn_INCLUDED +# define gdevprn_INCLUDED + +#include "memory_.h" +#include "string_.h" +#include "gx.h" +#include "gp.h" /* for gp_file_name_sizeof */ +#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 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. */ +#ifndef gx_device_printer_DEFINED +# define gx_device_printer_DEFINED +typedef struct gx_device_printer_s gx_device_printer; +#endif + +/* Define the abstract type for some band device procedures' arguments. */ +typedef struct gdev_prn_start_render_params_s gdev_prn_start_render_params; + +/* Define the abstract type for a page queue for async rendering. */ +#ifndef gx_page_queue_DEFINED +# define gx_page_queue_DEFINED +typedef struct gx_page_queue_s gx_page_queue; +#endif + +/* Define the abstract type for parameters describing buffer space. */ +#ifndef gdev_prn_space_params_DEFINED +# define gdev_prn_space_params_DEFINED +typedef struct gdev_prn_space_params_s gdev_prn_space_params; +#endif + +/* + * 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 prn_dev_proc_print_page(proc)\ + int proc(P2(gx_device_printer *, FILE *)) + prn_dev_proc_print_page((*print_page)); +/* BACKWARD COMPATIBILITY */ +#define dev_proc_print_page(proc) prn_dev_proc_print_page(proc) + + /* Print the page on the output file, with a given # of copies. */ + +#define prn_dev_proc_print_page_copies(proc)\ + int proc(P3(gx_device_printer *, FILE *, int)) + prn_dev_proc_print_page_copies((*print_page_copies)); +/* BACKWARD COMPATIBILITY */ +#define dev_proc_print_page_copies(proc) prn_dev_proc_print_page_copies(proc) + + /* Initialize the memory device for a page or a band. */ + /* (The macro definition is in gxdevcli.h.) */ + + dev_proc_make_buffer_device((*make_buffer_device)); + + /* + * Compute effective space params. These results effectively override + * the space_params in the device, but does not replace them; that is to + * say that computed space params are temps used for computation. + * Procedure must fill in only those space_params that it wishes to + * override, using curr width, height, margins, etc. + * + * Caller is gdevprn.open & gdevprn.put_params, calls driver or + * default. + */ + +#define prn_dev_proc_get_space_params(proc)\ + void proc(P2(const gx_device_printer *, gdev_prn_space_params *)) + prn_dev_proc_get_space_params((*get_space_params)); + + /* + * Only for gx_device_printer devices that overlap interpreting and + * rasterizing. Since there are 2 instances of the device (1 for writing + * the cmd list & 1 for rasterizing it), and each device is associated + * with an different thread, this function is called to start the + * rasterizer's thread. Once started, the rasterizer thread must call + * down to gdev_prn_asnyc_render_thread, which will only return after + * device closes. + * + * Caller is gdevprna.open, calls driver implementation or default. + */ + +#define prn_dev_proc_start_render_thread(proc)\ + int proc(P1(gdev_prn_start_render_params *)) + prn_dev_proc_start_render_thread((*start_render_thread)); + + /* + * Only for gx_device_printer devices that overlap interpreting and + * rasterizing. Since there are 2 instances of the device (1 for writing + * the cmd list & 1 for rasterizing it), these fns are called to + * open/close the rasterizer's instance, once the writer's instance has + * been created & init'd. These procs must cascade down to + * gdev_prn_async_render_open/close. + * + * Caller is gdevprna, calls driver implementation or default. + */ + +#define prn_dev_proc_open_render_device(proc)\ + int proc(P1(gx_device_printer *)) + prn_dev_proc_open_render_device((*open_render_device)); + +#define prn_dev_proc_close_render_device(proc)\ + int proc(P1(gx_device_printer *)) + prn_dev_proc_close_render_device((*close_render_device)); + + /* + * Buffer a page on the output device. A page may or may not have been + * fully rendered, but the rasterizer needs to realize the page to free + * up resources or support copypage. Printing a page may involve zero or + * more buffer_pages. All buffer_page output is overlaid in the buffer + * until a terminating print_page or print_page_copies clears the + * buffer. Note that, after the first buffer_page, the driver must use + * the get_overlay_bits function instead of get_bits. The difference is + * that get_overlay_bits requires the caller to supply the same buffered + * bitmap that was computed as a result of a previous buffer_page, so + * that get_overlay_bits can add further marks to the existing buffered + * image. NB that output must be accumulated in buffer even if + * num_copies == 0. + * + * Caller is expected to be gdevprn, calls driver implementation or + * default. + */ + +#define prn_dev_proc_buffer_page(proc)\ + int proc(P3(gx_device_printer *, FILE *, int)) + prn_dev_proc_buffer_page((*buffer_page)); + + /* + * Transform a given set of bits by marking it per the current page + * description. This is a different version of get_bits, where this + * procedure accepts a bitmap and merely adds further marks, without + * clearing the bits. + * + * Driver implementation is expected to be the caller. + */ + +#define prn_dev_proc_get_overlay_bits(proc)\ + int proc(P4(gx_device_printer *, int, int, byte *)) + prn_dev_proc_get_overlay_bits((*get_overlay_bits)); + + /* + * Find out where the band buffer for a given line is going to fall on + * the next call to get_bits. This is an alternative to get_overlay_bits + * in cases where the client doesn't own a suitably formatted buffer to + * deposit bits into. When using this function, do a + * locate_overlay_buffer, copy the background data into the returned + * buffer, then do get_bits to get the transformed data. IMPORTANT: the + * locate_overlay_buffer for a specific range of lines must immediately + * be followed by one or more get_bits for the same line range with no + * other intervening driver calls. If this condition is violated, + * results are undefined. + */ + +#define prn_dev_proc_locate_overlay_buffer(proc)\ + int proc(P3(gx_device_printer *, int, byte **)) + prn_dev_proc_locate_overlay_buffer((*locate_overlay_buffer)); + +} 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 gp_file_name_sizeof +typedef enum { + BandingAuto = 0, + BandingAlways, + BandingNever +} gdev_prn_banding_type; +struct gdev_prn_space_params_s { + long MaxBitmap; /* max size of non-buffered bitmap */ + long BufferSpace; /* space to use for buffer */ + gx_band_params band; /* see gxclist.h */ + bool params_are_read_only; /* true if put_params may not modify this struct */ + gdev_prn_banding_type banding_type; /* used to force banding or bitmap */ +}; + +#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;\ + /* ------ Device parameters that must be set ------ */\ + /* ------ before calling the device open routine. ------ */\ + gdev_prn_space_params space_params;\ + char fname[prn_fname_sizeof]; /* OutputFile */\ + /* ------ Other device parameters ------ */\ + bool OpenOutputFile;\ + bool ReopenPerPage;\ + bool Duplex;\ + int Duplex_set; /* -1 = not supported */\ + /* ------ End of parameters ------ */\ + bool file_is_new; /* true iff file just opened */\ + FILE *file; /* output file */\ + long buffer_space; /* amount of space for clist buffer, */\ + /* 0 means not using clist */\ + byte *buf; /* buffer for rendering */\ + /* ---- Begin async rendering support --- */\ + gs_memory_t *buffer_memory; /* allocator for command list */\ + gs_memory_t *bandlist_memory; /* allocator for bandlist files */\ + proc_free_up_bandlist_memory((*free_up_bandlist_memory)); /* if nz, proc to free some bandlist memory */\ + gx_page_queue *page_queue; /* if <> 0,page queue for gdevprna NOT GC'd */\ + bool is_async_renderer; /* device is only the rendering part of async device */\ + gx_device_printer *async_renderer; /* in async writer, pointer to async renderer */\ + uint clist_disable_mask; /* mask of clist options to disable */\ + /* ---- End async rendering support --- */\ + gx_device_procs orig_procs /* original (std_)procs */ + +/* The device descriptor */ +struct gx_device_printer_s { + gx_device_common; + gx_prn_device_common; +}; + +/* 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); + +/* Default printer-specific procedures */ +prn_dev_proc_get_space_params(gdev_prn_default_get_space_params); +prn_dev_proc_start_render_thread(gx_default_start_render_thread); /* for async rendering only, see gdevprna.c */ +prn_dev_proc_open_render_device(gx_default_open_render_device); +prn_dev_proc_close_render_device(gx_default_close_render_device); +prn_dev_proc_buffer_page(gx_default_buffer_page); /* returns an error */ +prn_dev_proc_get_overlay_bits(gdev_prn_get_overlay_bits); +prn_dev_proc_locate_overlay_buffer(gdev_prn_locate_overlay_buffer); + +/* 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, */\ + NULL, /* get_clipping_box */\ + NULL, /* begin_typed_image */\ + NULL, /* map_color_rgb_alpha */\ + NULL, /* create_compositor */\ + NULL, /* get_hardware_params */\ + NULL /* text_begin */\ +} + +/* The standard printer device procedures */ +/* (using gdev_prn_open/output_page/close). */ +extern const 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,\ + gdev_prn_default_get_space_params,\ + gx_default_start_render_thread,\ + gx_default_open_render_device,\ + gx_default_close_render_device,\ + gx_default_buffer_page,\ + gdev_prn_get_overlay_bits,\ + gdev_prn_locate_overlay_buffer\ + },\ + { PRN_MAX_BITMAP, PRN_BUFFER_SPACE,\ + { band_params_initial_values },\ + 0/*false*/, /* params_are_read_only */\ + BandingAuto /* banding_type */\ + },\ + { 0 }, /* fname */\ + 0/*false*/, /* OpenOutputFile */\ + 0/*false*/, /* ReopenPerPage */\ + 0/*false*/, -1, /* Duplex[_set] */\ + 0/*false*/, 0, 0, 0, /* file_is_new ... buf */\ + 0, 0, 0, 0, 0/*false*/, 0, 0, /* buffer_memory ... clist_dis'_mask */\ + { 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,\ + gdev_prn_default_get_space_params,\ + gx_default_start_render_thread,\ + gx_default_open_render_device,\ + gx_default_close_render_device,\ + gx_default_buffer_page,\ + gdev_prn_get_overlay_bits,\ + gdev_prn_locate_overlay_buffer\ + },\ + { PRN_MAX_BITMAP, PRN_BUFFER_SPACE,\ + { band_params_initial_values },\ + 0/*false*/, /* params_are_read_only */\ + BandingAuto /* banding_type */\ + },\ + { 0 }, /* fname */\ + 0/*false*/, /* OpenOutputFile */\ + 0/*false*/, /* ReopenPerPage */\ + 0/*false*/, -1, /* Duplex[_set] */\ + 0/*false*/, 0, 0, 0, /* file_is_new ... buf */\ + 0, 0, 0, 0, 0/*false*/, 0, 0, /* buffer_memory ... clist_dis'_mask */\ + { 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_positionable(P3(gx_device *dev, bool binary_mode, + bool positionable)); +/* open_printer defaults positionable = false */ +int gdev_prn_open_printer(P2(gx_device * dev, bool 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 *)); + +/* The default print_page_copies procedure just calls print_page */ +/* the given number of times. */ +prn_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 *)); + +/* Allocate / reallocate / free printer memory. */ +int gdev_prn_allocate_memory(P4(gx_device *pdev, + gdev_prn_space_params *space, + int new_width, int new_height)); +int gdev_prn_reallocate_memory(P4(gx_device *pdev, + gdev_prn_space_params *space, + int new_width, int new_height)); +int gdev_prn_free_memory(P1(gx_device *pdev)); + +/* 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 *, 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/gdevprna.h b/pstoraster/gdevprna.h new file mode 100644 index 0000000000..799a8dc12d --- /dev/null +++ b/pstoraster/gdevprna.h @@ -0,0 +1,190 @@ +/* Copyright (C) 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Generic asynchronous printer driver support */ + +/* Initial version 2/1/1998 by John Desrosiers (soho@crl.com) */ +/* 7/28/98 ghost@aladdin.com - Updated to Ghostscript coding standards. */ + +#ifndef gdevprna_INCLUDED +# define gdevprna_INCLUDED + +# include "gdevprn.h" +# include "gxsync.h" + +/* + * General + * ------- + * Async drivers actually create two separate instances of the device at + * the same time. The first (the writer instance) is only used in the + * interpretation operation; it feeds rendering commands into the command + * lists. The second device instance is used only for rendering the + * commands placed into the command list by the writer. + + * The writer builds a command list for an entire page; the command list + * is only queued for rendering once a page's command list is completely + * built. The only exception to this rule is when the interpreter runs + * out of memory, or when no free command list memory is available. In + * such cases, the interpreter queues a "partial page" consisting of all + * command list data written so far, plus a command indicating that the + * page description is not complete. After queuing the partial page, the + * interpereter waits until the rendering process has freed enough + * command list memory to enable the interpreter to proceed. + + * To avoid deadlocks when the system runs out of memory, special + * memory allocation provisions are made on both the writer and + * renderer sides. On the writer side, enough "reserve" bandlist + * memory is set aside at startup time to cover the needs of queuing a + * partial page to the renderer. The renderer operates out of a fixed + * memory space; that way, it can always complete rendering pages with + * the memory it has. To this end, the writer protects the renderer + * from consuming unbounded amounts of memory by a) never putting + * complex paths into the command list, b) pre-clipping any output + * unless the clip path consists of a single rectangle, c) never putting + * high-level images into the clip path unless the image in question + * meets some very stringent requirements, such as only being rotated by + * even multiples of 90 degrees and having source-image data rows which + * fit into the command buffer in one piece. These restrictions are what + * dictate the "restricted bandlist format." + + * Note that the renderer's instance of the device driver uses the + * renderer's memory. That implies that it must also operate in a small, + * fixed amount of memory, and must do all memory allocation using the + * memory allocator pointed to by the render device's ->memory member. + + * Opening the Device + * ------------------ + * The writer instance is opened first. This occurs when the system + * calls the "standard" open procedure via the device's procedure + * vector. The driver must implement the open function, but must call + * down to gdev_prn_async_write_open instead of calling down to + * gdev_prn_open. Before calling down to gdev_prn_async_write_open, the + * driver must: + * a - init several procedure vectors, to wit: start_render_thread, + * buffer_page, print_page_copies, + * b - init space_params.band.BandWidth, space_params.band.BandHeight, + * space_params.BufferSpace (see extended comments in gdevasyn.c + * for details on computing appropriate values). + * c - if it implements those functions, the driver must init the + * procedure vectors for: put_params, get_hardware_params, + * output_page, open_render_device. + * Notice that there are two procedure vectors: the usual std_procs, and + * the printer-specific printer_procs. + + * Since partial page support imposes extra requirements on drivers, + * such support can be disabled by zeroing out (in the async writer open + * routine, after calling down to gdev_prn_async_write_open) the + * free_up_bandlist_memory member of the driver structure. Doing so + * will, of course, cause interpretation to fail if memory runs out. + + * Once the driver calls down to gdev_prn_async_write_open, the async + * support logic will create a second instance of the driver for + * rendering, but will not open it just yet. Instead, the async logic + * will attempt to synchronize the two device instances. + + * Synchrnonizing the instances + * ---------------------------- + * While still in the gdev_prn_async_write_open routine, the async logic + * will call printer_procs.start_render_thread (which the driver is + * required to implement). start_render_thread must somehow either start a new + * thread or rendez-vous with an existing thread for use in rendering, + * then return. start_render_thread must also have caused the render thread + * to call gdev_prn_async_render_thread, passing it as an argument a magic + * cookie passed to start_render_thread. start_render_thread will only + * return once the device has been closed and all renering has been + * completed. + + * The render device will be opened on the render device's thread, by + * calling printer_procs.open_render_device. + + * Rendering Operation + * ------------------- + * During rendering, the device will not see rendering operations -- the + * first "rendering" operations the driver will see is when the renderer + * instance's print_page_copies or buffer_page routines get called. In + * both cases, the appropriate routine must then perform get_bits calls + * on the async logic in order to retrieve rendered bits, then transmit + * them to the appropriate device buffers. + + * The complication that is introduced is that which is related to + * partial pages: A buffer_page call instructs the driver to grab the + * rendered bits, but to keep the rendered bits available for later + * instead of marking on media. This implies that a buffer_page call + * opens a context where subsequent buffer_page's and print_page_copies' + * must first initialize the rendering buffers with the previous + * rendering results before calling get_bits. Drivers use the + * locate_overlay_buffer function to initialize the driver's rendering + * buffers. The first print_page_copies closes the context that was + * opened by the initial buffer_page -- the driver must go back to + * normal rendering until a new buffer_page comes along. + */ + +/* -------------- Type declarations --------------- */ + +/* typedef is in gdevprn.h */ +/* typedef struct gdev_prn_start_render_params_s gdev_prn_start_render_params;*/ +struct gdev_prn_start_render_params_s { + gx_device_printer *writer_device;/* writer dev that points to render dev */ + gx_semaphore_t *open_semaphore; /* signal this once open_code is set */ + int open_code; /* RETURNS status of open of reader device */ +}; + +/* -------- Macros used to initialize render-specific structures ------ */ + +#define init_async_render_procs(xpdev, xstart_render_thread,\ + xbuffer_page, xprint_page_copies)\ + BEGIN\ + (xpdev)->printer_procs.start_render_thread = (xstart_render_thread);\ + (xpdev)->printer_procs.buffer_page = (xbuffer_page);\ + (xpdev)->printer_procs.print_page_copies = (xprint_page_copies);\ + END + +/* -------------- Global procedure declarations --------- */ + +/* Open this printer device in ASYNC (overlapped) mode. + * + * This routine is always called by the concrete device's xx_open routine + * in lieu of gdev_prn_open. + */ +int gdev_prn_async_write_open(P4(gx_device_printer *pdev, int max_raster, + int min_band_height, int max_src_image_row)); + +/* Open the render portion of a printer device in ASYNC (overlapped) mode. + * + * This routine is always called by concrete device's xx_open_render_device + * in lieu of gdev_prn_open. + */ +int gdev_prn_async_render_open(P1(gx_device_printer *prdev)); + +/* + * Must be called by async device driver implementation (see + * gdevprna.h under "Synchronizing the Instances"). This is the + * rendering loop, which requires its own thread for as long as + * the device is open. This proc only returns after the device is closed. + */ +int /* rets 0 ok, -ve error code */ +gdev_prn_async_render_thread(P1(gdev_prn_start_render_params *)); + +#endif /* gdevprna_INCLUDED */ diff --git a/pstoraster/gdevps.c b/pstoraster/gdevps.c new file mode 100644 index 0000000000..dfb4d28486 --- /dev/null +++ b/pstoraster/gdevps.c @@ -0,0 +1,1151 @@ +/* Copyright (C) 1997, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* PostScript-writing driver */ +#include "math_.h" +#include "memory_.h" +#include "time_.h" +#include "gx.h" +#include "gserrors.h" +#include "gscdefs.h" +#include "gsmatrix.h" /* for gsiparam.h */ +#include "gsiparam.h" +#include "gsline.h" +#include "gsparam.h" +#include "gxdevice.h" +#include "gscspace.h" +#include "gxdcolor.h" +#include "gzpath.h" +#include "gdevpsdf.h" +#include "gdevpstr.h" +#include "strimpl.h" +#include "sa85x.h" + +/**************************************************************** + * Notes: + * ASCII85EncodePages should use ASCIIHexEncode if LanguageLevel < 2. + * Images are never compressed; in fact, none of the other + * Distiller parameters do anything. + ****************************************************************/ + +/* ---------------- Device definition ---------------- */ + +/* Device procedures */ +private dev_proc_open_device(psw_open); +private dev_proc_output_page(psw_output_page); +private dev_proc_close_device(psw_close); +private dev_proc_copy_mono(psw_copy_mono); +private dev_proc_copy_color(psw_copy_color); +private dev_proc_put_params(psw_put_params); +private dev_proc_get_params(psw_get_params); +private dev_proc_fill_path(psw_fill_path); +private dev_proc_stroke_path(psw_stroke_path); +private dev_proc_fill_mask(psw_fill_mask); +private dev_proc_begin_image(psw_begin_image); + +#define X_DPI 720 +#define Y_DPI 720 + +typedef struct psw_path_state_s { + int num_points; /* # of points since last non-lineto */ + bool move; /* true iff last non-lineto was moveto */ + gs_point dprev[2]; /* line deltas before previous point, */ + /* if num_points - move >= 2 */ +} psw_path_state_t; + +typedef struct psw_image_params_s { + gx_bitmap_id id; + ushort width, height; +} psw_image_params_t; + +typedef struct gx_device_pswrite_s { + gx_device_psdf_common; + /* Settable parameters */ +#define LanguageLevel_default 2.0 +#define psdf_version_default psdf_version_level2 + float LanguageLevel; + /* End of parameters */ + bool ProduceEPS; + bool first_page; + long bbox_position; + psdf_binary_writer image_writer; +#define image_stream image_writer.strm +#define image_cache_size 197 +#define image_cache_reprobe_step 121 + psw_image_params_t image_cache[image_cache_size]; + bool cache_toggle; + /* Temporary state while writing a path */ + psw_path_state_t path_state; +} gx_device_pswrite; + +gs_private_st_suffix_add1_final(st_device_pswrite, gx_device_pswrite, + "gx_device_pswrite", device_pswrite_enum_ptrs, device_pswrite_reloc_ptrs, + gx_device_finalize, st_device_psdf, image_stream); + +#define psw_procs\ + { psw_open,\ + gx_upright_get_initial_matrix,\ + NULL, /* sync_output */\ + psw_output_page,\ + psw_close,\ + gx_default_rgb_map_rgb_color,\ + gx_default_rgb_map_color_rgb,\ + gdev_vector_fill_rectangle,\ + NULL, /* tile_rectangle */\ + psw_copy_mono,\ + psw_copy_color,\ + NULL, /* draw_line */\ + NULL, /* get_bits */\ + psw_get_params,\ + psw_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 */\ + psw_fill_path,\ + psw_stroke_path,\ + psw_fill_mask,\ + gdev_vector_fill_trapezoid,\ + gdev_vector_fill_parallelogram,\ + gdev_vector_fill_triangle,\ + NULL /****** WRONG ******/, /* draw_thin_line */\ + psw_begin_image,\ + NULL, /* image_data */\ + NULL, /* end_image */\ + NULL, /* strip_tile_rectangle */\ + NULL/******psw_strip_copy_rop******/\ + } + +const gx_device_pswrite gs_pswrite_device = +{std_device_dci_type_body(gx_device_pswrite, 0, "pswrite", + &st_device_pswrite, + DEFAULT_WIDTH_10THS * X_DPI / 10, DEFAULT_HEIGHT_10THS * Y_DPI / 10, + X_DPI, Y_DPI, 3, 24, 255, 255, 256, 256), + psw_procs, + psdf_initial_values(psdf_version_default, 1 /*true */ ), /* (ASCII85EncodePages) */ + LanguageLevel_default, /* LanguageLevel */ + 0 /*false *//* ProduceEPS */ +}; + +const gx_device_pswrite gs_epswrite_device = +{std_device_dci_type_body(gx_device_pswrite, 0, "epswrite", + &st_device_pswrite, + DEFAULT_WIDTH_10THS * X_DPI / 10, DEFAULT_HEIGHT_10THS * Y_DPI / 10, + X_DPI, Y_DPI, 3, 24, 255, 255, 256, 256), + psw_procs, + psdf_initial_values(psdf_version_default, 1 /*true */ ), /* (ASCII85EncodePages) */ + LanguageLevel_default, /* LanguageLevel */ + 1 /*true *//* ProduceEPS */ +}; + +/* Vector device implementation */ +private int + psw_beginpage(P1(gx_device_vector * vdev)), psw_setlinewidth(P2(gx_device_vector * vdev, floatp width)), + psw_setcolors(P2(gx_device_vector * vdev, const gx_drawing_color * pdc)), + psw_dorect(P6(gx_device_vector * vdev, fixed x0, fixed y0, fixed x1, fixed y1, + gx_path_type_t type)), psw_beginpath(P2(gx_device_vector * vdev, gx_path_type_t type)), + psw_moveto(P6(gx_device_vector * vdev, floatp x0, floatp y0, + floatp x, floatp y, gx_path_type_t type)), psw_lineto(P6(gx_device_vector * vdev, floatp x0, floatp y0, + floatp x, floatp y, gx_path_type_t type)), + psw_curveto(P10(gx_device_vector * vdev, floatp x0, floatp y0, + floatp x1, floatp y1, floatp x2, floatp y2, + floatp x3, floatp y3, gx_path_type_t type)), psw_closepath(P6(gx_device_vector * vdev, floatp x0, floatp y0, + floatp x_start, floatp y_start, gx_path_type_t type)), + psw_endpath(P2(gx_device_vector * vdev, gx_path_type_t type)); +private const gx_device_vector_procs psw_vector_procs = +{ + /* Page management */ + psw_beginpage, + /* Imager state */ + psw_setlinewidth, + psdf_setlinecap, + psdf_setlinejoin, + psdf_setmiterlimit, + psdf_setdash, + psdf_setflat, + psdf_setlogop, + /* Other state */ + psw_setcolors, /* fill & stroke colors are the same */ + psw_setcolors, + /* Paths */ + psdf_dopath, + psw_dorect, + psw_beginpath, + psw_moveto, + psw_lineto, + psw_curveto, + psw_closepath, + psw_endpath +}; + +/* ---------------- File header ---------------- */ + +private const char *const psw_ps_header[] = +{ + "%!PS-Adobe-3.0", + "%%Pages: (atend)", + 0 +}; + +private const char *const psw_eps_header[] = +{ + "%!PS-Adobe-3.0 EPSF-3.0", + 0 +}; + +private const char *const psw_header[] = +{ + "%%EndComments", + "%%BeginProlog", + 0 +}; + +private const char *const psw_prolog[] = +{ + "%%BeginResource: procset GS_pswrite_ProcSet", + "/GS_pswrite_ProcSet 40 dict dup begin", + "/!{bind def}bind def/#{load def}!", + /* rG - */ + /* G - */ + "/rG{3{3 -1 roll 255 div}repeat setrgbcolor}!/G{255 div setgray}!/K{0 G}!", + /* r6 - */ + /* r5 - */ + /* r3 - */ + "/r6{dup 3 -1 roll rG}!/r5{dup 3 1 roll rG}!/r3{dup rG}!", + "/w/setlinewidth #/J/setlinecap #", + "/j/setlinejoin #/M/setmiterlimit #/d/setdash #/i/setflat #", + "/m/moveto #/l/lineto #/c/rcurveto #/h{p closepath}!/H{P closepath}!", + /* lx - */ + /* ly - */ + /* v - */ + /* y - */ + "/lx{0 rlineto}!/ly{0 exch rlineto}!/v{0 0 6 2 roll c}!/y{2 copy c}!", + /* re - */ + "/re{4 -2 roll m exch dup lx exch ly neg lx h}!", + /* ^ <-a> <-y> */ + "/^{3 index neg 3 index neg}!", + /* ... P - */ + "/P{count 0 gt{count -2 roll moveto p}if}!", + /* ... p - */ + "/p{count 2 idiv{count -2 roll rlineto}repeat}!", +"/f{P fill}!/f*{P eofill}!/S{P stroke}!/q/gsave #/Q/grestore #/rf{re fill}!", + "/Y{initclip P clip newpath}!/Y*{initclip P eoclip newpath}!/rY{re Y}!", + /* | */ + "/|{exch string readstring pop exch 4 1 roll 3 packedarray cvx exch 1 index def exec}!", + /* (|) + */ + "/+{dup type/nametype eq{2 index 7 add -3 bitshift 2 index mul}if}!", + /* (|) $ */ + "/@/currentfile #/${+ @ |}!", + /* Ix */ + "/Ix{[1 0 0 1 11 -2 roll exch neg exch neg]exch}!", + /* , - */ + /* If - */ + /* I - */ +"/,{true exch Ix imagemask}!/If{false exch Ix imagemask}!/I{exch Ix image}!", + 0 +}; + +private const char *const psw_1_prolog[] = +{ + 0 +}; + +private const char *const psw_1_5_prolog[] = +{ + "/Ic{exch Ix false 3 colorimage}!", + 0 +}; + +private const char *const psw_2_prolog[] = +{ + /* F */ + "/F{<>/CCITTFaxDecode filter}!", + /* X */ + /* - @X */ + /* +F */ + /* +F */ + /* @F */ + /* @C */ + "/X{/ASCII85Decode filter}!/@X{@ X}!/+F{2 index 2 index F}!/@F{@ +F}!/@C{@X +F}!", + /* (|) $X */ + /* -F */ + /* (|) $F */ + /* (|) $C */ + "/$X{+ @X |}!/-F{4 index 4 index F}!/$F{+ @ -F |}!/$C{+ @X -F |}!", + 0 +}; + +private const char *const psw_end_prolog[] = +{ + "end def", + "%%EndResource", + "%%EndProlog", + 0 +}; + +private void +psw_put_lines(stream * s, const char *const lines[]) +{ + int i; + + for (i = 0; lines[i] != 0; ++i) + pprints1(s, "%s\n", lines[i]); +} + +/* ---------------- Utilities ---------------- */ + +/* Reset the image cache. */ +private void +image_cache_reset(gx_device_pswrite * pdev) +{ + int i; + + for (i = 0; i < image_cache_size; ++i) + pdev->image_cache[i].id = gx_no_bitmap_id; + pdev->cache_toggle = false; +} + +/* Look up or enter image parameters in the cache. */ +/* Return -1 if the key is not in the cache, or its index. */ +/* If id is gx_no_bitmap_id or enter is false, do not enter it. */ +private int +image_cache_lookup(gx_device_pswrite * pdev, gx_bitmap_id id, + int width, int height, bool enter) +{ + int i1, i2; + psw_image_params_t *pip1; + psw_image_params_t *pip2; + + if (id == gx_no_bitmap_id) + return -1; + i1 = id % image_cache_size; + pip1 = &pdev->image_cache[i1]; + if (pip1->id == id && pip1->width == width && pip1->height == height) { + return i1; + } + i2 = (i1 + image_cache_reprobe_step) % image_cache_size; + pip2 = &pdev->image_cache[i2]; + if (pip2->id == id && pip2->width == width && pip2->height == height) { + return i2; + } + if (enter) { + int i = ((pdev->cache_toggle = !pdev->cache_toggle) ? i2 : i1); + psw_image_params_t *pip = &pdev->image_cache[i]; + + pip->id = id, pip->width = width, pip->height = height; + return i; + } + return -1; +} + +/* Prepare the encoding stream for image data. */ +/* Return 1 if we are using ASCII85 encoding. */ +private int +psw_image_stream_setup(gx_device_pswrite * pdev) +{ + int code = + psdf_begin_binary((gx_device_psdf *) pdev, &pdev->image_writer); + + return + (code < 0 ? code : + pdev->image_stream->state->template == &s_A85E_template ? 1 : 0); +} + +/* Clean up after writing an image. */ +private void +psw_image_cleanup(gx_device_pswrite * pdev) +{ + if (pdev->image_stream != 0) { + psdf_end_binary(&pdev->image_writer); + pdev->image_stream = 0; + } +} + +/* Write data for an image. Assumes width > 0, height > 0. */ +/****** IGNORES data_x ******/ +private void +psw_put_bits(stream * s, const byte * data, int data_x_bit, uint raster, + uint width_bits, int height) +{ + int y; + + for (y = 0; y < height; ++y) + pwrite(s, data + (data_x_bit >> 3) + y * raster, + (width_bits + 7) >> 3); +} +private int +psw_image_write(gx_device_pswrite * pdev, const char *imagestr, + const byte * data, int data_x, uint raster, gx_bitmap_id id, + int x, int y, int width, int height, int depth) +{ + stream *s = gdev_vector_stream((gx_device_vector *) pdev); + uint width_bits = width * depth; + int data_x_bit = data_x * depth; + int index = image_cache_lookup(pdev, id, width_bits, height, false); + char str[40]; + int code, encode; + + if (index >= 0) { + sprintf(str, "%d%c", index / 26, index % 26 + 'A'); + pprintd2(s, "%d %d ", x, y); + pprints2(s, "%s %s\n", str, imagestr); + return 0; + } + pprintd4(s, "%d %d %d %d ", x, y, width, height); + encode = code = psw_image_stream_setup(pdev); + if (code < 0) + return code; + if (depth == 1 && width > 16) { + /* + * We should really look at the statistics of the image before + * committing to using G4 encoding.... + */ + code = psdf_CFE_binary(&pdev->image_writer, width, height, false); + if (code < 0) + return code; + encode += 2; + } + if (id == gx_no_bitmap_id || width_bits * (ulong) height > 8000) { + const char *const uncached[4] = + { + "@", "@X", "@F", "@C" + }; + + pprints2(s, "%s %s\n", uncached[encode], imagestr); + psw_put_bits(pdev->image_stream, data, data_x_bit, raster, + width_bits, height); + psw_image_cleanup(pdev); + spputc(s, '\n'); + } else { + const char *const cached[4] = + { + "$", "$X", "$F", "$C" + }; + + index = image_cache_lookup(pdev, id, width_bits, height, true); + sprintf(str, "/%d%c ", index / 26, index % 26 + 'A'); + pputs(s, str); + if (depth != 1) + pprintld1(s, "%ld ", ((width_bits + 7) >> 3) * (ulong) height); + pprints1(s, "%s\n", cached[encode]); + psw_put_bits(pdev->image_stream, data, data_x_bit, raster, + width_bits, height); + psw_image_cleanup(pdev); + pprints1(s, "\n%s\n", imagestr); + } + return 0; +} + +/* Print a matrix. */ +private void +psw_put_matrix(stream * s, const gs_matrix * pmat) +{ + pprintg6(s, "[%g %g %g %g %g %g]", + pmat->xx, pmat->xy, pmat->yx, pmat->yy, pmat->tx, pmat->ty); +} + +/* ---------------- Vector device implementation ---------------- */ + +#define pdev ((gx_device_pswrite *)vdev) + +private int +psw_beginpage(gx_device_vector * vdev) +{ + stream *s = vdev->strm; + long page = vdev->PageCount + 1; + + if (pdev->first_page) { + psw_put_lines(s, + (pdev->ProduceEPS ? psw_eps_header : psw_ps_header)); + if (ftell(vdev->file) < 0) { /* File is not seekable. */ + pdev->bbox_position = -1; + pputs(s, "%%BoundingBox: (atend)\n"); + pputs(s, "%%HiResBoundingBox: (atend)\n"); + } else { /* File is seekable, leave room to rewrite bbox. */ + pdev->bbox_position = stell(s); + pputs(s, "%...............................................................\n"); + pputs(s, "%...............................................................\n"); + } + pprints1(s, "%%%%Creator: %s ", gs_product); + pprintld1(s, "%ld ", (long)gs_revision); + pprints1(s, "(%s)\n", vdev->dname); + { + struct tm tms; + time_t t; + char date_str[25]; + + time(&t); + tms = *localtime(&t); + sprintf(date_str, "%d/%02d/%02d %02d:%02d:%02d", + tms.tm_year + 1900, tms.tm_mon + 1, tms.tm_mday, + tms.tm_hour, tms.tm_min, tms.tm_sec); + pprints1(s, "%%%%CreationDate: %s\n", date_str); + } + if (pdev->params.ASCII85EncodePages) + pputs(s, "%%DocumentData: Clean7Bit\n"); + if (pdev->LanguageLevel == 2.0) + pputs(s, "%%LanguageLevel: 2\n"); + else if (pdev->LanguageLevel == 1.5) + pputs(s, "%%Extensions: CMYK\n"); + psw_put_lines(s, psw_header); + psw_put_lines(s, psw_prolog); + if (pdev->LanguageLevel < 1.5) + psw_put_lines(s, psw_1_prolog); + else { + psw_put_lines(s, psw_1_5_prolog); + if (pdev->LanguageLevel > 1.5) + psw_put_lines(s, psw_2_prolog); + } + psw_put_lines(s, psw_end_prolog); + } + pprintld2(s, "%%%%Page: %ld %ld\n%%%%BeginPageSetup\n", page, page); + pputs(s, "/pagesave save def GS_pswrite_ProcSet begin\n"); + if (!pdev->ProduceEPS) { + int width = (int)(vdev->width * 72.0 / vdev->HWResolution[0] + 0.5); + int height = (int)(vdev->height * 72.0 / vdev->HWResolution[1] + 0.5); + + if (pdev->LanguageLevel > 1.5) + pprintd2(s, "<< /PageSize [%d %d] >> setpagedevice\n", + width, height); + else { + typedef struct ps_ { + const char *size_name; + int width, height; + } page_size; + static const page_size sizes[] = { + {"/11x17", 792, 1224}, + {"/a3", 842, 1190}, + {"/a4", 595, 842}, + {"/b5", 501, 709}, + {"/ledger", 1224, 792}, + {"/legal", 612, 1008}, + {"/letter", 612, 792}, + {"null", 0, 0} + }; + const page_size *p = sizes; + + while (p->size_name[0] == '/' && + (p->width != width || p->height != height)) + ++p; + pprintd2(s, "%d %d ", width, height); + pprints1(s, "%s PS\n", p->size_name); + } + } + pprintg2(s, "%g %g scale\n%%%%EndPageSetup\n", + 72.0 / vdev->HWResolution[0], 72.0 / vdev->HWResolution[1]); + return 0; +} + +private int +psw_setlinewidth(gx_device_vector * vdev, floatp width) +{ /* + * The vector scale is 1, but we have to rescale the line width + * (which is given in device pixels) to account for the actual + * page scaling in effect. + */ + return psdf_setlinewidth(vdev, width * 72.0 / vdev->HWResolution[1]); +} + +private int +psw_setcolors(gx_device_vector * vdev, const gx_drawing_color * pdc) +{ + if (!gx_dc_is_pure(pdc)) + return_error(gs_error_rangecheck); + /* PostScript only keeps track of a single color. */ + vdev->fill_color = *pdc; + vdev->stroke_color = *pdc; + { + stream *s = gdev_vector_stream(vdev); + gx_color_index color = gx_dc_pure_color(pdc); + int r = color >> 16; + int g = (color >> 8) & 0xff; + int b = color & 0xff; + + if (r == g && g == b) { + if (r == 0) + pputs(s, "K\n"); + else + pprintd1(s, "%d G\n", r); + } else if (r == g) + pprintd2(s, "%d %d r6\n", b, r); + else if (g == b) + pprintd2(s, "%d %d r3\n", r, g); + else if (r == b) + pprintd2(s, "%d %d r5\n", g, b); + else + pprintd3(s, "%d %d %d rG\n", r, g, b); + } + return 0; +} + +/* Redefine dorect to recognize rectangle fills. */ +private int +psw_dorect(gx_device_vector * vdev, fixed x0, fixed y0, fixed x1, fixed y1, + gx_path_type_t type) +{ + if ((type & ~gx_path_type_rule) != gx_path_type_fill) + return psdf_dorect(vdev, x0, y0, x1, y1, type); + pprintg4(gdev_vector_stream(vdev), "%g %g %g %g rf\n", + fixed2float(x0), fixed2float(y0), + fixed2float(x1 - x0), fixed2float(y1 - y0)); + return 0; +} + +/* + * We redefine path tracing to use a compact form for polygons; also, + * we only need to write coordinates with 2 decimals of precision, + * since this is 10 times more precise than any existing output device. + */ +#define round_coord(v) (floor((v) * 100 + 0.5) / 100.0) +private void +print_coord2(stream * s, floatp x, floatp y, const char *str) +{ + pprintg2(s, "%g %g ", round_coord(x), round_coord(y)); + if (str != 0) + pputs(s, str); +} +#undef round_coord + +private int +psw_beginpath(gx_device_vector * vdev, gx_path_type_t type) +{ + pdev->path_state.num_points = 0; + pdev->path_state.move = false; + return 0; +} + +private int +psw_moveto(gx_device_vector * vdev, floatp x0, floatp y0, floatp x, floatp y, + gx_path_type_t type) +{ + stream *s = gdev_vector_stream(vdev); + + if (pdev->path_state.num_points > pdev->path_state.move) + pputs(s, (pdev->path_state.move ? "P\n" : "p\n")); + print_coord2(s, x, y, NULL); + pdev->path_state.num_points = 1; + pdev->path_state.move = true; + return 0; +} + +private int +psw_lineto(gx_device_vector * vdev, floatp x0, floatp y0, floatp x, floatp y, + gx_path_type_t type) +{ + double dx = x - x0, dy = y - y0; + + /* + * Omit null lines when filling. + ****** MAYBE WRONG IF PATH CONSISTS ONLY OF NULL LINES. ****** + */ + if (dx != 0 || dy != 0) { + stream *s = gdev_vector_stream(vdev); + + if (pdev->path_state.num_points - pdev->path_state.move >= 2 && + dx == -pdev->path_state.dprev[1].x && + dy == -pdev->path_state.dprev[1].y + ) + pputs(s, "^ "); + else + print_coord2(s, dx, dy, NULL); + pdev->path_state.num_points++; + pdev->path_state.dprev[1] = pdev->path_state.dprev[0]; + pdev->path_state.dprev[0].x = dx; + pdev->path_state.dprev[0].y = dy; + } + return 0; +} + +private int +psw_curveto(gx_device_vector * vdev, floatp x0, floatp y0, + floatp x1, floatp y1, floatp x2, floatp y2, floatp x3, floatp y3, + gx_path_type_t type) +{ + stream *s = gdev_vector_stream(vdev); + double dx1 = x1 - x0, dy1 = y1 - y0; + double dx2 = x2 - x0, dy2 = y2 - y0; + double dx3 = x3 - x0, dy3 = y3 - y0; + + if (pdev->path_state.num_points > 0) + pputs(s, (pdev->path_state.move ? + (pdev->path_state.num_points == 1 ? "m\n" : "P\n") : + "p\n")); + if (dx1 == 0 && dy1 == 0) { + print_coord2(s, dx2, dy2, NULL); + print_coord2(s, dx3, dy3, "v\n"); + } else if (x3 == x2 && y3 == y2) { + print_coord2(s, dx1, dy1, NULL); + print_coord2(s, dx2, dy2, "y\n"); + } else { + print_coord2(s, dx1, dy1, NULL); + print_coord2(s, dx2, dy2, NULL); + print_coord2(s, dx3, dy3, "c\n"); + } + pdev->path_state.num_points = 0; + pdev->path_state.move = false; + return 0; +} + +private int +psw_closepath(gx_device_vector * vdev, floatp x0, floatp y0, + floatp x_start, floatp y_start, gx_path_type_t type) +{ + pputs(gdev_vector_stream(vdev), + (pdev->path_state.num_points > 0 && pdev->path_state.move ? + "H\n" : "h\n")); + pdev->path_state.num_points = 0; + pdev->path_state.move = false; + return 0; +} + +private int +psw_endpath(gx_device_vector * vdev, gx_path_type_t type) +{ + stream *s = vdev->strm; + const char *star = (type & gx_path_type_even_odd ? "*" : ""); + + if (pdev->path_state.num_points > 0 && !pdev->path_state.move) + pputs(s, "p "); + if (type & gx_path_type_fill) { + if (type & (gx_path_type_stroke | gx_path_type_clip)) + pprints1(s, "q f%s Q ", star); + else + pprints1(s, "f%s\n", star); + } + if (type & gx_path_type_stroke) { + if (type & gx_path_type_clip) + pputs(s, "q S Q "); + else + pputs(s, "S\n"); + } + if (type & gx_path_type_clip) + pprints1(s, "Y%s\n", star); + return 0; +} + +#undef pdev + +/* ---------------- Driver procedures ---------------- */ + +#define vdev ((gx_device_vector *)dev) +#define pdev ((gx_device_pswrite *)dev) + +/* ------ Open/close/page ------ */ + +/* Open the device. */ +private int +psw_open(gx_device * dev) +{ + vdev->v_memory = dev->memory; +/****** WRONG ******/ + vdev->vec_procs = &psw_vector_procs; + { + int code = gdev_vector_open_file_bbox(vdev, 512, true); + + if (code < 0) + return code; + } + gdev_vector_init(vdev); + pdev->first_page = true; + pdev->binary_ok = !pdev->params.ASCII85EncodePages; + image_cache_reset(pdev); + return 0; +} + +/* Wrap up ("output") a page. */ +private int +psw_output_page(gx_device * dev, int num_copies, int flush) +{ + stream *s = gdev_vector_stream(vdev); + + if (num_copies != 1) + pprintd1(s, "userdict /#copies %d put\n", num_copies); + pprints1(s, "end %s pagesave restore\n%%%%PageTrailer\n", + (flush ? "showpage" : "copypage")); + sflush(s); + vdev->in_page = false; + pdev->first_page = false; + gdev_vector_reset(vdev); + image_cache_reset(pdev); + return 0; +} + +/* Close the device. */ +/* Note that if this is being called as a result of finalization, */ +/* the stream may no longer exist; but the file will still be open. */ +private int +psw_close(gx_device * dev) +{ + FILE *f = vdev->file; + + fprintf(f, "%%%%Trailer\n%%%%Pages: %ld\n", dev->PageCount); + { + gs_rect bbox; + long save_pos; + + gx_device_bbox_bbox(vdev->bbox_device, &bbox); + if (pdev->bbox_position >= 0) { + save_pos = ftell(f); + fseek(f, pdev->bbox_position, SEEK_SET); + } + fprintf(f, "%%%%BoundingBox: %d %d %d %d\n", + (int)floor(bbox.p.x), (int)floor(bbox.p.y), + (int)ceil(bbox.q.x), (int)ceil(bbox.q.y)); + fprintf(f, "%%%%HiResBoundingBox: %f %f %f %f\n", + bbox.p.x, bbox.p.y, bbox.q.x, bbox.q.y); + if (pdev->bbox_position >= 0) { + fputc('%', f); + fseek(f, save_pos, SEEK_SET); + } + } + if (!pdev->ProduceEPS) + fputs("%%EOF\n", f); + gdev_vector_close_file(vdev); + return 0; +} + +/* ---------------- Get/put parameters ---------------- */ + +/* Get parameters. */ +private int +psw_get_params(gx_device * dev, gs_param_list * plist) +{ + int code = gdev_psdf_get_params(dev, plist); + int ecode; + + if (code < 0) + return code; + if ((ecode = param_write_float(plist, "LanguageLevel", &pdev->LanguageLevel)) < 0) + return ecode; + return code; +} + +/* Put parameters. */ +private int +psw_put_params(gx_device * dev, gs_param_list * plist) +{ + int ecode = 0; + int code; + gs_param_name param_name; + float ll = pdev->LanguageLevel; + psdf_version save_version = pdev->version; + + switch (code = param_read_float(plist, (param_name = "LanguageLevel"), &ll)) { + case 0: + if (ll == 1.0 || ll == 1.5 || ll == 2.0) + break; + code = gs_error_rangecheck; + default: + ecode = code; + param_signal_error(plist, param_name, ecode); + case 1: + ; + } + + if (ecode < 0) + return ecode; + /* + * We have to set version to the new value, because the set of + * legal parameter values for psdf_put_params varies according to + * the version. + */ + { + static const psdf_version vv[3] = + { + psdf_version_level1, psdf_version_level1_color, + psdf_version_level2 + }; + + pdev->version = vv[(int)(ll * 2) - 2]; + } + code = gdev_psdf_put_params(dev, plist); + if (code < 0) { + pdev->version = save_version; + return code; + } + pdev->LanguageLevel = ll; + return code; +} + +/* ---------------- Images ---------------- */ + +/* Copy a monochrome bitmap. */ +private int +psw_copy_mono(gx_device * dev, const byte * data, + int data_x, int raster, gx_bitmap_id id, int x, int y, int w, int h, + gx_color_index zero, gx_color_index one) +{ + gx_drawing_color color; + const char *op; + int code = 0; + + if (w <= 0 || h <= 0) + return 0; + (*dev_proc(vdev->bbox_device, copy_mono)) + ((gx_device *) vdev->bbox_device, data, data_x, raster, id, + x, y, w, h, zero, one); + if (one == gx_no_color_index) { + color_set_pure(&color, zero); + code = gdev_vector_update_fill_color((gx_device_vector *) pdev, + &color); + op = "If"; + } else if (zero == vdev->black && one == vdev->white) + op = "1 I"; + else { + if (zero != gx_no_color_index) { + code = (*dev_proc(dev, fill_rectangle)) (dev, x, y, w, h, zero); + if (code < 0) + return code; + } + color_set_pure(&color, one); + code = gdev_vector_update_fill_color((gx_device_vector *) pdev, + &color); + op = ","; + } + if (code < 0) + return 0; + return psw_image_write(pdev, op, data, data_x, raster, id, + x, y, w, h, 1); +} + +/* Copy a color bitmap. */ +private int +psw_copy_color(gx_device * dev, + const byte * data, int data_x, int raster, gx_bitmap_id id, + int x, int y, int w, int h) +{ + int depth = dev->color_info.depth; + const byte *bits = data + data_x * 3; + char op[6]; + + if (w <= 0 || h <= 0) + return 0; + (*dev_proc(vdev->bbox_device, copy_color)) + ((gx_device *) vdev->bbox_device, data, data_x, raster, id, + x, y, w, h); + /* + * If this is a 1-pixel-high image, check for it being all the + * same color, and if so, fill it as a rectangle. + */ + if (h == 1 && !memcmp(bits, bits + 3, (w - 1) * 3)) { + return (*dev_proc(dev, fill_rectangle)) + (dev, x, y, w, h, (bits[0] << 16) + (bits[1] << 8) + bits[2]); + } + sprintf(op, "%d Ic", depth / 3); /* RGB */ + return psw_image_write(pdev, op, data, data_x, raster, id, + x, y, w, h, depth); +} + +/* Fill or stroke a path. */ +/* We redefine these to skip empty paths. */ +private int +psw_fill_path(gx_device * dev, const gs_imager_state * pis, + gx_path * ppath, const gx_fill_params * params, + const gx_device_color * pdevc, const gx_clip_path * pcpath) +{ + if (gx_path_is_void(ppath)) + return 0; + return gdev_vector_fill_path(dev, pis, ppath, params, pdevc, pcpath); +} +private int +psw_stroke_path(gx_device * dev, const gs_imager_state * pis, + gx_path * ppath, const gx_stroke_params * params, + const gx_device_color * pdevc, const gx_clip_path * pcpath) +{ + if (gx_path_is_void(ppath) && + (gx_path_is_null(ppath) || + gs_currentlinecap((const gs_state *)pis) != gs_cap_round) + ) + return 0; + return gdev_vector_stroke_path(dev, pis, ppath, params, pdevc, pcpath); +} + +/* Fill a mask. */ +private int +psw_fill_mask(gx_device * dev, + const byte * data, int data_x, 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) +{ + if (w <= 0 || h <= 0) + return 0; + if (depth > 1 || + gdev_vector_update_fill_color(vdev, pdcolor) < 0 || + gdev_vector_update_clip_path(vdev, pcpath) < 0 || + gdev_vector_update_log_op(vdev, lop) < 0 + ) + return gx_default_fill_mask(dev, data, data_x, raster, id, + x, y, w, h, pdcolor, depth, lop, pcpath); + (*dev_proc(vdev->bbox_device, fill_mask)) + ((gx_device *) vdev->bbox_device, data, data_x, raster, id, + x, y, w, h, pdcolor, depth, lop, pcpath); + return psw_image_write(pdev, ",", data, data_x, raster, id, + x, y, w, h, 1); +} + +/* ---------------- High-level images ---------------- */ + +private image_enum_proc_plane_data(psw_image_plane_data); +private image_enum_proc_end_image(psw_image_end_image); +private const gx_image_enum_procs_t psw_image_enum_procs = +{ + psw_image_plane_data, psw_image_end_image +}; + +/* Start processing an image. */ +private int +psw_begin_image(gx_device * dev, + const gs_imager_state * pis, const gs_image_t * pim, + gs_image_format_t format, const gs_int_rect * prect, + const gx_drawing_color * pdcolor, const gx_clip_path * pcpath, + gs_memory_t * mem, gx_image_enum_common_t ** pinfo) +{ + gdev_vector_image_enum_t *pie = + gs_alloc_struct(mem, gdev_vector_image_enum_t, + &st_vector_image_enum, "psw_begin_image"); + const gs_color_space *pcs = pim->ColorSpace; + gs_color_space_index index; + int num_components; + bool can_do = prect == 0; + int code; + + if (pie == 0) + return_error(gs_error_VMerror); + pie->memory = mem; + *pinfo = (gx_image_enum_common_t *) pie; + if (!pim->ImageMask) { + index = gs_color_space_get_index(pcs); + num_components = gs_color_space_num_components(pcs); + } + if (pdev->LanguageLevel < 2 && !pim->ImageMask) { /* + * Restrict ourselves to Level 1 images: device color spaces, [0 + * 1] decode, bits per component <= 8, no CombineWithColor. + */ + if (pim->BitsPerComponent > 8 || pim->CombineWithColor) + can_do = false; + else { + int i; + + switch (index) { + case gs_color_space_index_DeviceGray: + case gs_color_space_index_DeviceRGB: + case gs_color_space_index_DeviceCMYK: + for (i = 0; i < num_components * 2; ++i) + if (pim->Decode[i] != (i & 1)) + can_do = false; + break; + default: + can_do = false; + } + } + } + if (!can_do || + gdev_vector_begin_image(vdev, pis, pim, format, prect, pdcolor, + pcpath, mem, &psw_image_enum_procs, pie) < 0 || + (code = psw_image_stream_setup(pdev)) < 0 + ) + return gx_default_begin_image(dev, pis, pim, format, prect, + pdcolor, pcpath, mem, + &pie->default_info); + /* Write the image/colorimage/imagemask preamble. */ + { + stream *s = gdev_vector_stream((gx_device_vector *) pdev); + const char *source = (code ? "@X" : "@"); + gs_matrix imat; + + pputs(s, "q"); + (*dev_proc(dev, get_initial_matrix)) (dev, &imat); + gs_matrix_scale(&imat, 72.0 / dev->HWResolution[0], + 72.0 / dev->HWResolution[1], &imat); + gs_matrix_invert(&imat, &imat); + gs_matrix_multiply(&ctm_only(pis), &imat, &imat); + psw_put_matrix(s, &imat); + pprintd2(s, "concat\n%d %d ", pie->width, pie->height); + if (pim->ImageMask) { + pputs(s, (pim->Decode[0] == 0 ? "false" : "true")); + psw_put_matrix(s, &pim->ImageMatrix); + pprints1(s, "%s imagemask\n", source); + } else { + pprintd1(s, "%d", pim->BitsPerComponent); + psw_put_matrix(s, &pim->ImageMatrix); + if (index == gs_color_space_index_DeviceGray) + pprints1(s, "%s image\n", source); + else { + if (format == gs_image_format_chunky) + pprints1(s, "%s false", source); + else + pprints2(s, "%s %strue", source, + "dup dup dup " + (16 - num_components * 4)); + pprintd1(s, " %d colorimage\n", num_components); + } + } + } + return 0; +} + +/* Process the next piece of an image. */ +private int +psw_image_plane_data(gx_device * dev, + gx_image_enum_common_t * info, const gx_image_plane_t * planes, int height) +{ + gdev_vector_image_enum_t *pie = (gdev_vector_image_enum_t *) info; + + if (pie->default_info) + return gx_image_plane_data(pie->default_info, planes, height); + gx_image_plane_data(pie->bbox_info, planes, height); + { + int pi; + + for (pi = 0; pi < pie->num_planes; ++pi) + psw_put_bits(pdev->image_stream, planes[pi].data, + planes[pi].data_x * info->plane_depths[pi], + planes[pi].raster, + pie->width * info->plane_depths[pi], + height); + } + return (pie->y += height) >= pie->height; +} + +/* Clean up by releasing the buffers. */ +private int +psw_image_end_image(gx_device * dev, gx_image_enum_common_t * info, + bool draw_last) +{ + gdev_vector_image_enum_t *pie = (gdev_vector_image_enum_t *) info; + int code; + + code = gdev_vector_end_image(vdev, pie, draw_last, pdev->white); + if (code > 0) { + psw_image_cleanup(pdev); + pputs(pdev->strm, "\nQ\n"); + } + return code; +} diff --git a/pstoraster/gdevpsde.c b/pstoraster/gdevpsde.c new file mode 100644 index 0000000000..9389b60ab2 --- /dev/null +++ b/pstoraster/gdevpsde.c @@ -0,0 +1,282 @@ +/* Copyright (C) 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Embedded font writing */ +#include "memory_.h" +#include "gx.h" +#include "gserrors.h" +#include "gsccode.h" +#include "gsmatrix.h" +#include "gxfixed.h" +#include "gxfont.h" +#include "gxfont1.h" +#include "stream.h" +#include "gdevpstr.h" +#include "gdevpsdf.h" + +private int +embed_table(gs_param_list * plist, const char *key, const float *values, + int count) +{ + if (count != 0) { + gs_param_float_array fa; + + fa.size = count; + fa.data = values; + return param_write_float_array(plist, key, &fa); + } + return 0; +} + +private void +embed_uid(stream * s, const gs_uid * puid) +{ + if (uid_is_UniqueID(puid)) + pprintld1(s, "/UniqueID %ld def\n", puid->id); + else if (uid_is_XUID(puid)) { + uint i, n = uid_XUID_size(puid); + + pputs(s, "/XUID ["); + for (i = 0; i < n; ++i) + pprintld1(s, "%ld ", uid_XUID_values(puid)[i]); + pputs(s, "] def\n"); + } +} + +/* Write an embedded Type 1 font. */ +int +psdf_embed_type1_font(stream * s, gs_font_type1 * pfont) +{ + const gs_type1_data *const pdata = &pfont->data; + gs_param_list *plist; + param_printer_params_t ppp; + int code; + + ppp = param_printer_params_default; + ppp.item_suffix = " def\n"; + code = psdf_alloc_param_printer(&plist, &ppp, s, + print_binary_ok, s->memory); + if (code < 0) + return 0; + + /* Write the font header. */ + + pputs(s, "%!PS-AdobeFont-1.0: "); + pwrite(s, pfont->font_name.chars, pfont->font_name.size); + pputs(s, "\n11 dict begin\n"); + + /* Write FontInfo. Currently we don't write anything there. */ + + pputs(s, "/FontInfo 1 dict dup begin\n"); + pputs(s, "end readonly def\n"); + + /* Write the main font dictionary. */ + + pputs(s, "/FontName /"); + pwrite(s, pfont->font_name.chars, pfont->font_name.size); + pputs(s, " def\n"); + pputs(s, "/Encoding "); + switch (pfont->encoding_index) { + case 0: + pputs(s, "StandardEncoding"); + break; + case 1: + pputs(s, "ISOLatin1Encoding"); + break; + default:{ + gs_char i; + + pputs(s, "256 array\n"); + pputs(s, "0 1 255 {1 index exch /.notdef put} for\n"); + for (i = 0; i < 256; ++i) { + gs_glyph glyph = + (*pfont->procs.encode_char) (NULL, (gs_font *) pfont, &i); + const char *namestr; + uint namelen; + + if (glyph != gs_no_glyph && + (namestr = (*pfont->procs.callbacks.glyph_name) (glyph, &namelen)) != 0 && + !(namelen == 7 && !memcmp(namestr, ".notdef", 7)) + ) { + pprintd1(s, "dup %d /", (int)i); + pwrite(s, namestr, namelen); + pputs(s, " put\n"); + } + } + pputs(s, "readonly"); + } + } + pputs(s, " def\n"); + pprintg6(s, "/FontMatrix [%g %g %g %g %g %g] readonly def\n", + pfont->FontMatrix.xx, pfont->FontMatrix.xy, + pfont->FontMatrix.yx, pfont->FontMatrix.yy, + pfont->FontMatrix.tx, pfont->FontMatrix.ty); + embed_uid(s, &pfont->UID); + pprintg4(s, "/FontBBox {%g %g %g %g} readonly def\n", + pfont->FontBBox.p.x, pfont->FontBBox.p.y, + pfont->FontBBox.q.x, pfont->FontBBox.q.y); + { + private const gs_param_item_t font_items[] = + { + {"FontType", gs_param_type_int, + offset_of(gs_font_type1, FontType)}, + {"PaintType", gs_param_type_int, + offset_of(gs_font_type1, PaintType)}, + {"StrokeWidth", gs_param_type_float, + offset_of(gs_font_type1, StrokeWidth)}, + gs_param_item_end + }; + + code = gs_param_write_items(plist, pfont, NULL, font_items); + if (code < 0) + return code; + } + pputs(s, "currentdict end\n"); + + /* Write the Private dictionary. */ + + pputs(s, "dup /Private 17 dict dup begin\n"); + pputs(s, "/-|{string currentfile exch readstring pop}executeonly def\n"); + pputs(s, "/|-{noaccess def}executeonly def\n"); + pputs(s, "/|{noaccess put}executeonly def\n"); + { + private const gs_param_item_t private_items[] = + { + {"lenIV", gs_param_type_int, + offset_of(gs_type1_data, lenIV)}, + {"BlueFuzz", gs_param_type_int, + offset_of(gs_type1_data, BlueFuzz)}, + {"BlueScale", gs_param_type_float, + offset_of(gs_type1_data, BlueScale)}, + {"BlueShift", gs_param_type_float, + offset_of(gs_type1_data, BlueShift)}, + {"ExpansionFactor", gs_param_type_float, + offset_of(gs_type1_data, ExpansionFactor)}, + {"ForceBold", gs_param_type_bool, + offset_of(gs_type1_data, ForceBold)}, + {"LanguageGroup", gs_param_type_int, + offset_of(gs_type1_data, LanguageGroup)}, + {"RndStemUp", gs_param_type_bool, + offset_of(gs_type1_data, RndStemUp)}, + gs_param_item_end + }; + gs_type1_data defaults; + + defaults.lenIV = 4; + defaults.BlueFuzz = 1; + defaults.BlueScale = 0.039625; + defaults.BlueShift = 7.0; + defaults.ExpansionFactor = 0.06; + defaults.ForceBold = false; + defaults.LanguageGroup = 0; + defaults.RndStemUp = true; + code = gs_param_write_items(plist, pdata, &defaults, private_items); + if (code < 0) + return code; + embed_table(plist, "BlueValues", pdata->BlueValues.values, + pdata->BlueValues.count); + embed_table(plist, "OtherBlues", pdata->OtherBlues.values, + pdata->OtherBlues.count); + embed_table(plist, "FamilyBlues", pdata->FamilyBlues.values, + pdata->FamilyBlues.count); + embed_table(plist, "FamilyOtherBlues", pdata->FamilyOtherBlues.values, + pdata->FamilyOtherBlues.count); + embed_table(plist, "StdHW", pdata->StdHW.values, + pdata->StdHW.count); + embed_table(plist, "StemSnapH", pdata->StemSnapH.values, + pdata->StemSnapH.count); + embed_table(plist, "StemSnapV", pdata->StemSnapV.values, + pdata->StemSnapV.count); + } + embed_uid(s, &pfont->UID); + pputs(s, "/MinFeature{16 16} |-\n"); + pputs(s, "/password 5839 def\n"); + + /* Write the Subrs. */ + + { + int n, i; + gs_const_string str; + + for (n = 0; + (*pdata->procs->subr_data) (pfont, n, false, &str) != + gs_error_rangecheck; + ) + ++n; + pprintd1(s, "/Subrs %d array\n", n); + for (i = 0; i < n; ++i) + if ((*pdata->procs->subr_data) (pfont, i, false, &str) >= 0) { + char buf[50]; + + sprintf(buf, "dup %d %u -| ", i, str.size); + pputs(s, buf); + pwrite(s, str.data, str.size); + pputs(s, " |\n"); + } + pputs(s, "|-\n"); + } + + /* We don't write OtherSubrs -- there had better not be any! */ + + /* Write the CharStrings. */ + + { + int num_chars = 0; + gs_glyph glyph; + int index = 0; + gs_const_string gdata; + int code; + + for (glyph = gs_no_glyph, index = 0; + code = (*pdata->procs->next_glyph) (pfont, &index, &glyph), + index != 0; + ) + if (code == 0 && (*pdata->procs->glyph_data) (pfont, glyph, &gdata) >= 0) + ++num_chars; + pprintd1(s, "2 index /CharStrings %d dict dup begin\n", num_chars); + for (glyph = gs_no_glyph, index = 0; + code = (*pdata->procs->next_glyph) (pfont, &index, &glyph), + index != 0; + ) + if (code == 0 && (*pdata->procs->glyph_data) (pfont, glyph, &gdata) >= 0) { + uint gssize; + const char *gstr = + (*pfont->procs.callbacks.glyph_name) (glyph, &gssize); + + pputs(s, "/"); + pwrite(s, gstr, gssize); + pprintd1(s, " %d -| ", gdata.size); + pwrite(s, gdata.data, gdata.size); + pputs(s, " |-\n"); + } + } + + /* Wrap up. */ + + pputs(s, "end\nend\nreadonly put\nnoaccess put\n"); + pputs(s, "dup/FontName get exch definefont pop\n"); + psdf_free_param_printer(plist); + return 0; +} diff --git a/pstoraster/gdevpsdf.c b/pstoraster/gdevpsdf.c new file mode 100644 index 0000000000..38e5f40983 --- /dev/null +++ b/pstoraster/gdevpsdf.c @@ -0,0 +1,514 @@ +/* Copyright (C) 1997, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Common utilities for PostScript and PDF writers */ +#include "string_.h" +#include "gx.h" +#include "gserrors.h" +#include "gdevpsdf.h" +#include "gdevpstr.h" +#include "scanchar.h" +#include "strimpl.h" +#include "sa85x.h" +#include "scfx.h" +#include "sstring.h" + +/* Structure descriptor */ +public_st_device_psdf(); + +/* ---------------- Vector implementation procedures ---------------- */ + +int +psdf_setlinewidth(gx_device_vector * vdev, floatp width) +{ + pprintg1(gdev_vector_stream(vdev), "%g w\n", width); + return 0; +} + +int +psdf_setlinecap(gx_device_vector * vdev, gs_line_cap cap) +{ + pprintd1(gdev_vector_stream(vdev), "%d J\n", cap); + return 0; +} + +int +psdf_setlinejoin(gx_device_vector * vdev, gs_line_join join) +{ + pprintd1(gdev_vector_stream(vdev), "%d j\n", join); + return 0; +} + +int +psdf_setmiterlimit(gx_device_vector * vdev, floatp limit) +{ + pprintg1(gdev_vector_stream(vdev), "%g M\n", limit); + return 0; +} + +int +psdf_setdash(gx_device_vector * vdev, const float *pattern, uint count, + floatp offset) +{ + stream *s = gdev_vector_stream(vdev); + int i; + + pputs(s, "[ "); + for (i = 0; i < count; ++i) + pprintg1(s, "%g ", pattern[i]); + pprintg1(s, "] %g d\n", offset); + return 0; +} + +int +psdf_setflat(gx_device_vector * vdev, floatp flatness) +{ + pprintg1(gdev_vector_stream(vdev), "%g i\n", flatness); + return 0; +} + +int +psdf_setlogop(gx_device_vector * vdev, gs_logical_operation_t lop, + gs_logical_operation_t diff) +{ +/****** SHOULD AT LEAST DETECT SET-0 & SET-1 ******/ + return 0; +} + +int +psdf_setfillcolor(gx_device_vector * vdev, const gx_drawing_color * pdc) +{ + return psdf_set_color(vdev, pdc, "rg"); +} + +int +psdf_setstrokecolor(gx_device_vector * vdev, const gx_drawing_color * pdc) +{ + return psdf_set_color(vdev, pdc, "RG"); +} + +int +psdf_dorect(gx_device_vector * vdev, fixed x0, fixed y0, fixed x1, fixed y1, + gx_path_type_t type) +{ + int code = (*vdev_proc(vdev, beginpath)) (vdev, type); + + if (code < 0) + return code; + pprintg4(gdev_vector_stream(vdev), "%g %g %g %g re\n", + fixed2float(x0), fixed2float(y0), + fixed2float(x1 - x0), fixed2float(y1 - y0)); + return (*vdev_proc(vdev, endpath)) (vdev, type); +} + +int +psdf_beginpath(gx_device_vector * vdev, gx_path_type_t type) +{ + return 0; +} + +int +psdf_moveto(gx_device_vector * vdev, floatp x0, floatp y0, floatp x, floatp y, + bool first, gx_path_type_t type) +{ + pprintg2(gdev_vector_stream(vdev), "%g %g m\n", x, y); + return 0; +} + +int +psdf_lineto(gx_device_vector * vdev, floatp x0, floatp y0, floatp x, floatp y, + gx_path_type_t type) +{ + pprintg2(gdev_vector_stream(vdev), "%g %g l\n", x, y); + return 0; +} + +int +psdf_curveto(gx_device_vector * vdev, floatp x0, floatp y0, + floatp x1, floatp y1, floatp x2, floatp y2, floatp x3, floatp y3, + gx_path_type_t type) +{ + if (x1 == x0 && y1 == y0) + pprintg4(gdev_vector_stream(vdev), "%g %g %g %g v\n", + x2, y2, x3, y3); + else if (x3 == x2 && y3 == y2) + pprintg4(gdev_vector_stream(vdev), "%g %g %g %g y\n", + x1, y1, x2, y2); + else + pprintg6(gdev_vector_stream(vdev), "%g %g %g %g %g %g c\n", + x1, y1, x2, y2, x3, y3); + return 0; +} + +int +psdf_closepath(gx_device_vector * vdev, floatp x0, floatp y0, + floatp x_start, floatp y_start, gx_path_type_t type) +{ + pputs(gdev_vector_stream(vdev), "h\n"); + return 0; +} + +/* endpath is deliberately omitted. */ + +/* ---------------- Utilities ---------------- */ + +int +psdf_set_color(gx_device_vector * vdev, const gx_drawing_color * pdc, + const char *rgs) +{ + if (!gx_dc_is_pure(pdc)) + return_error(gs_error_rangecheck); + { + stream *s = gdev_vector_stream(vdev); + gx_color_index color = gx_dc_pure_color(pdc); + float r = (color >> 16) / 255.0; + float g = ((color >> 8) & 0xff) / 255.0; + float b = (color & 0xff) / 255.0; + + if (r == g && g == b) + pprintg1(s, "%g", r), pprints1(s, " %s\n", rgs + 1); + else + pprintg3(s, "%g %g %g", r, g, b), pprints1(s, " %s\n", rgs); + } + return 0; +} + +/* ---------------- Binary data writing ---------------- */ + +/* Begin writing binary data. */ +int +psdf_begin_binary(gx_device_psdf * pdev, psdf_binary_writer * pbw) +{ + pbw->strm = pdev->strm; + pbw->dev = pdev; + /* If not binary, set up the encoding stream. */ + if (!pdev->binary_ok) + psdf_encode_binary(pbw, &s_A85E_template, NULL); + return 0; +} + +/* Add an encoding filter. The client must have allocated the stream state, */ +/* if any, using pdev->v_memory. */ +int +psdf_encode_binary(psdf_binary_writer * pbw, const stream_template * template, + stream_state * ss) +{ + gx_device_psdf *pdev = pbw->dev; + gs_memory_t *mem = pdev->v_memory; + stream *es = s_alloc(mem, "psdf_encode_binary(stream)"); + stream_state *ess = (ss == 0 ? (stream_state *) es : ss); + uint bsize = max(template->min_out_size, 256); /* arbitrary */ + byte *buf = gs_alloc_bytes(mem, bsize, "psdf_encode_binary(buf)"); + + if (es == 0 || buf == 0) { + gs_free_object(mem, buf, "psdf_encode_binary(buf)"); + gs_free_object(mem, es, "psdf_encode_binary(stream)"); + return_error(gs_error_VMerror); + } + if (ess == 0) + ess = (stream_state *) es; + s_std_init(es, buf, bsize, &s_filter_write_procs, s_mode_write); + ess->template = template; + ess->memory = mem; + es->procs.process = template->process; + es->memory = mem; + es->state = ess; + if (template->init) + (*template->init) (ess); + es->strm = pbw->strm; + pbw->strm = es; + return 0; +} + +/* Add a 2-D CCITTFax encoding filter. */ +int +psdf_CFE_binary(psdf_binary_writer * pbw, int w, int h, bool invert) +{ + gx_device_psdf *pdev = pbw->dev; + gs_memory_t *mem = pdev->v_memory; + const stream_template *template = &s_CFE_template; + stream_CFE_state *st = + gs_alloc_struct(mem, stream_CFE_state, template->stype, + "psdf_CFE_binary"); + int code; + + if (st == 0) + return_error(gs_error_VMerror); + (*template->set_defaults) ((stream_state *) st); + st->K = -1; + st->Columns = w; + st->Rows = h; + st->BlackIs1 = !invert; + code = psdf_encode_binary(pbw, template, (stream_state *) st); + if (code < 0) + gs_free_object(mem, st, "psdf_CFE_binary"); + return code; +} + +/* Finish writing binary data. */ +int +psdf_end_binary(psdf_binary_writer * pbw) +{ + gx_device_psdf *pdev = pbw->dev; + + /* Close the filters in reverse order. */ + /* Stop before we try to close the file stream. */ + while (pbw->strm != pdev->strm) { + stream *next = pbw->strm->strm; + + sclose(pbw->strm); + pbw->strm = next; + } + return 0; +} + +/* + * Write a string in its shortest form ( () or <> ). Note that + * this form is different depending on whether binary data are allowed. + * Currently we don't support ASCII85 strings ( <~ ~> ). + */ +void +psdf_write_string(stream * s, const byte * str, uint size, int print_ok) +{ + uint added = 0; + uint i; + const stream_template *template; + stream_AXE_state state; + stream_state *st = NULL; + + if (print_ok & print_binary_ok) { /* Only need to escape (, ), \, CR, EOL. */ + pputc(s, '('); + for (i = 0; i < size; ++i) { + byte ch = str[i]; + + switch (ch) { + case char_CR: + pputs(s, "\\r"); + continue; + case char_EOL: + pputs(s, "\\n"); + continue; + case '(': + case ')': + case '\\': + pputc(s, '\\'); + } + pputc(s, ch); + } + pputc(s, ')'); + return; + } + for (i = 0; i < size; ++i) { + byte ch = str[i]; + + if (ch == 0 || ch >= 127) + added += 3; + else if (strchr("()\\\n\r\t\b\f", ch) != 0) + ++added; + else if (ch < 32) + added += 3; + } + + if (added < size) { /* More efficient to represent as PostScript string. */ + template = &s_PSSE_template; + pputc(s, '('); + } else { /* More efficient to represent as hex string. */ + template = &s_AXE_template; + st = (stream_state *) & state; + s_AXE_init_inline(&state); + pputc(s, '<'); + } + + { + byte buf[100]; /* size is arbitrary */ + stream_cursor_read r; + stream_cursor_write w; + int status; + + r.ptr = str - 1; + r.limit = r.ptr + size; + w.limit = buf + sizeof(buf) - 1; + do { + w.ptr = buf - 1; + status = (*template->process) (st, &r, &w, true); + pwrite(s, buf, (uint) (w.ptr + 1 - buf)); + } + while (status == 1); + } +} + +/* Set up a write stream that just keeps track of the position. */ +int +psdf_alloc_position_stream(stream ** ps, gs_memory_t * mem) +{ + stream *s = *ps = s_alloc(mem, "psdf_alloc_position_stream"); + + if (s == 0) + return_error(gs_error_VMerror); + swrite_position_only(s); + return 0; +} + +/* ---------------- Parameter printing ---------------- */ + +typedef struct printer_param_list_s { + gs_param_list_common; + stream *strm; + param_printer_params_t params; + int print_ok; + bool any; +} printer_param_list_t; + +gs_private_st_ptrs1(st_printer_param_list, printer_param_list_t, + "printer_param_list_t", printer_plist_enum_ptrs, printer_plist_reloc_ptrs, + strm); +const param_printer_params_t param_printer_params_default = +{ + param_printer_params_default_values +}; + +/* We'll implement the other printers later if we have to. */ +private param_proc_xmit_typed(param_print_typed); +/*private param_proc_begin_xmit_collection(param_print_begin_collection); */ +/*private param_proc_end_xmit_collection(param_print_end_collection); */ +private const gs_param_list_procs printer_param_list_procs = { + param_print_typed, + NULL /* begin_collection */ , + NULL /* end_collection */ , + NULL /* get_next_key */ , + gs_param_request_default, + gs_param_requested_default +}; + +int +psdf_alloc_param_printer(gs_param_list ** pplist, + const param_printer_params_t * ppp, stream * s, + int print_ok, gs_memory_t * mem) +{ + printer_param_list_t *prlist = + gs_alloc_struct(mem, printer_param_list_t, &st_printer_param_list, + "psdf_alloc_param_printer"); + + *pplist = (gs_param_list *) prlist; + if (prlist == 0) + return_error(gs_error_VMerror); + prlist->procs = &printer_param_list_procs; + prlist->memory = mem; + prlist->strm = s; + prlist->params = *ppp; + prlist->print_ok = print_ok; + prlist->any = false; + return 0; +} + +void +psdf_free_param_printer(gs_param_list * plist) +{ + if (plist) { + printer_param_list_t *prlist = (printer_param_list_t *) plist; + + if (prlist->any && prlist->params.suffix) + pputs(prlist->strm, prlist->params.suffix); + gs_free_object(prlist->memory, plist, "psdf_free_param_printer"); + } +} + +#define prlist ((printer_param_list_t *)plist) +private int +param_print_typed(gs_param_list * plist, gs_param_name pkey, + gs_param_typed_value * pvalue) +{ + stream *s = prlist->strm; + + if (!prlist->any) { + if (prlist->params.prefix) + pputs(s, prlist->params.prefix); + prlist->any = true; + } + if (prlist->params.item_prefix) + pputs(s, prlist->params.item_prefix); + pprints1(s, "/%s", pkey); + switch (pvalue->type) { + case gs_param_type_null: + pputs(s, " null"); + break; + case gs_param_type_bool: + pputs(s, (pvalue->value.b ? " true" : " false")); + break; + case gs_param_type_int: + pprintd1(s, " %d", pvalue->value.i); + break; + case gs_param_type_long: + pprintld1(s, " %l", pvalue->value.l); + break; + case gs_param_type_float: + pprintg1(s, " %g", pvalue->value.f); + break; + case gs_param_type_string: + psdf_write_string(s, pvalue->value.s.data, pvalue->value.s.size, + prlist->print_ok); + break; + case gs_param_type_name: +/****** SHOULD USE #-ESCAPES FOR PDF ******/ + pputc(s, '/'); + pwrite(s, pvalue->value.n.data, pvalue->value.n.size); + break; + case gs_param_type_int_array: + { + uint i; + char sepr = (pvalue->value.ia.size <= 10 ? ' ' : '\n'); + + pputc(s, '['); + for (i = 0; i < pvalue->value.ia.size; ++i) { + pprintd1(s, "%d", pvalue->value.ia.data[i]); + pputc(s, sepr); + } + pputc(s, ']'); + } + break; + case gs_param_type_float_array: + { + uint i; + char sepr = (pvalue->value.fa.size <= 10 ? ' ' : '\n'); + + pputc(s, '['); + for (i = 0; i < pvalue->value.fa.size; ++i) { + pprintg1(s, "%g", pvalue->value.fa.data[i]); + pputc(s, sepr); + } + pputc(s, ']'); + } + break; + /*case gs_param_type_string_array: */ + /*case gs_param_type_name_array: */ + default: + return_error(gs_error_typecheck); + } + if (prlist->params.item_suffix) + pputs(s, prlist->params.item_suffix); + return 0; +} + +#undef prlist diff --git a/pstoraster/gdevpsdf.h b/pstoraster/gdevpsdf.h new file mode 100644 index 0000000000..1e814a52ff --- /dev/null +++ b/pstoraster/gdevpsdf.h @@ -0,0 +1,292 @@ +/* Copyright (C) 1997, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Common output syntax and parameters for PostScript and PDF writers */ + +#ifndef gdevpsdf_INCLUDED +# define gdevpsdf_INCLUDED + +#include "gdevvec.h" +#include "gsparam.h" +#include "strimpl.h" +#include "scfx.h" + +/* ---------------- Distiller parameters ---------------- */ + +/* Parameters for controlling distillation of images. */ +typedef struct psdf_image_params_s { + stream_state *ACSDict; /* JPEG */ + bool AntiAlias; + bool AutoFilter; + int Depth; + stream_state *Dict; /* JPEG or CCITTFax */ + bool Downsample; + enum psdf_downsample_type { + ds_Average, + ds_Subsample + } DownsampleType; + bool Encode; + const char *Filter; + int Resolution; + const stream_template *filter_template; +} psdf_image_params; + +#define psdf_image_param_defaults(af, res, f, ft)\ + NULL/*ACSDict*/, 0/*false*/, af, -1, NULL/*Dict*/, 0/*false*/,\ + ds_Subsample, 1/*true*/, f, res, ft + +/* Declare templates for default image compression filters. */ +extern const stream_template s_CFE_template; + +/* Complete distiller parameters. */ +typedef struct psdf_distiller_params_s { + + /* General parameters */ + + bool ASCII85EncodePages; + enum psdf_auto_rotate_pages { + arp_None, + arp_All, + arp_PageByPage + } AutoRotatePages; + bool CompressPages; + long ImageMemory; + bool LZWEncodePages; + bool PreserveHalftoneInfo; + bool PreserveOPIComments; + bool PreserveOverprintSettings; + enum psdf_transfer_function_info { + tfi_Preserve, + tfi_Apply, + tfi_Remove + } TransferFunctionInfo; + enum psdf_ucr_and_bg_info { + ucrbg_Preserve, + ucrbg_Remove + } UCRandBGInfo; + bool UseFlateCompression; +#define psdf_general_param_defaults(ascii)\ + ascii, arp_None, 1/*true*/, 250000, 0/*false*/,\ + 0/*false*/, 0/*false*/, 0/*false*/, tfi_Apply, ucrbg_Remove, 1 /*true */ + + /* Color sampled image parameters */ + + psdf_image_params ColorImage; + enum psdf_color_conversion_strategy { + ccs_LeaveColorUnchanged, + ccs_UseDeviceDependentColor, + ccs_UseDeviceIndependentColor + } ColorConversionStrategy; + bool ConvertCMYKImagesToRGB; + bool ConvertImagesToIndexed; +#define psdf_color_image_param_defaults\ + { psdf_image_param_defaults(1/*true*/, 72, 0, 0) },\ + ccs_LeaveColorUnchanged, 1/*true*/, 0 /*false */ + + /* Grayscale sampled image parameters */ + + psdf_image_params GrayImage; +#define psdf_gray_image_param_defaults\ + { psdf_image_param_defaults(1/*true*/, 72, 0, 0) } + + /* Monochrome sampled image parameters */ + + psdf_image_params MonoImage; +#define psdf_mono_image_param_defaults\ + { psdf_image_param_defaults(0/*false*/, 300, "CCITTFaxEncode", &s_CFE_template) } + + /* Font embedding parameters */ + + gs_param_string_array AlwaysEmbed; + gs_param_string_array NeverEmbed; + bool EmbedAllFonts; + bool SubsetFonts; + int MaxSubsetPct; +#define psdf_font_param_defaults\ + { 0, 0, 1/*true*/ }, { 0, 0, 1/*true*/ },\ + 1/*true*/, 1/*true*/, 20 + +} psdf_distiller_params; + +/* Define PostScript/PDF versions, corresponding roughly to Adobe versions. */ +typedef enum { + psdf_version_level1 = 1000, /* Red Book Level 1 */ + psdf_version_level1_color = 1100, /* Level 1 + colorimage + CMYK color */ + psdf_version_level2 = 2000, /* Red Book Level 2 */ + psdf_version_level2_plus = 2017, /* Adobe release 2017 */ + psdf_version_ll3 = 3010 /* LanguageLevel 3, release 3010 */ +} psdf_version; + +/* Define the extended device structure. */ +#define gx_device_psdf_common\ + gx_device_vector_common;\ + psdf_version version;\ + bool binary_ok; /* derived from ASCII85EncodePages */\ + psdf_distiller_params params +typedef struct gx_device_psdf_s { + gx_device_psdf_common; +} gx_device_psdf; + +#define psdf_initial_values(version, ascii)\ + vector_initial_values,\ + version,\ + !(ascii),\ + { psdf_general_param_defaults(ascii),\ + psdf_color_image_param_defaults,\ + psdf_gray_image_param_defaults,\ + psdf_mono_image_param_defaults,\ + psdf_font_param_defaults\ + } + +/* st_device_psdf is never instantiated per se, but we still need to */ +/* extern its descriptor for the sake of subclasses. */ +extern_st(st_device_psdf); +#define public_st_device_psdf() /* in gdevpsdf.c */\ + gs_public_st_suffix_add0_final(st_device_psdf, gx_device_psdf,\ + "gx_device_psdf", device_psdf_enum_ptrs,\ + device_psdf_reloc_ptrs, gx_device_finalize, st_device_vector) +#define st_device_psdf_max_ptrs (st_device_vector_max_ptrs) + +/* Get/put parameters. */ +dev_proc_get_params(gdev_psdf_get_params); +dev_proc_put_params(gdev_psdf_put_params); + +/* Put a Boolean or integer parameter. */ +int psdf_put_bool_param(P4(gs_param_list * plist, gs_param_name param_name, + bool * pval, int ecode)); +int psdf_put_int_param(P4(gs_param_list * plist, gs_param_name param_name, + int *pval, int ecode)); + +/* ---------------- Vector implementation procedures ---------------- */ + + /* Imager state */ +int psdf_setlinewidth(P2(gx_device_vector * vdev, floatp width)); +int psdf_setlinecap(P2(gx_device_vector * vdev, gs_line_cap cap)); +int psdf_setlinejoin(P2(gx_device_vector * vdev, gs_line_join join)); +int psdf_setmiterlimit(P2(gx_device_vector * vdev, floatp limit)); +int psdf_setdash(P4(gx_device_vector * vdev, const float *pattern, + uint count, floatp offset)); +int psdf_setflat(P2(gx_device_vector * vdev, floatp flatness)); +int psdf_setlogop(P3(gx_device_vector * vdev, gs_logical_operation_t lop, + gs_logical_operation_t diff)); + + /* Other state */ +int psdf_setfillcolor(P2(gx_device_vector * vdev, const gx_drawing_color * pdc)); +int psdf_setstrokecolor(P2(gx_device_vector * vdev, const gx_drawing_color * pdc)); + + /* Paths */ +#define psdf_dopath gdev_vector_dopath +int psdf_dorect(P6(gx_device_vector * vdev, fixed x0, fixed y0, fixed x1, + fixed y1, gx_path_type_t type)); +int psdf_beginpath(P2(gx_device_vector * vdev, gx_path_type_t type)); +int psdf_moveto(P7(gx_device_vector * vdev, floatp x0, floatp y0, + floatp x, floatp y, bool first, gx_path_type_t type)); +int psdf_lineto(P6(gx_device_vector * vdev, floatp x0, floatp y0, + floatp x, floatp y, gx_path_type_t type)); +int psdf_curveto(P10(gx_device_vector * vdev, floatp x0, floatp y0, + floatp x1, floatp y1, floatp x2, + floatp y2, floatp x3, floatp y3, gx_path_type_t type)); +int psdf_closepath(P6(gx_device_vector * vdev, floatp x0, floatp y0, + floatp x_start, floatp y_start, gx_path_type_t type)); + +/* ---------------- Binary (image) data procedures ---------------- */ + +/* Define the structure for writing binary data. */ +typedef struct psdf_binary_writer_s { + stream *strm; + gx_device_psdf *dev; +} psdf_binary_writer; + +/* Begin writing binary data. */ +int psdf_begin_binary(P2(gx_device_psdf * pdev, psdf_binary_writer * pbw)); + +/* Add an encoding filter. The client must have allocated the stream state, */ +/* if any, using pdev->v_memory. */ +int psdf_encode_binary(P3(psdf_binary_writer * pbw, + const stream_template * template, stream_state * ss)); + +/* Add a 2-D CCITTFax encoding filter. */ +int psdf_CFE_binary(P4(psdf_binary_writer * pbw, int w, int h, bool invert)); + +/* Set up compression and downsampling filters for an image. */ +/* Note that this may modify the image parameters. */ +/* If pctm is NULL, downsampling is not used. */ +/* pis only provides UCR and BG information for CMYK => RGB conversion. */ +int psdf_setup_image_filters(P5(gx_device_psdf * pdev, psdf_binary_writer * pbw, + gs_image_t * pim, const gs_matrix * pctm, + const gs_imager_state * pis)); + +/* Finish writing binary data. */ +int psdf_end_binary(P1(psdf_binary_writer * pbw)); + +/* ------ Symbolic data printing ------ */ + +/* Print a PostScript string in the most efficient form. */ +#define print_binary_ok 1 +#define print_ASCII85_ok 2 +void psdf_write_string(P4(stream * s, const byte * str, uint size, + int print_ok)); + +/* + * Create a stream that just keeps track of how much has been written + * to it. We use this for measuring data that will be stored rather + * than written to an actual stream. This too should probably migrate + * to stream.c.... + */ +int psdf_alloc_position_stream(P2(stream ** ps, gs_memory_t * mem)); + +/* + * Create/release a parameter list for printing (non-default) filter + * parameters. This should probably migrate to a lower level.... + */ +typedef struct param_printer_params_s { + const char *prefix; /* before entire object, if any params */ + const char *suffix; /* after entire object, if any params */ + const char *item_prefix; /* before each param */ + const char *item_suffix; /* after each param */ +} param_printer_params_t; + +#define param_printer_params_default_values 0, 0, 0, "\n" +extern const param_printer_params_t param_printer_params_default; +int psdf_alloc_param_printer(P5(gs_param_list ** pplist, + const param_printer_params_t * ppp, stream * s, + int print_ok, gs_memory_t * mem)); +void psdf_free_param_printer(P1(gs_param_list * plist)); + +/* Write out a Type 1 font definition. */ +#ifndef gs_font_type1_DEFINED +# define gs_font_type1_DEFINED +typedef struct gs_font_type1_s gs_font_type1; + +#endif +int psdf_embed_type1_font(P2(stream * s, gs_font_type1 * pfont)); + +/* ---------------- Other procedures ---------------- */ + +/* Set the fill or stroke color. rgs is "rg" or "RG". */ +int psdf_set_color(P3(gx_device_vector * vdev, const gx_drawing_color * pdc, + const char *rgs)); + +#endif /* gdevpsdf_INCLUDED */ diff --git a/pstoraster/gdevpsdi.c b/pstoraster/gdevpsdi.c new file mode 100644 index 0000000000..9ba6c16149 --- /dev/null +++ b/pstoraster/gdevpsdi.c @@ -0,0 +1,349 @@ +/* + Copyright 1993-2000 by Easy Software Products. + Copyright 1997, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Image compression for PostScript and PDF writers */ +#include "math_.h" +#include "gx.h" +#include "gserrors.h" +#include "gscspace.h" +#include "gdevpsdf.h" +#include "gdevpsds.h" +#include "strimpl.h" +#include "scfx.h" +#include +#ifdef HAVE_LIBJPEG +#include "jpeglib.h" /* for sdct.h */ +#include "sdct.h" +#endif /* HAVE_LIBJPEG */ +#include "slzwx.h" +#include "spngpx.h" +#include "srlx.h" +#ifdef HAVE_LIBZ +#include "szlibx.h" +#endif /* HAVE_LIBZ */ + +/* ---------------- Image compression ---------------- */ + +/* Add a filter to expand or reduce the pixel width if needed. */ +/* At least one of bpc_in and bpc_out is 8; the other is 1, 2, 4, or 8. */ +private int +pixel_resize(psdf_binary_writer * pbw, int width, int num_components, + int bpc_in, int bpc_out) +{ + gs_memory_t *mem = pbw->dev->v_memory; + const stream_template *template; + stream_1248_state *st; + int code; + + if (bpc_out == bpc_in) + return 0; + if (bpc_in < 8) { + static const stream_template *const exts[5] = + { + 0, &s_1_8_template, &s_2_8_template, 0, &s_4_8_template + }; + + template = exts[bpc_in]; + } else { + static const stream_template *const rets[5] = + { + 0, &s_8_1_template, &s_8_2_template, 0, &s_8_4_template + }; + + template = rets[bpc_out]; + } + st = (stream_1248_state *) + s_alloc_state(mem, template->stype, "pixel_resize state"); + if (st == 0) + return_error(gs_error_VMerror); + code = psdf_encode_binary(pbw, template, (stream_state *) st); + if (code < 0) { + gs_free_object(mem, st, "pixel_resize state"); + return code; + } + s_1248_init(st, width, num_components); + return 0; +} + +/* Add the appropriate image compression filter, if any. */ +private int +setup_image_compression(psdf_binary_writer * pbw, const psdf_image_params * pdip, + const gs_image_t * pim) +{ + gx_device_psdf *pdev = pbw->dev; + const stream_template *template = pdip->filter_template; + stream_state *st; + + if (pdip->AutoFilter) { + /****** AutoFilter IS NYI ******/ + /* + * Even though this isn't obvious from the Adobe Tech Note, + * it appears that if UseFlateCompression is true, the default + * compressor for AutoFilter is FlateEncode, not LZWEncode. + */ +#ifdef HAVE_LIBZ + template = + (pdev->params.UseFlateCompression && + pdev->version >= psdf_version_ll3 ? + &s_zlibE_template : &s_LZWE_template); +#else + template = &s_LZWE_template; +#endif /* HAVE_LIBZ */ + } + if (!pdip->Encode || template == 0) /* no compression */ + return 0; +#ifdef HAVE_LIBJPEG + /* Only use DCTE for 8-bit data. */ + if (template == &s_DCTE_template && + !(pdip->Downsample ? + pdip->Depth == 8 || + (pdip->Depth == -1 && pim->BitsPerComponent == 8) : + pim->BitsPerComponent == 8) + ) { + /* Use LZW instead. */ + template = &s_LZWE_template; + } +#endif /* HAVE_LIBJPEG */ + st = s_alloc_state(pdev->v_memory, template->stype, + "setup_image_compression"); + if (st == 0) + return_error(gs_error_VMerror); + if (template->set_defaults) + (*template->set_defaults) (st); + if (template == &s_CFE_template) { + stream_CFE_state *const ss = (stream_CFE_state *) st; + + if (pdip->Dict != 0 && pdip->Dict->template == &s_CFE_template) { + stream_state common; + + common = *st; /* save generic info */ + *ss = *(const stream_CFE_state *)pdip->Dict; + *st = common; + } else { + ss->K = -1; + ss->BlackIs1 = true; + } + ss->Columns = pim->Width; + ss->Rows = (ss->EndOfBlock ? 0 : pim->Height); +#ifdef HAVE_LIBZ + } else if (template == &s_LZWE_template || + template == &s_zlibE_template) { +#else + } else if (template == &s_LZWE_template) { +#endif /* HAVE_LIBZ */ + /* Add a PNGPredictor filter. */ + int code = psdf_encode_binary(pbw, template, st); + + if (code < 0) { + gs_free_object(pdev->v_memory, st, "setup_image_compression"); + return code; + } + template = &s_PNGPE_template; + st = s_alloc_state(pdev->v_memory, template->stype, + "setup_image_compression"); + if (st == 0) + return_error(gs_error_VMerror); + if (template->set_defaults) + (*template->set_defaults) (st); + { + stream_PNGP_state *const ss = (stream_PNGP_state *) st; + + ss->Colors = gs_color_space_num_components(pim->ColorSpace); + ss->Columns = pim->Width; + } +#ifdef HAVE_LIBJPEG + } else if (template == &s_DCTE_template) { + /****** ADD PARAMETERS FROM pdip->Dict ******/ +#endif /* HAVE_LIBJPEG */ + } { + int code = psdf_encode_binary(pbw, template, st); + + if (code < 0) { + gs_free_object(pdev->v_memory, st, "setup_image_compression"); + return code; + } + } + return 0; +} + +/* Add downsampling, antialiasing, and compression filters. */ +/* Uses AntiAlias, Depth, DownsampleType, Resolution. */ +private int +setup_downsampling(psdf_binary_writer * pbw, const psdf_image_params * pdip, + gs_image_t * pim, floatp resolution) +{ + gx_device_psdf *pdev = pbw->dev; + const stream_template *template = + (pdip->DownsampleType == ds_Average ? + &s_Average_template : &s_Subsample_template); + int factor = (int)(resolution / pdip->Resolution); + int orig_bpc = pim->BitsPerComponent; + int orig_width = pim->Width; + int orig_height = pim->Height; + stream_state *st; + int code; + + if (factor <= 1 || pim->Width < factor || pim->Height < factor) + return setup_image_compression(pbw, pdip, pim); /* no downsampling */ + st = s_alloc_state(pdev->v_memory, template->stype, + "setup_downsampling"); + if (st == 0) + return_error(gs_error_VMerror); + if (template->set_defaults) + (*template->set_defaults) (st); + { + stream_Downsample_state *const ss = (stream_Downsample_state *) st; + + ss->Colors = gs_color_space_num_components(pim->ColorSpace); + ss->Columns = pim->Width; + ss->XFactor = ss->YFactor = factor; + ss->AntiAlias = pdip->AntiAlias; + if (template->init) + (*template->init) (st); + pim->Width /= factor; + pim->Height /= factor; + pim->BitsPerComponent = pdip->Depth; + gs_matrix_scale(&pim->ImageMatrix, (double)pim->Width / orig_width, + (double)pim->Height / orig_height, + &pim->ImageMatrix); + /****** NO ANTI-ALIASING YET ******/ + if ((code = setup_image_compression(pbw, pdip, pim)) < 0 || + (code = pixel_resize(pbw, pim->Width, ss->Colors, + 8, pdip->Depth)) < 0 || + (code = psdf_encode_binary(pbw, template, st)) < 0 || + (code = pixel_resize(pbw, orig_width, ss->Colors, + orig_bpc, 8)) < 0 + ) { + gs_free_object(pdev->v_memory, st, "setup_image_compression"); + return code; + } + } + return 0; +} + +/* Set up compression and downsampling filters for an image. */ +/* Note that this may modify the image parameters. */ +int +psdf_setup_image_filters(gx_device_psdf * pdev, psdf_binary_writer * pbw, + gs_image_t * pim, const gs_matrix * pctm, + const gs_imager_state * pis) +{ /* + * The following algorithms are per Adobe Tech Note # 5151, + * "Acrobat Distiller Parameters", revised 16 September 1996 + * for Acrobat(TM) Distiller(TM) 3.0. + * + * The control structure is a little tricky, because filter + * pipelines must be constructed back-to-front. + */ + int code = 0; + psdf_image_params params; + + if (pim->ImageMask) { + params = pdev->params.MonoImage; + params.Depth = 1; + } else { + int ncomp = gs_color_space_num_components(pim->ColorSpace); + int bpc = pim->BitsPerComponent; + + /* + * We can compute the image resolution by: + * W / (W * ImageMatrix^-1 * CTM / HWResolution). + * We can replace W by 1 to simplify the computation. + */ + double resolution; + + if (pctm == 0) + resolution = -1; + else { + gs_point pt; + + /* We could do both X and Y, but why bother? */ + gs_distance_transform_inverse(1.0, 0.0, &pim->ImageMatrix, &pt); + gs_distance_transform(pt.x, pt.y, pctm, &pt); + resolution = 1.0 / hypot(pt.x / pdev->HWResolution[0], + pt.y / pdev->HWResolution[1]); + } + if (ncomp == 1) { + /* Monochrome or gray */ + if (bpc == 1) + params = pdev->params.MonoImage; + else + params = pdev->params.GrayImage; + if (params.Depth == -1) + params.Depth = bpc; + /* Check for downsampling. */ + if (params.Downsample && params.Resolution <= resolution / 2) { + /* Use the downsampled depth, not the original data depth. */ + if (params.Depth == 1) { + params.Filter = pdev->params.MonoImage.Filter; + params.filter_template = pdev->params.MonoImage.filter_template; + params.Dict = pdev->params.MonoImage.Dict; + } else { + params.Filter = pdev->params.GrayImage.Filter; + params.filter_template = pdev->params.GrayImage.filter_template; + params.Dict = pdev->params.GrayImage.Dict; + } + code = setup_downsampling(pbw, ¶ms, pim, resolution); + } else { + code = setup_image_compression(pbw, ¶ms, pim); + } + } else { + /* Color */ + bool cmyk_to_rgb = + pdev->params.ConvertCMYKImagesToRGB && + pis != 0 && + gs_color_space_get_index(pim->ColorSpace) == + gs_color_space_index_DeviceCMYK; + + if (cmyk_to_rgb) + pim->ColorSpace = gs_cspace_DeviceRGB(pis); + params = pdev->params.ColorImage; + if (params.Depth == -1) + params.Depth = (cmyk_to_rgb ? 8 : bpc); + if (params.Downsample && params.Resolution <= resolution / 2) { + code = setup_downsampling(pbw, ¶ms, pim, resolution); + } else { + code = setup_image_compression(pbw, ¶ms, pim); + } + if (cmyk_to_rgb) { + gs_memory_t *mem = pdev->v_memory; + stream_C2R_state *ss = (stream_C2R_state *) + s_alloc_state(mem, s_C2R_template.stype, "C2R state"); + int code = pixel_resize(pbw, pim->Width, 3, 8, bpc); + + if (code < 0 || + (code = psdf_encode_binary(pbw, &s_C2R_template, + (stream_state *) ss)) < 0 || + (code = pixel_resize(pbw, pim->Width, 4, bpc, 8)) < 0 + ) + return code; + s_C2R_init(ss, pis); + } + } + } + return code; +} diff --git a/pstoraster/gdevpsdp.c b/pstoraster/gdevpsdp.c new file mode 100644 index 0000000000..cad5e1d8ab --- /dev/null +++ b/pstoraster/gdevpsdp.c @@ -0,0 +1,705 @@ +/* + Copyright 1993-2000 by Easy Software Products. + Copyright 1997, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* (Distiller) parameter handling for PostScript and PDF writers */ +#include "string_.h" +#include "gx.h" +#include "gserrors.h" +#include "gxdevice.h" +#include "gdevpsdf.h" +#include "gdevpstr.h" +#include "strimpl.h" /* for short-sighted compilers */ +#include "scfx.h" +#include +#ifdef HAVE_LIBJPEG +#include "jpeglib.h" /* for sdct.h */ +#include "sdct.h" +#endif /* HAVE_LIBJPEG */ +#include "slzwx.h" +#include "srlx.h" +#ifdef HAVE_LIBZ +#include "szlibx.h" +#endif /* HAVE_LIBZ */ + +/* ---------------- Get/put Distiller parameters ---------------- */ + +/* + * This code handles all the Distiller parameters except the *ACSDict and + * *ImageDict parameter dictionaries. (It doesn't cause any of the + * parameters actually to have any effect.) + */ + +typedef struct psdf_image_filter_name_s { + const char *pname; + const stream_template *template; + psdf_version min_version; +} psdf_image_filter_name; +typedef struct psdf_image_param_names_s { + const char *ACSDict; /* not used for mono */ + const char *AntiAlias; + const char *AutoFilter; /* not used for mono */ + const char *Depth; + const char *Dict; + const char *Downsample; + const char *DownsampleType; + const char *Encode; + const char *Filter; + const char *Resolution; +} psdf_image_param_names; +private const psdf_image_param_names Color_names = +{ + "ColorACSImageDict", "AntiAliasColorImages", "AutoFilterColorImages", + "ColorImageDepth", "ColorImageDict", + "DownsampleColorImages", "ColorImageDownsampleType", "EncodeColorImages", + "ColorImageFilter", "ColorImageResolution" +}; +private const psdf_image_filter_name Poly_filters[] = +{ +#ifdef HAVE_LIBJPEG + {"DCTEncode", &s_DCTE_template}, +#endif /* HAVE_LIBJPEG */ +#ifdef HAVE_LIBZ + {"FlateEncode", &s_zlibE_template, psdf_version_ll3}, +#endif /* HAVE_LIBZ */ + {"LZWEncode", &s_LZWE_template}, + {0, 0} +}; +private const psdf_image_param_names Gray_names = +{ + "GrayACSImageDict", "AntiAliasGrayImages", "AutoFilterGrayImages", + "GrayImageDepth", "GrayImageDict", + "DownsampleGrayImages", "GrayImageDownsampleType", "EncodeGrayImages", + "GrayImageFilter", "GrayImageResolution" +}; +private const psdf_image_param_names Mono_names = +{ + 0, "AntiAliasMonoImages", 0, + "MonoImageDepth", "MonoImageDict", + "DownsampleMonoImages", "MonoImageDownsampleType", "EncodeMonoImages", + "MonoImageFilter", "MonoImageResolution" +}; +private const psdf_image_filter_name Mono_filters[] = +{ + {"CCITTFaxEncode", &s_CFE_template}, +#ifdef HAVE_LIBZ + {"FlateEncode", &s_zlibE_template, psdf_version_ll3}, +#endif /* HAVE_LIBZ */ + {"LZWEncode", &s_LZWE_template}, + {"RunLengthEncode", &s_RLE_template}, + {0, 0} +}; +private const char *const AutoRotatePages_names[] = +{ + "None", "All", "PageByPage", 0 +}; +private const char *const ColorConversionStrategy_names[] = +{ + "LeaveColorUnchanged", "UseDeviceDependentColor", + "UseDeviceIndependentColor", 0 +}; +private const char *const DownsampleType_names[] = +{ + "Average", "Subsample", 0 +}; +private const char *const TransferFunctionInfo_names[] = +{ + "Preserve", "Apply", "Remove", 0 +}; +private const char *const UCRandBGInfo_names[] = +{ + "Preserve", "Remove", 0 +}; + +/* -------- Get parameters -------- */ + +#ifdef HAVE_LIBJPEG +extern stream_state_proc_get_params(s_DCTE_get_params, stream_DCT_state); +#endif /* HAVE_LIBJPEG */ +extern stream_state_proc_get_params(s_CF_get_params, stream_CF_state); +typedef stream_state_proc_get_params((*ss_get_params_t), stream_state); + +private int +psdf_CF_get_params(gs_param_list * plist, const stream_state * ss, bool all) +{ + return (ss == 0 ? 0 : + s_CF_get_params(plist, (const stream_CF_state *)ss, all)); +} +#ifdef HAVE_LIBJPEG +private int +psdf_DCT_get_params(gs_param_list * plist, const stream_state * ss, bool all) +{ + int code = (ss == 0 ? 0 : + s_DCTE_get_params(plist, (const stream_DCT_state *)ss, all)); + /* + * Add dummy Columns, Rows, and Colors parameters so that put_params + * won't complain. + */ + int dummy_size = 8, dummy_colors = 3; + + if (code < 0 || + (code = param_write_int(plist, "Columns", &dummy_size)) < 0 || + (code = param_write_int(plist, "Rows", &dummy_size)) < 0 || + (code = param_write_int(plist, "Colors", &dummy_colors)) < 0 + ) + return code; + return 0; +} +#endif /* HAVE_LIBJPEG */ + +/* + * Get an image Dict parameter. Note that we return a default (usually + * empty) dictionary if the parameter has never been set. + */ +private int +psdf_get_image_dict_param(gs_param_list * plist, const gs_param_name pname, + stream_state * ss, ss_get_params_t get_params) +{ + gs_param_dict dict; + int code; + + if (pname == 0) + return 0; + dict.size = 12; /* enough for all param dicts we know about */ + if ((code = param_begin_write_dict(plist, pname, &dict, false)) < 0) + return code; + code = (*get_params)(dict.list, ss, false); + param_end_write_dict(plist, pname, &dict); + return code; +} + +/* Get a set of image-related parameters. */ +private int +psdf_get_image_params(gs_param_list * plist, + const psdf_image_param_names * pnames, psdf_image_params * params) +{ + int code; + gs_param_string dsts, fs; + + param_string_from_string(dsts, + DownsampleType_names[params->DownsampleType]); + if ( +#ifdef HAVE_LIBJPEG + (code = psdf_get_image_dict_param(plist, pnames->ACSDict, + params->ACSDict, + psdf_DCT_get_params)) < 0 || +#endif /* HAVE_LIBJPEG */ + (code = param_write_bool(plist, pnames->AntiAlias, + ¶ms->AntiAlias)) < 0 || + (pnames->AutoFilter != 0 && + (code = param_write_bool(plist, pnames->AutoFilter, + ¶ms->AutoFilter)) < 0) || + (code = param_write_int(plist, pnames->Depth, + ¶ms->Depth)) < 0 || + (code = psdf_get_image_dict_param(plist, pnames->Dict, + params->Dict, +#ifdef HAVE_LIBJPEG + (params->Dict == 0 || + params->Dict->template == + &s_CFE_template ? + psdf_CF_get_params : + psdf_DCT_get_params))) < 0 || +#else + psdf_CF_get_params)) < 0 || +#endif /* HAVE_LIBJPEG */ + (code = param_write_bool(plist, pnames->Downsample, + ¶ms->Downsample)) < 0 || + (code = param_write_name(plist, pnames->DownsampleType, + &dsts)) < 0 || + (code = param_write_bool(plist, pnames->Encode, + ¶ms->Encode)) < 0 || + (code = (params->Filter == 0 ? 0 : + (param_string_from_string(fs, params->Filter), + param_write_name(plist, pnames->Filter, &fs)))) < 0 || + (code = param_write_int(plist, pnames->Resolution, + ¶ms->Resolution)) < 0 + ) + DO_NOTHING; + return code; +} + +/* Get parameters. */ +int +gdev_psdf_get_params(gx_device * dev, gs_param_list * plist) +{ + gx_device_psdf *pdev = (gx_device_psdf *) dev; + int code = gdev_vector_get_params(dev, plist); + gs_param_string arps, ccss, tfis, ucrbgis; + + if (code < 0) + return code; + param_string_from_string(arps, + AutoRotatePages_names[(int)pdev->params.AutoRotatePages]); + param_string_from_string(ccss, + ColorConversionStrategy_names[(int)pdev->params.ColorConversionStrategy]); + param_string_from_string(tfis, + TransferFunctionInfo_names[(int)pdev->params.TransferFunctionInfo]); + param_string_from_string(ucrbgis, + UCRandBGInfo_names[(int)pdev->params.UCRandBGInfo]); + if ( + /* General parameters */ + + (code = param_write_bool(plist, "ASCII85EncodePages", + &pdev->params.ASCII85EncodePages)) < 0 || + (code = param_write_name(plist, "AutoRotatePages", + &arps)) < 0 || + (code = param_write_bool(plist, "CompressPages", + &pdev->params.CompressPages)) < 0 || + (code = param_write_long(plist, "ImageMemory", + &pdev->params.ImageMemory)) < 0 || + (code = param_write_bool(plist, "LZWEncodePages", + &pdev->params.LZWEncodePages)) < 0 || + (code = param_write_bool(plist, "PreserveHalftoneInfo", + &pdev->params.PreserveHalftoneInfo)) < 0 || + (code = param_write_bool(plist, "PreserveOPIComments", + &pdev->params.PreserveOPIComments)) < 0 || + (code = param_write_bool(plist, "PreserveOverprintSettings", + &pdev->params.PreserveOverprintSettings)) < 0 || + (code = param_write_name(plist, "TransferFunctionInfo", &tfis)) < 0 || + (code = param_write_name(plist, "UCRandBGInfo", &ucrbgis)) < 0 || + (code = param_write_bool(plist, "UseFlateCompression", + &pdev->params.UseFlateCompression)) < 0 || + + /* Color sampled image parameters */ + + (code = psdf_get_image_params(plist, &Color_names, &pdev->params.ColorImage)) < 0 || + (code = param_write_name(plist, "ColorConversionStrategy", + &ccss)) < 0 || + (code = param_write_bool(plist, "ConvertCMYKImagesToRGB", + &pdev->params.ConvertCMYKImagesToRGB)) < 0 || + (code = param_write_bool(plist, "ConvertImagesToIndexed", + &pdev->params.ConvertImagesToIndexed)) < 0 || + + /* Gray sampled image parameters */ + + (code = psdf_get_image_params(plist, &Gray_names, &pdev->params.GrayImage)) < 0 || + + /* Mono sampled image parameters */ + + (code = psdf_get_image_params(plist, &Mono_names, &pdev->params.MonoImage)) < 0 || + + /* Font embedding parameters */ + + (code = param_write_name_array(plist, "AlwaysEmbed", &pdev->params.AlwaysEmbed)) < 0 || + (code = param_write_name_array(plist, "NeverEmbed", &pdev->params.NeverEmbed)) < 0 || + (code = param_write_bool(plist, "EmbedAllFonts", &pdev->params.EmbedAllFonts)) < 0 || + (code = param_write_bool(plist, "SubsetFonts", &pdev->params.SubsetFonts)) < 0 || + (code = param_write_int(plist, "MaxSubsetPct", &pdev->params.MaxSubsetPct)) < 0 + ); + return code; +} + +/* -------- Put parameters -------- */ + +#ifdef HAVE_LIBJPEG +extern stream_state_proc_put_params(s_DCTE_put_params, stream_DCT_state); +#endif /* HAVE_LIBJPEG */ +extern stream_state_proc_put_params(s_CF_put_params, stream_CF_state); +typedef stream_state_proc_put_params((*ss_put_params_t), stream_state); + +private int +psdf_CF_put_params(gs_param_list * plist, stream_state * st) +{ + stream_CFE_state *const ss = (stream_CFE_state *) st; + + (*s_CFE_template.set_defaults) (st); + ss->K = -1; + ss->BlackIs1 = true; + return s_CF_put_params(plist, (stream_CF_state *) ss); +} +#ifdef HAVE_LIBJPEG +private int +psdf_DCT_put_params(gs_param_list * plist, stream_state * ss) +{ + return s_DCTE_put_params(plist, (stream_DCT_state *) ss); +} +#endif /* HAVE_LIBJPEG */ + +/* Compare a C string and a gs_param_string. */ +bool +psdf_key_eq(const gs_param_string * pcs, const char *str) +{ + return (strlen(str) == pcs->size && + !strncmp(str, (const char *)pcs->data, pcs->size)); +} + +/* Put an enumerated value. */ +private int +psdf_put_enum_param(gs_param_list * plist, gs_param_name param_name, + int *pvalue, const char *const pnames[], int ecode) +{ + gs_param_string ens; + int code = param_read_name(plist, param_name, &ens); + + switch (code) { + case 1: + return ecode; + case 0: + { + int i; + + for (i = 0; pnames[i] != 0; ++i) + if (psdf_key_eq(&ens, pnames[i])) { + *pvalue = i; + return 0; + } + } + code = gs_error_rangecheck; + default: + ecode = code; + param_signal_error(plist, param_name, code); + } + return code; +} + +/* Put a Boolean or integer parameter. */ +int +psdf_put_bool_param(gs_param_list * plist, gs_param_name param_name, + bool * pval, int ecode) +{ + int code; + + switch (code = param_read_bool(plist, param_name, pval)) { + default: + ecode = code; + param_signal_error(plist, param_name, ecode); + case 0: + case 1: + break; + } + return ecode; +} +int +psdf_put_int_param(gs_param_list * plist, gs_param_name param_name, + int *pval, int ecode) +{ + int code; + + switch (code = param_read_int(plist, param_name, pval)) { + default: + ecode = code; + param_signal_error(plist, param_name, ecode); + case 0: + case 1: + break; + } + return ecode; +} + +/* Put [~](Always|Never)Embed parameters. */ +private int +psdf_put_embed_param(gs_param_list * plist, gs_param_name notpname, + gs_param_string_array * psa, int ecode) +{ + gs_param_name pname = notpname + 1; + int code; + gs_param_string_array nsa; + +/***** Storage management is incomplete ******/ +/***** Doesn't do incremental add/delete ******/ + switch (code = param_read_name_array(plist, pname, psa)) { + default: + ecode = code; + param_signal_error(plist, pname, ecode); + case 0: + case 1: + break; + } + switch (code = param_read_name_array(plist, notpname, &nsa)) { + default: + ecode = code; + param_signal_error(plist, notpname, ecode); + case 0: + case 1: + break; + } + return ecode; +} + +/* Put an image Dict parameter. */ +private int +psdf_put_image_dict_param(gs_param_list * plist, const gs_param_name pname, + stream_state ** pss, const stream_template * template, + ss_put_params_t put_params, gs_memory_t * mem) +{ + gs_param_dict dict; + stream_state *ss = *pss; + int code; + + switch (code = param_begin_read_dict(plist, pname, &dict, false)) { + default: + param_signal_error(plist, pname, code); + return code; + case 1: + ss = 0; + break; + case 0:{ + /****** + ****** THIS CAUSES A SEGV FOR DCT FILTERS, BECAUSE + ****** THEY DON'T INTIALIZE PROPERLY. + ******/ +#ifdef HAVE_LIBJPEG + if (template != &s_DCTE_template) +#endif /* HAVE_LIBJPEG */ + { + stream_state *ss_new = + s_alloc_state(mem, template->stype, pname); + + if (ss_new == 0) + return_error(gs_error_VMerror); + ss_new->template = template; + if (template->set_defaults) + (*template->set_defaults)(ss_new); + code = (*put_params)(dict.list, ss_new); + if (code < 0) { + param_signal_error(plist, pname, code); + /* Make sure we free the new state. */ + *pss = ss_new; + } else + ss = ss_new; + } + } + param_end_read_dict(plist, pname, &dict); + } + if (*pss != ss) { + if (ss) { + /****** FREE SUBSIDIARY OBJECTS -- HOW? ******/ + gs_free_object(mem, *pss, pname); + } + *pss = ss; + } + return code; +} + +/* Put a set of image-related parameters. */ +private int +psdf_put_image_params(const gx_device_psdf * pdev, gs_param_list * plist, + const psdf_image_param_names * pnames, const psdf_image_filter_name * pifn, + psdf_image_params * params, int ecode) +{ + gs_param_string fs; + + /* + * Since this procedure can be called before the device is open, + * we must use pdev->memory rather than pdev->v_memory. + */ + gs_memory_t *mem = pdev->memory; + gs_param_name pname; + int dsti = params->DownsampleType; + int code; + +#ifdef HAVE_LIBJPEG + if ((pname = pnames->ACSDict) != 0) { + code = psdf_put_image_dict_param(plist, pname, ¶ms->ACSDict, + &s_DCTE_template, + psdf_DCT_put_params, mem); + if (code < 0) + ecode = code; + } +#endif /* HAVE_LIBJPEG */ + ecode = psdf_put_bool_param(plist, pnames->AntiAlias, + ¶ms->AntiAlias, ecode); + if (pnames->AutoFilter) + ecode = psdf_put_bool_param(plist, pnames->AutoFilter, + ¶ms->AutoFilter, ecode); + ecode = psdf_put_int_param(plist, pnames->Depth, + ¶ms->Depth, ecode); + if ((pname = pnames->Dict) != 0) { + const stream_template *template; + ss_put_params_t put_params; + + /* Hack to determine what kind of a Dict we want: */ + if (pnames->Dict[0] == 'M') + template = &s_CFE_template, + put_params = psdf_CF_put_params; +#ifdef HAVE_LIBJPEG + else + template = &s_DCTE_template, + put_params = psdf_DCT_put_params; +#endif /* HAVE_LIBJPEG */ + code = psdf_put_image_dict_param(plist, pname, ¶ms->Dict, + template, put_params, mem); + if (code < 0) + ecode = code; + } + ecode = psdf_put_bool_param(plist, pnames->Downsample, + ¶ms->Downsample, ecode); + if ((ecode = psdf_put_enum_param(plist, pnames->DownsampleType, + &dsti, DownsampleType_names, + ecode)) >= 0 + ) + params->DownsampleType = (enum psdf_downsample_type)dsti; + ecode = psdf_put_bool_param(plist, pnames->Encode, + ¶ms->Encode, ecode); + switch (code = param_read_string(plist, pnames->Filter, &fs)) { + case 0: + { + const psdf_image_filter_name *pn = pifn; + + while (pn->pname != 0 && !psdf_key_eq(&fs, pn->pname)) + pn++; + if (pn->pname == 0 || pn->min_version > pdev->version) { + ecode = gs_error_rangecheck; + goto ipe; + } + params->Filter = pn->pname; + params->filter_template = pn->template; + break; + } + default: + ecode = code; + ipe:param_signal_error(plist, pnames->Filter, ecode); + case 1: + break; + } + ecode = psdf_put_int_param(plist, pnames->Resolution, + ¶ms->Resolution, ecode); + if (ecode >= 0) { /* Force parameters to acceptable values. */ + if (params->Resolution < 1) + params->Resolution = 1; + switch (params->Depth) { + default: + params->Depth = -1; + case 1: + case 2: + case 4: + case 8: + case -1: + break; + } + } + return ecode; +} + +/* Put parameters. */ +int +gdev_psdf_put_params(gx_device * dev, gs_param_list * plist) +{ + gx_device_psdf *pdev = (gx_device_psdf *) dev; + int ecode = 0; + int code; + gs_param_name param_name; + psdf_distiller_params params; + + /* General parameters. */ + + params = pdev->params; + + ecode = psdf_put_bool_param(plist, "ASCII85EncodePages", + ¶ms.ASCII85EncodePages, ecode); + { + int arpi = params.AutoRotatePages; + + ecode = psdf_put_enum_param(plist, "AutoRotatePages", &arpi, + AutoRotatePages_names, ecode); + params.AutoRotatePages = (enum psdf_auto_rotate_pages)arpi; + } + ecode = psdf_put_bool_param(plist, "CompressPages", + ¶ms.CompressPages, ecode); + switch (code = param_read_long(plist, (param_name = "ImageMemory"), ¶ms.ImageMemory)) { + default: + ecode = code; + param_signal_error(plist, param_name, ecode); + case 0: + case 1: + break; + } + ecode = psdf_put_bool_param(plist, "LZWEncodePages", + ¶ms.LZWEncodePages, ecode); + ecode = psdf_put_bool_param(plist, "PreserveHalftoneInfo", + ¶ms.PreserveHalftoneInfo, ecode); + ecode = psdf_put_bool_param(plist, "PreserveOPIComments", + ¶ms.PreserveOPIComments, ecode); + ecode = psdf_put_bool_param(plist, "PreserveOverprintSettings", + ¶ms.PreserveOverprintSettings, ecode); + { + int tfii = params.TransferFunctionInfo; + + ecode = psdf_put_enum_param(plist, "TransferFunctionInfo", &tfii, + TransferFunctionInfo_names, ecode); + params.TransferFunctionInfo = (enum psdf_transfer_function_info)tfii; + } + { + int ucrbgi = params.UCRandBGInfo; + + ecode = psdf_put_enum_param(plist, "UCRandBGInfo", &ucrbgi, + UCRandBGInfo_names, ecode); + params.UCRandBGInfo = (enum psdf_ucr_and_bg_info)ucrbgi; + } +#ifdef HAVE_LIBZ + ecode = psdf_put_bool_param(plist, "UseFlateCompression", + ¶ms.UseFlateCompression, ecode); +#endif /* HAVE_LIBZ */ + + /* Color sampled image parameters */ + + ecode = psdf_put_image_params(pdev, plist, &Color_names, Poly_filters, + ¶ms.ColorImage, ecode); + { + int ccsi = params.ColorConversionStrategy; + + ecode = psdf_put_enum_param(plist, "ColorConversionStrategy", &ccsi, + ColorConversionStrategy_names, ecode); + params.ColorConversionStrategy = + (enum psdf_color_conversion_strategy)ccsi; + } + ecode = psdf_put_bool_param(plist, "ConvertCMYKImagesToRGB", + ¶ms.ConvertCMYKImagesToRGB, ecode); + ecode = psdf_put_bool_param(plist, "ConvertImagesToIndexed", + ¶ms.ConvertImagesToIndexed, ecode); + + /* Gray sampled image parameters */ + + ecode = psdf_put_image_params(pdev, plist, &Gray_names, Poly_filters, + ¶ms.GrayImage, ecode); + + /* Mono sampled image parameters */ + + ecode = psdf_put_image_params(pdev, plist, &Mono_names, Mono_filters, + ¶ms.MonoImage, ecode); + + /* Font embedding parameters */ + + ecode = psdf_put_embed_param(plist, "~AlwaysEmbed", + ¶ms.AlwaysEmbed, ecode); + ecode = psdf_put_embed_param(plist, "~NeverEmbed", + ¶ms.NeverEmbed, ecode); + ecode = psdf_put_bool_param(plist, "EmbedAllFonts", + ¶ms.EmbedAllFonts, ecode); + ecode = psdf_put_bool_param(plist, "SubsetFonts", + ¶ms.SubsetFonts, ecode); + ecode = psdf_put_int_param(plist, "MaxSubsetPct", + ¶ms.MaxSubsetPct, ecode); + + if (ecode < 0) + return ecode; + code = gdev_vector_put_params(dev, plist); + if (code < 0) + return code; + + pdev->params = params; /* OK to update now */ + return 0; +} diff --git a/pstoraster/gdevpsds.c b/pstoraster/gdevpsds.c new file mode 100644 index 0000000000..da128b5b7d --- /dev/null +++ b/pstoraster/gdevpsds.c @@ -0,0 +1,470 @@ +/* Copyright (C) 1997, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Image processing streams for PostScript and PDF writers */ +#include "gx.h" +#include "memory_.h" +#include "gserrors.h" +#include "gxdcconv.h" +#include "gdevpsds.h" + +/* ---------------- Convert between 1/2/4 and 8 bits ---------------- */ +gs_private_st_simple(st_1248_state, stream_1248_state, "stream_1248_state"); + +/* Initialize the state. */ +private int +s_1_init(stream_state * st) +{ + stream_1248_state *const ss = (stream_1248_state *) st; + + ss->left = ss->samples_per_row; + ss->bits_per_sample = 1; + return 0; +} +private int +s_2_init(stream_state * st) +{ + stream_1248_state *const ss = (stream_1248_state *) st; + + ss->left = ss->samples_per_row; + ss->bits_per_sample = 2; + return 0; +} +private int +s_4_init(stream_state * st) +{ + stream_1248_state *const ss = (stream_1248_state *) st; + + ss->left = ss->samples_per_row; + ss->bits_per_sample = 4; + return 0; +} + +/* Process one buffer. */ +#define BEGIN_1248\ + stream_1248_state * const ss = (stream_1248_state *)st;\ + const byte *p = pr->ptr;\ + const byte *rlimit = pr->limit;\ + byte *q = pw->ptr;\ + byte *wlimit = pw->limit;\ + uint left = ss->left;\ + int status;\ + int n +#define END_1248\ + pr->ptr = p;\ + pw->ptr = q;\ + ss->left = left;\ + return status + +/* N-to-8 expansion */ +#define FOREACH_N_8(in, nout)\ + status = 0;\ + for ( ; p < rlimit; left -= n, q += n, ++p ) {\ + byte in = p[1];\ + n = min(left, nout);\ + if ( wlimit - q < n ) {\ + status = 1;\ + break;\ + }\ + switch ( n ) {\ + case 0: left = ss->samples_per_row; --p; continue; +#define END_FOREACH_N_8\ + }\ + } +private int +s_N_8_process(stream_state * st, stream_cursor_read * pr, + stream_cursor_write * pw, bool last) +{ + BEGIN_1248; + + switch (ss->bits_per_sample) { + + case 1:{ + FOREACH_N_8(in, 8) + case 8: + q[8] = (byte) - (in & 1); + case 7: + q[7] = (byte) - ((in >> 1) & 1); + case 6: + q[6] = (byte) - ((in >> 2) & 1); + case 5: + q[5] = (byte) - ((in >> 3) & 1); + case 4: + q[4] = (byte) - ((in >> 4) & 1); + case 3: + q[3] = (byte) - ((in >> 5) & 1); + case 2: + q[2] = (byte) - ((in >> 6) & 1); + case 1: + q[1] = (byte) - (in >> 7); + END_FOREACH_N_8; + } + break; + + case 2:{ + static const byte b2[4] = + {0x00, 0x55, 0xaa, 0xff}; + + FOREACH_N_8(in, 4) + case 4: + q[4] = b2[in & 3]; + case 3: + q[3] = b2[(in >> 2) & 3]; + case 2: + q[2] = b2[(in >> 4) & 3]; + case 1: + q[1] = b2[in >> 6]; + END_FOREACH_N_8; + } + break; + + case 4:{ + static const byte b4[16] = + { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff + }; + + FOREACH_N_8(in, 2) + case 2: + q[2] = b4[in & 0xf]; + case 1: + q[1] = b4[in >> 4]; + END_FOREACH_N_8; + } + break; + + default: + return ERRC; + } + + END_1248; +} + +/* 8-to-N reduction */ +#define FOREACH_8_N(out, nin)\ + byte out;\ + status = 1;\ + for ( ; q < wlimit; left -= n, p += n, ++q ) {\ + n = min(left, nin);\ + if ( rlimit - p < n ) {\ + status = 0;\ + break;\ + }\ + out = 0;\ + switch ( n ) {\ + case 0: left = ss->samples_per_row; --q; continue; +#define END_FOREACH_8_N\ + q[1] = out;\ + }\ + } +private int +s_8_N_process(stream_state * st, stream_cursor_read * pr, + stream_cursor_write * pw, bool last) +{ + BEGIN_1248; + + switch (ss->bits_per_sample) { + + case 1:{ + FOREACH_8_N(out, 8) + case 8: + out = p[8] >> 7; + case 7: + out |= (p[7] >> 7) << 1; + case 6: + out |= (p[6] >> 7) << 2; + case 5: + out |= (p[5] >> 7) << 3; + case 4: + out |= (p[4] >> 7) << 4; + case 3: + out |= (p[3] >> 7) << 5; + case 2: + out |= (p[2] >> 7) << 6; + case 1: + out |= p[1] & 0x80; + END_FOREACH_8_N; + } + break; + + case 2:{ + FOREACH_8_N(out, 4) + case 4: + out |= p[4] >> 6; + case 3: + out |= (p[3] >> 6) << 2; + case 2: + out |= (p[2] >> 6) << 4; + case 1: + out |= p[1] & 0xc0; + END_FOREACH_8_N; + } + break; + + case 4:{ + FOREACH_8_N(out, 2) + case 2: + out |= p[2] >> 4; + case 1: + out |= p[1] & 0xf0; + END_FOREACH_8_N; + } + break; + + default: + return ERRC; + } + + END_1248; +} + +const stream_template s_1_8_template = +{ + &st_1248_state, s_1_init, s_N_8_process, 1, 8 +}; +const stream_template s_2_8_template = +{ + &st_1248_state, s_2_init, s_N_8_process, 1, 4 +}; +const stream_template s_4_8_template = +{ + &st_1248_state, s_4_init, s_N_8_process, 1, 2 +}; + +const stream_template s_8_1_template = +{ + &st_1248_state, s_1_init, s_8_N_process, 8, 1 +}; +const stream_template s_8_2_template = +{ + &st_1248_state, s_2_init, s_8_N_process, 4, 1 +}; +const stream_template s_8_4_template = +{ + &st_1248_state, s_4_init, s_8_N_process, 2, 1 +}; + +/* ---------------- CMYK => RGB conversion ---------------- */ + +private_st_C2R_state(); + +/* Process one buffer. */ +private int +s_C2R_process(stream_state * st, stream_cursor_read * pr, + stream_cursor_write * pw, bool last) +{ + stream_C2R_state *const ss = (stream_C2R_state *) st; + const byte *p = pr->ptr; + const byte *rlimit = pr->limit; + byte *q = pw->ptr; + byte *wlimit = pw->limit; + + for (; rlimit - p >= 4 && wlimit - q >= 3; p += 4, q += 3) { + byte bc = p[1], bm = p[2], by = p[3], bk = p[4]; + frac rgb[3]; + + color_cmyk_to_rgb(byte2frac(bc), byte2frac(bm), byte2frac(by), + byte2frac(bk), ss->pis, rgb); + q[1] = frac2byte(rgb[0]); + q[2] = frac2byte(rgb[1]); + q[3] = frac2byte(rgb[2]); + } + pr->ptr = p; + pw->ptr = q; + return (rlimit - p < 4 ? 0 : 1); +} + +const stream_template s_C2R_template = +{ + &st_C2R_state, 0 /*NULL */ , s_C2R_process, 4, 3 +}; + +/* ---------------- Downsampling ---------------- */ + +private void +s_Downsample_set_defaults(register stream_state * st) +{ + stream_Downsample_state *const ss = + (stream_Downsample_state *) st; + + s_Downsample_set_defaults_inline(ss); +} + +/* Subsample */ +/****** DOESN'T IMPLEMENT padY YET ******/ + +gs_private_st_simple(st_Subsample_state, stream_Subsample_state, + "stream_Subsample_state"); + +/* Initialize the state. */ +private int +s_Subsample_init(stream_state * st) +{ + stream_Subsample_state *const ss = (stream_Subsample_state *) st; + + ss->x = ss->y = 0; + return 0; +} + +/* Process one buffer. */ +private int +s_Subsample_process(stream_state * st, stream_cursor_read * pr, + stream_cursor_write * pw, bool last) +{ + stream_Subsample_state *const ss = (stream_Subsample_state *) st; + const byte *p = pr->ptr; + const byte *rlimit = pr->limit; + byte *q = pw->ptr; + byte *wlimit = pw->limit; + int spp = ss->Colors; + int width = ss->Columns; + int xf = ss->XFactor, yf = ss->YFactor; + int xf2 = xf / 2, yf2 = yf / 2; + int xlimit = (width / xf) * xf; + int xlast = (ss->padX && xlimit < width ? xlimit + (width % xf) / 2 : -1); + int x = ss->x, y = ss->y; + int status = 0; + + for (; rlimit - p >= spp; p += spp) { + if (y == yf2 && ((x % xf == xf2 && x < xlimit) || x == xlast)) { + if (wlimit - q < spp) { + status = 1; + break; + } + memcpy(q + 1, p + 1, spp); + q += spp; + } + if (++x == width) { + x = 0; + if (++y == yf) { + y = 0; + } + } + } + pr->ptr = p; + pw->ptr = q; + ss->x = x, ss->y = y; + return status; +} + +const stream_template s_Subsample_template = +{ + &st_Subsample_state, s_Subsample_init, s_Subsample_process, 4, 4, + 0 /* NULL */, s_Downsample_set_defaults +}; + +/* Average */ + +private_st_Average_state(); + +/* Initialize the state. */ +private int +s_Average_init(stream_state * st) +{ + stream_Average_state *const ss = (stream_Average_state *) st; + + ss->sum_size = + ss->Colors * ((ss->Columns + ss->XFactor - 1) / ss->XFactor); + ss->copy_size = ss->sum_size - + (ss->padX || (ss->Columns % ss->XFactor == 0) ? 0 : ss->Colors); + ss->sums = + (uint *)gs_alloc_byte_array(st->memory, ss->sum_size, + sizeof(uint), "Average sums"); + if (ss->sums == 0) + return ERRC; /****** WRONG ******/ + memset(ss->sums, 0, ss->sum_size * sizeof(uint)); + return s_Subsample_init(st); +} + +/* Release the state. */ +private void +s_Average_release(stream_state * st) +{ + stream_Average_state *const ss = (stream_Average_state *) st; + + gs_free_object(st->memory, ss->sums, "Average sums"); +} + +/* Process one buffer. */ +private int +s_Average_process(stream_state * st, stream_cursor_read * pr, + stream_cursor_write * pw, bool last) +{ + stream_Average_state *const ss = (stream_Average_state *) st; + const byte *p = pr->ptr; + const byte *rlimit = pr->limit; + byte *q = pw->ptr; + byte *wlimit = pw->limit; + int spp = ss->Colors; + int width = ss->Columns; + int xf = ss->XFactor, yf = ss->YFactor; + int x = ss->x, y = ss->y; + uint *sums = ss->sums; + int status = 0; + +top: + if (y == yf || (last && p >= rlimit && ss->padY && y != 0)) { + /* We're copying averaged values to the output. */ + int ncopy = min(ss->copy_size - x, wlimit - q); + + if (ncopy) { + int scale = xf * y; + + while (--ncopy >= 0) + *++q = (byte) (sums[x++] / scale); + } + if (x < ss->copy_size) { + status = 1; + goto out; + } + /* Done copying. */ + x = y = 0; + memset(sums, 0, ss->sum_size * sizeof(uint)); + } + while (rlimit - p >= spp) { + uint *bp = sums + x / xf * spp; + int i; + + for (i = spp; --i >= 0;) + *bp++ += *++p; + if (++x == width) { + x = 0; + ++y; + goto top; + } + } +out: + pr->ptr = p; + pw->ptr = q; + ss->x = x, ss->y = y; + return status; +} + +const stream_template s_Average_template = +{ + &st_Average_state, s_Average_init, s_Average_process, 4, 4, + s_Average_release, s_Downsample_set_defaults +}; diff --git a/pstoraster/gdevpsds.h b/pstoraster/gdevpsds.h new file mode 100644 index 0000000000..772c1ff535 --- /dev/null +++ b/pstoraster/gdevpsds.h @@ -0,0 +1,110 @@ +/* Copyright (C) 1997, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Image processing stream interface for PostScript and PDF writers */ + +#ifndef gdevpsds_INCLUDED +# define gdevpsds_INCLUDED + +#include "strimpl.h" + +/* Convert between 1/2/4 bits and 8 bits. */ +typedef struct stream_1248_state_s { + stream_state_common; + /* The following are set at initialization time. */ + uint samples_per_row; /* >0 */ + int bits_per_sample; /* 1, 2, 4 */ + /* The following are updated dynamically. */ + uint left; /* # of samples left in current row */ +} stream_1248_state; + +/* Expand N (1, 2, 4) bits to 8. */ +extern const stream_template s_1_8_template; +extern const stream_template s_2_8_template; +extern const stream_template s_4_8_template; + +/* Reduce 8 bits to N (1, 2, 4) */ +extern const stream_template s_8_1_template; +extern const stream_template s_8_2_template; +extern const stream_template s_8_4_template; + +/* Initialize an expansion or reduction stream. */ +#define s_1248_init(ss, Columns, samples_per_pixel)\ + ((ss)->samples_per_row = (Columns) * (samples_per_pixel),\ + (*(ss)->template->init)((stream_state *)(ss))) + +/* Convert (8-bit) CMYK to RGB. */ +typedef struct stream_C2R_state_s { + stream_state_common; + /* The following are set at initialization time. */ + const gs_imager_state *pis; /* for UCR & BG */ +} stream_C2R_state; + +#define private_st_C2R_state() /* in gdevpsds.c */\ + gs_private_st_ptrs1(st_C2R_state, stream_C2R_state, "stream_C2R_state",\ + c2r_enum_ptrs, c2r_reloc_ptrs, pis) +extern const stream_template s_C2R_template; + +#define s_C2R_init(ss, pisv)\ + ((ss)->pis = (pisv), 0) + +/* Downsample, possibly with anti-aliasing. */ +#define stream_Downsample_state_common\ + stream_state_common;\ + /* The client sets the following before initialization. */\ + int Colors;\ + int Columns; /* # of input columns */\ + int XFactor, YFactor;\ + bool AntiAlias;\ + bool padX, padY; /* keep excess samples */\ + /* The following are updated dynamically. */\ + int x, y /* position within input image */ +#define s_Downsample_set_defaults_inline(ss)\ + ((ss)->AntiAlias = (ss)->padX = (ss)->padY = false) +typedef struct stream_Downsample_state_s { + stream_Downsample_state_common; +} stream_Downsample_state; + +/* Subsample */ +/****** Subsample DOESN'T IMPLEMENT padY YET ******/ +typedef struct stream_Subsample_state_s { + stream_Downsample_state_common; +} stream_Subsample_state; +extern const stream_template s_Subsample_template; + +/* Average */ +typedef struct stream_Average_state_s { + stream_Downsample_state_common; + uint sum_size; + uint copy_size; + uint *sums; /* accumulated sums for average */ +} stream_Average_state; + +#define private_st_Average_state() /* in gdevpsds.c */\ + gs_private_st_ptrs1(st_Average_state, stream_Average_state,\ + "stream_Average_state", avg_enum_ptrs, avg_reloc_ptrs, sums) +extern const stream_template s_Average_template; + +#endif /* gdevpsds_INCLUDED */ diff --git a/pstoraster/gdevpstr.h b/pstoraster/gdevpstr.h new file mode 100644 index 0000000000..12156c39ad --- /dev/null +++ b/pstoraster/gdevpstr.h @@ -0,0 +1,90 @@ +/* Copyright (C) 1997, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Stream output for PostScript- and PDF-writing drivers. */ + +#ifndef gdevpstr_INCLUDED +# define gdevpstr_INCLUDED + +/* Define an opaque type for streams. */ +#ifndef stream_DEFINED +# define stream_DEFINED +typedef struct stream_s stream; + +#endif + +/* Put a character on a stream. */ +#define pputc(s, c) spputc(s, c) + +/* Put a byte array on a stream. */ +int pwrite(P3(stream * s, const void *ptr, uint count)); + +/* Put a string on a stream. */ +int pputs(P2(stream * s, const char *str)); + +/* + * Print (a) floating point number(s) using a format. This is needed + * because %f format always prints a fixed number of digits after the + * decimal point, and %g format may use %e format, which PDF disallows. + * These functions return a pointer to the next %-element of the format, or + * to the terminating 0. + */ +const char *pprintg1(P3(stream * s, const char *format, floatp v)); +const char *pprintg2(P4(stream * s, const char *format, floatp v1, floatp v2)); +const char *pprintg3(P5(stream * s, const char *format, + floatp v1, floatp v2, floatp v3)); +const char *pprintg4(P6(stream * s, const char *format, + floatp v1, floatp v2, floatp v3, floatp v4)); +const char *pprintg6(P8(stream * s, const char *format, + floatp v1, floatp v2, floatp v3, floatp v4, + floatp v5, floatp v6)); + +/* + * The rest of these printing functions exist solely because the ANSI C + * "standard" for functions with a variable number of arguments is not + * implemented properly or consistently across compilers. + */ +/* Print (an) int value(s) using a format. */ +const char *pprintd1(P3(stream * s, const char *format, int v)); +const char *pprintd2(P4(stream * s, const char *format, int v1, int v2)); +const char *pprintd3(P5(stream * s, const char *format, + int v1, int v2, int v3)); +const char *pprintd4(P6(stream * s, const char *format, + int v1, int v2, int v3, int v4)); + +/* Print a long value using a format. */ +const char *pprintld1(P3(stream * s, const char *format, long v)); +const char *pprintld2(P4(stream * s, const char *format, long v1, long v2)); +const char *pprintld3(P5(stream * s, const char *format, + long v1, long v2, long v3)); + +/* Print (a) string(s) using a format. */ +const char *pprints1(P3(stream * s, const char *format, const char *str)); +const char *pprints2(P4(stream * s, const char *format, + const char *str1, const char *str2)); +const char *pprints3(P5(stream * s, const char *format, + const char *str1, const char *str2, const char *str3)); + +#endif /* gdevpstr_INCLUDED */ diff --git a/pstoraster/gdevpxop.h b/pstoraster/gdevpxop.h new file mode 100644 index 0000000000..9b61a01e0a --- /dev/null +++ b/pstoraster/gdevpxop.h @@ -0,0 +1,114 @@ +/* Copyright (C) 1997, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Operator and other tag definitions for PCL XL */ + +#ifndef gdevpxop_INCLUDED +# define gdevpxop_INCLUDED + +typedef enum { +/*0x */ + pxtNull = 0x00, pxt01, pxt02, pxt03, + pxt04, pxt05, pxt06, pxt07, + pxt08, pxtHT, pxtLF, pxtVT, + pxtFF, pxtCR, pxt0e, pxt0f, +/*1x */ + pxt10, pxt11, pxt12, pxt13, + pxt14, pxt15, pxt16, pxt17, + pxt18, pxt19, pxt1a, pxt1b, + pxt1c, pxt1d, pxt1e, pxt1f, +/*2x */ + pxtSpace, pxt21, pxt22, pxt23, + pxt24, pxt25, pxt26, pxt_beginASCII, + pxt_beginBinaryMSB, pxt_beginBinaryLSB, pxt2a, pxt2b, + pxt2c, pxt2d, pxt2e, pxt2f, +/*3x */ + pxt30, pxt31, pxt32, pxt33, + pxt34, pxt35, pxt36, pxt37, + pxt38, pxt39, pxt3a, pxt3b, + pxt3c, pxt3d, pxt3e, pxt3f, +/*4x */ + pxt40, pxtBeginSession, pxtEndSession, pxtBeginPage, + pxtEndPage, pxt45, pxt46, pxtComment, + pxtOpenDataSource, pxtCloseDataSource, pxt4a, pxt4b, + pxt4c, pxt4d, pxt4e, pxtBeginFontHeader, +/*5x */ + pxtReadFontHeader, pxtEndFontHeader, pxtBeginChar, pxtReadChar, + pxtEndChar, pxtRemoveFont, pxtSetCharAttributes /*2.0 */ , pxt57, + pxt58, pxt59, pxt5a, pxtBeginStream, + pxtReadStream, pxtEndStream, pxtExecStream, pxtRemoveStream /*2.0 */ , +/*6x */ + pxtPopGS, pxtPushGS, pxtSetClipReplace, pxtSetBrushSource, + pxtSetCharAngle, pxtSetCharScale, pxtSetCharShear, pxtSetClipIntersect, + pxtSetClipRectangle, pxtSetClipToPage, pxtSetColorSpace, pxtSetCursor, + pxtSetCursorRel, pxtSetHalftoneMethod, pxtSetFillMode, pxtSetFont, +/*7x */ + pxtSetLineDash, pxtSetLineCap, pxtSetLineJoin, pxtSetMiterLimit, + pxtSetPageDefaultCTM, pxtSetPageOrigin, pxtSetPageRotation, pxtSetPageScale, + pxtSetPaintTxMode, pxtSetPenSource, pxtSetPenWidth, pxtSetROP, + pxtSetSourceTxMode, pxtSetCharBoldValue, pxt7e, pxtSetClipMode, +/*8x */ + pxtSetPathToClip, pxtSetCharSubMode, pxt82, pxt83, + pxtCloseSubPath, pxtNewPath, pxtPaintPath, pxt87, + pxt88, pxt89, pxt8a, pxt8b, + pxt8c, pxt8d, pxt8e, pxt8f, +/*9x */ + pxt90, pxtArcPath, pxt92, pxtBezierPath, + pxt94, pxtBezierRelPath, pxtChord, pxtChordPath, + pxtEllipse, pxtEllipsePath, pxt9a, pxtLinePath, + pxt9c, pxtLineRelPath, pxtPie, pxtPiePath, +/*ax */ + pxtRectangle, pxtRectanglePath, pxtRoundRectangle, pxtRoundRectanglePath, + pxta4, pxta5, pxta6, pxta7, + pxtText, pxtTextPath, pxtaa, pxtab, + pxtac, pxtad, pxtae, pxtaf, +/*bx */ + pxtBeginImage, pxtReadImage, pxtEndImage, pxtBeginRastPattern, + pxtReadRastPattern, pxtEndRastPattern, pxtBeginScan, pxtb7, + pxtEndScan, pxtScanLineRel, pxtba, pxtbb, + pxtbc, pxtbd, pxtbe, pxtbf, +/*cx */ + pxt_ubyte, pxt_uint16, pxt_uint32, pxt_sint16, + pxt_sint32, pxt_real32, pxtc6, pxtc7, + pxt_ubyte_array, pxt_uint16_array, pxt_uint32_array, pxt_sint16_array, + pxt_sint32_array, pxt_real32_array, pxtce, pxtcf, +/*dx */ + pxt_ubyte_xy, pxt_uint16_xy, pxt_uint32_xy, pxt_sint16_xy, + pxt_sint32_xy, pxt_real32_xy, pxtd6, pxtd7, + pxtd8, pxtd9, pxtda, pxtdb, + pxtdc, pxtdd, pxtde, pxtdf, +/*ex */ + pxt_ubyte_box, pxt_uint16_box, pxt_uint32_box, pxt_sint16_box, + pxt_sint32_box, pxt_real32_box, pxte6, pxte7, + pxte8, pxte9, pxtea, pxteb, + pxtec, pxted, pxtee, pxtef, +/*fx */ + pxtf0, pxtf1, pxtf2, pxtf3, + pxtf4, pxtf5, pxtf6, pxtf7, + pxt_attr_ubyte, pxt_attr_uint16, pxt_dataLength, pxt_dataLengthByte, + pxtfc, pxtfd, pxtfe, pxtff +} px_tag_t; + +#endif /* gdevpxop_INCLUDED */ diff --git a/pstoraster/gdevvec.c b/pstoraster/gdevvec.c new file mode 100644 index 0000000000..80adbb7e84 --- /dev/null +++ b/pstoraster/gdevvec.c @@ -0,0 +1,905 @@ +/* Copyright (C) 1997, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Utilities for "vector" devices */ +#include "math_.h" +#include "memory_.h" +#include "string_.h" +#include "gx.h" +#include "gp.h" +#include "gserrors.h" +#include "gsparam.h" +#include "gsutil.h" +#include "gxfixed.h" +#include "gdevvec.h" +#include "gscspace.h" +#include "gxdcolor.h" +#include "gxpaint.h" /* requires gx_path, ... */ +#include "gzpath.h" +#include "gzcpath.h" + +/****** + ****** NOTE: EVERYTHING IN THIS FILE IS SUBJECT TO CHANGE WITHOUT NOTICE. + ****** USE AT YOUR OWN RISK. + ******/ + +/* Structure descriptors */ +public_st_device_vector(); +public_st_vector_image_enum(); + +/* ================ Default implementations of vector procs ================ */ + +int +gdev_vector_setflat(gx_device_vector * vdev, floatp flatness) +{ + return 0; +} + +int +gdev_vector_dopath(gx_device_vector * vdev, const gx_path * ppath, + gx_path_type_t type) +{ + bool do_close = (type & gx_path_type_stroke) != 0; + gs_fixed_rect rect; + gs_point scale; + double x_start = 0, y_start = 0, x_prev, y_prev; + bool first = true; + gs_path_enum cenum; + int code; + + if (gx_path_is_rectangle(ppath, &rect)) + return (*vdev_proc(vdev, dorect)) (vdev, rect.p.x, rect.p.y, rect.q.x, + rect.q.y, type); + scale = vdev->scale; + code = (*vdev_proc(vdev, beginpath)) (vdev, type); + gx_path_enum_init(&cenum, ppath); + for (;;) { + fixed vs[6]; + int pe_op = gx_path_enum_next(&cenum, (gs_fixed_point *) vs); + double x, y; + + sw:switch (pe_op) { + case 0: /* done */ + return (*vdev_proc(vdev, endpath)) (vdev, type); + case gs_pe_moveto: + code = (*vdev_proc(vdev, moveto)) + (vdev, x_prev, y_prev, (x = fixed2float(vs[0]) / scale.x), + (y = fixed2float(vs[1]) / scale.y), type); + if (first) + x_start = x, y_start = y, first = false; + break; + case gs_pe_lineto: + code = (*vdev_proc(vdev, lineto)) + (vdev, x_prev, y_prev, (x = fixed2float(vs[0]) / scale.x), + (y = fixed2float(vs[1]) / scale.y), type); + break; + case gs_pe_curveto: + code = (*vdev_proc(vdev, curveto)) + (vdev, x_prev, y_prev, + fixed2float(vs[0]) / scale.x, + fixed2float(vs[1]) / scale.y, + fixed2float(vs[2]) / scale.x, + fixed2float(vs[3]) / scale.y, + (x = fixed2float(vs[4]) / scale.x), + (y = fixed2float(vs[5]) / scale.y), + type); + break; + case gs_pe_closepath: + x = x_start, y = y_start; + if (do_close) { + code = (*vdev_proc(vdev, closepath)) + (vdev, x_prev, y_prev, x_start, y_start, type); + break; + } + pe_op = gx_path_enum_next(&cenum, (gs_fixed_point *) vs); + if (pe_op != 0) { + code = (*vdev_proc(vdev, closepath)) + (vdev, x_prev, y_prev, x_start, y_start, type); + if (code < 0) + return code; + goto sw; + } + return (*vdev_proc(vdev, endpath)) (vdev, type); + default: /* can't happen */ + return_error(gs_error_unknownerror); + } + if (code < 0) + return code; + x_prev = x, y_prev = y; + } +} + +int +gdev_vector_dorect(gx_device_vector * vdev, fixed x0, fixed y0, fixed x1, + fixed y1, gx_path_type_t type) +{ + int code = (*vdev_proc(vdev, beginpath)) (vdev, type); + + if (code < 0) + return code; + code = gdev_vector_write_rectangle(vdev, x0, y0, x1, y1, + (type & gx_path_type_stroke) != 0, + gx_rect_x_first); + if (code < 0) + return code; + return (*vdev_proc(vdev, endpath)) (vdev, type); +} + +/* ================ Utility procedures ================ */ + +/* Recompute the cached color values. */ +private void +gdev_vector_load_cache(gx_device_vector * vdev) +{ + vdev->black = gx_device_black((gx_device *)vdev); + vdev->white = gx_device_white((gx_device *)vdev); +} + +/* Initialize the state. */ +void +gdev_vector_init(gx_device_vector * vdev) +{ + gdev_vector_reset(vdev); + vdev->scale.x = vdev->scale.y = 1.0; + vdev->in_page = false; + gdev_vector_load_cache(vdev); +} + +/* Reset the remembered graphics state. */ +void +gdev_vector_reset(gx_device_vector * vdev) +{ + static const gs_imager_state state_initial = + {gs_imager_state_initial(1)}; + + vdev->state = state_initial; + color_unset(&vdev->fill_color); + color_unset(&vdev->stroke_color); + vdev->clip_path_id = + vdev->no_clip_path_id = gs_next_ids(1); +} + +/* Open the output file and stream. */ +int +gdev_vector_open_file_bbox(gx_device_vector * vdev, uint strmbuf_size, + bool bbox) +{ /* Open the file as positionable if possible. */ + int code = gx_device_open_output_file((gx_device *) vdev, vdev->fname, + true, true, &vdev->file); + + if (code < 0) + return code; + if ((vdev->strmbuf = gs_alloc_bytes(vdev->v_memory, strmbuf_size, + "vector_open(strmbuf)")) == 0 || + (vdev->strm = s_alloc(vdev->v_memory, + "vector_open(strm)")) == 0 || + (bbox && + (vdev->bbox_device = + gs_alloc_struct_immovable(vdev->v_memory, + gx_device_bbox, &st_device_bbox, + "vector_open(bbox_device)")) == 0) + ) { + if (vdev->bbox_device) + gs_free_object(vdev->v_memory, vdev->bbox_device, + "vector_open(bbox_device)"); + vdev->bbox_device = 0; + if (vdev->strm) + gs_free_object(vdev->v_memory, vdev->strm, + "vector_open(strm)"); + vdev->strm = 0; + if (vdev->strmbuf) + gs_free_object(vdev->v_memory, vdev->strmbuf, + "vector_open(strmbuf)"); + vdev->strmbuf = 0; + fclose(vdev->file); + vdev->file = 0; + return_error(gs_error_VMerror); + } + vdev->strmbuf_size = strmbuf_size; + swrite_file(vdev->strm, vdev->file, vdev->strmbuf, strmbuf_size); + /* + * We don't want finalization to close the file, but we do want it + * to flush the stream buffer. + */ + vdev->strm->procs.close = vdev->strm->procs.flush; + if (vdev->bbox_device) { + gx_device_bbox_init(vdev->bbox_device, NULL); + gx_device_set_resolution((gx_device *) vdev->bbox_device, + vdev->HWResolution[0], + vdev->HWResolution[1]); + /* Do the right thing about upright vs. inverted. */ + /* (This is dangerous in general, since the procedure */ + /* might reference non-standard elements.) */ + set_dev_proc(vdev->bbox_device, get_initial_matrix, + dev_proc(vdev, get_initial_matrix)); + (*dev_proc(vdev->bbox_device, open_device)) + ((gx_device *) vdev->bbox_device); + } + return 0; +} + +/* Get the current stream, calling beginpage if in_page is false. */ +stream * +gdev_vector_stream(gx_device_vector * vdev) +{ + if (!vdev->in_page) { + (*vdev_proc(vdev, beginpage)) (vdev); + vdev->in_page = true; + } + return vdev->strm; +} + +/* Compare two drawing colors. */ +/* Right now we don't attempt to handle non-pure colors. */ +private bool +drawing_color_eq(const gx_drawing_color * pdc1, const gx_drawing_color * pdc2) +{ + return (gx_dc_is_pure(pdc1) ? + gx_dc_is_pure(pdc2) && + gx_dc_pure_color(pdc1) == gx_dc_pure_color(pdc2) : + gx_dc_is_null(pdc1) ? + gx_dc_is_null(pdc2) : + false); +} + +/* Update the logical operation. */ +int +gdev_vector_update_log_op(gx_device_vector * vdev, gs_logical_operation_t lop) +{ + gs_logical_operation_t diff = lop ^ vdev->state.log_op; + + if (diff != 0) { + int code = (*vdev_proc(vdev, setlogop)) (vdev, lop, diff); + + if (code < 0) + return code; + vdev->state.log_op = lop; + } + return 0; +} + +/* Update the fill color. */ +int +gdev_vector_update_fill_color(gx_device_vector * vdev, + const gx_drawing_color * pdcolor) +{ + if (!drawing_color_eq(pdcolor, &vdev->fill_color)) { + int code = (*vdev_proc(vdev, setfillcolor)) (vdev, pdcolor); + + if (code < 0) + return code; + vdev->fill_color = *pdcolor; + } + return 0; +} + +/* Update the state for filling a region. */ +private int +update_fill(gx_device_vector * vdev, const gx_drawing_color * pdcolor, + gs_logical_operation_t lop) +{ + int code = gdev_vector_update_fill_color(vdev, pdcolor); + + if (code < 0) + return code; + return gdev_vector_update_log_op(vdev, lop); +} + +/* Bring state up to date for filling. */ +int +gdev_vector_prepare_fill(gx_device_vector * vdev, const gs_imager_state * pis, + const gx_fill_params * params, const gx_drawing_color * pdcolor) +{ + if (params->flatness != vdev->state.flatness) { + int code = (*vdev_proc(vdev, setflat)) (vdev, params->flatness); + + if (code < 0) + return code; + vdev->state.flatness = params->flatness; + } + return update_fill(vdev, pdcolor, pis->log_op); +} + +/* Compare two dash patterns. */ +private bool +dash_pattern_eq(const float *stored, const gx_dash_params * set, floatp scale) +{ + int i; + + for (i = 0; i < set->pattern_size; ++i) + if (stored[i] != (float)(set->pattern[i] * scale)) + return false; + return true; +} + +/* Bring state up to date for stroking. */ +int +gdev_vector_prepare_stroke(gx_device_vector * vdev, const gs_imager_state * pis, + const gx_stroke_params * params, const gx_drawing_color * pdcolor, + floatp scale) +{ + int pattern_size = pis->line_params.dash.pattern_size; + float dash_offset = pis->line_params.dash.offset * scale; + float half_width = pis->line_params.half_width * scale; + + if (pattern_size > max_dash) + return_error(gs_error_limitcheck); + if (dash_offset != vdev->state.line_params.dash.offset || + pattern_size != vdev->state.line_params.dash.pattern_size || + (pattern_size != 0 && + !dash_pattern_eq(vdev->dash_pattern, &pis->line_params.dash, + scale)) + ) { + float pattern[max_dash]; + int i, code; + + for (i = 0; i < pattern_size; ++i) + pattern[i] = pis->line_params.dash.pattern[i] * scale; + code = (*vdev_proc(vdev, setdash)) + (vdev, pattern, pattern_size, dash_offset); + if (code < 0) + return code; + memcpy(vdev->dash_pattern, pattern, pattern_size * sizeof(float)); + + vdev->state.line_params.dash.pattern_size = pattern_size; + vdev->state.line_params.dash.offset = dash_offset; + } + if (params->flatness != vdev->state.flatness) { + int code = (*vdev_proc(vdev, setflat)) (vdev, params->flatness); + + if (code < 0) + return code; + vdev->state.flatness = params->flatness; + } + if (half_width != vdev->state.line_params.half_width) { + int code = (*vdev_proc(vdev, setlinewidth)) + (vdev, pis->line_params.half_width * 2); + + if (code < 0) + return code; + vdev->state.line_params.half_width = half_width; + } + if (pis->line_params.miter_limit != vdev->state.line_params.miter_limit) { + int code = (*vdev_proc(vdev, setmiterlimit)) + (vdev, pis->line_params.miter_limit); + + if (code < 0) + return code; + gx_set_miter_limit(&vdev->state.line_params, + pis->line_params.miter_limit); + } + if (pis->line_params.cap != vdev->state.line_params.cap) { + int code = (*vdev_proc(vdev, setlinecap)) + (vdev, pis->line_params.cap); + + if (code < 0) + return code; + vdev->state.line_params.cap = pis->line_params.cap; + } + if (pis->line_params.join != vdev->state.line_params.join) { + int code = (*vdev_proc(vdev, setlinejoin)) + (vdev, pis->line_params.join); + + if (code < 0) + return code; + vdev->state.line_params.join = pis->line_params.join; + } { + int code = gdev_vector_update_log_op(vdev, pis->log_op); + + if (code < 0) + return code; + } + if (!drawing_color_eq(pdcolor, &vdev->stroke_color)) { + int code = (*vdev_proc(vdev, setstrokecolor)) (vdev, pdcolor); + + if (code < 0) + return code; + vdev->stroke_color = *pdcolor; + } + return 0; +} + +/* Write a polygon as part of a path. */ +/* May call beginpath, moveto, lineto, closepath, endpath. */ +int +gdev_vector_write_polygon(gx_device_vector * vdev, const gs_fixed_point * points, + uint count, bool close, gx_path_type_t type) +{ + int code = 0; + + if (type != gx_path_type_none && + (code = (*vdev_proc(vdev, beginpath)) (vdev, type)) < 0 + ) + return code; + if (count > 0) { + double x = fixed2float(points[0].x) / vdev->scale.x, y = fixed2float(points[0].y) / vdev->scale.y; + double x_start = x, y_start = y, x_prev, y_prev; + uint i; + + code = (*vdev_proc(vdev, moveto)) + (vdev, 0.0, 0.0, x, y, type); + if (code >= 0) + for (i = 1; i < count && code >= 0; ++i) { + x_prev = x, y_prev = y; + code = (*vdev_proc(vdev, lineto)) + (vdev, x_prev, y_prev, + (x = fixed2float(points[i].x) / vdev->scale.x), + (y = fixed2float(points[i].y) / vdev->scale.y), + type); + } + if (code >= 0 && close) + code = (*vdev_proc(vdev, closepath)) + (vdev, x, y, x_start, y_start, type); + } + return (code >= 0 && type != gx_path_type_none ? + (*vdev_proc(vdev, endpath)) (vdev, type) : code); +} + +/* Write a rectangle as part of a path. */ +/* May call moveto, lineto, closepath. */ +int +gdev_vector_write_rectangle(gx_device_vector * vdev, fixed x0, fixed y0, + fixed x1, fixed y1, bool close, gx_rect_direction_t direction) +{ + gs_fixed_point points[4]; + + points[0].x = x0, points[0].y = y0; + points[2].x = x1, points[2].y = y1; + if (direction == gx_rect_x_first) + points[1].x = x1, points[1].y = y0, + points[3].x = x0, points[3].y = y1; + else + points[1].x = x0, points[1].y = y1, + points[3].x = x1, points[3].y = y0; + return gdev_vector_write_polygon(vdev, points, 4, close, + gx_path_type_none); +} + +/* Write a clipping path by calling the path procedures. */ +int +gdev_vector_write_clip_path(gx_device_vector * vdev, const gx_clip_path * pcpath) +{ + const gx_clip_rect *prect; + gx_clip_rect page_rect; + int code; + + if (pcpath == 0) { /* There's no special provision for initclip. */ + /* Write a rectangle that covers the entire page. */ + page_rect.xmin = page_rect.ymin = 0; + page_rect.xmax = vdev->width; + page_rect.ymax = vdev->height; + page_rect.next = 0; + prect = &page_rect; + } else if (pcpath->path_valid) + return (*vdev_proc(vdev, dopath)) (vdev, &pcpath->path, + gx_path_type_clip); + else { + const gx_clip_list *list = gx_cpath_list(pcpath); + + prect = list->head; + if (prect == 0) + prect = &list->single; + } + /* Write out the rectangles. */ + code = (*vdev_proc(vdev, beginpath)) (vdev, gx_path_type_clip); + for (; code >= 0 && prect != 0; prect = prect->next) + if (prect->xmax > prect->xmin && prect->ymax > prect->ymin) + code = gdev_vector_write_rectangle + (vdev, int2fixed(prect->xmin), int2fixed(prect->ymin), + int2fixed(prect->xmax), int2fixed(prect->ymax), + false, gx_rect_x_first); + if (code >= 0) + code = (*vdev_proc(vdev, endpath)) (vdev, gx_path_type_clip); + return code; +} + +/* Update the clipping path if needed. */ +int +gdev_vector_update_clip_path(gx_device_vector * vdev, + const gx_clip_path * pcpath) +{ + if (pcpath) { + if (pcpath->id != vdev->clip_path_id) { + int code = gdev_vector_write_clip_path(vdev, pcpath); + + if (code < 0) + return code; + vdev->clip_path_id = pcpath->id; + } + } else { + if (vdev->clip_path_id != vdev->no_clip_path_id) { + int code = gdev_vector_write_clip_path(vdev, NULL); + + if (code < 0) + return code; + vdev->clip_path_id = vdev->no_clip_path_id; + } + } + return 0; +} + +/* Close the output file and stream. */ +void +gdev_vector_close_file(gx_device_vector * vdev) +{ + gs_free_object(vdev->v_memory, vdev->bbox_device, + "vector_close(bbox_device)"); + vdev->bbox_device = 0; + sclose(vdev->strm); + gs_free_object(vdev->v_memory, vdev->strm, "vector_close(strm)"); + vdev->strm = 0; + gs_free_object(vdev->v_memory, vdev->strmbuf, "vector_close(strmbuf)"); + vdev->strmbuf = 0; + fclose(vdev->file); /* we prevented sclose from doing this */ + vdev->file = 0; +} + +/* ---------------- Image enumeration ---------------- */ + +/* Initialize for enumerating an image. */ +int +gdev_vector_begin_image(gx_device_vector * vdev, + const gs_imager_state * pis, const gs_image_t * pim, + gs_image_format_t format, const gs_int_rect * prect, + const gx_drawing_color * pdcolor, const gx_clip_path * pcpath, + gs_memory_t * mem, const gx_image_enum_procs_t * pprocs, + gdev_vector_image_enum_t * pie) +{ + const gs_color_space *pcs = pim->ColorSpace; + int num_components; + int bits_per_pixel; + int code; + + if (pim->ImageMask) + bits_per_pixel = num_components = 1; + else + num_components = gs_color_space_num_components(pcs), + bits_per_pixel = pim->BitsPerComponent; + code = gx_image_enum_common_init((gx_image_enum_common_t *) pie, + (const gs_image_common_t *)pim, + pprocs, (gx_device *) vdev, + bits_per_pixel, num_components, + format); + if (code < 0) + return code; + pie->bits_per_pixel = bits_per_pixel * num_components / + pie->num_planes; + pie->default_info = 0; + pie->bbox_info = 0; + if ((code = gdev_vector_update_log_op(vdev, pis->log_op)) < 0 || + (code = gdev_vector_update_clip_path(vdev, pcpath)) < 0 || + ((pim->ImageMask || + (pim->CombineWithColor && rop3_uses_T(pis->log_op))) && + (code = gdev_vector_update_fill_color(vdev, pdcolor)) < 0) || + (vdev->bbox_device && + (code = (*dev_proc(vdev->bbox_device, begin_image)) + ((gx_device *) vdev->bbox_device, pis, pim, format, prect, + pdcolor, pcpath, mem, &pie->bbox_info)) < 0) + ) + return code; + pie->memory = mem; + if (prect) + pie->width = prect->q.x - prect->p.x, + pie->height = prect->q.y - prect->p.y; + else + pie->width = pim->Width, pie->height = pim->Height; + pie->bits_per_row = pie->width * pie->bits_per_pixel; + pie->y = 0; + return 0; +} + +/* End an image, optionally supplying any necessary blank padding rows. */ +/* Return 0 if we used the default implementation, 1 if not. */ +int +gdev_vector_end_image(gx_device_vector * vdev, + gdev_vector_image_enum_t * pie, bool draw_last, gx_color_index pad) +{ + int code; + + if (pie->default_info) { + code = gx_default_end_image((gx_device *) vdev, pie->default_info, + draw_last); + if (code >= 0) + code = 0; + } else { /* Fill out to the full image height. */ + if (pie->y < pie->height && pad != gx_no_color_index) { + uint bytes_per_row = (pie->bits_per_row + 7) >> 3; + byte *row = gs_alloc_bytes(pie->memory, bytes_per_row, + "gdev_vector_end_image(fill)"); + + if (row == 0) + return_error(gs_error_VMerror); +/****** FILL VALUE IS WRONG ******/ + memset(row, (byte) pad, bytes_per_row); + for (; pie->y < pie->height; pie->y++) + gx_image_data((gx_image_enum_common_t *) pie, + (const byte **)&row, 0, + bytes_per_row, 1); + gs_free_object(pie->memory, row, + "gdev_vector_end_image(fill)"); + } + code = 1; + } + if (vdev->bbox_device) { + int bcode = gx_image_end(pie->bbox_info, draw_last); + + if (bcode < 0) + code = bcode; + } + gs_free_object(pie->memory, pie, "gdev_vector_end_image"); + return code; +} + +/* ================ Device procedures ================ */ + +#define vdev ((gx_device_vector *)dev) + +/* Get parameters. */ +int +gdev_vector_get_params(gx_device * dev, gs_param_list * plist) +{ + int code = gx_default_get_params(dev, plist); + int ecode; + gs_param_string ofns; + + if (code < 0) + return code; + ofns.data = (const byte *)vdev->fname, + ofns.size = strlen(vdev->fname), + ofns.persistent = false; + if ((ecode = param_write_string(plist, "OutputFile", &ofns)) < 0) + return ecode; + return code; +} + +/* Put parameters. */ +int +gdev_vector_put_params(gx_device * dev, gs_param_list * plist) +{ + int ecode = 0; + int code; + gs_param_name param_name; + gs_param_string ofns; + + switch (code = param_read_string(plist, (param_name = "OutputFile"), &ofns)) { + case 0: + if (ofns.size > fname_size) + ecode = gs_error_limitcheck; + else + break; + goto ofe; + default: + ecode = code; + ofe:param_signal_error(plist, param_name, ecode); + case 1: + ofns.data = 0; + break; + } + + if (ecode < 0) + return ecode; + { + bool open = dev->is_open; + + /* Don't let gx_default_put_params close the device. */ + dev->is_open = false; + code = gx_default_put_params(dev, plist); + dev->is_open = open; + } + if (code < 0) + return code; + + if (ofns.data != 0 && + bytes_compare(ofns.data, ofns.size, + (const byte *)vdev->fname, strlen(vdev->fname)) + ) { + memcpy(vdev->fname, ofns.data, ofns.size); + vdev->fname[ofns.size] = 0; + if (vdev->file != 0) { + gdev_vector_close_file(vdev); + return gdev_vector_open_file(vdev, vdev->strmbuf_size); + } + } + gdev_vector_load_cache(vdev); /* in case color mapping changed */ + return 0; +} + +/* ---------------- Defaults ---------------- */ + +int +gdev_vector_fill_rectangle(gx_device * dev, int x, int y, int w, int h, + gx_color_index color) +{ + gx_drawing_color dcolor; + + /* Ignore the initial fill with white. */ + if (!vdev->in_page && color == vdev->white) + return 0; + color_set_pure(&dcolor, color); + { + int code = update_fill(vdev, &dcolor, rop3_T); + + if (code < 0) + return code; + } + if (vdev->bbox_device) { + int code = (*dev_proc(vdev->bbox_device, fill_rectangle)) + ((gx_device *) vdev->bbox_device, x, y, w, h, color); + + if (code < 0) + return code; + } + return (*vdev_proc(vdev, dorect)) (vdev, int2fixed(x), int2fixed(y), + int2fixed(x + w), int2fixed(y + h), + gx_path_type_fill); +} + +int +gdev_vector_fill_path(gx_device * dev, const gs_imager_state * pis, + gx_path * ppath, const gx_fill_params * params, + const gx_device_color * pdevc, const gx_clip_path * pcpath) +{ + int code; + + if ((code = gdev_vector_prepare_fill(vdev, pis, params, pdevc)) < 0 || + (code = gdev_vector_update_clip_path(vdev, pcpath)) < 0 || + (vdev->bbox_device && + (code = (*dev_proc(vdev->bbox_device, fill_path)) + ((gx_device *) vdev->bbox_device, pis, ppath, params, + pdevc, pcpath)) < 0) || + (code = (*vdev_proc(vdev, dopath)) + (vdev, ppath, + (params->rule > 0 ? gx_path_type_even_odd : + gx_path_type_winding_number) | gx_path_type_fill)) < 0 + ) + return gx_default_fill_path(dev, pis, ppath, params, pdevc, pcpath); + return code; +} + +int +gdev_vector_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) +{ + int code; + +/****** HANDLE SCALE ******/ + if ((code = gdev_vector_prepare_stroke(vdev, pis, params, pdcolor, + dev->HWResolution[0])) < 0 || + (code = gdev_vector_update_clip_path(vdev, pcpath)) < 0 || + (vdev->bbox_device && + (code = (*dev_proc(vdev->bbox_device, stroke_path)) + ((gx_device *) vdev->bbox_device, pis, ppath, params, + pdcolor, pcpath)) < 0) || + (code = (*vdev_proc(vdev, dopath)) + (vdev, ppath, gx_path_type_stroke)) < 0 + ) + return gx_default_stroke_path(dev, pis, ppath, params, pdcolor, pcpath); + return code; +} + +int +gdev_vector_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) +{ + fixed xl = left->start.x; + fixed wl = left->end.x - xl; + fixed yl = left->start.y; + fixed hl = left->end.y - yl; + fixed xr = right->start.x; + fixed wr = right->end.x - xr; + fixed yr = right->start.y; + fixed hr = right->end.y - yr; + fixed x0l = xl + fixed_mult_quo(wl, ybot - yl, hl); + fixed x1l = xl + fixed_mult_quo(wl, ytop - yl, hl); + fixed x0r = xr + fixed_mult_quo(wr, ybot - yr, hr); + fixed x1r = xr + fixed_mult_quo(wr, ytop - yr, hr); + +#define y0 ybot +#define y1 ytop + int code = update_fill(vdev, pdevc, lop); + gs_fixed_point points[4]; + + if (code < 0) + return gx_default_fill_trapezoid(dev, left, right, ybot, ytop, + swap_axes, pdevc, lop); + if (swap_axes) + points[0].y = x0l, points[1].y = x0r, + points[0].x = points[1].x = y0, + points[2].y = x1r, points[3].y = x1l, + points[2].x = points[3].x = y1; + else + points[0].x = x0l, points[1].x = x0r, + points[0].y = points[1].y = y0, + points[2].x = x1r, points[3].x = x1l, + points[2].y = points[3].y = y1; +#undef y0 +#undef y1 + if (vdev->bbox_device) { + int code = (*dev_proc(vdev->bbox_device, fill_trapezoid)) + ((gx_device *) vdev->bbox_device, left, right, ybot, ytop, + swap_axes, pdevc, lop); + + if (code < 0) + return code; + } + return gdev_vector_write_polygon(vdev, points, 4, true, + gx_path_type_fill); +} + +int +gdev_vector_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 pax = px + ax, pay = py + ay; + int code = update_fill(vdev, pdevc, lop); + gs_fixed_point points[4]; + + if (code < 0) + return gx_default_fill_parallelogram(dev, px, py, ax, ay, bx, by, + pdevc, lop); + if (vdev->bbox_device) { + code = (*dev_proc(vdev->bbox_device, fill_parallelogram)) + ((gx_device *) vdev->bbox_device, px, py, ax, ay, bx, by, + pdevc, lop); + if (code < 0) + return code; + } + points[0].x = px, points[0].y = py; + points[1].x = pax, points[0].y = pay; + points[2].x = pax + bx, points[2].y = pay + by; + points[3].x = px + bx, points[3].y = py + by; + return gdev_vector_write_polygon(vdev, points, 4, true, + gx_path_type_fill); +} + +int +gdev_vector_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) +{ + int code = update_fill(vdev, pdevc, lop); + gs_fixed_point points[3]; + + if (code < 0) + return gx_default_fill_triangle(dev, px, py, ax, ay, bx, by, + pdevc, lop); + if (vdev->bbox_device) { + code = (*dev_proc(vdev->bbox_device, fill_triangle)) + ((gx_device *) vdev->bbox_device, px, py, ax, ay, bx, by, + pdevc, lop); + if (code < 0) + return code; + } + points[0].x = px, points[0].y = py; + points[1].x = px + ax, points[1].y = py + ay; + points[2].x = px + bx, points[2].y = py + by; + return gdev_vector_write_polygon(vdev, points, 3, true, + gx_path_type_fill); +} + +#undef vdev diff --git a/pstoraster/gdevvec.h b/pstoraster/gdevvec.h new file mode 100644 index 0000000000..f4a2aebb47 --- /dev/null +++ b/pstoraster/gdevvec.h @@ -0,0 +1,349 @@ +/* Copyright (C) 1997, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Common definitions for "vector" devices */ + +#ifndef gdevvec_INCLUDED +# define gdevvec_INCLUDED + +#include "gp.h" /* for gp_file_name_sizeof */ +#include "gsropt.h" +#include "gxdevice.h" +#include "gdevbbox.h" +#include "gxiparam.h" +#include "gxistate.h" +#include "stream.h" + +/****** + ****** NOTE: EVERYTHING IN THIS FILE IS SUBJECT TO CHANGE WITHOUT NOTICE. + ****** USE AT YOUR OWN RISK. + ******/ + +/* + * "Vector" devices produce a stream of higher-level drawing commands rather + * than a raster image. (We don't like the term "vector", since the command + * vocabulary typically includes text and raster images as well as actual + * vectors, but it's widely used in the industry, and we weren't able to + * find one that read better.) Some examples of "vector" formats are PDF, + * PostScript, PCL XL, HP-GL/2 + RTL, CGM, Windows Metafile, and Macintosh + * PICT. + * + * This file extends the basic driver structure with elements likely to be + * useful to vector devices. These include: + * + * - Tracking whether any marks have been made on the page; + * + * - Keeping track of the page bounding box; + * + * - A copy of the most recently written current graphics state + * parameters; + * + * - An output stream (for drivers that compress or otherwise filter + * their output); + * + * - A vector of procedures for writing changes to the graphics state. + * + * - The ability to work with scaled output coordinate systems. + * + * We expect to add more elements and procedures as we gain more experience + * with this kind of driver. + */ + +/* ================ Types and structures ================ */ + +/* Define the abstract type for a vector device. */ +typedef struct gx_device_vector_s gx_device_vector; + +/* Define the maximum size of the output file name. */ +#define fname_size (gp_file_name_sizeof - 1) + +/* Define the longest dash pattern we can remember. */ +#define max_dash 11 + +/* + * Define procedures for writing common output elements. Not all devices + * will support all of these elements. Note that these procedures normally + * only write out commands, and don't update the driver state itself. All + * of them are optional, called only as indicated under the utility + * procedures below. + */ +typedef enum { + gx_path_type_none = 0, + /* + * All combinations of flags are legal. Multiple commands are + * executed in the order fill, stroke, clip. + */ + gx_path_type_fill = 1, + gx_path_type_stroke = 2, + gx_path_type_clip = 4, + gx_path_type_winding_number = 0, + gx_path_type_even_odd = 8, + gx_path_type_rule = gx_path_type_winding_number | gx_path_type_even_odd +} gx_path_type_t; +typedef enum { + gx_rect_x_first, + gx_rect_y_first +} gx_rect_direction_t; +typedef struct gx_device_vector_procs_s { + /* Page management */ + int (*beginpage) (P1(gx_device_vector * vdev)); + /* Imager state */ + int (*setlinewidth) (P2(gx_device_vector * vdev, floatp width)); + int (*setlinecap) (P2(gx_device_vector * vdev, gs_line_cap cap)); + int (*setlinejoin) (P2(gx_device_vector * vdev, gs_line_join join)); + int (*setmiterlimit) (P2(gx_device_vector * vdev, floatp limit)); + int (*setdash) (P4(gx_device_vector * vdev, const float *pattern, + uint count, floatp offset)); + int (*setflat) (P2(gx_device_vector * vdev, floatp flatness)); + int (*setlogop) (P3(gx_device_vector * vdev, gs_logical_operation_t lop, + gs_logical_operation_t diff)); + /* Other state */ + int (*setfillcolor) (P2(gx_device_vector * vdev, const gx_drawing_color * pdc)); + int (*setstrokecolor) (P2(gx_device_vector * vdev, const gx_drawing_color * pdc)); + /* Paths */ + /* dopath and dorect are normally defaulted */ + int (*dopath) (P3(gx_device_vector * vdev, const gx_path * ppath, + gx_path_type_t type)); + int (*dorect) (P6(gx_device_vector * vdev, fixed x0, fixed y0, fixed x1, + fixed y1, gx_path_type_t type)); + int (*beginpath) (P2(gx_device_vector * vdev, gx_path_type_t type)); + int (*moveto) (P6(gx_device_vector * vdev, floatp x0, floatp y0, + floatp x, floatp y, gx_path_type_t type)); + int (*lineto) (P6(gx_device_vector * vdev, floatp x0, floatp y0, + floatp x, floatp y, gx_path_type_t type)); + int (*curveto) (P10(gx_device_vector * vdev, floatp x0, floatp y0, + floatp x1, floatp y1, floatp x2, floatp y2, + floatp x3, floatp y3, gx_path_type_t type)); + int (*closepath) (P6(gx_device_vector * vdev, floatp x0, floatp y0, + floatp x_start, floatp y_start, gx_path_type_t type)); + int (*endpath) (P2(gx_device_vector * vdev, gx_path_type_t type)); +} gx_device_vector_procs; + +/* Default implementations of procedures */ +/* setflat does nothing */ +int gdev_vector_setflat(P2(gx_device_vector * vdev, floatp flatness)); + +/* dopath may call dorect, beginpath, moveto/lineto/curveto/closepath, */ +/* endpath */ +int gdev_vector_dopath(P3(gx_device_vector * vdev, const gx_path * ppath, + gx_path_type_t type)); + +/* dorect may call beginpath, moveto, lineto, closepath */ +int gdev_vector_dorect(P6(gx_device_vector * vdev, fixed x0, fixed y0, + fixed x1, fixed y1, gx_path_type_t type)); + +/* Finally, define the extended device structure. */ +#define gx_device_vector_common\ + gx_device_common;\ + gs_memory_t *v_memory;\ + /* Output element writing procedures */\ + const gx_device_vector_procs *vec_procs;\ + /* Output file */\ + char fname[fname_size + 1];\ + FILE *file;\ + stream *strm;\ + byte *strmbuf;\ + uint strmbuf_size;\ + /* Graphics state */\ + gs_imager_state state;\ + float dash_pattern[max_dash];\ + gx_drawing_color fill_color, stroke_color;\ + gs_id no_clip_path_id; /* indicates no clipping */\ + gs_id clip_path_id;\ + /* Other state */\ + gs_point scale; /* device coords / scale => output coords */\ + bool in_page; /* true if any marks on this page */\ + gx_device_bbox *bbox_device; /* for tracking bounding box */\ + /* Cached values */\ + gx_color_index black, white +#define vdev_proc(vdev, p) ((vdev)->vec_procs->p) + +#define vector_initial_values\ + 0, /* v_memory */\ + 0, /* vec_procs */\ + { 0 }, /* fname */\ + 0, /* file */\ + 0, /* strm */\ + 0, /* strmbuf */\ + 0, /* strmbuf_size */\ + { 0 }, /* state */\ + { 0 }, /* dash_pattern */\ + { 0 }, /* fill_color ****** WRONG ****** */\ + { 0 }, /* stroke_color ****** WRONG ****** */\ + gs_no_id, /* clip_path_id */\ + gs_no_id, /* no_clip_path_id */\ + { X_DPI/72.0, Y_DPI/72.0 }, /* scale */\ + 0/*false*/, /* in_page */\ + 0, /* bbox_device */\ + gx_no_color_index, /* black */\ + gx_no_color_index /* white */ + +struct gx_device_vector_s { + gx_device_vector_common; +}; + +/* st_device_vector is never instantiated per se, but we still need to */ +/* extern its descriptor for the sake of subclasses. */ +extern_st(st_device_vector); +#define public_st_device_vector() /* in gdevvec.c */\ + gs_public_st_suffix_add3_final(st_device_vector, gx_device_vector,\ + "gx_device_vector", device_vector_enum_ptrs,\ + device_vector_reloc_ptrs, gx_device_finalize, st_device, strm, strmbuf,\ + bbox_device) +#define st_device_vector_max_ptrs (st_device_max_ptrs + 3) + +/* ================ Utility procedures ================ */ + +/* Initialize the state. */ +void gdev_vector_init(P1(gx_device_vector * vdev)); + +/* Reset the remembered graphics state. */ +void gdev_vector_reset(P1(gx_device_vector * vdev)); + +/* Open the output file and stream, with optional bbox tracking. */ +int gdev_vector_open_file_bbox(P3(gx_device_vector * vdev, uint strmbuf_size, + bool bbox)); + +#define gdev_vector_open_file(vdev, strmbuf_size)\ + gdev_vector_open_file_bbox(vdev, strmbuf_size, false) + +/* Get the current stream, calling beginpage if in_page is false. */ +stream *gdev_vector_stream(P1(gx_device_vector * vdev)); + +/* Bring the logical operation up to date. */ +/* May call setlogop. */ +int gdev_vector_update_log_op(P2(gx_device_vector * vdev, + gs_logical_operation_t lop)); + +/* Bring the fill color up to date. */ +/* May call setfillcolor. */ +int gdev_vector_update_fill_color(P2(gx_device_vector * vdev, + const gx_drawing_color * pdcolor)); + +/* Bring state up to date for filling. */ +/* May call setflat, setfillcolor, setlogop. */ +int gdev_vector_prepare_fill(P4(gx_device_vector * vdev, + const gs_imager_state * pis, + const gx_fill_params * params, + const gx_drawing_color * pdcolor)); + +/* Bring state up to date for stroking. Note that we pass the scale */ +/* for the line width and dash offset explicitly. */ +/* May call setlinewidth, setlinecap, setlinejoin, setmiterlimit, */ +/* setdash, setflat, setstrokecolor, setlogop. */ +int gdev_vector_prepare_stroke(P5(gx_device_vector * vdev, + const gs_imager_state * pis, + const gx_stroke_params * params, + const gx_drawing_color * pdcolor, + floatp scale)); + +/* Write a polygon as part of a path (type = gx_path_type_none) */ +/* or as a path. */ +/* May call moveto, lineto, closepath (if close); */ +/* may call beginpath & endpath if type != none. */ +int gdev_vector_write_polygon(P5(gx_device_vector * vdev, + const gs_fixed_point * points, uint count, + bool close, gx_path_type_t type)); + +/* Write a rectangle. This is just a special case of write_polygon. */ +int gdev_vector_write_rectangle(P7(gx_device_vector * vdev, + fixed x0, fixed y0, fixed x1, fixed y1, + bool close, gx_rect_direction_t dir)); + +/* Write a clipping path by calling the path procedures. */ +/* May call the same procedures as writepath. */ +int gdev_vector_write_clip_path(P2(gx_device_vector * vdev, + const gx_clip_path * pcpath)); + +/* Bring the clipping state up to date. */ +/* May call write_rectangle (q.v.), write_clip_path (q.v.). */ +int gdev_vector_update_clip_path(P2(gx_device_vector * vdev, + const gx_clip_path * pcpath)); + +/* Close the output file and stream. */ +void gdev_vector_close_file(P1(gx_device_vector * vdev)); + +/* ---------------- Image enumeration ---------------- */ + +/* Define a common set of state parameters for enumerating images. */ +#define gdev_vector_image_enum_common\ + gx_image_enum_common;\ + /* Set by begin_image */\ + gs_memory_t *memory; /* from begin_image */\ + gx_image_enum_common_t *default_info; /* non-0 iff using default implementation */\ + gx_image_enum_common_t *bbox_info; /* non-0 iff passing image data to bbox dev */\ + int width, height;\ + int bits_per_pixel; /* (per plane) */\ + uint bits_per_row; /* (per plane) */\ + /* Updated dynamically by image_data */\ + int y /* 0 <= y < height */ +typedef struct gdev_vector_image_enum_s { + gdev_vector_image_enum_common; +} gdev_vector_image_enum_t; + +extern_st(st_vector_image_enum); +#define public_st_vector_image_enum() /* in gdevvec.c */\ + gs_public_st_ptrs2(st_vector_image_enum, gdev_vector_image_enum_t,\ + "gdev_vector_image_enum_t", vector_image_enum_enum_ptrs,\ + vector_image_enum_reloc_ptrs, default_info, bbox_info) + +/* + * Initialize for enumerating an image. Note that the last argument is an + * already-allocated enumerator, not a pointer to the place to store the + * enumerator. + */ +int gdev_vector_begin_image(P10(gx_device_vector * vdev, + const gs_imager_state * pis, const gs_image_t * pim, + gs_image_format_t format, const gs_int_rect * prect, + const gx_drawing_color * pdcolor, const gx_clip_path * pcpath, + gs_memory_t * mem, const gx_image_enum_procs_t * pprocs, + gdev_vector_image_enum_t * pie)); + +/* End an image, optionally supplying any necessary blank padding rows. */ +/* Return 0 if we used the default implementation, 1 if not. */ +int gdev_vector_end_image(P4(gx_device_vector * vdev, + gdev_vector_image_enum_t * pie, bool draw_last, gx_color_index pad)); + +/* ================ Device procedures ================ */ + +/* Redefine get/put_params to handle OutputFile. */ +dev_proc_put_params(gdev_vector_put_params); +dev_proc_get_params(gdev_vector_get_params); + +/* ---------------- Defaults ---------------- */ + +/* fill_rectangle may call setfillcolor, dorect. */ +dev_proc_fill_rectangle(gdev_vector_fill_rectangle); +/* fill_path may call prepare_fill, writepath, write_clip_path. */ +dev_proc_fill_path(gdev_vector_fill_path); +/* stroke_path may call prepare_stroke, write_path, write_clip_path. */ +dev_proc_stroke_path(gdev_vector_stroke_path); +/* fill_trapezoid, fill_parallelogram, and fill_triangle may call */ +/* setfillcolor, setlogop, beginpath, moveto, lineto, endpath. */ +dev_proc_fill_trapezoid(gdev_vector_fill_trapezoid); +dev_proc_fill_parallelogram(gdev_vector_fill_parallelogram); +dev_proc_fill_triangle(gdev_vector_fill_triangle); + +#endif /* gdevvec_INCLUDED */ diff --git a/pstoraster/genarch.c b/pstoraster/genarch.c new file mode 100644 index 0000000000..a8f308bffc --- /dev/null +++ b/pstoraster/genarch.c @@ -0,0 +1,163 @@ +/* Copyright (C) 1989, 1995, 1996, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Generate a header file (arch.h) with parameters */ +/* reflecting the machine architecture and compiler characteristics. */ + +#include "stdpre.h" +#include + +/* We should write the result on stdout, but the original Turbo C 'make' */ +/* can't handle output redirection (sigh). */ + +private void +section(FILE * f, char *str) +{ + fprintf(f, "\n\t /* ---------------- %s ---------------- */\n\n", str); +} + +int +main(int argc, char *argv[]) +{ + char *fname = argv[1]; + long one = 1; + char *ffs = "ffffffffffffffff"; /* 8 bytes */ + int ffs_strlen = strlen(ffs); + 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; + 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"); + + section(f, "Scalar alignments"); + +#define OFFSET_IN(s, e) (int)((char *)&s.e - (char *)&s) + fprintf(f, "#define arch_align_short_mod %d\n", OFFSET_IN(ss, s)); + fprintf(f, "#define arch_align_int_mod %d\n", OFFSET_IN(si, i)); + fprintf(f, "#define arch_align_long_mod %d\n", OFFSET_IN(sl, l)); + fprintf(f, "#define arch_align_ptr_mod %d\n", OFFSET_IN(sp, p)); + fprintf(f, "#define arch_align_float_mod %d\n", OFFSET_IN(sf, f)); + fprintf(f, "#define arch_align_double_mod %d\n", OFFSET_IN(sd, d)); +#undef OFFSET_IN + + section(f, "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_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)); + + section(f, "Unsigned max values"); + +#define PRINT_MAX(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) + PRINT_MAX("uchar", unsigned char, "unsigned char", ""); + PRINT_MAX("ushort", unsigned short, "unsigned short", ""); + PRINT_MAX("uint", unsigned int, "unsigned int", ""); + PRINT_MAX("ulong", unsigned long, "unsigned long", "L"); + +#undef PRINT_MAX + + section(f, "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..5df931e78e --- /dev/null +++ b/pstoraster/ghost.h @@ -0,0 +1,34 @@ +/* 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 supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Common definitions for interpreter */ + +#ifndef ghost_INCLUDED +# define ghost_INCLUDED + +#include "gx.h" +#include "iref.h" + +#endif /* ghost_INCLUDED */ diff --git a/pstoraster/gp.h b/pstoraster/gp.h new file mode 100644 index 0000000000..39aa8c4aa4 --- /dev/null +++ b/pstoraster/gp.h @@ -0,0 +1,233 @@ +/* Copyright (C) 1991, 1995, 1997, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Interface to platform-specific routines */ +/* Requires gsmemory.h, gstypes.h */ + +#ifndef gp_INCLUDED +# define gp_INCLUDED + +/* + * This file defines the interface to ***ALL*** platform-specific routines, + * with the exception of the thread/synchronization interface (gpsync.h). + * The routines are implemented in a gp_*.c file specific to each platform. + * We try very hard to keep this list short! + */ +/* + * gp_getenv is declared in a separate file, because a few places need it + * and don't want to include any of the other gs definitions. + */ +#include "gpgetenv.h" + +/* ------ 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()); + +/* ------ File naming and accessing ------ */ + +/* + * Define the maximum size of a file name returned by gp_open_scratch_file + * or gp_open_printer. (This should really be passed as an additional + * parameter, but it would break too many clients to make this change now.) + * Note that this is the size of the buffer, not the maximum number of + * characters: the latter is one less, because of the terminating \0. + */ +#define gp_file_name_sizeof 128 + +/* 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[gp_file_name_sizeof], + 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)); + +/* Force given file into binary mode (no eol translations, etc) */ +/* if 2nd param true, text mode if 2nd param false */ +bool gp_setmode_binary(P2(FILE * pfile, bool 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)); + +/* ------ 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. + * + * Note that if the file name is null (0-length), it may be replaced with + * the name of a scratch file. + */ +FILE *gp_open_printer(P2(char fname[gp_file_name_sizeof], int binary_mode)); + +/* Close the connection to the printer. */ +void gp_close_printer(P2(FILE * pfile, const char *fname)); + +/* ------ File enumeration ------ */ + +#ifndef file_enum_DEFINED /* also defined in iodev.h */ +# define file_enum_DEFINED +struct file_enum_s; /* opaque to client, defined by implementor */ +typedef struct file_enum_s file_enum; + +#endif + +/* + * 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)); + +#endif /* gp_INCLUDED */ diff --git a/pstoraster/gp_getnv.c b/pstoraster/gp_getnv.c new file mode 100644 index 0000000000..fbf997f32a --- /dev/null +++ b/pstoraster/gp_getnv.c @@ -0,0 +1,60 @@ +/* Copyright (C) 1997 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Standard implementation of gp_getenv */ +#include "stdio_.h" +#include "string_.h" +#include "gsmemory.h" +#include "gstypes.h" +#include "gp.h" + +/* Import the C getenv function. */ +extern char *getenv(P1(const char *)); + +/* Get the value of an environment variable. See gp.h for details. */ +int +gp_getenv(const char *key, char *ptr, int *plen) +{ + const char *str = getenv(key); + + if (str) { + int len = strlen(str); + + if (len < *plen) { + /* string fits */ + strcpy(ptr, str); + *plen = len + 1; + return 0; + } + /* string doesn't fit */ + *plen = len + 1; + return -1; + } + /* missing key */ + if (*plen > 0) + *ptr = 0; + *plen = 1; + return 1; +} diff --git a/pstoraster/gp_nofb.c b/pstoraster/gp_nofb.c new file mode 100644 index 0000000000..49c50ae8a5 --- /dev/null +++ b/pstoraster/gp_nofb.c @@ -0,0 +1,58 @@ +/* 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 supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* 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_nsync.c b/pstoraster/gp_nsync.c new file mode 100644 index 0000000000..0163cf5a23 --- /dev/null +++ b/pstoraster/gp_nsync.c @@ -0,0 +1,120 @@ +/* Copyright (C) 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Dummy thread / semaphore / monitor implementation */ +#include "std.h" +#include "gserror.h" +#include "gserrors.h" +#include "gpsync.h" + +/* ------- Synchronization primitives -------- */ + +/* Semaphores */ + +uint +gp_semaphore_sizeof(void) +{ + return sizeof(gp_semaphore); +} + +int +gp_semaphore_open(gp_semaphore * sema) +{ + if (sema) + *(int *)sema = 0; + return 0; +} + +int +gp_semaphore_close(gp_semaphore * sema) +{ + return 0; +} + +int +gp_semaphore_wait(gp_semaphore * sema) +{ + if (*(int *)sema == 0) + return_error(gs_error_unknownerror); + --(*(int *)sema); + return 0; +} + +int +gp_semaphore_signal(gp_semaphore * sema) +{ + ++(*(int *)sema); + return 0; +} + +/* Monitors */ + +uint +gp_monitor_sizeof(void) +{ + return sizeof(gp_monitor); +} + +int +gp_monitor_open(gp_monitor * mon) +{ + if (mon) + mon->dummy_ = 0; + return 0; +} + +int +gp_monitor_close(gp_monitor * mon) +{ + return 0; +} + +int +gp_monitor_enter(gp_monitor * mon) +{ + if (mon->dummy_ != 0) + return_error(gs_error_unknownerror); + mon->dummy_ = &mon; + return 0; +} + +int +gp_monitor_leave(gp_monitor * mon) +{ + if (mon->dummy_ != &mon) + return_error(gs_error_unknownerror); + mon->dummy_ = 0; + return 0; +} + +/* Thread creation */ + +int +gp_create_thread(gp_thread_creation_callback_t proc, void *proc_data) +{ + /* Just call the procedure now. */ + (*proc)(proc_data); + return 0; +} diff --git a/pstoraster/gp_unifn.c b/pstoraster/gp_unifn.c new file mode 100644 index 0000000000..aa128faaba --- /dev/null +++ b/pstoraster/gp_unifn.c @@ -0,0 +1,61 @@ +/* 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 supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* 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..7d6bf0ba82 --- /dev/null +++ b/pstoraster/gp_unifs.c @@ -0,0 +1,440 @@ +/*Copyright 1993-2000 by Easy Software Products. + Copyright 1993, 1995, 1996, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* "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 *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[gp_file_name_sizeof], + const char *mode) +{ /* The -8 is for XXXXXX plus a possible final / and -. */ + int len = gp_file_name_sizeof - strlen(prefix) - 8; + + /* + * MRS - Hello? TEMP is a DOS thing, TMPDIR is the UNIX thing. + * Also, we should default to /var/tmp, since the root + * partition is often small. + */ + + if (gp_getenv("TMPDIR", fname, &len) != 0) + strcpy(fname, "/var/tmp/"); + else { + 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); +} + +/* Set a file into binary or text mode. */ +int +gp_setmode_binary(FILE * pfile, bool mode) +{ + return 0; /* Noop under Unix */ +} + +/* ------ 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')) { + dlputs("[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) +{ + const 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..e705af6359 --- /dev/null +++ b/pstoraster/gp_unix.c @@ -0,0 +1,173 @@ +/* Copyright (C) 1989, 1995, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Unix-specific routines for Ghostscript */ +#include "pipe_.h" +#include "string_.h" +#include "time_.h" +#include "gx.h" +#include "gsexit.h" +#include "gp.h" + +/* + * 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; + const long 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[gp_file_name_sizeof], 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..aaaf2b7343 --- /dev/null +++ b/pstoraster/gpcheck.h @@ -0,0 +1,65 @@ +/* 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 supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Interrupt check interface */ + +#ifndef gpcheck_INCLUDED +# define gpcheck_INCLUDED + +/* + * 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 + +#endif /* gpcheck_INCLUDED */ diff --git a/pstoraster/gpgetenv.h b/pstoraster/gpgetenv.h new file mode 100644 index 0000000000..61b75c3884 --- /dev/null +++ b/pstoraster/gpgetenv.h @@ -0,0 +1,50 @@ +/* Copyright (C) 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Interface to platform-specific getenv routine */ + +#ifndef gpgetenv_INCLUDED +# define gpgetenv_INCLUDED + +/* + * Get a value from the environment (getenv). + * + * If the key is missing, set *ptr = 0 (if *plen > 0), set *plen = 1, + * and return 1. + * + * If the key is present and the length len of the value (not counting + * the terminating \0) is less than *plen, copy the value to ptr, set + * *plen = len + 1, and return 0. + * + * If the key is present and len >= *plen, set *plen = len + 1, + * don't store anything at ptr, and return -1. + * + * Note that *plen is the size of the buffer, not the length of the string: + * because of the terminating \0, the maximum string length is 1 less than + * the size of the buffer. + */ +int gp_getenv(P3(const char *key, char *ptr, int *plen)); + +#endif /* gpgetenv_INCLUDED */ diff --git a/pstoraster/gpsync.h b/pstoraster/gpsync.h new file mode 100644 index 0000000000..5a16f28d15 --- /dev/null +++ b/pstoraster/gpsync.h @@ -0,0 +1,81 @@ +/* Copyright (C) 1998 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility + to anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer + to the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given + to you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises supports the work of the GNU Project, but is not + affiliated with the Free Software Foundation or the GNU Project. GNU + Ghostscript, as distributed by Aladdin Enterprises, does not require any + GNU software to build or run it. +*/ + +/*$Id$ */ +/* Interface to platform-dependent synchronization primitives */ + +#if !defined(gpsync_INCLUDED) + #define gpsync_INCLUDED + +/* Initial version 4/1/98 by John Desrosiers (soho@crl.com). */ +/* 8/9/98 L. Peter Deutsch (ghost@aladdin.com) Changed ...sizeof to + procedures, added some comments. */ + +/* -------- Synchronization primitives ------- */ + +/* + * Semaphores support wait/signal semantics: a wait operation will allow + * control to proceed iff the number of signals since semaphore creation + * is greater than the number of waits. + */ +typedef struct { + void *dummy_; +} gp_semaphore; + +uint gp_semaphore_sizeof(P0()); +/* + * Hack: gp_semaphore_open(0) succeeds iff it's OK for the memory manager + * to move a gp_semaphore in memory. + */ +int gp_semaphore_open(P1(gp_semaphore * sema)); +int gp_semaphore_close(P1(gp_semaphore * sema)); +int gp_semaphore_wait(P1(gp_semaphore * sema)); +int gp_semaphore_signal(P1(gp_semaphore * sema)); + +/* + * Monitors support enter/leave semantics: at most one thread can have + * entered and not yet left a given monitor. + */ +typedef struct { + void *dummy_; +} gp_monitor; + +uint gp_monitor_sizeof(P0()); +/* + * Hack: gp_monitor_open(0) succeeds iff it's OK for the memory manager + * to move a gp_monitor in memory. + */ +int gp_monitor_open(P1(gp_monitor * mon)); +int gp_monitor_close(P1(gp_monitor * mon)); +int gp_monitor_enter(P1(gp_monitor * mon)); +int gp_monitor_leave(P1(gp_monitor * mon)); + +/* + * A new thread starts by calling a procedure, passing it a void * that + * allows it to gain access to whatever data it needs. + */ +typedef void (*gp_thread_creation_callback_t) (P1(void *)); +int gp_create_thread(P2(gp_thread_creation_callback_t, void *)); + +#endif /* !defined(gpsync_INCLUDED) */ diff --git a/pstoraster/gs_btokn.ps b/pstoraster/gs_btokn.ps new file mode 100644 index 0000000000..7ad61f8a5a --- /dev/null +++ b/pstoraster/gs_btokn.ps @@ -0,0 +1,313 @@ +% Copyright 1993-2000 by Easy Software Products. +% Copyright 1994, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved. +% +% This file is part of GNU Ghostscript. +% +% GNU Ghostscript is distributed in the hope that it will be useful, but +% WITHOUT ANY WARRANTY. No author or distributor accepts responsibility +% to anyone for the consequences of using it or for whether it serves any +% particular purpose or works at all, unless he says so in writing. Refer +% to the GNU General Public License for full details. +% +% Everyone is granted permission to copy, modify and redistribute GNU +% Ghostscript, but only under the conditions described in the GNU General +% Public License. A copy of this license is supposed to have been given +% to you along with GNU Ghostscript so you can know your rights and +% responsibilities. It should be in a file named COPYING. Among other +% things, the copyright notice and this notice must be preserved on all +% copies. +% +% Aladdin Enterprises supports the work of the GNU Project, but is not +% affiliated with the Free Software Foundation or the GNU Project. GNU +% Ghostscript, as distributed by Aladdin Enterprises, does not require any +% GNU software to build or run it. + +% $Id: gs_btokn.ps 956 2000-03-08 23:15:43Z mike $ +% 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 +dup /SystemNames exch def .installsystemnames + +% 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 + +/.bosheader { % .bosheader + % + dup 0 currentobjectformat 127 add put % object format => BOS tag + 2 index 255 le 2 index 65531 le and { + % Use the short header format: tag toplen(1) totlen(2) + exch 4 add exch + 0 4 getinterval + dup 1 5 -1 roll put + } { + % Use the long header format: tag 0(1) toplen(2) totlen(4) + exch 8 add exch + 0 0 4 2 roll .bosobject exch pop exch pop % store with byte swapping + } ifelse % Stack: shortlen str + exch dup -8 bitshift exch 255 and % str hibyte lobyte + currentobjectformat 1 and 0 eq { % lsb first + exch + } if + 2 index 3 3 -1 roll put + 1 index 2 3 -1 roll put +} .bind 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 + +%%%% MRS - stderr instead of stdout, which is used for output... +/printobject { % printobject - + (%stderr) (w) file 2 index 2 index writeobject pop pop +} odef +/writeobject { % writeobject - + 3 copy exch + % We must allocate the array in local VM + % to avoid a possible invalidaccess. + .currentglobal false .setglobal exch 1 array astore exch .setglobal + .writeobjects pop pop pop +} odef + +% Implement binary error message output. + /.printerror + { $error /binary get .languagelevel 2 ge 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..5d4ada0e49 --- /dev/null +++ b/pstoraster/gs_ccfnt.ps @@ -0,0 +1,100 @@ +% 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 supports the work of the GNU Project, but is not +% affiliated with the Free Software Foundation or the GNU Project. GNU +% Ghostscript, as distributed by Aladdin Enterprises, does not require any +% GNU software to build or run it. + +% $Id: gs_ccfnt.ps 956 2000-03-08 23:15:43Z mike $ +% 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_cff.ps b/pstoraster/gs_cff.ps new file mode 100644 index 0000000000..515fe5d083 --- /dev/null +++ b/pstoraster/gs_cff.ps @@ -0,0 +1,614 @@ +% Copyright (C) 1997 Aladdin Enterprises. All rights reserved. +% +% This file is part of GNU Ghostscript. +% +% GNU Ghostscript is distributed in the hope that it will be useful, but +% WITHOUT ANY WARRANTY. No author or distributor accepts responsibility +% to anyone for the consequences of using it or for whether it serves any +% particular purpose or works at all, unless he says so in writing. Refer +% to the GNU General Public License for full details. +% +% Everyone is granted permission to copy, modify and redistribute GNU +% Ghostscript, but only under the conditions described in the GNU General +% Public License. A copy of this license is supposed to have been given +% to you along with GNU Ghostscript so you can know your rights and +% responsibilities. It should be in a file named COPYING. Among other +% things, the copyright notice and this notice must be preserved on all +% copies. +% +% Aladdin Enterprises supports the work of the GNU Project, but is not +% affiliated with the Free Software Foundation or the GNU Project. GNU +% Ghostscript, as distributed by Aladdin Enterprises, does not require any +% GNU software to build or run it. + +% $Id: gs_cff.ps 1159 2000-06-26 15:50:18Z mike $ +% Loader for CFF (compressed) fonts. +% The following are not implemented yet: +% Deleted entries in the Name Index +% Embedded PostScript +% Multiple Master fonts +% CIDFonts +% Chameleon fonts +% Synthetic fonts +% Also, Type 2 charstrings are converted into Type 1 fonts with +% CharstringType = 2, which may or may not be supported. + +100 dict begin + +% ---------------- Standard strings (actually names) ---------------- % + +/StandardStrings mark +% 0 + /.notdef /space /exclam /quotedbl /numbersign + /dollar /percent /ampersand /quoteright /parenleft + /parenright /asterisk /plus /comma /hyphen + /period /slash /zero /one /two + /three /four /five /six /seven + /eight /nine /colon /semicolon /less + /equal /greater /question /at /A + /B /C /D /E /F + /G /H /I /J /K + /L /M /N /O /P +% 50 + /Q /R /S /T /U + /V /W /X /Y /Z + /bracketleft /backslash /bracketright /asciicircum /underscore + /quoteleft /a /b /c /d + /e /f /g /h /i + /j /k /l /m /n + /o /p /q /r /s + /t /u /v /w /x + /y /z /braceleft /bar /braceright + /asciitilde /exclamdown /cent /sterling /fraction +% 100 + /yen /florin /section /currency /quotesingle + /quotedblleft /guillemotleft /guilsinglleft /guilsinglright /fi + /fl /endash /dagger /daggerdbl /periodcentered + /paragraph /bullet /quotesinglbase /quotedblbase /quotedblright + /guillemotright /ellipsis /perthousand /questiondown /grave + /acute /circumflex /tilde /macron /breve + /dotaccent /dieresis /ring /cedilla /hungarumlaut + /ogonek /caron /emdash /AE /ordfeminine + /Lslash /Oslash /OE /ordmasculine /ae + /dotlessi /lslash /oslash /oe /germandbls +% 150 + /onesuperior /logicalnot /mu /trademark /Eth + /onehalf /plusminus /Thorn /onequarter /divide + /brokenbar /degree /thorn /threequarters /twosuperior + /registered /minus /eth /multiply /threesuperior + /copyright /Aacute /Acircumflex /Adieresis /Agrave + /Aring /Atilde /Ccedilla /Eacute /Ecircumflex + /Edieresis /Egrave /Iacute /Icircumflex /Idieresis + /Igrave /Ntilde /Oacute /Ocircumflex /Odieresis + /Ograve /Otilde /Scaron /Uacute /Ucircumflex + /Udieresis /Ugrave /Yacute /Ydieresis /Zcaron +% 200 + /aacute /acircumflex /adieresis /agrave /aring + /atilde /ccedilla /eacute /ecircumflex /edieresis + /egrave /iacute /icircumflex /idieresis /igrave + /ntilde /oacute /ocircumflex /odieresis /ograve + /otilde /scaron /uacute /ucircumflex /udieresis + /ugrave /yacute /ydieresis /zcaron /exclamsmall + /Hungarumlautsmall /dollaroldstyle /dollarsuperior /ampersandsmall /Acutesmall + /parenleftsuperior /parenrightsuperior /twodotenleader /onedotenleader /zerooldstyle + /oneoldstyle /twooldstyle /threeoldstyle /fouroldstyle /fiveoldstyle + /sixoldstyle /sevenoldstyle /eightoldstyle /nineoldstyle /commasuperior +% 250 + /threequartersemdash /periodsuperior /questionsmall /asuperior /bsuperior + /centsuperior /dsuperior /esuperior /isuperior /lsuperior + /msuperior /nsuperior /osuperior /rsuperior /ssuperior + /tsuperior /ff /ffi /ffl /parenleftinferior + /parenrightinferior /Circumflexsmall /hyphensuperior /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 +% 300 + /colonmonetary /onefitted /rupiah /Tildesmall /exclamdownsmall + /centoldstyle /Lslashsmall /Scaronsmall /Zcaronsmall /Dieresissmall + /Brevesmall /Caronsmall /Dotaccentsmall /Macronsmall /figuredash + /hypheninferior /Ogoneksmall /Ringsmall /Cedillasmall /questiondownsmall + /oneeighth /threeeighths /fiveeighths /seveneighths /onethird + /twothirds /zerosuperior /foursuperior /fivesuperior /sixsuperior + /sevensuperior /eightsuperior /ninesuperior /zeroinferior /oneinferior + /twoinferior /threeinferior /fourinferior /fiveinferior /sixinferior + /seveninferior /eightinferior /nineinferior /centinferior /dollarinferior + /periodinferior /commainferior /Agravesmall /Aacutesmall /Acircumflexsmall +% 350 + /Atildesmall /Adieresissmall /Aringsmall /AEsmall /Ccedillasmall + /Egravesmall /Eacutesmall /Ecircumflexsmall /Edieresissmall /Igravesmall + /Iacutesmall /Icircumflexsmall /Idieresissmall /Ethsmall /Ntildesmall + /Ogravesmall /Oacutesmall /Ocircumflexsmall /Otildesmall /Odieresissmall + /OEsmall /Oslashsmall /Ugravesmall /Uacutesmall /Ucircumflexsmall + /Udieresissmall /Yacutesmall /Thornsmall /Ydieresissmall (001.000) + (001.001) (001.002) (001.003) /Black /Bold + /Book /Light /Medium /Regular /Roman + /Semibold +.packtomark def + +% ---------------- Standard encodings ---------------- % + +/StandardEncodings [ + +% StandardEncoding +mark + 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 + 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 + 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 + 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 + 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 + 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 + 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 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 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 + 0 111 112 113 114 0 115 116 117 118 119 120 121 122 0 123 + 0 124 125 126 127 128 129 130 131 0 132 133 0 134 135 136 + 137 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 138 0 139 0 0 0 0 140 141 142 143 0 0 0 0 + 0 144 0 0 0 145 0 0 146 147 148 149 0 0 0 0 +.packtomark + +% ExpertEncoding +mark + 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 + 1 229 230 0 231 232 233 234 235 236 237 238 13 14 15 99 + 239 240 241 242 243 244 245 246 247 248 27 28 249 250 251 252 + 0 253 254 255 256 257 0 0 0 258 0 0 259 260 261 262 + 0 0 263 264 265 0 266 109 110 267 268 269 0 270 271 272 + 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 + 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 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 304 305 306 0 0 307 308 309 310 311 0 312 0 0 313 + 0 0 314 315 0 0 316 317 318 0 0 0 158 155 163 319 + 320 321 322 323 324 325 0 0 326 150 164 169 327 328 329 330 + 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 + 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 + 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 +.packtomark + +] readonly def + +% ---------------- Standard Charsets ---------------- % + +% We include an explicit 0 at the beginning of each charset. + +/StandardCharsets [ + +% ISOAdobe +mark + 0 + 1 1 228 { } for +.packtomark + +% Expert +mark + 0 + 1 229 230 231 232 233 234 235 236 237 238 13 14 15 99 239 + 240 241 242 243 244 245 246 247 248 27 28 249 250 251 252 253 + 254 255 256 257 258 259 260 261 262 263 264 265 266 109 110 267 + 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 + 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 + 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 + 316 317 318 158 155 163 319 320 321 322 323 324 325 326 150 164 + 169 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 + 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 + 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 + 374 375 376 377 378 +.packtomark + +% ExpertSubset +mark + 0 + 1 231 232 235 236 237 238 13 14 15 99 239 240 241 242 243 + 244 245 246 247 248 27 28 249 250 251 253 254 255 256 257 258 + 259 260 261 262 263 264 265 266 109 110 267 268 269 270 272 300 + 301 302 305 314 315 158 155 163 320 321 322 323 324 325 326 150 + 164 169 327 328 329 330 331 332 333 334 335 336 337 338 339 340 + 341 342 343 344 345 346 +.packtomark + +] readonly def + +% ---------------- Font loading ---------------- % + +% ------ Utilities ------ % + +/advance { % advance - + f cff eq { /pos pos 3 -1 roll add store } { pop } ifelse +} def +/next { % - next + f read { 1 advance } if +} def +/nextstring { % nextstring + dup 0 eq { + pop () + } { + string f exch readstring pop dup length advance + } ifelse +} def +/card8 % - card8 + /next load +def +/card16 { % - card16 + card8 8 bitshift card8 add +} def +/offset { % offset + 0 exch { 8 bitshift next add } repeat +} def +/sid % - sid + /card16 load +def +/Index { % - Index + mark card16 dup 0 ne { + 1 exch next dup offset pop exch { + dup offset dup 4 -1 roll sub 3 1 roll exch + } repeat pop + } if pop .packtomark + [ exch { nextstring } forall ] readonly +} def +/tokens { % - tokens ... (op# = 12 means EOF) + { + f read not { 12 exit } if + 1 advance + dup 12 eq { pop next 32 add exit } if + dup 28 lt { exit } if + dup 32 lt { + 28 sub { + { card16 32768 xor 32768 sub } + { 4 offset dup 16#7fffffff gt { -1 32 bitshift add } if } + { tokenreal } + { 31 exit } + } exch get exec + } { + dup 247 lt { + 139 sub + } { + 247 sub { + { next 108 add } + { next 364 add } + { next 620 add } + { next 876 add } + { next 108 add neg } + { next 364 add neg } + { next 620 add neg } + { next 876 add neg } + % 255 is deliberately omitted and will cause a rangecheck + } exch get exec + } ifelse + } ifelse + } loop +} def +/tokenbuf 100 string def +/tokenput { % tokenput + tokenbuf 2 index 3 -1 roll put 1 add +} def +/tokenrealarray [ + (0123456789.E) { } forall + [(E) 0 get /tokenput cvx (-) 0 get] cvx + null % will give an error + (-) 0 get + { exit } +] readonly def +/tokenreal { % - tokenreal + 0 { + next exch 1 index -4 bitshift tokenrealarray exch get exec tokenput + % We must leave the byte on the stack temporarily so that + % the exit will see a consistent stack state. + 1 index 15 and tokenrealarray exch get exec tokenput exch pop + } loop + tokenbuf 0 3 -1 roll getinterval cvr exch pop +} def +/Dict { % Dict - + /opdict exch store { + mark tokens opdict exch .knownget { exec } if cleartomark + } loop cleartomark +} def +/idstring { % idstring + dup 391 lt { StandardStrings } { 391 sub strings } ifelse exch get +} def +/idname { % idname + idstring dup type /nametype ne { cvn } if +} def + +% ------ Top dictionary ------ % + +/offput { % offput - + currentdict exch aload length 1 add packedarray cvx + offsets 3 1 roll put +} def +/queueput { % queueput - + 16#7fffffff offsets { pop .min } forall + pos sub nextstring + 3 1 roll aload length 2 add packedarray cvx + [ queued aload pop counttomark 2 add -1 roll ] + /queued exch store +} def +/xxput { % xxput - + 3 1 roll exch put +} def +/putfi { % putfi - + FontInfo xxput +} def +/xdef { % xdef - + exch def +} def +/topdictops mark + 12 { exit } + 0 { idstring /version putfi } + 1 { idstring /Notice putfi } + 32 { idstring /Copyright putfi } + 2 { idstring /FullName putfi } + 3 { idstring /FamilyName putfi } + 4 { idstring /Weight putfi } + 33 { 0 ne /isFixedPitch putfi } + 34 { /ItalicAngle putfi } + 35 { /UnderlinePosition putfi } + 36 { /UnderlineThickness putfi } + 37 { /PaintType xdef } + 38 { /CharstringType xdef } + 39 { counttomark array astore /FontMatrix xdef } + 13 { /UniqueID xdef } + 5 { counttomark array astore /FontBBox xdef } + 40 { /StrokeWidth xdef } + 14 { counttomark array astore /XUID xdef } + 15 { + dup StandardCharsets length lt { + StandardCharsets exch get /charset xdef + } { + { queuecharset } offput + } ifelse + } + 16 { + dup StandardEncodings length lt { + /Encoding xdef + } { + { queueEncoding } offput + } ifelse + } + 17 { { readCharStrings } offput } + 18 { exch /readPrivate cvx 2 packedarray offput } +.dicttomark readonly def + +/readCharStrings { % readCharStrings - + /CharStringArray Index put +} def + +% ------ Charsets and encodings ------ % + +% Note: formats 1 and 2 can overflow the operand stack. +% We'll fix this if it ever becomes necessary. +/charsetformats [ +{ [ 0 CharStringArray length 1 sub { sid } repeat ] +} +{ [ 0 CharStringArray length 1 sub { + dup 0 eq { pop exit } if + sid card8 1 add 2 index .min { exch 1 sub 1 index 1 add } repeat pop + } loop ] +} +{ [ 0 CharStringArray length 1 sub { + dup 0 eq { pop exit } if + sid card16 1 add 2 index .min { exch 1 sub 1 index 1 add } repeat pop + } loop ] +} +] readonly def +/queuecharset { % queuecharset - + { readcharset } queueput +} def +/readcharset { % readcharset - + begin 0 () /SubFileDecode filter /f exch store + charsetformats next get exec /charset exch def end +} def + +/encodingformats [ +{ 1 1 next { next exch Encoding 3 1 roll put } for +} +{ 1 next { + next next 1 add { + % Stack: gid code + Encoding 1 index 3 index put + exch 1 add exch 1 add + } repeat pop + } repeat pop +} +] readonly def +/queueEncoding { % queueEncoding - + { readEncoding } queueput +} def +/readEncoding { % readEncoding - + begin 0 () /SubFileDecode filter /f exch store + /Encoding [ 256 { /.notdef } repeat ] def + next encodingformats 1 index 127 and get exec + 128 ge { + % Read supplementary encodings. + next { + Encoding next sid idname put + } repeat + } if end +} def + +% ------ Private dictionary ------ % + +/deltarray { % -mark- ... deltarray ... + 0 counttomark 1 sub { counttomark -1 roll add dup } repeat pop + counttomark array astore +} def + +/privatedictops mark + 12 { exit } + 6 { deltarray /BlueValues xdef } + 7 { deltarray /OtherBlues xdef } + 8 { deltarray /FamilyBlues xdef } + 9 { deltarray /FamilyOtherBlues xdef } + 41 { /BlueScale xdef } + 42 { /BlueShift xdef } + 43 { /BlueFuzz xdef } + 10 { 1 array astore /StdHW xdef } + 11 { 1 array astore /StdVW xdef } + 44 { deltarray /StemSnapH xdef } + 45 { deltarray /StemSnapV xdef } + 46 { 0 ne /ForceBold xdef } + 47 { /ForceBoldThreshold xdef } + 48 { /lenIV xdef } + 49 { /LanguageGroup xdef } + 50 { /ExpansionFactor xdef } + 51 { /initialRandomSeed xdef } + 19 { { readSubrs } offput } + 20 { /defaultWidthX xdef } + 21 { /nominalWidthX xdef } + % Multiple Master fonts only + 59 { /NDV xdef } + 60 { /CDV xdef } + 61 { /lenBuildCharArray xdef } +.dicttomark readonly def + +/readPrivate { % readPrivate - + exch 1 index f exch () /SubFileDecode filter /f exch def + /Private get begin //privatedictops Dict end + /f cff def advance +} def + +% ------ Main program ------ % + +% We need to pass the file as a parameter for the sake of the PDF +% interpreter. +/StartData { % StartData - + currentfile exch () /SubFileDecode filter ReadData +} def +/ReadData { % ReadData - + + % Initialize. + + 30 dict begin + /cff exch def + /pos 0 def + /resname exch cvlit def + + % Read the header. + + /f cff def + /vmajor next def + /vminor next def + /hdrsize next def + /aoffsize next def + + % Read the Indexes. + + /names Index def + /topdicts Index def + /strings Index def + /gsubrs Index def + + % Read the top Dicts. + + /offsets 50 dict def + /queued [] def + /opdict null def % reserve a slot + /fonts [ topdicts { + 0 () /SubFileDecode filter /f exch def + 40 dict begin + % Preload defaults that differ from PostScript defaults, + % or that are required. + /FontType 1 def + /PaintType 0 def + /CharstringType 2 def + /FontMatrix [0.001 0 0 0.001 0 0] def + /charset StandardCharsets 0 get def + /Encoding 0 def + /FontInfo 10 dict + dup /UnderlinePosition -100 put + dup /UnderlineThickness 50 put + def + /Private 20 dict + gsubrs length 0 ne { dup /GlobalSubrs gsubrs put } if + def + //topdictops Dict + currentdict end + } forall ] def + + % Read other tables with queued offsets. + + DEBUG { offsets length =only ( offsets) = flush } if + { /f cff def + offsets pos 2 copy .knownget not { pop pop exit } if + 3 1 roll undef exec + } loop + offsets length 0 ne { + (Error: missing tables at ) print [ offsets { pop } forall ] == + (Current position is ) print pos == + flush stop + } if + + % Process out-of-order tables. + + DEBUG { queued length =only ( queued) = flush } if + queued { exec } forall + + % Update Encoding and CharStrings. + + fonts { + begin + % Construct the real Encoding. + % The value of Encoding is either a number, for predefined + % encodings, or an array of mixed GIDs and names. + /Encoding mark Encoding + DEBUG { (Encoding: ) print dup === flush } if + dup type /integertype eq { + StandardEncodings exch get { idname } forall + } { + { + dup type /integertype eq { charset exch get idname } if + } forall + } ifelse .packtomark def + % Construct the CharStrings. + % Note that they may only correspond to an initial + % subset of the charset. + /CharStrings charset length CharStringArray length .min dict def + DEBUG { + charset length =only ( charset ) print + CharStringArray length =only ( CharStringArray) = + charset == flush + } if + 0 1 CharStrings maxlength 1 sub { + dup CharStringArray exch get + exch charset exch get idstring + CharStrings xxput + } for + % Remove unwanted entries. + currentdict /charset undef + currentdict /CharStringArray undef + end + } forall + + % Wrap up. + + resname mark 0 1 fonts length 1 sub { + DEBUG { dup =only ( ) print flush } if + dup names exch get + DEBUG { dup == flush } if + exch fonts exch get + dup /FontName 3 index put + 1 index exch definefont + } for .dicttomark + end % temporary dict + end % FontSetInit ProcSet + /FontSet defineresource pop + +} bind def + +% ---------------- Resource category definition ---------------- % + +currentdict end readonly + +languagelevel exch 2 .setlanguagelevel + +/FontSet /Generic /Category findresource dup length dict .copydict +/Category defineresource pop + +/FontSetInit exch /ProcSet defineresource pop + +.setlanguagelevel diff --git a/pstoraster/gs_cidfn.ps b/pstoraster/gs_cidfn.ps new file mode 100644 index 0000000000..f7f9265021 --- /dev/null +++ b/pstoraster/gs_cidfn.ps @@ -0,0 +1,466 @@ +% Copyright (C) 1995, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved. +% +% This file is part of GNU Ghostscript. +% +% GNU Ghostscript is distributed in the hope that it will be useful, but +% WITHOUT ANY WARRANTY. No author or distributor accepts responsibility +% to anyone for the consequences of using it or for whether it serves any +% particular purpose or works at all, unless he says so in writing. Refer +% to the GNU General Public License for full details. +% +% Everyone is granted permission to copy, modify and redistribute GNU +% Ghostscript, but only under the conditions described in the GNU General +% Public License. A copy of this license is supposed to have been given +% to you along with GNU Ghostscript so you can know your rights and +% responsibilities. It should be in a file named COPYING. Among other +% things, the copyright notice and this notice must be preserved on all +% copies. +% +% Aladdin Enterprises supports the work of the GNU Project, but is not +% affiliated with the Free Software Foundation or the GNU Project. GNU +% Ghostscript, as distributed by Aladdin Enterprises, does not require any +% GNU software to build or run it. + +% $Id: gs_cidfn.ps 956 2000-03-08 23:15:43Z mike $ +% ProcSet for implementing CIDFont and CIDMap resources. +% When this is run, systemdict is still writable. + +% ---------------- Defining CIDFont resources ---------------- % + +% Define a CIDFont resource. This is the defineresource implementation for +% the CIDFont resource category. + +/.cidfonttypes where { pop } { /.cidfonttypes 6 dict def } ifelse +.cidfonttypes begin + +% The key in .cidfonttypes is the CIDFontType value; +% the value is a procedure that takes a font name and the CIDFont dictionary +% and replaces the latter with a real font. + +0 { % CIDFontType 0 = FontType 9 + currentglobal 3 1 roll dup gcheck setglobal + dup /FontType 9 put + dup /FontMatrix known not { + dup /FontMatrix [0.001 0 0 0.001 0 0] put + dup /FDArray get { + /FontMatrix get [1000 0 0 1000 0 0] 1 index concatmatrix pop + } forall + } if + dup /FDArray get mark exch { + % Add pro forma entries + currentglobal exch dup gcheck setglobal + dup /FontType 1 put + dup /CharStrings mark /.notdef () .dicttomark put + dup /Encoding [] put + % Create a dummy Subrs array now, if there isn't one here + % already (which can only happen if we're giving another + % name to an existing font). + dup /Private get dup /Subrs known not { + dup /SubrCount .knownget { + array 1 index /Subrs 3 -1 roll put + } if readonly + } if pop + exch setglobal + dup /FontName .knownget not { () } if exch .buildfont1 exch pop + } forall ] 1 index /FDepVector 3 -1 roll put + 3 -1 roll setglobal + 1 index exch .buildfont9 exch pop +} bind def + +1 { % CIDFontType 1 = FontType 10 + dup /FontType 10 put + 1 index exch .buildfont10 exch pop +} bind def + +2 { % CIDFontType 2 = FontType 11 + dup /FontType 11 put + 1 index exch .buildfont11 exch pop +} bind def + +end % .cidfonttypes + +% ---------------- Reading CIDFontType 0 files ---------------- % + +30 dict begin + +% We add the following entries to the CIDFont dictionary, in addition to +% the ones documented by Adobe: +% ReadString - procedure for reading a string from the binary data +% SubrCache - dictionary for caching Subr arrays +% For CIDFonts where we read the data from disk incrementally: +% DataOffset - starting position of data in file +% (if data are in hex) OffsetMap - map from logical data positions to +% physical positions in file + +/StartData % <(Binary)|(Hex)> StartData - + % (currentdict is CID font dict) +{ % If we're loading a resource file, we can just save a + % pointer to the binary data and load it incrementally. + % Check for this by opening the resource file, + % positioning it to currentfile's position plus the + % data length, and checking for %%EndData. + mark + { currentfile fileposition + CIDFontName 100 string ResourceFileName (r) file + mark + { % Stack: (Binary)|(Hex) length -mark- pos resfile + % -mark- + 5 index (Hex) eq + { 1 index 3 index setfileposition + 1 index 5 index .skiphex + %**************** SKIP > AND WHITESPACE SOMEHOW + } + { 1 index 3 index 6 index add setfileposition + } + ifelse + 1 index 9 string readstring pop (%%EndData) ne { stop } if + } + .internalstopped { cleartomark closefile stop } if + pop % pop the mark + } + .internalstopped + { % File is not positionable, load the data now. + cleartomark exch (Hex) eq + { { currentfile exch readhexstring pop } } + { { currentfile exch readstring pop } } + ifelse /ReadString exch def + dup 65535 le + { string ReadString + } + { mark exch + { dup 0 eq { pop exit } if + dup 65535 min dup string ReadString + 3 1 roll sub + } + loop ] + } + ifelse + /GlyphData exch def + % If we were reading hex data, skip past the >. + /ReadString load 2 get { readhexstring } 0 get eq { + currentfile 0 (>) /SubFileDecode filter dup flushfile closefile + } if + /.vmreadstring cvx + } + { % File is positionable, just save a pointer. + % Stack: (Binary)|(Hex) length -mark- pos file + 4 1 roll + /DataOffset exch def + pop /GlyphData exch def + exch (Hex) eq + { % Hex data, build the offset map. + .buildoffsetmap + /.hexreadstring + } + { % Binary data, just skip over it. + currentfile DataOffset GlyphData add setfileposition + /.binaryreadstring + } + ifelse cvx + 2 packedarray cvx + } + ifelse /ReadString exch def + /SubrCache 10 dict def + CIDFontName currentdict /CIDFont defineresource pop + end % CID font dict + end % resource category dict +} bind def + +% Skip a given distance in an ASCIIHex encoded file. We use this at +% rendering time as well. +/.skiphex % .skiphex - +{ exch /ASCIIHexDecode filter dup 3 -1 roll () /SubFileDecode filter + dup flushfile closefile closefile +} bind def + +% Build the map from logical offsets to physical offsets in ASCIIHex +% encoded data. +/.buildoffsetmap +{ /OffsetMap GlyphData 256 idiv 8000 min array def + 2 dict begin + /block GlyphData OffsetMap length idiv def + 0 1 OffsetMap length 1 sub + { OffsetMap exch currentfile fileposition put + currentfile block .skiphex + } + for + GlyphData block mod dup 0 eq + { pop } + { currentfile exch .skiphex } + ifelse + end % scratch dict +} bind def + +currentdict end + +% ---------------- Rendering ---------------- % + +% ------ Generic ------ % + +% Read a string at a given offset in a "file" (binary file, ASCII hex file, +% or GlyphData in RAM). +/.binaryreadstring % .binaryreadstring + { dup 4 -1 roll DataOffset add setfileposition exch readstring pop + } bind def +/.hexreadstring % .hexreadstring +{ % Use the OffsetMap to get to the block of hex data, + % then skip to the correct position by reading. + GlyphData OffsetMap length idiv + % Stack: pos string file blocklen + 3 index 1 index idiv OffsetMap exch get + 2 index exch setfileposition + % Skip the next (pos % blocklen) hex bytes. + 4 -1 roll exch mod 1 index exch .skiphex + % Stack: string file + exch readhexstring pop +} bind def +/.vmreadstring % .vmreadstring +{ GlyphData .stringsreadstring +} bind def +/.stringsreadstring % .stringsreadstring + % +{ dup type /stringtype eq + { 3 1 roll length getinterval + } + { { % Stack: pos string glyphdata + dup 0 get length dup 4 index gt { exit } if + 4 -1 roll exch sub 3 1 roll + dup length 1 sub 1 exch getinterval + } + loop + % Stack: pos string glyphdata glyphdata[0]length + % We know no request can span more than 2 strings. + 3 index 3 index length add 1 index le + { % Request fits in a single string: just return a substring. + pop 0 get 3 1 roll length getinterval + } + { % Request spans 2 strings. Copy the first part. + 1 index 0 get 4 index 3 -1 roll 1 index sub getinterval + 2 index copy + % Copy the second part. + % Stack: pos str glyphdata str1 + length exch 1 get 0 3 index length + 3 index sub getinterval 2 index 3 1 roll putinterval + exch pop + } + ifelse + } + ifelse +} bind def + +% Interpret a byte string as a (big-endian) integer. +/.cvbsi % .cvbsi +{ 0 exch { exch 8 bitshift add } forall +} bind def + +% Read an integer from binary data. +/.readint % .readint +{ string ReadString .cvbsi +} bind def + +% Read the glyph data for a given CID. The CIDFont is currentdict. +% Note that the data must be read into the same VM as the CharStrings +% dictionary of the selected subfont. +/.readglyphdata { % .readglyphdata + currentdict /GlyphDirectory .knownget { + dup type /arraytype eq { + 1 index exch get + } { + 1 index exch .knownget not { null } if + } ifelse + dup null eq { + FDepVector 0 get exch + } { + FDBytes 0 eq { + FDepVector 0 get exch + } { + % Note: FDBytes > 1 is not supported. + dup 0 get FDepVector exch get + exch dup length 1 sub 1 exch getinterval + } ifelse + } ifelse + } { + FDBytes GDBytes add mul CIDMapOffset add + dup FDBytes .readint exch + FDBytes add dup GDBytes .readint + exch GDBytes add FDBytes add GDBytes .readint + % Stack: fd pos nextpos + 1 index sub dup 0 eq { + pop pop pop FDepVector 0 get null + } { + % Stack: fd pos len + FDepVector 4 -1 roll get + dup /CharStrings get gcheck .currentglobal exch .setglobal + % Stack: pos len subfont global + 4 2 roll string ReadString exch .setglobal + } ifelse + } ifelse +} bind def + +% ------ CIDFontType 0 ------ % + +% Read some Subrs for the current Type 1 subfont. +% The subfont's Private dict is currentdict; the CIDFont itself is the +% next dictionary on the stack. +/.readsubrs { % .readsubrs + 1 SubrCount 1 sub { + dup SDBytes mul SubrMapOffset add + dup SDBytes .readint exch SDBytes add SDBytes .readint + 1 index sub string ReadString 2 index 3 1 roll put + } for +} bind def + +% Ensure that all the Subrs for the current Type 1 subfont are loaded. +% The subfont's Private dict is currentdict; the CIDFont itself is the +% next dictionary on the stack. +/.loadsubrs { + currentdict /SubrMapOffset .knownget { + Subrs 0 get null ne { + pop % We've already loaded the Subrs. + } { + currentglobal exch currentdict gcheck setglobal + SubrCache 1 index .knownget { + % We've already loaded some Subrs at this offset. + % Make sure we've got as many as we need. + dup length SubrCount lt { + % We need to load more. + SubrCount array exch 1 index copy length .readsubrs + SubrCache 3 -1 roll 2 index put + } if + } { + % We haven't loaded any Subrs at this offset yet. + SubrCount array 0 .readsubrs + SubrCache 3 -1 roll 2 index put + } ifelse + Subrs copy pop setglobal + } ifelse + } if +} bind def + +% BuildGlyph procedure for CIDFontType 0. +% ****** WHY NOT USE .type1execchar FOR THIS? ****** +% The name %Type9BuildGlyph is known to the interpreter. +/.cid0buildstring 10 string def +(%Type9BuildGlyph) cvn { % %Type9BuildGlyph - + .currentglobal 3 1 roll 1 index gcheck .setglobal + 1 index begin + dup .readglyphdata dup null eq + { %**** HANDLE NOTDEF **** + } + if + % Stack: cidfont cid subfont charstring +dup null eq { pop pop pop pop } { %**** WRONG **** + 4 -1 roll pop + exch dup /Private get begin .loadsubrs end + 3 -1 roll //.cid0buildstring cvs cvn 3 1 roll + dup /CharStrings get 3 index 4 -1 roll put + setfont + 1000 0 setcharwidth %**** WRONG **** + 0 0 moveto glyphshow +} ifelse %**** WRONG **** + end + .setglobal +} bind def + +% ------ CIDFontType 2 ------ % + +% BuildGlyph procedure for CIDFontType 2. +% ****** ADD THE OUTLINE STRING AS AN ARGUMENT TO .type42execchar. ****** +% The name %Type11BuildGlyph is known to the interpreter. +(%Type11BuildGlyph) cvn { % %Type11BuildGlyph - + .currentglobal 3 1 roll 1 index gcheck .setglobal + 1 index begin + % We must be prepared for out-of-range CIDs. + dup GDBytes mul GDBytes string CIDMap + mark 4 1 roll { .stringsreadstring } .internalstopped { + %**** 0 IS WRONG + cleartomark 0 GDBytes string CIDMap .stringsreadstring + } { + exch pop + } ifelse .cvbsi + % Stack: cidfont cid glyphindex +%**************** GlyphDirectory is not supported yet. +( + currentdict /GlyphDirectory .knownget +) pop false + { dup type /arraytype eq + { 1 index exch get } + { 1 index exch .knownget not { null } if } + ifelse + dup null eq + { %**** HANDLE NOTDEF + } + if + 1 index exch .type42execchar + } + { 1 index exch .type42execchar + } + ifelse + end + .setglobal +} bind def + +% ---------------- Define resources ---------------- % + +languagelevel exch 2 .setlanguagelevel + +% Define the CIDInit ProcSet resource. +% The ProcSet dictionary is still on the stack. + +/CMap /Generic /Category findresource dup length dict .copydict +/Category defineresource pop + % We might have loaded CMap support already. +/CIDInit /ProcSet 2 copy resourcestatus { + pop pop findresource dup length 4 index length add dict .copydict + 4 -1 roll exch .copydict +} { + 3 -1 roll +} ifelse exch defineresource pop + +% Define the CIDFont resource category. +% We break out .buildcidfont because it appears that at least for +% Type 32 (CIDFontType 4) fonts, the font can be registered in the Font +% category with only a CIDFontType and no FontType. +/.buildcidfont { % .buildcidfont + % + dup /CIDFontType get //.cidfonttypes exch get exec +} odef + +/CIDFont /Generic /Category findresource dup length dict .copydict +dup /InstanceType /dicttype put +dup /DefineResource { + .buildcidfont + /Generic /Category findresource /DefineResource get exec +} put +/Category defineresource pop + +% Add the new FontType resources. + +9 1 11 { dup /FontType defineresource pop } for + +% Add the new FMapType resource. + +9 dup /FMapType defineresource pop + +% Define the CIDMap resource category. +% These aren't documented, but it's clear what they are for: +% to give names to CIDMaps for CIDFontType 2 fonts. + +/CIDMap /Generic /Category findresource dup length dict .copydict +dup /.CheckResource { + % Allow either a string or an array of strings. + dup type dup /stringtype eq + { pop true + } + { dup /arraytype eq exch /packedarraytype eq or + { true exch { type /stringtype ne { pop false exit } if } forall + } + { false + } + ifelse + } + ifelse +} bind put +/Category defineresource pop + +.setlanguagelevel diff --git a/pstoraster/gs_cmap.ps b/pstoraster/gs_cmap.ps new file mode 100644 index 0000000000..e2ce96d65f --- /dev/null +++ b/pstoraster/gs_cmap.ps @@ -0,0 +1,256 @@ +% Copyright (C) 1995, 1996, 1997 Aladdin Enterprises. All rights reserved. +% +% This file is part of GNU Ghostscript. +% +% GNU Ghostscript is distributed in the hope that it will be useful, but +% WITHOUT ANY WARRANTY. No author or distributor accepts responsibility +% to anyone for the consequences of using it or for whether it serves any +% particular purpose or works at all, unless he says so in writing. Refer +% to the GNU General Public License for full details. +% +% Everyone is granted permission to copy, modify and redistribute GNU +% Ghostscript, but only under the conditions described in the GNU General +% Public License. A copy of this license is supposed to have been given +% to you along with GNU Ghostscript so you can know your rights and +% responsibilities. It should be in a file named COPYING. Among other +% things, the copyright notice and this notice must be preserved on all +% copies. +% +% Aladdin Enterprises supports the work of the GNU Project, but is not +% affiliated with the Free Software Foundation or the GNU Project. GNU +% Ghostscript, as distributed by Aladdin Enterprises, does not require any +% GNU software to build or run it. + +% $Id: gs_cmap.ps 956 2000-03-08 23:15:43Z mike $ +% ProcSet for implementing CMap resources. +% When this is run, systemdict is still writable. + +% NOTE: Rearranged fonts are not implemented yet. + +% ---------------- Public operators ---------------- % + +% composefont doesn't appear in CMap files -- it's documented in +% the "PostScript Language Reference Manual Supplement". +/composefont { % composefont + 10 dict begin + /CMap 2 index dup type /dicttype ne { /CMap findresource } if def + /Encoding [ 0 1 4 index length 1 sub { } for ] def + /FDepVector [ 2 index { + dup type /dicttype ne { + dup /CIDFont resourcestatus { + pop pop /CIDFont findresource + } { + /Font findresource + } ifelse + } if + } forall ] readonly def + /FMapType 9 def + /FontMatrix matrix def + /FontName 3 index def + /CMap load /WMode .knownget { /WMode exch def } if + /FontType 0 def + pop pop currentdict end /Font defineresource +} bind odef + +% ---------------- CMap operators ---------------- % + +30 dict begin + +% Our internal .CodeMaps structure is an array of two arrays: array 0 +% is the map for defined characters, array 1 is the map for notdefs. +% Both are multi-level arrays indexed by the successive bytes of the +% character code. Each value is either a sub-array, null, a character name, +% a CID (an integer), or a character code (expressed as a byte string). +% All of the arrays are read-only after they have been built. +% +% Note that the code in zfcmap.c that constructs the C structures from +% the PostScript structures has intimate knowledge of the above format. + +/.getmap { .CodeMaps exch get } bind def +/.putmap { .CodeMaps exch 3 -1 roll put } bind def + +% ------ Font-level operators ------ % + +/begincmap % - begincmap - + { /.CodeMaps [256 array 256 array] def + } bind def +/endcmap % - endcmap - + { /.CodeMaps .CodeMaps .endmap def + /CodeMap null def % for .buildcmap + currentdict end .buildcmap begin + } bind def + +/begincodespacerange % begincodespacerange - + { pop mark + } bind def +/endcodespacerange % ... endcodespacerange - + { counttomark 2 idiv + { .CodeMaps { 3 copy .addcodespacerange pop } forall pop pop + } 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 + { 0 .getmap .endmapchar 0 .putmap + } bind def + +/beginbfrange % beginbfrange - + { pop mark + } bind def +/endbfrange % ... + % endbfrange - + { 0 .getmap counttomark 3 idiv { .addbfrange } repeat 0 .putmap 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 - + { 0 .getmap .endmapchar 0 .putmap + } bind def + +/begincidrange % begincidrange - + { pop mark + } bind def +/endcidrange % ... endcidrange - + { 0 .getmap counttomark 3 idiv { { 1 add } exch .addmaprange exch pop } repeat + 0 .putmap pop + } bind def + +/.endmapchar % -mark- ... .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 - + { { } 1 .getmap .addmaprange 1 .putmap pop + } bind def + +% ---------------- Resource category definition ---------------- % + +currentdict end + +languagelevel exch 2 .setlanguagelevel + +/CMap /Generic /Category findresource dup length dict .copydict +/Category defineresource pop + % We might have loaded CID font support already. +/CIDInit /ProcSet 2 copy { findresource } .internalstopped + % An interior `stopped' might have reset VM allocation to local. +true .setglobal + { pop pop 3 -1 roll } + { dup length 4 index length add dict .copydict 4 -1 roll exch .copydict } +ifelse exch defineresource pop + +.setlanguagelevel diff --git a/pstoraster/gs_cmdl.ps b/pstoraster/gs_cmdl.ps new file mode 100644 index 0000000000..7293e09232 --- /dev/null +++ b/pstoraster/gs_cmdl.ps @@ -0,0 +1,188 @@ +% 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 supports the work of the GNU Project, but is not +% affiliated with the Free Software Foundation or the GNU Project. GNU +% Ghostscript, as distributed by Aladdin Enterprises, does not require any +% GNU software to build or run it. + +% $Id: gs_cmdl.ps 956 2000-03-08 23:15:43Z mike $ +% 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..b31a392281 --- /dev/null +++ b/pstoraster/gs_dbt_e.ps @@ -0,0 +1,67 @@ +% 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 supports the work of the GNU Project, but is not +% affiliated with the Free Software Foundation or the GNU Project. GNU +% Ghostscript, as distributed by Aladdin Enterprises, does not require any +% GNU software to build or run it. + +% $Id: gs_dbt_e.ps 956 2000-03-08 23:15:43Z mike $ +% 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..eedd980826 --- /dev/null +++ b/pstoraster/gs_diskf.ps @@ -0,0 +1,232 @@ +% 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 supports the work of the GNU Project, but is not +% affiliated with the Free Software Foundation or the GNU Project. GNU +% Ghostscript, as distributed by Aladdin Enterprises, does not require any +% GNU software to build or run it. + +% $Id: gs_diskf.ps 956 2000-03-08 23:15:43Z mike $ +% 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_dpnxt.ps b/pstoraster/gs_dpnxt.ps new file mode 100644 index 0000000000..2d2573ff7d --- /dev/null +++ b/pstoraster/gs_dpnxt.ps @@ -0,0 +1,120 @@ +% Copyright (C) 1997, 1998 Aladdin Enterprises. All rights reserved. +% +% This file is part of GNU Ghostscript. +% +% GNU Ghostscript is distributed in the hope that it will be useful, but +% WITHOUT ANY WARRANTY. No author or distributor accepts responsibility +% to anyone for the consequences of using it or for whether it serves any +% particular purpose or works at all, unless he says so in writing. Refer +% to the GNU General Public License for full details. +% +% Everyone is granted permission to copy, modify and redistribute GNU +% Ghostscript, but only under the conditions described in the GNU General +% Public License. A copy of this license is supposed to have been given +% to you along with GNU Ghostscript so you can know your rights and +% responsibilities. It should be in a file named COPYING. Among other +% things, the copyright notice and this notice must be preserved on all +% copies. +% +% Aladdin Enterprises supports the work of the GNU Project, but is not +% affiliated with the Free Software Foundation or the GNU Project. GNU +% Ghostscript, as distributed by Aladdin Enterprises, does not require any +% GNU software to build or run it. + +% $Id: gs_dpnxt.ps 956 2000-03-08 23:15:43Z mike $ +% gs_dpnxt.ps +% NeXT Display PostScript extensions + +% Define the operation values for compositing. These must match the values +% in gsdpnext.h, which also are the ones from the NeXT documentation. +% We put them in systemdict, which seems like as good a place as any. +mark + /Clear /Copy /Sover /Sin /Sout /Satop /Dover /Din /Dout /Datop /Xor + /PlusD /PlusL /Highlight % not sure about Highlight +counttomark { counttomark 1 sub def } repeat pop + +% We implement readimage and sizeimage using the following 3 otherwise +% undocumented lower-level operators: +% +% .sizeimagebox +% +% +% - .sizeimageparams +% +% +% .getbitsrect +% +% NOTE: These operators are subject to change without notice! + +% Implement readimage using .getbitsrect. Experimentation on a NeXT system +% shows that the data is always returned in order of increasing device Y, +% regardless of the CTM. +% +% Note that we can't make stack protection work for this operator, +% because it must remove its operands from the stack before calling +% the supplied procedure(s). + +/readimage { % [... ] + % readimage - + .sizeimageparams exch { + % multiproc = true. If N > 1, store the procedures in an array. + exch pop 1 index { 1 add } if + % Stack: ... string alpha? nprocs + dup 1 eq { + pop false % only 1 procedure, multiproc is irrelevant + } { + dup array 4 1 roll 3 add 2 roll astore 3 1 roll true + } ifelse + } { + % multiproc = false. + pop pop false + } ifelse + % Map the rectangle to device coordinates. + % Stack: x y w h proc(s) str alpha? multi? + 8 -4 roll matrix .sizeimagebox pop 8 4 roll + % Make sure we allocate the operand array in local VM + % to avoid a possible invalidaccess. + .currentglobal false .setglobal 9 1 roll + exch { 1 } { 0 } ifelse exch % alpha is last, if present + exch 4 1 roll 8 array astore exch .setglobal + { % Read out a block of scan lines and pass them to the procedure. + % Stack: [x y w h alpha? proc(s) str multi?] -- we must consume this. + dup 3 get 0 eq { pop exit } if + aload 9 1 roll pop exch pop currentdevice 7 1 roll + % Always read out the data as standard (not native) pixels. + .sizeimageparams pop pop exch .getbitsrect + % Stack: [x y w h alpha? proc(s) str multi?] hread substr + 3 -1 roll + % Stack: hread substr [x y w h alpha? proc(s) str multi?] + dup 1 2 copy get 5 index add put + % Stack: hread substr [x y' w h alpha? proc(s) str multi?] + dup 3 2 copy get 6 -1 roll sub put + % Stack: substr [x y' w h' alpha? proc(s) str multi?] + dup 5 get exch 7 get { + % multiproc = true, pass each plane to a different procedure. + % Stack: substr procs + 0 1 2 index length 1 sub { + % Push 1 plane and its procedure under the top 2 elements. + % Stack: ... substr procs plane# + 2 index length 2 index length idiv % bytes per plane + dup 2 index mul exch + % Stack: ... substr procs plane# start length + 4 index 3 1 roll getinterval 4 1 roll + 2 copy get 4 1 roll pop + } for + exch pop length 2 mul .execn + } { + % multiproc = false, just call the procedure. + exec + } ifelse + } //systemdict /exec get 3 packedarray cvx loop +} bind odef + +% Implement sizeimage using lower-level operators. + +/sizeimage { % sizeimage + % + % + .sizeimagebox 5 -2 roll pop pop + .sizeimageparams 3 -1 roll 4 1 roll +} bind odef diff --git a/pstoraster/gs_dps.ps b/pstoraster/gs_dps.ps new file mode 100644 index 0000000000..354d8155b5 --- /dev/null +++ b/pstoraster/gs_dps.ps @@ -0,0 +1,205 @@ +% Copyright (C) 1997, 1998 Aladdin Enterprises. All rights reserved. +% +% This file is part of GNU Ghostscript. +% +% GNU Ghostscript is distributed in the hope that it will be useful, but +% WITHOUT ANY WARRANTY. No author or distributor accepts responsibility +% to anyone for the consequences of using it or for whether it serves any +% particular purpose or works at all, unless he says so in writing. Refer +% to the GNU General Public License for full details. +% +% Everyone is granted permission to copy, modify and redistribute GNU +% Ghostscript, but only under the conditions described in the GNU General +% Public License. A copy of this license is supposed to have been given +% to you along with GNU Ghostscript so you can know your rights and +% responsibilities. It should be in a file named COPYING. Among other +% things, the copyright notice and this notice must be preserved on all +% copies. +% +% Aladdin Enterprises supports the work of the GNU Project, but is not +% affiliated with the Free Software Foundation or the GNU Project. GNU +% Ghostscript, as distributed by Aladdin Enterprises, does not require any +% GNU software to build or run it. + +% $Id: gs_dps.ps 956 2000-03-08 23:15:43Z mike $ +% Initialization file for Display PostScript functions. + +% ------ Contexts ------ % + +% To create a context with private local VM, we use the .localfork +% operator to actually create the context, the new VM, and an empty +% userdict, and then we call the .initlocaldicts procedure to make +% local copies of the initial contents of the dictionaries in local VM. +% savedlocaldicts in systemdict is a global read-only dictionary whose +% elements are global read-only copies of these initial contents; +% we just copy its elements into local VM and install them in systemdict. +% userdict and internaldict require special handling. + +% Switching between contexts with different local VMs requires +% changing the bindings in systemdict that reference local objects. +% For this purpose, each userdict has an entry called localdicts +% which holds the local copies of the elements of savedlocaldicts, +% plus internaldict. The context switching code in the interpreter +% effectively copies this dictionary into systemdict. +% NOTE: the name localdicts is known to the interpreter. + +% Switching between contexts also requires resetting the user parameters. +% The interpreter records the value of userparams (a local dictionary +% referenced from systemdict) for each context, and uses it for this. +% See gs_lev2.ps for more details. +% NOTE: the name userparams is known to the interpreter. + +% Save copies of local dictionaries at the end of system initialization. +% Also save the initial gstate. +/.savelocalstate { + .currentglobal true .setglobal + //systemdict /savedlocaldicts mark //systemdict { + dup gcheck { + pop pop + } { + dup type /dicttype eq { + % Save a copy of this dictionary in global VM. + dup maxlength dict .copydict readonly + } { + pop pop + } ifelse + } ifelse + } forall .dicttomark readonly .forceput % systemdict is read-only + % Create localdicts for the current context. + false .setglobal + userdict /localdicts mark savedlocaldicts { + pop dup load + } forall /internaldict dup load + .dicttomark readonly put + % Save a copy of the initial gstate. + true .setglobal + //systemdict /savedinitialgstate gstate readonly put + .setglobal +} .bind def + +% Initialize local dictionaries and gstate when creating a new context. +% Note that until this completes, we are in the anomalous situation of +% having systemdict point to dictionaries that are in a non-current +% local VM. Because of this, we turn off garbage collection temporarily. +/.copylocal { % .copylocal + % Copy a dictionary to the current (local) VM, + % and make it read-only if its current definition is. + dup maxlength dict .copydict + 1 index load wcheck not { readonly } if +} .bind def +% When this is called, the dictionary stack is in its initial state, +% and there is (anomalously) only one gstate on the gstate stack. +/.initlocaldicts { % - .initlocaldicts - + -2 vmreclaim + .currentglobal //systemdict begin + false .setglobal + % Since localdicts doesn't exist yet, references from + % systemdict to local objects won't get restored if + % a context switch happens in this code. Therefore, + % until localdicts is defined, we have to keep all our + % state on the operand stack. + + % Acquire userdict. + %****** WRONG IF NON-STANDARD INITIAL DSTACK ****** + countdictstack array dictstack + { dup gcheck not { exit } if pop } forall + % Create localdicts with a local copy of each dictionary, + % except for userdict and userparams, which just need + % to be filled in. + mark savedlocaldicts { + 1 index /userdict eq { + % Stack: userdict mark ... /userdict inituserdict + counttomark 1 add index exch .copydict + } { + 1 index /userparams eq { + % Stack: userparams mark ... /userparams inituserparams + userparams .copydict + } { + .copylocal + } ifelse + } ifelse + } forall /internaldict dup .makeinternaldict .makeoperator + .dicttomark readonly /localdicts exch put + % localdicts is now defined in userdict. + % Copy the definitions into systemdict. + localdicts { .forcedef } forall + % Set the user parameters. + userparams readonly .setuserparams + % Establish the initial gstate(s). + /savedinitialgstate .systemvar setgstate gsave + % Wrap up. + end .setglobal +} odef + +% Create a context with private local VM. +% The .localfork operator does all the work, but we must ensure that +% .initlocaldicts gets called when the new context starts up. +/localfork { % ... + % + % localfork + .currentglobal true .setglobal 3 index + dup dup xcheck + exch type dup /arraytype eq exch /packedarraytype eq or and not { + pop .setglobal /localfork cvx /typecheck signalerror + } if + {exec .initlocaldicts} aload pop + 3 1 roll 3 packedarray cvx + 4 1 roll 5 -1 roll pop .setglobal .localfork +} odef + +% Fork a context that shares VM. We still need to fill in userparams +% when the new context starts up. +/.postfork { % - .postfork - + % Initialize the user parameters. + savedlocaldicts /userparams get userparams .copydict readonly pop +} odef +/fork { % ... fork + .currentglobal false .setglobal 1 index + dup dup xcheck + exch type dup /arraytype eq exch /packedarraytype eq or and not { + pop .setglobal /fork cvx /typecheck signalerror + } if + {exec .postfork} aload pop + 3 1 roll 3 packedarray cvx + 3 1 roll exch pop .setglobal .fork +} odef + +% ------ Halftone phase ------ % + +/sethalftonephase { % sethalftonephase - + -1 2 index 2 index .setscreenphase pop pop +} odef +/currenthalftonephase { % - currenthalftonephase + 0 .currentscreenphase +} odef + +% ------ Device-source images ------ */ + +.imagetypes 2 /.image2 load put + +% ------ Device information ------ % + +/.deviceinfodict mark + /Colors null /GrayValues null /RedValues null /GreenValues null + /BlueValues null /ColorValues null +.dicttomark readonly def +/deviceinfo { % - deviceinfo + currentdevice //.deviceinfodict .getdeviceparams .dicttomark readonly +} odef + +% The current implementation allocates a 2-element array each time. +% Perhaps we should change this to 2 separate parameters for X and Y? +/.wtdict mark + /wtranslation null +.dicttomark readonly def +/wtranslation { % - wtranslation + currentdevice //.wtdict .getdeviceparams exch pop exch pop aload pop +} odef +currentdict /.wtdict .undef + +% ------ View clipping ------ % + +/rectviewclip { % rectviewclip - + % rectviewclip - + newpath .rectappend viewclip +} odef diff --git a/pstoraster/gs_dps1.ps b/pstoraster/gs_dps1.ps new file mode 100644 index 0000000000..f343b571a2 --- /dev/null +++ b/pstoraster/gs_dps1.ps @@ -0,0 +1,147 @@ +% Copyright (C) 1997 Aladdin Enterprises. All rights reserved. +% +% This file is part of GNU Ghostscript. +% +% GNU Ghostscript is distributed in the hope that it will be useful, but +% WITHOUT ANY WARRANTY. No author or distributor accepts responsibility +% to anyone for the consequences of using it or for whether it serves any +% particular purpose or works at all, unless he says so in writing. Refer +% to the GNU General Public License for full details. +% +% Everyone is granted permission to copy, modify and redistribute GNU +% Ghostscript, but only under the conditions described in the GNU General +% Public License. A copy of this license is supposed to have been given +% to you along with GNU Ghostscript so you can know your rights and +% responsibilities. It should be in a file named COPYING. Among other +% things, the copyright notice and this notice must be preserved on all +% copies. +% +% Aladdin Enterprises supports the work of the GNU Project, but is not +% affiliated with the Free Software Foundation or the GNU Project. GNU +% Ghostscript, as distributed by Aladdin Enterprises, does not require any +% GNU software to build or run it. + +% $Id: gs_dps1.ps 956 2000-03-08 23:15:43Z mike $ +% Initialization file for most of the Display PostScript functions +% that are also included in Level 2. + +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 + .forcedef % LocalFontDirectory is local, systemdict is global + .setglobal .FontDirectory + } + { /LocalFontDirectory .FontDirectory + .forcedef % LocalFontDirectory is local, systemdict is global + 50 dict + } +ifelse def + +end % systemdict +level2dict begin + +% setshared must rebind FontDirectory to the appropriate one of +% Local or SharedFontDirectory. + +/.setglobal % .setglobal - + { dup .setglobal + //systemdict /FontDirectory .currentglobal + { //SharedFontDirectory } + { /LocalFontDirectory .systemvar } % can't embed ref to local VM + ifelse .forceput pop % LocalFontDirectory is local, systemdict is global + } .bind odef % must bind .forceput and .setglobal + % even if NOBIND in effect +/setshared /.setglobal load def +.currentglobal setshared + +% See below for changes in save and restore. + +% ------ Fonts ------ % + +/selectfont % selectfont - + { 1 index findfont + 1 index dup type /arraytype eq { makefont } { scalefont } ifelse + setfont pop pop + } odef +% undefinefont has to take local/global VM into account. +/undefinefont % undefinefont - + { .FontDirectory 1 index .undef + .currentglobal + { % Current mode is global; delete from local directory too. + //systemdict /LocalFontDirectory .knownget + { 1 index .undef } + if + } + { % Current mode is local; if there was a shadowed global + % definition, copy it into the local directory. + //systemdict /SharedFontDirectory .knownget + { 1 index .knownget + { .FontDirectory 2 index 3 -1 roll put } + if + } + if + } + ifelse pop + } 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 - + { dup //restore % bind even if NOBIND + /LocalFontDirectory .systemvar + 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 + .currentglobal .setglobal % Rebind FontDirectory according to current VM. + pop + } bind odef + +% ------ Miscellaneous ------ % + +/undef /.undef load def + +end % level2dict diff --git a/pstoraster/gs_dps2.ps b/pstoraster/gs_dps2.ps new file mode 100644 index 0000000000..e375505ab4 --- /dev/null +++ b/pstoraster/gs_dps2.ps @@ -0,0 +1,200 @@ +% Copyright (C) 1990, 1996, 1997 Aladdin Enterprises. All rights reserved. +% +% This file is part of GNU Ghostscript. +% +% GNU Ghostscript is distributed in the hope that it will be useful, but +% WITHOUT ANY WARRANTY. No author or distributor accepts responsibility +% to anyone for the consequences of using it or for whether it serves any +% particular purpose or works at all, unless he says so in writing. Refer +% to the GNU General Public License for full details. +% +% Everyone is granted permission to copy, modify and redistribute GNU +% Ghostscript, but only under the conditions described in the GNU General +% Public License. A copy of this license is supposed to have been given +% to you along with GNU Ghostscript so you can know your rights and +% responsibilities. It should be in a file named COPYING. Among other +% things, the copyright notice and this notice must be preserved on all +% copies. +% +% Aladdin Enterprises supports the work of the GNU Project, but is not +% affiliated with the Free Software Foundation or the GNU Project. GNU +% Ghostscript, as distributed by Aladdin Enterprises, does not require any +% GNU software to build or run it. + +% $Id: gs_dps2.ps 956 2000-03-08 23:15:43Z mike $ +% Initialization file for basic Display PostScript functions +% that are also included in Level 2. + +level2dict begin + +% ------ Halftones ------ % + +/.makestackdict + { { counttomark -1 roll } forall .dicttomark + } bind def +/currenthalftone % - 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 { % sethalftone - + % We must create the new dictionary in the same VM as the + % operand; otherwise, invalidaccess errors may occur. + .currentglobal 1 index dup gcheck .setglobal + 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 .setglobal pop +} 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 % .fix...screen + % + { dup dup /HalftoneType get 1 eq + { dup wcheck not { dup length .copydict } if + dup /Frequency 5 index put + dup /Angle 4 index put + } + if + } bind def +/setscreen % setscreen - + { dup type /dicttype eq + { .fixsethalftonescreen sethalftone pop pop pop } + { //setscreen } + ifelse + } odef +/setcolorscreen % setcolorscreen - + { dup type /dicttype eq + { .fixsethalftonescreen sethalftone 12 { 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 % - currentscreen 60 0 + { .currenthalftone + { { .fixcurrenthalftonescreen } % halftone + { } % screen + { 12 3 roll 9 { pop } repeat % colorscreen + dup type /dicttype eq { .fixcurrenthalftonescreen } if + } + } + exch get exec + } odef +/currentcolorscreen % - currentcolorscreen (60 0 )*4 + { .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 +/.UserObjects { + .userdict /UserObjects +} odef +% In order to get proper error recovery behavior, we need to be careful +% not to pop any operands from the stack until we're done. +% The code below faithfully duplicates the apparent array-growing +% behavior of Adobe interpreters. +/defineuserobject { % defineuserobject - + .UserObjects .knownget { + length dup 3 index le { + % Stack: index value len + 2 index eq { 1 index 2 mul } { 1 index 1 add } ifelse + .localarray .UserObjects get + 1 index copy pop + .UserObjects 3 -1 roll put + } { + pop + } ifelse + } { + .UserObjects 3 index 1 add 10 .max .localarray put + } ifelse + .UserObjects get 2 index 2 index put pop pop +} odef +/execuserobject { % execuserobject - + .UserObjects get 1 index get exch pop exec +} odef +/undefineuserobject { % undefineuserobject - + .UserObjects get 1 index null put pop +} odef + +% ------ Cache control ------ % + +% Dummy definitions for cache control operators + +/ucachestatus { % - ucachestatus -mark- ? ? ? ? + mark 0 0 0 0 .userdict /.ucachesize .knownget not { 0 } if +} odef +/setucacheparams { % -mark- ... setucacheparams - + % Provoke an appropriate error if needed. + counttomark 1 lt { () 0 get } if + 0 or .userdict /.ucachesize 2 index 0 .max put cleartomark +} odef + +end % level2dict diff --git a/pstoraster/gs_epsf.ps b/pstoraster/gs_epsf.ps new file mode 100644 index 0000000000..fcccb3e330 --- /dev/null +++ b/pstoraster/gs_epsf.ps @@ -0,0 +1,67 @@ +% 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 supports the work of the GNU Project, but is not +% affiliated with the Free Software Foundation or the GNU Project. GNU +% Ghostscript, as distributed by Aladdin Enterprises, does not require any +% GNU software to build or run it. + +% $Id: gs_epsf.ps 956 2000-03-08 23:15:43Z mike $ +% Allow the interpreter to recognize MS-DOS EPSF file headers, and skip to +% the PostScript section of the file. + +/.runnoepsf /run load def +/.epsfheader def +/run + { dup type /filetype ne { (r) file } if + % Check for MS-DOS EPSF file (see Red Book p. 729). + true exch 0 1 3 + { % Stack: true file index + 1 index read dup { pop dup .epsfheader 3 index get eq } if + { pop pop } % if matched, don't need the character + { % unread characters (wasn't EPSF) + 2 index exch unread % unread mismatch character + dup { % loop unreading backwards in .epsfheader + 1 sub dup .epsfheader exch get 2 index exch unread + } repeat pop + exch not exch exit % change true to false + } + ifelse + } + for exch % Stack: file true/false + { % This block is executed if the file is MS-DOS EPSF. + % Build up the little-endian byte offset and length. + 2 + { 1 0 4 + { 2 index read not { pop exit } if % if EOF, let error happen + 2 index mul add exch 256 mul exch + } + repeat exch pop exch + } + repeat + % Stack: offset length file + % Use flushfile to skip quickly to the start of the + % PostScript section. + dup 4 -1 roll 12 sub () /SubFileDecode filter flushfile + % Now interpret the PostScript. + exch () /SubFileDecode filter cvx .runexec + } + { .runnoepsf + } + ifelse + } odef diff --git a/pstoraster/gs_fform.ps b/pstoraster/gs_fform.ps new file mode 100644 index 0000000000..17dfbef74f --- /dev/null +++ b/pstoraster/gs_fform.ps @@ -0,0 +1,100 @@ +% Copyright (C) 1995, 1996, 1998 Aladdin Enterprises. All rights reserved. +% +% This file is part of GNU Ghostscript. +% +% GNU Ghostscript is distributed in the hope that it will be useful, but +% WITHOUT ANY WARRANTY. No author or distributor accepts responsibility +% to anyone for the consequences of using it or for whether it serves any +% particular purpose or works at all, unless he says so in writing. Refer +% to the GNU General Public License for full details. +% +% Everyone is granted permission to copy, modify and redistribute GNU +% Ghostscript, but only under the conditions described in the GNU General +% Public License. A copy of this license is supposed to have been given +% to you along with GNU Ghostscript so you can know your rights and +% responsibilities. It should be in a file named COPYING. Among other +% things, the copyright notice and this notice must be preserved on all +% copies. +% +% Aladdin Enterprises supports the work of the GNU Project, but is not +% affiliated with the Free Software Foundation or the GNU Project. GNU +% Ghostscript, as distributed by Aladdin Enterprises, does not require any +% GNU software to build or run it. + +% $Id: gs_fform.ps 956 2000-03-08 23:15:43Z mike $ +% Form caching implemented in PostScript. + +% This implementation doesn't do the right thing about halftone or +% Pattern phase, but the Pattern cache doesn't either.... + +% The Form cache key is the Form dictionary; the value is an array +% of 2 elements [CTM pattern_instance]. +% +% In order to prevent restore from clearing the cache, we explicitly +% push the cache entries on the stack before a restore and reinstall them. +currentglobal false setglobal +/.formcachedict 20 dict def % must be local +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 + +/.execform1 { + dup /Implementation known not { + dup /FormType get 1 ne { /rangecheck signalerror } if + % The Implementation is a Pattern that will draw the form. + currentglobal 1 index gcheck setglobal + % Stack: form global + 10 dict begin + /PatternType 1 def + /PaintType 1 def % colored + /TilingType 1 def % irrelevant + % Copy the BBox to the correct VM. + /BBox 2 index /BBox get 4 array copy exch 1 index def + % Set XStep and YStep to very large numbers, + % so we won't get multiple copies of the form. + /XStep 1 index dup 2 get exch 0 get sub 100 mul def + /YStep exch dup 3 get exch 1 get sub 100 mul def + /PaintProc 2 index /PaintProc get def + currentdict end readonly + % Stack: form global impl + exch setglobal + 1 index /Implementation 3 -1 roll .forceput + } if + .formcachedict 1 index .knownget { + % Check whether we can use the cached value. + % Stack: form cachevalue + matrix currentmatrix true 0 1 3 { + % Stack: form cachevalue curmat true index + 3 index 0 get 1 index get exch 3 index exch get ne { + pop pop false exit + } if + } for exch pop + } { + false + } ifelse not + { % Make a new cache entry. + gsave + matrix currentmatrix dup 4 0 put dup 5 0 put dup setmatrix + % Stack: form mat + 1 index /Implementation get + 2 index /Matrix get + makepattern 2 array astore + .formcachedict 2 index 2 index put + grestore + } if + % Stack: form cachevalue + -1 0 0 transform + 2 { exch round cvi } repeat .setscreenphase + 1 get setpattern + /BBox get aload pop + exch 3 index sub exch 2 index sub rectfill +} .bind odef % must bind .forceput + +.formtypes 1 /.execform1 load put + +setglobal diff --git a/pstoraster/gs_fonts.ps b/pstoraster/gs_fonts.ps new file mode 100644 index 0000000000..c413882ace --- /dev/null +++ b/pstoraster/gs_fonts.ps @@ -0,0 +1,934 @@ +% Copyright (C) 1990, 1995, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved. +% +% This file is part of GNU Ghostscript. +% +% GNU Ghostscript is distributed in the hope that it will be useful, but +% WITHOUT ANY WARRANTY. No author or distributor accepts responsibility +% to anyone for the consequences of using it or for whether it serves any +% particular purpose or works at all, unless he says so in writing. Refer +% to the GNU General Public License for full details. +% +% Everyone is granted permission to copy, modify and redistribute GNU +% Ghostscript, but only under the conditions described in the GNU General +% Public License. A copy of this license is supposed to have been given +% to you along with GNU Ghostscript so you can know your rights and +% responsibilities. It should be in a file named COPYING. Among other +% things, the copyright notice and this notice must be preserved on all +% copies. +% +% Aladdin Enterprises supports the work of the GNU Project, but is not +% affiliated with the Free Software Foundation or the GNU Project. GNU +% Ghostscript, as distributed by Aladdin Enterprises, does not require any +% GNU software to build or run it. + +% $Id: gs_fonts.ps 956 2000-03-08 23:15:43Z mike $ +% 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 SUBSTFONT is defined, make it the default font. +/SUBSTFONT where { pop /defaultfontname /SUBSTFONT load def } if + +% Define a reliable way of accessing FontDirectory in systemdict. +/.FontDirectory +{ /FontDirectory .systemvar +} .bind odef + +% 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 + +% Define a temporary string for local use, since using =string +% interferes with some PostScript programs. +/.fonttempstring 128 string 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 .fonttempstring 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 + /dir true + /dll true + /doc true + /drv true + /exe true + /fon true + /fot true + /h true + /o true + /obj true + /pfm true + /pss true % Adobe Multiple Master font instances + /txt true +.dicttomark def +/.scan1fontstring 128 string def +/.scanfontheaders [(%!PS-Adobe*) (%!FontType*)] 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 flush } 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 + +% Create the dictionary that registers the .buildfont procedure (called by +% definefont) for each FontType. +/buildfontdict 20 dict def + +% Register Type 3 fonts, which are always supported, for definefont. +buildfontdict 3 /.buildfont3 cvx put + +% Register Type 0 fonts if they are supported. Strictly speaking, +% we should do this in its own file (gs_type0.ps), but since this is +% the only thing that would be in that file, it's simpler to put it here. +/.buildfont0 where { pop buildfontdict 0 /.buildfont0 cvx put } if + +% Define definefont. This is a procedure built on a set of operators +% that do all the error checking and key insertion. +/.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 +/.completefont { + { % 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. + % Note that some types of font don't have an Encoding. + dup /Encoding .knownget { + dup length 65 ge { + 64 get + dup /congruent eq { SymbolEncoding pop } if + /a9 eq { DingbatsEncoding pop } if + } { + pop + } ifelse + } if + } + ifelse + true exch + dup /FontType known not { + % This might be a CIDFont. + dup /CIDFontType known { + /.buildcidfont where { + pop exch pop false exch + } if + } if + } if + exch { + dup /FontType get //buildfontdict exch get exec + } { + .buildcidfont + } ifelse + + DISKFONTS + { FontFileDirectory 2 index known + { dup /FontFile FontFileDirectory 4 index get .growput + } + if + } + if + readonly % stack: name fontdict + } stopped { /invalidfont signalerror } if +} bind odef +/definefont + { .completefont + % 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 + } odef + +% Define a procedure for defining aliased fonts. +% We use this only for explicitly aliased fonts, not substituted fonts: +% we think this matches the observed behavior of Adobe interpreters. +/.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 in this case, do a cvn. + % We might also be defining (as an alias) a global font + % whose FontName is a local non-string, if someone passed a + % garbage value to findfont. In this case, just don't + % call definefont at all. + 2 index dup type /stringtype eq exch .gcheck or 1 index .gcheck not or + { /FontName 3 index dup type /stringtype eq { cvn } if put + % Don't bind in definefont, since Level 2 redefines it. + /definefont .systemvar exec + } + { .completefont pop exch pop + } + ifelse 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 { + % According to Ed Taft, Adobe interpreters push userdict + % before loading a font, and pop it afterwards. + userdict begin + cvx exec + end +} 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] + [(Frut) /Helvetica] + [(Geneva) /Helvetica] + [(Helv) /Helvetica] + [(NewYork) /Times] + [(Pala) /Palatino] + [(Sans) /Helvetica] + [(Schlbk) /NewCenturySchlbk] + [(Serif) /Times] + [(Swiss) /Helvetica] + [(Times) /Times] + [(Univers) /Helvetica] + % Substitute for Adobe Multiple Master fonts. + [(Minion) /Times] + [(Myriad) /Helvetica] + [(MyriadPkg) /Helvetica-Narrow] + % 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 type dup /stringtype eq exch /nametype eq or + { dup length string cvs } { () } ifelse + {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 exec + % 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. We must pop the arguments at the very end, +% so that stack protection will be effective. + +/definefont { % definefont + dup /FontMatrix known { + //definefont + } { + 2 copy /FontName get findfont //definefont exch pop exch pop + } ifelse +} bind odef + +/scalefont { % scalefont + 1 index /FontMatrix known { + //scalefont + } { + 1 index /FontName get findfont 1 index //scalefont + exch pop exch pop + } ifelse +} bind odef + +/makefont { % makefont + 1 index /FontMatrix known { + //makefont + } { + 1 index /FontName get findfont 1 index //makefont + exch pop exch pop + } ifelse +} bind odef + +/setfont { % setfont - + dup /FontMatrix known { + //setfont + } { + dup /FontName get findfont //setfont pop + } ifelse +} 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, +% but it still needs to restore the stacks reliably if it fails, +% so we do all the work in an operator. +/.findfont { + mark 1 index + //systemdict begin .dofindfont + % Define any needed aliases. + counttomark 1 sub { .aliasfont } repeat end + exch pop exch pop +} odef +/findfont { + .findfont +} 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. Make sure we're not already + % looking for the default 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 + % Substitute for the font. Don't alias. + /SUBSTFONT where { + pop QUIET not { + (Substituting for font ) print dup =only + (.\n) print flush + } if + cleartomark mark defaultfontname + } { + 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 + % Remove all the accumulated aliases. + counttomark 1 add 1 roll cleartomark mark exch + } ifelse + } + 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. Look for a file with the + % same name as the requested font. + dup dup type /nametype eq { .namestring } if .loadfontloop + } + { % Try each element of the Fontmap in turn. + false exch % (in case we exhaust the list) + % Stack: fontname false fontmaplist + { 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 + % Stack: font true -or- fontname false + { true + } + { % None of the Fontmap entries worked. + % Try loading a file with the same name + % as the requested font. + dup dup type /nametype eq { .namestring } if .loadfontloop + } + ifelse + } + ifelse + } + ifelse + } bind def +% Attempt to load a font from a file. +/.loadfontloop % .loadfontloop true + % .loadfontloop false + { % See above regarding the use of 'loop'. + + { + % Is the font name a string? + dup type /stringtype ne + { QUIET not + { (Can't find font with non-string name: ) print dup =only (.\n) print flush + } + if pop false exit + } + if + % 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 .systemvar exec + % Remove the fake definition, if any. + .FontDirectory 3 index .undef + 1 index (r) file .loadfont .FontDirectory exch + /.setglobal .systemvar 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 and FontType defined. +% (We define FontType only for the sake of some questionable code in the +% Apple Printer Utility 2.0 font inquiry code.) +% +% Note that this procedure only creates fake fonts in the FontDirectory +% associated with the current VM. This is because in multi-context systems, +% creating the fake fonts in local VM leads to undesirable complications. +/.definefakefonts + { + } + { + (gs_fonts FAKEFONTS) VMDEBUG + Fontmap { + pop dup type /stringtype eq { cvn } if + .FontDirectory 1 index known not { + 2 dict dup /FontName 3 index put + dup /FontType 1 put + .FontDirectory 3 1 roll put + } { + pop + } ifelse + } forall + } +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 % current VM is global + } def % don't bind, .current/setglobal get redefined + +% ---------------- 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_init.ps b/pstoraster/gs_init.ps new file mode 100644 index 0000000000..e430a4f869 --- /dev/null +++ b/pstoraster/gs_init.ps @@ -0,0 +1,1521 @@ +% Copyright 1993-2000 by Easy Software Products. +% Copyright 1989, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved. +% +% This file is part of GNU Ghostscript. +% +% GNU Ghostscript is distributed in the hope that it will be useful, but +% WITHOUT ANY WARRANTY. No author or distributor accepts responsibility +% to anyone for the consequences of using it or for whether it serves any +% particular purpose or works at all, unless he says so in writing. Refer +% to the GNU General Public License for full details. +% +% Everyone is granted permission to copy, modify and redistribute GNU +% Ghostscript, but only under the conditions described in the GNU General +% Public License. A copy of this license is supposed to have been given +% to you along with GNU Ghostscript so you can know your rights and +% responsibilities. It should be in a file named COPYING. Among other +% things, the copyright notice and this notice must be preserved on all +% copies. +% +% Aladdin Enterprises supports the work of the GNU Project, but is not +% affiliated with the Free Software Foundation or the GNU Project. GNU +% Ghostscript, as distributed by Aladdin Enterprises, does not require any +% GNU software to build or run it. + +% $Id: gs_init.ps 1284 2000-08-14 20:17:17Z mike $ +% 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. +550 +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 +systemdict exch + { % userdict wasn't already set up by iinit.c. + dup /userdict + currentdict dup 200 .setmaxlength % userdict + .forceput % userdict is local, systemdict is global + } +if begin + +% 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. +/DEBUG true 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 /BATCH known /BATCH exch 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 /NOINTERPOLATE known /NOINTERPOLATE exch def +currentdict /NOPAGEPROMPT known /NOPAGEPROMPT 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 /STRICT known /STRICT 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 + +/.currentuserparams where { + pop mark + % The Adobe implementations appear to have very large maximum + % stack sizes. This turns out to actually make a difference, + % since some badly-behaved files include extremely long procedures, + % or construct huge arrays on the operand stack. + % We reset the stack sizes now so that we don't have to worry + % about overflowing the (rather small) built-in stack sizes + % during initialization. + /MaxDictStack 500 + /MaxExecStack 5000 + /MaxOpStack 50000 + .dicttomark .setuserparams +} if + +% 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 + +% 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 100 mod dup 0 ne { 10 idiv } { pop } ifelse (.) + 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. +/obind { % obind + 1 index exch .makeoperator +} .bind def +/odef { % odef - + 1 index exch .makeoperator def +} .bind def + +% Define a special version of def for storing local objects into global +% dictionaries. Like .forceput, this exists only during initialization. +/.forcedef { % .forcedef - + currentdict 3 1 roll .forceput +} .bind odef + +% Define procedures for accessing variables in systemdict and userdict +% regardless of the contents of the dictionary stack. +/.systemvar { % .systemvar + //systemdict exch get +} .bind odef +/.userdict { % - .userdict + /userdict .systemvar +} .bind odef +/.uservar { % .uservar + .userdict exch get +} .bind odef + +% If we're delaying binding, remember everything that needs to be bound later. +DELAYBIND NOBIND not and + { .currentglobal false .setglobal + systemdict /.delaybind 1500 array .forceput + .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 + { /.delaybind .systemvar dup length 0 ne + { .delaycount 2 index put + .userdict /.delaycount .delaycount 1 add put + } + { pop .bind + } + ifelse + } .bind def + } if + +%**************** BACKWARD COMPATIBILITY +/hwsizedict mark /HWSize null .dicttomark readonly def +/copyscanlines { % copyscanlines + 0 3 1 roll 3 index //hwsizedict .getdeviceparams + exch pop exch pop aload pop 3 2 roll + 0 exch null exch .getbitsrect exch pop +} bind odef +currentdict /hwsizedict .undef +/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 +/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 redefined if setpagedevice is present. +/.beginpage { } odef +% In LanguageLevel 3, copypage erases the page. +/copypage { + .languagelevel 3 ge + 1 .endpage { + .currentnumcopies 1 index .outputpage + (>>copypage, press to continue<<\n) .confirm + dup { erasepage } if + } if pop .beginpage +} odef +/currentmatrix { + .currentmatrix 6 index astore pop +} 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 exec + % Only pop systemdict if it is still the top element, + % because this is apparently what Adobe interpreters do. + currentdict //systemdict eq { end } if + } odef +% .endpage is redefined if setpagedevice is present. +/.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 +% To satisfy the Genoa FTS, executive must be a procedure, not an operator. +/executive + { { NOPROMPT not { prompt } if + { (%statementedit) (r) file } stopped + { pop pop $error /errorname get /undefinedfilename eq + { .clearerror exit } if % EOF + handleerror null % ioerror?? + } + if + cvx { .runexec } execute + } loop + } bind def +/filter + { //filterdict 1 index .knownget + { exch pop exec } + { /filter load /undefined signalerror } + ifelse + } odef +/handleerror + { /errordict .systemvar /handleerror get exec } bind def +/identmatrix [1.0 0.0 0.0 1.0 0.0 0.0] readonly def +/identmatrix + { dup 0 //identmatrix putinterval } 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 +% Execute a file. +% Level 2 uses 2 .stop to clear the e-stack for a successful startjob: +% we detect that here, since we need to handle this even if we start out +% without job control in effect. +% +% What we push on the e-stack is the following to be executed in this order: +% .runexec1 .runexec2 +/.runexec1 { % .runexec1 - + dup type /filetype ne { cvx exec } if + cvx null 2 .stopped + % If we got back here from a startjob, just keep going. + % startjob replaces the null on the o-stack with a procedure + % to be executed when we get back here. + dup null ne { exec true } { pop false } ifelse +} bind def +/.runexec2 { % .runexec2 - + exch { + .runexec + } { + dup type /filetype ne { cvx exec } if + closefile + } ifelse +} bind def +/.runexec { % .runexec - + cvlit /.runexec1 cvx 1 index /.runexec2 cvx 4 .execn +} bind def +% The following is only for compatibility with Adobe interpreters. +/setdash { + 1 index length 11 gt { /setdash load /limitcheck signalerror } if + //setdash +} odef +/setdevice + { .setdevice { erasepage } if } odef +/setlinecap { + dup 2 gt { /setlinecap load /rangecheck signalerror } if + .setlinecap +} odef +/setlinejoin { + dup 2 gt { /setlinejoin load /rangecheck signalerror } if + .setlinejoin +} odef +/setmatrix { + dup aload pop .setmatrix pop +} odef +/showpage { + 0 .endpage .doneshowpage { + .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 { BATCH { null 0 .quit } { executive } ifelse } def +% 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. +/.internalstopped { null 1 .stopped null ne } bind def +/store { % Don't alter operands before completing. + 1 index where { 2 index 2 index put pop pop } { def } ifelse +} odef +% NOTE: the name typenames is known to (initialized by) the interpreter. +/type { + //typenames .type +} odef +% When running in Level 1 mode, this interpreter is supposed to be +% compatible with PostScript "version" 54.0 (I think). +/version (54.0) readonly def + +% internaldict is defined in systemdict, but is allocated in local VM. +% We make a procedure for creating it, since we must create a new one +% for each context with private local VM. +/.makeinternaldict { + .currentglobal false .setglobal + [ /dup .systemvar 1183615869 /eq .systemvar + [ /pop .systemvar 10 dict ] cvx + [ /internaldict /cvx .systemvar /invalidaccess /signalerror cvx ] cvx + /ifelse .systemvar + ] cvx executeonly + exch .setglobal +} odef +systemdict /internaldict dup .makeinternaldict .makeoperator +.forceput % proc is local, systemdict is global +% Move superexec to internaldict if superexec is defined. +currentdict /superexec .knownget { + 1183615869 internaldict /superexec 3 -1 roll put + currentdict /superexec .undef +} 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 + { /devicedict .systemvar 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 + { % We don't want to bind 'run' into this procedure, + % since run may get redefined. + findlibfile + { exch pop /run .systemvar exec } + { /undefinedfilename signalerror } + ifelse + } bind def +/selectdevice + { finddevice setdevice .setdefaultscreen } bind def +/signalerror % signalerror - + { /errordict .systemvar 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 +} bind def +/write= { + 1 index exch write=only (\n) writestring +} bind def +%%%% MRS - Send = output to stderr, since stdout is for output. +/=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 NOPAGEPROMPT or NOPROMPT is true) + % and wait for the user to type something. + % If the user just types a newline, flush it. + NOPAGEPROMPT NOPROMPT or { 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 { % .execute + stopped $error /newerror get and + { handleerror flush true } { false } ifelse +} bind def +/execute { % execute - + .execute pop +} odef +% Define an execute analogue of runlibfile0. +/execute0 { % execute0 - + .execute { /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. +% We don't use the obvious { (%stdin) run }, because we want the file to be +% reopened if a startjob does a restore. +/.runstdin { + { { (%stdin) (r) file cvx } .runexec } execute0 +} bind def +% Define the procedure that the C code uses for running commands +% given on the command line with -c. We turn the string into a file so that +% .runexec can do the right thing with a startjob. +/.runstring { + .currentglobal exch true .setglobal + 0 () .subfiledecode + exch .setglobal cvx { .runexec } execute +} bind def +% Define the procedure that the C code uses to set up for executing +% a string that may be received in pieces. +/.runstringbegin { + .currentglobal true .setglobal + { .needinput } bind 0 () .subfiledecode + exch .setglobal cvx .runexec +} bind 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'. + 1 .instopped { null eq { pop pop stop } if } if + $error /.inerror get 1 .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 dup maxlength =only + } if + /gcheck where { + pop gcheck { ((G)) } { ((L)) } ifelse print + } { + 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 /errorname null put + $error /errorinfo .undef + 0 .setoserrno + } bind def + +% Define $error. This must be in local VM. +.currentglobal false .setglobal +/$error 40 dict .forcedef % $error is local, systemdict is global + % 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 +.forcedef % errordict is local, systemdict is global +.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 + { /.printerror .systemvar 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 +.forcedef % FontDirectory is local, systemdict is global + +% 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. +% To satisfy the Genoa FTS, findencoding must be a procedure, not an operator. +/rootfont where { pop /findencoding { .findencoding } def } if + +% Define .registerencoding. +% NOTE: the name registeredencodings is known to (initialized by and shared +% with) the interpreter. +/.registerencoding { % .registerencoding - + % Check that the array is indexable. + % (It might still be a string, but then the .namestring will fail.) + dup 0 0 getinterval pop + % Check that all the elements of the array are names. + dup { .namestring pop } forall + % Do the store. + //registeredencodings 2 index 2 index readonly put pop pop +} bind odef +systemdict /registeredencodings .undef + +% 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} .internalstopped 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 (or higher) functionality is implemented, enable it now. +/.setlanguagelevel where { + pop 2 .setlanguagelevel + % If the resource machinery is loaded, fix up some things now. + /.fixresources where { pop .fixresources } if +} if +/ll3dict where { + pop 3 .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. +/undefinefont where { + pop /NullFont undefinefont +} { + FontDirectory /NullFont .undef +} ifelse + +(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 +% The following line used to skip setting of page size and resolution if +% NODISPLAY was selected. We think this was only to save time and memory, +% and it is a bad idea because it prevents setting the resolution in this +% situation, which pstoedit (among other programs) relies on. +%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 /Policies + % Stack: /Policies +1 index /InputAttributes +2 copy get dup length dict .copydict + % Stack: /Policies + % /InputAttributes +dup 0 2 copy get dup length dict .copydict + % Stack: /Policies + % /InputAttributes 0 +dup /PageSize 7 index /PageSize get +put % PageSize in 0 +put % 0 in InputAttributes +put % InputAttributes in pagedevice +% Also change the page size policy so we don't get an error. + % Stack: /Policies +2 copy get dup length dict .copydict + % Stack: /Policies +dup /PageSize 7 put % PageSize in Policies +put % Policies 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 + +% Establish an appropriate halftone screen and BG/UCR functions. +% We make this a procedure so we can call it again when switching devices. + +%%%% MRS - Changed default to 16x16 Floyd dither, matching the CUPS +%%%% image RIP. Also, added missing standard transfer function, +%%%% which is needed by output from many apps... + +% Set the default screen and BG/UCR based on the device resolution and +% process color capability. +/.setdefaultbgucr systemdict /setblackgeneration known { { + processcolors 1 eq { { } } { { pop 0.0 } } ifelse + dup setblackgeneration setundercolorremoval +} } { { +} } ifelse bind def +% 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. +<04> cvn { } def % Apple job separator +<0404> cvn { } def % two of the same +<1b> cvn { } def % MS Windows LaserJet 4 prologue + % (UEL = ESC %-12345X) +<1b45> cvn { } def % PJL reset prologue (ESC E) +<1b451b> cvn { } def % PJL reset epilogue (ESC E + UEL) +<041b> cvn { } def % MS Windows LaserJet 4 epilogue (^D + UEL) +(\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 + 2 index (%std*) .stringmatch or + { 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 + //systemdict /.delaybind {} .forceput % reclaim the space + //systemdict /.bindnow .forceundef % ditto + put + //systemdict /.forcedef .forceundef % remove temptation + //systemdict /.forceput .forceundef % ditto + //systemdict /.forceundef .forceundef % ditto +} .bind odef + +% Turn off array packing, since some PostScript code assumes that +% procedures are writable. +false setpacking + +(END INIT) VMDEBUG + +/.currentuserparams where { + pop + % Remove real user params from psuserparams. + mark .currentuserparams counttomark 2 idiv { + pop psuserparams exch undef + } repeat pop + % Update the copy of the user parameters. + mark .currentuserparams counttomark 2 idiv { + userparams 3 1 roll .forceput % userparams is read-only + } repeat pop + % Turn on idiom recognition, if available. + currentuserparams /IdiomRecognition known { + /IdiomRecognition true .definepsuserparam + } if + psuserparams readonly pop + systemdict /.definepsuserparam undef + % Save a copy of userparams for use with save/restore + % (and, if implemented, context switching). + .currentglobal false .setglobal + mark .currentuserparams psuserparams { } forall .dicttomark readonly + /userparams exch .forcedef % systemdict is read-only + .setglobal +} if +/.currentsystemparams where { + pop + % Remove real system params from pssystemparams. + mark .currentsystemparams counttomark 2 idiv { + pop pssystemparams exch .forceundef + } repeat pop +} if + +% Conditionally turn off image interpolation. +NOINTERPOLATE not { (%END NOINTERPOLATE) .skipeof } if +/.nointerpolate { + dup type /dicttype eq { + dup /Interpolate .knownget not { false } if { + dup gcheck .currentglobal exch .setglobal + exch dup length dict copy + dup /Interpolate .undef + exch .setglobal + } if + } if +} bind odef +/image { .nointerpolate image } bind odef +/imagemask { .nointerpolate imagemask } bind odef +%END NOINTERPOLATE + +% Establish local VM as the default. +false /setglobal where { pop setglobal } { .setglobal } ifelse +$error /.nosetlocal false put + +(END GLOBAL) VMDEBUG + +/.savelocalstate where { + % If we might create new contexts, save away copies of all dictionaries + % referenced from systemdict that are stored in local VM, + % and also save a copy of the initial gstate. + pop .savelocalstate +} { + % If we're *not* running in a multi-context system and FAKEFONTS is + % defined, add the fake fonts to LocalFontDirectory. + .definefakefonts % current VM is local +} ifelse + +% Close up systemdict. +currentdict /filterdict .undef % bound in where needed +currentdict /.cidfonttypes .undef % ditto +currentdict /.colorrenderingtypes .undef % ditto +currentdict /.formtypes .undef % ditto +currentdict /.imagetypes .undef % ditto +currentdict /.imagemasktypes .undef % ditto +currentdict /.patterntypes .undef % ditto +currentdict /.shadingtypes .undef % ditto +end + +% Clean up VM, and enable GC. +/vmreclaim where + { pop NOGC not { 2 vmreclaim 0 vmreclaim } if + } if +DELAYBIND not { + systemdict /.forcedef .undef % remove temptation + systemdict /.forceput .undef % ditto + systemdict /.forceundef .undef % ditto +} if +WRITESYSTEMDICT not { systemdict readonly pop } 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..607d9714f1 --- /dev/null +++ b/pstoraster/gs_iso_e.ps @@ -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 supports the work of the GNU Project, but is not +% affiliated with the Free Software Foundation or the GNU Project. GNU +% Ghostscript, as distributed by Aladdin Enterprises, does not require any +% GNU software to build or run it. + +% $Id: gs_iso_e.ps 956 2000-03-08 23:15:43Z mike $ +% 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..ee4272dd47 --- /dev/null +++ b/pstoraster/gs_kanji.ps @@ -0,0 +1,166 @@ +% 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 supports the work of the GNU Project, but is not +% affiliated with the Free Software Foundation or the GNU Project. GNU +% Ghostscript, as distributed by Aladdin Enterprises, does not require any +% GNU software to build or run it. + +% $Id: gs_kanji.ps 956 2000-03-08 23:15:43Z mike $ +% 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..e418ea3aa8 --- /dev/null +++ b/pstoraster/gs_ksb_e.ps @@ -0,0 +1,72 @@ +% 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 supports the work of the GNU Project, but is not +% affiliated with the Free Software Foundation or the GNU Project. GNU +% Ghostscript, as distributed by Aladdin Enterprises, does not require any +% GNU software to build or run it. + +% $Id: gs_ksb_e.ps 956 2000-03-08 23:15:43Z mike $ +% 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_lev2.ps b/pstoraster/gs_lev2.ps new file mode 100644 index 0000000000..94c490f8db --- /dev/null +++ b/pstoraster/gs_lev2.ps @@ -0,0 +1,717 @@ +% Copyright (C) 1990, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved. +% +% This file is part of GNU Ghostscript. +% +% GNU Ghostscript is distributed in the hope that it will be useful, but +% WITHOUT ANY WARRANTY. No author or distributor accepts responsibility +% to anyone for the consequences of using it or for whether it serves any +% particular purpose or works at all, unless he says so in writing. Refer +% to the GNU General Public License for full details. +% +% Everyone is granted permission to copy, modify and redistribute GNU +% Ghostscript, but only under the conditions described in the GNU General +% Public License. A copy of this license is supposed to have been given +% to you along with GNU Ghostscript so you can know your rights and +% responsibilities. It should be in a file named COPYING. Among other +% things, the copyright notice and this notice must be preserved on all +% copies. +% +% Aladdin Enterprises supports the work of the GNU Project, but is not +% affiliated with the Free Software Foundation or the GNU Project. GNU +% Ghostscript, as distributed by Aladdin Enterprises, does not require any +% GNU software to build or run it. + +% $Id: gs_lev2.ps 956 2000-03-08 23:15:43Z mike $ +% Initialization file for Level 2 functions. +% When this is run, systemdict is still writable, +% but (almost) everything defined here goes into level2dict. + +level2dict begin + +% ------ System and user parameters ------ % + +% User parameters must obey save/restore, and must also be maintained +% per-context. We implement the former, and some of the latter, here +% with PostScript code. NOTE: our implementation assumes that user +% parameters change only as a result of setuserparams -- that there are +% no user parameters that are ever changed dynamically by the interpreter +% (although the interpreter may adjust the value presented to setuserparams) +% +% There are two types of user parameters: those which are actually +% maintained in the interpreter, and those which exist only at the +% PostScript level. We maintain the current state of both types in +% a read-only local dictionary named userparams, defined in systemdict. +% In a multi-context system, each context has its own copy of this +% dictionary. In addition, there is a constant dictionary named +% psuserparams whose keys are the names of user parameters that exist +% only in PostScript and whose values are (currently) arbitrary values +% of the correct datatype: setuserparams uses this for type checking. +% setuserparams updates userparams explicitly, in addition to setting +% any user parameters in the interpreter; thus we can use userparams +% to reset those parameters after a restore or a context switch. +% NOTE: the name userparams is known to the interpreter, and in fact +% the interpreter creates the userparams dictionary. + +% Check parameters that are managed at the PostScript level. +% Currently we allow resetting them iff the new value is of the same type. +/.checksetparams { % + % .checksetparams + 2 index { + % Stack: newdict opname checkdict key newvalue + 3 copy pop .knownget + { type 1 index type ne + { pop pop pop load /typecheck signalerror } + if + dup type /stringtype eq + { dup rcheck not + { pop pop pop load /invalidaccess signalerror } + if + } + if + } + if pop pop + } forall pop pop +} .bind def % not odef, shouldn't reset stacks + +% currentuser/systemparams creates and returns a dictionary in the +% current VM. The easiest way to make this work is to copy any composite +% PostScript-level parameters to global VM. Currently, the only such +% parameters are strings. In fact, we always copy string parameters, +% so that we can be sure the contents won't be changed. +/.copyparam { % .copyparam + dup type /stringtype eq { + .currentglobal true .setglobal + 1 index length string exch .setglobal + copy readonly + } if +} .bind def + +% Some user parameters are managed entirely at the PostScript level. +% We take care of that here. +systemdict begin +/psuserparams 40 dict def +/getuserparam { % getuserparam + /userparams .systemvar 1 index get exch pop +} odef +% Fill in userparams (created by the interpreter) with current values. +mark .currentuserparams +counttomark 2 idiv { + userparams 3 1 roll put +} repeat pop +/.definepsuserparam { % .definepsuserparam - + psuserparams 3 copy pop put + userparams 3 1 roll put +} .bind def +end +/currentuserparams { % - currentuserparams + /userparams .systemvar dup length dict .copydict +} odef +/setuserparams { % setuserparams - + % Check that we will be able to set the PostScript-level + % user parameters. + /setuserparams /psuserparams .systemvar .checksetparams + % Set the C-level user params. If this succeeds, we know that + % the password check succeeded. + dup .setuserparams + % Now set the PostScript-level params. + % The interpreter may have adjusted the values of some of the + % parameters, so we have to read them back. + dup { + /userparams .systemvar 2 index known { + psuserparams 2 index known not { + pop dup .getuserparam + } if + .copyparam + /userparams .systemvar 3 1 roll .forceput % userparams is read-only + } { + pop pop + } ifelse + } forall + % A context switch might have occurred during the above loop, + % causing the interpreter-level parameters to be reset. + % Set them again to the new values. From here on, we are safe, + % since a context switch will consult userparams. + .setuserparams +} .bind odef +% Initialize user parameters managed here. +/JobName () .definepsuserparam + +% Restore must restore the user parameters. +% (Since userparams is in local VM, save takes care of saving them.) +/restore { % restore - + restore /userparams .systemvar .setuserparams +} .bind odef + +% The pssystemparams dictionary holds some system parameters that +% are managed entirely at the PostScript level. +systemdict begin +currentdict /pssystemparams known not { + /pssystemparams 40 dict readonly def +} if +/getsystemparam { % getsystemparam + //pssystemparams 1 index .knownget { exch pop } { .getsystemparam } ifelse +} odef +end +/currentsystemparams { % - currentsystemparams + mark .currentsystemparams //pssystemparams { } forall .dicttomark +} odef +/setsystemparams { % setsystemparams - + % Check that we will be able to set the PostScript-level + % system parameters. + /setsystemparams //pssystemparams .checksetparams + % Set the C-level system params. If this succeeds, we know that + % the password check succeeded. + dup .setsystemparams + % Now set the PostScript-level params. We must copy local strings + % into global VM. + dup + { //pssystemparams 2 index known + { % Stack: key newvalue + .copyparam + //pssystemparams 3 1 roll .forceput % pssystemparams is read-only + } + { pop pop + } + ifelse + } + forall pop +} .bind odef + +% Initialize the passwords. +% NOTE: the names StartJobPassword and SystemParamsPassword are known to +% the interpreter, and must be bound to noaccess strings. +% The length of these strings must be max_password (iutil2.h) + 1. +/StartJobPassword 65 string noaccess def +/SystemParamsPassword 65 string noaccess def + +% Redefine cache parameter setting to interact properly with userparams. +/setcachelimit { + mark /MaxFontItem 2 index .dicttomark setuserparams pop +} .bind odef +/setcacheparams { + % The MaxFontCache parameter is a system parameter, which we might + % not be able to set. Fortunately, this doesn't matter, because + % system parameters don't have to be synchronized between this code + % and the VM. + counttomark 1 add copy setcacheparams + currentcacheparams % mark size lower upper + 3 -1 roll pop + /MinFontCompress 3 1 roll + /MaxFontItem exch + .dicttomark setuserparams + cleartomark +} .bind odef + +% Add bogus user and system parameters to satisfy badly written PostScript +% programs that incorrectly assume the existence of all the parameters +% listed in Appendix C of the Red Book. Note that some of these may become +% real parameters later: code near the end of gs_init.ps takes care of +% removing any such parameters from ps{user,system}params. + +psuserparams begin + /MaxFormItem 100000 def + /MaxPatternItem 20000 def + /MaxScreenItem 48000 def + /MaxUPathItem 5000 def +end + +pssystemparams begin + /CurDisplayList 0 .forcedef + /CurFormCache 0 .forcedef + /CurOutlineCache 0 .forcedef + /CurPatternCache 0 .forcedef + /CurUPathCache 0 .forcedef + /CurScreenStorage 0 .forcedef + /CurSourceList 0 .forcedef + /DoPrintErrors false .forcedef + /MaxDisplayList 140000 .forcedef + /MaxFormCache 100000 .forcedef + /MaxOutlineCache 65000 .forcedef + /MaxPatternCache 100000 .forcedef + /MaxUPathCache 300000 .forcedef + /MaxScreenStorage 84000 .forcedef + /MaxSourceList 25000 .forcedef + /RamSize 4194304 .forcedef +end + +% ------ Miscellaneous ------ % + +(<<) cvn % - << -mark- + /mark load def +(>>) cvn % -mark- ... >> + /.dicttomark load def +/languagelevel 2 def +% When running in Level 2 mode, this interpreter is supposed to be +% compatible with Adobe version 2017. +/version (2017) readonly def + +% If binary tokens are supported by this interpreter, +% set an appropriate default binary object format. +/setobjectformat where + { pop + /RealFormat getsystemparam (IEEE) eq { 1 } { 3 } ifelse + /ByteOrder getsystemparam { 1 add } if + setobjectformat + } if + +% ------ Virtual memory ------ % + +/currentglobal % - currentglobal + /currentshared load def +/gcheck % gcheck + /scheck load def +/setglobal % 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 + +% VMReclaim and VMThreshold are user parameters. +/setvmthreshold { % setvmthreshold - + mark /VMThreshold 2 index .dicttomark setuserparams pop +} odef +/vmreclaim { % vmreclaim - + dup 0 gt { + .vmreclaim + } { + mark /VMReclaim 2 index .dicttomark setuserparams pop + } ifelse +} odef +-1 setvmthreshold + +% ------ IODevices ------ % + +/.getdevparams where { + pop /currentdevparams { % currentdevparams + .getdevparams .dicttomark + } odef +} if +/.putdevparams where { + pop /setdevparams { % setdevparams - + mark 1 index { } forall counttomark 2 add index + .putdevparams pop pop + } 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 + +end % serverdict + +% Because there may be objects on the e-stack created since the job save, +% we have to clear the e-stack before doing the end-of-job restore. +% We do this by executing a 2 .stop, which is caught by the 2 .stopped +% in .runexec; we leave on the o-stack a procedure to execute aftewards. +% +%**************** The definition of startjob is not complete yet, since +% it doesn't reset stdin/stdout. +/.startnewjob { % + % .startnewjob - + 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 + % The Adobe documentation doesn't say what happens to the + % graphics state stack in this case, but an experiment + % produced results suggesting that a grestoreall occurs. + grestoreall + } { + % Encapsulated job + pop + serverdict /.jobsave save put + serverdict /.jobsavelevel 1 put + .userdict /quit /stop load put + } ifelse + % Reset the interpreter state. + clear cleardictstack + initgraphics + false setglobal +} bind def +/.startjob { % + % .startjob + vmstatus pop pop serverdict /.jobsavelevel get eq + 2 index .checkpassword 0 gt and { + exch .checkpassword exch count 3 roll count 3 sub { pop } repeat + cleardictstack + % Reset the e-stack back to the 2 .stopped in .runexec, + % passing the finish_proc to be executed afterwards. + 2 .stop + } { % Password check failed + pop pop pop false + } ifelse +} odef +/startjob { % startjob + { .startnewjob true } .startjob +} odef + +systemdict begin +/quit { % - quit - + //systemdict begin serverdict /.jobsave get null eq + { end //quit } + { /quit load /invalidaccess /signalerror load end exec } + ifelse +} bind odef +end + +% We would like to define exitserver as a procedure, using the code +% that the Red Book says is equivalent to it. However, since startjob +% resets the exec stack, we can't do this, because control would never +% proceed past the call on startjob if the exitserver is successful. +% Instead, we need to construct exitserver out of pieces of startjob. + +serverdict begin + +/exitserver { % exitserver - + true exch { .startnewjob } .startjob not { + /exitserver /invalidaccess signalerror + } if +} bind def + +end % serverdict + +% ------ 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. + +/.dict1 { exch mark 3 1 roll .dicttomark } bind def + +currentglobal false setglobal 25 dict exch setglobal begin +currentsystemparams + +% The following do not depend on the presence of setpagedevice. +/buildtime 1 index /BuildTime get def +/byteorder 1 index /ByteOrder get def +/checkpassword { .checkpassword 0 gt } bind def +dup /DoStartPage known + { /dostartpage { /DoStartPage getsystemparam } bind def + /setdostartpage { /DoStartPage .dict1 setsystemparams } bind def + } if +dup /StartupMode known + { /dosysstart { /StartupMode getsystemparam 0 ne } bind def + /setdosysstart { { 1 } { 0 } ifelse /StartupMode .dict1 setsystemparams } bind def + } if +%****** Setting jobname is supposed to set userparams.JobName, too. +/jobname { /JobName getuserparam } bind def +/jobtimeout { /JobTimeout getuserparam } bind def +/ramsize { /RamSize getsystemparam } bind def +/realformat 1 index /RealFormat get def +dup /PrinterName known + { /setprintername { /PrinterName .dict1 setsystemparams } bind def + } if +/printername + { currentsystemparams /PrinterName .knownget not { () } if exch copy + } bind def +currentuserparams /WaitTimeout known + { /waittimeout { /WaitTimeout getuserparam } bind def + } if + +% The following do require setpagedevice. +/.setpagedevice where { pop } { (%END PAGEDEVICE) .skipeof } ifelse +/defaulttimeouts + { currentsystemparams dup + /JobTimeout .knownget not { 0 } if + exch /WaitTimeout .knownget not { 0 } if + currentpagedevice /ManualFeedTimeout .knownget not { 0 } if + } bind def +/margins + { currentpagedevice /Margins .knownget { exch } { [0 0] } ifelse + } bind def +/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 +/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 +/.setpagesize { 2 array astore /PageSize .dict1 setpagedevice } bind def +/setduplexmode { /Duplex .dict1 setpagedevice } bind def +/setmargins + { exch 2 array astore /Margins .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 +%END PAGEDEVICE + +% The following are not implemented yet. +%manualfeed +%manualfeedtimeout +%pagecount +%pagestackorder +%setpagestackorder + +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 .forcedef % statusdict is local, systemdict is global + +% ------ Color spaces ------ % + +% Define the setcolorspace procedures: +% proc +/colorspacedict mark + /DeviceGray { pop 0 setgray null } bind + /DeviceRGB { pop 0 0 0 setrgbcolor null } bind + /setcmykcolor where + { pop /DeviceCMYK { pop 0 0 0 1 setcmykcolor null } bind + } if + /.setcieaspace where + { pop /CIEBasedA { NOCIE { pop 0 setgray null } { dup 1 get .setcieaspace } ifelse } bind + } if + /.setcieabcspace where + { pop /CIEBasedABC { NOCIE { pop 0 0 0 setrgbcolor null } { dup 1 get .setcieabcspace } ifelse } bind + } if + /.setciedefspace where + { pop /CIEBasedDEF { NOCIE { pop 0 0 0 setrgbcolor null } { dup 1 get .setciedefspace } ifelse } bind + } if + /.setciedefgspace where + { pop /CIEBasedDEFG { NOCIE { pop 0 0 0 1 setcmykcolor null } { dup 1 get .setciedefgspace } ifelse } bind + } if + /.setseparationspace where + { pop /Separation { dup 2 get setcolorspace dup .setseparationspace } bind + } if + /.setindexedspace where + { pop /Indexed { dup 1 get setcolorspace dup .setindexedspace } bind + } if + /.nullpatternspace [/Pattern] readonly def + /.setpatternspace where + { pop /Pattern + { dup type /nametype eq { pop //.nullpatternspace } if + dup length 1 gt { dup 1 get setcolorspace } if + dup .setpatternspace + } bind + } if + /.setdevicenspace where + { pop /DeviceN { dup 2 get setcolorspace dup .setdevicenspace } bind + } if + /.setdevicepixelspace where + { pop /DevicePixel { dup .setdevicepixelspace } bind + } if + currentdict /.nullpatternspace .undef +.dicttomark def + +/.devcs [ + /DeviceGray /DeviceRGB /DeviceCMYK /DevicePixel +] readonly def +/currentcolorspace { % - currentcolorspace + .currentcolorspace dup type /integertype eq { + //.devcs exch 1 getinterval + } if +} odef +currentdict /.devcs .undef + +/setcolorspace { % setcolorspace - + dup dup dup type /nametype ne { 0 get } if + //colorspacedict exch get exec + dup null eq { pop } { .setcolorspace } ifelse pop +} odef + +% ------ CIE color rendering ------ % + +% Define findcolorrendering and a default ColorRendering ProcSet. + +/findcolorrendering { % findcolorrendering + % + /ColorRendering /ProcSet findresource + 1 index .namestring (.) concatstrings + 1 index /GetPageDeviceName get exec .namestring (.) concatstrings + 2 index /GetHalftoneName get exec .namestring + concatstrings concatstrings + dup /ColorRendering resourcestatus { + pop pop exch pop exch pop true + } { + pop /GetSubstituteCRD get exec false + } ifelse +} odef + +5 dict dup begin + +/GetPageDeviceName { % - GetPageDeviceName + currentpagedevice dup /PageDeviceName .knownget { + exch pop + } { + pop /none + } ifelse +} bind def + +/GetHalftoneName { % - GetHalftoneName + currenthalftone /HalftoneName .knownget not { /none } if +} bind def + +/GetSubstituteCRD { % GetSubstituteCRD + pop /DefaultColorRendering +} bind def + +end +% The resource machinery hasn't been activated, so just save the ProcSet +% and let .fixresources finish the installation process. +/ColorRendering exch def + +% Define setcolorrendering. + +/.colorrenderingtypes 5 dict def + +/setcolorrendering { % setcolorrendering - + dup /ColorRenderingType get //.colorrenderingtypes exch get exec +} odef + +/.setcolorrendering1 where { pop } { (%END CRD) .skipeof } ifelse + +.colorrenderingtypes 1 { + dup .buildcolorrendering1 .setcolorrendering1 +} .bind put + +% Initialize the default CIE rendering dictionary. +% 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. +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] readonly + /TransformPQR + [ {exch pop exch pop exch pop exch pop} bind dup dup ] readonly + /RangeLMN [0 0.9505 0 1 0 1.0890] readonly + /MatrixABC + [ 3.24063 -0.96893 0.05571 + -1.53721 1.87576 -0.20402 + -0.49863 0.04152 1.05700 + ] readonly + /EncodeABC [ {0 .max 0.45 exp} bind dup dup] readonly + /WhitePoint [0.9505 1 1.0890] readonly + % Some Genoa tests seem to require the presence of BlackPoint. + /BlackPoint [0 0 0] readonly +.dicttomark setcolorrendering + +%END CRD + +% Initialize a CIEBased color space for sRGB. +/CIEsRGB [ /CIEBasedABC + mark + /DecodeLMN [ { + dup 0.03928 le { 12.92321 div } { 0.055 add 1.055 div 2.4 exp } ifelse + } bind dup dup ] readonly + /MatrixLMN [ + 0.412457 0.212673 0.019334 + 0.357576 0.715152 0.119192 + 0.180437 0.072175 0.950301 + ] readonly + /WhitePoint [0.9505 1.0 1.0890] readonly + .dicttomark readonly +] readonly def + +% ------ Painting ------ % + +% A straightforward definition of execform that doesn't actually +% do any caching. +/.execform1 { + % This is a separate operator so that the stacks will be restored + % properly if an error occurs. + dup /Matrix get concat + dup /BBox get aload pop + exch 3 index sub exch 2 index sub rectclip + dup /PaintProc get + 1 index /Implementation known not { + 1 index dup /Implementation null .forceput readonly pop + } if + exec +} .bind odef % must bind .forceput + +/.formtypes 5 dict + dup 1 /.execform1 load put +def + +/execform { %
execform - + gsave { + dup /FormType get //.formtypes exch get exec + } stopped grestore { stop } if +} odef + +/.patterntypes 5 dict + dup 1 /.buildpattern1 load put +def + +/makepattern { % makepattern + //.patterntypes 2 index /PatternType get get + .currentglobal false .setglobal exch + % Stack: proto matrix global buildproc + 3 index dup length 1 add dict .copydict + 3 index 3 -1 roll exec 3 -1 roll .setglobal + 1 index /Implementation 3 -1 roll put + readonly exch pop exch pop +} odef + +/setpattern { % [ ...] setpattern - + currentcolorspace 0 get /Pattern ne { + [ /Pattern currentcolorspace ] setcolorspace + } if setcolor +} odef + +% Extend image and imagemask to accept dictionaries. +% We must create .imagetypes and .imagemasktypes outside level2dict, +% and leave some extra space because we're still in Level 1 mode. +systemdict begin +/.imagetypes 5 dict + dup 1 /.image1 load put +def +/.imagemasktypes 5 dict + dup 1 /.imagemask1 load put +def +end + +/.image /image load def +/image { + dup type /dicttype eq { + dup /ImageType get //.imagetypes exch get exec + } { + //.image + } ifelse +} odef +currentdict /.image undef + +/.imagemask /imagemask load def +/imagemask { + dup type /dicttype eq { + dup /ImageType get //.imagemasktypes exch get exec + } { + //.imagemask + } ifelse +} odef +currentdict /.imagemask undef + +end % level2dict diff --git a/pstoraster/gs_ll3.ps b/pstoraster/gs_ll3.ps new file mode 100644 index 0000000000..acf701ec67 --- /dev/null +++ b/pstoraster/gs_ll3.ps @@ -0,0 +1,387 @@ +% Copyright (C) 1997, 1998 Aladdin Enterprises. All rights reserved. +% +% This file is part of GNU Ghostscript. +% +% GNU Ghostscript is distributed in the hope that it will be useful, but +% WITHOUT ANY WARRANTY. No author or distributor accepts responsibility +% to anyone for the consequences of using it or for whether it serves any +% particular purpose or works at all, unless he says so in writing. Refer +% to the GNU General Public License for full details. +% +% Everyone is granted permission to copy, modify and redistribute GNU +% Ghostscript, but only under the conditions described in the GNU General +% Public License. A copy of this license is supposed to have been given +% to you along with GNU Ghostscript so you can know your rights and +% responsibilities. It should be in a file named COPYING. Among other +% things, the copyright notice and this notice must be preserved on all +% copies. +% +% Aladdin Enterprises supports the work of the GNU Project, but is not +% affiliated with the Free Software Foundation or the GNU Project. GNU +% Ghostscript, as distributed by Aladdin Enterprises, does not require any +% GNU software to build or run it. + +% $Id: gs_ll3.ps 956 2000-03-08 23:15:43Z mike $ +% Initialization file for PostScript LanguageLevel 3 functions. +% Essentially all of these are stubs right now. +% This file must be loaded after gs_lev2.ps and gs_res.ps. +% These definitions go into ll3dict or various ProcSets. +% NOTE: the interpreter creates ll3dict. + +ll3dict begin + +% We need LanguageLevel 2 or higher in order to have setuserparams and +% defineresource. +languagelevel dup 2 max .setlanguagelevel + +% ------ Idiom recognition ------ % + +/IdiomRecognition false .definepsuserparam + +% Modify `bind' to apply idiom recognition afterwards. +/.bindscratch 128 string def +% Do the right thing if NOBIND or DELAYBIND is in effect. +% Note also that since this definition of `bind' may get bound in, +% it has to function properly even at lower language levels, +% where IdiomRecognition may not be defined. +/bind load /.bind load ne +/bind { % bind + //.bind currentuserparams /IdiomRecognition + .knownget not { false } if { + (*) { + /IdiomSet findresource + false exch { + % Stack: proc false dummykey [template substitute] + exch pop dup 1 get exch 0 get + % Stack: proc false substitute template + 3 index .eqproc { + 2 index gcheck 1 index gcheck not and { + pop + } { + 3 -1 roll pop exch not exit + } ifelse + } { + pop + } ifelse + } forall { exit } if + } //.bindscratch /IdiomSet resourceforall + } if +} odef +{ /.bind /bind load def + /bind { } def +} if +currentdict /.bindscratch .undef + +% ------ HalftoneTypes 6, 10, 16 ------ % + +% This code depends on one new operator: +% +% .setstriphalftone - +% +% is the dictionary that will be returned by .currenthalftone. +% The operator only looks at the TransferFunction entry. +% Width, Height: as for HalftoneType 3. +% Thresholds: a BigStringEncode filter holding the thresholds, +% Width x Height x BitsPerSample / 8 bytes. +% shift: the amount of X shift per Y repetition of the halftone, +% 0 <= Shift < Width. +% bits: bits per sample, 8 or 16. +% +% Eventually the code below will have to get hooked up to sethalftone +% and currenthalftone.... + +/.copybytes { % .copybytes - + { 1 index read not { /sethalftone load /rangecheck signalerror exit } if + 1 index exch write + } repeat pop pop +} bind def + +/.copythresholds { % .copythresholds - + dup 8 idiv 3 index mul 2 index mul + dup /BigStringEncode filter 3 1 roll + % Stack: dict width height dest bits nbytes + 5 index /Thresholds get 3 index 3 -1 roll .copybytes + 1 index closefile + 0 .setstriphalftone +} bind def + +/.sethalftone6 { % .sethalftone6 - + % Keys: Width, Height, Thresholds, T'Function + dup /Width get 1 index /Height get + 8 .copythresholds +} odef + +/.copythresholds2 { % + % .copythresholds2 - +% The block height B is gcd(Height, Height2). + 3 index 2 index { + 2 copy lt { exch } if dup 1 eq { pop exit } if exch 1 index mod + } loop +% The raster R is (Width * Height + Width2 * Height2) / B * bits/8. + 5 index 5 index mul 4 index 4 index mul add 1 index idiv + 2 index 8 idiv mul +% Currently I don't know how to compute the stride. +% ****** COMPUTE THE STRIDE SOMEHOW ****** +% Push additional arguments onto the stack. + 1 index 1 index mul /BigStringEncode filter 4 1 roll + 9 index /Thresholds get + % Stack: dict width height width2 height2 bits + % dest B R stride source +% For the first rectangle, the number of blocks is Height / B; +% the offset is 0. + 5 copy 14 index 5 1 roll + 14 index 5 index idiv 4 1 roll + 0 exch .copyshifted +% For the second rectangle, the number of blocks is Height2 / B; +% the offset is Width. + 5 copy 12 index 5 1 roll + 12 index 4 index idiv 4 1 roll + 16 index exch .copyshifted + % Stack: dict width height width2 height2 bits + % dest B R stride source + % We want: dict R/(bits/8) B dest bits stride + pop exch 4 index 8 idiv idiv 4 1 roll + % R/(bits/8) dest B stride + exch 3 1 roll 5 -1 roll exch + 9 -4 roll 4 { pop } repeat + .setstriphalftone +} bind def + +% Copy a shifted rectangular threshold array into a BigStringEncode filter. +% Note that the width and shift are in bytes, not samples. +/.copyshifted { % + % .copyshifted - +% Copy N blocks of x B bytes from . +% Row Y (0 <= Y < B) in group G (0 <= G < N) must get copied to byte position +% Y * R + (G * stride + offset) mod R +% in the destination. + 1 index % Stack: ... rowstart + 6 index { % iterate over rows within a block + 5 index { % iterate over blocks + 8 index 1 index setfileposition + 1 index 9 index 9 index .copybytes + 4 index add % + raster + } repeat % end block + 3 index add 4 index mod % + stride, mod raster + } repeat % end row in block + 9 { pop } repeat +} bind def + +/.sethalftone10 { % .sethalftone10 - + % Keys: XSquare, YSquare, Thresholds, T'Function +% ****** DOESN'T HANDLE STRING SOURCE ****** + dup /XSquare get dup 2 index /YSquare get dup + 8 .copythresholds2 +} odef + +/.sethalftone16 { % .sethalftone16 - + % Keys: Width, Height, Width2, Height2, + % Thresholds, T'Function + dup /Width get 1 index /Height get + 2 index /Width2 .knownget { % 2-rectangle case + 3 index /Height2 get + 16 .copythresholds2 + } { % 1-rectangle case + 16 .copythresholds + } ifelse +} odef + +{6 10 16} { dup /HalftoneType defineresource pop } forall + +% ------ ImageTypes 3 and 4 (masked images) ------ % + +.imagetypes + dup 3 /.image3 load put + 4 /.image4 load put + +% ------ Functions ------ % + +% Define the FunctionType resource category. +/Generic /Category findresource dup maxlength 3 add dict .copydict begin + /InstanceType /integertype def +/FunctionType currentdict end /Category defineresource pop + +{0 2 3} { dup /FunctionType defineresource pop } forall + +% ------ Smooth shading ------ % + +% Define the ShadingType resource category. +/Generic /Category findresource dup maxlength 3 add dict .copydict begin + /InstanceType /integertype def +/ShadingType currentdict end /Category defineresource pop + +systemdict /.shadingtypes mark % not ll3dict + 1 /.buildshading1 load + 2 /.buildshading2 load + 3 /.buildshading3 load + 4 /.buildshading4 load + 5 /.buildshading5 load + 6 /.buildshading6 load + 7 /.buildshading7 load +.dicttomark put + +/.buildshading { % .buildshading + % The .buildshading operators use the current color space + % for ColorSpace. + dup /ShadingType get //.shadingtypes exch get + 1 index /ColorSpace get gsave { setcolorspace exec } stopped + grestore { stop } if +} bind def +/.buildpattern2 { %