Wed, 05 Aug 2009 15:04:55 +0100
Fixed printing so uncompressed mode is no longer used; now sends an uncompressed Packbits stream instead.
Added SetOption and GetOption, so can now turn autocut and mirror on and off. Defaults to both off after init.
src/ptouch.c | file | annotate | diff | revisions | |
src/ptouch.h | file | annotate | diff | revisions |
1.1 diff -r a933b13e087f -r 088286f9e1e4 src/ptouch.c 1.2 --- a/src/ptouch.c Wed Aug 05 15:02:31 2009 +0100 1.3 +++ b/src/ptouch.c Wed Aug 05 15:04:55 2009 +0100 1.4 @@ -11,6 +11,10 @@ 1.5 // TODO: disable 1.6 #define DEBUG 1.7 1.8 +// This debug option forces Request Status to always "see" a good status 1.9 +// block. Mostly useful for testing using write-to-file mode. 1.10 +#define DEBUG_SKIP_STATUS_READ 1.11 + 1.12 #include <stdio.h> 1.13 #include <stdlib.h> 1.14 #include <stdbool.h> 1.15 @@ -56,6 +60,18 @@ 1.16 1.17 int pt_GetStatus(pt_Device *dev) 1.18 { 1.19 +#ifdef DEBUG_SKIP_STATUS_READ 1.20 + unsigned char buf[32]; 1.21 + memset(buf, 0x00, 32); 1.22 + buf[0] = 0x80; 1.23 + buf[1] = 0x20; 1.24 + buf[2] = 0x42; 1.25 + buf[3] = 0x30; 1.26 + buf[4] = 0x4b; 1.27 + buf[5] = 0x30; 1.28 + buf[10] = 0x0c; 1.29 + buf[11] = 0x01; 1.30 +#else 1.31 // REQUEST STATUS 1.32 fprintf(dev->fp, "%c%c%c", ESC, 'i', 'S'); 1.33 1.34 @@ -71,6 +87,7 @@ 1.35 // Timeout 1.36 return PT_ERR_TIMEOUT; 1.37 } 1.38 +#endif 1.39 1.40 #ifdef DEBUG 1.41 printf("DEBUG: Printer status buffer = \n"); 1.42 @@ -104,16 +121,60 @@ 1.43 dev->pixelWidth = ((dev->mediaWidth * 180 * 10) / 254) - 2; 1.44 } 1.45 1.46 + // Set printing parameters to defaults -- 1.47 + // Mirror off 1.48 + // Autocut on 1.49 + dev->mirror = false; 1.50 + dev->autocut = false; 1.51 + 1.52 // Operation succeeded 1.53 return PT_ERR_SUCCESS; 1.54 } 1.55 1.56 -// TODO: print options struct parameter (e.g. fullcut, halfcut, print res, ...) 1.57 -// 1.58 -// 1.59 +int pt_SetOption(pt_Device *dev, PT_E_OPTION option, int value) 1.60 +{ 1.61 + // trap dev == NULL 1.62 + if (dev == NULL) { 1.63 + return PT_ERR_BAD_PARAMETER; 1.64 + } 1.65 + 1.66 + // set option 1.67 + switch(option) { 1.68 + case PT_OPTION_MIRROR: // Mirror 1.69 + dev->mirror = (value ? 1 : 0); 1.70 + return PT_ERR_SUCCESS; 1.71 + 1.72 + case PT_OPTION_AUTOCUT: // Auto-cutter enable/disable 1.73 + dev->autocut = (value ? 1 : 0); 1.74 + return PT_ERR_SUCCESS; 1.75 + 1.76 + default: 1.77 + return PT_ERR_BAD_PARAMETER; 1.78 + } 1.79 +} 1.80 1.81 -// labels: 1 or more labels 1.82 -// count: number of labels, 0<count<MAXINT 1.83 +int pt_GetOption(pt_Device *dev, PT_E_OPTION option, int *value) 1.84 +{ 1.85 + // trap dev == NULL or value == NULL 1.86 + if ((dev == NULL) || (value == NULL)) { 1.87 + return PT_ERR_BAD_PARAMETER; 1.88 + } 1.89 + 1.90 + // get option value 1.91 + switch(option) { 1.92 + case PT_OPTION_MIRROR: // Mirror 1.93 + *value = dev->mirror; 1.94 + return PT_ERR_SUCCESS; 1.95 + 1.96 + case PT_OPTION_AUTOCUT: // Auto-cutter enable/disable 1.97 + *value = dev->autocut; 1.98 + return PT_ERR_SUCCESS; 1.99 + 1.100 + default: 1.101 + return PT_ERR_BAD_PARAMETER; 1.102 + } 1.103 +} 1.104 + 1.105 int pt_Print(pt_Device *dev, gdImagePtr *labels, int count) 1.106 { 1.107 int err; 1.108 @@ -159,9 +220,11 @@ 1.109 1.110 // M {n1} -- Set Compression Mode 1.111 // {n1} = 0x00 ==> no compression 1.112 + // Doesn't seem to work on the PT-2450DX... 1.113 // {n1} = 0x01 ==> reserved 1.114 // {n1} = 0x02 ==> TIFF/Packbits 1.115 - fprintf(dev->fp, "M%c", 0x00); 1.116 + // But this works fine on the PT-2450DX... 1.117 + fprintf(dev->fp, "M%c", 0x02); 1.118 1.119 // Loop over the images that were passed in 1.120 for (int imnum=0; imnum < count; imnum++) { 1.121 @@ -170,10 +233,15 @@ 1.122 return PT_ERR_LABEL_TOO_WIDE; 1.123 } 1.124 1.125 - // 1.126 - // TODO: trap image height / width == 0? 1.127 - // will libgd allow an image with a zero dimension? 1.128 - // 1.129 + // Trap a label with a width of zero 1.130 + // I'm not sure if this can happen, but it's a single if statement, so 1.131 + // probably worth checking anyway... 1.132 + if (gdImageSX(*curLabel) == 0) { 1.133 + return PT_ERR_LABEL_ZERO_LENGTH; 1.134 + } 1.135 + 1.136 + // Get the index of the colour "white" (RGB:255,255,255) in the Gd image 1.137 + int col_white = gdImageColorResolve(*curLabel, 255, 255, 255); 1.138 1.139 // Iterate left-to-right over the source image 1.140 for (int xpos = 0; xpos < gdImageSX(*curLabel); xpos++) { 1.141 @@ -185,12 +253,12 @@ 1.142 1.143 // Calculate left-side margin for this label size 1.144 // Again, 128-dot printhead. 1.145 - int margin = (128 + dev->pixelWidth) / 2; 1.146 + int margin = (128 / 2) - (dev->pixelWidth / 2); 1.147 1.148 // Copy data from the image to the bit-buffer 1.149 for (int ypos = 0; ypos < gdImageSY(*curLabel); ypos++) { 1.150 - // Get pixel from gd, is it white (palette entry 0)? 1.151 - if (gdImageGetPixel(*curLabel, xpos, ypos) != 0) { 1.152 + // Get pixel from gd, is it white? 1.153 + if (gdImageGetPixel(*curLabel, xpos, ypos) != col_white) { 1.154 // No. Set the bit. 1.155 int bit = 1 << (7 - ((margin+ypos) % 8)); 1.156 bitbuf[(margin+ypos) / 8] |= bit; 1.157 @@ -211,7 +279,15 @@ 1.158 // Row is not clear -- send the pixel data 1.159 // 1.160 // TODO: the printer supports Packbits compression. Implement! 1.161 - fprintf(dev->fp, "G"); 1.162 + // TODO: After Packbits is implemented, ((128/8)+1) must be 1.163 + // changed to the length of the Packbits compressed data. 1.164 + // (note: 128/8 is the printhead size in bytes, the +1 is for 1.165 + // the control byte we add below...) 1.166 + fprintf(dev->fp, "G%c%c", ((128/8)+1) & 0xff, ((128/8)+1) >> 8); 1.167 + 1.168 + // This printer asks for Packbits compressed data. In this 1.169 + // case, we send a "run of N" control byte and fake it... 1.170 + fputc(sizeof(bitbuf) - 1, dev->fp); 1.171 for (int i=0; i<sizeof(bitbuf); i++) { 1.172 fputc(bitbuf[i], dev->fp); 1.173 }
2.1 diff -r a933b13e087f -r 088286f9e1e4 src/ptouch.h 2.2 --- a/src/ptouch.h Wed Aug 05 15:02:31 2009 +0100 2.3 +++ b/src/ptouch.h Wed Aug 05 15:04:55 2009 +0100 2.4 @@ -59,13 +59,25 @@ 2.5 /// Label image is too large for this label tape 2.6 PT_ERR_LABEL_TOO_WIDE = -3, 2.7 2.8 +/// Label has a length of zero 2.9 + PT_ERR_LABEL_ZERO_LENGTH = -4, 2.10 + 2.11 /// Printer is not ready 2.12 - PT_ERR_PRINTER_NOT_READY = -4 2.13 + PT_ERR_PRINTER_NOT_READY = -5 2.14 }; 2.15 2.16 +/* 2.17 + * Job options 2.18 + */ 2.19 +typedef enum { 2.20 +/// Mirror -- mirror the printed label along the long edge 2.21 + PT_OPTION_MIRROR, 2.22 +/// Auto-cutter -- enable or disable automatic label cutting 2.23 + PT_OPTION_AUTOCUT 2.24 +} PT_E_OPTION; 2.25 2.26 /** 2.27 - * @brief Initialise the printer 2.28 + * @brief Initialise the printer. 2.29 * 2.30 * Initialises the printer and returns a pointer to a pt_Device struct 2.31 * describing it. 2.32 @@ -77,7 +89,7 @@ 2.33 pt_Device *pt_Initialise(char *path); 2.34 2.35 /** 2.36 - * @brief Close a printer device 2.37 + * @brief Close a printer device. 2.38 * 2.39 * Closes the connection to the printer, and destroys the pt_Device struct. 2.40 * 2.41 @@ -86,7 +98,7 @@ 2.42 void pt_Close(pt_Device *dev); 2.43 2.44 /** 2.45 - * @brief Get the current status of the printer 2.46 + * @brief Get the current status of the printer. 2.47 * 2.48 * Queries the printer for its current status, then returns the result. 2.49 * 2.50 @@ -97,7 +109,45 @@ 2.51 int pt_GetStatus(pt_Device *dev); 2.52 2.53 /** 2.54 - * @brief Print one or more labels 2.55 + * @brief Set a job option for the next print job. 2.56 + * 2.57 + * Sets a job option (specified by <b>option</b>) for the next print job. 2.58 + * These options include printer features like auto-cutting and mirroring 2.59 + * of the label image. 2.60 + * 2.61 + * @param dev A pt_Device struct created by pt_Initialise. 2.62 + * @param option One of the PT_OPTION_* constants specifying the parameter 2.63 + * that is to be set. 2.64 + * @param value The value to assign to the job option. 2.65 + * @return <b>PT_ERR_BAD_PARAMETER:</b> Either <b>dev</b> was equal to NULL, 2.66 + * or the option value specified in <b>option</b> was invalid.<br> 2.67 + * <b>PT_ERR_SUCCESS:</b> Operation completed successfully, the current value 2.68 + * of the option parameter is now set to the contents of <b>value</b>. 2.69 + */ 2.70 +int pt_SetOption(pt_Device *dev, PT_E_OPTION option, int value); 2.71 + 2.72 +/** 2.73 + * @brief Get the current value of a job option for the next print job. 2.74 + * 2.75 + * Returns the current value of a job option (specified by <b>option</b>) 2.76 + * for the next print job. 2.77 + * These options include printer features like auto-cutting and mirroring 2.78 + * of the label image. 2.79 + * 2.80 + * @param dev A pt_Device struct created by pt_Initialise. 2.81 + * @param option One of the PT_OPTION_* constants specifying the parameter 2.82 + * that is to be returned. 2.83 + * @param value A pointer to an <b>int</b> that will contain the value 2.84 + * of the job option. 2.85 + * @return <b>PT_ERR_BAD_PARAMETER:</b> Either <b>dev</b> or <b>value</b> was 2.86 + * equal to NULL, or the option value specified in <b>option</b> was invalid.<br> 2.87 + * <b>PT_ERR_SUCCESS:</b> Operation completed successfully, the current value 2.88 + * of the option parameter is now stored in <b>value</b>. 2.89 + */ 2.90 +int pt_GetOption(pt_Device *dev, PT_E_OPTION option, int *value); 2.91 + 2.92 +/** 2.93 + * @brief Print one or more labels. 2.94 * 2.95 * Takes a pointer to an array of Libgd images, and prints each of them. 2.96 *