diff --git a/CMakeLists.txt b/CMakeLists.txt index 6181756..82de494 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -80,7 +80,7 @@ if ( APPLE ) # 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} "${PPDPATH}" ) + install ( FILES ${PPDS} DESTINATION "${PPDPATH}" ) # install ( CODE "EXECUTE_PROCESS(COMMAND /etc/init.d/cups start)" ) elseif ( UNIX ) set ( FILTERPATH "usr/lib/cups/filter" ) diff --git a/rastertozj.c b/rastertozj.c index f2a9a92..0115fbc 100644 --- a/rastertozj.c +++ b/rastertozj.c @@ -12,6 +12,12 @@ #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; @@ -38,6 +44,8 @@ static void initializeSettings(char *commandLineOptionSettings, struct settings_ ppd_file_t *pPpd = ppdOpenFile(getenv("PPD")); ppdMarkDefaults(pPpd); + // char* sDestination = getenv("DestinationPrinterID"); + cups_option_t *pOptions = NULL; int iNumOptions = cupsParseOptions(commandLineOptionSettings, 0, &pOptions); if (iNumOptions && pOptions) { @@ -151,16 +159,26 @@ static inline void sendRasterHeader(int xsize, int ysize) { mputnum(ysize); } +static inline void flushLines(unsigned short lines) +{ + SendCommand(escFlush); + mputchar (lines); +} + // print all unprinted (i.e. flush the buffer) static inline void flushBuffer() { - SendCommand(escFlush); - mputchar(0); + flushLines(0); } // flush, then feed 24 lines -static inline void flushAndFeed() { - SendCommand(escFlush); - mputchar(0x18); +static inline void flushManyLines(int iLines) +{ + while ( iLines ) + { + int iStride = min (iLines, 24); + flushLines ( iStride ); + iLines -= iStride; + } } // sent on the beginning of print job @@ -178,7 +196,7 @@ void finalizeJob() { SendCommand(escCashDrawer1Eject); if (settings.cashDrawer2 == 2) SendCommand(escCashDrawer2Eject); - SendCommand(escInit); +// SendCommand(escInit); } // sent at the end of every page @@ -188,9 +206,6 @@ typedef void (*__sighandler_t)(int); __sighandler_t old_signal; void finishPage() { - int i; - for (i = 0; i < settings.feedDist; ++i) - flushAndFeed(); signal(15, old_signal); } @@ -200,18 +215,11 @@ void cancelJob() { for (; i < 0x258; ++i) mputchar(0); finishPage(); - finalizeJob(); } // invoked before starting to print a page void startPage() { old_signal = signal(15, cancelJob); } -static inline int min(int a, int b) { - if (a > b) - return b; - return a; -} - void DebugPrintHeader (cups_page_header2_t* pHeader) { DEBUGPRINT( @@ -304,9 +312,9 @@ void DebugPrintHeader (cups_page_header2_t* pHeader) } // rearrange (compress) rows in pBuf, discarding tails of them -unsigned compress_buffer(unsigned char *pBuf, unsigned iSize, +static inline unsigned compress_buffer(unsigned char *pBuf, unsigned iSize, unsigned int iWideStride, unsigned int iStride) { - unsigned char *pEnd = pBuf + iSize; + const unsigned char *pEnd = pBuf + iSize; unsigned char *pTarget = pBuf; while (pBuf < pEnd) { int iBytes = min(pEnd - pBuf, iStride); @@ -318,7 +326,7 @@ unsigned compress_buffer(unsigned char *pBuf, unsigned iSize, } // returns -1 if whole line iz filled by zeros. Otherwise 0. -int line_iz_empty(const unsigned char *pBuf, unsigned iSize) { +static inline int line_is_empty(const unsigned char *pBuf, unsigned iSize) { int i; for (i = 0; i < iSize; ++i) if (pBuf[i]) @@ -326,6 +334,25 @@ int line_iz_empty(const unsigned char *pBuf, unsigned iSize) { return -1; } +static inline void send_raster(const unsigned char *pBuf, int width8, + int height) { + if (!height) + return; + sendRasterHeader(width8, height); + outputarray((char *)pBuf, width8 * height); +} + +#define EXITPRINT(CODE) \ + { \ + if (pRasterSrc) \ + cupsRasterClose(pRasterSrc); \ + if (pRasterBuf) \ + free(pRasterBuf); \ + if (fd) \ + close(fd); \ + return (CODE); \ + } + ////////////////////////////////////////////// ////////////////////////////////////////////// int main(int argc, char *argv[]) { @@ -345,9 +372,6 @@ int main(int argc, char *argv[]) { } DEBUGSTARTPRINT(); - - - int iCurrentPage = 0; // CUPS Page tHeader cups_page_header2_t tHeader; @@ -378,12 +402,8 @@ int main(int argc, char *argv[]) { if (!pRasterBuf) { pRasterBuf = malloc(tHeader.cupsBytesPerLine * 24); - if (!pRasterBuf) { // hope it never goes here... - cupsRasterClose(pRasterSrc); - if (fd) - close(fd); - return EXIT_FAILURE; - } + if (!pRasterBuf) // hope it never goes here... + EXITPRINT(EXIT_FAILURE) } fprintf(stderr, "PAGE: %d %d\n", ++iCurrentPage, tHeader.NumCopies); @@ -415,71 +435,67 @@ int main(int argc, char *argv[]) { iRowsToPrint -= iBlockHeight; unsigned iBytesChunk = 0; + // first, fetch whole block from the image if (iBlockHeight) iBytesChunk = cupsRasterReadPixels( pRasterSrc, pRasterBuf, tHeader.cupsBytesPerLine * iBlockHeight); - if (iBytesChunk && width_bytes < tHeader.cupsBytesPerLine) + // if original image is wider - rearrange buffer so that our calculated + // lines come one-by-one without extra gaps + if (width_bytes < tHeader.cupsBytesPerLine) iBytesChunk = compress_buffer(pRasterBuf, iBytesChunk, - tHeader.cupsBytesPerLine, width_bytes ); + tHeader.cupsBytesPerLine, width_bytes); + + // runaround for sometimes truncated output of cupsRasterReadPixels + if (iBytesChunk < width_bytes * iBlockHeight) { + memset(pRasterBuf + iBytesChunk, 0, + width_bytes * iBlockHeight - iBytesChunk); + iBytesChunk = width_bytes * iBlockHeight; + } + // 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; - unsigned char *pEnd = pBuf + iBytesChunk; + const unsigned char *pEnd = pBuf + iBytesChunk; int nonzerolines = 0; - for (; iBlockHeight; --iBlockHeight) { - if (line_iz_empty(pBuf, width_bytes)) - { - if (nonzerolines) // time to flush - } + while ( pBuf= rest_bytes) { // true, if whole block iz zeroes - ++zeroy; - continue; - } - - for (; zeroy > 0; --zeroy) - flushAndFeed(); - - sendRasterHeader(width_bytes, iBlockHeight); - outputarray((char *)pRasterBuf, rest_bytes); + send_raster(pChunk, width_bytes, nonzerolines); flushBuffer(); - } + } // loop over page + // page is finished. + // m.b. we have to print empty tail at the end if (settings.blankSpace) - for (; zeroy > 0; --zeroy) - flushAndFeed(); + flushManyLines (zeroy); + flushManyLines(settings.feedDist * 24); finishPage(); } finalizeJob(); - if (pRasterBuf) - free(pRasterBuf); - cupsRasterClose(pRasterSrc); - if (fd) - close(fd); fputs(iCurrentPage ? "INFO: Ready to print.\n" : "ERROR: No pages found!\n", stderr); DEBUGFINISHPRINT(); - return iCurrentPage ? EXIT_SUCCESS : EXIT_FAILURE; + EXITPRINT(iCurrentPage ? EXIT_SUCCESS : EXIT_FAILURE) } // end of rastertozj.c