/* ptouch-print - Print labels with images or text on a Brother P-Touch Copyright (C) 2015-2019 Dominic Radermacher This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 3 as published by the Free Software Foundation 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include /* printf() */ #include /* exit(), malloc() */ #include #include /* strcmp(), memcmp() */ #include /* open() */ #include /* open() */ #include /* open() */ #include //#include "config.h" #include #include "gettext.h" /* gettext(), ngettext() */ #include "ptouch.h" #define _(s) gettext(s) #define MAX_LINES 4 /* maybe this should depend on tape size */ gdImage *image_load(const char *file); void rasterline_setpixel(uint8_t* rasterline, size_t size, int pixel); int get_baselineoffset(char *text, char *font, int fsz); int find_fontsize(int want_px, char *font, char *text); int needed_width(char *text, char *font, int fsz); int print_img(ptouch_dev ptdev, gdImage *im); int write_png(gdImage *im, const char *file); gdImage *img_append(gdImage *in_1, gdImage *in_2); gdImage *img_cutmark(int tape_width); gdImage *render_text(char *font, char *line[], int lines, int tape_width); void unsupported_printer(ptouch_dev ptdev); void usage(char *progname); int parse_args(int argc, char **argv); // char *font_file="/usr/share/fonts/TTF/Ubuntu-M.ttf"; // char *font_file="Ubuntu:medium"; char *font_file="DejaVuSans"; char *save_png=NULL; int verbose=0; int fontsize=0; bool debug=false; /* -------------------------------------------------------------------- -------------------------------------------------------------------- */ void rasterline_setpixel(uint8_t* rasterline, size_t size, int pixel) { // TODO: pixel should be unsigned, since we can't have negative // if (pixel > ptdev->devinfo->device_max_px) { if (pixel > (int)(size*8)) { return; } rasterline[(size-1)-(pixel/8)] |= (uint8_t)(1<<(pixel%8)); return; } int print_img(ptouch_dev ptdev, gdImage *im) { int d,i,k,offset,tape_width; uint8_t rasterline[(ptdev->devinfo->max_px)/8]; if (!im) { printf(_("nothing to print\n")); return -1; } tape_width=ptouch_get_tape_width(ptdev); /* find out whether color 0 or color 1 is darker */ d=(gdImageRed(im,1)+gdImageGreen(im,1)+gdImageBlue(im,1) < gdImageRed(im,0)+gdImageGreen(im,0)+gdImageBlue(im,0))?1:0; if (gdImageSY(im) > tape_width) { printf(_("image is too large (%ipx x %ipx)\n"), gdImageSX(im), gdImageSY(im)); printf(_("maximum printing width for this tape is %ipx\n"), tape_width); return -1; } offset=64-(gdImageSY(im)/2); /* always print centered */ if ((ptdev->devinfo->flags & FLAG_RASTER_PACKBITS) == FLAG_RASTER_PACKBITS) { if (debug) { printf("enable PackBits mode\n"); } ptouch_enable_packbits(ptdev); } if (ptouch_rasterstart(ptdev) != 0) { printf(_("ptouch_rasterstart() failed\n")); return -1; } for (k=0; k 0) { fsz=fontsize; printf(_("setting font size=%i\n"), fsz); } else { for (i=0; i x) { x=tmp; } } im=gdImageCreatePalette(x, tape_width); gdImageColorAllocate(im, 255, 255, 255); black=gdImageColorAllocate(im, 0, 0, 0); /* gdImageStringFT(im,brect,fg,fontlist,size,angle,x,y,string) */ /* find max needed line height for ALL lines */ int max_height=0; for (i=0; i max_height) { max_height=lineheight; } } if (debug) { printf("debug: needed (max) height is %ipx\n", max_height); } /* now render lines */ for (i=0; i width) { width=gdImageSY(in_2); } } if ((width == 0) || (length == 0)) { return NULL; } out=gdImageCreatePalette(length, width); if (out == NULL) { return NULL; } gdImageColorAllocate(out, 255, 255, 255); gdImageColorAllocate(out, 0, 0, 0); if (debug) { printf("debug: created new img with size %d * %d\n", length, width); } if (in_1 != NULL) { gdImageCopy(out, in_1, 0, 0, 0, 0, gdImageSX(in_1), gdImageSY(in_1)); if (debug) { printf("debug: copied part 1\n"); } } if (in_2 != NULL) { gdImageCopy(out, in_2, i_1_x, 0, 0, 0, gdImageSX(in_2), gdImageSY(in_2)); if (debug) { printf("copied part 2\n"); } } return out; } gdImage *img_cutmark(int tape_width) { gdImage *out=NULL; int style_dashed[6]; out=gdImageCreatePalette(9, tape_width); if (out == NULL) { return NULL; } gdImageColorAllocate(out, 255, 255, 255); int black=gdImageColorAllocate(out, 0, 0, 0); style_dashed[0]=gdTransparent; style_dashed[1]=gdTransparent; style_dashed[2]=gdTransparent; style_dashed[3]=black; style_dashed[4]=black; style_dashed[5]=black; gdImageSetStyle(out, style_dashed, 6); gdImageLine(out, 5, 0, 5, tape_width-1, gdStyled); return out; } gdImage *img_padding(int tape_width, int length) { gdImage *out=NULL; if ((length < 1) || (length > 256)) { length=1; } out=gdImageCreatePalette(length, tape_width); if (out == NULL) { return NULL; } gdImageColorAllocate(out, 255, 255, 255); return out; } void usage(char *progname) { printf("usage: %s [options] \n", progname); printf("options:\n"); printf("\t--font \t\tuse font or \n"); printf("\t--writepng \tinstead of printing, write output to png file\n"); printf("\t\t\t\tThis currently works only when using\n\t\t\t\tEXACTLY ONE --text statement\n"); printf("print-commands:\n"); printf("\t--image \t\tprint the given image which must be a 2 color\n"); printf("\t\t\t\t(black/white) png\n"); printf("\t--text \t\tPrint 1-4 lines of text.\n"); printf("\t\t\t\tIf the text contains spaces, use quotation marks\n\t\t\t\taround it.\n"); printf("\t--cutmark\t\tPrint a mark where the tape should be cut\n"); printf("\t--fontsize\t\tManually set fontsize\n"); printf("\t--pad \t\tAdd n pixels padding (blank tape)\n"); exit(1); } /* here we don't print anything, but just try to catch syntax errors */ int parse_args(int argc, char **argv) { int lines, i; for (i=1; i= argc) || (argv[i+1][0] == '-')) { break; } i++; } } else if (strcmp(&argv[i][1], "-version") == 0) { printf(_("ptouch-print version %s by Dominic Radermacher\n"), VERSION); exit(0); } else { usage(argv[0]); } } return i; } int main(int argc, char *argv[]) { int i, lines = 0, tape_width; char *line[MAX_LINES]; gdImage *im=NULL; gdImage *out=NULL; ptouch_dev ptdev=NULL; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); i=parse_args(argc, argv); if (i != argc) { usage(argv[0]); } if ((ptouch_open(&ptdev)) < 0) { return 5; } if (ptouch_init(ptdev) != 0) { printf(_("ptouch_init() failed\n")); } if (ptouch_getstatus(ptdev) != 0) { printf(_("ptouch_getstatus() failed\n")); return 1; } tape_width=ptouch_get_tape_width(ptdev); for (i=1; istatus->media_type); printf("media width = %d mm\n", ptdev->status->media_width); printf("tape color = %02x\n", ptdev->status->tape_color); printf("text color = %02x\n", ptdev->status->text_color); printf("error = %04x\n", ptdev->status->error); exit(0); } else if (strcmp(&argv[i][1], "-image") == 0) { if ((im=image_load(argv[++i])) == NULL) { printf(_("failed to load image file\n")); return 1; } out=img_append(out, im); gdImageDestroy(im); im = NULL; } else if (strcmp(&argv[i][1], "-text") == 0) { for (lines=0; (lines < MAX_LINES) && (i < argc); lines++) { if ((i+1 >= argc) || (argv[i+1][0] == '-')) { break; } i++; line[lines]=argv[i]; } if (lines) { if ((im=render_text(font_file, line, lines, tape_width)) == NULL) { printf(_("could not render text\n")); return 1; } out=img_append(out, im); gdImageDestroy(im); im = NULL; } } else if (strcmp(&argv[i][1], "-cutmark") == 0) { im=img_cutmark(tape_width); out=img_append(out, im); gdImageDestroy(im); im = NULL; } else if (strcmp(&argv[i][1], "-pad") == 0) { int length=strtol(argv[++i], NULL, 10); im=img_padding(tape_width, length); out=img_append(out, im); gdImageDestroy(im); im = NULL; } else if (strcmp(&argv[i][1], "-debug") == 0) { debug = true; } else { usage(argv[0]); } } if (out) { if (save_png) { write_png(out, save_png); } else { print_img(ptdev, out); if (ptouch_eject(ptdev) != 0) { printf(_("ptouch_eject() failed\n")); return -1; } } gdImageDestroy(out); } if (im != NULL) { gdImageDestroy(im); } ptouch_close(ptdev); libusb_exit(NULL); return 0; }