diff options
Diffstat (limited to 'apps/unix/x11pdf.c')
-rw-r--r-- | apps/unix/x11pdf.c | 622 |
1 files changed, 189 insertions, 433 deletions
diff --git a/apps/unix/x11pdf.c b/apps/unix/x11pdf.c index 8405762f..524cbeff 100644 --- a/apps/unix/x11pdf.c +++ b/apps/unix/x11pdf.c @@ -1,5 +1,8 @@ -#include <fitz.h> -#include <mupdf.h> +#include "fitz.h" +#include "mupdf.h" +#include "pdfapp.h" + +#include "gs_l.xbm" #include <X11/Xlib.h> #include <X11/Xutil.h> @@ -23,45 +26,44 @@ static GC xgc; static XEvent xevt; static int mapped = 0; static Cursor xcarrow, xchand, xcwait; +static int justcopied = 0; +static int dirty = 0; +static char *password = ""; +static XColor xbgcolor; +static XColor xshcolor; -static char *doctitle = "<untitled>"; - -static float zoom = 1.0; -static int rotate = 0; -static int pageno = 1; -static int count = 0; - -static pdf_page *page = nil; -static fz_obj *pageobj = nil; +static pdfapp_t gapp; -static int hist[256]; -static int histlen = 0; - -/* for 123G commands */ -static unsigned char pagebuf[256]; -static int pagebufidx = 0; +/* + * Dialog boxes + */ -static pdf_xref *xref; -static pdf_pagetree *pages; -static pdf_outline *outline; -static fz_renderer *rast; -static fz_pixmap *image; +void winwarn(pdfapp_t *app, char *msg) +{ + fprintf(stderr, "ghostpdf: %s\n", msg); +} -void usage() +void winerror(pdfapp_t *app, char *msg) { - fprintf(stderr, "usage: ghostpdf [-b] [-pzr page/zoom/rotate] [-u password] file.pdf\n"); - fprintf(stderr, -"\n" - ); + fprintf(stderr, "ghostpdf: %s\n", msg); exit(1); } +char *winpassword(pdfapp_t *app, char *filename) +{ + char *r = password; + password = NULL; + return r; +} + /* * X11 magic */ -static void xopen(void) +void winopen(void) { + XWMHints *hints; + xdpy = XOpenDisplay(nil); assert(xdpy != nil); @@ -73,6 +75,17 @@ static void xopen(void) xchand = XCreateFontCursor(xdpy, XC_hand2); xcwait = XCreateFontCursor(xdpy, XC_watch); + xbgcolor.red = 0x7000; + xbgcolor.green = 0x7000; + xbgcolor.blue = 0x7000; + + xshcolor.red = 0x4000; + xshcolor.green = 0x4000; + xshcolor.blue = 0x4000; + + XAllocColor(xdpy, DefaultColormap(xdpy, xscr), &xbgcolor); + XAllocColor(xdpy, DefaultColormap(xdpy, xscr), &xshcolor); + xwin = XCreateWindow(xdpy, DefaultRootWindow(xdpy), 10, 10, 200, 100, 1, ximage_get_depth(), @@ -84,21 +97,56 @@ static void xopen(void) XSetWindowColormap(xdpy, xwin, ximage_get_colormap()); XSelectInput(xdpy, xwin, StructureNotifyMask | ExposureMask | KeyPressMask | - PointerMotionMask | ButtonPressMask); + PointerMotionMask | ButtonPressMask | ButtonReleaseMask); mapped = 0; xgc = XCreateGC(xdpy, xwin, 0, nil); + + XDefineCursor(xdpy, xwin, xcarrow); + + hints = XAllocWMHints(); + if (hints) + { + hints->flags = IconPixmapHint; + hints->icon_pixmap = XCreateBitmapFromData(xdpy, xwin, + gs_l_xbm_bits, gs_l_xbm_width, gs_l_xbm_height); + if (hints->icon_pixmap) + { + XSetWMHints(xdpy, xwin, hints); + } + XFree(hints); + } +} + +void wincursor(pdfapp_t *app, int curs) +{ + if (curs == ARROW) + XDefineCursor(xdpy, xwin, xcarrow); + if (curs == HAND) + XDefineCursor(xdpy, xwin, xchand); + if (curs == WAIT) + XDefineCursor(xdpy, xwin, xcwait); +} + +void wintitle(pdfapp_t *app, char *s) +{ + XmbSetWMProperties(xdpy, xwin, s, s, 0, 0, 0, 0, 0); } -static void xresize(void) +void winconvert(pdfapp_t *app, fz_pixmap *image) +{ + // never mind +} + +void winresize(pdfapp_t *app, int w, int h) { XWindowChanges values; int mask; mask = CWWidth | CWHeight; - values.width = image->w; - values.height = image->h; + values.width = w; + values.height = h; XConfigureWindow(xdpy, xwin, mask, &values); if (!mapped) @@ -114,421 +162,113 @@ static void xresize(void) } XSetForeground(xdpy, xgc, WhitePixel(xdpy, xscr)); - XFillRectangle(xdpy, xwin, xgc, 0, 0, image->w, image->h); + XFillRectangle(xdpy, xwin, xgc, 0, 0, gapp.image->w, gapp.image->h); XFlush(xdpy); mapped = 1; } } -static void xblit(void) -{ - ximage_blit(xwin, xgc, 0, 0, image->samples, 0, 0, - image->w, image->h, image->w * image->n); -} - -static void xtitle(char *s) +void winblit(pdfapp_t *app) { - XmbSetWMProperties(xdpy, xwin, s, s, 0, 0, 0, 0, 0); -} - -static void showpage(void) -{ - fz_error *error; - fz_matrix ctm; - fz_rect bbox; - fz_obj *obj; - char s[256]; - - assert(pageno > 0 && pageno <= pdf_getpagecount(pages)); - - XDefineCursor(xdpy, xwin, xcwait); - XFlush(xdpy); - - if (image) - fz_droppixmap(image); - image = nil; - - obj = pdf_getpageobject(pages, pageno - 1); - if (obj == pageobj) - goto Lskipload; - pageobj = obj; - - if (page) - pdf_droppage(page); - - sprintf(s, "Loading page %d", pageno); - XSetForeground(xdpy, xgc, BlackPixel(xdpy, xscr)); - XDrawString(xdpy, xwin, xgc, 10, 20, s, strlen(s)); - XFlush(xdpy); - - error = pdf_loadpage(&page, xref, pageobj); - if (error) - fz_abort(error); - -Lskipload: - - sprintf(s, "Rendering..."); - XSetForeground(xdpy, xgc, BlackPixel(xdpy, xscr)); - XDrawString(xdpy, xwin, xgc, 10, 30, s, strlen(s)); - XFlush(xdpy); - - ctm = fz_identity(); - ctm = fz_concat(ctm, fz_translate(0, -page->mediabox.max.y)); - ctm = fz_concat(ctm, fz_scale(zoom, -zoom)); - ctm = fz_concat(ctm, fz_rotate(rotate + page->rotate)); - - bbox = fz_transformaabb(ctm, page->mediabox); - - error = fz_rendertree(&image, rast, page->tree, ctm, fz_roundrect(bbox), 1); - if (error) - fz_abort(error); - - XDefineCursor(xdpy, xwin, xcarrow); - XFlush(xdpy); - + int x0 = gapp.panx; + int y0 = gapp.pany; + int x1 = gapp.panx + gapp.image->w; + int y1 = gapp.pany + gapp.image->h; + + XSetForeground(xdpy, xgc, xbgcolor.pixel); + XFillRectangle(xdpy, xwin, xgc, 0, 0, x0, gapp.winh); + XFillRectangle(xdpy, xwin, xgc, x1, 0, gapp.winw - x1, gapp.winh); + XFillRectangle(xdpy, xwin, xgc, 0, 0, gapp.winw, y0); + XFillRectangle(xdpy, xwin, xgc, 0, y1, gapp.winw, gapp.winh - y1); + + XSetForeground(xdpy, xgc, xshcolor.pixel); + XFillRectangle(xdpy, xwin, xgc, x0+2, y1, gapp.image->w, 2); + XFillRectangle(xdpy, xwin, xgc, x1, y0+2, 2, gapp.image->h); + + if (0) { - char buf[512]; - sprintf(buf, "%s - %d/%d", doctitle, pageno, count); - xtitle(buf); + ximage_blit(xwin, xgc, + x0, y0, + gapp.image->samples, + 0, 0, + gapp.image->w, + gapp.image->h, + gapp.image->w * gapp.image->n); } - - xresize(); - xblit(); -} - -static void pdfopen(char *filename, char *password) -{ - fz_error *error; - fz_obj *obj; - - error = pdf_newxref(&xref); - if (error) - fz_abort(error); - - error = pdf_loadxref(xref, filename); - if (error) - { - fz_warn(error->msg); - printf("trying to repair...\n"); - error = pdf_repairxref(xref, filename); - if (error) - fz_abort(error); - } - - error = pdf_decryptxref(xref); - if (error) - fz_abort(error); - - if (xref->crypt) - { - error = pdf_setpassword(xref->crypt, password); - if (error) fz_abort(error); - } - - obj = fz_dictgets(xref->trailer, "Root"); - if (!obj) - fz_abort(fz_throw("syntaxerror: missing Root object")); - error = pdf_loadindirect(&xref->root, xref, obj); - if (error) fz_abort(error); - - obj = fz_dictgets(xref->trailer, "Info"); - if (obj) - { - error = pdf_loadindirect(&xref->info, xref, obj); - if (error) fz_abort(error); - } - - error = pdf_loadnametrees(xref); - if (error) fz_abort(error); - - error = pdf_loadoutline(&outline, xref); - if (error) fz_abort(error); - - doctitle = filename; - if (xref->info) + else { - obj = fz_dictgets(xref->info, "Title"); - if (obj) - { - error = pdf_toutf8(&doctitle, obj); - if (error) fz_abort(error); - } + XSetForeground(xdpy, xgc, WhitePixel(xdpy, xscr)); + XFillRectangle(xdpy, xwin, xgc, + x0, y0, x1 - x0, y1 - y0); } - if (outline) - pdf_debugoutline(outline, 0); - - error = pdf_loadpagetree(&pages, xref); - if (error) fz_abort(error); - - count = pdf_getpagecount(pages); - - error = fz_newrenderer(&rast, pdf_devicergb, 0, 1024 * 512); - if (error) fz_abort(error); - - image = nil; } -static void dumptext() +void winrepaint(pdfapp_t *app) { - fz_error *error; - pdf_textline *line; - - printf("----"); - - error = pdf_loadtextfromtree(&line, page->tree); - if (error) - fz_abort(error); - - pdf_debugtextline(line); + dirty = 1; +} - pdf_droptextline(line); +void windocopy(pdfapp_t *app) +{ + /* yeah, right. not right now. */ } -static void gotouri(fz_obj *uri) +void winopenuri(pdfapp_t *app, char *buf) { char cmd[2048]; - char buf[2048]; - - printf("goto uri: "); - fz_debugobj(uri); - printf("\n"); - - memcpy(buf, fz_tostrbuf(uri), fz_tostrlen(uri)); - buf[fz_tostrlen(uri)] = 0; - if (getenv("BROWSER")) sprintf(cmd, "$BROWSER %s &", buf); else -#ifdef WIN32 - sprintf(cmd, "start %s", buf); -#else sprintf(cmd, "open %s", buf); -#endif system(cmd); } -static void gotopage(fz_obj *obj) +void onkey(int c) { - int oid = fz_tonum(obj); - int gen = fz_togen(obj); - int i; - - printf("goto page: %d %d R\n", oid, gen); - - for (i = 0; i < count; i++) + if (justcopied) { - if (fz_tonum(pages->pref[i]) == oid) - { - if (histlen + 1 == 256) - { - memmove(hist, hist + 1, sizeof(int) * 255); - histlen --; - } - hist[histlen++] = pageno; - pageno = i + 1; - showpage(); - return; - } + justcopied = 0; + winrepaint(&gapp); } -} -static void drawlinks(void) -{ - pdf_link *link; - fz_matrix ctm; - fz_point a, b, c, d; - fz_rect r; - - ctm = fz_identity(); - ctm = fz_concat(ctm, fz_translate(0, -page->mediabox.max.y)); - ctm = fz_concat(ctm, fz_scale(zoom, -zoom)); - ctm = fz_concat(ctm, fz_rotate(rotate + page->rotate)); - ctm = fz_concat(ctm, fz_translate(-image->x, -image->y)); - - for (link = page->links; link; link = link->next) - { - r = link->rect; - - a.x = r.min.x; a.y = r.min.y; - b.x = r.min.x; b.y = r.max.y; - c.x = r.max.x; c.y = r.max.y; - d.x = r.max.x; d.y = r.min.y; - - a = fz_transformpoint(ctm, a); - b = fz_transformpoint(ctm, b); - c = fz_transformpoint(ctm, c); - d = fz_transformpoint(ctm, d); - - XDrawLine(xdpy, xwin, xgc, a.x, a.y, b.x, b.y); - XDrawLine(xdpy, xwin, xgc, b.x, b.y, c.x, c.y); - XDrawLine(xdpy, xwin, xgc, c.x, c.y, d.x, d.y); - XDrawLine(xdpy, xwin, xgc, d.x, d.y, a.x, a.y); - } + if (c == 'q') + exit(0); - XFlush(xdpy); + pdfapp_onkey(&gapp, c); } -static void handlekey(int c) +void onmouse(int x, int y, int btn, int state) { - int oldpage = pageno; - float oldzoom = zoom; - int oldrotate = rotate; - - if (c >= '0' && c <= '9') - pagebuf[pagebufidx++] = c; - else - if (c != 'g' && c != 'G') - pagebufidx = 0; - - switch (c) + if (state != 0 && justcopied) { - case 'd': fz_debugglyphcache(rast->cache); break; - case 'a': rotate -= 5; break; - case 's': rotate += 5; break; - case 'x': dumptext(); break; - case 'o': drawlinks(); break; - - case '\b': - case 'b': - pageno--; - if (pageno < 1) - pageno = 1; - break; - case 'B': - pageno -= 10; - if (pageno < 1) - pageno = 1; - break; - case ' ': - case 'f': - pageno++; - if (pageno > count) - pageno = count; - break; - case 'F': - pageno += 10; - if (pageno > count) - pageno = count; - break; - case 'm': - if (histlen + 1 == 256) - { - memmove(hist, hist + 1, sizeof(int) * 255); - histlen --; - } - hist[histlen++] = pageno; - break; - case 't': - case 'T': - if (histlen > 0) - pageno = hist[--histlen]; - break; - case '-': - zoom -= 0.1; - if (zoom < 0.1) - zoom = 0.1; - break; - case '+': - zoom += 0.1; - if (zoom > 3.0) - zoom = 3.0; - break; - case '<': - rotate -= 90; - break; - case '>': - rotate += 90; - break; - case 'q': - exit(0); - case '\r': - case '\n': - case 'g': - case 'G': - if (pagebufidx > 0) - { - pagebuf[pagebufidx] = '\0'; - pageno = atoi(pagebuf); - pagebufidx = 0; - if (pageno < 1) - pageno = 1; - if (pageno > count) - pageno = count; - } - else - { - if (c == 'G') - { - pageno = count; - } - } - break; + justcopied = 0; + winrepaint(&gapp); } - if (pageno != oldpage || zoom != oldzoom || rotate != oldrotate) - showpage(); + pdfapp_onmouse(&gapp, x, y, btn, state); } -static void handlemouse(float x, int y, int btn) +void usage(void) { - pdf_link *link; - fz_matrix ctm; - fz_point p; - - p.x = x + image->x; - p.y = y + image->y; - - ctm = fz_identity(); - ctm = fz_concat(ctm, fz_translate(0, -page->mediabox.max.y)); - ctm = fz_concat(ctm, fz_scale(zoom, -zoom)); - ctm = fz_concat(ctm, fz_rotate(rotate + page->rotate)); - ctm = fz_invertmatrix(ctm); - - p = fz_transformpoint(ctm, p); - - for (link = page->links; link; link = link->next) - { - if (p.x >= link->rect.min.x && p.x <= link->rect.max.x) - if (p.y >= link->rect.min.y && p.y <= link->rect.max.y) - break; - } - - if (link) - { - XDefineCursor(xdpy, xwin, xchand); - if (btn) - { - if (fz_isstring(link->dest)) - gotouri(link->dest); - if (fz_isindirect(link->dest)) - gotopage(link->dest); - } - } - else - { - XDefineCursor(xdpy, xwin, xcarrow); - } + fprintf(stderr, "usage: ghostpdf [-d password] file.pdf\n"); + exit(1); } int main(int argc, char **argv) { char *filename; int c; + int len; + unsigned char buf[128]; + KeySym keysym; - int benchmark = 0; - char *password = ""; - - while ((c = getopt(argc, argv, "bz:r:p:u:")) != -1) + while ((c = getopt(argc, argv, "d:")) != -1) { switch (c) { - case 'b': ++benchmark; break; - case 'u': password = optarg; break; - case 'p': pageno = atoi(optarg); break; - case 'z': zoom = atof(optarg); break; - case 'r': rotate = atoi(optarg); break; + case 'd': password = optarg; break; default: usage(); } } @@ -536,56 +276,72 @@ int main(int argc, char **argv) if (argc - optind == 0) usage(); + filename = argv[optind++]; + fz_cpudetect(); fz_accelerate(); - filename = argv[optind++]; + winopen(); - xopen(); - pdfopen(filename, password); - showpage(); + pdfapp_init(&gapp); + gapp.scrw = DisplayWidth(xdpy, xscr); + gapp.scrh = DisplayHeight(xdpy, xscr); - if (benchmark) - { - while (pageno < count) - { - pageno ++; - showpage(); - } - return 0; - } + pdfapp_open(&gapp, filename); while (1) { - int len; - unsigned char buf[128]; - KeySym keysym; + do + { + XNextEvent(xdpy, &xevt); + + switch (xevt.type) + { + case Expose: + dirty = 1; + break; + + case ConfigureNotify: + if (gapp.image) + { + if (xevt.xconfigure.width != gapp.image->w || + xevt.xconfigure.height != gapp.image->h) + gapp.shrinkwrap = 0; + } + pdfapp_onresize(&gapp, + xevt.xconfigure.width, + xevt.xconfigure.height); + break; + + case KeyPress: + len = XLookupString(&xevt.xkey, buf, sizeof buf, &keysym, 0); + if (len) + onkey(buf[0]); + break; + + case MotionNotify: + onmouse(xevt.xbutton.x, xevt.xbutton.y, xevt.xbutton.button, 0); + break; + + case ButtonPress: + onmouse(xevt.xbutton.x, xevt.xbutton.y, xevt.xbutton.button, 1); + break; + + case ButtonRelease: + onmouse(xevt.xbutton.x, xevt.xbutton.y, xevt.xbutton.button, -1); + break; + } + } + while (XPending(xdpy)); - XNextEvent(xdpy, &xevt); - switch (xevt.type) + if (dirty) { - case Expose: - if (xevt.xexpose.count == 0) - xblit(); - break; - - case KeyPress: - len = XLookupString(&xevt.xkey, buf, sizeof buf, &keysym, 0); - if (len) - handlekey(buf[0]); - break; - - case MotionNotify: - handlemouse(xevt.xbutton.x, xevt.xbutton.y, 0); - break; - - case ButtonPress: - handlemouse(xevt.xbutton.x, xevt.xbutton.y, 1); - break; + winblit(&gapp); + dirty = 0; } } - pdf_closexref(xref); + pdfapp_close(&gapp); return 0; } |