예제 #1
0
파일: win_main.c 프로젝트: n1tehawk/mupdf
int WINAPI
WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
	int argc;
	LPWSTR *wargv = CommandLineToArgvW(GetCommandLineW(), &argc);
	char **argv;
	char argv0[256];
	MSG msg;
	int code;
	fz_context *ctx;
	int bps = 0;
	int displayRes = get_system_dpi();
	int c;
	char *layout_css = NULL;

	ctx = fz_new_context(NULL, NULL, FZ_STORE_DEFAULT);
	if (!ctx)
	{
		fprintf(stderr, "cannot initialise context\n");
		exit(1);
	}
	pdfapp_init(ctx, &gapp);

	argv = fz_argv_from_wargv(argc, wargv);

	while ((c = fz_getopt(argc, argv, "p:r:A:C:W:H:S:U:b:")) != -1)
	{
		switch (c)
		{
		case 'C':
			c = strtol(fz_optarg, NULL, 16);
			gapp.tint = 1;
			gapp.tint_r = (c >> 16) & 255;
			gapp.tint_g = (c >> 8) & 255;
			gapp.tint_b = (c) & 255;
			break;
		case 'p': password = fz_optarg; break;
		case 'r': displayRes = fz_atoi(fz_optarg); break;
		case 'A': fz_set_aa_level(ctx, fz_atoi(fz_optarg)); break;
		case 'W': gapp.layout_w = fz_atoi(fz_optarg); break;
		case 'H': gapp.layout_h = fz_atoi(fz_optarg); break;
		case 'S': gapp.layout_em = fz_atoi(fz_optarg); break;
		case 'b': bps = (fz_optarg && *fz_optarg) ? fz_atoi(fz_optarg) : 4096; break;
		case 'U': layout_css = fz_optarg; break;
		default: usage();
		}
	}

	pdfapp_setresolution(&gapp, displayRes);

	GetModuleFileNameA(NULL, argv0, sizeof argv0);
	install_app(argv0);

	winopen();

	if (fz_optind < argc)
	{
		strcpy(filename, argv[fz_optind]);
	}
	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");
	}

	if (layout_css)
	{
		fz_buffer *buf = fz_read_file(ctx, layout_css);
		fz_set_user_css(ctx, fz_string_from_buffer(ctx, buf));
		fz_drop_buffer(ctx, buf);
	}

	if (bps)
		pdfapp_open_progressive(&gapp, filename, 0, bps);
	else
		pdfapp_open(&gapp, filename, 0);

	while (GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

	fz_free_argv(argc, argv);

	do_close(&gapp);

	return 0;
}
예제 #2
0
int main(int argc, char **argv) {
	fz_document *doc = NULL;
	int c;
	fz_context *ctx;

	fz_var(doc);

	yctx = yutani_init();

	char * _width  = getenv("WIDTH");
	char * _height = getenv("HEIGHT");
	width  = _width  ? atoi(_width)  : 512;
	height = _height ? atoi(_height) : 512;

	init_decorations();

	window = yutani_window_create(yctx, width + decor_width(), height + decor_height());
	yutani_window_move(yctx, window, 50, 50);

	yutani_window_advertise_icon(yctx, window, "PDF Viewer", "pdfviewer");

	gfx_ctx = init_graphics_yutani(window);
	draw_fill(gfx_ctx,rgb(0,0,0));
	render_decorations(window, gfx_ctx, "PDFViewer - Loading...");

	while ((c = fz_getopt(argc, argv, "wf")) != -1) {
		switch (c) {
			case 'f':
				fit = 1;
				break;
		}
	}

	ctx = fz_new_context(NULL, NULL, FZ_STORE_DEFAULT);
	if (!ctx) {
		fprintf(stderr, "Could not initialize fitz context.\n");
		exit(1);
	}

	fz_set_aa_level(ctx, alphabits);
	colorspace = fz_device_rgb;

	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_throw(ctx, "cannot open document: %s", filename);
				}

				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++]);

				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;
	}

	fz_free_context(ctx);

	return (errored != 0);
}
예제 #3
0
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;
}
예제 #4
0
파일: x11_main.c 프로젝트: Asido/MuPDF
int main(int argc, char **argv)
{
	int c;
	int len;
	char buf[128];
	KeySym keysym;
	int oldx = 0;
	int oldy = 0;
	int resolution = 72;
	int pageno = 1;
	int pagemark = 0;
	int accelerate = 1;
	int fd;
	fd_set fds;
	int width = -1;
	int height = -1;

	while ((c = fz_getopt(argc, argv, "p:r:b:A")) != -1)
	{
		switch (c)
		{
		case 'p': password = fz_optarg; break;
		case 'r': resolution = atoi(fz_optarg); break;
		case 'A': accelerate = 0; break;
		case 'b': fz_set_aa_level(atoi(fz_optarg)); break;
		default: usage();
		}
	}

	if (resolution < MINRES)
		resolution = MINRES;
	if (resolution > MAXRES)
		resolution = MAXRES;

	if (argc - fz_optind == 0)
		usage();

	if (accelerate)
		fz_accelerate();

	filename = argv[fz_optind++];

	winopen();

	pdfapp_init(&gapp);
	gapp.scrw = DisplayWidth(xdpy, xscr);
	gapp.scrh = DisplayHeight(xdpy, xscr);
	gapp.resolution = resolution;

	if (argc - fz_optind > 1)
		pageno = atoi(argv[fz_optind++]);

	gapp.pageno = pageno;

	fd = open(filename, O_BINARY | O_RDONLY, 0666);
	if (fd < 0)
		winerror(&gapp, fz_throw("cannot open file '%s'", filename));

	pdfapp_open(&gapp, filename, fd, 0);

	if (pdfapp_calcfilehash(&gapp, fd))
	{
		pdfapp_getmarkfile(&gapp);
		pagemark = pdfapp_getpgmark(&gapp);
		if (pagemark > 0)
		{
			if (pagemark <= gapp.pagecount)
			{
				gapp.pageno = pagemark;
				pdfapp_showpage(&gapp, 1, 1, 1);
			}
			else
				pdfapp_closemarkfile(&gapp);
		}
	}

	FD_ZERO(&fds);
	FD_SET(x11fd, &fds);

	signal(SIGHUP, signal_handler);
	atexit(exit_cb);

	while (!closing)
	{
		do
		{
			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 (len)
					onkey(buf[0]);

				onmouse(oldx, oldy, 0, 0, 0);

				break;

			case MotionNotify:
				oldx = xevt.xbutton.x;
				oldy = xevt.xbutton.y;
				onmouse(xevt.xbutton.x, xevt.xbutton.y, xevt.xbutton.button, xevt.xbutton.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;
			}
		}
		while (!closing && XPending(xdpy));

		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;
			dirtysearch = 0;
		}

		if (XPending(xdpy))
			continue;

		if (select(x11fd + 1, &fds, NULL, NULL, NULL) < 0)
		{
			if (reloading)
			{
				winreloadfile(&gapp);
				reloading = 0;
			}
		}
	}

	pdfapp_close(&gapp);

	XDestroyWindow(xdpy, xwin);

	XFreePixmap(xdpy, xicon);

	XFreeCursor(xdpy, xcwait);
	XFreeCursor(xdpy, xchand);
	XFreeCursor(xdpy, xcarrow);

	XFreeGC(xdpy, xgc);

	XCloseDisplay(xdpy);

	return 0;
}
예제 #5
0
int bmpmupdf_pdffile_to_bmp(WILLUSBITMAP *bmp,char *filename,int pageno,double dpi,
                            int bpp)

    {
    fz_context *ctx;
    fz_colorspace *colorspace;
    fz_document *doc;
    fz_page *page;
    fz_display_list *list;
    fz_device *dev;
    fz_pixmap *pix;
    double dpp;
    fz_rect bounds,bounds2;
    fz_matrix ctm;
    fz_irect bbox;
//    fz_glyph_cache *glyphcache;
//    fz_error error;
    int np,status;

    dev=NULL;
    list=NULL;
    page=NULL;
    doc=NULL;
    status=0;
    if (pageno<1)
        return(-99);
    ctx = fz_new_context(NULL,NULL,FZ_STORE_DEFAULT);
    if (!ctx)
        return(-1);
    fz_try(ctx)
    {
    fz_register_document_handlers(ctx);
    fz_set_aa_level(ctx,8);
    /* Sumatra version of MuPDF v1.4 -- use locally installed fonts */
    pdf_install_load_system_font_funcs(ctx);
//    fz_accelerate();
//    glyphcache=fz_new_glyph_cache();
    colorspace=(bpp==8 ? fz_device_gray(ctx) : fz_device_rgb(ctx));
    fz_try(ctx) { doc=fz_open_document(ctx,filename); }
    fz_catch(ctx) 
        { 
        fz_free_context(ctx);
        return(-1);
        }
    /*
    if (fz_needs_password(doc) && !fz_authenticate_password(doc,password))
        return(-2);
    */
//    error=pdf_load_page_tree(xref);
//    if (error)
//        {
//        pdf_free_xref(xref);
//        return(-2);
//        }

    np=fz_count_pages(doc);
    if (pageno>np)
        return(-99);
    fz_try(ctx) { page = fz_load_page(doc,pageno-1); }
    fz_catch(ctx) 
        {
        fz_close_document(doc);
        fz_free_context(ctx);
        return(-3);
        }
    fz_try(ctx) { list=fz_new_display_list(ctx);
                  dev=fz_new_list_device(ctx,list);
                  fz_run_page(doc,page,dev,&fz_identity,NULL);
                }
    fz_catch(ctx)
        {
        fz_free_device(dev);
        fz_drop_display_list(ctx,list);
        fz_free_page(doc,page);
        fz_close_document(doc);
        fz_free_context(ctx);
        return(-4);
        }
    fz_free_device(dev);
    dev=NULL;
    dpp=dpi/72.;
    pix=NULL;
    fz_var(pix);
    fz_bound_page(doc,page,&bounds);
    ctm=fz_identity;
    fz_scale(&ctm,dpp,dpp);
//    ctm=fz_concat(ctm,fz_rotate(rotation));
    bounds2=bounds;
    fz_transform_rect(&bounds2,&ctm);
    fz_round_rect(&bbox,&bounds2);
//    ctm=fz_translate(0,-page->mediabox.y1);
//    ctm=fz_concat(ctm,fz_scale(dpp,-dpp));
//    ctm=fz_concat(ctm,fz_rotate(page->rotate));
//    ctm=fz_concat(ctm,fz_rotate(0));
//    bbox=fz_round_rect(fz_transform_rect(ctm,page->mediabox));
//    pix=fz_new_pixmap_with_rect(colorspace,bbox);
    fz_try(ctx)
        {
        pix=fz_new_pixmap_with_bbox(ctx,colorspace,&bbox);
        fz_clear_pixmap_with_value(ctx,pix,255);
        dev=fz_new_draw_device(ctx,pix);
        if (list)
            fz_run_display_list(list,dev,&ctm,&bounds2,NULL);
        else
            fz_run_page(doc,page,dev,&ctm,NULL);
        fz_free_device(dev);
        dev=NULL;
        status=bmpmupdf_pixmap_to_bmp(bmp,ctx,pix);
        fz_drop_pixmap(ctx,pix);
        }
    fz_catch(ctx)
        {
        fz_free_device(dev);
        fz_drop_pixmap(ctx,pix);
        fz_drop_display_list(ctx,list);
        fz_free_page(doc,page);
        fz_close_document(doc);
        fz_free_context(ctx);
        return(-5);
        }
    if (list)
        fz_drop_display_list(ctx,list);
    fz_free_page(doc,page);
//    pdf_free_xref(xref);
    fz_close_document(doc);
    fz_flush_warnings(ctx);
    } /* fz_catch before registering handlers */
    fz_catch(ctx) /* Error registering */
    {
    status = -10;
    }
    fz_free_context(ctx);
//    fz_free_glyph_cache(glyphcache);
//    fz_flush_warnings();
    if (status<0)
        return(status-10);
    return(0);
    }
예제 #6
0
/*
** Returns 0 if got dimensions.
*/
int bmpmupdf_pdffile_width_and_height(char *filename,int pageno,double *width_in,double *height_in)

    {
    fz_context *ctx;
    fz_document *doc;
    fz_page *page;
    fz_display_list *list;
    fz_device *dev;
    fz_rect bounds;
    int np;

    dev=NULL;
    list=NULL;
    page=NULL;
    doc=NULL;
    if (pageno<1)
        return(-99);
    ctx = fz_new_context(NULL,NULL,FZ_STORE_DEFAULT);
    if (!ctx)
        return(-1);
    fz_try(ctx)
    {
    fz_register_document_handlers(ctx);
    fz_set_aa_level(ctx,8);
    /* Sumatra version of MuPDF v1.4 -- use locally installed fonts */
    pdf_install_load_system_font_funcs(ctx);
    fz_try(ctx) { doc=fz_open_document(ctx,filename); }
    fz_catch(ctx) 
        { 
        fz_free_context(ctx);
        return(-1);
        }
    np=fz_count_pages(doc);
    if (pageno>np)
        return(-99);
    fz_try(ctx) { page = fz_load_page(doc,pageno-1); }
    fz_catch(ctx) 
        {
        fz_close_document(doc);
        fz_free_context(ctx);
        return(-3);
        }
    fz_try(ctx) { list=fz_new_display_list(ctx);
                  dev=fz_new_list_device(ctx,list);
                  fz_run_page(doc,page,dev,&fz_identity,NULL);
                }
    fz_catch(ctx)
        {
        fz_free_device(dev);
        fz_drop_display_list(ctx,list);
        fz_free_page(doc,page);
        fz_close_document(doc);
        fz_free_context(ctx);
        return(-4);
        }
    fz_free_device(dev);
    dev=NULL;
    fz_bound_page(doc,page,&bounds);
    if (width_in!=NULL)
        (*width_in)=fabs(bounds.x1-bounds.x0)/72.;
    if (height_in!=NULL)
        (*height_in)=fabs(bounds.y1-bounds.y0)/72.;
    fz_drop_display_list(ctx,list);
    fz_free_page(doc,page);
    fz_close_document(doc);
    } 
    fz_catch(ctx) /* Error registering */
    {
    fz_free_context(ctx);
    return(-20);
    }
    fz_free_context(ctx);
    return(0);
    }
예제 #7
0
파일: muconvert.c 프로젝트: Enzime/mupdf
int muconvert_main(int argc, char **argv)
{
	int i, c;

	while ((c = fz_getopt(argc, argv, "p:A:W:H:S:U:o:F:O:")) != -1)
	{
		switch (c)
		{
		default: usage(); break;

		case 'p': password = fz_optarg; break;
		case 'A': alphabits = atoi(fz_optarg); break;
		case 'W': layout_w = atof(fz_optarg); break;
		case 'H': layout_h = atof(fz_optarg); break;
		case 'S': layout_em = atof(fz_optarg); break;
		case 'U': layout_css = fz_optarg; break;

		case 'o': output = fz_optarg; break;
		case 'F': format = fz_optarg; break;
		case 'O': options = fz_optarg; break;
		}
	}

	if (fz_optind == argc || (!format && !output))
		usage();

	/* Create a context to hold the exception stack and various caches. */
	ctx = fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED);
	if (!ctx)
	{
		fprintf(stderr, "cannot create mupdf context\n");
		return EXIT_FAILURE;
	}

	/* Register the default file types to handle. */
	fz_try(ctx)
		fz_register_document_handlers(ctx);
	fz_catch(ctx)
	{
		fprintf(stderr, "cannot register document handlers: %s\n", fz_caught_message(ctx));
		fz_drop_context(ctx);
		return EXIT_FAILURE;
	}

	fz_set_aa_level(ctx, alphabits);

	if (layout_css)
	{
		fz_buffer *buf = fz_read_file(ctx, layout_css);
		fz_write_buffer_byte(ctx, buf, 0);
		fz_set_user_css(ctx, (char*)buf->data);
		fz_drop_buffer(ctx, buf);
	}

	/* Open the output document. */
	fz_try(ctx)
		out = fz_new_document_writer(ctx, output, format, options);
	fz_catch(ctx)
	{
		fprintf(stderr, "cannot create document: %s\n", fz_caught_message(ctx));
		fz_drop_context(ctx);
		return EXIT_FAILURE;
	}

	for (i = fz_optind; i < argc; ++i)
	{
		doc = fz_open_document(ctx, argv[i]);
		if (fz_needs_password(ctx, doc))
			if (!fz_authenticate_password(ctx, doc, password))
				fz_throw(ctx, FZ_ERROR_GENERIC, "cannot authenticate password: %s", argv[i]);
		fz_layout_document(ctx, doc, layout_w, layout_h, layout_em);
		count = fz_count_pages(ctx, doc);

		if (i+1 < argc && fz_is_page_range(ctx, argv[i+1]))
			runrange(argv[++i]);
		else
			runrange("1-N");

		fz_drop_document(ctx, doc);
	}

	fz_drop_document_writer(ctx, out);
	fz_drop_context(ctx);
	return EXIT_SUCCESS;
}