diff options
author | msweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be> | 2008-01-17 00:06:33 +0000 |
---|---|---|
committer | msweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be> | 2008-01-17 00:06:33 +0000 |
commit | 91c84a3551145559de2956179661e111e373db95 (patch) | |
tree | ea061b2b6ab3b9e4530347e35f5cde3511f8a305 | |
parent | 080811b190031b9182e96dc76fc610fadfeaec21 (diff) | |
download | cups-91c84a3551145559de2956179661e111e373db95.tar.gz |
Import CUPS 1.4svn-r7226.
git-svn-id: svn+ssh://src.apple.com/svn/cups/easysw/current@582 a1ca3aef-8c08-0410-bb20-df032aa958be
190 files changed, 3360 insertions, 65198 deletions
diff --git a/CHANGES-1.3.txt b/CHANGES-1.3.txt index bd9682755..788b076bc 100644 --- a/CHANGES-1.3.txt +++ b/CHANGES-1.3.txt @@ -4,6 +4,31 @@ CHANGES-1.3.txt CHANGES IN CUPS V1.3.6 - Documentation updates (STR #2646, STR #2647, STR #2649) + - cupsEncodeOptions2() did not handle option values like + "What's up, doc?" properly. + - Added lots of memory allocation checks (Fortify) + - The scheduler would crash if it was unable to add a job + file (Fortify) + - ppdOpen*() did not check all memory allocations (Coverity) + - ippReadIO() did not check all memory allocations (Coverity) + - The PostScript filter did not detect read errors (Coverity) + - The scheduler did not check for a missing job-sheets-completed + attribute when sending an event notification (Coverity) + - "Set Printer Options" might not work with raw queues (Coverity) + - cupsRasterInterpretPPD() could crash on certain PostScript + errors (Coverity) + - The USB backend did not check for back-channel support + properly on all systems (Coverity) + - Fixed memory leaks in the GIF and PNM image loading code + (Coverity) + - Removed some dead code in the CUPS API and scheduler (Coverity) + - Fixed two overflow bugs in the HP-GL/2 filter (Coverity) + - Fixed another ASN1 string parsing bug (STR #2665) + - The RSS notifier directory was not installed with the + correct permissions. + - The standard CUPS backends could use 100% CPU while waiting + for print data (STR #2664) + - Filename-based MIME rules did not work (STR #2659) - The cups-polld program did not exit if the scheduler crashed (STR #2640) - The scheduler would crash if you tried to set the port-monitor diff --git a/CHANGES.txt b/CHANGES.txt index c9bcee7f9..c5582f5fc 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,8 +1,10 @@ -CHANGES.txt - 2008-01-07 +CHANGES.txt - 2008-01-08 ------------------------ CHANGES IN CUPS V1.4b1 + - The pdftops filter now executes the Xpdf or poppler + pdftops utility to convert PDF files (STR #1471) - Bonjour printer registrations now advertise as local or global based on the current access policies for the printer. @@ -3,7 +3,7 @@ # # Top-level Makefile for the Common UNIX Printing System (CUPS). # -# Copyright 2007 by Apple Inc. +# Copyright 2007-2008 by Apple Inc. # Copyright 1997-2007 by Easy Software Products, all rights reserved. # # These coded instructions, statements, and computer programs are the @@ -20,7 +20,7 @@ include Makedefs # DIRS = cups backend berkeley cgi-bin filter locale man monitor \ - notifier $(PDFTOPS) scheduler systemv test \ + notifier scheduler systemv test \ $(PHPDIR) \ conf data doc $(FONTS) ppd templates diff --git a/backend/Dependencies b/backend/Dependencies index da928d11e..fd10e6a94 100644 --- a/backend/Dependencies +++ b/backend/Dependencies @@ -1,50 +1,52 @@ # DO NOT DELETE THIS LINE -- make depend depends on it. -betest.o: betest.c ../cups/string.h ../config.h -ipp.o: ipp.c ../cups/http-private.h ../config.h ../cups/http.h \ - ../cups/md5.h ../cups/ipp-private.h ../cups/ipp.h ../cups/backend.h \ - ../cups/cups.h ../cups/ppd.h ../cups/array.h ../cups/file.h \ - ../cups/language.h ../cups/language.h ../cups/i18n.h \ - ../cups/transcode.h ../cups/string.h -lpd.o: lpd.c ../cups/backend.h ../cups/http-private.h ../config.h \ - ../cups/http.h ../cups/md5.h ../cups/ipp-private.h ../cups/ipp.h \ - ../cups/cups.h ../cups/ppd.h ../cups/array.h ../cups/file.h \ - ../cups/language.h ../cups/i18n.h ../cups/transcode.h ../cups/string.h -pap.o: pap.c ../config.h ../cups/cups.h ../cups/ipp.h ../cups/http.h \ - ../cups/ppd.h ../cups/array.h ../cups/file.h ../cups/language.h \ - ../cups/backend.h ../cups/sidechannel.h ../cups/i18n.h \ - ../cups/transcode.h -parallel.o: parallel.c backend-private.h ../cups/backend.h \ - ../cups/sidechannel.h ../cups/cups.h ../cups/ipp.h ../cups/http.h \ - ../cups/ppd.h ../cups/array.h ../cups/file.h ../cups/language.h \ - ../cups/debug.h ../cups/i18n.h ../cups/transcode.h ../cups/string.h \ - ../config.h -scsi.o: scsi.c ../cups/backend.h ../cups/cups.h ../cups/ipp.h \ - ../cups/http.h ../cups/ppd.h ../cups/array.h ../cups/file.h \ - ../cups/language.h ../cups/i18n.h ../cups/transcode.h ../cups/string.h \ - ../config.h scsi-linux.c -serial.o: serial.c backend-private.h ../cups/backend.h \ - ../cups/sidechannel.h ../cups/cups.h ../cups/ipp.h ../cups/http.h \ - ../cups/ppd.h ../cups/array.h ../cups/file.h ../cups/language.h \ - ../cups/debug.h ../cups/i18n.h ../cups/transcode.h ../cups/string.h \ - ../config.h -snmp.o: snmp.c ../cups/http-private.h ../config.h ../cups/http.h \ - ../cups/md5.h ../cups/ipp-private.h ../cups/ipp.h backend-private.h \ - ../cups/backend.h ../cups/sidechannel.h ../cups/cups.h ../cups/ppd.h \ - ../cups/array.h ../cups/file.h ../cups/language.h ../cups/debug.h \ - ../cups/i18n.h ../cups/transcode.h ../cups/string.h ../cups/array.h \ - ../cups/file.h -socket.o: socket.c ../cups/http-private.h ../config.h ../cups/http.h \ - ../cups/md5.h ../cups/ipp-private.h ../cups/ipp.h backend-private.h \ - ../cups/backend.h ../cups/sidechannel.h ../cups/cups.h ../cups/ppd.h \ - ../cups/array.h ../cups/file.h ../cups/language.h ../cups/debug.h \ - ../cups/i18n.h ../cups/transcode.h ../cups/string.h -test1284.o: test1284.c ../cups/string.h ../config.h ieee1284.c \ - backend-private.h ../cups/backend.h ../cups/sidechannel.h \ - ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/ppd.h \ - ../cups/array.h ../cups/file.h ../cups/language.h ../cups/debug.h \ - ../cups/i18n.h ../cups/transcode.h -usb.o: usb.c ../cups/backend.h ../cups/cups.h ../cups/ipp.h \ - ../cups/http.h ../cups/ppd.h ../cups/array.h ../cups/file.h \ - ../cups/language.h ../cups/string.h ../config.h ../cups/i18n.h \ - ../cups/transcode.h usb-unix.c ieee1284.c backend-private.h \ - ../cups/sidechannel.h ../cups/debug.h + +betest.o: ../cups/string.h ../config.h +ipp.o: ../cups/http-private.h ../config.h ../cups/http.h ../cups/versioning.h +ipp.o: ../cups/md5.h ../cups/ipp-private.h ../cups/ipp.h ../cups/backend.h +ipp.o: ../cups/cups.h ../cups/ppd.h ../cups/array.h ../cups/file.h +ipp.o: ../cups/language.h ../cups/language.h ../cups/i18n.h +ipp.o: ../cups/transcode.h ../cups/string.h +lpd.o: ../cups/backend.h ../cups/versioning.h ../cups/http-private.h +lpd.o: ../config.h ../cups/http.h ../cups/md5.h ../cups/ipp-private.h +lpd.o: ../cups/ipp.h ../cups/cups.h ../cups/ppd.h ../cups/array.h +lpd.o: ../cups/file.h ../cups/language.h ../cups/i18n.h ../cups/transcode.h +lpd.o: ../cups/string.h +pap.o: ../config.h ../cups/cups.h ../cups/ipp.h ../cups/http.h +pap.o: ../cups/versioning.h ../cups/ppd.h ../cups/array.h ../cups/file.h +pap.o: ../cups/language.h ../cups/backend.h ../cups/sidechannel.h +pap.o: ../cups/i18n.h ../cups/transcode.h +parallel.o: backend-private.h ../cups/backend.h ../cups/versioning.h +parallel.o: ../cups/sidechannel.h ../cups/cups.h ../cups/ipp.h ../cups/http.h +parallel.o: ../cups/ppd.h ../cups/array.h ../cups/file.h ../cups/language.h +parallel.o: ../cups/debug.h ../cups/i18n.h ../cups/transcode.h ../cups/snmp.h +parallel.o: ../cups/string.h ../config.h +scsi.o: ../cups/backend.h ../cups/versioning.h ../cups/cups.h ../cups/ipp.h +scsi.o: ../cups/http.h ../cups/ppd.h ../cups/array.h ../cups/file.h +scsi.o: ../cups/language.h ../cups/i18n.h ../cups/transcode.h +scsi.o: ../cups/string.h ../config.h +serial.o: backend-private.h ../cups/backend.h ../cups/versioning.h +serial.o: ../cups/sidechannel.h ../cups/cups.h ../cups/ipp.h ../cups/http.h +serial.o: ../cups/ppd.h ../cups/array.h ../cups/file.h ../cups/language.h +serial.o: ../cups/debug.h ../cups/i18n.h ../cups/transcode.h ../cups/snmp.h +serial.o: ../cups/string.h ../config.h +snmp.o: backend-private.h ../cups/backend.h ../cups/versioning.h +snmp.o: ../cups/sidechannel.h ../cups/cups.h ../cups/ipp.h ../cups/http.h +snmp.o: ../cups/ppd.h ../cups/array.h ../cups/file.h ../cups/language.h +snmp.o: ../cups/debug.h ../cups/i18n.h ../cups/transcode.h ../cups/snmp.h +snmp.o: ../cups/string.h ../config.h ../cups/array.h ../cups/file.h +snmp.o: ../cups/http-private.h ../cups/md5.h ../cups/ipp-private.h +socket.o: ../cups/http-private.h ../config.h ../cups/http.h +socket.o: ../cups/versioning.h ../cups/md5.h ../cups/ipp-private.h +socket.o: ../cups/ipp.h backend-private.h ../cups/backend.h +socket.o: ../cups/sidechannel.h ../cups/cups.h ../cups/ppd.h ../cups/array.h +socket.o: ../cups/file.h ../cups/language.h ../cups/debug.h ../cups/i18n.h +socket.o: ../cups/transcode.h ../cups/snmp.h ../cups/string.h +test1284.o: ../cups/string.h ../config.h ieee1284.c backend-private.h +test1284.o: ../cups/backend.h ../cups/versioning.h ../cups/sidechannel.h +test1284.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/ppd.h +test1284.o: ../cups/array.h ../cups/file.h ../cups/language.h ../cups/debug.h +test1284.o: ../cups/i18n.h ../cups/transcode.h ../cups/snmp.h +usb.o: ../cups/backend.h ../cups/versioning.h ../cups/cups.h ../cups/ipp.h +usb.o: ../cups/http.h ../cups/ppd.h ../cups/array.h ../cups/file.h +usb.o: ../cups/language.h ../cups/string.h ../config.h ../cups/i18n.h +usb.o: ../cups/transcode.h diff --git a/backend/Makefile b/backend/Makefile index 79654eb62..3dccd1a53 100644 --- a/backend/Makefile +++ b/backend/Makefile @@ -3,7 +3,7 @@ # # Backend makefile for the Common UNIX Printing System (CUPS). # -# Copyright 2007 by Apple Inc. +# Copyright 2007-2008 by Apple Inc. # Copyright 1997-2007 by Easy Software Products, all rights reserved. # # These coded instructions, statements, and computer programs are the diff --git a/backend/backend-private.h b/backend/backend-private.h index d4a10b6a6..cd6f78b38 100644 --- a/backend/backend-private.h +++ b/backend/backend-private.h @@ -28,6 +28,7 @@ # include <cups/cups.h> # include <cups/debug.h> # include <cups/i18n.h> +# include <cups/snmp.h> # include <stdlib.h> # include <errno.h> # include <cups/string.h> @@ -44,6 +45,157 @@ extern "C" { /* + * OID constants... + */ + +#define CUPS_OID_mib2 1,3,6,1,2,1 + +#define CUPS_OID_host CUPS_OID_mib2,25 + +#define CUPS_OID_hrSystem CUPS_OID_host,1 + +#define CUPS_OID_hrStorage CUPS_OID_host,2 + +#define CUPS_OID_hrDevice CUPS_OID_host,3 +#define CUPS_OID_hrDeviceTable CUPS_OID_hrDevice,2 +#define CUPS_OID_hrDeviceEntry CUPS_OID_hrDeviceTable,1 +#define CUPS_OID_hrDeviceIndex CUPS_OID_hrDeviceEntry,1 +#define CUPS_OID_hrDeviceType CUPS_OID_hrDeviceEntry,2 +#define CUPS_OID_hrDeviceDescr CUPS_OID_hrDeviceEntry,3 + +#define CUPS_OID_hrPrinterTable CUPS_OID_hrDevice,5 +#define CUPS_OID_hrPrinterEntry CUPS_OID_hrPrinterTable,1 +#define CUPS_OID_hrPrinterStatus CUPS_OID_hrPrinterEntry,1 +#define CUPS_OID_hrPrinterDetectedErrorState CUPS_OID_hrPrinterEntry,2 + +#define CUPS_OID_printmib CUPS_OID_mib2,43 + +#define CUPS_OID_prtGeneral CUPS_OID_printmib,5 +#define CUPS_OID_prtGeneralTable CUPS_OID_prtGeneral,1 +#define CUPS_OID_prtGeneralEntry CUPS_OID_prtGeneralTable,1 +#define CUPS_OID_prtGeneralPrinterName CUPS_OID_prtGeneralEntry,16 +#define CUPS_OID_prtGeneralSerialNumber CUPS_OID_prtGeneralEntry,17 + +#define CUPS_OID_prtCover CUPS_OID_printmib,6 +#define CUPS_OID_prtCoverTable CUPS_OID_prtCover,1 +#define CUPS_OID_prtCoverEntry CUPS_OID_prtCoverTable,1 +#define CUPS_OID_prtCoverDescription CUPS_OID_prtCoverEntry,2 +#define CUPS_OID_prtCoverStatus CUPS_OID_prtCoverEntry,3 + +#define CUPS_OID_prtMarker CUPS_OID_printmib,10 +#define CUPS_OID_prtMarkerTable CUPS_OID_prtMarker,2 +#define CUPS_OID_prtMarkerEntry CUPS_OID_prtMarkerTable,1 +#define CUPS_OID_prtMarkerLifeCount CUPS_OID_prtMarkerEntry,4 + +#define CUPS_OID_prtMarkerSupplies CUPS_OID_printmib,11 +#define CUPS_OID_prtMarkerSuppliesTable CUPS_OID_prtMarkerSupplies,1 +#define CUPS_OID_prtMarkerSuppliesEntry CUPS_OID_prtMarkerSuppliesTable,1 +#define CUPS_OID_prtMarkerSuppliesIndex CUPS_OID_prtMarkerSuppliesEntry,1 +#define CUPS_OID_prtMarkerSuppliesMarkerIndex CUPS_OID_prtMarkerSuppliesEntry,2 +#define CUPS_OID_prtMarkerSuppliesColorantIndex CUPS_OID_prtMarkerSuppliesEntry,3 +#define CUPS_OID_prtMarkerSuppliesClass CUPS_OID_prtMarkerSuppliesEntry,4 +#define CUPS_OID_prtMarkerSuppliesType CUPS_OID_prtMarkerSuppliesEntry,5 +#define CUPS_OID_prtMarkerSuppliesDescription CUPS_OID_prtMarkerSuppliesEntry,6 +#define CUPS_OID_prtMarkerSuppliesSupplyUnit CUPS_OID_prtMarkerSuppliesEntry,7 +#define CUPS_OID_prtMarkerSuppliesMaxCapacity CUPS_OID_prtMarkerSupliesEntry,8 +#define CUPS_OID_prtMarkerSuppliesLevel CUPS_OID_prtMarkerSupliesEntry,9 + +#define CUPS_OID_prtMarkerColorant CUPS_OID_printmib,12 +#define CUPS_OID_prtMarkerColorantTable CUPS_OID_prtMarkerColorant,1 +#define CUPS_OID_prtMarkerColorantEntry CUPS_OID_prtMarkerColorantTable,1 +#define CUPS_OID_prtMarkerColorantIndex CUPS_OID_prtMarkerColorantEntry,1 +#define CUPS_OID_prtMarkerColorantMarkerIndex CUPS_OID_prtMarkerColorantEntry,2 +#define CUPS_OID_prtMarkerColorantRole CUPS_OID_prtMarkerColorantEntry,3 +#define CUPS_OID_prtMarkerColorantValue CUPS_OID_prtMarkerColorantEntry,4 +#define CUPS_OID_prtMarkerColorantTonality CUPS_OID_prtMarkerColorantEntry,5 + +#define CUPS_OID_prtInterpreter CUPS_OID_printmib,15 +#define CUPS_OID_prtInterpreterTable CUPS_OID_prtInterpreter,1 +#define CUPS_OID_prtInterpreterEntry CUPS_OID_prtInterpreterTable,1 +#define CUPS_OID_prtInterpreterLangFamily CUPS_OID_prtInterpreterEntry,2 +#define CUPS_OID_prtInterpreterLangLevel CUPS_OID_prtInterpreterEntry,3 + + +/* + * State constants... + */ + +#define CUPS_TC_other 1 +#define CUPS_TC_unknown 2 + +#define CUPS_TC_idle 3 +#define CUPS_TC_printing 4 +#define CUPS_TC_warmup 5 + +/* These come from the hrPrinterDetectedErrorState OCTET-STRING */ +#define CUPS_TC_lowPaper 0x8000 +#define CUPS_TC_noPaper 0x4000 +#define CUPS_TC_lowToner 0x2000 +#define CUPS_TC_noToner 0x1000 +#define CUPS_TC_doorOpen 0x0800 +#define CUPS_TC_jammed 0x0400 +#define CUPS_TC_offline 0x0200 +#define CUPS_TC_serviceRequested 0x0100 +#define CUPS_TC_inputTrayMissing 0x0080 +#define CUPS_TC_outputTrayMissing 0x0040 +#define CUPS_TC_markerSupplyMissing 0x0020 +#define CUPS_TC_outputNearFull 0x0010 +#define CUPS_TC_outputFull 0x0008 +#define CUPS_TC_inputTrayEmpty 0x0004 +#define CUPS_TC_overduePreventMaint 0x0002 + +#define CUPS_TC_prtCoverStatus_coverOpen 3 +#define CUPS_TC_prtCoverStatus_coverClosed 4 +#define CUPS_TC_prtCoverStatus_interlockOpen 5 +#define CUPS_TC_prtCoverStatus_interlockClosed 6 + +#define CUPS_TC_langPCL 3 +#define CUPS_TC_langHPGL 4 +#define CUPS_TC_langPJL 5 +#define CUPS_TC_langPS 6 +#define CUPS_TC_langEscapeP 9 +#define CUPS_TC_langCCITT 26 +#define CUPS_TC_langLIPS 39 +#define CUPS_TC_langTIFF 40 +#define CUPS_TC_langPCLXL 47 +#define CUPS_TC_langPDF 54 +#define CUPS_TC_langJPEG 61 + +#define CUPS_TC_toner 3 +#define CUPS_TC_wasteToner 4 +#define CUPS_TC_ink 5 +#define CUPS_TC_inkCartridge 6 +#define CUPS_TC_inkRibbon 7 +#define CUPS_TC_wasteInk 8 +#define CUPS_TC_opc 9 +#define CUPS_TC_developer 10 +#define CUPS_TC_fuserOil 11 +#define CUPS_TC_solidWax 12 +#define CUPS_TC_ribbonWax 13 +#define CUPS_TC_wasteWax 14 +#define CUPS_TC_fuser 15 +#define CUPS_TC_coronaWire 16 +#define CUPS_TC_fuserOilWick 17 +#define CUPS_TC_cleanerUnit 18 +#define CUPS_TC_fuserCleaningPad 19 +#define CUPS_TC_transferUnit 20 +#define CUPS_TC_tonerCartridge 21 +#define CUPS_TC_fuserOiler 22 +#define CUPS_TC_water 23 +#define CUPS_TC_wasteWater 24 +#define CUPS_TC_glueWaterAdditive 25 +#define CUPS_TC_wastePaper 26 +#define CUPS_TC_bindingSupply 27 +#define CUPS_TC_bandingSupply 28 +#define CUPS_TC_stitchingWire 29 +#define CUPS_TC_shrinkWrap 30 +#define CUPS_TC_paperWrap 31 +#define CUPS_TC_staples 32 +#define CUPS_TC_inserts 33 +#define CUPS_TC_covers 34 + + +/* * Prototypes... */ diff --git a/backend/runloop.c b/backend/runloop.c index a4a8c4bbf..5af3d77f1 100644 --- a/backend/runloop.c +++ b/backend/runloop.c @@ -3,7 +3,7 @@ * * Common run loop APIs for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 2006-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -216,7 +216,7 @@ backendRunLoop( FD_SET(CUPS_SC_FD, &input); FD_ZERO(&output); - if (print_bytes || !use_bc) + if (print_bytes || (!use_bc && !side_cb)) FD_SET(device_fd, &output); if (use_bc || side_cb) diff --git a/backend/snmp.c b/backend/snmp.c index 8969474ac..a001ff864 100644 --- a/backend/snmp.c +++ b/backend/snmp.c @@ -3,7 +3,7 @@ * * SNMP discovery backend for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 2006-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -21,38 +21,15 @@ * add_cache() - Add a cached device... * add_device_uri() - Add a device URI to the cache. * alarm_handler() - Handle alarm signals... - * asn1_decode_snmp() - Decode a SNMP packet. - * asn1_debug() - Decode an ASN1-encoded message. - * asn1_encode_snmp() - Encode a SNMP packet. - * asn1_get_integer() - Get an integer value. - * asn1_get_length() - Get a value length. - * asn1_get_oid() - Get an OID value. - * asn1_get_packed() - Get a packed integer value. - * asn1_get_string() - Get a string value. - * asn1_get_type() - Get a value type. - * asn1_set_integer() - Set an integer value. - * asn1_set_length() - Set a value length. - * asn1_set_oid() - Set an OID value. - * asn1_set_packed() - Set a packed integer value. - * asn1_size_integer() - Figure out the number of bytes needed for an - * integer value. - * asn1_size_length() - Figure out the number of bytes needed for a - * length value. - * asn1_size_oid() - Figure out the numebr of bytes needed for an - * OID value. - * asn1_size_packed() - Figure out the number of bytes needed for a - * packed integer value. * compare_cache() - Compare two cache entries. * debug_printf() - Display some debugging information. * fix_make_model() - Fix common problems in the make-and-model * string. * free_array() - Free an array of strings. * free_cache() - Free the array of cached devices. - * get_interface_addresses() - Get the broadcast address(es) associated - * with an interface. - * hex_debug() - Output hex debugging data... + * get_interface_addresses() - Get the broadcast address(es) associated with + * an interface. * list_device() - List a device we found... - * open_snmp_socket() - Open the SNMP broadcast socket. * password_cb() - Handle authentication requests. * probe_device() - Probe a device to discover whether it is a * printer. @@ -60,7 +37,6 @@ * read_snmp_response() - Read and parse a SNMP response... * run_time() - Return the total running time... * scan_devices() - Scan for devices using SNMP. - * send_snmp_query() - Send an SNMP query packet. * try_connect() - Try connecting on a port... * update_cache() - Update a cached device... */ @@ -69,10 +45,11 @@ * Include necessary headers. */ -#include <cups/http-private.h> #include "backend-private.h" #include <cups/array.h> #include <cups/file.h> +#include <cups/snmp.h> +#include <cups/http-private.h> #include <regex.h> @@ -133,28 +110,6 @@ */ /* - * Constants... - */ - -#define SNMP_PORT 161 /* SNMP well-known port */ -#define SNMP_MAX_OID 64 /* Maximum number of OID numbers */ -#define SNMP_MAX_PACKET 1472 /* Maximum size of SNMP packet */ -#define SNMP_MAX_STRING 512 /* Maximum size of string */ -#define SNMP_VERSION_1 0 /* SNMPv1 */ - -#define ASN1_END_OF_CONTENTS 0x00 /* End-of-contents */ -#define ASN1_BOOLEAN 0x01 /* BOOLEAN */ -#define ASN1_INTEGER 0x02 /* INTEGER or ENUMERATION */ -#define ASN1_BIT_STRING 0x03 /* BIT STRING */ -#define ASN1_OCTET_STRING 0x04 /* OCTET STRING */ -#define ASN1_NULL_VALUE 0x05 /* NULL VALUE */ -#define ASN1_OID 0x06 /* OBJECT IDENTIFIER */ -#define ASN1_SEQUENCE 0x30 /* SEQUENCE */ -#define ASN1_GET_REQUEST 0xa0 /* Get-Request-PDU */ -#define ASN1_GET_RESPONSE 0xa2 /* Get-Response-PDU */ - - -/* * Types... */ @@ -173,28 +128,6 @@ typedef struct snmp_cache_s /**** SNMP scan cache ****/ *make_and_model; /* device-make-and-model */ } snmp_cache_t; -typedef struct snmp_packet_s /**** SNMP packet ****/ -{ - const char *error; /* Encode/decode error */ - int version; /* Version number */ - char community[SNMP_MAX_STRING]; - /* Community name */ - int request_type; /* Request type */ - int request_id; /* request-id value */ - int error_status; /* error-status value */ - int error_index; /* error-index value */ - int object_name[SNMP_MAX_OID]; - /* object-name value */ - int object_type; /* object-value type */ - union - { - int boolean; /* Boolean value */ - int integer; /* Integer value */ - int oid[SNMP_MAX_OID]; /* OID value */ - char string[SNMP_MAX_STRING];/* String value */ - } object_value; /* object-value value */ -} snmp_packet_t; - /* * Private CUPS API to set the last error... @@ -213,40 +146,6 @@ static void add_cache(http_addr_t *addr, const char *addrname, const char *make_and_model); static device_uri_t *add_device_uri(char *value); static void alarm_handler(int sig); -static int asn1_decode_snmp(unsigned char *buffer, size_t len, - snmp_packet_t *packet); -static void asn1_debug(unsigned char *buffer, size_t len, - int indent); -static int asn1_encode_snmp(unsigned char *buffer, size_t len, - snmp_packet_t *packet); -static int asn1_get_integer(unsigned char **buffer, - unsigned char *bufend, - int length); -static int asn1_get_oid(unsigned char **buffer, - unsigned char *bufend, - int length, int *oid, int oidsize); -static int asn1_get_packed(unsigned char **buffer, - unsigned char *bufend); -static char *asn1_get_string(unsigned char **buffer, - unsigned char *bufend, - int length, char *string, - int strsize); -static int asn1_get_length(unsigned char **buffer, - unsigned char *bufend); -static int asn1_get_type(unsigned char **buffer, - unsigned char *bufend); -static void asn1_set_integer(unsigned char **buffer, - int integer); -static void asn1_set_length(unsigned char **buffer, - int length); -static void asn1_set_oid(unsigned char **buffer, - const int *oid); -static void asn1_set_packed(unsigned char **buffer, - int integer); -static int asn1_size_integer(int integer); -static int asn1_size_length(int length); -static int asn1_size_oid(const int *oid); -static int asn1_size_packed(int integer); static int compare_cache(snmp_cache_t *a, snmp_cache_t *b); static void debug_printf(const char *format, ...); static void fix_make_model(char *make_model, @@ -255,19 +154,13 @@ static void fix_make_model(char *make_model, static void free_array(cups_array_t *a); static void free_cache(void); static http_addrlist_t *get_interface_addresses(const char *ifname); -static void hex_debug(unsigned char *buffer, size_t len); static void list_device(snmp_cache_t *cache); -static int open_snmp_socket(void); static const char *password_cb(const char *prompt); static void probe_device(snmp_cache_t *device); static void read_snmp_conf(const char *address); static void read_snmp_response(int fd); static double run_time(void); static void scan_devices(int fd); -static void send_snmp_query(int fd, http_addr_t *addr, int version, - const char *community, - const unsigned request_id, - const int *oid); static int try_connect(http_addr_t *addr, const char *addrname, int port); static void update_cache(snmp_cache_t *device, const char *uri, @@ -282,11 +175,9 @@ static cups_array_t *Addresses = NULL; static cups_array_t *Communities = NULL; static cups_array_t *Devices = NULL; static int DebugLevel = 0; -static int DeviceDescOID[] = { 1, 3, 6, 1, 2, 1, 25, 3, - 2, 1, 3, 1, 0 }; +static int DeviceDescOID[] = { CUPS_OID_hrDeviceDescr, 1, 0 }; static unsigned DeviceDescRequest; -static int DeviceTypeOID[] = { 1, 3, 6, 1, 2, 1, 25, 3, - 2, 1, 2, 1, 0 }; +static int DeviceTypeOID[] = { CUPS_OID_hrDeviceType, 1, 0 }; static unsigned DeviceTypeRequest; static cups_array_t *DeviceURIs = NULL; static int HostNameLookups = 0; @@ -345,7 +236,7 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */ * Open the SNMP socket... */ - if ((fd = open_snmp_socket()) < 0) + if ((fd = cupsSNMPOpen()) < 0) return (1); /* @@ -354,6 +245,8 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */ read_snmp_conf(argv[1]); + cupsSNMPSetDebug(DebugLevel); + Devices = cupsArrayNew((cups_array_func_t)compare_cache, NULL); /* @@ -366,7 +259,7 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */ * Close, free, and return with no errors... */ - close(fd); + cupsSNMPClose(fd); free_array(Addresses); free_array(Communities); @@ -548,798 +441,6 @@ alarm_handler(int sig) /* I - Signal number */ /* - * 'asn1_decode_snmp()' - Decode a SNMP packet. - */ - -static int /* O - 0 on success, -1 on error */ -asn1_decode_snmp(unsigned char *buffer, /* I - Buffer */ - size_t len, /* I - Size of buffer */ - snmp_packet_t *packet) /* I - SNMP packet */ -{ - unsigned char *bufptr, /* Pointer into the data */ - *bufend; /* End of data */ - int length; /* Length of value */ - - - /* - * Initialize the decoding... - */ - - memset(packet, 0, sizeof(snmp_packet_t)); - - bufptr = buffer; - bufend = buffer + len; - - if (asn1_get_type(&bufptr, bufend) != ASN1_SEQUENCE) - packet->error = "Packet does not start with SEQUENCE"; - else if (asn1_get_length(&bufptr, bufend) == 0) - packet->error = "SEQUENCE uses indefinite length"; - else if (asn1_get_type(&bufptr, bufend) != ASN1_INTEGER) - packet->error = "No version number"; - else if ((length = asn1_get_length(&bufptr, bufend)) == 0) - packet->error = "Version uses indefinite length"; - else if ((packet->version = asn1_get_integer(&bufptr, bufend, length)) - != SNMP_VERSION_1) - packet->error = "Bad SNMP version number"; - else if (asn1_get_type(&bufptr, bufend) != ASN1_OCTET_STRING) - packet->error = "No community name"; - else if ((length = asn1_get_length(&bufptr, bufend)) == 0) - packet->error = "Community name uses indefinite length"; - else - { - asn1_get_string(&bufptr, bufend, length, packet->community, - sizeof(packet->community)); - - if ((packet->request_type = asn1_get_type(&bufptr, bufend)) - != ASN1_GET_RESPONSE) - packet->error = "Packet does not contain a Get-Response-PDU"; - else if (asn1_get_length(&bufptr, bufend) == 0) - packet->error = "Get-Response-PDU uses indefinite length"; - else if (asn1_get_type(&bufptr, bufend) != ASN1_INTEGER) - packet->error = "No request-id"; - else if ((length = asn1_get_length(&bufptr, bufend)) == 0) - packet->error = "request-id uses indefinite length"; - else - { - packet->request_id = asn1_get_integer(&bufptr, bufend, length); - - if (asn1_get_type(&bufptr, bufend) != ASN1_INTEGER) - packet->error = "No error-status"; - else if ((length = asn1_get_length(&bufptr, bufend)) == 0) - packet->error = "error-status uses indefinite length"; - else - { - packet->error_status = asn1_get_integer(&bufptr, bufend, length); - - if (asn1_get_type(&bufptr, bufend) != ASN1_INTEGER) - packet->error = "No error-index"; - else if ((length = asn1_get_length(&bufptr, bufend)) == 0) - packet->error = "error-index uses indefinite length"; - else - { - packet->error_index = asn1_get_integer(&bufptr, bufend, length); - - if (asn1_get_type(&bufptr, bufend) != ASN1_SEQUENCE) - packet->error = "No variable-bindings SEQUENCE"; - else if (asn1_get_length(&bufptr, bufend) == 0) - packet->error = "variable-bindings uses indefinite length"; - else if (asn1_get_type(&bufptr, bufend) != ASN1_SEQUENCE) - packet->error = "No VarBind SEQUENCE"; - else if (asn1_get_length(&bufptr, bufend) == 0) - packet->error = "VarBind uses indefinite length"; - else if (asn1_get_type(&bufptr, bufend) != ASN1_OID) - packet->error = "No name OID"; - else if ((length = asn1_get_length(&bufptr, bufend)) == 0) - packet->error = "Name OID uses indefinite length"; - else - { - asn1_get_oid(&bufptr, bufend, length, packet->object_name, - SNMP_MAX_OID); - - packet->object_type = asn1_get_type(&bufptr, bufend); - - if ((length = asn1_get_length(&bufptr, bufend)) == 0 && - packet->object_type != ASN1_NULL_VALUE && - packet->object_type != ASN1_OCTET_STRING) - packet->error = "Value uses indefinite length"; - else - { - switch (packet->object_type) - { - case ASN1_BOOLEAN : - packet->object_value.boolean = - asn1_get_integer(&bufptr, bufend, length); - break; - - case ASN1_INTEGER : - packet->object_value.integer = - asn1_get_integer(&bufptr, bufend, length); - break; - - case ASN1_NULL_VALUE : - break; - - case ASN1_OCTET_STRING : - asn1_get_string(&bufptr, bufend, length, - packet->object_value.string, - SNMP_MAX_STRING); - break; - - case ASN1_OID : - asn1_get_oid(&bufptr, bufend, length, - packet->object_value.oid, SNMP_MAX_OID); - break; - - default : - packet->error = "Unsupported value type"; - break; - } - } - } - } - } - } - } - - return (packet->error ? -1 : 0); -} - - -/* - * 'asn1_debug()' - Decode an ASN1-encoded message. - */ - -static void -asn1_debug(unsigned char *buffer, /* I - Buffer */ - size_t len, /* I - Length of buffer */ - int indent) /* I - Indentation */ -{ - int i; /* Looping var */ - unsigned char *bufend; /* End of buffer */ - int integer; /* Number value */ - int oid[SNMP_MAX_OID]; /* OID value */ - char string[SNMP_MAX_STRING];/* String value */ - unsigned char value_type; /* Type of value */ - int value_length; /* Length of value */ - - - bufend = buffer + len; - - while (buffer < bufend) - { - /* - * Get value type... - */ - - value_type = asn1_get_type(&buffer, bufend); - value_length = asn1_get_length(&buffer, bufend); - - switch (value_type) - { - case ASN1_BOOLEAN : - integer = asn1_get_integer(&buffer, bufend, value_length); - - fprintf(stderr, "DEBUG: %*sBOOLEAN %d bytes %d\n", indent, "", - value_length, integer); - break; - - case ASN1_INTEGER : - integer = asn1_get_integer(&buffer, bufend, value_length); - - fprintf(stderr, "DEBUG: %*sINTEGER %d bytes %d\n", indent, "", - value_length, integer); - break; - - case ASN1_OCTET_STRING : - fprintf(stderr, "DEBUG: %*sOCTET STRING %d bytes \"%s\"\n", indent, "", - value_length, asn1_get_string(&buffer, bufend, - value_length, string, - sizeof(string))); - break; - - case ASN1_NULL_VALUE : - fprintf(stderr, "DEBUG: %*sNULL VALUE %d bytes\n", indent, "", - value_length); - - buffer += value_length; - break; - - case ASN1_OID : - asn1_get_oid(&buffer, bufend, value_length, oid, SNMP_MAX_OID); - - fprintf(stderr, "DEBUG: %*sOID %d bytes ", indent, "", - value_length); - for (i = 0; oid[i]; i ++) - fprintf(stderr, ".%d", oid[i]); - putc('\n', stderr); - break; - - case ASN1_SEQUENCE : - fprintf(stderr, "DEBUG: %*sSEQUENCE %d bytes\n", indent, "", - value_length); - asn1_debug(buffer, value_length, indent + 4); - - buffer += value_length; - break; - - case ASN1_GET_REQUEST : - fprintf(stderr, "DEBUG: %*sGet-Request-PDU %d bytes\n", indent, "", - value_length); - asn1_debug(buffer, value_length, indent + 4); - - buffer += value_length; - break; - - case ASN1_GET_RESPONSE : - fprintf(stderr, "DEBUG: %*sGet-Response-PDU %d bytes\n", indent, "", - value_length); - asn1_debug(buffer, value_length, indent + 4); - - buffer += value_length; - break; - - default : - fprintf(stderr, "DEBUG: %*sUNKNOWN(%x) %d bytes\n", indent, "", - value_type, value_length); - - buffer += value_length; - break; - } - } -} - - -/* - * 'asn1_encode_snmp()' - Encode a SNMP packet. - */ - -static int /* O - Length on success, -1 on error */ -asn1_encode_snmp(unsigned char *buffer, /* I - Buffer */ - size_t bufsize, /* I - Size of buffer */ - snmp_packet_t *packet) /* I - SNMP packet */ -{ - unsigned char *bufptr; /* Pointer into buffer */ - int total, /* Total length */ - msglen, /* Length of entire message */ - commlen, /* Length of community string */ - reqlen, /* Length of request */ - listlen, /* Length of variable list */ - varlen, /* Length of variable */ - namelen, /* Length of object name OID */ - valuelen; /* Length of object value */ - - - /* - * Get the lengths of the community string, OID, and message... - */ - - namelen = asn1_size_oid(packet->object_name); - - switch (packet->object_type) - { - case ASN1_NULL_VALUE : - valuelen = 0; - break; - - case ASN1_BOOLEAN : - valuelen = asn1_size_integer(packet->object_value.boolean); - break; - - case ASN1_INTEGER : - valuelen = asn1_size_integer(packet->object_value.integer); - break; - - case ASN1_OCTET_STRING : - valuelen = strlen(packet->object_value.string); - break; - - case ASN1_OID : - valuelen = asn1_size_oid(packet->object_value.oid); - break; - - default : - packet->error = "Unknown object type"; - return (-1); - } - - varlen = 1 + asn1_size_length(namelen) + namelen + - 1 + asn1_size_length(valuelen) + valuelen; - listlen = 1 + asn1_size_length(varlen) + varlen; - reqlen = 2 + asn1_size_integer(packet->request_id) + - 2 + asn1_size_integer(packet->error_status) + - 2 + asn1_size_integer(packet->error_index) + - 1 + asn1_size_length(listlen) + listlen; - commlen = strlen(packet->community); - msglen = 2 + asn1_size_integer(packet->version) + - 1 + asn1_size_length(commlen) + commlen + - 1 + asn1_size_length(reqlen) + reqlen; - total = 1 + asn1_size_length(msglen) + msglen; - - if (total > bufsize) - { - packet->error = "Message too large for buffer"; - return (-1); - } - - /* - * Then format the message... - */ - - bufptr = buffer; - - *bufptr++ = ASN1_SEQUENCE; /* SNMPv1 message header */ - asn1_set_length(&bufptr, msglen); - - asn1_set_integer(&bufptr, packet->version); - /* version */ - - *bufptr++ = ASN1_OCTET_STRING; /* community */ - asn1_set_length(&bufptr, commlen); - memcpy(bufptr, packet->community, commlen); - bufptr += commlen; - - *bufptr++ = packet->request_type; /* Get-Request-PDU */ - asn1_set_length(&bufptr, reqlen); - - asn1_set_integer(&bufptr, packet->request_id); - - asn1_set_integer(&bufptr, packet->error_status); - - asn1_set_integer(&bufptr, packet->error_index); - - *bufptr++ = ASN1_SEQUENCE; /* variable-bindings */ - asn1_set_length(&bufptr, listlen); - - *bufptr++ = ASN1_SEQUENCE; /* variable */ - asn1_set_length(&bufptr, varlen); - - asn1_set_oid(&bufptr, packet->object_name); - /* ObjectName */ - - switch (packet->object_type) - { - case ASN1_NULL_VALUE : - *bufptr++ = ASN1_NULL_VALUE; /* ObjectValue */ - *bufptr++ = 0; /* Length */ - break; - - case ASN1_BOOLEAN : - asn1_set_integer(&bufptr, packet->object_value.boolean); - break; - - case ASN1_INTEGER : - asn1_set_integer(&bufptr, packet->object_value.integer); - break; - - case ASN1_OCTET_STRING : - *bufptr++ = ASN1_OCTET_STRING; - asn1_set_length(&bufptr, valuelen); - memcpy(bufptr, packet->object_value.string, valuelen); - bufptr += valuelen; - break; - - case ASN1_OID : - asn1_set_oid(&bufptr, packet->object_value.oid); - break; - } - - return (bufptr - buffer); -} - - -/* - * 'asn1_get_integer()' - Get an integer value. - */ - -static int /* O - Integer value */ -asn1_get_integer( - unsigned char **buffer, /* IO - Pointer in buffer */ - unsigned char *bufend, /* I - End of buffer */ - int length) /* I - Length of value */ -{ - int value; /* Integer value */ - - - for (value = 0; - length > 0 && *buffer < bufend; - length --, (*buffer) ++) - value = (value << 8) | **buffer; - - return (value); -} - - -/* - * 'asn1_get_length()' - Get a value length. - */ - -static int /* O - Length */ -asn1_get_length(unsigned char **buffer, /* IO - Pointer in buffer */ - unsigned char *bufend) /* I - End of buffer */ -{ - int length; /* Length */ - - - length = **buffer; - (*buffer) ++; - - if (length & 128) - length = asn1_get_integer(buffer, bufend, length & 127); - - return (length); -} - - -/* - * 'asn1_get_oid()' - Get an OID value. - */ - -static int /* O - Last OID number */ -asn1_get_oid( - unsigned char **buffer, /* IO - Pointer in buffer */ - unsigned char *bufend, /* I - End of buffer */ - int length, /* I - Length of value */ - int *oid, /* I - OID buffer */ - int oidsize) /* I - Size of OID buffer */ -{ - unsigned char *valend; /* End of value */ - int *oidend; /* End of OID buffer */ - int number; /* OID number */ - - - valend = *buffer + length; - oidend = oid + oidsize - 1; - - if (valend > bufend) - valend = bufend; - - number = asn1_get_packed(buffer, bufend); - - if (number < 80) - { - *oid++ = number / 40; - number = number % 40; - *oid++ = number; - } - else - { - *oid++ = 2; - number -= 80; - *oid++ = number; - } - - while (*buffer < valend) - { - number = asn1_get_packed(buffer, bufend); - - if (oid < oidend) - *oid++ = number; - } - - *oid = 0; - - return (number); -} - - -/* - * 'asn1_get_packed()' - Get a packed integer value. - */ - -static int /* O - Value */ -asn1_get_packed( - unsigned char **buffer, /* IO - Pointer in buffer */ - unsigned char *bufend) /* I - End of buffer */ -{ - int value; /* Value */ - - - value = 0; - - while ((**buffer & 128) && *buffer < bufend) - { - value = (value << 7) | (**buffer & 127); - (*buffer) ++; - } - - if (*buffer < bufend) - { - value = (value << 7) | **buffer; - (*buffer) ++; - } - - return (value); -} - - -/* - * 'asn1_get_string()' - Get a string value. - */ - -static char * /* O - String */ -asn1_get_string( - unsigned char **buffer, /* IO - Pointer in buffer */ - unsigned char *bufend, /* I - End of buffer */ - int length, /* I - Value length */ - char *string, /* I - String buffer */ - int strsize) /* I - String buffer size */ -{ - if (length < 0) - { - /* - * Disallow negative lengths! - */ - - fprintf(stderr, "ERROR: Bad ASN1 string length %d!\n", length); - *string = '\0'; - } - else if (length < strsize) - { - /* - * String is smaller than the buffer... - */ - - if (length > 0) - memcpy(string, *buffer, length); - - string[length] = '\0'; - } - else - { - /* - * String is larger than the buffer... - */ - - memcpy(string, buffer, strsize - 1); - string[strsize - 1] = '\0'; - } - - if (length > 0) - (*buffer) += length; - - return (string); -} - - -/* - * 'asn1_get_type()' - Get a value type. - */ - -static int /* O - Type */ -asn1_get_type(unsigned char **buffer, /* IO - Pointer in buffer */ - unsigned char *bufend) /* I - End of buffer */ -{ - int type; /* Type */ - - - type = **buffer; - (*buffer) ++; - - if ((type & 31) == 31) - type = asn1_get_packed(buffer, bufend); - - return (type); -} - - -/* - * 'asn1_set_integer()' - Set an integer value. - */ - -static void -asn1_set_integer(unsigned char **buffer,/* IO - Pointer in buffer */ - int integer) /* I - Integer value */ -{ - **buffer = ASN1_INTEGER; - (*buffer) ++; - - if (integer > 0x7fffff || integer < -0x800000) - { - **buffer = 4; - (*buffer) ++; - **buffer = integer >> 24; - (*buffer) ++; - **buffer = integer >> 16; - (*buffer) ++; - **buffer = integer >> 8; - (*buffer) ++; - **buffer = integer; - (*buffer) ++; - } - else if (integer > 0x7fff || integer < -0x8000) - { - **buffer = 3; - (*buffer) ++; - **buffer = integer >> 16; - (*buffer) ++; - **buffer = integer >> 8; - (*buffer) ++; - **buffer = integer; - (*buffer) ++; - } - else if (integer > 0x7f || integer < -0x80) - { - **buffer = 2; - (*buffer) ++; - **buffer = integer >> 8; - (*buffer) ++; - **buffer = integer; - (*buffer) ++; - } - else - { - **buffer = 1; - (*buffer) ++; - **buffer = integer; - (*buffer) ++; - } -} - - -/* - * 'asn1_set_length()' - Set a value length. - */ - -static void -asn1_set_length(unsigned char **buffer, /* IO - Pointer in buffer */ - int length) /* I - Length value */ -{ - if (length > 255) - { - **buffer = 0x82; /* 2-byte length */ - (*buffer) ++; - **buffer = length >> 8; - (*buffer) ++; - **buffer = length; - (*buffer) ++; - } - else if (length > 127) - { - **buffer = 0x81; /* 1-byte length */ - (*buffer) ++; - **buffer = length; - (*buffer) ++; - } - else - { - **buffer = length; /* Length */ - (*buffer) ++; - } -} - - -/* - * 'asn1_set_oid()' - Set an OID value. - */ - -static void -asn1_set_oid(unsigned char **buffer, /* IO - Pointer in buffer */ - const int *oid) /* I - OID value */ -{ - **buffer = ASN1_OID; - (*buffer) ++; - - asn1_set_length(buffer, asn1_size_oid(oid)); - - asn1_set_packed(buffer, oid[0] * 40 + oid[1]); - - for (oid += 2; *oid; oid ++) - asn1_set_packed(buffer, *oid); -} - - -/* - * 'asn1_set_packed()' - Set a packed integer value. - */ - -static void -asn1_set_packed(unsigned char **buffer, /* IO - Pointer in buffer */ - int integer) /* I - Integer value */ -{ - if (integer > 0xfffffff) - { - **buffer = (integer >> 28) & 0x7f; - (*buffer) ++; - } - - if (integer > 0x1fffff) - { - **buffer = (integer >> 21) & 0x7f; - (*buffer) ++; - } - - if (integer > 0x3fff) - { - **buffer = (integer >> 14) & 0x7f; - (*buffer) ++; - } - - if (integer > 0x7f) - { - **buffer = (integer >> 7) & 0x7f; - (*buffer) ++; - } - - **buffer = integer & 0x7f; - (*buffer) ++; -} - -/* - * 'asn1_size_integer()' - Figure out the number of bytes needed for an - * integer value. - */ - -static int /* O - Size in bytes */ -asn1_size_integer(int integer) /* I - Integer value */ -{ - if (integer > 0x7fffff || integer < -0x800000) - return (4); - else if (integer > 0x7fff || integer < -0x8000) - return (3); - else if (integer > 0x7f || integer < -0x80) - return (2); - else - return (1); -} - - -/* - * 'asn1_size_length()' - Figure out the number of bytes needed for a - * length value. - */ - -static int /* O - Size in bytes */ -asn1_size_length(int length) /* I - Length value */ -{ - if (length > 0xff) - return (3); - else if (length > 0x7f) - return (2); - else - return (1); -} - - -/* - * 'asn1_size_oid()' - Figure out the numebr of bytes needed for an - * OID value. - */ - -static int /* O - Size in bytes */ -asn1_size_oid(const int *oid) /* I - OID value */ -{ - int length; /* Length of value */ - - - for (length = asn1_size_packed(oid[0] * 40 + oid[1]), oid += 2; *oid; oid ++) - length += asn1_size_packed(*oid); - - return (length); -} - - -/* - * 'asn1_size_packed()' - Figure out the number of bytes needed for a - * packed integer value. - */ - -static int /* O - Size in bytes */ -asn1_size_packed(int integer) /* I - Integer value */ -{ - if (integer > 0xfffffff) - return (5); - else if (integer > 0x1fffff) - return (4); - else if (integer > 0x3fff) - return (3); - else if (integer > 0x7f) - return (2); - else - return (1); -} - - -/* * 'compare_cache()' - Compare two cache entries. */ @@ -1549,35 +650,6 @@ get_interface_addresses( /* - * 'hex_debug()' - Output hex debugging data... - */ - -static void -hex_debug(unsigned char *buffer, /* I - Buffer */ - size_t len) /* I - Number of bytes */ -{ - int col; /* Current column */ - - - fputs("DEBUG: Hex dump of packet:\n", stderr); - - for (col = 0; len > 0; col ++, buffer ++, len --) - { - if ((col & 15) == 0) - fprintf(stderr, "DEBUG: %04X ", col); - - fprintf(stderr, " %02X", *buffer); - - if ((col & 15) == 15) - putc('\n', stderr); - } - - if (col & 15) - putc('\n', stderr); -} - - -/* * 'list_device()' - List a device we found... */ @@ -1594,49 +666,6 @@ list_device(snmp_cache_t *cache) /* I - Cached device */ /* - * 'open_snmp_socket()' - Open the SNMP broadcast socket. - */ - -static int /* O - SNMP socket file descriptor */ -open_snmp_socket(void) -{ - int fd; /* SNMP socket file descriptor */ - int val; /* Socket option value */ - - - /* - * Create the SNMP socket... - */ - - if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) - { - fprintf(stderr, "ERROR: Unable to create SNMP socket - %s\n", - strerror(errno)); - - return (-1); - } - - /* - * Set the "broadcast" flag... - */ - - val = 1; - - if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &val, sizeof(val))) - { - fprintf(stderr, "ERROR: Unable to set broadcast mode - %s\n", - strerror(errno)); - - close(fd); - - return (-1); - } - - return (fd); -} - - -/* * 'password_cb()' - Handle authentication requests. * * All we do right now is return NULL, indicating that no authentication @@ -1862,12 +891,8 @@ read_snmp_conf(const char *address) /* I - Single address to probe */ static void read_snmp_response(int fd) /* I - SNMP socket file descriptor */ { - unsigned char buffer[SNMP_MAX_PACKET];/* Data packet */ - int bytes; /* Number of bytes received */ - http_addr_t addr; /* Source address */ - socklen_t addrlen; /* Source address length */ char addrname[256]; /* Source address name */ - snmp_packet_t packet; /* Decoded packet */ + cups_snmp_t packet; /* Decoded packet */ snmp_cache_t key, /* Search key */ *device; /* Matching device */ @@ -1876,10 +901,7 @@ read_snmp_response(int fd) /* I - SNMP socket file descriptor */ * Read the response data... */ - addrlen = sizeof(addr); - - if ((bytes = recvfrom(fd, buffer, sizeof(buffer), 0, (void *)&addr, - &addrlen)) < 0) + if (!cupsSNMPRead(fd, &packet, -1)) { fprintf(stderr, "ERROR: Unable to read data from socket: %s\n", strerror(errno)); @@ -1887,24 +909,20 @@ read_snmp_response(int fd) /* I - SNMP socket file descriptor */ } if (HostNameLookups) - httpAddrLookup(&addr, addrname, sizeof(addrname)); + httpAddrLookup(&(packet.address), addrname, sizeof(addrname)); else - httpAddrString(&addr, addrname, sizeof(addrname)); + httpAddrString(&(packet.address), addrname, sizeof(addrname)); - debug_printf("DEBUG: %.3f Received %d bytes from %s...\n", run_time(), - bytes, addrname); + debug_printf("DEBUG: %.3f Received data from %s...\n", run_time(), addrname); /* * Look for the response status code in the SNMP message header... */ - if (asn1_decode_snmp(buffer, bytes, &packet)) + if (packet.error) { - fprintf(stderr, "ERROR: Bad SNMP packet from %s: %s\n", - addrname, packet.error); - - asn1_debug(buffer, bytes, 0); - hex_debug(buffer, bytes); + fprintf(stderr, "ERROR: Bad SNMP packet from %s: %s\n", addrname, + packet.error); return; } @@ -1913,12 +931,6 @@ read_snmp_response(int fd) /* I - SNMP socket file descriptor */ debug_printf("DEBUG: request-id=%d\n", packet.request_id); debug_printf("DEBUG: error-status=%d\n", packet.error_status); - if (DebugLevel > 1) - asn1_debug(buffer, bytes, 0); - - if (DebugLevel > 2) - hex_debug(buffer, bytes); - if (packet.error_status) return; @@ -1950,13 +962,13 @@ read_snmp_response(int fd) /* I - SNMP socket file descriptor */ * Add the device and request the device description... */ - add_cache(&addr, addrname, NULL, NULL, NULL); + add_cache(&(packet.address), addrname, NULL, NULL, NULL); - send_snmp_query(fd, &addr, SNMP_VERSION_1, packet.community, - DeviceDescRequest, DeviceDescOID); + cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1, packet.community, + CUPS_ASN1_GET_REQUEST, DeviceDescRequest, DeviceDescOID); } else if (packet.request_id == DeviceDescRequest && - packet.object_type == ASN1_OCTET_STRING) + packet.object_type == CUPS_ASN1_OCTET_STRING) { /* * Update an existing cache entry... @@ -2085,8 +1097,8 @@ scan_devices(int fd) /* I - SNMP socket */ community, address); for (addr = addrs; addr; addr = addr->next) - send_snmp_query(fd, &(addr->addr), SNMP_VERSION_1, community, - DeviceTypeRequest, DeviceTypeOID); + cupsSNMPWrite(fd, &(addr->addr), CUPS_SNMP_VERSION_1, community, + CUPS_ASN1_GET_REQUEST, DeviceTypeRequest, DeviceTypeOID); } httpAddrFreeList(addrs); @@ -2137,70 +1149,6 @@ scan_devices(int fd) /* I - SNMP socket */ /* - * 'send_snmp_query()' - Send an SNMP query packet. - */ - -static void -send_snmp_query( - int fd, /* I - SNMP socket */ - http_addr_t *addr, /* I - Address to send to */ - int version, /* I - SNMP version */ - const char *community, /* I - Community name */ - const unsigned request_id, /* I - Request ID */ - const int *oid) /* I - OID */ -{ - int i; /* Looping var */ - snmp_packet_t packet; /* SNMP message packet */ - unsigned char buffer[SNMP_MAX_PACKET];/* SNMP message buffer */ - int bytes; /* Size of message */ - char addrname[32]; /* Address name */ - - - /* - * Create the SNMP message... - */ - - memset(&packet, 0, sizeof(packet)); - - packet.version = version; - packet.request_type = ASN1_GET_REQUEST; - packet.request_id = request_id; - packet.object_type = ASN1_NULL_VALUE; - - strlcpy(packet.community, community, sizeof(packet.community)); - - for (i = 0; oid[i]; i ++) - packet.object_name[i] = oid[i]; - - bytes = asn1_encode_snmp(buffer, sizeof(buffer), &packet); - - if (bytes < 0) - { - fprintf(stderr, "ERROR: Unable to send SNMP query: %s\n", - packet.error); - return; - } - - /* - * Send the message... - */ - - debug_printf("DEBUG: %.3f Sending %d bytes to %s...\n", run_time(), - bytes, httpAddrString(addr, addrname, sizeof(addrname))); - if (DebugLevel > 1) - asn1_debug(buffer, bytes, 0); - if (DebugLevel > 2) - hex_debug(buffer, bytes); - - addr->ipv4.sin_port = htons(SNMP_PORT); - - if (sendto(fd, buffer, bytes, 0, (void *)addr, sizeof(addr->ipv4)) < bytes) - fprintf(stderr, "ERROR: Unable to send %d bytes to %s: %s\n", - bytes, addrname, strerror(errno)); -} - - -/* * 'try_connect()' - Try connecting on a port... */ diff --git a/backend/usb-unix.c b/backend/usb-unix.c index 9d5273b64..104ea7d43 100644 --- a/backend/usb-unix.c +++ b/backend/usb-unix.c @@ -516,7 +516,7 @@ open_device(const char *uri, /* I - Device URI */ } #else { - if (use_bc) + if (*use_bc) fd = open(uri + 4, O_RDWR | O_EXCL); else fd = -1; diff --git a/cgi-bin/admin.c b/cgi-bin/admin.c index 86ccb9c15..0a981d231 100644 --- a/cgi-bin/admin.c +++ b/cgi-bin/admin.c @@ -3,7 +3,7 @@ * * Administration CGI for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1997-2007 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -1684,14 +1684,15 @@ do_config_server(http_t *http) /* I - HTTP connection */ * Allocate memory and load the file into a string buffer... */ - buffer = calloc(1, info.st_size + 1); + if ((buffer = calloc(1, info.st_size + 1)) != NULL) + { + cupsFileRead(cupsd, buffer, info.st_size); + cgiSetVariable("CUPSDCONF", buffer); + free(buffer); + } - cupsFileRead(cupsd, buffer, info.st_size); cupsFileClose(cupsd); - cgiSetVariable("CUPSDCONF", buffer); - free(buffer); - /* * Then get the default cupsd.conf file and put that into a string as * well... @@ -1702,37 +1703,39 @@ do_config_server(http_t *http) /* I - HTTP connection */ if (!stat(filename, &info) && info.st_size < (1024 * 1024) && (cupsd = cupsFileOpen(filename, "r")) != NULL) { - buffer = calloc(1, 2 * info.st_size + 1); - bufend = buffer + 2 * info.st_size - 1; - - for (bufptr = buffer; - bufptr < bufend && (ch = cupsFileGetChar(cupsd)) != EOF;) + if ((buffer = calloc(1, 2 * info.st_size + 1)) != NULL) { - if (ch == '\\' || ch == '\"') - { - *bufptr++ = '\\'; - *bufptr++ = ch; - } - else if (ch == '\n') - { - *bufptr++ = '\\'; - *bufptr++ = 'n'; - } - else if (ch == '\t') + bufend = buffer + 2 * info.st_size - 1; + + for (bufptr = buffer; + bufptr < bufend && (ch = cupsFileGetChar(cupsd)) != EOF;) { - *bufptr++ = '\\'; - *bufptr++ = 't'; + if (ch == '\\' || ch == '\"') + { + *bufptr++ = '\\'; + *bufptr++ = ch; + } + else if (ch == '\n') + { + *bufptr++ = '\\'; + *bufptr++ = 'n'; + } + else if (ch == '\t') + { + *bufptr++ = '\\'; + *bufptr++ = 't'; + } + else if (ch >= ' ') + *bufptr++ = ch; } - else if (ch >= ' ') - *bufptr++ = ch; - } - *bufptr = '\0'; + *bufptr = '\0'; - cupsFileClose(cupsd); + cgiSetVariable("CUPSDCONF_DEFAULT", buffer); + free(buffer); + } - cgiSetVariable("CUPSDCONF_DEFAULT", buffer); - free(buffer); + cupsFileClose(cupsd); } /* @@ -3088,7 +3091,7 @@ do_set_options(http_t *http, /* I - HTTP connection */ * Binary protocol support... */ - if (ppd->protocols && strstr(ppd->protocols, "BCP")) + if (ppd && ppd->protocols && strstr(ppd->protocols, "BCP")) { protocol = ppdFindAttr(ppd, "cupsProtocol", NULL); diff --git a/cgi-bin/ipp-var.c b/cgi-bin/ipp-var.c index d949e41f1..098d08630 100644 --- a/cgi-bin/ipp-var.c +++ b/cgi-bin/ipp-var.c @@ -3,7 +3,7 @@ * * CGI <-> IPP variable routines for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1997-2007 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -158,6 +158,8 @@ cgiGetAttributes(ipp_t *request, /* I - IPP request */ for (i = 0; i < num_attrs; i ++) free(attrs[i]); } + + fclose(in); } diff --git a/cgi-bin/search.c b/cgi-bin/search.c index 9765064f0..4ec4de397 100644 --- a/cgi-bin/search.c +++ b/cgi-bin/search.c @@ -3,7 +3,7 @@ * * Search routines for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1997-2006 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -53,7 +53,8 @@ cgiCompileSearch(const char *query) /* I - Query string */ * Allocate a regular expression storage structure... */ - re = (regex_t *)calloc(1, sizeof(regex_t)); + if ((re = (regex_t *)calloc(1, sizeof(regex_t))) == NULL) + return (NULL); /* * Allocate a buffer to hold the regular expression string, starting @@ -65,7 +66,11 @@ cgiCompileSearch(const char *query) /* I - Query string */ if (slen < 1024) slen = 1024; - s = (char *)malloc(slen); + if ((s = (char *)malloc(slen)) == NULL) + { + free(re); + return (NULL); + } /* * Copy the query string to the regular expression, handling basic @@ -227,7 +232,13 @@ cgiCompileSearch(const char *query) /* I - Query string */ char *lword2; /* New "last word" */ - lword2 = strdup(sword); + if ((lword2 = strdup(sword)) == NULL) + { + free(lword); + free(s); + free(re); + return (NULL); + } strcpy(sptr, ".*|.*"); sptr += 5; diff --git a/cgi-bin/template.c b/cgi-bin/template.c index 0d301e11a..661f6395b 100644 --- a/cgi-bin/template.c +++ b/cgi-bin/template.c @@ -3,7 +3,7 @@ * * CGI template function. * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1997-2006 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -55,6 +55,13 @@ cgiCopyTemplateFile(FILE *out, /* I - Output file */ tmpl ? tmpl : "(null)"); /* + * Range check input... + */ + + if (!tmpl || !out) + return; + + /* * Open the template file... */ diff --git a/cgi-bin/var.c b/cgi-bin/var.c index a142e9ccb..3ae98ca6c 100644 --- a/cgi-bin/var.c +++ b/cgi-bin/var.c @@ -3,7 +3,7 @@ * * CGI form variable and array functions. * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1997-2005 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -322,9 +322,15 @@ cgiSetArray(const char *name, /* I - Name of variable */ { if (element >= var->avalues) { + const char **temp; /* Temporary pointer */ + + temp = (const char **)realloc((void *)(var->values), + sizeof(char *) * (element + 16)); + if (!temp) + return; + var->avalues = element + 16; - var->values = (const char **)realloc((void *)(var->values), - sizeof(char *) * var->avalues); + var->values = temp; } if (element >= var->nvalues) @@ -362,9 +368,15 @@ cgiSetSize(const char *name, /* I - Name of variable */ if (size >= var->avalues) { + const char **temp; /* Temporary pointer */ + + temp = (const char **)realloc((void *)(var->values), + sizeof(char *) * (size + 16)); + if (!temp) + return; + var->avalues = size + 16; - var->values = (const char **)realloc((void *)(var->values), - sizeof(char *) * var->avalues); + var->values = temp; } if (size > var->nvalues) @@ -426,7 +438,7 @@ cgi_add_variable(const char *name, /* I - Variable name */ int element, /* I - Array element number */ const char *value) /* I - Variable value */ { - _cgi_var_t *var; /* New variable */ + _cgi_var_t *var; /* New variable */ if (name == NULL || value == NULL || element < 0 || element > 100000) @@ -438,19 +450,29 @@ cgi_add_variable(const char *name, /* I - Variable name */ if (form_count >= form_alloc) { + _cgi_var_t *temp_vars; /* Temporary form pointer */ + + if (form_alloc == 0) - form_vars = malloc(sizeof(_cgi_var_t) * 16); + temp_vars = malloc(sizeof(_cgi_var_t) * 16); else - form_vars = realloc(form_vars, (form_alloc + 16) * sizeof(_cgi_var_t)); + temp_vars = realloc(form_vars, (form_alloc + 16) * sizeof(_cgi_var_t)); + + if (!temp_vars) + return; + form_vars = temp_vars; form_alloc += 16; } - var = form_vars + form_count; + var = form_vars + form_count; + + if ((var->values = calloc(element + 1, sizeof(char *))) == NULL) + return; + 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 ++; diff --git a/config-scripts/cups-pdf.m4 b/config-scripts/cups-pdf.m4 index deac73ed8..6e4ed8fb0 100644 --- a/config-scripts/cups-pdf.m4 +++ b/config-scripts/cups-pdf.m4 @@ -18,12 +18,20 @@ AC_ARG_ENABLE(pdftops, [ --enable-pdftops build pdftops filter, default= PDFTOPS="" if test "x$enable_pdftops" != xno; then - AC_MSG_CHECKING(whether to build pdftops filter) - if test "x$enable_pdftops" = xyes -o $uname != Darwin; then - PDFTOPS="pdftops" - AC_MSG_RESULT(yes) - else - AC_MSG_RESULT(no) + AC_PATH_PROG(CUPS_PDFTOPS, pdftops) + AC_DEFINE_UNQUOTED(CUPS_PDFTOPS, "$CUPS_PDFTOPS") + + if test "x$CUPS_PDFTOPS" != x; then + AC_MSG_CHECKING(whether to build pdftops filter) + if test x$enable_pdftops = xyes -o $uname != Darwin; then + PDFTOPS="pdftops" + AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) + fi + elif test x$enable_pdftops = xyes; then + AC_MSG_ERROR(Unable to find pdftops program!) + exit 1 fi fi diff --git a/config.h.in b/config.h.in index 65262444e..9bcf7181f 100644 --- a/config.h.in +++ b/config.h.in @@ -431,6 +431,13 @@ /* + * Location of the poppler/Xpdf pdftops program... + */ + +#define CUPS_PDFTOPS "/usr/bin/pdftops" + + +/* * Do we have Darwin's CoreFoundation and SystemConfiguration frameworks? */ diff --git a/cups/Dependencies b/cups/Dependencies index 167b8b5ae..3e54079d5 100644 --- a/cups/Dependencies +++ b/cups/Dependencies @@ -1,324 +1,336 @@ -# DO NOT DELETE THIS LINE -- make depend depends on it. -adminutil.o: adminutil.c adminutil.h cups.h ipp.h http.h string.h \ - ../config.h ppd.h array.h file.h language.h globals.h string.h \ - http-private.h md5.h ipp-private.h i18n.h transcode.h debug.h -array.o: array.c array.h string.h ../config.h string.h debug.h -attr.o: attr.c ppd.h array.h file.h debug.h string.h ../config.h string.h -auth.o: auth.c globals.h string.h ../config.h string.h http-private.h \ - http.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h \ - i18n.h transcode.h debug.h -backchannel.o: backchannel.c cups.h ipp.h http.h string.h ../config.h \ - ppd.h array.h file.h language.h -backend.o: backend.c backend.h string.h ../config.h string.h -custom.o: custom.c globals.h string.h ../config.h string.h http-private.h \ - http.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h \ - i18n.h transcode.h debug.h -dest.o: dest.c globals.h string.h ../config.h string.h http-private.h \ - http.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h \ - i18n.h transcode.h -dir.o: dir.c dir.h string.h ../config.h string.h debug.h -emit.o: emit.c ppd.h array.h file.h string.h ../config.h string.h debug.h -encode.o: encode.c cups.h ipp.h http.h string.h ../config.h ppd.h array.h \ - file.h language.h ipp-private.h string.h debug.h -file.o: file.c http-private.h ../config.h http.h string.h md5.h \ - ipp-private.h ipp.h globals.h string.h cups.h ppd.h array.h file.h \ - language.h i18n.h transcode.h debug.h -getifaddrs.o: getifaddrs.c http-private.h ../config.h http.h string.h \ - md5.h ipp-private.h ipp.h -getputfile.o: getputfile.c http-private.h ../config.h http.h string.h \ - md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h \ - string.h debug.h -globals.o: globals.c http-private.h ../config.h http.h string.h md5.h \ - ipp-private.h ipp.h globals.h string.h cups.h ppd.h array.h file.h \ - language.h i18n.h transcode.h debug.h -http.o: http.c http-private.h ../config.h http.h string.h md5.h \ - ipp-private.h ipp.h globals.h string.h cups.h ppd.h array.h file.h \ - language.h i18n.h transcode.h debug.h -http-addr.o: http-addr.c globals.h string.h ../config.h string.h \ - http-private.h http.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h \ - file.h language.h i18n.h transcode.h debug.h -http-addrlist.o: http-addrlist.c http-private.h ../config.h http.h \ - string.h md5.h ipp-private.h ipp.h globals.h string.h cups.h ppd.h \ - array.h file.h language.h i18n.h transcode.h debug.h -http-support.o: http-support.c debug.h globals.h string.h ../config.h \ - string.h http-private.h http.h md5.h ipp-private.h ipp.h cups.h ppd.h \ - array.h file.h language.h i18n.h transcode.h -ipp.o: ipp.c http-private.h ../config.h http.h string.h md5.h \ - ipp-private.h ipp.h globals.h string.h cups.h ppd.h array.h file.h \ - language.h i18n.h transcode.h debug.h -ipp-support.o: ipp-support.c globals.h string.h ../config.h string.h \ - http-private.h http.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h \ - file.h language.h i18n.h transcode.h debug.h -langprintf.o: langprintf.c globals.h string.h ../config.h string.h \ - http-private.h http.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h \ - file.h language.h i18n.h transcode.h -language.o: language.c globals.h string.h ../config.h string.h \ - http-private.h http.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h \ - file.h language.h i18n.h transcode.h debug.h -localize.o: localize.c globals.h string.h ../config.h string.h \ - http-private.h http.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h \ - file.h language.h i18n.h transcode.h debug.h -mark.o: mark.c cups.h ipp.h http.h string.h ../config.h ppd.h array.h \ - file.h language.h string.h debug.h -md5.o: md5.c md5.h string.h ../config.h string.h -md5passwd.o: md5passwd.c http-private.h ../config.h http.h string.h md5.h \ - ipp-private.h ipp.h string.h -notify.o: notify.c globals.h string.h ../config.h string.h http-private.h \ - http.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h \ - i18n.h transcode.h -options.o: options.c cups.h ipp.h http.h string.h ../config.h ppd.h \ - array.h file.h language.h string.h debug.h -page.o: page.c ppd.h array.h file.h string.h ../config.h string.h -ppd.o: ppd.c globals.h string.h ../config.h string.h http-private.h \ - http.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h \ - i18n.h transcode.h debug.h -request.o: request.c globals.h string.h ../config.h string.h \ - http-private.h http.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h \ - file.h language.h i18n.h transcode.h debug.h -sidechannel.o: sidechannel.c sidechannel.h string.h ../config.h string.h -snprintf.o: snprintf.c string.h ../config.h string.h -string.o: string.c array.h debug.h string.h ../config.h string.h -tempfile.o: tempfile.c globals.h string.h ../config.h string.h \ - http-private.h http.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h \ - file.h language.h i18n.h transcode.h debug.h -transcode.o: transcode.c globals.h string.h ../config.h string.h \ - http-private.h http.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h \ - file.h language.h i18n.h transcode.h debug.h -usersys.o: usersys.c http-private.h ../config.h http.h string.h md5.h \ - ipp-private.h ipp.h globals.h string.h cups.h ppd.h array.h file.h \ - language.h i18n.h transcode.h debug.h -util.o: util.c globals.h string.h ../config.h string.h http-private.h \ - http.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h \ - i18n.h transcode.h debug.h -testadmin.o: testadmin.c adminutil.h cups.h ipp.h http.h string.h \ - ../config.h ppd.h array.h file.h language.h string.h -testarray.o: testarray.c ../cups/string.h ../config.h string.h array.h \ - dir.h debug.h -testcups.o: testcups.c cups.h ipp.h http.h string.h ../config.h ppd.h \ - array.h file.h language.h -testfile.o: testfile.c string.h ../config.h string.h file.h debug.h -testhttp.o: testhttp.c http.h string.h ../config.h string.h -testi18n.o: testi18n.c i18n.h transcode.h language.h array.h string.h \ - ../config.h string.h -testipp.o: testipp.c ../cups/string.h ../config.h string.h ipp-private.h \ - ipp.h http.h -testlang.o: testlang.c i18n.h transcode.h language.h array.h string.h \ - ../config.h string.h -testppd.o: testppd.c ../cups/string.h ../config.h string.h ppd.h array.h \ - file.h -# DO NOT DELETE THIS LINE -- make depend depends on it. -adminutil.32.o: adminutil.c adminutil.c adminutil.h cups.h ipp.h http.h string.h \ - ../config.h ppd.h array.h file.h language.h globals.h string.h \ - http-private.h md5.h ipp-private.h i18n.h transcode.h debug.h -array.32.o: array.c array.c array.h string.h ../config.h string.h debug.h -attr.32.o: attr.c attr.c ppd.h array.h file.h debug.h string.h ../config.h string.h -auth.32.o: auth.c auth.c globals.h string.h ../config.h string.h http-private.h \ - http.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h \ - i18n.h transcode.h debug.h -backchannel.32.o: backchannel.c backchannel.c cups.h ipp.h http.h string.h ../config.h \ - ppd.h array.h file.h language.h -backend.32.o: backend.c backend.c backend.h string.h ../config.h string.h -custom.32.o: custom.c custom.c globals.h string.h ../config.h string.h http-private.h \ - http.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h \ - i18n.h transcode.h debug.h -dest.32.o: dest.c dest.c globals.h string.h ../config.h string.h http-private.h \ - http.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h \ - i18n.h transcode.h -dir.32.o: dir.c dir.c dir.h string.h ../config.h string.h debug.h -emit.32.o: emit.c emit.c ppd.h array.h file.h string.h ../config.h string.h debug.h -encode.32.o: encode.c encode.c cups.h ipp.h http.h string.h ../config.h ppd.h array.h \ - file.h language.h ipp-private.h string.h debug.h -file.32.o: file.c file.c http-private.h ../config.h http.h string.h md5.h \ - ipp-private.h ipp.h globals.h string.h cups.h ppd.h array.h file.h \ - language.h i18n.h transcode.h debug.h -getifaddrs.32.o: getifaddrs.c getifaddrs.c http-private.h ../config.h http.h string.h \ - md5.h ipp-private.h ipp.h -getputfile.32.o: getputfile.c getputfile.c http-private.h ../config.h http.h string.h \ - md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h \ - string.h debug.h -globals.32.o: globals.c globals.c http-private.h ../config.h http.h string.h md5.h \ - ipp-private.h ipp.h globals.h string.h cups.h ppd.h array.h file.h \ - language.h i18n.h transcode.h debug.h -http.32.o: http.c http.c http-private.h ../config.h http.h string.h md5.h \ - ipp-private.h ipp.h globals.h string.h cups.h ppd.h array.h file.h \ - language.h i18n.h transcode.h debug.h -http-addr.32.o: http-addr.c http-addr.c globals.h string.h ../config.h string.h \ - http-private.h http.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h \ - file.h language.h i18n.h transcode.h debug.h -http-addrlist.32.o: http-addrlist.c http-addrlist.c http-private.h ../config.h http.h \ - string.h md5.h ipp-private.h ipp.h globals.h string.h cups.h ppd.h \ - array.h file.h language.h i18n.h transcode.h debug.h -http-support.32.o: http-support.c http-support.c debug.h globals.h string.h ../config.h \ - string.h http-private.h http.h md5.h ipp-private.h ipp.h cups.h ppd.h \ - array.h file.h language.h i18n.h transcode.h -ipp.32.o: ipp.c ipp.c http-private.h ../config.h http.h string.h md5.h \ - ipp-private.h ipp.h globals.h string.h cups.h ppd.h array.h file.h \ - language.h i18n.h transcode.h debug.h -ipp-support.32.o: ipp-support.c ipp-support.c globals.h string.h ../config.h string.h \ - http-private.h http.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h \ - file.h language.h i18n.h transcode.h debug.h -langprintf.32.o: langprintf.c langprintf.c globals.h string.h ../config.h string.h \ - http-private.h http.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h \ - file.h language.h i18n.h transcode.h -language.32.o: language.c language.c globals.h string.h ../config.h string.h \ - http-private.h http.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h \ - file.h language.h i18n.h transcode.h debug.h -localize.32.o: localize.c localize.c globals.h string.h ../config.h string.h \ - http-private.h http.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h \ - file.h language.h i18n.h transcode.h debug.h -mark.32.o: mark.c mark.c cups.h ipp.h http.h string.h ../config.h ppd.h array.h \ - file.h language.h string.h debug.h -md5.32.o: md5.c md5.c md5.h string.h ../config.h string.h -md5passwd.32.o: md5passwd.c md5passwd.c http-private.h ../config.h http.h string.h md5.h \ - ipp-private.h ipp.h string.h -notify.32.o: notify.c notify.c globals.h string.h ../config.h string.h http-private.h \ - http.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h \ - i18n.h transcode.h -options.32.o: options.c options.c cups.h ipp.h http.h string.h ../config.h ppd.h \ - array.h file.h language.h string.h debug.h -page.32.o: page.c page.c ppd.h array.h file.h string.h ../config.h string.h -ppd.32.o: ppd.c ppd.c globals.h string.h ../config.h string.h http-private.h \ - http.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h \ - i18n.h transcode.h debug.h -request.32.o: request.c request.c globals.h string.h ../config.h string.h \ - http-private.h http.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h \ - file.h language.h i18n.h transcode.h debug.h -sidechannel.32.o: sidechannel.c sidechannel.c sidechannel.h string.h ../config.h string.h -snprintf.32.o: snprintf.c snprintf.c string.h ../config.h string.h -string.32.o: string.c string.c array.h debug.h string.h ../config.h string.h -tempfile.32.o: tempfile.c tempfile.c globals.h string.h ../config.h string.h \ - http-private.h http.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h \ - file.h language.h i18n.h transcode.h debug.h -transcode.32.o: transcode.c transcode.c globals.h string.h ../config.h string.h \ - http-private.h http.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h \ - file.h language.h i18n.h transcode.h debug.h -usersys.32.o: usersys.c usersys.c http-private.h ../config.h http.h string.h md5.h \ - ipp-private.h ipp.h globals.h string.h cups.h ppd.h array.h file.h \ - language.h i18n.h transcode.h debug.h -util.32.o: util.c util.c globals.h string.h ../config.h string.h http-private.h \ - http.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h \ - i18n.h transcode.h debug.h -testadmin.32.o: testadmin.c testadmin.c adminutil.h cups.h ipp.h http.h string.h \ - ../config.h ppd.h array.h file.h language.h string.h -testarray.32.o: testarray.c testarray.c ../cups/string.h ../config.h string.h array.h \ - dir.h debug.h -testcups.32.o: testcups.c testcups.c cups.h ipp.h http.h string.h ../config.h ppd.h \ - array.h file.h language.h -testfile.32.o: testfile.c testfile.c string.h ../config.h string.h file.h debug.h -testhttp.32.o: testhttp.c testhttp.c http.h string.h ../config.h string.h -testi18n.32.o: testi18n.c testi18n.c i18n.h transcode.h language.h array.h string.h \ - ../config.h string.h -testipp.32.o: testipp.c testipp.c ../cups/string.h ../config.h string.h ipp-private.h \ - ipp.h http.h -testlang.32.o: testlang.c testlang.c i18n.h transcode.h language.h array.h string.h \ - ../config.h string.h -testppd.32.o: testppd.c testppd.c ../cups/string.h ../config.h string.h ppd.h array.h \ - file.h -# DO NOT DELETE THIS LINE -- make depend depends on it. -adminutil.64.o: adminutil.c adminutil.c adminutil.h cups.h ipp.h http.h string.h \ - ../config.h ppd.h array.h file.h language.h globals.h string.h \ - http-private.h md5.h ipp-private.h i18n.h transcode.h debug.h -array.64.o: array.c array.c array.h string.h ../config.h string.h debug.h -attr.64.o: attr.c attr.c ppd.h array.h file.h debug.h string.h ../config.h string.h -auth.64.o: auth.c auth.c globals.h string.h ../config.h string.h http-private.h \ - http.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h \ - i18n.h transcode.h debug.h -backchannel.64.o: backchannel.c backchannel.c cups.h ipp.h http.h string.h ../config.h \ - ppd.h array.h file.h language.h -backend.64.o: backend.c backend.c backend.h string.h ../config.h string.h -custom.64.o: custom.c custom.c globals.h string.h ../config.h string.h http-private.h \ - http.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h \ - i18n.h transcode.h debug.h -dest.64.o: dest.c dest.c globals.h string.h ../config.h string.h http-private.h \ - http.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h \ - i18n.h transcode.h -dir.64.o: dir.c dir.c dir.h string.h ../config.h string.h debug.h -emit.64.o: emit.c emit.c ppd.h array.h file.h string.h ../config.h string.h debug.h -encode.64.o: encode.c encode.c cups.h ipp.h http.h string.h ../config.h ppd.h array.h \ - file.h language.h ipp-private.h string.h debug.h -file.64.o: file.c file.c http-private.h ../config.h http.h string.h md5.h \ - ipp-private.h ipp.h globals.h string.h cups.h ppd.h array.h file.h \ - language.h i18n.h transcode.h debug.h -getifaddrs.64.o: getifaddrs.c getifaddrs.c http-private.h ../config.h http.h string.h \ - md5.h ipp-private.h ipp.h -getputfile.64.o: getputfile.c getputfile.c http-private.h ../config.h http.h string.h \ - md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h \ - string.h debug.h -globals.64.o: globals.c globals.c http-private.h ../config.h http.h string.h md5.h \ - ipp-private.h ipp.h globals.h string.h cups.h ppd.h array.h file.h \ - language.h i18n.h transcode.h debug.h -http.64.o: http.c http.c http-private.h ../config.h http.h string.h md5.h \ - ipp-private.h ipp.h globals.h string.h cups.h ppd.h array.h file.h \ - language.h i18n.h transcode.h debug.h -http-addr.64.o: http-addr.c http-addr.c globals.h string.h ../config.h string.h \ - http-private.h http.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h \ - file.h language.h i18n.h transcode.h debug.h -http-addrlist.64.o: http-addrlist.c http-addrlist.c http-private.h ../config.h http.h \ - string.h md5.h ipp-private.h ipp.h globals.h string.h cups.h ppd.h \ - array.h file.h language.h i18n.h transcode.h debug.h -http-support.64.o: http-support.c http-support.c debug.h globals.h string.h ../config.h \ - string.h http-private.h http.h md5.h ipp-private.h ipp.h cups.h ppd.h \ - array.h file.h language.h i18n.h transcode.h -ipp.64.o: ipp.c ipp.c http-private.h ../config.h http.h string.h md5.h \ - ipp-private.h ipp.h globals.h string.h cups.h ppd.h array.h file.h \ - language.h i18n.h transcode.h debug.h -ipp-support.64.o: ipp-support.c ipp-support.c globals.h string.h ../config.h string.h \ - http-private.h http.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h \ - file.h language.h i18n.h transcode.h debug.h -langprintf.64.o: langprintf.c langprintf.c globals.h string.h ../config.h string.h \ - http-private.h http.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h \ - file.h language.h i18n.h transcode.h -language.64.o: language.c language.c globals.h string.h ../config.h string.h \ - http-private.h http.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h \ - file.h language.h i18n.h transcode.h debug.h -localize.64.o: localize.c localize.c globals.h string.h ../config.h string.h \ - http-private.h http.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h \ - file.h language.h i18n.h transcode.h debug.h -mark.64.o: mark.c mark.c cups.h ipp.h http.h string.h ../config.h ppd.h array.h \ - file.h language.h string.h debug.h -md5.64.o: md5.c md5.c md5.h string.h ../config.h string.h -md5passwd.64.o: md5passwd.c md5passwd.c http-private.h ../config.h http.h string.h md5.h \ - ipp-private.h ipp.h string.h -notify.64.o: notify.c notify.c globals.h string.h ../config.h string.h http-private.h \ - http.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h \ - i18n.h transcode.h -options.64.o: options.c options.c cups.h ipp.h http.h string.h ../config.h ppd.h \ - array.h file.h language.h string.h debug.h -page.64.o: page.c page.c ppd.h array.h file.h string.h ../config.h string.h -ppd.64.o: ppd.c ppd.c globals.h string.h ../config.h string.h http-private.h \ - http.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h \ - i18n.h transcode.h debug.h -request.64.o: request.c request.c globals.h string.h ../config.h string.h \ - http-private.h http.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h \ - file.h language.h i18n.h transcode.h debug.h -sidechannel.64.o: sidechannel.c sidechannel.c sidechannel.h string.h ../config.h string.h -snprintf.64.o: snprintf.c snprintf.c string.h ../config.h string.h -string.64.o: string.c string.c array.h debug.h string.h ../config.h string.h -tempfile.64.o: tempfile.c tempfile.c globals.h string.h ../config.h string.h \ - http-private.h http.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h \ - file.h language.h i18n.h transcode.h debug.h -transcode.64.o: transcode.c transcode.c globals.h string.h ../config.h string.h \ - http-private.h http.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h \ - file.h language.h i18n.h transcode.h debug.h -usersys.64.o: usersys.c usersys.c http-private.h ../config.h http.h string.h md5.h \ - ipp-private.h ipp.h globals.h string.h cups.h ppd.h array.h file.h \ - language.h i18n.h transcode.h debug.h -util.64.o: util.c util.c globals.h string.h ../config.h string.h http-private.h \ - http.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h \ - i18n.h transcode.h debug.h -testadmin.64.o: testadmin.c testadmin.c adminutil.h cups.h ipp.h http.h string.h \ - ../config.h ppd.h array.h file.h language.h string.h -testarray.64.o: testarray.c testarray.c ../cups/string.h ../config.h string.h array.h \ - dir.h debug.h -testcups.64.o: testcups.c testcups.c cups.h ipp.h http.h string.h ../config.h ppd.h \ - array.h file.h language.h -testfile.64.o: testfile.c testfile.c string.h ../config.h string.h file.h debug.h -testhttp.64.o: testhttp.c testhttp.c http.h string.h ../config.h string.h -testi18n.64.o: testi18n.c testi18n.c i18n.h transcode.h language.h array.h string.h \ - ../config.h string.h -testipp.64.o: testipp.c testipp.c ../cups/string.h ../config.h string.h ipp-private.h \ - ipp.h http.h -testlang.64.o: testlang.c testlang.c i18n.h transcode.h language.h array.h string.h \ - ../config.h string.h -testppd.64.o: testppd.c testppd.c ../cups/string.h ../config.h string.h ppd.h array.h \ - file.h +# DO NOT DELETE + +adminutil.o: adminutil.h cups.h ipp.h http.h versioning.h ppd.h array.h +adminutil.o: file.h language.h globals.h string.h ../config.h http-private.h +adminutil.o: md5.h ipp-private.h i18n.h transcode.h debug.h +array.o: array.h versioning.h string.h ../config.h debug.h +attr.o: ppd.h array.h versioning.h file.h debug.h string.h ../config.h +auth.o: globals.h string.h ../config.h http-private.h http.h versioning.h +auth.o: md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h +auth.o: i18n.h transcode.h debug.h +backchannel.o: cups.h ipp.h http.h versioning.h ppd.h array.h file.h +backchannel.o: language.h +backend.o: backend.h versioning.h string.h ../config.h +custom.o: globals.h string.h ../config.h http-private.h http.h versioning.h +custom.o: md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h +custom.o: i18n.h transcode.h debug.h +dest.o: debug.h globals.h string.h ../config.h http-private.h http.h +dest.o: versioning.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h +dest.o: language.h i18n.h transcode.h +dir.o: dir.h versioning.h string.h ../config.h debug.h +emit.o: ppd.h array.h versioning.h file.h string.h ../config.h debug.h +encode.o: cups.h ipp.h http.h versioning.h ppd.h array.h file.h language.h +encode.o: ipp-private.h string.h ../config.h debug.h +file.o: http-private.h ../config.h http.h versioning.h md5.h ipp-private.h +file.o: ipp.h globals.h string.h cups.h ppd.h array.h file.h language.h +file.o: i18n.h transcode.h debug.h +getifaddrs.o: http-private.h ../config.h http.h versioning.h md5.h +getifaddrs.o: ipp-private.h ipp.h +getputfile.o: globals.h string.h ../config.h http-private.h http.h +getputfile.o: versioning.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h +getputfile.o: file.h language.h i18n.h transcode.h debug.h +globals.o: http-private.h ../config.h http.h versioning.h md5.h ipp-private.h +globals.o: ipp.h globals.h string.h cups.h ppd.h array.h file.h language.h +globals.o: i18n.h transcode.h debug.h +http.o: http-private.h ../config.h http.h versioning.h md5.h ipp-private.h +http.o: ipp.h globals.h string.h cups.h ppd.h array.h file.h language.h +http.o: i18n.h transcode.h debug.h +http-addr.o: globals.h string.h ../config.h http-private.h http.h +http-addr.o: versioning.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h +http-addr.o: file.h language.h i18n.h transcode.h debug.h +http-addrlist.o: http-private.h ../config.h http.h versioning.h md5.h +http-addrlist.o: ipp-private.h ipp.h globals.h string.h cups.h ppd.h array.h +http-addrlist.o: file.h language.h i18n.h transcode.h debug.h +http-support.o: debug.h globals.h string.h ../config.h http-private.h http.h +http-support.o: versioning.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h +http-support.o: file.h language.h i18n.h transcode.h +ipp.o: http-private.h ../config.h http.h versioning.h md5.h ipp-private.h +ipp.o: ipp.h globals.h string.h cups.h ppd.h array.h file.h language.h i18n.h +ipp.o: transcode.h debug.h +ipp-support.o: globals.h string.h ../config.h http-private.h http.h +ipp-support.o: versioning.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h +ipp-support.o: file.h language.h i18n.h transcode.h debug.h +langprintf.o: globals.h string.h ../config.h http-private.h http.h +langprintf.o: versioning.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h +langprintf.o: file.h language.h i18n.h transcode.h +language.o: globals.h string.h ../config.h http-private.h http.h versioning.h +language.o: md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h +language.o: i18n.h transcode.h debug.h +localize.o: globals.h string.h ../config.h http-private.h http.h versioning.h +localize.o: md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h +localize.o: i18n.h transcode.h debug.h +mark.o: cups.h ipp.h http.h versioning.h ppd.h array.h file.h language.h +mark.o: string.h ../config.h debug.h +md5.o: md5.h string.h ../config.h +md5passwd.o: http-private.h ../config.h http.h versioning.h md5.h +md5passwd.o: ipp-private.h ipp.h string.h +notify.o: globals.h string.h ../config.h http-private.h http.h versioning.h +notify.o: md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h +notify.o: i18n.h transcode.h +options.o: cups.h ipp.h http.h versioning.h ppd.h array.h file.h language.h +options.o: string.h ../config.h debug.h +page.o: ppd.h array.h versioning.h file.h string.h ../config.h +ppd.o: globals.h string.h ../config.h http-private.h http.h versioning.h +ppd.o: md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h +ppd.o: i18n.h transcode.h debug.h +request.o: globals.h string.h ../config.h http-private.h http.h versioning.h +request.o: md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h +request.o: i18n.h transcode.h debug.h +sidechannel.o: sidechannel.h versioning.h string.h ../config.h +snmp.o: globals.h string.h ../config.h http-private.h http.h versioning.h +snmp.o: md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h +snmp.o: i18n.h transcode.h snmp.h +snprintf.o: string.h ../config.h +string.o: array.h versioning.h debug.h string.h ../config.h +tempfile.o: globals.h string.h ../config.h http-private.h http.h versioning.h +tempfile.o: md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h +tempfile.o: i18n.h transcode.h debug.h +transcode.o: globals.h string.h ../config.h http-private.h http.h +transcode.o: versioning.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h +transcode.o: file.h language.h i18n.h transcode.h debug.h +usersys.o: http-private.h ../config.h http.h versioning.h md5.h ipp-private.h +usersys.o: ipp.h globals.h string.h cups.h ppd.h array.h file.h language.h +usersys.o: i18n.h transcode.h debug.h +util.o: globals.h string.h ../config.h http-private.h http.h versioning.h +util.o: md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h +util.o: i18n.h transcode.h debug.h +testadmin.o: adminutil.h cups.h ipp.h http.h versioning.h ppd.h array.h +testadmin.o: file.h language.h string.h ../config.h +testarray.o: ../cups/string.h ../config.h string.h array.h versioning.h dir.h +testarray.o: debug.h +testcups.o: cups.h ipp.h http.h versioning.h ppd.h array.h file.h language.h +testfile.o: string.h ../config.h file.h versioning.h debug.h +testhttp.o: http.h versioning.h string.h ../config.h +testi18n.o: i18n.h transcode.h language.h array.h versioning.h string.h +testi18n.o: ../config.h +testipp.o: ../cups/string.h ../config.h string.h ipp-private.h ipp.h http.h +testipp.o: versioning.h +testlang.o: i18n.h transcode.h language.h array.h versioning.h string.h +testlang.o: ../config.h +testppd.o: ../cups/string.h ../config.h string.h ppd.h array.h versioning.h +testppd.o: file.h +testsnmp.o: string.h ../config.h snmp.h http.h versioning.h +# DO NOT DELETE + +adminutil.32.o: adminutil.c adminutil.h cups.h ipp.h http.h versioning.h ppd.h array.h +adminutil.32.o: adminutil.c file.h language.h globals.h string.h ../config.h http-private.h +adminutil.32.o: adminutil.c md5.h ipp-private.h i18n.h transcode.h debug.h +array.32.o: array.c array.h versioning.h string.h ../config.h debug.h +attr.32.o: attr.c ppd.h array.h versioning.h file.h debug.h string.h ../config.h +auth.32.o: auth.c globals.h string.h ../config.h http-private.h http.h versioning.h +auth.32.o: auth.c md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h +auth.32.o: auth.c i18n.h transcode.h debug.h +backchannel.32.o: backchannel.c cups.h ipp.h http.h versioning.h ppd.h array.h file.h +backchannel.32.o: backchannel.c language.h +backend.32.o: backend.c backend.h versioning.h string.h ../config.h +custom.32.o: custom.c globals.h string.h ../config.h http-private.h http.h versioning.h +custom.32.o: custom.c md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h +custom.32.o: custom.c i18n.h transcode.h debug.h +dest.32.o: dest.c debug.h globals.h string.h ../config.h http-private.h http.h +dest.32.o: dest.c versioning.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h +dest.32.o: dest.c language.h i18n.h transcode.h +dir.32.o: dir.c dir.h versioning.h string.h ../config.h debug.h +emit.32.o: emit.c ppd.h array.h versioning.h file.h string.h ../config.h debug.h +encode.32.o: encode.c cups.h ipp.h http.h versioning.h ppd.h array.h file.h language.h +encode.32.o: encode.c ipp-private.h string.h ../config.h debug.h +file.32.o: file.c http-private.h ../config.h http.h versioning.h md5.h ipp-private.h +file.32.o: file.c ipp.h globals.h string.h cups.h ppd.h array.h file.h language.h +file.32.o: file.c i18n.h transcode.h debug.h +getifaddrs.32.o: getifaddrs.c http-private.h ../config.h http.h versioning.h md5.h +getifaddrs.32.o: getifaddrs.c ipp-private.h ipp.h +getputfile.32.o: getputfile.c globals.h string.h ../config.h http-private.h http.h +getputfile.32.o: getputfile.c versioning.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h +getputfile.32.o: getputfile.c file.h language.h i18n.h transcode.h debug.h +globals.32.o: globals.c http-private.h ../config.h http.h versioning.h md5.h ipp-private.h +globals.32.o: globals.c ipp.h globals.h string.h cups.h ppd.h array.h file.h language.h +globals.32.o: globals.c i18n.h transcode.h debug.h +http.32.o: http.c http-private.h ../config.h http.h versioning.h md5.h ipp-private.h +http.32.o: http.c ipp.h globals.h string.h cups.h ppd.h array.h file.h language.h +http.32.o: http.c i18n.h transcode.h debug.h +http-addr.32.o: http-addr.c globals.h string.h ../config.h http-private.h http.h +http-addr.32.o: http-addr.c versioning.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h +http-addr.32.o: http-addr.c file.h language.h i18n.h transcode.h debug.h +http-addrlist.32.o: http-addrlist.c http-private.h ../config.h http.h versioning.h md5.h +http-addrlist.32.o: http-addrlist.c ipp-private.h ipp.h globals.h string.h cups.h ppd.h array.h +http-addrlist.32.o: http-addrlist.c file.h language.h i18n.h transcode.h debug.h +http-support.32.o: http-support.c debug.h globals.h string.h ../config.h http-private.h http.h +http-support.32.o: http-support.c versioning.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h +http-support.32.o: http-support.c file.h language.h i18n.h transcode.h +ipp.32.o: ipp.c http-private.h ../config.h http.h versioning.h md5.h ipp-private.h +ipp.32.o: ipp.c ipp.h globals.h string.h cups.h ppd.h array.h file.h language.h i18n.h +ipp.32.o: ipp.c transcode.h debug.h +ipp-support.32.o: ipp-support.c globals.h string.h ../config.h http-private.h http.h +ipp-support.32.o: ipp-support.c versioning.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h +ipp-support.32.o: ipp-support.c file.h language.h i18n.h transcode.h debug.h +langprintf.32.o: langprintf.c globals.h string.h ../config.h http-private.h http.h +langprintf.32.o: langprintf.c versioning.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h +langprintf.32.o: langprintf.c file.h language.h i18n.h transcode.h +language.32.o: language.c globals.h string.h ../config.h http-private.h http.h versioning.h +language.32.o: language.c md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h +language.32.o: language.c i18n.h transcode.h debug.h +localize.32.o: localize.c globals.h string.h ../config.h http-private.h http.h versioning.h +localize.32.o: localize.c md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h +localize.32.o: localize.c i18n.h transcode.h debug.h +mark.32.o: mark.c cups.h ipp.h http.h versioning.h ppd.h array.h file.h language.h +mark.32.o: mark.c string.h ../config.h debug.h +md5.32.o: md5.c md5.h string.h ../config.h +md5passwd.32.o: md5passwd.c http-private.h ../config.h http.h versioning.h md5.h +md5passwd.32.o: md5passwd.c ipp-private.h ipp.h string.h +notify.32.o: notify.c globals.h string.h ../config.h http-private.h http.h versioning.h +notify.32.o: notify.c md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h +notify.32.o: notify.c i18n.h transcode.h +options.32.o: options.c cups.h ipp.h http.h versioning.h ppd.h array.h file.h language.h +options.32.o: options.c string.h ../config.h debug.h +page.32.o: page.c ppd.h array.h versioning.h file.h string.h ../config.h +ppd.32.o: ppd.c globals.h string.h ../config.h http-private.h http.h versioning.h +ppd.32.o: ppd.c md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h +ppd.32.o: ppd.c i18n.h transcode.h debug.h +request.32.o: request.c globals.h string.h ../config.h http-private.h http.h versioning.h +request.32.o: request.c md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h +request.32.o: request.c i18n.h transcode.h debug.h +sidechannel.32.o: sidechannel.c sidechannel.h versioning.h string.h ../config.h +snmp.32.o: snmp.c globals.h string.h ../config.h http-private.h http.h versioning.h +snmp.32.o: snmp.c md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h +snmp.32.o: snmp.c i18n.h transcode.h snmp.h +snprintf.32.o: snprintf.c string.h ../config.h +string.32.o: string.c array.h versioning.h debug.h string.h ../config.h +tempfile.32.o: tempfile.c globals.h string.h ../config.h http-private.h http.h versioning.h +tempfile.32.o: tempfile.c md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h +tempfile.32.o: tempfile.c i18n.h transcode.h debug.h +transcode.32.o: transcode.c globals.h string.h ../config.h http-private.h http.h +transcode.32.o: transcode.c versioning.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h +transcode.32.o: transcode.c file.h language.h i18n.h transcode.h debug.h +usersys.32.o: usersys.c http-private.h ../config.h http.h versioning.h md5.h ipp-private.h +usersys.32.o: usersys.c ipp.h globals.h string.h cups.h ppd.h array.h file.h language.h +usersys.32.o: usersys.c i18n.h transcode.h debug.h +util.32.o: util.c globals.h string.h ../config.h http-private.h http.h versioning.h +util.32.o: util.c md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h +util.32.o: util.c i18n.h transcode.h debug.h +testadmin.32.o: testadmin.c adminutil.h cups.h ipp.h http.h versioning.h ppd.h array.h +testadmin.32.o: testadmin.c file.h language.h string.h ../config.h +testarray.32.o: testarray.c ../cups/string.h ../config.h string.h array.h versioning.h dir.h +testarray.32.o: testarray.c debug.h +testcups.32.o: testcups.c cups.h ipp.h http.h versioning.h ppd.h array.h file.h language.h +testfile.32.o: testfile.c string.h ../config.h file.h versioning.h debug.h +testhttp.32.o: testhttp.c http.h versioning.h string.h ../config.h +testi18n.32.o: testi18n.c i18n.h transcode.h language.h array.h versioning.h string.h +testi18n.32.o: testi18n.c ../config.h +testipp.32.o: testipp.c ../cups/string.h ../config.h string.h ipp-private.h ipp.h http.h +testipp.32.o: testipp.c versioning.h +testlang.32.o: testlang.c i18n.h transcode.h language.h array.h versioning.h string.h +testlang.32.o: testlang.c ../config.h +testppd.32.o: testppd.c ../cups/string.h ../config.h string.h ppd.h array.h versioning.h +testppd.32.o: testppd.c file.h +testsnmp.32.o: testsnmp.c string.h ../config.h snmp.h http.h versioning.h +# DO NOT DELETE + +adminutil.64.o: adminutil.c adminutil.h cups.h ipp.h http.h versioning.h ppd.h array.h +adminutil.64.o: adminutil.c file.h language.h globals.h string.h ../config.h http-private.h +adminutil.64.o: adminutil.c md5.h ipp-private.h i18n.h transcode.h debug.h +array.64.o: array.c array.h versioning.h string.h ../config.h debug.h +attr.64.o: attr.c ppd.h array.h versioning.h file.h debug.h string.h ../config.h +auth.64.o: auth.c globals.h string.h ../config.h http-private.h http.h versioning.h +auth.64.o: auth.c md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h +auth.64.o: auth.c i18n.h transcode.h debug.h +backchannel.64.o: backchannel.c cups.h ipp.h http.h versioning.h ppd.h array.h file.h +backchannel.64.o: backchannel.c language.h +backend.64.o: backend.c backend.h versioning.h string.h ../config.h +custom.64.o: custom.c globals.h string.h ../config.h http-private.h http.h versioning.h +custom.64.o: custom.c md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h +custom.64.o: custom.c i18n.h transcode.h debug.h +dest.64.o: dest.c debug.h globals.h string.h ../config.h http-private.h http.h +dest.64.o: dest.c versioning.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h +dest.64.o: dest.c language.h i18n.h transcode.h +dir.64.o: dir.c dir.h versioning.h string.h ../config.h debug.h +emit.64.o: emit.c ppd.h array.h versioning.h file.h string.h ../config.h debug.h +encode.64.o: encode.c cups.h ipp.h http.h versioning.h ppd.h array.h file.h language.h +encode.64.o: encode.c ipp-private.h string.h ../config.h debug.h +file.64.o: file.c http-private.h ../config.h http.h versioning.h md5.h ipp-private.h +file.64.o: file.c ipp.h globals.h string.h cups.h ppd.h array.h file.h language.h +file.64.o: file.c i18n.h transcode.h debug.h +getifaddrs.64.o: getifaddrs.c http-private.h ../config.h http.h versioning.h md5.h +getifaddrs.64.o: getifaddrs.c ipp-private.h ipp.h +getputfile.64.o: getputfile.c globals.h string.h ../config.h http-private.h http.h +getputfile.64.o: getputfile.c versioning.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h +getputfile.64.o: getputfile.c file.h language.h i18n.h transcode.h debug.h +globals.64.o: globals.c http-private.h ../config.h http.h versioning.h md5.h ipp-private.h +globals.64.o: globals.c ipp.h globals.h string.h cups.h ppd.h array.h file.h language.h +globals.64.o: globals.c i18n.h transcode.h debug.h +http.64.o: http.c http-private.h ../config.h http.h versioning.h md5.h ipp-private.h +http.64.o: http.c ipp.h globals.h string.h cups.h ppd.h array.h file.h language.h +http.64.o: http.c i18n.h transcode.h debug.h +http-addr.64.o: http-addr.c globals.h string.h ../config.h http-private.h http.h +http-addr.64.o: http-addr.c versioning.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h +http-addr.64.o: http-addr.c file.h language.h i18n.h transcode.h debug.h +http-addrlist.64.o: http-addrlist.c http-private.h ../config.h http.h versioning.h md5.h +http-addrlist.64.o: http-addrlist.c ipp-private.h ipp.h globals.h string.h cups.h ppd.h array.h +http-addrlist.64.o: http-addrlist.c file.h language.h i18n.h transcode.h debug.h +http-support.64.o: http-support.c debug.h globals.h string.h ../config.h http-private.h http.h +http-support.64.o: http-support.c versioning.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h +http-support.64.o: http-support.c file.h language.h i18n.h transcode.h +ipp.64.o: ipp.c http-private.h ../config.h http.h versioning.h md5.h ipp-private.h +ipp.64.o: ipp.c ipp.h globals.h string.h cups.h ppd.h array.h file.h language.h i18n.h +ipp.64.o: ipp.c transcode.h debug.h +ipp-support.64.o: ipp-support.c globals.h string.h ../config.h http-private.h http.h +ipp-support.64.o: ipp-support.c versioning.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h +ipp-support.64.o: ipp-support.c file.h language.h i18n.h transcode.h debug.h +langprintf.64.o: langprintf.c globals.h string.h ../config.h http-private.h http.h +langprintf.64.o: langprintf.c versioning.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h +langprintf.64.o: langprintf.c file.h language.h i18n.h transcode.h +language.64.o: language.c globals.h string.h ../config.h http-private.h http.h versioning.h +language.64.o: language.c md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h +language.64.o: language.c i18n.h transcode.h debug.h +localize.64.o: localize.c globals.h string.h ../config.h http-private.h http.h versioning.h +localize.64.o: localize.c md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h +localize.64.o: localize.c i18n.h transcode.h debug.h +mark.64.o: mark.c cups.h ipp.h http.h versioning.h ppd.h array.h file.h language.h +mark.64.o: mark.c string.h ../config.h debug.h +md5.64.o: md5.c md5.h string.h ../config.h +md5passwd.64.o: md5passwd.c http-private.h ../config.h http.h versioning.h md5.h +md5passwd.64.o: md5passwd.c ipp-private.h ipp.h string.h +notify.64.o: notify.c globals.h string.h ../config.h http-private.h http.h versioning.h +notify.64.o: notify.c md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h +notify.64.o: notify.c i18n.h transcode.h +options.64.o: options.c cups.h ipp.h http.h versioning.h ppd.h array.h file.h language.h +options.64.o: options.c string.h ../config.h debug.h +page.64.o: page.c ppd.h array.h versioning.h file.h string.h ../config.h +ppd.64.o: ppd.c globals.h string.h ../config.h http-private.h http.h versioning.h +ppd.64.o: ppd.c md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h +ppd.64.o: ppd.c i18n.h transcode.h debug.h +request.64.o: request.c globals.h string.h ../config.h http-private.h http.h versioning.h +request.64.o: request.c md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h +request.64.o: request.c i18n.h transcode.h debug.h +sidechannel.64.o: sidechannel.c sidechannel.h versioning.h string.h ../config.h +snmp.64.o: snmp.c globals.h string.h ../config.h http-private.h http.h versioning.h +snmp.64.o: snmp.c md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h +snmp.64.o: snmp.c i18n.h transcode.h snmp.h +snprintf.64.o: snprintf.c string.h ../config.h +string.64.o: string.c array.h versioning.h debug.h string.h ../config.h +tempfile.64.o: tempfile.c globals.h string.h ../config.h http-private.h http.h versioning.h +tempfile.64.o: tempfile.c md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h +tempfile.64.o: tempfile.c i18n.h transcode.h debug.h +transcode.64.o: transcode.c globals.h string.h ../config.h http-private.h http.h +transcode.64.o: transcode.c versioning.h md5.h ipp-private.h ipp.h cups.h ppd.h array.h +transcode.64.o: transcode.c file.h language.h i18n.h transcode.h debug.h +usersys.64.o: usersys.c http-private.h ../config.h http.h versioning.h md5.h ipp-private.h +usersys.64.o: usersys.c ipp.h globals.h string.h cups.h ppd.h array.h file.h language.h +usersys.64.o: usersys.c i18n.h transcode.h debug.h +util.64.o: util.c globals.h string.h ../config.h http-private.h http.h versioning.h +util.64.o: util.c md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h +util.64.o: util.c i18n.h transcode.h debug.h +testadmin.64.o: testadmin.c adminutil.h cups.h ipp.h http.h versioning.h ppd.h array.h +testadmin.64.o: testadmin.c file.h language.h string.h ../config.h +testarray.64.o: testarray.c ../cups/string.h ../config.h string.h array.h versioning.h dir.h +testarray.64.o: testarray.c debug.h +testcups.64.o: testcups.c cups.h ipp.h http.h versioning.h ppd.h array.h file.h language.h +testfile.64.o: testfile.c string.h ../config.h file.h versioning.h debug.h +testhttp.64.o: testhttp.c http.h versioning.h string.h ../config.h +testi18n.64.o: testi18n.c i18n.h transcode.h language.h array.h versioning.h string.h +testi18n.64.o: testi18n.c ../config.h +testipp.64.o: testipp.c ../cups/string.h ../config.h string.h ipp-private.h ipp.h http.h +testipp.64.o: testipp.c versioning.h +testlang.64.o: testlang.c i18n.h transcode.h language.h array.h versioning.h string.h +testlang.64.o: testlang.c ../config.h +testppd.64.o: testppd.c ../cups/string.h ../config.h string.h ppd.h array.h versioning.h +testppd.64.o: testppd.c file.h +testsnmp.64.o: testsnmp.c string.h ../config.h snmp.h http.h versioning.h diff --git a/cups/Makefile b/cups/Makefile index d290c7528..e00a368e3 100644 --- a/cups/Makefile +++ b/cups/Makefile @@ -3,7 +3,7 @@ # # API library Makefile for the Common UNIX Printing System (CUPS). # -# Copyright 2007 by Apple Inc. +# Copyright 2007-2008 by Apple Inc. # Copyright 1997-2006 by Easy Software Products, all rights reserved. # # These coded instructions, statements, and computer programs are the @@ -55,6 +55,7 @@ LIBOBJS = \ ppd.o \ request.o \ sidechannel.o \ + snmp.o \ snprintf.o \ string.o \ tempfile.o \ @@ -76,6 +77,7 @@ OBJS = \ testipp.o \ testlang.o \ testppd.o \ + testsnmp.o \ php_cups_wrap.o @@ -96,6 +98,7 @@ HEADERS = \ language.h \ ppd.h \ sidechannel.h \ + snmp.h \ transcode.h \ versioning.h @@ -117,7 +120,8 @@ TARGETS = \ testi18n \ testipp \ testlang \ - testppd + testppd \ + testsnmp # @@ -146,8 +150,8 @@ depend: makedepend -Y -I.. -fDependencies.tmp $(OBJS:.o=.c) >/dev/null 2>&1 $(RM) Dependencies cp Dependencies.tmp Dependencies - sed -r -e '1,$$s/^([^.]+)\.o:/\1\.32.o: \1\.c /' Dependencies.tmp >>Dependencies - sed -r -e '1,$$s/^([^.]+)\.o:/\1\.64.o: \1\.c /' Dependencies.tmp >>Dependencies + sed -E -e '1,$$s/^([^.]+)\.o:/\1\.32.o: \1\.c /' Dependencies.tmp >>Dependencies + sed -E -e '1,$$s/^([^.]+)\.o:/\1\.64.o: \1\.c /' Dependencies.tmp >>Dependencies $(RM) Dependencies.tmp @@ -425,6 +429,16 @@ testppd: testppd.o libcups.a # +# testsnmp (dependency on static CUPS library is intentional) +# + +testsnmp: testsnmp.o libcups.a + echo Linking $@... + $(CC) $(LDFLAGS) -o $@ testsnmp.o libcups.a \ + $(LIBGSSAPI) $(SSLLIBS) $(COMMONLIBS) $(LIBZ) + + +# # Automatic API help files... # diff --git a/cups/auth.c b/cups/auth.c index 6882bfad1..dd2d22c51 100644 --- a/cups/auth.c +++ b/cups/auth.c @@ -3,7 +3,7 @@ * * Authentication functions for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1997-2007 by Easy Software Products. * * This file contains Kerberos support code, copyright 2006 by diff --git a/cups/dest.c b/cups/dest.c index d7656bb28..64b2ca431 100644 --- a/cups/dest.c +++ b/cups/dest.c @@ -1131,11 +1131,6 @@ appleSetDefault(const char *name) /* I - Default printer/class name */ return; } -#ifdef DEBUG - CFStringGetCString(network, name, namesize, kCFStringEncodingUTF8); - printf("appleSetDefault: network=\"%s\"\n", name); -#endif /* DEBUG */ - if ((newprinter = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingUTF8)) == NULL) { @@ -1209,8 +1204,9 @@ appleSetDefault(const char *name) /* I - Default printer/class name */ if (newlocation) CFRelease(newlocation); } - - CFRelease(locations); + + if (locations) + CFRelease(locations); CFRelease(network); CFRelease(newprinter); } diff --git a/cups/emit.c b/cups/emit.c index ccbc02596..5ac480f35 100644 --- a/cups/emit.c +++ b/cups/emit.c @@ -3,7 +3,7 @@ * * PPD code emission routines for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -103,16 +103,32 @@ ppdCollect2(ppd_file_t *ppd, /* I - PPD file data */ DEBUG_printf(("ppdCollect2(ppd=%p, section=%d, min_order=%f, choices=%p)\n", ppd, section, min_order, choices)); - if (ppd == NULL) + if (!ppd || !choices) + { + if (choices) + *choices = NULL; + return (0); + } /* * Allocate memory for up to N selected choices... */ - count = 0; - collect = calloc(sizeof(ppd_choice_t *), cupsArrayCount(ppd->marked)); - orders = calloc(sizeof(float), cupsArrayCount(ppd->marked)); + count = 0; + if ((collect = calloc(sizeof(ppd_choice_t *), + cupsArrayCount(ppd->marked))) == NULL) + { + *choices = NULL; + return (0); + } + + if ((orders = calloc(sizeof(float), cupsArrayCount(ppd->marked))) == NULL) + { + *choices = NULL; + free(collect); + return (0); + } /* * Loop through all options and add choices as needed... diff --git a/cups/encode.c b/cups/encode.c index 4e7f78118..9ac62b870 100644 --- a/cups/encode.c +++ b/cups/encode.c @@ -396,10 +396,44 @@ cupsEncodeOptions2( * Find the end of this value and mark it if needed... */ - if ((sep = strchr(val, ',')) != NULL) + for (sep = val; *sep; sep ++) + { + if (*sep == '\'') + { + /* + * Skip quoted option value... + */ + + sep ++; + + while (*sep && *sep != '\'') + sep ++; + + if (!*sep) + sep --; + } + else if (*sep == '\"') + { + /* + * Skip quoted option value... + */ + + sep ++; + + while (*sep && *sep != '\"') + sep ++; + + if (!*sep) + sep --; + } + else if (*sep == ',') + break; + else if (*sep == '\\' && sep[1]) + sep ++; + } + + if (*sep == ',') *sep++ = '\0'; - else - sep = val + strlen(val); /* * Copy the option value(s) over as needed by the type... diff --git a/cups/globals.h b/cups/globals.h index b310461dd..faed12951 100644 --- a/cups/globals.h +++ b/cups/globals.h @@ -3,7 +3,7 @@ * * Global variable definitions for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -97,6 +97,9 @@ typedef struct _cups_globals_s /**** CUPS global state data ****/ int ppd_line; /* Current line number */ ppd_conform_t ppd_conform; /* Level of conformance required */ + /* snmp.c */ + int snmp_debug; /* Log SNMP IO to stderr? */ + /* tempfile.c */ char tempfile[1024]; /* cupsTempFd/File buffer */ diff --git a/cups/http-addrlist.c b/cups/http-addrlist.c index 8f8e5c06f..6fc5a1243 100644 --- a/cups/http-addrlist.c +++ b/cups/http-addrlist.c @@ -3,7 +3,7 @@ * * HTTP address list routines for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -202,9 +202,11 @@ httpAddrGetList(const char *hostname, /* I - Hostname, IP address, or NULL for p * Domain socket address... */ - first = (http_addrlist_t *)calloc(1, sizeof(http_addrlist_t)); - first->addr.un.sun_family = AF_LOCAL; - strlcpy(first->addr.un.sun_path, hostname, sizeof(first->addr.un.sun_path)); + if ((first = (http_addrlist_t *)calloc(1, sizeof(http_addrlist_t))) != NULL) + { + first->addr.un.sun_family = AF_LOCAL; + strlcpy(first->addr.un.sun_path, hostname, sizeof(first->addr.un.sun_path)); + } } else #endif /* AF_LOCAL */ diff --git a/cups/http.c b/cups/http.c index 9efa1a365..f860a221d 100644 --- a/cups/http.c +++ b/cups/http.c @@ -3,7 +3,7 @@ * * HTTP routines for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * This file contains Kerberos support code, copyright 2006 by @@ -402,9 +402,11 @@ httpConnectEncrypt( * Allocate memory for the structure... */ - http = calloc(sizeof(http_t), 1); - if (http == NULL) + if ((http = calloc(sizeof(http_t), 1)) == NULL) + { + httpAddrFreeList(addrlist); return (NULL); + } http->version = HTTP_1_1; http->blocking = 1; @@ -1735,9 +1737,15 @@ httpSetAuthString(http_t *http, /* I - HTTP connection */ */ int len = (int)strlen(scheme) + (data ? (int)strlen(data) + 1 : 0) + 1; + char *temp; if (len > (int)sizeof(http->_authstring)) - http->authstring = malloc(len); + { + if ((temp = malloc(len)) == NULL) + len = sizeof(http->_authstring); + else + http->authstring = temp; + } if (data) snprintf(http->authstring, len, "%s %s", scheme, data); diff --git a/cups/ipp.c b/cups/ipp.c index c068d84ce..f212fd117 100644 --- a/cups/ipp.c +++ b/cups/ipp.c @@ -4,7 +4,7 @@ * Internet Printing Protocol support functions for the Common UNIX * Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -361,7 +361,12 @@ ippAddOctetString(ipp_t *ipp, /* I - IPP message */ if (data) { - attr->values[0].unknown.data = malloc(datalen); + if ((attr->values[0].unknown.data = malloc(datalen)) == NULL) + { + ippDeleteAttribute(ipp, attr); + return (NULL); + } + memcpy(attr->values[0].unknown.data, data, datalen); } @@ -1277,7 +1282,11 @@ ippReadIO(void *src, /* I - Data source */ if (ipp->current) ipp->prev = ipp->current; - attr = ipp->current = _ippAddAttr(ipp, 1); + if ((attr = ipp->current = _ippAddAttr(ipp, 1)) == NULL) + { + DEBUG_puts("ippReadIO: unable to allocate attribute!"); + return (IPP_ERROR); + } DEBUG_printf(("ippReadIO: name=\'%s\', ipp->current=%p, ipp->prev=%p\n", buffer, ipp->current, ipp->prev)); @@ -1538,7 +1547,7 @@ ippReadIO(void *src, /* I - Data source */ break; default : /* Other unsupported values */ - if (n > sizeof(buffer)) + if (n > IPP_MAX_LENGTH) { DEBUG_printf(("ippReadIO: bad value length %d!\n", n)); return (IPP_ERROR); @@ -1547,7 +1556,12 @@ ippReadIO(void *src, /* I - Data source */ value->unknown.length = n; if (n > 0) { - value->unknown.data = malloc(n); + if ((value->unknown.data = malloc(n)) == NULL) + { + DEBUG_puts("ippReadIO: Unable to allocate value"); + return (IPP_ERROR); + } + if ((*cb)(src, value->unknown.data, n) < n) { DEBUG_puts("ippReadIO: Unable to read unsupported value!"); diff --git a/cups/language.c b/cups/language.c index a94a3ae4b..ea629c903 100644 --- a/cups/language.c +++ b/cups/language.c @@ -3,7 +3,7 @@ * * I18N/language support for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1997-2007 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -975,7 +975,12 @@ _cupsMessageLoad(const char *filename) /* I - Message catalog to load */ return (a); } - m->id = strdup(ptr); + if ((m->id = strdup(ptr)) == NULL) + { + free(m); + cupsFileClose(fp); + return (a); + } } else if (s[0] == '\"' && m) { @@ -1023,7 +1028,11 @@ _cupsMessageLoad(const char *filename) /* I - Message catalog to load */ * Set the string... */ - m->str = strdup(ptr); + if ((m->str = strdup(ptr)) == NULL) + { + cupsFileClose(fp); + return (a); + } } } diff --git a/cups/libcups.exp b/cups/libcups.exp index de8fd50c9..a757eedcd 100644 --- a/cups/libcups.exp +++ b/cups/libcups.exp @@ -146,6 +146,14 @@ _cupsPutFile _cupsReadResponseData _cupsRemoveDest _cupsRemoveOption +_cupsSNMPClose +_cupsSNMPCopyOID +_cupsSNMPIsOID +_cupsSNMPIsOIDPrefixed +_cupsSNMPOpen +_cupsSNMPRead +_cupsSNMPSetDebug +_cupsSNMPWrite _cupsSendRequest _cupsServer _cupsSetDefaultDest diff --git a/cups/options.c b/cups/options.c index b0d703e63..f04138497 100644 --- a/cups/options.c +++ b/cups/options.c @@ -3,7 +3,7 @@ * * Option routines for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1997-2007 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -473,15 +473,24 @@ cupsParseOptions( *value; /* Pointer to value */ - if (arg == NULL || options == NULL || num_options < 0) + /* + * Range check input... + */ + + if (!arg) + return (num_options); + + if (!options || num_options < 0) return (0); /* * Make a copy of the argument string and then divide it up... */ - copyarg = strdup(arg); - ptr = copyarg; + if ((copyarg = strdup(arg)) == NULL) + return (num_options); + + ptr = copyarg; /* * Skip leading spaces... diff --git a/cups/ppd.c b/cups/ppd.c index 50ad5787f..ea9eb86b7 100644 --- a/cups/ppd.c +++ b/cups/ppd.c @@ -3,7 +3,7 @@ * * PPD file routines for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -826,6 +826,13 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ profile = realloc(ppd->profiles, sizeof(ppd_profile_t) * (ppd->num_profiles + 1)); + if (!profile) + { + cg->ppd_status = PPD_ALLOC_ERROR; + + goto error; + } + ppd->profiles = profile; profile += ppd->num_profiles; ppd->num_profiles ++; @@ -1112,7 +1119,12 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ } ppd->num_emulations = count; - ppd->emulations = calloc(count, sizeof(ppd_emul_t)); + if ((ppd->emulations = calloc(count, sizeof(ppd_emul_t))) == NULL) + { + cg->ppd_status = PPD_ALLOC_ERROR; + + goto error; + } for (i = 0, sptr = string; i < count; i ++) { @@ -1875,7 +1887,12 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ * Add the option choice... */ - choice = ppd_add_choice(option, name); + if ((choice = ppd_add_choice(option, name)) == NULL) + { + cg->ppd_status = PPD_ALLOC_ERROR; + + goto error; + } if (text[0]) cupsCharsetToUTF8((cups_utf8_t *)choice->text, text, diff --git a/cups/snmp.c b/cups/snmp.c new file mode 100644 index 000000000..123f96538 --- /dev/null +++ b/cups/snmp.c @@ -0,0 +1,1268 @@ +/* + * "$Id$" + * + * SNMP functions for the Common UNIX Printing System (CUPS). + * + * Copyright 2007-2008 by Apple Inc. + * Copyright 2006-2007 by Easy Software Products, all rights reserved. + * + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * "LICENSE" which should have been included with this file. If this + * file is missing or damaged, see the license at "http://www.cups.org/". + * + * This file is subject to the Apple OS-Developed Software exception. + * + * Contents: + * + * cupsSNMPClose() - Close a SNMP socket. + * cupsSNMPCopyOID() - Copy an OID. + * cupsSNMPIsOID() - Test whether a SNMP response contains the + * specified OID. + * cupsSNMPIsOIDPrefixed() - Test whether a SNMP response uses the specified + * OID prefix. + * cupsSNMPOpen() - Open a SNMP socket. + * cupsSNMPRead() - Read and parse a SNMP response... + * cupsSNMPSetDebug() - Enable/disable debug logging to stderr. + * cupsSNMPWrite() - Send an SNMP query packet. + * asn1_decode_snmp() - Decode a SNMP packet. + * asn1_debug() - Decode an ASN1-encoded message. + * asn1_encode_snmp() - Encode a SNMP packet. + * asn1_get_integer() - Get an integer value. + * asn1_get_length() - Get a value length. + * asn1_get_oid() - Get an OID value. + * asn1_get_packed() - Get a packed integer value. + * asn1_get_string() - Get a string value. + * asn1_get_type() - Get a value type. + * asn1_set_integer() - Set an integer value. + * asn1_set_length() - Set a value length. + * asn1_set_oid() - Set an OID value. + * asn1_set_packed() - Set a packed integer value. + * asn1_size_integer() - Figure out the number of bytes needed for an + * integer value. + * asn1_size_length() - Figure out the number of bytes needed for a + * length value. + * asn1_size_oid() - Figure out the numebr of bytes needed for an OID + * value. + * asn1_size_packed() - Figure out the number of bytes needed for a + * packed integer value. + * snmp_set_error() - Set the localized error for a packet. + */ + +/* + * Include necessary headers. + */ + +#include "globals.h" +#include "snmp.h" +#include <errno.h> +#ifdef HAVE_POLL +# include <sys/poll.h> +#endif /* HAVE_POLL */ + + +/* + * Local functions... + */ + +static int asn1_decode_snmp(unsigned char *buffer, size_t len, + cups_snmp_t *packet); +static void asn1_debug(const char *prefix, unsigned char *buffer, + size_t len, int indent); +static int asn1_encode_snmp(unsigned char *buffer, size_t len, + cups_snmp_t *packet); +static int asn1_get_integer(unsigned char **buffer, + unsigned char *bufend, + int length); +static int asn1_get_oid(unsigned char **buffer, + unsigned char *bufend, + int length, int *oid, int oidsize); +static int asn1_get_packed(unsigned char **buffer, + unsigned char *bufend); +static char *asn1_get_string(unsigned char **buffer, + unsigned char *bufend, + int length, char *string, + int strsize); +static int asn1_get_length(unsigned char **buffer, + unsigned char *bufend); +static int asn1_get_type(unsigned char **buffer, + unsigned char *bufend); +static void asn1_set_integer(unsigned char **buffer, + int integer); +static void asn1_set_length(unsigned char **buffer, + int length); +static void asn1_set_oid(unsigned char **buffer, + const int *oid); +static void asn1_set_packed(unsigned char **buffer, + int integer); +static int asn1_size_integer(int integer); +static int asn1_size_length(int length); +static int asn1_size_oid(const int *oid); +static int asn1_size_packed(int integer); +static void snmp_set_error(cups_snmp_t *packet, + const char *message); + + +/* + * 'cupsSNMPClose()' - Close a SNMP socket. + * + * @since CUPS 1.4@ + */ + +void +cupsSNMPClose(int fd) /* I - SNMP socket file descriptor */ +{ +#ifdef WIN32 + closesocket(fd); +#else + close(fd); +#endif /* WIN32 */ +} + + +/* + * 'cupsSNMPCopyOID()' - Copy an OID. + */ + +int * /* O - New OID */ +cupsSNMPCopyOID(int *dst, /* I - Destination OID */ + const int *src, /* I - Source OID */ + int dstsize) /* I - Number of integers in dst */ +{ + int i; /* Looping var */ + + + for (i = 0, dstsize --; src[i] && i < dstsize; i ++) + dst[i] = src[i]; + + dst[i] = 0; + + return (dst); +} + + +/* + * 'cupsSNMPIsOID()' - Test whether a SNMP response contains the specified OID. + * + * The array pointed to by "oid" is 0-terminated. + * + * @since CUPS 1.4@ + */ + +int /* O - 1 if equal, 0 if not equal */ +cupsSNMPIsOID(cups_snmp_t *packet, /* I - Response packet */ + const int *oid) /* I - OID */ +{ + int i; /* Looping var */ + + + /* + * Range check input... + */ + + if (!packet || !oid) + return (0); + + /* + * Compare OIDs... + */ + + for (i = 0; i < CUPS_SNMP_MAX_OID && oid[i] && packet->object_name[i]; i ++) + if (oid[i] != packet->object_name[i]) + return (0); + + return (i < CUPS_SNMP_MAX_OID && oid[i] == packet->object_name[i]); +} + + +/* + * 'cupsSNMPIsOIDPrefixed()' - Test whether a SNMP response uses the specified + * OID prefix. + * + * The array pointed to by "prefix" is 0-terminated. + * + * @since CUPS 1.4@ + */ + +int /* O - 1 if prefixed, 0 if not prefixed */ +cupsSNMPIsOIDPrefixed( + cups_snmp_t *packet, /* I - Response packet */ + const int *prefix) /* I - OID prefix */ +{ + int i; /* Looping var */ + + + /* + * Range check input... + */ + + if (!packet || !prefix) + return (0); + + /* + * Compare OIDs... + */ + + for (i = 0; + i < CUPS_SNMP_MAX_OID && prefix[i] && packet->object_name[i]; + i ++) + if (prefix[i] != packet->object_name[i]) + return (0); + + return (i < CUPS_SNMP_MAX_OID); +} + + +/* + * 'cupsSNMPOpen()' - Open a SNMP socket. + * + * @since CUPS 1.4@ + */ + +int /* O - SNMP socket file descriptor */ +cupsSNMPOpen(void) +{ + int fd; /* SNMP socket file descriptor */ + int val; /* Socket option value */ + + + /* + * Create the SNMP socket... + */ + + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + return (-1); + + /* + * Set the "broadcast" flag... + */ + + val = 1; + + if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &val, sizeof(val))) + { + close(fd); + + return (-1); + } + + return (fd); +} + + +/* + * 'cupsSNMPRead()' - Read and parse a SNMP response... + * + * If "timeout" is negative, cupsSNMPRead() will wait for a response + * indefinitely. + * + * @since CUPS 1.4@ + */ + +cups_snmp_t * /* O - SNMP packet or NULL if none */ +cupsSNMPRead(int fd, /* I - SNMP socket file descriptor */ + cups_snmp_t *packet, /* I - SNMP packet buffer */ + int msec) /* I - Timeout in milliseconds */ +{ + unsigned char buffer[CUPS_SNMP_MAX_PACKET]; + /* Data packet */ + int bytes; /* Number of bytes received */ + socklen_t addrlen; /* Source address length */ + + + /* + * Range check input... + */ + + if (fd < 0 || !packet) + return (NULL); + + /* + * Optionally wait for a response... + */ + + if (msec >= 0) + { + int ready; /* Data ready on socket? */ +#ifdef HAVE_POLL + struct pollfd pfd; /* Polled file descriptor */ + + pfd.fd = fd; + pfd.events = POLLIN; + + while ((ready = poll(&pfd, 1, msec)) < 0 && errno == EINTR); + +#else + fd_set input_set; /* select() input set */ + struct timeval timeout; /* select() timeout */ + + do + { + FD_ZERO(&input_set); + FD_SET(fd, &input_set); + + timeout.tv_sec = msec / 1000; + timeout.tv_usec = (msec % 1000) * 1000; + + ready = select(fd + 1, &input_set, NULL, NULL, &timeout); + } +# ifdef WIN32 + while (ready < 0 && WSAGetLastError() == WSAEINTR); +# else + while (ready < 0 && errno == EINTR); +# endif /* WIN32 */ +#endif /* HAVE_POLL */ + + /* + * If we don't have any data ready, return right away... + */ + + if (ready <= 0) + return (NULL); + } + + /* + * Read the response data... + */ + + addrlen = sizeof(packet->address); + + if ((bytes = recvfrom(fd, buffer, sizeof(buffer), 0, + (void *)&(packet->address), &addrlen)) < 0) + return (NULL); + + /* + * Look for the response status code in the SNMP message header... + */ + + asn1_debug("DEBUG: IN ", buffer, bytes, 0); + + asn1_decode_snmp(buffer, bytes, packet); + + /* + * Return decoded data packet... + */ + + return (packet); +} + + +/* + * 'cupsSNMPSetDebug()' - Enable/disable debug logging to stderr. + * + * @since CUPS 1.4@ + */ + +void +cupsSNMPSetDebug(int level) /* I - 1 to enable debug output, 0 otherwise */ +{ + _cups_globals_t *cg = _cupsGlobals(); /* Global data */ + + + cg->snmp_debug = level; +} + + +/* + * 'cupsSNMPWrite()' - Send an SNMP query packet. + * + * The array pointed to by "oid" is 0-terminated. + * + * @since CUPS 1.4@ + */ + +int /* O - 1 on success, 0 on error */ +cupsSNMPWrite( + int fd, /* I - SNMP socket */ + http_addr_t *address, /* I - Address to send to */ + int version, /* I - SNMP version */ + const char *community, /* I - Community name */ + cups_asn1_t request_type, /* I - Request type */ + const unsigned request_id, /* I - Request ID */ + const int *oid) /* I - OID */ +{ + int i; /* Looping var */ + cups_snmp_t packet; /* SNMP message packet */ + unsigned char buffer[CUPS_SNMP_MAX_PACKET]; + /* SNMP message buffer */ + int bytes; /* Size of message */ + + + /* + * Create the SNMP message... + */ + + memset(&packet, 0, sizeof(packet)); + + packet.version = version; + packet.request_type = request_type; + packet.request_id = request_id; + packet.object_type = CUPS_ASN1_NULL_VALUE; + + strlcpy(packet.community, community, sizeof(packet.community)); + + for (i = 0; oid[i]; i ++) + packet.object_name[i] = oid[i]; + + bytes = asn1_encode_snmp(buffer, sizeof(buffer), &packet); + + if (bytes < 0) + { + errno = E2BIG; + + return (0); + } + + asn1_debug("DEBUG: OUT ", buffer, bytes, 0); + + /* + * Send the message... + */ + +#ifdef AF_INET6 + if (address->addr.sa_family == AF_INET6) + address->ipv6.sin6_port = htons(CUPS_SNMP_PORT); + else +#endif /* AF_INET6 */ + address->ipv4.sin_port = htons(CUPS_SNMP_PORT); + + return (sendto(fd, buffer, bytes, 0, (void *)address, + httpAddrLength(address)) == bytes); +} + + +/* + * 'asn1_decode_snmp()' - Decode a SNMP packet. + */ + +static int /* O - 0 on success, -1 on error */ +asn1_decode_snmp(unsigned char *buffer, /* I - Buffer */ + size_t len, /* I - Size of buffer */ + cups_snmp_t *packet) /* I - SNMP packet */ +{ + unsigned char *bufptr, /* Pointer into the data */ + *bufend; /* End of data */ + int length; /* Length of value */ + + + /* + * Initialize the decoding... + */ + + memset(packet, 0, sizeof(cups_snmp_t)); + + bufptr = buffer; + bufend = buffer + len; + + if (asn1_get_type(&bufptr, bufend) != CUPS_ASN1_SEQUENCE) + snmp_set_error(packet, _("Packet does not start with SEQUENCE")); + else if (asn1_get_length(&bufptr, bufend) == 0) + snmp_set_error(packet, _("SEQUENCE uses indefinite length")); + else if (asn1_get_type(&bufptr, bufend) != CUPS_ASN1_INTEGER) + snmp_set_error(packet, _("No version number")); + else if ((length = asn1_get_length(&bufptr, bufend)) == 0) + snmp_set_error(packet, _("Version uses indefinite length")); + else if ((packet->version = asn1_get_integer(&bufptr, bufend, length)) + != CUPS_SNMP_VERSION_1) + snmp_set_error(packet, _("Bad SNMP version number")); + else if (asn1_get_type(&bufptr, bufend) != CUPS_ASN1_OCTET_STRING) + snmp_set_error(packet, _("No community name")); + else if ((length = asn1_get_length(&bufptr, bufend)) == 0) + snmp_set_error(packet, _("Community name uses indefinite length")); + else + { + asn1_get_string(&bufptr, bufend, length, packet->community, + sizeof(packet->community)); + + if ((packet->request_type = asn1_get_type(&bufptr, bufend)) + != CUPS_ASN1_GET_RESPONSE) + snmp_set_error(packet, _("Packet does not contain a Get-Response-PDU")); + else if (asn1_get_length(&bufptr, bufend) == 0) + snmp_set_error(packet, _("Get-Response-PDU uses indefinite length")); + else if (asn1_get_type(&bufptr, bufend) != CUPS_ASN1_INTEGER) + snmp_set_error(packet, _("No request-id")); + else if ((length = asn1_get_length(&bufptr, bufend)) == 0) + snmp_set_error(packet, _("request-id uses indefinite length")); + else + { + packet->request_id = asn1_get_integer(&bufptr, bufend, length); + + if (asn1_get_type(&bufptr, bufend) != CUPS_ASN1_INTEGER) + snmp_set_error(packet, _("No error-status")); + else if ((length = asn1_get_length(&bufptr, bufend)) == 0) + snmp_set_error(packet, _("error-status uses indefinite length")); + else + { + packet->error_status = asn1_get_integer(&bufptr, bufend, length); + + if (asn1_get_type(&bufptr, bufend) != CUPS_ASN1_INTEGER) + snmp_set_error(packet, _("No error-index")); + else if ((length = asn1_get_length(&bufptr, bufend)) == 0) + snmp_set_error(packet, _("error-index uses indefinite length")); + else + { + packet->error_index = asn1_get_integer(&bufptr, bufend, length); + + if (asn1_get_type(&bufptr, bufend) != CUPS_ASN1_SEQUENCE) + snmp_set_error(packet, _("No variable-bindings SEQUENCE")); + else if (asn1_get_length(&bufptr, bufend) == 0) + snmp_set_error(packet, + _("variable-bindings uses indefinite length")); + else if (asn1_get_type(&bufptr, bufend) != CUPS_ASN1_SEQUENCE) + snmp_set_error(packet, _("No VarBind SEQUENCE")); + else if (asn1_get_length(&bufptr, bufend) == 0) + snmp_set_error(packet, _("VarBind uses indefinite length")); + else if (asn1_get_type(&bufptr, bufend) != CUPS_ASN1_OID) + snmp_set_error(packet, _("No name OID")); + else if ((length = asn1_get_length(&bufptr, bufend)) == 0) + snmp_set_error(packet, _("Name OID uses indefinite length")); + else + { + asn1_get_oid(&bufptr, bufend, length, packet->object_name, + CUPS_SNMP_MAX_OID); + + packet->object_type = asn1_get_type(&bufptr, bufend); + + if ((length = asn1_get_length(&bufptr, bufend)) == 0 && + packet->object_type != CUPS_ASN1_NULL_VALUE && + packet->object_type != CUPS_ASN1_OCTET_STRING) + snmp_set_error(packet, _("Value uses indefinite length")); + else + { + switch (packet->object_type) + { + case CUPS_ASN1_BOOLEAN : + packet->object_value.boolean = + asn1_get_integer(&bufptr, bufend, length); + break; + + case CUPS_ASN1_INTEGER : + packet->object_value.integer = + asn1_get_integer(&bufptr, bufend, length); + break; + + case CUPS_ASN1_NULL_VALUE : + break; + + case CUPS_ASN1_OCTET_STRING : + asn1_get_string(&bufptr, bufend, length, + packet->object_value.string, + CUPS_SNMP_MAX_STRING); + break; + + case CUPS_ASN1_OID : + asn1_get_oid(&bufptr, bufend, length, + packet->object_value.oid, CUPS_SNMP_MAX_OID); + break; + + case CUPS_ASN1_COUNTER : + packet->object_value.counter = + asn1_get_integer(&bufptr, bufend, length); + break; + + case CUPS_ASN1_GAUGE : + packet->object_value.gauge = + asn1_get_integer(&bufptr, bufend, length); + break; + + default : + snmp_set_error(packet, _("Unsupported value type")); + break; + } + } + } + } + } + } + } + + return (packet->error ? -1 : 0); +} + + +/* + * 'asn1_debug()' - Decode an ASN1-encoded message. + */ + +static void +asn1_debug(const char *prefix, /* I - Prefix string */ + unsigned char *buffer, /* I - Buffer */ + size_t len, /* I - Length of buffer */ + int indent) /* I - Indentation */ +{ + int i; /* Looping var */ + unsigned char *bufend; /* End of buffer */ + int integer; /* Number value */ + int oid[CUPS_SNMP_MAX_OID]; /* OID value */ + char string[CUPS_SNMP_MAX_STRING]; + /* String value */ + unsigned char value_type; /* Type of value */ + int value_length; /* Length of value */ + _cups_globals_t *cg = _cupsGlobals(); /* Global data */ + + + if (cg->snmp_debug <= 0) + return; + + bufend = buffer + len; + + while (buffer < bufend) + { + /* + * Get value type... + */ + + value_type = asn1_get_type(&buffer, bufend); + value_length = asn1_get_length(&buffer, bufend); + + switch (value_type) + { + case CUPS_ASN1_BOOLEAN : + integer = asn1_get_integer(&buffer, bufend, value_length); + + fprintf(stderr, "%s%*sBOOLEAN %d bytes %d\n", prefix, indent, "", + value_length, integer); + break; + + case CUPS_ASN1_INTEGER : + integer = asn1_get_integer(&buffer, bufend, value_length); + + fprintf(stderr, "%s%*sINTEGER %d bytes %d\n", prefix, indent, "", + value_length, integer); + break; + + case CUPS_ASN1_OCTET_STRING : + fprintf(stderr, "%s%*sOCTET STRING %d bytes \"%s\"\n", prefix, + indent, "", value_length, + asn1_get_string(&buffer, bufend, value_length, string, + sizeof(string))); + break; + + case CUPS_ASN1_NULL_VALUE : + fprintf(stderr, "%s%*sNULL VALUE %d bytes\n", prefix, indent, "", + value_length); + + buffer += value_length; + break; + + case CUPS_ASN1_OID : + asn1_get_oid(&buffer, bufend, value_length, oid, CUPS_SNMP_MAX_OID); + + fprintf(stderr, "%s%*sOID %d bytes ", prefix, indent, "", + value_length); + for (i = 0; oid[i]; i ++) + fprintf(stderr, ".%d", oid[i]); + putc('\n', stderr); + break; + + case CUPS_ASN1_SEQUENCE : + fprintf(stderr, "%s%*sSEQUENCE %d bytes\n", prefix, indent, "", + value_length); + asn1_debug(prefix, buffer, value_length, indent + 4); + + buffer += value_length; + break; + + case CUPS_ASN1_GET_REQUEST : + fprintf(stderr, "%s%*sGet-Request-PDU %d bytes\n", prefix, indent, "", + value_length); + asn1_debug(prefix, buffer, value_length, indent + 4); + + buffer += value_length; + break; + + case CUPS_ASN1_GET_RESPONSE : + fprintf(stderr, "%s%*sGet-Response-PDU %d bytes\n", prefix, indent, + "", value_length); + asn1_debug(prefix, buffer, value_length, indent + 4); + + buffer += value_length; + break; + + default : + fprintf(stderr, "%s%*sUNKNOWN(%x) %d bytes\n", prefix, indent, "", + value_type, value_length); + + buffer += value_length; + break; + } + } +} + + +/* + * 'asn1_encode_snmp()' - Encode a SNMP packet. + */ + +static int /* O - Length on success, -1 on error */ +asn1_encode_snmp(unsigned char *buffer, /* I - Buffer */ + size_t bufsize, /* I - Size of buffer */ + cups_snmp_t *packet) /* I - SNMP packet */ +{ + unsigned char *bufptr; /* Pointer into buffer */ + int total, /* Total length */ + msglen, /* Length of entire message */ + commlen, /* Length of community string */ + reqlen, /* Length of request */ + listlen, /* Length of variable list */ + varlen, /* Length of variable */ + namelen, /* Length of object name OID */ + valuelen; /* Length of object value */ + + + /* + * Get the lengths of the community string, OID, and message... + */ + + namelen = asn1_size_oid(packet->object_name); + + switch (packet->object_type) + { + case CUPS_ASN1_NULL_VALUE : + valuelen = 0; + break; + + case CUPS_ASN1_BOOLEAN : + valuelen = asn1_size_integer(packet->object_value.boolean); + break; + + case CUPS_ASN1_INTEGER : + valuelen = asn1_size_integer(packet->object_value.integer); + break; + + case CUPS_ASN1_OCTET_STRING : + valuelen = strlen(packet->object_value.string); + break; + + case CUPS_ASN1_OID : + valuelen = asn1_size_oid(packet->object_value.oid); + break; + + default : + packet->error = "Unknown object type"; + return (-1); + } + + varlen = 1 + asn1_size_length(namelen) + namelen + + 1 + asn1_size_length(valuelen) + valuelen; + listlen = 1 + asn1_size_length(varlen) + varlen; + reqlen = 2 + asn1_size_integer(packet->request_id) + + 2 + asn1_size_integer(packet->error_status) + + 2 + asn1_size_integer(packet->error_index) + + 1 + asn1_size_length(listlen) + listlen; + commlen = strlen(packet->community); + msglen = 2 + asn1_size_integer(packet->version) + + 1 + asn1_size_length(commlen) + commlen + + 1 + asn1_size_length(reqlen) + reqlen; + total = 1 + asn1_size_length(msglen) + msglen; + + if (total > bufsize) + { + packet->error = "Message too large for buffer"; + return (-1); + } + + /* + * Then format the message... + */ + + bufptr = buffer; + + *bufptr++ = CUPS_ASN1_SEQUENCE; /* SNMPv1 message header */ + asn1_set_length(&bufptr, msglen); + + asn1_set_integer(&bufptr, packet->version); + /* version */ + + *bufptr++ = CUPS_ASN1_OCTET_STRING; /* community */ + asn1_set_length(&bufptr, commlen); + memcpy(bufptr, packet->community, commlen); + bufptr += commlen; + + *bufptr++ = packet->request_type; /* Get-Request-PDU */ + asn1_set_length(&bufptr, reqlen); + + asn1_set_integer(&bufptr, packet->request_id); + + asn1_set_integer(&bufptr, packet->error_status); + + asn1_set_integer(&bufptr, packet->error_index); + + *bufptr++ = CUPS_ASN1_SEQUENCE; /* variable-bindings */ + asn1_set_length(&bufptr, listlen); + + *bufptr++ = CUPS_ASN1_SEQUENCE; /* variable */ + asn1_set_length(&bufptr, varlen); + + asn1_set_oid(&bufptr, packet->object_name); + /* ObjectName */ + + switch (packet->object_type) + { + case CUPS_ASN1_NULL_VALUE : + *bufptr++ = CUPS_ASN1_NULL_VALUE; + /* ObjectValue */ + *bufptr++ = 0; /* Length */ + break; + + case CUPS_ASN1_BOOLEAN : + asn1_set_integer(&bufptr, packet->object_value.boolean); + break; + + case CUPS_ASN1_INTEGER : + asn1_set_integer(&bufptr, packet->object_value.integer); + break; + + case CUPS_ASN1_OCTET_STRING : + *bufptr++ = CUPS_ASN1_OCTET_STRING; + asn1_set_length(&bufptr, valuelen); + memcpy(bufptr, packet->object_value.string, valuelen); + bufptr += valuelen; + break; + + case CUPS_ASN1_OID : + asn1_set_oid(&bufptr, packet->object_value.oid); + break; + + default : + break; + } + + return (bufptr - buffer); +} + + +/* + * 'asn1_get_integer()' - Get an integer value. + */ + +static int /* O - Integer value */ +asn1_get_integer( + unsigned char **buffer, /* IO - Pointer in buffer */ + unsigned char *bufend, /* I - End of buffer */ + int length) /* I - Length of value */ +{ + int value; /* Integer value */ + + + for (value = 0; + length > 0 && *buffer < bufend; + length --, (*buffer) ++) + value = (value << 8) | **buffer; + + return (value); +} + + +/* + * 'asn1_get_length()' - Get a value length. + */ + +static int /* O - Length */ +asn1_get_length(unsigned char **buffer, /* IO - Pointer in buffer */ + unsigned char *bufend) /* I - End of buffer */ +{ + int length; /* Length */ + + + length = **buffer; + (*buffer) ++; + + if (length & 128) + length = asn1_get_integer(buffer, bufend, length & 127); + + return (length); +} + + +/* + * 'asn1_get_oid()' - Get an OID value. + */ + +static int /* O - Last OID number */ +asn1_get_oid( + unsigned char **buffer, /* IO - Pointer in buffer */ + unsigned char *bufend, /* I - End of buffer */ + int length, /* I - Length of value */ + int *oid, /* I - OID buffer */ + int oidsize) /* I - Size of OID buffer */ +{ + unsigned char *valend; /* End of value */ + int *oidend; /* End of OID buffer */ + int number; /* OID number */ + + + valend = *buffer + length; + oidend = oid + oidsize - 1; + + if (valend > bufend) + valend = bufend; + + number = asn1_get_packed(buffer, bufend); + + if (number < 80) + { + *oid++ = number / 40; + number = number % 40; + *oid++ = number; + } + else + { + *oid++ = 2; + number -= 80; + *oid++ = number; + } + + while (*buffer < valend) + { + number = asn1_get_packed(buffer, bufend); + + if (oid < oidend) + *oid++ = number; + } + + *oid = 0; + + return (number); +} + + +/* + * 'asn1_get_packed()' - Get a packed integer value. + */ + +static int /* O - Value */ +asn1_get_packed( + unsigned char **buffer, /* IO - Pointer in buffer */ + unsigned char *bufend) /* I - End of buffer */ +{ + int value; /* Value */ + + + value = 0; + + while ((**buffer & 128) && *buffer < bufend) + { + value = (value << 7) | (**buffer & 127); + (*buffer) ++; + } + + if (*buffer < bufend) + { + value = (value << 7) | **buffer; + (*buffer) ++; + } + + return (value); +} + + +/* + * 'asn1_get_string()' - Get a string value. + */ + +static char * /* O - String */ +asn1_get_string( + unsigned char **buffer, /* IO - Pointer in buffer */ + unsigned char *bufend, /* I - End of buffer */ + int length, /* I - Value length */ + char *string, /* I - String buffer */ + int strsize) /* I - String buffer size */ +{ + if (length < 0) + { + /* + * Disallow negative lengths! + */ + + *string = '\0'; + } + else if (length < strsize) + { + /* + * String is smaller than the buffer... + */ + + if (length > 0) + memcpy(string, *buffer, length); + + string[length] = '\0'; + } + else + { + /* + * String is larger than the buffer... + */ + + memcpy(string, *buffer, strsize - 1); + string[strsize - 1] = '\0'; + } + + if (length > 0) + (*buffer) += length; + + return (length < 0 ? NULL : string); +} + + +/* + * 'asn1_get_type()' - Get a value type. + */ + +static int /* O - Type */ +asn1_get_type(unsigned char **buffer, /* IO - Pointer in buffer */ + unsigned char *bufend) /* I - End of buffer */ +{ + int type; /* Type */ + + + type = **buffer; + (*buffer) ++; + + if ((type & 31) == 31) + type = asn1_get_packed(buffer, bufend); + + return (type); +} + + +/* + * 'asn1_set_integer()' - Set an integer value. + */ + +static void +asn1_set_integer(unsigned char **buffer,/* IO - Pointer in buffer */ + int integer) /* I - Integer value */ +{ + **buffer = CUPS_ASN1_INTEGER; + (*buffer) ++; + + if (integer > 0x7fffff || integer < -0x800000) + { + **buffer = 4; + (*buffer) ++; + **buffer = integer >> 24; + (*buffer) ++; + **buffer = integer >> 16; + (*buffer) ++; + **buffer = integer >> 8; + (*buffer) ++; + **buffer = integer; + (*buffer) ++; + } + else if (integer > 0x7fff || integer < -0x8000) + { + **buffer = 3; + (*buffer) ++; + **buffer = integer >> 16; + (*buffer) ++; + **buffer = integer >> 8; + (*buffer) ++; + **buffer = integer; + (*buffer) ++; + } + else if (integer > 0x7f || integer < -0x80) + { + **buffer = 2; + (*buffer) ++; + **buffer = integer >> 8; + (*buffer) ++; + **buffer = integer; + (*buffer) ++; + } + else + { + **buffer = 1; + (*buffer) ++; + **buffer = integer; + (*buffer) ++; + } +} + + +/* + * 'asn1_set_length()' - Set a value length. + */ + +static void +asn1_set_length(unsigned char **buffer, /* IO - Pointer in buffer */ + int length) /* I - Length value */ +{ + if (length > 255) + { + **buffer = 0x82; /* 2-byte length */ + (*buffer) ++; + **buffer = length >> 8; + (*buffer) ++; + **buffer = length; + (*buffer) ++; + } + else if (length > 127) + { + **buffer = 0x81; /* 1-byte length */ + (*buffer) ++; + **buffer = length; + (*buffer) ++; + } + else + { + **buffer = length; /* Length */ + (*buffer) ++; + } +} + + +/* + * 'asn1_set_oid()' - Set an OID value. + */ + +static void +asn1_set_oid(unsigned char **buffer, /* IO - Pointer in buffer */ + const int *oid) /* I - OID value */ +{ + **buffer = CUPS_ASN1_OID; + (*buffer) ++; + + asn1_set_length(buffer, asn1_size_oid(oid)); + + asn1_set_packed(buffer, oid[0] * 40 + oid[1]); + + for (oid += 2; *oid; oid ++) + asn1_set_packed(buffer, *oid); +} + + +/* + * 'asn1_set_packed()' - Set a packed integer value. + */ + +static void +asn1_set_packed(unsigned char **buffer, /* IO - Pointer in buffer */ + int integer) /* I - Integer value */ +{ + if (integer > 0xfffffff) + { + **buffer = (integer >> 28) & 0x7f; + (*buffer) ++; + } + + if (integer > 0x1fffff) + { + **buffer = (integer >> 21) & 0x7f; + (*buffer) ++; + } + + if (integer > 0x3fff) + { + **buffer = (integer >> 14) & 0x7f; + (*buffer) ++; + } + + if (integer > 0x7f) + { + **buffer = (integer >> 7) & 0x7f; + (*buffer) ++; + } + + **buffer = integer & 0x7f; + (*buffer) ++; +} + + +/* + * 'asn1_size_integer()' - Figure out the number of bytes needed for an + * integer value. + */ + +static int /* O - Size in bytes */ +asn1_size_integer(int integer) /* I - Integer value */ +{ + if (integer > 0x7fffff || integer < -0x800000) + return (4); + else if (integer > 0x7fff || integer < -0x8000) + return (3); + else if (integer > 0x7f || integer < -0x80) + return (2); + else + return (1); +} + + +/* + * 'asn1_size_length()' - Figure out the number of bytes needed for a + * length value. + */ + +static int /* O - Size in bytes */ +asn1_size_length(int length) /* I - Length value */ +{ + if (length > 0xff) + return (3); + else if (length > 0x7f) + return (2); + else + return (1); +} + + +/* + * 'asn1_size_oid()' - Figure out the numebr of bytes needed for an + * OID value. + */ + +static int /* O - Size in bytes */ +asn1_size_oid(const int *oid) /* I - OID value */ +{ + int length; /* Length of value */ + + + for (length = asn1_size_packed(oid[0] * 40 + oid[1]), oid += 2; *oid; oid ++) + length += asn1_size_packed(*oid); + + return (length); +} + + +/* + * 'asn1_size_packed()' - Figure out the number of bytes needed for a + * packed integer value. + */ + +static int /* O - Size in bytes */ +asn1_size_packed(int integer) /* I - Integer value */ +{ + if (integer > 0xfffffff) + return (5); + else if (integer > 0x1fffff) + return (4); + else if (integer > 0x3fff) + return (3); + else if (integer > 0x7f) + return (2); + else + return (1); +} + + +/* + * 'snmp_set_error()' - Set the localized error for a packet. + */ + +static void +snmp_set_error(cups_snmp_t *packet, /* I - Packet */ + const char *message) /* I - Error message */ +{ + _cups_globals_t *cg = _cupsGlobals(); /* Global data */ + + + if (!cg->lang_default) + cg->lang_default = cupsLangDefault(); + + packet->error = _cupsLangString(cg->lang_default, message); +} + + +/* + * End of "$Id$". + */ diff --git a/cups/snmp.h b/cups/snmp.h new file mode 100644 index 000000000..b0a9703be --- /dev/null +++ b/cups/snmp.h @@ -0,0 +1,121 @@ +/* + * "$Id$" + * + * SNMP definitions for the Common UNIX Printing System (CUPS). + * + * Copyright 2007-2008 by Apple Inc. + * Copyright 2006-2007 by Easy Software Products, all rights reserved. + * + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * "LICENSE" which should have been included with this file. If this + * file is missing or damaged, see the license at "http://www.cups.org/". + * + * This file is subject to the Apple OS-Developed Software exception. + */ + +#ifndef _CUPS_SNMP_H_ +# define _CUPS_SNMP_H_ + + +/* + * Include necessary headers. + */ + +#include "http.h" + + +/* + * Constants... + */ + +#define CUPS_SNMP_PORT 161 /* SNMP well-known port */ +#define CUPS_SNMP_MAX_OID 128 /* Maximum number of OID numbers */ +#define CUPS_SNMP_MAX_PACKET 1472 /* Maximum size of SNMP packet */ +#define CUPS_SNMP_MAX_STRING 512 /* Maximum size of string */ +#define CUPS_SNMP_VERSION_1 0 /* SNMPv1 */ + + +/* + * Types... + */ + +typedef enum cups_asn1_e /**** ASN1 request/object types ****/ +{ + CUPS_ASN1_END_OF_CONTENTS = 0x00, /* End-of-contents */ + CUPS_ASN1_BOOLEAN = 0x01, /* BOOLEAN */ + CUPS_ASN1_INTEGER = 0x02, /* INTEGER or ENUMERATION */ + CUPS_ASN1_BIT_STRING = 0x03, /* BIT STRING */ + CUPS_ASN1_OCTET_STRING = 0x04, /* OCTET STRING */ + CUPS_ASN1_NULL_VALUE = 0x05, /* NULL VALUE */ + CUPS_ASN1_OID = 0x06, /* OBJECT IDENTIFIER */ + CUPS_ASN1_SEQUENCE = 0x30, /* SEQUENCE */ + CUPS_ASN1_APPLICATION = 0x40, /* Application-specific bit */ + CUPS_ASN1_COUNTER = 0x41, /* 32-bit unsigned aka Counter32 */ + CUPS_ASN1_GAUGE = 0x42, /* 32-bit unsigned aka Gauge32 */ + CUPS_ASN1_GET_REQUEST = 0xa0, /* GetRequest-PDU */ + CUPS_ASN1_GET_NEXT_REQUEST = 0xa1, /* GetNextRequest-PDU */ + CUPS_ASN1_GET_RESPONSE = 0xa2 /* GetResponse-PDU */ +} cups_asn1_t; + +typedef struct cups_snmp_s /**** SNMP data packet ****/ +{ + const char *error; /* Encode/decode error */ + http_addr_t address; /* Source address */ + int version; /* Version number */ + char community[CUPS_SNMP_MAX_STRING]; + /* Community name */ + cups_asn1_t request_type; /* Request type */ + int request_id; /* request-id value */ + int error_status; /* error-status value */ + int error_index; /* error-index value */ + int object_name[CUPS_SNMP_MAX_OID]; + /* object-name value */ + cups_asn1_t object_type; /* object-value type */ + union + { + int boolean; /* Boolean value */ + int integer; /* Integer value */ + unsigned counter; /* Counter value */ + unsigned gauge; /* Gauge value */ + int oid[CUPS_SNMP_MAX_OID]; /* OID value */ + char string[CUPS_SNMP_MAX_STRING];/* String value */ + } object_value; /* object-value value */ +} cups_snmp_t; + + +/* + * Prototypes... + */ + +# ifdef __cplusplus +extern "C" { +# endif /* __cplusplus */ + +extern void cupsSNMPClose(int fd) _CUPS_API_1_4; +extern int *cupsSNMPCopyOID(int *dst, const int *src, int dstsize) + _CUPS_API_1_4; +extern int cupsSNMPIsOID(cups_snmp_t *packet, const int *oid) + _CUPS_API_1_4; +extern int cupsSNMPIsOIDPrefixed(cups_snmp_t *packet, + const int *prefix) _CUPS_API_1_4; +extern int cupsSNMPOpen(void) _CUPS_API_1_4; +extern cups_snmp_t *cupsSNMPRead(int fd, cups_snmp_t *packet, int msec) + _CUPS_API_1_4; +extern void cupsSNMPSetDebug(int level) _CUPS_API_1_4; +extern int cupsSNMPWrite(int fd, http_addr_t *addr, int version, + const char *community, + cups_asn1_t request_type, + const unsigned request_id, + const int *oid) _CUPS_API_1_4; + +# ifdef __cplusplus +} +# endif /* __cplusplus */ +#endif /* !_CUPS_SNMP_H_ */ + + +/* + * End of "$Id$". + */ diff --git a/cups/testcups.c b/cups/testcups.c index 68785d035..1ac4456bd 100644 --- a/cups/testcups.c +++ b/cups/testcups.c @@ -157,6 +157,7 @@ main(int argc, /* I - Number of command-line arguments */ { status = 1; puts("FAIL"); + return (1); } else puts("PASS"); diff --git a/cups/testsnmp.c b/cups/testsnmp.c new file mode 100644 index 000000000..7a3ccfc77 --- /dev/null +++ b/cups/testsnmp.c @@ -0,0 +1,224 @@ +/* + * "$Id$" + * + * SNMP test program for the Common UNIX Printing System (CUPS). + * + * Copyright 2008 by Apple Inc. + * + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". + * + * This file is subject to the Apple OS-Developed Software exception. + * + * Contents: + * + * main() - Main entry. + */ + +/* + * Include necessary headers... + */ + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include "string.h" +#include "snmp.h" + + +/* + * Local functions... + */ + +static int *scan_oid(char *s, int *oid, int oidsize); +static int show_oid(int fd, char *s, http_addr_t *addr); + + +/* + * 'main()' - Main entry. + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line args */ + char *argv[]) /* I - Command-line arguments */ +{ + int i; /* Looping var */ + int fd; /* SNMP socket */ + http_addrlist_t *host; /* Address of host */ + + + if (argc < 2) + { + puts("Usage: ./testsnmp host-or-ip"); + return (1); + } + + if ((host = httpAddrGetList(argv[1], AF_UNSPEC, "161")) == NULL) + { + printf("Unable to find \"%s\"!\n", argv[1]); + return (1); + } + + fputs("cupsSNMPOpen: ", stdout); + + if ((fd = cupsSNMPOpen()) < 0) + { + printf("FAIL (%s)\n", strerror(errno)); + return (1); + } + + puts("PASS"); + + if (argc > 2) + { + /* + * Query OIDs from the command-line... + */ + + for (i = 2; i < argc; i ++) + if (!show_oid(fd, argv[i], &(host->addr))) + return (1); + } + else if (!show_oid(fd, (char *)"1.3.6.1.2.1.43.10.2.1.4.1.1", &(host->addr))) + return (1); + + return (0); +} + + +/* + * 'scan_oid()' - Scan an OID value. + */ + +static int * /* O - OID or NULL on error */ +scan_oid(char *s, /* I - OID string */ + int *oid, /* I - OID array */ + int oidsize) /* I - Size of OID array in integers */ +{ + int i; /* Index into OID array */ + char *ptr; /* Pointer into string */ + + + for (ptr = s, i = 0, oidsize --; ptr && *ptr && i < oidsize; i ++) + { + if (!isdigit(*ptr & 255)) + return (NULL); + + oid[i] = strtol(ptr, &ptr, 10); + if (*ptr == '.') + ptr ++; + } + + if (i >= oidsize) + return (NULL); + + oid[i] = 0; + + return (oid); +} + + +/* + * 'show_oid()' - Show the specified OID. + */ + +static int /* O - 1 on success, 0 on error */ +show_oid(int fd, /* I - SNMP socket */ + char *s, /* I - OID to query */ + http_addr_t *addr) /* I - Address to query */ +{ + int i; /* Looping var */ + int oid[255]; /* OID */ + cups_snmp_t packet; /* SNMP packet */ + + + printf("cupsSNMPWrite(%s): ", s); + + if (!scan_oid(s, oid, sizeof(oid) / sizeof(oid[0]))) + { + puts("FAIL (bad OID)"); + return (0); + } + + if (!cupsSNMPWrite(fd, addr, CUPS_SNMP_VERSION_1, "public", + CUPS_ASN1_GET_REQUEST, 1, oid)) + { + puts("FAIL"); + return (0); + } + + puts("PASS"); + + fputs("cupsSNMPRead(5000): ", stdout); + + if (!cupsSNMPRead(fd, &packet, 5000)) + { + puts("FAIL (timeout)"); + return (0); + } + + if (!cupsSNMPIsOID(&packet, oid)) + { + puts("FAIL (bad OID)"); + return (0); + } + + if (packet.error) + { + printf("FAIL (%s)\n", packet.error); + return (0); + } + + switch (packet.object_type) + { + case CUPS_ASN1_BOOLEAN : + printf("PASS (BOOLEAN %s)\n", + packet.object_value.boolean ? "TRUE" : "FALSE"); + break; + + case CUPS_ASN1_INTEGER : + printf("PASS (INTEGER %d)\n", packet.object_value.integer); + break; + + case CUPS_ASN1_BIT_STRING : + printf("PASS (BIT-STRING \"%s\")\n", packet.object_value.string); + break; + + case CUPS_ASN1_OCTET_STRING : + printf("PASS (OCTET-STRING \"%s\")\n", packet.object_value.string); + break; + + case CUPS_ASN1_NULL_VALUE : + puts("PASS (NULL-VALUE)"); + break; + + case CUPS_ASN1_OID : + printf("PASS (OID %d", packet.object_value.oid[0]); + for (i = 1; packet.object_value.oid[i]; i ++) + printf(".%d", packet.object_value.oid[i]); + puts(")"); + break; + + case CUPS_ASN1_COUNTER : + printf("PASS (Counter %d)\n", packet.object_value.counter); + break; + + case CUPS_ASN1_GAUGE: + printf("PASS (Gauge %u)\n", packet.object_value.gauge); + break; + + default : + printf("PASS (Unknown-%X)\n", packet.object_type); + break; + } + + return (1); +} + + +/* + * End of "$Id$". + */ diff --git a/cups/transcode.c b/cups/transcode.c index aab841642..036106edc 100644 --- a/cups/transcode.c +++ b/cups/transcode.c @@ -3,7 +3,7 @@ * * Transcoding support for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1997-2007 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -132,8 +132,6 @@ _cupsCharmapFlush(void) vnext = vmap->next; free_vbcs_charmap(vmap); - - free(vmap); } vmap_cache = NULL; @@ -330,13 +328,8 @@ cupsCharsetToUTF8( if (encoding < CUPS_ENCODING_SBCS_END) bytes = conv_sbcs_to_utf8(dest, (cups_sbcs_t *)src, maxout, encoding); - else if (encoding < CUPS_ENCODING_VBCS_END) - bytes = conv_vbcs_to_utf8(dest, (cups_sbcs_t *)src, maxout, encoding); else - { - DEBUG_puts(" Bad encoding, returning -1"); - bytes = -1; - } + bytes = conv_vbcs_to_utf8(dest, (cups_sbcs_t *)src, maxout, encoding); #ifdef HAVE_PTHREAD_H pthread_mutex_unlock(&map_mutex); @@ -437,10 +430,8 @@ cupsUTF8ToCharset( if (encoding < CUPS_ENCODING_SBCS_END) bytes = conv_utf8_to_sbcs((cups_sbcs_t *)dest, src, maxout, encoding); - else if (encoding < CUPS_ENCODING_VBCS_END) - bytes = conv_utf8_to_vbcs((cups_sbcs_t *)dest, src, maxout, encoding); else - bytes = -1; + bytes = conv_utf8_to_vbcs((cups_sbcs_t *)dest, src, maxout, encoding); #ifdef HAVE_PTHREAD_H pthread_mutex_unlock(&map_mutex); @@ -1468,6 +1459,8 @@ get_vbcs_charmap( { DEBUG_puts(" Unable to get charmap count!"); + cupsFileClose(fp); + return (NULL); } @@ -1479,9 +1472,10 @@ get_vbcs_charmap( if ((vmap = (_cups_vmap_t *)calloc(1, sizeof(_cups_vmap_t))) == NULL) { - cupsFileClose(fp); DEBUG_puts(" Unable to allocate memory!"); + cupsFileClose(fp); + return (NULL); } diff --git a/cups/util.c b/cups/util.c index 33ba35053..6dea98085 100644 --- a/cups/util.c +++ b/cups/util.c @@ -984,9 +984,6 @@ cupsGetPPD3(http_t *http, /* I - HTTP connection or CUPS_HTTP_DEFAULT */ close(fd); - if (http2 != http) - httpClose(http2); - /* * See if we actually got the file or an error... */ @@ -1015,6 +1012,9 @@ cupsGetPPD3(http_t *http, /* I - HTTP connection or CUPS_HTTP_DEFAULT */ unlink(cg->ppd_filename); } + if (http2 != http) + httpClose(http2); + /* * Return the PPD file... */ diff --git a/filter/Makefile b/filter/Makefile index 0833cf6cb..f0691fc72 100644 --- a/filter/Makefile +++ b/filter/Makefile @@ -3,7 +3,7 @@ # # Filter makefile for the Common UNIX Printing System (CUPS). # -# Copyright 2007 by Apple Inc. +# Copyright 2007-2008 by Apple Inc. # Copyright 1997-2006 by Easy Software Products. # # These coded instructions, statements, and computer programs are the @@ -19,7 +19,7 @@ include ../Makedefs FILTERS = gziptoany hpgltops texttops pstops $(IMGFILTERS) \ - rastertolabel rastertoepson rastertohp + $(PDFTOPS) rastertolabel rastertoepson rastertohp TARGETS = $(FILTERS) \ $(LIBCUPSIMAGE) \ libcupsimage.a \ @@ -39,7 +39,8 @@ IMAGE32OBJS = $(IMAGEOBJS:.o=.32.o) IMAGE64OBJS = $(IMAGEOBJS:.o=.64.o) FORMOBJS = form-attr.o form-main.o form-ps.o form-text.o form-tree.o OBJS = $(HPGLOBJS) $(IMAGEOBJS) $(FORMOBJS) \ - gziptoany.o imagetops.o imagetoraster.o common.o pstops.o \ + gziptoany.o imagetops.o imagetoraster.o common.o \ + pdftops.o pstops.o \ rasterbench.o rastertoepson.o rastertohp.o rastertolabel.o \ testimage.o testraster.o textcommon.o texttops.o @@ -324,6 +325,15 @@ pstops: pstops.o common.o ../cups/$(LIBCUPS) # +# pdftops +# + +pdftops: pdftops.o common.o ../cups/$(LIBCUPS) + echo Linking $@... + $(CC) $(LDFLAGS) -o $@ pdftops.o common.o $(LIBS) + + +# # rastertolabel # diff --git a/filter/hpgl-input.c b/filter/hpgl-input.c index 54c99917f..d9af61a3c 100644 --- a/filter/hpgl-input.c +++ b/filter/hpgl-input.c @@ -3,7 +3,7 @@ * * HP-GL/2 input processing for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1993-2006 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -48,6 +48,7 @@ ParseCommand(FILE *fp, /* I - File to read from */ i; /* Looping var */ char buf[262144], /* String buffer */ *bufptr; /* Pointer into buffer */ + float temp; /* Temporary parameter value */ static param_t p[MAX_PARAMS]; /* Parameter buffer */ @@ -212,10 +213,10 @@ ParseCommand(FILE *fp, /* I - File to read from */ case '-' : case '+' : ungetc(ch, fp); - fscanf(fp, "%f", &(p[num_params].value.number)); - if (num_params < MAX_PARAMS) + if (fscanf(fp, "%f", &temp) == 1 && num_params < MAX_PARAMS) { - p[num_params].type = PARAM_RELATIVE; + p[num_params].type = PARAM_RELATIVE; + p[num_params].value.number = temp; num_params ++; } break; @@ -231,10 +232,10 @@ ParseCommand(FILE *fp, /* I - File to read from */ case '9' : case '.' : ungetc(ch, fp); - fscanf(fp, "%f", &(p[num_params].value.number)); - if (num_params < MAX_PARAMS) + if (fscanf(fp, "%f", &temp) == 1 && num_params < MAX_PARAMS) { - p[num_params].type = PARAM_ABSOLUTE; + p[num_params].type = PARAM_ABSOLUTE; + p[num_params].value.number = temp; num_params ++; } break; diff --git a/filter/image-bmp.c b/filter/image-bmp.c index c4b0db71e..1056252a7 100644 --- a/filter/image-bmp.c +++ b/filter/image-bmp.c @@ -3,7 +3,7 @@ * * BMP image routines for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1993-2007 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -179,9 +179,22 @@ _cupsImageReadBMP( cupsImageSetMaxTiles(img, 0); - in = malloc(img->xsize * 3); bpp = cupsImageGetDepth(img); - out = malloc(img->xsize * bpp); + + if ((in = malloc(img->xsize * 3)) == NULL) + { + fputs("DEBUG: Unable to allocate memory!\n", stderr); + fclose(fp); + return (1); + } + + if ((out = malloc(img->xsize * bpp)) == NULL) + { + fputs("DEBUG: Unable to allocate memory!\n", stderr); + free(in); + fclose(fp); + return (1); + } /* * Read the image data... diff --git a/filter/image-gif.c b/filter/image-gif.c index df8e81e4d..a391811fc 100644 --- a/filter/image-gif.c +++ b/filter/image-gif.c @@ -3,7 +3,7 @@ * * GIF image routines for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1993-2007 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -462,8 +462,14 @@ gif_read_image(FILE *fp, /* I - Input file */ pass = 0; code_size = getc(fp); + if (!pixels) + return (-1); + if (gif_read_lzw(fp, 1, code_size) < 0) + { + free(pixels); return (-1); + } temp = pixels; while ((pixel = gif_read_lzw(fp, 0, code_size)) >= 0) diff --git a/filter/image-photocd.c b/filter/image-photocd.c index 6635be7a4..6485de3f0 100644 --- a/filter/image-photocd.c +++ b/filter/image-photocd.c @@ -7,7 +7,7 @@ * is only YCC encoded. Support for the higher resolution images will * require a lot of extra code... * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1993-2006 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -99,11 +99,33 @@ _cupsImageReadPhotoCD( cupsImageSetMaxTiles(img, 0); bpp = cupsImageGetDepth(img); - in = malloc(768 * 3); - out = malloc(768 * bpp); + + if ((in = malloc(768 * 3)) == NULL) + { + fputs("DEBUG: Unable to allocate memory!\n", stderr); + fclose(fp); + return (1); + } + + if ((out = malloc(768 * bpp)) == NULL) + { + fputs("DEBUG: Unable to allocate memory!\n", stderr); + fclose(fp); + free(in); + return (1); + } if (bpp > 1) - rgb = malloc(768 * 3); + { + if ((rgb = malloc(768 * 3)) == NULL) + { + fputs("DEBUG: Unable to allocate memory!\n", stderr); + fclose(fp); + free(in); + free(out); + return (1); + } + } else rgb = NULL; @@ -141,6 +163,9 @@ _cupsImageReadPhotoCD( free(in); free(out); + if (bpp > 1) + free(rgb); + return (-1); } diff --git a/filter/image-pix.c b/filter/image-pix.c index e72fdff14..e5e20f463 100644 --- a/filter/image-pix.c +++ b/filter/image-pix.c @@ -3,7 +3,7 @@ * * Alias PIX image routines for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1993-2007 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -95,9 +95,22 @@ _cupsImageReadPIX( cupsImageSetMaxTiles(img, 0); - in = malloc(img->xsize * (depth / 8)); bpp = cupsImageGetDepth(img); - out = malloc(img->xsize * bpp); + + if ((in = malloc(img->xsize * (depth / 8))) == NULL) + { + fputs("DEBUG: Unable to allocate memory!\n", stderr); + fclose(fp); + return (1); + } + + if ((out = malloc(img->xsize * bpp)) == NULL) + { + fputs("DEBUG: Unable to allocate memory!\n", stderr); + fclose(fp); + free(in); + return (1); + } /* * Read the image data... diff --git a/filter/image-pnm.c b/filter/image-pnm.c index 1f87829d3..86615d917 100644 --- a/filter/image-pnm.c +++ b/filter/image-pnm.c @@ -3,7 +3,7 @@ * * Portable Any Map file routines for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1993-2007 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -67,7 +67,13 @@ _cupsImageReadPNM( * max sample */ - lineptr = fgets(line, sizeof(line), fp); + if ((lineptr = fgets(line, sizeof(line), fp)) == NULL) + { + fputs("DEBUG: Bad PNM header!\n", stderr); + fclose(fp); + return (1); + } + lineptr ++; format = atoi(lineptr); @@ -147,8 +153,21 @@ _cupsImageReadPNM( cupsImageSetMaxTiles(img, 0); bpp = cupsImageGetDepth(img); - in = malloc(img->xsize * 3); - out = malloc(img->xsize * bpp); + + if ((in = malloc(img->xsize * 3)) == NULL) + { + fputs("DEBUG: Unable to allocate memory!\n", stderr); + fclose(fp); + return (1); + } + + if ((out = malloc(img->xsize * bpp)) == NULL) + { + fputs("DEBUG: Unable to allocate memory!\n", stderr); + fclose(fp); + free(in); + return (1); + } /* * Read the image file... diff --git a/filter/image-sgi.c b/filter/image-sgi.c index 60c89f971..de81ceb6a 100644 --- a/filter/image-sgi.c +++ b/filter/image-sgi.c @@ -3,7 +3,7 @@ * * SGI image file routines for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1993-2007 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -77,7 +77,6 @@ _cupsImageReadSGI( fprintf(stderr, "DEBUG: Bad SGI image dimensions %ux%ux%u!\n", sgip->xsize, sgip->ysize, sgip->zsize); sgiClose(sgip); - fclose(fp); return (1); } @@ -92,10 +91,32 @@ _cupsImageReadSGI( cupsImageSetMaxTiles(img, 0); bpp = cupsImageGetDepth(img); - in = malloc(img->xsize * sgip->zsize); - out = malloc(img->xsize * bpp); - rows[0] = calloc(img->xsize * sgip->zsize, sizeof(unsigned short)); + if ((in = malloc(img->xsize * sgip->zsize)) == NULL) + { + fputs("DEBUG: Unable to allocate memory!\n", stderr); + sgiClose(sgip); + return (1); + } + + if ((out = malloc(img->xsize * bpp)) == NULL) + { + fputs("DEBUG: Unable to allocate memory!\n", stderr); + sgiClose(sgip); + free(in); + return (1); + } + + if ((rows[0] = calloc(img->xsize * sgip->zsize, + sizeof(unsigned short))) == NULL) + { + fputs("DEBUG: Unable to allocate memory!\n", stderr); + sgiClose(sgip); + free(in); + free(out); + return (1); + } + for (i = 1; i < sgip->zsize; i ++) rows[i] = rows[0] + i * img->xsize; diff --git a/filter/image-sgilib.c b/filter/image-sgilib.c index 38820b4b9..e0b1b3326 100644 --- a/filter/image-sgilib.c +++ b/filter/image-sgilib.c @@ -4,7 +4,7 @@ * SGI image file format library routines for the Common UNIX Printing * System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1993-2005 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -250,8 +250,20 @@ sgiOpenFile(FILE *file, /* I - File to open */ fseek(sgip->file, 512, SEEK_SET); - sgip->table = calloc(sgip->zsize, sizeof(long *)); - sgip->table[0] = calloc(sgip->ysize * sgip->zsize, sizeof(long)); + if ((sgip->table = calloc(sgip->zsize, sizeof(long *))) == NULL) + { + free(sgip); + return (NULL); + } + + if ((sgip->table[0] = calloc(sgip->ysize * sgip->zsize, + sizeof(long))) == NULL) + { + free(sgip->table); + free(sgip); + return (NULL); + } + for (i = 1; i < sgip->zsize; i ++) sgip->table[i] = sgip->table[0] + i * sgip->ysize; @@ -333,12 +345,39 @@ sgiOpenFile(FILE *file, /* I - File to open */ 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)); + if ((sgip->table = calloc(sgip->zsize, sizeof(long *))) == NULL) + { + free(sgip); + return (NULL); + } + + if ((sgip->table[0] = calloc(sgip->ysize * sgip->zsize, + sizeof(long))) == NULL) + { + free(sgip->table); + free(sgip); + return (NULL); + } + 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)); + + if ((sgip->length = calloc(sgip->zsize, sizeof(long *))) == NULL) + { + free(sgip->table); + free(sgip); + return (NULL); + } + + if ((sgip->length[0] = calloc(sgip->ysize * sgip->zsize, + sizeof(long))) == NULL) + { + free(sgip->length); + free(sgip->table); + free(sgip); + return (NULL); + } + for (i = 1; i < sgip->zsize; i ++) sgip->length[i] = sgip->length[0] + i * sgip->ysize; break; diff --git a/filter/image-sun.c b/filter/image-sun.c index 9120d5384..6817ecfea 100644 --- a/filter/image-sun.c +++ b/filter/image-sun.c @@ -3,7 +3,7 @@ * * Sun Raster image file routines for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1993-2007 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -152,9 +152,32 @@ _cupsImageReadSunRaster( in = malloc(img->xsize * 3 + 1); } - bpp = cupsImageGetDepth(img); - out = malloc(img->xsize * bpp); - scanline = malloc(scanwidth); + if (!in) + { + fputs("DEBUG: Unable to allocate memory!\n", stderr); + fclose(fp); + return (1); + } + + bpp = cupsImageGetDepth(img); + + if ((out = malloc(img->xsize * bpp)) == NULL) + { + fputs("DEBUG: Unable to allocate memory!\n", stderr); + fclose(fp); + free(in); + return (1); + } + + if ((scanline = malloc(scanwidth)) == NULL) + { + fputs("DEBUG: Unable to allocate memory!\n", stderr); + fclose(fp); + free(in); + free(out); + return (1); + } + run_count = 0; run_value = 0; diff --git a/filter/image.c b/filter/image.c index 9da27db69..589ba7df5 100644 --- a/filter/image.c +++ b/filter/image.c @@ -3,7 +3,7 @@ * * Base image support for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1993-2005 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -320,15 +320,10 @@ cupsImageOpen( */ if ((fp = fopen(filename, "r")) == NULL) - { -/* perror("ERROR: Unable to open image file"); -*/ return (NULL); - } + return (NULL); if (fread(header, 1, sizeof(header), fp) == 0) { -/* perror("ERROR: Unable to read image file header"); -*/ fclose(fp); return (NULL); } @@ -346,8 +341,7 @@ cupsImageOpen( if (img == NULL) { -/* perror("ERROR: Unable to allocate memory for image file"); -*/ fclose(fp); + fclose(fp); return (NULL); } @@ -401,8 +395,7 @@ cupsImageOpen( #endif /* HAVE_LIBTIFF */ else { -/* fputs("ERROR: Unknown image file format!"); -*/ fclose(fp); + fclose(fp); status = -1; } @@ -729,8 +722,11 @@ get_tile(cups_image_t *img, /* I - Image */ DEBUG_printf(("Creating tile array (%dx%d)\n", xtiles, ytiles)); - img->tiles = calloc(sizeof(cups_itile_t *), ytiles); - tile = calloc(sizeof(cups_itile_t), xtiles * ytiles); + if ((img->tiles = calloc(sizeof(cups_itile_t *), ytiles)) == NULL) + return (NULL); + + if ((tile = calloc(sizeof(cups_itile_t), xtiles * ytiles)) == NULL) + return (NULL); for (tiley = 0; tiley < ytiles; tiley ++) { @@ -751,13 +747,23 @@ get_tile(cups_image_t *img, /* I - Image */ { if (img->num_ics < img->max_ics) { - ic = calloc(sizeof(cups_ic_t) + bpp * CUPS_TILE_SIZE * - CUPS_TILE_SIZE, 1); - ic->pixels = ((cups_ib_t *)ic) + sizeof(cups_ic_t); + if ((ic = calloc(sizeof(cups_ic_t) + + bpp * CUPS_TILE_SIZE * CUPS_TILE_SIZE, 1)) == NULL) + { + if (img->num_ics == 0) + return (NULL); + + flush_tile(img); + ic = img->first; + } + else + { + ic->pixels = ((cups_ib_t *)ic) + sizeof(cups_ic_t); - img->num_ics ++; + img->num_ics ++; - DEBUG_printf(("Allocated cache tile %d (%p)...\n", img->num_ics, ic)); + DEBUG_printf(("Allocated cache tile %d (%p)...\n", img->num_ics, ic)); + } } else { diff --git a/filter/interpret.c b/filter/interpret.c index 16bb7aedd..e0db81e63 100644 --- a/filter/interpret.c +++ b/filter/interpret.c @@ -3,7 +3,7 @@ * * PPD command interpreter for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1993-2007 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -571,7 +571,7 @@ _cupsRasterExecPS( break; } - if (obj->type == CUPS_PS_OTHER) + if (obj && obj->type == CUPS_PS_OTHER) break; } diff --git a/filter/pdftops.c b/filter/pdftops.c new file mode 100644 index 000000000..7db2532f0 --- /dev/null +++ b/filter/pdftops.c @@ -0,0 +1,314 @@ +/* + * "$Id$" + * + * PDF to PostScript filter front-end for the Common UNIX Printing + * System (CUPS). + * + * Copyright 2007-2008 by Apple Inc. + * Copyright 1997-2006 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". + * + * Contents: + * + * main() - Main entry for filter... + * cancel_job() - Flag the job as canceled. + */ + +/* + * Include necessary headers... + */ + +#include <cups/cups.h> +#include <cups/string.h> +#include <cups/i18n.h> +#include <signal.h> +#include <sys/wait.h> + + +/* + * Local functions... + */ + +static void cancel_job(int sig); + + +/* + * 'main()' - Main entry for filter... + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line args */ + char *argv[]) /* I - Command-line arguments */ +{ + int fd; /* Copy file descriptor */ + char *filename, /* PDF file to convert */ + tempfile[1024]; /* Temporary file */ + char buffer[8192]; /* Copy buffer */ + int bytes; /* Bytes copied */ + int num_options; /* Number of options */ + cups_option_t *options; /* Options */ + const char *val; /* Option value */ + int orientation; /* Output orientation */ + ppd_file_t *ppd; /* PPD file */ + ppd_size_t *size; /* Current page size */ + int pdfpid, /* Process ID for pdftops */ + pdfstatus, /* Status from pdftops */ + pdfargc; /* Number of args for pdftops */ + char *pdfargv[100], /* Arguments for pdftops */ + pdfwidth[255], /* Paper width */ + pdfheight[255]; /* Paper height */ +#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) + struct sigaction action; /* Actions for POSIX signals */ +#endif /* HAVE_SIGACTION && !HAVE_SIGSET */ + + + /* + * Make sure status messages are not buffered... + */ + + setbuf(stderr, NULL); + + /* + * Make sure we have the right number of arguments for CUPS! + */ + + if (argc < 6 || argc > 7) + { + _cupsLangPrintf(stderr, + _("Usage: %s job user title copies options [filename]\n"), + argv[0]); + return (1); + } + + /* + * Register a signal handler to cleanly cancel a job. + */ + +#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ + sigset(SIGTERM, cancel_job); +#elif defined(HAVE_SIGACTION) + memset(&action, 0, sizeof(action)); + + sigemptyset(&action.sa_mask); + action.sa_handler = cancel_job; + sigaction(SIGTERM, &action, NULL); +#else + signal(SIGTERM, cancel_job); +#endif /* HAVE_SIGSET */ + + /* + * Copy stdin if needed... + */ + + if (argc == 6) + { + /* + * Copy stdin to a temp file... + */ + + if ((fd = cupsTempFd(tempfile, sizeof(tempfile))) < 0) + { + _cupsLangPrintError(_("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) + write(fd, buffer, bytes); + + close(fd); + + filename = tempfile; + } + else + { + /* + * Use the filename on the command-line... + */ + + filename = argv[6]; + tempfile[0] = '\0'; + } + + /* + * Load the PPD file and mark options... + */ + + ppd = ppdOpenFile(getenv("PPD")); + num_options = cupsParseOptions(argv[5], 0, &options); + + ppdMarkDefaults(ppd); + cupsMarkOptions(ppd, num_options, options); + + /* + * Build the command-line for the pdftops filter... + */ + + pdfargv[0] = (char *)"pdftops"; + pdfargc = 1; + + if (ppd) + { + /* + * Set language level and TrueType font handling... + */ + + if (ppd->language_level == 1) + { + pdfargv[pdfargc++] = (char *)"-level1"; + pdfargv[pdfargc++] = (char *)"-noembtt"; + } + else if (ppd->language_level == 2) + { + pdfargv[pdfargc++] = (char *)"-level2"; + if (!ppd->ttrasterizer) + pdfargv[pdfargc++] = (char *)"-noembtt"; + } + else + pdfargv[pdfargc++] = (char *)"-level3"; + + /* + * Set output page size... + */ + + size = ppdPageSize(ppd, NULL); + if (size) + { + /* + * Got the size, now get the orientation... + */ + + orientation = 0; + + if ((val = cupsGetOption("landscape", num_options, options)) != NULL) + { + if (strcasecmp(val, "no") != 0 && strcasecmp(val, "off") != 0 && + strcasecmp(val, "false") != 0) + orientation = 1; + } + else 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 (orientation & 1) + { + snprintf(pdfwidth, sizeof(pdfwidth), "%.1f", size->length); + snprintf(pdfheight, sizeof(pdfheight), "%.1f", size->width); + } + else + { + snprintf(pdfwidth, sizeof(pdfwidth), "%.1f", size->width); + snprintf(pdfheight, sizeof(pdfheight), "%.1f", size->length); + } + + pdfargv[pdfargc++] = (char *)"-paperw"; + pdfargv[pdfargc++] = pdfwidth; + pdfargv[pdfargc++] = (char *)"-paperh"; + pdfargv[pdfargc++] = pdfheight; + } + } + + if ((val = cupsGetOption("fitplot", num_options, options)) != NULL && + strcasecmp(val, "no") && strcasecmp(val, "off") && + strcasecmp(val, "false")) + pdfargv[pdfargc++] = (char *)"-expand"; + + pdfargv[pdfargc++] = filename; + pdfargv[pdfargc++] = (char *)"-"; + pdfargv[pdfargc] = NULL; + + if ((pdfpid = fork()) == 0) + { + /* + * Child comes here... + */ + + execv(CUPS_PDFTOPS, argv); + _cupsLangPrintError(_("ERROR: Unable to execute pdftops filter")); + exit(1); + } + else if (pdfpid < 0) + { + /* + * Unable to fork! + */ + + _cupsLangPrintError(_("ERROR: Unable to execute pdftops filter")); + pdfstatus = 1; + } + else + { + /* + * Parent comes here... + */ + + if (wait(&pdfstatus) != pdfpid) + { + kill(pdfpid, SIGTERM); + pdfstatus = 1; + } + else if (pdfstatus) + { + if (WIFEXITED(pdfstatus)) + { + pdfstatus = WEXITSTATUS(pdfstatus); + + _cupsLangPrintf(stderr, + _("ERROR: pdftops filter exited with status %d!"), + pdfstatus); + } + else + { + pdfstatus = WTERMSIG(pdfstatus); + + _cupsLangPrintf(stderr, + _("ERROR: pdftops filter crashed on signal %d!"), + pdfstatus); + } + } + } + + /* + * Cleanup and exit... + */ + + if (tempfile[0]) + unlink(tempfile); + + return (pdfstatus); +} + + +/* + * 'cancel_job()' - Flag the job as canceled. + */ + +static void +cancel_job(int sig) /* I - Signal number (unused) */ +{ + (void)sig; +} + + +/* + * End of "$Id$". + */ diff --git a/filter/pstops.c b/filter/pstops.c index 074abe065..f8ab6b00a 100644 --- a/filter/pstops.c +++ b/filter/pstops.c @@ -3,7 +3,7 @@ * * PostScript filter for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1993-2007 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -164,27 +164,27 @@ static void cancel_job(int sig); static int check_range(pstops_doc_t *doc, int page); static void copy_bytes(cups_file_t *fp, off_t offset, size_t length); -static size_t copy_comments(cups_file_t *fp, pstops_doc_t *doc, +static ssize_t copy_comments(cups_file_t *fp, pstops_doc_t *doc, ppd_file_t *ppd, char *line, - size_t linelen, size_t linesize); + ssize_t linelen, size_t linesize); static void copy_dsc(cups_file_t *fp, pstops_doc_t *doc, - ppd_file_t *ppd, char *line, size_t linelen, + ppd_file_t *ppd, char *line, ssize_t linelen, size_t linesize); static void copy_non_dsc(cups_file_t *fp, pstops_doc_t *doc, ppd_file_t *ppd, char *line, - size_t linelen, size_t linesize); -static size_t copy_page(cups_file_t *fp, pstops_doc_t *doc, + ssize_t linelen, size_t linesize); +static ssize_t copy_page(cups_file_t *fp, pstops_doc_t *doc, ppd_file_t *ppd, int number, char *line, - size_t linelen, size_t linesize); -static size_t copy_prolog(cups_file_t *fp, pstops_doc_t *doc, + ssize_t linelen, size_t linesize); +static ssize_t copy_prolog(cups_file_t *fp, pstops_doc_t *doc, ppd_file_t *ppd, char *line, - size_t linelen, size_t linesize); -static size_t copy_setup(cups_file_t *fp, pstops_doc_t *doc, + ssize_t linelen, size_t linesize); +static ssize_t copy_setup(cups_file_t *fp, pstops_doc_t *doc, ppd_file_t *ppd, char *line, - size_t linelen, size_t linesize); -static size_t copy_trailer(cups_file_t *fp, pstops_doc_t *doc, + ssize_t linelen, size_t linesize); +static ssize_t copy_trailer(cups_file_t *fp, pstops_doc_t *doc, ppd_file_t *ppd, int number, char *line, - size_t linelen, size_t linesize); + ssize_t linelen, size_t linesize); static void do_prolog(pstops_doc_t *doc, ppd_file_t *ppd); static void do_setup(pstops_doc_t *doc, ppd_file_t *ppd); static void doc_printf(pstops_doc_t *doc, const char *format, ...) @@ -203,7 +203,7 @@ static char *parse_text(const char *start, char **end, char *buffer, static void set_pstops_options(pstops_doc_t *doc, ppd_file_t *ppd, char *argv[], int num_options, cups_option_t *options); -static size_t skip_page(cups_file_t *fp, char *line, size_t linelen, +static ssize_t skip_page(cups_file_t *fp, char *line, ssize_t linelen, size_t linesize); static void start_nup(pstops_doc_t *doc, int number, int show_border, const int *bounding_box); @@ -581,12 +581,12 @@ copy_bytes(cups_file_t *fp, /* I - File to read from */ * On return, "line" will contain the next line in the file, if any. */ -static size_t /* O - Length of next line */ +static ssize_t /* O - Length of next line */ copy_comments(cups_file_t *fp, /* I - File to read from */ pstops_doc_t *doc, /* I - Document info */ ppd_file_t *ppd, /* I - PPD file */ char *line, /* I - Line buffer */ - size_t linelen, /* I - Length of initial line */ + ssize_t linelen, /* I - Length of initial line */ size_t linesize) /* I - Size of line buffer */ { int saw_bounding_box, /* Saw %%BoundingBox: comment? */ @@ -809,7 +809,7 @@ copy_dsc(cups_file_t *fp, /* I - File to read from */ pstops_doc_t *doc, /* I - Document info */ ppd_file_t *ppd, /* I - PPD file */ char *line, /* I - Line buffer */ - size_t linelen, /* I - Length of initial line */ + ssize_t linelen, /* I - Length of initial line */ size_t linesize) /* I - Size of line buffer */ { int number; /* Page number */ @@ -931,7 +931,7 @@ copy_dsc(cups_file_t *fp, /* I - File to read from */ number = doc->slow_order ? 0 : doc->page; - if (doc->temp && !JobCanceled) + if (doc->temp && !JobCanceled && cupsArrayCount(doc->pages) > 0) { int copy; /* Current copy */ @@ -1069,7 +1069,7 @@ copy_non_dsc(cups_file_t *fp, /* I - File to read from */ pstops_doc_t *doc, /* I - Document info */ ppd_file_t *ppd, /* I - PPD file */ char *line, /* I - Line buffer */ - size_t linelen, /* I - Length of initial line */ + ssize_t linelen, /* I - Length of initial line */ size_t linesize) /* I - Size of line buffer */ { int copy; /* Current copy */ @@ -1245,13 +1245,13 @@ copy_non_dsc(cups_file_t *fp, /* I - File to read from */ * On return, "line" will contain the next line in the file, if any. */ -static size_t /* O - Length of next line */ +static ssize_t /* O - Length of next line */ copy_page(cups_file_t *fp, /* I - File to read from */ pstops_doc_t *doc, /* I - Document info */ ppd_file_t *ppd, /* I - PPD file */ int number, /* I - Current page number */ char *line, /* I - Line buffer */ - size_t linelen, /* I - Length of initial line */ + ssize_t linelen, /* I - Length of initial line */ size_t linesize) /* I - Size of line buffer */ { char label[256], /* Page label string */ @@ -1714,12 +1714,12 @@ copy_page(cups_file_t *fp, /* I - File to read from */ * On return, "line" will contain the next line in the file, if any. */ -static size_t /* O - Length of next line */ +static ssize_t /* O - Length of next line */ copy_prolog(cups_file_t *fp, /* I - File to read from */ pstops_doc_t *doc, /* I - Document info */ ppd_file_t *ppd, /* I - PPD file */ char *line, /* I - Line buffer */ - size_t linelen, /* I - Length of initial line */ + ssize_t linelen, /* I - Length of initial line */ size_t linesize) /* I - Size of line buffer */ { while (strncmp(line, "%%BeginProlog", 13)) @@ -1768,12 +1768,12 @@ copy_prolog(cups_file_t *fp, /* I - File to read from */ * On return, "line" will contain the next line in the file, if any. */ -static size_t /* O - Length of next line */ +static ssize_t /* O - Length of next line */ copy_setup(cups_file_t *fp, /* I - File to read from */ pstops_doc_t *doc, /* I - Document info */ ppd_file_t *ppd, /* I - PPD file */ char *line, /* I - Line buffer */ - size_t linelen, /* I - Length of initial line */ + ssize_t linelen, /* I - Length of initial line */ size_t linesize) /* I - Size of line buffer */ { while (strncmp(line, "%%BeginSetup", 12)) @@ -1833,13 +1833,13 @@ copy_setup(cups_file_t *fp, /* I - File to read from */ * On return, "line" will contain the next line in the file, if any. */ -static size_t /* O - Length of next line */ +static ssize_t /* O - Length of next line */ copy_trailer(cups_file_t *fp, /* I - File to read from */ pstops_doc_t *doc, /* I - Document info */ ppd_file_t *ppd, /* I - PPD file */ int number, /* I - Number of pages */ char *line, /* I - Line buffer */ - size_t linelen, /* I - Length of initial line */ + ssize_t linelen, /* I - Length of initial line */ size_t linesize) /* I - Size of line buffer */ { /* @@ -2712,10 +2712,10 @@ set_pstops_options( * 'skip_page()' - Skip past a page that won't be printed... */ -static size_t /* O - Length of next line */ +static ssize_t /* O - Length of next line */ skip_page(cups_file_t *fp, /* I - File to read from */ char *line, /* I - Line buffer */ - size_t linelen, /* I - Length of initial line */ + ssize_t linelen, /* I - Length of initial line */ size_t linesize) /* I - Size of line buffer */ { int level; /* Embedded document level */ diff --git a/filter/rastertoepson.c b/filter/rastertoepson.c index f5c8c9d67..a50d977c7 100644 --- a/filter/rastertoepson.c +++ b/filter/rastertoepson.c @@ -4,7 +4,7 @@ * EPSON ESC/P and ESC/P2 filter for the Common UNIX Printing System * (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1993-2007 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -153,7 +153,7 @@ StartPage(const ppd_file_t *ppd, /* I - PPD file */ * Send a reset sequence. */ - if (ppd->nickname && strstr(ppd->nickname, "OKIDATA") != NULL) + if (ppd && ppd->nickname && strstr(ppd->nickname, "OKIDATA") != NULL) printf("\033{A"); /* Set EPSON emulation mode */ printf("\033@"); @@ -164,7 +164,7 @@ StartPage(const ppd_file_t *ppd, /* I - PPD file */ EjectPage = header->Margins[0] || header->Margins[1]; - switch (ppd->model_number) + switch (Model) { case EPSON_9PIN : case EPSON_24PIN : @@ -196,7 +196,7 @@ StartPage(const ppd_file_t *ppd, /* I - PPD file */ DotColumns = header->HWResolution[0] / 60; Shingling = 0; - if (ppd->model_number == EPSON_9PIN) + if (Model == EPSON_9PIN) printf("\033\063\030"); /* Set line feed */ else switch (header->HWResolution[0]) @@ -251,8 +251,11 @@ StartPage(const ppd_file_t *ppd, /* I - PPD file */ putchar(n); putchar(n >> 8); - t = (ppd->sizes[1].length - ppd->sizes[1].top) * - header->HWResolution[1] / 72.0; + if (ppd) + t = (ppd->sizes[1].length - ppd->sizes[1].top) * + header->HWResolution[1] / 72.0; + else + t = 0; pwrite("\033(c\004\000", 5); /* Top & bottom margins */ putchar(t); @@ -293,18 +296,35 @@ StartPage(const ppd_file_t *ppd, /* I - PPD file */ * Allocate memory for a line/row of graphics... */ - Planes[0] = malloc(header->cupsBytesPerLine); + if ((Planes[0] = malloc(header->cupsBytesPerLine)) == NULL) + { + fputs("ERROR: Unable to allocate memory!\n", stderr); + exit(1); + } + for (plane = 1; plane < NumPlanes; plane ++) Planes[plane] = Planes[0] + plane * header->cupsBytesPerLine / NumPlanes; if (header->cupsCompression || DotBytes) - CompBuffer = calloc(2, header->cupsWidth); + { + if ((CompBuffer = calloc(2, header->cupsWidth)) == NULL) + { + fputs("ERROR: Unable to allocate memory!\n", stderr); + exit(1); + } + } else CompBuffer = NULL; if (DotBytes) { - LineBuffers[0] = calloc(DotBytes, header->cupsWidth * (Shingling + 1)); + if ((LineBuffers[0] = calloc(DotBytes, + header->cupsWidth * (Shingling + 1))) == NULL) + { + fputs("ERROR: Unable to allocate memory!\n", stderr); + exit(1); + } + LineBuffers[1] = LineBuffers[0] + DotBytes * header->cupsWidth; DotBit = 128; LineCount = 0; diff --git a/filter/rastertohp.c b/filter/rastertohp.c index 2c41a2652..f35b58ca7 100644 --- a/filter/rastertohp.c +++ b/filter/rastertohp.c @@ -4,7 +4,7 @@ * Hewlett-Packard Page Control Language filter for the Common UNIX * Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1993-2007 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -277,7 +277,7 @@ StartPage(ppd_file_t *ppd, /* I - PPD file */ * Set graphics mode... */ - if (ppd->model_number == 2) + if (ppd && ppd->model_number == 2) { /* * Figure out the number of color planes... @@ -382,7 +382,12 @@ StartPage(ppd_file_t *ppd, /* I - PPD file */ * Allocate memory for a line of graphics... */ - Planes[0] = malloc(header->cupsBytesPerLine); + if ((Planes[0] = malloc(header->cupsBytesPerLine)) == NULL) + { + fputs("ERROR: Unable to allocate memory!\n", stderr); + exit(1); + } + for (plane = 1; plane < NumPlanes; plane ++) Planes[plane] = Planes[0] + plane * header->cupsBytesPerLine / NumPlanes; diff --git a/locale/checkpo.c b/locale/checkpo.c index ea41a3298..6b76f5be5 100644 --- a/locale/checkpo.c +++ b/locale/checkpo.c @@ -50,8 +50,7 @@ main(int argc, /* I - Number of command-line args */ *strfmts; /* Format strings in msgstr */ char *idfmt, /* Current msgid format string */ *strfmt; /* Current msgstr format string */ - int fmtidx, /* Format index */ - fmtcount; /* Format count */ + int fmtidx; /* Format index */ int status, /* Exit status */ pass, /* Pass/fail status */ untranslated; /* Untranslated messages */ @@ -135,8 +134,6 @@ main(int argc, /* I - Number of command-line args */ if (!idfmt || strcmp(strfmt, idfmt)) break; - - fmtcount ++; } if (cupsArrayCount(strfmts) != cupsArrayCount(idfmts) || strfmt) diff --git a/notifier/Makefile b/notifier/Makefile index dea93d70e..49e05ac0b 100644 --- a/notifier/Makefile +++ b/notifier/Makefile @@ -3,7 +3,7 @@ # # Notifier makefile for the Common UNIX Printing System (CUPS). # -# Copyright 2007 by Apple Inc. +# Copyright 2007-2008 by Apple Inc. # Copyright 1997-2007 by Easy Software Products, all rights reserved. # # These coded instructions, statements, and computer programs are the @@ -44,7 +44,7 @@ install: all for file in $(TARGETS); do \ $(INSTALL_BIN) $$file $(SERVERBIN)/notifier; \ done - $(INSTALL_DIR) -m 755 $(CACHEDIR)/rss + $(INSTALL_DIR) -m 775 $(CACHEDIR)/rss -chgrp $(CUPS_GROUP) $(CACHEDIR)/rss if test "x$(SYMROOT)" != "x"; then \ $(INSTALL_DIR) $(SYMROOT); \ diff --git a/pdftops/Annot.cxx b/pdftops/Annot.cxx deleted file mode 100644 index 19efb9c88..000000000 --- a/pdftops/Annot.cxx +++ /dev/null @@ -1,317 +0,0 @@ -//======================================================================== -// -// Annot.cc -// -// Copyright 2000-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include <stdlib.h> -#include "gmem.h" -#include "Object.h" -#include "Catalog.h" -#include "Gfx.h" -#include "Lexer.h" -#include "Annot.h" - -//------------------------------------------------------------------------ -// Annot -//------------------------------------------------------------------------ - -Annot::Annot(XRef *xrefA, Dict *acroForm, Dict *dict) { - Object apObj, asObj, obj1, obj2; - GBool regen, isTextField; - double t; - - ok = gFalse; - xref = xrefA; - appearBuf = NULL; - - 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(); - if (xMin > xMax) { - t = xMin; xMin = xMax; xMax = t; - } - if (yMin > yMax) { - t = yMin; yMin = yMax; yMax = t; - } - } else { - //~ this should return an error - xMin = yMin = 0; - xMax = yMax = 1; - } - obj1.free(); - - // check if field apperances need to be regenerated - regen = gFalse; - if (acroForm) { - acroForm->lookup("NeedAppearances", &obj1); - if (obj1.isBool() && obj1.getBool()) { - regen = gTrue; - } - obj1.free(); - } - - // check for a text-type field - isTextField = dict->lookup("FT", &obj1)->isName("Tx"); - obj1.free(); - -#if 0 //~ appearance stream generation is not finished yet - if (regen && isTextField) { - generateAppearance(acroForm, dict); - } else { -#endif - if (dict->lookup("AP", &apObj)->isDict()) { - if (dict->lookup("AS", &asObj)->isName()) { - if (apObj.dictLookup("N", &obj1)->isDict()) { - if (obj1.dictLookupNF(asObj.getName(), &obj2)->isRef()) { - obj2.copy(&appearance); - ok = gTrue; - } else { - obj2.free(); - if (obj1.dictLookupNF("Off", &obj2)->isRef()) { - obj2.copy(&appearance); - ok = gTrue; - } - } - obj2.free(); - } - obj1.free(); - } else { - if (apObj.dictLookupNF("N", &obj1)->isRef()) { - obj1.copy(&appearance); - ok = gTrue; - } - obj1.free(); - } - asObj.free(); - } - apObj.free(); -#if 0 //~ appearance stream generation is not finished yet - } -#endif -} - -Annot::~Annot() { - appearance.free(); - if (appearBuf) { - delete appearBuf; - } -} - -void Annot::generateAppearance(Dict *acroForm, Dict *dict) { - MemStream *appearStream; - Object daObj, vObj, drObj, appearDict, obj1, obj2; - GString *daStr, *daStr1, *vStr, *s; - char buf[256]; - double fontSize; - int c; - int i0, i1; - - //~ DA can be inherited - if (dict->lookup("DA", &daObj)->isString()) { - daStr = daObj.getString(); - - // look for a font size - //~ may want to parse the DS entry in place of this (if it exists) - daStr1 = NULL; - fontSize = 10; - for (i1 = daStr->getLength() - 2; i1 >= 0; --i1) { - if (daStr->getChar(i1) == 'T' && daStr->getChar(i1+1) == 'f') { - for (--i1; i1 >= 0 && Lexer::isSpace(daStr->getChar(i1)); --i1) ; - for (i0 = i1; i0 >= 0 && !Lexer::isSpace(daStr->getChar(i0)); --i0) ; - if (i0 >= 0) { - ++i0; - ++i1; - s = new GString(daStr, i0, i1 - i0); - fontSize = atof(s->getCString()); - delete s; - - // autosize the font - if (fontSize == 0) { - fontSize = 0.67 * (yMax - yMin); - daStr1 = new GString(daStr, 0, i0); - sprintf(buf, "%.2f", fontSize); - daStr1->append(buf); - daStr1->append(daStr->getCString() + i1, - daStr->getLength() - i1); - } - } - break; - } - } - - // build the appearance stream contents - appearBuf = new GString(); - appearBuf->append("/Tx BMC\n"); - appearBuf->append("q BT\n"); - appearBuf->append(daStr1 ? daStr1 : daStr)->append("\n"); - if (dict->lookup("V", &vObj)->isString()) { - //~ handle quadding -- this requires finding the font and using - //~ the encoding and char widths - sprintf(buf, "1 0 0 1 %.2f %.2f Tm\n", 2.0, yMax - yMin - fontSize); - appearBuf->append(buf); - sprintf(buf, "%g TL\n", fontSize); - appearBuf->append(buf); - vStr = vObj.getString(); - i0 = 0; - while (i0 < vStr->getLength()) { - for (i1 = i0; - i1 < vStr->getLength() && - vStr->getChar(i1) != '\n' && vStr->getChar(i1) != '\r'; - ++i1) ; - if (i0 > 0) { - appearBuf->append("T*\n"); - } - appearBuf->append('('); - for (; i0 < i1; ++i0) { - c = vStr->getChar(i0); - if (c == '(' || c == ')' || c == '\\') { - appearBuf->append('\\'); - appearBuf->append(c); - } else if (c < 0x20 || c >= 0x80) { - sprintf(buf, "\\%03o", c); - appearBuf->append(buf); - } else { - appearBuf->append(c); - } - } - appearBuf->append(") Tj\n"); - if (i1 + 1 < vStr->getLength() && - vStr->getChar(i1) == '\r' && vStr->getChar(i1 + 1) == '\n') { - i0 = i1 + 2; - } else { - i0 = i1 + 1; - } - } - } - vObj.free(); - appearBuf->append("ET Q\n"); - appearBuf->append("EMC\n"); - - // build the appearance stream dictionary - appearDict.initDict(xref); - appearDict.dictAdd(copyString("Length"), - obj1.initInt(appearBuf->getLength())); - appearDict.dictAdd(copyString("Subtype"), obj1.initName("Form")); - obj1.initArray(xref); - obj1.arrayAdd(obj2.initReal(0)); - obj1.arrayAdd(obj2.initReal(0)); - obj1.arrayAdd(obj2.initReal(xMax - xMin)); - obj1.arrayAdd(obj2.initReal(yMax - yMin)); - appearDict.dictAdd(copyString("BBox"), &obj1); - - // find the resource dictionary - dict->lookup("DR", &drObj); - if (!drObj.isDict()) { - dict->lookup("Parent", &obj1); - while (obj1.isDict()) { - drObj.free(); - obj1.dictLookup("DR", &drObj); - if (drObj.isDict()) { - break; - } - obj1.dictLookup("Parent", &obj2); - obj1.free(); - obj1 = obj2; - } - obj1.free(); - if (!drObj.isDict()) { - if (acroForm) { - drObj.free(); - acroForm->lookup("DR", &drObj); - } - } - } - if (drObj.isDict()) { - appearDict.dictAdd(copyString("Resources"), drObj.copy(&obj1)); - } - drObj.free(); - - // build the appearance stream - appearStream = new MemStream(appearBuf->getCString(), 0, - appearBuf->getLength(), &appearDict); - appearance.initStream(appearStream); - ok = gTrue; - - if (daStr1) { - delete daStr1; - } - } - daObj.free(); -} - -void Annot::draw(Gfx *gfx) { - Object obj; - - fprintf(stderr, "DEBUG: Annot::draw(gfx=%p)\n", gfx); - - if (appearance.fetch(xref, &obj)->isStream()) { - gfx->doAnnot(&obj, xMin, yMin, xMax, yMax); - } - obj.free(); -} - -//------------------------------------------------------------------------ -// Annots -//------------------------------------------------------------------------ - -Annots::Annots(XRef *xref, Catalog *catalog, Object *annotsObj) { - Dict *acroForm; - Annot *annot; - Object obj1; - int size; - int i; - - annots = NULL; - size = 0; - nAnnots = 0; - - acroForm = catalog->getAcroForm()->isDict() ? - catalog->getAcroForm()->getDict() : NULL; - if (annotsObj->isArray()) { - for (i = 0; i < annotsObj->arrayGetLength(); ++i) { - if (annotsObj->arrayGet(i, &obj1)->isDict()) { - annot = new Annot(xref, acroForm, obj1.getDict()); - if (annot->isOk()) { - if (nAnnots >= size) { - size += 16; - annots = (Annot **)greallocn(annots, size, sizeof(Annot *)); - } - annots[nAnnots++] = annot; - } else { - delete annot; - } - } - obj1.free(); - } - } -} - -Annots::~Annots() { - int i; - - for (i = 0; i < nAnnots; ++i) { - delete annots[i]; - } - gfree(annots); -} diff --git a/pdftops/Annot.h b/pdftops/Annot.h deleted file mode 100644 index 9e46dbb5b..000000000 --- a/pdftops/Annot.h +++ /dev/null @@ -1,73 +0,0 @@ -//======================================================================== -// -// Annot.h -// -// Copyright 2000-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef ANNOT_H -#define ANNOT_H - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -class XRef; -class Catalog; -class Gfx; - -//------------------------------------------------------------------------ -// Annot -//------------------------------------------------------------------------ - -class Annot { -public: - - Annot(XRef *xrefA, Dict *acroForm, Dict *dict); - ~Annot(); - GBool isOk() { return ok; } - - void draw(Gfx *gfx); - - // Get appearance object. - Object *getAppearance(Object *obj) { return appearance.fetch(xref, obj); } - -private: - - void generateAppearance(Dict *acroForm, Dict *dict); - - XRef *xref; // the xref table for this PDF file - Object appearance; // a reference to the Form XObject stream - // for the normal appearance - GString *appearBuf; - double xMin, yMin, // annotation rectangle - xMax, yMax; - GBool ok; -}; - -//------------------------------------------------------------------------ -// Annots -//------------------------------------------------------------------------ - -class Annots { -public: - - // Extract non-link annotations from array of annotations. - Annots(XRef *xref, Catalog *catalog, Object *annotsObj); - - ~Annots(); - - // Iterate through list of annotations. - int getNumAnnots() { return nAnnots; } - Annot *getAnnot(int i) { return annots[i]; } - -private: - - Annot **annots; - int nAnnots; -}; - -#endif diff --git a/pdftops/Array.cxx b/pdftops/Array.cxx deleted file mode 100644 index 137727295..000000000 --- a/pdftops/Array.cxx +++ /dev/null @@ -1,73 +0,0 @@ -//======================================================================== -// -// Array.cc -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include <stdlib.h> -#include <stddef.h> -#include "gmem.h" -#include "Object.h" -#include "Array.h" - -//------------------------------------------------------------------------ -// Array -//------------------------------------------------------------------------ - -Array::Array(XRef *xrefA) { - xref = xrefA; - 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 == size) { - if (length == 0) { - size = 8; - } else { - size *= 2; - } - elems = (Object *)greallocn(elems, size, sizeof(Object)); - } - elems[length] = *elem; - ++length; -} - -Object *Array::get(int i, Object *obj) { - if (i < 0 || i >= length) { -#ifdef DEBUG_MEM - abort(); -#else - return obj->initNull(); -#endif - } - return elems[i].fetch(xref, obj); -} - -Object *Array::getNF(int i, Object *obj) { - if (i < 0 || i >= length) { -#ifdef DEBUG_MEM - abort(); -#else - return obj->initNull(); -#endif - } - return elems[i].copy(obj); -} diff --git a/pdftops/Array.h b/pdftops/Array.h deleted file mode 100644 index d369e8143..000000000 --- a/pdftops/Array.h +++ /dev/null @@ -1,58 +0,0 @@ -//======================================================================== -// -// Array.h -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef ARRAY_H -#define ARRAY_H - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "Object.h" - -class XRef; - -//------------------------------------------------------------------------ -// Array -//------------------------------------------------------------------------ - -class Array { -public: - - // Constructor. - Array(XRef *xrefA); - - // 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: - - XRef *xref; // the xref table for this PDF file - Object *elems; // array of elements - int size; // size of <elems> array - int length; // number of elements in array - int ref; // reference count -}; - -#endif diff --git a/pdftops/BuiltinFont.cxx b/pdftops/BuiltinFont.cxx deleted file mode 100644 index 02a7f3554..000000000 --- a/pdftops/BuiltinFont.cxx +++ /dev/null @@ -1,65 +0,0 @@ -//======================================================================== -// -// BuiltinFont.cc -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include <stdlib.h> -#include <string.h> -#include "gmem.h" -#include "FontEncodingTables.h" -#include "BuiltinFont.h" - -//------------------------------------------------------------------------ - -BuiltinFontWidths::BuiltinFontWidths(BuiltinFontWidth *widths, int sizeA) { - int i, h; - - size = sizeA; - tab = (BuiltinFontWidth **)gmallocn(size, sizeof(BuiltinFontWidth *)); - for (i = 0; i < size; ++i) { - tab[i] = NULL; - } - for (i = 0; i < sizeA; ++i) { - h = hash(widths[i].name); - widths[i].next = tab[h]; - tab[h] = &widths[i]; - } -} - -BuiltinFontWidths::~BuiltinFontWidths() { - gfree(tab); -} - -GBool BuiltinFontWidths::getWidth(char *name, Gushort *width) { - int h; - BuiltinFontWidth *p; - - h = hash(name); - for (p = tab[h]; p; p = p->next) { - if (!strcmp(p->name, name)) { - *width = p->width; - return gTrue; - } - } - return gFalse; -} - -int BuiltinFontWidths::hash(char *name) { - char *p; - unsigned int h; - - h = 0; - for (p = name; *p; ++p) { - h = 17 * h + (int)(*p & 0xff); - } - return (int)(h % size); -} diff --git a/pdftops/BuiltinFont.h b/pdftops/BuiltinFont.h deleted file mode 100644 index 3c036d7f3..000000000 --- a/pdftops/BuiltinFont.h +++ /dev/null @@ -1,57 +0,0 @@ -//======================================================================== -// -// BuiltinFont.h -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef BUILTINFONT_H -#define BUILTINFONT_H - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "gtypes.h" - -struct BuiltinFont; -class BuiltinFontWidths; - -//------------------------------------------------------------------------ - -struct BuiltinFont { - char *name; - char **defaultBaseEnc; - short ascent; - short descent; - short bbox[4]; - BuiltinFontWidths *widths; -}; - -//------------------------------------------------------------------------ - -struct BuiltinFontWidth { - char *name; - Gushort width; - BuiltinFontWidth *next; -}; - -class BuiltinFontWidths { -public: - - BuiltinFontWidths(BuiltinFontWidth *widths, int sizeA); - ~BuiltinFontWidths(); - GBool getWidth(char *name, Gushort *width); - -private: - - int hash(char *name); - - BuiltinFontWidth **tab; - int size; -}; - -#endif diff --git a/pdftops/BuiltinFontTables.cxx b/pdftops/BuiltinFontTables.cxx deleted file mode 100644 index 5115b7bcf..000000000 --- a/pdftops/BuiltinFontTables.cxx +++ /dev/null @@ -1,4284 +0,0 @@ -//======================================================================== -// -// BuiltinFontTables.cc -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> -#include <stdlib.h> -#include "FontEncodingTables.h" -#include "BuiltinFontTables.h" - -static BuiltinFontWidth courierWidthsTab[] = { - { "Ntilde", 600, NULL }, - { "rcaron", 600, NULL }, - { "kcommaaccent", 600, NULL }, - { "Ncommaaccent", 600, NULL }, - { "Zacute", 600, NULL }, - { "comma", 600, NULL }, - { "cedilla", 600, NULL }, - { "plusminus", 600, NULL }, - { "circumflex", 600, NULL }, - { "dotaccent", 600, NULL }, - { "edotaccent", 600, NULL }, - { "asciitilde", 600, NULL }, - { "colon", 600, NULL }, - { "onehalf", 600, NULL }, - { "dollar", 600, NULL }, - { "Lcaron", 600, NULL }, - { "ntilde", 600, NULL }, - { "Aogonek", 600, NULL }, - { "ncommaaccent", 600, NULL }, - { "minus", 600, NULL }, - { "Iogonek", 600, NULL }, - { "zacute", 600, NULL }, - { "yen", 600, NULL }, - { "space", 600, NULL }, - { "Omacron", 600, NULL }, - { "questiondown", 600, NULL }, - { "emdash", 600, NULL }, - { "Agrave", 600, NULL }, - { "three", 600, NULL }, - { "numbersign", 600, NULL }, - { "lcaron", 600, NULL }, - { "A", 600, NULL }, - { "B", 600, NULL }, - { "C", 600, NULL }, - { "aogonek", 600, NULL }, - { "D", 600, NULL }, - { "E", 600, NULL }, - { "onequarter", 600, NULL }, - { "F", 600, NULL }, - { "G", 600, NULL }, - { "H", 600, NULL }, - { "I", 600, NULL }, - { "J", 600, NULL }, - { "K", 600, NULL }, - { "iogonek", 600, NULL }, - { "L", 600, NULL }, - { "backslash", 600, NULL }, - { "periodcentered", 600, NULL }, - { "M", 600, NULL }, - { "N", 600, NULL }, - { "omacron", 600, NULL }, - { "Tcommaaccent", 600, NULL }, - { "O", 600, NULL }, - { "P", 600, NULL }, - { "Q", 600, NULL }, - { "Uhungarumlaut", 600, NULL }, - { "R", 600, NULL }, - { "Aacute", 600, NULL }, - { "caron", 600, NULL }, - { "S", 600, NULL }, - { "T", 600, NULL }, - { "U", 600, NULL }, - { "agrave", 600, NULL }, - { "V", 600, NULL }, - { "W", 600, NULL }, - { "equal", 600, NULL }, - { "question", 600, NULL }, - { "X", 600, NULL }, - { "Y", 600, NULL }, - { "Z", 600, NULL }, - { "four", 600, NULL }, - { "a", 600, NULL }, - { "Gcommaaccent", 600, NULL }, - { "b", 600, NULL }, - { "c", 600, NULL }, - { "d", 600, NULL }, - { "e", 600, NULL }, - { "f", 600, NULL }, - { "g", 600, NULL }, - { "bullet", 600, NULL }, - { "h", 600, NULL }, - { "i", 600, NULL }, - { "Oslash", 600, NULL }, - { "dagger", 600, NULL }, - { "j", 600, NULL }, - { "k", 600, NULL }, - { "l", 600, NULL }, - { "m", 600, NULL }, - { "n", 600, NULL }, - { "tcommaaccent", 600, NULL }, - { "o", 600, NULL }, - { "ordfeminine", 600, NULL }, - { "ring", 600, NULL }, - { "p", 600, NULL }, - { "q", 600, NULL }, - { "uhungarumlaut", 600, NULL }, - { "r", 600, NULL }, - { "twosuperior", 600, NULL }, - { "aacute", 600, NULL }, - { "s", 600, NULL }, - { "OE", 600, NULL }, - { "t", 600, NULL }, - { "divide", 600, NULL }, - { "u", 600, NULL }, - { "Ccaron", 600, NULL }, - { "v", 600, NULL }, - { "w", 600, NULL }, - { "x", 600, NULL }, - { "y", 600, NULL }, - { "z", 600, NULL }, - { "Gbreve", 600, NULL }, - { "commaaccent", 600, NULL }, - { "hungarumlaut", 600, NULL }, - { "Idotaccent", 600, NULL }, - { "Nacute", 600, NULL }, - { "quotedbl", 600, NULL }, - { "gcommaaccent", 600, NULL }, - { "mu", 600, NULL }, - { "greaterequal", 600, NULL }, - { "Scaron", 600, NULL }, - { "Lslash", 600, NULL }, - { "semicolon", 600, NULL }, - { "oslash", 600, NULL }, - { "lessequal", 600, NULL }, - { "lozenge", 600, NULL }, - { "parenright", 600, NULL }, - { "ccaron", 600, NULL }, - { "Ecircumflex", 600, NULL }, - { "gbreve", 600, NULL }, - { "trademark", 600, NULL }, - { "daggerdbl", 600, NULL }, - { "nacute", 600, NULL }, - { "macron", 600, NULL }, - { "Otilde", 600, NULL }, - { "Emacron", 600, NULL }, - { "ellipsis", 600, NULL }, - { "scaron", 600, NULL }, - { "AE", 600, NULL }, - { "Ucircumflex", 600, NULL }, - { "lslash", 600, NULL }, - { "quotedblleft", 600, NULL }, - { "hyphen", 600, NULL }, - { "guilsinglright", 600, NULL }, - { "quotesingle", 600, NULL }, - { "eight", 600, NULL }, - { "exclamdown", 600, NULL }, - { "endash", 600, NULL }, - { "oe", 600, NULL }, - { "Abreve", 600, NULL }, - { "Umacron", 600, NULL }, - { "ecircumflex", 600, NULL }, - { "Adieresis", 600, NULL }, - { "copyright", 600, NULL }, - { "Egrave", 600, NULL }, - { "slash", 600, NULL }, - { "Edieresis", 600, NULL }, - { "otilde", 600, NULL }, - { "Idieresis", 600, NULL }, - { "parenleft", 600, NULL }, - { "one", 600, NULL }, - { "emacron", 600, NULL }, - { "Odieresis", 600, NULL }, - { "ucircumflex", 600, NULL }, - { "bracketleft", 600, NULL }, - { "Ugrave", 600, NULL }, - { "quoteright", 600, NULL }, - { "Udieresis", 600, NULL }, - { "perthousand", 600, NULL }, - { "Ydieresis", 600, NULL }, - { "umacron", 600, NULL }, - { "abreve", 600, NULL }, - { "Eacute", 600, NULL }, - { "adieresis", 600, NULL }, - { "egrave", 600, NULL }, - { "edieresis", 600, NULL }, - { "idieresis", 600, NULL }, - { "Eth", 600, NULL }, - { "ae", 600, NULL }, - { "asterisk", 600, NULL }, - { "odieresis", 600, NULL }, - { "Uacute", 600, NULL }, - { "ugrave", 600, NULL }, - { "five", 600, NULL }, - { "nine", 600, NULL }, - { "udieresis", 600, NULL }, - { "Zcaron", 600, NULL }, - { "Scommaaccent", 600, NULL }, - { "threequarters", 600, NULL }, - { "guillemotright", 600, NULL }, - { "Ccedilla", 600, NULL }, - { "ydieresis", 600, NULL }, - { "tilde", 600, NULL }, - { "at", 600, NULL }, - { "eacute", 600, NULL }, - { "underscore", 600, NULL }, - { "Euro", 600, NULL }, - { "Dcroat", 600, NULL }, - { "zero", 600, NULL }, - { "multiply", 600, NULL }, - { "eth", 600, NULL }, - { "Scedilla", 600, NULL }, - { "Racute", 600, NULL }, - { "Ograve", 600, NULL }, - { "partialdiff", 600, NULL }, - { "uacute", 600, NULL }, - { "braceleft", 600, NULL }, - { "Thorn", 600, NULL }, - { "zcaron", 600, NULL }, - { "scommaaccent", 600, NULL }, - { "ccedilla", 600, NULL }, - { "Dcaron", 600, NULL }, - { "dcroat", 600, NULL }, - { "scedilla", 600, NULL }, - { "Oacute", 600, NULL }, - { "Ocircumflex", 600, NULL }, - { "ogonek", 600, NULL }, - { "ograve", 600, NULL }, - { "racute", 600, NULL }, - { "Tcaron", 600, NULL }, - { "Eogonek", 600, NULL }, - { "thorn", 600, NULL }, - { "degree", 600, NULL }, - { "registered", 600, NULL }, - { "radical", 600, NULL }, - { "Aring", 600, NULL }, - { "percent", 600, NULL }, - { "six", 600, NULL }, - { "paragraph", 600, NULL }, - { "dcaron", 600, NULL }, - { "Uogonek", 600, NULL }, - { "two", 600, NULL }, - { "summation", 600, NULL }, - { "Igrave", 600, NULL }, - { "Lacute", 600, NULL }, - { "ocircumflex", 600, NULL }, - { "oacute", 600, NULL }, - { "Uring", 600, NULL }, - { "Lcommaaccent", 600, NULL }, - { "tcaron", 600, NULL }, - { "eogonek", 600, NULL }, - { "Delta", 600, NULL }, - { "Ohungarumlaut", 600, NULL }, - { "asciicircum", 600, NULL }, - { "aring", 600, NULL }, - { "grave", 600, NULL }, - { "uogonek", 600, NULL }, - { "bracketright", 600, NULL }, - { "ampersand", 600, NULL }, - { "Iacute", 600, NULL }, - { "lacute", 600, NULL }, - { "igrave", 600, NULL }, - { "Ncaron", 600, NULL }, - { "plus", 600, NULL }, - { "uring", 600, NULL }, - { "quotesinglbase", 600, NULL }, - { "lcommaaccent", 600, NULL }, - { "Yacute", 600, NULL }, - { "ohungarumlaut", 600, NULL }, - { "threesuperior", 600, NULL }, - { "acute", 600, NULL }, - { "section", 600, NULL }, - { "dieresis", 600, NULL }, - { "quotedblbase", 600, NULL }, - { "iacute", 600, NULL }, - { "ncaron", 600, NULL }, - { "florin", 600, NULL }, - { "yacute", 600, NULL }, - { "Rcommaaccent", 600, NULL }, - { "fi", 600, NULL }, - { "fl", 600, NULL }, - { "Acircumflex", 600, NULL }, - { "Cacute", 600, NULL }, - { "Icircumflex", 600, NULL }, - { "guillemotleft", 600, NULL }, - { "germandbls", 600, NULL }, - { "seven", 600, NULL }, - { "Amacron", 600, NULL }, - { "Sacute", 600, NULL }, - { "ordmasculine", 600, NULL }, - { "dotlessi", 600, NULL }, - { "sterling", 600, NULL }, - { "notequal", 600, NULL }, - { "Imacron", 600, NULL }, - { "rcommaaccent", 600, NULL }, - { "Zdotaccent", 600, NULL }, - { "acircumflex", 600, NULL }, - { "cacute", 600, NULL }, - { "Ecaron", 600, NULL }, - { "braceright", 600, NULL }, - { "icircumflex", 600, NULL }, - { "quotedblright", 600, NULL }, - { "amacron", 600, NULL }, - { "sacute", 600, NULL }, - { "imacron", 600, NULL }, - { "cent", 600, NULL }, - { "currency", 600, NULL }, - { "logicalnot", 600, NULL }, - { "zdotaccent", 600, NULL }, - { "Atilde", 600, NULL }, - { "breve", 600, NULL }, - { "bar", 600, NULL }, - { "fraction", 600, NULL }, - { "less", 600, NULL }, - { "ecaron", 600, NULL }, - { "guilsinglleft", 600, NULL }, - { "exclam", 600, NULL }, - { "period", 600, NULL }, - { "Rcaron", 600, NULL }, - { "Kcommaaccent", 600, NULL }, - { "greater", 600, NULL }, - { "atilde", 600, NULL }, - { "brokenbar", 600, NULL }, - { "quoteleft", 600, NULL }, - { "Edotaccent", 600, NULL }, - { "onesuperior", 600, NULL } -}; - -static BuiltinFontWidth courierBoldWidthsTab[] = { - { "Ntilde", 600, NULL }, - { "rcaron", 600, NULL }, - { "kcommaaccent", 600, NULL }, - { "Ncommaaccent", 600, NULL }, - { "Zacute", 600, NULL }, - { "comma", 600, NULL }, - { "cedilla", 600, NULL }, - { "plusminus", 600, NULL }, - { "circumflex", 600, NULL }, - { "dotaccent", 600, NULL }, - { "edotaccent", 600, NULL }, - { "asciitilde", 600, NULL }, - { "colon", 600, NULL }, - { "onehalf", 600, NULL }, - { "dollar", 600, NULL }, - { "Lcaron", 600, NULL }, - { "ntilde", 600, NULL }, - { "Aogonek", 600, NULL }, - { "ncommaaccent", 600, NULL }, - { "minus", 600, NULL }, - { "Iogonek", 600, NULL }, - { "zacute", 600, NULL }, - { "yen", 600, NULL }, - { "space", 600, NULL }, - { "Omacron", 600, NULL }, - { "questiondown", 600, NULL }, - { "emdash", 600, NULL }, - { "Agrave", 600, NULL }, - { "three", 600, NULL }, - { "numbersign", 600, NULL }, - { "lcaron", 600, NULL }, - { "A", 600, NULL }, - { "B", 600, NULL }, - { "C", 600, NULL }, - { "aogonek", 600, NULL }, - { "D", 600, NULL }, - { "E", 600, NULL }, - { "onequarter", 600, NULL }, - { "F", 600, NULL }, - { "G", 600, NULL }, - { "H", 600, NULL }, - { "I", 600, NULL }, - { "J", 600, NULL }, - { "K", 600, NULL }, - { "iogonek", 600, NULL }, - { "backslash", 600, NULL }, - { "L", 600, NULL }, - { "periodcentered", 600, NULL }, - { "M", 600, NULL }, - { "N", 600, NULL }, - { "omacron", 600, NULL }, - { "Tcommaaccent", 600, NULL }, - { "O", 600, NULL }, - { "P", 600, NULL }, - { "Q", 600, NULL }, - { "Uhungarumlaut", 600, NULL }, - { "R", 600, NULL }, - { "Aacute", 600, NULL }, - { "caron", 600, NULL }, - { "S", 600, NULL }, - { "T", 600, NULL }, - { "U", 600, NULL }, - { "agrave", 600, NULL }, - { "V", 600, NULL }, - { "W", 600, NULL }, - { "X", 600, NULL }, - { "question", 600, NULL }, - { "equal", 600, NULL }, - { "Y", 600, NULL }, - { "Z", 600, NULL }, - { "four", 600, NULL }, - { "a", 600, NULL }, - { "Gcommaaccent", 600, NULL }, - { "b", 600, NULL }, - { "c", 600, NULL }, - { "d", 600, NULL }, - { "e", 600, NULL }, - { "f", 600, NULL }, - { "g", 600, NULL }, - { "bullet", 600, NULL }, - { "h", 600, NULL }, - { "i", 600, NULL }, - { "Oslash", 600, NULL }, - { "dagger", 600, NULL }, - { "j", 600, NULL }, - { "k", 600, NULL }, - { "l", 600, NULL }, - { "m", 600, NULL }, - { "n", 600, NULL }, - { "tcommaaccent", 600, NULL }, - { "o", 600, NULL }, - { "ordfeminine", 600, NULL }, - { "ring", 600, NULL }, - { "p", 600, NULL }, - { "q", 600, NULL }, - { "uhungarumlaut", 600, NULL }, - { "r", 600, NULL }, - { "twosuperior", 600, NULL }, - { "aacute", 600, NULL }, - { "s", 600, NULL }, - { "OE", 600, NULL }, - { "t", 600, NULL }, - { "divide", 600, NULL }, - { "u", 600, NULL }, - { "Ccaron", 600, NULL }, - { "v", 600, NULL }, - { "w", 600, NULL }, - { "x", 600, NULL }, - { "y", 600, NULL }, - { "z", 600, NULL }, - { "Gbreve", 600, NULL }, - { "commaaccent", 600, NULL }, - { "hungarumlaut", 600, NULL }, - { "Idotaccent", 600, NULL }, - { "Nacute", 600, NULL }, - { "quotedbl", 600, NULL }, - { "gcommaaccent", 600, NULL }, - { "mu", 600, NULL }, - { "greaterequal", 600, NULL }, - { "Scaron", 600, NULL }, - { "Lslash", 600, NULL }, - { "semicolon", 600, NULL }, - { "oslash", 600, NULL }, - { "lessequal", 600, NULL }, - { "lozenge", 600, NULL }, - { "parenright", 600, NULL }, - { "ccaron", 600, NULL }, - { "Ecircumflex", 600, NULL }, - { "gbreve", 600, NULL }, - { "trademark", 600, NULL }, - { "daggerdbl", 600, NULL }, - { "nacute", 600, NULL }, - { "macron", 600, NULL }, - { "Otilde", 600, NULL }, - { "Emacron", 600, NULL }, - { "ellipsis", 600, NULL }, - { "scaron", 600, NULL }, - { "AE", 600, NULL }, - { "Ucircumflex", 600, NULL }, - { "lslash", 600, NULL }, - { "quotedblleft", 600, NULL }, - { "guilsinglright", 600, NULL }, - { "hyphen", 600, NULL }, - { "quotesingle", 600, NULL }, - { "eight", 600, NULL }, - { "exclamdown", 600, NULL }, - { "endash", 600, NULL }, - { "oe", 600, NULL }, - { "Abreve", 600, NULL }, - { "Umacron", 600, NULL }, - { "ecircumflex", 600, NULL }, - { "Adieresis", 600, NULL }, - { "copyright", 600, NULL }, - { "Egrave", 600, NULL }, - { "slash", 600, NULL }, - { "Edieresis", 600, NULL }, - { "otilde", 600, NULL }, - { "Idieresis", 600, NULL }, - { "parenleft", 600, NULL }, - { "one", 600, NULL }, - { "emacron", 600, NULL }, - { "Odieresis", 600, NULL }, - { "ucircumflex", 600, NULL }, - { "bracketleft", 600, NULL }, - { "Ugrave", 600, NULL }, - { "quoteright", 600, NULL }, - { "Udieresis", 600, NULL }, - { "perthousand", 600, NULL }, - { "Ydieresis", 600, NULL }, - { "umacron", 600, NULL }, - { "abreve", 600, NULL }, - { "Eacute", 600, NULL }, - { "adieresis", 600, NULL }, - { "egrave", 600, NULL }, - { "edieresis", 600, NULL }, - { "idieresis", 600, NULL }, - { "Eth", 600, NULL }, - { "ae", 600, NULL }, - { "asterisk", 600, NULL }, - { "odieresis", 600, NULL }, - { "Uacute", 600, NULL }, - { "ugrave", 600, NULL }, - { "nine", 600, NULL }, - { "five", 600, NULL }, - { "udieresis", 600, NULL }, - { "Zcaron", 600, NULL }, - { "Scommaaccent", 600, NULL }, - { "threequarters", 600, NULL }, - { "guillemotright", 600, NULL }, - { "Ccedilla", 600, NULL }, - { "ydieresis", 600, NULL }, - { "tilde", 600, NULL }, - { "at", 600, NULL }, - { "eacute", 600, NULL }, - { "underscore", 600, NULL }, - { "Euro", 600, NULL }, - { "Dcroat", 600, NULL }, - { "multiply", 600, NULL }, - { "zero", 600, NULL }, - { "eth", 600, NULL }, - { "Scedilla", 600, NULL }, - { "Ograve", 600, NULL }, - { "Racute", 600, NULL }, - { "partialdiff", 600, NULL }, - { "uacute", 600, NULL }, - { "braceleft", 600, NULL }, - { "Thorn", 600, NULL }, - { "zcaron", 600, NULL }, - { "scommaaccent", 600, NULL }, - { "ccedilla", 600, NULL }, - { "Dcaron", 600, NULL }, - { "dcroat", 600, NULL }, - { "Ocircumflex", 600, NULL }, - { "Oacute", 600, NULL }, - { "scedilla", 600, NULL }, - { "ogonek", 600, NULL }, - { "ograve", 600, NULL }, - { "racute", 600, NULL }, - { "Tcaron", 600, NULL }, - { "Eogonek", 600, NULL }, - { "thorn", 600, NULL }, - { "degree", 600, NULL }, - { "registered", 600, NULL }, - { "radical", 600, NULL }, - { "Aring", 600, NULL }, - { "percent", 600, NULL }, - { "six", 600, NULL }, - { "paragraph", 600, NULL }, - { "dcaron", 600, NULL }, - { "Uogonek", 600, NULL }, - { "two", 600, NULL }, - { "summation", 600, NULL }, - { "Igrave", 600, NULL }, - { "Lacute", 600, NULL }, - { "ocircumflex", 600, NULL }, - { "oacute", 600, NULL }, - { "Uring", 600, NULL }, - { "Lcommaaccent", 600, NULL }, - { "tcaron", 600, NULL }, - { "eogonek", 600, NULL }, - { "Delta", 600, NULL }, - { "Ohungarumlaut", 600, NULL }, - { "asciicircum", 600, NULL }, - { "aring", 600, NULL }, - { "grave", 600, NULL }, - { "uogonek", 600, NULL }, - { "bracketright", 600, NULL }, - { "Iacute", 600, NULL }, - { "ampersand", 600, NULL }, - { "igrave", 600, NULL }, - { "lacute", 600, NULL }, - { "Ncaron", 600, NULL }, - { "plus", 600, NULL }, - { "uring", 600, NULL }, - { "quotesinglbase", 600, NULL }, - { "lcommaaccent", 600, NULL }, - { "Yacute", 600, NULL }, - { "ohungarumlaut", 600, NULL }, - { "threesuperior", 600, NULL }, - { "acute", 600, NULL }, - { "section", 600, NULL }, - { "dieresis", 600, NULL }, - { "iacute", 600, NULL }, - { "quotedblbase", 600, NULL }, - { "ncaron", 600, NULL }, - { "florin", 600, NULL }, - { "yacute", 600, NULL }, - { "Rcommaaccent", 600, NULL }, - { "fi", 600, NULL }, - { "fl", 600, NULL }, - { "Acircumflex", 600, NULL }, - { "Cacute", 600, NULL }, - { "Icircumflex", 600, NULL }, - { "guillemotleft", 600, NULL }, - { "germandbls", 600, NULL }, - { "Amacron", 600, NULL }, - { "seven", 600, NULL }, - { "Sacute", 600, NULL }, - { "ordmasculine", 600, NULL }, - { "dotlessi", 600, NULL }, - { "sterling", 600, NULL }, - { "notequal", 600, NULL }, - { "Imacron", 600, NULL }, - { "rcommaaccent", 600, NULL }, - { "Zdotaccent", 600, NULL }, - { "acircumflex", 600, NULL }, - { "cacute", 600, NULL }, - { "Ecaron", 600, NULL }, - { "icircumflex", 600, NULL }, - { "braceright", 600, NULL }, - { "quotedblright", 600, NULL }, - { "amacron", 600, NULL }, - { "sacute", 600, NULL }, - { "imacron", 600, NULL }, - { "cent", 600, NULL }, - { "currency", 600, NULL }, - { "logicalnot", 600, NULL }, - { "zdotaccent", 600, NULL }, - { "Atilde", 600, NULL }, - { "breve", 600, NULL }, - { "bar", 600, NULL }, - { "fraction", 600, NULL }, - { "less", 600, NULL }, - { "ecaron", 600, NULL }, - { "guilsinglleft", 600, NULL }, - { "exclam", 600, NULL }, - { "period", 600, NULL }, - { "Rcaron", 600, NULL }, - { "Kcommaaccent", 600, NULL }, - { "greater", 600, NULL }, - { "atilde", 600, NULL }, - { "brokenbar", 600, NULL }, - { "quoteleft", 600, NULL }, - { "Edotaccent", 600, NULL }, - { "onesuperior", 600, NULL } -}; - -static BuiltinFontWidth courierBoldObliqueWidthsTab[] = { - { "Ntilde", 600, NULL }, - { "rcaron", 600, NULL }, - { "kcommaaccent", 600, NULL }, - { "Ncommaaccent", 600, NULL }, - { "Zacute", 600, NULL }, - { "comma", 600, NULL }, - { "cedilla", 600, NULL }, - { "plusminus", 600, NULL }, - { "circumflex", 600, NULL }, - { "dotaccent", 600, NULL }, - { "edotaccent", 600, NULL }, - { "asciitilde", 600, NULL }, - { "colon", 600, NULL }, - { "onehalf", 600, NULL }, - { "dollar", 600, NULL }, - { "Lcaron", 600, NULL }, - { "ntilde", 600, NULL }, - { "Aogonek", 600, NULL }, - { "ncommaaccent", 600, NULL }, - { "minus", 600, NULL }, - { "Iogonek", 600, NULL }, - { "zacute", 600, NULL }, - { "yen", 600, NULL }, - { "space", 600, NULL }, - { "Omacron", 600, NULL }, - { "questiondown", 600, NULL }, - { "emdash", 600, NULL }, - { "Agrave", 600, NULL }, - { "three", 600, NULL }, - { "numbersign", 600, NULL }, - { "lcaron", 600, NULL }, - { "A", 600, NULL }, - { "B", 600, NULL }, - { "C", 600, NULL }, - { "aogonek", 600, NULL }, - { "D", 600, NULL }, - { "E", 600, NULL }, - { "onequarter", 600, NULL }, - { "F", 600, NULL }, - { "G", 600, NULL }, - { "H", 600, NULL }, - { "I", 600, NULL }, - { "J", 600, NULL }, - { "K", 600, NULL }, - { "iogonek", 600, NULL }, - { "backslash", 600, NULL }, - { "L", 600, NULL }, - { "periodcentered", 600, NULL }, - { "M", 600, NULL }, - { "N", 600, NULL }, - { "omacron", 600, NULL }, - { "Tcommaaccent", 600, NULL }, - { "O", 600, NULL }, - { "P", 600, NULL }, - { "Q", 600, NULL }, - { "Uhungarumlaut", 600, NULL }, - { "R", 600, NULL }, - { "Aacute", 600, NULL }, - { "caron", 600, NULL }, - { "S", 600, NULL }, - { "T", 600, NULL }, - { "U", 600, NULL }, - { "agrave", 600, NULL }, - { "V", 600, NULL }, - { "W", 600, NULL }, - { "X", 600, NULL }, - { "question", 600, NULL }, - { "equal", 600, NULL }, - { "Y", 600, NULL }, - { "Z", 600, NULL }, - { "four", 600, NULL }, - { "a", 600, NULL }, - { "Gcommaaccent", 600, NULL }, - { "b", 600, NULL }, - { "c", 600, NULL }, - { "d", 600, NULL }, - { "e", 600, NULL }, - { "f", 600, NULL }, - { "g", 600, NULL }, - { "bullet", 600, NULL }, - { "h", 600, NULL }, - { "i", 600, NULL }, - { "Oslash", 600, NULL }, - { "dagger", 600, NULL }, - { "j", 600, NULL }, - { "k", 600, NULL }, - { "l", 600, NULL }, - { "m", 600, NULL }, - { "n", 600, NULL }, - { "tcommaaccent", 600, NULL }, - { "o", 600, NULL }, - { "ordfeminine", 600, NULL }, - { "ring", 600, NULL }, - { "p", 600, NULL }, - { "q", 600, NULL }, - { "uhungarumlaut", 600, NULL }, - { "r", 600, NULL }, - { "twosuperior", 600, NULL }, - { "aacute", 600, NULL }, - { "s", 600, NULL }, - { "OE", 600, NULL }, - { "t", 600, NULL }, - { "divide", 600, NULL }, - { "u", 600, NULL }, - { "Ccaron", 600, NULL }, - { "v", 600, NULL }, - { "w", 600, NULL }, - { "x", 600, NULL }, - { "y", 600, NULL }, - { "z", 600, NULL }, - { "Gbreve", 600, NULL }, - { "commaaccent", 600, NULL }, - { "hungarumlaut", 600, NULL }, - { "Idotaccent", 600, NULL }, - { "Nacute", 600, NULL }, - { "quotedbl", 600, NULL }, - { "gcommaaccent", 600, NULL }, - { "mu", 600, NULL }, - { "greaterequal", 600, NULL }, - { "Scaron", 600, NULL }, - { "Lslash", 600, NULL }, - { "semicolon", 600, NULL }, - { "oslash", 600, NULL }, - { "lessequal", 600, NULL }, - { "lozenge", 600, NULL }, - { "parenright", 600, NULL }, - { "ccaron", 600, NULL }, - { "Ecircumflex", 600, NULL }, - { "gbreve", 600, NULL }, - { "trademark", 600, NULL }, - { "daggerdbl", 600, NULL }, - { "nacute", 600, NULL }, - { "macron", 600, NULL }, - { "Otilde", 600, NULL }, - { "Emacron", 600, NULL }, - { "ellipsis", 600, NULL }, - { "scaron", 600, NULL }, - { "AE", 600, NULL }, - { "Ucircumflex", 600, NULL }, - { "lslash", 600, NULL }, - { "quotedblleft", 600, NULL }, - { "guilsinglright", 600, NULL }, - { "hyphen", 600, NULL }, - { "quotesingle", 600, NULL }, - { "eight", 600, NULL }, - { "exclamdown", 600, NULL }, - { "endash", 600, NULL }, - { "oe", 600, NULL }, - { "Abreve", 600, NULL }, - { "Umacron", 600, NULL }, - { "ecircumflex", 600, NULL }, - { "Adieresis", 600, NULL }, - { "copyright", 600, NULL }, - { "Egrave", 600, NULL }, - { "slash", 600, NULL }, - { "Edieresis", 600, NULL }, - { "otilde", 600, NULL }, - { "Idieresis", 600, NULL }, - { "parenleft", 600, NULL }, - { "one", 600, NULL }, - { "emacron", 600, NULL }, - { "Odieresis", 600, NULL }, - { "ucircumflex", 600, NULL }, - { "bracketleft", 600, NULL }, - { "Ugrave", 600, NULL }, - { "quoteright", 600, NULL }, - { "Udieresis", 600, NULL }, - { "perthousand", 600, NULL }, - { "Ydieresis", 600, NULL }, - { "umacron", 600, NULL }, - { "abreve", 600, NULL }, - { "Eacute", 600, NULL }, - { "adieresis", 600, NULL }, - { "egrave", 600, NULL }, - { "edieresis", 600, NULL }, - { "idieresis", 600, NULL }, - { "Eth", 600, NULL }, - { "ae", 600, NULL }, - { "asterisk", 600, NULL }, - { "odieresis", 600, NULL }, - { "Uacute", 600, NULL }, - { "ugrave", 600, NULL }, - { "nine", 600, NULL }, - { "five", 600, NULL }, - { "udieresis", 600, NULL }, - { "Zcaron", 600, NULL }, - { "Scommaaccent", 600, NULL }, - { "threequarters", 600, NULL }, - { "guillemotright", 600, NULL }, - { "Ccedilla", 600, NULL }, - { "ydieresis", 600, NULL }, - { "tilde", 600, NULL }, - { "at", 600, NULL }, - { "eacute", 600, NULL }, - { "underscore", 600, NULL }, - { "Euro", 600, NULL }, - { "Dcroat", 600, NULL }, - { "multiply", 600, NULL }, - { "zero", 600, NULL }, - { "eth", 600, NULL }, - { "Scedilla", 600, NULL }, - { "Ograve", 600, NULL }, - { "Racute", 600, NULL }, - { "partialdiff", 600, NULL }, - { "uacute", 600, NULL }, - { "braceleft", 600, NULL }, - { "Thorn", 600, NULL }, - { "zcaron", 600, NULL }, - { "scommaaccent", 600, NULL }, - { "ccedilla", 600, NULL }, - { "Dcaron", 600, NULL }, - { "dcroat", 600, NULL }, - { "Ocircumflex", 600, NULL }, - { "Oacute", 600, NULL }, - { "scedilla", 600, NULL }, - { "ogonek", 600, NULL }, - { "ograve", 600, NULL }, - { "racute", 600, NULL }, - { "Tcaron", 600, NULL }, - { "Eogonek", 600, NULL }, - { "thorn", 600, NULL }, - { "degree", 600, NULL }, - { "registered", 600, NULL }, - { "radical", 600, NULL }, - { "Aring", 600, NULL }, - { "percent", 600, NULL }, - { "six", 600, NULL }, - { "paragraph", 600, NULL }, - { "dcaron", 600, NULL }, - { "Uogonek", 600, NULL }, - { "two", 600, NULL }, - { "summation", 600, NULL }, - { "Igrave", 600, NULL }, - { "Lacute", 600, NULL }, - { "ocircumflex", 600, NULL }, - { "oacute", 600, NULL }, - { "Uring", 600, NULL }, - { "Lcommaaccent", 600, NULL }, - { "tcaron", 600, NULL }, - { "eogonek", 600, NULL }, - { "Delta", 600, NULL }, - { "Ohungarumlaut", 600, NULL }, - { "asciicircum", 600, NULL }, - { "aring", 600, NULL }, - { "grave", 600, NULL }, - { "uogonek", 600, NULL }, - { "bracketright", 600, NULL }, - { "Iacute", 600, NULL }, - { "ampersand", 600, NULL }, - { "igrave", 600, NULL }, - { "lacute", 600, NULL }, - { "Ncaron", 600, NULL }, - { "plus", 600, NULL }, - { "uring", 600, NULL }, - { "quotesinglbase", 600, NULL }, - { "lcommaaccent", 600, NULL }, - { "Yacute", 600, NULL }, - { "ohungarumlaut", 600, NULL }, - { "threesuperior", 600, NULL }, - { "acute", 600, NULL }, - { "section", 600, NULL }, - { "dieresis", 600, NULL }, - { "iacute", 600, NULL }, - { "quotedblbase", 600, NULL }, - { "ncaron", 600, NULL }, - { "florin", 600, NULL }, - { "yacute", 600, NULL }, - { "Rcommaaccent", 600, NULL }, - { "fi", 600, NULL }, - { "fl", 600, NULL }, - { "Acircumflex", 600, NULL }, - { "Cacute", 600, NULL }, - { "Icircumflex", 600, NULL }, - { "guillemotleft", 600, NULL }, - { "germandbls", 600, NULL }, - { "Amacron", 600, NULL }, - { "seven", 600, NULL }, - { "Sacute", 600, NULL }, - { "ordmasculine", 600, NULL }, - { "dotlessi", 600, NULL }, - { "sterling", 600, NULL }, - { "notequal", 600, NULL }, - { "Imacron", 600, NULL }, - { "rcommaaccent", 600, NULL }, - { "Zdotaccent", 600, NULL }, - { "acircumflex", 600, NULL }, - { "cacute", 600, NULL }, - { "Ecaron", 600, NULL }, - { "icircumflex", 600, NULL }, - { "braceright", 600, NULL }, - { "quotedblright", 600, NULL }, - { "amacron", 600, NULL }, - { "sacute", 600, NULL }, - { "imacron", 600, NULL }, - { "cent", 600, NULL }, - { "currency", 600, NULL }, - { "logicalnot", 600, NULL }, - { "zdotaccent", 600, NULL }, - { "Atilde", 600, NULL }, - { "breve", 600, NULL }, - { "bar", 600, NULL }, - { "fraction", 600, NULL }, - { "less", 600, NULL }, - { "ecaron", 600, NULL }, - { "guilsinglleft", 600, NULL }, - { "exclam", 600, NULL }, - { "period", 600, NULL }, - { "Rcaron", 600, NULL }, - { "Kcommaaccent", 600, NULL }, - { "greater", 600, NULL }, - { "atilde", 600, NULL }, - { "brokenbar", 600, NULL }, - { "quoteleft", 600, NULL }, - { "Edotaccent", 600, NULL }, - { "onesuperior", 600, NULL } -}; - -static BuiltinFontWidth courierObliqueWidthsTab[] = { - { "Ntilde", 600, NULL }, - { "rcaron", 600, NULL }, - { "kcommaaccent", 600, NULL }, - { "Ncommaaccent", 600, NULL }, - { "Zacute", 600, NULL }, - { "comma", 600, NULL }, - { "cedilla", 600, NULL }, - { "plusminus", 600, NULL }, - { "circumflex", 600, NULL }, - { "dotaccent", 600, NULL }, - { "edotaccent", 600, NULL }, - { "asciitilde", 600, NULL }, - { "colon", 600, NULL }, - { "onehalf", 600, NULL }, - { "dollar", 600, NULL }, - { "Lcaron", 600, NULL }, - { "ntilde", 600, NULL }, - { "Aogonek", 600, NULL }, - { "ncommaaccent", 600, NULL }, - { "minus", 600, NULL }, - { "Iogonek", 600, NULL }, - { "zacute", 600, NULL }, - { "yen", 600, NULL }, - { "space", 600, NULL }, - { "Omacron", 600, NULL }, - { "questiondown", 600, NULL }, - { "emdash", 600, NULL }, - { "Agrave", 600, NULL }, - { "three", 600, NULL }, - { "numbersign", 600, NULL }, - { "lcaron", 600, NULL }, - { "A", 600, NULL }, - { "B", 600, NULL }, - { "C", 600, NULL }, - { "aogonek", 600, NULL }, - { "D", 600, NULL }, - { "E", 600, NULL }, - { "onequarter", 600, NULL }, - { "F", 600, NULL }, - { "G", 600, NULL }, - { "H", 600, NULL }, - { "I", 600, NULL }, - { "J", 600, NULL }, - { "K", 600, NULL }, - { "iogonek", 600, NULL }, - { "backslash", 600, NULL }, - { "L", 600, NULL }, - { "periodcentered", 600, NULL }, - { "M", 600, NULL }, - { "N", 600, NULL }, - { "omacron", 600, NULL }, - { "Tcommaaccent", 600, NULL }, - { "O", 600, NULL }, - { "P", 600, NULL }, - { "Q", 600, NULL }, - { "Uhungarumlaut", 600, NULL }, - { "R", 600, NULL }, - { "Aacute", 600, NULL }, - { "caron", 600, NULL }, - { "S", 600, NULL }, - { "T", 600, NULL }, - { "U", 600, NULL }, - { "agrave", 600, NULL }, - { "V", 600, NULL }, - { "W", 600, NULL }, - { "X", 600, NULL }, - { "question", 600, NULL }, - { "equal", 600, NULL }, - { "Y", 600, NULL }, - { "Z", 600, NULL }, - { "four", 600, NULL }, - { "a", 600, NULL }, - { "Gcommaaccent", 600, NULL }, - { "b", 600, NULL }, - { "c", 600, NULL }, - { "d", 600, NULL }, - { "e", 600, NULL }, - { "f", 600, NULL }, - { "g", 600, NULL }, - { "bullet", 600, NULL }, - { "h", 600, NULL }, - { "i", 600, NULL }, - { "Oslash", 600, NULL }, - { "dagger", 600, NULL }, - { "j", 600, NULL }, - { "k", 600, NULL }, - { "l", 600, NULL }, - { "m", 600, NULL }, - { "n", 600, NULL }, - { "tcommaaccent", 600, NULL }, - { "o", 600, NULL }, - { "ordfeminine", 600, NULL }, - { "ring", 600, NULL }, - { "p", 600, NULL }, - { "q", 600, NULL }, - { "uhungarumlaut", 600, NULL }, - { "r", 600, NULL }, - { "twosuperior", 600, NULL }, - { "aacute", 600, NULL }, - { "s", 600, NULL }, - { "OE", 600, NULL }, - { "t", 600, NULL }, - { "divide", 600, NULL }, - { "u", 600, NULL }, - { "Ccaron", 600, NULL }, - { "v", 600, NULL }, - { "w", 600, NULL }, - { "x", 600, NULL }, - { "y", 600, NULL }, - { "z", 600, NULL }, - { "Gbreve", 600, NULL }, - { "commaaccent", 600, NULL }, - { "hungarumlaut", 600, NULL }, - { "Idotaccent", 600, NULL }, - { "Nacute", 600, NULL }, - { "quotedbl", 600, NULL }, - { "gcommaaccent", 600, NULL }, - { "mu", 600, NULL }, - { "greaterequal", 600, NULL }, - { "Scaron", 600, NULL }, - { "Lslash", 600, NULL }, - { "semicolon", 600, NULL }, - { "oslash", 600, NULL }, - { "lessequal", 600, NULL }, - { "lozenge", 600, NULL }, - { "parenright", 600, NULL }, - { "ccaron", 600, NULL }, - { "Ecircumflex", 600, NULL }, - { "gbreve", 600, NULL }, - { "trademark", 600, NULL }, - { "daggerdbl", 600, NULL }, - { "nacute", 600, NULL }, - { "macron", 600, NULL }, - { "Otilde", 600, NULL }, - { "Emacron", 600, NULL }, - { "ellipsis", 600, NULL }, - { "scaron", 600, NULL }, - { "AE", 600, NULL }, - { "Ucircumflex", 600, NULL }, - { "lslash", 600, NULL }, - { "quotedblleft", 600, NULL }, - { "guilsinglright", 600, NULL }, - { "hyphen", 600, NULL }, - { "quotesingle", 600, NULL }, - { "eight", 600, NULL }, - { "exclamdown", 600, NULL }, - { "endash", 600, NULL }, - { "oe", 600, NULL }, - { "Abreve", 600, NULL }, - { "Umacron", 600, NULL }, - { "ecircumflex", 600, NULL }, - { "Adieresis", 600, NULL }, - { "copyright", 600, NULL }, - { "Egrave", 600, NULL }, - { "slash", 600, NULL }, - { "Edieresis", 600, NULL }, - { "otilde", 600, NULL }, - { "Idieresis", 600, NULL }, - { "parenleft", 600, NULL }, - { "one", 600, NULL }, - { "emacron", 600, NULL }, - { "Odieresis", 600, NULL }, - { "ucircumflex", 600, NULL }, - { "bracketleft", 600, NULL }, - { "Ugrave", 600, NULL }, - { "quoteright", 600, NULL }, - { "Udieresis", 600, NULL }, - { "perthousand", 600, NULL }, - { "Ydieresis", 600, NULL }, - { "umacron", 600, NULL }, - { "abreve", 600, NULL }, - { "Eacute", 600, NULL }, - { "adieresis", 600, NULL }, - { "egrave", 600, NULL }, - { "edieresis", 600, NULL }, - { "idieresis", 600, NULL }, - { "Eth", 600, NULL }, - { "ae", 600, NULL }, - { "asterisk", 600, NULL }, - { "odieresis", 600, NULL }, - { "Uacute", 600, NULL }, - { "ugrave", 600, NULL }, - { "nine", 600, NULL }, - { "five", 600, NULL }, - { "udieresis", 600, NULL }, - { "Zcaron", 600, NULL }, - { "Scommaaccent", 600, NULL }, - { "threequarters", 600, NULL }, - { "guillemotright", 600, NULL }, - { "Ccedilla", 600, NULL }, - { "ydieresis", 600, NULL }, - { "tilde", 600, NULL }, - { "at", 600, NULL }, - { "eacute", 600, NULL }, - { "underscore", 600, NULL }, - { "Euro", 600, NULL }, - { "Dcroat", 600, NULL }, - { "multiply", 600, NULL }, - { "zero", 600, NULL }, - { "eth", 600, NULL }, - { "Scedilla", 600, NULL }, - { "Ograve", 600, NULL }, - { "Racute", 600, NULL }, - { "partialdiff", 600, NULL }, - { "uacute", 600, NULL }, - { "braceleft", 600, NULL }, - { "Thorn", 600, NULL }, - { "zcaron", 600, NULL }, - { "scommaaccent", 600, NULL }, - { "ccedilla", 600, NULL }, - { "Dcaron", 600, NULL }, - { "dcroat", 600, NULL }, - { "Ocircumflex", 600, NULL }, - { "Oacute", 600, NULL }, - { "scedilla", 600, NULL }, - { "ogonek", 600, NULL }, - { "ograve", 600, NULL }, - { "racute", 600, NULL }, - { "Tcaron", 600, NULL }, - { "Eogonek", 600, NULL }, - { "thorn", 600, NULL }, - { "degree", 600, NULL }, - { "registered", 600, NULL }, - { "radical", 600, NULL }, - { "Aring", 600, NULL }, - { "percent", 600, NULL }, - { "six", 600, NULL }, - { "paragraph", 600, NULL }, - { "dcaron", 600, NULL }, - { "Uogonek", 600, NULL }, - { "two", 600, NULL }, - { "summation", 600, NULL }, - { "Igrave", 600, NULL }, - { "Lacute", 600, NULL }, - { "ocircumflex", 600, NULL }, - { "oacute", 600, NULL }, - { "Uring", 600, NULL }, - { "Lcommaaccent", 600, NULL }, - { "tcaron", 600, NULL }, - { "eogonek", 600, NULL }, - { "Delta", 600, NULL }, - { "Ohungarumlaut", 600, NULL }, - { "asciicircum", 600, NULL }, - { "aring", 600, NULL }, - { "grave", 600, NULL }, - { "uogonek", 600, NULL }, - { "bracketright", 600, NULL }, - { "Iacute", 600, NULL }, - { "ampersand", 600, NULL }, - { "igrave", 600, NULL }, - { "lacute", 600, NULL }, - { "Ncaron", 600, NULL }, - { "plus", 600, NULL }, - { "uring", 600, NULL }, - { "quotesinglbase", 600, NULL }, - { "lcommaaccent", 600, NULL }, - { "Yacute", 600, NULL }, - { "ohungarumlaut", 600, NULL }, - { "threesuperior", 600, NULL }, - { "acute", 600, NULL }, - { "section", 600, NULL }, - { "dieresis", 600, NULL }, - { "iacute", 600, NULL }, - { "quotedblbase", 600, NULL }, - { "ncaron", 600, NULL }, - { "florin", 600, NULL }, - { "yacute", 600, NULL }, - { "Rcommaaccent", 600, NULL }, - { "fi", 600, NULL }, - { "fl", 600, NULL }, - { "Acircumflex", 600, NULL }, - { "Cacute", 600, NULL }, - { "Icircumflex", 600, NULL }, - { "guillemotleft", 600, NULL }, - { "germandbls", 600, NULL }, - { "Amacron", 600, NULL }, - { "seven", 600, NULL }, - { "Sacute", 600, NULL }, - { "ordmasculine", 600, NULL }, - { "dotlessi", 600, NULL }, - { "sterling", 600, NULL }, - { "notequal", 600, NULL }, - { "Imacron", 600, NULL }, - { "rcommaaccent", 600, NULL }, - { "Zdotaccent", 600, NULL }, - { "acircumflex", 600, NULL }, - { "cacute", 600, NULL }, - { "Ecaron", 600, NULL }, - { "icircumflex", 600, NULL }, - { "braceright", 600, NULL }, - { "quotedblright", 600, NULL }, - { "amacron", 600, NULL }, - { "sacute", 600, NULL }, - { "imacron", 600, NULL }, - { "cent", 600, NULL }, - { "currency", 600, NULL }, - { "logicalnot", 600, NULL }, - { "zdotaccent", 600, NULL }, - { "Atilde", 600, NULL }, - { "breve", 600, NULL }, - { "bar", 600, NULL }, - { "fraction", 600, NULL }, - { "less", 600, NULL }, - { "ecaron", 600, NULL }, - { "guilsinglleft", 600, NULL }, - { "exclam", 600, NULL }, - { "period", 600, NULL }, - { "Rcaron", 600, NULL }, - { "Kcommaaccent", 600, NULL }, - { "greater", 600, NULL }, - { "atilde", 600, NULL }, - { "brokenbar", 600, NULL }, - { "quoteleft", 600, NULL }, - { "Edotaccent", 600, NULL }, - { "onesuperior", 600, NULL } -}; - -static BuiltinFontWidth helveticaWidthsTab[] = { - { "Ntilde", 722, NULL }, - { "rcaron", 333, NULL }, - { "kcommaaccent", 500, NULL }, - { "Ncommaaccent", 722, NULL }, - { "Zacute", 611, NULL }, - { "comma", 278, NULL }, - { "cedilla", 333, NULL }, - { "plusminus", 584, NULL }, - { "circumflex", 333, NULL }, - { "dotaccent", 333, NULL }, - { "edotaccent", 556, NULL }, - { "asciitilde", 584, NULL }, - { "colon", 278, NULL }, - { "onehalf", 834, NULL }, - { "dollar", 556, NULL }, - { "Lcaron", 556, NULL }, - { "ntilde", 556, NULL }, - { "Aogonek", 667, NULL }, - { "ncommaaccent", 556, NULL }, - { "minus", 584, NULL }, - { "Iogonek", 278, NULL }, - { "zacute", 500, NULL }, - { "yen", 556, NULL }, - { "space", 278, NULL }, - { "Omacron", 778, NULL }, - { "questiondown", 611, NULL }, - { "emdash", 1000, NULL }, - { "Agrave", 667, NULL }, - { "three", 556, NULL }, - { "numbersign", 556, NULL }, - { "lcaron", 299, NULL }, - { "A", 667, NULL }, - { "B", 667, NULL }, - { "C", 722, NULL }, - { "aogonek", 556, NULL }, - { "D", 722, NULL }, - { "E", 667, NULL }, - { "onequarter", 834, NULL }, - { "F", 611, NULL }, - { "G", 778, NULL }, - { "H", 722, NULL }, - { "I", 278, NULL }, - { "J", 500, NULL }, - { "K", 667, NULL }, - { "iogonek", 222, NULL }, - { "backslash", 278, NULL }, - { "L", 556, NULL }, - { "periodcentered", 278, NULL }, - { "M", 833, NULL }, - { "N", 722, NULL }, - { "omacron", 556, NULL }, - { "Tcommaaccent", 611, NULL }, - { "O", 778, NULL }, - { "P", 667, NULL }, - { "Q", 778, NULL }, - { "Uhungarumlaut", 722, NULL }, - { "R", 722, NULL }, - { "Aacute", 667, NULL }, - { "caron", 333, NULL }, - { "S", 667, NULL }, - { "T", 611, NULL }, - { "U", 722, NULL }, - { "agrave", 556, NULL }, - { "V", 667, NULL }, - { "W", 944, NULL }, - { "X", 667, NULL }, - { "question", 556, NULL }, - { "equal", 584, NULL }, - { "Y", 667, NULL }, - { "Z", 611, NULL }, - { "four", 556, NULL }, - { "a", 556, NULL }, - { "Gcommaaccent", 778, NULL }, - { "b", 556, NULL }, - { "c", 500, NULL }, - { "d", 556, NULL }, - { "e", 556, NULL }, - { "f", 278, NULL }, - { "g", 556, NULL }, - { "bullet", 350, NULL }, - { "h", 556, NULL }, - { "i", 222, NULL }, - { "Oslash", 778, NULL }, - { "dagger", 556, NULL }, - { "j", 222, NULL }, - { "k", 500, NULL }, - { "l", 222, NULL }, - { "m", 833, NULL }, - { "n", 556, NULL }, - { "tcommaaccent", 278, NULL }, - { "o", 556, NULL }, - { "ordfeminine", 370, NULL }, - { "ring", 333, NULL }, - { "p", 556, NULL }, - { "q", 556, NULL }, - { "uhungarumlaut", 556, NULL }, - { "r", 333, NULL }, - { "twosuperior", 333, NULL }, - { "aacute", 556, NULL }, - { "s", 500, NULL }, - { "OE", 1000, NULL }, - { "t", 278, NULL }, - { "divide", 584, NULL }, - { "u", 556, NULL }, - { "Ccaron", 722, NULL }, - { "v", 500, NULL }, - { "w", 722, NULL }, - { "x", 500, NULL }, - { "y", 500, NULL }, - { "z", 500, NULL }, - { "Gbreve", 778, NULL }, - { "commaaccent", 250, NULL }, - { "hungarumlaut", 333, NULL }, - { "Idotaccent", 278, NULL }, - { "Nacute", 722, NULL }, - { "quotedbl", 355, NULL }, - { "gcommaaccent", 556, NULL }, - { "mu", 556, NULL }, - { "greaterequal", 549, NULL }, - { "Scaron", 667, NULL }, - { "Lslash", 556, NULL }, - { "semicolon", 278, NULL }, - { "oslash", 611, NULL }, - { "lessequal", 549, NULL }, - { "lozenge", 471, NULL }, - { "parenright", 333, NULL }, - { "ccaron", 500, NULL }, - { "Ecircumflex", 667, NULL }, - { "gbreve", 556, NULL }, - { "trademark", 1000, NULL }, - { "daggerdbl", 556, NULL }, - { "nacute", 556, NULL }, - { "macron", 333, NULL }, - { "Otilde", 778, NULL }, - { "Emacron", 667, NULL }, - { "ellipsis", 1000, NULL }, - { "scaron", 500, NULL }, - { "AE", 1000, NULL }, - { "Ucircumflex", 722, NULL }, - { "lslash", 222, NULL }, - { "quotedblleft", 333, NULL }, - { "guilsinglright", 333, NULL }, - { "hyphen", 333, NULL }, - { "quotesingle", 191, NULL }, - { "eight", 556, NULL }, - { "exclamdown", 333, NULL }, - { "endash", 556, NULL }, - { "oe", 944, NULL }, - { "Abreve", 667, NULL }, - { "Umacron", 722, NULL }, - { "ecircumflex", 556, NULL }, - { "Adieresis", 667, NULL }, - { "copyright", 737, NULL }, - { "Egrave", 667, NULL }, - { "slash", 278, NULL }, - { "Edieresis", 667, NULL }, - { "otilde", 556, NULL }, - { "Idieresis", 278, NULL }, - { "parenleft", 333, NULL }, - { "one", 556, NULL }, - { "emacron", 556, NULL }, - { "Odieresis", 778, NULL }, - { "ucircumflex", 556, NULL }, - { "bracketleft", 278, NULL }, - { "Ugrave", 722, NULL }, - { "quoteright", 222, NULL }, - { "Udieresis", 722, NULL }, - { "perthousand", 1000, NULL }, - { "Ydieresis", 667, NULL }, - { "umacron", 556, NULL }, - { "abreve", 556, NULL }, - { "Eacute", 667, NULL }, - { "adieresis", 556, NULL }, - { "egrave", 556, NULL }, - { "edieresis", 556, NULL }, - { "idieresis", 278, NULL }, - { "Eth", 722, NULL }, - { "ae", 889, NULL }, - { "asterisk", 389, NULL }, - { "odieresis", 556, NULL }, - { "Uacute", 722, NULL }, - { "ugrave", 556, NULL }, - { "nine", 556, NULL }, - { "five", 556, NULL }, - { "udieresis", 556, NULL }, - { "Zcaron", 611, NULL }, - { "Scommaaccent", 667, NULL }, - { "threequarters", 834, NULL }, - { "guillemotright", 556, NULL }, - { "Ccedilla", 722, NULL }, - { "ydieresis", 500, NULL }, - { "tilde", 333, NULL }, - { "at", 1015, NULL }, - { "eacute", 556, NULL }, - { "underscore", 556, NULL }, - { "Euro", 556, NULL }, - { "Dcroat", 722, NULL }, - { "multiply", 584, NULL }, - { "zero", 556, NULL }, - { "eth", 556, NULL }, - { "Scedilla", 667, NULL }, - { "Ograve", 778, NULL }, - { "Racute", 722, NULL }, - { "partialdiff", 476, NULL }, - { "uacute", 556, NULL }, - { "braceleft", 334, NULL }, - { "Thorn", 667, NULL }, - { "zcaron", 500, NULL }, - { "scommaaccent", 500, NULL }, - { "ccedilla", 500, NULL }, - { "Dcaron", 722, NULL }, - { "dcroat", 556, NULL }, - { "Ocircumflex", 778, NULL }, - { "Oacute", 778, NULL }, - { "scedilla", 500, NULL }, - { "ogonek", 333, NULL }, - { "ograve", 556, NULL }, - { "racute", 333, NULL }, - { "Tcaron", 611, NULL }, - { "Eogonek", 667, NULL }, - { "thorn", 556, NULL }, - { "degree", 400, NULL }, - { "registered", 737, NULL }, - { "radical", 453, NULL }, - { "Aring", 667, NULL }, - { "percent", 889, NULL }, - { "six", 556, NULL }, - { "paragraph", 537, NULL }, - { "dcaron", 643, NULL }, - { "Uogonek", 722, NULL }, - { "two", 556, NULL }, - { "summation", 600, NULL }, - { "Igrave", 278, NULL }, - { "Lacute", 556, NULL }, - { "ocircumflex", 556, NULL }, - { "oacute", 556, NULL }, - { "Uring", 722, NULL }, - { "Lcommaaccent", 556, NULL }, - { "tcaron", 317, NULL }, - { "eogonek", 556, NULL }, - { "Delta", 612, NULL }, - { "Ohungarumlaut", 778, NULL }, - { "asciicircum", 469, NULL }, - { "aring", 556, NULL }, - { "grave", 333, NULL }, - { "uogonek", 556, NULL }, - { "bracketright", 278, NULL }, - { "Iacute", 278, NULL }, - { "ampersand", 667, NULL }, - { "igrave", 278, NULL }, - { "lacute", 222, NULL }, - { "Ncaron", 722, NULL }, - { "plus", 584, NULL }, - { "uring", 556, NULL }, - { "quotesinglbase", 222, NULL }, - { "lcommaaccent", 222, NULL }, - { "Yacute", 667, NULL }, - { "ohungarumlaut", 556, NULL }, - { "threesuperior", 333, NULL }, - { "acute", 333, NULL }, - { "section", 556, NULL }, - { "dieresis", 333, NULL }, - { "iacute", 278, NULL }, - { "quotedblbase", 333, NULL }, - { "ncaron", 556, NULL }, - { "florin", 556, NULL }, - { "yacute", 500, NULL }, - { "Rcommaaccent", 722, NULL }, - { "fi", 500, NULL }, - { "fl", 500, NULL }, - { "Acircumflex", 667, NULL }, - { "Cacute", 722, NULL }, - { "Icircumflex", 278, NULL }, - { "guillemotleft", 556, NULL }, - { "germandbls", 611, NULL }, - { "Amacron", 667, NULL }, - { "seven", 556, NULL }, - { "Sacute", 667, NULL }, - { "ordmasculine", 365, NULL }, - { "dotlessi", 278, NULL }, - { "sterling", 556, NULL }, - { "notequal", 549, NULL }, - { "Imacron", 278, NULL }, - { "rcommaaccent", 333, NULL }, - { "Zdotaccent", 611, NULL }, - { "acircumflex", 556, NULL }, - { "cacute", 500, NULL }, - { "Ecaron", 667, NULL }, - { "icircumflex", 278, NULL }, - { "braceright", 334, NULL }, - { "quotedblright", 333, NULL }, - { "amacron", 556, NULL }, - { "sacute", 500, NULL }, - { "imacron", 278, NULL }, - { "cent", 556, NULL }, - { "currency", 556, NULL }, - { "logicalnot", 584, NULL }, - { "zdotaccent", 500, NULL }, - { "Atilde", 667, NULL }, - { "breve", 333, NULL }, - { "bar", 260, NULL }, - { "fraction", 167, NULL }, - { "less", 584, NULL }, - { "ecaron", 556, NULL }, - { "guilsinglleft", 333, NULL }, - { "exclam", 278, NULL }, - { "period", 278, NULL }, - { "Rcaron", 722, NULL }, - { "Kcommaaccent", 667, NULL }, - { "greater", 584, NULL }, - { "atilde", 556, NULL }, - { "brokenbar", 260, NULL }, - { "quoteleft", 222, NULL }, - { "Edotaccent", 667, NULL }, - { "onesuperior", 333, NULL } -}; - -static BuiltinFontWidth helveticaBoldWidthsTab[] = { - { "Ntilde", 722, NULL }, - { "rcaron", 389, NULL }, - { "kcommaaccent", 556, NULL }, - { "Ncommaaccent", 722, NULL }, - { "Zacute", 611, NULL }, - { "comma", 278, NULL }, - { "cedilla", 333, NULL }, - { "plusminus", 584, NULL }, - { "circumflex", 333, NULL }, - { "dotaccent", 333, NULL }, - { "edotaccent", 556, NULL }, - { "asciitilde", 584, NULL }, - { "colon", 333, NULL }, - { "onehalf", 834, NULL }, - { "dollar", 556, NULL }, - { "Lcaron", 611, NULL }, - { "ntilde", 611, NULL }, - { "Aogonek", 722, NULL }, - { "ncommaaccent", 611, NULL }, - { "minus", 584, NULL }, - { "Iogonek", 278, NULL }, - { "zacute", 500, NULL }, - { "yen", 556, NULL }, - { "space", 278, NULL }, - { "Omacron", 778, NULL }, - { "questiondown", 611, NULL }, - { "emdash", 1000, NULL }, - { "Agrave", 722, NULL }, - { "three", 556, NULL }, - { "numbersign", 556, NULL }, - { "lcaron", 400, NULL }, - { "A", 722, NULL }, - { "B", 722, NULL }, - { "C", 722, NULL }, - { "aogonek", 556, NULL }, - { "D", 722, NULL }, - { "E", 667, NULL }, - { "onequarter", 834, NULL }, - { "F", 611, NULL }, - { "G", 778, NULL }, - { "H", 722, NULL }, - { "I", 278, NULL }, - { "J", 556, NULL }, - { "K", 722, NULL }, - { "iogonek", 278, NULL }, - { "backslash", 278, NULL }, - { "L", 611, NULL }, - { "periodcentered", 278, NULL }, - { "M", 833, NULL }, - { "N", 722, NULL }, - { "omacron", 611, NULL }, - { "Tcommaaccent", 611, NULL }, - { "O", 778, NULL }, - { "P", 667, NULL }, - { "Q", 778, NULL }, - { "Uhungarumlaut", 722, NULL }, - { "R", 722, NULL }, - { "Aacute", 722, NULL }, - { "caron", 333, NULL }, - { "S", 667, NULL }, - { "T", 611, NULL }, - { "U", 722, NULL }, - { "agrave", 556, NULL }, - { "V", 667, NULL }, - { "W", 944, NULL }, - { "X", 667, NULL }, - { "question", 611, NULL }, - { "equal", 584, NULL }, - { "Y", 667, NULL }, - { "Z", 611, NULL }, - { "four", 556, NULL }, - { "a", 556, NULL }, - { "Gcommaaccent", 778, NULL }, - { "b", 611, NULL }, - { "c", 556, NULL }, - { "d", 611, NULL }, - { "e", 556, NULL }, - { "f", 333, NULL }, - { "g", 611, NULL }, - { "bullet", 350, NULL }, - { "h", 611, NULL }, - { "i", 278, NULL }, - { "Oslash", 778, NULL }, - { "dagger", 556, NULL }, - { "j", 278, NULL }, - { "k", 556, NULL }, - { "l", 278, NULL }, - { "m", 889, NULL }, - { "n", 611, NULL }, - { "tcommaaccent", 333, NULL }, - { "o", 611, NULL }, - { "ordfeminine", 370, NULL }, - { "ring", 333, NULL }, - { "p", 611, NULL }, - { "q", 611, NULL }, - { "uhungarumlaut", 611, NULL }, - { "r", 389, NULL }, - { "twosuperior", 333, NULL }, - { "aacute", 556, NULL }, - { "s", 556, NULL }, - { "OE", 1000, NULL }, - { "t", 333, NULL }, - { "divide", 584, NULL }, - { "u", 611, NULL }, - { "Ccaron", 722, NULL }, - { "v", 556, NULL }, - { "w", 778, NULL }, - { "x", 556, NULL }, - { "y", 556, NULL }, - { "z", 500, NULL }, - { "Gbreve", 778, NULL }, - { "commaaccent", 250, NULL }, - { "hungarumlaut", 333, NULL }, - { "Idotaccent", 278, NULL }, - { "Nacute", 722, NULL }, - { "quotedbl", 474, NULL }, - { "gcommaaccent", 611, NULL }, - { "mu", 611, NULL }, - { "greaterequal", 549, NULL }, - { "Scaron", 667, NULL }, - { "Lslash", 611, NULL }, - { "semicolon", 333, NULL }, - { "oslash", 611, NULL }, - { "lessequal", 549, NULL }, - { "lozenge", 494, NULL }, - { "parenright", 333, NULL }, - { "ccaron", 556, NULL }, - { "Ecircumflex", 667, NULL }, - { "gbreve", 611, NULL }, - { "trademark", 1000, NULL }, - { "daggerdbl", 556, NULL }, - { "nacute", 611, NULL }, - { "macron", 333, NULL }, - { "Otilde", 778, NULL }, - { "Emacron", 667, NULL }, - { "ellipsis", 1000, NULL }, - { "scaron", 556, NULL }, - { "AE", 1000, NULL }, - { "Ucircumflex", 722, NULL }, - { "lslash", 278, NULL }, - { "quotedblleft", 500, NULL }, - { "guilsinglright", 333, NULL }, - { "hyphen", 333, NULL }, - { "quotesingle", 238, NULL }, - { "eight", 556, NULL }, - { "exclamdown", 333, NULL }, - { "endash", 556, NULL }, - { "oe", 944, NULL }, - { "Abreve", 722, NULL }, - { "Umacron", 722, NULL }, - { "ecircumflex", 556, NULL }, - { "Adieresis", 722, NULL }, - { "copyright", 737, NULL }, - { "Egrave", 667, NULL }, - { "slash", 278, NULL }, - { "Edieresis", 667, NULL }, - { "otilde", 611, NULL }, - { "Idieresis", 278, NULL }, - { "parenleft", 333, NULL }, - { "one", 556, NULL }, - { "emacron", 556, NULL }, - { "Odieresis", 778, NULL }, - { "ucircumflex", 611, NULL }, - { "bracketleft", 333, NULL }, - { "Ugrave", 722, NULL }, - { "quoteright", 278, NULL }, - { "Udieresis", 722, NULL }, - { "perthousand", 1000, NULL }, - { "Ydieresis", 667, NULL }, - { "umacron", 611, NULL }, - { "abreve", 556, NULL }, - { "Eacute", 667, NULL }, - { "adieresis", 556, NULL }, - { "egrave", 556, NULL }, - { "edieresis", 556, NULL }, - { "idieresis", 278, NULL }, - { "Eth", 722, NULL }, - { "ae", 889, NULL }, - { "asterisk", 389, NULL }, - { "odieresis", 611, NULL }, - { "Uacute", 722, NULL }, - { "ugrave", 611, NULL }, - { "nine", 556, NULL }, - { "five", 556, NULL }, - { "udieresis", 611, NULL }, - { "Zcaron", 611, NULL }, - { "Scommaaccent", 667, NULL }, - { "threequarters", 834, NULL }, - { "guillemotright", 556, NULL }, - { "Ccedilla", 722, NULL }, - { "ydieresis", 556, NULL }, - { "tilde", 333, NULL }, - { "dbldaggerumlaut", 556, NULL }, - { "at", 975, NULL }, - { "eacute", 556, NULL }, - { "underscore", 556, NULL }, - { "Euro", 556, NULL }, - { "Dcroat", 722, NULL }, - { "multiply", 584, NULL }, - { "zero", 556, NULL }, - { "eth", 611, NULL }, - { "Scedilla", 667, NULL }, - { "Ograve", 778, NULL }, - { "Racute", 722, NULL }, - { "partialdiff", 494, NULL }, - { "uacute", 611, NULL }, - { "braceleft", 389, NULL }, - { "Thorn", 667, NULL }, - { "zcaron", 500, NULL }, - { "scommaaccent", 556, NULL }, - { "ccedilla", 556, NULL }, - { "Dcaron", 722, NULL }, - { "dcroat", 611, NULL }, - { "Ocircumflex", 778, NULL }, - { "Oacute", 778, NULL }, - { "scedilla", 556, NULL }, - { "ogonek", 333, NULL }, - { "ograve", 611, NULL }, - { "racute", 389, NULL }, - { "Tcaron", 611, NULL }, - { "Eogonek", 667, NULL }, - { "thorn", 611, NULL }, - { "degree", 400, NULL }, - { "registered", 737, NULL }, - { "radical", 549, NULL }, - { "Aring", 722, NULL }, - { "percent", 889, NULL }, - { "six", 556, NULL }, - { "paragraph", 556, NULL }, - { "dcaron", 743, NULL }, - { "Uogonek", 722, NULL }, - { "two", 556, NULL }, - { "summation", 600, NULL }, - { "Igrave", 278, NULL }, - { "Lacute", 611, NULL }, - { "ocircumflex", 611, NULL }, - { "oacute", 611, NULL }, - { "Uring", 722, NULL }, - { "Lcommaaccent", 611, NULL }, - { "tcaron", 389, NULL }, - { "eogonek", 556, NULL }, - { "Delta", 612, NULL }, - { "Ohungarumlaut", 778, NULL }, - { "asciicircum", 584, NULL }, - { "aring", 556, NULL }, - { "grave", 333, NULL }, - { "uogonek", 611, NULL }, - { "bracketright", 333, NULL }, - { "Iacute", 278, NULL }, - { "ampersand", 722, NULL }, - { "igrave", 278, NULL }, - { "lacute", 278, NULL }, - { "Ncaron", 722, NULL }, - { "plus", 584, NULL }, - { "uring", 611, NULL }, - { "quotesinglbase", 278, NULL }, - { "lcommaaccent", 278, NULL }, - { "Yacute", 667, NULL }, - { "ohungarumlaut", 611, NULL }, - { "threesuperior", 333, NULL }, - { "acute", 333, NULL }, - { "section", 556, NULL }, - { "dieresis", 333, NULL }, - { "iacute", 278, NULL }, - { "quotedblbase", 500, NULL }, - { "ncaron", 611, NULL }, - { "florin", 556, NULL }, - { "yacute", 556, NULL }, - { "Rcommaaccent", 722, NULL }, - { "fi", 611, NULL }, - { "fl", 611, NULL }, - { "Acircumflex", 722, NULL }, - { "Cacute", 722, NULL }, - { "Icircumflex", 278, NULL }, - { "guillemotleft", 556, NULL }, - { "germandbls", 611, NULL }, - { "Amacron", 722, NULL }, - { "seven", 556, NULL }, - { "Sacute", 667, NULL }, - { "ordmasculine", 365, NULL }, - { "dotlessi", 278, NULL }, - { "sterling", 556, NULL }, - { "notequal", 549, NULL }, - { "Imacron", 278, NULL }, - { "rcommaaccent", 389, NULL }, - { "Zdotaccent", 611, NULL }, - { "acircumflex", 556, NULL }, - { "cacute", 556, NULL }, - { "Ecaron", 667, NULL }, - { "icircumflex", 278, NULL }, - { "braceright", 389, NULL }, - { "quotedblright", 500, NULL }, - { "amacron", 556, NULL }, - { "sacute", 556, NULL }, - { "imacron", 278, NULL }, - { "cent", 556, NULL }, - { "currency", 556, NULL }, - { "logicalnot", 584, NULL }, - { "zdotaccent", 500, NULL }, - { "Atilde", 722, NULL }, - { "breve", 333, NULL }, - { "bar", 280, NULL }, - { "fraction", 167, NULL }, - { "less", 584, NULL }, - { "ecaron", 556, NULL }, - { "guilsinglleft", 333, NULL }, - { "exclam", 333, NULL }, - { "period", 278, NULL }, - { "Rcaron", 722, NULL }, - { "Kcommaaccent", 722, NULL }, - { "greater", 584, NULL }, - { "atilde", 556, NULL }, - { "brokenbar", 280, NULL }, - { "quoteleft", 278, NULL }, - { "Edotaccent", 667, NULL }, - { "onesuperior", 333, NULL } -}; - -static BuiltinFontWidth helveticaBoldObliqueWidthsTab[] = { - { "Ntilde", 722, NULL }, - { "rcaron", 389, NULL }, - { "kcommaaccent", 556, NULL }, - { "Ncommaaccent", 722, NULL }, - { "Zacute", 611, NULL }, - { "comma", 278, NULL }, - { "cedilla", 333, NULL }, - { "plusminus", 584, NULL }, - { "circumflex", 333, NULL }, - { "dotaccent", 333, NULL }, - { "edotaccent", 556, NULL }, - { "asciitilde", 584, NULL }, - { "colon", 333, NULL }, - { "onehalf", 834, NULL }, - { "dollar", 556, NULL }, - { "Lcaron", 611, NULL }, - { "ntilde", 611, NULL }, - { "Aogonek", 722, NULL }, - { "ncommaaccent", 611, NULL }, - { "minus", 584, NULL }, - { "Iogonek", 278, NULL }, - { "zacute", 500, NULL }, - { "yen", 556, NULL }, - { "space", 278, NULL }, - { "Omacron", 778, NULL }, - { "questiondown", 611, NULL }, - { "emdash", 1000, NULL }, - { "Agrave", 722, NULL }, - { "three", 556, NULL }, - { "numbersign", 556, NULL }, - { "lcaron", 400, NULL }, - { "A", 722, NULL }, - { "B", 722, NULL }, - { "C", 722, NULL }, - { "aogonek", 556, NULL }, - { "D", 722, NULL }, - { "E", 667, NULL }, - { "onequarter", 834, NULL }, - { "F", 611, NULL }, - { "G", 778, NULL }, - { "H", 722, NULL }, - { "I", 278, NULL }, - { "J", 556, NULL }, - { "K", 722, NULL }, - { "iogonek", 278, NULL }, - { "backslash", 278, NULL }, - { "L", 611, NULL }, - { "periodcentered", 278, NULL }, - { "M", 833, NULL }, - { "N", 722, NULL }, - { "omacron", 611, NULL }, - { "Tcommaaccent", 611, NULL }, - { "O", 778, NULL }, - { "P", 667, NULL }, - { "Q", 778, NULL }, - { "Uhungarumlaut", 722, NULL }, - { "R", 722, NULL }, - { "Aacute", 722, NULL }, - { "caron", 333, NULL }, - { "S", 667, NULL }, - { "T", 611, NULL }, - { "U", 722, NULL }, - { "agrave", 556, NULL }, - { "V", 667, NULL }, - { "W", 944, NULL }, - { "X", 667, NULL }, - { "question", 611, NULL }, - { "equal", 584, NULL }, - { "Y", 667, NULL }, - { "Z", 611, NULL }, - { "four", 556, NULL }, - { "a", 556, NULL }, - { "Gcommaaccent", 778, NULL }, - { "b", 611, NULL }, - { "c", 556, NULL }, - { "d", 611, NULL }, - { "e", 556, NULL }, - { "f", 333, NULL }, - { "g", 611, NULL }, - { "bullet", 350, NULL }, - { "h", 611, NULL }, - { "i", 278, NULL }, - { "Oslash", 778, NULL }, - { "dagger", 556, NULL }, - { "j", 278, NULL }, - { "k", 556, NULL }, - { "l", 278, NULL }, - { "m", 889, NULL }, - { "n", 611, NULL }, - { "tcommaaccent", 333, NULL }, - { "o", 611, NULL }, - { "ordfeminine", 370, NULL }, - { "ring", 333, NULL }, - { "p", 611, NULL }, - { "q", 611, NULL }, - { "uhungarumlaut", 611, NULL }, - { "r", 389, NULL }, - { "twosuperior", 333, NULL }, - { "aacute", 556, NULL }, - { "s", 556, NULL }, - { "OE", 1000, NULL }, - { "t", 333, NULL }, - { "divide", 584, NULL }, - { "u", 611, NULL }, - { "Ccaron", 722, NULL }, - { "v", 556, NULL }, - { "w", 778, NULL }, - { "x", 556, NULL }, - { "y", 556, NULL }, - { "z", 500, NULL }, - { "Gbreve", 778, NULL }, - { "commaaccent", 250, NULL }, - { "hungarumlaut", 333, NULL }, - { "Idotaccent", 278, NULL }, - { "Nacute", 722, NULL }, - { "quotedbl", 474, NULL }, - { "gcommaaccent", 611, NULL }, - { "mu", 611, NULL }, - { "greaterequal", 549, NULL }, - { "Scaron", 667, NULL }, - { "Lslash", 611, NULL }, - { "semicolon", 333, NULL }, - { "oslash", 611, NULL }, - { "lessequal", 549, NULL }, - { "lozenge", 494, NULL }, - { "parenright", 333, NULL }, - { "ccaron", 556, NULL }, - { "Ecircumflex", 667, NULL }, - { "gbreve", 611, NULL }, - { "trademark", 1000, NULL }, - { "daggerdbl", 556, NULL }, - { "nacute", 611, NULL }, - { "macron", 333, NULL }, - { "Otilde", 778, NULL }, - { "Emacron", 667, NULL }, - { "ellipsis", 1000, NULL }, - { "scaron", 556, NULL }, - { "AE", 1000, NULL }, - { "Ucircumflex", 722, NULL }, - { "lslash", 278, NULL }, - { "quotedblleft", 500, NULL }, - { "guilsinglright", 333, NULL }, - { "hyphen", 333, NULL }, - { "quotesingle", 238, NULL }, - { "eight", 556, NULL }, - { "exclamdown", 333, NULL }, - { "endash", 556, NULL }, - { "oe", 944, NULL }, - { "Abreve", 722, NULL }, - { "Umacron", 722, NULL }, - { "ecircumflex", 556, NULL }, - { "Adieresis", 722, NULL }, - { "copyright", 737, NULL }, - { "Egrave", 667, NULL }, - { "slash", 278, NULL }, - { "Edieresis", 667, NULL }, - { "otilde", 611, NULL }, - { "Idieresis", 278, NULL }, - { "parenleft", 333, NULL }, - { "one", 556, NULL }, - { "emacron", 556, NULL }, - { "Odieresis", 778, NULL }, - { "ucircumflex", 611, NULL }, - { "bracketleft", 333, NULL }, - { "Ugrave", 722, NULL }, - { "quoteright", 278, NULL }, - { "Udieresis", 722, NULL }, - { "perthousand", 1000, NULL }, - { "Ydieresis", 667, NULL }, - { "umacron", 611, NULL }, - { "abreve", 556, NULL }, - { "Eacute", 667, NULL }, - { "adieresis", 556, NULL }, - { "egrave", 556, NULL }, - { "edieresis", 556, NULL }, - { "idieresis", 278, NULL }, - { "Eth", 722, NULL }, - { "ae", 889, NULL }, - { "asterisk", 389, NULL }, - { "odieresis", 611, NULL }, - { "Uacute", 722, NULL }, - { "ugrave", 611, NULL }, - { "nine", 556, NULL }, - { "five", 556, NULL }, - { "udieresis", 611, NULL }, - { "Zcaron", 611, NULL }, - { "Scommaaccent", 667, NULL }, - { "threequarters", 834, NULL }, - { "guillemotright", 556, NULL }, - { "Ccedilla", 722, NULL }, - { "ydieresis", 556, NULL }, - { "tilde", 333, NULL }, - { "at", 975, NULL }, - { "eacute", 556, NULL }, - { "underscore", 556, NULL }, - { "Euro", 556, NULL }, - { "Dcroat", 722, NULL }, - { "multiply", 584, NULL }, - { "zero", 556, NULL }, - { "eth", 611, NULL }, - { "Scedilla", 667, NULL }, - { "Ograve", 778, NULL }, - { "Racute", 722, NULL }, - { "partialdiff", 494, NULL }, - { "uacute", 611, NULL }, - { "braceleft", 389, NULL }, - { "Thorn", 667, NULL }, - { "zcaron", 500, NULL }, - { "scommaaccent", 556, NULL }, - { "ccedilla", 556, NULL }, - { "Dcaron", 722, NULL }, - { "dcroat", 611, NULL }, - { "Ocircumflex", 778, NULL }, - { "Oacute", 778, NULL }, - { "scedilla", 556, NULL }, - { "ogonek", 333, NULL }, - { "ograve", 611, NULL }, - { "racute", 389, NULL }, - { "Tcaron", 611, NULL }, - { "Eogonek", 667, NULL }, - { "thorn", 611, NULL }, - { "degree", 400, NULL }, - { "registered", 737, NULL }, - { "radical", 549, NULL }, - { "Aring", 722, NULL }, - { "percent", 889, NULL }, - { "six", 556, NULL }, - { "paragraph", 556, NULL }, - { "dcaron", 743, NULL }, - { "Uogonek", 722, NULL }, - { "two", 556, NULL }, - { "summation", 600, NULL }, - { "Igrave", 278, NULL }, - { "Lacute", 611, NULL }, - { "ocircumflex", 611, NULL }, - { "oacute", 611, NULL }, - { "Uring", 722, NULL }, - { "Lcommaaccent", 611, NULL }, - { "tcaron", 389, NULL }, - { "eogonek", 556, NULL }, - { "Delta", 612, NULL }, - { "Ohungarumlaut", 778, NULL }, - { "asciicircum", 584, NULL }, - { "aring", 556, NULL }, - { "grave", 333, NULL }, - { "uogonek", 611, NULL }, - { "bracketright", 333, NULL }, - { "Iacute", 278, NULL }, - { "ampersand", 722, NULL }, - { "igrave", 278, NULL }, - { "lacute", 278, NULL }, - { "Ncaron", 722, NULL }, - { "plus", 584, NULL }, - { "uring", 611, NULL }, - { "quotesinglbase", 278, NULL }, - { "lcommaaccent", 278, NULL }, - { "Yacute", 667, NULL }, - { "ohungarumlaut", 611, NULL }, - { "threesuperior", 333, NULL }, - { "acute", 333, NULL }, - { "section", 556, NULL }, - { "dieresis", 333, NULL }, - { "iacute", 278, NULL }, - { "quotedblbase", 500, NULL }, - { "ncaron", 611, NULL }, - { "florin", 556, NULL }, - { "yacute", 556, NULL }, - { "Rcommaaccent", 722, NULL }, - { "fi", 611, NULL }, - { "fl", 611, NULL }, - { "Acircumflex", 722, NULL }, - { "Cacute", 722, NULL }, - { "Icircumflex", 278, NULL }, - { "guillemotleft", 556, NULL }, - { "germandbls", 611, NULL }, - { "Amacron", 722, NULL }, - { "seven", 556, NULL }, - { "Sacute", 667, NULL }, - { "ordmasculine", 365, NULL }, - { "dotlessi", 278, NULL }, - { "sterling", 556, NULL }, - { "notequal", 549, NULL }, - { "Imacron", 278, NULL }, - { "rcommaaccent", 389, NULL }, - { "Zdotaccent", 611, NULL }, - { "acircumflex", 556, NULL }, - { "cacute", 556, NULL }, - { "Ecaron", 667, NULL }, - { "icircumflex", 278, NULL }, - { "braceright", 389, NULL }, - { "quotedblright", 500, NULL }, - { "amacron", 556, NULL }, - { "sacute", 556, NULL }, - { "imacron", 278, NULL }, - { "cent", 556, NULL }, - { "currency", 556, NULL }, - { "logicalnot", 584, NULL }, - { "zdotaccent", 500, NULL }, - { "Atilde", 722, NULL }, - { "breve", 333, NULL }, - { "bar", 280, NULL }, - { "fraction", 167, NULL }, - { "less", 584, NULL }, - { "ecaron", 556, NULL }, - { "guilsinglleft", 333, NULL }, - { "exclam", 333, NULL }, - { "period", 278, NULL }, - { "Rcaron", 722, NULL }, - { "Kcommaaccent", 722, NULL }, - { "greater", 584, NULL }, - { "atilde", 556, NULL }, - { "brokenbar", 280, NULL }, - { "quoteleft", 278, NULL }, - { "Edotaccent", 667, NULL }, - { "onesuperior", 333, NULL } -}; - -static BuiltinFontWidth helveticaObliqueWidthsTab[] = { - { "Ntilde", 722, NULL }, - { "rcaron", 333, NULL }, - { "kcommaaccent", 500, NULL }, - { "Ncommaaccent", 722, NULL }, - { "Zacute", 611, NULL }, - { "comma", 278, NULL }, - { "cedilla", 333, NULL }, - { "plusminus", 584, NULL }, - { "circumflex", 333, NULL }, - { "dotaccent", 333, NULL }, - { "edotaccent", 556, NULL }, - { "asciitilde", 584, NULL }, - { "colon", 278, NULL }, - { "onehalf", 834, NULL }, - { "dollar", 556, NULL }, - { "Lcaron", 556, NULL }, - { "ntilde", 556, NULL }, - { "Aogonek", 667, NULL }, - { "ncommaaccent", 556, NULL }, - { "minus", 584, NULL }, - { "Iogonek", 278, NULL }, - { "zacute", 500, NULL }, - { "yen", 556, NULL }, - { "space", 278, NULL }, - { "Omacron", 778, NULL }, - { "questiondown", 611, NULL }, - { "emdash", 1000, NULL }, - { "Agrave", 667, NULL }, - { "three", 556, NULL }, - { "numbersign", 556, NULL }, - { "lcaron", 299, NULL }, - { "A", 667, NULL }, - { "B", 667, NULL }, - { "C", 722, NULL }, - { "aogonek", 556, NULL }, - { "D", 722, NULL }, - { "E", 667, NULL }, - { "onequarter", 834, NULL }, - { "F", 611, NULL }, - { "G", 778, NULL }, - { "H", 722, NULL }, - { "I", 278, NULL }, - { "J", 500, NULL }, - { "K", 667, NULL }, - { "iogonek", 222, NULL }, - { "backslash", 278, NULL }, - { "L", 556, NULL }, - { "periodcentered", 278, NULL }, - { "M", 833, NULL }, - { "N", 722, NULL }, - { "omacron", 556, NULL }, - { "Tcommaaccent", 611, NULL }, - { "O", 778, NULL }, - { "P", 667, NULL }, - { "Q", 778, NULL }, - { "Uhungarumlaut", 722, NULL }, - { "R", 722, NULL }, - { "Aacute", 667, NULL }, - { "caron", 333, NULL }, - { "S", 667, NULL }, - { "T", 611, NULL }, - { "U", 722, NULL }, - { "agrave", 556, NULL }, - { "V", 667, NULL }, - { "W", 944, NULL }, - { "X", 667, NULL }, - { "question", 556, NULL }, - { "equal", 584, NULL }, - { "Y", 667, NULL }, - { "Z", 611, NULL }, - { "four", 556, NULL }, - { "a", 556, NULL }, - { "Gcommaaccent", 778, NULL }, - { "b", 556, NULL }, - { "c", 500, NULL }, - { "d", 556, NULL }, - { "e", 556, NULL }, - { "f", 278, NULL }, - { "g", 556, NULL }, - { "bullet", 350, NULL }, - { "h", 556, NULL }, - { "i", 222, NULL }, - { "Oslash", 778, NULL }, - { "dagger", 556, NULL }, - { "j", 222, NULL }, - { "k", 500, NULL }, - { "l", 222, NULL }, - { "m", 833, NULL }, - { "n", 556, NULL }, - { "tcommaaccent", 278, NULL }, - { "o", 556, NULL }, - { "ordfeminine", 370, NULL }, - { "ring", 333, NULL }, - { "p", 556, NULL }, - { "q", 556, NULL }, - { "uhungarumlaut", 556, NULL }, - { "r", 333, NULL }, - { "twosuperior", 333, NULL }, - { "aacute", 556, NULL }, - { "s", 500, NULL }, - { "OE", 1000, NULL }, - { "t", 278, NULL }, - { "divide", 584, NULL }, - { "u", 556, NULL }, - { "Ccaron", 722, NULL }, - { "v", 500, NULL }, - { "w", 722, NULL }, - { "x", 500, NULL }, - { "y", 500, NULL }, - { "z", 500, NULL }, - { "Gbreve", 778, NULL }, - { "commaaccent", 250, NULL }, - { "hungarumlaut", 333, NULL }, - { "Idotaccent", 278, NULL }, - { "Nacute", 722, NULL }, - { "quotedbl", 355, NULL }, - { "gcommaaccent", 556, NULL }, - { "mu", 556, NULL }, - { "greaterequal", 549, NULL }, - { "Scaron", 667, NULL }, - { "Lslash", 556, NULL }, - { "semicolon", 278, NULL }, - { "oslash", 611, NULL }, - { "lessequal", 549, NULL }, - { "lozenge", 471, NULL }, - { "parenright", 333, NULL }, - { "ccaron", 500, NULL }, - { "Ecircumflex", 667, NULL }, - { "gbreve", 556, NULL }, - { "trademark", 1000, NULL }, - { "daggerdbl", 556, NULL }, - { "nacute", 556, NULL }, - { "macron", 333, NULL }, - { "Otilde", 778, NULL }, - { "Emacron", 667, NULL }, - { "ellipsis", 1000, NULL }, - { "scaron", 500, NULL }, - { "AE", 1000, NULL }, - { "Ucircumflex", 722, NULL }, - { "lslash", 222, NULL }, - { "quotedblleft", 333, NULL }, - { "guilsinglright", 333, NULL }, - { "hyphen", 333, NULL }, - { "quotesingle", 191, NULL }, - { "eight", 556, NULL }, - { "exclamdown", 333, NULL }, - { "endash", 556, NULL }, - { "oe", 944, NULL }, - { "Abreve", 667, NULL }, - { "Umacron", 722, NULL }, - { "ecircumflex", 556, NULL }, - { "Adieresis", 667, NULL }, - { "copyright", 737, NULL }, - { "Egrave", 667, NULL }, - { "slash", 278, NULL }, - { "Edieresis", 667, NULL }, - { "otilde", 556, NULL }, - { "Idieresis", 278, NULL }, - { "parenleft", 333, NULL }, - { "one", 556, NULL }, - { "emacron", 556, NULL }, - { "Odieresis", 778, NULL }, - { "ucircumflex", 556, NULL }, - { "bracketleft", 278, NULL }, - { "Ugrave", 722, NULL }, - { "quoteright", 222, NULL }, - { "Udieresis", 722, NULL }, - { "perthousand", 1000, NULL }, - { "Ydieresis", 667, NULL }, - { "umacron", 556, NULL }, - { "abreve", 556, NULL }, - { "Eacute", 667, NULL }, - { "adieresis", 556, NULL }, - { "egrave", 556, NULL }, - { "edieresis", 556, NULL }, - { "idieresis", 278, NULL }, - { "Eth", 722, NULL }, - { "ae", 889, NULL }, - { "asterisk", 389, NULL }, - { "odieresis", 556, NULL }, - { "Uacute", 722, NULL }, - { "ugrave", 556, NULL }, - { "nine", 556, NULL }, - { "five", 556, NULL }, - { "udieresis", 556, NULL }, - { "Zcaron", 611, NULL }, - { "Scommaaccent", 667, NULL }, - { "threequarters", 834, NULL }, - { "guillemotright", 556, NULL }, - { "Ccedilla", 722, NULL }, - { "ydieresis", 500, NULL }, - { "tilde", 333, NULL }, - { "at", 1015, NULL }, - { "eacute", 556, NULL }, - { "underscore", 556, NULL }, - { "Euro", 556, NULL }, - { "Dcroat", 722, NULL }, - { "multiply", 584, NULL }, - { "zero", 556, NULL }, - { "eth", 556, NULL }, - { "Scedilla", 667, NULL }, - { "Ograve", 778, NULL }, - { "Racute", 722, NULL }, - { "partialdiff", 476, NULL }, - { "uacute", 556, NULL }, - { "braceleft", 334, NULL }, - { "Thorn", 667, NULL }, - { "zcaron", 500, NULL }, - { "scommaaccent", 500, NULL }, - { "ccedilla", 500, NULL }, - { "Dcaron", 722, NULL }, - { "dcroat", 556, NULL }, - { "Ocircumflex", 778, NULL }, - { "Oacute", 778, NULL }, - { "scedilla", 500, NULL }, - { "ogonek", 333, NULL }, - { "ograve", 556, NULL }, - { "racute", 333, NULL }, - { "Tcaron", 611, NULL }, - { "Eogonek", 667, NULL }, - { "thorn", 556, NULL }, - { "degree", 400, NULL }, - { "registered", 737, NULL }, - { "radical", 453, NULL }, - { "Aring", 667, NULL }, - { "percent", 889, NULL }, - { "six", 556, NULL }, - { "paragraph", 537, NULL }, - { "dcaron", 643, NULL }, - { "Uogonek", 722, NULL }, - { "two", 556, NULL }, - { "summation", 600, NULL }, - { "Igrave", 278, NULL }, - { "Lacute", 556, NULL }, - { "ocircumflex", 556, NULL }, - { "oacute", 556, NULL }, - { "Uring", 722, NULL }, - { "Lcommaaccent", 556, NULL }, - { "tcaron", 317, NULL }, - { "eogonek", 556, NULL }, - { "Delta", 612, NULL }, - { "Ohungarumlaut", 778, NULL }, - { "asciicircum", 469, NULL }, - { "aring", 556, NULL }, - { "grave", 333, NULL }, - { "uogonek", 556, NULL }, - { "bracketright", 278, NULL }, - { "Iacute", 278, NULL }, - { "ampersand", 667, NULL }, - { "igrave", 278, NULL }, - { "lacute", 222, NULL }, - { "Ncaron", 722, NULL }, - { "plus", 584, NULL }, - { "uring", 556, NULL }, - { "quotesinglbase", 222, NULL }, - { "lcommaaccent", 222, NULL }, - { "Yacute", 667, NULL }, - { "ohungarumlaut", 556, NULL }, - { "threesuperior", 333, NULL }, - { "acute", 333, NULL }, - { "section", 556, NULL }, - { "dieresis", 333, NULL }, - { "iacute", 278, NULL }, - { "quotedblbase", 333, NULL }, - { "ncaron", 556, NULL }, - { "florin", 556, NULL }, - { "yacute", 500, NULL }, - { "Rcommaaccent", 722, NULL }, - { "fi", 500, NULL }, - { "fl", 500, NULL }, - { "Acircumflex", 667, NULL }, - { "Cacute", 722, NULL }, - { "Icircumflex", 278, NULL }, - { "guillemotleft", 556, NULL }, - { "germandbls", 611, NULL }, - { "Amacron", 667, NULL }, - { "seven", 556, NULL }, - { "Sacute", 667, NULL }, - { "ordmasculine", 365, NULL }, - { "dotlessi", 278, NULL }, - { "sterling", 556, NULL }, - { "notequal", 549, NULL }, - { "Imacron", 278, NULL }, - { "rcommaaccent", 333, NULL }, - { "Zdotaccent", 611, NULL }, - { "acircumflex", 556, NULL }, - { "cacute", 500, NULL }, - { "Ecaron", 667, NULL }, - { "icircumflex", 278, NULL }, - { "braceright", 334, NULL }, - { "quotedblright", 333, NULL }, - { "amacron", 556, NULL }, - { "sacute", 500, NULL }, - { "imacron", 278, NULL }, - { "cent", 556, NULL }, - { "currency", 556, NULL }, - { "logicalnot", 584, NULL }, - { "zdotaccent", 500, NULL }, - { "Atilde", 667, NULL }, - { "breve", 333, NULL }, - { "bar", 260, NULL }, - { "fraction", 167, NULL }, - { "less", 584, NULL }, - { "ecaron", 556, NULL }, - { "guilsinglleft", 333, NULL }, - { "exclam", 278, NULL }, - { "period", 278, NULL }, - { "Rcaron", 722, NULL }, - { "Kcommaaccent", 667, NULL }, - { "greater", 584, NULL }, - { "atilde", 556, NULL }, - { "brokenbar", 260, NULL }, - { "quoteleft", 222, NULL }, - { "Edotaccent", 667, NULL }, - { "onesuperior", 333, NULL } -}; - -static BuiltinFontWidth symbolWidthsTab[] = { - { "bracketleftex", 384, NULL }, - { "alpha", 631, NULL }, - { "union", 768, NULL }, - { "infinity", 713, NULL }, - { "comma", 250, NULL }, - { "copyrightsans", 790, NULL }, - { "plusminus", 549, NULL }, - { "arrowup", 603, NULL }, - { "apple", 790, NULL }, - { "parenleftbt", 384, NULL }, - { "notelement", 713, NULL }, - { "colon", 278, NULL }, - { "beta", 549, NULL }, - { "braceleftbt", 494, NULL }, - { "Lambda", 686, NULL }, - { "Phi", 763, NULL }, - { "minus", 549, NULL }, - { "space", 250, NULL }, - { "Sigma", 592, NULL }, - { "approxequal", 549, NULL }, - { "minute", 247, NULL }, - { "circleplus", 768, NULL }, - { "Omicron", 722, NULL }, - { "three", 500, NULL }, - { "numbersign", 500, NULL }, - { "lambda", 549, NULL }, - { "phi", 521, NULL }, - { "aleph", 823, NULL }, - { "Tau", 611, NULL }, - { "spade", 753, NULL }, - { "logicaland", 603, NULL }, - { "sigma", 603, NULL }, - { "propersuperset", 713, NULL }, - { "omicron", 549, NULL }, - { "question", 444, NULL }, - { "equal", 549, NULL }, - { "Epsilon", 611, NULL }, - { "emptyset", 823, NULL }, - { "diamond", 753, NULL }, - { "four", 500, NULL }, - { "Mu", 889, NULL }, - { "parenlefttp", 384, NULL }, - { "club", 753, NULL }, - { "bullet", 460, NULL }, - { "Omega", 768, NULL }, - { "tau", 439, NULL }, - { "Upsilon", 690, NULL }, - { "bracelefttp", 494, NULL }, - { "heart", 753, NULL }, - { "divide", 549, NULL }, - { "epsilon", 439, NULL }, - { "logicalor", 603, NULL }, - { "parenleftex", 384, NULL }, - { "greaterequal", 549, NULL }, - { "mu", 576, NULL }, - { "Nu", 722, NULL }, - { "therefore", 863, NULL }, - { "notsubset", 713, NULL }, - { "omega", 686, NULL }, - { "semicolon", 278, NULL }, - { "element", 713, NULL }, - { "upsilon", 576, NULL }, - { "existential", 549, NULL }, - { "integralbt", 686, NULL }, - { "lessequal", 549, NULL }, - { "phi1", 603, NULL }, - { "lozenge", 494, NULL }, - { "trademarkserif", 890, NULL }, - { "parenright", 333, NULL }, - { "reflexsuperset", 713, NULL }, - { "sigma1", 439, NULL }, - { "nu", 521, NULL }, - { "Gamma", 603, NULL }, - { "angleright", 329, NULL }, - { "ellipsis", 1000, NULL }, - { "Rho", 556, NULL }, - { "parenrightbt", 384, NULL }, - { "radicalex", 500, NULL }, - { "eight", 500, NULL }, - { "angleleft", 329, NULL }, - { "arrowdbldown", 603, NULL }, - { "congruent", 549, NULL }, - { "Theta", 741, NULL }, - { "intersection", 768, NULL }, - { "Pi", 768, NULL }, - { "slash", 278, NULL }, - { "registerserif", 790, NULL }, - { "parenleft", 333, NULL }, - { "one", 500, NULL }, - { "gamma", 411, NULL }, - { "bracketleft", 333, NULL }, - { "rho", 549, NULL }, - { "circlemultiply", 768, NULL }, - { "Chi", 722, NULL }, - { "theta", 521, NULL }, - { "pi", 549, NULL }, - { "integraltp", 686, NULL }, - { "Eta", 722, NULL }, - { "product", 823, NULL }, - { "nine", 500, NULL }, - { "five", 500, NULL }, - { "propersubset", 713, NULL }, - { "bracketrightbt", 384, NULL }, - { "trademarksans", 786, NULL }, - { "dotmath", 250, NULL }, - { "integralex", 686, NULL }, - { "chi", 549, NULL }, - { "parenrighttp", 384, NULL }, - { "eta", 603, NULL }, - { "underscore", 500, NULL }, - { "Euro", 750, NULL }, - { "multiply", 549, NULL }, - { "zero", 500, NULL }, - { "partialdiff", 494, NULL }, - { "angle", 768, NULL }, - { "arrowdblleft", 987, NULL }, - { "braceleft", 480, NULL }, - { "parenrightex", 384, NULL }, - { "Rfraktur", 795, NULL }, - { "Zeta", 611, NULL }, - { "braceex", 494, NULL }, - { "arrowdblup", 603, NULL }, - { "arrowdown", 603, NULL }, - { "Ifraktur", 686, NULL }, - { "degree", 400, NULL }, - { "Iota", 333, NULL }, - { "perpendicular", 658, NULL }, - { "radical", 549, NULL }, - { "asteriskmath", 500, NULL }, - { "percent", 833, NULL }, - { "zeta", 494, NULL }, - { "six", 500, NULL }, - { "two", 500, NULL }, - { "weierstrass", 987, NULL }, - { "summation", 713, NULL }, - { "bracketrighttp", 384, NULL }, - { "carriagereturn", 658, NULL }, - { "suchthat", 439, NULL }, - { "arrowvertex", 603, NULL }, - { "Delta", 612, NULL }, - { "iota", 329, NULL }, - { "arrowhorizex", 1000, NULL }, - { "bracketrightex", 384, NULL }, - { "bracketright", 333, NULL }, - { "ampersand", 778, NULL }, - { "plus", 549, NULL }, - { "proportional", 713, NULL }, - { "delta", 494, NULL }, - { "copyrightserif", 790, NULL }, - { "bracerightmid", 494, NULL }, - { "arrowleft", 987, NULL }, - { "second", 411, NULL }, - { "arrowdblboth", 1042, NULL }, - { "florin", 500, NULL }, - { "Psi", 795, NULL }, - { "bracerightbt", 494, NULL }, - { "bracketleftbt", 384, NULL }, - { "seven", 500, NULL }, - { "braceleftmid", 494, NULL }, - { "notequal", 549, NULL }, - { "psi", 686, NULL }, - { "equivalence", 549, NULL }, - { "universal", 713, NULL }, - { "arrowdblright", 987, NULL }, - { "braceright", 480, NULL }, - { "reflexsubset", 713, NULL }, - { "Xi", 645, NULL }, - { "theta1", 631, NULL }, - { "logicalnot", 713, NULL }, - { "Kappa", 722, NULL }, - { "similar", 549, NULL }, - { "bar", 200, NULL }, - { "fraction", 167, NULL }, - { "less", 549, NULL }, - { "registersans", 790, NULL }, - { "omega1", 713, NULL }, - { "exclam", 333, NULL }, - { "Upsilon1", 620, NULL }, - { "bracerighttp", 494, NULL }, - { "xi", 493, NULL }, - { "period", 250, NULL }, - { "Alpha", 722, NULL }, - { "arrowright", 987, NULL }, - { "greater", 549, NULL }, - { "bracketlefttp", 384, NULL }, - { "kappa", 549, NULL }, - { "gradient", 713, NULL }, - { "integral", 274, NULL }, - { "arrowboth", 1042, NULL }, - { "Beta", 667, NULL } -}; - -static BuiltinFontWidth timesBoldWidthsTab[] = { - { "Ntilde", 722, NULL }, - { "rcaron", 444, NULL }, - { "kcommaaccent", 556, NULL }, - { "Ncommaaccent", 722, NULL }, - { "Zacute", 667, NULL }, - { "comma", 250, NULL }, - { "cedilla", 333, NULL }, - { "plusminus", 570, NULL }, - { "circumflex", 333, NULL }, - { "dotaccent", 333, NULL }, - { "edotaccent", 444, NULL }, - { "asciitilde", 520, NULL }, - { "colon", 333, NULL }, - { "onehalf", 750, NULL }, - { "dollar", 500, NULL }, - { "Lcaron", 667, NULL }, - { "ntilde", 556, NULL }, - { "Aogonek", 722, NULL }, - { "ncommaaccent", 556, NULL }, - { "minus", 570, NULL }, - { "Iogonek", 389, NULL }, - { "zacute", 444, NULL }, - { "yen", 500, NULL }, - { "space", 250, NULL }, - { "Omacron", 778, NULL }, - { "questiondown", 500, NULL }, - { "emdash", 1000, NULL }, - { "Agrave", 722, NULL }, - { "three", 500, NULL }, - { "numbersign", 500, NULL }, - { "lcaron", 394, NULL }, - { "A", 722, NULL }, - { "B", 667, NULL }, - { "C", 722, NULL }, - { "aogonek", 500, NULL }, - { "D", 722, NULL }, - { "E", 667, NULL }, - { "onequarter", 750, NULL }, - { "F", 611, NULL }, - { "G", 778, NULL }, - { "H", 778, NULL }, - { "I", 389, NULL }, - { "J", 500, NULL }, - { "K", 778, NULL }, - { "iogonek", 278, NULL }, - { "backslash", 278, NULL }, - { "L", 667, NULL }, - { "periodcentered", 250, NULL }, - { "M", 944, NULL }, - { "N", 722, NULL }, - { "omacron", 500, NULL }, - { "Tcommaaccent", 667, NULL }, - { "O", 778, NULL }, - { "P", 611, NULL }, - { "Q", 778, NULL }, - { "Uhungarumlaut", 722, NULL }, - { "R", 722, NULL }, - { "Aacute", 722, NULL }, - { "caron", 333, NULL }, - { "S", 556, NULL }, - { "T", 667, NULL }, - { "U", 722, NULL }, - { "agrave", 500, NULL }, - { "V", 722, NULL }, - { "W", 1000, NULL }, - { "X", 722, NULL }, - { "question", 500, NULL }, - { "equal", 570, NULL }, - { "Y", 722, NULL }, - { "Z", 667, NULL }, - { "four", 500, NULL }, - { "a", 500, NULL }, - { "Gcommaaccent", 778, NULL }, - { "b", 556, NULL }, - { "c", 444, NULL }, - { "d", 556, NULL }, - { "e", 444, NULL }, - { "f", 333, NULL }, - { "g", 500, NULL }, - { "bullet", 350, NULL }, - { "h", 556, NULL }, - { "i", 278, NULL }, - { "Oslash", 778, NULL }, - { "dagger", 500, NULL }, - { "j", 333, NULL }, - { "k", 556, NULL }, - { "l", 278, NULL }, - { "m", 833, NULL }, - { "n", 556, NULL }, - { "tcommaaccent", 333, NULL }, - { "o", 500, NULL }, - { "ordfeminine", 300, NULL }, - { "ring", 333, NULL }, - { "p", 556, NULL }, - { "q", 556, NULL }, - { "uhungarumlaut", 556, NULL }, - { "r", 444, NULL }, - { "twosuperior", 300, NULL }, - { "aacute", 500, NULL }, - { "s", 389, NULL }, - { "OE", 1000, NULL }, - { "t", 333, NULL }, - { "divide", 570, NULL }, - { "u", 556, NULL }, - { "Ccaron", 722, NULL }, - { "v", 500, NULL }, - { "w", 722, NULL }, - { "x", 500, NULL }, - { "y", 500, NULL }, - { "z", 444, NULL }, - { "Gbreve", 778, NULL }, - { "commaaccent", 250, NULL }, - { "hungarumlaut", 333, NULL }, - { "Idotaccent", 389, NULL }, - { "Nacute", 722, NULL }, - { "quotedbl", 555, NULL }, - { "gcommaaccent", 500, NULL }, - { "mu", 556, NULL }, - { "greaterequal", 549, NULL }, - { "Scaron", 556, NULL }, - { "Lslash", 667, NULL }, - { "semicolon", 333, NULL }, - { "oslash", 500, NULL }, - { "lessequal", 549, NULL }, - { "lozenge", 494, NULL }, - { "parenright", 333, NULL }, - { "ccaron", 444, NULL }, - { "Ecircumflex", 667, NULL }, - { "gbreve", 500, NULL }, - { "trademark", 1000, NULL }, - { "daggerdbl", 500, NULL }, - { "nacute", 556, NULL }, - { "macron", 333, NULL }, - { "Otilde", 778, NULL }, - { "Emacron", 667, NULL }, - { "ellipsis", 1000, NULL }, - { "scaron", 389, NULL }, - { "AE", 1000, NULL }, - { "Ucircumflex", 722, NULL }, - { "lslash", 278, NULL }, - { "quotedblleft", 500, NULL }, - { "guilsinglright", 333, NULL }, - { "hyphen", 333, NULL }, - { "quotesingle", 278, NULL }, - { "eight", 500, NULL }, - { "exclamdown", 333, NULL }, - { "endash", 500, NULL }, - { "oe", 722, NULL }, - { "Abreve", 722, NULL }, - { "Umacron", 722, NULL }, - { "ecircumflex", 444, NULL }, - { "Adieresis", 722, NULL }, - { "copyright", 747, NULL }, - { "Egrave", 667, NULL }, - { "slash", 278, NULL }, - { "Edieresis", 667, NULL }, - { "otilde", 500, NULL }, - { "Idieresis", 389, NULL }, - { "parenleft", 333, NULL }, - { "one", 500, NULL }, - { "emacron", 444, NULL }, - { "Odieresis", 778, NULL }, - { "ucircumflex", 556, NULL }, - { "bracketleft", 333, NULL }, - { "Ugrave", 722, NULL }, - { "quoteright", 333, NULL }, - { "Udieresis", 722, NULL }, - { "perthousand", 1000, NULL }, - { "Ydieresis", 722, NULL }, - { "umacron", 556, NULL }, - { "abreve", 500, NULL }, - { "Eacute", 667, NULL }, - { "adieresis", 500, NULL }, - { "egrave", 444, NULL }, - { "edieresis", 444, NULL }, - { "idieresis", 278, NULL }, - { "Eth", 722, NULL }, - { "ae", 722, NULL }, - { "asterisk", 500, NULL }, - { "odieresis", 500, NULL }, - { "Uacute", 722, NULL }, - { "ugrave", 556, NULL }, - { "nine", 500, NULL }, - { "five", 500, NULL }, - { "udieresis", 556, NULL }, - { "Zcaron", 667, NULL }, - { "Scommaaccent", 556, NULL }, - { "threequarters", 750, NULL }, - { "guillemotright", 500, NULL }, - { "Ccedilla", 722, NULL }, - { "ydieresis", 500, NULL }, - { "tilde", 333, NULL }, - { "at", 930, NULL }, - { "eacute", 444, NULL }, - { "underscore", 500, NULL }, - { "Euro", 500, NULL }, - { "Dcroat", 722, NULL }, - { "multiply", 570, NULL }, - { "zero", 500, NULL }, - { "eth", 500, NULL }, - { "Scedilla", 556, NULL }, - { "Ograve", 778, NULL }, - { "Racute", 722, NULL }, - { "partialdiff", 494, NULL }, - { "uacute", 556, NULL }, - { "braceleft", 394, NULL }, - { "Thorn", 611, NULL }, - { "zcaron", 444, NULL }, - { "scommaaccent", 389, NULL }, - { "ccedilla", 444, NULL }, - { "Dcaron", 722, NULL }, - { "dcroat", 556, NULL }, - { "Ocircumflex", 778, NULL }, - { "Oacute", 778, NULL }, - { "scedilla", 389, NULL }, - { "ogonek", 333, NULL }, - { "ograve", 500, NULL }, - { "racute", 444, NULL }, - { "Tcaron", 667, NULL }, - { "Eogonek", 667, NULL }, - { "thorn", 556, NULL }, - { "degree", 400, NULL }, - { "registered", 747, NULL }, - { "radical", 549, NULL }, - { "Aring", 722, NULL }, - { "percent", 1000, NULL }, - { "six", 500, NULL }, - { "paragraph", 540, NULL }, - { "dcaron", 672, NULL }, - { "Uogonek", 722, NULL }, - { "two", 500, NULL }, - { "summation", 600, NULL }, - { "Igrave", 389, NULL }, - { "Lacute", 667, NULL }, - { "ocircumflex", 500, NULL }, - { "oacute", 500, NULL }, - { "Uring", 722, NULL }, - { "Lcommaaccent", 667, NULL }, - { "tcaron", 416, NULL }, - { "eogonek", 444, NULL }, - { "Delta", 612, NULL }, - { "Ohungarumlaut", 778, NULL }, - { "asciicircum", 581, NULL }, - { "aring", 500, NULL }, - { "grave", 333, NULL }, - { "uogonek", 556, NULL }, - { "bracketright", 333, NULL }, - { "Iacute", 389, NULL }, - { "ampersand", 833, NULL }, - { "igrave", 278, NULL }, - { "lacute", 278, NULL }, - { "Ncaron", 722, NULL }, - { "plus", 570, NULL }, - { "uring", 556, NULL }, - { "quotesinglbase", 333, NULL }, - { "lcommaaccent", 278, NULL }, - { "Yacute", 722, NULL }, - { "ohungarumlaut", 500, NULL }, - { "threesuperior", 300, NULL }, - { "acute", 333, NULL }, - { "section", 500, NULL }, - { "dieresis", 333, NULL }, - { "iacute", 278, NULL }, - { "quotedblbase", 500, NULL }, - { "ncaron", 556, NULL }, - { "florin", 500, NULL }, - { "yacute", 500, NULL }, - { "Rcommaaccent", 722, NULL }, - { "fi", 556, NULL }, - { "fl", 556, NULL }, - { "Acircumflex", 722, NULL }, - { "Cacute", 722, NULL }, - { "Icircumflex", 389, NULL }, - { "guillemotleft", 500, NULL }, - { "germandbls", 556, NULL }, - { "Amacron", 722, NULL }, - { "seven", 500, NULL }, - { "Sacute", 556, NULL }, - { "ordmasculine", 330, NULL }, - { "dotlessi", 278, NULL }, - { "sterling", 500, NULL }, - { "notequal", 549, NULL }, - { "Imacron", 389, NULL }, - { "rcommaaccent", 444, NULL }, - { "Zdotaccent", 667, NULL }, - { "acircumflex", 500, NULL }, - { "cacute", 444, NULL }, - { "Ecaron", 667, NULL }, - { "icircumflex", 278, NULL }, - { "braceright", 394, NULL }, - { "quotedblright", 500, NULL }, - { "amacron", 500, NULL }, - { "sacute", 389, NULL }, - { "imacron", 278, NULL }, - { "cent", 500, NULL }, - { "currency", 500, NULL }, - { "logicalnot", 570, NULL }, - { "zdotaccent", 444, NULL }, - { "Atilde", 722, NULL }, - { "breve", 333, NULL }, - { "bar", 220, NULL }, - { "fraction", 167, NULL }, - { "less", 570, NULL }, - { "ecaron", 444, NULL }, - { "guilsinglleft", 333, NULL }, - { "exclam", 333, NULL }, - { "period", 250, NULL }, - { "Rcaron", 722, NULL }, - { "Kcommaaccent", 778, NULL }, - { "greater", 570, NULL }, - { "atilde", 500, NULL }, - { "brokenbar", 220, NULL }, - { "quoteleft", 333, NULL }, - { "Edotaccent", 667, NULL }, - { "onesuperior", 300, NULL } -}; - -static BuiltinFontWidth timesBoldItalicWidthsTab[] = { - { "Ntilde", 722, NULL }, - { "rcaron", 389, NULL }, - { "kcommaaccent", 500, NULL }, - { "Ncommaaccent", 722, NULL }, - { "Zacute", 611, NULL }, - { "comma", 250, NULL }, - { "cedilla", 333, NULL }, - { "plusminus", 570, NULL }, - { "circumflex", 333, NULL }, - { "dotaccent", 333, NULL }, - { "edotaccent", 444, NULL }, - { "asciitilde", 570, NULL }, - { "colon", 333, NULL }, - { "onehalf", 750, NULL }, - { "dollar", 500, NULL }, - { "Lcaron", 611, NULL }, - { "ntilde", 556, NULL }, - { "Aogonek", 667, NULL }, - { "ncommaaccent", 556, NULL }, - { "minus", 606, NULL }, - { "Iogonek", 389, NULL }, - { "zacute", 389, NULL }, - { "yen", 500, NULL }, - { "space", 250, NULL }, - { "Omacron", 722, NULL }, - { "questiondown", 500, NULL }, - { "emdash", 1000, NULL }, - { "Agrave", 667, NULL }, - { "three", 500, NULL }, - { "numbersign", 500, NULL }, - { "lcaron", 382, NULL }, - { "A", 667, NULL }, - { "B", 667, NULL }, - { "C", 667, NULL }, - { "aogonek", 500, NULL }, - { "D", 722, NULL }, - { "E", 667, NULL }, - { "onequarter", 750, NULL }, - { "F", 667, NULL }, - { "G", 722, NULL }, - { "H", 778, NULL }, - { "I", 389, NULL }, - { "J", 500, NULL }, - { "K", 667, NULL }, - { "iogonek", 278, NULL }, - { "backslash", 278, NULL }, - { "L", 611, NULL }, - { "periodcentered", 250, NULL }, - { "M", 889, NULL }, - { "N", 722, NULL }, - { "omacron", 500, NULL }, - { "Tcommaaccent", 611, NULL }, - { "O", 722, NULL }, - { "P", 611, NULL }, - { "Q", 722, NULL }, - { "Uhungarumlaut", 722, NULL }, - { "R", 667, NULL }, - { "Aacute", 667, NULL }, - { "caron", 333, NULL }, - { "S", 556, NULL }, - { "T", 611, NULL }, - { "U", 722, NULL }, - { "agrave", 500, NULL }, - { "V", 667, NULL }, - { "W", 889, NULL }, - { "X", 667, NULL }, - { "question", 500, NULL }, - { "equal", 570, NULL }, - { "Y", 611, NULL }, - { "Z", 611, NULL }, - { "four", 500, NULL }, - { "a", 500, NULL }, - { "Gcommaaccent", 722, NULL }, - { "b", 500, NULL }, - { "c", 444, NULL }, - { "d", 500, NULL }, - { "e", 444, NULL }, - { "f", 333, NULL }, - { "g", 500, NULL }, - { "bullet", 350, NULL }, - { "h", 556, NULL }, - { "i", 278, NULL }, - { "Oslash", 722, NULL }, - { "dagger", 500, NULL }, - { "j", 278, NULL }, - { "k", 500, NULL }, - { "l", 278, NULL }, - { "m", 778, NULL }, - { "n", 556, NULL }, - { "tcommaaccent", 278, NULL }, - { "o", 500, NULL }, - { "ordfeminine", 266, NULL }, - { "ring", 333, NULL }, - { "p", 500, NULL }, - { "q", 500, NULL }, - { "uhungarumlaut", 556, NULL }, - { "r", 389, NULL }, - { "twosuperior", 300, NULL }, - { "aacute", 500, NULL }, - { "s", 389, NULL }, - { "OE", 944, NULL }, - { "t", 278, NULL }, - { "divide", 570, NULL }, - { "u", 556, NULL }, - { "Ccaron", 667, NULL }, - { "v", 444, NULL }, - { "w", 667, NULL }, - { "x", 500, NULL }, - { "y", 444, NULL }, - { "z", 389, NULL }, - { "Gbreve", 722, NULL }, - { "commaaccent", 250, NULL }, - { "hungarumlaut", 333, NULL }, - { "Idotaccent", 389, NULL }, - { "Nacute", 722, NULL }, - { "quotedbl", 555, NULL }, - { "gcommaaccent", 500, NULL }, - { "mu", 576, NULL }, - { "greaterequal", 549, NULL }, - { "Scaron", 556, NULL }, - { "Lslash", 611, NULL }, - { "semicolon", 333, NULL }, - { "oslash", 500, NULL }, - { "lessequal", 549, NULL }, - { "lozenge", 494, NULL }, - { "parenright", 333, NULL }, - { "ccaron", 444, NULL }, - { "Ecircumflex", 667, NULL }, - { "gbreve", 500, NULL }, - { "trademark", 1000, NULL }, - { "daggerdbl", 500, NULL }, - { "nacute", 556, NULL }, - { "macron", 333, NULL }, - { "Otilde", 722, NULL }, - { "Emacron", 667, NULL }, - { "ellipsis", 1000, NULL }, - { "scaron", 389, NULL }, - { "AE", 944, NULL }, - { "Ucircumflex", 722, NULL }, - { "lslash", 278, NULL }, - { "quotedblleft", 500, NULL }, - { "guilsinglright", 333, NULL }, - { "hyphen", 333, NULL }, - { "quotesingle", 278, NULL }, - { "eight", 500, NULL }, - { "exclamdown", 389, NULL }, - { "endash", 500, NULL }, - { "oe", 722, NULL }, - { "Abreve", 667, NULL }, - { "Umacron", 722, NULL }, - { "ecircumflex", 444, NULL }, - { "Adieresis", 667, NULL }, - { "copyright", 747, NULL }, - { "Egrave", 667, NULL }, - { "slash", 278, NULL }, - { "Edieresis", 667, NULL }, - { "otilde", 500, NULL }, - { "Idieresis", 389, NULL }, - { "parenleft", 333, NULL }, - { "one", 500, NULL }, - { "emacron", 444, NULL }, - { "Odieresis", 722, NULL }, - { "ucircumflex", 556, NULL }, - { "bracketleft", 333, NULL }, - { "Ugrave", 722, NULL }, - { "quoteright", 333, NULL }, - { "Udieresis", 722, NULL }, - { "perthousand", 1000, NULL }, - { "Ydieresis", 611, NULL }, - { "umacron", 556, NULL }, - { "abreve", 500, NULL }, - { "Eacute", 667, NULL }, - { "adieresis", 500, NULL }, - { "egrave", 444, NULL }, - { "edieresis", 444, NULL }, - { "idieresis", 278, NULL }, - { "Eth", 722, NULL }, - { "ae", 722, NULL }, - { "asterisk", 500, NULL }, - { "odieresis", 500, NULL }, - { "Uacute", 722, NULL }, - { "ugrave", 556, NULL }, - { "nine", 500, NULL }, - { "five", 500, NULL }, - { "udieresis", 556, NULL }, - { "Zcaron", 611, NULL }, - { "Scommaaccent", 556, NULL }, - { "threequarters", 750, NULL }, - { "guillemotright", 500, NULL }, - { "Ccedilla", 667, NULL }, - { "ydieresis", 444, NULL }, - { "tilde", 333, NULL }, - { "at", 832, NULL }, - { "eacute", 444, NULL }, - { "underscore", 500, NULL }, - { "Euro", 500, NULL }, - { "Dcroat", 722, NULL }, - { "multiply", 570, NULL }, - { "zero", 500, NULL }, - { "eth", 500, NULL }, - { "Scedilla", 556, NULL }, - { "Ograve", 722, NULL }, - { "Racute", 667, NULL }, - { "partialdiff", 494, NULL }, - { "uacute", 556, NULL }, - { "braceleft", 348, NULL }, - { "Thorn", 611, NULL }, - { "zcaron", 389, NULL }, - { "scommaaccent", 389, NULL }, - { "ccedilla", 444, NULL }, - { "Dcaron", 722, NULL }, - { "dcroat", 500, NULL }, - { "Ocircumflex", 722, NULL }, - { "Oacute", 722, NULL }, - { "scedilla", 389, NULL }, - { "ogonek", 333, NULL }, - { "ograve", 500, NULL }, - { "racute", 389, NULL }, - { "Tcaron", 611, NULL }, - { "Eogonek", 667, NULL }, - { "thorn", 500, NULL }, - { "degree", 400, NULL }, - { "registered", 747, NULL }, - { "radical", 549, NULL }, - { "Aring", 667, NULL }, - { "percent", 833, NULL }, - { "six", 500, NULL }, - { "paragraph", 500, NULL }, - { "dcaron", 608, NULL }, - { "Uogonek", 722, NULL }, - { "two", 500, NULL }, - { "summation", 600, NULL }, - { "Igrave", 389, NULL }, - { "Lacute", 611, NULL }, - { "ocircumflex", 500, NULL }, - { "oacute", 500, NULL }, - { "Uring", 722, NULL }, - { "Lcommaaccent", 611, NULL }, - { "tcaron", 366, NULL }, - { "eogonek", 444, NULL }, - { "Delta", 612, NULL }, - { "Ohungarumlaut", 722, NULL }, - { "asciicircum", 570, NULL }, - { "aring", 500, NULL }, - { "grave", 333, NULL }, - { "uogonek", 556, NULL }, - { "bracketright", 333, NULL }, - { "Iacute", 389, NULL }, - { "ampersand", 778, NULL }, - { "igrave", 278, NULL }, - { "lacute", 278, NULL }, - { "Ncaron", 722, NULL }, - { "plus", 570, NULL }, - { "uring", 556, NULL }, - { "quotesinglbase", 333, NULL }, - { "lcommaaccent", 278, NULL }, - { "Yacute", 611, NULL }, - { "ohungarumlaut", 500, NULL }, - { "threesuperior", 300, NULL }, - { "acute", 333, NULL }, - { "section", 500, NULL }, - { "dieresis", 333, NULL }, - { "iacute", 278, NULL }, - { "quotedblbase", 500, NULL }, - { "ncaron", 556, NULL }, - { "florin", 500, NULL }, - { "yacute", 444, NULL }, - { "Rcommaaccent", 667, NULL }, - { "fi", 556, NULL }, - { "fl", 556, NULL }, - { "Acircumflex", 667, NULL }, - { "Cacute", 667, NULL }, - { "Icircumflex", 389, NULL }, - { "guillemotleft", 500, NULL }, - { "germandbls", 500, NULL }, - { "Amacron", 667, NULL }, - { "seven", 500, NULL }, - { "Sacute", 556, NULL }, - { "ordmasculine", 300, NULL }, - { "dotlessi", 278, NULL }, - { "sterling", 500, NULL }, - { "notequal", 549, NULL }, - { "Imacron", 389, NULL }, - { "rcommaaccent", 389, NULL }, - { "Zdotaccent", 611, NULL }, - { "acircumflex", 500, NULL }, - { "cacute", 444, NULL }, - { "Ecaron", 667, NULL }, - { "icircumflex", 278, NULL }, - { "braceright", 348, NULL }, - { "quotedblright", 500, NULL }, - { "amacron", 500, NULL }, - { "sacute", 389, NULL }, - { "imacron", 278, NULL }, - { "cent", 500, NULL }, - { "currency", 500, NULL }, - { "logicalnot", 606, NULL }, - { "zdotaccent", 389, NULL }, - { "Atilde", 667, NULL }, - { "breve", 333, NULL }, - { "bar", 220, NULL }, - { "fraction", 167, NULL }, - { "less", 570, NULL }, - { "ecaron", 444, NULL }, - { "guilsinglleft", 333, NULL }, - { "exclam", 389, NULL }, - { "period", 250, NULL }, - { "Rcaron", 667, NULL }, - { "Kcommaaccent", 667, NULL }, - { "greater", 570, NULL }, - { "atilde", 500, NULL }, - { "brokenbar", 220, NULL }, - { "quoteleft", 333, NULL }, - { "Edotaccent", 667, NULL }, - { "onesuperior", 300, NULL } -}; - -static BuiltinFontWidth timesItalicWidthsTab[] = { - { "Ntilde", 667, NULL }, - { "rcaron", 389, NULL }, - { "kcommaaccent", 444, NULL }, - { "Ncommaaccent", 667, NULL }, - { "Zacute", 556, NULL }, - { "comma", 250, NULL }, - { "cedilla", 333, NULL }, - { "plusminus", 675, NULL }, - { "circumflex", 333, NULL }, - { "dotaccent", 333, NULL }, - { "edotaccent", 444, NULL }, - { "asciitilde", 541, NULL }, - { "colon", 333, NULL }, - { "onehalf", 750, NULL }, - { "dollar", 500, NULL }, - { "Lcaron", 611, NULL }, - { "ntilde", 500, NULL }, - { "Aogonek", 611, NULL }, - { "ncommaaccent", 500, NULL }, - { "minus", 675, NULL }, - { "Iogonek", 333, NULL }, - { "zacute", 389, NULL }, - { "yen", 500, NULL }, - { "space", 250, NULL }, - { "Omacron", 722, NULL }, - { "questiondown", 500, NULL }, - { "emdash", 889, NULL }, - { "Agrave", 611, NULL }, - { "three", 500, NULL }, - { "numbersign", 500, NULL }, - { "lcaron", 300, NULL }, - { "A", 611, NULL }, - { "B", 611, NULL }, - { "C", 667, NULL }, - { "aogonek", 500, NULL }, - { "D", 722, NULL }, - { "E", 611, NULL }, - { "onequarter", 750, NULL }, - { "F", 611, NULL }, - { "G", 722, NULL }, - { "H", 722, NULL }, - { "I", 333, NULL }, - { "J", 444, NULL }, - { "K", 667, NULL }, - { "iogonek", 278, NULL }, - { "backslash", 278, NULL }, - { "L", 556, NULL }, - { "periodcentered", 250, NULL }, - { "M", 833, NULL }, - { "N", 667, NULL }, - { "omacron", 500, NULL }, - { "Tcommaaccent", 556, NULL }, - { "O", 722, NULL }, - { "P", 611, NULL }, - { "Q", 722, NULL }, - { "Uhungarumlaut", 722, NULL }, - { "R", 611, NULL }, - { "Aacute", 611, NULL }, - { "caron", 333, NULL }, - { "S", 500, NULL }, - { "T", 556, NULL }, - { "U", 722, NULL }, - { "agrave", 500, NULL }, - { "V", 611, NULL }, - { "W", 833, NULL }, - { "X", 611, NULL }, - { "question", 500, NULL }, - { "equal", 675, NULL }, - { "Y", 556, NULL }, - { "Z", 556, NULL }, - { "four", 500, NULL }, - { "a", 500, NULL }, - { "Gcommaaccent", 722, NULL }, - { "b", 500, NULL }, - { "c", 444, NULL }, - { "d", 500, NULL }, - { "e", 444, NULL }, - { "f", 278, NULL }, - { "g", 500, NULL }, - { "bullet", 350, NULL }, - { "h", 500, NULL }, - { "i", 278, NULL }, - { "Oslash", 722, NULL }, - { "dagger", 500, NULL }, - { "j", 278, NULL }, - { "k", 444, NULL }, - { "l", 278, NULL }, - { "m", 722, NULL }, - { "n", 500, NULL }, - { "tcommaaccent", 278, NULL }, - { "o", 500, NULL }, - { "ordfeminine", 276, NULL }, - { "ring", 333, NULL }, - { "p", 500, NULL }, - { "q", 500, NULL }, - { "uhungarumlaut", 500, NULL }, - { "r", 389, NULL }, - { "twosuperior", 300, NULL }, - { "aacute", 500, NULL }, - { "s", 389, NULL }, - { "OE", 944, NULL }, - { "t", 278, NULL }, - { "divide", 675, NULL }, - { "u", 500, NULL }, - { "Ccaron", 667, NULL }, - { "v", 444, NULL }, - { "w", 667, NULL }, - { "x", 444, NULL }, - { "y", 444, NULL }, - { "z", 389, NULL }, - { "Gbreve", 722, NULL }, - { "commaaccent", 250, NULL }, - { "hungarumlaut", 333, NULL }, - { "Idotaccent", 333, NULL }, - { "Nacute", 667, NULL }, - { "quotedbl", 420, NULL }, - { "gcommaaccent", 500, NULL }, - { "mu", 500, NULL }, - { "greaterequal", 549, NULL }, - { "Scaron", 500, NULL }, - { "Lslash", 556, NULL }, - { "semicolon", 333, NULL }, - { "oslash", 500, NULL }, - { "lessequal", 549, NULL }, - { "lozenge", 471, NULL }, - { "parenright", 333, NULL }, - { "ccaron", 444, NULL }, - { "Ecircumflex", 611, NULL }, - { "gbreve", 500, NULL }, - { "trademark", 980, NULL }, - { "daggerdbl", 500, NULL }, - { "nacute", 500, NULL }, - { "macron", 333, NULL }, - { "Otilde", 722, NULL }, - { "Emacron", 611, NULL }, - { "ellipsis", 889, NULL }, - { "scaron", 389, NULL }, - { "AE", 889, NULL }, - { "Ucircumflex", 722, NULL }, - { "lslash", 278, NULL }, - { "quotedblleft", 556, NULL }, - { "guilsinglright", 333, NULL }, - { "hyphen", 333, NULL }, - { "quotesingle", 214, NULL }, - { "eight", 500, NULL }, - { "exclamdown", 389, NULL }, - { "endash", 500, NULL }, - { "oe", 667, NULL }, - { "Abreve", 611, NULL }, - { "Umacron", 722, NULL }, - { "ecircumflex", 444, NULL }, - { "Adieresis", 611, NULL }, - { "copyright", 760, NULL }, - { "Egrave", 611, NULL }, - { "slash", 278, NULL }, - { "Edieresis", 611, NULL }, - { "otilde", 500, NULL }, - { "Idieresis", 333, NULL }, - { "parenleft", 333, NULL }, - { "one", 500, NULL }, - { "emacron", 444, NULL }, - { "Odieresis", 722, NULL }, - { "ucircumflex", 500, NULL }, - { "bracketleft", 389, NULL }, - { "Ugrave", 722, NULL }, - { "quoteright", 333, NULL }, - { "Udieresis", 722, NULL }, - { "perthousand", 1000, NULL }, - { "Ydieresis", 556, NULL }, - { "umacron", 500, NULL }, - { "abreve", 500, NULL }, - { "Eacute", 611, NULL }, - { "adieresis", 500, NULL }, - { "egrave", 444, NULL }, - { "edieresis", 444, NULL }, - { "idieresis", 278, NULL }, - { "Eth", 722, NULL }, - { "ae", 667, NULL }, - { "asterisk", 500, NULL }, - { "odieresis", 500, NULL }, - { "Uacute", 722, NULL }, - { "ugrave", 500, NULL }, - { "nine", 500, NULL }, - { "five", 500, NULL }, - { "udieresis", 500, NULL }, - { "Zcaron", 556, NULL }, - { "Scommaaccent", 500, NULL }, - { "threequarters", 750, NULL }, - { "guillemotright", 500, NULL }, - { "Ccedilla", 667, NULL }, - { "ydieresis", 444, NULL }, - { "tilde", 333, NULL }, - { "at", 920, NULL }, - { "eacute", 444, NULL }, - { "underscore", 500, NULL }, - { "Euro", 500, NULL }, - { "Dcroat", 722, NULL }, - { "multiply", 675, NULL }, - { "zero", 500, NULL }, - { "eth", 500, NULL }, - { "Scedilla", 500, NULL }, - { "Ograve", 722, NULL }, - { "Racute", 611, NULL }, - { "partialdiff", 476, NULL }, - { "uacute", 500, NULL }, - { "braceleft", 400, NULL }, - { "Thorn", 611, NULL }, - { "zcaron", 389, NULL }, - { "scommaaccent", 389, NULL }, - { "ccedilla", 444, NULL }, - { "Dcaron", 722, NULL }, - { "dcroat", 500, NULL }, - { "Ocircumflex", 722, NULL }, - { "Oacute", 722, NULL }, - { "scedilla", 389, NULL }, - { "ogonek", 333, NULL }, - { "ograve", 500, NULL }, - { "racute", 389, NULL }, - { "Tcaron", 556, NULL }, - { "Eogonek", 611, NULL }, - { "thorn", 500, NULL }, - { "degree", 400, NULL }, - { "registered", 760, NULL }, - { "radical", 453, NULL }, - { "Aring", 611, NULL }, - { "percent", 833, NULL }, - { "six", 500, NULL }, - { "paragraph", 523, NULL }, - { "dcaron", 544, NULL }, - { "Uogonek", 722, NULL }, - { "two", 500, NULL }, - { "summation", 600, NULL }, - { "Igrave", 333, NULL }, - { "Lacute", 556, NULL }, - { "ocircumflex", 500, NULL }, - { "oacute", 500, NULL }, - { "Uring", 722, NULL }, - { "Lcommaaccent", 556, NULL }, - { "tcaron", 300, NULL }, - { "eogonek", 444, NULL }, - { "Delta", 612, NULL }, - { "Ohungarumlaut", 722, NULL }, - { "asciicircum", 422, NULL }, - { "aring", 500, NULL }, - { "grave", 333, NULL }, - { "uogonek", 500, NULL }, - { "bracketright", 389, NULL }, - { "Iacute", 333, NULL }, - { "ampersand", 778, NULL }, - { "igrave", 278, NULL }, - { "lacute", 278, NULL }, - { "Ncaron", 667, NULL }, - { "plus", 675, NULL }, - { "uring", 500, NULL }, - { "quotesinglbase", 333, NULL }, - { "lcommaaccent", 278, NULL }, - { "Yacute", 556, NULL }, - { "ohungarumlaut", 500, NULL }, - { "threesuperior", 300, NULL }, - { "acute", 333, NULL }, - { "section", 500, NULL }, - { "dieresis", 333, NULL }, - { "iacute", 278, NULL }, - { "quotedblbase", 556, NULL }, - { "ncaron", 500, NULL }, - { "florin", 500, NULL }, - { "yacute", 444, NULL }, - { "Rcommaaccent", 611, NULL }, - { "fi", 500, NULL }, - { "fl", 500, NULL }, - { "Acircumflex", 611, NULL }, - { "Cacute", 667, NULL }, - { "Icircumflex", 333, NULL }, - { "guillemotleft", 500, NULL }, - { "germandbls", 500, NULL }, - { "Amacron", 611, NULL }, - { "seven", 500, NULL }, - { "Sacute", 500, NULL }, - { "ordmasculine", 310, NULL }, - { "dotlessi", 278, NULL }, - { "sterling", 500, NULL }, - { "notequal", 549, NULL }, - { "Imacron", 333, NULL }, - { "rcommaaccent", 389, NULL }, - { "Zdotaccent", 556, NULL }, - { "acircumflex", 500, NULL }, - { "cacute", 444, NULL }, - { "Ecaron", 611, NULL }, - { "icircumflex", 278, NULL }, - { "braceright", 400, NULL }, - { "quotedblright", 556, NULL }, - { "amacron", 500, NULL }, - { "sacute", 389, NULL }, - { "imacron", 278, NULL }, - { "cent", 500, NULL }, - { "currency", 500, NULL }, - { "logicalnot", 675, NULL }, - { "zdotaccent", 389, NULL }, - { "Atilde", 611, NULL }, - { "breve", 333, NULL }, - { "bar", 275, NULL }, - { "fraction", 167, NULL }, - { "less", 675, NULL }, - { "ecaron", 444, NULL }, - { "guilsinglleft", 333, NULL }, - { "exclam", 333, NULL }, - { "period", 250, NULL }, - { "Rcaron", 611, NULL }, - { "Kcommaaccent", 667, NULL }, - { "greater", 675, NULL }, - { "atilde", 500, NULL }, - { "brokenbar", 275, NULL }, - { "quoteleft", 333, NULL }, - { "Edotaccent", 611, NULL }, - { "onesuperior", 300, NULL } -}; - -static BuiltinFontWidth timesRomanWidthsTab[] = { - { "Ntilde", 722, NULL }, - { "rcaron", 333, NULL }, - { "kcommaaccent", 500, NULL }, - { "Ncommaaccent", 722, NULL }, - { "Zacute", 611, NULL }, - { "comma", 250, NULL }, - { "cedilla", 333, NULL }, - { "plusminus", 564, NULL }, - { "circumflex", 333, NULL }, - { "dotaccent", 333, NULL }, - { "edotaccent", 444, NULL }, - { "asciitilde", 541, NULL }, - { "colon", 278, NULL }, - { "onehalf", 750, NULL }, - { "dollar", 500, NULL }, - { "Lcaron", 611, NULL }, - { "ntilde", 500, NULL }, - { "Aogonek", 722, NULL }, - { "ncommaaccent", 500, NULL }, - { "minus", 564, NULL }, - { "Iogonek", 333, NULL }, - { "zacute", 444, NULL }, - { "yen", 500, NULL }, - { "space", 250, NULL }, - { "Omacron", 722, NULL }, - { "questiondown", 444, NULL }, - { "emdash", 1000, NULL }, - { "Agrave", 722, NULL }, - { "three", 500, NULL }, - { "numbersign", 500, NULL }, - { "lcaron", 344, NULL }, - { "A", 722, NULL }, - { "B", 667, NULL }, - { "C", 667, NULL }, - { "aogonek", 444, NULL }, - { "D", 722, NULL }, - { "E", 611, NULL }, - { "onequarter", 750, NULL }, - { "F", 556, NULL }, - { "G", 722, NULL }, - { "H", 722, NULL }, - { "I", 333, NULL }, - { "J", 389, NULL }, - { "K", 722, NULL }, - { "iogonek", 278, NULL }, - { "backslash", 278, NULL }, - { "L", 611, NULL }, - { "periodcentered", 250, NULL }, - { "M", 889, NULL }, - { "N", 722, NULL }, - { "omacron", 500, NULL }, - { "Tcommaaccent", 611, NULL }, - { "O", 722, NULL }, - { "P", 556, NULL }, - { "Q", 722, NULL }, - { "Uhungarumlaut", 722, NULL }, - { "R", 667, NULL }, - { "Aacute", 722, NULL }, - { "caron", 333, NULL }, - { "S", 556, NULL }, - { "T", 611, NULL }, - { "U", 722, NULL }, - { "agrave", 444, NULL }, - { "V", 722, NULL }, - { "W", 944, NULL }, - { "X", 722, NULL }, - { "question", 444, NULL }, - { "equal", 564, NULL }, - { "Y", 722, NULL }, - { "Z", 611, NULL }, - { "four", 500, NULL }, - { "a", 444, NULL }, - { "Gcommaaccent", 722, NULL }, - { "b", 500, NULL }, - { "c", 444, NULL }, - { "d", 500, NULL }, - { "e", 444, NULL }, - { "f", 333, NULL }, - { "g", 500, NULL }, - { "bullet", 350, NULL }, - { "h", 500, NULL }, - { "i", 278, NULL }, - { "Oslash", 722, NULL }, - { "dagger", 500, NULL }, - { "j", 278, NULL }, - { "k", 500, NULL }, - { "l", 278, NULL }, - { "m", 778, NULL }, - { "n", 500, NULL }, - { "tcommaaccent", 278, NULL }, - { "o", 500, NULL }, - { "ordfeminine", 276, NULL }, - { "ring", 333, NULL }, - { "p", 500, NULL }, - { "q", 500, NULL }, - { "uhungarumlaut", 500, NULL }, - { "r", 333, NULL }, - { "twosuperior", 300, NULL }, - { "aacute", 444, NULL }, - { "s", 389, NULL }, - { "OE", 889, NULL }, - { "t", 278, NULL }, - { "divide", 564, NULL }, - { "u", 500, NULL }, - { "Ccaron", 667, NULL }, - { "v", 500, NULL }, - { "w", 722, NULL }, - { "x", 500, NULL }, - { "y", 500, NULL }, - { "z", 444, NULL }, - { "Gbreve", 722, NULL }, - { "commaaccent", 250, NULL }, - { "hungarumlaut", 333, NULL }, - { "Idotaccent", 333, NULL }, - { "Nacute", 722, NULL }, - { "quotedbl", 408, NULL }, - { "gcommaaccent", 500, NULL }, - { "mu", 500, NULL }, - { "greaterequal", 549, NULL }, - { "Scaron", 556, NULL }, - { "Lslash", 611, NULL }, - { "semicolon", 278, NULL }, - { "oslash", 500, NULL }, - { "lessequal", 549, NULL }, - { "lozenge", 471, NULL }, - { "parenright", 333, NULL }, - { "ccaron", 444, NULL }, - { "Ecircumflex", 611, NULL }, - { "gbreve", 500, NULL }, - { "trademark", 980, NULL }, - { "daggerdbl", 500, NULL }, - { "nacute", 500, NULL }, - { "macron", 333, NULL }, - { "Otilde", 722, NULL }, - { "Emacron", 611, NULL }, - { "ellipsis", 1000, NULL }, - { "scaron", 389, NULL }, - { "AE", 889, NULL }, - { "Ucircumflex", 722, NULL }, - { "lslash", 278, NULL }, - { "quotedblleft", 444, NULL }, - { "guilsinglright", 333, NULL }, - { "hyphen", 333, NULL }, - { "quotesingle", 180, NULL }, - { "eight", 500, NULL }, - { "exclamdown", 333, NULL }, - { "endash", 500, NULL }, - { "oe", 722, NULL }, - { "Abreve", 722, NULL }, - { "Umacron", 722, NULL }, - { "ecircumflex", 444, NULL }, - { "Adieresis", 722, NULL }, - { "copyright", 760, NULL }, - { "Egrave", 611, NULL }, - { "slash", 278, NULL }, - { "Edieresis", 611, NULL }, - { "otilde", 500, NULL }, - { "Idieresis", 333, NULL }, - { "parenleft", 333, NULL }, - { "one", 500, NULL }, - { "emacron", 444, NULL }, - { "Odieresis", 722, NULL }, - { "ucircumflex", 500, NULL }, - { "bracketleft", 333, NULL }, - { "Ugrave", 722, NULL }, - { "quoteright", 333, NULL }, - { "Udieresis", 722, NULL }, - { "perthousand", 1000, NULL }, - { "Ydieresis", 722, NULL }, - { "umacron", 500, NULL }, - { "abreve", 444, NULL }, - { "Eacute", 611, NULL }, - { "adieresis", 444, NULL }, - { "egrave", 444, NULL }, - { "edieresis", 444, NULL }, - { "idieresis", 278, NULL }, - { "Eth", 722, NULL }, - { "ae", 667, NULL }, - { "asterisk", 500, NULL }, - { "odieresis", 500, NULL }, - { "Uacute", 722, NULL }, - { "ugrave", 500, NULL }, - { "nine", 500, NULL }, - { "five", 500, NULL }, - { "udieresis", 500, NULL }, - { "Zcaron", 611, NULL }, - { "Scommaaccent", 556, NULL }, - { "threequarters", 750, NULL }, - { "guillemotright", 500, NULL }, - { "Ccedilla", 667, NULL }, - { "ydieresis", 500, NULL }, - { "tilde", 333, NULL }, - { "at", 921, NULL }, - { "eacute", 444, NULL }, - { "underscore", 500, NULL }, - { "Euro", 500, NULL }, - { "Dcroat", 722, NULL }, - { "multiply", 564, NULL }, - { "zero", 500, NULL }, - { "eth", 500, NULL }, - { "Scedilla", 556, NULL }, - { "Ograve", 722, NULL }, - { "Racute", 667, NULL }, - { "partialdiff", 476, NULL }, - { "uacute", 500, NULL }, - { "braceleft", 480, NULL }, - { "Thorn", 556, NULL }, - { "zcaron", 444, NULL }, - { "scommaaccent", 389, NULL }, - { "ccedilla", 444, NULL }, - { "Dcaron", 722, NULL }, - { "dcroat", 500, NULL }, - { "Ocircumflex", 722, NULL }, - { "Oacute", 722, NULL }, - { "scedilla", 389, NULL }, - { "ogonek", 333, NULL }, - { "ograve", 500, NULL }, - { "racute", 333, NULL }, - { "Tcaron", 611, NULL }, - { "Eogonek", 611, NULL }, - { "thorn", 500, NULL }, - { "degree", 400, NULL }, - { "registered", 760, NULL }, - { "radical", 453, NULL }, - { "Aring", 722, NULL }, - { "percent", 833, NULL }, - { "six", 500, NULL }, - { "paragraph", 453, NULL }, - { "dcaron", 588, NULL }, - { "Uogonek", 722, NULL }, - { "two", 500, NULL }, - { "summation", 600, NULL }, - { "Igrave", 333, NULL }, - { "Lacute", 611, NULL }, - { "ocircumflex", 500, NULL }, - { "oacute", 500, NULL }, - { "Uring", 722, NULL }, - { "Lcommaaccent", 611, NULL }, - { "tcaron", 326, NULL }, - { "eogonek", 444, NULL }, - { "Delta", 612, NULL }, - { "Ohungarumlaut", 722, NULL }, - { "asciicircum", 469, NULL }, - { "aring", 444, NULL }, - { "grave", 333, NULL }, - { "uogonek", 500, NULL }, - { "bracketright", 333, NULL }, - { "Iacute", 333, NULL }, - { "ampersand", 778, NULL }, - { "igrave", 278, NULL }, - { "lacute", 278, NULL }, - { "Ncaron", 722, NULL }, - { "plus", 564, NULL }, - { "uring", 500, NULL }, - { "quotesinglbase", 333, NULL }, - { "lcommaaccent", 278, NULL }, - { "Yacute", 722, NULL }, - { "ohungarumlaut", 500, NULL }, - { "threesuperior", 300, NULL }, - { "acute", 333, NULL }, - { "section", 500, NULL }, - { "dieresis", 333, NULL }, - { "iacute", 278, NULL }, - { "quotedblbase", 444, NULL }, - { "ncaron", 500, NULL }, - { "florin", 500, NULL }, - { "yacute", 500, NULL }, - { "Rcommaaccent", 667, NULL }, - { "fi", 556, NULL }, - { "fl", 556, NULL }, - { "Acircumflex", 722, NULL }, - { "Cacute", 667, NULL }, - { "Icircumflex", 333, NULL }, - { "guillemotleft", 500, NULL }, - { "germandbls", 500, NULL }, - { "Amacron", 722, NULL }, - { "seven", 500, NULL }, - { "Sacute", 556, NULL }, - { "ordmasculine", 310, NULL }, - { "dotlessi", 278, NULL }, - { "sterling", 500, NULL }, - { "notequal", 549, NULL }, - { "Imacron", 333, NULL }, - { "rcommaaccent", 333, NULL }, - { "Zdotaccent", 611, NULL }, - { "acircumflex", 444, NULL }, - { "cacute", 444, NULL }, - { "Ecaron", 611, NULL }, - { "icircumflex", 278, NULL }, - { "braceright", 480, NULL }, - { "quotedblright", 444, NULL }, - { "amacron", 444, NULL }, - { "sacute", 389, NULL }, - { "imacron", 278, NULL }, - { "cent", 500, NULL }, - { "currency", 500, NULL }, - { "logicalnot", 564, NULL }, - { "zdotaccent", 444, NULL }, - { "Atilde", 722, NULL }, - { "breve", 333, NULL }, - { "bar", 200, NULL }, - { "fraction", 167, NULL }, - { "less", 564, NULL }, - { "ecaron", 444, NULL }, - { "guilsinglleft", 333, NULL }, - { "exclam", 333, NULL }, - { "period", 250, NULL }, - { "Rcaron", 667, NULL }, - { "Kcommaaccent", 722, NULL }, - { "greater", 564, NULL }, - { "atilde", 444, NULL }, - { "brokenbar", 200, NULL }, - { "quoteleft", 333, NULL }, - { "Edotaccent", 611, NULL }, - { "onesuperior", 300, NULL } -}; - -static BuiltinFontWidth zapfDingbatsWidthsTab[] = { - { "a81", 438, NULL }, - { "a82", 138, NULL }, - { "a83", 277, NULL }, - { "a84", 415, NULL }, - { "a85", 509, NULL }, - { "a86", 410, NULL }, - { "a87", 234, NULL }, - { "a88", 234, NULL }, - { "a89", 390, NULL }, - { "a140", 788, NULL }, - { "a141", 788, NULL }, - { "a142", 788, NULL }, - { "a143", 788, NULL }, - { "a144", 788, NULL }, - { "a145", 788, NULL }, - { "a146", 788, NULL }, - { "a147", 788, NULL }, - { "a148", 788, NULL }, - { "a149", 788, NULL }, - { "a90", 390, NULL }, - { "a91", 276, NULL }, - { "a92", 276, NULL }, - { "space", 278, NULL }, - { "a93", 317, NULL }, - { "a94", 317, NULL }, - { "a95", 334, NULL }, - { "a96", 334, NULL }, - { "a97", 392, NULL }, - { "a98", 392, NULL }, - { "a99", 668, NULL }, - { "a150", 788, NULL }, - { "a151", 788, NULL }, - { "a152", 788, NULL }, - { "a153", 788, NULL }, - { "a154", 788, NULL }, - { "a155", 788, NULL }, - { "a156", 788, NULL }, - { "a157", 788, NULL }, - { "a158", 788, NULL }, - { "a159", 788, NULL }, - { "a160", 894, NULL }, - { "a161", 838, NULL }, - { "a162", 924, NULL }, - { "a163", 1016, NULL }, - { "a164", 458, NULL }, - { "a165", 924, NULL }, - { "a166", 918, NULL }, - { "a167", 927, NULL }, - { "a168", 928, NULL }, - { "a169", 928, NULL }, - { "a170", 834, NULL }, - { "a171", 873, NULL }, - { "a172", 828, NULL }, - { "a173", 924, NULL }, - { "a174", 917, NULL }, - { "a175", 930, NULL }, - { "a176", 931, NULL }, - { "a177", 463, NULL }, - { "a178", 883, NULL }, - { "a179", 836, NULL }, - { "a180", 867, NULL }, - { "a181", 696, NULL }, - { "a182", 874, NULL }, - { "a183", 760, NULL }, - { "a184", 946, NULL }, - { "a185", 865, NULL }, - { "a186", 967, NULL }, - { "a187", 831, NULL }, - { "a188", 873, NULL }, - { "a189", 927, NULL }, - { "a1", 974, NULL }, - { "a2", 961, NULL }, - { "a3", 980, NULL }, - { "a4", 719, NULL }, - { "a5", 789, NULL }, - { "a6", 494, NULL }, - { "a7", 552, NULL }, - { "a8", 537, NULL }, - { "a9", 577, NULL }, - { "a190", 970, NULL }, - { "a191", 918, NULL }, - { "a192", 748, NULL }, - { "a193", 836, NULL }, - { "a194", 771, NULL }, - { "a195", 888, NULL }, - { "a196", 748, NULL }, - { "a197", 771, NULL }, - { "a198", 888, NULL }, - { "a199", 867, NULL }, - { "a10", 692, NULL }, - { "a11", 960, NULL }, - { "a12", 939, NULL }, - { "a13", 549, NULL }, - { "a14", 855, NULL }, - { "a15", 911, NULL }, - { "a16", 933, NULL }, - { "a17", 945, NULL }, - { "a18", 974, NULL }, - { "a19", 755, NULL }, - { "a20", 846, NULL }, - { "a21", 762, NULL }, - { "a22", 761, NULL }, - { "a23", 571, NULL }, - { "a24", 677, NULL }, - { "a25", 763, NULL }, - { "a26", 760, NULL }, - { "a27", 759, NULL }, - { "a28", 754, NULL }, - { "a29", 786, NULL }, - { "a30", 788, NULL }, - { "a31", 788, NULL }, - { "a32", 790, NULL }, - { "a33", 793, NULL }, - { "a34", 794, NULL }, - { "a35", 816, NULL }, - { "a36", 823, NULL }, - { "a37", 789, NULL }, - { "a38", 841, NULL }, - { "a39", 823, NULL }, - { "a40", 833, NULL }, - { "a41", 816, NULL }, - { "a42", 831, NULL }, - { "a43", 923, NULL }, - { "a44", 744, NULL }, - { "a45", 723, NULL }, - { "a46", 749, NULL }, - { "a47", 790, NULL }, - { "a48", 792, NULL }, - { "a49", 695, NULL }, - { "a100", 668, NULL }, - { "a101", 732, NULL }, - { "a102", 544, NULL }, - { "a103", 544, NULL }, - { "a104", 910, NULL }, - { "a105", 911, NULL }, - { "a106", 667, NULL }, - { "a107", 760, NULL }, - { "a108", 760, NULL }, - { "a109", 626, NULL }, - { "a50", 776, NULL }, - { "a51", 768, NULL }, - { "a52", 792, NULL }, - { "a53", 759, NULL }, - { "a54", 707, NULL }, - { "a55", 708, NULL }, - { "a56", 682, NULL }, - { "a57", 701, NULL }, - { "a58", 826, NULL }, - { "a59", 815, NULL }, - { "a110", 694, NULL }, - { "a111", 595, NULL }, - { "a112", 776, NULL }, - { "a117", 690, NULL }, - { "a118", 791, NULL }, - { "a119", 790, NULL }, - { "a60", 789, NULL }, - { "a61", 789, NULL }, - { "a62", 707, NULL }, - { "a63", 687, NULL }, - { "a64", 696, NULL }, - { "a65", 689, NULL }, - { "a66", 786, NULL }, - { "a67", 787, NULL }, - { "a68", 713, NULL }, - { "a69", 791, NULL }, - { "a200", 696, NULL }, - { "a201", 874, NULL }, - { "a120", 788, NULL }, - { "a121", 788, NULL }, - { "a202", 974, NULL }, - { "a122", 788, NULL }, - { "a203", 762, NULL }, - { "a123", 788, NULL }, - { "a204", 759, NULL }, - { "a124", 788, NULL }, - { "a205", 509, NULL }, - { "a125", 788, NULL }, - { "a206", 410, NULL }, - { "a126", 788, NULL }, - { "a127", 788, NULL }, - { "a128", 788, NULL }, - { "a129", 788, NULL }, - { "a70", 785, NULL }, - { "a71", 791, NULL }, - { "a72", 873, NULL }, - { "a73", 761, NULL }, - { "a74", 762, NULL }, - { "a75", 759, NULL }, - { "a76", 892, NULL }, - { "a77", 892, NULL }, - { "a78", 788, NULL }, - { "a79", 784, NULL }, - { "a130", 788, NULL }, - { "a131", 788, NULL }, - { "a132", 788, NULL }, - { "a133", 788, NULL }, - { "a134", 788, NULL }, - { "a135", 788, NULL }, - { "a136", 788, NULL }, - { "a137", 788, NULL }, - { "a138", 788, NULL }, - { "a139", 788, NULL } -}; - -BuiltinFont builtinFonts[] = { - { "Courier", standardEncoding, 629, -157, { -23, -250, 715, 805}, NULL }, - { "Courier-Bold", standardEncoding, 629, -157, {-113, -250, 749, 801}, NULL }, - { "Courier-BoldOblique", standardEncoding, 629, -157, { -57, -250, 869, 801}, NULL }, - { "Courier-Oblique", standardEncoding, 629, -157, { -27, -250, 849, 805}, NULL }, - { "Helvetica", standardEncoding, 718, -207, {-166, -225, 1000, 931}, NULL }, - { "Helvetica-Bold", standardEncoding, 718, -207, {-170, -228, 1003, 962}, NULL }, - { "Helvetica-BoldOblique", standardEncoding, 718, -207, {-174, -228, 1114, 962}, NULL }, - { "Helvetica-Oblique", standardEncoding, 718, -207, {-170, -225, 1116, 931}, NULL }, - { "Symbol", symbolEncoding, 1010, -293, {-180, -293, 1090, 1010}, NULL }, - { "Times-Bold", standardEncoding, 683, -217, {-168, -218, 1000, 935}, NULL }, - { "Times-BoldItalic", standardEncoding, 683, -217, {-200, -218, 996, 921}, NULL }, - { "Times-Italic", standardEncoding, 683, -217, {-169, -217, 1010, 883}, NULL }, - { "Times-Roman", standardEncoding, 683, -217, {-168, -218, 1000, 898}, NULL }, - { "ZapfDingbats", zapfDingbatsEncoding, 820, -143, { -1, -143, 981, 820}, NULL } -}; - -BuiltinFont *builtinFontSubst[] = { - &builtinFonts[0], - &builtinFonts[3], - &builtinFonts[1], - &builtinFonts[2], - &builtinFonts[4], - &builtinFonts[7], - &builtinFonts[5], - &builtinFonts[6], - &builtinFonts[12], - &builtinFonts[11], - &builtinFonts[9], - &builtinFonts[10] -}; - -void initBuiltinFontTables() { - builtinFonts[0].widths = new BuiltinFontWidths(courierWidthsTab, 315); - builtinFonts[1].widths = new BuiltinFontWidths(courierBoldWidthsTab, 315); - builtinFonts[2].widths = new BuiltinFontWidths(courierBoldObliqueWidthsTab, 315); - builtinFonts[3].widths = new BuiltinFontWidths(courierObliqueWidthsTab, 315); - builtinFonts[4].widths = new BuiltinFontWidths(helveticaWidthsTab, 315); - builtinFonts[5].widths = new BuiltinFontWidths(helveticaBoldWidthsTab, 316); - builtinFonts[6].widths = new BuiltinFontWidths(helveticaBoldObliqueWidthsTab, 315); - builtinFonts[7].widths = new BuiltinFontWidths(helveticaObliqueWidthsTab, 315); - builtinFonts[8].widths = new BuiltinFontWidths(symbolWidthsTab, 190); - builtinFonts[9].widths = new BuiltinFontWidths(timesBoldWidthsTab, 315); - builtinFonts[10].widths = new BuiltinFontWidths(timesBoldItalicWidthsTab, 315); - builtinFonts[11].widths = new BuiltinFontWidths(timesItalicWidthsTab, 315); - builtinFonts[12].widths = new BuiltinFontWidths(timesRomanWidthsTab, 315); - builtinFonts[13].widths = new BuiltinFontWidths(zapfDingbatsWidthsTab, 202); -} - -void freeBuiltinFontTables() { - int i; - - for (i = 0; i < 14; ++i) { - delete builtinFonts[i].widths; - } -} diff --git a/pdftops/BuiltinFontTables.h b/pdftops/BuiltinFontTables.h deleted file mode 100644 index eb45549ef..000000000 --- a/pdftops/BuiltinFontTables.h +++ /dev/null @@ -1,23 +0,0 @@ -//======================================================================== -// -// BuiltinFontTables.h -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef BUILTINFONTTABLES_H -#define BUILTINFONTTABLES_H - -#include "BuiltinFont.h" - -#define nBuiltinFonts 14 -#define nBuiltinFontSubsts 12 - -extern BuiltinFont builtinFonts[nBuiltinFonts]; -extern BuiltinFont *builtinFontSubst[nBuiltinFontSubsts]; - -extern void initBuiltinFontTables(); -extern void freeBuiltinFontTables(); - -#endif diff --git a/pdftops/CMap.cxx b/pdftops/CMap.cxx deleted file mode 100644 index 3bcd656a5..000000000 --- a/pdftops/CMap.cxx +++ /dev/null @@ -1,408 +0,0 @@ -//======================================================================== -// -// CMap.cc -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include "gmem.h" -#include "gfile.h" -#include "GString.h" -#include "Error.h" -#include "GlobalParams.h" -#include "PSTokenizer.h" -#include "CMap.h" - -//------------------------------------------------------------------------ - -struct CMapVectorEntry { - GBool isVector; - union { - CMapVectorEntry *vector; - CID cid; - }; -}; - -//------------------------------------------------------------------------ - -static int getCharFromFile(void *data) { - return fgetc((FILE *)data); -} - -//------------------------------------------------------------------------ - -CMap *CMap::parse(CMapCache *cache, GString *collectionA, - GString *cMapNameA) { - FILE *f; - CMap *cmap; - PSTokenizer *pst; - char tok1[256], tok2[256], tok3[256]; - int n1, n2, n3; - Guint start, end, code; - - if (!(f = globalParams->findCMapFile(collectionA, cMapNameA))) { - - // Check for an identity CMap. - if (!cMapNameA->cmp("Identity") || !cMapNameA->cmp("Identity-H")) { - return new CMap(collectionA->copy(), cMapNameA->copy(), 0); - } - if (!cMapNameA->cmp("Identity-V")) { - return new CMap(collectionA->copy(), cMapNameA->copy(), 1); - } - - error(-1, "Couldn't find '%s' CMap file for '%s' collection", - cMapNameA->getCString(), collectionA->getCString()); - return NULL; - } - - cmap = new CMap(collectionA->copy(), cMapNameA->copy()); - - pst = new PSTokenizer(&getCharFromFile, f); - pst->getToken(tok1, sizeof(tok1), &n1); - while (pst->getToken(tok2, sizeof(tok2), &n2)) { - if (!strcmp(tok2, "usecmap")) { - if (tok1[0] == '/') { - cmap->useCMap(cache, tok1 + 1); - } - pst->getToken(tok1, sizeof(tok1), &n1); - } else if (!strcmp(tok1, "/WMode")) { - cmap->wMode = atoi(tok2); - pst->getToken(tok1, sizeof(tok1), &n1); - } else if (!strcmp(tok2, "begincodespacerange")) { - while (pst->getToken(tok1, sizeof(tok1), &n1)) { - if (!strcmp(tok1, "endcodespacerange")) { - break; - } - if (!pst->getToken(tok2, sizeof(tok2), &n2) || - !strcmp(tok2, "endcodespacerange")) { - error(-1, "Illegal entry in codespacerange block in CMap"); - break; - } - if (tok1[0] == '<' && tok2[0] == '<' && - n1 == n2 && n1 >= 4 && (n1 & 1) == 0) { - tok1[n1 - 1] = tok2[n1 - 1] = '\0'; - sscanf(tok1 + 1, "%x", &start); - sscanf(tok2 + 1, "%x", &end); - n1 = (n1 - 2) / 2; - cmap->addCodeSpace(cmap->vector, start, end, n1); - } - } - pst->getToken(tok1, sizeof(tok1), &n1); - } else if (!strcmp(tok2, "begincidchar")) { - while (pst->getToken(tok1, sizeof(tok1), &n1)) { - if (!strcmp(tok1, "endcidchar")) { - break; - } - if (!pst->getToken(tok2, sizeof(tok2), &n2) || - !strcmp(tok2, "endcidchar")) { - error(-1, "Illegal entry in cidchar block in CMap"); - break; - } - if (!(tok1[0] == '<' && tok1[n1 - 1] == '>' && - n1 >= 4 && (n1 & 1) == 0)) { - error(-1, "Illegal entry in cidchar block in CMap"); - continue; - } - tok1[n1 - 1] = '\0'; - if (sscanf(tok1 + 1, "%x", &code) != 1) { - error(-1, "Illegal entry in cidchar block in CMap"); - continue; - } - n1 = (n1 - 2) / 2; - cmap->addCIDs(code, code, n1, (CID)atoi(tok2)); - } - pst->getToken(tok1, sizeof(tok1), &n1); - } else if (!strcmp(tok2, "begincidrange")) { - while (pst->getToken(tok1, sizeof(tok1), &n1)) { - if (!strcmp(tok1, "endcidrange")) { - break; - } - if (!pst->getToken(tok2, sizeof(tok2), &n2) || - !strcmp(tok2, "endcidrange") || - !pst->getToken(tok3, sizeof(tok3), &n3) || - !strcmp(tok3, "endcidrange")) { - error(-1, "Illegal entry in cidrange block in CMap"); - break; - } - if (tok1[0] == '<' && tok2[0] == '<' && - n1 == n2 && n1 >= 4 && (n1 & 1) == 0) { - tok1[n1 - 1] = tok2[n1 - 1] = '\0'; - sscanf(tok1 + 1, "%x", &start); - sscanf(tok2 + 1, "%x", &end); - n1 = (n1 - 2) / 2; - cmap->addCIDs(start, end, n1, (CID)atoi(tok3)); - } - } - pst->getToken(tok1, sizeof(tok1), &n1); - } else { - strcpy(tok1, tok2); - } - } - delete pst; - - fclose(f); - - return cmap; -} - -CMap::CMap(GString *collectionA, GString *cMapNameA) { - int i; - - collection = collectionA; - cMapName = cMapNameA; - wMode = 0; - vector = (CMapVectorEntry *)gmallocn(256, sizeof(CMapVectorEntry)); - for (i = 0; i < 256; ++i) { - vector[i].isVector = gFalse; - vector[i].cid = 0; - } - refCnt = 1; -#if MULTITHREADED - gInitMutex(&mutex); -#endif -} - -CMap::CMap(GString *collectionA, GString *cMapNameA, int wModeA) { - collection = collectionA; - cMapName = cMapNameA; - wMode = wModeA; - vector = NULL; - refCnt = 1; -#if MULTITHREADED - gInitMutex(&mutex); -#endif -} - -void CMap::useCMap(CMapCache *cache, char *useName) { - GString *useNameStr; - CMap *subCMap; - - useNameStr = new GString(useName); - subCMap = cache->getCMap(collection, useNameStr); - delete useNameStr; - if (!subCMap) { - return; - } - copyVector(vector, subCMap->vector); - subCMap->decRefCnt(); -} - -void CMap::copyVector(CMapVectorEntry *dest, CMapVectorEntry *src) { - int i, j; - - for (i = 0; i < 256; ++i) { - if (src[i].isVector) { - if (!dest[i].isVector) { - dest[i].isVector = gTrue; - dest[i].vector = - (CMapVectorEntry *)gmallocn(256, sizeof(CMapVectorEntry)); - for (j = 0; j < 256; ++j) { - dest[i].vector[j].isVector = gFalse; - dest[i].vector[j].cid = 0; - } - } - copyVector(dest[i].vector, src[i].vector); - } else { - if (dest[i].isVector) { - error(-1, "Collision in usecmap"); - } else { - dest[i].cid = src[i].cid; - } - } - } -} - -void CMap::addCodeSpace(CMapVectorEntry *vec, Guint start, Guint end, - Guint nBytes) { - Guint start2, end2; - int startByte, endByte, i, j; - - if (nBytes > 1) { - startByte = (start >> (8 * (nBytes - 1))) & 0xff; - endByte = (end >> (8 * (nBytes - 1))) & 0xff; - start2 = start & ((1 << (8 * (nBytes - 1))) - 1); - end2 = end & ((1 << (8 * (nBytes - 1))) - 1); - for (i = startByte; i <= endByte; ++i) { - if (!vec[i].isVector) { - vec[i].isVector = gTrue; - vec[i].vector = - (CMapVectorEntry *)gmallocn(256, sizeof(CMapVectorEntry)); - for (j = 0; j < 256; ++j) { - vec[i].vector[j].isVector = gFalse; - vec[i].vector[j].cid = 0; - } - } - addCodeSpace(vec[i].vector, start2, end2, nBytes - 1); - } - } -} - -void CMap::addCIDs(Guint start, Guint end, Guint nBytes, CID firstCID) { - CMapVectorEntry *vec; - CID cid; - int byte; - Guint i; - - vec = vector; - for (i = nBytes - 1; i >= 1; --i) { - byte = (start >> (8 * i)) & 0xff; - if (!vec[byte].isVector) { - error(-1, "Invalid CID (%0*x - %0*x) in CMap", - 2*nBytes, start, 2*nBytes, end); - return; - } - vec = vec[byte].vector; - } - cid = firstCID; - for (byte = (int)(start & 0xff); byte <= (int)(end & 0xff); ++byte) { - if (vec[byte].isVector) { - error(-1, "Invalid CID (%0*x - %0*x) in CMap", - 2*nBytes, start, 2*nBytes, end); - } else { - vec[byte].cid = cid; - } - ++cid; - } -} - -CMap::~CMap() { - delete collection; - delete cMapName; - if (vector) { - freeCMapVector(vector); - } -#if MULTITHREADED - gDestroyMutex(&mutex); -#endif -} - -void CMap::freeCMapVector(CMapVectorEntry *vec) { - int i; - - for (i = 0; i < 256; ++i) { - if (vec[i].isVector) { - freeCMapVector(vec[i].vector); - } - } - gfree(vec); -} - -void CMap::incRefCnt() { -#if MULTITHREADED - gLockMutex(&mutex); -#endif - ++refCnt; -#if MULTITHREADED - gUnlockMutex(&mutex); -#endif -} - -void CMap::decRefCnt() { - GBool done; - -#if MULTITHREADED - gLockMutex(&mutex); -#endif - done = --refCnt == 0; -#if MULTITHREADED - gUnlockMutex(&mutex); -#endif - if (done) { - delete this; - } -} - -GBool CMap::match(GString *collectionA, GString *cMapNameA) { - return !collection->cmp(collectionA) && !cMapName->cmp(cMapNameA); -} - -CID CMap::getCID(char *s, int len, int *nUsed) { - CMapVectorEntry *vec; - int n, i; - - if (!(vec = vector)) { - // identity CMap - *nUsed = 2; - if (len < 2) { - return 0; - } - return ((s[0] & 0xff) << 8) + (s[1] & 0xff); - } - n = 0; - while (1) { - if (n >= len) { - *nUsed = n; - return 0; - } - i = s[n++] & 0xff; - if (!vec[i].isVector) { - *nUsed = n; - return vec[i].cid; - } - vec = vec[i].vector; - } -} - -//------------------------------------------------------------------------ - -CMapCache::CMapCache() { - int i; - - for (i = 0; i < cMapCacheSize; ++i) { - cache[i] = NULL; - } -} - -CMapCache::~CMapCache() { - int i; - - for (i = 0; i < cMapCacheSize; ++i) { - if (cache[i]) { - cache[i]->decRefCnt(); - } - } -} - -CMap *CMapCache::getCMap(GString *collection, GString *cMapName) { - CMap *cmap; - int i, j; - - if (cache[0] && cache[0]->match(collection, cMapName)) { - cache[0]->incRefCnt(); - return cache[0]; - } - for (i = 1; i < cMapCacheSize; ++i) { - if (cache[i] && cache[i]->match(collection, cMapName)) { - cmap = cache[i]; - for (j = i; j >= 1; --j) { - cache[j] = cache[j - 1]; - } - cache[0] = cmap; - cmap->incRefCnt(); - return cmap; - } - } - if ((cmap = CMap::parse(this, collection, cMapName))) { - if (cache[cMapCacheSize - 1]) { - cache[cMapCacheSize - 1]->decRefCnt(); - } - for (j = cMapCacheSize - 1; j >= 1; --j) { - cache[j] = cache[j - 1]; - } - cache[0] = cmap; - cmap->incRefCnt(); - return cmap; - } - return NULL; -} diff --git a/pdftops/CMap.h b/pdftops/CMap.h deleted file mode 100644 index a89266c8d..000000000 --- a/pdftops/CMap.h +++ /dev/null @@ -1,102 +0,0 @@ -//======================================================================== -// -// CMap.h -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef CMAP_H -#define CMAP_H - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "gtypes.h" -#include "CharTypes.h" - -#if MULTITHREADED -#include "GMutex.h" -#endif - -class GString; -struct CMapVectorEntry; -class CMapCache; - -//------------------------------------------------------------------------ - -class CMap { -public: - - // Create the CMap specified by <collection> and <cMapName>. Sets - // the initial reference count to 1. Returns NULL on failure. - static CMap *parse(CMapCache *cache, GString *collectionA, - GString *cMapNameA); - - ~CMap(); - - void incRefCnt(); - void decRefCnt(); - - // Return collection name (<registry>-<ordering>). - GString *getCollection() { return collection; } - - // Return true if this CMap matches the specified <collectionA>, and - // <cMapNameA>. - GBool match(GString *collectionA, GString *cMapNameA); - - // Return the CID corresponding to the character code starting at - // <s>, which contains <len> bytes. Sets *<nUsed> to the number of - // bytes used by the char code. - CID getCID(char *s, int len, int *nUsed); - - // Return the writing mode (0=horizontal, 1=vertical). - int getWMode() { return wMode; } - -private: - - CMap(GString *collectionA, GString *cMapNameA); - CMap(GString *collectionA, GString *cMapNameA, int wModeA); - void useCMap(CMapCache *cache, char *useName); - void copyVector(CMapVectorEntry *dest, CMapVectorEntry *src); - void addCodeSpace(CMapVectorEntry *vec, Guint start, Guint end, - Guint nBytes); - void addCIDs(Guint start, Guint end, Guint nBytes, CID firstCID); - void freeCMapVector(CMapVectorEntry *vec); - - GString *collection; - GString *cMapName; - int wMode; // writing mode (0=horizontal, 1=vertical) - CMapVectorEntry *vector; // vector for first byte (NULL for - // identity CMap) - int refCnt; -#if MULTITHREADED - GMutex mutex; -#endif -}; - -//------------------------------------------------------------------------ - -#define cMapCacheSize 4 - -class CMapCache { -public: - - CMapCache(); - ~CMapCache(); - - // Get the <cMapName> CMap for the specified character collection. - // Increments its reference count; there will be one reference for - // the cache plus one for the caller of this function. Returns NULL - // on failure. - CMap *getCMap(GString *collection, GString *cMapName); - -private: - - CMap *cache[cMapCacheSize]; -}; - -#endif diff --git a/pdftops/COPYING b/pdftops/COPYING deleted file mode 100644 index a43ea2126..000000000 --- a/pdftops/COPYING +++ /dev/null @@ -1,339 +0,0 @@ - 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. - - <one line to give the program's name and a brief idea of what it does.> - Copyright (C) 19yy <name of author> - - 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. - - <signature of Ty Coon>, 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 deleted file mode 100644 index 4fa6e8e91..000000000 --- a/pdftops/Catalog.cxx +++ /dev/null @@ -1,363 +0,0 @@ -//======================================================================== -// -// Catalog.cc -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include <stddef.h> -#include "gmem.h" -#include "Object.h" -#include "XRef.h" -#include "Array.h" -#include "Dict.h" -#include "Page.h" -#include "Error.h" -#include "Link.h" -#include "Catalog.h" - -// This define is used to limit the depth of recursive readPageTree calls -// This is needed because the page tree nodes can reference their parents -// leaving us in an infinite loop -// Most sane pdf documents don't have a call depth higher than 10 -#define MAX_CALL_DEPTH 1000 - -//------------------------------------------------------------------------ -// Catalog -//------------------------------------------------------------------------ - -Catalog::Catalog(XRef *xrefA) { - Object catDict, pagesDict; - Object obj, obj2; - int numPages0; - int i; - - ok = gTrue; - xref = xrefA; - pages = NULL; - pageRefs = NULL; - numPages = pagesSize = 0; - baseURI = NULL; - - xref->getCatalog(&catDict); - 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); - // some PDF files actually use real numbers here ("/Count 9.0") - if (!obj.isNum()) { - error(-1, "Page count in top-level pages object is wrong type (%s)", - obj.getTypeName()); - goto err3; - } - pagesSize = numPages0 = (int)obj.getNum(); - obj.free(); - pages = (Page **)gmallocn(pagesSize, sizeof(Page *)); - pageRefs = (Ref *)gmallocn(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, 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 - if (catDict.dictLookup("URI", &obj)->isDict()) { - if (obj.dictLookup("Base", &obj2)->isString()) { - baseURI = obj2.getString()->copy(); - } - obj2.free(); - } - obj.free(); - - // get the metadata stream - catDict.dictLookup("Metadata", &metadata); - - // get the structure tree root - catDict.dictLookup("StructTreeRoot", &structTreeRoot); - - // get the outline dictionary - catDict.dictLookup("Outlines", &outline); - - // get the AcroForm dictionary - catDict.dictLookup("AcroForm", &acroForm); - - catDict.free(); - return; - - err3: - obj.free(); - err2: - pagesDict.free(); - err1: - catDict.free(); - 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; - } - metadata.free(); - structTreeRoot.free(); - outline.free(); - acroForm.free(); -} - -GString *Catalog::readMetadata() { - GString *s; - Dict *dict; - Object obj; - int c; - - if (!metadata.isStream()) { - return NULL; - } - dict = metadata.streamGetDict(); - if (!dict->lookup("Subtype", &obj)->isName("XML")) { - error(-1, "Unknown Metadata type: '%s'", - obj.isName() ? obj.getName() : "???"); - } - obj.free(); - s = new GString(); - metadata.streamReset(); - while ((c = metadata.streamGetChar()) != EOF) { - s->append(c); - } - metadata.streamClose(); - return s; -} - -int Catalog::readPageTree(Dict *pagesDict, PageAttrs *attrs, int start, int callDepth) { - 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(xref, start+1, kid.getDict(), attrs2); - if (!page->isOk()) { - ++start; - goto err3; - } - if (start >= pagesSize) { - pagesSize += 32; - pages = (Page **)greallocn(pages, pagesSize, sizeof(Page *)); - pageRefs = (Ref *)greallocn(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 (callDepth > MAX_CALL_DEPTH) { - error(-1, "Limit of %d recursive calls reached while reading the page tree. If your document is correct and not a test to try to force a crash, please report a bug.", MAX_CALL_DEPTH); - } else { - if ((start = readPageTree(kid.getDict(), attrs1, start, callDepth + 1)) - < 0) - goto err2; - } - } else { - error(-1, "Kid object (page %d) is wrong type (%s)", - start+1, kid.getTypeName()); - } - 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()); - } else if (obj1.isDict()) { - if (obj1.dictLookup("D", &obj2)->isArray()) - dest = new LinkDest(obj2.getArray()); - else - error(-1, "Bad named destination value"); - obj2.free(); - } else { - error(-1, "Bad named destination value"); - } - obj1.free(); - if (dest && !dest->isOk()) { - delete dest; - dest = NULL; - } - - 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 deleted file mode 100644 index 8cef94818..000000000 --- a/pdftops/Catalog.h +++ /dev/null @@ -1,92 +0,0 @@ -//======================================================================== -// -// Catalog.h -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef CATALOG_H -#define CATALOG_H - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -class XRef; -class Object; -class Page; -class PageAttrs; -struct Ref; -class LinkDest; - -//------------------------------------------------------------------------ -// Catalog -//------------------------------------------------------------------------ - -class Catalog { -public: - - // Constructor. - Catalog(XRef *xrefA); - - // 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; } - - // Return the contents of the metadata stream, or NULL if there is - // no metadata. - GString *readMetadata(); - - // Return the structure tree root object. - Object *getStructTreeRoot() { return &structTreeRoot; } - - // 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 <name> is not a destination. - LinkDest *findDest(GString *name); - - Object *getOutline() { return &outline; } - - Object *getAcroForm() { return &acroForm; } - -private: - - XRef *xref; // the xref table for this PDF file - 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 - Object metadata; // metadata stream - Object structTreeRoot; // structure tree root dictionary - Object outline; // outline dictionary - Object acroForm; // AcroForm dictionary - GBool ok; // true if catalog is valid - - int readPageTree(Dict *pages, PageAttrs *attrs, int start, int callDepth); - Object *findDestInTree(Object *tree, GString *name, Object *obj); -}; - -#endif diff --git a/pdftops/CharCodeToUnicode.cxx b/pdftops/CharCodeToUnicode.cxx deleted file mode 100644 index 5dcb2e92e..000000000 --- a/pdftops/CharCodeToUnicode.cxx +++ /dev/null @@ -1,540 +0,0 @@ -//======================================================================== -// -// CharCodeToUnicode.cc -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include <stdio.h> -#include <string.h> -#include "gmem.h" -#include "gfile.h" -#include "GString.h" -#include "Error.h" -#include "GlobalParams.h" -#include "PSTokenizer.h" -#include "CharCodeToUnicode.h" - -//------------------------------------------------------------------------ - -#define maxUnicodeString 8 - -struct CharCodeToUnicodeString { - CharCode c; - Unicode u[maxUnicodeString]; - int len; -}; - -//------------------------------------------------------------------------ - -static int getCharFromString(void *data) { - char *p; - int c; - - p = *(char **)data; - if (*p) { - c = *p++; - *(char **)data = p; - } else { - c = EOF; - } - return c; -} - -static int getCharFromFile(void *data) { - return fgetc((FILE *)data); -} - -//------------------------------------------------------------------------ - -CharCodeToUnicode *CharCodeToUnicode::parseCIDToUnicode(GString *fileName, - GString *collection) { - FILE *f; - Unicode *mapA; - CharCode size, mapLenA; - char buf[64]; - Unicode u; - CharCodeToUnicode *ctu; - - if (!(f = fopen(fileName->getCString(), "r"))) { - error(-1, "Couldn't open cidToUnicode file '%s'", - fileName->getCString()); - return NULL; - } - - size = 32768; - mapA = (Unicode *)gmallocn(size, sizeof(Unicode)); - mapLenA = 0; - - while (getLine(buf, sizeof(buf), f)) { - if (mapLenA == size) { - size *= 2; - mapA = (Unicode *)greallocn(mapA, size, sizeof(Unicode)); - } - if (sscanf(buf, "%x", &u) == 1) { - mapA[mapLenA] = u; - } else { - error(-1, "Bad line (%d) in cidToUnicode file '%s'", - (int)(mapLenA + 1), fileName->getCString()); - mapA[mapLenA] = 0; - } - ++mapLenA; - } - fclose(f); - - ctu = new CharCodeToUnicode(collection->copy(), mapA, mapLenA, gTrue, - NULL, 0, 0); - gfree(mapA); - return ctu; -} - -CharCodeToUnicode *CharCodeToUnicode::parseUnicodeToUnicode( - GString *fileName) { - FILE *f; - Unicode *mapA; - CharCodeToUnicodeString *sMapA; - CharCode size, oldSize, len, sMapSizeA, sMapLenA; - char buf[256]; - char *tok; - Unicode u0; - Unicode uBuf[maxUnicodeString]; - CharCodeToUnicode *ctu; - int line, n, i; - - if (!(f = fopen(fileName->getCString(), "r"))) { - error(-1, "Couldn't open unicodeToUnicode file '%s'", - fileName->getCString()); - return NULL; - } - - size = 4096; - mapA = (Unicode *)gmallocn(size, sizeof(Unicode)); - memset(mapA, 0, size * sizeof(Unicode)); - len = 0; - sMapA = NULL; - sMapSizeA = sMapLenA = 0; - - line = 0; - while (getLine(buf, sizeof(buf), f)) { - ++line; - if (!(tok = strtok(buf, " \t\r\n")) || - sscanf(tok, "%x", &u0) != 1) { - error(-1, "Bad line (%d) in unicodeToUnicode file '%s'", - line, fileName->getCString()); - continue; - } - n = 0; - while (n < maxUnicodeString) { - if (!(tok = strtok(NULL, " \t\r\n"))) { - break; - } - if (sscanf(tok, "%x", &uBuf[n]) != 1) { - error(-1, "Bad line (%d) in unicodeToUnicode file '%s'", - line, fileName->getCString()); - break; - } - ++n; - } - if (n < 1) { - error(-1, "Bad line (%d) in unicodeToUnicode file '%s'", - line, fileName->getCString()); - continue; - } - if (u0 >= size) { - oldSize = size; - while (u0 >= size) { - size *= 2; - } - mapA = (Unicode *)greallocn(mapA, size, sizeof(Unicode)); - memset(mapA + oldSize, 0, (size - oldSize) * sizeof(Unicode)); - } - if (n == 1) { - mapA[u0] = uBuf[0]; - } else { - mapA[u0] = 0; - if (sMapLenA == sMapSizeA) { - sMapSizeA += 16; - sMapA = (CharCodeToUnicodeString *) - greallocn(sMapA, sMapSizeA, sizeof(CharCodeToUnicodeString)); - } - sMapA[sMapLenA].c = u0; - for (i = 0; i < n; ++i) { - sMapA[sMapLenA].u[i] = uBuf[i]; - } - sMapA[sMapLenA].len = n; - ++sMapLenA; - } - if (u0 >= len) { - len = u0 + 1; - } - } - fclose(f); - - ctu = new CharCodeToUnicode(fileName->copy(), mapA, len, gTrue, - sMapA, sMapLenA, sMapSizeA); - gfree(mapA); - return ctu; -} - -CharCodeToUnicode *CharCodeToUnicode::make8BitToUnicode(Unicode *toUnicode) { - return new CharCodeToUnicode(NULL, toUnicode, 256, gTrue, NULL, 0, 0); -} - -CharCodeToUnicode *CharCodeToUnicode::parseCMap(GString *buf, int nBits) { - CharCodeToUnicode *ctu; - char *p; - - ctu = new CharCodeToUnicode(NULL); - p = buf->getCString(); - ctu->parseCMap1(&getCharFromString, &p, nBits); - return ctu; -} - -void CharCodeToUnicode::mergeCMap(GString *buf, int nBits) { - char *p; - - p = buf->getCString(); - parseCMap1(&getCharFromString, &p, nBits); -} - -void CharCodeToUnicode::parseCMap1(int (*getCharFunc)(void *), void *data, - int nBits) { - PSTokenizer *pst; - char tok1[256], tok2[256], tok3[256]; - int nDigits, n1, n2, n3; - CharCode i; - CharCode code1, code2; - GString *name; - FILE *f; - - nDigits = nBits / 4; - pst = new PSTokenizer(getCharFunc, data); - pst->getToken(tok1, sizeof(tok1), &n1); - while (pst->getToken(tok2, sizeof(tok2), &n2)) { - if (!strcmp(tok2, "usecmap")) { - if (tok1[0] == '/') { - name = new GString(tok1 + 1); - if ((f = globalParams->findToUnicodeFile(name))) { - parseCMap1(&getCharFromFile, f, nBits); - fclose(f); - } else { - error(-1, "Couldn't find ToUnicode CMap file for '%s'", - name->getCString()); - } - delete name; - } - pst->getToken(tok1, sizeof(tok1), &n1); - } else if (!strcmp(tok2, "beginbfchar")) { - while (pst->getToken(tok1, sizeof(tok1), &n1)) { - if (!strcmp(tok1, "endbfchar")) { - break; - } - if (!pst->getToken(tok2, sizeof(tok2), &n2) || - !strcmp(tok2, "endbfchar")) { - error(-1, "Illegal entry in bfchar block in ToUnicode CMap"); - break; - } - if (!(n1 == 2 + nDigits && tok1[0] == '<' && tok1[n1 - 1] == '>' && - tok2[0] == '<' && tok2[n2 - 1] == '>')) { - error(-1, "Illegal entry in bfchar block in ToUnicode CMap"); - continue; - } - tok1[n1 - 1] = tok2[n2 - 1] = '\0'; - if (sscanf(tok1 + 1, "%x", &code1) != 1) { - error(-1, "Illegal entry in bfchar block in ToUnicode CMap"); - continue; - } - addMapping(code1, tok2 + 1, n2 - 2, 0); - } - pst->getToken(tok1, sizeof(tok1), &n1); - } else if (!strcmp(tok2, "beginbfrange")) { - while (pst->getToken(tok1, sizeof(tok1), &n1)) { - if (!strcmp(tok1, "endbfrange")) { - break; - } - if (!pst->getToken(tok2, sizeof(tok2), &n2) || - !strcmp(tok2, "endbfrange") || - !pst->getToken(tok3, sizeof(tok3), &n3) || - !strcmp(tok3, "endbfrange")) { - error(-1, "Illegal entry in bfrange block in ToUnicode CMap"); - break; - } - if (!(n1 == 2 + nDigits && tok1[0] == '<' && tok1[n1 - 1] == '>' && - n2 == 2 + nDigits && tok2[0] == '<' && tok2[n2 - 1] == '>')) { - error(-1, "Illegal entry in bfrange block in ToUnicode CMap"); - continue; - } - tok1[n1 - 1] = tok2[n2 - 1] = '\0'; - if (sscanf(tok1 + 1, "%x", &code1) != 1 || - sscanf(tok2 + 1, "%x", &code2) != 1) { - error(-1, "Illegal entry in bfrange block in ToUnicode CMap"); - continue; - } - if (!strcmp(tok3, "[")) { - i = 0; - while (pst->getToken(tok1, sizeof(tok1), &n1) && - code1 + i <= code2) { - if (!strcmp(tok1, "]")) { - break; - } - if (tok1[0] == '<' && tok1[n1 - 1] == '>') { - tok1[n1 - 1] = '\0'; - addMapping(code1 + i, tok1 + 1, n1 - 2, 0); - } else { - error(-1, "Illegal entry in bfrange block in ToUnicode CMap"); - } - ++i; - } - } else if (tok3[0] == '<' && tok3[n3 - 1] == '>') { - tok3[n3 - 1] = '\0'; - for (i = 0; code1 <= code2; ++code1, ++i) { - addMapping(code1, tok3 + 1, n3 - 2, i); - } - - } else { - error(-1, "Illegal entry in bfrange block in ToUnicode CMap"); - } - } - pst->getToken(tok1, sizeof(tok1), &n1); - } else { - strcpy(tok1, tok2); - } - } - delete pst; -} - -void CharCodeToUnicode::addMapping(CharCode code, char *uStr, int n, - int offset) { - CharCode oldLen, i; - Unicode u; - char uHex[5]; - int j; - - if (code >= mapLen) { - oldLen = mapLen; - mapLen = (code + 256) & ~255; - map = (Unicode *)greallocn(map, mapLen, sizeof(Unicode)); - for (i = oldLen; i < mapLen; ++i) { - map[i] = 0; - } - } - if (n <= 4) { - if (sscanf(uStr, "%x", &u) != 1) { - error(-1, "Illegal entry in ToUnicode CMap"); - return; - } - map[code] = u + offset; - } else { - if (sMapLen >= sMapSize) { - sMapSize = sMapSize + 16; - sMap = (CharCodeToUnicodeString *) - greallocn(sMap, sMapSize, sizeof(CharCodeToUnicodeString)); - } - map[code] = 0; - sMap[sMapLen].c = code; - sMap[sMapLen].len = n / 4; - for (j = 0; j < sMap[sMapLen].len && j < maxUnicodeString; ++j) { - strncpy(uHex, uStr + j*4, 4); - uHex[4] = '\0'; - if (sscanf(uHex, "%x", &sMap[sMapLen].u[j]) != 1) { - error(-1, "Illegal entry in ToUnicode CMap"); - } - } - sMap[sMapLen].u[sMap[sMapLen].len - 1] += offset; - ++sMapLen; - } -} - -CharCodeToUnicode::CharCodeToUnicode(GString *tagA) { - CharCode i; - - tag = tagA; - mapLen = 256; - map = (Unicode *)gmallocn(mapLen, sizeof(Unicode)); - for (i = 0; i < mapLen; ++i) { - map[i] = 0; - } - sMap = NULL; - sMapLen = sMapSize = 0; - refCnt = 1; -#if MULTITHREADED - gInitMutex(&mutex); -#endif -} - -CharCodeToUnicode::CharCodeToUnicode(GString *tagA, Unicode *mapA, - CharCode mapLenA, GBool copyMap, - CharCodeToUnicodeString *sMapA, - int sMapLenA, int sMapSizeA) { - tag = tagA; - mapLen = mapLenA; - if (copyMap) { - map = (Unicode *)gmallocn(mapLen, sizeof(Unicode)); - memcpy(map, mapA, mapLen * sizeof(Unicode)); - } else { - map = mapA; - } - sMap = sMapA; - sMapLen = sMapLenA; - sMapSize = sMapSizeA; - refCnt = 1; -#if MULTITHREADED - gInitMutex(&mutex); -#endif -} - -CharCodeToUnicode::~CharCodeToUnicode() { - if (tag) { - delete tag; - } - gfree(map); - if (sMap) { - gfree(sMap); - } -#if MULTITHREADED - gDestroyMutex(&mutex); -#endif -} - -void CharCodeToUnicode::incRefCnt() { -#if MULTITHREADED - gLockMutex(&mutex); -#endif - ++refCnt; -#if MULTITHREADED - gUnlockMutex(&mutex); -#endif -} - -void CharCodeToUnicode::decRefCnt() { - GBool done; - -#if MULTITHREADED - gLockMutex(&mutex); -#endif - done = --refCnt == 0; -#if MULTITHREADED - gUnlockMutex(&mutex); -#endif - if (done) { - delete this; - } -} - -GBool CharCodeToUnicode::match(GString *tagA) { - return tag && !tag->cmp(tagA); -} - -void CharCodeToUnicode::setMapping(CharCode c, Unicode *u, int len) { - int i, j; - - if (len == 1) { - map[c] = u[0]; - } else { - for (i = 0; i < sMapLen; ++i) { - if (sMap[i].c == c) { - break; - } - } - if (i == sMapLen) { - if (sMapLen == sMapSize) { - sMapSize += 8; - sMap = (CharCodeToUnicodeString *) - greallocn(sMap, sMapSize, sizeof(CharCodeToUnicodeString)); - } - ++sMapLen; - } - map[c] = 0; - sMap[i].c = c; - sMap[i].len = len; - for (j = 0; j < len && j < maxUnicodeString; ++j) { - sMap[i].u[j] = u[j]; - } - } -} - -int CharCodeToUnicode::mapToUnicode(CharCode c, Unicode *u, int size) { - int i, j; - - if (c >= mapLen) { - return 0; - } - if (map[c]) { - u[0] = map[c]; - return 1; - } - for (i = 0; i < sMapLen; ++i) { - if (sMap[i].c == c) { - for (j = 0; j < sMap[i].len && j < size; ++j) { - u[j] = sMap[i].u[j]; - } - return j; - } - } - return 0; -} - -//------------------------------------------------------------------------ - -CharCodeToUnicodeCache::CharCodeToUnicodeCache(int sizeA) { - int i; - - size = sizeA; - cache = (CharCodeToUnicode **)gmallocn(size, sizeof(CharCodeToUnicode *)); - for (i = 0; i < size; ++i) { - cache[i] = NULL; - } -} - -CharCodeToUnicodeCache::~CharCodeToUnicodeCache() { - int i; - - for (i = 0; i < size; ++i) { - if (cache[i]) { - cache[i]->decRefCnt(); - } - } - gfree(cache); -} - -CharCodeToUnicode *CharCodeToUnicodeCache::getCharCodeToUnicode(GString *tag) { - CharCodeToUnicode *ctu; - int i, j; - - if (cache[0] && cache[0]->match(tag)) { - cache[0]->incRefCnt(); - return cache[0]; - } - for (i = 1; i < size; ++i) { - if (cache[i] && cache[i]->match(tag)) { - ctu = cache[i]; - for (j = i; j >= 1; --j) { - cache[j] = cache[j - 1]; - } - cache[0] = ctu; - ctu->incRefCnt(); - return ctu; - } - } - return NULL; -} - -void CharCodeToUnicodeCache::add(CharCodeToUnicode *ctu) { - int i; - - if (cache[size - 1]) { - cache[size - 1]->decRefCnt(); - } - for (i = size - 1; i >= 1; --i) { - cache[i] = cache[i - 1]; - } - cache[0] = ctu; - ctu->incRefCnt(); -} diff --git a/pdftops/CharCodeToUnicode.h b/pdftops/CharCodeToUnicode.h deleted file mode 100644 index c7544f8c2..000000000 --- a/pdftops/CharCodeToUnicode.h +++ /dev/null @@ -1,117 +0,0 @@ -//======================================================================== -// -// CharCodeToUnicode.h -// -// Mapping from character codes to Unicode. -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef CHARCODETOUNICODE_H -#define CHARCODETOUNICODE_H - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "CharTypes.h" - -#if MULTITHREADED -#include "GMutex.h" -#endif - -struct CharCodeToUnicodeString; - -//------------------------------------------------------------------------ - -class CharCodeToUnicode { -public: - - // Read the CID-to-Unicode mapping for <collection> from the file - // specified by <fileName>. Sets the initial reference count to 1. - // Returns NULL on failure. - static CharCodeToUnicode *parseCIDToUnicode(GString *fileName, - GString *collection); - - // Create a Unicode-to-Unicode mapping from the file specified by - // <fileName>. Sets the initial reference count to 1. Returns NULL - // on failure. - static CharCodeToUnicode *parseUnicodeToUnicode(GString *fileName); - - // Create the CharCode-to-Unicode mapping for an 8-bit font. - // <toUnicode> is an array of 256 Unicode indexes. Sets the initial - // reference count to 1. - static CharCodeToUnicode *make8BitToUnicode(Unicode *toUnicode); - - // Parse a ToUnicode CMap for an 8- or 16-bit font. - static CharCodeToUnicode *parseCMap(GString *buf, int nBits); - - // Parse a ToUnicode CMap for an 8- or 16-bit font, merging it into - // <this>. - void mergeCMap(GString *buf, int nBits); - - ~CharCodeToUnicode(); - - void incRefCnt(); - void decRefCnt(); - - // Return true if this mapping matches the specified <tagA>. - GBool match(GString *tagA); - - // Set the mapping for <c>. - void setMapping(CharCode c, Unicode *u, int len); - - // Map a CharCode to Unicode. - int mapToUnicode(CharCode c, Unicode *u, int size); - - // Return the mapping's length, i.e., one more than the max char - // code supported by the mapping. - CharCode getLength() { return mapLen; } - -private: - - void parseCMap1(int (*getCharFunc)(void *), void *data, int nBits); - void addMapping(CharCode code, char *uStr, int n, int offset); - CharCodeToUnicode(GString *tagA); - CharCodeToUnicode(GString *tagA, Unicode *mapA, - CharCode mapLenA, GBool copyMap, - CharCodeToUnicodeString *sMapA, - int sMapLenA, int sMapSizeA); - - GString *tag; - Unicode *map; - CharCode mapLen; - CharCodeToUnicodeString *sMap; - int sMapLen, sMapSize; - int refCnt; -#if MULTITHREADED - GMutex mutex; -#endif -}; - -//------------------------------------------------------------------------ - -class CharCodeToUnicodeCache { -public: - - CharCodeToUnicodeCache(int sizeA); - ~CharCodeToUnicodeCache(); - - // Get the CharCodeToUnicode object for <tag>. Increments its - // reference count; there will be one reference for the cache plus - // one for the caller of this function. Returns NULL on failure. - CharCodeToUnicode *getCharCodeToUnicode(GString *tag); - - // Insert <ctu> into the cache, in the most-recently-used position. - void add(CharCodeToUnicode *ctu); - -private: - - CharCodeToUnicode **cache; - int size; -}; - -#endif diff --git a/pdftops/CharTypes.h b/pdftops/CharTypes.h deleted file mode 100644 index d0df630d0..000000000 --- a/pdftops/CharTypes.h +++ /dev/null @@ -1,24 +0,0 @@ -//======================================================================== -// -// CharTypes.h -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef CHARTYPES_H -#define CHARTYPES_H - -// Unicode character. -typedef unsigned int Unicode; - -// Character ID for CID character collections. -typedef unsigned int CID; - -// This is large enough to hold any of the following: -// - 8-bit char code -// - 16-bit CID -// - Unicode -typedef unsigned int CharCode; - -#endif diff --git a/pdftops/CompactFontTables.h b/pdftops/CompactFontTables.h deleted file mode 100644 index 28e16e775..000000000 --- a/pdftops/CompactFontTables.h +++ /dev/null @@ -1,464 +0,0 @@ -//======================================================================== -// -// CompactFontTables.h -// -// Copyright 1999-2003 Glyph & Cog, LLC -// -//======================================================================== - -#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 deleted file mode 100644 index 88b62056d..000000000 --- a/pdftops/Decrypt.cxx +++ /dev/null @@ -1,417 +0,0 @@ -//======================================================================== -// -// Decrypt.cc -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include <string.h> -#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 keyLength, int objNum, int objGen) { - int i; - - // construct object key - for (i = 0; i < keyLength; ++i) { - objKey[i] = fileKey[i]; - } - objKey[keyLength] = objNum & 0xff; - objKey[keyLength + 1] = (objNum >> 8) & 0xff; - objKey[keyLength + 2] = (objNum >> 16) & 0xff; - objKey[keyLength + 3] = objGen & 0xff; - objKey[keyLength + 4] = (objGen >> 8) & 0xff; - md5(objKey, keyLength + 5, objKey); - - // set up for decryption - x = y = 0; - if ((objKeyLength = keyLength + 5) > 16) { - objKeyLength = 16; - } - rc4InitKey(objKey, objKeyLength, state); -} - -void Decrypt::reset() { - x = y = 0; - rc4InitKey(objKey, objKeyLength, state); -} - -Guchar Decrypt::decryptByte(Guchar c) { - return rc4DecryptByte(state, &x, &y, c); -} - -GBool Decrypt::makeFileKey(int encVersion, int encRevision, int keyLength, - GString *ownerKey, GString *userKey, - int permissions, GString *fileID, - GString *ownerPassword, GString *userPassword, - Guchar *fileKey, GBool encryptMetadata, - GBool *ownerPasswordOk) { - Guchar test[32], test2[32]; - GString *userPassword2; - Guchar fState[256]; - Guchar tmpKey[16]; - Guchar fx, fy; - int len, i, j; - - // try using the supplied owner password to generate the user password - *ownerPasswordOk = gFalse; - if (ownerPassword) { - len = ownerPassword->getLength(); - if (len < 32) { - memcpy(test, ownerPassword->getCString(), len); - memcpy(test + len, passwordPad, 32 - len); - } else { - memcpy(test, ownerPassword->getCString(), 32); - } - md5(test, 32, test); - if (encRevision == 3) { - for (i = 0; i < 50; ++i) { - md5(test, 16, test); - } - } - if (encRevision == 2) { - rc4InitKey(test, keyLength, fState); - fx = fy = 0; - for (i = 0; i < 32; ++i) { - test2[i] = rc4DecryptByte(fState, &fx, &fy, ownerKey->getChar(i)); - } - } else { - memcpy(test2, ownerKey->getCString(), 32); - for (i = 19; i >= 0; --i) { - for (j = 0; j < keyLength; ++j) { - tmpKey[j] = test[j] ^ i; - } - rc4InitKey(tmpKey, keyLength, fState); - fx = fy = 0; - for (j = 0; j < 32; ++j) { - test2[j] = rc4DecryptByte(fState, &fx, &fy, test2[j]); - } - } - } - userPassword2 = new GString((char *)test2, 32); - if (makeFileKey2(encVersion, encRevision, keyLength, ownerKey, userKey, - permissions, fileID, userPassword2, fileKey, - encryptMetadata)) { - *ownerPasswordOk = gTrue; - delete userPassword2; - return gTrue; - } - delete userPassword2; - } - - // try using the supplied user password - return makeFileKey2(encVersion, encRevision, keyLength, ownerKey, userKey, - permissions, fileID, userPassword, fileKey, - encryptMetadata); -} - -GBool Decrypt::makeFileKey2(int encVersion, int encRevision, int keyLength, - GString *ownerKey, GString *userKey, - int permissions, GString *fileID, - GString *userPassword, Guchar *fileKey, - GBool encryptMetadata) { - Guchar *buf; - Guchar test[32]; - Guchar fState[256]; - Guchar tmpKey[16]; - Guchar fx, fy; - int len, i, j; - GBool ok; - - - // check whether we have non-zero keyLength - if ( keyLength < 5 || keyLength > 16 ) { - return gFalse; - } - - // generate file key - buf = (Guchar *)gmalloc(72 + 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()); - len = 68 + fileID->getLength(); - if (!encryptMetadata) { - buf[len++] = 0xff; - buf[len++] = 0xff; - buf[len++] = 0xff; - buf[len++] = 0xff; - } - md5(buf, len, fileKey); - if (encRevision == 3) { - for (i = 0; i < 50; ++i) { - md5(fileKey, keyLength, fileKey); - } - } - - // test user password - if (encRevision == 2) { - rc4InitKey(fileKey, keyLength, fState); - fx = fy = 0; - for (i = 0; i < 32; ++i) { - test[i] = rc4DecryptByte(fState, &fx, &fy, userKey->getChar(i)); - } - ok = memcmp(test, passwordPad, 32) == 0; - } else if (encRevision == 3) { - memcpy(test, userKey->getCString(), 32); - for (i = 19; i >= 0; --i) { - for (j = 0; j < keyLength; ++j) { - tmpKey[j] = fileKey[j] ^ i; - } - rc4InitKey(tmpKey, keyLength, fState); - fx = fy = 0; - for (j = 0; j < 32; ++j) { - test[j] = rc4DecryptByte(fState, &fx, &fy, test[j]); - } - } - memcpy(buf, passwordPad, 32); - memcpy(buf + 32, fileID->getCString(), fileID->getLength()); - md5(buf, 32 + fileID->getLength(), buf); - ok = memcmp(test, buf, 16) == 0; - } else { - ok = gFalse; - } - - 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 -//------------------------------------------------------------------------ - -// this works around a bug in older Sun compilers -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] = (Guchar)(a & 0xff); - digest[1] = (Guchar)((a >>= 8) & 0xff); - digest[2] = (Guchar)((a >>= 8) & 0xff); - digest[3] = (Guchar)((a >>= 8) & 0xff); - digest[4] = (Guchar)(b & 0xff); - digest[5] = (Guchar)((b >>= 8) & 0xff); - digest[6] = (Guchar)((b >>= 8) & 0xff); - digest[7] = (Guchar)((b >>= 8) & 0xff); - digest[8] = (Guchar)(c & 0xff); - digest[9] = (Guchar)((c >>= 8) & 0xff); - digest[10] = (Guchar)((c >>= 8) & 0xff); - digest[11] = (Guchar)((c >>= 8) & 0xff); - digest[12] = (Guchar)(d & 0xff); - digest[13] = (Guchar)((d >>= 8) & 0xff); - digest[14] = (Guchar)((d >>= 8) & 0xff); - digest[15] = (Guchar)((d >>= 8) & 0xff); -} diff --git a/pdftops/Decrypt.h b/pdftops/Decrypt.h deleted file mode 100644 index 790e92cc3..000000000 --- a/pdftops/Decrypt.h +++ /dev/null @@ -1,63 +0,0 @@ -//======================================================================== -// -// Decrypt.h -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef DECRYPT_H -#define DECRYPT_H - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "gtypes.h" -#include "GString.h" - -//------------------------------------------------------------------------ -// Decrypt -//------------------------------------------------------------------------ - -class Decrypt { -public: - - // Initialize the decryptor object. - Decrypt(Guchar *fileKey, int keyLength, int objNum, int objGen); - - // Reset decryption. - void reset(); - - // Decrypt one byte. - Guchar decryptByte(Guchar c); - - // Generate a file key. The <fileKey> buffer must have space for at - // least 16 bytes. Checks <ownerPassword> and then <userPassword> - // and returns true if either is correct. Sets <ownerPasswordOk> if - // the owner password was correct. Either or both of the passwords - // may be NULL, which is treated as an empty string. - static GBool makeFileKey(int encVersion, int encRevision, int keyLength, - GString *ownerKey, GString *userKey, - int permissions, GString *fileID, - GString *ownerPassword, GString *userPassword, - Guchar *fileKey, GBool encryptMetadata, - GBool *ownerPasswordOk); - -private: - - static GBool makeFileKey2(int encVersion, int encRevision, int keyLength, - GString *ownerKey, GString *userKey, - int permissions, GString *fileID, - GString *userPassword, Guchar *fileKey, - GBool encryptMetadata); - - int objKeyLength; - Guchar objKey[21]; - Guchar state[256]; - Guchar x, y; -}; - -#endif diff --git a/pdftops/Dependencies b/pdftops/Dependencies deleted file mode 100644 index eb9510e8f..000000000 --- a/pdftops/Dependencies +++ /dev/null @@ -1,110 +0,0 @@ -# DO NOT DELETE THIS LINE -- make depend depends on it. -pdftops.o: pdftops.cxx ../cups/string.h config.h ../cups/i18n.h \ - ../cups/transcode.h ../cups/language.h ../cups/array.h parseargs.h \ - gtypes.h GString.h gmem.h Object.h Array.h Dict.h Stream.h XRef.h \ - Catalog.h Page.h PDFDoc.h PSOutputDev.h config.h GlobalParams.h \ - CharTypes.h OutputDev.h Error.h ../cups/cups.h ../cups/ipp.h \ - ../cups/http.h ../cups/ppd.h ../cups/file.h -Annot.o: Annot.cxx config.h gmem.h Object.h gtypes.h GString.h Array.h \ - Dict.h Stream.h Catalog.h Gfx.h Lexer.h Annot.h -Array.o: Array.cxx config.h gmem.h Object.h gtypes.h GString.h Array.h \ - Dict.h Stream.h -BuiltinFont.o: BuiltinFont.cxx config.h gmem.h FontEncodingTables.h \ - BuiltinFont.h gtypes.h -BuiltinFontTables.o: BuiltinFontTables.cxx config.h FontEncodingTables.h \ - BuiltinFontTables.h BuiltinFont.h gtypes.h -Catalog.o: Catalog.cxx config.h gmem.h Object.h gtypes.h GString.h \ - Array.h Dict.h Stream.h XRef.h Page.h Error.h config.h Link.h Catalog.h -CharCodeToUnicode.o: CharCodeToUnicode.cxx config.h gmem.h gfile.h \ - gtypes.h GString.h Error.h config.h GlobalParams.h CharTypes.h \ - PSTokenizer.h CharCodeToUnicode.h -CMap.o: CMap.cxx config.h gmem.h gfile.h gtypes.h GString.h Error.h \ - config.h GlobalParams.h CharTypes.h PSTokenizer.h CMap.h -Decrypt.o: Decrypt.cxx config.h gmem.h Decrypt.h gtypes.h GString.h -Dict.o: Dict.cxx config.h gmem.h Object.h gtypes.h GString.h Array.h \ - Dict.h Stream.h XRef.h -Error.o: Error.cxx config.h GlobalParams.h gtypes.h CharTypes.h Error.h \ - config.h -FoFiBase.o: FoFiBase.cxx config.h gmem.h FoFiBase.h gtypes.h -FoFiEncodings.o: FoFiEncodings.cxx config.h FoFiEncodings.h gtypes.h -FoFiTrueType.o: FoFiTrueType.cxx config.h gtypes.h gmem.h GString.h \ - GHash.h FoFiTrueType.h FoFiBase.h -FoFiType1C.o: FoFiType1C.cxx config.h gmem.h GString.h FoFiEncodings.h \ - gtypes.h FoFiType1C.h FoFiBase.h -FoFiType1.o: FoFiType1.cxx config.h gmem.h FoFiEncodings.h gtypes.h \ - FoFiType1.h FoFiBase.h -FontEncodingTables.o: FontEncodingTables.cxx config.h \ - FontEncodingTables.h -Function.o: Function.cxx config.h gmem.h Object.h gtypes.h GString.h \ - Array.h Dict.h Stream.h Error.h config.h Function.h -gfile.o: gfile.cxx config.h GString.h gfile.h gtypes.h -Gfx.o: Gfx.cxx config.h gmem.h GlobalParams.h gtypes.h CharTypes.h \ - Object.h GString.h Array.h Dict.h Stream.h Lexer.h Parser.h GfxFont.h \ - GfxState.h Function.h OutputDev.h Page.h Error.h config.h Gfx.h -GfxFont.o: GfxFont.cxx config.h gmem.h Error.h config.h Object.h gtypes.h \ - GString.h Array.h Dict.h Stream.h GlobalParams.h CharTypes.h CMap.h \ - CharCodeToUnicode.h FontEncodingTables.h BuiltinFontTables.h \ - BuiltinFont.h FoFiType1.h FoFiBase.h FoFiType1C.h FoFiTrueType.h \ - GfxFont.h -GfxState.o: GfxState.cxx config.h gmem.h Error.h config.h Object.h \ - gtypes.h GString.h Array.h Dict.h Stream.h Page.h GfxState.h Function.h -GHash.o: GHash.cxx config.h gmem.h GString.h GHash.h gtypes.h -GList.o: GList.cxx config.h gmem.h GList.h gtypes.h -GlobalParams.o: GlobalParams.cxx config.h gmem.h GString.h GList.h \ - gtypes.h GHash.h gfile.h Error.h config.h NameToCharCode.h CharTypes.h \ - CharCodeToUnicode.h UnicodeMap.h CMap.h BuiltinFontTables.h \ - BuiltinFont.h FontEncodingTables.h GlobalParams.h NameToUnicodeTable.h \ - UnicodeMapTables.h UTF8.h -gmempp.o: gmempp.cxx config.h gmem.h -GString.o: GString.cxx config.h gtypes.h GString.h -JArithmeticDecoder.o: JArithmeticDecoder.cxx config.h Object.h gtypes.h \ - gmem.h GString.h Array.h Dict.h Stream.h JArithmeticDecoder.h -JBIG2Stream.o: JBIG2Stream.cxx config.h GList.h gtypes.h Error.h config.h \ - JArithmeticDecoder.h JBIG2Stream.h Object.h gmem.h GString.h Array.h \ - Dict.h Stream.h Stream-CCITT.h -JPXStream.o: JPXStream.cxx config.h gmem.h Error.h config.h \ - JArithmeticDecoder.h gtypes.h JPXStream.h Object.h GString.h Array.h \ - Dict.h Stream.h -Lexer.o: Lexer.cxx config.h Lexer.h Object.h gtypes.h gmem.h GString.h \ - Array.h Dict.h Stream.h Error.h config.h -Link.o: Link.cxx config.h gmem.h GString.h Error.h config.h Object.h \ - gtypes.h Array.h Dict.h Stream.h Link.h -NameToCharCode.o: NameToCharCode.cxx config.h gmem.h NameToCharCode.h \ - CharTypes.h -Object.o: Object.cxx config.h Object.h gtypes.h gmem.h GString.h Array.h \ - Dict.h Stream.h Error.h config.h XRef.h -Outline.o: Outline.cxx config.h gmem.h GString.h GList.h gtypes.h Link.h \ - Object.h Array.h Dict.h Stream.h PDFDocEncoding.h CharTypes.h Outline.h -OutputDev.o: OutputDev.cxx config.h Object.h gtypes.h gmem.h GString.h \ - Array.h Dict.h Stream.h GfxState.h Function.h OutputDev.h CharTypes.h -Page.o: Page.cxx config.h GlobalParams.h gtypes.h CharTypes.h Object.h \ - gmem.h GString.h Array.h Dict.h Stream.h XRef.h Link.h OutputDev.h \ - Gfx.h GfxState.h Function.h Annot.h Error.h config.h Page.h -Parser.o: Parser.cxx config.h Object.h gtypes.h gmem.h GString.h Array.h \ - Dict.h Stream.h Parser.h Lexer.h XRef.h Error.h config.h Decrypt.h -PDFDoc.o: PDFDoc.cxx config.h GString.h config.h GlobalParams.h gtypes.h \ - CharTypes.h Page.h Object.h gmem.h Array.h Dict.h Stream.h Catalog.h \ - XRef.h Link.h OutputDev.h Error.h ErrorCodes.h Lexer.h Parser.h \ - SecurityHandler.h Outline.h PDFDoc.h -PDFDocEncoding.o: PDFDocEncoding.cxx PDFDocEncoding.h CharTypes.h -PSOutputDev.o: PSOutputDev.cxx config.h GString.h GList.h gtypes.h \ - config.h GlobalParams.h CharTypes.h Object.h gmem.h Array.h Dict.h \ - Stream.h Error.h Function.h Gfx.h GfxState.h GfxFont.h UnicodeMap.h \ - FoFiType1C.h FoFiBase.h FoFiTrueType.h Catalog.h Page.h Annot.h XRef.h \ - PSOutputDev.h OutputDev.h -PSTokenizer.o: PSTokenizer.cxx config.h PSTokenizer.h gtypes.h -SecurityHandler.o: SecurityHandler.cxx config.h GString.h PDFDoc.h XRef.h \ - gtypes.h Object.h gmem.h Array.h Dict.h Stream.h Catalog.h Page.h \ - Decrypt.h Error.h config.h GlobalParams.h CharTypes.h SecurityHandler.h -Stream.o: Stream.cxx config.h gmem.h gfile.h gtypes.h config.h Error.h \ - Object.h GString.h Array.h Dict.h Stream.h Lexer.h Decrypt.h GfxState.h \ - Function.h JBIG2Stream.h JPXStream.h Stream-CCITT.h -UnicodeMap.o: UnicodeMap.cxx config.h gmem.h gfile.h gtypes.h GString.h \ - GList.h Error.h config.h GlobalParams.h CharTypes.h UnicodeMap.h -UnicodeTypeTable.o: UnicodeTypeTable.cxx CharTypes.h UnicodeTypeTable.h \ - gtypes.h -XpdfPluginAPI.o: XpdfPluginAPI.cxx config.h -XRef.o: XRef.cxx config.h gmem.h Object.h gtypes.h GString.h Array.h \ - Dict.h Stream.h Lexer.h Parser.h Error.h config.h ErrorCodes.h XRef.h -gmem.o: gmem.c config.h gmem.h -parseargs.o: parseargs.c parseargs.h gtypes.h diff --git a/pdftops/Dict.cxx b/pdftops/Dict.cxx deleted file mode 100644 index 371ecbffc..000000000 --- a/pdftops/Dict.cxx +++ /dev/null @@ -1,95 +0,0 @@ -//======================================================================== -// -// Dict.cc -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include <stddef.h> -#include <string.h> -#include "gmem.h" -#include "Object.h" -#include "XRef.h" -#include "Dict.h" - -//------------------------------------------------------------------------ -// Dict -//------------------------------------------------------------------------ - -Dict::Dict(XRef *xrefA) { - xref = xrefA; - 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 == size) { - if (length == 0) { - size = 8; - } else { - size *= 2; - } - entries = (DictEntry *)greallocn(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(xref, 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(xref, obj); -} - -Object *Dict::getValNF(int i, Object *obj) { - return entries[i].val.copy(obj); -} diff --git a/pdftops/Dict.h b/pdftops/Dict.h deleted file mode 100644 index f63c98e00..000000000 --- a/pdftops/Dict.h +++ /dev/null @@ -1,77 +0,0 @@ -//======================================================================== -// -// Dict.h -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef DICT_H -#define DICT_H - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "Object.h" - -//------------------------------------------------------------------------ -// Dict -//------------------------------------------------------------------------ - -struct DictEntry { - char *key; - Object val; -}; - -class Dict { -public: - - // Constructor. - Dict(XRef *xrefA); - - // 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 <key> 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); - - // Set the xref pointer. This is only used in one special case: the - // trailer dictionary, which is read before the xref table is - // parsed. - void setXRef(XRef *xrefA) { xref = xrefA; } - -private: - - XRef *xref; // the xref table for this PDF file - DictEntry *entries; // array of entries - int size; // size of <entries> 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 deleted file mode 100644 index 03d29e095..000000000 --- a/pdftops/Error.cxx +++ /dev/null @@ -1,38 +0,0 @@ -//======================================================================== -// -// Error.cc -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include <stdio.h> -#include <stddef.h> -#include <stdarg.h> -#include "GlobalParams.h" -#include "Error.h" - -void CDECL error(int pos, char *msg, ...) { - va_list args; - - // NB: this can be called before the globalParams object is created - if (globalParams && globalParams->getErrQuiet()) { - return; - } - if (pos >= 0) { - fprintf(stderr, "Error (%d): ", pos); - } else { - fprintf(stderr, "Error: "); - } - va_start(args, msg); - vfprintf(stderr, msg, args); - va_end(args); - fprintf(stderr, "\n"); - fflush(stderr); -} diff --git a/pdftops/Error.h b/pdftops/Error.h deleted file mode 100644 index cc51e5feb..000000000 --- a/pdftops/Error.h +++ /dev/null @@ -1,23 +0,0 @@ -//======================================================================== -// -// Error.h -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef ERROR_H -#define ERROR_H - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include <stdio.h> -#include "config.h" - -extern void CDECL error(int pos, char *msg, ...); - -#endif diff --git a/pdftops/ErrorCodes.h b/pdftops/ErrorCodes.h deleted file mode 100644 index b28528df5..000000000 --- a/pdftops/ErrorCodes.h +++ /dev/null @@ -1,36 +0,0 @@ -//======================================================================== -// -// ErrorCodes.h -// -// Copyright 2002-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef ERRORCODES_H -#define ERRORCODES_H - -#define errNone 0 // no error - -#define errOpenFile 1 // couldn't open the PDF file - -#define errBadCatalog 2 // couldn't read the page catalog - -#define errDamaged 3 // PDF file was damaged and couldn't be - // repaired - -#define errEncrypted 4 // file was encrypted and password was - // incorrect or not supplied - -#define errHighlightFile 5 // nonexistent or invalid highlight file - -#define errBadPrinter 6 // invalid printer - -#define errPrinting 7 // error during printing - -#define errPermission 8 // PDF file doesn't allow that operation - -#define errBadPageNum 9 // invalid page number - -#define errFileIO 10 // file I/O error - -#endif diff --git a/pdftops/FoFiBase.cxx b/pdftops/FoFiBase.cxx deleted file mode 100644 index 0cabe2455..000000000 --- a/pdftops/FoFiBase.cxx +++ /dev/null @@ -1,156 +0,0 @@ -//======================================================================== -// -// FoFiBase.cc -// -// Copyright 1999-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include <stdio.h> -#include "gmem.h" -#include "FoFiBase.h" - -//------------------------------------------------------------------------ -// FoFiBase -//------------------------------------------------------------------------ - -FoFiBase::FoFiBase(char *fileA, int lenA, GBool freeFileDataA) { - fileData = file = (Guchar *)fileA; - len = lenA; - freeFileData = freeFileDataA; -} - -FoFiBase::~FoFiBase() { - if (freeFileData) { - gfree(fileData); - } -} - -char *FoFiBase::readFile(char *fileName, int *fileLen) { - FILE *f; - char *buf; - int n; - - if (!(f = fopen(fileName, "rb"))) { - return NULL; - } - fseek(f, 0, SEEK_END); - n = (int)ftell(f); - fseek(f, 0, SEEK_SET); - buf = (char *)gmalloc(n); - if ((int)fread(buf, 1, n, f) != n) { - gfree(buf); - fclose(f); - return NULL; - } - fclose(f); - *fileLen = n; - return buf; -} - -int FoFiBase::getS8(int pos, GBool *ok) { - int x; - - if (pos < 0 || pos >= len) { - *ok = gFalse; - return 0; - } - x = file[pos]; - if (x & 0x80) { - x |= ~0xff; - } - return x; -} - -int FoFiBase::getU8(int pos, GBool *ok) { - if (pos < 0 || pos >= len) { - *ok = gFalse; - return 0; - } - return file[pos]; -} - -int FoFiBase::getS16BE(int pos, GBool *ok) { - int x; - - if (pos < 0 || pos+1 >= len) { - *ok = gFalse; - return 0; - } - x = file[pos]; - x = (x << 8) + file[pos+1]; - if (x & 0x8000) { - x |= ~0xffff; - } - return x; -} - -int FoFiBase::getU16BE(int pos, GBool *ok) { - int x; - - if (pos < 0 || pos+1 >= len) { - *ok = gFalse; - return 0; - } - x = file[pos]; - x = (x << 8) + file[pos+1]; - return x; -} - -int FoFiBase::getS32BE(int pos, GBool *ok) { - int x; - - if (pos < 0 || pos+3 >= len) { - *ok = gFalse; - return 0; - } - x = file[pos]; - x = (x << 8) + file[pos+1]; - x = (x << 8) + file[pos+2]; - x = (x << 8) + file[pos+3]; - if (x & 0x80000000) { - x |= ~0xffffffff; - } - return x; -} - -Guint FoFiBase::getU32BE(int pos, GBool *ok) { - Guint x; - - if (pos < 0 || pos+3 >= len) { - *ok = gFalse; - return 0; - } - x = file[pos]; - x = (x << 8) + file[pos+1]; - x = (x << 8) + file[pos+2]; - x = (x << 8) + file[pos+3]; - return x; -} - -Guint FoFiBase::getUVarBE(int pos, int size, GBool *ok) { - Guint x; - int i; - - if (pos < 0 || pos + size > len) { - *ok = gFalse; - return 0; - } - x = 0; - for (i = 0; i < size; ++i) { - x = (x << 8) + file[pos + i]; - } - return x; -} - -GBool FoFiBase::checkRegion(int pos, int size) { - return pos >= 0 && - pos + size >= pos && - pos + size <= len; -} diff --git a/pdftops/FoFiBase.h b/pdftops/FoFiBase.h deleted file mode 100644 index 74270270d..000000000 --- a/pdftops/FoFiBase.h +++ /dev/null @@ -1,57 +0,0 @@ -//======================================================================== -// -// FoFiBase.h -// -// Copyright 1999-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef FOFIBASE_H -#define FOFIBASE_H - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "gtypes.h" - -//------------------------------------------------------------------------ - -typedef void (*FoFiOutputFunc)(void *stream, char *data, int len); - -//------------------------------------------------------------------------ -// FoFiBase -//------------------------------------------------------------------------ - -class FoFiBase { -public: - - virtual ~FoFiBase(); - -protected: - - FoFiBase(char *fileA, int lenA, GBool freeFileDataA); - static char *readFile(char *fileName, int *fileLen); - - // S = signed / U = unsigned - // 8/16/32/Var = word length, in bytes - // BE = big endian - int getS8(int pos, GBool *ok); - int getU8(int pos, GBool *ok); - int getS16BE(int pos, GBool *ok); - int getU16BE(int pos, GBool *ok); - int getS32BE(int pos, GBool *ok); - Guint getU32BE(int pos, GBool *ok); - Guint getUVarBE(int pos, int size, GBool *ok); - - GBool checkRegion(int pos, int size); - - Guchar *fileData; - Guchar *file; - int len; - GBool freeFileData; -}; - -#endif diff --git a/pdftops/FoFiEncodings.cxx b/pdftops/FoFiEncodings.cxx deleted file mode 100644 index 946b56c19..000000000 --- a/pdftops/FoFiEncodings.cxx +++ /dev/null @@ -1,994 +0,0 @@ -//======================================================================== -// -// FoFiEncodings.cc -// -// Copyright 1999-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include <stdlib.h> -#include "FoFiEncodings.h" - -//------------------------------------------------------------------------ -// Type 1 and 1C font data -//------------------------------------------------------------------------ - -char *fofiType1StandardEncoding[256] = { - 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 -}; - -char *fofiType1ExpertEncoding[256] = { - 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" -}; - -//------------------------------------------------------------------------ -// Type 1C font data -//------------------------------------------------------------------------ - -char *fofiType1CStdStrings[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" -}; - -Gushort fofiType1CISOAdobeCharset[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 -}; - -Gushort fofiType1CExpertCharset[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 -}; - -Gushort fofiType1CExpertSubsetCharset[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 -}; diff --git a/pdftops/FoFiEncodings.h b/pdftops/FoFiEncodings.h deleted file mode 100644 index 804ed28a1..000000000 --- a/pdftops/FoFiEncodings.h +++ /dev/null @@ -1,36 +0,0 @@ -//======================================================================== -// -// FoFiEncodings.h -// -// Copyright 1999-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef FOFIENCODINGS_H -#define FOFIENCODINGS_H - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "gtypes.h" - -//------------------------------------------------------------------------ -// Type 1 and 1C font data -//------------------------------------------------------------------------ - -extern char *fofiType1StandardEncoding[256]; -extern char *fofiType1ExpertEncoding[256]; - -//------------------------------------------------------------------------ -// Type 1C font data -//------------------------------------------------------------------------ - -extern char *fofiType1CStdStrings[391]; -extern Gushort fofiType1CISOAdobeCharset[229]; -extern Gushort fofiType1CExpertCharset[166]; -extern Gushort fofiType1CExpertSubsetCharset[87]; - -#endif diff --git a/pdftops/FoFiTrueType.cxx b/pdftops/FoFiTrueType.cxx deleted file mode 100644 index 64195ab04..000000000 --- a/pdftops/FoFiTrueType.cxx +++ /dev/null @@ -1,1753 +0,0 @@ -//======================================================================== -// -// FoFiTrueType.cc -// -// Copyright 1999-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include <stdlib.h> -#include <string.h> -#include "gtypes.h" -#include "gmem.h" -#include "GString.h" -#include "GHash.h" -#include "FoFiTrueType.h" - -// -// Terminology -// ----------- -// -// character code = number used as an element of a text string -// -// character name = glyph name = name for a particular glyph within a -// font -// -// glyph index = GID = position (within some internal table in the font) -// where the instructions to draw a particular glyph are -// stored -// -// Type 1 fonts -// ------------ -// -// Type 1 fonts contain: -// -// Encoding: array of glyph names, maps char codes to glyph names -// -// Encoding[charCode] = charName -// -// CharStrings: dictionary of instructions, keyed by character names, -// maps character name to glyph data -// -// CharStrings[charName] = glyphData -// -// TrueType fonts -// -------------- -// -// TrueType fonts contain: -// -// 'cmap' table: mapping from character code to glyph index; there may -// be multiple cmaps in a TrueType font -// -// cmap[charCode] = gid -// -// 'post' table: mapping from glyph index to glyph name -// -// post[gid] = glyphName -// -// Type 42 fonts -// ------------- -// -// Type 42 fonts contain: -// -// Encoding: array of glyph names, maps char codes to glyph names -// -// Encoding[charCode] = charName -// -// CharStrings: dictionary of glyph indexes, keyed by character names, -// maps character name to glyph index -// -// CharStrings[charName] = gid -// - -//------------------------------------------------------------------------ - -#define ttcfTag 0x74746366 - -//------------------------------------------------------------------------ - -struct TrueTypeTable { - Guint tag; - Guint checksum; - int offset; - int origOffset; - int len; -}; - -struct TrueTypeCmap { - int platform; - int encoding; - int offset; - int len; - int fmt; -}; - -struct TrueTypeLoca { - int idx; - int origOffset; - int newOffset; - int len; -}; - -#define cmapTag 0x636d6170 -#define glyfTag 0x676c7966 -#define headTag 0x68656164 -#define locaTag 0x6c6f6361 -#define nameTag 0x6e616d65 -#define postTag 0x706f7374 - -static int cmpTrueTypeLocaOffset(const void *p1, const void *p2) { - TrueTypeLoca *loca1 = (TrueTypeLoca *)p1; - TrueTypeLoca *loca2 = (TrueTypeLoca *)p2; - - if (loca1->origOffset == loca2->origOffset) { - return loca1->idx - loca2->idx; - } - return loca1->origOffset - loca2->origOffset; -} - -static int cmpTrueTypeLocaIdx(const void *p1, const void *p2) { - TrueTypeLoca *loca1 = (TrueTypeLoca *)p1; - TrueTypeLoca *loca2 = (TrueTypeLoca *)p2; - - return loca1->idx - loca2->idx; -} - -static int cmpTrueTypeTableTag(const void *p1, const void *p2) { - TrueTypeTable *tab1 = (TrueTypeTable *)p1; - TrueTypeTable *tab2 = (TrueTypeTable *)p2; - - return (int)tab1->tag - (int)tab2->tag; -} - -//------------------------------------------------------------------------ - -struct T42Table { - char *tag; // 4-byte tag - GBool required; // required by the TrueType spec? -}; - -// TrueType tables to be embedded in Type 42 fonts. -// NB: the table names must be in alphabetical order here. -#define nT42Tables 11 -static T42Table t42Tables[nT42Tables] = { - { "cvt ", gTrue }, - { "fpgm", gTrue }, - { "glyf", gTrue }, - { "head", gTrue }, - { "hhea", gTrue }, - { "hmtx", gTrue }, - { "loca", gTrue }, - { "maxp", gTrue }, - { "prep", gTrue }, - { "vhea", gFalse }, - { "vmtx", gFalse } -}; -#define t42HeadTable 3 -#define t42LocaTable 6 -#define t42GlyfTable 2 -#define t42VheaTable 9 -#define t42VmtxTable 10 - -//------------------------------------------------------------------------ - -// Glyph names in some arbitrary standard order that Apple uses for -// their TrueType fonts. -static char *macGlyphNames[258] = { - ".notdef", "null", "CR", "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", "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", "notequal", - "AE", "Oslash", "infinity", "plusminus", - "lessequal", "greaterequal", "yen", "mu1", - "partialdiff", "summation", "product", "pi", - "integral", "ordfeminine", "ordmasculine", "Ohm", - "ae", "oslash", "questiondown", "exclamdown", - "logicalnot", "radical", "florin", "approxequal", - "increment", "guillemotleft", "guillemotright", "ellipsis", - "nbspace", "Agrave", "Atilde", "Otilde", - "OE", "oe", "endash", "emdash", - "quotedblleft", "quotedblright", "quoteleft", "quoteright", - "divide", "lozenge", "ydieresis", "Ydieresis", - "fraction", "currency", "guilsinglleft", "guilsinglright", - "fi", "fl", "daggerdbl", "periodcentered", - "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex", - "Ecircumflex", "Aacute", "Edieresis", "Egrave", - "Iacute", "Icircumflex", "Idieresis", "Igrave", - "Oacute", "Ocircumflex", "applelogo", "Ograve", - "Uacute", "Ucircumflex", "Ugrave", "dotlessi", - "circumflex", "tilde", "overscore", "breve", - "dotaccent", "ring", "cedilla", "hungarumlaut", - "ogonek", "caron", "Lslash", "lslash", - "Scaron", "scaron", "Zcaron", "zcaron", - "brokenbar", "Eth", "eth", "Yacute", - "yacute", "Thorn", "thorn", "minus", - "multiply", "onesuperior", "twosuperior", "threesuperior", - "onehalf", "onequarter", "threequarters", "franc", - "Gbreve", "gbreve", "Idot", "Scedilla", - "scedilla", "Cacute", "cacute", "Ccaron", - "ccaron", "dmacron" -}; - -//------------------------------------------------------------------------ -// FoFiTrueType -//------------------------------------------------------------------------ - -FoFiTrueType *FoFiTrueType::make(char *fileA, int lenA) { - FoFiTrueType *ff; - - ff = new FoFiTrueType(fileA, lenA, gFalse); - if (!ff->parsedOk) { - delete ff; - return NULL; - } - return ff; -} - -FoFiTrueType *FoFiTrueType::load(char *fileName) { - FoFiTrueType *ff; - char *fileA; - int lenA; - - if (!(fileA = FoFiBase::readFile(fileName, &lenA))) { - return NULL; - } - ff = new FoFiTrueType(fileA, lenA, gTrue); - if (!ff->parsedOk) { - delete ff; - return NULL; - } - return ff; -} - -FoFiTrueType::FoFiTrueType(char *fileA, int lenA, GBool freeFileDataA): - FoFiBase(fileA, lenA, freeFileDataA) -{ - tables = NULL; - nTables = 0; - cmaps = NULL; - nCmaps = 0; - nameToGID = NULL; - parsedOk = gFalse; - - parse(); -} - -FoFiTrueType::~FoFiTrueType() { - gfree(tables); - gfree(cmaps); - if (nameToGID) { - delete nameToGID; - } -} - -int FoFiTrueType::getNumCmaps() { - return nCmaps; -} - -int FoFiTrueType::getCmapPlatform(int i) { - return cmaps[i].platform; -} - -int FoFiTrueType::getCmapEncoding(int i) { - return cmaps[i].encoding; -} - -int FoFiTrueType::findCmap(int platform, int encoding) { - int i; - - for (i = 0; i < nCmaps; ++i) { - if (cmaps[i].platform == platform && cmaps[i].encoding == encoding) { - return i; - } - } - return -1; -} - -Gushort FoFiTrueType::mapCodeToGID(int i, int c) { - Gushort gid; - int segCnt, segEnd, segStart, segDelta, segOffset; - int cmapFirst, cmapLen; - int pos, a, b, m; - GBool ok; - - if (i < 0 || i >= nCmaps) { - return 0; - } - ok = gTrue; - pos = cmaps[i].offset; - switch (cmaps[i].fmt) { - case 0: - if (c < 0 || c >= cmaps[i].len - 6) { - return 0; - } - gid = getU8(cmaps[i].offset + 6 + c, &ok); - break; - case 4: - segCnt = getU16BE(pos + 6, &ok) / 2; - a = -1; - b = segCnt - 1; - segEnd = getU16BE(pos + 14 + 2*b, &ok); - if (c > segEnd) { - // malformed font -- the TrueType spec requires the last segEnd - // to be 0xffff - return 0; - } - // invariant: seg[a].end < code <= seg[b].end - while (b - a > 1 && ok) { - m = (a + b) / 2; - segEnd = getU16BE(pos + 14 + 2*m, &ok); - if (segEnd < c) { - a = m; - } else { - b = m; - } - } - segStart = getU16BE(pos + 16 + 2*segCnt + 2*b, &ok); - segDelta = getU16BE(pos + 16 + 4*segCnt + 2*b, &ok); - segOffset = getU16BE(pos + 16 + 6*segCnt + 2*b, &ok); - if (c < segStart) { - return 0; - } - if (segOffset == 0) { - gid = (c + segDelta) & 0xffff; - } else { - gid = getU16BE(pos + 16 + 6*segCnt + 2*b + - segOffset + 2 * (c - segStart), &ok); - if (gid != 0) { - gid = (gid + segDelta) & 0xffff; - } - } - break; - case 6: - cmapFirst = getU16BE(pos + 6, &ok); - cmapLen = getU16BE(pos + 8, &ok); - if (c < cmapFirst || c >= cmapFirst + cmapLen) { - return 0; - } - gid = getU16BE(pos + 10 + 2 * (c - cmapFirst), &ok); - break; - default: - return 0; - } - if (!ok) { - return 0; - } - return gid; -} - -int FoFiTrueType::mapNameToGID(char *name) { - if (!nameToGID) { - return 0; - } - return nameToGID->lookupInt(name); -} - -int FoFiTrueType::getEmbeddingRights() { - int i, fsType; - GBool ok; - - if ((i = seekTable("OS/2")) < 0) { - return 4; - } - ok = gTrue; - fsType = getU16BE(tables[i].offset + 8, &ok); - if (!ok) { - return 4; - } - if (fsType & 0x0008) { - return 2; - } - if (fsType & 0x0004) { - return 1; - } - if (fsType & 0x0002) { - return 0; - } - return 3; -} - -void FoFiTrueType::convertToType42(char *psName, char **encoding, - Gushort *codeToGID, - FoFiOutputFunc outputFunc, - void *outputStream) { - char buf[512]; - GBool ok; - - // write the header - ok = gTrue; - sprintf(buf, "%%!PS-TrueTypeFont-%g\n", (double)getS32BE(0, &ok) / 65536.0); - (*outputFunc)(outputStream, buf, strlen(buf)); - - // begin the font dictionary - (*outputFunc)(outputStream, "10 dict begin\n", 14); - (*outputFunc)(outputStream, "/FontName /", 11); - (*outputFunc)(outputStream, psName, strlen(psName)); - (*outputFunc)(outputStream, " def\n", 5); - (*outputFunc)(outputStream, "/FontType 42 def\n", 17); - (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30); - sprintf(buf, "/FontBBox [%d %d %d %d] def\n", - bbox[0], bbox[1], bbox[2], bbox[3]); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, "/PaintType 0 def\n", 17); - - // write the guts of the dictionary - cvtEncoding(encoding, outputFunc, outputStream); - cvtCharStrings(encoding, codeToGID, outputFunc, outputStream); - cvtSfnts(outputFunc, outputStream, NULL, gFalse); - - // end the dictionary and define the font - (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40); -} - -void FoFiTrueType::convertToCIDType2(char *psName, - Gushort *cidMap, int nCIDs, - GBool needVerticalMetrics, - FoFiOutputFunc outputFunc, - void *outputStream) { - char buf[512]; - Gushort cid; - GBool ok; - int i, j, k; - - // write the header - ok = gTrue; - sprintf(buf, "%%!PS-TrueTypeFont-%g\n", (double)getS32BE(0, &ok) / 65536.0); - (*outputFunc)(outputStream, buf, strlen(buf)); - - // begin the font dictionary - (*outputFunc)(outputStream, "20 dict begin\n", 14); - (*outputFunc)(outputStream, "/CIDFontName /", 14); - (*outputFunc)(outputStream, psName, strlen(psName)); - (*outputFunc)(outputStream, " def\n", 5); - (*outputFunc)(outputStream, "/CIDFontType 2 def\n", 19); - (*outputFunc)(outputStream, "/FontType 42 def\n", 17); - (*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32); - (*outputFunc)(outputStream, " /Registry (Adobe) def\n", 24); - (*outputFunc)(outputStream, " /Ordering (Identity) def\n", 27); - (*outputFunc)(outputStream, " /Supplement 0 def\n", 20); - (*outputFunc)(outputStream, " end def\n", 10); - (*outputFunc)(outputStream, "/GDBytes 2 def\n", 15); - if (cidMap) { - sprintf(buf, "/CIDCount %d def\n", nCIDs); - (*outputFunc)(outputStream, buf, strlen(buf)); - if (nCIDs > 32767) { - (*outputFunc)(outputStream, "/CIDMap [", 9); - for (i = 0; i < nCIDs; i += 32768 - 16) { - (*outputFunc)(outputStream, "<\n", 2); - for (j = 0; j < 32768 - 16 && i+j < nCIDs; j += 16) { - (*outputFunc)(outputStream, " ", 2); - for (k = 0; k < 16 && i+j+k < nCIDs; ++k) { - cid = cidMap[i+j+k]; - sprintf(buf, "%02x%02x", (cid >> 8) & 0xff, cid & 0xff); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - (*outputFunc)(outputStream, "\n", 1); - } - (*outputFunc)(outputStream, " >", 3); - } - (*outputFunc)(outputStream, "\n", 1); - (*outputFunc)(outputStream, "] def\n", 6); - } else { - (*outputFunc)(outputStream, "/CIDMap <\n", 10); - for (i = 0; i < nCIDs; i += 16) { - (*outputFunc)(outputStream, " ", 2); - for (j = 0; j < 16 && i+j < nCIDs; ++j) { - cid = cidMap[i+j]; - sprintf(buf, "%02x%02x", (cid >> 8) & 0xff, cid & 0xff); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - (*outputFunc)(outputStream, "\n", 1); - } - (*outputFunc)(outputStream, "> def\n", 6); - } - } else { - // direct mapping - just fill the string(s) with s[i]=i - sprintf(buf, "/CIDCount %d def\n", nGlyphs); - (*outputFunc)(outputStream, buf, strlen(buf)); - if (nGlyphs > 32767) { - (*outputFunc)(outputStream, "/CIDMap [\n", 10); - for (i = 0; i < nGlyphs; i += 32767) { - j = nGlyphs - i < 32767 ? nGlyphs - i : 32767; - sprintf(buf, " %d string 0 1 %d {\n", 2 * j, j - 1); - (*outputFunc)(outputStream, buf, strlen(buf)); - sprintf(buf, " 2 copy dup 2 mul exch %d add -8 bitshift put\n", i); - (*outputFunc)(outputStream, buf, strlen(buf)); - sprintf(buf, " 1 index exch dup 2 mul 1 add exch %d add" - " 255 and put\n", i); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, " } for\n", 8); - } - (*outputFunc)(outputStream, "] def\n", 6); - } else { - sprintf(buf, "/CIDMap %d string\n", 2 * nGlyphs); - (*outputFunc)(outputStream, buf, strlen(buf)); - sprintf(buf, " 0 1 %d {\n", nGlyphs - 1); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, - " 2 copy dup 2 mul exch -8 bitshift put\n", 42); - (*outputFunc)(outputStream, - " 1 index exch dup 2 mul 1 add exch 255 and put\n", 50); - (*outputFunc)(outputStream, " } for\n", 8); - (*outputFunc)(outputStream, "def\n", 4); - } - } - (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30); - sprintf(buf, "/FontBBox [%d %d %d %d] def\n", - bbox[0], bbox[1], bbox[2], bbox[3]); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, "/PaintType 0 def\n", 17); - (*outputFunc)(outputStream, "/Encoding [] readonly def\n", 26); - (*outputFunc)(outputStream, "/CharStrings 1 dict dup begin\n", 30); - (*outputFunc)(outputStream, " /.notdef 0 def\n", 17); - (*outputFunc)(outputStream, " end readonly def\n", 19); - - // write the guts of the dictionary - cvtSfnts(outputFunc, outputStream, NULL, needVerticalMetrics); - - // end the dictionary and define the font - (*outputFunc)(outputStream, - "CIDFontName currentdict end /CIDFont defineresource pop\n", - 56); -} - -void FoFiTrueType::convertToType0(char *psName, Gushort *cidMap, int nCIDs, - GBool needVerticalMetrics, - FoFiOutputFunc outputFunc, - void *outputStream) { - char buf[512]; - GString *sfntsName; - int n, i, j; - - // write the Type 42 sfnts array - sfntsName = (new GString(psName))->append("_sfnts"); - cvtSfnts(outputFunc, outputStream, sfntsName, needVerticalMetrics); - delete sfntsName; - - // write the descendant Type 42 fonts - n = cidMap ? nCIDs : nGlyphs; - for (i = 0; i < n; i += 256) { - (*outputFunc)(outputStream, "10 dict begin\n", 14); - (*outputFunc)(outputStream, "/FontName /", 11); - (*outputFunc)(outputStream, psName, strlen(psName)); - sprintf(buf, "_%02x def\n", i >> 8); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, "/FontType 42 def\n", 17); - (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30); - sprintf(buf, "/FontBBox [%d %d %d %d] def\n", - bbox[0], bbox[1], bbox[2], bbox[3]); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, "/PaintType 0 def\n", 17); - (*outputFunc)(outputStream, "/sfnts ", 7); - (*outputFunc)(outputStream, psName, strlen(psName)); - (*outputFunc)(outputStream, "_sfnts def\n", 11); - (*outputFunc)(outputStream, "/Encoding 256 array\n", 20); - for (j = 0; j < 256 && i+j < n; ++j) { - sprintf(buf, "dup %d /c%02x put\n", j, j); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - (*outputFunc)(outputStream, "readonly def\n", 13); - (*outputFunc)(outputStream, "/CharStrings 257 dict dup begin\n", 32); - (*outputFunc)(outputStream, "/.notdef 0 def\n", 15); - for (j = 0; j < 256 && i+j < n; ++j) { - sprintf(buf, "/c%02x %d def\n", j, cidMap ? cidMap[i+j] : i+j); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - (*outputFunc)(outputStream, "end readonly def\n", 17); - (*outputFunc)(outputStream, - "FontName currentdict end definefont pop\n", 40); - } - - // write the Type 0 parent font - (*outputFunc)(outputStream, "16 dict begin\n", 14); - (*outputFunc)(outputStream, "/FontName /", 11); - (*outputFunc)(outputStream, psName, strlen(psName)); - (*outputFunc)(outputStream, " def\n", 5); - (*outputFunc)(outputStream, "/FontType 0 def\n", 16); - (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30); - (*outputFunc)(outputStream, "/FMapType 2 def\n", 16); - (*outputFunc)(outputStream, "/Encoding [\n", 12); - for (i = 0; i < n; i += 256) { - sprintf(buf, "%d\n", i >> 8); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - (*outputFunc)(outputStream, "] def\n", 6); - (*outputFunc)(outputStream, "/FDepVector [\n", 14); - for (i = 0; i < n; i += 256) { - (*outputFunc)(outputStream, "/", 1); - (*outputFunc)(outputStream, psName, strlen(psName)); - sprintf(buf, "_%02x findfont\n", i >> 8); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - (*outputFunc)(outputStream, "] def\n", 6); - (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40); -} - -void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc, - void *outputStream, char *name, - Gushort *codeToGID) { - // this substitute cmap table maps char codes 0000-ffff directly to - // glyphs 0000-ffff - static char cmapTab[36] = { - 0, 0, // table version number - 0, 1, // number of encoding tables - 0, 1, // platform ID - 0, 0, // encoding ID - 0, 0, 0, 12, // offset of subtable - 0, 4, // subtable format - 0, 24, // subtable length - 0, 0, // subtable version - 0, 2, // segment count * 2 - 0, 2, // 2 * 2 ^ floor(log2(segCount)) - 0, 0, // floor(log2(segCount)) - 0, 0, // 2*segCount - 2*2^floor(log2(segCount)) - (char)0xff, (char)0xff, // endCount[0] - 0, 0, // reserved - 0, 0, // startCount[0] - 0, 0, // idDelta[0] - 0, 0 // pad to a mulitple of four bytes - }; - static char nameTab[8] = { - 0, 0, // format - 0, 0, // number of name records - 0, 6, // offset to start of string storage - 0, 0 // pad to multiple of four bytes - }; - static char postTab[32] = { - 0, 1, 0, 0, // format - 0, 0, 0, 0, // italic angle - 0, 0, // underline position - 0, 0, // underline thickness - 0, 0, 0, 0, // fixed pitch - 0, 0, 0, 0, // min Type 42 memory - 0, 0, 0, 0, // max Type 42 memory - 0, 0, 0, 0, // min Type 1 memory - 0, 0, 0, 0 // max Type 1 memory - }; - GBool missingCmap, missingName, missingPost, unsortedLoca, badCmapLen; - int nZeroLengthTables; - TrueTypeLoca *locaTable; - TrueTypeTable *newTables; - char *newNameTab, *newCmapTab; - int nNewTables, cmapIdx, cmapLen, glyfLen, newNameLen, newCmapLen, next; - Guint locaChecksum, glyfChecksum, fileChecksum; - char *tableDir; - char locaBuf[4], checksumBuf[4]; - GBool ok; - Guint t; - int pos, i, j, k, n; - - // check for missing tables - missingCmap = (cmapIdx = seekTable("cmap")) < 0; - missingName = seekTable("name") < 0; - missingPost = seekTable("post") < 0; - - // read the loca table, check to see if it's sorted - locaTable = (TrueTypeLoca *)gmallocn(nGlyphs + 1, sizeof(TrueTypeLoca)); - unsortedLoca = gFalse; - i = seekTable("loca"); - pos = tables[i].offset; - ok = gTrue; - for (i = 0; i <= nGlyphs; ++i) { - if (locaFmt) { - locaTable[i].origOffset = (int)getU32BE(pos + i*4, &ok); - } else { - locaTable[i].origOffset = 2 * getU16BE(pos + i*2, &ok); - } - if (i > 0 && locaTable[i].origOffset < locaTable[i-1].origOffset) { - unsortedLoca = gTrue; - } - locaTable[i].idx = i; - } - - // check for zero-length tables - nZeroLengthTables = 0; - for (i = 0; i < nTables; ++i) { - if (tables[i].len == 0) { - ++nZeroLengthTables; - } - } - - // check for an incorrect cmap table length - badCmapLen = gFalse; - cmapLen = 0; // make gcc happy - if (!missingCmap) { - cmapLen = cmaps[0].offset + cmaps[0].len; - for (i = 1; i < nCmaps; ++i) { - if (cmaps[i].offset + cmaps[i].len > cmapLen) { - cmapLen = cmaps[i].offset + cmaps[i].len; - } - } - cmapLen -= tables[cmapIdx].offset; - if (cmapLen > tables[cmapIdx].len) { - badCmapLen = gTrue; - } - } - - // if nothing is broken, just write the TTF file as is - if (!missingCmap && !missingName && !missingPost && !unsortedLoca && - !badCmapLen && nZeroLengthTables == 0 && !name && !codeToGID) { - (*outputFunc)(outputStream, (char *)file, len); - goto done1; - } - - // sort the 'loca' table: some (non-compliant) fonts have - // out-of-order loca tables; in order to correctly handle the case - // where (compliant) fonts have empty entries in the middle of the - // table, cmpTrueTypeLocaOffset uses offset as its primary sort key, - // and idx as its secondary key (ensuring that adjacent entries with - // the same pos value remain in the same order) - glyfLen = 0; // make gcc happy - if (unsortedLoca) { - qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca), - &cmpTrueTypeLocaOffset); - for (i = 0; i < nGlyphs; ++i) { - locaTable[i].len = locaTable[i+1].origOffset - locaTable[i].origOffset; - } - locaTable[nGlyphs].len = 0; - qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca), - &cmpTrueTypeLocaIdx); - pos = 0; - for (i = 0; i <= nGlyphs; ++i) { - locaTable[i].newOffset = pos; - pos += locaTable[i].len; - if (pos & 3) { - pos += 4 - (pos & 3); - } - } - glyfLen = pos; - } - - // compute checksums for the loca and glyf tables - locaChecksum = glyfChecksum = 0; - if (unsortedLoca) { - if (locaFmt) { - for (j = 0; j <= nGlyphs; ++j) { - locaChecksum += locaTable[j].newOffset; - } - } else { - for (j = 0; j <= nGlyphs; j += 2) { - locaChecksum += locaTable[j].newOffset << 16; - if (j + 1 <= nGlyphs) { - locaChecksum += locaTable[j+1].newOffset; - } - } - } - pos = tables[seekTable("glyf")].offset; - for (j = 0; j < nGlyphs; ++j) { - n = locaTable[j].len; - if (n > 0) { - k = locaTable[j].origOffset; - if (checkRegion(pos + k, n)) { - glyfChecksum += computeTableChecksum(file + pos + k, n); - } - } - } - } - - // construct the new name table - if (name) { - n = strlen(name); - newNameLen = (6 + 4*12 + 2 * (3*n + 7) + 3) & ~3; - newNameTab = (char *)gmalloc(newNameLen); - memset(newNameTab, 0, newNameLen); - newNameTab[0] = 0; // format selector - newNameTab[1] = 0; - newNameTab[2] = 0; // number of name records - newNameTab[3] = 4; - newNameTab[4] = 0; // offset to start of string storage - newNameTab[5] = 6 + 4*12; - next = 0; - for (i = 0; i < 4; ++i) { - newNameTab[6 + i*12 + 0] = 0; // platform ID = Microsoft - newNameTab[6 + i*12 + 1] = 3; - newNameTab[6 + i*12 + 2] = 0; // encoding ID = Unicode - newNameTab[6 + i*12 + 3] = 1; - newNameTab[6 + i*12 + 4] = 0x04; // language ID = American English - newNameTab[6 + i*12 + 5] = 0x09; - newNameTab[6 + i*12 + 6] = 0; // name ID - newNameTab[6 + i*12 + 7] = i + 1; - newNameTab[6 + i*12 + 8] = i+1 == 2 ? 0 : ((2*n) >> 8); // string length - newNameTab[6 + i*12 + 9] = i+1 == 2 ? 14 : ((2*n) & 0xff); - newNameTab[6 + i*12 + 10] = next >> 8; // string offset - newNameTab[6 + i*12 + 11] = next & 0xff; - if (i+1 == 2) { - memcpy(newNameTab + 6 + 4*12 + next, "\0R\0e\0g\0u\0l\0a\0r", 14); - next += 14; - } else { - for (j = 0; j < n; ++j) { - newNameTab[6 + 4*12 + next + 2*j] = 0; - newNameTab[6 + 4*12 + next + 2*j + 1] = name[j]; - } - next += 2*n; - } - } - } else { - newNameLen = 0; - newNameTab = NULL; - } - - // construct the new cmap table - if (codeToGID) { - newCmapLen = 44 + 256 * 2; - newCmapTab = (char *)gmalloc(newCmapLen); - newCmapTab[0] = 0; // table version number = 0 - newCmapTab[1] = 0; - newCmapTab[2] = 0; // number of encoding tables = 1 - newCmapTab[3] = 1; - newCmapTab[4] = 0; // platform ID = Microsoft - newCmapTab[5] = 3; - newCmapTab[6] = 0; // encoding ID = Unicode - newCmapTab[7] = 1; - newCmapTab[8] = 0; // offset of subtable - newCmapTab[9] = 0; - newCmapTab[10] = 0; - newCmapTab[11] = 12; - newCmapTab[12] = 0; // subtable format = 4 - newCmapTab[13] = 4; - newCmapTab[14] = 0x02; // subtable length - newCmapTab[15] = 0x20; - newCmapTab[16] = 0; // subtable version = 0 - newCmapTab[17] = 0; - newCmapTab[18] = 0; // segment count * 2 - newCmapTab[19] = 4; - newCmapTab[20] = 0; // 2 * 2 ^ floor(log2(segCount)) - newCmapTab[21] = 4; - newCmapTab[22] = 0; // floor(log2(segCount)) - newCmapTab[23] = 1; - newCmapTab[24] = 0; // 2*segCount - 2*2^floor(log2(segCount)) - newCmapTab[25] = 0; - newCmapTab[26] = 0x00; // endCount[0] - newCmapTab[27] = (char)0xff; - newCmapTab[28] = (char)0xff; // endCount[1] - newCmapTab[29] = (char)0xff; - newCmapTab[30] = 0; // reserved - newCmapTab[31] = 0; - newCmapTab[32] = 0x00; // startCount[0] - newCmapTab[33] = 0x00; - newCmapTab[34] = (char)0xff; // startCount[1] - newCmapTab[35] = (char)0xff; - newCmapTab[36] = 0; // idDelta[0] - newCmapTab[37] = 0; - newCmapTab[38] = 0; // idDelta[1] - newCmapTab[39] = 1; - newCmapTab[40] = 0; // idRangeOffset[0] - newCmapTab[41] = 4; - newCmapTab[42] = 0; // idRangeOffset[1] - newCmapTab[43] = 0; - for (i = 0; i < 256; ++i) { - newCmapTab[44 + 2*i] = codeToGID[i] >> 8; - newCmapTab[44 + 2*i + 1] = codeToGID[i] & 0xff; - } - } else { - newCmapLen = 0; - newCmapTab = NULL; - } - - // construct the new table directory: - // - keep all original tables with non-zero length - // - fix the cmap table's length, if necessary - // - add missing tables - // - sort the table by tag - // - compute new table positions, including 4-byte alignment - // - (re)compute table checksums - nNewTables = nTables - nZeroLengthTables + - (missingCmap ? 1 : 0) + (missingName ? 1 : 0) + - (missingPost ? 1 : 0); - newTables = (TrueTypeTable *)gmallocn(nNewTables, sizeof(TrueTypeTable)); - j = 0; - for (i = 0; i < nTables; ++i) { - if (tables[i].len > 0) { - newTables[j] = tables[i]; - newTables[j].origOffset = tables[i].offset; - if (checkRegion(tables[i].offset, newTables[i].len)) { - newTables[j].checksum = - computeTableChecksum(file + tables[i].offset, tables[i].len); - if (tables[i].tag == headTag) { - // don't include the file checksum - newTables[j].checksum -= getU32BE(tables[i].offset + 8, &ok); - } - } - if (newTables[j].tag == cmapTag && codeToGID) { - newTables[j].len = newCmapLen; - newTables[j].checksum = computeTableChecksum((Guchar *)newCmapTab, - newCmapLen); - } else if (newTables[j].tag == cmapTag && badCmapLen) { - newTables[j].len = cmapLen; - } else if (newTables[j].tag == locaTag && unsortedLoca) { - newTables[j].len = (nGlyphs + 1) * (locaFmt ? 4 : 2); - newTables[j].checksum = locaChecksum; - } else if (newTables[j].tag == glyfTag && unsortedLoca) { - newTables[j].len = glyfLen; - newTables[j].checksum = glyfChecksum; - } else if (newTables[j].tag == nameTag && name) { - newTables[j].len = newNameLen; - newTables[j].checksum = computeTableChecksum((Guchar *)newNameTab, - newNameLen); - } - ++j; - } - } - if (missingCmap) { - newTables[j].tag = cmapTag; - if (codeToGID) { - newTables[j].checksum = computeTableChecksum((Guchar *)newCmapTab, - newCmapLen); - newTables[j].len = newCmapLen; - } else { - newTables[j].checksum = computeTableChecksum((Guchar *)cmapTab, - sizeof(cmapTab)); - newTables[j].len = sizeof(cmapTab); - } - ++j; - } - if (missingName) { - newTables[j].tag = nameTag; - if (name) { - newTables[j].checksum = computeTableChecksum((Guchar *)newNameTab, - newNameLen); - newTables[j].len = newNameLen; - } else { - newTables[j].checksum = computeTableChecksum((Guchar *)nameTab, - sizeof(nameTab)); - newTables[j].len = sizeof(nameTab); - } - ++j; - } - if (missingPost) { - newTables[j].tag = postTag; - newTables[j].checksum = computeTableChecksum((Guchar *)postTab, - sizeof(postTab)); - newTables[j].len = sizeof(postTab); - ++j; - } - qsort(newTables, nNewTables, sizeof(TrueTypeTable), - &cmpTrueTypeTableTag); - pos = 12 + nNewTables * 16; - for (i = 0; i < nNewTables; ++i) { - newTables[i].offset = pos; - pos += newTables[i].len; - if (pos & 3) { - pos += 4 - (pos & 3); - } - } - - // write the table directory - tableDir = (char *)gmalloc(12 + nNewTables * 16); - tableDir[0] = 0x00; // sfnt version - tableDir[1] = 0x01; - tableDir[2] = 0x00; - tableDir[3] = 0x00; - tableDir[4] = (char)((nNewTables >> 8) & 0xff); // numTables - tableDir[5] = (char)(nNewTables & 0xff); - for (i = -1, t = (Guint)nNewTables; t; ++i, t >>= 1) ; - t = 1 << (4 + i); - tableDir[6] = (char)((t >> 8) & 0xff); // searchRange - tableDir[7] = (char)(t & 0xff); - tableDir[8] = (char)((i >> 8) & 0xff); // entrySelector - tableDir[9] = (char)(i & 0xff); - t = nNewTables * 16 - t; - tableDir[10] = (char)((t >> 8) & 0xff); // rangeShift - tableDir[11] = (char)(t & 0xff); - pos = 12; - for (i = 0; i < nNewTables; ++i) { - tableDir[pos ] = (char)(newTables[i].tag >> 24); - tableDir[pos+ 1] = (char)(newTables[i].tag >> 16); - tableDir[pos+ 2] = (char)(newTables[i].tag >> 8); - tableDir[pos+ 3] = (char) newTables[i].tag; - tableDir[pos+ 4] = (char)(newTables[i].checksum >> 24); - tableDir[pos+ 5] = (char)(newTables[i].checksum >> 16); - tableDir[pos+ 6] = (char)(newTables[i].checksum >> 8); - tableDir[pos+ 7] = (char) newTables[i].checksum; - tableDir[pos+ 8] = (char)(newTables[i].offset >> 24); - tableDir[pos+ 9] = (char)(newTables[i].offset >> 16); - tableDir[pos+10] = (char)(newTables[i].offset >> 8); - tableDir[pos+11] = (char) newTables[i].offset; - tableDir[pos+12] = (char)(newTables[i].len >> 24); - tableDir[pos+13] = (char)(newTables[i].len >> 16); - tableDir[pos+14] = (char)(newTables[i].len >> 8); - tableDir[pos+15] = (char) newTables[i].len; - pos += 16; - } - (*outputFunc)(outputStream, tableDir, 12 + nNewTables * 16); - - // compute the file checksum - fileChecksum = computeTableChecksum((Guchar *)tableDir, - 12 + nNewTables * 16); - for (i = 0; i < nNewTables; ++i) { - fileChecksum += newTables[i].checksum; - } - fileChecksum = 0xb1b0afba - fileChecksum; - - // write the tables - for (i = 0; i < nNewTables; ++i) { - if (newTables[i].tag == headTag) { - if (checkRegion(newTables[i].origOffset, newTables[i].len)) { - (*outputFunc)(outputStream, (char *)file + newTables[i].origOffset, 8); - checksumBuf[0] = fileChecksum >> 24; - checksumBuf[1] = fileChecksum >> 16; - checksumBuf[2] = fileChecksum >> 8; - checksumBuf[3] = fileChecksum; - (*outputFunc)(outputStream, checksumBuf, 4); - (*outputFunc)(outputStream, - (char *)file + newTables[i].origOffset + 12, - newTables[i].len - 12); - } else { - for (j = 0; j < newTables[i].len; ++j) { - (*outputFunc)(outputStream, "\0", 1); - } - } - } else if (newTables[i].tag == cmapTag && codeToGID) { - (*outputFunc)(outputStream, newCmapTab, newTables[i].len); - } else if (newTables[i].tag == cmapTag && missingCmap) { - (*outputFunc)(outputStream, cmapTab, newTables[i].len); - } else if (newTables[i].tag == nameTag && name) { - (*outputFunc)(outputStream, newNameTab, newTables[i].len); - } else if (newTables[i].tag == nameTag && missingName) { - (*outputFunc)(outputStream, nameTab, newTables[i].len); - } else if (newTables[i].tag == postTag && missingPost) { - (*outputFunc)(outputStream, postTab, newTables[i].len); - } else if (newTables[i].tag == locaTag && unsortedLoca) { - for (j = 0; j <= nGlyphs; ++j) { - if (locaFmt) { - locaBuf[0] = (char)(locaTable[j].newOffset >> 24); - locaBuf[1] = (char)(locaTable[j].newOffset >> 16); - locaBuf[2] = (char)(locaTable[j].newOffset >> 8); - locaBuf[3] = (char) locaTable[j].newOffset; - (*outputFunc)(outputStream, locaBuf, 4); - } else { - locaBuf[0] = (char)(locaTable[j].newOffset >> 9); - locaBuf[1] = (char)(locaTable[j].newOffset >> 1); - (*outputFunc)(outputStream, locaBuf, 2); - } - } - } else if (newTables[i].tag == glyfTag && unsortedLoca) { - pos = tables[seekTable("glyf")].offset; - for (j = 0; j < nGlyphs; ++j) { - n = locaTable[j].len; - if (n > 0) { - k = locaTable[j].origOffset; - if (checkRegion(pos + k, n)) { - (*outputFunc)(outputStream, (char *)file + pos + k, n); - } else { - for (k = 0; k < n; ++k) { - (*outputFunc)(outputStream, "\0", 1); - } - } - if ((k = locaTable[j].len & 3)) { - (*outputFunc)(outputStream, "\0\0\0\0", 4 - k); - } - } - } - } else { - if (checkRegion(newTables[i].origOffset, newTables[i].len)) { - (*outputFunc)(outputStream, (char *)file + newTables[i].origOffset, - newTables[i].len); - } else { - for (j = 0; j < newTables[i].len; ++j) { - (*outputFunc)(outputStream, "\0", 1); - } - } - } - if (newTables[i].len & 3) { - (*outputFunc)(outputStream, "\0\0\0", 4 - (newTables[i].len & 3)); - } - } - - gfree(newCmapTab); - gfree(newNameTab); - gfree(tableDir); - gfree(newTables); - done1: - gfree(locaTable); -} - -void FoFiTrueType::cvtEncoding(char **encoding, - FoFiOutputFunc outputFunc, - void *outputStream) { - char *name; - char buf[64]; - int i; - - (*outputFunc)(outputStream, "/Encoding 256 array\n", 20); - if (encoding) { - for (i = 0; i < 256; ++i) { - if (!(name = encoding[i])) { - name = ".notdef"; - } - sprintf(buf, "dup %d /", i); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, name, strlen(name)); - (*outputFunc)(outputStream, " put\n", 5); - } - } else { - for (i = 0; i < 256; ++i) { - sprintf(buf, "dup %d /c%02x put\n", i, i); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - } - (*outputFunc)(outputStream, "readonly def\n", 13); -} - -void FoFiTrueType::cvtCharStrings(char **encoding, - Gushort *codeToGID, - FoFiOutputFunc outputFunc, - void *outputStream) { - char *name; - char buf[64], buf2[16]; - int i, k; - - // always define '.notdef' - (*outputFunc)(outputStream, "/CharStrings 256 dict dup begin\n", 32); - (*outputFunc)(outputStream, "/.notdef 0 def\n", 15); - - // if there's no 'cmap' table, punt - if (nCmaps == 0) { - goto err; - } - - // map char name to glyph index: - // 1. use encoding to map name to char code - // 2. use codeToGID to map char code to glyph index - // N.B. We do this in reverse order because font subsets can have - // weird encodings that use the same character name twice, and - // the first definition is probably the one we want. - k = 0; // make gcc happy - for (i = 255; i >= 0; --i) { - if (encoding) { - name = encoding[i]; - } else { - sprintf(buf2, "c%02x", i); - name = buf2; - } - if (name && strcmp(name, ".notdef")) { - k = codeToGID[i]; - // note: Distiller (maybe Adobe's PS interpreter in general) - // doesn't like TrueType fonts that have CharStrings entries - // which point to nonexistent glyphs, hence the (k < nGlyphs) - // test - if (k > 0 && k < nGlyphs) { - (*outputFunc)(outputStream, "/", 1); - (*outputFunc)(outputStream, name, strlen(name)); - sprintf(buf, " %d def\n", k); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - } - } - - err: - (*outputFunc)(outputStream, "end readonly def\n", 17); -} - -void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc, - void *outputStream, GString *name, - GBool needVerticalMetrics) { - Guchar headData[54]; - TrueTypeLoca *locaTable; - Guchar *locaData; - TrueTypeTable newTables[nT42Tables]; - Guchar tableDir[12 + nT42Tables*16]; - GBool ok; - Guint checksum; - int nNewTables; - int length, pos, glyfPos, i, j, k; - Guchar vheaTab[36] = { - 0, 1, 0, 0, // table version number - 0, 0, // ascent - 0, 0, // descent - 0, 0, // reserved - 0, 0, // max advance height - 0, 0, // min top side bearing - 0, 0, // min bottom side bearing - 0, 0, // y max extent - 0, 0, // caret slope rise - 0, 1, // caret slope run - 0, 0, // caret offset - 0, 0, // reserved - 0, 0, // reserved - 0, 0, // reserved - 0, 0, // reserved - 0, 0, // metric data format - 0, 1 // number of advance heights in vmtx table - }; - Guchar *vmtxTab; - GBool needVhea, needVmtx; - int advance; - - // construct the 'head' table, zero out the font checksum - i = seekTable("head"); - pos = tables[i].offset; - if (!checkRegion(pos, 54)) { - return; - } - memcpy(headData, file + pos, 54); - headData[8] = headData[9] = headData[10] = headData[11] = (Guchar)0; - - // read the original 'loca' table, pad entries out to 4 bytes, and - // sort it into proper order -- some (non-compliant) fonts have - // out-of-order loca tables; in order to correctly handle the case - // where (compliant) fonts have empty entries in the middle of the - // table, cmpTrueTypeLocaPos uses offset as its primary sort key, - // and idx as its secondary key (ensuring that adjacent entries with - // the same pos value remain in the same order) - locaTable = (TrueTypeLoca *)gmallocn(nGlyphs + 1, sizeof(TrueTypeLoca)); - i = seekTable("loca"); - pos = tables[i].offset; - ok = gTrue; - for (i = 0; i <= nGlyphs; ++i) { - locaTable[i].idx = i; - if (locaFmt) { - locaTable[i].origOffset = (int)getU32BE(pos + i*4, &ok); - } else { - locaTable[i].origOffset = 2 * getU16BE(pos + i*2, &ok); - } - } - qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca), - &cmpTrueTypeLocaOffset); - for (i = 0; i < nGlyphs; ++i) { - locaTable[i].len = locaTable[i+1].origOffset - locaTable[i].origOffset; - } - locaTable[nGlyphs].len = 0; - qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca), - &cmpTrueTypeLocaIdx); - pos = 0; - for (i = 0; i <= nGlyphs; ++i) { - locaTable[i].newOffset = pos; - pos += locaTable[i].len; - if (pos & 3) { - pos += 4 - (pos & 3); - } - } - - // construct the new 'loca' table - locaData = (Guchar *)gmallocn(nGlyphs + 1, (locaFmt ? 4 : 2)); - for (i = 0; i <= nGlyphs; ++i) { - pos = locaTable[i].newOffset; - if (locaFmt) { - locaData[4*i ] = (Guchar)(pos >> 24); - locaData[4*i+1] = (Guchar)(pos >> 16); - locaData[4*i+2] = (Guchar)(pos >> 8); - locaData[4*i+3] = (Guchar) pos; - } else { - locaData[2*i ] = (Guchar)(pos >> 9); - locaData[2*i+1] = (Guchar)(pos >> 1); - } - } - - // count the number of tables - nNewTables = 0; - for (i = 0; i < nT42Tables; ++i) { - if (t42Tables[i].required || - seekTable(t42Tables[i].tag) >= 0) { - ++nNewTables; - } - } - vmtxTab = NULL; // make gcc happy - advance = 0; // make gcc happy - if (needVerticalMetrics) { - needVhea = seekTable("vhea") < 0; - needVmtx = seekTable("vmtx") < 0; - if (needVhea || needVmtx) { - i = seekTable("head"); - advance = getU16BE(tables[i].offset + 18, &ok); // units per em - if (needVhea) { - ++nNewTables; - } - if (needVmtx) { - ++nNewTables; - } - } - } - - // construct the new table headers, including table checksums - // (pad each table out to a multiple of 4 bytes) - pos = 12 + nNewTables*16; - k = 0; - for (i = 0; i < nT42Tables; ++i) { - length = -1; - checksum = 0; // make gcc happy - if (i == t42HeadTable) { - length = 54; - checksum = computeTableChecksum(headData, 54); - } else if (i == t42LocaTable) { - length = (nGlyphs + 1) * (locaFmt ? 4 : 2); - checksum = computeTableChecksum(locaData, length); - } else if (i == t42GlyfTable) { - length = 0; - checksum = 0; - glyfPos = tables[seekTable("glyf")].offset; - for (j = 0; j < nGlyphs; ++j) { - length += locaTable[j].len; - if (length & 3) { - length += 4 - (length & 3); - } - if (checkRegion(glyfPos + locaTable[j].origOffset, locaTable[j].len)) { - checksum += - computeTableChecksum(file + glyfPos + locaTable[j].origOffset, - locaTable[j].len); - } - } - } else { - if ((j = seekTable(t42Tables[i].tag)) >= 0) { - length = tables[j].len; - if (checkRegion(tables[j].offset, length)) { - checksum = computeTableChecksum(file + tables[j].offset, length); - } - } else if (needVerticalMetrics && i == t42VheaTable) { - vheaTab[10] = advance / 256; // max advance height - vheaTab[11] = advance % 256; - length = sizeof(vheaTab); - checksum = computeTableChecksum(vheaTab, length); - } else if (needVerticalMetrics && i == t42VmtxTable) { - length = 4 + (nGlyphs - 1) * 4; - vmtxTab = (Guchar *)gmalloc(length); - vmtxTab[0] = advance / 256; - vmtxTab[1] = advance % 256; - for (j = 2; j < length; j += 2) { - vmtxTab[j] = 0; - vmtxTab[j+1] = 0; - } - checksum = computeTableChecksum(vmtxTab, length); - } else if (t42Tables[i].required) { - //~ error(-1, "Embedded TrueType font is missing a required table ('%s')", - //~ t42Tables[i].tag); - length = 0; - checksum = 0; - } - } - if (length >= 0) { - newTables[k].tag = ((t42Tables[i].tag[0] & 0xff) << 24) | - ((t42Tables[i].tag[1] & 0xff) << 16) | - ((t42Tables[i].tag[2] & 0xff) << 8) | - (t42Tables[i].tag[3] & 0xff); - newTables[k].checksum = checksum; - newTables[k].offset = pos; - newTables[k].len = length; - pos += length; - if (pos & 3) { - pos += 4 - (length & 3); - } - ++k; - } - } - - // construct the table directory - tableDir[0] = 0x00; // sfnt version - tableDir[1] = 0x01; - tableDir[2] = 0x00; - tableDir[3] = 0x00; - tableDir[4] = 0; // numTables - tableDir[5] = nNewTables; - tableDir[6] = 0; // searchRange - tableDir[7] = (Guchar)128; - tableDir[8] = 0; // entrySelector - tableDir[9] = 3; - tableDir[10] = 0; // rangeShift - tableDir[11] = (Guchar)(16 * nNewTables - 128); - pos = 12; - for (i = 0; i < nNewTables; ++i) { - tableDir[pos ] = (Guchar)(newTables[i].tag >> 24); - tableDir[pos+ 1] = (Guchar)(newTables[i].tag >> 16); - tableDir[pos+ 2] = (Guchar)(newTables[i].tag >> 8); - tableDir[pos+ 3] = (Guchar) newTables[i].tag; - tableDir[pos+ 4] = (Guchar)(newTables[i].checksum >> 24); - tableDir[pos+ 5] = (Guchar)(newTables[i].checksum >> 16); - tableDir[pos+ 6] = (Guchar)(newTables[i].checksum >> 8); - tableDir[pos+ 7] = (Guchar) newTables[i].checksum; - tableDir[pos+ 8] = (Guchar)(newTables[i].offset >> 24); - tableDir[pos+ 9] = (Guchar)(newTables[i].offset >> 16); - tableDir[pos+10] = (Guchar)(newTables[i].offset >> 8); - tableDir[pos+11] = (Guchar) newTables[i].offset; - tableDir[pos+12] = (Guchar)(newTables[i].len >> 24); - tableDir[pos+13] = (Guchar)(newTables[i].len >> 16); - tableDir[pos+14] = (Guchar)(newTables[i].len >> 8); - tableDir[pos+15] = (Guchar) newTables[i].len; - pos += 16; - } - - // compute the font checksum and store it in the head table - checksum = computeTableChecksum(tableDir, 12 + nNewTables*16); - for (i = 0; i < nNewTables; ++i) { - checksum += newTables[i].checksum; - } - checksum = 0xb1b0afba - checksum; // because the TrueType spec says so - headData[ 8] = (Guchar)(checksum >> 24); - headData[ 9] = (Guchar)(checksum >> 16); - headData[10] = (Guchar)(checksum >> 8); - headData[11] = (Guchar) checksum; - - // start the sfnts array - if (name) { - (*outputFunc)(outputStream, "/", 1); - (*outputFunc)(outputStream, name->getCString(), name->getLength()); - (*outputFunc)(outputStream, " [\n", 3); - } else { - (*outputFunc)(outputStream, "/sfnts [\n", 9); - } - - // write the table directory - dumpString(tableDir, 12 + nNewTables*16, outputFunc, outputStream); - - // write the tables - for (i = 0; i < nNewTables; ++i) { - if (i == t42HeadTable) { - dumpString(headData, 54, outputFunc, outputStream); - } else if (i == t42LocaTable) { - length = (nGlyphs + 1) * (locaFmt ? 4 : 2); - dumpString(locaData, length, outputFunc, outputStream); - } else if (i == t42GlyfTable) { - glyfPos = tables[seekTable("glyf")].offset; - for (j = 0; j < nGlyphs; ++j) { - if (locaTable[j].len > 0 && - checkRegion(glyfPos + locaTable[j].origOffset, locaTable[j].len)) { - dumpString(file + glyfPos + locaTable[j].origOffset, - locaTable[j].len, outputFunc, outputStream); - } - } - } else { - // length == 0 means the table is missing and the error was - // already reported during the construction of the table - // headers - if ((length = newTables[i].len) > 0) { - if ((j = seekTable(t42Tables[i].tag)) >= 0 && - checkRegion(tables[j].offset, tables[j].len)) { - dumpString(file + tables[j].offset, tables[j].len, - outputFunc, outputStream); - } else if (needVerticalMetrics && i == t42VheaTable) { - dumpString(vheaTab, length, outputFunc, outputStream); - } else if (needVerticalMetrics && i == t42VmtxTable) { - dumpString(vmtxTab, length, outputFunc, outputStream); - gfree(vmtxTab); - } - } - } - } - - // end the sfnts array - (*outputFunc)(outputStream, "] def\n", 6); - - gfree(locaData); - gfree(locaTable); -} - -void FoFiTrueType::dumpString(Guchar *s, int length, - FoFiOutputFunc outputFunc, - void *outputStream) { - char buf[64]; - int pad, i, j; - - (*outputFunc)(outputStream, "<", 1); - for (i = 0; i < length; i += 32) { - for (j = 0; j < 32 && i+j < length; ++j) { - sprintf(buf, "%02X", s[i+j] & 0xff); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - if (i % (65536 - 32) == 65536 - 64) { - (*outputFunc)(outputStream, ">\n<", 3); - } else if (i+32 < length) { - (*outputFunc)(outputStream, "\n", 1); - } - } - if (length & 3) { - pad = 4 - (length & 3); - for (i = 0; i < pad; ++i) { - (*outputFunc)(outputStream, "00", 2); - } - } - // add an extra zero byte because the Adobe Type 42 spec says so - (*outputFunc)(outputStream, "00>\n", 4); -} - -Guint FoFiTrueType::computeTableChecksum(Guchar *data, int length) { - Guint checksum, word; - int i; - - checksum = 0; - for (i = 0; i+3 < length; i += 4) { - word = ((data[i ] & 0xff) << 24) + - ((data[i+1] & 0xff) << 16) + - ((data[i+2] & 0xff) << 8) + - (data[i+3] & 0xff); - checksum += word; - } - if (length & 3) { - word = 0; - i = length & ~3; - switch (length & 3) { - case 3: - word |= (data[i+2] & 0xff) << 8; - case 2: - word |= (data[i+1] & 0xff) << 16; - case 1: - word |= (data[i ] & 0xff) << 24; - break; - } - checksum += word; - } - return checksum; -} - -void FoFiTrueType::parse() { - Guint topTag; - int pos, i, j; - - parsedOk = gTrue; - - // look for a collection (TTC) - topTag = getU32BE(0, &parsedOk); - if (!parsedOk) { - return; - } - if (topTag == ttcfTag) { - pos = getU32BE(12, &parsedOk); - if (!parsedOk) { - return; - } - } else { - pos = 0; - } - - // read the table directory - nTables = getU16BE(pos + 4, &parsedOk); - if (!parsedOk) { - return; - } - tables = (TrueTypeTable *)gmallocn(nTables, sizeof(TrueTypeTable)); - pos += 12; - for (i = 0; i < nTables; ++i) { - tables[i].tag = getU32BE(pos, &parsedOk); - tables[i].checksum = getU32BE(pos + 4, &parsedOk); - tables[i].offset = (int)getU32BE(pos + 8, &parsedOk); - tables[i].len = (int)getU32BE(pos + 12, &parsedOk); - if (tables[i].offset + tables[i].len < tables[i].offset || - tables[i].offset + tables[i].len > len) { - parsedOk = gFalse; - } - pos += 16; - } - if (!parsedOk) { - return; - } - - // check for tables that are required by both the TrueType spec and - // the Type 42 spec - if (seekTable("head") < 0 || - seekTable("hhea") < 0 || - seekTable("loca") < 0 || - seekTable("maxp") < 0 || - seekTable("glyf") < 0 || - seekTable("hmtx") < 0) { - parsedOk = gFalse; - return; - } - - // read the cmaps - if ((i = seekTable("cmap")) >= 0) { - pos = tables[i].offset + 2; - nCmaps = getU16BE(pos, &parsedOk); - pos += 2; - if (!parsedOk) { - return; - } - cmaps = (TrueTypeCmap *)gmallocn(nCmaps, sizeof(TrueTypeCmap)); - for (j = 0; j < nCmaps; ++j) { - cmaps[j].platform = getU16BE(pos, &parsedOk); - cmaps[j].encoding = getU16BE(pos + 2, &parsedOk); - cmaps[j].offset = tables[i].offset + getU32BE(pos + 4, &parsedOk); - pos += 8; - cmaps[j].fmt = getU16BE(cmaps[j].offset, &parsedOk); - cmaps[j].len = getU16BE(cmaps[j].offset + 2, &parsedOk); - } - if (!parsedOk) { - return; - } - } else { - nCmaps = 0; - } - - // get the number of glyphs from the maxp table - i = seekTable("maxp"); - nGlyphs = getU16BE(tables[i].offset + 4, &parsedOk); - if (!parsedOk) { - return; - } - - // get the bbox and loca table format from the head table - i = seekTable("head"); - bbox[0] = getS16BE(tables[i].offset + 36, &parsedOk); - bbox[1] = getS16BE(tables[i].offset + 38, &parsedOk); - bbox[2] = getS16BE(tables[i].offset + 40, &parsedOk); - bbox[3] = getS16BE(tables[i].offset + 42, &parsedOk); - locaFmt = getS16BE(tables[i].offset + 50, &parsedOk); - if (!parsedOk) { - return; - } - - // make sure the loca table is sane (correct length and entries are - // in bounds) - i = seekTable("loca"); - if (tables[i].len < (nGlyphs + 1) * (locaFmt ? 4 : 2)) { - parsedOk = gFalse; - return; - } - for (j = 0; j <= nGlyphs; ++j) { - if (locaFmt) { - pos = (int)getU32BE(tables[i].offset + j*4, &parsedOk); - } else { - pos = getU16BE(tables[i].offset + j*2, &parsedOk); - } - if (pos < 0 || pos > len) { - parsedOk = gFalse; - } - } - if (!parsedOk) { - return; - } - - // read the post table - readPostTable(); -} - -void FoFiTrueType::readPostTable() { - GString *name; - int tablePos, postFmt, stringIdx, stringPos; - GBool ok; - int i, j, n, m; - - ok = gTrue; - if ((i = seekTable("post")) < 0) { - return; - } - tablePos = tables[i].offset; - postFmt = getU32BE(tablePos, &ok); - if (!ok) { - goto err; - } - if (postFmt == 0x00010000) { - nameToGID = new GHash(gTrue); - for (i = 0; i < 258; ++i) { - nameToGID->add(new GString(macGlyphNames[i]), i); - } - } else if (postFmt == 0x00020000) { - nameToGID = new GHash(gTrue); - n = getU16BE(tablePos + 32, &ok); - if (!ok) { - goto err; - } - if (n > nGlyphs) { - n = nGlyphs; - } - stringIdx = 0; - stringPos = tablePos + 34 + 2*n; - for (i = 0; i < n; ++i) { - j = getU16BE(tablePos + 34 + 2*i, &ok); - if (j < 258) { - nameToGID->removeInt(macGlyphNames[j]); - nameToGID->add(new GString(macGlyphNames[j]), i); - } else { - j -= 258; - if (j != stringIdx) { - for (stringIdx = 0, stringPos = tablePos + 34 + 2*n; - stringIdx < j; - ++stringIdx, stringPos += 1 + getU8(stringPos, &ok)) ; - if (!ok) { - goto err; - } - } - m = getU8(stringPos, &ok); - if (!ok || !checkRegion(stringPos + 1, m)) { - goto err; - } - name = new GString((char *)&file[stringPos + 1], m); - nameToGID->removeInt(name); - nameToGID->add(name, i); - ++stringIdx; - stringPos += 1 + m; - } - } - } else if (postFmt == 0x00028000) { - nameToGID = new GHash(gTrue); - for (i = 0; i < nGlyphs; ++i) { - j = getU8(tablePos + 32 + i, &ok); - if (!ok) { - goto err; - } - if (j < 258) { - nameToGID->removeInt(macGlyphNames[j]); - nameToGID->add(new GString(macGlyphNames[j]), i); - } - } - } - - return; - - err: - if (nameToGID) { - delete nameToGID; - nameToGID = NULL; - } -} - -int FoFiTrueType::seekTable(char *tag) { - Guint tagI; - int i; - - tagI = ((tag[0] & 0xff) << 24) | - ((tag[1] & 0xff) << 16) | - ((tag[2] & 0xff) << 8) | - (tag[3] & 0xff); - for (i = 0; i < nTables; ++i) { - if (tables[i].tag == tagI) { - return i; - } - } - return -1; -} diff --git a/pdftops/FoFiTrueType.h b/pdftops/FoFiTrueType.h deleted file mode 100644 index 715bb60f1..000000000 --- a/pdftops/FoFiTrueType.h +++ /dev/null @@ -1,140 +0,0 @@ -//======================================================================== -// -// FoFiTrueType.h -// -// Copyright 1999-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef FOFITRUETYPE_H -#define FOFITRUETYPE_H - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "gtypes.h" -#include "FoFiBase.h" - -class GString; -class GHash; -struct TrueTypeTable; -struct TrueTypeCmap; - -//------------------------------------------------------------------------ -// FoFiTrueType -//------------------------------------------------------------------------ - -class FoFiTrueType: public FoFiBase { -public: - - // Create a FoFiTrueType object from a memory buffer. - static FoFiTrueType *make(char *fileA, int lenA); - - // Create a FoFiTrueType object from a file on disk. - static FoFiTrueType *load(char *fileName); - - virtual ~FoFiTrueType(); - - // Return the number of cmaps defined by this font. - int getNumCmaps(); - - // Return the platform ID of the <i>th cmap. - int getCmapPlatform(int i); - - // Return the encoding ID of the <i>th cmap. - int getCmapEncoding(int i); - - // Return the index of the cmap for <platform>, <encoding>. Returns - // -1 if there is no corresponding cmap. - int findCmap(int platform, int encoding); - - // Return the GID corresponding to <c> according to the <i>th cmap. - Gushort mapCodeToGID(int i, int c); - - // Returns the GID corresponding to <name> according to the post - // table. Returns 0 if there is no mapping for <name> or if the - // font does not have a post table. - int mapNameToGID(char *name); - - // Returns the least restrictive embedding licensing right (as - // defined by the TrueType spec): - // * 4: OS/2 table is missing or invalid - // * 3: installable embedding - // * 2: editable embedding - // * 1: preview & print embedding - // * 0: restricted license embedding - int getEmbeddingRights(); - - // Convert to a Type 42 font, suitable for embedding in a PostScript - // file. <psName> will be used as the PostScript font name (so we - // don't need to depend on the 'name' table in the font). The - // <encoding> array specifies the mapping from char codes to names. - // If <encoding> is NULL, the encoding is unknown or undefined. The - // <codeToGID> array specifies the mapping from char codes to GIDs. - void convertToType42(char *psName, char **encoding, - Gushort *codeToGID, - FoFiOutputFunc outputFunc, void *outputStream); - - // Convert to a Type 2 CIDFont, suitable for embedding in a - // PostScript file. <psName> will be used as the PostScript font - // name (so we don't need to depend on the 'name' table in the - // font). The <cidMap> array maps CIDs to GIDs; it has <nCIDs> - // entries. - void convertToCIDType2(char *psName, Gushort *cidMap, int nCIDs, - GBool needVerticalMetrics, - FoFiOutputFunc outputFunc, void *outputStream); - - // Convert to a Type 0 (but non-CID) composite font, suitable for - // embedding in a PostScript file. <psName> will be used as the - // PostScript font name (so we don't need to depend on the 'name' - // table in the font). The <cidMap> array maps CIDs to GIDs; it has - // <nCIDs> entries. - void convertToType0(char *psName, Gushort *cidMap, int nCIDs, - GBool needVerticalMetrics, - FoFiOutputFunc outputFunc, void *outputStream); - - // Write a clean TTF file, filling in missing tables and correcting - // various other errors. If <name> is non-NULL, the font is renamed - // to <name>. If <codeToGID> is non-NULL, the font is re-encoded, - // using a Windows Unicode cmap. If <name> is NULL and the font is - // complete and correct, it will be written unmodified. - void writeTTF(FoFiOutputFunc outputFunc, void *outputStream, - char *name = NULL, Gushort *codeToGID = NULL); - -private: - - FoFiTrueType(char *fileA, int lenA, GBool freeFileDataA); - void cvtEncoding(char **encoding, - FoFiOutputFunc outputFunc, - void *outputStream); - void cvtCharStrings(char **encoding, - Gushort *codeToGID, - FoFiOutputFunc outputFunc, - void *outputStream); - void cvtSfnts(FoFiOutputFunc outputFunc, - void *outputStream, GString *name, - GBool needVerticalMetrics); - void dumpString(Guchar *s, int length, - FoFiOutputFunc outputFunc, - void *outputStream); - Guint computeTableChecksum(Guchar *data, int length); - void parse(); - void readPostTable(); - int seekTable(char *tag); - - TrueTypeTable *tables; - int nTables; - TrueTypeCmap *cmaps; - int nCmaps; - int nGlyphs; - int locaFmt; - int bbox[4]; - GHash *nameToGID; - - GBool parsedOk; -}; - -#endif diff --git a/pdftops/FoFiType1.cxx b/pdftops/FoFiType1.cxx deleted file mode 100644 index 103cc55a5..000000000 --- a/pdftops/FoFiType1.cxx +++ /dev/null @@ -1,207 +0,0 @@ -//======================================================================== -// -// FoFiType1.cc -// -// Copyright 1999-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include <stdlib.h> -#include <string.h> -#include "gmem.h" -#include "FoFiEncodings.h" -#include "FoFiType1.h" - -//------------------------------------------------------------------------ -// FoFiType1 -//------------------------------------------------------------------------ - -FoFiType1 *FoFiType1::make(char *fileA, int lenA) { - return new FoFiType1(fileA, lenA, gFalse); -} - -FoFiType1 *FoFiType1::load(char *fileName) { - char *fileA; - int lenA; - - if (!(fileA = FoFiBase::readFile(fileName, &lenA))) { - return NULL; - } - return new FoFiType1(fileA, lenA, gTrue); -} - -FoFiType1::FoFiType1(char *fileA, int lenA, GBool freeFileDataA): - FoFiBase(fileA, lenA, freeFileDataA) -{ - name = NULL; - encoding = NULL; - parsed = gFalse; -} - -FoFiType1::~FoFiType1() { - int i; - - if (name) { - gfree(name); - } - if (encoding && encoding != fofiType1StandardEncoding) { - for (i = 0; i < 256; ++i) { - gfree(encoding[i]); - } - gfree(encoding); - } -} - -char *FoFiType1::getName() { - if (!parsed) { - parse(); - } - return name; -} - -char **FoFiType1::getEncoding() { - if (!parsed) { - parse(); - } - return encoding; -} - -void FoFiType1::writeEncoded(char **newEncoding, - FoFiOutputFunc outputFunc, void *outputStream) { - char buf[512]; - char *line; - int i; - - // copy everything up to the encoding - for (line = (char *)file; - line && strncmp(line, "/Encoding", 9); - line = getNextLine(line)) ; - if (!line) { - // no encoding - just copy the whole font file - (*outputFunc)(outputStream, (char *)file, len); - return; - } - (*outputFunc)(outputStream, (char *)file, line - (char *)file); - - // write the new encoding - (*outputFunc)(outputStream, "/Encoding 256 array\n", 20); - (*outputFunc)(outputStream, - "0 1 255 {1 index exch /.notdef put} for\n", 40); - for (i = 0; i < 256; ++i) { - if (newEncoding[i]) { - sprintf(buf, "dup %d /%s put\n", i, newEncoding[i]); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - } - (*outputFunc)(outputStream, "readonly def\n", 13); - - // copy everything after the encoding - if (!strncmp(line, "/Encoding StandardEncoding def", 30)) { - line = getNextLine(line); - } else { - for (line = getNextLine(line); - line && strncmp(line, "readonly def", 12); - line = getNextLine(line)) ; - if (line) { - line = getNextLine(line); - } - } - if (line) { - (*outputFunc)(outputStream, line, ((char *)file + len) - line); - } -} - -char *FoFiType1::getNextLine(char *line) { - while (line < (char *)file + len && *line != '\x0a' && *line != '\x0d') { - ++line; - } - if (line < (char *)file + len && *line == '\x0d') { - ++line; - } - if (line < (char *)file + len && *line == '\x0a') { - ++line; - } - if (line >= (char *)file + len) { - return NULL; - } - return line; -} - -void FoFiType1::parse() { - char *line, *line1, *p, *p2; - char buf[256]; - char c; - int n, code, i, j; - - for (i = 1, line = (char *)file; - i <= 100 && line && (!name || !encoding); - ++i) { - - // get font name - if (!name && !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 = getNextLine(line); - - // get encoding - } else if (!encoding && - !strncmp(line, "/Encoding StandardEncoding def", 30)) { - encoding = fofiType1StandardEncoding; - } else if (!encoding && - !strncmp(line, "/Encoding 256 array", 19)) { - encoding = (char **)gmallocn(256, sizeof(char *)); - for (j = 0; j < 256; ++j) { - encoding[j] = NULL; - } - for (j = 0, line = getNextLine(line); - j < 300 && line && (line1 = getNextLine(line)); - ++j, line = line1) { - if ((n = line1 - line) > 255) { - n = 255; - } - strncpy(buf, line, n); - buf[n] = '\0'; - for (p = buf; *p == ' ' || *p == '\t'; ++p) ; - if (!strncmp(p, "dup", 3)) { - for (p += 3; *p == ' ' || *p == '\t'; ++p) ; - for (p2 = p; *p2 >= '0' && *p2 <= '9'; ++p2) ; - if (*p2) { - c = *p2; - *p2 = '\0'; - if ((code = atoi(p)) < 256) { - *p2 = c; - for (p = p2; *p == ' ' || *p == '\t'; ++p) ; - if (*p == '/') { - ++p; - for (p2 = p; *p2 && *p2 != ' ' && *p2 != '\t'; ++p2) ; - *p2 = '\0'; - encoding[code] = copyString(p); - } - } - } - } else { - if (strtok(buf, " \t") && - (p = strtok(NULL, " \t\n\r")) && !strcmp(p, "def")) { - break; - } - } - } - //~ check for getinterval/putinterval junk - - } else { - line = getNextLine(line); - } - } - - parsed = gTrue; -} diff --git a/pdftops/FoFiType1.h b/pdftops/FoFiType1.h deleted file mode 100644 index 6172c2d58..000000000 --- a/pdftops/FoFiType1.h +++ /dev/null @@ -1,59 +0,0 @@ -//======================================================================== -// -// FoFiType1.h -// -// Copyright 1999-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef FOFITYPE1_H -#define FOFITYPE1_H - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "gtypes.h" -#include "FoFiBase.h" - -//------------------------------------------------------------------------ -// FoFiType1 -//------------------------------------------------------------------------ - -class FoFiType1: public FoFiBase { -public: - - // Create a FoFiType1 object from a memory buffer. - static FoFiType1 *make(char *fileA, int lenA); - - // Create a FoFiType1 object from a file on disk. - static FoFiType1 *load(char *fileName); - - virtual ~FoFiType1(); - - // Return the font name. - char *getName(); - - // Return the encoding, as an array of 256 names (any of which may - // be NULL). - char **getEncoding(); - - // Write a version of the Type 1 font file with a new encoding. - void writeEncoded(char **newEncoding, - FoFiOutputFunc outputFunc, void *outputStream); - -private: - - FoFiType1(char *fileA, int lenA, GBool freeFileDataA); - - char *getNextLine(char *line); - void parse(); - - char *name; - char **encoding; - GBool parsed; -}; - -#endif diff --git a/pdftops/FoFiType1C.cxx b/pdftops/FoFiType1C.cxx deleted file mode 100644 index 0cda63576..000000000 --- a/pdftops/FoFiType1C.cxx +++ /dev/null @@ -1,2481 +0,0 @@ -//======================================================================== -// -// FoFiType1C.cc -// -// Copyright 1999-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include <stdlib.h> -#include <string.h> -#include <math.h> -#include "gmem.h" -#include "GString.h" -#include "FoFiEncodings.h" -#include "FoFiType1C.h" - -//------------------------------------------------------------------------ - -static char hexChars[17] = "0123456789ABCDEF"; - -//------------------------------------------------------------------------ -// FoFiType1C -//------------------------------------------------------------------------ - -FoFiType1C *FoFiType1C::make(char *fileA, int lenA) { - FoFiType1C *ff; - - ff = new FoFiType1C(fileA, lenA, gFalse); - if (!ff->parse()) { - delete ff; - return NULL; - } - return ff; -} - -FoFiType1C *FoFiType1C::load(char *fileName) { - FoFiType1C *ff; - char *fileA; - int lenA; - - if (!(fileA = FoFiBase::readFile(fileName, &lenA))) { - return NULL; - } - ff = new FoFiType1C(fileA, lenA, gTrue); - if (!ff->parse()) { - delete ff; - return NULL; - } - return ff; -} - -FoFiType1C::FoFiType1C(char *fileA, int lenA, GBool freeFileDataA): - FoFiBase(fileA, lenA, freeFileDataA) -{ - name = NULL; - encoding = NULL; - privateDicts = NULL; - fdSelect = NULL; - charset = NULL; -} - -FoFiType1C::~FoFiType1C() { - int i; - - if (name) { - delete name; - } - if (encoding && - encoding != fofiType1StandardEncoding && - encoding != fofiType1ExpertEncoding) { - for (i = 0; i < 256; ++i) { - gfree(encoding[i]); - } - gfree(encoding); - } - if (privateDicts) { - gfree(privateDicts); - } - if (fdSelect) { - gfree(fdSelect); - } - if (charset && - charset != fofiType1CISOAdobeCharset && - charset != fofiType1CExpertCharset && - charset != fofiType1CExpertSubsetCharset) { - gfree(charset); - } -} - -char *FoFiType1C::getName() { - return name ? name->getCString() : (char *)NULL; -} - -char **FoFiType1C::getEncoding() { - return encoding; -} - -Gushort *FoFiType1C::getCIDToGIDMap(int *nCIDs) { - Gushort *map; - int n, i; - - // a CID font's top dict has ROS as the first operator - if (topDict.firstOp != 0x0c1e) { - *nCIDs = 0; - return NULL; - } - - // in a CID font, the charset data is the GID-to-CID mapping, so all - // we have to do is reverse it - n = 0; - for (i = 0; i < nGlyphs; ++i) { - if (charset[i] > n) { - n = charset[i]; - } - } - ++n; - map = (Gushort *)gmallocn(n, sizeof(Gushort)); - memset(map, 0, n * sizeof(Gushort)); - for (i = 0; i < nGlyphs; ++i) { - map[charset[i]] = i; - } - *nCIDs = n; - return map; -} - -void FoFiType1C::convertToType1(char **newEncoding, GBool ascii, - FoFiOutputFunc outputFunc, - void *outputStream) { - Type1CEexecBuf eb; - Type1CIndex subrIdx; - Type1CIndexVal val; - char buf[512]; - char **enc; - GBool ok; - int i; - - // write header and font dictionary, up to encoding - ok = gTrue; - (*outputFunc)(outputStream, "%!FontType1-1.0: ", 17); - (*outputFunc)(outputStream, name->getCString(), name->getLength()); - if (topDict.versionSID != 0) { - getString(topDict.versionSID, buf, &ok); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - (*outputFunc)(outputStream, "\n", 1); - // the dictionary needs room for 12 entries: the following 9, plus - // Private and CharStrings (in the eexec section) and FID (which is - // added by definefont) - (*outputFunc)(outputStream, "12 dict begin\n", 14); - (*outputFunc)(outputStream, "/FontInfo 10 dict dup begin\n", 28); - if (topDict.versionSID != 0) { - (*outputFunc)(outputStream, "/version (", 10); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, ") readonly def\n", 15); - } - if (topDict.noticeSID != 0) { - getString(topDict.noticeSID, buf, &ok); - (*outputFunc)(outputStream, "/Notice (", 9); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, ") readonly def\n", 15); - } - if (topDict.copyrightSID != 0) { - getString(topDict.copyrightSID, buf, &ok); - (*outputFunc)(outputStream, "/Copyright (", 12); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, ") readonly def\n", 15); - } - if (topDict.fullNameSID != 0) { - getString(topDict.fullNameSID, buf, &ok); - (*outputFunc)(outputStream, "/FullName (", 11); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, ") readonly def\n", 15); - } - if (topDict.familyNameSID != 0) { - getString(topDict.familyNameSID, buf, &ok); - (*outputFunc)(outputStream, "/FamilyName (", 13); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, ") readonly def\n", 15); - } - if (topDict.weightSID != 0) { - getString(topDict.weightSID, buf, &ok); - (*outputFunc)(outputStream, "/Weight (", 9); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, ") readonly def\n", 15); - } - if (topDict.isFixedPitch) { - (*outputFunc)(outputStream, "/isFixedPitch true def\n", 23); - } else { - (*outputFunc)(outputStream, "/isFixedPitch false def\n", 24); - } - sprintf(buf, "/ItalicAngle %g def\n", topDict.italicAngle); - (*outputFunc)(outputStream, buf, strlen(buf)); - sprintf(buf, "/UnderlinePosition %g def\n", topDict.underlinePosition); - (*outputFunc)(outputStream, buf, strlen(buf)); - sprintf(buf, "/UnderlineThickness %g def\n", topDict.underlineThickness); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, "end readonly def\n", 17); - (*outputFunc)(outputStream, "/FontName /", 11); - (*outputFunc)(outputStream, name->getCString(), name->getLength()); - (*outputFunc)(outputStream, " def\n", 5); - sprintf(buf, "/PaintType %d def\n", topDict.paintType); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, "/FontType 1 def\n", 16); - sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] readonly def\n", - topDict.fontMatrix[0], topDict.fontMatrix[1], topDict.fontMatrix[2], - topDict.fontMatrix[3], topDict.fontMatrix[4], topDict.fontMatrix[5]); - (*outputFunc)(outputStream, buf, strlen(buf)); - sprintf(buf, "/FontBBox [%g %g %g %g] readonly def\n", - topDict.fontBBox[0], topDict.fontBBox[1], - topDict.fontBBox[2], topDict.fontBBox[3]); - (*outputFunc)(outputStream, buf, strlen(buf)); - sprintf(buf, "/StrokeWidth %g def\n", topDict.strokeWidth); - (*outputFunc)(outputStream, buf, strlen(buf)); - if (topDict.uniqueID != 0) { - sprintf(buf, "/UniqueID %d def\n", topDict.uniqueID); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - - // write the encoding - (*outputFunc)(outputStream, "/Encoding ", 10); - if (!newEncoding && encoding == fofiType1StandardEncoding) { - (*outputFunc)(outputStream, "StandardEncoding def\n", 21); - } else { - (*outputFunc)(outputStream, "256 array\n", 10); - (*outputFunc)(outputStream, - "0 1 255 {1 index exch /.notdef put} for\n", 40); - enc = newEncoding ? newEncoding : encoding; - for (i = 0; i < 256; ++i) { - if (enc[i]) { - sprintf(buf, "dup %d /%s put\n", i, enc[i]); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - } - (*outputFunc)(outputStream, "readonly def\n", 13); - } - (*outputFunc)(outputStream, "currentdict end\n", 16); - - // start the binary section - (*outputFunc)(outputStream, "currentfile eexec\n", 18); - eb.outputFunc = outputFunc; - eb.outputStream = outputStream; - eb.ascii = ascii; - eb.r1 = 55665; - eb.line = 0; - - // write the private dictionary - eexecWrite(&eb, "\x83\xca\x73\xd5"); - eexecWrite(&eb, "dup /Private 32 dict dup begin\n"); - eexecWrite(&eb, "/RD {string currentfile exch readstring pop}" - " executeonly def\n"); - eexecWrite(&eb, "/ND {noaccess def} executeonly def\n"); - eexecWrite(&eb, "/NP {noaccess put} executeonly def\n"); - eexecWrite(&eb, "/MinFeature {16 16} def\n"); - eexecWrite(&eb, "/password 5839 def\n"); - if (privateDicts[0].nBlueValues) { - eexecWrite(&eb, "/BlueValues ["); - for (i = 0; i < privateDicts[0].nBlueValues; ++i) { - sprintf(buf, "%s%d", i > 0 ? " " : "", privateDicts[0].blueValues[i]); - eexecWrite(&eb, buf); - } - eexecWrite(&eb, "] def\n"); - } - if (privateDicts[0].nOtherBlues) { - eexecWrite(&eb, "/OtherBlues ["); - for (i = 0; i < privateDicts[0].nOtherBlues; ++i) { - sprintf(buf, "%s%d", i > 0 ? " " : "", privateDicts[0].otherBlues[i]); - eexecWrite(&eb, buf); - } - eexecWrite(&eb, "] def\n"); - } - if (privateDicts[0].nFamilyBlues) { - eexecWrite(&eb, "/FamilyBlues ["); - for (i = 0; i < privateDicts[0].nFamilyBlues; ++i) { - sprintf(buf, "%s%d", i > 0 ? " " : "", privateDicts[0].familyBlues[i]); - eexecWrite(&eb, buf); - } - eexecWrite(&eb, "] def\n"); - } - if (privateDicts[0].nFamilyOtherBlues) { - eexecWrite(&eb, "/FamilyOtherBlues ["); - for (i = 0; i < privateDicts[0].nFamilyOtherBlues; ++i) { - sprintf(buf, "%s%d", i > 0 ? " " : "", - privateDicts[0].familyOtherBlues[i]); - eexecWrite(&eb, buf); - } - eexecWrite(&eb, "] def\n"); - } - if (privateDicts[0].blueScale != 0.039625) { - sprintf(buf, "/BlueScale %g def\n", privateDicts[0].blueScale); - eexecWrite(&eb, buf); - } - if (privateDicts[0].blueShift != 7) { - sprintf(buf, "/BlueShift %d def\n", privateDicts[0].blueShift); - eexecWrite(&eb, buf); - } - if (privateDicts[0].blueFuzz != 1) { - sprintf(buf, "/BlueFuzz %d def\n", privateDicts[0].blueFuzz); - eexecWrite(&eb, buf); - } - if (privateDicts[0].hasStdHW) { - sprintf(buf, "/StdHW [%g] def\n", privateDicts[0].stdHW); - eexecWrite(&eb, buf); - } - if (privateDicts[0].hasStdVW) { - sprintf(buf, "/StdVW [%g] def\n", privateDicts[0].stdVW); - eexecWrite(&eb, buf); - } - if (privateDicts[0].nStemSnapH) { - eexecWrite(&eb, "/StemSnapH ["); - for (i = 0; i < privateDicts[0].nStemSnapH; ++i) { - sprintf(buf, "%s%g", i > 0 ? " " : "", privateDicts[0].stemSnapH[i]); - eexecWrite(&eb, buf); - } - eexecWrite(&eb, "] def\n"); - } - if (privateDicts[0].nStemSnapV) { - eexecWrite(&eb, "/StemSnapV ["); - for (i = 0; i < privateDicts[0].nStemSnapV; ++i) { - sprintf(buf, "%s%g", i > 0 ? " " : "", privateDicts[0].stemSnapV[i]); - eexecWrite(&eb, buf); - } - eexecWrite(&eb, "] def\n"); - } - if (privateDicts[0].hasForceBold) { - sprintf(buf, "/ForceBold %s def\n", - privateDicts[0].forceBold ? "true" : "false"); - eexecWrite(&eb, buf); - } - if (privateDicts[0].forceBoldThreshold != 0) { - sprintf(buf, "/ForceBoldThreshold %g def\n", - privateDicts[0].forceBoldThreshold); - eexecWrite(&eb, buf); - } - if (privateDicts[0].languageGroup != 0) { - sprintf(buf, "/LanguageGroup %d def\n", privateDicts[0].languageGroup); - eexecWrite(&eb, buf); - } - if (privateDicts[0].expansionFactor != 0.06) { - sprintf(buf, "/ExpansionFactor %g def\n", privateDicts[0].expansionFactor); - eexecWrite(&eb, buf); - } - - // set up subroutines - ok = gTrue; - getIndex(privateDicts[0].subrsOffset, &subrIdx, &ok); - if (!ok) { - subrIdx.pos = -1; - } - - // write the CharStrings - sprintf(buf, "2 index /CharStrings %d dict dup begin\n", nGlyphs); - eexecWrite(&eb, buf); - for (i = 0; i < nGlyphs; ++i) { - ok = gTrue; - getIndexVal(&charStringsIdx, i, &val, &ok); - if (ok) { - getString(charset[i], buf, &ok); - if (ok) { - eexecCvtGlyph(&eb, buf, val.pos, val.len, &subrIdx, &privateDicts[0]); - } - } - } - eexecWrite(&eb, "end\n"); - eexecWrite(&eb, "end\n"); - eexecWrite(&eb, "readonly put\n"); - eexecWrite(&eb, "noaccess put\n"); - eexecWrite(&eb, "dup /FontName get exch definefont pop\n"); - eexecWrite(&eb, "mark currentfile closefile\n"); - - // trailer - if (ascii && eb.line > 0) { - (*outputFunc)(outputStream, "\n", 1); - } - for (i = 0; i < 8; ++i) { - (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65); - } - (*outputFunc)(outputStream, "cleartomark\n", 12); -} - -void FoFiType1C::convertToCIDType0(char *psName, - FoFiOutputFunc outputFunc, - void *outputStream) { - int *cidMap; - GString *charStrings; - int *charStringOffsets; - Type1CIndex subrIdx; - Type1CIndexVal val; - int nCIDs, gdBytes; - char buf[512], buf2[512]; - GBool ok; - int gid, offset, n, i, j, k; - - // compute the CID count and build the CID-to-GID mapping - nCIDs = 0; - for (i = 0; i < nGlyphs; ++i) { - if (charset[i] >= nCIDs) { - nCIDs = charset[i] + 1; - } - } - cidMap = (int *)gmallocn(nCIDs, sizeof(int)); - for (i = 0; i < nCIDs; ++i) { - cidMap[i] = -1; - } - for (i = 0; i < nGlyphs; ++i) { - cidMap[charset[i]] = i; - } - - // build the charstrings - charStrings = new GString(); - charStringOffsets = (int *)gmallocn(nCIDs + 1, sizeof(int)); - for (i = 0; i < nCIDs; ++i) { - charStringOffsets[i] = charStrings->getLength(); - if ((gid = cidMap[i]) >= 0) { - ok = gTrue; - getIndexVal(&charStringsIdx, gid, &val, &ok); - if (ok) { - getIndex(privateDicts[fdSelect[gid]].subrsOffset, &subrIdx, &ok); - if (!ok) { - subrIdx.pos = -1; - } - cvtGlyph(val.pos, val.len, charStrings, - &subrIdx, &privateDicts[fdSelect[gid]], gTrue); - } - } - } - charStringOffsets[nCIDs] = charStrings->getLength(); - - // compute gdBytes = number of bytes needed for charstring offsets - // (offset size needs to account for the charstring offset table, - // with a worst case of five bytes per entry, plus the charstrings - // themselves) - i = (nCIDs + 1) * 5 + charStrings->getLength(); - if (i < 0x100) { - gdBytes = 1; - } else if (i < 0x10000) { - gdBytes = 2; - } else if (i < 0x1000000) { - gdBytes = 3; - } else { - gdBytes = 4; - } - - // begin the font dictionary - (*outputFunc)(outputStream, "/CIDInit /ProcSet findresource begin\n", 37); - (*outputFunc)(outputStream, "20 dict begin\n", 14); - (*outputFunc)(outputStream, "/CIDFontName /", 14); - (*outputFunc)(outputStream, psName, strlen(psName)); - (*outputFunc)(outputStream, " def\n", 5); - (*outputFunc)(outputStream, "/CIDFontType 0 def\n", 19); - (*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32); - if (topDict.registrySID > 0 && topDict.orderingSID > 0) { - ok = gTrue; - getString(topDict.registrySID, buf, &ok); - if (ok) { - (*outputFunc)(outputStream, " /Registry (", 13); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, ") def\n", 6); - } - ok = gTrue; - getString(topDict.orderingSID, buf, &ok); - if (ok) { - (*outputFunc)(outputStream, " /Ordering (", 13); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, ") def\n", 6); - } - } else { - (*outputFunc)(outputStream, " /Registry (Adobe) def\n", 24); - (*outputFunc)(outputStream, " /Ordering (Identity) def\n", 27); - } - sprintf(buf, " /Supplement %d def\n", topDict.supplement); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, "end def\n", 8); - if (topDict.hasFontMatrix) { - sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n", - topDict.fontMatrix[0], topDict.fontMatrix[1], - topDict.fontMatrix[2], topDict.fontMatrix[3], - topDict.fontMatrix[4], topDict.fontMatrix[5]); - (*outputFunc)(outputStream, buf, strlen(buf)); - } else if (privateDicts[0].hasFontMatrix) { - (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30); - } else { - (*outputFunc)(outputStream, - "/FontMatrix [0.001 0 0 0.001 0 0] def\n", 38); - } - sprintf(buf, "/FontBBox [%g %g %g %g] def\n", - topDict.fontBBox[0], topDict.fontBBox[1], - topDict.fontBBox[2], topDict.fontBBox[3]); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, "/FontInfo 1 dict dup begin\n", 27); - (*outputFunc)(outputStream, " /FSType 8 def\n", 16); - (*outputFunc)(outputStream, "end def\n", 8); - - // CIDFont-specific entries - sprintf(buf, "/CIDCount %d def\n", nCIDs); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, "/FDBytes 1 def\n", 15); - sprintf(buf, "/GDBytes %d def\n", gdBytes); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, "/CIDMapOffset 0 def\n", 20); - if (topDict.paintType != 0) { - sprintf(buf, "/PaintType %d def\n", topDict.paintType); - (*outputFunc)(outputStream, buf, strlen(buf)); - sprintf(buf, "/StrokeWidth %g def\n", topDict.strokeWidth); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - - // FDArray entry - sprintf(buf, "/FDArray %d array\n", nFDs); - (*outputFunc)(outputStream, buf, strlen(buf)); - for (i = 0; i < nFDs; ++i) { - sprintf(buf, "dup %d 10 dict begin\n", i); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, "/FontType 1 def\n", 16); - if (privateDicts[i].hasFontMatrix) { - sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n", - privateDicts[i].fontMatrix[0], - privateDicts[i].fontMatrix[1], - privateDicts[i].fontMatrix[2], - privateDicts[i].fontMatrix[3], - privateDicts[i].fontMatrix[4], - privateDicts[i].fontMatrix[5]); - (*outputFunc)(outputStream, buf, strlen(buf)); - } else { - (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30); - } - sprintf(buf, "/PaintType %d def\n", topDict.paintType); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, "/Private 32 dict begin\n", 23); - if (privateDicts[i].nBlueValues) { - (*outputFunc)(outputStream, "/BlueValues [", 13); - for (j = 0; j < privateDicts[i].nBlueValues; ++j) { - sprintf(buf, "%s%d", j > 0 ? " " : "", privateDicts[i].blueValues[j]); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - (*outputFunc)(outputStream, "] def\n", 6); - } - if (privateDicts[i].nOtherBlues) { - (*outputFunc)(outputStream, "/OtherBlues [", 13); - for (j = 0; j < privateDicts[i].nOtherBlues; ++j) { - sprintf(buf, "%s%d", j > 0 ? " " : "", privateDicts[i].otherBlues[j]); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - (*outputFunc)(outputStream, "] def\n", 6); - } - if (privateDicts[i].nFamilyBlues) { - (*outputFunc)(outputStream, "/FamilyBlues [", 14); - for (j = 0; j < privateDicts[i].nFamilyBlues; ++j) { - sprintf(buf, "%s%d", j > 0 ? " " : "", privateDicts[i].familyBlues[j]); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - (*outputFunc)(outputStream, "] def\n", 6); - } - if (privateDicts[i].nFamilyOtherBlues) { - (*outputFunc)(outputStream, "/FamilyOtherBlues [", 19); - for (j = 0; j < privateDicts[i].nFamilyOtherBlues; ++j) { - sprintf(buf, "%s%d", j > 0 ? " " : "", - privateDicts[i].familyOtherBlues[j]); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - (*outputFunc)(outputStream, "] def\n", 6); - } - if (privateDicts[i].blueScale != 0.039625) { - sprintf(buf, "/BlueScale %g def\n", privateDicts[i].blueScale); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - if (privateDicts[i].blueShift != 7) { - sprintf(buf, "/BlueShift %d def\n", privateDicts[i].blueShift); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - if (privateDicts[i].blueFuzz != 1) { - sprintf(buf, "/BlueFuzz %d def\n", privateDicts[i].blueFuzz); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - if (privateDicts[i].hasStdHW) { - sprintf(buf, "/StdHW [%g] def\n", privateDicts[i].stdHW); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - if (privateDicts[i].hasStdVW) { - sprintf(buf, "/StdVW [%g] def\n", privateDicts[i].stdVW); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - if (privateDicts[i].nStemSnapH) { - (*outputFunc)(outputStream, "/StemSnapH [", 12); - for (j = 0; j < privateDicts[i].nStemSnapH; ++j) { - sprintf(buf, "%s%g", j > 0 ? " " : "", privateDicts[i].stemSnapH[j]); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - (*outputFunc)(outputStream, "] def\n", 6); - } - if (privateDicts[i].nStemSnapV) { - (*outputFunc)(outputStream, "/StemSnapV [", 12); - for (j = 0; j < privateDicts[i].nStemSnapV; ++j) { - sprintf(buf, "%s%g", j > 0 ? " " : "", privateDicts[i].stemSnapV[j]); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - (*outputFunc)(outputStream, "] def\n", 6); - } - if (privateDicts[i].hasForceBold) { - sprintf(buf, "/ForceBold %s def\n", - privateDicts[i].forceBold ? "true" : "false"); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - if (privateDicts[i].forceBoldThreshold != 0) { - sprintf(buf, "/ForceBoldThreshold %g def\n", - privateDicts[i].forceBoldThreshold); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - if (privateDicts[i].languageGroup != 0) { - sprintf(buf, "/LanguageGroup %d def\n", privateDicts[i].languageGroup); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - if (privateDicts[i].expansionFactor != 0.06) { - sprintf(buf, "/ExpansionFactor %g def\n", - privateDicts[i].expansionFactor); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - (*outputFunc)(outputStream, "currentdict end def\n", 20); - (*outputFunc)(outputStream, "currentdict end put\n", 20); - } - (*outputFunc)(outputStream, "def\n", 4); - - // start the binary section - offset = (nCIDs + 1) * (1 + gdBytes); - sprintf(buf, "(Hex) %d StartData\n", - offset + charStrings->getLength()); - (*outputFunc)(outputStream, buf, strlen(buf)); - - // write the charstring offset (CIDMap) table - for (i = 0; i <= nCIDs; i += 6) { - for (j = 0; j < 6 && i+j <= nCIDs; ++j) { - if (i+j < nCIDs && cidMap[i+j] >= 0) { - buf[0] = (char)fdSelect[cidMap[i+j]]; - } else { - buf[0] = (char)0; - } - n = offset + charStringOffsets[i+j]; - for (k = gdBytes; k >= 1; --k) { - buf[k] = (char)(n & 0xff); - n >>= 8; - } - for (k = 0; k <= gdBytes; ++k) { - sprintf(buf2, "%02x", buf[k] & 0xff); - (*outputFunc)(outputStream, buf2, 2); - } - } - (*outputFunc)(outputStream, "\n", 1); - } - - // write the charstring data - n = charStrings->getLength(); - for (i = 0; i < n; i += 32) { - for (j = 0; j < 32 && i+j < n; ++j) { - sprintf(buf, "%02x", charStrings->getChar(i+j) & 0xff); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - if (i + 32 >= n) { - (*outputFunc)(outputStream, ">", 1); - } - (*outputFunc)(outputStream, "\n", 1); - } - - gfree(charStringOffsets); - delete charStrings; - gfree(cidMap); -} - -void FoFiType1C::convertToType0(char *psName, - FoFiOutputFunc outputFunc, - void *outputStream) { - int *cidMap; - Type1CIndex subrIdx; - Type1CIndexVal val; - int nCIDs; - char buf[512]; - Type1CEexecBuf eb; - GBool ok; - int fd, i, j, k; - - // compute the CID count and build the CID-to-GID mapping - nCIDs = 0; - for (i = 0; i < nGlyphs; ++i) { - if (charset[i] >= nCIDs) { - nCIDs = charset[i] + 1; - } - } - cidMap = (int *)gmallocn(nCIDs, sizeof(int)); - for (i = 0; i < nCIDs; ++i) { - cidMap[i] = -1; - } - for (i = 0; i < nGlyphs; ++i) { - cidMap[charset[i]] = i; - } - - // write the descendant Type 1 fonts - for (i = 0; i < nCIDs; i += 256) { - - //~ this assumes that all CIDs in this block have the same FD -- - //~ to handle multiple FDs correctly, need to somehow divide the - //~ font up by FD - fd = 0; - for (j = 0; j < 256 && i+j < nCIDs; ++j) { - if (cidMap[i+j] >= 0) { - fd = fdSelect[cidMap[i+j]]; - break; - } - } - - // font dictionary (unencrypted section) - (*outputFunc)(outputStream, "16 dict begin\n", 14); - (*outputFunc)(outputStream, "/FontName /", 11); - (*outputFunc)(outputStream, psName, strlen(psName)); - sprintf(buf, "_%02x def\n", i >> 8); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, "/FontType 1 def\n", 16); - if (privateDicts[fd].hasFontMatrix) { - sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n", - privateDicts[fd].fontMatrix[0], - privateDicts[fd].fontMatrix[1], - privateDicts[fd].fontMatrix[2], - privateDicts[fd].fontMatrix[3], - privateDicts[fd].fontMatrix[4], - privateDicts[fd].fontMatrix[5]); - (*outputFunc)(outputStream, buf, strlen(buf)); - } else if (topDict.hasFontMatrix) { - (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30); - } else { - (*outputFunc)(outputStream, - "/FontMatrix [0.001 0 0 0.001 0 0] def\n", 38); - } - sprintf(buf, "/FontBBox [%g %g %g %g] def\n", - topDict.fontBBox[0], topDict.fontBBox[1], - topDict.fontBBox[2], topDict.fontBBox[3]); - (*outputFunc)(outputStream, buf, strlen(buf)); - sprintf(buf, "/PaintType %d def\n", topDict.paintType); - (*outputFunc)(outputStream, buf, strlen(buf)); - if (topDict.paintType != 0) { - sprintf(buf, "/StrokeWidth %g def\n", topDict.strokeWidth); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - (*outputFunc)(outputStream, "/Encoding 256 array\n", 20); - for (j = 0; j < 256 && i+j < nCIDs; ++j) { - sprintf(buf, "dup %d /c%02x put\n", j, j); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - if (j < 256) { - sprintf(buf, "%d 1 255 { 1 index exch /.notdef put } for\n", j); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - (*outputFunc)(outputStream, "readonly def\n", 13); - (*outputFunc)(outputStream, "currentdict end\n", 16); - - // start the binary section - (*outputFunc)(outputStream, "currentfile eexec\n", 18); - eb.outputFunc = outputFunc; - eb.outputStream = outputStream; - eb.ascii = gTrue; - eb.r1 = 55665; - eb.line = 0; - - // start the private dictionary - eexecWrite(&eb, "\x83\xca\x73\xd5"); - eexecWrite(&eb, "dup /Private 32 dict dup begin\n"); - eexecWrite(&eb, "/RD {string currentfile exch readstring pop}" - " executeonly def\n"); - eexecWrite(&eb, "/ND {noaccess def} executeonly def\n"); - eexecWrite(&eb, "/NP {noaccess put} executeonly def\n"); - eexecWrite(&eb, "/MinFeature {16 16} def\n"); - eexecWrite(&eb, "/password 5839 def\n"); - if (privateDicts[fd].nBlueValues) { - eexecWrite(&eb, "/BlueValues ["); - for (k = 0; k < privateDicts[fd].nBlueValues; ++k) { - sprintf(buf, "%s%d", k > 0 ? " " : "", privateDicts[fd].blueValues[k]); - eexecWrite(&eb, buf); - } - eexecWrite(&eb, "] def\n"); - } - if (privateDicts[fd].nOtherBlues) { - eexecWrite(&eb, "/OtherBlues ["); - for (k = 0; k < privateDicts[fd].nOtherBlues; ++k) { - sprintf(buf, "%s%d", k > 0 ? " " : "", privateDicts[fd].otherBlues[k]); - eexecWrite(&eb, buf); - } - eexecWrite(&eb, "] def\n"); - } - if (privateDicts[fd].nFamilyBlues) { - eexecWrite(&eb, "/FamilyBlues ["); - for (k = 0; k < privateDicts[fd].nFamilyBlues; ++k) { - sprintf(buf, "%s%d", k > 0 ? " " : "", - privateDicts[fd].familyBlues[k]); - eexecWrite(&eb, buf); - } - eexecWrite(&eb, "] def\n"); - } - if (privateDicts[fd].nFamilyOtherBlues) { - eexecWrite(&eb, "/FamilyOtherBlues ["); - for (k = 0; k < privateDicts[fd].nFamilyOtherBlues; ++k) { - sprintf(buf, "%s%d", k > 0 ? " " : "", - privateDicts[fd].familyOtherBlues[k]); - eexecWrite(&eb, buf); - } - eexecWrite(&eb, "] def\n"); - } - if (privateDicts[fd].blueScale != 0.039625) { - sprintf(buf, "/BlueScale %g def\n", privateDicts[fd].blueScale); - eexecWrite(&eb, buf); - } - if (privateDicts[fd].blueShift != 7) { - sprintf(buf, "/BlueShift %d def\n", privateDicts[fd].blueShift); - eexecWrite(&eb, buf); - } - if (privateDicts[fd].blueFuzz != 1) { - sprintf(buf, "/BlueFuzz %d def\n", privateDicts[fd].blueFuzz); - eexecWrite(&eb, buf); - } - if (privateDicts[fd].hasStdHW) { - sprintf(buf, "/StdHW [%g] def\n", privateDicts[fd].stdHW); - eexecWrite(&eb, buf); - } - if (privateDicts[fd].hasStdVW) { - sprintf(buf, "/StdVW [%g] def\n", privateDicts[fd].stdVW); - eexecWrite(&eb, buf); - } - if (privateDicts[fd].nStemSnapH) { - eexecWrite(&eb, "/StemSnapH ["); - for (k = 0; k < privateDicts[fd].nStemSnapH; ++k) { - sprintf(buf, "%s%g", k > 0 ? " " : "", privateDicts[fd].stemSnapH[k]); - eexecWrite(&eb, buf); - } - eexecWrite(&eb, "] def\n"); - } - if (privateDicts[fd].nStemSnapV) { - eexecWrite(&eb, "/StemSnapV ["); - for (k = 0; k < privateDicts[fd].nStemSnapV; ++k) { - sprintf(buf, "%s%g", k > 0 ? " " : "", privateDicts[fd].stemSnapV[k]); - eexecWrite(&eb, buf); - } - eexecWrite(&eb, "] def\n"); - } - if (privateDicts[fd].hasForceBold) { - sprintf(buf, "/ForceBold %s def\n", - privateDicts[fd].forceBold ? "true" : "false"); - eexecWrite(&eb, buf); - } - if (privateDicts[fd].forceBoldThreshold != 0) { - sprintf(buf, "/ForceBoldThreshold %g def\n", - privateDicts[fd].forceBoldThreshold); - eexecWrite(&eb, buf); - } - if (privateDicts[fd].languageGroup != 0) { - sprintf(buf, "/LanguageGroup %d def\n", privateDicts[fd].languageGroup); - eexecWrite(&eb, buf); - } - if (privateDicts[fd].expansionFactor != 0.06) { - sprintf(buf, "/ExpansionFactor %g def\n", - privateDicts[fd].expansionFactor); - eexecWrite(&eb, buf); - } - - // set up the subroutines - ok = gTrue; - getIndex(privateDicts[fd].subrsOffset, &subrIdx, &ok); - if (!ok) { - subrIdx.pos = -1; - } - - // start the CharStrings - sprintf(buf, "2 index /CharStrings 256 dict dup begin\n"); - eexecWrite(&eb, buf); - - // write the .notdef CharString - ok = gTrue; - getIndexVal(&charStringsIdx, 0, &val, &ok); - if (ok) { - eexecCvtGlyph(&eb, ".notdef", val.pos, val.len, - &subrIdx, &privateDicts[fd]); - } - - // write the CharStrings - for (j = 0; j < 256 && i+j < nCIDs; ++j) { - if (cidMap[i+j] >= 0) { - ok = gTrue; - getIndexVal(&charStringsIdx, cidMap[i+j], &val, &ok); - if (ok) { - sprintf(buf, "c%02x", j); - eexecCvtGlyph(&eb, buf, val.pos, val.len, - &subrIdx, &privateDicts[fd]); - } - } - } - eexecWrite(&eb, "end\n"); - eexecWrite(&eb, "end\n"); - eexecWrite(&eb, "readonly put\n"); - eexecWrite(&eb, "noaccess put\n"); - eexecWrite(&eb, "dup /FontName get exch definefont pop\n"); - eexecWrite(&eb, "mark currentfile closefile\n"); - - // trailer - if (eb.line > 0) { - (*outputFunc)(outputStream, "\n", 1); - } - for (j = 0; j < 8; ++j) { - (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65); - } - (*outputFunc)(outputStream, "cleartomark\n", 12); - } - - // write the Type 0 parent font - (*outputFunc)(outputStream, "16 dict begin\n", 14); - (*outputFunc)(outputStream, "/FontName /", 11); - (*outputFunc)(outputStream, psName, strlen(psName)); - (*outputFunc)(outputStream, " def\n", 5); - (*outputFunc)(outputStream, "/FontType 0 def\n", 16); - if (topDict.hasFontMatrix) { - sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n", - topDict.fontMatrix[0], topDict.fontMatrix[1], - topDict.fontMatrix[2], topDict.fontMatrix[3], - topDict.fontMatrix[4], topDict.fontMatrix[5]); - (*outputFunc)(outputStream, buf, strlen(buf)); - } else { - (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30); - } - (*outputFunc)(outputStream, "/FMapType 2 def\n", 16); - (*outputFunc)(outputStream, "/Encoding [\n", 12); - for (i = 0; i < nCIDs; i += 256) { - sprintf(buf, "%d\n", i >> 8); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - (*outputFunc)(outputStream, "] def\n", 6); - (*outputFunc)(outputStream, "/FDepVector [\n", 14); - for (i = 0; i < nCIDs; i += 256) { - (*outputFunc)(outputStream, "/", 1); - (*outputFunc)(outputStream, psName, strlen(psName)); - sprintf(buf, "_%02x findfont\n", i >> 8); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - (*outputFunc)(outputStream, "] def\n", 6); - (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40); - - gfree(cidMap); -} - -void FoFiType1C::eexecCvtGlyph(Type1CEexecBuf *eb, char *glyphName, - int offset, int nBytes, - Type1CIndex *subrIdx, - Type1CPrivateDict *pDict) { - char buf[512]; - GString *charBuf; - - // generate the charstring - charBuf = new GString(); - cvtGlyph(offset, nBytes, charBuf, subrIdx, pDict, gTrue); - - sprintf(buf, "/%s %d RD ", glyphName, charBuf->getLength()); - eexecWrite(eb, buf); - eexecWriteCharstring(eb, (Guchar *)charBuf->getCString(), - charBuf->getLength()); - eexecWrite(eb, " ND\n"); - - delete charBuf; -} - -void FoFiType1C::cvtGlyph(int offset, int nBytes, GString *charBuf, - Type1CIndex *subrIdx, Type1CPrivateDict *pDict, - GBool top) { - Type1CIndexVal val; - GBool ok, dFP; - double d, dx, dy; - Gushort r2; - Guchar byte; - int pos, subrBias, start, i, k; - - start = charBuf->getLength(); - if (top) { - charBuf->append((char)73); - charBuf->append((char)58); - charBuf->append((char)147); - charBuf->append((char)134); - nOps = 0; - nHints = 0; - firstOp = gTrue; - openPath = gFalse; - } - - pos = offset; - while (pos < offset + nBytes) { - ok = gTrue; - pos = getOp(pos, gTrue, &ok); - if (!ok) { - break; - } - if (!ops[nOps - 1].isNum) { - --nOps; // drop the operator - switch (ops[nOps].op) { - case 0x0001: // hstem - if (firstOp) { - cvtGlyphWidth(nOps & 1, charBuf, pDict); - firstOp = 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) { - // convert Type 2 edge hints (-20 or -21) to Type 1 ghost hints - if (ops[k+1].num < 0) { - d += ops[k].num + ops[k+1].num; - dFP |= ops[k].isFP | ops[k+1].isFP; - cvtNum(d, dFP, charBuf); - cvtNum(-ops[k+1].num, ops[k+1].isFP, charBuf); - } else { - d += ops[k].num; - dFP |= ops[k].isFP; - cvtNum(d, dFP, charBuf); - cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); - d += ops[k+1].num; - dFP |= ops[k+1].isFP; - } - charBuf->append((char)1); - } - nHints += nOps / 2; - nOps = 0; - break; - case 0x0003: // vstem - if (firstOp) { - cvtGlyphWidth(nOps & 1, charBuf, pDict); - firstOp = 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) { - // convert Type 2 edge hints (-20 or -21) to Type 1 ghost hints - if (ops[k+1].num < 0) { - d += ops[k].num + ops[k+1].num; - dFP |= ops[k].isFP | ops[k+1].isFP; - cvtNum(d, dFP, charBuf); - cvtNum(-ops[k+1].num, ops[k+1].isFP, charBuf); - } else { - d += ops[k].num; - dFP |= ops[k].isFP; - cvtNum(d, dFP, charBuf); - cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); - d += ops[k+1].num; - dFP |= ops[k+1].isFP; - } - charBuf->append((char)3); - } - nHints += nOps / 2; - nOps = 0; - break; - case 0x0004: // vmoveto - if (firstOp) { - cvtGlyphWidth(nOps == 2, charBuf, pDict); - firstOp = gFalse; - } - if (openPath) { - charBuf->append((char)9); - openPath = gFalse; - } - if (nOps != 1) { - //~ error(-1, "Wrong number of args (%d) to Type 2 vmoveto", nOps); - } - cvtNum(ops[0].num, ops[0].isFP, charBuf); - charBuf->append((char)4); - nOps = 0; - break; - case 0x0005: // 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) { - cvtNum(ops[k].num, ops[k].isFP, charBuf); - cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); - charBuf->append((char)5); - } - nOps = 0; - openPath = gTrue; - break; - case 0x0006: // hlineto - if (nOps < 1) { - //~ error(-1, "Wrong number of args (%d) to Type 2 hlineto", nOps); - } - for (k = 0; k < nOps; ++k) { - cvtNum(ops[k].num, ops[k].isFP, charBuf); - charBuf->append((char)((k & 1) ? 7 : 6)); - } - nOps = 0; - openPath = gTrue; - break; - case 0x0007: // vlineto - if (nOps < 1) { - //~ error(-1, "Wrong number of args (%d) to Type 2 vlineto", nOps); - } - for (k = 0; k < nOps; ++k) { - cvtNum(ops[k].num, ops[k].isFP, charBuf); - charBuf->append((char)((k & 1) ? 6 : 7)); - } - nOps = 0; - openPath = gTrue; - break; - case 0x0008: // 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) { - cvtNum(ops[k].num, ops[k].isFP, charBuf); - cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); - cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf); - cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf); - cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf); - cvtNum(ops[k+5].num, ops[k+5].isFP, charBuf); - charBuf->append((char)8); - } - nOps = 0; - openPath = gTrue; - break; - case 0x000a: // callsubr - if (nOps >= 1) { - subrBias = (subrIdx->len < 1240) - ? 107 : (subrIdx->len < 33900) ? 1131 : 32768; - k = subrBias + (int)ops[nOps - 1].num; - --nOps; - ok = gTrue; - getIndexVal(subrIdx, k, &val, &ok); - if (ok) { - cvtGlyph(val.pos, val.len, charBuf, subrIdx, pDict, gFalse); - } - } else { - //~ error(-1, "Too few args to Type 2 callsubr"); - } - // don't clear the stack - break; - case 0x000b: // return - // don't clear the stack - break; - case 0x000e: // endchar / seac - if (firstOp) { - cvtGlyphWidth(nOps == 1 || nOps == 5, charBuf, pDict); - firstOp = gFalse; - } - if (openPath) { - charBuf->append((char)9); - openPath = gFalse; - } - if (nOps == 4) { - cvtNum(0, gFalse, charBuf); - cvtNum(ops[0].num, ops[0].isFP, charBuf); - cvtNum(ops[1].num, ops[1].isFP, charBuf); - cvtNum(ops[2].num, ops[2].isFP, charBuf); - cvtNum(ops[3].num, ops[3].isFP, charBuf); - charBuf->append((char)12)->append((char)6); - } else if (nOps == 0) { - charBuf->append((char)14); - } else { - //~ error(-1, "Wrong number of args (%d) to Type 2 endchar", nOps); - } - nOps = 0; - break; - case 0x000f: // (obsolete) - // this op is ignored, but we need the glyph width - if (firstOp) { - cvtGlyphWidth(nOps > 0, charBuf, pDict); - firstOp = gFalse; - } - nOps = 0; - break; - case 0x0010: // blend - //~ error(-1, "Unimplemented Type 2 charstring op: %d", file[i]); - nOps = 0; - break; - case 0x0012: // hstemhm - // ignored - if (firstOp) { - cvtGlyphWidth(nOps & 1, charBuf, pDict); - firstOp = gFalse; - } - if (nOps & 1) { - //~ error(-1, "Wrong number of args (%d) to Type 2 hstemhm", nOps); - } - nHints += nOps / 2; - nOps = 0; - break; - case 0x0013: // hintmask - // ignored - if (firstOp) { - cvtGlyphWidth(nOps & 1, charBuf, pDict); - firstOp = gFalse; - } - if (nOps > 0) { - if (nOps & 1) { - //~ error(-1, "Wrong number of args (%d) to Type 2 hintmask/vstemhm", - //~ nOps); - } - nHints += nOps / 2; - } - pos += (nHints + 7) >> 3; - nOps = 0; - break; - case 0x0014: // cntrmask - // ignored - if (firstOp) { - cvtGlyphWidth(nOps & 1, charBuf, pDict); - firstOp = gFalse; - } - if (nOps > 0) { - if (nOps & 1) { - //~ error(-1, "Wrong number of args (%d) to Type 2 cntrmask/vstemhm", - //~ nOps); - } - nHints += nOps / 2; - } - pos += (nHints + 7) >> 3; - nOps = 0; - break; - case 0x0015: // rmoveto - if (firstOp) { - cvtGlyphWidth(nOps == 3, charBuf, pDict); - firstOp = gFalse; - } - if (openPath) { - charBuf->append((char)9); - openPath = gFalse; - } - if (nOps != 2) { - //~ error(-1, "Wrong number of args (%d) to Type 2 rmoveto", nOps); - } - cvtNum(ops[0].num, ops[0].isFP, charBuf); - cvtNum(ops[1].num, ops[1].isFP, charBuf); - charBuf->append((char)21); - nOps = 0; - break; - case 0x0016: // hmoveto - if (firstOp) { - cvtGlyphWidth(nOps == 2, charBuf, pDict); - firstOp = gFalse; - } - if (openPath) { - charBuf->append((char)9); - openPath = gFalse; - } - if (nOps != 1) { - //~ error(-1, "Wrong number of args (%d) to Type 2 hmoveto", nOps); - } - cvtNum(ops[0].num, ops[0].isFP, charBuf); - charBuf->append((char)22); - nOps = 0; - break; - case 0x0017: // vstemhm - // ignored - if (firstOp) { - cvtGlyphWidth(nOps & 1, charBuf, pDict); - firstOp = gFalse; - } - if (nOps & 1) { - //~ error(-1, "Wrong number of args (%d) to Type 2 vstemhm", nOps); - } - nHints += nOps / 2; - nOps = 0; - break; - case 0x0018: // 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) { - cvtNum(ops[k].num, ops[k].isFP, charBuf); - cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); - cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf); - cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf); - cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf); - cvtNum(ops[k+5].num, ops[k+5].isFP, charBuf); - charBuf->append((char)8); - } - cvtNum(ops[k].num, ops[k].isFP, charBuf); - cvtNum(ops[k+1].num, ops[k].isFP, charBuf); - charBuf->append((char)5); - nOps = 0; - openPath = gTrue; - break; - case 0x0019: // 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) { - cvtNum(ops[k].num, ops[k].isFP, charBuf); - cvtNum(ops[k+1].num, ops[k].isFP, charBuf); - charBuf->append((char)5); - } - cvtNum(ops[k].num, ops[k].isFP, charBuf); - cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); - cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf); - cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf); - cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf); - cvtNum(ops[k+5].num, ops[k+5].isFP, charBuf); - charBuf->append((char)8); - nOps = 0; - openPath = gTrue; - break; - case 0x001a: // 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) { - cvtNum(ops[0].num, ops[0].isFP, charBuf); - cvtNum(ops[1].num, ops[1].isFP, charBuf); - cvtNum(ops[2].num, ops[2].isFP, charBuf); - cvtNum(ops[3].num, ops[3].isFP, charBuf); - cvtNum(0, gFalse, charBuf); - cvtNum(ops[4].num, ops[4].isFP, charBuf); - charBuf->append((char)8); - k = 5; - } else { - k = 0; - } - for (; k < nOps; k += 4) { - cvtNum(0, gFalse, charBuf); - cvtNum(ops[k].num, ops[k].isFP, charBuf); - cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); - cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf); - cvtNum(0, gFalse, charBuf); - cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf); - charBuf->append((char)8); - } - nOps = 0; - openPath = gTrue; - break; - case 0x001b: // 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) { - cvtNum(ops[1].num, ops[1].isFP, charBuf); - cvtNum(ops[0].num, ops[0].isFP, charBuf); - cvtNum(ops[2].num, ops[2].isFP, charBuf); - cvtNum(ops[3].num, ops[3].isFP, charBuf); - cvtNum(ops[4].num, ops[4].isFP, charBuf); - cvtNum(0, gFalse, charBuf); - charBuf->append((char)8); - k = 5; - } else { - k = 0; - } - for (; k < nOps; k += 4) { - cvtNum(ops[k].num, ops[k].isFP, charBuf); - cvtNum(0, gFalse, charBuf); - cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); - cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf); - cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf); - cvtNum(0, gFalse, charBuf); - charBuf->append((char)8); - } - nOps = 0; - openPath = gTrue; - break; - case 0x001d: // callgsubr - if (nOps >= 1) { - k = gsubrBias + (int)ops[nOps - 1].num; - --nOps; - ok = gTrue; - getIndexVal(&gsubrIdx, k, &val, &ok); - if (ok) { - cvtGlyph(val.pos, val.len, charBuf, subrIdx, pDict, gFalse); - } - } else { - //~ error(-1, "Too few args to Type 2 callgsubr"); - } - // don't clear the stack - break; - case 0x001e: // 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) { - cvtNum(ops[k].num, ops[k].isFP, charBuf); - cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); - cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf); - cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf); - charBuf->append((char)30); - } else { - cvtNum(ops[k].num, ops[k].isFP, charBuf); - cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); - cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf); - cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf); - charBuf->append((char)31); - } - } - if (k == nOps-5) { - if (k % 8 == 0) { - cvtNum(0, gFalse, charBuf); - cvtNum(ops[k].num, ops[k].isFP, charBuf); - cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); - cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf); - cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf); - cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf); - } else { - cvtNum(ops[k].num, ops[k].isFP, charBuf); - cvtNum(0, gFalse, charBuf); - cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); - cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf); - cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf); - cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf); - } - charBuf->append((char)8); - } - nOps = 0; - openPath = gTrue; - break; - case 0x001f: // 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) { - cvtNum(ops[k].num, ops[k].isFP, charBuf); - cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); - cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf); - cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf); - charBuf->append((char)31); - } else { - cvtNum(ops[k].num, ops[k].isFP, charBuf); - cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); - cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf); - cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf); - charBuf->append((char)30); - } - } - if (k == nOps-5) { - if (k % 8 == 0) { - cvtNum(ops[k].num, ops[k].isFP, charBuf); - cvtNum(0, gFalse, charBuf); - cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); - cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf); - cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf); - cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf); - } else { - cvtNum(0, gFalse, charBuf); - cvtNum(ops[k].num, ops[k].isFP, charBuf); - cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); - cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf); - cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf); - cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf); - } - charBuf->append((char)8); - } - nOps = 0; - openPath = gTrue; - break; - case 0x0c00: // dotsection (should be Type 1 only?) - // ignored - nOps = 0; - break; - case 0x0c03: // and - case 0x0c04: // or - case 0x0c05: // not - case 0x0c08: // store - case 0x0c09: // abs - case 0x0c0a: // add - case 0x0c0b: // sub - case 0x0c0c: // div - case 0x0c0d: // load - case 0x0c0e: // neg - case 0x0c0f: // eq - case 0x0c12: // drop - case 0x0c14: // put - case 0x0c15: // get - case 0x0c16: // ifelse - case 0x0c17: // random - case 0x0c18: // mul - case 0x0c1a: // sqrt - case 0x0c1b: // dup - case 0x0c1c: // exch - case 0x0c1d: // index - case 0x0c1e: // roll - //~ error(-1, "Unimplemented Type 2 charstring op: 12.%d", file[i+1]); - nOps = 0; - break; - case 0x0c22: // hflex - if (nOps != 7) { - //~ error(-1, "Wrong number of args (%d) to Type 2 hflex", nOps); - } - cvtNum(ops[0].num, ops[0].isFP, charBuf); - cvtNum(0, gFalse, charBuf); - cvtNum(ops[1].num, ops[1].isFP, charBuf); - cvtNum(ops[2].num, ops[2].isFP, charBuf); - cvtNum(ops[3].num, ops[3].isFP, charBuf); - cvtNum(0, gFalse, charBuf); - charBuf->append((char)8); - cvtNum(ops[4].num, ops[4].isFP, charBuf); - cvtNum(0, gFalse, charBuf); - cvtNum(ops[5].num, ops[5].isFP, charBuf); - cvtNum(-ops[2].num, ops[2].isFP, charBuf); - cvtNum(ops[6].num, ops[6].isFP, charBuf); - cvtNum(0, gFalse, charBuf); - charBuf->append((char)8); - nOps = 0; - openPath = gTrue; - break; - case 0x0c23: // flex - if (nOps != 13) { - //~ error(-1, "Wrong number of args (%d) to Type 2 flex", nOps); - } - cvtNum(ops[0].num, ops[0].isFP, charBuf); - cvtNum(ops[1].num, ops[1].isFP, charBuf); - cvtNum(ops[2].num, ops[2].isFP, charBuf); - cvtNum(ops[3].num, ops[3].isFP, charBuf); - cvtNum(ops[4].num, ops[4].isFP, charBuf); - cvtNum(ops[5].num, ops[5].isFP, charBuf); - charBuf->append((char)8); - cvtNum(ops[6].num, ops[6].isFP, charBuf); - cvtNum(ops[7].num, ops[7].isFP, charBuf); - cvtNum(ops[8].num, ops[8].isFP, charBuf); - cvtNum(ops[9].num, ops[9].isFP, charBuf); - cvtNum(ops[10].num, ops[10].isFP, charBuf); - cvtNum(ops[11].num, ops[11].isFP, charBuf); - charBuf->append((char)8); - nOps = 0; - openPath = gTrue; - break; - case 0x0c24: // hflex1 - if (nOps != 9) { - //~ error(-1, "Wrong number of args (%d) to Type 2 hflex1", nOps); - } - cvtNum(ops[0].num, ops[0].isFP, charBuf); - cvtNum(ops[1].num, ops[1].isFP, charBuf); - cvtNum(ops[2].num, ops[2].isFP, charBuf); - cvtNum(ops[3].num, ops[3].isFP, charBuf); - cvtNum(ops[4].num, ops[4].isFP, charBuf); - cvtNum(0, gFalse, charBuf); - charBuf->append((char)8); - cvtNum(ops[5].num, ops[5].isFP, charBuf); - cvtNum(0, gFalse, charBuf); - cvtNum(ops[6].num, ops[6].isFP, charBuf); - cvtNum(ops[7].num, ops[7].isFP, charBuf); - cvtNum(ops[8].num, ops[8].isFP, charBuf); - cvtNum(-(ops[1].num + ops[3].num + ops[7].num), - ops[1].isFP | ops[3].isFP | ops[7].isFP, charBuf); - charBuf->append((char)8); - nOps = 0; - openPath = gTrue; - break; - case 0x0c25: // flex1 - if (nOps != 11) { - //~ error(-1, "Wrong number of args (%d) to Type 2 flex1", nOps); - } - cvtNum(ops[0].num, ops[0].isFP, charBuf); - cvtNum(ops[1].num, ops[1].isFP, charBuf); - cvtNum(ops[2].num, ops[2].isFP, charBuf); - cvtNum(ops[3].num, ops[3].isFP, charBuf); - cvtNum(ops[4].num, ops[4].isFP, charBuf); - cvtNum(ops[5].num, ops[5].isFP, charBuf); - charBuf->append((char)8); - cvtNum(ops[6].num, ops[6].isFP, charBuf); - cvtNum(ops[7].num, ops[7].isFP, charBuf); - cvtNum(ops[8].num, ops[8].isFP, charBuf); - cvtNum(ops[9].num, ops[9].isFP, charBuf); - dx = ops[0].num + ops[2].num + ops[4].num + ops[6].num + ops[8].num; - dy = ops[1].num + ops[3].num + ops[5].num + ops[7].num + ops[9].num; - if (fabs(dx) > fabs(dy)) { - cvtNum(ops[10].num, ops[10].isFP, charBuf); - cvtNum(-dy, ops[1].isFP | ops[3].isFP | ops[5].isFP | - ops[7].isFP | ops[9].isFP, charBuf); - } else { - cvtNum(-dx, ops[0].isFP | ops[2].isFP | ops[4].isFP | - ops[6].isFP | ops[8].isFP, charBuf); - cvtNum(ops[10].num, ops[10].isFP, charBuf); - } - charBuf->append((char)8); - nOps = 0; - openPath = gTrue; - break; - default: - //~ error(-1, "Illegal Type 2 charstring op: %04x", - //~ ops[nOps].op); - nOps = 0; - break; - } - } - } - - // charstring encryption - if (top) { - r2 = 4330; - for (i = start; i < charBuf->getLength(); ++i) { - byte = charBuf->getChar(i) ^ (r2 >> 8); - charBuf->setChar(i, byte); - r2 = (byte + r2) * 52845 + 22719; - } - } -} - -void FoFiType1C::cvtGlyphWidth(GBool useOp, GString *charBuf, - Type1CPrivateDict *pDict) { - double w; - GBool wFP; - int i; - - if (useOp) { - w = pDict->nominalWidthX + ops[0].num; - wFP = pDict->nominalWidthXFP | ops[0].isFP; - for (i = 1; i < nOps; ++i) { - ops[i-1] = ops[i]; - } - --nOps; - } else { - w = pDict->defaultWidthX; - wFP = pDict->defaultWidthXFP; - } - cvtNum(0, gFalse, charBuf); - cvtNum(w, wFP, charBuf); - charBuf->append((char)13); -} - -void FoFiType1C::cvtNum(double x, GBool isFP, GString *charBuf) { - Guchar buf[12]; - int y, n; - - n = 0; - if (isFP) { - 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 FoFiType1C::eexecWrite(Type1CEexecBuf *eb, char *s) { - Guchar *p; - Guchar x; - - for (p = (Guchar *)s; *p; ++p) { - x = *p ^ (eb->r1 >> 8); - eb->r1 = (x + eb->r1) * 52845 + 22719; - if (eb->ascii) { - (*eb->outputFunc)(eb->outputStream, &hexChars[x >> 4], 1); - (*eb->outputFunc)(eb->outputStream, &hexChars[x & 0x0f], 1); - eb->line += 2; - if (eb->line == 64) { - (*eb->outputFunc)(eb->outputStream, "\n", 1); - eb->line = 0; - } - } else { - (*eb->outputFunc)(eb->outputStream, (char *)&x, 1); - } - } -} - -void FoFiType1C::eexecWriteCharstring(Type1CEexecBuf *eb, - Guchar *s, int n) { - Guchar x; - int i; - - // eexec encryption - for (i = 0; i < n; ++i) { - x = s[i] ^ (eb->r1 >> 8); - eb->r1 = (x + eb->r1) * 52845 + 22719; - if (eb->ascii) { - (*eb->outputFunc)(eb->outputStream, &hexChars[x >> 4], 1); - (*eb->outputFunc)(eb->outputStream, &hexChars[x & 0x0f], 1); - eb->line += 2; - if (eb->line == 64) { - (*eb->outputFunc)(eb->outputStream, "\n", 1); - eb->line = 0; - } - } else { - (*eb->outputFunc)(eb->outputStream, (char *)&x, 1); - } - } -} - -GBool FoFiType1C::parse() { - Type1CIndex fdIdx; - Type1CIndexVal val; - int i; - - parsedOk = gTrue; - - // some tools embed Type 1C fonts with an extra whitespace char at - // the beginning - if (len > 0 && file[0] != '\x01') { - ++file; - --len; - } - - // find the indexes - getIndex(getU8(2, &parsedOk), &nameIdx, &parsedOk); - getIndex(nameIdx.endPos, &topDictIdx, &parsedOk); - getIndex(topDictIdx.endPos, &stringIdx, &parsedOk); - getIndex(stringIdx.endPos, &gsubrIdx, &parsedOk); - if (!parsedOk) { - return gFalse; - } - gsubrBias = (gsubrIdx.len < 1240) ? 107 - : (gsubrIdx.len < 33900) ? 1131 : 32768; - - // read the first font name - getIndexVal(&nameIdx, 0, &val, &parsedOk); - if (!parsedOk) { - return gFalse; - } - name = new GString((char *)&file[val.pos], val.len); - - // read the top dict for the first font - readTopDict(); - - // for CID fonts: read the FDArray dicts and private dicts - if (topDict.firstOp == 0x0c1e) { - if (topDict.fdArrayOffset == 0) { - nFDs = 1; - privateDicts = (Type1CPrivateDict *)gmalloc(sizeof(Type1CPrivateDict)); - readPrivateDict(0, 0, &privateDicts[0]); - } else { - getIndex(topDict.fdArrayOffset, &fdIdx, &parsedOk); - if (!parsedOk) { - return gFalse; - } - nFDs = fdIdx.len; - privateDicts = (Type1CPrivateDict *) - gmallocn(nFDs, sizeof(Type1CPrivateDict)); - for (i = 0; i < nFDs; ++i) { - getIndexVal(&fdIdx, i, &val, &parsedOk); - if (!parsedOk) { - return gFalse; - } - readFD(val.pos, val.len, &privateDicts[i]); - } - } - - // for 8-bit fonts: read the private dict - } else { - privateDicts = (Type1CPrivateDict *)gmalloc(sizeof(Type1CPrivateDict)); - readPrivateDict(topDict.privateOffset, topDict.privateSize, - &privateDicts[0]); - } - - // check for parse errors in the private dict(s) - if (!parsedOk) { - return gFalse; - } - - // get the charstrings index - if (topDict.charStringsOffset <= 0) { - parsedOk = gFalse; - return gFalse; - } - getIndex(topDict.charStringsOffset, &charStringsIdx, &parsedOk); - if (!parsedOk) { - return gFalse; - } - nGlyphs = charStringsIdx.len; - - // for CID fonts: read the FDSelect table - if (topDict.firstOp == 0x0c1e) { - readFDSelect(); - if (!parsedOk) { - return gFalse; - } - } - - // read the charset - if (!readCharset()) { - parsedOk = gFalse; - return gFalse; - } - - // for 8-bit fonts: build the encoding - if (topDict.firstOp != 0x0c14 && topDict.firstOp != 0x0c1e) { - buildEncoding(); - if (!parsedOk) { - return gFalse; - } - } - - return parsedOk; -} - -void FoFiType1C::readTopDict() { - Type1CIndexVal topDictPtr; - int pos; - - topDict.firstOp = -1; - topDict.versionSID = 0; - topDict.noticeSID = 0; - topDict.copyrightSID = 0; - topDict.fullNameSID = 0; - topDict.familyNameSID = 0; - topDict.weightSID = 0; - topDict.isFixedPitch = 0; - topDict.italicAngle = 0; - topDict.underlinePosition = -100; - topDict.underlineThickness = 50; - topDict.paintType = 0; - topDict.charstringType = 2; - topDict.fontMatrix[0] = 0.001; - topDict.fontMatrix[1] = 0; - topDict.fontMatrix[2] = 0; - topDict.fontMatrix[3] = 0.001; - topDict.fontMatrix[4] = 0; - topDict.fontMatrix[5] = 0; - topDict.hasFontMatrix = gFalse; - topDict.uniqueID = 0; - topDict.fontBBox[0] = 0; - topDict.fontBBox[1] = 0; - topDict.fontBBox[2] = 0; - topDict.fontBBox[3] = 0; - topDict.strokeWidth = 0; - topDict.charsetOffset = 0; - topDict.encodingOffset = 0; - topDict.charStringsOffset = 0; - topDict.privateSize = 0; - topDict.privateOffset = 0; - topDict.registrySID = 0; - topDict.orderingSID = 0; - topDict.supplement = 0; - topDict.fdArrayOffset = 0; - topDict.fdSelectOffset = 0; - - getIndexVal(&topDictIdx, 0, &topDictPtr, &parsedOk); - pos = topDictPtr.pos; - nOps = 0; - while (pos < topDictPtr.pos + topDictPtr.len) { - pos = getOp(pos, gFalse, &parsedOk); - if (!parsedOk) { - break; - } - if (!ops[nOps - 1].isNum) { - --nOps; // drop the operator - if (topDict.firstOp < 0) { - topDict.firstOp = ops[nOps].op; - } - switch (ops[nOps].op) { - case 0x0000: topDict.versionSID = (int)ops[0].num; break; - case 0x0001: topDict.noticeSID = (int)ops[0].num; break; - case 0x0c00: topDict.copyrightSID = (int)ops[0].num; break; - case 0x0002: topDict.fullNameSID = (int)ops[0].num; break; - case 0x0003: topDict.familyNameSID = (int)ops[0].num; break; - case 0x0004: topDict.weightSID = (int)ops[0].num; break; - case 0x0c01: topDict.isFixedPitch = (int)ops[0].num; break; - case 0x0c02: topDict.italicAngle = ops[0].num; break; - case 0x0c03: topDict.underlinePosition = ops[0].num; break; - case 0x0c04: topDict.underlineThickness = ops[0].num; break; - case 0x0c05: topDict.paintType = (int)ops[0].num; break; - case 0x0c06: topDict.charstringType = (int)ops[0].num; break; - case 0x0c07: topDict.fontMatrix[0] = ops[0].num; - topDict.fontMatrix[1] = ops[1].num; - topDict.fontMatrix[2] = ops[2].num; - topDict.fontMatrix[3] = ops[3].num; - topDict.fontMatrix[4] = ops[4].num; - topDict.fontMatrix[5] = ops[5].num; - topDict.hasFontMatrix = gTrue; break; - case 0x000d: topDict.uniqueID = (int)ops[0].num; break; - case 0x0005: topDict.fontBBox[0] = ops[0].num; - topDict.fontBBox[1] = ops[1].num; - topDict.fontBBox[2] = ops[2].num; - topDict.fontBBox[3] = ops[3].num; break; - case 0x0c08: topDict.strokeWidth = ops[0].num; break; - case 0x000f: topDict.charsetOffset = (int)ops[0].num; break; - case 0x0010: topDict.encodingOffset = (int)ops[0].num; break; - case 0x0011: topDict.charStringsOffset = (int)ops[0].num; break; - case 0x0012: topDict.privateSize = (int)ops[0].num; - topDict.privateOffset = (int)ops[1].num; break; - case 0x0c1e: topDict.registrySID = (int)ops[0].num; - topDict.orderingSID = (int)ops[1].num; - topDict.supplement = (int)ops[2].num; break; - case 0x0c24: topDict.fdArrayOffset = (int)ops[0].num; break; - case 0x0c25: topDict.fdSelectOffset = (int)ops[0].num; break; - } - nOps = 0; - } - } -} - -// Read a CID font dict (FD) - this pulls out the private dict -// pointer, and reads the private dict. It also pulls the FontMatrix -// (if any) out of the FD. -void FoFiType1C::readFD(int offset, int length, Type1CPrivateDict *pDict) { - int pos, pSize, pOffset; - double fontMatrix[6]; - GBool hasFontMatrix; - - hasFontMatrix = gFalse; - pSize = pOffset = 0; - pos = offset; - nOps = 0; - while (pos < offset + length) { - pos = getOp(pos, gFalse, &parsedOk); - if (!parsedOk) { - return; - } - if (!ops[nOps - 1].isNum) { - if (ops[nOps - 1].op == 0x0012) { - if (nOps < 3) { - parsedOk = gFalse; - return; - } - pSize = (int)ops[0].num; - pOffset = (int)ops[1].num; - break; - } else if (ops[nOps - 1].op == 0x0c07) { - fontMatrix[0] = ops[0].num; - fontMatrix[1] = ops[1].num; - fontMatrix[2] = ops[2].num; - fontMatrix[3] = ops[3].num; - fontMatrix[4] = ops[4].num; - fontMatrix[5] = ops[5].num; - hasFontMatrix = gTrue; - } - nOps = 0; - } - } - readPrivateDict(pOffset, pSize, pDict); - if (hasFontMatrix) { - pDict->fontMatrix[0] = fontMatrix[0]; - pDict->fontMatrix[1] = fontMatrix[1]; - pDict->fontMatrix[2] = fontMatrix[2]; - pDict->fontMatrix[3] = fontMatrix[3]; - pDict->fontMatrix[4] = fontMatrix[4]; - pDict->fontMatrix[5] = fontMatrix[5]; - pDict->hasFontMatrix = gTrue; - } -} - -void FoFiType1C::readPrivateDict(int offset, int length, - Type1CPrivateDict *pDict) { - int pos; - - pDict->hasFontMatrix = gFalse; - pDict->nBlueValues = 0; - pDict->nOtherBlues = 0; - pDict->nFamilyBlues = 0; - pDict->nFamilyOtherBlues = 0; - pDict->blueScale = 0.039625; - pDict->blueShift = 7; - pDict->blueFuzz = 1; - pDict->hasStdHW = gFalse; - pDict->hasStdVW = gFalse; - pDict->nStemSnapH = 0; - pDict->nStemSnapV = 0; - pDict->hasForceBold = gFalse; - pDict->forceBoldThreshold = 0; - pDict->languageGroup = 0; - pDict->expansionFactor = 0.06; - pDict->initialRandomSeed = 0; - pDict->subrsOffset = 0; - pDict->defaultWidthX = 0; - pDict->defaultWidthXFP = gFalse; - pDict->nominalWidthX = 0; - pDict->nominalWidthXFP = gFalse; - - // no dictionary - if (offset == 0 || length == 0) { - return; - } - - pos = offset; - nOps = 0; - while (pos < offset + length) { - pos = getOp(pos, gFalse, &parsedOk); - if (!parsedOk) { - break; - } - if (!ops[nOps - 1].isNum) { - --nOps; // drop the operator - switch (ops[nOps].op) { - case 0x0006: - pDict->nBlueValues = getDeltaIntArray(pDict->blueValues, - type1CMaxBlueValues); - break; - case 0x0007: - pDict->nOtherBlues = getDeltaIntArray(pDict->otherBlues, - type1CMaxOtherBlues); - break; - case 0x0008: - pDict->nFamilyBlues = getDeltaIntArray(pDict->familyBlues, - type1CMaxBlueValues); - break; - case 0x0009: - pDict->nFamilyOtherBlues = getDeltaIntArray(pDict->familyOtherBlues, - type1CMaxOtherBlues); - break; - case 0x0c09: - pDict->blueScale = ops[0].num; - break; - case 0x0c0a: - pDict->blueShift = (int)ops[0].num; - break; - case 0x0c0b: - pDict->blueFuzz = (int)ops[0].num; - break; - case 0x000a: - pDict->stdHW = ops[0].num; - pDict->hasStdHW = gTrue; - break; - case 0x000b: - pDict->stdVW = ops[0].num; - pDict->hasStdVW = gTrue; - break; - case 0x0c0c: - pDict->nStemSnapH = getDeltaFPArray(pDict->stemSnapH, - type1CMaxStemSnap); - break; - case 0x0c0d: - pDict->nStemSnapV = getDeltaFPArray(pDict->stemSnapV, - type1CMaxStemSnap); - break; - case 0x0c0e: - pDict->forceBold = ops[0].num != 0; - pDict->hasForceBold = gTrue; - break; - case 0x0c0f: - pDict->forceBoldThreshold = ops[0].num; - break; - case 0x0c11: - pDict->languageGroup = (int)ops[0].num; - break; - case 0x0c12: - pDict->expansionFactor = ops[0].num; - break; - case 0x0c13: - pDict->initialRandomSeed = (int)ops[0].num; - break; - case 0x0013: - pDict->subrsOffset = offset + (int)ops[0].num; - break; - case 0x0014: - pDict->defaultWidthX = ops[0].num; - pDict->defaultWidthXFP = ops[0].isFP; - break; - case 0x0015: - pDict->nominalWidthX = ops[0].num; - pDict->nominalWidthXFP = ops[0].isFP; - break; - } - nOps = 0; - } - } -} - -void FoFiType1C::readFDSelect() { - int fdSelectFmt, pos, nRanges, gid0, gid1, fd, i, j; - - fdSelect = (Guchar *)gmalloc(nGlyphs); - if (topDict.fdSelectOffset == 0) { - for (i = 0; i < nGlyphs; ++i) { - fdSelect[i] = 0; - } - } else { - pos = topDict.fdSelectOffset; - fdSelectFmt = getU8(pos++, &parsedOk); - if (!parsedOk) { - return; - } - if (fdSelectFmt == 0) { - if (!checkRegion(pos, nGlyphs)) { - parsedOk = gFalse; - return; - } - memcpy(fdSelect, file + pos, nGlyphs); - } else if (fdSelectFmt == 3) { - nRanges = getU16BE(pos, &parsedOk); - pos += 2; - gid0 = getU16BE(pos, &parsedOk); - pos += 2; - for (i = 1; i <= nRanges; ++i) { - fd = getU8(pos++, &parsedOk); - gid1 = getU16BE(pos, &parsedOk); - if (!parsedOk) { - return; - } - pos += 2; - if (gid0 > gid1 || gid1 > nGlyphs) { - //~ error(-1, "Bad FDSelect table in CID font"); - parsedOk = gFalse; - return; - } - for (j = gid0; j < gid1; ++j) { - fdSelect[j] = fd; - } - gid0 = gid1; - } - } else { - //~ error(-1, "Unknown FDSelect table format in CID font"); - for (i = 0; i < nGlyphs; ++i) { - fdSelect[i] = 0; - } - } - } -} - -void FoFiType1C::buildEncoding() { - char buf[256]; - int nCodes, nRanges, encFormat; - int pos, c, sid, nLeft, nSups, i, j; - - if (topDict.encodingOffset == 0) { - encoding = fofiType1StandardEncoding; - - } else if (topDict.encodingOffset == 1) { - encoding = fofiType1ExpertEncoding; - - } else { - encoding = (char **)gmallocn(256, sizeof(char *)); - for (i = 0; i < 256; ++i) { - encoding[i] = NULL; - } - pos = topDict.encodingOffset; - encFormat = getU8(pos++, &parsedOk); - if (!parsedOk) { - return; - } - if ((encFormat & 0x7f) == 0) { - nCodes = 1 + getU8(pos++, &parsedOk); - if (!parsedOk) { - return; - } - if (nCodes > nGlyphs) { - nCodes = nGlyphs; - } - for (i = 1; i < nCodes; ++i) { - c = getU8(pos++, &parsedOk); - if (!parsedOk) { - return; - } - if (encoding[c]) { - gfree(encoding[c]); - } - encoding[c] = copyString(getString(charset[i], buf, &parsedOk)); - } - } else if ((encFormat & 0x7f) == 1) { - nRanges = getU8(pos++, &parsedOk); - if (!parsedOk) { - return; - } - nCodes = 1; - for (i = 0; i < nRanges; ++i) { - c = getU8(pos++, &parsedOk); - nLeft = getU8(pos++, &parsedOk); - if (!parsedOk) { - return; - } - for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) { - if (c < 256) { - if (encoding[c]) { - gfree(encoding[c]); - } - encoding[c] = copyString(getString(charset[nCodes], buf, - &parsedOk)); - } - ++nCodes; - ++c; - } - } - } - if (encFormat & 0x80) { - nSups = getU8(pos++, &parsedOk); - if (!parsedOk) { - return; - } - for (i = 0; i < nSups; ++i) { - c = getU8(pos++, &parsedOk);; - if (!parsedOk) { - return;; - } - sid = getU16BE(pos, &parsedOk); - pos += 2; - if (!parsedOk) { - return; - } - if (encoding[c]) { - gfree(encoding[c]); - } - encoding[c] = copyString(getString(sid, buf, &parsedOk)); - } - } - } -} - -GBool FoFiType1C::readCharset() { - int charsetFormat, c, pos; - int nLeft, i, j; - - if (topDict.charsetOffset == 0) { - charset = fofiType1CISOAdobeCharset; - } else if (topDict.charsetOffset == 1) { - charset = fofiType1CExpertCharset; - } else if (topDict.charsetOffset == 2) { - charset = fofiType1CExpertSubsetCharset; - } else { - charset = (Gushort *)gmallocn(nGlyphs, sizeof(Gushort)); - for (i = 0; i < nGlyphs; ++i) { - charset[i] = 0; - } - pos = topDict.charsetOffset; - charsetFormat = getU8(pos++, &parsedOk); - if (charsetFormat == 0) { - for (i = 1; i < nGlyphs; ++i) { - charset[i] = (Gushort)getU16BE(pos, &parsedOk); - pos += 2; - if (!parsedOk) { - break; - } - } - } else if (charsetFormat == 1) { - i = 1; - while (i < nGlyphs) { - c = getU16BE(pos, &parsedOk); - pos += 2; - nLeft = getU8(pos++, &parsedOk); - if (!parsedOk) { - break; - } - for (j = 0; j <= nLeft && i < nGlyphs; ++j) { - charset[i++] = (Gushort)c++; - } - } - } else if (charsetFormat == 2) { - i = 1; - while (i < nGlyphs) { - c = getU16BE(pos, &parsedOk); - pos += 2; - nLeft = getU16BE(pos, &parsedOk); - pos += 2; - if (!parsedOk) { - break; - } - for (j = 0; j <= nLeft && i < nGlyphs; ++j) { - charset[i++] = (Gushort)c++; - } - } - } - if (!parsedOk) { - gfree(charset); - charset = NULL; - return gFalse; - } - } - return gTrue; -} - -int FoFiType1C::getOp(int pos, GBool charstring, GBool *ok) { - static char nybChars[16] = "0123456789.ee -"; - Type1COp op; - char buf[65]; - int b0, b1, nyb0, nyb1, x, i; - - b0 = getU8(pos++, ok); - op.isNum = gTrue; - op.isFP = gFalse; - - if (b0 == 28) { - x = getU8(pos++, ok); - x = (x << 8) | getU8(pos++, ok); - if (x & 0x8000) { - x |= ~0xffff; - } - op.num = x; - - } else if (!charstring && b0 == 29) { - x = getU8(pos++, ok); - x = (x << 8) | getU8(pos++, ok); - x = (x << 8) | getU8(pos++, ok); - x = (x << 8) | getU8(pos++, ok); - if (x & 0x80000000) { - x |= ~0xffffffff; - } - op.num = x; - - } else if (!charstring && b0 == 30) { - i = 0; - do { - b1 = getU8(pos++, ok); - nyb0 = b1 >> 4; - nyb1 = b1 & 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'; - op.num = atof(buf); - op.isFP = gTrue; - - } else if (b0 >= 32 && b0 <= 246) { - op.num = b0 - 139; - - } else if (b0 >= 247 && b0 <= 250) { - op.num = ((b0 - 247) << 8) + getU8(pos++, ok) + 108; - - } else if (b0 >= 251 && b0 <= 254) { - op.num = -((b0 - 251) << 8) - getU8(pos++, ok) - 108; - - } else if (charstring && b0 == 255) { - x = getU8(pos++, ok); - x = (x << 8) | getU8(pos++, ok); - x = (x << 8) | getU8(pos++, ok); - x = (x << 8) | getU8(pos++, ok); - if (x & 0x80000000) { - x |= ~0xffffffff; - } - op.num = (double)x / 65536.0; - op.isFP = gTrue; - - } else if (b0 == 12) { - op.isNum = gFalse; - op.op = 0x0c00 + getU8(pos++, ok); - - } else { - op.isNum = gFalse; - op.op = b0; - } - - if (nOps < 49) { - ops[nOps++] = op; - } - - return pos; -} - -// Convert the delta-encoded ops array to an array of ints. -int FoFiType1C::getDeltaIntArray(int *arr, int maxLen) { - int x; - int n, i; - - if ((n = nOps) > maxLen) { - n = maxLen; - } - x = 0; - for (i = 0; i < n; ++i) { - x += (int)ops[i].num; - arr[i] = x; - } - return n; -} - -// Convert the delta-encoded ops array to an array of doubles. -int FoFiType1C::getDeltaFPArray(double *arr, int maxLen) { - double x; - int n, i; - - if ((n = nOps) > maxLen) { - n = maxLen; - } - x = 0; - for (i = 0; i < n; ++i) { - x += ops[i].num; - arr[i] = x; - } - return n; -} - -void FoFiType1C::getIndex(int pos, Type1CIndex *idx, GBool *ok) { - idx->pos = pos; - idx->len = getU16BE(pos, ok); - if (idx->len == 0) { - // empty indexes are legal and contain just the length field - idx->offSize = 0; - idx->startPos = idx->endPos = pos + 2; - } else { - idx->offSize = getU8(pos + 2, ok); - if (idx->offSize < 1 || idx->offSize > 4) { - *ok = gFalse; - } - idx->startPos = pos + 3 + (idx->len + 1) * idx->offSize - 1; - if (idx->startPos < 0 || idx->startPos >= len) { - *ok = gFalse; - } - idx->endPos = idx->startPos + getUVarBE(pos + 3 + idx->len * idx->offSize, - idx->offSize, ok); - if (idx->endPos < idx->startPos || idx->endPos > len) { - *ok = gFalse; - } - } -} - -void FoFiType1C::getIndexVal(Type1CIndex *idx, int i, - Type1CIndexVal *val, GBool *ok) { - int pos0, pos1; - - if (i < 0 || i >= idx->len) { - *ok = gFalse; - return; - } - pos0 = idx->startPos + getUVarBE(idx->pos + 3 + i * idx->offSize, - idx->offSize, ok); - pos1 = idx->startPos + getUVarBE(idx->pos + 3 + (i + 1) * idx->offSize, - idx->offSize, ok); - if (pos0 < idx->startPos || pos0 > idx->endPos || - pos1 <= idx->startPos || pos1 > idx->endPos || - pos1 < pos0) { - *ok = gFalse; - } - val->pos = pos0; - val->len = pos1 - pos0; -} - -char *FoFiType1C::getString(int sid, char *buf, GBool *ok) { - Type1CIndexVal val; - int n; - - if (sid < 391) { - strcpy(buf, fofiType1CStdStrings[sid]); - } else { - sid -= 391; - getIndexVal(&stringIdx, sid, &val, ok); - if (*ok) { - if ((n = val.len) > 255) { - n = 255; - } - strncpy(buf, (char *)&file[val.pos], n); - buf[n] = '\0'; - } else { - buf[0] = '\0'; - } - } - return buf; -} diff --git a/pdftops/FoFiType1C.h b/pdftops/FoFiType1C.h deleted file mode 100644 index bd4759069..000000000 --- a/pdftops/FoFiType1C.h +++ /dev/null @@ -1,232 +0,0 @@ -//======================================================================== -// -// FoFiType1C.h -// -// Copyright 1999-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef FOFITYPE1C_H -#define FOFITYPE1C_H - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "gtypes.h" -#include "FoFiBase.h" - -class GString; - -//------------------------------------------------------------------------ - -struct Type1CIndex { - int pos; // absolute position in file - int len; // length (number of entries) - int offSize; // offset size - int startPos; // position of start of index data - 1 - int endPos; // position one byte past end of the index -}; - -struct Type1CIndexVal { - int pos; // absolute position in file - int len; // length, in bytes -}; - -struct Type1CTopDict { - int firstOp; - - int versionSID; - int noticeSID; - int copyrightSID; - int fullNameSID; - int familyNameSID; - int weightSID; - int isFixedPitch; - double italicAngle; - double underlinePosition; - double underlineThickness; - int paintType; - int charstringType; - double fontMatrix[6]; - GBool hasFontMatrix; // CID fonts are allowed to put their - // FontMatrix in the FD instead of the - // top dict - int uniqueID; - double fontBBox[4]; - double strokeWidth; - int charsetOffset; - int encodingOffset; - int charStringsOffset; - int privateSize; - int privateOffset; - - // CIDFont entries - int registrySID; - int orderingSID; - int supplement; - int fdArrayOffset; - int fdSelectOffset; -}; - -#define type1CMaxBlueValues 14 -#define type1CMaxOtherBlues 10 -#define type1CMaxStemSnap 12 - -struct Type1CPrivateDict { - double fontMatrix[6]; - GBool hasFontMatrix; - int blueValues[type1CMaxBlueValues]; - int nBlueValues; - int otherBlues[type1CMaxOtherBlues]; - int nOtherBlues; - int familyBlues[type1CMaxBlueValues]; - int nFamilyBlues; - int familyOtherBlues[type1CMaxOtherBlues]; - int nFamilyOtherBlues; - double blueScale; - int blueShift; - int blueFuzz; - double stdHW; - GBool hasStdHW; - double stdVW; - GBool hasStdVW; - double stemSnapH[type1CMaxStemSnap]; - int nStemSnapH; - double stemSnapV[type1CMaxStemSnap]; - int nStemSnapV; - GBool forceBold; - GBool hasForceBold; - double forceBoldThreshold; - int languageGroup; - double expansionFactor; - int initialRandomSeed; - int subrsOffset; - double defaultWidthX; - GBool defaultWidthXFP; - double nominalWidthX; - GBool nominalWidthXFP; -}; - -struct Type1COp { - GBool isNum; // true -> number, false -> operator - GBool isFP; // true -> floating point number, false -> int - union { - double num; // if num is true - int op; // if num is false - }; -}; - -struct Type1CEexecBuf { - FoFiOutputFunc outputFunc; - void *outputStream; - GBool ascii; // ASCII encoding? - Gushort r1; // eexec encryption key - int line; // number of eexec chars left on current line -}; - -//------------------------------------------------------------------------ -// FoFiType1C -//------------------------------------------------------------------------ - -class FoFiType1C: public FoFiBase { -public: - - // Create a FoFiType1C object from a memory buffer. - static FoFiType1C *make(char *fileA, int lenA); - - // Create a FoFiType1C object from a file on disk. - static FoFiType1C *load(char *fileName); - - virtual ~FoFiType1C(); - - // Return the font name. - char *getName(); - - // Return the encoding, as an array of 256 names (any of which may - // be NULL). This is only useful with 8-bit fonts. - char **getEncoding(); - - // Return the mapping from CIDs to GIDs, and return the number of - // CIDs in *<nCIDs>. This is only useful for CID fonts. - Gushort *getCIDToGIDMap(int *nCIDs); - - // Convert to a Type 1 font, suitable for embedding in a PostScript - // file. This is only useful with 8-bit fonts. If <newEncoding> is - // not NULL, it will be used in place of the encoding in the Type 1C - // font. If <ascii> is true the eexec section will be hex-encoded, - // otherwise it will be left as binary data. - void convertToType1(char **newEncoding, GBool ascii, - FoFiOutputFunc outputFunc, void *outputStream); - - // Convert to a Type 0 CIDFont, suitable for embedding in a - // PostScript file. <psName> will be used as the PostScript font - // name. - void convertToCIDType0(char *psName, - FoFiOutputFunc outputFunc, void *outputStream); - - // Convert to a Type 0 (but non-CID) composite font, suitable for - // embedding in a PostScript file. <psName> will be used as the - // PostScript font name. - void convertToType0(char *psName, - FoFiOutputFunc outputFunc, void *outputStream); - -private: - - FoFiType1C(char *fileA, int lenA, GBool freeFileDataA); - void eexecCvtGlyph(Type1CEexecBuf *eb, char *glyphName, - int offset, int nBytes, - Type1CIndex *subrIdx, - Type1CPrivateDict *pDict); - void cvtGlyph(int offset, int nBytes, GString *charBuf, - Type1CIndex *subrIdx, Type1CPrivateDict *pDict, - GBool top); - void cvtGlyphWidth(GBool useOp, GString *charBuf, - Type1CPrivateDict *pDict); - void cvtNum(double x, GBool isFP, GString *charBuf); - void eexecWrite(Type1CEexecBuf *eb, char *s); - void eexecWriteCharstring(Type1CEexecBuf *eb, Guchar *s, int n); - GBool parse(); - void readTopDict(); - void readFD(int offset, int length, Type1CPrivateDict *pDict); - void readPrivateDict(int offset, int length, Type1CPrivateDict *pDict); - void readFDSelect(); - void buildEncoding(); - GBool readCharset(); - int getOp(int pos, GBool charstring, GBool *ok); - int getDeltaIntArray(int *arr, int maxLen); - int getDeltaFPArray(double *arr, int maxLen); - void getIndex(int pos, Type1CIndex *idx, GBool *ok); - void getIndexVal(Type1CIndex *idx, int i, Type1CIndexVal *val, GBool *ok); - char *getString(int sid, char *buf, GBool *ok); - - GString *name; - char **encoding; - - Type1CIndex nameIdx; - Type1CIndex topDictIdx; - Type1CIndex stringIdx; - Type1CIndex gsubrIdx; - Type1CIndex charStringsIdx; - - Type1CTopDict topDict; - Type1CPrivateDict *privateDicts; - - int nGlyphs; - int nFDs; - Guchar *fdSelect; - Gushort *charset; - int gsubrBias; - - GBool parsedOk; - - Type1COp ops[49]; // operands and operator - int nOps; // number of operands - int nHints; // number of hints for the current glyph - GBool firstOp; // true if we haven't hit the first op yet - GBool openPath; // true if there is an unclosed path -}; - -#endif diff --git a/pdftops/FontEncodingTables.cxx b/pdftops/FontEncodingTables.cxx deleted file mode 100644 index cd8d89265..000000000 --- a/pdftops/FontEncodingTables.cxx +++ /dev/null @@ -1,1824 +0,0 @@ -//======================================================================== -// -// FontEncodingTables.cc -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> -#include <stdlib.h> -#include "FontEncodingTables.h" - -char *macRomanEncoding[256] = { - 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", - "notequal", - "AE", - "Oslash", - "infinity", - "plusminus", - "lessequal", - "greaterequal", - "yen", - "mu", - "partialdiff", - "summation", - "product", - "pi", - "integral", - "ordfeminine", - "ordmasculine", - "Omega", - "ae", - "oslash", - "questiondown", - "exclamdown", - "logicalnot", - "radical", - "florin", - "approxequal", - "Delta", - "guillemotleft", - "guillemotright", - "ellipsis", - "space", - "Agrave", - "Atilde", - "Otilde", - "OE", - "oe", - "endash", - "emdash", - "quotedblleft", - "quotedblright", - "quoteleft", - "quoteright", - "divide", - "lozenge", - "ydieresis", - "Ydieresis", - "fraction", - "currency", - "guilsinglleft", - "guilsinglright", - "fi", - "fl", - "daggerdbl", - "periodcentered", - "quotesinglbase", - "quotedblbase", - "perthousand", - "Acircumflex", - "Ecircumflex", - "Aacute", - "Edieresis", - "Egrave", - "Iacute", - "Icircumflex", - "Idieresis", - "Igrave", - "Oacute", - "Ocircumflex", - "apple", - "Ograve", - "Uacute", - "Ucircumflex", - "Ugrave", - "dotlessi", - "circumflex", - "tilde", - "macron", - "breve", - "dotaccent", - "ring", - "cedilla", - "hungarumlaut", - "ogonek", - "caron" -}; - -char *macExpertEncoding[256] = { - 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", - "centoldstyle", - "dollaroldstyle", - "dollarsuperior", - "ampersandsmall", - "Acutesmall", - "parenleftsuperior", - "parenrightsuperior", - "twodotenleader", - "onedotenleader", - "comma", - "hyphen", - "period", - "fraction", - "zerooldstyle", - "oneoldstyle", - "twooldstyle", - "threeoldstyle", - "fouroldstyle", - "fiveoldstyle", - "sixoldstyle", - "sevenoldstyle", - "eightoldstyle", - "nineoldstyle", - "colon", - "semicolon", - NULL, - "threequartersemdash", - NULL, - "questionsmall", - NULL, - NULL, - NULL, - NULL, - "Ethsmall", - NULL, - NULL, - "onequarter", - "onehalf", - "threequarters", - "oneeighth", - "threeeighths", - "fiveeighths", - "seveneighths", - "onethird", - "twothirds", - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - "ff", - "fi", - "fl", - "ffi", - "ffl", - "parenleftinferior", - NULL, - "parenrightinferior", - "Circumflexsmall", - "hypheninferior", - "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, - "asuperior", - "centsuperior", - NULL, - NULL, - NULL, - NULL, - "Aacutesmall", - "Agravesmall", - "Acircumflexsmall", - "Adieresissmall", - "Atildesmall", - "Aringsmall", - "Ccedillasmall", - "Eacutesmall", - "Egravesmall", - "Ecircumflexsmall", - "Edieresissmall", - "Iacutesmall", - "Igravesmall", - "Icircumflexsmall", - "Idieresissmall", - "Ntildesmall", - "Oacutesmall", - "Ogravesmall", - "Ocircumflexsmall", - "Odieresissmall", - "Otildesmall", - "Uacutesmall", - "Ugravesmall", - "Ucircumflexsmall", - "Udieresissmall", - NULL, - "eightsuperior", - "fourinferior", - "threeinferior", - "sixinferior", - "eightinferior", - "seveninferior", - "Scaronsmall", - NULL, - "centinferior", - "twoinferior", - NULL, - "Dieresissmall", - NULL, - "Caronsmall", - "osuperior", - "fiveinferior", - NULL, - "commainferior", - "periodinferior", - "Yacutesmall", - NULL, - "dollarinferior", - NULL, - NULL, - "Thornsmall", - NULL, - "nineinferior", - "zeroinferior", - "Zcaronsmall", - "AEsmall", - "Oslashsmall", - "questiondownsmall", - "oneinferior", - "Lslashsmall", - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - "Cedillasmall", - NULL, - NULL, - NULL, - NULL, - NULL, - "OEsmall", - "figuredash", - "hyphensuperior", - NULL, - NULL, - NULL, - NULL, - "exclamdownsmall", - NULL, - "Ydieresissmall", - NULL, - "onesuperior", - "twosuperior", - "threesuperior", - "foursuperior", - "fivesuperior", - "sixsuperior", - "sevensuperior", - "ninesuperior", - "zerosuperior", - NULL, - "esuperior", - "rsuperior", - "tsuperior", - NULL, - NULL, - "isuperior", - "ssuperior", - "dsuperior", - NULL, - NULL, - NULL, - NULL, - NULL, - "lsuperior", - "Ogoneksmall", - "Brevesmall", - "Macronsmall", - "bsuperior", - "nsuperior", - "msuperior", - "commasuperior", - "periodsuperior", - "Dotaccentsmall", - "Ringsmall", - NULL, - NULL, - NULL, - NULL -}; - -char *winAnsiEncoding[256] = { - 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", - "Euro", - "bullet", - "quotesinglbase", - "florin", - "quotedblbase", - "ellipsis", - "dagger", - "daggerdbl", - "circumflex", - "perthousand", - "Scaron", - "guilsinglleft", - "OE", - "bullet", - "Zcaron", - "bullet", - "bullet", - "quoteleft", - "quoteright", - "quotedblleft", - "quotedblright", - "bullet", - "endash", - "emdash", - "tilde", - "trademark", - "scaron", - "guilsinglright", - "oe", - "bullet", - "zcaron", - "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" -}; - -char *standardEncoding[256] = { - 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 -}; - -char *expertEncoding[256] = { - 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" -}; - -char *symbolEncoding[256] = { - 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 -}; - -char *zapfDingbatsEncoding[256] = { - 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 -}; diff --git a/pdftops/FontEncodingTables.h b/pdftops/FontEncodingTables.h deleted file mode 100644 index 8b0a1e7e9..000000000 --- a/pdftops/FontEncodingTables.h +++ /dev/null @@ -1,20 +0,0 @@ -//======================================================================== -// -// FontEncodingTables.h -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef FONTENCODINGTABLES_H -#define FONTENCODINGTABLES_H - -extern char *macRomanEncoding[]; -extern char *macExpertEncoding[]; -extern char *winAnsiEncoding[]; -extern char *standardEncoding[]; -extern char *expertEncoding[]; -extern char *symbolEncoding[]; -extern char *zapfDingbatsEncoding[]; - -#endif diff --git a/pdftops/Function.cxx b/pdftops/Function.cxx deleted file mode 100644 index 7959a4802..000000000 --- a/pdftops/Function.cxx +++ /dev/null @@ -1,1536 +0,0 @@ -//======================================================================== -// -// Function.cc -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include <math.h> -#include "gmem.h" -#include "Object.h" -#include "Dict.h" -#include "Stream.h" -#include "Error.h" -#include "Function.h" - -//------------------------------------------------------------------------ -// Function -//------------------------------------------------------------------------ - -Function::Function() { -} - -Function::~Function() { -} - -Function *Function::parse(Object *funcObj) { - Function *func; - Dict *dict; - int funcType; - Object obj1; - - if (funcObj->isStream()) { - dict = funcObj->streamGetDict(); - } else if (funcObj->isDict()) { - dict = funcObj->getDict(); - } else if (funcObj->isName("Identity")) { - return new IdentityFunction(); - } else { - error(-1, "Expected function dictionary or stream"); - return NULL; - } - - if (!dict->lookup("FunctionType", &obj1)->isInt()) { - error(-1, "Function type is missing or wrong type"); - obj1.free(); - return NULL; - } - funcType = obj1.getInt(); - obj1.free(); - - if (funcType == 0) { - func = new SampledFunction(funcObj, dict); - } else if (funcType == 2) { - func = new ExponentialFunction(funcObj, dict); - } else if (funcType == 3) { - func = new StitchingFunction(funcObj, dict); - } else if (funcType == 4) { - func = new PostScriptFunction(funcObj, dict); - } else { - error(-1, "Unimplemented function type (%d)", funcType); - return NULL; - } - if (!func->isOk()) { - delete func; - return NULL; - } - - return func; -} - -GBool Function::init(Dict *dict) { - Object obj1, obj2; - int i; - - //----- Domain - if (!dict->lookup("Domain", &obj1)->isArray()) { - error(-1, "Function is missing domain"); - goto err2; - } - m = obj1.arrayGetLength() / 2; - if (m > funcMaxInputs) { - error(-1, "Functions with more than %d inputs are unsupported", - funcMaxInputs); - 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 - hasRange = gFalse; - n = 0; - if (dict->lookup("Range", &obj1)->isArray()) { - hasRange = gTrue; - n = obj1.arrayGetLength() / 2; - if (n > funcMaxOutputs) { - error(-1, "Functions with more than %d outputs are unsupported", - funcMaxOutputs); - 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(); - - return gTrue; - - err1: - obj2.free(); - err2: - obj1.free(); - return gFalse; -} - -//------------------------------------------------------------------------ -// IdentityFunction -//------------------------------------------------------------------------ - -IdentityFunction::IdentityFunction() { - int i; - - // fill these in with arbitrary values just in case they get used - // somewhere - m = funcMaxInputs; - n = funcMaxOutputs; - for (i = 0; i < funcMaxInputs; ++i) { - domain[i][0] = 0; - domain[i][1] = 1; - } - hasRange = gFalse; -} - -IdentityFunction::~IdentityFunction() { -} - -void IdentityFunction::transform(double *in, double *out) { - int i; - - for (i = 0; i < funcMaxOutputs; ++i) { - out[i] = in[i]; - } -} - -//------------------------------------------------------------------------ -// SampledFunction -//------------------------------------------------------------------------ - -SampledFunction::SampledFunction(Object *funcObj, Dict *dict) { - Stream *str; - int sampleBits; - double sampleMul; - Object obj1, obj2; - Guint buf, bitMask; - int bits; - int s; - int i; - - samples = NULL; - ok = gFalse; - - //----- initialize the generic stuff - if (!init(dict)) { - goto err1; - } - if (!hasRange) { - error(-1, "Type 0 function is missing range"); - goto err1; - } - - //----- get the stream - if (!funcObj->isStream()) { - error(-1, "Type 0 function isn't a stream"); - goto err1; - } - str = funcObj->getStream(); - - //----- 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 err3; - } - sampleSize[i] = obj2.getInt(); - obj2.free(); - } - obj1.free(); - idxMul[0] = n; - for (i = 1; i < m; ++i) { - idxMul[i] = idxMul[i-1] * sampleSize[i-1]; - } - - //----- 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 err3; - } - 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 err3; - } - 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(); - for (i = 0; i < m; ++i) { - inputMul[i] = (encode[i][1] - encode[i][0]) / - (domain[i][1] - domain[i][0]); - } - - //----- 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 err3; - } - 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 err3; - } - 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 *)gmallocn(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; - } - str->close(); - - ok = gTrue; - return; - - err3: - obj2.free(); - err2: - obj1.free(); - err1: - return; -} - -SampledFunction::~SampledFunction() { - if (samples) { - gfree(samples); - } -} - -SampledFunction::SampledFunction(SampledFunction *func) { - memcpy(this, func, sizeof(SampledFunction)); - samples = (double *)gmallocn(nSamples, sizeof(double)); - memcpy(samples, func->samples, nSamples * sizeof(double)); -} - -void SampledFunction::transform(double *in, double *out) { - double x; - int e[funcMaxInputs][2]; - double efrac0[funcMaxInputs]; - double efrac1[funcMaxInputs]; - double s[1 << funcMaxInputs]; - int i, j, k, idx, t; - - // map input values into sample array - for (i = 0; i < m; ++i) { - x = (in[i] - domain[i][0]) * inputMul[i] + encode[i][0]; - if (x < 0) { - x = 0; - } else if (x > sampleSize[i] - 1) { - x = sampleSize[i] - 1; - } - e[i][0] = (int)x; - if ((e[i][1] = e[i][0] + 1) >= sampleSize[i]) { - // this happens if in[i] = domain[i][1] - e[i][1] = e[i][0]; - } - efrac1[i] = x - e[i][0]; - efrac0[i] = 1 - efrac1[i]; - } - - // for each output, do m-linear interpolation - for (i = 0; i < n; ++i) { - - // pull 2^m values out of the sample array - for (j = 0; j < (1<<m); ++j) { - idx = i; - for (k = 0, t = j; k < m; ++k, t >>= 1) { - idx += idxMul[k] * (e[k][t & 1]); - } - s[j] = samples[idx]; - } - - // do m sets of interpolations - for (j = 0, t = (1<<m); j < m; ++j, t >>= 1) { - for (k = 0; k < t; k += 2) { - s[k >> 1] = efrac0[j] * s[k] + efrac1[j] * s[k+1]; - } - } - - // map output value to range - out[i] = s[0] * (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]; - } - } -} - -//------------------------------------------------------------------------ -// ExponentialFunction -//------------------------------------------------------------------------ - -ExponentialFunction::ExponentialFunction(Object *funcObj, Dict *dict) { - Object obj1, obj2; - int i; - - ok = gFalse; - - //----- initialize the generic stuff - if (!init(dict)) { - goto err1; - } - if (m != 1) { - error(-1, "Exponential function with more than one input"); - goto err1; - } - - //----- C0 - if (dict->lookup("C0", &obj1)->isArray()) { - if (hasRange && obj1.arrayGetLength() != n) { - error(-1, "Function's C0 array is wrong length"); - goto err2; - } - n = obj1.arrayGetLength(); - for (i = 0; i < n; ++i) { - obj1.arrayGet(i, &obj2); - if (!obj2.isNum()) { - error(-1, "Illegal value in function C0 array"); - goto err3; - } - c0[i] = obj2.getNum(); - obj2.free(); - } - } else { - if (hasRange && n != 1) { - error(-1, "Function's C0 array is wrong length"); - goto err2; - } - n = 1; - c0[0] = 0; - } - obj1.free(); - - //----- C1 - if (dict->lookup("C1", &obj1)->isArray()) { - if (obj1.arrayGetLength() != n) { - error(-1, "Function's C1 array is wrong length"); - goto err2; - } - for (i = 0; i < n; ++i) { - obj1.arrayGet(i, &obj2); - if (!obj2.isNum()) { - error(-1, "Illegal value in function C1 array"); - goto err3; - } - c1[i] = obj2.getNum(); - obj2.free(); - } - } else { - if (n != 1) { - error(-1, "Function's C1 array is wrong length"); - goto err2; - } - c1[0] = 1; - } - obj1.free(); - - //----- N (exponent) - if (!dict->lookup("N", &obj1)->isNum()) { - error(-1, "Function has missing or invalid N"); - goto err2; - } - e = obj1.getNum(); - obj1.free(); - - ok = gTrue; - return; - - err3: - obj2.free(); - err2: - obj1.free(); - err1: - return; -} - -ExponentialFunction::~ExponentialFunction() { -} - -ExponentialFunction::ExponentialFunction(ExponentialFunction *func) { - memcpy(this, func, sizeof(ExponentialFunction)); -} - -void ExponentialFunction::transform(double *in, double *out) { - double x; - int i; - - if (in[0] < domain[0][0]) { - x = domain[0][0]; - } else if (in[0] > domain[0][1]) { - x = domain[0][1]; - } else { - x = in[0]; - } - for (i = 0; i < n; ++i) { - out[i] = c0[i] + pow(x, e) * (c1[i] - c0[i]); - if (hasRange) { - if (out[i] < range[i][0]) { - out[i] = range[i][0]; - } else if (out[i] > range[i][1]) { - out[i] = range[i][1]; - } - } - } - return; -} - -//------------------------------------------------------------------------ -// StitchingFunction -//------------------------------------------------------------------------ - -StitchingFunction::StitchingFunction(Object *funcObj, Dict *dict) { - Object obj1, obj2; - int i; - - ok = gFalse; - funcs = NULL; - bounds = NULL; - encode = NULL; - - //----- initialize the generic stuff - if (!init(dict)) { - goto err1; - } - if (m != 1) { - error(-1, "Stitching function with more than one input"); - goto err1; - } - - //----- Functions - if (!dict->lookup("Functions", &obj1)->isArray()) { - error(-1, "Missing 'Functions' entry in stitching function"); - goto err1; - } - k = obj1.arrayGetLength(); - funcs = (Function **)gmallocn(k, sizeof(Function *)); - bounds = (double *)gmallocn(k + 1, sizeof(double)); - encode = (double *)gmallocn(2 * k, sizeof(double)); - for (i = 0; i < k; ++i) { - funcs[i] = NULL; - } - for (i = 0; i < k; ++i) { - if (!(funcs[i] = Function::parse(obj1.arrayGet(i, &obj2)))) { - goto err2; - } - if (i > 0 && (funcs[i]->getInputSize() != 1 || - funcs[i]->getOutputSize() != funcs[0]->getOutputSize())) { - error(-1, "Incompatible subfunctions in stitching function"); - goto err2; - } - obj2.free(); - } - obj1.free(); - - //----- Bounds - if (!dict->lookup("Bounds", &obj1)->isArray() || - obj1.arrayGetLength() != k - 1) { - error(-1, "Missing or invalid 'Bounds' entry in stitching function"); - goto err1; - } - bounds[0] = domain[0][0]; - for (i = 1; i < k; ++i) { - if (!obj1.arrayGet(i - 1, &obj2)->isNum()) { - error(-1, "Invalid type in 'Bounds' array in stitching function"); - goto err2; - } - bounds[i] = obj2.getNum(); - obj2.free(); - } - bounds[k] = domain[0][1]; - obj1.free(); - - //----- Encode - if (!dict->lookup("Encode", &obj1)->isArray() || - obj1.arrayGetLength() != 2 * k) { - error(-1, "Missing or invalid 'Encode' entry in stitching function"); - goto err1; - } - for (i = 0; i < 2 * k; ++i) { - if (!obj1.arrayGet(i, &obj2)->isNum()) { - error(-1, "Invalid type in 'Encode' array in stitching function"); - goto err2; - } - encode[i] = obj2.getNum(); - obj2.free(); - } - obj1.free(); - - ok = gTrue; - return; - - err2: - obj2.free(); - err1: - obj1.free(); -} - -StitchingFunction::StitchingFunction(StitchingFunction *func) { - int i; - - k = func->k; - funcs = (Function **)gmallocn(k, sizeof(Function *)); - for (i = 0; i < k; ++i) { - funcs[i] = func->funcs[i]->copy(); - } - bounds = (double *)gmallocn(k + 1, sizeof(double)); - memcpy(bounds, func->bounds, (k + 1) * sizeof(double)); - encode = (double *)gmallocn(2 * k, sizeof(double)); - memcpy(encode, func->encode, 2 * k * sizeof(double)); - ok = gTrue; -} - -StitchingFunction::~StitchingFunction() { - int i; - - if (funcs) { - for (i = 0; i < k; ++i) { - if (funcs[i]) { - delete funcs[i]; - } - } - } - gfree(funcs); - gfree(bounds); - gfree(encode); -} - -void StitchingFunction::transform(double *in, double *out) { - double x; - int i; - - if (in[0] < domain[0][0]) { - x = domain[0][0]; - } else if (in[0] > domain[0][1]) { - x = domain[0][1]; - } else { - x = in[0]; - } - for (i = 0; i < k - 1; ++i) { - if (x < bounds[i+1]) { - break; - } - } - x = encode[2*i] + ((x - bounds[i]) / (bounds[i+1] - bounds[i])) * - (encode[2*i+1] - encode[2*i]); - funcs[i]->transform(&x, out); -} - -//------------------------------------------------------------------------ -// PostScriptFunction -//------------------------------------------------------------------------ - -enum PSOp { - psOpAbs, - psOpAdd, - psOpAnd, - psOpAtan, - psOpBitshift, - psOpCeiling, - psOpCopy, - psOpCos, - psOpCvi, - psOpCvr, - psOpDiv, - psOpDup, - psOpEq, - psOpExch, - psOpExp, - psOpFalse, - psOpFloor, - psOpGe, - psOpGt, - psOpIdiv, - psOpIndex, - psOpLe, - psOpLn, - psOpLog, - psOpLt, - psOpMod, - psOpMul, - psOpNe, - psOpNeg, - psOpNot, - psOpOr, - psOpPop, - psOpRoll, - psOpRound, - psOpSin, - psOpSqrt, - psOpSub, - psOpTrue, - psOpTruncate, - psOpXor, - psOpIf, - psOpIfelse, - psOpReturn -}; - -// Note: 'if' and 'ifelse' are parsed separately. -// The rest are listed here in alphabetical order. -// The index in this table is equivalent to the entry in PSOp. -char *psOpNames[] = { - "abs", - "add", - "and", - "atan", - "bitshift", - "ceiling", - "copy", - "cos", - "cvi", - "cvr", - "div", - "dup", - "eq", - "exch", - "exp", - "false", - "floor", - "ge", - "gt", - "idiv", - "index", - "le", - "ln", - "log", - "lt", - "mod", - "mul", - "ne", - "neg", - "not", - "or", - "pop", - "roll", - "round", - "sin", - "sqrt", - "sub", - "true", - "truncate", - "xor" -}; - -#define nPSOps (sizeof(psOpNames) / sizeof(char *)) - -enum PSObjectType { - psBool, - psInt, - psReal, - psOperator, - psBlock -}; - -// In the code array, 'if'/'ifelse' operators take up three slots -// plus space for the code in the subclause(s). -// -// +---------------------------------+ -// | psOperator: psOpIf / psOpIfelse | -// +---------------------------------+ -// | psBlock: ptr=<A> | -// +---------------------------------+ -// | psBlock: ptr=<B> | -// +---------------------------------+ -// | if clause | -// | ... | -// | psOperator: psOpReturn | -// +---------------------------------+ -// <A> | else clause | -// | ... | -// | psOperator: psOpReturn | -// +---------------------------------+ -// <B> | ... | -// -// For 'if', pointer <A> is present in the code stream but unused. - -struct PSObject { - PSObjectType type; - union { - GBool booln; // boolean (stack only) - int intg; // integer (stack and code) - double real; // real (stack and code) - PSOp op; // operator (code only) - int blk; // if/ifelse block pointer (code only) - }; -}; - -#define psStackSize 100 - -class PSStack { -public: - - PSStack() { sp = psStackSize; } - void pushBool(GBool booln); - void pushInt(int intg); - void pushReal(double real); - GBool popBool(); - int popInt(); - double popNum(); - GBool empty() { return sp == psStackSize; } - GBool topIsInt() { return sp < psStackSize && stack[sp].type == psInt; } - GBool topTwoAreInts() - { return sp < psStackSize - 1 && - stack[sp].type == psInt && - stack[sp+1].type == psInt; } - GBool topIsReal() { return sp < psStackSize && stack[sp].type == psReal; } - GBool topTwoAreNums() - { return sp < psStackSize - 1 && - (stack[sp].type == psInt || stack[sp].type == psReal) && - (stack[sp+1].type == psInt || stack[sp+1].type == psReal); } - void copy(int n); - void roll(int n, int j); - void index(int i); - void pop(); - -private: - - GBool checkOverflow(int n = 1); - GBool checkUnderflow(); - GBool checkType(PSObjectType t1, PSObjectType t2); - - PSObject stack[psStackSize]; - int sp; -}; - -GBool PSStack::checkOverflow(int n) { - if (sp - n < 0) { - error(-1, "Stack overflow in PostScript function"); - return gFalse; - } - return gTrue; -} - -GBool PSStack::checkUnderflow() { - if (sp == psStackSize) { - error(-1, "Stack underflow in PostScript function"); - return gFalse; - } - return gTrue; -} - -GBool PSStack::checkType(PSObjectType t1, PSObjectType t2) { - if (stack[sp].type != t1 && stack[sp].type != t2) { - error(-1, "Type mismatch in PostScript function"); - return gFalse; - } - return gTrue; -} - -void PSStack::pushBool(GBool booln) { - if (checkOverflow()) { - stack[--sp].type = psBool; - stack[sp].booln = booln; - } -} - -void PSStack::pushInt(int intg) { - if (checkOverflow()) { - stack[--sp].type = psInt; - stack[sp].intg = intg; - } -} - -void PSStack::pushReal(double real) { - if (checkOverflow()) { - stack[--sp].type = psReal; - stack[sp].real = real; - } -} - -GBool PSStack::popBool() { - if (checkUnderflow() && checkType(psBool, psBool)) { - return stack[sp++].booln; - } - return gFalse; -} - -int PSStack::popInt() { - if (checkUnderflow() && checkType(psInt, psInt)) { - return stack[sp++].intg; - } - return 0; -} - -double PSStack::popNum() { - double ret; - - if (checkUnderflow() && checkType(psInt, psReal)) { - ret = (stack[sp].type == psInt) ? (double)stack[sp].intg : stack[sp].real; - ++sp; - return ret; - } - return 0; -} - -void PSStack::copy(int n) { - int i; - - if (sp + n > psStackSize) { - error(-1, "Stack underflow in PostScript function"); - return; - } - if (!checkOverflow(n)) { - return; - } - for (i = sp + n - 1; i >= sp; --i) { - stack[i - n] = stack[i]; - } - sp -= n; -} - -void PSStack::roll(int n, int j) { - PSObject obj; - int i, k; - - if (j >= 0) { - j %= n; - } else { - j = -j % n; - if (j != 0) { - j = n - j; - } - } - if (n <= 0 || j == 0) { - return; - } - for (i = 0; i < j; ++i) { - obj = stack[sp]; - for (k = sp; k < sp + n - 1; ++k) { - stack[k] = stack[k+1]; - } - stack[sp + n - 1] = obj; - } -} - -void PSStack::index(int i) { - if (!checkOverflow()) { - return; - } - --sp; - stack[sp] = stack[sp + 1 + i]; -} - -void PSStack::pop() { - if (!checkUnderflow()) { - return; - } - ++sp; -} - -PostScriptFunction::PostScriptFunction(Object *funcObj, Dict *dict) { - Stream *str; - int codePtr; - GString *tok; - - code = NULL; - codeSize = 0; - ok = gFalse; - - //----- initialize the generic stuff - if (!init(dict)) { - goto err1; - } - if (!hasRange) { - error(-1, "Type 4 function is missing range"); - goto err1; - } - - //----- get the stream - if (!funcObj->isStream()) { - error(-1, "Type 4 function isn't a stream"); - goto err1; - } - str = funcObj->getStream(); - - //----- parse the function - codeString = new GString(); - str->reset(); - if (!(tok = getToken(str)) || tok->cmp("{")) { - error(-1, "Expected '{' at start of PostScript function"); - if (tok) { - delete tok; - } - goto err1; - } - delete tok; - codePtr = 0; - if (!parseCode(str, &codePtr)) { - goto err2; - } - str->close(); - - ok = gTrue; - - err2: - str->close(); - err1: - return; -} - -PostScriptFunction::PostScriptFunction(PostScriptFunction *func) { - memcpy(this, func, sizeof(PostScriptFunction)); - code = (PSObject *)gmallocn(codeSize, sizeof(PSObject)); - memcpy(code, func->code, codeSize * sizeof(PSObject)); - codeString = func->codeString->copy(); -} - -PostScriptFunction::~PostScriptFunction() { - gfree(code); - delete codeString; -} - -void PostScriptFunction::transform(double *in, double *out) { - PSStack *stack; - int i; - - stack = new PSStack(); - for (i = 0; i < m; ++i) { - //~ may need to check for integers here - stack->pushReal(in[i]); - } - exec(stack, 0); - for (i = n - 1; i >= 0; --i) { - out[i] = stack->popNum(); - if (out[i] < range[i][0]) { - out[i] = range[i][0]; - } else if (out[i] > range[i][1]) { - out[i] = range[i][1]; - } - } - // if (!stack->empty()) { - // error(-1, "Extra values on stack at end of PostScript function"); - // } - delete stack; -} - -GBool PostScriptFunction::parseCode(Stream *str, int *codePtr) { - GString *tok; - char *p; - GBool isReal; - int opPtr, elsePtr; - int a, b, mid, cmp; - - while (1) { - if (!(tok = getToken(str))) { - error(-1, "Unexpected end of PostScript function stream"); - return gFalse; - } - p = tok->getCString(); - if (isdigit(*p) || *p == '.' || *p == '-') { - isReal = gFalse; - for (++p; *p; ++p) { - if (*p == '.') { - isReal = gTrue; - break; - } - } - resizeCode(*codePtr); - if (isReal) { - code[*codePtr].type = psReal; - code[*codePtr].real = atof(tok->getCString()); - } else { - code[*codePtr].type = psInt; - code[*codePtr].intg = atoi(tok->getCString()); - } - ++*codePtr; - delete tok; - } else if (!tok->cmp("{")) { - delete tok; - opPtr = *codePtr; - *codePtr += 3; - resizeCode(opPtr + 2); - if (!parseCode(str, codePtr)) { - return gFalse; - } - if (!(tok = getToken(str))) { - error(-1, "Unexpected end of PostScript function stream"); - return gFalse; - } - if (!tok->cmp("{")) { - elsePtr = *codePtr; - if (!parseCode(str, codePtr)) { - return gFalse; - } - delete tok; - if (!(tok = getToken(str))) { - error(-1, "Unexpected end of PostScript function stream"); - return gFalse; - } - } else { - elsePtr = -1; - } - if (!tok->cmp("if")) { - if (elsePtr >= 0) { - error(-1, "Got 'if' operator with two blocks in PostScript function"); - return gFalse; - } - code[opPtr].type = psOperator; - code[opPtr].op = psOpIf; - code[opPtr+2].type = psBlock; - code[opPtr+2].blk = *codePtr; - } else if (!tok->cmp("ifelse")) { - if (elsePtr < 0) { - error(-1, "Got 'ifelse' operator with one blocks in PostScript function"); - return gFalse; - } - code[opPtr].type = psOperator; - code[opPtr].op = psOpIfelse; - code[opPtr+1].type = psBlock; - code[opPtr+1].blk = elsePtr; - code[opPtr+2].type = psBlock; - code[opPtr+2].blk = *codePtr; - } else { - error(-1, "Expected if/ifelse operator in PostScript function"); - delete tok; - return gFalse; - } - delete tok; - } else if (!tok->cmp("}")) { - delete tok; - resizeCode(*codePtr); - code[*codePtr].type = psOperator; - code[*codePtr].op = psOpReturn; - ++*codePtr; - break; - } else { - a = -1; - b = nPSOps; - // invariant: psOpNames[a] < tok < psOpNames[b] - cmp = 1; - while (b - a > 1) { - mid = (a + b) / 2; - cmp = tok->cmp(psOpNames[mid]); - if (cmp > 0) { - a = mid; - } else if (cmp < 0) { - b = mid; - } else { - a = b = mid; - } - } - if (cmp != 0) { - error(-1, "Unknown operator '%s' in PostScript function", - tok->getCString()); - delete tok; - return gFalse; - } - delete tok; - resizeCode(*codePtr); - code[*codePtr].type = psOperator; - code[*codePtr].op = (PSOp)a; - ++*codePtr; - } - } - return gTrue; -} - -GString *PostScriptFunction::getToken(Stream *str) { - GString *s; - int c; - - s = new GString(); - do { - c = str->getChar(); - if (c != EOF) { - codeString->append(c); - } - } while (c != EOF && isspace(c)); - if (c == '{' || c == '}') { - s->append((char)c); - } else if (isdigit(c) || c == '.' || c == '-') { - while (1) { - s->append((char)c); - c = str->lookChar(); - if (c == EOF || !(isdigit(c) || c == '.' || c == '-')) { - break; - } - str->getChar(); - codeString->append(c); - } - } else { - while (1) { - s->append((char)c); - c = str->lookChar(); - if (c == EOF || !isalnum(c)) { - break; - } - str->getChar(); - codeString->append(c); - } - } - return s; -} - -void PostScriptFunction::resizeCode(int newSize) { - if (newSize >= codeSize) { - codeSize += 64; - code = (PSObject *)greallocn(code, codeSize, sizeof(PSObject)); - } -} - -void PostScriptFunction::exec(PSStack *stack, int codePtr) { - int i1, i2; - double r1, r2; - GBool b1, b2; - - while (1) { - switch (code[codePtr].type) { - case psInt: - stack->pushInt(code[codePtr++].intg); - break; - case psReal: - stack->pushReal(code[codePtr++].real); - break; - case psOperator: - switch (code[codePtr++].op) { - case psOpAbs: - if (stack->topIsInt()) { - stack->pushInt(abs(stack->popInt())); - } else { - stack->pushReal(fabs(stack->popNum())); - } - break; - case psOpAdd: - if (stack->topTwoAreInts()) { - i2 = stack->popInt(); - i1 = stack->popInt(); - stack->pushInt(i1 + i2); - } else { - r2 = stack->popNum(); - r1 = stack->popNum(); - stack->pushReal(r1 + r2); - } - break; - case psOpAnd: - if (stack->topTwoAreInts()) { - i2 = stack->popInt(); - i1 = stack->popInt(); - stack->pushInt(i1 & i2); - } else { - b2 = stack->popBool(); - b1 = stack->popBool(); - stack->pushBool(b1 && b2); - } - break; - case psOpAtan: - r2 = stack->popNum(); - r1 = stack->popNum(); - stack->pushReal(atan2(r1, r2)); - break; - case psOpBitshift: - i2 = stack->popInt(); - i1 = stack->popInt(); - if (i2 > 0) { - stack->pushInt(i1 << i2); - } else if (i2 < 0) { - stack->pushInt((int)((Guint)i1 >> i2)); - } else { - stack->pushInt(i1); - } - break; - case psOpCeiling: - if (!stack->topIsInt()) { - stack->pushReal(ceil(stack->popNum())); - } - break; - case psOpCopy: - stack->copy(stack->popInt()); - break; - case psOpCos: - stack->pushReal(cos(stack->popNum())); - break; - case psOpCvi: - if (!stack->topIsInt()) { - stack->pushInt((int)stack->popNum()); - } - break; - case psOpCvr: - if (!stack->topIsReal()) { - stack->pushReal(stack->popNum()); - } - break; - case psOpDiv: - r2 = stack->popNum(); - r1 = stack->popNum(); - stack->pushReal(r1 / r2); - break; - case psOpDup: - stack->copy(1); - break; - case psOpEq: - if (stack->topTwoAreInts()) { - i2 = stack->popInt(); - i1 = stack->popInt(); - stack->pushBool(i1 == i2); - } else if (stack->topTwoAreNums()) { - r2 = stack->popNum(); - r1 = stack->popNum(); - stack->pushBool(r1 == r2); - } else { - b2 = stack->popBool(); - b1 = stack->popBool(); - stack->pushBool(b1 == b2); - } - break; - case psOpExch: - stack->roll(2, 1); - break; - case psOpExp: - r2 = stack->popNum(); - r1 = stack->popNum(); - stack->pushReal(pow(r1, r2)); - break; - case psOpFalse: - stack->pushBool(gFalse); - break; - case psOpFloor: - if (!stack->topIsInt()) { - stack->pushReal(floor(stack->popNum())); - } - break; - case psOpGe: - if (stack->topTwoAreInts()) { - i2 = stack->popInt(); - i1 = stack->popInt(); - stack->pushBool(i1 >= i2); - } else { - r2 = stack->popNum(); - r1 = stack->popNum(); - stack->pushBool(r1 >= r2); - } - break; - case psOpGt: - if (stack->topTwoAreInts()) { - i2 = stack->popInt(); - i1 = stack->popInt(); - stack->pushBool(i1 > i2); - } else { - r2 = stack->popNum(); - r1 = stack->popNum(); - stack->pushBool(r1 > r2); - } - break; - case psOpIdiv: - i2 = stack->popInt(); - i1 = stack->popInt(); - stack->pushInt(i1 / i2); - break; - case psOpIndex: - stack->index(stack->popInt()); - break; - case psOpLe: - if (stack->topTwoAreInts()) { - i2 = stack->popInt(); - i1 = stack->popInt(); - stack->pushBool(i1 <= i2); - } else { - r2 = stack->popNum(); - r1 = stack->popNum(); - stack->pushBool(r1 <= r2); - } - break; - case psOpLn: - stack->pushReal(log(stack->popNum())); - break; - case psOpLog: - stack->pushReal(log10(stack->popNum())); - break; - case psOpLt: - if (stack->topTwoAreInts()) { - i2 = stack->popInt(); - i1 = stack->popInt(); - stack->pushBool(i1 < i2); - } else { - r2 = stack->popNum(); - r1 = stack->popNum(); - stack->pushBool(r1 < r2); - } - break; - case psOpMod: - i2 = stack->popInt(); - i1 = stack->popInt(); - stack->pushInt(i1 % i2); - break; - case psOpMul: - if (stack->topTwoAreInts()) { - i2 = stack->popInt(); - i1 = stack->popInt(); - //~ should check for out-of-range, and push a real instead - stack->pushInt(i1 * i2); - } else { - r2 = stack->popNum(); - r1 = stack->popNum(); - stack->pushReal(r1 * r2); - } - break; - case psOpNe: - if (stack->topTwoAreInts()) { - i2 = stack->popInt(); - i1 = stack->popInt(); - stack->pushBool(i1 != i2); - } else if (stack->topTwoAreNums()) { - r2 = stack->popNum(); - r1 = stack->popNum(); - stack->pushBool(r1 != r2); - } else { - b2 = stack->popBool(); - b1 = stack->popBool(); - stack->pushBool(b1 != b2); - } - break; - case psOpNeg: - if (stack->topIsInt()) { - stack->pushInt(-stack->popInt()); - } else { - stack->pushReal(-stack->popNum()); - } - break; - case psOpNot: - if (stack->topIsInt()) { - stack->pushInt(~stack->popInt()); - } else { - stack->pushBool(!stack->popBool()); - } - break; - case psOpOr: - if (stack->topTwoAreInts()) { - i2 = stack->popInt(); - i1 = stack->popInt(); - stack->pushInt(i1 | i2); - } else { - b2 = stack->popBool(); - b1 = stack->popBool(); - stack->pushBool(b1 || b2); - } - break; - case psOpPop: - stack->pop(); - break; - case psOpRoll: - i2 = stack->popInt(); - i1 = stack->popInt(); - stack->roll(i1, i2); - break; - case psOpRound: - if (!stack->topIsInt()) { - r1 = stack->popNum(); - stack->pushReal((r1 >= 0) ? floor(r1 + 0.5) : ceil(r1 - 0.5)); - } - break; - case psOpSin: - stack->pushReal(sin(stack->popNum())); - break; - case psOpSqrt: - stack->pushReal(sqrt(stack->popNum())); - break; - case psOpSub: - if (stack->topTwoAreInts()) { - i2 = stack->popInt(); - i1 = stack->popInt(); - stack->pushInt(i1 - i2); - } else { - r2 = stack->popNum(); - r1 = stack->popNum(); - stack->pushReal(r1 - r2); - } - break; - case psOpTrue: - stack->pushBool(gTrue); - break; - case psOpTruncate: - if (!stack->topIsInt()) { - r1 = stack->popNum(); - stack->pushReal((r1 >= 0) ? floor(r1) : ceil(r1)); - } - break; - case psOpXor: - if (stack->topTwoAreInts()) { - i2 = stack->popInt(); - i1 = stack->popInt(); - stack->pushInt(i1 ^ i2); - } else { - b2 = stack->popBool(); - b1 = stack->popBool(); - stack->pushBool(b1 ^ b2); - } - break; - case psOpIf: - b1 = stack->popBool(); - if (b1) { - exec(stack, codePtr + 2); - } - codePtr = code[codePtr + 1].blk; - break; - case psOpIfelse: - b1 = stack->popBool(); - if (b1) { - exec(stack, codePtr + 2); - } else { - exec(stack, code[codePtr].blk); - } - codePtr = code[codePtr + 1].blk; - break; - case psOpReturn: - return; - } - break; - default: - error(-1, "Internal: bad object in PostScript function code"); - break; - } - } -} diff --git a/pdftops/Function.h b/pdftops/Function.h deleted file mode 100644 index df1623772..000000000 --- a/pdftops/Function.h +++ /dev/null @@ -1,225 +0,0 @@ -//======================================================================== -// -// Function.h -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef FUNCTION_H -#define FUNCTION_H - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "gtypes.h" -#include "Object.h" - -class Dict; -class Stream; -struct PSObject; -class PSStack; - -//------------------------------------------------------------------------ -// Function -//------------------------------------------------------------------------ - -#define funcMaxInputs 8 -#define funcMaxOutputs 32 - -class Function { -public: - - Function(); - - virtual ~Function(); - - // Construct a function. Returns NULL if unsuccessful. - static Function *parse(Object *funcObj); - - // Initialize the entries common to all function types. - GBool init(Dict *dict); - - virtual Function *copy() = 0; - - // Return the function type: - // -1 : identity - // 0 : sampled - // 2 : exponential - // 3 : stitching - // 4 : PostScript - virtual int getType() = 0; - - // Return size of input and output tuples. - int getInputSize() { return m; } - int getOutputSize() { return n; } - - double getDomainMin(int i) { return domain[i][0]; } - double getDomainMax(int i) { return domain[i][1]; } - double getRangeMin(int i) { return range[i][0]; } - double getRangeMax(int i) { return range[i][1]; } - GBool getHasRange() { return hasRange; } - - // Transform an input tuple into an output tuple. - virtual void transform(double *in, double *out) = 0; - - virtual GBool isOk() = 0; - -protected: - - int m, n; // size of input and output tuples - double // min and max values for function domain - domain[funcMaxInputs][2]; - double // min and max values for function range - range[funcMaxOutputs][2]; - GBool hasRange; // set if range is defined -}; - -//------------------------------------------------------------------------ -// IdentityFunction -//------------------------------------------------------------------------ - -class IdentityFunction: public Function { -public: - - IdentityFunction(); - virtual ~IdentityFunction(); - virtual Function *copy() { return new IdentityFunction(); } - virtual int getType() { return -1; } - virtual void transform(double *in, double *out); - virtual GBool isOk() { return gTrue; } - -private: -}; - -//------------------------------------------------------------------------ -// SampledFunction -//------------------------------------------------------------------------ - -class SampledFunction: public Function { -public: - - SampledFunction(Object *funcObj, Dict *dict); - virtual ~SampledFunction(); - virtual Function *copy() { return new SampledFunction(this); } - virtual int getType() { return 0; } - virtual void transform(double *in, double *out); - virtual GBool isOk() { return ok; } - - int getSampleSize(int i) { return sampleSize[i]; } - double getEncodeMin(int i) { return encode[i][0]; } - double getEncodeMax(int i) { return encode[i][1]; } - double getDecodeMin(int i) { return decode[i][0]; } - double getDecodeMax(int i) { return decode[i][1]; } - double *getSamples() { return samples; } - -private: - - SampledFunction(SampledFunction *func); - - int // number of samples for each domain element - sampleSize[funcMaxInputs]; - double // min and max values for domain encoder - encode[funcMaxInputs][2]; - double // min and max values for range decoder - decode[funcMaxOutputs][2]; - double // input multipliers - inputMul[funcMaxInputs]; - int idxMul[funcMaxInputs]; // sample array index multipliers - double *samples; // the samples - int nSamples; // size of the samples array - GBool ok; -}; - -//------------------------------------------------------------------------ -// ExponentialFunction -//------------------------------------------------------------------------ - -class ExponentialFunction: public Function { -public: - - ExponentialFunction(Object *funcObj, Dict *dict); - virtual ~ExponentialFunction(); - virtual Function *copy() { return new ExponentialFunction(this); } - virtual int getType() { return 2; } - virtual void transform(double *in, double *out); - virtual GBool isOk() { return ok; } - - double *getC0() { return c0; } - double *getC1() { return c1; } - double getE() { return e; } - -private: - - ExponentialFunction(ExponentialFunction *func); - - double c0[funcMaxOutputs]; - double c1[funcMaxOutputs]; - double e; - GBool ok; -}; - -//------------------------------------------------------------------------ -// StitchingFunction -//------------------------------------------------------------------------ - -class StitchingFunction: public Function { -public: - - StitchingFunction(Object *funcObj, Dict *dict); - virtual ~StitchingFunction(); - virtual Function *copy() { return new StitchingFunction(this); } - virtual int getType() { return 3; } - virtual void transform(double *in, double *out); - virtual GBool isOk() { return ok; } - - int getNumFuncs() { return k; } - Function *getFunc(int i) { return funcs[i]; } - double *getBounds() { return bounds; } - double *getEncode() { return encode; } - -private: - - StitchingFunction(StitchingFunction *func); - - int k; - Function **funcs; - double *bounds; - double *encode; - GBool ok; -}; - -//------------------------------------------------------------------------ -// PostScriptFunction -//------------------------------------------------------------------------ - -class PostScriptFunction: public Function { -public: - - PostScriptFunction(Object *funcObj, Dict *dict); - virtual ~PostScriptFunction(); - virtual Function *copy() { return new PostScriptFunction(this); } - virtual int getType() { return 4; } - virtual void transform(double *in, double *out); - virtual GBool isOk() { return ok; } - - GString *getCodeString() { return codeString; } - -private: - - PostScriptFunction(PostScriptFunction *func); - GBool parseCode(Stream *str, int *codePtr); - GString *getToken(Stream *str); - void resizeCode(int newSize); - void exec(PSStack *stack, int codePtr); - - GString *codeString; - PSObject *code; - int codeSize; - GBool ok; -}; - -#endif diff --git a/pdftops/GHash.cxx b/pdftops/GHash.cxx deleted file mode 100644 index 7185a693c..000000000 --- a/pdftops/GHash.cxx +++ /dev/null @@ -1,380 +0,0 @@ -//======================================================================== -// -// GHash.cc -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include "gmem.h" -#include "GString.h" -#include "GHash.h" - -//------------------------------------------------------------------------ - -struct GHashBucket { - GString *key; - union { - void *p; - int i; - } val; - GHashBucket *next; -}; - -struct GHashIter { - int h; - GHashBucket *p; -}; - -//------------------------------------------------------------------------ - -GHash::GHash(GBool deleteKeysA) { - int h; - - deleteKeys = deleteKeysA; - size = 7; - tab = (GHashBucket **)gmallocn(size, sizeof(GHashBucket *)); - for (h = 0; h < size; ++h) { - tab[h] = NULL; - } - len = 0; -} - -GHash::~GHash() { - GHashBucket *p; - int h; - - for (h = 0; h < size; ++h) { - while (tab[h]) { - p = tab[h]; - tab[h] = p->next; - if (deleteKeys) { - delete p->key; - } - delete p; - } - } - gfree(tab); -} - -void GHash::add(GString *key, void *val) { - GHashBucket *p; - int h; - - // expand the table if necessary - if (len >= size) { - expand(); - } - - // add the new symbol - p = new GHashBucket; - p->key = key; - p->val.p = val; - h = hash(key); - p->next = tab[h]; - tab[h] = p; - ++len; -} - -void GHash::add(GString *key, int val) { - GHashBucket *p; - int h; - - // expand the table if necessary - if (len >= size) { - expand(); - } - - // add the new symbol - p = new GHashBucket; - p->key = key; - p->val.i = val; - h = hash(key); - p->next = tab[h]; - tab[h] = p; - ++len; -} - -void GHash::replace(GString *key, void *val) { - GHashBucket *p; - int h; - - if ((p = find(key, &h))) { - p->val.p = val; - delete key; - } else { - add(key, val); - } -} - -void GHash::replace(GString *key, int val) { - GHashBucket *p; - int h; - - if ((p = find(key, &h))) { - p->val.i = val; - delete key; - } else { - add(key, val); - } -} - -void *GHash::lookup(GString *key) { - GHashBucket *p; - int h; - - if (!(p = find(key, &h))) { - return NULL; - } - return p->val.p; -} - -int GHash::lookupInt(GString *key) { - GHashBucket *p; - int h; - - if (!(p = find(key, &h))) { - return 0; - } - return p->val.i; -} - -void *GHash::lookup(char *key) { - GHashBucket *p; - int h; - - if (!(p = find(key, &h))) { - return NULL; - } - return p->val.p; -} - -int GHash::lookupInt(char *key) { - GHashBucket *p; - int h; - - if (!(p = find(key, &h))) { - return 0; - } - return p->val.i; -} - -void *GHash::remove(GString *key) { - GHashBucket *p; - GHashBucket **q; - void *val; - int h; - - if (!(p = find(key, &h))) { - return NULL; - } - q = &tab[h]; - while (*q != p) { - q = &((*q)->next); - } - *q = p->next; - if (deleteKeys) { - delete p->key; - } - val = p->val.p; - delete p; - --len; - return val; -} - -int GHash::removeInt(GString *key) { - GHashBucket *p; - GHashBucket **q; - int val; - int h; - - if (!(p = find(key, &h))) { - return 0; - } - q = &tab[h]; - while (*q != p) { - q = &((*q)->next); - } - *q = p->next; - if (deleteKeys) { - delete p->key; - } - val = p->val.i; - delete p; - --len; - return val; -} - -void *GHash::remove(char *key) { - GHashBucket *p; - GHashBucket **q; - void *val; - int h; - - if (!(p = find(key, &h))) { - return NULL; - } - q = &tab[h]; - while (*q != p) { - q = &((*q)->next); - } - *q = p->next; - if (deleteKeys) { - delete p->key; - } - val = p->val.p; - delete p; - --len; - return val; -} - -int GHash::removeInt(char *key) { - GHashBucket *p; - GHashBucket **q; - int val; - int h; - - if (!(p = find(key, &h))) { - return 0; - } - q = &tab[h]; - while (*q != p) { - q = &((*q)->next); - } - *q = p->next; - if (deleteKeys) { - delete p->key; - } - val = p->val.i; - delete p; - --len; - return val; -} - -void GHash::startIter(GHashIter **iter) { - *iter = new GHashIter; - (*iter)->h = -1; - (*iter)->p = NULL; -} - -GBool GHash::getNext(GHashIter **iter, GString **key, void **val) { - if (!*iter) { - return gFalse; - } - if ((*iter)->p) { - (*iter)->p = (*iter)->p->next; - } - while (!(*iter)->p) { - if (++(*iter)->h == size) { - delete *iter; - *iter = NULL; - return gFalse; - } - (*iter)->p = tab[(*iter)->h]; - } - *key = (*iter)->p->key; - *val = (*iter)->p->val.p; - return gTrue; -} - -GBool GHash::getNext(GHashIter **iter, GString **key, int *val) { - if (!*iter) { - return gFalse; - } - if ((*iter)->p) { - (*iter)->p = (*iter)->p->next; - } - while (!(*iter)->p) { - if (++(*iter)->h == size) { - delete *iter; - *iter = NULL; - return gFalse; - } - (*iter)->p = tab[(*iter)->h]; - } - *key = (*iter)->p->key; - *val = (*iter)->p->val.i; - return gTrue; -} - -void GHash::killIter(GHashIter **iter) { - delete *iter; - *iter = NULL; -} - -void GHash::expand() { - GHashBucket **oldTab; - GHashBucket *p; - int oldSize, h, i; - - oldSize = size; - oldTab = tab; - size = 2*size + 1; - tab = (GHashBucket **)gmallocn(size, sizeof(GHashBucket *)); - for (h = 0; h < size; ++h) { - tab[h] = NULL; - } - for (i = 0; i < oldSize; ++i) { - while (oldTab[i]) { - p = oldTab[i]; - oldTab[i] = oldTab[i]->next; - h = hash(p->key); - p->next = tab[h]; - tab[h] = p; - } - } - gfree(oldTab); -} - -GHashBucket *GHash::find(GString *key, int *h) { - GHashBucket *p; - - *h = hash(key); - for (p = tab[*h]; p; p = p->next) { - if (!p->key->cmp(key)) { - return p; - } - } - return NULL; -} - -GHashBucket *GHash::find(char *key, int *h) { - GHashBucket *p; - - *h = hash(key); - for (p = tab[*h]; p; p = p->next) { - if (!p->key->cmp(key)) { - return p; - } - } - return NULL; -} - -int GHash::hash(GString *key) { - char *p; - unsigned int h; - int i; - - h = 0; - for (p = key->getCString(), i = 0; i < key->getLength(); ++p, ++i) { - h = 17 * h + (int)(*p & 0xff); - } - return (int)(h % size); -} - -int GHash::hash(char *key) { - char *p; - unsigned int h; - - h = 0; - for (p = key; *p; ++p) { - h = 17 * h + (int)(*p & 0xff); - } - return (int)(h % size); -} diff --git a/pdftops/GHash.h b/pdftops/GHash.h deleted file mode 100644 index e454b69f3..000000000 --- a/pdftops/GHash.h +++ /dev/null @@ -1,78 +0,0 @@ -//======================================================================== -// -// GHash.h -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef GHASH_H -#define GHASH_H - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "gtypes.h" - -class GString; -struct GHashBucket; -struct GHashIter; - -//------------------------------------------------------------------------ - -class GHash { -public: - - GHash(GBool deleteKeysA = gFalse); - ~GHash(); - void add(GString *key, void *val); - void add(GString *key, int val); - void replace(GString *key, void *val); - void replace(GString *key, int val); - void *lookup(GString *key); - int lookupInt(GString *key); - void *lookup(char *key); - int lookupInt(char *key); - void *remove(GString *key); - int removeInt(GString *key); - void *remove(char *key); - int removeInt(char *key); - int getLength() { return len; } - void startIter(GHashIter **iter); - GBool getNext(GHashIter **iter, GString **key, void **val); - GBool getNext(GHashIter **iter, GString **key, int *val); - void killIter(GHashIter **iter); - -private: - - void expand(); - GHashBucket *find(GString *key, int *h); - GHashBucket *find(char *key, int *h); - int hash(GString *key); - int hash(char *key); - - GBool deleteKeys; // set if key strings should be deleted - int size; // number of buckets - int len; // number of entries - GHashBucket **tab; -}; - -#define deleteGHash(hash, T) \ - do { \ - GHash *_hash = (hash); \ - { \ - GHashIter *_iter; \ - GString *_key; \ - void *_p; \ - _hash->startIter(&_iter); \ - while (_hash->getNext(&_iter, &_key, &_p)) { \ - delete (T*)_p; \ - } \ - delete _hash; \ - } \ - } while(0) - -#endif diff --git a/pdftops/GList.cxx b/pdftops/GList.cxx deleted file mode 100644 index 326098c77..000000000 --- a/pdftops/GList.cxx +++ /dev/null @@ -1,97 +0,0 @@ -//======================================================================== -// -// GList.cc -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include <stdlib.h> -#include <string.h> -#include "gmem.h" -#include "GList.h" - -//------------------------------------------------------------------------ -// GList -//------------------------------------------------------------------------ - -GList::GList() { - size = 8; - data = (void **)gmallocn(size, sizeof(void*)); - length = 0; - inc = 0; -} - -GList::GList(int sizeA) { - size = sizeA; - data = (void **)gmallocn(size, sizeof(void*)); - length = 0; - inc = 0; -} - -GList::~GList() { - gfree(data); -} - -void GList::append(void *p) { - if (length >= size) { - expand(); - } - data[length++] = p; -} - -void GList::append(GList *list) { - int i; - - while (length + list->length > size) { - expand(); - } - for (i = 0; i < list->length; ++i) { - data[length++] = list->data[i]; - } -} - -void GList::insert(int i, void *p) { - if (length >= size) { - expand(); - } - if (i < length) { - memmove(data+i+1, data+i, (length - i) * sizeof(void *)); - } - data[i] = p; - ++length; -} - -void *GList::del(int i) { - void *p; - - p = data[i]; - if (i < length - 1) { - memmove(data+i, data+i+1, (length - i - 1) * sizeof(void *)); - } - --length; - if (size - length >= ((inc > 0) ? inc : size/2)) { - shrink(); - } - return p; -} - -void GList::sort(int (*cmp)(const void *obj1, const void *obj2)) { - qsort(data, length, sizeof(void *), cmp); -} - -void GList::expand() { - size += (inc > 0) ? inc : size; - data = (void **)greallocn(data, size, sizeof(void*)); -} - -void GList::shrink() { - size -= (inc > 0) ? inc : size/2; - data = (void **)greallocn(data, size, sizeof(void*)); -} diff --git a/pdftops/GList.h b/pdftops/GList.h deleted file mode 100644 index 48e02c0b3..000000000 --- a/pdftops/GList.h +++ /dev/null @@ -1,96 +0,0 @@ -//======================================================================== -// -// GList.h -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef GLIST_H -#define GLIST_H - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "gtypes.h" - -//------------------------------------------------------------------------ -// GList -//------------------------------------------------------------------------ - -class GList { -public: - - // Create an empty list. - GList(); - - // Create an empty list with space for <size1> elements. - GList(int sizeA); - - // Destructor - does not free pointed-to objects. - ~GList(); - - //----- general - - // Get the number of elements. - int getLength() { return length; } - - //----- ordered list support - - // Return the <i>th element. - // Assumes 0 <= i < length. - void *get(int i) { return data[i]; } - - // Append an element to the end of the list. - void append(void *p); - - // Append another list to the end of this one. - void append(GList *list); - - // Insert an element at index <i>. - // Assumes 0 <= i <= length. - void insert(int i, void *p); - - // Deletes and returns the element at index <i>. - // Assumes 0 <= i < length. - void *del(int i); - - // Sort the list accoring to the given comparison function. - // NB: this sorts an array of pointers, so the pointer args need to - // be double-dereferenced. - void sort(int (*cmp)(const void *ptr1, const void *ptr2)); - - //----- control - - // Set allocation increment to <inc>. If inc > 0, that many - // elements will be allocated every time the list is expanded. - // If inc <= 0, the list will be doubled in size. - void setAllocIncr(int incA) { inc = incA; } - -private: - - void expand(); - void shrink(); - - void **data; // the list elements - int size; // size of data array - int length; // number of elements on list - int inc; // allocation increment -}; - -#define deleteGList(list, T) \ - do { \ - GList *_list = (list); \ - { \ - int _i; \ - for (_i = 0; _i < _list->getLength(); ++_i) { \ - delete (T*)_list->get(_i); \ - } \ - delete _list; \ - } \ - } while (0) - -#endif diff --git a/pdftops/GMutex.h b/pdftops/GMutex.h deleted file mode 100644 index 7fa93d85e..000000000 --- a/pdftops/GMutex.h +++ /dev/null @@ -1,49 +0,0 @@ -//======================================================================== -// -// GMutex.h -// -// Portable mutex macros. -// -// Copyright 2002-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef GMUTEX_H -#define GMUTEX_H - -// Usage: -// -// GMutex m; -// gInitMutex(&m); -// ... -// gLockMutex(&m); -// ... critical section ... -// gUnlockMutex(&m); -// ... -// gDestroyMutex(&m); - -#ifdef WIN32 - -#include <windows.h> - -typedef CRITICAL_SECTION GMutex; - -#define gInitMutex(m) InitializeCriticalSection(m) -#define gDestroyMutex(m) DeleteCriticalSection(m) -#define gLockMutex(m) EnterCriticalSection(m) -#define gUnlockMutex(m) LeaveCriticalSection(m) - -#else // assume pthreads - -#include <pthread.h> - -typedef pthread_mutex_t GMutex; - -#define gInitMutex(m) pthread_mutex_init(m, NULL) -#define gDestroyMutex(m) pthread_mutex_destroy(m) -#define gLockMutex(m) pthread_mutex_lock(m) -#define gUnlockMutex(m) pthread_mutex_unlock(m) - -#endif - -#endif diff --git a/pdftops/GString.cxx b/pdftops/GString.cxx deleted file mode 100644 index fbc5b7e94..000000000 --- a/pdftops/GString.cxx +++ /dev/null @@ -1,319 +0,0 @@ -//======================================================================== -// -// GString.cc -// -// Simple variable-length string type. -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include <stdlib.h> -#include <stddef.h> -#include <string.h> -#include <ctype.h> -#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)]; - if (length1 < length) { - memcpy(s1, s, length1); - s1[length1] = '\0'; - } else { - memcpy(s1, s, length + 1); - } - delete[] s; - s = s1; - } -} - -GString::GString() { - s = NULL; - resize(length = 0); - s[0] = '\0'; -} - -GString::GString(const char *sA) { - int n = strlen(sA); - - s = NULL; - resize(length = n); - memcpy(s, sA, n + 1); -} - -GString::GString(const char *sA, int lengthA) { - s = NULL; - resize(length = lengthA); - memcpy(s, sA, length * sizeof(char)); - s[length] = '\0'; -} - -GString::GString(GString *str, int idx, int lengthA) { - s = NULL; - resize(length = lengthA); - memcpy(s, str->getCString() + idx, length); - 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 lengthA) { - resize(length + lengthA); - memcpy(s + length, str, lengthA); - length += lengthA; - 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 lengthA) { - int j; - - resize(length + lengthA); - for (j = length; j >= i; --j) - s[j+lengthA] = s[j]; - memcpy(s+i, str, lengthA); - length += lengthA; - return this; -} - -GString *GString::del(int i, int n) { - int j; - - if (n > 0) { - if (i + n > length) { - n = length - i; - } - 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; -} - -int GString::cmp(GString *str) { - int n1, n2, i, x; - char *p1, *p2; - - n1 = length; - n2 = str->length; - for (i = 0, p1 = s, p2 = str->s; i < n1 && i < n2; ++i, ++p1, ++p2) { - x = *p1 - *p2; - if (x != 0) { - return x; - } - } - return n1 - n2; -} - -int GString::cmpN(GString *str, int n) { - int n1, n2, i, x; - char *p1, *p2; - - n1 = length; - n2 = str->length; - for (i = 0, p1 = s, p2 = str->s; - i < n1 && i < n2 && i < n; - ++i, ++p1, ++p2) { - x = *p1 - *p2; - if (x != 0) { - return x; - } - } - if (i == n) { - return 0; - } - return n1 - n2; -} - -int GString::cmp(const char *sA) { - int n1, i, x; - const char *p1, *p2; - - n1 = length; - for (i = 0, p1 = s, p2 = sA; i < n1 && *p2; ++i, ++p1, ++p2) { - x = *p1 - *p2; - if (x != 0) { - return x; - } - } - if (i < n1) { - return 1; - } - if (*p2) { - return -1; - } - return 0; -} - -int GString::cmpN(const char *sA, int n) { - int n1, i, x; - const char *p1, *p2; - - n1 = length; - for (i = 0, p1 = s, p2 = sA; i < n1 && *p2 && i < n; ++i, ++p1, ++p2) { - x = *p1 - *p2; - if (x != 0) { - return x; - } - } - if (i == n) { - return 0; - } - if (i < n1) { - return 1; - } - if (*p2) { - return -1; - } - return 0; -} diff --git a/pdftops/GString.h b/pdftops/GString.h deleted file mode 100644 index aa16e5dd8..000000000 --- a/pdftops/GString.h +++ /dev/null @@ -1,97 +0,0 @@ -//======================================================================== -// -// GString.h -// -// Simple variable-length string type. -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef GSTRING_H -#define GSTRING_H - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -class GString { -public: - - // Create an empty string. - GString(); - - // Create a string from a C string. - GString(const char *sA); - - // Create a string from <lengthA> chars at <sA>. This string - // can contain null characters. - GString(const char *sA, int lengthA); - - // Create a string from <lengthA> chars at <idx> in <str>. - GString(GString *str, int idx, int lengthA); - - // 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 <i>th character. - char getChar(int i) { return s[i]; } - - // Change <i>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 lengthA); - - // 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 lengthA); - - // 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:> - int cmp(GString *str); - int cmpN(GString *str, int n); - int cmp(const char *sA); - int cmpN(const char *sA, int n); - -private: - - int length; - char *s; - - void resize(int length1); -}; - -#endif diff --git a/pdftops/Gfx.cxx b/pdftops/Gfx.cxx deleted file mode 100644 index 6e675a44c..000000000 --- a/pdftops/Gfx.cxx +++ /dev/null @@ -1,3623 +0,0 @@ -//======================================================================== -// -// Gfx.cc -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include <stdlib.h> -#include <stdio.h> -#include <stddef.h> -#include <string.h> -#include <math.h> -#include "gmem.h" -#include "GlobalParams.h" -#include "CharTypes.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 "Page.h" -#include "Error.h" -#include "Gfx.h" - -// the MSVC math.h doesn't define this -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - -//------------------------------------------------------------------------ -// constants -//------------------------------------------------------------------------ - -// Max recursive depth for a function shading fill. -#define functionMaxDepth 6 - -// Max delta allowed in any color component for a function shading fill. -#define functionColorDelta (dblToCol(1 / 256.0)) - -// Max number of splits along the t axis for an axial shading fill. -#define axialMaxSplits 256 - -// Max delta allowed in any color component for an axial shading fill. -#define axialColorDelta (dblToCol(1 / 256.0)) - -// Max number of splits along the t axis for a radial shading fill. -#define radialMaxSplits 256 - -// Max delta allowed in any color component for a radial shading fill. -#define radialColorDelta (dblToCol(1 / 256.0)) - -// Max recursive depth for a Gouraud triangle shading fill. -#define gouraudMaxDepth 4 - -// Max delta allowed in any color component for a Gouraud triangle -// shading fill. -#define gouraudColorDelta (dblToCol(1 / 256.0)) - -// Max recursive depth for a patch mesh shading fill. -#define patchMaxDepth 6 - -// Max delta allowed in any color component for a patch mesh shading -// fill. -#define patchColorDelta (dblToCol(1 / 256.0)) - -//------------------------------------------------------------------------ -// Operator table -//------------------------------------------------------------------------ - -#ifdef WIN32 // this works around a bug in the VC7 compiler -# pragma optimize("",off) -#endif - -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}, -}; - -#ifdef WIN32 // this works around a bug in the VC7 compiler -# pragma optimize("",on) -#endif - -#define numOps (sizeof(opTab) / sizeof(Operator)) - -//------------------------------------------------------------------------ -// GfxResources -//------------------------------------------------------------------------ - -GfxResources::GfxResources(XRef *xref, Dict *resDict, GfxResources *nextA) { - Object obj1, obj2; - Ref r; - - if (resDict) { - - // build font dictionary - fonts = NULL; - resDict->lookupNF("Font", &obj1); - if (obj1.isRef()) { - obj1.fetch(xref, &obj2); - if (obj2.isDict()) { - r = obj1.getRef(); - fonts = new GfxFontDict(xref, &r, obj2.getDict()); - } - obj2.free(); - } else if (obj1.isDict()) { - fonts = new GfxFontDict(xref, NULL, obj1.getDict()); - } - obj1.free(); - - // get XObject dictionary - resDict->lookup("XObject", &xObjDict); - - // get color space dictionary - resDict->lookup("ColorSpace", &colorSpaceDict); - - // get pattern dictionary - resDict->lookup("Pattern", &patternDict); - - // get shading dictionary - resDict->lookup("Shading", &shadingDict); - - // get graphics state parameter dictionary - resDict->lookup("ExtGState", &gStateDict); - - } else { - fonts = NULL; - xObjDict.initNull(); - colorSpaceDict.initNull(); - patternDict.initNull(); - shadingDict.initNull(); - gStateDict.initNull(); - } - - next = nextA; -} - -GfxResources::~GfxResources() { - if (fonts) { - delete fonts; - } - xObjDict.free(); - colorSpaceDict.free(); - patternDict.free(); - shadingDict.free(); - gStateDict.free(); -} - -GfxFont *GfxResources::lookupFont(char *name) { - GfxFont *font; - GfxResources *resPtr; - - for (resPtr = this; resPtr; resPtr = resPtr->next) { - if (resPtr->fonts) { - if ((font = resPtr->fonts->lookup(name))) - return font; - } - } - error(-1, "Unknown font tag '%s'", name); - return NULL; -} - -GBool GfxResources::lookupXObject(char *name, Object *obj) { - GfxResources *resPtr; - - for (resPtr = this; resPtr; resPtr = resPtr->next) { - if (resPtr->xObjDict.isDict()) { - if (!resPtr->xObjDict.dictLookup(name, obj)->isNull()) - return gTrue; - obj->free(); - } - } - error(-1, "XObject '%s' is unknown", name); - return gFalse; -} - -GBool GfxResources::lookupXObjectNF(char *name, Object *obj) { - GfxResources *resPtr; - - for (resPtr = this; resPtr; resPtr = resPtr->next) { - if (resPtr->xObjDict.isDict()) { - if (!resPtr->xObjDict.dictLookupNF(name, obj)->isNull()) - return gTrue; - obj->free(); - } - } - error(-1, "XObject '%s' is unknown", name); - return gFalse; -} - -void GfxResources::lookupColorSpace(char *name, Object *obj) { - GfxResources *resPtr; - - for (resPtr = this; resPtr; resPtr = resPtr->next) { - if (resPtr->colorSpaceDict.isDict()) { - if (!resPtr->colorSpaceDict.dictLookup(name, obj)->isNull()) { - return; - } - obj->free(); - } - } - obj->initNull(); -} - -GfxPattern *GfxResources::lookupPattern(char *name) { - GfxResources *resPtr; - GfxPattern *pattern; - Object obj; - - for (resPtr = this; resPtr; resPtr = resPtr->next) { - if (resPtr->patternDict.isDict()) { - if (!resPtr->patternDict.dictLookup(name, &obj)->isNull()) { - pattern = GfxPattern::parse(&obj); - obj.free(); - return pattern; - } - obj.free(); - } - } - error(-1, "Unknown pattern '%s'", name); - return NULL; -} - -GfxShading *GfxResources::lookupShading(char *name) { - GfxResources *resPtr; - GfxShading *shading; - Object obj; - - for (resPtr = this; resPtr; resPtr = resPtr->next) { - if (resPtr->shadingDict.isDict()) { - if (!resPtr->shadingDict.dictLookup(name, &obj)->isNull()) { - shading = GfxShading::parse(&obj); - obj.free(); - return shading; - } - obj.free(); - } - } - error(-1, "Unknown shading '%s'", name); - return NULL; -} - -GBool GfxResources::lookupGState(char *name, Object *obj) { - GfxResources *resPtr; - - for (resPtr = this; resPtr; resPtr = resPtr->next) { - if (resPtr->gStateDict.isDict()) { - if (!resPtr->gStateDict.dictLookup(name, obj)->isNull()) { - return gTrue; - } - obj->free(); - } - } - error(-1, "ExtGState '%s' is unknown", name); - return gFalse; -} - -//------------------------------------------------------------------------ -// Gfx -//------------------------------------------------------------------------ - -Gfx::Gfx(XRef *xrefA, OutputDev *outA, int pageNum, Dict *resDict, - double hDPI, double vDPI, PDFRectangle *box, - PDFRectangle *cropBox, int rotate, - GBool (*abortCheckCbkA)(void *data), - void *abortCheckCbkDataA) { - int i; - - xref = xrefA; - subPage = gFalse; - printCommands = globalParams->getPrintCommands(); - - // start the resource stack - res = new GfxResources(xref, resDict, NULL); - - // initialize - out = outA; - state = new GfxState(hDPI, vDPI, box, rotate, out->upsideDown()); - fontChanged = gFalse; - clip = clipNone; - ignoreUndef = 0; - renderThisPage = out->startPage(pageNum, state); - if (!renderThisPage) - return; - - out->setDefaultCTM(state->getCTM()); - out->updateAll(state); - for (i = 0; i < 6; ++i) { - baseMatrix[i] = state->getCTM()[i]; - } - formDepth = 0; - abortCheckCbk = abortCheckCbkA; - abortCheckCbkData = abortCheckCbkDataA; - - // set crop box - if (cropBox) { - state->moveTo(cropBox->x1, cropBox->y1); - state->lineTo(cropBox->x2, cropBox->y1); - state->lineTo(cropBox->x2, cropBox->y2); - state->lineTo(cropBox->x1, cropBox->y2); - state->closePath(); - state->clip(); - out->clip(state); - state->clearPath(); - } -} - -Gfx::Gfx(XRef *xrefA, OutputDev *outA, Dict *resDict, - PDFRectangle *box, PDFRectangle *cropBox, - GBool (*abortCheckCbkA)(void *data), - void *abortCheckCbkDataA) { - int i; - - xref = xrefA; - subPage = gTrue; - printCommands = globalParams->getPrintCommands(); - renderThisPage = gTrue; - - // start the resource stack - res = new GfxResources(xref, resDict, NULL); - - // initialize - out = outA; - state = new GfxState(72, 72, box, 0, gFalse); - fontChanged = gFalse; - clip = clipNone; - ignoreUndef = 0; - for (i = 0; i < 6; ++i) { - baseMatrix[i] = state->getCTM()[i]; - } - formDepth = 0; - abortCheckCbk = abortCheckCbkA; - abortCheckCbkData = abortCheckCbkDataA; - - // set crop box - if (cropBox) { - state->moveTo(cropBox->x1, cropBox->y1); - state->lineTo(cropBox->x2, cropBox->y1); - state->lineTo(cropBox->x2, cropBox->y2); - state->lineTo(cropBox->x1, cropBox->y2); - state->closePath(); - state->clip(); - out->clip(state); - state->clearPath(); - } -} - -Gfx::~Gfx() { - while (state->hasSaves()) { - restoreState(); - } - if (!subPage) { - out->endPage(); - } - while (res) { - popResources(); - } - if (state) { - delete state; - } -} - -void Gfx::display(Object *obj, GBool topLevel) { - Object obj2; - int i; - - if (!renderThisPage) - return; - - 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(xref, new Lexer(xref, obj)); - go(topLevel); - delete parser; - parser = NULL; -} - -void Gfx::go(GBool topLevel) { - Object obj; - Object args[maxArgs]; - int numArgs, i; - int lastAbortCheck; - - // scan a sequence of objects - updateLevel = lastAbortCheck = 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"); - fflush(stdout); - } - execOp(&obj, args, numArgs); - obj.free(); - for (i = 0; i < numArgs; ++i) - args[i].free(); - numArgs = 0; - - // periodically update display - if (++updateLevel >= 20000) { - out->dump(); - updateLevel = 0; - } - - // check for an abort - if (abortCheckCbk) { - if (updateLevel - lastAbortCheck > 10) { - if ((*abortCheckCbk)(abortCheckCbkData)) { - break; - } - lastAbortCheck = updateLevel; - } - } - - // 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"); - fflush(stdout); - } - 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"); - fflush(stdout); - } - for (i = 0; i < numArgs; ++i) - args[i].free(); - } - - // update display - if (topLevel && updateLevel > 0) { - out->dump(); - } -} - -void Gfx::execOp(Object *cmd, Object args[], int numArgs) { - Operator *op; - char *name; - Object *argPtr; - int i; - - // find operator - name = cmd->getCmd(); - if (!(op = findOp(name))) { - if (ignoreUndef == 0) - error(getPos(), "Unknown operator '%s'", name); - return; - } - - // type check args - argPtr = args; - if (op->numArgs >= 0) { - if (numArgs < op->numArgs) { - error(getPos(), "Too few (%d) args to '%s' operator", numArgs, name); - return; - } - if (numArgs > op->numArgs) { -#if 0 - error(getPos(), "Too many (%d) args to '%s' operator", numArgs, name); -#endif - argPtr += numArgs - op->numArgs; - numArgs = op->numArgs; - } - } 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(&argPtr[i], op->tchk[i])) { - error(getPos(), "Arg #%d to '%s' operator is wrong type (%s)", - i, name, argPtr[i].getTypeName()); - return; - } - } - - // do it - (this->*op->func)(argPtr, numArgs); -} - -Operator *Gfx::findOp(char *name) { - int a, b, m, cmp; - - a = -1; - b = numOps; - // invariant: opTab[a] < name < opTab[b] - cmp = 1; - 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; -} - -//------------------------------------------------------------------------ -// graphics state operators -//------------------------------------------------------------------------ - -void Gfx::opSave(Object args[], int numArgs) { - saveState(); -} - -void Gfx::opRestore(Object args[], int numArgs) { - restoreState(); -} - -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 *)gmallocn(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) { - Object obj1, obj2; - GfxBlendMode mode; - GBool haveFillOP; - - if (!res->lookupGState(args[0].getName(), &obj1)) { - return; - } - if (!obj1.isDict()) { - error(getPos(), "ExtGState '%s' is wrong type", args[0].getName()); - obj1.free(); - return; - } - - // transparency support: blend mode, fill/stroke opacity - if (!obj1.dictLookup("BM", &obj2)->isNull()) { - if (state->parseBlendMode(&obj2, &mode)) { - state->setBlendMode(mode); - out->updateBlendMode(state); - } else { - error(getPos(), "Invalid blend mode in ExtGState"); - } - } - obj2.free(); - if (obj1.dictLookup("ca", &obj2)->isNum()) { - state->setFillOpacity(obj2.getNum()); - out->updateFillOpacity(state); - } - obj2.free(); - if (obj1.dictLookup("CA", &obj2)->isNum()) { - state->setStrokeOpacity(obj2.getNum()); - out->updateStrokeOpacity(state); - } - obj2.free(); - - // fill/stroke overprint - if ((haveFillOP = (obj1.dictLookup("op", &obj2)->isBool()))) { - state->setFillOverprint(obj2.getBool()); - out->updateFillOverprint(state); - } - obj2.free(); - if (obj1.dictLookup("OP", &obj2)->isBool()) { - state->setStrokeOverprint(obj2.getBool()); - out->updateStrokeOverprint(state); - if (!haveFillOP) { - state->setFillOverprint(obj2.getBool()); - out->updateFillOverprint(state); - } - } - obj2.free(); - - obj1.free(); -} - -void Gfx::opSetRenderingIntent(Object args[], int numArgs) { -} - -//------------------------------------------------------------------------ -// color operators -//------------------------------------------------------------------------ - -void Gfx::opSetFillGray(Object args[], int numArgs) { - GfxColor color; - - state->setFillPattern(NULL); - state->setFillColorSpace(new GfxDeviceGrayColorSpace()); - out->updateFillColorSpace(state); - color.c[0] = dblToCol(args[0].getNum()); - state->setFillColor(&color); - out->updateFillColor(state); -} - -void Gfx::opSetStrokeGray(Object args[], int numArgs) { - GfxColor color; - - state->setStrokePattern(NULL); - state->setStrokeColorSpace(new GfxDeviceGrayColorSpace()); - out->updateStrokeColorSpace(state); - color.c[0] = dblToCol(args[0].getNum()); - state->setStrokeColor(&color); - out->updateStrokeColor(state); -} - -void Gfx::opSetFillCMYKColor(Object args[], int numArgs) { - GfxColor color; - int i; - - state->setFillPattern(NULL); - state->setFillColorSpace(new GfxDeviceCMYKColorSpace()); - out->updateFillColorSpace(state); - for (i = 0; i < 4; ++i) { - color.c[i] = dblToCol(args[i].getNum()); - } - state->setFillColor(&color); - out->updateFillColor(state); -} - -void Gfx::opSetStrokeCMYKColor(Object args[], int numArgs) { - GfxColor color; - int i; - - state->setStrokePattern(NULL); - state->setStrokeColorSpace(new GfxDeviceCMYKColorSpace()); - out->updateStrokeColorSpace(state); - for (i = 0; i < 4; ++i) { - color.c[i] = dblToCol(args[i].getNum()); - } - state->setStrokeColor(&color); - out->updateStrokeColor(state); -} - -void Gfx::opSetFillRGBColor(Object args[], int numArgs) { - GfxColor color; - int i; - - state->setFillPattern(NULL); - state->setFillColorSpace(new GfxDeviceRGBColorSpace()); - out->updateFillColorSpace(state); - for (i = 0; i < 3; ++i) { - color.c[i] = dblToCol(args[i].getNum()); - } - state->setFillColor(&color); - out->updateFillColor(state); -} - -void Gfx::opSetStrokeRGBColor(Object args[], int numArgs) { - GfxColor color; - int i; - - state->setStrokePattern(NULL); - state->setStrokeColorSpace(new GfxDeviceRGBColorSpace()); - out->updateStrokeColorSpace(state); - for (i = 0; i < 3; ++i) { - color.c[i] = dblToCol(args[i].getNum()); - } - state->setStrokeColor(&color); - out->updateStrokeColor(state); -} - -void Gfx::opSetFillColorSpace(Object args[], int numArgs) { - Object obj; - GfxColorSpace *colorSpace; - GfxColor color; - int i; - - state->setFillPattern(NULL); - res->lookupColorSpace(args[0].getName(), &obj); - if (obj.isNull()) { - colorSpace = GfxColorSpace::parse(&args[0]); - } else { - colorSpace = GfxColorSpace::parse(&obj); - } - obj.free(); - if (colorSpace) { - state->setFillColorSpace(colorSpace); - out->updateFillColorSpace(state); - } else { - error(getPos(), "Bad color space (fill)"); - } - for (i = 0; i < gfxColorMaxComps; ++i) { - color.c[i] = 0; - } - state->setFillColor(&color); - out->updateFillColor(state); -} - -void Gfx::opSetStrokeColorSpace(Object args[], int numArgs) { - Object obj; - GfxColorSpace *colorSpace; - GfxColor color; - int i; - - state->setStrokePattern(NULL); - res->lookupColorSpace(args[0].getName(), &obj); - if (obj.isNull()) { - colorSpace = GfxColorSpace::parse(&args[0]); - } else { - colorSpace = GfxColorSpace::parse(&obj); - } - obj.free(); - if (colorSpace) { - state->setStrokeColorSpace(colorSpace); - out->updateStrokeColorSpace(state); - } else { - error(getPos(), "Bad color space (stroke)"); - } - for (i = 0; i < gfxColorMaxComps; ++i) { - color.c[i] = 0; - } - state->setStrokeColor(&color); - out->updateStrokeColor(state); -} - -void Gfx::opSetFillColor(Object args[], int numArgs) { - GfxColor color; - int i; - - state->setFillPattern(NULL); - for (i = 0; i < numArgs; ++i) { - color.c[i] = dblToCol(args[i].getNum()); - } - state->setFillColor(&color); - out->updateFillColor(state); -} - -void Gfx::opSetStrokeColor(Object args[], int numArgs) { - GfxColor color; - int i; - - state->setStrokePattern(NULL); - for (i = 0; i < numArgs; ++i) { - color.c[i] = dblToCol(args[i].getNum()); - } - state->setStrokeColor(&color); - out->updateStrokeColor(state); -} - -void Gfx::opSetFillColorN(Object args[], int numArgs) { - GfxColor color; - GfxPattern *pattern; - int i; - - if (state->getFillColorSpace()->getMode() == csPattern) { - if (numArgs > 1) { - for (i = 0; i < numArgs && i < 4; ++i) { - if (args[i].isNum()) { - color.c[i] = dblToCol(args[i].getNum()); - } - } - state->setFillColor(&color); - out->updateFillColor(state); - } - if (args[numArgs-1].isName() && - (pattern = res->lookupPattern(args[numArgs-1].getName()))) { - state->setFillPattern(pattern); - } - - } else { - state->setFillPattern(NULL); - for (i = 0; i < numArgs && i < 4; ++i) { - if (args[i].isNum()) { - color.c[i] = dblToCol(args[i].getNum()); - } - } - state->setFillColor(&color); - out->updateFillColor(state); - } -} - -void Gfx::opSetStrokeColorN(Object args[], int numArgs) { - GfxColor color; - GfxPattern *pattern; - int i; - - if (state->getStrokeColorSpace()->getMode() == csPattern) { - if (numArgs > 1) { - for (i = 0; i < numArgs && i < 4; ++i) { - if (args[i].isNum()) { - color.c[i] = dblToCol(args[i].getNum()); - } - } - state->setStrokeColor(&color); - out->updateStrokeColor(state); - } - if (args[numArgs-1].isName() && - (pattern = res->lookupPattern(args[numArgs-1].getName()))) { - state->setStrokePattern(pattern); - } - - } else { - state->setStrokePattern(NULL); - for (i = 0; i < numArgs && i < 4; ++i) { - if (args[i].isNum()) { - color.c[i] = dblToCol(args[i].getNum()); - } - } - state->setStrokeColor(&color); - 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->isCurPt()) { - 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()) { - if (state->getFillColorSpace()->getMode() == csPattern) { - doPatternFill(gFalse); - } else { - out->fill(state); - } - } - doEndPath(); -} - -void Gfx::opEOFill(Object args[], int numArgs) { - if (!state->isCurPt()) { - //error(getPos(), "No path in eofill"); - return; - } - if (state->isPath()) { - if (state->getFillColorSpace()->getMode() == csPattern) { - doPatternFill(gTrue); - } else { - 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()) { - if (state->getFillColorSpace()->getMode() == csPattern) { - doPatternFill(gFalse); - } else { - 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(); - if (state->getFillColorSpace()->getMode() == csPattern) { - doPatternFill(gFalse); - } else { - 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()) { - if (state->getFillColorSpace()->getMode() == csPattern) { - doPatternFill(gTrue); - } else { - 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(); - if (state->getFillColorSpace()->getMode() == csPattern) { - doPatternFill(gTrue); - } else { - out->eoFill(state); - } - out->stroke(state); - } - doEndPath(); -} - -void Gfx::doPatternFill(GBool eoFill) { - GfxPattern *pattern; - - // this is a bit of a kludge -- patterns can be really slow, so we - // skip them if we're only doing text extraction, since they almost - // certainly don't contain any text - if (!out->needNonText()) { - return; - } - - if (!(pattern = state->getFillPattern())) { - return; - } - switch (pattern->getType()) { - case 1: - doTilingPatternFill((GfxTilingPattern *)pattern, eoFill); - break; - case 2: - doShadingPatternFill((GfxShadingPattern *)pattern, eoFill); - break; - default: - error(getPos(), "Unimplemented pattern type (%d) in fill", - pattern->getType()); - break; - } -} - -void Gfx::doTilingPatternFill(GfxTilingPattern *tPat, GBool eoFill) { - GfxPatternColorSpace *patCS; - GfxColorSpace *cs; - GfxPath *savedPath; - double xMin, yMin, xMax, yMax, x, y, x1, y1; - double cxMin, cyMin, cxMax, cyMax; - int xi0, yi0, xi1, yi1, xi, yi; - double *ctm, *btm, *ptm; - double m[6], ictm[6], m1[6], imb[6]; - double det; - double xstep, ystep; - int i; - - // get color space - patCS = (GfxPatternColorSpace *)state->getFillColorSpace(); - - // construct a (pattern space) -> (current space) transform matrix - ctm = state->getCTM(); - btm = baseMatrix; - ptm = tPat->getMatrix(); - // iCTM = invert CTM - 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; - // m1 = PTM * BTM = PTM * base transform matrix - m1[0] = ptm[0] * btm[0] + ptm[1] * btm[2]; - m1[1] = ptm[0] * btm[1] + ptm[1] * btm[3]; - m1[2] = ptm[2] * btm[0] + ptm[3] * btm[2]; - m1[3] = ptm[2] * btm[1] + ptm[3] * btm[3]; - m1[4] = ptm[4] * btm[0] + ptm[5] * btm[2] + btm[4]; - m1[5] = ptm[4] * btm[1] + ptm[5] * btm[3] + btm[5]; - // m = m1 * iCTM = (PTM * BTM) * (iCTM) - m[0] = m1[0] * ictm[0] + m1[1] * ictm[2]; - m[1] = m1[0] * ictm[1] + m1[1] * ictm[3]; - m[2] = m1[2] * ictm[0] + m1[3] * ictm[2]; - m[3] = m1[2] * ictm[1] + m1[3] * ictm[3]; - m[4] = m1[4] * ictm[0] + m1[5] * ictm[2] + ictm[4]; - m[5] = m1[4] * ictm[1] + m1[5] * ictm[3] + ictm[5]; - - // construct a (device space) -> (pattern space) transform matrix - det = 1 / (m1[0] * m1[3] - m1[1] * m1[2]); - imb[0] = m1[3] * det; - imb[1] = -m1[1] * det; - imb[2] = -m1[2] * det; - imb[3] = m1[0] * det; - imb[4] = (m1[2] * m1[5] - m1[3] * m1[4]) * det; - imb[5] = (m1[1] * m1[4] - m1[0] * m1[5]) * det; - - // save current graphics state - savedPath = state->getPath()->copy(); - saveState(); - - // set underlying color space (for uncolored tiling patterns); set - // various other parameters (stroke color, line width) to match - // Adobe's behavior - if (tPat->getPaintType() == 2 && (cs = patCS->getUnder())) { - state->setFillColorSpace(cs->copy()); - out->updateFillColorSpace(state); - state->setStrokeColorSpace(cs->copy()); - out->updateStrokeColorSpace(state); - state->setStrokeColor(state->getFillColor()); - } else { - state->setFillColorSpace(new GfxDeviceGrayColorSpace()); - out->updateFillColorSpace(state); - state->setStrokeColorSpace(new GfxDeviceGrayColorSpace()); - out->updateStrokeColorSpace(state); - } - state->setFillPattern(NULL); - out->updateFillColor(state); - state->setStrokePattern(NULL); - out->updateStrokeColor(state); - state->setLineWidth(0); - out->updateLineWidth(state); - - // clip to current path - state->clip(); - if (eoFill) { - out->eoClip(state); - } else { - out->clip(state); - } - state->clearPath(); - - // get the clip region, check for empty - state->getClipBBox(&cxMin, &cyMin, &cxMax, &cyMax); - if (cxMin > cxMax || cyMin > cyMax) { - goto err; - } - - // transform clip region bbox to pattern space - xMin = xMax = cxMin * imb[0] + cyMin * imb[2] + imb[4]; - yMin = yMax = cxMin * imb[1] + cyMin * imb[3] + imb[5]; - x1 = cxMin * imb[0] + cyMax * imb[2] + imb[4]; - y1 = cxMin * imb[1] + cyMax * imb[3] + imb[5]; - if (x1 < xMin) { - xMin = x1; - } else if (x1 > xMax) { - xMax = x1; - } - if (y1 < yMin) { - yMin = y1; - } else if (y1 > yMax) { - yMax = y1; - } - x1 = cxMax * imb[0] + cyMin * imb[2] + imb[4]; - y1 = cxMax * imb[1] + cyMin * imb[3] + imb[5]; - if (x1 < xMin) { - xMin = x1; - } else if (x1 > xMax) { - xMax = x1; - } - if (y1 < yMin) { - yMin = y1; - } else if (y1 > yMax) { - yMax = y1; - } - x1 = cxMax * imb[0] + cyMax * imb[2] + imb[4]; - y1 = cxMax * imb[1] + cyMax * imb[3] + imb[5]; - if (x1 < xMin) { - xMin = x1; - } else if (x1 > xMax) { - xMax = x1; - } - if (y1 < yMin) { - yMin = y1; - } else if (y1 > yMax) { - yMax = y1; - } - - // draw the pattern - //~ this should treat negative steps differently -- start at right/top - //~ edge instead of left/bottom (?) - xstep = fabs(tPat->getXStep()); - ystep = fabs(tPat->getYStep()); - xi0 = (int)floor((xMin - tPat->getBBox()[0]) / xstep); - xi1 = (int)ceil((xMax - tPat->getBBox()[0]) / xstep); - yi0 = (int)floor((yMin - tPat->getBBox()[1]) / ystep); - yi1 = (int)ceil((yMax - tPat->getBBox()[1]) / ystep); - for (i = 0; i < 4; ++i) { - m1[i] = m[i]; - } - if (out->useTilingPatternFill()) { - m1[4] = m[4]; - m1[5] = m[5]; - out->tilingPatternFill(state, tPat->getContentStream(), - tPat->getPaintType(), tPat->getResDict(), - m1, tPat->getBBox(), - xi0, yi0, xi1, yi1, xstep, ystep); - } else { - for (yi = yi0; yi < yi1; ++yi) { - for (xi = xi0; xi < xi1; ++xi) { - x = xi * xstep; - y = yi * ystep; - m1[4] = x * m[0] + y * m[2] + m[4]; - m1[5] = x * m[1] + y * m[3] + m[5]; - doForm1(tPat->getContentStream(), tPat->getResDict(), - m1, tPat->getBBox()); - } - } - } - - // restore graphics state - err: - restoreState(); - state->setPath(savedPath); -} - -void Gfx::doShadingPatternFill(GfxShadingPattern *sPat, GBool eoFill) { - GfxShading *shading; - GfxPath *savedPath; - double *ctm, *btm, *ptm; - double m[6], ictm[6], m1[6]; - double xMin, yMin, xMax, yMax; - double det; - - shading = sPat->getShading(); - - // save current graphics state - savedPath = state->getPath()->copy(); - saveState(); - - // clip to bbox - if (shading->getHasBBox()) { - shading->getBBox(&xMin, &yMin, &xMax, &yMax); - state->moveTo(xMin, yMin); - state->lineTo(xMax, yMin); - state->lineTo(xMax, yMax); - state->lineTo(xMin, yMax); - state->closePath(); - state->clip(); - out->clip(state); - state->setPath(savedPath->copy()); - } - - // clip to current path - state->clip(); - if (eoFill) { - out->eoClip(state); - } else { - out->clip(state); - } - - // set the color space - state->setFillColorSpace(shading->getColorSpace()->copy()); - out->updateFillColorSpace(state); - - // background color fill - if (shading->getHasBackground()) { - state->setFillColor(shading->getBackground()); - out->updateFillColor(state); - out->fill(state); - } - state->clearPath(); - - // construct a (pattern space) -> (current space) transform matrix - ctm = state->getCTM(); - btm = baseMatrix; - ptm = sPat->getMatrix(); - // iCTM = invert CTM - 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; - // m1 = PTM * BTM = PTM * base transform matrix - m1[0] = ptm[0] * btm[0] + ptm[1] * btm[2]; - m1[1] = ptm[0] * btm[1] + ptm[1] * btm[3]; - m1[2] = ptm[2] * btm[0] + ptm[3] * btm[2]; - m1[3] = ptm[2] * btm[1] + ptm[3] * btm[3]; - m1[4] = ptm[4] * btm[0] + ptm[5] * btm[2] + btm[4]; - m1[5] = ptm[4] * btm[1] + ptm[5] * btm[3] + btm[5]; - // m = m1 * iCTM = (PTM * BTM) * (iCTM) - m[0] = m1[0] * ictm[0] + m1[1] * ictm[2]; - m[1] = m1[0] * ictm[1] + m1[1] * ictm[3]; - m[2] = m1[2] * ictm[0] + m1[3] * ictm[2]; - m[3] = m1[2] * ictm[1] + m1[3] * ictm[3]; - m[4] = m1[4] * ictm[0] + m1[5] * ictm[2] + ictm[4]; - m[5] = m1[4] * ictm[1] + m1[5] * ictm[3] + ictm[5]; - - // set the new matrix - 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]); - - // do shading type-specific operations - switch (shading->getType()) { - case 1: - doFunctionShFill((GfxFunctionShading *)shading); - break; - case 2: - doAxialShFill((GfxAxialShading *)shading); - break; - case 3: - doRadialShFill((GfxRadialShading *)shading); - break; - case 4: - case 5: - doGouraudTriangleShFill((GfxGouraudTriangleShading *)shading); - break; - case 6: - case 7: - doPatchMeshShFill((GfxPatchMeshShading *)shading); - break; - } - - // restore graphics state - restoreState(); - state->setPath(savedPath); -} - -void Gfx::opShFill(Object args[], int numArgs) { - GfxShading *shading; - GfxPath *savedPath; - double xMin, yMin, xMax, yMax; - - if (!(shading = res->lookupShading(args[0].getName()))) { - return; - } - - // save current graphics state - savedPath = state->getPath()->copy(); - saveState(); - - // clip to bbox - if (shading->getHasBBox()) { - shading->getBBox(&xMin, &yMin, &xMax, &yMax); - state->moveTo(xMin, yMin); - state->lineTo(xMax, yMin); - state->lineTo(xMax, yMax); - state->lineTo(xMin, yMax); - state->closePath(); - state->clip(); - out->clip(state); - state->clearPath(); - } - - // set the color space - state->setFillColorSpace(shading->getColorSpace()->copy()); - out->updateFillColorSpace(state); - - // do shading type-specific operations - switch (shading->getType()) { - case 1: - doFunctionShFill((GfxFunctionShading *)shading); - break; - case 2: - doAxialShFill((GfxAxialShading *)shading); - break; - case 3: - doRadialShFill((GfxRadialShading *)shading); - break; - case 4: - case 5: - doGouraudTriangleShFill((GfxGouraudTriangleShading *)shading); - break; - case 6: - case 7: - doPatchMeshShFill((GfxPatchMeshShading *)shading); - break; - } - - // restore graphics state - restoreState(); - state->setPath(savedPath); - - delete shading; -} - -void Gfx::doFunctionShFill(GfxFunctionShading *shading) { - double x0, y0, x1, y1; - GfxColor colors[4]; - - if (out->useShadedFills()) { - out->functionShadedFill(state, shading); - } else { - shading->getDomain(&x0, &y0, &x1, &y1); - shading->getColor(x0, y0, &colors[0]); - shading->getColor(x0, y1, &colors[1]); - shading->getColor(x1, y0, &colors[2]); - shading->getColor(x1, y1, &colors[3]); - doFunctionShFill1(shading, x0, y0, x1, y1, colors, 0); - } -} - -void Gfx::doFunctionShFill1(GfxFunctionShading *shading, - double x0, double y0, - double x1, double y1, - GfxColor *colors, int depth) { - GfxColor fillColor; - GfxColor color0M, color1M, colorM0, colorM1, colorMM; - GfxColor colors2[4]; - double *matrix; - double xM, yM; - int nComps, i, j; - - nComps = shading->getColorSpace()->getNComps(); - matrix = shading->getMatrix(); - - // compare the four corner colors - for (i = 0; i < 4; ++i) { - for (j = 0; j < nComps; ++j) { - if (abs(colors[i].c[j] - colors[(i+1)&3].c[j]) > functionColorDelta) { - break; - } - } - if (j < nComps) { - break; - } - } - - // center of the rectangle - xM = 0.5 * (x0 + x1); - yM = 0.5 * (y0 + y1); - - // the four corner colors are close (or we hit the recursive limit) - // -- fill the rectangle; but require at least one subdivision - // (depth==0) to avoid problems when the four outer corners of the - // shaded region are the same color - if ((i == 4 && depth > 0) || depth == functionMaxDepth) { - - // use the center color - shading->getColor(xM, yM, &fillColor); - state->setFillColor(&fillColor); - out->updateFillColor(state); - - // fill the rectangle - state->moveTo(x0 * matrix[0] + y0 * matrix[2] + matrix[4], - x0 * matrix[1] + y0 * matrix[3] + matrix[5]); - state->lineTo(x1 * matrix[0] + y0 * matrix[2] + matrix[4], - x1 * matrix[1] + y0 * matrix[3] + matrix[5]); - state->lineTo(x1 * matrix[0] + y1 * matrix[2] + matrix[4], - x1 * matrix[1] + y1 * matrix[3] + matrix[5]); - state->lineTo(x0 * matrix[0] + y1 * matrix[2] + matrix[4], - x0 * matrix[1] + y1 * matrix[3] + matrix[5]); - state->closePath(); - out->fill(state); - state->clearPath(); - - // the four corner colors are not close enough -- subdivide the - // rectangle - } else { - - // colors[0] colorM0 colors[2] - // (x0,y0) (xM,y0) (x1,y0) - // +----------+----------+ - // | | | - // | UL | UR | - // color0M | colorMM | color1M - // (x0,yM) +----------+----------+ (x1,yM) - // | (xM,yM) | - // | LL | LR | - // | | | - // +----------+----------+ - // colors[1] colorM1 colors[3] - // (x0,y1) (xM,y1) (x1,y1) - - shading->getColor(x0, yM, &color0M); - shading->getColor(x1, yM, &color1M); - shading->getColor(xM, y0, &colorM0); - shading->getColor(xM, y1, &colorM1); - shading->getColor(xM, yM, &colorMM); - - // upper-left sub-rectangle - colors2[0] = colors[0]; - colors2[1] = color0M; - colors2[2] = colorM0; - colors2[3] = colorMM; - doFunctionShFill1(shading, x0, y0, xM, yM, colors2, depth + 1); - - // lower-left sub-rectangle - colors2[0] = color0M; - colors2[1] = colors[1]; - colors2[2] = colorMM; - colors2[3] = colorM1; - doFunctionShFill1(shading, x0, yM, xM, y1, colors2, depth + 1); - - // upper-right sub-rectangle - colors2[0] = colorM0; - colors2[1] = colorMM; - colors2[2] = colors[2]; - colors2[3] = color1M; - doFunctionShFill1(shading, xM, y0, x1, yM, colors2, depth + 1); - - // lower-right sub-rectangle - colors2[0] = colorMM; - colors2[1] = colorM1; - colors2[2] = color1M; - colors2[3] = colors[3]; - doFunctionShFill1(shading, xM, yM, x1, y1, colors2, depth + 1); - } -} - -void Gfx::doAxialShFill(GfxAxialShading *shading) { - double xMin, yMin, xMax, yMax; - double x0, y0, x1, y1; - double dx, dy, mul; - GBool dxZero, dyZero; - double tMin, tMax, t, tx, ty; - double s[4], sMin, sMax, tmp; - double ux0, uy0, ux1, uy1, vx0, vy0, vx1, vy1; - double t0, t1, tt; - double ta[axialMaxSplits + 1]; - int next[axialMaxSplits + 1]; - GfxColor color0, color1; - int nComps; - int i, j, k, kk; - - if (out->useShadedFills()) { - - out->axialShadedFill(state, shading); - - } else { - - // get the clip region bbox - state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax); - - // compute min and max t values, based on the four corners of the - // clip region bbox - shading->getCoords(&x0, &y0, &x1, &y1); - dx = x1 - x0; - dy = y1 - y0; - dxZero = fabs(dx) < 0.001; - dyZero = fabs(dy) < 0.001; - mul = 1 / (dx * dx + dy * dy); - tMin = tMax = ((xMin - x0) * dx + (yMin - y0) * dy) * mul; - t = ((xMin - x0) * dx + (yMax - y0) * dy) * mul; - if (t < tMin) { - tMin = t; - } else if (t > tMax) { - tMax = t; - } - t = ((xMax - x0) * dx + (yMin - y0) * dy) * mul; - if (t < tMin) { - tMin = t; - } else if (t > tMax) { - tMax = t; - } - t = ((xMax - x0) * dx + (yMax - y0) * dy) * mul; - if (t < tMin) { - tMin = t; - } else if (t > tMax) { - tMax = t; - } - if (tMin < 0 && !shading->getExtend0()) { - tMin = 0; - } - if (tMax > 1 && !shading->getExtend1()) { - tMax = 1; - } - - // get the function domain - t0 = shading->getDomain0(); - t1 = shading->getDomain1(); - - // Traverse the t axis and do the shading. - // - // For each point (tx, ty) on the t axis, consider a line through - // that point perpendicular to the t axis: - // - // x(s) = tx + s * -dy --> s = (x - tx) / -dy - // y(s) = ty + s * dx --> s = (y - ty) / dx - // - // Then look at the intersection of this line with the bounding box - // (xMin, yMin, xMax, yMax). In the general case, there are four - // intersection points: - // - // s0 = (xMin - tx) / -dy - // s1 = (xMax - tx) / -dy - // s2 = (yMin - ty) / dx - // s3 = (yMax - ty) / dx - // - // and we want the middle two s values. - // - // In the case where dx = 0, take s0 and s1; in the case where dy = - // 0, take s2 and s3. - // - // Each filled polygon is bounded by two of these line segments - // perpdendicular to the t axis. - // - // The t axis is bisected into smaller regions until the color - // difference across a region is small enough, and then the region - // is painted with a single color. - - // set up: require at least one split to avoid problems when the two - // ends of the t axis have the same color - nComps = shading->getColorSpace()->getNComps(); - ta[0] = tMin; - next[0] = axialMaxSplits / 2; - ta[axialMaxSplits / 2] = 0.5 * (tMin + tMax); - next[axialMaxSplits / 2] = axialMaxSplits; - ta[axialMaxSplits] = tMax; - - // compute the color at t = tMin - if (tMin < 0) { - tt = t0; - } else if (tMin > 1) { - tt = t1; - } else { - tt = t0 + (t1 - t0) * tMin; - } - shading->getColor(tt, &color0); - - // compute the coordinates of the point on the t axis at t = tMin; - // then compute the intersection of the perpendicular line with the - // bounding box - tx = x0 + tMin * dx; - ty = y0 + tMin * dy; - if (dxZero && dyZero) { - sMin = sMax = 0; - } if (dxZero) { - sMin = (xMin - tx) / -dy; - sMax = (xMax - tx) / -dy; - if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; } - } else if (dyZero) { - sMin = (yMin - ty) / dx; - sMax = (yMax - ty) / dx; - if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; } - } else { - s[0] = (yMin - ty) / dx; - s[1] = (yMax - ty) / dx; - s[2] = (xMin - tx) / -dy; - s[3] = (xMax - tx) / -dy; - for (j = 0; j < 3; ++j) { - kk = j; - for (k = j + 1; k < 4; ++k) { - if (s[k] < s[kk]) { - kk = k; - } - } - tmp = s[j]; s[j] = s[kk]; s[kk] = tmp; - } - sMin = s[1]; - sMax = s[2]; - } - ux0 = tx - sMin * dy; - uy0 = ty + sMin * dx; - vx0 = tx - sMax * dy; - vy0 = ty + sMax * dx; - - i = 0; - while (i < axialMaxSplits) { - - // bisect until color difference is small enough or we hit the - // bisection limit - j = next[i]; - while (j > i + 1) { - if (ta[j] < 0) { - tt = t0; - } else if (ta[j] > 1) { - tt = t1; - } else { - tt = t0 + (t1 - t0) * ta[j]; - } - shading->getColor(tt, &color1); - for (k = 0; k < nComps; ++k) { - if (abs(color1.c[k] - color0.c[k]) > axialColorDelta) { - break; - } - } - if (k == nComps) { - break; - } - k = (i + j) / 2; - ta[k] = 0.5 * (ta[i] + ta[j]); - next[i] = k; - next[k] = j; - j = k; - } - - // use the average of the colors of the two sides of the region - for (k = 0; k < nComps; ++k) { - color0.c[k] = (color0.c[k] + color1.c[k]) / 2; - } - - // compute the coordinates of the point on the t axis; then - // compute the intersection of the perpendicular line with the - // bounding box - tx = x0 + ta[j] * dx; - ty = y0 + ta[j] * dy; - if (dxZero && dyZero) { - sMin = sMax = 0; - } if (dxZero) { - sMin = (xMin - tx) / -dy; - sMax = (xMax - tx) / -dy; - if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; } - } else if (dyZero) { - sMin = (yMin - ty) / dx; - sMax = (yMax - ty) / dx; - if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; } - } else { - s[0] = (yMin - ty) / dx; - s[1] = (yMax - ty) / dx; - s[2] = (xMin - tx) / -dy; - s[3] = (xMax - tx) / -dy; - for (j = 0; j < 3; ++j) { - kk = j; - for (k = j + 1; k < 4; ++k) { - if (s[k] < s[kk]) { - kk = k; - } - } - tmp = s[j]; s[j] = s[kk]; s[kk] = tmp; - } - sMin = s[1]; - sMax = s[2]; - } - ux1 = tx - sMin * dy; - uy1 = ty + sMin * dx; - vx1 = tx - sMax * dy; - vy1 = ty + sMax * dx; - - // set the color - state->setFillColor(&color0); - out->updateFillColor(state); - - // fill the region - state->moveTo(ux0, uy0); - state->lineTo(vx0, vy0); - state->lineTo(vx1, vy1); - state->lineTo(ux1, uy1); - state->closePath(); - out->fill(state); - state->clearPath(); - - // set up for next region - ux0 = ux1; - uy0 = uy1; - vx0 = vx1; - vy0 = vy1; - color0 = color1; - i = next[i]; - } - } -} - -void Gfx::doRadialShFill(GfxRadialShading *shading) { - double sMin, sMax, xMin, yMin, xMax, yMax; - double x0, y0, r0, x1, y1, r1, t0, t1; - int nComps; - GfxColor colorA, colorB; - double xa, ya, xb, yb, ra, rb; - double ta, tb, sa, sb; - int ia, ib, k, n; - double *ctm; - double angle, t, d0, d1; - - if (out->useShadedFills()) { - - out->radialShadedFill(state, shading); - - } else { - - // get the shading info - shading->getCoords(&x0, &y0, &r0, &x1, &y1, &r1); - t0 = shading->getDomain0(); - t1 = shading->getDomain1(); - nComps = shading->getColorSpace()->getNComps(); - - // compute the (possibly extended) s range - sMin = 0; - sMax = 1; - if (shading->getExtend0()) { - if (r0 < r1) { - // extend the smaller end - sMin = -r0 / (r1 - r0); - } else { - // extend the larger end - state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax); - d0 = (x0 - xMin) * (x0 - xMin); - d1 = (x0 - xMax) * (x0 - xMax); - sMin = d0 > d1 ? d0 : d1; - d0 = (y0 - yMin) * (y0 - yMin); - d1 = (y0 - yMax) * (y0 - yMax); - sMin += d0 > d1 ? d0 : d1; - sMin = (sqrt(sMin) - r0) / (r1 - r0); - if (sMin > 0) { - sMin = 0; - } else if (sMin < -20) { - // sanity check - sMin = -20; - } - } - } - if (shading->getExtend1()) { - if (r1 < r0) { - // extend the smaller end - sMax = -r0 / (r1 - r0); - } else if (r1 > r0) { - // extend the larger end - state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax); - d0 = (x1 - xMin) * (x1 - xMin); - d1 = (x1 - xMax) * (x1 - xMax); - sMax = d0 > d1 ? d0 : d1; - d0 = (y1 - yMin) * (y1 - yMin); - d1 = (y1 - yMax) * (y1 - yMax); - sMax += d0 > d1 ? d0 : d1; - sMax = (sqrt(sMax) - r0) / (r1 - r0); - if (sMax < 1) { - sMax = 1; - } else if (sMax > 20) { - // sanity check - sMax = 20; - } - } - } - - // compute the number of steps into which circles must be divided to - // achieve a curve flatness of 0.1 pixel in device space for the - // largest circle (note that "device space" is 72 dpi when generating - // PostScript, hence the relatively small 0.1 pixel accuracy) - ctm = state->getCTM(); - t = fabs(ctm[0]); - if (fabs(ctm[1]) > t) { - t = fabs(ctm[1]); - } - if (fabs(ctm[2]) > t) { - t = fabs(ctm[2]); - } - if (fabs(ctm[3]) > t) { - t = fabs(ctm[3]); - } - if (r0 > r1) { - t *= r0; - } else { - t *= r1; - } - if (t < 1) { - n = 3; - } else { - n = (int)(M_PI / acos(1 - 0.1 / t)); - if (n < 3) { - n = 3; - } else if (n > 200) { - n = 200; - } - } - - // Traverse the t axis and do the shading. - // - // This generates and fills a series of rings. Each ring is defined - // by two circles: - // sa, ta, xa, ya, ra, colorA - // sb, tb, xb, yb, rb, colorB - // - // The s/t axis is divided into radialMaxSplits parts; these parts - // are combined as much as possible while respecting the - // radialColorDelta parameter. - - // setup for the start circle - ia = 0; - sa = sMin; - ta = t0 + sa * (t1 - t0); - xa = x0 + sa * (x1 - x0); - ya = y0 + sa * (y1 - y0); - ra = r0 + sa * (r1 - r0); - if (ta < t0) { - shading->getColor(t0, &colorA); - } else if (ta > t1) { - shading->getColor(t1, &colorA); - } else { - shading->getColor(ta, &colorA); - } - - while (ia < radialMaxSplits) { - - // go as far along the t axis (toward t1) as we can, such that the - // color difference is within the tolerance (radialColorDelta) -- - // this uses bisection (between the current value, t, and t1), - // limited to radialMaxSplits points along the t axis; require at - // least one split to avoid problems when the innermost and - // outermost colors are the same - ib = radialMaxSplits; - sb = sMin + ((double)ib / (double)radialMaxSplits) * (sMax - sMin); - tb = t0 + sb * (t1 - t0); - if (tb < t0) { - shading->getColor(t0, &colorB); - } else if (tb > t1) { - shading->getColor(t1, &colorB); - } else { - shading->getColor(tb, &colorB); - } - while (ib - ia > 1) { - for (k = 0; k < nComps; ++k) { - if (abs(colorB.c[k] - colorA.c[k]) > radialColorDelta) { - break; - } - } - if (k == nComps && ib < radialMaxSplits) { - break; - } - ib = (ia + ib) / 2; - sb = sMin + ((double)ib / (double)radialMaxSplits) * (sMax - sMin); - tb = t0 + sb * (t1 - t0); - if (tb < t0) { - shading->getColor(t0, &colorB); - } else if (tb > t1) { - shading->getColor(t1, &colorB); - } else { - shading->getColor(tb, &colorB); - } - } - - // compute center and radius of the circle - xb = x0 + sb * (x1 - x0); - yb = y0 + sb * (y1 - y0); - rb = r0 + sb * (r1 - r0); - - // use the average of the colors at the two circles - for (k = 0; k < nComps; ++k) { - colorA.c[k] = (colorA.c[k] + colorB.c[k]) / 2; - } - state->setFillColor(&colorA); - out->updateFillColor(state); - - // construct path for first circle - state->moveTo(xa + ra, ya); - for (k = 1; k < n; ++k) { - angle = ((double)k / (double)n) * 2 * M_PI; - state->lineTo(xa + ra * cos(angle), ya + ra * sin(angle)); - } - state->closePath(); - - // construct and append path for second circle - state->moveTo(xb + rb, yb); - for (k = 1; k < n; ++k) { - angle = ((double)k / (double)n) * 2 * M_PI; - state->lineTo(xb + rb * cos(angle), yb + rb * sin(angle)); - } - state->closePath(); - - // fill the ring - out->eoFill(state); - state->clearPath(); - - // step to the next value of t - ia = ib; - sa = sb; - ta = tb; - xa = xb; - ya = yb; - ra = rb; - colorA = colorB; - } - } -} - -void Gfx::doGouraudTriangleShFill(GfxGouraudTriangleShading *shading) { - double x0, y0, x1, y1, x2, y2; - GfxColor color0, color1, color2; - int i; - - for (i = 0; i < shading->getNTriangles(); ++i) { - shading->getTriangle(i, &x0, &y0, &color0, - &x1, &y1, &color1, - &x2, &y2, &color2); - gouraudFillTriangle(x0, y0, &color0, x1, y1, &color1, x2, y2, &color2, - shading->getColorSpace()->getNComps(), 0); - } -} - -void Gfx::gouraudFillTriangle(double x0, double y0, GfxColor *color0, - double x1, double y1, GfxColor *color1, - double x2, double y2, GfxColor *color2, - int nComps, int depth) { - double x01, y01, x12, y12, x20, y20; - GfxColor color01, color12, color20; - int i; - - for (i = 0; i < nComps; ++i) { - if (abs(color0->c[i] - color1->c[i]) > gouraudColorDelta || - abs(color1->c[i] - color2->c[i]) > gouraudColorDelta) { - break; - } - } - if (i == nComps || depth == gouraudMaxDepth) { - state->setFillColor(color0); - out->updateFillColor(state); - state->moveTo(x0, y0); - state->lineTo(x1, y1); - state->lineTo(x2, y2); - state->closePath(); - out->fill(state); - state->clearPath(); - } else { - x01 = 0.5 * (x0 + x1); - y01 = 0.5 * (y0 + y1); - x12 = 0.5 * (x1 + x2); - y12 = 0.5 * (y1 + y2); - x20 = 0.5 * (x2 + x0); - y20 = 0.5 * (y2 + y0); - //~ if the shading has a Function, this should interpolate on the - //~ function parameter, not on the color components - for (i = 0; i < nComps; ++i) { - color01.c[i] = (color0->c[i] + color1->c[i]) / 2; - color12.c[i] = (color1->c[i] + color2->c[i]) / 2; - color20.c[i] = (color2->c[i] + color0->c[i]) / 2; - } - gouraudFillTriangle(x0, y0, color0, x01, y01, &color01, - x20, y20, &color20, nComps, depth + 1); - gouraudFillTriangle(x01, y01, &color01, x1, y1, color1, - x12, y12, &color12, nComps, depth + 1); - gouraudFillTriangle(x01, y01, &color01, x12, y12, &color12, - x20, y20, &color20, nComps, depth + 1); - gouraudFillTriangle(x20, y20, &color20, x12, y12, &color12, - x2, y2, color2, nComps, depth + 1); - } -} - -void Gfx::doPatchMeshShFill(GfxPatchMeshShading *shading) { - int start, i; - - if (shading->getNPatches() > 128) { - start = 3; - } else if (shading->getNPatches() > 64) { - start = 2; - } else if (shading->getNPatches() > 16) { - start = 1; - } else { - start = 0; - } - for (i = 0; i < shading->getNPatches(); ++i) { - fillPatch(shading->getPatch(i), shading->getColorSpace()->getNComps(), - start); - } -} - -void Gfx::fillPatch(GfxPatch *patch, int nComps, int depth) { - GfxPatch patch00, patch01, patch10, patch11; - double xx[4][8], yy[4][8]; - double xxm, yym; - int i; - - for (i = 0; i < nComps; ++i) { - if (abs(patch->color[0][0].c[i] - patch->color[0][1].c[i]) - > patchColorDelta || - abs(patch->color[0][1].c[i] - patch->color[1][1].c[i]) - > patchColorDelta || - abs(patch->color[1][1].c[i] - patch->color[1][0].c[i]) - > patchColorDelta || - abs(patch->color[1][0].c[i] - patch->color[0][0].c[i]) - > patchColorDelta) { - break; - } - } - if (i == nComps || depth == patchMaxDepth) { - state->setFillColor(&patch->color[0][0]); - out->updateFillColor(state); - state->moveTo(patch->x[0][0], patch->y[0][0]); - state->curveTo(patch->x[0][1], patch->y[0][1], - patch->x[0][2], patch->y[0][2], - patch->x[0][3], patch->y[0][3]); - state->curveTo(patch->x[1][3], patch->y[1][3], - patch->x[2][3], patch->y[2][3], - patch->x[3][3], patch->y[3][3]); - state->curveTo(patch->x[3][2], patch->y[3][2], - patch->x[3][1], patch->y[3][1], - patch->x[3][0], patch->y[3][0]); - state->curveTo(patch->x[2][0], patch->y[2][0], - patch->x[1][0], patch->y[1][0], - patch->x[0][0], patch->y[0][0]); - state->closePath(); - out->fill(state); - state->clearPath(); - } else { - for (i = 0; i < 4; ++i) { - xx[i][0] = patch->x[i][0]; - yy[i][0] = patch->y[i][0]; - xx[i][1] = 0.5 * (patch->x[i][0] + patch->x[i][1]); - yy[i][1] = 0.5 * (patch->y[i][0] + patch->y[i][1]); - xxm = 0.5 * (patch->x[i][1] + patch->x[i][2]); - yym = 0.5 * (patch->y[i][1] + patch->y[i][2]); - xx[i][6] = 0.5 * (patch->x[i][2] + patch->x[i][3]); - yy[i][6] = 0.5 * (patch->y[i][2] + patch->y[i][3]); - xx[i][2] = 0.5 * (xx[i][1] + xxm); - yy[i][2] = 0.5 * (yy[i][1] + yym); - xx[i][5] = 0.5 * (xxm + xx[i][6]); - yy[i][5] = 0.5 * (yym + yy[i][6]); - xx[i][3] = xx[i][4] = 0.5 * (xx[i][2] + xx[i][5]); - yy[i][3] = yy[i][4] = 0.5 * (yy[i][2] + yy[i][5]); - xx[i][7] = patch->x[i][3]; - yy[i][7] = patch->y[i][3]; - } - for (i = 0; i < 4; ++i) { - patch00.x[0][i] = xx[0][i]; - patch00.y[0][i] = yy[0][i]; - patch00.x[1][i] = 0.5 * (xx[0][i] + xx[1][i]); - patch00.y[1][i] = 0.5 * (yy[0][i] + yy[1][i]); - xxm = 0.5 * (xx[1][i] + xx[2][i]); - yym = 0.5 * (yy[1][i] + yy[2][i]); - patch10.x[2][i] = 0.5 * (xx[2][i] + xx[3][i]); - patch10.y[2][i] = 0.5 * (yy[2][i] + yy[3][i]); - patch00.x[2][i] = 0.5 * (patch00.x[1][i] + xxm); - patch00.y[2][i] = 0.5 * (patch00.y[1][i] + yym); - patch10.x[1][i] = 0.5 * (xxm + patch10.x[2][i]); - patch10.y[1][i] = 0.5 * (yym + patch10.y[2][i]); - patch00.x[3][i] = 0.5 * (patch00.x[2][i] + patch10.x[1][i]); - patch00.y[3][i] = 0.5 * (patch00.y[2][i] + patch10.y[1][i]); - patch10.x[0][i] = patch00.x[3][i]; - patch10.y[0][i] = patch00.y[3][i]; - patch10.x[3][i] = xx[3][i]; - patch10.y[3][i] = yy[3][i]; - } - for (i = 4; i < 8; ++i) { - patch01.x[0][i-4] = xx[0][i]; - patch01.y[0][i-4] = yy[0][i]; - patch01.x[1][i-4] = 0.5 * (xx[0][i] + xx[1][i]); - patch01.y[1][i-4] = 0.5 * (yy[0][i] + yy[1][i]); - xxm = 0.5 * (xx[1][i] + xx[2][i]); - yym = 0.5 * (yy[1][i] + yy[2][i]); - patch11.x[2][i-4] = 0.5 * (xx[2][i] + xx[3][i]); - patch11.y[2][i-4] = 0.5 * (yy[2][i] + yy[3][i]); - patch01.x[2][i-4] = 0.5 * (patch01.x[1][i-4] + xxm); - patch01.y[2][i-4] = 0.5 * (patch01.y[1][i-4] + yym); - patch11.x[1][i-4] = 0.5 * (xxm + patch11.x[2][i-4]); - patch11.y[1][i-4] = 0.5 * (yym + patch11.y[2][i-4]); - patch01.x[3][i-4] = 0.5 * (patch01.x[2][i-4] + patch11.x[1][i-4]); - patch01.y[3][i-4] = 0.5 * (patch01.y[2][i-4] + patch11.y[1][i-4]); - patch11.x[0][i-4] = patch01.x[3][i-4]; - patch11.y[0][i-4] = patch01.y[3][i-4]; - patch11.x[3][i-4] = xx[3][i]; - patch11.y[3][i-4] = yy[3][i]; - } - //~ if the shading has a Function, this should interpolate on the - //~ function parameter, not on the color components - for (i = 0; i < nComps; ++i) { - patch00.color[0][0].c[i] = patch->color[0][0].c[i]; - patch00.color[0][1].c[i] = (patch->color[0][0].c[i] + - patch->color[0][1].c[i]) / 2; - patch01.color[0][0].c[i] = patch00.color[0][1].c[i]; - patch01.color[0][1].c[i] = patch->color[0][1].c[i]; - patch01.color[1][1].c[i] = (patch->color[0][1].c[i] + - patch->color[1][1].c[i]) / 2; - patch11.color[0][1].c[i] = patch01.color[1][1].c[i]; - patch11.color[1][1].c[i] = patch->color[1][1].c[i]; - patch11.color[1][0].c[i] = (patch->color[1][1].c[i] + - patch->color[1][0].c[i]) / 2; - patch10.color[1][1].c[i] = patch11.color[1][0].c[i]; - patch10.color[1][0].c[i] = patch->color[1][0].c[i]; - patch10.color[0][0].c[i] = (patch->color[1][0].c[i] + - patch->color[0][0].c[i]) / 2; - patch00.color[1][0].c[i] = patch10.color[0][0].c[i]; - patch00.color[1][1].c[i] = (patch00.color[1][0].c[i] + - patch01.color[1][1].c[i]) / 2; - patch01.color[1][0].c[i] = patch00.color[1][1].c[i]; - patch11.color[0][0].c[i] = patch00.color[1][1].c[i]; - patch10.color[0][1].c[i] = patch00.color[1][1].c[i]; - } - fillPatch(&patch00, nComps, depth + 1); - fillPatch(&patch10, nComps, depth + 1); - fillPatch(&patch01, nComps, depth + 1); - fillPatch(&patch11, nComps, depth + 1); - } -} - -void Gfx::doEndPath() { - if (state->isCurPt() && clip != clipNone) { - state->clip(); - if (clip == clipNormal) { - out->clip(state); - } else { - 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) { - out->endTextObject(state); -} - -//------------------------------------------------------------------------ -// 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 = res->lookupFont(args[0].getName()))) { - return; - } - if (printCommands) { - printf(" font: tag=%s name='%s' %g\n", - font->getTag()->getCString(), - font->getName() ? font->getName()->getCString() : "???", - args[1].getNum()); - fflush(stdout); - } - 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); - fontChanged = gTrue; -} - -//------------------------------------------------------------------------ -// 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; - } - if (fontChanged) { - out->updateFont(state); - fontChanged = gFalse; - } - out->beginStringOp(state); - doShowText(args[0].getString()); - out->endStringOp(state); -} - -void Gfx::opMoveShowText(Object args[], int numArgs) { - double tx, ty; - - if (!state->getFont()) { - error(getPos(), "No font in move/show"); - return; - } - if (fontChanged) { - out->updateFont(state); - fontChanged = gFalse; - } - tx = state->getLineX(); - ty = state->getLineY() - state->getLeading(); - state->textMoveTo(tx, ty); - out->updateTextPos(state); - out->beginStringOp(state); - doShowText(args[0].getString()); - out->endStringOp(state); -} - -void Gfx::opMoveSetShowText(Object args[], int numArgs) { - double tx, ty; - - if (!state->getFont()) { - error(getPos(), "No font in move/set/show"); - return; - } - if (fontChanged) { - out->updateFont(state); - fontChanged = gFalse; - } - 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); - out->beginStringOp(state); - doShowText(args[2].getString()); - out->endStringOp(state); -} - -void Gfx::opShowSpaceText(Object args[], int numArgs) { - Array *a; - Object obj; - int wMode; - int i; - - if (!state->getFont()) { - error(getPos(), "No font in show/space"); - return; - } - if (fontChanged) { - out->updateFont(state); - fontChanged = gFalse; - } - out->beginStringOp(state); - wMode = state->getFont()->getWMode(); - a = args[0].getArray(); - for (i = 0; i < a->getLength(); ++i) { - a->get(i, &obj); - if (obj.isNum()) { - // this uses the absolute value of the font size to match - // Acrobat's behavior - if (wMode) { - state->textShift(0, -obj.getNum() * 0.001 * - fabs(state->getFontSize())); - } else { - state->textShift(-obj.getNum() * 0.001 * - fabs(state->getFontSize()), 0); - } - 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(); - } - out->endStringOp(state); -} - -void Gfx::doShowText(GString *s) { - GfxFont *font; - int wMode; - double riseX, riseY; - CharCode code; - Unicode u[8]; - double x, y, dx, dy, dx2, dy2, curX, curY, tdx, tdy, lineX, lineY; - double originX, originY, tOriginX, tOriginY; - double oldCTM[6], newCTM[6]; - double *mat; - Object charProc; - Dict *resDict; - Parser *oldParser; - char *p; - int len, n, uLen, nChars, nSpaces, i; - - font = state->getFont(); - wMode = font->getWMode(); - - if (out->useDrawChar()) { - out->beginString(state, s); - } - - // handle a Type 3 char - if (font->getType() == fontType3 && out->interpretType3Chars()) { - 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[1] *= state->getFontSize(); - newCTM[2] *= state->getFontSize(); - newCTM[3] *= state->getFontSize(); - newCTM[0] *= state->getHorizScaling(); - newCTM[2] *= state->getHorizScaling(); - state->textTransformDelta(0, state->getRise(), &riseX, &riseY); - curX = state->getCurX(); - curY = state->getCurY(); - lineX = state->getLineX(); - lineY = state->getLineY(); - oldParser = parser; - p = s->getCString(); - len = s->getLength(); - while (len > 0) { - n = font->getNextChar(p, len, &code, - u, (int)(sizeof(u) / sizeof(Unicode)), &uLen, - &dx, &dy, &originX, &originY); - dx = dx * state->getFontSize() + state->getCharSpace(); - if (n == 1 && *p == ' ') { - dx += state->getWordSpace(); - } - dx *= state->getHorizScaling(); - dy *= state->getFontSize(); - state->textTransformDelta(dx, dy, &tdx, &tdy); - state->transform(curX + riseX, curY + riseY, &x, &y); - saveState(); - state->setCTM(newCTM[0], newCTM[1], newCTM[2], newCTM[3], x, y); - //~ out->updateCTM(???) - if (!out->beginType3Char(state, curX + riseX, curY + riseY, tdx, tdy, - code, u, uLen)) { - ((Gfx8BitFont *)font)->getCharProc(code, &charProc); - if ((resDict = ((Gfx8BitFont *)font)->getResources())) { - pushResources(resDict); - } - if (charProc.isStream()) { - display(&charProc, gFalse); - } else { - error(getPos(), "Missing or bad Type3 CharProc entry"); - } - out->endType3Char(state); - if (resDict) { - popResources(); - } - charProc.free(); - } - restoreState(); - // GfxState::restore() does *not* restore the current position, - // so we deal with it here using (curX, curY) and (lineX, lineY) - curX += tdx; - curY += tdy; - state->moveTo(curX, curY); - state->textSetPos(lineX, lineY); - p += n; - len -= n; - } - parser = oldParser; - - } else if (out->useDrawChar()) { - state->textTransformDelta(0, state->getRise(), &riseX, &riseY); - p = s->getCString(); - len = s->getLength(); - while (len > 0) { - n = font->getNextChar(p, len, &code, - u, (int)(sizeof(u) / sizeof(Unicode)), &uLen, - &dx, &dy, &originX, &originY); - if (wMode) { - dx *= state->getFontSize(); - dy = dy * state->getFontSize() + state->getCharSpace(); - if (n == 1 && *p == ' ') { - dy += state->getWordSpace(); - } - } else { - dx = dx * state->getFontSize() + state->getCharSpace(); - if (n == 1 && *p == ' ') { - dx += state->getWordSpace(); - } - dx *= state->getHorizScaling(); - dy *= state->getFontSize(); - } - state->textTransformDelta(dx, dy, &tdx, &tdy); - originX *= state->getFontSize(); - originY *= state->getFontSize(); - state->textTransformDelta(originX, originY, &tOriginX, &tOriginY); - out->drawChar(state, state->getCurX() + riseX, state->getCurY() + riseY, - tdx, tdy, tOriginX, tOriginY, code, n, u, uLen); - state->shift(tdx, tdy); - p += n; - len -= n; - } - - } else { - dx = dy = 0; - p = s->getCString(); - len = s->getLength(); - nChars = nSpaces = 0; - while (len > 0) { - n = font->getNextChar(p, len, &code, - u, (int)(sizeof(u) / sizeof(Unicode)), &uLen, - &dx2, &dy2, &originX, &originY); - dx += dx2; - dy += dy2; - if (n == 1 && *p == ' ') { - ++nSpaces; - } - ++nChars; - p += n; - len -= n; - } - if (wMode) { - dx *= state->getFontSize(); - dy = dy * state->getFontSize() - + nChars * state->getCharSpace() - + nSpaces * state->getWordSpace(); - } else { - dx = dx * state->getFontSize() - + nChars * state->getCharSpace() - + nSpaces * state->getWordSpace(); - dx *= state->getHorizScaling(); - dy *= state->getFontSize(); - } - state->textTransformDelta(dx, dy, &tdx, &tdy); - out->drawString(state, s); - state->shift(tdx, tdy); - } - - if (out->useDrawChar()) { - out->endString(state); - } - - updateLevel += 10 * s->getLength(); -} - -//------------------------------------------------------------------------ -// XObject operators -//------------------------------------------------------------------------ - -void Gfx::opXObject(Object args[], int numArgs) { - Object obj1, obj2, obj3, refObj; -#if OPI_SUPPORT - Object opiDict; -#endif - - if (!res->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")) { - if (out->needNonText()) { - res->lookupXObjectNF(args[0].getName(), &refObj); - doImage(&refObj, obj1.getStream(), gFalse); - refObj.free(); - } - } else if (obj2.isName("Form")) { - doForm(&obj1); - } else if (obj2.isName("PS")) { - obj1.streamGetDict()->lookup("Level1", &obj3); - out->psXObject(obj1.getStream(), - obj3.isStream() ? obj3.getStream() : (Stream *)NULL); - } 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(Object *ref, Stream *str, GBool inlineImg) { - Dict *dict, *maskDict; - int width, height; - int bits, maskBits; - StreamColorSpaceMode csMode; - GBool mask; - GBool invert; - GfxColorSpace *colorSpace, *maskColorSpace; - GfxImageColorMap *colorMap, *maskColorMap; - Object maskObj, smaskObj; - GBool haveColorKeyMask, haveExplicitMask, haveSoftMask; - int maskColors[2*gfxColorMaxComps]; - int maskWidth, maskHeight; - GBool maskInvert; - Stream *maskStr; - Object obj1, obj2; - int i; - - // get info from the stream - bits = 0; - csMode = streamCSNone; - str->getImageParams(&bits, &csMode); - - // 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 - if (bits == 0) { - dict->lookup("BitsPerComponent", &obj1); - if (obj1.isNull()) { - obj1.free(); - dict->lookup("BPC", &obj1); - } - if (obj1.isInt()) { - bits = obj1.getInt(); - } else if (mask) { - bits = 1; - } else { - goto err2; - } - 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, ref, 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()) { - res->lookupColorSpace(obj1.getName(), &obj2); - if (!obj2.isNull()) { - obj1.free(); - obj1 = obj2; - } else { - obj2.free(); - } - } - if (!obj1.isNull()) { - colorSpace = GfxColorSpace::parse(&obj1); - } else if (csMode == streamCSDeviceGray) { - colorSpace = new GfxDeviceGrayColorSpace(); - } else if (csMode == streamCSDeviceRGB) { - colorSpace = new GfxDeviceRGBColorSpace(); - } else if (csMode == streamCSDeviceCMYK) { - colorSpace = new GfxDeviceCMYKColorSpace(); - } else { - colorSpace = NULL; - } - obj1.free(); - if (!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 colorMap; - goto err1; - } - - // get the mask - haveColorKeyMask = haveExplicitMask = haveSoftMask = gFalse; - maskStr = NULL; // make gcc happy - maskWidth = maskHeight = 0; // make gcc happy - maskInvert = gFalse; // make gcc happy - maskColorMap = NULL; // make gcc happy - dict->lookup("Mask", &maskObj); - dict->lookup("SMask", &smaskObj); - if (smaskObj.isStream()) { - // soft mask - if (inlineImg) { - goto err1; - } - maskStr = smaskObj.getStream(); - maskDict = smaskObj.streamGetDict(); - maskDict->lookup("Width", &obj1); - if (obj1.isNull()) { - obj1.free(); - maskDict->lookup("W", &obj1); - } - if (!obj1.isInt()) { - goto err2; - } - maskWidth = obj1.getInt(); - obj1.free(); - maskDict->lookup("Height", &obj1); - if (obj1.isNull()) { - obj1.free(); - maskDict->lookup("H", &obj1); - } - if (!obj1.isInt()) { - goto err2; - } - maskHeight = obj1.getInt(); - obj1.free(); - maskDict->lookup("BitsPerComponent", &obj1); - if (obj1.isNull()) { - obj1.free(); - maskDict->lookup("BPC", &obj1); - } - if (!obj1.isInt()) { - goto err2; - } - maskBits = obj1.getInt(); - obj1.free(); - maskDict->lookup("ColorSpace", &obj1); - if (obj1.isNull()) { - obj1.free(); - maskDict->lookup("CS", &obj1); - } - if (obj1.isName()) { - res->lookupColorSpace(obj1.getName(), &obj2); - if (!obj2.isNull()) { - obj1.free(); - obj1 = obj2; - } else { - obj2.free(); - } - } - maskColorSpace = GfxColorSpace::parse(&obj1); - obj1.free(); - if (!maskColorSpace || maskColorSpace->getMode() != csDeviceGray) { - goto err1; - } - maskDict->lookup("Decode", &obj1); - if (obj1.isNull()) { - obj1.free(); - maskDict->lookup("D", &obj1); - } - maskColorMap = new GfxImageColorMap(maskBits, &obj1, maskColorSpace); - obj1.free(); - if (!maskColorMap->isOk()) { - delete maskColorMap; - goto err1; - } - //~ handle the Matte entry - haveSoftMask = gTrue; - } else if (maskObj.isArray()) { - // color key mask - for (i = 0; - i < maskObj.arrayGetLength() && i < 2*gfxColorMaxComps; - ++i) { - maskObj.arrayGet(i, &obj1); - maskColors[i] = obj1.getInt(); - obj1.free(); - } - haveColorKeyMask = gTrue; - } else if (maskObj.isStream()) { - // explicit mask - if (inlineImg) { - goto err1; - } - maskStr = maskObj.getStream(); - maskDict = maskObj.streamGetDict(); - maskDict->lookup("Width", &obj1); - if (obj1.isNull()) { - obj1.free(); - maskDict->lookup("W", &obj1); - } - if (!obj1.isInt()) { - goto err2; - } - maskWidth = obj1.getInt(); - obj1.free(); - maskDict->lookup("Height", &obj1); - if (obj1.isNull()) { - obj1.free(); - maskDict->lookup("H", &obj1); - } - if (!obj1.isInt()) { - goto err2; - } - maskHeight = obj1.getInt(); - obj1.free(); - maskDict->lookup("ImageMask", &obj1); - if (obj1.isNull()) { - obj1.free(); - maskDict->lookup("IM", &obj1); - } - if (!obj1.isBool() || !obj1.getBool()) { - goto err2; - } - obj1.free(); - maskInvert = gFalse; - maskDict->lookup("Decode", &obj1); - if (obj1.isNull()) { - obj1.free(); - maskDict->lookup("D", &obj1); - } - if (obj1.isArray()) { - obj1.arrayGet(0, &obj2); - if (obj2.isInt() && obj2.getInt() == 1) { - maskInvert = gTrue; - } - obj2.free(); - } else if (!obj1.isNull()) { - goto err2; - } - obj1.free(); - haveExplicitMask = gTrue; - } - - // draw it - if (haveSoftMask) { - out->drawSoftMaskedImage(state, ref, str, width, height, colorMap, - maskStr, maskWidth, maskHeight, maskColorMap); - delete maskColorMap; - } else if (haveExplicitMask) { - out->drawMaskedImage(state, ref, str, width, height, colorMap, - maskStr, maskWidth, maskHeight, maskInvert); - } else { - out->drawImage(state, ref, str, width, height, colorMap, - haveColorKeyMask ? maskColors : (int *)NULL, inlineImg); - } - delete colorMap; - - maskObj.free(); - smaskObj.free(); - } - - if ((i = width * height) > 1000) { - i = 1000; - } - updateLevel += i; - - return; - - err2: - obj1.free(); - err1: - error(getPos(), "Bad image parameters"); -} - -void Gfx::doForm(Object *str) { - Dict *dict; - Object matrixObj, bboxObj; - double m[6], bbox[6]; - Object resObj; - Dict *resDict; - Object obj1; - int i; - - // check for excessive recursion - if (formDepth > 20) { - return; - } - - // get stream dict - dict = str->streamGetDict(); - - // check form type - dict->lookup("FormType", &obj1); - if (!(obj1.isNull() || (obj1.isInt() && obj1.getInt() == 1))) { - error(getPos(), "Unknown form type"); - } - obj1.free(); - - // get bounding box - dict->lookup("BBox", &bboxObj); - if (!bboxObj.isArray()) { - matrixObj.free(); - bboxObj.free(); - error(getPos(), "Bad form bounding box"); - return; - } - for (i = 0; i < 4; ++i) { - bboxObj.arrayGet(i, &obj1); - bbox[i] = obj1.getNum(); - obj1.free(); - } - bboxObj.free(); - - // get matrix - dict->lookup("Matrix", &matrixObj); - if (matrixObj.isArray()) { - for (i = 0; i < 6; ++i) { - matrixObj.arrayGet(i, &obj1); - m[i] = obj1.getNum(); - obj1.free(); - } - } else { - m[0] = 1; m[1] = 0; - m[2] = 0; m[3] = 1; - m[4] = 0; m[5] = 0; - } - matrixObj.free(); - - // get resources - dict->lookup("Resources", &resObj); - resDict = resObj.isDict() ? resObj.getDict() : (Dict *)NULL; - - // draw it - ++formDepth; - doForm1(str, resDict, m, bbox); - --formDepth; - - resObj.free(); -} - -void Gfx::doAnnot(Object *str, double xMin, double yMin, - double xMax, double yMax) { - Dict *dict, *resDict; - Object matrixObj, bboxObj, resObj, flagsObj; - Object obj1; - double m[6], bbox[6], ictm[6]; - double *ctm; - double formX0, formY0, formX1, formY1; - double annotX0, annotY0, annotX1, annotY1; - double det, x, y, sx, sy; - int i, flags; - - // get stream dict - dict = str->streamGetDict(); - - // get annotation flags and only print annotations that are hidden or - // don't have the print bit set. - dict->lookup("F", &flagsObj); - if (flagsObj.isInt()) { - flags = flagsObj.getInt(); - } else { - // Print anything that doesn't have any flags set... - flags = 4; - } - flagsObj.free(); - - fprintf(stderr, "DEBUG: pdftops: doAnnot found annotation with flags = %x\n", - flags); - - if ((flags & 2) == 2 || (flags & 4) == 0) { - // Don't print hidden or no-print annotations... - return; - } - - // get the form bounding box - dict->lookup("BBox", &bboxObj); - if (!bboxObj.isArray()) { - bboxObj.free(); - error(getPos(), "Bad form bounding box"); - return; - } - for (i = 0; i < 4; ++i) { - bboxObj.arrayGet(i, &obj1); - bbox[i] = obj1.getNum(); - obj1.free(); - } - bboxObj.free(); - - // get the form matrix - dict->lookup("Matrix", &matrixObj); - if (matrixObj.isArray()) { - for (i = 0; i < 6; ++i) { - matrixObj.arrayGet(i, &obj1); - m[i] = obj1.getNum(); - obj1.free(); - } - } else { - m[0] = 1; m[1] = 0; - m[2] = 0; m[3] = 1; - m[4] = 0; m[5] = 0; - } - matrixObj.free(); - - // transform the form bbox from form space to user space - formX0 = bbox[0] * m[0] + bbox[1] * m[2] + m[4]; - formY0 = bbox[0] * m[1] + bbox[1] * m[3] + m[5]; - formX1 = bbox[2] * m[0] + bbox[3] * m[2] + m[4]; - formY1 = bbox[2] * m[1] + bbox[3] * m[3] + m[5]; - - // transform the annotation bbox from default user space to user - // space: (bbox * baseMatrix) * iCTM - ctm = state->getCTM(); - 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; - x = baseMatrix[0] * xMin + baseMatrix[2] * yMin + baseMatrix[4]; - y = baseMatrix[1] * xMin + baseMatrix[3] * yMin + baseMatrix[5]; - annotX0 = ictm[0] * x + ictm[2] * y + ictm[4]; - annotY0 = ictm[1] * x + ictm[3] * y + ictm[5]; - x = baseMatrix[0] * xMax + baseMatrix[2] * yMax + baseMatrix[4]; - y = baseMatrix[1] * xMax + baseMatrix[3] * yMax + baseMatrix[5]; - annotX1 = ictm[0] * x + ictm[2] * y + ictm[4]; - annotY1 = ictm[1] * x + ictm[3] * y + ictm[5]; - - // swap min/max coords - if (formX0 > formX1) { - x = formX0; formX0 = formX1; formX1 = x; - } - if (formY0 > formY1) { - y = formY0; formY0 = formY1; formY1 = y; - } - if (annotX0 > annotX1) { - x = annotX0; annotX0 = annotX1; annotX1 = x; - } - if (annotY0 > annotY1) { - y = annotY0; annotY0 = annotY1; annotY1 = y; - } - - // scale the form to fit the annotation bbox - if (formX1 == formX0) { - // this shouldn't happen - sx = 1; - } else { - sx = (annotX1 - annotX0) / (formX1 - formX0); - } - if (formY1 == formY0) { - // this shouldn't happen - sy = 1; - } else { - sy = (annotY1 - annotY0) / (formY1 - formY0); - } - m[0] *= sx; - m[2] *= sx; - m[4] = (m[4] - formX0) * sx + annotX0; - m[1] *= sy; - m[3] *= sy; - m[5] = (m[5] - formY0) * sy + annotY0; - - // get resources - dict->lookup("Resources", &resObj); - resDict = resObj.isDict() ? resObj.getDict() : (Dict *)NULL; - - // draw it - doForm1(str, resDict, m, bbox); - - resObj.free(); - bboxObj.free(); -} - -void Gfx::doForm1(Object *str, Dict *resDict, double *matrix, double *bbox) { - Parser *oldParser; - double oldBaseMatrix[6]; - int i; - - // push new resources on stack - pushResources(resDict); - - // save current graphics state - saveState(); - - // kill any pre-existing path - state->clearPath(); - - // save current parser - oldParser = parser; - - // set form transformation matrix - state->concatCTM(matrix[0], matrix[1], matrix[2], - matrix[3], matrix[4], matrix[5]); - out->updateCTM(state, matrix[0], matrix[1], matrix[2], - matrix[3], matrix[4], matrix[5]); - - // set new base matrix - for (i = 0; i < 6; ++i) { - oldBaseMatrix[i] = baseMatrix[i]; - baseMatrix[i] = state->getCTM()[i]; - } - - // set form bounding box - state->moveTo(bbox[0], bbox[1]); - state->lineTo(bbox[2], bbox[1]); - state->lineTo(bbox[2], bbox[3]); - state->lineTo(bbox[0], bbox[3]); - state->closePath(); - state->clip(); - out->clip(state); - state->clearPath(); - - // draw the form - display(str, gFalse); - - // restore base matrix - for (i = 0; i < 6; ++i) { - baseMatrix[i] = oldBaseMatrix[i]; - } - - // restore parser - parser = oldParser; - - // restore graphics state - restoreState(); - - // pop resource stack - popResources(); - - 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(NULL, 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(xref); - 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(); - } else { - key = copyString(obj.getName()); - obj.free(); - parser->getObj(&obj); - if (obj.isEOF() || obj.isError()) { - gfree(key); - break; - } - dict.dictAdd(key, &obj); - } - parser->getObj(&obj); - } - if (obj.isEOF()) { - error(getPos(), "End of file in inline image"); - obj.free(); - dict.free(); - return NULL; - } - obj.free(); - - // make stream - str = new EmbedStream(parser->getStream(), &dict, gFalse, 0); - 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) { - out->type3D0(state, args[0].getNum(), args[1].getNum()); -} - -void Gfx::opSetCacheDevice(Object args[], int numArgs) { - out->type3D1(state, args[0].getNum(), args[1].getNum(), - args[2].getNum(), args[3].getNum(), - args[4].getNum(), args[5].getNum()); -} - -//------------------------------------------------------------------------ -// 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"); - fflush(stdout); - } -} - -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"); - fflush(stdout); - } -} - -//------------------------------------------------------------------------ -// misc -//------------------------------------------------------------------------ - -void Gfx::saveState() { - out->saveState(state); - state = state->save(); -} - -void Gfx::restoreState() { - state = state->restore(); - out->restoreState(state); -} - -void Gfx::pushResources(Dict *resDict) { - res = new GfxResources(xref, resDict, res); -} - -void Gfx::popResources() { - GfxResources *resPtr; - - resPtr = res->getNext(); - delete res; - res = resPtr; -} diff --git a/pdftops/Gfx.h b/pdftops/Gfx.h deleted file mode 100644 index 04fdc9dec..000000000 --- a/pdftops/Gfx.h +++ /dev/null @@ -1,294 +0,0 @@ -//======================================================================== -// -// Gfx.h -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef GFX_H -#define GFX_H - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "gtypes.h" - -class GString; -class XRef; -class Array; -class Stream; -class Parser; -class Dict; -class OutputDev; -class GfxFontDict; -class GfxFont; -class GfxPattern; -class GfxTilingPattern; -class GfxShadingPattern; -class GfxShading; -class GfxFunctionShading; -class GfxAxialShading; -class GfxRadialShading; -class GfxGouraudTriangleShading; -class GfxPatchMeshShading; -struct GfxPatch; -class GfxState; -struct GfxColor; -class Gfx; -class PDFRectangle; - -//------------------------------------------------------------------------ -// 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(XRef *xref, Dict *resDict, GfxResources *nextA); - ~GfxResources(); - - GfxFont *lookupFont(char *name); - GBool lookupXObject(char *name, Object *obj); - GBool lookupXObjectNF(char *name, Object *obj); - void lookupColorSpace(char *name, Object *obj); - GfxPattern *lookupPattern(char *name); - GfxShading *lookupShading(char *name); - GBool lookupGState(char *name, Object *obj); - - GfxResources *getNext() { return next; } - -private: - - GfxFontDict *fonts; - Object xObjDict; - Object colorSpaceDict; - Object patternDict; - Object shadingDict; - Object gStateDict; - GfxResources *next; -}; - -class Gfx { -public: - - // Constructor for regular output. - Gfx(XRef *xrefA, OutputDev *outA, int pageNum, Dict *resDict, - double hDPI, double vDPI, PDFRectangle *box, - PDFRectangle *cropBox, int rotate, - GBool (*abortCheckCbkA)(void *data) = NULL, - void *abortCheckCbkDataA = NULL); - - // Constructor for a sub-page object. - Gfx(XRef *xrefA, OutputDev *outA, Dict *resDict, - PDFRectangle *box, PDFRectangle *cropBox, - GBool (*abortCheckCbkA)(void *data) = NULL, - void *abortCheckCbkDataA = NULL); - - ~Gfx(); - - // Interpret a stream or array of streams. - void display(Object *obj, GBool topLevel = gTrue); - - // Display an annotation, given its appearance (a Form XObject) and - // bounding box (in default user space). - void doAnnot(Object *str, double xMin, double yMin, - double xMax, double yMax); - - // Save graphics state. - void saveState(); - - // Restore graphics state. - void restoreState(); - - // Get the current graphics state object. - GfxState *getState() { return state; } - -private: - - XRef *xref; // the xref table for this PDF file - OutputDev *out; // output device - GBool subPage; // is this a sub-page object? - GBool printCommands; // print the drawing commands (for debugging) - GfxResources *res; // resource stack - int updateLevel; - - 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 - double baseMatrix[6]; // default matrix for most recent - // page/form/pattern - int formDepth; - - Parser *parser; // parser for page content stream(s) - - GBool // callback to check for an abort - (*abortCheckCbk)(void *data); - void *abortCheckCbkData; - GBool renderThisPage; // Render this page? - - static Operator opTab[]; // table of operators - - void go(GBool topLevel); - void execOp(Object *cmd, Object args[], int numArgs); - Operator *findOp(char *name); - GBool checkArg(Object *arg, TchkType type); - int getPos(); - - // 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 doPatternFill(GBool eoFill); - void doTilingPatternFill(GfxTilingPattern *tPat, GBool eoFill); - void doShadingPatternFill(GfxShadingPattern *sPat, GBool eoFill); - void opShFill(Object args[], int numArgs); - void doFunctionShFill(GfxFunctionShading *shading); - void doFunctionShFill1(GfxFunctionShading *shading, - double x0, double y0, - double x1, double y1, - GfxColor *colors, int depth); - void doAxialShFill(GfxAxialShading *shading); - void doRadialShFill(GfxRadialShading *shading); - void doGouraudTriangleShFill(GfxGouraudTriangleShading *shading); - void gouraudFillTriangle(double x0, double y0, GfxColor *color0, - double x1, double y1, GfxColor *color1, - double x2, double y2, GfxColor *color2, - int nComps, int depth); - void doPatchMeshShFill(GfxPatchMeshShading *shading); - void fillPatch(GfxPatch *patch, int nComps, int depth); - 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); - - // XObject operators - void opXObject(Object args[], int numArgs); - void doImage(Object *ref, Stream *str, GBool inlineImg); - void doForm(Object *str); - void doForm1(Object *str, Dict *resDict, double *matrix, double *bbox); - - // 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); - - void pushResources(Dict *resDict); - void popResources(); -}; - -#endif diff --git a/pdftops/GfxFont.cxx b/pdftops/GfxFont.cxx deleted file mode 100644 index c567c8591..000000000 --- a/pdftops/GfxFont.cxx +++ /dev/null @@ -1,1546 +0,0 @@ -//======================================================================== -// -// GfxFont.cc -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include "gmem.h" -#include "Error.h" -#include "Object.h" -#include "Dict.h" -#include "GlobalParams.h" -#include "CMap.h" -#include "CharCodeToUnicode.h" -#include "FontEncodingTables.h" -#include "BuiltinFontTables.h" -#include "FoFiType1.h" -#include "FoFiType1C.h" -#include "FoFiTrueType.h" -#include "GfxFont.h" - -//------------------------------------------------------------------------ - -struct StdFontMapEntry { - char *altName; - char *properName; -}; - -// Acrobat 4.0 and earlier substituted Base14-compatible fonts without -// providing Widths and a FontDescriptor, so we munge the names into -// the proper Base14 names. This table is from implementation note 44 -// in the PDF 1.4 spec, with some additions based on empirical -// evidence. -static StdFontMapEntry stdFontMap[] = { - { "Arial", "Helvetica" }, - { "Arial,Bold", "Helvetica-Bold" }, - { "Arial,BoldItalic", "Helvetica-BoldOblique" }, - { "Arial,Italic", "Helvetica-Oblique" }, - { "Arial-Bold", "Helvetica-Bold" }, - { "Arial-BoldItalic", "Helvetica-BoldOblique" }, - { "Arial-BoldItalicMT", "Helvetica-BoldOblique" }, - { "Arial-BoldMT", "Helvetica-Bold" }, - { "Arial-Italic", "Helvetica-Oblique" }, - { "Arial-ItalicMT", "Helvetica-Oblique" }, - { "ArialMT", "Helvetica" }, - { "Courier,Bold", "Courier-Bold" }, - { "Courier,BoldItalic", "Courier-BoldOblique" }, - { "Courier,Italic", "Courier-Oblique" }, - { "CourierNew", "Courier" }, - { "CourierNew,Bold", "Courier-Bold" }, - { "CourierNew,BoldItalic", "Courier-BoldOblique" }, - { "CourierNew,Italic", "Courier-Oblique" }, - { "CourierNew-Bold", "Courier-Bold" }, - { "CourierNew-BoldItalic", "Courier-BoldOblique" }, - { "CourierNew-Italic", "Courier-Oblique" }, - { "CourierNewPS-BoldItalicMT", "Courier-BoldOblique" }, - { "CourierNewPS-BoldMT", "Courier-Bold" }, - { "CourierNewPS-ItalicMT", "Courier-Oblique" }, - { "CourierNewPSMT", "Courier" }, - { "Helvetica,Bold", "Helvetica-Bold" }, - { "Helvetica,BoldItalic", "Helvetica-BoldOblique" }, - { "Helvetica,Italic", "Helvetica-Oblique" }, - { "Helvetica-BoldItalic", "Helvetica-BoldOblique" }, - { "Helvetica-Italic", "Helvetica-Oblique" }, - { "Symbol,Bold", "Symbol" }, - { "Symbol,BoldItalic", "Symbol" }, - { "Symbol,Italic", "Symbol" }, - { "TimesNewRoman", "Times-Roman" }, - { "TimesNewRoman,Bold", "Times-Bold" }, - { "TimesNewRoman,BoldItalic", "Times-BoldItalic" }, - { "TimesNewRoman,Italic", "Times-Italic" }, - { "TimesNewRoman-Bold", "Times-Bold" }, - { "TimesNewRoman-BoldItalic", "Times-BoldItalic" }, - { "TimesNewRoman-Italic", "Times-Italic" }, - { "TimesNewRomanPS", "Times-Roman" }, - { "TimesNewRomanPS-Bold", "Times-Bold" }, - { "TimesNewRomanPS-BoldItalic", "Times-BoldItalic" }, - { "TimesNewRomanPS-BoldItalicMT", "Times-BoldItalic" }, - { "TimesNewRomanPS-BoldMT", "Times-Bold" }, - { "TimesNewRomanPS-Italic", "Times-Italic" }, - { "TimesNewRomanPS-ItalicMT", "Times-Italic" }, - { "TimesNewRomanPSMT", "Times-Roman" }, - { "TimesNewRomanPSMT,Bold", "Times-Bold" }, - { "TimesNewRomanPSMT,BoldItalic", "Times-BoldItalic" }, - { "TimesNewRomanPSMT,Italic", "Times-Italic" } -}; - -//------------------------------------------------------------------------ -// GfxFont -//------------------------------------------------------------------------ - -GfxFont *GfxFont::makeFont(XRef *xref, char *tagA, Ref idA, Dict *fontDict) { - GString *nameA; - GfxFont *font; - Object obj1; - - // get base font name - nameA = NULL; - fontDict->lookup("BaseFont", &obj1); - if (obj1.isName()) { - nameA = new GString(obj1.getName()); - } - obj1.free(); - - // get font type - font = NULL; - fontDict->lookup("Subtype", &obj1); - if (obj1.isName("Type1") || obj1.isName("MMType1")) { - font = new Gfx8BitFont(xref, tagA, idA, nameA, fontType1, fontDict); - } else if (obj1.isName("Type1C")) { - font = new Gfx8BitFont(xref, tagA, idA, nameA, fontType1C, fontDict); - } else if (obj1.isName("Type3")) { - font = new Gfx8BitFont(xref, tagA, idA, nameA, fontType3, fontDict); - } else if (obj1.isName("TrueType")) { - font = new Gfx8BitFont(xref, tagA, idA, nameA, fontTrueType, fontDict); - } else if (obj1.isName("Type0")) { - font = new GfxCIDFont(xref, tagA, idA, nameA, fontDict); - } else { - error(-1, "Unknown font type: '%s'", - obj1.isName() ? obj1.getName() : "???"); - font = new Gfx8BitFont(xref, tagA, idA, nameA, fontUnknownType, fontDict); - } - obj1.free(); - - return font; -} - -GfxFont::GfxFont(char *tagA, Ref idA, GString *nameA) { - ok = gFalse; - tag = new GString(tagA); - id = idA; - name = nameA; - origName = nameA; - embFontName = NULL; - extFontFile = NULL; -} - -GfxFont::~GfxFont() { - delete tag; - if (origName && origName != name) { - delete origName; - } - if (name) { - delete name; - } - if (embFontName) { - delete embFontName; - } - if (extFontFile) { - delete extFontFile; - } -} - -void GfxFont::readFontDescriptor(XRef *xref, Dict *fontDict) { - Object obj1, obj2, obj3, obj4; - double t; - int i; - - // assume Times-Roman by default (for substitution purposes) - flags = fontSerif; - - embFontID.num = -1; - embFontID.gen = -1; - missingWidth = 0; - - if (fontDict->lookup("FontDescriptor", &obj1)->isDict()) { - - // get flags - if (obj1.dictLookup("Flags", &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 (obj1.dictLookupNF("FontFile", &obj2)->isRef()) { - embFontID = obj2.getRef(); - if (type != fontType1) { - error(-1, "Mismatch between font type and embedded font file"); - type = fontType1; - } - } - obj2.free(); - if (embFontID.num == -1 && - obj1.dictLookupNF("FontFile2", &obj2)->isRef()) { - embFontID = obj2.getRef(); - if (type != fontTrueType && type != fontCIDType2) { - error(-1, "Mismatch between font type and embedded font file"); - type = type == fontCIDType0 ? fontCIDType2 : fontTrueType; - } - } - obj2.free(); - if (embFontID.num == -1 && - obj1.dictLookupNF("FontFile3", &obj2)->isRef()) { - if (obj2.fetch(xref, &obj3)->isStream()) { - obj3.streamGetDict()->lookup("Subtype", &obj4); - if (obj4.isName("Type1")) { - embFontID = obj2.getRef(); - if (type != fontType1) { - error(-1, "Mismatch between font type and embedded font file"); - type = fontType1; - } - } else if (obj4.isName("Type1C")) { - embFontID = obj2.getRef(); - if (type != fontType1 && type != fontType1C) { - error(-1, "Mismatch between font type and embedded font file"); - } - type = fontType1C; - } else if (obj4.isName("TrueType")) { - embFontID = obj2.getRef(); - if (type != fontTrueType) { - error(-1, "Mismatch between font type and embedded font file"); - type = fontTrueType; - } - } else if (obj4.isName("CIDFontType0C")) { - embFontID = obj2.getRef(); - if (type != fontCIDType0) { - error(-1, "Mismatch between font type and embedded font file"); - } - type = fontCIDType0C; - } else { - error(-1, "Unknown embedded font type '%s'", - obj4.isName() ? obj4.getName() : "???"); - } - obj4.free(); - } - obj3.free(); - } - obj2.free(); - - // look for MissingWidth - obj1.dictLookup("MissingWidth", &obj2); - if (obj2.isNum()) { - missingWidth = obj2.getNum(); - } - obj2.free(); - - // get Ascent and Descent - obj1.dictLookup("Ascent", &obj2); - if (obj2.isNum()) { - t = 0.001 * obj2.getNum(); - // some broken font descriptors set ascent and descent to 0 - if (t != 0) { - ascent = t; - } - } - obj2.free(); - obj1.dictLookup("Descent", &obj2); - if (obj2.isNum()) { - t = 0.001 * obj2.getNum(); - // some broken font descriptors set ascent and descent to 0 - if (t != 0) { - descent = t; - } - // some broken font descriptors specify a positive descent - if (descent > 0) { - descent = -descent; - } - } - obj2.free(); - - // font FontBBox - if (obj1.dictLookup("FontBBox", &obj2)->isArray()) { - for (i = 0; i < 4 && i < obj2.arrayGetLength(); ++i) { - if (obj2.arrayGet(i, &obj3)->isNum()) { - fontBBox[i] = 0.001 * obj3.getNum(); - } - obj3.free(); - } - } - obj2.free(); - - } - obj1.free(); -} - -CharCodeToUnicode *GfxFont::readToUnicodeCMap(Dict *fontDict, int nBits, - CharCodeToUnicode *ctu) { - GString *buf; - Object obj1; - int c; - - if (!fontDict->lookup("ToUnicode", &obj1)->isStream()) { - obj1.free(); - return NULL; - } - buf = new GString(); - obj1.streamReset(); - while ((c = obj1.streamGetChar()) != EOF) { - buf->append(c); - } - obj1.streamClose(); - obj1.free(); - if (ctu) { - ctu->mergeCMap(buf, nBits); - } else { - ctu = CharCodeToUnicode::parseCMap(buf, nBits); - } - delete buf; - return ctu; -} - -void GfxFont::findExtFontFile() { - static char *type1Exts[] = { ".pfa", ".pfb", ".ps", "", NULL }; - static char *ttExts[] = { ".ttf", NULL }; - - if (name) { - if (type == fontType1) { - extFontFile = globalParams->findFontFile(name, type1Exts); - } else if (type == fontTrueType) { - extFontFile = globalParams->findFontFile(name, ttExts); - } - } -} - -char *GfxFont::readExtFontFile(int *len) { - FILE *f; - char *buf; - - if (!(f = fopen(extFontFile->getCString(), "rb"))) { - error(-1, "External font file '%s' vanished", extFontFile->getCString()); - 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->getCString()); - } - fclose(f); - return buf; -} - -char *GfxFont::readEmbFontFile(XRef *xref, int *len) { - char *buf; - Object obj1, obj2; - Stream *str; - int c; - int size, i; - - obj1.initRef(embFontID.num, embFontID.gen); - obj1.fetch(xref, &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; - str->close(); - - obj2.free(); - obj1.free(); - - return buf; -} - -//------------------------------------------------------------------------ -// Gfx8BitFont -//------------------------------------------------------------------------ - -Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA, - GfxFontType typeA, Dict *fontDict): - GfxFont(tagA, idA, nameA) -{ - GString *name2; - BuiltinFont *builtinFont; - char **baseEnc; - GBool baseEncFromFontFile; - char *buf; - int len; - FoFiType1 *ffT1; - FoFiType1C *ffT1C; - int code, code2; - char *charName; - GBool missing, hex; - Unicode toUnicode[256]; - CharCodeToUnicode *utu, *ctu2; - Unicode uBuf[8]; - double mul; - int firstChar, lastChar; - Gushort w; - Object obj1, obj2, obj3; - int n, i, a, b, m; - - type = typeA; - ctu = NULL; - - // do font name substitution for various aliases of the Base 14 font - // names - if (name) { - name2 = name->copy(); - i = 0; - while (i < name2->getLength()) { - if (name2->getChar(i) == ' ') { - name2->del(i); - } else { - ++i; - } - } - a = 0; - b = sizeof(stdFontMap) / sizeof(StdFontMapEntry); - // invariant: stdFontMap[a].altName <= name2 < stdFontMap[b].altName - while (b - a > 1) { - m = (a + b) / 2; - if (name2->cmp(stdFontMap[m].altName) >= 0) { - a = m; - } else { - b = m; - } - } - if (!name2->cmp(stdFontMap[a].altName)) { - name = new GString(stdFontMap[a].properName); - } - delete name2; - } - - // is it a built-in font? - builtinFont = NULL; - if (name) { - for (i = 0; i < nBuiltinFonts; ++i) { - if (!name->cmp(builtinFonts[i].name)) { - builtinFont = &builtinFonts[i]; - break; - } - } - } - - // default ascent/descent values - if (builtinFont) { - ascent = 0.001 * builtinFont->ascent; - descent = 0.001 * builtinFont->descent; - fontBBox[0] = 0.001 * builtinFont->bbox[0]; - fontBBox[1] = 0.001 * builtinFont->bbox[1]; - fontBBox[2] = 0.001 * builtinFont->bbox[2]; - fontBBox[3] = 0.001 * builtinFont->bbox[3]; - } else { - ascent = 0.95; - descent = -0.35; - fontBBox[0] = fontBBox[1] = fontBBox[2] = fontBBox[3] = 0; - } - - // get info from font descriptor - readFontDescriptor(xref, fontDict); - - // for non-embedded fonts, don't trust the ascent/descent/bbox - // values from the font descriptor - if (builtinFont && embFontID.num < 0) { - ascent = 0.001 * builtinFont->ascent; - descent = 0.001 * builtinFont->descent; - fontBBox[0] = 0.001 * builtinFont->bbox[0]; - fontBBox[1] = 0.001 * builtinFont->bbox[1]; - fontBBox[2] = 0.001 * builtinFont->bbox[2]; - fontBBox[3] = 0.001 * builtinFont->bbox[3]; - } - - // look for an external font file - 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 Type 3 bounding box, font definition, and resources - if (type == fontType3) { - if (fontDict->lookup("FontBBox", &obj1)->isArray()) { - for (i = 0; i < 4 && i < obj1.arrayGetLength(); ++i) { - if (obj1.arrayGet(i, &obj2)->isNum()) { - fontBBox[i] = obj2.getNum(); - } - obj2.free(); - } - } - obj1.free(); - if (!fontDict->lookup("CharProcs", &charProcs)->isDict()) { - error(-1, "Missing or invalid CharProcs dictionary in Type 3 font"); - charProcs.free(); - } - if (!fontDict->lookup("Resources", &resources)->isDict()) { - resources.free(); - } - } - - //----- build the font encoding ----- - - // Encodings start with a base encoding, which can come from - // (in order of priority): - // 1. FontDict.Encoding or FontDict.Encoding.BaseEncoding - // - MacRoman / MacExpert / WinAnsi / Standard - // 2. embedded or external font file - // 3. default: - // - builtin --> builtin encoding - // - TrueType --> WinAnsiEncoding - // - others --> StandardEncoding - // and then add a list of differences (if any) from - // FontDict.Encoding.Differences. - - // check FontDict for base encoding - hasEncoding = gFalse; - usesMacRomanEnc = gFalse; - baseEnc = NULL; - baseEncFromFontFile = gFalse; - fontDict->lookup("Encoding", &obj1); - if (obj1.isDict()) { - obj1.dictLookup("BaseEncoding", &obj2); - if (obj2.isName("MacRomanEncoding")) { - hasEncoding = gTrue; - usesMacRomanEnc = gTrue; - baseEnc = macRomanEncoding; - } else if (obj2.isName("MacExpertEncoding")) { - hasEncoding = gTrue; - baseEnc = macExpertEncoding; - } else if (obj2.isName("WinAnsiEncoding")) { - hasEncoding = gTrue; - baseEnc = winAnsiEncoding; - } - obj2.free(); - } else if (obj1.isName("MacRomanEncoding")) { - hasEncoding = gTrue; - usesMacRomanEnc = gTrue; - baseEnc = macRomanEncoding; - } else if (obj1.isName("MacExpertEncoding")) { - hasEncoding = gTrue; - baseEnc = macExpertEncoding; - } else if (obj1.isName("WinAnsiEncoding")) { - hasEncoding = gTrue; - baseEnc = winAnsiEncoding; - } - - // check embedded or external font file for base encoding - // (only for Type 1 fonts - trying to get an encoding out of a - // TrueType font is a losing proposition) - ffT1 = NULL; - ffT1C = NULL; - buf = NULL; - if (type == fontType1 && (extFontFile || embFontID.num >= 0)) { - if (extFontFile) { - ffT1 = FoFiType1::load(extFontFile->getCString()); - } else { - buf = readEmbFontFile(xref, &len); - ffT1 = FoFiType1::make(buf, len); - } - if (ffT1) { - if (ffT1->getName()) { - if (embFontName) { - delete embFontName; - } - embFontName = new GString(ffT1->getName()); - } - if (!baseEnc) { - baseEnc = ffT1->getEncoding(); - baseEncFromFontFile = gTrue; - } - } - } else if (type == fontType1C && (extFontFile || embFontID.num >= 0)) { - if (extFontFile) { - ffT1C = FoFiType1C::load(extFontFile->getCString()); - } else { - buf = readEmbFontFile(xref, &len); - ffT1C = FoFiType1C::make(buf, len); - } - if (ffT1C) { - if (ffT1C->getName()) { - if (embFontName) { - delete embFontName; - } - embFontName = new GString(ffT1C->getName()); - } - if (!baseEnc) { - baseEnc = ffT1C->getEncoding(); - baseEncFromFontFile = gTrue; - } - } - } - if (buf) { - gfree(buf); - } - - // get default base encoding - if (!baseEnc) { - if (builtinFont && embFontID.num < 0) { - baseEnc = builtinFont->defaultBaseEnc; - hasEncoding = gTrue; - } else if (type == fontTrueType) { - baseEnc = winAnsiEncoding; - } else { - baseEnc = standardEncoding; - } - } - - // copy the base encoding - for (i = 0; i < 256; ++i) { - enc[i] = baseEnc[i]; - if ((encFree[i] = baseEncFromFontFile) && enc[i]) { - enc[i] = copyString(baseEnc[i]); - } - } - - // some Type 1C font files have empty encodings, which can break the - // T1C->T1 conversion (since the 'seac' operator depends on having - // the accents in the encoding), so we fill in any gaps from - // StandardEncoding - if (type == fontType1C && (extFontFile || embFontID.num >= 0) && - baseEncFromFontFile) { - for (i = 0; i < 256; ++i) { - if (!enc[i] && standardEncoding[i]) { - enc[i] = standardEncoding[i]; - encFree[i] = gFalse; - } - } - } - - // merge differences into encoding - if (obj1.isDict()) { - obj1.dictLookup("Differences", &obj2); - if (obj2.isArray()) { - hasEncoding = gTrue; - 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 >= 0 && code < 256) { - if (encFree[code]) { - gfree(enc[code]); - } - enc[code] = copyString(obj3.getName()); - encFree[code] = gTrue; - } - ++code; - } else { - error(-1, "Wrong type in font encoding resource differences (%s)", - obj3.getTypeName()); - } - obj3.free(); - } - } - obj2.free(); - } - obj1.free(); - if (ffT1) { - delete ffT1; - } - if (ffT1C) { - delete ffT1C; - } - - //----- build the mapping to Unicode ----- - - // pass 1: use the name-to-Unicode mapping table - missing = hex = gFalse; - for (code = 0; code < 256; ++code) { - if ((charName = enc[code])) { - if (!(toUnicode[code] = globalParams->mapNameToUnicode(charName)) && - strcmp(charName, ".notdef")) { - // if it wasn't in the name-to-Unicode table, check for a - // name that looks like 'Axx' or 'xx', where 'A' is any letter - // and 'xx' is two hex digits - if ((strlen(charName) == 3 && - isalpha(charName[0]) && - isxdigit(charName[1]) && isxdigit(charName[2]) && - ((charName[1] >= 'a' && charName[1] <= 'f') || - (charName[1] >= 'A' && charName[1] <= 'F') || - (charName[2] >= 'a' && charName[2] <= 'f') || - (charName[2] >= 'A' && charName[2] <= 'F'))) || - (strlen(charName) == 2 && - isxdigit(charName[0]) && isxdigit(charName[1]) && - ((charName[0] >= 'a' && charName[0] <= 'f') || - (charName[0] >= 'A' && charName[0] <= 'F') || - (charName[1] >= 'a' && charName[1] <= 'f') || - (charName[1] >= 'A' && charName[1] <= 'F')))) { - hex = gTrue; - } - missing = gTrue; - } - } else { - toUnicode[code] = 0; - } - } - - // pass 2: try to fill in the missing chars, looking for names of - // the form 'Axx', 'xx', 'Ann', 'ABnn', or 'nn', where 'A' and 'B' - // are any letters, 'xx' is two hex digits, and 'nn' is 2-4 - // decimal digits - if (missing && globalParams->getMapNumericCharNames()) { - for (code = 0; code < 256; ++code) { - if ((charName = enc[code]) && !toUnicode[code] && - strcmp(charName, ".notdef")) { - n = strlen(charName); - code2 = -1; - if (hex && n == 3 && isalpha(charName[0]) && - isxdigit(charName[1]) && isxdigit(charName[2])) { - sscanf(charName+1, "%x", &code2); - } else if (hex && n == 2 && - isxdigit(charName[0]) && isxdigit(charName[1])) { - sscanf(charName, "%x", &code2); - } else if (!hex && n >= 2 && n <= 4 && - isdigit(charName[0]) && isdigit(charName[1])) { - code2 = atoi(charName); - } else if (n >= 3 && n <= 5 && - isdigit(charName[1]) && isdigit(charName[2])) { - code2 = atoi(charName+1); - } else if (n >= 4 && n <= 6 && - isdigit(charName[2]) && isdigit(charName[3])) { - code2 = atoi(charName+2); - } - if (code2 >= 0 && code2 <= 0xff) { - toUnicode[code] = (Unicode)code2; - } - } - } - } - - // construct the char code -> Unicode mapping object - ctu = CharCodeToUnicode::make8BitToUnicode(toUnicode); - - // merge in a ToUnicode CMap, if there is one -- this overwrites - // existing entries in ctu, i.e., the ToUnicode CMap takes - // precedence, but the other encoding info is allowed to fill in any - // holes - readToUnicodeCMap(fontDict, 8, ctu); - - // look for a Unicode-to-Unicode mapping - if (name && (utu = globalParams->getUnicodeToUnicode(name))) { - for (i = 0; i < 256; ++i) { - toUnicode[i] = 0; - } - ctu2 = CharCodeToUnicode::make8BitToUnicode(toUnicode); - for (i = 0; i < 256; ++i) { - n = ctu->mapToUnicode((CharCode)i, uBuf, 8); - if (n >= 1) { - n = utu->mapToUnicode((CharCode)uBuf[0], uBuf, 8); - if (n >= 1) { - ctu2->setMapping((CharCode)i, uBuf, n); - } - } - } - utu->decRefCnt(); - delete ctu; - ctu = ctu2; - } - - //----- get the character widths ----- - - // initialize all widths - for (code = 0; code < 256; ++code) { - widths[code] = missingWidth * 0.001; - } - - // use widths from font dict, if present - fontDict->lookup("FirstChar", &obj1); - firstChar = obj1.isInt() ? obj1.getInt() : 0; - obj1.free(); - if (firstChar < 0 || firstChar > 255) { - firstChar = 0; - } - fontDict->lookup("LastChar", &obj1); - lastChar = obj1.isInt() ? obj1.getInt() : 255; - obj1.free(); - if (lastChar < 0 || lastChar > 255) { - lastChar = 255; - } - mul = (type == fontType3) ? fontMat[0] : 0.001; - fontDict->lookup("Widths", &obj1); - if (obj1.isArray()) { - flags |= fontFixedWidth; - if (obj1.arrayGetLength() < lastChar - firstChar + 1) { - lastChar = firstChar + obj1.arrayGetLength() - 1; - } - for (code = firstChar; code <= lastChar; ++code) { - obj1.arrayGet(code - firstChar, &obj2); - if (obj2.isNum()) { - widths[code] = obj2.getNum() * mul; - if (widths[code] != widths[firstChar]) { - flags &= ~fontFixedWidth; - } - } - obj2.free(); - } - - // use widths from built-in font - } else if (builtinFont) { - // this is a kludge for broken PDF files that encode char 32 - // as .notdef - if (builtinFont->widths->getWidth("space", &w)) { - widths[32] = 0.001 * w; - } - for (code = 0; code < 256; ++code) { - if (enc[code] && builtinFont->widths->getWidth(enc[code], &w)) { - widths[code] = 0.001 * w; - } - } - - // couldn't find widths -- use defaults - } else { - // this is technically an error -- the Widths entry is required - // for all but the Base-14 fonts -- but certain PDF generators - // apparently don't include widths for Arial and TimesNewRoman - if (isFixedWidth()) { - i = 0; - } else if (isSerif()) { - i = 8; - } else { - i = 4; - } - if (isBold()) { - i += 2; - } - if (isItalic()) { - i += 1; - } - builtinFont = builtinFontSubst[i]; - // this is a kludge for broken PDF files that encode char 32 - // as .notdef - if (builtinFont->widths->getWidth("space", &w)) { - widths[32] = 0.001 * w; - } - for (code = 0; code < 256; ++code) { - if (enc[code] && builtinFont->widths->getWidth(enc[code], &w)) { - widths[code] = 0.001 * w; - } - } - } - obj1.free(); - - ok = gTrue; -} - -Gfx8BitFont::~Gfx8BitFont() { - int i; - - for (i = 0; i < 256; ++i) { - if (encFree[i] && enc[i]) { - gfree(enc[i]); - } - } - ctu->decRefCnt(); - if (charProcs.isDict()) { - charProcs.free(); - } - if (resources.isDict()) { - resources.free(); - } -} - -int Gfx8BitFont::getNextChar(char *s, int len, CharCode *code, - Unicode *u, int uSize, int *uLen, - double *dx, double *dy, double *ox, double *oy) { - CharCode c; - - *code = c = (CharCode)(*s & 0xff); - *uLen = ctu->mapToUnicode(c, u, uSize); - *dx = widths[c]; - *dy = *ox = *oy = 0; - return 1; -} - -CharCodeToUnicode *Gfx8BitFont::getToUnicode() { - ctu->incRefCnt(); - return ctu; -} - -Gushort *Gfx8BitFont::getCodeToGIDMap(FoFiTrueType *ff) { - Gushort *map; - int cmapPlatform, cmapEncoding; - int unicodeCmap, macRomanCmap, msSymbolCmap, cmap; - GBool useMacRoman, useUnicode; - char *charName; - Unicode u; - int code, i, n; - - map = (Gushort *)gmallocn(256, sizeof(Gushort)); - for (i = 0; i < 256; ++i) { - map[i] = 0; - } - - // To match up with the Adobe-defined behaviour, we choose a cmap - // like this: - // 1. If the PDF font has an encoding: - // 1a. If the PDF font specified MacRomanEncoding and the - // TrueType font has a Macintosh Roman cmap, use it, and - // reverse map the char names through MacRomanEncoding to - // get char codes. - // 1b. If the TrueType font has a Microsoft Unicode cmap or a - // non-Microsoft Unicode cmap, use it, and use the Unicode - // indexes, not the char codes. - // 1c. If the PDF font is symbolic and the TrueType font has a - // Microsoft Symbol cmap, use it, and use char codes - // directly (possibly with an offset of 0xf000). - // 1d. If the TrueType font has a Macintosh Roman cmap, use it, - // as in case 1a. - // 2. If the PDF font does not have an encoding or the PDF font is - // symbolic: - // 2a. If the TrueType font has a Macintosh Roman cmap, use it, - // and use char codes directly (possibly with an offset of - // 0xf000). - // 2b. If the TrueType font has a Microsoft Symbol cmap, use it, - // and use char codes directly (possible with an offset of - // 0xf000). - // 3. If none of these rules apply, use the first cmap and hope for - // the best (this shouldn't happen). - unicodeCmap = macRomanCmap = msSymbolCmap = -1; - for (i = 0; i < ff->getNumCmaps(); ++i) { - cmapPlatform = ff->getCmapPlatform(i); - cmapEncoding = ff->getCmapEncoding(i); - if ((cmapPlatform == 3 && cmapEncoding == 1) || - cmapPlatform == 0) { - unicodeCmap = i; - } else if (cmapPlatform == 1 && cmapEncoding == 0) { - macRomanCmap = i; - } else if (cmapPlatform == 3 && cmapEncoding == 0) { - msSymbolCmap = i; - } - } - cmap = 0; - useMacRoman = gFalse; - useUnicode = gFalse; - if (hasEncoding) { - if (usesMacRomanEnc && macRomanCmap >= 0) { - cmap = macRomanCmap; - useMacRoman = gTrue; - } else if (unicodeCmap >= 0) { - cmap = unicodeCmap; - useUnicode = gTrue; - } else if ((flags & fontSymbolic) && msSymbolCmap >= 0) { - cmap = msSymbolCmap; - } else if ((flags & fontSymbolic) && macRomanCmap >= 0) { - cmap = macRomanCmap; - } else if (macRomanCmap >= 0) { - cmap = macRomanCmap; - useMacRoman = gTrue; - } - } else { - if (macRomanCmap >= 0) { - cmap = macRomanCmap; - } else if (msSymbolCmap >= 0) { - cmap = msSymbolCmap; - } - } - - // reverse map the char names through MacRomanEncoding, then map the - // char codes through the cmap - if (useMacRoman) { - for (i = 0; i < 256; ++i) { - if ((charName = enc[i])) { - if ((code = globalParams->getMacRomanCharCode(charName))) { - map[i] = ff->mapCodeToGID(cmap, code); - } - } - } - - // map Unicode through the cmap - } else if (useUnicode) { - for (i = 0; i < 256; ++i) { - if (((charName = enc[i]) && - (u = globalParams->mapNameToUnicode(charName))) || - (n = ctu->mapToUnicode((CharCode)i, &u, 1))) { - map[i] = ff->mapCodeToGID(cmap, u); - } - } - - // map the char codes through the cmap, possibly with an offset of - // 0xf000 - } else { - for (i = 0; i < 256; ++i) { - if (!(map[i] = ff->mapCodeToGID(cmap, i))) { - map[i] = ff->mapCodeToGID(cmap, 0xf000 + i); - } - } - } - - // try the TrueType 'post' table to handle any unmapped characters - for (i = 0; i < 256; ++i) { - if (!map[i] && (charName = enc[i])) { - map[i] = (Gushort)(long)ff->mapNameToGID(charName); - } - } - - return map; -} - -Dict *Gfx8BitFont::getCharProcs() { - return charProcs.isDict() ? charProcs.getDict() : (Dict *)NULL; -} - -Object *Gfx8BitFont::getCharProc(int code, Object *proc) { - if (enc[code] && charProcs.isDict()) { - charProcs.dictLookup(enc[code], proc); - } else { - proc->initNull(); - } - return proc; -} - -Dict *Gfx8BitFont::getResources() { - return resources.isDict() ? resources.getDict() : (Dict *)NULL; -} - -//------------------------------------------------------------------------ -// GfxCIDFont -//------------------------------------------------------------------------ - -static int CDECL cmpWidthExcep(const void *w1, const void *w2) { - return ((GfxFontCIDWidthExcep *)w1)->first - - ((GfxFontCIDWidthExcep *)w2)->first; -} - -static int CDECL cmpWidthExcepV(const void *w1, const void *w2) { - return ((GfxFontCIDWidthExcepV *)w1)->first - - ((GfxFontCIDWidthExcepV *)w2)->first; -} - -GfxCIDFont::GfxCIDFont(XRef *xref, char *tagA, Ref idA, GString *nameA, - Dict *fontDict): - GfxFont(tagA, idA, nameA) -{ - Dict *desFontDict; - GString *collection, *cMapName; - Object desFontDictObj; - Object obj1, obj2, obj3, obj4, obj5, obj6; - CharCodeToUnicode *utu; - CharCode c; - Unicode uBuf[8]; - int c1, c2; - int excepsSize, i, j, k, n; - - ascent = 0.95; - descent = -0.35; - fontBBox[0] = fontBBox[1] = fontBBox[2] = fontBBox[3] = 0; - cMap = NULL; - ctu = NULL; - widths.defWidth = 1.0; - widths.defHeight = -1.0; - widths.defVY = 0.880; - widths.exceps = NULL; - widths.nExceps = 0; - widths.excepsV = NULL; - widths.nExcepsV = 0; - cidToGID = NULL; - cidToGIDLen = 0; - - // get the descendant font - if (!fontDict->lookup("DescendantFonts", &obj1)->isArray()) { - error(-1, "Missing DescendantFonts entry in Type 0 font"); - obj1.free(); - goto err1; - } - if (!obj1.arrayGet(0, &desFontDictObj)->isDict()) { - error(-1, "Bad descendant font in Type 0 font"); - goto err3; - } - obj1.free(); - desFontDict = desFontDictObj.getDict(); - - // font type - if (!desFontDict->lookup("Subtype", &obj1)) { - error(-1, "Missing Subtype entry in Type 0 descendant font"); - goto err3; - } - if (obj1.isName("CIDFontType0")) { - type = fontCIDType0; - } else if (obj1.isName("CIDFontType2")) { - type = fontCIDType2; - } else { - error(-1, "Unknown Type 0 descendant font type '%s'", - obj1.isName() ? obj1.getName() : "???"); - goto err3; - } - obj1.free(); - - // get info from font descriptor - readFontDescriptor(xref, desFontDict); - - // look for an external font file - findExtFontFile(); - - //----- encoding info ----- - - // char collection - if (!desFontDict->lookup("CIDSystemInfo", &obj1)->isDict()) { - error(-1, "Missing CIDSystemInfo dictionary in Type 0 descendant font"); - goto err3; - } - obj1.dictLookup("Registry", &obj2); - obj1.dictLookup("Ordering", &obj3); - if (!obj2.isString() || !obj3.isString()) { - error(-1, "Invalid CIDSystemInfo dictionary in Type 0 descendant font"); - goto err4; - } - collection = obj2.getString()->copy()->append('-')->append(obj3.getString()); - obj3.free(); - obj2.free(); - obj1.free(); - - // look for a ToUnicode CMap - if (!(ctu = readToUnicodeCMap(fontDict, 16, NULL))) { - - // the "Adobe-Identity" and "Adobe-UCS" collections don't have - // cidToUnicode files - if (collection->cmp("Adobe-Identity") && - collection->cmp("Adobe-UCS")) { - - // look for a user-supplied .cidToUnicode file - if (!(ctu = globalParams->getCIDToUnicode(collection))) { - error(-1, "Unknown character collection '%s'", - collection->getCString()); - // fall-through, assuming the Identity mapping -- this appears - // to match Adobe's behavior - } - } - } - - // look for a Unicode-to-Unicode mapping - if (name && (utu = globalParams->getUnicodeToUnicode(name))) { - if (ctu) { - for (c = 0; c < ctu->getLength(); ++c) { - n = ctu->mapToUnicode(c, uBuf, 8); - if (n >= 1) { - n = utu->mapToUnicode((CharCode)uBuf[0], uBuf, 8); - if (n >= 1) { - ctu->setMapping(c, uBuf, n); - } - } - } - utu->decRefCnt(); - } else { - ctu = utu; - } - } - - // encoding (i.e., CMap) - //~ need to handle a CMap stream here - //~ also need to deal with the UseCMap entry in the stream dict - if (!fontDict->lookup("Encoding", &obj1)->isName()) { - error(-1, "Missing or invalid Encoding entry in Type 0 font"); - delete collection; - goto err3; - } - cMapName = new GString(obj1.getName()); - obj1.free(); - if (!(cMap = globalParams->getCMap(collection, cMapName))) { - error(-1, "Unknown CMap '%s' for character collection '%s'", - cMapName->getCString(), collection->getCString()); - delete collection; - delete cMapName; - goto err2; - } - delete collection; - delete cMapName; - - // CIDToGIDMap (for embedded TrueType fonts) - if (type == fontCIDType2) { - desFontDict->lookup("CIDToGIDMap", &obj1); - if (obj1.isStream()) { - cidToGIDLen = 0; - i = 64; - cidToGID = (Gushort *)gmallocn(i, sizeof(Gushort)); - obj1.streamReset(); - while ((c1 = obj1.streamGetChar()) != EOF && - (c2 = obj1.streamGetChar()) != EOF) { - if (cidToGIDLen == i) { - i *= 2; - cidToGID = (Gushort *)greallocn(cidToGID, i, sizeof(Gushort)); - } - cidToGID[cidToGIDLen++] = (Gushort)((c1 << 8) + c2); - } - } else if (!obj1.isName("Identity") && !obj1.isNull()) { - error(-1, "Invalid CIDToGIDMap entry in CID font"); - } - obj1.free(); - } - - //----- character metrics ----- - - // default char width - if (desFontDict->lookup("DW", &obj1)->isInt()) { - widths.defWidth = obj1.getInt() * 0.001; - } - obj1.free(); - - // char width exceptions - if (desFontDict->lookup("W", &obj1)->isArray()) { - excepsSize = 0; - i = 0; - while (i + 1 < obj1.arrayGetLength()) { - obj1.arrayGet(i, &obj2); - obj1.arrayGet(i + 1, &obj3); - if (obj2.isInt() && obj3.isInt() && i + 2 < obj1.arrayGetLength()) { - if (obj1.arrayGet(i + 2, &obj4)->isNum()) { - if (widths.nExceps == excepsSize) { - excepsSize += 16; - widths.exceps = (GfxFontCIDWidthExcep *) - greallocn(widths.exceps, - excepsSize, sizeof(GfxFontCIDWidthExcep)); - } - widths.exceps[widths.nExceps].first = obj2.getInt(); - widths.exceps[widths.nExceps].last = obj3.getInt(); - widths.exceps[widths.nExceps].width = obj4.getNum() * 0.001; - ++widths.nExceps; - } else { - error(-1, "Bad widths array in Type 0 font"); - } - obj4.free(); - i += 3; - } else if (obj2.isInt() && obj3.isArray()) { - if (widths.nExceps + obj3.arrayGetLength() > excepsSize) { - excepsSize = (widths.nExceps + obj3.arrayGetLength() + 15) & ~15; - widths.exceps = (GfxFontCIDWidthExcep *) - greallocn(widths.exceps, - excepsSize, sizeof(GfxFontCIDWidthExcep)); - } - j = obj2.getInt(); - for (k = 0; k < obj3.arrayGetLength(); ++k) { - if (obj3.arrayGet(k, &obj4)->isNum()) { - widths.exceps[widths.nExceps].first = j; - widths.exceps[widths.nExceps].last = j; - widths.exceps[widths.nExceps].width = obj4.getNum() * 0.001; - ++j; - ++widths.nExceps; - } else { - error(-1, "Bad widths array in Type 0 font"); - } - obj4.free(); - } - i += 2; - } else { - error(-1, "Bad widths array in Type 0 font"); - ++i; - } - obj3.free(); - obj2.free(); - } - qsort(widths.exceps, widths.nExceps, sizeof(GfxFontCIDWidthExcep), - &cmpWidthExcep); - } - obj1.free(); - - // default metrics for vertical font - if (desFontDict->lookup("DW2", &obj1)->isArray() && - obj1.arrayGetLength() == 2) { - if (obj1.arrayGet(0, &obj2)->isNum()) { - widths.defVY = obj2.getNum() * 0.001; - } - obj2.free(); - if (obj1.arrayGet(1, &obj2)->isNum()) { - widths.defHeight = obj2.getNum() * 0.001; - } - obj2.free(); - } - obj1.free(); - - // char metric exceptions for vertical font - if (desFontDict->lookup("W2", &obj1)->isArray()) { - excepsSize = 0; - i = 0; - while (i + 1 < obj1.arrayGetLength()) { - obj1.arrayGet(i, &obj2); - obj1.arrayGet(i+ 1, &obj3); - if (obj2.isInt() && obj3.isInt() && i + 4 < obj1.arrayGetLength()) { - if (obj1.arrayGet(i + 2, &obj4)->isNum() && - obj1.arrayGet(i + 3, &obj5)->isNum() && - obj1.arrayGet(i + 4, &obj6)->isNum()) { - if (widths.nExcepsV == excepsSize) { - excepsSize += 16; - widths.excepsV = (GfxFontCIDWidthExcepV *) - greallocn(widths.excepsV, - excepsSize, sizeof(GfxFontCIDWidthExcepV)); - } - widths.excepsV[widths.nExcepsV].first = obj2.getInt(); - widths.excepsV[widths.nExcepsV].last = obj3.getInt(); - widths.excepsV[widths.nExcepsV].height = obj4.getNum() * 0.001; - widths.excepsV[widths.nExcepsV].vx = obj5.getNum() * 0.001; - widths.excepsV[widths.nExcepsV].vy = obj6.getNum() * 0.001; - ++widths.nExcepsV; - } else { - error(-1, "Bad widths (W2) array in Type 0 font"); - } - obj6.free(); - obj5.free(); - obj4.free(); - i += 5; - } else if (obj2.isInt() && obj3.isArray()) { - if (widths.nExcepsV + obj3.arrayGetLength() / 3 > excepsSize) { - excepsSize = - (widths.nExcepsV + obj3.arrayGetLength() / 3 + 15) & ~15; - widths.excepsV = (GfxFontCIDWidthExcepV *) - greallocn(widths.excepsV, - excepsSize, sizeof(GfxFontCIDWidthExcepV)); - } - j = obj2.getInt(); - for (k = 0; k < obj3.arrayGetLength(); k += 3) { - if (obj3.arrayGet(k, &obj4)->isNum() && - obj3.arrayGet(k+1, &obj5)->isNum() && - obj3.arrayGet(k+2, &obj6)->isNum()) { - widths.excepsV[widths.nExceps].first = j; - widths.excepsV[widths.nExceps].last = j; - widths.excepsV[widths.nExceps].height = obj4.getNum() * 0.001; - widths.excepsV[widths.nExceps].vx = obj5.getNum() * 0.001; - widths.excepsV[widths.nExceps].vy = obj6.getNum() * 0.001; - ++j; - ++widths.nExcepsV; - } else { - error(-1, "Bad widths (W2) array in Type 0 font"); - } - obj6.free(); - obj5.free(); - obj4.free(); - } - i += 2; - } else { - error(-1, "Bad widths (W2) array in Type 0 font"); - ++i; - } - obj3.free(); - obj2.free(); - } - qsort(widths.excepsV, widths.nExcepsV, sizeof(GfxFontCIDWidthExcepV), - &cmpWidthExcepV); - } - obj1.free(); - - desFontDictObj.free(); - ok = gTrue; - return; - - err4: - obj3.free(); - obj2.free(); - err3: - obj1.free(); - err2: - desFontDictObj.free(); - err1:; -} - -GfxCIDFont::~GfxCIDFont() { - if (cMap) { - cMap->decRefCnt(); - } - if (ctu) { - ctu->decRefCnt(); - } - gfree(widths.exceps); - gfree(widths.excepsV); - if (cidToGID) { - gfree(cidToGID); - } -} - -int GfxCIDFont::getNextChar(char *s, int len, CharCode *code, - Unicode *u, int uSize, int *uLen, - double *dx, double *dy, double *ox, double *oy) { - CID cid; - double w, h, vx, vy; - int n, a, b, m; - - if (!cMap) { - *code = 0; - *uLen = 0; - *dx = *dy = 0; - return 1; - } - - *code = (CharCode)(cid = cMap->getCID(s, len, &n)); - if (ctu) { - *uLen = ctu->mapToUnicode(cid, u, uSize); - } else { - *uLen = 0; - } - - // horizontal - if (cMap->getWMode() == 0) { - w = widths.defWidth; - h = vx = vy = 0; - if (widths.nExceps > 0 && cid >= widths.exceps[0].first) { - a = 0; - b = widths.nExceps; - // invariant: widths.exceps[a].first <= cid < widths.exceps[b].first - while (b - a > 1) { - m = (a + b) / 2; - if (widths.exceps[m].first <= cid) { - a = m; - } else { - b = m; - } - } - if (cid <= widths.exceps[a].last) { - w = widths.exceps[a].width; - } - } - - // vertical - } else { - w = 0; - h = widths.defHeight; - vx = widths.defWidth / 2; - vy = widths.defVY; - if (widths.nExcepsV > 0 && cid >= widths.excepsV[0].first) { - a = 0; - b = widths.nExcepsV; - // invariant: widths.excepsV[a].first <= cid < widths.excepsV[b].first - while (b - a > 1) { - m = (a + b) / 2; - if (widths.excepsV[m].last <= cid) { - a = m; - } else { - b = m; - } - } - if (cid <= widths.excepsV[a].last) { - h = widths.excepsV[a].height; - vx = widths.excepsV[a].vx; - vy = widths.excepsV[a].vy; - } - } - } - - *dx = w; - *dy = h; - *ox = vx; - *oy = vy; - - return n; -} - -int GfxCIDFont::getWMode() { - return cMap ? cMap->getWMode() : 0; -} - -CharCodeToUnicode *GfxCIDFont::getToUnicode() { - if (ctu) { - ctu->incRefCnt(); - } - return ctu; -} - -GString *GfxCIDFont::getCollection() { - return cMap ? cMap->getCollection() : (GString *)NULL; -} - -//------------------------------------------------------------------------ -// GfxFontDict -//------------------------------------------------------------------------ - -GfxFontDict::GfxFontDict(XRef *xref, Ref *fontDictRef, Dict *fontDict) { - int i; - Object obj1, obj2; - Ref r; - - numFonts = fontDict->getLength(); - fonts = (GfxFont **)gmallocn(numFonts, sizeof(GfxFont *)); - for (i = 0; i < numFonts; ++i) { - fontDict->getValNF(i, &obj1); - obj1.fetch(xref, &obj2); - if (obj2.isDict()) { - if (obj1.isRef()) { - r = obj1.getRef(); - } else { - // no indirect reference for this font, so invent a unique one - // (legal generation numbers are five digits, so any 6-digit - // number would be safe) - r.num = i; - if (fontDictRef) { - r.gen = 100000 + fontDictRef->num; - } else { - r.gen = 999999; - } - } - fonts[i] = GfxFont::makeFont(xref, fontDict->getKey(i), - r, obj2.getDict()); - if (fonts[i] && !fonts[i]->isOk()) { - delete fonts[i]; - fonts[i] = NULL; - } - } 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) { - if (fonts[i]) { - delete fonts[i]; - } - } - gfree(fonts); -} - -GfxFont *GfxFontDict::lookup(char *tag) { - int i; - - for (i = 0; i < numFonts; ++i) { - if (fonts[i] && fonts[i]->matches(tag)) { - return fonts[i]; - } - } - return NULL; -} diff --git a/pdftops/GfxFont.h b/pdftops/GfxFont.h deleted file mode 100644 index 6b051d490..000000000 --- a/pdftops/GfxFont.h +++ /dev/null @@ -1,315 +0,0 @@ -//======================================================================== -// -// GfxFont.h -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef GFXFONT_H -#define GFXFONT_H - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "gtypes.h" -#include "GString.h" -#include "Object.h" -#include "CharTypes.h" - -class Dict; -class CMap; -class CharCodeToUnicode; -class FoFiTrueType; -struct GfxFontCIDWidths; - -//------------------------------------------------------------------------ -// GfxFontType -//------------------------------------------------------------------------ - -enum GfxFontType { - //----- Gfx8BitFont - fontUnknownType, - fontType1, - fontType1C, - fontType3, - fontTrueType, - //----- GfxCIDFont - fontCIDType0, - fontCIDType0C, - fontCIDType2 -}; - -//------------------------------------------------------------------------ -// GfxFontCIDWidths -//------------------------------------------------------------------------ - -struct GfxFontCIDWidthExcep { - CID first; // this record applies to - CID last; // CIDs <first>..<last> - double width; // char width -}; - -struct GfxFontCIDWidthExcepV { - CID first; // this record applies to - CID last; // CIDs <first>..<last> - double height; // char height - double vx, vy; // origin position -}; - -struct GfxFontCIDWidths { - double defWidth; // default char width - double defHeight; // default char height - double defVY; // default origin position - GfxFontCIDWidthExcep *exceps; // exceptions - int nExceps; // number of valid entries in exceps - GfxFontCIDWidthExcepV * // exceptions for vertical font - excepsV; - int nExcepsV; // 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) - -class GfxFont { -public: - - // Build a GfxFont object. - static GfxFont *makeFont(XRef *xref, char *tagA, Ref idA, Dict *fontDict); - - GfxFont(char *tagA, Ref idA, GString *nameA); - - virtual ~GfxFont(); - - GBool isOk() { return ok; } - - // Get font tag. - GString *getTag() { return tag; } - - // Get font dictionary ID. - Ref *getID() { return &id; } - - // Does this font match the tag? - GBool matches(char *tagA) { return !tag->cmp(tagA); } - - // Get base font name. - GString *getName() { return name; } - - // Get the original font name (ignornig any munging that might have - // been done to map to a canonical Base-14 font name). - GString *getOrigName() { return origName; } - - // Get font type. - GfxFontType getType() { return type; } - virtual GBool isCIDFont() { return gFalse; } - - // 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. - GString *getEmbeddedFontName() { return embFontName; } - - // 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; } - - // Return the font matrix. - double *getFontMatrix() { return fontMat; } - - // Return the font bounding box. - double *getFontBBox() { return fontBBox; } - - // Return the ascent and descent values. - double getAscent() { return ascent; } - double getDescent() { return descent; } - - // Return the writing mode (0=horizontal, 1=vertical). - virtual int getWMode() { return 0; } - - // Read an external or embedded font file into a buffer. - char *readExtFontFile(int *len); - char *readEmbFontFile(XRef *xref, int *len); - - // Get the next char from a string <s> of <len> bytes, returning the - // char <code>, its Unicode mapping <u>, its displacement vector - // (<dx>, <dy>), and its origin offset vector (<ox>, <oy>). <uSize> - // is the number of entries available in <u>, and <uLen> is set to - // the number actually used. Returns the number of bytes used by - // the char code. - virtual int getNextChar(char *s, int len, CharCode *code, - Unicode *u, int uSize, int *uLen, - double *dx, double *dy, double *ox, double *oy) = 0; - -protected: - - void readFontDescriptor(XRef *xref, Dict *fontDict); - CharCodeToUnicode *readToUnicodeCMap(Dict *fontDict, int nBits, - CharCodeToUnicode *ctu); - void findExtFontFile(); - - GString *tag; // PDF font tag - Ref id; // reference (used as unique ID) - GString *name; // font name - GString *origName; // original font name - GfxFontType type; // type of font - int flags; // font descriptor flags - GString *embFontName; // name of embedded font - Ref embFontID; // ref to embedded font file stream - GString *extFontFile; // external font file name - double fontMat[6]; // font matrix (Type 3 only) - double fontBBox[4]; // font bounding box (Type 3 only) - double missingWidth; // "default" width - double ascent; // max height above baseline - double descent; // max depth below baseline - GBool ok; -}; - -//------------------------------------------------------------------------ -// Gfx8BitFont -//------------------------------------------------------------------------ - -class Gfx8BitFont: public GfxFont { -public: - - Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA, - GfxFontType typeA, Dict *fontDict); - - virtual ~Gfx8BitFont(); - - virtual int getNextChar(char *s, int len, CharCode *code, - Unicode *u, int uSize, int *uLen, - double *dx, double *dy, double *ox, double *oy); - - // Return the encoding. - char **getEncoding() { return enc; } - - // Return the Unicode map. - CharCodeToUnicode *getToUnicode(); - - // Return the character name associated with <code>. - char *getCharName(int code) { return enc[code]; } - - // Returns true if the PDF font specified an encoding. - GBool getHasEncoding() { return hasEncoding; } - - // Returns true if the PDF font specified MacRomanEncoding. - GBool getUsesMacRomanEnc() { return usesMacRomanEnc; } - - // Get width of a character. - double getWidth(Guchar c) { return widths[c]; } - - // Return a char code-to-GID mapping for the provided font file. - // (This is only useful for TrueType fonts.) - Gushort *getCodeToGIDMap(FoFiTrueType *ff); - - // Return the Type 3 CharProc dictionary, or NULL if none. - Dict *getCharProcs(); - - // Return the Type 3 CharProc for the character associated with <code>. - Object *getCharProc(int code, Object *proc); - - // Return the Type 3 Resources dictionary, or NULL if none. - Dict *getResources(); - -private: - - char *enc[256]; // char code --> char name - char encFree[256]; // boolean for each char name: if set, - // the string is malloc'ed - CharCodeToUnicode *ctu; // char code --> Unicode - GBool hasEncoding; - GBool usesMacRomanEnc; - double widths[256]; // character widths - Object charProcs; // Type 3 CharProcs dictionary - Object resources; // Type 3 Resources dictionary -}; - -//------------------------------------------------------------------------ -// GfxCIDFont -//------------------------------------------------------------------------ - -class GfxCIDFont: public GfxFont { -public: - - GfxCIDFont(XRef *xref, char *tagA, Ref idA, GString *nameA, - Dict *fontDict); - - virtual ~GfxCIDFont(); - - virtual GBool isCIDFont() { return gTrue; } - - virtual int getNextChar(char *s, int len, CharCode *code, - Unicode *u, int uSize, int *uLen, - double *dx, double *dy, double *ox, double *oy); - - // Return the writing mode (0=horizontal, 1=vertical). - virtual int getWMode(); - - // Return the Unicode map. - CharCodeToUnicode *getToUnicode(); - - // Get the collection name (<registry>-<ordering>). - GString *getCollection(); - - // Return the CID-to-GID mapping table. These should only be called - // if type is fontCIDType2. - Gushort *getCIDToGID() { return cidToGID; } - int getCIDToGIDLen() { return cidToGIDLen; } - -private: - - CMap *cMap; // char code --> CID - CharCodeToUnicode *ctu; // CID --> Unicode - GfxFontCIDWidths widths; // character widths - Gushort *cidToGID; // CID --> GID mapping (for embedded - // TrueType fonts) - int cidToGIDLen; -}; - -//------------------------------------------------------------------------ -// GfxFontDict -//------------------------------------------------------------------------ - -class GfxFontDict { -public: - - // Build the font dictionary, given the PDF font dictionary. - GfxFontDict(XRef *xref, Ref *fontDictRef, 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 deleted file mode 100644 index 7ab6b1265..000000000 --- a/pdftops/GfxState.cxx +++ /dev/null @@ -1,3946 +0,0 @@ -//======================================================================== -// -// GfxState.cc -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include <stddef.h> -#include <math.h> -#include <string.h> -#include "gmem.h" -#include "Error.h" -#include "Object.h" -#include "Array.h" -#include "Page.h" -#include "GfxState.h" - -//------------------------------------------------------------------------ - -static inline GfxColorComp clip01(GfxColorComp x) { - return (x < 0) ? 0 : (x > gfxColorComp1) ? gfxColorComp1 : x; -} - -static inline double clip01(double x) { - return (x < 0) ? 0 : (x > 1) ? 1 : x; -} - -//------------------------------------------------------------------------ - -static struct { - char *name; - GfxBlendMode mode; -} gfxBlendModeNames[] = { - { "Normal", gfxBlendNormal }, - { "Compatible", gfxBlendNormal }, - { "Multiply", gfxBlendMultiply }, - { "Screen", gfxBlendScreen }, - { "Overlay", gfxBlendOverlay }, - { "Darken", gfxBlendDarken }, - { "Lighten", gfxBlendLighten }, - { "ColorDodge", gfxBlendColorDodge }, - { "ColorBurn", gfxBlendColorBurn }, - { "HardLight", gfxBlendHardLight }, - { "SoftLight", gfxBlendSoftLight }, - { "Difference", gfxBlendDifference }, - { "Exclusion", gfxBlendExclusion }, - { "Hue", gfxBlendHue }, - { "Saturation", gfxBlendSaturation }, - { "Color", gfxBlendColor }, - { "Luminosity", gfxBlendLuminosity } -}; - -#define nGfxBlendModeNames \ - ((int)((sizeof(gfxBlendModeNames) / sizeof(char *)))) - -//------------------------------------------------------------------------ - -// NB: This must match the GfxColorSpaceMode enum defined in -// GfxState.h -static char *gfxColorSpaceModeNames[] = { - "DeviceGray", - "CalGray", - "DeviceRGB", - "CalRGB", - "DeviceCMYK", - "Lab", - "ICCBased", - "Indexed", - "Separation", - "DeviceN", - "Pattern" -}; - -#define nGfxColorSpaceModes ((sizeof(gfxColorSpaceModeNames) / sizeof(char *))) - -//------------------------------------------------------------------------ -// GfxColorSpace -//------------------------------------------------------------------------ - -GfxColorSpace::GfxColorSpace() { -} - -GfxColorSpace::~GfxColorSpace() { -} - -GfxColorSpace *GfxColorSpace::parse(Object *csObj) { - GfxColorSpace *cs; - Object obj1; - - cs = NULL; - if (csObj->isName()) { - if (csObj->isName("DeviceGray") || csObj->isName("G")) { - cs = new GfxDeviceGrayColorSpace(); - } else if (csObj->isName("DeviceRGB") || csObj->isName("RGB")) { - cs = new GfxDeviceRGBColorSpace(); - } else if (csObj->isName("DeviceCMYK") || csObj->isName("CMYK")) { - cs = new GfxDeviceCMYKColorSpace(); - } else if (csObj->isName("Pattern")) { - cs = new GfxPatternColorSpace(NULL); - } else { - error(-1, "Bad color space '%s'", csObj->getName()); - } - } else if (csObj->isArray()) { - csObj->arrayGet(0, &obj1); - if (obj1.isName("DeviceGray") || obj1.isName("G")) { - cs = new GfxDeviceGrayColorSpace(); - } else if (obj1.isName("DeviceRGB") || obj1.isName("RGB")) { - cs = new GfxDeviceRGBColorSpace(); - } else if (obj1.isName("DeviceCMYK") || obj1.isName("CMYK")) { - cs = new GfxDeviceCMYKColorSpace(); - } else if (obj1.isName("CalGray")) { - cs = GfxCalGrayColorSpace::parse(csObj->getArray()); - } else if (obj1.isName("CalRGB")) { - cs = GfxCalRGBColorSpace::parse(csObj->getArray()); - } else if (obj1.isName("Lab")) { - cs = GfxLabColorSpace::parse(csObj->getArray()); - } else if (obj1.isName("ICCBased")) { - cs = GfxICCBasedColorSpace::parse(csObj->getArray()); - } else if (obj1.isName("Indexed") || obj1.isName("I")) { - cs = GfxIndexedColorSpace::parse(csObj->getArray()); - } else if (obj1.isName("Separation")) { - cs = GfxSeparationColorSpace::parse(csObj->getArray()); - } else if (obj1.isName("DeviceN")) { - cs = GfxDeviceNColorSpace::parse(csObj->getArray()); - } else if (obj1.isName("Pattern")) { - cs = GfxPatternColorSpace::parse(csObj->getArray()); - } else { - error(-1, "Bad color space"); - } - obj1.free(); - } else { - error(-1, "Bad color space - expected name or array"); - } - return cs; -} - -void GfxColorSpace::getDefaultRanges(double *decodeLow, double *decodeRange, - int maxImgPixel) { - int i; - - for (i = 0; i < getNComps(); ++i) { - decodeLow[i] = 0; - decodeRange[i] = 1; - } -} - -int GfxColorSpace::getNumColorSpaceModes() { - return nGfxColorSpaceModes; -} - -char *GfxColorSpace::getColorSpaceModeName(int idx) { - return gfxColorSpaceModeNames[idx]; -} - -//------------------------------------------------------------------------ -// GfxDeviceGrayColorSpace -//------------------------------------------------------------------------ - -GfxDeviceGrayColorSpace::GfxDeviceGrayColorSpace() { -} - -GfxDeviceGrayColorSpace::~GfxDeviceGrayColorSpace() { -} - -GfxColorSpace *GfxDeviceGrayColorSpace::copy() { - return new GfxDeviceGrayColorSpace(); -} - -void GfxDeviceGrayColorSpace::getGray(GfxColor *color, GfxGray *gray) { - *gray = clip01(color->c[0]); -} - -void GfxDeviceGrayColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { - rgb->r = rgb->g = rgb->b = clip01(color->c[0]); -} - -void GfxDeviceGrayColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) { - cmyk->c = cmyk->m = cmyk->y = 0; - cmyk->k = clip01(gfxColorComp1 - color->c[0]); -} - -//------------------------------------------------------------------------ -// GfxCalGrayColorSpace -//------------------------------------------------------------------------ - -GfxCalGrayColorSpace::GfxCalGrayColorSpace() { - whiteX = whiteY = whiteZ = 1; - blackX = blackY = blackZ = 0; - gamma = 1; -} - -GfxCalGrayColorSpace::~GfxCalGrayColorSpace() { -} - -GfxColorSpace *GfxCalGrayColorSpace::copy() { - GfxCalGrayColorSpace *cs; - - cs = new GfxCalGrayColorSpace(); - cs->whiteX = whiteX; - cs->whiteY = whiteY; - cs->whiteZ = whiteZ; - cs->blackX = blackX; - cs->blackY = blackY; - cs->blackZ = blackZ; - cs->gamma = gamma; - return cs; -} - -GfxColorSpace *GfxCalGrayColorSpace::parse(Array *arr) { - GfxCalGrayColorSpace *cs; - Object obj1, obj2, obj3; - - arr->get(1, &obj1); - if (!obj1.isDict()) { - error(-1, "Bad CalGray color space"); - obj1.free(); - return NULL; - } - cs = new GfxCalGrayColorSpace(); - if (obj1.dictLookup("WhitePoint", &obj2)->isArray() && - obj2.arrayGetLength() == 3) { - obj2.arrayGet(0, &obj3); - cs->whiteX = obj3.getNum(); - obj3.free(); - obj2.arrayGet(1, &obj3); - cs->whiteY = obj3.getNum(); - obj3.free(); - obj2.arrayGet(2, &obj3); - cs->whiteZ = obj3.getNum(); - obj3.free(); - } - obj2.free(); - if (obj1.dictLookup("BlackPoint", &obj2)->isArray() && - obj2.arrayGetLength() == 3) { - obj2.arrayGet(0, &obj3); - cs->blackX = obj3.getNum(); - obj3.free(); - obj2.arrayGet(1, &obj3); - cs->blackY = obj3.getNum(); - obj3.free(); - obj2.arrayGet(2, &obj3); - cs->blackZ = obj3.getNum(); - obj3.free(); - } - obj2.free(); - if (obj1.dictLookup("Gamma", &obj2)->isNum()) { - cs->gamma = obj2.getNum(); - } - obj2.free(); - obj1.free(); - return cs; -} - -void GfxCalGrayColorSpace::getGray(GfxColor *color, GfxGray *gray) { - *gray = clip01(color->c[0]); -} - -void GfxCalGrayColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { - rgb->r = rgb->g = rgb->b = clip01(color->c[0]); -} - -void GfxCalGrayColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) { - cmyk->c = cmyk->m = cmyk->y = 0; - cmyk->k = clip01(gfxColorComp1 - color->c[0]); -} - -//------------------------------------------------------------------------ -// GfxDeviceRGBColorSpace -//------------------------------------------------------------------------ - -GfxDeviceRGBColorSpace::GfxDeviceRGBColorSpace() { -} - -GfxDeviceRGBColorSpace::~GfxDeviceRGBColorSpace() { -} - -GfxColorSpace *GfxDeviceRGBColorSpace::copy() { - return new GfxDeviceRGBColorSpace(); -} - -void GfxDeviceRGBColorSpace::getGray(GfxColor *color, GfxGray *gray) { - *gray = clip01((GfxColorComp)(0.3 * color->c[0] + - 0.59 * color->c[1] + - 0.11 * color->c[2] + 0.5)); -} - -void GfxDeviceRGBColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { - rgb->r = clip01(color->c[0]); - rgb->g = clip01(color->c[1]); - rgb->b = clip01(color->c[2]); -} - -void GfxDeviceRGBColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) { - GfxColorComp c, m, y, k; - - c = clip01(gfxColorComp1 - color->c[0]); - m = clip01(gfxColorComp1 - color->c[1]); - y = clip01(gfxColorComp1 - color->c[2]); - k = c; - if (m < k) { - k = m; - } - if (y < k) { - k = y; - } - cmyk->c = c - k; - cmyk->m = m - k; - cmyk->y = y - k; - cmyk->k = k; -} - -//------------------------------------------------------------------------ -// GfxCalRGBColorSpace -//------------------------------------------------------------------------ - -GfxCalRGBColorSpace::GfxCalRGBColorSpace() { - whiteX = whiteY = whiteZ = 1; - blackX = blackY = blackZ = 0; - gammaR = gammaG = gammaB = 1; - mat[0] = 1; mat[1] = 0; mat[2] = 0; - mat[3] = 0; mat[4] = 1; mat[5] = 0; - mat[6] = 0; mat[7] = 0; mat[8] = 1; -} - -GfxCalRGBColorSpace::~GfxCalRGBColorSpace() { -} - -GfxColorSpace *GfxCalRGBColorSpace::copy() { - GfxCalRGBColorSpace *cs; - int i; - - cs = new GfxCalRGBColorSpace(); - cs->whiteX = whiteX; - cs->whiteY = whiteY; - cs->whiteZ = whiteZ; - cs->blackX = blackX; - cs->blackY = blackY; - cs->blackZ = blackZ; - cs->gammaR = gammaR; - cs->gammaG = gammaG; - cs->gammaB = gammaB; - for (i = 0; i < 9; ++i) { - cs->mat[i] = mat[i]; - } - return cs; -} - -GfxColorSpace *GfxCalRGBColorSpace::parse(Array *arr) { - GfxCalRGBColorSpace *cs; - Object obj1, obj2, obj3; - int i; - - arr->get(1, &obj1); - if (!obj1.isDict()) { - error(-1, "Bad CalRGB color space"); - obj1.free(); - return NULL; - } - cs = new GfxCalRGBColorSpace(); - if (obj1.dictLookup("WhitePoint", &obj2)->isArray() && - obj2.arrayGetLength() == 3) { - obj2.arrayGet(0, &obj3); - cs->whiteX = obj3.getNum(); - obj3.free(); - obj2.arrayGet(1, &obj3); - cs->whiteY = obj3.getNum(); - obj3.free(); - obj2.arrayGet(2, &obj3); - cs->whiteZ = obj3.getNum(); - obj3.free(); - } - obj2.free(); - if (obj1.dictLookup("BlackPoint", &obj2)->isArray() && - obj2.arrayGetLength() == 3) { - obj2.arrayGet(0, &obj3); - cs->blackX = obj3.getNum(); - obj3.free(); - obj2.arrayGet(1, &obj3); - cs->blackY = obj3.getNum(); - obj3.free(); - obj2.arrayGet(2, &obj3); - cs->blackZ = obj3.getNum(); - obj3.free(); - } - obj2.free(); - if (obj1.dictLookup("Gamma", &obj2)->isArray() && - obj2.arrayGetLength() == 3) { - obj2.arrayGet(0, &obj3); - cs->gammaR = obj3.getNum(); - obj3.free(); - obj2.arrayGet(1, &obj3); - cs->gammaG = obj3.getNum(); - obj3.free(); - obj2.arrayGet(2, &obj3); - cs->gammaB = obj3.getNum(); - obj3.free(); - } - obj2.free(); - if (obj1.dictLookup("Matrix", &obj2)->isArray() && - obj2.arrayGetLength() == 9) { - for (i = 0; i < 9; ++i) { - obj2.arrayGet(i, &obj3); - cs->mat[i] = obj3.getNum(); - obj3.free(); - } - } - obj2.free(); - obj1.free(); - return cs; -} - -void GfxCalRGBColorSpace::getGray(GfxColor *color, GfxGray *gray) { - *gray = clip01((GfxColorComp)(0.299 * color->c[0] + - 0.587 * color->c[1] + - 0.114 * color->c[2] + 0.5)); -} - -void GfxCalRGBColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { - rgb->r = clip01(color->c[0]); - rgb->g = clip01(color->c[1]); - rgb->b = clip01(color->c[2]); -} - -void GfxCalRGBColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) { - GfxColorComp c, m, y, k; - - c = clip01(gfxColorComp1 - color->c[0]); - m = clip01(gfxColorComp1 - color->c[1]); - y = clip01(gfxColorComp1 - color->c[2]); - k = c; - if (m < k) { - k = m; - } - if (y < k) { - k = y; - } - cmyk->c = c - k; - cmyk->m = m - k; - cmyk->y = y - k; - cmyk->k = k; -} - -//------------------------------------------------------------------------ -// GfxDeviceCMYKColorSpace -//------------------------------------------------------------------------ - -GfxDeviceCMYKColorSpace::GfxDeviceCMYKColorSpace() { -} - -GfxDeviceCMYKColorSpace::~GfxDeviceCMYKColorSpace() { -} - -GfxColorSpace *GfxDeviceCMYKColorSpace::copy() { - return new GfxDeviceCMYKColorSpace(); -} - -void GfxDeviceCMYKColorSpace::getGray(GfxColor *color, GfxGray *gray) { - *gray = clip01((GfxColorComp)(gfxColorComp1 - color->c[3] - - 0.3 * color->c[0] - - 0.59 * color->c[1] - - 0.11 * color->c[2] + 0.5)); -} - -void GfxDeviceCMYKColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { - double c, m, y, k, c1, m1, y1, k1, r, g, b, x; - - c = colToDbl(color->c[0]); - m = colToDbl(color->c[1]); - y = colToDbl(color->c[2]); - k = colToDbl(color->c[3]); - c1 = 1 - c; - m1 = 1 - m; - y1 = 1 - y; - k1 = 1 - k; - // this is a matrix multiplication, unrolled for performance - // C M Y K - x = c1 * m1 * y1 * k1; // 0 0 0 0 - r = g = b = x; - x = c1 * m1 * y1 * k; // 0 0 0 1 - r += 0.1373 * x; - g += 0.1216 * x; - b += 0.1255 * x; - x = c1 * m1 * y * k1; // 0 0 1 0 - r += x; - g += 0.9490 * x; - x = c1 * m1 * y * k; // 0 0 1 1 - r += 0.1098 * x; - g += 0.1020 * x; - x = c1 * m * y1 * k1; // 0 1 0 0 - r += 0.9255 * x; - b += 0.5490 * x; - x = c1 * m * y1 * k; // 0 1 0 1 - r += 0.1412 * x; - x = c1 * m * y * k1; // 0 1 1 0 - r += 0.9294 * x; - g += 0.1098 * x; - b += 0.1412 * x; - x = c1 * m * y * k; // 0 1 1 1 - r += 0.1333 * x; - x = c * m1 * y1 * k1; // 1 0 0 0 - g += 0.6784 * x; - b += 0.9373 * x; - x = c * m1 * y1 * k; // 1 0 0 1 - g += 0.0588 * x; - b += 0.1412 * x; - x = c * m1 * y * k1; // 1 0 1 0 - g += 0.6510 * x; - b += 0.3137 * x; - x = c * m1 * y * k; // 1 0 1 1 - g += 0.0745 * x; - x = c * m * y1 * k1; // 1 1 0 0 - r += 0.1804 * x; - g += 0.1922 * x; - b += 0.5725 * x; - x = c * m * y1 * k; // 1 1 0 1 - b += 0.0078 * x; - x = c * m * y * k1; // 1 1 1 0 - r += 0.2118 * x; - g += 0.2119 * x; - b += 0.2235 * x; - rgb->r = clip01(dblToCol(r)); - rgb->g = clip01(dblToCol(g)); - rgb->b = clip01(dblToCol(b)); -} - -void GfxDeviceCMYKColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) { - cmyk->c = clip01(color->c[0]); - cmyk->m = clip01(color->c[1]); - cmyk->y = clip01(color->c[2]); - cmyk->k = clip01(color->c[3]); -} - -//------------------------------------------------------------------------ -// GfxLabColorSpace -//------------------------------------------------------------------------ - -// This is the inverse of MatrixLMN in Example 4.10 from the PostScript -// Language Reference, Third Edition. -static double xyzrgb[3][3] = { - { 3.240449, -1.537136, -0.498531 }, - { -0.969265, 1.876011, 0.041556 }, - { 0.055643, -0.204026, 1.057229 } -}; - -GfxLabColorSpace::GfxLabColorSpace() { - whiteX = whiteY = whiteZ = 1; - blackX = blackY = blackZ = 0; - aMin = bMin = -100; - aMax = bMax = 100; -} - -GfxLabColorSpace::~GfxLabColorSpace() { -} - -GfxColorSpace *GfxLabColorSpace::copy() { - GfxLabColorSpace *cs; - - cs = new GfxLabColorSpace(); - cs->whiteX = whiteX; - cs->whiteY = whiteY; - cs->whiteZ = whiteZ; - cs->blackX = blackX; - cs->blackY = blackY; - cs->blackZ = blackZ; - cs->aMin = aMin; - cs->aMax = aMax; - cs->bMin = bMin; - cs->bMax = bMax; - cs->kr = kr; - cs->kg = kg; - cs->kb = kb; - return cs; -} - -GfxColorSpace *GfxLabColorSpace::parse(Array *arr) { - GfxLabColorSpace *cs; - Object obj1, obj2, obj3; - - arr->get(1, &obj1); - if (!obj1.isDict()) { - error(-1, "Bad Lab color space"); - obj1.free(); - return NULL; - } - cs = new GfxLabColorSpace(); - if (obj1.dictLookup("WhitePoint", &obj2)->isArray() && - obj2.arrayGetLength() == 3) { - obj2.arrayGet(0, &obj3); - cs->whiteX = obj3.getNum(); - obj3.free(); - obj2.arrayGet(1, &obj3); - cs->whiteY = obj3.getNum(); - obj3.free(); - obj2.arrayGet(2, &obj3); - cs->whiteZ = obj3.getNum(); - obj3.free(); - } - obj2.free(); - if (obj1.dictLookup("BlackPoint", &obj2)->isArray() && - obj2.arrayGetLength() == 3) { - obj2.arrayGet(0, &obj3); - cs->blackX = obj3.getNum(); - obj3.free(); - obj2.arrayGet(1, &obj3); - cs->blackY = obj3.getNum(); - obj3.free(); - obj2.arrayGet(2, &obj3); - cs->blackZ = obj3.getNum(); - obj3.free(); - } - obj2.free(); - if (obj1.dictLookup("Range", &obj2)->isArray() && - obj2.arrayGetLength() == 4) { - obj2.arrayGet(0, &obj3); - cs->aMin = obj3.getNum(); - obj3.free(); - obj2.arrayGet(1, &obj3); - cs->aMax = obj3.getNum(); - obj3.free(); - obj2.arrayGet(2, &obj3); - cs->bMin = obj3.getNum(); - obj3.free(); - obj2.arrayGet(3, &obj3); - cs->bMax = obj3.getNum(); - obj3.free(); - } - obj2.free(); - obj1.free(); - - cs->kr = 1 / (xyzrgb[0][0] * cs->whiteX + - xyzrgb[0][1] * cs->whiteY + - xyzrgb[0][2] * cs->whiteZ); - cs->kg = 1 / (xyzrgb[1][0] * cs->whiteX + - xyzrgb[1][1] * cs->whiteY + - xyzrgb[1][2] * cs->whiteZ); - cs->kb = 1 / (xyzrgb[2][0] * cs->whiteX + - xyzrgb[2][1] * cs->whiteY + - xyzrgb[2][2] * cs->whiteZ); - - return cs; -} - -void GfxLabColorSpace::getGray(GfxColor *color, GfxGray *gray) { - GfxRGB rgb; - - getRGB(color, &rgb); - *gray = clip01((GfxColorComp)(0.299 * rgb.r + - 0.587 * rgb.g + - 0.114 * rgb.b + 0.5)); -} - -void GfxLabColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { - double X, Y, Z; - double t1, t2; - double r, g, b; - - // convert L*a*b* to CIE 1931 XYZ color space - t1 = (colToDbl(color->c[0]) + 16) / 116; - t2 = t1 + colToDbl(color->c[1]) / 500; - if (t2 >= (6.0 / 29.0)) { - X = t2 * t2 * t2; - } else { - X = (108.0 / 841.0) * (t2 - (4.0 / 29.0)); - } - X *= whiteX; - if (t1 >= (6.0 / 29.0)) { - Y = t1 * t1 * t1; - } else { - Y = (108.0 / 841.0) * (t1 - (4.0 / 29.0)); - } - Y *= whiteY; - t2 = t1 - colToDbl(color->c[2]) / 200; - if (t2 >= (6.0 / 29.0)) { - Z = t2 * t2 * t2; - } else { - Z = (108.0 / 841.0) * (t2 - (4.0 / 29.0)); - } - Z *= whiteZ; - - // convert XYZ to RGB, including gamut mapping and gamma correction - r = xyzrgb[0][0] * X + xyzrgb[0][1] * Y + xyzrgb[0][2] * Z; - g = xyzrgb[1][0] * X + xyzrgb[1][1] * Y + xyzrgb[1][2] * Z; - b = xyzrgb[2][0] * X + xyzrgb[2][1] * Y + xyzrgb[2][2] * Z; - rgb->r = dblToCol(pow(clip01(r * kr), 0.5)); - rgb->g = dblToCol(pow(clip01(g * kg), 0.5)); - rgb->b = dblToCol(pow(clip01(b * kb), 0.5)); -} - -void GfxLabColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) { - GfxRGB rgb; - GfxColorComp c, m, y, k; - - getRGB(color, &rgb); - c = clip01(gfxColorComp1 - rgb.r); - m = clip01(gfxColorComp1 - rgb.g); - y = clip01(gfxColorComp1 - rgb.b); - k = c; - if (m < k) { - k = m; - } - if (y < k) { - k = y; - } - cmyk->c = c - k; - cmyk->m = m - k; - cmyk->y = y - k; - cmyk->k = k; -} - -void GfxLabColorSpace::getDefaultRanges(double *decodeLow, double *decodeRange, - int maxImgPixel) { - decodeLow[0] = 0; - decodeRange[0] = 100; - decodeLow[1] = aMin; - decodeRange[1] = aMax - aMin; - decodeLow[2] = bMin; - decodeRange[2] = bMax - bMin; -} - -//------------------------------------------------------------------------ -// GfxICCBasedColorSpace -//------------------------------------------------------------------------ - -GfxICCBasedColorSpace::GfxICCBasedColorSpace(int nCompsA, GfxColorSpace *altA, - Ref *iccProfileStreamA) { - nComps = nCompsA; - alt = altA; - iccProfileStream = *iccProfileStreamA; - rangeMin[0] = rangeMin[1] = rangeMin[2] = rangeMin[3] = 0; - rangeMax[0] = rangeMax[1] = rangeMax[2] = rangeMax[3] = 1; -} - -GfxICCBasedColorSpace::~GfxICCBasedColorSpace() { - delete alt; -} - -GfxColorSpace *GfxICCBasedColorSpace::copy() { - GfxICCBasedColorSpace *cs; - int i; - - cs = new GfxICCBasedColorSpace(nComps, alt->copy(), &iccProfileStream); - for (i = 0; i < 4; ++i) { - cs->rangeMin[i] = rangeMin[i]; - cs->rangeMax[i] = rangeMax[i]; - } - return cs; -} - -GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr) { - GfxICCBasedColorSpace *cs; - Ref iccProfileStreamA; - int nCompsA; - GfxColorSpace *altA; - Dict *dict; - Object obj1, obj2, obj3; - int i; - - arr->getNF(1, &obj1); - if (obj1.isRef()) { - iccProfileStreamA = obj1.getRef(); - } else { - iccProfileStreamA.num = 0; - iccProfileStreamA.gen = 0; - } - obj1.free(); - arr->get(1, &obj1); - if (!obj1.isStream()) { - error(-1, "Bad ICCBased color space (stream)"); - obj1.free(); - return NULL; - } - dict = obj1.streamGetDict(); - if (!dict->lookup("N", &obj2)->isInt()) { - error(-1, "Bad ICCBased color space (N)"); - obj2.free(); - obj1.free(); - return NULL; - } - nCompsA = obj2.getInt(); - obj2.free(); - if (nCompsA > gfxColorMaxComps) { - error(-1, "ICCBased color space with too many (%d > %d) components", - nCompsA, gfxColorMaxComps); - nCompsA = gfxColorMaxComps; - } - if (dict->lookup("Alternate", &obj2)->isNull() || - !(altA = GfxColorSpace::parse(&obj2))) { - switch (nCompsA) { - case 1: - altA = new GfxDeviceGrayColorSpace(); - break; - case 3: - altA = new GfxDeviceRGBColorSpace(); - break; - case 4: - altA = new GfxDeviceCMYKColorSpace(); - break; - default: - error(-1, "Bad ICCBased color space - invalid N"); - obj2.free(); - obj1.free(); - return NULL; - } - } - obj2.free(); - cs = new GfxICCBasedColorSpace(nCompsA, altA, &iccProfileStreamA); - if (dict->lookup("Range", &obj2)->isArray() && - obj2.arrayGetLength() == 2 * nCompsA) { - for (i = 0; i < nCompsA; ++i) { - obj2.arrayGet(2*i, &obj3); - cs->rangeMin[i] = obj3.getNum(); - obj3.free(); - obj2.arrayGet(2*i+1, &obj3); - cs->rangeMax[i] = obj3.getNum(); - obj3.free(); - } - } - obj2.free(); - obj1.free(); - return cs; -} - -void GfxICCBasedColorSpace::getGray(GfxColor *color, GfxGray *gray) { - alt->getGray(color, gray); -} - -void GfxICCBasedColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { - alt->getRGB(color, rgb); -} - -void GfxICCBasedColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) { - alt->getCMYK(color, cmyk); -} - -void GfxICCBasedColorSpace::getDefaultRanges(double *decodeLow, - double *decodeRange, - int maxImgPixel) { - alt->getDefaultRanges(decodeLow, decodeRange, maxImgPixel); - -#if 0 - // this is nominally correct, but some PDF files don't set the - // correct ranges in the ICCBased dict - int i; - - for (i = 0; i < nComps; ++i) { - decodeLow[i] = rangeMin[i]; - decodeRange[i] = rangeMax[i] - rangeMin[i]; - } -#endif -} - -//------------------------------------------------------------------------ -// GfxIndexedColorSpace -//------------------------------------------------------------------------ - -GfxIndexedColorSpace::GfxIndexedColorSpace(GfxColorSpace *baseA, - int indexHighA) { - base = baseA; - indexHigh = indexHighA; - lookup = (Guchar *)gmallocn((indexHigh + 1) * base->getNComps(), - sizeof(Guchar)); -} - -GfxIndexedColorSpace::~GfxIndexedColorSpace() { - delete base; - gfree(lookup); -} - -GfxColorSpace *GfxIndexedColorSpace::copy() { - GfxIndexedColorSpace *cs; - - cs = new GfxIndexedColorSpace(base->copy(), indexHigh); - memcpy(cs->lookup, lookup, - (indexHigh + 1) * base->getNComps() * sizeof(Guchar)); - return cs; -} - -GfxColorSpace *GfxIndexedColorSpace::parse(Array *arr) { - GfxIndexedColorSpace *cs; - GfxColorSpace *baseA; - int indexHighA; - Object obj1; - int x; - char *s; - int n, i, j; - - if (arr->getLength() != 4) { - error(-1, "Bad Indexed color space"); - goto err1; - } - arr->get(1, &obj1); - if (!(baseA = GfxColorSpace::parse(&obj1))) { - error(-1, "Bad Indexed color space (base color space)"); - goto err2; - } - obj1.free(); - if (!arr->get(2, &obj1)->isInt()) { - error(-1, "Bad Indexed color space (hival)"); - delete baseA; - goto err2; - } - indexHighA = obj1.getInt(); - if (indexHighA < 0 || indexHighA > 255) { - // the PDF spec requires indexHigh to be in [0,255] -- allowing - // values larger than 255 creates a security hole: if nComps * - // indexHigh is greater than 2^31, the loop below may overwrite - // past the end of the array - error(-1, "Bad Indexed color space (invalid indexHigh value)"); - delete baseA; - goto err2; - } - obj1.free(); - cs = new GfxIndexedColorSpace(baseA, indexHighA); - arr->get(3, &obj1); - n = baseA->getNComps(); - if (obj1.isStream()) { - obj1.streamReset(); - for (i = 0; i <= indexHighA; ++i) { - for (j = 0; j < n; ++j) { - if ((x = obj1.streamGetChar()) == EOF) { - error(-1, "Bad Indexed color space (lookup table stream too short)"); - goto err3; - } - cs->lookup[i*n + j] = (Guchar)x; - } - } - obj1.streamClose(); - } else if (obj1.isString()) { - if (obj1.getString()->getLength() < (indexHighA + 1) * n) { - error(-1, "Bad Indexed color space (lookup table string too short)"); - goto err3; - } - s = obj1.getString()->getCString(); - for (i = 0; i <= indexHighA; ++i) { - for (j = 0; j < n; ++j) { - cs->lookup[i*n + j] = (Guchar)*s++; - } - } - } else { - error(-1, "Bad Indexed color space (lookup table)"); - goto err3; - } - obj1.free(); - return cs; - - err3: - delete cs; - err2: - obj1.free(); - err1: - return NULL; -} - -GfxColor *GfxIndexedColorSpace::mapColorToBase(GfxColor *color, - GfxColor *baseColor) { - Guchar *p; - double low[gfxColorMaxComps], range[gfxColorMaxComps]; - int n, i; - - n = base->getNComps(); - base->getDefaultRanges(low, range, indexHigh); - p = &lookup[(int)(colToDbl(color->c[0]) + 0.5) * n]; - for (i = 0; i < n; ++i) { - baseColor->c[i] = dblToCol(low[i] + (p[i] / 255.0) * range[i]); - } - return baseColor; -} - -void GfxIndexedColorSpace::getGray(GfxColor *color, GfxGray *gray) { - GfxColor color2; - - base->getGray(mapColorToBase(color, &color2), gray); -} - -void GfxIndexedColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { - GfxColor color2; - - base->getRGB(mapColorToBase(color, &color2), rgb); -} - -void GfxIndexedColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) { - GfxColor color2; - - base->getCMYK(mapColorToBase(color, &color2), cmyk); -} - -void GfxIndexedColorSpace::getDefaultRanges(double *decodeLow, - double *decodeRange, - int maxImgPixel) { - decodeLow[0] = 0; - decodeRange[0] = maxImgPixel; -} - -//------------------------------------------------------------------------ -// GfxSeparationColorSpace -//------------------------------------------------------------------------ - -GfxSeparationColorSpace::GfxSeparationColorSpace(GString *nameA, - GfxColorSpace *altA, - Function *funcA) { - name = nameA; - alt = altA; - func = funcA; -} - -GfxSeparationColorSpace::~GfxSeparationColorSpace() { - delete name; - delete alt; - delete func; -} - -GfxColorSpace *GfxSeparationColorSpace::copy() { - return new GfxSeparationColorSpace(name->copy(), alt->copy(), func->copy()); -} - -//~ handle the 'All' and 'None' colorants -GfxColorSpace *GfxSeparationColorSpace::parse(Array *arr) { - GfxSeparationColorSpace *cs; - GString *nameA; - GfxColorSpace *altA; - Function *funcA; - Object obj1; - - if (arr->getLength() != 4) { - error(-1, "Bad Separation color space"); - goto err1; - } - if (!arr->get(1, &obj1)->isName()) { - error(-1, "Bad Separation color space (name)"); - goto err2; - } - nameA = new GString(obj1.getName()); - obj1.free(); - arr->get(2, &obj1); - if (!(altA = GfxColorSpace::parse(&obj1))) { - error(-1, "Bad Separation color space (alternate color space)"); - goto err3; - } - obj1.free(); - arr->get(3, &obj1); - if (!(funcA = Function::parse(&obj1))) { - goto err4; - } - obj1.free(); - cs = new GfxSeparationColorSpace(nameA, altA, funcA); - return cs; - - err4: - delete altA; - err3: - delete nameA; - err2: - obj1.free(); - err1: - return NULL; -} - -void GfxSeparationColorSpace::getGray(GfxColor *color, GfxGray *gray) { - double x; - double c[gfxColorMaxComps]; - GfxColor color2; - int i; - - x = colToDbl(color->c[0]); - func->transform(&x, c); - for (i = 0; i < alt->getNComps(); ++i) { - color2.c[i] = dblToCol(c[i]); - } - alt->getGray(&color2, gray); -} - -void GfxSeparationColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { - double x; - double c[gfxColorMaxComps]; - GfxColor color2; - int i; - - x = colToDbl(color->c[0]); - func->transform(&x, c); - for (i = 0; i < alt->getNComps(); ++i) { - color2.c[i] = dblToCol(c[i]); - } - alt->getRGB(&color2, rgb); -} - -void GfxSeparationColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) { - double x; - double c[gfxColorMaxComps]; - GfxColor color2; - int i; - - x = colToDbl(color->c[0]); - func->transform(&x, c); - for (i = 0; i < alt->getNComps(); ++i) { - color2.c[i] = dblToCol(c[i]); - } - alt->getCMYK(&color2, cmyk); -} - -//------------------------------------------------------------------------ -// GfxDeviceNColorSpace -//------------------------------------------------------------------------ - -GfxDeviceNColorSpace::GfxDeviceNColorSpace(int nCompsA, - GfxColorSpace *altA, - Function *funcA) { - nComps = nCompsA; - alt = altA; - func = funcA; -} - -GfxDeviceNColorSpace::~GfxDeviceNColorSpace() { - int i; - - for (i = 0; i < nComps; ++i) { - delete names[i]; - } - delete alt; - delete func; -} - -GfxColorSpace *GfxDeviceNColorSpace::copy() { - GfxDeviceNColorSpace *cs; - int i; - - cs = new GfxDeviceNColorSpace(nComps, alt->copy(), func->copy()); - for (i = 0; i < nComps; ++i) { - cs->names[i] = names[i]->copy(); - } - return cs; -} - -//~ handle the 'None' colorant -GfxColorSpace *GfxDeviceNColorSpace::parse(Array *arr) { - GfxDeviceNColorSpace *cs; - int nCompsA; - GString *namesA[gfxColorMaxComps]; - GfxColorSpace *altA; - Function *funcA; - Object obj1, obj2; - int i; - - if (arr->getLength() != 4 && arr->getLength() != 5) { - error(-1, "Bad DeviceN color space"); - goto err1; - } - if (!arr->get(1, &obj1)->isArray()) { - error(-1, "Bad DeviceN color space (names)"); - goto err2; - } - nCompsA = obj1.arrayGetLength(); - if (nCompsA > gfxColorMaxComps) { - error(-1, "DeviceN color space with too many (%d > %d) components", - nCompsA, gfxColorMaxComps); - nCompsA = gfxColorMaxComps; - } - for (i = 0; i < nCompsA; ++i) { - if (!obj1.arrayGet(i, &obj2)->isName()) { - error(-1, "Bad DeviceN color space (names)"); - obj2.free(); - goto err2; - } - namesA[i] = new GString(obj2.getName()); - obj2.free(); - } - obj1.free(); - arr->get(2, &obj1); - if (!(altA = GfxColorSpace::parse(&obj1))) { - error(-1, "Bad DeviceN color space (alternate color space)"); - goto err3; - } - obj1.free(); - arr->get(3, &obj1); - if (!(funcA = Function::parse(&obj1))) { - goto err4; - } - obj1.free(); - cs = new GfxDeviceNColorSpace(nCompsA, altA, funcA); - for (i = 0; i < nCompsA; ++i) { - cs->names[i] = namesA[i]; - } - return cs; - - err4: - delete altA; - err3: - for (i = 0; i < nCompsA; ++i) { - delete namesA[i]; - } - err2: - obj1.free(); - err1: - return NULL; -} - -void GfxDeviceNColorSpace::getGray(GfxColor *color, GfxGray *gray) { - double x[gfxColorMaxComps], c[gfxColorMaxComps]; - GfxColor color2; - int i; - - for (i = 0; i < nComps; ++i) { - x[i] = colToDbl(color->c[i]); - } - func->transform(x, c); - for (i = 0; i < alt->getNComps(); ++i) { - color2.c[i] = dblToCol(c[i]); - } - alt->getGray(&color2, gray); -} - -void GfxDeviceNColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { - double x[gfxColorMaxComps], c[gfxColorMaxComps]; - GfxColor color2; - int i; - - for (i = 0; i < nComps; ++i) { - x[i] = colToDbl(color->c[i]); - } - func->transform(x, c); - for (i = 0; i < alt->getNComps(); ++i) { - color2.c[i] = dblToCol(c[i]); - } - alt->getRGB(&color2, rgb); -} - -void GfxDeviceNColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) { - double x[gfxColorMaxComps], c[gfxColorMaxComps]; - GfxColor color2; - int i; - - for (i = 0; i < nComps; ++i) { - x[i] = colToDbl(color->c[i]); - } - func->transform(x, c); - for (i = 0; i < alt->getNComps(); ++i) { - color2.c[i] = dblToCol(c[i]); - } - alt->getCMYK(&color2, cmyk); -} - -//------------------------------------------------------------------------ -// GfxPatternColorSpace -//------------------------------------------------------------------------ - -GfxPatternColorSpace::GfxPatternColorSpace(GfxColorSpace *underA) { - under = underA; -} - -GfxPatternColorSpace::~GfxPatternColorSpace() { - if (under) { - delete under; - } -} - -GfxColorSpace *GfxPatternColorSpace::copy() { - return new GfxPatternColorSpace(under ? under->copy() : - (GfxColorSpace *)NULL); -} - -GfxColorSpace *GfxPatternColorSpace::parse(Array *arr) { - GfxPatternColorSpace *cs; - GfxColorSpace *underA; - Object obj1; - - if (arr->getLength() != 1 && arr->getLength() != 2) { - error(-1, "Bad Pattern color space"); - return NULL; - } - underA = NULL; - if (arr->getLength() == 2) { - arr->get(1, &obj1); - if (!(underA = GfxColorSpace::parse(&obj1))) { - error(-1, "Bad Pattern color space (underlying color space)"); - obj1.free(); - return NULL; - } - obj1.free(); - } - cs = new GfxPatternColorSpace(underA); - return cs; -} - -void GfxPatternColorSpace::getGray(GfxColor *color, GfxGray *gray) { - *gray = 0; -} - -void GfxPatternColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { - rgb->r = rgb->g = rgb->b = 0; -} - -void GfxPatternColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) { - cmyk->c = cmyk->m = cmyk->y = 0; - cmyk->k = 1; -} - -//------------------------------------------------------------------------ -// Pattern -//------------------------------------------------------------------------ - -GfxPattern::GfxPattern(int typeA) { - type = typeA; -} - -GfxPattern::~GfxPattern() { -} - -GfxPattern *GfxPattern::parse(Object *obj) { - GfxPattern *pattern; - Object obj1; - - if (obj->isDict()) { - obj->dictLookup("PatternType", &obj1); - } else if (obj->isStream()) { - obj->streamGetDict()->lookup("PatternType", &obj1); - } else { - return NULL; - } - pattern = NULL; - if (obj1.isInt() && obj1.getInt() == 1) { - pattern = GfxTilingPattern::parse(obj); - } else if (obj1.isInt() && obj1.getInt() == 2) { - pattern = GfxShadingPattern::parse(obj); - } - obj1.free(); - return pattern; -} - -//------------------------------------------------------------------------ -// GfxTilingPattern -//------------------------------------------------------------------------ - -GfxTilingPattern *GfxTilingPattern::parse(Object *patObj) { - GfxTilingPattern *pat; - Dict *dict; - int paintTypeA, tilingTypeA; - double bboxA[4], matrixA[6]; - double xStepA, yStepA; - Object resDictA; - Object obj1, obj2; - int i; - - if (!patObj->isStream()) { - return NULL; - } - dict = patObj->streamGetDict(); - - if (dict->lookup("PaintType", &obj1)->isInt()) { - paintTypeA = obj1.getInt(); - } else { - paintTypeA = 1; - error(-1, "Invalid or missing PaintType in pattern"); - } - obj1.free(); - if (dict->lookup("TilingType", &obj1)->isInt()) { - tilingTypeA = obj1.getInt(); - } else { - tilingTypeA = 1; - error(-1, "Invalid or missing TilingType in pattern"); - } - obj1.free(); - bboxA[0] = bboxA[1] = 0; - bboxA[2] = bboxA[3] = 1; - if (dict->lookup("BBox", &obj1)->isArray() && - obj1.arrayGetLength() == 4) { - for (i = 0; i < 4; ++i) { - if (obj1.arrayGet(i, &obj2)->isNum()) { - bboxA[i] = obj2.getNum(); - } - obj2.free(); - } - } else { - error(-1, "Invalid or missing BBox in pattern"); - } - obj1.free(); - if (dict->lookup("XStep", &obj1)->isNum()) { - xStepA = obj1.getNum(); - } else { - xStepA = 1; - error(-1, "Invalid or missing XStep in pattern"); - } - obj1.free(); - if (dict->lookup("YStep", &obj1)->isNum()) { - yStepA = obj1.getNum(); - } else { - yStepA = 1; - error(-1, "Invalid or missing YStep in pattern"); - } - obj1.free(); - if (!dict->lookup("Resources", &resDictA)->isDict()) { - resDictA.free(); - resDictA.initNull(); - error(-1, "Invalid or missing Resources in pattern"); - } - matrixA[0] = 1; matrixA[1] = 0; - matrixA[2] = 0; matrixA[3] = 1; - matrixA[4] = 0; matrixA[5] = 0; - if (dict->lookup("Matrix", &obj1)->isArray() && - obj1.arrayGetLength() == 6) { - for (i = 0; i < 6; ++i) { - if (obj1.arrayGet(i, &obj2)->isNum()) { - matrixA[i] = obj2.getNum(); - } - obj2.free(); - } - } - obj1.free(); - - pat = new GfxTilingPattern(paintTypeA, tilingTypeA, bboxA, xStepA, yStepA, - &resDictA, matrixA, patObj); - resDictA.free(); - return pat; -} - -GfxTilingPattern::GfxTilingPattern(int paintTypeA, int tilingTypeA, - double *bboxA, double xStepA, double yStepA, - Object *resDictA, double *matrixA, - Object *contentStreamA): - GfxPattern(1) -{ - int i; - - paintType = paintTypeA; - tilingType = tilingTypeA; - for (i = 0; i < 4; ++i) { - bbox[i] = bboxA[i]; - } - xStep = xStepA; - yStep = yStepA; - resDictA->copy(&resDict); - for (i = 0; i < 6; ++i) { - matrix[i] = matrixA[i]; - } - contentStreamA->copy(&contentStream); -} - -GfxTilingPattern::~GfxTilingPattern() { - resDict.free(); - contentStream.free(); -} - -GfxPattern *GfxTilingPattern::copy() { - return new GfxTilingPattern(paintType, tilingType, bbox, xStep, yStep, - &resDict, matrix, &contentStream); -} - -//------------------------------------------------------------------------ -// GfxShadingPattern -//------------------------------------------------------------------------ - -GfxShadingPattern *GfxShadingPattern::parse(Object *patObj) { - Dict *dict; - GfxShading *shadingA; - double matrixA[6]; - Object obj1, obj2; - int i; - - if (!patObj->isDict()) { - return NULL; - } - dict = patObj->getDict(); - - dict->lookup("Shading", &obj1); - shadingA = GfxShading::parse(&obj1); - obj1.free(); - if (!shadingA) { - return NULL; - } - - matrixA[0] = 1; matrixA[1] = 0; - matrixA[2] = 0; matrixA[3] = 1; - matrixA[4] = 0; matrixA[5] = 0; - if (dict->lookup("Matrix", &obj1)->isArray() && - obj1.arrayGetLength() == 6) { - for (i = 0; i < 6; ++i) { - if (obj1.arrayGet(i, &obj2)->isNum()) { - matrixA[i] = obj2.getNum(); - } - obj2.free(); - } - } - obj1.free(); - - return new GfxShadingPattern(shadingA, matrixA); -} - -GfxShadingPattern::GfxShadingPattern(GfxShading *shadingA, double *matrixA): - GfxPattern(2) -{ - int i; - - shading = shadingA; - for (i = 0; i < 6; ++i) { - matrix[i] = matrixA[i]; - } -} - -GfxShadingPattern::~GfxShadingPattern() { - delete shading; -} - -GfxPattern *GfxShadingPattern::copy() { - return new GfxShadingPattern(shading->copy(), matrix); -} - -//------------------------------------------------------------------------ -// GfxShading -//------------------------------------------------------------------------ - -GfxShading::GfxShading(int typeA) { - type = typeA; - colorSpace = NULL; -} - -GfxShading::GfxShading(GfxShading *shading) { - int i; - - type = shading->type; - colorSpace = shading->colorSpace->copy(); - for (i = 0; i < gfxColorMaxComps; ++i) { - background.c[i] = shading->background.c[i]; - } - hasBackground = shading->hasBackground; - xMin = shading->xMin; - yMin = shading->yMin; - xMax = shading->xMax; - yMax = shading->yMax; - hasBBox = shading->hasBBox; -} - -GfxShading::~GfxShading() { - if (colorSpace) { - delete colorSpace; - } -} - -GfxShading *GfxShading::parse(Object *obj) { - GfxShading *shading; - Dict *dict; - int typeA; - Object obj1; - - if (obj->isDict()) { - dict = obj->getDict(); - } else if (obj->isStream()) { - dict = obj->streamGetDict(); - } else { - return NULL; - } - - if (!dict->lookup("ShadingType", &obj1)->isInt()) { - error(-1, "Invalid ShadingType in shading dictionary"); - obj1.free(); - return NULL; - } - typeA = obj1.getInt(); - obj1.free(); - - switch (typeA) { - case 1: - shading = GfxFunctionShading::parse(dict); - break; - case 2: - shading = GfxAxialShading::parse(dict); - break; - case 3: - shading = GfxRadialShading::parse(dict); - break; - case 4: - if (obj->isStream()) { - shading = GfxGouraudTriangleShading::parse(4, dict, obj->getStream()); - } else { - error(-1, "Invalid Type 4 shading object"); - goto err1; - } - break; - case 5: - if (obj->isStream()) { - shading = GfxGouraudTriangleShading::parse(5, dict, obj->getStream()); - } else { - error(-1, "Invalid Type 5 shading object"); - goto err1; - } - break; - case 6: - if (obj->isStream()) { - shading = GfxPatchMeshShading::parse(6, dict, obj->getStream()); - } else { - error(-1, "Invalid Type 6 shading object"); - goto err1; - } - break; - case 7: - if (obj->isStream()) { - shading = GfxPatchMeshShading::parse(7, dict, obj->getStream()); - } else { - error(-1, "Invalid Type 7 shading object"); - goto err1; - } - break; - default: - error(-1, "Unimplemented shading type %d", typeA); - goto err1; - } - - return shading; - - err1: - return NULL; -} - -GBool GfxShading::init(Dict *dict) { - Object obj1, obj2; - int i; - - dict->lookup("ColorSpace", &obj1); - if (!(colorSpace = GfxColorSpace::parse(&obj1))) { - error(-1, "Bad color space in shading dictionary"); - obj1.free(); - return gFalse; - } - obj1.free(); - - for (i = 0; i < gfxColorMaxComps; ++i) { - background.c[i] = 0; - } - hasBackground = gFalse; - if (dict->lookup("Background", &obj1)->isArray()) { - if (obj1.arrayGetLength() == colorSpace->getNComps()) { - hasBackground = gTrue; - for (i = 0; i < colorSpace->getNComps(); ++i) { - background.c[i] = dblToCol(obj1.arrayGet(i, &obj2)->getNum()); - obj2.free(); - } - } else { - error(-1, "Bad Background in shading dictionary"); - } - } - obj1.free(); - - xMin = yMin = xMax = yMax = 0; - hasBBox = gFalse; - if (dict->lookup("BBox", &obj1)->isArray()) { - if (obj1.arrayGetLength() == 4) { - hasBBox = gTrue; - xMin = obj1.arrayGet(0, &obj2)->getNum(); - obj2.free(); - yMin = obj1.arrayGet(1, &obj2)->getNum(); - obj2.free(); - xMax = obj1.arrayGet(2, &obj2)->getNum(); - obj2.free(); - yMax = obj1.arrayGet(3, &obj2)->getNum(); - obj2.free(); - } else { - error(-1, "Bad BBox in shading dictionary"); - } - } - obj1.free(); - - return gTrue; -} - -//------------------------------------------------------------------------ -// GfxFunctionShading -//------------------------------------------------------------------------ - -GfxFunctionShading::GfxFunctionShading(double x0A, double y0A, - double x1A, double y1A, - double *matrixA, - Function **funcsA, int nFuncsA): - GfxShading(1) -{ - int i; - - x0 = x0A; - y0 = y0A; - x1 = x1A; - y1 = y1A; - for (i = 0; i < 6; ++i) { - matrix[i] = matrixA[i]; - } - nFuncs = nFuncsA; - for (i = 0; i < nFuncs; ++i) { - funcs[i] = funcsA[i]; - } -} - -GfxFunctionShading::GfxFunctionShading(GfxFunctionShading *shading): - GfxShading(shading) -{ - int i; - - x0 = shading->x0; - y0 = shading->y0; - x1 = shading->x1; - y1 = shading->y1; - for (i = 0; i < 6; ++i) { - matrix[i] = shading->matrix[i]; - } - nFuncs = shading->nFuncs; - for (i = 0; i < nFuncs; ++i) { - funcs[i] = shading->funcs[i]->copy(); - } -} - -GfxFunctionShading::~GfxFunctionShading() { - int i; - - for (i = 0; i < nFuncs; ++i) { - delete funcs[i]; - } -} - -GfxFunctionShading *GfxFunctionShading::parse(Dict *dict) { - GfxFunctionShading *shading; - double x0A, y0A, x1A, y1A; - double matrixA[6]; - Function *funcsA[gfxColorMaxComps]; - int nFuncsA; - Object obj1, obj2; - int i; - - x0A = y0A = 0; - x1A = y1A = 1; - if (dict->lookup("Domain", &obj1)->isArray() && - obj1.arrayGetLength() == 4) { - x0A = obj1.arrayGet(0, &obj2)->getNum(); - obj2.free(); - y0A = obj1.arrayGet(1, &obj2)->getNum(); - obj2.free(); - x1A = obj1.arrayGet(2, &obj2)->getNum(); - obj2.free(); - y1A = obj1.arrayGet(3, &obj2)->getNum(); - obj2.free(); - } - obj1.free(); - - matrixA[0] = 1; matrixA[1] = 0; - matrixA[2] = 0; matrixA[3] = 1; - matrixA[4] = 0; matrixA[5] = 0; - if (dict->lookup("Matrix", &obj1)->isArray() && - obj1.arrayGetLength() == 6) { - matrixA[0] = obj1.arrayGet(0, &obj2)->getNum(); - obj2.free(); - matrixA[1] = obj1.arrayGet(1, &obj2)->getNum(); - obj2.free(); - matrixA[2] = obj1.arrayGet(2, &obj2)->getNum(); - obj2.free(); - matrixA[3] = obj1.arrayGet(3, &obj2)->getNum(); - obj2.free(); - matrixA[4] = obj1.arrayGet(4, &obj2)->getNum(); - obj2.free(); - matrixA[5] = obj1.arrayGet(5, &obj2)->getNum(); - obj2.free(); - } - obj1.free(); - - dict->lookup("Function", &obj1); - if (obj1.isArray()) { - nFuncsA = obj1.arrayGetLength(); - if (nFuncsA > gfxColorMaxComps) { - error(-1, "Invalid Function array in shading dictionary"); - goto err1; - } - for (i = 0; i < nFuncsA; ++i) { - obj1.arrayGet(i, &obj2); - if (!(funcsA[i] = Function::parse(&obj2))) { - goto err2; - } - obj2.free(); - } - } else { - nFuncsA = 1; - if (!(funcsA[0] = Function::parse(&obj1))) { - goto err1; - } - } - obj1.free(); - - shading = new GfxFunctionShading(x0A, y0A, x1A, y1A, matrixA, - funcsA, nFuncsA); - if (!shading->init(dict)) { - delete shading; - return NULL; - } - return shading; - - err2: - obj2.free(); - err1: - obj1.free(); - return NULL; -} - -GfxShading *GfxFunctionShading::copy() { - return new GfxFunctionShading(this); -} - -void GfxFunctionShading::getColor(double x, double y, GfxColor *color) { - double in[2], out[gfxColorMaxComps]; - int i; - - // NB: there can be one function with n outputs or n functions with - // one output each (where n = number of color components) - for (i = 0; i < gfxColorMaxComps; ++i) { - out[i] = 0; - } - in[0] = x; - in[1] = y; - for (i = 0; i < nFuncs; ++i) { - funcs[i]->transform(in, &out[i]); - } - for (i = 0; i < gfxColorMaxComps; ++i) { - color->c[i] = dblToCol(out[i]); - } -} - -//------------------------------------------------------------------------ -// GfxAxialShading -//------------------------------------------------------------------------ - -GfxAxialShading::GfxAxialShading(double x0A, double y0A, - double x1A, double y1A, - double t0A, double t1A, - Function **funcsA, int nFuncsA, - GBool extend0A, GBool extend1A): - GfxShading(2) -{ - int i; - - x0 = x0A; - y0 = y0A; - x1 = x1A; - y1 = y1A; - t0 = t0A; - t1 = t1A; - nFuncs = nFuncsA; - for (i = 0; i < nFuncs; ++i) { - funcs[i] = funcsA[i]; - } - extend0 = extend0A; - extend1 = extend1A; -} - -GfxAxialShading::GfxAxialShading(GfxAxialShading *shading): - GfxShading(shading) -{ - int i; - - x0 = shading->x0; - y0 = shading->y0; - x1 = shading->x1; - y1 = shading->y1; - t0 = shading->t0; - y1 = shading->t1; - nFuncs = shading->nFuncs; - for (i = 0; i < nFuncs; ++i) { - funcs[i] = shading->funcs[i]->copy(); - } - extend0 = shading->extend0; - extend1 = shading->extend1; -} - -GfxAxialShading::~GfxAxialShading() { - int i; - - for (i = 0; i < nFuncs; ++i) { - delete funcs[i]; - } -} - -GfxAxialShading *GfxAxialShading::parse(Dict *dict) { - GfxAxialShading *shading; - double x0A, y0A, x1A, y1A; - double t0A, t1A; - Function *funcsA[gfxColorMaxComps]; - int nFuncsA; - GBool extend0A, extend1A; - Object obj1, obj2; - int i; - - x0A = y0A = x1A = y1A = 0; - if (dict->lookup("Coords", &obj1)->isArray() && - obj1.arrayGetLength() == 4) { - x0A = obj1.arrayGet(0, &obj2)->getNum(); - obj2.free(); - y0A = obj1.arrayGet(1, &obj2)->getNum(); - obj2.free(); - x1A = obj1.arrayGet(2, &obj2)->getNum(); - obj2.free(); - y1A = obj1.arrayGet(3, &obj2)->getNum(); - obj2.free(); - } else { - error(-1, "Missing or invalid Coords in shading dictionary"); - goto err1; - } - obj1.free(); - - t0A = 0; - t1A = 1; - if (dict->lookup("Domain", &obj1)->isArray() && - obj1.arrayGetLength() == 2) { - t0A = obj1.arrayGet(0, &obj2)->getNum(); - obj2.free(); - t1A = obj1.arrayGet(1, &obj2)->getNum(); - obj2.free(); - } - obj1.free(); - - dict->lookup("Function", &obj1); - if (obj1.isArray()) { - nFuncsA = obj1.arrayGetLength(); - if (nFuncsA > gfxColorMaxComps) { - error(-1, "Invalid Function array in shading dictionary"); - goto err1; - } - for (i = 0; i < nFuncsA; ++i) { - obj1.arrayGet(i, &obj2); - if (!(funcsA[i] = Function::parse(&obj2))) { - obj1.free(); - obj2.free(); - goto err1; - } - obj2.free(); - } - } else { - nFuncsA = 1; - if (!(funcsA[0] = Function::parse(&obj1))) { - obj1.free(); - goto err1; - } - } - obj1.free(); - - extend0A = extend1A = gFalse; - if (dict->lookup("Extend", &obj1)->isArray() && - obj1.arrayGetLength() == 2) { - extend0A = obj1.arrayGet(0, &obj2)->getBool(); - obj2.free(); - extend1A = obj1.arrayGet(1, &obj2)->getBool(); - obj2.free(); - } - obj1.free(); - - shading = new GfxAxialShading(x0A, y0A, x1A, y1A, t0A, t1A, - funcsA, nFuncsA, extend0A, extend1A); - if (!shading->init(dict)) { - delete shading; - return NULL; - } - return shading; - - err1: - return NULL; -} - -GfxShading *GfxAxialShading::copy() { - return new GfxAxialShading(this); -} - -void GfxAxialShading::getColor(double t, GfxColor *color) { - double out[gfxColorMaxComps]; - int i; - - // NB: there can be one function with n outputs or n functions with - // one output each (where n = number of color components) - for (i = 0; i < gfxColorMaxComps; ++i) { - out[i] = 0; - } - for (i = 0; i < nFuncs; ++i) { - funcs[i]->transform(&t, &out[i]); - } - for (i = 0; i < gfxColorMaxComps; ++i) { - color->c[i] = dblToCol(out[i]); - } -} - -//------------------------------------------------------------------------ -// GfxRadialShading -//------------------------------------------------------------------------ - -GfxRadialShading::GfxRadialShading(double x0A, double y0A, double r0A, - double x1A, double y1A, double r1A, - double t0A, double t1A, - Function **funcsA, int nFuncsA, - GBool extend0A, GBool extend1A): - GfxShading(3) -{ - int i; - - x0 = x0A; - y0 = y0A; - r0 = r0A; - x1 = x1A; - y1 = y1A; - r1 = r1A; - t0 = t0A; - t1 = t1A; - nFuncs = nFuncsA; - for (i = 0; i < nFuncs; ++i) { - funcs[i] = funcsA[i]; - } - extend0 = extend0A; - extend1 = extend1A; -} - -GfxRadialShading::GfxRadialShading(GfxRadialShading *shading): - GfxShading(shading) -{ - int i; - - x0 = shading->x0; - y0 = shading->y0; - r0 = shading->r0; - x1 = shading->x1; - y1 = shading->y1; - r1 = shading->r1; - t0 = shading->t0; - y1 = shading->t1; - nFuncs = shading->nFuncs; - for (i = 0; i < nFuncs; ++i) { - funcs[i] = shading->funcs[i]->copy(); - } - extend0 = shading->extend0; - extend1 = shading->extend1; -} - -GfxRadialShading::~GfxRadialShading() { - int i; - - for (i = 0; i < nFuncs; ++i) { - delete funcs[i]; - } -} - -GfxRadialShading *GfxRadialShading::parse(Dict *dict) { - GfxRadialShading *shading; - double x0A, y0A, r0A, x1A, y1A, r1A; - double t0A, t1A; - Function *funcsA[gfxColorMaxComps]; - int nFuncsA; - GBool extend0A, extend1A; - Object obj1, obj2; - int i; - - x0A = y0A = r0A = x1A = y1A = r1A = 0; - if (dict->lookup("Coords", &obj1)->isArray() && - obj1.arrayGetLength() == 6) { - x0A = obj1.arrayGet(0, &obj2)->getNum(); - obj2.free(); - y0A = obj1.arrayGet(1, &obj2)->getNum(); - obj2.free(); - r0A = obj1.arrayGet(2, &obj2)->getNum(); - obj2.free(); - x1A = obj1.arrayGet(3, &obj2)->getNum(); - obj2.free(); - y1A = obj1.arrayGet(4, &obj2)->getNum(); - obj2.free(); - r1A = obj1.arrayGet(5, &obj2)->getNum(); - obj2.free(); - } else { - error(-1, "Missing or invalid Coords in shading dictionary"); - goto err1; - } - obj1.free(); - - t0A = 0; - t1A = 1; - if (dict->lookup("Domain", &obj1)->isArray() && - obj1.arrayGetLength() == 2) { - t0A = obj1.arrayGet(0, &obj2)->getNum(); - obj2.free(); - t1A = obj1.arrayGet(1, &obj2)->getNum(); - obj2.free(); - } - obj1.free(); - - dict->lookup("Function", &obj1); - if (obj1.isArray()) { - nFuncsA = obj1.arrayGetLength(); - if (nFuncsA > gfxColorMaxComps) { - error(-1, "Invalid Function array in shading dictionary"); - goto err1; - } - for (i = 0; i < nFuncsA; ++i) { - obj1.arrayGet(i, &obj2); - if (!(funcsA[i] = Function::parse(&obj2))) { - obj1.free(); - obj2.free(); - goto err1; - } - obj2.free(); - } - } else { - nFuncsA = 1; - if (!(funcsA[0] = Function::parse(&obj1))) { - obj1.free(); - goto err1; - } - } - obj1.free(); - - extend0A = extend1A = gFalse; - if (dict->lookup("Extend", &obj1)->isArray() && - obj1.arrayGetLength() == 2) { - extend0A = obj1.arrayGet(0, &obj2)->getBool(); - obj2.free(); - extend1A = obj1.arrayGet(1, &obj2)->getBool(); - obj2.free(); - } - obj1.free(); - - shading = new GfxRadialShading(x0A, y0A, r0A, x1A, y1A, r1A, t0A, t1A, - funcsA, nFuncsA, extend0A, extend1A); - if (!shading->init(dict)) { - delete shading; - return NULL; - } - return shading; - - err1: - return NULL; -} - -GfxShading *GfxRadialShading::copy() { - return new GfxRadialShading(this); -} - -void GfxRadialShading::getColor(double t, GfxColor *color) { - double out[gfxColorMaxComps]; - int i; - - // NB: there can be one function with n outputs or n functions with - // one output each (where n = number of color components) - for (i = 0; i < gfxColorMaxComps; ++i) { - out[i] = 0; - } - for (i = 0; i < nFuncs; ++i) { - funcs[i]->transform(&t, &out[i]); - } - for (i = 0; i < gfxColorMaxComps; ++i) { - color->c[i] = dblToCol(out[i]); - } -} - -//------------------------------------------------------------------------ -// GfxShadingBitBuf -//------------------------------------------------------------------------ - -class GfxShadingBitBuf { -public: - - GfxShadingBitBuf(Stream *strA); - ~GfxShadingBitBuf(); - GBool getBits(int n, Guint *val); - void flushBits(); - -private: - - Stream *str; - int bitBuf; - int nBits; -}; - -GfxShadingBitBuf::GfxShadingBitBuf(Stream *strA) { - str = strA; - str->reset(); - bitBuf = 0; - nBits = 0; -} - -GfxShadingBitBuf::~GfxShadingBitBuf() { - str->close(); -} - -GBool GfxShadingBitBuf::getBits(int n, Guint *val) { - int x; - - if (nBits >= n) { - x = (bitBuf >> (nBits - n)) & ((1 << n) - 1); - nBits -= n; - } else { - x = 0; - if (nBits > 0) { - x = bitBuf & ((1 << nBits) - 1); - n -= nBits; - nBits = 0; - } - while (n > 0) { - if ((bitBuf = str->getChar()) == EOF) { - nBits = 0; - return gFalse; - } - if (n >= 8) { - x = (x << 8) | bitBuf; - n -= 8; - } else { - x = (x << n) | (bitBuf >> (8 - n)); - nBits = 8 - n; - n = 0; - } - } - } - *val = x; - return gTrue; -} - -void GfxShadingBitBuf::flushBits() { - bitBuf = 0; - nBits = 0; -} - -//------------------------------------------------------------------------ -// GfxGouraudTriangleShading -//------------------------------------------------------------------------ - -GfxGouraudTriangleShading::GfxGouraudTriangleShading( - int typeA, - GfxGouraudVertex *verticesA, int nVerticesA, - int (*trianglesA)[3], int nTrianglesA, - Function **funcsA, int nFuncsA): - GfxShading(typeA) -{ - int i; - - vertices = verticesA; - nVertices = nVerticesA; - triangles = trianglesA; - nTriangles = nTrianglesA; - nFuncs = nFuncsA; - for (i = 0; i < nFuncs; ++i) { - funcs[i] = funcsA[i]; - } -} - -GfxGouraudTriangleShading::GfxGouraudTriangleShading( - GfxGouraudTriangleShading *shading): - GfxShading(shading) -{ - int i; - - nVertices = shading->nVertices; - vertices = (GfxGouraudVertex *)gmallocn(nVertices, sizeof(GfxGouraudVertex)); - memcpy(vertices, shading->vertices, nVertices * sizeof(GfxGouraudVertex)); - nTriangles = shading->nTriangles; - triangles = (int (*)[3])gmallocn(nTriangles * 3, sizeof(int)); - memcpy(triangles, shading->triangles, nTriangles * 3 * sizeof(int)); - nFuncs = shading->nFuncs; - for (i = 0; i < nFuncs; ++i) { - funcs[i] = shading->funcs[i]->copy(); - } -} - -GfxGouraudTriangleShading::~GfxGouraudTriangleShading() { - int i; - - gfree(vertices); - gfree(triangles); - for (i = 0; i < nFuncs; ++i) { - delete funcs[i]; - } -} - -GfxGouraudTriangleShading *GfxGouraudTriangleShading::parse(int typeA, - Dict *dict, - Stream *str) { - GfxGouraudTriangleShading *shading; - Function *funcsA[gfxColorMaxComps]; - int nFuncsA; - int coordBits, compBits, flagBits, vertsPerRow, nRows; - double xMin, xMax, yMin, yMax; - double cMin[gfxColorMaxComps], cMax[gfxColorMaxComps]; - double xMul, yMul; - double cMul[gfxColorMaxComps]; - GfxGouraudVertex *verticesA; - int (*trianglesA)[3]; - int nComps, nVerticesA, nTrianglesA, vertSize, triSize; - Guint x, y, flag; - Guint c[gfxColorMaxComps]; - GfxShadingBitBuf *bitBuf; - Object obj1, obj2; - int i, j, k, state; - - if (dict->lookup("BitsPerCoordinate", &obj1)->isInt()) { - coordBits = obj1.getInt(); - } else { - error(-1, "Missing or invalid BitsPerCoordinate in shading dictionary"); - goto err2; - } - obj1.free(); - if (dict->lookup("BitsPerComponent", &obj1)->isInt()) { - compBits = obj1.getInt(); - } else { - error(-1, "Missing or invalid BitsPerComponent in shading dictionary"); - goto err2; - } - obj1.free(); - flagBits = vertsPerRow = 0; // make gcc happy - if (typeA == 4) { - if (dict->lookup("BitsPerFlag", &obj1)->isInt()) { - flagBits = obj1.getInt(); - } else { - error(-1, "Missing or invalid BitsPerFlag in shading dictionary"); - goto err2; - } - obj1.free(); - } else { - if (dict->lookup("VerticesPerRow", &obj1)->isInt()) { - vertsPerRow = obj1.getInt(); - } else { - error(-1, "Missing or invalid VerticesPerRow in shading dictionary"); - goto err2; - } - obj1.free(); - } - if (dict->lookup("Decode", &obj1)->isArray() && - obj1.arrayGetLength() >= 6) { - xMin = obj1.arrayGet(0, &obj2)->getNum(); - obj2.free(); - xMax = obj1.arrayGet(1, &obj2)->getNum(); - obj2.free(); - xMul = (xMax - xMin) / (pow(2.0, coordBits) - 1); - yMin = obj1.arrayGet(2, &obj2)->getNum(); - obj2.free(); - yMax = obj1.arrayGet(3, &obj2)->getNum(); - obj2.free(); - yMul = (yMax - yMin) / (pow(2.0, coordBits) - 1); - for (i = 0; 5 + 2*i < obj1.arrayGetLength() && i < gfxColorMaxComps; ++i) { - cMin[i] = obj1.arrayGet(4 + 2*i, &obj2)->getNum(); - obj2.free(); - cMax[i] = obj1.arrayGet(5 + 2*i, &obj2)->getNum(); - obj2.free(); - cMul[i] = (cMax[i] - cMin[i]) / (double)((1 << compBits) - 1); - } - nComps = i; - } else { - error(-1, "Missing or invalid Decode array in shading dictionary"); - goto err2; - } - obj1.free(); - - if (!dict->lookup("Function", &obj1)->isNull()) { - if (obj1.isArray()) { - nFuncsA = obj1.arrayGetLength(); - if (nFuncsA > gfxColorMaxComps) { - error(-1, "Invalid Function array in shading dictionary"); - goto err1; - } - for (i = 0; i < nFuncsA; ++i) { - obj1.arrayGet(i, &obj2); - if (!(funcsA[i] = Function::parse(&obj2))) { - obj1.free(); - obj2.free(); - goto err1; - } - obj2.free(); - } - } else { - nFuncsA = 1; - if (!(funcsA[0] = Function::parse(&obj1))) { - obj1.free(); - goto err1; - } - } - } else { - nFuncsA = 0; - } - obj1.free(); - - nVerticesA = nTrianglesA = 0; - verticesA = NULL; - trianglesA = NULL; - vertSize = triSize = 0; - state = 0; - flag = 0; // make gcc happy - bitBuf = new GfxShadingBitBuf(str); - while (1) { - if (typeA == 4) { - if (!bitBuf->getBits(flagBits, &flag)) { - break; - } - } - if (!bitBuf->getBits(coordBits, &x) || - !bitBuf->getBits(coordBits, &y)) { - break; - } - for (i = 0; i < nComps; ++i) { - if (!bitBuf->getBits(compBits, &c[i])) { - break; - } - } - if (i < nComps) { - break; - } - if (nVerticesA == vertSize) { - vertSize = (vertSize == 0) ? 16 : 2 * vertSize; - verticesA = (GfxGouraudVertex *) - greallocn(verticesA, vertSize, sizeof(GfxGouraudVertex)); - } - verticesA[nVerticesA].x = xMin + xMul * (double)x; - verticesA[nVerticesA].y = yMin + yMul * (double)y; - for (i = 0; i < nComps; ++i) { - verticesA[nVerticesA].color.c[i] = - dblToCol(cMin[i] + cMul[i] * (double)c[i]); - } - ++nVerticesA; - bitBuf->flushBits(); - if (typeA == 4) { - if (state == 0 || state == 1) { - ++state; - } else if (state == 2 || flag > 0) { - if (nTrianglesA == triSize) { - triSize = (triSize == 0) ? 16 : 2 * triSize; - trianglesA = (int (*)[3]) - greallocn(trianglesA, triSize * 3, sizeof(int)); - } - if (state == 2) { - trianglesA[nTrianglesA][0] = nVerticesA - 3; - trianglesA[nTrianglesA][1] = nVerticesA - 2; - trianglesA[nTrianglesA][2] = nVerticesA - 1; - ++state; - } else if (flag == 1) { - trianglesA[nTrianglesA][0] = trianglesA[nTrianglesA - 1][1]; - trianglesA[nTrianglesA][1] = trianglesA[nTrianglesA - 1][2]; - trianglesA[nTrianglesA][2] = nVerticesA - 1; - } else { // flag == 2 - trianglesA[nTrianglesA][0] = trianglesA[nTrianglesA - 1][0]; - trianglesA[nTrianglesA][1] = trianglesA[nTrianglesA - 1][2]; - trianglesA[nTrianglesA][2] = nVerticesA - 1; - } - ++nTrianglesA; - } else { // state == 3 && flag == 0 - state = 1; - } - } - } - delete bitBuf; - if (typeA == 5) { - nRows = nVerticesA / vertsPerRow; - nTrianglesA = (nRows - 1) * 2 * (vertsPerRow - 1); - trianglesA = (int (*)[3])gmallocn(nTrianglesA * 3, sizeof(int)); - k = 0; - for (i = 0; i < nRows - 1; ++i) { - for (j = 0; j < vertsPerRow - 1; ++j) { - trianglesA[k][0] = i * vertsPerRow + j; - trianglesA[k][1] = i * vertsPerRow + j+1; - trianglesA[k][2] = (i+1) * vertsPerRow + j; - ++k; - trianglesA[k][0] = i * vertsPerRow + j+1; - trianglesA[k][1] = (i+1) * vertsPerRow + j; - trianglesA[k][2] = (i+1) * vertsPerRow + j+1; - ++k; - } - } - } - - shading = new GfxGouraudTriangleShading(typeA, verticesA, nVerticesA, - trianglesA, nTrianglesA, - funcsA, nFuncsA); - if (!shading->init(dict)) { - delete shading; - return NULL; - } - return shading; - - err2: - obj1.free(); - err1: - return NULL; -} - -GfxShading *GfxGouraudTriangleShading::copy() { - return new GfxGouraudTriangleShading(this); -} - -void GfxGouraudTriangleShading::getTriangle( - int i, - double *x0, double *y0, GfxColor *color0, - double *x1, double *y1, GfxColor *color1, - double *x2, double *y2, GfxColor *color2) { - double in; - double out[gfxColorMaxComps]; - int v, j; - - v = triangles[i][0]; - *x0 = vertices[v].x; - *y0 = vertices[v].y; - if (nFuncs > 0) { - in = colToDbl(vertices[v].color.c[0]); - for (j = 0; j < nFuncs; ++j) { - funcs[j]->transform(&in, &out[j]); - } - for (j = 0; j < gfxColorMaxComps; ++j) { - color0->c[j] = dblToCol(out[j]); - } - } else { - *color0 = vertices[v].color; - } - v = triangles[i][1]; - *x1 = vertices[v].x; - *y1 = vertices[v].y; - if (nFuncs > 0) { - in = colToDbl(vertices[v].color.c[0]); - for (j = 0; j < nFuncs; ++j) { - funcs[j]->transform(&in, &out[j]); - } - for (j = 0; j < gfxColorMaxComps; ++j) { - color1->c[j] = dblToCol(out[j]); - } - } else { - *color1 = vertices[v].color; - } - v = triangles[i][2]; - *x2 = vertices[v].x; - *y2 = vertices[v].y; - if (nFuncs > 0) { - in = colToDbl(vertices[v].color.c[0]); - for (j = 0; j < nFuncs; ++j) { - funcs[j]->transform(&in, &out[j]); - } - for (j = 0; j < gfxColorMaxComps; ++j) { - color2->c[j] = dblToCol(out[j]); - } - } else { - *color2 = vertices[v].color; - } -} - -//------------------------------------------------------------------------ -// GfxPatchMeshShading -//------------------------------------------------------------------------ - -GfxPatchMeshShading::GfxPatchMeshShading(int typeA, - GfxPatch *patchesA, int nPatchesA, - Function **funcsA, int nFuncsA): - GfxShading(typeA) -{ - int i; - - patches = patchesA; - nPatches = nPatchesA; - nFuncs = nFuncsA; - for (i = 0; i < nFuncs; ++i) { - funcs[i] = funcsA[i]; - } -} - -GfxPatchMeshShading::GfxPatchMeshShading(GfxPatchMeshShading *shading): - GfxShading(shading) -{ - int i; - - nPatches = shading->nPatches; - patches = (GfxPatch *)gmallocn(nPatches, sizeof(GfxPatch)); - memcpy(patches, shading->patches, nPatches * sizeof(GfxPatch)); - nFuncs = shading->nFuncs; - for (i = 0; i < nFuncs; ++i) { - funcs[i] = shading->funcs[i]->copy(); - } -} - -GfxPatchMeshShading::~GfxPatchMeshShading() { - int i; - - gfree(patches); - for (i = 0; i < nFuncs; ++i) { - delete funcs[i]; - } -} - -GfxPatchMeshShading *GfxPatchMeshShading::parse(int typeA, Dict *dict, - Stream *str) { - GfxPatchMeshShading *shading; - Function *funcsA[gfxColorMaxComps]; - int nFuncsA; - int coordBits, compBits, flagBits; - double xMin, xMax, yMin, yMax; - double cMin[gfxColorMaxComps], cMax[gfxColorMaxComps]; - double xMul, yMul; - double cMul[gfxColorMaxComps]; - GfxPatch *patchesA, *p; - int nComps, nPatchesA, patchesSize, nPts, nColors; - Guint flag; - double x[16], y[16]; - Guint xi, yi; - GfxColorComp c[4][gfxColorMaxComps]; - Guint ci[4]; - GfxShadingBitBuf *bitBuf; - Object obj1, obj2; - int i, j; - - if (dict->lookup("BitsPerCoordinate", &obj1)->isInt()) { - coordBits = obj1.getInt(); - } else { - error(-1, "Missing or invalid BitsPerCoordinate in shading dictionary"); - goto err2; - } - obj1.free(); - if (dict->lookup("BitsPerComponent", &obj1)->isInt()) { - compBits = obj1.getInt(); - } else { - error(-1, "Missing or invalid BitsPerComponent in shading dictionary"); - goto err2; - } - obj1.free(); - if (dict->lookup("BitsPerFlag", &obj1)->isInt()) { - flagBits = obj1.getInt(); - } else { - error(-1, "Missing or invalid BitsPerFlag in shading dictionary"); - goto err2; - } - obj1.free(); - if (dict->lookup("Decode", &obj1)->isArray() && - obj1.arrayGetLength() >= 6) { - xMin = obj1.arrayGet(0, &obj2)->getNum(); - obj2.free(); - xMax = obj1.arrayGet(1, &obj2)->getNum(); - obj2.free(); - xMul = (xMax - xMin) / (pow(2.0, coordBits) - 1); - yMin = obj1.arrayGet(2, &obj2)->getNum(); - obj2.free(); - yMax = obj1.arrayGet(3, &obj2)->getNum(); - obj2.free(); - yMul = (yMax - yMin) / (pow(2.0, coordBits) - 1); - for (i = 0; 5 + 2*i < obj1.arrayGetLength() && i < gfxColorMaxComps; ++i) { - cMin[i] = obj1.arrayGet(4 + 2*i, &obj2)->getNum(); - obj2.free(); - cMax[i] = obj1.arrayGet(5 + 2*i, &obj2)->getNum(); - obj2.free(); - cMul[i] = (cMax[i] - cMin[i]) / (double)((1 << compBits) - 1); - } - nComps = i; - } else { - error(-1, "Missing or invalid Decode array in shading dictionary"); - goto err2; - } - obj1.free(); - - if (!dict->lookup("Function", &obj1)->isNull()) { - if (obj1.isArray()) { - nFuncsA = obj1.arrayGetLength(); - if (nFuncsA > gfxColorMaxComps) { - error(-1, "Invalid Function array in shading dictionary"); - goto err1; - } - for (i = 0; i < nFuncsA; ++i) { - obj1.arrayGet(i, &obj2); - if (!(funcsA[i] = Function::parse(&obj2))) { - obj1.free(); - obj2.free(); - goto err1; - } - obj2.free(); - } - } else { - nFuncsA = 1; - if (!(funcsA[0] = Function::parse(&obj1))) { - obj1.free(); - goto err1; - } - } - } else { - nFuncsA = 0; - } - obj1.free(); - - nPatchesA = 0; - patchesA = NULL; - patchesSize = 0; - bitBuf = new GfxShadingBitBuf(str); - while (1) { - if (!bitBuf->getBits(flagBits, &flag)) { - break; - } - if (typeA == 6) { - switch (flag) { - case 0: nPts = 12; nColors = 4; break; - case 1: - case 2: - case 3: - default: nPts = 8; nColors = 2; break; - } - } else { - switch (flag) { - case 0: nPts = 16; nColors = 4; break; - case 1: - case 2: - case 3: - default: nPts = 12; nColors = 2; break; - } - } - for (i = 0; i < nPts; ++i) { - if (!bitBuf->getBits(coordBits, &xi) || - !bitBuf->getBits(coordBits, &yi)) { - break; - } - x[i] = xMin + xMul * (double)xi; - y[i] = yMin + yMul * (double)yi; - } - if (i < nPts) { - break; - } - for (i = 0; i < nColors; ++i) { - for (j = 0; j < nComps; ++j) { - if (!bitBuf->getBits(compBits, &ci[j])) { - break; - } - c[i][j] = dblToCol(cMin[j] + cMul[j] * (double)ci[j]); - } - if (j < nComps) { - break; - } - } - if (i < nColors) { - break; - } - if (nPatchesA == patchesSize) { - patchesSize = (patchesSize == 0) ? 16 : 2 * patchesSize; - patchesA = (GfxPatch *)greallocn(patchesA, - patchesSize, sizeof(GfxPatch)); - } - p = &patchesA[nPatchesA]; - if (typeA == 6) { - switch (flag) { - case 0: - p->x[0][0] = x[0]; - p->y[0][0] = y[0]; - p->x[0][1] = x[1]; - p->y[0][1] = y[1]; - p->x[0][2] = x[2]; - p->y[0][2] = y[2]; - p->x[0][3] = x[3]; - p->y[0][3] = y[3]; - p->x[1][3] = x[4]; - p->y[1][3] = y[4]; - p->x[2][3] = x[5]; - p->y[2][3] = y[5]; - p->x[3][3] = x[6]; - p->y[3][3] = y[6]; - p->x[3][2] = x[7]; - p->y[3][2] = y[7]; - p->x[3][1] = x[8]; - p->y[3][1] = y[8]; - p->x[3][0] = x[9]; - p->y[3][0] = y[9]; - p->x[2][0] = x[10]; - p->y[2][0] = y[10]; - p->x[1][0] = x[11]; - p->y[1][0] = y[11]; - for (j = 0; j < nComps; ++j) { - p->color[0][0].c[j] = c[0][j]; - p->color[0][1].c[j] = c[1][j]; - p->color[1][1].c[j] = c[2][j]; - p->color[1][0].c[j] = c[3][j]; - } - break; - case 1: - p->x[0][0] = patchesA[nPatchesA-1].x[0][3]; - p->y[0][0] = patchesA[nPatchesA-1].y[0][3]; - p->x[0][1] = patchesA[nPatchesA-1].x[1][3]; - p->y[0][1] = patchesA[nPatchesA-1].y[1][3]; - p->x[0][2] = patchesA[nPatchesA-1].x[2][3]; - p->y[0][2] = patchesA[nPatchesA-1].y[2][3]; - p->x[0][3] = patchesA[nPatchesA-1].x[3][3]; - p->y[0][3] = patchesA[nPatchesA-1].y[3][3]; - p->x[1][3] = x[0]; - p->y[1][3] = y[0]; - p->x[2][3] = x[1]; - p->y[2][3] = y[1]; - p->x[3][3] = x[2]; - p->y[3][3] = y[2]; - p->x[3][2] = x[3]; - p->y[3][2] = y[3]; - p->x[3][1] = x[4]; - p->y[3][1] = y[4]; - p->x[3][0] = x[5]; - p->y[3][0] = y[5]; - p->x[2][0] = x[6]; - p->y[2][0] = y[6]; - p->x[1][0] = x[7]; - p->y[1][0] = y[7]; - for (j = 0; j < nComps; ++j) { - p->color[0][0].c[j] = patchesA[nPatchesA-1].color[0][1].c[j]; - p->color[0][1].c[j] = patchesA[nPatchesA-1].color[1][1].c[j]; - p->color[1][1].c[j] = c[0][j]; - p->color[1][0].c[j] = c[1][j]; - } - break; - case 2: - p->x[0][0] = patchesA[nPatchesA-1].x[3][3]; - p->y[0][0] = patchesA[nPatchesA-1].y[3][3]; - p->x[0][1] = patchesA[nPatchesA-1].x[3][2]; - p->y[0][1] = patchesA[nPatchesA-1].y[3][2]; - p->x[0][2] = patchesA[nPatchesA-1].x[3][1]; - p->y[0][2] = patchesA[nPatchesA-1].y[3][1]; - p->x[0][3] = patchesA[nPatchesA-1].x[3][0]; - p->y[0][3] = patchesA[nPatchesA-1].y[3][0]; - p->x[1][3] = x[0]; - p->y[1][3] = y[0]; - p->x[2][3] = x[1]; - p->y[2][3] = y[1]; - p->x[3][3] = x[2]; - p->y[3][3] = y[2]; - p->x[3][2] = x[3]; - p->y[3][2] = y[3]; - p->x[3][1] = x[4]; - p->y[3][1] = y[4]; - p->x[3][0] = x[5]; - p->y[3][0] = y[5]; - p->x[2][0] = x[6]; - p->y[2][0] = y[6]; - p->x[1][0] = x[7]; - p->y[1][0] = y[7]; - for (j = 0; j < nComps; ++j) { - p->color[0][0].c[j] = patchesA[nPatchesA-1].color[1][1].c[j]; - p->color[0][1].c[j] = patchesA[nPatchesA-1].color[1][0].c[j]; - p->color[1][1].c[j] = c[0][j]; - p->color[1][0].c[j] = c[1][j]; - } - break; - case 3: - p->x[0][0] = patchesA[nPatchesA-1].x[3][0]; - p->y[0][0] = patchesA[nPatchesA-1].y[3][0]; - p->x[0][1] = patchesA[nPatchesA-1].x[2][0]; - p->y[0][1] = patchesA[nPatchesA-1].y[2][0]; - p->x[0][2] = patchesA[nPatchesA-1].x[1][0]; - p->y[0][2] = patchesA[nPatchesA-1].y[1][0]; - p->x[0][3] = patchesA[nPatchesA-1].x[0][0]; - p->y[0][3] = patchesA[nPatchesA-1].y[0][0]; - p->x[1][3] = x[0]; - p->y[1][3] = y[0]; - p->x[2][3] = x[1]; - p->y[2][3] = y[1]; - p->x[3][3] = x[2]; - p->y[3][3] = y[2]; - p->x[3][2] = x[3]; - p->y[3][2] = y[3]; - p->x[3][1] = x[4]; - p->y[3][1] = y[4]; - p->x[3][0] = x[5]; - p->y[3][0] = y[5]; - p->x[2][0] = x[6]; - p->y[2][0] = y[6]; - p->x[1][0] = x[7]; - p->y[1][0] = y[7]; - for (j = 0; j < nComps; ++j) { - p->color[0][1].c[j] = patchesA[nPatchesA-1].color[1][0].c[j]; - p->color[0][1].c[j] = patchesA[nPatchesA-1].color[0][0].c[j]; - p->color[1][1].c[j] = c[0][j]; - p->color[1][0].c[j] = c[1][j]; - } - break; - } - } else { - switch (flag) { - case 0: - p->x[0][0] = x[0]; - p->y[0][0] = y[0]; - p->x[0][1] = x[1]; - p->y[0][1] = y[1]; - p->x[0][2] = x[2]; - p->y[0][2] = y[2]; - p->x[0][3] = x[3]; - p->y[0][3] = y[3]; - p->x[1][3] = x[4]; - p->y[1][3] = y[4]; - p->x[2][3] = x[5]; - p->y[2][3] = y[5]; - p->x[3][3] = x[6]; - p->y[3][3] = y[6]; - p->x[3][2] = x[7]; - p->y[3][2] = y[7]; - p->x[3][1] = x[8]; - p->y[3][1] = y[8]; - p->x[3][0] = x[9]; - p->y[3][0] = y[9]; - p->x[2][0] = x[10]; - p->y[2][0] = y[10]; - p->x[1][0] = x[11]; - p->y[1][0] = y[11]; - p->x[1][1] = x[12]; - p->y[1][1] = y[12]; - p->x[1][2] = x[13]; - p->y[1][2] = y[13]; - p->x[2][2] = x[14]; - p->y[2][2] = y[14]; - p->x[2][1] = x[15]; - p->y[2][1] = y[15]; - for (j = 0; j < nComps; ++j) { - p->color[0][0].c[j] = c[0][j]; - p->color[0][1].c[j] = c[1][j]; - p->color[1][1].c[j] = c[2][j]; - p->color[1][0].c[j] = c[3][j]; - } - break; - case 1: - p->x[0][0] = patchesA[nPatchesA-1].x[0][3]; - p->y[0][0] = patchesA[nPatchesA-1].y[0][3]; - p->x[0][1] = patchesA[nPatchesA-1].x[1][3]; - p->y[0][1] = patchesA[nPatchesA-1].y[1][3]; - p->x[0][2] = patchesA[nPatchesA-1].x[2][3]; - p->y[0][2] = patchesA[nPatchesA-1].y[2][3]; - p->x[0][3] = patchesA[nPatchesA-1].x[3][3]; - p->y[0][3] = patchesA[nPatchesA-1].y[3][3]; - p->x[1][3] = x[0]; - p->y[1][3] = y[0]; - p->x[2][3] = x[1]; - p->y[2][3] = y[1]; - p->x[3][3] = x[2]; - p->y[3][3] = y[2]; - p->x[3][2] = x[3]; - p->y[3][2] = y[3]; - p->x[3][1] = x[4]; - p->y[3][1] = y[4]; - p->x[3][0] = x[5]; - p->y[3][0] = y[5]; - p->x[2][0] = x[6]; - p->y[2][0] = y[6]; - p->x[1][0] = x[7]; - p->y[1][0] = y[7]; - p->x[1][1] = x[8]; - p->y[1][1] = y[8]; - p->x[1][2] = x[9]; - p->y[1][2] = y[9]; - p->x[2][2] = x[10]; - p->y[2][2] = y[10]; - p->x[2][1] = x[11]; - p->y[2][1] = y[11]; - for (j = 0; j < nComps; ++j) { - p->color[0][0].c[j] = patchesA[nPatchesA-1].color[0][1].c[j]; - p->color[0][1].c[j] = patchesA[nPatchesA-1].color[1][1].c[j]; - p->color[1][1].c[j] = c[0][j]; - p->color[1][0].c[j] = c[1][j]; - } - break; - case 2: - p->x[0][0] = patchesA[nPatchesA-1].x[3][3]; - p->y[0][0] = patchesA[nPatchesA-1].y[3][3]; - p->x[0][1] = patchesA[nPatchesA-1].x[3][2]; - p->y[0][1] = patchesA[nPatchesA-1].y[3][2]; - p->x[0][2] = patchesA[nPatchesA-1].x[3][1]; - p->y[0][2] = patchesA[nPatchesA-1].y[3][1]; - p->x[0][3] = patchesA[nPatchesA-1].x[3][0]; - p->y[0][3] = patchesA[nPatchesA-1].y[3][0]; - p->x[1][3] = x[0]; - p->y[1][3] = y[0]; - p->x[2][3] = x[1]; - p->y[2][3] = y[1]; - p->x[3][3] = x[2]; - p->y[3][3] = y[2]; - p->x[3][2] = x[3]; - p->y[3][2] = y[3]; - p->x[3][1] = x[4]; - p->y[3][1] = y[4]; - p->x[3][0] = x[5]; - p->y[3][0] = y[5]; - p->x[2][0] = x[6]; - p->y[2][0] = y[6]; - p->x[1][0] = x[7]; - p->y[1][0] = y[7]; - p->x[1][1] = x[8]; - p->y[1][1] = y[8]; - p->x[1][2] = x[9]; - p->y[1][2] = y[9]; - p->x[2][2] = x[10]; - p->y[2][2] = y[10]; - p->x[2][1] = x[11]; - p->y[2][1] = y[11]; - for (j = 0; j < nComps; ++j) { - p->color[0][0].c[j] = patchesA[nPatchesA-1].color[1][1].c[j]; - p->color[0][1].c[j] = patchesA[nPatchesA-1].color[1][0].c[j]; - p->color[1][1].c[j] = c[0][j]; - p->color[1][0].c[j] = c[1][j]; - } - break; - case 3: - p->x[0][0] = patchesA[nPatchesA-1].x[3][0]; - p->y[0][0] = patchesA[nPatchesA-1].y[3][0]; - p->x[0][1] = patchesA[nPatchesA-1].x[2][0]; - p->y[0][1] = patchesA[nPatchesA-1].y[2][0]; - p->x[0][2] = patchesA[nPatchesA-1].x[1][0]; - p->y[0][2] = patchesA[nPatchesA-1].y[1][0]; - p->x[0][3] = patchesA[nPatchesA-1].x[0][0]; - p->y[0][3] = patchesA[nPatchesA-1].y[0][0]; - p->x[1][3] = x[0]; - p->y[1][3] = y[0]; - p->x[2][3] = x[1]; - p->y[2][3] = y[1]; - p->x[3][3] = x[2]; - p->y[3][3] = y[2]; - p->x[3][2] = x[3]; - p->y[3][2] = y[3]; - p->x[3][1] = x[4]; - p->y[3][1] = y[4]; - p->x[3][0] = x[5]; - p->y[3][0] = y[5]; - p->x[2][0] = x[6]; - p->y[2][0] = y[6]; - p->x[1][0] = x[7]; - p->y[1][0] = y[7]; - p->x[1][1] = x[8]; - p->y[1][1] = y[8]; - p->x[1][2] = x[9]; - p->y[1][2] = y[9]; - p->x[2][2] = x[10]; - p->y[2][2] = y[10]; - p->x[2][1] = x[11]; - p->y[2][1] = y[11]; - for (j = 0; j < nComps; ++j) { - p->color[0][0].c[j] = patchesA[nPatchesA-1].color[1][0].c[j]; - p->color[0][1].c[j] = patchesA[nPatchesA-1].color[0][0].c[j]; - p->color[1][1].c[j] = c[0][j]; - p->color[1][0].c[j] = c[1][j]; - } - break; - } - } - ++nPatchesA; - bitBuf->flushBits(); - } - delete bitBuf; - - if (typeA == 6) { - for (i = 0; i < nPatchesA; ++i) { - p = &patchesA[i]; - p->x[1][1] = (-4 * p->x[0][0] - +6 * (p->x[0][1] + p->x[1][0]) - -2 * (p->x[0][3] + p->x[3][0]) - +3 * (p->x[3][1] + p->x[1][3]) - - p->x[3][3]) / 9; - p->y[1][1] = (-4 * p->y[0][0] - +6 * (p->y[0][1] + p->y[1][0]) - -2 * (p->y[0][3] + p->y[3][0]) - +3 * (p->y[3][1] + p->y[1][3]) - - p->y[3][3]) / 9; - p->x[1][2] = (-4 * p->x[0][3] - +6 * (p->x[0][2] + p->x[1][3]) - -2 * (p->x[0][0] + p->x[3][3]) - +3 * (p->x[3][2] + p->x[1][0]) - - p->x[3][0]) / 9; - p->y[1][2] = (-4 * p->y[0][3] - +6 * (p->y[0][2] + p->y[1][3]) - -2 * (p->y[0][0] + p->y[3][3]) - +3 * (p->y[3][2] + p->y[1][0]) - - p->y[3][0]) / 9; - p->x[2][1] = (-4 * p->x[3][0] - +6 * (p->x[3][1] + p->x[2][0]) - -2 * (p->x[3][3] + p->x[0][0]) - +3 * (p->x[0][1] + p->x[2][3]) - - p->x[0][3]) / 9; - p->y[2][1] = (-4 * p->y[3][0] - +6 * (p->y[3][1] + p->y[2][0]) - -2 * (p->y[3][3] + p->y[0][0]) - +3 * (p->y[0][1] + p->y[2][3]) - - p->y[0][3]) / 9; - p->x[2][2] = (-4 * p->x[3][3] - +6 * (p->x[3][2] + p->x[2][3]) - -2 * (p->x[3][0] + p->x[0][3]) - +3 * (p->x[0][2] + p->x[2][0]) - - p->x[0][0]) / 9; - p->y[2][2] = (-4 * p->y[3][3] - +6 * (p->y[3][2] + p->y[2][3]) - -2 * (p->y[3][0] + p->y[0][3]) - +3 * (p->y[0][2] + p->y[2][0]) - - p->y[0][0]) / 9; - } - } - - shading = new GfxPatchMeshShading(typeA, patchesA, nPatchesA, - funcsA, nFuncsA); - if (!shading->init(dict)) { - delete shading; - return NULL; - } - return shading; - - err2: - obj1.free(); - err1: - return NULL; -} - -GfxShading *GfxPatchMeshShading::copy() { - return new GfxPatchMeshShading(this); -} - -//------------------------------------------------------------------------ -// GfxImageColorMap -//------------------------------------------------------------------------ - -GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode, - GfxColorSpace *colorSpaceA) { - GfxIndexedColorSpace *indexedCS; - GfxSeparationColorSpace *sepCS; - int maxPixel, indexHigh; - Guchar *lookup2; - Function *sepFunc; - Object obj; - double x[gfxColorMaxComps]; - double y[gfxColorMaxComps]; - int i, j, k; - - ok = gTrue; - - // bits per component and color space - bits = bitsA; - maxPixel = (1 << bits) - 1; - colorSpace = colorSpaceA; - - // get decode map - if (decode->isNull()) { - nComps = colorSpace->getNComps(); - colorSpace->getDefaultRanges(decodeLow, decodeRange, maxPixel); - } else if (decode->isArray()) { - nComps = decode->arrayGetLength() / 2; - if (nComps != colorSpace->getNComps()) { - goto err1; - } - for (i = 0; i < nComps; ++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; - } - - // Construct a lookup table -- this stores pre-computed decoded - // values for each component, i.e., the result of applying the - // decode mapping to each possible image pixel component value. - // - // Optimization: for Indexed and Separation color spaces (which have - // only one component), we store color values in the lookup table - // rather than component values. - for (k = 0; k < gfxColorMaxComps; ++k) { - lookup[k] = NULL; - } - colorSpace2 = NULL; - nComps2 = 0; - if (colorSpace->getMode() == csIndexed) { - // Note that indexHigh may not be the same as maxPixel -- - // Distiller will remove unused palette entries, resulting in - // indexHigh < maxPixel. - indexedCS = (GfxIndexedColorSpace *)colorSpace; - colorSpace2 = indexedCS->getBase(); - indexHigh = indexedCS->getIndexHigh(); - nComps2 = colorSpace2->getNComps(); - lookup2 = indexedCS->getLookup(); - colorSpace2->getDefaultRanges(x, y, indexHigh); - for (k = 0; k < nComps2; ++k) { - lookup[k] = (GfxColorComp *)gmallocn(maxPixel + 1, - sizeof(GfxColorComp)); - for (i = 0; i <= maxPixel; ++i) { - j = (int)(decodeLow[0] + (i * decodeRange[0]) / maxPixel + 0.5); - if (j < 0) { - j = 0; - } else if (j > indexHigh) { - j = indexHigh; - } - lookup[k][i] = - dblToCol(x[k] + (lookup2[j*nComps2 + k] / 255.0) * y[k]); - } - } - } else if (colorSpace->getMode() == csSeparation) { - sepCS = (GfxSeparationColorSpace *)colorSpace; - colorSpace2 = sepCS->getAlt(); - nComps2 = colorSpace2->getNComps(); - sepFunc = sepCS->getFunc(); - for (k = 0; k < nComps2; ++k) { - lookup[k] = (GfxColorComp *)gmallocn(maxPixel + 1, - sizeof(GfxColorComp)); - for (i = 0; i <= maxPixel; ++i) { - x[0] = decodeLow[0] + (i * decodeRange[0]) / maxPixel; - sepFunc->transform(x, y); - lookup[k][i] = dblToCol(y[k]); - } - } - } else { - for (k = 0; k < nComps; ++k) { - lookup[k] = (GfxColorComp *)gmallocn(maxPixel + 1, - sizeof(GfxColorComp)); - for (i = 0; i <= maxPixel; ++i) { - lookup[k][i] = dblToCol(decodeLow[k] + - (i * decodeRange[k]) / maxPixel); - } - } - } - - return; - - err2: - obj.free(); - err1: - ok = gFalse; -} - -GfxImageColorMap::GfxImageColorMap(GfxImageColorMap *colorMap) { - int n, i, k; - - colorSpace = colorMap->colorSpace->copy(); - bits = colorMap->bits; - nComps = colorMap->nComps; - nComps2 = colorMap->nComps2; - colorSpace2 = NULL; - for (k = 0; k < gfxColorMaxComps; ++k) { - lookup[k] = NULL; - } - n = 1 << bits; - if (colorSpace->getMode() == csIndexed) { - colorSpace2 = ((GfxIndexedColorSpace *)colorSpace)->getBase(); - for (k = 0; k < nComps2; ++k) { - lookup[k] = (GfxColorComp *)gmallocn(n, sizeof(GfxColorComp)); - memcpy(lookup[k], colorMap->lookup[k], n * sizeof(GfxColorComp)); - } - } else if (colorSpace->getMode() == csSeparation) { - colorSpace2 = ((GfxSeparationColorSpace *)colorSpace)->getAlt(); - for (k = 0; k < nComps2; ++k) { - lookup[k] = (GfxColorComp *)gmallocn(n, sizeof(GfxColorComp)); - memcpy(lookup[k], colorMap->lookup[k], n * sizeof(GfxColorComp)); - } - } else { - for (k = 0; k < nComps; ++k) { - lookup[k] = (GfxColorComp *)gmallocn(n, sizeof(GfxColorComp)); - memcpy(lookup[k], colorMap->lookup[k], n * sizeof(GfxColorComp)); - } - } - for (i = 0; i < nComps; ++i) { - decodeLow[i] = colorMap->decodeLow[i]; - decodeRange[i] = colorMap->decodeRange[i]; - } - ok = gTrue; -} - -GfxImageColorMap::~GfxImageColorMap() { - int i; - - delete colorSpace; - for (i = 0; i < gfxColorMaxComps; ++i) { - gfree(lookup[i]); - } -} - -void GfxImageColorMap::getGray(Guchar *x, GfxGray *gray) { - GfxColor color; - int i; - - if (colorSpace2) { - for (i = 0; i < nComps2; ++i) { - color.c[i] = lookup[i][x[0]]; - } - colorSpace2->getGray(&color, gray); - } else { - for (i = 0; i < nComps; ++i) { - color.c[i] = lookup[i][x[i]]; - } - colorSpace->getGray(&color, gray); - } -} - -void GfxImageColorMap::getRGB(Guchar *x, GfxRGB *rgb) { - GfxColor color; - int i; - - if (colorSpace2) { - for (i = 0; i < nComps2; ++i) { - color.c[i] = lookup[i][x[0]]; - } - colorSpace2->getRGB(&color, rgb); - } else { - for (i = 0; i < nComps; ++i) { - color.c[i] = lookup[i][x[i]]; - } - colorSpace->getRGB(&color, rgb); - } -} - -void GfxImageColorMap::getCMYK(Guchar *x, GfxCMYK *cmyk) { - GfxColor color; - int i; - - if (colorSpace2) { - for (i = 0; i < nComps2; ++i) { - color.c[i] = lookup[i][x[0]]; - } - colorSpace2->getCMYK(&color, cmyk); - } else { - for (i = 0; i < nComps; ++i) { - color.c[i] = lookup[i][x[i]]; - } - colorSpace->getCMYK(&color, cmyk); - } -} - -void GfxImageColorMap::getColor(Guchar *x, GfxColor *color) { - int maxPixel, i; - - maxPixel = (1 << bits) - 1; - for (i = 0; i < nComps; ++i) { - color->c[i] = dblToCol(decodeLow[i] + (x[i] * decodeRange[i]) / maxPixel); - } -} - -//------------------------------------------------------------------------ -// GfxSubpath and GfxPath -//------------------------------------------------------------------------ - -GfxSubpath::GfxSubpath(double x1, double y1) { - size = 16; - x = (double *)gmallocn(size, sizeof(double)); - y = (double *)gmallocn(size, sizeof(double)); - curve = (GBool *)gmallocn(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 *)gmallocn(size, sizeof(double)); - y = (double *)gmallocn(size, sizeof(double)); - curve = (GBool *)gmallocn(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 *)greallocn(x, size, sizeof(double)); - y = (double *)greallocn(y, size, sizeof(double)); - curve = (GBool *)greallocn(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 *)greallocn(x, size, sizeof(double)); - y = (double *)greallocn(y, size, sizeof(double)); - curve = (GBool *)greallocn(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; -} - -void GfxSubpath::offset(double dx, double dy) { - int i; - - for (i = 0; i < n; ++i) { - x[i] += dx; - y[i] += dy; - } -} - -GfxPath::GfxPath() { - justMoved = gFalse; - size = 16; - n = 0; - firstX = firstY = 0; - subpaths = (GfxSubpath **)gmallocn(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 **)gmallocn(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 **) - greallocn(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 **) - greallocn(subpaths, size, sizeof(GfxSubpath *)); - } - subpaths[n] = new GfxSubpath(firstX, firstY); - ++n; - justMoved = gFalse; - } - subpaths[n-1]->curveTo(x1, y1, x2, y2, x3, y3); -} - -void GfxPath::close() { - // this is necessary to handle the pathological case of - // moveto/closepath/clip, which defines an empty clipping region - if (justMoved) { - if (n >= size) { - size += 16; - subpaths = (GfxSubpath **) - greallocn(subpaths, size, sizeof(GfxSubpath *)); - } - subpaths[n] = new GfxSubpath(firstX, firstY); - ++n; - justMoved = gFalse; - } - subpaths[n-1]->close(); -} - -void GfxPath::append(GfxPath *path) { - int i; - - if (n + path->n > size) { - size = n + path->n; - subpaths = (GfxSubpath **) - greallocn(subpaths, size, sizeof(GfxSubpath *)); - } - for (i = 0; i < path->n; ++i) { - subpaths[n++] = path->subpaths[i]->copy(); - } - justMoved = gFalse; -} - -void GfxPath::offset(double dx, double dy) { - int i; - - for (i = 0; i < n; ++i) { - subpaths[i]->offset(dx, dy); - } -} - -//------------------------------------------------------------------------ -// GfxState -//------------------------------------------------------------------------ - -GfxState::GfxState(double hDPI, double vDPI, PDFRectangle *pageBox, - int rotateA, GBool upsideDown) { - double kx, ky; - - rotate = rotateA; - px1 = pageBox->x1; - py1 = pageBox->y1; - px2 = pageBox->x2; - py2 = pageBox->y2; - kx = hDPI / 72.0; - ky = vDPI / 72.0; - if (rotate == 90) { - ctm[0] = 0; - ctm[1] = upsideDown ? ky : -ky; - ctm[2] = kx; - ctm[3] = 0; - ctm[4] = -kx * py1; - ctm[5] = ky * (upsideDown ? -px1 : px2); - pageWidth = kx * (py2 - py1); - pageHeight = ky * (px2 - px1); - } else if (rotate == 180) { - ctm[0] = -kx; - ctm[1] = 0; - ctm[2] = 0; - ctm[3] = upsideDown ? ky : -ky; - ctm[4] = kx * px2; - ctm[5] = ky * (upsideDown ? -py1 : py2); - pageWidth = kx * (px2 - px1); - pageHeight = ky * (py2 - py1); - } else if (rotate == 270) { - ctm[0] = 0; - ctm[1] = upsideDown ? -ky : ky; - ctm[2] = -kx; - ctm[3] = 0; - ctm[4] = kx * py2; - ctm[5] = ky * (upsideDown ? px2 : -px1); - pageWidth = kx * (py2 - py1); - pageHeight = ky * (px2 - px1); - } else { - ctm[0] = kx; - ctm[1] = 0; - ctm[2] = 0; - ctm[3] = upsideDown ? -ky : ky; - ctm[4] = -kx * px1; - ctm[5] = ky * (upsideDown ? py2 : -py1); - pageWidth = kx * (px2 - px1); - pageHeight = ky * (py2 - py1); - } - - fillColorSpace = new GfxDeviceGrayColorSpace(); - strokeColorSpace = new GfxDeviceGrayColorSpace(); - fillColor.c[0] = 0; - strokeColor.c[0] = 0; - fillPattern = NULL; - strokePattern = NULL; - blendMode = gfxBlendNormal; - fillOpacity = 1; - strokeOpacity = 1; - fillOverprint = gFalse; - strokeOverprint = gFalse; - - lineWidth = 1; - lineDash = NULL; - lineDashLength = 0; - lineDashStart = 0; - flatness = 1; - 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; - - clipXMin = 0; - clipYMin = 0; - clipXMax = pageWidth; - clipYMax = pageHeight; - - saved = NULL; -} - -GfxState::~GfxState() { - if (fillColorSpace) { - delete fillColorSpace; - } - if (strokeColorSpace) { - delete strokeColorSpace; - } - if (fillPattern) { - delete fillPattern; - } - if (strokePattern) { - delete strokePattern; - } - gfree(lineDash); - if (path) { - // this gets set to NULL by restore() - 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 (fillPattern) { - fillPattern = state->fillPattern->copy(); - } - if (strokePattern) { - strokePattern = state->strokePattern->copy(); - } - if (lineDashLength > 0) { - lineDash = (double *)gmallocn(lineDashLength, sizeof(double)); - memcpy(lineDash, state->lineDash, lineDashLength * sizeof(double)); - } - saved = NULL; -} - -void GfxState::setPath(GfxPath *pathA) { - delete path; - path = pathA; -} - -void GfxState::getUserClipBBox(double *xMin, double *yMin, - double *xMax, double *yMax) { - double ictm[6]; - double xMin1, yMin1, xMax1, yMax1, det, tx, ty; - - // invert the CTM - 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; - - // transform all four corners of the clip bbox; find the min and max - // x and y values - xMin1 = xMax1 = clipXMin * ictm[0] + clipYMin * ictm[2] + ictm[4]; - yMin1 = yMax1 = clipXMin * ictm[1] + clipYMin * ictm[3] + ictm[5]; - tx = clipXMin * ictm[0] + clipYMax * ictm[2] + ictm[4]; - ty = clipXMin * ictm[1] + clipYMax * ictm[3] + ictm[5]; - if (tx < xMin1) { - xMin1 = tx; - } else if (tx > xMax1) { - xMax1 = tx; - } - if (ty < yMin1) { - yMin1 = ty; - } else if (ty > yMax1) { - yMax1 = ty; - } - tx = clipXMax * ictm[0] + clipYMin * ictm[2] + ictm[4]; - ty = clipXMax * ictm[1] + clipYMin * ictm[3] + ictm[5]; - if (tx < xMin1) { - xMin1 = tx; - } else if (tx > xMax1) { - xMax1 = tx; - } - if (ty < yMin1) { - yMin1 = ty; - } else if (ty > yMax1) { - yMax1 = ty; - } - tx = clipXMax * ictm[0] + clipYMax * ictm[2] + ictm[4]; - ty = clipXMax * ictm[1] + clipYMax * ictm[3] + ictm[5]; - if (tx < xMin1) { - xMin1 = tx; - } else if (tx > xMax1) { - xMax1 = tx; - } - if (ty < yMin1) { - yMin1 = ty; - } else if (ty > yMax1) { - yMax1 = ty; - } - - *xMin = xMin1; - *yMin = yMin1; - *xMax = xMax1; - *yMax = yMax1; -} - -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) { - int i; - - ctm[0] = a; - ctm[1] = b; - ctm[2] = c; - ctm[3] = d; - ctm[4] = e; - ctm[5] = f; - - // avoid FP exceptions on badly messed up PDF files - for (i = 0; i < 6; ++i) { - if (ctm[i] > 1e10) { - ctm[i] = 1e10; - } else if (ctm[i] < -1e10) { - ctm[i] = -1e10; - } - } -} - -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]; - int i; - - 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]; - - // avoid FP exceptions on badly messed up PDF files - for (i = 0; i < 6; ++i) { - if (ctm[i] > 1e10) { - ctm[i] = 1e10; - } else if (ctm[i] < -1e10) { - ctm[i] = -1e10; - } - } -} - -void GfxState::setFillColorSpace(GfxColorSpace *colorSpace) { - if (fillColorSpace) { - delete fillColorSpace; - } - fillColorSpace = colorSpace; -} - -void GfxState::setStrokeColorSpace(GfxColorSpace *colorSpace) { - if (strokeColorSpace) { - delete strokeColorSpace; - } - strokeColorSpace = colorSpace; -} - -void GfxState::setFillPattern(GfxPattern *pattern) { - if (fillPattern) { - delete fillPattern; - } - fillPattern = pattern; -} - -void GfxState::setStrokePattern(GfxPattern *pattern) { - if (strokePattern) { - delete strokePattern; - } - strokePattern = pattern; -} - -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::clip() { - double xMin, yMin, xMax, yMax, x, y; - GfxSubpath *subpath; - int i, j; - - xMin = xMax = yMin = yMax = 0; // make gcc happy - for (i = 0; i < path->getNumSubpaths(); ++i) { - subpath = path->getSubpath(i); - for (j = 0; j < subpath->getNumPoints(); ++j) { - transform(subpath->getX(j), subpath->getY(j), &x, &y); - if (i == 0 && j == 0) { - xMin = xMax = x; - yMin = yMax = y; - } else { - if (x < xMin) { - xMin = x; - } else if (x > xMax) { - xMax = x; - } - if (y < yMin) { - yMin = y; - } else if (y > yMax) { - yMax = y; - } - } - } - } - if (xMin > clipXMin) { - clipXMin = xMin; - } - if (yMin > clipYMin) { - clipYMin = yMin; - } - if (xMax < clipXMax) { - clipXMax = xMax; - } - if (yMax < clipYMax) { - clipYMax = yMax; - } -} - -void GfxState::textShift(double tx, double ty) { - double dx, dy; - - textTransformDelta(tx, ty, &dx, &dy); - curX += dx; - curY += dy; -} - -void GfxState::shift(double dx, double 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; - - // these attributes aren't saved/restored by the q/Q operators - oldState->path = path; - oldState->curX = curX; - oldState->curY = curY; - oldState->lineX = lineX; - oldState->lineY = lineY; - - path = NULL; - saved = NULL; - delete this; - - } else { - oldState = this; - } - - return oldState; -} - -GBool GfxState::parseBlendMode(Object *obj, GfxBlendMode *mode) { - Object obj2; - int i, j; - - if (obj->isName()) { - for (i = 0; i < nGfxBlendModeNames; ++i) { - if (!strcmp(obj->getName(), gfxBlendModeNames[i].name)) { - *mode = gfxBlendModeNames[i].mode; - return gTrue; - } - } - return gFalse; - } else if (obj->isArray()) { - for (i = 0; i < obj->arrayGetLength(); ++i) { - obj->arrayGet(i, &obj2); - if (!obj2.isName()) { - obj2.free(); - return gFalse; - } - for (j = 0; j < nGfxBlendModeNames; ++j) { - if (!strcmp(obj2.getName(), gfxBlendModeNames[j].name)) { - obj2.free(); - *mode = gfxBlendModeNames[j].mode; - return gTrue; - } - } - obj2.free(); - } - *mode = gfxBlendNormal; - return gTrue; - } else { - return gFalse; - } -} diff --git a/pdftops/GfxState.h b/pdftops/GfxState.h deleted file mode 100644 index e5045b6c9..000000000 --- a/pdftops/GfxState.h +++ /dev/null @@ -1,1206 +0,0 @@ -//======================================================================== -// -// GfxState.h -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef GFXSTATE_H -#define GFXSTATE_H - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "gtypes.h" -#include "Object.h" -#include "Function.h" - -class Array; -class GfxFont; -class PDFRectangle; -class GfxShading; - -//------------------------------------------------------------------------ -// GfxBlendMode -//------------------------------------------------------------------------ - -enum GfxBlendMode { - gfxBlendNormal, - gfxBlendMultiply, - gfxBlendScreen, - gfxBlendOverlay, - gfxBlendDarken, - gfxBlendLighten, - gfxBlendColorDodge, - gfxBlendColorBurn, - gfxBlendHardLight, - gfxBlendSoftLight, - gfxBlendDifference, - gfxBlendExclusion, - gfxBlendHue, - gfxBlendSaturation, - gfxBlendColor, - gfxBlendLuminosity -}; - -//------------------------------------------------------------------------ -// GfxColorComp -//------------------------------------------------------------------------ - -// 16.16 fixed point color component -typedef int GfxColorComp; - -#define gfxColorComp1 0x10000 - -static inline GfxColorComp dblToCol(double x) { - return (GfxColorComp)(x * gfxColorComp1); -} - -static inline double colToDbl(GfxColorComp x) { - return (double)x / (double)gfxColorComp1; -} - -static inline GfxColorComp byteToCol(Guchar x) { - // (x / 255) << 16 = (0.0000000100000001... * x) << 16 - // = ((x << 8) + (x) + (x >> 8) + ...) << 16 - // = (x << 8) + (x) + (x >> 7) - // [for rounding] - return (GfxColorComp)((x << 8) + x + (x >> 7)); -} - -static inline Guchar colToByte(GfxColorComp x) { - // 255 * x + 0.5 = 256 * x - x + 0x8000 - return (Guchar)(((x << 8) - x + 0x8000) >> 16); -} - -//------------------------------------------------------------------------ -// GfxColor -//------------------------------------------------------------------------ - -#define gfxColorMaxComps funcMaxOutputs - -struct GfxColor { - GfxColorComp c[gfxColorMaxComps]; -}; - -//------------------------------------------------------------------------ -// GfxGray -//------------------------------------------------------------------------ - -typedef GfxColorComp GfxGray; - -//------------------------------------------------------------------------ -// GfxRGB -//------------------------------------------------------------------------ - -struct GfxRGB { - GfxColorComp r, g, b; -}; - -//------------------------------------------------------------------------ -// GfxCMYK -//------------------------------------------------------------------------ - -struct GfxCMYK { - GfxColorComp c, m, y, k; -}; - -//------------------------------------------------------------------------ -// GfxColorSpace -//------------------------------------------------------------------------ - -// NB: The nGfxColorSpaceModes constant and the gfxColorSpaceModeNames -// array defined in GfxState.cc must match this enum. -enum GfxColorSpaceMode { - csDeviceGray, - csCalGray, - csDeviceRGB, - csCalRGB, - csDeviceCMYK, - csLab, - csICCBased, - csIndexed, - csSeparation, - csDeviceN, - csPattern -}; - -class GfxColorSpace { -public: - - GfxColorSpace(); - virtual ~GfxColorSpace(); - virtual GfxColorSpace *copy() = 0; - virtual GfxColorSpaceMode getMode() = 0; - - // Construct a color space. Returns NULL if unsuccessful. - static GfxColorSpace *parse(Object *csObj); - - // Convert to gray, RGB, or CMYK. - virtual void getGray(GfxColor *color, GfxGray *gray) = 0; - virtual void getRGB(GfxColor *color, GfxRGB *rgb) = 0; - virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk) = 0; - - // Return the number of color components. - virtual int getNComps() = 0; - - // Return the default ranges for each component, assuming an image - // with a max pixel value of <maxImgPixel>. - virtual void getDefaultRanges(double *decodeLow, double *decodeRange, - int maxImgPixel); - - // Return the number of color space modes - static int getNumColorSpaceModes(); - - // Return the name of the <idx>th color space mode. - static char *getColorSpaceModeName(int idx); - -private: -}; - -//------------------------------------------------------------------------ -// GfxDeviceGrayColorSpace -//------------------------------------------------------------------------ - -class GfxDeviceGrayColorSpace: public GfxColorSpace { -public: - - GfxDeviceGrayColorSpace(); - virtual ~GfxDeviceGrayColorSpace(); - virtual GfxColorSpace *copy(); - virtual GfxColorSpaceMode getMode() { return csDeviceGray; } - - virtual void getGray(GfxColor *color, GfxGray *gray); - virtual void getRGB(GfxColor *color, GfxRGB *rgb); - virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk); - - virtual int getNComps() { return 1; } - -private: -}; - -//------------------------------------------------------------------------ -// GfxCalGrayColorSpace -//------------------------------------------------------------------------ - -class GfxCalGrayColorSpace: public GfxColorSpace { -public: - - GfxCalGrayColorSpace(); - virtual ~GfxCalGrayColorSpace(); - virtual GfxColorSpace *copy(); - virtual GfxColorSpaceMode getMode() { return csCalGray; } - - // Construct a CalGray color space. Returns NULL if unsuccessful. - static GfxColorSpace *parse(Array *arr); - - virtual void getGray(GfxColor *color, GfxGray *gray); - virtual void getRGB(GfxColor *color, GfxRGB *rgb); - virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk); - - virtual int getNComps() { return 1; } - - // CalGray-specific access. - double getWhiteX() { return whiteX; } - double getWhiteY() { return whiteY; } - double getWhiteZ() { return whiteZ; } - double getBlackX() { return blackX; } - double getBlackY() { return blackY; } - double getBlackZ() { return blackZ; } - double getGamma() { return gamma; } - -private: - - double whiteX, whiteY, whiteZ; // white point - double blackX, blackY, blackZ; // black point - double gamma; // gamma value -}; - -//------------------------------------------------------------------------ -// GfxDeviceRGBColorSpace -//------------------------------------------------------------------------ - -class GfxDeviceRGBColorSpace: public GfxColorSpace { -public: - - GfxDeviceRGBColorSpace(); - virtual ~GfxDeviceRGBColorSpace(); - virtual GfxColorSpace *copy(); - virtual GfxColorSpaceMode getMode() { return csDeviceRGB; } - - virtual void getGray(GfxColor *color, GfxGray *gray); - virtual void getRGB(GfxColor *color, GfxRGB *rgb); - virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk); - - virtual int getNComps() { return 3; } - -private: -}; - -//------------------------------------------------------------------------ -// GfxCalRGBColorSpace -//------------------------------------------------------------------------ - -class GfxCalRGBColorSpace: public GfxColorSpace { -public: - - GfxCalRGBColorSpace(); - virtual ~GfxCalRGBColorSpace(); - virtual GfxColorSpace *copy(); - virtual GfxColorSpaceMode getMode() { return csCalRGB; } - - // Construct a CalRGB color space. Returns NULL if unsuccessful. - static GfxColorSpace *parse(Array *arr); - - virtual void getGray(GfxColor *color, GfxGray *gray); - virtual void getRGB(GfxColor *color, GfxRGB *rgb); - virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk); - - virtual int getNComps() { return 3; } - - // CalRGB-specific access. - double getWhiteX() { return whiteX; } - double getWhiteY() { return whiteY; } - double getWhiteZ() { return whiteZ; } - double getBlackX() { return blackX; } - double getBlackY() { return blackY; } - double getBlackZ() { return blackZ; } - double getGammaR() { return gammaR; } - double getGammaG() { return gammaG; } - double getGammaB() { return gammaB; } - double *getMatrix() { return mat; } - -private: - - double whiteX, whiteY, whiteZ; // white point - double blackX, blackY, blackZ; // black point - double gammaR, gammaG, gammaB; // gamma values - double mat[9]; // ABC -> XYZ transform matrix -}; - -//------------------------------------------------------------------------ -// GfxDeviceCMYKColorSpace -//------------------------------------------------------------------------ - -class GfxDeviceCMYKColorSpace: public GfxColorSpace { -public: - - GfxDeviceCMYKColorSpace(); - virtual ~GfxDeviceCMYKColorSpace(); - virtual GfxColorSpace *copy(); - virtual GfxColorSpaceMode getMode() { return csDeviceCMYK; } - - virtual void getGray(GfxColor *color, GfxGray *gray); - virtual void getRGB(GfxColor *color, GfxRGB *rgb); - virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk); - - virtual int getNComps() { return 4; } - -private: -}; - -//------------------------------------------------------------------------ -// GfxLabColorSpace -//------------------------------------------------------------------------ - -class GfxLabColorSpace: public GfxColorSpace { -public: - - GfxLabColorSpace(); - virtual ~GfxLabColorSpace(); - virtual GfxColorSpace *copy(); - virtual GfxColorSpaceMode getMode() { return csLab; } - - // Construct a Lab color space. Returns NULL if unsuccessful. - static GfxColorSpace *parse(Array *arr); - - virtual void getGray(GfxColor *color, GfxGray *gray); - virtual void getRGB(GfxColor *color, GfxRGB *rgb); - virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk); - - virtual int getNComps() { return 3; } - - virtual void getDefaultRanges(double *decodeLow, double *decodeRange, - int maxImgPixel); - - // Lab-specific access. - double getWhiteX() { return whiteX; } - double getWhiteY() { return whiteY; } - double getWhiteZ() { return whiteZ; } - double getBlackX() { return blackX; } - double getBlackY() { return blackY; } - double getBlackZ() { return blackZ; } - double getAMin() { return aMin; } - double getAMax() { return aMax; } - double getBMin() { return bMin; } - double getBMax() { return bMax; } - -private: - - double whiteX, whiteY, whiteZ; // white point - double blackX, blackY, blackZ; // black point - double aMin, aMax, bMin, bMax; // range for the a and b components - double kr, kg, kb; // gamut mapping mulitpliers -}; - -//------------------------------------------------------------------------ -// GfxICCBasedColorSpace -//------------------------------------------------------------------------ - -class GfxICCBasedColorSpace: public GfxColorSpace { -public: - - GfxICCBasedColorSpace(int nCompsA, GfxColorSpace *altA, - Ref *iccProfileStreamA); - virtual ~GfxICCBasedColorSpace(); - virtual GfxColorSpace *copy(); - virtual GfxColorSpaceMode getMode() { return csICCBased; } - - // Construct an ICCBased color space. Returns NULL if unsuccessful. - static GfxColorSpace *parse(Array *arr); - - virtual void getGray(GfxColor *color, GfxGray *gray); - virtual void getRGB(GfxColor *color, GfxRGB *rgb); - virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk); - - virtual int getNComps() { return nComps; } - - virtual void getDefaultRanges(double *decodeLow, double *decodeRange, - int maxImgPixel); - - // ICCBased-specific access. - GfxColorSpace *getAlt() { return alt; } - -private: - - int nComps; // number of color components (1, 3, or 4) - GfxColorSpace *alt; // alternate color space - double rangeMin[4]; // min values for each component - double rangeMax[4]; // max values for each component - Ref iccProfileStream; // the ICC profile -}; - -//------------------------------------------------------------------------ -// GfxIndexedColorSpace -//------------------------------------------------------------------------ - -class GfxIndexedColorSpace: public GfxColorSpace { -public: - - GfxIndexedColorSpace(GfxColorSpace *baseA, int indexHighA); - virtual ~GfxIndexedColorSpace(); - virtual GfxColorSpace *copy(); - virtual GfxColorSpaceMode getMode() { return csIndexed; } - - // Construct a Lab color space. Returns NULL if unsuccessful. - static GfxColorSpace *parse(Array *arr); - - virtual void getGray(GfxColor *color, GfxGray *gray); - virtual void getRGB(GfxColor *color, GfxRGB *rgb); - virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk); - - virtual int getNComps() { return 1; } - - virtual void getDefaultRanges(double *decodeLow, double *decodeRange, - int maxImgPixel); - - // Indexed-specific access. - GfxColorSpace *getBase() { return base; } - int getIndexHigh() { return indexHigh; } - Guchar *getLookup() { return lookup; } - GfxColor *mapColorToBase(GfxColor *color, GfxColor *baseColor); - -private: - - GfxColorSpace *base; // base color space - int indexHigh; // max pixel value - Guchar *lookup; // lookup table -}; - -//------------------------------------------------------------------------ -// GfxSeparationColorSpace -//------------------------------------------------------------------------ - -class GfxSeparationColorSpace: public GfxColorSpace { -public: - - GfxSeparationColorSpace(GString *nameA, GfxColorSpace *altA, - Function *funcA); - virtual ~GfxSeparationColorSpace(); - virtual GfxColorSpace *copy(); - virtual GfxColorSpaceMode getMode() { return csSeparation; } - - // Construct a Separation color space. Returns NULL if unsuccessful. - static GfxColorSpace *parse(Array *arr); - - virtual void getGray(GfxColor *color, GfxGray *gray); - virtual void getRGB(GfxColor *color, GfxRGB *rgb); - virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk); - - virtual int getNComps() { return 1; } - - // Separation-specific access. - GString *getName() { return name; } - GfxColorSpace *getAlt() { return alt; } - Function *getFunc() { return func; } - -private: - - GString *name; // colorant name - GfxColorSpace *alt; // alternate color space - Function *func; // tint transform (into alternate color space) -}; - -//------------------------------------------------------------------------ -// GfxDeviceNColorSpace -//------------------------------------------------------------------------ - -class GfxDeviceNColorSpace: public GfxColorSpace { -public: - - GfxDeviceNColorSpace(int nCompsA, GfxColorSpace *alt, Function *func); - virtual ~GfxDeviceNColorSpace(); - virtual GfxColorSpace *copy(); - virtual GfxColorSpaceMode getMode() { return csDeviceN; } - - // Construct a DeviceN color space. Returns NULL if unsuccessful. - static GfxColorSpace *parse(Array *arr); - - virtual void getGray(GfxColor *color, GfxGray *gray); - virtual void getRGB(GfxColor *color, GfxRGB *rgb); - virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk); - - virtual int getNComps() { return nComps; } - - // DeviceN-specific access. - GString *getColorantName(int i) { return names[i]; } - GfxColorSpace *getAlt() { return alt; } - Function *getTintTransformFunc() { return func; } - -private: - - int nComps; // number of components - GString // colorant names - *names[gfxColorMaxComps]; - GfxColorSpace *alt; // alternate color space - Function *func; // tint transform (into alternate color space) -}; - -//------------------------------------------------------------------------ -// GfxPatternColorSpace -//------------------------------------------------------------------------ - -class GfxPatternColorSpace: public GfxColorSpace { -public: - - GfxPatternColorSpace(GfxColorSpace *underA); - virtual ~GfxPatternColorSpace(); - virtual GfxColorSpace *copy(); - virtual GfxColorSpaceMode getMode() { return csPattern; } - - // Construct a Pattern color space. Returns NULL if unsuccessful. - static GfxColorSpace *parse(Array *arr); - - virtual void getGray(GfxColor *color, GfxGray *gray); - virtual void getRGB(GfxColor *color, GfxRGB *rgb); - virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk); - - virtual int getNComps() { return 0; } - - // Pattern-specific access. - GfxColorSpace *getUnder() { return under; } - -private: - - GfxColorSpace *under; // underlying color space (for uncolored - // patterns) -}; - -//------------------------------------------------------------------------ -// GfxPattern -//------------------------------------------------------------------------ - -class GfxPattern { -public: - - GfxPattern(int typeA); - virtual ~GfxPattern(); - - static GfxPattern *parse(Object *obj); - - virtual GfxPattern *copy() = 0; - - int getType() { return type; } - -private: - - int type; -}; - -//------------------------------------------------------------------------ -// GfxTilingPattern -//------------------------------------------------------------------------ - -class GfxTilingPattern: public GfxPattern { -public: - - static GfxTilingPattern *parse(Object *patObj); - virtual ~GfxTilingPattern(); - - virtual GfxPattern *copy(); - - int getPaintType() { return paintType; } - int getTilingType() { return tilingType; } - double *getBBox() { return bbox; } - double getXStep() { return xStep; } - double getYStep() { return yStep; } - Dict *getResDict() - { return resDict.isDict() ? resDict.getDict() : (Dict *)NULL; } - double *getMatrix() { return matrix; } - Object *getContentStream() { return &contentStream; } - -private: - - GfxTilingPattern(int paintTypeA, int tilingTypeA, - double *bboxA, double xStepA, double yStepA, - Object *resDictA, double *matrixA, - Object *contentStreamA); - - int paintType; - int tilingType; - double bbox[4]; - double xStep, yStep; - Object resDict; - double matrix[6]; - Object contentStream; -}; - -//------------------------------------------------------------------------ -// GfxShadingPattern -//------------------------------------------------------------------------ - -class GfxShadingPattern: public GfxPattern { -public: - - static GfxShadingPattern *parse(Object *patObj); - virtual ~GfxShadingPattern(); - - virtual GfxPattern *copy(); - - GfxShading *getShading() { return shading; } - double *getMatrix() { return matrix; } - -private: - - GfxShadingPattern(GfxShading *shadingA, double *matrixA); - - GfxShading *shading; - double matrix[6]; -}; - -//------------------------------------------------------------------------ -// GfxShading -//------------------------------------------------------------------------ - -class GfxShading { -public: - - GfxShading(int typeA); - GfxShading(GfxShading *shading); - virtual ~GfxShading(); - - static GfxShading *parse(Object *obj); - - virtual GfxShading *copy() = 0; - - int getType() { return type; } - GfxColorSpace *getColorSpace() { return colorSpace; } - GfxColor *getBackground() { return &background; } - GBool getHasBackground() { return hasBackground; } - void getBBox(double *xMinA, double *yMinA, double *xMaxA, double *yMaxA) - { *xMinA = xMin; *yMinA = yMin; *xMaxA = xMax; *yMaxA = yMax; } - GBool getHasBBox() { return hasBBox; } - -protected: - - GBool init(Dict *dict); - - int type; - GfxColorSpace *colorSpace; - GfxColor background; - GBool hasBackground; - double xMin, yMin, xMax, yMax; - GBool hasBBox; -}; - -//------------------------------------------------------------------------ -// GfxFunctionShading -//------------------------------------------------------------------------ - -class GfxFunctionShading: public GfxShading { -public: - - GfxFunctionShading(double x0A, double y0A, - double x1A, double y1A, - double *matrixA, - Function **funcsA, int nFuncsA); - GfxFunctionShading(GfxFunctionShading *shading); - virtual ~GfxFunctionShading(); - - static GfxFunctionShading *parse(Dict *dict); - - virtual GfxShading *copy(); - - void getDomain(double *x0A, double *y0A, double *x1A, double *y1A) - { *x0A = x0; *y0A = y0; *x1A = x1; *y1A = y1; } - double *getMatrix() { return matrix; } - int getNFuncs() { return nFuncs; } - Function *getFunc(int i) { return funcs[i]; } - void getColor(double x, double y, GfxColor *color); - -private: - - double x0, y0, x1, y1; - double matrix[6]; - Function *funcs[gfxColorMaxComps]; - int nFuncs; -}; - -//------------------------------------------------------------------------ -// GfxAxialShading -//------------------------------------------------------------------------ - -class GfxAxialShading: public GfxShading { -public: - - GfxAxialShading(double x0A, double y0A, - double x1A, double y1A, - double t0A, double t1A, - Function **funcsA, int nFuncsA, - GBool extend0A, GBool extend1A); - GfxAxialShading(GfxAxialShading *shading); - virtual ~GfxAxialShading(); - - static GfxAxialShading *parse(Dict *dict); - - virtual GfxShading *copy(); - - void getCoords(double *x0A, double *y0A, double *x1A, double *y1A) - { *x0A = x0; *y0A = y0; *x1A = x1; *y1A = y1; } - double getDomain0() { return t0; } - double getDomain1() { return t1; } - GBool getExtend0() { return extend0; } - GBool getExtend1() { return extend1; } - int getNFuncs() { return nFuncs; } - Function *getFunc(int i) { return funcs[i]; } - void getColor(double t, GfxColor *color); - -private: - - double x0, y0, x1, y1; - double t0, t1; - Function *funcs[gfxColorMaxComps]; - int nFuncs; - GBool extend0, extend1; -}; - -//------------------------------------------------------------------------ -// GfxRadialShading -//------------------------------------------------------------------------ - -class GfxRadialShading: public GfxShading { -public: - - GfxRadialShading(double x0A, double y0A, double r0A, - double x1A, double y1A, double r1A, - double t0A, double t1A, - Function **funcsA, int nFuncsA, - GBool extend0A, GBool extend1A); - GfxRadialShading(GfxRadialShading *shading); - virtual ~GfxRadialShading(); - - static GfxRadialShading *parse(Dict *dict); - - virtual GfxShading *copy(); - - void getCoords(double *x0A, double *y0A, double *r0A, - double *x1A, double *y1A, double *r1A) - { *x0A = x0; *y0A = y0; *r0A = r0; *x1A = x1; *y1A = y1; *r1A = r1; } - double getDomain0() { return t0; } - double getDomain1() { return t1; } - GBool getExtend0() { return extend0; } - GBool getExtend1() { return extend1; } - int getNFuncs() { return nFuncs; } - Function *getFunc(int i) { return funcs[i]; } - void getColor(double t, GfxColor *color); - -private: - - double x0, y0, r0, x1, y1, r1; - double t0, t1; - Function *funcs[gfxColorMaxComps]; - int nFuncs; - GBool extend0, extend1; -}; - -//------------------------------------------------------------------------ -// GfxGouraudTriangleShading -//------------------------------------------------------------------------ - -struct GfxGouraudVertex { - double x, y; - GfxColor color; -}; - -class GfxGouraudTriangleShading: public GfxShading { -public: - - GfxGouraudTriangleShading(int typeA, - GfxGouraudVertex *verticesA, int nVerticesA, - int (*trianglesA)[3], int nTrianglesA, - Function **funcsA, int nFuncsA); - GfxGouraudTriangleShading(GfxGouraudTriangleShading *shading); - virtual ~GfxGouraudTriangleShading(); - - static GfxGouraudTriangleShading *parse(int typeA, Dict *dict, Stream *str); - - virtual GfxShading *copy(); - - int getNTriangles() { return nTriangles; } - void getTriangle(int i, double *x0, double *y0, GfxColor *color0, - double *x1, double *y1, GfxColor *color1, - double *x2, double *y2, GfxColor *color2); - -private: - - GfxGouraudVertex *vertices; - int nVertices; - int (*triangles)[3]; - int nTriangles; - Function *funcs[gfxColorMaxComps]; - int nFuncs; -}; - -//------------------------------------------------------------------------ -// GfxPatchMeshShading -//------------------------------------------------------------------------ - -struct GfxPatch { - double x[4][4]; - double y[4][4]; - GfxColor color[2][2]; -}; - -class GfxPatchMeshShading: public GfxShading { -public: - - GfxPatchMeshShading(int typeA, GfxPatch *patchesA, int nPatchesA, - Function **funcsA, int nFuncsA); - GfxPatchMeshShading(GfxPatchMeshShading *shading); - virtual ~GfxPatchMeshShading(); - - static GfxPatchMeshShading *parse(int typeA, Dict *dict, Stream *str); - - virtual GfxShading *copy(); - - int getNPatches() { return nPatches; } - GfxPatch *getPatch(int i) { return &patches[i]; } - -private: - - GfxPatch *patches; - int nPatches; - Function *funcs[gfxColorMaxComps]; - int nFuncs; -}; - -//------------------------------------------------------------------------ -// GfxImageColorMap -//------------------------------------------------------------------------ - -class GfxImageColorMap { -public: - - // Constructor. - GfxImageColorMap(int bitsA, Object *decode, GfxColorSpace *colorSpaceA); - - // Destructor. - ~GfxImageColorMap(); - - // Return a copy of this color map. - GfxImageColorMap *copy() { return new GfxImageColorMap(this); } - - // Is color map valid? - GBool isOk() { return ok; } - - // Get the color space. - GfxColorSpace *getColorSpace() { return colorSpace; } - - // Get stream decoding info. - int getNumPixelComps() { return nComps; } - int getBits() { return bits; } - - // Get decode table. - double getDecodeLow(int i) { return decodeLow[i]; } - double getDecodeHigh(int i) { return decodeLow[i] + decodeRange[i]; } - - // Convert an image pixel to a color. - void getGray(Guchar *x, GfxGray *gray); - void getRGB(Guchar *x, GfxRGB *rgb); - void getCMYK(Guchar *x, GfxCMYK *cmyk); - void getColor(Guchar *x, GfxColor *color); - -private: - - GfxImageColorMap(GfxImageColorMap *colorMap); - - GfxColorSpace *colorSpace; // the image color space - int bits; // bits per component - int nComps; // number of components in a pixel - GfxColorSpace *colorSpace2; // secondary color space - int nComps2; // number of components in colorSpace2 - GfxColorComp * // lookup table - lookup[gfxColorMaxComps]; - double // minimum values for each component - decodeLow[gfxColorMaxComps]; - double // max - min value for each component - decodeRange[gfxColorMaxComps]; - 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; } - - // Add (<dx>, <dy>) to each point in the subpath. - void offset(double dx, double dy); - -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(); - - // Append <path> to <this>. - void append(GfxPath *path); - - // Add (<dx>, <dy>) to each point in the path. - void offset(double dx, double dy); - -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 <hDPI> - // x <vDPI>, page box <pageBox>, page rotation <rotateA>, and - // coordinate system specified by <upsideDown>. - GfxState(double hDPI, double vDPI, PDFRectangle *pageBox, - int rotateA, 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; } - int getRotate() { return rotate; } - GfxColor *getFillColor() { return &fillColor; } - GfxColor *getStrokeColor() { return &strokeColor; } - void getFillGray(GfxGray *gray) - { fillColorSpace->getGray(&fillColor, gray); } - void getStrokeGray(GfxGray *gray) - { strokeColorSpace->getGray(&strokeColor, gray); } - void getFillRGB(GfxRGB *rgb) - { fillColorSpace->getRGB(&fillColor, rgb); } - void getStrokeRGB(GfxRGB *rgb) - { strokeColorSpace->getRGB(&strokeColor, rgb); } - void getFillCMYK(GfxCMYK *cmyk) - { fillColorSpace->getCMYK(&fillColor, cmyk); } - void getStrokeCMYK(GfxCMYK *cmyk) - { strokeColorSpace->getCMYK(&strokeColor, cmyk); } - GfxColorSpace *getFillColorSpace() { return fillColorSpace; } - GfxColorSpace *getStrokeColorSpace() { return strokeColorSpace; } - GfxPattern *getFillPattern() { return fillPattern; } - GfxPattern *getStrokePattern() { return strokePattern; } - GfxBlendMode getBlendMode() { return blendMode; } - double getFillOpacity() { return fillOpacity; } - double getStrokeOpacity() { return strokeOpacity; } - GBool getFillOverprint() { return fillOverprint; } - GBool getStrokeOverprint() { return strokeOverprint; } - 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; } - void setPath(GfxPath *pathA); - double getCurX() { return curX; } - double getCurY() { return curY; } - void getClipBBox(double *xMin, double *yMin, double *xMax, double *yMax) - { *xMin = clipXMin; *yMin = clipYMin; *xMax = clipXMax; *yMax = clipYMax; } - void getUserClipBBox(double *xMin, double *yMin, double *xMax, double *yMax); - 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 setFillColorSpace(GfxColorSpace *colorSpace); - void setStrokeColorSpace(GfxColorSpace *colorSpace); - void setFillColor(GfxColor *color) { fillColor = *color; } - void setStrokeColor(GfxColor *color) { strokeColor = *color; } - void setFillPattern(GfxPattern *pattern); - void setStrokePattern(GfxPattern *pattern); - void setBlendMode(GfxBlendMode mode) { blendMode = mode; } - void setFillOpacity(double opac) { fillOpacity = opac; } - void setStrokeOpacity(double opac) { strokeOpacity = opac; } - void setFillOverprint(GBool op) { fillOverprint = op; } - void setStrokeOverprint(GBool op) { strokeOverprint = op; } - 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 limit) { miterLimit = limit; } - void setFont(GfxFont *fontA, double fontSizeA) - { font = fontA; fontSize = fontSizeA; } - 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 leadingA) - { leading = leadingA; } - void setRise(double riseA) - { rise = riseA; } - void setRender(int renderA) - { render = renderA; } - - // 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(); - - // Update clip region. - void clip(); - - // Text position. - void textSetPos(double tx, double ty) { lineX = tx; lineY = ty; } - void textMoveTo(double tx, double ty) - { lineX = tx; lineY = ty; textTransform(tx, ty, &curX, &curY); } - void textShift(double tx, double ty); - void shift(double dx, double dy); - - // Push/pop GfxState on/off stack. - GfxState *save(); - GfxState *restore(); - GBool hasSaves() { return saved != NULL; } - - // Misc - GBool parseBlendMode(Object *obj, GfxBlendMode *mode); - -private: - - double ctm[6]; // coord transform matrix - double px1, py1, px2, py2; // page corners (user coords) - double pageWidth, pageHeight; // page size (pixels) - int rotate; // page rotation angle - - GfxColorSpace *fillColorSpace; // fill color space - GfxColorSpace *strokeColorSpace; // stroke color space - GfxColor fillColor; // fill color - GfxColor strokeColor; // stroke color - GfxPattern *fillPattern; // fill pattern - GfxPattern *strokePattern; // stroke pattern - GfxBlendMode blendMode; // transparency blend mode - double fillOpacity; // fill opacity - double strokeOpacity; // stroke opacity - GBool fillOverprint; // fill overprint - GBool strokeOverprint; // stroke overprint - - 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) - - double clipXMin, clipYMin, // bounding box for clip region - clipXMax, clipYMax; - - GfxState *saved; // next GfxState on stack - - GfxState(GfxState *state); -}; - -#endif diff --git a/pdftops/GlobalParams.cxx b/pdftops/GlobalParams.cxx deleted file mode 100644 index 013e3d0b2..000000000 --- a/pdftops/GlobalParams.cxx +++ /dev/null @@ -1,1995 +0,0 @@ -//======================================================================== -// -// GlobalParams.cc -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include <string.h> -#include <stdio.h> -#include <ctype.h> -#ifdef ENABLE_PLUGINS -# ifndef WIN32 -# include <dlfcn.h> -# endif -#endif -#ifdef WIN32 -# include <shlobj.h> -#endif -#if HAVE_PAPER_H -#include <paper.h> -#endif -#include "gmem.h" -#include "GString.h" -#include "GList.h" -#include "GHash.h" -#include "gfile.h" -#include "Error.h" -#include "NameToCharCode.h" -#include "CharCodeToUnicode.h" -#include "UnicodeMap.h" -#include "CMap.h" -#include "BuiltinFontTables.h" -#include "FontEncodingTables.h" -#ifdef ENABLE_PLUGINS -# include "XpdfPluginAPI.h" -#endif -#include "GlobalParams.h" - -#if MULTITHREADED -# define lockGlobalParams gLockMutex(&mutex) -# define lockUnicodeMapCache gLockMutex(&unicodeMapCacheMutex) -# define lockCMapCache gLockMutex(&cMapCacheMutex) -# define unlockGlobalParams gUnlockMutex(&mutex) -# define unlockUnicodeMapCache gUnlockMutex(&unicodeMapCacheMutex) -# define unlockCMapCache gUnlockMutex(&cMapCacheMutex) -#else -# define lockGlobalParams -# define lockUnicodeMapCache -# define lockCMapCache -# define unlockGlobalParams -# define unlockUnicodeMapCache -# define unlockCMapCache -#endif - -#include "NameToUnicodeTable.h" -#include "UnicodeMapTables.h" -#include "UTF8.h" - -#ifdef ENABLE_PLUGINS -# ifdef WIN32 -extern XpdfPluginVecTable xpdfPluginVecTable; -# endif -#endif - -//------------------------------------------------------------------------ - -#define cidToUnicodeCacheSize 4 -#define unicodeToUnicodeCacheSize 4 - -//------------------------------------------------------------------------ - -static struct { - char *name; - char *t1FileName; - char *ttFileName; -} displayFontTab[] = { - {"Courier", "n022003l.pfb", "cour.ttf"}, - {"Courier-Bold", "n022004l.pfb", "courbd.ttf"}, - {"Courier-BoldOblique", "n022024l.pfb", "courbi.ttf"}, - {"Courier-Oblique", "n022023l.pfb", "couri.ttf"}, - {"Helvetica", "n019003l.pfb", "arial.ttf"}, - {"Helvetica-Bold", "n019004l.pfb", "arialbd.ttf"}, - {"Helvetica-BoldOblique", "n019024l.pfb", "arialbi.ttf"}, - {"Helvetica-Oblique", "n019023l.pfb", "ariali.ttf"}, - {"Symbol", "s050000l.pfb", NULL}, - {"Times-Bold", "n021004l.pfb", "timesbd.ttf"}, - {"Times-BoldItalic", "n021024l.pfb", "timesbi.ttf"}, - {"Times-Italic", "n021023l.pfb", "timesi.ttf"}, - {"Times-Roman", "n021003l.pfb", "times.ttf"}, - {"ZapfDingbats", "d050000l.pfb", NULL}, - {NULL} -}; - -#ifdef WIN32 -static char *displayFontDirs[] = { - "c:/windows/fonts", - "c:/winnt/fonts", - NULL -}; -#else -static char *displayFontDirs[] = { - "/usr/share/ghostscript/fonts", - "/usr/local/share/ghostscript/fonts", - "/usr/share/fonts/default/Type1", - "/usr/share/fonts/default/ghostscript", - "/usr/share/fonts/type1/gsfonts", - NULL -}; -#endif - -//------------------------------------------------------------------------ - -GlobalParams *globalParams = NULL; - -//------------------------------------------------------------------------ -// DisplayFontParam -//------------------------------------------------------------------------ - -DisplayFontParam::DisplayFontParam(GString *nameA, - DisplayFontParamKind kindA) { - name = nameA; - kind = kindA; - switch (kind) { - case displayFontT1: - t1.fileName = NULL; - break; - case displayFontTT: - tt.fileName = NULL; - break; - } -} - -DisplayFontParam::~DisplayFontParam() { - delete name; - switch (kind) { - case displayFontT1: - if (t1.fileName) { - delete t1.fileName; - } - break; - case displayFontTT: - if (tt.fileName) { - delete tt.fileName; - } - break; - } -} - -//------------------------------------------------------------------------ -// PSFontParam -//------------------------------------------------------------------------ - -PSFontParam::PSFontParam(GString *pdfFontNameA, int wModeA, - GString *psFontNameA, GString *encodingA) { - pdfFontName = pdfFontNameA; - wMode = wModeA; - psFontName = psFontNameA; - encoding = encodingA; -} - -PSFontParam::~PSFontParam() { - delete pdfFontName; - delete psFontName; - if (encoding) { - delete encoding; - } -} - -#ifdef ENABLE_PLUGINS -//------------------------------------------------------------------------ -// Plugin -//------------------------------------------------------------------------ - -class Plugin { -public: - - static Plugin *load(char *type, char *name); - ~Plugin(); - -private: - -#ifdef WIN32 - Plugin(HMODULE libA); - HMODULE lib; -#else - Plugin(void *dlA); - void *dl; -#endif -}; - -Plugin *Plugin::load(char *type, char *name) { - GString *path; - Plugin *plugin; - XpdfPluginVecTable *vt; - XpdfBool (*xpdfInitPlugin)(void); -#ifdef WIN32 - HMODULE libA; -#else - void *dlA; -#endif - - path = globalParams->getBaseDir(); - appendToPath(path, "plugins"); - appendToPath(path, type); - appendToPath(path, name); - -#ifdef WIN32 - path->append(".dll"); - if (!(libA = LoadLibrary(path->getCString()))) { - error(-1, "Failed to load plugin '%s'", - path->getCString()); - goto err1; - } - if (!(vt = (XpdfPluginVecTable *) - GetProcAddress(libA, "xpdfPluginVecTable"))) { - error(-1, "Failed to find xpdfPluginVecTable in plugin '%s'", - path->getCString()); - goto err2; - } -#else - //~ need to deal with other extensions here - path->append(".so"); - if (!(dlA = dlopen(path->getCString(), RTLD_NOW))) { - error(-1, "Failed to load plugin '%s': %s", - path->getCString(), dlerror()); - goto err1; - } - if (!(vt = (XpdfPluginVecTable *)dlsym(dlA, "xpdfPluginVecTable"))) { - error(-1, "Failed to find xpdfPluginVecTable in plugin '%s'", - path->getCString()); - goto err2; - } -#endif - - if (vt->version != xpdfPluginVecTable.version) { - error(-1, "Plugin '%s' is wrong version", path->getCString()); - goto err2; - } - memcpy(vt, &xpdfPluginVecTable, sizeof(xpdfPluginVecTable)); - -#ifdef WIN32 - if (!(xpdfInitPlugin = (XpdfBool (*)(void)) - GetProcAddress(libA, "xpdfInitPlugin"))) { - error(-1, "Failed to find xpdfInitPlugin in plugin '%s'", - path->getCString()); - goto err2; - } -#else - if (!(xpdfInitPlugin = (XpdfBool (*)(void))dlsym(dlA, "xpdfInitPlugin"))) { - error(-1, "Failed to find xpdfInitPlugin in plugin '%s'", - path->getCString()); - goto err2; - } -#endif - - if (!(*xpdfInitPlugin)()) { - error(-1, "Initialization of plugin '%s' failed", - path->getCString()); - goto err2; - } - -#ifdef WIN32 - plugin = new Plugin(libA); -#else - plugin = new Plugin(dlA); -#endif - - delete path; - return plugin; - - err2: -#ifdef WIN32 - FreeLibrary(libA); -#else - dlclose(dlA); -#endif - err1: - delete path; - return NULL; -} - -#ifdef WIN32 -Plugin::Plugin(HMODULE libA) { - lib = libA; -} -#else -Plugin::Plugin(void *dlA) { - dl = dlA; -} -#endif - -Plugin::~Plugin() { - void (*xpdfFreePlugin)(void); - -#ifdef WIN32 - if ((xpdfFreePlugin = (void (*)(void)) - GetProcAddress(lib, "xpdfFreePlugin"))) { - (*xpdfFreePlugin)(); - } - FreeLibrary(lib); -#else - if ((xpdfFreePlugin = (void (*)(void))dlsym(dl, "xpdfFreePlugin"))) { - (*xpdfFreePlugin)(); - } - dlclose(dl); -#endif -} - -#endif // ENABLE_PLUGINS - -//------------------------------------------------------------------------ -// parsing -//------------------------------------------------------------------------ - -GlobalParams::GlobalParams(char *cfgFileName) { - UnicodeMap *map; - GString *fileName; - FILE *f; - int i; - -#if MULTITHREADED - gInitMutex(&mutex); - gInitMutex(&unicodeMapCacheMutex); - gInitMutex(&cMapCacheMutex); -#endif - - initBuiltinFontTables(); - - // scan the encoding in reverse because we want the lowest-numbered - // index for each char name ('space' is encoded twice) - macRomanReverseMap = new NameToCharCode(); - for (i = 255; i >= 0; --i) { - if (macRomanEncoding[i]) { - macRomanReverseMap->add(macRomanEncoding[i], (CharCode)i); - } - } - -#ifdef WIN32 - // baseDir will be set by a call to setBaseDir - baseDir = new GString(); -#else - baseDir = appendToPath(getHomeDir(), ".xpdf"); -#endif - nameToUnicode = new NameToCharCode(); - cidToUnicodes = new GHash(gTrue); - unicodeToUnicodes = new GHash(gTrue); - residentUnicodeMaps = new GHash(); - unicodeMaps = new GHash(gTrue); - cMapDirs = new GHash(gTrue); - toUnicodeDirs = new GList(); - displayFonts = new GHash(); - displayCIDFonts = new GHash(); - displayNamedCIDFonts = new GHash(); -#if HAVE_PAPER_H - char *paperName; - const struct paper *paperType; - paperinit(); - if ((paperName = systempapername())) { - paperType = paperinfo(paperName); - psPaperWidth = (int)paperpswidth(paperType); - psPaperHeight = (int)paperpsheight(paperType); - } else { - error(-1, "No paper information available - using defaults"); - psPaperWidth = defPaperWidth; - psPaperHeight = defPaperHeight; - } - paperdone(); -#else - psPaperWidth = defPaperWidth; - psPaperHeight = defPaperHeight; -#endif - psImageableLLX = psImageableLLY = 0; - psImageableURX = psPaperWidth; - psImageableURY = psPaperHeight; - psCrop = gTrue; - psExpandSmaller = gFalse; - psShrinkLarger = gTrue; - psCenter = gTrue; - psDuplex = gFalse; - psLevel = psLevel2; - psFile = NULL; - psFonts = new GHash(); - psNamedFonts16 = new GList(); - psFonts16 = new GList(); - psEmbedType1 = gTrue; - psEmbedTrueType = gTrue; - psEmbedCIDPostScript = gTrue; - psEmbedCIDTrueType = gTrue; - psOPI = gFalse; - psASCIIHex = gFalse; - textEncoding = new GString("Latin1"); -#if defined(WIN32) - textEOL = eolDOS; -#elif defined(MACOS) - textEOL = eolMac; -#else - textEOL = eolUnix; -#endif - textPageBreaks = gTrue; - textKeepTinyChars = gFalse; - fontDirs = new GList(); - initialZoom = new GString("125"); - continuousView = gFalse; - enableT1lib = gTrue; - enableFreeType = gTrue; - antialias = gTrue; - urlCommand = NULL; - movieCommand = NULL; - mapNumericCharNames = gTrue; - printCommands = gFalse; - errQuiet = gFalse; - - cidToUnicodeCache = new CharCodeToUnicodeCache(cidToUnicodeCacheSize); - unicodeToUnicodeCache = - new CharCodeToUnicodeCache(unicodeToUnicodeCacheSize); - unicodeMapCache = new UnicodeMapCache(); - cMapCache = new CMapCache(); - -#ifdef ENABLE_PLUGINS - plugins = new GList(); - securityHandlers = new GList(); -#endif - - // set up the initial nameToUnicode table - for (i = 0; nameToUnicodeTab[i].name; ++i) { - nameToUnicode->add(nameToUnicodeTab[i].name, nameToUnicodeTab[i].u); - } - - // set up the residentUnicodeMaps table - map = new UnicodeMap("Latin1", gFalse, - latin1UnicodeMapRanges, latin1UnicodeMapLen); - residentUnicodeMaps->add(map->getEncodingName(), map); - map = new UnicodeMap("ASCII7", gFalse, - ascii7UnicodeMapRanges, ascii7UnicodeMapLen); - residentUnicodeMaps->add(map->getEncodingName(), map); - map = new UnicodeMap("Symbol", gFalse, - symbolUnicodeMapRanges, symbolUnicodeMapLen); - residentUnicodeMaps->add(map->getEncodingName(), map); - map = new UnicodeMap("ZapfDingbats", gFalse, zapfDingbatsUnicodeMapRanges, - zapfDingbatsUnicodeMapLen); - residentUnicodeMaps->add(map->getEncodingName(), map); - map = new UnicodeMap("UTF-8", gTrue, &mapUTF8); - residentUnicodeMaps->add(map->getEncodingName(), map); - map = new UnicodeMap("UCS-2", gTrue, &mapUCS2); - residentUnicodeMaps->add(map->getEncodingName(), map); - - // look for a user config file, then a system-wide config file - f = NULL; - fileName = NULL; - if (cfgFileName && cfgFileName[0]) { - fileName = new GString(cfgFileName); - if (!(f = fopen(fileName->getCString(), "r"))) { - delete fileName; - } - } - if (!f) { - fileName = appendToPath(getHomeDir(), xpdfUserConfigFile); - if (!(f = fopen(fileName->getCString(), "r"))) { - delete fileName; - } - } - if (!f) { -#if defined(WIN32) && !defined(__CYGWIN32__) - char buf[512]; - i = GetModuleFileName(NULL, buf, sizeof(buf)); - if (i <= 0 || i >= sizeof(buf)) { - // error or path too long for buffer - just use the current dir - buf[0] = '\0'; - } - fileName = grabPath(buf); - appendToPath(fileName, xpdfSysConfigFile); -#else - fileName = new GString(xpdfSysConfigFile); -#endif - if (!(f = fopen(fileName->getCString(), "r"))) { - delete fileName; - } - } - if (f) { - parseFile(fileName, f); - delete fileName; - fclose(f); - } -} - -void GlobalParams::parseFile(GString *fileName, FILE *f) { - int line; - GList *tokens; - GString *cmd, *incFile; - char *p1, *p2; - char buf[512]; - FILE *f2; - - line = 1; - while (getLine(buf, sizeof(buf) - 1, f)) { - - // break the line into tokens - tokens = new GList(); - p1 = buf; - while (*p1) { - for (; *p1 && isspace(*p1); ++p1) ; - if (!*p1) { - break; - } - if (*p1 == '"' || *p1 == '\'') { - for (p2 = p1 + 1; *p2 && *p2 != *p1; ++p2) ; - ++p1; - } else { - for (p2 = p1 + 1; *p2 && !isspace(*p2); ++p2) ; - } - tokens->append(new GString(p1, p2 - p1)); - p1 = *p2 ? p2 + 1 : p2; - } - - if (tokens->getLength() > 0 && - ((GString *)tokens->get(0))->getChar(0) != '#') { - cmd = (GString *)tokens->get(0); - if (!cmd->cmp("include")) { - if (tokens->getLength() == 2) { - incFile = (GString *)tokens->get(1); - if ((f2 = fopen(incFile->getCString(), "r"))) { - parseFile(incFile, f2); - fclose(f2); - } else { - error(-1, "Couldn't find included config file: '%s' (%s:%d)", - incFile->getCString(), fileName->getCString(), line); - } - } else { - error(-1, "Bad 'include' config file command (%s:%d)", - fileName->getCString(), line); - } - } else if (!cmd->cmp("nameToUnicode")) { - parseNameToUnicode(tokens, fileName, line); - } else if (!cmd->cmp("cidToUnicode")) { - parseCIDToUnicode(tokens, fileName, line); - } else if (!cmd->cmp("unicodeToUnicode")) { - parseUnicodeToUnicode(tokens, fileName, line); - } else if (!cmd->cmp("unicodeMap")) { - parseUnicodeMap(tokens, fileName, line); - } else if (!cmd->cmp("cMapDir")) { - parseCMapDir(tokens, fileName, line); - } else if (!cmd->cmp("toUnicodeDir")) { - parseToUnicodeDir(tokens, fileName, line); - } else if (!cmd->cmp("displayFontT1")) { - parseDisplayFont(tokens, displayFonts, displayFontT1, fileName, line); - } else if (!cmd->cmp("displayFontTT")) { - parseDisplayFont(tokens, displayFonts, displayFontTT, fileName, line); - } else if (!cmd->cmp("displayNamedCIDFontT1")) { - parseDisplayFont(tokens, displayNamedCIDFonts, - displayFontT1, fileName, line); - } else if (!cmd->cmp("displayCIDFontT1")) { - parseDisplayFont(tokens, displayCIDFonts, - displayFontT1, fileName, line); - } else if (!cmd->cmp("displayNamedCIDFontTT")) { - parseDisplayFont(tokens, displayNamedCIDFonts, - displayFontTT, fileName, line); - } else if (!cmd->cmp("displayCIDFontTT")) { - parseDisplayFont(tokens, displayCIDFonts, - displayFontTT, fileName, line); - } else if (!cmd->cmp("psFile")) { - parsePSFile(tokens, fileName, line); - } else if (!cmd->cmp("psFont")) { - parsePSFont(tokens, fileName, line); - } else if (!cmd->cmp("psNamedFont16")) { - parsePSFont16("psNamedFont16", psNamedFonts16, - tokens, fileName, line); - } else if (!cmd->cmp("psFont16")) { - parsePSFont16("psFont16", psFonts16, tokens, fileName, line); - } else if (!cmd->cmp("psPaperSize")) { - parsePSPaperSize(tokens, fileName, line); - } else if (!cmd->cmp("psImageableArea")) { - parsePSImageableArea(tokens, fileName, line); - } else if (!cmd->cmp("psCrop")) { - parseYesNo("psCrop", &psCrop, tokens, fileName, line); - } else if (!cmd->cmp("psExpandSmaller")) { - parseYesNo("psExpandSmaller", &psExpandSmaller, - tokens, fileName, line); - } else if (!cmd->cmp("psShrinkLarger")) { - parseYesNo("psShrinkLarger", &psShrinkLarger, tokens, fileName, line); - } else if (!cmd->cmp("psCenter")) { - parseYesNo("psCenter", &psCenter, tokens, fileName, line); - } else if (!cmd->cmp("psDuplex")) { - parseYesNo("psDuplex", &psDuplex, tokens, fileName, line); - } else if (!cmd->cmp("psLevel")) { - parsePSLevel(tokens, fileName, line); - } else if (!cmd->cmp("psEmbedType1Fonts")) { - parseYesNo("psEmbedType1", &psEmbedType1, tokens, fileName, line); - } else if (!cmd->cmp("psEmbedTrueTypeFonts")) { - parseYesNo("psEmbedTrueType", &psEmbedTrueType, - tokens, fileName, line); - } else if (!cmd->cmp("psEmbedCIDPostScriptFonts")) { - parseYesNo("psEmbedCIDPostScript", &psEmbedCIDPostScript, - tokens, fileName, line); - } else if (!cmd->cmp("psEmbedCIDTrueTypeFonts")) { - parseYesNo("psEmbedCIDTrueType", &psEmbedCIDTrueType, - tokens, fileName, line); - } else if (!cmd->cmp("psOPI")) { - parseYesNo("psOPI", &psOPI, tokens, fileName, line); - } else if (!cmd->cmp("psASCIIHex")) { - parseYesNo("psASCIIHex", &psASCIIHex, tokens, fileName, line); - } else if (!cmd->cmp("textEncoding")) { - parseTextEncoding(tokens, fileName, line); - } else if (!cmd->cmp("textEOL")) { - parseTextEOL(tokens, fileName, line); - } else if (!cmd->cmp("textPageBreaks")) { - parseYesNo("textPageBreaks", &textPageBreaks, - tokens, fileName, line); - } else if (!cmd->cmp("textKeepTinyChars")) { - parseYesNo("textKeepTinyChars", &textKeepTinyChars, - tokens, fileName, line); - } else if (!cmd->cmp("fontDir")) { - parseFontDir(tokens, fileName, line); - } else if (!cmd->cmp("initialZoom")) { - parseInitialZoom(tokens, fileName, line); - } else if (!cmd->cmp("continuousView")) { - parseYesNo("continuousView", &continuousView, tokens, fileName, line); - } else if (!cmd->cmp("enableT1lib")) { - parseYesNo("enableT1lib", &enableT1lib, tokens, fileName, line); - } else if (!cmd->cmp("enableFreeType")) { - parseYesNo("enableFreeType", &enableFreeType, tokens, fileName, line); - } else if (!cmd->cmp("antialias")) { - parseYesNo("antialias", &antialias, tokens, fileName, line); - } else if (!cmd->cmp("urlCommand")) { - parseCommand("urlCommand", &urlCommand, tokens, fileName, line); - } else if (!cmd->cmp("movieCommand")) { - parseCommand("movieCommand", &movieCommand, tokens, fileName, line); - } else if (!cmd->cmp("mapNumericCharNames")) { - parseYesNo("mapNumericCharNames", &mapNumericCharNames, - tokens, fileName, line); - } else if (!cmd->cmp("printCommands")) { - parseYesNo("printCommands", &printCommands, tokens, fileName, line); - } else if (!cmd->cmp("errQuiet")) { - parseYesNo("errQuiet", &errQuiet, tokens, fileName, line); - } else { - error(-1, "Unknown config file command '%s' (%s:%d)", - cmd->getCString(), fileName->getCString(), line); - if (!cmd->cmp("displayFontX") || - !cmd->cmp("displayNamedCIDFontX") || - !cmd->cmp("displayCIDFontX")) { - error(-1, "-- Xpdf no longer supports X fonts"); - } else if (!cmd->cmp("t1libControl") || !cmd->cmp("freetypeControl")) { - error(-1, "-- The t1libControl and freetypeControl options have been replaced"); - error(-1, " by the enableT1lib, enableFreeType, and antialias options"); - } else if (!cmd->cmp("fontpath") || !cmd->cmp("fontmap")) { - error(-1, "-- the config file format has changed since Xpdf 0.9x"); - } - } - } - - deleteGList(tokens, GString); - ++line; - } -} - -void GlobalParams::parseNameToUnicode(GList *tokens, GString *fileName, - int line) { - GString *name; - char *tok1, *tok2; - FILE *f; - char buf[256]; - int line2; - Unicode u; - - if (tokens->getLength() != 2) { - error(-1, "Bad 'nameToUnicode' config file command (%s:%d)", - fileName->getCString(), line); - return; - } - name = (GString *)tokens->get(1); - if (!(f = fopen(name->getCString(), "r"))) { - error(-1, "Couldn't open 'nameToUnicode' file '%s'", - name->getCString()); - return; - } - line2 = 1; - while (getLine(buf, sizeof(buf), f)) { - tok1 = strtok(buf, " \t\r\n"); - tok2 = strtok(NULL, " \t\r\n"); - if (tok1 && tok2) { - sscanf(tok1, "%x", &u); - nameToUnicode->add(tok2, u); - } else { - error(-1, "Bad line in 'nameToUnicode' file (%s:%d)", name, line2); - } - ++line2; - } - fclose(f); -} - -void GlobalParams::parseCIDToUnicode(GList *tokens, GString *fileName, - int line) { - GString *collection, *name, *old; - - if (tokens->getLength() != 3) { - error(-1, "Bad 'cidToUnicode' config file command (%s:%d)", - fileName->getCString(), line); - return; - } - collection = (GString *)tokens->get(1); - name = (GString *)tokens->get(2); - if ((old = (GString *)cidToUnicodes->remove(collection))) { - delete old; - } - cidToUnicodes->add(collection->copy(), name->copy()); -} - -void GlobalParams::parseUnicodeToUnicode(GList *tokens, GString *fileName, - int line) { - GString *font, *file, *old; - - if (tokens->getLength() != 3) { - error(-1, "Bad 'unicodeToUnicode' config file command (%s:%d)", - fileName->getCString(), line); - return; - } - font = (GString *)tokens->get(1); - file = (GString *)tokens->get(2); - if ((old = (GString *)unicodeToUnicodes->remove(font))) { - delete old; - } - unicodeToUnicodes->add(font->copy(), file->copy()); -} - -void GlobalParams::parseUnicodeMap(GList *tokens, GString *fileName, - int line) { - GString *encodingName, *name, *old; - - if (tokens->getLength() != 3) { - error(-1, "Bad 'unicodeMap' config file command (%s:%d)", - fileName->getCString(), line); - return; - } - encodingName = (GString *)tokens->get(1); - name = (GString *)tokens->get(2); - if ((old = (GString *)unicodeMaps->remove(encodingName))) { - delete old; - } - unicodeMaps->add(encodingName->copy(), name->copy()); -} - -void GlobalParams::parseCMapDir(GList *tokens, GString *fileName, int line) { - GString *collection, *dir; - GList *list; - - if (tokens->getLength() != 3) { - error(-1, "Bad 'cMapDir' config file command (%s:%d)", - fileName->getCString(), line); - return; - } - collection = (GString *)tokens->get(1); - dir = (GString *)tokens->get(2); - if (!(list = (GList *)cMapDirs->lookup(collection))) { - list = new GList(); - cMapDirs->add(collection->copy(), list); - } - list->append(dir->copy()); -} - -void GlobalParams::parseToUnicodeDir(GList *tokens, GString *fileName, - int line) { - if (tokens->getLength() != 2) { - error(-1, "Bad 'toUnicodeDir' config file command (%s:%d)", - fileName->getCString(), line); - return; - } - toUnicodeDirs->append(((GString *)tokens->get(1))->copy()); -} - -void GlobalParams::parseDisplayFont(GList *tokens, GHash *fontHash, - DisplayFontParamKind kind, - GString *fileName, int line) { - DisplayFontParam *param, *old; - - if (tokens->getLength() < 2) { - goto err1; - } - param = new DisplayFontParam(((GString *)tokens->get(1))->copy(), kind); - - switch (kind) { - case displayFontT1: - if (tokens->getLength() != 3) { - goto err2; - } - param->t1.fileName = ((GString *)tokens->get(2))->copy(); - break; - case displayFontTT: - if (tokens->getLength() != 3) { - goto err2; - } - param->tt.fileName = ((GString *)tokens->get(2))->copy(); - break; - } - - if ((old = (DisplayFontParam *)fontHash->remove(param->name))) { - delete old; - } - fontHash->add(param->name, param); - return; - - err2: - delete param; - err1: - error(-1, "Bad 'display*Font*' config file command (%s:%d)", - fileName->getCString(), line); -} - -void GlobalParams::parsePSPaperSize(GList *tokens, GString *fileName, - int line) { - GString *tok; - - if (tokens->getLength() == 2) { - tok = (GString *)tokens->get(1); - if (!setPSPaperSize(tok->getCString())) { - error(-1, "Bad 'psPaperSize' config file command (%s:%d)", - fileName->getCString(), line); - } - } else if (tokens->getLength() == 3) { - tok = (GString *)tokens->get(1); - psPaperWidth = atoi(tok->getCString()); - tok = (GString *)tokens->get(2); - psPaperHeight = atoi(tok->getCString()); - psImageableLLX = psImageableLLY = 0; - psImageableURX = psPaperWidth; - psImageableURY = psPaperHeight; - } else { - error(-1, "Bad 'psPaperSize' config file command (%s:%d)", - fileName->getCString(), line); - } -} - -void GlobalParams::parsePSImageableArea(GList *tokens, GString *fileName, - int line) { - if (tokens->getLength() != 5) { - error(-1, "Bad 'psImageableArea' config file command (%s:%d)", - fileName->getCString(), line); - return; - } - psImageableLLX = atoi(((GString *)tokens->get(1))->getCString()); - psImageableLLY = atoi(((GString *)tokens->get(2))->getCString()); - psImageableURX = atoi(((GString *)tokens->get(3))->getCString()); - psImageableURY = atoi(((GString *)tokens->get(4))->getCString()); -} - -void GlobalParams::parsePSLevel(GList *tokens, GString *fileName, int line) { - GString *tok; - - if (tokens->getLength() != 2) { - error(-1, "Bad 'psLevel' config file command (%s:%d)", - fileName->getCString(), line); - return; - } - tok = (GString *)tokens->get(1); - if (!tok->cmp("level1")) { - psLevel = psLevel1; - } else if (!tok->cmp("level1sep")) { - psLevel = psLevel1Sep; - } else if (!tok->cmp("level2")) { - psLevel = psLevel2; - } else if (!tok->cmp("level2sep")) { - psLevel = psLevel2Sep; - } else if (!tok->cmp("level3")) { - psLevel = psLevel3; - } else if (!tok->cmp("level3Sep")) { - psLevel = psLevel3Sep; - } else { - error(-1, "Bad 'psLevel' config file command (%s:%d)", - fileName->getCString(), line); - } -} - -void GlobalParams::parsePSFile(GList *tokens, GString *fileName, int line) { - if (tokens->getLength() != 2) { - error(-1, "Bad 'psFile' config file command (%s:%d)", - fileName->getCString(), line); - return; - } - if (psFile) { - delete psFile; - } - psFile = ((GString *)tokens->get(1))->copy(); -} - -void GlobalParams::parsePSFont(GList *tokens, GString *fileName, int line) { - PSFontParam *param; - - if (tokens->getLength() != 3) { - error(-1, "Bad 'psFont' config file command (%s:%d)", - fileName->getCString(), line); - return; - } - param = new PSFontParam(((GString *)tokens->get(1))->copy(), 0, - ((GString *)tokens->get(2))->copy(), NULL); - psFonts->add(param->pdfFontName, param); -} - -void GlobalParams::parsePSFont16(char *cmdName, GList *fontList, - GList *tokens, GString *fileName, int line) { - PSFontParam *param; - int wMode; - GString *tok; - - if (tokens->getLength() != 5) { - error(-1, "Bad '%s' config file command (%s:%d)", - cmdName, fileName->getCString(), line); - return; - } - tok = (GString *)tokens->get(2); - if (!tok->cmp("H")) { - wMode = 0; - } else if (!tok->cmp("V")) { - wMode = 1; - } else { - error(-1, "Bad '%s' config file command (%s:%d)", - cmdName, fileName->getCString(), line); - return; - } - param = new PSFontParam(((GString *)tokens->get(1))->copy(), - wMode, - ((GString *)tokens->get(3))->copy(), - ((GString *)tokens->get(4))->copy()); - fontList->append(param); -} - -void GlobalParams::parseTextEncoding(GList *tokens, GString *fileName, - int line) { - if (tokens->getLength() != 2) { - error(-1, "Bad 'textEncoding' config file command (%s:%d)", - fileName->getCString(), line); - return; - } - delete textEncoding; - textEncoding = ((GString *)tokens->get(1))->copy(); -} - -void GlobalParams::parseTextEOL(GList *tokens, GString *fileName, int line) { - GString *tok; - - if (tokens->getLength() != 2) { - error(-1, "Bad 'textEOL' config file command (%s:%d)", - fileName->getCString(), line); - return; - } - tok = (GString *)tokens->get(1); - if (!tok->cmp("unix")) { - textEOL = eolUnix; - } else if (!tok->cmp("dos")) { - textEOL = eolDOS; - } else if (!tok->cmp("mac")) { - textEOL = eolMac; - } else { - error(-1, "Bad 'textEOL' config file command (%s:%d)", - fileName->getCString(), line); - } -} - -void GlobalParams::parseFontDir(GList *tokens, GString *fileName, int line) { - if (tokens->getLength() != 2) { - error(-1, "Bad 'fontDir' config file command (%s:%d)", - fileName->getCString(), line); - return; - } - fontDirs->append(((GString *)tokens->get(1))->copy()); -} - -void GlobalParams::parseInitialZoom(GList *tokens, - GString *fileName, int line) { - if (tokens->getLength() != 2) { - error(-1, "Bad 'initialZoom' config file command (%s:%d)", - fileName->getCString(), line); - return; - } - delete initialZoom; - initialZoom = ((GString *)tokens->get(1))->copy(); -} - -void GlobalParams::parseCommand(char *cmdName, GString **val, - GList *tokens, GString *fileName, int line) { - if (tokens->getLength() != 2) { - error(-1, "Bad '%s' config file command (%s:%d)", - cmdName, fileName->getCString(), line); - return; - } - if (*val) { - delete *val; - } - *val = ((GString *)tokens->get(1))->copy(); -} - -void GlobalParams::parseYesNo(char *cmdName, GBool *flag, - GList *tokens, GString *fileName, int line) { - GString *tok; - - if (tokens->getLength() != 2) { - error(-1, "Bad '%s' config file command (%s:%d)", - cmdName, fileName->getCString(), line); - return; - } - tok = (GString *)tokens->get(1); - if (!parseYesNo2(tok->getCString(), flag)) { - error(-1, "Bad '%s' config file command (%s:%d)", - cmdName, fileName->getCString(), line); - } -} - -GBool GlobalParams::parseYesNo2(char *token, GBool *flag) { - if (!strcmp(token, "yes")) { - *flag = gTrue; - } else if (!strcmp(token, "no")) { - *flag = gFalse; - } else { - return gFalse; - } - return gTrue; -} - -GlobalParams::~GlobalParams() { - GHashIter *iter; - GString *key; - GList *list; - - freeBuiltinFontTables(); - - delete macRomanReverseMap; - - delete baseDir; - delete nameToUnicode; - deleteGHash(cidToUnicodes, GString); - deleteGHash(unicodeToUnicodes, GString); - deleteGHash(residentUnicodeMaps, UnicodeMap); - deleteGHash(unicodeMaps, GString); - deleteGList(toUnicodeDirs, GString); - deleteGHash(displayFonts, DisplayFontParam); - deleteGHash(displayCIDFonts, DisplayFontParam); - deleteGHash(displayNamedCIDFonts, DisplayFontParam); - if (psFile) { - delete psFile; - } - deleteGHash(psFonts, PSFontParam); - deleteGList(psNamedFonts16, PSFontParam); - deleteGList(psFonts16, PSFontParam); - delete textEncoding; - deleteGList(fontDirs, GString); - delete initialZoom; - if (urlCommand) { - delete urlCommand; - } - if (movieCommand) { - delete movieCommand; - } - - cMapDirs->startIter(&iter); - while (cMapDirs->getNext(&iter, &key, (void **)&list)) { - deleteGList(list, GString); - } - delete cMapDirs; - - delete cidToUnicodeCache; - delete unicodeToUnicodeCache; - delete unicodeMapCache; - delete cMapCache; - -#ifdef ENABLE_PLUGINS - delete securityHandlers; - deleteGList(plugins, Plugin); -#endif - -#if MULTITHREADED - gDestroyMutex(&mutex); - gDestroyMutex(&unicodeMapCacheMutex); - gDestroyMutex(&cMapCacheMutex); -#endif -} - -//------------------------------------------------------------------------ - -void GlobalParams::setBaseDir(char *dir) { - delete baseDir; - baseDir = new GString(dir); -} - -void GlobalParams::setupBaseFonts(char *dir) { - GString *fontName; - GString *fileName; -#ifdef WIN32 - HMODULE shell32Lib; - BOOL (__stdcall *SHGetSpecialFolderPathFunc)(HWND hwndOwner, - LPTSTR lpszPath, - int nFolder, - BOOL fCreate); - char winFontDir[MAX_PATH]; -#endif - FILE *f; - DisplayFontParamKind kind; - DisplayFontParam *dfp; - int i, j; - -#ifdef WIN32 - // SHGetSpecialFolderPath isn't available in older versions of - // shell32.dll (Win95 and WinNT4), so do a dynamic load - winFontDir[0] = '\0'; - if ((shell32Lib = LoadLibrary("shell32.dll"))) { - if ((SHGetSpecialFolderPathFunc = - (BOOL (__stdcall *)(HWND hwndOwner, LPTSTR lpszPath, - int nFolder, BOOL fCreate)) - GetProcAddress(shell32Lib, "SHGetSpecialFolderPath"))) { - if (!(*SHGetSpecialFolderPathFunc)(NULL, winFontDir, - CSIDL_FONTS, FALSE)) { - winFontDir[0] = '\0'; - } - } - } -#endif - for (i = 0; displayFontTab[i].name; ++i) { - fontName = new GString(displayFontTab[i].name); - if (getDisplayFont(fontName)) { - delete fontName; - continue; - } - fileName = NULL; - kind = displayFontT1; // make gcc happy - if (dir) { - fileName = appendToPath(new GString(dir), displayFontTab[i].t1FileName); - kind = displayFontT1; - if ((f = fopen(fileName->getCString(), "rb"))) { - fclose(f); - } else { - delete fileName; - fileName = NULL; - } - } -#ifdef WIN32 - if (!fileName && winFontDir[0] && displayFontTab[i].ttFileName) { - fileName = appendToPath(new GString(winFontDir), - displayFontTab[i].ttFileName); - kind = displayFontTT; - if ((f = fopen(fileName->getCString(), "rb"))) { - fclose(f); - } else { - delete fileName; - fileName = NULL; - } - } - // SHGetSpecialFolderPath(CSIDL_FONTS) doesn't work on Win 2k Server - // or Win2003 Server, or with older versions of shell32.dll, so check - // the "standard" directories - if (displayFontTab[i].ttFileName) { - for (j = 0; !fileName && displayFontDirs[j]; ++j) { - fileName = appendToPath(new GString(displayFontDirs[j]), - displayFontTab[i].ttFileName); - kind = displayFontTT; - if ((f = fopen(fileName->getCString(), "rb"))) { - fclose(f); - } else { - delete fileName; - fileName = NULL; - } - } - } -#else - for (j = 0; !fileName && displayFontDirs[j]; ++j) { - fileName = appendToPath(new GString(displayFontDirs[j]), - displayFontTab[i].t1FileName); - kind = displayFontT1; - if ((f = fopen(fileName->getCString(), "rb"))) { - fclose(f); - } else { - delete fileName; - fileName = NULL; - } - } -#endif - if (!fileName) { - error(-1, "No display font for '%s'", displayFontTab[i].name); - delete fontName; - continue; - } - dfp = new DisplayFontParam(fontName, kind); - dfp->t1.fileName = fileName; - globalParams->addDisplayFont(dfp); - } -} - -//------------------------------------------------------------------------ -// accessors -//------------------------------------------------------------------------ - -CharCode GlobalParams::getMacRomanCharCode(char *charName) { - // no need to lock - macRomanReverseMap is constant - return macRomanReverseMap->lookup(charName); -} - -GString *GlobalParams::getBaseDir() { - GString *s; - - lockGlobalParams; - s = baseDir->copy(); - unlockGlobalParams; - return s; -} - -Unicode GlobalParams::mapNameToUnicode(char *charName) { - // no need to lock - nameToUnicode is constant - return nameToUnicode->lookup(charName); -} - -UnicodeMap *GlobalParams::getResidentUnicodeMap(GString *encodingName) { - UnicodeMap *map; - - lockGlobalParams; - map = (UnicodeMap *)residentUnicodeMaps->lookup(encodingName); - unlockGlobalParams; - if (map) { - map->incRefCnt(); - } - return map; -} - -FILE *GlobalParams::getUnicodeMapFile(GString *encodingName) { - GString *fileName; - FILE *f; - - lockGlobalParams; - if ((fileName = (GString *)unicodeMaps->lookup(encodingName))) { - f = fopen(fileName->getCString(), "r"); - } else { - f = NULL; - } - unlockGlobalParams; - return f; -} - -FILE *GlobalParams::findCMapFile(GString *collection, GString *cMapName) { - GList *list; - GString *dir; - GString *fileName; - FILE *f; - int i; - - lockGlobalParams; - if (!(list = (GList *)cMapDirs->lookup(collection))) { - unlockGlobalParams; - return NULL; - } - for (i = 0; i < list->getLength(); ++i) { - dir = (GString *)list->get(i); - fileName = appendToPath(dir->copy(), cMapName->getCString()); - f = fopen(fileName->getCString(), "r"); - delete fileName; - if (f) { - unlockGlobalParams; - return f; - } - } - unlockGlobalParams; - return NULL; -} - -FILE *GlobalParams::findToUnicodeFile(GString *name) { - GString *dir, *fileName; - FILE *f; - int i; - - lockGlobalParams; - for (i = 0; i < toUnicodeDirs->getLength(); ++i) { - dir = (GString *)toUnicodeDirs->get(i); - fileName = appendToPath(dir->copy(), name->getCString()); - f = fopen(fileName->getCString(), "r"); - delete fileName; - if (f) { - unlockGlobalParams; - return f; - } - } - unlockGlobalParams; - return NULL; -} - -DisplayFontParam *GlobalParams::getDisplayFont(GString *fontName) { - DisplayFontParam *dfp; - - lockGlobalParams; - dfp = (DisplayFontParam *)displayFonts->lookup(fontName); - unlockGlobalParams; - return dfp; -} - -DisplayFontParam *GlobalParams::getDisplayCIDFont(GString *fontName, - GString *collection) { - DisplayFontParam *dfp; - - lockGlobalParams; - if (!fontName || - !(dfp = (DisplayFontParam *)displayNamedCIDFonts->lookup(fontName))) { - dfp = (DisplayFontParam *)displayCIDFonts->lookup(collection); - } - unlockGlobalParams; - return dfp; -} - -GString *GlobalParams::getPSFile() { - GString *s; - - lockGlobalParams; - s = psFile ? psFile->copy() : (GString *)NULL; - unlockGlobalParams; - return s; -} - -int GlobalParams::getPSPaperWidth() { - int w; - - lockGlobalParams; - w = psPaperWidth; - unlockGlobalParams; - return w; -} - -int GlobalParams::getPSPaperHeight() { - int h; - - lockGlobalParams; - h = psPaperHeight; - unlockGlobalParams; - return h; -} - -void GlobalParams::getPSImageableArea(int *llx, int *lly, int *urx, int *ury) { - lockGlobalParams; - *llx = psImageableLLX; - *lly = psImageableLLY; - *urx = psImageableURX; - *ury = psImageableURY; - unlockGlobalParams; -} - -GBool GlobalParams::getPSCrop() { - GBool f; - - lockGlobalParams; - f = psCrop; - unlockGlobalParams; - return f; -} - -GBool GlobalParams::getPSExpandSmaller() { - GBool f; - - lockGlobalParams; - f = psExpandSmaller; - unlockGlobalParams; - return f; -} - -GBool GlobalParams::getPSShrinkLarger() { - GBool f; - - lockGlobalParams; - f = psShrinkLarger; - unlockGlobalParams; - return f; -} - -GBool GlobalParams::getPSCenter() { - GBool f; - - lockGlobalParams; - f = psCenter; - unlockGlobalParams; - return f; -} - -GBool GlobalParams::getPSDuplex() { - GBool d; - - lockGlobalParams; - d = psDuplex; - unlockGlobalParams; - return d; -} - -PSLevel GlobalParams::getPSLevel() { - PSLevel level; - - lockGlobalParams; - level = psLevel; - unlockGlobalParams; - return level; -} - -PSFontParam *GlobalParams::getPSFont(GString *fontName) { - PSFontParam *p; - - lockGlobalParams; - p = (PSFontParam *)psFonts->lookup(fontName); - unlockGlobalParams; - return p; -} - -PSFontParam *GlobalParams::getPSFont16(GString *fontName, - GString *collection, int wMode) { - PSFontParam *p; - int i; - - lockGlobalParams; - p = NULL; - if (fontName) { - for (i = 0; i < psNamedFonts16->getLength(); ++i) { - p = (PSFontParam *)psNamedFonts16->get(i); - if (!p->pdfFontName->cmp(fontName) && - p->wMode == wMode) { - break; - } - p = NULL; - } - } - if (!p && collection) { - for (i = 0; i < psFonts16->getLength(); ++i) { - p = (PSFontParam *)psFonts16->get(i); - if (!p->pdfFontName->cmp(collection) && - p->wMode == wMode) { - break; - } - p = NULL; - } - } - unlockGlobalParams; - return p; -} - -GBool GlobalParams::getPSEmbedType1() { - GBool e; - - lockGlobalParams; - e = psEmbedType1; - unlockGlobalParams; - return e; -} - -GBool GlobalParams::getPSEmbedTrueType() { - GBool e; - - lockGlobalParams; - e = psEmbedTrueType; - unlockGlobalParams; - return e; -} - -GBool GlobalParams::getPSEmbedCIDPostScript() { - GBool e; - - lockGlobalParams; - e = psEmbedCIDPostScript; - unlockGlobalParams; - return e; -} - -GBool GlobalParams::getPSEmbedCIDTrueType() { - GBool e; - - lockGlobalParams; - e = psEmbedCIDTrueType; - unlockGlobalParams; - return e; -} - -GBool GlobalParams::getPSOPI() { - GBool opi; - - lockGlobalParams; - opi = psOPI; - unlockGlobalParams; - return opi; -} - -GBool GlobalParams::getPSASCIIHex() { - GBool ah; - - lockGlobalParams; - ah = psASCIIHex; - unlockGlobalParams; - return ah; -} - -GString *GlobalParams::getTextEncodingName() { - GString *s; - - lockGlobalParams; - s = textEncoding->copy(); - unlockGlobalParams; - return s; -} - -EndOfLineKind GlobalParams::getTextEOL() { - EndOfLineKind eol; - - lockGlobalParams; - eol = textEOL; - unlockGlobalParams; - return eol; -} - -GBool GlobalParams::getTextPageBreaks() { - GBool pageBreaks; - - lockGlobalParams; - pageBreaks = textPageBreaks; - unlockGlobalParams; - return pageBreaks; -} - -GBool GlobalParams::getTextKeepTinyChars() { - GBool tiny; - - lockGlobalParams; - tiny = textKeepTinyChars; - unlockGlobalParams; - return tiny; -} - -GString *GlobalParams::findFontFile(GString *fontName, char **exts) { - GString *dir, *fileName; - char **ext; - FILE *f; - int i; - - lockGlobalParams; - for (i = 0; i < fontDirs->getLength(); ++i) { - dir = (GString *)fontDirs->get(i); - for (ext = exts; *ext; ++ext) { - fileName = appendToPath(dir->copy(), fontName->getCString()); - fileName->append(*ext); - if ((f = fopen(fileName->getCString(), "rb"))) { - fclose(f); - unlockGlobalParams; - return fileName; - } - delete fileName; - } - } - unlockGlobalParams; - return NULL; -} - -GString *GlobalParams::getInitialZoom() { - GString *s; - - lockGlobalParams; - s = initialZoom->copy(); - unlockGlobalParams; - return s; -} - -GBool GlobalParams::getContinuousView() { - GBool f; - - lockGlobalParams; - f = continuousView; - unlockGlobalParams; - return f; -} - -GBool GlobalParams::getEnableT1lib() { - GBool f; - - lockGlobalParams; - f = enableT1lib; - unlockGlobalParams; - return f; -} - -GBool GlobalParams::getEnableFreeType() { - GBool f; - - lockGlobalParams; - f = enableFreeType; - unlockGlobalParams; - return f; -} - - -GBool GlobalParams::getAntialias() { - GBool f; - - lockGlobalParams; - f = antialias; - unlockGlobalParams; - return f; -} - -GBool GlobalParams::getMapNumericCharNames() { - GBool map; - - lockGlobalParams; - map = mapNumericCharNames; - unlockGlobalParams; - return map; -} - -GBool GlobalParams::getPrintCommands() { - GBool p; - - lockGlobalParams; - p = printCommands; - unlockGlobalParams; - return p; -} - -GBool GlobalParams::getErrQuiet() { - GBool q; - - lockGlobalParams; - q = errQuiet; - unlockGlobalParams; - return q; -} - -CharCodeToUnicode *GlobalParams::getCIDToUnicode(GString *collection) { - GString *fileName; - CharCodeToUnicode *ctu; - - lockGlobalParams; - if (!(ctu = cidToUnicodeCache->getCharCodeToUnicode(collection))) { - if ((fileName = (GString *)cidToUnicodes->lookup(collection)) && - (ctu = CharCodeToUnicode::parseCIDToUnicode(fileName, collection))) { - cidToUnicodeCache->add(ctu); - } - } - unlockGlobalParams; - return ctu; -} - -CharCodeToUnicode *GlobalParams::getUnicodeToUnicode(GString *fontName) { - CharCodeToUnicode *ctu; - GHashIter *iter; - GString *fontPattern, *fileName; - - lockGlobalParams; - fileName = NULL; - unicodeToUnicodes->startIter(&iter); - while (unicodeToUnicodes->getNext(&iter, &fontPattern, (void **)&fileName)) { - if (strstr(fontName->getCString(), fontPattern->getCString())) { - unicodeToUnicodes->killIter(&iter); - break; - } - fileName = NULL; - } - if (fileName) { - if (!(ctu = unicodeToUnicodeCache->getCharCodeToUnicode(fileName))) { - if ((ctu = CharCodeToUnicode::parseUnicodeToUnicode(fileName))) { - unicodeToUnicodeCache->add(ctu); - } - } - } else { - ctu = NULL; - } - unlockGlobalParams; - return ctu; -} - -UnicodeMap *GlobalParams::getUnicodeMap(GString *encodingName) { - return getUnicodeMap2(encodingName); -} - -UnicodeMap *GlobalParams::getUnicodeMap2(GString *encodingName) { - UnicodeMap *map; - - if (!(map = getResidentUnicodeMap(encodingName))) { - lockUnicodeMapCache; - map = unicodeMapCache->getUnicodeMap(encodingName); - unlockUnicodeMapCache; - } - return map; -} - -CMap *GlobalParams::getCMap(GString *collection, GString *cMapName) { - CMap *cMap; - - lockCMapCache; - cMap = cMapCache->getCMap(collection, cMapName); - unlockCMapCache; - return cMap; -} - -UnicodeMap *GlobalParams::getTextEncoding() { - return getUnicodeMap2(textEncoding); -} - -//------------------------------------------------------------------------ -// functions to set parameters -//------------------------------------------------------------------------ - -void GlobalParams::addDisplayFont(DisplayFontParam *param) { - DisplayFontParam *old; - - lockGlobalParams; - if ((old = (DisplayFontParam *)displayFonts->remove(param->name))) { - delete old; - } - displayFonts->add(param->name, param); - unlockGlobalParams; -} - -void GlobalParams::setPSFile(char *file) { - lockGlobalParams; - if (psFile) { - delete psFile; - } - psFile = new GString(file); - unlockGlobalParams; -} - -GBool GlobalParams::setPSPaperSize(char *size) { - lockGlobalParams; - if (!strcmp(size, "match")) { - psPaperWidth = psPaperHeight = -1; - } else if (!strcmp(size, "letter")) { - psPaperWidth = 612; - psPaperHeight = 792; - } else if (!strcmp(size, "legal")) { - psPaperWidth = 612; - psPaperHeight = 1008; - } else if (!strcmp(size, "A4")) { - psPaperWidth = 595; - psPaperHeight = 842; - } else if (!strcmp(size, "A3")) { - psPaperWidth = 842; - psPaperHeight = 1190; - } else { - unlockGlobalParams; - return gFalse; - } - psImageableLLX = psImageableLLY = 0; - psImageableURX = psPaperWidth; - psImageableURY = psPaperHeight; - unlockGlobalParams; - return gTrue; -} - -void GlobalParams::setPSPaperWidth(int width) { - lockGlobalParams; - psPaperWidth = width; - psImageableLLX = 0; - psImageableURX = psPaperWidth; - unlockGlobalParams; -} - -void GlobalParams::setPSPaperHeight(int height) { - lockGlobalParams; - psPaperHeight = height; - psImageableLLY = 0; - psImageableURY = psPaperHeight; - unlockGlobalParams; -} - -void GlobalParams::setPSImageableArea(int llx, int lly, int urx, int ury) { - lockGlobalParams; - psImageableLLX = llx; - psImageableLLY = lly; - psImageableURX = urx; - psImageableURY = ury; - unlockGlobalParams; -} - -void GlobalParams::setPSCrop(GBool crop) { - lockGlobalParams; - psCrop = crop; - unlockGlobalParams; -} - -void GlobalParams::setPSExpandSmaller(GBool expand) { - lockGlobalParams; - psExpandSmaller = expand; - unlockGlobalParams; -} - -void GlobalParams::setPSShrinkLarger(GBool shrink) { - lockGlobalParams; - psShrinkLarger = shrink; - unlockGlobalParams; -} - -void GlobalParams::setPSCenter(GBool center) { - lockGlobalParams; - psCenter = center; - unlockGlobalParams; -} - -void GlobalParams::setPSDuplex(GBool duplex) { - lockGlobalParams; - psDuplex = duplex; - unlockGlobalParams; -} - -void GlobalParams::setPSLevel(PSLevel level) { - lockGlobalParams; - psLevel = level; - unlockGlobalParams; -} - -void GlobalParams::setPSEmbedType1(GBool embed) { - lockGlobalParams; - psEmbedType1 = embed; - unlockGlobalParams; -} - -void GlobalParams::setPSEmbedTrueType(GBool embed) { - lockGlobalParams; - psEmbedTrueType = embed; - unlockGlobalParams; -} - -void GlobalParams::setPSEmbedCIDPostScript(GBool embed) { - lockGlobalParams; - psEmbedCIDPostScript = embed; - unlockGlobalParams; -} - -void GlobalParams::setPSEmbedCIDTrueType(GBool embed) { - lockGlobalParams; - psEmbedCIDTrueType = embed; - unlockGlobalParams; -} - -void GlobalParams::setPSOPI(GBool opi) { - lockGlobalParams; - psOPI = opi; - unlockGlobalParams; -} - -void GlobalParams::setPSASCIIHex(GBool hex) { - lockGlobalParams; - psASCIIHex = hex; - unlockGlobalParams; -} - -void GlobalParams::setTextEncoding(char *encodingName) { - lockGlobalParams; - delete textEncoding; - textEncoding = new GString(encodingName); - unlockGlobalParams; -} - -GBool GlobalParams::setTextEOL(char *s) { - lockGlobalParams; - if (!strcmp(s, "unix")) { - textEOL = eolUnix; - } else if (!strcmp(s, "dos")) { - textEOL = eolDOS; - } else if (!strcmp(s, "mac")) { - textEOL = eolMac; - } else { - unlockGlobalParams; - return gFalse; - } - unlockGlobalParams; - return gTrue; -} - -void GlobalParams::setTextPageBreaks(GBool pageBreaks) { - lockGlobalParams; - textPageBreaks = pageBreaks; - unlockGlobalParams; -} - -void GlobalParams::setTextKeepTinyChars(GBool keep) { - lockGlobalParams; - textKeepTinyChars = keep; - unlockGlobalParams; -} - -void GlobalParams::setInitialZoom(char *s) { - lockGlobalParams; - delete initialZoom; - initialZoom = new GString(s); - unlockGlobalParams; -} - -void GlobalParams::setContinuousView(GBool cont) { - lockGlobalParams; - continuousView = cont; - unlockGlobalParams; -} - -GBool GlobalParams::setEnableT1lib(char *s) { - GBool ok; - - lockGlobalParams; - ok = parseYesNo2(s, &enableT1lib); - unlockGlobalParams; - return ok; -} - -GBool GlobalParams::setEnableFreeType(char *s) { - GBool ok; - - lockGlobalParams; - ok = parseYesNo2(s, &enableFreeType); - unlockGlobalParams; - return ok; -} - - -GBool GlobalParams::setAntialias(char *s) { - GBool ok; - - lockGlobalParams; - ok = parseYesNo2(s, &antialias); - unlockGlobalParams; - return ok; -} - -void GlobalParams::setMapNumericCharNames(GBool map) { - lockGlobalParams; - mapNumericCharNames = map; - unlockGlobalParams; -} - -void GlobalParams::setPrintCommands(GBool printCommandsA) { - lockGlobalParams; - printCommands = printCommandsA; - unlockGlobalParams; -} - -void GlobalParams::setErrQuiet(GBool errQuietA) { - lockGlobalParams; - errQuiet = errQuietA; - unlockGlobalParams; -} - -void GlobalParams::addSecurityHandler(XpdfSecurityHandler *handler) { -#ifdef ENABLE_PLUGINS - lockGlobalParams; - securityHandlers->append(handler); - unlockGlobalParams; -#endif -} - -XpdfSecurityHandler *GlobalParams::getSecurityHandler(char *name) { -#ifdef ENABLE_PLUGINS - XpdfSecurityHandler *hdlr; - int i; - - lockGlobalParams; - for (i = 0; i < securityHandlers->getLength(); ++i) { - hdlr = (XpdfSecurityHandler *)securityHandlers->get(i); - if (!stricmp(hdlr->name, name)) { - unlockGlobalParams; - return hdlr; - } - } - unlockGlobalParams; - - if (!loadPlugin("security", name)) { - return NULL; - } - - lockGlobalParams; - for (i = 0; i < securityHandlers->getLength(); ++i) { - hdlr = (XpdfSecurityHandler *)securityHandlers->get(i); - if (!strcmp(hdlr->name, name)) { - unlockGlobalParams; - return hdlr; - } - } - unlockGlobalParams; -#endif - - return NULL; -} - -#ifdef ENABLE_PLUGINS -//------------------------------------------------------------------------ -// plugins -//------------------------------------------------------------------------ - -GBool GlobalParams::loadPlugin(char *type, char *name) { - Plugin *plugin; - - if (!(plugin = Plugin::load(type, name))) { - return gFalse; - } - lockGlobalParams; - plugins->append(plugin); - unlockGlobalParams; - return gTrue; -} - -#endif // ENABLE_PLUGINS diff --git a/pdftops/GlobalParams.h b/pdftops/GlobalParams.h deleted file mode 100644 index 2232d5e32..000000000 --- a/pdftops/GlobalParams.h +++ /dev/null @@ -1,336 +0,0 @@ -//======================================================================== -// -// GlobalParams.h -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef GLOBALPARAMS_H -#define GLOBALPARAMS_H - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include <stdio.h> -#include "gtypes.h" -#include "CharTypes.h" - -#if MULTITHREADED -#include "GMutex.h" -#endif - -class GString; -class GList; -class GHash; -class NameToCharCode; -class CharCodeToUnicode; -class CharCodeToUnicodeCache; -class UnicodeMap; -class UnicodeMapCache; -class CMap; -class CMapCache; -struct XpdfSecurityHandler; -class GlobalParams; - -//------------------------------------------------------------------------ - -// The global parameters object. -extern GlobalParams *globalParams; - -//------------------------------------------------------------------------ - -enum DisplayFontParamKind { - displayFontT1, - displayFontTT -}; - -struct DisplayFontParamT1 { - GString *fileName; -}; - -struct DisplayFontParamTT { - GString *fileName; -}; - -class DisplayFontParam { -public: - - GString *name; // font name for 8-bit fonts and named - // CID fonts; collection name for - // generic CID fonts - DisplayFontParamKind kind; - union { - DisplayFontParamT1 t1; - DisplayFontParamTT tt; - }; - - DisplayFontParam(GString *nameA, DisplayFontParamKind kindA); - ~DisplayFontParam(); -}; - -//------------------------------------------------------------------------ - -class PSFontParam { -public: - - GString *pdfFontName; // PDF font name for 8-bit fonts and - // named 16-bit fonts; char collection - // name for generic 16-bit fonts - int wMode; // writing mode (0=horiz, 1=vert) for - // 16-bit fonts - GString *psFontName; // PostScript font name - GString *encoding; // encoding, for 16-bit fonts only - - PSFontParam(GString *pdfFontNameA, int wModeA, - GString *psFontNameA, GString *encodingA); - ~PSFontParam(); -}; - -//------------------------------------------------------------------------ - -enum PSLevel { - psLevel1, - psLevel1Sep, - psLevel2, - psLevel2Sep, - psLevel3, - psLevel3Sep -}; - -//------------------------------------------------------------------------ - -enum EndOfLineKind { - eolUnix, // LF - eolDOS, // CR+LF - eolMac // CR -}; - -//------------------------------------------------------------------------ - -class GlobalParams { -public: - - // Initialize the global parameters by attempting to read a config - // file. - GlobalParams(char *cfgFileName); - - ~GlobalParams(); - - void setBaseDir(char *dir); - void setupBaseFonts(char *dir); - - //----- accessors - - CharCode getMacRomanCharCode(char *charName); - - GString *getBaseDir(); - Unicode mapNameToUnicode(char *charName); - UnicodeMap *getResidentUnicodeMap(GString *encodingName); - FILE *getUnicodeMapFile(GString *encodingName); - FILE *findCMapFile(GString *collection, GString *cMapName); - FILE *findToUnicodeFile(GString *name); - DisplayFontParam *getDisplayFont(GString *fontName); - DisplayFontParam *getDisplayCIDFont(GString *fontName, GString *collection); - GString *getPSFile(); - int getPSPaperWidth(); - int getPSPaperHeight(); - void getPSImageableArea(int *llx, int *lly, int *urx, int *ury); - GBool getPSDuplex(); - GBool getPSCrop(); - GBool getPSExpandSmaller(); - GBool getPSShrinkLarger(); - GBool getPSCenter(); - PSLevel getPSLevel(); - PSFontParam *getPSFont(GString *fontName); - PSFontParam *getPSFont16(GString *fontName, GString *collection, int wMode); - GBool getPSEmbedType1(); - GBool getPSEmbedTrueType(); - GBool getPSEmbedCIDPostScript(); - GBool getPSEmbedCIDTrueType(); - GBool getPSOPI(); - GBool getPSASCIIHex(); - GString *getTextEncodingName(); - EndOfLineKind getTextEOL(); - GBool getTextPageBreaks(); - GBool getTextKeepTinyChars(); - GString *findFontFile(GString *fontName, char **exts); - GString *getInitialZoom(); - GBool getContinuousView(); - GBool getEnableT1lib(); - GBool getEnableFreeType(); - GBool getAntialias(); - GString *getURLCommand() { return urlCommand; } - GString *getMovieCommand() { return movieCommand; } - GBool getMapNumericCharNames(); - GBool getPrintCommands(); - GBool getErrQuiet(); - - CharCodeToUnicode *getCIDToUnicode(GString *collection); - CharCodeToUnicode *getUnicodeToUnicode(GString *fontName); - UnicodeMap *getUnicodeMap(GString *encodingName); - CMap *getCMap(GString *collection, GString *cMapName); - UnicodeMap *getTextEncoding(); - - //----- functions to set parameters - - void addDisplayFont(DisplayFontParam *param); - void setPSFile(char *file); - GBool setPSPaperSize(char *size); - void setPSPaperWidth(int width); - void setPSPaperHeight(int height); - void setPSImageableArea(int llx, int lly, int urx, int ury); - void setPSDuplex(GBool duplex); - void setPSCrop(GBool crop); - void setPSExpandSmaller(GBool expand); - void setPSShrinkLarger(GBool shrink); - void setPSCenter(GBool center); - void setPSLevel(PSLevel level); - void setPSEmbedType1(GBool embed); - void setPSEmbedTrueType(GBool embed); - void setPSEmbedCIDPostScript(GBool embed); - void setPSEmbedCIDTrueType(GBool embed); - void setPSOPI(GBool opi); - void setPSASCIIHex(GBool hex); - void setTextEncoding(char *encodingName); - GBool setTextEOL(char *s); - void setTextPageBreaks(GBool pageBreaks); - void setTextKeepTinyChars(GBool keep); - void setInitialZoom(char *s); - void setContinuousView(GBool cont); - GBool setEnableT1lib(char *s); - GBool setEnableFreeType(char *s); - GBool setAntialias(char *s); - void setMapNumericCharNames(GBool map); - void setPrintCommands(GBool printCommandsA); - void setErrQuiet(GBool errQuietA); - - //----- security handlers - - void addSecurityHandler(XpdfSecurityHandler *handler); - XpdfSecurityHandler *getSecurityHandler(char *name); - -private: - - void parseFile(GString *fileName, FILE *f); - void parseNameToUnicode(GList *tokens, GString *fileName, int line); - void parseCIDToUnicode(GList *tokens, GString *fileName, int line); - void parseUnicodeToUnicode(GList *tokens, GString *fileName, int line); - void parseUnicodeMap(GList *tokens, GString *fileName, int line); - void parseCMapDir(GList *tokens, GString *fileName, int line); - void parseToUnicodeDir(GList *tokens, GString *fileName, int line); - void parseDisplayFont(GList *tokens, GHash *fontHash, - DisplayFontParamKind kind, - GString *fileName, int line); - void parsePSFile(GList *tokens, GString *fileName, int line); - void parsePSPaperSize(GList *tokens, GString *fileName, int line); - void parsePSImageableArea(GList *tokens, GString *fileName, int line); - void parsePSLevel(GList *tokens, GString *fileName, int line); - void parsePSFont(GList *tokens, GString *fileName, int line); - void parsePSFont16(char *cmdName, GList *fontList, - GList *tokens, GString *fileName, int line); - void parseTextEncoding(GList *tokens, GString *fileName, int line); - void parseTextEOL(GList *tokens, GString *fileName, int line); - void parseFontDir(GList *tokens, GString *fileName, int line); - void parseInitialZoom(GList *tokens, GString *fileName, int line); - void parseCommand(char *cmdName, GString **val, - GList *tokens, GString *fileName, int line); - void parseYesNo(char *cmdName, GBool *flag, - GList *tokens, GString *fileName, int line); - GBool parseYesNo2(char *token, GBool *flag); - UnicodeMap *getUnicodeMap2(GString *encodingName); -#ifdef ENABLE_PLUGINS - GBool loadPlugin(char *type, char *name); -#endif - - //----- static tables - - NameToCharCode * // mapping from char name to - macRomanReverseMap; // MacRomanEncoding index - - //----- user-modifiable settings - - GString *baseDir; // base directory - for plugins, etc. - NameToCharCode * // mapping from char name to Unicode - nameToUnicode; - GHash *cidToUnicodes; // files for mappings from char collections - // to Unicode, indexed by collection name - // [GString] - GHash *unicodeToUnicodes; // files for Unicode-to-Unicode mappings, - // indexed by font name pattern [GString] - GHash *residentUnicodeMaps; // mappings from Unicode to char codes, - // indexed by encoding name [UnicodeMap] - GHash *unicodeMaps; // files for mappings from Unicode to char - // codes, indexed by encoding name [GString] - GHash *cMapDirs; // list of CMap dirs, indexed by collection - // name [GList[GString]] - GList *toUnicodeDirs; // list of ToUnicode CMap dirs [GString] - GHash *displayFonts; // display font info, indexed by font name - // [DisplayFontParam] - GHash *displayCIDFonts; // display CID font info, indexed by - // collection [DisplayFontParam] - GHash *displayNamedCIDFonts; // display CID font info, indexed by - // font name [DisplayFontParam] - GString *psFile; // PostScript file or command (for xpdf) - int psPaperWidth; // paper size, in PostScript points, for - int psPaperHeight; // PostScript output - int psImageableLLX, // imageable area, in PostScript points, - psImageableLLY, // for PostScript output - psImageableURX, - psImageableURY; - GBool psCrop; // crop PS output to CropBox - GBool psExpandSmaller; // expand smaller pages to fill paper - GBool psShrinkLarger; // shrink larger pages to fit paper - GBool psCenter; // center pages on the paper - GBool psDuplex; // enable duplexing in PostScript? - PSLevel psLevel; // PostScript level to generate - GHash *psFonts; // PostScript font info, indexed by PDF - // font name [PSFontParam] - GList *psNamedFonts16; // named 16-bit fonts [PSFontParam] - GList *psFonts16; // generic 16-bit fonts [PSFontParam] - GBool psEmbedType1; // embed Type 1 fonts? - GBool psEmbedTrueType; // embed TrueType fonts? - GBool psEmbedCIDPostScript; // embed CID PostScript fonts? - GBool psEmbedCIDTrueType; // embed CID TrueType fonts? - GBool psOPI; // generate PostScript OPI comments? - GBool psASCIIHex; // use ASCIIHex instead of ASCII85? - GString *textEncoding; // encoding (unicodeMap) to use for text - // output - EndOfLineKind textEOL; // type of EOL marker to use for text - // output - GBool textPageBreaks; // insert end-of-page markers? - GBool textKeepTinyChars; // keep all characters in text output - GList *fontDirs; // list of font dirs [GString] - GString *initialZoom; // initial zoom level - GBool continuousView; // continuous view mode - GBool enableT1lib; // t1lib enable flag - GBool enableFreeType; // FreeType enable flag - GBool antialias; // anti-aliasing enable flag - GString *urlCommand; // command executed for URL links - GString *movieCommand; // command executed for movie annotations - GBool mapNumericCharNames; // map numeric char names (from font subsets)? - GBool printCommands; // print the drawing commands - GBool errQuiet; // suppress error messages? - - CharCodeToUnicodeCache *cidToUnicodeCache; - CharCodeToUnicodeCache *unicodeToUnicodeCache; - UnicodeMapCache *unicodeMapCache; - CMapCache *cMapCache; - -#ifdef ENABLE_PLUGINS - GList *plugins; // list of plugins [Plugin] - GList *securityHandlers; // list of loaded security handlers - // [XpdfSecurityHandler] -#endif - -#if MULTITHREADED - GMutex mutex; - GMutex unicodeMapCacheMutex; - GMutex cMapCacheMutex; -#endif -}; - -#endif diff --git a/pdftops/JArithmeticDecoder.cxx b/pdftops/JArithmeticDecoder.cxx deleted file mode 100644 index ec0778e64..000000000 --- a/pdftops/JArithmeticDecoder.cxx +++ /dev/null @@ -1,322 +0,0 @@ -//======================================================================== -// -// JArithmeticDecoder.cc -// -// Copyright 2002-2004 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include "Object.h" -#include "Stream.h" -#include "JArithmeticDecoder.h" - -//------------------------------------------------------------------------ -// JArithmeticDecoderStates -//------------------------------------------------------------------------ - -JArithmeticDecoderStats::JArithmeticDecoderStats(int contextSizeA) { - contextSize = contextSizeA; - cxTab = (Guchar *)gmallocn(contextSize, sizeof(Guchar)); - reset(); -} - -JArithmeticDecoderStats::~JArithmeticDecoderStats() { - gfree(cxTab); -} - -JArithmeticDecoderStats *JArithmeticDecoderStats::copy() { - JArithmeticDecoderStats *stats; - - stats = new JArithmeticDecoderStats(contextSize); - memcpy(stats->cxTab, cxTab, contextSize); - return stats; -} - -void JArithmeticDecoderStats::reset() { - memset(cxTab, 0, contextSize); -} - -void JArithmeticDecoderStats::copyFrom(JArithmeticDecoderStats *stats) { - memcpy(cxTab, stats->cxTab, contextSize); -} - -void JArithmeticDecoderStats::setEntry(Guint cx, int i, int mps) { - cxTab[cx] = (i << 1) + mps; -} - -//------------------------------------------------------------------------ -// JArithmeticDecoder -//------------------------------------------------------------------------ - -Guint JArithmeticDecoder::qeTab[47] = { - 0x56010000, 0x34010000, 0x18010000, 0x0AC10000, - 0x05210000, 0x02210000, 0x56010000, 0x54010000, - 0x48010000, 0x38010000, 0x30010000, 0x24010000, - 0x1C010000, 0x16010000, 0x56010000, 0x54010000, - 0x51010000, 0x48010000, 0x38010000, 0x34010000, - 0x30010000, 0x28010000, 0x24010000, 0x22010000, - 0x1C010000, 0x18010000, 0x16010000, 0x14010000, - 0x12010000, 0x11010000, 0x0AC10000, 0x09C10000, - 0x08A10000, 0x05210000, 0x04410000, 0x02A10000, - 0x02210000, 0x01410000, 0x01110000, 0x00850000, - 0x00490000, 0x00250000, 0x00150000, 0x00090000, - 0x00050000, 0x00010000, 0x56010000 -}; - -int JArithmeticDecoder::nmpsTab[47] = { - 1, 2, 3, 4, 5, 38, 7, 8, 9, 10, 11, 12, 13, 29, 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, 45, 46 -}; - -int JArithmeticDecoder::nlpsTab[47] = { - 1, 6, 9, 12, 29, 33, 6, 14, 14, 14, 17, 18, 20, 21, 14, 14, - 15, 16, 17, 18, 19, 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, 46 -}; - -int JArithmeticDecoder::switchTab[47] = { - 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -JArithmeticDecoder::JArithmeticDecoder() { - str = NULL; - dataLen = 0; - limitStream = gFalse; -} - -inline Guint JArithmeticDecoder::readByte() { - if (limitStream) { - --dataLen; - if (dataLen < 0) { - return 0xff; - } - } - return (Guint)str->getChar() & 0xff; -} - -JArithmeticDecoder::~JArithmeticDecoder() { - cleanup(); -} - -void JArithmeticDecoder::start() { - buf0 = readByte(); - buf1 = readByte(); - - // INITDEC - c = (buf0 ^ 0xff) << 16; - byteIn(); - c <<= 7; - ct -= 7; - a = 0x80000000; -} - -void JArithmeticDecoder::restart(int dataLenA) { - int oldDataLen; - - oldDataLen = dataLen; - dataLen = dataLenA; - if (oldDataLen == -1) { - buf1 = readByte(); - } else if (oldDataLen <= -2) { - buf0 = readByte(); - buf1 = readByte(); - } -} - -void JArithmeticDecoder::cleanup() { - if (limitStream) { - while (dataLen > 0) { - buf0 = buf1; - buf1 = readByte(); - } - } -} - -int JArithmeticDecoder::decodeBit(Guint context, - JArithmeticDecoderStats *stats) { - int bit; - Guint qe; - int iCX, mpsCX; - - iCX = stats->cxTab[context] >> 1; - mpsCX = stats->cxTab[context] & 1; - qe = qeTab[iCX]; - a -= qe; - if (c < a) { - if (a & 0x80000000) { - bit = mpsCX; - } else { - // MPS_EXCHANGE - if (a < qe) { - bit = 1 - mpsCX; - if (switchTab[iCX]) { - stats->cxTab[context] = (nlpsTab[iCX] << 1) | (1 - mpsCX); - } else { - stats->cxTab[context] = (nlpsTab[iCX] << 1) | mpsCX; - } - } else { - bit = mpsCX; - stats->cxTab[context] = (nmpsTab[iCX] << 1) | mpsCX; - } - // RENORMD - do { - if (ct == 0) { - byteIn(); - } - a <<= 1; - c <<= 1; - --ct; - } while (!(a & 0x80000000)); - } - } else { - c -= a; - // LPS_EXCHANGE - if (a < qe) { - bit = mpsCX; - stats->cxTab[context] = (nmpsTab[iCX] << 1) | mpsCX; - } else { - bit = 1 - mpsCX; - if (switchTab[iCX]) { - stats->cxTab[context] = (nlpsTab[iCX] << 1) | (1 - mpsCX); - } else { - stats->cxTab[context] = (nlpsTab[iCX] << 1) | mpsCX; - } - } - a = qe; - // RENORMD - do { - if (ct == 0) { - byteIn(); - } - a <<= 1; - c <<= 1; - --ct; - } while (!(a & 0x80000000)); - } - return bit; -} - -int JArithmeticDecoder::decodeByte(Guint context, - JArithmeticDecoderStats *stats) { - int byte; - int i; - - byte = 0; - for (i = 0; i < 8; ++i) { - byte = (byte << 1) | decodeBit(context, stats); - } - return byte; -} - -GBool JArithmeticDecoder::decodeInt(int *x, JArithmeticDecoderStats *stats) { - int s; - Guint v; - int i; - - prev = 1; - s = decodeIntBit(stats); - if (decodeIntBit(stats)) { - if (decodeIntBit(stats)) { - if (decodeIntBit(stats)) { - if (decodeIntBit(stats)) { - if (decodeIntBit(stats)) { - v = 0; - for (i = 0; i < 32; ++i) { - v = (v << 1) | decodeIntBit(stats); - } - v += 4436; - } else { - v = 0; - for (i = 0; i < 12; ++i) { - v = (v << 1) | decodeIntBit(stats); - } - v += 340; - } - } else { - v = 0; - for (i = 0; i < 8; ++i) { - v = (v << 1) | decodeIntBit(stats); - } - v += 84; - } - } else { - v = 0; - for (i = 0; i < 6; ++i) { - v = (v << 1) | decodeIntBit(stats); - } - v += 20; - } - } else { - v = decodeIntBit(stats); - v = (v << 1) | decodeIntBit(stats); - v = (v << 1) | decodeIntBit(stats); - v = (v << 1) | decodeIntBit(stats); - v += 4; - } - } else { - v = decodeIntBit(stats); - v = (v << 1) | decodeIntBit(stats); - } - - if (s) { - if (v == 0) { - return gFalse; - } - *x = -(int)v; - } else { - *x = (int)v; - } - return gTrue; -} - -int JArithmeticDecoder::decodeIntBit(JArithmeticDecoderStats *stats) { - int bit; - - bit = decodeBit(prev, stats); - if (prev < 0x100) { - prev = (prev << 1) | bit; - } else { - prev = (((prev << 1) | bit) & 0x1ff) | 0x100; - } - return bit; -} - -Guint JArithmeticDecoder::decodeIAID(Guint codeLen, - JArithmeticDecoderStats *stats) { - Guint i; - int bit; - - prev = 1; - for (i = 0; i < codeLen; ++i) { - bit = decodeBit(prev, stats); - prev = (prev << 1) | bit; - } - return prev - (1 << codeLen); -} - -void JArithmeticDecoder::byteIn() { - if (buf0 == 0xff) { - if (buf1 > 0x8f) { - ct = 8; - } else { - buf0 = buf1; - buf1 = readByte(); - c = c + 0xfe00 - (buf0 << 9); - ct = 7; - } - } else { - buf0 = buf1; - buf1 = readByte(); - c = c + 0xff00 - (buf0 << 8); - ct = 8; - } -} diff --git a/pdftops/JArithmeticDecoder.h b/pdftops/JArithmeticDecoder.h deleted file mode 100644 index 201e36d2c..000000000 --- a/pdftops/JArithmeticDecoder.h +++ /dev/null @@ -1,109 +0,0 @@ -//======================================================================== -// -// JArithmeticDecoder.h -// -// Arithmetic decoder used by the JBIG2 and JPEG2000 decoders. -// -// Copyright 2002-2004 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef JARITHMETICDECODER_H -#define JARITHMETICDECODER_H - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "gtypes.h" - -class Stream; - -//------------------------------------------------------------------------ -// JArithmeticDecoderStats -//------------------------------------------------------------------------ - -class JArithmeticDecoderStats { -public: - - JArithmeticDecoderStats(int contextSizeA); - ~JArithmeticDecoderStats(); - JArithmeticDecoderStats *copy(); - void reset(); - int getContextSize() { return contextSize; } - void copyFrom(JArithmeticDecoderStats *stats); - void setEntry(Guint cx, int i, int mps); - -private: - - Guchar *cxTab; // cxTab[cx] = (i[cx] << 1) + mps[cx] - int contextSize; - - friend class JArithmeticDecoder; -}; - -//------------------------------------------------------------------------ -// JArithmeticDecoder -//------------------------------------------------------------------------ - -class JArithmeticDecoder { -public: - - JArithmeticDecoder(); - ~JArithmeticDecoder(); - - void setStream(Stream *strA) - { str = strA; dataLen = 0; limitStream = gFalse; } - void setStream(Stream *strA, int dataLenA) - { str = strA; dataLen = dataLenA; limitStream = gTrue; } - - // Start decoding on a new stream. This fills the byte buffers and - // runs INITDEC. - void start(); - - // Restart decoding on an interrupted stream. This refills the - // buffers if needed, but does not run INITDEC. (This is used in - // JPEG 2000 streams when codeblock data is split across multiple - // packets/layers.) - void restart(int dataLenA); - - // Read any leftover data in the stream. - void cleanup(); - - // Decode one bit. - int decodeBit(Guint context, JArithmeticDecoderStats *stats); - - // Decode eight bits. - int decodeByte(Guint context, JArithmeticDecoderStats *stats); - - // Returns false for OOB, otherwise sets *<x> and returns true. - GBool decodeInt(int *x, JArithmeticDecoderStats *stats); - - Guint decodeIAID(Guint codeLen, - JArithmeticDecoderStats *stats); - -private: - - Guint readByte(); - int decodeIntBit(JArithmeticDecoderStats *stats); - void byteIn(); - - static Guint qeTab[47]; - static int nmpsTab[47]; - static int nlpsTab[47]; - static int switchTab[47]; - - Guint buf0, buf1; - Guint c, a; - int ct; - - Guint prev; // for the integer decoder - - Stream *str; - int dataLen; - GBool limitStream; -}; - -#endif diff --git a/pdftops/JBIG2Stream.cxx b/pdftops/JBIG2Stream.cxx deleted file mode 100644 index 38cbb9ca1..000000000 --- a/pdftops/JBIG2Stream.cxx +++ /dev/null @@ -1,3403 +0,0 @@ -//======================================================================== -// -// JBIG2Stream.cc -// -// Copyright 2002-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include <stdlib.h> -#include <limits.h> -#include "GList.h" -#include "Error.h" -#include "JArithmeticDecoder.h" -#include "JBIG2Stream.h" - -//~ share these tables -#include "Stream-CCITT.h" - -//------------------------------------------------------------------------ - -static int contextSize[4] = { 16, 13, 10, 10 }; -static int refContextSize[2] = { 13, 10 }; - -//------------------------------------------------------------------------ -// JBIG2HuffmanTable -//------------------------------------------------------------------------ - -#define jbig2HuffmanLOW 0xfffffffd -#define jbig2HuffmanOOB 0xfffffffe -#define jbig2HuffmanEOT 0xffffffff - -struct JBIG2HuffmanTable { - int val; - Guint prefixLen; - Guint rangeLen; // can also be LOW, OOB, or EOT - Guint prefix; -}; - -JBIG2HuffmanTable huffTableA[] = { - { 0, 1, 4, 0x000 }, - { 16, 2, 8, 0x002 }, - { 272, 3, 16, 0x006 }, - { 65808, 3, 32, 0x007 }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -JBIG2HuffmanTable huffTableB[] = { - { 0, 1, 0, 0x000 }, - { 1, 2, 0, 0x002 }, - { 2, 3, 0, 0x006 }, - { 3, 4, 3, 0x00e }, - { 11, 5, 6, 0x01e }, - { 75, 6, 32, 0x03e }, - { 0, 6, jbig2HuffmanOOB, 0x03f }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -JBIG2HuffmanTable huffTableC[] = { - { 0, 1, 0, 0x000 }, - { 1, 2, 0, 0x002 }, - { 2, 3, 0, 0x006 }, - { 3, 4, 3, 0x00e }, - { 11, 5, 6, 0x01e }, - { 0, 6, jbig2HuffmanOOB, 0x03e }, - { 75, 7, 32, 0x0fe }, - { -256, 8, 8, 0x0fe }, - { -257, 8, jbig2HuffmanLOW, 0x0ff }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -JBIG2HuffmanTable huffTableD[] = { - { 1, 1, 0, 0x000 }, - { 2, 2, 0, 0x002 }, - { 3, 3, 0, 0x006 }, - { 4, 4, 3, 0x00e }, - { 12, 5, 6, 0x01e }, - { 76, 5, 32, 0x01f }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -JBIG2HuffmanTable huffTableE[] = { - { 1, 1, 0, 0x000 }, - { 2, 2, 0, 0x002 }, - { 3, 3, 0, 0x006 }, - { 4, 4, 3, 0x00e }, - { 12, 5, 6, 0x01e }, - { 76, 6, 32, 0x03e }, - { -255, 7, 8, 0x07e }, - { -256, 7, jbig2HuffmanLOW, 0x07f }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -JBIG2HuffmanTable huffTableF[] = { - { 0, 2, 7, 0x000 }, - { 128, 3, 7, 0x002 }, - { 256, 3, 8, 0x003 }, - { -1024, 4, 9, 0x008 }, - { -512, 4, 8, 0x009 }, - { -256, 4, 7, 0x00a }, - { -32, 4, 5, 0x00b }, - { 512, 4, 9, 0x00c }, - { 1024, 4, 10, 0x00d }, - { -2048, 5, 10, 0x01c }, - { -128, 5, 6, 0x01d }, - { -64, 5, 5, 0x01e }, - { -2049, 6, jbig2HuffmanLOW, 0x03e }, - { 2048, 6, 32, 0x03f }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -JBIG2HuffmanTable huffTableG[] = { - { -512, 3, 8, 0x000 }, - { 256, 3, 8, 0x001 }, - { 512, 3, 9, 0x002 }, - { 1024, 3, 10, 0x003 }, - { -1024, 4, 9, 0x008 }, - { -256, 4, 7, 0x009 }, - { -32, 4, 5, 0x00a }, - { 0, 4, 5, 0x00b }, - { 128, 4, 7, 0x00c }, - { -128, 5, 6, 0x01a }, - { -64, 5, 5, 0x01b }, - { 32, 5, 5, 0x01c }, - { 64, 5, 6, 0x01d }, - { -1025, 5, jbig2HuffmanLOW, 0x01e }, - { 2048, 5, 32, 0x01f }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -JBIG2HuffmanTable huffTableH[] = { - { 0, 2, 1, 0x000 }, - { 0, 2, jbig2HuffmanOOB, 0x001 }, - { 4, 3, 4, 0x004 }, - { -1, 4, 0, 0x00a }, - { 22, 4, 4, 0x00b }, - { 38, 4, 5, 0x00c }, - { 2, 5, 0, 0x01a }, - { 70, 5, 6, 0x01b }, - { 134, 5, 7, 0x01c }, - { 3, 6, 0, 0x03a }, - { 20, 6, 1, 0x03b }, - { 262, 6, 7, 0x03c }, - { 646, 6, 10, 0x03d }, - { -2, 7, 0, 0x07c }, - { 390, 7, 8, 0x07d }, - { -15, 8, 3, 0x0fc }, - { -5, 8, 1, 0x0fd }, - { -7, 9, 1, 0x1fc }, - { -3, 9, 0, 0x1fd }, - { -16, 9, jbig2HuffmanLOW, 0x1fe }, - { 1670, 9, 32, 0x1ff }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -JBIG2HuffmanTable huffTableI[] = { - { 0, 2, jbig2HuffmanOOB, 0x000 }, - { -1, 3, 1, 0x002 }, - { 1, 3, 1, 0x003 }, - { 7, 3, 5, 0x004 }, - { -3, 4, 1, 0x00a }, - { 43, 4, 5, 0x00b }, - { 75, 4, 6, 0x00c }, - { 3, 5, 1, 0x01a }, - { 139, 5, 7, 0x01b }, - { 267, 5, 8, 0x01c }, - { 5, 6, 1, 0x03a }, - { 39, 6, 2, 0x03b }, - { 523, 6, 8, 0x03c }, - { 1291, 6, 11, 0x03d }, - { -5, 7, 1, 0x07c }, - { 779, 7, 9, 0x07d }, - { -31, 8, 4, 0x0fc }, - { -11, 8, 2, 0x0fd }, - { -15, 9, 2, 0x1fc }, - { -7, 9, 1, 0x1fd }, - { -32, 9, jbig2HuffmanLOW, 0x1fe }, - { 3339, 9, 32, 0x1ff }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -JBIG2HuffmanTable huffTableJ[] = { - { -2, 2, 2, 0x000 }, - { 6, 2, 6, 0x001 }, - { 0, 2, jbig2HuffmanOOB, 0x002 }, - { -3, 5, 0, 0x018 }, - { 2, 5, 0, 0x019 }, - { 70, 5, 5, 0x01a }, - { 3, 6, 0, 0x036 }, - { 102, 6, 5, 0x037 }, - { 134, 6, 6, 0x038 }, - { 198, 6, 7, 0x039 }, - { 326, 6, 8, 0x03a }, - { 582, 6, 9, 0x03b }, - { 1094, 6, 10, 0x03c }, - { -21, 7, 4, 0x07a }, - { -4, 7, 0, 0x07b }, - { 4, 7, 0, 0x07c }, - { 2118, 7, 11, 0x07d }, - { -5, 8, 0, 0x0fc }, - { 5, 8, 0, 0x0fd }, - { -22, 8, jbig2HuffmanLOW, 0x0fe }, - { 4166, 8, 32, 0x0ff }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -JBIG2HuffmanTable huffTableK[] = { - { 1, 1, 0, 0x000 }, - { 2, 2, 1, 0x002 }, - { 4, 4, 0, 0x00c }, - { 5, 4, 1, 0x00d }, - { 7, 5, 1, 0x01c }, - { 9, 5, 2, 0x01d }, - { 13, 6, 2, 0x03c }, - { 17, 7, 2, 0x07a }, - { 21, 7, 3, 0x07b }, - { 29, 7, 4, 0x07c }, - { 45, 7, 5, 0x07d }, - { 77, 7, 6, 0x07e }, - { 141, 7, 32, 0x07f }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -JBIG2HuffmanTable huffTableL[] = { - { 1, 1, 0, 0x000 }, - { 2, 2, 0, 0x002 }, - { 3, 3, 1, 0x006 }, - { 5, 5, 0, 0x01c }, - { 6, 5, 1, 0x01d }, - { 8, 6, 1, 0x03c }, - { 10, 7, 0, 0x07a }, - { 11, 7, 1, 0x07b }, - { 13, 7, 2, 0x07c }, - { 17, 7, 3, 0x07d }, - { 25, 7, 4, 0x07e }, - { 41, 8, 5, 0x0fe }, - { 73, 8, 32, 0x0ff }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -JBIG2HuffmanTable huffTableM[] = { - { 1, 1, 0, 0x000 }, - { 2, 3, 0, 0x004 }, - { 7, 3, 3, 0x005 }, - { 3, 4, 0, 0x00c }, - { 5, 4, 1, 0x00d }, - { 4, 5, 0, 0x01c }, - { 15, 6, 1, 0x03a }, - { 17, 6, 2, 0x03b }, - { 21, 6, 3, 0x03c }, - { 29, 6, 4, 0x03d }, - { 45, 6, 5, 0x03e }, - { 77, 7, 6, 0x07e }, - { 141, 7, 32, 0x07f }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -JBIG2HuffmanTable huffTableN[] = { - { 0, 1, 0, 0x000 }, - { -2, 3, 0, 0x004 }, - { -1, 3, 0, 0x005 }, - { 1, 3, 0, 0x006 }, - { 2, 3, 0, 0x007 }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -JBIG2HuffmanTable huffTableO[] = { - { 0, 1, 0, 0x000 }, - { -1, 3, 0, 0x004 }, - { 1, 3, 0, 0x005 }, - { -2, 4, 0, 0x00c }, - { 2, 4, 0, 0x00d }, - { -4, 5, 1, 0x01c }, - { 3, 5, 1, 0x01d }, - { -8, 6, 2, 0x03c }, - { 5, 6, 2, 0x03d }, - { -24, 7, 4, 0x07c }, - { 9, 7, 4, 0x07d }, - { -25, 7, jbig2HuffmanLOW, 0x07e }, - { 25, 7, 32, 0x07f }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -//------------------------------------------------------------------------ -// JBIG2HuffmanDecoder -//------------------------------------------------------------------------ - -class JBIG2HuffmanDecoder { -public: - - JBIG2HuffmanDecoder(); - ~JBIG2HuffmanDecoder(); - void setStream(Stream *strA) { str = strA; } - - void reset(); - - // Returns false for OOB, otherwise sets *<x> and returns true. - GBool decodeInt(int *x, JBIG2HuffmanTable *table); - - Guint readBits(Guint n); - Guint readBit(); - - // Sort the table by prefix length and assign prefix values. - void buildTable(JBIG2HuffmanTable *table, Guint len); - -private: - - Stream *str; - Guint buf; - Guint bufLen; -}; - -JBIG2HuffmanDecoder::JBIG2HuffmanDecoder() { - str = NULL; - reset(); -} - -JBIG2HuffmanDecoder::~JBIG2HuffmanDecoder() { -} - -void JBIG2HuffmanDecoder::reset() { - buf = 0; - bufLen = 0; -} - -//~ optimize this -GBool JBIG2HuffmanDecoder::decodeInt(int *x, JBIG2HuffmanTable *table) { - Guint i, len, prefix; - - i = 0; - len = 0; - prefix = 0; - while (table[i].rangeLen != jbig2HuffmanEOT) { - while (len < table[i].prefixLen) { - prefix = (prefix << 1) | readBit(); - ++len; - } - if (prefix == table[i].prefix) { - if (table[i].rangeLen == jbig2HuffmanOOB) { - return gFalse; - } - if (table[i].rangeLen == jbig2HuffmanLOW) { - *x = table[i].val - readBits(32); - } else if (table[i].rangeLen > 0) { - *x = table[i].val + readBits(table[i].rangeLen); - } else { - *x = table[i].val; - } - return gTrue; - } - ++i; - } - return gFalse; -} - -Guint JBIG2HuffmanDecoder::readBits(Guint n) { - Guint x, mask, nLeft; - - mask = (n == 32) ? 0xffffffff : ((1 << n) - 1); - if (bufLen >= n) { - x = (buf >> (bufLen - n)) & mask; - bufLen -= n; - } else { - x = buf & ((1 << bufLen) - 1); - nLeft = n - bufLen; - bufLen = 0; - while (nLeft >= 8) { - x = (x << 8) | (str->getChar() & 0xff); - nLeft -= 8; - } - if (nLeft > 0) { - buf = str->getChar(); - bufLen = 8 - nLeft; - x = (x << nLeft) | ((buf >> bufLen) & ((1 << nLeft) - 1)); - } - } - return x; -} - -Guint JBIG2HuffmanDecoder::readBit() { - if (bufLen == 0) { - buf = str->getChar(); - bufLen = 8; - } - --bufLen; - return (buf >> bufLen) & 1; -} - -void JBIG2HuffmanDecoder::buildTable(JBIG2HuffmanTable *table, Guint len) { - Guint i, j, k, prefix; - JBIG2HuffmanTable tab; - - // stable selection sort: - // - entries with prefixLen > 0, in ascending prefixLen order - // - entry with prefixLen = 0, rangeLen = EOT - // - all other entries with prefixLen = 0 - // (on entry, table[len] has prefixLen = 0, rangeLen = EOT) - for (i = 0; i < len; ++i) { - for (j = i; j < len && table[j].prefixLen == 0; ++j) ; - if (j == len) { - break; - } - for (k = j + 1; k < len; ++k) { - if (table[k].prefixLen > 0 && - table[k].prefixLen < table[j].prefixLen) { - j = k; - } - } - if (j != i) { - tab = table[j]; - for (k = j; k > i; --k) { - table[k] = table[k - 1]; - } - table[i] = tab; - } - } - table[i] = table[len]; - - // assign prefixes - i = 0; - prefix = 0; - table[i++].prefix = prefix++; - for (; table[i].rangeLen != jbig2HuffmanEOT; ++i) { - prefix <<= table[i].prefixLen - table[i-1].prefixLen; - table[i].prefix = prefix++; - } -} - -//------------------------------------------------------------------------ -// JBIG2MMRDecoder -//------------------------------------------------------------------------ - -class JBIG2MMRDecoder { -public: - - JBIG2MMRDecoder(); - ~JBIG2MMRDecoder(); - void setStream(Stream *strA) { str = strA; } - void reset(); - int get2DCode(); - int getBlackCode(); - int getWhiteCode(); - Guint get24Bits(); - void skipTo(Guint length); - -private: - - Stream *str; - Guint buf; - Guint bufLen; - Guint nBytesRead; -}; - -JBIG2MMRDecoder::JBIG2MMRDecoder() { - str = NULL; - reset(); -} - -JBIG2MMRDecoder::~JBIG2MMRDecoder() { -} - -void JBIG2MMRDecoder::reset() { - buf = 0; - bufLen = 0; - nBytesRead = 0; -} - -int JBIG2MMRDecoder::get2DCode() { - CCITTCode *p; - - if (bufLen == 0) { - buf = str->getChar() & 0xff; - bufLen = 8; - ++nBytesRead; - p = &twoDimTab1[(buf >> 1) & 0x7f]; - } else if (bufLen == 8) { - p = &twoDimTab1[(buf >> 1) & 0x7f]; - } else { - p = &twoDimTab1[(buf << (7 - bufLen)) & 0x7f]; - if (p->bits < 0 || p->bits > (int)bufLen) { - buf = (buf << 8) | (str->getChar() & 0xff); - bufLen += 8; - ++nBytesRead; - p = &twoDimTab1[(buf >> (bufLen - 7)) & 0x7f]; - } - } - if (p->bits < 0) { - error(str->getPos(), "Bad two dim code in JBIG2 MMR stream"); - return 0; - } - bufLen -= p->bits; - return p->n; -} - -int JBIG2MMRDecoder::getWhiteCode() { - CCITTCode *p; - Guint code; - - if (bufLen == 0) { - buf = str->getChar() & 0xff; - bufLen = 8; - ++nBytesRead; - } - while (1) { - if (bufLen >= 7 && ((buf >> (bufLen - 7)) & 0x7f) == 0) { - if (bufLen <= 12) { - code = buf << (12 - bufLen); - } else { - code = buf >> (bufLen - 12); - } - p = &whiteTab1[code & 0x1f]; - } else { - if (bufLen <= 9) { - code = buf << (9 - bufLen); - } else { - code = buf >> (bufLen - 9); - } - p = &whiteTab2[code & 0x1ff]; - } - if (p->bits > 0 && p->bits <= (int)bufLen) { - bufLen -= p->bits; - return p->n; - } - if (bufLen >= 12) { - break; - } - buf = (buf << 8) | (str->getChar() & 0xff); - bufLen += 8; - ++nBytesRead; - } - error(str->getPos(), "Bad white code in JBIG2 MMR stream"); - // eat a bit and return a positive number so that the caller doesn't - // go into an infinite loop - --bufLen; - return 1; -} - -int JBIG2MMRDecoder::getBlackCode() { - CCITTCode *p; - Guint code; - - if (bufLen == 0) { - buf = str->getChar() & 0xff; - bufLen = 8; - ++nBytesRead; - } - while (1) { - if (bufLen >= 6 && ((buf >> (bufLen - 6)) & 0x3f) == 0) { - if (bufLen <= 13) { - code = buf << (13 - bufLen); - } else { - code = buf >> (bufLen - 13); - } - p = &blackTab1[code & 0x7f]; - } else if (bufLen >= 4 && ((buf >> (bufLen - 4)) & 0x0f) == 0) { - if (bufLen <= 12) { - code = buf << (12 - bufLen); - } else { - code = buf >> (bufLen - 12); - } - p = &blackTab2[(code & 0xff) - 64]; - } else { - if (bufLen <= 6) { - code = buf << (6 - bufLen); - } else { - code = buf >> (bufLen - 6); - } - p = &blackTab3[code & 0x3f]; - } - if (p->bits > 0 && p->bits <= (int)bufLen) { - bufLen -= p->bits; - return p->n; - } - if (bufLen >= 13) { - break; - } - buf = (buf << 8) | (str->getChar() & 0xff); - bufLen += 8; - ++nBytesRead; - } - error(str->getPos(), "Bad black code in JBIG2 MMR stream"); - // eat a bit and return a positive number so that the caller doesn't - // go into an infinite loop - --bufLen; - return 1; -} - -Guint JBIG2MMRDecoder::get24Bits() { - while (bufLen < 24) { - buf = (buf << 8) | (str->getChar() & 0xff); - bufLen += 8; - ++nBytesRead; - } - return (buf >> (bufLen - 24)) & 0xffffff; -} - -void JBIG2MMRDecoder::skipTo(Guint length) { - while (nBytesRead < length) { - str->getChar(); - ++nBytesRead; - } -} - -//------------------------------------------------------------------------ -// JBIG2Segment -//------------------------------------------------------------------------ - -enum JBIG2SegmentType { - jbig2SegBitmap, - jbig2SegSymbolDict, - jbig2SegPatternDict, - jbig2SegCodeTable -}; - -class JBIG2Segment { -public: - - JBIG2Segment(Guint segNumA) { segNum = segNumA; } - virtual ~JBIG2Segment() {} - void setSegNum(Guint segNumA) { segNum = segNumA; } - Guint getSegNum() { return segNum; } - virtual JBIG2SegmentType getType() = 0; - -private: - - Guint segNum; -}; - -//------------------------------------------------------------------------ -// JBIG2Bitmap -//------------------------------------------------------------------------ - -struct JBIG2BitmapPtr { - Guchar *p; - int shift; - int x; -}; - -class JBIG2Bitmap: public JBIG2Segment { -public: - - JBIG2Bitmap(Guint segNumA, int wA, int hA); - virtual ~JBIG2Bitmap(); - virtual JBIG2SegmentType getType() { return jbig2SegBitmap; } - JBIG2Bitmap *copy() { return new JBIG2Bitmap(0, this); } - JBIG2Bitmap *getSlice(Guint x, Guint y, Guint wA, Guint hA); - void expand(int newH, Guint pixel); - void clearToZero(); - void clearToOne(); - int getWidth() { return w; } - int getHeight() { return h; } - int getPixel(int x, int y) - { return (x < 0 || x >= w || y < 0 || y >= h) ? 0 : - (data[y * line + (x >> 3)] >> (7 - (x & 7))) & 1; } - void setPixel(int x, int y) - { data[y * line + (x >> 3)] |= 1 << (7 - (x & 7)); } - void clearPixel(int x, int y) - { data[y * line + (x >> 3)] &= 0x7f7f >> (x & 7); } - void getPixelPtr(int x, int y, JBIG2BitmapPtr *ptr); - int nextPixel(JBIG2BitmapPtr *ptr); - void duplicateRow(int yDest, int ySrc); - void combine(JBIG2Bitmap *bitmap, int x, int y, Guint combOp); - Guchar *getDataPtr() { return data; } - int getDataSize() { return h * line; } - -private: - - JBIG2Bitmap(Guint segNumA, JBIG2Bitmap *bitmap); - - int w, h, line; - Guchar *data; -}; - -JBIG2Bitmap::JBIG2Bitmap(Guint segNumA, int wA, int hA): - JBIG2Segment(segNumA) -{ - w = wA; - h = hA; - line = (wA + 7) >> 3; - if (w <= 0 || h <= 0 || line <= 0 || h >= (INT_MAX - 1) / line) { - data = NULL; - return; - } - // need to allocate one extra guard byte for use in combine() - data = (Guchar *)gmalloc(h * line + 1); - data[h * line] = 0; -} - -JBIG2Bitmap::JBIG2Bitmap(Guint segNumA, JBIG2Bitmap *bitmap): - JBIG2Segment(segNumA) -{ - w = bitmap->w; - h = bitmap->h; - line = bitmap->line; - if (w <= 0 || h <= 0 || line <= 0 || h >= (INT_MAX - 1) / line) { - data = NULL; - return; - } - // need to allocate one extra guard byte for use in combine() - data = (Guchar *)gmalloc(h * line + 1); - memcpy(data, bitmap->data, h * line); - data[h * line] = 0; -} - -JBIG2Bitmap::~JBIG2Bitmap() { - gfree(data); -} - -//~ optimize this -JBIG2Bitmap *JBIG2Bitmap::getSlice(Guint x, Guint y, Guint wA, Guint hA) { - JBIG2Bitmap *slice; - Guint xx, yy; - - slice = new JBIG2Bitmap(0, wA, hA); - slice->clearToZero(); - for (yy = 0; yy < hA; ++yy) { - for (xx = 0; xx < wA; ++xx) { - if (getPixel(x + xx, y + yy)) { - slice->setPixel(xx, yy); - } - } - } - return slice; -} - -void JBIG2Bitmap::expand(int newH, Guint pixel) { - if (newH <= h || line <= 0 || newH >= (INT_MAX - 1) / line) { - return; - } - // need to allocate one extra guard byte for use in combine() - data = (Guchar *)grealloc(data, newH * line + 1); - if (pixel) { - memset(data + h * line, 0xff, (newH - h) * line); - } else { - memset(data + h * line, 0x00, (newH - h) * line); - } - h = newH; - data[h * line] = 0; -} - -void JBIG2Bitmap::clearToZero() { - memset(data, 0, h * line); -} - -void JBIG2Bitmap::clearToOne() { - memset(data, 0xff, h * line); -} - -inline void JBIG2Bitmap::getPixelPtr(int x, int y, JBIG2BitmapPtr *ptr) { - if (y < 0 || y >= h || x >= w) { - ptr->p = NULL; - } else if (x < 0) { - ptr->p = &data[y * line]; - ptr->shift = 7; - ptr->x = x; - } else { - ptr->p = &data[y * line + (x >> 3)]; - ptr->shift = 7 - (x & 7); - ptr->x = x; - } -} - -inline int JBIG2Bitmap::nextPixel(JBIG2BitmapPtr *ptr) { - int pix; - - if (!ptr->p) { - pix = 0; - } else if (ptr->x < 0) { - ++ptr->x; - pix = 0; - } else { - pix = (*ptr->p >> ptr->shift) & 1; - if (++ptr->x == w) { - ptr->p = NULL; - } else if (ptr->shift == 0) { - ++ptr->p; - ptr->shift = 7; - } else { - --ptr->shift; - } - } - return pix; -} - -void JBIG2Bitmap::duplicateRow(int yDest, int ySrc) { - memcpy(data + yDest * line, data + ySrc * line, line); -} - -void JBIG2Bitmap::combine(JBIG2Bitmap *bitmap, int x, int y, - Guint combOp) { - int x0, x1, y0, y1, xx, yy; - Guchar *srcPtr, *destPtr; - Guint src0, src1, src, dest, s1, s2, m1, m2, m3; - GBool oneByte; - - if (y < 0) { - y0 = -y; - } else { - y0 = 0; - } - if (y + bitmap->h > h) { - y1 = h - y; - } else { - y1 = bitmap->h; - } - if (y0 >= y1) { - return; - } - - if (x >= 0) { - x0 = x & ~7; - } else { - x0 = 0; - } - x1 = x + bitmap->w; - if (x1 > w) { - x1 = w; - } - if (x0 >= x1) { - return; - } - - s1 = x & 7; - s2 = 8 - s1; - m1 = 0xff >> (x1 & 7); - m2 = 0xff << (((x1 & 7) == 0) ? 0 : 8 - (x1 & 7)); - m3 = (0xff >> s1) & m2; - - oneByte = x0 == ((x1 - 1) & ~7); - - for (yy = y0; yy < y1; ++yy) { - - // one byte per line -- need to mask both left and right side - if (oneByte) { - if (x >= 0) { - destPtr = data + (y + yy) * line + (x >> 3); - srcPtr = bitmap->data + yy * bitmap->line; - dest = *destPtr; - src1 = *srcPtr; - switch (combOp) { - case 0: // or - dest |= (src1 >> s1) & m2; - break; - case 1: // and - dest &= ((0xff00 | src1) >> s1) | m1; - break; - case 2: // xor - dest ^= (src1 >> s1) & m2; - break; - case 3: // xnor - dest ^= ((src1 ^ 0xff) >> s1) & m2; - break; - case 4: // replace - dest = (dest & ~m3) | ((src1 >> s1) & m3); - break; - } - *destPtr = dest; - } else { - destPtr = data + (y + yy) * line; - srcPtr = bitmap->data + yy * bitmap->line + (-x >> 3); - dest = *destPtr; - src1 = *srcPtr; - switch (combOp) { - case 0: // or - dest |= src1 & m2; - break; - case 1: // and - dest &= src1 | m1; - break; - case 2: // xor - dest ^= src1 & m2; - break; - case 3: // xnor - dest ^= (src1 ^ 0xff) & m2; - break; - case 4: // replace - dest = (src1 & m2) | (dest & m1); - break; - } - *destPtr = dest; - } - - // multiple bytes per line -- need to mask left side of left-most - // byte and right side of right-most byte - } else { - - // left-most byte - if (x >= 0) { - destPtr = data + (y + yy) * line + (x >> 3); - srcPtr = bitmap->data + yy * bitmap->line; - src1 = *srcPtr++; - dest = *destPtr; - switch (combOp) { - case 0: // or - dest |= src1 >> s1; - break; - case 1: // and - dest &= (0xff00 | src1) >> s1; - break; - case 2: // xor - dest ^= src1 >> s1; - break; - case 3: // xnor - dest ^= (src1 ^ 0xff) >> s1; - break; - case 4: // replace - dest = (dest & (0xff << s2)) | (src1 >> s1); - break; - } - *destPtr++ = dest; - xx = x0 + 8; - } else { - destPtr = data + (y + yy) * line; - srcPtr = bitmap->data + yy * bitmap->line + (-x >> 3); - src1 = *srcPtr++; - xx = x0; - } - - // middle bytes - for (; xx < x1 - 8; xx += 8) { - dest = *destPtr; - src0 = src1; - src1 = *srcPtr++; - src = (((src0 << 8) | src1) >> s1) & 0xff; - switch (combOp) { - case 0: // or - dest |= src; - break; - case 1: // and - dest &= src; - break; - case 2: // xor - dest ^= src; - break; - case 3: // xnor - dest ^= src ^ 0xff; - break; - case 4: // replace - dest = src; - break; - } - *destPtr++ = dest; - } - - // right-most byte - // note: this last byte (src1) may not actually be used, depending - // on the values of s1, m1, and m2 - and in fact, it may be off - // the edge of the source bitmap, which means we need to allocate - // one extra guard byte at the end of each bitmap - dest = *destPtr; - src0 = src1; - src1 = *srcPtr++; - src = (((src0 << 8) | src1) >> s1) & 0xff; - switch (combOp) { - case 0: // or - dest |= src & m2; - break; - case 1: // and - dest &= src | m1; - break; - case 2: // xor - dest ^= src & m2; - break; - case 3: // xnor - dest ^= (src ^ 0xff) & m2; - break; - case 4: // replace - dest = (src & m2) | (dest & m1); - break; - } - *destPtr = dest; - } - } -} - -//------------------------------------------------------------------------ -// JBIG2SymbolDict -//------------------------------------------------------------------------ - -class JBIG2SymbolDict: public JBIG2Segment { -public: - - JBIG2SymbolDict(Guint segNumA, Guint sizeA); - virtual ~JBIG2SymbolDict(); - virtual JBIG2SegmentType getType() { return jbig2SegSymbolDict; } - Guint getSize() { return size; } - void setBitmap(Guint idx, JBIG2Bitmap *bitmap) { bitmaps[idx] = bitmap; } - JBIG2Bitmap *getBitmap(Guint idx) { return bitmaps[idx]; } - void setGenericRegionStats(JArithmeticDecoderStats *stats) - { genericRegionStats = stats; } - void setRefinementRegionStats(JArithmeticDecoderStats *stats) - { refinementRegionStats = stats; } - JArithmeticDecoderStats *getGenericRegionStats() - { return genericRegionStats; } - JArithmeticDecoderStats *getRefinementRegionStats() - { return refinementRegionStats; } - -private: - - Guint size; - JBIG2Bitmap **bitmaps; - JArithmeticDecoderStats *genericRegionStats; - JArithmeticDecoderStats *refinementRegionStats; -}; - -JBIG2SymbolDict::JBIG2SymbolDict(Guint segNumA, Guint sizeA): - JBIG2Segment(segNumA) -{ - size = sizeA; - bitmaps = (JBIG2Bitmap **)gmallocn(size, sizeof(JBIG2Bitmap *)); - genericRegionStats = NULL; - refinementRegionStats = NULL; -} - -JBIG2SymbolDict::~JBIG2SymbolDict() { - Guint i; - - for (i = 0; i < size; ++i) { - delete bitmaps[i]; - } - gfree(bitmaps); - if (genericRegionStats) { - delete genericRegionStats; - } - if (refinementRegionStats) { - delete refinementRegionStats; - } -} - -//------------------------------------------------------------------------ -// JBIG2PatternDict -//------------------------------------------------------------------------ - -class JBIG2PatternDict: public JBIG2Segment { -public: - - JBIG2PatternDict(Guint segNumA, Guint sizeA); - virtual ~JBIG2PatternDict(); - virtual JBIG2SegmentType getType() { return jbig2SegPatternDict; } - Guint getSize() { return size; } - void setBitmap(Guint idx, JBIG2Bitmap *bitmap) { bitmaps[idx] = bitmap; } - JBIG2Bitmap *getBitmap(Guint idx) { return bitmaps[idx]; } - -private: - - Guint size; - JBIG2Bitmap **bitmaps; -}; - -JBIG2PatternDict::JBIG2PatternDict(Guint segNumA, Guint sizeA): - JBIG2Segment(segNumA) -{ - size = sizeA; - bitmaps = (JBIG2Bitmap **)gmallocn(size, sizeof(JBIG2Bitmap *)); -} - -JBIG2PatternDict::~JBIG2PatternDict() { - Guint i; - - for (i = 0; i < size; ++i) { - delete bitmaps[i]; - } - gfree(bitmaps); -} - -//------------------------------------------------------------------------ -// JBIG2CodeTable -//------------------------------------------------------------------------ - -class JBIG2CodeTable: public JBIG2Segment { -public: - - JBIG2CodeTable(Guint segNumA, JBIG2HuffmanTable *tableA); - virtual ~JBIG2CodeTable(); - virtual JBIG2SegmentType getType() { return jbig2SegCodeTable; } - JBIG2HuffmanTable *getHuffTable() { return table; } - -private: - - JBIG2HuffmanTable *table; -}; - -JBIG2CodeTable::JBIG2CodeTable(Guint segNumA, JBIG2HuffmanTable *tableA): - JBIG2Segment(segNumA) -{ - table = tableA; -} - -JBIG2CodeTable::~JBIG2CodeTable() { - gfree(table); -} - -//------------------------------------------------------------------------ -// JBIG2Stream -//------------------------------------------------------------------------ - -JBIG2Stream::JBIG2Stream(Stream *strA, Object *globalsStream): - FilterStream(strA) -{ - pageBitmap = NULL; - - arithDecoder = new JArithmeticDecoder(); - genericRegionStats = new JArithmeticDecoderStats(1 << 1); - refinementRegionStats = new JArithmeticDecoderStats(1 << 1); - iadhStats = new JArithmeticDecoderStats(1 << 9); - iadwStats = new JArithmeticDecoderStats(1 << 9); - iaexStats = new JArithmeticDecoderStats(1 << 9); - iaaiStats = new JArithmeticDecoderStats(1 << 9); - iadtStats = new JArithmeticDecoderStats(1 << 9); - iaitStats = new JArithmeticDecoderStats(1 << 9); - iafsStats = new JArithmeticDecoderStats(1 << 9); - iadsStats = new JArithmeticDecoderStats(1 << 9); - iardxStats = new JArithmeticDecoderStats(1 << 9); - iardyStats = new JArithmeticDecoderStats(1 << 9); - iardwStats = new JArithmeticDecoderStats(1 << 9); - iardhStats = new JArithmeticDecoderStats(1 << 9); - iariStats = new JArithmeticDecoderStats(1 << 9); - iaidStats = new JArithmeticDecoderStats(1 << 1); - huffDecoder = new JBIG2HuffmanDecoder(); - mmrDecoder = new JBIG2MMRDecoder(); - - segments = globalSegments = new GList(); - if (globalsStream->isStream()) { - curStr = globalsStream->getStream(); - curStr->reset(); - arithDecoder->setStream(curStr); - huffDecoder->setStream(curStr); - mmrDecoder->setStream(curStr); - readSegments(); - } - - segments = NULL; - curStr = NULL; - dataPtr = dataEnd = NULL; -} - -JBIG2Stream::~JBIG2Stream() { - delete arithDecoder; - delete genericRegionStats; - delete refinementRegionStats; - delete iadhStats; - delete iadwStats; - delete iaexStats; - delete iaaiStats; - delete iadtStats; - delete iaitStats; - delete iafsStats; - delete iadsStats; - delete iardxStats; - delete iardyStats; - delete iardwStats; - delete iardhStats; - delete iariStats; - delete iaidStats; - delete huffDecoder; - delete mmrDecoder; - if (pageBitmap) { - delete pageBitmap; - } - if (segments) { - deleteGList(segments, JBIG2Segment); - } - if (globalSegments) { - deleteGList(globalSegments, JBIG2Segment); - } - delete str; -} - -void JBIG2Stream::reset() { - if (pageBitmap) { - delete pageBitmap; - pageBitmap = NULL; - } - if (segments) { - deleteGList(segments, JBIG2Segment); - } - segments = new GList(); - - curStr = str; - curStr->reset(); - arithDecoder->setStream(curStr); - huffDecoder->setStream(curStr); - mmrDecoder->setStream(curStr); - readSegments(); - - if (pageBitmap) { - dataPtr = pageBitmap->getDataPtr(); - dataEnd = dataPtr + pageBitmap->getDataSize(); - } else { - dataPtr = NULL; - } -} - -int JBIG2Stream::getChar() { - if (dataPtr && dataPtr < dataEnd) { - return (*dataPtr++ ^ 0xff) & 0xff; - } - return EOF; -} - -int JBIG2Stream::lookChar() { - if (dataPtr && dataPtr < dataEnd) { - return (*dataPtr ^ 0xff) & 0xff; - } - return EOF; -} - -GString *JBIG2Stream::getPSFilter(int psLevel, char *indent) { - return NULL; -} - -GBool JBIG2Stream::isBinary(GBool last) { - return str->isBinary(gTrue); -} - -void JBIG2Stream::readSegments() { - Guint segNum, segFlags, segType, page, segLength; - Guint refFlags, nRefSegs; - Guint *refSegs; - int c1, c2, c3; - Guint i; - - while (readULong(&segNum)) { - - // segment header flags - if (!readUByte(&segFlags)) { - goto eofError1; - } - segType = segFlags & 0x3f; - - // referred-to segment count and retention flags - if (!readUByte(&refFlags)) { - goto eofError1; - } - nRefSegs = refFlags >> 5; - if (nRefSegs == 7) { - if ((c1 = curStr->getChar()) == EOF || - (c2 = curStr->getChar()) == EOF || - (c3 = curStr->getChar()) == EOF) { - goto eofError1; - } - refFlags = (refFlags << 24) | (c1 << 16) | (c2 << 8) | c3; - nRefSegs = refFlags & 0x1fffffff; - for (i = 0; i < (nRefSegs + 9) >> 3; ++i) { - c1 = curStr->getChar(); - } - } - - // referred-to segment numbers - refSegs = (Guint *)gmallocn(nRefSegs, sizeof(Guint)); - if (segNum <= 256) { - for (i = 0; i < nRefSegs; ++i) { - if (!readUByte(&refSegs[i])) { - goto eofError2; - } - } - } else if (segNum <= 65536) { - for (i = 0; i < nRefSegs; ++i) { - if (!readUWord(&refSegs[i])) { - goto eofError2; - } - } - } else { - for (i = 0; i < nRefSegs; ++i) { - if (!readULong(&refSegs[i])) { - goto eofError2; - } - } - } - - // segment page association - if (segFlags & 0x40) { - if (!readULong(&page)) { - goto eofError2; - } - } else { - if (!readUByte(&page)) { - goto eofError2; - } - } - - // segment data length - if (!readULong(&segLength)) { - goto eofError2; - } - - // read the segment data - switch (segType) { - case 0: - if (!readSymbolDictSeg(segNum, segLength, refSegs, nRefSegs)) { - goto syntaxError; - } - break; - case 4: - readTextRegionSeg(segNum, gFalse, gFalse, segLength, refSegs, nRefSegs); - break; - case 6: - readTextRegionSeg(segNum, gTrue, gFalse, segLength, refSegs, nRefSegs); - break; - case 7: - readTextRegionSeg(segNum, gTrue, gTrue, segLength, refSegs, nRefSegs); - break; - case 16: - readPatternDictSeg(segNum, segLength); - break; - case 20: - readHalftoneRegionSeg(segNum, gFalse, gFalse, segLength, - refSegs, nRefSegs); - break; - case 22: - readHalftoneRegionSeg(segNum, gTrue, gFalse, segLength, - refSegs, nRefSegs); - break; - case 23: - readHalftoneRegionSeg(segNum, gTrue, gTrue, segLength, - refSegs, nRefSegs); - break; - case 36: - readGenericRegionSeg(segNum, gFalse, gFalse, segLength); - break; - case 38: - readGenericRegionSeg(segNum, gTrue, gFalse, segLength); - break; - case 39: - readGenericRegionSeg(segNum, gTrue, gTrue, segLength); - break; - case 40: - readGenericRefinementRegionSeg(segNum, gFalse, gFalse, segLength, - refSegs, nRefSegs); - break; - case 42: - readGenericRefinementRegionSeg(segNum, gTrue, gFalse, segLength, - refSegs, nRefSegs); - break; - case 43: - readGenericRefinementRegionSeg(segNum, gTrue, gTrue, segLength, - refSegs, nRefSegs); - break; - case 48: - readPageInfoSeg(segLength); - break; - case 50: - readEndOfStripeSeg(segLength); - break; - case 52: - readProfilesSeg(segLength); - break; - case 53: - readCodeTableSeg(segNum, segLength); - break; - case 62: - readExtensionSeg(segLength); - break; - default: - error(getPos(), "Unknown segment type in JBIG2 stream"); - for (i = 0; i < segLength; ++i) { - if ((c1 = curStr->getChar()) == EOF) { - goto eofError2; - } - } - break; - } - - gfree(refSegs); - } - - return; - - syntaxError: - gfree(refSegs); - return; - - eofError2: - gfree(refSegs); - eofError1: - error(getPos(), "Unexpected EOF in JBIG2 stream"); -} - -GBool JBIG2Stream::readSymbolDictSeg(Guint segNum, Guint length, - Guint *refSegs, Guint nRefSegs) { - JBIG2SymbolDict *symbolDict; - JBIG2HuffmanTable *huffDHTable, *huffDWTable; - JBIG2HuffmanTable *huffBMSizeTable, *huffAggInstTable; - JBIG2Segment *seg; - GList *codeTables; - JBIG2SymbolDict *inputSymbolDict; - Guint flags, sdTemplate, sdrTemplate, huff, refAgg; - Guint huffDH, huffDW, huffBMSize, huffAggInst; - Guint contextUsed, contextRetained; - int sdATX[4], sdATY[4], sdrATX[2], sdrATY[2]; - Guint numExSyms, numNewSyms, numInputSyms, symCodeLen; - JBIG2Bitmap **bitmaps; - JBIG2Bitmap *collBitmap, *refBitmap; - Guint *symWidths; - Guint symHeight, symWidth, totalWidth, x, symID; - int dh, dw, refAggNum, refDX, refDY, bmSize; - GBool ex; - int run, cnt; - Guint i, j, k; - Guchar *p; - - // symbol dictionary flags - if (!readUWord(&flags)) { - goto eofError; - } - sdTemplate = (flags >> 10) & 3; - sdrTemplate = (flags >> 12) & 1; - huff = flags & 1; - refAgg = (flags >> 1) & 1; - huffDH = (flags >> 2) & 3; - huffDW = (flags >> 4) & 3; - huffBMSize = (flags >> 6) & 1; - huffAggInst = (flags >> 7) & 1; - contextUsed = (flags >> 8) & 1; - contextRetained = (flags >> 9) & 1; - - // symbol dictionary AT flags - if (!huff) { - if (sdTemplate == 0) { - if (!readByte(&sdATX[0]) || - !readByte(&sdATY[0]) || - !readByte(&sdATX[1]) || - !readByte(&sdATY[1]) || - !readByte(&sdATX[2]) || - !readByte(&sdATY[2]) || - !readByte(&sdATX[3]) || - !readByte(&sdATY[3])) { - goto eofError; - } - } else { - if (!readByte(&sdATX[0]) || - !readByte(&sdATY[0])) { - goto eofError; - } - } - } - - // symbol dictionary refinement AT flags - if (refAgg && !sdrTemplate) { - if (!readByte(&sdrATX[0]) || - !readByte(&sdrATY[0]) || - !readByte(&sdrATX[1]) || - !readByte(&sdrATY[1])) { - goto eofError; - } - } - - // SDNUMEXSYMS and SDNUMNEWSYMS - if (!readULong(&numExSyms) || !readULong(&numNewSyms)) { - goto eofError; - } - - // get referenced segments: input symbol dictionaries and code tables - codeTables = new GList(); - numInputSyms = 0; - for (i = 0; i < nRefSegs; ++i) { - seg = findSegment(refSegs[i]); - if (seg->getType() == jbig2SegSymbolDict) { - numInputSyms += ((JBIG2SymbolDict *)seg)->getSize(); - } else if (seg->getType() == jbig2SegCodeTable) { - codeTables->append(seg); - } - } - - // compute symbol code length - symCodeLen = 0; - i = 1; - while (i < numInputSyms + numNewSyms) { - ++symCodeLen; - i <<= 1; - } - - // get the input symbol bitmaps - bitmaps = (JBIG2Bitmap **)gmallocn(numInputSyms + numNewSyms, - sizeof(JBIG2Bitmap *)); - for (i = 0; i < numInputSyms + numNewSyms; ++i) { - bitmaps[i] = NULL; - } - k = 0; - inputSymbolDict = NULL; - for (i = 0; i < nRefSegs; ++i) { - seg = findSegment(refSegs[i]); - if (seg->getType() == jbig2SegSymbolDict) { - inputSymbolDict = (JBIG2SymbolDict *)seg; - for (j = 0; j < inputSymbolDict->getSize(); ++j) { - bitmaps[k++] = inputSymbolDict->getBitmap(j); - } - } - } - - // get the Huffman tables - huffDHTable = huffDWTable = NULL; // make gcc happy - huffBMSizeTable = huffAggInstTable = NULL; // make gcc happy - i = 0; - if (huff) { - if (huffDH == 0) { - huffDHTable = huffTableD; - } else if (huffDH == 1) { - huffDHTable = huffTableE; - } else { - huffDHTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); - } - if (huffDW == 0) { - huffDWTable = huffTableB; - } else if (huffDW == 1) { - huffDWTable = huffTableC; - } else { - huffDWTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); - } - if (huffBMSize == 0) { - huffBMSizeTable = huffTableA; - } else { - huffBMSizeTable = - ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); - } - if (huffAggInst == 0) { - huffAggInstTable = huffTableA; - } else { - huffAggInstTable = - ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); - } - } - delete codeTables; - - // set up the Huffman decoder - if (huff) { - huffDecoder->reset(); - - // set up the arithmetic decoder - } else { - if (contextUsed && inputSymbolDict) { - resetGenericStats(sdTemplate, inputSymbolDict->getGenericRegionStats()); - } else { - resetGenericStats(sdTemplate, NULL); - } - resetIntStats(symCodeLen); - arithDecoder->start(); - } - - // set up the arithmetic decoder for refinement/aggregation - if (refAgg) { - if (contextUsed && inputSymbolDict) { - resetRefinementStats(sdrTemplate, - inputSymbolDict->getRefinementRegionStats()); - } else { - resetRefinementStats(sdrTemplate, NULL); - } - } - - // allocate symbol widths storage - symWidths = NULL; - if (huff && !refAgg) { - symWidths = (Guint *)gmallocn(numNewSyms, sizeof(Guint)); - } - - symHeight = 0; - i = 0; - while (i < numNewSyms) { - - // read the height class delta height - if (huff) { - huffDecoder->decodeInt(&dh, huffDHTable); - } else { - arithDecoder->decodeInt(&dh, iadhStats); - } - if (dh < 0 && (Guint)-dh >= symHeight) { - error(getPos(), "Bad delta-height value in JBIG2 symbol dictionary"); - goto syntaxError; - } - symHeight += dh; - symWidth = 0; - totalWidth = 0; - j = i; - - // read the symbols in this height class - while (1) { - - // read the delta width - if (huff) { - if (!huffDecoder->decodeInt(&dw, huffDWTable)) { - break; - } - } else { - if (!arithDecoder->decodeInt(&dw, iadwStats)) { - break; - } - } - if (dw < 0 && (Guint)-dw >= symWidth) { - error(getPos(), "Bad delta-height value in JBIG2 symbol dictionary"); - goto syntaxError; - } - symWidth += dw; - - // using a collective bitmap, so don't read a bitmap here - if (huff && !refAgg) { - symWidths[i] = symWidth; - totalWidth += symWidth; - - // refinement/aggregate coding - } else if (refAgg) { - if (huff) { - if (!huffDecoder->decodeInt(&refAggNum, huffAggInstTable)) { - break; - } - } else { - if (!arithDecoder->decodeInt(&refAggNum, iaaiStats)) { - break; - } - } -#if 0 //~ This special case was added about a year before the final draft - //~ of the JBIG2 spec was released. I have encountered some old - //~ JBIG2 images that predate it. - if (0) { -#else - if (refAggNum == 1) { -#endif - if (huff) { - symID = huffDecoder->readBits(symCodeLen); - huffDecoder->decodeInt(&refDX, huffTableO); - huffDecoder->decodeInt(&refDY, huffTableO); - huffDecoder->decodeInt(&bmSize, huffTableA); - huffDecoder->reset(); - arithDecoder->start(); - } else { - symID = arithDecoder->decodeIAID(symCodeLen, iaidStats); - arithDecoder->decodeInt(&refDX, iardxStats); - arithDecoder->decodeInt(&refDY, iardyStats); - } - refBitmap = bitmaps[symID]; - bitmaps[numInputSyms + i] = - readGenericRefinementRegion(symWidth, symHeight, - sdrTemplate, gFalse, - refBitmap, refDX, refDY, - sdrATX, sdrATY); - //~ do we need to use the bmSize value here (in Huffman mode)? - } else { - bitmaps[numInputSyms + i] = - readTextRegion(huff, gTrue, symWidth, symHeight, - refAggNum, 0, numInputSyms + i, NULL, - symCodeLen, bitmaps, 0, 0, 0, 1, 0, - huffTableF, huffTableH, huffTableK, huffTableO, - huffTableO, huffTableO, huffTableO, huffTableA, - sdrTemplate, sdrATX, sdrATY); - } - - // non-ref/agg coding - } else { - bitmaps[numInputSyms + i] = - readGenericBitmap(gFalse, symWidth, symHeight, - sdTemplate, gFalse, gFalse, NULL, - sdATX, sdATY, 0); - } - - ++i; - } - - // read the collective bitmap - if (huff && !refAgg) { - huffDecoder->decodeInt(&bmSize, huffBMSizeTable); - huffDecoder->reset(); - if (bmSize == 0) { - collBitmap = new JBIG2Bitmap(0, totalWidth, symHeight); - bmSize = symHeight * ((totalWidth + 7) >> 3); - p = collBitmap->getDataPtr(); - for (k = 0; k < (Guint)bmSize; ++k) { - *p++ = curStr->getChar(); - } - } else { - collBitmap = readGenericBitmap(gTrue, totalWidth, symHeight, - 0, gFalse, gFalse, NULL, NULL, NULL, - bmSize); - } - x = 0; - for (; j < i; ++j) { - bitmaps[numInputSyms + j] = - collBitmap->getSlice(x, 0, symWidths[j], symHeight); - x += symWidths[j]; - } - delete collBitmap; - } - } - - // create the symbol dict object - symbolDict = new JBIG2SymbolDict(segNum, numExSyms); - - // exported symbol list - i = j = 0; - ex = gFalse; - while (i < numInputSyms + numNewSyms) { - if (huff) { - huffDecoder->decodeInt(&run, huffTableA); - } else { - arithDecoder->decodeInt(&run, iaexStats); - } - if (ex) { - for (cnt = 0; cnt < run; ++cnt) { - symbolDict->setBitmap(j++, bitmaps[i++]->copy()); - } - } else { - i += run; - } - ex = !ex; - } - - for (i = 0; i < numNewSyms; ++i) { - delete bitmaps[numInputSyms + i]; - } - gfree(bitmaps); - if (symWidths) { - gfree(symWidths); - } - - // save the arithmetic decoder stats - if (!huff && contextRetained) { - symbolDict->setGenericRegionStats(genericRegionStats->copy()); - if (refAgg) { - symbolDict->setRefinementRegionStats(refinementRegionStats->copy()); - } - } - - // store the new symbol dict - segments->append(symbolDict); - - return gTrue; - - syntaxError: - for (i = 0; i < numNewSyms; ++i) { - if (bitmaps[numInputSyms + i]) { - delete bitmaps[numInputSyms + i]; - } - } - gfree(bitmaps); - if (symWidths) { - gfree(symWidths); - } - return gFalse; - - eofError: - error(getPos(), "Unexpected EOF in JBIG2 stream"); - return gFalse; -} - -void JBIG2Stream::readTextRegionSeg(Guint segNum, GBool imm, - GBool lossless, Guint length, - Guint *refSegs, Guint nRefSegs) { - JBIG2Bitmap *bitmap; - JBIG2HuffmanTable runLengthTab[36]; - JBIG2HuffmanTable *symCodeTab; - JBIG2HuffmanTable *huffFSTable, *huffDSTable, *huffDTTable; - JBIG2HuffmanTable *huffRDWTable, *huffRDHTable; - JBIG2HuffmanTable *huffRDXTable, *huffRDYTable, *huffRSizeTable; - JBIG2Segment *seg; - GList *codeTables; - JBIG2SymbolDict *symbolDict; - JBIG2Bitmap **syms; - Guint w, h, x, y, segInfoFlags, extCombOp; - Guint flags, huff, refine, logStrips, refCorner, transposed; - Guint combOp, defPixel, templ; - int sOffset; - Guint huffFlags, huffFS, huffDS, huffDT; - Guint huffRDW, huffRDH, huffRDX, huffRDY, huffRSize; - Guint numInstances, numSyms, symCodeLen; - int atx[2], aty[2]; - Guint i, k, kk; - int j; - - // region segment info field - if (!readULong(&w) || !readULong(&h) || - !readULong(&x) || !readULong(&y) || - !readUByte(&segInfoFlags)) { - goto eofError; - } - extCombOp = segInfoFlags & 7; - - // rest of the text region header - if (!readUWord(&flags)) { - goto eofError; - } - huff = flags & 1; - refine = (flags >> 1) & 1; - logStrips = (flags >> 2) & 3; - refCorner = (flags >> 4) & 3; - transposed = (flags >> 6) & 1; - combOp = (flags >> 7) & 3; - defPixel = (flags >> 9) & 1; - sOffset = (flags >> 10) & 0x1f; - if (sOffset & 0x10) { - sOffset |= -1 - 0x0f; - } - templ = (flags >> 15) & 1; - huffFS = huffDS = huffDT = 0; // make gcc happy - huffRDW = huffRDH = huffRDX = huffRDY = huffRSize = 0; // make gcc happy - if (huff) { - if (!readUWord(&huffFlags)) { - goto eofError; - } - huffFS = huffFlags & 3; - huffDS = (huffFlags >> 2) & 3; - huffDT = (huffFlags >> 4) & 3; - huffRDW = (huffFlags >> 6) & 3; - huffRDH = (huffFlags >> 8) & 3; - huffRDX = (huffFlags >> 10) & 3; - huffRDY = (huffFlags >> 12) & 3; - huffRSize = (huffFlags >> 14) & 1; - } - if (refine && templ == 0) { - if (!readByte(&atx[0]) || !readByte(&aty[0]) || - !readByte(&atx[1]) || !readByte(&aty[1])) { - goto eofError; - } - } - if (!readULong(&numInstances)) { - goto eofError; - } - - // get symbol dictionaries and tables - codeTables = new GList(); - numSyms = 0; - for (i = 0; i < nRefSegs; ++i) { - if ((seg = findSegment(refSegs[i]))) { - if (seg->getType() == jbig2SegSymbolDict) { - numSyms += ((JBIG2SymbolDict *)seg)->getSize(); - } else if (seg->getType() == jbig2SegCodeTable) { - codeTables->append(seg); - } - } else { - error(getPos(), "Invalid segment reference in JBIG2 text region"); - } - } - symCodeLen = 0; - i = 1; - while (i < numSyms) { - ++symCodeLen; - i <<= 1; - } - - // get the symbol bitmaps - syms = (JBIG2Bitmap **)gmallocn(numSyms, sizeof(JBIG2Bitmap *)); - kk = 0; - for (i = 0; i < nRefSegs; ++i) { - if ((seg = findSegment(refSegs[i]))) { - if (seg->getType() == jbig2SegSymbolDict) { - symbolDict = (JBIG2SymbolDict *)seg; - for (k = 0; k < symbolDict->getSize(); ++k) { - syms[kk++] = symbolDict->getBitmap(k); - } - } - } - } - - // get the Huffman tables - huffFSTable = huffDSTable = huffDTTable = NULL; // make gcc happy - huffRDWTable = huffRDHTable = NULL; // make gcc happy - huffRDXTable = huffRDYTable = huffRSizeTable = NULL; // make gcc happy - i = 0; - if (huff) { - if (huffFS == 0) { - huffFSTable = huffTableF; - } else if (huffFS == 1) { - huffFSTable = huffTableG; - } else { - huffFSTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); - } - if (huffDS == 0) { - huffDSTable = huffTableH; - } else if (huffDS == 1) { - huffDSTable = huffTableI; - } else if (huffDS == 2) { - huffDSTable = huffTableJ; - } else { - huffDSTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); - } - if (huffDT == 0) { - huffDTTable = huffTableK; - } else if (huffDT == 1) { - huffDTTable = huffTableL; - } else if (huffDT == 2) { - huffDTTable = huffTableM; - } else { - huffDTTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); - } - if (huffRDW == 0) { - huffRDWTable = huffTableN; - } else if (huffRDW == 1) { - huffRDWTable = huffTableO; - } else { - huffRDWTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); - } - if (huffRDH == 0) { - huffRDHTable = huffTableN; - } else if (huffRDH == 1) { - huffRDHTable = huffTableO; - } else { - huffRDHTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); - } - if (huffRDX == 0) { - huffRDXTable = huffTableN; - } else if (huffRDX == 1) { - huffRDXTable = huffTableO; - } else { - huffRDXTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); - } - if (huffRDY == 0) { - huffRDYTable = huffTableN; - } else if (huffRDY == 1) { - huffRDYTable = huffTableO; - } else { - huffRDYTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); - } - if (huffRSize == 0) { - huffRSizeTable = huffTableA; - } else { - huffRSizeTable = - ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); - } - } - delete codeTables; - - // symbol ID Huffman decoding table - if (huff) { - huffDecoder->reset(); - for (i = 0; i < 32; ++i) { - runLengthTab[i].val = i; - runLengthTab[i].prefixLen = huffDecoder->readBits(4); - runLengthTab[i].rangeLen = 0; - } - runLengthTab[32].val = 0x103; - runLengthTab[32].prefixLen = huffDecoder->readBits(4); - runLengthTab[32].rangeLen = 2; - runLengthTab[33].val = 0x203; - runLengthTab[33].prefixLen = huffDecoder->readBits(4); - runLengthTab[33].rangeLen = 3; - runLengthTab[34].val = 0x20b; - runLengthTab[34].prefixLen = huffDecoder->readBits(4); - runLengthTab[34].rangeLen = 7; - runLengthTab[35].prefixLen = 0; - runLengthTab[35].rangeLen = jbig2HuffmanEOT; - huffDecoder->buildTable(runLengthTab, 35); - symCodeTab = (JBIG2HuffmanTable *)gmallocn(numSyms + 1, - sizeof(JBIG2HuffmanTable)); - for (i = 0; i < numSyms; ++i) { - symCodeTab[i].val = i; - symCodeTab[i].rangeLen = 0; - } - i = 0; - while (i < numSyms) { - huffDecoder->decodeInt(&j, runLengthTab); - if (j > 0x200) { - for (j -= 0x200; j && i < numSyms; --j) { - symCodeTab[i++].prefixLen = 0; - } - } else if (j > 0x100) { - for (j -= 0x100; j && i < numSyms; --j) { - symCodeTab[i].prefixLen = symCodeTab[i-1].prefixLen; - ++i; - } - } else { - symCodeTab[i++].prefixLen = j; - } - } - symCodeTab[numSyms].prefixLen = 0; - symCodeTab[numSyms].rangeLen = jbig2HuffmanEOT; - huffDecoder->buildTable(symCodeTab, numSyms); - huffDecoder->reset(); - - // set up the arithmetic decoder - } else { - symCodeTab = NULL; - resetIntStats(symCodeLen); - arithDecoder->start(); - } - if (refine) { - resetRefinementStats(templ, NULL); - } - - bitmap = readTextRegion(huff, refine, w, h, numInstances, - logStrips, numSyms, symCodeTab, symCodeLen, syms, - defPixel, combOp, transposed, refCorner, sOffset, - huffFSTable, huffDSTable, huffDTTable, - huffRDWTable, huffRDHTable, - huffRDXTable, huffRDYTable, huffRSizeTable, - templ, atx, aty); - - gfree(syms); - - // combine the region bitmap into the page bitmap - if (imm) { - if (pageH == 0xffffffff && y + h > curPageH) { - pageBitmap->expand(y + h, pageDefPixel); - } - pageBitmap->combine(bitmap, x, y, extCombOp); - delete bitmap; - - // store the region bitmap - } else { - bitmap->setSegNum(segNum); - segments->append(bitmap); - } - - // clean up the Huffman decoder - if (huff) { - gfree(symCodeTab); - } - - return; - - eofError: - error(getPos(), "Unexpected EOF in JBIG2 stream"); -} - -JBIG2Bitmap *JBIG2Stream::readTextRegion(GBool huff, GBool refine, - int w, int h, - Guint numInstances, - Guint logStrips, - int numSyms, - JBIG2HuffmanTable *symCodeTab, - Guint symCodeLen, - JBIG2Bitmap **syms, - Guint defPixel, Guint combOp, - Guint transposed, Guint refCorner, - int sOffset, - JBIG2HuffmanTable *huffFSTable, - JBIG2HuffmanTable *huffDSTable, - JBIG2HuffmanTable *huffDTTable, - JBIG2HuffmanTable *huffRDWTable, - JBIG2HuffmanTable *huffRDHTable, - JBIG2HuffmanTable *huffRDXTable, - JBIG2HuffmanTable *huffRDYTable, - JBIG2HuffmanTable *huffRSizeTable, - Guint templ, - int *atx, int *aty) { - JBIG2Bitmap *bitmap; - JBIG2Bitmap *symbolBitmap; - Guint strips; - int t, dt, tt, s, ds, sFirst, j; - int rdw, rdh, rdx, rdy, ri, refDX, refDY, bmSize; - Guint symID, inst, bw, bh; - - strips = 1 << logStrips; - - // allocate the bitmap - bitmap = new JBIG2Bitmap(0, w, h); - if (defPixel) { - bitmap->clearToOne(); - } else { - bitmap->clearToZero(); - } - - // decode initial T value - if (huff) { - huffDecoder->decodeInt(&t, huffDTTable); - } else { - arithDecoder->decodeInt(&t, iadtStats); - } - t *= -(int)strips; - - inst = 0; - sFirst = 0; - while (inst < numInstances) { - - // decode delta-T - if (huff) { - huffDecoder->decodeInt(&dt, huffDTTable); - } else { - arithDecoder->decodeInt(&dt, iadtStats); - } - t += dt * strips; - - // first S value - if (huff) { - huffDecoder->decodeInt(&ds, huffFSTable); - } else { - arithDecoder->decodeInt(&ds, iafsStats); - } - sFirst += ds; - s = sFirst; - - // read the instances - while (1) { - - // T value - if (strips == 1) { - dt = 0; - } else if (huff) { - dt = huffDecoder->readBits(logStrips); - } else { - arithDecoder->decodeInt(&dt, iaitStats); - } - tt = t + dt; - - // symbol ID - if (huff) { - if (symCodeTab) { - huffDecoder->decodeInt(&j, symCodeTab); - symID = (Guint)j; - } else { - symID = huffDecoder->readBits(symCodeLen); - } - } else { - symID = arithDecoder->decodeIAID(symCodeLen, iaidStats); - } - - if (symID >= (Guint)numSyms) { - error(getPos(), "Invalid symbol number in JBIG2 text region"); - } else { - - // get the symbol bitmap - symbolBitmap = NULL; - if (refine) { - if (huff) { - ri = (int)huffDecoder->readBit(); - } else { - arithDecoder->decodeInt(&ri, iariStats); - } - } else { - ri = 0; - } - if (ri) { - if (huff) { - huffDecoder->decodeInt(&rdw, huffRDWTable); - huffDecoder->decodeInt(&rdh, huffRDHTable); - huffDecoder->decodeInt(&rdx, huffRDXTable); - huffDecoder->decodeInt(&rdy, huffRDYTable); - huffDecoder->decodeInt(&bmSize, huffRSizeTable); - huffDecoder->reset(); - arithDecoder->start(); - } else { - arithDecoder->decodeInt(&rdw, iardwStats); - arithDecoder->decodeInt(&rdh, iardhStats); - arithDecoder->decodeInt(&rdx, iardxStats); - arithDecoder->decodeInt(&rdy, iardyStats); - } - refDX = ((rdw >= 0) ? rdw : rdw - 1) / 2 + rdx; - refDY = ((rdh >= 0) ? rdh : rdh - 1) / 2 + rdy; - - symbolBitmap = - readGenericRefinementRegion(rdw + syms[symID]->getWidth(), - rdh + syms[symID]->getHeight(), - templ, gFalse, syms[symID], - refDX, refDY, atx, aty); - //~ do we need to use the bmSize value here (in Huffman mode)? - } else { - symbolBitmap = syms[symID]; - } - - // combine the symbol bitmap into the region bitmap - //~ something is wrong here - refCorner shouldn't degenerate into - //~ two cases - bw = symbolBitmap->getWidth() - 1; - bh = symbolBitmap->getHeight() - 1; - if (transposed) { - switch (refCorner) { - case 0: // bottom left - bitmap->combine(symbolBitmap, tt, s, combOp); - break; - case 1: // top left - bitmap->combine(symbolBitmap, tt, s, combOp); - break; - case 2: // bottom right - bitmap->combine(symbolBitmap, tt - bw, s, combOp); - break; - case 3: // top right - bitmap->combine(symbolBitmap, tt - bw, s, combOp); - break; - } - s += bh; - } else { - switch (refCorner) { - case 0: // bottom left - bitmap->combine(symbolBitmap, s, tt - bh, combOp); - break; - case 1: // top left - bitmap->combine(symbolBitmap, s, tt, combOp); - break; - case 2: // bottom right - bitmap->combine(symbolBitmap, s, tt - bh, combOp); - break; - case 3: // top right - bitmap->combine(symbolBitmap, s, tt, combOp); - break; - } - s += bw; - } - if (ri) { - delete symbolBitmap; - } - } - - // next instance - ++inst; - - // next S value - if (huff) { - if (!huffDecoder->decodeInt(&ds, huffDSTable)) { - break; - } - } else { - if (!arithDecoder->decodeInt(&ds, iadsStats)) { - break; - } - } - s += sOffset + ds; - } - } - - return bitmap; -} - -void JBIG2Stream::readPatternDictSeg(Guint segNum, Guint length) { - JBIG2PatternDict *patternDict; - JBIG2Bitmap *bitmap; - Guint flags, patternW, patternH, grayMax, templ, mmr; - int atx[4], aty[4]; - Guint i, x; - - // halftone dictionary flags, pattern width and height, max gray value - if (!readUByte(&flags) || - !readUByte(&patternW) || - !readUByte(&patternH) || - !readULong(&grayMax)) { - goto eofError; - } - templ = (flags >> 1) & 3; - mmr = flags & 1; - - // set up the arithmetic decoder - if (!mmr) { - resetGenericStats(templ, NULL); - arithDecoder->start(); - } - - // read the bitmap - atx[0] = -(int)patternW; aty[0] = 0; - atx[1] = -3; aty[1] = -1; - atx[2] = 2; aty[2] = -2; - atx[3] = -2; aty[3] = -2; - bitmap = readGenericBitmap(mmr, (grayMax + 1) * patternW, patternH, - templ, gFalse, gFalse, NULL, - atx, aty, length - 7); - - // create the pattern dict object - patternDict = new JBIG2PatternDict(segNum, grayMax + 1); - - // split up the bitmap - x = 0; - for (i = 0; i <= grayMax; ++i) { - patternDict->setBitmap(i, bitmap->getSlice(x, 0, patternW, patternH)); - x += patternW; - } - - // free memory - delete bitmap; - - // store the new pattern dict - segments->append(patternDict); - - return; - - eofError: - error(getPos(), "Unexpected EOF in JBIG2 stream"); -} - -void JBIG2Stream::readHalftoneRegionSeg(Guint segNum, GBool imm, - GBool lossless, Guint length, - Guint *refSegs, Guint nRefSegs) { - JBIG2Bitmap *bitmap; - JBIG2Segment *seg; - JBIG2PatternDict *patternDict; - JBIG2Bitmap *skipBitmap; - Guint *grayImg; - JBIG2Bitmap *grayBitmap; - JBIG2Bitmap *patternBitmap; - Guint w, h, x, y, segInfoFlags, extCombOp; - Guint flags, mmr, templ, enableSkip, combOp; - Guint gridW, gridH, stepX, stepY, patW, patH; - int atx[4], aty[4]; - int gridX, gridY, xx, yy, bit, j; - Guint bpp, m, n, i; - - // region segment info field - if (!readULong(&w) || !readULong(&h) || - !readULong(&x) || !readULong(&y) || - !readUByte(&segInfoFlags)) { - goto eofError; - } - extCombOp = segInfoFlags & 7; - - // rest of the halftone region header - if (!readUByte(&flags)) { - goto eofError; - } - mmr = flags & 1; - templ = (flags >> 1) & 3; - enableSkip = (flags >> 3) & 1; - combOp = (flags >> 4) & 7; - if (!readULong(&gridW) || !readULong(&gridH) || - !readLong(&gridX) || !readLong(&gridY) || - !readUWord(&stepX) || !readUWord(&stepY)) { - goto eofError; - } - if (w == 0 || h == 0 || w >= INT_MAX / h) { - error(getPos(), "Bad bitmap size in JBIG2 halftone segment"); - return; - } - if (gridH == 0 || gridW >= INT_MAX / gridH) { - error(getPos(), "Bad grid size in JBIG2 halftone segment"); - return; - } - - // get pattern dictionary - if (nRefSegs != 1) { - error(getPos(), "Bad symbol dictionary reference in JBIG2 halftone segment"); - return; - } - seg = findSegment(refSegs[0]); - if (seg->getType() != jbig2SegPatternDict) { - error(getPos(), "Bad symbol dictionary reference in JBIG2 halftone segment"); - return; - } - patternDict = (JBIG2PatternDict *)seg; - bpp = 0; - i = 1; - while (i < patternDict->getSize()) { - ++bpp; - i <<= 1; - } - patW = patternDict->getBitmap(0)->getWidth(); - patH = patternDict->getBitmap(0)->getHeight(); - - // set up the arithmetic decoder - if (!mmr) { - resetGenericStats(templ, NULL); - arithDecoder->start(); - } - - // allocate the bitmap - bitmap = new JBIG2Bitmap(segNum, w, h); - if (flags & 0x80) { // HDEFPIXEL - bitmap->clearToOne(); - } else { - bitmap->clearToZero(); - } - - // compute the skip bitmap - skipBitmap = NULL; - if (enableSkip) { - skipBitmap = new JBIG2Bitmap(0, gridW, gridH); - skipBitmap->clearToZero(); - for (m = 0; m < gridH; ++m) { - xx = gridX + m * stepY; - yy = gridY + m * stepX; - for (n = 0; n < gridW; ++n) { - if (((xx + (int)patW) >> 8) <= 0 || (xx >> 8) >= (int)w || - ((yy + (int)patH) >> 8) <= 0 || (yy >> 8) >= (int)h) { - skipBitmap->setPixel(n, m); - } - } - } - } - - // read the gray-scale image - grayImg = (Guint *)gmallocn(gridW * gridH, sizeof(Guint)); - memset(grayImg, 0, gridW * gridH * sizeof(Guint)); - atx[0] = templ <= 1 ? 3 : 2; aty[0] = -1; - atx[1] = -3; aty[1] = -1; - atx[2] = 2; aty[2] = -2; - atx[3] = -2; aty[3] = -2; - for (j = bpp - 1; j >= 0; --j) { - grayBitmap = readGenericBitmap(mmr, gridW, gridH, templ, gFalse, - enableSkip, skipBitmap, atx, aty, -1); - i = 0; - for (m = 0; m < gridH; ++m) { - for (n = 0; n < gridW; ++n) { - bit = grayBitmap->getPixel(n, m) ^ (grayImg[i] & 1); - grayImg[i] = (grayImg[i] << 1) | bit; - ++i; - } - } - delete grayBitmap; - } - - // decode the image - i = 0; - for (m = 0; m < gridH; ++m) { - xx = gridX + m * stepY; - yy = gridY + m * stepX; - for (n = 0; n < gridW; ++n) { - if (!(enableSkip && skipBitmap->getPixel(n, m))) { - patternBitmap = patternDict->getBitmap(grayImg[i]); - bitmap->combine(patternBitmap, xx >> 8, yy >> 8, combOp); - } - xx += stepX; - yy -= stepY; - ++i; - } - } - - gfree(grayImg); - - // combine the region bitmap into the page bitmap - if (imm) { - if (pageH == 0xffffffff && y + h > curPageH) { - pageBitmap->expand(y + h, pageDefPixel); - } - pageBitmap->combine(bitmap, x, y, extCombOp); - delete bitmap; - - // store the region bitmap - } else { - segments->append(bitmap); - } - - return; - - eofError: - error(getPos(), "Unexpected EOF in JBIG2 stream"); -} - -void JBIG2Stream::readGenericRegionSeg(Guint segNum, GBool imm, - GBool lossless, Guint length) { - JBIG2Bitmap *bitmap; - Guint w, h, x, y, segInfoFlags, extCombOp; - Guint flags, mmr, templ, tpgdOn; - int atx[4], aty[4]; - - // region segment info field - if (!readULong(&w) || !readULong(&h) || - !readULong(&x) || !readULong(&y) || - !readUByte(&segInfoFlags)) { - goto eofError; - } - extCombOp = segInfoFlags & 7; - - // rest of the generic region segment header - if (!readUByte(&flags)) { - goto eofError; - } - mmr = flags & 1; - templ = (flags >> 1) & 3; - tpgdOn = (flags >> 3) & 1; - - // AT flags - if (!mmr) { - if (templ == 0) { - if (!readByte(&atx[0]) || - !readByte(&aty[0]) || - !readByte(&atx[1]) || - !readByte(&aty[1]) || - !readByte(&atx[2]) || - !readByte(&aty[2]) || - !readByte(&atx[3]) || - !readByte(&aty[3])) { - goto eofError; - } - } else { - if (!readByte(&atx[0]) || - !readByte(&aty[0])) { - goto eofError; - } - } - } - - // set up the arithmetic decoder - if (!mmr) { - resetGenericStats(templ, NULL); - arithDecoder->start(); - } - - // read the bitmap - bitmap = readGenericBitmap(mmr, w, h, templ, tpgdOn, gFalse, - NULL, atx, aty, mmr ? 0 : length - 18); - - // combine the region bitmap into the page bitmap - if (imm) { - if (pageH == 0xffffffff && y + h > curPageH) { - pageBitmap->expand(y + h, pageDefPixel); - } - pageBitmap->combine(bitmap, x, y, extCombOp); - delete bitmap; - - // store the region bitmap - } else { - bitmap->setSegNum(segNum); - segments->append(bitmap); - } - - return; - - eofError: - error(getPos(), "Unexpected EOF in JBIG2 stream"); -} - -JBIG2Bitmap *JBIG2Stream::readGenericBitmap(GBool mmr, int w, int h, - int templ, GBool tpgdOn, - GBool useSkip, JBIG2Bitmap *skip, - int *atx, int *aty, - int mmrDataLength) { - JBIG2Bitmap *bitmap; - GBool ltp; - Guint ltpCX, cx, cx0, cx1, cx2; - JBIG2BitmapPtr cxPtr0, cxPtr1; - JBIG2BitmapPtr atPtr0, atPtr1, atPtr2, atPtr3; - int *refLine, *codingLine; - int code1, code2, code3; - int x, y, a0, pix, i, refI, codingI; - - bitmap = new JBIG2Bitmap(0, w, h); - bitmap->clearToZero(); - - //----- MMR decode - - if (mmr) { - - mmrDecoder->reset(); - refLine = (int *)gmallocn(w + 2, sizeof(int)); - codingLine = (int *)gmallocn(w + 2, sizeof(int)); - codingLine[0] = codingLine[1] = w; - - for (y = 0; y < h; ++y) { - - // copy coding line to ref line - for (i = 0; codingLine[i] < w; ++i) { - refLine[i] = codingLine[i]; - } - refLine[i] = refLine[i + 1] = w; - - // decode a line - refI = 0; // b1 = refLine[refI] - codingI = 0; // a1 = codingLine[codingI] - a0 = 0; - do { - code1 = mmrDecoder->get2DCode(); - switch (code1) { - case twoDimPass: - if (refLine[refI] < w) { - a0 = refLine[refI + 1]; - refI += 2; - } - break; - case twoDimHoriz: - if (codingI & 1) { - code1 = 0; - do { - code1 += code3 = mmrDecoder->getBlackCode(); - } while (code3 >= 64); - code2 = 0; - do { - code2 += code3 = mmrDecoder->getWhiteCode(); - } while (code3 >= 64); - } else { - code1 = 0; - do { - code1 += code3 = mmrDecoder->getWhiteCode(); - } while (code3 >= 64); - code2 = 0; - do { - code2 += code3 = mmrDecoder->getBlackCode(); - } while (code3 >= 64); - } - if (code1 > 0 || code2 > 0) { - a0 = codingLine[codingI++] = a0 + code1; - a0 = codingLine[codingI++] = a0 + code2; - while (refLine[refI] <= a0 && refLine[refI] < w) { - refI += 2; - } - } - break; - case twoDimVert0: - a0 = codingLine[codingI++] = refLine[refI]; - if (refLine[refI] < w) { - ++refI; - } - break; - case twoDimVertR1: - a0 = codingLine[codingI++] = refLine[refI] + 1; - if (refLine[refI] < w) { - ++refI; - while (refLine[refI] <= a0 && refLine[refI] < w) { - refI += 2; - } - } - break; - case twoDimVertR2: - a0 = codingLine[codingI++] = refLine[refI] + 2; - if (refLine[refI] < w) { - ++refI; - while (refLine[refI] <= a0 && refLine[refI] < w) { - refI += 2; - } - } - break; - case twoDimVertR3: - a0 = codingLine[codingI++] = refLine[refI] + 3; - if (refLine[refI] < w) { - ++refI; - while (refLine[refI] <= a0 && refLine[refI] < w) { - refI += 2; - } - } - break; - case twoDimVertL1: - a0 = codingLine[codingI++] = refLine[refI] - 1; - if (refI > 0) { - --refI; - } else { - ++refI; - } - while (refLine[refI] <= a0 && refLine[refI] < w) { - refI += 2; - } - break; - case twoDimVertL2: - a0 = codingLine[codingI++] = refLine[refI] - 2; - if (refI > 0) { - --refI; - } else { - ++refI; - } - while (refLine[refI] <= a0 && refLine[refI] < w) { - refI += 2; - } - break; - case twoDimVertL3: - a0 = codingLine[codingI++] = refLine[refI] - 3; - if (refI > 0) { - --refI; - } else { - ++refI; - } - while (refLine[refI] <= a0 && refLine[refI] < w) { - refI += 2; - } - break; - default: - error(getPos(), "Illegal code in JBIG2 MMR bitmap data"); - break; - } - } while (a0 < w); - codingLine[codingI++] = w; - - // convert the run lengths to a bitmap line - i = 0; - while (codingLine[i] < w) { - for (x = codingLine[i]; x < codingLine[i+1]; ++x) { - bitmap->setPixel(x, y); - } - i += 2; - } - } - - if (mmrDataLength >= 0) { - mmrDecoder->skipTo(mmrDataLength); - } else { - if (mmrDecoder->get24Bits() != 0x001001) { - error(getPos(), "Missing EOFB in JBIG2 MMR bitmap data"); - } - } - - gfree(refLine); - gfree(codingLine); - - //----- arithmetic decode - - } else { - // set up the typical row context - ltpCX = 0; // make gcc happy - if (tpgdOn) { - switch (templ) { - case 0: - ltpCX = 0x3953; // 001 11001 0101 0011 - break; - case 1: - ltpCX = 0x079a; // 0011 11001 101 0 - break; - case 2: - ltpCX = 0x0e3; // 001 1100 01 1 - break; - case 3: - ltpCX = 0x18a; // 01100 0101 1 - break; - } - } - - ltp = 0; - cx = cx0 = cx1 = cx2 = 0; // make gcc happy - for (y = 0; y < h; ++y) { - - // check for a "typical" (duplicate) row - if (tpgdOn) { - if (arithDecoder->decodeBit(ltpCX, genericRegionStats)) { - ltp = !ltp; - } - if (ltp) { - bitmap->duplicateRow(y, y-1); - continue; - } - } - - switch (templ) { - case 0: - - // set up the context - bitmap->getPixelPtr(0, y-2, &cxPtr0); - cx0 = bitmap->nextPixel(&cxPtr0); - cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0); - bitmap->getPixelPtr(0, y-1, &cxPtr1); - cx1 = bitmap->nextPixel(&cxPtr1); - cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1); - cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1); - cx2 = 0; - bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0); - bitmap->getPixelPtr(atx[1], y + aty[1], &atPtr1); - bitmap->getPixelPtr(atx[2], y + aty[2], &atPtr2); - bitmap->getPixelPtr(atx[3], y + aty[3], &atPtr3); - - // decode the row - for (x = 0; x < w; ++x) { - - // build the context - cx = (cx0 << 13) | (cx1 << 8) | (cx2 << 4) | - (bitmap->nextPixel(&atPtr0) << 3) | - (bitmap->nextPixel(&atPtr1) << 2) | - (bitmap->nextPixel(&atPtr2) << 1) | - bitmap->nextPixel(&atPtr3); - - // check for a skipped pixel - if (useSkip && skip->getPixel(x, y)) { - pix = 0; - - // decode the pixel - } else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) { - bitmap->setPixel(x, y); - } - - // update the context - cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 0x07; - cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x1f; - cx2 = ((cx2 << 1) | pix) & 0x0f; - } - break; - - case 1: - - // set up the context - bitmap->getPixelPtr(0, y-2, &cxPtr0); - cx0 = bitmap->nextPixel(&cxPtr0); - cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0); - cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0); - bitmap->getPixelPtr(0, y-1, &cxPtr1); - cx1 = bitmap->nextPixel(&cxPtr1); - cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1); - cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1); - cx2 = 0; - bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0); - - // decode the row - for (x = 0; x < w; ++x) { - - // build the context - cx = (cx0 << 9) | (cx1 << 4) | (cx2 << 1) | - bitmap->nextPixel(&atPtr0); - - // check for a skipped pixel - if (useSkip && skip->getPixel(x, y)) { - pix = 0; - - // decode the pixel - } else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) { - bitmap->setPixel(x, y); - } - - // update the context - cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 0x0f; - cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x1f; - cx2 = ((cx2 << 1) | pix) & 0x07; - } - break; - - case 2: - - // set up the context - bitmap->getPixelPtr(0, y-2, &cxPtr0); - cx0 = bitmap->nextPixel(&cxPtr0); - cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0); - bitmap->getPixelPtr(0, y-1, &cxPtr1); - cx1 = bitmap->nextPixel(&cxPtr1); - cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1); - cx2 = 0; - bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0); - - // decode the row - for (x = 0; x < w; ++x) { - - // build the context - cx = (cx0 << 7) | (cx1 << 3) | (cx2 << 1) | - bitmap->nextPixel(&atPtr0); - - // check for a skipped pixel - if (useSkip && skip->getPixel(x, y)) { - pix = 0; - - // decode the pixel - } else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) { - bitmap->setPixel(x, y); - } - - // update the context - cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 0x07; - cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x0f; - cx2 = ((cx2 << 1) | pix) & 0x03; - } - break; - - case 3: - - // set up the context - bitmap->getPixelPtr(0, y-1, &cxPtr1); - cx1 = bitmap->nextPixel(&cxPtr1); - cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1); - cx2 = 0; - bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0); - - // decode the row - for (x = 0; x < w; ++x) { - - // build the context - cx = (cx1 << 5) | (cx2 << 1) | - bitmap->nextPixel(&atPtr0); - - // check for a skipped pixel - if (useSkip && skip->getPixel(x, y)) { - pix = 0; - - // decode the pixel - } else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) { - bitmap->setPixel(x, y); - } - - // update the context - cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x1f; - cx2 = ((cx2 << 1) | pix) & 0x0f; - } - break; - } - } - } - - return bitmap; -} - -void JBIG2Stream::readGenericRefinementRegionSeg(Guint segNum, GBool imm, - GBool lossless, Guint length, - Guint *refSegs, - Guint nRefSegs) { - JBIG2Bitmap *bitmap, *refBitmap; - Guint w, h, x, y, segInfoFlags, extCombOp; - Guint flags, templ, tpgrOn; - int atx[2], aty[2]; - JBIG2Segment *seg; - - // region segment info field - if (!readULong(&w) || !readULong(&h) || - !readULong(&x) || !readULong(&y) || - !readUByte(&segInfoFlags)) { - goto eofError; - } - extCombOp = segInfoFlags & 7; - - // rest of the generic refinement region segment header - if (!readUByte(&flags)) { - goto eofError; - } - templ = flags & 1; - tpgrOn = (flags >> 1) & 1; - - // AT flags - if (!templ) { - if (!readByte(&atx[0]) || !readByte(&aty[0]) || - !readByte(&atx[1]) || !readByte(&aty[1])) { - goto eofError; - } - } - - // resize the page bitmap if needed - if (nRefSegs == 0 || imm) { - if (pageH == 0xffffffff && y + h > curPageH) { - pageBitmap->expand(y + h, pageDefPixel); - } - } - - // get referenced bitmap - if (nRefSegs > 1) { - error(getPos(), "Bad reference in JBIG2 generic refinement segment"); - return; - } - if (nRefSegs == 1) { - seg = findSegment(refSegs[0]); - if (seg->getType() != jbig2SegBitmap) { - error(getPos(), "Bad bitmap reference in JBIG2 generic refinement segment"); - return; - } - refBitmap = (JBIG2Bitmap *)seg; - } else { - refBitmap = pageBitmap->getSlice(x, y, w, h); - } - - // set up the arithmetic decoder - resetRefinementStats(templ, NULL); - arithDecoder->start(); - - // read - bitmap = readGenericRefinementRegion(w, h, templ, tpgrOn, - refBitmap, 0, 0, atx, aty); - - // combine the region bitmap into the page bitmap - if (imm) { - pageBitmap->combine(bitmap, x, y, extCombOp); - delete bitmap; - - // store the region bitmap - } else { - bitmap->setSegNum(segNum); - segments->append(bitmap); - } - - // delete the referenced bitmap - if (nRefSegs == 1) { - discardSegment(refSegs[0]); - } else { - delete refBitmap; - } - - return; - - eofError: - error(getPos(), "Unexpected EOF in JBIG2 stream"); -} - -JBIG2Bitmap *JBIG2Stream::readGenericRefinementRegion(int w, int h, - int templ, GBool tpgrOn, - JBIG2Bitmap *refBitmap, - int refDX, int refDY, - int *atx, int *aty) { - JBIG2Bitmap *bitmap; - GBool ltp; - Guint ltpCX, cx, cx0, cx2, cx3, cx4, tpgrCX0, tpgrCX1, tpgrCX2; - JBIG2BitmapPtr cxPtr0, cxPtr1, cxPtr2, cxPtr3, cxPtr4, cxPtr5, cxPtr6; - JBIG2BitmapPtr tpgrCXPtr0, tpgrCXPtr1, tpgrCXPtr2; - int x, y, pix; - - bitmap = new JBIG2Bitmap(0, w, h); - bitmap->clearToZero(); - - // set up the typical row context - if (templ) { - ltpCX = 0x008; - } else { - ltpCX = 0x0010; - } - - ltp = 0; - for (y = 0; y < h; ++y) { - - if (templ) { - - // set up the context - bitmap->getPixelPtr(0, y-1, &cxPtr0); - cx0 = bitmap->nextPixel(&cxPtr0); - bitmap->getPixelPtr(-1, y, &cxPtr1); - refBitmap->getPixelPtr(-refDX, y-1-refDY, &cxPtr2); - refBitmap->getPixelPtr(-1-refDX, y-refDY, &cxPtr3); - cx3 = refBitmap->nextPixel(&cxPtr3); - cx3 = (cx3 << 1) | refBitmap->nextPixel(&cxPtr3); - refBitmap->getPixelPtr(-refDX, y+1-refDY, &cxPtr4); - cx4 = refBitmap->nextPixel(&cxPtr4); - - // set up the typical prediction context - tpgrCX0 = tpgrCX1 = tpgrCX2 = 0; // make gcc happy - if (tpgrOn) { - refBitmap->getPixelPtr(-1-refDX, y-1-refDY, &tpgrCXPtr0); - tpgrCX0 = refBitmap->nextPixel(&tpgrCXPtr0); - tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0); - tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0); - refBitmap->getPixelPtr(-1-refDX, y-refDY, &tpgrCXPtr1); - tpgrCX1 = refBitmap->nextPixel(&tpgrCXPtr1); - tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1); - tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1); - refBitmap->getPixelPtr(-1-refDX, y+1-refDY, &tpgrCXPtr2); - tpgrCX2 = refBitmap->nextPixel(&tpgrCXPtr2); - tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2); - tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2); - } - - for (x = 0; x < w; ++x) { - - // update the context - cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 7; - cx3 = ((cx3 << 1) | refBitmap->nextPixel(&cxPtr3)) & 7; - cx4 = ((cx4 << 1) | refBitmap->nextPixel(&cxPtr4)) & 3; - - if (tpgrOn) { - // update the typical predictor context - tpgrCX0 = ((tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0)) & 7; - tpgrCX1 = ((tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1)) & 7; - tpgrCX2 = ((tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2)) & 7; - - // check for a "typical" pixel - if (arithDecoder->decodeBit(ltpCX, refinementRegionStats)) { - ltp = !ltp; - } - if (tpgrCX0 == 0 && tpgrCX1 == 0 && tpgrCX2 == 0) { - bitmap->clearPixel(x, y); - continue; - } else if (tpgrCX0 == 7 && tpgrCX1 == 7 && tpgrCX2 == 7) { - bitmap->setPixel(x, y); - continue; - } - } - - // build the context - cx = (cx0 << 7) | (bitmap->nextPixel(&cxPtr1) << 6) | - (refBitmap->nextPixel(&cxPtr2) << 5) | - (cx3 << 2) | cx4; - - // decode the pixel - if ((pix = arithDecoder->decodeBit(cx, refinementRegionStats))) { - bitmap->setPixel(x, y); - } - } - - } else { - - // set up the context - bitmap->getPixelPtr(0, y-1, &cxPtr0); - cx0 = bitmap->nextPixel(&cxPtr0); - bitmap->getPixelPtr(-1, y, &cxPtr1); - refBitmap->getPixelPtr(-refDX, y-1-refDY, &cxPtr2); - cx2 = refBitmap->nextPixel(&cxPtr2); - refBitmap->getPixelPtr(-1-refDX, y-refDY, &cxPtr3); - cx3 = refBitmap->nextPixel(&cxPtr3); - cx3 = (cx3 << 1) | refBitmap->nextPixel(&cxPtr3); - refBitmap->getPixelPtr(-1-refDX, y+1-refDY, &cxPtr4); - cx4 = refBitmap->nextPixel(&cxPtr4); - cx4 = (cx4 << 1) | refBitmap->nextPixel(&cxPtr4); - bitmap->getPixelPtr(atx[0], y+aty[0], &cxPtr5); - refBitmap->getPixelPtr(atx[1]-refDX, y+aty[1]-refDY, &cxPtr6); - - // set up the typical prediction context - tpgrCX0 = tpgrCX1 = tpgrCX2 = 0; // make gcc happy - if (tpgrOn) { - refBitmap->getPixelPtr(-1-refDX, y-1-refDY, &tpgrCXPtr0); - tpgrCX0 = refBitmap->nextPixel(&tpgrCXPtr0); - tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0); - tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0); - refBitmap->getPixelPtr(-1-refDX, y-refDY, &tpgrCXPtr1); - tpgrCX1 = refBitmap->nextPixel(&tpgrCXPtr1); - tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1); - tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1); - refBitmap->getPixelPtr(-1-refDX, y+1-refDY, &tpgrCXPtr2); - tpgrCX2 = refBitmap->nextPixel(&tpgrCXPtr2); - tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2); - tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2); - } - - for (x = 0; x < w; ++x) { - - // update the context - cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 3; - cx2 = ((cx2 << 1) | refBitmap->nextPixel(&cxPtr2)) & 3; - cx3 = ((cx3 << 1) | refBitmap->nextPixel(&cxPtr3)) & 7; - cx4 = ((cx4 << 1) | refBitmap->nextPixel(&cxPtr4)) & 7; - - if (tpgrOn) { - // update the typical predictor context - tpgrCX0 = ((tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0)) & 7; - tpgrCX1 = ((tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1)) & 7; - tpgrCX2 = ((tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2)) & 7; - - // check for a "typical" pixel - if (arithDecoder->decodeBit(ltpCX, refinementRegionStats)) { - ltp = !ltp; - } - if (tpgrCX0 == 0 && tpgrCX1 == 0 && tpgrCX2 == 0) { - bitmap->clearPixel(x, y); - continue; - } else if (tpgrCX0 == 7 && tpgrCX1 == 7 && tpgrCX2 == 7) { - bitmap->setPixel(x, y); - continue; - } - } - - // build the context - cx = (cx0 << 11) | (bitmap->nextPixel(&cxPtr1) << 10) | - (cx2 << 8) | (cx3 << 5) | (cx4 << 2) | - (bitmap->nextPixel(&cxPtr5) << 1) | - refBitmap->nextPixel(&cxPtr6); - - // decode the pixel - if ((pix = arithDecoder->decodeBit(cx, refinementRegionStats))) { - bitmap->setPixel(x, y); - } - } - } - } - - return bitmap; -} - -void JBIG2Stream::readPageInfoSeg(Guint length) { - Guint xRes, yRes, flags, striping; - - if (!readULong(&pageW) || !readULong(&pageH) || - !readULong(&xRes) || !readULong(&yRes) || - !readUByte(&flags) || !readUWord(&striping)) { - goto eofError; - } - pageDefPixel = (flags >> 2) & 1; - defCombOp = (flags >> 3) & 3; - - // allocate the page bitmap - if (pageH == 0xffffffff) { - curPageH = striping & 0x7fff; - } else { - curPageH = pageH; - } - pageBitmap = new JBIG2Bitmap(0, pageW, curPageH); - - // default pixel value - if (pageDefPixel) { - pageBitmap->clearToOne(); - } else { - pageBitmap->clearToZero(); - } - - return; - - eofError: - error(getPos(), "Unexpected EOF in JBIG2 stream"); -} - -void JBIG2Stream::readEndOfStripeSeg(Guint length) { - Guint i; - - // skip the segment - for (i = 0; i < length; ++i) { - curStr->getChar(); - } -} - -void JBIG2Stream::readProfilesSeg(Guint length) { - Guint i; - - // skip the segment - for (i = 0; i < length; ++i) { - curStr->getChar(); - } -} - -void JBIG2Stream::readCodeTableSeg(Guint segNum, Guint length) { - JBIG2HuffmanTable *huffTab; - Guint flags, oob, prefixBits, rangeBits; - int lowVal, highVal, val; - Guint huffTabSize, i; - - if (!readUByte(&flags) || !readLong(&lowVal) || !readLong(&highVal)) { - goto eofError; - } - oob = flags & 1; - prefixBits = ((flags >> 1) & 7) + 1; - rangeBits = ((flags >> 4) & 7) + 1; - - huffDecoder->reset(); - huffTabSize = 8; - huffTab = (JBIG2HuffmanTable *) - gmallocn(huffTabSize, sizeof(JBIG2HuffmanTable)); - i = 0; - val = lowVal; - while (val < highVal) { - if (i == huffTabSize) { - huffTabSize *= 2; - huffTab = (JBIG2HuffmanTable *) - greallocn(huffTab, huffTabSize, sizeof(JBIG2HuffmanTable)); - } - huffTab[i].val = val; - huffTab[i].prefixLen = huffDecoder->readBits(prefixBits); - huffTab[i].rangeLen = huffDecoder->readBits(rangeBits); - val += 1 << huffTab[i].rangeLen; - ++i; - } - if (i + oob + 3 > huffTabSize) { - huffTabSize = i + oob + 3; - huffTab = (JBIG2HuffmanTable *) - greallocn(huffTab, huffTabSize, sizeof(JBIG2HuffmanTable)); - } - huffTab[i].val = lowVal - 1; - huffTab[i].prefixLen = huffDecoder->readBits(prefixBits); - huffTab[i].rangeLen = jbig2HuffmanLOW; - ++i; - huffTab[i].val = highVal; - huffTab[i].prefixLen = huffDecoder->readBits(prefixBits); - huffTab[i].rangeLen = 32; - ++i; - if (oob) { - huffTab[i].val = 0; - huffTab[i].prefixLen = huffDecoder->readBits(prefixBits); - huffTab[i].rangeLen = jbig2HuffmanOOB; - ++i; - } - huffTab[i].val = 0; - huffTab[i].prefixLen = 0; - huffTab[i].rangeLen = jbig2HuffmanEOT; - huffDecoder->buildTable(huffTab, i); - - // create and store the new table segment - segments->append(new JBIG2CodeTable(segNum, huffTab)); - - return; - - eofError: - error(getPos(), "Unexpected EOF in JBIG2 stream"); -} - -void JBIG2Stream::readExtensionSeg(Guint length) { - Guint i; - - // skip the segment - for (i = 0; i < length; ++i) { - curStr->getChar(); - } -} - -JBIG2Segment *JBIG2Stream::findSegment(Guint segNum) { - JBIG2Segment *seg; - int i; - - for (i = 0; i < globalSegments->getLength(); ++i) { - seg = (JBIG2Segment *)globalSegments->get(i); - if (seg->getSegNum() == segNum) { - return seg; - } - } - for (i = 0; i < segments->getLength(); ++i) { - seg = (JBIG2Segment *)segments->get(i); - if (seg->getSegNum() == segNum) { - return seg; - } - } - return NULL; -} - -void JBIG2Stream::discardSegment(Guint segNum) { - JBIG2Segment *seg; - int i; - - for (i = 0; i < globalSegments->getLength(); ++i) { - seg = (JBIG2Segment *)globalSegments->get(i); - if (seg->getSegNum() == segNum) { - globalSegments->del(i); - return; - } - } - for (i = 0; i < segments->getLength(); ++i) { - seg = (JBIG2Segment *)segments->get(i); - if (seg->getSegNum() == segNum) { - segments->del(i); - return; - } - } -} - -void JBIG2Stream::resetGenericStats(Guint templ, - JArithmeticDecoderStats *prevStats) { - int size; - - size = contextSize[templ]; - if (prevStats && prevStats->getContextSize() == size) { - if (genericRegionStats->getContextSize() == size) { - genericRegionStats->copyFrom(prevStats); - } else { - delete genericRegionStats; - genericRegionStats = prevStats->copy(); - } - } else { - if (genericRegionStats->getContextSize() == size) { - genericRegionStats->reset(); - } else { - delete genericRegionStats; - genericRegionStats = new JArithmeticDecoderStats(1 << size); - } - } -} - -void JBIG2Stream::resetRefinementStats(Guint templ, - JArithmeticDecoderStats *prevStats) { - int size; - - size = refContextSize[templ]; - if (prevStats && prevStats->getContextSize() == size) { - if (refinementRegionStats->getContextSize() == size) { - refinementRegionStats->copyFrom(prevStats); - } else { - delete refinementRegionStats; - refinementRegionStats = prevStats->copy(); - } - } else { - if (refinementRegionStats->getContextSize() == size) { - refinementRegionStats->reset(); - } else { - delete refinementRegionStats; - refinementRegionStats = new JArithmeticDecoderStats(1 << size); - } - } -} - -void JBIG2Stream::resetIntStats(int symCodeLen) { - iadhStats->reset(); - iadwStats->reset(); - iaexStats->reset(); - iaaiStats->reset(); - iadtStats->reset(); - iaitStats->reset(); - iafsStats->reset(); - iadsStats->reset(); - iardxStats->reset(); - iardyStats->reset(); - iardwStats->reset(); - iardhStats->reset(); - iariStats->reset(); - if (iaidStats->getContextSize() == symCodeLen + 1) { - iaidStats->reset(); - } else { - delete iaidStats; - iaidStats = new JArithmeticDecoderStats(1 << (symCodeLen + 1)); - } -} - -GBool JBIG2Stream::readUByte(Guint *x) { - int c0; - - if ((c0 = curStr->getChar()) == EOF) { - return gFalse; - } - *x = (Guint)c0; - return gTrue; -} - -GBool JBIG2Stream::readByte(int *x) { - int c0; - - if ((c0 = curStr->getChar()) == EOF) { - return gFalse; - } - *x = c0; - if (c0 & 0x80) { - *x |= -1 - 0xff; - } - return gTrue; -} - -GBool JBIG2Stream::readUWord(Guint *x) { - int c0, c1; - - if ((c0 = curStr->getChar()) == EOF || - (c1 = curStr->getChar()) == EOF) { - return gFalse; - } - *x = (Guint)((c0 << 8) | c1); - return gTrue; -} - -GBool JBIG2Stream::readULong(Guint *x) { - int c0, c1, c2, c3; - - if ((c0 = curStr->getChar()) == EOF || - (c1 = curStr->getChar()) == EOF || - (c2 = curStr->getChar()) == EOF || - (c3 = curStr->getChar()) == EOF) { - return gFalse; - } - *x = (Guint)((c0 << 24) | (c1 << 16) | (c2 << 8) | c3); - return gTrue; -} - -GBool JBIG2Stream::readLong(int *x) { - int c0, c1, c2, c3; - - if ((c0 = curStr->getChar()) == EOF || - (c1 = curStr->getChar()) == EOF || - (c2 = curStr->getChar()) == EOF || - (c3 = curStr->getChar()) == EOF) { - return gFalse; - } - *x = ((c0 << 24) | (c1 << 16) | (c2 << 8) | c3); - if (c0 & 0x80) { - *x |= -1 - (int)0xffffffff; - } - return gTrue; -} diff --git a/pdftops/JBIG2Stream.h b/pdftops/JBIG2Stream.h deleted file mode 100644 index 13b4d917a..000000000 --- a/pdftops/JBIG2Stream.h +++ /dev/null @@ -1,143 +0,0 @@ -//======================================================================== -// -// JBIG2Stream.h -// -// Copyright 2002-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef JBIG2STREAM_H -#define JBIG2STREAM_H - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "gtypes.h" -#include "Object.h" -#include "Stream.h" - -class GList; -class JBIG2Segment; -class JBIG2Bitmap; -class JArithmeticDecoder; -class JArithmeticDecoderStats; -class JBIG2HuffmanDecoder; -struct JBIG2HuffmanTable; -class JBIG2MMRDecoder; - -//------------------------------------------------------------------------ - -class JBIG2Stream: public FilterStream { -public: - - JBIG2Stream(Stream *strA, Object *globalsStream); - virtual ~JBIG2Stream(); - virtual StreamKind getKind() { return strJBIG2; } - virtual void reset(); - virtual int getChar(); - virtual int lookChar(); - virtual GString *getPSFilter(int psLevel, char *indent); - virtual GBool isBinary(GBool last = gTrue); - -private: - - void readSegments(); - GBool readSymbolDictSeg(Guint segNum, Guint length, - Guint *refSegs, Guint nRefSegs); - void readTextRegionSeg(Guint segNum, GBool imm, - GBool lossless, Guint length, - Guint *refSegs, Guint nRefSegs); - JBIG2Bitmap *readTextRegion(GBool huff, GBool refine, - int w, int h, - Guint numInstances, - Guint logStrips, - int numSyms, - JBIG2HuffmanTable *symCodeTab, - Guint symCodeLen, - JBIG2Bitmap **syms, - Guint defPixel, Guint combOp, - Guint transposed, Guint refCorner, - int sOffset, - JBIG2HuffmanTable *huffFSTable, - JBIG2HuffmanTable *huffDSTable, - JBIG2HuffmanTable *huffDTTable, - JBIG2HuffmanTable *huffRDWTable, - JBIG2HuffmanTable *huffRDHTable, - JBIG2HuffmanTable *huffRDXTable, - JBIG2HuffmanTable *huffRDYTable, - JBIG2HuffmanTable *huffRSizeTable, - Guint templ, - int *atx, int *aty); - void readPatternDictSeg(Guint segNum, Guint length); - void readHalftoneRegionSeg(Guint segNum, GBool imm, - GBool lossless, Guint length, - Guint *refSegs, Guint nRefSegs); - void readGenericRegionSeg(Guint segNum, GBool imm, - GBool lossless, Guint length); - JBIG2Bitmap *readGenericBitmap(GBool mmr, int w, int h, - int templ, GBool tpgdOn, - GBool useSkip, JBIG2Bitmap *skip, - int *atx, int *aty, - int mmrDataLength); - void readGenericRefinementRegionSeg(Guint segNum, GBool imm, - GBool lossless, Guint length, - Guint *refSegs, - Guint nRefSegs); - JBIG2Bitmap *readGenericRefinementRegion(int w, int h, - int templ, GBool tpgrOn, - JBIG2Bitmap *refBitmap, - int refDX, int refDY, - int *atx, int *aty); - void readPageInfoSeg(Guint length); - void readEndOfStripeSeg(Guint length); - void readProfilesSeg(Guint length); - void readCodeTableSeg(Guint segNum, Guint length); - void readExtensionSeg(Guint length); - JBIG2Segment *findSegment(Guint segNum); - void discardSegment(Guint segNum); - void resetGenericStats(Guint templ, - JArithmeticDecoderStats *prevStats); - void resetRefinementStats(Guint templ, - JArithmeticDecoderStats *prevStats); - void resetIntStats(int symCodeLen); - GBool readUByte(Guint *x); - GBool readByte(int *x); - GBool readUWord(Guint *x); - GBool readULong(Guint *x); - GBool readLong(int *x); - - Guint pageW, pageH, curPageH; - Guint pageDefPixel; - JBIG2Bitmap *pageBitmap; - Guint defCombOp; - GList *segments; // [JBIG2Segment] - GList *globalSegments; // [JBIG2Segment] - Stream *curStr; - Guchar *dataPtr; - Guchar *dataEnd; - - JArithmeticDecoder *arithDecoder; - JArithmeticDecoderStats *genericRegionStats; - JArithmeticDecoderStats *refinementRegionStats; - JArithmeticDecoderStats *iadhStats; - JArithmeticDecoderStats *iadwStats; - JArithmeticDecoderStats *iaexStats; - JArithmeticDecoderStats *iaaiStats; - JArithmeticDecoderStats *iadtStats; - JArithmeticDecoderStats *iaitStats; - JArithmeticDecoderStats *iafsStats; - JArithmeticDecoderStats *iadsStats; - JArithmeticDecoderStats *iardxStats; - JArithmeticDecoderStats *iardyStats; - JArithmeticDecoderStats *iardwStats; - JArithmeticDecoderStats *iardhStats; - JArithmeticDecoderStats *iariStats; - JArithmeticDecoderStats *iaidStats; - JBIG2HuffmanDecoder *huffDecoder; - JBIG2MMRDecoder *mmrDecoder; -}; - -#endif diff --git a/pdftops/JPXStream.cxx b/pdftops/JPXStream.cxx deleted file mode 100644 index 2022462ad..000000000 --- a/pdftops/JPXStream.cxx +++ /dev/null @@ -1,2955 +0,0 @@ -//======================================================================== -// -// JPXStream.cc -// -// Copyright 2002-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include <limits.h> -#include "gmem.h" -#include "Error.h" -#include "JArithmeticDecoder.h" -#include "JPXStream.h" - -//~ to do: -// - precincts -// - ROI -// - progression order changes -// - packed packet headers -// - support for palettes, channel maps, etc. -// - make sure all needed JP2/JPX subboxes are parsed (readBoxes) -// - can we assume that QCC segments must come after the QCD segment? -// - skip EPH markers (readTilePartData) -// - handle tilePartToEOC in readTilePartData -// - deal with multiple codeword segments (readTilePartData, -// readCodeBlockData) -// - progression orders 2, 3, and 4 -// - in coefficient decoding (readCodeBlockData): -// - termination pattern: terminate after every coding pass -// - error resilience segmentation symbol -// - selective arithmetic coding bypass -// - vertically causal context formation -// - coeffs longer than 31 bits (should just ignore the extra bits?) -// - handle boxes larger than 2^32 bytes -// - the fixed-point arithmetic won't handle 16-bit pixels - -//------------------------------------------------------------------------ - -// number of contexts for the arithmetic decoder -#define jpxNContexts 19 - -#define jpxContextSigProp 0 // 0 - 8: significance prop and cleanup -#define jpxContextSign 9 // 9 - 13: sign -#define jpxContextMagRef 14 // 14 -16: magnitude refinement -#define jpxContextRunLength 17 // cleanup: run length -#define jpxContextUniform 18 // cleanup: first signif coeff - -//------------------------------------------------------------------------ - -#define jpxPassSigProp 0 -#define jpxPassMagRef 1 -#define jpxPassCleanup 2 - -//------------------------------------------------------------------------ - -// arithmetic decoder context for the significance propagation and -// cleanup passes: -// [horiz][vert][diag][subband] -// where subband = 0 for HL -// = 1 for LH and LL -// = 2 for HH -static Guint sigPropContext[3][3][5][3] = { - {{{ 0, 0, 0 }, // horiz=0, vert=0, diag=0 - { 1, 1, 3 }, // horiz=0, vert=0, diag=1 - { 2, 2, 6 }, // horiz=0, vert=0, diag=2 - { 2, 2, 8 }, // horiz=0, vert=0, diag=3 - { 2, 2, 8 }}, // horiz=0, vert=0, diag=4 - {{ 5, 3, 1 }, // horiz=0, vert=1, diag=0 - { 6, 3, 4 }, // horiz=0, vert=1, diag=1 - { 6, 3, 7 }, // horiz=0, vert=1, diag=2 - { 6, 3, 8 }, // horiz=0, vert=1, diag=3 - { 6, 3, 8 }}, // horiz=0, vert=1, diag=4 - {{ 8, 4, 2 }, // horiz=0, vert=2, diag=0 - { 8, 4, 5 }, // horiz=0, vert=2, diag=1 - { 8, 4, 7 }, // horiz=0, vert=2, diag=2 - { 8, 4, 8 }, // horiz=0, vert=2, diag=3 - { 8, 4, 8 }}}, // horiz=0, vert=2, diag=4 - {{{ 3, 5, 1 }, // horiz=1, vert=0, diag=0 - { 3, 6, 4 }, // horiz=1, vert=0, diag=1 - { 3, 6, 7 }, // horiz=1, vert=0, diag=2 - { 3, 6, 8 }, // horiz=1, vert=0, diag=3 - { 3, 6, 8 }}, // horiz=1, vert=0, diag=4 - {{ 7, 7, 2 }, // horiz=1, vert=1, diag=0 - { 7, 7, 5 }, // horiz=1, vert=1, diag=1 - { 7, 7, 7 }, // horiz=1, vert=1, diag=2 - { 7, 7, 8 }, // horiz=1, vert=1, diag=3 - { 7, 7, 8 }}, // horiz=1, vert=1, diag=4 - {{ 8, 7, 2 }, // horiz=1, vert=2, diag=0 - { 8, 7, 5 }, // horiz=1, vert=2, diag=1 - { 8, 7, 7 }, // horiz=1, vert=2, diag=2 - { 8, 7, 8 }, // horiz=1, vert=2, diag=3 - { 8, 7, 8 }}}, // horiz=1, vert=2, diag=4 - {{{ 4, 8, 2 }, // horiz=2, vert=0, diag=0 - { 4, 8, 5 }, // horiz=2, vert=0, diag=1 - { 4, 8, 7 }, // horiz=2, vert=0, diag=2 - { 4, 8, 8 }, // horiz=2, vert=0, diag=3 - { 4, 8, 8 }}, // horiz=2, vert=0, diag=4 - {{ 7, 8, 2 }, // horiz=2, vert=1, diag=0 - { 7, 8, 5 }, // horiz=2, vert=1, diag=1 - { 7, 8, 7 }, // horiz=2, vert=1, diag=2 - { 7, 8, 8 }, // horiz=2, vert=1, diag=3 - { 7, 8, 8 }}, // horiz=2, vert=1, diag=4 - {{ 8, 8, 2 }, // horiz=2, vert=2, diag=0 - { 8, 8, 5 }, // horiz=2, vert=2, diag=1 - { 8, 8, 7 }, // horiz=2, vert=2, diag=2 - { 8, 8, 8 }, // horiz=2, vert=2, diag=3 - { 8, 8, 8 }}} // horiz=2, vert=2, diag=4 -}; - -// arithmetic decoder context and xor bit for the sign bit in the -// significance propagation pass: -// [horiz][vert][k] -// where horiz/vert are offset by 2 (i.e., range is -2 .. 2) -// and k = 0 for the context -// = 1 for the xor bit -static Guint signContext[5][5][2] = { - {{ 13, 1 }, // horiz=-2, vert=-2 - { 13, 1 }, // horiz=-2, vert=-1 - { 12, 1 }, // horiz=-2, vert= 0 - { 11, 1 }, // horiz=-2, vert=+1 - { 11, 1 }}, // horiz=-2, vert=+2 - {{ 13, 1 }, // horiz=-1, vert=-2 - { 13, 1 }, // horiz=-1, vert=-1 - { 12, 1 }, // horiz=-1, vert= 0 - { 11, 1 }, // horiz=-1, vert=+1 - { 11, 1 }}, // horiz=-1, vert=+2 - {{ 10, 1 }, // horiz= 0, vert=-2 - { 10, 1 }, // horiz= 0, vert=-1 - { 9, 0 }, // horiz= 0, vert= 0 - { 10, 0 }, // horiz= 0, vert=+1 - { 10, 0 }}, // horiz= 0, vert=+2 - {{ 11, 0 }, // horiz=+1, vert=-2 - { 11, 0 }, // horiz=+1, vert=-1 - { 12, 0 }, // horiz=+1, vert= 0 - { 13, 0 }, // horiz=+1, vert=+1 - { 13, 0 }}, // horiz=+1, vert=+2 - {{ 11, 0 }, // horiz=+2, vert=-2 - { 11, 0 }, // horiz=+2, vert=-1 - { 12, 0 }, // horiz=+2, vert= 0 - { 13, 0 }, // horiz=+2, vert=+1 - { 13, 0 }}, // horiz=+2, vert=+2 -}; - -//------------------------------------------------------------------------ - -// constants used in the IDWT -#define idwtAlpha -1.586134342059924 -#define idwtBeta -0.052980118572961 -#define idwtGamma 0.882911075530934 -#define idwtDelta 0.443506852043971 -#define idwtKappa 1.230174104914001 -#define idwtIKappa (1.0 / idwtKappa) - -// number of bits to the right of the decimal point for the fixed -// point arithmetic used in the IDWT -#define fracBits 16 - -//------------------------------------------------------------------------ - -// floor(x / y) -#define jpxFloorDiv(x, y) ((x) / (y)) - -// floor(x / 2^y) -#define jpxFloorDivPow2(x, y) ((x) >> (y)) - -// ceil(x / y) -#define jpxCeilDiv(x, y) (((x) + (y) - 1) / (y)) - -// ceil(x / 2^y) -#define jpxCeilDivPow2(x, y) (((x) + (1 << (y)) - 1) >> (y)) - -//------------------------------------------------------------------------ - -JPXStream::JPXStream(Stream *strA): - FilterStream(strA) -{ - nComps = 0; - bpc = NULL; - width = height = 0; - haveCS = gFalse; - havePalette = gFalse; - haveCompMap = gFalse; - haveChannelDefn = gFalse; - - img.tiles = NULL; - bitBuf = 0; - bitBufLen = 0; - bitBufSkip = gFalse; - byteCount = 0; -} - -JPXStream::~JPXStream() { - JPXTile *tile; - JPXTileComp *tileComp; - JPXResLevel *resLevel; - JPXPrecinct *precinct; - JPXSubband *subband; - JPXCodeBlock *cb; - Guint comp, i, k, r, pre, sb; - - gfree(bpc); - if (havePalette) { - gfree(palette.bpc); - gfree(palette.c); - } - if (haveCompMap) { - gfree(compMap.comp); - gfree(compMap.type); - gfree(compMap.pComp); - } - if (haveChannelDefn) { - gfree(channelDefn.idx); - gfree(channelDefn.type); - gfree(channelDefn.assoc); - } - - if (img.tiles) { - for (i = 0; i < img.nXTiles * img.nYTiles; ++i) { - tile = &img.tiles[i]; - if (tile->tileComps) { - for (comp = 0; comp < img.nComps; ++comp) { - tileComp = &tile->tileComps[comp]; - gfree(tileComp->quantSteps); - gfree(tileComp->data); - gfree(tileComp->buf); - if (tileComp->resLevels) { - for (r = 0; r <= tileComp->nDecompLevels; ++r) { - resLevel = &tileComp->resLevels[r]; - if (resLevel->precincts) { - for (pre = 0; pre < 1; ++pre) { - precinct = &resLevel->precincts[pre]; - if (precinct->subbands) { - for (sb = 0; sb < (r == 0 ? 1 : 3); ++sb) { - subband = &precinct->subbands[sb]; - gfree(subband->inclusion); - gfree(subband->zeroBitPlane); - if (subband->cbs) { - for (k = 0; k < subband->nXCBs * subband->nYCBs; ++k) { - cb = &subband->cbs[k]; - gfree(cb->coeffs); - if (cb->arithDecoder) { - delete cb->arithDecoder; - } - if (cb->stats) { - delete cb->stats; - } - } - gfree(subband->cbs); - } - } - gfree(precinct->subbands); - } - } - gfree(img.tiles[i].tileComps[comp].resLevels[r].precincts); - } - } - gfree(img.tiles[i].tileComps[comp].resLevels); - } - } - gfree(img.tiles[i].tileComps); - } - } - gfree(img.tiles); - } - delete str; -} - -void JPXStream::reset() { - str->reset(); - if (readBoxes()) { - curY = img.yOffset; - } else { - // readBoxes reported an error, so we go immediately to EOF - curY = img.ySize; - } - curX = img.xOffset; - curComp = 0; - readBufLen = 0; -} - -int JPXStream::getChar() { - int c; - - if (readBufLen < 8) { - fillReadBuf(); - } - if (readBufLen == 8) { - c = readBuf & 0xff; - readBufLen = 0; - } else if (readBufLen > 8) { - c = (readBuf >> (readBufLen - 8)) & 0xff; - readBufLen -= 8; - } else if (readBufLen == 0) { - c = EOF; - } else { - c = (readBuf << (8 - readBufLen)) & 0xff; - readBufLen = 0; - } - return c; -} - -int JPXStream::lookChar() { - int c; - - if (readBufLen < 8) { - fillReadBuf(); - } - if (readBufLen == 8) { - c = readBuf & 0xff; - } else if (readBufLen > 8) { - c = (readBuf >> (readBufLen - 8)) & 0xff; - } else if (readBufLen == 0) { - c = EOF; - } else { - c = (readBuf << (8 - readBufLen)) & 0xff; - } - return c; -} - -void JPXStream::fillReadBuf() { - JPXTileComp *tileComp; - Guint tileIdx, tx, ty; - int pix, pixBits; - - do { - if (curY >= img.ySize) { - return; - } - tileIdx = ((curY - img.yTileOffset) / img.yTileSize) * img.nXTiles - + (curX - img.xTileOffset) / img.xTileSize; -#if 1 //~ ignore the palette, assume the PDF ColorSpace object is valid - tileComp = &img.tiles[tileIdx].tileComps[curComp]; -#else - tileComp = &img.tiles[tileIdx].tileComps[havePalette ? 0 : curComp]; -#endif - tx = jpxCeilDiv((curX - img.xTileOffset) % img.xTileSize, tileComp->hSep); - ty = jpxCeilDiv((curY - img.yTileOffset) % img.yTileSize, tileComp->vSep); - pix = (int)tileComp->data[ty * (tileComp->x1 - tileComp->x0) + tx]; - pixBits = tileComp->prec; -#if 1 //~ ignore the palette, assume the PDF ColorSpace object is valid - if (++curComp == img.nComps) { -#else - if (havePalette) { - if (pix >= 0 && pix < palette.nEntries) { - pix = palette.c[pix * palette.nComps + curComp]; - } else { - pix = - pixBits = palette.bpc[curComp]; - } - if (++curComp == (Guint)(havePalette ? palette.nComps : img.nComps)) { -#endif - curComp = 0; - if (++curX == img.xSize) { - curX = img.xOffset; - ++curY; - } - } - if (pixBits == 8) { - readBuf = (readBuf << 8) | (pix & 0xff); - } else { - readBuf = (readBuf << pixBits) | (pix & ((1 << pixBits) - 1)); - } - readBufLen += pixBits; - } while (readBufLen < 8); -} - -GString *JPXStream::getPSFilter(int psLevel, char *indent) { - return NULL; -} - -GBool JPXStream::isBinary(GBool last) { - return str->isBinary(gTrue); -} - -void JPXStream::getImageParams(int *bitsPerComponent, - StreamColorSpaceMode *csMode) { - Guint boxType, boxLen, dataLen, csEnum; - Guint bpc1, dummy, i; - int csMeth, csPrec, csPrec1, dummy2; - StreamColorSpaceMode csMode1; - GBool haveBPC, haveCSMode; - - csPrec = 0; // make gcc happy - haveBPC = haveCSMode = gFalse; - str->reset(); - if (str->lookChar() == 0xff) { - getImageParams2(bitsPerComponent, csMode); - } else { - while (readBoxHdr(&boxType, &boxLen, &dataLen)) { - if (boxType == 0x6a703268) { // JP2 header - // skip the superbox - } else if (boxType == 0x69686472) { // image header - if (readULong(&dummy) && - readULong(&dummy) && - readUWord(&dummy) && - readUByte(&bpc1) && - readUByte(&dummy) && - readUByte(&dummy) && - readUByte(&dummy)) { - *bitsPerComponent = bpc1 + 1; - haveBPC = gTrue; - } - } else if (boxType == 0x636F6C72) { // color specification - if (readByte(&csMeth) && - readByte(&csPrec1) && - readByte(&dummy2)) { - if (csMeth == 1) { - if (readULong(&csEnum)) { - csMode1 = streamCSNone; - if (csEnum == jpxCSBiLevel || - csEnum == jpxCSGrayscale) { - csMode1 = streamCSDeviceGray; - } else if (csEnum == jpxCSCMYK) { - csMode1 = streamCSDeviceCMYK; - } else if (csEnum == jpxCSsRGB || - csEnum == jpxCSCISesRGB || - csEnum == jpxCSROMMRGB) { - csMode1 = streamCSDeviceRGB; - } - if (csMode1 != streamCSNone && - (!haveCSMode || csPrec1 > csPrec)) { - *csMode = csMode1; - csPrec = csPrec1; - haveCSMode = gTrue; - } - for (i = 0; i < dataLen - 7; ++i) { - str->getChar(); - } - } - } else { - for (i = 0; i < dataLen - 3; ++i) { - str->getChar(); - } - } - } - } else if (boxType == 0x6A703263) { // codestream - if (!(haveBPC && haveCSMode)) { - getImageParams2(bitsPerComponent, csMode); - } - break; - } else { - for (i = 0; i < dataLen; ++i) { - str->getChar(); - } - } - } - } - str->close(); -} - -// Get image parameters from the codestream. -void JPXStream::getImageParams2(int *bitsPerComponent, - StreamColorSpaceMode *csMode) { - int segType; - Guint segLen, nComps1, bpc1, dummy, i; - - while (readMarkerHdr(&segType, &segLen)) { - if (segType == 0x51) { // SIZ - image and tile size - if (readUWord(&dummy) && - readULong(&dummy) && - readULong(&dummy) && - readULong(&dummy) && - readULong(&dummy) && - readULong(&dummy) && - readULong(&dummy) && - readULong(&dummy) && - readULong(&dummy) && - readUWord(&nComps1) && - readUByte(&bpc1)) { - *bitsPerComponent = (bpc1 & 0x7f) + 1; - // if there's no color space info, take a guess - if (nComps1 == 1) { - *csMode = streamCSDeviceGray; - } else if (nComps1 == 3) { - *csMode = streamCSDeviceRGB; - } else if (nComps1 == 4) { - *csMode = streamCSDeviceCMYK; - } - } - break; - } else { - if (segLen > 2) { - for (i = 0; i < segLen - 2; ++i) { - str->getChar(); - } - } - } - } -} - -GBool JPXStream::readBoxes() { - Guint boxType, boxLen, dataLen; - Guint bpc1, compression, unknownColorspace, ipr; - Guint i, j; - - haveImgHdr = gFalse; - - // check for a naked JPEG 2000 codestream (without the JP2/JPX - // wrapper) -- this appears to be a violation of the PDF spec, but - // Acrobat allows it - if (str->lookChar() == 0xff) { - error(getPos(), "Naked JPEG 2000 codestream, missing JP2/JPX wrapper"); - readCodestream(0); - nComps = img.nComps; - bpc = (Guint *)gmallocn(nComps, sizeof(Guint)); - for (i = 0; i < nComps; ++i) { - bpc[i] = img.tiles[0].tileComps[i].prec; - } - width = img.xSize - img.xOffset; - height = img.ySize - img.yOffset; - return gTrue; - } - - while (readBoxHdr(&boxType, &boxLen, &dataLen)) { - switch (boxType) { - case 0x6a703268: // JP2 header - // this is a grouping box ('superbox') which has no real - // contents and doesn't appear to be used consistently, i.e., - // some things which should be subboxes of the JP2 header box - // show up outside of it - so we simply ignore the JP2 header - // box - break; - case 0x69686472: // image header - if (!readULong(&height) || - !readULong(&width) || - !readUWord(&nComps) || - !readUByte(&bpc1) || - !readUByte(&compression) || - !readUByte(&unknownColorspace) || - !readUByte(&ipr)) { - error(getPos(), "Unexpected EOF in JPX stream"); - return gFalse; - } - if (compression != 7) { - error(getPos(), "Unknown compression type in JPX stream"); - return gFalse; - } - bpc = (Guint *)gmallocn(nComps, sizeof(Guint)); - for (i = 0; i < nComps; ++i) { - bpc[i] = bpc1; - } - haveImgHdr = gTrue; - break; - case 0x62706363: // bits per component - if (!haveImgHdr) { - error(getPos(), "Found bits per component box before image header box in JPX stream"); - return gFalse; - } - if (dataLen != nComps) { - error(getPos(), "Invalid bits per component box in JPX stream"); - return gFalse; - } - for (i = 0; i < nComps; ++i) { - if (!readUByte(&bpc[i])) { - error(getPos(), "Unexpected EOF in JPX stream"); - return gFalse; - } - } - break; - case 0x636F6C72: // color specification - if (!readColorSpecBox(dataLen)) { - return gFalse; - } - break; - case 0x70636c72: // palette - if (!readUWord(&palette.nEntries) || - !readUByte(&palette.nComps)) { - error(getPos(), "Unexpected EOF in JPX stream"); - return gFalse; - } - palette.bpc = (Guint *)gmallocn(palette.nComps, sizeof(Guint)); - palette.c = - (int *)gmallocn(palette.nEntries * palette.nComps, sizeof(int)); - for (i = 0; i < palette.nComps; ++i) { - if (!readUByte(&palette.bpc[i])) { - error(getPos(), "Unexpected EOF in JPX stream"); - return gFalse; - } - ++palette.bpc[i]; - } - for (i = 0; i < palette.nEntries; ++i) { - for (j = 0; j < palette.nComps; ++j) { - if (!readNBytes(((palette.bpc[j] & 0x7f) + 7) >> 3, - (palette.bpc[j] & 0x80) ? gTrue : gFalse, - &palette.c[i * palette.nComps + j])) { - error(getPos(), "Unexpected EOF in JPX stream"); - return gFalse; - } - } - } - havePalette = gTrue; - break; - case 0x636d6170: // component mapping - compMap.nChannels = dataLen / 4; - compMap.comp = (Guint *)gmallocn(compMap.nChannels, sizeof(Guint)); - compMap.type = (Guint *)gmallocn(compMap.nChannels, sizeof(Guint)); - compMap.pComp = (Guint *)gmallocn(compMap.nChannels, sizeof(Guint)); - for (i = 0; i < compMap.nChannels; ++i) { - if (!readUWord(&compMap.comp[i]) || - !readUByte(&compMap.type[i]) || - !readUByte(&compMap.pComp[i])) { - error(getPos(), "Unexpected EOF in JPX stream"); - return gFalse; - } - } - haveCompMap = gTrue; - break; - case 0x63646566: // channel definition - if (!readUWord(&channelDefn.nChannels)) { - error(getPos(), "Unexpected EOF in JPX stream"); - return gFalse; - } - channelDefn.idx = - (Guint *)gmallocn(channelDefn.nChannels, sizeof(Guint)); - channelDefn.type = - (Guint *)gmallocn(channelDefn.nChannels, sizeof(Guint)); - channelDefn.assoc = - (Guint *)gmallocn(channelDefn.nChannels, sizeof(Guint)); - for (i = 0; i < channelDefn.nChannels; ++i) { - if (!readUWord(&channelDefn.idx[i]) || - !readUWord(&channelDefn.type[i]) || - !readUWord(&channelDefn.assoc[i])) { - error(getPos(), "Unexpected EOF in JPX stream"); - return gFalse; - } - } - haveChannelDefn = gTrue; - break; - case 0x6A703263: // contiguous codestream - if (!bpc) { - error(getPos(), "JPX stream is missing the image header box"); - } - if (!haveCS) { - error(getPos(), "JPX stream has no supported color spec"); - } - if (!readCodestream(dataLen)) { - return gFalse; - } - break; - default: - for (i = 0; i < dataLen; ++i) { - if (str->getChar() == EOF) { - error(getPos(), "Unexpected EOF in JPX stream"); - return gFalse; - } - } - break; - } - } - return gTrue; -} - -GBool JPXStream::readColorSpecBox(Guint dataLen) { - JPXColorSpec newCS; - Guint csApprox, csEnum; - Guint i; - GBool ok; - - ok = gFalse; - if (!readUByte(&newCS.meth) || - !readByte(&newCS.prec) || - !readUByte(&csApprox)) { - goto err; - } - switch (newCS.meth) { - case 1: // enumerated colorspace - if (!readULong(&csEnum)) { - goto err; - } - newCS.enumerated.type = (JPXColorSpaceType)csEnum; - switch (newCS.enumerated.type) { - case jpxCSBiLevel: - ok = gTrue; - break; - case jpxCSYCbCr1: - ok = gTrue; - break; - case jpxCSYCbCr2: - ok = gTrue; - break; - case jpxCSYCBCr3: - ok = gTrue; - break; - case jpxCSPhotoYCC: - ok = gTrue; - break; - case jpxCSCMY: - ok = gTrue; - break; - case jpxCSCMYK: - ok = gTrue; - break; - case jpxCSYCCK: - ok = gTrue; - break; - case jpxCSCIELab: - if (dataLen == 7 + 7*4) { - if (!readULong(&newCS.enumerated.cieLab.rl) || - !readULong(&newCS.enumerated.cieLab.ol) || - !readULong(&newCS.enumerated.cieLab.ra) || - !readULong(&newCS.enumerated.cieLab.oa) || - !readULong(&newCS.enumerated.cieLab.rb) || - !readULong(&newCS.enumerated.cieLab.ob) || - !readULong(&newCS.enumerated.cieLab.il)) { - goto err; - } - } else if (dataLen == 7) { - //~ this assumes the 8-bit case - newCS.enumerated.cieLab.rl = 100; - newCS.enumerated.cieLab.ol = 0; - newCS.enumerated.cieLab.ra = 255; - newCS.enumerated.cieLab.oa = 128; - newCS.enumerated.cieLab.rb = 255; - newCS.enumerated.cieLab.ob = 96; - newCS.enumerated.cieLab.il = 0x00443530; - } else { - goto err; - } - ok = gTrue; - break; - case jpxCSsRGB: - ok = gTrue; - break; - case jpxCSGrayscale: - ok = gTrue; - break; - case jpxCSBiLevel2: - ok = gTrue; - break; - case jpxCSCIEJab: - // not allowed in PDF - goto err; - case jpxCSCISesRGB: - ok = gTrue; - break; - case jpxCSROMMRGB: - ok = gTrue; - break; - case jpxCSsRGBYCbCr: - ok = gTrue; - break; - case jpxCSYPbPr1125: - ok = gTrue; - break; - case jpxCSYPbPr1250: - ok = gTrue; - break; - default: - goto err; - } - break; - case 2: // restricted ICC profile - case 3: // any ICC profile (JPX) - case 4: // vendor color (JPX) - for (i = 0; i < dataLen - 3; ++i) { - if (str->getChar() == EOF) { - goto err; - } - } - break; - } - - if (ok && (!haveCS || newCS.prec > cs.prec)) { - cs = newCS; - haveCS = gTrue; - } - - return gTrue; - - err: - error(getPos(), "Error in JPX color spec"); - return gFalse; -} - -GBool JPXStream::readCodestream(Guint len) { - JPXTile *tile; - JPXTileComp *tileComp; - int segType; - GBool haveSIZ, haveCOD, haveQCD, haveSOT; - Guint precinctSize, style; - Guint segLen, capabilities, comp, i, j, r; - - //----- main header - haveSIZ = haveCOD = haveQCD = haveSOT = gFalse; - do { - if (!readMarkerHdr(&segType, &segLen)) { - error(getPos(), "Error in JPX codestream"); - return gFalse; - } - switch (segType) { - case 0x4f: // SOC - start of codestream - // marker only - break; - case 0x51: // SIZ - image and tile size - if (!readUWord(&capabilities) || - !readULong(&img.xSize) || - !readULong(&img.ySize) || - !readULong(&img.xOffset) || - !readULong(&img.yOffset) || - !readULong(&img.xTileSize) || - !readULong(&img.yTileSize) || - !readULong(&img.xTileOffset) || - !readULong(&img.yTileOffset) || - !readUWord(&img.nComps)) { - error(getPos(), "Error in JPX SIZ marker segment"); - return gFalse; - } - if (haveImgHdr && img.nComps != nComps) { - error(getPos(), "Different number of components in JPX SIZ marker segment"); - return gFalse; - } - img.nXTiles = (img.xSize - img.xTileOffset + img.xTileSize - 1) - / img.xTileSize; - img.nYTiles = (img.ySize - img.yTileOffset + img.yTileSize - 1) - / img.yTileSize; - // check for overflow before allocating memory - if (img.nXTiles <= 0 || img.nYTiles <= 0 || - img.nXTiles >= INT_MAX / img.nYTiles) { - error(getPos(), "Bad tile count in JPX SIZ marker segment"); - return gFalse; - } - img.tiles = (JPXTile *)gmallocn(img.nXTiles * img.nYTiles, - sizeof(JPXTile)); - for (i = 0; i < img.nXTiles * img.nYTiles; ++i) { - img.tiles[i].tileComps = (JPXTileComp *)gmallocn(img.nComps, - sizeof(JPXTileComp)); - for (comp = 0; comp < img.nComps; ++comp) { - img.tiles[i].tileComps[comp].quantSteps = NULL; - img.tiles[i].tileComps[comp].data = NULL; - img.tiles[i].tileComps[comp].buf = NULL; - img.tiles[i].tileComps[comp].resLevels = NULL; - } - } - for (comp = 0; comp < img.nComps; ++comp) { - if (!readUByte(&img.tiles[0].tileComps[comp].prec) || - !readUByte(&img.tiles[0].tileComps[comp].hSep) || - !readUByte(&img.tiles[0].tileComps[comp].vSep)) { - error(getPos(), "Error in JPX SIZ marker segment"); - return gFalse; - } - img.tiles[0].tileComps[comp].sgned = - (img.tiles[0].tileComps[comp].prec & 0x80) ? gTrue : gFalse; - img.tiles[0].tileComps[comp].prec = - (img.tiles[0].tileComps[comp].prec & 0x7f) + 1; - for (i = 1; i < img.nXTiles * img.nYTiles; ++i) { - img.tiles[i].tileComps[comp] = img.tiles[0].tileComps[comp]; - } - } - haveSIZ = gTrue; - break; - case 0x52: // COD - coding style default - if (!readUByte(&img.tiles[0].tileComps[0].style) || - !readUByte(&img.tiles[0].progOrder) || - !readUWord(&img.tiles[0].nLayers) || - !readUByte(&img.tiles[0].multiComp) || - !readUByte(&img.tiles[0].tileComps[0].nDecompLevels) || - !readUByte(&img.tiles[0].tileComps[0].codeBlockW) || - !readUByte(&img.tiles[0].tileComps[0].codeBlockH) || - !readUByte(&img.tiles[0].tileComps[0].codeBlockStyle) || - !readUByte(&img.tiles[0].tileComps[0].transform)) { - error(getPos(), "Error in JPX COD marker segment"); - return gFalse; - } - img.tiles[0].tileComps[0].codeBlockW += 2; - img.tiles[0].tileComps[0].codeBlockH += 2; - for (i = 0; i < img.nXTiles * img.nYTiles; ++i) { - if (i != 0) { - img.tiles[i].progOrder = img.tiles[0].progOrder; - img.tiles[i].nLayers = img.tiles[0].nLayers; - img.tiles[i].multiComp = img.tiles[0].multiComp; - } - for (comp = 0; comp < img.nComps; ++comp) { - if (!(i == 0 && comp == 0)) { - img.tiles[i].tileComps[comp].style = - img.tiles[0].tileComps[0].style; - img.tiles[i].tileComps[comp].nDecompLevels = - img.tiles[0].tileComps[0].nDecompLevels; - img.tiles[i].tileComps[comp].codeBlockW = - img.tiles[0].tileComps[0].codeBlockW; - img.tiles[i].tileComps[comp].codeBlockH = - img.tiles[0].tileComps[0].codeBlockH; - img.tiles[i].tileComps[comp].codeBlockStyle = - img.tiles[0].tileComps[0].codeBlockStyle; - img.tiles[i].tileComps[comp].transform = - img.tiles[0].tileComps[0].transform; - } - img.tiles[i].tileComps[comp].resLevels = - (JPXResLevel *)gmallocn( - (img.tiles[i].tileComps[comp].nDecompLevels + 1), - sizeof(JPXResLevel)); - for (r = 0; r <= img.tiles[i].tileComps[comp].nDecompLevels; ++r) { - img.tiles[i].tileComps[comp].resLevels[r].precincts = NULL; - } - } - } - for (r = 0; r <= img.tiles[0].tileComps[0].nDecompLevels; ++r) { - if (img.tiles[0].tileComps[0].style & 0x01) { - if (!readUByte(&precinctSize)) { - error(getPos(), "Error in JPX COD marker segment"); - return gFalse; - } - img.tiles[0].tileComps[0].resLevels[r].precinctWidth = - precinctSize & 0x0f; - img.tiles[0].tileComps[0].resLevels[r].precinctHeight = - (precinctSize >> 4) & 0x0f; - } else { - img.tiles[0].tileComps[0].resLevels[r].precinctWidth = 15; - img.tiles[0].tileComps[0].resLevels[r].precinctHeight = 15; - } - } - for (i = 0; i < img.nXTiles * img.nYTiles; ++i) { - for (comp = 0; comp < img.nComps; ++comp) { - if (!(i == 0 && comp == 0)) { - for (r = 0; r <= img.tiles[i].tileComps[comp].nDecompLevels; ++r) { - img.tiles[i].tileComps[comp].resLevels[r].precinctWidth = - img.tiles[0].tileComps[0].resLevels[r].precinctWidth; - img.tiles[i].tileComps[comp].resLevels[r].precinctHeight = - img.tiles[0].tileComps[0].resLevels[r].precinctHeight; - } - } - } - } - haveCOD = gTrue; - break; - case 0x53: // COC - coding style component - if (!haveCOD) { - error(getPos(), "JPX COC marker segment before COD segment"); - return gFalse; - } - if ((img.nComps > 256 && !readUWord(&comp)) || - (img.nComps <= 256 && !readUByte(&comp)) || - comp >= img.nComps || - !readUByte(&style) || - !readUByte(&img.tiles[0].tileComps[comp].nDecompLevels) || - !readUByte(&img.tiles[0].tileComps[comp].codeBlockW) || - !readUByte(&img.tiles[0].tileComps[comp].codeBlockH) || - !readUByte(&img.tiles[0].tileComps[comp].codeBlockStyle) || - !readUByte(&img.tiles[0].tileComps[comp].transform)) { - error(getPos(), "Error in JPX COC marker segment"); - return gFalse; - } - img.tiles[0].tileComps[comp].style = - (img.tiles[0].tileComps[comp].style & ~1) | (style & 1); - img.tiles[0].tileComps[comp].codeBlockW += 2; - img.tiles[0].tileComps[comp].codeBlockH += 2; - for (i = 0; i < img.nXTiles * img.nYTiles; ++i) { - if (i != 0) { - img.tiles[i].tileComps[comp].style = - img.tiles[0].tileComps[comp].style; - img.tiles[i].tileComps[comp].nDecompLevels = - img.tiles[0].tileComps[comp].nDecompLevels; - img.tiles[i].tileComps[comp].codeBlockW = - img.tiles[0].tileComps[comp].codeBlockW; - img.tiles[i].tileComps[comp].codeBlockH = - img.tiles[0].tileComps[comp].codeBlockH; - img.tiles[i].tileComps[comp].codeBlockStyle = - img.tiles[0].tileComps[comp].codeBlockStyle; - img.tiles[i].tileComps[comp].transform = - img.tiles[0].tileComps[comp].transform; - } - img.tiles[i].tileComps[comp].resLevels = - (JPXResLevel *)greallocn( - img.tiles[i].tileComps[comp].resLevels, - (img.tiles[i].tileComps[comp].nDecompLevels + 1), - sizeof(JPXResLevel)); - for (r = 0; r <= img.tiles[i].tileComps[comp].nDecompLevels; ++r) { - img.tiles[i].tileComps[comp].resLevels[r].precincts = NULL; - } - } - for (r = 0; r <= img.tiles[0].tileComps[comp].nDecompLevels; ++r) { - if (img.tiles[0].tileComps[comp].style & 0x01) { - if (!readUByte(&precinctSize)) { - error(getPos(), "Error in JPX COD marker segment"); - return gFalse; - } - img.tiles[0].tileComps[comp].resLevels[r].precinctWidth = - precinctSize & 0x0f; - img.tiles[0].tileComps[comp].resLevels[r].precinctHeight = - (precinctSize >> 4) & 0x0f; - } else { - img.tiles[0].tileComps[comp].resLevels[r].precinctWidth = 15; - img.tiles[0].tileComps[comp].resLevels[r].precinctHeight = 15; - } - } - for (i = 1; i < img.nXTiles * img.nYTiles; ++i) { - for (r = 0; r <= img.tiles[i].tileComps[comp].nDecompLevels; ++r) { - img.tiles[i].tileComps[comp].resLevels[r].precinctWidth = - img.tiles[0].tileComps[comp].resLevels[r].precinctWidth; - img.tiles[i].tileComps[comp].resLevels[r].precinctHeight = - img.tiles[0].tileComps[comp].resLevels[r].precinctHeight; - } - } - break; - case 0x5c: // QCD - quantization default - if (!readUByte(&img.tiles[0].tileComps[0].quantStyle)) { - error(getPos(), "Error in JPX QCD marker segment"); - return gFalse; - } - if ((img.tiles[0].tileComps[0].quantStyle & 0x1f) == 0x00) { - img.tiles[0].tileComps[0].nQuantSteps = segLen - 3; - img.tiles[0].tileComps[0].quantSteps = - (Guint *)greallocn(img.tiles[0].tileComps[0].quantSteps, - img.tiles[0].tileComps[0].nQuantSteps, - sizeof(Guint)); - for (i = 0; i < img.tiles[0].tileComps[0].nQuantSteps; ++i) { - if (!readUByte(&img.tiles[0].tileComps[0].quantSteps[i])) { - error(getPos(), "Error in JPX QCD marker segment"); - return gFalse; - } - } - } else if ((img.tiles[0].tileComps[0].quantStyle & 0x1f) == 0x01) { - img.tiles[0].tileComps[0].nQuantSteps = 1; - img.tiles[0].tileComps[0].quantSteps = - (Guint *)greallocn(img.tiles[0].tileComps[0].quantSteps, - img.tiles[0].tileComps[0].nQuantSteps, - sizeof(Guint)); - if (!readUWord(&img.tiles[0].tileComps[0].quantSteps[0])) { - error(getPos(), "Error in JPX QCD marker segment"); - return gFalse; - } - } else if ((img.tiles[0].tileComps[0].quantStyle & 0x1f) == 0x02) { - img.tiles[0].tileComps[0].nQuantSteps = (segLen - 3) / 2; - img.tiles[0].tileComps[0].quantSteps = - (Guint *)greallocn(img.tiles[0].tileComps[0].quantSteps, - img.tiles[0].tileComps[0].nQuantSteps, - sizeof(Guint)); - for (i = 0; i < img.tiles[0].tileComps[0].nQuantSteps; ++i) { - if (!readUWord(&img.tiles[0].tileComps[0].quantSteps[i])) { - error(getPos(), "Error in JPX QCD marker segment"); - return gFalse; - } - } - } else { - error(getPos(), "Error in JPX QCD marker segment"); - return gFalse; - } - for (i = 0; i < img.nXTiles * img.nYTiles; ++i) { - for (comp = 0; comp < img.nComps; ++comp) { - if (!(i == 0 && comp == 0)) { - img.tiles[i].tileComps[comp].quantStyle = - img.tiles[0].tileComps[0].quantStyle; - img.tiles[i].tileComps[comp].nQuantSteps = - img.tiles[0].tileComps[0].nQuantSteps; - img.tiles[i].tileComps[comp].quantSteps = - (Guint *)greallocn(img.tiles[i].tileComps[comp].quantSteps, - img.tiles[0].tileComps[0].nQuantSteps, - sizeof(Guint)); - for (j = 0; j < img.tiles[0].tileComps[0].nQuantSteps; ++j) { - img.tiles[i].tileComps[comp].quantSteps[j] = - img.tiles[0].tileComps[0].quantSteps[j]; - } - } - } - } - haveQCD = gTrue; - break; - case 0x5d: // QCC - quantization component - if (!haveQCD) { - error(getPos(), "JPX QCC marker segment before QCD segment"); - return gFalse; - } - if ((img.nComps > 256 && !readUWord(&comp)) || - (img.nComps <= 256 && !readUByte(&comp)) || - comp >= img.nComps || - !readUByte(&img.tiles[0].tileComps[comp].quantStyle)) { - error(getPos(), "Error in JPX QCC marker segment"); - return gFalse; - } - if ((img.tiles[0].tileComps[comp].quantStyle & 0x1f) == 0x00) { - img.tiles[0].tileComps[comp].nQuantSteps = - segLen - (img.nComps > 256 ? 5 : 4); - img.tiles[0].tileComps[comp].quantSteps = - (Guint *)greallocn(img.tiles[0].tileComps[comp].quantSteps, - img.tiles[0].tileComps[comp].nQuantSteps, - sizeof(Guint)); - for (i = 0; i < img.tiles[0].tileComps[comp].nQuantSteps; ++i) { - if (!readUByte(&img.tiles[0].tileComps[comp].quantSteps[i])) { - error(getPos(), "Error in JPX QCC marker segment"); - return gFalse; - } - } - } else if ((img.tiles[0].tileComps[comp].quantStyle & 0x1f) == 0x01) { - img.tiles[0].tileComps[comp].nQuantSteps = 1; - img.tiles[0].tileComps[comp].quantSteps = - (Guint *)greallocn(img.tiles[0].tileComps[comp].quantSteps, - img.tiles[0].tileComps[comp].nQuantSteps, - sizeof(Guint)); - if (!readUWord(&img.tiles[0].tileComps[comp].quantSteps[0])) { - error(getPos(), "Error in JPX QCC marker segment"); - return gFalse; - } - } else if ((img.tiles[0].tileComps[comp].quantStyle & 0x1f) == 0x02) { - img.tiles[0].tileComps[comp].nQuantSteps = - (segLen - (img.nComps > 256 ? 5 : 4)) / 2; - img.tiles[0].tileComps[comp].quantSteps = - (Guint *)greallocn(img.tiles[0].tileComps[comp].quantSteps, - img.tiles[0].tileComps[comp].nQuantSteps, - sizeof(Guint)); - for (i = 0; i < img.tiles[0].tileComps[comp].nQuantSteps; ++i) { - if (!readUWord(&img.tiles[0].tileComps[comp].quantSteps[i])) { - error(getPos(), "Error in JPX QCD marker segment"); - return gFalse; - } - } - } else { - error(getPos(), "Error in JPX QCC marker segment"); - return gFalse; - } - for (i = 1; i < img.nXTiles * img.nYTiles; ++i) { - img.tiles[i].tileComps[comp].quantStyle = - img.tiles[0].tileComps[comp].quantStyle; - img.tiles[i].tileComps[comp].nQuantSteps = - img.tiles[0].tileComps[comp].nQuantSteps; - img.tiles[i].tileComps[comp].quantSteps = - (Guint *)greallocn(img.tiles[i].tileComps[comp].quantSteps, - img.tiles[0].tileComps[comp].nQuantSteps, - sizeof(Guint)); - for (j = 0; j < img.tiles[0].tileComps[comp].nQuantSteps; ++j) { - img.tiles[i].tileComps[comp].quantSteps[j] = - img.tiles[0].tileComps[comp].quantSteps[j]; - } - } - break; - case 0x5e: // RGN - region of interest -#if 1 //~ ROI is unimplemented - fprintf(stderr, "RGN\n"); - for (i = 0; i < segLen - 2; ++i) { - if (str->getChar() == EOF) { - error(getPos(), "Error in JPX PPM marker segment"); - return gFalse; - } - } -#else - if ((img.nComps > 256 && !readUWord(&comp)) || - (img.nComps <= 256 && !readUByte(&comp)) || - comp >= img.nComps || - !readUByte(&compInfo[comp].defROI.style) || - !readUByte(&compInfo[comp].defROI.shift)) { - error(getPos(), "Error in JPX RGN marker segment"); - return gFalse; - } -#endif - break; - case 0x5f: // POC - progression order change -#if 1 //~ progression order changes are unimplemented - fprintf(stderr, "POC\n"); - for (i = 0; i < segLen - 2; ++i) { - if (str->getChar() == EOF) { - error(getPos(), "Error in JPX PPM marker segment"); - return gFalse; - } - } -#else - nProgs = (segLen - 2) / (img.nComps > 256 ? 9 : 7); - progs = (JPXProgOrder *)gmallocn(nProgs, sizeof(JPXProgOrder)); - for (i = 0; i < nProgs; ++i) { - if (!readUByte(&progs[i].startRes) || - !(img.nComps > 256 && readUWord(&progs[i].startComp)) || - !(img.nComps <= 256 && readUByte(&progs[i].startComp)) || - !readUWord(&progs[i].endLayer) || - !readUByte(&progs[i].endRes) || - !(img.nComps > 256 && readUWord(&progs[i].endComp)) || - !(img.nComps <= 256 && readUByte(&progs[i].endComp)) || - !readUByte(&progs[i].progOrder)) { - error(getPos(), "Error in JPX POC marker segment"); - return gFalse; - } - } -#endif - break; - case 0x60: // PPM - packed packet headers, main header -#if 1 //~ packed packet headers are unimplemented - fprintf(stderr, "PPM\n"); - for (i = 0; i < segLen - 2; ++i) { - if (str->getChar() == EOF) { - error(getPos(), "Error in JPX PPM marker segment"); - return gFalse; - } - } -#endif - break; - case 0x55: // TLM - tile-part lengths - // skipped - for (i = 0; i < segLen - 2; ++i) { - if (str->getChar() == EOF) { - error(getPos(), "Error in JPX TLM marker segment"); - return gFalse; - } - } - break; - case 0x57: // PLM - packet length, main header - // skipped - for (i = 0; i < segLen - 2; ++i) { - if (str->getChar() == EOF) { - error(getPos(), "Error in JPX PLM marker segment"); - return gFalse; - } - } - break; - case 0x63: // CRG - component registration - // skipped - for (i = 0; i < segLen - 2; ++i) { - if (str->getChar() == EOF) { - error(getPos(), "Error in JPX CRG marker segment"); - return gFalse; - } - } - break; - case 0x64: // COM - comment - // skipped - for (i = 0; i < segLen - 2; ++i) { - if (str->getChar() == EOF) { - error(getPos(), "Error in JPX COM marker segment"); - return gFalse; - } - } - break; - case 0x90: // SOT - start of tile - haveSOT = gTrue; - break; - default: - error(getPos(), "Unknown marker segment %02x in JPX stream", segType); - for (i = 0; i < segLen - 2; ++i) { - if (str->getChar() == EOF) { - break; - } - } - break; - } - } while (!haveSOT); - - if (!haveSIZ) { - error(getPos(), "Missing SIZ marker segment in JPX stream"); - return gFalse; - } - if (!haveCOD) { - error(getPos(), "Missing COD marker segment in JPX stream"); - return gFalse; - } - if (!haveQCD) { - error(getPos(), "Missing QCD marker segment in JPX stream"); - return gFalse; - } - - //----- read the tile-parts - while (1) { - if (!readTilePart()) { - return gFalse; - } - if (!readMarkerHdr(&segType, &segLen)) { - error(getPos(), "Error in JPX codestream"); - return gFalse; - } - if (segType != 0x90) { // SOT - start of tile - break; - } - } - - if (segType != 0xd9) { // EOC - end of codestream - error(getPos(), "Missing EOC marker in JPX codestream"); - return gFalse; - } - - //----- finish decoding the image - for (i = 0; i < img.nXTiles * img.nYTiles; ++i) { - tile = &img.tiles[i]; - for (comp = 0; comp < img.nComps; ++comp) { - tileComp = &tile->tileComps[comp]; - inverseTransform(tileComp); - } - if (!inverseMultiCompAndDC(tile)) { - return gFalse; - } - } - - //~ can free memory below tileComps here, and also tileComp.buf - - return gTrue; -} - -GBool JPXStream::readTilePart() { - JPXTile *tile; - JPXTileComp *tileComp; - JPXResLevel *resLevel; - JPXPrecinct *precinct; - JPXSubband *subband; - JPXCodeBlock *cb; - GBool haveSOD; - Guint tileIdx, tilePartLen, tilePartIdx, nTileParts; - GBool tilePartToEOC; - Guint precinctSize, style; - Guint n, nSBs, nx, ny, sbx0, sby0, comp, segLen; - Guint i, j, k, cbX, cbY, r, pre, sb, cbi; - int segType, level; - - // process the SOT marker segment - if (!readUWord(&tileIdx) || - !readULong(&tilePartLen) || - !readUByte(&tilePartIdx) || - !readUByte(&nTileParts)) { - error(getPos(), "Error in JPX SOT marker segment"); - return gFalse; - } - - if (tileIdx >= img.nXTiles * img.nYTiles) { - error(getPos(), "Weird tile index in JPX stream"); - return gFalse; - } - - tilePartToEOC = tilePartLen == 0; - tilePartLen -= 12; // subtract size of SOT segment - - haveSOD = gFalse; - do { - if (!readMarkerHdr(&segType, &segLen)) { - error(getPos(), "Error in JPX tile-part codestream"); - return gFalse; - } - tilePartLen -= 2 + segLen; - switch (segType) { - case 0x52: // COD - coding style default - if (!readUByte(&img.tiles[tileIdx].tileComps[0].style) || - !readUByte(&img.tiles[tileIdx].progOrder) || - !readUWord(&img.tiles[tileIdx].nLayers) || - !readUByte(&img.tiles[tileIdx].multiComp) || - !readUByte(&img.tiles[tileIdx].tileComps[0].nDecompLevels) || - !readUByte(&img.tiles[tileIdx].tileComps[0].codeBlockW) || - !readUByte(&img.tiles[tileIdx].tileComps[0].codeBlockH) || - !readUByte(&img.tiles[tileIdx].tileComps[0].codeBlockStyle) || - !readUByte(&img.tiles[tileIdx].tileComps[0].transform)) { - error(getPos(), "Error in JPX COD marker segment"); - return gFalse; - } - img.tiles[tileIdx].tileComps[0].codeBlockW += 2; - img.tiles[tileIdx].tileComps[0].codeBlockH += 2; - for (comp = 0; comp < img.nComps; ++comp) { - if (comp != 0) { - img.tiles[tileIdx].tileComps[comp].style = - img.tiles[tileIdx].tileComps[0].style; - img.tiles[tileIdx].tileComps[comp].nDecompLevels = - img.tiles[tileIdx].tileComps[0].nDecompLevels; - img.tiles[tileIdx].tileComps[comp].codeBlockW = - img.tiles[tileIdx].tileComps[0].codeBlockW; - img.tiles[tileIdx].tileComps[comp].codeBlockH = - img.tiles[tileIdx].tileComps[0].codeBlockH; - img.tiles[tileIdx].tileComps[comp].codeBlockStyle = - img.tiles[tileIdx].tileComps[0].codeBlockStyle; - img.tiles[tileIdx].tileComps[comp].transform = - img.tiles[tileIdx].tileComps[0].transform; - } - img.tiles[tileIdx].tileComps[comp].resLevels = - (JPXResLevel *)greallocn( - img.tiles[tileIdx].tileComps[comp].resLevels, - (img.tiles[tileIdx].tileComps[comp].nDecompLevels + 1), - sizeof(JPXResLevel)); - for (r = 0; - r <= img.tiles[tileIdx].tileComps[comp].nDecompLevels; - ++r) { - img.tiles[tileIdx].tileComps[comp].resLevels[r].precincts = NULL; - } - } - for (r = 0; r <= img.tiles[tileIdx].tileComps[0].nDecompLevels; ++r) { - if (img.tiles[tileIdx].tileComps[0].style & 0x01) { - if (!readUByte(&precinctSize)) { - error(getPos(), "Error in JPX COD marker segment"); - return gFalse; - } - img.tiles[tileIdx].tileComps[0].resLevels[r].precinctWidth = - precinctSize & 0x0f; - img.tiles[tileIdx].tileComps[0].resLevels[r].precinctHeight = - (precinctSize >> 4) & 0x0f; - } else { - img.tiles[tileIdx].tileComps[0].resLevels[r].precinctWidth = 15; - img.tiles[tileIdx].tileComps[0].resLevels[r].precinctHeight = 15; - } - } - for (comp = 1; comp < img.nComps; ++comp) { - for (r = 0; - r <= img.tiles[tileIdx].tileComps[comp].nDecompLevels; - ++r) { - img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctWidth = - img.tiles[tileIdx].tileComps[0].resLevels[r].precinctWidth; - img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctHeight = - img.tiles[tileIdx].tileComps[0].resLevels[r].precinctHeight; - } - } - break; - case 0x53: // COC - coding style component - if ((img.nComps > 256 && !readUWord(&comp)) || - (img.nComps <= 256 && !readUByte(&comp)) || - comp >= img.nComps || - !readUByte(&style) || - !readUByte(&img.tiles[tileIdx].tileComps[comp].nDecompLevels) || - !readUByte(&img.tiles[tileIdx].tileComps[comp].codeBlockW) || - !readUByte(&img.tiles[tileIdx].tileComps[comp].codeBlockH) || - !readUByte(&img.tiles[tileIdx].tileComps[comp].codeBlockStyle) || - !readUByte(&img.tiles[tileIdx].tileComps[comp].transform)) { - error(getPos(), "Error in JPX COC marker segment"); - return gFalse; - } - img.tiles[tileIdx].tileComps[comp].style = - (img.tiles[tileIdx].tileComps[comp].style & ~1) | (style & 1); - img.tiles[tileIdx].tileComps[comp].codeBlockW += 2; - img.tiles[tileIdx].tileComps[comp].codeBlockH += 2; - img.tiles[tileIdx].tileComps[comp].resLevels = - (JPXResLevel *)greallocn( - img.tiles[tileIdx].tileComps[comp].resLevels, - (img.tiles[tileIdx].tileComps[comp].nDecompLevels + 1), - sizeof(JPXResLevel)); - for (r = 0; r <= img.tiles[tileIdx].tileComps[comp].nDecompLevels; ++r) { - img.tiles[tileIdx].tileComps[comp].resLevels[r].precincts = NULL; - } - for (r = 0; r <= img.tiles[tileIdx].tileComps[comp].nDecompLevels; ++r) { - if (img.tiles[tileIdx].tileComps[comp].style & 0x01) { - if (!readUByte(&precinctSize)) { - error(getPos(), "Error in JPX COD marker segment"); - return gFalse; - } - img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctWidth = - precinctSize & 0x0f; - img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctHeight = - (precinctSize >> 4) & 0x0f; - } else { - img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctWidth = 15; - img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctHeight = 15; - } - } - break; - case 0x5c: // QCD - quantization default - if (!readUByte(&img.tiles[tileIdx].tileComps[0].quantStyle)) { - error(getPos(), "Error in JPX QCD marker segment"); - return gFalse; - } - if ((img.tiles[tileIdx].tileComps[0].quantStyle & 0x1f) == 0x00) { - img.tiles[tileIdx].tileComps[0].nQuantSteps = - segLen - 3; - img.tiles[tileIdx].tileComps[0].quantSteps = - (Guint *)greallocn(img.tiles[tileIdx].tileComps[0].quantSteps, - img.tiles[tileIdx].tileComps[0].nQuantSteps, - sizeof(Guint)); - for (i = 0; i < img.tiles[tileIdx].tileComps[0].nQuantSteps; ++i) { - if (!readUByte(&img.tiles[tileIdx].tileComps[0].quantSteps[i])) { - error(getPos(), "Error in JPX QCD marker segment"); - return gFalse; - } - } - } else if ((img.tiles[tileIdx].tileComps[0].quantStyle & 0x1f) == 0x01) { - img.tiles[tileIdx].tileComps[0].nQuantSteps = 1; - img.tiles[tileIdx].tileComps[0].quantSteps = - (Guint *)greallocn(img.tiles[tileIdx].tileComps[0].quantSteps, - img.tiles[tileIdx].tileComps[0].nQuantSteps, - sizeof(Guint)); - if (!readUWord(&img.tiles[tileIdx].tileComps[0].quantSteps[0])) { - error(getPos(), "Error in JPX QCD marker segment"); - return gFalse; - } - } else if ((img.tiles[tileIdx].tileComps[0].quantStyle & 0x1f) == 0x02) { - img.tiles[tileIdx].tileComps[0].nQuantSteps = (segLen - 3) / 2; - img.tiles[tileIdx].tileComps[0].quantSteps = - (Guint *)greallocn(img.tiles[tileIdx].tileComps[0].quantSteps, - img.tiles[tileIdx].tileComps[0].nQuantSteps, - sizeof(Guint)); - for (i = 0; i < img.tiles[tileIdx].tileComps[0].nQuantSteps; ++i) { - if (!readUWord(&img.tiles[tileIdx].tileComps[0].quantSteps[i])) { - error(getPos(), "Error in JPX QCD marker segment"); - return gFalse; - } - } - } else { - error(getPos(), "Error in JPX QCD marker segment"); - return gFalse; - } - for (comp = 1; comp < img.nComps; ++comp) { - img.tiles[tileIdx].tileComps[comp].quantStyle = - img.tiles[tileIdx].tileComps[0].quantStyle; - img.tiles[tileIdx].tileComps[comp].nQuantSteps = - img.tiles[tileIdx].tileComps[0].nQuantSteps; - img.tiles[tileIdx].tileComps[comp].quantSteps = - (Guint *)greallocn(img.tiles[tileIdx].tileComps[comp].quantSteps, - img.tiles[tileIdx].tileComps[0].nQuantSteps, - sizeof(Guint)); - for (j = 0; j < img.tiles[tileIdx].tileComps[0].nQuantSteps; ++j) { - img.tiles[tileIdx].tileComps[comp].quantSteps[j] = - img.tiles[tileIdx].tileComps[0].quantSteps[j]; - } - } - break; - case 0x5d: // QCC - quantization component - if ((img.nComps > 256 && !readUWord(&comp)) || - (img.nComps <= 256 && !readUByte(&comp)) || - comp >= img.nComps || - !readUByte(&img.tiles[tileIdx].tileComps[comp].quantStyle)) { - error(getPos(), "Error in JPX QCC marker segment"); - return gFalse; - } - if ((img.tiles[tileIdx].tileComps[comp].quantStyle & 0x1f) == 0x00) { - img.tiles[tileIdx].tileComps[comp].nQuantSteps = - segLen - (img.nComps > 256 ? 5 : 4); - img.tiles[tileIdx].tileComps[comp].quantSteps = - (Guint *)greallocn(img.tiles[tileIdx].tileComps[comp].quantSteps, - img.tiles[tileIdx].tileComps[comp].nQuantSteps, - sizeof(Guint)); - for (i = 0; i < img.tiles[tileIdx].tileComps[comp].nQuantSteps; ++i) { - if (!readUByte(&img.tiles[tileIdx].tileComps[comp].quantSteps[i])) { - error(getPos(), "Error in JPX QCC marker segment"); - return gFalse; - } - } - } else if ((img.tiles[tileIdx].tileComps[comp].quantStyle & 0x1f) - == 0x01) { - img.tiles[tileIdx].tileComps[comp].nQuantSteps = 1; - img.tiles[tileIdx].tileComps[comp].quantSteps = - (Guint *)greallocn(img.tiles[tileIdx].tileComps[comp].quantSteps, - img.tiles[tileIdx].tileComps[comp].nQuantSteps, - sizeof(Guint)); - if (!readUWord(&img.tiles[tileIdx].tileComps[comp].quantSteps[0])) { - error(getPos(), "Error in JPX QCC marker segment"); - return gFalse; - } - } else if ((img.tiles[tileIdx].tileComps[comp].quantStyle & 0x1f) - == 0x02) { - img.tiles[tileIdx].tileComps[comp].nQuantSteps = - (segLen - (img.nComps > 256 ? 5 : 4)) / 2; - img.tiles[tileIdx].tileComps[comp].quantSteps = - (Guint *)greallocn(img.tiles[tileIdx].tileComps[comp].quantSteps, - img.tiles[tileIdx].tileComps[comp].nQuantSteps, - sizeof(Guint)); - for (i = 0; i < img.tiles[tileIdx].tileComps[comp].nQuantSteps; ++i) { - if (!readUWord(&img.tiles[tileIdx].tileComps[comp].quantSteps[i])) { - error(getPos(), "Error in JPX QCD marker segment"); - return gFalse; - } - } - } else { - error(getPos(), "Error in JPX QCC marker segment"); - return gFalse; - } - break; - case 0x5e: // RGN - region of interest -#if 1 //~ ROI is unimplemented - fprintf(stderr, "RGN\n"); - for (i = 0; i < segLen - 2; ++i) { - if (str->getChar() == EOF) { - error(getPos(), "Error in JPX PPM marker segment"); - return gFalse; - } - } -#else - if ((img.nComps > 256 && !readUWord(&comp)) || - (img.nComps <= 256 && !readUByte(&comp)) || - comp >= img.nComps || - !readUByte(&compInfo[comp].roi.style) || - !readUByte(&compInfo[comp].roi.shift)) { - error(getPos(), "Error in JPX RGN marker segment"); - return gFalse; - } -#endif - break; - case 0x5f: // POC - progression order change -#if 1 //~ progression order changes are unimplemented - fprintf(stderr, "POC\n"); - for (i = 0; i < segLen - 2; ++i) { - if (str->getChar() == EOF) { - error(getPos(), "Error in JPX PPM marker segment"); - return gFalse; - } - } -#else - nTileProgs = (segLen - 2) / (img.nComps > 256 ? 9 : 7); - tileProgs = (JPXProgOrder *)gmallocn(nTileProgs, sizeof(JPXProgOrder)); - for (i = 0; i < nTileProgs; ++i) { - if (!readUByte(&tileProgs[i].startRes) || - !(img.nComps > 256 && readUWord(&tileProgs[i].startComp)) || - !(img.nComps <= 256 && readUByte(&tileProgs[i].startComp)) || - !readUWord(&tileProgs[i].endLayer) || - !readUByte(&tileProgs[i].endRes) || - !(img.nComps > 256 && readUWord(&tileProgs[i].endComp)) || - !(img.nComps <= 256 && readUByte(&tileProgs[i].endComp)) || - !readUByte(&tileProgs[i].progOrder)) { - error(getPos(), "Error in JPX POC marker segment"); - return gFalse; - } - } -#endif - break; - case 0x61: // PPT - packed packet headers, tile-part hdr -#if 1 //~ packed packet headers are unimplemented - fprintf(stderr, "PPT\n"); - for (i = 0; i < segLen - 2; ++i) { - if (str->getChar() == EOF) { - error(getPos(), "Error in JPX PPT marker segment"); - return gFalse; - } - } -#endif - case 0x58: // PLT - packet length, tile-part header - // skipped - for (i = 0; i < segLen - 2; ++i) { - if (str->getChar() == EOF) { - error(getPos(), "Error in JPX PLT marker segment"); - return gFalse; - } - } - break; - case 0x64: // COM - comment - // skipped - for (i = 0; i < segLen - 2; ++i) { - if (str->getChar() == EOF) { - error(getPos(), "Error in JPX COM marker segment"); - return gFalse; - } - } - break; - case 0x93: // SOD - start of data - haveSOD = gTrue; - break; - default: - error(getPos(), "Unknown marker segment %02x in JPX tile-part stream", - segType); - for (i = 0; i < segLen - 2; ++i) { - if (str->getChar() == EOF) { - break; - } - } - break; - } - } while (!haveSOD); - - //----- initialize the tile, precincts, and code-blocks - if (tilePartIdx == 0) { - tile = &img.tiles[tileIdx]; - i = tileIdx / img.nXTiles; - j = tileIdx % img.nXTiles; - if ((tile->x0 = img.xTileOffset + j * img.xTileSize) < img.xOffset) { - tile->x0 = img.xOffset; - } - if ((tile->y0 = img.yTileOffset + i * img.yTileSize) < img.yOffset) { - tile->y0 = img.yOffset; - } - if ((tile->x1 = img.xTileOffset + (j + 1) * img.xTileSize) > img.xSize) { - tile->x1 = img.xSize; - } - if ((tile->y1 = img.yTileOffset + (i + 1) * img.yTileSize) > img.ySize) { - tile->y1 = img.ySize; - } - tile->comp = 0; - tile->res = 0; - tile->precinct = 0; - tile->layer = 0; - tile->maxNDecompLevels = 0; - for (comp = 0; comp < img.nComps; ++comp) { - tileComp = &tile->tileComps[comp]; - if (tileComp->nDecompLevels > tile->maxNDecompLevels) { - tile->maxNDecompLevels = tileComp->nDecompLevels; - } - tileComp->x0 = jpxCeilDiv(tile->x0, tileComp->hSep); - tileComp->y0 = jpxCeilDiv(tile->y0, tileComp->hSep); - tileComp->x1 = jpxCeilDiv(tile->x1, tileComp->hSep); - tileComp->y1 = jpxCeilDiv(tile->y1, tileComp->hSep); - tileComp->cbW = 1 << tileComp->codeBlockW; - tileComp->cbH = 1 << tileComp->codeBlockH; - tileComp->data = (int *)gmallocn((tileComp->x1 - tileComp->x0) * - (tileComp->y1 - tileComp->y0), - sizeof(int)); - if (tileComp->x1 - tileComp->x0 > tileComp->y1 - tileComp->y0) { - n = tileComp->x1 - tileComp->x0; - } else { - n = tileComp->y1 - tileComp->y0; - } - tileComp->buf = (int *)gmallocn(n + 8, sizeof(int)); - for (r = 0; r <= tileComp->nDecompLevels; ++r) { - resLevel = &tileComp->resLevels[r]; - k = r == 0 ? tileComp->nDecompLevels - : tileComp->nDecompLevels - r + 1; - resLevel->x0 = jpxCeilDivPow2(tileComp->x0, k); - resLevel->y0 = jpxCeilDivPow2(tileComp->y0, k); - resLevel->x1 = jpxCeilDivPow2(tileComp->x1, k); - resLevel->y1 = jpxCeilDivPow2(tileComp->y1, k); - if (r == 0) { - resLevel->bx0[0] = resLevel->x0; - resLevel->by0[0] = resLevel->y0; - resLevel->bx1[0] = resLevel->x1; - resLevel->by1[0] = resLevel->y1; - } else { - resLevel->bx0[0] = jpxCeilDivPow2(tileComp->x0 - (1 << (k-1)), k); - resLevel->by0[0] = resLevel->y0; - resLevel->bx1[0] = jpxCeilDivPow2(tileComp->x1 - (1 << (k-1)), k); - resLevel->by1[0] = resLevel->y1; - resLevel->bx0[1] = resLevel->x0; - resLevel->by0[1] = jpxCeilDivPow2(tileComp->y0 - (1 << (k-1)), k); - resLevel->bx1[1] = resLevel->x1; - resLevel->by1[1] = jpxCeilDivPow2(tileComp->y1 - (1 << (k-1)), k); - resLevel->bx0[2] = jpxCeilDivPow2(tileComp->x0 - (1 << (k-1)), k); - resLevel->by0[2] = jpxCeilDivPow2(tileComp->y0 - (1 << (k-1)), k); - resLevel->bx1[2] = jpxCeilDivPow2(tileComp->x1 - (1 << (k-1)), k); - resLevel->by1[2] = jpxCeilDivPow2(tileComp->y1 - (1 << (k-1)), k); - } - resLevel->precincts = (JPXPrecinct *)gmallocn(1, sizeof(JPXPrecinct)); - for (pre = 0; pre < 1; ++pre) { - precinct = &resLevel->precincts[pre]; - precinct->x0 = resLevel->x0; - precinct->y0 = resLevel->y0; - precinct->x1 = resLevel->x1; - precinct->y1 = resLevel->y1; - nSBs = r == 0 ? 1 : 3; - precinct->subbands = - (JPXSubband *)gmallocn(nSBs, sizeof(JPXSubband)); - for (sb = 0; sb < nSBs; ++sb) { - subband = &precinct->subbands[sb]; - subband->x0 = resLevel->bx0[sb]; - subband->y0 = resLevel->by0[sb]; - subband->x1 = resLevel->bx1[sb]; - subband->y1 = resLevel->by1[sb]; - subband->nXCBs = jpxCeilDivPow2(subband->x1, - tileComp->codeBlockW) - - jpxFloorDivPow2(subband->x0, - tileComp->codeBlockW); - subband->nYCBs = jpxCeilDivPow2(subband->y1, - tileComp->codeBlockH) - - jpxFloorDivPow2(subband->y0, - tileComp->codeBlockH); - n = subband->nXCBs > subband->nYCBs ? subband->nXCBs - : subband->nYCBs; - for (subband->maxTTLevel = 0, --n; - n; - ++subband->maxTTLevel, n >>= 1) ; - n = 0; - for (level = subband->maxTTLevel; level >= 0; --level) { - nx = jpxCeilDivPow2(subband->nXCBs, level); - ny = jpxCeilDivPow2(subband->nYCBs, level); - n += nx * ny; - } - subband->inclusion = - (JPXTagTreeNode *)gmallocn(n, sizeof(JPXTagTreeNode)); - subband->zeroBitPlane = - (JPXTagTreeNode *)gmallocn(n, sizeof(JPXTagTreeNode)); - for (k = 0; k < n; ++k) { - subband->inclusion[k].finished = gFalse; - subband->inclusion[k].val = 0; - subband->zeroBitPlane[k].finished = gFalse; - subband->zeroBitPlane[k].val = 0; - } - subband->cbs = (JPXCodeBlock *)gmallocn(subband->nXCBs * - subband->nYCBs, - sizeof(JPXCodeBlock)); - sbx0 = jpxFloorDivPow2(subband->x0, tileComp->codeBlockW); - sby0 = jpxFloorDivPow2(subband->y0, tileComp->codeBlockH); - cb = subband->cbs; - for (cbY = 0; cbY < subband->nYCBs; ++cbY) { - for (cbX = 0; cbX < subband->nXCBs; ++cbX) { - cb->x0 = (sbx0 + cbX) << tileComp->codeBlockW; - cb->x1 = cb->x0 + tileComp->cbW; - if (subband->x0 > cb->x0) { - cb->x0 = subband->x0; - } - if (subband->x1 < cb->x1) { - cb->x1 = subband->x1; - } - cb->y0 = (sby0 + cbY) << tileComp->codeBlockH; - cb->y1 = cb->y0 + tileComp->cbH; - if (subband->y0 > cb->y0) { - cb->y0 = subband->y0; - } - if (subband->y1 < cb->y1) { - cb->y1 = subband->y1; - } - cb->seen = gFalse; - cb->lBlock = 3; - cb->nextPass = jpxPassCleanup; - cb->nZeroBitPlanes = 0; - cb->coeffs = - (JPXCoeff *)gmallocn((1 << (tileComp->codeBlockW - + tileComp->codeBlockH)), - sizeof(JPXCoeff)); - for (cbi = 0; - cbi < (Guint)(1 << (tileComp->codeBlockW - + tileComp->codeBlockH)); - ++cbi) { - cb->coeffs[cbi].flags = 0; - cb->coeffs[cbi].len = 0; - cb->coeffs[cbi].mag = 0; - } - cb->arithDecoder = NULL; - cb->stats = NULL; - ++cb; - } - } - } - } - } - } - } - - return readTilePartData(tileIdx, tilePartLen, tilePartToEOC); -} - -GBool JPXStream::readTilePartData(Guint tileIdx, - Guint tilePartLen, GBool tilePartToEOC) { - JPXTile *tile; - JPXTileComp *tileComp; - JPXResLevel *resLevel; - JPXPrecinct *precinct; - JPXSubband *subband; - JPXCodeBlock *cb; - Guint ttVal; - Guint bits, cbX, cbY, nx, ny, i, j, n, sb; - int level; - - tile = &img.tiles[tileIdx]; - - // read all packets from this tile-part - while (1) { - if (tilePartToEOC) { - //~ peek for an EOC marker - } else if (tilePartLen == 0) { - break; - } - - tileComp = &tile->tileComps[tile->comp]; - resLevel = &tileComp->resLevels[tile->res]; - precinct = &resLevel->precincts[tile->precinct]; - - //----- packet header - - // zero-length flag - if (!readBits(1, &bits)) { - goto err; - } - if (!bits) { - // packet is empty -- clear all code-block inclusion flags - for (sb = 0; sb < (tile->res == 0 ? 1 : 3); ++sb) { - subband = &precinct->subbands[sb]; - for (cbY = 0; cbY < subband->nYCBs; ++cbY) { - for (cbX = 0; cbX < subband->nXCBs; ++cbX) { - cb = &subband->cbs[cbY * subband->nXCBs + cbX]; - cb->included = gFalse; - } - } - } - } else { - - for (sb = 0; sb < (tile->res == 0 ? 1 : 3); ++sb) { - subband = &precinct->subbands[sb]; - for (cbY = 0; cbY < subband->nYCBs; ++cbY) { - for (cbX = 0; cbX < subband->nXCBs; ++cbX) { - cb = &subband->cbs[cbY * subband->nXCBs + cbX]; - - // skip code-blocks with no coefficients - if (cb->x0 >= cb->x1 || cb->y0 >= cb->y1) { - cb->included = gFalse; - continue; - } - - // code-block inclusion - if (cb->seen) { - if (!readBits(1, &cb->included)) { - goto err; - } - } else { - ttVal = 0; - i = 0; - for (level = subband->maxTTLevel; level >= 0; --level) { - nx = jpxCeilDivPow2(subband->nXCBs, level); - ny = jpxCeilDivPow2(subband->nYCBs, level); - j = i + (cbY >> level) * nx + (cbX >> level); - if (!subband->inclusion[j].finished && - !subband->inclusion[j].val) { - subband->inclusion[j].val = ttVal; - } else { - ttVal = subband->inclusion[j].val; - } - while (!subband->inclusion[j].finished && - ttVal <= tile->layer) { - if (!readBits(1, &bits)) { - goto err; - } - if (bits == 1) { - subband->inclusion[j].finished = gTrue; - } else { - ++ttVal; - } - } - subband->inclusion[j].val = ttVal; - if (ttVal > tile->layer) { - break; - } - i += nx * ny; - } - cb->included = level < 0; - } - - if (cb->included) { - - // zero bit-plane count - if (!cb->seen) { - ttVal = 0; - i = 0; - for (level = subband->maxTTLevel; level >= 0; --level) { - nx = jpxCeilDivPow2(subband->nXCBs, level); - ny = jpxCeilDivPow2(subband->nYCBs, level); - j = i + (cbY >> level) * nx + (cbX >> level); - if (!subband->zeroBitPlane[j].finished && - !subband->zeroBitPlane[j].val) { - subband->zeroBitPlane[j].val = ttVal; - } else { - ttVal = subband->zeroBitPlane[j].val; - } - while (!subband->zeroBitPlane[j].finished) { - if (!readBits(1, &bits)) { - goto err; - } - if (bits == 1) { - subband->zeroBitPlane[j].finished = gTrue; - } else { - ++ttVal; - } - } - subband->zeroBitPlane[j].val = ttVal; - i += nx * ny; - } - cb->nZeroBitPlanes = ttVal; - } - - // number of coding passes - if (!readBits(1, &bits)) { - goto err; - } - if (bits == 0) { - cb->nCodingPasses = 1; - } else { - if (!readBits(1, &bits)) { - goto err; - } - if (bits == 0) { - cb->nCodingPasses = 2; - } else { - if (!readBits(2, &bits)) { - goto err; - } - if (bits < 3) { - cb->nCodingPasses = 3 + bits; - } else { - if (!readBits(5, &bits)) { - goto err; - } - if (bits < 31) { - cb->nCodingPasses = 6 + bits; - } else { - if (!readBits(7, &bits)) { - goto err; - } - cb->nCodingPasses = 37 + bits; - } - } - } - } - - // update Lblock - while (1) { - if (!readBits(1, &bits)) { - goto err; - } - if (!bits) { - break; - } - ++cb->lBlock; - } - - // length of compressed data - //~ deal with multiple codeword segments - for (n = cb->lBlock, i = cb->nCodingPasses >> 1; - i; - ++n, i >>= 1) ; - if (!readBits(n, &cb->dataLen)) { - goto err; - } - } - } - } - } - } - tilePartLen -= byteCount; - clearBitBuf(); - - //----- packet data - - for (sb = 0; sb < (tile->res == 0 ? 1 : 3); ++sb) { - subband = &precinct->subbands[sb]; - for (cbY = 0; cbY < subband->nYCBs; ++cbY) { - for (cbX = 0; cbX < subband->nXCBs; ++cbX) { - cb = &subband->cbs[cbY * subband->nXCBs + cbX]; - if (cb->included) { - if (!readCodeBlockData(tileComp, resLevel, precinct, subband, - tile->res, sb, cb)) { - return gFalse; - } - tilePartLen -= cb->dataLen; - cb->seen = gTrue; - } - } - } - } - - //----- next packet - - switch (tile->progOrder) { - case 0: // layer, resolution level, component, precinct - if (++tile->comp == img.nComps) { - tile->comp = 0; - if (++tile->res == tile->maxNDecompLevels + 1) { - tile->res = 0; - if (++tile->layer == tile->nLayers) { - tile->layer = 0; - } - } - } - break; - case 1: // resolution level, layer, component, precinct - if (++tile->comp == img.nComps) { - tile->comp = 0; - if (++tile->layer == tile->nLayers) { - tile->layer = 0; - if (++tile->res == tile->maxNDecompLevels + 1) { - tile->res = 0; - } - } - } - break; - case 2: // resolution level, precinct, component, layer - //~ this isn't correct -- see B.12.1.3 - if (++tile->layer == tile->nLayers) { - tile->layer = 0; - if (++tile->comp == img.nComps) { - tile->comp = 0; - if (++tile->res == tile->maxNDecompLevels + 1) { - tile->res = 0; - } - } - } - break; - case 3: // precinct, component, resolution level, layer - //~ this isn't correct -- see B.12.1.4 - if (++tile->layer == tile->nLayers) { - tile->layer = 0; - if (++tile->res == tile->maxNDecompLevels + 1) { - tile->res = 0; - if (++tile->comp == img.nComps) { - tile->comp = 0; - } - } - } - break; - case 4: // component, precinct, resolution level, layer - //~ this isn't correct -- see B.12.1.5 - if (++tile->layer == tile->nLayers) { - tile->layer = 0; - if (++tile->res == tile->maxNDecompLevels + 1) { - tile->res = 0; - if (++tile->comp == img.nComps) { - tile->comp = 0; - } - } - } - break; - } - } - - return gTrue; - - err: - error(getPos(), "Error in JPX stream"); - return gFalse; -} - -GBool JPXStream::readCodeBlockData(JPXTileComp *tileComp, - JPXResLevel *resLevel, - JPXPrecinct *precinct, - JPXSubband *subband, - Guint res, Guint sb, - JPXCodeBlock *cb) { - JPXCoeff *coeff0, *coeff1, *coeff; - Guint horiz, vert, diag, all, cx, xorBit; - int horizSign, vertSign; - Guint i, x, y0, y1, y2; - - if (cb->arithDecoder) { - cb->arithDecoder->restart(cb->dataLen); - } else { - cb->arithDecoder = new JArithmeticDecoder(); - cb->arithDecoder->setStream(str, cb->dataLen); - cb->arithDecoder->start(); - cb->stats = new JArithmeticDecoderStats(jpxNContexts); - cb->stats->setEntry(jpxContextSigProp, 4, 0); - cb->stats->setEntry(jpxContextRunLength, 3, 0); - cb->stats->setEntry(jpxContextUniform, 46, 0); - } - - for (i = 0; i < cb->nCodingPasses; ++i) { - switch (cb->nextPass) { - - //----- significance propagation pass - case jpxPassSigProp: - for (y0 = cb->y0, coeff0 = cb->coeffs; - y0 < cb->y1; - y0 += 4, coeff0 += 4 << tileComp->codeBlockW) { - for (x = cb->x0, coeff1 = coeff0; - x < cb->x1; - ++x, ++coeff1) { - for (y1 = 0, coeff = coeff1; - y1 < 4 && y0+y1 < cb->y1; - ++y1, coeff += tileComp->cbW) { - if (!(coeff->flags & jpxCoeffSignificant)) { - horiz = vert = diag = 0; - horizSign = vertSign = 2; - if (x > cb->x0) { - if (coeff[-1].flags & jpxCoeffSignificant) { - ++horiz; - horizSign += (coeff[-1].flags & jpxCoeffSign) ? -1 : 1; - } - if (y0+y1 > cb->y0) { - diag += (coeff[-(int)tileComp->cbW - 1].flags - >> jpxCoeffSignificantB) & 1; - } - if (y0+y1 < cb->y1 - 1) { - diag += (coeff[tileComp->cbW - 1].flags - >> jpxCoeffSignificantB) & 1; - } - } - if (x < cb->x1 - 1) { - if (coeff[1].flags & jpxCoeffSignificant) { - ++horiz; - horizSign += (coeff[1].flags & jpxCoeffSign) ? -1 : 1; - } - if (y0+y1 > cb->y0) { - diag += (coeff[-(int)tileComp->cbW + 1].flags - >> jpxCoeffSignificantB) & 1; - } - if (y0+y1 < cb->y1 - 1) { - diag += (coeff[tileComp->cbW + 1].flags - >> jpxCoeffSignificantB) & 1; - } - } - if (y0+y1 > cb->y0) { - if (coeff[-(int)tileComp->cbW].flags & jpxCoeffSignificant) { - ++vert; - vertSign += (coeff[-(int)tileComp->cbW].flags & jpxCoeffSign) - ? -1 : 1; - } - } - if (y0+y1 < cb->y1 - 1) { - if (coeff[tileComp->cbW].flags & jpxCoeffSignificant) { - ++vert; - vertSign += (coeff[tileComp->cbW].flags & jpxCoeffSign) - ? -1 : 1; - } - } - cx = sigPropContext[horiz][vert][diag][res == 0 ? 1 : sb]; - if (cx != 0) { - if (cb->arithDecoder->decodeBit(cx, cb->stats)) { - coeff->flags |= jpxCoeffSignificant | jpxCoeffFirstMagRef; - coeff->mag = (coeff->mag << 1) | 1; - cx = signContext[horizSign][vertSign][0]; - xorBit = signContext[horizSign][vertSign][1]; - if (cb->arithDecoder->decodeBit(cx, cb->stats) ^ xorBit) { - coeff->flags |= jpxCoeffSign; - } - } - ++coeff->len; - coeff->flags |= jpxCoeffTouched; - } - } - } - } - } - ++cb->nextPass; - break; - - //----- magnitude refinement pass - case jpxPassMagRef: - for (y0 = cb->y0, coeff0 = cb->coeffs; - y0 < cb->y1; - y0 += 4, coeff0 += 4 << tileComp->codeBlockW) { - for (x = cb->x0, coeff1 = coeff0; - x < cb->x1; - ++x, ++coeff1) { - for (y1 = 0, coeff = coeff1; - y1 < 4 && y0+y1 < cb->y1; - ++y1, coeff += tileComp->cbW) { - if ((coeff->flags & jpxCoeffSignificant) && - !(coeff->flags & jpxCoeffTouched)) { - if (coeff->flags & jpxCoeffFirstMagRef) { - all = 0; - if (x > cb->x0) { - all += (coeff[-1].flags >> jpxCoeffSignificantB) & 1; - if (y0+y1 > cb->y0) { - all += (coeff[-(int)tileComp->cbW - 1].flags - >> jpxCoeffSignificantB) & 1; - } - if (y0+y1 < cb->y1 - 1) { - all += (coeff[tileComp->cbW - 1].flags - >> jpxCoeffSignificantB) & 1; - } - } - if (x < cb->x1 - 1) { - all += (coeff[1].flags >> jpxCoeffSignificantB) & 1; - if (y0+y1 > cb->y0) { - all += (coeff[-(int)tileComp->cbW + 1].flags - >> jpxCoeffSignificantB) & 1; - } - if (y0+y1 < cb->y1 - 1) { - all += (coeff[tileComp->cbW + 1].flags - >> jpxCoeffSignificantB) & 1; - } - } - if (y0+y1 > cb->y0) { - all += (coeff[-(int)tileComp->cbW].flags - >> jpxCoeffSignificantB) & 1; - } - if (y0+y1 < cb->y1 - 1) { - all += (coeff[tileComp->cbW].flags - >> jpxCoeffSignificantB) & 1; - } - cx = all ? 15 : 14; - } else { - cx = 16; - } - coeff->mag = (coeff->mag << 1) | - cb->arithDecoder->decodeBit(cx, cb->stats); - ++coeff->len; - coeff->flags |= jpxCoeffTouched; - coeff->flags &= ~jpxCoeffFirstMagRef; - } - } - } - } - ++cb->nextPass; - break; - - //----- cleanup pass - case jpxPassCleanup: - for (y0 = cb->y0, coeff0 = cb->coeffs; - y0 < cb->y1; - y0 += 4, coeff0 += 4 << tileComp->codeBlockW) { - for (x = cb->x0, coeff1 = coeff0; - x < cb->x1; - ++x, ++coeff1) { - y1 = 0; - if (y0 + 3 < cb->y1 && - !(coeff1->flags & jpxCoeffTouched) && - !(coeff1[tileComp->cbW].flags & jpxCoeffTouched) && - !(coeff1[2 * tileComp->cbW].flags & jpxCoeffTouched) && - !(coeff1[3 * tileComp->cbW].flags & jpxCoeffTouched) && - (x == cb->x0 || y0 == cb->y0 || - !(coeff1[-(int)tileComp->cbW - 1].flags - & jpxCoeffSignificant)) && - (y0 == cb->y0 || - !(coeff1[-(int)tileComp->cbW].flags - & jpxCoeffSignificant)) && - (x == cb->x1 - 1 || y0 == cb->y0 || - !(coeff1[-(int)tileComp->cbW + 1].flags - & jpxCoeffSignificant)) && - (x == cb->x0 || - (!(coeff1[-1].flags & jpxCoeffSignificant) && - !(coeff1[tileComp->cbW - 1].flags - & jpxCoeffSignificant) && - !(coeff1[2 * tileComp->cbW - 1].flags - & jpxCoeffSignificant) && - !(coeff1[3 * tileComp->cbW - 1].flags - & jpxCoeffSignificant))) && - (x == cb->x1 - 1 || - (!(coeff1[1].flags & jpxCoeffSignificant) && - !(coeff1[tileComp->cbW + 1].flags - & jpxCoeffSignificant) && - !(coeff1[2 * tileComp->cbW + 1].flags - & jpxCoeffSignificant) && - !(coeff1[3 * tileComp->cbW + 1].flags - & jpxCoeffSignificant))) && - (x == cb->x0 || y0+4 == cb->y1 || - !(coeff1[4 * tileComp->cbW - 1].flags & jpxCoeffSignificant)) && - (y0+4 == cb->y1 || - !(coeff1[4 * tileComp->cbW].flags & jpxCoeffSignificant)) && - (x == cb->x1 - 1 || y0+4 == cb->y1 || - !(coeff1[4 * tileComp->cbW + 1].flags - & jpxCoeffSignificant))) { - if (cb->arithDecoder->decodeBit(jpxContextRunLength, cb->stats)) { - y1 = cb->arithDecoder->decodeBit(jpxContextUniform, cb->stats); - y1 = (y1 << 1) | - cb->arithDecoder->decodeBit(jpxContextUniform, cb->stats); - for (y2 = 0, coeff = coeff1; - y2 < y1; - ++y2, coeff += tileComp->cbW) { - ++coeff->len; - } - coeff->flags |= jpxCoeffSignificant | jpxCoeffFirstMagRef; - coeff->mag = (coeff->mag << 1) | 1; - ++coeff->len; - cx = signContext[2][2][0]; - xorBit = signContext[2][2][1]; - if (cb->arithDecoder->decodeBit(cx, cb->stats) ^ xorBit) { - coeff->flags |= jpxCoeffSign; - } - ++y1; - } else { - for (y1 = 0, coeff = coeff1; - y1 < 4; - ++y1, coeff += tileComp->cbW) { - ++coeff->len; - } - y1 = 4; - } - } - for (coeff = &coeff1[y1 << tileComp->codeBlockW]; - y1 < 4 && y0 + y1 < cb->y1; - ++y1, coeff += tileComp->cbW) { - if (!(coeff->flags & jpxCoeffTouched)) { - horiz = vert = diag = 0; - horizSign = vertSign = 2; - if (x > cb->x0) { - if (coeff[-1].flags & jpxCoeffSignificant) { - ++horiz; - horizSign += (coeff[-1].flags & jpxCoeffSign) ? -1 : 1; - } - if (y0+y1 > cb->y0) { - diag += (coeff[-(int)tileComp->cbW - 1].flags - >> jpxCoeffSignificantB) & 1; - } - if (y0+y1 < cb->y1 - 1) { - diag += (coeff[tileComp->cbW - 1].flags - >> jpxCoeffSignificantB) & 1; - } - } - if (x < cb->x1 - 1) { - if (coeff[1].flags & jpxCoeffSignificant) { - ++horiz; - horizSign += (coeff[1].flags & jpxCoeffSign) ? -1 : 1; - } - if (y0+y1 > cb->y0) { - diag += (coeff[-(int)tileComp->cbW + 1].flags - >> jpxCoeffSignificantB) & 1; - } - if (y0+y1 < cb->y1 - 1) { - diag += (coeff[tileComp->cbW + 1].flags - >> jpxCoeffSignificantB) & 1; - } - } - if (y0+y1 > cb->y0) { - if (coeff[-(int)tileComp->cbW].flags & jpxCoeffSignificant) { - ++vert; - vertSign += (coeff[-(int)tileComp->cbW].flags & jpxCoeffSign) - ? -1 : 1; - } - } - if (y0+y1 < cb->y1 - 1) { - if (coeff[tileComp->cbW].flags & jpxCoeffSignificant) { - ++vert; - vertSign += (coeff[tileComp->cbW].flags & jpxCoeffSign) - ? -1 : 1; - } - } - cx = sigPropContext[horiz][vert][diag][res == 0 ? 1 : sb]; - if (cb->arithDecoder->decodeBit(cx, cb->stats)) { - coeff->flags |= jpxCoeffSignificant | jpxCoeffFirstMagRef; - coeff->mag = (coeff->mag << 1) | 1; - cx = signContext[horizSign][vertSign][0]; - xorBit = signContext[horizSign][vertSign][1]; - if (cb->arithDecoder->decodeBit(cx, cb->stats) ^ xorBit) { - coeff->flags |= jpxCoeffSign; - } - } - ++coeff->len; - } else { - coeff->flags &= ~jpxCoeffTouched; - } - } - } - } - cb->nextPass = jpxPassSigProp; - break; - } - } - - cb->arithDecoder->cleanup(); - return gTrue; -} - -// Inverse quantization, and wavelet transform (IDWT). This also does -// the initial shift to convert to fixed point format. -void JPXStream::inverseTransform(JPXTileComp *tileComp) { - JPXResLevel *resLevel; - JPXPrecinct *precinct; - JPXSubband *subband; - JPXCodeBlock *cb; - JPXCoeff *coeff0, *coeff; - Guint qStyle, guard, eps, shift; - int shift2; - double mu; - int val; - int *dataPtr; - Guint nx0, ny0, nx1, ny1; - Guint r, cbX, cbY, x, y; - - //----- (NL)LL subband (resolution level 0) - - resLevel = &tileComp->resLevels[0]; - precinct = &resLevel->precincts[0]; - subband = &precinct->subbands[0]; - - // i-quant parameters - qStyle = tileComp->quantStyle & 0x1f; - guard = (tileComp->quantStyle >> 5) & 7; - if (qStyle == 0) { - eps = (tileComp->quantSteps[0] >> 3) & 0x1f; - shift = guard + eps - 1; - mu = 0; // make gcc happy - } else { - shift = guard - 1 + tileComp->prec; - mu = (double)(0x800 + (tileComp->quantSteps[0] & 0x7ff)) / 2048.0; - } - if (tileComp->transform == 0) { - shift += fracBits; - } - - // copy (NL)LL into the upper-left corner of the data array, doing - // the fixed point adjustment and dequantization along the way - cb = subband->cbs; - for (cbY = 0; cbY < subband->nYCBs; ++cbY) { - for (cbX = 0; cbX < subband->nXCBs; ++cbX) { - for (y = cb->y0, coeff0 = cb->coeffs; - y < cb->y1; - ++y, coeff0 += tileComp->cbW) { - dataPtr = &tileComp->data[(y - subband->y0) - * (tileComp->x1 - tileComp->x0) - + (cb->x0 - subband->x0)]; - for (x = cb->x0, coeff = coeff0; x < cb->x1; ++x, ++coeff) { - val = (int)coeff->mag; - if (val != 0) { - shift2 = shift - (cb->nZeroBitPlanes + coeff->len); - if (shift2 > 0) { - val = (val << shift2) + (1 << (shift2 - 1)); - } else { - val >>= -shift2; - } - if (qStyle == 0) { - if (tileComp->transform == 0) { - val &= -1 << fracBits; - } - } else { - val = (int)((double)val * mu); - } - if (coeff->flags & jpxCoeffSign) { - val = -val; - } - } - *dataPtr++ = val; - } - } - ++cb; - } - } - - //----- IDWT for each level - - for (r = 1; r <= tileComp->nDecompLevels; ++r) { - resLevel = &tileComp->resLevels[r]; - - // (n)LL is already in the upper-left corner of the - // tile-component data array -- interleave with (n)HL/LH/HH - // and inverse transform to get (n-1)LL, which will be stored - // in the upper-left corner of the tile-component data array - if (r == tileComp->nDecompLevels) { - nx0 = tileComp->x0; - ny0 = tileComp->y0; - nx1 = tileComp->x1; - ny1 = tileComp->y1; - } else { - nx0 = tileComp->resLevels[r+1].x0; - ny0 = tileComp->resLevels[r+1].y0; - nx1 = tileComp->resLevels[r+1].x1; - ny1 = tileComp->resLevels[r+1].y1; - } - inverseTransformLevel(tileComp, r, resLevel, nx0, ny0, nx1, ny1); - } -} - -// Do one level of the inverse transform: -// - take (n)LL from the tile-component data array -// - take (n)HL/LH/HH from <resLevel> -// - leave the resulting (n-1)LL in the tile-component data array -void JPXStream::inverseTransformLevel(JPXTileComp *tileComp, - Guint r, JPXResLevel *resLevel, - Guint nx0, Guint ny0, - Guint nx1, Guint ny1) { - JPXPrecinct *precinct; - JPXSubband *subband; - JPXCodeBlock *cb; - JPXCoeff *coeff0, *coeff; - Guint qStyle, guard, eps, shift, t; - int shift2; - double mu; - int val; - int *dataPtr; - Guint xo, yo; - Guint x, y, sb, cbX, cbY; - int xx, yy; - - //----- interleave - - // spread out LL - for (yy = resLevel->y1 - 1; yy >= (int)resLevel->y0; --yy) { - for (xx = resLevel->x1 - 1; xx >= (int)resLevel->x0; --xx) { - tileComp->data[(2 * yy - ny0) * (tileComp->x1 - tileComp->x0) - + (2 * xx - nx0)] = - tileComp->data[(yy - resLevel->y0) * (tileComp->x1 - tileComp->x0) - + (xx - resLevel->x0)]; - } - } - - // i-quant parameters - qStyle = tileComp->quantStyle & 0x1f; - guard = (tileComp->quantStyle >> 5) & 7; - - // interleave HL/LH/HH - precinct = &resLevel->precincts[0]; - for (sb = 0; sb < 3; ++sb) { - - // i-quant parameters - if (qStyle == 0) { - eps = (tileComp->quantSteps[3*r - 2 + sb] >> 3) & 0x1f; - shift = guard + eps - 1; - mu = 0; // make gcc happy - } else { - shift = guard + tileComp->prec; - if (sb == 2) { - ++shift; - } - t = tileComp->quantSteps[qStyle == 1 ? 0 : (3*r - 2 + sb)]; - mu = (double)(0x800 + (t & 0x7ff)) / 2048.0; - } - if (tileComp->transform == 0) { - shift += fracBits; - } - - // copy the subband coefficients into the data array, doing the - // fixed point adjustment and dequantization along the way - xo = (sb & 1) ? 0 : 1; - yo = (sb > 0) ? 1 : 0; - subband = &precinct->subbands[sb]; - cb = subband->cbs; - for (cbY = 0; cbY < subband->nYCBs; ++cbY) { - for (cbX = 0; cbX < subband->nXCBs; ++cbX) { - for (y = cb->y0, coeff0 = cb->coeffs; - y < cb->y1; - ++y, coeff0 += tileComp->cbW) { - dataPtr = &tileComp->data[(2 * y + yo - ny0) - * (tileComp->x1 - tileComp->x0) - + (2 * cb->x0 + xo - nx0)]; - for (x = cb->x0, coeff = coeff0; x < cb->x1; ++x, ++coeff) { - val = (int)coeff->mag; - if (val != 0) { - shift2 = shift - (cb->nZeroBitPlanes + coeff->len); - if (shift2 > 0) { - val = (val << shift2) + (1 << (shift2 - 1)); - } else { - val >>= -shift2; - } - if (qStyle == 0) { - if (tileComp->transform == 0) { - val &= -1 << fracBits; - } - } else { - val = (int)((double)val * mu); - } - if (coeff->flags & jpxCoeffSign) { - val = -val; - } - } - *dataPtr = val; - dataPtr += 2; - } - } - ++cb; - } - } - } - - //----- horizontal (row) transforms - dataPtr = tileComp->data; - for (y = 0; y < ny1 - ny0; ++y) { - inverseTransform1D(tileComp, dataPtr, 1, nx0, nx1); - dataPtr += tileComp->x1 - tileComp->x0; - } - - //----- vertical (column) transforms - dataPtr = tileComp->data; - for (x = 0; x < nx1 - nx0; ++x) { - inverseTransform1D(tileComp, dataPtr, - tileComp->x1 - tileComp->x0, ny0, ny1); - ++dataPtr; - } -} - -void JPXStream::inverseTransform1D(JPXTileComp *tileComp, - int *data, Guint stride, - Guint i0, Guint i1) { - int *buf; - Guint offset, end, i; - - //----- special case for length = 1 - if (i1 - i0 == 1) { - if (i0 & 1) { - *data >>= 1; - } - - } else { - - // choose an offset: this makes even buf[] indexes correspond to - // odd values of i, and vice versa - offset = 3 + (i0 & 1); - end = offset + i1 - i0; - - //----- gather - buf = tileComp->buf; - for (i = 0; i < i1 - i0; ++i) { - buf[offset + i] = data[i * stride]; - } - - //----- extend right - buf[end] = buf[end - 2]; - if (i1 - i0 == 2) { - buf[end+1] = buf[offset + 1]; - buf[end+2] = buf[offset]; - buf[end+3] = buf[offset + 1]; - } else { - buf[end+1] = buf[end - 3]; - if (i1 - i0 == 3) { - buf[end+2] = buf[offset + 1]; - buf[end+3] = buf[offset + 2]; - } else { - buf[end+2] = buf[end - 4]; - if (i1 - i0 == 4) { - buf[end+3] = buf[offset + 1]; - } else { - buf[end+3] = buf[end - 5]; - } - } - } - - //----- extend left - buf[offset - 1] = buf[offset + 1]; - buf[offset - 2] = buf[offset + 2]; - buf[offset - 3] = buf[offset + 3]; - if (offset == 4) { - buf[0] = buf[offset + 4]; - } - - //----- 9-7 irreversible filter - - if (tileComp->transform == 0) { - // step 1 (even) - for (i = 1; i <= end + 2; i += 2) { - buf[i] = (int)(idwtKappa * buf[i]); - } - // step 2 (odd) - for (i = 0; i <= end + 3; i += 2) { - buf[i] = (int)(idwtIKappa * buf[i]); - } - // step 3 (even) - for (i = 1; i <= end + 2; i += 2) { - buf[i] = (int)(buf[i] - idwtDelta * (buf[i-1] + buf[i+1])); - } - // step 4 (odd) - for (i = 2; i <= end + 1; i += 2) { - buf[i] = (int)(buf[i] - idwtGamma * (buf[i-1] + buf[i+1])); - } - // step 5 (even) - for (i = 3; i <= end; i += 2) { - buf[i] = (int)(buf[i] - idwtBeta * (buf[i-1] + buf[i+1])); - } - // step 6 (odd) - for (i = 4; i <= end - 1; i += 2) { - buf[i] = (int)(buf[i] - idwtAlpha * (buf[i-1] + buf[i+1])); - } - - //----- 5-3 reversible filter - - } else { - // step 1 (even) - for (i = 3; i <= end; i += 2) { - buf[i] -= (buf[i-1] + buf[i+1] + 2) >> 2; - } - // step 2 (odd) - for (i = 4; i < end; i += 2) { - buf[i] += (buf[i-1] + buf[i+1]) >> 1; - } - } - - //----- scatter - for (i = 0; i < i1 - i0; ++i) { - data[i * stride] = buf[offset + i]; - } - } -} - -// Inverse multi-component transform and DC level shift. This also -// converts fixed point samples back to integers. -GBool JPXStream::inverseMultiCompAndDC(JPXTile *tile) { - JPXTileComp *tileComp; - int coeff, d0, d1, d2, t, minVal, maxVal, zeroVal; - int *dataPtr; - Guint j, comp, x, y; - - //----- inverse multi-component transform - - if (tile->multiComp == 1) { - if (img.nComps < 3 || - tile->tileComps[0].hSep != tile->tileComps[1].hSep || - tile->tileComps[0].vSep != tile->tileComps[1].vSep || - tile->tileComps[1].hSep != tile->tileComps[2].hSep || - tile->tileComps[1].vSep != tile->tileComps[2].vSep) { - return gFalse; - } - - // inverse irreversible multiple component transform - if (tile->tileComps[0].transform == 0) { - j = 0; - for (y = 0; y < tile->tileComps[0].y1 - tile->tileComps[0].y0; ++y) { - for (x = 0; x < tile->tileComps[0].x1 - tile->tileComps[0].x0; ++x) { - d0 = tile->tileComps[0].data[j]; - d1 = tile->tileComps[1].data[j]; - d2 = tile->tileComps[2].data[j]; - tile->tileComps[0].data[j] = (int)(d0 + 1.402 * d2 + 0.5); - tile->tileComps[1].data[j] = - (int)(d0 - 0.34413 * d1 - 0.71414 * d2 + 0.5); - tile->tileComps[2].data[j] = (int)(d0 + 1.772 * d1 + 0.5); - ++j; - } - } - - // inverse reversible multiple component transform - } else { - j = 0; - for (y = 0; y < tile->tileComps[0].y1 - tile->tileComps[0].y0; ++y) { - for (x = 0; x < tile->tileComps[0].x1 - tile->tileComps[0].x0; ++x) { - d0 = tile->tileComps[0].data[j]; - d1 = tile->tileComps[1].data[j]; - d2 = tile->tileComps[2].data[j]; - tile->tileComps[1].data[j] = t = d0 - ((d2 + d1) >> 2); - tile->tileComps[0].data[j] = d2 + t; - tile->tileComps[2].data[j] = d1 + t; - ++j; - } - } - } - } - - //----- DC level shift - for (comp = 0; comp < img.nComps; ++comp) { - tileComp = &tile->tileComps[comp]; - - // signed: clip - if (tileComp->sgned) { - minVal = -(1 << (tileComp->prec - 1)); - maxVal = (1 << (tileComp->prec - 1)) - 1; - dataPtr = tileComp->data; - for (y = 0; y < tileComp->y1 - tileComp->y0; ++y) { - for (x = 0; x < tileComp->x1 - tileComp->x0; ++x) { - coeff = *dataPtr; - if (tileComp->transform == 0) { - coeff >>= fracBits; - } - if (coeff < minVal) { - coeff = minVal; - } else if (coeff > maxVal) { - coeff = maxVal; - } - *dataPtr++ = coeff; - } - } - - // unsigned: inverse DC level shift and clip - } else { - maxVal = (1 << tileComp->prec) - 1; - zeroVal = 1 << (tileComp->prec - 1); - dataPtr = tileComp->data; - for (y = 0; y < tileComp->y1 - tileComp->y0; ++y) { - for (x = 0; x < tileComp->x1 - tileComp->x0; ++x) { - coeff = *dataPtr; - if (tileComp->transform == 0) { - coeff >>= fracBits; - } - coeff += zeroVal; - if (coeff < 0) { - coeff = 0; - } else if (coeff > maxVal) { - coeff = maxVal; - } - *dataPtr++ = coeff; - } - } - } - } - - return gTrue; -} - -GBool JPXStream::readBoxHdr(Guint *boxType, Guint *boxLen, Guint *dataLen) { - Guint len, lenH; - - if (!readULong(&len) || - !readULong(boxType)) { - return gFalse; - } - if (len == 1) { - if (!readULong(&lenH) || !readULong(&len)) { - return gFalse; - } - if (lenH) { - error(getPos(), "JPX stream contains a box larger than 2^32 bytes"); - return gFalse; - } - *boxLen = len; - *dataLen = len - 16; - } else if (len == 0) { - *boxLen = 0; - *dataLen = 0; - } else { - *boxLen = len; - *dataLen = len - 8; - } - return gTrue; -} - -int JPXStream::readMarkerHdr(int *segType, Guint *segLen) { - int c; - - do { - do { - if ((c = str->getChar()) == EOF) { - return gFalse; - } - } while (c != 0xff); - do { - if ((c = str->getChar()) == EOF) { - return gFalse; - } - } while (c == 0xff); - } while (c == 0x00); - *segType = c; - if ((c >= 0x30 && c <= 0x3f) || - c == 0x4f || c == 0x92 || c == 0x93 || c == 0xd9) { - *segLen = 0; - return gTrue; - } - return readUWord(segLen); -} - -GBool JPXStream::readUByte(Guint *x) { - int c0; - - if ((c0 = str->getChar()) == EOF) { - return gFalse; - } - *x = (Guint)c0; - return gTrue; -} - -GBool JPXStream::readByte(int *x) { - int c0; - - if ((c0 = str->getChar()) == EOF) { - return gFalse; - } - *x = c0; - if (c0 & 0x80) { - *x |= -1 - 0xff; - } - return gTrue; -} - -GBool JPXStream::readUWord(Guint *x) { - int c0, c1; - - if ((c0 = str->getChar()) == EOF || - (c1 = str->getChar()) == EOF) { - return gFalse; - } - *x = (Guint)((c0 << 8) | c1); - return gTrue; -} - -GBool JPXStream::readULong(Guint *x) { - int c0, c1, c2, c3; - - if ((c0 = str->getChar()) == EOF || - (c1 = str->getChar()) == EOF || - (c2 = str->getChar()) == EOF || - (c3 = str->getChar()) == EOF) { - return gFalse; - } - *x = (Guint)((c0 << 24) | (c1 << 16) | (c2 << 8) | c3); - return gTrue; -} - -GBool JPXStream::readNBytes(int nBytes, GBool signd, int *x) { - int y, c, i; - - y = 0; - for (i = 0; i < nBytes; ++i) { - if ((c = str->getChar()) == EOF) { - return gFalse; - } - y = (y << 8) + c; - } - if (signd) { - if (y & (1 << (8 * nBytes - 1))) { - y |= -1 << (8 * nBytes); - } - } - *x = y; - return gTrue; -} - -GBool JPXStream::readBits(int nBits, Guint *x) { - int c; - - while (bitBufLen < nBits) { - if ((c = str->getChar()) == EOF) { - return gFalse; - } - ++byteCount; - if (bitBufSkip) { - bitBuf = (bitBuf << 7) | (c & 0x7f); - bitBufLen += 7; - } else { - bitBuf = (bitBuf << 8) | (c & 0xff); - bitBufLen += 8; - } - bitBufSkip = c == 0xff; - } - *x = (bitBuf >> (bitBufLen - nBits)) & ((1 << nBits) - 1); - bitBufLen -= nBits; - return gTrue; -} - -void JPXStream::clearBitBuf() { - bitBufLen = 0; - bitBufSkip = gFalse; - byteCount = 0; -} diff --git a/pdftops/JPXStream.h b/pdftops/JPXStream.h deleted file mode 100644 index 60c12f07f..000000000 --- a/pdftops/JPXStream.h +++ /dev/null @@ -1,349 +0,0 @@ -//======================================================================== -// -// JPXStream.h -// -// Copyright 2002-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef JPXSTREAM_H -#define JPXSTREAM_H - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "gtypes.h" -#include "Object.h" -#include "Stream.h" - -class JArithmeticDecoderStats; - -//------------------------------------------------------------------------ - -enum JPXColorSpaceType { - jpxCSBiLevel = 0, - jpxCSYCbCr1 = 1, - jpxCSYCbCr2 = 3, - jpxCSYCBCr3 = 4, - jpxCSPhotoYCC = 9, - jpxCSCMY = 11, - jpxCSCMYK = 12, - jpxCSYCCK = 13, - jpxCSCIELab = 14, - jpxCSsRGB = 16, - jpxCSGrayscale = 17, - jpxCSBiLevel2 = 18, - jpxCSCIEJab = 19, - jpxCSCISesRGB = 20, - jpxCSROMMRGB = 21, - jpxCSsRGBYCbCr = 22, - jpxCSYPbPr1125 = 23, - jpxCSYPbPr1250 = 24 -}; - -struct JPXColorSpecCIELab { - Guint rl, ol, ra, oa, rb, ob, il; -}; - -struct JPXColorSpecEnumerated { - JPXColorSpaceType type; // color space type - union { - JPXColorSpecCIELab cieLab; - }; -}; - -struct JPXColorSpec { - Guint meth; // method - int prec; // precedence - union { - JPXColorSpecEnumerated enumerated; - }; -}; - -//------------------------------------------------------------------------ - -struct JPXPalette { - Guint nEntries; // number of entries in the palette - Guint nComps; // number of components in each entry - Guint *bpc; // bits per component, for each component - int *c; // color data: - // c[i*nComps+j] = entry i, component j -}; - -//------------------------------------------------------------------------ - -struct JPXCompMap { - Guint nChannels; // number of channels - Guint *comp; // codestream components mapped to each channel - Guint *type; // 0 for direct use, 1 for palette mapping - Guint *pComp; // palette components to use -}; - -//------------------------------------------------------------------------ - -struct JPXChannelDefn { - Guint nChannels; // number of channels - Guint *idx; // channel indexes - Guint *type; // channel types - Guint *assoc; // channel associations -}; - -//------------------------------------------------------------------------ - -struct JPXTagTreeNode { - GBool finished; // true if this node is finished - Guint val; // current value -}; - -//------------------------------------------------------------------------ - -struct JPXCoeff { - Gushort flags; // flag bits - Gushort len; // number of significant bits in mag - Guint mag; // magnitude value -}; - -// coefficient flags -#define jpxCoeffSignificantB 0 -#define jpxCoeffTouchedB 1 -#define jpxCoeffFirstMagRefB 2 -#define jpxCoeffSignB 7 -#define jpxCoeffSignificant (1 << jpxCoeffSignificantB) -#define jpxCoeffTouched (1 << jpxCoeffTouchedB) -#define jpxCoeffFirstMagRef (1 << jpxCoeffFirstMagRefB) -#define jpxCoeffSign (1 << jpxCoeffSignB) - -//------------------------------------------------------------------------ - -struct JPXCodeBlock { - //----- size - Guint x0, y0, x1, y1; // bounds - - //----- persistent state - GBool seen; // true if this code-block has already - // been seen - Guint lBlock; // base number of bits used for pkt data length - Guint nextPass; // next coding pass - - //---- info from first packet - Guint nZeroBitPlanes; // number of zero bit planes - - //----- info for the current packet - Guint included; // code-block inclusion in this packet: - // 0=not included, 1=included - Guint nCodingPasses; // number of coding passes in this pkt - Guint dataLen; // pkt data length - - //----- coefficient data - JPXCoeff *coeffs; // the coefficients - JArithmeticDecoder // arithmetic decoder - *arithDecoder; - JArithmeticDecoderStats // arithmetic decoder stats - *stats; -}; - -//------------------------------------------------------------------------ - -struct JPXSubband { - //----- computed - Guint x0, y0, x1, y1; // bounds - Guint nXCBs, nYCBs; // number of code-blocks in the x and y - // directions - - //----- tag trees - Guint maxTTLevel; // max tag tree level - JPXTagTreeNode *inclusion; // inclusion tag tree for each subband - JPXTagTreeNode *zeroBitPlane; // zero-bit plane tag tree for each - // subband - - //----- children - JPXCodeBlock *cbs; // the code-blocks (len = nXCBs * nYCBs) -}; - -//------------------------------------------------------------------------ - -struct JPXPrecinct { - //----- computed - Guint x0, y0, x1, y1; // bounds of the precinct - - //----- children - JPXSubband *subbands; // the subbands -}; - -//------------------------------------------------------------------------ - -struct JPXResLevel { - //----- from the COD and COC segments (main and tile) - Guint precinctWidth; // log2(precinct width) - Guint precinctHeight; // log2(precinct height) - - //----- computed - Guint x0, y0, x1, y1; // bounds of the tile-comp (for this res level) - Guint bx0[3], by0[3], // subband bounds - bx1[3], by1[3]; - - //---- children - JPXPrecinct *precincts; // the precincts -}; - -//------------------------------------------------------------------------ - -struct JPXTileComp { - //----- from the SIZ segment - GBool sgned; // 1 for signed, 0 for unsigned - Guint prec; // precision, in bits - Guint hSep; // horizontal separation of samples - Guint vSep; // vertical separation of samples - - //----- from the COD and COC segments (main and tile) - Guint style; // coding style parameter (Scod / Scoc) - Guint nDecompLevels; // number of decomposition levels - Guint codeBlockW; // log2(code-block width) - Guint codeBlockH; // log2(code-block height) - Guint codeBlockStyle; // code-block style - Guint transform; // wavelet transformation - - //----- from the QCD and QCC segments (main and tile) - Guint quantStyle; // quantization style - Guint *quantSteps; // quantization step size for each subband - Guint nQuantSteps; // number of entries in quantSteps - - //----- computed - Guint x0, y0, x1, y1; // bounds of the tile-comp, in ref coords - Guint cbW; // code-block width - Guint cbH; // code-block height - - //----- image data - int *data; // the decoded image data - int *buf; // intermediate buffer for the inverse - // transform - - //----- children - JPXResLevel *resLevels; // the resolution levels - // (len = nDecompLevels + 1) -}; - -//------------------------------------------------------------------------ - -struct JPXTile { - //----- from the COD segments (main and tile) - Guint progOrder; // progression order - Guint nLayers; // number of layers - Guint multiComp; // multiple component transformation - - //----- computed - Guint x0, y0, x1, y1; // bounds of the tile, in ref coords - Guint maxNDecompLevels; // max number of decomposition levels used - // in any component in this tile - - //----- progression order loop counters - Guint comp; // component - Guint res; // resolution level - Guint precinct; // precinct - Guint layer; // layer - - //----- children - JPXTileComp *tileComps; // the tile-components (len = JPXImage.nComps) -}; - -//------------------------------------------------------------------------ - -struct JPXImage { - //----- from the SIZ segment - Guint xSize, ySize; // size of reference grid - Guint xOffset, yOffset; // image offset - Guint xTileSize, yTileSize; // size of tiles - Guint xTileOffset, // offset of first tile - yTileOffset; - Guint nComps; // number of components - - //----- computed - Guint nXTiles; // number of tiles in x direction - Guint nYTiles; // number of tiles in y direction - - //----- children - JPXTile *tiles; // the tiles (len = nXTiles * nYTiles) -}; - -//------------------------------------------------------------------------ - -class JPXStream: public FilterStream { -public: - - JPXStream(Stream *strA); - virtual ~JPXStream(); - virtual StreamKind getKind() { return strJPX; } - virtual void reset(); - virtual int getChar(); - virtual int lookChar(); - virtual GString *getPSFilter(int psLevel, char *indent); - virtual GBool isBinary(GBool last = gTrue); - virtual void getImageParams(int *bitsPerComponent, - StreamColorSpaceMode *csMode); - -private: - - void fillReadBuf(); - void getImageParams2(int *bitsPerComponent, StreamColorSpaceMode *csMode); - GBool readBoxes(); - GBool readColorSpecBox(Guint dataLen); - GBool readCodestream(Guint len); - GBool readTilePart(); - GBool readTilePartData(Guint tileIdx, - Guint tilePartLen, GBool tilePartToEOC); - GBool readCodeBlockData(JPXTileComp *tileComp, - JPXResLevel *resLevel, - JPXPrecinct *precinct, - JPXSubband *subband, - Guint res, Guint sb, - JPXCodeBlock *cb); - void inverseTransform(JPXTileComp *tileComp); - void inverseTransformLevel(JPXTileComp *tileComp, - Guint r, JPXResLevel *resLevel, - Guint nx0, Guint ny0, - Guint nx1, Guint ny1); - void inverseTransform1D(JPXTileComp *tileComp, - int *data, Guint stride, - Guint i0, Guint i1); - GBool inverseMultiCompAndDC(JPXTile *tile); - GBool readBoxHdr(Guint *boxType, Guint *boxLen, Guint *dataLen); - int readMarkerHdr(int *segType, Guint *segLen); - GBool readUByte(Guint *x); - GBool readByte(int *x); - GBool readUWord(Guint *x); - GBool readULong(Guint *x); - GBool readNBytes(int nBytes, GBool signd, int *x); - GBool readBits(int nBits, Guint *x); - void clearBitBuf(); - - Guint nComps; // number of components - Guint *bpc; // bits per component, for each component - Guint width, height; // image size - GBool haveImgHdr; // set if a JP2/JPX image header has been - // found - JPXColorSpec cs; // color specification - GBool haveCS; // set if a color spec has been found - JPXPalette palette; // the palette - GBool havePalette; // set if a palette has been found - JPXCompMap compMap; // the component mapping - GBool haveCompMap; // set if a component mapping has been found - JPXChannelDefn channelDefn; // channel definition - GBool haveChannelDefn; // set if a channel defn has been found - - JPXImage img; // JPEG2000 decoder data - Guint bitBuf; // buffer for bit reads - int bitBufLen; // number of bits in bitBuf - GBool bitBufSkip; // true if next bit should be skipped - // (for bit stuffing) - Guint byteCount; // number of bytes read since last call - // to clearBitBuf - - Guint curX, curY, curComp; // current position for lookChar/getChar - Guint readBuf; // read buffer - Guint readBufLen; // number of valid bits in readBuf -}; - -#endif diff --git a/pdftops/Lexer.cxx b/pdftops/Lexer.cxx deleted file mode 100644 index 2bb0f50db..000000000 --- a/pdftops/Lexer.cxx +++ /dev/null @@ -1,485 +0,0 @@ -//======================================================================== -// -// Lexer.cc -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include <stdlib.h> -#include <stddef.h> -#include <string.h> -#include <ctype.h> -#include "Lexer.h" -#include "Error.h" - -//------------------------------------------------------------------------ - -// A '1' in this array means the character is white space. A '1' or -// '2' means the character ends a name or command. -static char specialChars[256] = { - 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 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, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, // 2x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 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, 2, 0, 2, 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, 2, 0, 2, 0, 0, // 7x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ax - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // bx - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // cx - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // dx - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ex - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // fx -}; - -//------------------------------------------------------------------------ -// Lexer -//------------------------------------------------------------------------ - -Lexer::Lexer(XRef *xref, Stream *str) { - Object obj; - - curStr.initStream(str); - streams = new Array(xref); - streams->add(curStr.copy(&obj)); - strPtr = 0; - freeArray = gTrue; - curStr.streamReset(); -} - -Lexer::Lexer(XRef *xref, Object *obj) { - Object obj2; - - if (obj->isStream()) { - streams = new Array(xref); - 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.streamClose(); - curStr.free(); - } - if (freeArray) { - delete streams; - } -} - -int Lexer::getChar() { - int c; - - c = EOF; - while (!curStr.isNone() && (c = curStr.streamGetChar()) == EOF) { - curStr.streamClose(); - curStr.free(); - ++strPtr; - if (strPtr < streams->getLength()) { - streams->get(strPtr, &curStr); - curStr.streamReset(); - } - } - return c; -} - -int Lexer::lookChar() { - if (curStr.isNone()) { - return EOF; - } - return curStr.streamLookChar(); -} - -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 (specialChars[c] != 1) { - 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 (c == '-') { - // ignore minus signs in the middle of numbers to match - // Adobe's behavior - error(getPos(), "Badly formatted number"); - getChar(); - continue; - } - 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: -#if 0 - // This breaks some PDF files, e.g., ones from Photoshop. - case '\r': - case '\n': -#endif - error(getPos(), "Unterminated string"); - done = gTrue; - break; - - case '(': - ++numParen; - c2 = c; - break; - - case ')': - if (--numParen == 0) { - done = gTrue; - } else { - c2 = c; - } - 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 && !specialChars[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 (specialChars[c] != 1) { - 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 && !specialChars[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; - } - } -} - -GBool Lexer::isSpace(int c) { - return c >= 0 && c <= 0xff && specialChars[c] == 1; -} diff --git a/pdftops/Lexer.h b/pdftops/Lexer.h deleted file mode 100644 index 9ec2feb70..000000000 --- a/pdftops/Lexer.h +++ /dev/null @@ -1,80 +0,0 @@ -//======================================================================== -// -// Lexer.h -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef LEXER_H -#define LEXER_H - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "Object.h" -#include "Stream.h" - -class XRef; - -#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(XRef *xref, Stream *str); - - // Construct a lexer for a stream or array of streams (assumes obj - // is either a stream or array of streams). - Lexer(XRef *xref, 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. This is only used for error - // messages, so it returns an int instead of a Guint. - int getPos() - { return curStr.isNone() ? -1 : (int)curStr.streamGetPos(); } - - // Set position in file. - void setPos(Guint pos, int dir = 0) - { if (!curStr.isNone()) curStr.streamSetPos(pos, dir); } - - // Returns true if <c> is a whitespace character. - static GBool isSpace(int c); - -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 deleted file mode 100644 index de2bbf82e..000000000 --- a/pdftops/Link.cxx +++ /dev/null @@ -1,907 +0,0 @@ -//======================================================================== -// -// Link.cc -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include <stddef.h> -#include <string.h> -#include "gmem.h" -#include "GString.h" -#include "Error.h" -#include "Object.h" -#include "Array.h" -#include "Dict.h" -#include "Link.h" - -//------------------------------------------------------------------------ -// LinkAction -//------------------------------------------------------------------------ - -LinkAction *LinkAction::parseDest(Object *obj) { - LinkAction *action; - - action = new LinkGoTo(obj); - if (!action->isOk()) { - delete action; - return NULL; - } - return action; -} - -LinkAction *LinkAction::parseAction(Object *obj, GString *baseURI) { - LinkAction *action; - Object obj2, obj3, obj4; - - if (!obj->isDict()) { - error(-1, "Bad annotation action"); - return NULL; - } - - obj->dictLookup("S", &obj2); - - // GoTo action - if (obj2.isName("GoTo")) { - obj->dictLookup("D", &obj3); - action = new LinkGoTo(&obj3); - obj3.free(); - - // GoToR action - } else if (obj2.isName("GoToR")) { - obj->dictLookup("F", &obj3); - obj->dictLookup("D", &obj4); - action = new LinkGoToR(&obj3, &obj4); - obj3.free(); - obj4.free(); - - // Launch action - } else if (obj2.isName("Launch")) { - action = new LinkLaunch(obj); - - // URI action - } else if (obj2.isName("URI")) { - obj->dictLookup("URI", &obj3); - action = new LinkURI(&obj3, baseURI); - obj3.free(); - - // Named action - } else if (obj2.isName("Named")) { - obj->dictLookup("N", &obj3); - action = new LinkNamed(&obj3); - obj3.free(); - - // Movie action - } else if (obj2.isName("Movie")) { - obj->dictLookupNF("Annot", &obj3); - obj->dictLookup("T", &obj4); - action = new LinkMovie(&obj3, &obj4); - obj3.free(); - obj4.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(); - - if (action && !action->isOk()) { - delete action; - return NULL; - } - return action; -} - -GString *LinkAction::getFileSpecName(Object *fileSpecObj) { - GString *name; - Object obj1; - - name = NULL; - - // string - if (fileSpecObj->isString()) { - name = fileSpecObj->getString()->copy(); - - // dictionary - } else if (fileSpecObj->isDict()) { -#ifdef WIN32 - if (!fileSpecObj->dictLookup("DOS", &obj1)->isString()) { -#else - if (!fileSpecObj->dictLookup("Unix", &obj1)->isString()) { -#endif - 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"); - } - - // system-dependent path manipulation - if (name) { -#ifdef WIN32 - int i, j; - - // "//...." --> "\...." - // "/x/...." --> "x:\...." - // "/server/share/...." --> "\\server\share\...." - // convert escaped slashes to slashes and unescaped slashes to backslashes - i = 0; - if (name->getChar(0) == '/') { - if (name->getLength() >= 2 && name->getChar(1) == '/') { - name->del(0); - i = 0; - } else if (name->getLength() >= 2 && - ((name->getChar(1) >= 'a' && name->getChar(1) <= 'z') || - (name->getChar(1) >= 'A' && name->getChar(1) <= 'Z')) && - (name->getLength() == 2 || name->getChar(2) == '/')) { - name->setChar(0, name->getChar(1)); - name->setChar(1, ':'); - i = 2; - } else { - for (j = 2; j < name->getLength(); ++j) { - if (name->getChar(j-1) != '\\' && - name->getChar(j) == '/') { - break; - } - } - if (j < name->getLength()) { - name->setChar(0, '\\'); - name->insert(0, '\\'); - i = 2; - } - } - } - for (; i < name->getLength(); ++i) { - if (name->getChar(i) == '/') { - name->setChar(i, '\\'); - } else if (name->getChar(i) == '\\' && - i+1 < name->getLength() && - name->getChar(i+1) == '/') { - name->del(i); - } - } -#else - // no manipulation needed for Unix -#endif - } - - return name; -} - -//------------------------------------------------------------------------ -// LinkDest -//------------------------------------------------------------------------ - -LinkDest::LinkDest(Array *a) { - Object obj1, obj2; - - // initialize fields - left = bottom = right = top = zoom = 0; - ok = gFalse; - - // get page - if (a->getLength() < 2) { - error(-1, "Annotation destination array is too short"); - return; - } - a->getNF(0, &obj1); - if (obj1.isInt()) { - pageNum = obj1.getInt() + 1; - pageIsRef = gFalse; - } else if (obj1.isRef()) { - pageRef.num = obj1.getRefNum(); - pageRef.gen = obj1.getRefGen(); - pageIsRef = gTrue; - } else { - error(-1, "Bad annotation destination"); - goto err2; - } - obj1.free(); - - // get destination type - a->get(1, &obj1); - - // XYZ link - if (obj1.isName("XYZ")) { - kind = destXYZ; - if (a->getLength() < 3) { - changeLeft = gFalse; - } else { - 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(); - } - if (a->getLength() < 4) { - changeTop = gFalse; - } else { - 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(); - } - if (a->getLength() < 5) { - changeZoom = gFalse; - } else { - 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")) { - if (a->getLength() < 2) { - error(-1, "Annotation destination array is too short"); - goto err2; - } - kind = destFit; - - // FitH link - } else if (obj1.isName("FitH")) { - if (a->getLength() < 3) { - error(-1, "Annotation destination array is too short"); - goto err2; - } - 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")) { - if (a->getLength() < 3) { - error(-1, "Annotation destination array is too short"); - goto err2; - } - 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")) { - if (a->getLength() < 6) { - error(-1, "Annotation destination array is too short"); - goto err2; - } - 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")) { - if (a->getLength() < 2) { - error(-1, "Annotation destination array is too short"); - goto err2; - } - kind = destFitB; - - // FitBH link - } else if (obj1.isName("FitBH")) { - if (a->getLength() < 3) { - error(-1, "Annotation destination array is too short"); - goto err2; - } - 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")) { - if (a->getLength() < 3) { - error(-1, "Annotation destination array is too short"); - goto err2; - } - 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()); - 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()); - 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(); -#ifdef WIN32 - if (actionObj->dictLookup("Win", &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"); - } -#else - //~ 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"); - } -#endif - } - 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 && baseURI->getLength() > 0) { - 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; -} - -//------------------------------------------------------------------------ -// LinkNamed -//------------------------------------------------------------------------ - -LinkNamed::LinkNamed(Object *nameObj) { - name = NULL; - if (nameObj->isName()) { - name = new GString(nameObj->getName()); - } -} - -LinkNamed::~LinkNamed() { - if (name) { - delete name; - } -} - -//------------------------------------------------------------------------ -// LinkMovie -//------------------------------------------------------------------------ - -LinkMovie::LinkMovie(Object *annotObj, Object *titleObj) { - annotRef.num = -1; - title = NULL; - if (annotObj->isRef()) { - annotRef = annotObj->getRef(); - } else if (titleObj->isString()) { - title = titleObj->getString()->copy(); - } else { - error(-1, "Movie action is missing both the Annot and T keys"); - } -} - -LinkMovie::~LinkMovie() { - if (title) { - delete title; - } -} - -//------------------------------------------------------------------------ -// LinkUnknown -//------------------------------------------------------------------------ - -LinkUnknown::LinkUnknown(char *actionA) { - action = new GString(actionA); -} - -LinkUnknown::~LinkUnknown() { - delete action; -} - -//------------------------------------------------------------------------ -// LinkBorderStyle -//------------------------------------------------------------------------ - -LinkBorderStyle::LinkBorderStyle(LinkBorderType typeA, double widthA, - double *dashA, int dashLengthA, - double rA, double gA, double bA) { - type = typeA; - width = widthA; - dash = dashA; - dashLength = dashLengthA; - r = rA; - g = gA; - b = bA; -} - -LinkBorderStyle::~LinkBorderStyle() { - if (dash) { - gfree(dash); - } -} - -//------------------------------------------------------------------------ -// Link -//------------------------------------------------------------------------ - -Link::Link(Dict *dict, GString *baseURI) { - Object obj1, obj2, obj3; - LinkBorderType borderType; - double borderWidth; - double *borderDash; - int borderDashLength; - double borderR, borderG, borderB; - double t; - int i; - - borderStyle = NULL; - 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 the border style info - borderType = linkBorderSolid; - borderWidth = 1; - borderDash = NULL; - borderDashLength = 0; - borderR = 0; - borderG = 0; - borderB = 1; - if (dict->lookup("BS", &obj1)->isDict()) { - if (obj1.dictLookup("S", &obj2)->isName()) { - if (obj2.isName("S")) { - borderType = linkBorderSolid; - } else if (obj2.isName("D")) { - borderType = linkBorderDashed; - } else if (obj2.isName("B")) { - borderType = linkBorderEmbossed; - } else if (obj2.isName("I")) { - borderType = linkBorderEngraved; - } else if (obj2.isName("U")) { - borderType = linkBorderUnderlined; - } - } - obj2.free(); - if (obj1.dictLookup("W", &obj2)->isNum()) { - borderWidth = obj2.getNum(); - } - obj2.free(); - if (obj1.dictLookup("D", &obj2)->isArray()) { - borderDashLength = obj2.arrayGetLength(); - borderDash = (double *)gmallocn(borderDashLength, sizeof(double)); - for (i = 0; i < borderDashLength; ++i) { - if (obj2.arrayGet(i, &obj3)->isNum()) { - borderDash[i] = obj3.getNum(); - } else { - borderDash[i] = 1; - } - obj3.free(); - } - } - obj2.free(); - } else { - obj1.free(); - if (dict->lookup("Border", &obj1)->isArray()) { - if (obj1.arrayGetLength() >= 3) { - if (obj1.arrayGet(2, &obj2)->isNum()) { - borderWidth = obj2.getNum(); - } - obj2.free(); - if (obj1.arrayGetLength() >= 4) { - if (obj1.arrayGet(3, &obj2)->isArray()) { - borderType = linkBorderDashed; - borderDashLength = obj2.arrayGetLength(); - borderDash = (double *)gmallocn(borderDashLength, sizeof(double)); - for (i = 0; i < borderDashLength; ++i) { - if (obj2.arrayGet(i, &obj3)->isNum()) { - borderDash[i] = obj3.getNum(); - } else { - borderDash[i] = 1; - } - obj3.free(); - } - } else { - // Adobe draws no border at all if the last element is of - // the wrong type. - borderWidth = 0; - } - obj2.free(); - } - } - } - } - obj1.free(); - if (dict->lookup("C", &obj1)->isArray() && obj1.arrayGetLength() == 3) { - if (obj1.arrayGet(0, &obj2)->isNum()) { - borderR = obj2.getNum(); - } - obj1.free(); - if (obj1.arrayGet(1, &obj2)->isNum()) { - borderG = obj2.getNum(); - } - obj1.free(); - if (obj1.arrayGet(2, &obj2)->isNum()) { - borderB = obj2.getNum(); - } - obj1.free(); - } - obj1.free(); - borderStyle = new LinkBorderStyle(borderType, borderWidth, - borderDash, borderDashLength, - borderR, borderG, borderB); - - // look for destination - if (!dict->lookup("Dest", &obj1)->isNull()) { - action = LinkAction::parseDest(&obj1); - - // look for action - } else { - obj1.free(); - if (dict->lookup("A", &obj1)->isDict()) { - action = LinkAction::parseAction(&obj1, baseURI); - } - } - obj1.free(); - - // check for bad action - if (action) { - ok = gTrue; - } - - return; - - err1: - obj2.free(); - err2: - obj1.free(); -} - -Link::~Link() { - if (borderStyle) { - delete borderStyle; - } - 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 **)greallocn(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 = numLinks - 1; i >= 0; --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; -} diff --git a/pdftops/Link.h b/pdftops/Link.h deleted file mode 100644 index 160b2b8cb..000000000 --- a/pdftops/Link.h +++ /dev/null @@ -1,409 +0,0 @@ -//======================================================================== -// -// Link.h -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef LINK_H -#define LINK_H - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#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 - actionNamed, // named action - actionMovie, // movie action - 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; - - // Parse a destination (old-style action) name, string, or array. - static LinkAction *parseDest(Object *obj); - - // Parse an action dictionary. - static LinkAction *parseAction(Object *obj, GString *baseURI = NULL); - - // Extract a file name from a file specification (string or - // dictionary). - static GString *getFileSpecName(Object *fileSpecObj); -}; - -//------------------------------------------------------------------------ -// LinkDest -//------------------------------------------------------------------------ - -enum LinkDestKind { - destXYZ, - destFit, - destFitH, - destFitV, - destFitR, - destFitB, - destFitBH, - destFitBV -}; - -class LinkDest { -public: - - // Build a LinkDest from the array. - LinkDest(Array *a); - - // 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 -}; - -//------------------------------------------------------------------------ -// LinkNamed -//------------------------------------------------------------------------ - -class LinkNamed: public LinkAction { -public: - - // Build a LinkNamed given the action name. - LinkNamed(Object *nameObj); - - virtual ~LinkNamed(); - - virtual GBool isOk() { return name != NULL; } - - virtual LinkActionKind getKind() { return actionNamed; } - GString *getName() { return name; } - -private: - - GString *name; -}; - -//------------------------------------------------------------------------ -// LinkMovie -//------------------------------------------------------------------------ - -class LinkMovie: public LinkAction { -public: - - LinkMovie(Object *annotObj, Object *titleObj); - - virtual ~LinkMovie(); - - virtual GBool isOk() { return annotRef.num >= 0 || title != NULL; } - - virtual LinkActionKind getKind() { return actionMovie; } - GBool hasAnnotRef() { return annotRef.num >= 0; } - Ref *getAnnotRef() { return &annotRef; } - GString *getTitle() { return title; } - -private: - - Ref annotRef; - GString *title; -}; - -//------------------------------------------------------------------------ -// LinkUnknown -//------------------------------------------------------------------------ - -class LinkUnknown: public LinkAction { -public: - - // Build a LinkUnknown with the specified action type. - LinkUnknown(char *actionA); - - // 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 -}; - -//------------------------------------------------------------------------ -// LinkBorderStyle -//------------------------------------------------------------------------ - -enum LinkBorderType { - linkBorderSolid, - linkBorderDashed, - linkBorderEmbossed, - linkBorderEngraved, - linkBorderUnderlined -}; - -class LinkBorderStyle { -public: - - LinkBorderStyle(LinkBorderType typeA, double widthA, - double *dashA, int dashLengthA, - double rA, double gA, double bA); - ~LinkBorderStyle(); - - LinkBorderType getType() { return type; } - double getWidth() { return width; } - void getDash(double **dashA, int *dashLengthA) - { *dashA = dash; *dashLengthA = dashLength; } - void getColor(double *rA, double *gA, double *bA) - { *rA = r; *gA = g; *bA = b; } - -private: - - LinkBorderType type; - double width; - double *dash; - int dashLength; - double r, g, b; -}; - -//------------------------------------------------------------------------ -// 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 the link rectangle. - void getRect(double *xa1, double *ya1, double *xa2, double *ya2) - { *xa1 = x1; *ya1 = y1; *xa2 = x2; *ya2 = y2; } - - // Get the border style info. - LinkBorderStyle *getBorderStyle() { return borderStyle; } - -private: - - double x1, y1; // lower left corner - double x2, y2; // upper right corner - LinkBorderStyle *borderStyle; // border style - 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 <x>,<y> is in a link, return the associated action; - // else return NULL. - LinkAction *find(double x, double y); - - // Return true if <x>,<y> is in a link. - GBool onLink(double x, double y); - -private: - - Link **links; - int numLinks; -}; - -#endif diff --git a/pdftops/Makefile b/pdftops/Makefile deleted file mode 100644 index c908cc3a2..000000000 --- a/pdftops/Makefile +++ /dev/null @@ -1,149 +0,0 @@ -# -# "$Id: Makefile 6649 2007-07-11 21:46:42Z mike $" -# -# pdftops filter Makefile for the Common UNIX Printing System (CUPS). -# -# CUPS filter changes Copyright 2007 by Apple Inc. and Copyright 1997-2006 -# by Easy Software Products. -# -# Xpdf code Copyright 1996-1999 by Derek B. Noonburg -# - - -include ../Makedefs - -# -# Object files... -# - -LIBOBJS = \ - Annot.o \ - Array.o \ - BuiltinFont.o \ - BuiltinFontTables.o \ - Catalog.o \ - CharCodeToUnicode.o \ - CMap.o \ - Decrypt.o \ - Dict.o \ - Error.o \ - FoFiBase.o \ - FoFiEncodings.o \ - FoFiTrueType.o \ - FoFiType1C.o \ - FoFiType1.o \ - FontEncodingTables.o \ - Function.o \ - gfile.o \ - Gfx.o \ - GfxFont.o \ - GfxState.o \ - GHash.o \ - GList.o \ - GlobalParams.o \ - gmem.o \ - gmempp.o \ - GString.o \ - JArithmeticDecoder.o \ - JBIG2Stream.o \ - JPXStream.o \ - Lexer.o \ - Link.o \ - NameToCharCode.o \ - Object.o \ - Outline.o \ - OutputDev.o \ - Page.o \ - parseargs.o \ - Parser.o \ - PDFDoc.o \ - PDFDocEncoding.o \ - PSOutputDev.o \ - PSTokenizer.o \ - SecurityHandler.o \ - Stream.o \ - UnicodeMap.o \ - UnicodeTypeTable.o \ - XpdfPluginAPI.o \ - XRef.o - -OBJS = pdftops.o $(LIBOBJS) - -TARGETS = libxpdf.a pdftops - - -# -# Make everything... -# - -all: $(TARGETS) - - -# -# Clean all object files... -# - -clean: - $(RM) $(OBJS) - $(RM) libxpdf.a - $(RM) pdftops - $(RM) pdftoraster - - -# -# Update dependencies (without system header dependencies...) -# - -depend: - makedepend -Y -I.. -fDependencies $(OBJS:.o=.cxx) gmem.c parseargs.c >/dev/null 2>&1 - - -# -# Install the filter... -# - -install: all - $(INSTALL_DIR) -m 755 $(SERVERBIN)/filter - $(INSTALL_BIN) pdftops $(SERVERBIN)/filter - - -# -# Uninstall the filter... -# - -uninstall: - $(RM) $(SERVERBIN)/filter/pdftops - -$(RMDIR) $(SERVERBIN)/filter - -$(RMDIR) $(SERVERBIN) - - -# -# pdftops -# - -pdftops: libxpdf.a pdftops.o ../cups/$(LIBCUPS) - echo Linking $@... - $(CXX) $(LDFLAGS) -o $@ pdftops.o libxpdf.a $(LIBS) $(CXXLIBS) -lm - - -# -# libxpdf.a -# - -libxpdf.a: $(LIBOBJS) - echo Archiving $@... - $(RM) $@ - $(AR) $(ARFLAGS) $@ $(LIBOBJS) - $(RANLIB) $@ - - -# -# Dependencies... -# - -include Dependencies - - -# -# End of "$Id: Makefile 6649 2007-07-11 21:46:42Z mike $". -# diff --git a/pdftops/NameToCharCode.cxx b/pdftops/NameToCharCode.cxx deleted file mode 100644 index a3ef99977..000000000 --- a/pdftops/NameToCharCode.cxx +++ /dev/null @@ -1,116 +0,0 @@ -//======================================================================== -// -// NameToCharCode.cc -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include <string.h> -#include "gmem.h" -#include "NameToCharCode.h" - -//------------------------------------------------------------------------ - -struct NameToCharCodeEntry { - char *name; - CharCode c; -}; - -//------------------------------------------------------------------------ - -NameToCharCode::NameToCharCode() { - int i; - - size = 31; - len = 0; - tab = (NameToCharCodeEntry *)gmallocn(size, sizeof(NameToCharCodeEntry)); - for (i = 0; i < size; ++i) { - tab[i].name = NULL; - } -} - -NameToCharCode::~NameToCharCode() { - int i; - - for (i = 0; i < size; ++i) { - if (tab[i].name) { - gfree(tab[i].name); - } - } - gfree(tab); -} - -void NameToCharCode::add(char *name, CharCode c) { - NameToCharCodeEntry *oldTab; - int h, i, oldSize; - - // expand the table if necessary - if (len >= size / 2) { - oldSize = size; - oldTab = tab; - size = 2*size + 1; - tab = (NameToCharCodeEntry *)gmallocn(size, sizeof(NameToCharCodeEntry)); - for (h = 0; h < size; ++h) { - tab[h].name = NULL; - } - for (i = 0; i < oldSize; ++i) { - if (oldTab[i].name) { - h = hash(oldTab[i].name); - while (tab[h].name) { - if (++h == size) { - h = 0; - } - } - tab[h] = oldTab[i]; - } - } - gfree(oldTab); - } - - // add the new name - h = hash(name); - while (tab[h].name && strcmp(tab[h].name, name)) { - if (++h == size) { - h = 0; - } - } - if (!tab[h].name) { - tab[h].name = copyString(name); - } - tab[h].c = c; - - ++len; -} - -CharCode NameToCharCode::lookup(char *name) { - int h; - - h = hash(name); - while (tab[h].name) { - if (!strcmp(tab[h].name, name)) { - return tab[h].c; - } - if (++h == size) { - h = 0; - } - } - return 0; -} - -int NameToCharCode::hash(char *name) { - char *p; - unsigned int h; - - h = 0; - for (p = name; *p; ++p) { - h = 17 * h + (int)(*p & 0xff); - } - return (int)(h % size); -} diff --git a/pdftops/NameToCharCode.h b/pdftops/NameToCharCode.h deleted file mode 100644 index 30147fb07..000000000 --- a/pdftops/NameToCharCode.h +++ /dev/null @@ -1,42 +0,0 @@ -//======================================================================== -// -// NameToCharCode.h -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef NAMETOCHARCODE_H -#define NAMETOCHARCODE_H - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "CharTypes.h" - -struct NameToCharCodeEntry; - -//------------------------------------------------------------------------ - -class NameToCharCode { -public: - - NameToCharCode(); - ~NameToCharCode(); - - void add(char *name, CharCode c); - CharCode lookup(char *name); - -private: - - int hash(char *name); - - NameToCharCodeEntry *tab; - int size; - int len; -}; - -#endif diff --git a/pdftops/NameToUnicodeTable.h b/pdftops/NameToUnicodeTable.h deleted file mode 100644 index 0b1812c0c..000000000 --- a/pdftops/NameToUnicodeTable.h +++ /dev/null @@ -1,1097 +0,0 @@ -//======================================================================== -// -// NameToUnicodeTable.h -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -static struct { - Unicode u; - char *name; -} nameToUnicodeTab[] = { - {0x0021, "!"}, - {0x0023, "#"}, - {0x0024, "$"}, - {0x0025, "%"}, - {0x0026, "&"}, - {0x0027, "'"}, - {0x0028, "("}, - {0x0029, ")"}, - {0x002a, "*"}, - {0x002b, "+"}, - {0x002c, ","}, - {0x002d, "-"}, - {0x002e, "."}, - {0x002f, "/"}, - {0x0030, "0"}, - {0x0031, "1"}, - {0x0032, "2"}, - {0x0033, "3"}, - {0x0034, "4"}, - {0x0035, "5"}, - {0x0036, "6"}, - {0x0037, "7"}, - {0x0038, "8"}, - {0x0039, "9"}, - {0x003a, ":"}, - {0x003b, ";"}, - {0x003c, "<"}, - {0x003d, "="}, - {0x003e, ">"}, - {0x003f, "?"}, - {0x0040, "@"}, - {0x0041, "A"}, - {0x00c6, "AE"}, - {0x01fc, "AEacute"}, - {0xf7e6, "AEsmall"}, - {0x00c1, "Aacute"}, - {0xf7e1, "Aacutesmall"}, - {0x0102, "Abreve"}, - {0x00c2, "Acircumflex"}, - {0xf7e2, "Acircumflexsmall"}, - {0xf6c9, "Acute"}, - {0xf7b4, "Acutesmall"}, - {0x00c4, "Adieresis"}, - {0xf7e4, "Adieresissmall"}, - {0x00c0, "Agrave"}, - {0xf7e0, "Agravesmall"}, - {0x0391, "Alpha"}, - {0x0386, "Alphatonos"}, - {0x0100, "Amacron"}, - {0x0104, "Aogonek"}, - {0x00c5, "Aring"}, - {0x01fa, "Aringacute"}, - {0xf7e5, "Aringsmall"}, - {0xf761, "Asmall"}, - {0x00c3, "Atilde"}, - {0xf7e3, "Atildesmall"}, - {0x0042, "B"}, - {0x0392, "Beta"}, - {0xf6f4, "Brevesmall"}, - {0xf762, "Bsmall"}, - {0x0043, "C"}, - {0x0106, "Cacute"}, - {0xf6ca, "Caron"}, - {0xf6f5, "Caronsmall"}, - {0x010c, "Ccaron"}, - {0x00c7, "Ccedilla"}, - {0xf7e7, "Ccedillasmall"}, - {0x0108, "Ccircumflex"}, - {0x010a, "Cdotaccent"}, - {0xf7b8, "Cedillasmall"}, - {0x03a7, "Chi"}, - {0xf6f6, "Circumflexsmall"}, - {0xf763, "Csmall"}, - {0x0044, "D"}, - {0x010e, "Dcaron"}, - {0x0110, "Dcroat"}, - {0x2206, "Delta"}, - {0xf6cb, "Dieresis"}, - {0xf6cc, "DieresisAcute"}, - {0xf6cd, "DieresisGrave"}, - {0xf7a8, "Dieresissmall"}, - {0xf6f7, "Dotaccentsmall"}, - {0xf764, "Dsmall"}, - {0x0045, "E"}, - {0x00c9, "Eacute"}, - {0xf7e9, "Eacutesmall"}, - {0x0114, "Ebreve"}, - {0x011a, "Ecaron"}, - {0x00ca, "Ecircumflex"}, - {0xf7ea, "Ecircumflexsmall"}, - {0x00cb, "Edieresis"}, - {0xf7eb, "Edieresissmall"}, - {0x0116, "Edotaccent"}, - {0x00c8, "Egrave"}, - {0xf7e8, "Egravesmall"}, - {0x0112, "Emacron"}, - {0x014a, "Eng"}, - {0x0118, "Eogonek"}, - {0x0395, "Epsilon"}, - {0x0388, "Epsilontonos"}, - {0xf765, "Esmall"}, - {0x0397, "Eta"}, - {0x0389, "Etatonos"}, - {0x00d0, "Eth"}, - {0xf7f0, "Ethsmall"}, - {0x20ac, "Euro"}, - {0x0046, "F"}, - {0xf766, "Fsmall"}, - {0x0047, "G"}, - {0x0393, "Gamma"}, - {0x011e, "Gbreve"}, - {0x01e6, "Gcaron"}, - {0x011c, "Gcircumflex"}, - {0x0122, "Gcommaaccent"}, - {0x0120, "Gdotaccent"}, - {0xf6ce, "Grave"}, - {0xf760, "Gravesmall"}, - {0xf767, "Gsmall"}, - {0x0048, "H"}, - {0x25cf, "H18533"}, - {0x25aa, "H18543"}, - {0x25ab, "H18551"}, - {0x25a1, "H22073"}, - {0x0126, "Hbar"}, - {0x0124, "Hcircumflex"}, - {0xf768, "Hsmall"}, - {0xf6cf, "Hungarumlaut"}, - {0xf6f8, "Hungarumlautsmall"}, - {0x0049, "I"}, - {0x0132, "IJ"}, - {0x00cd, "Iacute"}, - {0xf7ed, "Iacutesmall"}, - {0x012c, "Ibreve"}, - {0x00ce, "Icircumflex"}, - {0xf7ee, "Icircumflexsmall"}, - {0x00cf, "Idieresis"}, - {0xf7ef, "Idieresissmall"}, - {0x0130, "Idotaccent"}, - {0x2111, "Ifraktur"}, - {0x00cc, "Igrave"}, - {0xf7ec, "Igravesmall"}, - {0x012a, "Imacron"}, - {0x012e, "Iogonek"}, - {0x0399, "Iota"}, - {0x03aa, "Iotadieresis"}, - {0x038a, "Iotatonos"}, - {0xf769, "Ismall"}, - {0x0128, "Itilde"}, - {0x004a, "J"}, - {0x0134, "Jcircumflex"}, - {0xf76a, "Jsmall"}, - {0x004b, "K"}, - {0x039a, "Kappa"}, - {0x0136, "Kcommaaccent"}, - {0xf76b, "Ksmall"}, - {0x004c, "L"}, - {0xf6bf, "LL"}, - {0x0139, "Lacute"}, - {0x039b, "Lambda"}, - {0x013d, "Lcaron"}, - {0x013b, "Lcommaaccent"}, - {0x013f, "Ldot"}, - {0x0141, "Lslash"}, - {0xf6f9, "Lslashsmall"}, - {0xf76c, "Lsmall"}, - {0x004d, "M"}, - {0xf6d0, "Macron"}, - {0xf7af, "Macronsmall"}, - {0xf76d, "Msmall"}, - {0x039c, "Mu"}, - {0x004e, "N"}, - {0x0143, "Nacute"}, - {0x0147, "Ncaron"}, - {0x0145, "Ncommaaccent"}, - {0xf76e, "Nsmall"}, - {0x00d1, "Ntilde"}, - {0xf7f1, "Ntildesmall"}, - {0x039d, "Nu"}, - {0x004f, "O"}, - {0x0152, "OE"}, - {0xf6fa, "OEsmall"}, - {0x00d3, "Oacute"}, - {0xf7f3, "Oacutesmall"}, - {0x014e, "Obreve"}, - {0x00d4, "Ocircumflex"}, - {0xf7f4, "Ocircumflexsmall"}, - {0x00d6, "Odieresis"}, - {0xf7f6, "Odieresissmall"}, - {0xf6fb, "Ogoneksmall"}, - {0x00d2, "Ograve"}, - {0xf7f2, "Ogravesmall"}, - {0x01a0, "Ohorn"}, - {0x0150, "Ohungarumlaut"}, - {0x014c, "Omacron"}, - {0x2126, "Omega"}, - {0x038f, "Omegatonos"}, - {0x039f, "Omicron"}, - {0x038c, "Omicrontonos"}, - {0x00d8, "Oslash"}, - {0x01fe, "Oslashacute"}, - {0xf7f8, "Oslashsmall"}, - {0xf76f, "Osmall"}, - {0x00d5, "Otilde"}, - {0xf7f5, "Otildesmall"}, - {0x0050, "P"}, - {0x03a6, "Phi"}, - {0x03a0, "Pi"}, - {0x03a8, "Psi"}, - {0xf770, "Psmall"}, - {0x0051, "Q"}, - {0xf771, "Qsmall"}, - {0x0052, "R"}, - {0x0154, "Racute"}, - {0x0158, "Rcaron"}, - {0x0156, "Rcommaaccent"}, - {0x211c, "Rfraktur"}, - {0x03a1, "Rho"}, - {0xf6fc, "Ringsmall"}, - {0xf772, "Rsmall"}, - {0x0053, "S"}, - {0x250c, "SF010000"}, - {0x2514, "SF020000"}, - {0x2510, "SF030000"}, - {0x2518, "SF040000"}, - {0x253c, "SF050000"}, - {0x252c, "SF060000"}, - {0x2534, "SF070000"}, - {0x251c, "SF080000"}, - {0x2524, "SF090000"}, - {0x2500, "SF100000"}, - {0x2502, "SF110000"}, - {0x2561, "SF190000"}, - {0x2562, "SF200000"}, - {0x2556, "SF210000"}, - {0x2555, "SF220000"}, - {0x2563, "SF230000"}, - {0x2551, "SF240000"}, - {0x2557, "SF250000"}, - {0x255d, "SF260000"}, - {0x255c, "SF270000"}, - {0x255b, "SF280000"}, - {0x255e, "SF360000"}, - {0x255f, "SF370000"}, - {0x255a, "SF380000"}, - {0x2554, "SF390000"}, - {0x2569, "SF400000"}, - {0x2566, "SF410000"}, - {0x2560, "SF420000"}, - {0x2550, "SF430000"}, - {0x256c, "SF440000"}, - {0x2567, "SF450000"}, - {0x2568, "SF460000"}, - {0x2564, "SF470000"}, - {0x2565, "SF480000"}, - {0x2559, "SF490000"}, - {0x2558, "SF500000"}, - {0x2552, "SF510000"}, - {0x2553, "SF520000"}, - {0x256b, "SF530000"}, - {0x256a, "SF540000"}, - {0x015a, "Sacute"}, - {0x0160, "Scaron"}, - {0xf6fd, "Scaronsmall"}, - {0x015e, "Scedilla"}, - {0x015c, "Scircumflex"}, - {0x0218, "Scommaaccent"}, - {0x03a3, "Sigma"}, - {0xf773, "Ssmall"}, - {0x0054, "T"}, - {0x03a4, "Tau"}, - {0x0166, "Tbar"}, - {0x0164, "Tcaron"}, - {0x0162, "Tcommaaccent"}, - {0x0398, "Theta"}, - {0x00de, "Thorn"}, - {0xf7fe, "Thornsmall"}, - {0xf6fe, "Tildesmall"}, - {0xf774, "Tsmall"}, - {0x0055, "U"}, - {0x00da, "Uacute"}, - {0xf7fa, "Uacutesmall"}, - {0x016c, "Ubreve"}, - {0x00db, "Ucircumflex"}, - {0xf7fb, "Ucircumflexsmall"}, - {0x00dc, "Udieresis"}, - {0xf7fc, "Udieresissmall"}, - {0x00d9, "Ugrave"}, - {0xf7f9, "Ugravesmall"}, - {0x01af, "Uhorn"}, - {0x0170, "Uhungarumlaut"}, - {0x016a, "Umacron"}, - {0x0172, "Uogonek"}, - {0x03a5, "Upsilon"}, - {0x03d2, "Upsilon1"}, - {0x03ab, "Upsilondieresis"}, - {0x038e, "Upsilontonos"}, - {0x016e, "Uring"}, - {0xf775, "Usmall"}, - {0x0168, "Utilde"}, - {0x0056, "V"}, - {0xf776, "Vsmall"}, - {0x0057, "W"}, - {0x1e82, "Wacute"}, - {0x0174, "Wcircumflex"}, - {0x1e84, "Wdieresis"}, - {0x1e80, "Wgrave"}, - {0xf777, "Wsmall"}, - {0x0058, "X"}, - {0x039e, "Xi"}, - {0xf778, "Xsmall"}, - {0x0059, "Y"}, - {0x00dd, "Yacute"}, - {0xf7fd, "Yacutesmall"}, - {0x0176, "Ycircumflex"}, - {0x0178, "Ydieresis"}, - {0xf7ff, "Ydieresissmall"}, - {0x1ef2, "Ygrave"}, - {0xf779, "Ysmall"}, - {0x005a, "Z"}, - {0x0179, "Zacute"}, - {0x017d, "Zcaron"}, - {0xf6ff, "Zcaronsmall"}, - {0x017b, "Zdotaccent"}, - {0x0396, "Zeta"}, - {0xf77a, "Zsmall"}, - {0x0022, "\""}, - {0x005c, "\\"}, - {0x005d, "]"}, - {0x005e, "^"}, - {0x005f, "_"}, - {0x0060, "`"}, - {0x0061, "a"}, - {0x00e1, "aacute"}, - {0x0103, "abreve"}, - {0x00e2, "acircumflex"}, - {0x00b4, "acute"}, - {0x0301, "acutecomb"}, - {0x00e4, "adieresis"}, - {0x00e6, "ae"}, - {0x01fd, "aeacute"}, - {0x2015, "afii00208"}, - {0x0410, "afii10017"}, - {0x0411, "afii10018"}, - {0x0412, "afii10019"}, - {0x0413, "afii10020"}, - {0x0414, "afii10021"}, - {0x0415, "afii10022"}, - {0x0401, "afii10023"}, - {0x0416, "afii10024"}, - {0x0417, "afii10025"}, - {0x0418, "afii10026"}, - {0x0419, "afii10027"}, - {0x041a, "afii10028"}, - {0x041b, "afii10029"}, - {0x041c, "afii10030"}, - {0x041d, "afii10031"}, - {0x041e, "afii10032"}, - {0x041f, "afii10033"}, - {0x0420, "afii10034"}, - {0x0421, "afii10035"}, - {0x0422, "afii10036"}, - {0x0423, "afii10037"}, - {0x0424, "afii10038"}, - {0x0425, "afii10039"}, - {0x0426, "afii10040"}, - {0x0427, "afii10041"}, - {0x0428, "afii10042"}, - {0x0429, "afii10043"}, - {0x042a, "afii10044"}, - {0x042b, "afii10045"}, - {0x042c, "afii10046"}, - {0x042d, "afii10047"}, - {0x042e, "afii10048"}, - {0x042f, "afii10049"}, - {0x0490, "afii10050"}, - {0x0402, "afii10051"}, - {0x0403, "afii10052"}, - {0x0404, "afii10053"}, - {0x0405, "afii10054"}, - {0x0406, "afii10055"}, - {0x0407, "afii10056"}, - {0x0408, "afii10057"}, - {0x0409, "afii10058"}, - {0x040a, "afii10059"}, - {0x040b, "afii10060"}, - {0x040c, "afii10061"}, - {0x040e, "afii10062"}, - {0xf6c4, "afii10063"}, - {0xf6c5, "afii10064"}, - {0x0430, "afii10065"}, - {0x0431, "afii10066"}, - {0x0432, "afii10067"}, - {0x0433, "afii10068"}, - {0x0434, "afii10069"}, - {0x0435, "afii10070"}, - {0x0451, "afii10071"}, - {0x0436, "afii10072"}, - {0x0437, "afii10073"}, - {0x0438, "afii10074"}, - {0x0439, "afii10075"}, - {0x043a, "afii10076"}, - {0x043b, "afii10077"}, - {0x043c, "afii10078"}, - {0x043d, "afii10079"}, - {0x043e, "afii10080"}, - {0x043f, "afii10081"}, - {0x0440, "afii10082"}, - {0x0441, "afii10083"}, - {0x0442, "afii10084"}, - {0x0443, "afii10085"}, - {0x0444, "afii10086"}, - {0x0445, "afii10087"}, - {0x0446, "afii10088"}, - {0x0447, "afii10089"}, - {0x0448, "afii10090"}, - {0x0449, "afii10091"}, - {0x044a, "afii10092"}, - {0x044b, "afii10093"}, - {0x044c, "afii10094"}, - {0x044d, "afii10095"}, - {0x044e, "afii10096"}, - {0x044f, "afii10097"}, - {0x0491, "afii10098"}, - {0x0452, "afii10099"}, - {0x0453, "afii10100"}, - {0x0454, "afii10101"}, - {0x0455, "afii10102"}, - {0x0456, "afii10103"}, - {0x0457, "afii10104"}, - {0x0458, "afii10105"}, - {0x0459, "afii10106"}, - {0x045a, "afii10107"}, - {0x045b, "afii10108"}, - {0x045c, "afii10109"}, - {0x045e, "afii10110"}, - {0x040f, "afii10145"}, - {0x0462, "afii10146"}, - {0x0472, "afii10147"}, - {0x0474, "afii10148"}, - {0xf6c6, "afii10192"}, - {0x045f, "afii10193"}, - {0x0463, "afii10194"}, - {0x0473, "afii10195"}, - {0x0475, "afii10196"}, - {0xf6c7, "afii10831"}, - {0xf6c8, "afii10832"}, - {0x04d9, "afii10846"}, - {0x200e, "afii299"}, - {0x200f, "afii300"}, - {0x200d, "afii301"}, - {0x066a, "afii57381"}, - {0x060c, "afii57388"}, - {0x0660, "afii57392"}, - {0x0661, "afii57393"}, - {0x0662, "afii57394"}, - {0x0663, "afii57395"}, - {0x0664, "afii57396"}, - {0x0665, "afii57397"}, - {0x0666, "afii57398"}, - {0x0667, "afii57399"}, - {0x0668, "afii57400"}, - {0x0669, "afii57401"}, - {0x061b, "afii57403"}, - {0x061f, "afii57407"}, - {0x0621, "afii57409"}, - {0x0622, "afii57410"}, - {0x0623, "afii57411"}, - {0x0624, "afii57412"}, - {0x0625, "afii57413"}, - {0x0626, "afii57414"}, - {0x0627, "afii57415"}, - {0x0628, "afii57416"}, - {0x0629, "afii57417"}, - {0x062a, "afii57418"}, - {0x062b, "afii57419"}, - {0x062c, "afii57420"}, - {0x062d, "afii57421"}, - {0x062e, "afii57422"}, - {0x062f, "afii57423"}, - {0x0630, "afii57424"}, - {0x0631, "afii57425"}, - {0x0632, "afii57426"}, - {0x0633, "afii57427"}, - {0x0634, "afii57428"}, - {0x0635, "afii57429"}, - {0x0636, "afii57430"}, - {0x0637, "afii57431"}, - {0x0638, "afii57432"}, - {0x0639, "afii57433"}, - {0x063a, "afii57434"}, - {0x0640, "afii57440"}, - {0x0641, "afii57441"}, - {0x0642, "afii57442"}, - {0x0643, "afii57443"}, - {0x0644, "afii57444"}, - {0x0645, "afii57445"}, - {0x0646, "afii57446"}, - {0x0648, "afii57448"}, - {0x0649, "afii57449"}, - {0x064a, "afii57450"}, - {0x064b, "afii57451"}, - {0x064c, "afii57452"}, - {0x064d, "afii57453"}, - {0x064e, "afii57454"}, - {0x064f, "afii57455"}, - {0x0650, "afii57456"}, - {0x0651, "afii57457"}, - {0x0652, "afii57458"}, - {0x0647, "afii57470"}, - {0x06a4, "afii57505"}, - {0x067e, "afii57506"}, - {0x0686, "afii57507"}, - {0x0698, "afii57508"}, - {0x06af, "afii57509"}, - {0x0679, "afii57511"}, - {0x0688, "afii57512"}, - {0x0691, "afii57513"}, - {0x06ba, "afii57514"}, - {0x06d2, "afii57519"}, - {0x06d5, "afii57534"}, - {0x20aa, "afii57636"}, - {0x05be, "afii57645"}, - {0x05c3, "afii57658"}, - {0x05d0, "afii57664"}, - {0x05d1, "afii57665"}, - {0x05d2, "afii57666"}, - {0x05d3, "afii57667"}, - {0x05d4, "afii57668"}, - {0x05d5, "afii57669"}, - {0x05d6, "afii57670"}, - {0x05d7, "afii57671"}, - {0x05d8, "afii57672"}, - {0x05d9, "afii57673"}, - {0x05da, "afii57674"}, - {0x05db, "afii57675"}, - {0x05dc, "afii57676"}, - {0x05dd, "afii57677"}, - {0x05de, "afii57678"}, - {0x05df, "afii57679"}, - {0x05e0, "afii57680"}, - {0x05e1, "afii57681"}, - {0x05e2, "afii57682"}, - {0x05e3, "afii57683"}, - {0x05e4, "afii57684"}, - {0x05e5, "afii57685"}, - {0x05e6, "afii57686"}, - {0x05e7, "afii57687"}, - {0x05e8, "afii57688"}, - {0x05e9, "afii57689"}, - {0x05ea, "afii57690"}, - {0xfb2a, "afii57694"}, - {0xfb2b, "afii57695"}, - {0xfb4b, "afii57700"}, - {0xfb1f, "afii57705"}, - {0x05f0, "afii57716"}, - {0x05f1, "afii57717"}, - {0x05f2, "afii57718"}, - {0xfb35, "afii57723"}, - {0x05b4, "afii57793"}, - {0x05b5, "afii57794"}, - {0x05b6, "afii57795"}, - {0x05bb, "afii57796"}, - {0x05b8, "afii57797"}, - {0x05b7, "afii57798"}, - {0x05b0, "afii57799"}, - {0x05b2, "afii57800"}, - {0x05b1, "afii57801"}, - {0x05b3, "afii57802"}, - {0x05c2, "afii57803"}, - {0x05c1, "afii57804"}, - {0x05b9, "afii57806"}, - {0x05bc, "afii57807"}, - {0x05bd, "afii57839"}, - {0x05bf, "afii57841"}, - {0x05c0, "afii57842"}, - {0x02bc, "afii57929"}, - {0x2105, "afii61248"}, - {0x2113, "afii61289"}, - {0x2116, "afii61352"}, - {0x202c, "afii61573"}, - {0x202d, "afii61574"}, - {0x202e, "afii61575"}, - {0x200c, "afii61664"}, - {0x066d, "afii63167"}, - {0x02bd, "afii64937"}, - {0x00e0, "agrave"}, - {0x2135, "aleph"}, - {0x03b1, "alpha"}, - {0x03ac, "alphatonos"}, - {0x0101, "amacron"}, - {0x0026, "ampersand"}, - {0xf726, "ampersandsmall"}, - {0x2220, "angle"}, - {0x2329, "angleleft"}, - {0x232a, "angleright"}, - {0x0387, "anoteleia"}, - {0x0105, "aogonek"}, - {0x2248, "approxequal"}, - {0x00e5, "aring"}, - {0x01fb, "aringacute"}, - {0x2194, "arrowboth"}, - {0x21d4, "arrowdblboth"}, - {0x21d3, "arrowdbldown"}, - {0x21d0, "arrowdblleft"}, - {0x21d2, "arrowdblright"}, - {0x21d1, "arrowdblup"}, - {0x2193, "arrowdown"}, - {0xf8e7, "arrowhorizex"}, - {0x2190, "arrowleft"}, - {0x2192, "arrowright"}, - {0x2191, "arrowup"}, - {0x2195, "arrowupdn"}, - {0x21a8, "arrowupdnbse"}, - {0xf8e6, "arrowvertex"}, - {0x005e, "asciicircum"}, - {0x007e, "asciitilde"}, - {0x002a, "asterisk"}, - {0x2217, "asteriskmath"}, - {0xf6e9, "asuperior"}, - {0x0040, "at"}, - {0x00e3, "atilde"}, - {0x0062, "b"}, - {0x005c, "backslash"}, - {0x007c, "bar"}, - {0x03b2, "beta"}, - {0x2588, "block"}, - {0xf8f4, "braceex"}, - {0x007b, "braceleft"}, - {0xf8f3, "braceleftbt"}, - {0xf8f2, "braceleftmid"}, - {0xf8f1, "bracelefttp"}, - {0x007d, "braceright"}, - {0xf8fe, "bracerightbt"}, - {0xf8fd, "bracerightmid"}, - {0xf8fc, "bracerighttp"}, - {0x005b, "bracketleft"}, - {0xf8f0, "bracketleftbt"}, - {0xf8ef, "bracketleftex"}, - {0xf8ee, "bracketlefttp"}, - {0x005d, "bracketright"}, - {0xf8fb, "bracketrightbt"}, - {0xf8fa, "bracketrightex"}, - {0xf8f9, "bracketrighttp"}, - {0x02d8, "breve"}, - {0x00a6, "brokenbar"}, - {0xf6ea, "bsuperior"}, - {0x2022, "bullet"}, - {0x0063, "c"}, - {0x0107, "cacute"}, - {0x02c7, "caron"}, - {0x21b5, "carriagereturn"}, - {0x010d, "ccaron"}, - {0x00e7, "ccedilla"}, - {0x0109, "ccircumflex"}, - {0x010b, "cdotaccent"}, - {0x00b8, "cedilla"}, - {0x00a2, "cent"}, - {0xf6df, "centinferior"}, - {0xf7a2, "centoldstyle"}, - {0xf6e0, "centsuperior"}, - {0x03c7, "chi"}, - {0x25cb, "circle"}, - {0x2297, "circlemultiply"}, - {0x2295, "circleplus"}, - {0x02c6, "circumflex"}, - {0x2663, "club"}, - {0x003a, "colon"}, - {0x20a1, "colonmonetary"}, - {0x002c, "comma"}, - {0xf6c3, "commaaccent"}, - {0xf6e1, "commainferior"}, - {0xf6e2, "commasuperior"}, - {0x2245, "congruent"}, - {0x00a9, "copyright"}, - {0x00a9, "copyrightsans"}, - {0x00a9, "copyrightserif"}, - {0x00a4, "currency"}, - {0xf6d1, "cyrBreve"}, - {0xf6d2, "cyrFlex"}, - {0xf6d4, "cyrbreve"}, - {0xf6d5, "cyrflex"}, - {0x0064, "d"}, - {0x2020, "dagger"}, - {0x2021, "daggerdbl"}, - {0xf6d3, "dblGrave"}, - {0xf6d6, "dblgrave"}, - {0x010f, "dcaron"}, - {0x0111, "dcroat"}, - {0x00b0, "degree"}, - {0x03b4, "delta"}, - {0x2666, "diamond"}, - {0x00a8, "dieresis"}, - {0xf6d7, "dieresisacute"}, - {0xf6d8, "dieresisgrave"}, - {0x0385, "dieresistonos"}, - {0x00f7, "divide"}, - {0x2593, "dkshade"}, - {0x2584, "dnblock"}, - {0x0024, "dollar"}, - {0xf6e3, "dollarinferior"}, - {0xf724, "dollaroldstyle"}, - {0xf6e4, "dollarsuperior"}, - {0x20ab, "dong"}, - {0x02d9, "dotaccent"}, - {0x0323, "dotbelowcomb"}, - {0x0131, "dotlessi"}, - {0xf6be, "dotlessj"}, - {0x22c5, "dotmath"}, - {0xf6eb, "dsuperior"}, - {0x0065, "e"}, - {0x00e9, "eacute"}, - {0x0115, "ebreve"}, - {0x011b, "ecaron"}, - {0x00ea, "ecircumflex"}, - {0x00eb, "edieresis"}, - {0x0117, "edotaccent"}, - {0x00e8, "egrave"}, - {0x0038, "eight"}, - {0x2088, "eightinferior"}, - {0xf738, "eightoldstyle"}, - {0x2078, "eightsuperior"}, - {0x2208, "element"}, - {0x2026, "ellipsis"}, - {0x0113, "emacron"}, - {0x2014, "emdash"}, - {0x2205, "emptyset"}, - {0x2013, "endash"}, - {0x014b, "eng"}, - {0x0119, "eogonek"}, - {0x03b5, "epsilon"}, - {0x03ad, "epsilontonos"}, - {0x003d, "equal"}, - {0x2261, "equivalence"}, - {0x212e, "estimated"}, - {0xf6ec, "esuperior"}, - {0x03b7, "eta"}, - {0x03ae, "etatonos"}, - {0x00f0, "eth"}, - {0x0021, "exclam"}, - {0x203c, "exclamdbl"}, - {0x00a1, "exclamdown"}, - {0xf7a1, "exclamdownsmall"}, - {0x0021, "exclamleft"}, - {0xf721, "exclamsmall"}, - {0x2203, "existential"}, - {0x0066, "f"}, - {0x2640, "female"}, - {0xfb00, "ff"}, - {0xfb03, "ffi"}, - {0xfb04, "ffl"}, - {0xfb01, "fi"}, - {0x2012, "figuredash"}, - {0x25a0, "filledbox"}, - {0x25ac, "filledrect"}, - {0x0035, "five"}, - {0x215d, "fiveeighths"}, - {0x2085, "fiveinferior"}, - {0xf735, "fiveoldstyle"}, - {0x2075, "fivesuperior"}, - {0xfb02, "fl"}, - {0x0192, "florin"}, - {0x0034, "four"}, - {0x2084, "fourinferior"}, - {0xf734, "fouroldstyle"}, - {0x2074, "foursuperior"}, - {0x2044, "fraction"}, - {0x20a3, "franc"}, - {0x0067, "g"}, - {0x03b3, "gamma"}, - {0x011f, "gbreve"}, - {0x01e7, "gcaron"}, - {0x011d, "gcircumflex"}, - {0x0123, "gcommaaccent"}, - {0x0121, "gdotaccent"}, - {0x00df, "germandbls"}, - {0x2207, "gradient"}, - {0x0060, "grave"}, - {0x0300, "gravecomb"}, - {0x003e, "greater"}, - {0x2265, "greaterequal"}, - {0x00ab, "guillemotleft"}, - {0x00bb, "guillemotright"}, - {0x2039, "guilsinglleft"}, - {0x203a, "guilsinglright"}, - {0x0068, "h"}, - {0x0127, "hbar"}, - {0x0125, "hcircumflex"}, - {0x2665, "heart"}, - {0x0309, "hookabovecomb"}, - {0x2302, "house"}, - {0x02dd, "hungarumlaut"}, - {0x002d, "hyphen"}, - {0xf6e5, "hypheninferior"}, - {0xf6e6, "hyphensuperior"}, - {0x0069, "i"}, - {0x00ed, "iacute"}, - {0x012d, "ibreve"}, - {0x00ee, "icircumflex"}, - {0x00ef, "idieresis"}, - {0x00ec, "igrave"}, - {0x0133, "ij"}, - {0x012b, "imacron"}, - {0x221e, "infinity"}, - {0x222b, "integral"}, - {0x2321, "integralbt"}, - {0xf8f5, "integralex"}, - {0x2320, "integraltp"}, - {0x2229, "intersection"}, - {0x25d8, "invbullet"}, - {0x25d9, "invcircle"}, - {0x263b, "invsmileface"}, - {0x012f, "iogonek"}, - {0x03b9, "iota"}, - {0x03ca, "iotadieresis"}, - {0x0390, "iotadieresistonos"}, - {0x03af, "iotatonos"}, - {0xf6ed, "isuperior"}, - {0x0129, "itilde"}, - {0x006a, "j"}, - {0x0135, "jcircumflex"}, - {0x006b, "k"}, - {0x03ba, "kappa"}, - {0x0137, "kcommaaccent"}, - {0x0138, "kgreenlandic"}, - {0x006c, "l"}, - {0x013a, "lacute"}, - {0x03bb, "lambda"}, - {0x013e, "lcaron"}, - {0x013c, "lcommaaccent"}, - {0x0140, "ldot"}, - {0x003c, "less"}, - {0x2264, "lessequal"}, - {0x258c, "lfblock"}, - {0x20a4, "lira"}, - {0xf6c0, "ll"}, - {0x2227, "logicaland"}, - {0x00ac, "logicalnot"}, - {0x2228, "logicalor"}, - {0x017f, "longs"}, - {0x25ca, "lozenge"}, - {0x0142, "lslash"}, - {0xf6ee, "lsuperior"}, - {0x2591, "ltshade"}, - {0x006d, "m"}, - {0x00af, "macron"}, - {0x2642, "male"}, - {0x2212, "minus"}, - {0x2032, "minute"}, - {0xf6ef, "msuperior"}, - {0x00b5, "mu"}, - {0x00d7, "multiply"}, - {0x266a, "musicalnote"}, - {0x266b, "musicalnotedbl"}, - {0x006e, "n"}, - {0x0144, "nacute"}, - {0x0149, "napostrophe"}, - {0x00a0, "nbspace"}, - {0x0148, "ncaron"}, - {0x0146, "ncommaaccent"}, - {0x0039, "nine"}, - {0x2089, "nineinferior"}, - {0xf739, "nineoldstyle"}, - {0x2079, "ninesuperior"}, - {0x00a0, "nonbreakingspace"}, - {0x2209, "notelement"}, - {0x2260, "notequal"}, - {0x2284, "notsubset"}, - {0x207f, "nsuperior"}, - {0x00f1, "ntilde"}, - {0x03bd, "nu"}, - {0x0023, "numbersign"}, - {0x006f, "o"}, - {0x00f3, "oacute"}, - {0x014f, "obreve"}, - {0x00f4, "ocircumflex"}, - {0x00f6, "odieresis"}, - {0x0153, "oe"}, - {0x02db, "ogonek"}, - {0x00f2, "ograve"}, - {0x01a1, "ohorn"}, - {0x0151, "ohungarumlaut"}, - {0x014d, "omacron"}, - {0x03c9, "omega"}, - {0x03d6, "omega1"}, - {0x03ce, "omegatonos"}, - {0x03bf, "omicron"}, - {0x03cc, "omicrontonos"}, - {0x0031, "one"}, - {0x2024, "onedotenleader"}, - {0x215b, "oneeighth"}, - {0xf6dc, "onefitted"}, - {0x00bd, "onehalf"}, - {0x2081, "oneinferior"}, - {0xf731, "oneoldstyle"}, - {0x00bc, "onequarter"}, - {0x00b9, "onesuperior"}, - {0x2153, "onethird"}, - {0x25e6, "openbullet"}, - {0x00aa, "ordfeminine"}, - {0x00ba, "ordmasculine"}, - {0x221f, "orthogonal"}, - {0x00f8, "oslash"}, - {0x01ff, "oslashacute"}, - {0xf6f0, "osuperior"}, - {0x00f5, "otilde"}, - {0x0070, "p"}, - {0x00b6, "paragraph"}, - {0x0028, "parenleft"}, - {0xf8ed, "parenleftbt"}, - {0xf8ec, "parenleftex"}, - {0x208d, "parenleftinferior"}, - {0x207d, "parenleftsuperior"}, - {0xf8eb, "parenlefttp"}, - {0x0029, "parenright"}, - {0xf8f8, "parenrightbt"}, - {0xf8f7, "parenrightex"}, - {0x208e, "parenrightinferior"}, - {0x207e, "parenrightsuperior"}, - {0xf8f6, "parenrighttp"}, - {0x2202, "partialdiff"}, - {0x0025, "percent"}, - {0x002e, "period"}, - {0x00b7, "periodcentered"}, - {0xf6e7, "periodinferior"}, - {0xf6e8, "periodsuperior"}, - {0x22a5, "perpendicular"}, - {0x2030, "perthousand"}, - {0x20a7, "peseta"}, - {0x03c6, "phi"}, - {0x03d5, "phi1"}, - {0x03c0, "pi"}, - {0x002b, "plus"}, - {0x00b1, "plusminus"}, - {0x211e, "prescription"}, - {0x220f, "product"}, - {0x2282, "propersubset"}, - {0x2283, "propersuperset"}, - {0x221d, "proportional"}, - {0x03c8, "psi"}, - {0x0071, "q"}, - {0x003f, "question"}, - {0x00bf, "questiondown"}, - {0xf7bf, "questiondownsmall"}, - {0xf73f, "questionsmall"}, - {0x0022, "quotedbl"}, - {0x201e, "quotedblbase"}, - {0x201c, "quotedblleft"}, - {0x201d, "quotedblright"}, - {0x2018, "quoteleft"}, - {0x201b, "quotereversed"}, - {0x2019, "quoteright"}, - {0x201a, "quotesinglbase"}, - {0x0027, "quotesingle"}, - {0x0072, "r"}, - {0x0155, "racute"}, - {0x221a, "radical"}, - {0xf8e5, "radicalex"}, - {0x0159, "rcaron"}, - {0x0157, "rcommaaccent"}, - {0x2286, "reflexsubset"}, - {0x2287, "reflexsuperset"}, - {0x00ae, "registered"}, - {0x00ae, "registersans"}, - {0x00ae, "registerserif"}, - {0x2310, "revlogicalnot"}, - {0x03c1, "rho"}, - {0x02da, "ring"}, - {0xf6f1, "rsuperior"}, - {0x2590, "rtblock"}, - {0xf6dd, "rupiah"}, - {0x0073, "s"}, - {0x015b, "sacute"}, - {0x0161, "scaron"}, - {0x015f, "scedilla"}, - {0x015d, "scircumflex"}, - {0x0219, "scommaaccent"}, - {0x2033, "second"}, - {0x00a7, "section"}, - {0x003b, "semicolon"}, - {0x0037, "seven"}, - {0x215e, "seveneighths"}, - {0x2087, "seveninferior"}, - {0xf737, "sevenoldstyle"}, - {0x2077, "sevensuperior"}, - {0x2592, "shade"}, - {0x03c3, "sigma"}, - {0x03c2, "sigma1"}, - {0x223c, "similar"}, - {0x0036, "six"}, - {0x2086, "sixinferior"}, - {0xf736, "sixoldstyle"}, - {0x2076, "sixsuperior"}, - {0x002f, "slash"}, - {0x263a, "smileface"}, - {0x0020, "space"}, - {0x2660, "spade"}, - {0xf6f2, "ssuperior"}, - {0x00a3, "sterling"}, - {0x220b, "suchthat"}, - {0x2211, "summation"}, - {0x263c, "sun"}, - {0x0074, "t"}, - {0x03c4, "tau"}, - {0x0167, "tbar"}, - {0x0165, "tcaron"}, - {0x0163, "tcommaaccent"}, - {0x2234, "therefore"}, - {0x03b8, "theta"}, - {0x03d1, "theta1"}, - {0x00fe, "thorn"}, - {0x0033, "three"}, - {0x215c, "threeeighths"}, - {0x2083, "threeinferior"}, - {0xf733, "threeoldstyle"}, - {0x00be, "threequarters"}, - {0xf6de, "threequartersemdash"}, - {0x00b3, "threesuperior"}, - {0x02dc, "tilde"}, - {0x0303, "tildecomb"}, - {0x0384, "tonos"}, - {0x2122, "trademark"}, - {0x2122, "trademarksans"}, - {0x2122, "trademarkserif"}, - {0x25bc, "triagdn"}, - {0x25c4, "triaglf"}, - {0x25ba, "triagrt"}, - {0x25b2, "triagup"}, - {0xf6f3, "tsuperior"}, - {0x0032, "two"}, - {0x2025, "twodotenleader"}, - {0x2082, "twoinferior"}, - {0xf732, "twooldstyle"}, - {0x00b2, "twosuperior"}, - {0x2154, "twothirds"}, - {0x0075, "u"}, - {0x00fa, "uacute"}, - {0x016d, "ubreve"}, - {0x00fb, "ucircumflex"}, - {0x00fc, "udieresis"}, - {0x00f9, "ugrave"}, - {0x01b0, "uhorn"}, - {0x0171, "uhungarumlaut"}, - {0x016b, "umacron"}, - {0x005f, "underscore"}, - {0x2017, "underscoredbl"}, - {0x222a, "union"}, - {0x2200, "universal"}, - {0x0173, "uogonek"}, - {0x2580, "upblock"}, - {0x03c5, "upsilon"}, - {0x03cb, "upsilondieresis"}, - {0x03b0, "upsilondieresistonos"}, - {0x03cd, "upsilontonos"}, - {0x016f, "uring"}, - {0x0169, "utilde"}, - {0x0076, "v"}, - {0x0077, "w"}, - {0x1e83, "wacute"}, - {0x0175, "wcircumflex"}, - {0x1e85, "wdieresis"}, - {0x2118, "weierstrass"}, - {0x1e81, "wgrave"}, - {0x0078, "x"}, - {0x03be, "xi"}, - {0x0079, "y"}, - {0x00fd, "yacute"}, - {0x0177, "ycircumflex"}, - {0x00ff, "ydieresis"}, - {0x00a5, "yen"}, - {0x1ef3, "ygrave"}, - {0x007a, "z"}, - {0x017a, "zacute"}, - {0x017e, "zcaron"}, - {0x017c, "zdotaccent"}, - {0x0030, "zero"}, - {0x2080, "zeroinferior"}, - {0xf730, "zerooldstyle"}, - {0x2070, "zerosuperior"}, - {0x03b6, "zeta"}, - {0x007b, "{"}, - {0x007c, "|"}, - {0x007d, "}"}, - {0x007e, "~"}, - { 0, NULL } -}; diff --git a/pdftops/Object.cxx b/pdftops/Object.cxx deleted file mode 100644 index 0b6ac3431..000000000 --- a/pdftops/Object.cxx +++ /dev/null @@ -1,231 +0,0 @@ -//======================================================================== -// -// Object.cc -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include <stddef.h> -#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(XRef *xref) { - initObj(objArray); - array = new Array(xref); - return this; -} - -Object *Object::initDict(XRef *xref) { - initObj(objDict); - dict = new Dict(xref); - return this; -} - -Object *Object::initDict(Dict *dictA) { - initObj(objDict); - dict = dictA; - dict->incRef(); - return this; -} - -Object *Object::initStream(Stream *streamA) { - initObj(objStream); - stream = streamA; - 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(XRef *xref, 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, "("); - fwrite(string->getCString(), 1, string->getLength(), f); - fprintf(f, ")"); - 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, "<stream>"); - break; - case objRef: - fprintf(f, "%d %d R", ref.num, ref.gen); - break; - case objCmd: - fprintf(f, "%s", cmd); - break; - case objError: - fprintf(f, "<error>"); - break; - case objEOF: - fprintf(f, "<EOF>"); - break; - case objNone: - fprintf(f, "<none>"); - 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 deleted file mode 100644 index 72ba2629b..000000000 --- a/pdftops/Object.h +++ /dev/null @@ -1,303 +0,0 @@ -//======================================================================== -// -// Object.h -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef OBJECT_H -#define OBJECT_H - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include <stdio.h> -#include <string.h> -#include "gtypes.h" -#include "gmem.h" -#include "GString.h" - -class XRef; -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 boolnA) - { initObj(objBool); booln = boolnA; return this; } - Object *initInt(int intgA) - { initObj(objInt); intg = intgA; return this; } - Object *initReal(double realA) - { initObj(objReal); real = realA; return this; } - Object *initString(GString *stringA) - { initObj(objString); string = stringA; return this; } - Object *initName(char *nameA) - { initObj(objName); name = copyString(nameA); return this; } - Object *initNull() - { initObj(objNull); return this; } - Object *initArray(XRef *xref); - Object *initDict(XRef *xref); - Object *initDict(Dict *dictA); - Object *initStream(Stream *streamA); - Object *initRef(int numA, int genA) - { initObj(objRef); ref.num = numA; ref.gen = genA; return this; } - Object *initCmd(char *cmdA) - { initObj(objCmd); cmd = copyString(cmdA); 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(XRef *xref, 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 *nameA) - { return type == objName && !strcmp(name, nameA); } - GBool isDict(char *dictType); - GBool isStream(char *dictType); - GBool isCmd(char *cmdA) - { return type == objCmd && !strcmp(cmd, cmdA); } - - // 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; } - char *getCmd() { return cmd; } - - // 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(); - void streamClose(); - int streamGetChar(); - int streamLookChar(); - char *streamGetLine(char *buf, int size); - Guint streamGetPos(); - void streamSetPos(Guint pos, int dir = 0); - 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 void Object::streamClose() - { stream->close(); } - -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 Guint Object::streamGetPos() - { return stream->getPos(); } - -inline void Object::streamSetPos(Guint pos, int dir) - { stream->setPos(pos, dir); } - -inline Dict *Object::streamGetDict() - { return stream->getDict(); } - -#endif diff --git a/pdftops/Outline.cxx b/pdftops/Outline.cxx deleted file mode 100644 index d127e944a..000000000 --- a/pdftops/Outline.cxx +++ /dev/null @@ -1,151 +0,0 @@ -//======================================================================== -// -// Outline.cc -// -// Copyright 2002-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include "gmem.h" -#include "GString.h" -#include "GList.h" -#include "Link.h" -#include "PDFDocEncoding.h" -#include "Outline.h" - -//------------------------------------------------------------------------ - -Outline::Outline(Object *outlineObj, XRef *xref) { - Object first, last; - - items = NULL; - if (!outlineObj->isDict()) { - return; - } - items = OutlineItem::readItemList(outlineObj->dictLookupNF("First", &first), - outlineObj->dictLookupNF("Last", &last), - xref); - first.free(); - last.free(); -} - -Outline::~Outline() { - if (items) { - deleteGList(items, OutlineItem); - } -} - -//------------------------------------------------------------------------ - -OutlineItem::OutlineItem(Dict *dict, XRef *xrefA) { - Object obj1; - GString *s; - int i; - - xref = xrefA; - title = NULL; - action = NULL; - kids = NULL; - - if (dict->lookup("Title", &obj1)->isString()) { - s = obj1.getString(); - if ((s->getChar(0) & 0xff) == 0xfe && - (s->getChar(1) & 0xff) == 0xff) { - titleLen = (s->getLength() - 2) / 2; - title = (Unicode *)gmallocn(titleLen, sizeof(Unicode)); - for (i = 0; i < titleLen; ++i) { - title[i] = ((s->getChar(2 + 2*i) & 0xff) << 8) | - (s->getChar(3 + 2*i) & 0xff); - } - } else { - titleLen = s->getLength(); - title = (Unicode *)gmallocn(titleLen, sizeof(Unicode)); - for (i = 0; i < titleLen; ++i) { - title[i] = pdfDocEncoding[s->getChar(i) & 0xff]; - } - } - } else { - titleLen = 0; - } - obj1.free(); - - if (!dict->lookup("Dest", &obj1)->isNull()) { - action = LinkAction::parseDest(&obj1); - } else { - obj1.free(); - if (!dict->lookup("A", &obj1)->isNull()) { - action = LinkAction::parseAction(&obj1); - } - } - obj1.free(); - - dict->lookupNF("First", &firstRef); - dict->lookupNF("Last", &lastRef); - dict->lookupNF("Next", &nextRef); - - startsOpen = gFalse; - if (dict->lookup("Count", &obj1)->isInt()) { - if (obj1.getInt() > 0) { - startsOpen = gTrue; - } - } - obj1.free(); -} - -OutlineItem::~OutlineItem() { - close(); - if (title) { - gfree(title); - } - if (action) { - delete action; - } - firstRef.free(); - lastRef.free(); - nextRef.free(); -} - -GList *OutlineItem::readItemList(Object *firstItemRef, Object *lastItemRef, - XRef *xrefA) { - GList *items; - OutlineItem *item; - Object obj; - Object *p; - - items = new GList(); - p = firstItemRef; - while (p->isRef()) { - if (!p->fetch(xrefA, &obj)->isDict()) { - obj.free(); - break; - } - item = new OutlineItem(obj.getDict(), xrefA); - obj.free(); - items->append(item); - if (p->getRef().num == lastItemRef->getRef().num && - p->getRef().gen == lastItemRef->getRef().gen) { - break; - } - p = &item->nextRef; - } - return items; -} - -void OutlineItem::open() { - if (!kids) { - kids = readItemList(&firstRef, &lastRef, xref); - } -} - -void OutlineItem::close() { - if (kids) { - deleteGList(kids, OutlineItem); - kids = NULL; - } -} diff --git a/pdftops/Outline.h b/pdftops/Outline.h deleted file mode 100644 index e83386221..000000000 --- a/pdftops/Outline.h +++ /dev/null @@ -1,76 +0,0 @@ -//======================================================================== -// -// Outline.h -// -// Copyright 2002-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef OUTLINE_H -#define OUTLINE_H - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "Object.h" -#include "CharTypes.h" - -class GString; -class GList; -class XRef; -class LinkAction; - -//------------------------------------------------------------------------ - -class Outline { -public: - - Outline(Object *outlineObj, XRef *xref); - ~Outline(); - - GList *getItems() { return items; } - -private: - - GList *items; // NULL if document has no outline - // [OutlineItem] -}; - -//------------------------------------------------------------------------ - -class OutlineItem { -public: - - OutlineItem(Dict *dict, XRef *xrefA); - ~OutlineItem(); - - static GList *readItemList(Object *firstItemRef, Object *lastItemRef, - XRef *xrefA); - - void open(); - void close(); - - Unicode *getTitle() { return title; } - int getTitleLength() { return titleLen; } - LinkAction *getAction() { return action; } - GBool isOpen() { return startsOpen; } - GBool hasKids() { return firstRef.isRef(); } - GList *getKids() { return kids; } - -private: - - XRef *xref; - Unicode *title; - int titleLen; - LinkAction *action; - Object firstRef; - Object lastRef; - Object nextRef; - GBool startsOpen; - GList *kids; // NULL unless this item is open [OutlineItem] -}; - -#endif diff --git a/pdftops/OutputDev.cxx b/pdftops/OutputDev.cxx deleted file mode 100644 index a68ca80a2..000000000 --- a/pdftops/OutputDev.cxx +++ /dev/null @@ -1,129 +0,0 @@ -//======================================================================== -// -// OutputDev.cc -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include <stddef.h> -#include "Object.h" -#include "Stream.h" -#include "GfxState.h" -#include "OutputDev.h" - -//------------------------------------------------------------------------ -// OutputDev -//------------------------------------------------------------------------ - -void OutputDev::setDefaultCTM(double *ctm) { - int i; - double det; - - for (i = 0; i < 6; ++i) { - defCTM[i] = ctm[i]; - } - det = 1 / (defCTM[0] * defCTM[3] - defCTM[1] * defCTM[2]); - defICTM[0] = defCTM[3] * det; - defICTM[1] = -defCTM[1] * det; - defICTM[2] = -defCTM[2] * det; - defICTM[3] = defCTM[0] * det; - defICTM[4] = (defCTM[2] * defCTM[5] - defCTM[3] * defCTM[4]) * det; - defICTM[5] = (defCTM[1] * defCTM[4] - defCTM[0] * defCTM[5]) * det; -} - -void OutputDev::cvtDevToUser(double dx, double dy, double *ux, double *uy) { - *ux = defICTM[0] * dx + defICTM[2] * dy + defICTM[4]; - *uy = defICTM[1] * dx + defICTM[3] * dy + defICTM[5]; -} - -void OutputDev::cvtUserToDev(double ux, double uy, int *dx, int *dy) { - *dx = (int)(defCTM[0] * ux + defCTM[2] * uy + defCTM[4] + 0.5); - *dy = (int)(defCTM[1] * ux + defCTM[3] * uy + defCTM[5] + 0.5); -} - -void OutputDev::updateAll(GfxState *state) { - updateLineDash(state); - updateFlatness(state); - updateLineJoin(state); - updateLineCap(state); - updateMiterLimit(state); - updateLineWidth(state); - updateFillColorSpace(state); - updateFillColor(state); - updateStrokeColorSpace(state); - updateStrokeColor(state); - updateBlendMode(state); - updateFillOpacity(state); - updateStrokeOpacity(state); - updateFillOverprint(state); - updateStrokeOverprint(state); - updateFont(state); -} - -GBool OutputDev::beginType3Char(GfxState *state, double x, double y, - double dx, double dy, - CharCode code, Unicode *u, int uLen) { - return gFalse; -} - -void OutputDev::drawImageMask(GfxState *state, Object *ref, 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(); - str->close(); - } -} - -void OutputDev::drawImage(GfxState *state, Object *ref, Stream *str, - int width, int height, GfxImageColorMap *colorMap, - int *maskColors, 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(); - str->close(); - } -} - -void OutputDev::drawMaskedImage(GfxState *state, Object *ref, Stream *str, - int width, int height, - GfxImageColorMap *colorMap, - Stream *maskStr, - int maskWidth, int maskHeight, - GBool maskInvert) { - drawImage(state, ref, str, width, height, colorMap, NULL, gFalse); -} - -void OutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str, - int width, int height, - GfxImageColorMap *colorMap, - Stream *maskStr, - int maskWidth, int maskHeight, - GfxImageColorMap *maskColorMap) { - drawImage(state, ref, str, width, height, colorMap, NULL, gFalse); -} - -#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 deleted file mode 100644 index a58c5fdd0..000000000 --- a/pdftops/OutputDev.h +++ /dev/null @@ -1,205 +0,0 @@ -//======================================================================== -// -// OutputDev.h -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef OUTPUTDEV_H -#define OUTPUTDEV_H - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "gtypes.h" -#include "CharTypes.h" - -class GString; -class GfxState; -class GfxColorSpace; -class GfxImageColorMap; -class GfxFunctionShading; -class GfxAxialShading; -class GfxRadialShading; -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; - - // Does this device use tilingPatternFill()? If this returns false, - // tiling pattern fills will be reduced to a series of other drawing - // operations. - virtual GBool useTilingPatternFill() { return gFalse; } - - // Does this device use functionShadedFill(), axialShadedFill(), and - // radialShadedFill()? If this returns false, these shaded fills - // will be reduced to a series of other drawing operations. - virtual GBool useShadedFills() { return gFalse; } - - // Does this device use beginType3Char/endType3Char? Otherwise, - // text in Type 3 fonts will be drawn with drawChar/drawString. - virtual GBool interpretType3Chars() = 0; - - // Does this device need non-text content? - virtual GBool needNonText() { return gTrue; } - - //----- initialization and control - - // Set default transform matrix. - virtual void setDefaultCTM(double *ctm); - - // Start a page. - virtual GBool startPage(int pageNum, GfxState *state) { return (gTrue); } - - // 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(double dx, double dy, double *ux, double *uy); - virtual void cvtUserToDev(double ux, double uy, int *dx, int *dy); - - double *getDefCTM() { return defCTM; } - double *getDefICTM() { return defICTM; } - - //----- 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 updateFillColorSpace(GfxState *state) {} - virtual void updateStrokeColorSpace(GfxState *state) {} - virtual void updateFillColor(GfxState *state) {} - virtual void updateStrokeColor(GfxState *state) {} - virtual void updateBlendMode(GfxState *state) {} - virtual void updateFillOpacity(GfxState *state) {} - virtual void updateStrokeOpacity(GfxState *state) {} - virtual void updateFillOverprint(GfxState *state) {} - virtual void updateStrokeOverprint(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) {} - virtual void tilingPatternFill(GfxState *state, Object *str, - int paintType, Dict *resDict, - double *mat, double *bbox, - int x0, int y0, int x1, int y1, - double xStep, double yStep) {} - virtual void functionShadedFill(GfxState *state, - GfxFunctionShading *shading) {} - virtual void axialShadedFill(GfxState *state, GfxAxialShading *shading) {} - virtual void radialShadedFill(GfxState *state, GfxRadialShading *shading) {} - - //----- path clipping - virtual void clip(GfxState *state) {} - virtual void eoClip(GfxState *state) {} - - //----- text drawing - virtual void beginStringOp(GfxState *state) {} - virtual void endStringOp(GfxState *state) {} - 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, - double originX, double originY, - CharCode code, int nBytes, Unicode *u, int uLen) {} - virtual void drawString(GfxState *state, GString *s) {} - virtual GBool beginType3Char(GfxState *state, double x, double y, - double dx, double dy, - CharCode code, Unicode *u, int uLen); - virtual void endType3Char(GfxState *state) {} - virtual void endTextObject(GfxState *state) {} - - //----- image drawing - virtual void drawImageMask(GfxState *state, Object *ref, Stream *str, - int width, int height, GBool invert, - GBool inlineImg); - virtual void drawImage(GfxState *state, Object *ref, Stream *str, - int width, int height, GfxImageColorMap *colorMap, - int *maskColors, GBool inlineImg); - virtual void drawMaskedImage(GfxState *state, Object *ref, Stream *str, - int width, int height, - GfxImageColorMap *colorMap, - Stream *maskStr, int maskWidth, int maskHeight, - GBool maskInvert); - virtual void drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str, - int width, int height, - GfxImageColorMap *colorMap, - Stream *maskStr, - int maskWidth, int maskHeight, - GfxImageColorMap *maskColorMap); - -#if OPI_SUPPORT - //----- OPI functions - virtual void opiBegin(GfxState *state, Dict *opiDict); - virtual void opiEnd(GfxState *state, Dict *opiDict); -#endif - - //----- Type 3 font operators - virtual void type3D0(GfxState *state, double wx, double wy) {} - virtual void type3D1(GfxState *state, double wx, double wy, - double llx, double lly, double urx, double ury) {} - - //----- PostScript XObjects - virtual void psXObject(Stream *psStream, Stream *level1Stream) {} - -private: - - double defCTM[6]; // default coordinate transform matrix - double defICTM[6]; // inverse of default CTM -}; - -#endif diff --git a/pdftops/PDFDoc.cxx b/pdftops/PDFDoc.cxx deleted file mode 100644 index 70e36fe0a..000000000 --- a/pdftops/PDFDoc.cxx +++ /dev/null @@ -1,431 +0,0 @@ -//======================================================================== -// -// PDFDoc.cc -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include <stdio.h> -#include <stdlib.h> -#include <stddef.h> -#include <string.h> -#ifdef WIN32 -# include <windows.h> -#endif -#include "GString.h" -#include "config.h" -#include "GlobalParams.h" -#include "Page.h" -#include "Catalog.h" -#include "Stream.h" -#include "XRef.h" -#include "Link.h" -#include "OutputDev.h" -#include "Error.h" -#include "ErrorCodes.h" -#include "Lexer.h" -#include "Parser.h" -#include "SecurityHandler.h" -#ifndef DISABLE_OUTLINE -#include "Outline.h" -#endif -#include "PDFDoc.h" - -//------------------------------------------------------------------------ - -#define headerSearchSize 1024 // read this many bytes at beginning of - // file to look for '%PDF' - -//------------------------------------------------------------------------ -// PDFDoc -//------------------------------------------------------------------------ - -PDFDoc::PDFDoc(GString *fileNameA, GString *ownerPassword, - GString *userPassword, void *guiDataA) { - Object obj; - GString *fileName1, *fileName2; - - ok = gFalse; - errCode = errNone; - - guiData = guiDataA; - - file = NULL; - str = NULL; - xref = NULL; - catalog = NULL; - links = NULL; -#ifndef DISABLE_OUTLINE - outline = NULL; -#endif - - fileName = fileNameA; - fileName1 = fileName; - - - // try to open file - fileName2 = NULL; -#ifdef VMS - if (!(file = fopen(fileName1->getCString(), "rb", "ctx=stm"))) { - error(-1, "Couldn't open file '%s'", fileName1->getCString()); - errCode = errOpenFile; - return; - } -#else - if (!(file = fopen(fileName1->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; - errCode = errOpenFile; - return; - } - } - delete fileName2; - } -#endif - - // create stream - obj.initNull(); - str = new FileStream(file, 0, gFalse, 0, &obj); - - ok = setup(ownerPassword, userPassword); -} - -#ifdef WIN32 -PDFDoc::PDFDoc(wchar_t *fileNameA, int fileNameLen, GString *ownerPassword, - GString *userPassword, void *guiDataA) { - OSVERSIONINFO version; - wchar_t fileName2[_MAX_PATH + 1]; - Object obj; - int i; - - ok = gFalse; - errCode = errNone; - - guiData = guiDataA; - - file = NULL; - str = NULL; - xref = NULL; - catalog = NULL; - links = NULL; -#ifndef DISABLE_OUTLINE - outline = NULL; -#endif - - //~ file name should be stored in Unicode (?) - fileName = new GString(); - for (i = 0; i < fileNameLen; ++i) { - fileName->append((char)fileNameA[i]); - } - - // zero-terminate the file name string - for (i = 0; i < fileNameLen && i < _MAX_PATH; ++i) { - fileName2[i] = fileNameA[i]; - } - fileName2[i] = 0; - - // try to open file - // NB: _wfopen is only available in NT - version.dwOSVersionInfoSize = sizeof(version); - GetVersionEx(&version); - if (version.dwPlatformId == VER_PLATFORM_WIN32_NT) { - file = _wfopen(fileName2, L"rb"); - } else { - file = fopen(fileName->getCString(), "rb"); - } - if (!file) { - error(-1, "Couldn't open file '%s'", fileName->getCString()); - errCode = errOpenFile; - return; - } - - // create stream - obj.initNull(); - str = new FileStream(file, 0, gFalse, 0, &obj); - - ok = setup(ownerPassword, userPassword); -} -#endif - -PDFDoc::PDFDoc(BaseStream *strA, GString *ownerPassword, - GString *userPassword, void *guiDataA) { - ok = gFalse; - errCode = errNone; - guiData = guiDataA; - fileName = NULL; - file = NULL; - str = strA; - xref = NULL; - catalog = NULL; - links = NULL; -#ifndef DISABLE_OUTLINE - outline = NULL; -#endif - ok = setup(ownerPassword, userPassword); -} - -GBool PDFDoc::setup(GString *ownerPassword, GString *userPassword) { - str->reset(); - - // check header - checkHeader(); - - // read xref table - xref = new XRef(str); - if (!xref->isOk()) { - error(-1, "Couldn't read xref table"); - errCode = xref->getErrorCode(); - return gFalse; - } - - // check for encryption - if (!checkEncryption(ownerPassword, userPassword)) { - errCode = errEncrypted; - return gFalse; - } - - // read catalog - catalog = new Catalog(xref); - if (!catalog->isOk()) { - error(-1, "Couldn't read page catalog"); - errCode = errBadCatalog; - return gFalse; - } - -#ifndef DISABLE_OUTLINE - // read outline - outline = new Outline(catalog->getOutline(), xref); -#endif - - // done - return gTrue; -} - -PDFDoc::~PDFDoc() { -#ifndef DISABLE_OUTLINE - if (outline) { - delete outline; - } -#endif - 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); - if (!(p = strtok(&hdrBuf[i+5], " \t\n\r"))) { - error(-1, "May not be a PDF file (continuing anyway)"); - return; - } - 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); - } -} - -GBool PDFDoc::checkEncryption(GString *ownerPassword, GString *userPassword) { - Object encrypt; - GBool encrypted; - SecurityHandler *secHdlr; - GBool ret; - - xref->getTrailerDict()->dictLookup("Encrypt", &encrypt); - if ((encrypted = encrypt.isDict())) { - if ((secHdlr = SecurityHandler::make(this, &encrypt))) { - if (secHdlr->checkEncryption(ownerPassword, userPassword)) { - // authorization succeeded - xref->setEncryption(secHdlr->getPermissionFlags(), - secHdlr->getOwnerPasswordOk(), - secHdlr->getFileKey(), - secHdlr->getFileKeyLength(), - secHdlr->getEncVersion()); - ret = gTrue; - } else { - // authorization failed - ret = gFalse; - } - delete secHdlr; - } else { - // couldn't find the matching security handler - ret = gFalse; - } - } else { - // document is not encrypted - ret = gTrue; - } - encrypt.free(); - return ret; -} - -void PDFDoc::displayPage(OutputDev *out, int page, double hDPI, double vDPI, - int rotate, GBool useMediaBox, GBool crop, - GBool doLinks, - GBool (*abortCheckCbk)(void *data), - void *abortCheckCbkData) { - Page *p; - - if (globalParams->getPrintCommands()) { - printf("***** page %d *****\n", page); - } - p = catalog->getPage(page); - if (doLinks) { - if (links) { - delete links; - } - getLinks(p); - p->display(out, hDPI, vDPI, rotate, useMediaBox, crop, links, catalog, - abortCheckCbk, abortCheckCbkData); - } else { - p->display(out, hDPI, vDPI, rotate, useMediaBox, crop, NULL, catalog, - abortCheckCbk, abortCheckCbkData); - } -} - -void PDFDoc::displayPages(OutputDev *out, int firstPage, int lastPage, - double hDPI, double vDPI, int rotate, - GBool useMediaBox, GBool crop, GBool doLinks, - GBool (*abortCheckCbk)(void *data), - void *abortCheckCbkData) { - int page; - - for (page = firstPage; page <= lastPage; ++page) { - displayPage(out, page, hDPI, vDPI, rotate, useMediaBox, crop, doLinks, - abortCheckCbk, abortCheckCbkData); - } -} - -void PDFDoc::displayPageSlice(OutputDev *out, int page, - double hDPI, double vDPI, int rotate, - GBool useMediaBox, GBool crop, GBool doLinks, - int sliceX, int sliceY, int sliceW, int sliceH, - GBool (*abortCheckCbk)(void *data), - void *abortCheckCbkData) { - Page *p; - - p = catalog->getPage(page); - if (doLinks) { - if (links) { - delete links; - } - getLinks(p); - p->displaySlice(out, hDPI, vDPI, rotate, useMediaBox, crop, - sliceX, sliceY, sliceW, sliceH, - links, catalog, abortCheckCbk, abortCheckCbkData); - } else { - p->displaySlice(out, hDPI, vDPI, rotate, useMediaBox, crop, - sliceX, sliceY, sliceW, sliceH, - NULL, catalog, abortCheckCbk, abortCheckCbkData); - } -} - -Links *PDFDoc::takeLinks() { - Links *ret; - - ret = links; - links = NULL; - return ret; -} - -GBool PDFDoc::isLinearized() { - Parser *parser; - Object obj1, obj2, obj3, obj4, obj5; - GBool lin; - - lin = gFalse; - obj1.initNull(); - parser = new Parser(xref, - new Lexer(xref, - str->makeSubStream(str->getStart(), gFalse, 0, &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); - } - str->close(); - 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 deleted file mode 100644 index 0496db3ac..000000000 --- a/pdftops/PDFDoc.h +++ /dev/null @@ -1,182 +0,0 @@ -//======================================================================== -// -// PDFDoc.h -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef PDFDOC_H -#define PDFDOC_H - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include <stdio.h> -#include "XRef.h" -#include "Catalog.h" -#include "Page.h" - -class GString; -class BaseStream; -class OutputDev; -class Links; -class LinkAction; -class LinkDest; -class Outline; - -//------------------------------------------------------------------------ -// PDFDoc -//------------------------------------------------------------------------ - -class PDFDoc { -public: - - PDFDoc(GString *fileNameA, GString *ownerPassword = NULL, - GString *userPassword = NULL, void *guiDataA = NULL); -#ifdef WIN32 - PDFDoc(wchar_t *fileNameA, int fileNameLen, GString *ownerPassword = NULL, - GString *userPassword = NULL, void *guiDataA = NULL); -#endif - PDFDoc(BaseStream *strA, GString *ownerPassword = NULL, - GString *userPassword = NULL, void *guiDataA = NULL); - ~PDFDoc(); - - // Was PDF document successfully opened? - GBool isOk() { return ok; } - - // Get the error code (if isOk() returns false). - int getErrorCode() { return errCode; } - - // Get file name. - GString *getFileName() { return fileName; } - - // Get the xref table. - XRef *getXRef() { return xref; } - - // Get catalog. - Catalog *getCatalog() { return catalog; } - - // Get base stream. - BaseStream *getBaseStream() { return str; } - - // Get page parameters. - double getPageMediaWidth(int page) - { return catalog->getPage(page)->getMediaWidth(); } - double getPageMediaHeight(int page) - { return catalog->getPage(page)->getMediaHeight(); } - double getPageCropWidth(int page) - { return catalog->getPage(page)->getCropWidth(); } - double getPageCropHeight(int page) - { return catalog->getPage(page)->getCropHeight(); } - int getPageRotate(int page) - { return catalog->getPage(page)->getRotate(); } - - // Get number of pages. - int getNumPages() { return catalog->getNumPages(); } - - // Return the contents of the metadata stream, or NULL if there is - // no metadata. - GString *readMetadata() { return catalog->readMetadata(); } - - // Return the structure tree root object. - Object *getStructTreeRoot() { return catalog->getStructTreeRoot(); } - - // Display a page. - void displayPage(OutputDev *out, int page, double hDPI, double vDPI, - int rotate, GBool useMediaBox, GBool crop, - GBool doLinks, - GBool (*abortCheckCbk)(void *data) = NULL, - void *abortCheckCbkData = NULL); - - // Display a range of pages. - void displayPages(OutputDev *out, int firstPage, int lastPage, - double hDPI, double vDPI, int rotate, - GBool useMediaBox, GBool crop, GBool doLinks, - GBool (*abortCheckCbk)(void *data) = NULL, - void *abortCheckCbkData = NULL); - - // Display part of a page. - void displayPageSlice(OutputDev *out, int page, - double hDPI, double vDPI, int rotate, - GBool useMediaBox, GBool crop, GBool doLinks, - int sliceX, int sliceY, int sliceW, int sliceH, - GBool (*abortCheckCbk)(void *data) = NULL, - void *abortCheckCbkData = NULL); - - // 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); } - - // Returns the links for the current page, transferring ownership to - // the caller. - Links *takeLinks(); - - // Find a named destination. Returns the link destination, or - // NULL if <name> is not a destination. - LinkDest *findDest(GString *name) - { return catalog->findDest(name); } - -#ifndef DISABLE_OUTLINE - // Return the outline object. - Outline *getOutline() { return outline; } -#endif - - // Is the file encrypted? - GBool isEncrypted() { return xref->isEncrypted(); } - - // Check various permissions. - GBool okToPrint(GBool ignoreOwnerPW = gFalse) - { return xref->okToPrint(ignoreOwnerPW); } - GBool okToChange(GBool ignoreOwnerPW = gFalse) - { return xref->okToChange(ignoreOwnerPW); } - GBool okToCopy(GBool ignoreOwnerPW = gFalse) - { return xref->okToCopy(ignoreOwnerPW); } - GBool okToAddNotes(GBool ignoreOwnerPW = gFalse) - { return xref->okToAddNotes(ignoreOwnerPW); } - - // Is this document linearized? - GBool isLinearized(); - - // Return the document's Info dictionary (if any). - Object *getDocInfo(Object *obj) { return xref->getDocInfo(obj); } - Object *getDocInfoNF(Object *obj) { return xref->getDocInfoNF(obj); } - - // Return the PDF version specified by the file. - double getPDFVersion() { return pdfVersion; } - - // Save this file with another name. - GBool saveAs(GString *name); - - // Return a pointer to the GUI (XPDFCore or WinPDFCore object). - void *getGUIData() { return guiData; } - - -private: - - GBool setup(GString *ownerPassword, GString *userPassword); - void checkHeader(); - GBool checkEncryption(GString *ownerPassword, GString *userPassword); - void getLinks(Page *page); - - GString *fileName; - FILE *file; - BaseStream *str; - void *guiData; - double pdfVersion; - XRef *xref; - Catalog *catalog; - Links *links; -#ifndef DISABLE_OUTLINE - Outline *outline; -#endif - - - GBool ok; - int errCode; -}; - -#endif diff --git a/pdftops/PDFDocEncoding.cxx b/pdftops/PDFDocEncoding.cxx deleted file mode 100644 index 89dc38283..000000000 --- a/pdftops/PDFDocEncoding.cxx +++ /dev/null @@ -1,44 +0,0 @@ -//======================================================================== -// -// PDFDocEncoding.h -// -// Copyright 2002-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include "PDFDocEncoding.h" - -Unicode pdfDocEncoding[256] = { - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 00 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 10 - 0x02d8, 0x02c7, 0x02c6, 0x02d9, 0x02dd, 0x02db, 0x02da, 0x02dc, - 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, // 20 - 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, // 30 - 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, - 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, // 40 - 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, - 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, // 50 - 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, - 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, // 60 - 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, - 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, // 70 - 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x0000, - 0x2022, 0x2020, 0x2021, 0x2026, 0x2014, 0x2013, 0x0192, 0x2044, // 80 - 0x2039, 0x203a, 0x2212, 0x2030, 0x201e, 0x201c, 0x201d, 0x2018, - 0x2019, 0x201a, 0x2122, 0xfb01, 0xfb02, 0x0141, 0x0152, 0x0160, // 90 - 0x0178, 0x017d, 0x0131, 0x0142, 0x0153, 0x0161, 0x017e, 0x0000, - 0x20ac, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, // a0 - 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x0000, 0x00ae, 0x00af, - 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, // b0 - 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf, - 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, // c0 - 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, - 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, // d0 - 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df, - 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, // e0 - 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, - 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, // f0 - 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff -}; diff --git a/pdftops/PDFDocEncoding.h b/pdftops/PDFDocEncoding.h deleted file mode 100644 index 3259d3e10..000000000 --- a/pdftops/PDFDocEncoding.h +++ /dev/null @@ -1,16 +0,0 @@ -//======================================================================== -// -// PDFDocEncoding.h -// -// Copyright 2002-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef PDFDOCENCODING_H -#define PDFDOCENCODING_H - -#include "CharTypes.h" - -extern Unicode pdfDocEncoding[256]; - -#endif diff --git a/pdftops/PSOutputDev.cxx b/pdftops/PSOutputDev.cxx deleted file mode 100644 index 6c8abf095..000000000 --- a/pdftops/PSOutputDev.cxx +++ /dev/null @@ -1,5040 +0,0 @@ -//======================================================================== -// -// PSOutputDev.cc -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include <stdio.h> -#include <stdlib.h> -#include <ctype.h> -#include <stddef.h> -#include <stdarg.h> -#include <signal.h> -#include <math.h> -#include "GString.h" -#include "GList.h" -#include "config.h" -#include "GlobalParams.h" -#include "Object.h" -#include "Error.h" -#include "Function.h" -#include "Gfx.h" -#include "GfxState.h" -#include "GfxFont.h" -#include "UnicodeMap.h" -#include "FoFiType1C.h" -#include "FoFiTrueType.h" -#include "Catalog.h" -#include "Page.h" -#include "Stream.h" -#include "Annot.h" -#include "XRef.h" -#include "PSOutputDev.h" - -#ifdef MACOS -// needed for setting type/creator of MacOS files -#include "ICSupport.h" -#endif - -//------------------------------------------------------------------------ -// PostScript prolog and setup -//------------------------------------------------------------------------ - -// The '~' escapes mark prolog code that is emitted only in certain -// levels: -// -// ~[123][sn] -// ^ ^----- s=psLevel*Sep, n=psLevel* -// +----- 1=psLevel1*, 2=psLevel2*, 3=psLevel3* - -static char *prolog[] = { - "/xpdf 75 dict def xpdf begin", - "% PDF special state", - "/pdfDictSize 15 def", - "~1sn", - "/pdfStates 64 array def", - " 0 1 63 {", - " pdfStates exch pdfDictSize dict", - " dup /pdfStateIdx 3 index put", - " put", - " } for", - "~123sn", - "/pdfSetup {", - " 3 1 roll 2 array astore", - " /setpagedevice where {", - " pop 3 dict begin", - " /PageSize exch def", - " /ImagingBBox null def", - " /Policies 1 dict dup begin /PageSize 3 def end def", - " { /Duplex true def } if", - " currentdict end setpagedevice", - " } {", - " pop pop", - " } ifelse", - "} def", - "~1sn", - "/pdfOpNames [", - " /pdfFill /pdfStroke /pdfLastFill /pdfLastStroke", - " /pdfTextMat /pdfFontSize /pdfCharSpacing /pdfTextRender", - " /pdfTextRise /pdfWordSpacing /pdfHorizScaling /pdfTextClipPath", - "] def", - "~123sn", - "/pdfStartPage {", - "~1sn", - " pdfStates 0 get begin", - "~23sn", - " pdfDictSize dict begin", - "~23n", - " /pdfFillCS [] def", - " /pdfFillXform {} def", - " /pdfStrokeCS [] def", - " /pdfStrokeXform {} def", - "~1n", - " /pdfFill 0 def", - " /pdfStroke 0 def", - "~1s", - " /pdfFill [0 0 0 1] def", - " /pdfStroke [0 0 0 1] def", - "~23sn", - " /pdfFill [0] def", - " /pdfStroke [0] def", - " /pdfFillOP false def", - " /pdfStrokeOP false def", - "~123sn", - " /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", - " /pdfTextClipPath [] def", - "} def", - "/pdfEndPage { end } def", - "~23s", - "% separation convention operators", - "/findcmykcustomcolor where {", - " pop", - "}{", - " /findcmykcustomcolor { 5 array astore } def", - "} ifelse", - "/setcustomcolor where {", - " pop", - "}{", - " /setcustomcolor {", - " exch", - " [ exch /Separation exch dup 4 get exch /DeviceCMYK exch", - " 0 4 getinterval cvx", - " [ exch /dup load exch { mul exch dup } /forall load", - " /pop load dup ] cvx", - " ] setcolorspace setcolor", - " } def", - "} ifelse", - "/customcolorimage where {", - " pop", - "}{", - " /customcolorimage {", - " gsave", - " [ exch /Separation exch dup 4 get exch /DeviceCMYK exch", - " 0 4 getinterval", - " [ exch /dup load exch { mul exch dup } /forall load", - " /pop load dup ] cvx", - " ] setcolorspace", - " 10 dict begin", - " /ImageType 1 def", - " /DataSource exch def", - " /ImageMatrix exch def", - " /BitsPerComponent exch def", - " /Height exch def", - " /Width exch def", - " /Decode [1 0] def", - " currentdict end", - " image", - " grestore", - " } def", - "} ifelse", - "~123sn", - "% PDF color state", - "~1n", - "/g { dup /pdfFill exch def setgray", - " /pdfLastFill true def /pdfLastStroke false def } def", - "/G { dup /pdfStroke exch def setgray", - " /pdfLastStroke true def /pdfLastFill false def } def", - "/fCol {", - " pdfLastFill not {", - " pdfFill setgray", - " /pdfLastFill true def /pdfLastStroke false def", - " } if", - "} def", - "/sCol {", - " pdfLastStroke not {", - " pdfStroke setgray", - " /pdfLastStroke true def /pdfLastFill false def", - " } if", - "} def", - "~1s", - "/k { 4 copy 4 array astore /pdfFill exch def setcmykcolor", - " /pdfLastFill true def /pdfLastStroke false def } def", - "/K { 4 copy 4 array astore /pdfStroke exch def setcmykcolor", - " /pdfLastStroke true def /pdfLastFill false def } def", - "/fCol {", - " pdfLastFill not {", - " pdfFill aload pop setcmykcolor", - " /pdfLastFill true def /pdfLastStroke false def", - " } if", - "} def", - "/sCol {", - " pdfLastStroke not {", - " pdfStroke aload pop setcmykcolor", - " /pdfLastStroke true def /pdfLastFill false def", - " } if", - "} def", - "~23n", - "/cs { /pdfFillXform exch def dup /pdfFillCS exch def", - " setcolorspace } def", - "/CS { /pdfStrokeXform exch def dup /pdfStrokeCS exch def", - " setcolorspace } def", - "/sc { pdfLastFill not { pdfFillCS setcolorspace } if", - " dup /pdfFill exch def aload pop pdfFillXform setcolor", - " /pdfLastFill true def /pdfLastStroke false def } def", - "/SC { pdfLastStroke not { pdfStrokeCS setcolorspace } if", - " dup /pdfStroke exch def aload pop pdfStrokeXform setcolor", - " /pdfLastStroke true def /pdfLastFill false def } def", - "/op { /pdfFillOP exch def", - " pdfLastFill { pdfFillOP setoverprint } if } def", - "/OP { /pdfStrokeOP exch def", - " pdfLastStroke { pdfStrokeOP setoverprint } if } def", - "/fCol {", - " pdfLastFill not {", - " pdfFillCS setcolorspace", - " pdfFill aload pop pdfFillXform setcolor", - " pdfFillOP setoverprint", - " /pdfLastFill true def /pdfLastStroke false def", - " } if", - "} def", - "/sCol {", - " pdfLastStroke not {", - " pdfStrokeCS setcolorspace", - " pdfStroke aload pop pdfStrokeXform setcolor", - " pdfStrokeOP setoverprint", - " /pdfLastStroke true def /pdfLastFill false def", - " } if", - "} def", - "~23s", - "/k { 4 copy 4 array astore /pdfFill exch def setcmykcolor", - " /pdfLastFill true def /pdfLastStroke false def } def", - "/K { 4 copy 4 array astore /pdfStroke exch def setcmykcolor", - " /pdfLastStroke true def /pdfLastFill false def } def", - "/ck { 6 copy 6 array astore /pdfFill exch def", - " findcmykcustomcolor exch setcustomcolor", - " /pdfLastFill true def /pdfLastStroke false def } def", - "/CK { 6 copy 6 array astore /pdfStroke exch def", - " findcmykcustomcolor exch setcustomcolor", - " /pdfLastStroke true def /pdfLastFill false def } def", - "/op { /pdfFillOP exch def", - " pdfLastFill { pdfFillOP setoverprint } if } def", - "/OP { /pdfStrokeOP exch def", - " pdfLastStroke { pdfStrokeOP setoverprint } if } def", - "/fCol {", - " pdfLastFill not {", - " pdfFill aload length 4 eq {", - " setcmykcolor", - " }{", - " findcmykcustomcolor exch setcustomcolor", - " } ifelse", - " pdfFillOP setoverprint", - " /pdfLastFill true def /pdfLastStroke false def", - " } if", - "} def", - "/sCol {", - " pdfLastStroke not {", - " pdfStroke aload length 4 eq {", - " setcmykcolor", - " }{", - " findcmykcustomcolor exch setcustomcolor", - " } ifelse", - " pdfStrokeOP setoverprint", - " /pdfLastStroke true def /pdfLastFill false def", - " } if", - "} def", - "~123sn", - "% 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 {", - " exch findfont", - " dup length dict begin", - " { 1 index /FID ne { def } { pop pop } ifelse } forall", - " /WMode exch def", - " currentdict", - " end", - " definefont pop", - "} def", - "~3sn", - "/pdfMakeFont16L3 {", - " 1 index /CIDFont resourcestatus {", - " pop pop 1 index /CIDFont findresource /CIDFontType known", - " } {", - " false", - " } ifelse", - " {", - " 0 eq { /Identity-H } { /Identity-V } ifelse", - " exch 1 array astore composefont pop", - " } {", - " pdfMakeFont16", - " } ifelse", - "} def", - "~123sn", - "% graphics state operators", - "~1sn", - "/q {", - " gsave", - " pdfOpNames length 1 sub -1 0 { pdfOpNames exch get load } for", - " pdfStates pdfStateIdx 1 add get begin", - " pdfOpNames { exch def } forall", - "} def", - "/Q { end grestore } def", - "~23sn", - "/q { gsave pdfDictSize dict begin } def", - "/Q {", - " end grestore", - " /pdfLastFill where {", - " pop", - " pdfLastFill {", - " pdfFillOP setoverprint", - " } {", - " pdfStrokeOP setoverprint", - " } ifelse", - " } if", - "} def", - "~123sn", - "/cm { concat } def", - "/d { setdash } def", - "/i { setflat } def", - "/j { setlinejoin } def", - "/J { setlinecap } def", - "/M { setmiterlimit } def", - "/w { setlinewidth } 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", - "/Sf { fCol 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", - "/cshow where {", - " pop", - " /cshow2 {", - " dup {", - " pop pop", - " 1 string dup 0 3 index put 3 index exec", - " } exch cshow", - " pop pop", - " } def", - "}{", - " /cshow2 {", - " currentfont /FontType get 0 eq {", - " 0 2 2 index length 1 sub {", - " 2 copy get exch 1 add 2 index exch get", - " 2 copy exch 256 mul add", - " 2 string dup 0 6 5 roll put dup 1 5 4 roll put", - " 3 index exec", - " } for", - " } {", - " dup {", - " 1 string dup 0 3 index put 3 index exec", - " } forall", - " } ifelse", - " pop pop", - " } def", - "} ifelse", - "/awcp {", // awidthcharpath - " exch {", - " false charpath", - " 5 index 5 index rmoveto", - " 6 index eq { 7 index 7 index rmoveto } if", - " } exch cshow2", - " 6 {pop} repeat", - "} def", - "/Tj {", - " fCol", // because stringwidth has to draw Type 3 chars - " 1 index stringwidth pdfTextMat idtransform pop", - " sub 1 index length dup 0 ne { div } { pop pop 0 } ifelse", - " pdfWordSpacing pdfHorizScaling mul 0 pdfTextMat dtransform 32", - " 4 3 roll pdfCharSpacing pdfHorizScaling mul add 0", - " pdfTextMat dtransform", - " 6 5 roll Tj1", - "} def", - "/Tj16 {", - " fCol", // because stringwidth has to draw Type 3 chars - " 2 index stringwidth pdfTextMat idtransform pop", - " sub exch div", - " pdfWordSpacing pdfHorizScaling mul 0 pdfTextMat dtransform 32", - " 4 3 roll pdfCharSpacing pdfHorizScaling mul add 0", - " pdfTextMat dtransform", - " 6 5 roll Tj1", - "} def", - "/Tj16V {", - " fCol", // because stringwidth has to draw Type 3 chars - " 2 index stringwidth pdfTextMat idtransform exch pop", - " sub exch div", - " 0 pdfWordSpacing pdfTextMat dtransform 32", - " 4 3 roll pdfCharSpacing add 0 exch", - " pdfTextMat dtransform", - " 6 5 roll Tj1", - "} def", - "/Tj1 {", - " 0 pdfTextRise pdfTextMat dtransform rmoveto", - " currentpoint 8 2 roll", - " pdfTextRender 1 and 0 eq {", - " 6 copy awidthshow", - " } if", - " pdfTextRender 3 and dup 1 eq exch 2 eq or {", - " 7 index 7 index moveto", - " 6 copy", - " currentfont /FontType get 3 eq { fCol } { sCol } ifelse", - " false awcp currentpoint stroke moveto", - " } if", - " pdfTextRender 4 and 0 ne {", - " 8 6 roll moveto", - " false awcp", - " /pdfTextClipPath [ pdfTextClipPath aload pop", - " {/moveto cvx}", - " {/lineto cvx}", - " {/curveto cvx}", - " {/closepath cvx}", - " pathforall ] def", - " currentpoint newpath moveto", - " } {", - " 8 {pop} repeat", - " } ifelse", - " 0 pdfTextRise neg pdfTextMat dtransform rmoveto", - "} def", - "/TJm { pdfFontSize 0.001 mul mul neg 0", - " pdfTextMat dtransform rmoveto } def", - "/TJmV { pdfFontSize 0.001 mul mul neg 0 exch", - " pdfTextMat dtransform rmoveto } def", - "/Tclip { pdfTextClipPath cvx exec clip newpath", - " /pdfTextClipPath [] def } def", - "~1ns", - "% Level 1 image operators", - "~1n", - "/pdfIm1 {", - " /pdfImBuf1 4 index string def", - " { currentfile pdfImBuf1 readhexstring pop } image", - "} def", - "~1s", - "/pdfIm1Sep {", - " /pdfImBuf1 4 index string def", - " /pdfImBuf2 4 index string def", - " /pdfImBuf3 4 index string def", - " /pdfImBuf4 4 index string def", - " { currentfile pdfImBuf1 readhexstring pop }", - " { currentfile pdfImBuf2 readhexstring pop }", - " { currentfile pdfImBuf3 readhexstring pop }", - " { currentfile pdfImBuf4 readhexstring pop }", - " true 4 colorimage", - "} def", - "~1ns", - "/pdfImM1 {", - " fCol /pdfImBuf1 4 index 7 add 8 idiv string def", - " { currentfile pdfImBuf1 readhexstring pop } imagemask", - "} def", - "/pdfImM1a {", - " { 2 copy get exch 1 add exch } imagemask", - " pop pop", - "} def", - "~23sn", - "% Level 2 image operators", - "/pdfImBuf 100 string def", - "/pdfIm {", - " image", - " { currentfile pdfImBuf readline", - " not { pop exit } if", - " (%-EOD-) eq { exit } if } loop", - "} def", - "~23s", - "/pdfImSep {", - " findcmykcustomcolor exch", - " dup /Width get /pdfImBuf1 exch string def", - " dup /Decode get aload pop 1 index sub /pdfImDecodeRange exch def", - " /pdfImDecodeLow exch def", - " begin Width Height BitsPerComponent ImageMatrix DataSource end", - " /pdfImData exch def", - " { pdfImData pdfImBuf1 readstring pop", - " 0 1 2 index length 1 sub {", - " 1 index exch 2 copy get", - " pdfImDecodeRange mul 255 div pdfImDecodeLow add round cvi", - " 255 exch sub put", - " } for }", - " 6 5 roll customcolorimage", - " { currentfile pdfImBuf readline", - " not { pop exit } if", - " (%-EOD-) eq { exit } if } loop", - "} def", - "~23sn", - "/pdfImM {", - " fCol imagemask", - " { currentfile pdfImBuf readline", - " not { pop exit } if", - " (%-EOD-) eq { exit } if } loop", - "} def", - "/pdfImClip {", - " gsave", - " 0 2 4 index length 1 sub {", - " dup 4 index exch 2 copy", - " get 5 index div put", - " 1 add 3 index exch 2 copy", - " get 3 index div put", - " } for", - " pop pop rectclip", - "} def", - "/pdfImClipEnd { grestore } def", - "~23n", - "% shading operators", - "/colordelta {", - " false 0 1 3 index length 1 sub {", - " dup 4 index exch get 3 index 3 2 roll get sub abs 0.004 gt {", - " pop true", - " } if", - " } for", - " exch pop exch pop", - "} def", - "/funcCol { func n array astore } def", - "/funcSH {", - " dup 0 eq {", - " true", - " } {", - " dup 6 eq {", - " false", - " } {", - " 4 index 4 index funcCol dup", - " 6 index 4 index funcCol dup", - " 3 1 roll colordelta 3 1 roll", - " 5 index 5 index funcCol dup", - " 3 1 roll colordelta 3 1 roll", - " 6 index 8 index funcCol dup", - " 3 1 roll colordelta 3 1 roll", - " colordelta or or or", - " } ifelse", - " } ifelse", - " {", - " 1 add", - " 4 index 3 index add 0.5 mul exch 4 index 3 index add 0.5 mul exch", - " 6 index 6 index 4 index 4 index 4 index funcSH", - " 2 index 6 index 6 index 4 index 4 index funcSH", - " 6 index 2 index 4 index 6 index 4 index funcSH", - " 5 3 roll 3 2 roll funcSH pop pop", - " } {", - " pop 3 index 2 index add 0.5 mul 3 index 2 index add 0.5 mul", - " funcCol sc", - " dup 4 index exch mat transform m", - " 3 index 3 index mat transform l", - " 1 index 3 index mat transform l", - " mat transform l pop pop h f*", - " } ifelse", - "} def", - "/axialCol {", - " dup 0 lt {", - " pop t0", - " } {", - " dup 1 gt {", - " pop t1", - " } {", - " dt mul t0 add", - " } ifelse", - " } ifelse", - " func n array astore", - "} def", - "/axialSH {", - " dup 0 eq {", - " true", - " } {", - " dup 8 eq {", - " false", - " } {", - " 2 index axialCol 2 index axialCol colordelta", - " } ifelse", - " } ifelse", - " {", - " 1 add 3 1 roll 2 copy add 0.5 mul", - " dup 4 3 roll exch 4 index axialSH", - " exch 3 2 roll axialSH", - " } {", - " pop 2 copy add 0.5 mul axialCol sc", - " exch dup dx mul x0 add exch dy mul y0 add", - " 3 2 roll dup dx mul x0 add exch dy mul y0 add", - " dx abs dy abs ge {", - " 2 copy yMin sub dy mul dx div add yMin m", - " yMax sub dy mul dx div add yMax l", - " 2 copy yMax sub dy mul dx div add yMax l", - " yMin sub dy mul dx div add yMin l", - " h f*", - " } {", - " exch 2 copy xMin sub dx mul dy div add xMin exch m", - " xMax sub dx mul dy div add xMax exch l", - " exch 2 copy xMax sub dx mul dy div add xMax exch l", - " xMin sub dx mul dy div add xMin exch l", - " h f*", - " } ifelse", - " } ifelse", - "} def", - "/radialCol {", - " dup t0 lt {", - " pop t0", - " } {", - " dup t1 gt {", - " pop t1", - " } if", - " } ifelse", - " func n array astore", - "} def", - "/radialSH {", - " dup 0 eq {", - " true", - " } {", - " dup 8 eq {", - " false", - " } {", - " 2 index dt mul t0 add radialCol", - " 2 index dt mul t0 add radialCol colordelta", - " } ifelse", - " } ifelse", - " {", - " 1 add 3 1 roll 2 copy add 0.5 mul", - " dup 4 3 roll exch 4 index radialSH", - " exch 3 2 roll radialSH", - " } {", - " pop 2 copy add 0.5 mul dt mul t0 add axialCol sc", - " exch dup dx mul x0 add exch dup dy mul y0 add exch dr mul r0 add", - " 0 360 arc h", - " dup dx mul x0 add exch dup dy mul y0 add exch dr mul r0 add", - " 0 360 arc h f*", - " } ifelse", - "} def", - "~123sn", - "end", - NULL -}; - -static char *cmapProlog[] = { - "/CIDInit /ProcSet findresource begin", - "10 dict begin", - " begincmap", - " /CMapType 1 def", - " /CMapName /Identity-H def", - " /CIDSystemInfo 3 dict dup begin", - " /Registry (Adobe) def", - " /Ordering (Identity) def", - " /Supplement 0 def", - " end def", - " 1 begincodespacerange", - " <0000> <ffff>", - " endcodespacerange", - " 0 usefont", - " 1 begincidrange", - " <0000> <ffff> 0", - " endcidrange", - " endcmap", - " currentdict CMapName exch /CMap defineresource pop", - "end", - "10 dict begin", - " begincmap", - " /CMapType 1 def", - " /CMapName /Identity-V def", - " /CIDSystemInfo 3 dict dup begin", - " /Registry (Adobe) def", - " /Ordering (Identity) def", - " /Supplement 0 def", - " end def", - " /WMode 1 def", - " 1 begincodespacerange", - " <0000> <ffff>", - " endcodespacerange", - " 0 usefont", - " 1 begincidrange", - " <0000> <ffff> 0", - " endcidrange", - " endcmap", - " currentdict CMapName exch /CMap defineresource pop", - "end", - "end", - NULL -}; - -//------------------------------------------------------------------------ -// Fonts -//------------------------------------------------------------------------ - -struct PSSubstFont { - char *psName; // PostScript name - double mWidth; // width of 'm' character -}; - -static char *psFonts[] = { - "Courier", - "Courier-Bold", - "Courier-Oblique", - "Courier-BoldOblique", - "Helvetica", - "Helvetica-Bold", - "Helvetica-Oblique", - "Helvetica-BoldOblique", - "Symbol", - "Times-Roman", - "Times-Bold", - "Times-Italic", - "Times-BoldItalic", - "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} -}; - -// Encoding info for substitute 16-bit font -struct PSFont16Enc { - Ref fontID; - GString *enc; -}; - -//------------------------------------------------------------------------ -// process colors -//------------------------------------------------------------------------ - -#define psProcessCyan 1 -#define psProcessMagenta 2 -#define psProcessYellow 4 -#define psProcessBlack 8 -#define psProcessCMYK 15 - -//------------------------------------------------------------------------ -// PSOutCustomColor -//------------------------------------------------------------------------ - -class PSOutCustomColor { -public: - - PSOutCustomColor(double cA, double mA, - double yA, double kA, GString *nameA); - ~PSOutCustomColor(); - - double c, m, y, k; - GString *name; - PSOutCustomColor *next; -}; - -PSOutCustomColor::PSOutCustomColor(double cA, double mA, - double yA, double kA, GString *nameA) { - c = cA; - m = mA; - y = yA; - k = kA; - name = nameA; - next = NULL; -} - -PSOutCustomColor::~PSOutCustomColor() { - delete name; -} - -//------------------------------------------------------------------------ -// DeviceNRecoder -//------------------------------------------------------------------------ - -class DeviceNRecoder: public FilterStream { -public: - - DeviceNRecoder(Stream *strA, int widthA, int heightA, - GfxImageColorMap *colorMapA); - virtual ~DeviceNRecoder(); - virtual StreamKind getKind() { return strWeird; } - virtual void reset(); - virtual int getChar() - { return (bufIdx >= bufSize && !fillBuf()) ? EOF : buf[bufIdx++]; } - virtual int lookChar() - { return (bufIdx >= bufSize && !fillBuf()) ? EOF : buf[bufIdx]; } - virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; } - virtual GBool isBinary(GBool last = gTrue) { return gTrue; } - virtual GBool isEncoder() { return gTrue; } - -private: - - GBool fillBuf(); - - int width, height; - GfxImageColorMap *colorMap; - Function *func; - ImageStream *imgStr; - int buf[gfxColorMaxComps]; - int pixelIdx; - int bufIdx; - int bufSize; -}; - -DeviceNRecoder::DeviceNRecoder(Stream *strA, int widthA, int heightA, - GfxImageColorMap *colorMapA): - FilterStream(strA) { - width = widthA; - height = heightA; - colorMap = colorMapA; - imgStr = NULL; - pixelIdx = 0; - bufIdx = gfxColorMaxComps; - bufSize = ((GfxDeviceNColorSpace *)colorMap->getColorSpace())-> - getAlt()->getNComps(); - func = ((GfxDeviceNColorSpace *)colorMap->getColorSpace())-> - getTintTransformFunc(); -} - -DeviceNRecoder::~DeviceNRecoder() { - if (imgStr) { - delete imgStr; - } -} - -void DeviceNRecoder::reset() { - imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(), - colorMap->getBits()); - imgStr->reset(); -} - -GBool DeviceNRecoder::fillBuf() { - Guchar pixBuf[gfxColorMaxComps]; - GfxColor color; - double x[gfxColorMaxComps], y[gfxColorMaxComps]; - int i; - - if (pixelIdx >= width * height) { - return gFalse; - } - imgStr->getPixel(pixBuf); - colorMap->getColor(pixBuf, &color); - for (i = 0; - i < ((GfxDeviceNColorSpace *)colorMap->getColorSpace())->getNComps(); - ++i) { - x[i] = colToDbl(color.c[i]); - } - func->transform(x, y); - for (i = 0; i < bufSize; ++i) { - buf[i] = (int)(y[i] * 255 + 0.5); - } - bufIdx = 0; - ++pixelIdx; - return gTrue; -} - -//------------------------------------------------------------------------ -// PSOutputDev -//------------------------------------------------------------------------ - -extern "C" { -typedef void (*SignalFunc)(int); -} - -static void outputToFile(void *stream, char *data, int len) { - fwrite(data, 1, len, (FILE *)stream); -} - -PSOutputDev::PSOutputDev(char *fileName, XRef *xrefA, Catalog *catalog, - int firstPage, int lastPage, PSOutMode modeA, - int imgLLXA, int imgLLYA, int imgURXA, int imgURYA, - GBool manualCtrlA, const char *pageRangesA) { - FILE *f; - PSFileType fileTypeA; - - underlayCbk = NULL; - underlayCbkData = NULL; - overlayCbk = NULL; - overlayCbkData = NULL; - - fontIDs = NULL; - fontFileIDs = NULL; - fontFileNames = NULL; - font16Enc = NULL; - xobjStack = NULL; - embFontList = NULL; - customColors = NULL; - haveTextClip = gFalse; - t3String = NULL; - - // open file or pipe - if (!strcmp(fileName, "-")) { - fileTypeA = psStdout; - f = stdout; - } else if (fileName[0] == '|') { - fileTypeA = psPipe; -#ifdef HAVE_POPEN -#ifndef WIN32 - signal(SIGPIPE, (SignalFunc)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 { - fileTypeA = psFile; - if (!(f = fopen(fileName, "w"))) { - error(-1, "Couldn't open PostScript file '%s'", fileName); - ok = gFalse; - return; - } - } - - init(outputToFile, f, fileTypeA, - xrefA, catalog, firstPage, lastPage, modeA, - imgLLXA, imgLLYA, imgURXA, imgURYA, manualCtrlA, pageRangesA); -} - -PSOutputDev::PSOutputDev(PSOutputFunc outputFuncA, void *outputStreamA, - XRef *xrefA, Catalog *catalog, - int firstPage, int lastPage, PSOutMode modeA, - int imgLLXA, int imgLLYA, int imgURXA, int imgURYA, - GBool manualCtrlA, const char *pageRangesA) { - underlayCbk = NULL; - underlayCbkData = NULL; - overlayCbk = NULL; - overlayCbkData = NULL; - - fontIDs = NULL; - fontFileIDs = NULL; - fontFileNames = NULL; - font16Enc = NULL; - xobjStack = NULL; - embFontList = NULL; - customColors = NULL; - haveTextClip = gFalse; - t3String = NULL; - - init(outputFuncA, outputStreamA, psGeneric, - xrefA, catalog, firstPage, lastPage, modeA, - imgLLXA, imgLLYA, imgURXA, imgURYA, manualCtrlA, pageRangesA); -} - -void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA, - PSFileType fileTypeA, XRef *xrefA, Catalog *catalog, - int firstPage, int lastPage, PSOutMode modeA, - int imgLLXA, int imgLLYA, int imgURXA, int imgURYA, - GBool manualCtrlA, const char *pageRangesA) { - Page *page; - PDFRectangle *box; - - // initialize - ok = gTrue; - outputFunc = outputFuncA; - outputStream = outputStreamA; - fileType = fileTypeA; - xref = xrefA; - level = globalParams->getPSLevel(); - mode = modeA; - paperWidth = globalParams->getPSPaperWidth(); - paperHeight = globalParams->getPSPaperHeight(); - imgLLX = imgLLXA; - imgLLY = imgLLYA; - imgURX = imgURXA; - imgURY = imgURYA; - pageRanges = pageRangesA; - if (imgLLX == 0 && imgURX == 0 && imgLLY == 0 && imgURY == 0) { - globalParams->getPSImageableArea(&imgLLX, &imgLLY, &imgURX, &imgURY); - } - if (paperWidth < 0 || paperHeight < 0) { - // this check is needed in case the document has zero pages - if (firstPage > 0 && firstPage <= catalog->getNumPages()) { - page = catalog->getPage(firstPage); - paperWidth = (int)ceil(page->getMediaWidth()); - paperHeight = (int)ceil(page->getMediaHeight()); - } else { - paperWidth = 1; - paperHeight = 1; - } - imgLLX = imgLLY = 0; - imgURX = paperWidth; - imgURY = paperHeight; - } - manualCtrl = manualCtrlA; - if (mode == psModeForm) { - lastPage = firstPage; - } - processColors = 0; - inType3Char = gFalse; - -#if OPI_SUPPORT - // initialize OPI nesting levels - opi13Nest = 0; - opi20Nest = 0; -#endif - - tx0 = ty0 = 0; - xScale0 = yScale0 = 0; - rotate0 = -1; - clipLLX0 = clipLLY0 = 0; - clipURX0 = clipURY0 = -1; - - // initialize fontIDs, fontFileIDs, and fontFileNames lists - fontIDSize = 64; - fontIDLen = 0; - fontIDs = (Ref *)gmallocn(fontIDSize, sizeof(Ref)); - fontFileIDSize = 64; - fontFileIDLen = 0; - fontFileIDs = (Ref *)gmallocn(fontFileIDSize, sizeof(Ref)); - fontFileNameSize = 64; - fontFileNameLen = 0; - fontFileNames = (GString **)gmallocn(fontFileNameSize, sizeof(GString *)); - nextTrueTypeNum = 0; - font16EncLen = 0; - font16EncSize = 0; - - xobjStack = new GList(); - numSaves = 0; - numTilingPatterns = 0; - nextFunc = 0; - - // initialize embedded font resource comment list - embFontList = new GString(); - - if (!manualCtrl) { - // this check is needed in case the document has zero pages - if (firstPage > 0 && firstPage <= catalog->getNumPages()) { - writeHeader(firstPage, lastPage, - catalog->getPage(firstPage)->getMediaBox(), - catalog->getPage(firstPage)->getCropBox(), - catalog->getPage(firstPage)->getRotate()); - } else { - box = new PDFRectangle(0, 0, 1, 1); - writeHeader(firstPage, lastPage, box, box, 0); - delete box; - } - if (mode != psModeForm) { - writePS("%%BeginProlog\n"); - } - writeXpdfProcset(); - if (mode != psModeForm) { - writePS("%%EndProlog\n"); - writePS("%%BeginSetup\n"); - } - writeDocSetup(catalog, firstPage, lastPage); - if (mode != psModeForm) { - writePS("%%EndSetup\n"); - } - } - - // initialize sequential page number - seqPage = 1; -} - -PSOutputDev::~PSOutputDev() { - PSOutCustomColor *cc; - int i; - - if (ok) { - if (!manualCtrl) { - writePS("%%Trailer\n"); - writeTrailer(); - if (mode != psModeForm) { - writePS("%%EOF\n"); - } - } - if (fileType == psFile) { -#ifdef MACOS - ICS_MapRefNumAndAssign((short)((FILE *)outputStream)->handle); -#endif - fclose((FILE *)outputStream); - } -#ifdef HAVE_POPEN - else if (fileType == psPipe) { - pclose((FILE *)outputStream); -#ifndef WIN32 - signal(SIGPIPE, (SignalFunc)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); - } - if (font16Enc) { - for (i = 0; i < font16EncLen; ++i) { - delete font16Enc[i].enc; - } - gfree(font16Enc); - } - if (xobjStack) { - delete xobjStack; - } - while (customColors) { - cc = customColors; - customColors = cc->next; - delete cc; - } -} - -void PSOutputDev::writeHeader(int firstPage, int lastPage, - PDFRectangle *mediaBox, PDFRectangle *cropBox, - int pageRotate) { - Object info, obj1; - double x1, y1, x2, y2; - GString *s; - int i; - - switch (mode) { - case psModePS: - writePS("%!PS-Adobe-3.0\n"); - break; - case psModeEPS: - writePS("%!PS-Adobe-3.0 EPSF-3.0\n"); - break; - case psModeForm: - writePS("%!PS-Adobe-3.0 Resource-Form\n"); - break; - } - - // Tell CUPS pstops filter not to do its own rotation... - int cups_rotate = 0; - int width = (int)ceil(mediaBox->x2 - mediaBox->x1); - int height = (int)ceil(mediaBox->y2 - mediaBox->y1); - int imgWidth = (int)ceil(cropBox->x2 - cropBox->x1); - - if (width > height && width > imgWidth) cups_rotate = 90; - - writePSFmt("%%cupsRotation: %d\n", cups_rotate); - - writePSFmt("%%Producer: xpdf/pdftops %s\n", xpdfVersion); - xref->getDocInfo(&info); - if (info.isDict() && info.dictLookup("Creator", &obj1)->isString()) { - writePS("%%Creator: "); - s = obj1.getString(); - if ((s->getChar(0) & 0xff) == 0xfe && - (s->getChar(1) & 0xff) == 0xff) { - // Convert UTF-16 to UTF-8... - for (i = 2; i < s->getLength() && i < 400; i += 2) { - int ch = ((s->getChar(i) & 255) << 8) | (s->getChar(i + 1) & 255); - - if (ch >= 0xd800 && ch <= 0xdbff) { - // Multi-word UTF-16 char... - i += 2; - int lch = ((s->getChar(i) & 255) << 8) | (s->getChar(i + 1) & 255); - - if (lch < 0xdc00 || lch >= 0xdfff) continue; - - ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000; - } - - if (ch < 0x80) - { - /* - * Single byte ASCII... - */ - - writePSChar(ch); - } - else if (ch < 0x800) - { - /* - * Two-byte UTF-8... - */ - - writePSChar(0xc0 | (ch >> 6)); - writePSChar(0x80 | (ch & 0x3f)); - } - else if (ch < 0x10000) - { - /* - * Three-byte UTF-8... - */ - - writePSChar(0xe0 | (ch >> 12)); - writePSChar(0x80 | ((ch >> 6) & 0x3f)); - writePSChar(0x80 | (ch & 0x3f)); - } - else - { - /* - * Four-byte UTF-8... - */ - - writePSChar(0xf0 | (ch >> 18)); - writePSChar(0x80 | ((ch >> 12) & 0x3f)); - writePSChar(0x80 | ((ch >> 6) & 0x3f)); - writePSChar(0x80 | (ch & 0x3f)); - } - } - } else { - for (i = 0; i < s->getLength() && i < 200; ++i) { - writePSChar(s->getChar(i)); - } - } - writePS("\n"); - } - obj1.free(); - if (info.isDict() && info.dictLookup("Title", &obj1)->isString()) { - writePS("%%Title: "); - s = obj1.getString(); - if ((s->getChar(0) & 0xff) == 0xfe && - (s->getChar(1) & 0xff) == 0xff) { - // Convert UTF-16 to UTF-8... - for (i = 2; i < s->getLength() && i < 400; i += 2) { - int ch = ((s->getChar(i) & 255) << 8) | (s->getChar(i + 1) & 255); - - if (ch >= 0xd800 && ch <= 0xdbff) { - // Multi-word UTF-16 char... - i += 2; - int lch = ((s->getChar(i) & 255) << 8) | (s->getChar(i + 1) & 255); - - if (lch < 0xdc00 || lch >= 0xdfff) continue; - - ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000; - } - - if (ch < 0x80) - { - /* - * Single byte ASCII... - */ - - writePSChar(ch); - } - else if (ch < 0x800) - { - /* - * Two-byte UTF-8... - */ - - writePSChar(0xc0 | (ch >> 6)); - writePSChar(0x80 | (ch & 0x3f)); - } - else if (ch < 0x10000) - { - /* - * Three-byte UTF-8... - */ - - writePSChar(0xe0 | (ch >> 12)); - writePSChar(0x80 | ((ch >> 6) & 0x3f)); - writePSChar(0x80 | (ch & 0x3f)); - } - else - { - /* - * Four-byte UTF-8... - */ - - writePSChar(0xf0 | (ch >> 18)); - writePSChar(0x80 | ((ch >> 12) & 0x3f)); - writePSChar(0x80 | ((ch >> 6) & 0x3f)); - writePSChar(0x80 | (ch & 0x3f)); - } - } - } else { - for (i = 0; i < s->getLength() && i < 200; ++i) { - writePSChar(s->getChar(i)); - } - } - writePS("\n"); - } - obj1.free(); - info.free(); - writePSFmt("%%%%LanguageLevel: %d\n", - (level == psLevel1 || level == psLevel1Sep) ? 1 : - (level == psLevel2 || level == psLevel2Sep) ? 2 : 3); - if (level == psLevel1Sep || level == psLevel2Sep || level == psLevel3Sep) { - writePS("%%DocumentProcessColors: (atend)\n"); - writePS("%%DocumentCustomColors: (atend)\n"); - } - writePS("%%DocumentSuppliedResources: (atend)\n"); - - switch (mode) { - case psModePS: - writePSFmt("%%%%DocumentMedia: plain %d %d 0 () ()\n", - paperWidth, paperHeight); - writePSFmt("%%%%BoundingBox: 0 0 %d %d\n", paperWidth, paperHeight); - writePSFmt("%%%%Pages: %d\n", lastPage - firstPage + 1); - writePS("%%EndComments\n"); - writePS("%%BeginDefaults\n"); - writePS("%%PageMedia: plain\n"); - writePS("%%EndDefaults\n"); - break; - case psModeEPS: - epsX1 = cropBox->x1; - epsY1 = cropBox->y1; - epsX2 = cropBox->x2; - epsY2 = cropBox->y2; - if (pageRotate == 0 || pageRotate == 180) { - x1 = epsX1; - y1 = epsY1; - x2 = epsX2; - y2 = epsY2; - } else { // pageRotate == 90 || pageRotate == 270 - x1 = 0; - y1 = 0; - x2 = epsY2 - epsY1; - y2 = epsX2 - epsX1; - } - writePSFmt("%%%%BoundingBox: %d %d %d %d\n", - (int)floor(x1), (int)floor(y1), (int)ceil(x2), (int)ceil(y2)); - if (floor(x1) != ceil(x1) || floor(y1) != ceil(y1) || - floor(x2) != ceil(x2) || floor(y2) != ceil(y2)) { - writePSFmt("%%%%HiResBoundingBox: %g %g %g %g\n", x1, y1, x2, y2); - } - writePS("%%EndComments\n"); - break; - case psModeForm: - writePS("%%EndComments\n"); - writePS("32 dict dup begin\n"); - writePSFmt("/BBox [%d %d %d %d] def\n", - (int)floor(mediaBox->x1), (int)floor(mediaBox->y1), - (int)ceil(mediaBox->x2), (int)ceil(mediaBox->y2)); - writePS("/FormType 1 def\n"); - writePS("/Matrix [1 0 0 1 0 0] def\n"); - break; - } -} - -void PSOutputDev::writeXpdfProcset() { - GBool lev1, lev2, lev3, sep, nonSep; - char **p; - char *q; - - writePSFmt("%%%%BeginResource: procset xpdf %s 0\n", xpdfVersion); - lev1 = lev2 = lev3 = sep = nonSep = gTrue; - for (p = prolog; *p; ++p) { - if ((*p)[0] == '~') { - lev1 = lev2 = lev3 = sep = nonSep = gFalse; - for (q = *p + 1; *q; ++q) { - switch (*q) { - case '1': lev1 = gTrue; break; - case '2': lev2 = gTrue; break; - case '3': lev3 = gTrue; break; - case 's': sep = gTrue; break; - case 'n': nonSep = gTrue; break; - } - } - } else if ((level == psLevel1 && lev1 && nonSep) || - (level == psLevel1Sep && lev1 && sep) || - (level == psLevel2 && lev2 && nonSep) || - (level == psLevel2Sep && lev2 && sep) || - (level == psLevel3 && lev3 && nonSep) || - (level == psLevel3Sep && lev3 && sep)) { - writePSFmt("%s\n", *p); - } - } - writePS("%%EndResource\n"); - - if (level >= psLevel3) { - for (p = cmapProlog; *p; ++p) { - writePSFmt("%s\n", *p); - } - } -} - -void PSOutputDev::writeDocSetup(Catalog *catalog, - int firstPage, int lastPage) { - Page *page; - Dict *resDict; - Annots *annots; - Object obj1, obj2; - int pg, i; - - if (mode == psModeForm) { - // swap the form and xpdf dicts - writePS("xpdf end begin dup begin\n"); - } else { - writePS("xpdf begin\n"); - } - for (pg = firstPage; pg <= lastPage; ++pg) { - page = catalog->getPage(pg); - if ((resDict = page->getResourceDict())) { - setupResources(resDict); - } - annots = new Annots(xref, catalog, page->getAnnots(&obj1)); - obj1.free(); - for (i = 0; i < annots->getNumAnnots(); ++i) { - if (annots->getAnnot(i)->getAppearance(&obj1)->isStream()) { - obj1.streamGetDict()->lookup("Resources", &obj2); - if (obj2.isDict()) { - setupResources(obj2.getDict()); - } - obj2.free(); - } - obj1.free(); - } - delete annots; - } - if (mode != psModeForm) { - if (mode != psModeEPS && !manualCtrl) { - writePSFmt("%d %d %s pdfSetup\n", - paperWidth, paperHeight, - globalParams->getPSDuplex() ? "true" : "false"); - } -#if OPI_SUPPORT - if (globalParams->getPSOPI()) { - writePS("/opiMatrix matrix currentmatrix def\n"); - } -#endif - } -} - -void PSOutputDev::writePageTrailer() { - if (mode != psModeForm) { - writePS("pdfEndPage\n"); - } -} - -void PSOutputDev::writeTrailer() { - PSOutCustomColor *cc; - - if (mode == psModeForm) { - writePS("/Foo exch /Form defineresource pop\n"); - } else { - writePS("end\n"); - writePS("%%DocumentSuppliedResources:\n"); - writePS(embFontList->getCString()); - if (level == psLevel1Sep || level == psLevel2Sep || - level == psLevel3Sep) { - writePS("%%DocumentProcessColors:"); - if (processColors & psProcessCyan) { - writePS(" Cyan"); - } - if (processColors & psProcessMagenta) { - writePS(" Magenta"); - } - if (processColors & psProcessYellow) { - writePS(" Yellow"); - } - if (processColors & psProcessBlack) { - writePS(" Black"); - } - writePS("\n"); - writePS("%%DocumentCustomColors:"); - for (cc = customColors; cc; cc = cc->next) { - writePSFmt(" (%s)", cc->name->getCString()); - } - writePS("\n"); - writePS("%%CMYKCustomColor:\n"); - for (cc = customColors; cc; cc = cc->next) { - writePSFmt("%%%%+ %g %g %g %g (%s)\n", - cc->c, cc->m, cc->y, cc->k, cc->name->getCString()); - } - } - } -} - -void PSOutputDev::setupResources(Dict *resDict) { - Object xObjDict, xObjRef, xObj, patDict, patRef, pat, resObj; - Ref ref0, ref1; - GBool skip; - int i, j; - - setupFonts(resDict); - setupImages(resDict); - - //----- recursively scan XObjects - resDict->lookup("XObject", &xObjDict); - if (xObjDict.isDict()) { - for (i = 0; i < xObjDict.dictGetLength(); ++i) { - - // avoid infinite recursion on XObjects - skip = gFalse; - if ((xObjDict.dictGetValNF(i, &xObjRef)->isRef())) { - ref0 = xObjRef.getRef(); - for (j = 0; j < xobjStack->getLength(); ++j) { - ref1 = *(Ref *)xobjStack->get(j); - if (ref1.num == ref0.num && ref1.gen == ref0.gen) { - skip = gTrue; - break; - } - } - if (!skip) { - xobjStack->append(&ref0); - } - } - if (!skip) { - - // process the XObject's resource dictionary - xObjDict.dictGetVal(i, &xObj); - if (xObj.isStream()) { - xObj.streamGetDict()->lookup("Resources", &resObj); - if (resObj.isDict()) { - setupResources(resObj.getDict()); - } - resObj.free(); - } - xObj.free(); - } - - if (xObjRef.isRef() && !skip) { - xobjStack->del(xobjStack->getLength() - 1); - } - xObjRef.free(); - } - } - xObjDict.free(); - - //----- recursively scan Patterns - resDict->lookup("Pattern", &patDict); - if (patDict.isDict()) { - inType3Char = gTrue; - for (i = 0; i < patDict.dictGetLength(); ++i) { - - // avoid infinite recursion on Patterns - skip = gFalse; - if ((patDict.dictGetValNF(i, &patRef)->isRef())) { - ref0 = patRef.getRef(); - for (j = 0; j < xobjStack->getLength(); ++j) { - ref1 = *(Ref *)xobjStack->get(j); - if (ref1.num == ref0.num && ref1.gen == ref0.gen) { - skip = gTrue; - break; - } - } - if (!skip) { - xobjStack->append(&ref0); - } - } - if (!skip) { - - // process the Pattern's resource dictionary - patDict.dictGetVal(i, &pat); - if (pat.isStream()) { - pat.streamGetDict()->lookup("Resources", &resObj); - if (resObj.isDict()) { - setupResources(resObj.getDict()); - } - resObj.free(); - } - pat.free(); - } - - if (patRef.isRef() && !skip) { - xobjStack->del(xobjStack->getLength() - 1); - } - patRef.free(); - } - inType3Char = gFalse; - } - patDict.free(); -} - -void PSOutputDev::setupFonts(Dict *resDict) { - Object obj1, obj2; - Ref r; - GfxFontDict *gfxFontDict; - GfxFont *font; - int i; - - gfxFontDict = NULL; - resDict->lookupNF("Font", &obj1); - if (obj1.isRef()) { - obj1.fetch(xref, &obj2); - if (obj2.isDict()) { - r = obj1.getRef(); - gfxFontDict = new GfxFontDict(xref, &r, obj2.getDict()); - } - obj2.free(); - } else if (obj1.isDict()) { - gfxFontDict = new GfxFontDict(xref, NULL, obj1.getDict()); - } - if (gfxFontDict) { - for (i = 0; i < gfxFontDict->getNumFonts(); ++i) { - if ((font = gfxFontDict->getFont(i))) { - setupFont(font, resDict); - } - } - delete gfxFontDict; - } - obj1.free(); -} - -void PSOutputDev::setupFont(GfxFont *font, Dict *parentResDict) { - Ref fontFileID; - GString *name; - PSFontParam *fontParam; - GString *psName; - char type3Name[64], buf[16]; - GBool subst; - UnicodeMap *uMap; - char *charName; - double xs, ys; - 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 *)greallocn(fontIDs, fontIDSize, sizeof(Ref)); - } - fontIDs[fontIDLen++] = *font->getID(); - - xs = ys = 1; - subst = gFalse; - - // check for resident 8-bit font - if (font->getName() && - (fontParam = globalParams->getPSFont(font->getName()))) { - psName = new GString(fontParam->psFontName->getCString()); - - // check for embedded Type 1 font - } else if (globalParams->getPSEmbedType1() && - font->getType() == fontType1 && - font->getEmbeddedFontID(&fontFileID)) { - psName = filterPSName(font->getEmbeddedFontName()); - setupEmbeddedType1Font(&fontFileID, psName); - - // check for embedded Type 1C font - } else if (globalParams->getPSEmbedType1() && - font->getType() == fontType1C && - font->getEmbeddedFontID(&fontFileID)) { - psName = filterPSName(font->getEmbeddedFontName()); - setupEmbeddedType1CFont(font, &fontFileID, psName); - - // check for external Type 1 font file - } else if (globalParams->getPSEmbedType1() && - font->getType() == fontType1 && - font->getExtFontFile()) { - // this assumes that the PS font name matches the PDF font name - psName = font->getName()->copy(); - setupExternalType1Font(font->getExtFontFile(), psName); - - // check for embedded TrueType font - } else if (globalParams->getPSEmbedTrueType() && - font->getType() == fontTrueType && - font->getEmbeddedFontID(&fontFileID)) { - psName = filterPSName(font->getEmbeddedFontName()); - setupEmbeddedTrueTypeFont(font, &fontFileID, psName); - - // check for external TrueType font file - } else if (globalParams->getPSEmbedTrueType() && - font->getType() == fontTrueType && - font->getExtFontFile()) { - psName = filterPSName(font->getName()); - setupExternalTrueTypeFont(font, psName); - - // check for embedded CID PostScript font - } else if (globalParams->getPSEmbedCIDPostScript() && - font->getType() == fontCIDType0C && - font->getEmbeddedFontID(&fontFileID)) { - psName = filterPSName(font->getEmbeddedFontName()); - setupEmbeddedCIDType0Font(font, &fontFileID, psName); - - // check for embedded CID TrueType font - } else if (globalParams->getPSEmbedCIDTrueType() && - font->getType() == fontCIDType2 && - font->getEmbeddedFontID(&fontFileID)) { - psName = filterPSName(font->getEmbeddedFontName()); - //~ should check to see if font actually uses vertical mode - setupEmbeddedCIDTrueTypeFont(font, &fontFileID, psName, gTrue); - - } else if (font->getType() == fontType3) { - sprintf(type3Name, "T3_%d_%d", - font->getID()->num, font->getID()->gen); - psName = new GString(type3Name); - setupType3Font(font, psName, parentResDict); - - // do 8-bit font substitution - } else if (!font->isCIDFont()) { - subst = gTrue; - name = font->getName(); - psName = NULL; - if (name) { - for (i = 0; psFonts[i]; ++i) { - if (name->cmp(psFonts[i]) == 0) { - psName = new GString(psFonts[i]); - 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 = new GString(psSubstFonts[i].psName); - for (code = 0; code < 256; ++code) { - if ((charName = ((Gfx8BitFont *)font)->getCharName(code)) && - charName[0] == 'm' && charName[1] == '\0') { - break; - } - } - if (code < 256) { - w1 = ((Gfx8BitFont *)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; - } - } - - // do 16-bit font substitution - } else if ((fontParam = globalParams-> - getPSFont16(font->getName(), - ((GfxCIDFont *)font)->getCollection(), - font->getWMode()))) { - subst = gTrue; - psName = fontParam->psFontName->copy(); - if (font16EncLen >= font16EncSize) { - font16EncSize += 16; - font16Enc = (PSFont16Enc *)greallocn(font16Enc, - font16EncSize, sizeof(PSFont16Enc)); - } - font16Enc[font16EncLen].fontID = *font->getID(); - font16Enc[font16EncLen].enc = fontParam->encoding->copy(); - if ((uMap = globalParams->getUnicodeMap(font16Enc[font16EncLen].enc))) { - uMap->decRefCnt(); - ++font16EncLen; - } else { - error(-1, "Couldn't find Unicode map for 16-bit font encoding '%s'", - font16Enc[font16EncLen].enc->getCString()); - } - - // give up - can't do anything with this font - } else { - error(-1, "Couldn't find a font to substitute for '%s' ('%s' character collection)", - font->getName() ? font->getName()->getCString() : "(unnamed)", - ((GfxCIDFont *)font)->getCollection() - ? ((GfxCIDFont *)font)->getCollection()->getCString() - : "(unknown)"); - return; - } - - // generate PostScript code to set up the font - if (font->isCIDFont()) { - if (level == psLevel3 || level == psLevel3Sep) { - writePSFmt("/F%d_%d /%s %d pdfMakeFont16L3\n", - font->getID()->num, font->getID()->gen, psName->getCString(), - font->getWMode()); - } else { - writePSFmt("/F%d_%d /%s %d pdfMakeFont16\n", - font->getID()->num, font->getID()->gen, psName->getCString(), - font->getWMode()); - } - } else { - writePSFmt("/F%d_%d /%s %g %g\n", - font->getID()->num, font->getID()->gen, psName->getCString(), - xs, ys); - for (i = 0; i < 256; i += 8) { - writePSFmt((i == 0) ? "[ " : " "); - for (j = 0; j < 8; ++j) { - if (font->getType() == fontTrueType && - !subst && - !((Gfx8BitFont *)font)->getHasEncoding()) { - sprintf(buf, "c%02x", i+j); - charName = buf; - } else { - charName = ((Gfx8BitFont *)font)->getCharName(i+j); - // this is a kludge for broken PDF files that encode char 32 - // as .notdef - if (i+j == 32 && charName && !strcmp(charName, ".notdef")) { - charName = "space"; - } - } - writePS("/"); - writePSName(charName ? charName : (char *)".notdef"); - // the empty name is legal in PDF and PostScript, but PostScript - // uses a double-slash (//...) for "immediately evaluated names", - // so we need to add a space character here - if (charName && !charName[0]) { - writePS(" "); - } - } - writePS((i == 256-8) ? (char *)"]\n" : (char *)"\n"); - } - writePS("pdfMakeFont\n"); - } - - delete psName; -} - -void PSOutputDev::setupEmbeddedType1Font(Ref *id, GString *psName) { - static char hexChar[17] = "0123456789abcdef"; - Object refObj, strObj, obj1, obj2, obj3; - Dict *dict; - int length1, length2, length3; - 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 *)greallocn(fontFileIDs, fontFileIDSize, sizeof(Ref)); - } - fontFileIDs[fontFileIDLen++] = *id; - - // get the font stream and info - refObj.initRef(id->num, id->gen); - refObj.fetch(xref, &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); - dict->lookup("Length3", &obj3); - if (!obj1.isInt() || !obj2.isInt() || !obj3.isInt()) { - error(-1, "Missing length fields in embedded font stream dictionary"); - obj1.free(); - obj2.free(); - obj3.free(); - goto err1; - } - length1 = obj1.getInt(); - length2 = obj2.getInt(); - length3 = obj3.getInt(); - obj1.free(); - obj2.free(); - obj3.free(); - - // beginning comment - writePSFmt("%%%%BeginResource: font %s\n", psName->getCString()); - embFontList->append("%%+ font "); - embFontList->append(psName->getCString()); - embFontList->append("\n"); - - // copy ASCII portion of font - strObj.streamReset(); - for (i = 0; i < length1 && (c = strObj.streamGetChar()) != EOF; ++i) { - writePSChar(c); - } - - // 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) { - writePSChar(hexChar[(start[i] >> 4) & 0x0f]); - writePSChar(hexChar[start[i] & 0x0f]); - } - // if Length2 is incorrect (too small), font data gets chopped, so - // we take a few extra characters from the trailer just in case -// length2 += length3 >= 8 ? 8 : length3; - while (i < length2) { - if ((c = strObj.streamGetChar()) == EOF) { - break; - } - writePSChar(hexChar[(c >> 4) & 0x0f]); - writePSChar(hexChar[c & 0x0f]); - if (++i % 32 == 0) { - writePSChar('\n'); - } - } - if (i % 32 > 0) { - writePSChar('\n'); - } - - // already in ASCII format -- just copy it - } else { - for (i = 0; i < 4; ++i) { - writePSChar(start[i]); - } - for (i = 4; i < length2; ++i) { - if ((c = strObj.streamGetChar()) == EOF) { - break; - } - writePSChar(c); - } - } - - // write padding and "cleartomark" - for (i = 0; i < 8; ++i) { - writePS("00000000000000000000000000000000" - "00000000000000000000000000000000\n"); - } - writePS("cleartomark\n"); - - // ending comment - writePS("%%EndResource\n"); - - err1: - strObj.streamClose(); - strObj.free(); -} - -//~ This doesn't handle .pfb files or binary eexec data (which only -//~ happens in pfb files?). -void PSOutputDev::setupExternalType1Font(GString *fileName, GString *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 **)greallocn(fontFileNames, - fontFileNameSize, sizeof(GString *)); - } - fontFileNames[fontFileNameLen++] = fileName->copy(); - - // beginning comment - writePSFmt("%%%%BeginResource: font %s\n", psName->getCString()); - embFontList->append("%%+ font "); - embFontList->append(psName->getCString()); - 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) { - writePSChar(c); - } - fclose(fontFile); - - // ending comment - writePS("%%EndResource\n"); -} - -void PSOutputDev::setupEmbeddedType1CFont(GfxFont *font, Ref *id, - GString *psName) { - char *fontBuf; - int fontLen; - FoFiType1C *ffT1C; - 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 *)greallocn(fontFileIDs, fontFileIDSize, sizeof(Ref)); - } - fontFileIDs[fontFileIDLen++] = *id; - - // beginning comment - writePSFmt("%%%%BeginResource: font %s\n", psName->getCString()); - embFontList->append("%%+ font "); - embFontList->append(psName->getCString()); - embFontList->append("\n"); - - // convert it to a Type 1 font - fontBuf = font->readEmbFontFile(xref, &fontLen); - if ((ffT1C = FoFiType1C::make(fontBuf, fontLen))) { - ffT1C->convertToType1(NULL, gTrue, outputFunc, outputStream); - delete ffT1C; - } - gfree(fontBuf); - - // ending comment - writePS("%%EndResource\n"); -} - -void PSOutputDev::setupEmbeddedTrueTypeFont(GfxFont *font, Ref *id, - GString *psName) { - char unique[32]; - char *fontBuf; - int fontLen; - FoFiTrueType *ffTT; - Gushort *codeToGID; - 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) { - sprintf(unique, "_%d", nextTrueTypeNum++); - psName->append(unique); - break; - } - } - - // add entry to fontFileIDs list - if (i == fontFileIDLen) { - if (fontFileIDLen >= fontFileIDSize) { - fontFileIDSize += 64; - fontFileIDs = (Ref *)greallocn(fontFileIDs, fontFileIDSize, sizeof(Ref)); - } - fontFileIDs[fontFileIDLen++] = *id; - } - - // beginning comment - writePSFmt("%%%%BeginResource: font %s\n", psName->getCString()); - embFontList->append("%%+ font "); - embFontList->append(psName->getCString()); - embFontList->append("\n"); - - // convert it to a Type 42 font - fontBuf = font->readEmbFontFile(xref, &fontLen); - if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) { - codeToGID = ((Gfx8BitFont *)font)->getCodeToGIDMap(ffTT); - ffTT->convertToType42(psName->getCString(), - ((Gfx8BitFont *)font)->getHasEncoding() - ? ((Gfx8BitFont *)font)->getEncoding() - : (char **)NULL, - codeToGID, outputFunc, outputStream); - gfree(codeToGID); - delete ffTT; - } - gfree(fontBuf); - - // ending comment - writePS("%%EndResource\n"); -} - -void PSOutputDev::setupExternalTrueTypeFont(GfxFont *font, GString *psName) { - char unique[32]; - GString *fileName; - char *fontBuf; - int fontLen; - FoFiTrueType *ffTT; - Gushort *codeToGID; - int i; - - // check if font is already embedded - fileName = font->getExtFontFile(); - for (i = 0; i < fontFileNameLen; ++i) { - if (!fontFileNames[i]->cmp(fileName)) { - sprintf(unique, "_%d", nextTrueTypeNum++); - psName->append(unique); - break; - } - } - - // add entry to fontFileNames list - if (i == fontFileNameLen) { - if (fontFileNameLen >= fontFileNameSize) { - fontFileNameSize += 64; - fontFileNames = - (GString **)greallocn(fontFileNames, - fontFileNameSize, sizeof(GString *)); - } - fontFileNames[fontFileNameLen++] = fileName->copy(); - } - - // beginning comment - writePSFmt("%%%%BeginResource: font %s\n", psName->getCString()); - embFontList->append("%%+ font "); - embFontList->append(psName->getCString()); - embFontList->append("\n"); - - // convert it to a Type 42 font - fontBuf = font->readExtFontFile(&fontLen); - if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) { - codeToGID = ((Gfx8BitFont *)font)->getCodeToGIDMap(ffTT); - ffTT->convertToType42(psName->getCString(), - ((Gfx8BitFont *)font)->getHasEncoding() - ? ((Gfx8BitFont *)font)->getEncoding() - : (char **)NULL, - codeToGID, outputFunc, outputStream); - delete ffTT; - } - gfree(fontBuf); - - // ending comment - writePS("%%EndResource\n"); -} - -void PSOutputDev::setupEmbeddedCIDType0Font(GfxFont *font, Ref *id, - GString *psName) { - char *fontBuf; - int fontLen; - FoFiType1C *ffT1C; - 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 *)greallocn(fontFileIDs, fontFileIDSize, sizeof(Ref)); - } - fontFileIDs[fontFileIDLen++] = *id; - - // beginning comment - writePSFmt("%%%%BeginResource: font %s\n", psName->getCString()); - embFontList->append("%%+ font "); - embFontList->append(psName->getCString()); - embFontList->append("\n"); - - // convert it to a Type 0 font - fontBuf = font->readEmbFontFile(xref, &fontLen); - if ((ffT1C = FoFiType1C::make(fontBuf, fontLen))) { - if (globalParams->getPSLevel() >= psLevel3) { - // Level 3: use a CID font - ffT1C->convertToCIDType0(psName->getCString(), outputFunc, outputStream); - } else { - // otherwise: use a non-CID composite font - ffT1C->convertToType0(psName->getCString(), outputFunc, outputStream); - } - delete ffT1C; - } - gfree(fontBuf); - - // ending comment - writePS("%%EndResource\n"); -} - -void PSOutputDev::setupEmbeddedCIDTrueTypeFont(GfxFont *font, Ref *id, - GString *psName, - GBool needVerticalMetrics) { - char unique[32]; - char *fontBuf; - int fontLen; - FoFiTrueType *ffTT; - 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) { - sprintf(unique, "_%d", nextTrueTypeNum++); - psName->append(unique); - break; - } - } - - // add entry to fontFileIDs list - if (fontFileIDLen >= fontFileIDSize) { - fontFileIDSize += 64; - fontFileIDs = (Ref *)greallocn(fontFileIDs, fontFileIDSize, sizeof(Ref)); - } - fontFileIDs[fontFileIDLen++] = *id; - - // beginning comment - writePSFmt("%%%%BeginResource: font %s\n", psName->getCString()); - embFontList->append("%%+ font "); - embFontList->append(psName->getCString()); - embFontList->append("\n"); - - // convert it to a Type 0 font - fontBuf = font->readEmbFontFile(xref, &fontLen); - if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) { - if (globalParams->getPSLevel() >= psLevel3) { - // Level 3: use a CID font - ffTT->convertToCIDType2(psName->getCString(), - ((GfxCIDFont *)font)->getCIDToGID(), - ((GfxCIDFont *)font)->getCIDToGIDLen(), - needVerticalMetrics, - outputFunc, outputStream); - } else { - // otherwise: use a non-CID composite font - ffTT->convertToType0(psName->getCString(), - ((GfxCIDFont *)font)->getCIDToGID(), - ((GfxCIDFont *)font)->getCIDToGIDLen(), - needVerticalMetrics, - outputFunc, outputStream); - } - delete ffTT; - } - gfree(fontBuf); - - // ending comment - writePS("%%EndResource\n"); -} - -void PSOutputDev::setupType3Font(GfxFont *font, GString *psName, - Dict *parentResDict) { - Dict *resDict; - Dict *charProcs; - Object charProc; - Gfx *gfx; - PDFRectangle box; - double *m; - char buf[256]; - int i; - - // set up resources used by font - if ((resDict = ((Gfx8BitFont *)font)->getResources())) { - inType3Char = gTrue; - setupResources(resDict); - inType3Char = gFalse; - } else { - resDict = parentResDict; - } - - // beginning comment - writePSFmt("%%%%BeginResource: font %s\n", psName->getCString()); - embFontList->append("%%+ font "); - embFontList->append(psName->getCString()); - embFontList->append("\n"); - - // font dictionary - writePS("8 dict begin\n"); - writePS("/FontType 3 def\n"); - m = font->getFontMatrix(); - writePSFmt("/FontMatrix [%g %g %g %g %g %g] def\n", - m[0], m[1], m[2], m[3], m[4], m[5]); - m = font->getFontBBox(); - writePSFmt("/FontBBox [%g %g %g %g] def\n", - m[0], m[1], m[2], m[3]); - writePS("/Encoding 256 array def\n"); - writePS(" 0 1 255 { Encoding exch /.notdef put } for\n"); - writePS("/BuildGlyph {\n"); - writePS(" exch /CharProcs get exch\n"); - writePS(" 2 copy known not { pop /.notdef } if\n"); - writePS(" get exec\n"); - writePS("} bind def\n"); - writePS("/BuildChar {\n"); - writePS(" 1 index /Encoding get exch get\n"); - writePS(" 1 index /BuildGlyph get exec\n"); - writePS("} bind def\n"); - if ((charProcs = ((Gfx8BitFont *)font)->getCharProcs())) { - writePSFmt("/CharProcs %d dict def\n", charProcs->getLength()); - writePS("CharProcs begin\n"); - box.x1 = m[0]; - box.y1 = m[1]; - box.x2 = m[2]; - box.y2 = m[3]; - gfx = new Gfx(xref, this, resDict, &box, NULL); - inType3Char = gTrue; - t3Cacheable = gFalse; - for (i = 0; i < charProcs->getLength(); ++i) { - writePS("/"); - writePSName(charProcs->getKey(i)); - writePS(" {\n"); - gfx->display(charProcs->getVal(i, &charProc)); - charProc.free(); - if (t3String) { - if (t3Cacheable) { - sprintf(buf, "%g %g %g %g %g %g setcachedevice\n", - t3WX, t3WY, t3LLX, t3LLY, t3URX, t3URY); - } else { - sprintf(buf, "%g %g setcharwidth\n", t3WX, t3WY); - } - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, t3String->getCString(), - t3String->getLength()); - delete t3String; - t3String = NULL; - } - (*outputFunc)(outputStream, "Q\n", 2); - writePS("} def\n"); - } - inType3Char = gFalse; - delete gfx; - writePS("end\n"); - } - writePS("currentdict end\n"); - writePSFmt("/%s exch definefont pop\n", psName->getCString()); - - // ending comment - writePS("%%EndResource\n"); -} - -void PSOutputDev::setupImages(Dict *resDict) { - Object xObjDict, xObj, xObjRef, subtypeObj; - int i; - - if (!(mode == psModeForm || inType3Char)) { - return; - } - - resDict->lookup("XObject", &xObjDict); - if (xObjDict.isDict()) { - for (i = 0; i < xObjDict.dictGetLength(); ++i) { - xObjDict.dictGetValNF(i, &xObjRef); - xObjDict.dictGetVal(i, &xObj); - if (xObj.isStream()) { - xObj.streamGetDict()->lookup("Subtype", &subtypeObj); - if (subtypeObj.isName("Image")) { - if (xObjRef.isRef()) { - setupImage(xObjRef.getRef(), xObj.getStream()); - } else { - error(-1, "Image in resource dict is not an indirect reference"); - } - } - subtypeObj.free(); - } - xObj.free(); - xObjRef.free(); - } - } - xObjDict.free(); -} - -void PSOutputDev::setupImage(Ref id, Stream *str) { - GBool useASCIIHex; - int c; - int size, line, col, i; - - // construct an encoder stream - useASCIIHex = level == psLevel1 || level == psLevel1Sep || - globalParams->getPSASCIIHex(); - if (useASCIIHex) { - str = new ASCIIHexEncoder(str); - } else { - str = new ASCII85Encoder(str); - } - - // compute image data size - str->reset(); - col = size = 0; - do { - do { - c = str->getChar(); - } while (c == '\n' || c == '\r'); - if (c == (useASCIIHex ? '>' : '~') || c == EOF) { - break; - } - if (c == 'z') { - ++col; - } else { - ++col; - for (i = 1; i <= (useASCIIHex ? 1 : 4); ++i) { - do { - c = str->getChar(); - } while (c == '\n' || c == '\r'); - if (c == (useASCIIHex ? '>' : '~') || c == EOF) { - break; - } - ++col; - } - } - if (col > 225) { - ++size; - col = 0; - } - } while (c != (useASCIIHex ? '>' : '~') && c != EOF); - ++size; - writePSFmt("%d array dup /ImData_%d_%d exch def\n", size, id.num, id.gen); - str->close(); - - // write the data into the array - str->reset(); - line = col = 0; - writePS((char *)(useASCIIHex ? "dup 0 <" : "dup 0 <~")); - do { - do { - c = str->getChar(); - } while (c == '\n' || c == '\r'); - if (c == (useASCIIHex ? '>' : '~') || c == EOF) { - break; - } - if (c == 'z') { - writePSChar(c); - ++col; - } else { - writePSChar(c); - ++col; - for (i = 1; i <= (useASCIIHex ? 1 : 4); ++i) { - do { - c = str->getChar(); - } while (c == '\n' || c == '\r'); - if (c == (useASCIIHex ? '>' : '~') || c == EOF) { - break; - } - writePSChar(c); - ++col; - } - } - // each line is: "dup nnnnn <~...data...~> put<eol>" - // so max data length = 255 - 20 = 235 - // chunks are 1 or 4 bytes each, so we have to stop at 232 - // but make it 225 just to be safe - if (col > 225) { - writePS((char *)(useASCIIHex ? "> put\n" : "~> put\n")); - ++line; - writePSFmt((char *)(useASCIIHex ? "dup %d <" : "dup %d <~"), line); - col = 0; - } - } while (c != (useASCIIHex ? '>' : '~') && c != EOF); - writePS((char *)(useASCIIHex ? "> put\n" : "~> put\n")); - writePS("pop\n"); - str->close(); - - delete str; -} - -GBool PSOutputDev::startPage(int pageNum, GfxState *state) { - int x1, y1, x2, y2, width, height; - int imgWidth, imgHeight, imgWidth2, imgHeight2; - GBool landscape; - - - if (mode == psModePS) { - writePSFmt("%%%%Page: %d %d\n", pageNum, seqPage); - writePS("%%BeginPageSetup\n"); - } - - // underlays - if (underlayCbk) { - (*underlayCbk)(this, underlayCbkData); - } - if (overlayCbk) { - saveState(NULL); - } - - switch (mode) { - - case psModePS: - // rotate, translate, and scale page - imgWidth = imgURX - imgLLX; - imgHeight = imgURY - imgLLY; - x1 = (int)floor(state->getX1()); - y1 = (int)floor(state->getY1()); - x2 = (int)ceil(state->getX2()); - y2 = (int)ceil(state->getY2()); - width = x2 - x1; - height = y2 - y1; - tx = ty = 0; - // rotation and portrait/landscape mode - if (rotate0 >= 0) { - rotate = (360 - rotate0) % 360; - landscape = gFalse; - } else { - rotate = (360 - state->getRotate()) % 360; - - fprintf(stderr, "DEBUG: Page rotate=%d, width=%d, height=%d, imgWidth=%d, imgHeight=%d\n", - state->getRotate(), width, height, imgWidth, imgHeight); - - if (rotate == 0 || rotate == 180) { - if (width > height && width > imgWidth) { - rotate += 90; - landscape = gTrue; - } else { - landscape = gFalse; - } - } else { // rotate == 90 || rotate == 270 - if (height > width && height > imgWidth) { - rotate = 270 - rotate; - landscape = gTrue; - } else { - landscape = gFalse; - } - } - } - - writePSFmt("%%%%PageOrientation: %s\n", - landscape ? "Landscape" : "Portrait"); - writePS("pdfStartPage\n"); - if (rotate == 0) { - imgWidth2 = imgWidth; - imgHeight2 = imgHeight; - } else if (rotate == 90) { - writePS("90 rotate\n"); - ty = -imgWidth; - imgWidth2 = imgHeight; - imgHeight2 = imgWidth; - } else if (rotate == 180) { - writePS("180 rotate\n"); - imgWidth2 = imgWidth; - imgHeight2 = imgHeight; - tx = -imgWidth; - ty = -imgHeight; - } else { // rotate == 270 - writePS("270 rotate\n"); - tx = -imgHeight; - imgWidth2 = imgHeight; - imgHeight2 = imgWidth; - } - // shrink or expand - if (xScale0 > 0 && yScale0 > 0) { - xScale = xScale0; - yScale = yScale0; - } else if ((globalParams->getPSShrinkLarger() && - (width > imgWidth2 || height > imgHeight2)) || - (globalParams->getPSExpandSmaller() && - (width < imgWidth2 && height < imgHeight2))) { - xScale = (double)imgWidth2 / (double)width; - yScale = (double)imgHeight2 / (double)height; - if (yScale < xScale) { - xScale = yScale; - } else { - yScale = xScale; - } - } else { - xScale = yScale = 1; - paperWidth = width; - paperHeight = height; - } - - // deal with odd bounding boxes or clipping - if (clipLLX0 < clipURX0 && clipLLY0 < clipURY0) { - tx -= xScale * clipLLX0; - ty -= yScale * clipLLY0; - } else { - tx -= xScale * x1; - ty -= yScale * y1; - } - // center - if (globalParams->getPSCenter()) { - if (clipLLX0 < clipURX0 && clipLLY0 < clipURY0) { - tx += (imgWidth2 - xScale * (clipURX0 - clipLLX0)) / 2; - ty += (imgHeight2 - yScale * (clipURY0 - clipLLY0)) / 2; - } else { - tx += (imgWidth2 - xScale * width) / 2; - ty += (imgHeight2 - yScale * height) / 2; - } - } - tx += rotate == 0 ? imgLLX + tx0 : imgLLY + ty0; - ty += rotate == 0 ? imgLLY + ty0 : -(imgLLX + tx0); - if (tx != 0 || ty != 0) { - writePSFmt("%g %g translate\n", tx, ty); - } - if (xScale != 1 || yScale != 1) { - writePSFmt("%0.4f %0.4f scale\n", xScale, xScale); - } - if (clipLLX0 < clipURX0 && clipLLY0 < clipURY0) { - writePSFmt("%g %g %g %g re W\n", - clipLLX0, clipLLY0, clipURX0 - clipLLX0, clipURY0 - clipLLY0); - } else { - writePSFmt("%d %d %d %d re W\n", x1, y1, x2 - x1, y2 - y1); - } - - writePS("%%EndPageSetup\n"); - ++seqPage; - break; - - case psModeEPS: - writePS("pdfStartPage\n"); - tx = ty = 0; - rotate = (360 - state->getRotate()) % 360; - if (rotate == 0) { - } else if (rotate == 90) { - writePS("90 rotate\n"); - tx = -epsX1; - ty = -epsY2; - } else if (rotate == 180) { - writePS("180 rotate\n"); - tx = -(epsX1 + epsX2); - ty = -(epsY1 + epsY2); - } else { // rotate == 270 - writePS("270 rotate\n"); - tx = -epsX2; - ty = -epsY1; - } - if (tx != 0 || ty != 0) { - writePSFmt("%g %g translate\n", tx, ty); - } - xScale = yScale = 1; - break; - - case psModeForm: - writePS("/PaintProc {\n"); - writePS("begin xpdf begin\n"); - writePS("pdfStartPage\n"); - tx = ty = 0; - xScale = yScale = 1; - rotate = 0; - break; - } - - if (!checkRange(pageNum)) - return (gFalse); - else - return (gTrue); -} - -void PSOutputDev::endPage() { - if (overlayCbk) { - restoreState(NULL); - (*overlayCbk)(this, overlayCbkData); - } - - if (mode == psModeForm) { - writePS("pdfEndPage\n"); - writePS("end end\n"); - writePS("} def\n"); - writePS("end end\n"); - } else { - if (!manualCtrl) { - writePS("showpage\n"); - } - writePS("%%PageTrailer\n"); - writePageTrailer(); - } -} - -void PSOutputDev::saveState(GfxState *state) { - writePS("q\n"); - ++numSaves; -} - -void PSOutputDev::restoreState(GfxState *state) { - writePS("Q\n"); - --numSaves; -} - -void PSOutputDev::updateCTM(GfxState *state, double m11, double m12, - double m21, double m22, double m31, double m32) { - writePSFmt("[%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) { - writePSFmt("%g%s", - dash[i] == 0 ? 1 : dash[i], - (i == length-1) ? "" : " "); - } - writePSFmt("] %g d\n", start); -} - -void PSOutputDev::updateFlatness(GfxState *state) { - writePSFmt("%d i\n", state->getFlatness()); -} - -void PSOutputDev::updateLineJoin(GfxState *state) { - writePSFmt("%d j\n", state->getLineJoin()); -} - -void PSOutputDev::updateLineCap(GfxState *state) { - writePSFmt("%d J\n", state->getLineCap()); -} - -void PSOutputDev::updateMiterLimit(GfxState *state) { - writePSFmt("%g M\n", state->getMiterLimit()); -} - -void PSOutputDev::updateLineWidth(GfxState *state) { - writePSFmt("%g w\n", state->getLineWidth()); -} - -void PSOutputDev::updateFillColorSpace(GfxState *state) { - switch (level) { - case psLevel1: - case psLevel1Sep: - break; - case psLevel2: - case psLevel3: - if (state->getFillColorSpace()->getMode() != csPattern) { - dumpColorSpaceL2(state->getFillColorSpace(), gTrue, gFalse); - writePS(" cs\n"); - } - break; - case psLevel2Sep: - case psLevel3Sep: - break; - } -} - -void PSOutputDev::updateStrokeColorSpace(GfxState *state) { - switch (level) { - case psLevel1: - case psLevel1Sep: - break; - case psLevel2: - case psLevel3: - if (state->getStrokeColorSpace()->getMode() != csPattern) { - dumpColorSpaceL2(state->getStrokeColorSpace(), gTrue, gFalse); - writePS(" CS\n"); - } - break; - case psLevel2Sep: - case psLevel3Sep: - break; - } -} - -void PSOutputDev::updateFillColor(GfxState *state) { - GfxColor color; - GfxColor *colorPtr; - GfxGray gray; - GfxCMYK cmyk; - GfxSeparationColorSpace *sepCS; - double c, m, y, k; - int i; - - switch (level) { - case psLevel1: - state->getFillGray(&gray); - writePSFmt("%g g\n", colToDbl(gray)); - break; - case psLevel1Sep: - state->getFillCMYK(&cmyk); - c = colToDbl(cmyk.c); - m = colToDbl(cmyk.m); - y = colToDbl(cmyk.y); - k = colToDbl(cmyk.k); - writePSFmt("%g %g %g %g k\n", c, m, y, k); - addProcessColor(c, m, y, k); - break; - case psLevel2: - case psLevel3: - if (state->getFillColorSpace()->getMode() != csPattern) { - colorPtr = state->getFillColor(); - writePS("["); - for (i = 0; i < state->getFillColorSpace()->getNComps(); ++i) { - if (i > 0) { - writePS(" "); - } - writePSFmt("%g", colToDbl(colorPtr->c[i])); - } - writePS("] sc\n"); - } - break; - case psLevel2Sep: - case psLevel3Sep: - if (state->getFillColorSpace()->getMode() == csSeparation) { - sepCS = (GfxSeparationColorSpace *)state->getFillColorSpace(); - color.c[0] = gfxColorComp1; - sepCS->getCMYK(&color, &cmyk); - writePSFmt("%g %g %g %g %g (%s) ck\n", - colToDbl(state->getFillColor()->c[0]), - colToDbl(cmyk.c), colToDbl(cmyk.m), - colToDbl(cmyk.y), colToDbl(cmyk.k), - sepCS->getName()->getCString()); - addCustomColor(sepCS); - } else { - state->getFillCMYK(&cmyk); - c = colToDbl(cmyk.c); - m = colToDbl(cmyk.m); - y = colToDbl(cmyk.y); - k = colToDbl(cmyk.k); - writePSFmt("%g %g %g %g k\n", c, m, y, k); - addProcessColor(c, m, y, k); - } - break; - } - t3Cacheable = gFalse; -} - -void PSOutputDev::updateStrokeColor(GfxState *state) { - GfxColor color; - GfxColor *colorPtr; - GfxGray gray; - GfxCMYK cmyk; - GfxSeparationColorSpace *sepCS; - double c, m, y, k; - int i; - - switch (level) { - case psLevel1: - state->getStrokeGray(&gray); - writePSFmt("%g G\n", colToDbl(gray)); - break; - case psLevel1Sep: - state->getStrokeCMYK(&cmyk); - c = colToDbl(cmyk.c); - m = colToDbl(cmyk.m); - y = colToDbl(cmyk.y); - k = colToDbl(cmyk.k); - writePSFmt("%g %g %g %g K\n", c, m, y, k); - addProcessColor(c, m, y, k); - break; - case psLevel2: - case psLevel3: - if (state->getStrokeColorSpace()->getMode() != csPattern) { - colorPtr = state->getStrokeColor(); - writePS("["); - for (i = 0; i < state->getStrokeColorSpace()->getNComps(); ++i) { - if (i > 0) { - writePS(" "); - } - writePSFmt("%g", colToDbl(colorPtr->c[i])); - } - writePS("] SC\n"); - } - break; - case psLevel2Sep: - case psLevel3Sep: - if (state->getStrokeColorSpace()->getMode() == csSeparation) { - sepCS = (GfxSeparationColorSpace *)state->getStrokeColorSpace(); - color.c[0] = gfxColorComp1; - sepCS->getCMYK(&color, &cmyk); - writePSFmt("%g %g %g %g %g (%s) CK\n", - colToDbl(state->getStrokeColor()->c[0]), - colToDbl(cmyk.c), colToDbl(cmyk.m), - colToDbl(cmyk.y), colToDbl(cmyk.k), - sepCS->getName()->getCString()); - addCustomColor(sepCS); - } else { - state->getStrokeCMYK(&cmyk); - c = colToDbl(cmyk.c); - m = colToDbl(cmyk.m); - y = colToDbl(cmyk.y); - k = colToDbl(cmyk.k); - writePSFmt("%g %g %g %g K\n", c, m, y, k); - addProcessColor(c, m, y, k); - } - break; - } - t3Cacheable = gFalse; -} - -void PSOutputDev::addProcessColor(double c, double m, double y, double k) { - if (c > 0) { - processColors |= psProcessCyan; - } - if (m > 0) { - processColors |= psProcessMagenta; - } - if (y > 0) { - processColors |= psProcessYellow; - } - if (k > 0) { - processColors |= psProcessBlack; - } -} - -void PSOutputDev::addCustomColor(GfxSeparationColorSpace *sepCS) { - PSOutCustomColor *cc; - GfxColor color; - GfxCMYK cmyk; - - for (cc = customColors; cc; cc = cc->next) { - if (!cc->name->cmp(sepCS->getName())) { - return; - } - } - color.c[0] = gfxColorComp1; - sepCS->getCMYK(&color, &cmyk); - cc = new PSOutCustomColor(colToDbl(cmyk.c), colToDbl(cmyk.m), - colToDbl(cmyk.y), colToDbl(cmyk.k), - sepCS->getName()->copy()); - cc->next = customColors; - customColors = cc; -} - -void PSOutputDev::updateFillOverprint(GfxState *state) { - if (level >= psLevel2) { - writePSFmt("%s op\n", state->getFillOverprint() ? "true" : "false"); - } -} - -void PSOutputDev::updateStrokeOverprint(GfxState *state) { - if (level >= psLevel2) { - writePSFmt("%s OP\n", state->getStrokeOverprint() ? "true" : "false"); - } -} - -void PSOutputDev::updateFont(GfxState *state) { - if (state->getFont()) { - writePSFmt("/F%d_%d %g Tf\n", - state->getFont()->getID()->num, state->getFont()->getID()->gen, - fabs(state->getFontSize()) < 0.00001 ? 0.00001 - : state->getFontSize()); - } -} - -void PSOutputDev::updateTextMat(GfxState *state) { - double *mat; - - mat = state->getTextMat(); - if (fabs(mat[0] * mat[3] - mat[1] * mat[2]) < 0.00001) { - // avoid a singular (or close-to-singular) matrix - writePSFmt("[0.00001 0 0 0.00001 %g %g] Tm\n", mat[4], mat[5]); - } else { - writePSFmt("[%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) { - writePSFmt("%g Tc\n", state->getCharSpace()); -} - -void PSOutputDev::updateRender(GfxState *state) { - int rm; - - rm = state->getRender(); - writePSFmt("%d Tr\n", rm); - rm &= 3; - if (rm != 0 && rm != 3) { - t3Cacheable = gFalse; - } -} - -void PSOutputDev::updateRise(GfxState *state) { - writePSFmt("%g Ts\n", state->getRise()); -} - -void PSOutputDev::updateWordSpace(GfxState *state) { - writePSFmt("%g Tw\n", state->getWordSpace()); -} - -void PSOutputDev::updateHorizScaling(GfxState *state) { - double h; - - h = state->getHorizScaling(); - if (fabs(h) < 0.01) { - h = 0.01; - } - writePSFmt("%g Tz\n", h); -} - -void PSOutputDev::updateTextPos(GfxState *state) { - writePSFmt("%g %g Td\n", state->getLineX(), state->getLineY()); -} - -void PSOutputDev::updateTextShift(GfxState *state, double shift) { - if (state->getFont()->getWMode()) { - writePSFmt("%g TJmV\n", shift); - } else { - writePSFmt("%g TJm\n", shift); - } -} - -void PSOutputDev::stroke(GfxState *state) { - doPath(state->getPath()); - if (t3String) { - // if we're construct a cacheable Type 3 glyph, we need to do - // everything in the fill color - writePS("Sf\n"); - } else { - 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::tilingPatternFill(GfxState *state, Object *str, - int paintType, Dict *resDict, - double *mat, double *bbox, - int x0, int y0, int x1, int y1, - double xStep, double yStep) { - PDFRectangle box; - Gfx *gfx; - - // define a Type 3 font - writePS("8 dict begin\n"); - writePS("/FontType 3 def\n"); - writePS("/FontMatrix [1 0 0 1 0 0] def\n"); - writePSFmt("/FontBBox [%g %g %g %g] def\n", - bbox[0], bbox[1], bbox[2], bbox[3]); - writePS("/Encoding 256 array def\n"); - writePS(" 0 1 255 { Encoding exch /.notdef put } for\n"); - writePS(" Encoding 120 /x put\n"); - writePS("/BuildGlyph {\n"); - writePS(" exch /CharProcs get exch\n"); - writePS(" 2 copy known not { pop /.notdef } if\n"); - writePS(" get exec\n"); - writePS("} bind def\n"); - writePS("/BuildChar {\n"); - writePS(" 1 index /Encoding get exch get\n"); - writePS(" 1 index /BuildGlyph get exec\n"); - writePS("} bind def\n"); - writePS("/CharProcs 1 dict def\n"); - writePS("CharProcs begin\n"); - box.x1 = bbox[0]; - box.y1 = bbox[1]; - box.x2 = bbox[2]; - box.y2 = bbox[3]; - gfx = new Gfx(xref, this, resDict, &box, NULL); - writePS("/x {\n"); - if (paintType == 2) { - writePSFmt("%g 0 %g %g %g %g setcachedevice\n", - xStep, bbox[0], bbox[1], bbox[2], bbox[3]); - } else { - writePSFmt("%g 0 setcharwidth\n", xStep); - } - inType3Char = gTrue; - ++numTilingPatterns; - gfx->display(str); - --numTilingPatterns; - inType3Char = gFalse; - writePS("} def\n"); - delete gfx; - writePS("end\n"); - writePS("currentdict end\n"); - writePSFmt("/xpdfTile%d exch definefont pop\n", numTilingPatterns); - - // draw the tiles - writePSFmt("/xpdfTile%d findfont setfont\n", numTilingPatterns); - writePSFmt("gsave [%g %g %g %g %g %g] concat\n", - mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]); - writePSFmt("%d 1 %d { %g exch %g mul m %d 1 %d { pop (x) show } for } for\n", - y0, y1 - 1, x0 * xStep, yStep, x0, x1 - 1); - writePS("grestore\n"); -} - -void PSOutputDev::functionShadedFill(GfxState *state, - GfxFunctionShading *shading) { - double x0, y0, x1, y1; - double *mat; - int i; - - shading->getDomain(&x0, &y0, &x1, &y1); - mat = shading->getMatrix(); - writePSFmt("/mat [%g %g %g %g %g %g] def\n", - mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]); - writePSFmt("/n %d def\n", shading->getColorSpace()->getNComps()); - if (shading->getNFuncs() == 1) { - writePS("/func "); - cvtFunction(shading->getFunc(0)); - writePS("def\n"); - } else { - writePS("/func {\n"); - for (i = 0; i < shading->getNFuncs(); ++i) { - if (i < shading->getNFuncs() - 1) { - writePS("2 copy\n"); - } - cvtFunction(shading->getFunc(i)); - writePS("exec\n"); - if (i < shading->getNFuncs() - 1) { - writePS("3 1 roll\n"); - } - } - writePS("} def\n"); - } - writePSFmt("%g %g %g %g 0 funcSH\n", x0, y0, x1, y1); -} - -void PSOutputDev::axialShadedFill(GfxState *state, GfxAxialShading *shading) { - double xMin, yMin, xMax, yMax; - double x0, y0, x1, y1, dx, dy, mul; - double tMin, tMax, t, t0, t1; - int i; - - // get the clip region bbox - state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax); - - // compute min and max t values, based on the four corners of the - // clip region bbox - shading->getCoords(&x0, &y0, &x1, &y1); - dx = x1 - x0; - dy = y1 - y0; - mul = 1 / (dx * dx + dy * dy); - tMin = tMax = ((xMin - x0) * dx + (yMin - y0) * dy) * mul; - t = ((xMin - x0) * dx + (yMax - y0) * dy) * mul; - if (t < tMin) { - tMin = t; - } else if (t > tMax) { - tMax = t; - } - t = ((xMax - x0) * dx + (yMin - y0) * dy) * mul; - if (t < tMin) { - tMin = t; - } else if (t > tMax) { - tMax = t; - } - t = ((xMax - x0) * dx + (yMax - y0) * dy) * mul; - if (t < tMin) { - tMin = t; - } else if (t > tMax) { - tMax = t; - } - if (tMin < 0 && !shading->getExtend0()) { - tMin = 0; - } - if (tMax > 1 && !shading->getExtend1()) { - tMax = 1; - } - - // get the function domain - t0 = shading->getDomain0(); - t1 = shading->getDomain1(); - - // generate the PS code - writePSFmt("/t0 %g def\n", t0); - writePSFmt("/t1 %g def\n", t1); - writePSFmt("/dt %g def\n", t1 - t0); - writePSFmt("/x0 %g def\n", x0); - writePSFmt("/y0 %g def\n", y0); - writePSFmt("/dx %g def\n", x1 - x0); - writePSFmt("/x1 %g def\n", x1); - writePSFmt("/y1 %g def\n", y1); - writePSFmt("/dy %g def\n", y1 - y0); - writePSFmt("/xMin %g def\n", xMin); - writePSFmt("/yMin %g def\n", yMin); - writePSFmt("/xMax %g def\n", xMax); - writePSFmt("/yMax %g def\n", yMax); - writePSFmt("/n %d def\n", shading->getColorSpace()->getNComps()); - if (shading->getNFuncs() == 1) { - writePS("/func "); - cvtFunction(shading->getFunc(0)); - writePS("def\n"); - } else { - writePS("/func {\n"); - for (i = 0; i < shading->getNFuncs(); ++i) { - if (i < shading->getNFuncs() - 1) { - writePS("dup\n"); - } - cvtFunction(shading->getFunc(i)); - writePS("exec\n"); - if (i < shading->getNFuncs() - 1) { - writePS("exch\n"); - } - } - writePS("} def\n"); - } - writePSFmt("%g %g 0 axialSH\n", tMin, tMax); -} - -void PSOutputDev::radialShadedFill(GfxState *state, - GfxRadialShading *shading) { - double x0, y0, r0, x1, y1, r1, t0, t1, sMin, sMax; - double xMin, yMin, xMax, yMax; - double d0, d1; - int i; - - // get the shading info - shading->getCoords(&x0, &y0, &r0, &x1, &y1, &r1); - t0 = shading->getDomain0(); - t1 = shading->getDomain1(); - - // compute the (possibly extended) s range - sMin = 0; - sMax = 1; - if (shading->getExtend0()) { - if (r0 < r1) { - // extend the smaller end - sMin = -r0 / (r1 - r0); - } else { - // extend the larger end - state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax); - d0 = (x0 - xMin) * (x0 - xMin); - d1 = (x0 - xMax) * (x0 - xMax); - sMin = d0 > d1 ? d0 : d1; - d0 = (y0 - yMin) * (y0 - yMin); - d1 = (y0 - yMax) * (y0 - yMax); - sMin += d0 > d1 ? d0 : d1; - sMin = (sqrt(sMin) - r0) / (r1 - r0); - if (sMin > 0) { - sMin = 0; - } else if (sMin < -20) { - // sanity check - sMin = -20; - } - } - } - if (shading->getExtend1()) { - if (r1 < r0) { - // extend the smaller end - sMax = -r0 / (r1 - r0); - } else if (r1 > r0) { - // extend the larger end - state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax); - d0 = (x1 - xMin) * (x1 - xMin); - d1 = (x1 - xMax) * (x1 - xMax); - sMax = d0 > d1 ? d0 : d1; - d0 = (y1 - yMin) * (y1 - yMin); - d1 = (y1 - yMax) * (y1 - yMax); - sMax += d0 > d1 ? d0 : d1; - sMax = (sqrt(sMax) - r0) / (r1 - r0); - if (sMax < 1) { - sMax = 1; - } else if (sMax > 20) { - // sanity check - sMax = 20; - } - } - } - - // generate the PS code - writePSFmt("/x0 %g def\n", x0); - writePSFmt("/x1 %g def\n", x1); - writePSFmt("/dx %g def\n", x1 - x0); - writePSFmt("/y0 %g def\n", y0); - writePSFmt("/y1 %g def\n", y1); - writePSFmt("/dy %g def\n", y1 - y0); - writePSFmt("/r0 %g def\n", r0); - writePSFmt("/r1 %g def\n", r1); - writePSFmt("/dr %g def\n", r1 - r0); - writePSFmt("/t0 %g def\n", t0); - writePSFmt("/t1 %g def\n", t1); - writePSFmt("/dt %g def\n", t1 - t0); - writePSFmt("/n %d def\n", shading->getColorSpace()->getNComps()); - if (shading->getNFuncs() == 1) { - writePS("/func "); - cvtFunction(shading->getFunc(0)); - writePS("def\n"); - } else { - writePS("/func {\n"); - for (i = 0; i < shading->getNFuncs(); ++i) { - if (i < shading->getNFuncs() - 1) { - writePS("dup\n"); - } - cvtFunction(shading->getFunc(i)); - writePS("exec\n"); - if (i < shading->getNFuncs() - 1) { - writePS("exch\n"); - } - } - writePS("} def\n"); - } - writePSFmt("%g %g 0 radialSH\n", sMin, sMax); -} - -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) { - writePSFmt("%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) { - writePSFmt("%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(); - writePSFmt("%g %g m\n", subpath->getX(0), subpath->getY(0)); - j = 1; - while (j < m) { - if (subpath->getCurve(j)) { - writePSFmt("%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 { - writePSFmt("%g %g l\n", subpath->getX(j), subpath->getY(j)); - ++j; - } - } - if (subpath->isClosed()) { - writePS("h\n"); - } - } -} - -void PSOutputDev::drawString(GfxState *state, GString *s) { - GfxFont *font; - int wMode; - GString *s2; - double dx, dy, dx2, dy2, originX, originY; - char *p; - UnicodeMap *uMap; - CharCode code; - Unicode u[8]; - char buf[8]; - int len, nChars, uLen, n, m, i, j; - - // check for invisible text -- this is used by Acrobat Capture - if (state->getRender() == 3) { - return; - } - - // ignore empty strings - if (s->getLength() == 0) { - return; - } - - // get the font - if (!(font = state->getFont())) { - return; - } - wMode = font->getWMode(); - - // check for a subtitute 16-bit font - uMap = NULL; - if (font->isCIDFont()) { - for (i = 0; i < font16EncLen; ++i) { - if (font->getID()->num == font16Enc[i].fontID.num && - font->getID()->gen == font16Enc[i].fontID.gen) { - uMap = globalParams->getUnicodeMap(font16Enc[i].enc); - break; - } - } - } - - // compute width of chars in string, ignoring char spacing and word - // spacing -- the Tj operator will adjust for the metrics of the - // font that's actually used - dx = dy = 0; - nChars = 0; - p = s->getCString(); - len = s->getLength(); - if (font->isCIDFont()) { - s2 = new GString(); - } else { - s2 = s; - } - while (len > 0) { - n = font->getNextChar(p, len, &code, - u, (int)(sizeof(u) / sizeof(Unicode)), &uLen, - &dx2, &dy2, &originX, &originY); - if (font->isCIDFont()) { - if (uMap) { - for (i = 0; i < uLen; ++i) { - m = uMap->mapUnicode(u[i], buf, (int)sizeof(buf)); - for (j = 0; j < m; ++j) { - s2->append(buf[j]); - } - } - //~ this really needs to get the number of chars in the target - //~ encoding - which may be more than the number of Unicode - //~ chars - nChars += uLen; - } else { - s2->append((char)((code >> 8) & 0xff)); - s2->append((char)(code & 0xff)); - ++nChars; - } - } - dx += dx2; - dy += dy2; - p += n; - len -= n; - } - dx *= state->getFontSize() * state->getHorizScaling(); - dy *= state->getFontSize(); - if (uMap) { - uMap->decRefCnt(); - } - - if (s2->getLength() > 0) { - writePSString(s2); - if (font->isCIDFont()) { - if (wMode) { - writePSFmt(" %d %g Tj16V\n", nChars, dy); - } else { - writePSFmt(" %d %g Tj16\n", nChars, dx); - } - } else { - writePSFmt(" %g Tj\n", dx); - } - } - if (font->isCIDFont()) { - delete s2; - } - - if (state->getRender() & 4) { - haveTextClip = gTrue; - } -} - -void PSOutputDev::endTextObject(GfxState *state) { - if (haveTextClip) { - writePS("Tclip\n"); - haveTextClip = gFalse; - } -} - -void PSOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, - int width, int height, GBool invert, - GBool inlineImg) { - int len; - - len = height * ((width + 7) / 8); - if (level == psLevel1 || level == psLevel1Sep) { - doImageL1(ref, NULL, invert, inlineImg, str, width, height, len); - } else { - doImageL2(ref, NULL, invert, inlineImg, str, width, height, len, - NULL, NULL, 0, 0, gFalse); - } -} - -void PSOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, - int width, int height, GfxImageColorMap *colorMap, - int *maskColors, GBool inlineImg) { - int len; - - len = height * ((width * colorMap->getNumPixelComps() * - colorMap->getBits() + 7) / 8); - switch (level) { - case psLevel1: - doImageL1(ref, colorMap, gFalse, inlineImg, str, width, height, len); - break; - case psLevel1Sep: - //~ handle indexed, separation, ... color spaces - doImageL1Sep(colorMap, gFalse, inlineImg, str, width, height, len); - break; - case psLevel2: - case psLevel2Sep: - case psLevel3: - case psLevel3Sep: - doImageL2(ref, colorMap, gFalse, inlineImg, str, - width, height, len, maskColors, NULL, 0, 0, gFalse); - break; - } - t3Cacheable = gFalse; -} - -void PSOutputDev::drawMaskedImage(GfxState *state, Object *ref, Stream *str, - int width, int height, - GfxImageColorMap *colorMap, - Stream *maskStr, - int maskWidth, int maskHeight, - GBool maskInvert) { - int len; - - len = height * ((width * colorMap->getNumPixelComps() * - colorMap->getBits() + 7) / 8); - switch (level) { - case psLevel1: - doImageL1(ref, colorMap, gFalse, gFalse, str, width, height, len); - break; - case psLevel1Sep: - //~ handle indexed, separation, ... color spaces - doImageL1Sep(colorMap, gFalse, gFalse, str, width, height, len); - break; - case psLevel2: - case psLevel2Sep: - case psLevel3: - case psLevel3Sep: - doImageL2(ref, colorMap, gFalse, gFalse, str, width, height, len, - NULL, maskStr, maskWidth, maskHeight, maskInvert); - break; - } - t3Cacheable = gFalse; -} - -void PSOutputDev::doImageL1(Object *ref, GfxImageColorMap *colorMap, - GBool invert, GBool inlineImg, - Stream *str, int width, int height, int len) { - ImageStream *imgStr; - Guchar pixBuf[gfxColorMaxComps]; - GfxGray gray; - int col, x, y, c, i; - - if (inType3Char && !colorMap) { - if (inlineImg) { - // create an array - str = new FixedLengthEncoder(str, len); - str = new ASCIIHexEncoder(str); - str->reset(); - col = 0; - writePS("[<"); - do { - do { - c = str->getChar(); - } while (c == '\n' || c == '\r'); - if (c == '>' || c == EOF) { - break; - } - writePSChar(c); - ++col; - // each line is: "<...data...><eol>" - // so max data length = 255 - 4 = 251 - // but make it 240 just to be safe - // chunks are 2 bytes each, so we need to stop on an even col number - if (col == 240) { - writePS(">\n<"); - col = 0; - } - } while (c != '>' && c != EOF); - writePS(">]\n"); - writePS("0\n"); - str->close(); - delete str; - } else { - // set up to use the array already created by setupImages() - writePSFmt("ImData_%d_%d 0\n", ref->getRefNum(), ref->getRefGen()); - } - } - - // image/imagemask command - if (inType3Char && !colorMap) { - writePSFmt("%d %d %s [%d 0 0 %d 0 %d] pdfImM1a\n", - width, height, invert ? "true" : "false", - width, -height, height); - } else if (colorMap) { - writePSFmt("%d %d 8 [%d 0 0 %d 0 %d] pdfIm1\n", - width, height, - width, -height, height); - } else { - writePSFmt("%d %d %s [%d 0 0 %d 0 %d] pdfImM1\n", - width, height, invert ? "true" : "false", - width, -height, height); - } - - // image data - if (!(inType3Char && !colorMap)) { - - 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->getGray(pixBuf, &gray); - writePSFmt("%02x", colToByte(gray)); - if (++i == 32) { - writePSChar('\n'); - i = 0; - } - } - } - if (i != 0) { - writePSChar('\n'); - } - delete imgStr; - - // imagemask - } else { - str->reset(); - i = 0; - for (y = 0; y < height; ++y) { - for (x = 0; x < width; x += 8) { - writePSFmt("%02x", str->getChar() & 0xff); - if (++i == 32) { - writePSChar('\n'); - i = 0; - } - } - } - if (i != 0) { - writePSChar('\n'); - } - str->close(); - } - } -} - -void PSOutputDev::doImageL1Sep(GfxImageColorMap *colorMap, - GBool invert, GBool inlineImg, - Stream *str, int width, int height, int len) { - ImageStream *imgStr; - Guchar *lineBuf; - Guchar pixBuf[gfxColorMaxComps]; - GfxCMYK cmyk; - int x, y, i, comp; - - // width, height, matrix, bits per component - writePSFmt("%d %d 8 [%d 0 0 %d 0 %d] pdfIm1Sep\n", - width, height, - width, -height, height); - - // allocate a line buffer - lineBuf = (Guchar *)gmalloc(4 * width); - - // 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) { - - // read the line - for (x = 0; x < width; ++x) { - imgStr->getPixel(pixBuf); - colorMap->getCMYK(pixBuf, &cmyk); - lineBuf[4*x+0] = colToByte(cmyk.c); - lineBuf[4*x+1] = colToByte(cmyk.m); - lineBuf[4*x+2] = colToByte(cmyk.y); - lineBuf[4*x+3] = colToByte(cmyk.k); - addProcessColor(colToDbl(cmyk.c), colToDbl(cmyk.m), - colToDbl(cmyk.y), colToDbl(cmyk.k)); - } - - // write one line of each color component - for (comp = 0; comp < 4; ++comp) { - for (x = 0; x < width; ++x) { - writePSFmt("%02x", lineBuf[4*x + comp]); - if (++i == 32) { - writePSChar('\n'); - i = 0; - } - } - } - } - - if (i != 0) { - writePSChar('\n'); - } - - delete imgStr; - gfree(lineBuf); -} - -void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap, - GBool invert, GBool inlineImg, - Stream *str, int width, int height, int len, - int *maskColors, Stream *maskStr, - int maskWidth, int maskHeight, GBool maskInvert) { - ImageStream *imgStr; - Guchar *line, *pix; - GString *s; - int n, numComps; - GBool useRLE, useASCII, useASCIIHex, useCompressed; - GfxSeparationColorSpace *sepCS; - GfxColor color; - GfxCMYK cmyk; - int c; - int col, i, x, x0, y, y0, maskXor; - - // color key masking - if (maskColors && colorMap && !inlineImg) { - // can't read the stream twice for inline images -- but masking - // isn't allowed with inline images anyway - writePS("[\n"); - numComps = colorMap->getNumPixelComps(); - imgStr = new ImageStream(str, width, numComps, colorMap->getBits()); - imgStr->reset(); - for (y = 0, y0 = 0; y < height; ++y) { - if (!(line = imgStr->getLine())) { - break; - } - for (x = 0, x0 = 0, pix = line; x < width; ++x, pix += numComps) { - for (i = 0; i < numComps; ++i) { - if (pix[i] < maskColors[2*i] || - pix[i] > maskColors[2*i+1]) { - break; - } - } - if (i == numComps) { - if (y0 < y) { - writePSFmt("0 %d %d %d\n", height - y, width, y - y0); - } - if (x0 < x) { - writePSFmt("%d %d %d 1\n", x0, height - y - 1, x - x0); - } - x0 = x + 1; - y0 = y + 1; - } - } - if (x0 > 0 && x0 < width) { - writePSFmt("%d %d %d 1\n", x0, height - y - 1, width - x0); - } - } - if (y0 < height) { - writePSFmt("0 0 %d %d\n", width, height - y0); - } - delete imgStr; - str->close(); - writePSFmt("] %d %d pdfImClip\n", width, height); - - // explicit masking - } else if (maskStr) { - writePS("[\n"); - imgStr = new ImageStream(maskStr, maskWidth, 1, 1); - imgStr->reset(); - maskXor = maskInvert ? 1 : 0; - for (y = 0, y0 = 0; y < maskHeight; ++y) { - if (!(line = imgStr->getLine())) { - break; - } - for (x = 0, x0 = 0, pix = line; x < maskWidth; ++x, ++pix) { - if (*pix ^ maskXor) { - if (y0 < y) { - writePSFmt("0 %d %d %d\n", maskHeight - y, maskWidth, y - y0); - } - if (x0 < x) { - writePSFmt("%d %d %d 1\n", x0, maskHeight - y - 1, x - x0); - } - x0 = x + 1; - y0 = y + 1; - } - } - if (x0 > 0 && x0 < maskWidth) { - writePSFmt("%d %d %d 1\n", x0, maskHeight - y - 1, maskWidth - x0); - } - } - if (y0 < maskHeight) { - writePSFmt("0 0 %d %d\n", maskWidth, maskHeight - y0); - } - delete imgStr; - maskStr->close(); - writePSFmt("] %d %d pdfImClip\n", maskWidth, maskHeight); - } - - // color space - if (colorMap) { - dumpColorSpaceL2(colorMap->getColorSpace(), gFalse, gTrue); - writePS(" setcolorspace\n"); - } - - useASCIIHex = globalParams->getPSASCIIHex(); - - // set up the image data - if (mode == psModeForm || inType3Char) { - if (inlineImg) { - // create an array - str = new FixedLengthEncoder(str, len); - if (useASCIIHex) { - str = new ASCIIHexEncoder(str); - } else { - str = new ASCII85Encoder(str); - } - str->reset(); - col = 0; - writePS((char *)(useASCIIHex ? "[<" : "[<~")); - do { - do { - c = str->getChar(); - } while (c == '\n' || c == '\r'); - if (c == (useASCIIHex ? '>' : '~') || c == EOF) { - break; - } - if (c == 'z') { - writePSChar(c); - ++col; - } else { - writePSChar(c); - ++col; - for (i = 1; i <= (useASCIIHex ? 1 : 4); ++i) { - do { - c = str->getChar(); - } while (c == '\n' || c == '\r'); - if (c == (useASCIIHex ? '>' : '~') || c == EOF) { - break; - } - writePSChar(c); - ++col; - } - } - // each line is: "<~...data...~><eol>" - // so max data length = 255 - 6 = 249 - // chunks are 1 or 5 bytes each, so we have to stop at 245 - // but make it 240 just to be safe - if (col > 240) { - writePS((char *)(useASCIIHex ? ">\n<" : "~>\n<~")); - col = 0; - } - } while (c != (useASCIIHex ? '>' : '~') && c != EOF); - writePS((char *)(useASCIIHex ? ">]\n" : "~>]\n")); - writePS("0\n"); - str->close(); - delete str; - } else { - // set up to use the array already created by setupImages() - writePSFmt("ImData_%d_%d 0\n", ref->getRefNum(), ref->getRefGen()); - } - } - - // image dictionary - writePS("<<\n /ImageType 1\n"); - - // width, height, matrix, bits per component - writePSFmt(" /Width %d\n", width); - writePSFmt(" /Height %d\n", height); - writePSFmt(" /ImageMatrix [%d 0 0 %d 0 %d]\n", width, -height, height); - if (colorMap && colorMap->getColorSpace()->getMode() == csDeviceN) { - writePSFmt(" /BitsPerComponent 8\n"); - } else { - writePSFmt(" /BitsPerComponent %d\n", - colorMap ? colorMap->getBits() : 1); - } - - // decode - if (colorMap) { - writePS(" /Decode ["); - if ((level == psLevel2Sep || level == psLevel3Sep) && - colorMap->getColorSpace()->getMode() == csSeparation) { - // this matches up with the code in the pdfImSep operator - n = (1 << colorMap->getBits()) - 1; - writePSFmt("%g %g", colorMap->getDecodeLow(0) * n, - colorMap->getDecodeHigh(0) * n); - } else if (colorMap->getColorSpace()->getMode() == csDeviceN) { - numComps = ((GfxDeviceNColorSpace *)colorMap->getColorSpace())-> - getAlt()->getNComps(); - for (i = 0; i < numComps; ++i) { - if (i > 0) { - writePS(" "); - } - writePS("0 1"); - } - } else { - numComps = colorMap->getNumPixelComps(); - for (i = 0; i < numComps; ++i) { - if (i > 0) { - writePS(" "); - } - writePSFmt("%g %g", colorMap->getDecodeLow(i), - colorMap->getDecodeHigh(i)); - } - } - writePS("]\n"); - } else { - writePSFmt(" /Decode [%d %d]\n", invert ? 1 : 0, invert ? 0 : 1); - } - - if (mode == psModeForm || inType3Char) { - - // data source - writePS(" /DataSource { 2 copy get exch 1 add exch }\n"); - - // end of image dictionary - writePSFmt(">>\n%s\n", colorMap ? "image" : "imagemask"); - - // get rid of the array and index - writePS("pop pop\n"); - - } else { - - // data source - writePS(" /DataSource currentfile\n"); - s = str->getPSFilter(level < psLevel2 ? 1 : level < psLevel3 ? 2 : 3, - " "); - if ((colorMap && colorMap->getColorSpace()->getMode() == csDeviceN) || - inlineImg || !s) { - useRLE = gTrue; - useASCII = gTrue; - useCompressed = gFalse; - } else { - useRLE = gFalse; - useASCII = str->isBinary(); - useCompressed = gTrue; - } - if (useASCII) { - writePSFmt(" /ASCII%sDecode filter\n", - useASCIIHex ? "Hex" : "85"); - } - if (useRLE) { - writePS(" /RunLengthDecode filter\n"); - } - if (useCompressed) { - writePS(s->getCString()); - } - if (s) { - delete s; - } - - // cut off inline image streams at appropriate length - if (inlineImg) { - str = new FixedLengthEncoder(str, len); - } else if (useCompressed) { - str = str->getBaseStream(); - } - - // recode DeviceN data - if (colorMap && colorMap->getColorSpace()->getMode() == csDeviceN) { - str = new DeviceNRecoder(str, width, height, colorMap); - } - - // add RunLengthEncode and ASCIIHex/85 encode filters - if (useRLE) { - str = new RunLengthEncoder(str); - } - if (useASCII) { - if (useASCIIHex) { - str = new ASCIIHexEncoder(str); - } else { - 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 ASCII and RLE filters) - str->reset(); - n = 0; - while ((c = str->getChar()) != EOF) { - ++n; - } - str->close(); - } - // +6/7 for "pdfIm\n" / "pdfImM\n" - // +8 for newline + trailer - n += colorMap ? 14 : 15; - writePSFmt("%%%%BeginData: %d Hex Bytes\n", n); - } -#endif - if ((level == psLevel2Sep || level == psLevel3Sep) && colorMap && - colorMap->getColorSpace()->getMode() == csSeparation) { - color.c[0] = gfxColorComp1; - sepCS = (GfxSeparationColorSpace *)colorMap->getColorSpace(); - sepCS->getCMYK(&color, &cmyk); - writePSFmt("%g %g %g %g (%s) pdfImSep\n", - colToDbl(cmyk.c), colToDbl(cmyk.m), - colToDbl(cmyk.y), colToDbl(cmyk.k), - sepCS->getName()->getCString()); - } else { - writePSFmt("%s\n", colorMap ? "pdfIm" : "pdfImM"); - } - - // copy the stream data - str->reset(); - while ((c = str->getChar()) != EOF) { - writePSChar(c); - } - str->close(); - - // add newline and trailer to the end - writePSChar('\n'); - writePS("%-EOD-\n"); -#if OPI_SUPPORT - if (opi13Nest) { - writePS("%%EndData\n"); - } -#endif - - // delete encoders - if (useRLE || useASCII || inlineImg) { - delete str; - } - } - - if ((maskColors && colorMap && !inlineImg) || maskStr) { - writePS("pdfImClipEnd\n"); - } -} - -void PSOutputDev::dumpColorSpaceL2(GfxColorSpace *colorSpace, - GBool genXform, GBool updateColors) { - GfxCalGrayColorSpace *calGrayCS; - GfxCalRGBColorSpace *calRGBCS; - GfxLabColorSpace *labCS; - GfxIndexedColorSpace *indexedCS; - GfxSeparationColorSpace *separationCS; - GfxDeviceNColorSpace *deviceNCS; - GfxColorSpace *baseCS; - Guchar *lookup, *p; - double x[gfxColorMaxComps], y[gfxColorMaxComps]; - GfxColor color; - GfxCMYK cmyk; - Function *func; - int n, numComps, numAltComps; - int byte; - int i, j, k; - - switch (colorSpace->getMode()) { - - case csDeviceGray: - writePS("/DeviceGray"); - if (genXform) { - writePS(" {}"); - } - if (updateColors) { - processColors |= psProcessBlack; - } - break; - - case csCalGray: - calGrayCS = (GfxCalGrayColorSpace *)colorSpace; - writePS("[/CIEBasedA <<\n"); - writePSFmt(" /DecodeA {%g exp} bind\n", calGrayCS->getGamma()); - writePSFmt(" /MatrixA [%g %g %g]\n", - calGrayCS->getWhiteX(), calGrayCS->getWhiteY(), - calGrayCS->getWhiteZ()); - writePSFmt(" /WhitePoint [%g %g %g]\n", - calGrayCS->getWhiteX(), calGrayCS->getWhiteY(), - calGrayCS->getWhiteZ()); - writePSFmt(" /BlackPoint [%g %g %g]\n", - calGrayCS->getBlackX(), calGrayCS->getBlackY(), - calGrayCS->getBlackZ()); - writePS(">>]"); - if (genXform) { - writePS(" {}"); - } - if (updateColors) { - processColors |= psProcessBlack; - } - break; - - case csDeviceRGB: - writePS("/DeviceRGB"); - if (genXform) { - writePS(" {}"); - } - if (updateColors) { - processColors |= psProcessCMYK; - } - break; - - case csCalRGB: - calRGBCS = (GfxCalRGBColorSpace *)colorSpace; - writePS("[/CIEBasedABC <<\n"); - writePSFmt(" /DecodeABC [{%g exp} bind {%g exp} bind {%g exp} bind]\n", - calRGBCS->getGammaR(), calRGBCS->getGammaG(), - calRGBCS->getGammaB()); - writePSFmt(" /MatrixABC [%g %g %g %g %g %g %g %g %g]\n", - calRGBCS->getMatrix()[0], calRGBCS->getMatrix()[1], - calRGBCS->getMatrix()[2], calRGBCS->getMatrix()[3], - calRGBCS->getMatrix()[4], calRGBCS->getMatrix()[5], - calRGBCS->getMatrix()[6], calRGBCS->getMatrix()[7], - calRGBCS->getMatrix()[8]); - writePSFmt(" /WhitePoint [%g %g %g]\n", - calRGBCS->getWhiteX(), calRGBCS->getWhiteY(), - calRGBCS->getWhiteZ()); - writePSFmt(" /BlackPoint [%g %g %g]\n", - calRGBCS->getBlackX(), calRGBCS->getBlackY(), - calRGBCS->getBlackZ()); - writePS(">>]"); - if (genXform) { - writePS(" {}"); - } - if (updateColors) { - processColors |= psProcessCMYK; - } - break; - - case csDeviceCMYK: - writePS("/DeviceCMYK"); - if (genXform) { - writePS(" {}"); - } - if (updateColors) { - processColors |= psProcessCMYK; - } - break; - - case csLab: - labCS = (GfxLabColorSpace *)colorSpace; - writePS("[/CIEBasedABC <<\n"); - writePSFmt(" /RangeABC [0 100 %g %g %g %g]\n", - labCS->getAMin(), labCS->getAMax(), - labCS->getBMin(), labCS->getBMax()); - 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"); - writePSFmt(" {4 29 div sub 108 841 div mul } ifelse %g mul} bind\n", - labCS->getWhiteX()); - writePS(" {dup 6 29 div ge {dup dup mul mul}\n"); - writePSFmt(" {4 29 div sub 108 841 div mul } ifelse %g mul} bind\n", - labCS->getWhiteY()); - writePS(" {dup 6 29 div ge {dup dup mul mul}\n"); - writePSFmt(" {4 29 div sub 108 841 div mul } ifelse %g mul} bind]\n", - labCS->getWhiteZ()); - writePSFmt(" /WhitePoint [%g %g %g]\n", - labCS->getWhiteX(), labCS->getWhiteY(), labCS->getWhiteZ()); - writePSFmt(" /BlackPoint [%g %g %g]\n", - labCS->getBlackX(), labCS->getBlackY(), labCS->getBlackZ()); - writePS(">>]"); - if (genXform) { - writePS(" {}"); - } - if (updateColors) { - processColors |= psProcessCMYK; - } - break; - - case csICCBased: - // there is no transform function to the alternate color space, so - // we can use it directly - dumpColorSpaceL2(((GfxICCBasedColorSpace *)colorSpace)->getAlt(), - genXform, updateColors); - break; - - case csIndexed: - indexedCS = (GfxIndexedColorSpace *)colorSpace; - baseCS = indexedCS->getBase(); - writePS("[/Indexed "); - dumpColorSpaceL2(baseCS, gFalse, gFalse); - n = indexedCS->getIndexHigh(); - numComps = baseCS->getNComps(); - lookup = indexedCS->getLookup(); - writePSFmt(" %d <\n", n); - if (baseCS->getMode() == csDeviceN) { - func = ((GfxDeviceNColorSpace *)baseCS)->getTintTransformFunc(); - numAltComps = ((GfxDeviceNColorSpace *)baseCS)->getAlt()->getNComps(); - p = lookup; - for (i = 0; i <= n; i += 8) { - writePS(" "); - for (j = i; j < i+8 && j <= n; ++j) { - for (k = 0; k < numComps; ++k) { - x[k] = *p++ / 255.0; - } - func->transform(x, y); - for (k = 0; k < numAltComps; ++k) { - byte = (int)(y[k] * 255 + 0.5); - if (byte < 0) { - byte = 0; - } else if (byte > 255) { - byte = 255; - } - writePSFmt("%02x", byte); - } - if (updateColors) { - color.c[0] = dblToCol(j); - indexedCS->getCMYK(&color, &cmyk); - addProcessColor(colToDbl(cmyk.c), colToDbl(cmyk.m), - colToDbl(cmyk.y), colToDbl(cmyk.k)); - } - } - writePS("\n"); - } - } else { - for (i = 0; i <= n; i += 8) { - writePS(" "); - for (j = i; j < i+8 && j <= n; ++j) { - for (k = 0; k < numComps; ++k) { - writePSFmt("%02x", lookup[j * numComps + k]); - } - if (updateColors) { - color.c[0] = dblToCol(j); - indexedCS->getCMYK(&color, &cmyk); - addProcessColor(colToDbl(cmyk.c), colToDbl(cmyk.m), - colToDbl(cmyk.y), colToDbl(cmyk.k)); - } - } - writePS("\n"); - } - } - writePS(">]"); - if (genXform) { - writePS(" {}"); - } - break; - - case csSeparation: - separationCS = (GfxSeparationColorSpace *)colorSpace; - writePS("[/Separation /"); - writePSName(separationCS->getName()->getCString()); - writePS(" "); - dumpColorSpaceL2(separationCS->getAlt(), gFalse, gFalse); - writePS("\n"); - cvtFunction(separationCS->getFunc()); - writePS("]"); - if (genXform) { - writePS(" {}"); - } - if (updateColors) { - addCustomColor(separationCS); - } - break; - - case csDeviceN: - // DeviceN color spaces are a Level 3 PostScript feature. - deviceNCS = (GfxDeviceNColorSpace *)colorSpace; - dumpColorSpaceL2(deviceNCS->getAlt(), gFalse, updateColors); - if (genXform) { - writePS(" "); - cvtFunction(deviceNCS->getTintTransformFunc()); - } - break; - - case csPattern: - //~ unimplemented - break; - } -} - -#if OPI_SUPPORT -void PSOutputDev::opiBegin(GfxState *state, Dict *opiDict) { - Object dict; - - if (globalParams->getPSOPI()) { - 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)) { - writePSFmt("%%%%ImageFileName: %s\n", - obj2.getString()->getCString()); - obj2.free(); - } - obj1.free(); - - dict->lookup("MainImage", &obj1); - if (obj1.isString()) { - writePSFmt("%%%%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(); - writePSFmt("%%%%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(); - writePSFmt("%%%%ImageCropRect: %g %g %g %g\n", left, top, right, bottom); - } - obj1.free(); - - dict->lookup("Overprint", &obj1); - if (obj1.isBool()) { - writePSFmt("%%%%ImageOverprint: %s\n", obj1.getBool() ? "true" : "false"); - } - obj1.free(); - - dict->lookup("Inks", &obj1); - if (obj1.isName()) { - writePSFmt("%%%%ImageInks: %s\n", obj1.getName()); - } else if (obj1.isArray() && obj1.arrayGetLength() >= 1) { - obj1.arrayGet(0, &obj2); - if (obj2.isName()) { - writePSFmt("%%%%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()); - writePSFmt(" %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(); - writePSFmt("%%%%IncludedImageDimensions: %d %d\n", w, h); - } - obj1.free(); - - dict->lookup("IncludedImageQuality", &obj1); - if (obj1.isNum()) { - writePSFmt("%%%%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)) { - writePSFmt("%%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(); - writePSFmt("%%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()) { - writePSFmt("%%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()) { - writePSFmt("%%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(); - writePSFmt("%%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); - writePSFmt(" %d", obj2.getInt()); - obj2.free(); - } - } - writePS("\n"); - } - obj1.free(); - - dict->lookup("ID", &obj1); - if (obj1.isString()) { - writePSFmt("%%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(); - writePSFmt("%%ALDImageType: %d %d\n", samples, bits); - } - obj1.free(); - - dict->lookup("Overprint", &obj1); - if (obj1.isBool()) { - writePSFmt("%%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); - writePSFmt("%%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(); - writePSFmt("%%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(); - writePSFmt("%%ALDImageDimensions: %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()) { - writePSFmt("%%ALDImageTint: %g\n", obj1.getNum()); - } - obj1.free(); - - dict->lookup("Transparency", &obj1); - if (obj1.isBool()) { - writePSFmt("%%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 (rotate == 90) { - t = *x1; - *x1 = -*y1; - *y1 = t; - } else if (rotate == 180) { - *x1 = -*x1; - *y1 = -*y1; - } else if (rotate == 270) { - t = *x1; - *x1 = *y1; - *y1 = -t; - } - *x1 *= xScale; - *y1 *= yScale; -} - -void PSOutputDev::opiEnd(GfxState *state, Dict *opiDict) { - Object dict; - - if (globalParams->getPSOPI()) { - 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::type3D0(GfxState *state, double wx, double wy) { - writePSFmt("%g %g setcharwidth\n", wx, wy); - writePS("q\n"); -} - -void PSOutputDev::type3D1(GfxState *state, double wx, double wy, - double llx, double lly, double urx, double ury) { - t3WX = wx; - t3WY = wy; - t3LLX = llx; - t3LLY = lly; - t3URX = urx; - t3URY = ury; - t3String = new GString(); - writePS("q\n"); - t3Cacheable = gTrue; -} - -void PSOutputDev::psXObject(Stream *psStream, Stream *level1Stream) { - Stream *str; - int c; - - if ((level == psLevel1 || level == psLevel1Sep) && level1Stream) { - str = level1Stream; - } else { - str = psStream; - } - str->reset(); - while ((c = str->getChar()) != EOF) { - writePSChar(c); - } - str->close(); -} - -//~ can nextFunc be reset to 0 -- maybe at the start of each page? -//~ or maybe at the start of each color space / pattern? -void PSOutputDev::cvtFunction(Function *func) { - SampledFunction *func0; - ExponentialFunction *func2; - StitchingFunction *func3; - PostScriptFunction *func4; - int thisFunc, m, n, nSamples, i, j, k; - - switch (func->getType()) { - - case -1: // identity - writePS("{}\n"); - break; - - case 0: // sampled - func0 = (SampledFunction *)func; - thisFunc = nextFunc++; - m = func0->getInputSize(); - n = func0->getOutputSize(); - nSamples = n; - for (i = 0; i < m; ++i) { - nSamples *= func0->getSampleSize(i); - } - writePSFmt("/xpdfSamples%d [\n", thisFunc); - for (i = 0; i < nSamples; ++i) { - writePSFmt("%g\n", func0->getSamples()[i]); - } - writePS("] def\n"); - writePSFmt("{ %d array %d array %d 2 roll\n", 2*m, m, m+2); - // [e01] [efrac] x0 x1 ... xm-1 - for (i = m-1; i >= 0; --i) { - // [e01] [efrac] x0 x1 ... xi - writePSFmt("%g sub %g mul %g add\n", - func0->getDomainMin(i), - (func0->getEncodeMax(i) - func0->getEncodeMin(i)) / - (func0->getDomainMax(i) - func0->getDomainMin(i)), - func0->getEncodeMin(i)); - // [e01] [efrac] x0 x1 ... xi-1 xi' - writePSFmt("dup 0 lt { pop 0 } { dup %d gt { pop %d } if } ifelse\n", - func0->getSampleSize(i) - 1, func0->getSampleSize(i) - 1); - // [e01] [efrac] x0 x1 ... xi-1 xi' - writePS("dup floor cvi exch dup ceiling cvi exch 2 index sub\n"); - // [e01] [efrac] x0 x1 ... xi-1 floor(xi') ceiling(xi') xi'-floor(xi') - writePSFmt("%d index %d 3 2 roll put\n", i+3, i); - // [e01] [efrac] x0 x1 ... xi-1 floor(xi') ceiling(xi') - writePSFmt("%d index %d 3 2 roll put\n", i+3, 2*i+1); - // [e01] [efrac] x0 x1 ... xi-1 floor(xi') - writePSFmt("%d index %d 3 2 roll put\n", i+2, 2*i); - // [e01] [efrac] x0 x1 ... xi-1 - } - // [e01] [efrac] - for (i = 0; i < n; ++i) { - // [e01] [efrac] y(0) ... y(i-1) - for (j = 0; j < (1<<m); ++j) { - // [e01] [efrac] y(0) ... y(i-1) s(0) s(1) ... s(j-1) - writePSFmt("xpdfSamples%d\n", thisFunc); - k = m - 1; - writePSFmt("%d index %d get\n", i+j+2, 2 * k + ((j >> k) & 1)); - for (k = m - 2; k >= 0; --k) { - writePSFmt("%d mul %d index %d get add\n", - func0->getSampleSize(k), - i + j + 3, - 2 * k + ((j >> k) & 1)); - } - if (n > 1) { - writePSFmt("%d mul %d add ", n, i); - } - writePS("get\n"); - } - // [e01] [efrac] y(0) ... y(i-1) s(0) s(1) ... s(2^m-1) - for (j = 0; j < m; ++j) { - // [e01] [efrac] y(0) ... y(i-1) s(0) s(1) ... s(2^(m-j)-1) - for (k = 0; k < (1 << (m - j)); k += 2) { - // [e01] [efrac] y(0) ... y(i-1) <k/2 s' values> <2^(m-j)-k s values> - writePSFmt("%d index %d get dup\n", i + k/2 + (1 << (m-j)) - k, j); - writePS("3 2 roll mul exch 1 exch sub 3 2 roll mul add\n"); - writePSFmt("%d 1 roll\n", k/2 + (1 << m-j) - k - 1); - } - // [e01] [efrac] s'(0) s'(1) ... s(2^(m-j-1)-1) - } - // [e01] [efrac] y(0) ... y(i-1) s - writePSFmt("%g mul %g add\n", - func0->getDecodeMax(i) - func0->getDecodeMin(i), - func0->getDecodeMin(i)); - writePSFmt("dup %g lt { pop %g } { dup %g gt { pop %g } if } ifelse\n", - func0->getRangeMin(i), func0->getRangeMin(i), - func0->getRangeMax(i), func0->getRangeMax(i)); - // [e01] [efrac] y(0) ... y(i-1) y(i) - } - // [e01] [efrac] y(0) ... y(n-1) - writePSFmt("%d %d roll pop pop }\n", n+2, n); - break; - - case 2: // exponential - func2 = (ExponentialFunction *)func; - n = func2->getOutputSize(); - writePSFmt("{ dup %g lt { pop %g } { dup %g gt { pop %g } if } ifelse\n", - func2->getDomainMin(0), func2->getDomainMin(0), - func2->getDomainMax(0), func2->getDomainMax(0)); - // x - for (i = 0; i < n; ++i) { - // x y(0) .. y(i-1) - writePSFmt("%d index %g exp %g mul %g add\n", - i, func2->getE(), func2->getC1()[i] - func2->getC0()[i], - func2->getC0()[i]); - if (func2->getHasRange()) { - writePSFmt("dup %g lt { pop %g } { dup %g gt { pop %g } if } ifelse\n", - func2->getRangeMin(i), func2->getRangeMin(i), - func2->getRangeMax(i), func2->getRangeMax(i)); - } - } - // x y(0) .. y(n-1) - writePSFmt("%d %d roll pop }\n", n+1, n); - break; - - case 3: // stitching - func3 = (StitchingFunction *)func; - thisFunc = nextFunc++; - for (i = 0; i < func3->getNumFuncs(); ++i) { - cvtFunction(func3->getFunc(i)); - writePSFmt("/xpdfFunc%d_%d exch def\n", thisFunc, i); - } - writePSFmt("{ dup %g lt { pop %g } { dup %g gt { pop %g } if } ifelse\n", - func3->getDomainMin(0), func3->getDomainMin(0), - func3->getDomainMax(0), func3->getDomainMax(0)); - for (i = 0; i < func3->getNumFuncs() - 1; ++i) { - writePSFmt("dup %g lt { %g sub %g mul %g add xpdfFunc%d_%d } {\n", - func3->getBounds()[i+1], - func3->getBounds()[i], - (func3->getEncode()[2*i+1] - func3->getEncode()[2*i]) / - (func3->getBounds()[i+1] - func3->getBounds()[i]), - func3->getEncode()[2*i], - thisFunc, i); - } - writePSFmt("%g sub %g mul %g add xpdfFunc%d_%d\n", - func3->getBounds()[i], - (func3->getEncode()[2*i+1] - func3->getEncode()[2*i]) / - (func3->getBounds()[i+1] - func3->getBounds()[i]), - func3->getEncode()[2*i], - thisFunc, i); - for (i = 0; i < func3->getNumFuncs() - 1; ++i) { - writePS("} ifelse\n"); - } - writePS("}\n"); - break; - - case 4: // PostScript - func4 = (PostScriptFunction *)func; - writePS(func4->getCodeString()->getCString()); - writePS("\n"); - break; - } -} - -void PSOutputDev::writePSChar(char c) { - if (t3String) { - t3String->append(c); - } else { - (*outputFunc)(outputStream, &c, 1); - } -} - -void PSOutputDev::writePS(char *s) { - if (t3String) { - t3String->append(s); - } else { - (*outputFunc)(outputStream, s, strlen(s)); - } -} - -void PSOutputDev::writePSFmt(const char *fmt, ...) { - va_list args; - char buf[512]; - - va_start(args, fmt); - vsprintf(buf, fmt, args); - va_end(args); - if (t3String) { - t3String->append(buf); - } else { - (*outputFunc)(outputStream, buf, strlen(buf)); - } -} - -void PSOutputDev::writePSString(GString *s) { - Guchar *p; - int n, line; - char buf[8]; - - writePSChar('('); - line = 1; - for (p = (Guchar *)s->getCString(), n = s->getLength(); n; ++p, --n) { - if (line >= 64) { - writePSChar('\\'); - writePSChar('\n'); - line = 0; - } - if (*p == '(' || *p == ')' || *p == '\\') { - writePSChar('\\'); - writePSChar((char)*p); - line += 2; - } else if (*p < 0x20 || *p >= 0x80) { - sprintf(buf, "\\%03o", *p); - writePS(buf); - line += 4; - } else { - writePSChar((char)*p); - ++line; - } - } - writePSChar(')'); -} - -void PSOutputDev::writePSName(char *s) { - char *p; - char c; - - p = s; - while ((c = *p++)) { - if (c <= (char)0x20 || c >= (char)0x7f || - c == '(' || c == ')' || c == '<' || c == '>' || - c == '[' || c == ']' || c == '{' || c == '}' || - c == '/' || c == '%') { - writePSFmt("#%02x", c & 0xff); - } else { - writePSChar(c); - } - } -} - -GString *PSOutputDev::filterPSName(GString *name) { - GString *name2; - char buf[8]; - int i; - char c; - - name2 = new GString(); - - // ghostscript chokes on names that begin with out-of-limits - // numbers, e.g., 1e4foo is handled correctly (as a name), but - // 1e999foo generates a limitcheck error - c = name->getChar(0); - if (c >= '0' && c <= '9') { - name2->append('f'); - } - - for (i = 0; i < name->getLength(); ++i) { - c = name->getChar(i); - if (c <= (char)0x20 || c >= (char)0x7f || - c == '(' || c == ')' || c == '<' || c == '>' || - c == '[' || c == ']' || c == '{' || c == '}' || - c == '/' || c == '%') { - sprintf(buf, "#%02x", c & 0xff); - name2->append(buf); - } else { - name2->append(c); - } - } - return name2; -} - -GBool /* O - gTrue if selected, gFalse otherwise */ -PSOutputDev::checkRange(int page) /* I - Page number */ -{ - const char *range; /* Pointer into range string */ - int lower, upper; /* Lower and upper page numbers */ - - - if (pageRanges == NULL) - return (gTrue); /* 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 & 255)) - upper = 65535; - else - upper = strtol(range, (char **)&range, 10); - } - else - upper = lower; - } - - if (page >= lower && page <= upper) - return (gTrue); - - if (*range == ',') - range ++; - else - break; - } - - return (gFalse); -} diff --git a/pdftops/PSOutputDev.h b/pdftops/PSOutputDev.h deleted file mode 100644 index 4cd3fd276..000000000 --- a/pdftops/PSOutputDev.h +++ /dev/null @@ -1,354 +0,0 @@ -//======================================================================== -// -// PSOutputDev.h -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef PSOUTPUTDEV_H -#define PSOUTPUTDEV_H - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include <stddef.h> -#include "config.h" -#include "Object.h" -#include "GlobalParams.h" -#include "OutputDev.h" - -class Function; -class GfxPath; -class GfxFont; -class GfxColorSpace; -class GfxSeparationColorSpace; -class PDFRectangle; -struct PSFont16Enc; -class PSOutCustomColor; - -//------------------------------------------------------------------------ -// PSOutputDev -//------------------------------------------------------------------------ - -enum PSOutMode { - psModePS, - psModeEPS, - psModeForm -}; - -enum PSFileType { - psFile, // write to file - psPipe, // write to pipe - psStdout, // write to stdout - psGeneric // write to a generic stream -}; - -typedef void (*PSOutputFunc)(void *stream, char *data, int len); - -class PSOutputDev: public OutputDev { -public: - - // Open a PostScript output file, and write the prolog. - PSOutputDev(char *fileName, XRef *xrefA, Catalog *catalog, - int firstPage, int lastPage, PSOutMode modeA, - int imgLLXA = 0, int imgLLYA = 0, - int imgURXA = 0, int imgURYA = 0, - GBool manualCtrlA = gFalse, - const char *pageRangesA = (const char *)0); - - // Open a PSOutputDev that will write to a generic stream. - PSOutputDev(PSOutputFunc outputFuncA, void *outputStreamA, - XRef *xrefA, Catalog *catalog, - int firstPage, int lastPage, PSOutMode modeA, - int imgLLXA = 0, int imgLLYA = 0, - int imgURXA = 0, int imgURYA = 0, - GBool manualCtrlA = gFalse, - const char *pageRangesA = (const char *)0); - - // 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; } - - // Does this device use tilingPatternFill()? If this returns false, - // tiling pattern fills will be reduced to a series of other drawing - // operations. - virtual GBool useTilingPatternFill() { return gTrue; } - - // Does this device use functionShadedFill(), axialShadedFill(), and - // radialShadedFill()? If this returns false, these shaded fills - // will be reduced to a series of other drawing operations. - virtual GBool useShadedFills() - { return level == psLevel2 || level == psLevel3; } - - // Does this device use beginType3Char/endType3Char? Otherwise, - // text in Type 3 fonts will be drawn with drawChar/drawString. - virtual GBool interpretType3Chars() { return gFalse; } - - //----- header/trailer (used only if manualCtrl is true) - - // Write the document-level header. - void writeHeader(int firstPage, int lastPage, - PDFRectangle *mediaBox, PDFRectangle *cropBox, - int pageRotate); - - // Write the Xpdf procset. - void writeXpdfProcset(); - - // Write the document-level setup. - void writeDocSetup(Catalog *catalog, int firstPage, int lastPage); - - // Write the trailer for the current page. - void writePageTrailer(); - - // Write the document trailer. - void writeTrailer(); - - //----- initialization and control - - // Start a page. - virtual GBool 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 updateFillColorSpace(GfxState *state); - virtual void updateStrokeColorSpace(GfxState *state); - virtual void updateFillColor(GfxState *state); - virtual void updateStrokeColor(GfxState *state); - virtual void updateFillOverprint(GfxState *state); - virtual void updateStrokeOverprint(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); - virtual void tilingPatternFill(GfxState *state, Object *str, - int paintType, Dict *resDict, - double *mat, double *bbox, - int x0, int y0, int x1, int y1, - double xStep, double yStep); - virtual void functionShadedFill(GfxState *state, - GfxFunctionShading *shading); - virtual void axialShadedFill(GfxState *state, GfxAxialShading *shading); - virtual void radialShadedFill(GfxState *state, GfxRadialShading *shading); - - //----- path clipping - virtual void clip(GfxState *state); - virtual void eoClip(GfxState *state); - - //----- text drawing - virtual void drawString(GfxState *state, GString *s); - virtual void endTextObject(GfxState *state); - - //----- image drawing - virtual void drawImageMask(GfxState *state, Object *ref, Stream *str, - int width, int height, GBool invert, - GBool inlineImg); - virtual void drawImage(GfxState *state, Object *ref, Stream *str, - int width, int height, GfxImageColorMap *colorMap, - int *maskColors, GBool inlineImg); - virtual void drawMaskedImage(GfxState *state, Object *ref, Stream *str, - int width, int height, - GfxImageColorMap *colorMap, - Stream *maskStr, int maskWidth, int maskHeight, - GBool maskInvert); - -#if OPI_SUPPORT - //----- OPI functions - virtual void opiBegin(GfxState *state, Dict *opiDict); - virtual void opiEnd(GfxState *state, Dict *opiDict); -#endif - - //----- Type 3 font operators - virtual void type3D0(GfxState *state, double wx, double wy); - virtual void type3D1(GfxState *state, double wx, double wy, - double llx, double lly, double urx, double ury); - - //----- PostScript XObjects - virtual void psXObject(Stream *psStream, Stream *level1Stream); - - //----- miscellaneous - void setOffset(double x, double y) - { tx0 = x; ty0 = y; } - void setScale(double x, double y) - { xScale0 = x; yScale0 = y; } - void setRotate(int rotateA) - { rotate0 = rotateA; } - void setClip(double llx, double lly, double urx, double ury) - { clipLLX0 = llx; clipLLY0 = lly; clipURX0 = urx; clipURY0 = ury; } - void setUnderlayCbk(void (*cbk)(PSOutputDev *psOut, void *data), - void *data) - { underlayCbk = cbk; underlayCbkData = data; } - void setOverlayCbk(void (*cbk)(PSOutputDev *psOut, void *data), - void *data) - { overlayCbk = cbk; overlayCbkData = data; } - -private: - - void init(PSOutputFunc outputFuncA, void *outputStreamA, - PSFileType fileTypeA, XRef *xrefA, Catalog *catalog, - int firstPage, int lastPage, PSOutMode modeA, - int imgLLXA, int imgLLYA, int imgURXA, int imgURYA, - GBool manualCtrlA, const char *pageRangesA); - void setupResources(Dict *resDict); - void setupFonts(Dict *resDict); - void setupFont(GfxFont *font, Dict *parentResDict); - void setupEmbeddedType1Font(Ref *id, GString *psName); - void setupExternalType1Font(GString *fileName, GString *psName); - void setupEmbeddedType1CFont(GfxFont *font, Ref *id, GString *psName); - void setupEmbeddedTrueTypeFont(GfxFont *font, Ref *id, GString *psName); - void setupExternalTrueTypeFont(GfxFont *font, GString *psName); - void setupEmbeddedCIDType0Font(GfxFont *font, Ref *id, GString *psName); - void setupEmbeddedCIDTrueTypeFont(GfxFont *font, Ref *id, GString *psName, - GBool needVerticalMetrics); - void setupType3Font(GfxFont *font, GString *psName, Dict *parentResDict); - void setupImages(Dict *resDict); - void setupImage(Ref id, Stream *str); - void addProcessColor(double c, double m, double y, double k); - void addCustomColor(GfxSeparationColorSpace *sepCS); - void doPath(GfxPath *path); - void doImageL1(Object *ref, GfxImageColorMap *colorMap, - GBool invert, GBool inlineImg, - Stream *str, int width, int height, int len); - void doImageL1Sep(GfxImageColorMap *colorMap, - GBool invert, GBool inlineImg, - Stream *str, int width, int height, int len); - void doImageL2(Object *ref, GfxImageColorMap *colorMap, - GBool invert, GBool inlineImg, - Stream *str, int width, int height, int len, - int *maskColors, Stream *maskStr, - int maskWidth, int maskHeight, GBool maskInvert); - void dumpColorSpaceL2(GfxColorSpace *colorSpace, - GBool genXform, GBool updateColors); -#if OPI_SUPPORT - 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); -#endif - void cvtFunction(Function *func); - void writePSChar(char c); - void writePS(char *s); - void writePSFmt(const char *fmt, ...); - void writePSString(GString *s); - void writePSName(char *s); - GString *filterPSName(GString *name); - GBool checkRange(int page); - - PSLevel level; // PostScript level (1, 2, separation) - PSOutMode mode; // PostScript mode (PS, EPS, form) - int paperWidth; // width of paper, in pts - int paperHeight; // height of paper, in pts - int imgLLX, imgLLY, // imageable area, in pts - imgURX, imgURY; - - PSOutputFunc outputFunc; - void *outputStream; - PSFileType fileType; // file / pipe / stdout - GBool manualCtrl; - int seqPage; // current sequential page number - void (*underlayCbk)(PSOutputDev *psOut, void *data); - void *underlayCbkData; - void (*overlayCbk)(PSOutputDev *psOut, void *data); - void *overlayCbkData; - - XRef *xref; // the xref table for this PDF file - - 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 - int nextTrueTypeNum; // next unique number to append to a TrueType - // font name - PSFont16Enc *font16Enc; // encodings for substitute 16-bit fonts - int font16EncLen; // number of entries in font16Enc array - int font16EncSize; // size of font16Enc array - GList *xobjStack; // stack of XObject dicts currently being - // processed - int numSaves; // current number of gsaves - int numTilingPatterns; // current number of nested tiling patterns - int nextFunc; // next unique number to use for a function - - double tx0, ty0; // global translation - double xScale0, yScale0; // global scaling - int rotate0; // rotation angle (0, 90, 180, 270) - double clipLLX0, clipLLY0, - clipURX0, clipURY0; - double tx, ty; // global translation for current page - double xScale, yScale; // global scaling for current page - int rotate; // rotation angle for current page - double epsX1, epsY1, // EPS bounding box (unrotated) - epsX2, epsY2; - - GString *embFontList; // resource comments for embedded fonts - - int processColors; // used process colors - PSOutCustomColor // used custom colors - *customColors; - - GBool haveTextClip; // set if text has been drawn with a - // clipping render mode - - GBool inType3Char; // inside a Type 3 CharProc - GString *t3String; // Type 3 content string - double t3WX, t3WY, // Type 3 character parameters - t3LLX, t3LLY, t3URX, t3URY; - GBool t3Cacheable; // cleared if char is not cacheable - -#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? - const char *pageRanges; // page ranges to render - - friend class WinPDFPrinter; -}; - -#endif diff --git a/pdftops/PSTokenizer.cxx b/pdftops/PSTokenizer.cxx deleted file mode 100644 index 834b0ca2d..000000000 --- a/pdftops/PSTokenizer.cxx +++ /dev/null @@ -1,135 +0,0 @@ -//======================================================================== -// -// PSTokenizer.cc -// -// Copyright 2002-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include <stdio.h> -#include <stdlib.h> -#include "PSTokenizer.h" - -//------------------------------------------------------------------------ - -// A '1' in this array means the character is white space. A '1' or -// '2' means the character ends a name or command. -static char specialChars[256] = { - 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 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, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, // 2x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 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, 2, 0, 2, 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, 2, 0, 2, 0, 0, // 7x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ax - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // bx - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // cx - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // dx - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ex - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // fx -}; - -//------------------------------------------------------------------------ - -PSTokenizer::PSTokenizer(int (*getCharFuncA)(void *), void *dataA) { - getCharFunc = getCharFuncA; - data = dataA; - charBuf = -1; -} - -PSTokenizer::~PSTokenizer() { -} - -GBool PSTokenizer::getToken(char *buf, int size, int *length) { - GBool comment, backslash; - int c; - int i; - - // skip whitespace and comments - comment = gFalse; - while (1) { - if ((c = getChar()) == EOF) { - buf[0] = '\0'; - *length = 0; - return gFalse; - } - if (comment) { - if (c == '\x0a' || c == '\x0d') { - comment = gFalse; - } - } else if (c == '%') { - comment = gTrue; - } else if (specialChars[c] != 1) { - break; - } - } - - // read a token - i = 0; - buf[i++] = c; - if (c == '(') { - backslash = gFalse; - while ((c = lookChar()) != EOF) { - if (i < size - 1) { - buf[i++] = c; - } - getChar(); - if (c == '\\') { - backslash = gTrue; - } else if (!backslash && c == ')') { - break; - } else { - backslash = gFalse; - } - } - } else if (c == '<') { - while ((c = lookChar()) != EOF) { - getChar(); - if (i < size - 1) { - buf[i++] = c; - } - if (c == '>') { - break; - } - } - } else if (c != '[' && c != ']') { - while ((c = lookChar()) != EOF && !specialChars[c]) { - getChar(); - if (i < size - 1) { - buf[i++] = c; - } - } - } - buf[i] = '\0'; - *length = i; - - return gTrue; -} - -int PSTokenizer::lookChar() { - if (charBuf < 0) { - charBuf = (*getCharFunc)(data); - } - return charBuf; -} - -int PSTokenizer::getChar() { - int c; - - if (charBuf < 0) { - charBuf = (*getCharFunc)(data); - } - c = charBuf; - charBuf = -1; - return c; -} diff --git a/pdftops/PSTokenizer.h b/pdftops/PSTokenizer.h deleted file mode 100644 index d8d347618..000000000 --- a/pdftops/PSTokenizer.h +++ /dev/null @@ -1,41 +0,0 @@ -//======================================================================== -// -// PSTokenizer.h -// -// Copyright 2002-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef PSTOKENIZER_H -#define PSTOKENIZER_H - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "gtypes.h" - -//------------------------------------------------------------------------ - -class PSTokenizer { -public: - - PSTokenizer(int (*getCharFuncA)(void *), void *dataA); - ~PSTokenizer(); - - // Get the next PostScript token. Returns false at end-of-stream. - GBool getToken(char *buf, int size, int *length); - -private: - - int lookChar(); - int getChar(); - - int (*getCharFunc)(void *); - void *data; - int charBuf; -}; - -#endif diff --git a/pdftops/Page.cxx b/pdftops/Page.cxx deleted file mode 100644 index ab0a21ff7..000000000 --- a/pdftops/Page.cxx +++ /dev/null @@ -1,367 +0,0 @@ -//======================================================================== -// -// Page.cc -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include <stddef.h> -#include "GlobalParams.h" -#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 "GfxState.h" -#include "Annot.h" -#endif -#include "Error.h" -#include "Page.h" - -//------------------------------------------------------------------------ -// PageAttrs -//------------------------------------------------------------------------ - -PageAttrs::PageAttrs(PageAttrs *attrs, Dict *dict) { - Object obj1; - - // get old/default values - if (attrs) { - mediaBox = attrs->mediaBox; - cropBox = attrs->cropBox; - haveCropBox = attrs->haveCropBox; - 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 - mediaBox.x1 = 0; - mediaBox.y1 = 0; - mediaBox.x2 = 612; - mediaBox.y2 = 792; - cropBox.x1 = cropBox.y1 = cropBox.x2 = cropBox.y2 = 0; - haveCropBox = gFalse; - rotate = 0; - resources.initNull(); - } - - // media box - readBox(dict, "MediaBox", &mediaBox); - - // crop box - if (readBox(dict, "CropBox", &cropBox)) { - haveCropBox = gTrue; - } - if (!haveCropBox) { - cropBox = mediaBox; - } - - // other boxes - bleedBox = cropBox; - readBox(dict, "BleedBox", &bleedBox); - trimBox = cropBox; - readBox(dict, "TrimBox", &trimBox); - artBox = cropBox; - readBox(dict, "ArtBox", &artBox); - - // rotate - dict->lookup("Rotate", &obj1); - if (obj1.isInt()) { - rotate = obj1.getInt(); - } - obj1.free(); - while (rotate < 0) { - rotate += 360; - } - while (rotate >= 360) { - rotate -= 360; - } - - // misc attributes - dict->lookup("LastModified", &lastModified); - dict->lookup("BoxColorInfo", &boxColorInfo); - dict->lookup("Group", &group); - dict->lookup("Metadata", &metadata); - dict->lookup("PieceInfo", &pieceInfo); - dict->lookup("SeparationInfo", &separationInfo); - - // resource dictionary - dict->lookup("Resources", &obj1); - if (obj1.isDict()) { - resources.free(); - obj1.copy(&resources); - } - obj1.free(); -} - -PageAttrs::~PageAttrs() { - lastModified.free(); - boxColorInfo.free(); - group.free(); - metadata.free(); - pieceInfo.free(); - separationInfo.free(); - resources.free(); -} - -GBool PageAttrs::readBox(Dict *dict, char *key, PDFRectangle *box) { - PDFRectangle tmp; - double t; - Object obj1, obj2; - GBool ok; - - dict->lookup(key, &obj1); - if (obj1.isArray() && obj1.arrayGetLength() == 4) { - ok = gTrue; - obj1.arrayGet(0, &obj2); - if (obj2.isNum()) { - tmp.x1 = obj2.getNum(); - } else { - ok = gFalse; - } - obj2.free(); - obj1.arrayGet(1, &obj2); - if (obj2.isNum()) { - tmp.y1 = obj2.getNum(); - } else { - ok = gFalse; - } - obj2.free(); - obj1.arrayGet(2, &obj2); - if (obj2.isNum()) { - tmp.x2 = obj2.getNum(); - } else { - ok = gFalse; - } - obj2.free(); - obj1.arrayGet(3, &obj2); - if (obj2.isNum()) { - tmp.y2 = obj2.getNum(); - } else { - ok = gFalse; - } - obj2.free(); - if (ok) { - if (tmp.x1 > tmp.x2) { - t = tmp.x1; tmp.x1 = tmp.x2; tmp.x2 = t; - } - if (tmp.y1 > tmp.y2) { - t = tmp.y1; tmp.y1 = tmp.y2; tmp.y2 = t; - } - *box = tmp; - } - } else { - ok = gFalse; - } - obj1.free(); - return ok; -} - -//------------------------------------------------------------------------ -// Page -//------------------------------------------------------------------------ - -Page::Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA) { - ok = gTrue; - xref = xrefA; - num = numA; - - // get attributes - attrs = attrsA; - - // 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, double hDPI, double vDPI, - int rotate, GBool useMediaBox, GBool crop, - Links *links, Catalog *catalog, - GBool (*abortCheckCbk)(void *data), - void *abortCheckCbkData) { - displaySlice(out, hDPI, vDPI, rotate, useMediaBox, crop, - -1, -1, -1, -1, links, catalog, - abortCheckCbk, abortCheckCbkData); -} - -void Page::displaySlice(OutputDev *out, double hDPI, double vDPI, - int rotate, GBool useMediaBox, GBool crop, - int sliceX, int sliceY, int sliceW, int sliceH, - Links *links, Catalog *catalog, - GBool (*abortCheckCbk)(void *data), - void *abortCheckCbkData) { -#ifndef PDF_PARSER_ONLY - PDFRectangle *mediaBox, *cropBox, *baseBox; - PDFRectangle box; - Gfx *gfx; - Object obj; - Link *link; - Annots *annotList; - double kx, ky; - int i; - - rotate += getRotate(); - if (rotate >= 360) { - rotate -= 360; - } else if (rotate < 0) { - rotate += 360; - } - - mediaBox = getMediaBox(); - cropBox = getCropBox(); - if (sliceW >= 0 && sliceH >= 0) { - baseBox = useMediaBox ? mediaBox : cropBox; - kx = 72.0 / hDPI; - ky = 72.0 / vDPI; - if (rotate == 90) { - if (out->upsideDown()) { - box.x1 = baseBox->x1 + ky * sliceY; - box.x2 = baseBox->x1 + ky * (sliceY + sliceH); - } else { - box.x1 = baseBox->x2 - ky * (sliceY + sliceH); - box.x2 = baseBox->x2 - ky * sliceY; - } - box.y1 = baseBox->y1 + kx * sliceX; - box.y2 = baseBox->y1 + kx * (sliceX + sliceW); - } else if (rotate == 180) { - box.x1 = baseBox->x2 - kx * (sliceX + sliceW); - box.x2 = baseBox->x2 - kx * sliceX; - if (out->upsideDown()) { - box.y1 = baseBox->y1 + ky * sliceY; - box.y2 = baseBox->y1 + ky * (sliceY + sliceH); - } else { - box.y1 = baseBox->y2 - ky * (sliceY + sliceH); - box.y2 = baseBox->y2 - ky * sliceY; - } - } else if (rotate == 270) { - if (out->upsideDown()) { - box.x1 = baseBox->x2 - ky * (sliceY + sliceH); - box.x2 = baseBox->x2 - ky * sliceY; - } else { - box.x1 = baseBox->x1 + ky * sliceY; - box.x2 = baseBox->x1 + ky * (sliceY + sliceH); - } - box.y1 = baseBox->y2 - kx * (sliceX + sliceW); - box.y2 = baseBox->y2 - kx * sliceX; - } else { - box.x1 = baseBox->x1 + kx * sliceX; - box.x2 = baseBox->x1 + kx * (sliceX + sliceW); - if (out->upsideDown()) { - box.y1 = baseBox->y2 - ky * (sliceY + sliceH); - box.y2 = baseBox->y2 - ky * sliceY; - } else { - box.y1 = baseBox->y1 + ky * sliceY; - box.y2 = baseBox->y1 + ky * (sliceY + sliceH); - } - } - } else if (useMediaBox) { - box = *mediaBox; - } else { - box = *cropBox; - crop = gFalse; - } - - if (globalParams->getPrintCommands()) { - printf("***** MediaBox = ll:%g,%g ur:%g,%g\n", - mediaBox->x1, mediaBox->y1, mediaBox->x2, mediaBox->y2); - printf("***** CropBox = ll:%g,%g ur:%g,%g\n", - cropBox->x1, cropBox->y1, cropBox->x2, cropBox->y2); - printf("***** Rotate = %d\n", attrs->getRotate()); - } - - gfx = new Gfx(xref, out, num, attrs->getResourceDict(), - hDPI, vDPI, &box, crop ? cropBox : (PDFRectangle *)NULL, - rotate, abortCheckCbk, abortCheckCbkData); - contents.fetch(xref, &obj); - if (!obj.isNull()) { - gfx->saveState(); - gfx->display(&obj); - gfx->restoreState(); - } - obj.free(); - - // draw links - if (links) { - gfx->saveState(); - for (i = 0; i < links->getNumLinks(); ++i) { - link = links->getLink(i); - out->drawLink(link, catalog); - } - gfx->restoreState(); - out->dump(); - } - - // draw non-link annotations - annotList = new Annots(xref, catalog, annots.fetch(xref, &obj)); - obj.free(); - if (annotList->getNumAnnots() > 0) { - if (globalParams->getPrintCommands()) { - printf("***** Annotations\n"); - } - for (i = 0; i < annotList->getNumAnnots(); ++i) { - annotList->getAnnot(i)->draw(gfx); - } - out->dump(); - } - delete annotList; - - delete gfx; -#endif -} - -void Page::getDefaultCTM(double *ctm, double hDPI, double vDPI, - int rotate, GBool upsideDown) { - GfxState *state; - int i; - - rotate += getRotate(); - if (rotate >= 360) { - rotate -= 360; - } else if (rotate < 0) { - rotate += 360; - } - state = new GfxState(hDPI, vDPI, getMediaBox(), rotate, upsideDown); - for (i = 0; i < 6; ++i) { - ctm[i] = state->getCTM()[i]; - } - delete state; -} diff --git a/pdftops/Page.h b/pdftops/Page.h deleted file mode 100644 index 3177912f4..000000000 --- a/pdftops/Page.h +++ /dev/null @@ -1,175 +0,0 @@ -//======================================================================== -// -// Page.h -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef PAGE_H -#define PAGE_H - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "Object.h" - -class Dict; -class XRef; -class OutputDev; -class Links; -class Catalog; - -//------------------------------------------------------------------------ - -class PDFRectangle { -public: - double x1, y1, x2, y2; - - PDFRectangle() { x1 = y1 = x2 = y2 = 0; } - PDFRectangle(double x1A, double y1A, double x2A, double y2A) - { x1 = x1A; y1 = y1A; x2 = x2A; y2 = y2A; } - GBool isValid() { return x1 != 0 || y1 != 0 || x2 != 0 || y2 != 0; } -}; - -//------------------------------------------------------------------------ -// PageAttrs -//------------------------------------------------------------------------ - -class PageAttrs { -public: - - // Construct a new PageAttrs object by merging a dictionary - // (of type Pages or Page) into another PageAttrs object. If - // <attrs> is NULL, uses defaults. - PageAttrs(PageAttrs *attrs, Dict *dict); - - // Destructor. - ~PageAttrs(); - - // Accessors. - PDFRectangle *getMediaBox() { return &mediaBox; } - PDFRectangle *getCropBox() { return &cropBox; } - GBool isCropped() { return haveCropBox; } - PDFRectangle *getBleedBox() { return &bleedBox; } - PDFRectangle *getTrimBox() { return &trimBox; } - PDFRectangle *getArtBox() { return &artBox; } - int getRotate() { return rotate; } - GString *getLastModified() - { return lastModified.isString() - ? lastModified.getString() : (GString *)NULL; } - Dict *getBoxColorInfo() - { return boxColorInfo.isDict() ? boxColorInfo.getDict() : (Dict *)NULL; } - Dict *getGroup() - { return group.isDict() ? group.getDict() : (Dict *)NULL; } - Stream *getMetadata() - { return metadata.isStream() ? metadata.getStream() : (Stream *)NULL; } - Dict *getPieceInfo() - { return pieceInfo.isDict() ? pieceInfo.getDict() : (Dict *)NULL; } - Dict *getSeparationInfo() - { return separationInfo.isDict() - ? separationInfo.getDict() : (Dict *)NULL; } - Dict *getResourceDict() - { return resources.isDict() ? resources.getDict() : (Dict *)NULL; } - -private: - - GBool readBox(Dict *dict, char *key, PDFRectangle *box); - - PDFRectangle mediaBox; - PDFRectangle cropBox; - GBool haveCropBox; - PDFRectangle bleedBox; - PDFRectangle trimBox; - PDFRectangle artBox; - int rotate; - Object lastModified; - Object boxColorInfo; - Object group; - Object metadata; - Object pieceInfo; - Object separationInfo; - Object resources; -}; - -//------------------------------------------------------------------------ -// Page -//------------------------------------------------------------------------ - -class Page { -public: - - // Constructor. - Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA); - - // Destructor. - ~Page(); - - // Is page valid? - GBool isOk() { return ok; } - - // Get page parameters. - PDFRectangle *getMediaBox() { return attrs->getMediaBox(); } - PDFRectangle *getCropBox() { return attrs->getCropBox(); } - GBool isCropped() { return attrs->isCropped(); } - double getMediaWidth() - { return attrs->getMediaBox()->x2 - attrs->getMediaBox()->x1; } - double getMediaHeight() - { return attrs->getMediaBox()->y2 - attrs->getMediaBox()->y1; } - double getCropWidth() - { return attrs->getCropBox()->x2 - attrs->getCropBox()->x1; } - double getCropHeight() - { return attrs->getCropBox()->y2 - attrs->getCropBox()->y1; } - PDFRectangle *getBleedBox() { return attrs->getBleedBox(); } - PDFRectangle *getTrimBox() { return attrs->getTrimBox(); } - PDFRectangle *getArtBox() { return attrs->getArtBox(); } - int getRotate() { return attrs->getRotate(); } - GString *getLastModified() { return attrs->getLastModified(); } - Dict *getBoxColorInfo() { return attrs->getBoxColorInfo(); } - Dict *getGroup() { return attrs->getGroup(); } - Stream *getMetadata() { return attrs->getMetadata(); } - Dict *getPieceInfo() { return attrs->getPieceInfo(); } - Dict *getSeparationInfo() { return attrs->getSeparationInfo(); } - - // Get resource dictionary. - Dict *getResourceDict() { return attrs->getResourceDict(); } - - // Get annotations array. - Object *getAnnots(Object *obj) { return annots.fetch(xref, obj); } - - // Get contents. - Object *getContents(Object *obj) { return contents.fetch(xref, obj); } - - // Display a page. - void display(OutputDev *out, double hDPI, double vDPI, - int rotate, GBool useMediaBox, GBool crop, - Links *links, Catalog *catalog, - GBool (*abortCheckCbk)(void *data) = NULL, - void *abortCheckCbkData = NULL); - - // Display part of a page. - void displaySlice(OutputDev *out, double hDPI, double vDPI, - int rotate, GBool useMediaBox, GBool crop, - int sliceX, int sliceY, int sliceW, int sliceH, - Links *links, Catalog *catalog, - GBool (*abortCheckCbk)(void *data) = NULL, - void *abortCheckCbkData = NULL); - - // Get the page's default CTM. - void getDefaultCTM(double *ctm, double hDPI, double vDPI, - int rotate, GBool upsideDown); - -private: - - XRef *xref; // the xref table for this PDF file - 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/Parser.cxx b/pdftops/Parser.cxx deleted file mode 100644 index 455b079ec..000000000 --- a/pdftops/Parser.cxx +++ /dev/null @@ -1,214 +0,0 @@ -//======================================================================== -// -// Parser.cc -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include <stddef.h> -#include "Object.h" -#include "Array.h" -#include "Dict.h" -#include "Parser.h" -#include "XRef.h" -#include "Error.h" -#include "Decrypt.h" - -Parser::Parser(XRef *xrefA, Lexer *lexerA) { - xref = xrefA; - lexer = lexerA; - inlineImg = 0; - lexer->getObj(&buf1); - lexer->getObj(&buf2); -} - -Parser::~Parser() { - buf1.free(); - buf2.free(); - delete lexer; -} - -Object *Parser::getObj(Object *obj, - Guchar *fileKey, int keyLength, - int objNum, int objGen) { - char *key; - Stream *str; - Object obj2; - int num; - Decrypt *decrypt; - GString *s; - char *p; - int i; - - // 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(xref); - while (!buf1.isCmd("]") && !buf1.isEOF()) - obj->arrayAdd(getObj(&obj2, fileKey, keyLength, objNum, objGen)); - if (buf1.isEOF()) - error(getPos(), "End of file inside array"); - shift(); - - // dictionary or stream - } else if (buf1.isCmd("<<")) { - shift(); - obj->initDict(xref); - 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()) { - gfree(key); - break; - } - obj->dictAdd(key, getObj(&obj2, fileKey, keyLength, objNum, objGen)); - } - } - if (buf1.isEOF()) - error(getPos(), "End of file inside dictionary"); - if (buf2.isCmd("stream")) { - if ((str = makeStream(obj))) { - obj->initStream(str); - if (fileKey) { - str->getBaseStream()->doDecryption(fileKey, keyLength, - objNum, objGen); - } - } 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); - } - - // string - } else if (buf1.isString() && fileKey) { - buf1.copy(obj); - s = obj->getString(); - decrypt = new Decrypt(fileKey, keyLength, objNum, objGen); - for (i = 0, p = obj->getString()->getCString(); - i < s->getLength(); - ++i, ++p) { - *p = decrypt->decryptByte(*p); - } - delete decrypt; - shift(); - - // simple object - } else { - buf1.copy(obj); - shift(); - } - - return obj; -} - -Stream *Parser::makeStream(Object *dict) { - Object obj; - BaseStream *baseStr; - Stream *str; - Guint pos, endPos, length; - - // get stream start position - lexer->skipToNextLine(); - pos = lexer->getPos(); - - // get length - dict->dictLookup("Length", &obj); - if (obj.isInt()) { - length = (Guint)obj.getInt(); - obj.free(); - } else { - error(getPos(), "Bad 'Length' attribute in stream"); - obj.free(); - return NULL; - } - - // check for length in damaged file - if (xref && xref->getStreamEnd(pos, &endPos)) { - length = endPos - pos; - } - - // in badly damaged PDF files, we can run off the end of the input - // stream immediately after the "stream" token - if (!lexer->getStream()) { - return NULL; - } - baseStr = lexer->getStream()->getBaseStream(); - - // 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'"); - // kludge for broken PDF files: just add 5k to the length, and - // hope its enough - length += 5000; - } - - // make base stream - str = baseStr->makeSubStream(pos, gTrue, length, dict); - - // get filters - str = str->addFilters(dict); - - return str; -} - -void Parser::shift() { - if (inlineImg > 0) { - if (inlineImg < 2) { - ++inlineImg; - } else { - // in a damaged content stream, if 'ID' shows up in the middle - // of a dictionary, we need to reset - inlineImg = 0; - } - } 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 deleted file mode 100644 index 754e9744c..000000000 --- a/pdftops/Parser.h +++ /dev/null @@ -1,56 +0,0 @@ -//======================================================================== -// -// Parser.h -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef PARSER_H -#define PARSER_H - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "Lexer.h" - -//------------------------------------------------------------------------ -// Parser -//------------------------------------------------------------------------ - -class Parser { -public: - - // Constructor. - Parser(XRef *xrefA, Lexer *lexerA); - - // Destructor. - ~Parser(); - - // Get the next object from the input stream. - Object *getObj(Object *obj, - Guchar *fileKey = NULL, int keyLength = 0, - int objNum = 0, int objGen = 0); - - // Get stream. - Stream *getStream() { return lexer->getStream(); } - - // Get current position in file. - int getPos() { return lexer->getPos(); } - -private: - - XRef *xref; // the xref table for this PDF file - 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 deleted file mode 100644 index f089d05d6..000000000 --- a/pdftops/README +++ /dev/null @@ -1,446 +0,0 @@ -Xpdf -==== - -version 2.02 -2003-mar-24 - -The Xpdf software and documentation are -copyright 1996-2003 Glyph & Cog, LLC. - -Email: derekn@foolabs.com -WWW: http://www.foolabs.com/xpdf/ - -The PDF data structures, operators, and specification are -copyright 1985-2001 Adobe Systems Inc. - - -What is Xpdf? -------------- - -Xpdf is an open source viewer for Portable Document Format (PDF) -files. (These are also sometimes also called 'Acrobat' files, from -the name of Adobe's PDF software.) The Xpdf project also includes a -PDF text extractor, PDF-to-PostScript converter, and various other -utilities. - -Xpdf runs under the X Window System on UNIX, VMS, and OS/2. The non-X -components (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 can use Type 1, -TrueType, or 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 see the Glyph & -Cog web site: - - http://www.glyphandcog.com/ - - -Compatibility -------------- - -Xpdf is developed and tested on a Linux 2.2 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, pdffonts, -pdfimages) can also be compiled on Win32 systems. See the Xpdf web -page for details. - -If you compile 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, BeOS, and EPOC. 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 four additional utilities (which are fully described in -their man pages): - - pdfinfo -- dumps a PDF file's Info dictionary (plus some other - useful information) - pdffonts -- lists the fonts used in a PDF file along with various - information for each font - 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.). - - -Upgrading from Xpdf 0.9x ------------------------- - -WARNING: Xpdf 1.x switched to a completely different config file setup -than Xpdf 0.9x. - -Many of the configuration options that used to be X resources have -been moved into the Xpdf config file. There are also lots of new and -improved options. If you're upgrading from Xpdf 0.9x, please read -through the sample config file (doc/sample-xpdfrc) and the xpdfrc(5) -man page. - -The Asian language support has been pulled out into separate packages, -loaded at run time. This is much cleaner than the 0.9x approach -- it -makes the base distribution smaller, allows the language support -packages to be upgraded separately, and lets users customize Xpdf for -other text encodings without modifying the source. See the web site -(http://www.foolabs.com/xpdf) for info on downloading the language -support packages. - -All of the Xpdf tools, including the X viewer and the command line -programs, read the same config file. They first attempt to read the -user's personal config file: - - $HOME/.xpdfrc - -If it is not found, the Xpdf tools read a system-wide config file, -typically something like: - - /usr/local/etc/xpdfrc - -(this location can be customized when building Xpdf). - -The Win32 command line tools look in the directory containing the -executable, e.g.: - - C:/Program Files/Xpdf/xpdfrc - -Xpdf comes with a "sample-xpdfrc" file in the doc directory. This is -a good starting point for constructing your own config file. - -For full details, please see the xpdfrc(5) man page. - - -Fonts ------ - -By default, Xpdf will use 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 -maybe Zapf Dingbats). - -If Xpdf is built with support for t1lib (or FreeType 2), you can get -much higher quality text by using Type 1 fonts instead of X server -fonts. For example, you can use the Type 1 fonts that come with -ghostscript. To do this, add the following lines to the xpdfrc file -(e.g., /usr/local/etc/xpdfrc or $HOME/.xpdfrc): - -displayFontT1 Times-Roman /usr/local/share/ghostscript/fonts/n021003l.pfb -displayFontT1 Times-Italic /usr/local/share/ghostscript/fonts/n021023l.pfb -displayFontT1 Times-Bold /usr/local/share/ghostscript/fonts/n021004l.pfb -displayFontT1 Times-BoldItalic /usr/local/share/ghostscript/fonts/n021024l.pfb -displayFontT1 Helvetica /usr/local/share/ghostscript/fonts/n019003l.pfb -displayFontT1 Helvetica-Oblique /usr/local/share/ghostscript/fonts/n019023l.pfb -displayFontT1 Helvetica-Bold /usr/local/share/ghostscript/fonts/n019004l.pfb -displayFontT1 Helvetica-BoldOblique /usr/local/share/ghostscript/fonts/n019024l.pfb -displayFontT1 Courier /usr/local/share/ghostscript/fonts/n022003l.pfb -displayFontT1 Courier-Oblique /usr/local/share/ghostscript/fonts/n022023l.pfb -displayFontT1 Courier-Bold /usr/local/share/ghostscript/fonts/n022004l.pfb -displayFontT1 Courier-BoldOblique /usr/local/share/ghostscript/fonts/n022024l.pfb -displayFontT1 Symbol /usr/local/share/ghostscript/fonts/s050000l.pfb -displayFontT1 ZapfDingbats /usr/local/share/ghostscript/fonts/d050000l.pfb - -You will need to replace '/usr/local/share/ghostscript/fonts' with the -appropriate path on your system. - - -Compiling Xpdf --------------- - -See the separate file, INSTALL. - - -Bugs ----- - -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, Martin P.J. Zinser, and David Mathog 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 and the - xpdf/cygwin/XFree86 build instructions. -* 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. -* Pine Tree Systems A/S for funding the OPI and EPS support in - pdftops. -* Easy Software Products for funding the "sh" operator support. -* Tom Kacvinsky for help with FreeType and for being my interface to - the FreeType team. -* Theppitak Karoonboonyanan for help with Thai support. -* Leonard Rosenthol for help and contributions on a bunch of things. -* Alexandros Diamantidis and Maria Adaloglou for help with Greek - support. -* Lawrence Lai for help with the CJK Unicode maps. - -Various people have contributed modifications made for use by the -pdftex project: - -* Han The Thanh -* Martin Schröder of ArtCom GmbH - - -References ----------- - -Adobe Systems Inc., _PDF Reference: Adobe Portable Document Format -version 1.4_, 3nd ed. -Addison-Wesley, 2001, ISBN 0-201-75839-3. -http://partners.adobe.com/asn/developer/acrosdk/docs/filefmtspecs/PDFReference.pdf -[The printed manual for PDF version 1.4.] - -Adobe Systems Inc., _Portable Document Format: Changes from Version -1.3 to 1.4_, Adobe Developer Support Technical Note #5409. -June 11, 2001. -http://partners.adobe.com/asn/developer/acrosdk/docs/filefmtspecs/PDF14Deltas.pdf -[Updates for PDF 1.4.] - -Adobe Systems Inc., _PostScript Language Reference_, 3rd ed. -Addison-Wesley, 1999, ISBN 0-201-37922-8. -[The official PostScript manual.] - -Adobe Systems, Inc., _The Type 42 Font Format Specification_, -Adobe Developer Support Technical Specification #5012. 1998. -http://partners.adobe.com/asn/developer/pdfs/tn/5012.Type42_Spec.pdf -[Type 42 is the format used to embed TrueType fonts in PostScript -files.] - -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 and Chinese font support.] - -Adobe Systems, Inc., _Adobe-Japan1-4 Character Collection for -CID-Keyed Fonts_, Adobe Developer Support Technical Note #5078. -2000. -http://partners.adobe.com/asn/developer/PDFS/TN/5078.CID_Glyph.pdf -[The Adobe Japanese character set.] - -Adobe Systems, Inc., _Adobe-GB1-4 Character Collection for -CID-Keyed Fonts_, Adobe Developer Support Technical Note #5079. -2000. -http://partners.adobe.com/asn/developer/pdfs/tn/5079.Adobe-GB1-4.pdf -[The Adobe Chinese GB (simplified) character set.] - -Adobe Systems, Inc., _Adobe-CNS1-3 Character Collection for -CID-Keyed Fonts_, Adobe Developer Support Technical Note #5080. -2000. -http://partners.adobe.com/asn/developer/PDFS/TN/5080.CNS_CharColl.pdf -[The Adobe Chinese CNS (traditional) 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.] - -Adobe Systems Inc., _Open Prepress Interface (OPI) Specification - -Version 2.0_, Adobe Developer Support Technical Note #5660. 2000. -http://partners.adobe.com/asn/developer/PDFS/TN/5660.OPI_2.0.pdf - -Adobe Systems Inc., CMap files. -ftp://ftp.oreilly.com/pub/examples/nutshell/cjkv/adobe/ -[The actual CMap files for the 16-bit CJK encodings.] - -Adobe Systems Inc., Unicode glyph lists. -http://partners.adobe.com/asn/developer/type/unicodegn.html -http://partners.adobe.com/asn/developer/type/glyphlist.txt -http://partners.adobe.com/asn/developer/type/corporateuse.txt -http://partners.adobe.com/asn/developer/type/zapfdingbats.txt -[Mappings between character names to Unicode.] - -Aldus Corp., _OPI: Open Prepress Interface Specification 1.3_. 1993. -http://partners.adobe.com/asn/developer/PDFS/TN/OPI_13.pdf - -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.] - -T. Boutell, et al., "PNG (Portable Network Graphics) Specification, -Version 1.0. RFC 2083. -[PDF uses the PNG filter algorithms.] - -CCITT, "Information Technology - Digital Compression and Coding of -Continuous-tone Still Images - Requirements and Guidelines", CCITT -Recommendation T.81. -http://www.w3.org/Graphics/JPEG/ -[The official JPEG spec.] - -A. Chernov, "Registration of a Cyrillic Character Set". RFC 1489. -[Documentation for the KOI8-R Cyrillic encoding.] - -Roman Czyborra, "The ISO 8859 Alphabet Soup". -http://czyborra.com/charsets/iso8859.html -[Documentation on the various ISO 859 encodings.] - -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.] - -ISO/IEC, _Information technology -- Lossy/lossless coding of bi-level -images_. ISO/IEC 14492, First edition (2001-12-15). -http://webstore.ansi.org/ -[The official JBIG2 standard. The final draft of this spec is -available from http://www.jpeg.org/jbighomepage.html.] - -ITU, "Standardization of Group 3 facsimile terminals for document -transmission", ITU-T Recommendation T.4, 1999. -ITU, "Facsimile coding schemes and coding control functions for Group 4 -facsimile apparatus", ITU-T Recommendation T.6, 1993. -http://www.itu.int/ -[The official Group 3 and 4 fax standards - used by the CCITTFaxDecode -stream, as well as the JBIG2Decode stream.] - -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.] - -Microsoft, _TrueType 1.0 Font Files_, rev. 1.66. 1995. -http://www.microsoft.com/typography/tt/tt.htm -[The TrueType font spec (in MS Word format, naturally).] - -Thai Industrial Standard, "Standard for Thai Character Codes for -Computers", TIS-620-2533 (1990). -http://www.nectec.or.th/it-standards/std620/std620.htm -[The TIS-620 Thai encoding.] - -P. Peterlin, "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.] - -Charles Poynton, "Color FAQ". -http://www.inforamp.net/~poynton/ColorFAQ.html -[The mapping from the CIE 1931 (XYZ) color space to RGB.] - -R. Rivest, "The MD5 Message-Digest Algorithm". RFC 1321. -[MD5 is used in PDF document encryption.] - -Unicode Consortium, "Unicode Home Page". -http://www.unicode.org/ -[Online copy of the Unicode spec.] - -W3C Recommendation, "PNG (Portable Network Graphics) Specification -Version 1.0". -http://www.w3.org/Graphics/PNG/ -[Defines the PNG image predictor.] - -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.] - -F. Yergeau, "UTF-8, a transformation format of ISO 10646". RFC 2279. -[A commonly used Unicode encoding.] diff --git a/pdftops/SecurityHandler.cxx b/pdftops/SecurityHandler.cxx deleted file mode 100644 index 34e766a2c..000000000 --- a/pdftops/SecurityHandler.cxx +++ /dev/null @@ -1,378 +0,0 @@ -//======================================================================== -// -// SecurityHandler.cc -// -// Copyright 2004 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include "GString.h" -#include "PDFDoc.h" -#include "Decrypt.h" -#include "Error.h" -#include "GlobalParams.h" -#if HAVE_XPDFCORE -# include "XPDFCore.h" -#elif HAVE_WINPDFCORE -# include "WinPDFCore.h" -#endif -#ifdef ENABLE_PLUGINS -# include "XpdfPluginAPI.h" -#endif -#include "SecurityHandler.h" - -//------------------------------------------------------------------------ -// SecurityHandler -//------------------------------------------------------------------------ - -SecurityHandler *SecurityHandler::make(PDFDoc *docA, Object *encryptDictA) { - Object filterObj; - SecurityHandler *secHdlr; -#ifdef ENABLE_PLUGINS - XpdfSecurityHandler *xsh; -#endif - - encryptDictA->dictLookup("Filter", &filterObj); - if (filterObj.isName("Standard")) { - secHdlr = new StandardSecurityHandler(docA, encryptDictA); - } else if (filterObj.isName()) { -#ifdef ENABLE_PLUGINS - if ((xsh = globalParams->getSecurityHandler(filterObj.getName()))) { - secHdlr = new ExternalSecurityHandler(docA, encryptDictA, xsh); - } else { -#endif - error(-1, "Couldn't find the '%s' security handler", - filterObj.getName()); - secHdlr = NULL; -#ifdef ENABLE_PLUGINS - } -#endif - } else { - error(-1, "Missing or invalid 'Filter' entry in encryption dictionary"); - secHdlr = NULL; - } - filterObj.free(); - return secHdlr; -} - -SecurityHandler::SecurityHandler(PDFDoc *docA) { - doc = docA; -} - -SecurityHandler::~SecurityHandler() { -} - -GBool SecurityHandler::checkEncryption(GString *ownerPassword, - GString *userPassword) { - void *authData; - GBool ok; - int i; - - if (ownerPassword || userPassword) { - authData = makeAuthData(ownerPassword, userPassword); - } else { - authData = NULL; - } - ok = authorize(authData); - if (authData) { - freeAuthData(authData); - } - for (i = 0; !ok && i < 3; ++i) { - if (!(authData = getAuthData())) { - break; - } - ok = authorize(authData); - if (authData) { - freeAuthData(authData); - } - } - if (!ok) { - error(-1, "Incorrect password"); - } - return ok; -} - -//------------------------------------------------------------------------ -// StandardSecurityHandler -//------------------------------------------------------------------------ - -class StandardAuthData { -public: - - StandardAuthData(GString *ownerPasswordA, GString *userPasswordA) { - ownerPassword = ownerPasswordA; - userPassword = userPasswordA; - } - - ~StandardAuthData() { - if (ownerPassword) { - delete ownerPassword; - } - if (userPassword) { - delete userPassword; - } - } - - GString *ownerPassword; - GString *userPassword; -}; - -StandardSecurityHandler::StandardSecurityHandler(PDFDoc *docA, - Object *encryptDictA): - SecurityHandler(docA) -{ - Object versionObj, revisionObj, lengthObj; - Object ownerKeyObj, userKeyObj, permObj, fileIDObj; - Object fileIDObj1; - Object cryptFiltersObj, streamFilterObj, stringFilterObj; - Object cryptFilterObj, cfmObj, cfLengthObj; - Object encryptMetadataObj; - - ok = gFalse; - fileID = NULL; - ownerKey = NULL; - userKey = NULL; - - encryptDictA->dictLookup("V", &versionObj); - encryptDictA->dictLookup("R", &revisionObj); - encryptDictA->dictLookup("Length", &lengthObj); - encryptDictA->dictLookup("O", &ownerKeyObj); - encryptDictA->dictLookup("U", &userKeyObj); - encryptDictA->dictLookup("P", &permObj); - doc->getXRef()->getTrailerDict()->dictLookup("ID", &fileIDObj); - if (versionObj.isInt() && - revisionObj.isInt() && - ownerKeyObj.isString() && ownerKeyObj.getString()->getLength() == 32 && - userKeyObj.isString() && userKeyObj.getString()->getLength() == 32 && - permObj.isInt()) { - encVersion = versionObj.getInt(); - encRevision = revisionObj.getInt(); - // revision 2 forces a 40-bit key - some buggy PDF generators - // set the Length value incorrectly - if (encRevision == 2 || !lengthObj.isInt()) { - fileKeyLength = 5; - } else { - fileKeyLength = lengthObj.getInt() / 8; - } - encryptMetadata = gTrue; - //~ this currently only handles a subset of crypt filter functionality - if (encVersion == 4 && encRevision == 4) { - encryptDictA->dictLookup("CF", &cryptFiltersObj); - encryptDictA->dictLookup("StmF", &streamFilterObj); - encryptDictA->dictLookup("StrF", &stringFilterObj); - if (cryptFiltersObj.isDict() && - streamFilterObj.isName() && - stringFilterObj.isName() && - !strcmp(streamFilterObj.getName(), stringFilterObj.getName())) { - if (cryptFiltersObj.dictLookup(streamFilterObj.getName(), - &cryptFilterObj)->isDict()) { - if (cryptFilterObj.dictLookup("CFM", &cfmObj)->isName("V2")) { - encVersion = 2; - encRevision = 3; - if (cryptFilterObj.dictLookup("Length", &cfLengthObj)->isInt()) { - //~ according to the spec, this should be cfLengthObj / 8 - fileKeyLength = cfLengthObj.getInt(); - } - cfLengthObj.free(); - } - cfmObj.free(); - } - cryptFilterObj.free(); - } - stringFilterObj.free(); - streamFilterObj.free(); - cryptFiltersObj.free(); - if (encryptDictA->dictLookup("EncryptMetadata", - &encryptMetadataObj)->isBool()) { - encryptMetadata = encryptMetadataObj.getBool(); - } - encryptMetadataObj.free(); - } - permFlags = permObj.getInt(); - ownerKey = ownerKeyObj.getString()->copy(); - userKey = userKeyObj.getString()->copy(); - if (encVersion >= 1 && encVersion <= 2 && - encRevision >= 2 && encRevision <= 3) { - if (fileIDObj.isArray()) { - if (fileIDObj.arrayGet(0, &fileIDObj1)->isString()) { - fileID = fileIDObj1.getString()->copy(); - } else { - fileID = new GString(); - } - fileIDObj1.free(); - } else { - fileID = new GString(); - } - ok = gTrue; - } else { - error(-1, "Unsupported version/revision (%d/%d) of Standard security handler", - encVersion, encRevision); - } - } else { - error(-1, "Weird encryption info"); - } - if (fileKeyLength > 16) { - fileKeyLength = 16; - } - fileIDObj.free(); - permObj.free(); - userKeyObj.free(); - ownerKeyObj.free(); - lengthObj.free(); - revisionObj.free(); - versionObj.free(); -} - -StandardSecurityHandler::~StandardSecurityHandler() { - if (fileID) { - delete fileID; - } - if (ownerKey) { - delete ownerKey; - } - if (userKey) { - delete userKey; - } -} - -void *StandardSecurityHandler::makeAuthData(GString *ownerPassword, - GString *userPassword) { - return new StandardAuthData(ownerPassword ? ownerPassword->copy() - : (GString *)NULL, - userPassword ? userPassword->copy() - : (GString *)NULL); -} - -void *StandardSecurityHandler::getAuthData() { -#if HAVE_XPDFCORE - XPDFCore *core; - GString *password; - - if (!(core = (XPDFCore *)doc->getGUIData()) || - !(password = core->getPassword())) { - return NULL; - } - return new StandardAuthData(password, password->copy()); -#elif HAVE_WINPDFCORE - WinPDFCore *core; - GString *password; - - if (!(core = (WinPDFCore *)doc->getGUIData()) || - !(password = core->getPassword())) { - return NULL; - } - return new StandardAuthData(password, password->copy()); -#else - return NULL; -#endif -} - -void StandardSecurityHandler::freeAuthData(void *authData) { - delete (StandardAuthData *)authData; -} - -GBool StandardSecurityHandler::authorize(void *authData) { - GString *ownerPassword, *userPassword; - - if (!ok) { - return gFalse; - } - if (authData) { - ownerPassword = ((StandardAuthData *)authData)->ownerPassword; - userPassword = ((StandardAuthData *)authData)->userPassword; - } else { - ownerPassword = NULL; - userPassword = NULL; - } - if (!Decrypt::makeFileKey(encVersion, encRevision, fileKeyLength, - ownerKey, userKey, permFlags, fileID, - ownerPassword, userPassword, fileKey, - encryptMetadata, &ownerPasswordOk)) { - return gFalse; - } - return gTrue; -} - -#ifdef ENABLE_PLUGINS - -//------------------------------------------------------------------------ -// ExternalSecurityHandler -//------------------------------------------------------------------------ - -ExternalSecurityHandler::ExternalSecurityHandler(PDFDoc *docA, - Object *encryptDictA, - XpdfSecurityHandler *xshA): - SecurityHandler(docA) -{ - encryptDictA->copy(&encryptDict); - xsh = xshA; - ok = gFalse; - - if (!(*xsh->newDoc)(xsh->handlerData, (XpdfDoc)docA, - (XpdfObject)encryptDictA, &docData)) { - return; - } - - ok = gTrue; -} - -ExternalSecurityHandler::~ExternalSecurityHandler() { - (*xsh->freeDoc)(xsh->handlerData, docData); - encryptDict.free(); -} - -void *ExternalSecurityHandler::makeAuthData(GString *ownerPassword, - GString *userPassword) { - char *opw, *upw; - void *authData; - - opw = ownerPassword ? ownerPassword->getCString() : (char *)NULL; - upw = userPassword ? userPassword->getCString() : (char *)NULL; - if (!(*xsh->makeAuthData)(xsh->handlerData, docData, opw, upw, &authData)) { - return NULL; - } - return authData; -} - -void *ExternalSecurityHandler::getAuthData() { - void *authData; - - if (!(*xsh->getAuthData)(xsh->handlerData, docData, &authData)) { - return NULL; - } - return authData; -} - -void ExternalSecurityHandler::freeAuthData(void *authData) { - (*xsh->freeAuthData)(xsh->handlerData, docData, authData); -} - -GBool ExternalSecurityHandler::authorize(void *authData) { - char *key; - int length; - - if (!ok) { - return gFalse; - } - permFlags = (*xsh->authorize)(xsh->handlerData, docData, authData); - if (!(permFlags & xpdfPermissionOpen)) { - return gFalse; - } - if (!(*xsh->getKey)(xsh->handlerData, docData, &key, &length, &encVersion)) { - return gFalse; - } - if ((fileKeyLength = length) > 16) { - fileKeyLength = 16; - } - memcpy(fileKey, key, fileKeyLength); - (*xsh->freeKey)(xsh->handlerData, docData, key, length); - return gTrue; -} - -#endif // ENABLE_PLUGINS diff --git a/pdftops/SecurityHandler.h b/pdftops/SecurityHandler.h deleted file mode 100644 index db108bab2..000000000 --- a/pdftops/SecurityHandler.h +++ /dev/null @@ -1,155 +0,0 @@ -//======================================================================== -// -// SecurityHandler.h -// -// Copyright 2004 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef SECURITYHANDLER_H -#define SECURITYHANDLER_H - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "gtypes.h" -#include "Object.h" - -class GString; -class PDFDoc; -struct XpdfSecurityHandler; - -//------------------------------------------------------------------------ -// SecurityHandler -//------------------------------------------------------------------------ - -class SecurityHandler { -public: - - static SecurityHandler *make(PDFDoc *docA, Object *encryptDictA); - - SecurityHandler(PDFDoc *docA); - virtual ~SecurityHandler(); - - // Check the document's encryption. If the document is encrypted, - // this will first try <ownerPassword> and <userPassword> (in - // "batch" mode), and if those fail, it will attempt to request a - // password from the user. This is the high-level function that - // calls the lower level functions for the specific security handler - // (requesting a password three times, etc.). Returns true if the - // document can be opened (if it's unencrypted, or if a correct - // password is obtained); false otherwise (encrypted and no correct - // password). - GBool checkEncryption(GString *ownerPassword, - GString *userPassword); - - // Create authorization data for the specified owner and user - // passwords. If the security handler doesn't support "batch" mode, - // this function should return NULL. - virtual void *makeAuthData(GString *ownerPassword, - GString *userPassword) = 0; - - // Construct authorization data, typically by prompting the user for - // a password. Returns an authorization data object, or NULL to - // cancel. - virtual void *getAuthData() = 0; - - // Free the authorization data returned by makeAuthData or - // getAuthData. - virtual void freeAuthData(void *authData) = 0; - - // Attempt to authorize the document, using the supplied - // authorization data (which may be NULL). Returns true if - // successful (i.e., if at least the right to open the document was - // granted). - virtual GBool authorize(void *authData) = 0; - - // Return the various authorization parameters. These are only - // valid after authorize has returned true. - virtual int getPermissionFlags() = 0; - virtual GBool getOwnerPasswordOk() = 0; - virtual Guchar *getFileKey() = 0; - virtual int getFileKeyLength() = 0; - virtual int getEncVersion() = 0; - -protected: - - PDFDoc *doc; -}; - -//------------------------------------------------------------------------ -// StandardSecurityHandler -//------------------------------------------------------------------------ - -class StandardSecurityHandler: public SecurityHandler { -public: - - StandardSecurityHandler(PDFDoc *docA, Object *encryptDictA); - virtual ~StandardSecurityHandler(); - - virtual void *makeAuthData(GString *ownerPassword, - GString *userPassword); - virtual void *getAuthData(); - virtual void freeAuthData(void *authData); - virtual GBool authorize(void *authData); - virtual int getPermissionFlags() { return permFlags; } - virtual GBool getOwnerPasswordOk() { return ownerPasswordOk; } - virtual Guchar *getFileKey() { return fileKey; } - virtual int getFileKeyLength() { return fileKeyLength; } - virtual int getEncVersion() { return encVersion; } - -private: - - int permFlags; - GBool ownerPasswordOk; - Guchar fileKey[16]; - int fileKeyLength; - int encVersion; - int encRevision; - GBool encryptMetadata; - - GString *ownerKey, *userKey; - GString *fileID; - GBool ok; -}; - -#ifdef ENABLE_PLUGINS -//------------------------------------------------------------------------ -// ExternalSecurityHandler -//------------------------------------------------------------------------ - -class ExternalSecurityHandler: public SecurityHandler { -public: - - ExternalSecurityHandler(PDFDoc *docA, Object *encryptDictA, - XpdfSecurityHandler *xshA); - virtual ~ExternalSecurityHandler(); - - virtual void *makeAuthData(GString *ownerPassword, - GString *userPassword); - virtual void *getAuthData(); - virtual void freeAuthData(void *authData); - virtual GBool authorize(void *authData); - virtual int getPermissionFlags() { return permFlags; } - virtual GBool getOwnerPasswordOk() { return gFalse; } - virtual Guchar *getFileKey() { return fileKey; } - virtual int getFileKeyLength() { return fileKeyLength; } - virtual int getEncVersion() { return encVersion; } - -private: - - Object encryptDict; - XpdfSecurityHandler *xsh; - void *docData; - int permFlags; - Guchar fileKey[16]; - int fileKeyLength; - int encVersion; - GBool ok; -}; -#endif // ENABLE_PLUGINS - -#endif diff --git a/pdftops/Stream-CCITT.h b/pdftops/Stream-CCITT.h deleted file mode 100644 index c4458fe71..000000000 --- a/pdftops/Stream-CCITT.h +++ /dev/null @@ -1,459 +0,0 @@ -//======================================================================== -// -// Stream-CCITT.h -// -// Tables for CCITT Fax decoding. -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -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 deleted file mode 100644 index 40819ae5f..000000000 --- a/pdftops/Stream.cxx +++ /dev/null @@ -1,4687 +0,0 @@ -//======================================================================== -// -// Stream.cc -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include <stdio.h> -#include <stdlib.h> -#include <stddef.h> -#include <limits.h> -#ifndef WIN32 -#include <unistd.h> -#endif -#include <string.h> -#include <ctype.h> -#include "gmem.h" -#include "gfile.h" -#include "config.h" -#include "Error.h" -#include "Object.h" -#include "Lexer.h" -#include "Decrypt.h" -#include "GfxState.h" -#include "Stream.h" -#include "JBIG2Stream.h" -#include "JPXStream.h" -#include "Stream-CCITT.h" - -#ifdef __DJGPP__ -static GBool setDJSYSFLAGS = gFalse; -#endif - -#ifdef VMS -#ifdef __GNUC__ -#define SEEK_SET 0 -#define SEEK_CUR 1 -#define SEEK_END 2 -#endif -#endif - -//------------------------------------------------------------------------ -// Stream (base class) -//------------------------------------------------------------------------ - -Stream::Stream() { - ref = 1; -} - -Stream::~Stream() { -} - -void Stream::close() { -} - -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(int psLevel, 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 globals, 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 if (!strcmp(name, "JBIG2Decode")) { - if (params->isDict()) { - params->dictLookup("JBIG2Globals", &globals); - } - str = new JBIG2Stream(str, &globals); - globals.free(); - } else if (!strcmp(name, "JPXDecode")) { - str = new JPXStream(str); - } else { - error(getPos(), "Unknown filter '%s'", name); - str = new EOFStream(str); - } - return str; -} - -//------------------------------------------------------------------------ -// BaseStream -//------------------------------------------------------------------------ - -BaseStream::BaseStream(Object *dictA) { - dict = *dictA; - decrypt = NULL; -} - -BaseStream::~BaseStream() { - dict.free(); - if (decrypt) - delete decrypt; -} - -void BaseStream::doDecryption(Guchar *fileKey, int keyLength, - int objNum, int objGen) { - decrypt = new Decrypt(fileKey, keyLength, objNum, objGen); -} - -//------------------------------------------------------------------------ -// FilterStream -//------------------------------------------------------------------------ - -FilterStream::FilterStream(Stream *strA) { - str = strA; -} - -FilterStream::~FilterStream() { -} - -void FilterStream::close() { - str->close(); -} - -void FilterStream::setPos(Guint pos, int dir) { - error(-1, "Internal: called setPos() on FilterStream"); -} - -//------------------------------------------------------------------------ -// ImageStream -//------------------------------------------------------------------------ - -ImageStream::ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA) { - int imgLineSize; - - str = strA; - width = widthA; - nComps = nCompsA; - nBits = nBitsA; - - nVals = width * nComps; - if (nBits == 1) { - imgLineSize = (nVals + 7) & ~7; - } else { - imgLineSize = nVals; - } - imgLine = (Guchar *)gmallocn(imgLineSize, sizeof(Guchar)); - imgIdx = nVals; -} - -ImageStream::~ImageStream() { - gfree(imgLine); -} - -void ImageStream::reset() { - str->reset(); -} - -GBool ImageStream::getPixel(Guchar *pix) { - int i; - - if (imgIdx >= nVals) { - getLine(); - imgIdx = 0; - } - for (i = 0; i < nComps; ++i) { - pix[i] = imgLine[imgIdx++]; - } - return gTrue; -} - -Guchar *ImageStream::getLine() { - Gulong buf, bitMask; - int bits; - int c; - int i; - - 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; - } - } - return imgLine; -} - -void ImageStream::skipLine() { - int n, i; - - n = (nVals * nBits + 7) >> 3; - for (i = 0; i < n; ++i) { - str->getChar(); - } -} - -//------------------------------------------------------------------------ -// StreamPredictor -//------------------------------------------------------------------------ - -StreamPredictor::StreamPredictor(Stream *strA, int predictorA, - int widthA, int nCompsA, int nBitsA) { - str = strA; - predictor = predictorA; - width = widthA; - nComps = nCompsA; - nBits = nBitsA; - predLine = NULL; - ok = gFalse; - - nVals = width * nComps; - pixBytes = (nComps * nBits + 7) >> 3; - rowBytes = ((nVals * nBits + 7) >> 3) + pixBytes; - if (width <= 0 || nComps <= 0 || nBits <= 0 || - nComps > gfxColorMaxComps || - nBits > 16 || - width >= INT_MAX / nComps || // check for overflow in nVals - nVals >= (INT_MAX - 7) / nBits) { // check for overflow in rowBytes - return; - } - predLine = (Guchar *)gmalloc(rowBytes); - memset(predLine, 0, rowBytes); - predIdx = rowBytes; - - ok = gTrue; -} - -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[gfxColorMaxComps * 2 + 1]; - int left, up, upLeft, p, pa, pb, pc; - int c; - Gulong inBuf, outBuf, bitMask; - int inBits, outBits; - int i, j, k, kk; - - // get PNG optimum predictor number - if (predictor >= 10) { - if ((curPred = str->getRawChar()) == EOF) { - return gFalse; - } - curPred += 10; - } else { - curPred = predictor; - } - - // read the raw line, apply PNG (byte) predictor - memset(upLeftBuf, 0, pixBytes + 1); - for (i = pixBytes; i < rowBytes; ++i) { - for (j = pixBytes; j > 0; --j) { - upLeftBuf[j] = upLeftBuf[j-1]; - } - upLeftBuf[0] = predLine[i]; - if ((c = str->getRawChar()) == EOF) { - if (i > pixBytes) { - // this ought to return false, but some (broken) PDF files - // contain truncated image data, and Adobe apparently reads the - // last partial line - break; - } - return gFalse; - } - 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] = left + (Guchar)c; - else if (pb <= pc) - predLine[i] = up + (Guchar)c; - else - predLine[i] = upLeft + (Guchar)c; - break; - case 10: // PNG none - default: // no predictor or TIFF predictor - predLine[i] = (Guchar)c; - break; - } - } - - // apply TIFF (component) predictor - 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 { - memset(upLeftBuf, 0, nComps + 1); - bitMask = (1 << nBits) - 1; - inBuf = outBuf = 0; - inBits = outBits = 0; - j = k = pixBytes; - for (i = 0; i < width; ++i) { - for (kk = 0; kk < nComps; ++kk) { - if (inBits < nBits) { - inBuf = (inBuf << 8) | (predLine[j++] & 0xff); - inBits += 8; - } - upLeftBuf[kk] = (upLeftBuf[kk] + - (inBuf >> (inBits - nBits))) & bitMask; - inBits -= nBits; - outBuf = (outBuf << nBits) | upLeftBuf[kk]; - outBits += nBits; - if (outBits >= 8) { - predLine[k++] = (Guchar)(outBuf >> (outBits - 8)); - outBits -= 8; - } - } - } - if (outBits > 0) { - predLine[k++] = (Guchar)((outBuf << (8 - outBits)) + - (inBuf & ((1 << (8 - outBits)) - 1))); - } - } - } - - // reset to start of line - predIdx = pixBytes; - - return gTrue; -} - -//------------------------------------------------------------------------ -// FileStream -//------------------------------------------------------------------------ - -FileStream::FileStream(FILE *fA, Guint startA, GBool limitedA, - Guint lengthA, Object *dictA): - BaseStream(dictA) { - f = fA; - start = startA; - limited = limitedA; - length = lengthA; - bufPtr = bufEnd = buf; - bufPos = start; - savePos = 0; - saved = gFalse; -} - -FileStream::~FileStream() { - close(); -} - -Stream *FileStream::makeSubStream(Guint startA, GBool limitedA, - Guint lengthA, Object *dictA) { - return new FileStream(f, startA, limitedA, lengthA, dictA); -} - -void FileStream::reset() { -#if HAVE_FSEEKO - savePos = (Guint)ftello(f); - fseeko(f, start, SEEK_SET); -#elif HAVE_FSEEK64 - savePos = (Guint)ftell64(f); - fseek64(f, start, SEEK_SET); -#else - savePos = (Guint)ftell(f); - fseek(f, start, SEEK_SET); -#endif - saved = gTrue; - bufPtr = bufEnd = buf; - bufPos = start; - if (decrypt) - decrypt->reset(); -} - -void FileStream::close() { - if (saved) { -#if HAVE_FSEEKO - fseeko(f, savePos, SEEK_SET); -#elif HAVE_FSEEK64 - fseek64(f, savePos, SEEK_SET); -#else - fseek(f, savePos, SEEK_SET); -#endif - saved = gFalse; - } -} - -GBool FileStream::fillBuf() { - int n; - char *p; - - bufPos += bufEnd - buf; - bufPtr = bufEnd = buf; - if (limited && bufPos >= start + length) { - return gFalse; - } - if (limited && bufPos + fileStreamBufSize > start + length) { - n = start + length - bufPos; - } else { - n = fileStreamBufSize; - } - n = fread(buf, 1, n, f); - bufEnd = buf + n; - if (bufPtr >= bufEnd) { - return gFalse; - } - if (decrypt) { - for (p = buf; p < bufEnd; ++p) { - *p = (char)decrypt->decryptByte((Guchar)*p); - } - } - return gTrue; -} - -void FileStream::setPos(Guint pos, int dir) { - Guint size; - - if (dir >= 0) { -#if HAVE_FSEEKO - fseeko(f, pos, SEEK_SET); -#elif HAVE_FSEEK64 - fseek64(f, pos, SEEK_SET); -#else - fseek(f, pos, SEEK_SET); -#endif - bufPos = pos; - } else { -#if HAVE_FSEEKO - fseeko(f, 0, SEEK_END); - size = (Guint)ftello(f); -#elif HAVE_FSEEK64 - fseek64(f, 0, SEEK_END); - size = (Guint)ftell64(f); -#else - fseek(f, 0, SEEK_END); - size = (Guint)ftell(f); -#endif - if (pos > size) - pos = (Guint)size; -#ifdef __CYGWIN32__ - //~ work around a bug in cygwin's implementation of fseek - rewind(f); -#endif -#if HAVE_FSEEKO - fseeko(f, -(int)pos, SEEK_END); - bufPos = (Guint)ftello(f); -#elif HAVE_FSEEK64 - fseek64(f, -(int)pos, SEEK_END); - bufPos = (Guint)ftell64(f); -#else - fseek(f, -(int)pos, SEEK_END); - bufPos = (Guint)ftell(f); -#endif - } - bufPtr = bufEnd = buf; -} - -void FileStream::moveStart(int delta) { - start += delta; - bufPtr = bufEnd = buf; - bufPos = start; -} - -//------------------------------------------------------------------------ -// MemStream -//------------------------------------------------------------------------ - -MemStream::MemStream(char *bufA, Guint startA, Guint lengthA, Object *dictA): - BaseStream(dictA) { - buf = bufA; - start = startA; - length = lengthA; - bufEnd = buf + start + length; - bufPtr = buf + start; - needFree = gFalse; -} - -MemStream::~MemStream() { - if (needFree) { - gfree(buf); - } -} - -Stream *MemStream::makeSubStream(Guint startA, GBool limited, - Guint lengthA, Object *dictA) { - MemStream *subStr; - Guint newLength; - - if (!limited || startA + lengthA > start + length) { - newLength = start + length - startA; - } else { - newLength = lengthA; - } - subStr = new MemStream(buf, startA, newLength, dictA); - return subStr; -} - -void MemStream::reset() { - bufPtr = buf + start; - if (decrypt) { - decrypt->reset(); - } -} - -void MemStream::close() { -} - -void MemStream::setPos(Guint pos, int dir) { - Guint i; - - if (dir >= 0) { - i = pos; - } else { - i = start + length - pos; - } - if (i < start) { - i = start; - } else if (i > start + length) { - i = start + length; - } - bufPtr = buf + i; -} - -void MemStream::moveStart(int delta) { - start += delta; - length -= delta; - bufPtr = buf + start; -} - -void MemStream::doDecryption(Guchar *fileKey, int keyLength, - int objNum, int objGen) { - char *newBuf; - char *p, *q; - - this->BaseStream::doDecryption(fileKey, keyLength, objNum, objGen); - if (decrypt) { - newBuf = (char *)gmalloc(length); - for (p = buf + start, q = newBuf; p < bufEnd; ++p, ++q) { - *q = (char)decrypt->decryptByte((Guchar)*p); - } - bufEnd = newBuf + length; - bufPtr = newBuf + (bufPtr - (buf + start)); - start = 0; - buf = newBuf; - needFree = gTrue; - } -} - -//------------------------------------------------------------------------ -// EmbedStream -//------------------------------------------------------------------------ - -EmbedStream::EmbedStream(Stream *strA, Object *dictA, - GBool limitedA, Guint lengthA): - BaseStream(dictA) { - str = strA; - limited = limitedA; - length = lengthA; -} - -EmbedStream::~EmbedStream() { -} - -Stream *EmbedStream::makeSubStream(Guint start, GBool limitedA, - Guint lengthA, Object *dictA) { - error(-1, "Internal: called makeSubStream() on EmbedStream"); - return NULL; -} - -int EmbedStream::getChar() { - if (limited && !length) { - return EOF; - } - --length; - return str->getChar(); -} - -int EmbedStream::lookChar() { - if (limited && !length) { - return EOF; - } - return str->lookChar(); -} - -void EmbedStream::setPos(Guint pos, int dir) { - error(-1, "Internal: called setPos() on EmbedStream"); -} - -Guint EmbedStream::getStart() { - error(-1, "Internal: called getStart() on EmbedStream"); - return 0; -} - -void EmbedStream::moveStart(int delta) { - error(-1, "Internal: called moveStart() on EmbedStream"); -} - -//------------------------------------------------------------------------ -// ASCIIHexStream -//------------------------------------------------------------------------ - -ASCIIHexStream::ASCIIHexStream(Stream *strA): - FilterStream(strA) { - 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(int psLevel, char *indent) { - GString *s; - - if (psLevel < 2) { - return NULL; - } - if (!(s = str->getPSFilter(psLevel, indent))) { - return NULL; - } - s->append(indent)->append("/ASCIIHexDecode filter\n"); - return s; -} - -GBool ASCIIHexStream::isBinary(GBool last) { - return str->isBinary(gFalse); -} - -//------------------------------------------------------------------------ -// ASCII85Stream -//------------------------------------------------------------------------ - -ASCII85Stream::ASCII85Stream(Stream *strA): - FilterStream(strA) { - 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 (Lexer::isSpace(c[0])); - 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 (Lexer::isSpace(c[k])); - 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(int psLevel, char *indent) { - GString *s; - - if (psLevel < 2) { - return NULL; - } - if (!(s = str->getPSFilter(psLevel, indent))) { - return NULL; - } - s->append(indent)->append("/ASCII85Decode filter\n"); - return s; -} - -GBool ASCII85Stream::isBinary(GBool last) { - return str->isBinary(gFalse); -} - -//------------------------------------------------------------------------ -// LZWStream -//------------------------------------------------------------------------ - -LZWStream::LZWStream(Stream *strA, int predictor, int columns, int colors, - int bits, int earlyA): - FilterStream(strA) { - if (predictor != 1) { - pred = new StreamPredictor(this, predictor, columns, colors, bits); - if (!pred->isOk()) { - delete pred; - pred = NULL; - } - } else { - pred = NULL; - } - early = earlyA; - eof = gFalse; - inputBits = 0; - clearTable(); -} - -LZWStream::~LZWStream() { - if (pred) { - delete pred; - } - delete str; -} - -int LZWStream::getChar() { - if (pred) { - return pred->getChar(); - } - if (eof) { - return EOF; - } - if (seqIndex >= seqLength) { - if (!processNextCode()) { - return EOF; - } - } - return seqBuf[seqIndex++]; -} - -int LZWStream::lookChar() { - if (pred) { - return pred->lookChar(); - } - if (eof) { - return EOF; - } - if (seqIndex >= seqLength) { - if (!processNextCode()) { - return EOF; - } - } - return seqBuf[seqIndex]; -} - -int LZWStream::getRawChar() { - if (eof) { - return EOF; - } - if (seqIndex >= seqLength) { - if (!processNextCode()) { - return EOF; - } - } - return seqBuf[seqIndex++]; -} - -void LZWStream::reset() { - str->reset(); - eof = gFalse; - inputBits = 0; - clearTable(); -} - -GBool LZWStream::processNextCode() { - int code; - int nextLength; - int i, j; - - // check for EOF - if (eof) { - return gFalse; - } - - // check for eod and clear-table codes - start: - code = getCode(); - if (code == EOF || code == 257) { - eof = gTrue; - return gFalse; - } - if (code == 256) { - clearTable(); - goto start; - } - if (nextCode >= 4097) { - error(getPos(), "Bad LZW stream - expected clear-table code"); - clearTable(); - } - - // process the next code - nextLength = seqLength + 1; - if (code < 256) { - seqBuf[0] = code; - seqLength = 1; - } else if (code < nextCode) { - seqLength = table[code].length; - for (i = seqLength - 1, j = code; i > 0; --i) { - seqBuf[i] = table[j].tail; - j = table[j].head; - } - seqBuf[0] = j; - } else if (code == nextCode) { - seqBuf[seqLength] = newChar; - ++seqLength; - } else { - error(getPos(), "Bad LZW stream - unexpected code"); - eof = gTrue; - return gFalse; - } - newChar = seqBuf[0]; - if (first) { - first = gFalse; - } else { - table[nextCode].length = nextLength; - table[nextCode].head = prevCode; - table[nextCode].tail = newChar; - ++nextCode; - if (nextCode + early == 512) - nextBits = 10; - else if (nextCode + early == 1024) - nextBits = 11; - else if (nextCode + early == 2048) - nextBits = 12; - } - prevCode = code; - - // reset buffer - seqIndex = 0; - - return gTrue; -} - -void LZWStream::clearTable() { - nextCode = 258; - nextBits = 9; - seqIndex = seqLength = 0; - first = gTrue; -} - -int LZWStream::getCode() { - int c; - int code; - - while (inputBits < nextBits) { - if ((c = str->getChar()) == EOF) - return EOF; - inputBuf = (inputBuf << 8) | (c & 0xff); - inputBits += 8; - } - code = (inputBuf >> (inputBits - nextBits)) & ((1 << nextBits) - 1); - inputBits -= nextBits; - return code; -} - -GString *LZWStream::getPSFilter(int psLevel, char *indent) { - GString *s; - - if (psLevel < 2 || pred) { - return NULL; - } - if (!(s = str->getPSFilter(psLevel, indent))) { - return NULL; - } - s->append(indent)->append("<< "); - if (!early) { - s->append("/EarlyChange 0 "); - } - s->append(">> /LZWDecode filter\n"); - return s; -} - -GBool LZWStream::isBinary(GBool last) { - return str->isBinary(gTrue); -} - -//------------------------------------------------------------------------ -// RunLengthStream -//------------------------------------------------------------------------ - -RunLengthStream::RunLengthStream(Stream *strA): - FilterStream(strA) { - bufPtr = bufEnd = buf; - eof = gFalse; -} - -RunLengthStream::~RunLengthStream() { - delete str; -} - -void RunLengthStream::reset() { - str->reset(); - bufPtr = bufEnd = buf; - eof = gFalse; -} - -GString *RunLengthStream::getPSFilter(int psLevel, char *indent) { - GString *s; - - if (psLevel < 2) { - return NULL; - } - if (!(s = str->getPSFilter(psLevel, indent))) { - return NULL; - } - 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 *strA, int encodingA, GBool endOfLineA, - GBool byteAlignA, int columnsA, int rowsA, - GBool endOfBlockA, GBool blackA): - FilterStream(strA) { - encoding = encodingA; - endOfLine = endOfLineA; - byteAlign = byteAlignA; - columns = columnsA; - if (columns < 1) { - columns = 1; - } else if (columns > INT_MAX - 2) { - columns = INT_MAX - 2; - } - rows = rowsA; - endOfBlock = endOfBlockA; - black = blackA; - // 0 <= codingLine[0] < codingLine[1] < ... < codingLine[n] = columns - // ---> max codingLine size = columns + 1 - // refLine has one extra guard entry at the end - // ---> max refLine size = columns + 2 - codingLine = (int *)gmallocn(columns + 1, sizeof(int)); - refLine = (int *)gmallocn(columns + 2, sizeof(int)); - - eof = gFalse; - row = 0; - nextLine2D = encoding < 0; - inputBits = 0; - codingLine[0] = columns; - a0i = 1; - outputBits = 0; - - buf = EOF; -} - -CCITTFaxStream::~CCITTFaxStream() { - delete str; - gfree(refLine); - gfree(codingLine); -} - -void CCITTFaxStream::reset() { - short code1; - - str->reset(); - eof = gFalse; - row = 0; - nextLine2D = encoding < 0; - inputBits = 0; - codingLine[0] = columns; - a0i = 1; - outputBits = 0; - buf = EOF; - - // skip any initial zero bits and end-of-line marker, and get the 2D - // encoding tag - while ((code1 = lookBits(12)) == 0) { - eatBits(1); - } - if (code1 == 0x001) { - eatBits(12); - } - if (encoding > 0) { - nextLine2D = !lookBits(1); - eatBits(1); - } -} - -inline void CCITTFaxStream::addPixels(int a1, int blackPixels) { - if (a1 > codingLine[a0i]) { - if (a1 > columns) { - error(getPos(), "CCITTFax row is wrong length (%d)", a1); - err = gTrue; - a1 = columns; - } - if ((a0i & 1) ^ blackPixels) { - ++a0i; - } - codingLine[a0i] = a1; - } -} - -inline void CCITTFaxStream::addPixelsNeg(int a1, int blackPixels) { - if (a1 > codingLine[a0i]) { - if (a1 > columns) { - error(getPos(), "CCITTFax row is wrong length (%d)", a1); - err = gTrue; - a1 = columns; - } - if ((a0i & 1) ^ blackPixels) { - ++a0i; - } - codingLine[a0i] = a1; - } else if (a1 < codingLine[a0i]) { - if (a1 < 0) { - error(getPos(), "Invalid CCITTFax code"); - err = gTrue; - a1 = 0; - } - while (a0i > 0 && a1 <= codingLine[a0i - 1]) { - --a0i; - } - codingLine[a0i] = a1; - } -} - - -int CCITTFaxStream::lookChar() { - short code1, code2, code3; - int b1i, blackPixels, i, bits; - GBool gotEOL; - - if (buf != EOF) { - return buf; - } - - // read the next row - if (outputBits == 0) { - - // if at eof just return EOF - if (eof) { - return EOF; - } - - err = gFalse; - - // 2-D encoding - if (nextLine2D) { - for (i = 0; codingLine[i] < columns; ++i) - refLine[i] = codingLine[i]; - refLine[i++] = columns; - refLine[i] = columns; - codingLine[0] = 0; - a0i = 0; - b1i = 0; - blackPixels = 0; - // invariant: - // refLine[b1i-1] <= codingLine[a0i] < refLine[b1i] < refLine[b1i+1] - // <= columns - // exception at left edge: - // codingLine[a0i = 0] = refLine[b1i = 0] = 0 is possible - // exception at right edge: - // refLine[b1i] = refLine[b1i+1] = columns is possible - while (codingLine[a0i] < columns) { - code1 = getTwoDimCode(); - switch (code1) { - case twoDimPass: - addPixels(refLine[b1i + 1], blackPixels); - if (refLine[b1i + 1] < columns) { - b1i += 2; - } - break; - case twoDimHoriz: - code1 = code2 = 0; - if (blackPixels) { - do { - code1 += code3 = getBlackCode(); - } while (code3 >= 64); - do { - code2 += code3 = getWhiteCode(); - } while (code3 >= 64); - } else { - do { - code1 += code3 = getWhiteCode(); - } while (code3 >= 64); - do { - code2 += code3 = getBlackCode(); - } while (code3 >= 64); - } - addPixels(codingLine[a0i] + code1, blackPixels); - if (codingLine[a0i] < columns) { - addPixels(codingLine[a0i] + code2, blackPixels ^ 1); - } - while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) { - b1i += 2; - } - break; - case twoDimVertR3: - addPixels(refLine[b1i] + 3, blackPixels); - blackPixels ^= 1; - if (codingLine[a0i] < columns) { - ++b1i; - while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) { - b1i += 2; - } - } - break; - case twoDimVertR2: - addPixels(refLine[b1i] + 2, blackPixels); - blackPixels ^= 1; - if (codingLine[a0i] < columns) { - ++b1i; - while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) { - b1i += 2; - } - } - break; - case twoDimVertR1: - addPixels(refLine[b1i] + 1, blackPixels); - blackPixels ^= 1; - if (codingLine[a0i] < columns) { - ++b1i; - while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) { - b1i += 2; - } - } - break; - case twoDimVert0: - addPixels(refLine[b1i], blackPixels); - blackPixels ^= 1; - if (codingLine[a0i] < columns) { - ++b1i; - while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) { - b1i += 2; - } - } - break; - case twoDimVertL3: - addPixelsNeg(refLine[b1i] - 3, blackPixels); - blackPixels ^= 1; - if (codingLine[a0i] < columns) { - if (b1i > 0) { - --b1i; - } else { - ++b1i; - } - while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) { - b1i += 2; - } - } - break; - case twoDimVertL2: - addPixelsNeg(refLine[b1i] - 2, blackPixels); - blackPixels ^= 1; - if (codingLine[a0i] < columns) { - if (b1i > 0) { - --b1i; - } else { - ++b1i; - } - while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) { - b1i += 2; - } - } - break; - case twoDimVertL1: - addPixelsNeg(refLine[b1i] - 1, blackPixels); - blackPixels ^= 1; - if (codingLine[a0i] < columns) { - if (b1i > 0) { - --b1i; - } else { - ++b1i; - } - while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) { - b1i += 2; - } - } - break; - case EOF: - addPixels(columns, 0); - eof = gTrue; - break; - default: - error(getPos(), "Bad 2D code %04x in CCITTFax stream", code1); - addPixels(columns, 0); - err = gTrue; - break; - } - } - - // 1-D encoding - } else { - codingLine[0] = 0; - a0i = 0; - blackPixels = 0; - while (codingLine[a0i] < columns) { - code1 = 0; - if (blackPixels) { - do { - code1 += code3 = getBlackCode(); - } while (code3 >= 64); - } else { - do { - code1 += code3 = getWhiteCode(); - } while (code3 >= 64); - } - addPixels(codingLine[a0i] + code1, blackPixels); - blackPixels ^= 1; - } - } - - // byte-align the row - if (byteAlign) { - inputBits &= ~7; - } - - // check for end-of-line marker, skipping over any extra zero bits - gotEOL = gFalse; - if (!endOfBlock && row == rows - 1) { - eof = gTrue; - } else { - code1 = lookBits(12); - while (code1 == 0) { - eatBits(1); - code1 = lookBits(12); - } - if (code1 == 0x001) { - eatBits(12); - gotEOL = gTrue; - } else if (code1 == EOF) { - eof = gTrue; - } - } - - // get 2D encoding tag - if (!eof && encoding > 0) { - nextLine2D = !lookBits(1); - eatBits(1); - } - - // check for end-of-block marker - if (endOfBlock && gotEOL) { - 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; - } - - // look for an end-of-line marker after an error -- we only do - // this if we know the stream contains end-of-line markers because - // the "just plow on" technique tends to work better otherwise - } else if (err && endOfLine) { - while (1) { - code1 = lookBits(13); - if (code1 == EOF) { - eof = gTrue; - return EOF; - } - if ((code1 >> 1) == 0x001) { - break; - } - eatBits(1); - } - eatBits(12); - if (encoding > 0) { - eatBits(1); - nextLine2D = !(code1 & 1); - } - } - - // set up for output - if (codingLine[0] > 0) { - outputBits = codingLine[a0i = 0]; - } else { - outputBits = codingLine[a0i = 1]; - } - - ++row; - } - - // get a byte - if (outputBits >= 8) { - buf = (a0i & 1) ? 0x00 : 0xff; - outputBits -= 8; - if (outputBits == 0 && codingLine[a0i] < columns) { - ++a0i; - outputBits = codingLine[a0i] - codingLine[a0i - 1]; - } - } else { - bits = 8; - buf = 0; - do { - if (outputBits > bits) { - buf <<= bits; - if (!(a0i & 1)) { - buf |= 0xff >> (8 - bits); - } - outputBits -= bits; - bits = 0; - } else { - buf <<= outputBits; - if (!(a0i & 1)) { - buf |= 0xff >> (8 - outputBits); - } - bits -= outputBits; - outputBits = 0; - if (codingLine[a0i] < columns) { - ++a0i; - outputBits = codingLine[a0i] - codingLine[a0i - 1]; - } else if (bits > 0) { - buf <<= bits; - bits = 0; - } - } - } while (bits); - } - if (black) { - buf ^= 0xff; - } - 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 == EOF) { - return 1; - } - 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 (code == EOF) { - return 1; - } - 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 (code == EOF) { - return 1; - } - 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); - // eat a bit and return a positive number so that the caller doesn't - // go into an infinite loop - eatBits(1); - return 1; -} - -short CCITTFaxStream::getBlackCode() { - short code; - CCITTCode *p; - int n; - - code = 0; // make gcc happy - if (endOfBlock) { - code = lookBits(13); - if (code == EOF) { - return 1; - } - if ((code >> 7) == 0) { - p = &blackTab1[code]; - } else if ((code >> 9) == 0 && (code >> 7) != 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 (code == EOF) { - return 1; - } - 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 (code == EOF) { - return 1; - } - 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 (code == EOF) { - return 1; - } - 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); - // eat a bit and return a positive number so that the caller doesn't - // go into an infinite loop - eatBits(1); - return 1; -} - -short CCITTFaxStream::lookBits(int n) { - int c; - - while (inputBits < n) { - if ((c = str->getChar()) == EOF) { - if (inputBits == 0) { - return EOF; - } - // near the end of the stream, the caller may ask for more bits - // than are available, but there may still be a valid code in - // however many bits are available -- we need to return correct - // data in this case - return (inputBuf << (n - inputBits)) & (0xffff >> (16 - n)); - } - inputBuf = (inputBuf << 8) + c; - inputBits += 8; - } - return (inputBuf >> (inputBits - n)) & (0xffff >> (16 - n)); -} - -GString *CCITTFaxStream::getPSFilter(int psLevel, char *indent) { - GString *s; - char s1[50]; - - if (psLevel < 2) { - return NULL; - } - if (!(s = str->getPSFilter(psLevel, indent))) { - return NULL; - } - 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) -#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 - -// 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 *strA): - FilterStream(strA) { - int i, j; - - progressive = interleaved = gFalse; - 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; - } - frameBuf[i] = 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; - if (progressive || !interleaved) { - for (i = 0; i < numComps; ++i) { - gfree(frameBuf[i]); - } - } else { - for (i = 0; i < numComps; ++i) { - for (j = 0; j < mcuHeight; ++j) { - gfree(rowBuf[i][j]); - } - } - } -} - -void DCTStream::reset() { - int i, j; - - str->reset(); - - progressive = interleaved = gFalse; - width = height = 0; - numComps = 0; - numQuantTables = 0; - numDCHuffTables = 0; - numACHuffTables = 0; - colorXform = 0; - gotJFIFMarker = gFalse; - gotAdobeMarker = gFalse; - restartInterval = 0; - - if (!readHeader()) { - y = height; - return; - } - - // compute MCU size - if (numComps == 1) { - compInfo[0].hSample = compInfo[0].vSample = 1; - } - mcuWidth = compInfo[0].hSample; - mcuHeight = compInfo[0].vSample; - for (i = 1; i < numComps; ++i) { - if (compInfo[i].hSample > mcuWidth) { - mcuWidth = compInfo[i].hSample; - } - if (compInfo[i].vSample > mcuHeight) { - mcuHeight = compInfo[i].vSample; - } - } - mcuWidth *= 8; - mcuHeight *= 8; - - // figure out color transform - if (!gotAdobeMarker && numComps == 3) { - if (gotJFIFMarker) { - colorXform = 1; - } else if (compInfo[0].id == 82 && compInfo[1].id == 71 && - compInfo[2].id == 66) { // ASCII "RGB" - colorXform = 0; - } else { - colorXform = 1; - } - } - - if (progressive || !interleaved) { - - // allocate a buffer for the whole image - bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth; - bufHeight = ((height + mcuHeight - 1) / mcuHeight) * mcuHeight; - if (bufWidth <= 0 || bufHeight <= 0 || - bufWidth > INT_MAX / bufWidth / (int)sizeof(int)) { - error(getPos(), "Invalid image size in DCT stream"); - y = height; - return; - } - for (i = 0; i < numComps; ++i) { - frameBuf[i] = (int *)gmallocn(bufWidth * bufHeight, sizeof(int)); - memset(frameBuf[i], 0, bufWidth * bufHeight * sizeof(int)); - } - - // read the image data - do { - restartMarker = 0xd0; - restart(); - readScan(); - } while (readHeader()); - - // decode - decodeImage(); - - // initialize counters - comp = 0; - x = 0; - y = 0; - - } else { - - // allocate a buffer for one row of MCUs - bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth; - for (i = 0; i < numComps; ++i) { - for (j = 0; j < mcuHeight; ++j) { - rowBuf[i][j] = (Guchar *)gmallocn(bufWidth, sizeof(Guchar)); - } - } - - // initialize counters - comp = 0; - x = 0; - y = 0; - dy = mcuHeight; - - restartMarker = 0xd0; - restart(); - } -} - -int DCTStream::getChar() { - int c; - - if (y >= height) { - return EOF; - } - if (progressive || !interleaved) { - c = frameBuf[comp][y * bufWidth + x]; - if (++comp == numComps) { - comp = 0; - if (++x == width) { - x = 0; - ++y; - } - } - } else { - if (dy >= mcuHeight) { - if (!readMCURow()) { - y = height; - return EOF; - } - comp = 0; - x = 0; - dy = 0; - } - c = rowBuf[comp][dy][x]; - 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 (progressive || !interleaved) { - return frameBuf[comp][y * bufWidth + x]; - } else { - 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; - } - eobRun = 0; -} - -// Read one row of MCUs from a sequential JPEG stream. -GBool DCTStream::readMCURow() { - int data1[64]; - Guchar data2[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[scanInfo.dcHuffTable[cc]], - &acHuffTables[scanInfo.acHuffTable[cc]], - &compInfo[cc].prevDC, - data1)) { - return gFalse; - } - transformDataUnit(quantTables[compInfo[cc].quantTable], - data1, data2); - if (hSub == 1 && vSub == 1) { - for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) { - p1 = &rowBuf[cc][y2+y3][x1+x2]; - p1[0] = data2[i]; - p1[1] = data2[i+1]; - p1[2] = data2[i+2]; - p1[3] = data2[i+3]; - p1[4] = data2[i+4]; - p1[5] = data2[i+5]; - p1[6] = data2[i+6]; - p1[7] = data2[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] = data2[i]; - p1[2] = p1[3] = p2[2] = p2[3] = data2[i+1]; - p1[4] = p1[5] = p2[4] = p2[5] = data2[i+2]; - p1[6] = p1[7] = p2[6] = p2[7] = data2[i+3]; - p1[8] = p1[9] = p2[8] = p2[9] = data2[i+4]; - p1[10] = p1[11] = p2[10] = p2[11] = data2[i+5]; - p1[12] = p1[13] = p2[12] = p2[13] = data2[i+6]; - p1[14] = p1[15] = p2[14] = p2[15] = data2[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] = data2[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 + 32768) >> 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; -} - -// Read one scan from a progressive or non-interleaved JPEG stream. -void DCTStream::readScan() { - int data[64]; - int x1, y1, dx1, dy1, x2, y2, y3, cc, i; - int h, v, horiz, vert, vSub; - int *p1; - int c; - - if (scanInfo.numComps == 1) { - for (cc = 0; cc < numComps; ++cc) { - if (scanInfo.comp[cc]) { - break; - } - } - dx1 = mcuWidth / compInfo[cc].hSample; - dy1 = mcuHeight / compInfo[cc].vSample; - } else { - dx1 = mcuWidth; - dy1 = mcuHeight; - } - - for (y1 = 0; y1 < height; y1 += dy1) { - for (x1 = 0; x1 < width; x1 += dx1) { - - // deal with restart marker - if (restartInterval > 0 && restartCtr == 0) { - c = readMarker(); - if (c != restartMarker) { - error(getPos(), "Bad DCT data: incorrect restart marker"); - return; - } - if (++restartMarker == 0xd8) { - restartMarker = 0xd0; - } - restart(); - } - - // read one MCU - for (cc = 0; cc < numComps; ++cc) { - if (!scanInfo.comp[cc]) { - continue; - } - - h = compInfo[cc].hSample; - v = compInfo[cc].vSample; - horiz = mcuWidth / h; - vert = mcuHeight / v; - vSub = vert / 8; - for (y2 = 0; y2 < dy1; y2 += vert) { - for (x2 = 0; x2 < dx1; x2 += horiz) { - - // pull out the current values - p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)]; - for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) { - data[i] = p1[0]; - data[i+1] = p1[1]; - data[i+2] = p1[2]; - data[i+3] = p1[3]; - data[i+4] = p1[4]; - data[i+5] = p1[5]; - data[i+6] = p1[6]; - data[i+7] = p1[7]; - p1 += bufWidth * vSub; - } - - // read one data unit - if (progressive) { - if (!readProgressiveDataUnit( - &dcHuffTables[scanInfo.dcHuffTable[cc]], - &acHuffTables[scanInfo.acHuffTable[cc]], - &compInfo[cc].prevDC, - data)) { - return; - } - } else { - if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]], - &acHuffTables[scanInfo.acHuffTable[cc]], - &compInfo[cc].prevDC, - data)) { - return; - } - } - - // add the data unit into frameBuf - p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)]; - for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) { - 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]; - p1 += bufWidth * vSub; - } - } - } - } - --restartCtr; - } - } -} - -// Read one data unit from a sequential JPEG stream. -GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable, - DCTHuffTable *acHuffTable, - int *prevDC, int data[64]) { - int run, size, amp; - int c; - int i, j; - - if ((size = readHuffSym(dcHuffTable)) == 9999) { - return gFalse; - } - if (size > 0) { - if ((amp = readAmp(size)) == 9999) { - return gFalse; - } - } else { - amp = 0; - } - data[0] = *prevDC += amp; - for (i = 1; i < 64; ++i) { - data[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; - if (i < 64) { - j = dctZigZag[i++]; - data[j] = amp; - } - } - } - return gTrue; -} - -// Read one data unit from a sequential JPEG stream. -GBool DCTStream::readProgressiveDataUnit(DCTHuffTable *dcHuffTable, - DCTHuffTable *acHuffTable, - int *prevDC, int data[64]) { - int run, size, amp, bit, c; - int i, j, k; - - // get the DC coefficient - i = scanInfo.firstCoeff; - if (i == 0) { - if (scanInfo.ah == 0) { - if ((size = readHuffSym(dcHuffTable)) == 9999) { - return gFalse; - } - if (size > 0) { - if ((amp = readAmp(size)) == 9999) { - return gFalse; - } - } else { - amp = 0; - } - data[0] += (*prevDC += amp) << scanInfo.al; - } else { - if ((bit = readBit()) == 9999) { - return gFalse; - } - data[0] += bit << scanInfo.al; - } - ++i; - } - if (scanInfo.lastCoeff == 0) { - return gTrue; - } - - // check for an EOB run - if (eobRun > 0) { - while (i <= scanInfo.lastCoeff) { - j = dctZigZag[i++]; - if (data[j] != 0) { - if ((bit = readBit()) == EOF) { - return gFalse; - } - if (bit) { - data[j] += 1 << scanInfo.al; - } - } - } - --eobRun; - return gTrue; - } - - // read the AC coefficients - while (i <= scanInfo.lastCoeff) { - if ((c = readHuffSym(acHuffTable)) == 9999) { - return gFalse; - } - - // ZRL - if (c == 0xf0) { - k = 0; - while (k < 16) { - j = dctZigZag[i++]; - if (data[j] == 0) { - ++k; - } else { - if ((bit = readBit()) == EOF) { - return gFalse; - } - if (bit) { - data[j] += 1 << scanInfo.al; - } - } - } - - // EOB run - } else if ((c & 0x0f) == 0x00) { - j = c >> 4; - eobRun = 0; - for (k = 0; k < j; ++k) { - if ((bit = readBit()) == EOF) { - return gFalse; - } - eobRun = (eobRun << 1) | bit; - } - eobRun += 1 << j; - while (i <= scanInfo.lastCoeff) { - j = dctZigZag[i++]; - if (data[j] != 0) { - if ((bit = readBit()) == EOF) { - return gFalse; - } - if (bit) { - data[j] += 1 << scanInfo.al; - } - } - } - --eobRun; - break; - - // zero run and one AC coefficient - } else { - run = (c >> 4) & 0x0f; - size = c & 0x0f; - if ((amp = readAmp(size)) == 9999) { - return gFalse; - } - k = 0; - do { - j = dctZigZag[i++]; - while (data[j] != 0) { - if ((bit = readBit()) == EOF) { - return gFalse; - } - if (bit) { - data[j] += 1 << scanInfo.al; - } - j = dctZigZag[i++]; - } - ++k; - } while (k <= run); - data[j] = amp << scanInfo.al; - } - } - - return gTrue; -} - -// Decode a progressive JPEG image. -void DCTStream::decodeImage() { - int dataIn[64]; - Guchar dataOut[64]; - Gushort *quantTable; - int pY, pCb, pCr, pR, pG, pB; - int x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i; - int h, v, horiz, vert, hSub, vSub; - int *p0, *p1, *p2; - - for (y1 = 0; y1 < bufHeight; y1 += mcuHeight) { - for (x1 = 0; x1 < bufWidth; x1 += mcuWidth) { - for (cc = 0; cc < numComps; ++cc) { - quantTable = quantTables[compInfo[cc].quantTable]; - 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) { - - // pull out the coded data unit - p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)]; - for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) { - dataIn[i] = p1[0]; - dataIn[i+1] = p1[1]; - dataIn[i+2] = p1[2]; - dataIn[i+3] = p1[3]; - dataIn[i+4] = p1[4]; - dataIn[i+5] = p1[5]; - dataIn[i+6] = p1[6]; - dataIn[i+7] = p1[7]; - p1 += bufWidth * vSub; - } - - // transform - transformDataUnit(quantTable, dataIn, dataOut); - - // store back into frameBuf, doing replication for - // subsampled components - p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)]; - if (hSub == 1 && vSub == 1) { - for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) { - p1[0] = dataOut[i] & 0xff; - p1[1] = dataOut[i+1] & 0xff; - p1[2] = dataOut[i+2] & 0xff; - p1[3] = dataOut[i+3] & 0xff; - p1[4] = dataOut[i+4] & 0xff; - p1[5] = dataOut[i+5] & 0xff; - p1[6] = dataOut[i+6] & 0xff; - p1[7] = dataOut[i+7] & 0xff; - p1 += bufWidth; - } - } else if (hSub == 2 && vSub == 2) { - p2 = p1 + bufWidth; - for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) { - p1[0] = p1[1] = p2[0] = p2[1] = dataOut[i] & 0xff; - p1[2] = p1[3] = p2[2] = p2[3] = dataOut[i+1] & 0xff; - p1[4] = p1[5] = p2[4] = p2[5] = dataOut[i+2] & 0xff; - p1[6] = p1[7] = p2[6] = p2[7] = dataOut[i+3] & 0xff; - p1[8] = p1[9] = p2[8] = p2[9] = dataOut[i+4] & 0xff; - p1[10] = p1[11] = p2[10] = p2[11] = dataOut[i+5] & 0xff; - p1[12] = p1[13] = p2[12] = p2[13] = dataOut[i+6] & 0xff; - p1[14] = p1[15] = p2[14] = p2[15] = dataOut[i+7] & 0xff; - p1 += bufWidth * 2; - p2 += bufWidth * 2; - } - } else { - i = 0; - for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) { - for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) { - p2 = p1 + x4; - for (y5 = 0; y5 < vSub; ++y5) { - for (x5 = 0; x5 < hSub; ++x5) { - p2[x5] = dataOut[i] & 0xff; - } - p2 += bufWidth; - } - ++i; - } - p1 += bufWidth * vSub; - } - } - } - } - } - - // color space conversion - if (colorXform) { - // convert YCbCr to RGB - if (numComps == 3) { - for (y2 = 0; y2 < mcuHeight; ++y2) { - p0 = &frameBuf[0][(y1+y2) * bufWidth + x1]; - p1 = &frameBuf[1][(y1+y2) * bufWidth + x1]; - p2 = &frameBuf[2][(y1+y2) * bufWidth + x1]; - for (x2 = 0; x2 < mcuWidth; ++x2) { - pY = *p0; - pCb = *p1 - 128; - pCr = *p2 - 128; - pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16; - *p0++ = dctClip[dctClipOffset + pR]; - pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + - 32768) >> 16; - *p1++ = dctClip[dctClipOffset + pG]; - pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16; - *p2++ = dctClip[dctClipOffset + pB]; - } - } - // convert YCbCrK to CMYK (K is passed through unchanged) - } else if (numComps == 4) { - for (y2 = 0; y2 < mcuHeight; ++y2) { - p0 = &frameBuf[0][(y1+y2) * bufWidth + x1]; - p1 = &frameBuf[1][(y1+y2) * bufWidth + x1]; - p2 = &frameBuf[2][(y1+y2) * bufWidth + x1]; - for (x2 = 0; x2 < mcuWidth; ++x2) { - pY = *p0; - pCb = *p1 - 128; - pCr = *p2 - 128; - pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16; - *p0++ = 255 - dctClip[dctClipOffset + pR]; - pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + - 32768) >> 16; - *p1++ = 255 - dctClip[dctClipOffset + pG]; - pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16; - *p2++ = 255 - dctClip[dctClipOffset + pB]; - } - } - } - } - } - } -} - -// Transform one data unit -- this performs the dequantization and -// IDCT steps. 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. -void DCTStream::transformDataUnit(Gushort *quantTable, - int dataIn[64], Guchar dataOut[64]) { - int v0, v1, v2, v3, v4, v5, v6, v7, t; - int *p; - int i; - - // dequant - for (i = 0; i < 64; ++i) { - dataIn[i] *= quantTable[i]; - } - - // inverse DCT on rows - for (i = 0; i < 64; i += 8) { - p = dataIn + i; - - // check for all-zero AC coefficients - if (p[1] == 0 && p[2] == 0 && p[3] == 0 && - p[4] == 0 && p[5] == 0 && p[6] == 0 && p[7] == 0) { - t = (dctSqrt2 * p[0] + 512) >> 10; - p[0] = t; - p[1] = t; - p[2] = t; - p[3] = t; - p[4] = t; - p[5] = t; - p[6] = t; - p[7] = t; - continue; - } - - // stage 4 - v0 = (dctSqrt2 * p[0] + 128) >> 8; - v1 = (dctSqrt2 * p[4] + 128) >> 8; - v2 = p[2]; - v3 = p[6]; - v4 = (dctSqrt1d2 * (p[1] - p[7]) + 128) >> 8; - v7 = (dctSqrt1d2 * (p[1] + p[7]) + 128) >> 8; - v5 = p[3] << 4; - v6 = p[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 - p[0] = v0 + v7; - p[7] = v0 - v7; - p[1] = v1 + v6; - p[6] = v1 - v6; - p[2] = v2 + v5; - p[5] = v2 - v5; - p[3] = v3 + v4; - p[4] = v3 - v4; - } - - // inverse DCT on columns - for (i = 0; i < 8; ++i) { - p = dataIn + i; - - // check for all-zero AC coefficients - if (p[1*8] == 0 && p[2*8] == 0 && p[3*8] == 0 && - p[4*8] == 0 && p[5*8] == 0 && p[6*8] == 0 && p[7*8] == 0) { - t = (dctSqrt2 * dataIn[i+0] + 8192) >> 14; - p[0*8] = t; - p[1*8] = t; - p[2*8] = t; - p[3*8] = t; - p[4*8] = t; - p[5*8] = t; - p[6*8] = t; - p[7*8] = t; - continue; - } - - // stage 4 - v0 = (dctSqrt2 * p[0*8] + 2048) >> 12; - v1 = (dctSqrt2 * p[4*8] + 2048) >> 12; - v2 = p[2*8]; - v3 = p[6*8]; - v4 = (dctSqrt1d2 * (p[1*8] - p[7*8]) + 2048) >> 12; - v7 = (dctSqrt1d2 * (p[1*8] + p[7*8]) + 2048) >> 12; - v5 = p[3*8]; - v6 = p[5*8]; - - // 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 - p[0*8] = v0 + v7; - p[7*8] = v0 - v7; - p[1*8] = v1 + v6; - p[6*8] = v1 - v6; - p[2*8] = v2 + v5; - p[5*8] = v2 - v5; - p[3*8] = v3 + v4; - p[4*8] = v3 - v4; - } - - // convert to 8-bit integers - for (i = 0; i < 64; ++i) { - dataOut[i] = dctClip[dctClipOffset + 128 + ((dataIn[i] + 8) >> 4)]; - } -} - -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 n; - int c = 0; - int i; - - // read headers - doScan = gFalse; - while (!doScan) { - c = readMarker(); - switch (c) { - case 0xc0: // SOF0 (sequential) - case 0xc1: // SOF1 (extended sequential) - if (!readBaselineSOF()) { - return gFalse; - } - break; - case 0xc2: // SOF2 (progressive) - if (!readProgressiveSOF()) { - return gFalse; - } - break; - case 0xc4: // DHT - if (!readHuffmanTables()) { - return gFalse; - } - break; - case 0xd8: // SOI - break; - case 0xd9: // EOI - return gFalse; - 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 0xe0: // APP0 - if (!readJFIFMarker()) { - 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; - } - } - - return gTrue; -} - -GBool DCTStream::readBaselineSOF() { - int length; - int prec; - int i; - int c; - - length = read16(); - prec = str->getChar(); - height = read16(); - width = read16(); - numComps = str->getChar(); - if (numComps <= 0 || numComps > 4) { - error(getPos(), "Bad number of components in DCT stream"); - numComps = 0; - return gFalse; - } - if (prec != 8) { - error(getPos(), "Bad DCT precision %d", prec); - return gFalse; - } - for (i = 0; i < numComps; ++i) { - compInfo[i].id = str->getChar(); - c = str->getChar(); - compInfo[i].hSample = (c >> 4) & 0x0f; - compInfo[i].vSample = c & 0x0f; - compInfo[i].quantTable = str->getChar(); - } - progressive = gFalse; - return gTrue; -} - -GBool DCTStream::readProgressiveSOF() { - int length; - int prec; - int i; - int c; - - length = read16(); - prec = str->getChar(); - height = read16(); - width = read16(); - numComps = str->getChar(); - if (numComps <= 0 || numComps > 4) { - error(getPos(), "Bad number of components in DCT stream"); - numComps = 0; - return gFalse; - } - if (prec != 8) { - error(getPos(), "Bad DCT precision %d", prec); - return gFalse; - } - for (i = 0; i < numComps; ++i) { - compInfo[i].id = str->getChar(); - c = str->getChar(); - compInfo[i].hSample = (c >> 4) & 0x0f; - compInfo[i].vSample = c & 0x0f; - compInfo[i].quantTable = str->getChar(); - } - progressive = gTrue; - return gTrue; -} - -GBool DCTStream::readScanInfo() { - int length; - int id, c; - int i, j; - - length = read16() - 2; - scanInfo.numComps = str->getChar(); - if (scanInfo.numComps <= 0 || scanInfo.numComps > 4) { - error(getPos(), "Bad number of components in DCT stream"); - scanInfo.numComps = 0; - return gFalse; - } - --length; - if (length != 2 * scanInfo.numComps + 3) { - error(getPos(), "Bad DCT scan info block"); - return gFalse; - } - interleaved = scanInfo.numComps == numComps; - for (j = 0; j < numComps; ++j) { - scanInfo.comp[j] = gFalse; - } - for (i = 0; i < scanInfo.numComps; ++i) { - id = str->getChar(); - // some (broken) DCT streams reuse ID numbers, but at least they - // keep the components in order, so we check compInfo[i] first to - // work around the problem - if (id == compInfo[i].id) { - j = i; - } else { - 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; - } - } - scanInfo.comp[j] = gTrue; - c = str->getChar(); - scanInfo.dcHuffTable[j] = (c >> 4) & 0x0f; - scanInfo.acHuffTable[j] = c & 0x0f; - } - scanInfo.firstCoeff = str->getChar(); - scanInfo.lastCoeff = str->getChar(); - if (scanInfo.firstCoeff < 0 || scanInfo.lastCoeff > 63 || - scanInfo.firstCoeff > scanInfo.lastCoeff) { - error(getPos(), "Bad DCT coefficient numbers in scan info block"); - return gFalse; - } - c = str->getChar(); - scanInfo.ah = (c >> 4) & 0x0f; - scanInfo.al = c & 0x0f; - return gTrue; -} - -GBool DCTStream::readQuantTables() { - int length, prec, i, index; - - length = read16() - 2; - while (length > 0) { - index = str->getChar(); - prec = (index >> 4) & 0x0f; - index &= 0x0f; - if (prec > 1 || index >= 4) { - error(getPos(), "Bad DCT quantization table"); - return gFalse; - } - if (index == numQuantTables) { - numQuantTables = index + 1; - } - for (i = 0; i < 64; ++i) { - if (prec) { - quantTables[index][dctZigZag[i]] = read16(); - } else { - quantTables[index][dctZigZag[i]] = str->getChar(); - } - } - if (prec) { - length -= 129; - } else { - 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 { - index &= 0x0f; - 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::readJFIFMarker() { - int length, i; - char buf[5]; - int c; - - length = read16(); - length -= 2; - if (length >= 5) { - for (i = 0; i < 5; ++i) { - if ((c = str->getChar()) == EOF) { - error(getPos(), "Bad DCT APP0 marker"); - return gFalse; - } - buf[i] = c; - } - length -= 5; - if (!memcmp(buf, "JFIF\0", 5)) { - gotJFIFMarker = gTrue; - } - } - while (length > 0) { - if (str->getChar() == EOF) { - error(getPos(), "Bad DCT APP0 marker"); - return gFalse; - } - --length; - } - 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; - for (i = 14; i < length; ++i) { - if (str->getChar() == EOF) { - goto err; - } - } - 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 && c != EOF); - 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(int psLevel, char *indent) { - GString *s; - - if (psLevel < 2) { - return NULL; - } - if (!(s = str->getPSFilter(psLevel, indent))) { - return NULL; - } - 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}, - {0, 258}, - {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} -}; - -static FlateCode flateFixedLitCodeTabCodes[512] = { - {7, 0x0100}, - {8, 0x0050}, - {8, 0x0010}, - {8, 0x0118}, - {7, 0x0110}, - {8, 0x0070}, - {8, 0x0030}, - {9, 0x00c0}, - {7, 0x0108}, - {8, 0x0060}, - {8, 0x0020}, - {9, 0x00a0}, - {8, 0x0000}, - {8, 0x0080}, - {8, 0x0040}, - {9, 0x00e0}, - {7, 0x0104}, - {8, 0x0058}, - {8, 0x0018}, - {9, 0x0090}, - {7, 0x0114}, - {8, 0x0078}, - {8, 0x0038}, - {9, 0x00d0}, - {7, 0x010c}, - {8, 0x0068}, - {8, 0x0028}, - {9, 0x00b0}, - {8, 0x0008}, - {8, 0x0088}, - {8, 0x0048}, - {9, 0x00f0}, - {7, 0x0102}, - {8, 0x0054}, - {8, 0x0014}, - {8, 0x011c}, - {7, 0x0112}, - {8, 0x0074}, - {8, 0x0034}, - {9, 0x00c8}, - {7, 0x010a}, - {8, 0x0064}, - {8, 0x0024}, - {9, 0x00a8}, - {8, 0x0004}, - {8, 0x0084}, - {8, 0x0044}, - {9, 0x00e8}, - {7, 0x0106}, - {8, 0x005c}, - {8, 0x001c}, - {9, 0x0098}, - {7, 0x0116}, - {8, 0x007c}, - {8, 0x003c}, - {9, 0x00d8}, - {7, 0x010e}, - {8, 0x006c}, - {8, 0x002c}, - {9, 0x00b8}, - {8, 0x000c}, - {8, 0x008c}, - {8, 0x004c}, - {9, 0x00f8}, - {7, 0x0101}, - {8, 0x0052}, - {8, 0x0012}, - {8, 0x011a}, - {7, 0x0111}, - {8, 0x0072}, - {8, 0x0032}, - {9, 0x00c4}, - {7, 0x0109}, - {8, 0x0062}, - {8, 0x0022}, - {9, 0x00a4}, - {8, 0x0002}, - {8, 0x0082}, - {8, 0x0042}, - {9, 0x00e4}, - {7, 0x0105}, - {8, 0x005a}, - {8, 0x001a}, - {9, 0x0094}, - {7, 0x0115}, - {8, 0x007a}, - {8, 0x003a}, - {9, 0x00d4}, - {7, 0x010d}, - {8, 0x006a}, - {8, 0x002a}, - {9, 0x00b4}, - {8, 0x000a}, - {8, 0x008a}, - {8, 0x004a}, - {9, 0x00f4}, - {7, 0x0103}, - {8, 0x0056}, - {8, 0x0016}, - {8, 0x011e}, - {7, 0x0113}, - {8, 0x0076}, - {8, 0x0036}, - {9, 0x00cc}, - {7, 0x010b}, - {8, 0x0066}, - {8, 0x0026}, - {9, 0x00ac}, - {8, 0x0006}, - {8, 0x0086}, - {8, 0x0046}, - {9, 0x00ec}, - {7, 0x0107}, - {8, 0x005e}, - {8, 0x001e}, - {9, 0x009c}, - {7, 0x0117}, - {8, 0x007e}, - {8, 0x003e}, - {9, 0x00dc}, - {7, 0x010f}, - {8, 0x006e}, - {8, 0x002e}, - {9, 0x00bc}, - {8, 0x000e}, - {8, 0x008e}, - {8, 0x004e}, - {9, 0x00fc}, - {7, 0x0100}, - {8, 0x0051}, - {8, 0x0011}, - {8, 0x0119}, - {7, 0x0110}, - {8, 0x0071}, - {8, 0x0031}, - {9, 0x00c2}, - {7, 0x0108}, - {8, 0x0061}, - {8, 0x0021}, - {9, 0x00a2}, - {8, 0x0001}, - {8, 0x0081}, - {8, 0x0041}, - {9, 0x00e2}, - {7, 0x0104}, - {8, 0x0059}, - {8, 0x0019}, - {9, 0x0092}, - {7, 0x0114}, - {8, 0x0079}, - {8, 0x0039}, - {9, 0x00d2}, - {7, 0x010c}, - {8, 0x0069}, - {8, 0x0029}, - {9, 0x00b2}, - {8, 0x0009}, - {8, 0x0089}, - {8, 0x0049}, - {9, 0x00f2}, - {7, 0x0102}, - {8, 0x0055}, - {8, 0x0015}, - {8, 0x011d}, - {7, 0x0112}, - {8, 0x0075}, - {8, 0x0035}, - {9, 0x00ca}, - {7, 0x010a}, - {8, 0x0065}, - {8, 0x0025}, - {9, 0x00aa}, - {8, 0x0005}, - {8, 0x0085}, - {8, 0x0045}, - {9, 0x00ea}, - {7, 0x0106}, - {8, 0x005d}, - {8, 0x001d}, - {9, 0x009a}, - {7, 0x0116}, - {8, 0x007d}, - {8, 0x003d}, - {9, 0x00da}, - {7, 0x010e}, - {8, 0x006d}, - {8, 0x002d}, - {9, 0x00ba}, - {8, 0x000d}, - {8, 0x008d}, - {8, 0x004d}, - {9, 0x00fa}, - {7, 0x0101}, - {8, 0x0053}, - {8, 0x0013}, - {8, 0x011b}, - {7, 0x0111}, - {8, 0x0073}, - {8, 0x0033}, - {9, 0x00c6}, - {7, 0x0109}, - {8, 0x0063}, - {8, 0x0023}, - {9, 0x00a6}, - {8, 0x0003}, - {8, 0x0083}, - {8, 0x0043}, - {9, 0x00e6}, - {7, 0x0105}, - {8, 0x005b}, - {8, 0x001b}, - {9, 0x0096}, - {7, 0x0115}, - {8, 0x007b}, - {8, 0x003b}, - {9, 0x00d6}, - {7, 0x010d}, - {8, 0x006b}, - {8, 0x002b}, - {9, 0x00b6}, - {8, 0x000b}, - {8, 0x008b}, - {8, 0x004b}, - {9, 0x00f6}, - {7, 0x0103}, - {8, 0x0057}, - {8, 0x0017}, - {8, 0x011f}, - {7, 0x0113}, - {8, 0x0077}, - {8, 0x0037}, - {9, 0x00ce}, - {7, 0x010b}, - {8, 0x0067}, - {8, 0x0027}, - {9, 0x00ae}, - {8, 0x0007}, - {8, 0x0087}, - {8, 0x0047}, - {9, 0x00ee}, - {7, 0x0107}, - {8, 0x005f}, - {8, 0x001f}, - {9, 0x009e}, - {7, 0x0117}, - {8, 0x007f}, - {8, 0x003f}, - {9, 0x00de}, - {7, 0x010f}, - {8, 0x006f}, - {8, 0x002f}, - {9, 0x00be}, - {8, 0x000f}, - {8, 0x008f}, - {8, 0x004f}, - {9, 0x00fe}, - {7, 0x0100}, - {8, 0x0050}, - {8, 0x0010}, - {8, 0x0118}, - {7, 0x0110}, - {8, 0x0070}, - {8, 0x0030}, - {9, 0x00c1}, - {7, 0x0108}, - {8, 0x0060}, - {8, 0x0020}, - {9, 0x00a1}, - {8, 0x0000}, - {8, 0x0080}, - {8, 0x0040}, - {9, 0x00e1}, - {7, 0x0104}, - {8, 0x0058}, - {8, 0x0018}, - {9, 0x0091}, - {7, 0x0114}, - {8, 0x0078}, - {8, 0x0038}, - {9, 0x00d1}, - {7, 0x010c}, - {8, 0x0068}, - {8, 0x0028}, - {9, 0x00b1}, - {8, 0x0008}, - {8, 0x0088}, - {8, 0x0048}, - {9, 0x00f1}, - {7, 0x0102}, - {8, 0x0054}, - {8, 0x0014}, - {8, 0x011c}, - {7, 0x0112}, - {8, 0x0074}, - {8, 0x0034}, - {9, 0x00c9}, - {7, 0x010a}, - {8, 0x0064}, - {8, 0x0024}, - {9, 0x00a9}, - {8, 0x0004}, - {8, 0x0084}, - {8, 0x0044}, - {9, 0x00e9}, - {7, 0x0106}, - {8, 0x005c}, - {8, 0x001c}, - {9, 0x0099}, - {7, 0x0116}, - {8, 0x007c}, - {8, 0x003c}, - {9, 0x00d9}, - {7, 0x010e}, - {8, 0x006c}, - {8, 0x002c}, - {9, 0x00b9}, - {8, 0x000c}, - {8, 0x008c}, - {8, 0x004c}, - {9, 0x00f9}, - {7, 0x0101}, - {8, 0x0052}, - {8, 0x0012}, - {8, 0x011a}, - {7, 0x0111}, - {8, 0x0072}, - {8, 0x0032}, - {9, 0x00c5}, - {7, 0x0109}, - {8, 0x0062}, - {8, 0x0022}, - {9, 0x00a5}, - {8, 0x0002}, - {8, 0x0082}, - {8, 0x0042}, - {9, 0x00e5}, - {7, 0x0105}, - {8, 0x005a}, - {8, 0x001a}, - {9, 0x0095}, - {7, 0x0115}, - {8, 0x007a}, - {8, 0x003a}, - {9, 0x00d5}, - {7, 0x010d}, - {8, 0x006a}, - {8, 0x002a}, - {9, 0x00b5}, - {8, 0x000a}, - {8, 0x008a}, - {8, 0x004a}, - {9, 0x00f5}, - {7, 0x0103}, - {8, 0x0056}, - {8, 0x0016}, - {8, 0x011e}, - {7, 0x0113}, - {8, 0x0076}, - {8, 0x0036}, - {9, 0x00cd}, - {7, 0x010b}, - {8, 0x0066}, - {8, 0x0026}, - {9, 0x00ad}, - {8, 0x0006}, - {8, 0x0086}, - {8, 0x0046}, - {9, 0x00ed}, - {7, 0x0107}, - {8, 0x005e}, - {8, 0x001e}, - {9, 0x009d}, - {7, 0x0117}, - {8, 0x007e}, - {8, 0x003e}, - {9, 0x00dd}, - {7, 0x010f}, - {8, 0x006e}, - {8, 0x002e}, - {9, 0x00bd}, - {8, 0x000e}, - {8, 0x008e}, - {8, 0x004e}, - {9, 0x00fd}, - {7, 0x0100}, - {8, 0x0051}, - {8, 0x0011}, - {8, 0x0119}, - {7, 0x0110}, - {8, 0x0071}, - {8, 0x0031}, - {9, 0x00c3}, - {7, 0x0108}, - {8, 0x0061}, - {8, 0x0021}, - {9, 0x00a3}, - {8, 0x0001}, - {8, 0x0081}, - {8, 0x0041}, - {9, 0x00e3}, - {7, 0x0104}, - {8, 0x0059}, - {8, 0x0019}, - {9, 0x0093}, - {7, 0x0114}, - {8, 0x0079}, - {8, 0x0039}, - {9, 0x00d3}, - {7, 0x010c}, - {8, 0x0069}, - {8, 0x0029}, - {9, 0x00b3}, - {8, 0x0009}, - {8, 0x0089}, - {8, 0x0049}, - {9, 0x00f3}, - {7, 0x0102}, - {8, 0x0055}, - {8, 0x0015}, - {8, 0x011d}, - {7, 0x0112}, - {8, 0x0075}, - {8, 0x0035}, - {9, 0x00cb}, - {7, 0x010a}, - {8, 0x0065}, - {8, 0x0025}, - {9, 0x00ab}, - {8, 0x0005}, - {8, 0x0085}, - {8, 0x0045}, - {9, 0x00eb}, - {7, 0x0106}, - {8, 0x005d}, - {8, 0x001d}, - {9, 0x009b}, - {7, 0x0116}, - {8, 0x007d}, - {8, 0x003d}, - {9, 0x00db}, - {7, 0x010e}, - {8, 0x006d}, - {8, 0x002d}, - {9, 0x00bb}, - {8, 0x000d}, - {8, 0x008d}, - {8, 0x004d}, - {9, 0x00fb}, - {7, 0x0101}, - {8, 0x0053}, - {8, 0x0013}, - {8, 0x011b}, - {7, 0x0111}, - {8, 0x0073}, - {8, 0x0033}, - {9, 0x00c7}, - {7, 0x0109}, - {8, 0x0063}, - {8, 0x0023}, - {9, 0x00a7}, - {8, 0x0003}, - {8, 0x0083}, - {8, 0x0043}, - {9, 0x00e7}, - {7, 0x0105}, - {8, 0x005b}, - {8, 0x001b}, - {9, 0x0097}, - {7, 0x0115}, - {8, 0x007b}, - {8, 0x003b}, - {9, 0x00d7}, - {7, 0x010d}, - {8, 0x006b}, - {8, 0x002b}, - {9, 0x00b7}, - {8, 0x000b}, - {8, 0x008b}, - {8, 0x004b}, - {9, 0x00f7}, - {7, 0x0103}, - {8, 0x0057}, - {8, 0x0017}, - {8, 0x011f}, - {7, 0x0113}, - {8, 0x0077}, - {8, 0x0037}, - {9, 0x00cf}, - {7, 0x010b}, - {8, 0x0067}, - {8, 0x0027}, - {9, 0x00af}, - {8, 0x0007}, - {8, 0x0087}, - {8, 0x0047}, - {9, 0x00ef}, - {7, 0x0107}, - {8, 0x005f}, - {8, 0x001f}, - {9, 0x009f}, - {7, 0x0117}, - {8, 0x007f}, - {8, 0x003f}, - {9, 0x00df}, - {7, 0x010f}, - {8, 0x006f}, - {8, 0x002f}, - {9, 0x00bf}, - {8, 0x000f}, - {8, 0x008f}, - {8, 0x004f}, - {9, 0x00ff} -}; - -FlateHuffmanTab FlateStream::fixedLitCodeTab = { - flateFixedLitCodeTabCodes, 9 -}; - -static FlateCode flateFixedDistCodeTabCodes[32] = { - {5, 0x0000}, - {5, 0x0010}, - {5, 0x0008}, - {5, 0x0018}, - {5, 0x0004}, - {5, 0x0014}, - {5, 0x000c}, - {5, 0x001c}, - {5, 0x0002}, - {5, 0x0012}, - {5, 0x000a}, - {5, 0x001a}, - {5, 0x0006}, - {5, 0x0016}, - {5, 0x000e}, - {0, 0x0000}, - {5, 0x0001}, - {5, 0x0011}, - {5, 0x0009}, - {5, 0x0019}, - {5, 0x0005}, - {5, 0x0015}, - {5, 0x000d}, - {5, 0x001d}, - {5, 0x0003}, - {5, 0x0013}, - {5, 0x000b}, - {5, 0x001b}, - {5, 0x0007}, - {5, 0x0017}, - {5, 0x000f}, - {0, 0x0000} -}; - -FlateHuffmanTab FlateStream::fixedDistCodeTab = { - flateFixedDistCodeTabCodes, 5 -}; - -FlateStream::FlateStream(Stream *strA, int predictor, int columns, - int colors, int bits): - FilterStream(strA) { - if (predictor != 1) { - pred = new StreamPredictor(this, predictor, columns, colors, bits); - if (!pred->isOk()) { - delete pred; - pred = NULL; - } - } else { - pred = NULL; - } - litCodeTab.codes = NULL; - distCodeTab.codes = NULL; -} - -FlateStream::~FlateStream() { - if (litCodeTab.codes != fixedLitCodeTab.codes) { - gfree(litCodeTab.codes); - } - if (distCodeTab.codes != fixedDistCodeTab.codes) { - gfree(distCodeTab.codes); - } - if (pred) { - delete pred; - } - delete str; -} - -void FlateStream::reset() { - int cmf, flg; - - index = 0; - remain = 0; - codeBuf = 0; - codeSize = 0; - compressedBlock = gFalse; - endOfBlock = gTrue; - eof = gTrue; - - 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; - } - - 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(int psLevel, char *indent) { - GString *s; - - if (psLevel < 3 || pred) { - return NULL; - } - if (!(s = str->getPSFilter(psLevel, indent))) { - return NULL; - } - s->append(indent)->append("<< >> /FlateDecode filter\n"); - return s; -} - -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; - - // free the code tables from the previous block - if (litCodeTab.codes != fixedLitCodeTab.codes) { - gfree(litCodeTab.codes); - } - litCodeTab.codes = NULL; - if (distCodeTab.codes != fixedDistCodeTab.codes) { - gfree(distCodeTab.codes); - } - distCodeTab.codes = NULL; - - // 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() { - litCodeTab.codes = fixedLitCodeTab.codes; - litCodeTab.maxLen = fixedLitCodeTab.maxLen; - distCodeTab.codes = fixedDistCodeTab.codes; - distCodeTab.maxLen = fixedDistCodeTab.maxLen; -} - -GBool FlateStream::readDynamicCodes() { - int numCodeLenCodes; - int numLitCodes; - int numDistCodes; - int codeLenCodeLengths[flateMaxCodeLenCodes]; - FlateHuffmanTab codeLenCodeTab; - int len, repeat, code; - int i; - - codeLenCodeTab.codes = NULL; - - // 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; - } - - // build the code length code table - for (i = 0; i < flateMaxCodeLenCodes; ++i) { - codeLenCodeLengths[i] = 0; - } - for (i = 0; i < numCodeLenCodes; ++i) { - if ((codeLenCodeLengths[codeLenCodeMap[i]] = getCodeWord(3)) == -1) { - goto err; - } - } - compHuffmanCodes(codeLenCodeLengths, flateMaxCodeLenCodes, &codeLenCodeTab); - - // build the 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; - } - repeat += 3; - if (i + repeat > numLitCodes + numDistCodes) { - goto err; - } - for (; repeat > 0; --repeat) { - codeLengths[i++] = len; - } - } else if (code == 17) { - if ((repeat = getCodeWord(3)) == EOF) { - goto err; - } - repeat += 3; - if (i + repeat > numLitCodes + numDistCodes) { - goto err; - } - len = 0; - for (; repeat > 0; --repeat) { - codeLengths[i++] = 0; - } - } else if (code == 18) { - if ((repeat = getCodeWord(7)) == EOF) { - goto err; - } - repeat += 11; - if (i + repeat > numLitCodes + numDistCodes) { - goto err; - } - len = 0; - for (; repeat > 0; --repeat) { - codeLengths[i++] = 0; - } - } else { - codeLengths[i++] = len = code; - } - } - compHuffmanCodes(codeLengths, numLitCodes, &litCodeTab); - compHuffmanCodes(codeLengths + numLitCodes, numDistCodes, &distCodeTab); - - gfree(codeLenCodeTab.codes); - return gTrue; - -err: - error(getPos(), "Bad dynamic code table in flate stream"); - gfree(codeLenCodeTab.codes); - return gFalse; -} - -// Convert an array <lengths> of <n> lengths, in value order, into a -// Huffman code lookup table. -void FlateStream::compHuffmanCodes(int *lengths, int n, FlateHuffmanTab *tab) { - int tabSize, len, code, code2, skip, val, i, t; - - // find max code length - tab->maxLen = 0; - for (val = 0; val < n; ++val) { - if (lengths[val] > tab->maxLen) { - tab->maxLen = lengths[val]; - } - } - - // allocate the table - tabSize = 1 << tab->maxLen; - tab->codes = (FlateCode *)gmallocn(tabSize, sizeof(FlateCode)); - - // clear the table - for (i = 0; i < tabSize; ++i) { - tab->codes[i].len = 0; - tab->codes[i].val = 0; - } - - // build the table - for (len = 1, code = 0, skip = 2; - len <= tab->maxLen; - ++len, code <<= 1, skip <<= 1) { - for (val = 0; val < n; ++val) { - if (lengths[val] == len) { - - // bit-reverse the code - code2 = 0; - t = code; - for (i = 0; i < len; ++i) { - code2 = (code2 << 1) | (t & 1); - t >>= 1; - } - - // fill in the table entries - for (i = code2; i < tabSize; i += skip) { - tab->codes[i].len = (Gushort)len; - tab->codes[i].val = (Gushort)val; - } - - ++code; - } - } - } -} - -int FlateStream::getHuffmanCodeWord(FlateHuffmanTab *tab) { - FlateCode *code; - int c; - - while (codeSize < tab->maxLen) { - if ((c = str->getChar()) == EOF) { - break; - } - codeBuf |= (c & 0xff) << codeSize; - codeSize += 8; - } - code = &tab->codes[codeBuf & ((1 << tab->maxLen) - 1)]; - if (codeSize == 0 || codeSize < code->len || code->len == 0) { - return EOF; - } - codeBuf >>= code->len; - codeSize -= code->len; - return (int)code->val; -} - -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 *strA): - FilterStream(strA) { -} - -EOFStream::~EOFStream() { - delete str; -} - -//------------------------------------------------------------------------ -// FixedLengthEncoder -//------------------------------------------------------------------------ - -FixedLengthEncoder::FixedLengthEncoder(Stream *strA, int lengthA): - FilterStream(strA) { - length = lengthA; - 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(); -} - -GBool FixedLengthEncoder::isBinary(GBool last) { - return str->isBinary(gTrue); -} - -//------------------------------------------------------------------------ -// ASCIIHexEncoder -//------------------------------------------------------------------------ - -ASCIIHexEncoder::ASCIIHexEncoder(Stream *strA): - FilterStream(strA) { - bufPtr = bufEnd = buf; - lineLen = 0; - eof = gFalse; -} - -ASCIIHexEncoder::~ASCIIHexEncoder() { - if (str->isEncoder()) { - delete str; - } -} - -void ASCIIHexEncoder::reset() { - str->reset(); - bufPtr = bufEnd = buf; - lineLen = 0; - eof = gFalse; -} - -GBool ASCIIHexEncoder::fillBuf() { - static char *hex = "0123456789abcdef"; - int c; - - if (eof) { - return gFalse; - } - bufPtr = bufEnd = buf; - if ((c = str->getChar()) == EOF) { - *bufEnd++ = '>'; - eof = gTrue; - } else { - if (lineLen >= 64) { - *bufEnd++ = '\n'; - lineLen = 0; - } - *bufEnd++ = hex[(c >> 4) & 0x0f]; - *bufEnd++ = hex[c & 0x0f]; - lineLen += 2; - } - return gTrue; -} - -//------------------------------------------------------------------------ -// ASCII85Encoder -//------------------------------------------------------------------------ - -ASCII85Encoder::ASCII85Encoder(Stream *strA): - FilterStream(strA) { - 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 *strA): - FilterStream(strA) { - 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; - 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 deleted file mode 100644 index c06d9433b..000000000 --- a/pdftops/Stream.h +++ /dev/null @@ -1,848 +0,0 @@ -//======================================================================== -// -// Stream.h -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef STREAM_H -#define STREAM_H - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include <stdio.h> -#include "gtypes.h" -#include "Object.h" - -class Decrypt; -class BaseStream; - -//------------------------------------------------------------------------ - -enum StreamKind { - strFile, - strASCIIHex, - strASCII85, - strLZW, - strRunLength, - strCCITTFax, - strDCT, - strFlate, - strJBIG2, - strJPX, - strWeird // internal-use stream types -}; - -enum StreamColorSpaceMode { - streamCSNone, - streamCSDeviceGray, - streamCSDeviceRGB, - streamCSDeviceCMYK -}; - -//------------------------------------------------------------------------ -// 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; - - // Close down the stream. - virtual void close(); - - // 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. If <dir> is negative, the - // position is from the end of the file; otherwise the position is - // from the start of the file. - virtual void setPos(Guint pos, int dir = 0) = 0; - - // Get PostScript command for the filter(s). - virtual GString *getPSFilter(int psLevel, char *indent); - - // Does this stream type potentially contain non-printable chars? - virtual GBool isBinary(GBool last = gTrue) = 0; - - // Get the BaseStream 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; } - - // Get image parameters which are defined by the stream contents. - virtual void getImageParams(int *bitsPerComponent, - StreamColorSpaceMode *csMode) {} - - // Add filters to this stream according to the parameters in <dict>. - // 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 *dictA); - virtual ~BaseStream(); - virtual Stream *makeSubStream(Guint start, GBool limited, - Guint length, Object *dict) = 0; - virtual void setPos(Guint pos, int dir = 0) = 0; - virtual GBool isBinary(GBool last = gTrue) { return last; } - virtual BaseStream *getBaseStream() { return this; } - virtual Dict *getDict() { return dict.getDict(); } - - // Get/set position of first byte of stream within the file. - virtual Guint getStart() = 0; - virtual void moveStart(int delta) = 0; - - // Set decryption for this stream. - virtual void doDecryption(Guchar *fileKey, int keyLength, - int objNum, int objGen); - -protected: - - Decrypt *decrypt; - -private: - - Object dict; -}; - -//------------------------------------------------------------------------ -// FilterStream -// -// This is the base class for all streams that filter another stream. -//------------------------------------------------------------------------ - -class FilterStream: public Stream { -public: - - FilterStream(Stream *strA); - virtual ~FilterStream(); - virtual void close(); - virtual int getPos() { return str->getPos(); } - virtual void setPos(Guint pos, int dir = 0); - 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 *strA, int widthA, int nCompsA, int nBitsA); - - ~ImageStream(); - - // Reset the stream. - void reset(); - - // Gets the next pixel from the stream. <pix> should be able to hold - // at least nComps elements. Returns false at end of file. - GBool getPixel(Guchar *pix); - - // Returns a pointer to the next line of pixels. Returns NULL at - // end of file. - Guchar *getLine(); - - // 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 *strA, int predictorA, - int widthA, int nCompsA, int nBitsA); - - ~StreamPredictor(); - - GBool isOk() { return ok; } - - 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 - GBool ok; -}; - -//------------------------------------------------------------------------ -// FileStream -//------------------------------------------------------------------------ - -#define fileStreamBufSize 256 - -class FileStream: public BaseStream { -public: - - FileStream(FILE *fA, Guint startA, GBool limitedA, - Guint lengthA, Object *dictA); - virtual ~FileStream(); - virtual Stream *makeSubStream(Guint startA, GBool limitedA, - Guint lengthA, Object *dictA); - virtual StreamKind getKind() { return strFile; } - virtual void reset(); - virtual void close(); - 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(Guint pos, int dir = 0); - virtual Guint getStart() { return start; } - virtual void moveStart(int delta); - -private: - - GBool fillBuf(); - - FILE *f; - Guint start; - GBool limited; - Guint length; - char buf[fileStreamBufSize]; - char *bufPtr; - char *bufEnd; - Guint bufPos; - int savePos; - GBool saved; -}; - -//------------------------------------------------------------------------ -// MemStream -//------------------------------------------------------------------------ - -class MemStream: public BaseStream { -public: - - MemStream(char *bufA, Guint startA, Guint lengthA, Object *dictA); - virtual ~MemStream(); - virtual Stream *makeSubStream(Guint start, GBool limited, - Guint lengthA, Object *dictA); - virtual StreamKind getKind() { return strWeird; } - virtual void reset(); - virtual void close(); - virtual int getChar() - { return (bufPtr < bufEnd) ? (*bufPtr++ & 0xff) : EOF; } - virtual int lookChar() - { return (bufPtr < bufEnd) ? (*bufPtr & 0xff) : EOF; } - virtual int getPos() { return (int)(bufPtr - buf); } - virtual void setPos(Guint pos, int dir = 0); - virtual Guint getStart() { return start; } - virtual void moveStart(int delta); - virtual void doDecryption(Guchar *fileKey, int keyLength, - int objNum, int objGen); - -private: - - char *buf; - Guint start; - Guint length; - char *bufEnd; - char *bufPtr; - GBool needFree; -}; - -//------------------------------------------------------------------------ -// 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 *strA, Object *dictA, GBool limitedA, Guint lengthA); - virtual ~EmbedStream(); - virtual Stream *makeSubStream(Guint start, GBool limitedA, - Guint lengthA, Object *dictA); - virtual StreamKind getKind() { return str->getKind(); } - virtual void reset() {} - virtual int getChar(); - virtual int lookChar(); - virtual int getPos() { return str->getPos(); } - virtual void setPos(Guint pos, int dir = 0); - virtual Guint getStart(); - virtual void moveStart(int delta); - -private: - - Stream *str; - GBool limited; - Guint length; -}; - -//------------------------------------------------------------------------ -// ASCIIHexStream -//------------------------------------------------------------------------ - -class ASCIIHexStream: public FilterStream { -public: - - ASCIIHexStream(Stream *strA); - 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(int psLevel, char *indent); - virtual GBool isBinary(GBool last = gTrue); - -private: - - int buf; - GBool eof; -}; - -//------------------------------------------------------------------------ -// ASCII85Stream -//------------------------------------------------------------------------ - -class ASCII85Stream: public FilterStream { -public: - - ASCII85Stream(Stream *strA); - 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(int psLevel, 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 *strA, int predictor, int columns, int colors, - int bits, int earlyA); - virtual ~LZWStream(); - virtual StreamKind getKind() { return strLZW; } - virtual void reset(); - virtual int getChar(); - virtual int lookChar(); - virtual int getRawChar(); - virtual GString *getPSFilter(int psLevel, char *indent); - virtual GBool isBinary(GBool last = gTrue); - -private: - - StreamPredictor *pred; // predictor - int early; // early parameter - GBool eof; // true if at eof - int inputBuf; // input buffer - int inputBits; // number of bits in input buffer - struct { // decoding table - int length; - int head; - Guchar tail; - } table[4097]; - int nextCode; // next code to be used - int nextBits; // number of bits in next code word - int prevCode; // previous code used in stream - int newChar; // next char to be added to table - Guchar seqBuf[4097]; // buffer for current sequence - int seqLength; // length of current sequence - int seqIndex; // index into current sequence - GBool first; // first code after a table clear - - GBool processNextCode(); - void clearTable(); - int getCode(); -}; - -//------------------------------------------------------------------------ -// RunLengthStream -//------------------------------------------------------------------------ - -class RunLengthStream: public FilterStream { -public: - - RunLengthStream(Stream *strA); - 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(int psLevel, 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 *strA, int encodingA, GBool endOfLineA, - GBool byteAlignA, int columnsA, int rowsA, - GBool endOfBlockA, GBool blackA); - 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(int psLevel, 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 - int *codingLine; // coding line changing elements - int *refLine; // reference line changing elements - int a0i; // index into codingLine - GBool err; // error on current line - int outputBits; // remaining ouput bits - int buf; // character buffer - - void addPixels(int a1, int black); - void addPixelsNeg(int a1, int black); - short getTwoDimCode(); - short getWhiteCode(); - short getBlackCode(); - short lookBits(int n); - void eatBits(int n) { if ((inputBits -= n) < 0) inputBits = 0; } -}; - -//------------------------------------------------------------------------ -// DCTStream -//------------------------------------------------------------------------ - -// DCT component info -struct DCTCompInfo { - int id; // component ID - int hSample, vSample; // horiz/vert sampling resolutions - int quantTable; // quantization table number - int prevDC; // DC coefficient accumulator -}; - -struct DCTScanInfo { - GBool comp[4]; // comp[i] is set if component i is - // included in this scan - int numComps; // number of components in the scan - int dcHuffTable[4]; // DC Huffman table numbers - int acHuffTable[4]; // AC Huffman table numbers - int firstCoeff, lastCoeff; // first and last DCT coefficient - int ah, al; // successive approximation parameters -}; - -// 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 *strA); - virtual ~DCTStream(); - virtual StreamKind getKind() { return strDCT; } - virtual void reset(); - virtual int getChar(); - virtual int lookChar(); - virtual GString *getPSFilter(int psLevel, char *indent); - virtual GBool isBinary(GBool last = gTrue); - Stream *getRawStream() { return str; } - -private: - - GBool progressive; // set if in progressive mode - GBool interleaved; // set if in interleaved mode - int width, height; // image size - int mcuWidth, mcuHeight; // size of min coding unit, in data units - int bufWidth, bufHeight; // frameBuf size - DCTCompInfo compInfo[4]; // info for each component - DCTScanInfo scanInfo; // info for the current scan - int numComps; // number of components in image - int colorXform; // need YCbCr-to-RGB transform? - GBool gotJFIFMarker; // set if APP0 JFIF marker was present - GBool gotAdobeMarker; // set if APP14 Adobe marker was present - int restartInterval; // restart interval, in MCUs - Gushort 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 (non-progressive mode) - int *frameBuf[4]; // buffer for frame (progressive mode) - int comp, x, y, dy; // current position within image/MCU - int restartCtr; // MCUs left until restart - int restartMarker; // next restart marker - int eobRun; // number of EOBs left in the current run - int inputBuf; // input buffer for variable length codes - int inputBits; // number of valid bits in input buffer - - void restart(); - GBool readMCURow(); - void readScan(); - GBool readDataUnit(DCTHuffTable *dcHuffTable, - DCTHuffTable *acHuffTable, - int *prevDC, int data[64]); - GBool readProgressiveDataUnit(DCTHuffTable *dcHuffTable, - DCTHuffTable *acHuffTable, - int *prevDC, int data[64]); - void decodeImage(); - void transformDataUnit(Gushort *quantTable, - int dataIn[64], Guchar dataOut[64]); - int readHuffSym(DCTHuffTable *table); - int readAmp(int size); - int readBit(); - GBool readHeader(); - GBool readBaselineSOF(); - GBool readProgressiveSOF(); - GBool readScanInfo(); - GBool readQuantTables(); - GBool readHuffmanTables(); - GBool readRestartInterval(); - GBool readJFIFMarker(); - 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 { - Gushort len; // code length, in bits - Gushort val; // value represented by this code -}; - -struct FlateHuffmanTab { - FlateCode *codes; - int maxLen; -}; - -// 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 *strA, int predictor, int columns, - int colors, int bits); - virtual ~FlateStream(); - virtual StreamKind getKind() { return strFlate; } - virtual void reset(); - virtual int getChar(); - virtual int lookChar(); - virtual int getRawChar(); - virtual GString *getPSFilter(int psLevel, 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 - int // literal and distance code lengths - codeLengths[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]; - static FlateHuffmanTab // fixed literal code table - fixedLitCodeTab; - static FlateHuffmanTab // fixed distance code table - fixedDistCodeTab; - - void readSome(); - GBool startBlock(); - void loadFixedCodes(); - GBool readDynamicCodes(); - void compHuffmanCodes(int *lengths, int n, FlateHuffmanTab *tab); - int getHuffmanCodeWord(FlateHuffmanTab *tab); - int getCodeWord(int bits); -}; - -//------------------------------------------------------------------------ -// EOFStream -//------------------------------------------------------------------------ - -class EOFStream: public FilterStream { -public: - - EOFStream(Stream *strA); - virtual ~EOFStream(); - virtual StreamKind getKind() { return strWeird; } - virtual void reset() {} - virtual int getChar() { return EOF; } - virtual int lookChar() { return EOF; } - virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; } - virtual GBool isBinary(GBool last = gTrue) { return gFalse; } -}; - -//------------------------------------------------------------------------ -// FixedLengthEncoder -//------------------------------------------------------------------------ - -class FixedLengthEncoder: public FilterStream { -public: - - FixedLengthEncoder(Stream *strA, int lengthA); - ~FixedLengthEncoder(); - virtual StreamKind getKind() { return strWeird; } - virtual void reset(); - virtual int getChar(); - virtual int lookChar(); - virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; } - virtual GBool isBinary(GBool last = gTrue); - virtual GBool isEncoder() { return gTrue; } - -private: - - int length; - int count; -}; - -//------------------------------------------------------------------------ -// ASCIIHexEncoder -//------------------------------------------------------------------------ - -class ASCIIHexEncoder: public FilterStream { -public: - - ASCIIHexEncoder(Stream *strA); - virtual ~ASCIIHexEncoder(); - 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(int psLevel, char *indent) { return NULL; } - virtual GBool isBinary(GBool last = gTrue) { return gFalse; } - virtual GBool isEncoder() { return gTrue; } - -private: - - char buf[4]; - char *bufPtr; - char *bufEnd; - int lineLen; - GBool eof; - - GBool fillBuf(); -}; - -//------------------------------------------------------------------------ -// ASCII85Encoder -//------------------------------------------------------------------------ - -class ASCII85Encoder: public FilterStream { -public: - - ASCII85Encoder(Stream *strA); - 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(int psLevel, 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 *strA); - 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(int psLevel, char *indent) { return NULL; } - virtual GBool isBinary(GBool last = gTrue) { return gTrue; } - virtual GBool isEncoder() { return gTrue; } - -private: - - char buf[131]; - char *bufPtr; - char *bufEnd; - char *nextEnd; - GBool eof; - - GBool fillBuf(); -}; - -#endif diff --git a/pdftops/UTF8.h b/pdftops/UTF8.h deleted file mode 100644 index 8536dbf94..000000000 --- a/pdftops/UTF8.h +++ /dev/null @@ -1,56 +0,0 @@ -//======================================================================== -// -// UTF8.h -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -static int mapUTF8(Unicode u, char *buf, int bufSize) { - if (u <= 0x0000007f) { - if (bufSize < 1) { - return 0; - } - buf[0] = (char)u; - return 1; - } else if (u <= 0x000007ff) { - if (bufSize < 2) { - return 0; - } - buf[0] = (char)(0xc0 + (u >> 6)); - buf[1] = (char)(0x80 + (u & 0x3f)); - return 2; - } else if (u <= 0x0000ffff) { - if (bufSize < 3) { - return 0; - } - buf[0] = (char)(0xe0 + (u >> 12)); - buf[1] = (char)(0x80 + ((u >> 6) & 0x3f)); - buf[2] = (char)(0x80 + (u & 0x3f)); - return 3; - } else if (u <= 0x0010ffff) { - if (bufSize < 4) { - return 0; - } - buf[0] = (char)(0xf0 + (u >> 18)); - buf[1] = (char)(0x80 + ((u >> 12) & 0x3f)); - buf[2] = (char)(0x80 + ((u >> 6) & 0x3f)); - buf[3] = (char)(0x80 + (u & 0x3f)); - return 4; - } else { - return 0; - } -} - -static int mapUCS2(Unicode u, char *buf, int bufSize) { - if (u <= 0xffff) { - if (bufSize < 2) { - return 0; - } - buf[0] = (char)((u >> 8) & 0xff); - buf[1] = (char)(u & 0xff); - return 2; - } else { - return 0; - } -} diff --git a/pdftops/UnicodeMap.cxx b/pdftops/UnicodeMap.cxx deleted file mode 100644 index de4683c30..000000000 --- a/pdftops/UnicodeMap.cxx +++ /dev/null @@ -1,293 +0,0 @@ -//======================================================================== -// -// UnicodeMap.cc -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include <stdio.h> -#include <string.h> -#include "gmem.h" -#include "gfile.h" -#include "GString.h" -#include "GList.h" -#include "Error.h" -#include "GlobalParams.h" -#include "UnicodeMap.h" - -//------------------------------------------------------------------------ - -#define maxExtCode 16 - -struct UnicodeMapExt { - Unicode u; // Unicode char - char code[maxExtCode]; - Guint nBytes; -}; - -//------------------------------------------------------------------------ - -UnicodeMap *UnicodeMap::parse(GString *encodingNameA) { - FILE *f; - UnicodeMap *map; - UnicodeMapRange *range; - UnicodeMapExt *eMap; - int size, eMapsSize; - char buf[256]; - int line, nBytes, i, x; - char *tok1, *tok2, *tok3; - - if (!(f = globalParams->getUnicodeMapFile(encodingNameA))) { - error(-1, "Couldn't find unicodeMap file for the '%s' encoding", - encodingNameA->getCString()); - return NULL; - } - - map = new UnicodeMap(encodingNameA->copy()); - - size = 8; - map->ranges = (UnicodeMapRange *)gmallocn(size, sizeof(UnicodeMapRange)); - eMapsSize = 0; - - line = 1; - while (getLine(buf, sizeof(buf), f)) { - if ((tok1 = strtok(buf, " \t\r\n")) && - (tok2 = strtok(NULL, " \t\r\n"))) { - if (!(tok3 = strtok(NULL, " \t\r\n"))) { - tok3 = tok2; - tok2 = tok1; - } - nBytes = strlen(tok3) / 2; - if (nBytes <= 4) { - if (map->len == size) { - size *= 2; - map->ranges = (UnicodeMapRange *) - greallocn(map->ranges, size, sizeof(UnicodeMapRange)); - } - range = &map->ranges[map->len]; - sscanf(tok1, "%x", &range->start); - sscanf(tok2, "%x", &range->end); - sscanf(tok3, "%x", &range->code); - range->nBytes = nBytes; - ++map->len; - } else if (tok2 == tok1) { - if (map->eMapsLen == eMapsSize) { - eMapsSize += 16; - map->eMaps = (UnicodeMapExt *) - greallocn(map->eMaps, eMapsSize, sizeof(UnicodeMapExt)); - } - eMap = &map->eMaps[map->eMapsLen]; - sscanf(tok1, "%x", &eMap->u); - for (i = 0; i < nBytes; ++i) { - sscanf(tok3 + i*2, "%2x", &x); - eMap->code[i] = (char)x; - } - eMap->nBytes = nBytes; - ++map->eMapsLen; - } else { - error(-1, "Bad line (%d) in unicodeMap file for the '%s' encoding", - line, encodingNameA->getCString()); - } - } else { - error(-1, "Bad line (%d) in unicodeMap file for the '%s' encoding", - line, encodingNameA->getCString()); - } - ++line; - } - - fclose(f); - - return map; -} - -UnicodeMap::UnicodeMap(GString *encodingNameA) { - encodingName = encodingNameA; - unicodeOut = gFalse; - kind = unicodeMapUser; - ranges = NULL; - len = 0; - eMaps = NULL; - eMapsLen = 0; - refCnt = 1; -#if MULTITHREADED - gInitMutex(&mutex); -#endif -} - -UnicodeMap::UnicodeMap(char *encodingNameA, GBool unicodeOutA, - UnicodeMapRange *rangesA, int lenA) { - encodingName = new GString(encodingNameA); - unicodeOut = unicodeOutA; - kind = unicodeMapResident; - ranges = rangesA; - len = lenA; - eMaps = NULL; - eMapsLen = 0; - refCnt = 1; -#if MULTITHREADED - gInitMutex(&mutex); -#endif -} - -UnicodeMap::UnicodeMap(char *encodingNameA, GBool unicodeOutA, - UnicodeMapFunc funcA) { - encodingName = new GString(encodingNameA); - unicodeOut = unicodeOutA; - kind = unicodeMapFunc; - func = funcA; - eMaps = NULL; - eMapsLen = 0; - refCnt = 1; -#if MULTITHREADED - gInitMutex(&mutex); -#endif -} - -UnicodeMap::~UnicodeMap() { - delete encodingName; - if (kind == unicodeMapUser && ranges) { - gfree(ranges); - } - if (eMaps) { - gfree(eMaps); - } -#if MULTITHREADED - gDestroyMutex(&mutex); -#endif -} - -void UnicodeMap::incRefCnt() { -#if MULTITHREADED - gLockMutex(&mutex); -#endif - ++refCnt; -#if MULTITHREADED - gUnlockMutex(&mutex); -#endif -} - -void UnicodeMap::decRefCnt() { - GBool done; - -#if MULTITHREADED - gLockMutex(&mutex); -#endif - done = --refCnt == 0; -#if MULTITHREADED - gUnlockMutex(&mutex); -#endif - if (done) { - delete this; - } -} - -GBool UnicodeMap::match(GString *encodingNameA) { - return !encodingName->cmp(encodingNameA); -} - -int UnicodeMap::mapUnicode(Unicode u, char *buf, int bufSize) { - int a, b, m, n, i, j; - Guint code; - - if (kind == unicodeMapFunc) { - return (*func)(u, buf, bufSize); - } - - a = 0; - b = len; - if (u >= ranges[a].start) { - // invariant: ranges[a].start <= u < ranges[b].start - while (b - a > 1) { - m = (a + b) / 2; - if (u >= ranges[m].start) { - a = m; - } else if (u < ranges[m].start) { - b = m; - } - } - if (u <= ranges[a].end) { - n = ranges[a].nBytes; - if (n > bufSize) { - return 0; - } - code = ranges[a].code + (u - ranges[a].start); - for (i = n - 1; i >= 0; --i) { - buf[i] = (char)(code & 0xff); - code >>= 8; - } - return n; - } - } - - for (i = 0; i < eMapsLen; ++i) { - if (eMaps[i].u == u) { - n = eMaps[i].nBytes; - for (j = 0; j < n; ++j) { - buf[j] = eMaps[i].code[j]; - } - return n; - } - } - - return 0; -} - -//------------------------------------------------------------------------ - -UnicodeMapCache::UnicodeMapCache() { - int i; - - for (i = 0; i < unicodeMapCacheSize; ++i) { - cache[i] = NULL; - } -} - -UnicodeMapCache::~UnicodeMapCache() { - int i; - - for (i = 0; i < unicodeMapCacheSize; ++i) { - if (cache[i]) { - cache[i]->decRefCnt(); - } - } -} - -UnicodeMap *UnicodeMapCache::getUnicodeMap(GString *encodingName) { - UnicodeMap *map; - int i, j; - - if (cache[0] && cache[0]->match(encodingName)) { - cache[0]->incRefCnt(); - return cache[0]; - } - for (i = 1; i < unicodeMapCacheSize; ++i) { - if (cache[i] && cache[i]->match(encodingName)) { - map = cache[i]; - for (j = i; j >= 1; --j) { - cache[j] = cache[j - 1]; - } - cache[0] = map; - map->incRefCnt(); - return map; - } - } - if ((map = UnicodeMap::parse(encodingName))) { - if (cache[unicodeMapCacheSize - 1]) { - cache[unicodeMapCacheSize - 1]->decRefCnt(); - } - for (j = unicodeMapCacheSize - 1; j >= 1; --j) { - cache[j] = cache[j - 1]; - } - cache[0] = map; - map->incRefCnt(); - return map; - } - return NULL; -} diff --git a/pdftops/UnicodeMap.h b/pdftops/UnicodeMap.h deleted file mode 100644 index 07dd01ccf..000000000 --- a/pdftops/UnicodeMap.h +++ /dev/null @@ -1,123 +0,0 @@ -//======================================================================== -// -// UnicodeMap.h -// -// Mapping from Unicode to an encoding. -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef UNICODEMAP_H -#define UNICODEMAP_H - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "gtypes.h" -#include "CharTypes.h" - -#if MULTITHREADED -#include "GMutex.h" -#endif - -class GString; - -//------------------------------------------------------------------------ - -enum UnicodeMapKind { - unicodeMapUser, // read from a file - unicodeMapResident, // static list of ranges - unicodeMapFunc // function pointer -}; - -typedef int (*UnicodeMapFunc)(Unicode u, char *buf, int bufSize); - -struct UnicodeMapRange { - Unicode start, end; // range of Unicode chars - Guint code, nBytes; // first output code -}; - -struct UnicodeMapExt; - -//------------------------------------------------------------------------ - -class UnicodeMap { -public: - - // Create the UnicodeMap specified by <encodingName>. Sets the - // initial reference count to 1. Returns NULL on failure. - static UnicodeMap *parse(GString *encodingNameA); - - // Create a resident UnicodeMap. - UnicodeMap(char *encodingNameA, GBool unicodeOutA, - UnicodeMapRange *rangesA, int lenA); - - // Create a resident UnicodeMap that uses a function instead of a - // list of ranges. - UnicodeMap(char *encodingNameA, GBool unicodeOutA, - UnicodeMapFunc funcA); - - ~UnicodeMap(); - - void incRefCnt(); - void decRefCnt(); - - GString *getEncodingName() { return encodingName; } - - GBool isUnicode() { return unicodeOut; } - - // Return true if this UnicodeMap matches the specified - // <encodingNameA>. - GBool match(GString *encodingNameA); - - // Map Unicode to the target encoding. Fills in <buf> with the - // output and returns the number of bytes used. Output will be - // truncated at <bufSize> bytes. No string terminator is written. - // Returns 0 if no mapping is found. - int mapUnicode(Unicode u, char *buf, int bufSize); - -private: - - UnicodeMap(GString *encodingNameA); - - GString *encodingName; - UnicodeMapKind kind; - GBool unicodeOut; - union { - UnicodeMapRange *ranges; // (user, resident) - UnicodeMapFunc func; // (func) - }; - int len; // (user, resident) - UnicodeMapExt *eMaps; // (user) - int eMapsLen; // (user) - int refCnt; -#if MULTITHREADED - GMutex mutex; -#endif -}; - -//------------------------------------------------------------------------ - -#define unicodeMapCacheSize 4 - -class UnicodeMapCache { -public: - - UnicodeMapCache(); - ~UnicodeMapCache(); - - // Get the UnicodeMap for <encodingName>. Increments its reference - // count; there will be one reference for the cache plus one for the - // caller of this function. Returns NULL on failure. - UnicodeMap *getUnicodeMap(GString *encodingName); - -private: - - UnicodeMap *cache[unicodeMapCacheSize]; -}; - -#endif diff --git a/pdftops/UnicodeMapTables.h b/pdftops/UnicodeMapTables.h deleted file mode 100644 index 9c5103461..000000000 --- a/pdftops/UnicodeMapTables.h +++ /dev/null @@ -1,361 +0,0 @@ -//======================================================================== -// -// UnicodeMapTables.h -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -static UnicodeMapRange latin1UnicodeMapRanges[] = { - { 0x000a, 0x000a, 0x0a, 1 }, - { 0x000c, 0x000d, 0x0c, 1 }, - { 0x0020, 0x007e, 0x20, 1 }, - { 0x00a0, 0x00a0, 0x20, 1 }, - { 0x00a1, 0x00ac, 0xa1, 1 }, - { 0x00ae, 0x00ff, 0xae, 1 }, - { 0x010c, 0x010c, 0x43, 1 }, - { 0x010d, 0x010d, 0x63, 1 }, - { 0x0131, 0x0131, 0x69, 1 }, - { 0x0141, 0x0141, 0x4c, 1 }, - { 0x0142, 0x0142, 0x6c, 1 }, - { 0x0152, 0x0152, 0x4f45, 2 }, - { 0x0153, 0x0153, 0x6f65, 2 }, - { 0x0160, 0x0160, 0x53, 1 }, - { 0x0161, 0x0161, 0x73, 1 }, - { 0x0178, 0x0178, 0x59, 1 }, - { 0x017d, 0x017d, 0x5a, 1 }, - { 0x017e, 0x017e, 0x7a, 1 }, - { 0x02c6, 0x02c6, 0x5e, 1 }, - { 0x02da, 0x02da, 0xb0, 1 }, - { 0x02dc, 0x02dc, 0x7e, 1 }, - { 0x2013, 0x2013, 0xad, 1 }, - { 0x2014, 0x2014, 0x2d2d, 2 }, - { 0x2018, 0x2018, 0x60, 1 }, - { 0x2019, 0x2019, 0x27, 1 }, - { 0x201a, 0x201a, 0x2c, 1 }, - { 0x201c, 0x201c, 0x22, 1 }, - { 0x201d, 0x201d, 0x22, 1 }, - { 0x201e, 0x201e, 0x2c2c, 2 }, - { 0x2022, 0x2022, 0xb7, 1 }, - { 0x2026, 0x2026, 0x2e2e2e, 3 }, - { 0x2039, 0x2039, 0x3c, 1 }, - { 0x203a, 0x203a, 0x3e, 1 }, - { 0x2044, 0x2044, 0x2f, 1 }, - { 0x2122, 0x2122, 0x544d, 2 }, - { 0x2212, 0x2212, 0x2d, 1 }, - { 0xf6f9, 0xf6f9, 0x4c, 1 }, - { 0xf6fa, 0xf6fa, 0x4f45, 2 }, - { 0xf6fc, 0xf6fc, 0xb0, 1 }, - { 0xf6fd, 0xf6fd, 0x53, 1 }, - { 0xf6fe, 0xf6fe, 0x7e, 1 }, - { 0xf6ff, 0xf6ff, 0x5a, 1 }, - { 0xf721, 0xf721, 0x21, 1 }, - { 0xf724, 0xf724, 0x24, 1 }, - { 0xf726, 0xf726, 0x26, 1 }, - { 0xf730, 0xf739, 0x30, 1 }, - { 0xf73f, 0xf73f, 0x3f, 1 }, - { 0xf761, 0xf77a, 0x41, 1 }, - { 0xf7a1, 0xf7a2, 0xa1, 1 }, - { 0xf7bf, 0xf7bf, 0xbf, 1 }, - { 0xf7e0, 0xf7f6, 0xc0, 1 }, - { 0xf7f8, 0xf7fe, 0xd8, 1 }, - { 0xf7ff, 0xf7ff, 0x59, 1 }, - { 0xfb00, 0xfb00, 0x6666, 2 }, - { 0xfb01, 0xfb01, 0x6669, 2 }, - { 0xfb02, 0xfb02, 0x666c, 2 }, - { 0xfb03, 0xfb03, 0x666669, 3 }, - { 0xfb04, 0xfb04, 0x66666c, 3 } -}; -#define latin1UnicodeMapLen (sizeof(latin1UnicodeMapRanges) / sizeof(UnicodeMapRange)) - -static UnicodeMapRange ascii7UnicodeMapRanges[] = { - { 0x000a, 0x000a, 0x0a, 1 }, - { 0x000c, 0x000d, 0x0c, 1 }, - { 0x0020, 0x005f, 0x20, 1 }, - { 0x0061, 0x007e, 0x61, 1 }, - { 0x00a6, 0x00a6, 0x7c, 1 }, - { 0x00a9, 0x00a9, 0x286329, 3 }, - { 0x00ae, 0x00ae, 0x285229, 3 }, - { 0x00b7, 0x00b7, 0x2a, 1 }, - { 0x00bc, 0x00bc, 0x312f34, 3 }, - { 0x00bd, 0x00bd, 0x312f32, 3 }, - { 0x00be, 0x00be, 0x332f34, 3 }, - { 0x00c0, 0x00c0, 0x41, 1 }, - { 0x00c1, 0x00c1, 0x41, 1 }, - { 0x00c2, 0x00c2, 0x41, 1 }, - { 0x00c3, 0x00c3, 0x41, 1 }, - { 0x00c4, 0x00c4, 0x41, 1 }, - { 0x00c5, 0x00c5, 0x41, 1 }, - { 0x00c6, 0x00c6, 0x4145, 2 }, - { 0x00c7, 0x00c7, 0x43, 1 }, - { 0x00c8, 0x00c8, 0x45, 1 }, - { 0x00c9, 0x00c9, 0x45, 1 }, - { 0x00ca, 0x00ca, 0x45, 1 }, - { 0x00cb, 0x00cb, 0x45, 1 }, - { 0x00cc, 0x00cc, 0x49, 1 }, - { 0x00cd, 0x00cd, 0x49, 1 }, - { 0x00ce, 0x00ce, 0x49, 1 }, - { 0x00cf, 0x00cf, 0x49, 1 }, - { 0x00d1, 0x00d2, 0x4e, 1 }, - { 0x00d3, 0x00d3, 0x4f, 1 }, - { 0x00d4, 0x00d4, 0x4f, 1 }, - { 0x00d5, 0x00d5, 0x4f, 1 }, - { 0x00d6, 0x00d6, 0x4f, 1 }, - { 0x00d7, 0x00d7, 0x78, 1 }, - { 0x00d8, 0x00d8, 0x4f, 1 }, - { 0x00d9, 0x00d9, 0x55, 1 }, - { 0x00da, 0x00da, 0x55, 1 }, - { 0x00db, 0x00db, 0x55, 1 }, - { 0x00dc, 0x00dc, 0x55, 1 }, - { 0x00dd, 0x00dd, 0x59, 1 }, - { 0x00e0, 0x00e0, 0x61, 1 }, - { 0x00e1, 0x00e1, 0x61, 1 }, - { 0x00e2, 0x00e2, 0x61, 1 }, - { 0x00e3, 0x00e3, 0x61, 1 }, - { 0x00e4, 0x00e4, 0x61, 1 }, - { 0x00e5, 0x00e5, 0x61, 1 }, - { 0x00e6, 0x00e6, 0x6165, 2 }, - { 0x00e7, 0x00e7, 0x63, 1 }, - { 0x00e8, 0x00e8, 0x65, 1 }, - { 0x00e9, 0x00e9, 0x65, 1 }, - { 0x00ea, 0x00ea, 0x65, 1 }, - { 0x00eb, 0x00eb, 0x65, 1 }, - { 0x00ec, 0x00ec, 0x69, 1 }, - { 0x00ed, 0x00ed, 0x69, 1 }, - { 0x00ee, 0x00ee, 0x69, 1 }, - { 0x00ef, 0x00ef, 0x69, 1 }, - { 0x00f1, 0x00f2, 0x6e, 1 }, - { 0x00f3, 0x00f3, 0x6f, 1 }, - { 0x00f4, 0x00f4, 0x6f, 1 }, - { 0x00f5, 0x00f5, 0x6f, 1 }, - { 0x00f6, 0x00f6, 0x6f, 1 }, - { 0x00f7, 0x00f7, 0x2f, 1 }, - { 0x00f8, 0x00f8, 0x6f, 1 }, - { 0x00f9, 0x00f9, 0x75, 1 }, - { 0x00fa, 0x00fa, 0x75, 1 }, - { 0x00fb, 0x00fb, 0x75, 1 }, - { 0x00fc, 0x00fc, 0x75, 1 }, - { 0x00fd, 0x00fd, 0x79, 1 }, - { 0x00ff, 0x00ff, 0x79, 1 }, - { 0x0131, 0x0131, 0x69, 1 }, - { 0x0141, 0x0141, 0x4c, 1 }, - { 0x0152, 0x0152, 0x4f45, 2 }, - { 0x0153, 0x0153, 0x6f65, 2 }, - { 0x0160, 0x0160, 0x53, 1 }, - { 0x0178, 0x0178, 0x59, 1 }, - { 0x017d, 0x017d, 0x5a, 1 }, - { 0x2013, 0x2013, 0x2d, 1 }, - { 0x2014, 0x2014, 0x2d2d, 2 }, - { 0x2018, 0x2018, 0x60, 1 }, - { 0x2019, 0x2019, 0x27, 1 }, - { 0x201c, 0x201c, 0x22, 1 }, - { 0x201d, 0x201d, 0x22, 1 }, - { 0x2022, 0x2022, 0x2a, 1 }, - { 0x2026, 0x2026, 0x2e2e2e, 3 }, - { 0x2122, 0x2122, 0x544d, 2 }, - { 0x2212, 0x2212, 0x2d, 1 }, - { 0xf6f9, 0xf6f9, 0x4c, 1 }, - { 0xf6fa, 0xf6fa, 0x4f45, 2 }, - { 0xf6fd, 0xf6fd, 0x53, 1 }, - { 0xf6fe, 0xf6fe, 0x7e, 1 }, - { 0xf6ff, 0xf6ff, 0x5a, 1 }, - { 0xf721, 0xf721, 0x21, 1 }, - { 0xf724, 0xf724, 0x24, 1 }, - { 0xf726, 0xf726, 0x26, 1 }, - { 0xf730, 0xf739, 0x30, 1 }, - { 0xf73f, 0xf73f, 0x3f, 1 }, - { 0xf761, 0xf77a, 0x41, 1 }, - { 0xf7e0, 0xf7e0, 0x41, 1 }, - { 0xf7e1, 0xf7e1, 0x41, 1 }, - { 0xf7e2, 0xf7e2, 0x41, 1 }, - { 0xf7e3, 0xf7e3, 0x41, 1 }, - { 0xf7e4, 0xf7e4, 0x41, 1 }, - { 0xf7e5, 0xf7e5, 0x41, 1 }, - { 0xf7e6, 0xf7e6, 0x4145, 2 }, - { 0xf7e7, 0xf7e7, 0x43, 1 }, - { 0xf7e8, 0xf7e8, 0x45, 1 }, - { 0xf7e9, 0xf7e9, 0x45, 1 }, - { 0xf7ea, 0xf7ea, 0x45, 1 }, - { 0xf7eb, 0xf7eb, 0x45, 1 }, - { 0xf7ec, 0xf7ec, 0x49, 1 }, - { 0xf7ed, 0xf7ed, 0x49, 1 }, - { 0xf7ee, 0xf7ee, 0x49, 1 }, - { 0xf7ef, 0xf7ef, 0x49, 1 }, - { 0xf7f1, 0xf7f2, 0x4e, 1 }, - { 0xf7f3, 0xf7f3, 0x4f, 1 }, - { 0xf7f4, 0xf7f4, 0x4f, 1 }, - { 0xf7f5, 0xf7f5, 0x4f, 1 }, - { 0xf7f6, 0xf7f6, 0x4f, 1 }, - { 0xf7f8, 0xf7f8, 0x4f, 1 }, - { 0xf7f9, 0xf7f9, 0x55, 1 }, - { 0xf7fa, 0xf7fa, 0x55, 1 }, - { 0xf7fb, 0xf7fb, 0x55, 1 }, - { 0xf7fc, 0xf7fc, 0x55, 1 }, - { 0xf7fd, 0xf7fd, 0x59, 1 }, - { 0xf7ff, 0xf7ff, 0x59, 1 }, - { 0xfb00, 0xfb00, 0x6666, 2 }, - { 0xfb01, 0xfb01, 0x6669, 2 }, - { 0xfb02, 0xfb02, 0x666c, 2 }, - { 0xfb03, 0xfb03, 0x666669, 3 }, - { 0xfb04, 0xfb04, 0x66666c, 3 } -}; -#define ascii7UnicodeMapLen (sizeof(ascii7UnicodeMapRanges) / sizeof(UnicodeMapRange)) - -static UnicodeMapRange symbolUnicodeMapRanges[] = { - { 0x0020, 0x0021, 0x20, 1 }, - { 0x0023, 0x0023, 0x23, 1 }, - { 0x0025, 0x0026, 0x25, 1 }, - { 0x0028, 0x0029, 0x28, 1 }, - { 0x002b, 0x002c, 0x2b, 1 }, - { 0x002e, 0x003f, 0x2e, 1 }, - { 0x005b, 0x005b, 0x5b, 1 }, - { 0x005d, 0x005d, 0x5d, 1 }, - { 0x005f, 0x005f, 0x5f, 1 }, - { 0x007b, 0x007d, 0x7b, 1 }, - { 0x00ac, 0x00ac, 0xd8, 1 }, - { 0x00b0, 0x00b1, 0xb0, 1 }, - { 0x00b5, 0x00b5, 0x6d, 1 }, - { 0x00d7, 0x00d7, 0xb4, 1 }, - { 0x00f7, 0x00f7, 0xb8, 1 }, - { 0x0192, 0x0192, 0xa6, 1 }, - { 0x0391, 0x0392, 0x41, 1 }, - { 0x0393, 0x0393, 0x47, 1 }, - { 0x0395, 0x0395, 0x45, 1 }, - { 0x0396, 0x0396, 0x5a, 1 }, - { 0x0397, 0x0397, 0x48, 1 }, - { 0x0398, 0x0398, 0x51, 1 }, - { 0x0399, 0x0399, 0x49, 1 }, - { 0x039a, 0x039d, 0x4b, 1 }, - { 0x039e, 0x039e, 0x58, 1 }, - { 0x039f, 0x03a0, 0x4f, 1 }, - { 0x03a1, 0x03a1, 0x52, 1 }, - { 0x03a3, 0x03a5, 0x53, 1 }, - { 0x03a6, 0x03a6, 0x46, 1 }, - { 0x03a7, 0x03a7, 0x43, 1 }, - { 0x03a8, 0x03a8, 0x59, 1 }, - { 0x03b1, 0x03b2, 0x61, 1 }, - { 0x03b3, 0x03b3, 0x67, 1 }, - { 0x03b4, 0x03b5, 0x64, 1 }, - { 0x03b6, 0x03b6, 0x7a, 1 }, - { 0x03b7, 0x03b7, 0x68, 1 }, - { 0x03b8, 0x03b8, 0x71, 1 }, - { 0x03b9, 0x03b9, 0x69, 1 }, - { 0x03ba, 0x03bb, 0x6b, 1 }, - { 0x03bd, 0x03bd, 0x6e, 1 }, - { 0x03be, 0x03be, 0x78, 1 }, - { 0x03bf, 0x03c0, 0x6f, 1 }, - { 0x03c1, 0x03c1, 0x72, 1 }, - { 0x03c2, 0x03c2, 0x56, 1 }, - { 0x03c3, 0x03c5, 0x73, 1 }, - { 0x03c6, 0x03c6, 0x66, 1 }, - { 0x03c7, 0x03c7, 0x63, 1 }, - { 0x03c8, 0x03c8, 0x79, 1 }, - { 0x03c9, 0x03c9, 0x77, 1 }, - { 0x03d1, 0x03d1, 0x4a, 1 }, - { 0x03d2, 0x03d2, 0xa1, 1 }, - { 0x03d5, 0x03d5, 0x6a, 1 }, - { 0x03d6, 0x03d6, 0x76, 1 }, - { 0x2022, 0x2022, 0xb7, 1 }, - { 0x2026, 0x2026, 0xbc, 1 }, - { 0x2032, 0x2032, 0xa2, 1 }, - { 0x2033, 0x2033, 0xb2, 1 }, - { 0x2044, 0x2044, 0xa4, 1 }, - { 0x2111, 0x2111, 0xc1, 1 }, - { 0x2118, 0x2118, 0xc3, 1 }, - { 0x211c, 0x211c, 0xc2, 1 }, - { 0x2126, 0x2126, 0x57, 1 }, - { 0x2135, 0x2135, 0xc0, 1 }, - { 0x2190, 0x2193, 0xac, 1 }, - { 0x2194, 0x2194, 0xab, 1 }, - { 0x21b5, 0x21b5, 0xbf, 1 }, - { 0x21d0, 0x21d3, 0xdc, 1 }, - { 0x21d4, 0x21d4, 0xdb, 1 }, - { 0x2200, 0x2200, 0x22, 1 }, - { 0x2202, 0x2202, 0xb6, 1 }, - { 0x2203, 0x2203, 0x24, 1 }, - { 0x2205, 0x2205, 0xc6, 1 }, - { 0x2206, 0x2206, 0x44, 1 }, - { 0x2207, 0x2207, 0xd1, 1 }, - { 0x2208, 0x2209, 0xce, 1 }, - { 0x220b, 0x220b, 0x27, 1 }, - { 0x220f, 0x220f, 0xd5, 1 }, - { 0x2211, 0x2211, 0xe5, 1 }, - { 0x2212, 0x2212, 0x2d, 1 }, - { 0x2217, 0x2217, 0x2a, 1 }, - { 0x221a, 0x221a, 0xd6, 1 }, - { 0x221d, 0x221d, 0xb5, 1 }, - { 0x221e, 0x221e, 0xa5, 1 }, - { 0x2220, 0x2220, 0xd0, 1 }, - { 0x2227, 0x2228, 0xd9, 1 }, - { 0x2229, 0x222a, 0xc7, 1 }, - { 0x222b, 0x222b, 0xf2, 1 }, - { 0x2234, 0x2234, 0x5c, 1 }, - { 0x223c, 0x223c, 0x7e, 1 }, - { 0x2245, 0x2245, 0x40, 1 }, - { 0x2248, 0x2248, 0xbb, 1 }, - { 0x2260, 0x2261, 0xb9, 1 }, - { 0x2264, 0x2264, 0xa3, 1 }, - { 0x2265, 0x2265, 0xb3, 1 }, - { 0x2282, 0x2282, 0xcc, 1 }, - { 0x2283, 0x2283, 0xc9, 1 }, - { 0x2284, 0x2284, 0xcb, 1 }, - { 0x2286, 0x2286, 0xcd, 1 }, - { 0x2287, 0x2287, 0xca, 1 }, - { 0x2295, 0x2295, 0xc5, 1 }, - { 0x2297, 0x2297, 0xc4, 1 }, - { 0x22a5, 0x22a5, 0x5e, 1 }, - { 0x22c5, 0x22c5, 0xd7, 1 }, - { 0x2320, 0x2320, 0xf3, 1 }, - { 0x2321, 0x2321, 0xf5, 1 }, - { 0x2329, 0x2329, 0xe1, 1 }, - { 0x232a, 0x232a, 0xf1, 1 }, - { 0x25ca, 0x25ca, 0xe0, 1 }, - { 0x2660, 0x2660, 0xaa, 1 }, - { 0x2663, 0x2663, 0xa7, 1 }, - { 0x2665, 0x2665, 0xa9, 1 }, - { 0x2666, 0x2666, 0xa8, 1 }, - { 0xf6d9, 0xf6d9, 0xd3, 1 }, - { 0xf6da, 0xf6da, 0xd2, 1 }, - { 0xf6db, 0xf6db, 0xd4, 1 }, - { 0xf8e5, 0xf8e5, 0x60, 1 }, - { 0xf8e6, 0xf8e7, 0xbd, 1 }, - { 0xf8e8, 0xf8ea, 0xe2, 1 }, - { 0xf8eb, 0xf8f4, 0xe6, 1 }, - { 0xf8f5, 0xf8f5, 0xf4, 1 }, - { 0xf8f6, 0xf8fe, 0xf6, 1 } -}; -#define symbolUnicodeMapLen (sizeof(symbolUnicodeMapRanges) / sizeof(UnicodeMapRange)) - -static UnicodeMapRange zapfDingbatsUnicodeMapRanges[] = { - { 0x0020, 0x0020, 0x20, 1 }, - { 0x2192, 0x2192, 0xd5, 1 }, - { 0x2194, 0x2195, 0xd6, 1 }, - { 0x2460, 0x2469, 0xac, 1 }, - { 0x25a0, 0x25a0, 0x6e, 1 }, - { 0x25b2, 0x25b2, 0x73, 1 }, - { 0x25bc, 0x25bc, 0x74, 1 }, - { 0x25c6, 0x25c6, 0x75, 1 }, - { 0x25cf, 0x25cf, 0x6c, 1 }, - { 0x25d7, 0x25d7, 0x77, 1 }, - { 0x2605, 0x2605, 0x48, 1 }, - { 0x260e, 0x260e, 0x25, 1 }, - { 0x261b, 0x261b, 0x2a, 1 }, - { 0x261e, 0x261e, 0x2b, 1 }, - { 0x2660, 0x2660, 0xab, 1 }, - { 0x2663, 0x2663, 0xa8, 1 }, - { 0x2665, 0x2665, 0xaa, 1 }, - { 0x2666, 0x2666, 0xa9, 1 }, - { 0x2701, 0x2704, 0x21, 1 }, - { 0x2706, 0x2709, 0x26, 1 }, - { 0x270c, 0x2727, 0x2c, 1 }, - { 0x2729, 0x274b, 0x49, 1 }, - { 0x274d, 0x274d, 0x6d, 1 }, - { 0x274f, 0x2752, 0x6f, 1 }, - { 0x2756, 0x2756, 0x76, 1 }, - { 0x2758, 0x275e, 0x78, 1 }, - { 0x2761, 0x2767, 0xa1, 1 }, - { 0x2776, 0x2794, 0xb6, 1 }, - { 0x2798, 0x27af, 0xd8, 1 }, - { 0x27b1, 0x27be, 0xf1, 1 } -}; -#define zapfDingbatsUnicodeMapLen (sizeof(zapfDingbatsUnicodeMapRanges) / sizeof(UnicodeMapRange)) diff --git a/pdftops/UnicodeTypeTable.cxx b/pdftops/UnicodeTypeTable.cxx deleted file mode 100644 index b89604036..000000000 --- a/pdftops/UnicodeTypeTable.cxx +++ /dev/null @@ -1,949 +0,0 @@ -//======================================================================== -// -// UnicodeTypeTable.cc -// -// Copyright 2004 Glyph & Cog, LLC -// -//======================================================================== - -#include <stdlib.h> -#include "CharTypes.h" -#include "UnicodeTypeTable.h" - -struct UnicodeMapTableEntry { - char *vector; - char type; -}; - -struct UnicodeCaseTableVector { - Unicode codes[256]; -}; - -static UnicodeMapTableEntry typeTable[256] = { - { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLNNNNNNNNNNLNNNNLNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLL", 'X' }, - { NULL, 'L' }, - { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLNNNNNNNNNNNNNNLLNNNNNNNNNNNNNNLLLLLNNNNNNNNNLNNNNNNNNNNNNNNNNN", 'X' }, - { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLNNNNNNNNNNNLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLL", 'X' }, - { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, - { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNRNRNNRNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR", 'X' }, - { "RRRRNNNNNNNNNRNNNNNNNNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNRRRNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNNRNNNNNNNRRNNNNNNNRRNNNNNNNNNNRRRRRR", 'X' }, - { "RRRRRRRRRRRRRRNNRNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNNNNNNNNNNNNNNNNNNNNNNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNNNNNNRNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, - { NULL, 'N' }, - { "NNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLNNNNNNNNLLLLNLLLNNNNLLLLLLLLLLLLLNNLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLNNNNLLLLLLLLNLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLNNLLLLLLLNNNNN", 'X' }, - { "NNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLNNNNNNNNLLLLNLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLNNNNNNNNNNNNNNNN", 'X' }, - { "NNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLNLNNNLLLLLLLLLNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNLLLLL", 'X' }, - { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNLLLLNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, - { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNLLLLLLLNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, - { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLNNNNNNNNNNNNLLLLLLLNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLNNNNNNNNNLLLLLLLLLLNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, - { "LLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLNLNLNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNLNNNNNLNNLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, - { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNLNNNNNNLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, - { "LLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNLLLLLLLLNLLNNNNNNNNNNNLLLLLLLNLNLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNN", 'X' }, - { "NNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, - { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLNNNNNLLLLLLNLLLLLLNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLNNNLLLLLLLLLLLNNNLLLLLLLLLLLLNNNNLLLLLLLLLLLLLNNNLLLLLLLLLLLLLNNN", 'X' }, - { "NNNNNNNNNNNNNNLRNNNNNNNNNNNNNNNNNNNNNNNNNNLRNLRNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLNNNNNNNNNNNNNLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, - { "NNLNNNNLNNLLLLLLLLLLNLNNNLLLLLNNNNNNLNLNLNLLLLNLLLNLLLLLLLNNLLLLNNNNNLLLLLNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, - { NULL, 'N' }, - { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, - { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNN", 'X' }, - { NULL, 'N' }, - { NULL, 'N' }, - { NULL, 'N' }, - { NULL, 'L' }, - { NULL, 'N' }, - { NULL, 'N' }, - { NULL, 'N' }, - { NULL, 'N' }, - { NULL, 'N' }, - { NULL, 'N' }, - { NULL, 'N' }, - { "NNNNNLLLNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLNNNNNNNLLLLLNNLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLL", 'X' }, - { NULL, 'L' }, - { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNLLLLLLLLLLLLNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, - { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN", 'X' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { "LLLLLLLLLLLLLLLLLLLLLLLLRRRRRRNRRRRRRRRRRNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR", 'X' }, - { NULL, 'R' }, - { "RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNN", 'X' }, - { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNN", 'X' }, - { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLL", 'X' } -}; - -static UnicodeCaseTableVector caseTable00 = {{ - 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, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, - 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, - 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, - 0x0078, 0x0079, 0x007a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, - 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, - 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, - 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, - 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, - 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, - 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, - 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, - 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f, - 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, - 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, - 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x03bc, 0x00b6, 0x00b7, - 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf, - 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, - 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, - 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00d7, - 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00df, - 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, - 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, - 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, - 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff -}}; -static UnicodeCaseTableVector caseTable01 = {{ - 0x0101, 0x0101, 0x0103, 0x0103, 0x0105, 0x0105, 0x0107, 0x0107, - 0x0109, 0x0109, 0x010b, 0x010b, 0x010d, 0x010d, 0x010f, 0x010f, - 0x0111, 0x0111, 0x0113, 0x0113, 0x0115, 0x0115, 0x0117, 0x0117, - 0x0119, 0x0119, 0x011b, 0x011b, 0x011d, 0x011d, 0x011f, 0x011f, - 0x0121, 0x0121, 0x0123, 0x0123, 0x0125, 0x0125, 0x0127, 0x0127, - 0x0129, 0x0129, 0x012b, 0x012b, 0x012d, 0x012d, 0x012f, 0x012f, - 0x0130, 0x0131, 0x0133, 0x0133, 0x0135, 0x0135, 0x0137, 0x0137, - 0x0138, 0x013a, 0x013a, 0x013c, 0x013c, 0x013e, 0x013e, 0x0140, - 0x0140, 0x0142, 0x0142, 0x0144, 0x0144, 0x0146, 0x0146, 0x0148, - 0x0148, 0x0149, 0x014b, 0x014b, 0x014d, 0x014d, 0x014f, 0x014f, - 0x0151, 0x0151, 0x0153, 0x0153, 0x0155, 0x0155, 0x0157, 0x0157, - 0x0159, 0x0159, 0x015b, 0x015b, 0x015d, 0x015d, 0x015f, 0x015f, - 0x0161, 0x0161, 0x0163, 0x0163, 0x0165, 0x0165, 0x0167, 0x0167, - 0x0169, 0x0169, 0x016b, 0x016b, 0x016d, 0x016d, 0x016f, 0x016f, - 0x0171, 0x0171, 0x0173, 0x0173, 0x0175, 0x0175, 0x0177, 0x0177, - 0x00ff, 0x017a, 0x017a, 0x017c, 0x017c, 0x017e, 0x017e, 0x0073, - 0x0180, 0x0253, 0x0183, 0x0183, 0x0185, 0x0185, 0x0254, 0x0188, - 0x0188, 0x0256, 0x0257, 0x018c, 0x018c, 0x018d, 0x01dd, 0x0259, - 0x025b, 0x0192, 0x0192, 0x0260, 0x0263, 0x0195, 0x0269, 0x0268, - 0x0199, 0x0199, 0x019a, 0x019b, 0x026f, 0x0272, 0x019e, 0x0275, - 0x01a1, 0x01a1, 0x01a3, 0x01a3, 0x01a5, 0x01a5, 0x0280, 0x01a8, - 0x01a8, 0x0283, 0x01aa, 0x01ab, 0x01ad, 0x01ad, 0x0288, 0x01b0, - 0x01b0, 0x028a, 0x028b, 0x01b4, 0x01b4, 0x01b6, 0x01b6, 0x0292, - 0x01b9, 0x01b9, 0x01ba, 0x01bb, 0x01bd, 0x01bd, 0x01be, 0x01bf, - 0x01c0, 0x01c1, 0x01c2, 0x01c3, 0x01c6, 0x01c6, 0x01c6, 0x01c9, - 0x01c9, 0x01c9, 0x01cc, 0x01cc, 0x01cc, 0x01ce, 0x01ce, 0x01d0, - 0x01d0, 0x01d2, 0x01d2, 0x01d4, 0x01d4, 0x01d6, 0x01d6, 0x01d8, - 0x01d8, 0x01da, 0x01da, 0x01dc, 0x01dc, 0x01dd, 0x01df, 0x01df, - 0x01e1, 0x01e1, 0x01e3, 0x01e3, 0x01e5, 0x01e5, 0x01e7, 0x01e7, - 0x01e9, 0x01e9, 0x01eb, 0x01eb, 0x01ed, 0x01ed, 0x01ef, 0x01ef, - 0x01f0, 0x01f3, 0x01f3, 0x01f3, 0x01f5, 0x01f5, 0x0195, 0x01bf, - 0x01f9, 0x01f9, 0x01fb, 0x01fb, 0x01fd, 0x01fd, 0x01ff, 0x01ff -}}; -static UnicodeCaseTableVector caseTable02 = {{ - 0x0201, 0x0201, 0x0203, 0x0203, 0x0205, 0x0205, 0x0207, 0x0207, - 0x0209, 0x0209, 0x020b, 0x020b, 0x020d, 0x020d, 0x020f, 0x020f, - 0x0211, 0x0211, 0x0213, 0x0213, 0x0215, 0x0215, 0x0217, 0x0217, - 0x0219, 0x0219, 0x021b, 0x021b, 0x021d, 0x021d, 0x021f, 0x021f, - 0x019e, 0x0221, 0x0223, 0x0223, 0x0225, 0x0225, 0x0227, 0x0227, - 0x0229, 0x0229, 0x022b, 0x022b, 0x022d, 0x022d, 0x022f, 0x022f, - 0x0231, 0x0231, 0x0233, 0x0233, 0x0234, 0x0235, 0x0236, 0x0237, - 0x0238, 0x0239, 0x023a, 0x023b, 0x023c, 0x023d, 0x023e, 0x023f, - 0x0240, 0x0241, 0x0242, 0x0243, 0x0244, 0x0245, 0x0246, 0x0247, - 0x0248, 0x0249, 0x024a, 0x024b, 0x024c, 0x024d, 0x024e, 0x024f, - 0x0250, 0x0251, 0x0252, 0x0253, 0x0254, 0x0255, 0x0256, 0x0257, - 0x0258, 0x0259, 0x025a, 0x025b, 0x025c, 0x025d, 0x025e, 0x025f, - 0x0260, 0x0261, 0x0262, 0x0263, 0x0264, 0x0265, 0x0266, 0x0267, - 0x0268, 0x0269, 0x026a, 0x026b, 0x026c, 0x026d, 0x026e, 0x026f, - 0x0270, 0x0271, 0x0272, 0x0273, 0x0274, 0x0275, 0x0276, 0x0277, - 0x0278, 0x0279, 0x027a, 0x027b, 0x027c, 0x027d, 0x027e, 0x027f, - 0x0280, 0x0281, 0x0282, 0x0283, 0x0284, 0x0285, 0x0286, 0x0287, - 0x0288, 0x0289, 0x028a, 0x028b, 0x028c, 0x028d, 0x028e, 0x028f, - 0x0290, 0x0291, 0x0292, 0x0293, 0x0294, 0x0295, 0x0296, 0x0297, - 0x0298, 0x0299, 0x029a, 0x029b, 0x029c, 0x029d, 0x029e, 0x029f, - 0x02a0, 0x02a1, 0x02a2, 0x02a3, 0x02a4, 0x02a5, 0x02a6, 0x02a7, - 0x02a8, 0x02a9, 0x02aa, 0x02ab, 0x02ac, 0x02ad, 0x02ae, 0x02af, - 0x02b0, 0x02b1, 0x02b2, 0x02b3, 0x02b4, 0x02b5, 0x02b6, 0x02b7, - 0x02b8, 0x02b9, 0x02ba, 0x02bb, 0x02bc, 0x02bd, 0x02be, 0x02bf, - 0x02c0, 0x02c1, 0x02c2, 0x02c3, 0x02c4, 0x02c5, 0x02c6, 0x02c7, - 0x02c8, 0x02c9, 0x02ca, 0x02cb, 0x02cc, 0x02cd, 0x02ce, 0x02cf, - 0x02d0, 0x02d1, 0x02d2, 0x02d3, 0x02d4, 0x02d5, 0x02d6, 0x02d7, - 0x02d8, 0x02d9, 0x02da, 0x02db, 0x02dc, 0x02dd, 0x02de, 0x02df, - 0x02e0, 0x02e1, 0x02e2, 0x02e3, 0x02e4, 0x02e5, 0x02e6, 0x02e7, - 0x02e8, 0x02e9, 0x02ea, 0x02eb, 0x02ec, 0x02ed, 0x02ee, 0x02ef, - 0x02f0, 0x02f1, 0x02f2, 0x02f3, 0x02f4, 0x02f5, 0x02f6, 0x02f7, - 0x02f8, 0x02f9, 0x02fa, 0x02fb, 0x02fc, 0x02fd, 0x02fe, 0x02ff -}}; -static UnicodeCaseTableVector caseTable03 = {{ - 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307, - 0x0308, 0x0309, 0x030a, 0x030b, 0x030c, 0x030d, 0x030e, 0x030f, - 0x0310, 0x0311, 0x0312, 0x0313, 0x0314, 0x0315, 0x0316, 0x0317, - 0x0318, 0x0319, 0x031a, 0x031b, 0x031c, 0x031d, 0x031e, 0x031f, - 0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0x0325, 0x0326, 0x0327, - 0x0328, 0x0329, 0x032a, 0x032b, 0x032c, 0x032d, 0x032e, 0x032f, - 0x0330, 0x0331, 0x0332, 0x0333, 0x0334, 0x0335, 0x0336, 0x0337, - 0x0338, 0x0339, 0x033a, 0x033b, 0x033c, 0x033d, 0x033e, 0x033f, - 0x0340, 0x0341, 0x0342, 0x0343, 0x0344, 0x03b9, 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, 0x03ac, 0x0387, - 0x03ad, 0x03ae, 0x03af, 0x038b, 0x03cc, 0x038d, 0x03cd, 0x03ce, - 0x0390, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, - 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, - 0x03c0, 0x03c1, 0x03a2, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, - 0x03c8, 0x03c9, 0x03ca, 0x03cb, 0x03ac, 0x03ad, 0x03ae, 0x03af, - 0x03b0, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, - 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, - 0x03c0, 0x03c1, 0x03c3, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, - 0x03c8, 0x03c9, 0x03ca, 0x03cb, 0x03cc, 0x03cd, 0x03ce, 0x03cf, - 0x03b2, 0x03b8, 0x03d2, 0x03d3, 0x03d4, 0x03c6, 0x03c0, 0x03d7, - 0x03d9, 0x03d9, 0x03db, 0x03db, 0x03dd, 0x03dd, 0x03df, 0x03df, - 0x03e1, 0x03e1, 0x03e3, 0x03e3, 0x03e5, 0x03e5, 0x03e7, 0x03e7, - 0x03e9, 0x03e9, 0x03eb, 0x03eb, 0x03ed, 0x03ed, 0x03ef, 0x03ef, - 0x03ba, 0x03c1, 0x03f2, 0x03f3, 0x03b8, 0x03b5, 0x03f6, 0x03f8, - 0x03f8, 0x03f2, 0x03fb, 0x03fb, 0x03fc, 0x03fd, 0x03fe, 0x03ff -}}; -static UnicodeCaseTableVector caseTable04 = {{ - 0x0450, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457, - 0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x045d, 0x045e, 0x045f, - 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, - 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f, - 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, - 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f, - 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, - 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f, - 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, - 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f, - 0x0450, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457, - 0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x045d, 0x045e, 0x045f, - 0x0461, 0x0461, 0x0463, 0x0463, 0x0465, 0x0465, 0x0467, 0x0467, - 0x0469, 0x0469, 0x046b, 0x046b, 0x046d, 0x046d, 0x046f, 0x046f, - 0x0471, 0x0471, 0x0473, 0x0473, 0x0475, 0x0475, 0x0477, 0x0477, - 0x0479, 0x0479, 0x047b, 0x047b, 0x047d, 0x047d, 0x047f, 0x047f, - 0x0481, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487, - 0x0488, 0x0489, 0x048b, 0x048b, 0x048d, 0x048d, 0x048f, 0x048f, - 0x0491, 0x0491, 0x0493, 0x0493, 0x0495, 0x0495, 0x0497, 0x0497, - 0x0499, 0x0499, 0x049b, 0x049b, 0x049d, 0x049d, 0x049f, 0x049f, - 0x04a1, 0x04a1, 0x04a3, 0x04a3, 0x04a5, 0x04a5, 0x04a7, 0x04a7, - 0x04a9, 0x04a9, 0x04ab, 0x04ab, 0x04ad, 0x04ad, 0x04af, 0x04af, - 0x04b1, 0x04b1, 0x04b3, 0x04b3, 0x04b5, 0x04b5, 0x04b7, 0x04b7, - 0x04b9, 0x04b9, 0x04bb, 0x04bb, 0x04bd, 0x04bd, 0x04bf, 0x04bf, - 0x04c0, 0x04c2, 0x04c2, 0x04c4, 0x04c4, 0x04c6, 0x04c6, 0x04c8, - 0x04c8, 0x04ca, 0x04ca, 0x04cc, 0x04cc, 0x04ce, 0x04ce, 0x04cf, - 0x04d1, 0x04d1, 0x04d3, 0x04d3, 0x04d5, 0x04d5, 0x04d7, 0x04d7, - 0x04d9, 0x04d9, 0x04db, 0x04db, 0x04dd, 0x04dd, 0x04df, 0x04df, - 0x04e1, 0x04e1, 0x04e3, 0x04e3, 0x04e5, 0x04e5, 0x04e7, 0x04e7, - 0x04e9, 0x04e9, 0x04eb, 0x04eb, 0x04ed, 0x04ed, 0x04ef, 0x04ef, - 0x04f1, 0x04f1, 0x04f3, 0x04f3, 0x04f5, 0x04f5, 0x04f6, 0x04f7, - 0x04f9, 0x04f9, 0x04fa, 0x04fb, 0x04fc, 0x04fd, 0x04fe, 0x04ff -}}; -static UnicodeCaseTableVector caseTable05 = {{ - 0x0501, 0x0501, 0x0503, 0x0503, 0x0505, 0x0505, 0x0507, 0x0507, - 0x0509, 0x0509, 0x050b, 0x050b, 0x050d, 0x050d, 0x050f, 0x050f, - 0x0510, 0x0511, 0x0512, 0x0513, 0x0514, 0x0515, 0x0516, 0x0517, - 0x0518, 0x0519, 0x051a, 0x051b, 0x051c, 0x051d, 0x051e, 0x051f, - 0x0520, 0x0521, 0x0522, 0x0523, 0x0524, 0x0525, 0x0526, 0x0527, - 0x0528, 0x0529, 0x052a, 0x052b, 0x052c, 0x052d, 0x052e, 0x052f, - 0x0530, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567, - 0x0568, 0x0569, 0x056a, 0x056b, 0x056c, 0x056d, 0x056e, 0x056f, - 0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577, - 0x0578, 0x0579, 0x057a, 0x057b, 0x057c, 0x057d, 0x057e, 0x057f, - 0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0557, - 0x0558, 0x0559, 0x055a, 0x055b, 0x055c, 0x055d, 0x055e, 0x055f, - 0x0560, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567, - 0x0568, 0x0569, 0x056a, 0x056b, 0x056c, 0x056d, 0x056e, 0x056f, - 0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577, - 0x0578, 0x0579, 0x057a, 0x057b, 0x057c, 0x057d, 0x057e, 0x057f, - 0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0587, - 0x0588, 0x0589, 0x058a, 0x058b, 0x058c, 0x058d, 0x058e, 0x058f, - 0x0590, 0x0591, 0x0592, 0x0593, 0x0594, 0x0595, 0x0596, 0x0597, - 0x0598, 0x0599, 0x059a, 0x059b, 0x059c, 0x059d, 0x059e, 0x059f, - 0x05a0, 0x05a1, 0x05a2, 0x05a3, 0x05a4, 0x05a5, 0x05a6, 0x05a7, - 0x05a8, 0x05a9, 0x05aa, 0x05ab, 0x05ac, 0x05ad, 0x05ae, 0x05af, - 0x05b0, 0x05b1, 0x05b2, 0x05b3, 0x05b4, 0x05b5, 0x05b6, 0x05b7, - 0x05b8, 0x05b9, 0x05ba, 0x05bb, 0x05bc, 0x05bd, 0x05be, 0x05bf, - 0x05c0, 0x05c1, 0x05c2, 0x05c3, 0x05c4, 0x05c5, 0x05c6, 0x05c7, - 0x05c8, 0x05c9, 0x05ca, 0x05cb, 0x05cc, 0x05cd, 0x05ce, 0x05cf, - 0x05d0, 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5, 0x05d6, 0x05d7, - 0x05d8, 0x05d9, 0x05da, 0x05db, 0x05dc, 0x05dd, 0x05de, 0x05df, - 0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5, 0x05e6, 0x05e7, - 0x05e8, 0x05e9, 0x05ea, 0x05eb, 0x05ec, 0x05ed, 0x05ee, 0x05ef, - 0x05f0, 0x05f1, 0x05f2, 0x05f3, 0x05f4, 0x05f5, 0x05f6, 0x05f7, - 0x05f8, 0x05f9, 0x05fa, 0x05fb, 0x05fc, 0x05fd, 0x05fe, 0x05ff -}}; -static UnicodeCaseTableVector caseTable1e = {{ - 0x1e01, 0x1e01, 0x1e03, 0x1e03, 0x1e05, 0x1e05, 0x1e07, 0x1e07, - 0x1e09, 0x1e09, 0x1e0b, 0x1e0b, 0x1e0d, 0x1e0d, 0x1e0f, 0x1e0f, - 0x1e11, 0x1e11, 0x1e13, 0x1e13, 0x1e15, 0x1e15, 0x1e17, 0x1e17, - 0x1e19, 0x1e19, 0x1e1b, 0x1e1b, 0x1e1d, 0x1e1d, 0x1e1f, 0x1e1f, - 0x1e21, 0x1e21, 0x1e23, 0x1e23, 0x1e25, 0x1e25, 0x1e27, 0x1e27, - 0x1e29, 0x1e29, 0x1e2b, 0x1e2b, 0x1e2d, 0x1e2d, 0x1e2f, 0x1e2f, - 0x1e31, 0x1e31, 0x1e33, 0x1e33, 0x1e35, 0x1e35, 0x1e37, 0x1e37, - 0x1e39, 0x1e39, 0x1e3b, 0x1e3b, 0x1e3d, 0x1e3d, 0x1e3f, 0x1e3f, - 0x1e41, 0x1e41, 0x1e43, 0x1e43, 0x1e45, 0x1e45, 0x1e47, 0x1e47, - 0x1e49, 0x1e49, 0x1e4b, 0x1e4b, 0x1e4d, 0x1e4d, 0x1e4f, 0x1e4f, - 0x1e51, 0x1e51, 0x1e53, 0x1e53, 0x1e55, 0x1e55, 0x1e57, 0x1e57, - 0x1e59, 0x1e59, 0x1e5b, 0x1e5b, 0x1e5d, 0x1e5d, 0x1e5f, 0x1e5f, - 0x1e61, 0x1e61, 0x1e63, 0x1e63, 0x1e65, 0x1e65, 0x1e67, 0x1e67, - 0x1e69, 0x1e69, 0x1e6b, 0x1e6b, 0x1e6d, 0x1e6d, 0x1e6f, 0x1e6f, - 0x1e71, 0x1e71, 0x1e73, 0x1e73, 0x1e75, 0x1e75, 0x1e77, 0x1e77, - 0x1e79, 0x1e79, 0x1e7b, 0x1e7b, 0x1e7d, 0x1e7d, 0x1e7f, 0x1e7f, - 0x1e81, 0x1e81, 0x1e83, 0x1e83, 0x1e85, 0x1e85, 0x1e87, 0x1e87, - 0x1e89, 0x1e89, 0x1e8b, 0x1e8b, 0x1e8d, 0x1e8d, 0x1e8f, 0x1e8f, - 0x1e91, 0x1e91, 0x1e93, 0x1e93, 0x1e95, 0x1e95, 0x1e96, 0x1e97, - 0x1e98, 0x1e99, 0x1e9a, 0x1e61, 0x1e9c, 0x1e9d, 0x1e9e, 0x1e9f, - 0x1ea1, 0x1ea1, 0x1ea3, 0x1ea3, 0x1ea5, 0x1ea5, 0x1ea7, 0x1ea7, - 0x1ea9, 0x1ea9, 0x1eab, 0x1eab, 0x1ead, 0x1ead, 0x1eaf, 0x1eaf, - 0x1eb1, 0x1eb1, 0x1eb3, 0x1eb3, 0x1eb5, 0x1eb5, 0x1eb7, 0x1eb7, - 0x1eb9, 0x1eb9, 0x1ebb, 0x1ebb, 0x1ebd, 0x1ebd, 0x1ebf, 0x1ebf, - 0x1ec1, 0x1ec1, 0x1ec3, 0x1ec3, 0x1ec5, 0x1ec5, 0x1ec7, 0x1ec7, - 0x1ec9, 0x1ec9, 0x1ecb, 0x1ecb, 0x1ecd, 0x1ecd, 0x1ecf, 0x1ecf, - 0x1ed1, 0x1ed1, 0x1ed3, 0x1ed3, 0x1ed5, 0x1ed5, 0x1ed7, 0x1ed7, - 0x1ed9, 0x1ed9, 0x1edb, 0x1edb, 0x1edd, 0x1edd, 0x1edf, 0x1edf, - 0x1ee1, 0x1ee1, 0x1ee3, 0x1ee3, 0x1ee5, 0x1ee5, 0x1ee7, 0x1ee7, - 0x1ee9, 0x1ee9, 0x1eeb, 0x1eeb, 0x1eed, 0x1eed, 0x1eef, 0x1eef, - 0x1ef1, 0x1ef1, 0x1ef3, 0x1ef3, 0x1ef5, 0x1ef5, 0x1ef7, 0x1ef7, - 0x1ef9, 0x1ef9, 0x1efa, 0x1efb, 0x1efc, 0x1efd, 0x1efe, 0x1eff -}}; -static UnicodeCaseTableVector caseTable1f = {{ - 0x1f00, 0x1f01, 0x1f02, 0x1f03, 0x1f04, 0x1f05, 0x1f06, 0x1f07, - 0x1f00, 0x1f01, 0x1f02, 0x1f03, 0x1f04, 0x1f05, 0x1f06, 0x1f07, - 0x1f10, 0x1f11, 0x1f12, 0x1f13, 0x1f14, 0x1f15, 0x1f16, 0x1f17, - 0x1f10, 0x1f11, 0x1f12, 0x1f13, 0x1f14, 0x1f15, 0x1f1e, 0x1f1f, - 0x1f20, 0x1f21, 0x1f22, 0x1f23, 0x1f24, 0x1f25, 0x1f26, 0x1f27, - 0x1f20, 0x1f21, 0x1f22, 0x1f23, 0x1f24, 0x1f25, 0x1f26, 0x1f27, - 0x1f30, 0x1f31, 0x1f32, 0x1f33, 0x1f34, 0x1f35, 0x1f36, 0x1f37, - 0x1f30, 0x1f31, 0x1f32, 0x1f33, 0x1f34, 0x1f35, 0x1f36, 0x1f37, - 0x1f40, 0x1f41, 0x1f42, 0x1f43, 0x1f44, 0x1f45, 0x1f46, 0x1f47, - 0x1f40, 0x1f41, 0x1f42, 0x1f43, 0x1f44, 0x1f45, 0x1f4e, 0x1f4f, - 0x1f50, 0x1f51, 0x1f52, 0x1f53, 0x1f54, 0x1f55, 0x1f56, 0x1f57, - 0x1f58, 0x1f51, 0x1f5a, 0x1f53, 0x1f5c, 0x1f55, 0x1f5e, 0x1f57, - 0x1f60, 0x1f61, 0x1f62, 0x1f63, 0x1f64, 0x1f65, 0x1f66, 0x1f67, - 0x1f60, 0x1f61, 0x1f62, 0x1f63, 0x1f64, 0x1f65, 0x1f66, 0x1f67, - 0x1f70, 0x1f71, 0x1f72, 0x1f73, 0x1f74, 0x1f75, 0x1f76, 0x1f77, - 0x1f78, 0x1f79, 0x1f7a, 0x1f7b, 0x1f7c, 0x1f7d, 0x1f7e, 0x1f7f, - 0x1f80, 0x1f81, 0x1f82, 0x1f83, 0x1f84, 0x1f85, 0x1f86, 0x1f87, - 0x1f80, 0x1f81, 0x1f82, 0x1f83, 0x1f84, 0x1f85, 0x1f86, 0x1f87, - 0x1f90, 0x1f91, 0x1f92, 0x1f93, 0x1f94, 0x1f95, 0x1f96, 0x1f97, - 0x1f90, 0x1f91, 0x1f92, 0x1f93, 0x1f94, 0x1f95, 0x1f96, 0x1f97, - 0x1fa0, 0x1fa1, 0x1fa2, 0x1fa3, 0x1fa4, 0x1fa5, 0x1fa6, 0x1fa7, - 0x1fa0, 0x1fa1, 0x1fa2, 0x1fa3, 0x1fa4, 0x1fa5, 0x1fa6, 0x1fa7, - 0x1fb0, 0x1fb1, 0x1fb2, 0x1fb3, 0x1fb4, 0x1fb5, 0x1fb6, 0x1fb7, - 0x1fb0, 0x1fb1, 0x1f70, 0x1f71, 0x1fb3, 0x1fbd, 0x03b9, 0x1fbf, - 0x1fc0, 0x1fc1, 0x1fc2, 0x1fc3, 0x1fc4, 0x1fc5, 0x1fc6, 0x1fc7, - 0x1f72, 0x1f73, 0x1f74, 0x1f75, 0x1fc3, 0x1fcd, 0x1fce, 0x1fcf, - 0x1fd0, 0x1fd1, 0x1fd2, 0x1fd3, 0x1fd4, 0x1fd5, 0x1fd6, 0x1fd7, - 0x1fd0, 0x1fd1, 0x1f76, 0x1f77, 0x1fdc, 0x1fdd, 0x1fde, 0x1fdf, - 0x1fe0, 0x1fe1, 0x1fe2, 0x1fe3, 0x1fe4, 0x1fe5, 0x1fe6, 0x1fe7, - 0x1fe0, 0x1fe1, 0x1f7a, 0x1f7b, 0x1fe5, 0x1fed, 0x1fee, 0x1fef, - 0x1ff0, 0x1ff1, 0x1ff2, 0x1ff3, 0x1ff4, 0x1ff5, 0x1ff6, 0x1ff7, - 0x1f78, 0x1f79, 0x1f7c, 0x1f7d, 0x1ff3, 0x1ffd, 0x1ffe, 0x1fff -}}; -static UnicodeCaseTableVector caseTable21 = {{ - 0x2100, 0x2101, 0x2102, 0x2103, 0x2104, 0x2105, 0x2106, 0x2107, - 0x2108, 0x2109, 0x210a, 0x210b, 0x210c, 0x210d, 0x210e, 0x210f, - 0x2110, 0x2111, 0x2112, 0x2113, 0x2114, 0x2115, 0x2116, 0x2117, - 0x2118, 0x2119, 0x211a, 0x211b, 0x211c, 0x211d, 0x211e, 0x211f, - 0x2120, 0x2121, 0x2122, 0x2123, 0x2124, 0x2125, 0x03c9, 0x2127, - 0x2128, 0x2129, 0x006b, 0x00e5, 0x212c, 0x212d, 0x212e, 0x212f, - 0x2130, 0x2131, 0x2132, 0x2133, 0x2134, 0x2135, 0x2136, 0x2137, - 0x2138, 0x2139, 0x213a, 0x213b, 0x213c, 0x213d, 0x213e, 0x213f, - 0x2140, 0x2141, 0x2142, 0x2143, 0x2144, 0x2145, 0x2146, 0x2147, - 0x2148, 0x2149, 0x214a, 0x214b, 0x214c, 0x214d, 0x214e, 0x214f, - 0x2150, 0x2151, 0x2152, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, - 0x2158, 0x2159, 0x215a, 0x215b, 0x215c, 0x215d, 0x215e, 0x215f, - 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, - 0x2178, 0x2179, 0x217a, 0x217b, 0x217c, 0x217d, 0x217e, 0x217f, - 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, - 0x2178, 0x2179, 0x217a, 0x217b, 0x217c, 0x217d, 0x217e, 0x217f, - 0x2180, 0x2181, 0x2182, 0x2183, 0x2184, 0x2185, 0x2186, 0x2187, - 0x2188, 0x2189, 0x218a, 0x218b, 0x218c, 0x218d, 0x218e, 0x218f, - 0x2190, 0x2191, 0x2192, 0x2193, 0x2194, 0x2195, 0x2196, 0x2197, - 0x2198, 0x2199, 0x219a, 0x219b, 0x219c, 0x219d, 0x219e, 0x219f, - 0x21a0, 0x21a1, 0x21a2, 0x21a3, 0x21a4, 0x21a5, 0x21a6, 0x21a7, - 0x21a8, 0x21a9, 0x21aa, 0x21ab, 0x21ac, 0x21ad, 0x21ae, 0x21af, - 0x21b0, 0x21b1, 0x21b2, 0x21b3, 0x21b4, 0x21b5, 0x21b6, 0x21b7, - 0x21b8, 0x21b9, 0x21ba, 0x21bb, 0x21bc, 0x21bd, 0x21be, 0x21bf, - 0x21c0, 0x21c1, 0x21c2, 0x21c3, 0x21c4, 0x21c5, 0x21c6, 0x21c7, - 0x21c8, 0x21c9, 0x21ca, 0x21cb, 0x21cc, 0x21cd, 0x21ce, 0x21cf, - 0x21d0, 0x21d1, 0x21d2, 0x21d3, 0x21d4, 0x21d5, 0x21d6, 0x21d7, - 0x21d8, 0x21d9, 0x21da, 0x21db, 0x21dc, 0x21dd, 0x21de, 0x21df, - 0x21e0, 0x21e1, 0x21e2, 0x21e3, 0x21e4, 0x21e5, 0x21e6, 0x21e7, - 0x21e8, 0x21e9, 0x21ea, 0x21eb, 0x21ec, 0x21ed, 0x21ee, 0x21ef, - 0x21f0, 0x21f1, 0x21f2, 0x21f3, 0x21f4, 0x21f5, 0x21f6, 0x21f7, - 0x21f8, 0x21f9, 0x21fa, 0x21fb, 0x21fc, 0x21fd, 0x21fe, 0x21ff -}}; -static UnicodeCaseTableVector caseTable24 = {{ - 0x2400, 0x2401, 0x2402, 0x2403, 0x2404, 0x2405, 0x2406, 0x2407, - 0x2408, 0x2409, 0x240a, 0x240b, 0x240c, 0x240d, 0x240e, 0x240f, - 0x2410, 0x2411, 0x2412, 0x2413, 0x2414, 0x2415, 0x2416, 0x2417, - 0x2418, 0x2419, 0x241a, 0x241b, 0x241c, 0x241d, 0x241e, 0x241f, - 0x2420, 0x2421, 0x2422, 0x2423, 0x2424, 0x2425, 0x2426, 0x2427, - 0x2428, 0x2429, 0x242a, 0x242b, 0x242c, 0x242d, 0x242e, 0x242f, - 0x2430, 0x2431, 0x2432, 0x2433, 0x2434, 0x2435, 0x2436, 0x2437, - 0x2438, 0x2439, 0x243a, 0x243b, 0x243c, 0x243d, 0x243e, 0x243f, - 0x2440, 0x2441, 0x2442, 0x2443, 0x2444, 0x2445, 0x2446, 0x2447, - 0x2448, 0x2449, 0x244a, 0x244b, 0x244c, 0x244d, 0x244e, 0x244f, - 0x2450, 0x2451, 0x2452, 0x2453, 0x2454, 0x2455, 0x2456, 0x2457, - 0x2458, 0x2459, 0x245a, 0x245b, 0x245c, 0x245d, 0x245e, 0x245f, - 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, 0x2467, - 0x2468, 0x2469, 0x246a, 0x246b, 0x246c, 0x246d, 0x246e, 0x246f, - 0x2470, 0x2471, 0x2472, 0x2473, 0x2474, 0x2475, 0x2476, 0x2477, - 0x2478, 0x2479, 0x247a, 0x247b, 0x247c, 0x247d, 0x247e, 0x247f, - 0x2480, 0x2481, 0x2482, 0x2483, 0x2484, 0x2485, 0x2486, 0x2487, - 0x2488, 0x2489, 0x248a, 0x248b, 0x248c, 0x248d, 0x248e, 0x248f, - 0x2490, 0x2491, 0x2492, 0x2493, 0x2494, 0x2495, 0x2496, 0x2497, - 0x2498, 0x2499, 0x249a, 0x249b, 0x249c, 0x249d, 0x249e, 0x249f, - 0x24a0, 0x24a1, 0x24a2, 0x24a3, 0x24a4, 0x24a5, 0x24a6, 0x24a7, - 0x24a8, 0x24a9, 0x24aa, 0x24ab, 0x24ac, 0x24ad, 0x24ae, 0x24af, - 0x24b0, 0x24b1, 0x24b2, 0x24b3, 0x24b4, 0x24b5, 0x24d0, 0x24d1, - 0x24d2, 0x24d3, 0x24d4, 0x24d5, 0x24d6, 0x24d7, 0x24d8, 0x24d9, - 0x24da, 0x24db, 0x24dc, 0x24dd, 0x24de, 0x24df, 0x24e0, 0x24e1, - 0x24e2, 0x24e3, 0x24e4, 0x24e5, 0x24e6, 0x24e7, 0x24e8, 0x24e9, - 0x24d0, 0x24d1, 0x24d2, 0x24d3, 0x24d4, 0x24d5, 0x24d6, 0x24d7, - 0x24d8, 0x24d9, 0x24da, 0x24db, 0x24dc, 0x24dd, 0x24de, 0x24df, - 0x24e0, 0x24e1, 0x24e2, 0x24e3, 0x24e4, 0x24e5, 0x24e6, 0x24e7, - 0x24e8, 0x24e9, 0x24ea, 0x24eb, 0x24ec, 0x24ed, 0x24ee, 0x24ef, - 0x24f0, 0x24f1, 0x24f2, 0x24f3, 0x24f4, 0x24f5, 0x24f6, 0x24f7, - 0x24f8, 0x24f9, 0x24fa, 0x24fb, 0x24fc, 0x24fd, 0x24fe, 0x24ff -}}; -static UnicodeCaseTableVector caseTableff = {{ - 0xff00, 0xff01, 0xff02, 0xff03, 0xff04, 0xff05, 0xff06, 0xff07, - 0xff08, 0xff09, 0xff0a, 0xff0b, 0xff0c, 0xff0d, 0xff0e, 0xff0f, - 0xff10, 0xff11, 0xff12, 0xff13, 0xff14, 0xff15, 0xff16, 0xff17, - 0xff18, 0xff19, 0xff1a, 0xff1b, 0xff1c, 0xff1d, 0xff1e, 0xff1f, - 0xff20, 0xff41, 0xff42, 0xff43, 0xff44, 0xff45, 0xff46, 0xff47, - 0xff48, 0xff49, 0xff4a, 0xff4b, 0xff4c, 0xff4d, 0xff4e, 0xff4f, - 0xff50, 0xff51, 0xff52, 0xff53, 0xff54, 0xff55, 0xff56, 0xff57, - 0xff58, 0xff59, 0xff5a, 0xff3b, 0xff3c, 0xff3d, 0xff3e, 0xff3f, - 0xff40, 0xff41, 0xff42, 0xff43, 0xff44, 0xff45, 0xff46, 0xff47, - 0xff48, 0xff49, 0xff4a, 0xff4b, 0xff4c, 0xff4d, 0xff4e, 0xff4f, - 0xff50, 0xff51, 0xff52, 0xff53, 0xff54, 0xff55, 0xff56, 0xff57, - 0xff58, 0xff59, 0xff5a, 0xff5b, 0xff5c, 0xff5d, 0xff5e, 0xff5f, - 0xff60, 0xff61, 0xff62, 0xff63, 0xff64, 0xff65, 0xff66, 0xff67, - 0xff68, 0xff69, 0xff6a, 0xff6b, 0xff6c, 0xff6d, 0xff6e, 0xff6f, - 0xff70, 0xff71, 0xff72, 0xff73, 0xff74, 0xff75, 0xff76, 0xff77, - 0xff78, 0xff79, 0xff7a, 0xff7b, 0xff7c, 0xff7d, 0xff7e, 0xff7f, - 0xff80, 0xff81, 0xff82, 0xff83, 0xff84, 0xff85, 0xff86, 0xff87, - 0xff88, 0xff89, 0xff8a, 0xff8b, 0xff8c, 0xff8d, 0xff8e, 0xff8f, - 0xff90, 0xff91, 0xff92, 0xff93, 0xff94, 0xff95, 0xff96, 0xff97, - 0xff98, 0xff99, 0xff9a, 0xff9b, 0xff9c, 0xff9d, 0xff9e, 0xff9f, - 0xffa0, 0xffa1, 0xffa2, 0xffa3, 0xffa4, 0xffa5, 0xffa6, 0xffa7, - 0xffa8, 0xffa9, 0xffaa, 0xffab, 0xffac, 0xffad, 0xffae, 0xffaf, - 0xffb0, 0xffb1, 0xffb2, 0xffb3, 0xffb4, 0xffb5, 0xffb6, 0xffb7, - 0xffb8, 0xffb9, 0xffba, 0xffbb, 0xffbc, 0xffbd, 0xffbe, 0xffbf, - 0xffc0, 0xffc1, 0xffc2, 0xffc3, 0xffc4, 0xffc5, 0xffc6, 0xffc7, - 0xffc8, 0xffc9, 0xffca, 0xffcb, 0xffcc, 0xffcd, 0xffce, 0xffcf, - 0xffd0, 0xffd1, 0xffd2, 0xffd3, 0xffd4, 0xffd5, 0xffd6, 0xffd7, - 0xffd8, 0xffd9, 0xffda, 0xffdb, 0xffdc, 0xffdd, 0xffde, 0xffdf, - 0xffe0, 0xffe1, 0xffe2, 0xffe3, 0xffe4, 0xffe5, 0xffe6, 0xffe7, - 0xffe8, 0xffe9, 0xffea, 0xffeb, 0xffec, 0xffed, 0xffee, 0xffef, - 0xfff0, 0xfff1, 0xfff2, 0xfff3, 0xfff4, 0xfff5, 0xfff6, 0xfff7, - 0xfff8, 0xfff9, 0xfffa, 0xfffb, 0xfffc, 0xfffd, 0xfffe, 0xffff -}}; -static UnicodeCaseTableVector *caseTable[256] = { - &caseTable00, - &caseTable01, - &caseTable02, - &caseTable03, - &caseTable04, - &caseTable05, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - &caseTable1e, - &caseTable1f, - NULL, - &caseTable21, - NULL, - NULL, - &caseTable24, - 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, - 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, - 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, - 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, - &caseTableff -}; - -static inline char getType(Unicode c) { - int i; - char type; - - if (c > 0xffff) { - type = 'X'; - } else { - i = (c >> 8) & 0xff; - if ((type = typeTable[i].type) == 'X') { - type = typeTable[i].vector[c & 0xff]; - } - } - return type; -} - -GBool unicodeTypeL(Unicode c) { - return getType(c) == 'L'; -} - -GBool unicodeTypeR(Unicode c) { - return getType(c) == 'R'; -} - -Unicode unicodeToUpper(Unicode c) { - int i; - - if (c > 0xffff) { - return c; - } - i = (c >> 8) & 0xff; - if (caseTable[i]) { - return caseTable[i]->codes[c & 0xff]; - } - return c; -} - diff --git a/pdftops/UnicodeTypeTable.h b/pdftops/UnicodeTypeTable.h deleted file mode 100644 index 7103dbddf..000000000 --- a/pdftops/UnicodeTypeTable.h +++ /dev/null @@ -1,20 +0,0 @@ -//======================================================================== -// -// UnicodeTypeTable.h -// -// Copyright 2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef UNICODETYPETABLE_H -#define UNICODETYPETABLE_H - -#include "gtypes.h" - -extern GBool unicodeTypeL(Unicode c); - -extern GBool unicodeTypeR(Unicode c); - -extern Unicode unicodeToUpper(Unicode c); - -#endif diff --git a/pdftops/XRef.cxx b/pdftops/XRef.cxx deleted file mode 100644 index c581803f7..000000000 --- a/pdftops/XRef.cxx +++ /dev/null @@ -1,888 +0,0 @@ -//======================================================================== -// -// XRef.cc -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include <stdlib.h> -#include <stddef.h> -#include <string.h> -#include <ctype.h> -#include "gmem.h" -#include "Object.h" -#include "Stream.h" -#include "Lexer.h" -#include "Parser.h" -#include "Dict.h" -#include "Error.h" -#include "ErrorCodes.h" -#include "XRef.h" - -//------------------------------------------------------------------------ - -#define xrefSearchSize 1024 // read this many bytes at end of file - // to look for 'startxref' - -//------------------------------------------------------------------------ -// Permission bits -//------------------------------------------------------------------------ - -#define permPrint (1<<2) -#define permChange (1<<3) -#define permCopy (1<<4) -#define permNotes (1<<5) -#define defPermFlags 0xfffc - -//------------------------------------------------------------------------ -// ObjectStream -//------------------------------------------------------------------------ - -class ObjectStream { -public: - - // Create an object stream, using object number <objStrNum>, - // generation 0. - ObjectStream(XRef *xref, int objStrNumA); - - ~ObjectStream(); - - // Return the object number of this object stream. - int getObjStrNum() { return objStrNum; } - - // Get the <objIdx>th object from this stream, which should be - // object number <objNum>, generation 0. - Object *getObject(int objIdx, int objNum, Object *obj); - -private: - - int objStrNum; // object number of the object stream - int nObjects; // number of objects in the stream - Object *objs; // the objects (length = nObjects) - int *objNums; // the object numbers (length = nObjects) -}; - -ObjectStream::ObjectStream(XRef *xref, int objStrNumA) { - Stream *str; - Parser *parser; - int *offsets; - Object objStr, obj1, obj2; - int first, i; - - objStrNum = objStrNumA; - nObjects = 0; - objs = NULL; - objNums = NULL; - - if (!xref->fetch(objStrNum, 0, &objStr)->isStream()) { - goto err1; - } - - if (!objStr.streamGetDict()->lookup("N", &obj1)->isInt()) { - obj1.free(); - goto err1; - } - nObjects = obj1.getInt(); - obj1.free(); - if (nObjects <= 0) { - goto err1; - } - - if (!objStr.streamGetDict()->lookup("First", &obj1)->isInt()) { - obj1.free(); - goto err1; - } - first = obj1.getInt(); - obj1.free(); - if (first < 0) { - goto err1; - } - - objs = new Object[nObjects]; - objNums = (int *)gmallocn(nObjects, sizeof(int)); - offsets = (int *)gmallocn(nObjects, sizeof(int)); - - // parse the header: object numbers and offsets - objStr.streamReset(); - obj1.initNull(); - str = new EmbedStream(objStr.getStream(), &obj1, gTrue, first); - parser = new Parser(xref, new Lexer(xref, str)); - for (i = 0; i < nObjects; ++i) { - parser->getObj(&obj1); - parser->getObj(&obj2); - if (!obj1.isInt() || !obj2.isInt()) { - obj1.free(); - obj2.free(); - delete parser; - gfree(offsets); - goto err1; - } - objNums[i] = obj1.getInt(); - offsets[i] = obj2.getInt(); - obj1.free(); - obj2.free(); - if (objNums[i] < 0 || offsets[i] < 0 || - (i > 0 && offsets[i] < offsets[i-1])) { - delete parser; - gfree(offsets); - goto err1; - } - } - while (str->getChar() != EOF) ; - delete parser; - - // skip to the first object - this shouldn't be necessary because - // the First key is supposed to be equal to offsets[0], but just in - // case... - for (i = first; i < offsets[0]; ++i) { - objStr.getStream()->getChar(); - } - - // parse the objects - for (i = 0; i < nObjects; ++i) { - obj1.initNull(); - if (i == nObjects - 1) { - str = new EmbedStream(objStr.getStream(), &obj1, gFalse, 0); - } else { - str = new EmbedStream(objStr.getStream(), &obj1, gTrue, - offsets[i+1] - offsets[i]); - } - parser = new Parser(xref, new Lexer(xref, str)); - parser->getObj(&objs[i]); - while (str->getChar() != EOF) ; - delete parser; - } - - gfree(offsets); - - err1: - objStr.free(); - return; -} - -ObjectStream::~ObjectStream() { - int i; - - if (objs) { - for (i = 0; i < nObjects; ++i) { - objs[i].free(); - } - delete[] objs; - } - gfree(objNums); -} - -Object *ObjectStream::getObject(int objIdx, int objNum, Object *obj) { - if (objIdx < 0 || objIdx >= nObjects || objNum != objNums[objIdx]) { - return obj->initNull(); - } - return objs[objIdx].copy(obj); -} - -//------------------------------------------------------------------------ -// XRef -//------------------------------------------------------------------------ - -XRef::XRef(BaseStream *strA) { - Guint pos; - Object obj; - - ok = gTrue; - errCode = errNone; - size = 0; - entries = NULL; - streamEnds = NULL; - streamEndsLen = 0; - objStr = NULL; - - encrypted = gFalse; - permFlags = defPermFlags; - ownerPasswordOk = gFalse; - - // read the trailer - str = strA; - start = str->getStart(); - pos = getStartXref(); - - // if there was a problem with the 'startxref' position, try to - // reconstruct the xref table - if (pos == 0) { - if (!(ok = constructXRef())) { - errCode = errDamaged; - return; - } - - // read the xref table - } else { - while (readXRef(&pos)) ; - - // if there was a problem with the xref table, - // try to reconstruct it - if (!ok) { - if (!(ok = constructXRef())) { - errCode = errDamaged; - return; - } - } - } - - // get the root dictionary (catalog) object - trailerDict.dictLookupNF("Root", &obj); - if (obj.isRef()) { - rootNum = obj.getRefNum(); - rootGen = obj.getRefGen(); - obj.free(); - } else { - obj.free(); - if (!(ok = constructXRef())) { - errCode = errDamaged; - return; - } - } - - // now set the trailer dictionary's xref pointer so we can fetch - // indirect objects from it - trailerDict.getDict()->setXRef(this); -} - -XRef::~XRef() { - gfree(entries); - trailerDict.free(); - if (streamEnds) { - gfree(streamEnds); - } - if (objStr) { - delete objStr; - } -} - -// Read the 'startxref' position. -Guint XRef::getStartXref() { - char buf[xrefSearchSize+1]; - char *p; - int c, n, i; - - // read last xrefSearchSize bytes - str->setPos(xrefSearchSize, -1); - 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) ; - lastXRefPos = strToUnsigned(p); - - return lastXRefPos; -} - -// Read one xref table section. Also reads the associated trailer -// dictionary, and returns the prev pointer (if any). -GBool XRef::readXRef(Guint *pos) { - Parser *parser; - Object obj; - GBool more; - - // start up a parser, parse one token - obj.initNull(); - parser = new Parser(NULL, - new Lexer(NULL, - str->makeSubStream(start + *pos, gFalse, 0, &obj))); - parser->getObj(&obj); - - // parse an old-style xref table - if (obj.isCmd("xref")) { - obj.free(); - more = readXRefTable(parser, pos); - - // parse an xref stream - } else if (obj.isInt()) { - obj.free(); - if (!parser->getObj(&obj)->isInt()) { - goto err1; - } - obj.free(); - if (!parser->getObj(&obj)->isCmd("obj")) { - goto err1; - } - obj.free(); - if (!parser->getObj(&obj)->isStream()) { - goto err1; - } - more = readXRefStream(obj.getStream(), pos); - obj.free(); - - } else { - goto err1; - } - - delete parser; - return more; - - err1: - obj.free(); - delete parser; - ok = gFalse; - return gFalse; -} - -GBool XRef::readXRefTable(Parser *parser, Guint *pos) { - XRefEntry entry; - GBool more; - Object obj, obj2; - Guint pos2; - int first, n, newSize, i; - - while (1) { - parser->getObj(&obj); - if (obj.isCmd("trailer")) { - obj.free(); - break; - } - if (!obj.isInt()) { - goto err1; - } - first = obj.getInt(); - obj.free(); - if (!parser->getObj(&obj)->isInt()) { - goto err1; - } - n = obj.getInt(); - obj.free(); - if (first < 0 || n < 0 || first + n < 0) { - goto err1; - } - if (first + n > size) { - for (newSize = size ? 2 * size : 1024; - first + n > newSize && newSize > 0; - newSize <<= 1) ; - if (newSize < 0) { - goto err1; - } - entries = (XRefEntry *)greallocn(entries, newSize, sizeof(XRefEntry)); - for (i = size; i < newSize; ++i) { - entries[i].offset = 0xffffffff; - entries[i].type = xrefEntryFree; - } - size = newSize; - } - for (i = first; i < first + n; ++i) { - if (!parser->getObj(&obj)->isInt()) { - goto err1; - } - entry.offset = (Guint)obj.getInt(); - obj.free(); - if (!parser->getObj(&obj)->isInt()) { - goto err1; - } - entry.gen = obj.getInt(); - obj.free(); - parser->getObj(&obj); - if (obj.isCmd("n")) { - entry.type = xrefEntryUncompressed; - } else if (obj.isCmd("f")) { - entry.type = xrefEntryFree; - } else { - goto err1; - } - obj.free(); - if (entries[i].offset == 0xffffffff) { - entries[i] = entry; - // 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].type == xrefEntryFree) { - i = first = 0; - entries[0] = entries[1]; - entries[1].offset = 0xffffffff; - } - } - } - } - - // read the trailer dictionary - if (!parser->getObj(&obj)->isDict()) { - goto err1; - } - - // get the 'Prev' pointer - obj.getDict()->lookupNF("Prev", &obj2); - if (obj2.isInt()) { - *pos = (Guint)obj2.getInt(); - more = gTrue; - } else if (obj2.isRef()) { - // certain buggy PDF generators generate "/Prev NNN 0 R" instead - // of "/Prev NNN" - *pos = (Guint)obj2.getRefNum(); - more = gTrue; - } else { - more = gFalse; - } - obj2.free(); - - // save the first trailer dictionary - if (trailerDict.isNone()) { - obj.copy(&trailerDict); - } - - // check for an 'XRefStm' key - if (obj.getDict()->lookup("XRefStm", &obj2)->isInt()) { - pos2 = (Guint)obj2.getInt(); - readXRef(&pos2); - if (!ok) { - obj2.free(); - goto err1; - } - } - obj2.free(); - - obj.free(); - return more; - - err1: - obj.free(); - ok = gFalse; - return gFalse; -} - -GBool XRef::readXRefStream(Stream *xrefStr, Guint *pos) { - Dict *dict; - int w[3]; - GBool more; - Object obj, obj2, idx; - int newSize, first, n, i; - - dict = xrefStr->getDict(); - - if (!dict->lookupNF("Size", &obj)->isInt()) { - goto err1; - } - newSize = obj.getInt(); - obj.free(); - if (newSize < 0) { - goto err1; - } - if (newSize > size) { - entries = (XRefEntry *)greallocn(entries, newSize, sizeof(XRefEntry)); - for (i = size; i < newSize; ++i) { - entries[i].offset = 0xffffffff; - entries[i].type = xrefEntryFree; - } - size = newSize; - } - - if (!dict->lookupNF("W", &obj)->isArray() || - obj.arrayGetLength() < 3) { - goto err1; - } - for (i = 0; i < 3; ++i) { - if (!obj.arrayGet(i, &obj2)->isInt()) { - obj2.free(); - goto err1; - } - w[i] = obj2.getInt(); - obj2.free(); - if (w[i] < 0 || w[i] > 4) { - goto err1; - } - } - obj.free(); - - xrefStr->reset(); - dict->lookupNF("Index", &idx); - if (idx.isArray()) { - for (i = 0; i+1 < idx.arrayGetLength(); i += 2) { - if (!idx.arrayGet(i, &obj)->isInt()) { - idx.free(); - goto err1; - } - first = obj.getInt(); - obj.free(); - if (!idx.arrayGet(i+1, &obj)->isInt()) { - idx.free(); - goto err1; - } - n = obj.getInt(); - obj.free(); - if (first < 0 || n < 0 || - !readXRefStreamSection(xrefStr, w, first, n)) { - idx.free(); - goto err0; - } - } - } else { - if (!readXRefStreamSection(xrefStr, w, 0, newSize)) { - idx.free(); - goto err0; - } - } - idx.free(); - - dict->lookupNF("Prev", &obj); - if (obj.isInt()) { - *pos = (Guint)obj.getInt(); - more = gTrue; - } else { - more = gFalse; - } - obj.free(); - if (trailerDict.isNone()) { - trailerDict.initDict(dict); - } - - return more; - - err1: - obj.free(); - err0: - ok = gFalse; - return gFalse; -} - -GBool XRef::readXRefStreamSection(Stream *xrefStr, int *w, int first, int n) { - Guint offset; - int type, gen, c, newSize, i, j; - - if (first + n < 0) { - return gFalse; - } - if (first + n > size) { - for (newSize = size ? 2 * size : 1024; - first + n > newSize && newSize > 0; - newSize <<= 1) ; - if (newSize < 0) { - return gFalse; - } - entries = (XRefEntry *)greallocn(entries, newSize, sizeof(XRefEntry)); - for (i = size; i < newSize; ++i) { - entries[i].offset = 0xffffffff; - entries[i].type = xrefEntryFree; - } - size = newSize; - } - for (i = first; i < first + n; ++i) { - if (w[0] == 0) { - type = 1; - } else { - for (type = 0, j = 0; j < w[0]; ++j) { - if ((c = xrefStr->getChar()) == EOF) { - return gFalse; - } - type = (type << 8) + c; - } - } - for (offset = 0, j = 0; j < w[1]; ++j) { - if ((c = xrefStr->getChar()) == EOF) { - return gFalse; - } - offset = (offset << 8) + c; - } - for (gen = 0, j = 0; j < w[2]; ++j) { - if ((c = xrefStr->getChar()) == EOF) { - return gFalse; - } - gen = (gen << 8) + c; - } - if (entries[i].offset == 0xffffffff) { - switch (type) { - case 0: - entries[i].offset = offset; - entries[i].gen = gen; - entries[i].type = xrefEntryFree; - break; - case 1: - entries[i].offset = offset; - entries[i].gen = gen; - entries[i].type = xrefEntryUncompressed; - break; - case 2: - entries[i].offset = offset; - entries[i].gen = gen; - entries[i].type = xrefEntryCompressed; - break; - default: - return gFalse; - } - } - } - - return gTrue; -} - -// Attempt to construct an xref table for a damaged file. -GBool XRef::constructXRef() { - Parser *parser; - Object newTrailerDict, obj; - char buf[256]; - Guint pos; - int num, gen; - int newSize; - int streamEndsSize; - char *p; - int i; - GBool gotRoot; - - gfree(entries); - size = 0; - entries = NULL; - - error(0, "PDF file is damaged - attempting to reconstruct xref table..."); - gotRoot = gFalse; - streamEndsLen = streamEndsSize = 0; - - 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(NULL, - new Lexer(NULL, - str->makeSubStream(pos + 7, gFalse, 0, &obj))); - parser->getObj(&newTrailerDict); - if (newTrailerDict.isDict()) { - newTrailerDict.dictLookupNF("Root", &obj); - if (obj.isRef()) { - rootNum = obj.getRefNum(); - rootGen = obj.getRefGen(); - if (!trailerDict.isNone()) { - trailerDict.free(); - } - newTrailerDict.copy(&trailerDict); - gotRoot = gTrue; - } - obj.free(); - } - newTrailerDict.free(); - delete parser; - - // look for object - } else if (isdigit(*p)) { - num = atoi(p); - if (num > 0) { - 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; - if (newSize < 0) { - error(-1, "Bad object number"); - return gFalse; - } - entries = (XRefEntry *) - greallocn(entries, newSize, sizeof(XRefEntry)); - for (i = size; i < newSize; ++i) { - entries[i].offset = 0xffffffff; - entries[i].type = xrefEntryFree; - } - size = newSize; - } - if (entries[num].type == xrefEntryFree || - gen >= entries[num].gen) { - entries[num].offset = pos - start; - entries[num].gen = gen; - entries[num].type = xrefEntryUncompressed; - } - } - } - } - } - } - - } else if (!strncmp(p, "endstream", 9)) { - if (streamEndsLen == streamEndsSize) { - streamEndsSize += 64; - streamEnds = (Guint *)greallocn(streamEnds, - streamEndsSize, sizeof(int)); - } - streamEnds[streamEndsLen++] = pos; - } - } - - if (gotRoot) - return gTrue; - - error(-1, "Couldn't find trailer dictionary"); - return gFalse; -} - -void XRef::setEncryption(int permFlagsA, GBool ownerPasswordOkA, - Guchar *fileKeyA, int keyLengthA, int encVersionA) { - int i; - - encrypted = gTrue; - permFlags = permFlagsA; - ownerPasswordOk = ownerPasswordOkA; - if (keyLengthA <= 16) { - keyLength = keyLengthA; - } else { - keyLength = 16; - } - for (i = 0; i < keyLength; ++i) { - fileKey[i] = fileKeyA[i]; - } - encVersion = encVersionA; -} - -GBool XRef::okToPrint(GBool ignoreOwnerPW) { - return (!ignoreOwnerPW && ownerPasswordOk) || (permFlags & permPrint); -} - -GBool XRef::okToChange(GBool ignoreOwnerPW) { - return (!ignoreOwnerPW && ownerPasswordOk) || (permFlags & permChange); -} - -GBool XRef::okToCopy(GBool ignoreOwnerPW) { - return (!ignoreOwnerPW && ownerPasswordOk) || (permFlags & permCopy); -} - -GBool XRef::okToAddNotes(GBool ignoreOwnerPW) { - return (!ignoreOwnerPW && ownerPasswordOk) || (permFlags & permNotes); -} - -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) { - goto err; - } - - e = &entries[num]; - switch (e->type) { - - case xrefEntryUncompressed: - if (e->gen != gen) { - goto err; - } - obj1.initNull(); - parser = new Parser(this, - new Lexer(this, - str->makeSubStream(start + e->offset, gFalse, 0, &obj1))); - parser->getObj(&obj1); - parser->getObj(&obj2); - parser->getObj(&obj3); - if (!obj1.isInt() || obj1.getInt() != num || - !obj2.isInt() || obj2.getInt() != gen || - !obj3.isCmd("obj")) { - obj1.free(); - obj2.free(); - obj3.free(); - delete parser; - goto err; - } - parser->getObj(obj, encrypted ? fileKey : (Guchar *)NULL, keyLength, - num, gen); - obj1.free(); - obj2.free(); - obj3.free(); - delete parser; - break; - - case xrefEntryCompressed: - if (gen != 0) { - goto err; - } - if (!objStr || objStr->getObjStrNum() != (int)e->offset) { - if (objStr) { - delete objStr; - } - objStr = new ObjectStream(this, e->offset); - } - objStr->getObject(e->gen, num, obj); - break; - - default: - goto err; - } - - return obj; - - err: - return obj->initNull(); -} - -Object *XRef::getDocInfo(Object *obj) { - return trailerDict.dictLookup("Info", obj); -} - -// Added for the pdftex project. -Object *XRef::getDocInfoNF(Object *obj) { - return trailerDict.dictLookupNF("Info", obj); -} - -GBool XRef::getStreamEnd(Guint streamStart, Guint *streamEnd) { - int a, b, m; - - if (streamEndsLen == 0 || - streamStart > streamEnds[streamEndsLen - 1]) { - return gFalse; - } - - a = -1; - b = streamEndsLen - 1; - // invariant: streamEnds[a] < streamStart <= streamEnds[b] - while (b - a > 1) { - m = (a + b) / 2; - if (streamStart <= streamEnds[m]) { - b = m; - } else { - a = m; - } - } - *streamEnd = streamEnds[b]; - return gTrue; -} - -Guint XRef::strToUnsigned(char *s) { - Guint x; - char *p; - int i; - - x = 0; - for (p = s, i = 0; *p && isdigit(*p) && i < 10; ++p, ++i) { - x = 10 * x + (*p - '0'); - } - return x; -} diff --git a/pdftops/XRef.h b/pdftops/XRef.h deleted file mode 100644 index 6588276c0..000000000 --- a/pdftops/XRef.h +++ /dev/null @@ -1,131 +0,0 @@ -//======================================================================== -// -// XRef.h -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef XREF_H -#define XREF_H - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "gtypes.h" -#include "Object.h" - -class Dict; -class Stream; -class Parser; -class ObjectStream; - -//------------------------------------------------------------------------ -// XRef -//------------------------------------------------------------------------ - -enum XRefEntryType { - xrefEntryFree, - xrefEntryUncompressed, - xrefEntryCompressed -}; - -struct XRefEntry { - Guint offset; - int gen; - XRefEntryType type; -}; - -class XRef { -public: - - // Constructor. Read xref table from stream. - XRef(BaseStream *strA); - - // Destructor. - ~XRef(); - - // Is xref table valid? - GBool isOk() { return ok; } - - // Get the error code (if isOk() returns false). - int getErrorCode() { return errCode; } - - // Set the encryption parameters. - void setEncryption(int permFlagsA, GBool ownerPasswordOkA, - Guchar *fileKeyA, int keyLengthA, int encVersionA); - - // Is the file encrypted? - GBool isEncrypted() { return encrypted; } - - // Check various permissions. - GBool okToPrint(GBool ignoreOwnerPW = gFalse); - GBool okToChange(GBool ignoreOwnerPW = gFalse); - GBool okToCopy(GBool ignoreOwnerPW = gFalse); - GBool okToAddNotes(GBool ignoreOwnerPW = gFalse); - - // 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); - Object *getDocInfoNF(Object *obj); - - // Return the number of objects in the xref table. - int getNumObjects() { return size; } - - // Return the offset of the last xref table. - Guint getLastXRefPos() { return lastXRefPos; } - - // Return the catalog object reference. - int getRootNum() { return rootNum; } - int getRootGen() { return rootGen; } - - // Get end position for a stream in a damaged file. - // Returns false if unknown or file is not damaged. - GBool getStreamEnd(Guint streamStart, Guint *streamEnd); - - // Direct access. - int getSize() { return size; } - XRefEntry *getEntry(int i) { return &entries[i]; } - Object *getTrailerDict() { return &trailerDict; } - -private: - - BaseStream *str; // input stream - Guint start; // offset in file (to allow for garbage - // at beginning of file) - XRefEntry *entries; // xref entries - int size; // size of <entries> array - int rootNum, rootGen; // catalog dict - GBool ok; // true if xref table is valid - int errCode; // error code (if <ok> is false) - Object trailerDict; // trailer dictionary - Guint lastXRefPos; // offset of last xref table - Guint *streamEnds; // 'endstream' positions - only used in - // damaged files - int streamEndsLen; // number of valid entries in streamEnds - ObjectStream *objStr; // cached object stream - GBool encrypted; // true if file is encrypted - int permFlags; // permission bits - GBool ownerPasswordOk; // true if owner password is correct - Guchar fileKey[16]; // file decryption key - int keyLength; // length of key, in bytes - int encVersion; // encryption algorithm - - Guint getStartXref(); - GBool readXRef(Guint *pos); - GBool readXRefTable(Parser *parser, Guint *pos); - GBool readXRefStreamSection(Stream *xrefStr, int *w, int first, int n); - GBool readXRefStream(Stream *xrefStr, Guint *pos); - GBool constructXRef(); - Guint strToUnsigned(char *s); -}; - -#endif diff --git a/pdftops/XpdfPluginAPI.cxx b/pdftops/XpdfPluginAPI.cxx deleted file mode 100644 index dfa63282b..000000000 --- a/pdftops/XpdfPluginAPI.cxx +++ /dev/null @@ -1,262 +0,0 @@ -//======================================================================== -// -// XpdfPluginAPI.cc -// -// Copyright 2004 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> - -#ifdef ENABLE_PLUGINS - -#include "gmem.h" -#include "GlobalParams.h" -#include "Object.h" -#include "PDFDoc.h" -#ifdef WIN32 -#include "WinPDFCore.h" -#else -#include "XPDFCore.h" -#endif -#include "XpdfPluginAPI.h" - -//------------------------------------------------------------------------ - -//~ This should use a pool of Objects; change xpdfFreeObj to match. -static Object *allocObj() { - return (Object *)gmalloc(sizeof(Object)); -} - -//------------------------------------------------------------------------ -// Document access functions -//------------------------------------------------------------------------ - -XpdfObject _xpdfGetInfoDict(XpdfDoc doc) { - Object *obj; - - obj = allocObj(); - return (XpdfObject)((PDFDoc *)doc)->getDocInfo(obj); -} - -XpdfObject _xpdfGetCatalog(XpdfDoc doc) { - Object *obj; - - obj = allocObj(); - return (XpdfObject)((PDFDoc *)doc)->getXRef()->getCatalog(obj); -} - -#ifdef _WIN32 - -HWND _xpdfWin32GetWindow(XpdfDoc doc) { - WinPDFCore *core; - - if (!(core = (WinPDFCore *)((PDFDoc *)doc)->getGUIData())) { - return NULL; - } - return core->getDrawFrame(); -} - -#else - -Widget _xpdfXGetWindow(XpdfDoc doc) { - XPDFCore *core; - - if (!(core = (XPDFCore *)((PDFDoc *)doc)->getGUIData())) { - return NULL; - } - return core->getWidget(); -} - -#endif - -//------------------------------------------------------------------------ -// Object access functions. -//------------------------------------------------------------------------ - -XpdfBool _xpdfObjIsBool(XpdfObject obj) { - return (XpdfBool)((Object *)obj)->isBool(); -} - -XpdfBool _xpdfObjIsInt(XpdfObject obj) { - return (XpdfBool)((Object *)obj)->isInt(); -} - -XpdfBool _xpdfObjIsReal(XpdfObject obj) { - return (XpdfBool)((Object *)obj)->isReal(); -} - -XpdfBool _xpdfObjIsNumber(XpdfObject obj) { - return (XpdfBool)((Object *)obj)->isNum(); -} - -XpdfBool _xpdfObjIsString(XpdfObject obj) { - return (XpdfBool)((Object *)obj)->isString(); -} - -XpdfBool _xpdfObjIsName(XpdfObject obj) { - return (XpdfBool)((Object *)obj)->isName(); -} - -XpdfBool _xpdfObjIsNull(XpdfObject obj) { - return (XpdfBool)((Object *)obj)->isNull(); -} - -XpdfBool _xpdfObjIsArray(XpdfObject obj) { - return (XpdfBool)((Object *)obj)->isArray(); -} - -XpdfBool _xpdfObjIsDict(XpdfObject obj) { - return (XpdfBool)((Object *)obj)->isDict(); -} - -XpdfBool _xpdfObjIsStream(XpdfObject obj) { - return (XpdfBool)((Object *)obj)->isStream(); -} - -XpdfBool _xpdfObjIsRef(XpdfObject obj) { - return (XpdfBool)((Object *)obj)->isRef(); -} - -XpdfBool _xpdfBoolValue(XpdfObject obj) { - return (XpdfBool)((Object *)obj)->getBool(); -} - -int _xpdfIntValue(XpdfObject obj) { - if (!((Object *)obj)->isInt()) { - return 0; - } - return ((Object *)obj)->getInt(); -} - -double _xpdfRealValue(XpdfObject obj) { - if (!((Object *)obj)->isReal()) { - return 0; - } - return ((Object *)obj)->getReal(); -} - -double _xpdfNumberValue(XpdfObject obj) { - if (!((Object *)obj)->isNum()) { - return 0; - } - return ((Object *)obj)->getNum(); -} - -int _xpdfStringLength(XpdfObject obj) { - if (!((Object *)obj)->isString()) { - return 0; - } - return ((Object *)obj)->getString()->getLength(); -} - -char *_xpdfStringValue(XpdfObject obj) { - if (!((Object *)obj)->isString()) { - return 0; - } - return ((Object *)obj)->getString()->getCString(); -} - -char *_xpdfNameValue(XpdfObject obj) { - if (!((Object *)obj)->isName()) { - return NULL; - } - return ((Object *)obj)->getName(); -} - -int _xpdfArrayLength(XpdfObject obj) { - if (!((Object *)obj)->isArray()) { - return 0; - } - return ((Object *)obj)->arrayGetLength(); -} - -XpdfObject _xpdfArrayGet(XpdfObject obj, int idx) { - Object *elem; - - elem = allocObj(); - if (!((Object *)obj)->isArray()) { - return (XpdfObject)elem->initNull(); - } - return (XpdfObject)((Object *)obj)->arrayGet(idx, elem); -} - -XpdfObject _xpdfDictGet(XpdfObject obj, char *key) { - Object *elem; - - elem = allocObj(); - if (!((Object *)obj)->isDict()) { - return (XpdfObject)elem->initNull(); - } - return (XpdfObject)((Object *)obj)->dictLookup(key, elem); -} - -void _xpdfFreeObj(XpdfObject obj) { - ((Object *)obj)->free(); - gfree(obj); -} - -//------------------------------------------------------------------------ -// Memory allocation functions -//------------------------------------------------------------------------ - -void *_xpdfMalloc(int size) { - return gmalloc(size); -} - -void *_xpdfRealloc(void *p, int size) { - return grealloc(p, size); -} - -void _xpdfFree(void *p) { - gfree(p); -} - -//------------------------------------------------------------------------ -// Security handlers -//------------------------------------------------------------------------ - -void _xpdfRegisterSecurityHandler(XpdfSecurityHandler *handler) { - if (handler->version <= xpdfPluginAPIVersion) { - globalParams->addSecurityHandler(handler); - } -} - -//------------------------------------------------------------------------ - -XpdfPluginVecTable xpdfPluginVecTable = { - xpdfPluginAPIVersion, - &_xpdfGetInfoDict, - &_xpdfGetCatalog, -#ifdef _WIN32 - &_xpdfWin32GetWindow, -#else - &_xpdfXGetWindow, -#endif - &_xpdfObjIsBool, - &_xpdfObjIsInt, - &_xpdfObjIsReal, - &_xpdfObjIsString, - &_xpdfObjIsName, - &_xpdfObjIsNull, - &_xpdfObjIsArray, - &_xpdfObjIsDict, - &_xpdfObjIsStream, - &_xpdfObjIsRef, - &_xpdfBoolValue, - &_xpdfIntValue, - &_xpdfRealValue, - &_xpdfStringLength, - &_xpdfStringValue, - &_xpdfNameValue, - &_xpdfArrayLength, - &_xpdfArrayGet, - &_xpdfDictGet, - &_xpdfFreeObj, - &_xpdfMalloc, - &_xpdfRealloc, - &_xpdfFree, - &_xpdfRegisterSecurityHandler, -}; - -#endif // ENABLE_PLUGINS diff --git a/pdftops/XpdfPluginAPI.h b/pdftops/XpdfPluginAPI.h deleted file mode 100644 index 7467f0209..000000000 --- a/pdftops/XpdfPluginAPI.h +++ /dev/null @@ -1,323 +0,0 @@ -/* - * XpdfPluginAPI.h - * - * Copyright 2004 Glyph & Cog, LLC - */ - -#ifndef XPDFPLUGINAPI_H -#define XPDFPLUGINAPI_H - -#ifdef _WIN32 -#include <windows.h> -#else -//#define Object XtObject -//#include <X11/Intrinsic.h> -//#undef Object -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/*------------------------------------------------------------------------ - * Macros - *------------------------------------------------------------------------*/ - -/* - * The current API version. - */ -#define xpdfPluginAPIVersion 1 - -#ifdef _WIN32 -# ifdef __cplusplus -# define PLUGINFUNC(retType) extern "C" __declspec(dllexport) retType -# else -# define PLUGINFUNC(retType) extern __declspec(dllexport) retType -# endif -#else -# ifdef __cplusplus -# define PLUGINFUNC(retType) extern "C" retType -# else -# define PLUGINFUNC(retType) extern retType -# endif -#endif - -/*------------------------------------------------------------------------ - * Plugin setup/cleanup - *------------------------------------------------------------------------*/ - -/* - * All plugins are required to implement two functions: - * - * -- Initialize the plugin. Returns non-zero if successful. - * PLUGINFUNC(XpdfBool) xpdfInitPlugin(void); - * - * -- Free the plugin. - * PLUGINFUNC(void) xpdfFreePlugin(void); - */ - -/*------------------------------------------------------------------------ - * Types - *------------------------------------------------------------------------*/ - -/* - * Standard C boolean -- zero = false, non-zero = true. - */ -typedef int XpdfBool; -#define xpdfTrue 1 -#define xpdfFalse 0 - -/* - * PDF document handle. - */ -typedef struct _XpdfDoc *XpdfDoc; - -/* - * PDF object handle. - */ -typedef struct _XpdfObject *XpdfObject; - -/* - * Document access permissions. Any of these can be bitwise 'or'ed - * together. If xpdfPermissionOpen is not included, the document - * cannot be opened at all, and the other bits are ignored. - */ -typedef unsigned int XpdfPermission; -#define xpdfPermissionOpen (1 << 0) -#define xpdfPermissionPrint (1 << 2) -#define xpdfPermissionChange (1 << 3) -#define xpdfPermissionCopy (1 << 4) -#define xpdfPermissionNotes (1 << 5) - -/*------------------------------------------------------------------------ - * Security handler - *------------------------------------------------------------------------*/ - -/* - * XpdfSecurityHandler - a security handler plugin should create one - * of these and pass it to xpdfRegisterSecurityHandler. - */ -#ifdef __cplusplus -struct XpdfSecurityHandler { -#else -typedef struct { -#endif - - /* - * Version of the security handler spec (this document) -- use - * xpdfPluginAPIVersion. - */ - int version; - - /* - * Security handler name. - */ - char *name; - - /* - * Any global data the security handler needs. XpdfViewer will pass - * this pointer to all handler functions as the <handlerData> - * argument. - */ - void *handlerData; - - /* - * Allocate and initialize data for a new document. XpdfViewer will - * pass the returned pointer to all other handler functions as the - * <docData> argument. Returns non-zero if successful. - */ - XpdfBool (*newDoc)(void *handlerData, XpdfDoc doc, - XpdfObject encryptDict, void **docData); - - /* - * Free the data allocated by newDoc. - */ - void (*freeDoc)(void *handlerData, void *docData); - - /* - * Construct authorization data based on the supplied owner and user - * passwords (either or both of which may be NULL). This function - * is called in "batch" mode, i.e., if the password was supplied on - * the command line or via an Xpdf library API. It should not - * generate any user interaction (e.g., a password dialog). It is - * not required to support this function: the makeAuthData function - * pointer can be set to NULL. Returns non-zero if successful. - */ - XpdfBool (*makeAuthData)(void *handlerData, void *docData, - char *ownerPassword, char *userPassword, - void **authData); - - /* - * Request any needed information (e.g., a password) from the user, - * and construct an authorization data object. Returns non-zero if - * successful. - */ - XpdfBool (*getAuthData)(void *handlerData, void *docData, - void **authData); - - /* - * Free the data allocated by getAuthData. - */ - void (*freeAuthData)(void *handlerData, void *docData, - void *authData); - - /* - * Request permission to access the document. This returns all - * permissions granted by authData. - */ - XpdfPermission (*authorize)(void *handlerData, void *docData, - void *authData); - - /* - * Get the decryption key and algorithm version associated with the - * document. Returns non-zero if successful. - */ - XpdfBool (*getKey)(void *handlerData, void *docData, - char **key, int *keyLen, int *cryptVersion); - - /* - * Free the data allocated by getKey. - */ - void (*freeKey)(void *handlerData, void *docData, - char *key, int keyLen); - -#ifdef __cplusplus -}; -#else -} XpdfSecurityHandler; -#endif - -/*------------------------------------------------------------------------*/ - -typedef struct { - int version; - -/*------------------------------------------------------------------------ - * Document access functions - *------------------------------------------------------------------------*/ - -/* - * Get a document's info dictionary. (The returned object must be - * freed with xpdfFreeObj.) - */ -XpdfObject (*_xpdfGetInfoDict)(XpdfDoc doc); - -/* - * Get a document's catalog ("root") dictionary. (The returned object - * must be freed with xpdfFreeObj.) - */ -XpdfObject (*_xpdfGetCatalog)(XpdfDoc doc); - -/*------------------------------------------------------------------------ - * Object access functions - *------------------------------------------------------------------------*/ - -/* - * Check an object's type. - */ -XpdfBool (*_xpdfObjIsBool)(XpdfObject obj); -XpdfBool (*_xpdfObjIsInt)(XpdfObject obj); -XpdfBool (*_xpdfObjIsReal)(XpdfObject obj); -XpdfBool (*_xpdfObjIsString)(XpdfObject obj); -XpdfBool (*_xpdfObjIsName)(XpdfObject obj); -XpdfBool (*_xpdfObjIsNull)(XpdfObject obj); -XpdfBool (*_xpdfObjIsArray)(XpdfObject obj); -XpdfBool (*_xpdfObjIsDict)(XpdfObject obj); -XpdfBool (*_xpdfObjIsStream)(XpdfObject obj); -XpdfBool (*_xpdfObjIsRef)(XpdfObject obj); - -/* - * Value access. - * (Objects returned by xpdfArrayGet and xpdfDictGet must be freed - * with xpdfFreeObj.) - */ -XpdfBool (*_xpdfBoolValue)(XpdfObject obj); -int (*_xpdfIntValue)(XpdfObject obj); -double (*_xpdfRealValue)(XpdfObject obj); -int (*_xpdfStringLength)(XpdfObject obj); -char *(*_xpdfStringValue)(XpdfObject obj); -char *(*_xpdfNameValue)(XpdfObject obj); -int (*_xpdfArrayLength)(XpdfObject obj); -XpdfObject (*_xpdfArrayGet)(XpdfObject obj, int idx); -XpdfObject (*_xpdfDictGet)(XpdfObject obj, char *key); - -/* - * Object destruction. NB: *all* objects must be freed after use. - */ -void (*_xpdfFreeObj)(XpdfObject obj); - -/*------------------------------------------------------------------------ - * Memory allocation functions - *------------------------------------------------------------------------*/ - -void *(*_xpdfMalloc)(int size); -void *(*_xpdfRealloc)(void *p, int size); -void (*_xpdfFree)(void *p); - -/*------------------------------------------------------------------------ - * Security handler functions - *------------------------------------------------------------------------*/ - -/* - * Register a new security handler. - */ -void (*_xpdfRegisterSecurityHandler)(XpdfSecurityHandler *handler); - -/*------------------------------------------------------------------------*/ - -} XpdfPluginVecTable; - -#ifdef _WIN32 - -extern __declspec(dllexport) XpdfPluginVecTable xpdfPluginVecTable; - -#define xpdfPluginSetup \ - extern __declspec(dllexport) \ - XpdfPluginVecTable xpdfPluginVecTable = {xpdfPluginAPIVersion}; - -#else - -extern XpdfPluginVecTable xpdfPluginVecTable; - -#define xpdfPluginSetup \ - XpdfPluginVecTable xpdfPluginVecTable = {xpdfPluginAPIVersion}; - -#endif - -#define xpdfGetInfoDict (*xpdfPluginVecTable._xpdfGetInfoDict) -#define xpdfGetCatalog (*xpdfPluginVecTable._xpdfGetCatalog) -#ifdef _WIN32 -#define xpdfWin32GetWindow (*xpdfPluginVecTable._xpdfWin32GetWindow) -#else -#define xpdfXGetWindow (*xpdfPluginVecTable._xpdfXGetWindow) -#endif -#define xpdfObjIsBool (*xpdfPluginVecTable._xpdfObjIsBool) -#define xpdfObjIsInt (*xpdfPluginVecTable._xpdfObjIsInt) -#define xpdfObjIsReal (*xpdfPluginVecTable._xpdfObjIsReal) -#define xpdfObjIsString (*xpdfPluginVecTable._xpdfObjIsString) -#define xpdfObjIsName (*xpdfPluginVecTable._xpdfObjIsName) -#define xpdfObjIsNull (*xpdfPluginVecTable._xpdfObjIsNull) -#define xpdfObjIsArray (*xpdfPluginVecTable._xpdfObjIsArray) -#define xpdfObjIsDict (*xpdfPluginVecTable._xpdfObjIsDict) -#define xpdfObjIsStream (*xpdfPluginVecTable._xpdfObjIsStream) -#define xpdfObjIsRef (*xpdfPluginVecTable._xpdfObjIsRef) -#define xpdfBoolValue (*xpdfPluginVecTable._xpdfBoolValue) -#define xpdfIntValue (*xpdfPluginVecTable._xpdfIntValue) -#define xpdfRealValue (*xpdfPluginVecTable._xpdfRealValue) -#define xpdfStringLength (*xpdfPluginVecTable._xpdfStringLength) -#define xpdfStringValue (*xpdfPluginVecTable._xpdfStringValue) -#define xpdfNameValue (*xpdfPluginVecTable._xpdfNameValue) -#define xpdfArrayLength (*xpdfPluginVecTable._xpdfArrayLength) -#define xpdfArrayGet (*xpdfPluginVecTable._xpdfArrayGet) -#define xpdfDictGet (*xpdfPluginVecTable._xpdfDictGet) -#define xpdfFreeObj (*xpdfPluginVecTable._xpdfFreeObj) -#define xpdfMalloc (*xpdfPluginVecTable._xpdfMalloc) -#define xpdfRealloc (*xpdfPluginVecTable._xpdfRealloc) -#define xpdfFree (*xpdfPluginVecTable._xpdfFree) -#define xpdfRegisterSecurityHandler (*xpdfPluginVecTable._xpdfRegisterSecurityHandler) - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/pdftops/config.h b/pdftops/config.h deleted file mode 100644 index 4c8f75673..000000000 --- a/pdftops/config.h +++ /dev/null @@ -1,112 +0,0 @@ -//======================================================================== -// -// config.h -// -// Copyright 1996-2005 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef CONFIG_H -#define CONFIG_H - -//------------------------------------------------------------------------ -// version -//------------------------------------------------------------------------ - -// xpdf version -#define xpdfVersion "3.01" -#define xpdfVersionNum 3.01 -#define xpdfMajorVersion 3 -#define xpdfMinorVersion 1 -#define xpdfUpdateVersion 0 -#define xpdfMajorVersionStr "3" -#define xpdfMinorVersionStr "1" -#define xpdfUpdateVersionStr "0" - -// supported PDF version -#define supportedPDFVersionStr "1.5" -#define supportedPDFVersionNum 1.5 - -// copyright notice -#define xpdfCopyright "Copyright 1996-2005 Glyph & Cog, LLC" - -// Windows resource file stuff -#define winxpdfVersion "WinXpdf 3.01" -#define xpdfCopyrightAmp "Copyright 1996-2005 Glyph && Cog, LLC" - -//------------------------------------------------------------------------ -// paper size -//------------------------------------------------------------------------ - -// default paper size (in points) for PostScript output -#ifdef A4_PAPER -#define defPaperWidth 595 // ISO A4 (210x297 mm) -#define defPaperHeight 842 -#else -#define defPaperWidth 612 // American letter (8.5x11") -#define defPaperHeight 792 -#endif - -//------------------------------------------------------------------------ -// config file (xpdfrc) path -//------------------------------------------------------------------------ - -// user config file name, relative to the user's home directory -#if defined(VMS) || (defined(WIN32) && !defined(__CYGWIN32__)) -#define xpdfUserConfigFile "xpdfrc" -#else -#define xpdfUserConfigFile ".xpdfrc" -#endif - -// system config file name (set via the configure script) -#ifdef SYSTEM_XPDFRC -#define xpdfSysConfigFile SYSTEM_XPDFRC -#else -// under Windows, we get the directory with the executable and then -// append this file name -#define xpdfSysConfigFile "xpdfrc" -#endif - -//------------------------------------------------------------------------ -// X-related constants -//------------------------------------------------------------------------ - -// default maximum size of color cube to allocate -#define defaultRGBCube 5 - -// number of fonts (combined t1lib, FreeType, X server) to cache -#define xOutFontCacheSize 64 - -// number of Type 3 fonts to cache -#define xOutT3FontCacheSize 8 - -//------------------------------------------------------------------------ -// popen -//------------------------------------------------------------------------ - -#if defined(_MSC_VER) || defined(__BORLANDC__) -#define popen _popen -#define pclose _pclose -#endif - -#if defined(VMS) || defined(VMCMS) || defined(DOS) || defined(OS2) || defined(__EMX__) || defined(WIN32) || defined(__DJGPP__) || defined(MACOS) -#define POPEN_READ_MODE "rb" -#else -#define POPEN_READ_MODE "r" -#endif - -//------------------------------------------------------------------------ -// Win32 stuff -//------------------------------------------------------------------------ - -#ifdef CDECL -#undef CDECL -#endif - -#if defined(_MSC_VER) || defined(__BORLANDC__) -#define CDECL __cdecl -#else -#define CDECL -#endif - -#endif diff --git a/pdftops/gfile.cxx b/pdftops/gfile.cxx deleted file mode 100644 index ae0ea9ce2..000000000 --- a/pdftops/gfile.cxx +++ /dev/null @@ -1,707 +0,0 @@ -//======================================================================== -// -// gfile.cc -// -// Miscellaneous file and directory name manipulation. -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> - -#ifndef WIN32 -# if defined(MACOS) -# include <sys/stat.h> -# elif !defined(ACORN) -# include <sys/types.h> -# include <sys/stat.h> -# include <fcntl.h> -# endif -# include <limits.h> -# include <string.h> -# if !defined(VMS) && !defined(ACORN) && !defined(MACOS) -# include <pwd.h> -# endif -# if defined(VMS) && (__DECCXX_VER < 50200000) -# include <unixlib.h> -# 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 -} - -#if 0 // Not needed for PS output -GBool openTempFile(GString **name, FILE **f, char *mode, char *ext) { -#if defined(WIN32) - //---------- Win32 ---------- - char *s; - - if (!(s = _tempnam(getenv("TEMP"), NULL))) { - return gFalse; - } - *name = new GString(s); - free(s); - if (ext) { - (*name)->append(ext); - } - if (!(*f = fopen((*name)->getCString(), mode))) { - delete (*name); - return gFalse; - } - return gTrue; -#elif defined(VMS) || defined(__EMX__) || 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; - int fd; - - if (ext) { -#if HAVE_MKSTEMPS - if ((s = getenv("TMPDIR"))) { - *name = new GString(s); - } else { - *name = new GString("/tmp"); - } - (*name)->append("/XXXXXX")->append(ext); - fd = mkstemps((*name)->getCString(), strlen(ext)); -#else - if (!(s = tmpnam(NULL))) { - return gFalse; - } - *name = new GString(s); - (*name)->append(ext); - fd = open((*name)->getCString(), O_WRONLY | O_CREAT | O_EXCL, 0600); -#endif - } 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 -} - -GBool executeCommand(char *cmd) { -#ifdef VMS - return system(cmd) ? gTrue : gFalse; -#else - return system(cmd) ? gFalse : gTrue; -#endif -} -#endif // 0 - -char *getLine(char *buf, int size, FILE *f) { - int c, i; - - i = 0; - while (i < size - 1) { - if ((c = fgetc(f)) == EOF) { - break; - } - buf[i++] = (char)c; - if (c == '\x0a') { - break; - } - if (c == '\x0d') { - c = fgetc(f); - if (c == '\x0a' && i < size - 1) { - buf[i++] = (char)c; - } else if (c != EOF) { - ungetc(c, f); - } - break; - } - } - buf[i] = '\0'; - if (i == 0) { - return NULL; - } - return buf; -} - -//------------------------------------------------------------------------ -// GDir and GDirEntry -//------------------------------------------------------------------------ - -GDirEntry::GDirEntry(char *dirPath, char *nameA, 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(nameA); - dir = gFalse; - if (doStat) { -#ifdef VMS - if (!strcmp(nameA, "-") || - ((p = strrchr(nameA, '.')) && !strncmp(p, ".DIR;", 5))) - dir = gTrue; -#elif defined(ACORN) -#else - s = new GString(dirPath); - appendToPath(s, nameA); -#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 doStatA) { - path = new GString(name); - doStat = doStatA; -#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() { - GDirEntry *e; - -#if defined(WIN32) - if (hnd) { - e = new GDirEntry(path->getCString(), ffd.cFileName, doStat); - if (hnd && !FindNextFile(hnd, &ffd)) { - FindClose(hnd); - hnd = NULL; - } - } else { - e = NULL; - } -#elif defined(ACORN) -#elif defined(MACOS) -#elif defined(VMS) - struct dirent *ent; - e = NULL; - if (dir) { - if (needParent) { - e = new GDirEntry(path->getCString(), "-", doStat); - needParent = gFalse; - return e; - } - ent = readdir(dir); - if (ent) { - e = new GDirEntry(path->getCString(), ent->d_name, doStat); - } - } -#else - struct dirent *ent; - e = NULL; - if (dir) { - ent = readdir(dir); - if (ent && !strcmp(ent->d_name, ".")) { - ent = readdir(dir); - } - 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); - delete tmp; -#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 deleted file mode 100644 index 808e1821d..000000000 --- a/pdftops/gfile.h +++ /dev/null @@ -1,126 +0,0 @@ -//======================================================================== -// -// gfile.h -// -// Miscellaneous file and directory name manipulation. -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef GFILE_H -#define GFILE_H - -#include <stdio.h> -#include <stdlib.h> -#include <stddef.h> -#if defined(WIN32) -# include <sys/stat.h> -# ifdef FPTEX -# include <win32lib.h> -# else -# include <windows.h> -# endif -#elif defined(ACORN) -#elif defined(MACOS) -# include <ctime.h> -#else -# include <unistd.h> -# include <sys/types.h> -# ifdef VMS -# include "vms_dirent.h" -# else -# include <dirent.h> -# define NAMLEN(d) strlen((d)->d_name) -# 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. <path> may be an empty -// string, denoting the current directory). Returns <path>. -extern GString *appendToPath(GString *path, char *fileName); - -// Grab the path from the front of the file name. If there is no -// directory component in <fileName>, 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 '~'). -extern GString *makePathAbsolute(GString *path); - -// Get the modification time for <fileName>. Returns 0 if there is an -// error. -extern time_t getModTime(char *fileName); - -// Create a temporary file and open it for writing. If <ext> 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 <mode> string -// should be "w" or "wb". Returns true on success. -extern GBool openTempFile(GString **name, FILE **f, char *mode, char *ext); - -// Execute <command>. Returns true on success. -extern GBool executeCommand(char *cmd); - -// Just like fgets, but handles Unix, Mac, and/or DOS end-of-line -// conventions. -extern char *getLine(char *buf, int size, FILE *f); - -//------------------------------------------------------------------------ -// GDir and GDirEntry -//------------------------------------------------------------------------ - -class GDirEntry { -public: - - GDirEntry(char *dirPath, char *nameA, 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 doStatA = 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 deleted file mode 100644 index f7f35dfe7..000000000 --- a/pdftops/gmem.c +++ /dev/null @@ -1,239 +0,0 @@ -/* - * gmem.c - * - * Memory routines with out-of-memory checking. - * - * Copyright 1996-2003 Glyph & Cog, LLC - */ - -#include <config.h> -#include <stdio.h> -#include <stdlib.h> -#include <stddef.h> -#include <string.h> -#include <limits.h> -#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 0xdeadbeefdeadbeefUL -#else -#define gMemDeadVal 0xdeadbeefUL -#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; -static int gMemInUse = 0; - -#endif /* DEBUG_MEM */ - -void *gmalloc(int size) { -#ifdef DEBUG_MEM - int size1; - char *mem; - GMemHdr *hdr; - void *data; - int lst; - unsigned 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 = (unsigned long *)(mem + gMemHdrSize + size1); - hdr->size = size; - hdr->index = gMemIndex++; - lst = ((int)hdr >> gMemListShift) & gMemListMask; - hdr->next = gMemList[lst]; - gMemList[lst] = hdr; - ++gMemAlloc; - gMemInUse += size; - for (p = (unsigned 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 *gmallocn(int nObjs, int objSize) { - int n; - - if (nObjs == 0) { - return NULL; - } - n = nObjs * objSize; - if (objSize <= 0 || nObjs < 0 || nObjs >= INT_MAX / objSize) { - fprintf(stderr, "Bogus memory allocation size\n"); - exit(1); - } - return gmalloc(n); -} - -void *greallocn(void *p, int nObjs, int objSize) { - int n; - - if (nObjs == 0) { - if (p) { - gfree(p); - } - return NULL; - } - n = nObjs * objSize; - if (objSize <= 0 || nObjs < 0 || nObjs >= INT_MAX / objSize) { - fprintf(stderr, "Bogus memory allocation size\n"); - exit(1); - } - return grealloc(p, n); -} - -void gfree(void *p) { -#ifdef DEBUG_MEM - int size; - GMemHdr *hdr; - GMemHdr *prevHdr, *q; - int lst; - unsigned 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; - gMemInUse -= hdr->size; - size = gMemDataSize(hdr->size); - trl = (unsigned 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 = (unsigned 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 deleted file mode 100644 index e74d18223..000000000 --- a/pdftops/gmem.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * gmem.h - * - * Memory routines with out-of-memory checking. - * - * Copyright 1996-2003 Glyph & Cog, LLC - */ - -#ifndef GMEM_H -#define GMEM_H - -#include <stdio.h> - -#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 <p> is NULL, calls malloc instead of realloc(). - */ -extern void *grealloc(void *p, int size); - -/* - * These are similar to gmalloc and grealloc, but take an object count - * and size. The result is similar to allocating nObjs * objSize - * bytes, but there is an additional error check that the total size - * doesn't overflow an int. - */ -extern void *gmallocn(int nObjs, int objSize); -extern void *greallocn(void *p, int nObjs, int objSize); - -/* - * 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 deleted file mode 100644 index a70338ca3..000000000 --- a/pdftops/gmempp.cxx +++ /dev/null @@ -1,32 +0,0 @@ -//======================================================================== -// -// gmempp.cc -// -// Use gmalloc/gfree for C++ new/delete operators. -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include <config.h> -#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 deleted file mode 100644 index 9f64f57d4..000000000 --- a/pdftops/gtypes.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * gtypes.h - * - * Some useful simple types. - * - * Copyright 1996-2003 Glyph & Cog, LLC - */ - -#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 <sys/types.h>, - * 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 deleted file mode 100644 index f77cc85c8..000000000 --- a/pdftops/parseargs.c +++ /dev/null @@ -1,190 +0,0 @@ -/* - * parseargs.h - * - * Command line argument parser. - * - * Copyright 1996-2003 Glyph & Cog, LLC - */ - -#include <stdio.h> -#include <stddef.h> -#include <string.h> -#include <stdlib.h> -#include <ctype.h> -#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 = " <int>"; - break; - case argFP: - case argFPDummy: - typ = " <fp>"; - break; - case argString: - case argStringDummy: - typ = " <string>"; - 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 & 0xff)) - ++s; - if (*s) - return gFalse; - return gTrue; -} - -GBool isFP(char *s) { - int n; - - if (*s == '-' || *s == '+') - ++s; - n = 0; - while (isdigit(*s & 0xff)) { - ++s; - ++n; - } - if (*s == '.') - ++s; - while (isdigit(*s & 0xff)) { - ++s; - ++n; - } - if (n > 0 && (*s == 'e' || *s == 'E')) { - ++s; - if (*s == '-' || *s == '+') - ++s; - n = 0; - if (!isdigit(*s & 0xff)) - return gFalse; - do { - ++s; - } while (isdigit(*s & 0xff)); - } - if (*s) - return gFalse; - return gTrue; -} diff --git a/pdftops/parseargs.h b/pdftops/parseargs.h deleted file mode 100644 index 0d163b985..000000000 --- a/pdftops/parseargs.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * parseargs.h - * - * Command line argument parser. - * - * Copyright 1996-2003 Glyph & Cog, LLC - */ - -#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 <args>. 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 deleted file mode 100644 index a583ae46c..000000000 --- a/pdftops/pdftops.cxx +++ /dev/null @@ -1,344 +0,0 @@ -// -// "$Id: pdftops.cxx 6649 2007-07-11 21:46:42Z mike $" -// -// PDF to PostScript filter front-end for the Common UNIX Printing -// System (CUPS). -// -// Copyright 2007 by Apple Inc. -// Copyright 1997-2006 by Easy Software Products. -// -// These coded instructions, statements, and computer programs are the -// property of Apple Inc. and are protected by Federal copyright -// law. Distribution and use rights are outlined in the file "LICENSE.txt" -// which should have been included with this file. If this file is -// file is missing or damaged, see the license at "http://www.cups.org/". -// -// Contents: -// -// main() - Main entry for filter... -// - -// -// Include necessary headers... -// - -#include <stdio.h> -#include <stdlib.h> -#include <stddef.h> -#include <cups/string.h> -#include <cups/i18n.h> -#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 "GlobalParams.h" -#include "Error.h" -#include "config.h" - -#include <cups/cups.h> - - -// -// 'main()' - Main entry for filter... -// - -int // O - Exit status -main(int argc, // I - Number of command-line args - char *argv[]) // I - Command-line arguments -{ - PDFDoc *doc; // Input file - GString *fileName; // Input filename - GString *psFileName; // Output filename - PSLevel level; // PostScript level - PSOutputDev *psOut; // Output device - int num_options; // Number of options - cups_option_t *options; // Options - const char *val; // Option value - ppd_file_t *ppd; // Current PPD - ppd_size_t *size; // Current media size - int fd; // Copy file descriptor - const char *server_root; // Location of config files - char tempfile[1024]; // Temporary file - char buffer[8192]; // Copy buffer - int bytes; // Bytes copied - int width, length; // Size in points - int left, bottom, right, top; - // Imageable area in points - int orientation; // Orientation - int temp; // Temporary var - int duplex; // Duplex the output? - int fit; // Fit the pages to the output - int printCommands; // Output debug info for commands? - - - // Make sure status messages are not buffered... - setbuf(stderr, NULL); - - // Make sure we have the right number of arguments for CUPS! - if (argc < 6 || argc > 7) { - fprintf(stderr, _("Usage: %s job user title copies options [filename]\n"), - argv[0]); - return (1); - } - - // Copy stdin if needed... - if (argc == 6) { - if ((fd = cupsTempFd(tempfile, sizeof(tempfile))) < 0) { - 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) - write(fd, buffer, bytes); - close(fd); - - fileName = new GString(tempfile); - } else { - fileName = new GString(argv[6]); - tempfile[0] = '\0'; - } - - // Default to "Universal" size - min of A4 and Letter... - left = 0; - bottom = 0; - right = 595; - top = 792; - width = 595; - length = 792; - level = psLevel2; - duplex = 0; - fit = 0; - - // Get PPD and initialize options as needed... - num_options = cupsParseOptions(argv[5], 0, &options); - - if ((ppd = ppdOpenFile(getenv("PPD"))) != NULL) - { - fprintf(stderr, "DEBUG: pdftops - opened PPD file \"%s\"...\n", getenv("PPD")); - - ppdMarkDefaults(ppd); - cupsMarkOptions(ppd, num_options, options); - - if ((size = ppdPageSize(ppd, NULL)) != NULL) - { - left = (int)size->left; - bottom = (int)size->bottom; - right = (int)size->right; - top = (int)size->top; - width = (int)size->width; - length = (int)size->length; - } - - level = ppd->language_level == 1 ? psLevel1 : psLevel2; - } - - // Track the orientation of the print job and update the page - // dimensions and margins as needed... - orientation = 0; - - if ((val = cupsGetOption("landscape", num_options, options)) != NULL) - { - if (strcasecmp(val, "no") != 0 && strcasecmp(val, "off") != 0 && - strcasecmp(val, "false") != 0) - orientation = 1; - } - else 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; - } - - switch (orientation & 3) - { - case 0 : /* Portait */ - break; - - case 1 : /* Landscape */ - temp = left; - left = bottom; - bottom = temp; - - temp = right; - right = top; - top = temp; - - temp = width; - width = length; - length = temp; - break; - - case 2 : /* Reverse Portrait */ - temp = width - left; - left = width - right; - right = temp; - - temp = length - bottom; - bottom = length - top; - top = temp; - break; - - case 3 : /* Reverse Landscape */ - temp = width - left; - left = width - right; - right = temp; - - temp = length - bottom; - bottom = length - top; - top = temp; - - temp = left; - left = bottom; - bottom = temp; - - temp = right; - right = top; - top = temp; - - temp = width; - width = length; - length = temp; - break; - } - - if ((val = cupsGetOption("debug", num_options, options)) != NULL && - strcasecmp(val, "no") && strcasecmp(val, "off") && - strcasecmp(val, "false")) - printCommands = 1; - else - printCommands = 0; - - if ((val = cupsGetOption("fitplot", num_options, options)) != NULL && - strcasecmp(val, "no") && strcasecmp(val, "off") && - strcasecmp(val, "false")) - fit = 1; - - 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 ((val = cupsGetOption("JCLDuplex", num_options, options)) != NULL && - strncasecmp(val, "Duplex", 6) == 0) - duplex = 1; - else if ((val = cupsGetOption("EFDuplex", num_options, options)) != NULL && - strncasecmp(val, "Duplex", 6) == 0) - duplex = 1; - else if ((val = cupsGetOption("KD03Duplex", num_options, options)) != NULL && - strncasecmp(val, "Duplex", 6) == 0) - duplex = 1; - else if (ppdIsMarked(ppd, "Duplex", "DuplexNoTumble") || - ppdIsMarked(ppd, "Duplex", "DuplexTumble") || - ppdIsMarked(ppd, "JCLDuplex", "DuplexNoTumble") || - ppdIsMarked(ppd, "JCLDuplex", "DuplexTumble") || - ppdIsMarked(ppd, "EFDuplex", "DuplexNoTumble") || - ppdIsMarked(ppd, "EFDuplex", "DuplexTumble") || - ppdIsMarked(ppd, "KD03Duplex", "DuplexNoTumble") || - ppdIsMarked(ppd, "KD03Duplex", "DuplexTumble")) - duplex = 1; - - if (ppd != NULL) - ppdClose(ppd); - - fprintf(stderr, "DEBUG: pdftops - level = %d, width = %d, length = %d\n", - level, width, length); - - // read config file - if ((server_root = getenv("CUPS_SERVERROOT")) == NULL) - server_root = CUPS_SERVERROOT; - - snprintf(buffer, sizeof(buffer), "%s/pdftops.conf", server_root); - - globalParams = new GlobalParams(buffer); - - if (fit || globalParams->getPSPaperWidth() > 0) - { - // Only set paper size and area if we are fitting to the job's - // page size or the pdftops.conf file does not contain - // "psPaperSize match"... - globalParams->setPSPaperWidth(width); - globalParams->setPSPaperHeight(length); - globalParams->setPSImageableArea(left, bottom, right, top); - } - - globalParams->setPSDuplex(duplex); - globalParams->setPSExpandSmaller(fit); - globalParams->setPSShrinkLarger(fit); - globalParams->setPSLevel(level); - globalParams->setPSASCIIHex(level == psLevel1); - globalParams->setPSEmbedType1(1); - globalParams->setPSEmbedTrueType(1); - globalParams->setPSEmbedCIDPostScript(1); - globalParams->setErrQuiet(0); - globalParams->setPrintCommands(printCommands); - - if (printCommands) - setbuf(stdout, NULL); - - // open PDF file - doc = new PDFDoc(fileName, NULL, NULL); - - // check for print permission - if (doc->isOk() && doc->okToPrint()) - { - // CUPS always writes to stdout... - psFileName = new GString("-"); - - // write PostScript file - psOut = new PSOutputDev(psFileName->getCString(), doc->getXRef(), - doc->getCatalog(), 1, doc->getNumPages(), - psModePS, 0, 0, 0, 0, gFalse, NULL); - if (psOut->isOk()) - doc->displayPages(psOut, 1, doc->getNumPages(), 72.0, 72.0, 0, - gTrue, gFalse, gFalse); - delete psOut; - - // clean up - delete psFileName; - } - else - { - error(-1, "Unable to print this document."); - } - - cupsFreeOptions(num_options, options); - - delete doc; - delete globalParams; - - // check for memory leaks - Object::memCheck(stderr); - gMemReport(stderr); - - // Remove temp file if needed... - if (tempfile[0]) - unlink(tempfile); - - return 0; -} - - -// -// End of "$Id: pdftops.cxx 6649 2007-07-11 21:46:42Z mike $". -// diff --git a/scheduler/auth.c b/scheduler/auth.c index 78b7a5d30..5b2dd3e96 100644 --- a/scheduler/auth.c +++ b/scheduler/auth.c @@ -179,8 +179,13 @@ cupsdAddLocation(const char *location) /* I - Location path */ * Initialize the record and copy the name over... */ - temp->location = strdup(location); - temp->length = strlen(temp->location); + if ((temp->location = strdup(location)) == NULL) + { + free(temp); + return (NULL); + } + + temp->length = strlen(temp->location); cupsArrayAdd(Locations, temp); diff --git a/scheduler/banners.c b/scheduler/banners.c index 47b56d3b1..66305fb08 100644 --- a/scheduler/banners.c +++ b/scheduler/banners.c @@ -3,7 +3,7 @@ * * Banner routines for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1997-2006 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -147,8 +147,8 @@ add_banner(const char *name, /* I - Name of banner */ if ((filetype = mimeFileType(MimeDatabase, filename, NULL, NULL)) == NULL) { cupsdLogMessage(CUPSD_LOG_WARN, - "add_banner: Banner \"%s\" (\"%s\") is of an unknown file type - skipping!", - name, filename); + "add_banner: Banner \"%s\" (\"%s\") is of an unknown file " + "type - skipping!", name, filename); return; } @@ -156,13 +156,27 @@ add_banner(const char *name, /* I - Name of banner */ * Allocate memory... */ - temp = calloc(1, sizeof(cupsd_banner_t)); + if ((temp = calloc(1, sizeof(cupsd_banner_t))) == NULL) + { + cupsdLogMessage(CUPSD_LOG_WARN, + "add_banner: Unable to allocate memory for banner \"%s\" - " + "skipping!", name); + return; + } /* * Copy the new banner data over... */ - temp->name = strdup(name); + if ((temp->name = strdup(name)) == NULL) + { + cupsdLogMessage(CUPSD_LOG_WARN, + "add_banner: Unable to allocate memory for banner \"%s\" - " + "skipping!", name); + free(temp); + return; + } + temp->filetype = filetype; cupsArrayAdd(Banners, temp); diff --git a/scheduler/classes.c b/scheduler/classes.c index 192c4d01d..81d7c0b61 100644 --- a/scheduler/classes.c +++ b/scheduler/classes.c @@ -393,7 +393,7 @@ cupsdLoadAllClasses(void) { cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of classes.conf.", linenum); - return; + break; } } else if (!strcasecmp(line, "</Class>")) @@ -407,14 +407,14 @@ cupsdLoadAllClasses(void) { cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of classes.conf.", linenum); - return; + break; } } else if (!p) { cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of classes.conf.", linenum); - return; + break; } else if (!strcasecmp(line, "AuthInfoRequired")) { @@ -458,7 +458,7 @@ cupsdLoadAllClasses(void) { cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of classes.conf.", linenum); - return; + break; } else if ((temp = cupsdFindPrinter(value)) == NULL) { @@ -504,7 +504,7 @@ cupsdLoadAllClasses(void) cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of classes.conf.", linenum); - return; + break; } } else if (!strcasecmp(line, "StateMessage")) @@ -546,7 +546,7 @@ cupsdLoadAllClasses(void) cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of classes.conf.", linenum); - return; + break; } } else if (!strcasecmp(line, "Shared")) @@ -568,9 +568,9 @@ cupsdLoadAllClasses(void) else { cupsdLogMessage(CUPSD_LOG_ERROR, - "Syntax error on line %d of printers.conf.", + "Syntax error on line %d of classes.conf.", linenum); - return; + break; } } else if (!strcasecmp(line, "JobSheets")) @@ -609,7 +609,7 @@ cupsdLoadAllClasses(void) { cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of classes.conf.", linenum); - return; + break; } } else if (!strcasecmp(line, "AllowUser")) @@ -623,7 +623,7 @@ cupsdLoadAllClasses(void) { cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of classes.conf.", linenum); - return; + break; } } else if (!strcasecmp(line, "DenyUser")) @@ -637,7 +637,7 @@ cupsdLoadAllClasses(void) { cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of classes.conf.", linenum); - return; + break; } } else if (!strcasecmp(line, "QuotaPeriod")) @@ -648,7 +648,7 @@ cupsdLoadAllClasses(void) { cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of classes.conf.", linenum); - return; + break; } } else if (!strcasecmp(line, "PageLimit")) @@ -659,7 +659,7 @@ cupsdLoadAllClasses(void) { cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of classes.conf.", linenum); - return; + break; } } else if (!strcasecmp(line, "KLimit")) @@ -670,7 +670,7 @@ cupsdLoadAllClasses(void) { cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of classes.conf.", linenum); - return; + break; } } else if (!strcasecmp(line, "OpPolicy")) @@ -694,7 +694,7 @@ cupsdLoadAllClasses(void) { cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of classes.conf.", linenum); - return; + break; } } else if (!strcasecmp(line, "ErrorPolicy")) @@ -705,7 +705,7 @@ cupsdLoadAllClasses(void) { cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of classes.conf.", linenum); - return; + break; } } else diff --git a/scheduler/client.c b/scheduler/client.c index 5de5f1fc0..38e1c76f7 100644 --- a/scheduler/client.c +++ b/scheduler/client.c @@ -3,7 +3,7 @@ * * Client routines for the Common UNIX Printing System (CUPS) scheduler. * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * This file contains Kerberos support code, copyright 2006 by @@ -144,9 +144,19 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */ Clients = cupsArrayNew(NULL, NULL); if (!Clients) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "Unable to allocate memory for client array!"); + cupsdPauseListening(); return; + } - con = calloc(1, sizeof(cupsd_client_t)); + if ((con = calloc(1, sizeof(cupsd_client_t))) == NULL) + { + cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to allocate memory for client!"); + cupsdPauseListening(); + return; + } con->http.activity = time(NULL); con->file = -1; diff --git a/scheduler/conf.c b/scheduler/conf.c index 753081ed8..9aa003ad6 100644 --- a/scheduler/conf.c +++ b/scheduler/conf.c @@ -3,7 +3,7 @@ * * Configuration routines for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -1126,19 +1126,27 @@ cupsdReadConfiguration(void) if (!mimeType(MimeDatabase, "application", "octet-stream")) NumMimeTypes ++; - MimeTypes = calloc(NumMimeTypes, sizeof(const char *)); - - for (i = 0, type = mimeFirstType(MimeDatabase); - type; - i ++, type = mimeNextType(MimeDatabase)) + if ((MimeTypes = calloc(NumMimeTypes, sizeof(const char *))) == NULL) { - snprintf(mimetype, sizeof(mimetype), "%s/%s", type->super, type->type); - - MimeTypes[i] = _cupsStrAlloc(mimetype); + cupsdLogMessage(CUPSD_LOG_ERROR, + "Unable to allocate memory for %d MIME types!", + NumMimeTypes); + NumMimeTypes = 0; } + else + { + for (i = 0, type = mimeFirstType(MimeDatabase); + type; + i ++, type = mimeNextType(MimeDatabase)) + { + snprintf(mimetype, sizeof(mimetype), "%s/%s", type->super, type->type); + + MimeTypes[i] = _cupsStrAlloc(mimetype); + } - if (i < NumMimeTypes) - MimeTypes[i] = _cupsStrAlloc("application/octet-stream"); + if (i < NumMimeTypes) + MimeTypes[i] = _cupsStrAlloc("application/octet-stream"); + } if (LogLevel == CUPSD_LOG_DEBUG2) { @@ -2570,8 +2578,16 @@ read_configuration(cups_file_t *fp) /* I - File to read from */ if ((ptr = strchr(temp, ' ')) != NULL) *ptr = '\0'; - relay->from.type = AUTH_NAME; - relay->from.mask.name.name = strdup(temp); + relay->from.type = AUTH_NAME; + + if ((relay->from.mask.name.name = strdup(temp)) == NULL) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "Unable to allocate BrowseRelay name at line %d - %s.", + linenum, strerror(errno)); + continue; + } + relay->from.mask.name.length = strlen(temp); } else diff --git a/scheduler/cups-deviced.c b/scheduler/cups-deviced.c index 3cacab3ab..385037ea2 100644 --- a/scheduler/cups-deviced.c +++ b/scheduler/cups-deviced.c @@ -3,7 +3,7 @@ * * Device scanning mini-daemon for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1997-2006 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -291,6 +291,8 @@ main(int argc, /* I - Number of command-line args */ if (!dev) { cupsDirClose(dir); + fclose(fp); + kill(pid, SIGTERM); return (1); } diff --git a/scheduler/cups-driverd.c b/scheduler/cups-driverd.c index 5f242447a..4f29c03d5 100644 --- a/scheduler/cups-driverd.c +++ b/scheduler/cups-driverd.c @@ -7,7 +7,7 @@ * in CUPS_DATADIR/model and dynamically generated PPD files using * the driver helper programs in CUPS_SERVERBIN/driver. * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1997-2007 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -1664,6 +1664,7 @@ load_drivers(void) if (!ppd) { cupsDirClose(dir); + pclose(fp); return (0); } diff --git a/scheduler/cups-lpd.c b/scheduler/cups-lpd.c index 360ceb659..7e810f4ca 100644 --- a/scheduler/cups-lpd.c +++ b/scheduler/cups-lpd.c @@ -3,7 +3,7 @@ * * Line Printer Daemon interface for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1997-2006 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -1274,9 +1274,9 @@ recv_print_job( if (status) break; } - - fclose(fp); } + + fclose(fp); } } diff --git a/scheduler/cupsfilter.c b/scheduler/cupsfilter.c index 4085be18f..abe1092d5 100644 --- a/scheduler/cupsfilter.c +++ b/scheduler/cupsfilter.c @@ -3,7 +3,7 @@ * * CUPS filtering program for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1997-2006 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -138,6 +138,7 @@ main(int argc, /* I - Number of command-line args */ mime = NULL; srctype = NULL; + compression = 0; dsttype = "application/pdf"; infile = NULL; outfile = NULL; @@ -480,7 +481,8 @@ escape_options( for (i = num_options, option = options, bytes = 1; i > 0; i --, option ++) bytes += 2 * (strlen(option->name) + strlen(option->value)) + 2; - s = malloc(bytes); + if ((s = malloc(bytes)) == NULL) + return (NULL); /* * Copy the options to the string... @@ -830,6 +832,8 @@ exec_filters(cups_array_t *filters, /* I - Array of filters to run */ } } + cupsArrayDelete(pids); + return (retval); } diff --git a/scheduler/dirsvc.c b/scheduler/dirsvc.c index ae0ddcb81..a1d8fe1c9 100644 --- a/scheduler/dirsvc.c +++ b/scheduler/dirsvc.c @@ -332,7 +332,7 @@ cupsdLoadRemoteCache(void) { cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of remote.cache.", linenum); - return; + break; } } else if (!strcasecmp(line, "<Class") || @@ -373,7 +373,7 @@ cupsdLoadRemoteCache(void) { cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of remote.cache.", linenum); - return; + break; } } else if (!strcasecmp(line, "</Printer>") || @@ -393,14 +393,14 @@ cupsdLoadRemoteCache(void) { cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of remote.cache.", linenum); - return; + break; } } else if (!p) { cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of remote.cache.", linenum); - return; + break; } else if (!strcasecmp(line, "Info")) { @@ -433,7 +433,7 @@ cupsdLoadRemoteCache(void) { cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of remote.cache.", linenum); - return; + break; } } else if (!strcasecmp(line, "Option") && value) @@ -469,7 +469,7 @@ cupsdLoadRemoteCache(void) { cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of remote.cache.", linenum); - return; + break; } } else if (!strcasecmp(line, "StateMessage")) @@ -501,7 +501,7 @@ cupsdLoadRemoteCache(void) { cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of remote.cache.", linenum); - return; + break; } } else if (!strcasecmp(line, "Type")) @@ -512,7 +512,7 @@ cupsdLoadRemoteCache(void) { cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of remote.cache.", linenum); - return; + break; } } else if (!strcasecmp(line, "BrowseTime")) @@ -528,7 +528,7 @@ cupsdLoadRemoteCache(void) { cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of remote.cache.", linenum); - return; + break; } } else if (!strcasecmp(line, "JobSheets")) @@ -563,7 +563,7 @@ cupsdLoadRemoteCache(void) { cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of remote.cache.", linenum); - return; + break; } } else if (!strcasecmp(line, "AllowUser")) @@ -577,7 +577,7 @@ cupsdLoadRemoteCache(void) { cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of remote.cache.", linenum); - return; + break; } } else if (!strcasecmp(line, "DenyUser")) @@ -591,7 +591,7 @@ cupsdLoadRemoteCache(void) { cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of remote.cache.", linenum); - return; + break; } } else diff --git a/scheduler/ipp.c b/scheduler/ipp.c index 976779dd8..7b2a77fef 100644 --- a/scheduler/ipp.c +++ b/scheduler/ipp.c @@ -3,7 +3,7 @@ * * IPP routines for the Common UNIX Printing System (CUPS) scheduler. * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * This file contains Kerberos support code, copyright 2006 by @@ -752,7 +752,7 @@ cupsdProcessIPPRequest( * 'cupsdTimeoutJob()' - Timeout a job waiting on job files. */ -void +int /* O - 0 on success, -1 on error */ cupsdTimeoutJob(cupsd_job_t *job) /* I - Job to timeout */ { cupsd_printer_t *printer; /* Destination printer or class */ @@ -780,10 +780,13 @@ cupsdTimeoutJob(cupsd_job_t *job) /* I - Job to timeout */ cupsdLogMessage(CUPSD_LOG_INFO, "[Job %d] Adding end banner page \"%s\".", job->id, attr->values[1].string.text); - kbytes = copy_banner(NULL, job, attr->values[1].string.text); + if ((kbytes = copy_banner(NULL, job, attr->values[1].string.text)) < 0) + return (-1); cupsdUpdateQuota(printer, job->username, 0, kbytes); } + + return (0); } @@ -1792,7 +1795,8 @@ add_job(cupsd_client_t *con, /* I - Client connection */ "[Job %d] Adding start banner page \"%s\".", job->id, attr->values[0].string.text); - kbytes = copy_banner(con, job, attr->values[0].string.text); + if ((kbytes = copy_banner(con, job, attr->values[0].string.text)) < 0) + return (NULL); cupsdUpdateQuota(printer, job->username, 0, kbytes); } @@ -3432,13 +3436,6 @@ check_quotas(cupsd_client_t *con, /* I - Client connection */ con, con->http.fd, p, p->name); /* - * Check input... - */ - - if (!con || !p) - return (0); - - /* * Figure out who is printing... */ @@ -3944,7 +3941,7 @@ copy_banner(cupsd_client_t *con, /* I - Client connection */ */ if (add_file(con, job, banner->filetype, 0)) - return (0); + return (-1); snprintf(filename, sizeof(filename), "%s/d%05d-%03d", RequestRoot, job->id, job->num_files); @@ -7712,7 +7709,8 @@ print_job(cupsd_client_t *con, /* I - Client connection */ * See if we need to add the ending sheet... */ - cupsdTimeoutJob(job); + if (cupsdTimeoutJob(job)) + return; /* * Log and save the job... @@ -8916,7 +8914,8 @@ send_document(cupsd_client_t *con, /* I - Client connection */ * See if we need to add the ending sheet... */ - cupsdTimeoutJob(job); + if (cupsdTimeoutJob(job)) + return; if (job->state_value == IPP_JOB_STOPPED) { @@ -10150,8 +10149,8 @@ validate_user(cupsd_job_t *job, /* I - Job */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "validate_user(job=%d, con=%d, owner=\"%s\", username=%p, " "userlen=%d)", - job ? job->id : 0, con->http.fd, owner ? owner : "(null)", - username, userlen); + job->id, con ? con->http.fd : 0, + owner ? owner : "(null)", username, userlen); /* * Validate input... diff --git a/scheduler/job.c b/scheduler/job.c index 458d6bd03..459a17b4c 100644 --- a/scheduler/job.c +++ b/scheduler/job.c @@ -3,7 +3,7 @@ * * Job management routines for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -113,7 +113,8 @@ cupsdAddJob(int priority, /* I - Job priority */ cupsd_job_t *job; /* New job record */ - job = calloc(sizeof(cupsd_job_t), 1); + if ((job = calloc(sizeof(cupsd_job_t), 1)) == NULL) + return (NULL); job->id = NextJobId ++; job->priority = priority; @@ -376,7 +377,11 @@ cupsdCheckJobs(void) job->hold_until < time(NULL)) { if (job->pending_timeout) - cupsdTimeoutJob(job); /* Add trailing banner as needed */ + { + /* Add trailing banner as needed */ + if (cupsdTimeoutJob(job)) + continue; + } job->state->values[0].integer = IPP_JOB_PENDING; job->state_value = IPP_JOB_PENDING; @@ -2971,6 +2976,17 @@ start_job(cupsd_job_t *job, /* I - Job ID */ else argv = calloc(8, sizeof(char *)); + if (!argv) + { + cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to allocate argument array!"); + cupsArrayDelete(filters); + + FilterLevel -= job->cost; + + cupsdStopPrinter(printer, 0); + return; + } + sprintf(jobid, "%d", job->id); argv[0] = printer->name; @@ -3557,7 +3573,7 @@ update_job(cupsd_job_t *job) /* I - Job to check */ * job sheet count... */ - if (job->sheets != NULL) + if (job->sheets) { if (!strncasecmp(message, "total ", 6)) { @@ -3602,8 +3618,9 @@ update_job(cupsd_job_t *job) /* I - Job to check */ cupsdLogPage(job, message); - cupsdAddEvent(CUPSD_EVENT_JOB_PROGRESS, job->printer, job, - "Printed %d page(s).", job->sheets->values[0].integer); + if (job->sheets) + cupsdAddEvent(CUPSD_EVENT_JOB_PROGRESS, job->printer, job, + "Printed %d page(s).", job->sheets->values[0].integer); } else if (loglevel == CUPSD_LOG_STATE) { diff --git a/scheduler/job.h b/scheduler/job.h index 704690583..78c836b75 100644 --- a/scheduler/job.h +++ b/scheduler/job.h @@ -3,7 +3,7 @@ * * Print job definitions for the Common UNIX Printing System (CUPS) scheduler. * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -123,7 +123,7 @@ extern void cupsdSetJobHoldUntil(cupsd_job_t *job, const char *when); extern void cupsdSetJobPriority(cupsd_job_t *job, int priority); extern void cupsdStopAllJobs(int force); extern void cupsdStopJob(cupsd_job_t *job, int force); -extern void cupsdTimeoutJob(cupsd_job_t *job); +extern int cupsdTimeoutJob(cupsd_job_t *job); extern void cupsdUnloadCompletedJobs(void); diff --git a/scheduler/log.c b/scheduler/log.c index dbe08e750..bc113c634 100644 --- a/scheduler/log.c +++ b/scheduler/log.c @@ -3,7 +3,7 @@ * * Log file routines for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -274,6 +274,9 @@ cupsdLogMessage(int level, /* I - Log level */ if (len >= linesize) { + char *temp; /* Temporary string pointer */ + + len ++; if (len < 8192) @@ -281,18 +284,12 @@ cupsdLogMessage(int level, /* I - Log level */ else if (len > 65536) len = 65536; - line = realloc(line, len); + temp = realloc(line, len); - if (line) - linesize = len; - else + if (temp) { - cupsFilePrintf(ErrorFile, - "ERROR: Unable to allocate memory for line - %s\n", - strerror(errno)); - cupsFileFlush(ErrorFile); - - return (0); + line = temp; + linesize = len; } va_start(ap, message); diff --git a/scheduler/main.c b/scheduler/main.c index 5d51538b2..8aeb5e90d 100644 --- a/scheduler/main.c +++ b/scheduler/main.c @@ -3,7 +3,7 @@ * * Scheduler main loop for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -228,11 +228,22 @@ main(int argc, /* I - Number of command-line args */ * are passed a NULL pointer. */ - current = malloc(1024); - getcwd(current, 1024); + if ((current = malloc(1024)) == NULL) + { + _cupsLangPuts(stderr, + _("cupsd: Unable to get current directory!\n")); + return (1); + } + + if (!getcwd(current, 1024)) + { + _cupsLangPuts(stderr, + _("cupsd: Unable to get current directory!\n")); + free(current); + return (1); + } cupsdSetStringf(&ConfigurationFile, "%s/%s", current, argv[i]); - free(current); } break; diff --git a/scheduler/mime.c b/scheduler/mime.c index 6edaa4a66..cee81209e 100644 --- a/scheduler/mime.c +++ b/scheduler/mime.c @@ -3,7 +3,7 @@ * * MIME database file routines for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1997-2006 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -235,7 +235,10 @@ mimeMerge(mime_t *mime, /* I - MIME database to add to */ if (!mime) mime = mimeNew(); if (!mime) + { + cupsDirClose(dir); return (NULL); + } /* * Read all the .types files... diff --git a/scheduler/printers.c b/scheduler/printers.c index 03498bbc6..61b6f6ef9 100644 --- a/scheduler/printers.c +++ b/scheduler/printers.c @@ -3,7 +3,7 @@ * * Printer routines for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -909,7 +909,7 @@ cupsdLoadAllPrinters(void) { cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of printers.conf.", linenum); - return; + break; } } else if (!strcasecmp(line, "</Printer>")) @@ -954,14 +954,14 @@ cupsdLoadAllPrinters(void) { cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of printers.conf.", linenum); - return; + break; } } else if (!p) { cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of printers.conf.", linenum); - return; + break; } else if (!strcasecmp(line, "AuthInfoRequired")) { @@ -988,7 +988,7 @@ cupsdLoadAllPrinters(void) { cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of printers.conf.", linenum); - return; + break; } } else if (!strcasecmp(line, "Option") && value) @@ -1020,7 +1020,7 @@ cupsdLoadAllPrinters(void) { cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of printers.conf.", linenum); - return; + break; } } else if (!strcasecmp(line, "State")) @@ -1037,7 +1037,7 @@ cupsdLoadAllPrinters(void) { cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of printers.conf.", linenum); - return; + break; } } else if (!strcasecmp(line, "StateMessage")) @@ -1078,7 +1078,7 @@ cupsdLoadAllPrinters(void) { cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of printers.conf.", linenum); - return; + break; } } else if (!strcasecmp(line, "Shared")) @@ -1101,7 +1101,7 @@ cupsdLoadAllPrinters(void) { cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of printers.conf.", linenum); - return; + break; } } else if (!strcasecmp(line, "JobSheets")) @@ -1136,7 +1136,7 @@ cupsdLoadAllPrinters(void) { cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of printers.conf.", linenum); - return; + break; } } else if (!strcasecmp(line, "AllowUser")) @@ -1150,7 +1150,7 @@ cupsdLoadAllPrinters(void) { cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of printers.conf.", linenum); - return; + break; } } else if (!strcasecmp(line, "DenyUser")) @@ -1164,7 +1164,7 @@ cupsdLoadAllPrinters(void) { cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of printers.conf.", linenum); - return; + break; } } else if (!strcasecmp(line, "QuotaPeriod")) @@ -1175,7 +1175,7 @@ cupsdLoadAllPrinters(void) { cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of printers.conf.", linenum); - return; + break; } } else if (!strcasecmp(line, "PageLimit")) @@ -1186,7 +1186,7 @@ cupsdLoadAllPrinters(void) { cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of printers.conf.", linenum); - return; + break; } } else if (!strcasecmp(line, "KLimit")) @@ -1197,7 +1197,7 @@ cupsdLoadAllPrinters(void) { cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of printers.conf.", linenum); - return; + break; } } else if (!strcasecmp(line, "OpPolicy")) @@ -1221,7 +1221,7 @@ cupsdLoadAllPrinters(void) { cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of printers.conf.", linenum); - return; + break; } } else if (!strcasecmp(line, "ErrorPolicy")) @@ -1232,7 +1232,7 @@ cupsdLoadAllPrinters(void) { cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of printers.conf.", linenum); - return; + break; } } else diff --git a/scheduler/subscriptions.c b/scheduler/subscriptions.c index 1c9c06770..96a6d13c5 100644 --- a/scheduler/subscriptions.c +++ b/scheduler/subscriptions.c @@ -3,7 +3,7 @@ * * Subscription routines for the Common UNIX Printing System (CUPS) scheduler. * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -731,7 +731,7 @@ cupsdLoadAllSubscriptions(void) cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of subscriptions.conf.", linenum); - return; + break; } } else if (!strcasecmp(line, "</Subscription>")) @@ -741,7 +741,7 @@ cupsdLoadAllSubscriptions(void) cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of subscriptions.conf.", linenum); - return; + break; } if (delete_sub) @@ -755,7 +755,7 @@ cupsdLoadAllSubscriptions(void) cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of subscriptions.conf.", linenum); - return; + break; } else if (!strcasecmp(line, "Events")) { @@ -769,7 +769,7 @@ cupsdLoadAllSubscriptions(void) cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of subscriptions.conf.", linenum); - return; + break; } while (*value) @@ -792,7 +792,7 @@ cupsdLoadAllSubscriptions(void) cupsdLogMessage(CUPSD_LOG_ERROR, "Unknown event name \'%s\' on line %d of subscriptions.conf.", value, linenum); - return; + break; } value = valueptr; @@ -811,7 +811,7 @@ cupsdLoadAllSubscriptions(void) cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of subscriptions.conf.", linenum); - return; + break; } } else if (!strcasecmp(line, "Recipient")) @@ -827,7 +827,7 @@ cupsdLoadAllSubscriptions(void) cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of subscriptions.conf.", linenum); - return; + break; } } else if (!strcasecmp(line, "JobId")) @@ -851,7 +851,7 @@ cupsdLoadAllSubscriptions(void) cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of subscriptions.conf.", linenum); - return; + break; } } else if (!strcasecmp(line, "PrinterName")) @@ -875,7 +875,7 @@ cupsdLoadAllSubscriptions(void) cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of subscriptions.conf.", linenum); - return; + break; } } else if (!strcasecmp(line, "UserData")) @@ -937,7 +937,7 @@ cupsdLoadAllSubscriptions(void) cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of subscriptions.conf.", linenum); - return; + break; } } else if (!strcasecmp(line, "LeaseDuration")) @@ -956,7 +956,7 @@ cupsdLoadAllSubscriptions(void) cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of subscriptions.conf.", linenum); - return; + break; } } else if (!strcasecmp(line, "Interval")) @@ -972,7 +972,7 @@ cupsdLoadAllSubscriptions(void) cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of subscriptions.conf.", linenum); - return; + break; } } else if (!strcasecmp(line, "ExpirationTime")) @@ -988,7 +988,7 @@ cupsdLoadAllSubscriptions(void) cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of subscriptions.conf.", linenum); - return; + break; } } else if (!strcasecmp(line, "NextEventId")) @@ -1004,7 +1004,7 @@ cupsdLoadAllSubscriptions(void) cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of subscriptions.conf.", linenum); - return; + break; } } else diff --git a/scheduler/testspeed.c b/scheduler/testspeed.c index f58d9e6b5..65a0f9ff0 100644 --- a/scheduler/testspeed.c +++ b/scheduler/testspeed.c @@ -166,7 +166,7 @@ main(int argc, /* I - Number of command-line arguments */ * Exit with no errors... */ - return (status); + return (0); } diff --git a/scheduler/type.c b/scheduler/type.c index 30e98d12d..e56bf02d4 100644 --- a/scheduler/type.c +++ b/scheduler/type.c @@ -567,12 +567,12 @@ mimeFileType(mime_t *mime, /* I - MIME database */ if ((base = strrchr(filename, '/')) != NULL) base ++; else - filename = filename; + base = filename; } else if ((base = strrchr(pathname, '/')) != NULL) base ++; else - filename = pathname; + base = pathname; /* * Then check it against all known types... diff --git a/systemv/accept.c b/systemv/accept.c index 5d816cf0f..e7efddad7 100644 --- a/systemv/accept.c +++ b/systemv/accept.c @@ -4,7 +4,7 @@ * "accept", "disable", "enable", and "reject" commands for the Common * UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1997-2006 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -125,8 +125,11 @@ main(int argc, /* I - Number of command-line arguments */ break; case 'h' : /* Connect to host */ - if (http != NULL) + if (http) + { httpClose(http); + http = NULL; + } if (argv[i][2] != '\0') cupsSetServer(argv[i] + 2); diff --git a/systemv/cupstestppd.c b/systemv/cupstestppd.c index 8e7201f40..0ab40ffe3 100644 --- a/systemv/cupstestppd.c +++ b/systemv/cupstestppd.c @@ -3,7 +3,7 @@ * * PPD test program for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -2010,8 +2010,10 @@ check_translations(ppd_file_t *ppd, /* I - PPD file */ * This file contains localizations, check them... */ - languages = strdup(attr->value); - langlist = cupsArrayNew((cups_array_func_t)strcmp, NULL); + if ((languages = strdup(attr->value)) == NULL) + return (1); + + langlist = cupsArrayNew((cups_array_func_t)strcmp, NULL); for (langptr = languages; *langptr;) { diff --git a/systemv/lpmove.c b/systemv/lpmove.c index 0795737f1..88d2a154a 100644 --- a/systemv/lpmove.c +++ b/systemv/lpmove.c @@ -61,7 +61,6 @@ main(int argc, /* I - Number of command-line arguments */ dest = NULL; dests = NULL; - http = NULL; job = NULL; jobid = 0; num_dests = 0; @@ -75,8 +74,6 @@ main(int argc, /* I - Number of command-line arguments */ #ifdef HAVE_SSL cupsSetEncryption(HTTP_ENCRYPT_REQUIRED); - if (http) - httpEncryption(http, HTTP_ENCRYPT_REQUIRED); #else _cupsLangPrintf(stderr, _("%s: Sorry, no encryption support compiled in!\n"), @@ -85,12 +82,6 @@ main(int argc, /* I - Number of command-line arguments */ break; case 'h' : /* Connect to host */ - if (http) - { - httpClose(http); - http = NULL; - } - if (argv[i][2] != '\0') cupsSetServer(argv[i] + 2); else @@ -142,17 +133,14 @@ main(int argc, /* I - Number of command-line arguments */ return (1); } - if (!http) - { - http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption()); + http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption()); - if (http == NULL) - { - _cupsLangPrintf(stderr, - _("lpmove: Unable to connect to server: %s\n"), - strerror(errno)); - return (1); - } + if (http == NULL) + { + _cupsLangPrintf(stderr, + _("lpmove: Unable to connect to server: %s\n"), + strerror(errno)); + return (1); } return (move_job(http, src, jobid, dest)); diff --git a/test/ipptest.c b/test/ipptest.c index e0030ae55..6bd9923c0 100644 --- a/test/ipptest.c +++ b/test/ipptest.c @@ -3,7 +3,7 @@ * * IPP test command for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1997-2007 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -268,6 +268,7 @@ do_tests(const char *uri, /* I - URI to connect on */ { printf("Unable to connect to %s on port %d - %s\n", server, port, strerror(errno)); + fclose(fp); return (0); } |