diff options
author | Tor Andersson <tor.andersson@artifex.com> | 2013-06-19 15:29:44 +0200 |
---|---|---|
committer | Tor Andersson <tor.andersson@artifex.com> | 2013-06-20 16:45:35 +0200 |
commit | 0a927854a10e1e6b9770a81e2e1d9f3093631757 (patch) | |
tree | 3d65d820d9fdba2d0d394d99c36290c851b78ca0 /apps | |
parent | 1ae8f19179c5f0f8c6352b3c7855465325d5449a (diff) | |
download | mupdf-0a927854a10e1e6b9770a81e2e1d9f3093631757.tar.xz |
Rearrange source files.
Diffstat (limited to 'apps')
-rw-r--r-- | apps/jstest_main.c | 424 | ||||
-rw-r--r-- | apps/man/mudraw.1 | 89 | ||||
-rw-r--r-- | apps/man/mupdf.1 | 92 | ||||
-rw-r--r-- | apps/man/mutool.1 | 77 | ||||
-rw-r--r-- | apps/mudraw.c | 1090 | ||||
-rw-r--r-- | apps/mupdf.ico | bin | 15086 -> 0 bytes | |||
-rw-r--r-- | apps/mutool.c | 93 | ||||
-rw-r--r-- | apps/pdfapp.c | 1545 | ||||
-rw-r--r-- | apps/pdfapp.h | 149 | ||||
-rw-r--r-- | apps/pdfclean.c | 237 | ||||
-rw-r--r-- | apps/pdfextract.c | 231 | ||||
-rw-r--r-- | apps/pdfinfo.c | 1032 | ||||
-rw-r--r-- | apps/pdfposter.c | 183 | ||||
-rw-r--r-- | apps/pdfshow.c | 251 | ||||
-rw-r--r-- | apps/win_main.c | 1163 | ||||
-rw-r--r-- | apps/win_res.rc | 82 | ||||
-rw-r--r-- | apps/x11_image.c | 703 | ||||
-rw-r--r-- | apps/x11_main.c | 993 |
18 files changed, 0 insertions, 8434 deletions
diff --git a/apps/jstest_main.c b/apps/jstest_main.c deleted file mode 100644 index 2003ad55..00000000 --- a/apps/jstest_main.c +++ /dev/null @@ -1,424 +0,0 @@ -#include "pdfapp.h" - -#include <ctype.h> - -/* - A useful bit of bash script to call this is: - for f in ../ghostpcl/tests_private/pdf/forms/v1.3/ *.pdf ; do g=${f%.*} ; echo $g ; win32/debug/mujstest-v8.exe -o $g-%d.png -p ../ghostpcl/ $g.mjs > $g.log 2>&1 ; done - - Remove the space from "/ *.pdf" before running - can't leave that - in here, as it causes a warning about a possibly malformed comment. -*/ - -static pdfapp_t gapp; -static int file_open = 0; -static char filename[1024] = ""; -static char *scriptname; -static char *output = NULL; -static char *prefix = NULL; -static int shotcount = 0; -static int verbosity = 0; - -#define LONGLINE 4096 - -static char getline_buffer[LONGLINE]; - -void winwarn(pdfapp_t *app, char *msg) -{ - fprintf(stderr, "warning: %s\n", msg); -} - -void winerror(pdfapp_t *app, char *msg) -{ - fprintf(stderr, "%s\n", msg); - exit(1); -} - -void winalert(pdfapp_t *app, pdf_alert_event *alert) -{ - fprintf(stderr, "Alert %s: %s", alert->title, alert->message); - switch (alert->button_group_type) - { - case PDF_ALERT_BUTTON_GROUP_OK: - case PDF_ALERT_BUTTON_GROUP_OK_CANCEL: - alert->button_pressed = PDF_ALERT_BUTTON_OK; - break; - case PDF_ALERT_BUTTON_GROUP_YES_NO: - case PDF_ALERT_BUTTON_GROUP_YES_NO_CANCEL: - alert->button_pressed = PDF_ALERT_BUTTON_YES; - break; - } -} - -void winadvancetimer(pdfapp_t *app, float duration) -{ -} - -void winprint(pdfapp_t *app) -{ - fprintf(stderr, "The MuPDF library supports printing, but this application currently does not"); -} - -static char pd_password[256] = ""; -static char td_textinput[LONGLINE] = ""; - -char *winpassword(pdfapp_t *app, char *filename) -{ - if (pd_password[0] == 0) - return NULL; - return pd_password; -} - -char *wintextinput(pdfapp_t *app, char *inittext, int retry) -{ - if (retry) - return NULL; - - if (td_textinput[0] != 0) - return td_textinput; - return inittext; -} - -int winchoiceinput(pdfapp_t *app, int nopts, char *opts[], int *nvals, char *vals[]) -{ - return 0; -} - -void winhelp(pdfapp_t*app) -{ -} - -void winclose(pdfapp_t *app) -{ - pdfapp_close(app); - exit(0); -} - -int winsavequery(pdfapp_t *app) -{ - return DISCARD; -} - -int wingetsavepath(pdfapp_t *app, char *buf, int len) -{ - return 0; -} - -void winreplacefile(char *source, char *target) -{ -} - -void wincursor(pdfapp_t *app, int curs) -{ -} - -void wintitle(pdfapp_t *app, char *title) -{ -} - -void windrawrect(pdfapp_t *app, int x0, int y0, int x1, int y1) -{ -} - -void windrawstring(pdfapp_t *app, int x, int y, char *s) -{ -} - -void winresize(pdfapp_t *app, int w, int h) -{ -} - -void winrepaint(pdfapp_t *app) -{ -} - -void winrepaintsearch(pdfapp_t *app) -{ -} - -void winfullscreen(pdfapp_t *app, int state) -{ -} - -/* - * Event handling - */ - -void windocopy(pdfapp_t *app) -{ -} - -void winreloadfile(pdfapp_t *app) -{ - pdfapp_close(app); - pdfapp_open(app, filename, 1); -} - -void winopenuri(pdfapp_t *app, char *buf) -{ -} - -static void -usage(void) -{ - fprintf(stderr, "mujstest: Scriptable tester for mupdf + js\n"); - fprintf(stderr, "\nSyntax: mujstest -o <filename> [ -p <prefix> ] [-v] <scriptfile>\n"); - fprintf(stderr, "\n<filename> should sensibly be of the form file-%%d.png\n"); - fprintf(stderr, "\n<prefix> is a path prefix to apply to filenames within the script\n"); - fprintf(stderr, "\n-v\tverbose\n"); - fprintf(stderr, "\nscriptfile contains a list of commands:\n"); - fprintf(stderr, "\tPASSWORD <password>\tSet the password\n"); - fprintf(stderr, "\tOPEN <filename>\tOpen a file\n"); - fprintf(stderr, "\tGOTO <page>\tJump to a particular page\n"); - fprintf(stderr, "\tSCREENSHOT\tSave a screenshot\n"); - fprintf(stderr, "\tRESIZE <w> <h>\tResize the screen to a given size\n"); - fprintf(stderr, "\tCLICK <x> <y> <btn>\tClick at a given position\n"); - fprintf(stderr, "\tTEXT <string>\tSet a value to be entered\n"); - exit(1); -} - -static char * -my_getline(FILE *file) -{ - int c; - char *d = getline_buffer; - int space = sizeof(getline_buffer)-1; - - /* Skip over any prefix of whitespace */ - do - { - c = fgetc(file); - } - while (isspace(c)); - - if (c < 0) - return NULL; - - /* Read the line in */ - do - { - *d++ = (char)c; - c = fgetc(file); - } - while (c >= 32 && space--); - - /* If we ran out of space, skip the rest of the line */ - if (space == 0) - { - while (c >= 32) - c = fgetc(file); - } - - *d = 0; - - return getline_buffer; -} - -static int -match(char **line, const char *match) -{ - char *s = *line; - - if (s == NULL) - return 0; - - while (isspace(*(unsigned char *)s)) - s++; - - while (*s == *match) - { - if (*s == 0) - { - *line = s; - return 1; - } - s++; - match++; - } - - if (*match != 0) - return 0; - - /* We matched! Skip over any whitespace */ - while (isspace(*(unsigned char *)s)) - s++; - - *line = s; - - /* Trim whitespace off the end of the line */ - /* Run to the end of the line */ - while (*s) - s++; - - /* Run back until we find where we started, or non whitespace */ - while (s != *line && isspace((unsigned char)s[-1])) - s--; - - /* Remove the suffix of whitespace */ - *s = 0; - - return 1; -} - -static void unescape_string(char *d, const char *s) -{ - char c; - - while ((c = *s++) != 0) - { - if (c == '\\') - { - c = *s++; - switch(c) - { - case 'n': - c = '\n'; - break; - case 'r': - c = '\r'; - break; - case 't': - c = '\t'; - break; - } - } - *d++ = c; - } - *d = 0; -} - -int -main(int argc, char *argv[]) -{ - fz_context *ctx; - FILE *script = NULL; - int c; - - while ((c = fz_getopt(argc, argv, "o:p:v")) != -1) - { - switch(c) - { - case 'o': output = fz_optarg; break; - case 'p': prefix = fz_optarg; break; - case 'v': verbosity ^= 1; break; - default: usage(); break; - } - } - - if (fz_optind == argc) - usage(); - - ctx = fz_new_context(NULL, NULL, FZ_STORE_DEFAULT); - if (!ctx) - { - fprintf(stderr, "cannot initialise context\n"); - exit(1); - } - pdfapp_init(ctx, &gapp); - gapp.scrw = 640; - gapp.scrh = 480; - gapp.colorspace = fz_device_rgb(ctx); - - fz_try(ctx) - { - while (fz_optind < argc) - { - scriptname = argv[fz_optind++]; - script = fopen(scriptname, "rb"); - if (script == NULL) - fz_throw(ctx, FZ_ERROR_GENERIC, "cannot open script: %s", scriptname); - - do - { - char *line = my_getline(script); - if (line == NULL) - continue; - if (verbosity) - fprintf(stderr, "'%s'\n", line); - if (match(&line, "%")) - { - /* Comment */ - } - else if (match(&line, "PASSWORD")) - { - strcpy(pd_password, line); - } - else if (match(&line, "OPEN")) - { - char path[1024]; - if (file_open) - pdfapp_close(&gapp); - strcpy(filename, line); - if (prefix) - { - sprintf(path, "%s%s", prefix, line); - } - else - { - strcpy(path, line); - } - pdfapp_open(&gapp, path, 0); - file_open = 1; - } - else if (match(&line, "GOTO")) - { - pdfapp_gotopage(&gapp, atoi(line)-1); - } - else if (match(&line, "SCREENSHOT")) - { - char text[1024]; - - sprintf(text, output, ++shotcount); - if (strstr(text, ".pgm") || strstr(text, ".ppm") || strstr(text, ".pnm")) - fz_write_pnm(ctx, gapp.image, text); - else - fz_write_png(ctx, gapp.image, text, 0); - } - else if (match(&line, "RESIZE")) - { - int w, h; - sscanf(line, "%d %d", &w, &h); - pdfapp_onresize(&gapp, w, h); - } - else if (match(&line, "CLICK")) - { - float x, y, b; - int n; - n = sscanf(line, "%f %f %f", &x, &y, &b); - if (n < 1) - x = 0.0f; - if (n < 2) - y = 0.0f; - if (n < 3) - b = 1; - /* state = 1 = transition down */ - pdfapp_onmouse(&gapp, (int)x, (int)y, b, 0, 1); - /* state = -1 = transition up */ - pdfapp_onmouse(&gapp, (int)x, (int)y, b, 0, -1); - } - else if (match(&line, "TEXT")) - { - unescape_string(td_textinput, line); - } - else - { - fprintf(stderr, "Unmatched: %s\n", line); - } - } - while (!feof(script)); - - fclose(script); - } - } - fz_catch(ctx) - { - fprintf(stderr, "error: cannot execute '%s'\n", scriptname); - } - - if (file_open) - pdfapp_close(&gapp); - - fz_free_context(ctx); - - return 0; -} diff --git a/apps/man/mudraw.1 b/apps/man/mudraw.1 deleted file mode 100644 index eec79f7b..00000000 --- a/apps/man/mudraw.1 +++ /dev/null @@ -1,89 +0,0 @@ -.TH MUDRAW 1 "March 28, 2012" -.\" Please adjust this date whenever revising the manpage. -.SH NAME -mudraw \- render PDF/XPS/CBZ documents -.SH SYNOPSIS -.B mudraw -.RI [ options ] -.RI input.{pdf,xps,cbz} -.RI [ pages] -.SH DESCRIPTION -.B mudraw -will render a document of a supported document format to image files. -The supported document formats are: pdf, xps and cbz. -The supported image formats are: pgm, ppm, pam and png. -Select the pages to be rendered by specifying a comma -separated list of ranges and individual page numbers (for example: 1,5,10-15). -In no pages are specified all the pages will be rendered. -.SH OPTIONS -.TP -.B \-o output -The image format is deduced from the output file name. -Embed %d in the name to indicate the page number (for example: "page%d.png"). -.TP -.B \-p password -Use the specified password if the file is encrypted. -.TP -.B \-r resolution -Render the page at the specified resolution. -The default resolution is 72 dpi. -.TP -.B \-w width -Render the page at the specified width (or, if the -r flag is used, -render with a maximum width). -.TP -.B \-h height -Render the page at the specified height (or, if the -r flag is used, -render with a maximum height). -.TP -.B \-f -'Fit' exactly; ignore the aspect ratio when matching specified width/heights. -.TP -.B \-R angle -Rotate clockwise by given number of degrees. -.TP -.B \-a -Save the alpha channel. -The default behavior is to render each page with a white background. -With this option, the page background is transparent. -Only supported for pam and png output formats. -.TP -.B \-g -Render in grayscale. -The default is to render a full color RGB image. -If the output format is pgm or ppm this option is ignored. -.TP -.B \-m -Show timing information. -Take the time it takes for each page to render and print -a summary at the end. -.TP -.B \-5 -Print an MD5 checksum of the rendered image data for each page. -.TP -.B \-t -Print the text contents of each page in UTF-8 encoding. -Give the option twice to print detailed information -about the location of each character in XML format. -.TP -.B \-x -Print the display list used to render each page. -.TP -.B \-A -Disable the use of accelerated functions. -.TP -.B \-G gamma -Gamma correct the output image. -Some typical values are 0.7 or 1.4 to thin or darken text rendering. -.TP -.B \-I -Invert the output image colors. -.TP -.B pages -Comma separated list of ranges to render. -.SH SEE ALSO -.BR mupdf (1), -.BR mupdfclean (1). -.BR mupdfshow (1). -.SH AUTHOR -MuPDF is Copyright 2006-2013 Artifex Software, Inc. diff --git a/apps/man/mupdf.1 b/apps/man/mupdf.1 deleted file mode 100644 index a4a268a5..00000000 --- a/apps/man/mupdf.1 +++ /dev/null @@ -1,92 +0,0 @@ -.TH MUPDF 1 "June 12, 2012" -.\" Please adjust this date whenever revising the manpage. -.SH NAME -mupdf \- MuPDF is a lightweight PDF viewer written in portable C -.SH SYNOPSIS -.B mupdf -.RI [ options ] " PDFfile" -.SH DESCRIPTION -This manual page briefly describes the -.B mupdf -command. -.PP -.SH OPTIONS -A description of each of the supported options is included below. -.TP -.B \-p password -Uses the given password to open an encrypted PDF file. -The password is tried both as user and owner password. -.TP -.B \-r resolution -Changes the initial zoom level, specified as the resolution in dpi. -The default value is 72. -.SH MOUSE AND KEY BINDINGS -In addition to the key bindings described below, the mouse can also be -used. Clicking the left mouse button follows links within the PDF while -dragging with the left mouse button pans the page. Dragging with the right -mouse button selects an area and copies the enclosed text to the clipboard -buffer. Using the scroll-wheel while pressing Control zooms in/out, if -Shift is pressed on the other hand then the page is panned. -.TP -.B L, R -Rotate page left (clockwise) or right (counter-clockwise). -.TP -.B h, j, k, l -Scroll page left, down, up, or right. -.TP -.B \+, \- -Zoom in or out. -.TP -.B W, H -Zoom so page exactly fits width or height of window. -.TP -.B w -Shrinkwrap window to fit the page. -.TP -.B r -Reload file. -.TP -.B . pgdn right space -Go to the next page -.TP -.B , pgup left b backspace -Go to the previous page -.TP -.B <, > -Skip back/forth 10 pages at a time. -.TP -.B m -Mark page for snap back. -.TP -.B t -Pop back to the latest mark. -.TP -.B [0-9]m -Save the current page number in the numbered register. -.TP -.B [0-9]t -Go to the page saved in the numbered register. -.TP -.B 123g -Go to page 123. -.TP -.B / -Search for text. -.TP -.B n, N -Find the next/previous search result. -.TP -.B c -Toggle between color and grayscale rendering. -.TP -.B i -Toggle between normal and inverted color rendering. -.P -Sending a \fBSIGHUP\fR signal to the mupdf process will also cause the viewed -file to be reloaded automatically, for use in e.g. build scripts. -.SH SEE ALSO -.BR mupdfclean (1), -.BR mupdfdraw (1), -.BR mupdfshow (1). -.SH AUTHOR -MuPDF is Copyright 2006-2013 Artifex Software, Inc. diff --git a/apps/man/mutool.1 b/apps/man/mutool.1 deleted file mode 100644 index d1c7079b..00000000 --- a/apps/man/mutool.1 +++ /dev/null @@ -1,77 +0,0 @@ -.TH "MUTOOL" "1" "Oct 02, 2012" -.\" Please adjust this date whenever revising the manpage. -.\" no hyphenation -.nh -.\" adjust left -.ad l -.SH NAME -mutool \- all purpose tool for dealing with PDF files -.SH SYNOPSIS -mutool <sub-command> [options] -.SH DESCRIPTION -mutool is a tool based on MuPDF for dealing with PDF files in various manners. -There are several sub commands available, as described below. -.SH CLEAN -mutool clean [options] input.pdf [output.pdf] [pages] -.PP -The clean command pretty prints and rewrites the syntax of a PDF file. -It can be used to repair broken files, expand compressed streams, filter -out a range of pages, etc. -.PP -If no output file is specified, it will write the cleaned PDF to "out.pdf" -in the current directory. -.TP -.B \-p password -Use the specified password if the file is encrypted. -.TP -.B \-g -Garbage collect objects that have no references from other objects. -Give the option twice to renumber all objects and compact the cross reference table. -Give it three times to merge and reuse duplicate objects. -.TP -.B \-d -Decompress streams. This will make the output file larger, but provides -easy access for reading and editing the contents with a text editor. -.TP -.B pages -Comma separated list of page ranges to include. -.SH EXTRACT -TODO -.SH INFO -TODO -.SH POSTER -TODO -.SH SHOW -mutool show [options] file.pdf [object numbers ...] -.PP -The show command will print the specified objects and streams to stdout. -Streams are decoded and non-printable characters are represented -with a period by default. -.TP -.B \-b -Print streams as binary data and omit the object header. -.TP -.B \-e -Print streams in their original encoded (or compressed) form. -.TP -.B \-p password -Use the specified password if the file is encrypted. -.PP -Specify objects by number, or use one of the following special names: -.TP -.B 'xref' or 'x' -Print the cross reference table. -.TP -.B 'trailer' or 't' -Print the trailer dictionary. -.TP -.B 'pages' or 'p' -List the object numbers for every page. -.TP -.B 'grep' or 'g' -Print all the objects in the file in a compact one-line format suitable for piping to grep. -.SH SEE ALSO -.BR mupdf (1), -.BR mudraw (1). -.SH AUTHOR -MuPDF is Copyright 2006-2013 Artifex Software, Inc. diff --git a/apps/mudraw.c b/apps/mudraw.c deleted file mode 100644 index 57bd4be2..00000000 --- a/apps/mudraw.c +++ /dev/null @@ -1,1090 +0,0 @@ -/* - * mudraw -- command line tool for drawing pdf/xps/cbz documents - */ - -#include "mupdf/fitz.h" -#include "mupdf/pdf.h" /* for mujstest */ - -#ifdef _MSC_VER -#include <winsock2.h> -#define main main_utf8 -#else -#include <sys/time.h> -#endif - -enum { TEXT_PLAIN = 1, TEXT_HTML = 2, TEXT_XML = 3 }; - -enum { OUT_PNG, OUT_PPM, OUT_PNM, OUT_PAM, OUT_PGM, OUT_PBM, OUT_SVG, OUT_PWG, OUT_PCL }; - -enum { CS_INVALID, CS_UNSET, CS_MONO, CS_GRAY, CS_GRAYALPHA, CS_RGB, CS_RGBA }; - -typedef struct -{ - char *suffix; - int format; -} suffix_t; - -static const suffix_t suffix_table[] = -{ - { ".png", OUT_PNG }, - { ".pgm", OUT_PGM }, - { ".ppm", OUT_PPM }, - { ".pnm", OUT_PNM }, - { ".pam", OUT_PAM }, - { ".pbm", OUT_PBM }, - { ".svg", OUT_SVG }, - { ".pwg", OUT_PWG }, - { ".pcl", OUT_PCL } -}; - -typedef struct -{ - char *name; - int colorspace; -} cs_name_t; - -static const cs_name_t cs_name_table[] = -{ - { "m", CS_MONO }, - { "mono", CS_MONO }, - { "g", CS_GRAY }, - { "gray", CS_GRAY }, - { "grey", CS_GRAY }, - { "ga", CS_GRAYALPHA }, - { "grayalpha", CS_GRAYALPHA }, - { "greyalpha", CS_GRAYALPHA }, - { "rgb", CS_RGB }, - { "rgba", CS_RGBA }, - { "rgbalpha", CS_RGBA } -}; - -typedef struct -{ - int format; - int default_cs; - int permitted_cs[6]; -} format_cs_table_t; - -static const format_cs_table_t format_cs_table[] = -{ - { OUT_PNG, CS_RGB, { CS_GRAY, CS_GRAYALPHA, CS_RGB, CS_RGBA } }, - { OUT_PPM, CS_RGB, { CS_GRAY, CS_RGB } }, - { OUT_PNM, CS_GRAY, { CS_GRAY, CS_RGB } }, - { OUT_PAM, CS_RGBA, { CS_RGBA } }, - { OUT_PGM, CS_GRAY, { CS_GRAY, CS_RGB } }, - { OUT_PBM, CS_MONO, { CS_MONO } }, - { OUT_SVG, CS_RGB, { CS_RGB } }, - { OUT_PWG, CS_RGB, { CS_MONO, CS_GRAY, CS_RGB } }, - { OUT_PCL, CS_MONO, { CS_MONO } } -}; - -/* - A useful bit of bash script to call this to generate mjs files: - for f in tests_private/pdf/forms/v1.3/ *.pdf ; do g=${f%.*} ; echo $g ; ../mupdf.git/win32/debug/mudraw.exe -j $g.mjs $g.pdf ; done - - Remove the space from "/ *.pdf" before running - can't leave that - in here, as it causes a warning about a possibly malformed comment. -*/ - -static char lorem[] = -"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum " -"vehicula augue id est lobortis mollis. Aenean vestibulum metus sed est " -"gravida non tempus lacus aliquet. Nulla vehicula lobortis tincidunt. " -"Donec malesuada nisl et lacus condimentum nec tincidunt urna gravida. " -"Sed dapibus magna eu velit ultrices non rhoncus risus lacinia. Fusce " -"vitae nulla volutpat elit dictum ornare at eu libero. Maecenas felis " -"enim, tempor a tincidunt id, commodo consequat lectus.\n" -"Morbi tincidunt adipiscing lacus eu dignissim. Pellentesque augue elit, " -"ultrices vitae fermentum et, faucibus et purus. Nam ante libero, lacinia " -"id tincidunt at, ultricies a lorem. Donec non neque at purus condimentum " -"eleifend quis sit amet libero. Sed semper, mi ut tempus tincidunt, lacus " -"eros pellentesque lacus, id vehicula est diam eu quam. Integer tristique " -"fringilla rhoncus. Phasellus convallis, justo ut mollis viverra, dui odio " -"euismod ante, nec fringilla nisl mi ac diam.\n" -"Maecenas mi urna, ornare commodo feugiat id, cursus in massa. Vivamus " -"augue augue, aliquam at varius eu, venenatis fermentum felis. Sed varius " -"turpis a felis ultrices quis aliquet nunc tincidunt. Suspendisse posuere " -"commodo nunc non viverra. Praesent condimentum varius quam, vel " -"consectetur odio volutpat in. Sed malesuada augue ut lectus commodo porta. " -"Vivamus eget mauris sit amet diam ultrices sollicitudin. Cras pharetra leo " -"non elit lacinia vulputate.\n" -"Donec ac enim justo, ornare scelerisque diam. Ut vel ante at lorem " -"placerat bibendum ultricies mattis metus. Phasellus in imperdiet odio. " -"Proin semper lacinia libero, sed rutrum eros blandit non. Duis tincidunt " -"ligula est, non pellentesque mauris. Aliquam in erat scelerisque lacus " -"dictum suscipit eget semper magna. Nullam luctus imperdiet risus a " -"semper.\n" -"Curabitur sit amet tempor sapien. Quisque et tortor in lacus dictum " -"pulvinar. Nunc at nisl ut velit vehicula hendrerit. Mauris elementum " -"sollicitudin leo ac ullamcorper. Proin vel leo nec justo tempus aliquet " -"nec ut mi. Pellentesque vel nisl id dui hendrerit fermentum nec quis " -"tortor. Proin eu sem luctus est consequat euismod. Vestibulum ante ipsum " -"primis in faucibus orci luctus et ultrices posuere cubilia Curae; Fusce " -"consectetur ultricies nisl ornare dictum. Cras sagittis consectetur lorem " -"sed posuere. Mauris accumsan laoreet arcu, id molestie lorem faucibus eu. " -"Vivamus commodo, neque nec imperdiet pretium, lorem metus viverra turpis, " -"malesuada vulputate justo eros sit amet neque. Nunc quis justo elit, non " -"rutrum mauris. Maecenas blandit condimentum nibh, nec vulputate orci " -"pulvinar at. Proin sed arcu vel odio tempus lobortis sed posuere ipsum. Ut " -"feugiat pellentesque tortor nec ornare.\n"; - -static char *output = NULL; -static float resolution = 72; -static int res_specified = 0; -static float rotation = 0; - -static int showxml = 0; -static int showtext = 0; -static int showtime = 0; -static int showmd5 = 0; -static int showoutline = 0; -static int uselist = 1; -static int alphabits = 8; -static float gamma_value = 1; -static int invert = 0; -static int width = 0; -static int height = 0; -static int fit = 0; -static int errored = 0; -static int ignore_errors = 0; -static int output_format; -static int append = 0; -static int out_cs = CS_UNSET; - -static fz_text_sheet *sheet = NULL; -static fz_colorspace *colorspace; -static char *filename; -static int files = 0; -fz_output *out = NULL; - -static char *mujstest_filename = NULL; -static FILE *mujstest_file = NULL; -static int mujstest_count = 0; - -static struct { - int count, total; - int min, max; - int minpage, maxpage; - char *minfilename; - char *maxfilename; -} timing; - -static void usage(void) -{ - fprintf(stderr, - "usage: mudraw [options] input [pages]\n" - "\t-o -\toutput filename (%%d for page number)\n" - "\t\tsupported formats: pgm, ppm, pam, png, pbm\n" - "\t-p -\tpassword\n" - "\t-r -\tresolution in dpi (default: 72)\n" - "\t-w -\twidth (in pixels) (maximum width if -r is specified)\n" - "\t-h -\theight (in pixels) (maximum height if -r is specified)\n" - "\t-f -\tfit width and/or height exactly (ignore aspect)\n" - "\t-c -\tcolorspace {mono,gray,grayalpha,rgb,rgba}\n" - "\t-b -\tnumber of bits of antialiasing (0 to 8)\n" - "\t-g\trender in grayscale\n" - "\t-m\tshow timing information\n" - "\t-t\tshow text (-tt for xml, -ttt for more verbose xml)\n" - "\t-x\tshow display list\n" - "\t-d\tdisable use of display list\n" - "\t-5\tshow md5 checksums\n" - "\t-R -\trotate clockwise by given number of degrees\n" - "\t-G -\tgamma correct output\n" - "\t-I\tinvert output\n" - "\t-l\tprint outline\n" - "\t-j -\tOutput mujstest file\n" - "\t-i\tignore errors and continue with the next file\n" - "\tpages\tcomma separated list of ranges\n"); - exit(1); -} - -static int gettime(void) -{ - static struct timeval first; - static int once = 1; - struct timeval now; - if (once) - { - gettimeofday(&first, NULL); - once = 0; - } - gettimeofday(&now, NULL); - return (now.tv_sec - first.tv_sec) * 1000 + (now.tv_usec - first.tv_usec) / 1000; -} - -static int isrange(char *s) -{ - while (*s) - { - if ((*s < '0' || *s > '9') && *s != '-' && *s != ',') - return 0; - s++; - } - return 1; -} - -static void escape_string(FILE *out, int len, const char *string) -{ - while (len-- && *string) - { - char c = *string++; - switch (c) - { - case '\n': - fputc('\\', out); - fputc('n', out); - break; - case '\r': - fputc('\\', out); - fputc('r', out); - break; - case '\t': - fputc('\\', out); - fputc('t', out); - break; - default: - fputc(c, out); - } - } -} - -static void drawpage(fz_context *ctx, fz_document *doc, int pagenum) -{ - fz_page *page; - fz_display_list *list = NULL; - fz_device *dev = NULL; - int start; - fz_cookie cookie = { 0 }; - int needshot = 0; - - fz_var(list); - fz_var(dev); - - if (showtime) - { - start = gettime(); - } - - fz_try(ctx) - { - page = fz_load_page(doc, pagenum - 1); - } - fz_catch(ctx) - { - fz_rethrow_message(ctx, "cannot load page %d in file '%s'", pagenum, filename); - } - - if (mujstest_file) - { - pdf_document *inter = pdf_specifics(doc); - pdf_widget *widget = NULL; - - if (inter) - widget = pdf_first_widget(inter, (pdf_page *)page); - - if (widget) - { - fprintf(mujstest_file, "GOTO %d\n", pagenum); - needshot = 1; - } - for (;widget; widget = pdf_next_widget(widget)) - { - fz_rect rect; - int w, h, len; - int type = pdf_widget_get_type(widget); - - pdf_bound_widget(widget, &rect); - w = (rect.x1 - rect.x0); - h = (rect.y1 - rect.y0); - ++mujstest_count; - switch (type) - { - default: - fprintf(mujstest_file, "%% UNKNOWN %0.2f %0.2f %0.2f %0.2f\n", rect.x0, rect.y0, rect.x1, rect.y1); - break; - case PDF_WIDGET_TYPE_PUSHBUTTON: - fprintf(mujstest_file, "%% PUSHBUTTON %0.2f %0.2f %0.2f %0.2f\n", rect.x0, rect.y0, rect.x1, rect.y1); - break; - case PDF_WIDGET_TYPE_CHECKBOX: - fprintf(mujstest_file, "%% CHECKBOX %0.2f %0.2f %0.2f %0.2f\n", rect.x0, rect.y0, rect.x1, rect.y1); - break; - case PDF_WIDGET_TYPE_RADIOBUTTON: - fprintf(mujstest_file, "%% RADIOBUTTON %0.2f %0.2f %0.2f %0.2f\n", rect.x0, rect.y0, rect.x1, rect.y1); - break; - case PDF_WIDGET_TYPE_TEXT: - { - int maxlen = pdf_text_widget_max_len(inter, widget); - int texttype = pdf_text_widget_content_type(inter, widget); - - /* If height is low, assume a single row, and base - * the width off that. */ - if (h < 10) - { - w = (w+h-1) / (h ? h : 1); - h = 1; - } - /* Otherwise, if width is low, work off height */ - else if (w < 10) - { - h = (w+h-1) / (w ? w : 1); - w = 1; - } - else - { - w = (w+9)/10; - h = (h+9)/10; - } - len = w*h; - if (len < 2) - len = 2; - if (len > maxlen) - len = maxlen; - fprintf(mujstest_file, "%% TEXT %0.2f %0.2f %0.2f %0.2f\n", rect.x0, rect.y0, rect.x1, rect.y1); - switch (texttype) - { - default: - case PDF_WIDGET_CONTENT_UNRESTRAINED: - fprintf(mujstest_file, "TEXT %d ", mujstest_count); - escape_string(mujstest_file, len-3, lorem); - fprintf(mujstest_file, "\n"); - break; - case PDF_WIDGET_CONTENT_NUMBER: - fprintf(mujstest_file, "TEXT %d\n", mujstest_count); - break; - case PDF_WIDGET_CONTENT_SPECIAL: -#ifdef __MINGW32__ - fprintf(mujstest_file, "TEXT %I64d\n", 46702919800LL + mujstest_count); -#else - fprintf(mujstest_file, "TEXT %lld\n", 46702919800LL + mujstest_count); -#endif - break; - case PDF_WIDGET_CONTENT_DATE: - fprintf(mujstest_file, "TEXT Jun %d 1979\n", 1 + ((13 + mujstest_count) % 30)); - break; - case PDF_WIDGET_CONTENT_TIME: - ++mujstest_count; - fprintf(mujstest_file, "TEXT %02d:%02d\n", ((mujstest_count/60) % 24), mujstest_count % 60); - break; - } - break; - } - case PDF_WIDGET_TYPE_LISTBOX: - fprintf(mujstest_file, "%% LISTBOX %0.2f %0.2f %0.2f %0.2f\n", rect.x0, rect.y0, rect.x1, rect.y1); - break; - case PDF_WIDGET_TYPE_COMBOBOX: - fprintf(mujstest_file, "%% COMBOBOX %0.2f %0.2f %0.2f %0.2f\n", rect.x0, rect.y0, rect.x1, rect.y1); - break; - } - fprintf(mujstest_file, "CLICK %0.2f %0.2f\n", (rect.x0+rect.x1)/2, (rect.y0+rect.y1)/2); - } - } - - if (uselist) - { - fz_try(ctx) - { - list = fz_new_display_list(ctx); - dev = fz_new_list_device(ctx, list); - fz_run_page(doc, page, dev, &fz_identity, &cookie); - } - fz_always(ctx) - { - fz_free_device(dev); - dev = NULL; - } - fz_catch(ctx) - { - fz_drop_display_list(ctx, list); - fz_free_page(doc, page); - fz_rethrow_message(ctx, "cannot draw page %d in file '%s'", pagenum, filename); - } - } - - if (showxml) - { - fz_try(ctx) - { - dev = fz_new_trace_device(ctx); - if (list) - fz_run_display_list(list, dev, &fz_identity, &fz_infinite_rect, &cookie); - else - fz_run_page(doc, page, dev, &fz_identity, &cookie); - } - fz_always(ctx) - { - fz_free_device(dev); - dev = NULL; - } - fz_catch(ctx) - { - fz_drop_display_list(ctx, list); - fz_free_page(doc, page); - fz_rethrow(ctx); - } - } - - if (showtext) - { - fz_text_page *text = NULL; - - fz_var(text); - - fz_try(ctx) - { - text = fz_new_text_page(ctx); - dev = fz_new_text_device(ctx, sheet, text); - if (showtext == TEXT_HTML) - fz_disable_device_hints(dev, FZ_IGNORE_IMAGE); - if (list) - fz_run_display_list(list, dev, &fz_identity, &fz_infinite_rect, &cookie); - else - fz_run_page(doc, page, dev, &fz_identity, &cookie); - fz_free_device(dev); - dev = NULL; - if (showtext == TEXT_XML) - { - fz_print_text_page_xml(ctx, out, text); - } - else if (showtext == TEXT_HTML) - { - fz_analyze_text(ctx, sheet, text); - fz_print_text_page_html(ctx, out, text); - } - else if (showtext == TEXT_PLAIN) - { - fz_print_text_page(ctx, out, text); - fz_printf(out, "\f\n"); - } - } - fz_always(ctx) - { - fz_free_device(dev); - dev = NULL; - fz_free_text_page(ctx, text); - } - fz_catch(ctx) - { - fz_drop_display_list(ctx, list); - fz_free_page(doc, page); - fz_rethrow(ctx); - } - } - - if (showmd5 || showtime) - printf("page %s %d", filename, pagenum); - - if (output && output_format == OUT_SVG) - { - float zoom; - fz_matrix ctm; - fz_rect bounds, tbounds; - char buf[512]; - FILE *file; - fz_output *out; - - sprintf(buf, output, pagenum); - file = fopen(buf, "wb"); - if (file == NULL) - fz_throw(ctx, FZ_ERROR_GENERIC, "cannot open file '%s': %s", buf, strerror(errno)); - out = fz_new_output_with_file(ctx, file); - - fz_bound_page(doc, page, &bounds); - zoom = resolution / 72; - fz_pre_rotate(fz_scale(&ctm, zoom, zoom), rotation); - tbounds = bounds; - fz_transform_rect(&tbounds, &ctm); - - fz_try(ctx) - { - dev = fz_new_svg_device(ctx, out, tbounds.x1-tbounds.x0, tbounds.y1-tbounds.y0); - if (list) - fz_run_display_list(list, dev, &ctm, &tbounds, &cookie); - else - fz_run_page(doc, page, dev, &ctm, &cookie); - fz_free_device(dev); - dev = NULL; - } - fz_always(ctx) - { - fz_free_device(dev); - dev = NULL; - fz_close_output(out); - fclose(file); - } - fz_catch(ctx) - { - fz_drop_display_list(ctx, list); - fz_free_page(doc, page); - fz_rethrow(ctx); - } - } - - if ((output && output_format != OUT_SVG)|| showmd5 || showtime) - { - float zoom; - fz_matrix ctm; - fz_rect bounds, tbounds; - fz_irect ibounds; - fz_pixmap *pix = NULL; - int w, h; - - fz_var(pix); - - fz_bound_page(doc, page, &bounds); - zoom = resolution / 72; - fz_pre_scale(fz_rotate(&ctm, rotation), zoom, zoom); - tbounds = bounds; - fz_round_rect(&ibounds, fz_transform_rect(&tbounds, &ctm)); - - /* Make local copies of our width/height */ - w = width; - h = height; - - /* If a resolution is specified, check to see whether w/h are - * exceeded; if not, unset them. */ - if (res_specified) - { - int t; - t = ibounds.x1 - ibounds.x0; - if (w && t <= w) - w = 0; - t = ibounds.y1 - ibounds.y0; - if (h && t <= h) - h = 0; - } - - /* Now w or h will be 0 unless they need to be enforced. */ - if (w || h) - { - float scalex = w / (tbounds.x1 - tbounds.x0); - float scaley = h / (tbounds.y1 - tbounds.y0); - fz_matrix scale_mat; - - if (fit) - { - if (w == 0) - scalex = 1.0f; - if (h == 0) - scaley = 1.0f; - } - else - { - if (w == 0) - scalex = scaley; - if (h == 0) - scaley = scalex; - } - if (!fit) - { - if (scalex > scaley) - scalex = scaley; - else - scaley = scalex; - } - fz_scale(&scale_mat, scalex, scaley); - fz_concat(&ctm, &ctm, &scale_mat); - tbounds = bounds; - fz_transform_rect(&tbounds, &ctm); - } - fz_round_rect(&ibounds, &tbounds); - fz_rect_from_irect(&tbounds, &ibounds); - - /* TODO: banded rendering and multi-page ppm */ - - fz_try(ctx) - { - int savealpha = (out_cs == CS_RGBA || out_cs == CS_GRAYALPHA); - - pix = fz_new_pixmap_with_bbox(ctx, colorspace, &ibounds); - fz_pixmap_set_resolution(pix, resolution); - - if (savealpha) - fz_clear_pixmap(ctx, pix); - else - fz_clear_pixmap_with_value(ctx, pix, 255); - - dev = fz_new_draw_device(ctx, pix); - if (list) - fz_run_display_list(list, dev, &ctm, &tbounds, &cookie); - else - fz_run_page(doc, page, dev, &ctm, &cookie); - fz_free_device(dev); - dev = NULL; - - if (invert) - fz_invert_pixmap(ctx, pix); - if (gamma_value != 1) - fz_gamma_pixmap(ctx, pix, gamma_value); - - if (savealpha) - fz_unmultiply_pixmap(ctx, pix); - - if (output) - { - char buf[512]; - sprintf(buf, output, pagenum); - if (output_format == OUT_PGM || output_format == OUT_PPM || output_format == OUT_PNM) - fz_write_pnm(ctx, pix, buf); - else if (output_format == OUT_PAM) - fz_write_pam(ctx, pix, buf, savealpha); - else if (output_format == OUT_PNG) - fz_write_png(ctx, pix, buf, savealpha); - else if (output_format == OUT_PWG) - { - if (strstr(output, "%d") != NULL) - append = 0; - if (out_cs == CS_MONO) - { - fz_bitmap *bit = fz_halftone_pixmap(ctx, pix, NULL); - fz_write_pwg_bitmap(ctx, bit, buf, append, NULL); - fz_drop_bitmap(ctx, bit); - } - else - fz_write_pwg(ctx, pix, buf, append, NULL); - append = 1; - } - else if (output_format == OUT_PCL) - { - fz_pcl_options options; - - fz_pcl_preset(ctx, &options, "ljet4"); - - if (strstr(output, "%d") != NULL) - append = 0; - if (out_cs == CS_MONO) - { - fz_bitmap *bit = fz_halftone_pixmap(ctx, pix, NULL); - fz_write_pcl_bitmap(ctx, bit, buf, append, &options); - fz_drop_bitmap(ctx, bit); - } - else - fz_write_pcl(ctx, pix, buf, append, &options); - append = 1; - } - else if (output_format == OUT_PBM) { - fz_bitmap *bit = fz_halftone_pixmap(ctx, pix, NULL); - fz_write_pbm(ctx, bit, buf); - fz_drop_bitmap(ctx, bit); - } - } - - if (showmd5) - { - unsigned char digest[16]; - int i; - - fz_md5_pixmap(pix, digest); - printf(" "); - for (i = 0; i < 16; i++) - printf("%02x", digest[i]); - } - } - fz_always(ctx) - { - fz_free_device(dev); - dev = NULL; - fz_drop_pixmap(ctx, pix); - } - fz_catch(ctx) - { - fz_drop_display_list(ctx, list); - fz_free_page(doc, page); - fz_rethrow(ctx); - } - } - - if (list) - fz_drop_display_list(ctx, list); - - fz_free_page(doc, page); - - if (showtime) - { - int end = gettime(); - int diff = end - start; - - if (diff < timing.min) - { - timing.min = diff; - timing.minpage = pagenum; - timing.minfilename = filename; - } - if (diff > timing.max) - { - timing.max = diff; - timing.maxpage = pagenum; - timing.maxfilename = filename; - } - timing.total += diff; - timing.count ++; - - printf(" %dms", diff); - } - - if (showmd5 || showtime) - printf("\n"); - - fz_flush_warnings(ctx); - - if (mujstest_file && needshot) - { - fprintf(mujstest_file, "SCREENSHOT\n"); - } - - if (cookie.errors) - errored = 1; -} - -static void drawrange(fz_context *ctx, fz_document *doc, char *range) -{ - int page, spage, epage, pagecount; - char *spec, *dash; - - pagecount = fz_count_pages(doc); - spec = fz_strsep(&range, ","); - while (spec) - { - dash = strchr(spec, '-'); - - if (dash == spec) - spage = epage = pagecount; - else - spage = epage = atoi(spec); - - if (dash) - { - if (strlen(dash) > 1) - epage = atoi(dash + 1); - else - epage = pagecount; - } - - spage = fz_clampi(spage, 1, pagecount); - epage = fz_clampi(epage, 1, pagecount); - - if (spage < epage) - for (page = spage; page <= epage; page++) - drawpage(ctx, doc, page); - else - for (page = spage; page >= epage; page--) - drawpage(ctx, doc, page); - - spec = fz_strsep(&range, ","); - } -} - -static void drawoutline(fz_context *ctx, fz_document *doc) -{ - fz_outline *outline = fz_load_outline(doc); - fz_output *out = NULL; - - fz_var(out); - fz_try(ctx) - { - out = fz_new_output_with_file(ctx, stdout); - if (showoutline > 1) - fz_print_outline_xml(ctx, out, outline); - else - fz_print_outline(ctx, out, outline); - } - fz_always(ctx) - { - fz_close_output(out); - fz_free_outline(ctx, outline); - } - fz_catch(ctx) - { - fz_rethrow(ctx); - } -} - -static int -parse_colorspace(const char *name) -{ - int i; - - for (i = 0; i < nelem(cs_name_table); i++) - { - if (!strcmp(name, cs_name_table[i].name)) - return cs_name_table[i].colorspace; - } - fprintf(stderr, "Unknown colorspace \"%s\"\n", name); - exit(1); - return -1; -} - -int main(int argc, char **argv) -{ - char *password = ""; - fz_document *doc = NULL; - int c; - fz_context *ctx; - - fz_var(doc); - - while ((c = fz_getopt(argc, argv, "lo:p:r:R:b:c:dgmtx5G:Iw:h:fij:")) != -1) - { - switch (c) - { - case 'o': output = fz_optarg; break; - case 'p': password = fz_optarg; break; - case 'r': resolution = atof(fz_optarg); res_specified = 1; break; - case 'R': rotation = atof(fz_optarg); break; - case 'b': alphabits = atoi(fz_optarg); break; - case 'l': showoutline++; break; - case 'm': showtime++; break; - case 't': showtext++; break; - case 'x': showxml++; break; - case '5': showmd5++; break; - case 'g': out_cs = CS_GRAY; break; - case 'd': uselist = 0; break; - case 'c': out_cs = parse_colorspace(fz_optarg); break; - case 'G': gamma_value = atof(fz_optarg); break; - case 'w': width = atof(fz_optarg); break; - case 'h': height = atof(fz_optarg); break; - case 'f': fit = 1; break; - case 'I': invert++; break; - case 'j': mujstest_filename = fz_optarg; break; - case 'i': ignore_errors = 1; break; - default: usage(); break; - } - } - - if (fz_optind == argc) - usage(); - - if (!showtext && !showxml && !showtime && !showmd5 && !showoutline && !output && !mujstest_filename) - { - printf("nothing to do\n"); - exit(0); - } - - if (mujstest_filename) - { - if (strcmp(mujstest_filename, "-") == 0) - mujstest_file = stdout; - else - mujstest_file = fopen(mujstest_filename, "wb"); - } - - ctx = fz_new_context(NULL, NULL, FZ_STORE_DEFAULT); - if (!ctx) - { - fprintf(stderr, "cannot initialise context\n"); - exit(1); - } - - fz_set_aa_level(ctx, alphabits); - - /* Determine output type */ - output_format = OUT_PNG; - if (output) - { - char *suffix = output; - int i; - - for (i = 0; i < nelem(suffix_table); i++) - { - char *s = strstr(suffix, suffix_table[i].suffix); - - if (s != NULL) - { - suffix = s+1; - output_format = suffix_table[i].format; - i = 0; - } - } - } - - { - int i, j; - - for (i = 0; i < nelem(format_cs_table); i++) - { - if (format_cs_table[i].format == output_format) - { - if (out_cs == CS_UNSET) - out_cs = format_cs_table[i].default_cs; - for (j = 0; j < nelem(format_cs_table[i].permitted_cs); j++) - { - if (format_cs_table[i].permitted_cs[j] == out_cs) - break; - } - if (j == nelem(format_cs_table[i].permitted_cs)) - { - fprintf(stderr, "Unsupported colorspace for this format\n"); - exit(1); - } - } - } - } - - switch (out_cs) - { - case CS_MONO: - case CS_GRAY: - case CS_GRAYALPHA: - colorspace = fz_device_gray(ctx); - break; - case CS_RGB: - case CS_RGBA: - colorspace = fz_device_rgb(ctx); - break; - default: - fprintf(stderr, "Unknown colorspace!\n"); - exit(1); - break; - } - - timing.count = 0; - timing.total = 0; - timing.min = 1 << 30; - timing.max = 0; - timing.minpage = 0; - timing.maxpage = 0; - timing.minfilename = ""; - timing.maxfilename = ""; - - if (showxml || showtext) - out = fz_new_output_with_file(ctx, stdout); - - if (showxml || showtext == TEXT_XML) - fz_printf(out, "<?xml version=\"1.0\"?>\n"); - - if (showtext) - sheet = fz_new_text_sheet(ctx); - - if (showtext == TEXT_HTML) - { - fz_printf(out, "<style>\n"); - fz_printf(out, "body{background-color:gray;margin:12pt;}\n"); - fz_printf(out, "div.page{background-color:white;margin:6pt;padding:6pt;}\n"); - fz_printf(out, "div.block{border:1px solid gray;margin:6pt;padding:6pt;}\n"); - fz_printf(out, "div.metaline{display:table;width:100%%}\n"); - fz_printf(out, "div.line{display:table-row;padding:6pt}\n"); - fz_printf(out, "div.cell{display:table-cell;padding-left:6pt;padding-right:6pt}\n"); - fz_printf(out, "p{margin:0pt;padding:0pt;}\n"); - fz_printf(out, "</style>\n"); - fz_printf(out, "<body>\n"); - } - - fz_try(ctx) - { - while (fz_optind < argc) - { - fz_try(ctx) - { - filename = argv[fz_optind++]; - files++; - - fz_try(ctx) - { - doc = fz_open_document(ctx, filename); - } - fz_catch(ctx) - { - fz_rethrow_message(ctx, "cannot open document: %s", filename); - } - - if (fz_needs_password(doc)) - { - if (!fz_authenticate_password(doc, password)) - fz_throw(ctx, FZ_ERROR_GENERIC, "cannot authenticate password: %s", filename); - if (mujstest_file) - fprintf(mujstest_file, "PASSWORD %s\n", password); - } - - if (mujstest_file) - { - fprintf(mujstest_file, "OPEN %s\n", filename); - } - - if (showxml || showtext == TEXT_XML) - fz_printf(out, "<document name=\"%s\">\n", filename); - - if (showoutline) - drawoutline(ctx, doc); - - if (showtext || showxml || showtime || showmd5 || output || mujstest_file) - { - if (fz_optind == argc || !isrange(argv[fz_optind])) - drawrange(ctx, doc, "1-"); - if (fz_optind < argc && isrange(argv[fz_optind])) - drawrange(ctx, doc, argv[fz_optind++]); - } - - if (showxml || showtext == TEXT_XML) - fz_printf(out, "</document>\n"); - - fz_close_document(doc); - doc = NULL; - } - fz_catch(ctx) - { - if (!ignore_errors) - fz_rethrow(ctx); - - fz_close_document(doc); - doc = NULL; - fz_warn(ctx, "ignoring error in '%s'", filename); - } - } - } - fz_catch(ctx) - { - fz_close_document(doc); - fprintf(stderr, "error: cannot draw '%s'\n", filename); - errored = 1; - } - - if (showtext == TEXT_HTML) - { - fz_printf(out, "</body>\n"); - fz_printf(out, "<style>\n"); - fz_print_text_sheet(ctx, out, sheet); - fz_printf(out, "</style>\n"); - } - - if (showtext) - fz_free_text_sheet(ctx, sheet); - - if (showxml || showtext) - { - fz_close_output(out); - out = NULL; - } - - if (showtime && timing.count > 0) - { - if (files == 1) - { - printf("total %dms / %d pages for an average of %dms\n", - timing.total, timing.count, timing.total / timing.count); - printf("fastest page %d: %dms\n", timing.minpage, timing.min); - printf("slowest page %d: %dms\n", timing.maxpage, timing.max); - } - else - { - printf("total %dms / %d pages for an average of %dms in %d files\n", - timing.total, timing.count, timing.total / timing.count, files); - printf("fastest page %d: %dms (%s)\n", timing.minpage, timing.min, timing.minfilename); - printf("slowest page %d: %dms (%s)\n", timing.maxpage, timing.max, timing.maxfilename); - } - } - - if (mujstest_file && mujstest_file != stdout) - fclose(mujstest_file); - - fz_free_context(ctx); - return (errored != 0); -} - -#ifdef _MSC_VER -int wmain(int argc, wchar_t *wargv[]) -{ - char **argv = fz_argv_from_wargv(argc, wargv); - int ret = main(argc, argv); - fz_free_argv(argc, argv); - return ret; -} -#endif diff --git a/apps/mupdf.ico b/apps/mupdf.ico Binary files differdeleted file mode 100644 index 80deb8ea..00000000 --- a/apps/mupdf.ico +++ /dev/null diff --git a/apps/mutool.c b/apps/mutool.c deleted file mode 100644 index 62355f32..00000000 --- a/apps/mutool.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * mutool -- swiss army knife of pdf manipulation tools - */ - -#include "mupdf/fitz.h" - -#ifdef _MSC_VER -#define main main_utf8 -#endif - -int pdfclean_main(int argc, char *argv[]); -int pdfextract_main(int argc, char *argv[]); -int pdfinfo_main(int argc, char *argv[]); -int pdfposter_main(int argc, char *argv[]); -int pdfshow_main(int argc, char *argv[]); - -static struct { - int (*func)(int argc, char *argv[]); - char *name; - char *desc; -} tools[] = { - { pdfclean_main, "clean", "rewrite pdf file" }, - { pdfextract_main, "extract", "extract font and image resources" }, - { pdfinfo_main, "info", "show information about pdf resources" }, - { pdfposter_main, "poster", "split large page into many tiles" }, - { pdfshow_main, "show", "show internal pdf objects" }, -}; - -static int -namematch(const char *end, const char *start, const char *match) -{ - int len = strlen(match); - return ((end-len >= start) && (strncmp(end-len, match, len) == 0)); -} - -int main(int argc, char **argv) -{ - char *start, *end; - char buf[32]; - int i; - - if (argc == 0) - { - fprintf(stderr, "No command name found!\n"); - return 1; - } - - /* Check argv[0] */ - - if (argc > 0) - { - end = start = argv[0]; - while (*end) - end++; - if ((end-4 >= start) && (end[-4] == '.') && (end[-3] == 'e') && (end[-2] == 'x') && (end[-1] == 'e')) - end = end-4; - for (i = 0; i < nelem(tools); i++) - { - strcpy(buf, "mupdf"); - strcat(buf, tools[i].name); - if (namematch(end, start, buf) || namematch(end, start, buf+2)) - return tools[i].func(argc, argv); - } - } - - /* Check argv[1] */ - - if (argc > 1) - { - for (i = 0; i < nelem(tools); i++) - if (!strcmp(tools[i].name, argv[1])) - return tools[i].func(argc - 1, argv + 1); - } - - /* Print usage */ - - fprintf(stderr, "usage: mutool <command> [options]\n"); - - for (i = 0; i < nelem(tools); i++) - fprintf(stderr, "\t%s\t-- %s\n", tools[i].name, tools[i].desc); - - return 1; -} - -#ifdef _MSC_VER -int wmain(int argc, wchar_t *wargv[]) -{ - char **argv = fz_argv_from_wargv(argc, wargv); - int ret = main(argc, argv); - fz_free_argv(argc, argv); - return ret; -} -#endif diff --git a/apps/pdfapp.c b/apps/pdfapp.c deleted file mode 100644 index e76c6c7c..00000000 --- a/apps/pdfapp.c +++ /dev/null @@ -1,1545 +0,0 @@ -#include "pdfapp.h" - -#include <ctype.h> /* for tolower() */ - -#define ZOOMSTEP 1.142857 -#define BEYOND_THRESHHOLD 40 -#ifndef PATH_MAX -#define PATH_MAX (1024) -#endif - -#ifndef MAX -#define MAX(a,b) ((a) > (b) ? (a) : (b)) -#endif - -enum panning -{ - DONT_PAN = 0, - PAN_TO_TOP, - PAN_TO_BOTTOM -}; - -static void pdfapp_showpage(pdfapp_t *app, int loadpage, int drawpage, int repaint, int transition); -static void pdfapp_updatepage(pdfapp_t *app); - -static void pdfapp_warn(pdfapp_t *app, const char *fmt, ...) -{ - char buf[1024]; - va_list ap; - va_start(ap, fmt); - vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - buf[sizeof(buf)-1] = 0; - winwarn(app, buf); -} - -static void pdfapp_error(pdfapp_t *app, char *msg) -{ - winerror(app, msg); -} - -char *pdfapp_version(pdfapp_t *app) -{ - return - "MuPDF 1.2\n" - "Copyright 2006-2013 Artifex Software, Inc.\n"; -} - -char *pdfapp_usage(pdfapp_t *app) -{ - return - "L\t\t-- rotate left\n" - "R\t\t-- rotate right\n" - "h\t\t-- scroll left\n" - "j down\t\t-- scroll down\n" - "k up\t\t-- scroll up\n" - "l\t\t-- scroll right\n" - "+\t\t-- zoom in\n" - "-\t\t-- zoom out\n" - "W\t\t-- zoom to fit window width\n" - "H\t\t-- zoom to fit window height\n" - "w\t\t-- shrinkwrap\n" - "f\t\t-- fullscreen\n" - "r\t\t-- reload file\n" - ". pgdn right spc\t-- next page\n" - ", pgup left b bkspc\t-- previous page\n" - ">\t\t-- next 10 pages\n" - "<\t\t-- back 10 pages\n" - "m\t\t-- mark page for snap back\n" - "t\t\t-- pop back to latest mark\n" - "1m\t\t-- mark page in register 1\n" - "1t\t\t-- go to page in register 1\n" - "G\t\t-- go to last page\n" - "123g\t\t-- go to page 123\n" - "/\t\t-- search forwards for text\n" - "?\t\t-- search backwards for text\n" - "n\t\t-- find next search result\n" - "N\t\t-- find previous search result\n" - "c\t\t-- toggle between color and grayscale\n" - "i\t\t-- toggle inverted color mode\n" - "q\t\t-- quit\n" - ; -} - -void pdfapp_init(fz_context *ctx, pdfapp_t *app) -{ - memset(app, 0, sizeof(pdfapp_t)); - app->scrw = 640; - app->scrh = 480; - app->resolution = 72; - app->ctx = ctx; -#ifdef _WIN32 - app->colorspace = fz_device_bgr(ctx); -#else - app->colorspace = fz_device_rgb(ctx); -#endif -} - -void pdfapp_invert(pdfapp_t *app, const fz_rect *rect) -{ - fz_irect b; - fz_invert_pixmap_rect(app->image, fz_round_rect(&b, rect)); -} - -static void event_cb(pdf_doc_event *event, void *data) -{ - pdfapp_t *app = (pdfapp_t *)data; - - switch (event->type) - { - case PDF_DOCUMENT_EVENT_ALERT: - { - pdf_alert_event *alert = pdf_access_alert_event(event); - winalert(app, alert); - } - break; - - case PDF_DOCUMENT_EVENT_PRINT: - winprint(app); - break; - - case PDF_DOCUMENT_EVENT_EXEC_MENU_ITEM: - { - char *item = pdf_access_exec_menu_item_event(event); - - if (!strcmp(item, "Print")) - winprint(app); - else - pdfapp_warn(app, "The document attempted to execute menu item: %s. (Not supported)", item); - } - break; - - case PDF_DOCUMENT_EVENT_EXEC_DIALOG: - pdfapp_warn(app, "The document attempted to open a dialog box. (Not supported)"); - break; - - case PDF_DOCUMENT_EVENT_LAUNCH_URL: - { - pdf_launch_url_event *launch_url = pdf_access_launch_url_event(event); - - pdfapp_warn(app, "The document attempted to open url: %s. (Not supported by app)", launch_url->url); - } - break; - - case PDF_DOCUMENT_EVENT_MAIL_DOC: - { - pdf_mail_doc_event *mail_doc = pdf_access_mail_doc_event(event); - - pdfapp_warn(app, "The document attmepted to mail the document%s%s%s%s%s%s%s%s (Not supported)", - mail_doc->to[0]?", To: ":"", mail_doc->to, - mail_doc->cc[0]?", Cc: ":"", mail_doc->cc, - mail_doc->bcc[0]?", Bcc: ":"", mail_doc->bcc, - mail_doc->subject[0]?", Subject: ":"", mail_doc->subject); - } - break; - } -} - -void pdfapp_open(pdfapp_t *app, char *filename, int reload) -{ - fz_context *ctx = app->ctx; - char *password = ""; - - fz_try(ctx) - { - pdf_document *idoc; - - app->doc = fz_open_document(ctx, filename); - - idoc = pdf_specifics(app->doc); - - if (idoc) - pdf_set_doc_event_callback(idoc, event_cb, app); - - if (fz_needs_password(app->doc)) - { - int okay = fz_authenticate_password(app->doc, password); - while (!okay) - { - password = winpassword(app, filename); - if (!password) - fz_throw(ctx, FZ_ERROR_GENERIC, "Needs a password"); - okay = fz_authenticate_password(app->doc, password); - if (!okay) - pdfapp_warn(app, "Invalid password."); - } - } - - app->docpath = fz_strdup(ctx, filename); - app->doctitle = filename; - if (strrchr(app->doctitle, '\\')) - app->doctitle = strrchr(app->doctitle, '\\') + 1; - if (strrchr(app->doctitle, '/')) - app->doctitle = strrchr(app->doctitle, '/') + 1; - app->doctitle = fz_strdup(ctx, app->doctitle); - - app->pagecount = fz_count_pages(app->doc); - app->outline = fz_load_outline(app->doc); - } - fz_catch(ctx) - { - pdfapp_error(app, "cannot open document"); - } - - if (app->pageno < 1) - app->pageno = 1; - if (app->pageno > app->pagecount) - app->pageno = app->pagecount; - if (app->resolution < MINRES) - app->resolution = MINRES; - if (app->resolution > MAXRES) - app->resolution = MAXRES; - - if (!reload) - { - app->shrinkwrap = 1; - app->rotate = 0; - app->panx = 0; - app->pany = 0; - } - - pdfapp_showpage(app, 1, 1, 1, 0); -} - -void pdfapp_close(pdfapp_t *app) -{ - fz_drop_display_list(app->ctx, app->page_list); - app->page_list = NULL; - - fz_drop_display_list(app->ctx, app->annotations_list); - app->annotations_list = NULL; - - fz_free_text_page(app->ctx, app->page_text); - app->page_text = NULL; - - fz_free_text_sheet(app->ctx, app->page_sheet); - app->page_sheet = NULL; - - fz_drop_link(app->ctx, app->page_links); - app->page_links = NULL; - - fz_free(app->ctx, app->doctitle); - app->doctitle = NULL; - - fz_free(app->ctx, app->docpath); - app->docpath = NULL; - - fz_drop_pixmap(app->ctx, app->image); - app->image = NULL; - - fz_drop_pixmap(app->ctx, app->new_image); - app->new_image = NULL; - - fz_drop_pixmap(app->ctx, app->old_image); - app->old_image = NULL; - - fz_free_outline(app->ctx, app->outline); - app->outline = NULL; - - fz_free_page(app->doc, app->page); - app->page = NULL; - - fz_close_document(app->doc); - app->doc = NULL; - - fz_flush_warnings(app->ctx); -} - -static int gen_tmp_file(char *buf, int len) -{ - int i; - char *name = strrchr(buf, '/'); - - if (name == NULL) - name = strrchr(buf, '\\'); - - if (name != NULL) - name++; - else - name = buf; - - for (i = 0; i < 10000; i++) - { - FILE *f; - snprintf(name, buf+len-name, "tmp%04d", i); - f = fopen(buf, "r"); - if (f == NULL) - return 1; - fclose(f); - } - - return 0; -} - -static int pdfapp_save(pdfapp_t *app) -{ - char buf[PATH_MAX]; - - if (wingetsavepath(app, buf, PATH_MAX)) - { - fz_write_options opts; - - opts.do_ascii = 1; - opts.do_expand = 0; - opts.do_garbage = 1; - opts.do_linear = 0; - - if (strcmp(buf, app->docpath) != 0) - { - fz_write_document(app->doc, buf, &opts); - return 1; - } - - if (gen_tmp_file(buf, PATH_MAX)) - { - int written; - - fz_try(app->ctx) - { - fz_write_document(app->doc, buf, &opts); - written = 1; - } - fz_catch(app->ctx) - { - written = 0; - } - - if (written) - { - char buf2[PATH_MAX]; - fz_strlcpy(buf2, app->docpath, PATH_MAX); - pdfapp_close(app); - winreplacefile(buf, buf2); - pdfapp_open(app, buf2, 1); - - return written; - } - } - } - - return 0; -} - -int pdfapp_preclose(pdfapp_t *app) -{ - pdf_document *idoc = pdf_specifics(app->doc); - - if (idoc && pdf_has_unsaved_changes(idoc)) - { - switch (winsavequery(app)) - { - case DISCARD: - return 1; - - case CANCEL: - return 0; - - case SAVE: - return pdfapp_save(app); - } - } - - return 1; -} - -static void pdfapp_viewctm(fz_matrix *mat, pdfapp_t *app) -{ - fz_pre_rotate(fz_scale(mat, app->resolution/72.0f, app->resolution/72.0f), app->rotate); -} - -static void pdfapp_panview(pdfapp_t *app, int newx, int newy) -{ - int image_w = fz_pixmap_width(app->ctx, app->image); - int image_h = fz_pixmap_height(app->ctx, app->image); - - if (newx > 0) - newx = 0; - if (newy > 0) - newy = 0; - - if (newx + image_w < app->winw) - newx = app->winw - image_w; - if (newy + image_h < app->winh) - newy = app->winh - image_h; - - if (app->winw >= image_w) - newx = (app->winw - image_w) / 2; - if (app->winh >= image_h) - newy = (app->winh - image_h) / 2; - - if (newx != app->panx || newy != app->pany) - winrepaint(app); - - app->panx = newx; - app->pany = newy; -} - -static void pdfapp_loadpage(pdfapp_t *app) -{ - fz_device *mdev = NULL; - int errored = 0; - fz_cookie cookie = { 0 }; - - fz_var(mdev); - - fz_drop_display_list(app->ctx, app->page_list); - fz_drop_display_list(app->ctx, app->annotations_list); - fz_free_text_page(app->ctx, app->page_text); - fz_free_text_sheet(app->ctx, app->page_sheet); - fz_drop_link(app->ctx, app->page_links); - fz_free_page(app->doc, app->page); - - app->page_list = NULL; - app->annotations_list = NULL; - app->page_text = NULL; - app->page_sheet = NULL; - app->page_links = NULL; - app->page = NULL; - app->page_bbox.x0 = 0; - app->page_bbox.y0 = 0; - app->page_bbox.x1 = 100; - app->page_bbox.y1 = 100; - - fz_try(app->ctx) - { - app->page = fz_load_page(app->doc, app->pageno - 1); - - fz_bound_page(app->doc, app->page, &app->page_bbox); - } - fz_catch(app->ctx) - { - pdfapp_warn(app, "Cannot load page"); - return; - } - - fz_try(app->ctx) - { - fz_annot *annot; - /* Create display lists */ - app->page_list = fz_new_display_list(app->ctx); - mdev = fz_new_list_device(app->ctx, app->page_list); - fz_run_page_contents(app->doc, app->page, mdev, &fz_identity, &cookie); - fz_free_device(mdev); - mdev = NULL; - app->annotations_list = fz_new_display_list(app->ctx); - mdev = fz_new_list_device(app->ctx, app->annotations_list); - for (annot = fz_first_annot(app->doc, app->page); annot; annot = fz_next_annot(app->doc, annot)) - fz_run_annot(app->doc, app->page, annot, mdev, &fz_identity, &cookie); - if (cookie.errors) - { - pdfapp_warn(app, "Errors found on page"); - errored = 1; - } - } - fz_always(app->ctx) - { - fz_free_device(mdev); - } - fz_catch(app->ctx) - { - pdfapp_warn(app, "Cannot load page"); - errored = 1; - } - - fz_try(app->ctx) - { - app->page_links = fz_load_links(app->doc, app->page); - } - fz_catch(app->ctx) - { - if (!errored) - pdfapp_warn(app, "Cannot load page"); - } - - app->errored = errored; -} - -static void pdfapp_recreate_annotationslist(pdfapp_t *app) -{ - fz_device *mdev = NULL; - int errored = 0; - fz_cookie cookie = { 0 }; - - fz_var(mdev); - - fz_drop_display_list(app->ctx, app->annotations_list); - app->annotations_list = NULL; - - fz_try(app->ctx) - { - fz_annot *annot; - /* Create display list */ - app->annotations_list = fz_new_display_list(app->ctx); - mdev = fz_new_list_device(app->ctx, app->annotations_list); - for (annot = fz_first_annot(app->doc, app->page); annot; annot = fz_next_annot(app->doc, annot)) - fz_run_annot(app->doc, app->page, annot, mdev, &fz_identity, &cookie); - if (cookie.errors) - { - pdfapp_warn(app, "Errors found on page"); - errored = 1; - } - } - fz_always(app->ctx) - { - fz_free_device(mdev); - } - fz_catch(app->ctx) - { - pdfapp_warn(app, "Cannot load page"); - errored = 1; - } - - app->errored = errored; -} - -static void pdfapp_runpage(pdfapp_t *app, fz_device *dev, const fz_matrix *ctm, const fz_rect *rect, fz_cookie *cookie) -{ - fz_begin_page(dev, rect, ctm); - if (app->page_list) - fz_run_display_list(app->page_list, dev, ctm, rect, cookie); - if (app->annotations_list) - fz_run_display_list(app->annotations_list, dev, ctm, rect, cookie); - fz_end_page(dev); -} - -#define MAX_TITLE 256 - -static void pdfapp_updatepage(pdfapp_t *app) -{ - pdf_document *idoc = pdf_specifics(app->doc); - fz_device *idev; - fz_matrix ctm; - fz_annot *annot; - - pdfapp_viewctm(&ctm, app); - pdf_update_page(idoc, (pdf_page *)app->page); - pdfapp_recreate_annotationslist(app); - - while ((annot = (fz_annot *)pdf_poll_changed_annot(idoc, (pdf_page *)app->page)) != NULL) - { - fz_rect bounds; - fz_irect ibounds; - fz_transform_rect(fz_bound_annot(app->doc, annot, &bounds), &ctm); - fz_rect_from_irect(&bounds, fz_round_rect(&ibounds, &bounds)); - fz_clear_pixmap_rect_with_value(app->ctx, app->image, 255, &ibounds); - idev = fz_new_draw_device_with_bbox(app->ctx, app->image, &ibounds); - pdfapp_runpage(app, idev, &ctm, &bounds, NULL); - fz_free_device(idev); - } - - pdfapp_showpage(app, 0, 0, 1, 0); -} - -static void pdfapp_showpage(pdfapp_t *app, int loadpage, int drawpage, int repaint, int transition) -{ - char buf[MAX_TITLE]; - fz_device *idev; - fz_device *tdev; - fz_colorspace *colorspace; - fz_matrix ctm; - fz_rect bounds; - fz_irect ibounds; - fz_cookie cookie = { 0 }; - - if (!app->nowaitcursor) - wincursor(app, WAIT); - - if (!app->transitions_enabled || !app->presentation_mode) - transition = 0; - - if (transition) - { - app->old_image = app->image; - app->image = NULL; - } - - if (loadpage) - { - pdfapp_loadpage(app); - - /* Zero search hit position */ - app->hit_count = 0; - - /* Extract text */ - app->page_sheet = fz_new_text_sheet(app->ctx); - app->page_text = fz_new_text_page(app->ctx); - - if (app->page_list || app->annotations_list) - { - tdev = fz_new_text_device(app->ctx, app->page_sheet, app->page_text); - pdfapp_runpage(app, tdev, &fz_identity, &fz_infinite_rect, &cookie); - fz_free_device(tdev); - } - } - - if (drawpage) - { - char buf2[64]; - int len; - - sprintf(buf2, " - %d/%d (%d dpi)", - app->pageno, app->pagecount, app->resolution); - len = MAX_TITLE-strlen(buf2); - if ((int)strlen(app->doctitle) > len) - { - snprintf(buf, len-3, "%s", app->doctitle); - strcat(buf, "..."); - strcat(buf, buf2); - } - else - sprintf(buf, "%s%s", app->doctitle, buf2); - wintitle(app, buf); - - pdfapp_viewctm(&ctm, app); - bounds = app->page_bbox; - fz_round_rect(&ibounds, fz_transform_rect(&bounds, &ctm)); - fz_rect_from_irect(&bounds, &ibounds); - - /* Draw */ - if (app->image) - fz_drop_pixmap(app->ctx, app->image); - if (app->grayscale) - colorspace = fz_device_gray(app->ctx); - else - colorspace = app->colorspace; - app->image = NULL; - app->image = fz_new_pixmap_with_bbox(app->ctx, colorspace, &ibounds); - fz_clear_pixmap_with_value(app->ctx, app->image, 255); - if (app->page_list || app->annotations_list) - { - idev = fz_new_draw_device(app->ctx, app->image); - pdfapp_runpage(app, idev, &ctm, &bounds, &cookie); - fz_free_device(idev); - } - if (app->invert) - fz_invert_pixmap(app->ctx, app->image); - } - - if (transition) - { - fz_transition *new_trans; - app->new_image = app->image; - app->image = NULL; - app->image = fz_new_pixmap_with_bbox(app->ctx, colorspace, &ibounds); - app->duration = 0; - new_trans = fz_page_presentation(app->doc, app->page, &app->duration); - if (new_trans) - app->transition = *new_trans; - else - { - /* If no transition specified, use a default one */ - memset(&app->transition, 0, sizeof(*new_trans)); - app->transition.duration = 1.0; - app->transition.type = FZ_TRANSITION_WIPE; - app->transition.vertical = 0; - app->transition.direction = 0; - } - if (app->duration == 0) - app->duration = 5; - app->in_transit = fz_generate_transition(app->image, app->old_image, app->new_image, 0, &app->transition); - if (!app->in_transit) - { - if (app->duration != 0) - winadvancetimer(app, app->duration); - } - app->start_time = clock(); - } - - if (repaint) - { - pdfapp_panview(app, app->panx, app->pany); - - if (app->shrinkwrap) - { - int w = fz_pixmap_width(app->ctx, app->image); - int h = fz_pixmap_height(app->ctx, app->image); - if (app->winw == w) - app->panx = 0; - if (app->winh == h) - app->pany = 0; - if (w > app->scrw * 90 / 100) - w = app->scrw * 90 / 100; - if (h > app->scrh * 90 / 100) - h = app->scrh * 90 / 100; - if (w != app->winw || h != app->winh) - winresize(app, w, h); - } - - winrepaint(app); - - wincursor(app, ARROW); - } - - if (cookie.errors && app->errored == 0) - { - app->errored = 1; - pdfapp_warn(app, "Errors found on page. Page rendering may be incomplete."); - } - - fz_flush_warnings(app->ctx); -} - -static void pdfapp_gotouri(pdfapp_t *app, char *uri) -{ - winopenuri(app, uri); -} - -void pdfapp_gotopage(pdfapp_t *app, int number) -{ - app->isediting = 0; - winrepaint(app); - - if (app->histlen + 1 == 256) - { - memmove(app->hist, app->hist + 1, sizeof(int) * 255); - app->histlen --; - } - app->hist[app->histlen++] = app->pageno; - app->pageno = number + 1; - pdfapp_showpage(app, 1, 1, 1, 0); -} - -void pdfapp_inverthit(pdfapp_t *app) -{ - fz_rect bbox; - fz_matrix ctm; - int i; - - pdfapp_viewctm(&ctm, app); - - for (i = 0; i < app->hit_count; i++) - { - bbox = app->hit_bbox[i]; - pdfapp_invert(app, fz_transform_rect(&bbox, &ctm)); - } -} - -static void pdfapp_search_in_direction(pdfapp_t *app, enum panning *panto, int dir) -{ - int firstpage, page; - - wincursor(app, WAIT); - - firstpage = app->pageno; - if (app->searchpage == app->pageno) - page = app->pageno + dir; - else - page = app->pageno; - - if (page < 1) page = app->pagecount; - if (page > app->pagecount) page = 1; - - do - { - if (page != app->pageno) - { - app->pageno = page; - pdfapp_showpage(app, 1, 0, 0, 0); - } - - app->hit_count = fz_search_text_page(app->ctx, app->page_text, app->search, app->hit_bbox, nelem(app->hit_bbox)); - if (app->hit_count > 0) - { - *panto = dir == 1 ? PAN_TO_TOP : PAN_TO_BOTTOM; - app->searchpage = app->pageno; - wincursor(app, HAND); - winrepaint(app); - return; - } - - page += dir; - if (page < 1) page = app->pagecount; - if (page > app->pagecount) page = 1; - } while (page != firstpage); - - pdfapp_warn(app, "String '%s' not found.", app->search); - - app->pageno = firstpage; - pdfapp_showpage(app, 1, 0, 0, 0); - wincursor(app, HAND); - winrepaint(app); -} - -void pdfapp_onresize(pdfapp_t *app, int w, int h) -{ - if (app->winw != w || app->winh != h) - { - app->winw = w; - app->winh = h; - pdfapp_panview(app, app->panx, app->pany); - winrepaint(app); - } -} - -void pdfapp_onkey(pdfapp_t *app, int c) -{ - int oldpage = app->pageno; - enum panning panto = PAN_TO_TOP; - int loadpage = 1; - - if (app->isediting) - { - int n = strlen(app->search); - if (c < ' ') - { - if (c == '\b' && n > 0) - { - app->search[n - 1] = 0; - winrepaintsearch(app); - } - if (c == '\n' || c == '\r') - { - app->isediting = 0; - if (n > 0) - { - winrepaintsearch(app); - - if (app->searchdir < 0) - { - if (app->pageno == 1) - app->pageno = app->pagecount; - else - app->pageno--; - pdfapp_showpage(app, 1, 1, 0, 0); - } - - pdfapp_onkey(app, 'n'); - } - else - winrepaint(app); - } - if (c == '\033') - { - app->isediting = 0; - winrepaint(app); - } - } - else - { - if (n + 2 < sizeof app->search) - { - app->search[n] = c; - app->search[n + 1] = 0; - winrepaintsearch(app); - } - } - return; - } - - /* - * Save numbers typed for later - */ - - if (c >= '0' && c <= '9') - { - app->number[app->numberlen++] = c; - app->number[app->numberlen] = '\0'; - } - - switch (c) - { - - case 'q': - winclose(app); - break; - - /* - * Zoom and rotate - */ - - case '+': - case '=': - app->resolution *= ZOOMSTEP; - if (app->resolution > MAXRES) - app->resolution = MAXRES; - pdfapp_showpage(app, 0, 1, 1, 0); - break; - case '-': - app->resolution /= ZOOMSTEP; - if (app->resolution < MINRES) - app->resolution = MINRES; - pdfapp_showpage(app, 0, 1, 1, 0); - break; - - case 'W': - app->resolution *= (double) app->winw / (double) fz_pixmap_width(app->ctx, app->image); - if (app->resolution > MAXRES) - app->resolution = MAXRES; - else if (app->resolution < MINRES) - app->resolution = MINRES; - pdfapp_showpage(app, 0, 1, 1, 0); - break; - case 'H': - app->resolution *= (double) app->winh / (double) fz_pixmap_height(app->ctx, app->image); - if (app->resolution > MAXRES) - app->resolution = MAXRES; - else if (app->resolution < MINRES) - app->resolution = MINRES; - pdfapp_showpage(app, 0, 1, 1, 0); - break; - - case 'L': - app->rotate -= 90; - pdfapp_showpage(app, 0, 1, 1, 0); - break; - case 'R': - app->rotate += 90; - pdfapp_showpage(app, 0, 1, 1, 0); - break; - - case 'c': - app->grayscale ^= 1; - pdfapp_showpage(app, 0, 1, 1, 0); - break; - - case 'i': - app->invert ^= 1; - pdfapp_showpage(app, 0, 1, 1, 0); - break; - -#ifndef NDEBUG - case 'a': - app->rotate -= 15; - pdfapp_showpage(app, 0, 1, 1, 0); - break; - case 's': - app->rotate += 15; - pdfapp_showpage(app, 0, 1, 1, 0); - break; -#endif - - /* - * Pan view, but don't need to repaint image - */ - - case 'f': - app->shrinkwrap = 0; - winfullscreen(app, !app->fullscreen); - app->fullscreen = !app->fullscreen; - break; - - case 'w': - if (app->fullscreen) - { - winfullscreen(app, 0); - app->fullscreen = 0; - } - app->shrinkwrap = 1; - app->panx = app->pany = 0; - pdfapp_showpage(app, 0, 0, 1, 0); - break; - - case 'h': - app->panx += fz_pixmap_width(app->ctx, app->image) / 10; - pdfapp_showpage(app, 0, 0, 1, 0); - break; - - case 'j': - app->pany -= fz_pixmap_height(app->ctx, app->image) / 10; - pdfapp_showpage(app, 0, 0, 1, 0); - break; - - case 'k': - app->pany += fz_pixmap_height(app->ctx, app->image) / 10; - pdfapp_showpage(app, 0, 0, 1, 0); - break; - - case 'l': - app->panx -= fz_pixmap_width(app->ctx, app->image) / 10; - pdfapp_showpage(app, 0, 0, 1, 0); - break; - - /* - * Page navigation - */ - - case 'g': - case '\n': - case '\r': - if (app->numberlen > 0) - app->pageno = atoi(app->number); - else - app->pageno = 1; - break; - - case 'G': - app->pageno = app->pagecount; - break; - - case 'm': - if (app->numberlen > 0) - { - int idx = atoi(app->number); - - if (idx >= 0 && idx < nelem(app->marks)) - app->marks[idx] = app->pageno; - } - else - { - if (app->histlen + 1 == 256) - { - memmove(app->hist, app->hist + 1, sizeof(int) * 255); - app->histlen --; - } - app->hist[app->histlen++] = app->pageno; - } - break; - - case 't': - if (app->numberlen > 0) - { - int idx = atoi(app->number); - - if (idx >= 0 && idx < nelem(app->marks)) - if (app->marks[idx] > 0) - app->pageno = app->marks[idx]; - } - else if (app->histlen > 0) - app->pageno = app->hist[--app->histlen]; - break; - - case 'p': - app->presentation_mode = !app->presentation_mode; - break; - - /* - * Back and forth ... - */ - - case ',': - panto = PAN_TO_BOTTOM; - if (app->numberlen > 0) - app->pageno -= atoi(app->number); - else - app->pageno--; - break; - - case '.': - panto = PAN_TO_TOP; - if (app->numberlen > 0) - app->pageno += atoi(app->number); - else - app->pageno++; - break; - - case '\b': - case 'b': - panto = DONT_PAN; - if (app->numberlen > 0) - app->pageno -= atoi(app->number); - else - app->pageno--; - break; - - case ' ': - panto = DONT_PAN; - if (app->numberlen > 0) - app->pageno += atoi(app->number); - else - app->pageno++; - break; - - case '<': - panto = PAN_TO_TOP; - app->pageno -= 10; - break; - case '>': - panto = PAN_TO_TOP; - app->pageno += 10; - break; - - /* - * Saving the file - */ - case 'S': - pdfapp_save(app); - break; - - /* - * Reloading the file... - */ - - case 'r': - panto = DONT_PAN; - oldpage = -1; - winreloadfile(app); - break; - - /* - * Searching - */ - - case '?': - app->isediting = 1; - app->searchdir = -1; - app->search[0] = 0; - app->hit_count = 0; - app->searchpage = -1; - winrepaintsearch(app); - break; - - case '/': - app->isediting = 1; - app->searchdir = 1; - app->search[0] = 0; - app->hit_count = 0; - app->searchpage = -1; - winrepaintsearch(app); - break; - - case 'n': - if (app->searchdir > 0) - pdfapp_search_in_direction(app, &panto, 1); - else - pdfapp_search_in_direction(app, &panto, -1); - loadpage = 0; - break; - - case 'N': - if (app->searchdir > 0) - pdfapp_search_in_direction(app, &panto, -1); - else - pdfapp_search_in_direction(app, &panto, 1); - loadpage = 0; - break; - - } - - if (c < '0' || c > '9') - app->numberlen = 0; - - if (app->pageno < 1) - app->pageno = 1; - if (app->pageno > app->pagecount) - app->pageno = app->pagecount; - - if (app->pageno != oldpage) - { - switch (panto) - { - case PAN_TO_TOP: - app->pany = 0; - break; - case PAN_TO_BOTTOM: - app->pany = -2000; - break; - case DONT_PAN: - break; - } - pdfapp_showpage(app, loadpage, 1, 1, 1); - } -} - -void pdfapp_onmouse(pdfapp_t *app, int x, int y, int btn, int modifiers, int state) -{ - fz_context *ctx = app->ctx; - fz_irect irect; - fz_link *link; - fz_matrix ctm; - fz_point p; - int processed = 0; - - fz_pixmap_bbox(app->ctx, app->image, &irect); - p.x = x - app->panx + irect.x0; - p.y = y - app->pany + irect.y0; - - pdfapp_viewctm(&ctm, app); - fz_invert_matrix(&ctm, &ctm); - - fz_transform_point(&p, &ctm); - - if (btn == 1 && (state == 1 || state == -1)) - { - pdf_ui_event event; - pdf_document *idoc = pdf_specifics(app->doc); - - event.etype = PDF_EVENT_TYPE_POINTER; - event.event.pointer.pt = p; - if (state == 1) - event.event.pointer.ptype = PDF_POINTER_DOWN; - else /* state == -1 */ - event.event.pointer.ptype = PDF_POINTER_UP; - - if (idoc && pdf_pass_event(idoc, (pdf_page *)app->page, &event)) - { - pdf_widget *widget; - - widget = pdf_focused_widget(idoc); - - app->nowaitcursor = 1; - pdfapp_updatepage(app); - - if (widget) - { - switch (pdf_widget_get_type(widget)) - { - case PDF_WIDGET_TYPE_TEXT: - { - char *text = pdf_text_widget_text(idoc, widget); - char *current_text = text; - int retry = 0; - - do - { - current_text = wintextinput(app, current_text, retry); - retry = 1; - } - while (current_text && !pdf_text_widget_set_text(idoc, widget, current_text)); - - fz_free(app->ctx, text); - pdfapp_updatepage(app); - } - break; - - case PDF_WIDGET_TYPE_LISTBOX: - case PDF_WIDGET_TYPE_COMBOBOX: - { - int nopts; - int nvals; - char **opts = NULL; - char **vals = NULL; - - fz_var(opts); - fz_var(vals); - - fz_try(ctx) - { - nopts = pdf_choice_widget_options(idoc, widget, NULL); - opts = fz_malloc(ctx, nopts * sizeof(*opts)); - (void)pdf_choice_widget_options(idoc, widget, opts); - - nvals = pdf_choice_widget_value(idoc, widget, NULL); - vals = fz_malloc(ctx, MAX(nvals,nopts) * sizeof(*vals)); - (void)pdf_choice_widget_value(idoc, widget, vals); - - if (winchoiceinput(app, nopts, opts, &nvals, vals)) - { - pdf_choice_widget_set_value(idoc, widget, nvals, vals); - pdfapp_updatepage(app); - } - } - fz_always(ctx) - { - fz_free(ctx, opts); - fz_free(ctx, vals); - } - fz_catch(ctx) - { - pdfapp_warn(app, "setting of choice failed"); - } - } - break; - - case PDF_WIDGET_TYPE_SIGNATURE: - { - char ebuf[256]; - - ebuf[0] = 0; - if (pdf_check_signature(ctx, idoc, widget, app->docpath, ebuf, sizeof(ebuf))) - { - winwarn(app, "Signature is valid"); - } - else - { - if (ebuf[0] == 0) - winwarn(app, "Signature check failed for unknown reason"); - else - winwarn(app, ebuf); - } - } - break; - } - } - - app->nowaitcursor = 0; - processed = 1; - } - } - - for (link = app->page_links; link; link = link->next) - { - if (p.x >= link->rect.x0 && p.x <= link->rect.x1) - if (p.y >= link->rect.y0 && p.y <= link->rect.y1) - break; - } - - if (link) - { - wincursor(app, HAND); - if (btn == 1 && state == 1 && !processed) - { - if (link->dest.kind == FZ_LINK_URI) - pdfapp_gotouri(app, link->dest.ld.uri.uri); - else if (link->dest.kind == FZ_LINK_GOTO) - pdfapp_gotopage(app, link->dest.ld.gotor.page); - return; - } - } - else - { - fz_annot *annot; - for (annot = fz_first_annot(app->doc, app->page); annot; annot = fz_next_annot(app->doc, annot)) - { - fz_rect rect; - fz_bound_annot(app->doc, annot, &rect); - if (x >= rect.x0 && x < rect.x1) - if (y >= rect.y0 && y < rect.y1) - break; - } - if (annot) - wincursor(app, CARET); - else - wincursor(app, ARROW); - } - - if (state == 1 && !processed) - { - if (btn == 1 && !app->iscopying) - { - app->ispanning = 1; - app->selx = x; - app->sely = y; - app->beyondy = 0; - } - if (btn == 3 && !app->ispanning) - { - app->iscopying = 1; - app->selx = x; - app->sely = y; - app->selr.x0 = x; - app->selr.x1 = x; - app->selr.y0 = y; - app->selr.y1 = y; - } - if (btn == 4 || btn == 5) /* scroll wheel */ - { - int dir = btn == 4 ? 1 : -1; - app->ispanning = app->iscopying = 0; - if (modifiers & (1<<2)) - { - /* zoom in/out if ctrl is pressed */ - if (dir > 0) - app->resolution *= ZOOMSTEP; - else - app->resolution /= ZOOMSTEP; - if (app->resolution > MAXRES) - app->resolution = MAXRES; - if (app->resolution < MINRES) - app->resolution = MINRES; - pdfapp_showpage(app, 0, 1, 1, 0); - } - else - { - /* scroll up/down, or left/right if - shift is pressed */ - int isx = (modifiers & (1<<0)); - int xstep = isx ? 20 * dir : 0; - int ystep = !isx ? 20 * dir : 0; - pdfapp_panview(app, app->panx + xstep, app->pany + ystep); - } - } - } - - else if (state == -1) - { - if (app->iscopying) - { - app->iscopying = 0; - app->selr.x0 = fz_mini(app->selx, x) - app->panx + irect.x0; - app->selr.x1 = fz_maxi(app->selx, x) - app->panx + irect.x0; - app->selr.y0 = fz_mini(app->sely, y) - app->pany + irect.y0; - app->selr.y1 = fz_maxi(app->sely, y) - app->pany + irect.y0; - winrepaint(app); - if (app->selr.x0 < app->selr.x1 && app->selr.y0 < app->selr.y1) - windocopy(app); - } - app->ispanning = 0; - } - - else if (app->ispanning) - { - int newx = app->panx + x - app->selx; - int newy = app->pany + y - app->sely; - /* Scrolling beyond limits implies flipping pages */ - /* Are we requested to scroll beyond limits? */ - if (newy + fz_pixmap_height(app->ctx, app->image) < app->winh || newy > 0) - { - /* Yes. We can assume that deltay != 0 */ - int deltay = y - app->sely; - /* Check whether the panning has occurred in the - * direction that we are already crossing the - * limit it. If not, we can conclude that we - * have switched ends of the page and will thus - * start over counting. - */ - if( app->beyondy == 0 || (app->beyondy ^ deltay) >= 0 ) - { - /* Updating how far we are beyond and - * flipping pages if beyond threshold - */ - app->beyondy += deltay; - if (app->beyondy > BEYOND_THRESHHOLD) - { - if( app->pageno > 1 ) - { - app->pageno--; - pdfapp_showpage(app, 1, 1, 1, 0); - newy = -fz_pixmap_height(app->ctx, app->image); - } - app->beyondy = 0; - } - else if (app->beyondy < -BEYOND_THRESHHOLD) - { - if( app->pageno < app->pagecount ) - { - app->pageno++; - pdfapp_showpage(app, 1, 1, 1, 0); - newy = 0; - } - app->beyondy = 0; - } - } - else - app->beyondy = 0; - } - /* Although at this point we've already determined that - * or that no scrolling will be performed in - * y-direction, the x-direction has not yet been taken - * care off. Therefore - */ - pdfapp_panview(app, newx, newy); - - app->selx = x; - app->sely = y; - } - - else if (app->iscopying) - { - app->selr.x0 = fz_mini(app->selx, x) - app->panx + irect.x0; - app->selr.x1 = fz_maxi(app->selx, x) - app->panx + irect.x0; - app->selr.y0 = fz_mini(app->sely, y) - app->pany + irect.y0; - app->selr.y1 = fz_maxi(app->sely, y) - app->pany + irect.y0; - winrepaint(app); - } - -} - -void pdfapp_oncopy(pdfapp_t *app, unsigned short *ucsbuf, int ucslen) -{ - fz_rect hitbox; - fz_matrix ctm; - fz_text_page *page = app->page_text; - int c, i, p; - int seen = 0; - int block_num; - - int x0 = app->selr.x0; - int x1 = app->selr.x1; - int y0 = app->selr.y0; - int y1 = app->selr.y1; - - pdfapp_viewctm(&ctm, app); - - p = 0; - - for (block_num = 0; block_num < page->len; block_num++) - { - fz_text_line *line; - fz_text_block *block; - fz_text_span *span; - - if (page->blocks[block_num].type != FZ_PAGE_BLOCK_TEXT) - continue; - block = page->blocks[block_num].u.text; - - for (line = block->lines; line < block->lines + block->len; line++) - { - for (span = line->first_span; span; span = span->next) - { - if (seen) - { -#ifdef _WIN32 - if (p < ucslen - 1) - ucsbuf[p++] = '\r'; -#endif - if (p < ucslen - 1) - ucsbuf[p++] = '\n'; - } - - seen = 0; - - for (i = 0; i < span->len; i++) - { - fz_text_char_bbox(&hitbox, span, i); - fz_transform_rect(&hitbox, &ctm); - c = span->text[i].c; - if (c < 32) - c = '?'; - if (hitbox.x1 >= x0 && hitbox.x0 <= x1 && hitbox.y1 >= y0 && hitbox.y0 <= y1) - { - if (p < ucslen - 1) - ucsbuf[p++] = c; - seen = 1; - } - } - - seen = (seen && span == line->last_span); - } - } - } - - ucsbuf[p] = 0; -} - -void pdfapp_postblit(pdfapp_t *app) -{ - clock_t time; - float seconds; - int llama; - - app->transitions_enabled = 1; - if (!app->in_transit) - return; - time = clock(); - seconds = (float)(time - app->start_time) / CLOCKS_PER_SEC; - llama = seconds * 256 / app->transition.duration; - if (llama >= 256) - { - /* Completed. */ - fz_drop_pixmap(app->ctx, app->image); - app->image = app->new_image; - app->new_image = NULL; - fz_drop_pixmap(app->ctx, app->old_image); - app->old_image = NULL; - if (app->duration != 0) - winadvancetimer(app, app->duration); - } - else - fz_generate_transition(app->image, app->old_image, app->new_image, llama, &app->transition); - winrepaint(app); - if (llama >= 256) - { - /* Completed. */ - app->in_transit = 0; - } -} diff --git a/apps/pdfapp.h b/apps/pdfapp.h deleted file mode 100644 index 3e40e0c4..00000000 --- a/apps/pdfapp.h +++ /dev/null @@ -1,149 +0,0 @@ -#ifndef PDFAPP_H -#define PDFAPP_H - -#include "mupdf/fitz.h" -#include "mupdf/pdf.h" - -/* - * Utility object for handling a pdf application / view - * Takes care of PDF loading and displaying and navigation, - * uses a number of callbacks to the GUI app. - */ - -#define MINRES 54 -#define MAXRES 300 - -typedef struct pdfapp_s pdfapp_t; - -enum { ARROW, HAND, WAIT, CARET }; - -enum { DISCARD, SAVE, CANCEL }; - -extern void winwarn(pdfapp_t*, char *s); -extern void winerror(pdfapp_t*, char *s); -extern void wintitle(pdfapp_t*, char *title); -extern void winresize(pdfapp_t*, int w, int h); -extern void winrepaint(pdfapp_t*); -extern void winrepaintsearch(pdfapp_t*); -extern char *winpassword(pdfapp_t*, char *filename); -extern char *wintextinput(pdfapp_t*, char *inittext, int retry); -extern int winchoiceinput(pdfapp_t*, int nopts, char *opts[], int *nvals, char *vals[]); -extern void winopenuri(pdfapp_t*, char *s); -extern void wincursor(pdfapp_t*, int curs); -extern void windocopy(pdfapp_t*); -extern void winreloadfile(pdfapp_t*); -extern void windrawstring(pdfapp_t*, int x, int y, char *s); -extern void winclose(pdfapp_t*); -extern void winhelp(pdfapp_t*); -extern void winfullscreen(pdfapp_t*, int state); -extern int winsavequery(pdfapp_t*); -extern int wingetsavepath(pdfapp_t*, char *buf, int len); -extern void winalert(pdfapp_t *, pdf_alert_event *alert); -extern void winprint(pdfapp_t *); -extern void winadvancetimer(pdfapp_t *, float duration); -extern void winreplacefile(char *source, char *target); - -struct pdfapp_s -{ - /* current document params */ - fz_document *doc; - char *docpath; - char *doctitle; - fz_outline *outline; - - int pagecount; - - /* current view params */ - int resolution; - int rotate; - fz_pixmap *image; - int grayscale; - fz_colorspace *colorspace; - int invert; - - /* presentation mode */ - int presentation_mode; - int transitions_enabled; - fz_pixmap *old_image; - fz_pixmap *new_image; - clock_t start_time; - int in_transit; - float duration; - fz_transition transition; - - /* current page params */ - int pageno; - fz_page *page; - fz_rect page_bbox; - fz_display_list *page_list; - fz_display_list *annotations_list; - fz_text_page *page_text; - fz_text_sheet *page_sheet; - fz_link *page_links; - int errored; - - /* snapback history */ - int hist[256]; - int histlen; - int marks[10]; - - /* window system sizes */ - int winw, winh; - int scrw, scrh; - int shrinkwrap; - int fullscreen; - - /* event handling state */ - char number[256]; - int numberlen; - - int ispanning; - int panx, pany; - - int iscopying; - int selx, sely; - /* TODO - While sely keeps track of the relative change in - * cursor position between two ticks/events, beyondy shall keep - * track of the relative change in cursor position from the - * point where the user hits a scrolling limit. This is ugly. - * Used in pdfapp.c:pdfapp_onmouse. - */ - int beyondy; - fz_rect selr; - - int nowaitcursor; - - /* search state */ - int isediting; - int searchdir; - char search[512]; - int searchpage; - fz_rect hit_bbox[512]; - int hit_count; - - /* client context storage */ - void *userdata; - - fz_context *ctx; -}; - -void pdfapp_init(fz_context *ctx, pdfapp_t *app); -void pdfapp_open(pdfapp_t *app, char *filename, int reload); -void pdfapp_close(pdfapp_t *app); -int pdfapp_preclose(pdfapp_t *app); - -char *pdfapp_version(pdfapp_t *app); -char *pdfapp_usage(pdfapp_t *app); - -void pdfapp_onkey(pdfapp_t *app, int c); -void pdfapp_onmouse(pdfapp_t *app, int x, int y, int btn, int modifiers, int state); -void pdfapp_oncopy(pdfapp_t *app, unsigned short *ucsbuf, int ucslen); -void pdfapp_onresize(pdfapp_t *app, int w, int h); -void pdfapp_gotopage(pdfapp_t *app, int number); - -void pdfapp_invert(pdfapp_t *app, const fz_rect *rect); -void pdfapp_inverthit(pdfapp_t *app); - -void pdfapp_postblit(pdfapp_t *app); - -#endif diff --git a/apps/pdfclean.c b/apps/pdfclean.c deleted file mode 100644 index c437b819..00000000 --- a/apps/pdfclean.c +++ /dev/null @@ -1,237 +0,0 @@ -/* - * PDF cleaning tool: general purpose pdf syntax washer. - * - * Rewrite PDF with pretty printed objects. - * Garbage collect unreachable objects. - * Inflate compressed streams. - * Create subset documents. - * - * TODO: linearize document for fast web view - */ - -#include "mupdf/pdf.h" - -static pdf_document *xref = NULL; -static fz_context *ctx = NULL; - -static void usage(void) -{ - fprintf(stderr, - "usage: mutool clean [options] input.pdf [output.pdf] [pages]\n" - "\t-p -\tpassword\n" - "\t-g\tgarbage collect unused objects\n" - "\t-gg\tin addition to -g compact xref table\n" - "\t-ggg\tin addition to -gg merge duplicate objects\n" - "\t-d\tdecompress all streams\n" - "\t-l\tlinearize PDF\n" - "\t-i\ttoggle decompression of image streams\n" - "\t-f\ttoggle decompression of font streams\n" - "\t-a\tascii hex encode binary streams\n" - "\tpages\tcomma separated list of ranges\n"); - exit(1); -} - -/* - * Recreate page tree to only retain specified pages. - */ - -static void retainpages(int argc, char **argv) -{ - pdf_obj *oldroot, *root, *pages, *kids, *countobj, *parent, *olddests; - - /* Keep only pages/type and (reduced) dest entries to avoid - * references to unretained pages */ - oldroot = pdf_dict_gets(pdf_trailer(xref), "Root"); - pages = pdf_dict_gets(oldroot, "Pages"); - olddests = pdf_load_name_tree(xref, "Dests"); - - root = pdf_new_dict(ctx, 2); - pdf_dict_puts(root, "Type", pdf_dict_gets(oldroot, "Type")); - pdf_dict_puts(root, "Pages", pdf_dict_gets(oldroot, "Pages")); - - pdf_update_object(xref, pdf_to_num(oldroot), root); - - pdf_drop_obj(root); - - /* Create a new kids array with only the pages we want to keep */ - parent = pdf_new_indirect(ctx, pdf_to_num(pages), pdf_to_gen(pages), xref); - kids = pdf_new_array(ctx, 1); - - /* Retain pages specified */ - while (argc - fz_optind) - { - int page, spage, epage, pagecount; - char *spec, *dash; - char *pagelist = argv[fz_optind]; - - pagecount = pdf_count_pages(xref); - spec = fz_strsep(&pagelist, ","); - while (spec) - { - dash = strchr(spec, '-'); - - if (dash == spec) - spage = epage = pagecount; - else - spage = epage = atoi(spec); - - if (dash) - { - if (strlen(dash) > 1) - epage = atoi(dash + 1); - else - epage = pagecount; - } - - if (spage > epage) - page = spage, spage = epage, epage = page; - - spage = fz_clampi(spage, 1, pagecount); - epage = fz_clampi(epage, 1, pagecount); - - for (page = spage; page <= epage; page++) - { - pdf_obj *pageobj = xref->page_objs[page-1]; - pdf_obj *pageref = xref->page_refs[page-1]; - - pdf_dict_puts(pageobj, "Parent", parent); - - /* Store page object in new kids array */ - pdf_array_push(kids, pageref); - } - - spec = fz_strsep(&pagelist, ","); - } - - fz_optind++; - } - - pdf_drop_obj(parent); - - /* Update page count and kids array */ - countobj = pdf_new_int(ctx, pdf_array_len(kids)); - pdf_dict_puts(pages, "Count", countobj); - pdf_drop_obj(countobj); - pdf_dict_puts(pages, "Kids", kids); - pdf_drop_obj(kids); - - /* Also preserve the (partial) Dests name tree */ - if (olddests) - { - int i; - pdf_obj *names = pdf_new_dict(ctx, 1); - pdf_obj *dests = pdf_new_dict(ctx, 1); - pdf_obj *names_list = pdf_new_array(ctx, 32); - int len = pdf_dict_len(olddests); - - for (i = 0; i < len; i++) - { - pdf_obj *key = pdf_dict_get_key(olddests, i); - pdf_obj *val = pdf_dict_get_val(olddests, i); - pdf_obj *key_str = pdf_new_string(ctx, pdf_to_name(key), strlen(pdf_to_name(key))); - pdf_obj *dest = pdf_dict_gets(val, "D"); - - dest = pdf_array_get(dest ? dest : val, 0); - if (pdf_array_contains(pdf_dict_gets(pages, "Kids"), dest)) - { - pdf_array_push(names_list, key_str); - pdf_array_push(names_list, val); - } - pdf_drop_obj(key_str); - } - - root = pdf_dict_gets(pdf_trailer(xref), "Root"); - pdf_dict_puts(dests, "Names", names_list); - pdf_dict_puts(names, "Dests", dests); - pdf_dict_puts(root, "Names", names); - - pdf_drop_obj(names); - pdf_drop_obj(dests); - pdf_drop_obj(names_list); - pdf_drop_obj(olddests); - } -} - -int pdfclean_main(int argc, char **argv) -{ - char *infile; - char *outfile = "out.pdf"; - char *password = ""; - int c; - int subset; - fz_write_options opts; - int write_failed = 0; - int errors = 0; - - opts.do_garbage = 0; - opts.do_expand = 0; - opts.do_ascii = 0; - opts.do_linear = 0; - opts.continue_on_error = 1; - opts.errors = &errors; - - while ((c = fz_getopt(argc, argv, "adfgilp:")) != -1) - { - switch (c) - { - case 'p': password = fz_optarg; break; - case 'g': opts.do_garbage ++; break; - case 'd': opts.do_expand ^= fz_expand_all; break; - case 'f': opts.do_expand ^= fz_expand_fonts; break; - case 'i': opts.do_expand ^= fz_expand_images; break; - case 'l': opts.do_linear ++; break; - case 'a': opts.do_ascii ++; break; - default: usage(); break; - } - } - - if (argc - fz_optind < 1) - usage(); - - infile = argv[fz_optind++]; - - if (argc - fz_optind > 0 && - (strstr(argv[fz_optind], ".pdf") || strstr(argv[fz_optind], ".PDF"))) - { - outfile = argv[fz_optind++]; - } - - subset = 0; - if (argc - fz_optind > 0) - subset = 1; - - ctx = fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED); - if (!ctx) - { - fprintf(stderr, "cannot initialise context\n"); - exit(1); - } - - fz_try(ctx) - { - xref = pdf_open_document_no_run(ctx, infile); - if (pdf_needs_password(xref)) - if (!pdf_authenticate_password(xref, password)) - fz_throw(ctx, FZ_ERROR_GENERIC, "cannot authenticate password: %s", infile); - - /* Only retain the specified subset of the pages */ - if (subset) - retainpages(argc, argv); - - pdf_write_document(xref, outfile, &opts); - } - fz_always(ctx) - { - pdf_close_document(xref); - } - fz_catch(ctx) - { - write_failed = 1; - } - - fz_free_context(ctx); - - if (errors) - write_failed = 1; - return write_failed ? 1 : 0; -} diff --git a/apps/pdfextract.c b/apps/pdfextract.c deleted file mode 100644 index 6e8e4aec..00000000 --- a/apps/pdfextract.c +++ /dev/null @@ -1,231 +0,0 @@ -/* - * pdfextract -- the ultimate way to extract images and fonts from pdfs - */ - -#include "mupdf/pdf.h" - -static pdf_document *doc = NULL; -static fz_context *ctx = NULL; -static int dorgb = 0; - -static void usage(void) -{ - fprintf(stderr, "usage: mutool extract [options] file.pdf [object numbers]\n"); - fprintf(stderr, "\t-p\tpassword\n"); - fprintf(stderr, "\t-r\tconvert images to rgb\n"); - exit(1); -} - -static int isimage(pdf_obj *obj) -{ - pdf_obj *type = pdf_dict_gets(obj, "Subtype"); - return pdf_is_name(type) && !strcmp(pdf_to_name(type), "Image"); -} - -static int isfontdesc(pdf_obj *obj) -{ - pdf_obj *type = pdf_dict_gets(obj, "Type"); - return pdf_is_name(type) && !strcmp(pdf_to_name(type), "FontDescriptor"); -} - -static void writepixmap(fz_context *ctx, fz_pixmap *pix, char *file, int rgb) -{ - char name[1024]; - fz_pixmap *converted = NULL; - - if (!pix) - return; - - if (rgb && pix->colorspace && pix->colorspace != fz_device_rgb(ctx)) - { - fz_irect bbox; - converted = fz_new_pixmap_with_bbox(ctx, fz_device_rgb(ctx), fz_pixmap_bbox(ctx, pix, &bbox)); - fz_convert_pixmap(ctx, converted, pix); - pix = converted; - } - - if (pix->n <= 4) - { - sprintf(name, "%s.png", file); - printf("extracting image %s\n", name); - fz_write_png(ctx, pix, name, 0); - } - else - { - sprintf(name, "%s.pam", file); - printf("extracting image %s\n", name); - fz_write_pam(ctx, pix, name, 0); - } - - fz_drop_pixmap(ctx, converted); -} - -static void saveimage(int num) -{ - fz_image *image; - fz_pixmap *pix; - pdf_obj *ref; - char name[32]; - - ref = pdf_new_indirect(ctx, num, 0, doc); - - /* TODO: detect DCTD and save as jpeg */ - - image = pdf_load_image(doc, ref); - pix = fz_image_to_pixmap(ctx, image, 0, 0); - fz_drop_image(ctx, image); - - sprintf(name, "img-%04d", num); - writepixmap(ctx, pix, name, dorgb); - - fz_drop_pixmap(ctx, pix); - pdf_drop_obj(ref); -} - -static void savefont(pdf_obj *dict, int num) -{ - char name[1024]; - char *subtype; - fz_buffer *buf; - pdf_obj *stream = NULL; - pdf_obj *obj; - char *ext = ""; - FILE *f; - char *fontname = "font"; - int n, len; - unsigned char *data; - - obj = pdf_dict_gets(dict, "FontName"); - if (obj) - fontname = pdf_to_name(obj); - - obj = pdf_dict_gets(dict, "FontFile"); - if (obj) - { - stream = obj; - ext = "pfa"; - } - - obj = pdf_dict_gets(dict, "FontFile2"); - if (obj) - { - stream = obj; - ext = "ttf"; - } - - obj = pdf_dict_gets(dict, "FontFile3"); - if (obj) - { - stream = obj; - - obj = pdf_dict_gets(obj, "Subtype"); - if (obj && !pdf_is_name(obj)) - fz_throw(ctx, FZ_ERROR_GENERIC, "Invalid font descriptor subtype"); - - subtype = pdf_to_name(obj); - if (!strcmp(subtype, "Type1C")) - ext = "cff"; - else if (!strcmp(subtype, "CIDFontType0C")) - ext = "cid"; - else if (!strcmp(subtype, "OpenType")) - ext = "otf"; - else - fz_throw(ctx, FZ_ERROR_GENERIC, "Unhandled font type '%s'", subtype); - } - - if (!stream) - { - fz_warn(ctx, "Unhandled font type"); - return; - } - - buf = pdf_load_stream(doc, pdf_to_num(stream), pdf_to_gen(stream)); - - sprintf(name, "%s-%04d.%s", fontname, num, ext); - printf("extracting font %s\n", name); - - f = fopen(name, "wb"); - if (!f) - fz_throw(ctx, FZ_ERROR_GENERIC, "Error creating font file"); - - len = fz_buffer_storage(ctx, buf, &data); - n = fwrite(data, 1, len, f); - if (n < len) - fz_throw(ctx, FZ_ERROR_GENERIC, "Error writing font file"); - - if (fclose(f) < 0) - fz_throw(ctx, FZ_ERROR_GENERIC, "Error closing font file"); - - fz_drop_buffer(ctx, buf); -} - -static void showobject(int num) -{ - pdf_obj *obj; - - if (!doc) - fz_throw(ctx, FZ_ERROR_GENERIC, "no file specified"); - - obj = pdf_load_object(doc, num, 0); - - if (isimage(obj)) - saveimage(num); - else if (isfontdesc(obj)) - savefont(obj, num); - - pdf_drop_obj(obj); -} - -int pdfextract_main(int argc, char **argv) -{ - char *infile; - char *password = ""; - int c, o; - - while ((c = fz_getopt(argc, argv, "p:r")) != -1) - { - switch (c) - { - case 'p': password = fz_optarg; break; - case 'r': dorgb++; break; - default: usage(); break; - } - } - - if (fz_optind == argc) - usage(); - - infile = argv[fz_optind++]; - - ctx = fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED); - if (!ctx) - { - fprintf(stderr, "cannot initialise context\n"); - exit(1); - } - - doc = pdf_open_document_no_run(ctx, infile); - if (pdf_needs_password(doc)) - if (!pdf_authenticate_password(doc, password)) - fz_throw(ctx, FZ_ERROR_GENERIC, "cannot authenticate password: %s", infile); - - if (fz_optind == argc) - { - int len = pdf_count_objects(doc); - for (o = 0; o < len; o++) - showobject(o); - } - else - { - while (fz_optind < argc) - { - showobject(atoi(argv[fz_optind])); - fz_optind++; - } - } - - pdf_close_document(doc); - fz_flush_warnings(ctx); - fz_free_context(ctx); - return 0; -} diff --git a/apps/pdfinfo.c b/apps/pdfinfo.c deleted file mode 100644 index 79743892..00000000 --- a/apps/pdfinfo.c +++ /dev/null @@ -1,1032 +0,0 @@ -/* - * Information tool. - * Print information about the input pdf. - */ - -#include "mupdf/pdf.h" - -pdf_document *xref; -fz_context *ctx; -int pagecount; - -void closexref(void); - -void openxref(char *filename, char *password, int dieonbadpass, int loadpages); - -enum -{ - DIMENSIONS = 0x01, - FONTS = 0x02, - IMAGES = 0x04, - SHADINGS = 0x08, - PATTERNS = 0x10, - XOBJS = 0x20, - ALL = DIMENSIONS | FONTS | IMAGES | SHADINGS | PATTERNS | XOBJS -}; - -struct info -{ - int page; - pdf_obj *pageref; - pdf_obj *pageobj; - union { - struct { - pdf_obj *obj; - } info; - struct { - pdf_obj *obj; - } crypt; - struct { - pdf_obj *obj; - fz_rect *bbox; - } dim; - struct { - pdf_obj *obj; - pdf_obj *subtype; - pdf_obj *name; - } font; - struct { - pdf_obj *obj; - pdf_obj *width; - pdf_obj *height; - pdf_obj *bpc; - pdf_obj *filter; - pdf_obj *cs; - pdf_obj *altcs; - } image; - struct { - pdf_obj *obj; - pdf_obj *type; - } shading; - struct { - pdf_obj *obj; - pdf_obj *type; - pdf_obj *paint; - pdf_obj *tiling; - pdf_obj *shading; - } pattern; - struct { - pdf_obj *obj; - pdf_obj *groupsubtype; - pdf_obj *reference; - } form; - } u; -}; - -static struct info *dim = NULL; -static int dims = 0; -static struct info *font = NULL; -static int fonts = 0; -static struct info *image = NULL; -static int images = 0; -static struct info *shading = NULL; -static int shadings = 0; -static struct info *pattern = NULL; -static int patterns = 0; -static struct info *form = NULL; -static int forms = 0; -static struct info *psobj = NULL; -static int psobjs = 0; - -void closexref(void) -{ - int i; - if (xref) - { - pdf_close_document(xref); - xref = NULL; - } - - if (dim) - { - for (i = 0; i < dims; i++) - fz_free(ctx, dim[i].u.dim.bbox); - fz_free(ctx, dim); - dim = NULL; - dims = 0; - } - - if (font) - { - fz_free(ctx, font); - font = NULL; - fonts = 0; - } - - if (image) - { - fz_free(ctx, image); - image = NULL; - images = 0; - } - - if (shading) - { - fz_free(ctx, shading); - shading = NULL; - shadings = 0; - } - - if (pattern) - { - fz_free(ctx, pattern); - pattern = NULL; - patterns = 0; - } - - if (form) - { - fz_free(ctx, form); - form = NULL; - forms = 0; - } - - if (psobj) - { - fz_free(ctx, psobj); - psobj = NULL; - psobjs = 0; - } -} - -static void -infousage(void) -{ - fprintf(stderr, - "usage: mutool info [options] [file.pdf ... ]\n" - "\t-d -\tpassword for decryption\n" - "\t-f\tlist fonts\n" - "\t-i\tlist images\n" - "\t-m\tlist dimensions\n" - "\t-p\tlist patterns\n" - "\t-s\tlist shadings\n" - "\t-x\tlist form and postscript xobjects\n"); - exit(1); -} - -static void -showglobalinfo(void) -{ - pdf_obj *obj; - - printf("\nPDF-%d.%d\n", xref->version / 10, xref->version % 10); - - obj = pdf_dict_gets(pdf_trailer(xref), "Info"); - if (obj) - { - printf("Info object (%d %d R):\n", pdf_to_num(obj), pdf_to_gen(obj)); - pdf_fprint_obj(stdout, pdf_resolve_indirect(obj), 0); - } - - obj = pdf_dict_gets(pdf_trailer(xref), "Encrypt"); - if (obj) - { - printf("\nEncryption object (%d %d R):\n", pdf_to_num(obj), pdf_to_gen(obj)); - pdf_fprint_obj(stdout, pdf_resolve_indirect(obj), 0); - } - - printf("\nPages: %d\n\n", pagecount); -} - -static void -gatherdimensions(int page, pdf_obj *pageref, pdf_obj *pageobj) -{ - fz_rect bbox; - pdf_obj *obj; - int j; - - obj = pdf_dict_gets(pageobj, "MediaBox"); - if (!pdf_is_array(obj)) - return; - - pdf_to_rect(ctx, obj, &bbox); - - obj = pdf_dict_gets(pageobj, "UserUnit"); - if (pdf_is_real(obj)) - { - float unit = pdf_to_real(obj); - bbox.x0 *= unit; - bbox.y0 *= unit; - bbox.x1 *= unit; - bbox.y1 *= unit; - } - - for (j = 0; j < dims; j++) - if (!memcmp(dim[j].u.dim.bbox, &bbox, sizeof (fz_rect))) - break; - - if (j < dims) - return; - - dim = fz_resize_array(ctx, dim, dims+1, sizeof(struct info)); - dims++; - - dim[dims - 1].page = page; - dim[dims - 1].pageref = pageref; - dim[dims - 1].pageobj = pageobj; - dim[dims - 1].u.dim.bbox = fz_malloc(ctx, sizeof(fz_rect)); - memcpy(dim[dims - 1].u.dim.bbox, &bbox, sizeof (fz_rect)); - - return; -} - -static void -gatherfonts(int page, pdf_obj *pageref, pdf_obj *pageobj, pdf_obj *dict) -{ - int i, n; - - n = pdf_dict_len(dict); - for (i = 0; i < n; i++) - { - pdf_obj *fontdict = NULL; - pdf_obj *subtype = NULL; - pdf_obj *basefont = NULL; - pdf_obj *name = NULL; - int k; - - fontdict = pdf_dict_get_val(dict, i); - if (!pdf_is_dict(fontdict)) - { - fz_warn(ctx, "not a font dict (%d %d R)", pdf_to_num(fontdict), pdf_to_gen(fontdict)); - continue; - } - - subtype = pdf_dict_gets(fontdict, "Subtype"); - basefont = pdf_dict_gets(fontdict, "BaseFont"); - if (!basefont || pdf_is_null(basefont)) - name = pdf_dict_gets(fontdict, "Name"); - - for (k = 0; k < fonts; k++) - if (!pdf_objcmp(font[k].u.font.obj, fontdict)) - break; - - if (k < fonts) - continue; - - font = fz_resize_array(ctx, font, fonts+1, sizeof(struct info)); - fonts++; - - font[fonts - 1].page = page; - font[fonts - 1].pageref = pageref; - font[fonts - 1].pageobj = pageobj; - font[fonts - 1].u.font.obj = fontdict; - font[fonts - 1].u.font.subtype = subtype; - font[fonts - 1].u.font.name = basefont ? basefont : name; - } -} - -static void -gatherimages(int page, pdf_obj *pageref, pdf_obj *pageobj, pdf_obj *dict) -{ - int i, n; - - n = pdf_dict_len(dict); - for (i = 0; i < n; i++) - { - pdf_obj *imagedict; - pdf_obj *type; - pdf_obj *width; - pdf_obj *height; - pdf_obj *bpc = NULL; - pdf_obj *filter = NULL; - pdf_obj *cs = NULL; - pdf_obj *altcs; - int k; - - imagedict = pdf_dict_get_val(dict, i); - if (!pdf_is_dict(imagedict)) - { - fz_warn(ctx, "not an image dict (%d %d R)", pdf_to_num(imagedict), pdf_to_gen(imagedict)); - continue; - } - - type = pdf_dict_gets(imagedict, "Subtype"); - if (strcmp(pdf_to_name(type), "Image")) - continue; - - filter = pdf_dict_gets(imagedict, "Filter"); - - altcs = NULL; - cs = pdf_dict_gets(imagedict, "ColorSpace"); - if (pdf_is_array(cs)) - { - pdf_obj *cses = cs; - - cs = pdf_array_get(cses, 0); - if (pdf_is_name(cs) && (!strcmp(pdf_to_name(cs), "DeviceN") || !strcmp(pdf_to_name(cs), "Separation"))) - { - altcs = pdf_array_get(cses, 2); - if (pdf_is_array(altcs)) - altcs = pdf_array_get(altcs, 0); - } - } - - width = pdf_dict_gets(imagedict, "Width"); - height = pdf_dict_gets(imagedict, "Height"); - bpc = pdf_dict_gets(imagedict, "BitsPerComponent"); - - for (k = 0; k < images; k++) - if (!pdf_objcmp(image[k].u.image.obj, imagedict)) - break; - - if (k < images) - continue; - - image = fz_resize_array(ctx, image, images+1, sizeof(struct info)); - images++; - - image[images - 1].page = page; - image[images - 1].pageref = pageref; - image[images - 1].pageobj = pageobj; - image[images - 1].u.image.obj = imagedict; - image[images - 1].u.image.width = width; - image[images - 1].u.image.height = height; - image[images - 1].u.image.bpc = bpc; - image[images - 1].u.image.filter = filter; - image[images - 1].u.image.cs = cs; - image[images - 1].u.image.altcs = altcs; - } -} - -static void -gatherforms(int page, pdf_obj *pageref, pdf_obj *pageobj, pdf_obj *dict) -{ - int i, n; - - n = pdf_dict_len(dict); - for (i = 0; i < n; i++) - { - pdf_obj *xobjdict; - pdf_obj *type; - pdf_obj *subtype; - pdf_obj *group; - pdf_obj *groupsubtype; - pdf_obj *reference; - int k; - - xobjdict = pdf_dict_get_val(dict, i); - if (!pdf_is_dict(xobjdict)) - { - fz_warn(ctx, "not a xobject dict (%d %d R)", pdf_to_num(xobjdict), pdf_to_gen(xobjdict)); - continue; - } - - type = pdf_dict_gets(xobjdict, "Subtype"); - if (strcmp(pdf_to_name(type), "Form")) - continue; - - subtype = pdf_dict_gets(xobjdict, "Subtype2"); - if (!strcmp(pdf_to_name(subtype), "PS")) - continue; - - group = pdf_dict_gets(xobjdict, "Group"); - groupsubtype = pdf_dict_gets(group, "S"); - reference = pdf_dict_gets(xobjdict, "Ref"); - - for (k = 0; k < forms; k++) - if (!pdf_objcmp(form[k].u.form.obj, xobjdict)) - break; - - if (k < forms) - continue; - - form = fz_resize_array(ctx, form, forms+1, sizeof(struct info)); - forms++; - - form[forms - 1].page = page; - form[forms - 1].pageref = pageref; - form[forms - 1].pageobj = pageobj; - form[forms - 1].u.form.obj = xobjdict; - form[forms - 1].u.form.groupsubtype = groupsubtype; - form[forms - 1].u.form.reference = reference; - } -} - -static void -gatherpsobjs(int page, pdf_obj *pageref, pdf_obj *pageobj, pdf_obj *dict) -{ - int i, n; - - n = pdf_dict_len(dict); - for (i = 0; i < n; i++) - { - pdf_obj *xobjdict; - pdf_obj *type; - pdf_obj *subtype; - int k; - - xobjdict = pdf_dict_get_val(dict, i); - if (!pdf_is_dict(xobjdict)) - { - fz_warn(ctx, "not a xobject dict (%d %d R)", pdf_to_num(xobjdict), pdf_to_gen(xobjdict)); - continue; - } - - type = pdf_dict_gets(xobjdict, "Subtype"); - subtype = pdf_dict_gets(xobjdict, "Subtype2"); - if (strcmp(pdf_to_name(type), "PS") && - (strcmp(pdf_to_name(type), "Form") || strcmp(pdf_to_name(subtype), "PS"))) - continue; - - for (k = 0; k < psobjs; k++) - if (!pdf_objcmp(psobj[k].u.form.obj, xobjdict)) - break; - - if (k < psobjs) - continue; - - psobj = fz_resize_array(ctx, psobj, psobjs+1, sizeof(struct info)); - psobjs++; - - psobj[psobjs - 1].page = page; - psobj[psobjs - 1].pageref = pageref; - psobj[psobjs - 1].pageobj = pageobj; - psobj[psobjs - 1].u.form.obj = xobjdict; - } -} - -static void -gathershadings(int page, pdf_obj *pageref, pdf_obj *pageobj, pdf_obj *dict) -{ - int i, n; - - n = pdf_dict_len(dict); - for (i = 0; i < n; i++) - { - pdf_obj *shade; - pdf_obj *type; - int k; - - shade = pdf_dict_get_val(dict, i); - if (!pdf_is_dict(shade)) - { - fz_warn(ctx, "not a shading dict (%d %d R)", pdf_to_num(shade), pdf_to_gen(shade)); - continue; - } - - type = pdf_dict_gets(shade, "ShadingType"); - if (!pdf_is_int(type) || pdf_to_int(type) < 1 || pdf_to_int(type) > 7) - { - fz_warn(ctx, "not a shading type (%d %d R)", pdf_to_num(shade), pdf_to_gen(shade)); - type = NULL; - } - - for (k = 0; k < shadings; k++) - if (!pdf_objcmp(shading[k].u.shading.obj, shade)) - break; - - if (k < shadings) - continue; - - shading = fz_resize_array(ctx, shading, shadings+1, sizeof(struct info)); - shadings++; - - shading[shadings - 1].page = page; - shading[shadings - 1].pageref = pageref; - shading[shadings - 1].pageobj = pageobj; - shading[shadings - 1].u.shading.obj = shade; - shading[shadings - 1].u.shading.type = type; - } -} - -static void -gatherpatterns(int page, pdf_obj *pageref, pdf_obj *pageobj, pdf_obj *dict) -{ - int i, n; - - n = pdf_dict_len(dict); - for (i = 0; i < n; i++) - { - pdf_obj *patterndict; - pdf_obj *type; - pdf_obj *paint = NULL; - pdf_obj *tiling = NULL; - pdf_obj *shading = NULL; - int k; - - patterndict = pdf_dict_get_val(dict, i); - if (!pdf_is_dict(patterndict)) - { - fz_warn(ctx, "not a pattern dict (%d %d R)", pdf_to_num(patterndict), pdf_to_gen(patterndict)); - continue; - } - - type = pdf_dict_gets(patterndict, "PatternType"); - if (!pdf_is_int(type) || pdf_to_int(type) < 1 || pdf_to_int(type) > 2) - { - fz_warn(ctx, "not a pattern type (%d %d R)", pdf_to_num(patterndict), pdf_to_gen(patterndict)); - type = NULL; - } - - if (pdf_to_int(type) == 1) - { - paint = pdf_dict_gets(patterndict, "PaintType"); - if (!pdf_is_int(paint) || pdf_to_int(paint) < 1 || pdf_to_int(paint) > 2) - { - fz_warn(ctx, "not a pattern paint type (%d %d R)", pdf_to_num(patterndict), pdf_to_gen(patterndict)); - paint = NULL; - } - - tiling = pdf_dict_gets(patterndict, "TilingType"); - if (!pdf_is_int(tiling) || pdf_to_int(tiling) < 1 || pdf_to_int(tiling) > 3) - { - fz_warn(ctx, "not a pattern tiling type (%d %d R)", pdf_to_num(patterndict), pdf_to_gen(patterndict)); - tiling = NULL; - } - } - else - { - shading = pdf_dict_gets(patterndict, "Shading"); - } - - for (k = 0; k < patterns; k++) - if (!pdf_objcmp(pattern[k].u.pattern.obj, patterndict)) - break; - - if (k < patterns) - continue; - - pattern = fz_resize_array(ctx, pattern, patterns+1, sizeof(struct info)); - patterns++; - - pattern[patterns - 1].page = page; - pattern[patterns - 1].pageref = pageref; - pattern[patterns - 1].pageobj = pageobj; - pattern[patterns - 1].u.pattern.obj = patterndict; - pattern[patterns - 1].u.pattern.type = type; - pattern[patterns - 1].u.pattern.paint = paint; - pattern[patterns - 1].u.pattern.tiling = tiling; - pattern[patterns - 1].u.pattern.shading = shading; - } -} - -static void -gatherresourceinfo(int page, pdf_obj *rsrc, int show) -{ - pdf_obj *pageobj; - pdf_obj *pageref; - pdf_obj *font; - pdf_obj *xobj; - pdf_obj *shade; - pdf_obj *pattern; - pdf_obj *subrsrc; - int i; - - pageobj = xref->page_objs[page-1]; - pageref = xref->page_refs[page-1]; - - if (!pageobj) - fz_throw(ctx, FZ_ERROR_GENERIC, "cannot retrieve info from page %d", page); - - font = pdf_dict_gets(rsrc, "Font"); - if (show & FONTS && font) - { - int n; - - gatherfonts(page, pageref, pageobj, font); - n = pdf_dict_len(font); - for (i = 0; i < n; i++) - { - pdf_obj *obj = pdf_dict_get_val(font, i); - - subrsrc = pdf_dict_gets(obj, "Resources"); - if (subrsrc && pdf_objcmp(rsrc, subrsrc)) - gatherresourceinfo(page, subrsrc, show); - } - } - - xobj = pdf_dict_gets(rsrc, "XObject"); - if (show & XOBJS && xobj) - { - int n; - - gatherimages(page, pageref, pageobj, xobj); - gatherforms(page, pageref, pageobj, xobj); - gatherpsobjs(page, pageref, pageobj, xobj); - n = pdf_dict_len(xobj); - for (i = 0; i < n; i++) - { - pdf_obj *obj = pdf_dict_get_val(xobj, i); - subrsrc = pdf_dict_gets(obj, "Resources"); - if (subrsrc && pdf_objcmp(rsrc, subrsrc)) - gatherresourceinfo(page, subrsrc, show); - } - } - - shade = pdf_dict_gets(rsrc, "Shading"); - if (show & SHADINGS && shade) - gathershadings(page, pageref, pageobj, shade); - - pattern = pdf_dict_gets(rsrc, "Pattern"); - if (show & PATTERNS && pattern) - { - int n; - gatherpatterns(page, pageref, pageobj, pattern); - n = pdf_dict_len(pattern); - for (i = 0; i < n; i++) - { - pdf_obj *obj = pdf_dict_get_val(pattern, i); - subrsrc = pdf_dict_gets(obj, "Resources"); - if (subrsrc && pdf_objcmp(rsrc, subrsrc)) - gatherresourceinfo(page, subrsrc, show); - } - } -} - -static void -gatherpageinfo(int page, int show) -{ - pdf_obj *pageobj; - pdf_obj *pageref; - pdf_obj *rsrc; - - pageobj = xref->page_objs[page-1]; - pageref = xref->page_refs[page-1]; - - if (!pageobj) - fz_throw(ctx, FZ_ERROR_GENERIC, "cannot retrieve info from page %d", page); - - gatherdimensions(page, pageref, pageobj); - - rsrc = pdf_dict_gets(pageobj, "Resources"); - gatherresourceinfo(page, rsrc, show); -} - -static void -printinfo(char *filename, int show, int page) -{ - int i; - int j; - -#define PAGE_FMT "\t% 5d (% 7d %1d R): " - - if (show & DIMENSIONS && dims > 0) - { - printf("Mediaboxes (%d):\n", dims); - for (i = 0; i < dims; i++) - { - printf(PAGE_FMT "[ %g %g %g %g ]\n", - dim[i].page, - pdf_to_num(dim[i].pageref), pdf_to_gen(dim[i].pageref), - dim[i].u.dim.bbox->x0, - dim[i].u.dim.bbox->y0, - dim[i].u.dim.bbox->x1, - dim[i].u.dim.bbox->y1); - } - printf("\n"); - } - - if (show & FONTS && fonts > 0) - { - printf("Fonts (%d):\n", fonts); - for (i = 0; i < fonts; i++) - { - printf(PAGE_FMT "%s '%s' (%d %d R)\n", - font[i].page, - pdf_to_num(font[i].pageref), pdf_to_gen(font[i].pageref), - pdf_to_name(font[i].u.font.subtype), - pdf_to_name(font[i].u.font.name), - pdf_to_num(font[i].u.font.obj), pdf_to_gen(font[i].u.font.obj)); - } - printf("\n"); - } - - if (show & IMAGES && images > 0) - { - printf("Images (%d):\n", images); - for (i = 0; i < images; i++) - { - char *cs = NULL; - char *altcs = NULL; - - printf(PAGE_FMT "[ ", - image[i].page, - pdf_to_num(image[i].pageref), pdf_to_gen(image[i].pageref)); - - if (pdf_is_array(image[i].u.image.filter)) - { - int n = pdf_array_len(image[i].u.image.filter); - for (j = 0; j < n; j++) - { - pdf_obj *obj = pdf_array_get(image[i].u.image.filter, j); - char *filter = fz_strdup(ctx, pdf_to_name(obj)); - - if (strstr(filter, "Decode")) - *(strstr(filter, "Decode")) = '\0'; - - printf("%s%s", - filter, - j == pdf_array_len(image[i].u.image.filter) - 1 ? "" : " "); - fz_free(ctx, filter); - } - } - else if (image[i].u.image.filter) - { - pdf_obj *obj = image[i].u.image.filter; - char *filter = fz_strdup(ctx, pdf_to_name(obj)); - - if (strstr(filter, "Decode")) - *(strstr(filter, "Decode")) = '\0'; - - printf("%s", filter); - fz_free(ctx, filter); - } - else - printf("Raw"); - - if (image[i].u.image.cs) - { - cs = fz_strdup(ctx, pdf_to_name(image[i].u.image.cs)); - - if (!strncmp(cs, "Device", 6)) - { - int len = strlen(cs + 6); - memmove(cs + 3, cs + 6, len + 1); - cs[3 + len + 1] = '\0'; - } - if (strstr(cs, "ICC")) - fz_strlcpy(cs, "ICC", 4); - if (strstr(cs, "Indexed")) - fz_strlcpy(cs, "Idx", 4); - if (strstr(cs, "Pattern")) - fz_strlcpy(cs, "Pat", 4); - if (strstr(cs, "Separation")) - fz_strlcpy(cs, "Sep", 4); - } - if (image[i].u.image.altcs) - { - altcs = fz_strdup(ctx, pdf_to_name(image[i].u.image.altcs)); - - if (!strncmp(altcs, "Device", 6)) - { - int len = strlen(altcs + 6); - memmove(altcs + 3, altcs + 6, len + 1); - altcs[3 + len + 1] = '\0'; - } - if (strstr(altcs, "ICC")) - fz_strlcpy(altcs, "ICC", 4); - if (strstr(altcs, "Indexed")) - fz_strlcpy(altcs, "Idx", 4); - if (strstr(altcs, "Pattern")) - fz_strlcpy(altcs, "Pat", 4); - if (strstr(altcs, "Separation")) - fz_strlcpy(altcs, "Sep", 4); - } - - printf(" ] %dx%d %dbpc %s%s%s (%d %d R)\n", - pdf_to_int(image[i].u.image.width), - pdf_to_int(image[i].u.image.height), - image[i].u.image.bpc ? pdf_to_int(image[i].u.image.bpc) : 1, - image[i].u.image.cs ? cs : "ImageMask", - image[i].u.image.altcs ? " " : "", - image[i].u.image.altcs ? altcs : "", - pdf_to_num(image[i].u.image.obj), pdf_to_gen(image[i].u.image.obj)); - - fz_free(ctx, cs); - fz_free(ctx, altcs); - } - printf("\n"); - } - - if (show & SHADINGS && shadings > 0) - { - printf("Shading patterns (%d):\n", shadings); - for (i = 0; i < shadings; i++) - { - char *shadingtype[] = - { - "", - "Function", - "Axial", - "Radial", - "Triangle mesh", - "Lattice", - "Coons patch", - "Tensor patch", - }; - - printf(PAGE_FMT "%s (%d %d R)\n", - shading[i].page, - pdf_to_num(shading[i].pageref), pdf_to_gen(shading[i].pageref), - shadingtype[pdf_to_int(shading[i].u.shading.type)], - pdf_to_num(shading[i].u.shading.obj), pdf_to_gen(shading[i].u.shading.obj)); - } - printf("\n"); - } - - if (show & PATTERNS && patterns > 0) - { - printf("Patterns (%d):\n", patterns); - for (i = 0; i < patterns; i++) - { - if (pdf_to_int(pattern[i].u.pattern.type) == 1) - { - char *painttype[] = - { - "", - "Colored", - "Uncolored", - }; - char *tilingtype[] = - { - "", - "Constant", - "No distortion", - "Constant/fast tiling", - }; - - printf(PAGE_FMT "Tiling %s %s (%d %d R)\n", - pattern[i].page, - pdf_to_num(pattern[i].pageref), pdf_to_gen(pattern[i].pageref), - painttype[pdf_to_int(pattern[i].u.pattern.paint)], - tilingtype[pdf_to_int(pattern[i].u.pattern.tiling)], - pdf_to_num(pattern[i].u.pattern.obj), pdf_to_gen(pattern[i].u.pattern.obj)); - } - else - { - printf(PAGE_FMT "Shading %d %d R (%d %d R)\n", - pattern[i].page, - pdf_to_num(pattern[i].pageref), pdf_to_gen(pattern[i].pageref), - pdf_to_num(pattern[i].u.pattern.shading), pdf_to_gen(pattern[i].u.pattern.shading), - pdf_to_num(pattern[i].u.pattern.obj), pdf_to_gen(pattern[i].u.pattern.obj)); - } - } - printf("\n"); - } - - if (show & XOBJS && forms > 0) - { - printf("Form xobjects (%d):\n", forms); - for (i = 0; i < forms; i++) - { - printf(PAGE_FMT "Form%s%s%s%s (%d %d R)\n", - form[i].page, - pdf_to_num(form[i].pageref), pdf_to_gen(form[i].pageref), - form[i].u.form.groupsubtype ? " " : "", - form[i].u.form.groupsubtype ? pdf_to_name(form[i].u.form.groupsubtype) : "", - form[i].u.form.groupsubtype ? " Group" : "", - form[i].u.form.reference ? " Reference" : "", - pdf_to_num(form[i].u.form.obj), pdf_to_gen(form[i].u.form.obj)); - } - printf("\n"); - } - - if (show & XOBJS && psobjs > 0) - { - printf("Postscript xobjects (%d):\n", psobjs); - for (i = 0; i < psobjs; i++) - { - printf(PAGE_FMT "(%d %d R)\n", - psobj[i].page, - pdf_to_num(psobj[i].pageref), pdf_to_gen(psobj[i].pageref), - pdf_to_num(psobj[i].u.form.obj), pdf_to_gen(psobj[i].u.form.obj)); - } - printf("\n"); - } -} - -static void -showinfo(char *filename, int show, char *pagelist) -{ - int page, spage, epage; - char *spec, *dash; - int allpages; - int pagecount; - - if (!xref) - infousage(); - - allpages = !strcmp(pagelist, "1-"); - - pagecount = pdf_count_pages(xref); - spec = fz_strsep(&pagelist, ","); - while (spec && pagecount) - { - dash = strchr(spec, '-'); - - if (dash == spec) - spage = epage = pagecount; - else - spage = epage = atoi(spec); - - if (dash) - { - if (strlen(dash) > 1) - epage = atoi(dash + 1); - else - epage = pagecount; - } - - if (spage > epage) - page = spage, spage = epage, epage = page; - - spage = fz_clampi(spage, 1, pagecount); - epage = fz_clampi(epage, 1, pagecount); - - if (allpages) - printf("Retrieving info from pages %d-%d...\n", spage, epage); - for (page = spage; page <= epage; page++) - { - gatherpageinfo(page, show); - if (!allpages) - { - printf("Page %d:\n", page); - printinfo(filename, show, page); - printf("\n"); - } - } - - spec = fz_strsep(&pagelist, ","); - } - - if (allpages) - printinfo(filename, show, -1); -} - -static int arg_is_page_range(const char *arg) -{ - int c; - - while ((c = *arg++) != 0) - { - if ((c < '0' || c > '9') && (c != '-') && (c != ',')) - return 0; - } - return 1; -} - -int pdfinfo_main(int argc, char **argv) -{ - enum { NO_FILE_OPENED, NO_INFO_GATHERED, INFO_SHOWN } state; - char *filename = ""; - char *password = ""; - int show = ALL; - int c; - - while ((c = fz_getopt(argc, argv, "mfispxd:")) != -1) - { - switch (c) - { - case 'm': if (show == ALL) show = DIMENSIONS; else show |= DIMENSIONS; break; - case 'f': if (show == ALL) show = FONTS; else show |= FONTS; break; - case 'i': if (show == ALL) show = IMAGES; else show |= IMAGES; break; - case 's': if (show == ALL) show = SHADINGS; else show |= SHADINGS; break; - case 'p': if (show == ALL) show = PATTERNS; else show |= PATTERNS; break; - case 'x': if (show == ALL) show = XOBJS; else show |= XOBJS; break; - case 'd': password = fz_optarg; break; - default: - infousage(); - break; - } - } - - if (fz_optind == argc) - infousage(); - - ctx = fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED); - if (!ctx) - { - fprintf(stderr, "cannot initialise context\n"); - exit(1); - } - - state = NO_FILE_OPENED; - while (fz_optind < argc) - { - if (state == NO_FILE_OPENED || !arg_is_page_range(argv[fz_optind])) - { - if (state == NO_INFO_GATHERED) - { - showinfo(filename, show, "1-"); - closexref(); - } - - closexref(); - - filename = argv[fz_optind]; - printf("%s:\n", filename); - xref = pdf_open_document_no_run(ctx, filename); - if (pdf_needs_password(xref)) - if (!pdf_authenticate_password(xref, password)) - fz_throw(ctx, FZ_ERROR_GENERIC, "cannot authenticate password: %s", filename); - pagecount = pdf_count_pages(xref); - - showglobalinfo(); - state = NO_INFO_GATHERED; - } - else - { - showinfo(filename, show, argv[fz_optind]); - state = INFO_SHOWN; - } - - fz_optind++; - } - - if (state == NO_INFO_GATHERED) - showinfo(filename, show, "1-"); - - closexref(); - fz_free_context(ctx); - return 0; -} diff --git a/apps/pdfposter.c b/apps/pdfposter.c deleted file mode 100644 index ed3a4bda..00000000 --- a/apps/pdfposter.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - * PDF cleaning tool: general purpose pdf syntax washer. - * - * Rewrite PDF with pretty printed objects. - * Garbage collect unreachable objects. - * Inflate compressed streams. - * Create subset documents. - * - * TODO: linearize document for fast web view - */ - -#include "mupdf/pdf.h" - -static int x_factor = 0; -static int y_factor = 0; - -static void usage(void) -{ - fprintf(stderr, - "usage: mutool poster [options] input.pdf [output.pdf]\n" - "\t-p -\tpassword\n" - "\t-x\tx decimation factor\n" - "\t-y\ty decimation factor\n"); - exit(1); -} - -/* - * Recreate page tree to only retain specified pages. - */ - -static void decimatepages(pdf_document *xref) -{ - pdf_obj *oldroot, *root, *pages, *kids, *parent; - fz_context *ctx = xref->ctx; - int num_pages = pdf_count_pages(xref); - int page, kidcount; - - /* Keep only pages/type and (reduced) dest entries to avoid - * references to unretained pages */ - oldroot = pdf_dict_gets(pdf_trailer(xref), "Root"); - pages = pdf_dict_gets(oldroot, "Pages"); - - root = pdf_new_dict(ctx, 2); - pdf_dict_puts(root, "Type", pdf_dict_gets(oldroot, "Type")); - pdf_dict_puts(root, "Pages", pdf_dict_gets(oldroot, "Pages")); - - pdf_update_object(xref, pdf_to_num(oldroot), root); - - pdf_drop_obj(root); - - /* Create a new kids array with only the pages we want to keep */ - parent = pdf_new_indirect(ctx, pdf_to_num(pages), pdf_to_gen(pages), xref); - kids = pdf_new_array(ctx, 1); - - kidcount = 0; - for (page=0; page < num_pages; page++) - { - pdf_page *page_details = pdf_load_page(xref, page); - int xf = x_factor, yf = y_factor; - int x, y; - float w = page_details->mediabox.x1 - page_details->mediabox.x0; - float h = page_details->mediabox.y1 - page_details->mediabox.y0; - - if (xf == 0 && yf == 0) - { - /* Nothing specified, so split along the long edge */ - if (w > h) - xf = 2, yf = 1; - else - xf = 1, yf = 2; - } - else if (xf == 0) - xf = 1; - else if (yf == 0) - yf = 1; - - for (y = yf-1; y >= 0; y--) - { - for (x = 0; x < xf; x++) - { - pdf_obj *newpageobj, *newpageref, *newmediabox; - fz_rect mb; - int num; - - newpageobj = pdf_copy_dict(ctx, xref->page_objs[page]); - num = pdf_create_object(xref); - pdf_update_object(xref, num, newpageobj); - newpageref = pdf_new_indirect(ctx, num, 0, xref); - - newmediabox = pdf_new_array(ctx, 4); - - mb.x0 = page_details->mediabox.x0 + (w/xf)*x; - if (x == xf-1) - mb.x1 = page_details->mediabox.x1; - else - mb.x1 = page_details->mediabox.x0 + (w/xf)*(x+1); - mb.y0 = page_details->mediabox.y0 + (h/yf)*y; - if (y == yf-1) - mb.y1 = page_details->mediabox.y1; - else - mb.y1 = page_details->mediabox.y0 + (h/yf)*(y+1); - - pdf_array_push(newmediabox, pdf_new_real(ctx, mb.x0)); - pdf_array_push(newmediabox, pdf_new_real(ctx, mb.y0)); - pdf_array_push(newmediabox, pdf_new_real(ctx, mb.x1)); - pdf_array_push(newmediabox, pdf_new_real(ctx, mb.y1)); - - pdf_dict_puts(newpageobj, "Parent", parent); - pdf_dict_puts(newpageobj, "MediaBox", newmediabox); - - /* Store page object in new kids array */ - pdf_array_push(kids, newpageref); - - kidcount++; - } - } - } - - pdf_drop_obj(parent); - - /* Update page count and kids array */ - pdf_dict_puts(pages, "Count", pdf_new_int(ctx, kidcount)); - pdf_dict_puts(pages, "Kids", kids); - pdf_drop_obj(kids); -} - -int pdfposter_main(int argc, char **argv) -{ - char *infile; - char *outfile = "out.pdf"; - char *password = ""; - int c; - fz_write_options opts; - pdf_document *xref; - fz_context *ctx; - - opts.do_garbage = 0; - opts.do_expand = 0; - opts.do_ascii = 0; - - while ((c = fz_getopt(argc, argv, "x:y:")) != -1) - { - switch (c) - { - case 'p': password = fz_optarg; break; - case 'x': x_factor = atoi(fz_optarg); break; - case 'y': y_factor = atoi(fz_optarg); break; - default: usage(); break; - } - } - - if (argc - fz_optind < 1) - usage(); - - infile = argv[fz_optind++]; - - if (argc - fz_optind > 0 && - (strstr(argv[fz_optind], ".pdf") || strstr(argv[fz_optind], ".PDF"))) - { - outfile = argv[fz_optind++]; - } - - ctx = fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED); - if (!ctx) - { - fprintf(stderr, "cannot initialise context\n"); - exit(1); - } - - xref = pdf_open_document_no_run(ctx, infile); - if (pdf_needs_password(xref)) - if (!pdf_authenticate_password(xref, password)) - fz_throw(ctx, FZ_ERROR_GENERIC, "cannot authenticate password: %s", infile); - - /* Only retain the specified subset of the pages */ - decimatepages(xref); - - pdf_write_document(xref, outfile, &opts); - - pdf_close_document(xref); - fz_free_context(ctx); - return 0; -} diff --git a/apps/pdfshow.c b/apps/pdfshow.c deleted file mode 100644 index 78e3fd08..00000000 --- a/apps/pdfshow.c +++ /dev/null @@ -1,251 +0,0 @@ -/* - * pdfshow -- the ultimate pdf debugging tool - */ - -#include "mupdf/pdf.h" - -static pdf_document *doc = NULL; -static fz_context *ctx = NULL; -static int showbinary = 0; -static int showdecode = 1; -static int showcolumn; - -static void usage(void) -{ - fprintf(stderr, "usage: mutool show [options] file.pdf [grepable] [xref] [trailer] [pagetree] [object numbers]\n"); - fprintf(stderr, "\t-b\tprint streams as binary data\n"); - fprintf(stderr, "\t-e\tprint encoded streams (don't decode)\n"); - fprintf(stderr, "\t-p\tpassword\n"); - exit(1); -} - -static void showtrailer(void) -{ - if (!doc) - fz_throw(ctx, FZ_ERROR_GENERIC, "no file specified"); - printf("trailer\n"); - pdf_fprint_obj(stdout, pdf_trailer(doc), 0); - printf("\n"); -} - -static void showencrypt(void) -{ - pdf_obj *encrypt; - - if (!doc) - fz_throw(ctx, FZ_ERROR_GENERIC, "no file specified"); - encrypt = pdf_dict_gets(pdf_trailer(doc), "Encrypt"); - if (!encrypt) - fz_throw(ctx, FZ_ERROR_GENERIC, "document not encrypted"); - printf("encryption dictionary\n"); - pdf_fprint_obj(stdout, pdf_resolve_indirect(encrypt), 0); - printf("\n"); -} - -static void showxref(void) -{ - if (!doc) - fz_throw(ctx, FZ_ERROR_GENERIC, "no file specified"); - pdf_print_xref(doc); - printf("\n"); -} - -static void showpagetree(void) -{ - pdf_obj *ref; - int count; - int i; - - if (!doc) - fz_throw(ctx, FZ_ERROR_GENERIC, "no file specified"); - - count = pdf_count_pages(doc); - for (i = 0; i < count; i++) - { - ref = doc->page_refs[i]; - printf("page %d = %d %d R\n", i + 1, pdf_to_num(ref), pdf_to_gen(ref)); - } - printf("\n"); -} - -static void showsafe(unsigned char *buf, int n) -{ - int i; - for (i = 0; i < n; i++) { - if (buf[i] == '\r' || buf[i] == '\n') { - putchar('\n'); - showcolumn = 0; - } - else if (buf[i] < 32 || buf[i] > 126) { - putchar('.'); - showcolumn ++; - } - else { - putchar(buf[i]); - showcolumn ++; - } - if (showcolumn == 79) { - putchar('\n'); - showcolumn = 0; - } - } -} - -static void showstream(int num, int gen) -{ - fz_stream *stm; - unsigned char buf[2048]; - int n; - - showcolumn = 0; - - if (showdecode) - stm = pdf_open_stream(doc, num, gen); - else - stm = pdf_open_raw_stream(doc, num, gen); - - while (1) - { - n = fz_read(stm, buf, sizeof buf); - if (n == 0) - break; - if (showbinary) - fwrite(buf, 1, n, stdout); - else - showsafe(buf, n); - } - - fz_close(stm); -} - -static void showobject(int num, int gen) -{ - pdf_obj *obj; - - if (!doc) - fz_throw(ctx, FZ_ERROR_GENERIC, "no file specified"); - - obj = pdf_load_object(doc, num, gen); - - if (pdf_is_stream(doc, num, gen)) - { - if (showbinary) - { - showstream(num, gen); - } - else - { - printf("%d %d obj\n", num, gen); - pdf_fprint_obj(stdout, obj, 0); - printf("stream\n"); - showstream(num, gen); - printf("endstream\n"); - printf("endobj\n\n"); - } - } - else - { - printf("%d %d obj\n", num, gen); - pdf_fprint_obj(stdout, obj, 0); - printf("endobj\n\n"); - } - - pdf_drop_obj(obj); -} - -static void showgrep(char *filename) -{ - pdf_obj *obj; - int i, len; - - len = pdf_count_objects(doc); - for (i = 0; i < len; i++) - { - pdf_xref_entry *entry = pdf_get_xref_entry(doc, i); - if (entry->type == 'n' || entry->type == 'o') - { - fz_try(ctx) - { - obj = pdf_load_object(doc, i, 0); - } - fz_catch(ctx) - { - fz_warn(ctx, "skipping object (%d 0 R)", i); - continue; - } - - pdf_sort_dict(obj); - - printf("%s:%d: ", filename, i); - pdf_fprint_obj(stdout, obj, 1); - - pdf_drop_obj(obj); - } - } - - printf("%s:trailer: ", filename); - pdf_fprint_obj(stdout, pdf_trailer(doc), 1); -} - -int pdfshow_main(int argc, char **argv) -{ - char *password = NULL; /* don't throw errors if encrypted */ - char *filename; - int c; - - while ((c = fz_getopt(argc, argv, "p:be")) != -1) - { - switch (c) - { - case 'p': password = fz_optarg; break; - case 'b': showbinary = 1; break; - case 'e': showdecode = 0; break; - default: usage(); break; - } - } - - if (fz_optind == argc) - usage(); - - filename = argv[fz_optind++]; - - ctx = fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED); - if (!ctx) - { - fprintf(stderr, "cannot initialise context\n"); - exit(1); - } - - fz_var(doc); - fz_try(ctx) - { - doc = pdf_open_document_no_run(ctx, filename); - if (pdf_needs_password(doc)) - if (!pdf_authenticate_password(doc, password)) - fz_warn(ctx, "cannot authenticate password: %s", filename); - - if (fz_optind == argc) - showtrailer(); - - while (fz_optind < argc) - { - switch (argv[fz_optind][0]) - { - case 't': showtrailer(); break; - case 'e': showencrypt(); break; - case 'x': showxref(); break; - case 'p': showpagetree(); break; - case 'g': showgrep(filename); break; - default: showobject(atoi(argv[fz_optind]), 0); break; - } - fz_optind++; - } - } - fz_catch(ctx) - { - } - - pdf_close_document(doc); - fz_free_context(ctx); - return 0; -} diff --git a/apps/win_main.c b/apps/win_main.c deleted file mode 100644 index bf765d6b..00000000 --- a/apps/win_main.c +++ /dev/null @@ -1,1163 +0,0 @@ -#include "pdfapp.h" - -#ifndef UNICODE -#define UNICODE -#endif -#ifndef _UNICODE -#define _UNICODE -#endif -#define WIN32_LEAN_AND_MEAN -#include <windows.h> -#include <commdlg.h> -#include <shellapi.h> - -#ifndef WM_MOUSEWHEEL -#define WM_MOUSEWHEEL 0x020A -#endif - -#define MIN(x,y) ((x) < (y) ? (x) : (y)) - -#define ID_ABOUT 0x1000 -#define ID_DOCINFO 0x1001 - -static HWND hwndframe = NULL; -static HWND hwndview = NULL; -static HDC hdc; -static HBRUSH bgbrush; -static HBRUSH shbrush; -static BITMAPINFO *dibinf; -static HCURSOR arrowcurs, handcurs, waitcurs, caretcurs; -static LRESULT CALLBACK frameproc(HWND, UINT, WPARAM, LPARAM); -static LRESULT CALLBACK viewproc(HWND, UINT, WPARAM, LPARAM); -static int timer_pending = 0; - -static int justcopied = 0; - -static pdfapp_t gapp; - -#define PATH_MAX (1024) - -static wchar_t wbuf[PATH_MAX]; -static char filename[PATH_MAX]; - -/* - * Create registry keys to associate MuPDF with PDF and XPS files. - */ - -#define OPEN_KEY(parent, name, ptr) \ - RegCreateKeyExA(parent, name, 0, 0, 0, KEY_WRITE, 0, &ptr, 0) - -#define SET_KEY(parent, name, value) \ - RegSetValueExA(parent, name, 0, REG_SZ, (const BYTE *)(value), strlen(value) + 1) - -void install_app(char *argv0) -{ - char buf[512]; - HKEY software, classes, mupdf, dotpdf, dotxps; - HKEY shell, open, command, supported_types; - HKEY pdf_progids, xps_progids; - - OPEN_KEY(HKEY_CURRENT_USER, "Software", software); - OPEN_KEY(software, "Classes", classes); - OPEN_KEY(classes, ".pdf", dotpdf); - OPEN_KEY(dotpdf, "OpenWithProgids", pdf_progids); - OPEN_KEY(classes, ".xps", dotxps); - OPEN_KEY(dotxps, "OpenWithProgids", xps_progids); - OPEN_KEY(classes, "MuPDF", mupdf); - OPEN_KEY(mupdf, "SupportedTypes", supported_types); - OPEN_KEY(mupdf, "shell", shell); - OPEN_KEY(shell, "open", open); - OPEN_KEY(open, "command", command); - - sprintf(buf, "\"%s\" \"%%1\"", argv0); - - SET_KEY(open, "FriendlyAppName", "MuPDF"); - SET_KEY(command, "", buf); - SET_KEY(supported_types, ".pdf", ""); - SET_KEY(supported_types, ".xps", ""); - SET_KEY(pdf_progids, "MuPDF", ""); - SET_KEY(xps_progids, "MuPDF", ""); - - RegCloseKey(dotxps); - RegCloseKey(dotpdf); - RegCloseKey(mupdf); - RegCloseKey(classes); - RegCloseKey(software); -} - -/* - * Dialog boxes - */ - -void winwarn(pdfapp_t *app, char *msg) -{ - MessageBoxA(hwndframe, msg, "MuPDF: Warning", MB_ICONWARNING); -} - -void winerror(pdfapp_t *app, char *msg) -{ - MessageBoxA(hwndframe, msg, "MuPDF: Error", MB_ICONERROR); - exit(1); -} - -void winalert(pdfapp_t *app, pdf_alert_event *alert) -{ - int buttons = MB_OK; - int icon = MB_ICONWARNING; - int pressed = PDF_ALERT_BUTTON_NONE; - - switch (alert->icon_type) - { - case PDF_ALERT_ICON_ERROR: - icon = MB_ICONERROR; - break; - case PDF_ALERT_ICON_WARNING: - icon = MB_ICONWARNING; - break; - case PDF_ALERT_ICON_QUESTION: - icon = MB_ICONQUESTION; - break; - case PDF_ALERT_ICON_STATUS: - icon = MB_ICONINFORMATION; - break; - } - - switch (alert->button_group_type) - { - case PDF_ALERT_BUTTON_GROUP_OK: - buttons = MB_OK; - break; - case PDF_ALERT_BUTTON_GROUP_OK_CANCEL: - buttons = MB_OKCANCEL; - break; - case PDF_ALERT_BUTTON_GROUP_YES_NO: - buttons = MB_YESNO; - break; - case PDF_ALERT_BUTTON_GROUP_YES_NO_CANCEL: - buttons = MB_YESNOCANCEL; - break; - } - - pressed = MessageBoxA(hwndframe, alert->message, alert->title, icon|buttons); - - switch (pressed) - { - case IDOK: - alert->button_pressed = PDF_ALERT_BUTTON_OK; - break; - case IDCANCEL: - alert->button_pressed = PDF_ALERT_BUTTON_CANCEL; - break; - case IDNO: - alert->button_pressed = PDF_ALERT_BUTTON_NO; - break; - case IDYES: - alert->button_pressed = PDF_ALERT_BUTTON_YES; - } -} - -void winprint(pdfapp_t *app) -{ - MessageBoxA(hwndframe, "The MuPDF library supports printing, but this application currently does not", "Print document", MB_ICONWARNING); -} - -int winsavequery(pdfapp_t *app) -{ - switch(MessageBoxA(hwndframe, "File has unsaved changes. Do you want to save", "MuPDF", MB_YESNOCANCEL)) - { - case IDYES: return SAVE; - case IDNO: return DISCARD; - default: return CANCEL; - } -} - -int winfilename(wchar_t *buf, int len) -{ - OPENFILENAME ofn; - buf[0] = 0; - memset(&ofn, 0, sizeof(OPENFILENAME)); - ofn.lStructSize = sizeof(OPENFILENAME); - ofn.hwndOwner = hwndframe; - ofn.lpstrFile = buf; - ofn.nMaxFile = len; - ofn.lpstrInitialDir = NULL; - ofn.lpstrTitle = L"MuPDF: Open PDF file"; - ofn.lpstrFilter = L"Documents (*.pdf;*.xps;*.cbz;*.zip;*.png;*.jpg;*.tif)\0*.zip;*.cbz;*.xps;*.pdf;*.jpe;*.jpg;*.jpeg;*.jfif;*.tif;*.tiff\0PDF Files (*.pdf)\0*.pdf\0XPS Files (*.xps)\0*.xps\0CBZ Files (*.cbz;*.zip)\0*.zip;*.cbz\0Image Files (*.png;*.jpe;*.tif)\0*.png;*.jpg;*.jpe;*.jpeg;*.jfif;*.tif;*.tiff\0All Files\0*\0\0"; - ofn.Flags = OFN_FILEMUSTEXIST|OFN_HIDEREADONLY; - return GetOpenFileNameW(&ofn); -} - -int wingetsavepath(pdfapp_t *app, char *buf, int len) -{ - wchar_t twbuf[PATH_MAX]; - OPENFILENAME ofn; - - wcscpy(twbuf, wbuf); - memset(&ofn, 0, sizeof(OPENFILENAME)); - ofn.lStructSize = sizeof(OPENFILENAME); - ofn.hwndOwner = hwndframe; - ofn.lpstrFile = twbuf; - ofn.nMaxFile = PATH_MAX; - ofn.lpstrInitialDir = NULL; - ofn.lpstrTitle = L"MuPDF: Save PDF file"; - ofn.lpstrFilter = L"Documents (*.pdf;*.xps;*.cbz;*.zip;*.png;*.jpg;*.tif)\0*.zip;*.cbz;*.xps;*.pdf;*.jpe;*.jpg;*.jpeg;*.jfif;*.tif;*.tiff\0PDF Files (*.pdf)\0*.pdf\0XPS Files (*.xps)\0*.xps\0CBZ Files (*.cbz;*.zip)\0*.zip;*.cbz\0Image Files (*.png;*.jpe;*.tif)\0*.png;*.jpg;*.jpe;*.jpeg;*.jfif;*.tif;*.tiff\0All Files\0*\0\0"; - ofn.Flags = OFN_HIDEREADONLY; - if (GetSaveFileName(&ofn)) - { - int code = WideCharToMultiByte(CP_UTF8, 0, twbuf, -1, buf, MIN(PATH_MAX, len), NULL, NULL); - if (code == 0) - { - winerror(&gapp, "cannot convert filename to utf-8"); - return 0; - } - - wcscpy(wbuf, twbuf); - strcpy(filename, buf); - return 1; - } - else - { - return 0; - } -} - -void winreplacefile(char *source, char *target) -{ - wchar_t wsource[PATH_MAX]; - wchar_t wtarget[PATH_MAX]; - - int sz = MultiByteToWideChar(CP_UTF8, 0, source, -1, wsource, PATH_MAX); - if (sz == 0) - { - winerror(&gapp, "cannot convert filename to Unicode"); - return; - } - - sz = MultiByteToWideChar(CP_UTF8, 0, target, -1, wtarget, PATH_MAX); - if (sz == 0) - { - winerror(&gapp, "cannot convert filename to Unicode"); - return; - } - -#if (_WIN32_WINNT >= 0x0500) - ReplaceFile(wtarget, wsource, NULL, REPLACEFILE_IGNORE_MERGE_ERRORS, NULL, NULL); -#else - DeleteFile(wtarget); - MoveFile(wsource, wtarget); -#endif -} - -static char pd_filename[256] = "The file is encrypted."; -static char pd_password[256] = ""; -static wchar_t pd_passwordw[256] = {0}; -static char td_textinput[1024] = ""; -static int td_retry = 0; -static int cd_nopts; -static int *cd_nvals; -static char **cd_opts; -static char **cd_vals; -static int pd_okay = 0; - -INT CALLBACK -dlogpassproc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - switch(message) - { - case WM_INITDIALOG: - SetDlgItemTextA(hwnd, 4, pd_filename); - return TRUE; - case WM_COMMAND: - switch(wParam) - { - case 1: - pd_okay = 1; - GetDlgItemTextW(hwnd, 3, pd_passwordw, nelem(pd_passwordw)); - EndDialog(hwnd, 1); - WideCharToMultiByte(CP_UTF8, 0, pd_passwordw, -1, pd_password, sizeof pd_password, NULL, NULL); - return TRUE; - case 2: - pd_okay = 0; - EndDialog(hwnd, 1); - return TRUE; - } - break; - } - return FALSE; -} - -INT CALLBACK -dlogtextproc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - switch(message) - { - case WM_INITDIALOG: - SetDlgItemTextA(hwnd, 3, td_textinput); - if (!td_retry) - ShowWindow(GetDlgItem(hwnd, 4), SW_HIDE); - return TRUE; - case WM_COMMAND: - switch(wParam) - { - case 1: - pd_okay = 1; - GetDlgItemTextA(hwnd, 3, td_textinput, sizeof td_textinput); - EndDialog(hwnd, 1); - return TRUE; - case 2: - pd_okay = 0; - EndDialog(hwnd, 1); - return TRUE; - } - break; - case WM_CTLCOLORSTATIC: - if ((HWND)lParam == GetDlgItem(hwnd, 4)) - { - SetTextColor((HDC)wParam, RGB(255,0,0)); - SetBkMode((HDC)wParam, TRANSPARENT); - - return (INT)GetStockObject(NULL_BRUSH); - } - break; - } - return FALSE; -} - -INT CALLBACK -dlogchoiceproc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - HWND listbox; - int i; - int item; - int sel; - switch(message) - { - case WM_INITDIALOG: - listbox = GetDlgItem(hwnd, 3); - for (i = 0; i < cd_nopts; i++) - SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)cd_opts[i]); - - /* FIXME: handle multiple select */ - if (*cd_nvals > 0) - { - item = SendMessageA(listbox, LB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)cd_vals[0]); - if (item != LB_ERR) - SendMessageA(listbox, LB_SETCURSEL, item, 0); - } - return TRUE; - case WM_COMMAND: - switch(wParam) - { - case 1: - listbox = GetDlgItem(hwnd, 3); - *cd_nvals = 0; - for (i = 0; i < cd_nopts; i++) - { - item = SendMessageA(listbox, LB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)cd_opts[i]); - sel = SendMessageA(listbox, LB_GETSEL, item, 0); - if (sel && sel != LB_ERR) - cd_vals[(*cd_nvals)++] = cd_opts[i]; - } - pd_okay = 1; - EndDialog(hwnd, 1); - return TRUE; - case 2: - pd_okay = 0; - EndDialog(hwnd, 1); - return TRUE; - } - break; - } - return FALSE; -} - -char *winpassword(pdfapp_t *app, char *filename) -{ - char buf[1024], *s; - int code; - strcpy(buf, filename); - s = buf; - if (strrchr(s, '\\')) s = strrchr(s, '\\') + 1; - if (strrchr(s, '/')) s = strrchr(s, '/') + 1; - if (strlen(s) > 32) - strcpy(s + 30, "..."); - sprintf(pd_filename, "The file \"%s\" is encrypted.", s); - code = DialogBoxW(NULL, L"IDD_DLOGPASS", hwndframe, dlogpassproc); - if (code <= 0) - winerror(app, "cannot create password dialog"); - if (pd_okay) - return pd_password; - return NULL; -} - -char *wintextinput(pdfapp_t *app, char *inittext, int retry) -{ - int code; - td_retry = retry; - fz_strlcpy(td_textinput, inittext ? inittext : "", sizeof td_textinput); - code = DialogBoxW(NULL, L"IDD_DLOGTEXT", hwndframe, dlogtextproc); - if (code <= 0) - winerror(app, "cannot create text input dialog"); - if (pd_okay) - return td_textinput; - return NULL; -} - -int winchoiceinput(pdfapp_t *app, int nopts, char *opts[], int *nvals, char *vals[]) -{ - int code; - cd_nopts = nopts; - cd_nvals = nvals; - cd_opts = opts; - cd_vals = vals; - code = DialogBoxW(NULL, L"IDD_DLOGLIST", hwndframe, dlogchoiceproc); - if (code <= 0) - winerror(app, "cannot create text input dialog"); - return pd_okay; -} - -INT CALLBACK -dloginfoproc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - char buf[256]; - fz_document *doc = gapp.doc; - - switch(message) - { - case WM_INITDIALOG: - - SetDlgItemTextW(hwnd, 0x10, wbuf); - - if (fz_meta(doc, FZ_META_FORMAT_INFO, buf, 256) < 0) - { - SetDlgItemTextA(hwnd, 0x11, "Unknown"); - SetDlgItemTextA(hwnd, 0x12, "None"); - SetDlgItemTextA(hwnd, 0x13, "n/a"); - return TRUE; - } - - SetDlgItemTextA(hwnd, 0x11, buf); - - if (fz_meta(doc, FZ_META_CRYPT_INFO, buf, 256) == 0) - { - SetDlgItemTextA(hwnd, 0x12, buf); - } - else - { - SetDlgItemTextA(hwnd, 0x12, "None"); - } - buf[0] = 0; - if (fz_meta(doc, FZ_META_HAS_PERMISSION, NULL, FZ_PERMISSION_PRINT) == 0) - strcat(buf, "print, "); - if (fz_meta(doc, FZ_META_HAS_PERMISSION, NULL, FZ_PERMISSION_CHANGE) == 0) - strcat(buf, "modify, "); - if (fz_meta(doc, FZ_META_HAS_PERMISSION, NULL, FZ_PERMISSION_COPY) == 0) - strcat(buf, "copy, "); - if (fz_meta(doc, FZ_META_HAS_PERMISSION, NULL, FZ_PERMISSION_NOTES) == 0) - strcat(buf, "annotate, "); - if (strlen(buf) > 2) - buf[strlen(buf)-2] = 0; - else - strcpy(buf, "None"); - SetDlgItemTextA(hwnd, 0x13, buf); - -#define SETUTF8(ID, STRING) \ - { \ - *(char **)buf = STRING; \ - if (fz_meta(doc, FZ_META_INFO, buf, 256) <= 0) \ - buf[0] = 0; \ - SetDlgItemTextA(hwnd, ID, buf); \ - } - - SETUTF8(0x20, "Title"); - SETUTF8(0x21, "Author"); - SETUTF8(0x22, "Subject"); - SETUTF8(0x23, "Keywords"); - SETUTF8(0x24, "Creator"); - SETUTF8(0x25, "Producer"); - SETUTF8(0x26, "CreationDate"); - SETUTF8(0x27, "ModDate"); - return TRUE; - - case WM_COMMAND: - EndDialog(hwnd, 1); - return TRUE; - } - return FALSE; -} - -void info() -{ - int code = DialogBoxW(NULL, L"IDD_DLOGINFO", hwndframe, dloginfoproc); - if (code <= 0) - winerror(&gapp, "cannot create info dialog"); -} - -INT CALLBACK -dlogaboutproc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - switch(message) - { - case WM_INITDIALOG: - SetDlgItemTextA(hwnd, 2, pdfapp_version(&gapp)); - SetDlgItemTextA(hwnd, 3, pdfapp_usage(&gapp)); - return TRUE; - case WM_COMMAND: - EndDialog(hwnd, 1); - return TRUE; - } - return FALSE; -} - -void winhelp(pdfapp_t*app) -{ - int code = DialogBoxW(NULL, L"IDD_DLOGABOUT", hwndframe, dlogaboutproc); - if (code <= 0) - winerror(&gapp, "cannot create help dialog"); -} - -/* - * Main window - */ - -void winopen() -{ - WNDCLASS wc; - HMENU menu; - RECT r; - ATOM a; - - /* Create and register window frame class */ - memset(&wc, 0, sizeof(wc)); - wc.style = 0; - wc.lpfnWndProc = frameproc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = GetModuleHandle(NULL); - wc.hIcon = LoadIconA(wc.hInstance, "IDI_ICONAPP"); - wc.hCursor = NULL; //LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = NULL; - wc.lpszMenuName = NULL; - wc.lpszClassName = L"FrameWindow"; - a = RegisterClassW(&wc); - if (!a) - winerror(&gapp, "cannot register frame window class"); - - /* Create and register window view class */ - memset(&wc, 0, sizeof(wc)); - wc.style = CS_HREDRAW | CS_VREDRAW; - wc.lpfnWndProc = viewproc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = GetModuleHandle(NULL); - wc.hIcon = NULL; - wc.hCursor = NULL; - wc.hbrBackground = NULL; - wc.lpszMenuName = NULL; - wc.lpszClassName = L"ViewWindow"; - a = RegisterClassW(&wc); - if (!a) - winerror(&gapp, "cannot register view window class"); - - /* Get screen size */ - SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0); - gapp.scrw = r.right - r.left; - gapp.scrh = r.bottom - r.top; - - /* Create cursors */ - arrowcurs = LoadCursor(NULL, IDC_ARROW); - handcurs = LoadCursor(NULL, IDC_HAND); - waitcurs = LoadCursor(NULL, IDC_WAIT); - caretcurs = LoadCursor(NULL, IDC_IBEAM); - - /* And a background color */ - bgbrush = CreateSolidBrush(RGB(0x70,0x70,0x70)); - shbrush = CreateSolidBrush(RGB(0x40,0x40,0x40)); - - /* Init DIB info for buffer */ - dibinf = malloc(sizeof(BITMAPINFO) + 12); - assert(dibinf); - dibinf->bmiHeader.biSize = sizeof(dibinf->bmiHeader); - dibinf->bmiHeader.biPlanes = 1; - dibinf->bmiHeader.biBitCount = 32; - dibinf->bmiHeader.biCompression = BI_RGB; - dibinf->bmiHeader.biXPelsPerMeter = 2834; - dibinf->bmiHeader.biYPelsPerMeter = 2834; - dibinf->bmiHeader.biClrUsed = 0; - dibinf->bmiHeader.biClrImportant = 0; - dibinf->bmiHeader.biClrUsed = 0; - - /* Create window */ - hwndframe = CreateWindowW(L"FrameWindow", // window class name - NULL, // window caption - WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, - CW_USEDEFAULT, CW_USEDEFAULT, // initial position - 300, // initial x size - 300, // initial y size - 0, // parent window handle - 0, // window menu handle - 0, // program instance handle - 0); // creation parameters - if (!hwndframe) - winerror(&gapp, "cannot create frame"); - - hwndview = CreateWindowW(L"ViewWindow", // window class name - NULL, - WS_VISIBLE | WS_CHILD, - CW_USEDEFAULT, CW_USEDEFAULT, - CW_USEDEFAULT, CW_USEDEFAULT, - hwndframe, 0, 0, 0); - if (!hwndview) - winerror(&gapp, "cannot create view"); - - hdc = NULL; - - SetWindowTextW(hwndframe, L"MuPDF"); - - menu = GetSystemMenu(hwndframe, 0); - AppendMenuW(menu, MF_SEPARATOR, 0, NULL); - AppendMenuW(menu, MF_STRING, ID_ABOUT, L"About MuPDF..."); - AppendMenuW(menu, MF_STRING, ID_DOCINFO, L"Document Properties..."); - - SetCursor(arrowcurs); -} - -void winclose(pdfapp_t *app) -{ - if (pdfapp_preclose(app)) - { - pdfapp_close(app); - exit(0); - } -} - -void wincursor(pdfapp_t *app, int curs) -{ - if (curs == ARROW) - SetCursor(arrowcurs); - if (curs == HAND) - SetCursor(handcurs); - if (curs == WAIT) - SetCursor(waitcurs); - if (curs == CARET) - SetCursor(caretcurs); -} - -void wintitle(pdfapp_t *app, char *title) -{ - wchar_t wide[256], *dp; - char *sp; - int rune; - - dp = wide; - sp = title; - while (*sp && dp < wide + 255) - { - sp += fz_chartorune(&rune, sp); - *dp++ = rune; - } - *dp = 0; - - SetWindowTextW(hwndframe, wide); -} - -void windrawrect(pdfapp_t *app, int x0, int y0, int x1, int y1) -{ - RECT r; - r.left = x0; - r.top = y0; - r.right = x1; - r.bottom = y1; - FillRect(hdc, &r, (HBRUSH)GetStockObject(WHITE_BRUSH)); -} - -void windrawstring(pdfapp_t *app, int x, int y, char *s) -{ - HFONT font = (HFONT)GetStockObject(ANSI_FIXED_FONT); - SelectObject(hdc, font); - TextOutA(hdc, x, y - 12, s, strlen(s)); -} - -void winblitsearch() -{ - if (gapp.isediting) - { - char buf[sizeof(gapp.search) + 50]; - sprintf(buf, "Search: %s", gapp.search); - windrawrect(&gapp, 0, 0, gapp.winw, 30); - windrawstring(&gapp, 10, 20, buf); - } -} - -void winblit() -{ - int image_w = fz_pixmap_width(gapp.ctx, gapp.image); - int image_h = fz_pixmap_height(gapp.ctx, gapp.image); - int image_n = fz_pixmap_components(gapp.ctx, gapp.image); - unsigned char *samples = fz_pixmap_samples(gapp.ctx, gapp.image); - int x0 = gapp.panx; - int y0 = gapp.pany; - int x1 = gapp.panx + image_w; - int y1 = gapp.pany + image_h; - RECT r; - - if (gapp.image) - { - if (gapp.iscopying || justcopied) - { - pdfapp_invert(&gapp, &gapp.selr); - justcopied = 1; - } - - pdfapp_inverthit(&gapp); - - dibinf->bmiHeader.biWidth = image_w; - dibinf->bmiHeader.biHeight = -image_h; - dibinf->bmiHeader.biSizeImage = image_h * 4; - - if (image_n == 2) - { - int i = image_w * image_h; - unsigned char *color = malloc(i*4); - unsigned char *s = samples; - unsigned char *d = color; - for (; i > 0 ; i--) - { - d[2] = d[1] = d[0] = *s++; - d[3] = *s++; - d += 4; - } - SetDIBitsToDevice(hdc, - gapp.panx, gapp.pany, image_w, image_h, - 0, 0, 0, image_h, color, - dibinf, DIB_RGB_COLORS); - free(color); - } - if (image_n == 4) - { - SetDIBitsToDevice(hdc, - gapp.panx, gapp.pany, image_w, image_h, - 0, 0, 0, image_h, samples, - dibinf, DIB_RGB_COLORS); - } - - pdfapp_inverthit(&gapp); - - if (gapp.iscopying || justcopied) - { - pdfapp_invert(&gapp, &gapp.selr); - justcopied = 1; - } - } - - /* Grey background */ - r.top = 0; r.bottom = gapp.winh; - r.left = 0; r.right = x0; - FillRect(hdc, &r, bgbrush); - r.left = x1; r.right = gapp.winw; - FillRect(hdc, &r, bgbrush); - r.left = 0; r.right = gapp.winw; - r.top = 0; r.bottom = y0; - FillRect(hdc, &r, bgbrush); - r.top = y1; r.bottom = gapp.winh; - FillRect(hdc, &r, bgbrush); - - /* Drop shadow */ - r.left = x0 + 2; - r.right = x1 + 2; - r.top = y1; - r.bottom = y1 + 2; - FillRect(hdc, &r, shbrush); - r.left = x1; - r.right = x1 + 2; - r.top = y0 + 2; - r.bottom = y1; - FillRect(hdc, &r, shbrush); - - winblitsearch(); -} - -void winresize(pdfapp_t *app, int w, int h) -{ - ShowWindow(hwndframe, SW_SHOWDEFAULT); - w += GetSystemMetrics(SM_CXFRAME) * 2; - h += GetSystemMetrics(SM_CYFRAME) * 2; - h += GetSystemMetrics(SM_CYCAPTION); - SetWindowPos(hwndframe, 0, 0, 0, w, h, SWP_NOZORDER | SWP_NOMOVE); -} - -void winrepaint(pdfapp_t *app) -{ - InvalidateRect(hwndview, NULL, 0); -} - -void winrepaintsearch(pdfapp_t *app) -{ - // TODO: invalidate only search area and - // call only search redraw routine. - InvalidateRect(hwndview, NULL, 0); -} - -void winfullscreen(pdfapp_t *app, int state) -{ - static WINDOWPLACEMENT savedplace; - static int isfullscreen = 0; - if (state && !isfullscreen) - { - GetWindowPlacement(hwndframe, &savedplace); - SetWindowLong(hwndframe, GWL_STYLE, WS_POPUP | WS_VISIBLE); - SetWindowPos(hwndframe, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_FRAMECHANGED); - ShowWindow(hwndframe, SW_SHOWMAXIMIZED); - isfullscreen = 1; - } - if (!state && isfullscreen) - { - SetWindowLong(hwndframe, GWL_STYLE, WS_OVERLAPPEDWINDOW); - SetWindowPos(hwndframe, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_FRAMECHANGED); - SetWindowPlacement(hwndframe, &savedplace); - isfullscreen = 0; - } -} - -/* - * Event handling - */ - -void windocopy(pdfapp_t *app) -{ - HGLOBAL handle; - unsigned short *ucsbuf; - - if (!OpenClipboard(hwndframe)) - return; - EmptyClipboard(); - - handle = GlobalAlloc(GMEM_MOVEABLE, 4096 * sizeof(unsigned short)); - if (!handle) - { - CloseClipboard(); - return; - } - - ucsbuf = GlobalLock(handle); - pdfapp_oncopy(&gapp, ucsbuf, 4096); - GlobalUnlock(handle); - - SetClipboardData(CF_UNICODETEXT, handle); - CloseClipboard(); - - justcopied = 1; /* keep inversion around for a while... */ -} - -void winreloadfile(pdfapp_t *app) -{ - pdfapp_close(app); - pdfapp_open(app, filename, 1); -} - -void winopenuri(pdfapp_t *app, char *buf) -{ - ShellExecuteA(hwndframe, "open", buf, 0, 0, SW_SHOWNORMAL); -} - -#define OUR_TIMER_ID 1 - -void winadvancetimer(pdfapp_t *app, float delay) -{ - timer_pending = 1; - SetTimer(hwndview, OUR_TIMER_ID, (unsigned int)(1000*delay), NULL); -} - -static void killtimer(pdfapp_t *app) -{ - timer_pending = 0; -} - -void handlekey(int c) -{ - if (timer_pending) - killtimer(&gapp); - - if (GetCapture() == hwndview) - return; - - if (justcopied) - { - justcopied = 0; - winrepaint(&gapp); - } - - /* translate VK into ASCII equivalents */ - if (c > 256) - { - switch (c - 256) - { - case VK_F1: c = '?'; break; - case VK_ESCAPE: c = '\033'; break; - case VK_DOWN: c = 'j'; break; - case VK_UP: c = 'k'; break; - case VK_LEFT: c = 'b'; break; - case VK_RIGHT: c = ' '; break; - case VK_PRIOR: c = ','; break; - case VK_NEXT: c = '.'; break; - } - } - - pdfapp_onkey(&gapp, c); - winrepaint(&gapp); -} - -void handlemouse(int x, int y, int btn, int state) -{ - if (state != 0 && timer_pending) - killtimer(&gapp); - - if (state != 0 && justcopied) - { - justcopied = 0; - winrepaint(&gapp); - } - - if (state == 1) - SetCapture(hwndview); - if (state == -1) - ReleaseCapture(); - - pdfapp_onmouse(&gapp, x, y, btn, 0, state); -} - -LRESULT CALLBACK -frameproc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - switch(message) - { - case WM_SETFOCUS: - PostMessage(hwnd, WM_APP+5, 0, 0); - return 0; - case WM_APP+5: - SetFocus(hwndview); - return 0; - - case WM_DESTROY: - PostQuitMessage(0); - return 0; - - case WM_SYSCOMMAND: - if (wParam == ID_ABOUT) - { - winhelp(&gapp); - return 0; - } - if (wParam == ID_DOCINFO) - { - info(); - return 0; - } - if (wParam == SC_MAXIMIZE) - gapp.shrinkwrap = 0; - break; - - case WM_SIZE: - { - // More generally, you should use GetEffectiveClientRect - // if you have a toolbar etc. - RECT rect; - GetClientRect(hwnd, &rect); - MoveWindow(hwndview, rect.left, rect.top, - rect.right-rect.left, rect.bottom-rect.top, TRUE); - return 0; - } - - case WM_SIZING: - gapp.shrinkwrap = 0; - break; - - case WM_NOTIFY: - case WM_COMMAND: - return SendMessage(hwndview, message, wParam, lParam); - - case WM_CLOSE: - if (!pdfapp_preclose(&gapp)) - return 0; - } - - return DefWindowProc(hwnd, message, wParam, lParam); -} - -LRESULT CALLBACK -viewproc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - static int oldx = 0; - static int oldy = 0; - int x = (signed short) LOWORD(lParam); - int y = (signed short) HIWORD(lParam); - - switch (message) - { - case WM_SIZE: - if (wParam == SIZE_MINIMIZED) - return 0; - if (wParam == SIZE_MAXIMIZED) - gapp.shrinkwrap = 0; - pdfapp_onresize(&gapp, LOWORD(lParam), HIWORD(lParam)); - break; - - /* Paint events are low priority and automagically catenated - * so we don't need to do any fancy waiting to defer repainting. - */ - case WM_PAINT: - { - //puts("WM_PAINT"); - PAINTSTRUCT ps; - hdc = BeginPaint(hwnd, &ps); - winblit(); - hdc = NULL; - EndPaint(hwnd, &ps); - pdfapp_postblit(&gapp); - return 0; - } - - case WM_ERASEBKGND: - return 1; // well, we don't need to erase to redraw cleanly - - /* Mouse events */ - - case WM_LBUTTONDOWN: - SetFocus(hwndview); - oldx = x; oldy = y; - handlemouse(x, y, 1, 1); - return 0; - case WM_MBUTTONDOWN: - SetFocus(hwndview); - oldx = x; oldy = y; - handlemouse(x, y, 2, 1); - return 0; - case WM_RBUTTONDOWN: - SetFocus(hwndview); - oldx = x; oldy = y; - handlemouse(x, y, 3, 1); - return 0; - - case WM_LBUTTONUP: - oldx = x; oldy = y; - handlemouse(x, y, 1, -1); - return 0; - case WM_MBUTTONUP: - oldx = x; oldy = y; - handlemouse(x, y, 2, -1); - return 0; - case WM_RBUTTONUP: - oldx = x; oldy = y; - handlemouse(x, y, 3, -1); - return 0; - - case WM_MOUSEMOVE: - oldx = x; oldy = y; - handlemouse(x, y, 0, 0); - return 0; - - /* Mouse wheel */ - - case WM_MOUSEWHEEL: - if ((signed short)HIWORD(wParam) > 0) - handlekey(LOWORD(wParam) & MK_SHIFT ? '+' : 'k'); - else - handlekey(LOWORD(wParam) & MK_SHIFT ? '-' : 'j'); - return 0; - - /* Timer */ - case WM_TIMER: - if (wParam == OUR_TIMER_ID && timer_pending && gapp.presentation_mode) - { - timer_pending = 0; - handlekey(VK_RIGHT + 256); - handlemouse(oldx, oldy, 0, 0); /* update cursor */ - return 0; - } - break; - - /* Keyboard events */ - - case WM_KEYDOWN: - /* only handle special keys */ - switch (wParam) - { - case VK_F1: - case VK_LEFT: - case VK_UP: - case VK_PRIOR: - case VK_RIGHT: - case VK_DOWN: - case VK_NEXT: - case VK_ESCAPE: - handlekey(wParam + 256); - handlemouse(oldx, oldy, 0, 0); /* update cursor */ - return 0; - } - return 1; - - /* unicode encoded chars, including escape, backspace etc... */ - case WM_CHAR: - if (wParam < 256) - { - handlekey(wParam); - handlemouse(oldx, oldy, 0, 0); /* update cursor */ - } - return 0; - } - - fflush(stdout); - - /* Pass on unhandled events to Windows */ - return DefWindowProc(hwnd, message, wParam, lParam); -} - -int WINAPI -WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) -{ - int argc; - LPWSTR *argv = CommandLineToArgvW(GetCommandLineW(), &argc); - char argv0[256]; - MSG msg; - int code; - fz_context *ctx; - - ctx = fz_new_context(NULL, NULL, FZ_STORE_DEFAULT); - if (!ctx) - { - fprintf(stderr, "cannot initialise context\n"); - exit(1); - } - pdfapp_init(ctx, &gapp); - - GetModuleFileNameA(NULL, argv0, sizeof argv0); - install_app(argv0); - - winopen(); - - if (argc == 2) - { - wcscpy(wbuf, argv[1]); - } - else - { - if (!winfilename(wbuf, nelem(wbuf))) - exit(0); - } - - code = WideCharToMultiByte(CP_UTF8, 0, wbuf, -1, filename, sizeof filename, NULL, NULL); - if (code == 0) - winerror(&gapp, "cannot convert filename to utf-8"); - - pdfapp_open(&gapp, filename, 0); - - while (GetMessage(&msg, NULL, 0, 0)) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - - pdfapp_close(&gapp); - - return 0; -} diff --git a/apps/win_res.rc b/apps/win_res.rc deleted file mode 100644 index fbf6915c..00000000 --- a/apps/win_res.rc +++ /dev/null @@ -1,82 +0,0 @@ -IDI_ICONAPP ICON "mupdf.ico" - -IDD_DLOGPASS DIALOG 50, 50, 204, 60 -//STYLE DS_MODALFRAME | WS_POPUP -STYLE 128 | 0x80000000 -CAPTION " MuPDF: Password " -FONT 8, "MS Shell Dlg" -BEGIN - EDITTEXT 3, 57, 20, 140, 12, 32 - DEFPUSHBUTTON "Okay", 1, 90, 40, 50, 14, 0x50010001 - PUSHBUTTON "Cancel", 2, 147, 40, 50, 14, 0x50010000 - LTEXT "The file is encrypted.", 4, 10, 7, 180, 10, 0x00000 - LTEXT "Password:", 5, 17, 22, 40, 10, 0x00000 -END - -IDD_DLOGINFO DIALOG 50, 50, 300, 145 -STYLE 128 | 0x80000000 -CAPTION " Document Properties " -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "Okay", 1, 300-10-50, 145-7-14, 50, 14, 0x50010001 - - LTEXT "File:", -1, 10, 10, 50, 10, 0 - LTEXT "Format:", -1, 10, 20, 50, 10, 0 - LTEXT "Encryption:", -1, 10, 30, 50, 10, 0 - LTEXT "Permissions:", -1, 10, 40, 50, 10, 0 - - LTEXT "<file", 0x10, 60, 10, 230, 10, 0 - LTEXT "<version", 0x11, 60, 20, 230, 10, 0 - LTEXT "<encryption", 0x12, 60, 30, 230, 10, 0 - LTEXT "<permissions", 0x13, 60, 40, 230, 10, 0 - - LTEXT "Title:", -1, 10, 55, 50, 10, 0 - LTEXT "Author:", -1, 10, 65, 50, 10, 0 - LTEXT "Subject:", -1, 10, 75, 50, 10, 0 - LTEXT "Keywords:", -1, 10, 85, 50, 10, 0 - LTEXT "Creator:", -1, 10, 95, 50, 10, 0 - LTEXT "Producer:", -1, 10, 105, 50, 10, 0 - LTEXT "Created:", -1, 10, 115, 50, 10, 0 - LTEXT "Modified:", -1, 10, 125, 50, 10, 0 - - LTEXT "", 0x20, 60, 55, 230, 10, 0 - LTEXT "", 0x21, 60, 65, 230, 10, 0 - LTEXT "", 0x22, 60, 75, 230, 10, 0 - LTEXT "", 0x23, 60, 85, 230, 10, 0 - LTEXT "", 0x24, 60, 95, 230, 10, 0 - LTEXT "", 0x25, 60, 105, 230, 10, 0 - LTEXT "", 0x26, 60, 115, 100, 10, 0 - LTEXT "", 0x27, 60, 125, 100, 10, 0 -END - -IDD_DLOGTEXT DIALOG 50, 50, 204, 85 -STYLE 128 | 0x80000000 -CAPTION " MuPDF: fill out form" -FONT 8, "MS Shell Dlg" -BEGIN - EDITTEXT 3,8,7,183,50,0x1004 - DEFPUSHBUTTON "Okay",1,89,64,50,14 - PUSHBUTTON "Cancel",2,147,64,50,14 - LTEXT "** Invalid value **",4,11,65,62,8 -END - -IDD_DLOGLIST DIALOG 50, 50, 204, 85 -STYLE 128 | 0x80000000 -CAPTION " MuPDF: select an item" -FONT 8, "MS Shell Dlg" -BEGIN - LISTBOX 3,8,7,183,50,0x210102 - DEFPUSHBUTTON "Okay",1,89,64,50,14 - PUSHBUTTON "Cancel",2,147,64,50,14 -END - -IDD_DLOGABOUT DIALOG 50, 50, 200, 300 -STYLE 128 | 0x80000000 -CAPTION " About MuPDF " -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "Okay", 1, 200-10-50, 300-7-14, 50, 14, 0x50010001 - LTEXT "<copyright>", 2, 10, 10, 180, 20, 0 - LTEXT "<usage>", 3, 10, 35, 180, 240, 0 -END - diff --git a/apps/x11_image.c b/apps/x11_image.c deleted file mode 100644 index 4f2db2e8..00000000 --- a/apps/x11_image.c +++ /dev/null @@ -1,703 +0,0 @@ -/* - * Blit RGBA images to X with X(Shm)Images - */ - -#ifndef _XOPEN_SOURCE -# define _XOPEN_SOURCE 1 -#endif - -#ifndef _XOPEN_SOURCE -# define _XOPEN_SOURCE 1 -#endif - -#define noSHOWINFO - -#include "mupdf/fitz.h" - -#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include <sys/ipc.h> -#include <sys/shm.h> -#include <X11/extensions/XShm.h> - -extern int ffs(int); - -static int is_big_endian(void) -{ - static const int one = 1; - return *(char*)&one == 0; -} - -typedef void (*ximage_convert_func_t) -( - const unsigned char *src, - int srcstride, - unsigned char *dst, - int dststride, - int w, - int h - ); - -#define POOLSIZE 4 -#define WIDTH 256 -#define HEIGHT 256 - -enum { - ARGB8888, - BGRA8888, - RGBA8888, - ABGR8888, - RGB888, - BGR888, - RGB565, - RGB565_BR, - RGB555, - RGB555_BR, - BGR233, - UNKNOWN -}; - -#ifdef SHOWINFO -static char *modename[] = { - "ARGB8888", - "BGRA8888", - "RGBA8888", - "ABGR8888", - "RGB888", - "BGR888", - "RGB565", - "RGB565_BR", - "RGB555", - "RGB555_BR", - "BGR233", - "UNKNOWN" -}; -#endif - -extern ximage_convert_func_t ximage_convert_funcs[]; - -static struct -{ - Display *display; - int screen; - XVisualInfo visual; - Colormap colormap; - - int bitsperpixel; - int mode; - - XColor rgbcube[256]; - - ximage_convert_func_t convert_func; - - int useshm; - int shmcode; - XImage *pool[POOLSIZE]; - /* MUST exist during the lifetime of the shared ximage according to the - xc/doc/hardcopy/Xext/mit-shm.PS.gz */ - XShmSegmentInfo shminfo[POOLSIZE]; - int lastused; -} info; - -static XImage * -createximage(Display *dpy, Visual *vis, XShmSegmentInfo *xsi, int depth, int w, int h) -{ - XImage *img; - Status status; - - if (!XShmQueryExtension(dpy)) - goto fallback; - if (!info.useshm) - goto fallback; - - img = XShmCreateImage(dpy, vis, depth, ZPixmap, NULL, xsi, w, h); - if (!img) - { - fprintf(stderr, "warn: could not XShmCreateImage\n"); - goto fallback; - } - - xsi->shmid = shmget(IPC_PRIVATE, - img->bytes_per_line * img->height, - IPC_CREAT | 0777); - if (xsi->shmid < 0) - { - XDestroyImage(img); - fprintf(stderr, "warn: could not shmget\n"); - goto fallback; - } - - img->data = xsi->shmaddr = shmat(xsi->shmid, NULL, 0); - if (img->data == (char*)-1) - { - XDestroyImage(img); - fprintf(stderr, "warn: could not shmat\n"); - goto fallback; - } - - xsi->readOnly = False; - status = XShmAttach(dpy, xsi); - if (!status) - { - shmdt(xsi->shmaddr); - XDestroyImage(img); - fprintf(stderr, "warn: could not XShmAttach\n"); - goto fallback; - } - - XSync(dpy, False); - - shmctl(xsi->shmid, IPC_RMID, NULL); - - return img; - -fallback: - info.useshm = 0; - - img = XCreateImage(dpy, vis, depth, ZPixmap, 0, NULL, w, h, 32, 0); - if (!img) - { - fprintf(stderr, "fail: could not XCreateImage"); - abort(); - } - - img->data = malloc(h * img->bytes_per_line); - if (!img->data) - { - fprintf(stderr, "fail: could not malloc"); - abort(); - } - - return img; -} - -static void -make_colormap(void) -{ - if (info.visual.class == PseudoColor && info.visual.depth == 8) - { - int i, r, g, b; - i = 0; - for (b = 0; b < 4; b++) { - for (g = 0; g < 8; g++) { - for (r = 0; r < 8; r++) { - info.rgbcube[i].pixel = i; - info.rgbcube[i].red = (r * 36) << 8; - info.rgbcube[i].green = (g * 36) << 8; - info.rgbcube[i].blue = (b * 85) << 8; - info.rgbcube[i].flags = - DoRed | DoGreen | DoBlue; - i++; - } - } - } - info.colormap = XCreateColormap(info.display, - RootWindow(info.display, info.screen), - info.visual.visual, - AllocAll); - XStoreColors(info.display, info.colormap, info.rgbcube, 256); - return; - } - else if (info.visual.class == TrueColor) - { - info.colormap = 0; - return; - } - fprintf(stderr, "Cannot handle visual class %d with depth: %d\n", - info.visual.class, info.visual.depth); - return; -} - -static void -select_mode(void) -{ - - int byteorder; - int byterev; - unsigned long rm, gm, bm; - unsigned long rs, gs, bs; - - byteorder = ImageByteOrder(info.display); - if (is_big_endian()) - byterev = byteorder != MSBFirst; - else - byterev = byteorder != LSBFirst; - - rm = info.visual.red_mask; - gm = info.visual.green_mask; - bm = info.visual.blue_mask; - - rs = ffs(rm) - 1; - gs = ffs(gm) - 1; - bs = ffs(bm) - 1; - -#ifdef SHOWINFO - printf("ximage: mode %d/%d %08lx %08lx %08lx (%ld,%ld,%ld) %s%s\n", - info.visual.depth, - info.bitsperpixel, - rm, gm, bm, rs, gs, bs, - byteorder == MSBFirst ? "msb" : "lsb", - byterev ? " <swap>":""); -#endif - - info.mode = UNKNOWN; - if (info.bitsperpixel == 8) { - /* Either PseudoColor with BGR233 colormap, or TrueColor */ - info.mode = BGR233; - } - else if (info.bitsperpixel == 16) { - if (rm == 0xF800 && gm == 0x07E0 && bm == 0x001F) - info.mode = !byterev ? RGB565 : RGB565_BR; - if (rm == 0x7C00 && gm == 0x03E0 && bm == 0x001F) - info.mode = !byterev ? RGB555 : RGB555_BR; - } - else if (info.bitsperpixel == 24) { - if (rs == 0 && gs == 8 && bs == 16) - info.mode = byteorder == MSBFirst ? RGB888 : BGR888; - if (rs == 16 && gs == 8 && bs == 0) - info.mode = byteorder == MSBFirst ? BGR888 : RGB888; - } - else if (info.bitsperpixel == 32) { - if (rs == 0 && gs == 8 && bs == 16) - info.mode = byteorder == MSBFirst ? ABGR8888 : RGBA8888; - if (rs == 8 && gs == 16 && bs == 24) - info.mode = byteorder == MSBFirst ? BGRA8888 : ARGB8888; - if (rs == 16 && gs == 8 && bs == 0) - info.mode = byteorder == MSBFirst ? ARGB8888 : BGRA8888; - if (rs == 24 && gs == 16 && bs == 8) - info.mode = byteorder == MSBFirst ? RGBA8888 : ABGR8888; - } - -#ifdef SHOWINFO - printf("ximage: RGBA8888 to %s\n", modename[info.mode]); -#endif - - /* select conversion function */ - info.convert_func = ximage_convert_funcs[info.mode]; -} - -static int -create_pool(void) -{ - int i; - - info.lastused = 0; - - for (i = 0; i < POOLSIZE; i++) { - info.pool[i] = NULL; - } - - for (i = 0; i < POOLSIZE; i++) { - info.pool[i] = createximage(info.display, - info.visual.visual, &info.shminfo[i], info.visual.depth, - WIDTH, HEIGHT); - if (!info.pool[i]) { - return 0; - } - } - - return 1; -} - -static XImage * -next_pool_image(void) -{ - if (info.lastused + 1 >= POOLSIZE) { - if (info.useshm) - XSync(info.display, False); - else - XFlush(info.display); - info.lastused = 0; - } - return info.pool[info.lastused ++]; -} - -static int -ximage_error_handler(Display *display, XErrorEvent *event) -{ - /* Turn off shared memory images if we get an error from the MIT-SHM extension */ - if (event->request_code == info.shmcode) - { - char buf[80]; - XGetErrorText(display, event->error_code, buf, sizeof buf); - fprintf(stderr, "ximage: disabling shared memory extension: %s\n", buf); - info.useshm = 0; - return 0; - } - - XSetErrorHandler(NULL); - return (XSetErrorHandler(ximage_error_handler))(display, event); -} - -int -ximage_init(Display *display, int screen, Visual *visual) -{ - XVisualInfo template; - XVisualInfo *visuals; - int nvisuals; - XPixmapFormatValues *formats; - int nformats; - int ok; - int i; - int major; - int event; - int error; - - info.display = display; - info.screen = screen; - info.colormap = 0; - - /* Get XVisualInfo for this visual */ - template.visualid = XVisualIDFromVisual(visual); - visuals = XGetVisualInfo(display, VisualIDMask, &template, &nvisuals); - if (nvisuals != 1) { - fprintf(stderr, "Visual not found!\n"); - XFree(visuals); - return 0; - } - memcpy(&info.visual, visuals, sizeof (XVisualInfo)); - XFree(visuals); - - /* Get appropriate PixmapFormat for this visual */ - formats = XListPixmapFormats(info.display, &nformats); - for (i = 0; i < nformats; i++) { - if (formats[i].depth == info.visual.depth) { - info.bitsperpixel = formats[i].bits_per_pixel; - break; - } - } - XFree(formats); - if (i == nformats) { - fprintf(stderr, "PixmapFormat not found!\n"); - return 0; - } - - /* extract mode */ - select_mode(); - - /* prepare colormap */ - make_colormap(); - - /* identify code for MIT-SHM extension */ - if (XQueryExtension(display, "MIT-SHM", &major, &event, &error) && - XShmQueryExtension(display)) - info.shmcode = major; - - /* intercept errors looking for SHM code */ - XSetErrorHandler(ximage_error_handler); - - /* prepare pool of XImages */ - info.useshm = 1; - ok = create_pool(); - if (!ok) - return 0; - -#ifdef SHOWINFO - printf("ximage: %sPutImage\n", info.useshm ? "XShm" : "X"); -#endif - - return 1; -} - -int -ximage_get_depth(void) -{ - return info.visual.depth; -} - -Visual * -ximage_get_visual(void) -{ - return info.visual.visual; -} - -Colormap -ximage_get_colormap(void) -{ - return info.colormap; -} - -void -ximage_blit(Drawable d, GC gc, - int dstx, int dsty, - unsigned char *srcdata, - int srcx, int srcy, - int srcw, int srch, - int srcstride) -{ - XImage *image; - int ax, ay; - int w, h; - unsigned char *srcptr; - - for (ay = 0; ay < srch; ay += HEIGHT) - { - h = fz_mini(srch - ay, HEIGHT); - for (ax = 0; ax < srcw; ax += WIDTH) - { - w = fz_mini(srcw - ax, WIDTH); - - image = next_pool_image(); - - srcptr = srcdata + - (ay + srcy) * srcstride + - (ax + srcx) * 4; - - info.convert_func(srcptr, srcstride, - (unsigned char *) image->data, - image->bytes_per_line, w, h); - - if (info.useshm) - { - XShmPutImage(info.display, d, gc, image, - 0, 0, dstx + ax, dsty + ay, - w, h, False); - } - else - { - XPutImage(info.display, d, gc, image, - 0, 0, - dstx + ax, - dsty + ay, - w, h); - } - } - } -} - -/* - * Primitive conversion functions - */ - -#ifndef restrict -#ifndef _C99 -#ifdef __GNUC__ -#define restrict __restrict__ -#else -#define restrict -#endif -#endif -#endif - -#define PARAMS \ - const unsigned char * restrict src, \ - int srcstride, \ - unsigned char * restrict dst, \ - int dststride, \ - int w, \ - int h - -/* - * Convert byte:RGBA8888 to various formats - */ - -static void -ximage_convert_argb8888(PARAMS) -{ - int x, y; - for (y = 0; y < h; y++) { - for (x = 0; x < w; x ++) { - dst[x * 4 + 0] = src[x * 4 + 3]; /* a */ - dst[x * 4 + 1] = src[x * 4 + 0]; /* r */ - dst[x * 4 + 2] = src[x * 4 + 1]; /* g */ - dst[x * 4 + 3] = src[x * 4 + 2]; /* b */ - } - dst += dststride; - src += srcstride; - } -} - -static void -ximage_convert_bgra8888(PARAMS) -{ - int x, y; - for (y = 0; y < h; y++) { - for (x = 0; x < w; x++) { - dst[x * 4 + 0] = src[x * 4 + 2]; - dst[x * 4 + 1] = src[x * 4 + 1]; - dst[x * 4 + 2] = src[x * 4 + 0]; - dst[x * 4 + 3] = src[x * 4 + 3]; - } - dst += dststride; - src += srcstride; - } -} - -static void -ximage_convert_abgr8888(PARAMS) -{ - int x, y; - for (y = 0; y < h; y++) { - for (x = 0; x < w; x++) { - dst[x * 4 + 0] = src[x * 4 + 3]; - dst[x * 4 + 1] = src[x * 4 + 2]; - dst[x * 4 + 2] = src[x * 4 + 1]; - dst[x * 4 + 3] = src[x * 4 + 0]; - } - dst += dststride; - src += srcstride; - } -} - -static void -ximage_convert_rgba8888(PARAMS) -{ - int x, y; - for (y = 0; y < h; y++) { - for (x = 0; x < w; x++) { - ((unsigned *)dst)[x] = ((unsigned *)src)[x]; - } - dst += dststride; - src += srcstride; - } -} - -static void -ximage_convert_bgr888(PARAMS) -{ - int x, y; - for (y = 0; y < h; y++) { - for (x = 0; x < w; x++) { - dst[3*x + 0] = src[4*x + 2]; - dst[3*x + 1] = src[4*x + 1]; - dst[3*x + 2] = src[4*x + 0]; - } - src += srcstride; - dst += dststride; - } -} - -static void -ximage_convert_rgb888(PARAMS) -{ - int x, y; - for (y = 0; y < h; y++) { - for (x = 0; x < w; x++) { - dst[3*x + 0] = src[4*x + 0]; - dst[3*x + 1] = src[4*x + 1]; - dst[3*x + 2] = src[4*x + 2]; - } - src += srcstride; - dst += dststride; - } -} - -static void -ximage_convert_rgb565(PARAMS) -{ - unsigned char r, g, b; - int x, y; - for (y = 0; y < h; y++) { - for (x = 0; x < w; x++) { - r = src[4*x + 0]; - g = src[4*x + 1]; - b = src[4*x + 2]; - ((unsigned short *)dst)[x] = - ((r & 0xF8) << 8) | - ((g & 0xFC) << 3) | - (b >> 3); - } - src += srcstride; - dst += dststride; - } -} - -static void -ximage_convert_rgb565_br(PARAMS) -{ - unsigned char r, g, b; - int x, y; - for (y = 0; y < h; y++) { - for (x = 0; x < w; x++) { - r = src[4*x + 0]; - g = src[4*x + 1]; - b = src[4*x + 2]; - /* final word is: - g4 g3 g2 b7 b6 b5 b4 b3 : r7 r6 r5 r4 r3 g7 g6 g5 - */ - ((unsigned short *)dst)[x] = - (r & 0xF8) | - ((g & 0xE0) >> 5) | - ((g & 0x1C) << 11) | - ((b & 0xF8) << 5); - } - src += srcstride; - dst += dststride; - } -} - -static void -ximage_convert_rgb555(PARAMS) -{ - unsigned char r, g, b; - int x, y; - for (y = 0; y < h; y++) { - for (x = 0; x < w; x++) { - r = src[4*x + 0]; - g = src[4*x + 1]; - b = src[4*x + 2]; - ((unsigned short *)dst)[x] = - ((r & 0xF8) << 7) | - ((g & 0xF8) << 2) | - (b >> 3); - } - src += srcstride; - dst += dststride; - } -} - -static void -ximage_convert_rgb555_br(PARAMS) -{ - unsigned char r, g, b; - int x, y; - for (y = 0; y < h; y++) { - for (x = 0; x < w; x++) { - r = src[4*x + 0]; - g = src[4*x + 1]; - b = src[4*x + 2]; - /* final word is: - g5 g4 g3 b7 b6 b5 b4 b3 : 0 r7 r6 r5 r4 r3 g7 g6 - */ - ((unsigned short *)dst)[x] = - ((r & 0xF8) >> 1) | - ((g & 0xC0) >> 6) | - ((g & 0x38) << 10) | - ((b & 0xF8) << 5); - } - src += srcstride; - dst += dststride; - } -} - -static void -ximage_convert_bgr233(PARAMS) -{ - unsigned char r, g, b; - int x,y; - for(y = 0; y < h; y++) { - for(x = 0; x < w; x++) { - r = src[4*x + 0]; - g = src[4*x + 1]; - b = src[4*x + 2]; - /* format: b7 b6 g7 g6 g5 r7 r6 r5 */ - dst[x] = (b&0xC0) | ((g>>2)&0x38) | ((r>>5)&0x7); - } - src += srcstride; - dst += dststride; - } -} - -ximage_convert_func_t ximage_convert_funcs[] = { - ximage_convert_argb8888, - ximage_convert_bgra8888, - ximage_convert_rgba8888, - ximage_convert_abgr8888, - ximage_convert_rgb888, - ximage_convert_bgr888, - ximage_convert_rgb565, - ximage_convert_rgb565_br, - ximage_convert_rgb555, - ximage_convert_rgb555_br, - ximage_convert_bgr233, -}; diff --git a/apps/x11_main.c b/apps/x11_main.c deleted file mode 100644 index 481adce1..00000000 --- a/apps/x11_main.c +++ /dev/null @@ -1,993 +0,0 @@ -#include "pdfapp.h" - -#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include <X11/Xatom.h> -#include <X11/cursorfont.h> -#include <X11/keysym.h> - -#include <sys/select.h> -#include <sys/time.h> -#include <sys/types.h> -#include <unistd.h> -#include <signal.h> - -#define mupdf_icon_bitmap_16_width 16 -#define mupdf_icon_bitmap_16_height 16 -static unsigned char mupdf_icon_bitmap_16_bits[] = { - 0x00, 0x00, 0x00, 0x1e, 0x00, 0x2b, 0x80, 0x55, 0x8c, 0x62, 0x8c, 0x51, - 0x9c, 0x61, 0x1c, 0x35, 0x3c, 0x1f, 0x3c, 0x0f, 0xfc, 0x0f, 0xec, 0x0d, - 0xec, 0x0d, 0xcc, 0x0c, 0xcc, 0x0c, 0x00, 0x00 }; - -#define mupdf_icon_bitmap_16_mask_width 16 -#define mupdf_icon_bitmap_16_mask_height 16 -static unsigned char mupdf_icon_bitmap_16_mask_bits[] = { - 0x00, 0x1e, 0x00, 0x3f, 0x80, 0x7f, 0xce, 0xff, 0xde, 0xff, 0xde, 0xff, - 0xfe, 0xff, 0xfe, 0x7f, 0xfe, 0x3f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f, - 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f, 0xce, 0x1c }; - -#ifndef timeradd -#define timeradd(a, b, result) \ - do { \ - (result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \ - (result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \ - if ((result)->tv_usec >= 1000000) \ - { \ - ++(result)->tv_sec; \ - (result)->tv_usec -= 1000000; \ - } \ - } while (0) -#endif - -#ifndef timersub -#define timersub(a, b, result) \ - do { \ - (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ - (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \ - if ((result)->tv_usec < 0) { \ - --(result)->tv_sec; \ - (result)->tv_usec += 1000000; \ - } \ - } while (0) -#endif - -extern int ximage_init(Display *display, int screen, Visual *visual); -extern int ximage_get_depth(void); -extern Visual *ximage_get_visual(void); -extern Colormap ximage_get_colormap(void); -extern void ximage_blit(Drawable d, GC gc, int dstx, int dsty, - unsigned char *srcdata, - int srcx, int srcy, int srcw, int srch, int srcstride); - -void windrawstringxor(pdfapp_t *app, int x, int y, char *s); -void cleanup(pdfapp_t *app); - -static Display *xdpy; -static Atom XA_CLIPBOARD; -static Atom XA_TARGETS; -static Atom XA_TIMESTAMP; -static Atom XA_UTF8_STRING; -static Atom WM_DELETE_WINDOW; -static Atom NET_WM_STATE; -static Atom NET_WM_STATE_FULLSCREEN; -static int x11fd; -static int xscr; -static Window xwin; -static Pixmap xicon, xmask; -static GC xgc; -static XEvent xevt; -static int mapped = 0; -static Cursor xcarrow, xchand, xcwait, xccaret; -static int justcopied = 0; -static int dirty = 0; -static int transition_dirty = 0; -static int dirtysearch = 0; -static char *password = ""; -static XColor xbgcolor; -static XColor xshcolor; -static int reqw = 0; -static int reqh = 0; -static char copylatin1[1024 * 16] = ""; -static char copyutf8[1024 * 48] = ""; -static Time copytime; -static char *filename; - -static pdfapp_t gapp; -static int closing = 0; -static int reloading = 0; -static int showingpage = 0; - -static int advance_scheduled = 0; -static struct timeval tmo_advance; - -/* - * Dialog boxes - */ - -void winerror(pdfapp_t *app, char *msg) -{ - fprintf(stderr, "mupdf: error: %s\n", msg); - cleanup(app); - exit(1); -} - -void winwarn(pdfapp_t *app, char *msg) -{ - fprintf(stderr, "mupdf: warning: %s\n", msg); -} - -void winalert(pdfapp_t *app, pdf_alert_event *alert) -{ - fprintf(stderr, "Alert %s: %s", alert->title, alert->message); - switch (alert->button_group_type) - { - case PDF_ALERT_BUTTON_GROUP_OK: - case PDF_ALERT_BUTTON_GROUP_OK_CANCEL: - alert->button_pressed = PDF_ALERT_BUTTON_OK; - break; - case PDF_ALERT_BUTTON_GROUP_YES_NO: - case PDF_ALERT_BUTTON_GROUP_YES_NO_CANCEL: - alert->button_pressed = PDF_ALERT_BUTTON_YES; - break; - } -} - -void winprint(pdfapp_t *app) -{ - fprintf(stderr, "The MuPDF library supports printing, but this application currently does not"); -} - -char *winpassword(pdfapp_t *app, char *filename) -{ - char *r = password; - password = NULL; - return r; -} - -char *wintextinput(pdfapp_t *app, char *inittext, int retry) -{ - static char buf[256]; - - if (retry) - return NULL; - - printf("> [%s] ", inittext); - fgets(buf, sizeof buf, stdin); - return buf; -} - -int winchoiceinput(pdfapp_t *app, int nopts, char *opts[], int *nvals, char *vals[]) -{ - /* FIXME: temporary dummy implementation */ - return 0; -} - -/* - * X11 magic - */ - -static void winopen(void) -{ - XWMHints *wmhints; - XClassHint *classhint; - - xdpy = XOpenDisplay(NULL); - if (!xdpy) - fz_throw(gapp.ctx, FZ_ERROR_GENERIC, "cannot open display"); - - XA_CLIPBOARD = XInternAtom(xdpy, "CLIPBOARD", False); - XA_TARGETS = XInternAtom(xdpy, "TARGETS", False); - XA_TIMESTAMP = XInternAtom(xdpy, "TIMESTAMP", False); - XA_UTF8_STRING = XInternAtom(xdpy, "UTF8_STRING", False); - WM_DELETE_WINDOW = XInternAtom(xdpy, "WM_DELETE_WINDOW", False); - NET_WM_STATE = XInternAtom(xdpy, "_NET_WM_STATE", False); - NET_WM_STATE_FULLSCREEN = XInternAtom(xdpy, "_NET_WM_STATE_FULLSCREEN", False); - - xscr = DefaultScreen(xdpy); - - ximage_init(xdpy, xscr, DefaultVisual(xdpy, xscr)); - - xcarrow = XCreateFontCursor(xdpy, XC_left_ptr); - xchand = XCreateFontCursor(xdpy, XC_hand2); - xcwait = XCreateFontCursor(xdpy, XC_watch); - xccaret = XCreateFontCursor(xdpy, XC_xterm); - - 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, 0, - ximage_get_depth(), - InputOutput, - ximage_get_visual(), - 0, - NULL); - if (xwin == None) - fz_throw(gapp.ctx, FZ_ERROR_GENERIC, "cannot create window"); - - XSetWindowColormap(xdpy, xwin, ximage_get_colormap()); - XSelectInput(xdpy, xwin, - StructureNotifyMask | ExposureMask | KeyPressMask | - PointerMotionMask | ButtonPressMask | ButtonReleaseMask); - - mapped = 0; - - xgc = XCreateGC(xdpy, xwin, 0, NULL); - - XDefineCursor(xdpy, xwin, xcarrow); - - wmhints = XAllocWMHints(); - if (wmhints) - { - wmhints->flags = IconPixmapHint | IconMaskHint; - xicon = XCreateBitmapFromData(xdpy, xwin, - (char*)mupdf_icon_bitmap_16_bits, - mupdf_icon_bitmap_16_width, - mupdf_icon_bitmap_16_height); - xmask = XCreateBitmapFromData(xdpy, xwin, - (char*)mupdf_icon_bitmap_16_mask_bits, - mupdf_icon_bitmap_16_mask_width, - mupdf_icon_bitmap_16_mask_height); - if (xicon && xmask) - { - wmhints->icon_pixmap = xicon; - wmhints->icon_mask = xmask; - XSetWMHints(xdpy, xwin, wmhints); - } - XFree(wmhints); - } - - classhint = XAllocClassHint(); - if (classhint) - { - classhint->res_name = "mupdf"; - classhint->res_class = "MuPDF"; - XSetClassHint(xdpy, xwin, classhint); - XFree(classhint); - } - - XSetWMProtocols(xdpy, xwin, &WM_DELETE_WINDOW, 1); - - x11fd = ConnectionNumber(xdpy); -} - -void winclose(pdfapp_t *app) -{ - closing = 1; -} - -int winsavequery(pdfapp_t *app) -{ - /* FIXME: temporary dummy implementation */ - return DISCARD; -} - -int wingetsavepath(pdfapp_t *app, char *buf, int len) -{ - /* FIXME: temporary dummy implementation */ - return 0; -} - -void winreplacefile(char *source, char *target) -{ - rename(source, target); -} - -void cleanup(pdfapp_t *app) -{ - fz_context *ctx = app->ctx; - - pdfapp_close(app); - - XDestroyWindow(xdpy, xwin); - - XFreePixmap(xdpy, xicon); - - XFreeCursor(xdpy, xccaret); - XFreeCursor(xdpy, xcwait); - XFreeCursor(xdpy, xchand); - XFreeCursor(xdpy, xcarrow); - - XFreeGC(xdpy, xgc); - - XCloseDisplay(xdpy); - - fz_free_context(ctx); -} - -static int winresolution() -{ - return DisplayWidth(xdpy, xscr) * 25.4 / - DisplayWidthMM(xdpy, xscr) + 0.5; -} - -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); - if (curs == CARET) - XDefineCursor(xdpy, xwin, xccaret); - XFlush(xdpy); -} - -void wintitle(pdfapp_t *app, char *s) -{ - XStoreName(xdpy, xwin, s); -#ifdef X_HAVE_UTF8_STRING - Xutf8SetWMProperties(xdpy, xwin, s, s, NULL, 0, NULL, NULL, NULL); -#else - XmbSetWMProperties(xdpy, xwin, s, s, NULL, 0, NULL, NULL, NULL); -#endif -} - -void winhelp(pdfapp_t *app) -{ - fprintf(stderr, "%s\n%s", pdfapp_version(app), pdfapp_usage(app)); -} - -void winresize(pdfapp_t *app, int w, int h) -{ - int image_w = fz_pixmap_width(gapp.ctx, gapp.image); - int image_h = fz_pixmap_height(gapp.ctx, gapp.image); - XWindowChanges values; - int mask, width, height; - - mask = CWWidth | CWHeight; - values.width = w; - values.height = h; - XConfigureWindow(xdpy, xwin, mask, &values); - - reqw = w; - reqh = h; - - if (!mapped) - { - gapp.winw = w; - gapp.winh = h; - width = -1; - height = -1; - - XMapWindow(xdpy, xwin); - XFlush(xdpy); - - while (1) - { - XNextEvent(xdpy, &xevt); - if (xevt.type == ConfigureNotify) - { - width = xevt.xconfigure.width; - height = xevt.xconfigure.height; - } - if (xevt.type == MapNotify) - break; - } - - XSetForeground(xdpy, xgc, WhitePixel(xdpy, xscr)); - XFillRectangle(xdpy, xwin, xgc, 0, 0, image_w, image_h); - XFlush(xdpy); - - if (width != reqw || height != reqh) - { - gapp.shrinkwrap = 0; - dirty = 1; - pdfapp_onresize(&gapp, width, height); - } - - mapped = 1; - } -} - -void winfullscreen(pdfapp_t *app, int state) -{ - XEvent xev; - xev.xclient.type = ClientMessage; - xev.xclient.serial = 0; - xev.xclient.send_event = True; - xev.xclient.window = xwin; - xev.xclient.message_type = NET_WM_STATE; - xev.xclient.format = 32; - xev.xclient.data.l[0] = state; - xev.xclient.data.l[1] = NET_WM_STATE_FULLSCREEN; - xev.xclient.data.l[2] = 0; - XSendEvent(xdpy, DefaultRootWindow(xdpy), False, - SubstructureRedirectMask | SubstructureNotifyMask, - &xev); -} - -static void fillrect(int x, int y, int w, int h) -{ - if (w > 0 && h > 0) - XFillRectangle(xdpy, xwin, xgc, x, y, w, h); -} - -static void winblitsearch(pdfapp_t *app) -{ - if (gapp.isediting) - { - char buf[sizeof(gapp.search) + 50]; - sprintf(buf, "Search: %s", gapp.search); - XSetForeground(xdpy, xgc, WhitePixel(xdpy, xscr)); - fillrect(0, 0, gapp.winw, 30); - windrawstring(&gapp, 10, 20, buf); - } -} - -static void winblit(pdfapp_t *app) -{ - int image_w = fz_pixmap_width(gapp.ctx, gapp.image); - int image_h = fz_pixmap_height(gapp.ctx, gapp.image); - int image_n = fz_pixmap_components(gapp.ctx, gapp.image); - unsigned char *image_samples = fz_pixmap_samples(gapp.ctx, gapp.image); - int x0 = gapp.panx; - int y0 = gapp.pany; - int x1 = gapp.panx + image_w; - int y1 = gapp.pany + image_h; - - XSetForeground(xdpy, xgc, xbgcolor.pixel); - fillrect(0, 0, x0, gapp.winh); - fillrect(x1, 0, gapp.winw - x1, gapp.winh); - fillrect(0, 0, gapp.winw, y0); - fillrect(0, y1, gapp.winw, gapp.winh - y1); - - XSetForeground(xdpy, xgc, xshcolor.pixel); - fillrect(x0+2, y1, image_w, 2); - fillrect(x1, y0+2, 2, image_h); - - if (gapp.iscopying || justcopied) - { - pdfapp_invert(&gapp, &gapp.selr); - justcopied = 1; - } - - pdfapp_inverthit(&gapp); - - if (image_n == 4) - ximage_blit(xwin, xgc, - x0, y0, - image_samples, - 0, 0, - image_w, - image_h, - image_w * image_n); - else if (image_n == 2) - { - int i = image_w*image_h; - unsigned char *color = malloc(i*4); - if (color) - { - unsigned char *s = image_samples; - unsigned char *d = color; - for (; i > 0 ; i--) - { - d[2] = d[1] = d[0] = *s++; - d[3] = *s++; - d += 4; - } - ximage_blit(xwin, xgc, - x0, y0, - color, - 0, 0, - image_w, - image_h, - image_w * 4); - free(color); - } - } - - pdfapp_inverthit(&gapp); - - if (gapp.iscopying || justcopied) - { - pdfapp_invert(&gapp, &gapp.selr); - justcopied = 1; - } - - winblitsearch(app); - - if (showingpage) - { - char buf[42]; - snprintf(buf, sizeof buf, "Page %d/%d", gapp.pageno, gapp.pagecount); - windrawstringxor(&gapp, 10, 20, buf); - } -} - -void winrepaint(pdfapp_t *app) -{ - dirty = 1; - if (app->in_transit) - transition_dirty = 1; -} - -void winrepaintsearch(pdfapp_t *app) -{ - dirtysearch = 1; -} - -void winadvancetimer(pdfapp_t *app, float duration) -{ - struct timeval now; - - gettimeofday(&now, NULL); - memset(&tmo_advance, 0, sizeof(tmo_advance)); - tmo_advance.tv_sec = (int)duration; - tmo_advance.tv_usec = 1000000 * (duration - tmo_advance.tv_sec); - timeradd(&tmo_advance, &now, &tmo_advance); - advance_scheduled = 1; -} - -void windrawstringxor(pdfapp_t *app, int x, int y, char *s) -{ - int prevfunction; - XGCValues xgcv; - - XGetGCValues(xdpy, xgc, GCFunction, &xgcv); - prevfunction = xgcv.function; - xgcv.function = GXxor; - XChangeGC(xdpy, xgc, GCFunction, &xgcv); - - XSetForeground(xdpy, xgc, WhitePixel(xdpy, DefaultScreen(xdpy))); - - XDrawString(xdpy, xwin, xgc, x, y, s, strlen(s)); - XFlush(xdpy); - - XGetGCValues(xdpy, xgc, GCFunction, &xgcv); - xgcv.function = prevfunction; - XChangeGC(xdpy, xgc, GCFunction, &xgcv); -} - -void windrawstring(pdfapp_t *app, int x, int y, char *s) -{ - XSetForeground(xdpy, xgc, BlackPixel(xdpy, DefaultScreen(xdpy))); - XDrawString(xdpy, xwin, xgc, x, y, s, strlen(s)); -} - -void docopy(pdfapp_t *app, Atom copy_target) -{ - unsigned short copyucs2[16 * 1024]; - char *latin1 = copylatin1; - char *utf8 = copyutf8; - unsigned short *ucs2; - int ucs; - - pdfapp_oncopy(&gapp, copyucs2, 16 * 1024); - - for (ucs2 = copyucs2; ucs2[0] != 0; ucs2++) - { - ucs = ucs2[0]; - - utf8 += fz_runetochar(utf8, ucs); - - if (ucs < 256) - *latin1++ = ucs; - else - *latin1++ = '?'; - } - - *utf8 = 0; - *latin1 = 0; - - XSetSelectionOwner(xdpy, copy_target, xwin, copytime); - - justcopied = 1; -} - -void windocopy(pdfapp_t *app) -{ - docopy(app, XA_PRIMARY); -} - -void onselreq(Window requestor, Atom selection, Atom target, Atom property, Time time) -{ - XEvent nevt; - - advance_scheduled = 0; - - if (property == None) - property = target; - - nevt.xselection.type = SelectionNotify; - nevt.xselection.send_event = True; - nevt.xselection.display = xdpy; - nevt.xselection.requestor = requestor; - nevt.xselection.selection = selection; - nevt.xselection.target = target; - nevt.xselection.property = property; - nevt.xselection.time = time; - - if (target == XA_TARGETS) - { - Atom atomlist[4]; - atomlist[0] = XA_TARGETS; - atomlist[1] = XA_TIMESTAMP; - atomlist[2] = XA_STRING; - atomlist[3] = XA_UTF8_STRING; - XChangeProperty(xdpy, requestor, property, target, - 32, PropModeReplace, - (unsigned char *)atomlist, sizeof(atomlist)/sizeof(Atom)); - } - - else if (target == XA_STRING) - { - XChangeProperty(xdpy, requestor, property, target, - 8, PropModeReplace, - (unsigned char *)copylatin1, strlen(copylatin1)); - } - - else if (target == XA_UTF8_STRING) - { - XChangeProperty(xdpy, requestor, property, target, - 8, PropModeReplace, - (unsigned char *)copyutf8, strlen(copyutf8)); - } - - else - { - nevt.xselection.property = None; - } - - XSendEvent(xdpy, requestor, False, 0, &nevt); -} - -void winreloadfile(pdfapp_t *app) -{ - pdfapp_close(app); - pdfapp_open(app, filename, 1); -} - -void winopenuri(pdfapp_t *app, char *buf) -{ - char *browser = getenv("BROWSER"); - if (!browser) - { -#ifdef __APPLE__ - browser = "open"; -#else - browser = "xdg-open"; -#endif - } - if (fork() == 0) - { - execlp(browser, browser, buf, (char*)0); - fprintf(stderr, "cannot exec '%s'\n", browser); - exit(0); - } -} - -static void onkey(int c) -{ - advance_scheduled = 0; - - if (justcopied) - { - justcopied = 0; - winrepaint(&gapp); - } - - if (!gapp.isediting && c == 'P') - { - showingpage = 1; - winrepaint(&gapp); - return; - } - - pdfapp_onkey(&gapp, c); -} - -static void onmouse(int x, int y, int btn, int modifiers, int state) -{ - if (state != 0) - advance_scheduled = 0; - - if (state != 0 && justcopied) - { - justcopied = 0; - winrepaint(&gapp); - } - - pdfapp_onmouse(&gapp, x, y, btn, modifiers, state); -} - -static void signal_handler(int signal) -{ - if (signal == SIGHUP) - reloading = 1; -} - -static void usage(void) -{ - fprintf(stderr, "usage: mupdf [options] file.pdf [page]\n"); - fprintf(stderr, "\t-b -\tset anti-aliasing quality in bits (0=off, 8=best)\n"); - fprintf(stderr, "\t-p -\tpassword\n"); - fprintf(stderr, "\t-r -\tresolution\n"); - exit(1); -} - -int main(int argc, char **argv) -{ - int c; - int len; - char buf[128]; - KeySym keysym; - int oldx = 0; - int oldy = 0; - int resolution = -1; - int pageno = 1; - fd_set fds; - int width = -1; - int height = -1; - fz_context *ctx; - struct timeval tmo_at; - struct timeval now; - struct timeval tmo; - struct timeval *timeout; - struct timeval tmo_advance_delay; - - ctx = fz_new_context(NULL, NULL, FZ_STORE_DEFAULT); - if (!ctx) - { - fprintf(stderr, "cannot initialise context\n"); - exit(1); - } - - while ((c = fz_getopt(argc, argv, "p:r:b:")) != -1) - { - switch (c) - { - case 'p': password = fz_optarg; break; - case 'r': resolution = atoi(fz_optarg); break; - case 'b': fz_set_aa_level(ctx, atoi(fz_optarg)); break; - default: usage(); - } - } - - if (argc - fz_optind == 0) - usage(); - - filename = argv[fz_optind++]; - - if (argc - fz_optind == 1) - pageno = atoi(argv[fz_optind++]); - - pdfapp_init(ctx, &gapp); - - winopen(); - - if (resolution == -1) - resolution = winresolution(); - if (resolution < MINRES) - resolution = MINRES; - if (resolution > MAXRES) - resolution = MAXRES; - - gapp.transitions_enabled = 1; - gapp.scrw = DisplayWidth(xdpy, xscr); - gapp.scrh = DisplayHeight(xdpy, xscr); - gapp.resolution = resolution; - gapp.pageno = pageno; - - pdfapp_open(&gapp, filename, 0); - - FD_ZERO(&fds); - - signal(SIGHUP, signal_handler); - - tmo_at.tv_sec = 0; - tmo_at.tv_usec = 0; - - while (!closing) - { - while (!closing && XPending(xdpy) && !transition_dirty) - { - XNextEvent(xdpy, &xevt); - - switch (xevt.type) - { - case Expose: - dirty = 1; - break; - - case ConfigureNotify: - if (gapp.image) - { - if (xevt.xconfigure.width != reqw || - xevt.xconfigure.height != reqh) - gapp.shrinkwrap = 0; - } - width = xevt.xconfigure.width; - height = xevt.xconfigure.height; - - break; - - case KeyPress: - len = XLookupString(&xevt.xkey, buf, sizeof buf, &keysym, NULL); - - if (!gapp.isediting) - switch (keysym) - { - case XK_Escape: - len = 1; buf[0] = '\033'; - break; - - case XK_Up: - len = 1; buf[0] = 'k'; - break; - case XK_Down: - len = 1; buf[0] = 'j'; - break; - - case XK_Left: - len = 1; buf[0] = 'b'; - break; - case XK_Right: - len = 1; buf[0] = ' '; - break; - - case XK_Page_Up: - len = 1; buf[0] = ','; - break; - case XK_Page_Down: - len = 1; buf[0] = '.'; - break; - } - if (xevt.xkey.state & ControlMask && keysym == XK_c) - docopy(&gapp, XA_CLIPBOARD); - else if (len) - onkey(buf[0]); - - onmouse(oldx, oldy, 0, 0, 0); - - break; - - case MotionNotify: - oldx = xevt.xmotion.x; - oldy = xevt.xmotion.y; - onmouse(xevt.xmotion.x, xevt.xmotion.y, 0, xevt.xmotion.state, 0); - break; - - case ButtonPress: - onmouse(xevt.xbutton.x, xevt.xbutton.y, xevt.xbutton.button, xevt.xbutton.state, 1); - break; - - case ButtonRelease: - copytime = xevt.xbutton.time; - onmouse(xevt.xbutton.x, xevt.xbutton.y, xevt.xbutton.button, xevt.xbutton.state, -1); - break; - - case SelectionRequest: - onselreq(xevt.xselectionrequest.requestor, - xevt.xselectionrequest.selection, - xevt.xselectionrequest.target, - xevt.xselectionrequest.property, - xevt.xselectionrequest.time); - break; - - case ClientMessage: - if (xevt.xclient.format == 32 && xevt.xclient.data.l[0] == WM_DELETE_WINDOW) - closing = 1; - break; - } - } - - if (closing) - continue; - - if (width != -1 || height != -1) - { - pdfapp_onresize(&gapp, width, height); - width = -1; - height = -1; - } - - if (dirty || dirtysearch) - { - if (dirty) - winblit(&gapp); - else if (dirtysearch) - winblitsearch(&gapp); - dirty = 0; - transition_dirty = 0; - dirtysearch = 0; - pdfapp_postblit(&gapp); - } - - if (showingpage && !tmo_at.tv_sec && !tmo_at.tv_usec) - { - tmo.tv_sec = 2; - tmo.tv_usec = 0; - - gettimeofday(&now, NULL); - timeradd(&now, &tmo, &tmo_at); - } - - if (XPending(xdpy) || transition_dirty) - continue; - - timeout = NULL; - - if (tmo_at.tv_sec || tmo_at.tv_usec) - { - gettimeofday(&now, NULL); - timersub(&tmo_at, &now, &tmo); - if (tmo.tv_sec <= 0) - { - tmo_at.tv_sec = 0; - tmo_at.tv_usec = 0; - timeout = NULL; - showingpage = 0; - winrepaint(&gapp); - } - else - timeout = &tmo; - } - - if (advance_scheduled) - { - gettimeofday(&now, NULL); - timersub(&tmo_advance, &now, &tmo_advance_delay); - if (tmo_advance_delay.tv_sec <= 0) - { - /* Too late already */ - onkey(' '); - onmouse(oldx, oldy, 0, 0, 0); - advance_scheduled = 0; - } - else if (timeout == NULL) - { - timeout = &tmo_advance_delay; - } - else - { - struct timeval tmp; - timersub(&tmo_advance_delay, timeout, &tmp); - if (tmp.tv_sec < 0) - { - timeout = &tmo_advance_delay; - } - } - } - - FD_SET(x11fd, &fds); - if (select(x11fd + 1, &fds, NULL, NULL, timeout) < 0) - { - if (reloading) - { - winreloadfile(&gapp); - reloading = 0; - } - } - if (!FD_ISSET(x11fd, &fds)) - { - if (timeout == &tmo_advance_delay) - { - onkey(' '); - onmouse(oldx, oldy, 0, 0, 0); - advance_scheduled = 0; - } - else - { - tmo_at.tv_sec = 0; - tmo_at.tv_usec = 0; - timeout = NULL; - showingpage = 0; - winrepaint(&gapp); - } - } - } - - cleanup(&gapp); - - return 0; -} |