// To get required headers, run // sudo apt-get install libcups2-dev libcupsimage2-dev #include #include #include #include #include #include // uncomment next line in order to have verbose dump in DEBUGFILE // after print //#define DEBUGP #define DEBUGFILE "/tmp/debugraster.txt" struct settings_ { int cashDrawer1; int cashDrawer2; int blankSpace; int feedDist; }; struct settings_ settings; struct command { int length; char* command; }; // define printer initialize command static const struct command printerInitializeCommand = {2,(char[2]){0x1b,0x40}}; // define cashDrawerEjector command static const struct command cashDrawerEject [2] = {{5,(char[5]){0x1b,0x70,0,0x40,0x50}}, {5,(char[5]){0x1b,0x70,1,0x40,0x50}}}; // define raster mode start command static const struct command rasterModeStartCommand = {4,(char[4]){0x1d,0x76,0x30,0}}; #ifdef DEBUGP FILE* lfd = 0; #endif // putchar with debug wrapper inline void mputchar(char c) { unsigned char m = c; #ifdef DEBUGP if (lfd) fprintf (lfd,"%02x ",m); #endif putchar(m); } // procedure to output an array inline void outputarray(const char * array, int length) { int i = 0; for (;i>8); } // enter raster mode and set up x and y dimensions inline void rasterheader(int xsize, int ysize) { outputCommand(rasterModeStartCommand); mputchar(lo(xsize)); mputchar(hi(xsize)); mputchar(lo(ysize)); mputchar(hi(ysize)); } // print all unprinted (i.e. flush the buffer) // then feed given number of lines inline void skiplines(int size) { mputchar(0x1b); mputchar(0x4a); mputchar(size); } // get an option inline int getOptionChoiceIndex(const char * choiceName, ppd_file_t * ppd) { ppd_choice_t * choice; ppd_option_t * option; choice = ppdFindMarkedChoice(ppd, choiceName); if (choice == NULL) { if ((option = ppdFindOption(ppd, choiceName)) == NULL) return -1; if ((choice = ppdFindChoice(option,option->defchoice)) == NULL) return -1; } return atoi(choice->choice); } void initializeSettings(char * commandLineOptionSettings) { ppd_file_t * ppd = NULL; cups_option_t * options = NULL; int numOptions = 0; ppd = ppdOpenFile(getenv("PPD")); ppdMarkDefaults(ppd); numOptions = cupsParseOptions(commandLineOptionSettings, 0, &options); if ((numOptions != 0) && (options != NULL)) { cupsMarkOptions(ppd, numOptions, options); cupsFreeOptions(numOptions, options); } 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); ppdClose(ppd); } // 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); } // 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); } // sent at the end of every page #ifndef __sighandler_t typedef void (*__sighandler_t) (int); #endif __sighandler_t old_signal; void EndPage() { int i; for (i=0; i 7) { fputs("ERROR: rastertozj job-id user title copies options [file]\n", stderr); return EXIT_FAILURE; } 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 initializeSettings(argv[5]); jobSetup(); ras = cupsRasterOpen(fd, CUPS_RASTER_READ); page = 0; while (cupsRasterReadHeader2(ras, &header)) { if ((header.cupsHeight == 0) || (header.cupsBytesPerLine == 0)) break; #ifdef DEBUGP if (lfd) fprintf(lfd,"\nheader.cupsHeight=%d, header.cupsBytesPerLine=%d\n",header.cupsHeight,header.cupsBytesPerLine); #endif 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 } fprintf(stderr, "PAGE: %d %d\n", ++page, header.NumCopies); pageSetup(); int foo = ( header.cupsWidth > 0x180 ) ? 0x180 : header.cupsWidth; foo = (foo+7) & 0xFFFFFFF8; int width_size = foo >> 3; #ifdef DEBUGP if (lfd) fprintf(lfd,"\nheader.cupsWidth=%d, foo=%d, width_size=%d\n",header.cupsWidth,foo,width_size); #endif y = 0; 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)); int rest = header.cupsHeight-y; if (rest>24) rest=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_bytes) { ++zeroy; continue; } for (;zeroy>0;--zeroy) skiplines(24); rasterheader(width_size,rest); outputarray((char*)rasterData,width_size*24); skiplines(0); } if (!settings.blankSpace) for(;zeroy>0;--zeroy) skiplines(24); EndPage(); } ShutDown(); if (originalRasterDataPtr != NULL) free(originalRasterDataPtr); cupsRasterClose(ras); if (fd != 0) close(fd); if (page == 0) fputs("ERROR: No pages found!\n", stderr); else fputs("INFO: Ready to print.\n", stderr); #ifdef DEBUGP if (lfd) fclose(lfd); #endif return (page == 0)?EXIT_FAILURE:EXIT_SUCCESS; } // end of rastertozj.c