diff --git a/CMakeLists.txt b/CMakeLists.txt index c8bf3f0..0a9aea2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required ( VERSION 3.12 ) +cmake_minimum_required ( VERSION 3.0 ) # set default build type to Release (if nothing else provided from outside yet) IF ( NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES ) @@ -9,27 +9,29 @@ ENDIF () project ( rastertozj C ) -#set ( CMAKE_INSTALL_PREFIX "/usr" CACHE FILEPATH "force install to /usr" FORCE ) - function( DIAG VARR ) message ( STATUS "${VARR} -> ${${VARR}}" ) endfunction() -# build the filter binary +# requirements to build the filter binary find_package ( Cups REQUIRED ) find_library ( CUPSIMAGELIB NAMES cupsimage ) mark_as_advanced ( CUPSIMAGELIB ) -set ( DEBUGFILE "/tmp/debugraster.txt" CACHE STRING "File where to make debug output if DEBUGP is set" ) -option ( DEBUGP "Whetner to output debug info" ON ) - add_executable ( rastertozj rastertozj.c ) target_compile_options ( rastertozj PRIVATE -Wall -fPIC ) target_include_directories ( rastertozj PRIVATE ${CUPS_INCLUDE_DIR} ) target_link_libraries ( rastertozj PRIVATE ${CUPS_LIBRARIES} ${CUPSIMAGELIB} ) -if ( DEBUGP ) - target_compile_definitions ( rastertozj PRIVATE DEBUGP DEBUGFILE="${DEBUGFILE}") +if ( CMAKE_BUILD_TYPE STREQUAL "Debug" ) + target_compile_definitions ( rastertozj PRIVATE DEBUGP ) + if ( APPLE ) + target_compile_definitions ( rastertozj PRIVATE SAFEDEBUG ) + message ( STATUS "On Mac OSX log is saved in sandbox, as /private/var/spool/cups/tmp" ) + elseif ( UNIX ) + set ( DEBUGFILE "/tmp/debugraster.txt" CACHE STRING "File where to make debug output if we build ad Debug" ) + target_compile_definitions ( rastertozj PRIVATE DEBUGFILE="${DEBUGFILE}" ) + endif () endif () # build ppds @@ -38,37 +40,63 @@ if ( NOT DEFINED PPDC ) endif () mark_as_advanced( PPDC ) +set ( PPDS "" ) if ( PPDC ) - set ( ENV{LANG} c ) - execute_process ( - COMMAND "${PPDC}" -d "${CMAKE_CURRENT_BINARY_DIR}" "zj-58.drv" - WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" - RESULT_VARIABLE res - OUTPUT_VARIABLE _CONTENT - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE ) + set ( DRVSRC "${CMAKE_CURRENT_SOURCE_DIR}/zjdrv.drv") + set ( PPDDIR "${CMAKE_CURRENT_BINARY_DIR}/ppd" ) + list (APPEND PPDS "${PPDDIR}/zj58.ppd" ) + list (APPEND PPDS "${PPDDIR}/xp58.ppd" ) + list (APPEND PPDS "${PPDDIR}/tm20.ppd" ) + list (APPEND PPDS "${PPDDIR}/zj80.ppd" ) + ADD_CUSTOM_COMMAND ( OUTPUT ${PPDS} + COMMAND LANG=c ${PPDC} ${DRVSRC} + MAIN_DEPENDENCY ${DRVSRC} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Building PPDs" + VERBATIM + ) + ADD_CUSTOM_TARGET ( ppds ALL DEPENDS ${PPDS} ) +else() + message (STATUS "No ppdc found; fall back to defaultly shipped ZJ-58.ppd") + list ( APPEND PPDS "${CMAKE_CURRENT_SOURCE_DIR}/zj58.ppd" ) + list ( APPEND PPDS "${CMAKE_CURRENT_SOURCE_DIR}/zj80.ppd" ) endif() # installation stuff -# this one works if you perform 'make install' -set ( CMAKE_INSTALL_PREFIX "/usr" CACHE FILEPATH "this is forced to /usr" FORCE ) - -# this one works if you perform 'make package' - it is kind of root for all packaging +# Set both installation prefixes to / +set ( CMAKE_INSTALL_PREFIX "/" CACHE FILEPATH "this is forced to /" FORCE ) set ( CPACK_PACKAGING_INSTALL_PREFIX "/" ) +set ( CPACK_PACKAGE_CONTACT "Alexey N. Vinogradov (a.n.vinogradov@gmail.com)" ) - -include ( GNUInstallDirs ) +set ( CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON ) +set ( CPACK_DEBIAN_PACKAGE_PREDEPENDS "libcups2-dev, libcupsimage2-dev" ) +set ( CPACK_DEBIAN_PACKAGE_SECTION "libs" ) +set ( CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://github.com/klirichek/zj-58") if ( APPLE ) set ( FILTERPATH "usr/libexec/cups/filter" ) set ( PPDPATH "Library/Printers/PPDs/Contents/Resources") + set ( OWNER "root:wheel") + install ( CODE "EXECUTE_PROCESS(COMMAND sudo launchctl stop org.cups.cupsd)" ) + install ( TARGETS rastertozj DESTINATION ${FILTERPATH} ) + # this line sets correct target permissions, due to CUPS requirements + # However as a side effect you'll need either fakeroot, either sudo to even perform 'make package' because of it. + install ( CODE "EXECUTE_PROCESS(COMMAND chown ${OWNER} \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${FILTERPATH}/rastertozj\")" ) + install ( FILES ${PPDS} DESTINATION "${PPDPATH}" ) + install ( CODE "EXECUTE_PROCESS(COMMAND sudo launchctl start org.cups.cupsd)" ) elseif ( UNIX ) set ( FILTERPATH "usr/lib/cups/filter" ) set ( PPDPATH "usr/share/cups/model/zjiang/" ) + set ( OWNER "root:root") + install ( CODE "EXECUTE_PROCESS(COMMAND /etc/init.d/cups stop)" ) + install ( TARGETS rastertozj DESTINATION ${FILTERPATH} ) + # this line sets correct target permissions, due to CUPS requirements + # However as a side effect you'll need either fakeroot, either sudo to even perform 'make package' because of it. + install ( CODE "EXECUTE_PROCESS(COMMAND chown ${OWNER} \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${FILTERPATH}/rastertozj\")" ) + install ( FILES ${PPDS} DESTINATION "${PPDPATH}" ) + install ( CODE "EXECUTE_PROCESS(COMMAND /etc/init.d/cups start)" ) endif() -install ( TARGETS rastertozj DESTINATION ${FILTERPATH} ) -install ( FILES ${CMAKE_CURRENT_BINARY_DIR}/zj58.ppd DESTINATION "${PPDPATH}" ) include (CPack) diff --git a/Makefile b/Makefile deleted file mode 100644 index 2098bea..0000000 --- a/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -CC=gcc -RM=rm -f -CFLAGS=-Wl,-rpath,/usr/lib -Wall -fPIC -O3 -LDFLAGS= -LDLIBS=-lcupsimage -lcups - -SRCS=rastertozj.c -OBJS=$(subst .c,.o,$(SRCS)) - -all: rastertozj - -rastertozj: $(OBJS) - gcc $(LDFLAGS) -o rastertozj rastertozj.o $(LDLIBS) - -rastertozj.o: rastertozj.c - gcc $(CFLAGS) -c rastertozj.c - diff --git a/README.md b/README.md index 94ff3aa..cba386d 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,53 @@ -zj-58 +CUPS driver for thermal receipt printers (was: zj-58) +===================================================== + +CUPS filter for thermal receipt printers for rolls 58 and 80mm. + +Originally it was filter for Zijiang zj-58 with specific PPD, +but later it is revealed that it actually works with many other cheap 58mm printers, like +Xprinter XP-58, etc. Also support for 80mm printers added. + +Printing is performed from cups-raster using ESC/POS sequence 'GS v 0 '. +Empty (zero) lines feeded as 'feed' command (to avoid send empty raster). + +Also 2 Cash Drawers supported, with tunable impulse length for 'on' and 'off.' + +Build ===== -CUPS filter for thermal printer Zjiang ZJ-58 +You need toolchain, CMake and cups-devel. + +It may be achieved, say (as example) by running +``` +sudo apt install build-essential cmake libcups2-dev libcupsimage2-dev +``` + +After it the filter could be built by the sequence of commands: + +``` + mkdir build && cd build && cmake .. + make +``` + + +Installation +============ + +Need administrative rights! + +``` + sudo make install +``` + +'Sudo' is necessary to stop/restart cups service before operation, and also to place files with necessary rights. + + +Debian packaging +================ -The linux driver provided on Zjiang site unfortunately doesn't work. -First, it is 32-bit binary (and so, on x64 system need some x86 libs to be installed). -Second, it's PPD is not correct - it just doesn't show any advanced settings because of it. -Finally, raster filter just crashes on any try to run it! -But even if you run it, you'll see that it's working with printer is not optimal: for example, if it sees a blank line, it will send the blank raster to print (instead of just use 'feeding' command, which is definitely faster!) +For simplicity done with the same script as installation, so also need adminstrative rights. +``` + sudo cpack -G DEB +``` -This is the solution: -PPD is fixed and works. -Filter is provided as src (you can found a list of packages need to be installed in order to build it in the header of source). -Also, printing of blank lines is optimized. +That will stop/start cups as a side effect, however that is not critical. \ No newline at end of file diff --git a/ZJ-58.ppd b/ZJ-58.ppd deleted file mode 100644 index 5c77cc5..0000000 --- a/ZJ-58.ppd +++ /dev/null @@ -1,117 +0,0 @@ -*PPD-Adobe: "4.3" -*FormatVersion: "4.3" -*FileVersion: "1.2" -*LanguageVersion: English -*LanguageEncoding: ISOLatin1 -*PCFileName: "zj58.ppd" -*Manufacturer: "Zijiang" -*Product: "(zj-58)" -*1284DeviceID: "MFG:Zijiang;CMD:Zijiang;MDL:ZJ-58;CLS:PRINTER;" -*cupsVersion: 1.1 -*cupsManualCopies: True -*cupsModelNumber: 58 -*cupsFilter: "application/vnd.cups-raster 0 rastertozj" -*ModelName: "ZJ-58" -*ShortNickName: "ZJ-58" -*NickName: "Zijiang ZJ-58" -*PSVersion: "(3010.000) 550" -*LanguageLevel: "3" -*ColorDevice: False -*DefaultColorSpace: Gray -*FileSystem: False -*Throughput: "1" -*LandscapeOrientation: Plus90 -*VariablePaperSize: True -*TTRasterizer: Type42 - -*OpenUI *PageSize/Media Size: PickOne -*OrderDependency: 10 AnySetup *PageSize -*DefaultPageSize: X48MMY105MM - -*PageSize X48MMY105MM/58mm x 105mm: "<>setpagedevice" -*PageSize X48MMY210MM/58mm x 210mm: "<>setpagedevice" -*PageSize X48MMY297MM/58mm x 297mm: "<>setpagedevice" -*PageSize X48MMY3276MM/58mm x 3276mm: "<>setpagedevice" - -*CloseUI: *PageSize - -*OpenUI *PageRegion: PickOne -*OrderDependency: 10 AnySetup *PageRegion -*DefaultPageRegion: X48mmY105mm - -*PageRegion X48MMY105MM/58mm x 105mm: "<>setpagedevice" -*PageRegion X48MMY210MM/58mm x 210mm: "<>setpagedevice" -*PageRegion X48MMY297MM/58mm x 297mm: "<>setpagedevice" -*PageRegion X48MMY3276MM/58mm x 3276mm: "<>setpagedevice" - -*DefaultImageableArea: X48MMY105MM - -*ImageableArea X48MMY105MM: "0 0 136 298" -*ImageableArea X48MMY210MM: "0 0 136 595" -*ImageableArea X48MMY297MM: "0 0 136 842" -*ImageableArea X48MMY3276MM: "0 0 136 9286" - -*DefaultPaperDimension: X48MMY105MM - -*PaperDimension X48MMY105MM: "136 298" -*PaperDimension X48MMY210MM: "136 595" -*PaperDimension X48MMY297MM: "136 842" -*PaperDimension X48MMY3276MM: "136 9286" - -*MaxMediaWidth: "136" -*MaxMediaHeight: "9286" -*HWMargins: 0 0 0 0 -*CustomPageSize True: "pop pop pop <>setpagedevice" -*ParamCustomPageSize Width: 1 points 48 136 -*ParamCustomPageSize Height: 2 points 48 9282 -*ParamCustomPageSize WidthOffset: 3 points 0 0 -*ParamCustomPageSize HeightOffset: 4 points 0 0 -*ParamCustomPageSize Orientation: 5 int 0 0 - -*OpenGroup: CutGroup/Cut Options -*OpenUI *FeedDist/Feed distance after print: PickOne -*DefaultFeedDist: 2feed9mm -*FeedDist 0feed3mm/feed 3mm: "" -*FeedDist 1feed6mm/feed 6mm: "" -*FeedDist 2feed9mm/feed 9mm: "" -*FeedDist 3feed12mm/feed 12mm: "" -*FeedDist 4feed15mm/feed 15mm: "" -*FeedDist 5feed18mm/feed 18mm: "" -*FeedDist 6feed21mm/feed 21mm: "" -*FeedDist 7feed24mm/feed 24mm: "" -*FeedDist 8feed27mm/feed 27mm: "" -*FeedDist 9feed30mm/feed 30mm: "" -*FeedDist 10feed33mm/feed 33mm: "" -*FeedDist 11feed36mm/feed 36mm: "" -*FeedDist 12feed39mm/feed 39mm: "" -*FeedDist 13feed42mm/feed 42mm: "" -*FeedDist 14feed45mm/feed 45mm: "" -*CloseUI: *FeedDist - - -*OpenUI *BlankSpace/Blank space at page's end: PickOne -*DefaultBlankSpace: 1NoPrint -*BlankSpace 0Print/Print: "" -*BlankSpace 1NoPrint/Do not print: "" -*CloseUI: *BlankSpace - -*CloseGroup: *CutGroup - -*OpenGroup: *CashDrawerGroup/Cash Drawer Control -*OpenUI *CashDrawer1Setting/Cash Drawer 1: PickOne -*DefaultCashDrawer1Setting: 0NotCashDrawer1 -*CashDrawer1Setting 0NotCashDrawer1/Not Cash Drawer 1: "" -*CashDrawer1Setting 1NotCashDrawer1BeforePrinting/Cash Drawer 1 Before Printing: "" -*CashDrawer1Setting 2NotCashDrawer1BeforePrinting/Cash Drawer 1 After Printing: "" -*CloseUI: *CashDrawer1Setting - -*OpenUI *CashDrawer2Setting/Cash Drawer 2: PickOne -*DefaultCashDrawer2Setting: 0NotCashDrawer2 -*CashDrawer2Setting 0NotCashDrawer2/Not Cash Drawer 2: "" -*CashDrawer2Setting 1NotCashDrawer2BeforePrinting/Cash Drawer 2 Before Printing: "" -*CashDrawer2Setting 2NotCashDrawer2BeforePrinting/Cash Drawer 2 After Printing: "" -*CloseUI: *CashDrawer2Setting -*CloseGroup: *CashDrawerGroup - - -*% End diff --git a/install b/install index 45e0e08..96576c2 100755 --- a/install +++ b/install @@ -3,6 +3,9 @@ # Installs zj-58 driver # Tested as working under Ubuntu 14.04 +# Deprecated. Don't use this script; +# use build with cmake and then 'make install' instead + /etc/init.d/cups stop cp rastertozj /usr/lib/cups/filter/ mkdir -p /usr/share/cups/model/zjiang diff --git a/rastertozj.c b/rastertozj.c index 7c4f288..2b9bbbe 100644 --- a/rastertozj.c +++ b/rastertozj.c @@ -11,56 +11,85 @@ #define DEBUGFILE "/tmp/debugraster.txt" #endif +static inline int min(int a, int b) { + if (a > b) + return b; + return a; +} + +// settings and their stuff struct settings_ { - int cashDrawer1; - int cashDrawer2; - int blankSpace; - int feedDist; + int modelNum; // the only setting we get from PPD. + unsigned CashDrawer1; + unsigned CashDrawer2; + unsigned CashDrawer1On; + unsigned CashDrawer1Off; + unsigned CashDrawer2On; + unsigned CashDrawer2Off; + cups_bool_t InsertSheet; + cups_adv_t AdvanceMedia; + cups_cut_t CutMedia; + unsigned int AdvanceDistance; }; struct settings_ settings; -struct command { - int length; - char *command; -}; - -/* - * zj uses kind of epson ESC/P dialect code. Here is subset of commands - * - * initialize - esc @ - * cash drawer 1 - esc p 0 @ P - * cash drawer 2 - esc p 1 @ P - * start raster - esc v 0 - * skip lines - esc j - * cut - esc i - */ -// define printer initialize command -static const struct command printerInitializeCommand = {2, - (char[2]){0x1b, 0x40}}; // esc @ - -// define cashDrawerEjector command -static const struct command cashDrawerEject[2] = { - {5, (char[5]){0x1b, 0x70, 0, 0x40, 0x50}}, // esc p N @ P - {5, (char[5]){0x1b, 0x70, 1, 0x40, 0x50}}}; +static void initializeSettings(char *commandLineOptionSettings, struct settings_ *pSettings) { + ppd_file_t *pPpd = ppdOpenFile(getenv("PPD")); + // char* sDestination = getenv("DestinationPrinterID"); + memset(pSettings, 0, sizeof(struct settings_)); + pSettings->modelNum = pPpd->model_number; + ppdClose(pPpd); +} -// define raster mode start command -static const struct command rasterModeStartCommand = { - 4, (char[4]){0x1d, 0x76, 0x30, 0}}; // esc v 0 +static void update_settings_from_job (cups_page_header2_t * pHeader) +{ + if (!pHeader) + return; + settings.CashDrawer1 = pHeader->cupsInteger[0]; + settings.CashDrawer2 = pHeader->cupsInteger[1]; + settings.CashDrawer1On = pHeader->cupsInteger[2]; + settings.CashDrawer1Off = pHeader->cupsInteger[3]; + settings.CashDrawer2On = pHeader->cupsInteger[4]; + settings.CashDrawer2Off = pHeader->cupsInteger[5]; + settings.InsertSheet = pHeader->cupsInteger[6]; + settings.AdvanceMedia = pHeader->AdvanceMedia; + settings.CutMedia = pHeader->CutMedia; + settings.AdvanceDistance = pHeader->AdvanceDistance; +} #ifndef DEBUGP - static inline void mputchar(char c) { putchar(c); } - +#define DEBUGSTARTPRINT() +#define DEBUGFINISHPRINT() +#define DEBUGPRINT(...) #else - FILE *lfd = 0; -// putchar with debug wrapper +// putchar with debug wrappers static inline void mputchar(char c) { unsigned char m = c; if (lfd) fprintf(lfd, "%02x ", m); putchar(m); } +// on macos cups filters works in a sandbox and cant write +// filtes everywhere. We'll use $TMPDIR/debugraster.txt for them +#ifdef SAFEDEBUG +static inline void DEBUGSTARTPRINT() { + char * tmpfolder = getenv("TMPDIR"); + const char *filename = "/debugraster.txt"; + char *dbgpath = (char *)malloc(strlen(tmpfolder) + strlen(filename) + 1); + strcpy(dbgpath,tmpfolder); + strcat(dbgpath,filename); + lfd = fopen(dbgpath,"w"); + free(dbgpath); +} +#else +#define DEBUGSTARTPRINT() lfd = fopen(DEBUGFILE, "w") +#endif +#define DEBUGFINISHPRINT() \ + if (lfd) \ + fclose(lfd) +#define DEBUGPRINT(...) if (lfd) fprintf(lfd, "\n" __VA_ARGS__) #endif // procedure to output an array @@ -70,91 +99,106 @@ static inline void outputarray(const char *array, int length) { mputchar(array[i]); } -// output a command -static inline void outputCommand(struct command output) { - outputarray(output.command, output.length); -} +// output a command. -1 is because we determine them as string literals, +// so \0 implicitly added at the end, but we don't need it at all +#define SendCommand(COMMAND) outputarray((COMMAND),sizeof((COMMAND))-1) -static inline int lo(int val) { return val & 0xFF; } +static inline void mputnum(unsigned int val) { + mputchar(val&0xFFU); + mputchar((val>>8)&0xFFU); +} -static inline int hi(int val) { return lo(val >> 8); } +/* + * zj uses kind of epson ESC/POS dialect code. Here is subset of commands + * + * initialize - esc @ + * cash drawer 1 - esc p 0 @ P + * cash drawer 2 - esc p 1 @ P // @ =0x40 and P=0x50 and + * where *2ms is pulse on time, *2ms is pulse off. + * start raster - GS v 0 // 0 is full-density, may be also 1, 2, 4 + * skip lines - esc J // then N [0..255], each value 1/44 inches (0.176mm) + * // another commands out-of-spec: + * esc 'i' - cutter; xprinter android example shows as GS V \1 (1D 56 01) + * esc '8' - wait{4, cutter also (char[4]){29,'V','A',20}}; GS V 'A' 20 + */ -// enter raster mode and set up x and y dimensions -static inline void rasterheader(int xsize, int ysize) { - outputCommand(rasterModeStartCommand); - mputchar(lo(xsize)); - mputchar(hi(xsize)); - mputchar(lo(ysize)); - mputchar(hi(ysize)); -} +// define printer initialize command +static const char escInit[] = "\x1b@"; -// print all unprinted (i.e. flush the buffer) -// then feed given number of lines -static inline void skiplines(int size) { - mputchar(0x1b); - mputchar(0x4a); // esc j - mputchar(size); -} +// define cashDrawerEjector command +static const char escCashDrawerEject[] = "\x1bp"; -// get an option -static inline int getOptionChoiceIndex(const char *choiceName, - ppd_file_t *ppd) { - ppd_choice_t *choice; - ppd_option_t *option; +// define raster mode start command +static const char escRasterMode[] = "\x1dv0\0"; - choice = ppdFindMarkedChoice(ppd, choiceName); +// define flush command +static const char escFlush[] = "\x1bJ"; - if (choice == NULL) { - if ((option = ppdFindOption(ppd, choiceName)) == NULL) - return -1; - if ((choice = ppdFindChoice(option, option->defchoice)) == NULL) - return -1; - } +// define cut command +//static const char escCut[] = "\x1bi"; +static const char escCut[] = "\x1dV\1"; - return atoi(choice->choice); +// enter raster mode and set up x and y dimensions +static inline void sendRasterHeader(int xsize, int ysize) { + // outputCommand(rasterModeStartCommand); + SendCommand(escRasterMode); + mputnum(xsize); + mputnum(ysize); } -static void initializeSettings(char *commandLineOptionSettings) { - ppd_file_t *ppd = NULL; - cups_option_t *options = NULL; - int numOptions = 0; - - ppd = ppdOpenFile(getenv("PPD")); +static inline void flushLines(unsigned short lines) +{ + SendCommand(escFlush); + mputchar (lines); +} - ppdMarkDefaults(ppd); +// print all unprinted (i.e. flush the buffer) +static inline void flushBuffer() { + flushLines(0); +} - numOptions = cupsParseOptions(commandLineOptionSettings, 0, &options); - if ((numOptions != 0) && (options != NULL)) { - cupsMarkOptions(ppd, numOptions, options); - cupsFreeOptions(numOptions, options); +// flush, then feed 24 lines +static inline void flushManyLines(int iLines) +{ + DEBUGPRINT("Skip %d empty lines: ", iLines); + while ( iLines ) + { + int iStride = min (iLines, 24); + flushLines ( iStride ); + iLines -= iStride; } +} - memset(&settings, 0x00, sizeof(struct settings_)); - - settings.cashDrawer1 = getOptionChoiceIndex("CashDrawer1Setting", ppd); - settings.cashDrawer2 = getOptionChoiceIndex("CashDrawer2Setting", ppd); - settings.blankSpace = getOptionChoiceIndex("BlankSpace", ppd); - settings.feedDist = getOptionChoiceIndex("FeedDist", ppd); +inline static void CashDrawerEject (unsigned iDrawer, unsigned iOn, + unsigned iOff) +{ + SendCommand(escCashDrawerEject); + mputchar(iDrawer); + mputchar(iOn); + mputchar(iOff); +} - ppdClose(ppd); +inline static void cutMedia() +{ + SendCommand(escCut); } // sent on the beginning of print job -void jobSetup() { - if (settings.cashDrawer1 == 1) - outputCommand(cashDrawerEject[0]); - if (settings.cashDrawer2 == 1) - outputCommand(cashDrawerEject[1]); - outputCommand(printerInitializeCommand); +void setupJob() { + SendCommand(escInit); + if (settings.CashDrawer1 == 1) + CashDrawerEject(0,settings.CashDrawer1On,settings.CashDrawer1Off); + if (settings.CashDrawer2 == 1) + CashDrawerEject(1, settings.CashDrawer2On, settings.CashDrawer2Off); } // sent at the very end of print job -void ShutDown() { - if (settings.cashDrawer1 == 2) - outputCommand(cashDrawerEject[0]); - if (settings.cashDrawer2 == 2) - outputCommand(cashDrawerEject[1]); - outputCommand(printerInitializeCommand); +void finalizeJob() { + if (settings.CashDrawer1 == 2) + CashDrawerEject(0, settings.CashDrawer1On, settings.CashDrawer1Off); + if (settings.CashDrawer2 == 2) + CashDrawerEject(1, settings.CashDrawer2On, settings.CashDrawer2Off); +// SendCommand(escInit); } // sent at the end of every page @@ -163,10 +207,7 @@ typedef void (*__sighandler_t)(int); #endif __sighandler_t old_signal; -void EndPage() { - int i; - for (i = 0; i < settings.feedDist; ++i) - skiplines(0x18); +void finishPage() { signal(15, old_signal); } @@ -175,166 +216,315 @@ void cancelJob() { int i = 0; for (; i < 0x258; ++i) mputchar(0); - EndPage(); - ShutDown(); + finishPage(); } // invoked before starting to print a page -void pageSetup() { old_signal = signal(15, cancelJob); } +void startPage() { old_signal = signal(15, cancelJob); } + +void DebugPrintHeader (cups_page_header2_t* pHeader) +{ + DEBUGPRINT( + "MediaClass '%s'\n" + "MediaColor '%s'\n" + "MediaType '%s'\n" + "OutputType '%s'\n" + "AdvanceDistance %d\n" + "AdvanceMedia %d\n" + "Collate %d\n" + "CutMedia %d\n" + "Duplex %d\n" + "HWResolution %d %d\n" + "ImagingBoundingBox %d %d %d %d\n" + "InsertSheet %d\n" + "Jog %d\n" + "LeadingEdge %d\n" + "Margins %d %d\n" + "ManualFeed %d\n" + "MediaPosition %d\n" + "MediaWeight %d\n" + "MirrorPrint %d\n" + "NegativePrint %d\n" + "NumCopies %d\n" + "Orientation %d\n" + "OutputFaceUp %d\n" + "PageSize %d %d\n" + "Separations %d\n" + "TraySwitch %d\n" + "Tumble %d\n" + "cupsWidth %d\n" + "cupsHeight %d\n" + "cupsMediaType %d\n" + "cupsBitsPerColor %d\n" + "cupsBitsPerPixel %d\n" + "cupsBytesPerLine %d\n" + "cupsColorOrder %d\n" + "cupsColorSpace %d\n" + "cupsCompression %d\n" + "cupsRowCount %d\n" + "cupsRowFeed %d\n" + "cupsRowStep %d\n" + "cupsNumColors %d\n" + "cupsBorderlessScalingFactor %f\n" + "cupsPageSize %f %f\n" + "cupsImagingBBox %f %f %f %f\n" + "cupsInteger %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n" + "cupsReal %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f\n" + "cupsString '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s'\n" + "cupsMarkerType '%s'\n" + "cupsRenderingIntent '%s'\n" + "cupsPageSizeName '%s'\n", + pHeader->MediaClass, pHeader->MediaColor, pHeader->MediaType, + pHeader->OutputType, pHeader->AdvanceDistance, pHeader->AdvanceMedia, + pHeader->Collate, pHeader->CutMedia, pHeader->Duplex, + pHeader->HWResolution[0], pHeader->HWResolution[1], + pHeader->ImagingBoundingBox[0], pHeader->ImagingBoundingBox[1], + pHeader->ImagingBoundingBox[2], pHeader->ImagingBoundingBox[3], + pHeader->InsertSheet, pHeader->Jog, pHeader->LeadingEdge, pHeader->Margins[0], + pHeader->Margins[1], pHeader->ManualFeed, pHeader->MediaPosition, + pHeader->MediaWeight, pHeader->MirrorPrint, pHeader->NegativePrint, + pHeader->NumCopies, pHeader->Orientation, pHeader->OutputFaceUp, + pHeader->PageSize[0], pHeader->PageSize[1], pHeader->Separations, + pHeader->TraySwitch, pHeader->Tumble, pHeader->cupsWidth, pHeader->cupsHeight, + pHeader->cupsMediaType, pHeader->cupsBitsPerColor, pHeader->cupsBitsPerPixel, + pHeader->cupsBytesPerLine, pHeader->cupsColorOrder, pHeader->cupsColorSpace, + pHeader->cupsCompression, pHeader->cupsRowCount, pHeader->cupsRowFeed, + pHeader->cupsRowStep, pHeader->cupsNumColors, + pHeader->cupsBorderlessScalingFactor, pHeader->cupsPageSize[0], + pHeader->cupsPageSize[1], pHeader->cupsImagingBBox[0], + pHeader->cupsImagingBBox[1], pHeader->cupsImagingBBox[2], + pHeader->cupsImagingBBox[3], pHeader->cupsInteger[0], + pHeader->cupsInteger[1], pHeader->cupsInteger[2], pHeader->cupsInteger[3], + pHeader->cupsInteger[4], pHeader->cupsInteger[5], pHeader->cupsInteger[6], + pHeader->cupsInteger[7], pHeader->cupsInteger[8], pHeader->cupsInteger[9], + pHeader->cupsInteger[10], pHeader->cupsInteger[11], pHeader->cupsInteger[12], + pHeader->cupsInteger[13], pHeader->cupsInteger[14], pHeader->cupsInteger[15], + pHeader->cupsReal[0], pHeader->cupsReal[1], pHeader->cupsReal[2], + pHeader->cupsReal[3], pHeader->cupsReal[4], pHeader->cupsReal[5], + pHeader->cupsReal[6], pHeader->cupsReal[7], pHeader->cupsReal[8], + pHeader->cupsReal[9], pHeader->cupsReal[10], pHeader->cupsReal[11], + pHeader->cupsReal[12], pHeader->cupsReal[13], pHeader->cupsReal[14], + pHeader->cupsReal[15], pHeader->cupsString[0], pHeader->cupsString[1], + pHeader->cupsString[2], pHeader->cupsString[3], pHeader->cupsString[4], + pHeader->cupsString[5], pHeader->cupsString[6], pHeader->cupsString[7], + pHeader->cupsString[8], pHeader->cupsString[9], pHeader->cupsString[10], + pHeader->cupsString[11], pHeader->cupsString[12], pHeader->cupsString[13], + pHeader->cupsString[14], pHeader->cupsString[15], pHeader->cupsMarkerType, + pHeader->cupsRenderingIntent, pHeader->cupsPageSizeName); +} + +// rearrange (compress) rows in pBuf, discarding tails of them +static inline unsigned compress_buffer(unsigned char *pBuf, unsigned iSize, + unsigned int iWideStride, unsigned int iStride) { + const unsigned char *pEnd = pBuf + iSize; + unsigned char *pTarget = pBuf; + while (pBuf < pEnd) { + int iBytes = min(pEnd - pBuf, iStride); + memmove(pTarget, pBuf, iBytes); + pTarget += iBytes; + pBuf += iWideStride; + } + return min(iSize, pTarget - pBuf); +} + +// returns -1 if whole line iz filled by zeros. Otherwise 0. +static inline int line_is_empty(const unsigned char *pBuf, unsigned iSize) { + int i; + for (i = 0; i < iSize; ++i) + if (pBuf[i]) + return 0; + return -1; +} + +static inline void send_raster(const unsigned char *pBuf, int width8, + int height) { + if (!height) + return; + DEBUGPRINT("Raster block %dx%d pixels\n", width8*8, height); + sendRasterHeader(width8, height); + outputarray((char *)pBuf, width8 * height); + flushBuffer(); +} + +#define EXITPRINT(CODE) \ + { \ + if (pRasterSrc) \ + cupsRasterClose(pRasterSrc); \ + if (pRasterBuf) \ + free(pRasterBuf); \ + if (fd) \ + close(fd); \ + return (CODE); \ + } ////////////////////////////////////////////// ////////////////////////////////////////////// int main(int argc, char *argv[]) { - int fd = 0; // File descriptor providing CUPS raster data - cups_raster_t *ras = NULL; // Raster stream for printing - cups_page_header2_t header; // CUPS Page header - int page = 0; // Current page - int y = 0; // Vertical position in page 0 <= y <= header.cupsHeight - - unsigned char *rasterData = NULL; // Pointer to raster data from CUPS - unsigned char *originalRasterDataPtr = - NULL; // Copy of original pointer for freeing buffer - if (argc < 6 || argc > 7) { fputs("ERROR: rastertozj job-id user title copies options [file]\n", stderr); return EXIT_FAILURE; } + int fd = STDIN_FILENO; // File descriptor providing CUPS raster data if (argc == 7) { if ((fd = open(argv[6], O_RDONLY)) == -1) { perror("ERROR: Unable to open raster file - "); sleep(1); return EXIT_FAILURE; } - } else - fd = 0; + } -#ifdef DEBUGP - lfd = fopen(DEBUGFILE, "w"); -#endif + DEBUGSTARTPRINT(); + int iCurrentPage = 0; + // CUPS Page tHeader + cups_page_header2_t tHeader; + unsigned char *pRasterBuf = NULL; // Pointer to raster data from CUPS + // Raster stream for printing + cups_raster_t *pRasterSrc = cupsRasterOpen(fd, CUPS_RASTER_READ); + initializeSettings(argv[5],&settings); + + DEBUGPRINT("ModelNumber from PPD '%d'\n", settings.modelNum); + + // set max num of pixels per line depended from model number (from ppd) + int iMaxWidth = settings.modelNum; + if (!iMaxWidth) + iMaxWidth = 0x240; - initializeSettings(argv[5]); - jobSetup(); - ras = cupsRasterOpen(fd, CUPS_RASTER_READ); - page = 0; + // postpone start of the job until we parse first header and get necessary values from there. + int iJobStarted = 0; - while (cupsRasterReadHeader2(ras, &header)) { - if ((header.cupsHeight == 0) || (header.cupsBytesPerLine == 0)) + // loop over the whole raster, page by page + while (cupsRasterReadHeader2(pRasterSrc, &tHeader)) { + if ((!tHeader.cupsHeight) || (!tHeader.cupsBytesPerLine)) break; -#ifdef DEBUGP - if (lfd) - fprintf(lfd, "\nheader.cupsHeight=%d, header.cupsBytesPerLine=%d\n", - header.cupsHeight, header.cupsBytesPerLine); -#endif + update_settings_from_job( &tHeader ); - if (rasterData == NULL) { - rasterData = malloc(header.cupsBytesPerLine * 24); - if (rasterData == NULL) { - if (originalRasterDataPtr != NULL) - free(originalRasterDataPtr); - cupsRasterClose(ras); - if (fd != 0) - close(fd); - return EXIT_FAILURE; - } - originalRasterDataPtr = rasterData; // used to later free the memory + if (!iJobStarted) + { + setupJob(); + iJobStarted = 1; } - fprintf(stderr, "PAGE: %d %d\n", ++page, header.NumCopies); - pageSetup(); + DebugPrintHeader ( &tHeader ); - int foo = (header.cupsWidth > 0x180) ? 0x180 : header.cupsWidth; + if (!pRasterBuf) { + pRasterBuf = malloc(tHeader.cupsBytesPerLine * 24); + if (!pRasterBuf) // hope it never goes here... + EXITPRINT(EXIT_FAILURE) + } + + fprintf(stderr, "PAGE: %d %d\n", ++iCurrentPage, tHeader.NumCopies); + + startPage(); + + // calculate num of bytes to print given width having 1 bit per pixel. + int foo = min(tHeader.cupsWidth, iMaxWidth); // 0x240 for 80mm (72mm printable) foo = (foo + 7) & 0xFFFFFFF8; - int width_size = foo >> 3; + int width_bytes = foo >> 3; // in bytes, [0..0x30] -#ifdef DEBUGP - if (lfd) - fprintf(lfd, "\nheader.cupsWidth=%d, foo=%d, width_size=%d\n", - header.cupsWidth, foo, width_size); -#endif - y = 0; + DEBUGPRINT("cupsWidth=%d, cupsBytesPerLine=%d; foo=%d, width_bytes=%d", + tHeader.cupsWidth, tHeader.cupsBytesPerLine, foo, width_bytes ); + + int iRowsToPrint = tHeader.cupsHeight; int zeroy = 0; - while (y < header.cupsHeight) { - if ((y & 127) != 0) - fprintf(stderr, "INFO: Printing page %d, %d%% complete...\n", page, - (100 * y / header.cupsHeight)); + // loop over one page, top to bottom by blocks of most 24 scan lines + while (iRowsToPrint) { + fprintf(stderr, "INFO: Printing iCurrentPage %d, %d%% complete...\n", + iCurrentPage, + (100 * (tHeader.cupsHeight - iRowsToPrint) / tHeader.cupsHeight)); - int rest = header.cupsHeight - y; - if (rest > 24) - rest = 24; + int iBlockHeight = min(iRowsToPrint, 24); -#ifdef DEBUGP - if (lfd) - fprintf(lfd, "\nProcessing block of %d, starting from %d lines\n", rest, - y); -#endif - y += rest; - - if (y) { - unsigned char *buf = rasterData; - int j; - for (j = 0; j < rest; ++j) { - if (!cupsRasterReadPixels(ras, buf, header.cupsBytesPerLine)) - break; - buf += width_size; - } -#ifdef DEBUGP - if (lfd) - fprintf(lfd, "\nRead %d lines\n", j); -#endif - if (j < rest) - continue; - } - int rest_bytes = rest * width_size; - int j; - for (j = 0; j < rest_bytes; ++j) - if (rasterData[j] != 0) - break; - -#ifdef DEBUGP - if (lfd) - fprintf(lfd, "\nChecked %d bytes of %d for zero\n", j, rest_bytes); -#endif + DEBUGPRINT("--------Processing block of %d, starting from %d lines", + iBlockHeight, tHeader.cupsHeight - iRowsToPrint); - if (j >= rest_bytes) { - ++zeroy; - continue; + iRowsToPrint -= iBlockHeight; + unsigned iBytesChunk = 0; + + // first, fetch whole block from the image + if (iBlockHeight) + iBytesChunk = cupsRasterReadPixels( + pRasterSrc, pRasterBuf, tHeader.cupsBytesPerLine * iBlockHeight); + + DEBUGPRINT("--------Got %d from %d requested bytes", + iBytesChunk, + tHeader.cupsBytesPerLine * + iBlockHeight); + + // if original image is wider - rearrange buffer so that our calculated + // lines come one-by-one without extra gaps + if (width_bytes < tHeader.cupsBytesPerLine) { + DEBUGPRINT("--------Compress line from %d to %d bytes", tHeader.cupsBytesPerLine, width_bytes); + iBytesChunk = compress_buffer(pRasterBuf, iBytesChunk, + tHeader.cupsBytesPerLine, width_bytes); } - for (; zeroy > 0; --zeroy) - skiplines(24); + // runaround for sometimes truncated output of cupsRasterReadPixels + if (iBytesChunk < width_bytes * iBlockHeight) { + DEBUGPRINT("--------Restore truncated gap of %d bytes", + width_bytes * iBlockHeight - iBytesChunk); + memset(pRasterBuf + iBytesChunk, 0, + width_bytes * iBlockHeight - iBytesChunk); + iBytesChunk = width_bytes * iBlockHeight; + } - rasterheader(width_size, rest); - outputarray((char *)rasterData, width_size * 24); - skiplines(0); - } + // lazy output of current raster. First check current line if it is zero. + // if there were many zeroes and met non-zero - flush zeros by 'feed' cmd + // if opposite - send non-zero chunk as raster. + unsigned char *pBuf = pRasterBuf; + unsigned char *pChunk = pBuf; + const unsigned char *pEnd = pBuf + iBytesChunk; + int nonzerolines = 0; + while ( pBuf 0; --zeroy) - skiplines(24); + // page is finished. + // m.b. we have to print empty tail at the end + if (settings.InsertSheet) + flushManyLines (zeroy); - EndPage(); - } + if (settings.AdvanceMedia == CUPS_ADVANCE_PAGE) + flushManyLines(settings.AdvanceDistance); - ShutDown(); + if (settings.CutMedia == CUPS_CUT_PAGE) + cutMedia(); - if (originalRasterDataPtr) - free(originalRasterDataPtr); - cupsRasterClose(ras); - if (fd) - close(fd); + finishPage(); + } // loop over all pages pages - fputs(page ? "INFO: Ready to print.\n" : "ERROR: No pages found!\n", stderr); + if (settings.AdvanceMedia==CUPS_ADVANCE_JOB) + flushManyLines(settings.AdvanceDistance); -#ifdef DEBUGP - if (lfd) - fclose(lfd); -#endif + if (settings.CutMedia == CUPS_CUT_JOB) + cutMedia(); - return page ? EXIT_SUCCESS : EXIT_FAILURE; + finalizeJob(); + fputs(iCurrentPage ? "INFO: Ready to print.\n" : "ERROR: No pages found!\n", + stderr); + DEBUGFINISHPRINT(); + EXITPRINT(iCurrentPage ? EXIT_SUCCESS : EXIT_FAILURE) } // end of rastertozj.c diff --git a/zj-58.drv b/zj-58.drv deleted file mode 100644 index d55fcad..0000000 --- a/zj-58.drv +++ /dev/null @@ -1,66 +0,0 @@ -// CUPS PPD Compiler CUPS v2.1.3 -// (Don't edit .ppd directly, edit this file instead, then use -// ppdc zj-58.drv to generate zj58.ppd) -// Include necessary files... -#include -#include - -// Zijiang ZJ-58 -{ - Manufacturer "Zijiang" - ModelName "ZJ-58" - PCFileName "zj58.ppd" - Version "1.2" - DriverType ps - ModelNumber 58 - ManualCopies Yes - Throughput 1 - Attribute "NickName" "" "Zijiang ZJ-58" - Attribute "ShortNickName" "" "ZJ-58" - Attribute "Product" "" "(zj-58)" - Attribute "1284DeviceID" "" "MFG:Zijiang;CMD:Zijiang;MDL:ZJ-58;CLS:PRINTER;" - Attribute "PSVersion" "" "(3010.000) 550" - Attribute "LanguageLevel" "" "3" - Attribute "DefaultColorSpace" "" "Gray" - Attribute "FileSystem" "" "False" - Attribute "LandscapeOrientation" "" "Plus90" - Attribute "TTRasterizer" "" "Type42" - Attribute "VariablePaperSize" "" "True" - Filter "application/vnd.cups-raster 0 rastertozj" - - *CustomMedia "X48MMY105MM/58mm x 105mm" 136.00 298.00 0.00 0.00 0.00 0.00 "<>setpagedevice" "<>setpagedevice" - CustomMedia "X48MMY210MM/58mm x 210mm" 136.00 595.00 0.00 0.00 0.00 0.00 "<>setpagedevice" "<>setpagedevice" - CustomMedia "X48MMY297MM/58mm x 297mm" 136.00 842.00 0.00 0.00 0.00 0.00 "<>setpagedevice" "<>setpagedevice" - CustomMedia "X48MMY3276MM/58mm x 3276mm" 136.00 9286.00 0.00 0.00 0.00 0.00 "<>setpagedevice" "<>setpagedevice" - - Group "CutGroup/Cut Options" - Option "FeedDist/Feed distance after print" PickOne AnySetup 0.0 - Choice "0feed3mm/feed 3mm" "" - Choice "1feed6mm/feed 6mm" "" - *Choice "2feed9mm/feed 9mm" "" - Choice "3feed12mm/feed 12mm" "" - Choice "4feed15mm/feed 15mm" "" - Choice "5feed18mm/feed 18mm" "" - Choice "6feed21mm/feed 21mm" "" - Choice "7feed24mm/feed 24mm" "" - Choice "8feed27mm/feed 27mm" "" - Choice "9feed30mm/feed 30mm" "" - Choice "10feed33mm/feed 33mm" "" - Choice "11feed36mm/feed 36mm" "" - Choice "12feed39mm/feed 39mm" "" - Choice "13feed42mm/feed 42mm" "" - Choice "14feed45mm/feed 45mm" "" - Option "BlankSpace/Blank space at page's end" PickOne AnySetup 0.0 - Choice "0Print/Print" "" - *Choice "1NoPrint/Do not print" "" - Group "*CashDrawerGroup/Cash Drawer Control" - Option "CashDrawer1Setting/Cash Drawer 1" PickOne AnySetup 0.0 - *Choice "0NotCashDrawer1/Not Cash Drawer 1" "" - Choice "1NotCashDrawer1BeforePrinting/Cash Drawer 1 Before Printing" "" - Choice "2NotCashDrawer1BeforePrinting/Cash Drawer 1 After Printing" "" - Option "CashDrawer2Setting/Cash Drawer 2" PickOne AnySetup 0.0 - *Choice "0NotCashDrawer2/Not Cash Drawer 2" "" - Choice "1NotCashDrawer2BeforePrinting/Cash Drawer 2 Before Printing" "" - Choice "2NotCashDrawer2BeforePrinting/Cash Drawer 2 After Printing" "" - -} diff --git a/zj58.ppd b/zj58.ppd new file mode 100644 index 0000000..737f433 --- /dev/null +++ b/zj58.ppd @@ -0,0 +1,212 @@ +*PPD-Adobe: "4.3" +*%%%% PPD file for ZJ-58 with CUPS. +*%%%% Created by the CUPS PPD Compiler CUPS v2.2.7. +*FormatVersion: "4.3" +*FileVersion: "1.2" +*LanguageVersion: English +*LanguageEncoding: ISOLatin1 +*PCFileName: "zj58.ppd" +*Product: "(zj-58)" +*Manufacturer: "Zijiang" +*ModelName: "Zijiang ZJ-58" +*ShortNickName: "ZJ-58" +*NickName: "Zijiang ZJ-58" +*PSVersion: "(3010.000) 550" +*LanguageLevel: "3" +*ColorDevice: False +*DefaultColorSpace: Gray +*FileSystem: False +*Throughput: "1" +*LandscapeOrientation: Plus90 +*TTRasterizer: Type42 +*% Driver-defined attributes... +*VariablePaperSize: True +*1284DeviceID: "MFG:Zijiang;CMD:Zijiang;MDL:ZJ-58;CLS:PRINTER;" +*cupsVersion: 2.2 +*cupsModelNumber: 384 +*cupsManualCopies: True +*cupsFilter: "application/vnd.cups-raster 100 rastertozj" +*cupsLanguages: "en" +*UIConstraints: *CashDrawer1Setting *OptionCash1 False +*UIConstraints: *OptionCash1 False *CashDrawer1Setting +*UIConstraints: *CashDrawer2Setting *OptionCash2 False +*UIConstraints: *OptionCash2 False *CashDrawer2Setting +*UIConstraints: *CutMedia *OptionCutter False +*UIConstraints: *OptionCutter False *CutMedia +*OpenUI *PageSize/Media Size: PickOne +*OrderDependency: 10 AnySetup *PageSize +*DefaultPageSize: X48MMY65MM +*PageSize X48MMY65MM/58mm x 65mm: "<>setpagedevice" +*PageSize X48MMY105MM/58mm x 105mm: "<>setpagedevice" +*PageSize X48MMY210MM/58mm x 210mm: "<>setpagedevice" +*PageSize X48MMY297MM/58mm x 297mm: "<>setpagedevice" +*PageSize X48MMY3276MM/58mm x 3276mm: "<>setpagedevice" +*CloseUI: *PageSize +*OpenUI *PageRegion/Media Size: PickOne +*OrderDependency: 10 AnySetup *PageRegion +*DefaultPageRegion: X48MMY65MM +*PageRegion X48MMY65MM/58mm x 65mm: "<>setpagedevice" +*PageRegion X48MMY105MM/58mm x 105mm: "<>setpagedevice" +*PageRegion X48MMY210MM/58mm x 210mm: "<>setpagedevice" +*PageRegion X48MMY297MM/58mm x 297mm: "<>setpagedevice" +*PageRegion X48MMY3276MM/58mm x 3276mm: "<>setpagedevice" +*CloseUI: *PageRegion +*DefaultImageableArea: X48MMY65MM +*ImageableArea X48MMY65MM/58mm x 65mm: "14 0 150 182" +*ImageableArea X48MMY105MM/58mm x 105mm: "14 0 150 298" +*ImageableArea X48MMY210MM/58mm x 210mm: "14 0 150 595" +*ImageableArea X48MMY297MM/58mm x 297mm: "14 0 150 842" +*ImageableArea X48MMY3276MM/58mm x 3276mm: "14 0 150 9286" +*DefaultPaperDimension: X48MMY65MM +*PaperDimension X48MMY65MM/58mm x 65mm: "164 182" +*PaperDimension X48MMY105MM/58mm x 105mm: "164 298" +*PaperDimension X48MMY210MM/58mm x 210mm: "164 595" +*PaperDimension X48MMY297MM/58mm x 297mm: "164 842" +*PaperDimension X48MMY3276MM/58mm x 3276mm: "164 9286" +*MaxMediaWidth: "164" +*MaxMediaHeight: "9286" +*HWMargins: 14 0 14 0 +*CustomPageSize True: "pop pop pop <>setpagedevice" +*ParamCustomPageSize Width: 1 points 164 164 +*ParamCustomPageSize Height: 2 points 56 9286 +*ParamCustomPageSize WidthOffset: 3 points 0 0 +*ParamCustomPageSize HeightOffset: 4 points 0 0 +*ParamCustomPageSize Orientation: 5 int 0 0 +*OpenUI *CutMedia/Cut Media: PickOne +*OrderDependency: 10 AnySetup *CutMedia +*DefaultCutMedia: None +*CutMedia None/No cutting: "<>setpagedevice" +*CutMedia EndOfPage/Cut at every page: "<>setpagedevice" +*CutMedia EndOfJob/Cut at every job: "<>setpagedevice" +*CloseUI: *CutMedia +*OpenGroup: InstallableOptions/Installable Options +*OpenUI *OptionCash1/Cash drawer 1: Boolean +*OrderDependency: 10 AnySetup *OptionCash1 +*DefaultOptionCash1: False +*OptionCash1 False/Not Installed: "" +*OptionCash1 True/Installed: "" +*CloseUI: *OptionCash1 +*OpenUI *OptionCash2/Cash drawer 2: Boolean +*OrderDependency: 10 AnySetup *OptionCash2 +*DefaultOptionCash2: False +*OptionCash2 False/Not Installed: "" +*OptionCash2 True/Installed: "" +*CloseUI: *OptionCash2 +*OpenUI *OptionCutter/Cutter: Boolean +*OrderDependency: 10 AnySetup *OptionCutter +*DefaultOptionCutter: False +*OptionCutter False/Not Installed: "" +*OptionCutter True/Installed: "" +*CloseUI: *OptionCutter +*CloseGroup: InstallableOptions +*OpenGroup: BlankGroup/Blank Options +*OpenUI *FeedDist/Feed distance: PickOne +*OrderDependency: 10 AnySetup *FeedDist +*DefaultFeedDist: 2feed9mm +*FeedDist 0feed3mm/3mm: "<>setpagedevice" +*FeedDist 1feed6mm/6mm: "<>setpagedevice" +*FeedDist 2feed9mm/9mm: "<>setpagedevice" +*FeedDist 3feed12mm/12mm: "<>setpagedevice" +*FeedDist 4feed15mm/15mm: "<>setpagedevice" +*FeedDist 5feed18mm/18mm: "<>setpagedevice" +*FeedDist 6feed21mm/21mm: "<>setpagedevice" +*FeedDist 7feed24mm/24mm: "<>setpagedevice" +*FeedDist 8feed27mm/27mm: "<>setpagedevice" +*FeedDist 9feed30mm/30mm: "<>setpagedevice" +*FeedDist 10feed33mm/33mm: "<>setpagedevice" +*FeedDist 11feed36mm/36mm: "<>setpagedevice" +*FeedDist 12feed39mm/39mm: "<>setpagedevice" +*FeedDist 13feed42mm/42mm: "<>setpagedevice" +*FeedDist 14feed45mm/45mm: "<>setpagedevice" +*CloseUI: *FeedDist +*OpenUI *FeedWhere/When to feed: PickOne +*OrderDependency: 10 AnySetup *FeedWhere +*DefaultFeedWhere: AfterJob +*FeedWhere None/Never: "" +*FeedWhere AfterPage/After each page: "<>setpagedevice" +*FeedWhere AfterJob/After whole printing: "<>setpagedevice" +*CloseUI: *FeedWhere +*OpenUI *BlankSpace/Blank space at page's end: Boolean +*OrderDependency: 10 AnySetup *BlankSpace +*DefaultBlankSpace: False +*BlankSpace True/Print: "<>setpagedevice" +*BlankSpace False/None: "<>setpagedevice" +*CloseUI: *BlankSpace +*CloseGroup: BlankGroup +*OpenGroup: *CashDrawerGroup/Cash Drawer Control +*OpenUI *CashDrawer1Setting/Cash Drawer 1: PickOne +*OrderDependency: 10 DocumentSetup *CashDrawer1Setting +*DefaultCashDrawer1Setting: None +*CashDrawer1Setting None/None: "<>setpagedevice" +*CashDrawer1Setting 1BeforePrinting/Before Printing: "<>setpagedevice" +*CashDrawer1Setting 1AfterPrinting/After Printing: "<>setpagedevice" +*CloseUI: *CashDrawer1Setting +*OpenUI *CashDrawer2Setting/Cash Drawer 2: PickOne +*OrderDependency: 10 DocumentSetup *CashDrawer2Setting +*DefaultCashDrawer2Setting: None +*CashDrawer2Setting None/None: "<>setpagedevice" +*CashDrawer2Setting 2BeforePrinting/Before Printing: "<>setpagedevice" +*CashDrawer2Setting 2AfterPrinting/After Printing: "<>setpagedevice" +*CloseUI: *CashDrawer2Setting +*CloseGroup: *CashDrawerGroup +*OpenGroup: *CashDrawerTune/Cash Drawer Tune +*OpenUI *CashDrawer1PulseOn/Cash Drawer 1 pulse ON time: PickOne +*OrderDependency: 9 DocumentSetup *CashDrawer1PulseOn +*DefaultCashDrawer1PulseOn: 40XMS +*CashDrawer1PulseOn None/None: "" +*CashDrawer1PulseOn 10XMS/32mS: "<>setpagedevice" +*CashDrawer1PulseOn 20XMS/64mS: "<>setpagedevice" +*CashDrawer1PulseOn 30XMS/96mS: "<>setpagedevice" +*CashDrawer1PulseOn 40XMS/128mS: "<>setpagedevice" +*CashDrawer1PulseOn 50XMS/160mS: "<>setpagedevice" +*CashDrawer1PulseOn 60XMS/192mS: "<>setpagedevice" +*CashDrawer1PulseOn 70XMS/224mS: "<>setpagedevice" +*CashDrawer1PulseOn 80XMS/256mS: "<>setpagedevice" +*CloseUI: *CashDrawer1PulseOn +*OpenUI *CashDrawer1PulseOff/Cash Drawer 1 pulse OFF time: PickOne +*OrderDependency: 9 DocumentSetup *CashDrawer1PulseOff +*DefaultCashDrawer1PulseOff: 50XMS +*CashDrawer1PulseOff None/None: "" +*CashDrawer1PulseOff 10XMS/32mS: "<>setpagedevice" +*CashDrawer1PulseOff 20XMS/64mS: "<>setpagedevice" +*CashDrawer1PulseOff 30XMS/96mS: "<>setpagedevice" +*CashDrawer1PulseOff 40XMS/128mS: "<>setpagedevice" +*CashDrawer1PulseOff 50XMS/160mS: "<>setpagedevice" +*CashDrawer1PulseOff 60XMS/192mS: "<>setpagedevice" +*CashDrawer1PulseOff 70XMS/224mS: "<>setpagedevice" +*CashDrawer1PulseOff 80XMS/256mS: "<>setpagedevice" +*CloseUI: *CashDrawer1PulseOff +*OpenUI *CashDrawer2PulseOn/Cash Drawer 2 pulse ON time: PickOne +*OrderDependency: 9 DocumentSetup *CashDrawer2PulseOn +*DefaultCashDrawer2PulseOn: 40XMS +*CashDrawer2PulseOn None/None: "" +*CashDrawer2PulseOn 10XMS/32mS: "<>setpagedevice" +*CashDrawer2PulseOn 20XMS/64mS: "<>setpagedevice" +*CashDrawer2PulseOn 30XMS/96mS: "<>setpagedevice" +*CashDrawer2PulseOn 40XMS/128mS: "<>setpagedevice" +*CashDrawer2PulseOn 50XMS/160mS: "<>setpagedevice" +*CashDrawer2PulseOn 60XMS/192mS: "<>setpagedevice" +*CashDrawer2PulseOn 70XMS/224mS: "<>setpagedevice" +*CashDrawer2PulseOn 80XMS/256mS: "<>setpagedevice" +*CloseUI: *CashDrawer2PulseOn +*OpenUI *CashDrawer2PulseOff/Cash Drawer 2 pulse OFF time: PickOne +*OrderDependency: 9 DocumentSetup *CashDrawer2PulseOff +*DefaultCashDrawer2PulseOff: 50XMS +*CashDrawer2PulseOff None/None: "" +*CashDrawer2PulseOff 10XMS/32mS: "<>setpagedevice" +*CashDrawer2PulseOff 20XMS/64mS: "<>setpagedevice" +*CashDrawer2PulseOff 30XMS/96mS: "<>setpagedevice" +*CashDrawer2PulseOff 40XMS/128mS: "<>setpagedevice" +*CashDrawer2PulseOff 50XMS/160mS: "<>setpagedevice" +*CashDrawer2PulseOff 60XMS/192mS: "<>setpagedevice" +*CashDrawer2PulseOff 70XMS/224mS: "<>setpagedevice" +*CashDrawer2PulseOff 80XMS/256mS: "<>setpagedevice" +*CloseUI: *CashDrawer2PulseOff +*OpenUI *Resolution/Resolution: PickOne +*OrderDependency: 10 AnySetup *Resolution +*DefaultResolution: 203x203dpi +*Resolution 203x203dpi/203 DPI Grayscale: "<>setpagedevice" +*CloseUI: *Resolution +*CloseGroup: *CashDrawerTune +*DefaultFont: Courier +*% End of zj58.ppd, 10245 bytes. diff --git a/zj80.ppd b/zj80.ppd new file mode 100644 index 0000000..6ac713d --- /dev/null +++ b/zj80.ppd @@ -0,0 +1,212 @@ +*PPD-Adobe: "4.3" +*%%%% PPD file for ZJ-80 with CUPS. +*%%%% Created by the CUPS PPD Compiler CUPS v2.2.7. +*FormatVersion: "4.3" +*FileVersion: "1.2" +*LanguageVersion: English +*LanguageEncoding: ISOLatin1 +*PCFileName: "zj80.ppd" +*Product: "(zj-80)" +*Manufacturer: "Zijiang" +*ModelName: "Zijiang ZJ-80" +*ShortNickName: "ZJ-80" +*NickName: "Zijiang ZJ-80" +*PSVersion: "(3010.000) 550" +*LanguageLevel: "3" +*ColorDevice: False +*DefaultColorSpace: Gray +*FileSystem: False +*Throughput: "1" +*LandscapeOrientation: Plus90 +*TTRasterizer: Type42 +*% Driver-defined attributes... +*VariablePaperSize: True +*1284DeviceID: "MFG:Zijiang;CMD:Zijiang;MDL:ZJ-80;CLS:PRINTER;" +*cupsVersion: 2.2 +*cupsModelNumber: 560 +*cupsManualCopies: True +*cupsFilter: "application/vnd.cups-raster 100 rastertozj" +*cupsLanguages: "en" +*UIConstraints: *CashDrawer1Setting *OptionCash1 False +*UIConstraints: *OptionCash1 False *CashDrawer1Setting +*UIConstraints: *CashDrawer2Setting *OptionCash2 False +*UIConstraints: *OptionCash2 False *CashDrawer2Setting +*UIConstraints: *CutMedia *OptionCutter False +*UIConstraints: *OptionCutter False *CutMedia +*OpenUI *PageSize/Media Size: PickOne +*OrderDependency: 10 AnySetup *PageSize +*DefaultPageSize: X70MMY65MM +*PageSize X70MMY65MM/80mm x 65mm: "<>setpagedevice" +*PageSize X70MMY105MM/80mm x 105mm: "<>setpagedevice" +*PageSize X70MMY210MM/80mm x 210mm: "<>setpagedevice" +*PageSize X70MMY297MM/80mm x 297mm: "<>setpagedevice" +*PageSize X70MMY3276MM/80mm x 3276mm: "<>setpagedevice" +*CloseUI: *PageSize +*OpenUI *PageRegion/Media Size: PickOne +*OrderDependency: 10 AnySetup *PageRegion +*DefaultPageRegion: X70MMY65MM +*PageRegion X70MMY65MM/80mm x 65mm: "<>setpagedevice" +*PageRegion X70MMY105MM/80mm x 105mm: "<>setpagedevice" +*PageRegion X70MMY210MM/80mm x 210mm: "<>setpagedevice" +*PageRegion X70MMY297MM/80mm x 297mm: "<>setpagedevice" +*PageRegion X70MMY3276MM/80mm x 3276mm: "<>setpagedevice" +*CloseUI: *PageRegion +*DefaultImageableArea: X70MMY65MM +*ImageableArea X70MMY65MM/80mm x 65mm: "14 0 212 182" +*ImageableArea X70MMY105MM/80mm x 105mm: "14 0 212 298" +*ImageableArea X70MMY210MM/80mm x 210mm: "14 0 212 595" +*ImageableArea X70MMY297MM/80mm x 297mm: "14 0 212 842" +*ImageableArea X70MMY3276MM/80mm x 3276mm: "14 0 212 9286" +*DefaultPaperDimension: X70MMY65MM +*PaperDimension X70MMY65MM/80mm x 65mm: "226 182" +*PaperDimension X70MMY105MM/80mm x 105mm: "226 298" +*PaperDimension X70MMY210MM/80mm x 210mm: "226 595" +*PaperDimension X70MMY297MM/80mm x 297mm: "226 842" +*PaperDimension X70MMY3276MM/80mm x 3276mm: "226 9286" +*MaxMediaWidth: "226" +*MaxMediaHeight: "9286" +*HWMargins: 14 0 14 0 +*CustomPageSize True: "pop pop pop <>setpagedevice" +*ParamCustomPageSize Width: 1 points 226 226 +*ParamCustomPageSize Height: 2 points 56 9286 +*ParamCustomPageSize WidthOffset: 3 points 0 0 +*ParamCustomPageSize HeightOffset: 4 points 0 0 +*ParamCustomPageSize Orientation: 5 int 0 0 +*OpenUI *CutMedia/Cut Media: PickOne +*OrderDependency: 10 AnySetup *CutMedia +*DefaultCutMedia: None +*CutMedia None/No cutting: "<>setpagedevice" +*CutMedia EndOfPage/Cut at every page: "<>setpagedevice" +*CutMedia EndOfJob/Cut at every job: "<>setpagedevice" +*CloseUI: *CutMedia +*OpenGroup: InstallableOptions/Installable Options +*OpenUI *OptionCash1/Cash drawer 1: Boolean +*OrderDependency: 10 AnySetup *OptionCash1 +*DefaultOptionCash1: False +*OptionCash1 False/Not Installed: "" +*OptionCash1 True/Installed: "" +*CloseUI: *OptionCash1 +*OpenUI *OptionCash2/Cash drawer 2: Boolean +*OrderDependency: 10 AnySetup *OptionCash2 +*DefaultOptionCash2: False +*OptionCash2 False/Not Installed: "" +*OptionCash2 True/Installed: "" +*CloseUI: *OptionCash2 +*OpenUI *OptionCutter/Cutter: Boolean +*OrderDependency: 10 AnySetup *OptionCutter +*DefaultOptionCutter: False +*OptionCutter False/Not Installed: "" +*OptionCutter True/Installed: "" +*CloseUI: *OptionCutter +*CloseGroup: InstallableOptions +*OpenGroup: BlankGroup/Blank Options +*OpenUI *FeedDist/Feed distance: PickOne +*OrderDependency: 10 AnySetup *FeedDist +*DefaultFeedDist: 2feed9mm +*FeedDist 0feed3mm/3mm: "<>setpagedevice" +*FeedDist 1feed6mm/6mm: "<>setpagedevice" +*FeedDist 2feed9mm/9mm: "<>setpagedevice" +*FeedDist 3feed12mm/12mm: "<>setpagedevice" +*FeedDist 4feed15mm/15mm: "<>setpagedevice" +*FeedDist 5feed18mm/18mm: "<>setpagedevice" +*FeedDist 6feed21mm/21mm: "<>setpagedevice" +*FeedDist 7feed24mm/24mm: "<>setpagedevice" +*FeedDist 8feed27mm/27mm: "<>setpagedevice" +*FeedDist 9feed30mm/30mm: "<>setpagedevice" +*FeedDist 10feed33mm/33mm: "<>setpagedevice" +*FeedDist 11feed36mm/36mm: "<>setpagedevice" +*FeedDist 12feed39mm/39mm: "<>setpagedevice" +*FeedDist 13feed42mm/42mm: "<>setpagedevice" +*FeedDist 14feed45mm/45mm: "<>setpagedevice" +*CloseUI: *FeedDist +*OpenUI *FeedWhere/When to feed: PickOne +*OrderDependency: 10 AnySetup *FeedWhere +*DefaultFeedWhere: AfterJob +*FeedWhere None/Never: "" +*FeedWhere AfterPage/After each page: "<>setpagedevice" +*FeedWhere AfterJob/After whole printing: "<>setpagedevice" +*CloseUI: *FeedWhere +*OpenUI *BlankSpace/Blank space at page's end: Boolean +*OrderDependency: 10 AnySetup *BlankSpace +*DefaultBlankSpace: False +*BlankSpace True/Print: "<>setpagedevice" +*BlankSpace False/None: "<>setpagedevice" +*CloseUI: *BlankSpace +*CloseGroup: BlankGroup +*OpenGroup: *CashDrawerGroup/Cash Drawer Control +*OpenUI *CashDrawer1Setting/Cash Drawer 1: PickOne +*OrderDependency: 10 DocumentSetup *CashDrawer1Setting +*DefaultCashDrawer1Setting: None +*CashDrawer1Setting None/None: "<>setpagedevice" +*CashDrawer1Setting 1BeforePrinting/Before Printing: "<>setpagedevice" +*CashDrawer1Setting 1AfterPrinting/After Printing: "<>setpagedevice" +*CloseUI: *CashDrawer1Setting +*OpenUI *CashDrawer2Setting/Cash Drawer 2: PickOne +*OrderDependency: 10 DocumentSetup *CashDrawer2Setting +*DefaultCashDrawer2Setting: None +*CashDrawer2Setting None/None: "<>setpagedevice" +*CashDrawer2Setting 2BeforePrinting/Before Printing: "<>setpagedevice" +*CashDrawer2Setting 2AfterPrinting/After Printing: "<>setpagedevice" +*CloseUI: *CashDrawer2Setting +*CloseGroup: *CashDrawerGroup +*OpenGroup: *CashDrawerTune/Cash Drawer Tune +*OpenUI *CashDrawer1PulseOn/Cash Drawer 1 pulse ON time: PickOne +*OrderDependency: 9 DocumentSetup *CashDrawer1PulseOn +*DefaultCashDrawer1PulseOn: 40XMS +*CashDrawer1PulseOn None/None: "" +*CashDrawer1PulseOn 10XMS/32mS: "<>setpagedevice" +*CashDrawer1PulseOn 20XMS/64mS: "<>setpagedevice" +*CashDrawer1PulseOn 30XMS/96mS: "<>setpagedevice" +*CashDrawer1PulseOn 40XMS/128mS: "<>setpagedevice" +*CashDrawer1PulseOn 50XMS/160mS: "<>setpagedevice" +*CashDrawer1PulseOn 60XMS/192mS: "<>setpagedevice" +*CashDrawer1PulseOn 70XMS/224mS: "<>setpagedevice" +*CashDrawer1PulseOn 80XMS/256mS: "<>setpagedevice" +*CloseUI: *CashDrawer1PulseOn +*OpenUI *CashDrawer1PulseOff/Cash Drawer 1 pulse OFF time: PickOne +*OrderDependency: 9 DocumentSetup *CashDrawer1PulseOff +*DefaultCashDrawer1PulseOff: 50XMS +*CashDrawer1PulseOff None/None: "" +*CashDrawer1PulseOff 10XMS/32mS: "<>setpagedevice" +*CashDrawer1PulseOff 20XMS/64mS: "<>setpagedevice" +*CashDrawer1PulseOff 30XMS/96mS: "<>setpagedevice" +*CashDrawer1PulseOff 40XMS/128mS: "<>setpagedevice" +*CashDrawer1PulseOff 50XMS/160mS: "<>setpagedevice" +*CashDrawer1PulseOff 60XMS/192mS: "<>setpagedevice" +*CashDrawer1PulseOff 70XMS/224mS: "<>setpagedevice" +*CashDrawer1PulseOff 80XMS/256mS: "<>setpagedevice" +*CloseUI: *CashDrawer1PulseOff +*OpenUI *CashDrawer2PulseOn/Cash Drawer 2 pulse ON time: PickOne +*OrderDependency: 9 DocumentSetup *CashDrawer2PulseOn +*DefaultCashDrawer2PulseOn: 40XMS +*CashDrawer2PulseOn None/None: "" +*CashDrawer2PulseOn 10XMS/32mS: "<>setpagedevice" +*CashDrawer2PulseOn 20XMS/64mS: "<>setpagedevice" +*CashDrawer2PulseOn 30XMS/96mS: "<>setpagedevice" +*CashDrawer2PulseOn 40XMS/128mS: "<>setpagedevice" +*CashDrawer2PulseOn 50XMS/160mS: "<>setpagedevice" +*CashDrawer2PulseOn 60XMS/192mS: "<>setpagedevice" +*CashDrawer2PulseOn 70XMS/224mS: "<>setpagedevice" +*CashDrawer2PulseOn 80XMS/256mS: "<>setpagedevice" +*CloseUI: *CashDrawer2PulseOn +*OpenUI *CashDrawer2PulseOff/Cash Drawer 2 pulse OFF time: PickOne +*OrderDependency: 9 DocumentSetup *CashDrawer2PulseOff +*DefaultCashDrawer2PulseOff: 50XMS +*CashDrawer2PulseOff None/None: "" +*CashDrawer2PulseOff 10XMS/32mS: "<>setpagedevice" +*CashDrawer2PulseOff 20XMS/64mS: "<>setpagedevice" +*CashDrawer2PulseOff 30XMS/96mS: "<>setpagedevice" +*CashDrawer2PulseOff 40XMS/128mS: "<>setpagedevice" +*CashDrawer2PulseOff 50XMS/160mS: "<>setpagedevice" +*CashDrawer2PulseOff 60XMS/192mS: "<>setpagedevice" +*CashDrawer2PulseOff 70XMS/224mS: "<>setpagedevice" +*CashDrawer2PulseOff 80XMS/256mS: "<>setpagedevice" +*CloseUI: *CashDrawer2PulseOff +*OpenUI *Resolution/Resolution: PickOne +*OrderDependency: 10 AnySetup *Resolution +*DefaultResolution: 203x203dpi +*Resolution 203x203dpi/203 DPI Grayscale: "<>setpagedevice" +*CloseUI: *Resolution +*CloseGroup: *CashDrawerTune +*DefaultFont: Courier +*% End of zj80.ppd, 10245 bytes. diff --git a/zjdrv.drv b/zjdrv.drv new file mode 100644 index 0000000..49fc364 --- /dev/null +++ b/zjdrv.drv @@ -0,0 +1,216 @@ +// CUPS PPD Compiler CUPS v2.1.3 +// (Don't edit .ppd directly, edit this file instead, then use +// ppdc zj-58.drv to generate zj58.ppd) + +// common for all thermal printers +Version "1.2" +DriverType custom +ManualCopies Yes +Throughput 1 +Attribute "PSVersion" "" "(3010.000) 550" +Attribute "LanguageLevel" "" "3" +Attribute "DefaultColorSpace" "" "Gray" +Attribute "FileSystem" "" "False" +Attribute "LandscapeOrientation" "" "Plus90" +Attribute "TTRasterizer" "" "Type42" +Attribute "VariablePaperSize" "" "True" +Filter "application/vnd.cups-raster 100 rastertozj" +ColorDevice False +VariablePaperSize Yes + +// cutter +Option "CutMedia/Cut Media" PickOne AnySetup 10 + *Choice "None/No cutting" "<>setpagedevice" + Choice "EndOfPage/Cut at every page" "<>setpagedevice" + Choice "EndOfJob/Cut at every job" "<>setpagedevice" + +Group "BlankGroup/Blank Options" + Option "FeedDist/Feed distance" PickOne AnySetup 10 + Choice "0feed3mm/3mm" "<>setpagedevice" + Choice "1feed6mm/6mm" "<>setpagedevice" + *Choice "2feed9mm/9mm" "<>setpagedevice" + Choice "3feed12mm/12mm" "<>setpagedevice" + Choice "4feed15mm/15mm" "<>setpagedevice" + Choice "5feed18mm/18mm" "<>setpagedevice" + Choice "6feed21mm/21mm" "<>setpagedevice" + Choice "7feed24mm/24mm" "<>setpagedevice" + Choice "8feed27mm/27mm" "<>setpagedevice" + Choice "9feed30mm/30mm" "<>setpagedevice" + Choice "10feed33mm/33mm" "<>setpagedevice" + Choice "11feed36mm/36mm" "<>setpagedevice" + Choice "12feed39mm/39mm" "<>setpagedevice" + Choice "13feed42mm/42mm" "<>setpagedevice" + Choice "14feed45mm/45mm" "<>setpagedevice" + + Option "FeedWhere/When to feed" PickOne AnySetup 10 + Choice "None/Never" "" + Choice "AfterPage/After each page" "<>setpagedevice" + *Choice "AfterJob/After whole printing" "<>setpagedevice" + + Option "BlankSpace/Blank space at page's end" Boolean AnySetup 10 + Choice "True/Print" "<>setpagedevice" + *Choice "False/None" "<>setpagedevice" + +Group "*CashDrawerGroup/Cash Drawer Control" + Option "CashDrawer1Setting/Cash Drawer 1" PickOne DocumentSetup 10 + *Choice "None/None" "<>setpagedevice" + Choice "1BeforePrinting/Before Printing" "<>setpagedevice" + Choice "1AfterPrinting/After Printing" "<>setpagedevice" + + Option "CashDrawer2Setting/Cash Drawer 2" PickOne DocumentSetup 10 + *Choice "None/None" "<>setpagedevice" + Choice "2BeforePrinting/Before Printing" "<>setpagedevice" + Choice "2AfterPrinting/After Printing" "<>setpagedevice" + +Group "*CashDrawerTune/Cash Drawer Tune" + Option "CashDrawer1PulseOn/Cash Drawer 1 pulse ON time" PickOne DocumentSetup 9 + Choice "None/None" "" + Choice "10XMS/32mS" "<>setpagedevice" + Choice "20XMS/64mS" "<>setpagedevice" + Choice "30XMS/96mS" "<>setpagedevice" + *Choice "40XMS/128mS" "<>setpagedevice" + Choice "50XMS/160mS" "<>setpagedevice" + Choice "60XMS/192mS" "<>setpagedevice" + Choice "70XMS/224mS" "<>setpagedevice" + Choice "80XMS/256mS" "<>setpagedevice" + + Option "CashDrawer1PulseOff/Cash Drawer 1 pulse OFF time" PickOne DocumentSetup 9 + Choice "None/None" "" + Choice "10XMS/32mS" "<>setpagedevice" + Choice "20XMS/64mS" "<>setpagedevice" + Choice "30XMS/96mS" "<>setpagedevice" + Choice "40XMS/128mS" "<>setpagedevice" + *Choice "50XMS/160mS" "<>setpagedevice" + Choice "60XMS/192mS" "<>setpagedevice" + Choice "70XMS/224mS" "<>setpagedevice" + Choice "80XMS/256mS" "<>setpagedevice" + + Option "CashDrawer2PulseOn/Cash Drawer 2 pulse ON time" PickOne DocumentSetup 9 + Choice "None/None" "" + Choice "10XMS/32mS" "<>setpagedevice" + Choice "20XMS/64mS" "<>setpagedevice" + Choice "30XMS/96mS" "<>setpagedevice" + *Choice "40XMS/128mS" "<>setpagedevice" + Choice "50XMS/160mS" "<>setpagedevice" + Choice "60XMS/192mS" "<>setpagedevice" + Choice "70XMS/224mS" "<>setpagedevice" + Choice "80XMS/256mS" "<>setpagedevice" + + Option "CashDrawer2PulseOff/Cash Drawer 2 pulse OFF time" PickOne DocumentSetup 9 + Choice "None/None" "" + Choice "10XMS/32mS" "<>setpagedevice" + Choice "20XMS/64mS" "<>setpagedevice" + Choice "30XMS/96mS" "<>setpagedevice" + Choice "40XMS/128mS" "<>setpagedevice" + *Choice "50XMS/160mS" "<>setpagedevice" + Choice "60XMS/192mS" "<>setpagedevice" + Choice "70XMS/224mS" "<>setpagedevice" + Choice "80XMS/256mS" "<>setpagedevice" + + + Installable "OptionCash1/Cash drawer 1" + UIConstraints "*CashDrawer1Setting *OptionCash1 False" + // UIConstraints "*CashDrawer1PulseOn *OptionCash1 False" + // UIConstraints "*CashDrawer1PulseOff *OptionCash1 False" + +// Attribute cupsUIConstraints Cash1Off "*OptionCash1 False *CashDrawer1Setting" +// Attribute cupsUIConstraints Cash1Off "*OptionCash1 False *CashDrawer1PulseOn" +// Attribute cupsUIConstraints Cash1Off "*OptionCash1 False *CashDrawer1PulseOff" +// Attribute cupsUIResolver Cash1Off "*CashDrawer1Setting None *CashDrawer1PulseOn None *CashDrawer1PulseOff None" +// Attribute cupsUIResolver Cash1Off "*CashDrawer1PulseOn None" +// Attribute cupsUIResolver Cash1Off "*CashDrawer1PulseOff None" + + Installable "OptionCash2/Cash drawer 2" + UIConstraints "*CashDrawer2Setting *OptionCash2 False" + // UIConstraints "*CashDrawer2PulseOn *OptionCash2 False" + // UIConstraints "*CashDrawer2PulseOff *OptionCash2 False" + + Installable "OptionCutter/Cutter" + UIConstraints "*CutMedia *OptionCutter False" + +// Attribute cupsUIConstraints CutterOff "*OptionCutter False *CutMedia" +// Attribute cupsUIResolver CutterOff "*CutMedia None" + + +Option "Resolution/Resolution" PickOne AnySetup 10 +*Choice "203x203dpi/203 DPI Grayscale" "<>setpagedevice" + +HWMargins 14 0 14 0 + +// 58mm printers +{ + #define POINTS 164 + #define PIXELS 384 + + // model num is used by filter to determine raster width. 384 for 48mm, 560 for 70mm + ModelNumber $PIXELS + MinSize $POINTS 56 + MaxSize $POINTS 9286 + + *CustomMedia "X48MMY65MM/58mm x 65mm" $POINTS 182 14 0 14 0 "<>setpagedevice" "<>setpagedevice" + CustomMedia "X48MMY105MM/58mm x 105mm" $POINTS 298 14 0 14 0 "<>setpagedevice" "<>setpagedevice" + CustomMedia "X48MMY210MM/58mm x 210mm" $POINTS 595 14 0 14 0 "<>setpagedevice" "<>setpagedevice" + CustomMedia "X48MMY297MM/58mm x 297mm" $POINTS 842 14 0 14 0 "<>setpagedevice" "<>setpagedevice" + CustomMedia "X48MMY3276MM/58mm x 3276mm" $POINTS 9286 14 0 14 0 "<>setpagedevice" "<>setpagedevice" + + // Zijiang ZJ-58 + { + Manufacturer "Zijiang" + ModelName "ZJ-58" + PCFileName "zj58.ppd" + Attribute "NickName" "" "Zijiang ZJ-58" + Attribute "ShortNickName" "" "ZJ-58" + Attribute "Product" "" "(zj-58)" + Attribute "1284DeviceID" "" "MFG:Zijiang;CMD:Zijiang;MDL:ZJ-58;CLS:PRINTER;" + } + + // XPrinter XP-58 + { + Manufacturer "J-speed" + ModelName "XP-58" + PCFileName "xp58.ppd" + Attribute "NickName" "" "J-speed XP-58" + Attribute "ShortNickName" "" "XP-58" + Attribute "Product" "" "(xp-58)" + Attribute "1284DeviceID" "" "MFG:J-speed;CMD:Xprinter;MDL:XP-58;CLS:PRINTER;" + } +} + +// 80mm printers +{ + #define POINTS 226 + #define PIXELS 560 + // model num is used by filter to determine raster width. 58 -> 0x180, 80 -> 0x240. + ModelNumber $PIXELS + MinSize $POINTS 56 + MaxSize $POINTS 9286 + + *CustomMedia "X70MMY65MM/80mm x 65mm" $POINTS 182 14 0 14 0 "<>setpagedevice" "<>setpagedevice" + CustomMedia "X70MMY105MM/80mm x 105mm" $POINTS 298 14 0 14 0 "<>setpagedevice" "<>setpagedevice" + CustomMedia "X70MMY210MM/80mm x 210mm" $POINTS 595 14 0 14 0 "<>setpagedevice" "<>setpagedevice" + CustomMedia "X70MMY297MM/80mm x 297mm" $POINTS 842 14 0 14 0 "<>setpagedevice" "<>setpagedevice" + CustomMedia "X70MMY3276MM/80mm x 3276mm" $POINTS 9286 14 0 14 0 "<>setpagedevice" "<>setpagedevice" + + // Zijiang ZJ-80 + { + Manufacturer "Zijiang" + ModelName "ZJ-80" + PCFileName "zj80.ppd" + Attribute "NickName" "" "Zijiang ZJ-80" + Attribute "ShortNickName" "" "ZJ-80" + Attribute "Product" "" "(zj-80)" + Attribute "1284DeviceID" "" "MFG:Zijiang;CMD:Zijiang;MDL:ZJ-80;CLS:PRINTER;" + } + + // Epson TM-T20 + { + Manufacturer "Epson" + ModelName "TM-T20" + PCFileName "tm20.ppd" + Attribute "NickName" "" "Epson TM-T20" + Attribute "ShortNickName" "" "TM-T20" + Attribute "Product" "" "(TM-T20)" + Attribute "1MFG:Epson;CMD:Epson;MDL:TMT20;CLS:PRINTER;" + } +} +