diff options
author | Fritz Elfert <felfert@to.com> | 2002-03-03 23:55:35 +0000 |
---|---|---|
committer | Fritz Elfert <felfert@to.com> | 2002-03-03 23:55:35 +0000 |
commit | 7b84391212adfa3b7f9fc5da1d3a3a5861023236 (patch) | |
tree | 3eb99bcbe05e7b6d08a5d598057c58c4648b21fa /plpprint/plpprintd.cc | |
parent | 5a374c616d8157c78bfbfb162ffbc30ba7681cf0 (diff) | |
download | plptools-7b84391212adfa3b7f9fc5da1d3a3a5861023236.tar.gz plptools-7b84391212adfa3b7f9fc5da1d3a3a5861023236.tar.bz2 plptools-7b84391212adfa3b7f9fc5da1d3a3a5861023236.zip |
- Added first version of PostScript prolog
- Implemented page conversion (incomplete).
Diffstat (limited to 'plpprint/plpprintd.cc')
-rw-r--r-- | plpprint/plpprintd.cc | 571 |
1 files changed, 539 insertions, 32 deletions
diff --git a/plpprint/plpprintd.cc b/plpprint/plpprintd.cc index 7cf4006..9f32c22 100644 --- a/plpprint/plpprintd.cc +++ b/plpprint/plpprintd.cc @@ -36,6 +36,7 @@ #include <ppsocket.h> #include <wprt.h> +#include <psibitmap.h> #define _GNU_SOURCE #include <getopt.h> @@ -113,58 +114,564 @@ infolog(char *fmt, ...) return 0; } +static int minx, maxx, miny, maxy; +string usedfonts; + +typedef struct { + char *psifont; + bool bold; + bool italic; + char *psfont; +} fontmap_entry; + +#define FALLBACK_FONT "Courier" + +static fontmap_entry fontmap[] = { + { "Times New Roman", false, false, "Times-Roman"}, + { "Times New Roman", true, false, "Times-Bold"}, + { "Times New Roman", false, true, "Times-Italic"}, + { "Times New Roman", true, true, "Times-BoldItalic"}, + { "Arial", false, false, "Helvetica"}, + { "Arial", true, false, "Helvetica-Bold"}, + { "Arial", false, true, "Helvetica-Oblique"}, + { "Arial", true, true, "Helvetica-BoldOblique"}, + { "Courier New", false, false, "Courier"}, + { "Courier New", true, false, "Courier-Bold"}, + { "Courier New", false, true, "Courier-Oblique"}, + { "Courier New", true, true, "Courier-BoldOblique"}, + { "Swiss", false, false, "Courier"}, + { "Swiss", true, false, "Courier-Bold"}, + { "Swiss", false, true, "Courier-Oblique"}, + { "Swiss", true, true, "Courier-BoldOblique"}, + { NULL, false, false, NULL} +}; + +static void +ps_setfont(FILE *f, const char *fname, bool bold, bool italic, + unsigned long fsize) +{ + fontmap_entry *fe = fontmap; + char *psf = NULL; + while (fe->psifont) { + if ((!strcmp(fe->psifont, fname)) && + (fe->bold == bold) && + (fe->italic == italic)) { + psf = fe->psfont; + break; + } + fe++; + } + if (!psf) { + psf = FALLBACK_FONT; + errorlog("No font mapping for '%s' (%s%s%s); fallback to %s\n", + fname, (bold) ? "Bold" : "", (italic) ? "Italic" : "", + (bold || italic) ? "" : "Regular", psf); + } + if (usedfonts.find(psf) == usedfonts.npos) { + usedfonts += "%%+ font "; + usedfonts += psf; + usedfonts += "\n"; + } + fprintf(f, "%d /%s F\n", fsize, psf); +} + static void -convert_job(const char *jobname) +ps_escape(string &text) { - // ... To be done ... - unlink(jobname); + int pos = 0; + while ((pos = text.find_first_of("()", pos)) != text.npos) { + text.insert(pos, "\\"); + pos += 2; + } +} + +static void +ps_bitmap(FILE *f, int llx, int lly, int urx, int ury, const char *buf) +{ + bufferStore out; + int width, height; + if (decodeBitmap((const unsigned char *)buf, width, height, out)) { + fprintf(f, "%d %d %d %d I\n"); + const char *p = out.getString(0); + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) + fprintf(f, "%02x", *p++); + fprintf(f, "\n"); + } + } else + errorlog("Corrupted bitmap data"); +} + +static void +convertPage(FILE *f, int page, bool last, bufferStore buf) +{ + int len = buf.getLen(); + int i = 0; + long boffset = 0; + unsigned long left = 0; + unsigned long top = 0; + unsigned long right = 0; + unsigned long bottom = 0; + int lmargin = -1; + +#ifdef DEBUG + char dumpname[128]; + sprintf(dumpname, "/tmp/pdump_%d", page); + FILE *df = fopen(dumpname, "w"); + fwrite(buf.getString(0), 1, len, df); + fclose(df); + debuglog("Saved page input to %s\n", dumpname); +#endif + if (page == 0) { + time_t now = time(NULL); + fputs( + "%!PS-Adobe-3.0\n" + "%%Creator: plpprintd " VERSION "\n" + "%%CreationDate: ", f); + fputs(ctime(&now), f); + fputs( + "%%Pages: (atend)\n" + "%%BoundingBox: (atend)\n" + "%%DocumentNeededResources: (atend)\n" + "%%LanguageLvel: 2\n" + "%%EndComments\n" + "%%BeginProlog\n", f); + char pbuf[1024]; + FILE *pf = fopen(PKGDATA "/prolog.ps", "r"); + while (fgets(pbuf, sizeof(pbuf), pf)) + fputs(pbuf, f); + fclose(pf); + fputs( + "%%EndProlog\n" + "%%BeginSetup\n" + "currentpagedevice /PageSize get 1 get /top exch def\n" + "%%EndSetup\n", f); + minx = miny = 9999; + maxx = maxy = 0; + usedfonts = ""; + } + fprintf(f, "%%%%Page: %d %d\n", page+1, page+1); + while (i < len) { + unsigned char opcode = buf.getByte(i); + switch (opcode) { + case 0x00: { + // Start of section + unsigned long section = buf.getDWord(i+1); + fprintf(f, "%% @%d: Section %d\n", i, section); + // (section & 3) = + // 0 = Header, 1 = Body, 2 = Footer, 3 = Footer + i += 5; + } + break; + case 0x01: { + // End of page + i = len + 1; + } + break; + case 0x03: { + // ??? + fprintf(f, "%% @%d: U03 %d\n", i, buf.getByte(i+1)); + debuglog("@%d: U03 %d", i, buf.getByte(i+1)); + i += 2; + } + break; + case 0x04: { + // Bounding box + left = buf.getDWord(i+1); + top = buf.getDWord(i+5); + right = buf.getDWord(i+9); + bottom = buf.getDWord(i+13); + if (lmargin == -1) + lmargin = left; + if (left < minx) + minx = left; + if (right > maxx) + maxx = right; + if (top < miny) + miny = top; + if (bottom > maxy) + maxy = bottom; + i += 17; + fprintf(f, "%% @%d: bbox %d %d %d %d\n", i, left, top, right, + bottom); + } + break; + case 0x05: { + // ??? + fprintf(f, "%% @%d: U05\n", i); + debuglog("@%d: U05", i); + i++; + } + break; + case 0x06: { + // ??? + fprintf(f, "%% @%d: U06 %d 0x%08x\n", i, + buf.getByte(i+1), buf.getDWord(i+2)); + debuglog("@%d: U06 %d 0x%08x", i, + buf.getByte(i+1), buf.getDWord(i+2)); + i += 6; + } + break; + case 0x07: { + // Font + int namelen; + int ofs; + if (buf.getByte(i+1) & 1) { + namelen = buf.getWord(i+1) >> 3; + ofs = i + 3; + } else { + namelen = buf.getByte(i+1) >> 2; + ofs = i + 2; + } + string fname(buf.getString(ofs), namelen); + ofs += namelen; + int screenfont = buf.getByte(ofs); + int basesize = buf.getWord(ofs+1); + unsigned long style = buf.getDWord(ofs+3); + bool italic = ((style & 1) != 0); + bool bold = ((style & 2) != 0); + unsigned long fontsize = buf.getDWord(ofs+7); + boffset = (long)buf.getDWord(ofs+11); + fprintf(f, "%% @%d: Font '%s' %d %s%s%s\n", i, fname.c_str(), + fontsize, bold ? "Bold" : "", italic ? "Italic" : "", + (bold || italic) ? "" : "Regular"); + ps_setfont(f, fname.c_str(), bold, italic, fontsize); + i = ofs + 15; + } + break; + case 0x08: { + // ??? + fprintf(f, "%% @%d: U08\n", i); + debuglog("@%d: U08", i); + i++; + } + break; + case 0x09: { + // underline + fprintf(f, "%% @%d: Underline %d\n", i, buf.getByte(i+1)); + fprintf(f, "%d UL\n", buf.getByte(i+1)); + i += 2; + } + break; + case 0x0a: { + // strikethru + fprintf(f, "%% @%d: Strikethru %d\n", i, buf.getByte(i+1)); + fprintf(f, "%d ST\n", buf.getByte(i+1)); + i += 2; + } + break; + case 0x0b: { + // newline + fprintf(f, "%% @%d: Newline %d %d\n", i, buf.getDWord(i+1), + buf.getDWord(i+5)); + i += 9; + } + break; + case 0x0c: { + // cr + fprintf(f, "%% @%d: CR %d %d\n", i, buf.getDWord(i+1), + buf.getDWord(i+5)); + i += 9; + } + break; + case 0x0d: { + // foreground color + fprintf(f, "%% @%d: Foreground %d %d %d\n", i, buf.getByte(i+1), + buf.getByte(i+2), buf.getByte(i+3)); + fprintf(f, "%d %d %d FG\n", buf.getByte(i+1), + buf.getByte(i+2), buf.getByte(i+3)); + i += 4; + } + break; + case 0x0e: { + // ??? + fprintf(f, "%% @%d: U0e %d\n", i, buf.getByte(i+1)); + debuglog("@%d: U0e %d", i, buf.getByte(i+1)); + i += 2; + } + break; + case 0x0f: { + // ??? + fprintf(f, "%% @%d: U0f %d %d\n", i, buf.getDWord(i+1), + buf.getDWord(i+5)); + debuglog("@%d: U0f %d %d", i, buf.getDWord(i+1), + buf.getDWord(i+5)); + i += 9; + } + break; + case 0x10: { + // background color + fprintf(f, "%% @%d: Background %d %d %d\n", i, buf.getByte(i+1), + buf.getByte(i+2), buf.getByte(i+3)); + fprintf(f, "%d %d %d BG\n", buf.getByte(i+1), + buf.getByte(i+2), buf.getByte(i+3)); + i += 4; + } + break; + case 0x11: { + // ??? + fprintf(f, "%% @%d: U11 %d\n", i, buf.getByte(i+1)); + debuglog("@%d: U11 %d", i, buf.getByte(i+1)); + i += 2; + } + break; + case 0x17: { + // ??? + fprintf(f, "%% @%d: U17 %d %d\n", i, buf.getDWord(i+1), + buf.getDWord(i+5)); + debuglog("@%d: U17 %d %d", i, buf.getDWord(i+1), + buf.getDWord(i+5)); + i += 9; + } + break; + case 0x19: { + // Draw line + fprintf(f, "%% @%d: Line %d %d %d %d\n", i, + buf.getDWord(i+1), buf.getDWord(i+5), + buf.getDWord(i+9), buf.getDWord(i+13)); + fprintf(f, "%d %d %d %d L\n", + buf.getDWord(i+1), buf.getDWord(i+5), + buf.getDWord(i+9), buf.getDWord(i+13)); + i += 17; + } + break; + case 0x1b: { + // ??? + fprintf(f, "%% @%d: U1b %d %d\n", i, buf.getDWord(i+1), + buf.getDWord(i+5)); + debuglog("@%d: U1b %d %d", i, buf.getDWord(i+1), + buf.getDWord(i+5)); + i += 9; + } + break; + case 0x1f: { + // Draw ellipse + fprintf(f, "%% @%d: Ellipse %d %d %d %d\n", i, + buf.getDWord(i+1), buf.getDWord(i+5), + buf.getDWord(i+9), buf.getDWord(i+13)); + fprintf(f, "%d %d %d %d E\n", + buf.getDWord(i+1), buf.getDWord(i+5), + buf.getDWord(i+9), buf.getDWord(i+13)); + i += 17; + } + break; + case 0x20: { + // Draw rectangle + fprintf(f, "%% @%d: Rectangle %d %d %d %d\n", i, + buf.getDWord(i+1), buf.getDWord(i+5), + buf.getDWord(i+9), buf.getDWord(i+13)); + fprintf(f, "%d %d %d %d R\n", + buf.getDWord(i+1), buf.getDWord(i+5), + buf.getDWord(i+9), buf.getDWord(i+13)); + i += 17; + } + break; + + case 0x23: { + // Draw polygon + unsigned long count = buf.getDWord(i+1); + int o = i + 5; + fprintf(f, "%% @%d: Polygon (%d segments)\n", i, count); + fprintf(f, "[\n"); + for (int j = 0; j < count; j++) { + fprintf(f, "%d %d\n", buf.getDWord(o), + buf.getDWord(o+4)); + o += 8; + } + fprintf(f, "] P\n"); + i = o + 1; + } + break; + case 0x25: { + // Draw bitmap + // skip for now + unsigned long blen = buf.getDWord(i+17); + fprintf(f, "%% @%d: U25\n", i); + debuglog("@%d: U25 len=%d ofs=%d", i, blen, buf.getDWord(i+21)); + i += (17 + blen); + } + break; + case 0x26: { + // Draw bitmap + unsigned long llx = buf.getDWord(i+1); + unsigned long lly = buf.getDWord(i+13); + unsigned long urx = buf.getDWord(i+9); + unsigned long ury = buf.getDWord(i+5); + unsigned long bw = buf.getDWord(i+25); + unsigned long bh = buf.getDWord(i+29); + unsigned long blen = buf.getDWord(i+17); + unsigned long bofs = buf.getDWord(i+21); + unsigned long bits = buf.getDWord(i+41); + bool rle = (buf.getDWord(i+53) == 1); + fprintf(f, "%% @%d: Bitmap\n", i); + ps_bitmap(f, llx, lly, urx, ury, buf.getString(17)); + debuglog("Bitmap len=%d ofs=%d", blen, bofs); + i += (17 + blen + 16); + } + break; + case 0x27: { + // Draw label + int tlen; + int ofs; + if (buf.getByte(i+1) & 1) { + tlen = buf.getWord(i+1) >> 3; + ofs = i + 3; + } else { + tlen = buf.getByte(i+1) >> 2; + ofs = i + 2; + } + string text(buf.getString(ofs), tlen); + ofs += tlen; + ps_escape(text); + fprintf(f, "(%s) %d %d 0 0 false T\n", text.c_str(), + buf.getDWord(ofs), buf.getDWord(ofs+4) + boffset); + i = ofs + 8; + } + break; + case 0x28: { + // Draw text + int tlen; + int ofs; + if (buf.getByte(i+1) & 1) { + tlen = buf.getWord(i+1) >> 3; + ofs = i + 3; + } else { + tlen = buf.getByte(i+1) >> 2; + ofs = i + 2; + } + string text(buf.getString(ofs), tlen); + ofs += tlen; + int x = buf.getDWord(ofs); + fprintf(f, "%% @%d: Text '%s' %d %d %d %d ?%d ?%d\n", i, + text.c_str(), x, buf.getDWord(ofs+12) + boffset, + buf.getDWord(ofs+4), buf.getDWord(ofs+8), + buf.getByte(ofs+16), buf.getDWord(ofs+17)); + ps_escape(text); + if ((x == 0) && (lmargin != -1)) + x = lmargin; + fprintf(f, "(%s) %d %d %d %d true T\n", text.c_str(), + x, buf.getDWord(ofs+12) + boffset, + buf.getDWord(ofs+4), buf.getDWord(ofs+8)); + i = ofs + 25; + } + break; + default: + debuglog("@%d: UNHANDLED OPCODE %02x", i, opcode); + i++; + break; + } + } + fprintf(f, "showpage\n"); + if (last) { + fputs( + "%%Trailer\n" + "%%DocumentNeededResources: ", f); + if (usedfonts.empty()) + fputs("none\n", f); + else { + usedfonts.erase(0, 4); + fputs(usedfonts.c_str(), f); + } + fprintf(f, "%%%%Pages: %d\n", page + 1); + fprintf(f, "%%%%BoundingBox: %d %d %d %d\n", + minx / 20, miny / 20, maxx / 20, maxy / 20); + fputs("%%EOF\n", f); + } } +static unsigned char fakePage[15] = { + 0x2a, 0x2a, 0x09, 0x00, 0x00, 0x00, 0x82, 0x2e, + 0x00, 0x00, 0xc6, 0x41, 0x00, 0x00, 0x00, +}; + +const static void service_loop() { serviceLoop = true; while (serviceLoop) { bool spoolOpen = false; - bufferStore c; + bool pageStart = true; + bool cancelled = false; + unsigned long plen; + int pageCount; + bufferStore buf; + bufferStore pageBuf; int fd; + FILE *f; + unsigned char b; char *jname = (char *)malloc(strlen(spooldir) + strlen(TEMPLATE) + 2); while (1) { /* Job loop */ - c.init(); - if (wPrt->getData(c) != rfsv::E_PSI_GEN_NONE) { - if (spoolOpen) { - unlink(jname); - close(fd); - errorlog("Job aborted"); + buf.init(); + if (wPrt->getData(buf) == rfsv::E_PSI_GEN_NONE) { + if ((buf.getLen() == 15) && + (!memcmp(buf.getString(0), fakePage, 15))) { + cancelled = false; + if (spoolOpen) { + fclose(f); + infolog("Cancelled job %s", jname); + unlink(jname); + break; + } + continue; + } + if (!spoolOpen && !cancelled) { + sprintf(jname, "%s/%s", spooldir, TEMPLATE); + if ((fd = mkstemp(jname)) != -1) { + infolog("Receiving new job %s", jname); + spoolOpen = true; + pageStart = true; + pageCount = 0; + } else { + errorlog("Could not create spool file."); + cancelled = true; + wPrt->cancelJob(); + } + f = fdopen(fd, "w"); + plen = 0; + } + b = buf.getByte(0); + if ((b != 0x2a) && (b != 0xff)) { + errorlog("Invalid packet type 0x%02x.", b); + cancelled = true; + wPrt->cancelJob(); + } + bool jobEnd = (b == 0xff); + if (!cancelled) { + buf.discardFirstBytes(1); + if (pageStart) { + b = buf.getByte(0); + plen = buf.getDWord(1) - 8; + buf.discardFirstBytes(5+8); + pageStart = false; + pageBuf.init(); + } + pageBuf.addBuff(buf); + plen -= buf.getLen(); + if (plen <= 0) { + convertPage(f, pageCount++, jobEnd, pageBuf); + pageBuf.init(); + pageStart = true; + } + } + if (jobEnd) { + if (spoolOpen) + fclose(f); + if (!cancelled) { + if (pageCount > 0) { + infolog("Spooling %d pages", pageCount); + // TODO: print it... + } + } else + unlink(jname); + spoolOpen = false; } - free(jname); - return; - } - if ((c.getLen() == 15) && (c.getWord(0) == 0x2a2a)) { - sprintf(jname, "%s/%s", spooldir, TEMPLATE); - if ((fd = mkstemp(jname)) != -1) { - debuglog("Receiving new job %s", jname); - write(fd, c.getString(0), c.getLen()); - spoolOpen = true; - } else - errorlog("Could not create spool file."); - } else { - if (spoolOpen) - write(fd, c.getString(0), c.getLen()); - if (c.getWord(0) == 0xffff) - break; } } - if (spoolOpen) { - close(fd); - spoolOpen = false; - debuglog("Job received, start conversion ..."); - convert_job(jname); - } free(jname); } } |