summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor@ghostscript.com>2005-01-08 19:14:58 +0100
committerTor Andersson <tor@ghostscript.com>2005-01-08 19:14:58 +0100
commit67501e91744a55653c985b088d008d7a54cea1e8 (patch)
treea92e8d02027ea6b847f075fa2d694dfd6a3053cd
parentc76a3d84a81c59f880ecac26bf4935e1bb76afc1 (diff)
downloadmupdf-67501e91744a55653c985b088d008d7a54cea1e8.tar.xz
ported x11pdf to win32
-rw-r--r--Jamfile12
-rw-r--r--TODO1
-rw-r--r--filter/filer.c12
-rw-r--r--mupdf/shade1.c5
-rw-r--r--render/glyphcache.c8
-rw-r--r--render/pixmap.c6
-rw-r--r--test/w32pdf.c656
7 files changed, 683 insertions, 17 deletions
diff --git a/Jamfile b/Jamfile
index 0c112fff..54821b57 100644
--- a/Jamfile
+++ b/Jamfile
@@ -201,7 +201,8 @@ LINKLIBS =
-lm
;
-LINKLIBS on x11pdf = -lX11 -lXext $(LINKLIBS) ;
+LINKLIBS on x11pdf$(SUFEXE) = -lX11 -lXext $(LINKLIBS) ;
+LINKLIBS on w32pdf$(SUFEXE) = -lgdi32 $(LINKLIBS) ;
Main pdfclean : test/pdfclean.c ;
Main pdfdebug : test/pdfdebug.c ;
@@ -209,18 +210,14 @@ Main pdfdebug : test/pdfdebug.c ;
Main pdfrip : test/pdfrip.c ;
# Main pdffunction : test/pdffunction.c ;
-# Main x11pdf : test/x11pdf.c test/ximage.c ;
-
-Main carbonpdf : macpdf/carbonpdf.c macpdf/view.c ;
-File macpdf/carbonpdf.app/Contents/MacOS/carbonpdf : carbonpdf ;
-MODE on macpdf/carbonpdf.app/Contents/MacOS/carbonpdf = 755 ;
+Main x11pdf : test/x11pdf.c test/ximage.c ;
CCFLAGS += `pkg-config --cflags gtk+ gthread` ;
LINKLIBS on gtkpdf = $(LINKLIBS) `pkg-config --libs gtk+ gmodule gthread` ;
LINKLIBS on carbonpdf = $(LINKLIBS) -framework Carbon ;
-# Main gtkpdf : test/gtkpdf.c ;
+Main gtkpdf : test/gtkpdf.c ;
LinkLibraries
pdfclean
@@ -229,7 +226,6 @@ LinkLibraries
pdfrip
pdffunction
x11pdf
- carbonpdf
gtkpdf
: libmupdf libfonts libfitz ;
diff --git a/TODO b/TODO
index 2fbfd259..5b52caaf 100644
--- a/TODO
+++ b/TODO
@@ -5,6 +5,7 @@ immediate plan:
* write mupdf hackers guide
* clean up and 'freeze' public api
+ * get font bbox from fontdescriptor if available
* refactor image loading
* refactor xref loading/repair
* restructure build.c and interpret.c (ftb vs csi)
diff --git a/filter/filer.c b/filter/filer.c
index 92237778..a63a7dd2 100644
--- a/filter/filer.c
+++ b/filter/filer.c
@@ -219,12 +219,16 @@ fz_readfile(fz_buffer **bufp, fz_file *file)
if (n < CHUNKSIZE)
{
- newbuf = fz_realloc(buf, pos);
- if (!newbuf)
+ if (pos > 0)
{
- fz_free(buf);
- return fz_outofmem;
+ newbuf = fz_realloc(buf, pos);
+ if (!newbuf)
+ {
+ fz_free(buf);
+ return fz_outofmem;
+ }
}
+ else newbuf = buf;
real = *bufp = fz_malloc(sizeof(fz_buffer));
if (!real)
diff --git a/mupdf/shade1.c b/mupdf/shade1.c
index ed81821a..f25616bd 100644
--- a/mupdf/shade1.c
+++ b/mupdf/shade1.c
@@ -74,18 +74,19 @@ pdf_loadtype1shade(fz_shade *shade, pdf_xref *xref, fz_obj *dict, fz_obj *ref)
#define ADD_VERTEX(xx, yy) \
{\
fz_point p;\
+ float cp[2], cv[FZ_MAXCOLORS];\
+ int c;\
p.x = xx;\
p.y = yy;\
p = fz_transformpoint(matrix, p);\
shade->mesh[n++] = p.x;\
shade->mesh[n++] = p.y;\
\
- float cp[2], cv[FZ_MAXCOLORS];\
cp[0] = xx;\
cp[1] = yy;\
error = pdf_evalfunction(func, cp, 2, cv, shade->cs->n);\
\
- for (int c = 0; c < shade->cs->n; ++c) {\
+ for (c = 0; c < shade->cs->n; ++c) {\
shade->mesh[n++] = cv[c];\
}\
}\
diff --git a/render/glyphcache.c b/render/glyphcache.c
index 9fd4a5a7..6fc8bd52 100644
--- a/render/glyphcache.c
+++ b/render/glyphcache.c
@@ -114,6 +114,9 @@ static int hdist = 0;
static int coos = 0;
static int covf = 0;
+static int ghits = 0;
+static int gmisses = 0;
+
static fz_val *
hashfind(fz_glyphcache *arena, fz_key *key)
{
@@ -218,6 +221,7 @@ fz_debugglyphcache(fz_glyphcache *arena)
printf("avg dist: %d / %d: %g\n", hdist, hcoll, (double)hdist / hcoll);
printf("out-of-space evicts: %d\n", coos);
printf("out-of-hash evicts: %d\n", covf);
+ printf("hits = %d misses = %d ratio = %g\n", ghits, gmisses, (float)ghits / (ghits + gmisses));
/*
int i;
for (i = 0; i < arena->slots; i++)
@@ -333,9 +337,13 @@ fz_renderglyph(fz_glyphcache *arena, fz_glyph *glyph, fz_font *font, int cid, fz
bubble(arena, val - arena->lru);
+ ghits++;
+
return nil;
}
+ gmisses++;
+
ctm.e = fz_floor(ctm.e) + key.e / 256.0;
ctm.f = fz_floor(ctm.f) + key.f / 256.0;
diff --git a/render/pixmap.c b/render/pixmap.c
index c024a025..4e6823d9 100644
--- a/render/pixmap.c
+++ b/render/pixmap.c
@@ -76,8 +76,8 @@ fz_debugpixmap(fz_pixmap *pix)
if (pix->n == 4)
{
int x, y;
- FILE *ppm = fopen("out.ppm", "w");
- FILE *pgm = fopen("out.pgm", "w");
+ FILE *ppm = fopen("out.ppm", "wb");
+ FILE *pgm = fopen("out.pgm", "wb");
fprintf(ppm, "P6\n%d %d\n255\n", pix->w, pix->h);
fprintf(pgm, "P5\n%d %d\n255\n", pix->w, pix->h);
@@ -100,7 +100,7 @@ fz_debugpixmap(fz_pixmap *pix)
else if (pix->n == 2)
{
int x, y;
- FILE *pgm = fopen("out.pgm", "w");
+ FILE *pgm = fopen("out.pgm", "wb");
fprintf(pgm, "P5\n%d %d\n255\n", pix->w, pix->h);
for (y = 0; y < pix->h; y++)
diff --git a/test/w32pdf.c b/test/w32pdf.c
new file mode 100644
index 00000000..33fb589c
--- /dev/null
+++ b/test/w32pdf.c
@@ -0,0 +1,656 @@
+#include <fitz.h>
+#include <mupdf.h>
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+static HWND hwnd;
+static HDC hdc;
+static BITMAPINFO *dibinf;
+static TCHAR szAppName[] = TEXT("mupdf");
+static HCURSOR arrowcurs, handcurs, waitcurs;
+static LRESULT CALLBACK winproc(HWND, UINT, WPARAM, LPARAM);
+
+static char *doctitle = "<untitled>";
+static float zoom = 1.0;
+static int rotate = 0;
+static int pageno = 1;
+static int count = 0;
+
+static pdf_page *page = nil;
+static fz_obj *pageobj = nil;
+
+static int hist[256];
+static int histlen = 0;
+
+/* for 123G commands */
+static unsigned char pagebuf[256];
+static int pagebufidx = 0;
+
+static pdf_xref *xref;
+static pdf_pagetree *pages;
+static pdf_outline *outline;
+static fz_renderer *rast;
+static fz_pixmap *image;
+
+void usage()
+{
+ fprintf(stderr, "usage: w32pdf [-b] [-pzr page/zoom/rotate] [-u password] file.pdf\n");
+ exit(1);
+}
+
+void winabort(const char *msg)
+{
+ MessageBoxA(NULL, msg, "Fatal error", MB_ICONERROR);
+ abort();
+}
+
+void winopen()
+{
+ WNDCLASS wc;
+
+ /* Create and register window class */
+ wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
+ wc.lpfnWndProc = winproc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = 0; //hInstance;
+ wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
+ wc.hCursor = NULL; //LoadCursor(NULL, IDC_ARROW);
+ wc.hbrBackground = NULL;//(HBRUSH) GetStockObject(BLACK_BRUSH);
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = szAppName;
+ assert(RegisterClass(&wc) && "Register window class");
+
+ /* Create cursors */
+ arrowcurs = LoadCursor(NULL, IDC_ARROW);
+ handcurs = LoadCursor(NULL, IDC_HAND);
+ waitcurs = LoadCursor(NULL, IDC_WAIT);
+
+ /* Init DIB info for buffer */
+ dibinf = malloc(sizeof(BITMAPINFO) + 12);
+ assert(dibinf != NULL);
+ dibinf->bmiHeader.biSize = sizeof(dibinf->bmiHeader);
+ dibinf->bmiHeader.biPlanes = 1;
+ dibinf->bmiHeader.biBitCount = 24;
+ 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 */
+ hwnd = CreateWindow(szAppName, // window class name
+ NULL, // window caption
+ //WS_OVERLAPPEDWINDOW, // window style
+ WS_CAPTION|WS_THICKFRAME|WS_SYSMENU|WS_MINIMIZEBOX,
+ CW_USEDEFAULT, // initial x position
+ 5, // CW_USEDEFAULT, // initial y position
+ 300, // initial x size
+ 300, // initial y size
+ NULL, // parent window handle
+ NULL, // window menu handle
+ 0,//hInstance, // program instance handle
+ NULL); // creation parameters
+
+ hdc = NULL;
+
+ SetWindowTextA(hwnd, "MuPDF");
+
+ SetCursor(arrowcurs);
+}
+
+void winblit()
+{
+ /* TODO: repack image in windows format */
+ int stride = ((image->w * 3 + 3) / 4) * 4;
+ char *buf;
+ char *s;
+ char *p;
+ int y, x;
+
+ buf = fz_malloc(image->h * stride);
+ if (!buf)
+ return;
+
+ for (y = 0; y < image->h; y++)
+ {
+ p = buf + y * stride;
+ s = image->samples + y * image->w * 4;
+ for (x = 0; x < image->w; x++)
+ {
+ p[x * 3 + 0] = s[x * 4 + 3];
+ p[x * 3 + 1] = s[x * 4 + 2];
+ p[x * 3 + 2] = s[x * 4 + 1];
+ }
+ }
+
+ dibinf->bmiHeader.biWidth = image->w;
+ dibinf->bmiHeader.biHeight = -image->h;
+ dibinf->bmiHeader.biSizeImage = image->h * stride;
+
+ assert(hdc != NULL);
+ SetDIBitsToDevice(hdc,
+ 0, /* destx */
+ 0, /* desty */
+ image->w, /* destw */
+ image->h, /* desth */
+ 0, /* srcx */
+ 0, /* srcy */
+ 0, /* startscan */
+ image->h, /* numscans */
+ buf, /* pBits */
+ dibinf, /* pInfo */
+ DIB_RGB_COLORS /* color use flag */
+ );
+
+ fz_free(buf);
+}
+
+void winresize(int w, int h)
+{
+ ShowWindow(hwnd, SW_SHOWDEFAULT);
+ w += GetSystemMetrics(SM_CXFRAME) * 2;
+ h += GetSystemMetrics(SM_CYFRAME) * 2;
+ h += GetSystemMetrics(SM_CYCAPTION);
+ SetWindowPos(hwnd, 0, 0, 0, w, h, SWP_NOZORDER | SWP_NOMOVE);
+}
+
+void winrepaint(void)
+{
+ RECT wr = (RECT){0, 0, image->w, image->h};
+ InvalidateRect(hwnd, &wr, 0);
+}
+
+void dragndrop()
+{
+ SetCapture(hwnd);
+ ReleaseCapture();
+}
+
+static void showpage(void)
+{
+ fz_error *error;
+ fz_matrix ctm;
+ fz_rect bbox;
+ fz_obj *obj;
+
+ assert(pageno > 0 && pageno <= pdf_getpagecount(pages));
+
+ SetCursor(waitcurs);
+
+ if (image)
+ fz_droppixmap(image);
+ image = nil;
+
+ obj = pdf_getpageobject(pages, pageno - 1);
+ if (obj == pageobj)
+ goto Lskipload;
+ pageobj = obj;
+
+ if (page)
+ pdf_droppage(page);
+
+ error = pdf_loadpage(&page, xref, pageobj);
+ if (error)
+ fz_abort(error);
+
+Lskipload:
+
+ ctm = fz_identity();
+ ctm = fz_concat(ctm, fz_translate(0, -page->mediabox.max.y));
+ ctm = fz_concat(ctm, fz_scale(zoom, -zoom));
+ ctm = fz_concat(ctm, fz_rotate(rotate + page->rotate));
+
+ bbox = fz_transformaabb(ctm, page->mediabox);
+
+ error = fz_rendertree(&image, rast, page->tree, ctm, fz_roundrect(bbox), 1);
+ if (error)
+ fz_abort(error);
+
+ SetCursor(arrowcurs);
+ {
+ char buf[512];
+ sprintf(buf, "%s - %d/%d", doctitle, pageno, count);
+ SetWindowTextA(hwnd, buf);
+ }
+
+ winresize(image->w, image->h);
+ winrepaint();
+}
+
+static void pdfopen(char *filename, char *password)
+{
+ fz_error *error;
+ fz_obj *obj;
+
+ error = pdf_newxref(&xref);
+ if (error)
+ fz_abort(error);
+
+ error = pdf_loadxref(xref, filename);
+ if (error)
+ {
+ fz_warn(error->msg);
+ printf("trying to repair...\n");
+ error = pdf_repairxref(xref, filename);
+ if (error)
+ fz_abort(error);
+ }
+
+ error = pdf_decryptxref(xref);
+ if (error)
+ fz_abort(error);
+
+ if (xref->crypt)
+ {
+ error = pdf_setpassword(xref->crypt, password);
+ if (error) fz_abort(error);
+ }
+
+ obj = fz_dictgets(xref->trailer, "Root");
+ if (!obj)
+ fz_abort(fz_throw("syntaxerror: missing Root object"));
+ error = pdf_loadindirect(&xref->root, xref, obj);
+ if (error) fz_abort(error);
+
+ obj = fz_dictgets(xref->trailer, "Info");
+ if (obj)
+ {
+ error = pdf_loadindirect(&xref->info, xref, obj);
+ if (error) fz_abort(error);
+ }
+
+ error = pdf_loadnametrees(xref);
+ if (error) fz_abort(error);
+
+ error = pdf_loadoutline(&outline, xref);
+ if (error) fz_abort(error);
+
+ doctitle = filename;
+ if (xref->info)
+ {
+ obj = fz_dictgets(xref->info, "Title");
+ if (obj)
+ {
+ error = pdf_toutf8(&doctitle, obj);
+ if (error) fz_abort(error);
+ }
+ }
+
+// if (outline)
+// pdf_debugoutline(outline, 0);
+
+ error = pdf_loadpagetree(&pages, xref);
+ if (error) fz_abort(error);
+
+ count = pdf_getpagecount(pages);
+
+ error = fz_newrenderer(&rast, pdf_devicergb, 0, 1024 * 512);
+ if (error) fz_abort(error);
+
+ image = nil;
+}
+
+static void gotouri(fz_obj *uri)
+{
+ char cmd[2048];
+ char buf[2048];
+
+ printf("goto uri: ");
+ fz_debugobj(uri);
+ printf("\n");
+
+ memcpy(buf, fz_tostrbuf(uri), fz_tostrlen(uri));
+ buf[fz_tostrlen(uri)] = 0;
+
+ if (getenv("BROWSER"))
+ sprintf(cmd, "$BROWSER %s &", buf);
+ else
+ sprintf(cmd, "start %s", buf);
+ system(cmd);
+}
+
+static void gotopage(fz_obj *obj)
+{
+ int oid = fz_tonum(obj);
+ int gen = fz_togen(obj);
+ int i;
+
+ printf("goto page: %d %d R\n", oid, gen);
+
+ for (i = 0; i < count; i++)
+ {
+ if (fz_tonum(pages->pref[i]) == oid)
+ {
+ if (histlen + 1 == 256)
+ {
+ memmove(hist, hist + 1, sizeof(int) * 255);
+ histlen --;
+ }
+ hist[histlen++] = pageno;
+ pageno = i + 1;
+ showpage();
+ return;
+ }
+ }
+}
+
+static void handlekey(int c)
+{
+ int oldpage = pageno;
+ float oldzoom = zoom;
+ int oldrotate = rotate;
+
+ if (c >= '0' && c <= '9')
+ pagebuf[pagebufidx++] = c;
+ else
+ if (c != 'g' && c != 'G')
+ pagebufidx = 0;
+
+ switch (c)
+ {
+ case 'd': fz_debugglyphcache(rast->cache); break;
+ case 'a': rotate -= 5; break;
+ case 's': rotate += 5; break;
+// case 'x': dumptext(); break;
+// case 'o': drawlinks(); break;
+
+ case '\b':
+ case 'b':
+ pageno--;
+ if (pageno < 1)
+ pageno = 1;
+ break;
+ case 'B':
+ pageno -= 10;
+ if (pageno < 1)
+ pageno = 1;
+ break;
+ case ' ':
+ case 'f':
+ pageno++;
+ if (pageno > count)
+ pageno = count;
+ break;
+ case 'F':
+ pageno += 10;
+ if (pageno > count)
+ pageno = count;
+ break;
+ case 'm':
+ if (histlen + 1 == 256)
+ {
+ memmove(hist, hist + 1, sizeof(int) * 255);
+ histlen --;
+ }
+ hist[histlen++] = pageno;
+ break;
+ case 't':
+ case 'T':
+ if (histlen > 0)
+ pageno = hist[--histlen];
+ break;
+ case '-':
+ zoom -= 0.1;
+ if (zoom < 0.1)
+ zoom = 0.1;
+ break;
+ case '+':
+ zoom += 0.1;
+ if (zoom > 3.0)
+ zoom = 3.0;
+ break;
+ case '<':
+ rotate -= 90;
+ break;
+ case '>':
+ rotate += 90;
+ break;
+ case 'q':
+ exit(0);
+ case 'g':
+ case 'G':
+ if (pagebufidx > 0)
+ {
+ pagebuf[pagebufidx] = '\0';
+ pageno = atoi(pagebuf);
+ pagebufidx = 0;
+ if (pageno < 1)
+ pageno = 1;
+ if (pageno > count)
+ pageno = count;
+ }
+ else
+ {
+ if (c == 'G')
+ {
+ pageno = count;
+ }
+ }
+ break;
+ }
+
+ if (pageno != oldpage || zoom != oldzoom || rotate != oldrotate)
+ showpage();
+}
+
+static void handlemouse(int x, int y, int btn)
+{
+ pdf_link *link;
+ fz_matrix ctm;
+ fz_point p;
+
+ p.x = x + image->x;
+ p.y = y + image->y;
+
+ ctm = fz_identity();
+ ctm = fz_concat(ctm, fz_translate(0, -page->mediabox.max.y));
+ ctm = fz_concat(ctm, fz_scale(zoom, -zoom));
+ ctm = fz_concat(ctm, fz_rotate(rotate + page->rotate));
+ ctm = fz_invertmatrix(ctm);
+
+ p = fz_transformpoint(ctm, p);
+
+ for (link = page->links; link; link = link->next)
+ {
+ if (p.x >= link->rect.min.x && p.x <= link->rect.max.x)
+ if (p.y >= link->rect.min.y && p.y <= link->rect.max.y)
+ break;
+ }
+
+ if (link)
+ {
+ SetCursor(handcurs);
+ if (btn)
+ {
+ if (fz_isstring(link->dest))
+ gotouri(link->dest);
+ if (fz_isindirect(link->dest))
+ gotopage(link->dest);
+ }
+ }
+ else
+ {
+ SetCursor(arrowcurs);
+ }
+}
+
+LRESULT CALLBACK
+winproc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ int x = (signed short) LOWORD(lParam);
+ int y = (signed short) HIWORD(lParam);
+ int key;
+
+ switch (message)
+ {
+ case WM_CREATE:
+ //puts("WM_CREATE");
+ return 0;
+
+ case WM_DESTROY:
+ //puts("WM_DESTROY");
+ PostQuitMessage(0);
+ return 0;
+
+ case WM_CLOSE:
+ //puts("WM_CLOSE");
+ PostQuitMessage(0);
+ return 0;
+
+ case WM_KILLFOCUS:
+ //puts("WM_KILLFOCUS");
+ return 0;
+
+ case WM_SIZING:
+ //puts("WM_SIZING");
+ return 0;
+
+ /* 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);
+ return 0;
+ }
+
+ /* Mouse events */
+
+ case WM_LBUTTONDOWN:
+ //puts("WM_LBUTTONDOWN");
+ handlemouse(x, y, 1);
+ return 0;
+ case WM_RBUTTONDOWN:
+ //puts("WM_RBUTTONDOWN");
+ handlemouse(x, y, 4);
+ return 0;
+ case WM_MBUTTONDOWN:
+ //puts("WM_MBUTTONDOWN");
+ handlemouse(x, y, 2);
+ return 0;
+
+ case WM_LBUTTONUP:
+ //puts("WM_LBUTTONUP");
+ handlemouse(x, y, 0);
+ return 0;
+ case WM_RBUTTONUP:
+ //puts("WM_RBUTTONUP");
+ handlemouse(x, y, 0);
+ return 0;
+ case WM_MBUTTONUP:
+ //puts("WM_RBUTTONUP");
+ handlemouse(x, y, 0);
+ return 0;
+
+ case WM_MOUSEMOVE:
+ //puts("WM_MOUSEMOVE");
+ handlemouse(x, y, 0);
+ return 0;
+
+ /* Mouse wheel */
+ case WM_MOUSEWHEEL:
+ if ((signed short)HIWORD(wParam) > 0) {
+ // wheel-up
+ }
+ else {
+ // wheel-down
+ }
+ return 0;
+
+ /* Keyboard events */
+
+ /* Only deal with key-down */
+ case WM_KEYUP:
+ return 0;
+ case WM_SYSKEYUP:
+ return 0;
+
+ case WM_SYSCHAR:
+ //printf("WM_SYSCHAR: %d '%c'\n", wParam, wParam);
+ return 0;
+
+ case WM_SYSKEYDOWN:
+ //printf("WM_SYSKEYDOWN: %d '%c'\n", wParam, wParam);
+ return 0;
+
+ case WM_KEYDOWN:
+ //printf("WM_KEYDOWN: %d '%c'\n", wParam, wParam);
+ return 0;
+
+ /* unicode encoded chars, including escape, backspace etc... */
+ case WM_CHAR:
+ //printf("WM_CHAR: %d '%c'\n", wParam, wParam);
+ key = wParam;
+ handlekey(key);
+ return 0;
+ }
+
+ fflush(stdout);
+
+ /* Pass on unhandled events to Windows */
+ return DefWindowProc(hwnd, message, wParam, lParam);
+}
+
+int main(int argc, char **argv)
+{
+ char *filename;
+ int c;
+
+ int benchmark = 0;
+ char *password = "";
+
+ while ((c = getopt(argc, argv, "bz:r:p:u:")) != -1)
+ {
+ switch (c)
+ {
+ case 'b': ++benchmark; break;
+ case 'u': password = optarg; break;
+ case 'p': pageno = atoi(optarg); break;
+ case 'z': zoom = atof(optarg); break;
+ case 'r': rotate = atoi(optarg); break;
+ default: usage();
+ }
+ }
+
+ if (argc - optind == 0)
+ usage();
+
+ fz_cpudetect();
+ fz_accelerate();
+
+ filename = argv[optind++];
+
+ winopen();
+ pdfopen(filename, password);
+ showpage();
+
+ if (benchmark)
+ {
+ while (pageno < count)
+ {
+ pageno ++;
+ showpage();
+ }
+ return 0;
+ }
+
+ MSG msg;
+ while (GetMessage(&msg, NULL, 0, 0))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+
+ pdf_closexref(xref);
+
+ return 0;
+}
+